From ada206d8f7157c2f6e78209d24c5f51264a1eea8 Mon Sep 17 00:00:00 2001 From: Albrecht Schlosser Date: Wed, 22 Dec 2010 13:06:03 +0000 Subject: [PATCH] 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 --- CHANGES | 25 +++---- FL/Fl_Tabs.H | 8 ++- src/Fl_Tabs.cxx | 168 ++++++++++++++++++++++++++++++++++++------------ 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; ivisible()) 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= 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= 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 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 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 @@ -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; + } } //