summaryrefslogtreecommitdiff
path: root/FL/Fl_Tree.H
diff options
context:
space:
mode:
authorMatthias Melcher <fltk@matthiasm.com>2009-11-14 15:49:12 +0000
committerMatthias Melcher <fltk@matthiasm.com>2009-11-14 15:49:12 +0000
commit07a18370ad2aa1f2253afbf45565d55605a88b47 (patch)
treef2619866e648a105259b24c8265ec08a11bf1971 /FL/Fl_Tree.H
parent69601a6d5827539394b9468176727ec651c1ebbc (diff)
Added Fl_Tree source code, demo files, and documentation. Thanks, Greg!
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@6934 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'FL/Fl_Tree.H')
-rw-r--r--FL/Fl_Tree.H647
1 files changed, 647 insertions, 0 deletions
diff --git a/FL/Fl_Tree.H b/FL/Fl_Tree.H
new file mode 100644
index 000000000..edef13b00
--- /dev/null
+++ b/FL/Fl_Tree.H
@@ -0,0 +1,647 @@
+#ifndef FL_TREE_H
+#define FL_TREE_H
+
+#include <FL/Fl.H>
+#include <FL/Fl_Group.H>
+#include <FL/Fl_Scrollbar.H>
+#include <FL/fl_draw.H>
+
+#include <FL/Fl_Tree_Item.H>
+#include <FL/Fl_Tree_Prefs.H>
+
+//////////////////////
+// FL/Fl_Tree.H
+//////////////////////
+//
+// Fl_Tree -- This file is part of the Fl_Tree widget for FLTK
+// Copyright (C) 2009 by Greg Ercolano.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+// USA.
+//
+
+///
+/// \file
+/// \brief This file contains the definitions of the Fl_Tree class
+///
+
+/// \class Fl_Tree
+///
+/// \brief Tree widget.
+///
+/// \code
+/// Fl_Tree // Top level widget
+/// |--- Fl_Tree_Item // Items in the tree
+/// |--- Fl_Tree_Prefs // Preferences for the tree
+/// |--- Fl_Tree_Connector (enum) // Connection modes
+/// |--- Fl_Tree_Select (enum) // Selection modes
+/// |--- Fl_Tree_Sort (enum) // Sort behavior
+/// \endcode
+///
+/// An expandable tree widget.
+///
+/// Similar to Fl_Browser, Fl_Tree is browser of Fl_Tree_Item's, which can be
+/// in a parented hierarchy. 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.
+///
+/// The simple way to define a tree:
+/// \code
+/// Fl_Tree tree(X,Y,W,H);
+/// tree.begin();
+/// tree.add("Flintstones/Fred");
+/// tree.add("Flintstones/Wilma");
+/// tree.add("Flintstones/Pebbles");
+/// tree.add("Simpsons/Homer");
+/// tree.add("Simpsons/Marge");
+/// tree.add("Simpsons/Bart");
+/// tree.add("Simpsons/Lisa");
+/// 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().
+///
+/// The tree can have different selection behaviors controlled by Fl_Tree::selectmode().
+///
+/// FLTK and custom FLTK 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
+/// Fl_Tree_Item::openicon(),
+/// Fl_Tree_Item::closeicon(),
+/// Fl_Tree_Item::usericon().
+///
+/// Various default preferences can be manipulated vi Fl_Tree_Prefs, including
+/// colors, margins, connection lines.
+///
+/// \image html tree-elements.png
+///
+
+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;
+
+protected:
+ /// 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));
+ }
+ /// 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;
+ }
+
+public:
+ Fl_Tree(int X, int Y, int W, int H, const char *L=0);
+ ~Fl_Tree();
+ int handle(int e);
+ void draw();
+
+ ///////////////////////
+ // root methods
+ ///////////////////////
+
+ /// Set the label for the root item.
+ ///
+ /// Makes an internally managed copy of 'new_label'.
+ ///
+ void root_label(const char *new_label) {
+ if ( ! _root ) return;
+ _root->label(new_label);
+ }
+ /// Returns the root item.
+ Fl_Tree_Item* root() {
+ return(_root);
+ }
+
+ ////////////////////////////////
+ // Item creation/removal methods
+ ////////////////////////////////
+ Fl_Tree_Item *add(const char *path);
+ Fl_Tree_Item *insert_above(Fl_Tree_Item *above, const char *name);
+
+ /// Remove the specified 'item' from the tree.
+ /// If it has children, all those are removed too.
+ /// \returns 0 if done, -1 if 'item' not found.
+ ///
+ int remove(Fl_Tree_Item *item) {
+ if ( !item ) return(0);
+ if ( item == _root ) {
+ clear();
+ } else {
+ Fl_Tree_Item *parent = item->parent(); // find item's parent
+ if ( ! parent ) return(-1);
+ parent->remove_child(item); // remove child + children
+ }
+ return(0);
+ }
+ /// Clear all children from the tree.
+ /// The tree will be left completely empty.
+ ///
+ void clear() {
+ if ( ! _root ) return;
+ _root->clear_children();
+ delete _root; _root = 0;
+ }
+ /// Clear all the children of a particular node in the tree.
+ void clear_children(Fl_Tree_Item *item) {
+ if ( item->has_children() ) {
+ item->clear_children();
+ redraw(); // redraw only if there were children to clear
+ }
+ }
+
+ ////////////////////////
+ // Item lookup methods
+ ////////////////////////
+ Fl_Tree_Item *find_item(const char *path);
+ const Fl_Tree_Item *find_item(const char *path) const;
+
+ /// Return the parent for specified 'item'.
+ ///
+ /// \returns item's parent, or 0 if none (root).
+ ///
+ Fl_Tree_Item *parent(Fl_Tree_Item *item) {
+ return(item->parent());
+ }
+ /// Return the item that was last clicked.
+ ///
+ /// Valid only from within an Fl_Tree::callback().
+ ///
+ /// \returns the item clicked, or 0 if none.
+ ///
+ 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);
+ }
+
+ //////////////////////////
+ // Item open/close methods
+ //////////////////////////
+
+ /// Open the specified 'item'.
+ /// This causes the item's children (if any) to be shown.
+ /// Handles redrawing if anything was actually changed.
+ ///
+ void open(Fl_Tree_Item *item) {
+ if ( ! item->is_open() ) {
+ item->open();
+ redraw();
+ }
+ }
+ /// Opens the item specified by a 'menu item' style pathname (eg: "Parent/child/item").
+ /// This causes the item's children (if any) to be shown.
+ /// Handles redrawing if anything was actually changed.
+ ///
+ /// \returns
+ /// - 0 : OK
+ /// - -1 : item was not found
+ ///
+ int open(const char *path) {
+ Fl_Tree_Item *item = find_item(path);
+ if ( item ) {
+ open(item);
+ return(0);
+ }
+ return(-1);
+ }
+ /// Closes the 'item'.
+ /// Handles redrawing if anything was actually changed.
+ ///
+ void close(Fl_Tree_Item *item) {
+ if ( ! item->is_close() ) {
+ item->close();
+ redraw();
+ }
+ }
+ /// Closes the item specified by 'path', eg: "Parent/child/item".
+ ///
+ /// Handles redrawing if anything was actually changed.
+ ///
+ /// \returns
+ /// - 0 -- OK
+ /// - -1 -- item was not found
+ ///
+ int close(const char *path) {
+ Fl_Tree_Item *item = find_item(path);
+ if ( item ) {
+ close(item);
+ return(0);
+ }
+ return(-1);
+ }
+ /// See if item is open.
+ ///
+ /// Items that are 'open' are themselves not necessarily visible;
+ /// one of the item's parents might be closed.
+ ///
+ /// \returns
+ /// - 1 : item is open
+ /// - 0 : item is closed
+ ///
+ int is_open(Fl_Tree_Item *item) const {
+ return(item->is_open()?1:0);
+ }
+ /// See if item specified by 'path' (eg: "Parent/child/item") is open.
+ ///
+ /// Items that are 'open' are themselves not necessarily visible;
+ /// one of the item's parents might be closed.
+ ///
+ /// \returns
+ /// - 1 : item is open
+ /// - 0 : item is closed
+ /// - -1 : 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);
+ }
+ /// See if item is closed.
+ /// \returns
+ /// - 1 : item is open
+ /// - 0 : item is closed
+ ///
+ int is_close(Fl_Tree_Item *item) const {
+ return(item->is_close());
+ }
+ /// See if item specified by 'path' (eg: "Parent/child/item") is closed.
+ ///
+ /// \returns
+ /// - 1 : item is closed
+ /// - 0 : item is open
+ /// - -1 : 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);
+ }
+
+ /////////////////////////
+ // Item selection methods
+ /////////////////////////
+
+ /// Select the specified item. Use 'deselect()' to de-select it.
+ /// Handles redrawing if anything was actually changed.
+ ///
+ void select(Fl_Tree_Item *item) {
+ if ( ! item->is_selected() ) {
+ item->select();
+ redraw();
+ }
+ }
+ /// Select an item specified by 'path' (eg: "Parent/child/item").
+ /// Handles redrawing if anything was actually changed.
+ ///
+ /// \returns
+ /// - 0 : OK
+ /// - -1 : item was not found
+ ///
+ int select(const char *path) {
+ Fl_Tree_Item *item = find_item(path);
+ if ( item ) {
+ select(item);
+ return(0);
+ }
+ return(-1);
+ }
+ /// Toggle item's select state.
+ /// Handles redrawing.
+ ///
+ void select_toggle(Fl_Tree_Item *item) {
+ item->select_toggle();
+ redraw();
+ }
+ /// De-select the specified item.
+ /// Handles redrawing if anything was actually changed.
+ ///
+ void deselect(Fl_Tree_Item *item) {
+ if ( item->is_selected() ) {
+ item->deselect();
+ redraw();
+ }
+ }
+ /// De-select an item specified by 'path' (eg: "Parent/child/item").
+ /// Handles redrawing if anything was actually changed.
+ ///
+ /// \returns
+ /// - 0 : OK
+ /// - -1 : item was not found
+ ///
+ int deselect(const char *path) {
+ Fl_Tree_Item *item = find_item(path);
+ if ( item ) {
+ deselect(item);
+ return(0);
+ }
+ return(-1);
+ }
+
+ int deselect_all(Fl_Tree_Item *item=0);
+ int select_only(Fl_Tree_Item *selitem);
+
+ /// See if the specified item is selected.
+ /// \return
+ /// - 1 : item selected
+ /// - 0 : item deselected
+ ///
+ int is_selected(Fl_Tree_Item *item) const {
+ return(item->is_selected()?1:0);
+ }
+ /// See if item specified by 'path' (eg: "Parent/child/item") is selected.
+ ///
+ /// \returns
+ /// - 1 : item selected
+ /// - 0 : item deselected
+ /// - -1 : item was not found
+ ///
+ int is_selected(const char *path) {
+ Fl_Tree_Item *item = find_item(path);
+ if ( item ) return(is_selected(item));
+ return(-1);
+ }
+ /// Print the tree as 'ascii art' to stdout.
+ /// Used mainly for debugging.
+ ///
+ void show_self() {
+ if ( ! _root ) return;
+ _root->show_self();
+ }
+
+ /////////////////////////////////
+ // Item attribute related methods
+ /////////////////////////////////
+
+ /// Get the default label fontsize used for creating new items.
+ int labelsize() const {
+ return(_prefs.labelsize());
+ }
+ /// Set the default label font size used for creating new items.
+ /// To change the font size on a per-item basis, use Fl_Tree_Item::labelsize(int)
+ ///
+ void labelsize(int val) {
+ _prefs.labelsize(val);
+ }
+
+ /// Get the default font face used for item's labels when new items are created.
+ ///
+ /// Don't use this if you want to change an existing label() size; use
+ /// item->labelfont() instead.
+ ///
+ int labelfont() const {
+ return(_prefs.labelfont());
+ }
+ /// Set the default font face used for item's labels when new items are created.
+ ///
+ /// Don't use this if you want to change an existing label() size; use
+ /// item->labelfont(int) instead.
+ ///
+ void labelfont(int val) {
+ _prefs.labelfont(val);
+ }
+ /// Get the amount of white space (in pixels) that should appear
+ /// between the widget's left border and the tree's contents.
+ ///
+ int marginleft() const {
+ return(_prefs.marginleft());
+ }
+ /// Set the amount of white space (in pixels) that should appear
+ /// between the widget's left border and the left side of the tree's contents.
+ ///
+ void marginleft(int val) {
+ _prefs.marginleft(val);
+ redraw();
+ }
+ /// Get the amount of white space (in pixels) that should appear
+ /// between the widget's top border and the top of the tree's contents.
+ ///
+ int margintop() const {
+ return(_prefs.margintop());
+ }
+ /// Sets the amount of white space (in pixels) that should appear
+ /// between the widget's top border and the top of the tree's contents.
+ ///
+ void margintop(int val) {
+ _prefs.margintop(val);
+ redraw();
+ }
+ /// Get the amount of white space (in pixels) that should appear
+ /// below an open child tree's contents.
+ ///
+ int openchild_marginbottom() const {
+ return(_prefs.openchild_marginbottom());
+ }
+ /// Set the amount of white space (in pixels) that should appear
+ /// below an open child tree's contents.
+ ///
+ void openchild_marginbottom(int val) {
+ _prefs.openchild_marginbottom(val);
+ redraw();
+ }
+ /// Gets the width of the horizontal connection lines (in pixels)
+ /// that appear to the left of each tree item's label.
+ ///
+ int connectorwidth() const {
+ return(_prefs.connectorwidth());
+ }
+ /// Sets the width of the horizontal connection lines (in pixels)
+ /// that appear to the left of each tree item's label.
+ ///
+ void connectorwidth(int val) {
+ _prefs.connectorwidth(val);
+ redraw();
+ }
+ /// Returns the Fl_Pixmap being used as the default user icon for newly created items.
+ /// Returns zero if no icon has been set, which is the default.
+ ///
+ Fl_Pixmap *usericon() const {
+ return(_prefs.usericon());
+ }
+ /// Sets the Fl_Pixmap to be used as the default user icon for all
+ /// newly created items.
+ ///
+ /// If you want to specify user icons on a per-item basis,
+ /// use Fl_Tree_Item::usericon() instead.
+ ///
+ /// \param[in] val -- The new pixmap to be used, or
+ /// zero to disable user icons.
+ ///
+ void usericon(Fl_Pixmap *val) {
+ _prefs.usericon(val);
+ redraw();
+ }
+ /// Returns the icon to be used as the 'open' icon.
+ /// If none was set, the internal default is returned,
+ /// a simple '[+]' icon.
+ ///
+ Fl_Pixmap *openicon() const {
+ return(_prefs.openicon());
+ }
+ /// Sets the icon to be used as the 'open' icon.
+ /// This overrides the built in default '[+]' icon.
+ ///
+ /// \param[in] val -- The new pixmap, or zero to use the default [+] icon.
+ ///
+ void openicon(Fl_Pixmap *val) {
+ _prefs.openicon(val);
+ redraw();
+ }
+ /// Returns the icon to be used as the 'close' icon.
+ /// If none was set, the internal default is returned,
+ /// a simple '[-]' icon.
+ ///
+ Fl_Pixmap *closeicon() const {
+ return(_prefs.closeicon());
+ }
+ /// Sets the icon to be used as the 'close' icon.
+ /// This overrides the built in default '[-]' icon.
+ ///
+ /// \param[in] val -- The new pixmap, or zero to use the default [-] icon.
+ ///
+ void closeicon(Fl_Pixmap *val) {
+ _prefs.closeicon(val);
+ redraw();
+ }
+ /// Returns 1 if the collapse icon is enabled, 0 if not.
+ int showcollapse() const {
+ return(_prefs.showcollapse());
+ }
+ /// Set if we should show the collapse icon or not.
+ /// If collapse icons are disabled, the user will not be able
+ /// to interactively collapse items in the tree, unless the application
+ /// provides some other means via open() and close().
+ ///
+ /// \param[in] val 1: shows collapse icons (default),\n
+ /// 0: hides collapse icons.
+ ///
+ void showcollapse(int val) {
+ _prefs.showcollapse(val);
+ redraw();
+ }
+ /// Returns 1 if the root item is to be shown, or 0 if not.
+ int showroot() const {
+ return(_prefs.showroot());
+ }
+ /// Set if the root item should be shown or not.
+ /// \param[in] val 1 -- show the root item (default)\n
+ /// 0 -- hide the root item.
+ ///
+ void showroot(int val) {
+ _prefs.showroot(val);
+ redraw();
+ }
+ /// Returns the line drawing style for inter-connecting items.
+ Fl_Tree_Connector connectorstyle() const {
+ return(_prefs.connectorstyle());
+ }
+ /// Sets the line drawing style for inter-connecting items.
+ void connectorstyle(Fl_Tree_Connector val) {
+ _prefs.connectorstyle(val);
+ redraw();
+ }
+ /// Set the default sort order used when items are added to the tree.
+ /// See Fl_Tree_Sort for possible values.
+ ///
+ Fl_Tree_Sort sortorder() const {
+ return(_prefs.sortorder());
+ }
+ /// Gets the sort order used to add items to the tree.
+ void sortorder(Fl_Tree_Sort val) {
+ _prefs.sortorder(val);
+ // no redraw().. only affects new add()itions
+ }
+ /// Sets the style of box used to draw selected items.
+ /// This is an fltk Fl_Boxtype.
+ /// The default is influenced by FLTK's current Fl::scheme()
+ ///
+ Fl_Boxtype selectbox() const {
+ return(_prefs.selectbox());
+ }
+ /// Gets the style of box used to draw selected items.
+ /// This is an fltk Fl_Boxtype.
+ /// The default is influenced by FLTK's current Fl::scheme()
+ ///
+ void selectbox(Fl_Boxtype val) {
+ _prefs.selectbox(val);
+ redraw();
+ }
+ /// Gets the tree's current selection mode.
+ Fl_Tree_Select selectmode() const {
+ return(_prefs.selectmode());
+ }
+ /// Sets the tree's selection mode.
+ void selectmode(Fl_Tree_Select val) {
+ _prefs.selectmode(val);
+ }
+};
+
+#endif /*FL_TREE_H*/