DO NOT REPLY TO THIS MESSAGE.  INSTEAD, POST ANY RESPONSES TO THE LINK BELOW.

[STR New]

Link: http://www.fltk.org/str.php?L2480
Version: 1.3-feature





Link: http://www.fltk.org/str.php?L2480
Version: 1.3-feature
Index: FL/Fl_Tabs.H
===================================================================
--- FL/Fl_Tabs.H        (revision 8014)
+++ FL/Fl_Tabs.H        (working copy)
@@ -62,7 +62,12 @@
 class FL_EXPORT Fl_Tabs : public Fl_Group {
   Fl_Widget *value_;
   Fl_Widget *push_;
-  int tab_positions(int*, int*);
+  int *tab_positions_p;
+  int *tab_positions_wp;
+  void clear_tab_positions();
+  int check_children_count_changed();
+  int tab_positions();
+  int tab_count_;
   int tab_height();
   void draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int sel=0);
 protected:
@@ -77,6 +82,8 @@
   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, bool top_if_first=true);
 };
 
 #endif
Index: src/Fl_Tabs.cxx
===================================================================
--- src/Fl_Tabs.cxx     (revision 8014)
+++ src/Fl_Tabs.cxx     (working copy)
@@ -40,6 +40,7 @@
 
 #define BORDER 2
 #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
@@ -47,48 +48,50 @@
 // or by EXTRASPACE or by zero.
 // 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 = check_children_count_changed();
+  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_positions_p[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_positions_wp[i]  = wt+EXTRASPACE;
+    tab_positions_p[i+1] = tab_positions_p[i]+tab_positions_wp[i]+BORDER;
   }
   fl_draw_shortcut = prev_draw_shortcut;
 
   int r = w();
-  if (p[i] <= r) return selected;
+  if (tab_positions_p[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_positions_p[i] = r;
+  for (i = nc; i--;) {
+    int l = r-tab_positions_wp[i];
+    if (tab_positions_p[i+1] < l) l = tab_positions_p[i+1];
+    if (tab_positions_p[i] <= l) break;
+    tab_positions_p[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_positions_p[i] >= i*EXTRASPACE) break;
+    tab_positions_p[i] = i*EXTRASPACE;
+    int W = w()-1-EXTRASPACE*(children()-i) - tab_positions_p[i];
+    if (tab_positions_wp[i] > W) tab_positions_wp[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_positions_p[i] = tab_positions_p[i-1]+tab_positions_wp[i-1];
   }
   return selected;
 }
@@ -119,17 +122,13 @@
   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_positions_p[i+1]) {
       ret = child(i);
       break;
     }
   }
-  free(p);
-  free(wp);
   return ret;
 }
 
@@ -165,7 +164,7 @@
     o = which(Fl::event_x(), Fl::event_y());
     if (event == FL_RELEASE) {
       push(0);
-      if (o && Fl::visible_focus() && Fl::focus()!=this) { 
+      if (o && Fl::visible_focus() && visible_focus() && Fl::focus()!=this) {
         Fl::focus(this);
         redraw_tabs();
       }
@@ -197,7 +196,7 @@
     return ret; }
   case FL_FOCUS:
   case FL_UNFOCUS:
-    if (!Fl::visible_focus()) return Fl_Group::handle(event);
+    if (!Fl::visible_focus() && visible_focus()) return 
Fl_Group::handle(event);
     if (Fl::event() == FL_RELEASE ||
        Fl::event() == FL_SHORTCUT ||
        Fl::event() == FL_KEYBOARD ||
@@ -313,12 +312,9 @@
     if (selection_color() != c) {
       // Draw the top 5 lines of the tab pane in the selection color so
       // that the user knows which tab is selected...
-      if (H >= 0) fl_push_clip(x(), y() + H, w(), 5);
-      else fl_push_clip(x(), y() + h() - H - 4, w(), 5);
-
-      draw_box(box(), x(), y()+(H>=0?H:0), w(), h()-(H>=0?H:-H),
-               selection_color());
-
+      int clip_y = (H >= 0) ? y() + H : y() + h() + H - SELECTION_BORDER;
+      fl_push_clip(x(), clip_y, w(), SELECTION_BORDER);
+      draw_box(box(), x(), clip_y, w(), SELECTION_BORDER, selection_color());
       fl_pop_clip();
     }
     if (v) draw_child(*v);
@@ -327,21 +323,20 @@
   }
   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_positions_p[i], x()+tab_positions_p[i+1],
+               tab_positions_wp[i], H, a[i], LEFT);
+    for (i=nc-1; i > selected; i--)
+      draw_tab(x()+tab_positions_p[i], x()+tab_positions_p[i+1],
+               tab_positions_wp[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_positions_p[i], x()+tab_positions_p[i+1],
+               tab_positions_wp[i], H, a[i], SELECTED);
     }
-    free(p);
-    free(wp);
   }
 }
 
@@ -439,8 +434,56 @@
 {
   box(FL_THIN_UP_BOX);
   push_ = 0;
+  tab_positions_p = 0;
+  tab_positions_wp = 0;
+  tab_count_ = 0;
 }
 
+Fl_Tabs::~Fl_Tabs() {
+  clear_tab_positions();
+}
+
+/**
+    Return the position and size availlable to be used by it's Fl_Group childs.
+    If there isn't any child yet the "top_if_first" parameter will be used to
+    calculate the return value for tabs labels on top "top_if_first=true" the
+    default or on bottom "top_if_first=false".
+*/
+void Fl_Tabs::client_area(int &rx, int &ry, int &rw, int &rh, bool 
top_if_first){
+    int tab_label_height = fl_height(labelfont(), labelsize()) + BORDER*2;
+    int y_offset;
+    if(children()) y_offset = tab_height() < 0 ? 0 : 1;
+    else y_offset = top_if_first ? 1 : 0;
+    rx = x() + BORDER;
+    ry = y() + BORDER + y_offset*tab_label_height;
+    rw = w()-BORDER*2;
+    rh = h() - BORDER*2 - tab_label_height;
+}
+
+void Fl_Tabs::clear_tab_positions() {
+  if(tab_positions_p) {
+     free(tab_positions_p);
+     tab_positions_p = 0;
+  }
+  if(tab_positions_wp){
+     free(tab_positions_wp);
+     tab_positions_wp = 0;
+  }
+}
+
+int Fl_Tabs::check_children_count_changed() {
+  int nc = children();
+  if(nc != tab_count_){
+    clear_tab_positions();
+    if(nc) {
+      tab_positions_p  = (int*)malloc((nc+1)*sizeof(int));
+      tab_positions_wp = (int*)malloc((nc+1)*sizeof(int));
+    }
+    tab_count_ = nc;
+  }
+  return nc;
+}
+
 //
 // End of "$Id$".
 //
_______________________________________________
fltk-dev mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-dev

Reply via email to