Author: greg.ercolano
Date: 2012-04-22 06:40:02 -0700 (Sun, 22 Apr 2012)
New Revision: 9377
Log:
Various mods for Fl_Tree
    o Fix STR#2828 (E): {Vertical|Widget} Gap
    o Moved Fabien's reselected methods to Fl_Tree_Prefs,
      return method made const, doxygen, removed underbars from methods
      (to follow general API)
    o Widgets can now appear to the right of labels.
      This can be controlled with 
item_draw_mode(FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET)
    o Cleaned up Fl_Tree_Item::draw(), Fl_Tree::draw()
    o New methods:
            marginbottom()       -- [ABI feature] extra space below last tree 
element when scrolling
            widgetmarginleft()   -- [ABI feature] space to left of widget
            usericonmarginleft() -- space to left of usericon
            labelmarginleft()    -- space to left of label
            item_draw_mode()     -- control how items, widget() are drawn
    o Updated Fl_Tree docs, tree-elements.png
    o test/tree: added sliders to test the above new features,
      added "open all" and "close all" buttons
    o Probably other stuff..


TODO: Fix "scroll-beyond-bottom" (STR#2796)
TODO: Fix other items in STR#2828



Modified:
   branches/branch-1.3/FL/Fl_Tree.H
   branches/branch-1.3/FL/Fl_Tree_Item.H
   branches/branch-1.3/FL/Fl_Tree_Prefs.H
   branches/branch-1.3/documentation/src/tree-elements.png
   branches/branch-1.3/examples/tree-as-container.cxx
   branches/branch-1.3/src/Fl_Tree.cxx
   branches/branch-1.3/src/Fl_Tree_Item.cxx
   branches/branch-1.3/src/Fl_Tree_Prefs.cxx

Modified: branches/branch-1.3/FL/Fl_Tree.H
===================================================================
--- branches/branch-1.3/FL/Fl_Tree.H    2012-04-22 13:09:19 UTC (rev 9376)
+++ branches/branch-1.3/FL/Fl_Tree.H    2012-04-22 13:40:02 UTC (rev 9377)
@@ -194,17 +194,6 @@
   FL_TREE_REASON_CLOSED                ///< an item was closed
 };
 
-#if FLTK_ABI_VERSION >= 10302
-/// \enum Fl_Tree_Item_Select_Mode
-/// Defines the ways an item can be (re) selected.
-///
-enum Fl_Tree_Item_Reselect_Mode
-{
-  FL_TREE_SELECTABLE_ONCE=0, /// backward compatible default: an item can only 
be selected once
-  FL_TREE_SELECTABLE_ALWAYS, /// needed for new RESELECT feature
-};
-#endif
-
 class FL_EXPORT Fl_Tree : public Fl_Group {
   Fl_Tree_Item  *_root;                                // can be null!
   Fl_Tree_Item  *_item_focus;                  // item that has focus box
@@ -216,20 +205,6 @@
 #if FLTK_ABI_VERSION >= 10302
   // NEW: 
   Fl_Tree_Item *_lastselect;
-       
-  // NEW:
-public:
-  //! Returns the current item re/selection mode
-  Fl_Tree_Item_Reselect_Mode item_reselect_mode() const {
-    return _itemReselectMode;
-  }
-  
-  //! Sets the item re/selection mode
-  void item_reselect_mode(Fl_Tree_Item_Reselect_Mode mode) {
-    _itemReselectMode = mode;
-  }
-private:
-  Fl_Tree_Item_Reselect_Mode _itemReselectMode;
 #else
   // OLD: static data inside handle() method
 #endif
@@ -325,8 +300,20 @@
   void marginleft(int val);
   int margintop() const;
   void margintop(int val);
+#if FLTK_ABI_VERSION >= 10302
+  int marginbottom() const;
+  void marginbottom(int val);
+#endif
+  int linespacing() const;
+  void linespacing(int val);
   int openchild_marginbottom() const;
   void openchild_marginbottom(int val);
+  int usericonmarginleft() const;
+  void usericonmarginleft(int val);
+  int labelmarginleft() const;
+  void labelmarginleft(int val);
+  int widgetmarginleft() const;
+  void widgetmarginleft(int val);
   int connectorwidth() const;
   void connectorwidth(int val);
   Fl_Image* usericon() const;
@@ -347,6 +334,12 @@
   void selectbox(Fl_Boxtype val);
   Fl_Tree_Select selectmode() const;
   void selectmode(Fl_Tree_Select val);
+#if FLTK_ABI_VERSION >= 10302
+  Fl_Tree_Item_Reselect_Mode item_reselect_mode() const;
+  void item_reselect_mode(Fl_Tree_Item_Reselect_Mode mode);
+  Fl_Tree_Item_Draw_Mode item_draw_mode() const;
+  void item_draw_mode(Fl_Tree_Item_Draw_Mode mode);
+#endif
 
   int displayed(Fl_Tree_Item *item);
   void show_item(Fl_Tree_Item *item, int yoff);

Modified: branches/branch-1.3/FL/Fl_Tree_Item.H
===================================================================
--- branches/branch-1.3/FL/Fl_Tree_Item.H       2012-04-22 13:09:19 UTC (rev 
9376)
+++ branches/branch-1.3/FL/Fl_Tree_Item.H       2012-04-22 13:40:02 UTC (rev 
9377)
@@ -62,7 +62,7 @@
   char                    _active;             // item activated?
   char                    _selected;           // item selected?
   int                     _xywh[4];            // xywh of this widget (if 
visible)
-  int                     _collapse_xywh[4];   // xywh of collapse icon (if 
any)
+  int                     _collapse_xywh[4];   // xywh of collapse icon (if 
visible)
   int                     _label_xywh[4];      // xywh of label
   Fl_Widget              *_widget;             // item's label widget 
