FLTK logo

STR #2639

FLTK matrix user chat room
(using Element browser app)   FLTK gitter user chat room   GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Apps      FLTK Library      Forums      Links     Login 
 Home  |  Articles & FAQs  |  Bugs & Features  |  Documentation  |  Download  |  Screenshots  ]
 

Return to Bugs & Features | SVN ⇄ GIT ]

STR #2639

Application:FLTK Library
Status:1 - Closed w/Resolution
Priority:3 - Moderate, e.g. unable to compile the software
Scope:3 - Applies to all machines and operating systems
Subsystem:Core Library
Summary:Fl_Pack resizes hidden widgets, which it doesn't touch when visible.
Version:1.4-feature
Created By:jcid
Assigned To:matt
Fix Version:1.4.0
Fix Commit:3a7c9fe9781067075c38393b6599d8095a777483
Update Notification:

Receive EMails Don't Receive EMails

Trouble Report Files:


Name/Time/Date Filename/Size  
 
#1 jcid
07:52 May 22, 2011
rsz.cc
2k
 
 
#2 jcid
14:20 May 30, 2011
gr_rsz.cc
2k
 
 
#3 AlbrechtS
09:26 Jan 20, 2023
str2639_rsz_flex.cxx
2k
 
 
#4 AlbrechtS
10:24 Jan 20, 2023
str2639_rsz_gr.cxx
2k
 
     

Trouble Report Comments:


Name/Time/Date Text  
 
#1 jcid
07:52 May 22, 2011
Fl_Pack resizes hidden widgets, which it doesn't
touch when visible:

  The tiny example program illustrates the point:

  * resize the window back and forth and both "Group 1" and
    "Group 2" keep their heights. OK here.
  * With a small window, hide "Group 2" and resize to a big
    window, then show "Group 2". It grew while hidden!?

This bug makes it hard to find a way to code a hideable UI panel.
There're workarounds but they're not easy to find as the docs
don't shed light on it.

  Workaround examples:

  1) remove Group2 after hiding, re-insert on show.
  2) resize Group2 to 0,0 upon hide, then resize again upon show.

It'd be great to have a simple and obvious way to do it.
 
 
#2 AlbrechtS
14:42 May 23, 2011
I can't replicate your problem. Your example program behaves well in my tests on Linux and Windows (G2 keeps its size). I also tried to comment the g3->size(...) lines, but still no luck. Did you upload the wrong demo program?  
 
#3 AlbrechtS
14:44 May 23, 2011
Side note to Matt: it is not clear if we have a bug or not. If yes, then its severity is minor, hence it shouldn't stop the next RC.  
 
#4 matt
15:47 May 23, 2011
This sounds incredibly familiar. I thought I fixed this three months ago?! Or it wasn't really a ug, or something. Boy, I am getting old :-/ .  
 
#5 chris
04:09 May 24, 2011
I can repeatably reproduce it with latest svn, but only when
following exactly this sequence:

- hide g2
- resize window vertically
- show g2
 
 
#6 ianmacarthur
05:15 May 24, 2011
I can reproduce it sometimes, using Chris's recipe, but not consistently. (On WinXP.)

There is something messed up in the resizing though, but I can't quite describe what.

I've never been a fan of Fl_Pack anyway...!
 
 
#7 jcid
05:44 May 24, 2011
Hi,

  I'm running on Ubuntu GNU/Linux, fltk-1.3-rc5, and re-checked
the uploaded program to be the right one (download/fresh compile).
 
  I wrote Matt about this a couple of months ago. Funny how he
also couldn't reproduce it in the first try, but succeeded later:

[Matt wrote:]
> [jcid wrote:]
> >  It's even possible to continue growing/shrinking using the same
> > trick. e.g.:
> >
> >  1.- start with a small window
> >  2.- hide "Group 2"
> >  3.- maximize window
> >  4.- show "Group2"
> >  5.- shrink window to original size
> >  6.- hide "Group 2"
> >  7.- maximize window
> >  8.- show "Group2"
> >
> >  Here, "Group 2" has grown near four times in height.
>
> OK,  now  I  see  something too. The maximizing did the trick. It
> seems  that  g2,  when  hidden,  lies  within  the  area  of  the
> resizable.  So  when  it  is  shown again, the entire "resizable"
> mechanics  are  messed  up. Now that I can replicate the issue, I
> will  fuz  around with it for a bit an let you know when I get an
> idea.  The  most  likely  correct  solution  will  be to manually
> recalculate  the  g3 position and sizes when you show or hide g2,
> and the call init_sizes().

  After a deeper analysis, he came with this detailed diagnose:

