diff options
| author | Matthias Melcher <fltk@matthiasm.com> | 2009-11-14 15:49:12 +0000 |
|---|---|---|
| committer | Matthias Melcher <fltk@matthiasm.com> | 2009-11-14 15:49:12 +0000 |
| commit | 07a18370ad2aa1f2253afbf45565d55605a88b47 (patch) | |
| tree | f2619866e648a105259b24c8265ec08a11bf1971 /FL | |
| parent | 69601a6d5827539394b9468176727ec651c1ebbc (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')
| -rw-r--r-- | FL/Fl_Table.H | 398 | ||||
| -rw-r--r-- | FL/Fl_Table_Row.H | 18 | ||||
| -rw-r--r-- | FL/Fl_Tree.H | 647 | ||||
| -rw-r--r-- | FL/Fl_Tree_Item.H | 291 | ||||
| -rw-r--r-- | FL/Fl_Tree_Item_Array.H | 80 | ||||
| -rw-r--r-- | FL/Fl_Tree_Prefs.H | 353 |
6 files changed, 1579 insertions, 208 deletions
diff --git a/FL/Fl_Table.H b/FL/Fl_Table.H index 5d0d2cf28..47e394176 100644 --- a/FL/Fl_Table.H +++ b/FL/Fl_Table.H @@ -52,24 +52,24 @@ Normally applications use widgets derived from this widget, and do not use this widget directly; this widget is usually too low level to be used directly by applications. - + This widget does \em not handle the data in the table. The draw_cell() method must be overridden by a subclass to manage drawing the contents of the cells. - + This widget can be used in several ways: - - As a custom widget; see test/testtablerow.cxx. Very optimal for even - extremely large tables. - - As a table made up of a single FLTK widget instanced all over the table; - see test/singleinput.cxx. Very optimal for even extremely large tables; - - As a regular container of FLTK widgets, one widget per cell. - See test/widgettable.cxx. \em Not recommended for large tables. - + - As a custom widget; see test/testtablerow.cxx. Very optimal for even + extremely large tables. + - As a table made up of a single FLTK widget instanced all over the table; + see test/singleinput.cxx. Very optimal for even extremely large tables; + - As a regular container of FLTK widgets, one widget per cell. + See test/widgettable.cxx. \em Not recommended for large tables. + When acting as part of a custom widget, events on the cells and/or headings generate callbacks when they are clicked by the user. You control when events are generated based on the setting for Fl_Table::when(). - + When acting as a container for FLTK widgets, the FLTK widgets maintain themselves. Although the draw_cell() method must be overridden, its contents can be very simple. See the draw_cell() code in test/widgettable.cxx. @@ -77,7 +77,7 @@ The following variables are available to classes deriving from Fl_Table: \image html table-dimensions.gif - + <table border=0> <tr><td>x()/y()/w()/h()</td> <td>Fl_Table widget's outer dimension. The outer edge of the border of the @@ -178,21 +178,21 @@ public: CONTEXT_TABLE = 0x20, // in the table CONTEXT_RC_RESIZE = 0x40 // column or row being resized }; - + private: int _rows, _cols; // total rows/cols int _row_header_w; // width of row header int _col_header_h; // height of column header int _row_position; // last row_position set (not necessarily == toprow!) int _col_position; // last col_position set (not necessarily == leftcol!) - + char _row_header; // row header enabled? char _col_header; // col header enabled? char _row_resize; // row resizing enabled? char _col_resize; // col resizing enabled? int _row_resize_min; // row minimum resizing height (default=1) int _col_resize_min; // col minimum resizing width (default=1) - + // OPTIMIZATION: partial row/column redraw variables int _redraw_toprow; int _redraw_botrow; @@ -200,10 +200,10 @@ private: int _redraw_rightcol; Fl_Color _row_header_color; Fl_Color _col_header_color; - + int _auto_drag; int _selecting; - + // An STL-ish vector without templates class IntVector { int *arr; @@ -231,23 +231,23 @@ private: void size(unsigned int count) { if ( count != _size ) { arr = (int*)realloc(arr, count * sizeof(int)); - _size = count; + _size = count; } } int pop_back() { int tmp = arr[_size-1]; _size--; return(tmp); } void push_back(int val) { unsigned int x = _size; size(_size+1); arr[x] = val; } int back() { return(arr[_size-1]); } }; - + IntVector _colwidths; // column widths in pixels IntVector _rowheights; // row heights in pixels - + Fl_Cursor _last_cursor; // last mouse cursor before changed to 'resize' cursor - + // EVENT CALLBACK DATA TableContext _callback_context; // event context int _callback_row, _callback_col; // event row/col - + // handle() state variables. // Put here instead of local statics in handle(), so more // than one Fl_Table can exist without crosstalk between them. @@ -257,15 +257,15 @@ private: int _dragging_x; // starting x position for horiz drag int _dragging_y; // starting y position for vert drag int _last_row; // last row we FL_PUSH'ed - + // Redraw single cell void _redraw_cell(TableContext context, int R, int C); - + void _start_auto_drag(); void _stop_auto_drag(); void _auto_drag_cb(); static void _auto_drag_cb2(void *d); - + protected: enum ResizeFlag { RESIZE_NONE = 0, @@ -274,51 +274,51 @@ protected: RESIZE_ROW_ABOVE = 3, RESIZE_ROW_BELOW = 4 }; - + int table_w, table_h; // table's virtual size (in pixels) int toprow, botrow, leftcol, rightcol; // four corners of viewable table - + // selection int current_row, current_col; int select_row, select_col; - + // OPTIMIZATION: Precomputed scroll positions for the toprow/leftcol int toprow_scrollpos; int leftcol_scrollpos; - + // Dimensions int tix, tiy, tiw, tih; // data table inner dimension xywh int tox, toy, tow, toh; // data table outer dimension xywh int wix, wiy, wiw, wih; // widget inner dimension xywh - + Fl_Scroll *table; // container for child fltk widgets (if any) Fl_Scrollbar *vscrollbar; // vertical scrollbar Fl_Scrollbar *hscrollbar; // horizontal scrollbar - + // Fltk int handle(int e); // fltk handle() override - + // Class maintenance void recalc_dimensions(); void table_resized(); // table resized; recalc void table_scrolled(); // table scrolled; recalc void get_bounds(TableContext context, // return x/y/w/h bounds for context - int &X, int &Y, int &W, int &H); + int &X, int &Y, int &W, int &H); void change_cursor(Fl_Cursor newcursor); // change mouse cursor to some other shape TableContext cursor2rowcol(int &R, int &C, ResizeFlag &resizeflag); - // find r/c given current x/y event + // find r/c given current x/y event int find_cell(TableContext context, // find cell's x/y/w/h given r/c - int R, int C, int &X, int &Y, int &W, int &H); + int R, int C, int &X, int &Y, int &W, int &H); int row_col_clamp(TableContext context, int &R, int &C); - // clamp r/c to known universe - + // clamp r/c to known universe + /** Subclass should override this method to handle drawing the cells. This method will be called whenever the table is redrawn, once per cell. - + Only cells that are completely (or partially) visible will be told to draw. - + \p context will be one of the following: <table border=1> @@ -371,65 +371,65 @@ protected: // This is called whenever Fl_Table wants you to draw a cell void MyTable::draw_cell(TableContext context, int R=0, int C=0, int X=0, int Y=0, int W=0, int H=0) { - static char s[40]; - sprintf(s, "%d/%d", R, C); // text for each cell - switch ( context ) - { - case CONTEXT_STARTPAGE: // Fl_Table telling us its starting to draw page - fl_font(FL_HELVETICA, 16); - return; - - case CONTEXT_ROW_HEADER: // Fl_Table telling us it's draw row/col headers - case CONTEXT_COL_HEADER: - fl_push_clip(X, Y, W, H); - { - fl_draw_box(FL_THIN_UP_BOX, X, Y, W, H, color()); - fl_color(FL_BLACK); - fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER); - } - fl_pop_clip(); - return; - - case CONTEXT_CELL: // Fl_Table telling us to draw cells - fl_push_clip(X, Y, W, H); - { - // BG COLOR - fl_color( row_selected(R) ? selection_color() : FL_WHITE); - fl_rectf(X, Y, W, H); - - // TEXT - fl_color(FL_BLACK); - fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER); - - // BORDER - fl_color(FL_LIGHT2); - fl_rect(X, Y, W, H); - } - fl_pop_clip(); - return; - - default: - return; - } - //NOTREACHED + static char s[40]; + sprintf(s, "%d/%d", R, C); // text for each cell + switch ( context ) + { + case CONTEXT_STARTPAGE: // Fl_Table telling us its starting to draw page + fl_font(FL_HELVETICA, 16); + return; + + case CONTEXT_ROW_HEADER: // Fl_Table telling us it's draw row/col headers + case CONTEXT_COL_HEADER: + fl_push_clip(X, Y, W, H); + { + fl_draw_box(FL_THIN_UP_BOX, X, Y, W, H, color()); + fl_color(FL_BLACK); + fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER); + } + fl_pop_clip(); + return; + + case CONTEXT_CELL: // Fl_Table telling us to draw cells + fl_push_clip(X, Y, W, H); + { + // BG COLOR + fl_color( row_selected(R) ? selection_color() : FL_WHITE); + fl_rectf(X, Y, W, H); + + // TEXT + fl_color(FL_BLACK); + fl_draw(s, X, Y, W, H, FL_ALIGN_CENTER); + + // BORDER + fl_color(FL_LIGHT2); + fl_rect(X, Y, W, H); + } + fl_pop_clip(); + return; + + default: + return; + } + //NOTREACHED } \endcode */ virtual void draw_cell(TableContext context, int R=0, int C=0, - int X=0, int Y=0, int W=0, int H=0) - { } // overridden by deriving class - + int X=0, int Y=0, int W=0, int H=0) + { } // overridden by deriving class + long row_scroll_position(int row); // find scroll position of row (in pixels) long col_scroll_position(int col); // find scroll position of col (in pixels) - + int is_fltk_container() { // does table contain fltk widgets? return( Fl_Group::children() > 3 ); // (ie. more than box and 2 scrollbars?) } - + static void scroll_cb(Fl_Widget*,void*); // h/v scrollbar callback - + void damage_zone(int r1, int c1, int r2, int c2, int r3 = 0, int c3 = 0); - + void redraw_range(int toprow, int botrow, int leftcol, int rightcol) { if ( _redraw_toprow == -1 ) { // Initialize redraw range @@ -444,11 +444,11 @@ protected: if ( leftcol < _redraw_leftcol ) _redraw_leftcol = leftcol; if ( rightcol > _redraw_rightcol ) _redraw_rightcol = rightcol; } - + // Indicate partial redraw needed of some cells damage(FL_DAMAGE_CHILD); } - + public: /** The constructor for the Fl_Table. @@ -456,24 +456,24 @@ public: with headers and row/column resize behavior disabled. */ Fl_Table(int X, int Y, int W, int H, const char *l=0); - + /** The destructor for the Fl_Table. Destroys the table and its associated widgets. */ ~Fl_Table(); - + /** Clears the table to zero rows, zero columns. Same as rows(0); cols(0); \see rows(int), cols(int) */ virtual void clear() { rows(0); cols(0); } - + // topline() // middleline() // bottomline() - + /** Sets the kind of box drawn around the data table, the default being FL_NO_BOX. Changing this value will cause the table @@ -518,30 +518,30 @@ public: /** Returns the range of row and column numbers for all the visible (and partially visible) cells in the table. - + These values can be used e.g. by your draw_cell() routine during CONTEXT_STARTPAGE to figure out what cells are about to be redrawn, for the purposes of locking the data from a database before it's drawn. \code - leftcol rightcol - : : + leftcol rightcol + : : toprow .. .-------------------. - | | - | V I S I B L E | - | | - | T A B L E | - | | + | | + | V I S I B L E | + | | + | T A B L E | + | | botrow .. '-------------------` \endcode e.g. in a table where the visible rows are 5-20, and the visible columns are 100-120, then those variables would be: - - toprow = 5 - - botrow = 20 - - leftcol = 100 - - rightcol = 120 + - toprow = 5 + - botrow = 20 + - leftcol = 100 + - rightcol = 120 */ inline void visible_cells(int& r1, int& r2, int& c1, int& c2) { r1 = toprow; @@ -733,7 +733,7 @@ public: inline int row_height(int row) { return((row<0 || row>=(int)_rowheights.size()) ? 0 : _rowheights[row]); } - + /** Sets the width of the specified column in pixels, and the table is redrawn. callback() will be invoked with CONTEXT_RC_RESIZE @@ -812,24 +812,24 @@ public: void get_selection(int& s_top, int& s_left, int& s_bottom, int& s_right); void set_selection(int s_top, int s_left, int s_bottom, int s_right); int move_cursor(int R, int C); - + /** Changes the size of the Fl_Table, causing it to redraw. */ void resize(int X, int Y, int W, int H); // fltk resize() override void draw(void); // fltk draw() override - -// This crashes sortapp() during init. -// void box(Fl_Boxtype val) { -// Fl_Group::box(val); -// if ( table ) { -// resize(x(), y(), w(), h()); -// } -// } -// Fl_Boxtype box(void) const { -// return(Fl_Group::box()); -// } - + + // This crashes sortapp() during init. + // void box(Fl_Boxtype val) { + // Fl_Group::box(val); + // if ( table ) { + // resize(x(), y(), w(), h()); + // } + // } + // Fl_Boxtype box(void) const { + // return(Fl_Group::box()); + // } + // Child group void init_sizes() { table->init_sizes(); @@ -879,8 +879,8 @@ public: \code for ( int i=0; i<children(); i++ ) { - Fl_Widget *w = child(i); - [..] + Fl_Widget *w = child(i); + [..] } \endcode */ @@ -975,85 +975,85 @@ public: #if DOXYGEN /** - Callbacks will be called depending on the setting of Fl_Widget::when(). - - Callback functions should use the following functions to determine the - context/row/column: - - * Fl_Table::callback_row() returns current row - * Fl_Table::callback_col() returns current column - * Fl_Table::callback_context() returns current table context - - callback_row() and callback_col() will be set to the row and column number the - event occurred on. If someone clicked on a row header, \p col will be \a 0. - If someone clicked on a column header, \p row will be \a 0. - - callback_context() will return one of the following: - - <table border=1> - <tr><td><tt>Fl_Table::CONTEXT_ROW_HEADER</tt></td> - <td>Someone clicked on a row header. Excludes resizing.</td> - </tr><tr> - <td><tt>Fl_Table::CONTEXT_COL_HEADER</tt></td> - <td>Someone clicked on a column header. Excludes resizing.</td> - </tr><tr> - <td><tt>Fl_Table::CONTEXT_CELL</tt></td> - <td> - Someone clicked on a cell. - - To receive callbacks for FL_RELEASE events, you must set - when(FL_WHEN_RELEASE). - </td> - </tr><tr> - <td><tt>Fl_Table::CONTEXT_RC_RESIZE</tt></td> - <td> - Someone is resizing rows/columns either interactively, - or via the col_width() or row_height() API. - - Use is_interactive_resize() - to determine interactive resizing. - - If resizing a column, R=0 and C=column being resized. - - If resizing a row, C=0 and R=row being resized. - - NOTE: To receive resize events, you must set when(FL_WHEN_CHANGED). - </td> - </tr> - </table> - - \code - class MyTable - { - [..] - private: - // Handle events that happen on the table - void event_callback2() - { - int R = callback_row(), // row where event occurred - C = callback_col(); // column where event occurred - TableContext context = callback_context(); // which part of table - fprintf(stderr, "callback: Row=%d Col=%d Context=%d Event=%d\n", - R, C, (int)context, (int)Fl::event()); - } - - // Actual static callback - static void event_callback(Fl_Widget*, void* data) - { - MyTable *o = (MyTable*)data; - o->event_callback2(); - } - - public: - MyTable() // Constructor - { - [..] - table.callback(&event_callback, (void*)this); // setup callback - table.when(FL_WHEN_CHANGED|FL_WHEN_RELEASE); // when to call it - } - }; - \endcode - */ + Callbacks will be called depending on the setting of Fl_Widget::when(). + + Callback functions should use the following functions to determine the + context/row/column: + + * Fl_Table::callback_row() returns current row + * Fl_Table::callback_col() returns current column + * Fl_Table::callback_context() returns current table context + + callback_row() and callback_col() will be set to the row and column number the + event occurred on. If someone clicked on a row header, \p col will be \a 0. + If someone clicked on a column header, \p row will be \a 0. + + callback_context() will return one of the following: + + <table border=1> + <tr><td><tt>Fl_Table::CONTEXT_ROW_HEADER</tt></td> + <td>Someone clicked on a row header. Excludes resizing.</td> + </tr><tr> + <td><tt>Fl_Table::CONTEXT_COL_HEADER</tt></td> + <td>Someone clicked on a column header. Excludes resizing.</td> + </tr><tr> + <td><tt>Fl_Table::CONTEXT_CELL</tt></td> + <td> + Someone clicked on a cell. + + To receive callbacks for FL_RELEASE events, you must set + when(FL_WHEN_RELEASE). + </td> + </tr><tr> + <td><tt>Fl_Table::CONTEXT_RC_RESIZE</tt></td> + <td> + Someone is resizing rows/columns either interactively, + or via the col_width() or row_height() API. + + Use is_interactive_resize() + to determine interactive resizing. + + If resizing a column, R=0 and C=column being resized. + + If resizing a row, C=0 and R=row being resized. + + NOTE: To receive resize events, you must set when(FL_WHEN_CHANGED). + </td> + </tr> + </table> + + \code + class MyTable + { + [..] + private: + // Handle events that happen on the table + void event_callback2() + { + int R = callback_row(), // row where event occurred + C = callback_col(); // column where event occurred + TableContext context = callback_context(); // which part of table + fprintf(stderr, "callback: Row=%d Col=%d Context=%d Event=%d\n", + R, C, (int)context, (int)Fl::event()); + } + + // Actual static callback + static void event_callback(Fl_Widget*, void* data) + { + MyTable *o = (MyTable*)data; + o->event_callback2(); + } + + public: + MyTable() // Constructor + { + [..] + table.callback(&event_callback, (void*)this); // setup callback + table.when(FL_WHEN_CHANGED|FL_WHEN_RELEASE); // when to call it + } + }; + \endcode + */ void callback(Fl_Widget*, void*); #endif }; diff --git a/FL/Fl_Table_Row.H b/FL/Fl_Table_Row.H index 593cf0b58..137993c94 100644 --- a/FL/Fl_Table_Row.H +++ b/FL/Fl_Table_Row.H @@ -98,7 +98,7 @@ private: void size(int count) { if ( count != _size ) { arr = (char*)realloc(arr, count * sizeof(char)); - _size = count; + _size = count; } } char pop_back() { @@ -116,7 +116,7 @@ private: } }; CharVector _rowselect; // selection flag for each row - + // handle() state variables. // Put here instead of local statics in handle(), so more // than one instance can exist without crosstalk between. @@ -126,22 +126,22 @@ private: int _last_y; // last event's Y position int _last_push_x; // last PUSH event's X position int _last_push_y; // last PUSH event's Y position - + TableRowSelectMode _selectmode; - + protected: int handle(int event); int find_cell(TableContext context, // find cell's x/y/w/h given r/c - int R, int C, int &X, int &Y, int &W, int &H) { + int R, int C, int &X, int &Y, int &W, int &H) { return(Fl_Table::find_cell(context, R, C, X, Y, W, H)); } - + public: /** The constructor for the Fl_Table_Row. This creates an empty table with no rows or columns, with headers and row/column resize behavior disabled. - */ + */ Fl_Table_Row(int X, int Y, int W, int H, const char *l=0) : Fl_Table(X,Y,W,H,l) { _dragging_select = 0; _last_row = -1; @@ -168,7 +168,7 @@ public: - \p Fl_Table_Row::SELECT_NONE - No selection allowed - \p Fl_Table_Row::SELECT_SINGLE - Only single rows can be selected - \p Fl_Table_Row::SELECT_MULTI - Multiple rows can be selected - */ + */ void type(TableRowSelectMode val); // set selection mode TableRowSelectMode type() const { // get selection mode @@ -187,7 +187,7 @@ public: of 'flag'. 0=deselected, 1=select, 2=toggle existing state. */ int select_row(int row, int flag=1); // select state for row: flag:0=off, 1=on, 2=toggle - // returns: 0=no change, 1=changed, -1=range err + // returns: 0=no change, 1=changed, -1=range err /** This convenience function changes the selection state 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*/ diff --git a/FL/Fl_Tree_Item.H b/FL/Fl_Tree_Item.H new file mode 100644 index 000000000..388dce790 --- /dev/null +++ b/FL/Fl_Tree_Item.H @@ -0,0 +1,291 @@ +#ifndef FL_TREE_ITEM_H +#define FL_TREE_ITEM_H + +#include <FL/Fl.H> +#include <FL/Fl_Widget.H> +#include <FL/Fl_Pixmap.H> +#include <FL/fl_draw.H> + +#include <FL/Fl_Tree_Item_Array.H> +#include <FL/Fl_Tree_Prefs.H> + +////////////////////// +// FL/Fl_Tree_Item.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 for Fl_Tree_Item +/// + +/// \brief Tree item +/// +/// This class is a single tree item, and manages all of the item's attributes. +/// Fl_Tree_Item is used by Fl_Tree, which is comprised of many instances of Fl_Tree_Item. +/// +/// Fl_Tree_Item is hierarchical; it dynamically manages an Fl_Tree_Item_Array of children +/// that are themselves instances of Fl_Tree_Item. Each item can have zero or more children. +/// When an item has children, close() and open() can be used to hide or show them. +/// +/// Items have their own attributes; font size, face, color. +/// Items maintain their own hierarchy of children. +/// +/// When you make changes to items, you'll need to tell the tree to redraw() +/// for the changes to show up. +/// +class Fl_Tree_Item { + const char *_label; // label (memory managed) + int _labelfont; // label's font face + int _labelsize; // label's font size + Fl_Color _labelfgcolor; // label's fg color + Fl_Color _labelbgcolor; // label's bg color + char _open; // item is open? + char _visible; // item is visible? + 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 _label_xywh[4]; // xywh of label + Fl_Widget *_widget; // item's label widget (optional) + Fl_Pixmap *_usericon; // item's user-specific icon (optional) + Fl_Tree_Item_Array _children; // array of child items + Fl_Tree_Item *_parent; // parent item (=0 if root) +protected: + void show_widgets(); + void hide_widgets(); + void draw_vertical_connector(int x, int y1, int y2, const Fl_Tree_Prefs &prefs); + void draw_horizontal_connector(int x1, int x2, int y, const Fl_Tree_Prefs &prefs); +public: + Fl_Tree_Item(const Fl_Tree_Prefs &prefs); // CTOR + ~Fl_Tree_Item(); // DTOR + Fl_Tree_Item(const Fl_Tree_Item *o); // COPY CTOR + void draw(int X, int &Y, int W, Fl_Widget *tree, const Fl_Tree_Prefs &prefs, int lastchild=1); + void show_self(const char *indent = "") const; + void label(const char *val); + const char *label() const; + + /// Set item's label font face. + void labelfont(int val) { + _labelfont = val; + } + /// Get item's label font face. + int labelfont() const { + return(_labelfont); + } + /// Set item's label font size. + void labelsize(int val) { + _labelsize = val; + } + /// Get item's label font size. + int labelsize() const { + return(_labelsize); + } + /// Set item's label foreground text color. + void labelfgcolor(Fl_Color val) { + _labelfgcolor = val; + } + /// Set item's label text color. + void labelcolor(Fl_Color val) { + _labelfgcolor = val; + } + /// Return item's label text color. + Fl_Color labelcolor() const { + return(_labelfgcolor); + } + /// Return item's label foreground text color. + Fl_Color labelfgcolor() const { + return(_labelfgcolor); + } + /// Set item's label background color. + void labelbgcolor(Fl_Color val) { + _labelbgcolor = val; + } + /// Return item's background text color. + Fl_Color labelbgcolor() const { + return(_labelbgcolor); + } + /// Assign an FLTK widget to this item. + void widget(Fl_Widget *val) { + _widget = val; + } + /// Return FLTK widget assigned to this item. + Fl_Widget *widget() const { + return(_widget); + } + /// Return the number of children this item has. + int children() const { + return(_children.total()); + } + /// Return the child item for the given 'index'. + Fl_Tree_Item *child(int index) { + return(_children[index]); + } + /// Return the const child item for the given 'index'. + const Fl_Tree_Item *child(int t) const; + /// See if this item has children. + int has_children() const { + return(children()); + } + int find_child(const char *name); + int find_child(Fl_Tree_Item *item); + int remove_child(Fl_Tree_Item *item); + int remove_child(const char *new_label); + void clear_children(); + void swap_children(int ax, int bx); + int swap_children(Fl_Tree_Item *a, Fl_Tree_Item *b); + const Fl_Tree_Item *find_item(char **arr) const; + Fl_Tree_Item *find_item(char **arr); + ////////////////// + // Adding items + ////////////////// + Fl_Tree_Item *add(const Fl_Tree_Prefs &prefs, const char *new_label); + Fl_Tree_Item *add(const Fl_Tree_Prefs &prefs, char **arr); + Fl_Tree_Item *insert(const Fl_Tree_Prefs &prefs, const char *new_label, int pos=0); + Fl_Tree_Item *insert_above(const Fl_Tree_Prefs &prefs, const char *new_label); + int depth() const; + Fl_Tree_Item *prev(); + Fl_Tree_Item *next(); + + /// Return the parent for this item. + Fl_Tree_Item *parent() { + return(_parent); + } + /// Return the const parent for this item. + const Fl_Tree_Item *parent() const { + return(_parent); + } + /// Set the parent for this item. + /// Should only be used by Fl_Tree's internals. + /// + void parent(Fl_Tree_Item *val) { + _parent = val; + } + ////////////////// + // State + ////////////////// + void open(); + void close(); + /// See if the item is 'open'. + int is_open() const { + return(_open?1:0); + } + /// See if the item is 'closed'. + int is_close() const { + return(_open?0:1); + } + /// Toggle the item's open/closed state. + void open_toggle() { + _open?close():open(); + } + /// Change the item's selection state to the optionally specified 'val'. + /// If 'val' is not specified, the item will be selected. + /// + void select(int val=1) { + _selected = val; + } + /// Toggle the item's selection state. + void select_toggle() { + if ( is_selected() ) { + deselect(); // deselect if selected + } else { + select(); // select if deselected + } + } + /// Disable the item's selection state. + void deselect() { + _selected = 0; + } + /// Deselect self and all children + /// Returns count of how many items were in the 'selected' state, + /// ie. how many items were "changed". + /// + int deselect_all() { + int count = 0; + if ( is_selected() ) { + deselect(); + ++count; + } + for ( int t=0; t<children(); t++ ) { + count += child(t)->deselect_all(); + } + return(count); + } + /// See if the item is selected. + char is_selected() const { + return(_selected); + } + /// Change the item's activation state to the optionally specified 'val'. + /// + /// When deactivated, the item will be 'grayed out'; the callback() + /// won't be invoked if the user clicks on the label. If the item + /// has a widget() associated with the item, its activation state + /// will be changed as well. + /// + /// If 'val' is not specified, the item will be activated. + /// + void activate(int val=1) { + _active = val; + if ( _widget && val != (int)_widget->active() ) { + if ( val ) { + _widget->activate(); + } else { + _widget->deactivate(); + } + _widget->redraw(); + } + } + /// Deactivate the item; the callback() won't be invoked when clicked. + /// Same as activate(0) + /// + void deactivate() { + activate(0); + } + /// See if the item is activated. + char is_activated() const { + return(_active); + } + /// See if the item is activated. + char is_active() const { + return(_active); + } + /// Set the user icon's pixmap. '0' will disable. + void usericon(Fl_Pixmap *val) { + _usericon = val; + } + /// Get the user icon. Returns '0' if disabled. + Fl_Pixmap *usericon() const { + return(_usericon); + } + ////////////////// + // Events + ////////////////// + const Fl_Tree_Item *find_clicked(const Fl_Tree_Prefs &prefs) const; + Fl_Tree_Item *find_clicked(const Fl_Tree_Prefs &prefs); + int event_on_collapse_icon(const Fl_Tree_Prefs &prefs) const; + int event_on_label(const Fl_Tree_Prefs &prefs) const; + /// Is this item the root of the tree? + int is_root() const { + return(_parent==0?1:0); + } +}; + +#endif /*FL_TREE_ITEM_H*/ diff --git a/FL/Fl_Tree_Item_Array.H b/FL/Fl_Tree_Item_Array.H new file mode 100644 index 000000000..7e31862eb --- /dev/null +++ b/FL/Fl_Tree_Item_Array.H @@ -0,0 +1,80 @@ +#ifndef _FL_TREE_ITEM_ARRAY_H +#define _FL_TREE_ITEM_ARRAY_H + +class Fl_Tree_Item; // forward decl must *precede* first doxygen comment block +// or doxygen will not document our class.. + +////////////////////// +// FL/Fl_Tree_Item_Array.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 defines a class that manages an array of Fl_Tree_Item pointers. +/// + +/// \brief Manages an array of Fl_Tree_Item pointers. +/// +/// Because FLTK 1.x.x. has mandated that templates and STL not be used, +/// we use this class to dynamically manage the arrays. +/// +/// None of the methods do range checking on index values; the caller +/// must be sure that index values are within the range 0<index<total() +/// (unless otherwise noted). +/// + +class Fl_Tree_Item_Array { + Fl_Tree_Item **_items; // items array + int _total; // #items in array + int _size; // #items *allocated* for array + int _chunksize; // #items to enlarge mem allocation + void enlarge(int count); +public: + Fl_Tree_Item_Array(int new_chunksize = 10); // CTOR + ~Fl_Tree_Item_Array(); // DTOR + Fl_Tree_Item_Array(const Fl_Tree_Item_Array *o); // COPY CTOR + /// Return the item and index \p i. + Fl_Tree_Item *operator[](int i) { + return(_items[i]); + } + /// Const version of operator[](int i) + const Fl_Tree_Item *operator[](int i) const { + return(_items[i]); + } + /// Return the total items in the array, or 0 if empty. + int total() const { + return(_total); + } + /// Swap the two items at index positions \p ax and \p bx. + void swap(int ax, int bx) { + Fl_Tree_Item *asave = _items[ax]; + _items[ax] = _items[bx]; + _items[bx] = asave; + } + void clear(); + void add(Fl_Tree_Item *val); + void insert(int pos, Fl_Tree_Item *new_item); + void remove(int index); + int remove(Fl_Tree_Item *item); +}; + +#endif /*_FL_TREE_ITEM_ARRAY_H*/ diff --git a/FL/Fl_Tree_Prefs.H b/FL/Fl_Tree_Prefs.H new file mode 100644 index 000000000..36cecefa5 --- /dev/null +++ b/FL/Fl_Tree_Prefs.H @@ -0,0 +1,353 @@ +#ifndef FL_TREE_PREFS_H +#define FL_TREE_PREFS_H + +////////////////////// +// FL/Fl_Tree_Prefs.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 for Fl_Tree's preferences. +/// +/// \code +/// Fl_Tree_Prefs +/// : +/// .....:....... +/// : : +/// Fl_Tree : +/// |_____ Fl_Tree_Item +/// +/// \endcode +/// + +/// \class Fl_Tree_Prefs +/// \brief Tree widget's preferences. + +/// \enum Fl_Tree_Sort +/// 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_ASCENDING=1, ///< Add items in ascending sort order. + FL_TREE_SORT_DESCENDING=2 ///< Add items in descending sort order. +}; + +/// \enum Fl_Tree_Connector +/// Defines the style of connection lines between items. +/// +enum Fl_Tree_Connector { + FL_TREE_CONNECTOR_NONE=0, ///< Use no lines connecting items + FL_TREE_CONNECTOR_DOTTED=1, ///< Use dotted lines connecting items (default) + FL_TREE_CONNECTOR_SOLID=2 ///< Use solid lines connecting items +}; + +/// \enum Fl_Tree_Select +/// Tree selection style. +/// +enum Fl_Tree_Select { + FL_TREE_SELECT_NONE=0, ///< Nothing selected when items are clicked + FL_TREE_SELECT_SINGLE, ///< Single item selected when item is clicked (default) + FL_TREE_SELECT_MULTI ///< Multiple items can be selected by clicking with + ///< SHIFT or CTRL or mouse drags. +}; + +/// \class Fl_Tree_Prefs +/// +/// \brief Fl_Tree's Preferences class. +/// +/// This class manages the Fl_Tree's defaults. +/// You should probably be using the methods in Fl_Tree +/// instead of trying to accessing tree's preferences settings directly. +/// +class Fl_Tree_Prefs { + int _labelfont; // label's font face + int _labelsize; // label's font size + int _margintop; // -- + int _marginleft; // |- tree's margins + //int _marginright; // | + //int _marginbottom; // -- + 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 + int _connectorwidth; // connector width (right of open/close icon) + int _linespacing; // vertical space between lines + // Colors + Fl_Color _fgcolor; // label's foreground color + Fl_Color _bgcolor; // background color + Fl_Color _selectcolor; // selection color + Fl_Color _inactivecolor; // inactive color + Fl_Color _connectorcolor; // connector dotted line color + Fl_Tree_Connector _connectorstyle; // connector line style + Fl_Pixmap *_openpixmap; // the 'open' icon [+] + Fl_Pixmap *_closepixmap; // the 'close' icon [-] + Fl_Pixmap *_userpixmap; // user's own icon + char _showcollapse; // 1=show collapse icons, 0=don't + char _showroot; // show the root item as part of the tree + Fl_Tree_Sort _sortorder; // none, ascening, descending, etc. + Fl_Boxtype _selectbox; // selection box type + Fl_Tree_Select _selectmode; // selection mode +public: + Fl_Tree_Prefs(); + + //////////////////////////// + // Labels + //////////////////////////// + /// Return the label's font. + inline int labelfont() const { + return(_labelfont); + } + /// Set the label's font to \p val. + inline void labelfont(int val) { + _labelfont = val; + } + /// Return the label's size in pixels. + inline int labelsize() const { + return(_labelsize); + } + /// Set the label's size in pixels to \p val. + inline void labelsize(int val) { + _labelsize = val; + } + + //////////////////////////// + // Margins + //////////////////////////// + /// Get the left margin's value in pixels + inline int marginleft() const { + return(_marginleft); + } + /// Set the left margin's value in pixels + inline void marginleft(int val) { + _marginleft = val; + } + /// Get the top margin's value in pixels + inline int margintop() const { + return(_margintop); + } + /// Set the top margin's value in pixels + inline void margintop(int val) { + _margintop = val; + } + /// Get the margin below an open child in pixels + inline int openchild_marginbottom() const { + return(_openchild_marginbottom); + } + /// Set the margin below an open child in pixels + 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); + } + /// Set the user icon's left margin value in pixels + inline void usericonmarginleft(int val) { + _usericonmarginleft = val; + } + /// Get the label's left margin value in pixels + inline int labelmarginleft() const { + return(_labelmarginleft); + } + /// Set the label's left margin value in pixels + inline void labelmarginleft(int val) { + _labelmarginleft = val; + } + /// Get the line spacing value in pixels + inline int linespacing() const { + return(_linespacing); + } + /// Set the line spacing value in pixels + inline void linespacing(int val) { + _linespacing = val; + } + + //////////////////////////// + // Colors and Styles + //////////////////////////// + /// Get the default label foreground color + inline Fl_Color fgcolor() const { + return(_fgcolor); + } + /// Set the default label foreground color + inline void fgcolor(Fl_Color val) { + _fgcolor = val; + } + /// Get the default label background color + inline Fl_Color bgcolor() const { + return(_bgcolor); + } + /// Set the default label background color + inline void bgcolor(Fl_Color val) { + _bgcolor = val; + } + /// Get the default selection color + inline Fl_Color selectcolor() const { + return(_selectcolor); + } + /// Set the default selection color + inline void selectcolor(Fl_Color val) { + _selectcolor = val; + } + /// Get the default inactive color + inline Fl_Color inactivecolor() const { + return(_inactivecolor); + } + /// Set the default inactive color + inline void inactivecolor(Fl_Color val) { + _inactivecolor = val; + } + /// Get the connector color; the color used for tree connection lines + inline Fl_Color connectorcolor() const { + return(_connectorcolor); + } + /// Set the connector color; the color used for tree connection lines + inline void connectorcolor(Fl_Color val) { + _connectorcolor = val; + } + /// Get the connector style + inline Fl_Tree_Connector connectorstyle() const { + return(_connectorstyle); + } + /// Set the connector style + inline void connectorstyle(Fl_Tree_Connector val) { + _connectorstyle = val; + } + /// Set the connector style [integer]. + inline void connectorstyle(int val) { + _connectorstyle = Fl_Tree_Connector(val); + } + /// Get the tree connection line's width + inline int connectorwidth() const { + return(_connectorwidth); + } + /// Set the tree connection line's width + inline void connectorwidth(int val) { + _connectorwidth = val; + } + + //////////////////////////// + // Icons + //////////////////////////// + /// Get the current default 'open' icon. + /// Returns the Fl_Pixmap* of the icon, or 0 if none. + /// + inline Fl_Pixmap *openicon() const { + return(_openpixmap); + } + void openicon(Fl_Pixmap *val); + /// Gets the default 'close' icon + /// Returns the Fl_Pixmap* of the icon, or 0 if none. + /// + inline Fl_Pixmap *closeicon() const { + return(_closepixmap); + } + void closeicon(Fl_Pixmap *val); + /// Gets the default 'user icon' (default is 0) + inline Fl_Pixmap *usericon() const { + return(_userpixmap); + } + /// Sets the default 'user icon' + /// Returns the Fl_Pixmap* of the icon, or 0 if none (default). + /// + inline void usericon(Fl_Pixmap *val) { + _userpixmap = val; + } + + //////////////////////////// + // Options + //////////////////////////// + /// Returns 1 if the collapse icon is enabled, 0 if not. + inline char showcollapse() const { + return(_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. + /// + inline void showcollapse(int val) { + _showcollapse = val; + } + /// Get the default sort order value + inline Fl_Tree_Sort sortorder() const { + return(_sortorder); + } + /// Set the default sort order value. + /// Defines the order new items appear when add()ed to the tree. + /// See Fl_Tree_Sort for possible values. + /// + inline void sortorder(Fl_Tree_Sort val) { + _sortorder = val; + } + /// Get the default selection box's box drawing style as an Fl_Boxtype. + inline Fl_Boxtype selectbox() const { + return(_selectbox); + } + /// Set the default selection box's box drawing style to \p val. + inline void selectbox(Fl_Boxtype val) { + _selectbox = val; + } + /// Returns 1 if the root item is to be shown, or 0 if not. + inline int showroot() const { + return(int(_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. + /// + inline void showroot(int val) { + _showroot = char(val); + } + /// Get the selection mode used for the tree + inline Fl_Tree_Select selectmode() const { + return(_selectmode); + } + /// Set the selection mode used for the tree to \p val. + /// This affects how items in the tree are selected + /// when clicked on and dragged over by the mouse. + /// See Fl_Tree_Select for possible values. + /// + inline void selectmode(Fl_Tree_Select val) { + _selectmode = val; + } +}; + +#endif /*FL_TREE_PREFS_H*/ |
