Checked in initial draft of the new tree widget.

2000-10-04    <jrb@redhat.com>

	* gtk/gtk{tree,cell}?*.[ch]: Checked in initial draft of the new
	tree widget.
This commit is contained in:
4 2000-10-05 01:04:57 +00:00 committed by Jonathan Blandford
parent 76806e9a1e
commit 3ff4a2c081
38 changed files with 11465 additions and 0 deletions

View File

@ -1,3 +1,8 @@
2000-10-04 <jrb@redhat.com>
* gtk/gtk{tree,cell}?*.[ch]: Checked in initial draft of the new
tree widget.
2000-10-04 Jonathan Blandford <jrb@redhat.com>
* gdk/gdkwindow.c (gdk_window_draw_arc): Fix obvious bug in circle

View File

@ -1,3 +1,8 @@
2000-10-04 <jrb@redhat.com>
* gtk/gtk{tree,cell}?*.[ch]: Checked in initial draft of the new
tree widget.
2000-10-04 Jonathan Blandford <jrb@redhat.com>
* gdk/gdkwindow.c (gdk_window_draw_arc): Fix obvious bug in circle

View File

@ -1,3 +1,8 @@
2000-10-04 <jrb@redhat.com>
* gtk/gtk{tree,cell}?*.[ch]: Checked in initial draft of the new
tree widget.
2000-10-04 Jonathan Blandford <jrb@redhat.com>
* gdk/gdkwindow.c (gdk_window_draw_arc): Fix obvious bug in circle

View File

@ -1,3 +1,8 @@
2000-10-04 <jrb@redhat.com>
* gtk/gtk{tree,cell}?*.[ch]: Checked in initial draft of the new
tree widget.
2000-10-04 Jonathan Blandford <jrb@redhat.com>
* gdk/gdkwindow.c (gdk_window_draw_arc): Fix obvious bug in circle

View File

@ -1,3 +1,8 @@
2000-10-04 <jrb@redhat.com>
* gtk/gtk{tree,cell}?*.[ch]: Checked in initial draft of the new
tree widget.
2000-10-04 Jonathan Blandford <jrb@redhat.com>
* gdk/gdkwindow.c (gdk_window_draw_arc): Fix obvious bug in circle

View File

@ -1,3 +1,8 @@
2000-10-04 <jrb@redhat.com>
* gtk/gtk{tree,cell}?*.[ch]: Checked in initial draft of the new
tree widget.
2000-10-04 Jonathan Blandford <jrb@redhat.com>
* gdk/gdkwindow.c (gdk_window_draw_arc): Fix obvious bug in circle

View File

@ -1,3 +1,8 @@
2000-10-04 <jrb@redhat.com>
* gtk/gtk{tree,cell}?*.[ch]: Checked in initial draft of the new
tree widget.
2000-10-04 Jonathan Blandford <jrb@redhat.com>
* gdk/gdkwindow.c (gdk_window_draw_arc): Fix obvious bug in circle

268
gtk/gtkcellrenderer.c Normal file
View File

@ -0,0 +1,268 @@
/* gtkcellrenderer.c
* Copyright (C) 2000 Red Hat, Inc. Jonathan Blandford
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "gtkcellrenderer.h"
#ifndef _
#define _(x) x
#endif
static void gtk_cell_renderer_init (GtkCellRenderer *cell);
static void gtk_cell_renderer_class_init (GtkCellRendererClass *class);
static void gtk_cell_renderer_get_param (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec,
const gchar *trailer);
static void gtk_cell_renderer_set_param (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec,
const gchar *trailer);
enum {
PROP_ZERO,
PROP_XALIGN,
PROP_YALIGN,
PROP_XPAD,
PROP_YPAD
};
GtkType
gtk_cell_renderer_get_type (void)
{
static GtkType cell_type = 0;
if (!cell_type)
{
static const GTypeInfo cell_info =
{
sizeof (GtkCellRendererClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gtk_cell_renderer_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GtkCellRenderer),
0,
(GInstanceInitFunc) gtk_cell_renderer_init,
};
cell_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkCellRenderer", &cell_info);
}
return cell_type;
}
static void
gtk_cell_renderer_init (GtkCellRenderer *cell)
{
cell->xpad = 0;
cell->ypad = 0;
cell->xalign = 0.5;
cell->yalign = 0.5;
}
static void
gtk_cell_renderer_class_init (GtkCellRendererClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->get_param = gtk_cell_renderer_get_param;
object_class->set_param = gtk_cell_renderer_set_param;
class->render = NULL;
class->get_size = NULL;
g_object_class_install_param (object_class,
PROP_XALIGN,
g_param_spec_float ("xalign",
_("xalign"),
_("The x-align."),
0.0,
1.0,
0.0,
G_PARAM_READABLE |
G_PARAM_WRITABLE));
g_object_class_install_param (object_class,
PROP_YALIGN,
g_param_spec_float ("yalign",
_("yalign"),
_("The y-align."),
0.0,
1.0,
0.5,
G_PARAM_READABLE |
G_PARAM_WRITABLE));
g_object_class_install_param (object_class,
PROP_XPAD,
g_param_spec_uint ("xpad",
_("xpad"),
_("The xpad."),
0,
100,
2,
G_PARAM_READABLE |
G_PARAM_WRITABLE));
g_object_class_install_param (object_class,
PROP_YPAD,
g_param_spec_uint ("ypad",
_("ypad"),
_("The ypad."),
0,
100,
2,
G_PARAM_READABLE |
G_PARAM_WRITABLE));
}
static void
gtk_cell_renderer_get_param (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec,
const gchar *trailer)
{
GtkCellRenderer *cell = GTK_CELL_RENDERER (object);
switch (param_id)
{
case PROP_XALIGN:
g_value_init (value, G_TYPE_FLOAT);
g_value_set_float (value, cell->xalign);
break;
case PROP_YALIGN:
g_value_init (value, G_TYPE_FLOAT);
g_value_set_float (value, cell->yalign);
break;
case PROP_XPAD:
g_value_init (value, G_TYPE_INT);
g_value_set_float (value, cell->xpad);
break;
case PROP_YPAD:
g_value_init (value, G_TYPE_INT);
g_value_set_float (value, cell->ypad);
break;
default:
break;
}
}
static void
gtk_cell_renderer_set_param (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec,
const gchar *trailer)
{
GtkCellRenderer *cell = GTK_CELL_RENDERER (object);
switch (param_id)
{
case PROP_XALIGN:
cell->xalign = g_value_get_float (value);
break;
case PROP_YALIGN:
cell->yalign = g_value_get_float (value);
break;
case PROP_XPAD:
cell->xpad = g_value_get_int (value);
break;
case PROP_YPAD:
cell->ypad = g_value_get_int (value);
break;
default:
break;
}
}
void
gtk_cell_renderer_get_size (GtkCellRenderer *cell,
GtkWidget *widget,
gint *width,
gint *height)
{
/* It's actually okay to pass in a NULL cell, as we run into that
* a lot */
if (cell == NULL)
return;
g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
g_return_if_fail (GTK_CELL_RENDERER_GET_CLASS (cell)->get_size != NULL);
GTK_CELL_RENDERER_GET_CLASS (cell)->get_size (cell, widget, width, height);
}
void
gtk_cell_renderer_render (GtkCellRenderer *cell,
GdkWindow *window,
GtkWidget *widget,
GdkRectangle *background_area,
GdkRectangle *cell_area,
GdkRectangle *expose_area,
guint flags)
{
/* It's actually okay to pass in a NULL cell, as we run into that
* a lot */
if (cell == NULL)
return;
g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
g_return_if_fail (GTK_CELL_RENDERER_GET_CLASS (cell)->render != NULL);
GTK_CELL_RENDERER_GET_CLASS (cell)->render (cell,
window,
widget,
background_area,
cell_area,
expose_area,
flags);
}
gint
gtk_cell_renderer_event (GtkCellRenderer *cell,
GdkEvent *event,
GtkWidget *widget,
gchar *path,
GdkRectangle *background_area,
GdkRectangle *cell_area,
guint flags)
{
/* It's actually okay to pass in a NULL cell, as we run into that
* a lot */
if (cell == NULL)
return FALSE;
g_return_val_if_fail (GTK_IS_CELL_RENDERER (cell), FALSE);
if (GTK_CELL_RENDERER_GET_CLASS (cell)->event == NULL)
return FALSE;
return GTK_CELL_RENDERER_GET_CLASS (cell)->event (cell,
event,
widget,
path,
background_area,
cell_area,
flags);
}

111
gtk/gtkcellrenderer.h Normal file
View File

@ -0,0 +1,111 @@
/* gtkcellrenderer.h
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GTK_CELL_RENDERER_H__
#define __GTK_CELL_RENDERER_H__
#include <gtk/gtkobject.h>
#include <gtk/gtkwidget.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef enum
{
GTK_CELL_RENDERER_SELECTED = 1 << 0,
GTK_CELL_RENDERER_PRELIT = 1 << 1,
GTK_CELL_RENDERER_INSENSITIVE = 1 << 2
} GtkCellRendererType;
#define GTK_TYPE_CELL_RENDERER (gtk_cell_renderer_get_type ())
#define GTK_CELL_RENDERER(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_CELL_RENDERER, GtkCellRenderer))
#define GTK_CELL_RENDERER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_CELL_RENDERER, GtkCellRendererClass))
#define GTK_IS_CELL_RENDERER(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_CELL_RENDERER))
#define GTK_IS_CELL_RENDERER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), GTK_TYPE_CELL_RENDERER))
#define GTK_CELL_RENDERER_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_CELL_RENDERER, GtkCellRendererClass))
typedef struct _GtkCellRenderer GtkCellRenderer;
typedef struct _GtkCellRendererClass GtkCellRendererClass;
struct _GtkCellRenderer
{
GtkObject parent;
gfloat xalign;
gfloat yalign;
guint16 xpad;
guint16 ypad;
};
struct _GtkCellRendererClass
{
GtkObjectClass parent_class;
/* vtable - not signals */
void (* get_size) (GtkCellRenderer *cell,
GtkWidget *widget,
gint *width,
gint *height);
void (* render) (GtkCellRenderer *cell,
GdkWindow *window,
GtkWidget *widget,
GdkRectangle *background_area,
GdkRectangle *cell_area,
GdkRectangle *expose_area,
guint flags);
gint (* event) (GtkCellRenderer *cell,
GdkEvent *event,
GtkWidget *widget,
gchar *path,
GdkRectangle *background_area,
GdkRectangle *cell_area,
guint flags);
};
GtkType gtk_cell_renderer_get_type (void);
void gtk_cell_renderer_get_size (GtkCellRenderer *cell,
GtkWidget *widget,
gint *width,
gint *height);
void gtk_cell_renderer_render (GtkCellRenderer *cell,
GdkWindow *window,
GtkWidget *widget,
GdkRectangle *background_area,
GdkRectangle *cell_area,
GdkRectangle *expose_area,
guint flags);
gint gtk_cell_renderer_event (GtkCellRenderer *cell,
GdkEvent *event,
GtkWidget *widget,
gchar *path,
GdkRectangle *background_area,
GdkRectangle *cell_area,
guint flags);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_CELL_RENDERER_H__ */

240
gtk/gtkcellrendererpixbuf.c Normal file
View File

@ -0,0 +1,240 @@
/* gtkcellrendererpixbuf.c
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include "gtkcellrendererpixbuf.h"
#ifndef _
#define _(x) x
#endif
static void gtk_cell_renderer_pixbuf_get_param (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec,
const gchar *trailer);
static void gtk_cell_renderer_pixbuf_set_param (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec,
const gchar *trailer);
static void gtk_cell_renderer_pixbuf_init (GtkCellRendererPixbuf *celltext);
static void gtk_cell_renderer_pixbuf_class_init (GtkCellRendererPixbufClass *class);
static void gtk_cell_renderer_pixbuf_get_size (GtkCellRenderer *cell,
GtkWidget *widget,
gint *width,
gint *height);
static void gtk_cell_renderer_pixbuf_render (GtkCellRenderer *cell,
GdkWindow *window,
GtkWidget *widget,
GdkRectangle *background_area,
GdkRectangle *cell_area,
GdkRectangle *expose_area,
guint flags);
enum {
PROP_ZERO,
PROP_PIXBUF
};
GtkType
gtk_cell_renderer_pixbuf_get_type (void)
{
static GtkType cell_pixbuf_type = 0;
if (!cell_pixbuf_type)
{
static const GTypeInfo cell_pixbuf_info =
{
sizeof (GtkCellRendererPixbufClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gtk_cell_renderer_pixbuf_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GtkCellRendererPixbuf),
0, /* n_preallocs */
(GInstanceInitFunc) gtk_cell_renderer_pixbuf_init,
};
cell_pixbuf_type = g_type_register_static (GTK_TYPE_CELL_RENDERER, "GtkCellRendererPixbuf", &cell_pixbuf_info);
}
return cell_pixbuf_type;
}
static void
gtk_cell_renderer_pixbuf_init (GtkCellRendererPixbuf *cellpixbuf)
{
}
static void
gtk_cell_renderer_pixbuf_class_init (GtkCellRendererPixbufClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
object_class->get_param = gtk_cell_renderer_pixbuf_get_param;
object_class->set_param = gtk_cell_renderer_pixbuf_set_param;
cell_class->get_size = gtk_cell_renderer_pixbuf_get_size;
cell_class->render = gtk_cell_renderer_pixbuf_render;
g_object_class_install_param (object_class,
PROP_PIXBUF,
g_param_spec_object ("pixbuf",
_("Pixbuf Object"),
_("The pixbuf to render."),
GDK_TYPE_PIXBUF,
G_PARAM_READABLE |
G_PARAM_WRITABLE));
}
static void
gtk_cell_renderer_pixbuf_get_param (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec,
const gchar *trailer)
{
GtkCellRendererPixbuf *cellpixbuf = GTK_CELL_RENDERER_PIXBUF (object);
switch (param_id)
{
case PROP_PIXBUF:
g_value_init (value, G_TYPE_OBJECT);
g_value_set_object (value, G_OBJECT (cellpixbuf->pixbuf));
break;
default:
break;
}
}
static void
gtk_cell_renderer_pixbuf_set_param (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec,
const gchar *trailer)
{
GdkPixbuf *pixbuf;
GtkCellRendererPixbuf *cellpixbuf = GTK_CELL_RENDERER_PIXBUF (object);
switch (param_id)
{
case PROP_PIXBUF:
pixbuf = GDK_PIXBUF (g_value_get_object (value));
g_object_ref (G_OBJECT (pixbuf));
if (cellpixbuf->pixbuf)
g_object_unref (G_OBJECT (cellpixbuf->pixbuf));
cellpixbuf->pixbuf = pixbuf;
break;
default:
break;
}
}
GtkCellRenderer *
gtk_cell_renderer_pixbuf_new (void)
{
return GTK_CELL_RENDERER (gtk_type_new (gtk_cell_renderer_pixbuf_get_type ()));
}
static void
gtk_cell_renderer_pixbuf_get_size (GtkCellRenderer *cell,
GtkWidget *widget,
gint *width,
gint *height)
{
GtkCellRendererPixbuf *cellpixbuf = (GtkCellRendererPixbuf *) cell;
if (width)
*width = (gint) GTK_CELL_RENDERER (cellpixbuf)->xpad * 2 +
(cellpixbuf->pixbuf ? gdk_pixbuf_get_width (cellpixbuf->pixbuf) : 0);
if (height)
*height = (gint) GTK_CELL_RENDERER (cellpixbuf)->ypad * 2 +
(cellpixbuf->pixbuf ? gdk_pixbuf_get_height (cellpixbuf->pixbuf) : 0);
}
static void
gtk_cell_renderer_pixbuf_render (GtkCellRenderer *cell,
GdkWindow *window,
GtkWidget *widget,
GdkRectangle *background_area,
GdkRectangle *cell_area,
GdkRectangle *expose_area,
guint flags)
{
GtkCellRendererPixbuf *cellpixbuf = (GtkCellRendererPixbuf *) cell;
GdkPixbuf *pixbuf;
guchar *pixels;
gint rowstride;
gint real_xoffset;
gint real_yoffset;
GdkGC *bg_gc = NULL;
pixbuf = cellpixbuf->pixbuf;
if (!pixbuf)
return;
if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED)
bg_gc = widget->style->bg_gc [GTK_STATE_SELECTED];
else
bg_gc = widget->style->base_gc [GTK_STATE_NORMAL];
gdk_gc_set_clip_rectangle (bg_gc, cell_area);
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
pixels = gdk_pixbuf_get_pixels (pixbuf);
real_xoffset = GTK_CELL_RENDERER (cellpixbuf)->xalign * (cell_area->width - gdk_pixbuf_get_width (pixbuf) - (2 * GTK_CELL_RENDERER (cellpixbuf)->xpad));
real_xoffset = MAX (real_xoffset, 0) + GTK_CELL_RENDERER (cellpixbuf)->xpad;
real_yoffset = GTK_CELL_RENDERER (cellpixbuf)->yalign * (cell_area->height - gdk_pixbuf_get_height (pixbuf) - (2 * GTK_CELL_RENDERER (cellpixbuf)->ypad));
real_yoffset = MAX (real_yoffset, 0) + GTK_CELL_RENDERER (cellpixbuf)->ypad;
if (gdk_pixbuf_get_has_alpha (pixbuf))
gdk_draw_rgb_32_image (window,
bg_gc,
cell_area->x + real_xoffset,
cell_area->y + real_yoffset,
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf),
GDK_RGB_DITHER_NORMAL,
pixels,
rowstride);
else
gdk_draw_rgb_image (window,
bg_gc,
cell_area->x + real_xoffset,
cell_area->y + real_yoffset,
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf),
GDK_RGB_DITHER_NORMAL,
pixels,
rowstride);
gdk_gc_set_clip_rectangle (bg_gc, NULL);
}

View File

@ -0,0 +1,58 @@
/* gtkcellrendererpixbuf.h
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GTK_CELL_RENDERER_PIXBUF_H__
#define __GTK_CELL_RENDERER_PIXBUF_H__
#include <gtk/gtkcellrenderer.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GTK_TYPE_CELL_RENDERER_PIXBUF (gtk_cell_renderer_pixbuf_get_type ())
#define GTK_CELL_RENDERER_PIXBUF(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_CELL_RENDERER_PIXBUF, GtkCellRendererPixbuf))
#define GTK_CELL_RENDERER_PIXBUF_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_CELL_RENDERER_PIXBUF, GtkCellRendererPixbufClass))
#define GTK_IS_CELL_RENDERER_PIXBUF(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_CELL_RENDERER_PIXBUF))
#define GTK_IS_CELL_RENDERER_PIXBUF_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), GTK_TYPE_CELL_RENDERER_PIXBUF))
typedef struct _GtkCellRendererPixbuf GtkCellRendererPixbuf;
typedef struct _GtkCellRendererPixbufClass GtkCellRendererPixbufClass;
struct _GtkCellRendererPixbuf
{
GtkCellRenderer parent;
GdkPixbuf *pixbuf;
};
struct _GtkCellRendererPixbufClass
{
GtkCellRendererClass parent_class;
};
GtkType gtk_cell_renderer_pixbuf_get_type (void);
GtkCellRenderer *gtk_cell_renderer_pixbuf_new (void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_CELL_RENDERER_PIXBUF_H__ */

449
gtk/gtkcellrenderertext.c Normal file
View File

@ -0,0 +1,449 @@
/* gtkcellrenderertext.c
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include "gtkcellrenderertext.h"
#ifndef _
#define _(x) x
#endif
static void gtk_cell_renderer_text_init (GtkCellRendererText *celltext);
static void gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class);
static void gtk_cell_renderer_text_get_param (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec,
const gchar *trailer);
static void gtk_cell_renderer_text_set_param (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec,
const gchar *trailer);
static void gtk_cell_renderer_text_get_size (GtkCellRenderer *cell,
GtkWidget *widget,
gint *width,
gint *height);
static void gtk_cell_renderer_text_render (GtkCellRenderer *cell,
GdkWindow *window,
GtkWidget *widget,
GdkRectangle *background_area,
GdkRectangle *cell_area,
GdkRectangle *expose_area,
guint flags);
enum {
PROP_ZERO,
PROP_TEXT,
PROP_FONT,
PROP_BACKGROUND,
PROP_BACKGROUND_GDK,
PROP_FOREGROUND,
PROP_FOREGROUND_GDK,
PROP_STRIKETHROUGH,
PROP_UNDERLINE,
PROP_EDITABLE,
PROP_ITALIC,
PROP_BOLD
};
GtkType
gtk_cell_renderer_text_get_type (void)
{
static GtkType cell_text_type = 0;
if (!cell_text_type)
{
static const GTypeInfo cell_text_info =
{
sizeof (GtkCellRendererTextClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gtk_cell_renderer_text_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GtkCellRendererText),
0, /* n_preallocs */
(GInstanceInitFunc) gtk_cell_renderer_text_init,
};
cell_text_type = g_type_register_static (GTK_TYPE_CELL_RENDERER, "GtkCellRendererText", &cell_text_info);
}
return cell_text_type;
}
static void
gtk_cell_renderer_text_init (GtkCellRendererText *celltext)
{
celltext->attr_list = pango_attr_list_new ();
GTK_CELL_RENDERER (celltext)->xalign = 0.0;
GTK_CELL_RENDERER (celltext)->yalign = 0.5;
GTK_CELL_RENDERER (celltext)->xpad = 2;
GTK_CELL_RENDERER (celltext)->ypad = 2;
celltext->underline = FALSE;
}
static void
gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
object_class->get_param = gtk_cell_renderer_text_get_param;
object_class->set_param = gtk_cell_renderer_text_set_param;
cell_class->get_size = gtk_cell_renderer_text_get_size;
cell_class->render = gtk_cell_renderer_text_render;
g_object_class_install_param (object_class,
PROP_TEXT,
g_param_spec_string ("text",
_("Text String"),
_("The text of the renderer."),
"",
G_PARAM_READABLE |
G_PARAM_WRITABLE));
g_object_class_install_param (object_class,
PROP_FONT,
g_param_spec_string ("font",
_("Font String"),
_("The string of the font."),
"",
G_PARAM_WRITABLE));
g_object_class_install_param (object_class,
PROP_BACKGROUND,
g_param_spec_string ("background",
_("Background Color string"),
_("The color for the background of the text."),
"white",
G_PARAM_WRITABLE));
g_object_class_install_param (object_class,
PROP_FOREGROUND,
g_param_spec_string ("foreground",
_("Foreground Color string"),
_("The color for the background of the text."),
"black",
G_PARAM_WRITABLE));
g_object_class_install_param (object_class,
PROP_STRIKETHROUGH,
g_param_spec_boolean ("strikethrough",
_("Strikethrough"),
_("Draw a line through the text."),
FALSE,
G_PARAM_READABLE |
G_PARAM_WRITABLE));
g_object_class_install_param (object_class,
PROP_UNDERLINE,
g_param_spec_boolean ("underline",
_("Underline"),
_("Underline the text."),
FALSE,
G_PARAM_READABLE |
G_PARAM_WRITABLE));
g_object_class_install_param (object_class,
PROP_EDITABLE,
g_param_spec_boolean ("editable",
_("Editable"),
_("Make the text editable."),
FALSE,
G_PARAM_READABLE |
G_PARAM_WRITABLE));
g_object_class_install_param (object_class,
PROP_ITALIC,
g_param_spec_boolean ("italic",
_("Italic"),
_("Make the text italic."),
FALSE,
G_PARAM_WRITABLE));
g_object_class_install_param (object_class,
PROP_BOLD,
g_param_spec_boolean ("bold",
_("Bold"),
_("Make the text bold."),
FALSE,
G_PARAM_WRITABLE));
}
static void
gtk_cell_renderer_text_get_param (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec,
const gchar *trailer)
{
GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (object);
PangoAttrIterator *attr_iter;
PangoAttribute *attr;
switch (param_id)
{
case PROP_TEXT:
g_value_init (value, G_TYPE_STRING);
g_value_set_string (value, celltext->text);
break;
case PROP_STRIKETHROUGH:
g_value_init (value, G_TYPE_BOOLEAN);
attr_iter = pango_attr_list_get_iterator (celltext->attr_list);
attr = pango_attr_iterator_get (attr_iter,
PANGO_ATTR_STRIKETHROUGH);
g_value_set_boolean (value, ((PangoAttrInt*) attr)->value);
break;
case PROP_UNDERLINE:
g_value_init (value, G_TYPE_BOOLEAN);
g_value_set_boolean (value, celltext->underline);
break;
case PROP_EDITABLE:
g_value_init (value, G_TYPE_BOOLEAN);
g_value_set_boolean (value, celltext->editable);
break;
default:
break;
}
}
static void
gtk_cell_renderer_text_set_param (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec,
const gchar *trailer)
{
GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (object);
GdkColor color;
PangoFontDescription *font_desc;
gchar *string;
PangoAttribute *attribute;
gchar *font;
switch (param_id)
{
case PROP_TEXT:
g_free (celltext->text);
celltext->text = g_value_dup_string (value);
break;
case PROP_FONT:
font = g_value_get_string (value);
if (font)
{
font_desc = pango_font_description_from_string (font);
attribute = pango_attr_font_desc_new (font_desc);
attribute->start_index = 0;
attribute->end_index = G_MAXINT;
pango_font_description_free (font_desc);
pango_attr_list_change (celltext->attr_list,
attribute);
}
break;
case PROP_BACKGROUND:
string = g_value_get_string (value);
if (string && gdk_color_parse (string, &color))
{
attribute = pango_attr_background_new (color.red,
color.green,
color.blue);
attribute->start_index = 0;
attribute->end_index = G_MAXINT;
pango_attr_list_change (celltext->attr_list,
attribute);
}
break;
case PROP_BACKGROUND_GDK:
break;
case PROP_FOREGROUND:
string = g_value_get_string (value);
if (string && gdk_color_parse (string, &color))
{
attribute = pango_attr_foreground_new (color.red,
color.green,
color.blue);
attribute->start_index = 0;
attribute->end_index = G_MAXINT;
pango_attr_list_change (celltext->attr_list,
attribute);
}
break;
case PROP_FOREGROUND_GDK:
break;
case PROP_STRIKETHROUGH:
attribute = pango_attr_strikethrough_new (g_value_get_boolean (value));
attribute->start_index = 0;
attribute->end_index = G_MAXINT;
pango_attr_list_change (celltext->attr_list,
attribute);
break;
case PROP_UNDERLINE:
celltext->underline = g_value_get_boolean (value);
attribute = pango_attr_underline_new (celltext->underline ?
PANGO_UNDERLINE_SINGLE :
PANGO_UNDERLINE_NONE);
attribute->start_index = 0;
attribute->end_index = G_MAXINT;
pango_attr_list_change (celltext->attr_list,
attribute);
break;
case PROP_EDITABLE:
break;
case PROP_ITALIC:
attribute = pango_attr_style_new (g_value_get_boolean (value) ?
PANGO_STYLE_ITALIC :
PANGO_STYLE_NORMAL);
attribute->start_index = 0;
attribute->end_index = G_MAXINT;
pango_attr_list_change (celltext->attr_list,
attribute);
break;
case PROP_BOLD:
attribute = pango_attr_weight_new (g_value_get_boolean (value) ?
PANGO_WEIGHT_BOLD :
PANGO_WEIGHT_NORMAL);
attribute->start_index = 0;
attribute->end_index = G_MAXINT;
pango_attr_list_change (celltext->attr_list,
attribute);
break;
default:
break;
}
}
GtkCellRenderer *
gtk_cell_renderer_text_new (void)
{
return GTK_CELL_RENDERER (gtk_type_new (gtk_cell_renderer_text_get_type ()));
}
static void
gtk_cell_renderer_text_get_size (GtkCellRenderer *cell,
GtkWidget *widget,
gint *width,
gint *height)
{
GtkCellRendererText *celltext = (GtkCellRendererText *)cell;
PangoRectangle rect;
PangoLayout *layout;
PangoAttribute *attr;
PangoUnderline underline;
layout = gtk_widget_create_pango_layout (widget, celltext->text);
underline = celltext->underline ?
PANGO_UNDERLINE_DOUBLE :
PANGO_UNDERLINE_NONE;
attr = pango_attr_underline_new (underline);
attr->start_index = 0;
attr->end_index = G_MAXINT;
pango_attr_list_change (celltext->attr_list, attr);
pango_layout_set_attributes (layout, celltext->attr_list);
pango_layout_set_width (layout, -1);
pango_layout_get_pixel_extents (layout, NULL, &rect);
if (width)
*width = GTK_CELL_RENDERER (celltext)->xpad * 2 + rect.width;
if (height)
*height = GTK_CELL_RENDERER (celltext)->ypad * 2 + rect.height;
g_object_unref (G_OBJECT (layout));
}
static void
gtk_cell_renderer_text_render (GtkCellRenderer *cell,
GdkWindow *window,
GtkWidget *widget,
GdkRectangle *background_area,
GdkRectangle *cell_area,
GdkRectangle *expose_area,
guint flags)
{
GtkCellRendererText *celltext = (GtkCellRendererText *) cell;
PangoRectangle rect;
PangoLayout *layout;
PangoAttribute *attr;
PangoUnderline underline;
gint real_xoffset;
gint real_yoffset;
GdkGC *font_gc = NULL;
if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED)
font_gc = widget->style->fg_gc [GTK_STATE_SELECTED];
else
font_gc = widget->style->fg_gc [GTK_STATE_NORMAL];
layout = gtk_widget_create_pango_layout (widget, celltext->text);
if (celltext->underline)
underline = PANGO_UNDERLINE_SINGLE;
else
underline = PANGO_UNDERLINE_NONE;
attr = pango_attr_underline_new (underline);
attr->start_index = 0;
attr->end_index = G_MAXINT;
pango_attr_list_change (celltext->attr_list, attr);
pango_layout_set_attributes (layout, celltext->attr_list);
pango_layout_set_width (layout, -1);
pango_layout_get_pixel_extents (layout, NULL, &rect);
if ((flags & GTK_CELL_RENDERER_PRELIT) == GTK_CELL_RENDERER_PRELIT)
underline = (celltext->underline) ? PANGO_UNDERLINE_DOUBLE:PANGO_UNDERLINE_SINGLE;
else
underline = (celltext->underline) ? PANGO_UNDERLINE_SINGLE:PANGO_UNDERLINE_NONE;
attr = pango_attr_underline_new (underline);
attr->start_index = 0;
attr->end_index = G_MAXINT;
pango_attr_list_change (celltext->attr_list, attr);
pango_layout_set_attributes (layout, celltext->attr_list);
gdk_gc_set_clip_rectangle (font_gc, cell_area);
real_xoffset = cell->xalign * (cell_area->width - rect.width - (2 * cell->xpad));
real_xoffset = MAX (real_xoffset, 0) + cell->xpad;
real_yoffset = cell->yalign * (cell_area->height - rect.height - (2 * cell->ypad));
real_yoffset = MAX (real_yoffset, 0) + cell->ypad;
gdk_draw_layout (window,
font_gc,
cell_area->x + real_xoffset,
cell_area->y + real_yoffset,
layout);
g_object_unref (G_OBJECT (layout));
gdk_gc_set_clip_rectangle (font_gc, NULL);
}

