Flu_Tree_Browser.h
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:46k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: Flu_Tree_Browser.h,v $
  4.  * PRODUCTION Revision 1000.0  2004/04/12 18:22:29  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [CATCHUP_003] Dev-tree R1.7
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*
  10.  * These files were imported into NCBI's CVS directly from FLU version 2.9.1.
  11.  * Modifications to the source are listed below.
  12.  *
  13.  * ==========================================================================
  14.  * $Log: Flu_Tree_Browser.h,v $
  15.  * Revision 1000.0  2004/04/12 18:22:29  gouriano
  16.  * PRODUCTION: IMPORTED [CATCHUP_003] Dev-tree R1.7
  17.  *
  18.  * Revision 1.7  2004/04/07 12:41:18  dicuccio
  19.  * Fixed compiler warning on MSVC - unsighed char -> bool conversion
  20.  *
  21.  * Revision 1.6  2004/03/25 17:13:45  ivanov
  22.  * Introduced FLU_DND_BASE macro to make DOC++ happy
  23.  *
  24.  * Revision 1.5  2004/03/11 14:10:41  dicuccio
  25.  * Fixes for 64-bit compilation
  26.  *
  27.  * Revision 1.4  2004/03/11 13:51:55  dicuccio
  28.  * Imported FLU version 2.9.1.  Altered export specifiers to match NCBI layout.
  29.  * Altered include paths to match NCBI toolkit layout.
  30.  *
  31.  * ==========================================================================
  32.  */
  33. // $Id: Flu_Tree_Browser.h,v 1000.0 2004/04/12 18:22:29 gouriano Exp $
  34. /***************************************************************
  35.  *                FLU - FLTK Utility Widgets 
  36.  *  Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University
  37.  *
  38.  * This file and its content is protected by a software license.
  39.  * You should have received a copy of this license with this file.
  40.  * If not, please contact the Ohio Supercomputer Center immediately:
  41.  * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212
  42.  * 
  43.  ***************************************************************/
  44. #ifndef _FLU_TREE_BROWSER_H
  45. #define _FLU_TREE_BROWSER_H
  46. #include <stdio.h>
  47. #include <string.h>
  48. #include <stdlib.h>
  49. #define USE_FLU_DND
  50. /* fltk includes */
  51. #include <FL/Fl.H>
  52. #include <FL/Fl_Box.H>
  53. #include <FL/Fl_Pixmap.H>
  54. #include <FL/Fl_Image.H>
  55. #include <FL/Fl_Scrollbar.H>
  56. #include <FL/Fl_Group.H>
  57. #include <FL/Fl_Menu_Button.H>
  58. /* flu includes */
  59. #include <gui/widgets/FLU/Flu_Enumerations.h>
  60. #include <gui/widgets/FLU/FluSimpleString.h>
  61. #ifdef USE_FLU_DND
  62. #include <gui/widgets/FLU/Flu_DND.h>
  63. #else
  64. typedef struct { bool dummy; } Flu_DND_Event;  // for compatibilty when not compiling DND support
  65. #endif
  66. //! This class provides a browser for hierarchical data representation (i.e. a "tree")
  67. #ifdef USE_FLU_DND
  68. #  define FLU_DND_BASE , public Flu_DND
  69. #else
  70. #  define FLU_DND_BASE
  71. #endif
  72. class NCBI_GUIWIDGETS_FLU_EXPORT Flu_Tree_Browser : public Fl_Group FLU_DND_BASE
  73. {
  74.  public:
  75.   class Node;
  76.   friend class Node;
  77.   //! Normal FLTK widget constructor
  78.   Flu_Tree_Browser( int x, int y, int w, int h, const char *label = 0 );
  79.   //! Default destructor
  80.   virtual ~Flu_Tree_Browser();
  81.   //! Add the entry specified by b fullpath to the tree. If b w is not c NULL then that widget is the entry and its label is visible depending on the value of b showLabel. Note that the widget is destroyed by the tree/node on clear() or the destructor
  82.   /*! If b fullpath ends in a slash ("/"), then the entry is added as a branch, else it is added as a leaf
  83.     return a pointer to the Node of the added entry or NULL if the add failed */
  84.   Node* add( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true );
  85.   //! Add entry b name in path b path to the tree. If b w is not c NULL then that widget is the entry and its label is visible depending on the value of b showLabel. Note that the widget is destroyed by the tree/node on clear() or the destructor
  86.   /*! If b name ends in a slash ("/"), then the entry is added as a branch, else it is added as a leaf
  87.     return a pointer to the Node of the added entry or NULL if the add failed */
  88.   Node* add( const char* path, const char* name, Fl_Widget *w = 0, bool showLabel = true );
  89.   //! Add entry b name to node b n. If b w is not c NULL then that widget is the entry and its label is visible depending on the value of b showLabel. Note that the widget is destroyed by the tree/node on clear() or the destructor
  90.   /*! If b name ends in a slash ("/"), then the entry is added as a branch, else it is added as a leaf
  91.     return a pointer to the Node of the added entry or NULL if the add failed */
  92.   inline Node* add( Node* n, const char* name, Fl_Widget *w = 0, bool showLabel = true )
  93.     { return n->add( name, w, showLabel ); }
  94.   //! Convenience function that is the same as add() except it appends a '/' to b fullpath if one does not exist
  95.   Node* add_branch( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true );
  96.   //! Convenience function that is the same as add() except it appends a '/' to b name if one does not exist
  97.   Node* add_branch( const char* path, const char* name, Fl_Widget *w = 0, bool showLabel = true );
  98.   //! Convenience function that is the same as add() except it appends a '/' to b name if one does not exist
  99.   inline Node* add_branch( Node* n, const char* name, Fl_Widget *w = 0, bool showLabel = true )
  100.     { return n->add_branch( name, w, showLabel ); }
  101.   //! Convenience function that is the same as add() except it removes any '/' at the end of b fullpath
  102.   Node* add_leaf( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true );
  103.   //! Convenience function that is the same as add() except it removes any '/' at the end of b fullpath
  104.   Node* add_leaf( const char* path, const char* name, Fl_Widget *w = 0, bool showLabel = true );
  105.   //! Convenience function that is the same as add() except it removes any '/' at the end of b fullpath
  106.   inline Node* add_leaf( Node* n, const char* name, Fl_Widget *w = 0, bool showLabel = true )
  107.     { return n->add_leaf( name, w, showLabel ); }
  108.   //! Set whether all branches are always open. Default value is c false
  109.   inline void all_branches_always_open( bool b )
  110.     { rdata.allBranchesAlwaysOpen = b; }
  111.   //! Get whether all branches are always open. Default value is c false
  112.   inline bool all_branches_always_open()
  113.     { return rdata.allBranchesAlwaysOpen; }
  114.   //! Set whether multiple leaves with the same path are allowed. Default value is c true
  115.   inline void allow_leaf_duplication( bool b )
  116.     { rdata.allowDuplication = b; }
  117.   //! Get whether multiple leaves with the same path are allowed.
  118.   inline bool allow_leaf_duplication()
  119.     { return rdata.allowDuplication; }
  120.   //! return c true if drag and drop support has been compiled in, c false otherwise
  121.   inline bool have_dnd()
  122.     {
  123. #ifdef USE_FLU_DND
  124.       return true;
  125. #else
  126.       return false;
  127. #endif
  128.     }
  129.   //! Set whether drag and drop processing is enabled for the browser. Default is c false
  130.   /*! If DND is enabled, either text or instances of Flu_Tree_Browser::DND_Object from outside the tree can be dragged and dropped
  131.     onto the tree to create a new node. Nodes within the tree can be dragged and dropped (only within the same tree) according to
  132.     the value of selection_drag_mode(). */
  133.   inline void allow_dnd( bool b )
  134.     { rdata.dnd = b; }
  135.   //! Get whether drag and drop processing is enabled for the browser.
  136.   inline bool allow_dnd()
  137.     { return rdata.dnd; }
  138.   //! Set whether the root node is always open. Shortcut for c get_root()->always_open(b). Default is c false
  139.   inline void always_open( bool b )
  140.     { root.always_open( b ); }
  141.   //! Get whether the root node is always open
  142.   inline bool always_open()
  143.     { return root.always_open(); }
  144.   //! Set whether animations of opening/closing branches are enabled. Default is c false
  145.   inline void animate( bool b )
  146.     { rdata.animate = b; }
  147.   //! Get whether animations of opening/closing branches are enabled
  148.   inline bool animate()
  149.     { return rdata.animate; }
  150.   //! Set whether the tree automatically determines whether a node is a branch or a leaf based on whether it has any children. Default is c false
  151.   void auto_branches( bool b );
  152.   //! Get whether the tree automatically determines whether a node is a branch or a leaf based on whether it has any children
  153.   inline bool auto_branches() const
  154.     { return rdata.autoBranches; }
  155.   //! Get the default branch text color 
  156.   inline Fl_Color branch_color() const
  157.     { return rdata.defBranchColor; }
  158.   //! Get the default branch text font 
  159.   inline Fl_Font branch_font() const
  160.     { return rdata.defBranchFont; }
  161.   //! Get the default branch text size 
  162.   inline int branch_size() const
  163.     { return rdata.defBranchSize; }
  164.   //! Set the default color, font and size to use for the text of all subsequent branches added to the tree
  165.   inline void branch_text( Fl_Color color, Fl_Font font, int size )
  166.     { rdata.defBranchColor = color; rdata.defBranchFont = font; rdata.defBranchSize = size; }
  167.   //! Set the default branch icons to use for all subsequent branches added to the tree
  168.   void branch_icons( Fl_Image *closed, Fl_Image *open );
  169.   //! Get the type of box to draw the browser in
  170.   inline Fl_Boxtype box() const
  171.     { return _box->box(); }
  172.   //! Set the type of box to draw the browser in. Default is FL_NO_BOX
  173.   inline void box( Fl_Boxtype b )
  174.     { _box->box( b ); }
  175.   //! Override of Fl_Widget::callback
  176.   inline void callback( Fl_Callback *c, void *user_data = 0 )
  177.     { rdata.cb = c; rdata.cbd = user_data; }
  178.   //! Get the reason why the last callback happened. This can be one of FLU_UNHILIGHTED, FLU_HILIGHTED, FLU_SELECTED, FLU_UNSELECTED, FLU_OPENED, FLU_CLOSED, FLU_DOUBLE_CLICK, FLU_WIDGET_CALLBACK, FLU_MOVED_CALLBACK, FLU_NEW_NODE_CALLBACK
  179.   inline int callback_reason() const
  180.     { return rdata.cbReason; }
  181.   //! Get the node on which the last callback happened.
  182.   /*! note this node is only guaranteed to be in the tree b during the callback. If the callback adds/removes nodes, then this node may have changed. In general, do not use the node returned by this method outside of the tree callback. */
  183.   inline Node* callback_node() const
  184.     { return rdata.cbNode; }
  185.   //! Clear all entries from the tree
  186.   void clear();
  187.   //! Set the default collapse icons to use for all subsequent branches added to the tree
  188.   void collapse_icons( Fl_Image *closed, Fl_Image *open );
  189.   //! Get the amount of time to take when animating an open/close. Use in conjunction with frame_rate()
  190.   inline float collapse_time() const
  191.     { return rdata.collapseTime; }
  192.   //! Set the amount of time to take when animating an open/close. Use in conjunction with frame_rate(). Default is 0.1 seconds
  193.   inline void collapse_time( float t )
  194.     { rdata.collapseTime = t; }
  195.   //! Get the background color of the browser
  196.   inline Fl_Color color() const
  197.     { return _box->color(); }
  198.   //! Set the background color of the browser. Default is FL_WHITE
  199.   inline void color( Fl_Color c )
  200.     { _box->color( c ); }
  201.   //! Set the background color of the browser. Default is FL_WHITE
  202.   inline void color( unsigned c )
  203.     { _box->color( (Fl_Color)c ); }
  204.   //! Set the color, style, and width of the connector lines. Default is FL_DARK2, FL_DOT, 1
  205.   inline void connector_style( Fl_Color color, int style, int width = 1 )
  206.     { rdata.defLineColor = color; rdata.lineStyle = style; rdata.lineWidth = width; }
  207.   //! Get the color of the connector lines
  208.   inline Fl_Color connector_color() const
  209.     { return rdata.defLineColor; }
  210.   //! Get the style of the connector lines
  211.   inline int connector_style() const
  212.     { return rdata.lineStyle; }
  213.   //! Get the width of the connector lines
  214.   inline int connector_width() const
  215.     { return rdata.lineWidth; }
  216.   //! Set whether double-clicking a branch opens/closes it
  217.   inline void double_click_opens( bool b )
  218.     { rdata.doubleClickToOpen = b; }
  219.   //! Get whether double-clicking a branch opens/closes it
  220.   inline bool double_click_opens()
  221.     { return rdata.doubleClickToOpen; }
  222.   //! Get the color to use for shading even entries
  223.   inline Fl_Color even_shaded_entry_color() const 
  224.     { return rdata.shadedColors[0]; }
  225.   //! Find the entry identified by b fullpath
  226.   /*! return a pointer to the Node of the found entry, or NULL if no matching entry was found */
  227.   inline Node* find( const char *fullpath )
  228.     { return find_next( fullpath ); }
  229.   //! Find entry b name in path b path
  230.   /*! return a pointer to the Node of the found entry, or NULL if no matching entry was found */
  231.   Node* find( const char *path, const char *name );
  232.   //! Find the entry identified by unique id b id
  233.   /*! return a pointer to the Node of the found entry, or NULL if no matching entry was found */
  234.   Node* find( unsigned int id );
  235.   //! Search for Node b n in the tree
  236.   /*! return a pointer to b n if it is found, or NULL if it is not in the tree */
  237.   inline Node* find( Node *n )
  238.     { if( !n ) return NULL; else return find( n->id() ); }
  239.   //! Find the entry containing the widget b w
  240.   /*! return a pointer to the Node of the found entry, or NULL if no matching entry was found */
  241.   Node* find( Fl_Widget *w );
  242.   //! Find the next entry identified by b fullpath after b startNode
  243.   /*! return a pointer to the Node of the found entry, or NULL if no matching entry was found */
  244.   Node* find_next( const char *fullpath, Node* startNode = NULL );
  245.   //! Find the next entry b name in path b path after b startNode
  246.   /*! return a pointer to the Node of the found entry, or NULL if no matching entry was found */
  247.   Node* find_next( const char *path, const char *name );
  248.   //! return the number of discovered nodes matching path b fullpath
  249.   int find_number( const char *fullpath );
  250.   //! return the number of discovered nodes with name b name in path b path
  251.   int find_number( const char *path, const char *name );
  252.   //! return the full path of the entry identified by unique id b id, or the empty string if no matching entry was found
  253.   /*! note the returned value is only valid until the next time find_path() is called */
  254.   const char* find_path( unsigned int id );
  255.   //! return the full path of the entry containing the widget b w, or the empty string if no matching entry was found
  256.   /*! note the returned value is only valid until the next time find_path() is called */
  257.   const char* find_path( Fl_Widget *w );
  258.   //! return the full path of Node b n, or the empty string if b n is not in the tree
  259.   /*! note the returned value is only valid until the next time find_path() is called */
  260.   inline const char* find_path( Node *n )
  261.     { if( !n ) return ""; else return find_path( n->id() ); }
  262.   //! return the first node in the tree (i.e. the root)
  263.   inline Node* first() { return root.first(); }
  264.   //! return the first branch encountered in a depth-first traversal of the tree. NULL means there are no branches
  265.   inline Node* first_branch() { return root.first_branch(); }
  266.   //! return the first leaf encountered in a depth-first traversal of the tree. NULL means there are no leaves
  267.   inline Node* first_leaf() { return root.first_leaf(); }
  268.   //! Get the frame rate to use during the open/close animation. Use in conjunction with collapse_time()
  269.   inline float frame_rate() const
  270.     { return rdata.fps; }
  271.   //! Set the frame rate to use during the open/close animation. Use in conjunction with collapse_time(). Default is 100 frames per second
  272.   inline void frame_rate( float f )
  273.     { if( f <= 0.0f ) rdata.fps = 0.001f; else rdata.fps = f; }
  274.   //! return a pointer to the root node of the tree
  275.   inline Node *get_root() { return &root; }
  276.   //! return the selected Node that is at b index among all selected nodes, or c NULL if no Node is selected
  277.   /*! For example, c get_selected(1) will return the first selected node. */
  278.   Node* get_selected( int index );
  279.   //! Override of Fl_Widget::handle
  280.   int handle( int event );
  281.   //! Set the horizontal icon gap for each entry. Default is 2
  282.   inline void horizontal_gap( int g )
  283.     { rdata.hGap = g; rdata.forceResize = true; }
  284.   //! Get the horizontal icon gap for each entry
  285.   inline int horizontal_gap() const
  286.     { return rdata.hGap; }
  287.   //! Set how entries are inserted into the tree. This can be one of FLU_INSERT_FRONT, FLU_INSERT_BACK, FLU_INSERT_SORTED, FLU_INSERT_SORTED_REVERSE. Default is FLU_INSERT_SORTED
  288.   void insertion_mode( int m );
  289.   //! Get how entries are inserted into the tree.
  290.   inline int insertion_mode()
  291.     { return rdata.insertionMode; }
  292.   //! Set the title of the Tree (also the label for the root entry)
  293.   inline void label( const char *l )
  294.     { root.text = l; }
  295.   //! Get the title of the Tree (also the label for the root entry)
  296.   inline const char* label() const
  297.     { return root.text.c_str(); }
  298.   //! return the last node in the tree
  299.   inline Node* last() { return root.last(); }
  300.   //! return the last branch encountered in a depth-first traversal of the tree. NULL means there are no branches
  301.   inline Node* last_branch() { return root.last_branch(); }
  302.   //! return the last leaf encountered in a depth-first traversal of the tree. NULL means there are no leaves
  303.   inline Node* last_leaf() { return root.last_leaf(); }
  304.   //! Get the default leaf text color 
  305.   inline Fl_Color leaf_color() const
  306.     { return rdata.defLeafColor; }
  307.   //! Get the default leaf text font 
  308.   inline Fl_Font leaf_font() const
  309.     { return rdata.defLeafFont; }
  310.   //! Get the default leaf text size 
  311.   inline int leaf_size() const
  312.     { return rdata.defLeafSize; }
  313.   //! Set the default leaf icon to use for all subsequent leaves added to the tree
  314.   void leaf_icon( Fl_Image *icon );
  315.   //! Set the default color, font and size to use for the text of all subsequent leaves added to the tree, Default is FL_BLACK, FL_HELVETICA, 12
  316.   inline void leaf_text( Fl_Color color, Fl_Font font, int size )
  317.     { rdata.defLeafColor = color; rdata.defLeafFont = font; rdata.defLeafSize = size; }
  318.   //! Set whether items can be moved only within their group ( c true ) or can be moved anywhere in the tree ( c false ). Default is c false. Used only when selection_drag_mode() is FLU_DRAG_TO_MOVE.
  319.   inline void move_only_same_group( bool b )
  320.     { rdata.moveOnlySameGroup = b; }
  321.   //! Get whether items can be moved only within their group ( c true ) or can be moved anywhere in the tree ( c false ). Used only when selection_drag_mode() is FLU_DRAG_TO_MOVE.
  322.   inline bool move_only_same_group()
  323.     { return rdata.moveOnlySameGroup; }
  324.   //! return the number of selected entries
  325.   int num_selected();
  326.   //! Get the color to use for shading odd entries
  327.   inline Fl_Color odd_shaded_entry_color() const 
  328.     { return rdata.shadedColors[1]; }
  329.   //! Set whether only a single branch (except the root branch) is allowed open at a time. Default is c false
  330.   inline void only_one_open_branch( bool b )
  331.     { rdata.singleBranchOpen = b; }
  332.   //! Get whether only a single branch (except the root branch) is allowed open at a time
  333.   inline bool only_one_open_branch()
  334.     { return rdata.singleBranchOpen; }
  335.   //! Open or close the root node
  336.   inline void open( bool b )
  337.     { root.open( b ); }
  338.   //! Is the root node open or closed?
  339.   inline bool open() const
  340.     { return root.open(); }
  341.   //! Set whether selecting a branch also opens it. Default is c false
  342.   inline void open_on_select( bool b )
  343.     { rdata.openOnSelect = b; }
  344.   //! Get whether selecting a branch also opens it
  345.   inline bool open_on_select() const
  346.     { return rdata.openOnSelect; }
  347.   //! Print the tree to stdout
  348.   void print();
  349.   //! Remove the entry identified by path b fullpath from the tree
  350.   /*! return the unique id of the removed entry, or c 0 if no matching entry was found */
  351.   unsigned int remove( const char *fullpath );
  352.   //! Remove entry b name in path b path from the tree
  353.   /*! return the unique id of the removed entry, or c 0 if no matching entry was found */
  354.   unsigned int remove( const char *path, const char *name );
  355.   //! Remove the entry identified by unique id b id from the tree
  356.   /*! return the unique id of the removed entry, or c 0 if no matching entry was found */
  357.   unsigned int remove( unsigned int id );
  358.   //! Remove the entry containing the widget b w from the tree. Note that the widget is automatically destroyed
  359.   /*! return the unique id of the removed entry, or c 0 if no matching entry was found */
  360.   unsigned int remove( Fl_Widget *w );
  361.   //! Remove Node b n from the tree
  362.   /*! return the id of b n on successful removal, or c 0 if b n is not in the tree */
  363.   inline unsigned int remove( Node* n )
  364.     { if( !n ) return 0; else return remove( n->id() ); }
  365.   //! Override of Fl_Widget::resize
  366.   void resize( int X, int Y, int W, int H );
  367.   //! Convenience routine to set the root label color. See Flu_Tree_Browser::Node::label_color()
  368.   inline void root_color( Fl_Color c )
  369.     { get_root()->label_color( c ); }
  370.   //! Convenience routine to set the root label color. See Flu_Tree_Browser::Node::label_color()
  371.   inline Fl_Color root_color()
  372.     { return get_root()->label_color(); }
  373.   //! Convenience routine to set the root label font. See Flu_Tree_Browser::Node::label_font()
  374.   inline void root_font( Fl_Font f )
  375.     { get_root()->label_font( f ); }
  376.   //! Convenience routine to set the root label font. See Flu_Tree_Browser::Node::label_font()
  377.   inline Fl_Font root_font()
  378.     { return get_root()->label_font(); }
  379.   //! Convenience routine to set the root label size. See Flu_Tree_Browser::Node::label_size()
  380.   inline void root_size( unsigned char s )
  381.     { get_root()->label_size( s ); }
  382.   //! Convenience routine to set the root label size. See Flu_Tree_Browser::Node::label_size()
  383.   inline unsigned char root_size()
  384.     { return get_root()->label_size(); }
  385.   //! Select all entries in the tree
  386.   inline void select_all()
  387.     { root.select_all(); }
  388.   //! Get the color to use when hilighting selected entries
  389.   inline Fl_Color selection_color() const
  390.     { return rdata.defSelectionColor; }
  391.   //! Set the color to use when hilighting selected entries. Default is FL_SELECTION_COLOR
  392.   inline void selection_color( Fl_Color c )
  393.     { rdata.defSelectionColor = c; }
  394.   //! Set the color to use when hilighting selected entries. Default is FL_SELECTION_COLOR
  395.   inline void selection_color( unsigned c )
  396.     { selection_color( (Fl_Color)c ); }
  397.   //! Set how selection is affected when the mouse is dragged. This can be one of FLU_DRAG_IGNORE, FLU_DRAG_TO_SELECT, FLU_DRAG_TO_MOVE. Default is FLU_DRAG_TO_SELECT.
  398.   inline void selection_drag_mode( int m )
  399.     { rdata.selectionDragMode = m; }
  400.   //! Get how selection is affected when the mouse is dragged
  401.   inline int selection_drag_mode() const
  402.     { return rdata.selectionDragMode; }
  403.   //! Set how individual entries are selected using the mouse. This can be one of FLU_NO_SELECT, FLU_SINGLE_SELECT, FLU_MULTI_SELECT. Default is FLU_MULTI_SELECT
  404.   inline void selection_mode( int m )
  405.     { rdata.selectionMode = m; root.unselect_all(); }
  406.   //! Get how individual entries are selected using the mouse
  407.   inline int selection_mode() const
  408.     { return rdata.selectionMode; }
  409.   //! Set which node is hilighted and ready to be selected or unselected. This also scrolls the browser so b n is visible.
  410.   void set_hilighted( Node* n );
  411.   //! Set the title of the root of the tree to b label. If b w is not c NULL then that widget is the entry and its label is visible depending on the value of b showLabel. Note that the widget is destroyed by the tree/node on clear() or the destructor
  412.   /*! The root icons, color, font and size are set to the current branch icons and text color, font and size */
  413.   Node* set_root( const char *label, Fl_Widget *w = 0, bool showLabel = true );
  414.   //! Set the colors to use for shading every other entry. Default is FL_WHITE, FL_WHITE
  415.   inline void shaded_entry_colors( Fl_Color even, Fl_Color odd )
  416.     { rdata.shadedColors[0] = even; rdata.shadedColors[1] = odd; }
  417.   //! Set whether branch entries are visible. Default is c true
  418.   inline void show_branches( bool b )
  419.     { rdata.showBranches = b; rdata.forceResize = true; }
  420.   //! Get whether branch entries are visible
  421.   inline bool show_branches() const
  422.     { return rdata.showBranches; }
  423.   //! Set whether the connectors between entries are visible. Default is c true
  424.   inline void show_connectors( bool b )
  425.     { rdata.showConnectors = b; }
  426.   //! Get whether the connectors between entries are visible
  427.   inline bool show_connectors() const
  428.     { return rdata.showConnectors; }
  429.   //! Set whether the root branch (i.e. the name of the tree) is visible. Default is c true
  430.   inline void show_root( bool b )
  431.     { rdata.showRoot = b; rdata.forceResize = true; }
  432.   //! Get whether the root branch (i.e. the name of the tree) is visible
  433.   inline bool show_root() const
  434.     { return rdata.showRoot; }
  435.   //! Set whether leaf entries are visible. Default is c true
  436.   inline void show_leaves( bool b )
  437.     { rdata.showLeaves = b; rdata.forceResize = true; }
  438.   //! Get whether leaf entries are visible
  439.   inline bool show_leaves() const
  440.     { return rdata.showLeaves; }
  441.   //! Sort the tree according to insertion_mode()
  442.   inline void sort()
  443.     { root.sort(); }
  444.   //! Unselect all entries in the tree
  445.   inline void unselect_all()
  446.     { root.unselect_all(); }
  447.   //! Set the vertical gap between tree entries. Default is 0
  448.   inline void vertical_gap( int g )
  449.     { rdata.vGap = g; rdata.forceResize = true; }
  450.   //! Get the vertical gap between tree entries
  451.   inline int vertical_gap() const
  452.     { return rdata.vGap; }
  453.   //! Override of Fl_Widget::when. Currently only FL_WHEN_NEVER, FL_WHEN_CHANGED, and FL_WHEN_NOT_CHANGED are supported. Default value is FL_WHEN_CHANGED
  454.   /*! When the callback occurs, you can use callback_reason() to determine exactly what cause the callback and callback_node()
  455.     to get the node that was affected. */
  456.   inline void when( unsigned int w )
  457.     { rdata.when = w; }
  458.   //! Override of Fl_Widget::when
  459.   inline unsigned int when() const
  460.     { return rdata.when; }
  461.   //! Set the gap between the widget and the icon that precedes it. Default is 2
  462.   inline void widget_gap( int g )
  463.     { rdata.wGap = g; rdata.forceResize = true; }
  464.   //! Get the gap between the widget and the icon that precedes it 
  465.   inline int widget_gap() const
  466.     { return rdata.wGap; }
  467.  protected:
  468.   class RData;
  469.   //! Internal class holding an (alphabetically) ordered list of nodes
  470.   class NCBI_GUIWIDGETS_FLU_EXPORT NodeList
  471.     {
  472.     public:
  473.       NodeList();
  474.       ~NodeList();
  475.       void add( Node* n, int position = -1 );
  476.       inline Node* child( int n ) const { return _nodes[n]; }
  477.       int erase( Node* n );
  478.       int erase( const char* n );
  479.       void erase( int n );
  480.       void clear();
  481.       int findNum( const char *n );  // find the number of nodes in the list with name n
  482.       Node* find( const char* n, int which = 1 );  // find the which'th node in the list with name n
  483.       inline int size() const { return _nNodes; };
  484.       void sort();
  485.       static bool move( Node* n1, int where, Node* n2 );
  486.     private:
  487.       friend class Node;
  488.       static int compareNodes( const void *arg1, const void* arg2 );
  489.       static int reverseCompareNodes( const void *arg1, const void* arg2 );
  490.       bool search( Node *n, int &index );
  491.       bool search( const char *n, int &index );
  492.       bool linSearch( Node *n, int &index );
  493.       bool linSearch( const char *n, int &index );
  494.       bool binSearch( Node *n, int &index );
  495.       bool binSearch( const char *n, int &index );
  496.       Node **_nodes;
  497.       int _nNodes, _size;
  498.     };
  499.  public:
  500.   //! Internal class holding a stack of integers
  501.   class NCBI_GUIWIDGETS_FLU_EXPORT IntStack
  502.     {
  503.     public:
  504.       IntStack();
  505.       IntStack( const IntStack& s );
  506.       ~IntStack();
  507.       void push( int i );
  508.       int pop();
  509.       void clear();
  510.       inline int operator [](int i) { return _list[i]; }
  511.       inline int size() { return _size; }
  512.       IntStack& operator =( const IntStack& s );
  513.     private:
  514.       int *_list;
  515.       int _size, _bufferSize;
  516.     };
  517.   public:
  518.   enum { MOVE_BEFORE, MOVE_INSIDE, MOVE_AFTER }; // where to move a dragged node?
  519.  protected:
  520.   //! Recursive data structure passed down through the node tree
  521.   class NCBI_GUIWIDGETS_FLU_EXPORT RData {
  522.   public:
  523.     // volatile objects (from the perspective of each node during a recursive descent)
  524.     int x, y, totalW, totalH;
  525.     bool first, last, dragging, shiftSelect, shiftSelectAll, visibilityChanged;
  526.     Node *hilighted, *lastHilighted, *previous, *grabbed, *dragNode, *animatedNode;
  527.     int delta, shadedIndex, counter, searchIndex, branchIconW, dragPos, dragWhere;
  528.     Fl_Color lineColor, bgColor, selectionColor;
  529.     bool forceResize;  // force the browser to resize on the next draw (which forces a recalculation of the tree layout)
  530.     unsigned int nextId;  // monotonically increasing id of each entry
  531.     FluSimpleString path;  // used to construct the full path during a findPath() operation
  532.     IntStack branchConnectors;
  533.     // static objects (from the perspective of each node during a recursive descent)
  534.     int insertionMode;
  535.     Fl_Image *defaultCollapseIcons[2], *defaultBranchIcons[2];
  536.     Fl_Image *collapseIcons[2], *branchIcons[2], *leafIcon;
  537.     int hGap, vGap, wGap;
  538.     int lineStyle, lineWidth, selectionMode, selectionDragMode;
  539.     bool showRoot, showConnectors, showLeaves, showBranches, openOnSelect,
  540.       allowDuplication, animate, animating, singleBranchOpen, moveOnlySameGroup, justOpenedClosed,
  541.       isMoveValid, doubleClickToOpen, dnd, allBranchesAlwaysOpen, autoBranches;
  542.     float collapseTime, fps, animationDelta, animationOffset;
  543.     Fl_Color defLineColor, defSelectionColor, shadedColors[2];
  544.     Fl_Color defLeafColor, defBranchColor;
  545.     Fl_Font defLeafFont, defBranchFont;
  546.     int defLeafSize, defBranchSize;
  547.     int browserX, browserY, browserW, browserH;
  548.     Node *root;
  549.     Flu_Tree_Browser *tree;
  550.     Fl_Callback *cb;
  551.     void *cbd;
  552.     unsigned int when, cbReason;
  553.     Node *cbNode, *lastOpenBranch;
  554.     //int (*sortCB)(Node*,Node*);
  555.   };
  556.  public:
  557. #ifdef USE_FLU_DND
  558.   //! This class can be subclassed to make an object which can be dropped on a tree to make a new node
  559.   /*! When the object is dropped, the tree will name the object according to what the function
  560.     b name() returns */
  561.   class NCBI_GUIWIDGETS_FLU_EXPORT DND_Object : public Flu_DND
  562.     {
  563.     public:
  564.       //! Default constructor
  565.       DND_Object();
  566.       //! The descendent should call this when the user grabs the object to start dragging it (e.g. on the FL_PUSH event)
  567.       inline void grab()
  568. { dnd_grab( this, "DND_Object" ); }
  569.       //! Descendents MUST implement this function to return the name of the dropped object
  570.       virtual const char* name() = 0;
  571.     };
  572. #endif
  573.   //! This class holds a single entry in the tree
  574.   class NCBI_GUIWIDGETS_FLU_EXPORT Node
  575.     {
  576.     protected:
  577.       enum { ADD, REMOVE, FIND, FIND_NUMBER, GET_SELECTED };  // parameters for modify()
  578.       enum { DRAW, MEASURE, MEASURE_THIS_OPEN, HANDLE, COUNT_SELECTED };  // parameters for recurse()
  579.       // flags
  580.       enum { SELECTED = 0x0001, COLLAPSED = 0x0002, LEAF = 0x0004, SHOW_LABEL = 0x0008,
  581.      ACTIVE = 0x0010, EXPAND_TO_WIDTH = 0x0020, ALWAYS_OPEN = 0x0040,
  582.      SOME_VISIBLE_CHILDREN = 0x0080, MOVABLE = 0x0100, DROPPABLE = 0x0200 };
  583.       // flag manipulator functions
  584.       inline bool CHECK( unsigned short flag ) const { return (flags & flag) ? true : false; }
  585.       inline void SET( unsigned short flag ) { flags |= flag; }
  586.       inline void SET( unsigned short flag, bool b ) { if(b) SET(flag); else CLEAR(flag); }
  587.       inline void CLEAR( unsigned short flag ) { flags &= ~flag; }
  588.     public:
  589.       //! Is this node currently active?
  590.       inline bool active() const
  591. { return CHECK(ACTIVE); }
  592.       //! Activate or deactivate this node
  593.       void active( bool b );
  594.       //! Activate this node
  595.       inline void activate()
  596. { active(true); }
  597.       //! Add the entry specified by b fullpath to this node. If b w is not c NULL then that widget is the entry and the label (as specified in b fullPath) is visible depending on the value of b showLabel. Note that the widget is destroyed by the tree/node on clear() or the destructor
  598.       /*! return a pointer to the Node of the added entry or NULL if the add failed */
  599.       inline Node* add( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true )
  600. { return( modify( fullpath, ADD, tree->rdata, w, showLabel ) ); }
  601.       //! Convenience function that is the same as add() except it appends a '/' to b fullpath if one does not exist
  602.       Node* add_branch( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true );
  603.       //! Convenience function that is the same as add() except it removes any '/' at the end of b fullpath
  604.       Node* add_leaf( const char* fullpath, Fl_Widget *w = 0, bool showLabel = true );
  605.       //! Set whether a branch node is always open (only for branch nodes). Default is c false
  606.       inline void always_open( bool b )
  607. { if( b ) open(true); SET(ALWAYS_OPEN,b); tree->rdata.forceResize = true; }
  608.       //! Get whether a branch node is always open (only for branches)
  609.       inline bool always_open() const
  610. { return CHECK(ALWAYS_OPEN); }
  611.       //! Set the branch icons to use for this node (only for branch nodes)
  612.       void branch_icons( Fl_Image *closed, Fl_Image *open );
  613.       //! Convenience routine to set both branch icons at once
  614.       inline void branch_icon( Fl_Image *icon )
  615. { branch_icons( icon, icon ); }
  616.       //! return child b i of this node. Bounds checking is performed and NULL is returned if the child cannot be found
  617.       Node* child( int i ) const;
  618.       //! return the number of child nodes beneath this node
  619.       inline int children() const
  620. { return _children.size(); }
  621.       //! Clear all child entries from this node (does not change the entry of this node)
  622.       void clear();
  623.       //! Close this node (only for branches)
  624.       inline void close()
  625. { open( false ); }
  626.       //! Is this node closed? (only for branches)
  627.       inline bool closed()
  628. { return !open(); }
  629.        //! Set the collapse icons to use for this node (only for branch nodes)
  630.       /*! note if a NULL icon is passed, the default plus/minus icons are chosen */
  631.       void collapse_icons( Fl_Image *closed, Fl_Image *open );
  632.       //! Deactivate this node
  633.       inline void deactivate()
  634. { active(false); }
  635.       //! Get the depth of this node in the tree
  636.       unsigned short depth() const;
  637.       //! Do the tree browser callback. b reason should be one of FLU_HILIGHTED, FLU_UNHILIGHTED, FLU_SELECTED, FLU_UNSELECTED, FLU_OPENED, FLU_CLOSED, FLU_DOUBLE_CLICK, FLU_WIDGET_CALLBACK
  638.       void do_callback( int reason );
  639.       //! Set whether this node can receive new nodes as a result of dragging-and-dropping (only for branch nodes). Default is c true
  640.       inline void droppable( bool b )
  641. { SET(DROPPABLE,b); }
  642.       //! Get whether this node can receive new nodes as a result of dragging-and-dropping (only for branch nodes).
  643.       inline bool droppable()
  644. { return CHECK(DROPPABLE); }
  645.       //! Set whether to force the size of the widget to expand to fill the visible width of the browser. Default is c false
  646.       inline void expand_to_width( bool b )
  647. { SET(EXPAND_TO_WIDTH,b); tree->rdata.forceResize = true; }
  648.       //! Get whether to force the size of the widget to expand to fill the visible width of the browser
  649.       inline bool expand_to_width() const
  650. { return CHECK(EXPAND_TO_WIDTH); }
  651.       //! Find the entry identified by b fullpath
  652.       /*! return a pointer to the Node of the found entry, or NULL if no matching entry was found */
  653.       inline Node* find( const char *fullpath )
  654. { return( modify( fullpath, FIND, tree->rdata ) ); }
  655.       //! Find the entry identified by unique id b id
  656.       /*! return a pointer to the Node of the found entry, or NULL if no matching entry was found */
  657.       Node* find( unsigned int id );
  658.       //! Find the entry containing the widget b w
  659.       /*! return a pointer to the Node of the found entry, or NULL if no matching entry was found */
  660.       Node* find( Fl_Widget *w );
  661.       //! Search for Node b n
  662.       /*! return a pointer to b n if it is found, or NULL if it is not present */
  663.       inline Node* find( Node *n )
  664. { if( !n ) return NULL; else return find( n->id() ); }
  665.       //! return the full path of this node
  666.       /*! note the returned value is only valid until the next time find_path() is called */
  667.       inline const char* find_path()
  668. { return tree->find_path( this ); }
  669.       //! return the first node in this hierarchy (i.e. this node)
  670.       Node* first();
  671.       //! return the first branch encountered in a depth-first traversal (or this node if it is a branch). NULL means there are no branches
  672.       Node* first_branch();
  673.       //! return the first leaf encountered in a depth-first traversal (or this node if it is a leaf). NULL means there are no leaves
  674.       Node* first_leaf();
  675.       //! Get the unique ID of this node
  676.       inline unsigned int id() const
  677. { return _id; }
  678.       //! Get the index this node is (as a child) in its parent's list
  679.       /*! return -1 if this node has no parent, else its index in its parent's list of children */
  680.       int index() const;
  681.       //! Is node b n an ancestor of this node?
  682.       bool is_ancestor( Node* n );
  683.       //! Is this node a branch node?
  684.       bool is_branch() const;
  685.       //! Is node b n a descendent of this node?
  686.       bool is_descendent( Node* n );
  687.       //! Is this node a leaf node?
  688.       bool is_leaf() const;
  689.       //! Is this node the root node?
  690.       inline bool is_root() const
  691. { return( _parent == 0 ); }
  692.       //! Set the label for this node. Note that setting the label may invalidate a sorted tree. Fix by calling Flu_Tree_Browser::sort() 
  693.       inline void label( const char *l )
  694. { text = l; tree->redraw(); }
  695.       //! Get the label for this node
  696.       inline const char* label() const
  697. { return text.c_str(); }
  698.       //! Set the label color for this node
  699.       inline void label_color( Fl_Color c )
  700. { textColor = c; }
  701.       //! Get the label color for this node
  702.       inline Fl_Color label_color() const
  703. { return textColor; }
  704.       //! Set the label font for this node
  705.       inline void label_font( Fl_Font f )
  706. { textFont = f; tree->rdata.forceResize = true; }
  707.       //! Get the label font for this node
  708.       inline Fl_Font label_font() const
  709. { return textFont; }
  710.       //! Set the label size for this node
  711.       inline void label_size( unsigned char s )
  712. { textSize = s; tree->rdata.forceResize = true; }
  713.       //! Get the label size for this node
  714.       inline unsigned char label_size() const
  715. { return textSize; }
  716.       //! Is the label for this node visible?
  717.       inline bool label_visible() const
  718. { return CHECK(SHOW_LABEL); }
  719.       //! Set whether the label for this node is visible
  720.       inline void label_visible( bool b )
  721. { SET(SHOW_LABEL,b); tree->rdata.forceResize = true; }
  722.       //! return the last node in this hierarchy
  723.       Node* last();
  724.       //! return the last branch encountered in a depth-first traversal (or this node if it is a branch and has no children). NULL means there are no branches
  725.       Node* last_branch();
  726.       //! return the last leaf encountered in a depth-first traversal (or this node if it is a leaf). NULL means there are no leaves
  727.       Node* last_leaf();
  728.       //! Set the leaf icon to use for this node (only for leaf nodes)
  729.       void leaf_icon( Fl_Image *icon );
  730.       //! Set whether this node can be moved (either via move() or by dragging with the mouse). Default is c true
  731.       inline void movable( bool b )
  732. { SET(MOVABLE,b); }
  733.       //! Get whether this node can be moved (either via move() or by dragging with the mouse)
  734.       inline bool movable()
  735. { return CHECK(MOVABLE); }
  736.       //! Move this node to a position before, after, or inside node b n
  737.       /*! param where can be one of MOVE_BEFORE, MOVE_AFTER, or MOVE_INSIDE
  738. return c true if the move was successful, or c false if the move is not allowed
  739.        */
  740.       inline bool move( int where, Node* n )
  741. { return( move( this, where, n ) ); }
  742.       //! Move node b n1 to a position before, after, or inside node b n2
  743.       /*! param where can be one of MOVE_BEFORE, MOVE_AFTER, or MOVE_INSIDE
  744. return c true if the move was successful, or c false if the move is not allowed
  745.        */
  746.       static bool move( Node* n1, int where, Node* n2 );
  747.       //! return the next node (after this node) in this hierarchy (depth-first traversal)
  748.       Node* next();
  749.       //! return the next branch (after this node) encountered in a depth-first traversal. NULL means there are no more branches
  750.       Node* next_branch();
  751.       //! return the next leaf (after this node) encountered in a depth-first traversal. NULL means there are no more leaves
  752.       Node* next_leaf();
  753.       //! return the next sibling (after this node) encountered in a depth-first traversal. NULL means this node is the last child w.r.t. its parent
  754.       Node* next_sibling();
  755.       //! Is this node currently open? (only for branch nodes)
  756.       inline bool open() const
  757. { return( !CHECK(COLLAPSED) || tree->rdata.allBranchesAlwaysOpen ); }
  758.       //! Open or close this node (only for branch nodes)
  759.       void open( bool b );
  760.       //! Get the node that is the parent of this node, or NULL if there is no parent
  761.       inline Node* parent() const
  762. { return _parent; }
  763.       //! return the previous node (before this node) in this hierarchy (depth-first traversal)
  764.       Node* previous();
  765.       //! return the previous branch (before this node) encountered in a depth-first traversal. NULL means there are no more branches
  766.       Node* previous_branch();
  767.       //! return the previous leaf (before this node) encountered in a depth-first traversal. NULL means there are no more leaves
  768.       Node* previous_leaf();
  769.       //! return the previous sibling (before this node) encountered in a depth-first traversal. NULL means this node is the first child w.r.t. its parent
  770.       Node* previous_sibling();
  771.       //! Print this node and its children to stdout
  772.       void print( int spaces = 0 );
  773.       //! Remove the entry identified by path b fullpath from this node
  774.       /*! return the unique id of the removed entry, or c 0 if no matching entry was found */
  775.       inline unsigned int remove( const char *fullpath )
  776. { return( reinterpret_cast<long>(modify( fullpath, REMOVE, tree->rdata )) ); }
  777.       //! Remove the entry identified by unique id b id from this node
  778.       /*! return the unique id of the removed entry, or c 0 if no matching entry was found */
  779.       unsigned int remove( unsigned int id );
  780.       //! Remove the entry containing the widget b w from this node. Note that the widget is automatically destroyed
  781.       /*! return the unique id of the removed entry, or c 0 if no matching entry was found */
  782.       unsigned int remove( Fl_Widget *w );
  783.       //! Remove Node b n
  784.       /*! return the id of b n on successful removal, or c 0 if b n is present */
  785.       inline unsigned int remove( Node* n )
  786. { if( !n ) return 0; else return remove( n->id() ); }
  787.       //! Select this entry and all child entries
  788.       void select_all();
  789.       //! Is this node currently selected?
  790.       inline bool selected() const
  791. { return CHECK(SELECTED); }
  792.       //! Select or unselect this node
  793.       void select( bool b );
  794.       //! Sort this node's children according to Flu_Tree_Browser::insertion_mode()
  795.       inline void sort_children()
  796. { sort(); }
  797.       //! Unselect this entry and all child entries (except for Node b except )
  798.       void unselect_all( Node* except = NULL );
  799.       //! Get the user-specific data stored in this node
  800.       inline void* user_data()
  801. { return userData; }
  802.       //! Set the user-specific data stored in this node
  803.       inline void user_data( void *d )
  804. { userData = d; }
  805.       //! Get the widget in this node, or NULL if there is no widget. Note that the widget is destroyed by the tree/node on clear() or the destructor
  806.       inline Fl_Widget* widget() const
  807. { return( _widget ? _widget->w : NULL ); }
  808.       //! Set the widget in this node. Note that the widget is destroyed by the tree/node on clear() or the destructor
  809.       void widget( Fl_Widget *w );
  810.     protected:
  811.       friend class Flu_Tree_Browser;
  812.       friend class NodeList;
  813.       // Root node constructor
  814.       Node( const char *lbl = 0 );
  815.       // Non-root constructor
  816.       Node( bool l, const char* n, Node *p, RData &rdata, Fl_Widget *w, bool showLabel );
  817.       ~Node();
  818.       // add/remove/find/get
  819.       Node* modify( const char* path, int what, RData &rdata, Fl_Widget *w = 0, bool showLabel = true );
  820.       void initType();
  821.       void sort();
  822.       void determineVisibility( bool parentVisible = true );
  823.       static bool isMoveValid( Node* &n1, int &where, Node* &n2 );
  824.       // handle/draw/measure/count
  825.       int recurse( RData &rdata, int type, int event = 0 );
  826.       void draw( RData &rdata, bool measure );
  827.       // recursively finding the full path of the node identified by id
  828.       bool findPath( unsigned int id, RData &rdata );
  829.       // recursively finding the full path of the node containing w
  830.       bool findPath( Fl_Widget *w, RData &rdata );
  831.       class NCBI_GUIWIDGETS_FLU_EXPORT WidgetInfo
  832. {
  833. public:
  834.   Fl_Widget *w;
  835.   int defaultW;  // the initial width of the widget
  836.   void (*CB)(Fl_Widget*,void*);
  837.   void *CBData;
  838. };
  839.       unsigned int _id; // the unique id of this node
  840.       unsigned short flags;
  841.       NodeList _children;
  842.       Node *_parent;
  843.       Flu_Tree_Browser *tree;
  844.       FluSimpleString text;
  845.       WidgetInfo *_widget;  // memory overhead deferred to WidgetInfo. present only if widget is
  846.       void *userData;
  847.       int totalChildH; // needed for animation
  848.       Fl_Image *cIcon[2], *bIcon[2], *lIcon;
  849.       Fl_Color textColor;
  850.       Fl_Font textFont;
  851.       unsigned char textSize;  // the font size of the entry label text
  852.       unsigned short textW, textH;  // how big the entry label actually is (stored within the node for performance reasons)
  853.       int currentY; // needed for animation
  854.       unsigned short currentH;
  855.       inline static void _widgetCB( Fl_Widget* w, void* arg )
  856. { ((Node*)arg)->widgetCB(); }
  857.       void widgetCB();
  858.      };
  859.  protected:
  860.   inline static void _scrollCB( Fl_Widget* w, void* arg )
  861.     { ((Flu_Tree_Browser*)arg)->redraw(); }
  862.   inline static void _timerRedrawCB( void *arg )
  863.     { ((Flu_Tree_Browser*)arg)->timerRedrawCB(); }
  864.   void timerRedrawCB();
  865.   inline static void _timerScrollCB( void *arg )
  866.     { ((Flu_Tree_Browser*)arg)->timerScrollCB(); }
  867.   void timerScrollCB();
  868.   void on_dnd_leave();
  869.   void on_dnd_release();
  870.   bool on_dnd_drag( int X, int Y );
  871.   void on_dnd_drop( const Flu_DND_Event *e );
  872.   /* override of Fl_Double_Window::draw() */
  873.   void draw();
  874.   Fl_Group *scrollBox;
  875.   Fl_Scrollbar *scrollH, *scrollV;
  876.   Fl_Group *_box;
  877.   Node root;
  878.   RData rdata;
  879.   int lastEvent;
  880.   float autoScrollX, autoScrollY;
  881.   bool scrolledTimerOn;
  882. };
  883. #endif