FLTK Utility Library and Widget Collection (FLU): Flu_Tree_Browser.h Source File

Main Page | Class Hierarchy | Class List | File List | Class Members

# Flu_Tree_Browser.h

    00001 // $Id: Flu_Tree_Browser.h,v 1.87 2004/08/02 14:18:16 jbryan Exp $
    00002
    00003 /***************************************************************
    00004  *                FLU - FLTK Utility Widgets
    00005  *  Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University
    00006  *
    00007  * This file and its content is protected by a software license.
    00008  * You should have received a copy of this license with this file.
    00009  * If not, please contact the Ohio Supercomputer Center immediately:
    00010  * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212
    00011  *
    00012  ***************************************************************/
    00013
    00014
    00015
    00016 #ifndef _FLU_TREE_BROWSER_H
    00017 #define _FLU_TREE_BROWSER_H
    00018
    00019 #include <stdio.h>
    00020 #include <string.h>
    00021 #include <stdlib.h>
    00022
    00023 #define USE_FLU_DND
    00024
    00025 /* fltk includes */
    00026 #include <FL/Fl.H>
    00027 #include <FL/Fl_Box.H>
    00028 #include <FL/Fl_Pixmap.H>
    00029 #include <FL/Fl_Image.H>
    00030 #include <FL/Fl_Scrollbar.H>
    00031 #include <FL/Fl_Group.H>
    00032 #include <FL/Fl_Menu_Button.H>
    00033
    00034 /* flu includes */
    00035 #include "FLU/Flu_Enumerations.h"
    00036 #include "FLU/FluSimpleString.h"
    00037 #ifdef USE_FLU_DND
    00038 #include "FLU/Flu_DND.h"
    00039 #else
    00040 typedef struct { bool dummy; } Flu_DND_Event;  // for compatibilty when not compiling DND support
    00041 #endif
    00042
    00044 #ifdef USE_FLU_DND
    00045 class FLU_EXPORT Flu_Tree_Browser : public Fl_Group, public Flu_DND
    00046 #else
    00047 class FLU_EXPORT Flu_Tree_Browser : public Fl_Group
    00048 #endif
    00049 {
    00050
    00051   static bool USE_FLU_WIDGET_CALLBACK;
    00052
    00053  public:
    00054
    00055   class Node;
    00056   friend class Node;
    00057
    00059   Flu_Tree_Browser( int x, int y, int w, int h, const char *label = 0 );
    00060
    00062   virtual ~Flu_Tree_Browser();
    00063
    00065
    00067   Node* add( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true );
    00068
    00070
    00072   Node* add( const char* path, const char* name, Fl_Widget *w = 0, bool showLabel = true );
    00073
    00075
    00077   inline Node* add( Node* n, const char* name, Fl_Widget *w = 0, bool showLabel = true )
    00078     { return n->add( name, w, showLabel ); }
    00079
    00081   Node* add_branch( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true );
    00082
    00084   Node* add_branch( const char* path, const char* name, Fl_Widget *w = 0, bool showLabel = true );
    00085
    00087   inline Node* add_branch( Node* n, const char* name, Fl_Widget *w = 0, bool showLabel = true )
    00088     { return n->add_branch( name, w, showLabel ); }
    00089
    00091   Node* add_leaf( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true );
    00092
    00094   Node* add_leaf( const char* path, const char* name, Fl_Widget *w = 0, bool showLabel = true );
    00095
    00097   inline Node* add_leaf( Node* n, const char* name, Fl_Widget *w = 0, bool showLabel = true )
    00098     { return n->add_leaf( name, w, showLabel ); }
    00099
    00101   inline void all_branches_always_open( bool b )
    00102     { rdata.allBranchesAlwaysOpen = b; }
    00103
    00105   inline bool all_branches_always_open()
    00106     { return rdata.allBranchesAlwaysOpen; }
    00107
    00109   inline void allow_leaf_duplication( bool b )
    00110     { rdata.allowDuplication = b; }
    00111
    00113   inline bool allow_leaf_duplication()
    00114     { return rdata.allowDuplication; }
    00115
    00117   inline bool have_dnd()
    00118     {
    00119 #ifdef USE_FLU_DND
    00120       return true;
    00121 #else
    00122       return false;
    00123 #endif
    00124     }
    00125
    00127
    00130   inline void allow_dnd( bool b )
    00131     { rdata.dnd = b; }
    00132
    00134   inline bool allow_dnd()
    00135     { return rdata.dnd; }
    00136
    00138   inline void always_open( bool b )
    00139     { root.always_open( b ); }
    00140
    00142   inline bool always_open()
    00143     { return root.always_open(); }
    00144
    00146   inline void animate( bool b )
    00147     { rdata.animate = b; }
    00148
    00150   inline bool animate()
    00151     { return rdata.animate; }
    00152
    00154   void auto_branches( bool b );
    00155
    00157   inline bool auto_branches() const
    00158     { return rdata.autoBranches; }
    00159
    00161   inline Fl_Color branch_color() const
    00162     { return rdata.defBranchColor; }
    00163
    00165   inline Fl_Font branch_font() const
    00166     { return rdata.defBranchFont; }
    00167
    00169   inline int branch_size() const
    00170     { return rdata.defBranchSize; }
    00171
    00173   inline void branch_text( Fl_Color color, Fl_Font font, int size )
    00174     { rdata.defBranchColor = color; rdata.defBranchFont = font; rdata.defBranchSize = size; }
    00175
    00177   void branch_icons( Fl_Image *closed, Fl_Image *open );
    00178
    00180   inline Fl_Boxtype box() const
    00181     { return _box->box(); }
    00182
    00184   inline void box( Fl_Boxtype b )
    00185     { _box->box( b ); }
    00186
    00188   //inline void callback( Fl_Callback *c, void *user_data = 0 )
    00189   //{ rdata.cb = c; rdata.cbd = user_data; }
    00190
    00192   inline int callback_reason() const
    00193     { return rdata.cbReason; }
    00194
    00196
    00197   inline Node* callback_node() const
    00198     { return rdata.cbNode; }
    00199
    00201   void clear();
    00202
    00204   void collapse_icons( Fl_Image *closed, Fl_Image *open );
    00205
    00207   inline float collapse_time() const
    00208     { return rdata.collapseTime; }
    00209
    00211   inline void collapse_time( float t )
    00212     { rdata.collapseTime = t; }
    00213
    00215   inline Fl_Color color() const
    00216     { return _box->color(); }
    00217
    00219   inline void color( Fl_Color c )
    00220     { _box->color( c ); }
    00221
    00223   inline void color( unsigned c )
    00224     { _box->color( (Fl_Color)c ); }
    00225
    00227   inline void connector_style( Fl_Color color, int style, int width = 1 )
    00228     { rdata.defLineColor = color; rdata.lineStyle = style; rdata.lineWidth = width; }
    00229
    00231   inline Fl_Color connector_color() const
    00232     { return rdata.defLineColor; }
    00233
    00235   inline int connector_style() const
    00236     { return rdata.lineStyle; }
    00237
    00239   inline int connector_width() const
    00240     { return rdata.lineWidth; }
    00241
    00243   inline void double_click_opens( bool b )
    00244     { rdata.doubleClickToOpen = b; }
    00245
    00247   inline bool double_click_opens()
    00248     { return rdata.doubleClickToOpen; }
    00249
    00251   inline Fl_Color even_shaded_entry_color() const
    00252     { return rdata.shadedColors[0]; }
    00253
    00255
    00256   inline Node* find( const char *fullpath )
    00257     { return find_next( fullpath ); }
    00258
    00260
    00261   Node* find( const char *path, const char *name );
    00262
    00264
    00265   Node* find( unsigned int id );
    00266
    00268
    00269   inline Node* find( Node *n )
    00270     { if( !n ) return NULL; else return find( n->id() ); }
    00271
    00273
    00274   Node* find( Fl_Widget *w );
    00275
    00277
    00278   Node* find_next( const char *fullpath, Node* startNode = NULL );
    00279
    00281
    00282   Node* find_next( const char *path, const char *name );
    00283
    00285   int find_number( const char *fullpath );
    00286
    00288   int find_number( const char *path, const char *name );
    00289
    00291
    00292   const char* find_path( unsigned int id );
    00293
    00295
    00296   const char* find_path( Fl_Widget *w );
    00297
    00299
    00300   inline const char* find_path( Node *n )
    00301     { if( !n ) return ""; else return find_path( n->id() ); }
    00302
    00304   inline Node* first() { return root.first(); }
    00305
    00307   inline Node* first_branch() { return root.first_branch(); }
    00308
    00310   inline Node* first_leaf() { return root.first_leaf(); }
    00311
    00313   inline float frame_rate() const
    00314     { return rdata.fps; }
    00315
    00317   inline void frame_rate( float f )
    00318     { if( f <= 0.0f ) rdata.fps = 0.001f; else rdata.fps = f; }
    00319
    00321   inline Node *get_root() { return &root; }
    00322
    00324
    00325   Node* get_selected( int index );
    00326
    00328   int handle( int event );
    00329
    00331   inline void horizontal_gap( int g )
    00332     { rdata.hGap = g; rdata.forceResize = true; }
    00333
    00335   inline int horizontal_gap() const
    00336     { return rdata.hGap; }
    00337
    00339   void insertion_mode( int m );
    00340
    00342   inline int insertion_mode()
    00343     { return rdata.insertionMode; }
    00344
    00346   bool Flu_Tree_Browser :: inside_entry_area( int x, int y );
    00347
    00349   inline void label( const char *l )
    00350     { root.text = l; }
    00351
    00353   inline const char* label() const
    00354     { return root.text.c_str(); }
    00355
    00357   inline Node* last() { return root.last(); }
    00358
    00360   inline Node* last_branch() { return root.last_branch(); }
    00361
    00363   inline Node* last_leaf() { return root.last_leaf(); }
    00364
    00366   inline Fl_Color leaf_color() const
    00367     { return rdata.defLeafColor; }
    00368
    00370   inline Fl_Font leaf_font() const
    00371     { return rdata.defLeafFont; }
    00372
    00374   inline int leaf_size() const
    00375     { return rdata.defLeafSize; }
    00376
    00378   void leaf_icon( Fl_Image *icon );
    00379
    00381   inline void leaf_text( Fl_Color color, Fl_Font font, int size )
    00382     { rdata.defLeafColor = color; rdata.defLeafFont = font; rdata.defLeafSize = size; }
    00383
    00385   inline void move_only_same_group( bool b )
    00386     { rdata.moveOnlySameGroup = b; }
    00387
    00389   inline bool move_only_same_group()
    00390     { return rdata.moveOnlySameGroup; }
    00391
    00393   int num_selected();
    00394
    00396   inline Fl_Color odd_shaded_entry_color() const
    00397     { return rdata.shadedColors[1]; }
    00398
    00400   inline void only_one_open_branch( bool b )
    00401     { rdata.singleBranchOpen = b; }
    00402
    00404   inline bool only_one_open_branch()
    00405     { return rdata.singleBranchOpen; }
    00406
    00408   inline void open( bool b )
    00409     { root.open( b ); }
    00410
    00412   inline bool open() const
    00413     { return root.open(); }
    00414
    00416   inline void open_without_children( bool b )
    00417     { rdata.openWOChildren = b; }
    00418
    00420   inline bool open_without_children() const
    00421     { return rdata.openWOChildren; }
    00422
    00424   inline void open_on_select( bool b )
    00425     { rdata.openOnSelect = b; }
    00426
    00428   inline bool open_on_select() const
    00429     { return rdata.openOnSelect; }
    00430
    00432   void print();
    00433
    00435
    00436   unsigned int remove( const char *fullpath );
    00437
    00439
    00440   unsigned int remove( const char *path, const char *name );
    00441
    00443
    00444   unsigned int remove( unsigned int id );
    00445
    00447
    00448   unsigned int remove( Fl_Widget *w );
    00449
    00451
    00452   inline unsigned int remove( Node* n )
    00453     { if( !n ) return 0; else return remove( n->id() ); }
    00454
    00456   void resize( int X, int Y, int W, int H );
    00457
    00459   inline void root_color( Fl_Color c )
    00460     { get_root()->label_color( c ); }
    00461
    00463   inline Fl_Color root_color()
    00464     { return get_root()->label_color(); }
    00465
    00467   inline void root_font( Fl_Font f )
    00468     { get_root()->label_font( f ); }
    00469
    00471   inline Fl_Font root_font()
    00472     { return get_root()->label_font(); }
    00473
    00475   inline void root_size( unsigned char s )
    00476     { get_root()->label_size( s ); }
    00477
    00479   inline unsigned char root_size()
    00480     { return get_root()->label_size(); }
    00481
    00483   inline void select_all()
    00484     { root.select_all(); }
    00485
    00487   inline Fl_Color selection_color() const
    00488     { return rdata.defSelectionColor; }
    00489
    00491   inline void selection_color( Fl_Color c )
    00492     { rdata.defSelectionColor = c; }
    00493
    00495   inline void selection_color( unsigned c )
    00496     { selection_color( (Fl_Color)c ); }
    00497
    00499   inline void selection_drag_mode( int m )
    00500     { rdata.selectionDragMode = m; }
    00501
    00503   inline int selection_drag_mode() const
    00504     { return rdata.selectionDragMode; }
    00505
    00507   inline void selection_mode( int m )
    00508     { rdata.selectionMode = m; root.unselect_all(); }
    00509
    00511   inline int selection_mode() const
    00512     { return rdata.selectionMode; }
    00513
    00514   inline void select_under_mouse( bool b )
    00515     { rdata.selectUnderMouse = b; }
    00516
    00517   inline bool select_under_mouse() const
    00518     { return rdata.selectUnderMouse; }
    00519
    00521   void set_hilighted( Node* n );
    00522
    00524
    00525   Node* set_root( const char *label, Fl_Widget *w = 0, bool showLabel = true );
    00526
    00528   inline void shaded_entry_colors( Fl_Color even, Fl_Color odd )
    00529     { rdata.shadedColors[0] = even; rdata.shadedColors[1] = odd; }
    00530
    00532   inline void show_branches( bool b )
    00533     { rdata.showBranches = b; rdata.forceResize = true; }
    00534
    00536   inline bool show_branches() const
    00537     { return rdata.showBranches; }
    00538
    00540   inline void show_connectors( bool b )
    00541     { rdata.showConnectors = b; }
    00542
    00544   inline bool show_connectors() const
    00545     { return rdata.showConnectors; }
    00546
    00548   inline void show_root( bool b )
    00549     { rdata.showRoot = b; rdata.forceResize = true; }
    00550
    00552   inline bool show_root() const
    00553     { return rdata.showRoot; }
    00554
    00556   inline void show_leaves( bool b )
    00557     { rdata.showLeaves = b; rdata.forceResize = true; }
    00558
    00560   inline bool show_leaves() const
    00561     { return rdata.showLeaves; }
    00562
    00564   inline void sort()
    00565     { root.sort(); }
    00566
    00568   inline void unselect_all()
    00569     { root.unselect_all(); }
    00570
    00571   inline static void use_FLU_WIDGET_CALLBACK( bool b )
    00572     { USE_FLU_WIDGET_CALLBACK = b; }
    00573
    00575   inline void vertical_gap( int g )
    00576     { rdata.vGap = g; rdata.forceResize = true; }
    00577
    00579   inline int vertical_gap() const
    00580     { return rdata.vGap; }
    00581
    00583
    00585   //inline void when( unsigned int w )
    00586   //{ rdata.when = w; }
    00587
    00589   //inline unsigned int when() const
    00590   //{ return rdata.when; }
    00591
    00593   inline void widget_gap( int g )
    00594     { rdata.wGap = g; rdata.forceResize = true; }
    00595
    00597   inline int widget_gap() const
    00598     { return rdata.wGap; }
    00599
    00600  protected:
    00601
    00602   class RData;
    00603
    00605   class FLU_EXPORT NodeList
    00606     {
    00607     public:
    00608       NodeList();
    00609       ~NodeList();
    00610       void add( Node* n, int position = -1 );
    00611       inline Node* child( int n ) const { return _nodes[n]; }
    00612       int erase( Node* n );
    00613       int erase( const char* n );
    00614       void erase( int n );
    00615       void clear();
    00616       int findNum( const char *n );  // find the number of nodes in the list with name n
    00617       Node* find( const char* n, int which = 1 );  // find the which'th node in the list with name n
    00618       inline int size() const { return _nNodes; };
    00619       void sort();
    00620       static bool move( Node* n1, int where, Node* n2 );
    00621     private:
    00622       friend class Node;
    00623       static int compareNodes( const void *arg1, const void* arg2 );
    00624       static int reverseCompareNodes( const void *arg1, const void* arg2 );
    00625       bool search( Node *n, int &index );
    00626       bool search( const char *n, int &index );
    00627       bool linSearch( Node *n, int &index );
    00628       bool linSearch( const char *n, int &index );
    00629       bool binSearch( Node *n, int &index );
    00630       bool binSearch( const char *n, int &index );
    00631       Node **_nodes;
    00632       int _nNodes, _size;
    00633     };
    00634
    00636   class FLU_EXPORT IntStack
    00637     {
    00638     public:
    00639       IntStack();
    00640       IntStack( const IntStack& s );
    00641       ~IntStack();
    00642       void push( int i );
    00643       int pop();
    00644       void clear();
    00645       inline int operator [](int i) { return _list[i]; }
    00646       inline int size() { return _size; }
    00647       IntStack& operator =( const IntStack& s );
    00648     private:
    00649       int *_list;
    00650       int _size, _bufferSize;
    00651     };
    00652
    00653   public:
    00654   enum { MOVE_BEFORE, MOVE_INSIDE, MOVE_AFTER }; // where to move a dragged node?
    00655  protected:
    00656
    00658   class FLU_EXPORT RData {
    00659   public:
    00660     // volatile objects (from the perspective of each node during a recursive descent)
    00661     int x, y, totalW, totalH;
    00662     bool first, last, dragging, shiftSelect, shiftSelectAll, visibilityChanged;
    00663     Node *hilighted, *lastHilighted, *previous, *grabbed, *dragNode, *animatedNode;
    00664     int delta, shadedIndex, counter, searchIndex, branchIconW, dragPos, dragWhere;
    00665     Fl_Color lineColor, bgColor, selectionColor;
    00666     bool forceResize;  // force the browser to resize on the next draw (which forces a recalculation of the tree layout)
    00667     unsigned int nextId;  // monotonically increasing id of each entry
    00668     FluSimpleString path;  // used to construct the full path during a findPath() operation
    00669     IntStack branchConnectors;
    00670
    00671     // static objects (from the perspective of each node during a recursive descent)
    00672     int insertionMode;
    00673     Fl_Image *defaultCollapseIcons[2], *defaultBranchIcons[2];
    00674     Fl_Image *collapseIcons[2], *branchIcons[2], *leafIcon;
    00675     int hGap, vGap, wGap;
    00676     int lineStyle, lineWidth, selectionMode, selectionDragMode;
    00677     bool showRoot, showConnectors, showLeaves, showBranches, openOnSelect,
    00678       allowDuplication, animate, animating, singleBranchOpen, moveOnlySameGroup, justOpenedClosed,
    00679       isMoveValid, doubleClickToOpen, dnd, allBranchesAlwaysOpen, autoBranches, openWOChildren,
    00680       selectUnderMouse;
    00681     float collapseTime, fps, animationDelta, animationOffset;
    00682     Fl_Color defLineColor, defSelectionColor, shadedColors[2];
    00683     Fl_Color defLeafColor, defBranchColor;
    00684     Fl_Font defLeafFont, defBranchFont;
    00685     int defLeafSize, defBranchSize;
    00686     int browserX, browserY, browserW, browserH;
    00687     Node *root;
    00688     Flu_Tree_Browser *tree;
    00689     unsigned int cbReason;
    00690     Node *cbNode, *lastOpenBranch;
    00691   };
    00692
    00693  public:
    00694
    00695 #ifdef USE_FLU_DND
    00696
    00697
    00699   class FLU_EXPORT DND_Object : public Flu_DND
    00700     {
    00701     public:
    00702
    00704       DND_Object();
    00705
    00707       inline void grab()
    00708         { dnd_grab( this, "DND_Object" ); }
    00709
    00711       virtual const char* name() = 0;
    00712
    00713     };
    00714 #endif
    00715
    00717   class FLU_EXPORT Node
    00718     {
    00719
    00720     protected:
    00721
    00722       enum { ADD, REMOVE, FIND, FIND_NUMBER, GET_SELECTED };  // parameters for modify()
    00723       enum { DRAW, MEASURE, MEASURE_THIS_OPEN, HANDLE, COUNT_SELECTED };  // parameters for recurse()
    00724
    00725       // flags
    00726       enum { SELECTED = 0x0001, COLLAPSED = 0x0002, LEAF = 0x0004, SHOW_LABEL = 0x0008,
    00727              ACTIVE = 0x0010, EXPAND_TO_WIDTH = 0x0020, ALWAYS_OPEN = 0x0040,
    00728              SOME_VISIBLE_CHILDREN = 0x0080, MOVABLE = 0x0100, DROPPABLE = 0x0200 };
    00729
    00730       // flag manipulator functions
    00731       inline bool CHECK( unsigned short flag ) const { return flags & flag; }
    00732       inline void SET( unsigned short flag ) { flags |= flag; }
    00733       inline void SET( unsigned short flag, bool b ) { if(b) SET(flag); else CLEAR(flag); }
    00734       inline void CLEAR( unsigned short flag ) { flags &= ~flag; }
    00735
    00736     public:
    00737
    00739       inline bool active() const
    00740         { return CHECK(ACTIVE); }
    00741
    00743       void active( bool b );
    00744
    00746       inline void activate()
    00747         { active(true); }
    00748
    00750
    00751       inline Node* add( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true )
    00752         { return( modify( fullpath, ADD, tree->rdata, w, showLabel ) ); }
    00753
    00755       Node* add_branch( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true );
    00756
    00758       Node* add_leaf( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true );
    00759
    00761       inline void always_open( bool b )
    00762         { if( b ) open(true); SET(ALWAYS_OPEN,b); tree->rdata.forceResize = true; }
    00763
    00765       inline bool always_open() const
    00766         { return CHECK(ALWAYS_OPEN); }
    00767
    00769       void branch_icons( Fl_Image *closed, Fl_Image *open );
    00770
    00772       inline void branch_icon( Fl_Image *icon )
    00773         { branch_icons( icon, icon ); }
    00774
    00776       Node* child( int i ) const;
    00777
    00779       inline int children() const
    00780         { return _children.size(); }
    00781
    00783       void clear();
    00784
    00786       inline void close()
    00787         { open( false ); }
    00788
    00790       inline bool closed()
    00791         { return !open(); }
    00792
    00794
    00795       void collapse_icons( Fl_Image *closed, Fl_Image *open );
    00796
    00798       inline void deactivate()
    00799         { active(false); }
    00800
    00802       unsigned short depth() const;
    00803
    00805       void do_callback( int reason );
    00806
    00808       inline void droppable( bool b )
    00809         { SET(DROPPABLE,b); }
    00810
    00812       inline bool droppable()
    00813         { return CHECK(DROPPABLE); }
    00814
    00816       inline void expand_to_width( bool b )
    00817         { SET(EXPAND_TO_WIDTH,b); tree->rdata.forceResize = true; }
    00818
    00820       inline bool expand_to_width() const
    00821         { return CHECK(EXPAND_TO_WIDTH); }
    00822
    00824
    00825       inline Node* find( const char *fullpath )
    00826         { return( modify( fullpath, FIND, tree->rdata ) ); }
    00827
    00829
    00830       Node* find( unsigned int id );
    00831
    00833
    00834       Node* find( Fl_Widget *w );
    00835
    00837
    00838       inline Node* find( Node *n )
    00839         { if( !n ) return NULL; else return find( n->id() ); }
    00840
    00842
    00843       inline const char* find_path()
    00844         { return tree->find_path( this ); }
    00845
    00847       Node* first();
    00848
    00850       Node* first_branch();
    00851
    00853       Node* first_leaf();
    00854
    00856
    00857       Node* get_selected( int index );
    00858
    00860       inline unsigned int id() const
    00861         { return _id; }
    00862
    00864
    00865       int index() const;
    00866
    00868       Node* insert( const char* fullpath, int pos );
    00869
    00871       Node* insert_branch( const char* fullpath, int pos );
    00872
    00874       Node* insert_leaf( const char* fullpath, int pos );
    00875
    00877       bool is_ancestor( Node* n );
    00878
    00880       bool is_branch() const;
    00881
    00883       bool is_descendent( Node* n );
    00884
    00886       bool is_leaf() const;
    00887
    00889       inline bool is_root() const
    00890         { return( _parent == 0 ); }
    00891
    00893       inline void label( const char *l )
    00894         { text = l; tree->redraw(); }
    00895
    00897       inline const char* label() const
    00898         { return text.c_str(); }
    00899
    00901       inline void label_color( Fl_Color c )
    00902         { textColor = c; }
    00903
    00905       inline Fl_Color label_color() const
    00906         { return textColor; }
    00907
    00909       inline void label_font( Fl_Font f )
    00910         { textFont = f; tree->rdata.forceResize = true; }
    00911
    00913       inline Fl_Font label_font() const
    00914         { return textFont; }
    00915
    00917       inline void label_size( unsigned char s )
    00918         { textSize = s; tree->rdata.forceResize = true; }
    00919
    00921       inline unsigned char label_size() const
    00922         { return textSize; }
    00923
    00925       inline bool label_visible() const
    00926         { return CHECK(SHOW_LABEL); }
    00927
    00929       inline void label_visible( bool b )
    00930         { SET(SHOW_LABEL,b); tree->rdata.forceResize = true; }
    00931
    00933       Node* last();
    00934
    00936       Node* last_branch();
    00937
    00939       Node* last_leaf();
    00940
    00942       void leaf_icon( Fl_Image *icon );
    00943
    00945       inline void movable( bool b )
    00946         { SET(MOVABLE,b); }
    00947
    00949       inline bool movable()
    00950         { return CHECK(MOVABLE); }
    00951
    00953
    00955       bool move( int pos );
    00956
    00958
    00961       inline bool move( int where, Node* n )
    00962         { return( move( this, where, n ) ); }
    00963
    00965
    00968       static bool move( Node* n1, int where, Node* n2 );
    00969
    00971       Node* next();
    00972
    00974       Node* next_branch();
    00975
    00977       Node* next_leaf();
    00978
    00980       Node* next_sibling();
    00981
    00983       int num_selected();
    00984
    00986       inline bool open() const
    00987         { return( !CHECK(COLLAPSED) || tree->rdata.allBranchesAlwaysOpen ); }
    00988
    00990       void open( bool b );
    00991
    00993       inline Node* parent() const
    00994         { return _parent; }
    00995
    00997       Node* previous();
    00998
    01000       Node* previous_branch();
    01001
    01003       Node* previous_leaf();
    01004
    01006       Node* previous_sibling();
    01007
    01009       void print( int spaces = 0 );
    01010
    01012
    01013       inline unsigned int remove( const char *fullpath )
    01014         { return( (unsigned int)modify( fullpath, REMOVE, tree->rdata ) ); }
    01015
    01017
    01018       unsigned int remove( unsigned int id );
    01019
    01021
    01022       unsigned int remove( Fl_Widget *w );
    01023
    01025
    01026       inline unsigned int remove( Node* n )
    01027         { if( !n ) return 0; else return remove( n->id() ); }
    01028
    01030       void select_all();
    01031
    01033       inline bool selected() const
    01034         { return CHECK(SELECTED); }
    01035
    01037       void select( bool b );
    01038
    01040       inline void select_only()
    01041         { tree->unselect_all(); select(true); }
    01042
    01044       inline void sort_children()
    01045         { sort(); }
    01046
    01048
    01049       inline bool swap( Node* n )
    01050         { swap( this, n ); }
    01051
    01053
    01054       static bool swap( Node* n1, Node* n2 );
    01055
    01057       void unselect_all( Node* except = NULL );
    01058
    01060       inline void* user_data()
    01061         { return userData; }
    01062
    01064       inline void user_data( void *d )
    01065         { userData = d; }
    01066
    01068       inline Fl_Widget* widget() const
    01069         { return( _widget ? _widget->w : NULL ); }
    01070
    01072       void widget( Fl_Widget *w );
    01073
    01074     protected:
    01075
    01076       friend class Flu_Tree_Browser;
    01077       friend class NodeList;
    01078
    01079       // Root node constructor
    01080       Node( const char *lbl = 0 );
    01081
    01082       // Non-root constructor
    01083       Node( bool l, const char* n, Node *p, RData &rdata, Fl_Widget *w, bool showLabel );
    01084
    01085       ~Node();
    01086
    01087       // add/remove/find/get
    01088       Node* modify( const char* path, int what, RData &rdata, Fl_Widget *w = 0, bool showLabel = true );
    01089
    01090       void initType();
    01091
    01092       void sort();
    01093
    01094       void determineVisibility( bool parentVisible = true );
    01095
    01096       static bool isMoveValid( Node* &n1, int &where, Node* &n2 );
    01097
    01098       // handle/draw/measure/count
    01099       int recurse( RData &rdata, int type, int event = 0 );
    01100
    01101       void draw( RData &rdata, bool measure );
    01102
    01103       // recursively finding the full path of the node identified by id
    01104       bool findPath( unsigned int id, RData &rdata );
    01105
    01106       // recursively finding the full path of the node containing w
    01107       bool findPath( Fl_Widget *w, RData &rdata );
    01108
    01109       class FLU_EXPORT WidgetInfo
    01110         {
    01111         public:
    01112           Fl_Widget *w;
    01113           int defaultW;  // the initial width of the widget
    01114           void (*CB)(Fl_Widget*,void*);
    01115           void *CBData;
    01116         };
    01117
    01118       unsigned int _id; // the unique id of this node
    01119       unsigned short flags;
    01120       NodeList _children;
    01121       Node *_parent;
    01122       Flu_Tree_Browser *tree;
    01123       FluSimpleString text;
    01124       WidgetInfo *_widget;  // memory overhead deferred to WidgetInfo. present only if widget is
    01125       Fl_Group *_group;
    01126       void *userData;
    01127       int totalChildH; // needed for animation
    01128       Fl_Image *cIcon[2], *bIcon[2], *lIcon;
    01129       Fl_Color textColor;
    01130       Fl_Font textFont;
    01131       unsigned char textSize;  // the font size of the entry label text
    01132       unsigned short textW, textH;  // how big the entry label actually is (stored within the node for performance reasons)
    01133       int currentY; // needed for animation
    01134       unsigned short currentH;
    01135
    01136       inline static void _widgetCB( Fl_Widget* w, void* arg )
    01137         { ((Node*)arg)->widgetCB(); }
    01138       void widgetCB();
    01139      };
    01140
    01141  protected:
    01142
    01143   inline static void _scrollCB( Fl_Widget* w, void* arg )
    01144     { ((Flu_Tree_Browser*)arg)->redraw(); }
    01145
    01146   inline static void _timerRedrawCB( void *arg )
    01147     { ((Flu_Tree_Browser*)arg)->timerRedrawCB(); }
    01148   void timerRedrawCB();
    01149
    01150   inline static void _timerScrollCB( void *arg )
    01151     { ((Flu_Tree_Browser*)arg)->timerScrollCB(); }
    01152   void timerScrollCB();
    01153
    01154   void on_dnd_leave();
    01155
    01156   void on_dnd_release();
    01157
    01158   bool on_dnd_drag( int X, int Y );
    01159
    01160   void on_dnd_drop( const Flu_DND_Event *e );
    01161
    01162   /* override of Fl_Double_Window::draw() */
    01163   void draw();
    01164
    01165   Fl_Group *scrollBox;
    01166   Fl_Scrollbar *scrollH, *scrollV;
    01167   Fl_Group *_box;
    01168   Node root;
    01169   RData rdata;
    01170   int lastEvent;
    01171   float autoScrollX, autoScrollY;
    01172   bool scrolledTimerOn;
    01173
    01174 };
    01175
    01176 #endif