2000-06-08 Chris Toshok <toshok@helixcode.com> * e-tree-gnode.c, e-tree-gnode.h: New files. A tree model using a GNode structure to store it's info. * e-tree-model.c, e-tree-model.h: New files. A proxy model sitting between a table model and the real tree model (of which ETreeGNode is an example). * e-cell-tree.c, e-cell-tree.h: New files. A cell renderer capable of wrapping up a subcell and drawing the tree controls for expanding/collapsing trees. * tree-expanded.xpm, tree-unexpanded.xpm: New files. the standard + and - icons. * e-tree-example-1.c: New file, giving a (pretty poor :) example of using ETreeGNode. * Makefile.am: at the tree stuff to the build, and build tree-example-1. * .cvsignore: ignore tree-example-1. svn path=/trunk/; revision=3483
211 lines
4.4 KiB
C
211 lines
4.4 KiB
C
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
|
/*
|
|
* e-tree-gnode.c: a Tree Model that reflects a GNode structure visually.
|
|
*
|
|
* Author:
|
|
* Chris Toshok (toshok@helixcode.com)
|
|
*
|
|
* (C) 2000 Helix Code, Inc.
|
|
*/
|
|
#include <config.h>
|
|
#include <gtk/gtksignal.h>
|
|
#include "e-util/e-util.h"
|
|
#include "e-tree-gnode.h"
|
|
|
|
#define PARENT_TYPE E_TREE_MODEL_TYPE
|
|
|
|
static ETreePath *
|
|
gnode_get_root (ETreeModel *etm)
|
|
{
|
|
ETreeGNode *etg = E_TREE_GNODE (etm);
|
|
ETreePath *path = NULL;
|
|
|
|
path = g_list_append(path, etg->root);
|
|
|
|
return path;
|
|
}
|
|
|
|
static ETreePath *
|
|
gnode_get_prev (ETreeModel *etm, ETreePath *node)
|
|
{
|
|
ETreePath *prev_path;
|
|
|
|
GNode *gnode;
|
|
GNode *prev_sibling;
|
|
|
|
g_return_val_if_fail (node && node->data, NULL);
|
|
|
|
gnode = (GNode*)node->data;
|
|
prev_sibling = g_node_prev_sibling(gnode);
|
|
|
|
if (!prev_sibling)
|
|
return NULL;
|
|
|
|
prev_path = g_list_copy (node->next);
|
|
prev_path = g_list_prepend (prev_path, prev_sibling);
|
|
return prev_path;
|
|
}
|
|
|
|
static ETreePath *
|
|
gnode_get_next (ETreeModel *etm, ETreePath *node)
|
|
{
|
|
ETreePath *next_path;
|
|
GNode *gnode;
|
|
GNode *next_sibling;
|
|
|
|
g_return_val_if_fail (node && node->data, NULL);
|
|
|
|
gnode = (GNode*)node->data;
|
|
next_sibling = g_node_next_sibling(gnode);
|
|
|
|
if (!next_sibling)
|
|
return NULL;
|
|
|
|
next_path = g_list_copy (node->next);
|
|
next_path = g_list_prepend (next_path, next_sibling);
|
|
return next_path;
|
|
}
|
|
|
|
static void *
|
|
gnode_value_at (ETreeModel *etm, ETreePath *node, int col)
|
|
{
|
|
ETreeGNode *etg = E_TREE_GNODE (etm);
|
|
GNode *gnode;
|
|
|
|
g_return_val_if_fail (node && node->data, NULL);
|
|
|
|
gnode = (GNode*)node->data;
|
|
|
|
return etg->value_at (etm, gnode, col, etg->data);
|
|
}
|
|
|
|
static void
|
|
gnode_set_value_at (ETreeModel *etm, ETreePath *node, int col, const void *val)
|
|
{
|
|
ETreeGNode *etg = E_TREE_GNODE (etm);
|
|
GNode *gnode;
|
|
|
|
g_return_if_fail (node && node->data);
|
|
|
|
gnode = (GNode*)node->data;
|
|
|
|
/* XXX */
|
|
}
|
|
|
|
static gboolean
|
|
gnode_is_editable (ETreeModel *etm, ETreePath *node, int col)
|
|
{
|
|
ETreeGNode *etg = E_TREE_GNODE (etm);
|
|
GNode *gnode;
|
|
|
|
g_return_val_if_fail (node && node->data, FALSE);
|
|
|
|
gnode = (GNode*)node->data;
|
|
|
|
/* XXX */
|
|
return FALSE;
|
|
}
|
|
|
|
static guint
|
|
gnode_get_children (ETreeModel *etm, ETreePath *node, ETreePath ***paths)
|
|
{
|
|
ETreeGNode *etg = E_TREE_GNODE (etm);
|
|
GNode *gnode;
|
|
guint n_children;
|
|
|
|
g_return_val_if_fail (node && node->data, 0);
|
|
|
|
gnode = (GNode*)node->data;
|
|
|
|
n_children = g_node_n_children (gnode);
|
|
|
|
if (paths)
|
|
{
|
|
int i;
|
|
(*paths) = g_malloc (sizeof (ETreePath*) * n_children);
|
|
for (i = 0; i < n_children; i ++) {
|
|
(*paths)[i] = g_list_copy (node);
|
|
(*paths)[i] = g_list_prepend ((*paths)[i], g_node_nth_child (gnode, i));
|
|
}
|
|
}
|
|
|
|
return n_children;
|
|
}
|
|
|
|
static void
|
|
gnode_release_paths (ETreeModel *etm, ETreePath **paths, guint num_paths)
|
|
{
|
|
guint i;
|
|
g_return_if_fail (paths);
|
|
|
|
for (i = 0; i < num_paths; i ++)
|
|
g_list_free (paths[i]);
|
|
g_free (paths);
|
|
}
|
|
|
|
static gboolean
|
|
gnode_is_expanded (ETreeModel *etm, ETreePath *node)
|
|
{
|
|
ETreeGNode *etg = E_TREE_GNODE (etm);
|
|
GNode *gnode;
|
|
|
|
g_return_val_if_fail (node && node->data, FALSE);
|
|
|
|
gnode = (GNode*)node->data;
|
|
|
|
return (gboolean)gnode->data;
|
|
}
|
|
|
|
static void
|
|
gnode_set_expanded (ETreeModel *etm, ETreePath *node, gboolean expanded)
|
|
{
|
|
ETreeGNode *etg = E_TREE_GNODE (etm);
|
|
GNode *gnode;
|
|
int num_descendents;
|
|
|
|
g_return_if_fail (node && node->data);
|
|
|
|
gnode = (GNode*)node->data;
|
|
|
|
/* XXX */
|
|
gnode->data = (gpointer)expanded;
|
|
|
|
e_table_model_changed (E_TABLE_MODEL(etm));
|
|
}
|
|
|
|
static void
|
|
e_tree_gnode_class_init (GtkObjectClass *object_class)
|
|
{
|
|
ETreeModelClass *model_class = (ETreeModelClass *) object_class;
|
|
|
|
model_class->get_root = gnode_get_root;
|
|
model_class->get_next = gnode_get_next;
|
|
model_class->get_prev = gnode_get_prev;
|
|
model_class->value_at = gnode_value_at;
|
|
model_class->set_value_at = gnode_set_value_at;
|
|
model_class->is_editable = gnode_is_editable;
|
|
model_class->get_children = gnode_get_children;
|
|
model_class->release_paths = gnode_release_paths;
|
|
model_class->is_expanded = gnode_is_expanded;
|
|
model_class->set_expanded = gnode_set_expanded;
|
|
}
|
|
|
|
E_MAKE_TYPE(e_tree_gnode, "ETreeGNode", ETreeGNode, e_tree_gnode_class_init, NULL, PARENT_TYPE)
|
|
|
|
ETreeModel *
|
|
e_tree_gnode_new (GNode *root_node,
|
|
ETreeGNodeValueAtFn value_at,
|
|
void *data)
|
|
{
|
|
ETreeGNode *etg;
|
|
|
|
etg = gtk_type_new (e_tree_gnode_get_type ());
|
|
|
|
etg->root = root_node;
|
|
|
|
etg->value_at = value_at;
|
|
etg->data = data;
|
|
|
|
return (ETreeModel*)etg;
|
|
}
|