VTree RFC




Hi,

I typed in a proposed interface for 'GtkVTree' which I've talked about
before - this allows you to display trees which change frequently or trees
which are very large (even infinite) in an efficient way, because the
widget obtains its data from your application rather than storing its own
copy. It also saves a significant amount of memory and makes it easier to
keep your GUI synced with your data structures.

There is more user flexibility with this widget, you can write custom
cell-drawing routines, and do things like display a vertical "slice" of
the tree (i.e. as you expand nodes the closer-to-root nodes disappear
keeping the visible tree depth constant).

Anyway, comments welcome.

Havoc


#ifndef __GTK_VTREE_H__
#define __GTK_VTREE_H__


#include <gdk/gdk.h>
#include <gtk/gtkwidget.h>

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

#define GTK_TYPE_VTREE			(gtk_vtree_get_type ())
#define GTK_VTREE(obj)			(GTK_CHECK_CAST ((obj), GTK_TYPE_VTREE, GtkVTree))
#define GTK_VTREE_CLASS(klass)		(GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_VTREE, GtkVTreeClass))
#define GTK_IS_VTREE(obj)		(GTK_CHECK_TYPE ((obj), GTK_TYPE_VTREE))
#define GTK_IS_VTREE_CLASS(klass)	(GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_VTREE))


typedef struct _GtkVTree       GtkVTree;
typedef struct _GtkVTreeClass  GtkVTreeClass;

struct _GtkVTree
{
  GtkWidget widget;

  /* fill this in */
};

struct _GtkVTreeClass
{
  GtkWidgetClass        parent_class;
  
  /* fill this in, will be basically the same as clist/ctree */
};

typedef enum 
{
  GTK_VTREE_EXPANDED,
  GTK_VTREE_COLLAPSED,
  GTK_VTREE_HIDDEN
} GtkVTreeNodeState;

typedef struct _GtkVTreeNodeInfo GtkVTreeNodeInfo;

struct _GtkVTreeNodeInfo 
{
  /* Is this node expanded, collapsed, or "hidden" (should not 
   * be displayed right now)
   * A node which has no children should always report "collapsed"
   */

  GtkVTreeNodeState state;
  
  /* Can the node be expanded? (i.e. should an expander be displayed?)  
   */
  
  guint expandable : 1;
};

/* How to render each cell */

typedef enum 
{
  GTK_VTREE_CELL_BLANK,   /* Blank cell */
  GTK_VTREE_CELL_PIXTEXT, /* Pixmap and/or text, like CTree */
  GTK_VTREE_CELL_TOGGLE,  /* Toggle button */
  GTK_VTREE_CELL_RADIO,   /* Radio button */
  GTK_VTREE_CELL_USER     /* Custom cell drawn by user code */
  /*  GTK_VTREE_CELL_ENTRY,*/   /* Editable text - disabled pending GtkEntry backend abstraction */

} GtkVTreeCellType;

/* To use the GtkVTree, you must create a GtkVTreeTable. Basically
 *  this is a set of functions to be used to access your tree
 *  data. (The purpose of GtkVTree is to avoid data copies and
 *  increase flexibility - it is thus more annoying to use than
 *  GtkCTree.) The "gpointer node" arguments and gpointer return 
 *  values represent a data type provided by you and opaque to 
 *  GtkVTree, which may well be GNode but does not have to be.
 */

typedef struct _GtkVTreeVTable GtkVTreeVTable;

struct _GtkVTreeVTable 
{
  /* Should fill in GtkVTreeNodeInfo with info for node; must be
   * constant-time fast 
   */
  
  void (* vtree_node_info) (GtkVTree* vtree,
                            gpointer node, GtkVTreeNodeInfo* info);

  /* GtkVTree will use these tree-walking functions to traverse and
   * render the tree. It will traverse all nodes which are "visible,"
   * but little more; this means each node which is not hidden, whose
   * parent nodes are expanded.  Of course the first node has to be 
   * traversed even if it's hidden.
   */

  /* Fetch the "top left" node, i.e. the first node in the top level
   * of the tree. Your tree is not required to have a single root.  
   * NULL means the tree is empty.
   */

  gpointer (* vtree_node_first)       (GtkVTree* vtree);

  /* Start of list of this node's children, NULL if none */
  gpointer (* vtree_node_first_child) (GtkVTree* vtree, gpointer node);
  
