diff --git a/documentation/src/resize-example5a.png b/documentation/src/resize-example5a.png new file mode 100644 index 0000000000..0bb1706884 Binary files /dev/null and b/documentation/src/resize-example5a.png differ diff --git a/documentation/src/resize-example5b.png b/documentation/src/resize-example5b.png new file mode 100644 index 0000000000..165a2c43ec Binary files /dev/null and b/documentation/src/resize-example5b.png differ diff --git a/documentation/src/resize-example5c.png b/documentation/src/resize-example5c.png new file mode 100644 index 0000000000..78a96f6359 Binary files /dev/null and b/documentation/src/resize-example5c.png differ diff --git a/documentation/src/resize.dox b/documentation/src/resize.dox index 348625cf97..c3b30daf97 100644 --- a/documentation/src/resize.dox +++ b/documentation/src/resize.dox @@ -19,11 +19,11 @@ resizing behavior of that group is determined by its group = new Fl_Group(xg, yg, wg, hg, "No Resizing"); child1 = new Fl_Box(xb, yb, wb, hb, "B"); // or other widget type . . . - group->resizable(0); // no resizing + group->resizable((Fl_Widget*)0); // no resizing group->end() \endcode -The \p resizable may be set to zero, +The \p resizable may be set to the NULL pointer, which means that the group will not resize. Note that this is the default behavior for Fl_Window and Fl_Pack derived widgets, and therefore the programmer must explicitly set @@ -125,7 +125,7 @@ Setting the \p resizable to be the icon box won't give us what we want: The message text area would be the logical choice so that the user can expand the dialog to see if there is more of an explanation below -the short error message. This results in the behaviour shown in the +the short error message. This results in the behavior shown in the diagram below. \image html resize-example3b.png "Resizing dialog example (b)" @@ -189,6 +189,91 @@ It might take some thought to achieve exactly what you want and sometimes it is necessary to introduce parallel hierarchies in order to get widgets in different groups to resize together. +Imagine you have a group containing three widgets in a row, +and you want the widget in the middle to stay the same size +when the group is stretched and the ones on either side and +the padding between them to resize symmetrically. +As described earlier, the default resizing behavior for a group +results in proportional resizing of the child widgets (and also +of the margins and padding between them) as shown below, which +is clearly not what you want. + +\image html resize-example5a.png "Resizing a row of widgets (a)" +\image latex resize-example5a.png "Resizing a row of widgets (a)" width=12cm + +Simply adding a group around A and B and setting its \p resizable +to A, as in the previous btn-input example, will mean that B stays +the same size, but the other widgets won't resize symmetrically, +so what else is needed? +It isn't immediately obvious how to solve this problem, even for +experienced FLTK users. +This is possibly because users are generally advised to design +widgets so that they don't overlap. + +Albrecht Schlosser proposed an innovative technique that involves +an invisible box that deliberately overlaps others to achieve the +desired behavior. +For the current example, this means inserting two new groups +into the existing group and adding a hidden resizable widget. + +The first group, shown in red below, extends from the left +edge of the parent group to the middle of the gap between +boxes B and C on the right. +This first group contains boxes A and B, +where A is the first group's \p resizable attribute. + +The second group, shown in blue, extends from the right edge +of the first group to the right edge of the parent group. +This second group contains box C, where C is +the second group's \p resizable. + +The extra box widget is added to the parent group +and is set as the group's \p resizable. +The three \p resizable widgets are shown in yellow. + +The clever bit is that this extra box widget is not horizontally +aligned with any of the existing groups and widgets in the usual +way, but instead overlaps the right and left parts of the two new +groups by the same small amount, which means that its midpoint +is aligned with the edge between the groups. + +Note that, for clarity, the height of the original group has +been increased to allow space for the additional annotation +and to highlight the extra resizable box in the extra space +at the bottom of the group. +This is fine for the horizontal-only resizing shown here, but +means that widgets A, B and C will never change height because +the extra resizable box does not overlap them vertically. +Only the padding below them will be resized. + +\image html resize-example5b.png "Resizing a row of widgets (b)" +\image latex resize-example5b.png "Resizing a row of widgets (b)" width=12cm + +In a real application, you probably want to allow widgets A, +B and C to resize vertically while the height of any padding +or widgets above or below remains fixed, so the extra resizable +box has to lie within the height of widgets A, B and C. +Obviously after calling hide() on the box it is no +longer visible, and may therefore be the same height as the +other widgets, or a fraction of the height, as shown below. + +\image html resize-example5c.png "Resizing a row of widgets (c)" +\image latex resize-example5c.png "Resizing a row of widgets (c)" width=12cm + +To summarize the key points of the new technique: + +\li The new resizable widget must overlap the widgets on each + side by exactly the same amount. + +\li The width of the new resizable widget is not fixed, but should + probably be a relatively small value to avoid potential problems. + +\li The total width of the two new groups must equal the width + of the existing group and there can be no offsets or gaps + between them because margins and gaps will affect the + resizing behavior. + +\li The same principles apply to vertical resizing. \htmlonly
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 160efe21a0..1ae9319107 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -126,6 +126,9 @@ CREATE_EXAMPLE (resize-example3b "resize-example3b.cxx;resize-arrows.cxx" fltk) CREATE_EXAMPLE (resize-example3c "resize-example3c.cxx;resize-arrows.cxx" fltk) CREATE_EXAMPLE (resize-example4a "resize-example4a.cxx;resize-arrows.cxx" fltk) CREATE_EXAMPLE (resize-example4b "resize-example4b.cxx;resize-arrows.cxx" fltk) +CREATE_EXAMPLE (resize-example5a "resize-example5a.cxx;resize-arrows.cxx" fltk) +CREATE_EXAMPLE (resize-example5b "resize-example5b.cxx;resize-arrows.cxx" fltk) +CREATE_EXAMPLE (resize-example5c "resize-example5c.cxx;resize-arrows.cxx" fltk) CREATE_EXAMPLE (rotated_text rotated_text.cxx fltk) CREATE_EXAMPLE (scroll scroll.cxx fltk) CREATE_EXAMPLE (subwindow subwindow.cxx fltk) diff --git a/test/demo.menu b/test/demo.menu index f53b0ede33..c865fe5d4c 100644 --- a/test/demo.menu +++ b/test/demo.menu @@ -106,3 +106,5 @@ @ir:Example\n3c:resize-example3c @ir:Example\n4a:resize-example4a @ir:Example\n4b:resize-example4b + @ir:Example\n5a:resize-example5a + @ir:Example\n5b:resize-example5b diff --git a/test/makedepend b/test/makedepend index 0a24d86035..3eac520e75 100644 --- a/test/makedepend +++ b/test/makedepend @@ -1794,6 +1794,51 @@ resize-example4b.o: ../FL/Fl_Widget.H resize-example4b.o: ../FL/Fl_Window.H resize-example4b.o: ../FL/platform_types.h resize-example4b.o: resize-arrows.h +resize-example5a.o: ../FL/abi-version.h +resize-example5a.o: ../FL/Enumerations.H +resize-example5a.o: ../FL/Fl.H +resize-example5a.o: ../FL/Fl_Bitmap.H +resize-example5a.o: ../FL/Fl_Box.H +resize-example5a.o: ../FL/Fl_Double_Window.H +resize-example5a.o: ../FL/Fl_Export.H +resize-example5a.o: ../FL/Fl_Group.H +resize-example5a.o: ../FL/Fl_Image.H +resize-example5a.o: ../FL/fl_types.h +resize-example5a.o: ../FL/fl_utf8.h +resize-example5a.o: ../FL/Fl_Widget.H +resize-example5a.o: ../FL/Fl_Window.H +resize-example5a.o: ../FL/platform_types.h +resize-example5a.o: resize-arrows.h +resize-example5b.o: ../FL/abi-version.h +resize-example5b.o: ../FL/Enumerations.H +resize-example5b.o: ../FL/Fl.H +resize-example5b.o: ../FL/Fl_Bitmap.H +resize-example5b.o: ../FL/Fl_Box.H +resize-example5b.o: ../FL/Fl_Double_Window.H +resize-example5b.o: ../FL/Fl_Export.H +resize-example5b.o: ../FL/Fl_Group.H +resize-example5b.o: ../FL/Fl_Image.H +resize-example5b.o: ../FL/fl_types.h +resize-example5b.o: ../FL/fl_utf8.h +resize-example5b.o: ../FL/Fl_Widget.H +resize-example5b.o: ../FL/Fl_Window.H +resize-example5b.o: ../FL/platform_types.h +resize-example5b.o: resize-arrows.h +resize-example5c.o: ../FL/abi-version.h +resize-example5c.o: ../FL/Enumerations.H +resize-example5c.o: ../FL/Fl.H +resize-example5c.o: ../FL/Fl_Bitmap.H +resize-example5c.o: ../FL/Fl_Box.H +resize-example5c.o: ../FL/Fl_Double_Window.H +resize-example5c.o: ../FL/Fl_Export.H +resize-example5c.o: ../FL/Fl_Group.H +resize-example5c.o: ../FL/Fl_Image.H +resize-example5c.o: ../FL/fl_types.h +resize-example5c.o: ../FL/fl_utf8.h +resize-example5c.o: ../FL/Fl_Widget.H +resize-example5c.o: ../FL/Fl_Window.H +resize-example5c.o: ../FL/platform_types.h +resize-example5c.o: resize-arrows.h resize.o: ../FL/abi-version.h resize.o: ../FL/Enumerations.H resize.o: ../FL/Fl.H diff --git a/test/resize-example5a.cxx b/test/resize-example5a.cxx new file mode 100644 index 0000000000..e3e8b77091 --- /dev/null +++ b/test/resize-example5a.cxx @@ -0,0 +1,97 @@ +// +// Resize example for use in the Fast Light Tool Kit (FLTK) documentation. +// +// See Article #415: How does resizing work? +// https://www.fltk.org/articles.php?L415 +// +// Copyright 1998-2020 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// https://www.fltk.org/COPYING.php +// +// Please see the following page on how to report bugs and issues: +// +// https://www.fltk.org/bugs.php +// + +#include "resize-arrows.h" +#include + +// window, simplex and arrow dimensions +int TLx = 35, TRx = 320, TLw = 260, Ww = 620; +int TLy = 35, LGy = 100, TLh = 65, LGh = 70, LAh = 35, Wh = 175; + +Fl_Double_Window *window = 0; + +class Simplex : public Fl_Group { +public: + Simplex(int X, int Y, int W, int H, const char *T = 0); + Fl_Box *m_boxA, *m_boxB, *m_boxC; + Fl_Group *m_group; +}; + +Simplex::Simplex(int X, int Y, int W, int H, const char *T) + : Fl_Group(X, Y, W, H, T) { + this->box(FL_UP_BOX); + m_group = new Fl_Group(X + 10, Y + 10, 240, 45); + m_group->box(FL_UP_BOX); + m_boxA = new Fl_Box(X + 20, Y + 20, 80, 25, "A"); + m_boxA->box(FL_UP_BOX); + m_boxB = new Fl_Box(X + 110, Y + 20, 40, 25, "B"); + m_boxB->box(FL_UP_BOX); + m_boxC = new Fl_Box(X + 160, Y + 20, 80, 25, "C"); + m_boxC->box(FL_UP_BOX); + m_group->color(FL_YELLOW); + m_group->end(); + this->resizable(m_group); + this->end(); +} + +class Resizables : public Fl_Group { +public: + Resizables(int X, int Y, int W, int H, const char *T = 0); + Simplex *TL, *TR; // top left, top right + Harrow *LA, *RA; // left arrow, right arrow +}; + +Resizables::Resizables(int X, int Y, int W, int H, const char *T) + : Fl_Group(X, Y, W, H, T) { + TL = new Simplex(X + TLx, Y + TLy, TLw, TLh, "Original"); + TL->align(FL_ALIGN_TOP_LEFT); + + TR = new Simplex(X + TRx, Y + TLy, TLw, TLh, "Horizontally Resized"); + TR->align(FL_ALIGN_TOP_LEFT); + + Fl_Group *LG = new Fl_Group(X + TLx, Y + LGy, TLw, LGh); + LG->box(FL_NO_BOX); + LG->color(FL_WHITE); + LA = new Harrow(TL->m_group->x(), LG->y(), TL->m_group->w(), LAh, "Initial\nwidth"); + LG->resizable(LA); + LG->end(); + + Fl_Group *RG = new Fl_Group(X + TRx, Y + LGy, TLw, LGh); + RG->box(FL_NO_BOX); + RG->color(FL_WHITE); + RA = new Harrow(TR->m_group->x(), RG->y(), TR->m_group->w(), LAh, "Resized\nwidth"); + RG->resizable(RA); + RG->end(); + + this->resizable(TR); + this->end(); +} + + +int main(int argc, char **argv) { + window = new Fl_Double_Window(Ww, Wh, "resize-example5a"); + window->color(FL_WHITE); + Resizables *resizables = new Resizables(0, 0, Ww, Wh); + window->end(); + window->resizable(resizables); + window->size_range(Ww, Wh); + window->show(argc, argv); + window->size(Ww + 90, Wh); + return Fl::run(); +} diff --git a/test/resize-example5b.cxx b/test/resize-example5b.cxx new file mode 100644 index 0000000000..62680b6dc7 --- /dev/null +++ b/test/resize-example5b.cxx @@ -0,0 +1,122 @@ +// +// Resize example for use in the Fast Light Tool Kit (FLTK) documentation. +// +// See Article #415: How does resizing work? +// https://www.fltk.org/articles.php?L415 +// +// Copyright 1998-2020 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// https://www.fltk.org/COPYING.php +// +// Please see the following page on how to report bugs and issues: +// +// https://www.fltk.org/bugs.php +// + +#include "resize-arrows.h" +#include + +// window, simplex and arrow dimensions +int TLx = 35, TRx = 320, TLw = 260, Ww = 620; +int TLy = 35, LGy = 125, TLh = 90, LGh = 70, LAh = 35, Wh = 200; + +Fl_Double_Window *window = 0; + +class Simplex : public Fl_Group { +public: + Simplex(int X, int Y, int W, int H, const char *T = 0); + Fl_Box *m_boxA, *m_boxB, *m_boxC, *m_boxI; + Fl_Group *m_group, *m_groupL, *m_groupR; +}; + +Simplex::Simplex(int X, int Y, int W, int H, const char *T) + : Fl_Group(X, Y, W, H, T) { + this->box(FL_UP_BOX); + m_group = new Fl_Group(X + 10, Y + 10, 240, 70); + m_group->box(FL_UP_BOX); + + m_groupL = new Fl_Group(X + 10, Y + 15, 145, 35, "AB group"); + m_groupL->align(FL_ALIGN_BOTTOM_LEFT); + m_groupL->box(FL_UP_BOX); + m_groupL->color(FL_RED); + m_groupL->labelcolor(FL_RED); + m_boxA = new Fl_Box(X + 20, Y + 20, 80, 25, "A"); + m_boxA->box(FL_UP_BOX); + m_boxA->color(FL_YELLOW); + m_boxB = new Fl_Box(X + 110, Y + 20, 40, 25, "B"); + m_boxB->box(FL_UP_BOX); + m_groupL->resizable(m_boxA); + m_groupL->end(); + + m_groupR = new Fl_Group(X + 155, Y + 15, 95, 35, "C group"); + m_groupR->align(FL_ALIGN_BOTTOM_RIGHT); + m_groupR->box(FL_UP_BOX); + m_groupR->color(FL_BLUE); + m_groupR->labelcolor(FL_BLUE); + m_boxC = new Fl_Box(X + 160, Y + 20, 80, 25, "C"); + m_boxC->box(FL_UP_BOX); + m_boxC->color(FL_YELLOW); + m_groupR->resizable(m_boxC); + m_groupR->end(); + + int d = 20; + m_boxI = new Fl_Box(X + 155 - d, Y + 55, 2 * d, 10); + m_boxI->box(FL_UP_BOX); + m_boxI->color(FL_YELLOW); + + m_group->resizable(m_boxI); + m_group->end(); + + this->resizable(m_group); + this->end(); +} + +class Resizables : public Fl_Group { +public: + Resizables(int X, int Y, int W, int H, const char *T = 0); + Simplex *TL, *TR; // top left, top right + Harrow *LA, *RA; // left arrow, right arrow +}; + +Resizables::Resizables(int X, int Y, int W, int H, const char *T) + : Fl_Group(X, Y, W, H, T) { + TL = new Simplex(X + TLx, Y + TLy, TLw, TLh, "Original"); + TL->align(FL_ALIGN_TOP_LEFT); + + TR = new Simplex(X + TRx, Y + TLy, TLw, TLh, "Horizontally Resized"); + TR->align(FL_ALIGN_TOP_LEFT); + + Fl_Group *LG = new Fl_Group(X + TLx, Y + LGy, TLw, LGh); + LG->box(FL_NO_BOX); + LG->color(FL_WHITE); + LA = new Harrow(TL->m_boxI->x(), LG->y(), TL->m_boxI->w(), LAh, "Initial\nwidth"); + LG->resizable(LA); + LG->end(); + + Fl_Group *RG = new Fl_Group(X + TRx, Y + LGy, TLw, LGh); + RG->box(FL_NO_BOX); + RG->color(FL_WHITE); + RA = new Harrow(TR->m_boxI->x(), RG->y(), TR->m_boxI->w(), LAh, "Resized\nwidth"); + RG->resizable(RA); + RG->end(); + + this->resizable(TR); + this->end(); +} + + +int main(int argc, char **argv) { + window = new Fl_Double_Window(Ww, Wh, "resize-example5b"); + window->color(FL_WHITE); + Resizables *resizables = new Resizables(0, 0, Ww, Wh); + window->end(); + window->resizable(resizables); + window->size_range(Ww, Wh); + window->show(argc, argv); + window->size(Ww + 90, Wh); + return Fl::run(); +} diff --git a/test/resize-example5c.cxx b/test/resize-example5c.cxx new file mode 100644 index 0000000000..b824009fe5 --- /dev/null +++ b/test/resize-example5c.cxx @@ -0,0 +1,114 @@ +// +// Resize example for use in the Fast Light Tool Kit (FLTK) documentation. +// +// See Article #415: How does resizing work? +// https://www.fltk.org/articles.php?L415 +// +// Copyright 1998-2020 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// https://www.fltk.org/COPYING.php +// +// Please see the following page on how to report bugs and issues: +// +// https://www.fltk.org/bugs.php +// + +#include "resize-arrows.h" +#include + +// window, simplex and arrow dimensions +int TLx = 35, TRx = 320, TLw = 260, Ww = 620; +int TLy = 35, LGy = 100, TLh = 65, LGh = 70, LAh = 35, Wh = 175; + +Fl_Double_Window *window = 0; + +class Simplex : public Fl_Group { +public: + Simplex(int X, int Y, int W, int H, const char *T = 0); + Fl_Box *m_boxA, *m_boxB, *m_boxC, *m_boxI; + Fl_Group *m_group, *m_groupL, *m_groupR; +}; + +Simplex::Simplex(int X, int Y, int W, int H, const char *T) + : Fl_Group(X, Y, W, H, T) { + this->box(FL_UP_BOX); + m_group = new Fl_Group(X + 10, Y + 10, 240, 45); + m_group->box(FL_UP_BOX); + + m_groupL = new Fl_Group(X + 10, Y + 15, 145, 35); + m_groupL->box(FL_NO_BOX); + m_boxA = new Fl_Box(X + 20, Y + 20, 80, 25, "A"); + m_boxA->box(FL_UP_BOX); + m_boxB = new Fl_Box(X + 110, Y + 20, 40, 25, "B"); + m_boxB->box(FL_UP_BOX); + m_groupL->resizable(m_boxA); + m_groupL->end(); + + m_groupR = new Fl_Group(X + 155, Y + 15, 95, 35); + m_groupR->box(FL_NO_BOX); + m_boxC = new Fl_Box(X + 160, Y + 20, 80, 25, "C"); + m_boxC->box(FL_UP_BOX); + m_groupR->resizable(m_boxC); + m_groupR->end(); + + int d = 20; + m_boxI = new Fl_Box(X + 155 - d, Y + 40, 2 * d, 5); + m_boxI->box(FL_FLAT_BOX); + m_boxI->color(FL_YELLOW); + + m_group->resizable(m_boxI); + m_group->end(); + + this->resizable(m_group); + this->end(); +} + +class Resizables : public Fl_Group { +public: + Resizables(int X, int Y, int W, int H, const char *T = 0); + Simplex *TL, *TR; // top left, top right + Harrow *LA, *RA; // left arrow, right arrow +}; + +Resizables::Resizables(int X, int Y, int W, int H, const char *T) + : Fl_Group(X, Y, W, H, T) { + TL = new Simplex(X + TLx, Y + TLy, TLw, TLh, "Original"); + TL->align(FL_ALIGN_TOP_LEFT); + + TR = new Simplex(X + TRx, Y + TLy, TLw, TLh, "Horizontally Resized"); + TR->align(FL_ALIGN_TOP_LEFT); + + Fl_Group *LG = new Fl_Group(X + TLx, Y + LGy, TLw, LGh); + LG->box(FL_NO_BOX); + LG->color(FL_WHITE); + LA = new Harrow(TL->m_boxI->x(), LG->y(), TL->m_boxI->w(), LAh, "Initial\nwidth"); + LG->resizable(LA); + LG->end(); + + Fl_Group *RG = new Fl_Group(X + TRx, Y + LGy, TLw, LGh); + RG->box(FL_NO_BOX); + RG->color(FL_WHITE); + RA = new Harrow(TR->m_boxI->x(), RG->y(), TR->m_boxI->w(), LAh, "Resized\nwidth"); + RG->resizable(RA); + RG->end(); + + this->resizable(TR); + this->end(); +} + + +int main(int argc, char **argv) { + window = new Fl_Double_Window(Ww, Wh, "resize-example5c"); + window->color(FL_WHITE); + Resizables *resizables = new Resizables(0, 0, Ww, Wh); + window->end(); + window->resizable(resizables); + window->size_range(Ww, Wh); + window->show(argc, argv); + window->size(Ww + 90, Wh); + return Fl::run(); +}