65
gtk/gtkcellrenderertext.h Normal file
View File

@ -0,0 +1,65 @@
/* gtkcellrenderertext.h
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GTK_CELL_RENDERER_TEXT_H__
#define __GTK_CELL_RENDERER_TEXT_H__
#include <pango/pango.h>
#include <gtk/gtkcellrenderer.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GTK_TYPE_CELL_RENDERER_TEXT (gtk_cell_renderer_text_get_type ())
#define GTK_CELL_RENDERER_TEXT(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_CELL_RENDERER_TEXT, GtkCellRendererText))
#define GTK_CELL_RENDERER_TEXT_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_CELL_RENDERER_TEXT, GtkCellRendererTextClass))
#define GTK_IS_CELL_RENDERER_TEXT(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_CELL_RENDERER_TEXT))
#define GTK_IS_CELL_RENDERER_TEXT_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), GTK_TYPE_CELL_RENDERER_TEXT))
typedef struct _GtkCellRendererText GtkCellRendererText;
typedef struct _GtkCellRendererTextClass GtkCellRendererTextClass;
struct _GtkCellRendererText
{
GtkCellRenderer parent;
/*< private >*/
gchar *text;
PangoAttrList *attr_list;
guint editable : 1;
guint underline : 1;
};
struct _GtkCellRendererTextClass
{
GtkCellRendererClass parent_class;
};
GtkType gtk_cell_renderer_text_get_type (void);
GtkCellRenderer *gtk_cell_renderer_text_new (void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_CELL_RENDERER_TEXT_H__ */

View File

@ -0,0 +1,399 @@
/* gtkcellrenderertextpixbuf.c
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include "gtkcellrenderertextpixbuf.h"
#ifndef _
#define _(x) x
#endif
enum {
PROP_ZERO,
PROP_PIXBUF_POS,
PROP_PIXBUF,
PROP_PIXBUF_XALIGN,
PROP_PIXBUF_YALIGN,
PROP_PIXBUF_XPAD,
PROP_PIXBUF_YPAD
};
static void gtk_cell_renderer_text_pixbuf_get_param (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec,
const gchar *trailer);
static void gtk_cell_renderer_text_pixbuf_set_param (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec,
const gchar *trailer);
static void gtk_cell_renderer_text_pixbuf_init (GtkCellRendererTextPixbuf *celltextpixbuf);
static void gtk_cell_renderer_text_pixbuf_class_init (GtkCellRendererTextPixbufClass *class);
static void gtk_cell_renderer_text_pixbuf_get_size (GtkCellRenderer *cell,
GtkWidget *view,
gint *width,
gint *height);
static void gtk_cell_renderer_text_pixbuf_render (GtkCellRenderer *cell,
GdkWindow *window,
GtkWidget *view,
GdkRectangle *background_area,
GdkRectangle *cell_area,
GdkRectangle *expose_area,
guint flags);
GtkCellRendererTextClass *parent_class = NULL;
GtkType
gtk_cell_renderer_text_pixbuf_get_type (void)
{
static GtkType cell_text_pixbuf_type = 0;
if (!cell_text_pixbuf_type)
{
static const GTypeInfo cell_text_pixbuf_info =
{
sizeof (GtkCellRendererTextPixbufClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gtk_cell_renderer_text_pixbuf_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GtkCellRendererTextPixbuf),
0, /* n_preallocs */
(GInstanceInitFunc) gtk_cell_renderer_text_pixbuf_init,
};
cell_text_pixbuf_type = g_type_register_static (GTK_TYPE_CELL_RENDERER_TEXT, "GtkCellRendererTextPixbuf", &cell_text_pixbuf_info);
}
return cell_text_pixbuf_type;
}
static void
gtk_cell_renderer_text_pixbuf_init (GtkCellRendererTextPixbuf *celltextpixbuf)
{
celltextpixbuf->pixbuf = GTK_CELL_RENDERER_PIXBUF (gtk_cell_renderer_pixbuf_new ());
celltextpixbuf->pixbuf_pos = GTK_POS_LEFT;
}
static void
gtk_cell_renderer_text_pixbuf_class_init (GtkCellRendererTextPixbufClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
parent_class = g_type_class_peek_parent (class);
object_class->get_param = gtk_cell_renderer_text_pixbuf_get_param;
object_class->set_param = gtk_cell_renderer_text_pixbuf_set_param;
cell_class->get_size = gtk_cell_renderer_text_pixbuf_get_size;
cell_class->render = gtk_cell_renderer_text_pixbuf_render;
g_object_class_install_param (object_class,
PROP_PIXBUF_POS,
g_param_spec_int ("pixbufpos",
_("Pixbuf location"),
_("The relative location of the pixbuf to the text."),
GTK_POS_LEFT,
GTK_POS_BOTTOM,
GTK_POS_LEFT,
G_PARAM_READABLE |
G_PARAM_WRITABLE));
g_object_class_install_param (object_class,
PROP_PIXBUF,
g_param_spec_object ("pixbuf",
_("Pixbuf Object"),
_("The pixbuf to render."),
GDK_TYPE_PIXBUF,
G_PARAM_READABLE |
G_PARAM_WRITABLE));
g_object_class_install_param (object_class,
PROP_PIXBUF_XALIGN,
g_param_spec_float ("pixbuf xalign",
_("pixbuf xalign"),
_("The x-align of the pixbuf."),
0.0,
1.0,
0.0,
G_PARAM_READABLE |
G_PARAM_WRITABLE));
g_object_class_install_param (object_class,
PROP_PIXBUF_YALIGN,
g_param_spec_float ("pixbuf yalign",
_("pixbuf yalign"),
_("The y-align of the pixbuf."),
0.0,
1.0,
0.5,
G_PARAM_READABLE |
G_PARAM_WRITABLE));
g_object_class_install_param (object_class,
PROP_PIXBUF_XPAD,
g_param_spec_uint ("pixbuf xpad",
_("pixbuf xpad"),
_("The xpad of the pixbuf."),
0,
100,
2,
G_PARAM_READABLE |
G_PARAM_WRITABLE));
g_object_class_install_param (object_class,
PROP_PIXBUF_YPAD,
g_param_spec_uint ("pixbuf ypad",
_("pixbuf ypad"),
_("The ypad of the pixbuf."),
0,
100,
2,
G_PARAM_READABLE |
G_PARAM_WRITABLE));
}
static void
gtk_cell_renderer_text_pixbuf_get_param (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec,
const gchar *trailer)
{
GtkCellRendererTextPixbuf *celltextpixbuf = GTK_CELL_RENDERER_TEXT_PIXBUF (object);
switch (param_id)
{
case PROP_PIXBUF_POS:
g_value_set_int (value, celltextpixbuf->pixbuf_pos);
break;
case PROP_PIXBUF:
g_object_get_param (G_OBJECT (celltextpixbuf->pixbuf),
"pixbuf",
value);
break;
case PROP_PIXBUF_XALIGN:
g_object_get_param (G_OBJECT (celltextpixbuf->pixbuf),
"xalign",
value);
break;
case PROP_PIXBUF_YALIGN:
g_object_get_param (G_OBJECT (celltextpixbuf->pixbuf),
"yalign",
value);
break;
case PROP_PIXBUF_XPAD:
g_object_get_param (G_OBJECT (celltextpixbuf->pixbuf),
"xpad",
value);
break;
case PROP_PIXBUF_YPAD:
g_object_get_param (G_OBJECT (celltextpixbuf->pixbuf),
"ypad",
value);
break;
default:
break;
}
}
static void
gtk_cell_renderer_text_pixbuf_set_param (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec,
const gchar *trailer)
{
GtkCellRendererTextPixbuf *celltextpixbuf = GTK_CELL_RENDERER_TEXT_PIXBUF (object);
switch (param_id)
{
case PROP_PIXBUF:
g_object_set_param (G_OBJECT (celltextpixbuf->pixbuf),
"pixbuf",
value);
break;
case PROP_PIXBUF_POS:
celltextpixbuf->pixbuf_pos = g_value_get_int (value);
break;
case PROP_PIXBUF_XALIGN:
g_object_set_param (G_OBJECT (celltextpixbuf->pixbuf),
"xalign",
value);
break;
case PROP_PIXBUF_YALIGN:
g_object_set_param (G_OBJECT (celltextpixbuf->pixbuf),
"yalign",
value);
break;
case PROP_PIXBUF_XPAD:
g_object_set_param (G_OBJECT (celltextpixbuf->pixbuf),
"xpad",
value);
break;
case PROP_PIXBUF_YPAD:
g_object_set_param (G_OBJECT (celltextpixbuf->pixbuf),
"ypad",
value);
break;
default:
break;
}
}
GtkCellRenderer *
gtk_cell_renderer_text_pixbuf_new (void)
{
return GTK_CELL_RENDERER (gtk_type_new (gtk_cell_renderer_text_pixbuf_get_type ()));
}
typedef void (* CellSizeFunc) (GtkCellRenderer *cell,
GtkWidget *widget,
gint *width,
gint *height);
typedef void (* CellRenderFunc) (GtkCellRenderer *cell,
GdkWindow *window,
GtkWidget *widget,
GdkRectangle *background_area,
GdkRectangle *cell_area,
GdkRectangle *expose_area,
guint flags);
static void
gtk_cell_renderer_text_pixbuf_get_size (GtkCellRenderer *cell,
GtkWidget *widget,
gint *width,
gint *height)
{
GtkCellRendererTextPixbuf *celltextpixbuf = (GtkCellRendererTextPixbuf *)cell;
gint pixbuf_width;
gint pixbuf_height;
gint text_width;
gint text_height;
(* GTK_CELL_RENDERER_CLASS (parent_class)->get_size) (cell, widget, &text_width, &text_height);
(* GTK_CELL_RENDERER_CLASS (G_OBJECT_GET_CLASS (celltextpixbuf->pixbuf))->get_size) (GTK_CELL_RENDERER (celltextpixbuf->pixbuf),
widget,
&pixbuf_width,
&pixbuf_height);
if (celltextpixbuf->pixbuf_pos == GTK_POS_LEFT ||
celltextpixbuf->pixbuf_pos == GTK_POS_RIGHT)
{
*width = pixbuf_width + text_width;
*height = MAX (pixbuf_height, text_height);
}
else
{
*width = MAX (pixbuf_width, text_width);
*height = pixbuf_height + text_height;
}
}
static void
gtk_cell_renderer_text_pixbuf_render (GtkCellRenderer *cell,
GdkWindow *window,
GtkWidget *widget,
GdkRectangle *background_area,
GdkRectangle *cell_area,
GdkRectangle *expose_area,
guint flags)
{
GtkCellRendererTextPixbuf *celltextpixbuf = (GtkCellRendererTextPixbuf *) cell;
CellSizeFunc size_func1, size_func2;
CellRenderFunc render_func1, render_func2;
GtkCellRenderer *cell1, *cell2;
gint tmp_width;
gint tmp_height;
GdkRectangle real_cell_area;
if (celltextpixbuf->pixbuf_pos == GTK_POS_LEFT ||
celltextpixbuf->pixbuf_pos == GTK_POS_TOP)
{
size_func1 = GTK_CELL_RENDERER_CLASS (G_OBJECT_GET_CLASS (celltextpixbuf->pixbuf))->get_size;
render_func1 = GTK_CELL_RENDERER_CLASS (G_OBJECT_GET_CLASS (celltextpixbuf->pixbuf))->render;
cell1 = GTK_CELL_RENDERER (celltextpixbuf->pixbuf);
size_func2 = GTK_CELL_RENDERER_CLASS (parent_class)->get_size;
render_func2 = GTK_CELL_RENDERER_CLASS (parent_class)->render;
cell2 = cell;
}
else
{
size_func1 = GTK_CELL_RENDERER_CLASS (parent_class)->get_size;
render_func1 = GTK_CELL_RENDERER_CLASS (parent_class)->render;
cell1 = cell;
size_func2 = GTK_CELL_RENDERER_CLASS (G_OBJECT_GET_CLASS (celltextpixbuf->pixbuf))->get_size;
render_func2 = GTK_CELL_RENDERER_CLASS (G_OBJECT_GET_CLASS (celltextpixbuf->pixbuf))->render;
cell2 = GTK_CELL_RENDERER (celltextpixbuf->pixbuf);
}
(size_func1) (cell1, widget, &tmp_width, &tmp_height);
real_cell_area.x = cell_area->x;
real_cell_area.y = cell_area->y;
if (celltextpixbuf->pixbuf_pos == GTK_POS_LEFT ||
celltextpixbuf->pixbuf_pos == GTK_POS_RIGHT)
{
real_cell_area.width = MIN (tmp_width, cell_area->width);
real_cell_area.height = cell_area->height;
}
else
{
real_cell_area.height = MIN (tmp_height, cell_area->height);
real_cell_area.width = cell_area->width;
}
(render_func1) (cell1,
window,
widget,
background_area,
&real_cell_area,
expose_area,
flags);
if (celltextpixbuf->pixbuf_pos == GTK_POS_LEFT ||
celltextpixbuf->pixbuf_pos == GTK_POS_RIGHT)
{
real_cell_area.x = real_cell_area.x + real_cell_area.width;
real_cell_area.width = cell_area->width - real_cell_area.width;
}
else
{
real_cell_area.y = real_cell_area.y + real_cell_area.height;
real_cell_area.height = cell_area->height - real_cell_area.height;
}
(render_func2 ) (cell2,
window,
widget,
background_area,
&real_cell_area,
expose_area,
flags);
}

View File

@ -0,0 +1,61 @@
/* gtkcellrenderertextpixbuf.h
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GTK_CELL_RENDERER_TEXT_PIXBUF_H__
#define __GTK_CELL_RENDERER_TEXT_PIXBUF_H__
#include <gtk/gtkcellrenderertext.h>
#include <gtk/gtkcellrendererpixbuf.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GTK_TYPE_CELL_RENDERER_TEXT_PIXBUF (gtk_cell_renderer_text_pixbuf_get_type ())
#define GTK_CELL_RENDERER_TEXT_PIXBUF(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_CELL_RENDERER_TEXT_PIXBUF, GtkCellRendererTextPixbuf))
#define GTK_CELL_RENDERER_TEXT_PIXBUF_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_CELL_RENDERER_TEXT_PIXBUF, GtkCellRendererTextPixbufClass))
#define GTK_IS_CELL_RENDERER_TEXT_PIXBUF(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_CELL_RENDERER_TEXT_PIXBUF))
#define GTK_IS_CELL_RENDERER_TEXT_PIXBUF_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), GTK_TYPE_CELL_RENDERER_TEXT_PIXBUF))
typedef struct _GtkCellRendererTextPixbuf GtkCellRendererTextPixbuf;
typedef struct _GtkCellRendererTextPixbufClass GtkCellRendererTextPixbufClass;
struct _GtkCellRendererTextPixbuf
{
GtkCellRendererText parent;
/*< private >*/
GtkCellRendererPixbuf *pixbuf;
GtkPositionType pixbuf_pos;
};
struct _GtkCellRendererTextPixbufClass
{
GtkCellRendererTextClass parent_class;
};
GtkType gtk_cell_renderer_text_pixbuf_get_type (void);
GtkCellRenderer *gtk_cell_renderer_text_pixbuf_new (void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_CELL_RENDERER_TEXT_PIXBUF_H__ */

321
gtk/gtkcellrenderertoggle.c Normal file
View File

@ -0,0 +1,321 @@
/* gtkcellrenderertoggle.c
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <gtk/gtkcellrenderertoggle.h>
#include <gtk/gtksignal.h>
#ifndef _
#define _(x) x
#endif
static void gtk_cell_renderer_toggle_get_param (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec,
const gchar *trailer);
static void gtk_cell_renderer_toggle_set_param (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec,
const gchar *trailer);
static void gtk_cell_renderer_toggle_init (GtkCellRendererToggle *celltext);
static void gtk_cell_renderer_toggle_class_init (GtkCellRendererToggleClass *class);
static void gtk_cell_renderer_toggle_get_size (GtkCellRenderer *cell,
GtkWidget *widget,
gint *width,
gint *height);
static void gtk_cell_renderer_toggle_render (GtkCellRenderer *cell,
GdkWindow *window,
GtkWidget *widget,
GdkRectangle *background_area,
GdkRectangle *cell_area,
GdkRectangle *expose_area,
guint flags);
static gint gtk_cell_renderer_toggle_event (GtkCellRenderer *cell,
GdkEvent *event,
GtkWidget *widget,
gchar *path,
GdkRectangle *background_area,
GdkRectangle *cell_area,
guint flags);
enum {
TOGGLED,
LAST_SIGNAL
};
enum {
PROP_ZERO,
PROP_STATE,
PROP_RADIO
};
#define TOGGLE_WIDTH 12
static guint toggle_cell_signals[LAST_SIGNAL] = { 0 };
GtkType
gtk_cell_renderer_toggle_get_type (void)
{
static GtkType cell_toggle_type = 0;
if (!cell_toggle_type)
{
static const GTypeInfo cell_toggle_info =
{
sizeof (GtkCellRendererToggleClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gtk_cell_renderer_toggle_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GtkCellRendererToggle),
0, /* n_preallocs */
(GInstanceInitFunc) gtk_cell_renderer_toggle_init,
};
cell_toggle_type = g_type_register_static (GTK_TYPE_CELL_RENDERER, "GtkCellRendererToggle", &cell_toggle_info);
}
return cell_toggle_type;
}
static void
gtk_cell_renderer_toggle_init (GtkCellRendererToggle *celltoggle)
{
celltoggle->state = FALSE;
celltoggle->radio = FALSE;
GTK_CELL_RENDERER (celltoggle)->xpad = 2;
GTK_CELL_RENDERER (celltoggle)->ypad = 2;
}
static void
gtk_cell_renderer_toggle_class_init (GtkCellRendererToggleClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
object_class->get_param = gtk_cell_renderer_toggle_get_param;
object_class->set_param = gtk_cell_renderer_toggle_set_param;
cell_class->get_size = gtk_cell_renderer_toggle_get_size;
cell_class->render = gtk_cell_renderer_toggle_render;
cell_class->event = gtk_cell_renderer_toggle_event;
g_object_class_install_param (object_class,
PROP_STATE,
g_param_spec_boolean ("state",
_("Toggle state"),
_("The toggle-state of the button."),
FALSE,
G_PARAM_READABLE |
G_PARAM_WRITABLE));
g_object_class_install_param (object_class,
PROP_RADIO,
g_param_spec_boolean ("radio",
_("Radio state"),
_("Draw the toggle button as a radio button."),
FALSE,
G_PARAM_READABLE |
G_PARAM_WRITABLE));
toggle_cell_signals[TOGGLED] =
gtk_signal_new ("toggled",
GTK_RUN_LAST,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkCellRendererToggleClass, toggled),
gtk_marshal_NONE__POINTER,
GTK_TYPE_NONE, 1,
GTK_TYPE_POINTER);
gtk_object_class_add_signals (GTK_OBJECT_CLASS (object_class), toggle_cell_signals, LAST_SIGNAL);
}
static void
gtk_cell_renderer_toggle_get_param (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec,
const gchar *trailer)
{
GtkCellRendererToggle *celltoggle = GTK_CELL_RENDERER_TOGGLE (object);
switch (param_id)
{
case PROP_STATE:
g_value_init (value, G_TYPE_BOOLEAN);
g_value_set_boolean (value, celltoggle->state);
break;
case PROP_RADIO:
g_value_init (value, G_TYPE_BOOLEAN);
g_value_set_boolean (value, celltoggle->radio);
break;
default:
break;
}
}
static void
gtk_cell_renderer_toggle_set_param (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec,
const gchar *trailer)
{
GtkCellRendererToggle *celltoggle = GTK_CELL_RENDERER_TOGGLE (object);
switch (param_id)
{
case PROP_STATE:
celltoggle->state = g_value_get_boolean (value);
break;
case PROP_RADIO:
celltoggle->radio = g_value_get_boolean (value);
break;
default:
break;
}
}
GtkCellRenderer *
gtk_cell_renderer_toggle_new (void)
{
return GTK_CELL_RENDERER (gtk_type_new (gtk_cell_renderer_toggle_get_type ()));
}
static void
gtk_cell_renderer_toggle_get_size (GtkCellRenderer *cell,
GtkWidget *widget,
gint *width,
gint *height)
{
if (width)
*width = (gint) cell->xpad * 2 + TOGGLE_WIDTH;
if (height)
*height = (gint) cell->ypad * 2 + TOGGLE_WIDTH;
}
static void
gtk_cell_renderer_toggle_render (GtkCellRenderer *cell,
GdkWindow *window,
GtkWidget *widget,
GdkRectangle *background_area,
GdkRectangle *cell_area,
GdkRectangle *expose_area,
guint flags)
{
GtkCellRendererToggle *celltoggle = (GtkCellRendererToggle *) cell;
gint width, height;
gint real_xoffset, real_yoffset;
width = MIN (TOGGLE_WIDTH, cell_area->width - cell->xpad * 2);
height = MIN (TOGGLE_WIDTH, cell_area->height - cell->ypad * 2);
if (width <= 0 || height <= 0)
return;
real_xoffset = cell->xalign * (cell_area->width - width - (2 * cell->xpad));
real_xoffset = MAX (real_xoffset, 0) + cell->xpad;
real_yoffset = cell->yalign * (cell_area->height - height - (2 * cell->ypad));
real_yoffset = MAX (real_yoffset, 0) + cell->ypad;
gdk_gc_set_clip_rectangle (widget->style->black_gc, cell_area);
if (!celltoggle->radio)
{
gdk_draw_rectangle (window,
widget->style->black_gc,
FALSE,
cell_area->x + real_xoffset,
cell_area->y + real_yoffset,
width, height);
if (celltoggle->state)
{
gdk_draw_line (window,
widget->style->black_gc,
cell_area->x + real_xoffset,
cell_area->y + real_yoffset,
cell_area->x + real_xoffset + width,
cell_area->y + real_yoffset + height);
gdk_draw_line (window,
widget->style->black_gc,
cell_area->x + real_xoffset + width,
cell_area->y + real_yoffset,
cell_area->x + real_xoffset,
cell_area->y + real_yoffset + height);
}
}
else
{
gdk_draw_arc (window,
widget->style->black_gc,
FALSE,
cell_area->x + real_xoffset,
cell_area->y + real_yoffset,
width,
height,
0, 360*64);
if (celltoggle->state)
{
gdk_draw_arc (window,
widget->style->black_gc,
TRUE,
cell_area->x + real_xoffset + 2,
cell_area->y + real_yoffset + 2,
width - 4,
height - 4,
0, 360*64);
}
}
gdk_gc_set_clip_rectangle (widget->style->black_gc, NULL);
}
static gint
gtk_cell_renderer_toggle_event (GtkCellRenderer *cell,
GdkEvent *event,
GtkWidget *widget,
gchar *path,
GdkRectangle *background_area,
GdkRectangle *cell_area,
guint flags)
{
gtk_signal_emit (GTK_OBJECT (cell), toggle_cell_signals[TOGGLED], path);
return TRUE;
}
void
gtk_cell_renderer_toggle_set_radio (GtkCellRendererToggle *toggle,
gboolean radio)
{
g_return_if_fail (toggle != NULL);
g_return_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle));
toggle->radio = radio;
}