(optional)
   Fl_Image               *_usericon;           // item's user-specific icon 
(optional)
@@ -86,6 +86,7 @@
   int y() const { return(_xywh[1]); }
   int w() const { return(_xywh[2]); }
   int h() const { return(_xywh[3]); }
+  int calc_item_height(const Fl_Tree_Prefs &prefs);
   void draw(int X, int &Y, int W, Fl_Widget *tree, Fl_Tree_Item *itemfocus, 
const Fl_Tree_Prefs &prefs, int lastchild=1);
   void show_self(const char *indent = "") const;
   void label(const char *val);

Modified: branches/branch-1.3/FL/Fl_Tree_Prefs.H
===================================================================
--- branches/branch-1.3/FL/Fl_Tree_Prefs.H      2012-04-22 13:09:19 UTC (rev 
9376)
+++ branches/branch-1.3/FL/Fl_Tree_Prefs.H      2012-04-22 13:40:02 UTC (rev 
9377)
@@ -45,7 +45,7 @@
 /// Sort order options for items added to the tree
 ///
 enum Fl_Tree_Sort {
-  FL_TREE_SORT_NONE=0, ///< No sorting; items are added in the order defined 
(default).
+  FL_TREE_SORT_NONE=0,         ///< No sorting; items are added in the order 
defined (default).
   FL_TREE_SORT_ASCENDING=1,    ///< Add items in ascending sort order.
   FL_TREE_SORT_DESCENDING=2    ///< Add items in descending sort order.
 };
@@ -65,10 +65,28 @@
 enum Fl_Tree_Select {
   FL_TREE_SELECT_NONE=0,       ///< Nothing selected when items are clicked
   FL_TREE_SELECT_SINGLE=1,     ///< Single item selected when item is clicked 
(default)
-  FL_TREE_SELECT_MULTI=2       ///< Multiple items can be selected by clicking 
with
-  ///< SHIFT or CTRL or mouse drags.
+  FL_TREE_SELECT_MULTI=2       ///< Multiple items can be selected by clicking
+                               ///< with SHIFT, CTRL or mouse drags.
 };
 
+#if FLTK_ABI_VERSION >= 10302
+/// \enum Fl_Tree_Item_Select_Mode
+/// Defines the ways an item can be (re) selected.
+///
+enum Fl_Tree_Item_Reselect_Mode {
+  FL_TREE_SELECTABLE_ONCE=0,   ///< item can only be selected once (default)
+  FL_TREE_SELECTABLE_ALWAYS,   ///< needed for new RESELECT feature
+};
+
+/// \enum Fl_Tree_Item_Draw_Mode
+/// Tree display style for items.
+///
+enum Fl_Tree_Item_Draw_Mode {
+  FL_TREE_ITEM_DRAW_WIDGET_ONLY=0,     ///< if widget() defined, draw it in 
place of the label (default)
+  FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET=1 ///< if widget() defined, draw it to 
right of label
+};
+#endif
+
 /// \class Fl_Tree_Prefs
 ///
 /// \brief Fl_Tree's Preferences class.
@@ -81,12 +99,16 @@
   Fl_Font _labelfont;                  // label's font face
   Fl_Fontsize _labelsize;              // label's font size
   int _margintop;                      // -- 
-  int _marginleft;                     //   |- tree's margins
-  //int _marginright;                  //   |
-  //int _marginbottom;                 // --
+  int _marginleft;                     //   |- tree's controllable margins
+#if FLTK_ABI_VERSION >= 10302
+  int _marginbottom;                   // --
+#endif
   int _openchild_marginbottom;         // extra space below an open child tree
   int _usericonmarginleft;             // space to left of user icon (if any)
   int _labelmarginleft;                        // space to left of label
+#if FLTK_ABI_VERSION >= 10302
+  int _widgetmarginleft;               // space to left of widget
+#endif
   int _connectorwidth;                 // connector width (right of open/close 
icon)
   int _linespacing;                    // vertical space between lines
   // Colors
@@ -102,6 +124,10 @@
   Fl_Tree_Sort   _sortorder;           // none, ascening, descending, etc.
   Fl_Boxtype     _selectbox;           // selection box type
   Fl_Tree_Select _selectmode;          // selection mode
+#if FLTK_ABI_VERSION >= 10302
+  Fl_Tree_Item_Reselect_Mode _itemreselectmode;        // controls item 
selection callback() behavior
+  Fl_Tree_Item_Draw_Mode     _itemdrawmode;    // controls how items draw 
label, widget()
+#endif
 public:
   Fl_Tree_Prefs();
   
@@ -144,6 +170,18 @@
   inline void margintop(int val) {
     _margintop = val;
   }
