In the docs for Fl_Tabs, check the use of
when() to control when the
callback is invoked, e.g.
https://www.fltk.org/doc-1.4/classFl__Tabs.html
See in particular the section entitled
"Callback's Use Of when()"
where there's quite a bit written about this:
Callback's Use Of when()
As of FLTK 1.3.3, Fl_Tabs() supports the following flags for when():
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:
- The above flags can be logically OR-ed (|) or added (+) to combine behaviors.
- The default value for when() is FL_WHEN_RELEASE (inherited from Fl_Widget).
- If FL_WHEN_RELEASE is the only flag specified, the behavior will be as if (FL_WHEN_RELEASE|FL_WHEN_CHANGED) was specified.
- The value of changed() will be valid during the callback.
- 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.
- 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.
On 9/2/21 3:53 AM, rs wrote:
Right, here is a minimal example that exhibits the issue:
I don't see the issue.>then the callback is only being called when switching to the first (n-1) tabs. I.e. if i have 4 tabs,>"A","B","C", and "D", the callback is only called when switching to "A", "B" or "C".
I modified your example to show me which tab is active in the callback, and the callback is invoked for all tabs. (gcc 9.3.0 on Linux Mint 20).
I'm uncertain what your test of tabs->value() was to accomplish in the mywin handler, you will receive messages for the "previous" tab (e.g. UNFOCUS) when switching to a new tab.
I do. It's really strange.
'Taint the compiler. Building FLTK and the test app with Clang 10.0.0 also shows the issue.
--
You received this message because you are subscribed to the Google Groups "fltk.general" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkgeneral...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkgeneral/51ad069b-dbbc-4135-9ed4-7b4e20f6e044n%40googlegroups.com.
On 9/2/21 6:38 PM, Bill Spitzak wrote:
It does seem like a bug, calling value() should not have any side-effects. Especially because the tabs widget works even if nobody calls value().
On 9/2/21 6:38 PM, Bill Spitzak wrote:
It does seem like a bug, calling value() should not have any side-effects. Especially because the tabs widget works even if nobody calls value().
Ah, it is weird that just testing with Fl_Tabs::value(void)
can apparently
end up calling hide() and show().. yikes.
That code goes back to 1999 though, so looks like you'd know
for sure:
49a0693962 (Matthias Melcher 2006-08-17 13:43:07 +0000 308)
Fl_Widget* Fl_Tabs::value() {
a7904da09a (Bill Spitzak 1999-10-15 09:01:48 +0000
309) Fl_Widget* v = 0;
a7904da09a (Bill Spitzak 1999-10-15 09:01:48 +0000
310) Fl_Widget*const* a = array();
a7904da09a (Bill Spitzak 1999-10-15 09:01:48 +0000
311) for (int i=children(); i--;) {
a7904da09a (Bill Spitzak 1999-10-15 09:01:48 +0000
312) Fl_Widget* o = *a++;
a7904da09a (Bill Spitzak 1999-10-15 09:01:48 +0000
313) if (v) o->hide();
a7904da09a (Bill Spitzak 1999-10-15 09:01:48 +0000
314) else if (o->visible()) v = o;
a7904da09a (Bill Spitzak 1999-10-15 09:01:48 +0000
315) else if (!i) {o->show(); v =
o;}
f9039b2ae2 (Michael R Sweet 1998-10-06 18:21:25 +0000
316) }
f9039b2ae2 (Michael R Sweet 1998-10-06 18:21:25 +0000
317) return v;
f9039b2ae2 (Michael R Sweet 1998-10-06 18:21:25 +0000
318) }
Perhaps that's the cause, because that last line in the loop
that
calls o->show() on the last item seems to be maybe what's
forcing
the last child to be visible if no other one is..
..and by that I mean the loop code in
Fl_Tabs::value(Fl_Widget*) that changes
the selected tab by hide()ing all but the one to be show()n
gets confused when it reaches the last tab and finds it
visible() before it show()s it,
causing the loop to think there was no change when there in
fact was.
It would appear Fl_Widget* value(void) seems to enforce that:
> Not more than one group is visible
> That at least one group is visible (the last, if no
others are)
And that sounds like a good thing to enforce at least
/somewhere/,
as it's hard to imagine the Tabs widget with no group visible,
and/or
more than one group visible at a time.
So perhaps the fix I suggested is the right one, assuming we
want to
leave the value(void) code alone, and the show()
FL_HIDE/FL_SHOW event behavior
is correct.
--
You received this message because you are subscribed to the Google Groups "fltk.general" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkgeneral...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkgeneral/9a3b1031-913e-486b-2bef-c0ff991d4346%40seriss.com.
Also means value() can return on the first visible child, which is slightly faster.
On Fri, Sep 3, 2021 at 8:58 AM Bill Spitzak <spi...@gmail.com> wrote:
I agree, and your fix is probably correct.
I think that show() and hide() in value() was because I was worried that the tabs could get into some kind of incorrect state where the number that are visible is not one, and this is trying to fix that. I think now that is probably a mistake, such states should not happen, and it would be better to just return the first visible one or null if none are visible. If this is a problem it would be better to fix it when there is an attempt to set the value, rather than when it is read.
On 9/3/21 9:43 AM, Albrecht Schlosser wrote:
[1] @Greg: calling the existing value(void) method inside value(Fl_Widget *) could cause even more unexpected side effects than we're having now. Other than that: great findings, thanks!
I noticed value(void) is called elsewhere when you follow
hide() down the event rabbit hole.
Looking quickly, it's called during the handling of e.g.
FL_HIDE which is triggered
by hide() and show() in value(Fl_Widget*). It's also called at
the top of draw().
On 9/3/21 8:58 AM, Bill Spitzak wrote:
I agree, and your fix is probably correct.
I think that show() and hide() in value() was because I was worried that the tabs could get into some kind of incorrect state where the number that are visible is not one, and this is trying to fix that. I think now that is probably a mistake, such states should not happen, and it would be better to just return the first visible one or null if none are visible. If this is a problem it would be better to fix it when there is an attempt to set the value, rather than when it is read.
--
You received this message because you are subscribed to the Google Groups "fltk.general" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkgeneral...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkgeneral/22d804de-0f92-a796-50d8-36e319b78d57%40online.de.
I agree with most of this, it is the way to go. A few differences I think should be done:
1. value(Fl_Widget*) should do the recalc, rather than leaving it in a possible bad state until draw() calls recalc.
2. recalc might be better called "fix" or "make_exactly_one_tab_visible" or something, depending on what reads best, and it should be private (or maybe protected)
On 9/3/21 9:50 PM Bill Spitzak wrote:
2. recalc might be better called "fix" or "make_exactly_one_tab_visible" or something, depending on what reads best, and it should be private (or maybe protected)
What about fix_visibility()? As a precedent we have Fl_Scroll::fix_scrollbar_order(), fl_fix_focus() and likely some more.