DO NOT REPLY TO THIS MESSAGE. INSTEAD, POST ANY RESPONSES TO THE LINK BELOW.
[STR Active]
Link: http://www.fltk.org/str.php?L2939
Version: 1.3.2
Attaching a v7 patch; simplified the docs a bit.
Also added an Fl_Tabs code example while I was at it
(which should be committed separately)
Link: http://www.fltk.org/str.php?L2939
Version: 1.3.2
Index: FL/Fl_Tabs.H
===================================================================
--- FL/Fl_Tabs.H (revision 9853)
+++ FL/Fl_Tabs.H (working copy)
@@ -49,6 +49,52 @@
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():
+
+ \code
+ FL_WHEN_NEVER -- callback never invoked (all flags off)
+ FL_WHEN_CHANGED -- if flag set, invokes callback when a tab has been
changed (on click or keyboard navigation)
+ FL_WHEN_NOT_CHANGED -- if flag set, invokes callback when the tabs remain
unchanged (on click or keyboard navigation)
+ FL_WHEN_RELEASE -- if flag set, invokes callback on RELEASE of mouse
button or keyboard navigation
+
+ Notes:
+
+ (a) The above flags can be logically OR-ed (|) or added (+) to combine
behaviors.
+ (b) The default value for when() is FL_WHEN_RELEASE (inherited from
Fl_Widget).
+ (c) If FL_WHEN_RELEASE is the /only/ flag specified,
+ the behavior will be as if (FL_WHEN_RELEASE|FL_WHEN_CHANGED) was
specified.
+ (d) The value of changed() will be valid during the callback.
+ (e) If both FL_WHEN_CHANGED and 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.
+ (f) 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.
+ \endcode
+
*/
class FL_EXPORT Fl_Tabs : public Fl_Group {
Fl_Widget *value_;
Index: src/Fl_Tabs.cxx
===================================================================
--- src/Fl_Tabs.cxx (revision 9855)
+++ src/Fl_Tabs.cxx (working copy)
@@ -170,25 +170,62 @@
}}
/* 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();
+ 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?
+ }
}
- if (o && value(o)) {
- Fl_Widget_Tracker wp(o);
- set_changed();
- do_callback();
- if (wp.deleted()) return 1;
- }
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) {
+ Fl_Widget_Tracker wp(o);
+ do_callback();
+ if (wp.deleted()) return 1;
+ }
+ return 1; }
case FL_MOVE: {
int ret = Fl_Group::handle(event);
Fl_Widget *o = Fl_Tooltip::current(), *n = o;
@@ -217,23 +254,53 @@
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 +309,28 @@
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();
+ 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
+ }
+ push(0); // key released
+ }
+ return 1;
+ break;
+ }
+ return Fl_Group::handle(event);
case FL_SHORTCUT:
for (i = 0; i < children(); ++i) {
Fl_Widget *c = child(i);
@@ -256,6 +345,7 @@
return Fl_Group::handle(event);
case FL_SHOW:
value(); // update visibilities and fall through
+ /* FALLTHROUGH */
default:
return Fl_Group::handle(event);
_______________________________________________
fltk-bugs mailing list
fltk-bugs@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk-bugs