summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlbrecht Schlosser <albrechts.fltk@online.de>2010-12-22 13:06:03 +0000
committerAlbrecht Schlosser <albrechts.fltk@online.de>2010-12-22 13:06:03 +0000
commitada206d8f7157c2f6e78209d24c5f51264a1eea8 (patch)
tree17cafce319325533177868195dc63ee47a3d8b16
parent1f39dbe5fc0d658755054ae0404e72c37f0fd3f8 (diff)
Added Fl_Tabs::client_area() (STR #2480).
Fixed some typos in CHANGES. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@8101 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
-rw-r--r--CHANGES25
-rw-r--r--FL/Fl_Tabs.H8
-rw-r--r--src/Fl_Tabs.cxx168
3 files changed, 146 insertions, 55 deletions
diff --git a/CHANGES b/CHANGES
index 8f79fc6f0..4a0813443 100644
--- a/CHANGES
+++ b/CHANGES
@@ -3,7 +3,7 @@ CHANGES IN FLTK 1.3.0
New Features
- - Added UTF-8 Unicode supprt
+ - Added UTF-8 Unicode support
- Added Fl_Tree widget for hierarchical views
- Added Fl_Table widget for widget layout
- Added Fl_Native_Filechooser as a widget and global options
@@ -13,7 +13,9 @@ CHANGES IN FLTK 1.3.0
- Added basic Fl_Device abstraction layer for all drawing functions
Other Additions
-
+
+ - Added new method client_area() for easier positioning of children
+ in Fl_Tabs (STR #2480)
- Added global UI options (STR #2471)
- Added drag'n'drop support for Fl_Text_*
- Added new label and image alignments (STR #2269)
@@ -28,7 +30,7 @@ CHANGES IN FLTK 1.3.0
- Added class Fl_Widget_Tracker to simplify safe handling of widget
deletion in callbacks. This is used in Fl_Widget::do_callback()
to prevent accessing widgets after deletion in the callback.
- - Added argument-less constructor in Fuid Widget Class
+ - Added argument-less constructor in Fluid Widget Class
- Added Fl_Menu_::find_item by callback
- Added indexing to Fl_Preferences
- Added jpeg support to Fluid image() element
@@ -42,7 +44,7 @@ CHANGES IN FLTK 1.3.0
- Added "ide" subdirectory for all IDE support files
- Added Fl_Menu_ methods: insert(), find_index(), clear_submenu()
- Added menu shortcut alignment for OS X
- - Added drop box to utf8 test that will show the utf8 encoding
+ - Added drop box to UTF-8 test that will show the UTF-8 encoding
for the first dropped character
- Added flexible gap size for text buffer (STR #2046)
- Added sorting to Fl_Browser_ (STR #2113)
@@ -50,7 +52,7 @@ CHANGES IN FLTK 1.3.0
- Added scroll_to(int,int) to Fl_Scroll, replacing
position(int,int) which now behaves as it should (STR #1303)
- Added alternative text input awareness on OS X
-
+
Documentation
- Added documentation for event delivery (STR #1983)
@@ -59,10 +61,10 @@ CHANGES IN FLTK 1.3.0
- Updated Copyright dates to 2010 (STR #2036)
- Updated mirror sites in documentation (STR #2220)
- Fixed documentation for Fl_Progress (STR #2209)
- - Fixed documentation (added missing COMCTRL32.LIB dependency)
-
+ - Fixed documentation (added missing COMCTL32.LIB dependency)
+
Improvements
-
+
- Moved OS X code base to the more modern Cocoa toolkit thanks
to the awesome work of Manolo Gouy (STR #2221)
- Improved handling of composed keys in OS X 10.5 and up
@@ -210,11 +212,10 @@ CHANGES IN FLTK 1.3.0
- Removed Watcom compiler support because it was introduced in
1.1.6 as a partial solution and never completed.
- - Removed an XForms compatibility "feature" that prevented the down
- array of Fl_Menu_Button from drawing (STR #2141).
+ - Removed an XForms compatibility "feature" that prevented the
+ down array of Fl_Menu_Button from drawing (STR #2141).
- Removed support for gcc 2.x (or older)
- Removed redundant Fl_Group casts
-
CHANGES IN FLTK 1.1.9
@@ -223,7 +224,7 @@ CHANGES IN FLTK 1.1.9
- Fixed regression in callback handling (STR #1918)
- Fixed wrong relative path when absolute path has a
trailing slash in fl_filename_relative (STR #1920)
- - Fixed multiple selction of files and directories in
+ - Fixed multiple selection of files and directories in
Fl_File_Chooser (STR #1913)
- Fixed MSWindows crash when selecting umlauts
in Fl_Help_View (STR #1912)
diff --git a/FL/Fl_Tabs.H b/FL/Fl_Tabs.H
index c55a0b74e..da413ee6d 100644
--- a/FL/Fl_Tabs.H
+++ b/FL/Fl_Tabs.H
@@ -62,7 +62,11 @@
class FL_EXPORT Fl_Tabs : public Fl_Group {
Fl_Widget *value_;
Fl_Widget *push_;
- int tab_positions(int*, int*);
+ int *tab_pos; // array of x-offsets of tabs per child + 1
+ int *tab_width; // array of widths of tabs per child + 1
+ int tab_count; // array size
+ int tab_positions(); // allocate and calculate tab positions
+ void clear_tab_positions();
int tab_height();
void draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int sel=0);
protected:
@@ -77,6 +81,8 @@ public:
int push(Fl_Widget *);
Fl_Tabs(int,int,int,int,const char * = 0);
Fl_Widget *which(int event_x, int event_y);
+ ~Fl_Tabs();
+ void client_area(int &rx, int &ry, int &rw, int &rh, int tabh=0);
};
#endif
diff --git a/src/Fl_Tabs.cxx b/src/Fl_Tabs.cxx
index 6f1c3674b..2b49cf610 100644
--- a/src/Fl_Tabs.cxx
+++ b/src/Fl_Tabs.cxx
@@ -42,60 +42,74 @@
#define EXTRASPACE 10
#define SELECTION_BORDER 5
-// return the left edges of each tab (plus a fake left edge for a tab
-// past the right-hand one). These position are actually of the left
+// Return the left edges of each tab (plus a fake left edge for a tab
+// past the right-hand one). These positions are actually of the left
// edge of the slope. They are either separated by the correct distance
// or by EXTRASPACE or by zero.
+// These positions are updated in the private arrays tab_pos[] and
+// tab_width[], resp.. If needed, these arrays are (re)allocated.
// Return value is the index of the selected item.
-int Fl_Tabs::tab_positions(int* p, int* wp) {
+int Fl_Tabs::tab_positions() {
+ int nc = children();
+ if (nc != tab_count) {
+ clear_tab_positions();
+ if (nc) {
+ tab_pos = (int*)malloc((nc+1)*sizeof(int));
+ tab_width = (int*)malloc((nc+1)*sizeof(int));
+ }
+ tab_count = nc;
+ }
+ if (nc == 0) return 0;
int selected = 0;
Fl_Widget*const* a = array();
int i;
char prev_draw_shortcut = fl_draw_shortcut;
fl_draw_shortcut = 1;
- p[0] = Fl::box_dx(box());
- for (i=0; i<children(); i++) {
+ tab_pos[0] = Fl::box_dx(box());
+ for (i=0; i<nc; i++) {
Fl_Widget* o = *a++;
if (o->visible()) selected = i;
int wt = 0; int ht = 0;
o->measure_label(wt,ht);
- wp[i] = wt+EXTRASPACE;
- p[i+1] = p[i]+wp[i]+BORDER;
+ tab_width[i] = wt + EXTRASPACE;
+ tab_pos[i+1] = tab_pos[i] + tab_width[i] + BORDER;
}
fl_draw_shortcut = prev_draw_shortcut;
int r = w();
- if (p[i] <= r) return selected;
+ if (tab_pos[i] <= r) return selected;
// uh oh, they are too big:
// pack them against right edge:
- p[i] = r;
- for (i = children(); i--;) {
- int l = r-wp[i];
- if (p[i+1] < l) l = p[i+1];
- if (p[i] <= l) break;
- p[i] = l;
+ tab_pos[i] = r;
+ for (i = nc; i--;) {
+ int l = r-tab_width[i];
+ if (tab_pos[i+1] < l) l = tab_pos[i+1];
+ if (tab_pos[i] <= l) break;
+ tab_pos[i] = l;
r -= EXTRASPACE;
}
// pack them against left edge and truncate width if they still don't fit:
- for (i = 0; i<children(); i++) {
- if (p[i] >= i*EXTRASPACE) break;
- p[i] = i*EXTRASPACE;
- int W = w()-1-EXTRASPACE*(children()-i) - p[i];
- if (wp[i] > W) wp[i] = W;
+ for (i = 0; i<nc; i++) {
+ if (tab_pos[i] >= i*EXTRASPACE) break;
+ tab_pos[i] = i*EXTRASPACE;
+ int W = w()-1-EXTRASPACE*(children()-i) - tab_pos[i];
+ if (tab_width[i] > W) tab_width[i] = W;
}
// adjust edges according to visiblity:
- for (i = children(); i > selected; i--) {
- p[i] = p[i-1]+wp[i-1];
+ for (i = nc; i > selected; i--) {
+ tab_pos[i] = tab_pos[i-1] + tab_width[i-1];
}
return selected;
}
-// return space needed for tabs. Negative to put them on the bottom:
+// Returns space (height) in pixels needed for tabs. Negative to put them on the bottom.
+// Returns full height, if children() = 0.
int Fl_Tabs::tab_height() {
+ if (children() == 0) return h();
int H = h();
int H2 = y();
Fl_Widget*const* a = array();
@@ -109,8 +123,10 @@ int Fl_Tabs::tab_height() {
else return (H <= 0) ? 0 : H;
}
-// this is used by fluid to pick tabs:
+// This is used for event handling (clicks) and by fluid to pick tabs.
+// Returns 0, if children() = 0, or if the event is outside of the tabs area.
Fl_Widget *Fl_Tabs::which(int event_x, int event_y) {
+ if (children() == 0) return 0;
int H = tab_height();
if (H < 0) {
if (event_y > y()+h() || event_y < y()+h()+H) return 0;
@@ -120,17 +136,13 @@ Fl_Widget *Fl_Tabs::which(int event_x, int event_y) {
if (event_x < x()) return 0;
Fl_Widget *ret = 0L;
int nc = children();
- int *p = (int*)malloc((nc+1)*sizeof(int));
- int *wp = (int*)malloc((nc+1)*sizeof(int));
- tab_positions(p, wp);
- for (int i=0; i<children(); i++) {
- if (event_x < x()+p[i+1]) {
+ tab_positions();
+ for (int i=0; i<nc; i++) {
+ if (event_x < x()+tab_pos[i+1]) {
ret = child(i);
break;
}
}
- free(p);
- free(wp);
return ret;
}
@@ -325,21 +337,20 @@ void Fl_Tabs::draw() {
}
if (damage() & (FL_DAMAGE_SCROLL|FL_DAMAGE_ALL)) {
int nc = children();
- int *p = (int*)malloc((nc+1)*sizeof(int));
- int *wp = (int*)malloc((nc+1)*sizeof(int));
- int selected = tab_positions(p,wp);
+ int selected = tab_positions();
int i;
Fl_Widget*const* a = array();
for (i=0; i<selected; i++)
- draw_tab(x()+p[i], x()+p[i+1], wp[i], H, a[i], LEFT);
- for (i=children()-1; i > selected; i--)
- draw_tab(x()+p[i], x()+p[i+1], wp[i], H, a[i], RIGHT);
+ draw_tab(x()+tab_pos[i], x()+tab_pos[i+1],
+ tab_width[i], H, a[i], LEFT);
+ for (i=nc-1; i > selected; i--)
+ draw_tab(x()+tab_pos[i], x()+tab_pos[i+1],
+ tab_width[i], H, a[i], RIGHT);
if (v) {
i = selected;
- draw_tab(x()+p[i], x()+p[i+1], wp[i], H, a[i], SELECTED);
+ draw_tab(x()+tab_pos[i], x()+tab_pos[i+1],
+ tab_width[i], H, a[i], SELECTED);
}
- free(p);
- free(wp);
}
}
@@ -420,11 +431,11 @@ void Fl_Tabs::draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int what) {
away from the top or bottom edge of the Fl_Tabs widget,
which is where the tabs will be drawn.
- All children of Fl_Tab should have the same size and exactly fit on top of
+ All children of Fl_Tabs should have the same size and exactly fit on top of
each other. They should only leave space above or below where that tabs will
- go, but not on the sides. If the first child of Fl_Tab is set to
+ go, but not on the sides. If the first child of Fl_Tabs is set to
"resizable()", the riders will not resize when the tabs are resized.
-
+
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. A kludge
@@ -437,6 +448,79 @@ Fl_Tabs::Fl_Tabs(int X,int Y,int W, int H, const char *l) :
{
box(FL_THIN_UP_BOX);
push_ = 0;
+ tab_pos = 0;
+ tab_width = 0;
+ tab_count = 0;
+}
+
+Fl_Tabs::~Fl_Tabs() {
+ clear_tab_positions();
+}
+
+/**
+ Returns the position and size available to be used by its children.
+
+ If there isn't any child yet the \p tabh parameter will be used to
+ calculate the return values. This assumes that the children's labelsize
+ is the same as the Fl_Tabs' labelsize and adds a small border.
+
+ If there are already children, the values of child(0) are returned, and
+ \p tabh is ignored.
+
+ \note Children should always use the same positions and sizes.
+
+ \p tabh can be one of
+ \li 0: calculate label size, tabs on top
+ \li -1: calculate label size, tabs on bottom
+ \li > 0: use given \p tabh value, tabs on top (height = tabh)
+ \li < -1: use given \p tabh value, tabs on bottom (height = -tabh)
+
+ \param[in] tabh position and optional height of tabs (see above)
+ \param[out] rx,ry,rw,rh (x,y,w,h) of client area for children
+*/
+void Fl_Tabs::client_area(int &rx, int &ry, int &rw, int &rh, int tabh) {
+
+ if (children()) { // use existing values
+
+ rx = child(0)->x();
+ ry = child(0)->y();
+ rw = child(0)->w();
+ rh = child(0)->h();
+
+ } else { // calculate values
+
+ int y_offset;
+ int label_height = fl_height(labelfont(), labelsize()) + BORDER*2;
+
+ if (tabh == 0) // use default (at top)
+ y_offset = label_height;
+ else if (tabh == -1) // use default (at bottom)
+ y_offset = -label_height;
+ else
+ y_offset = tabh; // user given value
+
+ rx = x();
+ rw = w();
+
+ if (y_offset >= 0) { // labels at top
+ ry = y() + y_offset;
+ rh = h() - y_offset;
+ } else { // labels at bottom
+ ry = y();
+ rh = h() + y_offset;
+ }
+ }
+}
+
+void Fl_Tabs::clear_tab_positions() {
+ if (tab_pos) {
+ free(tab_pos);
+ tab_pos = 0;
+ }
+ if (tab_width){
+ free(tab_width);
+ tab_width = 0;
+ }
}
//