Solves STR #2939; adding when() support to Fl_Tabs.
Also added a general Fl_Tabs code example to the docs. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@9867 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
parent
d5404dea25
commit
6bcd9390f8
43
FL/Fl_Tabs.H
43
FL/Fl_Tabs.H
@ -49,6 +49,49 @@
|
||||
gap is larger. It is easiest to lay this out in fluid, using the
|
||||
fluid browser to select each child group and resize them until
|
||||
the tabs look the way you want them to.
|
||||
|
||||
Typical use:
|
||||
\code
|
||||
Fl_Tabs *tabs = new Fl_Tabs(10,10,300,200);
|
||||
{
|
||||
Fl_Group *tab1 = new Fl_Group(20,30,280,170,"Tab1");
|
||||
{
|
||||
..widgets that go in tab#1..
|
||||
}
|
||||
tab1->end();
|
||||
Fl_Group *tab2 = new Fl_Group(20,30,280,170,"Tab2");
|
||||
{
|
||||
..widgets that go in tab#2..
|
||||
}
|
||||
tab2->end();
|
||||
}
|
||||
tabs->end();
|
||||
\endcode
|
||||
|
||||
In the above, tab1's tab can be made red by using tab1->selection_color(FL_RED);
|
||||
and tab1's text can be made bold by tab1->labelfont(FL_HELVETICA_BOLD),
|
||||
and can be made 'engraved' by tab1->labeltype(FL_ENGRAVED_LABEL);
|
||||
|
||||
As of FLTK 1.3.3, Fl_Tabs() supports the following flags for when():
|
||||
|
||||
- \ref FL_WHEN_NEVER -- callback never invoked (all flags off)
|
||||
- \ref FL_WHEN_CHANGED -- if flag set, invokes callback when a tab has been changed (on click or keyboard navigation)
|
||||
- \ref FL_WHEN_NOT_CHANGED -- if flag set, invokes callback when the tabs remain unchanged (on click or keyboard navigation)
|
||||
- \ref FL_WHEN_RELEASE -- if flag set, invokes callback on RELEASE of mouse button or keyboard navigation
|
||||
|
||||
Notes:
|
||||
|
||||
-# The above flags can be logically OR-ed (|) or added (+) to combine behaviors.
|
||||
-# The default value for when() is \ref FL_WHEN_RELEASE (inherited from Fl_Widget).
|
||||
-# If \ref FL_WHEN_RELEASE is the \em only flag specified,
|
||||
the behavior will be as if (\ref FL_WHEN_RELEASE|\ref FL_WHEN_CHANGED) was specified.
|
||||
-# The value of changed() will be valid during the callback.
|
||||
-# If both \ref FL_WHEN_CHANGED and \ref FL_WHEN_NOT_CHANGED are specified,
|
||||
the callback is invoked whether the tab has been changed or not.
|
||||
The changed() method can be used to determine the cause.
|
||||
-# \ref FL_WHEN_NOT_CHANGED can happen if someone clicks on an already selected tab,
|
||||
or if a keyboard navigation attempt results in no change to the tabs,
|
||||
such as using the arrow keys while at the left or right end of the tabs.
|
||||
*/
|
||||
class FL_EXPORT Fl_Tabs : public Fl_Group {
|
||||
Fl_Widget *value_;
|
||||
|
132
src/Fl_Tabs.cxx
132
src/Fl_Tabs.cxx
@ -170,25 +170,59 @@ int Fl_Tabs::handle(int event) {
|
||||
}}
|
||||
/* FALLTHROUGH */
|
||||
case FL_DRAG:
|
||||
case FL_RELEASE:
|
||||
o = which(Fl::event_x(), Fl::event_y());
|
||||
case FL_RELEASE: {
|
||||
// PUSH, DRAG, RELEASE..
|
||||
int do_cb=0;
|
||||
if ((o = which(Fl::event_x(), Fl::event_y()))) { // get tab group for tab user is over
|
||||
if (o != value()) set_changed(); // if over tab, handle change
|
||||
else clear_changed();
|
||||
}
|
||||
if (event == FL_RELEASE) {
|
||||
push(0);
|
||||
if (o && Fl::visible_focus() && Fl::focus()!=this) {
|
||||
Fl::focus(this);
|
||||
redraw_tabs();
|
||||
}
|
||||
if (o && value(o)) {
|
||||
Fl_Widget_Tracker wp(o);
|
||||
set_changed();
|
||||
do_callback();
|
||||
if (wp.deleted()) return 1;
|
||||
push(0); // no longer 'pushed'
|
||||
// Over a tab?
|
||||
if (o) {
|
||||
// Handle taking keyboard focus w/visible focus indication
|
||||
if (Fl::visible_focus() && Fl::focus()!=this) {
|
||||
Fl::focus(this);
|
||||
redraw_tabs();
|
||||
}
|
||||
if (value(o)) { // commit to value, see if it "changed"..
|
||||
set_changed(); // it changed
|
||||
do_cb =
|
||||
( (when() & FL_WHEN_RELEASE) && // wants cb on RELEASE and..
|
||||
(when() & FL_WHEN_CHANGED) // when changed?
|
||||
) || ( // ..or..
|
||||
(when() == FL_WHEN_RELEASE) // *only* WHEN_RELEASE specified? (default behavior)
|
||||
) ? 1 : 0;
|
||||
} else {
|
||||
clear_changed(); // no change
|
||||
do_cb = (when() & FL_WHEN_RELEASE && // wants cb when RELEASE and..
|
||||
when() & FL_WHEN_NOT_CHANGED)?1:0; // ..when no change occurred?
|
||||
}
|
||||
}
|
||||
Fl_Tooltip::current(o);
|
||||
} else {
|
||||
push(o);
|
||||
// PUSH or DRAG?
|
||||
// Be careful; a user can PUSH on a tab, but can abort the change
|
||||
// if they glide off the tab before a RELEASE. Callbacks on PUSH
|
||||
// will see a value change, but it may change back on RELEASE if
|
||||
// the user aborts the change.
|
||||
//
|
||||
push(o); // DRAG|PUSH -- indicate if still on tab
|
||||
if (o && event == FL_PUSH) { // still on tab?
|
||||
// See if we should do the callback
|
||||
do_cb =
|
||||
( !(when() & FL_WHEN_RELEASE) && // wants callback on PUSH? (ie. NOT RELEASE)
|
||||
(
|
||||
((when() & FL_WHEN_NOT_CHANGED) && !changed()) || // want cb if no change and no change occurred?
|
||||
((when() & FL_WHEN_CHANGED) && changed()) // want cb if change and change occurred?
|
||||
)
|
||||
) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
if (do_cb)
|
||||
do_callback();
|
||||
return 1; }
|
||||
case FL_MOVE: {
|
||||
int ret = Fl_Group::handle(event);
|
||||
Fl_Widget *o = Fl_Tooltip::current(), *n = o;
|
||||
@ -217,23 +251,53 @@ int Fl_Tabs::handle(int event) {
|
||||
if (Fl::event() == FL_UNFOCUS) return 0;
|
||||
else return 1;
|
||||
} else return Fl_Group::handle(event);
|
||||
/* NOTREACHED */
|
||||
case FL_KEYBOARD:
|
||||
// NOTE:
|
||||
// 1) FL_KEYBOARD same as FL_KEYDN; we can receive a string of these
|
||||
// without FL_KEYUP between during key-repeat.
|
||||
// 2) We use push() to keep track of value() changes during key-repeat for FL_KEYUP.
|
||||
// (It would be bad if app's callback saw changed()=false if key-repeat hit the
|
||||
// left-most or right-most tabs)
|
||||
//
|
||||
switch (Fl::event_key()) {
|
||||
case FL_Left:
|
||||
if (child(0)->visible()) return 0;
|
||||
for (i = 1; i < children(); i ++)
|
||||
// First push on tab? (ie. non key-repeat?)
|
||||
// Save current value (so KEYUP can see if changed() during key-repeat)
|
||||
// and clear_changed().
|
||||
//
|
||||
if (!push()) { push(value()); clear_changed(); }// first push on tab? (not key-repeat) save curr value for change
|
||||
if (child(0)->visible()) { // already on left-most tab?
|
||||
if (when() & FL_WHEN_NOT_CHANGED) // want callback if no change?
|
||||
do_callback(); // do callback
|
||||
// return 1 to 'handle' the arrow key, or 0 to let
|
||||
// arrow key be used by fltk for focus navigation.
|
||||
return (Fl::option(Fl::OPTION_ARROW_FOCUS) ? 0 : 1);
|
||||
}
|
||||
for (i = 1; i < children(); i ++) // Find currently visible child
|
||||
if (child(i)->visible()) break;
|
||||
value(child(i - 1));
|
||||
value(child(i - 1)); // select the next tab to the left
|
||||
set_changed();
|
||||
do_callback();
|
||||
if ( (when() & FL_WHEN_CHANGED) && // changed: want cb on change and..
|
||||
!(when() & FL_WHEN_RELEASE)) // ..on PUSH?
|
||||
do_callback(); // do callback
|
||||
return 1;
|
||||
case FL_Right:
|
||||
if (child(children() - 1)->visible()) return 0;
|
||||
for (i = 0; i < children(); i ++)
|
||||
if (!push()) { push(value()); clear_changed(); }// first push on tab? (not key-repeat)
|
||||
if (child(children() - 1)->visible()) { // already on right-most tab?
|
||||
if (when() & FL_WHEN_NOT_CHANGED) // want callback if no change?
|
||||
do_callback(); // do callback
|
||||
// return 1 to 'handle' the arrow key, or 0 to let
|
||||
// arrow key be used by fltk for focus navigation.
|
||||
return (Fl::option(Fl::OPTION_ARROW_FOCUS) ? 0 : 1);
|
||||
}
|
||||
for (i = 0; i < children(); i ++) // Find currently visible child
|
||||
if (child(i)->visible()) break;
|
||||
value(child(i + 1));
|
||||
value(child(i + 1)); // select the next tab to the right
|
||||
set_changed();
|
||||
do_callback();
|
||||
if ( (when() & FL_WHEN_CHANGED) && // change: want callback on change and..
|
||||
!(when() & FL_WHEN_RELEASE)) // ..on PUSH?
|
||||
do_callback(); // do callback
|
||||
return 1;
|
||||
case FL_Down:
|
||||
redraw();
|
||||
@ -242,6 +306,29 @@ int Fl_Tabs::handle(int event) {
|
||||
break;
|
||||
}
|
||||
return Fl_Group::handle(event);
|
||||
case FL_KEYUP:
|
||||
switch (Fl::event_key()) {
|
||||
case FL_Left:
|
||||
case FL_Right:
|
||||
if (push()) {
|
||||
// See if value() changed since first KEYDN
|
||||
if (push() != value()) set_changed();
|
||||
else clear_changed();
|
||||
push(0); // key released, no longer push()ed
|
||||
if ( when() & FL_WHEN_RELEASE) { // want cb on RELEASE?
|
||||
if ( (changed() && ( // changed and..
|
||||
(when() & FL_WHEN_CHANGED) || // want cb on change or..
|
||||
(when()==FL_WHEN_RELEASE))) || // want cb on RELEASE only (implies change -- legacy default)
|
||||
(!changed() && // ..or, not changed and..
|
||||
(when() & FL_WHEN_NOT_CHANGED))) { // want cb on no change?
|
||||
do_callback(); // do callback
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
return Fl_Group::handle(event);
|
||||
case FL_SHORTCUT:
|
||||
for (i = 0; i < children(); ++i) {
|
||||
Fl_Widget *c = child(i);
|
||||
@ -256,6 +343,7 @@ int Fl_Tabs::handle(int event) {
|
||||
return Fl_Group::handle(event);
|
||||
case FL_SHOW:
|
||||
value(); // update visibilities and fall through
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
return Fl_Group::handle(event);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user