View File

@ -0,0 +1,68 @@
/* gtkcellrenderertoggle.h
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GTK_CELL_RENDERER_TOGGLE_H__
#define __GTK_CELL_RENDERER_TOGGLE_H__
#include <gtk/gtkcellrenderer.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GTK_TYPE_CELL_RENDERER_TOGGLE (gtk_cell_renderer_toggle_get_type ())
#define GTK_CELL_RENDERER_TOGGLE(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_CELL_RENDERER_TOGGLE, GtkCellRendererToggle))
#define GTK_CELL_RENDERER_TOGGLE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_CELL_RENDERER_TOGGLE, GtkCellRendererToggleClass))
#define GTK_IS_CELL_RENDERER_TOGGLE(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_CELL_RENDERER_TOGGLE))
#define GTK_IS_CELL_RENDERER_TOGGLE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), GTK_TYPE_CELL_RENDERER_TOGGLE))
typedef struct _GtkCellRendererToggle GtkCellRendererToggle;
typedef struct _GtkCellRendererToggleClass GtkCellRendererToggleClass;
struct _GtkCellRendererToggle
{
GtkCellRenderer parent;
/*< private >*/
guint state : 1;
guint radio : 1;
};
struct _GtkCellRendererToggleClass
{
GtkCellRendererClass parent_class;
void (* toggled) (GtkCellRendererToggle *celltoggle,
gchar *path);
};
GtkType gtk_cell_renderer_toggle_get_type (void);
GtkCellRenderer *gtk_cell_renderer_toggle_new (void);
void gtk_cell_renderer_toggle_set_radio (GtkCellRendererToggle *toggle,
gboolean radio);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_CELL_RENDERER_TOGGLE_H__ */

458
gtk/gtkliststore.c Normal file
View File

@ -0,0 +1,458 @@
/* gtkliststore.c
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <string.h>
#include "gtktreemodel.h"
#include "gtkliststore.h"
#include "gtktreedatalist.h"
#define G_SLIST(x) ((GSList *) x)
static void gtk_list_store_init (GtkListStore *list_store);
static void gtk_list_store_class_init (GtkListStoreClass *class);
static gint gtk_list_store_get_n_columns (GtkTreeModel *tree_model);
static GtkTreeNode gtk_list_store_get_node (GtkTreeModel *tree_model,
GtkTreePath *path);
static GtkTreePath *gtk_list_store_get_path (GtkTreeModel *tree_model,
GtkTreeNode node);
static void gtk_list_store_node_get_value (GtkTreeModel *tree_model,
GtkTreeNode node,
gint column,
GValue *value);
static gboolean gtk_list_store_node_next (GtkTreeModel *tree_model,
GtkTreeNode *node);
static GtkTreeNode gtk_list_store_node_children (GtkTreeModel *tree_model,
GtkTreeNode node);
static gboolean gtk_list_store_node_has_child (GtkTreeModel *tree_model,
GtkTreeNode node);
static gint gtk_list_store_node_n_children (GtkTreeModel *tree_model,
GtkTreeNode node);
static GtkTreeNode gtk_list_store_node_nth_child (GtkTreeModel *tree_model,
GtkTreeNode node,
gint n);
static GtkTreeNode gtk_list_store_node_parent (GtkTreeModel *tree_model,
GtkTreeNode node);
static GtkTreeModelClass *parent_class = NULL;
GtkType
gtk_list_store_get_type (void)
{
static GtkType list_store_type = 0;
if (!list_store_type)
{
static const GTypeInfo list_store_info =
{
sizeof (GtkListStoreClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gtk_list_store_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GtkListStore),
0,
(GInstanceInitFunc) gtk_list_store_init,
};
list_store_type = g_type_register_static (GTK_TYPE_TREE_MODEL, "GtkListStore", &list_store_info);
}
return list_store_type;
}
static void
gtk_list_store_class_init (GtkListStoreClass *class)
{
GtkObjectClass *object_class;
GtkTreeModelClass *tree_model_class;
object_class = (GtkObjectClass*) class;
tree_model_class = (GtkTreeModelClass *) class;
parent_class = gtk_type_class (gtk_tree_model_get_type ());
tree_model_class->get_n_columns = gtk_list_store_get_n_columns;
tree_model_class->get_node = gtk_list_store_get_node;
tree_model_class->get_path = gtk_list_store_get_path;
tree_model_class->node_get_value = gtk_list_store_node_get_value;
tree_model_class->node_next = gtk_list_store_node_next;
tree_model_class->node_children = gtk_list_store_node_children;
tree_model_class->node_has_child = gtk_list_store_node_has_child;
tree_model_class->node_n_children = gtk_list_store_node_n_children;
tree_model_class->node_nth_child = gtk_list_store_node_nth_child;
tree_model_class->node_parent = gtk_list_store_node_parent;
}
static void
gtk_list_store_init (GtkListStore *list_store)
{
list_store->root = NULL;
}
GtkObject *
gtk_list_store_new (void)
{
return GTK_OBJECT (gtk_type_new (gtk_list_store_get_type ()));
}
GtkObject *
gtk_list_store_new_with_types (gint n_columns,
...)
{
GtkObject *retval;
va_list args;
gint i;
g_return_val_if_fail (n_columns > 0, NULL);
retval = gtk_list_store_new ();
gtk_list_store_set_n_columns (GTK_LIST_STORE (retval),
n_columns);
va_start (args, n_columns);
for (i = 0; i < n_columns; i++)
gtk_list_store_set_column_type (GTK_LIST_STORE (retval),
i, va_arg (args, GType));
va_end (args);
return retval;
}
void
gtk_list_store_set_n_columns (GtkListStore *list_store,
gint n_columns)
{
GType *new_columns;
g_return_if_fail (list_store != NULL);
g_return_if_fail (GTK_IS_LIST_STORE (list_store));
if (list_store->n_columns == n_columns)
return;
new_columns = g_new0 (GType, n_columns);
if (list_store->column_headers)
{
/* copy the old header orders over */
if (n_columns >= list_store->n_columns)
memcpy (new_columns, list_store->column_headers, list_store->n_columns * sizeof (gchar *));
else
memcpy (new_columns, list_store->column_headers, n_columns * sizeof (GType));
g_free (list_store->column_headers);
}
list_store->column_headers = new_columns;
list_store->n_columns = n_columns;
}
void
gtk_list_store_set_column_type (GtkListStore *list_store,
gint column,
GType type)
{
g_return_if_fail (list_store != NULL);
g_return_if_fail (GTK_IS_LIST_STORE (list_store));
g_return_if_fail (column >=0 && column < list_store->n_columns);
list_store->column_headers[column] = type;
}
/* Fulfill the GtkTreeModel requirements */
static gint
gtk_list_store_get_n_columns (GtkTreeModel *tree_model)
{
g_return_val_if_fail (tree_model != NULL, 0);
g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), 0);
return GTK_LIST_STORE (tree_model)->n_columns;
}
static GtkTreeNode
gtk_list_store_get_node (GtkTreeModel *tree_model,
GtkTreePath *path)
{
g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, NULL);
return (GtkTreeNode) g_slist_nth (G_SLIST (GTK_LIST_STORE (tree_model)->root),
gtk_tree_path_get_indices (path)[0]);
}
static GtkTreePath *
gtk_list_store_get_path (GtkTreeModel *tree_model,
GtkTreeNode node)
{
GtkTreePath *retval;
GSList *list;
gint i = 0;
g_return_val_if_fail (GTK_IS_LIST_STORE (tree_model), NULL);
for (list = G_SLIST (GTK_LIST_STORE (tree_model)->root); list; list = list->next)
{
i++;
if (list == G_SLIST (node))
break;
}
if (list == NULL)
return NULL;
retval = gtk_tree_path_new ();
gtk_tree_path_append_index (retval, i);
return retval;
}
static void
gtk_list_store_node_get_value (GtkTreeModel *tree_model,
GtkTreeNode node,
gint column,
GValue *value)
{
GtkTreeDataList *list;
gint tmp_column = column;
g_return_if_fail (tree_model != NULL);
g_return_if_fail (GTK_IS_LIST_STORE (tree_model));
g_return_if_fail (node != NULL);
g_return_if_fail (column < GTK_LIST_STORE (tree_model)->n_columns);
list = G_SLIST (node)->data;
while (tmp_column-- > 0 && list)
list = list->next;
g_return_if_fail (list != NULL);
gtk_tree_data_list_node_to_value (list,
GTK_LIST_STORE (tree_model)->column_headers[column],
value);
}
static gboolean
gtk_list_store_node_next (GtkTreeModel *tree_model,
GtkTreeNode *node)
{
if (node == NULL || *node == NULL)
return FALSE;
*node = (GtkTreeNode *) G_SLIST (*node)->next;
return (*node != NULL);
}
static GtkTreeNode
gtk_list_store_node_children (GtkTreeModel *tree_model,
GtkTreeNode node)
{
return NULL;
}
static gboolean
gtk_list_store_node_has_child (GtkTreeModel *tree_model,
GtkTreeNode node)
{
return FALSE;
}
static gint
gtk_list_store_node_n_children (GtkTreeModel *tree_model,
GtkTreeNode node)
{
return 0;
}
static GtkTreeNode
gtk_list_store_node_nth_child (GtkTreeModel *tree_model,
GtkTreeNode node,
gint n)
{
return NULL;
}
static GtkTreeNode
gtk_list_store_node_parent (GtkTreeModel *tree_model,
GtkTreeNode node)
{
return NULL;
}
/* Public accessors */
GtkTreeNode *
gtk_list_store_node_new (void)
{
GtkTreeNode *retval = (GtkTreeNode *) g_slist_alloc ();
return retval;
}
/* This is a somewhat inelegant function that does a lot of list
* manipulations on it's own.
*/
void
gtk_list_store_node_set_cell (GtkListStore *list_store,
GtkTreeNode *node,
gint column,
GValue *value)
{
GtkTreeDataList *list;
GtkTreeDataList *prev;
g_return_if_fail (list_store != NULL);
g_return_if_fail (GTK_IS_LIST_STORE (list_store));
g_return_if_fail (node != NULL);
g_return_if_fail (column >= 0 && column < list_store->n_columns);
prev = list = G_SLIST (node)->data;
while (list != NULL)
{
if (column == 0)
{
gtk_tree_data_list_value_to_node (list, value);
return;
}
column--;
prev = list;
list = list->next;
}
if (G_SLIST (node)->data == NULL)
{
G_SLIST (node)->data = list = gtk_tree_data_list_alloc ();
list->next = NULL;
}
else
{
list = prev->next = gtk_tree_data_list_alloc ();
list->next = NULL;
}
while (column != 0)
{
list->next = gtk_tree_data_list_alloc ();
list = list->next;
list->next = NULL;
column --;
}
gtk_tree_data_list_value_to_node (list, value);
}
void
gtk_list_store_node_remove (GtkListStore *list_store,
GtkTreeNode *node)
{
}
GtkTreeNode *
gtk_list_store_node_insert (GtkListStore *list_store,
gint position,
GtkTreeNode *node)
{
GSList *list;
g_return_val_if_fail (list_store != NULL, node);
g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), node);
g_return_val_if_fail (node != NULL, node);
g_return_val_if_fail (position < 0, node);
g_return_val_if_fail (G_SLIST (node)->next == NULL, node);
if (position == 0)
{
gtk_list_store_node_prepend (list_store, node);
return node;
}
list = g_slist_nth (G_SLIST (list_store->root), position);
if (list)
{
G_SLIST (node)->next = list->next;
list->next = G_SLIST (node)->next;
}
return node;
}
GtkTreeNode *
gtk_list_store_node_insert_before (GtkListStore *list_store,
GtkTreeNode *sibling,
GtkTreeNode *node)
{
g_return_val_if_fail (list_store != NULL, node);
g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), node);
g_return_val_if_fail (node != NULL, node);
/* FIXME: This is all wrong. This is actually insert_after */
if (sibling == NULL)
return gtk_list_store_node_prepend (list_store, node);
G_SLIST (node)->next = G_SLIST (sibling)->next;
G_SLIST (sibling)->next = G_SLIST (node);
return node;
}
GtkTreeNode *
gtk_list_store_node_prepend (GtkListStore *list_store,
GtkTreeNode *node)
{
g_return_val_if_fail (list_store != NULL, node);
g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), node);
g_return_val_if_fail (node != NULL, node);
G_SLIST (node)->next = G_SLIST (list_store->root);
list_store->root = node;
return node;
}
GtkTreeNode *
gtk_list_store_node_append (GtkListStore *list_store,
GtkTreeNode *node)
{
GSList *list;
g_return_val_if_fail (list_store != NULL, node);
g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), node);
g_return_val_if_fail (node != NULL, node);
g_return_val_if_fail (G_SLIST (node)->next == NULL, node);
list = g_slist_last (G_SLIST (list_store->root));
if (list == NULL)
list_store->root = node;
else
list->next = G_SLIST (node);
return node;
}
GtkTreeNode *
gtk_list_store_node_get_root (GtkListStore *list_store)
{
g_return_val_if_fail (list_store != NULL, NULL);
g_return_val_if_fail (GTK_IS_LIST_STORE (list_store), NULL);
return (GtkTreeNode *) list_store->root;
}

87
gtk/gtkliststore.h Normal file
View File

@ -0,0 +1,87 @@
/* gtkliststore.h
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GTK_LIST_STORE_H__
#define __GTK_LIST_STORE_H__
#include <gtk/gtktreemodel.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GTK_TYPE_LIST_STORE (gtk_list_store_get_type ())
#define GTK_LIST_STORE(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_LIST_STORE, GtkListStore))
#define GTK_LIST_STORE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_LISTSTORE, GtkListStoreClass))
#define GTK_IS_LIST_STORE(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_LIST_STORE))
#define GTK_IS_LIST_STORE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), GTK_TYPE_LIST_STORE))
typedef struct _GtkListStore GtkListStore;
typedef struct _GtkListStoreClass GtkListStoreClass;
struct _GtkListStore
{
GtkTreeModel parent;
/*< private >*/
GtkTreeNode *root;
gint n_columns;
GType *column_headers;
};
struct _GtkListStoreClass
{
GtkTreeModelClass parent_class;
};
GtkType gtk_list_store_get_type (void);
GtkObject *gtk_list_store_new (void);
GtkObject *gtk_list_store_new_with_types (gint n_columns,
...);
void gtk_list_store_set_n_columns (GtkListStore *store,
gint n_columns);
void gtk_list_store_set_column_type (GtkListStore *store,
gint column,
GType type);
GtkTreeNode *gtk_list_store_node_new (void);
void gtk_list_store_node_set_cell (GtkListStore *store,
GtkTreeNode *node,
gint column,
GValue *value);
void gtk_list_store_node_remove (GtkListStore *store,
GtkTreeNode *node);
GtkTreeNode *gtk_list_store_node_insert (GtkListStore *store,
gint position,
GtkTreeNode *node);
GtkTreeNode *gtk_list_store_node_insert_before (GtkListStore *store,
GtkTreeNode *sibling,
GtkTreeNode *node);
GtkTreeNode *gtk_list_store_node_prepend (GtkListStore *store,
GtkTreeNode *node);
GtkTreeNode *gtk_list_store_node_append (GtkListStore *store,
GtkTreeNode *node);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_LIST_STORE_H__ */

430
gtk/gtkmodelsimple.c Normal file
View File

@ -0,0 +1,430 @@
/* gtkmodelsimple.c
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "gtkmodelsimple.h"
#include "gtkmarshal.h"
#include "gtksignal.h"
enum {
GET_N_COLUMNS,
GET_NODE,
GET_PATH,
NODE_GET_VALUE,
NODE_COPY,
NODE_NEXT,
NODE_CHILDREN,
NODE_HAS_CHILD,
NODE_N_CHILDREN,
NODE_NTH_CHILD,
NODE_PARENT,
LAST_SIGNAL
};
static void gtk_model_simple_init (GtkModelSimple *model_simple);
static void gtk_model_simple_class_init (GtkModelSimpleClass *class);
static gint gtk_real_model_simple_get_n_columns (GtkTreeModel *tree_model);
static GtkTreeNode gtk_real_model_simple_get_node (GtkTreeModel *tree_model,
GtkTreePath *path);
static GtkTreePath *gtk_real_model_simple_get_path (GtkTreeModel *tree_model,
GtkTreeNode node);
static void gtk_real_model_simple_node_get_value (GtkTreeModel *tree_model,
GtkTreeNode node,
gint column,
GValue *value);
static gboolean gtk_real_model_simple_node_next (GtkTreeModel *tree_model,
GtkTreeNode *node);
static GtkTreeNode gtk_real_model_simple_node_children (GtkTreeModel *tree_model,
GtkTreeNode node);
static gboolean gtk_real_model_simple_node_has_child (GtkTreeModel *tree_model,
GtkTreeNode node);
static gint gtk_real_model_simple_node_n_children (GtkTreeModel *tree_model,
GtkTreeNode node);
static GtkTreeNode gtk_real_model_simple_node_nth_child (GtkTreeModel *tree_model,
GtkTreeNode node,
gint n);
static GtkTreeNode gtk_real_model_simple_node_parent (GtkTreeModel *tree_model,
GtkTreeNode node);
static GtkTreeModelClass *parent_class = NULL;
static guint model_simple_signals[LAST_SIGNAL] = { 0 };
GtkType
gtk_model_simple_get_type (void)
{
static GtkType model_simple_type = 0;
if (!model_simple_type)
{
static const GTypeInfo model_simple_info =
{
sizeof (GtkModelSimpleClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gtk_model_simple_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GtkModelSimple),
0,
(GInstanceInitFunc) gtk_model_simple_init
};
model_simple_type = g_type_register_static (GTK_TYPE_TREE_MODEL, "GtkModelSimple", &model_simple_info);
}
return model_simple_type;
}
GtkObject *
gtk_model_simple_new (void)
{
return GTK_OBJECT (gtk_type_new (GTK_TYPE_MODEL_SIMPLE));
}
typedef gint (*GtkSignal_INT__NONE) (GtkObject * object,
gpointer user_data);
void
gtk_marshal_INT__NONE (GtkObject * object,
GtkSignalFunc func, gpointer func_data, GtkArg * args)
{
GtkSignal_INT__NONE rfunc;
gint *return_val;
return_val = GTK_RETLOC_INT (args[0]);
rfunc = (GtkSignal_INT__NONE) func;
*return_val = (*rfunc) (object, func_data);
}
typedef gpointer (*GtkSignal_POINTER__NONE) (GtkObject * object,
gpointer user_data);
void
gtk_marshal_POINTER__NONE (GtkObject * object,
GtkSignalFunc func, gpointer func_data, GtkArg * args)
{
GtkSignal_POINTER__NONE rfunc;
gpointer *return_val;
return_val = GTK_RETLOC_POINTER (args[0]);
rfunc = (GtkSignal_POINTER__NONE) func;
*return_val = (*rfunc) (object, func_data);
}
typedef gpointer (*GtkSignal_POINTER__POINTER) (GtkObject * object,
gpointer arg1,
gpointer user_data);
void
gtk_marshal_POINTER__POINTER (GtkObject * object,
GtkSignalFunc func,
gpointer func_data, GtkArg * args)
{
GtkSignal_POINTER__POINTER rfunc;
gpointer *return_val;
return_val = GTK_RETLOC_POINTER (args[1]);
rfunc = (GtkSignal_POINTER__POINTER) func;
*return_val = (*rfunc) (object, GTK_VALUE_POINTER (args[0]), func_data);
}
typedef gpointer (*GtkSignal_POINTER__POINTER_INT) (GtkObject * object,
gpointer arg1,
gint arg2,
gpointer user_data);
void
gtk_marshal_POINTER__POINTER_INT (GtkObject * object,
GtkSignalFunc func,
gpointer func_data, GtkArg * args)
{
GtkSignal_POINTER__POINTER_INT rfunc;
gpointer *return_val;
return_val = GTK_RETLOC_POINTER (args[2]);
rfunc = (GtkSignal_POINTER__POINTER_INT) func;
*return_val = (*rfunc) (object, GTK_VALUE_POINTER (args[0]), GTK_VALUE_INT (args[1]), func_data);
}
static void
gtk_model_simple_class_init (GtkModelSimpleClass *class)
{
GtkObjectClass *object_class;
GtkTreeModelClass *tree_model_class;
object_class = (GtkObjectClass*) class;
tree_model_class = (GtkTreeModelClass*) class;
parent_class = g_type_class_peek_parent (class);
model_simple_signals[GET_N_COLUMNS] =
gtk_signal_new ("get_n_columns",
GTK_RUN_LAST,
GTK_CLASS_TYPE (object_class),
0,
gtk_marshal_INT__NONE,
GTK_TYPE_INT, 0);
model_simple_signals[GET_NODE] =
gtk_signal_new ("get_node",
GTK_RUN_LAST,
GTK_CLASS_TYPE (object_class),
0,
gtk_marshal_POINTER__POINTER,
GTK_TYPE_POINTER, 1,
GTK_TYPE_POINTER);
model_simple_signals[GET_PATH] =
gtk_signal_new ("get_path",
GTK_RUN_LAST,
GTK_CLASS_TYPE (object_class),
0,
gtk_marshal_POINTER__POINTER,
GTK_TYPE_POINTER, 1,
GTK_TYPE_POINTER);
model_simple_signals[NODE_GET_VALUE] =
gtk_signal_new ("node_get_value",
GTK_RUN_LAST,
GTK_CLASS_TYPE (object_class),
0,
gtk_marshal_NONE__POINTER_INT_POINTER,
GTK_TYPE_NONE, 3,
GTK_TYPE_POINTER,
GTK_TYPE_INT,
GTK_TYPE_POINTER);
model_simple_signals[NODE_NEXT] =
gtk_signal_new ("node_next",
GTK_RUN_LAST,
GTK_CLASS_TYPE (object_class),
0,
gtk_marshal_BOOL__POINTER,
GTK_TYPE_BOOL, 1,
GTK_TYPE_POINTER);
model_simple_signals[NODE_CHILDREN] =
gtk_signal_new ("node_children",
GTK_RUN_LAST,
GTK_CLASS_TYPE (object_class),
0,
gtk_marshal_POINTER__POINTER,
GTK_TYPE_POINTER, 1,
GTK_TYPE_POINTER);
model_simple_signals[NODE_HAS_CHILD] =
gtk_signal_new ("node_has_child",
GTK_RUN_LAST,
GTK_CLASS_TYPE (object_class),
0,
gtk_marshal_POINTER__POINTER,
GTK_TYPE_POINTER, 1,
GTK_TYPE_POINTER);
model_simple_signals[NODE_N_CHILDREN] =
gtk_signal_new ("node_n_children",
GTK_RUN_LAST,
GTK_CLASS_TYPE (object_class),
0,
gtk_marshal_POINTER__POINTER,
GTK_TYPE_POINTER, 1,
GTK_TYPE_POINTER);
model_simple_signals[NODE_NTH_CHILD] =
gtk_signal_new ("node_nth_child",
GTK_RUN_LAST,
GTK_CLASS_TYPE (object_class),
0,
gtk_marshal_POINTER__POINTER_INT,
GTK_TYPE_POINTER, 2,
GTK_TYPE_POINTER,
GTK_TYPE_POINTER);
model_simple_signals[NODE_PARENT] =
gtk_signal_new ("node_parent",
GTK_RUN_LAST,
GTK_CLASS_TYPE (object_class),
0,
gtk_marshal_POINTER__POINTER,
GTK_TYPE_POINTER, 1,
GTK_TYPE_POINTER);
tree_model_class->get_n_columns = gtk_real_model_simple_get_n_columns;
tree_model_class->get_node = gtk_real_model_simple_get_node;
tree_model_class->get_path = gtk_real_model_simple_get_path;
tree_model_class->node_get_value = gtk_real_model_simple_node_get_value;
tree_model_class->node_next = gtk_real_model_simple_node_next;
tree_model_class->node_children = gtk_real_model_simple_node_children;
tree_model_class->node_has_child = gtk_real_model_simple_node_has_child;
tree_model_class->node_n_children = gtk_real_model_simple_node_n_children;
tree_model_class->node_nth_child = gtk_real_model_simple_node_nth_child;
tree_model_class->node_parent = gtk_real_model_simple_node_parent;
gtk_object_class_add_signals (object_class, model_simple_signals, LAST_SIGNAL);
}
static void
gtk_model_simple_init (GtkModelSimple *model_simple)
{
}
static gint
gtk_real_model_simple_get_n_columns (GtkTreeModel *tree_model)
{
gint retval = 0;
gtk_signal_emit (GTK_OBJECT (tree_model), model_simple_signals[GET_N_COLUMNS], &retval);
return retval;
}
static GtkTreeNode
gtk_real_model_simple_get_node (GtkTreeModel *tree_model,
GtkTreePath *path)
{
GtkTreeNode retval;
gtk_signal_emit (GTK_OBJECT (tree_model), model_simple_signals[GET_NODE], path, &retval);
return retval;
}
static GtkTreePath *
gtk_real_model_simple_get_path (GtkTreeModel *tree_model,
GtkTreeNode node)
{
GtkTreePath *retval;
gtk_signal_emit (GTK_OBJECT (tree_model), model_simple_signals[GET_PATH], node, &retval);
return retval;
}
static void
gtk_real_model_simple_node_get_value (GtkTreeModel *tree_model,
GtkTreeNode node,
gint column,
GValue *value)
{
gtk_signal_emit (GTK_OBJECT (tree_model), model_simple_signals[NODE_GET_VALUE], node, column, value);
}
static gboolean
gtk_real_model_simple_node_next (GtkTreeModel *tree_model,
GtkTreeNode *node)
{
gboolean retval = FALSE;
gtk_signal_emit (GTK_OBJECT (tree_model), model_simple_signals[NODE_NEXT], node, &retval);
return retval;
}
static GtkTreeNode
gtk_real_model_simple_node_children (GtkTreeModel *tree_model,
GtkTreeNode node)
{
GtkTreeNode retval = NULL;
gtk_signal_emit (GTK_OBJECT (tree_model), model_simple_signals[NODE_CHILDREN], node, &retval);
return retval;
}
static gboolean
gtk_real_model_simple_node_has_child (GtkTreeModel *tree_model,
GtkTreeNode node)
{
gboolean retval = FALSE;
gtk_signal_emit (GTK_OBJECT (tree_model), model_simple_signals[NODE_HAS_CHILD], node, &retval);
return retval;
}
static gint
gtk_real_model_simple_node_n_children (GtkTreeModel *tree_model,
GtkTreeNode node)
{
gint retval = 0;
gtk_signal_emit (GTK_OBJECT (tree_model), model_simple_signals[NODE_N_CHILDREN], node, &retval);
return retval;
}
static GtkTreeNode
gtk_real_model_simple_node_nth_child (GtkTreeModel *tree_model,
GtkTreeNode node,
gint n)
{
GtkTreeNode retval = NULL;
gtk_signal_emit (GTK_OBJECT (tree_model), model_simple_signals[NODE_NTH_CHILD], node, n, &retval);
return retval;
}
static GtkTreeNode
gtk_real_model_simple_node_parent (GtkTreeModel *tree_model,
GtkTreeNode node)
{
GtkTreeNode retval = NULL;
gtk_signal_emit (GTK_OBJECT (tree_model), model_simple_signals[NODE_PARENT], node, &retval);
return retval;
}
/* Public functions */
void
gtk_model_simple_node_changed (GtkModelSimple *simple,
GtkTreePath *path,
GtkTreeNode *tree_node)
{
g_return_if_fail (simple != NULL);
g_return_if_fail (GTK_IS_MODEL_SIMPLE (simple));
g_return_if_fail (path != NULL);
gtk_signal_emit_by_name (GTK_OBJECT (simple), "node_changed", path, tree_node);
}
void
gtk_model_simple_node_inserted (GtkModelSimple *simple,
GtkTreePath *path,
GtkTreeNode *tree_node)
{
g_return_if_fail (simple != NULL);
g_return_if_fail (GTK_IS_MODEL_SIMPLE (simple));
g_return_if_fail (path != NULL);
gtk_signal_emit_by_name (GTK_OBJECT (simple), "node_inserted", path, tree_node);
}
void
gtk_model_simple_node_child_toggled (GtkModelSimple *simple,
GtkTreePath *path,
GtkTreeNode *tree_node)
{
g_return_if_fail (simple != NULL);
g_return_if_fail (GTK_IS_MODEL_SIMPLE (simple));
g_return_if_fail (path != NULL);
gtk_signal_emit_by_name (GTK_OBJECT (simple), "node_child_toggled", path, tree_node);
}
void
gtk_model_simple_node_deleted (GtkModelSimple *simple,
GtkTreePath *path,
GtkTreeNode *tree_node)
{
g_return_if_fail (simple != NULL);
g_return_if_fail (GTK_IS_MODEL_SIMPLE (simple));
g_return_if_fail (path != NULL);
gtk_signal_emit_by_name (GTK_OBJECT (simple), "node_deleted", path, tree_node);
}

