mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-05 16:20:10 +00:00
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:
parent
76806e9a1e
commit
3ff4a2c081
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
268
gtk/gtkcellrenderer.c
Normal 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
111
gtk/gtkcellrenderer.h
Normal 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
240
gtk/gtkcellrendererpixbuf.c
Normal 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);
|
||||
}
|
58
gtk/gtkcellrendererpixbuf.h
Normal file
58
gtk/gtkcellrendererpixbuf.h
Normal 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
449
gtk/gtkcellrenderertext.c
Normal 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
65
gtk/gtkcellrenderertext.h
Normal 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__ */
|
399
gtk/gtkcellrenderertextpixbuf.c
Normal file
399
gtk/gtkcellrenderertextpixbuf.c
Normal 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);
|
||||
}
|
61
gtk/gtkcellrenderertextpixbuf.h
Normal file
61
gtk/gtkcellrenderertextpixbuf.h
Normal 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
321
gtk/gtkcellrenderertoggle.c
Normal 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;
|
||||
}
|
68
gtk/gtkcellrenderertoggle.h
Normal file
68
gtk/gtkcellrenderertoggle.h
Normal 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
458
gtk/gtkliststore.c
Normal 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
87
gtk/gtkliststore.h
Normal 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
430
gtk/gtkmodelsimple.c
Normal 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
73
gtk/gtkmodelsimple.h
Normal 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
994
gtk/gtkrbtree.c
Normal 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
133
gtk/gtkrbtree.h
Normal 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>K_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
159
gtk/gtktreedatalist.c
Normal 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
53
gtk/gtktreedatalist.h
Normal 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
421
gtk/gtktreemodel.c
Normal 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
144
gtk/gtktreemodel.h
Normal 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
191
gtk/gtktreeprivate.h
Normal 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)&>K_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
702
gtk/gtktreeselection.c
Normal 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
120
gtk/gtktreeselection.h
Normal 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
655
gtk/gtktreestore.c
Normal 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
99
gtk/gtktreestore.h
Normal 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
3384
gtk/gtktreeview.c
Normal file
File diff suppressed because it is too large
Load Diff
105
gtk/gtktreeview.h
Normal file
105
gtk/gtktreeview.h
Normal 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
633
gtk/gtktreeviewcolumn.c
Normal 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
137
gtk/gtktreeviewcolumn.h
Normal 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
206
gtk/treestoretest.c
Normal 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
206
tests/treestoretest.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user