Skip to content

Commit

Permalink
Added Fl_Tabs::client_area() (STR #2480).
Browse files Browse the repository at this point in the history
Fixed some typos in CHANGES.


git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@8101 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
  • Loading branch information
Albrecht Schlosser committed Dec 22, 2010
1 parent 1f39dbe commit ada206d
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 55 deletions.
25 changes: 13 additions & 12 deletions CHANGES
Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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
Expand All @@ -42,15 +44,15 @@ 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)
- Added clarification to Fl_GL_Window mode function (STR #1945)
- 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)
Expand All @@ -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
Expand Down Expand 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

Expand All @@ -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)
Expand Down
8 changes: 7 additions & 1 deletion FL/Fl_Tabs.H
Expand Up @@ -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:
Expand All @@ -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
Expand Down
168 changes: 126 additions & 42 deletions src/Fl_Tabs.cxx
Expand Up @@ -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();
Expand All @@ -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;
Expand All @@ -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;
}

Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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
Expand All @@ -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;
}
}

//
Expand Down

0 comments on commit ada206d

Please sign in to comment.