73
gtk/gtkmodelsimple.h Normal file
View File

@ -0,0 +1,73 @@
/* gtkmodelsimple.h
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GTK_MODEL_SIMPLE_H__
#define __GTK_MODEL_SIMPLE_H__
#include <gtk/gtktreemodel.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GTK_TYPE_MODEL_SIMPLE (gtk_model_simple_get_type ())
#define GTK_MODEL_SIMPLE(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_MODEL_SIMPLE, GtkModelSimple))
#define GTK_MODEL_SIMPLE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_MODEL_SIMPLE, GtkModelSimpleClass))
#define GTK_IS_MODEL_SIMPLE(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_MODEL_SIMPLE))
#define GTK_IS_MODEL_SIMPLE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), GTK_TYPE_MODEL_SIMPLE))
typedef struct _GtkModelSimple GtkModelSimple;
typedef struct _GtkModelSimpleClass GtkModelSimpleClass;
struct _GtkModelSimple
{
GtkTreeModel parent;
};
struct _GtkModelSimpleClass
{
GtkTreeModelClass parent_class;
};
GtkType gtk_model_simple_get_type (void);
GtkObject *gtk_model_simple_new (void);
void gtk_model_simple_node_changed (GtkModelSimple *simple,
GtkTreePath *path,
GtkTreeNode *tree_node);
void gtk_model_simple_node_inserted (GtkModelSimple *simple,
GtkTreePath *path,
GtkTreeNode *tree_node);
void gtk_model_simple_node_child_toggled (GtkModelSimple *simple,
GtkTreePath *path,
GtkTreeNode *tree_node);
void gtk_model_simple_node_deleted (GtkModelSimple *simple,
GtkTreePath *path,
GtkTreeNode *tree_node);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_MODEL_SIMPLE_H__ */

994
gtk/gtkrbtree.c Normal file
View File

@ -0,0 +1,994 @@
/* gtkrbtree.c
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "gtkrbtree.h"
static void _gtk_rbnode_validate_allocator (GAllocator *allocator);
static GtkRBNode *_gtk_rbnode_new (GtkRBTree *tree,
gint height);
static void _gtk_rbnode_free (GtkRBNode *node);
static void _gtk_rbnode_rotate_left (GtkRBTree *tree,
GtkRBNode *node);
static void _gtk_rbnode_rotate_left (GtkRBTree *tree,
GtkRBNode *node);
static void _gtk_rbtree_insert_fixup (GtkRBTree *tree,
GtkRBNode *node);
static void _gtk_rbtree_remove_node_fixup (GtkRBTree *tree,
GtkRBNode *node);
static gint _count_nodes (GtkRBTree *tree,
GtkRBNode *node);
/* node allocation
*/
struct _GAllocator /* from gmem.c */
{
gchar *name;
guint16 n_preallocs;
guint is_unused : 1;
guint type : 4;
GAllocator *last;
GMemChunk *mem_chunk;
GtkRBNode *free_nodes; /* implementation specific */
};
G_LOCK_DEFINE_STATIC (current_allocator);
static GAllocator *current_allocator = NULL;
/* HOLDS: current_allocator_lock */
static void
_gtk_rbnode_validate_allocator (GAllocator *allocator)
{
g_return_if_fail (allocator != NULL);
g_return_if_fail (allocator->is_unused == TRUE);
if (allocator->type != G_ALLOCATOR_NODE)
{
allocator->type = G_ALLOCATOR_NODE;
if (allocator->mem_chunk)
{
g_mem_chunk_destroy (allocator->mem_chunk);
allocator->mem_chunk = NULL;
}
}
if (!allocator->mem_chunk)
{
allocator->mem_chunk = g_mem_chunk_new (allocator->name,
sizeof (GtkRBNode),
sizeof (GtkRBNode) * allocator->n_preallocs,
G_ALLOC_ONLY);
allocator->free_nodes = NULL;
}
allocator->is_unused = FALSE;
}
static GtkRBNode *
_gtk_rbnode_new (GtkRBTree *tree,
gint height)
{
GtkRBNode *node;
G_LOCK (current_allocator);
if (!current_allocator)
{
GAllocator *allocator = g_allocator_new ("GTK+ default GtkRBNode allocator",
128);
_gtk_rbnode_validate_allocator (allocator);
allocator->last = NULL;
current_allocator = allocator;
}
if (!current_allocator->free_nodes)
node = g_chunk_new (GtkRBNode, current_allocator->mem_chunk);
else
{
node = current_allocator->free_nodes;
current_allocator->free_nodes = node->left;
}
G_UNLOCK (current_allocator);
node->left = tree->nil;
node->right = tree->nil;
node->parent = tree->nil;
node->flags = GTK_RBNODE_RED;
node->count = 1;
node->children = NULL;
node->offset = height;
return node;
}
static void
_gtk_rbnode_free (GtkRBNode *node)
{
G_LOCK (current_allocator);
node->left = current_allocator->free_nodes;
current_allocator->free_nodes = node;
G_UNLOCK (current_allocator);
}
static void
_gtk_rbnode_rotate_left (GtkRBTree *tree,
GtkRBNode *node)
{
gint node_height, right_height;
GtkRBNode *right = node->right;
g_return_if_fail (node != tree->nil);
node_height = node->offset -
(node->left?node->left->offset:0) -
(node->right?node->right->offset:0) -
(node->children?node->children->root->offset:0);
right_height = right->offset -
(right->left?right->left->offset:0) -
(right->right?right->right->offset:0) -
(right->children?right->children->root->offset:0);
node->right = right->left;
if (right->left != tree->nil)
right->left->parent = node;
if (right != tree->nil)
right->parent = node->parent;
if (node->parent != tree->nil)
{
if (node == node->parent->left)
node->parent->left = right;
else
node->parent->right = right;
} else {
tree->root = right;
}
right->left = node;
if (node != tree->nil)
node->parent = right;
node->count = 1 + (node->left?node->left->count:0) +
(node->right?node->right->count:0);
right->count = 1 + (right->left?right->left->count:0) +
(right->right?right->right->count:0);
node->offset = node_height +
(node->left?node->left->offset:0) +
(node->right?node->right->offset:0) +
(node->children?node->children->root->offset:0);
right->offset = right_height +
(right->left?right->left->offset:0) +
(right->right?right->right->offset:0) +
(right->children?right->children->root->offset:0);
}
static void
_gtk_rbnode_rotate_right (GtkRBTree *tree,
GtkRBNode *node)
{
gint node_height, left_height;
GtkRBNode *left = node->left;
g_return_if_fail (node != tree->nil);
node_height = node->offset -
(node->left?node->left->offset:0) -
(node->right?node->right->offset:0) -
(node->children?node->children->root->offset:0);
left_height = left->offset -
(left->left?left->left->offset:0) -
(left->right?left->right->offset:0) -
(left->children?left->children->root->offset:0);
node->left = left->right;
if (left->right != tree->nil)
left->right->parent = node;
if (left != tree->nil)
left->parent = node->parent;
if (node->parent != tree->nil)
{
if (node == node->parent->right)
node->parent->right = left;
else
node->parent->left = left;
}
else
{
tree->root = left;
}
/* link node and left */
left->right = node;
if (node != tree->nil)
node->parent = left;
node->count = 1 + (node->left?node->left->count:0) +
(node->right?node->right->count:0);
left->count = 1 + (left->left?left->left->count:0) +
(left->right?left->right->count:0);
node->offset = node_height +
(node->left?node->left->offset:0) +
(node->right?node->right->offset:0) +
(node->children?node->children->root->offset:0);
left->offset = left_height +
(left->left?left->left->offset:0) +
(left->right?left->right->offset:0) +
(left->children?left->children->root->offset:0);
}
static void
_gtk_rbtree_insert_fixup (GtkRBTree *tree,
GtkRBNode *node)
{
/* check Red-Black properties */
while (node != tree->root && GTK_RBNODE_GET_COLOR (node->parent) == GTK_RBNODE_RED)
{
/* we have a violation */
if (node->parent == node->parent->parent->left)
{
GtkRBNode *y = node->parent->parent->right;
if (GTK_RBNODE_GET_COLOR (y) == GTK_RBNODE_RED)
{
/* uncle is GTK_RBNODE_RED */
GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_BLACK);
GTK_RBNODE_SET_COLOR (y, GTK_RBNODE_BLACK);
GTK_RBNODE_SET_COLOR (node->parent->parent, GTK_RBNODE_RED);
node = node->parent->parent;
}
else
{
/* uncle is GTK_RBNODE_BLACK */
if (node == node->parent->right)
{
/* make node a left child */
node = node->parent;
_gtk_rbnode_rotate_left (tree, node);
}
/* recolor and rotate */
GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_BLACK);
GTK_RBNODE_SET_COLOR (node->parent->parent, GTK_RBNODE_RED);
_gtk_rbnode_rotate_right(tree, node->parent->parent);
}
}
else
{
/* mirror image of above code */
GtkRBNode *y = node->parent->parent->left;
if (GTK_RBNODE_GET_COLOR (y) == GTK_RBNODE_RED)
{
/* uncle is GTK_RBNODE_RED */
GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_BLACK);
GTK_RBNODE_SET_COLOR (y, GTK_RBNODE_BLACK);
GTK_RBNODE_SET_COLOR (node->parent->parent, GTK_RBNODE_RED);
node = node->parent->parent;
}
else
{
/* uncle is GTK_RBNODE_BLACK */
if (node == node->parent->left)
{
node = node->parent;
_gtk_rbnode_rotate_right (tree, node);
}
GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_BLACK);
GTK_RBNODE_SET_COLOR (node->parent->parent, GTK_RBNODE_RED);
_gtk_rbnode_rotate_left (tree, node->parent->parent);
}
}
}
GTK_RBNODE_SET_COLOR (tree->root, GTK_RBNODE_BLACK);
}
static void
_gtk_rbtree_remove_node_fixup (GtkRBTree *tree,
GtkRBNode *node)
{
while (node != tree->root && GTK_RBNODE_GET_COLOR (node) == GTK_RBNODE_BLACK)
{
if (node == node->parent->left)
{
GtkRBNode *w = node->parent->right;
if (GTK_RBNODE_GET_COLOR (w) == GTK_RBNODE_RED)
{
GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_BLACK);
GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_RED);
_gtk_rbnode_rotate_left (tree, node->parent);
w = node->parent->right;
}
if (GTK_RBNODE_GET_COLOR (w->left) == GTK_RBNODE_BLACK && GTK_RBNODE_GET_COLOR (w->right) == GTK_RBNODE_BLACK)
{
GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_RED);
node = node->parent;
}
else
{
if (GTK_RBNODE_GET_COLOR (w->right) == GTK_RBNODE_BLACK)
{
GTK_RBNODE_SET_COLOR (w->left, GTK_RBNODE_BLACK);
GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_RED);
_gtk_rbnode_rotate_right (tree, w);
w = node->parent->right;
}
GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_GET_COLOR (node->parent));
GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_BLACK);
GTK_RBNODE_SET_COLOR (w->right, GTK_RBNODE_BLACK);
_gtk_rbnode_rotate_left (tree, node->parent);
node = tree->root;
}
}
else
{
GtkRBNode *w = node->parent->left;
if (GTK_RBNODE_GET_COLOR (w) == GTK_RBNODE_RED)
{
GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_BLACK);
GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_RED);
_gtk_rbnode_rotate_right (tree, node->parent);
w = node->parent->left;
}
if (GTK_RBNODE_GET_COLOR (w->right) == GTK_RBNODE_BLACK && GTK_RBNODE_GET_COLOR (w->left) == GTK_RBNODE_BLACK)
{
GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_RED);
node = node->parent;
}
else
{
if (GTK_RBNODE_GET_COLOR (w->left) == GTK_RBNODE_BLACK)
{
GTK_RBNODE_SET_COLOR (w->right, GTK_RBNODE_BLACK);
GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_RED);
_gtk_rbnode_rotate_left (tree, w);
w = node->parent->left;
}
GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_GET_COLOR (node->parent));
GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_BLACK);
GTK_RBNODE_SET_COLOR (w->left, GTK_RBNODE_BLACK);
_gtk_rbnode_rotate_right (tree, node->parent);
node = tree->root;
}
}
}
GTK_RBNODE_SET_COLOR (node, GTK_RBNODE_BLACK);
}
/* Public functions */
void
_gtk_rbnode_push_allocator (GAllocator *allocator)
{
G_LOCK (current_allocator);
_gtk_rbnode_validate_allocator ( allocator );
allocator->last = current_allocator;
current_allocator = allocator;
G_UNLOCK (current_allocator);
}
void
_gtk_rbnode_pop_allocator (void)
{
G_LOCK (current_allocator);
if (current_allocator)
{
GAllocator *allocator;
allocator = current_allocator;
current_allocator = allocator->last;
allocator->last = NULL;
allocator->is_unused = TRUE;
}
G_UNLOCK (current_allocator);
}
GtkRBTree *
_gtk_rbtree_new (void)
{
GtkRBTree *retval;
retval = (GtkRBTree *) g_new (GtkRBTree, 1);
retval->parent_tree = NULL;
retval->parent_node = NULL;
retval->nil = g_new0 (GtkRBNode, 1);
retval->nil->left = NULL;
retval->nil->right = NULL;
retval->nil->parent = NULL;
retval->nil->flags = GTK_RBNODE_BLACK;
retval->nil->count = 0;
retval->nil->offset = 0;
retval->root = retval->nil;
return retval;
}
static void
_gtk_rbtree_free_helper (GtkRBTree *tree,
GtkRBNode *node,
gpointer data)
{
if (node->children)
_gtk_rbtree_free (node->children);
_gtk_rbnode_free (node);
}
void
_gtk_rbtree_free (GtkRBTree *tree)
{
_gtk_rbtree_traverse (tree,
tree->root,
G_POST_ORDER,
_gtk_rbtree_free_helper,
NULL);
if (tree->parent_node &&
tree->parent_node->children == tree)
tree->parent_node->children = NULL;
_gtk_rbnode_free (tree->nil);
g_free (tree);
}
void
_gtk_rbtree_remove (GtkRBTree *tree)
{
GtkRBTree *tmp_tree;
GtkRBNode *tmp_node;
gint height = tree->root->offset;
tmp_tree = tree->parent_tree;
tmp_node = tree->parent_node;
while (tmp_tree && tmp_node && tmp_node != tmp_tree->nil)
{
tmp_node->offset -= height;
tmp_node = tmp_node->parent;
if (tmp_node == tmp_tree->nil)
{
tmp_node = tmp_tree->parent_node;
tmp_tree = tmp_tree->parent_tree;
}
}
_gtk_rbtree_free (tree);
}
GtkRBNode *
_gtk_rbtree_insert_after (GtkRBTree *tree,
GtkRBNode *current,
gint height)
{
GtkRBNode *node;
gboolean right = TRUE;
GtkRBNode *tmp_node;
GtkRBTree *tmp_tree;
if (current != NULL && current->right != tree->nil)
{
current = current->right;
while (current->left != tree->nil)
current = current->left;
right = FALSE;
}
/* setup new node */
node = _gtk_rbnode_new (tree, height);
node->parent = (current?current:tree->nil);
/* insert node in tree */
if (current)
{
if (right)
current->right = node;
else
current->left = node;
tmp_node = node->parent;
tmp_tree = tree;
}
else
{
tree->root = node;
tmp_node = tree->parent_node;
tmp_tree = tree->parent_tree;
}
while (tmp_tree && tmp_node && tmp_node != tmp_tree->nil)
{
/* We only want to propagate the count if we are in the tree we
* started in. */
if (tmp_tree == tree)
tmp_node->count++;
tmp_node->offset += height;
tmp_node = tmp_node->parent;
if (tmp_node == tmp_tree->nil)
{
tmp_node = tmp_tree->parent_node;
tmp_tree = tmp_tree->parent_tree;
}
}
_gtk_rbtree_insert_fixup (tree, node);
return node;
}
GtkRBNode *
_gtk_rbtree_insert_before (GtkRBTree *tree,
GtkRBNode *current,
gint height)
{
GtkRBNode *node;
gboolean left = TRUE;
GtkRBNode *tmp_node;
GtkRBTree *tmp_tree;
if (current != NULL && current->left != tree->nil)
{
current = current->left;
while (current->right != tree->nil)
current = current->right;
left = FALSE;
}
/* setup new node */
node = _gtk_rbnode_new (tree, height);
node->parent = (current?current:tree->nil);
/* insert node in tree */
if (current)
{
if (left)
current->left = node;
else
current->right = node;
tmp_node = node->parent;
tmp_tree = tree;
}
else
{
tree->root = node;
tmp_node = tree->parent_node;
tmp_tree = tree->parent_tree;
}
while (tmp_tree && tmp_node && tmp_node != tmp_tree->nil)
{
/* We only want to propagate the count if we are in the tree we
* started in. */
if (tmp_tree == tree)
tmp_node->count++;
tmp_node->offset += height;
tmp_node = tmp_node->parent;
if (tmp_node == tmp_tree->nil)
{
tmp_node = tmp_tree->parent_node;
tmp_tree = tmp_tree->parent_tree;
}
}
_gtk_rbtree_insert_fixup (tree, node);
return node;
}
GtkRBNode *
_gtk_rbtree_find_count (GtkRBTree *tree,
gint count)
{
GtkRBNode *node;
node = tree->root;
while (node != tree->nil && (node->left->count + 1 != count))
{
if (node->left->count >= count)
node = node->left;
else
{
count -= (node->left->count + 1);
node = node->right;
}
}
if (node == tree->nil)
return NULL;
return node;
}
void
_gtk_rbtree_node_set_height (GtkRBTree *tree,
GtkRBNode *node,
gint height)
{
gint diff = height - GTK_RBNODE_GET_HEIGHT (node);
GtkRBNode *tmp_node = node;
GtkRBTree *tmp_tree = tree;
if (diff == 0)
return;
while (tmp_tree && tmp_node && tmp_node != tmp_tree->nil)
{
tmp_node->offset += diff;
tmp_node = tmp_node->parent;
if (tmp_node == tmp_tree->nil)
{
tmp_node = tmp_tree->parent_node;
tmp_tree = tmp_tree->parent_tree;
}
}
}
gint
_gtk_rbtree_node_find_offset (GtkRBTree *tree,
GtkRBNode *node)
{
GtkRBNode *last;
gint retval = node->left->offset;
while (tree && node && node != tree->nil)
{
last = node;
node = node->parent;
if (node->right == last)
retval += node->left->offset + GTK_RBNODE_GET_HEIGHT (node);
if (node == tree->nil)
{
node = tree->parent_node;
tree = tree->parent_tree;
if (node)
retval += node->left->offset;
}
}
return retval;
}
gint
_gtk_rbtree_find_offset (GtkRBTree *tree,
gint height,
GtkRBTree **new_tree,
GtkRBNode **new_node)
{
GtkRBNode *tmp_node;
tmp_node = tree->root;
while (tmp_node != tree->nil &&
(tmp_node->left->offset > height ||
(tmp_node->offset - tmp_node->right->offset) < height))
{
if (tmp_node->left->offset > height)
tmp_node = tmp_node->left;
else
{
height -= (tmp_node->offset - tmp_node->right->offset);
tmp_node = tmp_node->right;
}
}
if (tmp_node == tree->nil)
{
*new_tree = NULL;
*new_node = NULL;
return 0;
}
if (tmp_node->children)
{
if ((tmp_node->offset -
tmp_node->right->offset -
tmp_node->children->root->offset) > height)
{
*new_tree = tree;
*new_node = tmp_node;
return (height - tmp_node->left->offset);
}
return _gtk_rbtree_find_offset (tmp_node->children,
height - tmp_node->left->offset -
(tmp_node->offset -
tmp_node->left->offset -
tmp_node->right->offset -
tmp_node->children->root->offset),
new_tree,
new_node);
}
*new_tree = tree;
*new_node = tmp_node;
return (height - tmp_node->left->offset);
}
void
_gtk_rbtree_remove_node (GtkRBTree *tree,
GtkRBNode *node)
{
GtkRBNode *x, *y;
g_return_if_fail (tree != NULL);
g_return_if_fail (node != NULL);
/* make sure we're deleting a node that's actually in the tree */
for (x = node; x->parent != tree->nil; x = x->parent)
;
g_return_if_fail (x == tree->root);
if (node->left == tree->nil || node->right == tree->nil)
{
y = node;
}
else
{
y = node->right;
while (y->left != tree->nil)
y = y->left;
}
for (x = y; x != tree->nil; x = x->parent)
x->count--;
y->count = node->count;
/* x is y's only child */
if (y->left != tree->nil)
x = y->left;
else
x = y->right;
/* remove y from the parent chain */
x->parent = y->parent;
if (y->parent != tree->nil)
if (y == y->parent->left)
y->parent->left = x;
else
y->parent->right = x;
else
tree->root = x;
if (y != node)
node->children = y->children;
if (GTK_RBNODE_GET_COLOR (y) == GTK_RBNODE_BLACK)
_gtk_rbtree_remove_node_fixup (tree, x);
G_LOCK (current_allocator);
y->left = current_allocator->free_nodes;
current_allocator->free_nodes = y;
G_UNLOCK (current_allocator);
}
GtkRBNode *
_gtk_rbtree_next (GtkRBTree *tree,
GtkRBNode *node)
{
g_return_val_if_fail (tree != NULL, NULL);
g_return_val_if_fail (node != NULL, NULL);
/* Case 1: the node's below us. */
if (node->right != tree->nil)
{
node = node->right;
while (node->left != tree->nil)
node = node->left;
return node;
}
/* Case 2: it's an ancestor */
while (node->parent != tree->nil)
{
if (node->parent->right == node)
node = node->parent;
else
return (node->parent);
}
/* Case 3: There is no next node */
return NULL;
}
GtkRBNode *
_gtk_rbtree_prev (GtkRBTree *tree,
GtkRBNode *node)
{
g_return_val_if_fail (tree != NULL, NULL);
g_return_val_if_fail (node != NULL, NULL);
/* Case 1: the node's below us. */
if (node->left != tree->nil)
{
node = node->left;
while (node->right != tree->nil)
node = node->right;
return node;
}
/* Case 2: it's an ancestor */
while (node->parent != tree->nil)
{
if (node->parent->left == node)
node = node->parent;
else
return (node->parent);
}
/* Case 3: There is no next node */
return NULL;
}
void
_gtk_rbtree_next_full (GtkRBTree *tree,
GtkRBNode *node,
GtkRBTree **new_tree,
GtkRBNode **new_node)
{
g_return_if_fail (tree != NULL);
g_return_if_fail (node != NULL);
g_return_if_fail (new_tree != NULL);
g_return_if_fail (new_node != NULL);
if (node->children)
{
*new_tree = node->children;
*new_node = (*new_tree)->root;
while ((*new_node)->left != (*new_tree)->nil)
*new_node = (*new_node)->left;
return;
}
*new_tree = tree;
*new_node = _gtk_rbtree_next (tree, node);
while ((*new_node == NULL) &&
(*new_tree != NULL))
{
*new_node = (*new_tree)->parent_node;
*new_tree = (*new_tree)->parent_tree;
if (*new_tree)
*new_node = _gtk_rbtree_next (*new_tree, *new_node);
}
}
void
_gtk_rbtree_prev_full (GtkRBTree *tree,
GtkRBNode *node,
GtkRBTree **new_tree,
GtkRBNode **new_node)
{
g_return_if_fail (tree != NULL);
g_return_if_fail (node != NULL);
g_return_if_fail (new_tree != NULL);
g_return_if_fail (new_node != NULL);
*new_tree = tree;
*new_node = _gtk_rbtree_prev (tree, node);
if (*new_node == NULL)
{
*new_node = (*new_tree)->parent_node;
*new_tree = (*new_tree)->parent_tree;
}
else
{
while ((*new_node)->children)
{
*new_tree = (*new_node)->children;
*new_node = (*new_tree)->root;
while ((*new_node)->right != (*new_tree)->nil)
*new_node = (*new_node)->right;
}
}
}
static void
_gtk_rbtree_traverse_pre_order (GtkRBTree *tree,
GtkRBNode *node,
GtkRBTreeTraverseFunc func,
gpointer data)
{
if (node == tree->nil)
return;
(* func) (tree, node, data);
_gtk_rbtree_traverse_pre_order (tree, node->left, func, data);
_gtk_rbtree_traverse_pre_order (tree, node->right, func, data);
}
static void
_gtk_rbtree_traverse_post_order (GtkRBTree *tree,
GtkRBNode *node,
GtkRBTreeTraverseFunc func,
gpointer data)
{
if (node == tree->nil)
return;
_gtk_rbtree_traverse_post_order (tree, node->left, func, data);
_gtk_rbtree_traverse_post_order (tree, node->right, func, data);
(* func) (tree, node, data);
}
void
_gtk_rbtree_traverse (GtkRBTree *tree,
GtkRBNode *node,
GTraverseType order,
GtkRBTreeTraverseFunc func,
gpointer data)
{
g_return_if_fail (tree != NULL);
g_return_if_fail (node != NULL);
g_return_if_fail (func != NULL);
g_return_if_fail (order <= G_LEVEL_ORDER);
switch (order)
{
case G_PRE_ORDER:
_gtk_rbtree_traverse_pre_order (tree, node, func, data);
break;
case G_POST_ORDER:
_gtk_rbtree_traverse_post_order (tree, node, func, data);
break;
case G_IN_ORDER:
case G_LEVEL_ORDER:
default:
g_warning ("unsupported traversal order.");
break;
}
}
static gint
_count_nodes (GtkRBTree *tree,
GtkRBNode *node)
{
gint res;
if (node == tree->nil)
return 0;
res = (_count_nodes (tree, node->left) +
_count_nodes (tree, node->right) + 1);
if (res != node->count)
g_print ("Tree failed\n");
return res;
}
void
_gtk_rbtree_test (GtkRBTree *tree)
{
if ((_count_nodes (tree, tree->root->left) +
_count_nodes (tree, tree->root->right) + 1) == tree->root->count)
g_print ("Tree passed\n");
else
g_print ("Tree failed\n");
}
static void
_gtk_rbtree_test_height_helper (GtkRBTree *tree,
GtkRBNode *node,
gint height)
{
if (node == tree->nil)
return;
if (node->offset -
(node->left?node->left->offset:0) -
(node->right?node->right->offset:0) -
(node->children?node->children->root->offset:0) != height)
g_error ("tree failed\n");
_gtk_rbtree_test_height_helper (tree, node->left, height);
_gtk_rbtree_test_height_helper (tree, node->right, height);
if (node->children)
_gtk_rbtree_test_height_helper (node->children, node->children->root, height);
}
void
_gtk_rbtree_test_height (GtkRBTree *tree,
gint height)
{
_gtk_rbtree_test_height_helper (tree, tree->root, height);
}

