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.91 2004/11/05 17:03:20 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   Node* add( const char* path, const char* name, Fl_Widget *w = 0, bool showLabel = true );
    00071
    00073
    00075   inline Node* add( Node* n, const char* name, Fl_Widget *w = 0, bool showLabel = true )
    00076     { return n->add( name, w, showLabel ); }
    00077
    00079   Node* add_branch( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true );
    00080
    00082   Node* add_branch( const char* path, const char* name, Fl_Widget *w = 0, bool showLabel = true );
    00083
    00085   inline Node* add_branch( Node* n, const char* name, Fl_Widget *w = 0, bool showLabel = true )
    00086     { return n->add_branch( name, w, showLabel ); }
    00087
    00089   Node* add_leaf( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true );
    00090
    00092   Node* add_leaf( const char* path, const char* name, Fl_Widget *w = 0, bool showLabel = true );
    00093
    00095   inline Node* add_leaf( Node* n, const char* name, Fl_Widget *w = 0, bool showLabel = true )
    00096     { return n->add_leaf( name, w, showLabel ); }
    00097
    00099   inline void all_branches_always_open( bool b )
    00100     { rdata.allBranchesAlwaysOpen = b; }
    00101
    00103   inline bool all_branches_always_open()
    00104     { return rdata.allBranchesAlwaysOpen; }
    00105
    00107   inline void allow_leaf_duplication( bool b )
    00108     { rdata.allowDuplication = b; }
    00109
    00111   inline bool allow_leaf_duplication()
    00112     { return rdata.allowDuplication; }
    00113
    00115   inline bool have_dnd()
    00116     {
    00117 #ifdef USE_FLU_DND
    00118       return true;
    00119 #else
    00120       return false;
    00121 #endif
    00122     }
    00123
    00125
    00128   inline void allow_dnd( bool b )
    00129     { rdata.dnd = b; }
    00130
    00132   inline bool allow_dnd()
    00133     { return rdata.dnd; }
    00134
    00136   inline void always_open( bool b )
    00137     { root.always_open( b ); }
    00138
    00140   inline bool always_open()
    00141     { return root.always_open(); }
    00142
    00144   inline void animate( bool b )
    00145     { rdata.animate = b; }
    00146
    00148   inline bool animate()
    00149     { return rdata.animate; }
    00150
    00152   void auto_branches( bool b );
    00153
    00155   inline bool auto_branches() const
    00156     { return rdata.autoBranches; }
    00157
    00159   inline Fl_Color branch_color() const
    00160     { return rdata.defBranchColor; }
    00161
    00163   inline Fl_Font branch_font() const
    00164     { return rdata.defBranchFont; }
    00165
    00167   inline int branch_size() const
    00168     { return rdata.defBranchSize; }
    00169
    00171   inline void branch_text( Fl_Color color, Fl_Font font, int size )
    00172     { rdata.defBranchColor = color; rdata.defBranchFont = font; rdata.defBranchSize = size; }
    00173
    00175
    00176   void branch_icons( Fl_Image *closed, Fl_Image *open );
    00177
    00179   inline Fl_Boxtype box() const
    00180     { return _box->box(); }
    00181
    00183   inline void box( Fl_Boxtype b )
    00184     { _box->box( b ); }
    00185
    00187   //inline void callback( Fl_Callback *c, void *user_data = 0 )
    00188   //{ rdata.cb = c; rdata.cbd = user_data; }
    00189
    00191   inline int callback_reason() const
    00192     { return rdata.cbReason; }
    00193
    00195
    00196   inline Node* callback_node() const
    00197     { return rdata.cbNode; }
    00198
    00200   void clear();
    00201
    00203   void collapse_icons( Fl_Image *closed, Fl_Image *open );
    00204
    00206   inline float collapse_time() const
    00207     { return rdata.collapseTime; }
    00208
    00210   inline void collapse_time( float t )
    00211     { rdata.collapseTime = t; }
    00212
    00214   inline Fl_Color color() const
    00215     { return _box->color(); }
    00216
    00218   inline void color( Fl_Color c )
    00219     { _box->color( c ); }
    00220
    00222   inline void color( unsigned c )
    00223     { _box->color( (Fl_Color)c ); }
    00224
    00226   inline void connector_style( Fl_Color color, int style, int width = 1 )
    00227     { rdata.defLineColor = color; rdata.lineStyle = style; rdata.lineWidth = width; }
    00228
    00230   inline Fl_Color connector_color() const
    00231     { return rdata.defLineColor; }
    00232
    00234   inline int connector_style() const
    00235     { return rdata.lineStyle; }
    00236
    00238   inline int connector_width() const
    00239     { return rdata.lineWidth; }
    00240
    00242   inline void double_click_opens( bool b )
    00243     { rdata.doubleClickToOpen = b; }
    00244
    00246   inline bool double_click_opens()
    00247     { return rdata.doubleClickToOpen; }
    00248
    00250   inline Fl_Color even_shaded_entry_color() const
    00251     { return rdata.shadedColors[0]; }
    00252
    00254
    00255   inline Node* find( const char *fullpath )
    00256     { return find_next( fullpath ); }
    00257
    00259
    00260   Node* find( const char *path, const char *name );
    00261
    00263
    00264   Node* find( unsigned int id );
    00265
    00267
    00268   inline Node* find( Node *n )
    00269     { if( !n ) return NULL; else return find( n->id() ); }
    00270
    00272
    00273   Node* find( Fl_Widget *w );
    00274
    00276
    00277   Node* find_next( const char *fullpath, Node* startNode = NULL );
    00278
    00280
    00281   Node* find_next( const char *path, const char *name );
    00282
    00284   int find_number( const char *fullpath );
    00285
    00287   int find_number( const char *path, const char *name );
    00288
    00290
    00291   const char* find_path( unsigned int id );
    00292
    00294
    00295   const char* find_path( Fl_Widget *w );
    00296
    00298
    00299   inline const char* find_path( Node *n )
    00300     { if( !n ) return ""; else return find_path( n->id() ); }
    00301
    00303   inline Node* first() { return root.first(); }
    00304
    00306   inline Node* first_branch() { return root.first_branch(); }
    00307
    00309   inline Node* first_leaf() { return root.first_leaf(); }
    00310
    00312   inline float frame_rate() const
    00313     { return rdata.fps; }
    00314
    00316   inline void frame_rate( float f )
    00317     { if( f <= 0.0f ) rdata.fps = 0.001f; else rdata.fps = f; }
    00318
    00320   inline Node* get_hilighted()
    00321     { return rdata.hilighted; }
    00322
    00324   inline Node *get_root() { return &root; }
    00325
    00327
    00328   Node* get_selected( int index );
    00329
    00331   int handle( int event );
    00332
    00334   inline void horizontal_gap( int g )
    00335     { rdata.hGap = g; rdata.forceResize = true; }
    00336
    00338   inline int horizontal_gap() const
    00339     { return rdata.hGap; }
    00340
    00342   void insertion_mode( int m );
    00343
    00345   inline int insertion_mode()
    00346     { return rdata.insertionMode; }
    00347
    00349   bool Flu_Tree_Browser :: inside_entry_area( int x, int y );
    00350
    00352   inline void label( const char *l )
    00353     { root.text = l; }
    00354
    00356   inline const char* label() const
    00357     { return root.text.c_str(); }
    00358
    00360   inline Node* last() { return root.last(); }
    00361
    00363   inline Node* last_branch() { return root.last_branch(); }
    00364
    00366   inline Node* last_leaf() { return root.last_leaf(); }
    00367
    00369   inline Fl_Color leaf_color() const
    00370     { return rdata.defLeafColor; }
    00371
    00373   inline Fl_Font leaf_font() const
    00374     { return rdata.defLeafFont; }
    00375
    00377   inline int leaf_size() const
    00378     { return rdata.defLeafSize; }
    00379
    00381   void leaf_icon( Fl_Image *icon );
    00382
    00384   inline void leaf_text( Fl_Color color, Fl_Font font, int size )
    00385     { rdata.defLeafColor = color; rdata.defLeafFont = font; rdata.defLeafSize = size; }
    00386
    00388   inline void move_only_same_group( bool b )
    00389     { rdata.moveOnlySameGroup = b; }
    00390
    00392   inline bool move_only_same_group()
    00393     { return rdata.moveOnlySameGroup; }
    00394
    00396   int num_selected();
    00397
    00399   inline Fl_Color odd_shaded_entry_color() const
    00400     { return rdata.shadedColors[1]; }
    00401
    00403   inline void only_one_open_branch( bool b )
    00404     { rdata.singleBranchOpen = b; }
    00405
    00407   inline bool only_one_open_branch()
    00408     { return rdata.singleBranchOpen; }
    00409
    00411   inline void open( bool b )
    00412     { root.open( b ); }
    00413
    00415   inline bool open() const
    00416     { return root.open(); }
    00417
    00419   inline void open_without_children( bool b )
    00420     { rdata.openWOChildren = b; }
    00421
    00423   inline bool open_without_children() const
    00424     { return rdata.openWOChildren; }
    00425
    00427   inline void open_on_select( bool b )
    00428     { rdata.openOnSelect = b; }
    00429
    00431   inline bool open_on_select() const
    00432     { return rdata.openOnSelect; }
    00433
    00435   void print();
    00436
    00438
    00439   unsigned int remove( const char *fullpath );
    00440
    00442
    00443   unsigned int remove( const char *path, const char *name );
    00444
    00446
    00447   unsigned int remove( unsigned int id );
    00448
    00450
    00451   unsigned int remove( Fl_Widget *w );
    00452
    00454
    00455   inline unsigned int remove( Node* n )
    00456     { if( !n ) return 0; else return remove( n->id() ); }
    00457
    00459   void resize( int X, int Y, int W, int H );
    00460
    00462   inline void root_color( Fl_Color c )
    00463     { get_root()->label_color( c ); }
    00464
    00466   inline Fl_Color root_color()
    00467     { return get_root()->label_color(); }
    00468
    00470   inline void root_font( Fl_Font f )
    00471     { get_root()->label_font( f ); }
    00472
    00474   inline Fl_Font root_font()
    00475     { return get_root()->label_font(); }
    00476
    00478   inline void root_size( unsigned char s )
    00479     { get_root()->label_size( s ); }
    00480
    00482   inline unsigned char root_size()
    00483     { return get_root()->label_size(); }
    00484
    00486   inline void select_all()
    00487     { root.select_all(); }
    00488
    00490   inline Fl_Color selection_color() const
    00491     { return rdata.defSelectionColor; }
    00492
    00494   inline void selection_color( Fl_Color c )
    00495     { rdata.defSelectionColor = c; }
    00496
    00498   inline void selection_color( unsigned c )
    00499     { selection_color( (Fl_Color)c ); }
    00500
    00502   inline void selection_drag_mode( int m )
    00503     { rdata.selectionDragMode = m; }
    00504
    00506   inline int selection_drag_mode() const
    00507     { return rdata.selectionDragMode; }
    00508
    00510   inline void selection_follows_hilight( bool b )
    00511     { rdata.selectionFollowsHilight = b; if( b && rdata.hilighted ) rdata.hilighted->select(true); }
    00512
    00514   inline bool selection_follows_hilight()
    00515     { return rdata.selectionFollowsHilight; }
    00516
    00518   inline void selection_mode( int m )
    00519     { rdata.selectionMode = m; root.unselect_all(); }
    00520
    00522   inline int selection_mode() const
    00523     { return rdata.selectionMode; }
    00524
    00526   inline void select_under_mouse( bool b )
    00527     { rdata.selectUnderMouse = b; }
    00528
    00530   inline bool select_under_mouse() const
    00531     { return rdata.selectUnderMouse; }
    00532
    00534   void set_default_branch_icons();
    00535
    00537   void set_hilighted( Node* n );
    00538
    00540
    00541   Node* set_root( const char *label, Fl_Widget *w = 0, bool showLabel = true );
    00542
    00544   inline void shaded_entry_colors( Fl_Color even, Fl_Color odd )
    00545     { rdata.shadedColors[0] = even; rdata.shadedColors[1] = odd; }
    00546
    00548   inline void show_branches( bool b )
    00549     { rdata.showBranches = b; rdata.forceResize = true; }
    00550
    00552   inline bool show_branches() const
    00553     { return rdata.showBranches; }
    00554
    00556   inline void show_connectors( bool b )
    00557     { rdata.showConnectors = b; }
    00558
    00560   inline bool show_connectors() const
    00561     { return rdata.showConnectors; }
    00562
    00564   inline void show_root( bool b )
    00565     { rdata.showRoot = b; rdata.forceResize = true; }
    00566
    00568   inline bool show_root() const
    00569     { return rdata.showRoot; }
    00570
    00572   inline void show_leaves( bool b )
    00573     { rdata.showLeaves = b; rdata.forceResize = true; }
    00574
    00576   inline bool show_leaves() const
    00577     { return rdata.showLeaves; }
    00578
    00580   inline void sort()
    00581     { root.sort(); }
    00582
    00584   inline void unselect_all()
    00585     { root.unselect_all(); }
    00586
    00587   inline static void use_FLU_WIDGET_CALLBACK( bool b )
    00588     { USE_FLU_WIDGET_CALLBACK = b; }
    00589
    00591   inline void vertical_gap( int g )
    00592     { rdata.vGap = g; rdata.forceResize = true; }
    00593
    00595   inline int vertical_gap() const
    00596     { return rdata.vGap; }
    00597
    00599
    00601   //inline void when( unsigned int w )
    00602   //{ rdata.when = w; }
    00603
    00605   //inline unsigned int when() const
    00606   //{ return rdata.when; }
    00607
    00609   inline void widget_gap( int g )
    00610     { rdata.wGap = g; rdata.forceResize = true; }
    00611
    00613   inline int widget_gap() const
    00614     { return rdata.wGap; }
    00615
    00616  protected:
    00617
    00618   class RData;
    00619
    00621   class FLU_EXPORT NodeList
    00622     {
    00623     public:
    00624       NodeList();
    00625       ~NodeList();
    00626       void add( Node* n, int position = -1 );
    00627       inline Node* child( int n ) const { return _nodes[n]; }
    00628       int erase( Node* n );
    00629       int erase( const char* n );
    00630       void erase( int n );
    00631       void clear();
    00632       int findNum( const char *n );  // find the number of nodes in the list with name n
    00633       Node* find( const char* n, int which = 1 );  // find the which'th node in the list with name n
    00634       inline int size() const { return _nNodes; };
    00635       void sort();
    00636       static bool move( Node* n1, int where, Node* n2 );
    00637     private:
    00638       friend class Node;
    00639       static int compareNodes( const void *arg1, const void* arg2 );
    00640       static int reverseCompareNodes( const void *arg1, const void* arg2 );
    00641       bool search( Node *n, int &index );
    00642       bool search( const char *n, int &index );
    00643       bool linSearch( Node *n, int &index );
    00644       bool linSearch( const char *n, int &index );
    00645       bool binSearch( Node *n, int &index );
    00646       bool binSearch( const char *n, int &index );
    00647       Node **_nodes;
    00648       int _nNodes, _size;
    00649     };
    00650
    00652   class FLU_EXPORT IntStack
    00653     {
    00654     public:
    00655       IntStack();
    00656       IntStack( const IntStack& s );
    00657       ~IntStack();
    00658       void push( int i );
    00659       int pop();
    00660       void clear();
    00661       inline int operator [](int i) { return _list[i]; }
    00662       inline int size() { return _size; }
    00663       IntStack& operator =( const IntStack& s );
    00664     private:
    00665       int *_list;
    00666       int _size, _bufferSize;
    00667     };
    00668
    00669   public:
    00670   enum { MOVE_BEFORE, MOVE_INSIDE, MOVE_AFTER }; // where to move a dragged node?
    00671  protected:
    00672
    00674   class FLU_EXPORT RData {
    00675   public:
    00676     // volatile objects (from the perspective of each node during a recursive descent)
    00677     int x, y, totalW, totalH;
    00678     bool first, last, dragging, shiftSelect, shiftSelectAll, visibilityChanged, selectionFollowsHilight;
    00679     Node *hilighted,  *previous, *grabbed, *dragNode, *animatedNode;
    00680     int delta, shadedIndex, counter, searchIndex, branchIconW, dragPos, dragWhere;
    00681     Fl_Color lineColor, bgColor, selectionColor;
    00682     bool forceResize;  // force the browser to resize on the next draw (which forces a recalculation of the tree layout)
    00683     unsigned int nextId;  // monotonically increasing id of each entry
    00684     FluSimpleString path;  // used to construct the full path during a findPath() operation
    00685     IntStack branchConnectors;
    00686
    00687     // static objects (from the perspective of each node during a recursive descent)
    00688     int insertionMode;
    00689     Fl_Image *defaultCollapseIcons[2], *defaultBranchIcons[2];
    00690     Fl_Image *collapseIcons[2], *branchIcons[2], *leafIcon;
    00691     int hGap, vGap, wGap;
    00692     int lineStyle, lineWidth, selectionMode, selectionDragMode;
    00693     bool showRoot, showConnectors, showLeaves, showBranches, openOnSelect,
    00694       allowDuplication, animate, animating, singleBranchOpen, moveOnlySameGroup, justOpenedClosed,
    00695       isMoveValid, doubleClickToOpen, dnd, allBranchesAlwaysOpen, autoBranches, openWOChildren,
    00696       selectUnderMouse;
    00697     float collapseTime, fps, animationDelta, animationOffset;
    00698     Fl_Color defLineColor, defSelectionColor, shadedColors[2];
    00699     Fl_Color defLeafColor, defBranchColor;
    00700     Fl_Font defLeafFont, defBranchFont;
    00701     int defLeafSize, defBranchSize;
    00702     int browserX, browserY, browserW, browserH;
    00703     Node *root;
    00704     Flu_Tree_Browser *tree;
    00705     unsigned int cbReason;
    00706     Node *cbNode, *lastOpenBranch;
    00707   };
    00708
    00709  public:
    00710
    00711 #ifdef USE_FLU_DND
    00712
    00713
    00715   class FLU_EXPORT DND_Object : public Flu_DND
    00716     {
    00717     public:
    00718
    00720       DND_Object();
    00721
    00723       inline void grab()
    00724         { dnd_grab( this, "DND_Object" ); }
    00725
    00727       virtual const char* name() = 0;
    00728
    00729     };
    00730 #endif
    00731
    00733   class FLU_EXPORT Node
    00734     {
    00735
    00736     protected:
    00737
    00738       enum { ADD, REMOVE, FIND, FIND_NUMBER, GET_SELECTED };  // parameters for modify()
    00739       enum { DRAW, MEASURE, MEASURE_THIS_OPEN, HANDLE, COUNT_SELECTED };  // parameters for recurse()
    00740
    00741       // flags
    00742       enum { SELECTED = 0x0001, COLLAPSED = 0x0002, LEAF = 0x0004, SHOW_LABEL = 0x0008,
    00743              ACTIVE = 0x0010, EXPAND_TO_WIDTH = 0x0020, ALWAYS_OPEN = 0x0040,
    00744              SOME_VISIBLE_CHILDREN = 0x0080, MOVABLE = 0x0100, DROPPABLE = 0x0200,
    00745              AUTO_LABEL_COLOR = 0x0400, AUTO_COLOR = 0x0800, AUTO_LABEL = 0x1000,
    00746              SWAP_LABEL_AND_WIDGET = 0x2000, ICON_AT_END = 0x4000 };
    00747
    00748       // flag manipulator functions
    00749       inline bool CHECK( unsigned short flag ) const { return flags & flag; }
    00750       inline void SET( unsigned short flag ) { flags |= flag; }
    00751       inline void SET( unsigned short flag, bool b ) { if(b) SET(flag); else CLEAR(flag); }
    00752       inline void CLEAR( unsigned short flag ) { flags &= ~flag; }
    00753
    00754     public:
    00755
    00757       inline bool active() const
    00758         { return CHECK(ACTIVE); }
    00759
    00761       void active( bool b );
    00762
    00764       inline void activate()
    00765         { active(true); }
    00766
    00768
    00769       inline Node* add( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true )
    00770         { return( modify( fullpath, ADD, tree->rdata, w, showLabel ) ); }
    00771
    00773       Node* add_branch( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true );
    00774
    00776       Node* add_leaf( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true );
    00777
    00779       Node* add( const char* path, const char* name, Fl_Widget *w = 0, bool showLabel = true );
    00780
    00782       Node* add_branch( const char* path, const char* name, Fl_Widget *w = 0, bool showLabel = true );
    00783
    00785       Node* add_leaf( const char* path, const char* name, Fl_Widget *w = 0, bool showLabel = true );
    00786
    00788       inline void always_open( bool b )
    00789         { if( b ) open(true); SET(ALWAYS_OPEN,b); tree->rdata.forceResize = true; }
    00790
    00792       inline bool always_open() const
    00793         { return CHECK(ALWAYS_OPEN); }
    00794
    00796       inline void auto_color( bool b )
    00797         { SET(AUTO_COLOR,b); }
    00798
    00800       inline bool auto_color()
    00801         { return CHECK(AUTO_COLOR); }
    00802
    00804       inline void auto_label( bool b )
    00805         { SET(AUTO_LABEL,b); }
    00806
    00808       inline bool auto_label()
    00809         { return CHECK(AUTO_LABEL); }
    00810
    00812       inline void auto_label_color( bool b )
    00813         { SET(AUTO_LABEL_COLOR,b); }
    00814
    00816       inline bool auto_label_color()
    00817         { return CHECK(AUTO_LABEL_COLOR); }
    00818
    00820       void branch_icons( Fl_Image *closed, Fl_Image *open );
    00821
    00823       inline void branch_icon( Fl_Image *icon )
    00824         { branch_icons( icon, icon ); }
    00825
    00827       Node* child( int i ) const;
    00828
    00830       inline int children() const
    00831         { return _children.size(); }
    00832
    00834       void clear();
    00835
    00837       inline void close()
    00838         { open( false ); }
    00839
    00841       inline bool closed()
    00842         { return !open(); }
    00843
    00845
    00846       void collapse_icons( Fl_Image *closed, Fl_Image *open );
    00847
    00849       inline void deactivate()
    00850         { active(false); }
    00851
    00853       unsigned short depth() const;
    00854
    00856       void do_callback( int reason );
    00857
    00859       inline void droppable( bool b )
    00860         { SET(DROPPABLE,b); }
    00861
    00863       inline bool droppable()
    00864         { return CHECK(DROPPABLE); }
    00865
    00867       inline void expand_to_width( bool b )
    00868         { SET(EXPAND_TO_WIDTH,b); tree->rdata.forceResize = true; }
    00869
    00871       inline bool expand_to_width() const
    00872         { return CHECK(EXPAND_TO_WIDTH); }
    00873
    00875
    00876       inline Node* find( const char *fullpath )
    00877         { return( modify( fullpath, FIND, tree->rdata ) ); }
    00878
    00880
    00881       Node* find( unsigned int id );
    00882
    00884
    00885       Node* find( Fl_Widget *w );
    00886
    00888
    00889       inline Node* find( Node *n )
    00890         { if( !n ) return NULL; else return find( n->id() ); }
    00891
    00893
    00894       inline const char* find_path()
    00895         { return tree->find_path( this ); }
    00896
    00898       Node* first();
    00899
    00901       Node* first_branch();
    00902
    00904       Node* first_leaf();
    00905
    00907       inline void swap_label_and_widget( bool b )
    00908         { SET(SWAP_LABEL_AND_WIDGET,b); }
    00909
    00911       inline bool swap_label_and_widget()
    00912         { return CHECK(SWAP_LABEL_AND_WIDGET); }
    00913
    00915
    00916       Node* get_selected( int index );
    00917
    00919       inline void icon_at_end( bool b )
    00920         { SET(ICON_AT_END,b); }
    00921
    00923       inline bool icon_at_end()
    00924         { return CHECK(ICON_AT_END); }
    00925
    00927       inline unsigned int id() const
    00928         { return _id; }
    00929
    00931
    00932       int index() const;
    00933
    00935       Node* insert( const char* fullpath, int pos );
    00936
    00938       Node* insert_branch( const char* fullpath, int pos );
    00939
    00941       Node* insert_leaf( const char* fullpath, int pos );
    00942
    00944       bool is_ancestor( Node* n );
    00945
    00947       bool is_branch() const;
    00948
    00950       bool is_descendent( Node* n );
    00951
    00953       bool is_leaf() const;
    00954
    00956       inline bool is_root() const
    00957         { return( _parent == 0 ); }
    00958
    00960       inline void label( const char *l )
    00961         { text = l; tree->redraw(); }
    00962
    00964       inline const char* label() const
    00965         { return text.c_str(); }
    00966
    00968       inline void label_color( Fl_Color c )
    00969         { textColor = c; }
    00970
    00972       inline Fl_Color label_color() const
    00973         { return textColor; }
    00974
    00976       inline void label_font( Fl_Font f )
    00977         { textFont = f; tree->rdata.forceResize = true; }
    00978
    00980       inline Fl_Font label_font() const
    00981         { return textFont; }
    00982
    00984       inline void label_size( unsigned char s )
    00985         { textSize = s; tree->rdata.forceResize = true; }
    00986
    00988       inline unsigned char label_size() const
    00989         { return textSize; }
    00990
    00992       inline bool label_visible() const
    00993         { return CHECK(SHOW_LABEL); }
    00994
    00996       inline void label_visible( bool b )
    00997         { SET(SHOW_LABEL,b); tree->rdata.forceResize = true; }
    00998
    01000       Node* last();
    01001
    01003       Node* last_branch();
    01004
    01006       Node* last_leaf();
    01007
    01009       void leaf_icon( Fl_Image *icon );
    01010
    01012       inline void movable( bool b )
    01013         { SET(MOVABLE,b); }
    01014
    01016       inline bool movable()
    01017         { return CHECK(MOVABLE); }
    01018
    01020
    01022       bool move( int pos );
    01023
    01025
    01028       inline bool move( int where, Node* n )
    01029         { return( move( this, where, n ) ); }
    01030
    01032
    01035       static bool move( Node* n1, int where, Node* n2 );
    01036
    01038       Node* next();
    01039
    01041       Node* next_branch();
    01042
    01044       Node* next_leaf();
    01045
    01047       Node* next_sibling();
    01048
    01050       int num_selected();
    01051
    01053       inline bool open() const
    01054         { return( !CHECK(COLLAPSED) || tree->rdata.allBranchesAlwaysOpen ); }
    01055
    01057       void open( bool b );
    01058
    01060       inline Node* parent() const
    01061         { return _parent; }
    01062
    01064       Node* previous();
    01065
    01067       Node* previous_branch();
    01068
    01070       Node* previous_leaf();
    01071
    01073       Node* previous_sibling();
    01074
    01076       void print( int spaces = 0 );
    01077
    01079
    01080       inline unsigned int remove( const char *fullpath )
    01081         { return( (unsigned int)modify( fullpath, REMOVE, tree->rdata ) ); }
    01082
    01084
    01085       unsigned int remove( unsigned int id );
    01086
    01088
    01089       unsigned int remove( Fl_Widget *w );
    01090
    01092
    01093       inline unsigned int remove( Node* n )
    01094         { if( !n ) return 0; else return remove( n->id() ); }
    01095
    01097       void select_all();
    01098
    01100       inline bool selected() const
    01101         { return CHECK(SELECTED); }
    01102
    01104       void select( bool b );
    01105
    01107       inline void select_only()
    01108         { tree->unselect_all(); select(true); }
    01109
    01111       inline void sort_children()
    01112         { sort(); }
    01113
    01115
    01116       inline bool swap( Node* n )
    01117         { return swap( this, n ); }
    01118
    01120
    01121       static bool swap( Node* n1, Node* n2 );
    01122
    01124       void unselect_all( Node* except = NULL );
    01125
    01127       inline void* user_data()
    01128         { return userData; }
    01129
    01131       inline void user_data( void *d )
    01132         { userData = d; }
    01133
    01135       inline Fl_Widget* widget() const
    01136         { return( _widget ? _widget->w : NULL ); }
    01137
    01139       void widget( Fl_Widget *w );
    01140
    01141     protected:
    01142
    01143       friend class Flu_Tree_Browser;
    01144       friend class NodeList;
    01145
    01146       // Root node constructor
    01147       Node( const char *lbl = 0 );
    01148
    01149       // Non-root constructor
    01150       Node( bool l, const char* n, Node *p, RData &rdata, Fl_Widget *w, bool showLabel );
    01151
    01152       ~Node();
    01153
    01154       // add/remove/find/get
    01155       Node* modify( const char* path, int what, RData &rdata, Fl_Widget *w = 0, bool showLabel = true );
    01156
    01157       void initType();
    01158
    01159       void sort();
    01160
    01161       void determineVisibility( bool parentVisible = true );
    01162
    01163       static bool isMoveValid( Node* &n1, int &where, Node* &n2 );
    01164
    01165       // handle/draw/measure/count
    01166       int recurse( RData &rdata, int type, int event = 0 );
    01167
    01168       void draw( RData &rdata, bool measure );
    01169
    01170       // recursively finding the full path of the node identified by id
    01171       bool findPath( unsigned int id, RData &rdata );
    01172
    01173       // recursively finding the full path of the node containing w
    01174       bool findPath( Fl_Widget *w, RData &rdata );
    01175
    01176       class FLU_EXPORT WidgetInfo
    01177         {
    01178         public:
    01179           Fl_Widget *w;
    01180           int defaultW;  // the initial width of the widget
    01181           void (*CB)(Fl_Widget*,void*);
    01182           void *CBData;
    01183         };
    01184
    01185       unsigned int _id; // the unique id of this node
    01186       unsigned short flags;
    01187       NodeList _children;
    01188       Node *_parent;
    01189       Flu_Tree_Browser *tree;
    01190       FluSimpleString text;
    01191       WidgetInfo *_widget;  // memory overhead deferred to WidgetInfo. present only if widget is
    01192       Fl_Group *_group;
    01193       void *userData;
    01194       int totalChildH; // needed for animation
    01195       Fl_Image *cIcon[2], *bIcon[2], *lIcon;
    01196       Fl_Color textColor;
    01197       Fl_Font textFont;
    01198       unsigned char textSize;  // the font size of the entry label text
    01199       unsigned short textW, textH;  // how big the entry label actually is (stored within the node for performance reasons)
    01200       int currentY; // needed for animation
    01201       unsigned short currentH;
    01202
    01203       inline static void _widgetCB( Fl_Widget* w, void* arg )
    01204         { ((Node*)arg)->widgetCB(); }
    01205       void widgetCB();
    01206      };
    01207
    01208  protected:
    01209
    01210   inline static void _scrollCB( Fl_Widget* w, void* arg )
    01211     { ((Flu_Tree_Browser*)arg)->redraw(); }
    01212
    01213   inline static void _timerRedrawCB( void *arg )
    01214     { ((Flu_Tree_Browser*)arg)->timerRedrawCB(); }
    01215   void timerRedrawCB();
    01216
    01217   inline static void _timerScrollCB( void *arg )
    01218     { ((Flu_Tree_Browser*)arg)->timerScrollCB(); }
    01219   void timerScrollCB();
    01220
    01221   void on_dnd_leave();
    01222
    01223   void on_dnd_release();
    01224
    01225   bool on_dnd_drag( int X, int Y );
    01226
    01227   void on_dnd_drop( const Flu_DND_Event *e );
    01228
    01229   /* override of Fl_Double_Window::draw() */
    01230   void draw();
    01231
    01232   Fl_Group *scrollBox;
    01233   Fl_Scrollbar *scrollH, *scrollV;
    01234   Fl_Group *_box;
    01235   Node root;
    01236   RData rdata;
    01237   //int lastEvent;
    01238   float autoScrollX, autoScrollY;
    01239   bool scrolledTimerOn;
    01240
    01241 };
    01242
    01243 #endif