+#if FLTK_ABI_VERSION >= 10302
+  /// Get the bottom margin's value in pixels.
+  /// This is the extra distance the vertical scroller lets you travel.
+  inline int marginbottom() const {
+    return(_marginbottom);
+  }
+  /// Set the bottom margin's value in pixels
+  /// This is the extra distance the vertical scroller lets you travel.
+  inline void marginbottom(int val) {
+    _marginbottom = val;
+  }
+#endif
   /// Get the margin below an open child in pixels
   inline int openchild_marginbottom() const {
     return(_openchild_marginbottom);
@@ -152,22 +190,6 @@
   inline void openchild_marginbottom(int val) {
     _openchild_marginbottom = val;
   }
-  
-  /****** NOT IMPLEMENTED
-   inline int marginright() const {
-   return(_marginright);
-   }
-   inline void marginright(int val) {
-   _marginright = val;
-   }
-   inline int marginbottom() const {
-   return(_marginbottom);
-   }
-   inline void marginbottom(int val) {
-   _marginbottom = val;
-   }
-   *******/
-  
   /// Get the user icon's left margin value in pixels
   inline int usericonmarginleft() const {
     return(_usericonmarginleft);
@@ -184,6 +206,16 @@
   inline void labelmarginleft(int val) {
     _labelmarginleft = val;
   }
+#if FLTK_ABI_VERSION >= 10302
+  /// Get the widget()'s left margin value in pixels
+  inline int widgetmarginleft() const {
+    return(_widgetmarginleft);
+  }
+  /// Set the widget's left margin value in pixels
+  inline void widgetmarginleft(int val) {
+    _widgetmarginleft = val;
+  }
+#endif
   /// Get the line spacing value in pixels
   inline int linespacing() const {
     return(_linespacing);
@@ -329,6 +361,28 @@
   inline void selectmode(Fl_Tree_Select val) {
     _selectmode = val;
   }
+#if FLTK_ABI_VERSION >= 10302
+  /// Returns the current item re/selection mode
+  Fl_Tree_Item_Reselect_Mode item_reselect_mode() const {
+    return _itemreselectmode;
+  }
+  /// Sets the item re/selection mode
+  void item_reselect_mode(Fl_Tree_Item_Reselect_Mode mode) {
+    _itemreselectmode = mode;
+  }
+  /// Get the 'item draw mode' used for the tree
+  inline Fl_Tree_Item_Draw_Mode item_draw_mode() const {
+    return(_itemdrawmode);
+  }
+  /// Set the 'item draw mode' used for the tree to \p val.
+  ///     This affects how items in the tree are drawn,
+  ///     such as when a widget() is defined. 
+  ///     See Fl_Tree_Item_Draw_Mode for possible values.
+  ///
+  inline void item_draw_mode(Fl_Tree_Item_Draw_Mode val) {
+    _itemdrawmode = val;
+  }
+#endif
 };
 
 #endif /*FL_TREE_PREFS_H*/

Modified: branches/branch-1.3/documentation/src/tree-elements.png
===================================================================
(Binary files differ)

Modified: branches/branch-1.3/examples/tree-as-container.cxx
===================================================================
--- branches/branch-1.3/examples/tree-as-container.cxx  2012-04-22 13:09:19 UTC 
(rev 9376)
+++ branches/branch-1.3/examples/tree-as-container.cxx  2012-04-22 13:40:02 UTC 
(rev 9377)
@@ -23,10 +23,10 @@
 #include <FL/Fl_Group.H>
 #include <FL/Fl_Input.H>
 
-#define MAX_ROWS     80000
+#define MAX_ROWS     20000
 #define MAX_FIELDS   5
 #define FIELD_WIDTH  70
-#define FIELD_HEIGHT 25
+#define FIELD_HEIGHT 30
 
 class MyData : public Fl_Group {
     Fl_Input *fields[MAX_FIELDS];

Modified: branches/branch-1.3/src/Fl_Tree.cxx
===================================================================
--- branches/branch-1.3/src/Fl_Tree.cxx 2012-04-22 13:09:19 UTC (rev 9376)
+++ branches/branch-1.3/src/Fl_Tree.cxx 2012-04-22 13:40:02 UTC (rev 9377)
@@ -102,7 +102,6 @@
 #if FLTK_ABI_VERSION >= 10302
   // NEW
   _lastselect       = 0;
-  _itemReselectMode = FL_TREE_SELECTABLE_ONCE;
 #else
   // OLD: data initialized static inside handle()
 #endif
@@ -372,17 +371,25 @@
   int cy = y() + Fl::box_dy(box());
   int cw = w() - Fl::box_dw(box());
   int ch = h() - Fl::box_dh(box());
-  if (damage() & ~FL_DAMAGE_CHILD) { // redraw entire thing
+  {
     // Handle group's bg
-    Fl_Group::draw_box();
-    Fl_Group::draw_label();
+    if ( damage() & ~FL_DAMAGE_CHILD) {                        // redraw 
entire widget?
+      Fl_Group::draw_box();
+      Fl_Group::draw_label();
+    }
     if ( ! _root ) return;
     // These values are changed during drawing
-    // 'Y' will be the lowest point on the tree
+    // By end, 'Y' will be the lowest point on the tree
     int X = cx + _prefs.marginleft();
     int Y = cy + _prefs.margintop() - (_vscroll->visible() ? _vscroll->value() 
: 0);
     int W = cw - _prefs.marginleft();                  // - 
_prefs.marginright();
+    // Adjust root's X/W if connectors off
+    if (_prefs.connectorstyle() == FL_TREE_CONNECTOR_NONE) {
+      X -= _prefs.openicon()->w();
+      W += _prefs.openicon()->w();
+    }
     int Ysave = Y;
+     
     fl_push_clip(cx,cy,cw,ch);
     {
       fl_font(_prefs.labelfont(), _prefs.labelsize());
@@ -393,53 +400,34 @@
     fl_pop_clip();
     
     // Show vertical scrollbar?
-    int ydiff = (Y+_prefs.margintop())-Ysave;          // ydiff=size of tree
-    int ytoofar = (cy+ch) - Y;                         // ytoofar -- scrolled 
beyond bottom (e.g. stow)
-    
-    //printf("ydiff=%d ch=%d Ysave=%d ytoofar=%d value=%d\n",
-    //int(ydiff),int(ch),int(Ysave),int(ytoofar), int(_vscroll->value()));
-    
-    if ( ytoofar > 0 ) ydiff += ytoofar;
-    if ( Ysave<cy || ydiff > ch || int(_vscroll->value()) > 1 ) {
-      _vscroll->visible();
-
-      int scrollsize = _scrollbar_size ? _scrollbar_size : 
Fl::scrollbar_size();
-      int sx = x()+w()-Fl::box_dx(box())-scrollsize;
-      int sy = y()+Fl::box_dy(box());
-      int sw = scrollsize;
-      int sh = h()-Fl::box_dh(box());
-      _vscroll->show();
-      _vscroll->range(0.0,ydiff-ch);
-      _vscroll->resize(sx,sy,sw,sh);
-      _vscroll->slider_size(float(ch)/float(ydiff));
-    } else {
-      _vscroll->Fl_Slider::value(0);
-      _vscroll->hide();
-    }
-  }
-  // Draw children
-  fl_push_clip(cx,cy,cw-(_vscroll->visible()?_vscroll->w():0),ch);
-  // Similar to Fl_Group::draw(), but optimized to ignore drawing
-  // items outside the viewport.
-  // TODO: Suggest Fl_Group::draw() do this if clip_children() is enabled.
-  {
-    Fl_Widget*const* a = Fl_Group::array();
-    if (damage() & ~FL_DAMAGE_CHILD) { // redraw the entire thing:
-      for (int i=Fl_Group::children(); i--;) {
-       Fl_Widget& o = **a++;
-       if ( (o.y()+o.h()) < y() || (o.y() > (y()+h())) ) continue;
-       Fl_Group::draw_child(o);
-       Fl_Group::draw_outside_label(o);
+    {
+#if FLTK_ABI_VERSION >= 10302
+      // NEW
+      int SY = Y + _prefs.marginbottom();
+#else
+      // OLD
+      int SY = Y;
+#endif
+      int ydiff = (SY+_prefs.margintop())-Ysave;               // ydiff=size 
of tree
+      int ytoofar = (cy+ch) - SY;                              // ytoofar -- 
scrolled beyond bottom (e.g. stow)
+      if ( ytoofar > 0 ) ydiff += ytoofar;
+      if ( Ysave<cy || ydiff>ch || int(_vscroll->value())>1 ) {
+       _vscroll->visible();
+       int scrollsize = _scrollbar_size ? _scrollbar_size : 
Fl::scrollbar_size();
+       int sx = x()+w()-Fl::box_dx(box())-scrollsize;
+       int sy = y()+Fl::box_dy(box());
+       int sw = scrollsize;
+       int sh = h()-Fl::box_dh(box());
+       _vscroll->show();
+       _vscroll->resize(sx,sy,sw,sh);
+       _vscroll->slider_size(float(ch)/float(ydiff));
+       _vscroll->range(0.0,ydiff-ch);
+      } else {
+       _vscroll->Fl_Slider::value(0);
+       _vscroll->hide();
       }
-    } else {   // only redraw the children that need it:
-      for (int i=Fl_Group::children(); i--;) {
-       Fl_Widget& o = **a++;
-       if ( (o.y()+o.h()) < y() || (o.y() > (y()+h())) ) continue;
-       Fl_Group::update_child(o);
-      }
     }
   }
-  fl_pop_clip();
   draw_child(*_vscroll);       // draw scroll last
 }
 
@@ -1399,7 +1387,39 @@
   redraw();
 }
 
+#if FLTK_ABI_VERSION >= 10302
 /// Get the amount of white space (in pixels) that should appear
+/// below the last visible item when the vertical scroller is scrolled to the 
bottom.
+///
+int Fl_Tree::marginbottom() const {
+  return(_prefs.marginbottom());
+}
+
+/// Sets the amount of white space (in pixels) that should appear
+/// below the last visible item when the vertical scroller is scrolled to the 
bottom.
+///
+void Fl_Tree::marginbottom(int val) {
+  _prefs.marginbottom(val);
+  redraw();
+}
+#endif
+
+/// Get the amount of white space (in pixels) that should appear
+/// between items in the tree.
+///
+int Fl_Tree::linespacing() const {
+  return(_prefs.linespacing());
+}
+
+/// Sets the amount of white space (in pixels) that should appear
+/// between items in the tree.
+///
+void Fl_Tree::linespacing(int val) {
+  _prefs.linespacing(val);
+  redraw();
+}
+
+/// Get the amount of white space (in pixels) that should appear
 /// below an open child tree's contents.
 ///
 int Fl_Tree::openchild_marginbottom() const {
@@ -1413,6 +1433,41 @@
   _prefs.openchild_marginbottom(val);
   redraw();
 }
+/// Get the amount of white space (in pixels) that should appear
+/// to the left of the usericon.
+int Fl_Tree::usericonmarginleft() const {
+  return(_prefs.usericonmarginleft());
+}
+/// Set the amount of white space (in pixels) that should appear
+/// to the left of the usericon.
+void Fl_Tree::usericonmarginleft(int val) {
+  _prefs.usericonmarginleft(val);
+  redraw();
+}
+/// Get the amount of white space (in pixels) that should appear
+/// to the left of the label text.
+int Fl_Tree::labelmarginleft() const {
+  return(_prefs.labelmarginleft());
+}
+/// Set the amount of white space (in pixels) that should appear
+/// to the left of the label text.
+void Fl_Tree::labelmarginleft(int val) {
+  _prefs.labelmarginleft(val);
+  redraw();
+}
+#if FLTK_ABI_VERSION >= 10302
+/// Get the amount of white space (in pixels) that should appear
+/// to the left of the child fltk widget (if any).
+int Fl_Tree::widgetmarginleft() const {
+  return(_prefs.widgetmarginleft());
+}
+/// Set the amount of white space (in pixels) that should appear
+/// to the left of the child fltk widget (if any).
+void Fl_Tree::widgetmarginleft(int val) {
+  _prefs.widgetmarginleft(val);
+  redraw();
+}
+#endif
 
 /// Gets the width of the horizontal connection lines (in pixels) 
 /// that appear to the left of each tree item's label.
@@ -1570,6 +1625,32 @@
   _prefs.selectmode(val);
 }
 
+#if FLTK_ABI_VERSION >= 10302
+/// Returns the current item re/selection mode
+Fl_Tree_Item_Reselect_Mode Fl_Tree::item_reselect_mode() const {
+  return(_prefs.item_reselect_mode());
+}
+
+/// Sets the item re/selection mode
+void Fl_Tree::item_reselect_mode(Fl_Tree_Item_Reselect_Mode mode) {
+  _prefs.item_reselect_mode(mode);
+}
+
+/// Get the 'item draw mode' used for the tree
+Fl_Tree_Item_Draw_Mode Fl_Tree::item_draw_mode() const {
+  return(_prefs.item_draw_mode());
+}
+
+/// Set the 'item draw mode' used for the tree to \p val.
+///     This affects how items in the tree are drawn,
+///     such as when a widget() is defined. 
+///     See Fl_Tree_Item_Draw_Mode for possible values.
+///
+void Fl_Tree::item_draw_mode(Fl_Tree_Item_Draw_Mode val) {
+  _prefs.item_draw_mode(val);
+}
+#endif
+
 /// See if \p item is currently displayed on-screen (visible within the 
widget).
 /// This can be used to detect if the item is scrolled off-screen.
 /// Checks to see if the item's vertical position is within the top and bottom

Modified: branches/branch-1.3/src/Fl_Tree_Item.cxx
===================================================================
--- branches/branch-1.3/src/Fl_Tree_Item.cxx    2012-04-22 13:09:19 UTC (rev 
9376)
+++ branches/branch-1.3/src/Fl_Tree_Item.cxx    2012-04-22 13:40:02 UTC (rev 
9377)
@@ -26,6 +26,7 @@
 //
 //     http://www.fltk.org/str.php
 //
+/////////////////////////////////////////////////////////////////////////// 80 
/
 
 // Was the last event inside the specified xywh?
 static int event_inside(const int xywh[4]) {
@@ -556,6 +557,25 @@
 #endif
 }
 
+/// Return the item's 'visible' height
+int Fl_Tree_Item::calc_item_height(const Fl_Tree_Prefs &prefs) {
+  if ( ! _visible ) return(0);
+  int H = 0;
+  if ( _label ) {
+    fl_font(_labelfont, _labelsize);   // fldescent() needs this :/
+    H = _labelsize + fl_descent() + 1; // at least one pixel space below 
descender
+  }
+  if ( has_children() && prefs.openicon() && H<prefs.openicon()->h() )
+    H = prefs.openicon()->h();
+  if ( usericon() && H<usericon()->h() )
+    H = usericon()->h();
+  // NO: we don't use widget's height, we force it to match ours
+  //if ( widget() && widget()->visible() && H<widget()->h() )
+  //  H = widget()->h();
+  H += prefs.linespacing();
+  return(H);
+}
+
 /// Draw this item and its children.
 void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree,
                        Fl_Tree_Item *itemfocus,
@@ -563,145 +583,167 @@
   if ( ! _visible ) return; 
   int tree_top = tree->y();
   int tree_bot = tree_top + tree->h();
-  fl_font(_labelfont, _labelsize);
-  int H = _labelsize;
-  if(usericon() && H < usericon()->h()) H = usericon()->h(); 
-  H += prefs.linespacing() + fl_descent();
-  // adjust horizontally if we draw no connecting lines
-  if ( is_root() && prefs.connectorstyle() == FL_TREE_CONNECTOR_NONE ) {
-    X -= prefs.openicon()->w();
-    W += prefs.openicon()->w();
-  }
-  // Colors, fonts
-  Fl_Color fg = _selected ? fl_contrast(_labelfgcolor, tree->selection_color())
-                          : _active ? _labelfgcolor 
-                                   : fl_inactive(_labelfgcolor);
-  Fl_Color bg = _selected ? _active ? tree->selection_color() 
-                                    : fl_inactive(tree->selection_color())
-                          : _labelbgcolor;
+  int H = calc_item_height(prefs);
+
   // Update the xywh of this item
   _xywh[0] = X;
   _xywh[1] = Y;
   _xywh[2] = W;
   _xywh[3] = H;
-  // Text size
-  int textw=0, texth=0;
-  fl_measure(_label, textw, texth, 0);
-  int textycenter = Y+(H/2);
+
+  // Determine collapse icon's xywh
+  //   Note: calculate collapse icon's xywh for possible mouse click detection.
+  //   We don't care about items clipped off the viewport; they won't get 
mouse events.
+  //
+  int item_y_center = Y+(H/2);
   int &icon_w = _collapse_xywh[2] = prefs.openicon()->w();
   int &icon_x = _collapse_xywh[0] = X + (icon_w + prefs.connectorwidth())/2 - 
3;
-  int &icon_y = _collapse_xywh[1] = textycenter - (prefs.openicon()->h()/2);
+  int &icon_y = _collapse_xywh[1] = item_y_center - (prefs.openicon()->h()/2);
   _collapse_xywh[3] = prefs.openicon()->h();
+
   // Horizontal connector values
-  int hstartx  = X+icon_w/2-1;
-  int hendx    = hstartx + prefs.connectorwidth();
-  int hcenterx = X + icon_w + ((hendx - (X + icon_w)) / 2);
-  
-  // See if we should draw this item
-  //    If this item is root, and showroot() is disabled, don't draw.
-  //    'clipped' is an optimization to prevent drawing anything offscreen.
+  //   XXX: Must calculate these even if(clipped) because 'draw children' code 
(below)
+  //   needs hconn_x_center value. (Otherwise, these calculations could be 
'clipped')
   //
+  int hconn_x  = X+icon_w/2-1;
+  int hconn_x2 = hconn_x + prefs.connectorwidth();
+  int hconn_x_center = X + icon_w + ((hconn_x2 - (X + icon_w)) / 2);
+  int cw1 = icon_w+prefs.connectorwidth()/2, cw2 = prefs.connectorwidth();
+  int conn_w = cw1>cw2 ? cw1 : cw2;
+
+  // Background position
+  int &bg_x = _label_xywh[0] = X+(icon_w/2-1+conn_w);
+  int &bg_y = _label_xywh[1] = Y;
+  int &bg_w = _label_xywh[2] = W-(icon_w/2-1+conn_w);
+  int &bg_h = _label_xywh[3] = H;
+
+  // Usericon position
+  int uicon_x = bg_x + ( (usericon() || prefs.usericon()) ? 
prefs.usericonmarginleft() : 0);
+  int uicon_w = usericon() ? usericon()->w() : prefs.usericon() ? 
prefs.usericon()->w() : 0;
+
+  // Label position
+  int label_x = uicon_x + uicon_w + (_label ? prefs.labelmarginleft() : 0);
+
+  // Recalc widget position
+  //   Do this whether clipped or not, so that when scrolled,
+  //   the widgets move to appropriate 'offscreen' positions
+  //   (so that they don't get mouse events, etc)
+  //
+  if ( widget() ) {
+    int wx = label_x;
+    int wy = bg_y;
+    int ww = widget()->w();            // use widget's width
+    int wh = H;                                // lock widget's height to item 
height
+#if FLTK_ABI_VERSION >= 10302
+    if ( _label && prefs.item_draw_mode() == 
FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET ) {
+#else
+    if ( _label && !widget() ) {       // back compat: don't draw label if 
widget() present
+#endif
+      fl_font(_labelfont, _labelsize); // fldescent() needs this
+      int dx,dy,lw,lh;
+      fl_text_extents(_label,dx,dy,lw,lh);
+#if FLTK_ABI_VERSION >= 10302
+      // NEW
+      wx += (lw + prefs.widgetmarginleft());
+#else
+      // OLD
+      wx += (lw + 3);
+#endif
+    }
+    if ( widget()->x() != wx || widget()->y() != wy ||
+        widget()->w() != ww || widget()->h() != wh ) {
+      widget()->resize(wx,wy,ww,wh);           // we'll handle redraw below
+    }
+  }
+  char clipped = ((Y+H) < tree_top) || (Y>tree_bot) ? 1 : 0;
   char drawthis = ( is_root() && prefs.showroot() == 0 ) ? 0 : 1;
-  char clipped = ((Y+H) < tree_top) || (Y>tree_bot) ? 1 : 0;
-  if ( drawthis ) {
-    // Draw connectors
-    if ( prefs.connectorstyle() != FL_TREE_CONNECTOR_NONE ) {
-      // Horiz connector between center of icon and text
-      // if this is root, the connector should not dangle in thin air on the 
left
-      if (is_root()) {
-        if (!clipped) draw_horizontal_connector(hcenterx, hendx, textycenter, 
prefs);
-      } else {
-        if (!clipped) draw_horizontal_connector(hstartx, hendx, textycenter, 
prefs);
-      }
-      if ( has_children() && is_open() ) {
-        // Small vertical line down to children
-        if (!clipped) draw_vertical_connector(hcenterx, textycenter, Y+H, 
prefs);
-      }
-      // Connectors for last child
-      if ( ! is_root() ) {
-        if ( lastchild ) {
-          if (!clipped) draw_vertical_connector(hstartx, Y, textycenter, 
prefs);
-        } else {
-          if (!clipped) draw_vertical_connector(hstartx, Y, Y+H, prefs);
-        }
-      }
-    } 
-    // Draw collapse icon
-    if ( has_children() && prefs.showcollapse() ) {
-      // Draw icon image
-      if ( is_open() ) {
-        if (!clipped) prefs.closeicon()->draw(icon_x,icon_y);
-      } else {
-        if (!clipped) prefs.openicon()->draw(icon_x,icon_y);
-      }
-    }
-    // Background for this item
-    int cw1 = icon_w+prefs.connectorwidth()/2, cw2 = prefs.connectorwidth();
-    int cwidth = cw1>cw2 ? cw1 : cw2;
-    int &bx = _label_xywh[0] = X+(icon_w/2-1+cwidth);
-    int &by = _label_xywh[1] = Y;
-    int &bw = _label_xywh[2] = W-(icon_w/2-1+cwidth);
-    int &bh = _label_xywh[3] = H;
-    // Draw bg only if different from tree's bg
-    if ( bg != tree->color() || is_selected() ) {
-      if ( is_selected() ) {
-        // Selected? Use selectbox() style
-        if (!clipped) fl_draw_box(prefs.selectbox(), bx, by, bw, bh, bg);
-      } else {
-        // Not Selected? use plain filled rectangle
-       if (!clipped) {
-         fl_color(bg);
-         fl_rectf(bx, by, bw, bh);
+  if ( !clipped ) {
+    Fl_Color fg = _selected ? fl_contrast(_labelfgcolor, 
tree->selection_color())
+                           : _active ? _labelfgcolor 
+                                     : fl_inactive(_labelfgcolor);
+    Fl_Color bg = _selected ? _active ? tree->selection_color() 
+                                     : fl_inactive(tree->selection_color())
+                           : _labelbgcolor;
+    // See if we should draw this item
+    //    If this item is root, and showroot() is disabled, don't draw.
+    //    'clipped' is an optimization to prevent drawing anything offscreen.
+    //
+    if ( drawthis ) {                                  // draw this item at 
all?
+      if ( tree->damage() & ~FL_DAMAGE_CHILD ) {       // non-child damage?
+       // Draw connectors
+       if ( prefs.connectorstyle() != FL_TREE_CONNECTOR_NONE ) {
+         // Horiz connector between center of icon and text
+         // if this is root, the connector should not dangle in thin air on 
the left
+         if (is_root()) draw_horizontal_connector(hconn_x_center, hconn_x2, 
item_y_center, prefs);
+         else           draw_horizontal_connector(hconn_x, hconn_x2, 
item_y_center, prefs);
+         // Small vertical line down to children
+         if ( has_children() && is_open() )
+           draw_vertical_connector(hconn_x_center, item_y_center, Y+H, prefs);
+         // Connectors for last child
+         if ( !is_root() ) {
+           if ( lastchild ) draw_vertical_connector(hconn_x, Y, item_y_center, 
prefs);
+           else             draw_vertical_connector(hconn_x, Y, Y+H, prefs);
+         }
        }
+       // Draw collapse icon
+       if ( has_children() && prefs.showcollapse() ) {
+         // Draw icon image
+         if ( is_open() ) {
+           prefs.closeicon()->draw(icon_x,icon_y);
+         } else {
+           prefs.openicon()->draw(icon_x,icon_y);
+         }
+       }
+       // Background for this item
+       // Draw bg only if different from tree's bg
+       if ( bg != tree->color() || is_selected() ) {
+         if ( is_selected() ) {                        // Selected? Use 
selectbox() style
+           fl_draw_box(prefs.selectbox(),bg_x,bg_y,bg_w,bg_h,bg);
+         } else {                                      // Not Selected? use 
plain filled rectangle
+           fl_color(bg);
+           fl_rectf(bg_x,bg_y,bg_w,bg_h);
+         }
+         if ( widget() ) widget()->damage(FL_DAMAGE_ALL);      // if there's a 
child widget, we just damaged it
+       }
+       // Draw user icon (if any)
+       if ( usericon() ) {
+         // Item has user icon? Use it
+         int uicon_y = item_y_center - (usericon()->h() >> 1);
+         usericon()->draw(uicon_x,uicon_y);
+       } else if ( prefs.usericon() ) {
+         // Prefs has user icon? Use it
+         int uicon_y = item_y_center - (prefs.usericon()->h() >> 1);
+         prefs.usericon()->draw(uicon_x,uicon_y);
+       }
+       // Draw label
+#if FLTK_ABI_VERSION >= 10302
+        if ( _label && 
+            ( !widget() || prefs.item_draw_mode() ==
+              FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET) ) {
+#else
+        if ( _label && !widget() ) {   // back compat: don't draw label if 
widget() present
+#endif
+         int label_y = Y+(H/2)+(_labelsize/2)-fl_descent()/2;
+         fl_color(fg);
+         fl_font(_labelfont, _labelsize);
+         fl_draw(_label, label_x, label_y);
+       }
+      }                        // end non-child damage
+      // Draw child FLTK widget?
+      if ( widget() && widget()->damage() ) {
+        widget()->draw();
       }
-    }
-    // Draw user icon (if any)
-    int useroff = (icon_w/2-1+cwidth);
-    if ( usericon() ) {
-      // Item has user icon? Use it
-      useroff += prefs.usericonmarginleft();
-      icon_y = textycenter - (usericon()->h() >> 1);
-      if (!clipped) usericon()->draw(X+useroff,icon_y);
-      useroff += usericon()->w();
-    } else if ( prefs.usericon() ) {
-      // Prefs has user icon? Use it
-      useroff += prefs.usericonmarginleft();
-      icon_y = textycenter - (prefs.usericon()->h() >> 1);
-      if (!clipped) prefs.usericon()->draw(X+useroff,icon_y);
-      useroff += prefs.usericon()->w();
-    }
-    useroff += prefs.labelmarginleft();
-    // Draw label
-    if ( widget() ) {
-      // Widget? Draw it
-      int lx = X+useroff;
-      int ly = by;
-      int lw = widget()->w();
-      int lh = bh;
-      if ( widget()->x() != lx || widget()->y() != ly ||
-          widget()->w() != lw || widget()->h() != lh ) {
-        widget()->resize(lx, ly, lw, lh);              // fltk will handle 
drawing this
+      // Draw focus box around item's bg last
+      if ( this == itemfocus && Fl::visible_focus() && Fl::focus() == tree) {
+       draw_item_focus(FL_NO_BOX,bg,bg_x+1,bg_y+1,bg_w-1,bg_h-1);
       }
-    } else {
-      // No label widget? Draw text label
-      if ( _label && !clipped ) {
-        fl_color(fg);
-        fl_draw(_label, X+useroff, Y+H-fl_descent()-1);
-      }
-    }
-    if ( !clipped &&
-         this == itemfocus &&
-         Fl::visible_focus() &&
-        Fl::focus() == tree) {
-      // Draw focus box around this item
-      draw_item_focus(FL_NO_BOX,bg,bx+1,by+1,bw-1,bh-1);
-    }
-    Y += H;
-  }                    // end drawthis
-  // Draw children
+    }                  // end drawthis
+  }                    // end clipped
+  if ( drawthis ) Y += H;                      // adjust Y (even if clipped)
+  // Draw child items (if any)
   if ( has_children() && is_open() ) {
-    int child_x = drawthis ?                           // offset children to 
right,
-    (hcenterx - (icon_w/2) + 1) : X;                   // unless didn't 
drawthis
+    int child_x = drawthis ? (hconn_x_center - (icon_w/2) + 1) // offset 
children to right,
+                           : X;                                        // 
unless didn't drawthis
     int child_w = W - (child_x-X);
     int child_y_start = Y;
     for ( int t=0; t<children(); t++ ) {
@@ -715,7 +757,7 @@
       // Special 'clipped' calculation. (intentional variable shadowing)
       int clipped = ((child_y_start < tree_top) && (Y < tree_top)) ||
                     ((child_y_start > tree_bot) && (Y > tree_bot));
-      if (!clipped) draw_vertical_connector(hstartx, child_y_start, Y, prefs);
+      if (!clipped) draw_vertical_connector(hconn_x, child_y_start, Y, prefs);
     }
   }
 }

Modified: branches/branch-1.3/src/Fl_Tree_Prefs.cxx
===================================================================
--- branches/branch-1.3/src/Fl_Tree_Prefs.cxx   2012-04-22 13:09:19 UTC (rev 
9376)
+++ branches/branch-1.3/src/Fl_Tree_Prefs.cxx   2012-04-22 13:40:02 UTC (rev 
9377)
@@ -125,11 +125,15 @@
   _labelsize              = FL_NORMAL_SIZE;
   _marginleft             = 6;
   _margintop              = 3;
-  //_marginright          = 3;
-  //_marginbottom         = 3;
+#if FLTK_ABI_VERSION >= 10302
+  _marginbottom           = 20;
+#endif
   _openchild_marginbottom = 0;
   _usericonmarginleft     = 3;
   _labelmarginleft        = 3;
+#if FLTK_ABI_VERSION >= 10302
+  _widgetmarginleft       = 3;
+#endif
   _linespacing            = 0;
   _labelfgcolor           = FL_BLACK;
   _labelbgcolor           = FL_WHITE;
@@ -148,6 +152,10 @@
   _sortorder              = FL_TREE_SORT_NONE;
   _selectbox              = FL_FLAT_BOX;
   _selectmode             = FL_TREE_SELECT_SINGLE;
+#if FLTK_ABI_VERSION >= 10302
+  _itemreselectmode       = FL_TREE_SELECTABLE_ONCE;
+  _itemdrawmode           = FL_TREE_ITEM_DRAW_WIDGET_ONLY;
+#endif
   // Let fltk's current 'scheme' affect defaults
   if ( Fl::scheme() ) {
     if ( strcmp(Fl::scheme(), "gtk+") == 0 ) {

_______________________________________________
fltk-commit mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-commit

Reply via email to