> [Matt wrote]
> OK,  I  think I am getting there: the gist of it is this: Fl_Pack
> does  not  have  a  resize() function at all, so resizing it will
> fall  back  to  Fl_Group::resize()  which  correctly  resizes all
> widgets, visible or not, to keep the integrity of the layout.
>
> Fl_Pack   however   recalculates   the   widget   layout   during
> Fl_Pack::draw().  At  this  point, Fl_Group::resize() has already
> resized  your  G2  because  it clearly is within the range of the
> resizable().
>
> I did the following changes in your code:
>
> static void b1_cb(Fl_Widget *w, void *data) {
>   Fl_Group *g2 = (Fl_Group *)data;
>
>   if (g2->visible()) {
>     g2->hide();
>     g3->resize(g2->x(), g2->y(), g3->w(), g3->h()+g2->h());
>     p1->init_sizes();
>     g2->window()->redraw();
>   }
> }
>
> static void b2_cb(Fl_Widget *w, void *data) {
>   Fl_Group *g2 = (Fl_Group *)data;
>
>   if (!g2->visible()) {
>     g3->resize(g3->x(), g3->y()+g2->h(), g3->w(), g3->h()-g2->h());
>     g2->show();
>     p1->init_sizes();
>     g2->window()->redraw();
>   }
> }
>
> An  also  added  a  resize  function to F_Pack. It is very simple
> because  Fl_Pack::draw()  does  the  actual  layout, as mentioned
> above.
>
> protected:
>   void draw();
>   void resize(int X, int Y, int W, int H) {
>     int dx = X-x(), dy = Y-y();
>     int dw = W-w(), dh = H-h();
>     Fl_Widget::resize(X, Y, W, H);
>     Fl_Widget *r = resizable();
>     if (r && r!=this && (dw || dh)) {
>       r->size(r->w()+dw, r->h()+dh);
>     }
>     // let redraw() do the rest of the layout process
>     if (dx || dy || dw || dh)
>       redraw();
>   }
>
>
> Maybe  we should propose to add this to Fl_Pack? This is the time
> to break such things, before we release 1.3!
>
> What do you think? Also, does this solve the issue?

  And yes it solved the issue, but OTOH, the workarounds were simpler,
and at this point it was clear that something was going wrong in
the resize mechanics of Fl_Pack.

  HTH
 
 
#8 matt
06:10 May 26, 2011
Sorry, now it's too late for such a major change in behavior. I will bump this with high priority though.  
 
#9 jcid
14:29 May 30, 2011
Hi,

  FWIW, it turns out that Fl_Group also does strange things upon
resize. The second attached program (gr_rsc.cc) shows this:

 1.- <start program>
 2.- hide g2
 3.- maximize window
 4.- show g2

  g2 has increased in height! Again, its height doesn't increase
upon maiximize when it is visible.

  I left init_sizes() calls commented in different parts of the
hide/show callback code. Enabling them by pairs produces weird effects.
I don't know which of these effects is intended, but I found no
reference to them in the docs, so at least some of them may be a bug.

  As Matt plans to fix this STR before rc7, the new example was uploaded
in the hope it helps the cause.
 
 
#10 AlbrechtS
08:31 Jan 20, 2023
Fl_Pack is *very* special WRT its resizing, and particularly resizing itself around its children and that this is done in its draw() method which makes it an uncommon widget in the FLTK environment.

The subject (aka "Summary") says: "Fl_Pack resizes hidden widgets, which it doesn't touch when visible."

That sounds like it a bug, but maybe it's a feature? What position and size should hidden widgets have? IMHO this sounds like an invalid or at least undefined usage of Fl_Pack. Hence we might want to document this behavior as a caveat, and that's it. We could also mention the workaround given in the original post.

Note that there is meanwhile Fl_Flex which does similar things and can (IIRC) correctly handle hidden widgets (I would need to check this to be sure, but I believe it should be able to do this). Maybe this can used to replace Fl_Pack in the user's project.

OTOH, if the main issue of resizing hidden widgets in unexpected ways could be resolved by small changes, then I'd be fine with that. Otherwise I'd suggest to close this issue.

