Re: [fltk.general] scroll to focus in Fl_Scroll

2013-01-06 Thread Denton Thomas
> No, sorry for being unclear. It's solely to detect that the current
> focus_tracker_ variable value is invalid. This would enable you to
> see when the current focus widget (inside your group) loses focus
> and gets it again. Otherwise you wouldn't scroll the widget back
> into the visible area in that case. However, you would only need to
> do that, if the user scrolled the focus widget out with the scrollbars
> or something like that...

Ah, of course! That makes very good sense, actually. Another case might be a 
window resize, if events go through the queue for that. Agreed that I certainly 
need to track that, and setting focus_tracker_ to 0 would be a simple enough 
way.

DLT
___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk


Re: [fltk.general] scroll to focus in Fl_Scroll

2013-01-06 Thread Albrecht Schlosser
On 05.01.2013 23:01, Denton Thomas wrote:
 > Albrecht wrote:
 >
 >> What about adding here:
 >>
 >>if (!contains(f_new)) focus_tracker_ = 0; // focus in another 
group
 >>
 >>> if(f_new && (f_new != focus_tracker_) && contains(f_new))  {
 >>>   focus_tracker_ = f_new; // focus_tracker_ = NULL in ctor
 >>>   scroll_to(scroll_to_focus_x_(), scroll_to_focus_y_());
 >>>   redraw();
 >>> }
 >>> return ret;
 >>> }
 >>>
 >
 > I guess that's because of cycles, yes?

No, sorry for being unclear. It's solely to detect that the current
focus_tracker_ variable value is invalid. This would enable you to
see when the current focus widget (inside your group) loses focus
and gets it again. Otherwise you wouldn't scroll the widget back
into the visible area in that case. However, you would only need to
do that, if the user scrolled the focus widget out with the scrollbars
or something like that...

 >> So, if you want to save some (or more) CPU cycles, I'd recommend
 >> checking what is really needed, and then filter events and/or do
 >> some basic, but simple checks first.
 >
 > I guess you're thinking it would be cheaper to break up the logical 
AND comparisons? I hadn't considered that.

No, sorry again. I thought of events that are delivered to the scroll
widget, but ignored. There can be really *lots* of such events. There
is maybe the most important FL_MOVE, but there are also all events that
other widgets may ignore, like FL_ENTER, FL_LEAVE, drag'n'drop, etc..
The most important events after FL_MOVE would probably be FL_KEYUP and
FL_SHORTCUT. FL_KEYUP is ignored by almost all FLTK widgets, but FLTK
"tries really hard to deliver all events ..." (cited off the top of my
head from the docs elsewhere), so you can be sure that your scroll
widget WILL receive lost of FL_KEYUP events. FL_SHORTCUT will be sent
to (maybe) all widgets if the current focus widget and all parent
widgets ignore an FL_KEYBOARD event. You could say that all key events
are not really a problem, since most users won't type more than about
10 keys per sec., but you can probably see real CPU usage if you move
the mouse pointer fast over your scroll area. Maybe still not very
important, but you can get the idea...

 > I figured contains() was the most expensive/unpredictable step, so I 
put contains() last.

That seems all okay. contains() moves up the parent() chain of the
widget you requested (i.e. parent(w) if you called contains(w)) until
either it finds the group (in this case the scroll widget) or it finds
the top widget (no parent). This can be a few pointer dereferences,
depending on your overall widget tree depth. Not something I'd be
much concerned about.

 > For my own applications, I also don't specifically need to know 
