diff --git a/FL/Fl_Tile.H b/FL/Fl_Tile.H index 2792c4150..f794a9c62 100644 --- a/FL/Fl_Tile.H +++ b/FL/Fl_Tile.H @@ -3,10 +3,10 @@ // // Tile header file for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2010 by Bill Spitzak and others. +// Copyright 1998-2014 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 +// the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // http://www.fltk.org/COPYING.php @@ -16,71 +16,19 @@ // http://www.fltk.org/str.php // -/* \file - Fl_Tile widget . */ - #ifndef Fl_Tile_H #define Fl_Tile_H #include "Fl_Group.H" -/** - The Fl_Tile class lets you resize the children by dragging - the border between them: - -

\image html Fl_Tile.png

- \image latex Fl_Tile.png "Fl_Tile" width=4cm - -

For the tiling to work correctly, the children of an - Fl_Tile must cover the entire area of the widget, but not - overlap. This means that all children must touch each - other at their edges, and no gaps can't be left inside the - Fl_Tile. - -

Fl_Tile does not normailly draw any graphics of its own. - The "borders" which can be seen in the snapshot above - are actually part of the children. Their boxtypes have been set - to FL_DOWN_BOX creating the impression of - "ridges" where the boxes touch. What you see are - actually two adjacent FL_DOWN_BOX's drawn next to each - other. All neighboring widgets share the same edge - the widget's - thick borders make it appear as though the widgets aren't actually - touching, but they are. If the edges of adjacent widgets do not - touch, then it will be impossible to drag the corresponding - edges.

- -

Fl_Tile allows objects to be resized to zero dimensions. - To prevent this you can use the resizable() to limit where - corners can be dragged to.

- -

Even though objects can be resized to zero sizes, they must - initially have non-zero sizes so the Fl_Tile can figure out - their layout. If desired, call position() after creating the - children but before displaying the window to set the borders where you - want. - -

Note on resizable(Fl_Widget &w) : - The "resizable" child widget (which should be invisible) limits where the - border can be dragged to. If you don't set it, it will be possible to - drag the borders right to the edge, and thus resize objects on the edge - to zero width or height. The resizable() widget is not - resized by dragging any borders. See also void Fl_Group::resizable(Fl_Widget &w) - +/* + The Fl_Tile class lets you resize its children by dragging + the border between them. */ + class FL_EXPORT Fl_Tile : public Fl_Group { public: int handle(int); - /** - Creates a new Fl_Tile widget using the given position, size, - and label string. The default boxtype is FL_NO_BOX. - -

