From 474feee1db323f45fb121b02d76e776cb5c7c2f1 Mon Sep 17 00:00:00 2001 From: Greg Ercolano Date: Fri, 27 Apr 2012 02:03:48 +0000 Subject: o Added FL_TREE_ITEM_HEIGHT_FROM_WIDGET option to item_draw_mode() to allow widgets to control the size of items in the tree (instead of vice versa). o Added item_draw_mode(int) to allow for easier bitflag maintenance, since enums don't seem to be typesafe yet. o Tree demo modified to demonstrate this feature. An important feature for adding large widgets to tree items. Will probably add an example, 'tree-of-tables' to demo this usage. o Small doc fixes. o Had to rename FL_TREE_ITEM_DRAW_WIDGET_ONLY to FL_TREE_ITEM_DRAW_DEFAULT. Its meaning for the bit fields changed when new bit fields were added. (The prev name just didn't make sense in the new context. Since it was just a few svn commits old and an unreleased ABI feature, it shouldn't affect anyone not in R&D) git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@9404 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- FL/Fl_Tree.H | 29 ++++++++---- FL/Fl_Tree_Item.H | 8 ++-- FL/Fl_Tree_Prefs.H | 18 +++++--- src/Fl_Tree.cxx | 5 ++- src/Fl_Tree_Item.cxx | 26 +++++++---- src/Fl_Tree_Prefs.cxx | 2 +- test/tree.fl | 121 ++++++++++++++++++++++++++++++++++---------------- 7 files changed, 140 insertions(+), 69 deletions(-) diff --git a/FL/Fl_Tree.H b/FL/Fl_Tree.H index e934963a0..a53560f8b 100644 --- a/FL/Fl_Tree.H +++ b/FL/Fl_Tree.H @@ -52,9 +52,9 @@ /// |--- Fl_Tree_Sort (enum) // Sort behavior /// \endcode /// -/// Similar to Fl_Browser, Fl_Tree is a browser of Fl_Tree_Item's, which is arranged -/// in a parented hierarchy, or 'tree'. Subtrees can be expanded or closed. Items can be -/// added, deleted, inserted, sorted and re-ordered. +/// Similar to Fl_Browser, Fl_Tree is a browser of Fl_Tree_Item's arranged +/// in a parented hierarchy, or 'tree'. Subtrees can be expanded or closed. +/// Items can be added, deleted, inserted, sorted and re-ordered. /// /// The tree items may also contain other FLTK widgets, like buttons, input fields, /// or even "custom" widgets. @@ -100,13 +100,23 @@ /// FLTK widgets (including custom widgets) can be assigned to tree items via /// Fl_Tree_Item::widget(). /// -/// Icons for individual items can be changed with -/// Fl_Tree_Item::openicon(), -/// Fl_Tree_Item::closeicon(), -/// Fl_Tree_Item::usericon(). +/// When a widget() is defined, the default behavior is for the widget() +/// to be shown in place of the item's label (if it has one). +/// Only the widget()'s width will be used; the widget()'s x() and y() position +/// will be managed by the tree, and the h() will track the item's height. +/// This default behavior can be altered: +/// Setting Fl_Tree::item_draw_mode()'s FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET flag +/// causes the label + widget to be displayed together in that order, and +/// adding the FL_TREE_ITEM_HEIGHT_FROM_WIDGET flag causes widget's height +/// to define the widget()'s height. +/// +/// The tree's open/close icons can be redefined with +/// Fl_Tree::openicon(), Fl_Tree::closeicon(). User icons +/// can either be changed globally with Fl_Tree::usericon(), +/// or on a per-item basis with Fl_Tree_Item::usericon(). /// /// Various default preferences can be globally manipulated via Fl_Tree_Prefs, -/// including colors, margins, icons, connection lines. +/// including colors, margins, icons, connection lines, etc. /// /// The tree's callback() will be invoked when items change state or are open/closed. /// when() controls when mouse/keyboard events invoke the callback. @@ -125,7 +135,7 @@ /// } /// \endcode /// -/// To get the item's full menu pathname, you can use Fl_Tree_Item::item_pathname(), eg: +/// To get the item's full menu pathname, you can use Fl_Tree::item_pathname(), eg: /// /// \code /// char pathname[256] = "???"; @@ -415,6 +425,7 @@ public: 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); + void item_draw_mode(int mode); #endif int displayed(Fl_Tree_Item *item); diff --git a/FL/Fl_Tree_Item.H b/FL/Fl_Tree_Item.H index ff6e5c50a..83d6a4b42 100644 --- a/FL/Fl_Tree_Item.H +++ b/FL/Fl_Tree_Item.H @@ -232,7 +232,7 @@ public: select(); // select if deselected } } - /// Select self and all children + /// Select item and all its children. /// Returns count of how many items were in the 'deselected' state, /// ie. how many items were "changed". /// @@ -251,7 +251,7 @@ public: void deselect() { _selected = 0; } - /// Deselect self and all children + /// Deselect item and all its children. /// Returns count of how many items were in the 'selected' state, /// ie. how many items were "changed". /// @@ -310,11 +310,11 @@ public: } int visible_r() const; - /// Set the user icon's image. '0' will disable. + /// Set the item's user icon to an Fl_Image. '0' will disable. void usericon(Fl_Image *val) { _usericon = val; } - /// Get the user icon. Returns '0' if disabled. + /// Get the item's user icon as an Fl_Image. Returns '0' if disabled. Fl_Image *usericon() const { return(_usericon); } diff --git a/FL/Fl_Tree_Prefs.H b/FL/Fl_Tree_Prefs.H index f396b80ce..12dcafdbf 100644 --- a/FL/Fl_Tree_Prefs.H +++ b/FL/Fl_Tree_Prefs.H @@ -73,19 +73,23 @@ enum Fl_Tree_Select { #if FLTK_ABI_VERSION >= 10302 /// \enum Fl_Tree_Item_Reselect_Mode -/// Defines the ways an item can be (re) selected. +/// Defines the ways an item can be (re) selected +/// via item_reselect_mode(). /// enum Fl_Tree_Item_Reselect_Mode { - FL_TREE_SELECTABLE_ONCE=0, ///< item can only be selected once (default) - FL_TREE_SELECTABLE_ALWAYS, ///< enables FL_TREE_REASON_RESELECTED events for callbacks + FL_TREE_SELECTABLE_ONCE=0, ///< Item can only be selected once (default) + FL_TREE_SELECTABLE_ALWAYS, ///< Enables FL_TREE_REASON_RESELECTED events for callbacks }; /// \enum Fl_Tree_Item_Draw_Mode -/// Controls how item's labels and widget()s are drawn in the tree. +/// Bit flags that control how item's labels and widget()s are drawn in the tree +/// via item_draw_mode(). /// 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 + FL_TREE_ITEM_DRAW_DEFAULT=0, ///< If widget() defined, draw in place of label, + ///< and widget() tracks item height (default) + FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET=1, ///< If widget() defined, include label to the left of the widget + FL_TREE_ITEM_HEIGHT_FROM_WIDGET=2 ///< If widget() defined, widget()'s height controls item's height }; #endif @@ -128,7 +132,7 @@ class FL_EXPORT Fl_Tree_Prefs { 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() + Fl_Tree_Item_Draw_Mode _itemdrawmode; // controls how items draw label + widget() #endif public: Fl_Tree_Prefs(); diff --git a/src/Fl_Tree.cxx b/src/Fl_Tree.cxx index 48eca8460..e1ab1baf0 100644 --- a/src/Fl_Tree.cxx +++ b/src/Fl_Tree.cxx @@ -554,7 +554,7 @@ Fl_Tree_Item* Fl_Tree::add(const char *path) { return(item); } -/// Add a new child to a tree-item. +/// Add a new child to a specific item in the tree. /// /// \param[in] item The existing item to add new child to. Must not be NULL. /// \param[in] name The label for the new item @@ -1724,6 +1724,9 @@ Fl_Tree_Item_Draw_Mode Fl_Tree::item_draw_mode() const { void Fl_Tree::item_draw_mode(Fl_Tree_Item_Draw_Mode val) { _prefs.item_draw_mode(val); } +void Fl_Tree::item_draw_mode(int val) { + _prefs.item_draw_mode(Fl_Tree_Item_Draw_Mode(val)); +} #endif /// See if \p item is currently displayed on-screen (visible within the widget). diff --git a/src/Fl_Tree_Item.cxx b/src/Fl_Tree_Item.cxx index 39e061d64..79ab11ad4 100644 --- a/src/Fl_Tree_Item.cxx +++ b/src/Fl_Tree_Item.cxx @@ -564,9 +564,16 @@ int Fl_Tree_Item::calc_item_height(const Fl_Tree_Prefs &prefs) const { if ( ! _visible ) return(0); int H = 0; if ( _label ) { - fl_font(_labelfont, _labelsize); // fldescent() needs this :/ + fl_font(_labelfont, _labelsize); // fl_descent() needs this :/ H = _labelsize + fl_descent() + 1; // at least one pixel space below descender } +#if FLTK_ABI_VERSION >= 10302 + if ( widget() && + (prefs.item_draw_mode() & FL_TREE_ITEM_HEIGHT_FROM_WIDGET) && + H < widget()->h()) { + H = widget()->h(); + } +#endif if ( has_children() && prefs.openicon() && Hh() ) H = prefs.openicon()->h(); if ( usericon() && Hh() ) @@ -632,15 +639,18 @@ void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree, 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 ) { + int wh = (prefs.item_draw_mode() & FL_TREE_ITEM_HEIGHT_FROM_WIDGET) + ? widget()->h() : H; + if ( _label && + (prefs.item_draw_mode() & FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET) ) { #else + int wh = H; // lock widget's height to item height 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); + int lw=0, lh=0; + fl_measure(_label,lw,lh); // get box around text (including white space) #if FLTK_ABI_VERSION >= 10302 // NEW wx += (lw + prefs.widgetmarginleft()); @@ -717,14 +727,14 @@ void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree, // Draw label #if FLTK_ABI_VERSION >= 10302 if ( _label && - ( !widget() || prefs.item_draw_mode() == - FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET) ) { + ( !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); + int label_y = Y+(H/2)+(_labelsize/2)-fl_descent()/2; fl_draw(_label, label_x, label_y); } } // end non-child damage diff --git a/src/Fl_Tree_Prefs.cxx b/src/Fl_Tree_Prefs.cxx index c32262d5b..7f4a5337b 100644 --- a/src/Fl_Tree_Prefs.cxx +++ b/src/Fl_Tree_Prefs.cxx @@ -154,7 +154,7 @@ Fl_Tree_Prefs::Fl_Tree_Prefs() { _selectmode = FL_TREE_SELECT_SINGLE; #if FLTK_ABI_VERSION >= 10302 _itemreselectmode = FL_TREE_SELECTABLE_ONCE; - _itemdrawmode = FL_TREE_ITEM_DRAW_WIDGET_ONLY; + _itemdrawmode = FL_TREE_ITEM_DRAW_DEFAULT; #endif // Let fltk's current 'scheme' affect defaults if ( Fl::scheme() ) { diff --git a/test/tree.fl b/test/tree.fl index 2d6c1bdce..10c7185d8 100644 --- a/test/tree.fl +++ b/test/tree.fl @@ -52,9 +52,24 @@ Function {reason_as_name(Fl_Tree_Reason reason)} { }} {} } -Function {Button_CB(Fl_Widget*w, void*data)} {return_type void +Function {Button_CB(Fl_Widget*w, void*data)} {open return_type void } { - code {fprintf(stderr, "'%s' button pushed\\n", w->label());} {} + code {// Each push changes height so we can test 'Item h() from widget' +// Cycle through larger sizes until 50, then wrap to normal size. +// +// In the case of 'ccc button', it is the child widget, so change +// its size. +// +// In the case of the 'D1' and 'D2' buttons, the parent's Fl_Group +// is the child, so change the size of that instead. +// +Fl_Widget *cw = strcmp(w->label(), "ccc button")==0 ? w : w->parent(); +int height = cw->h(); +height += 10; +if ( height > 50 ) height = 20; +cw->resize(cw->x(), cw->y(), cw->w(), height); +tree->redraw(); // adjusted height +fprintf(stderr, "'%s' button pushed (height=%d)\\n", w->label(), height);} {} } Function {AssignUserIcons()} { @@ -135,6 +150,9 @@ tree->add("Bbb/child-04"); but = new Fl_Button(1,1,140,1,"ccc button"); // we control w() only but->labelsize(10); but->callback(Button_CB); + but->tooltip("Button inside tree.\\n" + "If 'Item h() from widget' enabled, " + "pressing button enlarges it."); } i->widget(but); tree->end(); @@ -143,6 +161,10 @@ tree->add("Bbb/child-04"); { // Assign an FLTK group to one of the items with widgets Fl_Tree_Item *i; + const char *tipmsg = "A group of two buttons inside the tree.\\n" + "If 'Item h() from widget' enabled, " + "pressing either button enlarges the group " + "and both buttons together."; if ( ( i = tree->find_item("Bbb/child-04") ) != NULL ) { static Fl_Group *grp = 0; if ( !grp ) { // only do this once at program startup @@ -153,9 +175,12 @@ tree->add("Bbb/child-04"); Fl_Button *abut = new Fl_Button(grp->x()+0 ,grp->y()+2,65,15,"D1"); abut->labelsize(10); abut->callback(Button_CB); + abut->tooltip(tipmsg); Fl_Button *bbut = new Fl_Button(grp->x()+75,grp->y()+2,65,15,"D2"); bbut->labelsize(10); bbut->callback(Button_CB); + bbut->tooltip(tipmsg); + grp->end(); grp->resizable(grp); tree->end(); @@ -240,7 +265,7 @@ Function {} {open } { Fl_Window window { label tree open - xywh {425 44 1015 590} type Double visible + xywh {678 506 1015 590} type Double visible } { Fl_Group tree { label Tree @@ -570,36 +595,6 @@ These happen when mouse drags or multi-clicks an item} xywh {485 273 140 21} dow xywh {60 60 36 21} labelsize 12 } } - Fl_Choice itemdrawmode_chooser { - label {Item Draw Mode} - callback {\#if FLTK_ABI_VERSION >= 10302 -// NEW -switch ( itemdrawmode_chooser->value() ) { - case 0: tree->item_draw_mode(FL_TREE_ITEM_DRAW_WIDGET_ONLY); break; // None - case 1: tree->item_draw_mode(FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET); break; // Single -} -tree->redraw(); -\#else -// OLD -itemdrawmode_chooser->deactivate(); // deactivate if this ABI feature is disabled -itemdrawmode_chooser->tooltip("DISABLED.\\n" - "Set FLTK_ABI_VERSION to 10302 (or higher)\\n" - "to get this feature"); -window->redraw(); // deactivated -\#endif} - tooltip {Sets how Fl_Tree draws item label and widget()} xywh {485 297 140 21} down_box BORDER_BOX labelsize 12 textsize 11 - code0 {itemdrawmode_chooser->value(0);} - code1 {itemdrawmode_chooser->do_callback();} - } { - MenuItem {} { - label {Widget Only} - xywh {50 50 36 21} labelsize 12 - } - MenuItem {} { - label {Label And Widget} - xywh {60 60 36 21} labelsize 12 - } - } Fl_Choice whenmode_chooser { label When callback {// Set when mode @@ -609,7 +604,7 @@ switch ( whenmode_chooser->value() ) { case 2: tree->when(FL_WHEN_NEVER); break; default: tree->when(FL_WHEN_RELEASE); break; }} - tooltip {Sets when() the tree's callback is invoked} xywh {485 321 140 21} down_box BORDER_BOX labelsize 12 textsize 11 + tooltip {Sets when() the tree's callback is invoked} xywh {485 299 140 21} down_box BORDER_BOX labelsize 12 textsize 11 code0 {whenmode_chooser->value(1);} code1 {cb_whenmode_chooser(whenmode_chooser, (void*)0);} } { @@ -630,7 +625,7 @@ switch ( whenmode_chooser->value() ) { label {Enable user icons?} user_data tree callback {AssignUserIcons();} - tooltip {Tests Fl_Tree_Item::usericon()} xywh {485 353 20 16} down_box DOWN_BOX labelsize 12 align 7 + tooltip {Tests Fl_Tree_Item::usericon()} xywh {450 353 20 16} down_box DOWN_BOX labelsize 11 align 7 code0 {usericon_radio->value(1);} } Fl_Check_Button showroot_radio { @@ -638,7 +633,7 @@ switch ( whenmode_chooser->value() ) { user_data tree callback {int onoff = showroot_radio->value(); tree->showroot(onoff);} - tooltip {Tests tree->showroot();} xywh {485 369 20 16} down_box DOWN_BOX labelsize 12 align 7 + tooltip {Tests tree->showroot();} xywh {450 370 20 16} down_box DOWN_BOX labelsize 11 align 7 code0 {int onoff = tree->showroot(); showroot_radio->value(onoff);} } Fl_Check_Button visiblefocus_checkbox { @@ -646,7 +641,7 @@ tree->showroot(onoff);} user_data tree callback {int onoff = visiblefocus_checkbox->value(); tree->visible_focus(onoff);} - tooltip {Toggles the tree's visible_focus() box} xywh {485 386 20 16} down_box DOWN_BOX labelsize 12 align 7 + tooltip {Toggles the tree's visible_focus() box} xywh {450 387 20 16} down_box DOWN_BOX labelsize 11 align 7 code0 {int onoff = tree->visible_focus(); visiblefocus_checkbox->value(onoff);} } Fl_Button selection_color_button { @@ -655,9 +650,57 @@ tree->visible_focus(onoff);} selection_color_button->color(val); // update modified color to button tree->selection_color(val); tree->redraw();} - tooltip {Changes the tree widget's selection color. Tests Fl_Tree::selection_color()} xywh {485 409 16 16} box DOWN_BOX labelsize 12 align 7 + tooltip {Changes the tree widget's selection color. Tests Fl_Tree::selection_color()} xywh {450 409 16 16} box DOWN_BOX labelsize 11 align 7 code0 {o->color(tree->selection_color());} } + Fl_Check_Button labelandwidget_radio { + label {Show label + widget} + callback {\#if FLTK_ABI_VERSION >= 10302 +// NEW +int flags = tree->item_draw_mode(); +if ( labelandwidget_radio->value() ) + { flags |= FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET; } +else + { flags &= ~FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET; } +tree->item_draw_mode(flags); +tree->redraw(); +\#else +// OLD +labelandwidget_radio->deactivate(); // deactivate if this ABI feature is disabled +labelandwidget_radio->tooltip("DISABLED.\\n" + "Set FLTK_ABI_VERSION to 10302 (or higher)\\n" + "to get this feature"); +window->redraw(); // deactivated +\#endif} + tooltip {Enables both label and widget() for display. +By default, the widget() is shown in place of the item's label} xywh {610 354 20 16} down_box DOWN_BOX labelsize 11 align 7 + code0 {labelandwidget_radio->value(0);} + code1 {labelandwidget_radio->do_callback();} + } + Fl_Check_Button itemheightfromwidget_radio { + label {Item h() from widget} + callback {\#if FLTK_ABI_VERSION >= 10302 +// NEW +int flags = tree->item_draw_mode(); +if ( itemheightfromwidget_radio->value() ) + { flags |= FL_TREE_ITEM_HEIGHT_FROM_WIDGET; } +else + { flags &= ~FL_TREE_ITEM_HEIGHT_FROM_WIDGET; } +tree->item_draw_mode(flags); +tree->redraw(); +\#else +// OLD +itemheightfromwidget_radio->deactivate(); // deactivate if this ABI feature is disabled +itemheightfromwidget_radio->tooltip("DISABLED.\\n" + "Set FLTK_ABI_VERSION to 10302 (or higher)\\n" + "to get this feature"); +window->redraw(); // deactivated +\#endif} selected + tooltip {If enabled, item's height will track the widget()'s height. +When enabled, click 'ccc' or 'D1/D2' buttons to test} xywh {610 369 20 16} down_box DOWN_BOX labelsize 11 align 7 + code0 {itemheightfromwidget_radio->value(0);} + code1 {itemheightfromwidget_radio->do_callback();} + } Fl_Box {} { label {Test Operations} tooltip {These controls only affect the defaults for new items that are created. These test the Fl_Tree_Prefs methods.} xywh {315 450 330 125} box GTK_DOWN_BOX color 47 labelsize 12 align 1 @@ -717,7 +760,7 @@ To use: if ( item->has_children() ) item->open(); } -tree->redraw();} selected +tree->redraw();} tooltip {Opens all nodes that have children} xywh {435 466 95 16} labelsize 9 } Fl_Button loaddb_button { -- cgit v1.2.3