@Matt: there's a citation of your analysis in comment #7. Can you tell if this leads to an easy solution of the main issue? If not, see above.

Note: I changed priority from High to Moderate. This is not a bug that should hold the release. I even thought about classifying it as "Low: documentation error or undocumented side-effect", but this would need further investigation (see my suggestions above).
 
 
#11 AlbrechtS
09:48 Jan 20, 2023
I tested Fl_Flex in the given context by modifying the first demo program https://www.fltk.org/strfiles/2639/rsz.cc and replacing Fl_Pack with Fl_Flex. Fl_Flex needs some layout hints if you want only one flexible (i.e. resizable) widget (usually all children are flexible). See uploaded file https://www.fltk.org/strfiles/2639/str2639_rsz_flex.cxx . Setting the layout is done like this:

  // Fl_Flex p1: set layout and end group

  p1->fixed(g1, 30);
  p1->fixed(g2, 30);
  p1->fixed(b1, 30);
  p1->fixed(b2, 30);
  p1->end();
  // p1->resizable(g3); // would be ignored by Fl_Flex

I also added a size_range():

  window->size_range(200, 60);

Using 60 lets you resize the window to a minimal height of 60 which hides all groups behind the buttons, but resizing works as designed. Hiding and showing the group g2 works as expected. :-)

IMHO Fl_Flex is superior to Fl_Pack in many ways and can replace Fl_Pack in cases where Fl_Pack doesn't work well by design. An even more flexible widget Fl_Grid will be added to FLTK 1.4.0 soon.
 
 
#12 AlbrechtS
10:45 Jan 20, 2023
Regarding comment #9 - the issue with Fl_Group resizing (gr_rsz.cc):

Fl_Group resizes hidden widgets as well. This is correct because you can for instance switch widgets in the same place like in Fl_Tabs where always only one group is shown and all other groups (children) are hidden.

When your program hides g2 and resizes g3 to occupy its space, then g2 is hidden "behind" the area of g3 which is the resizable. Hence g2 is resized when the window is maximized. When you then show g2 and resize g3 by the *current* height of g2, then you see the *resized* height of g2. This is technically correct and as designed.

To fix this in your application (i.e. in the demo program) you can for instance resize g2 to zero height after hiding it. Then it is not in the range of the resizable and not resized when the window is maximized. However, its "original" size is lost (now zero). Hence you need to use the "known" original height of g2 to restore it before "freeing" the space by resizing g3 (using g2->h()). OTOH you could use the constant, known height of g2 (30) in both resizing operations.

Note also that init_sizes() is *required* after you rearrange children within an Fl_Group widget: I removed obsolete statements and used init_sizes() where appropriate.

Please see my working solution https://www.fltk.org/strfiles/2639/str2639_rsz_gr.cxx for the Fl_Group resizing issue mentioned in comment #9.

Long story, short: you need to *know* the original height of g2 to restore it after resizing, this can't be avoided. At least this is what Fl_Group provides with its proportional resizing algorithm. You may write your own group widget that stores the initial width/height of some or all of its children if you need to do such things.

Sounds complicated? Yes, some knowledge of the intrinsics of resizing is required to know what's going on and why it does what it does.

Too complicated? There's Fl_Flex (since 1.4.0) that can help with a much shorter program without knowing all that and without manually resizing widgets.

Summary: Fl_Group resizing works as designed.
 
 
#13 AlbrechtS
11:01 Jan 20, 2023
Note to devs (particularly Matt): The OP is unreachable, mails to him bounce, i.e. we can't expect a reaction unless he's watching this more than 10 years old STR.


That said, I propose to close this STR w/Resolution.


Matt, if you want to pursue the only open point - adding Fl_Pack::resize() as described above - then I'm leaving this decision up to you as the STR assignee, otherwise please close. Everything else is IMHO resolved.
 
 
#14 matt
07:15 Jan 23, 2023
Fixed in Git repository.

tl;dr I fixed this by overriding Fl_Pack::resize() to go around the side effects of Fl_Group::resize()

I also fixed some FLUID issues around Fl_Pack and cleaned up the source code a little bit.

There is quite a big issue with Fl_Pack when drawing. It's basically impossible to set any frame of box type without messing everything up and making things unreadable. But that is some fun for another day.
 
 
#15 AlbrechtS
15:09 Jan 23, 2023
Closed.  
     

Return to Bugs & Features ]

 
 

Comments are owned by the poster. All other content is copyright 1998-2024 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.