  /* Next sibling of node, NULL if none */
  gpointer (* vtree_node_next)        (GtkVTree* vtree, gpointer node);

  /* These two functions are optional; if they are non-NULL, the VTree
   * uses them to find the current size of the tree and get the
   * on-screen nodes instead of using the above functions (though the
   * above are still required).  Basically this permits you to use an
   * array instead of a tree structure for efficiency, if your data is
   * really a list and not a tree. You can still use them with a tree,
   * say if you are maintaining this info anyway. If they are not constant
   * time operations, do NOT implement them!
   */

  /* Return number of rows in the tree's current state, considering
   * expanded/contracted state of each node. 
   */
  guint    (* vtree_n_rows)           (GtkVTree* vtree); 

  /* Return visible node number n, or NULL if none */
  gpointer (* vtree_nth_node)         (GtkVTree* vtree, guint n);

  /* Fill array of cell types; will be called only if the node is 
   * being displayed. Array size matches number of tree columns.
   */
  void     (* vtree_node_celltypes)   (GtkVTree* vtree, 
                                       gpointer node, 
                                       GtkVTreeCellType* fillme);
  
  /* Any of the following can be NULL if you don't have cells 
   * of the matching type 
   */

  /* Called for radio and toggle cells */
  gboolean (* vtree_node_get_state)   (GtkVTree* vtree,
                                       gpointer node, guint column);
  void     (* vtree_node_set_state)   (GtkVTree* vtree,
                                       gpointer node, guint column, 
                                       gboolean state);

  /* Called for pixtext cells */
  void     (* vtree_node_get_pixtext) (GtkVTree* vtree,
                                       gpointer node, guint column,
                                       GdkPixmap** pixmap, 
                                       GdkBitmap** mask,
                                       const gchar** text);

  /* Called for user-drawn cells */
  void     (* vtree_node_draw)        (GtkVTree* vtree,
                                       gpointer node, 
                                       guint column,
                                       GtkVTree* vtree, 
                                       GdkDrawable* drawable, 
                                       GdkRectangle* rect);

  /* These can be NULL if you don't show the expanders.
   * The user must maintain expanded/collapsed state of 
   * tree nodes.
   */
  void     (* vtree_node_expand)      (GtkVTree* vtree,
                                       gpointer node);

  void     (* vtree_node_collapse)    (GtkVTree* vtree,
                                       gpointer node);
  
  /* The user does not have to maintain the current selection,
   * but if non-NULL these hooks will be called when it 
   * changes
   */
  void     (* vtree_node_select)      (GtkVTree* vtree,
                                       gpointer node);

  void     (* vtree_node_unselect)    (GtkVTree* vtree,
                                       gpointer node);
  
};

GtkType        gtk_vtree_get_type       (void);

/* Defaults to hidden titles */
GtkWidget*     gtk_vtree_new            (GtkVTreeVTable* table, 
                                         guint ncols);

/* Defaults to visible titles */
GtkWidget*     gtk_vtree_new_with_titles(GtkVTreeVTable* table,
                                         guint ncols, 
                                         const gchar* titles[]);

/* Set number of columns; if titles is NULL, then titles are not
 * shown. 
 */
void           gtk_vtree_set_columns    (GtkVTree* vtree,
                                         guint ncols,
                                         const gchar* titles[]);

/* Set which column should contain the expanders; by default, no 
 * column does, and the user can't expand/contract rows.
 * Set to -1 for no expanders.
 */
void           gtk_vtree_set_tree_column(GtkVTree* vtree, gint column);


/* The following two functions queue a one-shot idle function
 * rather than acting immediately.
 */

/* Redisplay the rows currently on-screen, since their content
 * has changed.
 */
void           gtk_vtree_data_changed   (GtkVTree* vtree);

/* Rescan the tree and redisplay, since nodes have been added or 
 * removed or expanded/collapsed.
 */
void           gtk_vtree_structure_changed (GtkVTree* vtree);

/* Will eventually have most of the CTree functionality, when
 * applicable.  Row "styles" won't be available, since the user can
 * always draw cells themselves. Probably also won't fool with 
 * line and expander styles.
 */

#ifdef __cplusplus
}
#endif /* __cplusplus */


#endif /* __GTK_VTREE_H__ *




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]