133
gtk/gtkrbtree.h Normal file
View File

@ -0,0 +1,133 @@
/* gtkrbtree.h
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GTK_RBTREE_H__
#define __GTK_RBTREE_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <glib.h>
typedef enum
{
GTK_RBNODE_BLACK = 1 << 0,
GTK_RBNODE_RED = 1 << 1,
GTK_RBNODE_IS_PARENT = 1 << 2,
GTK_RBNODE_IS_SELECTED = 1 << 3,
GTK_RBNODE_IS_PRELIT = 1 << 4,
GTK_RBNODE_IS_VIEW = 1 << 5
} GtkRBNodeColor;
typedef struct _GtkRBTree GtkRBTree;
typedef struct _GtkRBNode GtkRBNode;
typedef struct _GtkRBTreeView GtkRBTreeView;
typedef void (*GtkRBTreeTraverseFunc) (GtkRBTree *tree,
GtkRBNode *node,
gpointer data);
struct _GtkRBTree
{
GtkRBNode *root;
GtkRBNode *nil;
GtkRBTree *parent_tree;
GtkRBNode *parent_node;
};
struct _GtkRBNode
{
guint flags;
GtkRBNode *left;
GtkRBNode *right;
GtkRBNode *parent;
gint count; /* aggregate number of children we have */
gint offset; /* aggregate of the heights of all our children */
GtkRBTree *children;
};
struct _GtkRBNodeView
{
GtkRBNode parent;
gint offset;
GtkRBTree *children;
};
#define GTK_RBNODE_GET_COLOR(node) (node?(((node->flags&GTK_RBNODE_RED)==GTK_RBNODE_RED)?GTK_RBNODE_RED:GTK_RBNODE_BLACK):GTK_RBNODE_BLACK)
#define GTK_RBNODE_SET_COLOR(node,color) if((node->flags&color)!=color)node->flags=node->flags^(GTK_RBNODE_RED|GTK_RBNODE_BLACK)
#define GTK_RBNODE_GET_HEIGHT(node) (node->offset-(node->left->offset+node->right->offset+(node->children?node->children->root->offset:0)))
#define GTK_RBNODE_SET_FLAG(node, flag) G_STMT_START{ (node->flags|=flag); }G_STMT_END
#define GTK_RBNODE_UNSET_FLAG(node, flag) G_STMT_START{ (node->flags&=~(flag)); }G_STMT_END
#define GTK_RBNODE_FLAG_SET(node, flag) (node?(((node->flags&flag)==flag)?TRUE:FALSE):FALSE)
void _gtk_rbtree_push_allocator (GAllocator *allocator);
void _gtk_rbtree_pop_allocator (void);
GtkRBTree *_gtk_rbtree_new (void);
void _gtk_rbtree_free (GtkRBTree *tree);
void _gtk_rbtree_remove (GtkRBTree *tree);
void _gtk_rbtree_destroy (GtkRBTree *tree);
GtkRBNode *_gtk_rbtree_insert_before (GtkRBTree *tree,
GtkRBNode *node,
gint height);
GtkRBNode *_gtk_rbtree_insert_after (GtkRBTree *tree,
GtkRBNode *node,
gint height);
void _gtk_rbtree_remove_node (GtkRBTree *tree,
GtkRBNode *node);
GtkRBNode *_gtk_rbtree_find_count (GtkRBTree *tree,
gint count);
void _gtk_rbtree_node_set_height (GtkRBTree *tree,
GtkRBNode *node,
gint height);
gint _gtk_rbtree_node_find_offset (GtkRBTree *tree,
GtkRBNode *node);
gint _gtk_rbtree_find_offset (GtkRBTree *tree,
gint offset,
GtkRBTree **new_tree,
GtkRBNode **new_node);
void _gtk_rbtree_traverse (GtkRBTree *tree,
GtkRBNode *node,
GTraverseType order,
GtkRBTreeTraverseFunc func,
gpointer data);
GtkRBNode *_gtk_rbtree_next (GtkRBTree *tree,
GtkRBNode *node);
GtkRBNode *_gtk_rbtree_prev (GtkRBTree *tree,
GtkRBNode *node);
void _gtk_rbtree_next_full (GtkRBTree *tree,
GtkRBNode *node,
GtkRBTree **new_tree,
GtkRBNode **new_node);
void _gtk_rbtree_prev_full (GtkRBTree *tree,
GtkRBNode *node,
GtkRBTree **new_tree,
GtkRBNode **new_node);
/* This func just checks the integrity of the tree */
/* It will go away later. */
void _gtk_rbtree_test (GtkRBTree *tree);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_RBTREE_H__ */

159
gtk/gtktreedatalist.c Normal file
View File

@ -0,0 +1,159 @@
/* gtktreedatalist.h
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "gtktreedatalist.h"
#include "gobject/gvalue.h"
/* node allocation
*/
struct _GAllocator /* from gmem.c */
{
gchar *name;
guint16 n_preallocs;
guint is_unused : 1;
guint type : 4;
GAllocator *last;
GMemChunk *mem_chunk;
GtkTreeDataList *free_nodes;
};
G_LOCK_DEFINE_STATIC (current_allocator);
static GAllocator *current_allocator = NULL;
/* HOLDS: current_allocator_lock */
static void
gtk_tree_data_list_validate_allocator (GAllocator *allocator)
{
g_return_if_fail (allocator != NULL);
g_return_if_fail (allocator->is_unused == TRUE);
if (allocator->type != G_ALLOCATOR_NODE)
{
allocator->type = G_ALLOCATOR_NODE;
if (allocator->mem_chunk)
{
g_mem_chunk_destroy (allocator->mem_chunk);
allocator->mem_chunk = NULL;
}
}
if (!allocator->mem_chunk)
{
allocator->mem_chunk = g_mem_chunk_new (allocator->name,
sizeof (GtkTreeDataList),
sizeof (GtkTreeDataList) * allocator->n_preallocs,
G_ALLOC_ONLY);
allocator->free_nodes = NULL;
}
allocator->is_unused = FALSE;
}
void
gtk_tree_data_list_push_allocator (GAllocator *allocator)
{
G_LOCK (current_allocator);
gtk_tree_data_list_validate_allocator ( allocator );
allocator->last = current_allocator;
current_allocator = allocator;
G_UNLOCK (current_allocator);
}
void
gtk_tree_data_list_pop_allocator (void)
{
G_LOCK (current_allocator);
if (current_allocator)
{
GAllocator *allocator;
allocator = current_allocator;
current_allocator = allocator->last;
allocator->last = NULL;
allocator->is_unused = TRUE;
}
G_UNLOCK (current_allocator);
}
GtkTreeDataList *
gtk_tree_data_list_alloc (void)
{
GtkTreeDataList *list;
G_LOCK (current_allocator);
if (!current_allocator)
{
GAllocator *allocator = g_allocator_new ("GTK+ default GtkTreeDataList allocator",
128);
gtk_tree_data_list_validate_allocator (allocator);
allocator->last = NULL;
current_allocator = allocator;
}
if (!current_allocator->free_nodes)
list = g_chunk_new (GtkTreeDataList, current_allocator->mem_chunk);
else
{
list = current_allocator->free_nodes;
current_allocator->free_nodes = list->next;
}
G_UNLOCK (current_allocator);
return list;
}
void
gtk_tree_data_list_free (GtkTreeDataList *list)
{
G_LOCK (current_allocator);
list->next = current_allocator->free_nodes;
current_allocator->free_nodes = list;
G_UNLOCK (current_allocator);
}
void
gtk_tree_data_list_node_to_value (GtkTreeDataList *list,
GType type,
GValue *value)
{
g_value_init (value, type);
switch (type)
{
case G_TYPE_STRING:
g_value_set_string (value, (gchar *) list->data.v_pointer);
break;
}
}
void
gtk_tree_data_list_value_to_node (GtkTreeDataList *list,
GValue *value)
{
switch (value->g_type)
{
case G_TYPE_STRING:
list->data.v_pointer = g_value_dup_string (value);
break;
default:
g_warning ("Unsupported type (%s) stored.", g_type_name (value->g_type));
return;
}
}

53
gtk/gtktreedatalist.h Normal file
View File

@ -0,0 +1,53 @@
/* gtktreedatalist.h
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GTK_TREE_DATA_LIST_H__
#define __GTK_TREE_DATA_LIST_H__
#include <glib.h>
#include <gobject/gobject.h>
typedef struct _GtkTreeDataList GtkTreeDataList;
struct _GtkTreeDataList
{
GtkTreeDataList *next;
union {
gint v_int;
guint v_uint;
gfloat v_float;
gpointer v_pointer;
} data;
};
/* FIXME: s/gtk/_gtk/g to make internal */
void gtk_tree_data_list_push_allocator (GAllocator *allocator);
void gtk_tree_data_list_pop_allocator (void);
GtkTreeDataList *gtk_tree_data_list_alloc (void);
void gtk_tree_data_list_free (GtkTreeDataList *list);
void gtk_tree_data_list_node_to_value (GtkTreeDataList *list,
GType type,
GValue *value);
void gtk_tree_data_list_value_to_node (GtkTreeDataList *list,
GValue *value);
#endif /* __GTK_TREE_DATA_LIST_H__ */

421
gtk/gtktreemodel.c Normal file
View File

@ -0,0 +1,421 @@
/* gtktreemodel.c
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "gtktreemodel.h"
#include "gtksignal.h"
enum {
NODE_CHANGED,
NODE_INSERTED,
NODE_CHILD_TOGGLED,
NODE_DELETED,
LAST_SIGNAL
};
struct _GtkTreePath
{
gint depth;
gint *indices;
};
static void gtk_tree_model_init (GtkTreeModel *tree_model);
static void gtk_tree_model_class_init (GtkTreeModelClass *klass);
static GtkObjectClass *parent_class = NULL;
static guint tree_model_signals[LAST_SIGNAL] = { 0 };
GtkType
gtk_tree_model_get_type (void)
{
static GtkType tree_model_type = 0;
if (!tree_model_type)
{
static const GTypeInfo tree_model_info =
{
sizeof (GtkTreeModelClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gtk_tree_model_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GtkTreeModel),
0, /* n_preallocs */
(GInstanceInitFunc) gtk_tree_model_init
};
tree_model_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkTreeModel", &tree_model_info);
}
return tree_model_type;
}
static void
gtk_tree_model_class_init (GtkTreeModelClass *class)
{
GtkObjectClass *object_class;
object_class = (GtkObjectClass*) class;
parent_class = g_type_class_peek_parent (class);
tree_model_signals[NODE_CHANGED] =
gtk_signal_new ("node_changed",
GTK_RUN_FIRST,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkTreeModelClass, node_changed),
gtk_marshal_NONE__POINTER_POINTER,
GTK_TYPE_NONE, 2,
GTK_TYPE_POINTER,
GTK_TYPE_POINTER);
tree_model_signals[NODE_INSERTED] =
gtk_signal_new ("node_inserted",
GTK_RUN_FIRST,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkTreeModelClass, node_inserted),
gtk_marshal_NONE__POINTER_POINTER,
GTK_TYPE_NONE, 2,
GTK_TYPE_POINTER,
GTK_TYPE_POINTER);
tree_model_signals[NODE_CHILD_TOGGLED] =
gtk_signal_new ("node_child_toggled",
GTK_RUN_FIRST,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkTreeModelClass, node_child_toggled),
gtk_marshal_NONE__POINTER_POINTER,
GTK_TYPE_NONE, 2,
GTK_TYPE_POINTER,
GTK_TYPE_POINTER);
tree_model_signals[NODE_DELETED] =
gtk_signal_new ("node_deleted",
GTK_RUN_FIRST,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkTreeModelClass, node_deleted),
gtk_marshal_NONE__POINTER,
GTK_TYPE_NONE, 1,
GTK_TYPE_POINTER);
gtk_object_class_add_signals (object_class, tree_model_signals, LAST_SIGNAL);
class->get_node = NULL;
class->node_next = NULL;
class->node_children = NULL;
class->node_n_children = NULL;
class->node_nth_child = NULL;
class->node_parent = NULL;
}
static void
gtk_tree_model_init (GtkTreeModel *tree_model)
{
}
/* GtkTreePath Operations */
GtkTreePath *
gtk_tree_path_new (void)
{
GtkTreePath *retval;
retval = (GtkTreePath *) g_new (GtkTreePath, 1);
retval->depth = 0;
retval->indices = NULL;
return retval;
}
GtkTreePath *
gtk_tree_path_new_from_string (gchar *path)
{
GtkTreePath *retval;
gchar *ptr;
gint i;
g_return_val_if_fail (path != NULL, gtk_tree_path_new ());
retval = gtk_tree_path_new ();
while (1)
{
i = strtol (path, &ptr, 10);
gtk_tree_path_append_index (retval, i);
if (*ptr == '\000')
break;
path = ptr + 1;
}
return retval;
}
gchar *
gtk_tree_path_to_string (GtkTreePath *path)
{
gchar *retval, *ptr;
gint i;
if (path->depth == 0)
return NULL;
ptr = retval = (gchar *) g_new0 (char *, path->depth*8);
sprintf (retval, "%d", path->indices[0]);
while (*ptr != '\000')
ptr++;
for (i = 1; i < path->depth; i++)
{
sprintf (ptr, ":%d", path->indices[i]);
while (*ptr != '\000')
ptr++;
}
return retval;
}
GtkTreePath *
gtk_tree_path_new_root (void)
{
GtkTreePath *retval;
retval = gtk_tree_path_new ();
gtk_tree_path_append_index (retval, 0);
return retval;
}
void
gtk_tree_path_append_index (GtkTreePath *path,
gint index)
{
gint *new_indices = g_new (gint, ++path->depth);
if (path->indices == NULL)
{
path->indices = new_indices;
path->indices[0] = index;
return;
}
memcpy (new_indices, path->indices, (path->depth - 1)*sizeof (gint));
g_free (path->indices);
path->indices = new_indices;
path->indices[path->depth - 1] = index;
}
void
gtk_tree_path_prepend_index (GtkTreePath *path,
gint index)
{
gint *new_indices = g_new (gint, ++path->depth);
if (path->indices == NULL)
{
path->indices = new_indices;
path->indices[0] = index;
return;
}
memcpy (new_indices + 1, path->indices, (path->depth - 1)*sizeof (gint));
g_free (path->indices);
path->indices = new_indices;
path->indices[0] = index;
}
gint
gtk_tree_path_get_depth (GtkTreePath *path)
{
return path->depth;
}
gint *
gtk_tree_path_get_indices (GtkTreePath *path)
{
return path->indices;
}
void
gtk_tree_path_free (GtkTreePath *path)
{
g_free (path->indices);
g_free (path);
}
GtkTreePath *
gtk_tree_path_copy (GtkTreePath *path)
{
GtkTreePath *retval;
retval = g_new (GtkTreePath, 1);
retval->depth = path->depth;
retval->indices = g_new (gint, path->depth);
memcpy (retval->indices, path->indices, path->depth * sizeof (gint));
return retval;
}
gint
gtk_tree_path_compare (GtkTreePath *a,
GtkTreePath *b)
{
gint p = 0, q = 0;
g_return_val_if_fail (a != NULL, 0);
g_return_val_if_fail (b != NULL, 0);
g_return_val_if_fail (a->depth > 0, 0);
g_return_val_if_fail (b->depth > 0, 0);
do
{
if (a->indices[p] == b->indices[q])
continue;
return (a->indices[p] < b->indices[q]?1:-1);
}
while (++p < a->depth && ++q < b->depth);
if (a->depth == b->depth)
return 0;
return (a->depth < b->depth?1:-1);
}
void
gtk_tree_path_next (GtkTreePath *path)
{
g_return_if_fail (path != NULL);
path->indices[path->depth - 1] ++;
}
gint
gtk_tree_path_prev (GtkTreePath *path)
{
g_return_val_if_fail (path != NULL, FALSE);
if (path->indices[path->depth] == 0)
return FALSE;
path->indices[path->depth - 1] --;
return TRUE;
}
gint
gtk_tree_path_up (GtkTreePath *path)
{
g_return_val_if_fail (path != NULL, FALSE);
if (path->depth == 1)
return FALSE;
path->depth--;
return TRUE;
}
void
gtk_tree_path_down (GtkTreePath *path)
{
g_return_if_fail (path != NULL);
gtk_tree_path_append_index (path, 0);
}
gint
gtk_tree_model_get_n_columns (GtkTreeModel *tree_model)
{
g_return_val_if_fail (GTK_TREE_MODEL_GET_CLASS (tree_model)->get_n_columns != NULL, 0);
return (* GTK_TREE_MODEL_GET_CLASS (tree_model)->get_n_columns) (tree_model);
}
/* Node options */
GtkTreeNode
gtk_tree_model_get_node (GtkTreeModel *tree_model,
GtkTreePath *path)
{
g_return_val_if_fail (GTK_TREE_MODEL_GET_CLASS (tree_model)->get_node != NULL, NULL);
return (* GTK_TREE_MODEL_GET_CLASS (tree_model)->get_node) (tree_model, path);
}
GtkTreePath *
gtk_tree_model_get_path (GtkTreeModel *tree_model,
GtkTreeNode node)
{
g_return_val_if_fail (GTK_TREE_MODEL_GET_CLASS (tree_model)->get_path != NULL, NULL);
return (* GTK_TREE_MODEL_GET_CLASS (tree_model)->get_path) (tree_model, node);
}
void
gtk_tree_model_node_get_value (GtkTreeModel *tree_model,
GtkTreeNode node,
gint column,
GValue *value)
{
g_return_if_fail (GTK_TREE_MODEL_GET_CLASS (tree_model)->node_get_value != NULL);
(* GTK_TREE_MODEL_GET_CLASS (tree_model)->node_get_value) (tree_model, node, column, value);
}
gboolean
gtk_tree_model_node_next (GtkTreeModel *tree_model,
GtkTreeNode *node)
{
g_return_val_if_fail (GTK_TREE_MODEL_GET_CLASS (tree_model)->node_next != NULL, FALSE);
return (* GTK_TREE_MODEL_GET_CLASS (tree_model)->node_next) (tree_model, node);
}
GtkTreeNode
gtk_tree_model_node_children (GtkTreeModel *tree_model,
GtkTreeNode node)
{
g_return_val_if_fail (GTK_TREE_MODEL_GET_CLASS (tree_model)->node_children != NULL, NULL);
return (* GTK_TREE_MODEL_GET_CLASS (tree_model)->node_children) (tree_model, node);
}
gboolean
gtk_tree_model_node_has_child (GtkTreeModel *tree_model,
GtkTreeNode node)
{
g_return_val_if_fail (GTK_TREE_MODEL_GET_CLASS (tree_model)->node_has_child != NULL, FALSE);
return (* GTK_TREE_MODEL_GET_CLASS (tree_model)->node_has_child) (tree_model, node);
}
gint
gtk_tree_model_node_n_children (GtkTreeModel *tree_model,
GtkTreeNode node)
{
g_return_val_if_fail (GTK_TREE_MODEL_GET_CLASS (tree_model)->node_n_children != NULL, -1);
return (* GTK_TREE_MODEL_GET_CLASS (tree_model)->node_n_children) (tree_model, node);
}
GtkTreeNode
gtk_tree_model_node_nth_child (GtkTreeModel *tree_model,
GtkTreeNode node,
gint n)
{
g_return_val_if_fail (GTK_TREE_MODEL_GET_CLASS (tree_model)->node_nth_child != NULL, NULL);
return (* GTK_TREE_MODEL_GET_CLASS (tree_model)->node_nth_child) (tree_model, node, n);
}
GtkTreeNode
gtk_tree_model_node_parent (GtkTreeModel *tree_model,
GtkTreeNode node)
{
g_return_val_if_fail (GTK_TREE_MODEL_GET_CLASS (tree_model)->node_parent != NULL, NULL);
return (* GTK_TREE_MODEL_GET_CLASS (tree_model)->node_parent) (tree_model, node);
}

144
gtk/gtktreemodel.h Normal file
View File

@ -0,0 +1,144 @@
/* gtktreemodel.h
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GTK_TREE_MODEL_H__
#define __GTK_TREE_MODEL_H__
#include <gtk/gtkobject.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GTK_TYPE_TREE_MODEL (gtk_tree_model_get_type ())
#define GTK_TREE_MODEL(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_TREE_MODEL, GtkTreeModel))
#define GTK_TREE_MODEL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_TREE_MODEL, GtkTreeModelClass))
#define GTK_IS_TREE_MODEL(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_TREE_MODEL))
#define GTK_IS_TREE_MODEL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), GTK_TYPE_TREE_MODEL))
#define GTK_TREE_MODEL_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_TREE_MODEL, GtkTreeModelClass))
typedef gpointer GtkTreeNode;
typedef struct _GtkTreePath GtkTreePath;
typedef struct _GtkTreeModel GtkTreeModel;
typedef struct _GtkTreeModelClass GtkTreeModelClass;
struct _GtkTreeModel
{
GtkObject parent;
};
struct _GtkTreeModelClass
{
GtkObjectClass parent_class;
/* signals */
void (* node_changed) (GtkTreeModel *tree_model,
GtkTreePath *path,
GtkTreeNode *node);
void (* node_inserted) (GtkTreeModel *tree_model,
GtkTreePath *path,
GtkTreeNode *node);
void (* node_child_toggled) (GtkTreeModel *tree_model,
GtkTreePath *path,
GtkTreeNode *node);
void (* node_deleted) (GtkTreeModel *tree_model,
GtkTreePath *path);
/* VTable - not signals */
gint (* get_n_columns) (GtkTreeModel *tree_model);
GtkTreeNode (* get_node) (GtkTreeModel *tree_model,
GtkTreePath *path);
GtkTreePath *(* get_path) (GtkTreeModel *tree_model,
GtkTreeNode node);
void (* node_get_value) (GtkTreeModel *tree_model,
GtkTreeNode node,
gint column,
GValue *value);
gboolean (* node_next) (GtkTreeModel *tree_model,
GtkTreeNode *node);
GtkTreeNode (* node_children) (GtkTreeModel *tree_model,
GtkTreeNode node);
gboolean (* node_has_child) (GtkTreeModel *tree_model,
GtkTreeNode node);
gint (* node_n_children) (GtkTreeModel *tree_model,
GtkTreeNode node);
GtkTreeNode (* node_nth_child) (GtkTreeModel *tree_model,
GtkTreeNode node,
gint n);
GtkTreeNode (* node_parent) (GtkTreeModel *tree_model,
GtkTreeNode node);
};
/* Basic tree_model operations */
GtkType gtk_tree_model_get_type (void);
/* GtkTreePath Operations */
GtkTreePath *gtk_tree_path_new (void);
GtkTreePath *gtk_tree_path_new_from_string (gchar *path);
gchar *gtk_tree_path_to_string (GtkTreePath *path);
GtkTreePath *gtk_tree_path_new_root (void);
void gtk_tree_path_append_index (GtkTreePath *path,
gint index);
void gtk_tree_path_prepend_index (GtkTreePath *path,
gint index);
gint gtk_tree_path_get_depth (GtkTreePath *path);
gint *gtk_tree_path_get_indices (GtkTreePath *path);
void gtk_tree_path_free (GtkTreePath *path);
GtkTreePath *gtk_tree_path_copy (GtkTreePath *path);
gint gtk_tree_path_compare (GtkTreePath *a,
GtkTreePath *b);
void gtk_tree_path_next (GtkTreePath *path);
gint gtk_tree_path_prev (GtkTreePath *path);
gint gtk_tree_path_up (GtkTreePath *path);
void gtk_tree_path_down (GtkTreePath *path);
/* Header operations */
gint gtk_tree_model_get_n_columns (GtkTreeModel *tree_model);
/* Node operations */
GtkTreeNode gtk_tree_model_get_node (GtkTreeModel *tree_model,
GtkTreePath *path);
GtkTreePath *gtk_tree_model_get_path (GtkTreeModel *tree_model,
GtkTreeNode node);
void gtk_tree_model_node_get_value (GtkTreeModel *tree_model,
GtkTreeNode node,
gint column,
GValue *value);
gboolean gtk_tree_model_node_next (GtkTreeModel *tree_model,
GtkTreeNode *node);
GtkTreeNode gtk_tree_model_node_children (GtkTreeModel *tree_model,
GtkTreeNode node);
gboolean gtk_tree_model_node_has_child (GtkTreeModel *tree_model,
GtkTreeNode node);
gint gtk_tree_model_node_n_children (GtkTreeModel *tree_model,
GtkTreeNode node);
GtkTreeNode gtk_tree_model_node_nth_child (GtkTreeModel *tree_model,
GtkTreeNode node,
gint n);
GtkTreeNode gtk_tree_model_node_parent (GtkTreeModel *tree_model,
GtkTreeNode node);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_TREE_MODEL_H__ */

191
gtk/gtktreeprivate.h Normal file
View File

@ -0,0 +1,191 @@
/* gtktreeprivate.h
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GTK_TREE_PRIVATE_H__
#define __GTK_TREE_PRIVATE_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <gtk/gtktreeview.h>
#include <gtk/gtktreeselection.h>
#include <gtk/gtkrbtree.h>
typedef enum {
GTK_TREE_VIEW_IS_LIST = 1 << 0,
GTK_TREE_VIEW_SHOW_EXPANDERS = 1 << 1,
GTK_TREE_VIEW_IN_COLUMN_RESIZE = 1 << 2,
GTK_TREE_VIEW_ARROW_PRELIT = 1 << 3,
GTK_TREE_VIEW_HEADERS_VISIBLE = 1 << 4,
GTK_TREE_VIEW_DRAW_KEYFOCUS = 1 << 5,
GTK_TREE_VIEW_MODEL_SETUP = 1 << 6
} GtkTreeViewFlags;
#define GTK_TREE_VIEW_SET_FLAG(tree_view, flag) G_STMT_START{ (tree_view->priv->flags|=flag); }G_STMT_END
#define GTK_TREE_VIEW_UNSET_FLAG(tree_view, flag) G_STMT_START{ (tree_view->priv->flags&=~(flag)); }G_STMT_END
#define GTK_TREE_VIEW_FLAG_SET(tree_view, flag) ((tree_view->priv->flags&flag)==flag)
#define TREE_VIEW_HEADER_HEIGHT(tree_view) (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE)?tree_view->priv->header_height:0)
#define TREE_VIEW_COLUMN_SIZE(column) (CLAMP (column->size, (column->min_width!=-1)?column->min_width:column->size, (column->max_width!=-1)?column->max_width:column->size))
#define TREE_VIEW_DRAW_EXPANDERS(tree_view) (!GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IS_LIST)&&GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_SHOW_EXPANDERS))
struct _GtkTreeViewPrivate
{
GtkTreeModel *model;
guint flags;
/* tree information */
GtkRBTree *tree;
gint tab_offset;
GtkRBNode *button_pressed_node;
GtkRBTree *button_pressed_tree;
GList *children;
gint width;
gint height;
GtkAdjustment *hadjustment;
GtkAdjustment *vadjustment;
GdkWindow *bin_window;
GdkWindow *header_window;
/* Selection stuff */
GtkTreePath *anchor;
GtkTreePath *cursor;
/* Column Resizing */
GdkCursor *cursor_drag;
GdkGC *xor_gc;
gint drag_pos;
gint x_drag;
/* Prelight information */
GtkRBNode *prelight_node;
GtkRBTree *prelight_tree;
gint prelight_offset;
/* Selection information */
GtkTreeSelection *selection;
/* Header information */
gint columns;
GList *column;
gint header_height;
};
#ifdef __GNUC__
#define TREE_VIEW_INTERNAL_ASSERT(expr, ret) G_STMT_START{ \
if (!(expr)) \
{ \
g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_CRITICAL, \
"file %s: line %d (%s): assertion `%s' failed.\n" \
"There is a disparity between the internal view of the GtkTreeView,\n" \
"and the GtkTreeModel. This generally means that the model has changed\n"\
"without letting the view know. Any display from now on is likely to\n" \
"be incorrect.\n", \
__FILE__, \
__LINE__, \
__PRETTY_FUNCTION__, \
#expr); \
return ret; \
}; }G_STMT_END
#define TREE_VIEW_INTERNAL_ASSERT_VOID(expr) G_STMT_START{ \
if (!(expr)) \
{ \
g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_CRITICAL, \
"file %s: line %d (%s): assertion `%s' failed.\n" \
"There is a disparity between the internal view of the GtkTreeView,\n" \
"and the GtkTreeModel. This generally means that the model has changed\n"\
"without letting the view know. Any display from now on is likely to\n" \
"be incorrect.\n", \
__FILE__, \
__LINE__, \
__PRETTY_FUNCTION__, \
#expr); \
return; \
}; }G_STMT_END
#else
#define TREE_VIEW_INTERNAL_ASSERT(expr, ret) G_STMT_START{ \
if (!(expr)) \
{ \
g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_CRITICAL, \
"file %s: line %d: assertion `%s' failed.\n" \
"There is a disparity between the internal view of the GtkTreeView,\n" \
"and the GtkTreeModel. This generally means that the model has changed\n"\
"without letting the view know. Any display from now on is likely to\n" \
"be incorrect.\n", \
__FILE__, \
__LINE__, \
#expr); \
return ret; \
}; }G_STMT_END
#define TREE_VIEW_INTERNAL_ASSERT_VOID(expr) G_STMT_START{ \
if (!(expr)) \
{ \
g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_CRITICAL, \
"file %s: line %d: assertion '%s' failed.\n" \
"There is a disparity between the internal view of the GtkTreeView,\n" \
"and the GtkTreeModel. This generally means that the model has changed\n"\
"without letting the view know. Any display from now on is likely to\n" \
"be incorrect.\n", \
__FILE__, \
__LINE__, \
#expr); \
return; \
}; }G_STMT_END
#endif
/* functions that shouldn't be exported */
void _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection,
GtkRBNode *node,
GtkRBTree *tree,
GtkTreePath *path,
GdkModifierType state);
gboolean _gtk_tree_view_find_node (GtkTreeView *tree_view,
GtkTreePath *path,
GtkRBTree **tree,
GtkRBNode **node);
GtkTreePath *_gtk_tree_view_find_path (GtkTreeView *tree_view,
GtkRBTree *tree,
GtkRBNode *node);
void _gtk_tree_view_set_size (GtkTreeView *tree_view,
gint width,
gint height);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_TREE_PRIVATE_H__ */

702
gtk/gtktreeselection.c Normal file
View File

@ -0,0 +1,702 @@
/* gtktreeselection.h
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "gtktreeselection.h"
#include "gtktreeprivate.h"
#include "gtkrbtree.h"
#include "gtksignal.h"
static void gtk_tree_selection_init (GtkTreeSelection *selection);
static void gtk_tree_selection_class_init (GtkTreeSelectionClass *class);
enum {
ROW_SELECTED,
ROW_UNSELECTED,
LAST_SIGNAL
};
static GtkObjectClass *parent_class = NULL;
static guint tree_selection_signals[LAST_SIGNAL] = { 0 };
static void
gtk_tree_selection_real_select_node (GtkTreeSelection *selection, GtkRBTree *tree, GtkRBNode *node, gboolean select)
{
gboolean selected = FALSE;
GtkTreePath *path = NULL;
if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) != select)
{
path = _gtk_tree_view_find_path (selection->tree_view, tree, node);
if (selection->user_func)
{
if ((*selection->user_func) (selection, selection->tree_view->priv->model, path, selection->user_data))
selected = TRUE;
}
else
selected = TRUE;
}
if (selected == TRUE)
{
GtkTreeNode tree_node;
tree_node = gtk_tree_model_get_node (selection->tree_view->priv->model, path);
node->flags ^= GTK_RBNODE_IS_SELECTED;
if (select)
gtk_signal_emit (GTK_OBJECT (selection), tree_selection_signals[ROW_SELECTED], selection->tree_view->priv->model, tree_node);
else
gtk_signal_emit (GTK_OBJECT (selection), tree_selection_signals[ROW_UNSELECTED], selection->tree_view->priv->model, tree_node);
gtk_widget_queue_draw (GTK_WIDGET (selection->tree_view));
}
}
GtkType
gtk_tree_selection_get_type (void)
{
static GtkType selection_type = 0;
if (!selection_type)
{
static const GTypeInfo selection_info =
{
sizeof (GtkTreeSelectionClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gtk_tree_selection_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GtkTreeSelection),
0, /* n_preallocs */
(GInstanceInitFunc) gtk_tree_selection_init
};
selection_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkTreeSelection", &selection_info);
}
return selection_type;
}
static void
gtk_tree_selection_class_init (GtkTreeSelectionClass *class)
{
GtkObjectClass *object_class;
object_class = (GtkObjectClass*) class;
parent_class = g_type_class_peek_parent (class);
tree_selection_signals[ROW_SELECTED] =
gtk_signal_new ("row_selected",
GTK_RUN_FIRST,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkTreeSelectionClass, row_selected),
gtk_marshal_NONE__POINTER_POINTER,
GTK_TYPE_NONE, 2,
GTK_TYPE_POINTER,
GTK_TYPE_POINTER);
tree_selection_signals[ROW_UNSELECTED] =
gtk_signal_new ("row_unselected",
GTK_RUN_FIRST,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkTreeSelectionClass, row_unselected),
gtk_marshal_NONE__POINTER_POINTER,
GTK_TYPE_NONE, 2,
GTK_TYPE_POINTER,
GTK_TYPE_POINTER);
gtk_object_class_add_signals (object_class, tree_selection_signals, LAST_SIGNAL);
class->row_selected = NULL;
class->row_unselected = NULL;
}
static void
gtk_tree_selection_init (GtkTreeSelection *selection)
{
selection->type = GTK_TREE_SELECTION_MULTI;
selection->user_func = NULL;
selection->user_data = NULL;
selection->user_func = NULL;
selection->tree_view = NULL;
}
GtkObject *
gtk_tree_selection_new (void)
{
GtkObject *selection;
selection = GTK_OBJECT (gtk_type_new (GTK_TYPE_TREE_SELECTION));
return selection;
}
GtkObject *
gtk_tree_selection_new_with_tree_view (GtkTreeView *tree_view)
{
GtkObject *selection;
g_return_val_if_fail (tree_view != NULL, NULL);
g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
selection = gtk_tree_selection_new ();
gtk_tree_selection_set_tree_view (GTK_TREE_SELECTION (selection), tree_view);
return selection;
}
void
gtk_tree_selection_set_tree_view (GtkTreeSelection *selection,
GtkTreeView *tree_view)
{
g_return_if_fail (selection != NULL);
g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
if (tree_view != NULL)
g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
selection->tree_view = tree_view;
tree_view->priv->selection = selection;
}
void
gtk_tree_selection_set_type (GtkTreeSelection *selection,
GtkTreeSelectionType type)
{
g_return_if_fail (selection != NULL);
g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
if (selection->type == type)
return;
if (type == GTK_TREE_SELECTION_SINGLE)
{
GtkRBTree *tree = NULL;
GtkRBNode *node = NULL;
gint selected = FALSE;
if (selection->tree_view->priv->anchor)
{
_gtk_tree_view_find_node (selection->tree_view,
selection->tree_view->priv->anchor,
&tree,
&node);
if (node && GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
selected = TRUE;
}
gtk_tree_selection_unselect_all (selection);
if (node && selected)
GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SELECTED);
}
selection->type = type;
}
void
gtk_tree_selection_set_select_function (GtkTreeSelection *selection,
GtkTreeSelectionFunc func,
gpointer data)
{
g_return_if_fail (selection != NULL);
g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
g_return_if_fail (func != NULL);
selection->user_func = func;
selection->user_data = data;
}
gpointer
gtk_tree_selection_get_user_data (GtkTreeSelection *selection)
{
g_return_val_if_fail (selection != NULL, NULL);
g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
return selection->user_data;
}
GtkTreeNode *
gtk_tree_selection_get_selected (GtkTreeSelection *selection)
{
GtkTreeNode *retval;
GtkRBTree *tree;
GtkRBNode *node;
g_return_val_if_fail (selection != NULL, NULL);
g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
if (selection->tree_view->priv->anchor == NULL)
return NULL;
g_return_val_if_fail (selection->tree_view != NULL, NULL);
g_return_val_if_fail (selection->tree_view->priv->model != NULL, NULL);
if (!_gtk_tree_view_find_node (selection->tree_view,
selection->tree_view->priv->anchor,
&tree,
&node) &&
! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
/* We don't want to return the anchor if it isn't actually selected.
*/
return NULL;
retval = gtk_tree_model_get_node (selection->tree_view->priv->model,
selection->tree_view->priv->anchor);
return retval;
}
void
gtk_tree_selection_selected_foreach (GtkTreeSelection *selection,
GtkTreeSelectionForeachFunc func,
gpointer data)
{
GtkTreePath *path;
GtkRBTree *tree;
GtkRBNode *node;
GtkTreeNode tree_node;
g_return_if_fail (selection != NULL);
g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
g_return_if_fail (selection->tree_view != NULL);
g_return_if_fail (selection->tree_view->priv->model != NULL);
if (func == NULL ||
selection->tree_view->priv->tree == NULL ||
selection->tree_view->priv->tree->root == NULL)
return;
tree = selection->tree_view->priv->tree;
node = selection->tree_view->priv->tree->root;
while (node->left != tree->nil)
node = node->left;
/* find the node internally */
path = gtk_tree_path_new_root ();
tree_node = gtk_tree_model_get_node (selection->tree_view->priv->model, path);
gtk_tree_path_free (path);
do
{
if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
(* func) (selection->tree_view->priv->model, tree_node, data);
if (node->children)
{
tree = node->children;
node = tree->root;
while (node->left != tree->nil)
node = node->left;
tree_node = gtk_tree_model_node_children (selection->tree_view->priv->model, tree_node);
/* Sanity Check! */
TREE_VIEW_INTERNAL_ASSERT_VOID (tree_node != NULL);
}
else
{
gboolean done = FALSE;
do
{
node = _gtk_rbtree_next (tree, node);
if (node != NULL)
{
gtk_tree_model_node_next (selection->tree_view->priv->model, &tree_node);
done = TRUE;
/* Sanity Check! */
TREE_VIEW_INTERNAL_ASSERT_VOID (tree_node != NULL);
}
else
{
node = tree->parent_node;
tree = tree->parent_tree;
if (tree == NULL)
/* we've run out of tree */
/* We're done with this function */
return;
tree_node = gtk_tree_model_node_parent (selection->tree_view->priv->model, tree_node);
/* Sanity check */
TREE_VIEW_INTERNAL_ASSERT_VOID (tree_node != NULL);
}
}
while (!done);
}
}
while (TRUE);
}
void
gtk_tree_selection_select_path (GtkTreeSelection *selection,
GtkTreePath *path)
{
GtkRBNode *node;
GtkRBTree *tree;
GdkModifierType state = 0;
g_return_if_fail (selection != NULL);
g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
g_return_if_fail (selection->tree_view != NULL);
g_return_if_fail (path != NULL);
_gtk_tree_view_find_node (selection->tree_view,
path,
&tree,
&node);
if (node == NULL || GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
return;
if (selection->type == GTK_TREE_SELECTION_MULTI)
state = GDK_CONTROL_MASK;
_gtk_tree_selection_internal_select_node (selection,
node,
tree,
path,
state);
}
void
gtk_tree_selection_unselect_path (GtkTreeSelection *selection,
GtkTreePath *path)
{
GtkRBNode *node;
GtkRBTree *tree;
g_return_if_fail (selection != NULL);
g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
g_return_if_fail (selection->tree_view != NULL);
g_return_if_fail (path != NULL);
_gtk_tree_view_find_node (selection->tree_view,
path,
&tree,
&node);
if (node == NULL || !GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
return;
_gtk_tree_selection_internal_select_node (selection,
node,
tree,
path,
GDK_CONTROL_MASK);
}
void
gtk_tree_selection_select_node (GtkTreeSelection *selection,
GtkTreeNode *tree_node)
{
GtkTreePath *path;
g_return_if_fail (selection != NULL);
g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
g_return_if_fail (selection->tree_view != NULL);
g_return_if_fail (selection->tree_view->priv->model != NULL);
path = gtk_tree_model_get_path (selection->tree_view->priv->model,
tree_node);
if (path == NULL)
return;
gtk_tree_selection_select_path (selection, path);
gtk_tree_path_free (path);
}
void
gtk_tree_selection_unselect_node (GtkTreeSelection *selection,
GtkTreeNode *tree_node)
{
GtkTreePath *path;
g_return_if_fail (selection != NULL);
g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
g_return_if_fail (selection->tree_view != NULL);
path = gtk_tree_model_get_path (selection->tree_view->priv->model,
tree_node);
if (path == NULL)
return;
gtk_tree_selection_select_path (selection, path);
gtk_tree_path_free (path);
}
/* Wish I was in python, right now... */
struct _TempTuple {
GtkTreeSelection *selection;
gint dirty;
};
static void
select_all_helper (GtkRBTree *tree,
GtkRBNode *node,
gpointer data)
{
struct _TempTuple *tuple = data;
if (node->children)
_gtk_rbtree_traverse (node->children,
node->children->root,
G_PRE_ORDER,
select_all_helper,
data);
if (!GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
{
gtk_tree_selection_real_select_node (tuple->selection, tree, node, TRUE);
tuple->dirty = TRUE;
}
}
void
gtk_tree_selection_select_all (GtkTreeSelection *selection)
{
struct _TempTuple *tuple;
g_return_if_fail (selection != NULL);
g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
g_return_if_fail (selection->tree_view != NULL);
g_return_if_fail (selection->tree_view->priv->tree != NULL);
if (selection->type == GTK_TREE_SELECTION_SINGLE)
{
GtkRBNode *node;
node = selection->tree_view->priv->tree->root;
while (node->right != selection->tree_view->priv->tree->nil)
node = node->right;
return;
}
tuple = g_new (struct _TempTuple, 1);
tuple->selection = selection;
tuple->dirty = FALSE;
_gtk_rbtree_traverse (selection->tree_view->priv->tree,
selection->tree_view->priv->tree->root,
G_PRE_ORDER,
select_all_helper,
tuple);
if (tuple->dirty)
gtk_widget_queue_draw (GTK_WIDGET (selection->tree_view));
g_free (tuple);
}
static void
unselect_all_helper (GtkRBTree *tree,
GtkRBNode *node,
gpointer data)
{
struct _TempTuple *tuple = data;
if (node->children)
_gtk_rbtree_traverse (node->children,
node->children->root,
G_PRE_ORDER,
unselect_all_helper,
data);
if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
{
gtk_tree_selection_real_select_node (tuple->selection, tree, node, FALSE);
tuple->dirty = TRUE;
}
}
void
gtk_tree_selection_unselect_all (GtkTreeSelection *selection)
{
struct _TempTuple *tuple;
g_return_if_fail (selection != NULL);
g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
g_return_if_fail (selection->tree_view != NULL);
if (selection->tree_view->priv->tree == NULL)
return;
if (selection->type == GTK_TREE_SELECTION_SINGLE)
{
GtkRBTree *tree = NULL;
GtkRBNode *node = NULL;
if (selection->tree_view->priv->anchor == NULL)
return;
_gtk_tree_view_find_node (selection->tree_view,
selection->tree_view->priv->anchor,
&tree,
&node);
if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
gtk_tree_selection_real_select_node (selection, tree, node, FALSE);
return;
}
tuple = g_new (struct _TempTuple, 1);
tuple->selection = selection;
tuple->dirty = FALSE;
_gtk_rbtree_traverse (selection->tree_view->priv->tree,
selection->tree_view->priv->tree->root,
G_PRE_ORDER,
unselect_all_helper,
tuple);
if (tuple->dirty)
gtk_widget_queue_draw (GTK_WIDGET (selection->tree_view));
g_free (tuple);
}
void
gtk_tree_selection_select_range (GtkTreeSelection *selection,
GtkTreePath *start_path,
GtkTreePath *end_path)
{
GtkRBNode *start_node, *end_node;
GtkRBTree *start_tree, *end_tree;
g_return_if_fail (selection != NULL);
g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
g_return_if_fail (selection->tree_view != NULL);
switch (gtk_tree_path_compare (start_path, end_path))
{
case -1:
_gtk_tree_view_find_node (selection->tree_view,
end_path,
&start_tree,
&start_node);
_gtk_tree_view_find_node (selection->tree_view,
start_path,
&end_tree,
&end_node);
break;
case 0:
_gtk_tree_view_find_node (selection->tree_view,
start_path,
&start_tree,
&start_node);
end_tree = start_tree;
end_node = start_node;
break;
case 1:
_gtk_tree_view_find_node (selection->tree_view,
start_path,
&start_tree,
&start_node);
_gtk_tree_view_find_node (selection->tree_view,
end_path,
&end_tree,
&end_node);
break;
}
g_return_if_fail (start_node != NULL);
g_return_if_fail (end_node != NULL);
do
{
gtk_tree_selection_real_select_node (selection, start_tree, start_node, TRUE);
if (start_node == end_node)
return;
if (start_node->children)
{
start_tree = start_node->children;
start_node = start_tree->root;
while (start_node->left != start_tree->nil)
start_node = start_node->left;
}
else
{
gboolean done = FALSE;
do
{
start_node = _gtk_rbtree_next (start_tree, start_node);
if (start_node != NULL)
{
done = TRUE;
}
else
{
start_node = start_tree->parent_node;
start_tree = start_tree->parent_tree;
if (start_tree == NULL)
/* we've run out of tree */
/* This means we never found end node!! */
return;
}
}
while (!done);
}
}
while (TRUE);
}
/* Called internally by gtktree_view. It handles actually selecting
* the tree. This should almost certainly ever be called by
* anywhere else */
void
_gtk_tree_selection_internal_select_node (GtkTreeSelection *selection,
GtkRBNode *node,
GtkRBTree *tree,
GtkTreePath *path,
GdkModifierType state)
{
gint flags;
if (((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) && (selection->tree_view->priv->anchor == NULL))
{
selection->tree_view->priv->anchor = gtk_tree_path_copy (path);
gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
}
else if ((state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) == (GDK_SHIFT_MASK|GDK_CONTROL_MASK))
{
gtk_tree_selection_select_range (selection,
selection->tree_view->priv->anchor,
path);
}
else if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
{
flags = node->flags;
if (selection->type == GTK_TREE_SELECTION_SINGLE)
gtk_tree_selection_unselect_all (selection);
if (selection->tree_view->priv->anchor)
gtk_tree_path_free (selection->tree_view->priv->anchor);
selection->tree_view->priv->anchor = gtk_tree_path_copy (path);
if ((flags & GTK_RBNODE_IS_SELECTED) == GTK_RBNODE_IS_SELECTED)
gtk_tree_selection_real_select_node (selection, tree, node, FALSE);
else
gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
}
else if ((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
{
gtk_tree_selection_unselect_all (selection);
gtk_tree_selection_select_range (selection,
selection->tree_view->priv->anchor,
path);
}
else
{
gtk_tree_selection_unselect_all (selection);
if (selection->tree_view->priv->anchor)
gtk_tree_path_free (selection->tree_view->priv->anchor);
selection->tree_view->priv->anchor = gtk_tree_path_copy (path);
gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
}
}

120
gtk/gtktreeselection.h Normal file
View File

@ -0,0 +1,120 @@
/* gtktreeselection.h
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GTK_TREE_SELECTION_H__
#define __GTK_TREE_SELECTION_H__
#include <gobject/gobject.h>
#include <gtk/gtkobject.h>
#include <gtk/gtktreeview.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#warning "Die GTK_TREE_SELECTION, DIE"
#undef GTK_TREE_SELECTION
#define GTK_TYPE_TREE_SELECTION (gtk_tree_selection_get_type ())
#define GTK_TREE_SELECTION(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_TREE_SELECTION, GtkTreeSelection))
#define GTK_TREE_SELECTION_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_TREE_SELECTION, GtkTreeSelectionClass))
#define GTK_IS_TREE_SELECTION(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_TREE_SELECTION))
#define GTK_IS_TREE_SELECTION_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), GTK_TYPE_TREE_SELECTION))
typedef enum
{
GTK_TREE_SELECTION_SINGLE,
GTK_TREE_SELECTION_MULTI
} GtkTreeSelectionType;
typedef gboolean (* GtkTreeSelectionFunc) (GtkTreeSelection *selection,
GtkTreeModel *model,
GtkTreePath *path,
gpointer data);
typedef void (* GtkTreeSelectionForeachFunc) (GtkTreeModel *model,
GtkTreeNode *node,
gpointer data);
struct _GtkTreeSelection
{
GtkObject parent;
GtkTreeView *tree_view;
GtkTreeSelectionType type;
GtkTreeSelectionFunc user_func;
gpointer user_data;
};
struct _GtkTreeSelectionClass
{
GtkObjectClass parent_class;
void (* row_selected) (GtkTreeView *tree_view,
GtkTreeModel *tree_model,
GtkTreeNode *node);
void (* row_unselected) (GtkTreeView *tree_view,
GtkTreeModel *tree_model,
GtkTreeNode *node);
};
GtkType gtk_tree_selection_get_type (void);
GtkObject *gtk_tree_selection_new (void);
void gtk_tree_selection_set_type (GtkTreeSelection *selection,
GtkTreeSelectionType type);
void gtk_tree_selection_set_select_function (GtkTreeSelection *selection,
GtkTreeSelectionFunc func,
gpointer data);
gpointer gtk_tree_selection_get_user_data (GtkTreeSelection *selection);
/* Only meaningful if GTK_TREE_SELECTION_SINGLE is set */
/* Use selected_foreach for GTK_TREE_SELECTION_MULTI */
GtkTreeNode *gtk_tree_selection_get_selected (GtkTreeSelection *selection);
/* FIXME: Get a more convenient get_selection function???? one returning GSList?? */
void gtk_tree_selection_selected_foreach (GtkTreeSelection *selection,
GtkTreeSelectionForeachFunc func,
gpointer data);
void gtk_tree_selection_select_path (GtkTreeSelection *selection,
GtkTreePath *path);
void gtk_tree_selection_unselect_path (GtkTreeSelection *selection,
GtkTreePath *path);
void gtk_tree_selection_select_node (GtkTreeSelection *selection,
GtkTreeNode *tree_node);
void gtk_tree_selection_unselect_node (GtkTreeSelection *selection,
GtkTreeNode *tree_node);
void gtk_tree_selection_select_all (GtkTreeSelection *selection);
void gtk_tree_selection_unselect_all (GtkTreeSelection *selection);
void gtk_tree_selection_select_range (GtkTreeSelection *selection,
GtkTreePath *start_path,
GtkTreePath *end_path);
/*< private >*/
GtkObject *gtk_tree_selection_new_with_tree_view (GtkTreeView *tree_view);
void gtk_tree_selection_set_tree_view (GtkTreeSelection *selection,
GtkTreeView *tree_view);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_TREE_SELECTION_H__ */

655
gtk/gtktreestore.c Normal file
View File

@ -0,0 +1,655 @@
/* gtktreestore.c
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "gtktreemodel.h"
#include "gtktreestore.h"
#include "gtktreedatalist.h"
#include "gtksignal.h"
#include <string.h>
#define G_NODE(node) ((GNode *)node)
static void gtk_tree_store_init (GtkTreeStore *TreeStore);
static void gtk_tree_store_class_init (GtkTreeStoreClass *klass);
static gint gtk_tree_store_get_n_columns (GtkTreeModel *tree_model);
static GtkTreeNode gtk_tree_store_get_node (GtkTreeModel *tree_model,
GtkTreePath *path);
static GtkTreePath *gtk_tree_store_get_path (GtkTreeModel *tree_model,
GtkTreeNode node);
static void gtk_tree_store_node_get_value (GtkTreeModel *tree_model,
GtkTreeNode node,
gint column,
GValue *value);
static gboolean gtk_tree_store_node_next (GtkTreeModel *tree_model,
GtkTreeNode *node);
static GtkTreeNode gtk_tree_store_node_children (GtkTreeModel *tree_model,
GtkTreeNode node);
static gboolean gtk_tree_store_node_has_child (GtkTreeModel *tree_model,
GtkTreeNode node);
static gint gtk_tree_store_node_n_children (GtkTreeModel *tree_model,
GtkTreeNode node);
static GtkTreeNode gtk_tree_store_node_nth_child (GtkTreeModel *tree_model,
GtkTreeNode node,
gint n);
static GtkTreeNode gtk_tree_store_node_parent (GtkTreeModel *tree_model,
GtkTreeNode node);
static GtkTreeModelClass *parent_class = NULL;
GtkType
gtk_tree_store_get_type (void)
{
static GtkType tree_store_type = 0;
if (!tree_store_type)
{
static const GTypeInfo tree_store_info =
{
sizeof (GtkTreeStoreClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gtk_tree_store_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GtkTreeStore),
0, /* n_preallocs */
(GInstanceInitFunc) gtk_tree_store_init
};
tree_store_type = g_type_register_static (GTK_TYPE_TREE_MODEL, "GtkTreeStore", &tree_store_info);
}
return tree_store_type;
}
static void
gtk_tree_store_class_init (GtkTreeStoreClass *klass)
{
GtkObjectClass *object_class;
GtkTreeModelClass *tree_model_class;
object_class = (GtkObjectClass *) klass;
tree_model_class = (GtkTreeModelClass *) klass;
parent_class = gtk_type_class (gtk_tree_model_get_type ());
tree_model_class->get_n_columns = gtk_tree_store_get_n_columns;
tree_model_class->get_node = gtk_tree_store_get_node;
tree_model_class->get_path = gtk_tree_store_get_path;
tree_model_class->node_get_value = gtk_tree_store_node_get_value;
tree_model_class->node_next = gtk_tree_store_node_next;
tree_model_class->node_children = gtk_tree_store_node_children;
tree_model_class->node_has_child = gtk_tree_store_node_has_child;
tree_model_class->node_n_children = gtk_tree_store_node_n_children;
tree_model_class->node_nth_child = gtk_tree_store_node_nth_child;
tree_model_class->node_parent = gtk_tree_store_node_parent;
}
static void
gtk_tree_store_init (GtkTreeStore *tree_store)
{
tree_store->root = gtk_tree_store_node_new ();
}
GtkObject *
gtk_tree_store_new (void)
{
return GTK_OBJECT (gtk_type_new (gtk_tree_store_get_type ()));
}
GtkObject *
gtk_tree_store_new_with_values (gint n_columns,
...)
{
GtkObject *retval;
va_list args;
gint i;
g_return_val_if_fail (n_columns > 0, NULL);
retval = gtk_tree_store_new ();
gtk_tree_store_set_n_columns (GTK_TREE_STORE (retval),
n_columns);
va_start (args, n_columns);
for (i = 0; i < n_columns; i++)
gtk_tree_store_set_column_type (GTK_TREE_STORE (retval),
i, va_arg (args, GType));
va_end (args);
return retval;
}
void
gtk_tree_store_set_n_columns (GtkTreeStore *tree_store,
gint n_columns)
{
GType *new_columns;
g_return_if_fail (tree_store != NULL);
g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
if (tree_store->n_columns == n_columns)
return;
new_columns = g_new0 (GType, n_columns);
if (tree_store->column_headers)
{
/* copy the old header orders over */
if (n_columns >= tree_store->n_columns)
memcpy (new_columns, tree_store->column_headers, tree_store->n_columns * sizeof (gchar *));
else
memcpy (new_columns, tree_store->column_headers, n_columns * sizeof (GType));
g_free (tree_store->column_headers);
}
tree_store->column_headers = new_columns;
tree_store->n_columns = n_columns;
}
void
gtk_tree_store_set_column_type (GtkTreeStore *tree_store,
gint column,
GType type)
{
g_return_if_fail (tree_store != NULL);
g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
g_return_if_fail (column >=0 && column < tree_store->n_columns);
tree_store->column_headers[column] = type;
}
/* fulfill the GtkTreeModel requirements */
/* NOTE: GtkTreeStore::root is a GNode, that acts as the parent node. However,
* it is not visible to the tree or to the user., and the path "1" refers to the
* first child of GtkTreeStore::root.
*/
static gint
gtk_tree_store_get_n_columns (GtkTreeModel *tree_model)
{
g_return_val_if_fail (tree_model != NULL, 0);
g_return_val_if_fail (GTK_IS_TREE_STORE (tree_model), 0);
return GTK_TREE_STORE (tree_model)->n_columns;
}
static GtkTreeNode
gtk_tree_store_get_node (GtkTreeModel *tree_model,
GtkTreePath *path)
{
gint i;
GtkTreeNode *node;
gint *indices = gtk_tree_path_get_indices (path);
node = GTK_TREE_STORE (tree_model)->root;
for (i = 0; i < gtk_tree_path_get_depth (path); i ++)
{
node = (GtkTreeNode *) gtk_tree_store_node_nth_child (tree_model,
(GtkTreeNode *) node,
indices[i]);
if (node == NULL)
return NULL;
};
return (GtkTreeNode) node;
}
static GtkTreePath *
gtk_tree_store_get_path (GtkTreeModel *tree_model,
GtkTreeNode node)
{
GtkTreePath *retval;
GNode *tmp_node;
gint i = 0;
g_return_val_if_fail (tree_model != NULL, NULL);
if (node == NULL)
return NULL;
if (node == G_NODE (GTK_TREE_STORE (tree_model)->root))
return NULL;
if (G_NODE (node)->parent == G_NODE (GTK_TREE_STORE (tree_model)->root))
{
retval = gtk_tree_path_new ();
tmp_node = G_NODE (GTK_TREE_STORE (tree_model)->root)->children;
}
else
{
retval = gtk_tree_store_get_path (tree_model,
G_NODE (node)->parent);
tmp_node = G_NODE (node)->parent->children;
}
if (retval == NULL)
return NULL;
if (tmp_node == NULL)
{
gtk_tree_path_free (retval);
return NULL;
}
for (; tmp_node; tmp_node = tmp_node->next)
{
if (tmp_node == G_NODE (node))
break;
i++;
}
if (tmp_node == NULL)
{
/* We couldn't find node, meaning it's prolly not ours */
gtk_tree_path_free (retval);
return NULL;
}
gtk_tree_path_append_index (retval, i);
return retval;
}
static void
gtk_tree_store_node_get_value (GtkTreeModel *tree_model,
GtkTreeNode node,
gint column,
GValue *value)
{
GtkTreeDataList *list;
gint tmp_column = column;
g_return_if_fail (tree_model != NULL);
g_return_if_fail (GTK_IS_TREE_STORE (tree_model));
g_return_if_fail (node != NULL);
g_return_if_fail (column < GTK_TREE_STORE (tree_model)->n_columns);
list = G_NODE (node)->data;
while (tmp_column-- > 0 && list)
list = list->next;
g_return_if_fail (list != NULL);
gtk_tree_data_list_node_to_value (list,
GTK_TREE_STORE (tree_model)->column_headers[column],
value);
}
static gboolean
gtk_tree_store_node_next (GtkTreeModel *tree_model,
GtkTreeNode *node)
{
if (node == NULL || *node == NULL)
return FALSE;
*node = (GtkTreeNode *) G_NODE (*node)->next;
return (*node != NULL);
}
static GtkTreeNode
gtk_tree_store_node_children (GtkTreeModel *tree_model,
GtkTreeNode node)
{
return (GtkTreeNode) G_NODE (node)->children;
}
static gboolean
gtk_tree_store_node_has_child (GtkTreeModel *tree_model,
GtkTreeNode node)
{
return G_NODE (node)->children != NULL;
}
static gint
gtk_tree_store_node_n_children (GtkTreeModel *tree_model,
GtkTreeNode node)
{
gint i = 0;
node = (GtkTreeNode *) G_NODE (node)->children;
while (node != NULL)
{
i++;
node = (GtkTreeNode *) G_NODE (node)->next;
}
return i;
}
static GtkTreeNode
gtk_tree_store_node_nth_child (GtkTreeModel *tree_model,
GtkTreeNode node,
gint n)
{
g_return_val_if_fail (node != NULL, NULL);
return (GtkTreeNode *) g_node_nth_child (G_NODE (node), n);
}
static GtkTreeNode
gtk_tree_store_node_parent (GtkTreeModel *tree_model,
GtkTreeNode node)
{
return (GtkTreeNode) G_NODE (node)->parent;
}
/* Public accessors */
GtkTreeNode *
gtk_tree_store_node_new (void)
{
GtkTreeNode *retval;
retval = (GtkTreeNode *) g_node_new (NULL);
return retval;
}
/*
* This is a somewhat inelegant function that does a lot of list
* manipulations on it's own.
*/
void
gtk_tree_store_node_set_cell (GtkTreeStore *tree_store,
GtkTreeNode *node,
gint column,
GValue *value)
{
GtkTreeDataList *list;
GtkTreeDataList *prev;
g_return_if_fail (tree_store != NULL);
g_return_if_fail (GTK_IS_TREE_STORE (tree_store));
g_return_if_fail (node != NULL);
g_return_if_fail (column >= 0 && column < tree_store->n_columns);
prev = list = G_NODE (node)->data;
while (list != NULL)
{
if (column == 0)
{
gtk_tree_data_list_value_to_node (list, value);
return;
}
column--;
prev = list;
list = list->next;
}
if (G_NODE (node)->data == NULL)
{
G_NODE (node)->data = list = gtk_tree_data_list_alloc ();
list->next = NULL;
}
else
{
list = prev->next = gtk_tree_data_list_alloc ();
list->next = NULL;
}
while (column != 0)
{
list->next = gtk_tree_data_list_alloc ();
list = list->next;
list->next = NULL;
column --;
}
gtk_tree_data_list_value_to_node (list, value);
}
void
gtk_tree_store_node_remove (GtkTreeStore *model,
GtkTreeNode *node)
{
GtkTreePath *path;
GNode *parent;
g_return_if_fail (model != NULL);
g_return_if_fail (GTK_IS_TREE_STORE (model));
g_return_if_fail (node != NULL);
/* FIXME: if node is NULL, do I want to free the tree? */
parent = G_NODE (node)->parent;
path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), node);
g_node_destroy (G_NODE (node));
gtk_signal_emit_by_name (GTK_OBJECT (model),
"node_deleted",
path);
if (parent != G_NODE (model->root) && parent->children == NULL)
{
gtk_tree_path_up (path);
gtk_signal_emit_by_name (GTK_OBJECT (model),
"node_child_toggled",
path,
parent);
}
gtk_tree_path_free (path);
}
GtkTreeNode *
gtk_tree_store_node_insert (GtkTreeStore *model,
GtkTreeNode *parent,
gint position,
GtkTreeNode *node)
{
GtkTreePath *path;
g_return_val_if_fail (model != NULL, node);
g_return_val_if_fail (GTK_IS_TREE_STORE (model), node);
g_return_val_if_fail (node != NULL, node);
if (parent == NULL)
parent = model->root;
g_node_insert (G_NODE (parent), position, G_NODE (node));
path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), node);
gtk_signal_emit_by_name (GTK_OBJECT (model),
"node_inserted",
path, node);
gtk_tree_path_free (path);
return node;
}
GtkTreeNode *
gtk_tree_store_node_insert_before (GtkTreeStore *model,
GtkTreeNode *parent,
GtkTreeNode *sibling,
GtkTreeNode *node)
{
GtkTreePath *path;
g_return_val_if_fail (model != NULL, node);
g_return_val_if_fail (GTK_IS_TREE_STORE (model), node);
g_return_val_if_fail (node != NULL, node);
if (parent == NULL && sibling == NULL)
parent = model->root;
if (parent == NULL)
parent = (GtkTreeNode *) G_NODE (sibling)->parent;
g_node_insert_before (G_NODE (parent), G_NODE (sibling), G_NODE (node));
path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), node);
gtk_signal_emit_by_name (GTK_OBJECT (model),
"node_inserted",
path, node);
gtk_tree_path_free (path);
return node;
}
GtkTreeNode *
gtk_tree_store_node_insert_after (GtkTreeStore *model,
GtkTreeNode *parent,
GtkTreeNode *sibling,
GtkTreeNode *node)
{
GtkTreePath *path;
g_return_val_if_fail (model != NULL, node);
g_return_val_if_fail (GTK_IS_TREE_STORE (model), node);
g_return_val_if_fail (node != NULL, node);
if (parent == NULL && sibling == NULL)
parent = model->root;
if (parent == NULL)
parent = (GtkTreeNode *) G_NODE (sibling)->parent;
g_node_insert_after (G_NODE (parent), G_NODE (sibling), G_NODE (node));
path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), node);
gtk_signal_emit_by_name (GTK_OBJECT (model),
"node_inserted",
path, node);
gtk_tree_path_free (path);
return node;
}
GtkTreeNode *
gtk_tree_store_node_prepend (GtkTreeStore *model,
GtkTreeNode *parent,
GtkTreeNode *node)
{
g_return_val_if_fail (model != NULL, node);
g_return_val_if_fail (GTK_IS_TREE_STORE (model), node);
g_return_val_if_fail (node != NULL, node);
if (parent == NULL)
parent = model->root;
if (G_NODE (parent)->children == NULL)
{
GtkTreePath *path;
g_node_prepend (G_NODE (parent), G_NODE (node));
if (parent != model->root)
{
path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), parent);
gtk_signal_emit_by_name (GTK_OBJECT (model),
"node_child_toggled",
path,
parent);
gtk_tree_path_append_index (path, 1);
}
else
{
path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), G_NODE (parent)->children);
}
gtk_signal_emit_by_name (GTK_OBJECT (model),
"node_inserted",
path,
G_NODE (parent)->children);
gtk_tree_path_free (path);
}
else
{
gtk_tree_store_node_insert_after (model,
parent == model->root?NULL:parent,
NULL,
node);
}
return node;
}
GtkTreeNode *
gtk_tree_store_node_append (GtkTreeStore *model,
GtkTreeNode *parent,
GtkTreeNode *node)
{
g_return_val_if_fail (model != NULL, node);
g_return_val_if_fail (GTK_IS_TREE_STORE (model), node);
g_return_val_if_fail (node != NULL, node);
if (parent == NULL)
parent = model->root;
if (G_NODE (parent)->children == NULL)
{
GtkTreePath *path;
g_node_append (G_NODE (parent), G_NODE (node));
if (parent != model->root)
{
path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), parent);
gtk_signal_emit_by_name (GTK_OBJECT (model),
"node_child_toggled",
path,
parent);
gtk_tree_path_append_index (path, 1);
}
else
{
path = gtk_tree_store_get_path (GTK_TREE_MODEL (model), G_NODE (parent)->children);
}
gtk_signal_emit_by_name (GTK_OBJECT (model),
"node_inserted",
path,
G_NODE (parent)->children);
gtk_tree_path_free (path);
}
else
{
gtk_tree_store_node_insert_before (model,
parent == model->root?NULL:parent,
NULL,
node);
}
return node;
}
GtkTreeNode *
gtk_tree_store_node_get_root (GtkTreeStore *model)
{
g_return_val_if_fail (model != NULL, NULL);
g_return_val_if_fail (GTK_IS_TREE_STORE (model), NULL);
return (GtkTreeNode *) model->root;
}
gboolean
gtk_tree_store_node_is_ancestor (GtkTreeStore *model,
GtkTreeNode *node,
GtkTreeNode *descendant)
{
g_return_val_if_fail (model != NULL, FALSE);
g_return_val_if_fail (GTK_IS_TREE_STORE (model), FALSE);
g_return_val_if_fail (node != NULL, FALSE);
g_return_val_if_fail (descendant != NULL, FALSE);
return g_node_is_ancestor (G_NODE (node), G_NODE (descendant));
}
gint
gtk_tree_store_node_depth (GtkTreeStore *model,
GtkTreeNode *node)
{
g_return_val_if_fail (model != NULL, 0);
g_return_val_if_fail (GTK_IS_TREE_STORE (model), 0);
g_return_val_if_fail (node != NULL, 0);
return g_node_depth (G_NODE (node));
}

99
gtk/gtktreestore.h Normal file
View File

@ -0,0 +1,99 @@
/* gtktreestore.h
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GTK_TREE_STORE_H__
#define __GTK_TREE_STORE_H__
#include <gtk/gtktreemodel.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GTK_TYPE_TREE_STORE (gtk_tree_store_get_type ())
#define GTK_TREE_STORE(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_TREE_STORE, GtkTreeStore))
#define GTK_TREE_STORE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_TREE_STORE, GtkTreeStoreClass))
#define GTK_IS_TREE_STORE(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_TREE_STORE))
#define GTK_IS_TREE_STORE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), GTK_TYPE_TREE_STORE))
typedef struct _GtkTreeStore GtkTreeStore;
typedef struct _GtkTreeStoreClass GtkTreeStoreClass;
struct _GtkTreeStore
{
GtkTreeModel parent;
GtkTreeNode *root;
gint n_columns;
GType *column_headers;
};
struct _GtkTreeStoreClass
{
GtkTreeModelClass parent_class;
};
GtkType gtk_tree_store_get_type (void);
GtkObject *gtk_tree_store_new (void);
GtkObject *gtk_tree_store_new_with_values (gint n_columns,
...);
void gtk_tree_store_set_n_columns (GtkTreeStore *tree_store,
gint n_columns);
void gtk_tree_store_set_column_type (GtkTreeStore *store,
gint column,
GType type);
GtkTreeNode *gtk_tree_store_node_new (void);
void gtk_tree_store_node_set_cell (GtkTreeStore *tree_store,
GtkTreeNode *node,
gint column,
GValue *value);
void gtk_tree_store_node_remove (GtkTreeStore *tree_store,
GtkTreeNode *node);
GtkTreeNode *gtk_tree_store_node_insert (GtkTreeStore *tree_store,
GtkTreeNode *parent,
gint position,
GtkTreeNode *node);
GtkTreeNode *gtk_tree_store_node_insert_before (GtkTreeStore *tree_store,
GtkTreeNode *parent,
GtkTreeNode *sibling,
GtkTreeNode *node);
GtkTreeNode *gtk_tree_store_node_insert_after (GtkTreeStore *tree_store,
GtkTreeNode *parent,
GtkTreeNode *sibling,
GtkTreeNode *node);
GtkTreeNode *gtk_tree_store_node_prepend (GtkTreeStore *tree_store,
GtkTreeNode *parent,
GtkTreeNode *node);
GtkTreeNode *gtk_tree_store_node_append (GtkTreeStore *tree_store,
GtkTreeNode *parent,
GtkTreeNode *node);
GtkTreeNode *gtk_tree_store_node_get_root (GtkTreeStore *tree_store);
gboolean gtk_tree_store_node_is_ancestor (GtkTreeStore *tree_store,
GtkTreeNode *node,
GtkTreeNode *descendant);
gint gtk_tree_store_node_depth (GtkTreeStore *tree_store,
GtkTreeNode *node);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_TREE_STORE_H__ */

3384
gtk/gtktreeview.c Normal file

File diff suppressed because it is too large Load Diff

105
gtk/gtktreeview.h Normal file
View File

@ -0,0 +1,105 @@
/* gtktreeview.h
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GTK_TREE_VIEW_H__
#define __GTK_TREE_VIEW_H__
#include <gtk/gtkcontainer.h>
#include <gtk/gtktreemodel.h>
#include <gtk/gtktreeviewcolumn.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GTK_TYPE_TREE_VIEW (gtk_tree_view_get_type ())
#define GTK_TREE_VIEW(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_TREE_VIEW, GtkTreeView))
#define GTK_TREE_VIEW_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_TREE_VIEW, GtkTreeViewClass))
#define GTK_IS_TREE_VIEW(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_TREE_VIEW))
#define GTK_IS_TREE_VIEW_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), GTK_TYPE_TREE_VIEW))
typedef struct _GtkTreeView GtkTreeView;
typedef struct _GtkTreeViewClass GtkTreeViewClass;
typedef struct _GtkTreeViewPrivate GtkTreeViewPrivate;
typedef struct _GtkTreeSelection GtkTreeSelection;
typedef struct _GtkTreeSelectionClass GtkTreeSelectionClass;
struct _GtkTreeView
{
GtkContainer parent;
GtkTreeViewPrivate *priv;
};
struct _GtkTreeViewClass
{
GtkContainerClass parent_class;
void (*set_scroll_adjustments) (GtkTreeView *tree_view,
GtkAdjustment *hadjustment,
GtkAdjustment *vadjustment);
gint (*expand_row) (GtkTreeView *tree_view,
GtkTreeNode *node);
};
/* Creators */
GtkType gtk_tree_view_get_type (void);
GtkWidget *gtk_tree_view_new (void);
GtkWidget *gtk_tree_view_new_with_model (GtkTreeModel *model);
GtkTreeModel *gtk_tree_view_get_model (GtkTreeView *tree_view);
void gtk_tree_view_set_model (GtkTreeView *tree_view,
GtkTreeModel *tree_model);
GtkTreeSelection *gtk_tree_view_get_selection (GtkTreeView *tree_view);
void gtk_tree_view_set_selection (GtkTreeView *tree_view,
GtkTreeSelection *selection);
GtkAdjustment *gtk_tree_view_get_hadjustment (GtkTreeView *layout);
void gtk_tree_view_set_hadjustment (GtkTreeView *layout,
GtkAdjustment *adjustment);
GtkAdjustment *gtk_tree_view_get_vadjustment (GtkTreeView *layout);
void gtk_tree_view_set_vadjustment (GtkTreeView *layout,
GtkAdjustment *adjustment);
gboolean gtk_tree_view_get_headers_visible (GtkTreeView *tree_view);
void gtk_tree_view_set_headers_visible (GtkTreeView *tree_view,
gboolean headers_visible);
void gtk_tree_view_columns_autosize (GtkTreeView *tree_view);
void gtk_tree_view_set_headers_active (GtkTreeView *tree_view,
gboolean active);
gint gtk_tree_view_add_column (GtkTreeView *tree_view,
GtkTreeViewColumn *column);
GtkTreeViewColumn *gtk_tree_view_get_column (GtkTreeView *tree_view,
gint n);
/* Actions */
void gtk_tree_view_move_to (GtkTreeView *tree_view,
GtkTreePath *path,
gint column,
gfloat row_align,
gfloat col_align);
void gtk_tree_view_expand_all (GtkTreeView *tree_view);
void gtk_tree_view_collapse_all (GtkTreeView *tree_view);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_TREE_VIEW_H__ */

633
gtk/gtktreeviewcolumn.c Normal file
View File

@ -0,0 +1,633 @@
/* gtktreeviewcolumn.c
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "gtktreeviewcolumn.h"
#include "gtktreeprivate.h"
#include "gtksignal.h"
#include "gtkbutton.h"
#include "gtkalignment.h"
enum {
CLICKED,
LAST_SIGNAL
};
static void gtk_tree_view_column_init (GtkTreeViewColumn *tree_column);
static void gtk_tree_view_column_class_init (GtkTreeViewColumnClass *klass);
static void gtk_tree_view_column_set_attributesv (GtkTreeViewColumn *tree_column,
va_list args);
static void gtk_real_tree_column_clicked (GtkTreeViewColumn *tree_column);
static GtkObjectClass *parent_class = NULL;
static guint tree_column_signals[LAST_SIGNAL] = { 0 };
GtkType
gtk_tree_view_column_get_type (void)
{
static GtkType tree_column_type = 0;
if (!tree_column_type)
{
static const GTypeInfo tree_column_info =
{
sizeof (GtkTreeViewColumnClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gtk_tree_view_column_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GtkTreeViewColumn),
0,
(GInstanceInitFunc) gtk_tree_view_column_init,
};
tree_column_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkTreeViewColumn", &tree_column_info);
}
return tree_column_type;
}
static void
gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class)
{
GtkObjectClass *object_class;
object_class = (GtkObjectClass*) class;
parent_class = g_type_class_peek_parent (class);
tree_column_signals[CLICKED] =
gtk_signal_new ("clicked",
GTK_RUN_FIRST,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkTreeViewColumnClass, clicked),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
gtk_object_class_add_signals (object_class, tree_column_signals, LAST_SIGNAL);
class->clicked = gtk_real_tree_column_clicked;
}
static void
gtk_tree_view_column_init (GtkTreeViewColumn *tree_column)
{
tree_column->button = NULL;
tree_column->justification = GTK_JUSTIFY_LEFT;
tree_column->size = 0;
tree_column->min_width = -1;
tree_column->max_width = -1;
tree_column->cell = NULL;
tree_column->attributes = NULL;
tree_column->column_type = GTK_TREE_VIEW_COLUMN_AUTOSIZE;
tree_column->visible = TRUE;
tree_column->button_active = FALSE;
tree_column->dirty = TRUE;
}
/* used to make the buttons 'unclickable' */
static gint
gtk_tree_view_passive_func (GtkWidget *widget,
GdkEvent *event,
gpointer data)
{
g_return_val_if_fail (event != NULL, FALSE);
switch (event->type)
{
case GDK_MOTION_NOTIFY:
case GDK_BUTTON_PRESS:
case GDK_2BUTTON_PRESS:
case GDK_3BUTTON_PRESS:
case GDK_BUTTON_RELEASE:
case GDK_ENTER_NOTIFY:
case GDK_LEAVE_NOTIFY:
return TRUE;
default:
break;
}
return FALSE;
}
static void
gtk_real_tree_column_clicked (GtkTreeViewColumn *tree_column)
{
g_return_if_fail (tree_column != NULL);
g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
}
GtkObject *
gtk_tree_view_column_new (void)
{
GtkObject *retval;
retval = GTK_OBJECT (gtk_type_new (GTK_TYPE_TREE_COLUMN));
return retval;
}
GtkObject *
gtk_tree_view_column_new_with_attributes (gchar *title,
GtkCellRenderer *cell,
...)
{
GtkObject *retval;
va_list args;
retval = gtk_tree_view_column_new ();
gtk_tree_view_column_set_title (GTK_TREE_VIEW_COLUMN (retval), title);
gtk_tree_view_column_set_cell_renderer (GTK_TREE_VIEW_COLUMN (retval), cell);
va_start (args, cell);
gtk_tree_view_column_set_attributesv (GTK_TREE_VIEW_COLUMN (retval),
args);
va_end (args);
return retval;
}
void
gtk_tree_view_column_set_cell_renderer (GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell)
{
g_return_if_fail (tree_column != NULL);
g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
if (cell)
g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
if (cell)
g_object_ref (G_OBJECT (cell));
if (tree_column->cell)
g_object_unref (G_OBJECT (tree_column->cell));
tree_column->cell = cell;
}
void
gtk_tree_view_column_add_attribute (GtkTreeViewColumn *tree_column,
gchar *attribute,
gint column)
{
g_return_if_fail (tree_column != NULL);
g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
tree_column->attributes = g_slist_prepend (tree_column->attributes, GINT_TO_POINTER (column));
tree_column->attributes = g_slist_prepend (tree_column->attributes, g_strdup (attribute));
}
static void
gtk_tree_view_column_set_attributesv (GtkTreeViewColumn *tree_column,
va_list args)
{
GSList *list;
gchar *attribute;
gint column;
g_return_if_fail (tree_column != NULL);
g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
attribute = va_arg (args, gchar *);
list = tree_column->attributes;
while (list && list->next)
{
g_free (list->data);
list = list->next->next;
}
g_slist_free (tree_column->attributes);
tree_column->attributes = NULL;
while (attribute != NULL)
{
column = va_arg (args, gint);
gtk_tree_view_column_add_attribute (tree_column,
attribute,
column);
attribute = va_arg (args, gchar *);
}
}
void
gtk_tree_view_column_set_attributes (GtkTreeViewColumn *tree_column,
...)
{
va_list args;
g_return_if_fail (tree_column != NULL);
g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
va_start (args, tree_column);
gtk_tree_view_column_set_attributesv (tree_column, args);
va_end (args);
}
void
gtk_tree_view_column_set_cell_data (GtkTreeViewColumn *tree_column,
GtkTreeModel *tree_model,
GtkTreeNode tree_node)
{
GSList *list;
GValue value = { 0, };
GObject *cell;
g_return_if_fail (tree_column != NULL);
g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
g_return_if_fail (tree_column->cell != NULL);
if (tree_column->func && (* tree_column->func) (tree_column,
tree_model,
tree_node,
tree_column->func_data))
return;
cell = (GObject *) tree_column->cell;
list = tree_column->attributes;
while (list && list->next)
{
gtk_tree_model_node_get_value (tree_model,
tree_node,
GPOINTER_TO_INT (list->next->data),
&value);
g_object_set_param (cell, (gchar *) list->data, &value);
g_value_unset (&value);
list = list->next->next;
}
}
/* Options for manipulating the columns */
void
gtk_tree_view_column_set_visible (GtkTreeViewColumn *tree_column,
gboolean visible)
{
g_return_if_fail (tree_column != NULL);
g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
if (tree_column->visible == visible)
return;
tree_column->visible = visible;
if (visible)
{
gtk_widget_show (tree_column->button);
gdk_window_show (tree_column->window);
}
else
{
gtk_widget_hide (tree_column->button);
gdk_window_hide (tree_column->window);
}
if (GTK_WIDGET_REALIZED (tree_column->tree_view))
{
_gtk_tree_view_set_size (GTK_TREE_VIEW (tree_column->tree_view), -1, -1);
gtk_widget_queue_resize (tree_column->tree_view);
}
}
gboolean
gtk_tree_view_column_get_visible (GtkTreeViewColumn *tree_column)
{
g_return_val_if_fail (tree_column != NULL, FALSE);
g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
return tree_column->visible;
}
void
gtk_tree_view_column_set_col_type (GtkTreeViewColumn *tree_column,
GtkTreeViewColumnType type)
{
g_return_if_fail (tree_column != NULL);
g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
if (type == tree_column->column_type)
return;
tree_column->column_type = type;
switch (type)
{
case GTK_TREE_VIEW_COLUMN_AUTOSIZE:
tree_column->dirty = TRUE;
case GTK_TREE_VIEW_COLUMN_FIXED:
gdk_window_hide (tree_column->window);
break;
default:
gdk_window_show (tree_column->window);
gdk_window_raise (tree_column->window);
break;
}
gtk_widget_queue_resize (tree_column->tree_view);
}
gint
gtk_tree_view_column_get_col_type (GtkTreeViewColumn *tree_column)
{
g_return_val_if_fail (tree_column != NULL, 0);
g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
return tree_column->column_type;
}
gint
gtk_tree_view_column_get_preferred_size (GtkTreeViewColumn *tree_column)
{
return 0;
}
gint
gtk_tree_view_column_get_size (GtkTreeViewColumn *tree_column)
{
g_return_val_if_fail (tree_column != NULL, 0);
g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
return tree_column->size;
}
void
gtk_tree_view_column_set_size (GtkTreeViewColumn *tree_column,
gint size)
{
g_return_if_fail (tree_column != NULL);
g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
g_return_if_fail (size > 0);
if (tree_column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE ||
tree_column->size == size)
return;
tree_column->size = size;
if (GTK_WIDGET_REALIZED (tree_column->tree_view))
gtk_widget_queue_resize (tree_column->tree_view);
}
void
gtk_tree_view_column_set_min_width (GtkTreeViewColumn *tree_column,
gint min_width)
{
gint real_min_width;
g_return_if_fail (tree_column != NULL);
g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
g_return_if_fail (min_width >= -1);
if (min_width == tree_column->min_width)
return;
real_min_width = (tree_column->min_width == -1) ?
tree_column->button->requisition.width : tree_column->min_width;
/* We want to queue a resize if the either the old min_size or the
* new min_size determined the size of the column */
if (GTK_WIDGET_REALIZED (tree_column->tree_view) &&
((tree_column->min_width > tree_column->size) ||
(tree_column->min_width == -1 &&
tree_column->button->requisition.width > tree_column->size) ||
(min_width > tree_column->size) ||
(min_width == -1 &&
tree_column->button->requisition.width > tree_column->size)))
gtk_widget_queue_resize (tree_column->tree_view);
if (tree_column->max_width != -1 &&
tree_column->max_width < real_min_width)
tree_column->max_width = real_min_width;
tree_column->min_width = min_width;
}
gint
gtk_tree_view_column_get_min_width (GtkTreeViewColumn *tree_column)
{
g_return_val_if_fail (tree_column != NULL, -1);
g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), -1);
return tree_column->min_width;
}
void
gtk_tree_view_column_set_max_width (GtkTreeViewColumn *tree_column,
gint max_width)
{
gint real_min_width;
g_return_if_fail (tree_column != NULL);
g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
g_return_if_fail (max_width >= -1);
if (max_width == tree_column->max_width)
return;
real_min_width = tree_column->min_width == -1 ?
tree_column->button->requisition.width : tree_column->min_width;
if (GTK_WIDGET_REALIZED (tree_column->tree_view) &&
((tree_column->max_width < tree_column->size) ||
(max_width != -1 && max_width < tree_column->size)))
gtk_widget_queue_resize (tree_column->tree_view);
tree_column->max_width = max_width;
if (real_min_width > max_width)
tree_column->min_width = max_width;
}
gint
gtk_tree_view_column_get_max_width (GtkTreeViewColumn *tree_column)
{
g_return_val_if_fail (tree_column != NULL, -1);
g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), -1);
return tree_column->max_width;
}
void
gtk_tree_view_column_set_title (GtkTreeViewColumn *tree_column,
gchar *title)
{
g_return_if_fail (tree_column != NULL);
g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
g_free (tree_column->title);
if (title)
tree_column->title = g_strdup (title);
else
tree_column->title = NULL;
}
gchar *
gtk_tree_view_column_get_title (GtkTreeViewColumn *tree_column)
{
g_return_val_if_fail (tree_column != NULL, NULL);
g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
return tree_column->title;
}
void
gtk_tree_view_column_set_header_active (GtkTreeViewColumn *tree_column,
gboolean active)
{
g_return_if_fail (tree_column != NULL);
g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
if (!tree_column->button)
return;
if (tree_column->button_active == active)
return;
tree_column->button_active = active;
if (active)
{
gtk_signal_disconnect_by_func (GTK_OBJECT (tree_column->button),
(GtkSignalFunc) gtk_tree_view_passive_func,
NULL);
GTK_WIDGET_SET_FLAGS (tree_column->button, GTK_CAN_FOCUS);
if (GTK_WIDGET_VISIBLE (tree_column->tree_view))
gtk_widget_queue_draw (tree_column->button);
}
else
{
gtk_signal_connect (GTK_OBJECT (tree_column->button),
"event",
(GtkSignalFunc) gtk_tree_view_passive_func,
NULL);
GTK_WIDGET_UNSET_FLAGS (tree_column->button, GTK_CAN_FOCUS);
if (GTK_WIDGET_VISIBLE (tree_column->tree_view))
gtk_widget_queue_draw (tree_column->button);
}
}
void
gtk_tree_view_column_set_widget (GtkTreeViewColumn *tree_column,
GtkWidget *widget)
{
#if 0
gint new_button = 0;
GtkWidget *old_widget;
g_return_if_fail (tree_view != NULL);
g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
if (column < 0 || column >= tree_view->priv->columns)
return;
/* if the column button doesn't currently exist,
* it has to be created first */
if (!column->button)
{
column_button_create (tree_view, column);
new_button = 1;
}
column_title_new (clist, column, NULL);
/* remove and destroy the old widget */
old_widget = GTK_BIN (clist->column[column].button)->child;
if (old_widget)
gtk_container_remove (GTK_CONTAINER (clist->column[column].button),
old_widget);
/* add and show the widget */
if (widget)
{
gtk_container_add (GTK_CONTAINER (clist->column[column].button), widget);
gtk_widget_show (widget);
}
/* if this button didn't previously exist, then the
* column button positions have to be re-computed */
if (GTK_WIDGET_VISIBLE (clist) && new_button)
size_allocate_title_buttons (clist);
#endif
}
GtkWidget *
gtk_tree_view_column_get_widget (GtkTreeViewColumn *tree_column)
{
g_return_val_if_fail (tree_column != NULL, NULL);
g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
if (tree_column->button)
return GTK_BUTTON (tree_column->button)->child;
return NULL;
}
void
gtk_tree_view_column_set_justification (GtkTreeViewColumn *tree_column,
GtkJustification justification)
{
GtkWidget *alignment;
g_return_if_fail (tree_column != NULL);
g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
if (tree_column->justification == justification)
return;
tree_column->justification = justification;
/* change the alignment of the button title if it's not a
* custom widget */
alignment = GTK_BIN (tree_column->button)->child;
if (GTK_IS_ALIGNMENT (alignment))
{
switch (tree_column->justification)
{
case GTK_JUSTIFY_LEFT:
gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.0, 0.5, 0.0, 0.0);
break;
case GTK_JUSTIFY_RIGHT:
gtk_alignment_set (GTK_ALIGNMENT (alignment), 1.0, 0.5, 0.0, 0.0);
break;
case GTK_JUSTIFY_CENTER:
gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
break;
case GTK_JUSTIFY_FILL:
gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
break;
default:
break;
}
}
}

137
gtk/gtktreeviewcolumn.h Normal file
View File

@ -0,0 +1,137 @@
/* gtktreeviewcolumn.h
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GTK_TREE_VIEW_COLUMN_H__
#define __GTK_TREE_VIEW_COLUMN_H__
#include <gtk/gtkobject.h>
#include <gtk/gtkcellrenderer.h>
#include <gtk/gtktreemodel.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GTK_TYPE_TREE_COLUMN (gtk_tree_view_column_get_type ())
#define GTK_TREE_VIEW_COLUMN(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_TREE_COLUMN, GtkTreeViewColumn))
#define GTK_TREE_VIEW_COLUMN_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_TREE_COLUMN, GtkTreeViewColumnClass))
#define GTK_IS_TREE_VIEW_COLUMN(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_TREE_COLUMN))
#define GTK_IS_TREE_VIEW_COLUMN_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), GTK_TYPE_TREE_COLUMN))
typedef enum
{
GTK_TREE_VIEW_COLUMN_RESIZEABLE,
GTK_TREE_VIEW_COLUMN_AUTOSIZE,
GTK_TREE_VIEW_COLUMN_FIXED
} GtkTreeViewColumnType;
typedef struct _GtkTreeViewColumn GtkTreeViewColumn;
typedef struct _GtkTreeViewColumnClass GtkTreeViewColumnClass;
typedef gboolean (* GtkTreeViewColumnFunc) (GtkTreeViewColumn *tree_column,
GtkTreeModel *tree_model,
GtkTreeNode tree_node,
gpointer data);
struct _GtkTreeViewColumn
{
GtkObject parent;
GtkWidget *tree_view;
GtkWidget *button;
GdkWindow *window;
GtkJustification justification;
gint id;
gint size;
gint min_width;
gint max_width;
GtkTreeViewColumnFunc *func;
gpointer func_data;
gchar *title;
GtkCellRenderer *cell;
GSList *attributes;
GtkTreeViewColumnType column_type;
guint visible : 1;
guint button_active : 1;
guint dirty : 1;
};
struct _GtkTreeViewColumnClass
{
GtkObjectClass parent_class;
void (*clicked) (GtkTreeViewColumn *tree_column);
};
GtkType gtk_tree_view_column_get_type (void);
GtkObject *gtk_tree_view_column_new (void);
GtkObject *gtk_tree_view_column_new_with_attributes (gchar *title,
GtkCellRenderer *cell,
...);
void gtk_tree_view_column_set_cell_renderer (GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell);
void gtk_tree_view_column_add_attribute (GtkTreeViewColumn *tree_column,
gchar *attribute,
gint column);
void gtk_tree_view_column_set_attributes (GtkTreeViewColumn *tree_column,
...);
void gtk_tree_view_column_set_cell_data (GtkTreeViewColumn *tree_column,
GtkTreeModel *tree_model,
GtkTreeNode tree_node);
void gtk_tree_view_column_set_visible (GtkTreeViewColumn *tree_column,
gboolean visible);
gboolean gtk_tree_view_column_get_visible (GtkTreeViewColumn *tree_column);
void gtk_tree_view_column_set_col_type (GtkTreeViewColumn *tree_column,
GtkTreeViewColumnType type);
gint gtk_tree_view_column_get_col_type (GtkTreeViewColumn *tree_column);
gint gtk_tree_view_column_get_preferred_size (GtkTreeViewColumn *tree_column);
gint gtk_tree_view_column_get_size (GtkTreeViewColumn *tree_column);
void gtk_tree_view_column_set_size (GtkTreeViewColumn *tree_column,
gint width);
void gtk_tree_view_column_set_min_width (GtkTreeViewColumn *tree_column,
gint min_width);
gint gtk_tree_view_column_get_min_width (GtkTreeViewColumn *tree_column);
void gtk_tree_view_column_set_max_width (GtkTreeViewColumn *tree_column,
gint max_width);
gint gtk_tree_view_column_get_max_width (GtkTreeViewColumn *tree_column);
/* Options for manipulating the column headers
*/
void gtk_tree_view_column_set_title (GtkTreeViewColumn *tree_column,
gchar *title);
gchar *gtk_tree_view_column_get_title (GtkTreeViewColumn *tree_column);
void gtk_tree_view_column_set_header_active (GtkTreeViewColumn *tree_column,
gboolean active);
void gtk_tree_view_column_set_widget (GtkTreeViewColumn *tree_column,
GtkWidget *widget);
GtkWidget *gtk_tree_view_column_get_widget (GtkTreeViewColumn *tree_column);
void gtk_tree_view_column_set_justification (GtkTreeViewColumn *tree_column,
GtkJustification justification);
GtkJustification gtk_tree_view_column_get_justification (GtkTreeViewColumn *tree_column);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_TREE_VIEW_COLUMN_H__ */

206
gtk/treestoretest.c Normal file
View File

@ -0,0 +1,206 @@
#include <gtk/gtk.h>
#include <stdlib.h>
GtkObject *model;
static void
row_selected (GtkTreeView *tree_view,
GtkTreeModel *tree_model,
GtkTreeNode *node,
GtkWidget *button)
{
gtk_widget_set_sensitive (button, TRUE);
}
static void
row_unselected (GtkTreeView *tree_view,
GtkTreeModel *tree_model,
GtkTreeNode *node,
GtkWidget *button)
{
gtk_widget_set_sensitive (button, FALSE);
}
static GtkTreeNode *
node_new ()
{
static GValue value = {0, };
static gint i = 0;
gchar *str;
GtkTreeNode *node = gtk_tree_store_node_new ();
g_value_init (&value, G_TYPE_STRING);
str = g_strdup_printf ("FOO: %d", i++);
g_value_set_string (&value, str);
g_free (str);
gtk_tree_store_node_set_cell (GTK_TREE_STORE (model), node, 0, &value);
g_value_unset (&value);
return node;
}
static void
node_remove (GtkWidget *button, GtkTreeView *tree_view)
{
GtkTreeNode *selected = gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)));
gtk_tree_store_node_remove (GTK_TREE_STORE (model),
selected);
}
static void
node_insert (GtkWidget *button, GtkTreeView *tree_view)
{
GtkWidget *entry;
GtkTreeNode *selected = gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)));
entry = gtk_object_get_user_data (GTK_OBJECT (button));
gtk_tree_store_node_insert (GTK_TREE_STORE (model),
selected,
atoi (gtk_entry_get_text (GTK_ENTRY (entry))),
node_new ());
}
static void
node_insert_before (GtkWidget *button, GtkTreeView *tree_view)
{
GtkTreeNode *selected = gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)));
gtk_tree_store_node_insert_before (GTK_TREE_STORE (model),
NULL,
selected,
node_new ());
}
static void
node_insert_after (GtkWidget *button, GtkTreeView *tree_view)
{
GtkTreeNode *selected = gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)));
gtk_tree_store_node_insert_after (GTK_TREE_STORE (model),
NULL,
selected,
node_new ());
}
static void
node_prepend (GtkWidget *button, GtkTreeView *tree_view)
{
GtkTreeNode *selected = gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)));
gtk_tree_store_node_prepend (GTK_TREE_STORE (model),
selected,
node_new ());
}
static void
node_append (GtkWidget *button, GtkTreeView *tree_view)
{
GtkTreeNode *selected = gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)));
gtk_tree_store_node_append (GTK_TREE_STORE (model),
selected,
node_new ());
}
static void
make_window ()
{
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *hbox, *entry;
GtkWidget *button;
GtkWidget *scrolled_window;
GtkWidget *tree_view;
GtkObject *column;
GtkCellRenderer *cell;
GtkObject *selection;
/* Make the Widgets/Objects */
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
vbox = gtk_vbox_new (FALSE, 8);
gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
gtk_window_set_default_size (GTK_WINDOW (window), 300, 350);
scrolled_window = gtk_scrolled_window_new (NULL, NULL);
tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
selection = GTK_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)));
gtk_tree_selection_set_type (GTK_TREE_SELECTION (selection), GTK_TREE_SELECTION_SINGLE);
/* Put them together */
gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view);
gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (window), vbox);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_signal_connect (GTK_OBJECT (window), "destroy", gtk_main_quit, NULL);
/* buttons */
button = gtk_button_new_with_label ("gtk_tree_store_node_remove");
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (selection),
"row_selected", row_selected, button);
gtk_signal_connect (GTK_OBJECT (selection),
"row_unselected", row_unselected, button);
gtk_signal_connect (GTK_OBJECT (button), "clicked", node_remove, tree_view);
gtk_widget_set_sensitive (button, FALSE);
button = gtk_button_new_with_label ("gtk_tree_store_node_insert");
hbox = gtk_hbox_new (FALSE, 8);
entry = gtk_entry_new ();
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), entry);
gtk_signal_connect (GTK_OBJECT (button), "clicked", node_insert, tree_view);
button = gtk_button_new_with_label ("gtk_tree_store_node_insert_before");
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (selection),
"row_selected", row_selected, button);
gtk_signal_connect (GTK_OBJECT (selection),
"row_unselected", row_unselected, button);
gtk_signal_connect (GTK_OBJECT (button), "clicked", node_insert_before, tree_view);
gtk_widget_set_sensitive (button, FALSE);
button = gtk_button_new_with_label ("gtk_tree_store_node_insert_after");
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (selection),
"row_selected", row_selected, button);
gtk_signal_connect (GTK_OBJECT (selection),
"row_unselected", row_unselected, button);
gtk_signal_connect (GTK_OBJECT (button), "clicked", node_insert_after, tree_view);
gtk_widget_set_sensitive (button, FALSE);
button = gtk_button_new_with_label ("gtk_tree_store_node_prepend");
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (button), "clicked", node_prepend, tree_view);
button = gtk_button_new_with_label ("gtk_tree_store_node_append");
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (button), "clicked", node_append, tree_view);
/* The selected column */
cell = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("nodes", cell, "text", 0, NULL);
gtk_tree_view_add_column (GTK_TREE_VIEW (tree_view), GTK_TREE_VIEW_COLUMN (column));
/* Show it all */
gtk_widget_show_all (window);
}
int
main (int argc, char *argv[])
{
gtk_init (&argc, &argv);
model = gtk_tree_store_new_with_values (2, G_TYPE_STRING, G_TYPE_STRING);
make_window ();
make_window ();
/* A few to start */
gtk_tree_store_node_append (GTK_TREE_STORE (model), NULL, node_new ());
gtk_tree_store_node_append (GTK_TREE_STORE (model), NULL, node_new ());
gtk_tree_store_node_append (GTK_TREE_STORE (model), NULL, node_new ());
gtk_main ();
return 0;
}

206
tests/treestoretest.c Normal file
View File

@ -0,0 +1,206 @@
#include <gtk/gtk.h>
#include <stdlib.h>
GtkObject *model;
static void
row_selected (GtkTreeView *tree_view,
GtkTreeModel *tree_model,
GtkTreeNode *node,
GtkWidget *button)
{
gtk_widget_set_sensitive (button, TRUE);
}
static void
row_unselected (GtkTreeView *tree_view,
GtkTreeModel *tree_model,
GtkTreeNode *node,
GtkWidget *button)
{
gtk_widget_set_sensitive (button, FALSE);
}
static GtkTreeNode *
node_new ()
{
static GValue value = {0, };
static gint i = 0;
gchar *str;
GtkTreeNode *node = gtk_tree_store_node_new ();
g_value_init (&value, G_TYPE_STRING);
str = g_strdup_printf ("FOO: %d", i++);
g_value_set_string (&value, str);
g_free (str);
gtk_tree_store_node_set_cell (GTK_TREE_STORE (model), node, 0, &value);
g_value_unset (&value);
return node;
}
static void
node_remove (GtkWidget *button, GtkTreeView *tree_view)
{
GtkTreeNode *selected = gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)));
gtk_tree_store_node_remove (GTK_TREE_STORE (model),
selected);
}
static void
node_insert (GtkWidget *button, GtkTreeView *tree_view)
{
GtkWidget *entry;
GtkTreeNode *selected = gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)));
entry = gtk_object_get_user_data (GTK_OBJECT (button));
gtk_tree_store_node_insert (GTK_TREE_STORE (model),
selected,
atoi (gtk_entry_get_text (GTK_ENTRY (entry))),
node_new ());
}
static void
node_insert_before (GtkWidget *button, GtkTreeView *tree_view)
{
GtkTreeNode *selected = gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)));
gtk_tree_store_node_insert_before (GTK_TREE_STORE (model),
NULL,
selected,
node_new ());
}
static void
node_insert_after (GtkWidget *button, GtkTreeView *tree_view)
{
GtkTreeNode *selected = gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)));
gtk_tree_store_node_insert_after (GTK_TREE_STORE (model),
NULL,
selected,
node_new ());
}
static void
node_prepend (GtkWidget *button, GtkTreeView *tree_view)
{
GtkTreeNode *selected = gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)));
gtk_tree_store_node_prepend (GTK_TREE_STORE (model),
selected,
node_new ());
}
static void
node_append (GtkWidget *button, GtkTreeView *tree_view)
{
GtkTreeNode *selected = gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)));
gtk_tree_store_node_append (GTK_TREE_STORE (model),
selected,
node_new ());
}
static void
make_window ()
{
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *hbox, *entry;
GtkWidget *button;
GtkWidget *scrolled_window;
GtkWidget *tree_view;
GtkObject *column;
GtkCellRenderer *cell;
GtkObject *selection;
/* Make the Widgets/Objects */
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
vbox = gtk_vbox_new (FALSE, 8);
gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
gtk_window_set_default_size (GTK_WINDOW (window), 300, 350);
scrolled_window = gtk_scrolled_window_new (NULL, NULL);
tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
selection = GTK_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)));
gtk_tree_selection_set_type (GTK_TREE_SELECTION (selection), GTK_TREE_SELECTION_SINGLE);
/* Put them together */
gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view);
gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (window), vbox);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_signal_connect (GTK_OBJECT (window), "destroy", gtk_main_quit, NULL);
/* buttons */
button = gtk_button_new_with_label ("gtk_tree_store_node_remove");
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (selection),
"row_selected", row_selected, button);
gtk_signal_connect (GTK_OBJECT (selection),
"row_unselected", row_unselected, button);
gtk_signal_connect (GTK_OBJECT (button), "clicked", node_remove, tree_view);
gtk_widget_set_sensitive (button, FALSE);
button = gtk_button_new_with_label ("gtk_tree_store_node_insert");
hbox = gtk_hbox_new (FALSE, 8);
entry = gtk_entry_new ();
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), entry);
gtk_signal_connect (GTK_OBJECT (button), "clicked", node_insert, tree_view);
button = gtk_button_new_with_label ("gtk_tree_store_node_insert_before");
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (selection),
"row_selected", row_selected, button);
gtk_signal_connect (GTK_OBJECT (selection),
"row_unselected", row_unselected, button);
gtk_signal_connect (GTK_OBJECT (button), "clicked", node_insert_before, tree_view);
gtk_widget_set_sensitive (button, FALSE);
button = gtk_button_new_with_label ("gtk_tree_store_node_insert_after");
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (selection),
"row_selected", row_selected, button);
gtk_signal_connect (GTK_OBJECT (selection),
"row_unselected", row_unselected, button);
gtk_signal_connect (GTK_OBJECT (button), "clicked", node_insert_after, tree_view);
gtk_widget_set_sensitive (button, FALSE);
button = gtk_button_new_with_label ("gtk_tree_store_node_prepend");
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (button), "clicked", node_prepend, tree_view);
button = gtk_button_new_with_label ("gtk_tree_store_node_append");
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (button), "clicked", node_append, tree_view);
/* The selected column */
cell = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("nodes", cell, "text", 0, NULL);
gtk_tree_view_add_column (GTK_TREE_VIEW (tree_view), GTK_TREE_VIEW_COLUMN (column));
/* Show it all */
gtk_widget_show_all (window);
}
int
main (int argc, char *argv[])
{
gtk_init (&argc, &argv);
model = gtk_tree_store_new_with_values (2, G_TYPE_STRING, G_TYPE_STRING);
make_window ();
make_window ();
/* A few to start */
gtk_tree_store_node_append (GTK_TREE_STORE (model), NULL, node_new ());
gtk_tree_store_node_append (GTK_TREE_STORE (model), NULL, node_new ());
gtk_tree_store_node_append (GTK_TREE_STORE (model), NULL, node_new ());
gtk_main ();
return 0;
}