The destructor also deletes all the children. This allows a - whole tree to be deleted at once, without having to keep a pointer to - all the children in the user code. A kludge has been done so the - Fl_Tile and all of it's children can be automatic (local) - variables, but you must declare the Fl_Tile first, so - that it is destroyed last. - */ Fl_Tile(int X,int Y,int W,int H,const char*l=0); void resize(int, int, int, int); void position(int, int, int, int); diff --git a/documentation/src/Fl_Tile.png b/documentation/src/Fl_Tile.png index eafa59c99..20d90deed 100644 Binary files a/documentation/src/Fl_Tile.png and b/documentation/src/Fl_Tile.png differ diff --git a/src/Fl_Tile.cxx b/src/Fl_Tile.cxx index f89edcdbc..be231fab0 100644 --- a/src/Fl_Tile.cxx +++ b/src/Fl_Tile.cxx @@ -3,10 +3,10 @@ // // Tile widget for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2010 by Bill Spitzak and others. +// Copyright 1998-2014 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 +// the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // http://www.fltk.org/COPYING.php @@ -16,23 +16,81 @@ // http://www.fltk.org/str.php // +/** + \class Fl_Tile -// Group of 2 or 4 "tiles" that can be resized by dragging border -// The size of the first child determines where the resize border is. -// The resizebox is used to limit where the border can be dragged to. + The Fl_Tile class lets you resize its children by dragging + the border between them. + + \image html Fl_Tile.png + \image latex Fl_Tile.png "Fl_Tile" width=5cm + + For the tiling to work correctly, the children of an Fl_Tile must + cover the entire area of the widget, but not overlap. + This means that all children must touch each other at their edges, + and no gaps can be left inside the Fl_Tile. + + Fl_Tile does not normally draw any graphics of its own. + The "borders" which can be seen in the snapshot above are actually + part of the children. Their boxtypes have been set to FL_DOWN_BOX + creating the impression of "ridges" where the boxes touch. What + you see are actually two adjacent FL_DOWN_BOX's drawn next to each + other. All neighboring widgets share the same edge - the widget's + thick borders make it appear as though the widgets aren't actually + touching, but they are. If the edges of adjacent widgets do not + touch, then it will be impossible to drag the corresponding edges. + + Fl_Tile allows objects to be resized to zero dimensions. + To prevent this you can use the resizable() to limit where + corners can be dragged to. For more information see note below. + + Even though objects can be resized to zero sizes, they must initially + have non-zero sizes so the Fl_Tile can figure out their layout. + If desired, call position() after creating the children but before + displaying the window to set the borders where you want. + + Note on resizable(Fl_Widget &w): + The "resizable" child widget (which should be invisible) limits where + the borders can be dragged to. All dragging will be limited inside the + resizable widget's borders. If you don't set it, it will be possible + to drag the borders right to the edges of the Fl_Tile widget, and thus + resize objects on the edges to zero width or height. When the entire + Fl_Tile widget is resized, the resizable() widget will keep its border + distance to all borders the same (this is normal resize behavior), so + that you can effectively set a border width that will never change. + + Note: + You can still resize widgets \b inside the resizable() to zero width and/or + height, i.e. box \b 2b above to zero width and box \b 3a to zero height. + + \see void Fl_Group::resizable(Fl_Widget &w) + + Example for resizable with 20 pixel border distance: + \code + int dx = 20, dy = dx; + Fl_Tile tile(50,50,300,300); + // ... create widgets inside tile (see test/tile.cxx) ... + // create resizable() box + Fl_Box r(tile.x()+dx,tile.y()+dy,tile.w()-2*dx,tile.h()-2*dy); + tile.resizable(r); + tile.end(); + \endcode + + See also the complete example program in test/tile.cxx. +*/ #include #include #include #include -// Drag the edges that were initially at oldx,oldy to newx,newy: -// pass zero as oldx or oldy to disable drag in that direction: -/** - Drag the intersection at from_x,from_y to to_x,to_y. +/** + Drags the intersection at (\p oldx,\p oldy) to (\p newx,\p newy). This redraws all the necessary children. + + Pass zero as \p oldx or \p oldy to disable drag in that direction. */ -void Fl_Tile::position(int oix, int oiy, int newx, int newy) { +void Fl_Tile::position(int oldx, int oldy, int newx, int newy) { Fl_Widget*const* a = array(); int *p = sizes(); p += 8; // skip group & resizable's saved size @@ -41,28 +99,43 @@ void Fl_Tile::position(int oix, int oiy, int newx, int newy) { if (o == resizable()) continue; int X = o->x(); int R = X+o->w(); - if (oix) { + if (oldx) { int t = p[0]; - if (t == oix || (t>oix && Xnewx) ) X = newx; + if (t == oldx || (t>oldx && Xnewx) ) X = newx; t = p[1]; - if (t == oix || (t>oix && Rnewx) ) R = newx; + if (t == oldx || (t>oldx && Rnewx) ) R = newx; } int Y = o->y(); int B = Y+o->h(); - if (oiy) { + if (oldy) { int t = p[2]; - if (t == oiy || (t>oiy && Ynewy) ) Y = newy; + if (t == oldy || (t>oldy && Ynewy) ) Y = newy; t = p[3]; - if (t == oiy || (t>oiy && Bnewy) ) B = newy; + if (t == oldy || (t>oldy && Bnewy) ) B = newy; } o->damage_resize(X,Y,R-X,B-Y); } } -// move the lower-right corner (sort of): +/** + Resizes the Fl_Tile widget and its children. + + Fl_Tile implements its own resize() method. It does not use + Fl_Group::resize() to resize itself and its children. + + Enlarging works by just moving the lower-right corner and resizing + the bottom and right border widgets accordingly. + + Shrinking the Fl_Tile works in the opposite way by shrinking + the bottom and right border widgets, unless they are reduced to zero + width or height, resp. or to their minimal sizes defined by the + resizable() widget. In this case other widgets will be shrunk as well. + + See the Fl_Tile class documentation about how the resizable() works. +*/ + void Fl_Tile::resize(int X,int Y,int W,int H) { - //Fl_Group::resize(X, Y, W, H); - //return; + // remember how much to move the child widgets: int dx = X-x(); int dy = Y-y(); @@ -71,11 +144,13 @@ void Fl_Tile::resize(int X,int Y,int W,int H) { int *p = sizes(); // resize this (skip the Fl_Group resize): Fl_Widget::resize(X,Y,W,H); - // find bottom-right of resiable: - int OR = p[5]; - int NR = X+W-(p[1]-OR); - int OB = p[7]; - int NB = Y+H-(p[3]-OB); + + // find bottom-right corner of resizable: + int OR = p[5]; // old right border + int NR = X+W-(p[1]-OR); // new right border + int OB = p[7]; // old bottom border + int NB = Y+H-(p[3]-OB); // new bottom border + // move everything to be on correct side of new resizable: Fl_Widget*const* a = array(); p += 8; @@ -90,7 +165,7 @@ void Fl_Tile::resize(int X,int Y,int W,int H) { if (*p++ >= OB) yy += dh; else if (yy > NB) yy = NB; if (*p++ >= OB) B += dh; else if (B > NB) B = NB; o->resize(xx,yy,R-xx,B-yy); - // do *not* call o->redraw() here! If you do, and the tile is inside a + // do *not* call o->redraw() here! If you do, and the tile is inside a // scroll, it'll set the damage areas wrong for all children! } } @@ -200,9 +275,22 @@ int Fl_Tile::handle(int event) { return Fl_Group::handle(event); } +/** + Creates a new Fl_Tile widget using the given position, size, + and label string. The default boxtype is FL_NO_BOX. -Fl_Tile::Fl_Tile(int X,int Y,int W,int H,const char*l) -: Fl_Group(X,Y,W,H,l) + The destructor also deletes all the children. This allows a + whole tree to be deleted at once, without having to keep a pointer to + all the children in the user code. A kludge has been done so the + Fl_Tile and all of its children can be automatic (local) + variables, but you must declare the Fl_Tile first, so + that it is destroyed last. + + \see class Fl_Group +*/ + +Fl_Tile::Fl_Tile(int X,int Y,int W,int H,const char*l) +: Fl_Group(X,Y,W,H,l) { } diff --git a/test/tile.cxx b/test/tile.cxx index 088ce08b5..614fd7c67 100644 --- a/test/tile.cxx +++ b/test/tile.cxx @@ -3,7 +3,7 @@ // // Tile test program for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2010 by Bill Spitzak and others. +// Copyright 1998-2014 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 @@ -27,19 +27,23 @@ int main(int argc, char** argv) { Fl_Double_Window window(300,300); window.box(FL_NO_BOX); window.resizable(window); + + int dx = 20, dy = dx; // border width of resizable() - see below Fl_Tile tile(0,0,300,300); + Fl_Box box0(0,0,150,150,"0"); box0.box(FL_DOWN_BOX); box0.color(9); box0.labelsize(36); box0.align(FL_ALIGN_CLIP); + Fl_Double_Window w1(150,0,150,150,"1"); w1.box(FL_NO_BOX); - Fl_Box box1(0,0,150,150,"1\nThis is a\nchild\nwindow"); + Fl_Box box1(0,0,150,150,"1\nThis is a child window"); box1.box(FL_DOWN_BOX); box1.color(19); box1.labelsize(18); - box1.align(FL_ALIGN_CLIP); + box1.align(FL_ALIGN_CLIP|FL_ALIGN_INSIDE|FL_ALIGN_WRAP); w1.resizable(box1); w1.end(); @@ -49,6 +53,7 @@ int main(int argc, char** argv) { box2a.color(12); box2a.labelsize(36); box2a.align(FL_ALIGN_CLIP); + Fl_Box box2b(70,150,80,150,"2b"); box2b.box(FL_DOWN_BOX); box2b.color(13); @@ -62,22 +67,27 @@ int main(int argc, char** argv) { box3a.color(12); box3a.labelsize(36); box3a.align(FL_ALIGN_CLIP); + Fl_Box box3b(150,150+70,150,80,"3b"); box3b.box(FL_DOWN_BOX); box3b.color(13); box3b.labelsize(36); box3b.align(FL_ALIGN_CLIP); //tile3.end(); - - Fl_Box r(10,0,300-10,300-10); + + // create the symmetrical resize box with dx and dy pixels distance, resp. + // from the borders of the Fl_Tile widget + Fl_Box r(tile.x()+dx,tile.y()+dy,tile.w()-2*dx,tile.h()-2*dy); tile.resizable(r); // r.box(FL_BORDER_FRAME); tile.end(); window.end(); -#ifdef TEST_INACTIVE // test inactive case + +#ifdef TEST_INACTIVE // test inactive case tile.deactivate(); #endif + w1.show(); window.show(argc,argv); return Fl::run();