From f58cd169c08a4be9ae07903a9e61b686bb7a75b6 Mon Sep 17 00:00:00 2001 From: Greg Ercolano Date: Sun, 22 Apr 2012 13:40:02 +0000 Subject: [PATCH] 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 git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@9377 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- FL/Fl_Tree.H | 43 ++-- FL/Fl_Tree_Item.H | 3 +- FL/Fl_Tree_Prefs.H | 98 +++++++--- documentation/src/tree-elements.png | Bin 9673 -> 12750 bytes examples/tree-as-container.cxx | 4 +- src/Fl_Tree.cxx | 179 ++++++++++++----- src/Fl_Tree_Item.cxx | 292 ++++++++++++++++------------ src/Fl_Tree_Prefs.cxx | 12 +- 8 files changed, 405 insertions(+), 226 deletions(-) diff --git a/FL/Fl_Tree.H b/FL/Fl_Tree.H index aa43fd2a1..1b8dbd758 100644 --- a/FL/Fl_Tree.H +++ b/FL/Fl_Tree.H @@ -194,17 +194,6 @@ enum Fl_Tree_Reason { 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 @@ class FL_EXPORT Fl_Tree : public Fl_Group { #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 @@ public: 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 @@ public: 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); diff --git a/FL/Fl_Tree_Item.H b/FL/Fl_Tree_Item.H index d090df1b6..9b7a7d56b 100644 --- a/FL/Fl_Tree_Item.H +++ b/FL/Fl_Tree_Item.H @@ -62,7 +62,7 @@ class FL_EXPORT Fl_Tree_Item { 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 @@ public: 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); diff --git a/FL/Fl_Tree_Prefs.H b/FL/Fl_Tree_Prefs.H index 0db3881f7..58eed4044 100644 --- a/FL/Fl_Tree_Prefs.H +++ b/FL/Fl_Tree_Prefs.H @@ -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_Connector { 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 @@ class FL_EXPORT Fl_Tree_Prefs { 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 @@ class FL_EXPORT Fl_Tree_Prefs { 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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*/ diff --git a/documentation/src/tree-elements.png b/documentation/src/tree-elements.png index 0e3bbea6a93c11654bbf7e4385d5e9110a19f593..78997cfec04a5d73ef90a03ef973edfaeef26e9f 100644 GIT binary patch literal 12750 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 X&-+Tm_QL5=Jq0MqsmoSNn}z&8a#E*n diff --git a/examples/tree-as-container.cxx b/examples/tree-as-container.cxx index 73a7fb580..fa3280a93 100644 --- a/examples/tree-as-container.cxx +++ b/examples/tree-as-container.cxx @@ -23,10 +23,10 @@ #include #include -#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]; diff --git a/src/Fl_Tree.cxx b/src/Fl_Tree.cxx index 2d68a3037..8769578cc 100644 --- a/src/Fl_Tree.cxx +++ b/src/Fl_Tree.cxx @@ -102,7 +102,6 @@ Fl_Tree::Fl_Tree(int X, int Y, int W, int H, const char *L) : Fl_Group(X,Y,W,H,L #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 @@ void Fl_Tree::draw() { 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 @@ void Fl_Tree::draw() { 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 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); - } - } 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); + { +#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 ( Ysavech || 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(); } } } - fl_pop_clip(); draw_child(*_vscroll); // draw scroll last } @@ -1399,6 +1387,38 @@ void Fl_Tree::margintop(int val) { 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. /// @@ -1413,6 +1433,41 @@ void Fl_Tree::openchild_marginbottom(int val) { _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 @@ void Fl_Tree::selectmode(Fl_Tree_Select val) { _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 diff --git a/src/Fl_Tree_Item.cxx b/src/Fl_Tree_Item.cxx index 1b28602c9..ea91092fb 100644 --- a/src/Fl_Tree_Item.cxx +++ b/src/Fl_Tree_Item.cxx @@ -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 @@ static void draw_item_focus(Fl_Boxtype B, Fl_Color C, int X, int Y, int W, int H #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() && Hh() ) + H = prefs.openicon()->h(); + if ( usericon() && Hh() ) + H = usericon()->h(); + // NO: we don't use widget's height, we force it to match ours + //if ( widget() && widget()->visible() && Hh() ) + // 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 @@ void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree, 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') // - char drawthis = ( is_root() && prefs.showroot() == 0 ) ? 0 : 1; + 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; - 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); + char drawthis = ( is_root() && prefs.showroot() == 0 ) ? 0 : 1; + 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 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); } } } diff --git a/src/Fl_Tree_Prefs.cxx b/src/Fl_Tree_Prefs.cxx index b8b640d4a..c32262d5b 100644 --- a/src/Fl_Tree_Prefs.cxx +++ b/src/Fl_Tree_Prefs.cxx @@ -125,11 +125,15 @@ Fl_Tree_Prefs::Fl_Tree_Prefs() { _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 @@ Fl_Tree_Prefs::Fl_Tree_Prefs() { _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 ) {