Tree widget implementation by Bolliet Jerome.
There is also another tree widget implementation by AOSASA Shigeru <aozasa@sakuranet.or.jp>: ftp://ftp.gimp.org/pub/gtk/contrib/gtk-shige-971216-0.tar.gz -Shawn
This commit is contained in:
@ -8,3 +8,4 @@ testgtk
|
||||
testinput
|
||||
testselection
|
||||
simple
|
||||
testtree
|
||||
|
@ -193,11 +193,15 @@ EXTRA_DIST = \
|
||||
marble.xpm \
|
||||
3DRings.xpm \
|
||||
FilesQueue.xpm \
|
||||
Modeller.xpm
|
||||
Modeller.xpm \
|
||||
tree_plus.xpm \
|
||||
tree_minus.xpm \
|
||||
tree_plus.xbm \
|
||||
tree_minus.xbm
|
||||
|
||||
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/glib @x_cflags@
|
||||
|
||||
noinst_PROGRAMS = testgtk testinput testselection simple
|
||||
noinst_PROGRAMS = testgtk testinput testselection simple testtree
|
||||
testgtk_LDADD = \
|
||||
libgtk.la \
|
||||
$(top_builddir)/gdk/libgdk.la \
|
||||
@ -230,6 +234,14 @@ simple_LDADD = \
|
||||
$(top_builddir)/glib/libglib.la \
|
||||
-lm
|
||||
|
||||
testtree_LDADD = \
|
||||
libgtk.la \
|
||||
$(top_builddir)/gdk/libgdk.la \
|
||||
@x_ldflags@ \
|
||||
@x_libs@ \
|
||||
$(top_builddir)/glib/libglib.la \
|
||||
-lm
|
||||
|
||||
DEPS = \
|
||||
$(top_builddir)/gtk/libgtk.la \
|
||||
$(top_builddir)/gdk/libgdk.la \
|
||||
@ -239,6 +251,7 @@ testgtk_DEPENDENCIES = $(DEPS)
|
||||
testinput_DEPENDENCIES = $(DEPS)
|
||||
testselection_DEPENDENCIES = $(DEPS)
|
||||
simple_DEPENDENCIES = $(DEPS)
|
||||
testtree_DEPENDENCIES = $(DEPS)
|
||||
|
||||
.PHONY: files
|
||||
|
||||
|
@ -259,11 +259,15 @@ EXTRA_DIST = \
|
||||
marble.xpm \
|
||||
3DRings.xpm \
|
||||
FilesQueue.xpm \
|
||||
Modeller.xpm
|
||||
Modeller.xpm \
|
||||
tree_plus.xpm \
|
||||
tree_minus.xpm \
|
||||
tree_plus.xbm \
|
||||
tree_minus.xbm
|
||||
|
||||
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/glib @x_cflags@
|
||||
|
||||
noinst_PROGRAMS = testgtk testinput testselection simple
|
||||
noinst_PROGRAMS = testgtk testinput testselection simple testtree
|
||||
testgtk_LDADD = \
|
||||
libgtk.la \
|
||||
$(top_builddir)/gdk/libgdk.la \
|
||||
@ -296,6 +300,14 @@ simple_LDADD = \
|
||||
$(top_builddir)/glib/libglib.la \
|
||||
-lm
|
||||
|
||||
testtree_LDADD = \
|
||||
libgtk.la \
|
||||
$(top_builddir)/gdk/libgdk.la \
|
||||
@x_ldflags@ \
|
||||
@x_libs@ \
|
||||
$(top_builddir)/glib/libglib.la \
|
||||
-lm
|
||||
|
||||
DEPS = \
|
||||
$(top_builddir)/gtk/libgtk.la \
|
||||
$(top_builddir)/gdk/libgdk.la \
|
||||
@ -305,6 +317,7 @@ testgtk_DEPENDENCIES = $(DEPS)
|
||||
testinput_DEPENDENCIES = $(DEPS)
|
||||
testselection_DEPENDENCIES = $(DEPS)
|
||||
simple_DEPENDENCIES = $(DEPS)
|
||||
testtree_DEPENDENCIES = $(DEPS)
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = ../config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
@ -352,6 +365,9 @@ testselection_LDFLAGS =
|
||||
simple_SOURCES = simple.c
|
||||
simple_OBJECTS = simple.o
|
||||
simple_LDFLAGS =
|
||||
testtree_SOURCES = testtree.c
|
||||
testtree_OBJECTS = testtree.o
|
||||
testtree_LDFLAGS =
|
||||
CFLAGS = @CFLAGS@
|
||||
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
|
||||
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
|
||||
@ -363,7 +379,7 @@ DIST_COMMON = Makefile.am Makefile.in
|
||||
|
||||
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
||||
TAR = gtar
|
||||
TAR = tar
|
||||
GZIP = --best
|
||||
DEP_FILES = .deps/fnmatch.P .deps/gtkaccelerator.P \
|
||||
.deps/gtkadjustment.P .deps/gtkalignment.P .deps/gtkarrow.P \
|
||||
@ -391,9 +407,9 @@ DEP_FILES = .deps/fnmatch.P .deps/gtkaccelerator.P \
|
||||
.deps/gtkviewport.P .deps/gtkvpaned.P .deps/gtkvruler.P \
|
||||
.deps/gtkvscale.P .deps/gtkvscrollbar.P .deps/gtkvseparator.P \
|
||||
.deps/gtkwidget.P .deps/gtkwindow.P .deps/simple.P .deps/testgtk.P \
|
||||
.deps/testinput.P .deps/testselection.P
|
||||
SOURCES = $(libgtk_la_SOURCES) testgtk.c testinput.c testselection.c simple.c
|
||||
OBJECTS = $(libgtk_la_OBJECTS) testgtk.o testinput.o testselection.o simple.o
|
||||
.deps/testinput.P .deps/testselection.P .deps/testtree.P
|
||||
SOURCES = $(libgtk_la_SOURCES) testgtk.c testinput.c testselection.c simple.c testtree.c
|
||||
OBJECTS = $(libgtk_la_OBJECTS) testgtk.o testinput.o testselection.o simple.o testtree.o
|
||||
|
||||
default: all
|
||||
|
||||
@ -498,6 +514,10 @@ simple: $(simple_OBJECTS) $(simple_DEPENDENCIES)
|
||||
@rm -f simple
|
||||
$(LINK) $(simple_LDFLAGS) $(simple_OBJECTS) $(simple_LDADD) $(LIBS)
|
||||
|
||||
testtree: $(testtree_OBJECTS) $(testtree_DEPENDENCIES)
|
||||
@rm -f testtree
|
||||
$(LINK) $(testtree_LDFLAGS) $(testtree_OBJECTS) $(testtree_LDADD) $(LIBS)
|
||||
|
||||
install-gtkincludeHEADERS: $(gtkinclude_HEADERS)
|
||||
@$(NORMAL_INSTALL)
|
||||
$(mkinstalldirs) $(gtkincludedir)
|
||||
|
956
gtk/gtktree.c
956
gtk/gtktree.c
@ -16,11 +16,63 @@
|
||||
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#include "gtktree.h"
|
||||
#include "gtktreeitem.h"
|
||||
#include "gtkmain.h"
|
||||
#include "gtksignal.h"
|
||||
#include "gtklist.h"
|
||||
|
||||
enum {
|
||||
SELECTION_CHANGED,
|
||||
SELECT_CHILD,
|
||||
UNSELECT_CHILD,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
typedef void (*GtkTreeSignal) (GtkObject *object,
|
||||
gpointer arg1,
|
||||
gpointer data);
|
||||
|
||||
|
||||
static void gtk_tree_class_init (GtkTreeClass *klass);
|
||||
static void gtk_tree_init (GtkTree *tree);
|
||||
static void gtk_tree_destroy (GtkObject *object);
|
||||
static void gtk_tree_map (GtkWidget *widget);
|
||||
static void gtk_tree_unmap (GtkWidget *widget);
|
||||
static void gtk_tree_realize (GtkWidget *widget);
|
||||
static void gtk_tree_draw (GtkWidget *widget,
|
||||
GdkRectangle *area);
|
||||
static gint gtk_tree_expose (GtkWidget *widget,
|
||||
GdkEventExpose *event);
|
||||
static gint gtk_tree_motion_notify (GtkWidget *widget,
|
||||
GdkEventMotion *event);
|
||||
static gint gtk_tree_button_press (GtkWidget *widget,
|
||||
GdkEventButton *event);
|
||||
static gint gtk_tree_button_release (GtkWidget *widget,
|
||||
GdkEventButton *event);
|
||||
static void gtk_tree_size_request (GtkWidget *widget,
|
||||
GtkRequisition *requisition);
|
||||
static void gtk_tree_size_allocate (GtkWidget *widget,
|
||||
GtkAllocation *allocation);
|
||||
static void gtk_tree_add (GtkContainer *container,
|
||||
GtkWidget *widget);
|
||||
static void gtk_tree_remove (GtkContainer *container,
|
||||
GtkWidget *widget);
|
||||
static void gtk_tree_foreach (GtkContainer *container,
|
||||
GtkCallback callback,
|
||||
gpointer callback_data);
|
||||
|
||||
static void gtk_real_tree_select_child (GtkTree *tree,
|
||||
GtkWidget *child);
|
||||
static void gtk_real_tree_unselect_child (GtkTree *tree,
|
||||
GtkWidget *child);
|
||||
|
||||
static void gtk_tree_marshal_signal (GtkObject *object,
|
||||
GtkSignalFunc func,
|
||||
gpointer func_data,
|
||||
GtkArg *args);
|
||||
|
||||
static GtkContainerClass *parent_class = NULL;
|
||||
static gint tree_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
guint
|
||||
gtk_tree_get_type ()
|
||||
@ -48,11 +100,75 @@ gtk_tree_get_type ()
|
||||
static void
|
||||
gtk_tree_class_init (GtkTreeClass *class)
|
||||
{
|
||||
GtkObjectClass *object_class;
|
||||
GtkWidgetClass *widget_class;
|
||||
GtkContainerClass *container_class;
|
||||
|
||||
object_class = (GtkObjectClass*) class;
|
||||
widget_class = (GtkWidgetClass*) class;
|
||||
container_class = (GtkContainerClass*) class;
|
||||
|
||||
parent_class = gtk_type_class (gtk_container_get_type ());
|
||||
|
||||
tree_signals[SELECTION_CHANGED] =
|
||||
gtk_signal_new ("selection_changed",
|
||||
GTK_RUN_FIRST,
|
||||
object_class->type,
|
||||
GTK_SIGNAL_OFFSET (GtkTreeClass, selection_changed),
|
||||
gtk_signal_default_marshaller,
|
||||
GTK_TYPE_NONE, 0);
|
||||
tree_signals[SELECT_CHILD] =
|
||||
gtk_signal_new ("select_child",
|
||||
GTK_RUN_FIRST,
|
||||
object_class->type,
|
||||
GTK_SIGNAL_OFFSET (GtkTreeClass, select_child),
|
||||
gtk_tree_marshal_signal,
|
||||
GTK_TYPE_NONE, 1,
|
||||
GTK_TYPE_WIDGET);
|
||||
tree_signals[UNSELECT_CHILD] =
|
||||
gtk_signal_new ("unselect_child",
|
||||
GTK_RUN_FIRST,
|
||||
object_class->type,
|
||||
GTK_SIGNAL_OFFSET (GtkTreeClass, unselect_child),
|
||||
gtk_tree_marshal_signal,
|
||||
GTK_TYPE_NONE, 1,
|
||||
GTK_TYPE_WIDGET);
|
||||
|
||||
gtk_object_class_add_signals (object_class, tree_signals, LAST_SIGNAL);
|
||||
|
||||
object_class->destroy = gtk_tree_destroy;
|
||||
|
||||
widget_class->map = gtk_tree_map;
|
||||
widget_class->unmap = gtk_tree_unmap;
|
||||
widget_class->realize = gtk_tree_realize;
|
||||
widget_class->draw = gtk_tree_draw;
|
||||
widget_class->expose_event = gtk_tree_expose;
|
||||
widget_class->motion_notify_event = gtk_tree_motion_notify;
|
||||
widget_class->button_press_event = gtk_tree_button_press;
|
||||
widget_class->button_release_event = gtk_tree_button_release;
|
||||
widget_class->size_request = gtk_tree_size_request;
|
||||
widget_class->size_allocate = gtk_tree_size_allocate;
|
||||
|
||||
container_class->add = gtk_tree_add;
|
||||
container_class->remove = gtk_tree_remove;
|
||||
container_class->foreach = gtk_tree_foreach;
|
||||
|
||||
class->selection_changed = NULL;
|
||||
class->select_child = gtk_real_tree_select_child;
|
||||
class->unselect_child = gtk_real_tree_unselect_child;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_init (GtkTree *tree)
|
||||
{
|
||||
tree->children = NULL;
|
||||
tree->root_tree = NULL;
|
||||
tree->selection = NULL;
|
||||
tree->tree_owner = NULL;
|
||||
tree->selection_mode = GTK_SELECTION_SINGLE;
|
||||
tree->indent_value = 10;
|
||||
tree->current_indent = 0;
|
||||
tree->view_mode = GTK_TREE_VIEW_LINE;
|
||||
}
|
||||
|
||||
GtkWidget*
|
||||
@ -65,12 +181,22 @@ void
|
||||
gtk_tree_append (GtkTree *tree,
|
||||
GtkWidget *child)
|
||||
{
|
||||
|
||||
g_return_if_fail (tree != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE_ITEM (child));
|
||||
|
||||
gtk_tree_insert(tree, child, -1);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_tree_prepend (GtkTree *tree,
|
||||
GtkWidget *child)
|
||||
{
|
||||
g_return_if_fail (tree != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE_ITEM (child));
|
||||
|
||||
gtk_tree_insert(tree, child, 0);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
@ -78,4 +204,834 @@ gtk_tree_insert (GtkTree *tree,
|
||||
GtkWidget *child,
|
||||
gint position)
|
||||
{
|
||||
gint nchildren;
|
||||
|
||||
g_return_if_fail (tree != NULL || child != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE_ITEM(child));
|
||||
|
||||
/* set parent widget to item */
|
||||
gtk_widget_set_parent (child, GTK_WIDGET (tree));
|
||||
|
||||
if (GTK_WIDGET_VISIBLE (child->parent))
|
||||
{
|
||||
if (GTK_WIDGET_REALIZED (child->parent) &&
|
||||
!GTK_WIDGET_REALIZED (child))
|
||||
gtk_widget_realize (child);
|
||||
|
||||
if (GTK_WIDGET_MAPPED (child->parent) &&
|
||||
!GTK_WIDGET_MAPPED (child))
|
||||
gtk_widget_map (child);
|
||||
}
|
||||
|
||||
nchildren = g_list_length (tree->children);
|
||||
|
||||
if ((position < 0) || (position > nchildren))
|
||||
position = nchildren;
|
||||
|
||||
if (position == nchildren)
|
||||
{
|
||||
tree->children = g_list_append(tree->children, child);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_list_insert(tree->children, child, position);
|
||||
}
|
||||
|
||||
if (GTK_WIDGET_VISIBLE (tree))
|
||||
gtk_widget_queue_resize (GTK_WIDGET (tree));
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_add (GtkContainer *container,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkTree *tree;
|
||||
|
||||
g_return_if_fail (container != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE (container));
|
||||
g_return_if_fail (widget != NULL);
|
||||
|
||||
tree = GTK_TREE (container);
|
||||
|
||||
gtk_widget_set_parent (widget, GTK_WIDGET (container));
|
||||
if (GTK_WIDGET_VISIBLE (widget->parent))
|
||||
{
|
||||
if (GTK_WIDGET_REALIZED (widget->parent) &&
|
||||
!GTK_WIDGET_REALIZED (widget))
|
||||
gtk_widget_realize (widget);
|
||||
|
||||
if (GTK_WIDGET_MAPPED (widget->parent) &&
|
||||
!GTK_WIDGET_MAPPED (widget))
|
||||
gtk_widget_map (widget);
|
||||
}
|
||||
|
||||
tree->children = g_list_append (tree->children, widget);
|
||||
|
||||
#ifdef 0
|
||||
if (!tree->selection && (tree->selection_mode == GTK_SELECTION_BROWSE))
|
||||
{
|
||||
gtk_tree_select_child (tree, widget);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
|
||||
gtk_widget_queue_resize (widget);
|
||||
|
||||
}
|
||||
|
||||
static gint
|
||||
gtk_tree_button_press (GtkWidget *widget,
|
||||
GdkEventButton *event)
|
||||
{
|
||||
GtkTree *tree;
|
||||
GtkWidget *item;
|
||||
|
||||
g_return_val_if_fail (widget != NULL, FALSE);
|
||||
g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
|
||||
tree = GTK_TREE (widget);
|
||||
item = gtk_get_event_widget ((GdkEvent*) event);
|
||||
|
||||
while (!gtk_type_is_a (GTK_WIDGET_TYPE (item), gtk_tree_item_get_type ()))
|
||||
item = item->parent;
|
||||
|
||||
switch(event->button)
|
||||
{
|
||||
case 1:
|
||||
gtk_tree_select_child (tree, item);
|
||||
break;
|
||||
case 2:
|
||||
if(GTK_TREE_ITEM(item)->subtree) gtk_tree_item_expand(GTK_TREE_ITEM(item));
|
||||
break;
|
||||
case 3:
|
||||
if(GTK_TREE_ITEM(item)->subtree) gtk_tree_item_collapse(GTK_TREE_ITEM(item));
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gint
|
||||
gtk_tree_button_release (GtkWidget *widget,
|
||||
GdkEventButton *event)
|
||||
{
|
||||
GtkTree *tree;
|
||||
GtkWidget *item;
|
||||
|
||||
g_return_val_if_fail (widget != NULL, FALSE);
|
||||
g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
|
||||
tree = GTK_TREE (widget);
|
||||
item = gtk_get_event_widget ((GdkEvent*) event);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gint
|
||||
gtk_tree_child_position (GtkTree *tree,
|
||||
GtkWidget *child)
|
||||
{
|
||||
GList *children;
|
||||
gint pos;
|
||||
|
||||
|
||||
g_return_val_if_fail (tree != NULL, -1);
|
||||
g_return_val_if_fail (GTK_IS_TREE (tree), -1);
|
||||
g_return_val_if_fail (child != NULL, -1);
|
||||
|
||||
pos = 0;
|
||||
children = tree->children;
|
||||
|
||||
while (children)
|
||||
{
|
||||
if (child == GTK_WIDGET (children->data))
|
||||
return pos;
|
||||
|
||||
pos += 1;
|
||||
children = children->next;
|
||||
}
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_tree_clear_items (GtkTree *tree,
|
||||
gint start,
|
||||
gint end)
|
||||
{
|
||||
g_return_if_fail (tree != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE (tree));
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_destroy (GtkObject *object)
|
||||
{
|
||||
GtkTree *tree;
|
||||
GtkWidget *child;
|
||||
GList *children;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE (object));
|
||||
|
||||
tree = GTK_TREE (object);
|
||||
|
||||
children = tree->children;
|
||||
while (children)
|
||||
{
|
||||
child = children->data;
|
||||
children = children->next;
|
||||
|
||||
child->parent = NULL;
|
||||
gtk_object_unref (GTK_OBJECT (child));
|
||||
gtk_widget_destroy (child);
|
||||
}
|
||||
|
||||
g_list_free (tree->children);
|
||||
|
||||
if(tree->root_tree == NULL)
|
||||
g_list_free (tree->selection);
|
||||
|
||||
if (GTK_OBJECT_CLASS (parent_class)->destroy)
|
||||
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_draw (GtkWidget *widget,
|
||||
GdkRectangle *area)
|
||||
{
|
||||
GtkTree *tree;
|
||||
GtkWidget *subtree;
|
||||
GtkWidget *child;
|
||||
GdkRectangle child_area;
|
||||
GList *children;
|
||||
|
||||
|
||||
g_return_if_fail (widget != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE (widget));
|
||||
g_return_if_fail (area != NULL);
|
||||
|
||||
if (GTK_WIDGET_DRAWABLE (widget))
|
||||
{
|
||||
tree = GTK_TREE (widget);
|
||||
|
||||
children = tree->children;
|
||||
while (children)
|
||||
{
|
||||
child = children->data;
|
||||
children = children->next;
|
||||
|
||||
if (gtk_widget_intersect (child, area, &child_area))
|
||||
gtk_widget_draw (child, &child_area);
|
||||
|
||||
if((subtree = GTK_TREE_ITEM(child)->subtree) &&
|
||||
GTK_WIDGET_VISIBLE(subtree) &&
|
||||
gtk_widget_intersect (subtree, area, &child_area))
|
||||
gtk_widget_draw (subtree, &child_area);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static gint
|
||||
gtk_tree_expose (GtkWidget *widget,
|
||||
GdkEventExpose *event)
|
||||
{
|
||||
GtkTree *tree;
|
||||
GtkWidget *child;
|
||||
GdkEventExpose child_event;
|
||||
GList *children;
|
||||
|
||||
|
||||
g_return_val_if_fail (widget != NULL, FALSE);
|
||||
g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
|
||||
if (GTK_WIDGET_DRAWABLE (widget))
|
||||
{
|
||||
tree = GTK_TREE (widget);
|
||||
|
||||
child_event = *event;
|
||||
|
||||
children = tree->children;
|
||||
while (children)
|
||||
{
|
||||
child = children->data;
|
||||
children = children->next;
|
||||
|
||||
if (GTK_WIDGET_NO_WINDOW (child) &&
|
||||
gtk_widget_intersect (child, &event->area, &child_event.area))
|
||||
gtk_widget_event (child, (GdkEvent*) &child_event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_foreach (GtkContainer *container,
|
||||
GtkCallback callback,
|
||||
gpointer callback_data)
|
||||
{
|
||||
GtkTree *tree;
|
||||
GtkWidget *child;
|
||||
GList *children;
|
||||
|
||||
|
||||
g_return_if_fail (container != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE (container));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
tree = GTK_TREE (container);
|
||||
children = tree->children;
|
||||
|
||||
while (children)
|
||||
{
|
||||
child = children->data;
|
||||
children = children->next;
|
||||
|
||||
(* callback) (child, callback_data);
|
||||
|
||||
if(GTK_TREE_ITEM(child)->subtree)
|
||||
(* callback)(GTK_TREE_ITEM(child)->subtree, callback_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_map (GtkWidget *widget)
|
||||
{
|
||||
GtkTree *tree;
|
||||
GtkWidget *child;
|
||||
GList *children;
|
||||
|
||||
|
||||
g_return_if_fail (widget != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE (widget));
|
||||
|
||||
GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
|
||||
tree = GTK_TREE (widget);
|
||||
|
||||
gdk_window_show (widget->window);
|
||||
|
||||
if(GTK_IS_TREE(widget->parent))
|
||||
{
|
||||
/* set root tree for this tree */
|
||||
tree->root_tree = GTK_TREE(widget->parent)->root_tree;
|
||||
|
||||
tree->indent_value = GTK_TREE(GTK_WIDGET(tree)->parent)->indent_value;
|
||||
tree->current_indent = GTK_TREE(GTK_WIDGET(tree)->parent)->current_indent +
|
||||
tree->indent_value;
|
||||
tree->view_mode = GTK_TREE(GTK_WIDGET(tree)->parent)->view_mode;
|
||||
} else
|
||||
tree->root_tree = tree;
|
||||
|
||||
children = tree->children;
|
||||
while (children)
|
||||
{
|
||||
child = children->data;
|
||||
children = children->next;
|
||||
|
||||
if (GTK_WIDGET_VISIBLE (child) &&
|
||||
!GTK_WIDGET_MAPPED (child))
|
||||
gtk_widget_map (child);
|
||||
|
||||
if ((child = GTK_WIDGET(GTK_TREE_ITEM(child)->subtree)) &&
|
||||
GTK_WIDGET_VISIBLE (child) &&
|
||||
!GTK_WIDGET_MAPPED (child))
|
||||
gtk_widget_map (child);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_marshal_signal (GtkObject *object,
|
||||
GtkSignalFunc func,
|
||||
gpointer func_data,
|
||||
GtkArg *args)
|
||||
{
|
||||
GtkTreeSignal rfunc;
|
||||
|
||||
rfunc = (GtkTreeSignal) func;
|
||||
|
||||
(* rfunc) (object, GTK_VALUE_OBJECT (args[0]), func_data);
|
||||
}
|
||||
|
||||
static gint
|
||||
gtk_tree_motion_notify (GtkWidget *widget,
|
||||
GdkEventMotion *event)
|
||||
{
|
||||
g_return_val_if_fail (widget != NULL, FALSE);
|
||||
g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
|
||||
g_print("gtk_tree_motion_notify\n");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_realize (GtkWidget *widget)
|
||||
{
|
||||
GdkWindowAttr attributes;
|
||||
gint attributes_mask;
|
||||
|
||||
|
||||
g_return_if_fail (widget != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE (widget));
|
||||
|
||||
GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
|
||||
|
||||
attributes.window_type = GDK_WINDOW_CHILD;
|
||||
attributes.x = widget->allocation.x;
|
||||
attributes.y = widget->allocation.y;
|
||||
attributes.width = widget->allocation.width;
|
||||
attributes.height = widget->allocation.height;
|
||||
attributes.wclass = GDK_INPUT_OUTPUT;
|
||||
attributes.visual = gtk_widget_get_visual (widget);
|
||||
attributes.colormap = gtk_widget_get_colormap (widget);
|
||||
attributes.event_mask = GDK_EXPOSURE_MASK;
|
||||
|
||||
attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
|
||||
|
||||
widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
|
||||
gdk_window_set_user_data (widget->window, widget);
|
||||
|
||||
widget->style = gtk_style_attach (widget->style, widget->window);
|
||||
gdk_window_set_background (widget->window, &widget->style->white);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_remove (GtkContainer *container,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GList *item_list;
|
||||
|
||||
g_return_if_fail (container != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE (container));
|
||||
g_return_if_fail (widget != NULL);
|
||||
g_return_if_fail (container == GTK_CONTAINER (widget->parent));
|
||||
|
||||
item_list = g_list_alloc ();
|
||||
item_list->data = widget;
|
||||
|
||||
gtk_tree_remove_items (GTK_TREE (container), item_list);
|
||||
|
||||
g_list_free (item_list);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_tree_remove_items (GtkTree *tree,
|
||||
GList *items)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GList *selected_widgets;
|
||||
GList *tmp_list;
|
||||
GtkTree *real_tree, *root_tree;
|
||||
|
||||
g_return_if_fail (tree != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE (tree));
|
||||
|
||||
root_tree = GTK_TREE(GTK_TREE_ROOT_TREE(tree));
|
||||
tmp_list = items;
|
||||
selected_widgets = NULL;
|
||||
widget = NULL;
|
||||
|
||||
while (tmp_list)
|
||||
{
|
||||
widget = tmp_list->data;
|
||||
tmp_list = tmp_list->next;
|
||||
|
||||
/* get real owner of this widget */
|
||||
real_tree = GTK_TREE(widget->parent);
|
||||
|
||||
if (widget->state == GTK_STATE_SELECTED)
|
||||
selected_widgets = g_list_prepend (selected_widgets, widget);
|
||||
|
||||
/* remove this item of his real parent */
|
||||
real_tree->children = g_list_remove (real_tree->children, widget);
|
||||
|
||||
/* delete subtree if there is no children in it */
|
||||
if(real_tree->children == NULL &&
|
||||
real_tree != root_tree)
|
||||
{
|
||||
gtk_tree_item_remove_subtree(GTK_TREE_ITEM(real_tree->tree_owner));
|
||||
}
|
||||
|
||||
/* remove subtree associate at this item if it exist */
|
||||
if(GTK_TREE_ITEM(widget)->subtree)
|
||||
{
|
||||
if (GTK_WIDGET_MAPPED (GTK_TREE_ITEM(widget)->subtree))
|
||||
gtk_widget_unmap (GTK_TREE_ITEM(widget)->subtree);
|
||||
|
||||
gtk_widget_unparent (GTK_TREE_ITEM(widget)->subtree);
|
||||
}
|
||||
|
||||
/* remove really widget for this item */
|
||||
if (GTK_WIDGET_MAPPED (widget))
|
||||
gtk_widget_unmap (widget);
|
||||
|
||||
gtk_widget_unparent (widget);
|
||||
}
|
||||
|
||||
if (selected_widgets)
|
||||
{
|
||||
tmp_list = selected_widgets;
|
||||
while (tmp_list)
|
||||
{
|
||||
widget = tmp_list->data;
|
||||
tmp_list = tmp_list->next;
|
||||
|
||||
gtk_tree_unselect_child (tree, widget);
|
||||
}
|
||||
}
|
||||
|
||||
g_list_free (selected_widgets);
|
||||
|
||||
if (root_tree->children && !root_tree->selection &&
|
||||
(root_tree->selection_mode == GTK_SELECTION_BROWSE))
|
||||
{
|
||||
widget = root_tree->children->data;
|
||||
gtk_tree_select_child (root_tree, widget);
|
||||
}
|
||||
|
||||
if (GTK_WIDGET_VISIBLE (root_tree))
|
||||
gtk_widget_queue_resize (GTK_WIDGET (root_tree));
|
||||
}
|
||||
|
||||
void
|
||||
gtk_tree_select_child (GtkTree *tree,
|
||||
GtkWidget *child)
|
||||
{
|
||||
|
||||
gtk_signal_emit (GTK_OBJECT (tree), tree_signals[SELECT_CHILD], child);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
gtk_tree_select_item (GtkTree *tree,
|
||||
gint item)
|
||||
{
|
||||
GList *tmp_list;
|
||||
|
||||
|
||||
g_return_if_fail (tree != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE (tree));
|
||||
|
||||
tmp_list = g_list_nth (tree->children, item);
|
||||
if (tmp_list)
|
||||
gtk_tree_select_child (tree, GTK_WIDGET (tmp_list->data));
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_size_allocate (GtkWidget *widget,
|
||||
GtkAllocation *allocation)
|
||||
{
|
||||
GtkTree *tree;
|
||||
GtkWidget *child, *subtree;
|
||||
GtkAllocation child_allocation;
|
||||
GList *children;
|
||||
|
||||
|
||||
g_return_if_fail (widget != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE (widget));
|
||||
g_return_if_fail (allocation != NULL);
|
||||
|
||||
tree = GTK_TREE (widget);
|
||||
|
||||
widget->allocation = *allocation;
|
||||
if (GTK_WIDGET_REALIZED (widget))
|
||||
gdk_window_move_resize (widget->window,
|
||||
allocation->x, allocation->y,
|
||||
allocation->width, allocation->height);
|
||||
|
||||
if (tree->children)
|
||||
{
|
||||
child_allocation.x = GTK_CONTAINER (tree)->border_width;
|
||||
child_allocation.y = GTK_CONTAINER (tree)->border_width;
|
||||
child_allocation.width = allocation->width - child_allocation.x * 2;
|
||||
|
||||
children = tree->children;
|
||||
|
||||
while (children)
|
||||
{
|
||||
child = children->data;
|
||||
children = children->next;
|
||||
|
||||
if (GTK_WIDGET_VISIBLE (child))
|
||||
{
|
||||
child_allocation.height = child->requisition.height;
|
||||
|
||||
gtk_widget_size_allocate (child, &child_allocation);
|
||||
|
||||
child_allocation.y += child_allocation.height;
|
||||
|
||||
if((subtree = GTK_TREE_ITEM(child)->subtree))
|
||||
if(GTK_WIDGET_VISIBLE (subtree))
|
||||
{
|
||||
child_allocation.height = subtree->requisition.height;
|
||||
gtk_widget_size_allocate (subtree, &child_allocation);
|
||||
child_allocation.y += child_allocation.height;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_size_request (GtkWidget *widget,
|
||||
GtkRequisition *requisition)
|
||||
{
|
||||
GtkTree *tree;
|
||||
GtkWidget *child, *subtree;
|
||||
GList *children;
|
||||
|
||||
|
||||
g_return_if_fail (widget != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE (widget));
|
||||
g_return_if_fail (requisition != NULL);
|
||||
|
||||
tree = GTK_TREE (widget);
|
||||
requisition->width = 0;
|
||||
requisition->height = 0;
|
||||
|
||||
children = tree->children;
|
||||
while (children)
|
||||
{
|
||||
child = children->data;
|
||||
children = children->next;
|
||||
|
||||
if (GTK_WIDGET_VISIBLE (child))
|
||||
{
|
||||
gtk_widget_size_request (child, &child->requisition);
|
||||
|
||||
requisition->width = MAX (requisition->width, child->requisition.width);
|
||||
requisition->height += child->requisition.height;
|
||||
|
||||
if((subtree = GTK_TREE_ITEM(child)->subtree) &&
|
||||
GTK_WIDGET_VISIBLE (subtree))
|
||||
{
|
||||
gtk_widget_size_request (subtree, &subtree->requisition);
|
||||
|
||||
requisition->width = MAX (requisition->width,
|
||||
subtree->requisition.width);
|
||||
|
||||
requisition->height += subtree->requisition.height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
requisition->width += GTK_CONTAINER (tree)->border_width * 2;
|
||||
requisition->height += GTK_CONTAINER (tree)->border_width * 2;
|
||||
|
||||
requisition->width = MAX (requisition->width, 1);
|
||||
requisition->height = MAX (requisition->height, 1);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_unmap (GtkWidget *widget)
|
||||
{
|
||||
|
||||
g_return_if_fail (widget != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE (widget));
|
||||
|
||||
GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
|
||||
gdk_window_hide (widget->window);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
gtk_tree_unselect_child (GtkTree *tree,
|
||||
GtkWidget *child)
|
||||
{
|
||||
gtk_signal_emit (GTK_OBJECT (tree), tree_signals[UNSELECT_CHILD], child);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_tree_unselect_item (GtkTree *tree,
|
||||
gint item)
|
||||
{
|
||||
GList *tmp_list;
|
||||
|
||||
|
||||
g_return_if_fail (tree != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE (tree));
|
||||
|
||||
tmp_list = g_list_nth (tree->children, item);
|
||||
if (tmp_list)
|
||||
gtk_tree_unselect_child (tree, GTK_WIDGET (tmp_list->data));
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_real_tree_select_child (GtkTree *tree,
|
||||
GtkWidget *child)
|
||||
{
|
||||
GList *selection, *root_selection;
|
||||
GList *tmp_list;
|
||||
GtkWidget *tmp_item;
|
||||
|
||||
|
||||
g_return_if_fail (tree != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE (tree));
|
||||
g_return_if_fail (child != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE_ITEM (child));
|
||||
|
||||
root_selection = tree->root_tree->selection;
|
||||
|
||||
switch (tree->root_tree->selection_mode)
|
||||
{
|
||||
case GTK_SELECTION_SINGLE:
|
||||
|
||||
selection = root_selection;
|
||||
|
||||
/* remove old selection list */
|
||||
while (selection)
|
||||
{
|
||||
tmp_item = selection->data;
|
||||
|
||||
if (tmp_item != child)
|
||||
{
|
||||
gtk_tree_item_deselect (GTK_TREE_ITEM (tmp_item));
|
||||
|
||||
tmp_list = selection;
|
||||
selection = selection->next;
|
||||
|
||||
root_selection = g_list_remove_link (root_selection, tmp_list);
|
||||
|
||||
g_list_free (tmp_list);
|
||||
}
|
||||
else
|
||||
selection = selection->next;
|
||||
}
|
||||
|
||||
if (child->state == GTK_STATE_NORMAL)
|
||||
{
|
||||
gtk_tree_item_select (GTK_TREE_ITEM (child));
|
||||
root_selection = g_list_prepend (root_selection, child);
|
||||
}
|
||||
else if (child->state == GTK_STATE_SELECTED)
|
||||
{
|
||||
gtk_tree_item_deselect (GTK_TREE_ITEM (child));
|
||||
root_selection = g_list_remove (root_selection, child);
|
||||
}
|
||||
|
||||
tree->root_tree->selection= root_selection;
|
||||
|
||||
gtk_signal_emit (GTK_OBJECT (tree->root_tree),
|
||||
tree_signals[SELECTION_CHANGED]);
|
||||
|
||||
case GTK_SELECTION_BROWSE:
|
||||
selection = root_selection;
|
||||
|
||||
while (selection)
|
||||
{
|
||||
tmp_item = selection->data;
|
||||
|
||||
if (tmp_item != child)
|
||||
{
|
||||
gtk_tree_item_deselect (GTK_TREE_ITEM (tmp_item));
|
||||
|
||||
tmp_list = selection;
|
||||
selection = selection->next;
|
||||
|
||||
root_selection = g_list_remove_link (root_selection, tmp_list);
|
||||
|
||||
g_list_free (tmp_list);
|
||||
}
|
||||
else
|
||||
selection = selection->next;
|
||||
}
|
||||
|
||||
tree->root_tree->selection= root_selection;
|
||||
|
||||
if (child->state == GTK_STATE_NORMAL)
|
||||
{
|
||||
gtk_tree_item_select (GTK_TREE_ITEM (child));
|
||||
root_selection = g_list_prepend (root_selection, child);
|
||||
tree->root_tree->selection= root_selection;
|
||||
gtk_signal_emit (GTK_OBJECT (tree->root_tree),
|
||||
tree_signals[SELECTION_CHANGED]);
|
||||
}
|
||||
break;
|
||||
|
||||
case GTK_SELECTION_MULTIPLE:
|
||||
if (child->state == GTK_STATE_NORMAL)
|
||||
{
|
||||
gtk_tree_item_select (GTK_TREE_ITEM (child));
|
||||
root_selection = g_list_prepend (root_selection, child);
|
||||
tree->root_tree->selection= root_selection;
|
||||
gtk_signal_emit (GTK_OBJECT (tree->root_tree),
|
||||
tree_signals[SELECTION_CHANGED]);
|
||||
}
|
||||
else if (child->state == GTK_STATE_SELECTED)
|
||||
{
|
||||
gtk_tree_item_deselect (GTK_TREE_ITEM (child));
|
||||
root_selection = g_list_remove (root_selection, child);
|
||||
tree->root_tree->selection= root_selection;
|
||||
gtk_signal_emit (GTK_OBJECT (tree->root_tree),
|
||||
tree_signals[SELECTION_CHANGED]);
|
||||
}
|
||||
break;
|
||||
|
||||
case GTK_SELECTION_EXTENDED:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_real_tree_unselect_child (GtkTree *tree,
|
||||
GtkWidget *child)
|
||||
{
|
||||
|
||||
g_return_if_fail (tree != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE (tree));
|
||||
g_return_if_fail (child != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE_ITEM (child));
|
||||
|
||||
switch (tree->selection_mode)
|
||||
{
|
||||
case GTK_SELECTION_SINGLE:
|
||||
case GTK_SELECTION_MULTIPLE:
|
||||
case GTK_SELECTION_BROWSE:
|
||||
if (child->state == GTK_STATE_SELECTED)
|
||||
{
|
||||
GtkTree* root_tree = GTK_TREE_ROOT_TREE(tree);
|
||||
gtk_tree_item_deselect (GTK_TREE_ITEM (child));
|
||||
root_tree->selection = g_list_remove (root_tree->selection, child);
|
||||
gtk_signal_emit (GTK_OBJECT (tree->root_tree),
|
||||
tree_signals[SELECTION_CHANGED]);
|
||||
}
|
||||
break;
|
||||
|
||||
case GTK_SELECTION_EXTENDED:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gtk_tree_set_selection_mode (GtkTree *tree,
|
||||
GtkSelectionMode mode)
|
||||
{
|
||||
g_return_if_fail (tree != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE (tree));
|
||||
|
||||
tree->selection_mode = mode;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_tree_set_view_mode (GtkTree *tree,
|
||||
GtkTreeViewMode mode)
|
||||
{
|
||||
g_return_if_fail (tree != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE (tree));
|
||||
|
||||
tree->view_mode = mode;
|
||||
}
|
||||
|
@ -32,6 +32,15 @@ extern "C" {
|
||||
#define GTK_TREE_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_tree_get_type (), GtkTreeClass)
|
||||
#define GTK_IS_TREE(obj) GTK_CHECK_TYPE (obj, gtk_tree_get_type ())
|
||||
|
||||
#define GTK_IS_ROOT_TREE(obj) (GTK_TREE(obj)->root_tree == NULL)
|
||||
#define GTK_TREE_ROOT_TREE(obj) (GTK_TREE(obj)->root_tree ? GTK_TREE(obj)->root_tree : GTK_TREE(obj))
|
||||
#define GTK_TREE_SELECTION(obj) (GTK_TREE_ROOT_TREE(obj)->selection)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GTK_TREE_VIEW_LINE, /* default view mode */
|
||||
GTK_TREE_VIEW_ITEM
|
||||
} GtkTreeViewMode;
|
||||
|
||||
typedef struct _GtkTree GtkTree;
|
||||
typedef struct _GtkTreeClass GtkTreeClass;
|
||||
@ -41,25 +50,58 @@ struct _GtkTree
|
||||
GtkContainer container;
|
||||
|
||||
GList *children;
|
||||
|
||||
GtkTree* root_tree; /* owner of selection list */
|
||||
GtkWidget* tree_owner;
|
||||
GList *selection;
|
||||
guint indent_value;
|
||||
guint current_indent;
|
||||
guint selection_mode : 2;
|
||||
guint view_mode : 1;
|
||||
};
|
||||
|
||||
struct _GtkTreeClass
|
||||
{
|
||||
GtkContainerClass parent_class;
|
||||
|
||||
void (* selection_changed) (GtkTree *tree);
|
||||
void (* select_child) (GtkTree *tree,
|
||||
GtkWidget *child);
|
||||
void (* unselect_child) (GtkTree *tree,
|
||||
GtkWidget *child);
|
||||
};
|
||||
|
||||
|
||||
guint gtk_tree_get_type (void);
|
||||
GtkWidget* gtk_tree_new (void);
|
||||
void gtk_tree_append (GtkTree *tree,
|
||||
GtkWidget *child);
|
||||
void gtk_tree_prepend (GtkTree *tree,
|
||||
GtkWidget *child);
|
||||
void gtk_tree_insert (GtkTree *tree,
|
||||
GtkWidget *child,
|
||||
gint position);
|
||||
|
||||
|
||||
guint gtk_tree_get_type (void);
|
||||
GtkWidget* gtk_tree_new (void);
|
||||
void gtk_tree_append (GtkTree *tree,
|
||||
GtkWidget *child);
|
||||
void gtk_tree_prepend (GtkTree *tree,
|
||||
GtkWidget *child);
|
||||
void gtk_tree_insert (GtkTree *tree,
|
||||
GtkWidget *child,
|
||||
gint position);
|
||||
void gtk_tree_remove_item (GtkTree *tree,
|
||||
GtkWidget *child);
|
||||
void gtk_tree_remove_items (GtkTree *tree,
|
||||
GList *items);
|
||||
void gtk_tree_clear_items (GtkTree *tree,
|
||||
gint start,
|
||||
gint end);
|
||||
void gtk_tree_select_item (GtkTree *tree,
|
||||
gint item);
|
||||
void gtk_tree_unselect_item (GtkTree *tree,
|
||||
gint item);
|
||||
void gtk_tree_select_child (GtkTree *tree,
|
||||
GtkWidget *child);
|
||||
void gtk_tree_unselect_child (GtkTree *tree,
|
||||
GtkWidget *child);
|
||||
gint gtk_tree_child_position (GtkTree *tree,
|
||||
GtkWidget *child);
|
||||
void gtk_tree_set_selection_mode (GtkTree *tree,
|
||||
GtkSelectionMode mode);
|
||||
void gtk_tree_set_view_mode (GtkTree *tree,
|
||||
GtkTreeViewMode mode);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
@ -16,12 +16,74 @@
|
||||
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#include "gtklabel.h"
|
||||
#include "gtktree.h"
|
||||
#include "gtktreeitem.h"
|
||||
#include "gtkeventbox.h"
|
||||
#include "gtkpixmap.h"
|
||||
#include "gtkmain.h"
|
||||
#include "gtksignal.h"
|
||||
|
||||
/* remove comment if you want replace loading pixmap by static bitmap
|
||||
for icons
|
||||
experimental code and it is buggy */
|
||||
/* #define WITH_BITMAP */
|
||||
|
||||
#define DEFAULT_DELTA 9
|
||||
|
||||
#ifdef WITH_BITMAP
|
||||
#include "tree_plus.xbm"
|
||||
#include "tree_minus.xbm"
|
||||
#endif
|
||||
|
||||
enum {
|
||||
COLLAPSE_TREE,
|
||||
EXPAND_TREE,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
typedef void (*GtkTreeItemSignal) (GtkObject *object,
|
||||
gpointer arg1,
|
||||
gpointer data);
|
||||
|
||||
static void gtk_tree_item_class_init (GtkTreeItemClass *klass);
|
||||
static void gtk_tree_item_init (GtkTreeItem *tree_item);
|
||||
static void gtk_tree_item_realize (GtkWidget *widget);
|
||||
static void gtk_tree_item_size_request (GtkWidget *widget,
|
||||
GtkRequisition *requisition);
|
||||
static void gtk_tree_item_size_allocate (GtkWidget *widget,
|
||||
GtkAllocation *allocation);
|
||||
static void gtk_tree_item_draw (GtkWidget *widget,
|
||||
GdkRectangle *area);
|
||||
static void gtk_tree_item_draw_focus (GtkWidget *widget);
|
||||
static gint gtk_tree_item_button_press (GtkWidget *widget,
|
||||
GdkEventButton *event);
|
||||
static gint gtk_tree_item_expose (GtkWidget *widget,
|
||||
GdkEventExpose *event);
|
||||
static gint gtk_tree_item_focus_in (GtkWidget *widget,
|
||||
GdkEventFocus *event);
|
||||
static gint gtk_tree_item_focus_out (GtkWidget *widget,
|
||||
GdkEventFocus *event);
|
||||
static void gtk_real_tree_item_select (GtkItem *item);
|
||||
static void gtk_real_tree_item_deselect (GtkItem *item);
|
||||
static void gtk_real_tree_item_toggle (GtkItem *item);
|
||||
static void gtk_real_tree_item_expand (GtkTreeItem *item);
|
||||
static void gtk_real_tree_item_collapse (GtkTreeItem *item);
|
||||
static void gtk_real_tree_item_expand (GtkTreeItem *item);
|
||||
static void gtk_real_tree_item_collapse (GtkTreeItem *item);
|
||||
static void gtk_tree_item_marshal_signal (GtkObject *object,
|
||||
GtkSignalFunc func,
|
||||
gpointer func_data,
|
||||
GtkArg *args);
|
||||
static void gtk_tree_item_destroy (GtkObject *object);
|
||||
static void gtk_tree_item_subtree_button_click (GtkWidget *widget);
|
||||
static void gtk_tree_item_subtree_button_changed_state (GtkWidget *widget);
|
||||
|
||||
static void gtk_tree_item_map(GtkWidget*);
|
||||
static void gtk_tree_item_unmap(GtkWidget*);
|
||||
|
||||
static GtkItemClass *parent_class = NULL;
|
||||
static GtkContainerClass *container_class = NULL;
|
||||
static gint tree_item_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
guint
|
||||
gtk_tree_item_get_type ()
|
||||
@ -49,18 +111,191 @@ gtk_tree_item_get_type ()
|
||||
static void
|
||||
gtk_tree_item_class_init (GtkTreeItemClass *class)
|
||||
{
|
||||
GtkObjectClass *object_class;
|
||||
GtkWidgetClass *widget_class;
|
||||
GtkItemClass *item_class;
|
||||
|
||||
object_class = (GtkObjectClass*) class;
|
||||
widget_class = (GtkWidgetClass*) class;
|
||||
item_class = (GtkItemClass*) class;
|
||||
container_class = (GtkContainerClass*) class;
|
||||
|
||||
parent_class = gtk_type_class (gtk_item_get_type ());
|
||||
|
||||
tree_item_signals[EXPAND_TREE] =
|
||||
gtk_signal_new ("expand",
|
||||
GTK_RUN_FIRST,
|
||||
object_class->type,
|
||||
GTK_SIGNAL_OFFSET (GtkTreeItemClass, expand),
|
||||
gtk_tree_item_marshal_signal,
|
||||
GTK_TYPE_NONE, 0);
|
||||
tree_item_signals[COLLAPSE_TREE] =
|
||||
gtk_signal_new ("collapse",
|
||||
GTK_RUN_FIRST,
|
||||
object_class->type,
|
||||
GTK_SIGNAL_OFFSET (GtkTreeItemClass, collapse),
|
||||
gtk_tree_item_marshal_signal,
|
||||
GTK_TYPE_NONE, 0);
|
||||
|
||||
gtk_object_class_add_signals (object_class, tree_item_signals, LAST_SIGNAL);
|
||||
|
||||
object_class->destroy = gtk_tree_item_destroy;
|
||||
|
||||
widget_class->realize = gtk_tree_item_realize;
|
||||
widget_class->size_request = gtk_tree_item_size_request;
|
||||
widget_class->size_allocate = gtk_tree_item_size_allocate;
|
||||
widget_class->draw = gtk_tree_item_draw;
|
||||
widget_class->draw_focus = gtk_tree_item_draw_focus;
|
||||
widget_class->button_press_event = gtk_tree_item_button_press;
|
||||
widget_class->expose_event = gtk_tree_item_expose;
|
||||
widget_class->focus_in_event = gtk_tree_item_focus_in;
|
||||
widget_class->focus_out_event = gtk_tree_item_focus_out;
|
||||
widget_class->map = gtk_tree_item_map;
|
||||
widget_class->unmap = gtk_tree_item_unmap;
|
||||
|
||||
item_class->select = gtk_real_tree_item_select;
|
||||
item_class->deselect = gtk_real_tree_item_deselect;
|
||||
item_class->toggle = gtk_real_tree_item_toggle;
|
||||
|
||||
class->expand = gtk_real_tree_item_expand;
|
||||
class->collapse = gtk_real_tree_item_collapse;
|
||||
|
||||
container_class = (GtkContainerClass*) parent_class;
|
||||
}
|
||||
|
||||
/* callback for event box mouse event */
|
||||
static void
|
||||
gtk_tree_item_subtree_button_click (GtkWidget *widget)
|
||||
{
|
||||
GtkTreeItem* item;
|
||||
|
||||
item = (GtkTreeItem*) gtk_object_get_user_data(GTK_OBJECT(widget));
|
||||
|
||||
if(item->expanded)
|
||||
gtk_tree_item_collapse(item);
|
||||
else
|
||||
gtk_tree_item_expand(item);
|
||||
}
|
||||
|
||||
/* callback for event box state changed */
|
||||
static void
|
||||
gtk_tree_item_subtree_button_changed_state(GtkWidget *w)
|
||||
{
|
||||
if(GTK_WIDGET_VISIBLE (w)) {
|
||||
|
||||
if (w->state == GTK_STATE_NORMAL)
|
||||
gdk_window_set_background (w->window, &w->style->white);
|
||||
else
|
||||
gdk_window_set_background (w->window, &w->style->bg[w->state]);
|
||||
|
||||
if (GTK_WIDGET_DRAWABLE(w))
|
||||
gdk_window_clear_area (w->window, 0, 0,
|
||||
w->allocation.width, w->allocation.height);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_item_init (GtkTreeItem *tree_item)
|
||||
{
|
||||
GtkWidget *eventbox, *pixmapwid;
|
||||
static GdkPixmap *pixmap_plus = NULL;
|
||||
static GdkPixmap *pixmap_minus = NULL;
|
||||
#ifndef WITH_BITMAP
|
||||
static GdkBitmap *mask = NULL;
|
||||
#endif
|
||||
static GtkStyle *style = NULL;
|
||||
|
||||
tree_item->expanded = FALSE;
|
||||
tree_item->subtree = NULL;
|
||||
GTK_WIDGET_SET_FLAGS (tree_item, GTK_CAN_FOCUS);
|
||||
|
||||
if(style == NULL)
|
||||
{
|
||||
|
||||
style=gtk_widget_get_style(GTK_WIDGET(tree_item));
|
||||
|
||||
#ifndef WITH_BITMAP
|
||||
/* create pixmaps for one time, based on xpm file */
|
||||
pixmap_plus = gdk_pixmap_create_from_xpm (GTK_WIDGET(tree_item)->window, &mask,
|
||||
&style->bg[GTK_STATE_NORMAL],
|
||||
"tree_plus.xpm");
|
||||
if(!pixmap_plus)
|
||||
g_warning("gtk_tree_item_init: can't find tree_plus.xpm file !\n");
|
||||
|
||||
pixmap_minus = gdk_pixmap_create_from_xpm (GTK_WIDGET(tree_item)->window, &mask,
|
||||
&style->bg[GTK_STATE_NORMAL],
|
||||
"tree_minus.xpm");
|
||||
if(!pixmap_minus)
|
||||
g_warning("gtk_tree_item_init: can't find tree_minus.xpm file !\n");
|
||||
#else
|
||||
|
||||
pixmap_plus = gdk_pixmap_create_from_data(GTK_WIDGET(tree_item)->window,
|
||||
(gchar*) tree_plus_bits,
|
||||
tree_plus_width, tree_plus_height, -1,
|
||||
&style->black,
|
||||
&style->white);
|
||||
|
||||
pixmap_minus = gdk_pixmap_create_from_data(GTK_WIDGET(tree_item)->window,
|
||||
(gchar*) tree_minus_bits,
|
||||
tree_minus_width, tree_minus_height, -1,
|
||||
&style->black,
|
||||
&style->white);
|
||||
#endif /* WITH_BITMAP */
|
||||
}
|
||||
|
||||
if(pixmap_plus && pixmap_minus)
|
||||
{
|
||||
/* create an event box containing one pixmaps */
|
||||
eventbox = gtk_event_box_new();
|
||||
gtk_widget_set_events (eventbox, GDK_BUTTON_PRESS_MASK);
|
||||
gtk_signal_connect(GTK_OBJECT(eventbox), "state_changed",
|
||||
(GtkSignalFunc)gtk_tree_item_subtree_button_changed_state,
|
||||
(gpointer)NULL);
|
||||
gtk_signal_connect(GTK_OBJECT(eventbox), "realize",
|
||||
(GtkSignalFunc)gtk_tree_item_subtree_button_changed_state,
|
||||
(gpointer)NULL);
|
||||
gtk_signal_connect(GTK_OBJECT(eventbox), "button_press_event",
|
||||
(GtkSignalFunc)gtk_tree_item_subtree_button_click,
|
||||
(gpointer)NULL);
|
||||
gtk_object_set_user_data(GTK_OBJECT(eventbox), tree_item);
|
||||
tree_item->pixmaps_box = eventbox;
|
||||
|
||||
/* create pixmap for button '+' */
|
||||
#ifndef WITH_BITMAP
|
||||
pixmapwid = gtk_pixmap_new (pixmap_plus, mask);
|
||||
#else
|
||||
pixmapwid = gtk_pixmap_new (pixmap_plus, NULL);
|
||||
#endif
|
||||
if(!tree_item->expanded)
|
||||
gtk_container_add(GTK_CONTAINER(eventbox), pixmapwid);
|
||||
gtk_widget_show(pixmapwid);
|
||||
tree_item->plus_pix_widget = pixmapwid;
|
||||
|
||||
/* create pixmap for button '-' */
|
||||
#ifndef WITH_BITMAP
|
||||
pixmapwid = gtk_pixmap_new (pixmap_minus, mask);
|
||||
#else
|
||||
pixmapwid = gtk_pixmap_new (pixmap_minus, NULL);
|
||||
#endif
|
||||
if(tree_item->expanded)
|
||||
gtk_container_add(GTK_CONTAINER(eventbox), pixmapwid);
|
||||
gtk_widget_show(pixmapwid);
|
||||
tree_item->minus_pix_widget = pixmapwid;
|
||||
|
||||
gtk_widget_set_parent(eventbox, GTK_WIDGET(tree_item));
|
||||
} else
|
||||
tree_item->pixmaps_box = NULL;
|
||||
}
|
||||
|
||||
|
||||
GtkWidget*
|
||||
gtk_tree_item_new ()
|
||||
{
|
||||
return GTK_WIDGET (gtk_type_new (gtk_tree_item_get_type ()));
|
||||
GtkWidget *tree_item;
|
||||
|
||||
tree_item = GTK_WIDGET (gtk_type_new (gtk_tree_item_get_type ()));
|
||||
|
||||
return tree_item;
|
||||
}
|
||||
|
||||
GtkWidget*
|
||||
@ -69,6 +304,7 @@ gtk_tree_item_new_with_label (gchar *label)
|
||||
GtkWidget *tree_item;
|
||||
GtkWidget *label_widget;
|
||||
|
||||
|
||||
tree_item = gtk_tree_item_new ();
|
||||
label_widget = gtk_label_new (label);
|
||||
gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
|
||||
@ -76,6 +312,7 @@ gtk_tree_item_new_with_label (gchar *label)
|
||||
gtk_container_add (GTK_CONTAINER (tree_item), label_widget);
|
||||
gtk_widget_show (label_widget);
|
||||
|
||||
|
||||
return tree_item;
|
||||
}
|
||||
|
||||
@ -85,24 +322,577 @@ gtk_tree_item_set_subtree (GtkTreeItem *tree_item,
|
||||
{
|
||||
g_return_if_fail (tree_item != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
|
||||
|
||||
if(tree_item->subtree) {
|
||||
g_warning("there is already a subtree for this tree item\n");
|
||||
return;
|
||||
}
|
||||
|
||||
tree_item->subtree = subtree;
|
||||
GTK_TREE(subtree)->tree_owner = GTK_WIDGET(tree_item);
|
||||
|
||||
/* set root tree for selection list */
|
||||
GTK_TREE(subtree)->root_tree = GTK_TREE(GTK_WIDGET(tree_item)->parent)->root_tree;
|
||||
|
||||
/* show subtree button */
|
||||
if(tree_item->pixmaps_box)
|
||||
gtk_widget_show(tree_item->pixmaps_box);
|
||||
|
||||
/* set parent widget */
|
||||
gtk_widget_set_parent(subtree, GTK_WIDGET(tree_item)->parent);
|
||||
|
||||
if(GTK_WIDGET_VISIBLE(GTK_WIDGET(tree_item)))
|
||||
{
|
||||
if(GTK_WIDGET_REALIZED (GTK_WIDGET(tree_item)) &&
|
||||
!GTK_WIDGET_REALIZED (GTK_WIDGET(subtree)))
|
||||
gtk_widget_realize (GTK_WIDGET(subtree));
|
||||
|
||||
if(GTK_WIDGET_MAPPED (GTK_WIDGET(tree_item)) &&
|
||||
!GTK_WIDGET_MAPPED (GTK_WIDGET(subtree)))
|
||||
gtk_widget_map (GTK_WIDGET(subtree));
|
||||
}
|
||||
|
||||
if(tree_item->expanded)
|
||||
gtk_widget_show(subtree);
|
||||
else
|
||||
gtk_widget_hide(subtree);
|
||||
|
||||
if (GTK_WIDGET_VISIBLE (tree_item) && GTK_WIDGET_VISIBLE (tree_item))
|
||||
gtk_widget_queue_resize (GTK_WIDGET(tree_item));
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
gtk_tree_item_select (GtkTreeItem *tree_item)
|
||||
{
|
||||
|
||||
gtk_item_select (GTK_ITEM (tree_item));
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
gtk_tree_item_deselect (GtkTreeItem *tree_item)
|
||||
{
|
||||
|
||||
gtk_item_deselect (GTK_ITEM (tree_item));
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
gtk_tree_item_expand (GtkTreeItem *tree_item)
|
||||
{
|
||||
|
||||
gtk_signal_emit (GTK_OBJECT (tree_item), tree_item_signals[EXPAND_TREE], NULL);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
gtk_tree_item_collapse (GtkTreeItem *tree_item)
|
||||
{
|
||||
|
||||
gtk_signal_emit (GTK_OBJECT (tree_item), tree_item_signals[COLLAPSE_TREE], NULL);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_item_realize (GtkWidget *widget)
|
||||
{
|
||||
g_return_if_fail (widget != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE_ITEM (widget));
|
||||
|
||||
if (GTK_WIDGET_CLASS (parent_class)->realize)
|
||||
(* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
|
||||
|
||||
gdk_window_set_background (widget->window, &widget->style->white);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_item_size_request (GtkWidget *widget,
|
||||
GtkRequisition *requisition)
|
||||
{
|
||||
GtkBin *bin;
|
||||
GtkTreeItem* item;
|
||||
|
||||
g_return_if_fail (widget != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE_ITEM (widget));
|
||||
g_return_if_fail (requisition != NULL);
|
||||
|
||||
bin = GTK_BIN (widget);
|
||||
item = GTK_TREE_ITEM(widget);
|
||||
|
||||
requisition->width = (GTK_CONTAINER (widget)->border_width +
|
||||
widget->style->klass->xthickness) * 2;
|
||||
requisition->height = GTK_CONTAINER (widget)->border_width * 2;
|
||||
|
||||
if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
|
||||
{
|
||||
gtk_widget_size_request (bin->child, &bin->child->requisition);
|
||||
|
||||
requisition->width += bin->child->requisition.width;
|
||||
|
||||
gtk_widget_size_request (item->pixmaps_box,
|
||||
&item->pixmaps_box->requisition);
|
||||
requisition->width += item->pixmaps_box->requisition.width + DEFAULT_DELTA +
|
||||
GTK_TREE(widget->parent)->current_indent;
|
||||
|
||||
requisition->height += MAX(bin->child->requisition.height,
|
||||
item->pixmaps_box->requisition.height);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_item_size_allocate (GtkWidget *widget,
|
||||
GtkAllocation *allocation)
|
||||
{
|
||||
GtkBin *bin;
|
||||
GtkTreeItem* item;
|
||||
GtkAllocation child_allocation;
|
||||
guint border_width;
|
||||
|
||||
g_return_if_fail (widget != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE_ITEM (widget));
|
||||
g_return_if_fail (allocation != NULL);
|
||||
|
||||
widget->allocation = *allocation;
|
||||
if (GTK_WIDGET_REALIZED (widget))
|
||||
gdk_window_move_resize (widget->window,
|
||||
allocation->x, allocation->y,
|
||||
allocation->width, allocation->height);
|
||||
|
||||
bin = GTK_BIN (widget);
|
||||
item = GTK_TREE_ITEM(widget);
|
||||
|
||||
if (bin->child)
|
||||
{
|
||||
border_width = (GTK_CONTAINER (widget)->border_width +
|
||||
widget->style->klass->xthickness);
|
||||
|
||||
child_allocation.x = border_width + GTK_TREE(widget->parent)->current_indent;
|
||||
child_allocation.y = GTK_CONTAINER (widget)->border_width;
|
||||
|
||||
child_allocation.height = allocation->height - child_allocation.y * 2;
|
||||
child_allocation.width = item->pixmaps_box->requisition.width;
|
||||
|
||||
child_allocation.y += 1;
|
||||
child_allocation.height -= 2;
|
||||
gtk_widget_size_allocate (item->pixmaps_box, &child_allocation);
|
||||
|
||||
child_allocation.height += 2;
|
||||
child_allocation.x += item->pixmaps_box->requisition.width+DEFAULT_DELTA;
|
||||
|
||||
child_allocation.width =
|
||||
allocation->width - (child_allocation.x + border_width);
|
||||
|
||||
gtk_widget_size_allocate (bin->child, &child_allocation);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_item_draw (GtkWidget *widget,
|
||||
GdkRectangle *area)
|
||||
{
|
||||
GtkBin *bin;
|
||||
GdkRectangle child_area, item_area;
|
||||
GtkTreeItem* tree_item;
|
||||
|
||||
g_return_if_fail (widget != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE_ITEM (widget));
|
||||
g_return_if_fail (area != NULL);
|
||||
|
||||
if (GTK_WIDGET_DRAWABLE (widget))
|
||||
{
|
||||
bin = GTK_BIN (widget);
|
||||
tree_item = GTK_TREE_ITEM(widget);
|
||||
|
||||
/* draw left size of tree item */
|
||||
item_area.x = 0; item_area.y = 0;
|
||||
item_area.width = tree_item->pixmaps_box->allocation.width+DEFAULT_DELTA +
|
||||
(GTK_TREE(widget->parent)->current_indent + 2);
|
||||
item_area.height = widget->allocation.height;
|
||||
|
||||
if(gdk_rectangle_intersect(&item_area, area, &child_area)) {
|
||||
|
||||
if (!GTK_WIDGET_IS_SENSITIVE (widget))
|
||||
gtk_style_set_background (widget->style, widget->window,
|
||||
GTK_STATE_INSENSITIVE);
|
||||
else if(GTK_TREE(widget->parent)->view_mode == GTK_TREE_VIEW_LINE &&
|
||||
widget->state == GTK_STATE_SELECTED)
|
||||
gtk_style_set_background (widget->style, widget->window, widget->state);
|
||||
else
|
||||
gdk_window_set_background (widget->window, &widget->style->white);
|
||||
|
||||
gdk_window_clear_area (widget->window,
|
||||
child_area.x, child_area.y,
|
||||
child_area.width, child_area.height);
|
||||
|
||||
if (tree_item->pixmaps_box &&
|
||||
GTK_WIDGET_VISIBLE(tree_item->pixmaps_box) &&
|
||||
gtk_widget_intersect (tree_item->pixmaps_box, area, &child_area))
|
||||
gtk_widget_draw (tree_item->pixmaps_box, &child_area);
|
||||
}
|
||||
|
||||
/* draw right side */
|
||||
if(gtk_widget_intersect (bin->child, area, &child_area)) {
|
||||
|
||||
if (!GTK_WIDGET_IS_SENSITIVE (widget))
|
||||
gtk_style_set_background (widget->style, widget->window,
|
||||
GTK_STATE_INSENSITIVE);
|
||||
else if (widget->state == GTK_STATE_NORMAL)
|
||||
gdk_window_set_background(widget->window, &widget->style->white);
|
||||
else
|
||||
gtk_style_set_background (widget->style, widget->window, widget->state);
|
||||
|
||||
gdk_window_clear_area (widget->window, child_area.x, child_area.y,
|
||||
child_area.width+1, child_area.height);
|
||||
|
||||
if (bin->child &&
|
||||
GTK_WIDGET_VISIBLE(bin->child) &&
|
||||
gtk_widget_intersect (bin->child, area, &child_area))
|
||||
gtk_widget_draw (bin->child, &child_area);
|
||||
}
|
||||
|
||||
gtk_widget_draw_focus (widget);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_item_draw_focus (GtkWidget *widget)
|
||||
{
|
||||
GdkGC *gc;
|
||||
int dx;
|
||||
|
||||
g_return_if_fail (widget != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE_ITEM (widget));
|
||||
|
||||
if (GTK_WIDGET_DRAWABLE (widget))
|
||||
{
|
||||
if (GTK_WIDGET_HAS_FOCUS (widget))
|
||||
gc = widget->style->black_gc;
|
||||
else if (!GTK_WIDGET_IS_SENSITIVE (widget))
|
||||
gc = widget->style->bg_gc[GTK_STATE_INSENSITIVE];
|
||||
else if (widget->state == GTK_STATE_NORMAL)
|
||||
gc = widget->style->white_gc;
|
||||
else
|
||||
gc = widget->style->bg_gc[widget->state];
|
||||
|
||||
dx = 0;
|
||||
|
||||
if(GTK_TREE(widget->parent)->view_mode == GTK_TREE_VIEW_ITEM)
|
||||
dx = GTK_TREE_ITEM(widget)->pixmaps_box->allocation.width + DEFAULT_DELTA +
|
||||
GTK_TREE(widget->parent)->current_indent+1;
|
||||
|
||||
gdk_draw_rectangle (widget->window, gc, FALSE, dx, 0,
|
||||
widget->allocation.width - 1 - dx,
|
||||
widget->allocation.height - 1);
|
||||
}
|
||||
}
|
||||
|
||||
static gint
|
||||
gtk_tree_item_button_press (GtkWidget *widget,
|
||||
GdkEventButton *event)
|
||||
{
|
||||
|
||||
g_return_val_if_fail (widget != NULL, FALSE);
|
||||
g_return_val_if_fail (GTK_IS_TREE_ITEM (widget), FALSE);
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
|
||||
if (event->type == GDK_BUTTON_PRESS)
|
||||
if (!GTK_WIDGET_HAS_FOCUS (widget))
|
||||
gtk_widget_grab_focus (widget);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gint
|
||||
gtk_tree_item_expose (GtkWidget *widget,
|
||||
GdkEventExpose *event)
|
||||
{
|
||||
g_return_val_if_fail (widget != NULL, FALSE);
|
||||
g_return_val_if_fail (GTK_IS_TREE_ITEM (widget), FALSE);
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
|
||||
if (GTK_WIDGET_DRAWABLE (widget))
|
||||
gtk_tree_item_draw(widget, &event->area);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gint
|
||||
gtk_tree_item_focus_in (GtkWidget *widget,
|
||||
GdkEventFocus *event)
|
||||
{
|
||||
|
||||
g_return_val_if_fail (widget != NULL, FALSE);
|
||||
g_return_val_if_fail (GTK_IS_TREE_ITEM (widget), FALSE);
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
|
||||
GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
|
||||
gtk_widget_draw_focus (widget);
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gint
|
||||
gtk_tree_item_focus_out (GtkWidget *widget,
|
||||
GdkEventFocus *event)
|
||||
{
|
||||
|
||||
g_return_val_if_fail (widget != NULL, FALSE);
|
||||
g_return_val_if_fail (GTK_IS_TREE_ITEM (widget), FALSE);
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
|
||||
GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
|
||||
gtk_widget_draw_focus (widget);
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_real_tree_item_select (GtkItem *item)
|
||||
{
|
||||
|
||||
g_return_if_fail (item != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE_ITEM (item));
|
||||
|
||||
if (GTK_WIDGET (item)->state == GTK_STATE_SELECTED)
|
||||
return;
|
||||
|
||||
gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_SELECTED);
|
||||
|
||||
if(GTK_TREE(GTK_WIDGET(item)->parent)->view_mode == GTK_TREE_VIEW_LINE)
|
||||
gtk_widget_set_state (GTK_TREE_ITEM (item)->pixmaps_box, GTK_STATE_SELECTED);
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (item));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_real_tree_item_deselect (GtkItem *item)
|
||||
{
|
||||
|
||||
g_return_if_fail (item != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE_ITEM (item));
|
||||
|
||||
if (GTK_WIDGET (item)->state == GTK_STATE_NORMAL)
|
||||
return;
|
||||
|
||||
gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_NORMAL);
|
||||
|
||||
if(GTK_TREE(GTK_WIDGET(item)->parent)->view_mode == GTK_TREE_VIEW_LINE)
|
||||
gtk_widget_set_state (GTK_TREE_ITEM (item)->pixmaps_box, GTK_STATE_NORMAL);
|
||||
|
||||
gtk_widget_queue_draw (GTK_WIDGET (item));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_real_tree_item_toggle (GtkItem *item)
|
||||
{
|
||||
|
||||
g_return_if_fail (item != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE_ITEM (item));
|
||||
|
||||
if (GTK_WIDGET (item)->parent && GTK_IS_TREE (GTK_WIDGET (item)->parent))
|
||||
gtk_tree_select_child (GTK_TREE (GTK_WIDGET (item)->parent),
|
||||
GTK_WIDGET (item));
|
||||
else
|
||||
{
|
||||
/* Should we really bother with this bit? A listitem not in a list?
|
||||
* -Johannes Keukelaar
|
||||
* yes, always be on the save side!
|
||||
* -timj
|
||||
*/
|
||||
if (GTK_WIDGET (item)->state == GTK_STATE_SELECTED)
|
||||
gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_NORMAL);
|
||||
else
|
||||
gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_SELECTED);
|
||||
gtk_widget_queue_draw (GTK_WIDGET (item));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_item_marshal_signal (GtkObject *object,
|
||||
GtkSignalFunc func,
|
||||
gpointer func_data,
|
||||
GtkArg *args)
|
||||
{
|
||||
GtkTreeItemSignal rfunc;
|
||||
|
||||
rfunc = (GtkTreeItemSignal) func;
|
||||
|
||||
(* rfunc) (object, GTK_VALUE_OBJECT (args[0]), func_data);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_real_tree_item_expand (GtkTreeItem *tree_item)
|
||||
{
|
||||
GtkTree* tree;
|
||||
|
||||
g_return_if_fail (tree_item != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
|
||||
g_return_if_fail (tree_item->subtree != NULL);
|
||||
|
||||
|
||||
if(!tree_item->expanded)
|
||||
{
|
||||
tree = GTK_TREE(GTK_WIDGET(tree_item)->parent);
|
||||
|
||||
/* hide subtree widget */
|
||||
gtk_widget_show(tree_item->subtree);
|
||||
|
||||
/* hide button '+' and show button '-' */
|
||||
if(tree_item->pixmaps_box) {
|
||||
gtk_container_remove(GTK_CONTAINER(tree_item->pixmaps_box),
|
||||
tree_item->plus_pix_widget);
|
||||
gtk_container_add(GTK_CONTAINER(tree_item->pixmaps_box),
|
||||
tree_item->minus_pix_widget);
|
||||
}
|
||||
if(tree->root_tree) gtk_widget_queue_resize(GTK_WIDGET(tree->root_tree));
|
||||
tree_item->expanded = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_real_tree_item_collapse (GtkTreeItem *tree_item)
|
||||
{
|
||||
GtkTree* tree;
|
||||
|
||||
g_return_if_fail (tree_item != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
|
||||
g_return_if_fail (tree_item->subtree != NULL);
|
||||
|
||||
if(tree_item->expanded)
|
||||
{
|
||||
tree = GTK_TREE(GTK_WIDGET(tree_item)->parent);
|
||||
|
||||
/* hide subtree widget */
|
||||
gtk_widget_hide(tree_item->subtree);
|
||||
|
||||
/* hide button '-' and show button '+' */
|
||||
if(tree_item->pixmaps_box) {
|
||||
gtk_container_remove(GTK_CONTAINER(tree_item->pixmaps_box),
|
||||
tree_item->minus_pix_widget);
|
||||
gtk_container_add(GTK_CONTAINER(tree_item->pixmaps_box),
|
||||
tree_item->plus_pix_widget);
|
||||
}
|
||||
if(tree->root_tree) gtk_widget_queue_resize(GTK_WIDGET(tree->root_tree));
|
||||
tree_item->expanded = FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_item_destroy (GtkObject *object)
|
||||
{
|
||||
GtkTreeItem* item;
|
||||
GtkWidget* child;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE_ITEM (object));
|
||||
|
||||
item = GTK_TREE_ITEM(object);
|
||||
|
||||
/* free sub tree if it exist */
|
||||
if((child = item->subtree))
|
||||
{
|
||||
child->parent = NULL;
|
||||
gtk_object_unref (GTK_OBJECT (child));
|
||||
gtk_widget_destroy (child);
|
||||
}
|
||||
|
||||
if (GTK_OBJECT_CLASS (parent_class)->destroy)
|
||||
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
gtk_tree_item_remove_subtree (GtkTreeItem* item)
|
||||
{
|
||||
g_return_if_fail(item != NULL);
|
||||
g_return_if_fail(GTK_IS_TREE_ITEM(item));
|
||||
g_return_if_fail(item->subtree);
|
||||
|
||||
if(GTK_TREE(item->subtree)->children)
|
||||
gtk_tree_remove_items(GTK_TREE(item->subtree),
|
||||
GTK_TREE(item->subtree)->children);
|
||||
|
||||
if (GTK_WIDGET_MAPPED (item->subtree))
|
||||
gtk_widget_unmap (item->subtree);
|
||||
|
||||
gtk_widget_unparent (item->subtree);
|
||||
|
||||
if(item->pixmaps_box)
|
||||
gtk_widget_hide(item->pixmaps_box);
|
||||
|
||||
item->subtree = NULL;
|
||||
item->expanded = FALSE;
|
||||
if(item->pixmaps_box) {
|
||||
gtk_container_remove(GTK_CONTAINER(item->pixmaps_box),
|
||||
item->minus_pix_widget);
|
||||
gtk_container_add(GTK_CONTAINER(item->pixmaps_box),
|
||||
item->plus_pix_widget);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_item_map (GtkWidget *widget)
|
||||
{
|
||||
GtkBin *bin;
|
||||
GtkTreeItem* item;
|
||||
|
||||
g_return_if_fail (widget != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE_ITEM (widget));
|
||||
|
||||
GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
|
||||
bin = GTK_BIN (widget);
|
||||
item = GTK_TREE_ITEM(widget);
|
||||
|
||||
if (!GTK_WIDGET_NO_WINDOW (widget))
|
||||
gdk_window_show (widget->window);
|
||||
else
|
||||
gtk_widget_queue_draw (widget);
|
||||
|
||||
if(item->pixmaps_box &&
|
||||
GTK_WIDGET_VISIBLE (item->pixmaps_box) &&
|
||||
!GTK_WIDGET_MAPPED (item->pixmaps_box))
|
||||
gtk_widget_map (item->pixmaps_box);
|
||||
|
||||
if (bin->child &&
|
||||
GTK_WIDGET_VISIBLE (bin->child) &&
|
||||
!GTK_WIDGET_MAPPED (bin->child))
|
||||
gtk_widget_map (bin->child);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_item_unmap (GtkWidget *widget)
|
||||
{
|
||||
GtkBin *bin;
|
||||
GtkTreeItem* item;
|
||||
|
||||
g_return_if_fail (widget != NULL);
|
||||
g_return_if_fail (GTK_IS_TREE_ITEM (widget));
|
||||
|
||||
GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
|
||||
bin = GTK_BIN (widget);
|
||||
item = GTK_TREE_ITEM(widget);
|
||||
|
||||
if (GTK_WIDGET_NO_WINDOW (widget))
|
||||
gdk_window_clear_area (widget->window,
|
||||
widget->allocation.x,
|
||||
widget->allocation.y,
|
||||
widget->allocation.width,
|
||||
widget->allocation.height);
|
||||
else
|
||||
gdk_window_hide (widget->window);
|
||||
|
||||
if(item->pixmaps_box &&
|
||||
GTK_WIDGET_VISIBLE (item->pixmaps_box) &&
|
||||
GTK_WIDGET_MAPPED (item->pixmaps_box))
|
||||
gtk_widget_unmap (bin->child);
|
||||
|
||||
if (bin->child &&
|
||||
GTK_WIDGET_VISIBLE (bin->child) &&
|
||||
GTK_WIDGET_MAPPED (bin->child))
|
||||
gtk_widget_unmap (bin->child);
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ extern "C" {
|
||||
#define GTK_TREE_ITEM_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_tree_item_get_type (), GtkTreeItemClass)
|
||||
#define GTK_IS_TREE_ITEM(obj) GTK_CHECK_TYPE (obj, gtk_tree_item_get_type ())
|
||||
|
||||
#define GTK_TREE_ITEM_SUBTREE(obj) GTK_TREE_ITEM(obj)->subtree;
|
||||
|
||||
typedef struct _GtkTreeItem GtkTreeItem;
|
||||
typedef struct _GtkTreeItemClass GtkTreeItemClass;
|
||||
@ -40,8 +41,11 @@ struct _GtkTreeItem
|
||||
{
|
||||
GtkItem item;
|
||||
|
||||
GtkWidget *child;
|
||||
GtkWidget *subtree;
|
||||
GtkWidget *pixmaps_box;
|
||||
GtkWidget *plus_pix_widget, *minus_pix_widget;
|
||||
|
||||
guint expanded : 1;
|
||||
};
|
||||
|
||||
struct _GtkTreeItemClass
|
||||
@ -58,6 +62,7 @@ GtkWidget* gtk_tree_item_new (void);
|
||||
GtkWidget* gtk_tree_item_new_with_label (gchar *label);
|
||||
void gtk_tree_item_set_subtree (GtkTreeItem *tree_item,
|
||||
GtkWidget *subtree);
|
||||
void gtk_tree_item_remove_subtree (GtkTreeItem *tree_item);
|
||||
void gtk_tree_item_select (GtkTreeItem *tree_item);
|
||||
void gtk_tree_item_deselect (GtkTreeItem *tree_item);
|
||||
void gtk_tree_item_expand (GtkTreeItem *tree_item);
|
||||
|
231
gtk/testtree.c
Normal file
231
gtk/testtree.c
Normal file
@ -0,0 +1,231 @@
|
||||
#include "gtk.h"
|
||||
|
||||
typedef struct sTreeButtons {
|
||||
GtkWidget *button_add, *button_remove;
|
||||
} sTreeButton;
|
||||
|
||||
static gint cb_delete_event() {
|
||||
return TRUE;
|
||||
}
|
||||
static void cb_destroy_event() {
|
||||
gtk_main_quit();
|
||||
}
|
||||
static void cb_tree_changed(GtkTree* tree) {
|
||||
sTreeButton* tree_buttons;
|
||||
GList* selected;
|
||||
gint nb_selected;
|
||||
|
||||
tree_buttons = gtk_object_get_user_data(GTK_OBJECT(tree));
|
||||
|
||||
selected = tree->selection;
|
||||
nb_selected = g_list_length(selected);
|
||||
|
||||
if(nb_selected == 0) {
|
||||
if(tree->children == NULL)
|
||||
gtk_widget_set_sensitive(tree_buttons->button_add, TRUE);
|
||||
else
|
||||
gtk_widget_set_sensitive(tree_buttons->button_add, FALSE);
|
||||
gtk_widget_set_sensitive(tree_buttons->button_remove, FALSE);
|
||||
} else {
|
||||
gtk_widget_set_sensitive(tree_buttons->button_remove, TRUE);
|
||||
gtk_widget_set_sensitive(tree_buttons->button_add, (nb_selected == 1));
|
||||
}
|
||||
}
|
||||
|
||||
static void add_tree_item(GtkWidget* w, GtkTree* tree) {
|
||||
static gint nb_item_add = 0;
|
||||
GList* selected;
|
||||
gint nb_selected;
|
||||
GtkTreeItem *selected_item;
|
||||
GtkWidget* new_item;
|
||||
GtkWidget* subtree;
|
||||
gchar buffer[255];
|
||||
|
||||
selected = GTK_TREE_SELECTION(tree);
|
||||
nb_selected = g_list_length(selected);
|
||||
|
||||
if(nb_selected > 1) return;
|
||||
|
||||
if(nb_selected == 0 && tree->children != NULL) return;
|
||||
|
||||
if(tree->children == NULL) {
|
||||
subtree = GTK_WIDGET(tree);
|
||||
} else {
|
||||
selected_item = GTK_TREE_ITEM(selected->data);
|
||||
subtree = GTK_TREE_ITEM_SUBTREE(selected_item);
|
||||
}
|
||||
if(!subtree) { /* create a new subtree if not exist */
|
||||
subtree = gtk_tree_new();
|
||||
gtk_signal_connect(GTK_OBJECT(subtree), "selection_changed",
|
||||
(GtkSignalFunc)cb_tree_changed,
|
||||
(gpointer)NULL);
|
||||
gtk_tree_item_set_subtree(GTK_TREE_ITEM(selected_item), subtree);
|
||||
}
|
||||
|
||||
/* create a new item */
|
||||
sprintf(buffer, "new item %d", nb_item_add++);
|
||||
new_item = gtk_tree_item_new_with_label(buffer);
|
||||
gtk_tree_append(GTK_TREE(subtree), new_item);
|
||||
gtk_widget_show(new_item);
|
||||
}
|
||||
|
||||
static void remove_tree_item(GtkWidget* w, GtkTree* tree) {
|
||||
GList* selected, *clear_list;
|
||||
GtkTree* root_tree;
|
||||
|
||||
root_tree = GTK_TREE_ROOT_TREE(tree);
|
||||
selected = GTK_TREE_SELECTION(tree);
|
||||
|
||||
clear_list = NULL;
|
||||
|
||||
while (selected) {
|
||||
clear_list = g_list_prepend (clear_list, selected->data);
|
||||
selected = selected->next;
|
||||
}
|
||||
|
||||
if(clear_list) {
|
||||
clear_list = g_list_reverse (clear_list);
|
||||
gtk_tree_remove_items(root_tree, clear_list);
|
||||
|
||||
selected = clear_list;
|
||||
|
||||
while (selected) {
|
||||
gtk_widget_destroy (GTK_WIDGET (selected->data));
|
||||
selected = selected->next;
|
||||
}
|
||||
|
||||
g_list_free (clear_list);
|
||||
}
|
||||
}
|
||||
|
||||
void create_tree_item(GtkWidget* parent, int level, int nb_item, int level_max) {
|
||||
int i;
|
||||
char buffer[255];
|
||||
GtkWidget *item, *tree;
|
||||
|
||||
for(i = 0; i<nb_item; i++) {
|
||||
|
||||
sprintf(buffer, "item %d-%d", level, i);
|
||||
item = gtk_tree_item_new_with_label(buffer);
|
||||
gtk_tree_append(GTK_TREE(parent), item);
|
||||
gtk_widget_show(item);
|
||||
|
||||
/* g_print("item '%s' : 0x%x\n", buffer, (int)item); */
|
||||
|
||||
if(level < level_max) {
|
||||
tree = gtk_tree_new();
|
||||
|
||||
/* g_print("subtree '%s' : 0x%x\n", buffer, (int)tree); */
|
||||
gtk_signal_connect(GTK_OBJECT(tree), "selection_changed",
|
||||
(GtkSignalFunc)cb_tree_changed,
|
||||
(gpointer)NULL);
|
||||
create_tree_item(tree, level+1, nb_item, level_max);
|
||||
gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), tree);
|
||||
/* gtk_tree_item_expand(GTK_TREE_ITEM(item)); */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void create_tree_page(GtkWidget* parent, GtkSelectionMode mode,
|
||||
char* page_name) {
|
||||
GtkWidget *root, *scrolled_win;
|
||||
GtkWidget *box, *label;
|
||||
GtkWidget *button;
|
||||
sTreeButton* tree_buttons;
|
||||
|
||||
/* create notebook page */
|
||||
box = gtk_vbox_new(FALSE, 5);
|
||||
gtk_container_border_width (GTK_CONTAINER (box), 5);
|
||||
gtk_widget_show (box);
|
||||
|
||||
label = gtk_label_new(page_name);
|
||||
gtk_notebook_append_page(GTK_NOTEBOOK(parent), box, label);
|
||||
|
||||
scrolled_win = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
|
||||
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
||||
gtk_box_pack_start (GTK_BOX (box), scrolled_win, TRUE, TRUE, 0);
|
||||
gtk_widget_set_usize (scrolled_win, 200, 200);
|
||||
gtk_widget_show (scrolled_win);
|
||||
|
||||
root = gtk_tree_new();
|
||||
/* g_print("root: 0x%x\n", (int)root); */
|
||||
gtk_container_add(GTK_CONTAINER(scrolled_win), root);
|
||||
gtk_tree_set_selection_mode(GTK_TREE(root), mode);
|
||||
/* gtk_tree_set_view_mode(GTK_TREE(root), GTK_TREE_VIEW_ITEM); */
|
||||
gtk_signal_connect(GTK_OBJECT(root), "selection_changed",
|
||||
(GtkSignalFunc)cb_tree_changed,
|
||||
(gpointer)NULL);
|
||||
gtk_widget_show(root);
|
||||
|
||||
create_tree_item(root, 1, 3, 3);
|
||||
|
||||
tree_buttons = g_malloc(sizeof(sTreeButton));
|
||||
|
||||
button = gtk_button_new_with_label("Add");
|
||||
gtk_box_pack_start(GTK_BOX (box), button, TRUE, TRUE, 0);
|
||||
gtk_signal_connect(GTK_OBJECT(button), "clicked",
|
||||
(GtkSignalFunc)add_tree_item,
|
||||
(gpointer)root);
|
||||
gtk_widget_set_sensitive(button, FALSE);
|
||||
gtk_widget_show(button);
|
||||
tree_buttons->button_add = button;
|
||||
|
||||
button = gtk_button_new_with_label("Remove");
|
||||
gtk_box_pack_start(GTK_BOX (box), button, TRUE, TRUE, 0);
|
||||
gtk_signal_connect(GTK_OBJECT(button), "clicked",
|
||||
(GtkSignalFunc)remove_tree_item,
|
||||
(gpointer)root);
|
||||
gtk_widget_set_sensitive(button, FALSE);
|
||||
gtk_widget_show(button);
|
||||
tree_buttons->button_remove = button;
|
||||
|
||||
gtk_object_set_user_data(GTK_OBJECT(root), (gpointer)tree_buttons);
|
||||
}
|
||||
|
||||
void main(int argc, char** argv) {
|
||||
GtkWidget* window, *notebook;
|
||||
GtkWidget* box1;
|
||||
GtkWidget* separator;
|
||||
GtkWidget* button;
|
||||
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title(GTK_WINDOW(window), "Test Tree");
|
||||
gtk_signal_connect (GTK_OBJECT (window), "delete_event",
|
||||
(GtkSignalFunc) cb_delete_event, NULL);
|
||||
gtk_signal_connect (GTK_OBJECT (window), "destroy",
|
||||
(GtkSignalFunc) cb_destroy_event, NULL);
|
||||
box1 = gtk_vbox_new(FALSE, 0);
|
||||
gtk_container_add(GTK_CONTAINER(window), box1);
|
||||
gtk_widget_show(box1);
|
||||
|
||||
/* create notebook */
|
||||
notebook = gtk_notebook_new ();
|
||||
gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
|
||||
gtk_box_pack_start (GTK_BOX (box1), notebook, TRUE, TRUE, 0);
|
||||
gtk_widget_show (notebook);
|
||||
|
||||
/* create unique selection page */
|
||||
create_tree_page(notebook, GTK_SELECTION_SINGLE, "Single");
|
||||
create_tree_page(notebook, GTK_SELECTION_BROWSE, "Browse");
|
||||
create_tree_page(notebook, GTK_SELECTION_MULTIPLE, "Multiple");
|
||||
|
||||
separator = gtk_hseparator_new();
|
||||
gtk_box_pack_start(GTK_BOX (box1), separator, TRUE, TRUE, 0);
|
||||
gtk_widget_show (separator);
|
||||
|
||||
button = gtk_button_new_with_label("Close");
|
||||
gtk_box_pack_start(GTK_BOX (box1), button, TRUE, TRUE, 0);
|
||||
gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
|
||||
(GtkSignalFunc)gtk_widget_destroy,
|
||||
GTK_OBJECT(window));
|
||||
gtk_widget_show(button);
|
||||
|
||||
gtk_widget_show(window);
|
||||
|
||||
gtk_main();
|
||||
}
|
5
gtk/tree_minus.xbm
Normal file
5
gtk/tree_minus.xbm
Normal file
@ -0,0 +1,5 @@
|
||||
#define tree_minus_width 9
|
||||
#define tree_minus_height 9
|
||||
static char tree_minus_bits[] = {
|
||||
0xff,0xff,0x01,0xff,0x01,0xff,0x01,0xff,0x7d,0xff,0x01,0xff,0x01,0xff,0x01,
|
||||
0xff,0xff,0xff};
|
18
gtk/tree_minus.xpm
Normal file
18
gtk/tree_minus.xpm
Normal file
@ -0,0 +1,18 @@
|
||||
/* XPM */
|
||||
static char *tree_minus[] = {
|
||||
/* width height num_colors chars_per_pixel */
|
||||
" 9 9 2 1",
|
||||
/* colors */
|
||||
". c #000000",
|
||||
"# c #f8fcf8",
|
||||
/* pixels */
|
||||
".........",
|
||||
".#######.",
|
||||
".#######.",
|
||||
".#######.",
|
||||
".#.....#.",
|
||||
".#######.",
|
||||
".#######.",
|
||||
".#######.",
|
||||
"........."
|
||||
};
|
5
gtk/tree_plus.xbm
Normal file
5
gtk/tree_plus.xbm
Normal file
@ -0,0 +1,5 @@
|
||||
#define tree_plus_width 9
|
||||
#define tree_plus_height 9
|
||||
static char tree_plus_bits[] = {
|
||||
0xff,0xff,0x01,0xff,0x11,0xff,0x11,0xff,0x7d,0xff,0x11,0xff,0x11,0xff,0x01,
|
||||
0xff,0xff,0xff};
|
18
gtk/tree_plus.xpm
Normal file
18
gtk/tree_plus.xpm
Normal file
@ -0,0 +1,18 @@
|
||||
/* XPM */
|
||||
static char *tree_plus[] = {
|
||||
/* width height num_colors chars_per_pixel */
|
||||
" 9 9 2 1",
|
||||
/* colors */
|
||||
". c #000000",
|
||||
"# c #f8fcf8",
|
||||
/* pixels */
|
||||
".........",
|
||||
".#######.",
|
||||
".###.###.",
|
||||
".###.###.",
|
||||
".#.....#.",
|
||||
".###.###.",
|
||||
".###.###.",
|
||||
".#######.",
|
||||
"........."
|
||||
};
|
Reference in New Issue
Block a user