diff options
| author | Albrecht Schlosser <albrechts.fltk@online.de> | 2017-07-07 19:16:40 +0000 |
|---|---|---|
| committer | Albrecht Schlosser <albrechts.fltk@online.de> | 2017-07-07 19:16:40 +0000 |
| commit | 0c210ae8674b94163f6840bda75e25eedbc0d4d1 (patch) | |
| tree | ed3302c93aa25f6a69869885813ca045cbd2615d | |
| parent | 27d77364755328874e22bc47b91cc5ef9887e2fe (diff) | |
Introduce Fl_Group::bounds(), deprecate Fl_Group::sizes().
The new method Fl_Group::bounds() replaces Fl_Group::sizes() whose
internal array structure was not documented.
Fl_Group::bounds() uses the new and documented class Fl_Rect for its
internal structure.
src/Fl_Tile.cxx now uses bounds() instead of sizes().
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12302 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
| -rw-r--r-- | CHANGES | 4 | ||||
| -rw-r--r-- | FL/Fl_Group.H | 11 | ||||
| -rw-r--r-- | src/Fl_Group.cxx | 228 | ||||
| -rw-r--r-- | src/Fl_Tile.cxx | 53 |
4 files changed, 180 insertions, 116 deletions
@@ -18,6 +18,10 @@ Changes in FLTK 1.4.0 Released: ??? ?? 2017 New Features and Extensions - (add new items here) + - New method Fl_Group::bounds() replaces Fl_Group::sizes() which is now + deprecated. Fl_Group::bounds() uses the new class Fl_Rect that contains + widget coordinates and sizes x(), y(), w(), and h() (STR #3385). + Documentation for bounds() and its internal structure was added. - X11 platform: Added support for HiDPI displays and for rescaling any window at run-time under user control. Under the gnome desktop, FLTK applications detect the current gnome scaling factor and use it to scale all FLTK windows. diff --git a/FL/Fl_Group.H b/FL/Fl_Group.H index 8a6f8f6e1..8ab96c9a6 100644 --- a/FL/Fl_Group.H +++ b/FL/Fl_Group.H @@ -3,7 +3,7 @@ // // Group header file for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2010 by Bill Spitzak and others. +// Copyright 1998-2017 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 @@ -22,9 +22,8 @@ #ifndef Fl_Group_H #define Fl_Group_H -#ifndef Fl_Widget_H #include "Fl_Widget.H" -#endif +#include "Fl_Rect.H" /** The Fl_Group class is the FLTK container widget. It maintains @@ -44,7 +43,8 @@ class FL_EXPORT Fl_Group : public Fl_Widget { Fl_Widget* savedfocus_; Fl_Widget* resizable_; int children_; - int *sizes_; // remembered initial sizes of children + Fl_Rect *bounds_; // remembered initial sizes of children + int *sizes_; // remembered initial sizes of children (FLTK 1.3 compat.) int navigation(int); static Fl_Group *current_; @@ -59,7 +59,8 @@ protected: void draw_children(); void draw_outside_label(const Fl_Widget& widget) const ; void update_child(Fl_Widget& widget) const; - int *sizes(); + Fl_Rect *bounds(); + int *sizes(); // FLTK 1.3 compatibility public: diff --git a/src/Fl_Group.cxx b/src/Fl_Group.cxx index 769156540..34049a53d 100644 --- a/src/Fl_Group.cxx +++ b/src/Fl_Group.cxx @@ -72,7 +72,7 @@ void Fl_Group::end() {current_ = parent();} /** Returns the currently active group. - + The Fl_Widget constructor automatically does current()->add(widget) if this is not null. To prevent new widgets from being added to a group, call Fl_Group::current(0). @@ -81,7 +81,7 @@ Fl_Group *Fl_Group::current() {return current_;} /** Sets the current group. - \see Fl_Group::current() + \see Fl_Group::current() */ void Fl_Group::current(Fl_Group *g) {current_ = g;} @@ -363,7 +363,9 @@ Fl_Group::Fl_Group(int X,int Y,int W,int H,const char *l) array_ = 0; savedfocus_ = 0; resizable_ = this; - sizes_ = 0; // this is allocated when first resize() is done + bounds_ = 0; // this is allocated when first resize() is done + sizes_ = 0; // see bounds_ (FLTK 1.3 compatibility) + // Subclasses may want to construct child objects as part of their // constructor, so make sure they are add()'d to this object. // But you must end() the object! @@ -375,6 +377,12 @@ Fl_Group::Fl_Group(int X,int Y,int W,int H,const char *l) This method differs from the remove() method in that it affects all child widgets and deletes them from memory. + + The resizable() widget of the Fl_Group is set to the Fl_Group itself. + + \internal If the Fl_Group widget contains the Fl::focus() or the + Fl::pushed() widget these are set to sensible values (other widgets + or the Fl_Group widget itself). */ void Fl_Group::clear() { savedfocus_ = 0; @@ -382,9 +390,8 @@ void Fl_Group::clear() { init_sizes(); // we must change the Fl::pushed() widget, if it is one of - // the group's children. Otherwise fl_fix_focus() would send - // lots of events to children that are about to be deleted - // anyway. + // the group's children. Otherwise fl_fix_focus() would send lots + // of events to children that are about to be deleted anyway. Fl_Widget *pushed = Fl::pushed(); // save pushed() widget if (contains(pushed)) pushed = this; // set it to be the group, if it's a child @@ -431,11 +438,11 @@ void Fl_Group::clear() { The destructor <I>also deletes all the children</I>. This allows a whole tree to be deleted at once, without having to keep a pointer to all the children in the user code. - + It is allowed that the Fl_Group and all of its children are automatic (local) variables, but you must declare the Fl_Group \e first, so that it is destroyed last. - + If you add static or automatic (local) variables to an Fl_Group, then it is your responsibility to remove (or delete) all such static or automatic child widgets \e \b before destroying the group - otherwise the child @@ -493,7 +500,7 @@ void Fl_Group::add(Fl_Widget &o) {insert(o, children_);} This method differs from the clear() method in that it only affects a single widget and does not delete it from memory. - + \since FLTK 1.3.0 */ void Fl_Group::remove(int index) { @@ -502,7 +509,7 @@ void Fl_Group::remove(int index) { if (&o == savedfocus_) savedfocus_ = 0; if (o.parent_ == this) { // this should always be true o.parent_ = 0; - } + } // remove the widget from the group @@ -524,7 +531,7 @@ void Fl_Group::remove(int index) { This method differs from the clear() method in that it only affects a single widget and does not delete it from memory. - + \note If you have the child's index anyway, use remove(int index) instead, because this doesn't need a child lookup in the group's table of children. This can be much faster, if there are lots of @@ -536,83 +543,137 @@ void Fl_Group::remove(Fl_Widget &o) { if (i < children_) remove(i); } -//////////////////////////////////////////////////////////////// - -// Rather lame kludge here, I need to detect windows and ignore the -// changes to X,Y, since all children are relative to X,Y. That -// is why I check type(): - -// sizes array stores the initial positions of widgets as -// left,right,top,bottom quads. The first quad is the group, the -// second is the resizable (clipped to the group), and the -// rest are the children. This is a convenient order for the -// algorithm. If you change this be sure to fix Fl_Tile which -// also uses this array! - /** Resets the internal array of widget sizes and positions. The Fl_Group widget keeps track of the original widget sizes and - positions when resizing occurs so that if you resize a window back to its - original size the widgets will be in the correct places. If you rearrange - the widgets in your group, call this method to register the new arrangement - with the Fl_Group that contains them. - + positions when resizing occurs so that if you resize a window back to + its original size the widgets will be in the correct places. If you + rearrange the widgets in your group, call this method to register the + new arrangement with the Fl_Group that contains them. + If you add or remove widgets, this will be done automatically. - - \note The internal array of widget sizes and positions will be allocated and - filled when the next resize() occurs. - - \sa sizes() + + \note The internal array of widget sizes and positions will be allocated + and filled when the next resize() occurs. For more information on + the contents and structure of the bounds() array see bounds(). + + \see bounds() + \see sizes() (deprecated) */ void Fl_Group::init_sizes() { - delete[] sizes_; sizes_ = 0; + delete[] bounds_; + bounds_ = 0; + delete[] sizes_; // FLTK 1.3 compatibility + sizes_ = 0; // FLTK 1.3 compatibility } /** Returns the internal array of widget sizes and positions. - If the sizes() array does not exist, it will be allocated and filled + If the bounds() array does not exist, it will be allocated and filled with the current widget sizes and positions. - \note You should never need to use this method directly, unless you have - special needs to rearrange the children of a Fl_Group. Fl_Tile uses - this to rearrange its widget positions. - - \sa init_sizes() + The bounds() array stores the initial positions of widgets as Fl_Rect's. + The size of the array is children() + 2. + + - The first Fl_Rect is the group, + - the second is the resizable (clipped to the group), + - the rest are the children. + + This is a convenient order for the resize algorithm. + + If the group and/or the resizable() is a Fl_Window (or subclass) then + the x() and y() coordinates of their respective Fl_Rect's are zero. - \todo Should the internal representation of the sizes() array be documented? + \note You should never need to use this \e protected method directly, + unless you have special needs to rearrange the children of a + Fl_Group. Fl_Tile uses this to rearrange its widget positions. + + \returns Array of Fl_Rect's with widget positions and sizes. The + returned array is only valid until init_sizes() is called + or widgets are added to or removed from the group. + + \note The returned array should be considered read-only. Do not change + its contents. If you need to rearrange children in a group, do + so by resizing the children and call init_sizes(). + + \see init_sizes() + + \since FLTK 1.4.0 + + \internal If you change this be sure to fix Fl_Tile which also uses this array! */ -int* Fl_Group::sizes() { - if (!sizes_) { - int* p = sizes_ = new int[4*(children_+2)]; - // first thing in sizes array is the group's size: - if (type() < FL_WINDOW) {p[0] = x(); p[2] = y();} else {p[0] = p[2] = 0;} - p[1] = p[0]+w(); p[3] = p[2]+h(); +Fl_Rect* Fl_Group::bounds() { + if (!bounds_) { + Fl_Rect* p = bounds_ = new Fl_Rect[children_+2]; + // first thing in bounds array is the group's size: + if (as_window()) + p[0] = Fl_Rect(w(),h()); // x = y = 0 + else + p[0] = Fl_Rect(this); // next is the resizable's size: - p[4] = p[0]; // init to the group's size - p[5] = p[1]; - p[6] = p[2]; - p[7] = p[3]; + int left = p->x(); // init to the group's position and size + int top = p->y(); + int right = p->r(); + int bottom = p->b(); Fl_Widget* r = resizable(); if (r && r != this) { // then clip the resizable to it int t; - t = r->x(); if (t > p[0]) p[4] = t; - t +=r->w(); if (t < p[1]) p[5] = t; - t = r->y(); if (t > p[2]) p[6] = t; - t +=r->h(); if (t < p[3]) p[7] = t; + t = r->x(); if (t > left) left = t; + t +=r->w(); if (t < right) right = t; + t = r->y(); if (t > top) top = t; + t +=r->h(); if (t < bottom) bottom = t; } + p[1] = Fl_Rect(left, top, right-left, bottom-top); // next is all the children's sizes: - p += 8; + p += 2; Fl_Widget*const* a = array(); for (int i=children_; i--;) { - Fl_Widget* o = *a++; - *p++ = o->x(); - *p++ = o->x()+o->w(); - *p++ = o->y(); - *p++ = o->y()+o->h(); + *p++ = Fl_Rect(*a++); } } + return bounds_; +} + +/** Returns the internal array of widget sizes and positions. + + For backward compatibility with FLTK versions before 1.4. + + The sizes() array stores the initial positions of widgets as + (left, right, top, bottom) quads. The first quad is the group, the + second is the resizable (clipped to the group), and the rest are the + children. If the group and/or the resizable() is a Fl_Window, then + the first (left) and third (top) entries of their respective quads + (x,y) are zero. + + \deprecated Deprecated since 1.4.0. Please use bounds() instead. + + \note This method will be removed in a future FLTK version (1.5.0 or higher). + + \returns Array of int's with widget positions and sizes. The returned + array is only valid until init_sizes() is called or widgets + are added to or removed from the group. + + \note Since FLTK 1.4.0 the returned array is a \b read-only and re-ordered + copy of the internal bounds() array. Do not change its contents. + If you need to rearrange children in a group, do so by resizing + the children and call init_sizes(). + + \see bounds() +*/ +int* Fl_Group::sizes() +{ + if (sizes_) return sizes_; + // allocate new sizes_ array and copy bounds_ over to sizes_ + int* pi = sizes_ = new int[4*(children_+2)]; + Fl_Rect *rb = bounds(); + for (int i = 0; i < children_+2; i++, rb++) { + *pi++ = rb->x(); + *pi++ = rb->r(); + *pi++ = rb->y(); + *pi++ = rb->b(); + } return sizes_; } @@ -633,14 +694,14 @@ void Fl_Group::resize(int X, int Y, int W, int H) { int dy = Y-y(); int dw = W-w(); int dh = H-h(); - - int *p = sizes(); // save initial sizes and positions + + Fl_Rect* p = bounds(); // save initial sizes and positions Fl_Widget::resize(X,Y,W,H); // make new xywh values visible for children if (!resizable() || (dw==0 && dh==0) ) { - if (type() < FL_WINDOW) { + if (!as_window()) { Fl_Widget*const* a = array(); for (int i=children_; i--;) { Fl_Widget* o = *a++; @@ -651,48 +712,47 @@ void Fl_Group::resize(int X, int Y, int W, int H) { } else if (children_) { // get changes in size/position from the initial size: - dx = X - p[0]; - dw = W - (p[1]-p[0]); - dy = Y - p[2]; - dh = H - (p[3]-p[2]); - if (type() >= FL_WINDOW) dx = dy = 0; - p += 4; + dx = X - p->x(); + dw = W - p->w(); + dy = Y - p->y(); + dh = H - p++->h(); + if (as_window()) dx = dy = 0; // get initial size of resizable(): - int IX = *p++; - int IR = *p++; - int IY = *p++; - int IB = *p++; + int IX = p->x(); + int IR = p->r(); + int IY = p->y(); + int IB = p++->b(); Fl_Widget*const* a = array(); for (int i=children_; i--;) { Fl_Widget* o = *a++; #if 1 - int XX = *p++; + int XX = p->x(); if (XX >= IR) XX += dw; else if (XX > IX) XX = IX+((XX-IX)*(IR+dw-IX)+(IR-IX)/2)/(IR-IX); - int R = *p++; + int R = p->r(); if (R >= IR) R += dw; else if (R > IX) R = IX+((R-IX)*(IR+dw-IX)+(IR-IX)/2)/(IR-IX); - int YY = *p++; + int YY = p->y(); if (YY >= IB) YY += dh; else if (YY > IY) YY = IY+((YY-IY)*(IB+dh-IY)+(IB-IY)/2)/(IB-IY); - int B = *p++; + int B = p++->b(); if (B >= IB) B += dh; else if (B > IY) B = IY+((B-IY)*(IB+dh-IY)+(IB-IY)/2)/(IB-IY); #else // much simpler code from Francois Ostiguy: - int XX = *p++; + int XX = p->x(); if (XX >= IR) XX += dw; else if (XX > IX) XX += dw * (XX-IX)/(IR-IX); - int R = *p++; + int R = p->r(); if (R >= IR) R += dw; else if (R > IX) R = R + dw * (R-IX)/(IR-IX); - int YY = *p++; + int YY = p->y(); if (YY >= IB) YY += dh; else if (YY > IY) YY = YY + dh*(YY-IY)/(IB-IY); - int B = *p++; + int B = p++->b(); if (B >= IB) B += dh; else if (B > IY) B = B + dh*(B-IY)/(IB-IY); #endif @@ -750,7 +810,7 @@ void Fl_Group::draw() { void Fl_Group::update_child(Fl_Widget& widget) const { if (widget.damage() && widget.visible() && widget.type() < FL_WINDOW && fl_not_clipped(widget.x(), widget.y(), widget.w(), widget.h())) { - widget.draw(); + widget.draw(); widget.clear_damage(); } } diff --git a/src/Fl_Tile.cxx b/src/Fl_Tile.cxx index 1a533cabd..249f83add 100644 --- a/src/Fl_Tile.cxx +++ b/src/Fl_Tile.cxx @@ -3,7 +3,7 @@ // // Tile widget for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2016 by Bill Spitzak and others. +// Copyright 1998-2017 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 @@ -87,7 +87,6 @@ #include <FL/Fl.H> #include <FL/Fl_Tile.H> #include <FL/Fl_Window.H> -#include <stdlib.h> /** Drags the intersection at (\p oldx,\p oldy) to (\p newx,\p newy). @@ -97,25 +96,25 @@ */ 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 - for (int i=children(); i--; p += 4) { + Fl_Rect *p = bounds(); + p += 2; // skip group & resizable's saved size + for (int i=children(); i--; p++) { Fl_Widget* o = *a++; if (o == resizable()) continue; int X = o->x(); int R = X+o->w(); if (oldx) { - int t = p[0]; + int t = p->x(); if (t == oldx || (t>oldx && X<newx) || (t<oldx && X>newx) ) X = newx; - t = p[1]; + t = p->r(); if (t == oldx || (t>oldx && R<newx) || (t<oldx && R>newx) ) R = newx; } int Y = o->y(); int B = Y+o->h(); if (oldy) { - int t = p[2]; + int t = p->y(); if (t == oldy || (t>oldy && Y<newy) || (t<oldy && Y>newy) ) Y = newy; - t = p[3]; + t = p->b(); if (t == oldy || (t>oldy && B<newy) || (t<oldy && B>newy) ) B = newy; } o->damage_resize(X,Y,R-X,B-Y); @@ -146,29 +145,29 @@ void Fl_Tile::resize(int X,int Y,int W,int H) { int dy = Y-y(); int dw = W-w(); int dh = H-h(); - int *p = sizes(); + Fl_Rect *p = bounds(); // resize this (skip the Fl_Group resize): Fl_Widget::resize(X,Y,W,H); // 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 + int OR = p[1].r(); // old right border + int NR = X+W-(p[0].r()-OR); // new right border + int OB = p[1].b(); // old bottom border + int NB = Y+H-(p[0].b()-OB); // new bottom border // move everything to be on correct side of new resizable: Fl_Widget*const* a = array(); - p += 8; - for (int i=children(); i--;) { + p += 2; + for (int i=children(); i--; p++) { Fl_Widget* o = *a++; int xx = o->x()+dx; int R = xx+o->w(); - if (*p++ >= OR) xx += dw; else if (xx > NR) xx = NR; - if (*p++ >= OR) R += dw; else if (R > NR) R = NR; + if (p->x() >= OR) xx += dw; else if (xx > NR) xx = NR; + if (p->r() >= OR) R += dw; else if (R > NR) R = NR; int yy = o->y()+dy; int B = yy+o->h(); - if (*p++ >= OB) yy += dh; else if (yy > NB) yy = NB; - if (*p++ >= OB) B += dh; else if (B > NB) B = NB; + if (p->y() >= OB) yy += dh; else if (yy > NB) yy = NB; + if (p->b() >= 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 // scroll, it'll set the damage areas wrong for all children! @@ -216,25 +215,25 @@ int Fl_Tile::handle(int event) { int oldx = 0; int oldy = 0; Fl_Widget*const* a = array(); - int *q = sizes(); - int *p = q+8; - for (int i=children(); i--; p += 4) { + Fl_Rect *q = bounds(); + Fl_Rect *p = q+2; + for (int i=children(); i--; p++) { Fl_Widget* o = *a++; if (o == resizable()) continue; - if (p[1]<q[1] && o->y()<=my+GRABAREA && o->y()+o->h()>=my-GRABAREA) { + if (p->r() < q->r() && o->y()<=my+GRABAREA && o->y()+o->h()>=my-GRABAREA) { int t = mx - (o->x()+o->w()); if (abs(t) < mindx) { sdx = t; mindx = abs(t); - oldx = p[1]; + oldx = p->r(); } } - if (p[3]<q[3] && o->x()<=mx+GRABAREA && o->x()+o->w()>=mx-GRABAREA) { + if (p->b() < q->b() && o->x()<=mx+GRABAREA && o->x()+o->w()>=mx-GRABAREA) { int t = my - (o->y()+o->h()); if (abs(t) < mindy) { sdy = t; mindy = abs(t); - oldy = p[3]; + oldy = p->b(); } } } |