whether focus is outside the group ... finding it is just a byproduct. 
If your own application needs the flag, though, how about:
 >
 > if (f_new && (f_new != focus_tracker_) {
 >if(contains(focus_tracker_) {
 > ... do the scroll, etc ...
 >}
 >else focus_tracker_ = 0;
 > }
 >
 > This would avoid running contains() when focus doesn't change, but it 
ensures a flag is 0 when focus is outside the group. I think the down 
side is that contains() would -always- run when focus is outside the 
group, even when focus does not change. I don't need that, but maybe you do!

Something like that, yes. Again, my intention was to detect
focus loss, so that you can act on the focus coming back.

Albrecht
___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk


Re: [fltk.general] scroll to focus in Fl_Scroll

2013-01-05 Thread Denton Thomas
> >>> Albrecht wrote:

> What about adding here:
>
>   if (!contains(f_new)) focus_tracker_ = 0; // focus in another group
>
> >if(f_new && (f_new != focus_tracker_) && contains(f_new))  {
> >  focus_tracker_ = f_new; // focus_tracker_ = NULL in ctor
> >  scroll_to(scroll_to_focus_x_(), scroll_to_focus_y_());
> >  redraw();
> >}
> >return ret;
> > }
> >

I guess that's because of cycles, yes?

> So, if you want to save some (or more) CPU cycles, I'd recommend
> checking what is really needed, and then filter events and/or do
> some basic, but simple checks first.

I guess you're thinking it would be cheaper to break up the logical AND 
comparisons? I hadn't considered that.

I figured contains() was the most expensive/unpredictable step, so I put 
contains() last. If (f_new != focus_tracker_) fails, then the && would fail and 
contains() wouldn't run. If contains() is not the most expensive part, then I'm 
up the wrong tree.

For my own applications, I also don't specifically need to know whether focus 
is outside the group ... finding it is just a byproduct. If your own 
application needs the flag, though, how about:

if (f_new && (f_new != focus_tracker_) {
  if(contains(focus_tracker_) {
   ... do the scroll, etc ...
  }
  else focus_tracker_ = 0;
}

This would avoid running contains() when focus doesn't change, but it ensures a 
flag is 0 when focus is outside the group. I think the down side is that 
contains() would -always- run when focus is outside the group, even when focus 
does not change. I don't need that, but maybe you do!

DLT


___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk


Re: [fltk.general] scroll to focus in Fl_Scroll

2013-01-04 Thread Albrecht Schlosser
On 04.01.2013 12:36, Denton Thomas wrote:

> New handle() below. I like this version a bit better, if only because it 
> meets your original suggestion for a simple solution.

Please see also my RFC in fltk.general:



Albrecht

___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk


Re: [fltk.general] scroll to focus in Fl_Scroll

2013-01-04 Thread Albrecht Schlosser
On 04.01.2013 12:36, Denton Thomas wrote:
>>> Albrecht wrote:
>>
>> Oh, yes, that's certainly true. If navigation happens to
>> succeed in a subgroup, then this subgroup does it all. No
>> parent group will notice. You could maybe derive an own
>> Fl_Group class to do this in conjunction with its parent
>> YourScroll class, but this could be a never ending story,
>> unless you know exactly what groups and widgets you need
>> in your special case.
>>
>
> Perhaps this is solve-able after all. New handle() below. I like this version 
> a bit better, if only because it meets your original suggestion for a simple 
> solution.

Yup, simplicity rocks ;-)

> int handle(int event) {
>int ret = Fl_Scroll::handle(event);
>Fl_Widget* f_new = Fl::focus();

What about adding here:

  if (!contains(f_new)) focus_tracker_ = 0; // focus in another group

>if(f_new && (f_new != focus_tracker_) && contains(f_new))  {
>  focus_tracker_ = f_new; // focus_tracker_ = NULL in ctor
>  scroll_to(scroll_to_focus_x_(), scroll_to_focus_y_());
>  redraw();
>}
>return ret;
> }
>
> I've deleted test_focus_() and scroll_to_focus_() functions as unused kruft. 
> All the rest remains untouched.
>
> New handle() just checks if focus (1) has moved and (2) is somewhere in the 
> scroll group. I've done the membership test with contains(), which seems to 
> return true even if the focus widget is nested. So far, at least.

That's how contains() is defined, it *should* (and will) find nested
widgets - and the container widget itself as well.

> I found the problem you mentioned re catching key combinations/order, 
> especially w/ Shift+Tab, etc.

This was only a test case and had nothing to do with the keys
pressed per se. I only used it as a means to leave the scroll
group and return easily.

> If the above works, I can avoid the key problem altogether by ignoring the 
> event code. Otherwise it may be a bottomless pit of testing the 
> possible/accepted keycodes for changing focus. I -think- that the test above 
> will catch any method of changing to the focus widget. I also -think- it's 
> safe ... but I'll have to test some more.

There's nothing that could be wrong with it, IMHO. Just comparing
previous focus (or maybe an ancient predecessor if you left the
groupt meanwhile) with current focus can't be wrong.

> The main oddity is that I've ditched testing whether the base handle() 
> returned 1. If I rely on that, I can't see nested widgets. Ignoring the value 
> seems alright, but maybe this does something bad that I haven't caught yet.

This was probably the reason why leaving the group couldn't be
handled, since this would return 0 from Fl_Scroll's handle() -
which means that the parent group should handle it. However,
then the focus change would also happen after returning from
handle, so this would probably not work either. :-(

One drawback of not testing any event type and/or the return
value would be more CPU time to do your checks all the time,
even if there is an FL_MOVE event. However, maybe *this* is what
triggers your focus checks eventually and makes it all work now.

So, if you want to save some (or more) CPU cycles, I'd recommend
checking what is really needed, and then filter events and/or do
some basic, but simple checks first.

Note that there is FL/names.h with the fl_eventnames[] array that
makes it simple to debug events with something like

   printf("event = %3d: %s\n",event,fl_eventnames[event]);

In my tests I usually omit repeating FL_MOVE events, since they
can be annoying. YMMV

> Since the placement code seems to be working [knock on wood], I've cut the 
> color changes / debug. Thanks for identifying how the color change happened 
> to the input field - I hadn't figured that one out.

You're welcome.

> I'll post a new test unit when I've got it.

Albrecht

___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk


Re: [fltk.general] scroll to focus in Fl_Scroll

2013-01-04 Thread Denton Thomas
> > Albrecht wrote:
>
> Oh, yes, that's certainly true. If navigation happens to
> succeed in a subgroup, then this subgroup does it all. No
> parent group will notice. You could maybe derive an own
> Fl_Group class to do this in conjunction with its parent
> YourScroll class, but this could be a never ending story,
> unless you know exactly what groups and widgets you need
> in your special case.
>

Perhaps this is solve-able after all. New handle() below. I like this version a 
bit better, if only because it meets your original suggestion for a simple 
solution.

int handle(int event) {
  int ret = Fl_Scroll::handle(event);
  Fl_Widget* f_new = Fl::focus();
  if(f_new && (f_new != focus_tracker_) && contains(f_new))  {
focus_tracker_ = f_new; // focus_tracker_ = NULL in ctor
scroll_to(scroll_to_focus_x_(), scroll_to_focus_y_());
redraw();
  }
  return ret;
}

I've deleted test_focus_() and scroll_to_focus_() functions as unused kruft. 
All the rest remains untouched.

New handle() just checks if focus (1) has moved and (2) is somewhere in the 
scroll group. I've done the membership test with contains(), which seems to 
return true even if the focus widget is nested. So far, at least.

I found the problem you mentioned re catching key combinations/order, 
especially w/ Shift+Tab, etc. If the above works, I can avoid the key problem 
altogether by ignoring the event code. Otherwise it may be a bottomless pit of 
testing the possible/accepted keycodes for changing focus. I -think- that the 
test above will catch any method of changing to the focus widget. I also 
-think- it's safe ... but I'll have to test some more.

The main oddity is that I've ditched testing whether the base handle() returned 
1. If I rely on that, I can't see nested widgets. Ignoring the value seems 
alright, but maybe this does something bad that I haven't caught yet.

Since the placement code seems to be working [knock on wood], I've cut the 
color changes / debug. Thanks for identifying how the color change happened to 
the input field - I hadn't figured that one out.

I'll post a new test unit when I've got it.

Denton
___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk


Re: [fltk.general] scroll to focus in Fl_Scroll

2013-01-04 Thread Albrecht Schlosser
On 04.01.2013 10:05, Albrecht Schlosser wrote:

> the scroll widget (see the notes and the callback). You may
> need to call the parent's redraw method as well, if you have
> a frame box time somewhere, so that the redraw doesn't draw

... frame box TYPE ...

(fingers faster than mind ;-) )

Albrecht

___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk


Re: [fltk.general] scroll to focus in Fl_Scroll

2013-01-04 Thread Albrecht Schlosser
On 04.01.2013 03:12, Denton Thomas wrote:
> Albrecht wrote:
>> It's not perfect, and maybe some of the changes would turn out
>> to be useless... just take it as a base for more own experiments.
>>
>
> Thanks for all this, Albrecht. I'll certainly use those immediately. I 
> appreciate it, as this is part of a current project.
>
> I'll keep testing re the style/redraw problem. I'm not sure what I'm doing 
> wrong there - the box style changes just didn't appear on screen ... which 
> was odd. I'll check out your patch to see how you've done it.

You'll see that I did it by explicitly calling redraw() on
the scroll widget (see the notes and the callback). You may
need to call the parent's redraw method as well, if you have
a frame box time somewhere, so that the redraw doesn't draw
the background.

> As well, I caught a more glaring problem: if Fl::focus() is in a group inside 
> of the Fl_Scroll, then it seems the Fl_Scroll::handle() method is not ever 
> run ... so the focus tracking code can't run. I'll write a general test to 
> make sure it's not my own Fl_Group subclass that's hogging the event chain, 
> though.

Oh, yes, that's certainly true. If navigation happens to
succeed in a subgroup, then this subgroup does it all. No
parent group will notice. You could maybe derive an own
Fl_Group class to do this in conjunction with its parent
YourScroll class, but this could be a never ending story,
unless you know exactly what groups and widgets you need
in your special case.

In my case I'm using only simple widgets within the scroll
and I handle it all in the child widgets, but this is a
special case, since all /my/ child widgets are own classes
anyway (and inherit from another common class as well - which
is not generally recommended to do, but I did ...).

Another issue I observed in your test case that I couldn't
fix in my tests is this: click on the input field, then use
SHIFT/TAB to go backwards into your group. This is not handled
by the scroll widget. Go one more back with SHIFT/TAB, then
forwards with TAB, and you'll see. Try also to move the scrollbar
to scroll the last widget out of the visible area while the focus
is on it or on the input widget, then use TAB and/or SHIFT/TAB.
That's what I meant when I wrote that there's a problem when
the focus leaves the scroll widget and comes back to it.

Another small point: you tested that the same widget doesn't
scroll if it gets the focus again, e.g. by mouse clicking.
So, if you move the scroll area while one widget has the
focus to move it partly out of the scroll area, then click on
it again, it will stay where it is and doesn't scroll to be
fully visible. This could be called a feature though...

One last point: in your original test program I could sometimes
make the input widget to get a red background. I hope this is
fixed with my 2nd patch, but you should check this, if you
intend to do something with the "previous focus widget" to make
sure you don't modify a widget outside your scroll group.

Albrecht

___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk


Re: [fltk.general] scroll to focus in Fl_Scroll

2013-01-03 Thread Denton Thomas
Albrecht wrote:
> It's not perfect, and maybe some of the changes would turn out
> to be useless... just take it as a base for more own experiments.
>

Thanks for all this, Albrecht. I'll certainly use those immediately. I 
appreciate it, as this is part of a current project.

I'll keep testing re the style/redraw problem. I'm not sure what I'm doing 
wrong there - the box style changes just didn't appear on screen ... which was 
odd. I'll check out your patch to see how you've done it.

As well, I caught a more glaring problem: if Fl::focus() is in a group inside 
of the Fl_Scroll, then it seems the Fl_Scroll::handle() method is not ever run 
... so the focus tracking code can't run. I'll write a general test to make 
sure it's not my own Fl_Group subclass that's hogging the event chain, though.

Cheers -

Denton
___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk


Re: [fltk.general] scroll to focus in Fl_Scroll

2013-01-03 Thread Albrecht Schlosser
On 03.01.2013 05:47, Denton Thomas wrote:

> For both of you (Ian, Albrecht), here is my solution. It includes a test 
> sequence that produces some random buttons, and lets the client dynamically 
> change the size of the scrollbar. I wanted to allow a dynamic box style 
> change for the scroll group, but it didn't work for some reason ... it just 
> wouldn't redraw in the new style (???). I'm on 1.3.0 - I think I should just 
> update to the newest release.
>
> Thanks in advance for any advice - this will certainly be helpful in my 
> current project.

I tried your test case, and it seemed to work mostly.

Concerning the scrollbar size changes, here's a diff that makes
it work. I put the scroll_ widget in the user_data argument to
access it in the callback and set the scrollbar size. Note that
you changed the global scrollbar size variable, whereas my patch
changes only that of this particular scroll widget.

diff --git a/Track_Focus_Scroll-Main.cpp b/Track_Focus_Scroll-Main.cpp
index cb89b47..0360aef 100644
--- a/Track_Focus_Scroll-Main.cpp
+++ b/Track_Focus_Scroll-Main.cpp
@@ -186,8 +186,9 @@ void set_scrollbar_size_cb_(Fl_Widget *src, void *dat) {

int x = atoi(((Fl_Int_Input *)src)->value());

-  Fl::scrollbar_size(x);
-  printf("Set scrollbar size to %d\n", x);
+  Fl_Scroll *scroll = (Fl_Scroll *)dat;
+  scroll->scrollbar_size(x); scroll->redraw();
+  printf("Set scrollbar size to %d\n", x); fflush(stdout);
  }

  void setup() {
@@ -238,7 +239,7 @@ void setup() {
s = new Fl_Int_Input(scroll_->x() + scroll_->w() + 10, scroll_->y(), 
50, 35, "scrollbar size");
  s->labelsize(9);
  s->align(FL_ALIGN_TOP);
-s->callback(set_scrollbar_size_cb_, NULL);
+s->callback(set_scrollbar_size_cb_, scroll_);

win_->resizable(scroll_);
win_->end();

I don't really understand what you mean with "I wanted to allow a 
dynamic box style change for the scroll group, but it didn't work for 
some reason ... it just wouldn't redraw in the new style (???)".

I assume that the problem was triggering the redraw(), and the solution
is in my patch. Or was this something else?

I also experimented a little more to remove some artifacts when
the focus leaves the scroll widget and/or comes back to it. My
time doesn't allow more comments now, I'm just posting another
diff that should be applied after the first one. Just try to
understand what it does, and experiment with the diff's in it.
It's not perfect, and maybe some of the changes would turn out
to be useless... just take it as a base for more own experiments.

diff --git a/Track_Focus_Scroll-Main.cpp b/Track_Focus_Scroll-Main.cpp
index 0360aef..f042f66 100644
--- a/Track_Focus_Scroll-Main.cpp
+++ b/Track_Focus_Scroll-Main.cpp
@@ -45,12 +45,14 @@ class Track_Focus_Scroll : public Fl_Scroll {
/** if Fl_Scroll:handle() manages event && Fl::focus() changes, call
  adjust_scroll_() to manage scroll bars */
int handle(int event) {
+if(!contains(Fl::focus())) focus_tracker_ = 0;
+// if(event == FL_UNFOCUS) focus_tracker_ = 0;
  int ret = Fl_Scroll::handle(event);
+if(!contains(Fl::focus())) focus_tracker_ = 0;

-if((event == FL_KEYBOARD) || (event == FL_PUSH)) {
+if((event == FL_KEYBOARD) || (event == FL_SHORTCUT) || (event == 
FL_PUSH)) {
if(ret && scroll_to_focus_()) redraw();
  }
-
  return ret;
}

@@ -65,17 +67,20 @@ class Track_Focus_Scroll : public Fl_Scroll {
*/
int test_focus_() {
  // if widget is not a widget inside of the scroll group, end.
-if(focus_tracker_ == Fl::focus()) return 0;
+if(focus_tracker_ && (focus_tracker_ == Fl::focus())) return 0;

  // record new focus ...
  if(focus_tracker_) focus_tracker_->color(FL_BLUE);
  focus_tracker_ = Fl::focus();
-focus_tracker_->color(FL_RED);

  if((!focus_tracker_->inside(this)) ||
 (focus_tracker_ == &scrollbar) || (focus_tracker_ == 
&hscrollbar) ||
-   focus_tracker_->inside(&scrollbar) || 
focus_tracker_->inside(&hscrollbar))
+   focus_tracker_->inside(&scrollbar) || 
focus_tracker_->inside(&hscrollbar)) {
+  focus_tracker_ = 0;
return 0;
+}
+
+focus_tracker_->color(FL_RED);

  return 1; // scroll to it!


Hth

Albrecht

___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk


Re: [fltk.general] scroll to focus in Fl_Scroll

2013-01-02 Thread Denton Thomas
Ian wrote:
> Ah, but there's a thought... If Denton has already modified his widgets =
> to handle the focus differently, then they may perhaps be "eating" the =
> nav events, thus preventing them from propagating to the container =
> scroll widget at all?
>

I may have done that, yes. Have to go back and check now!

For both of you (Ian, Albrecht), here is my solution. It includes a test 
sequence that produces some random buttons, and lets the client dynamically 
change the size of the scrollbar. I wanted to allow a dynamic box style change 
for the scroll group, but it didn't work for some reason ... it just wouldn't 
redraw in the new style (???). I'm on 1.3.0 - I think I should just update to 
the newest release.

Thanks in advance for any advice - this will certainly be helpful in my current 
project.

Denton
---


/** \file Track_Focus_Scroll-Main.cpp

  Testing/Draft: Track_Focus_Scroll

  CHANGES
- dentonlt, january 2013: original version
  - kudos to Albrecht Schlosser and Ian MacArthur for their assistance;
see the fltk newsgroup for replies to:
http://fltk.org/newsgroups.php?gfltk.general+v:35850

*/

// stdlib
#include 

// FLTK lib
#include 
#include 
#include 
#include 
#include 

class Track_Focus_Scroll;

Fl_Window *win_;
Fl_Int_Input *f; // fudge input
Fl_Int_Input * s; // scrollbar width input
Track_Focus_Scroll *scroll_;

/** @class Track_Focus_Scroll
  \brief Fl_Scroll that auto-scrolls to widget in focus

  This subclass of Fl_Scroll provides a handle() function that puts
  the Fl::focus() widget in view whenever the focus changes. handle()
  checks for a focus change after either FL_KEYBOARD or FL_PUSH.

  \see handle()
  \see scroll_to_focus()

  */
class Track_Focus_Scroll : public Fl_Scroll {

  Fl_Widget *focus_tracker_; ///< for tracking the Fl::focus() widget

  /** if Fl_Scroll:handle() manages event && Fl::focus() changes, call
adjust_scroll_() to manage scroll bars */
  int handle(int event) {
int ret = Fl_Scroll::handle(event);

if((event == FL_KEYBOARD) || (event == FL_PUSH)) {
  if(ret && scroll_to_focus_()) redraw();
}

return ret;
  }

  /** This is a support function for scroll_to_focus_(). You should not have to
call this function directly.

\see scroll_to_focus_()

test Fl::focus() to see (1) if focus has changed since last call
and (2) if focus is inside Fl_Scroll. If both true, return 1. Else return 0.

  */
  int test_focus_() {
// if widget is not a widget inside of the scroll group, end.
if(focus_tracker_ == Fl::focus()) return 0;

// record new focus ...
if(focus_tracker_) focus_tracker_->color(FL_BLUE);
focus_tracker_ = Fl::focus();
focus_tracker_->color(FL_RED);

if((!focus_tracker_->inside(this)) ||
   (focus_tracker_ == &scrollbar) || (focus_tracker_ == &hscrollbar) ||
   focus_tracker_->inside(&scrollbar) || 
focus_tracker_->inside(&hscrollbar))
  return 0;

return 1; // scroll to it!

  }

  /** This is a support function for scroll_to_focus_(). You should not have to
call this function directly.

\see scroll_to_focus_()

test focus_tracker_'s x dimensions. If all/part of widget is outside view 
area,
calculate a new scroll xposition that will put focus_tracker_ in the view 
area.
Return that new scoll xposition. */
  int scroll_to_focus_x_() {

int xpos = xposition();

if(!focus_tracker_) return xpos; // avoid glorious segfault ...

int sx, sy, sw, sh;
bbox(sx, sy, sw, sh); // visible scroll area dimensions ...
int style_fudge_ = x() - sx; // to remove the few pixels taken up by the 
style border

int wx = focus_tracker_->x();
int ww = focus_tracker_->w();
int minw = (ww < sw) ? ww : sw; // get smaller of widget width or scroll 
view width

//otherwise, we scroll until as much as possible of the focus_tracker_ 
widget is in view.
if(wx > sx + sw - ww)  // scroll right
  return xpos + wx - sw + minw - x() + style_fudge_; // move ahead by (dist 
b/t window edge & widget) + minw + fudge
if(wx < sx) // scroll left; this should always scroll until the widget's 
left side is against the scroll field left side.
  return xpos + wx - x() + style_fudge_; // move back by (dist b/t window 
edge and widget) + fudge

return xpos;

  }

/** This is a support function for scroll_to_focus_(). You should not have to
call this function directly.

\see scroll_to_focus_()

test focus_tracker_'s y dimensions. If all/part of widget is outside view 
area,
calculate a new scroll yposition that will put focus_tracker_ in the view 
area.
Return that new scoll yposition. */
  int scroll_to_focus_y_() {

int ypos = yposition(); // get current scroll position

if(!focus_tracker_) return ypos; // avoid glorious segfault ...

int sx, sy, sw, sh;
bbox(sx, sy, sw, sh); // get dimensions ...
int style_fudge_ = y() - sy;

int wy = focus_tracker_->y();
int wh = f

Re: [fltk.general] scroll to focus in Fl_Scroll

2013-01-02 Thread Ian MacArthur

On 2 Jan 2013, at 12:14, Albrecht Schlosser wrote:


> Yep, that's also correct, but fortunately normal FLTK widgets don't
> *use* the navigation keys. Hence, navigation key events usually return
> zero from the widget's handle() method, and the group gets it.


Ah, but there's a thought... If Denton has already modified his widgets to 
handle the focus differently, then they may perhaps be "eating" the nav events, 
thus preventing them from propagating to the container scroll widget at all?



___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk


Re: [fltk.general] scroll to focus in Fl_Scroll

2013-01-02 Thread Albrecht Schlosser
On 02.01.2013 14:12, Denton Thomas wrote:
>> On 02.01.2013 13:14, Albrecht Schlosser wrote:
> ..
>>>
>
>>> Fl_Widget *fw = Fl::focus(); // save focus widget
>>> int ret = Fl_Scroll::handle(event);
>>> if (ret && fw != Fl::focus) { // event used and focus changed
> ..
>> Albrecht
>>
>
> Thanks for all this, Albrecht. I started mucking with an Fl_Scroll subclass & 
> custom handle(), and decided to track the focus widget in the same way as 
> you. I hadn't though to cut the test down to that one if statement - big help.

You're welcome, I'm glad if I could help.

Here's something I forgot: you should also check if the
focus widget after Fl_Scoll::handle() is
  (a) a child of your scroll widget, and
  (b) NOT one of the scrollbars.

There are public members scrollbar and hscrollbar in Fl_Scroll.
Do NOT assume that the scrollbars are the last members of Fl_Scroll,
since this can change...

> Now working on determining dx/dy. I'll post my subclass when I'm all done.

Looking forward to your post...

Albrecht

___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk


Re: [fltk.general] scroll to focus in Fl_Scroll

2013-01-02 Thread Denton Thomas
> On 02.01.2013 13:14, Albrecht Schlosser wrote:
..
> >

> >Fl_Widget *fw = Fl::focus(); // save focus widget
> >int ret = Fl_Scroll::handle(event);
> >if (ret && fw != Fl::focus) { // event used and focus changed
..
> Albrecht
>

Thanks for all this, Albrecht. I started mucking with an Fl_Scroll subclass & 
custom handle(), and decided to track the focus widget in the same way as you. 
I hadn't though to cut the test down to that one if statement - big help.

Now working on determining dx/dy. I'll post my subclass when I'm all done.

Cheers -

Denton


___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk


Re: [fltk.general] scroll to focus in Fl_Scroll

2013-01-02 Thread Albrecht Schlosser
On 02.01.2013 13:14, Albrecht Schlosser wrote:
> So the approach to subclass Fl_Scroll should work as suggested.
> It could maybe need just a little code in handle(), something
> like this might suffice:
>
> MyScroll::handle(int event) {
>
>Fl_Widget *fw = Fl::focus(); // save focus widget
>int ret = Fl_Scroll::handle(event);
>if (ret && fw != Fl::focus) { // event used and focus changed

should read: if (ret && fw != Fl::focus()) { ...

>  // check focus widget and scroll ...
>  // your design decision here how to manage scrolling
>  // returns wx and wx to scroll to

should read: // returns wx and wy to scroll to

>  scroll_to(wx,wy);
>
>}
>return ret; // return Fl_Scroll/Fl_Group's return value
> }

And note that this is untested code.

Albrecht

___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk


Re: [fltk.general] scroll to focus in Fl_Scroll

2013-01-02 Thread Albrecht Schlosser
On 01.01.2013 23:39, Ian MacArthur wrote:
>
> On 1 Jan 2013, at 21:44, Denton Thomas wrote:
>
>
>>> My thinking is that this *should* work and would mean that only one 
>>> "special" derived widget is needed, rather than having to make every 
>>> contained widget be a "special" widget.
>>>
>>
>> Yep, I agree. I've just made a template to add the handlers to any old 
>> widget, but it seems like a kludge.
>>
>>>  From what I can tell, an Fl_Group does not parse events if they are 
>>> already within the group. If I tab from one widget to another, within the 
>>> group, the event never goes through Fl_Scroll:handle(). So the group never 
>>> knows to check whether focus has changed hands/positions.
>>
>> At least I don't -think- it does ... I'll test some more.
>
> Ah... that was what I was worried about, perhaps...
>
> (Paraphrasing somewhat...) Normally, events in fltk get propagated from the 
> container widget (e.g. group or scroll) down to its children, until one of 
> them takes it.

Correct.

> But I suspect that keyboard events get routed *first* to the widget with 
> focus, and only if it doesn't want them, do they get passed to the container 
> widget to be distributed.

Yep, correct as well.

> And so I guess it is possible that keyboard nav events would go to the focus 
> widget

True so far...

> without necessarily passing through the parent container at all. And thereby 
> rendering my cunning scheme useless.

Yep, that's also correct, but fortunately normal FLTK widgets don't
*use* the navigation keys. Hence, navigation key events usually return
zero from the widget's handle() method, and the group gets it.

> Oh well. If you look into this further, be handy to know for sure if this is 
> the way things are!

Eventually, when the group gets the key event, there is this code
in Fl_Group::handle():

   case FL_KEYBOARD:
 return navigation(navkey());

and this method at line #315 in current svn (r 9783):

// try to move the focus in response to a keystroke:
int Fl_Group::navigation(int key) {
  ...
}

So the approach to subclass Fl_Scroll should work as suggested.
It could maybe need just a little code in handle(), something
like this might suffice:

MyScroll::handle(int event) {

   Fl_Widget *fw = Fl::focus(); // save focus widget
   int ret = Fl_Scroll::handle(event);
   if (ret && fw != Fl::focus) { // event used and focus changed

 // check focus widget and scroll ...
 // your design decision here how to manage scrolling
 // returns wx and wx to scroll to

 scroll_to(wx,wy);

   }
   return ret; // return Fl_Scroll/Fl_Group's return value
}

So far this simple code. Maybe you'd want to also check for
FL_KEYBOARD and/or FL_SHORTCUT events, but that's probably not
necessary.

That said, I have done it in my own code also in all the child
widget classes, but I had shared code in my child classes anyway,
so this was the easiest approach for me at that time.

I'll check if I can use this simple code in my own app as well,
but this will not be done soon. So don't hold your breath for
any more info from me concerning this approach.

To the OP: I'd be interested in your feedback, if it works this
way for you, and in any corrections you need to make.

Albrecht

___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk


Re: [fltk.general] scroll to focus in Fl_Scroll

2013-01-01 Thread Ian MacArthur

On 1 Jan 2013, at 21:44, Denton Thomas wrote:


>> My thinking is that this *should* work and would mean that only one 
>> "special" derived widget is needed, rather than having to make every 
>> contained widget be a "special" widget.
>> 
> 
> Yep, I agree. I've just made a template to add the handlers to any old 
> widget, but it seems like a kludge.
> 
>> From what I can tell, an Fl_Group does not parse events if they are already 
>> within the group. If I tab from one widget to another, within the group, the 
>> event never goes through Fl_Scroll:handle(). So the group never knows to 
>> check whether focus has changed hands/positions.
> 
> At least I don't -think- it does ... I'll test some more.

Ah... that was what I was worried about, perhaps...

(Paraphrasing somewhat...) Normally, events in fltk get propagated from the 
container widget (e.g. group or scroll) down to its children, until one of them 
takes it.

But I suspect that keyboard events get routed *first* to the widget with focus, 
and only if it doesn't want them, do they get passed to the container widget to 
be distributed.

And so I guess it is possible that keyboard nav events would go to the focus 
widget without necessarily passing through the parent container at all. And 
thereby rendering my cunning scheme useless.

Oh well. If you look into this further, be handy to know for sure if this is 
the way things are!



___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk


Re: [fltk.general] scroll to focus in Fl_Scroll

2013-01-01 Thread Denton Thomas
Thanks for that, Ian.

>
> My thinking is that this *should* work and would mean that only one "special" 
> derived widget is needed, rather than having to make every contained widget 
> be a "special" widget.
>

Yep, I agree. I've just made a template to add the handlers to any old widget, 
but it seems like a kludge.

>From what I can tell, an Fl_Group does not parse events if they are already 
>within the group. If I tab from one widget to another, within the group, the 
>event never goes through Fl_Scroll:handle(). So the group never knows to check 
>whether focus has changed hands/positions.

At least I don't -think- it does ... I'll test some more.

Denton
___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk


Re: [fltk.general] scroll to focus in Fl_Scroll

2013-01-01 Thread Ian MacArthur

On 1 Jan 2013, at 00:07, Denton Thomas wrote:

> I have an Fl_Scroll with many widgets (buttons, text displays, etc). If I tab 
> through those widgets, I will eventually change focus to a widget that is in 
> the scroll group but outside the visible scroll position.
> 
> Is there a existing method the Fl_Scroll to notice when the focus widget is 
> not visible, and then to scroll itself to put that widget in view?

Hmm, I don't think we have any specific mechanism for handling keyboard 
navigation within a scroll widget.

I don't think I've ever seen this asked before either, which seems odd, since 
it does seem like a reasonable behaviour (to have the scroll move to expose the 
focussed widget following keyboard navigation...)

Or I may be missing something really obvious and this is actually trivial!


> From what I can tell, this is not a trivial task.
> 
> I previously used a custom handle() in each child to tell Fl_Scroll when 
> FL_FOCUS changes, then Fl_Scroll::scroll_to(x,y) to put the widget in view 
> ... but perhaps this is not the best method?

I think I'd have gone at this the other way round; that is, derive a custom 
widget from Fl_Scroll and fill it with "standard" widgets.

The handle method of the derived scroll would of course call the base handle 
method, then check to see if the focus had moved to a non-visible widget and 
try to do the scroll_to() as required.

Well, something like that - though I have not tried it... My thinking is that 
this *should* work and would mean that only one "special" derived widget is 
needed, rather than having to make every contained widget be a "special" widget.

If you try this; I'd be interested to hear how it works out!

Cheers, bliadhna mhath ùr...
-- 
Ian


___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk


[fltk.general] scroll to focus in Fl_Scroll

2012-12-31 Thread Denton Thomas
Hi, All -

Perhaps this has been asked before, but I couldn't find it in the forums. A RTM 
link would be great ... !

I have an Fl_Scroll with many widgets (buttons, text displays, etc). If I tab 
through those widgets, I will eventually change focus to a widget that is in 
the scroll group but outside the visible scroll position.

Is there a existing method the Fl_Scroll to notice when the focus widget is not 
visible, and then to scroll itself to put that widget in view? From what I can 
tell, this is not a trivial task.

I previously used a custom handle() in each child to tell Fl_Scroll when 
FL_FOCUS changes, then Fl_Scroll::scroll_to(x,y) to put the widget in view ... 
but perhaps this is not the best method?

Thanks for the advice. And Happy New Year!!

Denton
___
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk