diff options
| author | Greg Ercolano <erco@seriss.com> | 2010-08-26 13:32:30 +0000 |
|---|---|---|
| committer | Greg Ercolano <erco@seriss.com> | 2010-08-26 13:32:30 +0000 |
| commit | c7ef0f1d17f30f98342117f0635702121ce61d9a (patch) | |
| tree | ee7d0742b9e4454d69aec87f363a9c903c444e9d /FL/Fl_Tree.H | |
| parent | 23303736e3cb6a51e72dec08660ca06902925adb (diff) | |
Fl_Tree related mods
* open() / close() now can invoke the callback().
New method callback_reason() lets one determine the cause.
(Used FLU's tree for reference on this)
* new Fl_Tree methods:
> item_pathname()
> show_item(), show_top(), show_middle(), show_bottom().
> next_selected_item() -- loop through the selected items.
> callback_item() -- the item that caused the callback
> callback_reason() -- reason the callback was invoked
FL_TREE_REASON_SELECTED -- item was selected
FL_TREE_REASON_DESELECTED -- item was de-selected
FL_TREE_REASON_OPENED -- item was opened
FL_TREE_REASON_CLOSED -- item was closed
> position()
> display()
* new Fl_Tree_Item methods:
> find_child_item() -- searches children for a path
> find_item() -- searches self and children for a path
> next(item) -- loop forward through tree
> prev(item) -- loop backward through tree
> first_selected_item()
> next_selected_item()
> x(), y(), w(), h()
* deprecated:
> item_clicked(). Use callback_item() instead
* the 'docallback' optional integer argument for all methods
is now back to 0 or 1 only. (Other values became unnecessary
when above new callback() behavior was defined)
* test/tree has new "Test Callback Flags" button to test the
'docallback' flags for eg. open/close/select/deselect
to make sure no bugs creep in.
* INTERNAL: added free_path() to free special path array created by parse_path().
* Various docs strengthened:
* How to use first()/next() and last()/prev() to walk tree
> made sure more method's options use \param[in]
> Added more \see references
* Moved several implementations from .H -> .cxx
* Added autoscroll to keyboard nav and mouse drags
* test/unittests: added Fl_Tree to scrollsize test
TODO:
o Horiz scroll bar (see Johannes Schock's email re. additions he sent)
o Need to allow keyboard nav to move focus to child FLTK widgets
o Fix fast-selections so that no gaps are left behind.
(Select all items from the last selected item to the current)
o Investigate non-default values of when() causing odd behavior.
(See the tree demo's when() pulldown..)
* tree demo modified to include top/mid/bot buttons that test the above.
* Keyboard navigation added:
Up/Down -- move focus
Left/Right -- closes/opens tree item in focus
Spacebar -- toggle selection state of item in focus
Enter -- selects the item in focus, deselecting all others
Tab/Shift-Tab -- change widget focus
* All Fl_Tree select() and deselect() methods now return a value
that indicates if the item's state was changed.
* Fixed focus box drawing (focus box resides more precisely within item's box)
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@7691 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'FL/Fl_Tree.H')
| -rw-r--r-- | FL/Fl_Tree.H | 563 |
1 files changed, 390 insertions, 173 deletions
diff --git a/FL/Fl_Tree.H b/FL/Fl_Tree.H index be309c81f..5e6865124 100644 --- a/FL/Fl_Tree.H +++ b/FL/Fl_Tree.H @@ -84,68 +84,75 @@ /// tree.end(); /// \endcode /// -/// Items can be added with Fl_Tree::add(), -/// removed with Fl_Tree::remove(), -/// inserted with Fl_Tree::insert_above(), -/// selected/deselected with Fl_Tree::select() and Fl_Tree::deselect(). -/// Items can be swapped with Fl_Tree_Item::swap_children(), sorting control via -/// Fl_Tree::sortorder(). +/// Items can be added with add(), +/// removed with remove(), +/// completely cleared with clear(), +/// inserted with insert() and insert_above(), +/// selected/deselected with select() and deselect(), +/// open/closed with open() and closed(). +/// Children of an item can be swapped around with Fl_Tree_Item::swap_children(), +/// sorting can be controlled when items are add()ed via sortorder(). +/// You can walk the entire tree with first() and next(). +/// You can walk selected items with first_selected_item() and +/// next_selected_item(). +/// Items can be found by their pathname using find_item(const char*), +/// and an item's pathname can be found with item_pathname(). /// -/// The tree can have different selection behaviors controlled by Fl_Tree::selectmode(). +/// The tree can have different selection behaviors controlled by selectmode(). /// -/// FLTK and custom FLTK widgets can be assigned to tree items via Fl_Tree_Item::widget(). +/// FLTK widgets (including custom widgets) can be assigned to tree items via +/// Fl_Tree_Item::widget(). /// -/// Parent nodes can be open/closed with open() and close(), icons can be assigned -/// or redefined with some or all items via +/// Icons for individual items can be changed with /// Fl_Tree_Item::openicon(), /// Fl_Tree_Item::closeicon(), /// Fl_Tree_Item::usericon(). /// -/// Various default preferences can be manipulated via Fl_Tree_Prefs, including -/// colors, margins, connection lines. +/// Various default preferences can be globally manipulated via Fl_Tree_Prefs, +/// including colors, margins, icons, connection lines. +/// +/// The tree's callback() will be invoked when items change state or are open/closed. +/// when() controls when mouse/keyboard events invoke the callback. +/// callback_item() and callback_reason() can be used to determine the cause of the callback. /// /// \image html tree-elements.png /// -/// \todo Needs handling of callbacks when items are procedurally select()ed + +/// \enum Fl_Tree_Reason +/// The reason the callback was invoked. /// +enum Fl_Tree_Reason { + FL_TREE_REASON_NONE=0, ///< unknown reason + FL_TREE_REASON_SELECTED, ///< an item was selected + FL_TREE_REASON_DESELECTED, ///< an item was de-selected + FL_TREE_REASON_OPENED, ///< an item was opened + FL_TREE_REASON_CLOSED ///< an item was closed +}; + class Fl_Tree : public Fl_Group { - Fl_Tree_Item *_root; // can be null! - Fl_Tree_Item *_item_clicked; - Fl_Tree_Prefs _prefs; // all the tree's settings - Fl_Scrollbar *_vscroll; + Fl_Tree_Item *_root; // can be null! + Fl_Tree_Item *_item_focus; // item that has focus box + Fl_Tree_Item *_callback_item; // item invoked during callback (can be NULL) + Fl_Tree_Reason _callback_reason; // reason for the callback + Fl_Tree_Prefs _prefs; // all the tree's settings + int _scrollbar_size; // size of scrollbar trough + +protected: + /// Vertical scrollbar + Fl_Scrollbar *_vscroll; -public: - /// Find the item that was clicked. - /// You probably want to use item_clicked() instead, which is fast. - /// - /// This method walks the entire tree looking for the first item that is - /// under the mouse (ie. at Fl::event_x()/Fl:event_y(). - /// - /// Use this method /only/ if you've subclassed Fl_Tree, and are receiving - /// events before Fl_Tree has been able to process and update item_clicked(). - /// - /// \returns the item clicked, or 0 if no item was under the current event. - /// - const Fl_Tree_Item *find_clicked() const { - if ( ! _root ) return(0); - return(_root->find_clicked(_prefs)); - } protected: - /// Set the item that was last clicked. - /// Should only be used by subclasses needing to change this value. - /// Normally Fl_Tree manages this value. - /// - void item_clicked(Fl_Tree_Item* val) { - _item_clicked = val; - } - void do_callback_for_item(Fl_Tree_Item* item) { - Fl_Tree_Item *save = _item_clicked; // save previous 'item_clicked' - _item_clicked = item; // set item_clicked to this item while we do callback + void set_item_focus(Fl_Tree_Item *o); + void item_clicked(Fl_Tree_Item* val); + /// Do the callback for the item, setting the item and reason + void do_callback_for_item(Fl_Tree_Item* item, Fl_Tree_Reason reason) { + callback_reason(reason); + callback_item(item); do_callback((Fl_Widget*)this, user_data()); - _item_clicked = save; // restore item_clicked } - + Fl_Tree_Item *next_visible_item(Fl_Tree_Item *start, int dir); + public: Fl_Tree(int X, int Y, int W, int H, const char *L=0); ~Fl_Tree(); @@ -204,7 +211,7 @@ public: void clear_children(Fl_Tree_Item *item) { if ( item->has_children() ) { item->clear_children(); - redraw(); // redraw only if there were children to clear + redraw(); // redraw only if there were children to clear } } @@ -213,52 +220,29 @@ public: //////////////////////// Fl_Tree_Item *find_item(const char *path); const Fl_Tree_Item *find_item(const char *path) const; + int item_pathname(char *pathname, int pathnamelen, const Fl_Tree_Item *item) const; + + const Fl_Tree_Item *find_clicked() const; /// Return the item that was last clicked. /// - /// Valid only from within an Fl_Tree::callback(). + /// Valid only from within the callback(). + /// + /// Deprecated: use callback_item() instead. /// /// \returns the item clicked, or 0 if none. /// 0 may also be used to indicate several items were clicked/changed. /// Fl_Tree_Item *item_clicked() { - return(_item_clicked); - } - /// Returns the first item in the tree. - /// - /// Use this to walk the tree in the forward direction, eg: - /// \code - /// for ( Fl_Tree_Item *item = tree->first(); item; item = item->next() ) { - /// printf("Item: %s\n", item->label()); - /// } - /// \endcode - /// - /// \returns first item in tree, or 0 if none (tree empty). - /// - Fl_Tree_Item *first() { - return(_root); // first item always root - } - /// Returns the last item in the tree. - /// - /// Use this to walk the tree in reverse, eg: - /// - /// \code - /// for ( Fl_Tree_Item *item = tree->last(); item; item = item->prev() ) { - /// printf("Item: %s\n", item->label()); - /// } - /// \endcode - /// - /// \returns last item in the tree, or 0 if none (tree empty). - /// - Fl_Tree_Item *last() { - if ( ! _root ) return(0); - Fl_Tree_Item *item = _root; - while ( item->has_children() ) { - item = item->child(item->children()-1); - } - return(item); - } - + return(_callback_item); + } + Fl_Tree_Item *first(); + Fl_Tree_Item *next(Fl_Tree_Item *item=0); + Fl_Tree_Item *prev(Fl_Tree_Item *item=0); + Fl_Tree_Item *last(); + Fl_Tree_Item *first_selected_item(); + Fl_Tree_Item *next_selected_item(Fl_Tree_Item *item=0); + ////////////////////////// // Item open/close methods ////////////////////////// @@ -266,59 +250,140 @@ public: /// Open the specified 'item'. /// This causes the item's children (if any) to be shown. /// Handles redrawing if anything was actually changed. + /// Invokes the callback depending on the value of optional parameter \p docallback. /// - void open(Fl_Tree_Item *item) { - if ( ! item->is_open() ) { - item->open(); - redraw(); + /// The callback can use callback_item() and callback_reason() respectively to determine + /// the item changed and the reason the callback was called. + /// + /// \param[in] item -- the item to be opened + /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: + /// - 0 - callback() is not invoked + /// - 1 - callback() is invoked if item changed, + /// callback_reason() will be FL_TREE_REASON_OPENED + /// + /// \returns + /// - 1 -- item was opened + /// - 0 -- item was already open, no change + /// + /// \see open(), close(), is_open(), is_close(), callback_item(), callback_reason() + /// + int open(Fl_Tree_Item *item, int docallback=1) { + if ( item->is_open() ) return(0); + item->open(); + redraw(); + if ( docallback ) { + do_callback_for_item(item, FL_TREE_REASON_OPENED); } + return(1); } /// Opens the item specified by \p path (eg: "Parent/child/item"). /// This causes the item's children (if any) to be shown. /// Handles redrawing if anything was actually changed. + /// Invokes the callback depending on the value of optional parameter \p docallback. + /// + /// The callback can use callback_item() and callback_reason() respectively to determine + /// the item changed and the reason the callback was called. + /// + /// \param[in] path -- the tree item's pathname (eg. "Flintstones/Fred") + /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: + /// - 0 - callback() is not invoked + /// - 1 - callback() is invoked if item changed, + /// callback_reason() will be FL_TREE_REASON_OPENED /// /// \returns - /// - 0 : OK - /// - -1 : item was not found + /// - 1 -- OK: item opened + /// - 0 -- OK: item was already open, no change + /// - -1 -- ERROR: item was not found + /// + /// \see open(), close(), is_open(), is_close(), callback_item(), callback_reason() /// - int open(const char *path) { + int open(const char *path, int docallback=1) { Fl_Tree_Item *item = find_item(path); - if ( item ) { - open(item); - return(0); + if ( ! item ) return(-1); + return(open(item, docallback)); + } + /// Toggle the open state of \p item. + /// Handles redrawing if anything was actually changed. + /// Invokes the callback depending on the value of optional parameter \p docallback. + /// + /// The callback can use callback_item() and callback_reason() respectively to determine + /// the item changed and the reason the callback was called. + /// + /// \param[in] item -- the item to be opened + /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: + /// - 0 - callback() is not invoked + /// - 1 - callback() is invoked, callback_reason() will be either + /// FL_TREE_REASON_OPENED or FL_TREE_REASON_CLOSED + /// + /// \see open(), close(), is_open(), is_close(), callback_item(), callback_reason() + /// + void open_toggle(Fl_Tree_Item *item, int docallback=1) { + if ( item->is_open() ) { + close(item, docallback); + } else { + open(item, docallback); } - return(-1); } /// Closes the specified \p item. /// Handles redrawing if anything was actually changed. + /// Invokes the callback depending on the value of optional parameter \p docallback. /// - void close(Fl_Tree_Item *item) { - if ( ! item->is_close() ) { - item->close(); - redraw(); + /// The callback can use callback_item() and callback_reason() respectively to determine + /// the item changed and the reason the callback was called. + /// + /// \param[in] item -- the item to be closed + /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: + /// - 0 - callback() is not invoked + /// - 1 - callback() is invoked if item changed, + /// callback_reason() will be FL_TREE_REASON_CLOSED + /// + /// \returns + /// - 1 -- item was closed + /// - 0 -- item was already closed, no change + /// + /// \see open(), close(), is_open(), is_close(), callback_item(), callback_reason() + /// + int close(Fl_Tree_Item *item, int docallback=1) { + if ( item->is_close() ) return(0); + item->close(); + redraw(); + if ( docallback ) { + do_callback_for_item(item, FL_TREE_REASON_CLOSED); } + return(1); } /// Closes the item specified by \p path, eg: "Parent/child/item". - /// /// Handles redrawing if anything was actually changed. + /// Invokes the callback depending on the value of optional parameter \p docallback. + /// + /// The callback can use callback_item() and callback_reason() respectively to determine + /// the item changed and the reason the callback was called. + /// + /// \param[in] path -- the tree item's pathname (eg. "Flintstones/Fred") + /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: + /// - 0 - callback() is not invoked + /// - 1 - callback() is invoked if item changed, + /// callback_reason() will be FL_TREE_REASON_CLOSED /// /// \returns - /// - 0 -- OK - /// - -1 -- item was not found + /// - 1 -- OK: item closed + /// - 0 -- OK: item was already closed, no change + /// - -1 -- ERROR: item was not found + /// + /// \see open(), close(), is_open(), is_close(), callback_item(), callback_reason() /// - int close(const char *path) { + int close(const char *path, int docallback=1) { Fl_Tree_Item *item = find_item(path); - if ( item ) { - close(item); - return(0); - } - return(-1); + if ( ! item ) return(-1); + return(close(item, docallback)); } /// See if \p item is open. /// /// Items that are 'open' are themselves not necessarily visible; /// one of the item's parents might be closed. /// + /// \param[in] item -- the item to be tested + /// /// \returns /// - 1 : item is open /// - 0 : item is closed @@ -331,17 +396,22 @@ public: /// Items that are 'open' are themselves not necessarily visible; /// one of the item's parents might be closed. /// + /// \param[in] path -- the tree item's pathname (eg. "Flintstones/Fred") + /// /// \returns - /// - 1 : item is open - /// - 0 : item is closed - /// - -1 : item was not found + /// - 1 - OK: item is open + /// - 0 - OK: item is closed + /// - -1 - ERROR: item was not found /// int is_open(const char *path) const { const Fl_Tree_Item *item = find_item(path); - if ( item ) return(item->is_open()?1:0); - return(-1); + if ( ! item ) return(-1); + return(item->is_open()?1:0); } /// See if the specified \p item is closed. + /// + /// \param[in] item -- the item to be tested + /// /// \returns /// - 1 : item is open /// - 0 : item is closed @@ -351,111 +421,154 @@ public: } /// See if item specified by \p path (eg: "Parent/child/item") is closed. /// + /// \param[in] path -- the tree item's pathname (eg. "Flintstones/Fred") + /// /// \returns - /// - 1 : item is closed - /// - 0 : item is open - /// - -1 : item was not found + /// - 1 - OK: item is closed + /// - 0 - OK: item is open + /// - -1 - ERROR: item was not found /// int is_close(const char *path) const { const Fl_Tree_Item *item = find_item(path); - if ( item ) return(item->is_close()?1:0); - return(-1); + if ( ! item ) return(-1); + return(item->is_close()?1:0); } - ///////////////////////// - // Item selection methods - ///////////////////////// - /// Select the specified \p item. Use 'deselect()' to de-select it. /// Handles redrawing if anything was actually changed. + /// Invokes the callback depending on the value of optional parameter \p docallback. /// - /// \p docallback is an optional paramemter that can either be 0 or 1. - /// - 0 - the callback() is not invoked (default) - /// - 1 - the callback() is invoked if the item changed state, - /// and the callback can use item_clicked() to determine the selected item. + /// The callback can use callback_item() and callback_reason() respectively to determine + /// the item changed and the reason the callback was called. /// - void select(Fl_Tree_Item *item, int docallback=0) { + /// \param[in] item -- the item to be selected + /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: + /// - 0 - the callback() is not invoked + /// - 1 - the callback() is invoked if item changed state, + /// callback_reason() will be FL_TREE_REASON_SELECTED + /// + /// \returns + /// - 1 - item's state was changed + /// - 0 - item was already selected, no change was made + /// + int select(Fl_Tree_Item *item, int docallback=1) { if ( ! item->is_selected() ) { item->select(); - if ( docallback == 1 ) do_callback_for_item(item); + set_changed(); + if ( docallback ) { + do_callback_for_item(item, FL_TREE_REASON_SELECTED); + } redraw(); + return(1); } + return(0); } /// Select the item specified by \p path (eg: "Parent/child/item"). /// Handles redrawing if anything was actually changed. + /// Invokes the callback depending on the value of optional parameter \p docallback. /// - /// \p docallback is an optional paramemter that can either be 0 or 1. - /// - 0 - the callback() is not invoked (default) - /// - 1 - the callback() is invoked if the item changed state, - /// and the callback can use item_clicked() to determine the selected item. + /// The callback can use callback_item() and callback_reason() respectively to determine + /// the item changed and the reason the callback was called. + /// + /// \param[in] path -- the tree item's pathname (eg. "Flintstones/Fred") + /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: + /// - 0 - the callback() is not invoked + /// - 1 - the callback() is invoked if item changed state, + /// callback_reason() will be FL_TREE_REASON_SELECTED /// /// \returns - /// - 0 : OK - /// - -1 : item was not found + /// - 1 : OK: item's state was changed + /// - 0 : OK: item was already selected, no change was made + /// - -1 : ERROR: item was not found /// - int select(const char *path, int docallback=0) { + int select(const char *path, int docallback=1) { Fl_Tree_Item *item = find_item(path); - if ( item ) { - select(item); - if ( docallback == 1 ) do_callback_for_item(item); - return(0); - } - return(-1); + if ( ! item ) return(-1); + return(select(item, docallback)); } /// Toggle the select state of the specified \p item. - /// Handles redrawing. + /// Handles redrawing if anything was actually changed. + /// Invokes the callback depending on the value of optional parameter \p docallback. /// - /// \p docallback is an optional paramemter that can either be 0 or 1. - /// - 0 - the callback() is not invoked (default) - /// - 1 - the callback() is invoked, - /// and the callback can use item_clicked() to determine the selected item. + /// The callback can use callback_item() and callback_reason() respectively to determine + /// the item changed and the reason the callback was called. /// - void select_toggle(Fl_Tree_Item *item, int docallback=0) { + /// \param[in] item -- the item to be selected + /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: + /// - 0 - the callback() is not invoked + /// - 1 - the callback() is invoked, callback_reason() will be + /// either FL_TREE_REASON_SELECTED or FL_TREE_REASON_DESELECTED + /// + void select_toggle(Fl_Tree_Item *item, int docallback=1) { item->select_toggle(); - if ( docallback == 1 ) do_callback_for_item(item); + set_changed(); + if ( docallback ) { + do_callback_for_item(item, item->is_selected() ? FL_TREE_REASON_SELECTED + : FL_TREE_REASON_DESELECTED); + } redraw(); } /// De-select the specified \p item. /// Handles redrawing if anything was actually changed. + /// Invokes the callback depending on the value of optional parameter \p docallback. /// - /// \p docallback is an optional paramemter that can either be 0 or 1. - /// - 0 - the callback() is not invoked (default) - /// - 1 - the callback() is invoked if the item changed state, - /// and the callback can use item_clicked() to determine the selected item. + /// The callback can use callback_item() and callback_reason() respectively to determine + /// the item changed and the reason the callback was called. /// - void deselect(Fl_Tree_Item *item, int docallback=0) { + /// \param[in] item -- the item to be selected + /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: + /// - 0 - the callback() is not invoked + /// - 1 - the callback() is invoked if item changed state, + /// callback_reason() will be FL_TREE_REASON_DESELECTED + /// + /// \returns + /// - 0 - item was already deselected, no change was made + /// - 1 - item's state was changed + /// + int deselect(Fl_Tree_Item *item, int docallback=1) { if ( item->is_selected() ) { item->deselect(); - if ( docallback == 1 ) do_callback_for_item(item); + set_changed(); + if ( docallback ) { + do_callback_for_item(item, FL_TREE_REASON_DESELECTED); + } redraw(); + return(1); } + return(0); } - /// De-select an item specified by \p path (eg: "Parent/child/item"). + /// Deselect an item specified by \p path (eg: "Parent/child/item"). /// Handles redrawing if anything was actually changed. + /// Invokes the callback depending on the value of optional parameter \p docallback. + /// + /// The callback can use callback_item() and callback_reason() respectively to determine + /// the item changed and the reason the callback was called. /// - /// \p docallback is an optional paramemter that can either be 0 or 1. - /// - 0 - the callback() is not invoked (default) - /// - 1 - the callback() is invoked if the item changed state, - /// and the callback can use item_clicked() to determine the selected item. + /// \param[in] path -- the tree item's pathname (eg. "Flintstones/Fred") + /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: + /// - 0 - the callback() is not invoked + /// - 1 - the callback() is invoked if item changed state, + /// callback_reason() will be FL_TREE_REASON_DESELECTED /// /// \returns - /// - 0 : OK - /// - -1 : item was not found + /// - 1 - OK: item's state was changed + /// - 0 - OK: item was already deselected, no change was made + /// - -1 - ERROR: item was not found /// - int deselect(const char *path, int docallback=0) { + int deselect(const char *path, int docallback=1) { Fl_Tree_Item *item = find_item(path); - if ( item ) { - deselect(item, docallback); - return(0); - } - return(-1); + if ( ! item ) return(-1); + return(deselect(item, docallback)); } - int deselect_all(Fl_Tree_Item *item=0, int docallback=0); - int select_only(Fl_Tree_Item *selitem, int docallback=0); - int select_all(Fl_Tree_Item *item=0, int docallback=0); + int deselect_all(Fl_Tree_Item *item=0, int docallback=1); + int select_only(Fl_Tree_Item *selitem, int docallback=1); + int select_all(Fl_Tree_Item *item=0, int docallback=1); /// See if the specified \p item is selected. + /// + /// \param[in] item -- the item to be tested + /// /// \return /// - 1 : item selected /// - 0 : item deselected @@ -465,6 +578,8 @@ public: } /// See if item specified by \p path (eg: "Parent/child/item") is selected. /// + /// \param[in] path -- the tree item's pathname (eg. "Flintstones/Fred") + /// /// \returns /// - 1 : item selected /// - 0 : item deselected @@ -472,8 +587,8 @@ public: /// int is_selected(const char *path) { Fl_Tree_Item *item = find_item(path); - if ( item ) return(is_selected(item)); - return(-1); + if ( ! item ) return(-1); + return(is_selected(item)); } /// Print the tree as 'ascii art' to stdout. /// Used mainly for debugging. @@ -688,7 +803,109 @@ public: void selectmode(Fl_Tree_Select val) { _prefs.selectmode(val); } - + void show_item(Fl_Tree_Item *item, int yoff=0); + void show_item_bottom(Fl_Tree_Item *item); + void show_item_middle(Fl_Tree_Item *item); + void show_item_top(Fl_Tree_Item *item); + void display(Fl_Tree_Item *item); + int vposition() const; + void vposition(int ypos); + + /// See if widget \p w is one of the Fl_Tree widget's scrollbars. + /// Use this to skip over the scrollbars when walking the child() array. Example: + /// \code + /// for ( int i=0; i<tree->children(); i++ ) { // walk children + /// Fl_Widget *w= tree->child(i); + /// if ( brow->is_scrollbar(w) ) continue; // skip scrollbars + /// ..do work here.. + /// } + /// \endcode + /// \param[in] w Widget to test + /// \returns 1 if \p w is a scrollbar, 0 if not. + /// + int is_scrollbar(Fl_Widget *w) { + return( ( w == _vscroll ) ? 1 : 0 ); + } + /// Gets the current size of the scrollbars' troughs, in pixels. + /// + /// If this value is zero (default), this widget will use the global + /// Fl::scrollbar_size() value as the scrollbar's width. + /// + /// \returns Scrollbar size in pixels, or 0 if the global Fl::scrollsize() is being used. + /// \see Fl::scrollbar_size(int) + /// + int scrollbar_size() const { + return(_scrollbar_size); + } + /// Sets the pixel size of the scrollbars' troughs to the \p size, in pixels. + /// + /// Normally you should not need this method, and should use the global + /// Fl::scrollbar_size(int) instead to manage the size of ALL + /// your widgets' scrollbars. This ensures your application + /// has a consistent UI, is the default behavior, and is normally + /// what you want. + /// + /// Only use THIS method if you really need to override the global + /// scrollbar size. The need for this should be rare. + /// + /// Setting \p size to the special value of 0 causes the widget to + /// track the global Fl::scrollbar_size(), which is the default. + /// + /// \param[in] size Sets the scrollbar size in pixels.\n + /// If 0 (default), scrollbar size tracks the global Fl::scrollbar_size() + /// \see Fl::scrollbar_size() + /// + void scrollbar_size(int size) { + _scrollbar_size = size; + int scrollsize = _scrollbar_size ? _scrollbar_size : Fl::scrollbar_size(); + if ( _vscroll->w() != scrollsize ) { + _vscroll->resize(x()+w()-scrollsize, h(), scrollsize, _vscroll->h()); + } + } + + /////////////////////// + // callback related + /////////////////////// + + /// Sets the item that was changed for this callback. + /// Used internally to pass the item that invoked the callback. + /// + void callback_item(Fl_Tree_Item* item) { + _callback_item = item; + } + /// Gets the item that caused the callback. + /// The callback() can use this value to see which item changed. + /// + Fl_Tree_Item* callback_item() { + return(_callback_item); + } + /// Sets the reason for this callback. + /// Used internally to pass the reason the callback was invoked. + /// + void callback_reason(Fl_Tree_Reason reason) { + _callback_reason = reason; + } + /// Gets the reason for this callback. + /// + /// The callback() can use this value to see why it was called. Example: + /// \code + /// void MyTreeCallback(Fl_Widget *w, void *userdata) { + /// Fl_Tree *tree = (Fl_Tree*)w; + /// Fl_Tree_Item *item = tree->callback_item(); // the item changed (can be NULL if more than one item was changed!) + /// switch ( tree->callback_reason() ) { // reason callback was invoked + /// case FL_TREE_REASON_OPENED: ..item was opened.. + /// case FL_TREE_REASON_CLOSED: ..item was closed.. + /// case FL_TREE_REASON_SELECTED: ..item was selected.. + /// case FL_TREE_REASON_DESELECTED: ..item was deselected.. + /// } + /// } + /// \endcode + /// + Fl_Tree_Reason callback_reason() const { + return(_callback_reason); + } + + /// Load FLTK preferences void load(class Fl_Preferences&); }; |
