diff options
author | Matthias Vogelgesang <matthias.vogelgesang@gmail.com> | 2012-07-04 10:49:26 +0200 |
---|---|---|
committer | Matthias Vogelgesang <matthias.vogelgesang@gmail.com> | 2012-07-04 10:49:26 +0200 |
commit | 39c6bb082696283e74ee72a2097749a4de1a418b (patch) | |
tree | c3b7e2cf8e9710d6eac6b330ff58adf4b28d1ee8 | |
parent | b67947751a24366137844cd1a3b41bed7095bf76 (diff) | |
download | uca-39c6bb082696283e74ee72a2097749a4de1a418b.tar.gz uca-39c6bb082696283e74ee72a2097749a4de1a418b.tar.bz2 uca-39c6bb082696283e74ee72a2097749a4de1a418b.tar.xz uca-39c6bb082696283e74ee72a2097749a4de1a418b.zip |
Add property tree view
The standard tree view widget is not capable of setting individual cell
renderers per row. Thus I made one with a custom cell renderer that uses an
appropriate cell renderer depending of the property type.
I developed this independently and put it up on Github at
https://github.com/matze/EggPropertyTreeView.
-rw-r--r-- | test/CMakeLists.txt | 5 | ||||
-rw-r--r-- | test/control.c | 46 | ||||
-rw-r--r-- | test/control.glade | 30 | ||||
-rw-r--r-- | test/egg-property-cell-renderer.c | 502 | ||||
-rw-r--r-- | test/egg-property-cell-renderer.h | 55 | ||||
-rw-r--r-- | test/egg-property-tree-view.c | 114 | ||||
-rw-r--r-- | test/egg-property-tree-view.h | 54 |
7 files changed, 740 insertions, 66 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 428a56a..224bd46 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -36,7 +36,10 @@ target_link_libraries(grab-async uca ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES}) if (GTK2_FOUND) include_directories(${GTK2_INCLUDE_DIRS}) - add_executable(control control.c) + add_executable(control + control.c + egg-property-cell-renderer.c + egg-property-tree-view.c) target_link_libraries(control uca ${GTK2_LIBRARIES} ${GTHREAD2_LIBRARIES}) endif() diff --git a/test/control.c b/test/control.c index d408d90..eb3cce5 100644 --- a/test/control.c +++ b/test/control.c @@ -23,7 +23,9 @@ #include <time.h> #include <unistd.h> #include <errno.h> + #include "uca-camera.h" +#include "egg-property-tree-view.h" typedef struct { @@ -54,6 +56,7 @@ typedef struct { enum { COLUMN_NAME = 0, COLUMN_VALUE, + COLUMN_EDITABLE, NUM_COLUMNS }; @@ -230,7 +233,7 @@ static void on_valuecell_edited(GtkCellRendererText *renderer, gchar *path, gcha static void value_cell_data_func(GtkTreeViewColumn *column, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter, gpointer data) { gboolean editable; - gtk_tree_model_get(model, iter, 2, &editable, -1); + gtk_tree_model_get(model, iter, COLUMN_EDITABLE, &editable, -1); if (editable) { g_object_set(cell, @@ -249,40 +252,6 @@ static void value_cell_data_func(GtkTreeViewColumn *column, GtkCellRenderer *cel } } -static void populate_property_list(GtkBuilder *builder, UcaCamera *camera) -{ - GtkTreeViewColumn *value_column = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(builder, "valuecolumn")); - GtkCellRendererText *value_renderer = GTK_CELL_RENDERER_TEXT(gtk_builder_get_object(builder, "valuecell")); - GtkListStore *list_store = GTK_LIST_STORE(gtk_builder_get_object(builder, "camera-properties")); - GtkTreeIter iter; - - gtk_tree_view_column_set_cell_data_func(value_column, GTK_CELL_RENDERER(value_renderer), value_cell_data_func, NULL, NULL); - - GObjectClass *oclass = G_OBJECT_GET_CLASS(camera); - guint num_specs = 0; - GParamSpec **specs = g_object_class_list_properties(oclass, &num_specs); - GValue dest_value = {0}, src_value = {0}; - g_value_init(&dest_value, G_TYPE_STRING); - - for (guint i = 0; i < num_specs; i++) { - gtk_list_store_append(list_store, &iter); - gtk_list_store_set(list_store, &iter, 0, specs[i]->name, -1); - - if (specs[i]->flags & G_PARAM_READABLE) { - g_value_init(&src_value, specs[i]->value_type); - g_object_get_property(G_OBJECT(camera), specs[i]->name, &src_value); - if (g_value_transform(&src_value, &dest_value)) - gtk_list_store_set(list_store, &iter, - 1, g_value_get_string(&dest_value), - 2, specs[i]->flags & G_PARAM_WRITABLE, - -1); - g_value_unset(&src_value); - } - } - - g_free(specs); -} - static void transform_string_to_boolean(const GValue *src_value, GValue *dest_value) { const gchar *str = g_value_get_string(src_value); @@ -355,11 +324,16 @@ static void create_main_window(GtkBuilder *builder, const gchar* camera_name) GtkWidget *window = GTK_WIDGET(gtk_builder_get_object(builder, "window")); GtkWidget *image = GTK_WIDGET(gtk_builder_get_object(builder, "image")); + GtkWidget *property_tree_view = egg_property_tree_view_new (G_OBJECT (camera)); + GtkContainer *scrolled_property_window = GTK_CONTAINER (gtk_builder_get_object (builder, "scrolledwindow2")); + + gtk_container_add (scrolled_property_window, property_tree_view); + gtk_widget_show_all (GTK_WIDGET (scrolled_property_window)); + GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, td.width, td.height); gtk_image_set_from_pixbuf(GTK_IMAGE(image), pixbuf); register_transform_funcs(); - populate_property_list(builder, camera); td.pixel_size = bits_per_sample == 16 ? 2 : 1; td.image = image; diff --git a/test/control.glade b/test/control.glade index 36ed0ce..d70a343 100644 --- a/test/control.glade +++ b/test/control.glade @@ -196,35 +196,7 @@ <property name="hscrollbar_policy">automatic</property> <property name="vscrollbar_policy">automatic</property> <child> - <object class="GtkTreeView" id="treeview-properties"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="model">camera-properties</property> - <property name="headers_clickable">False</property> - <property name="search_column">0</property> - <child> - <object class="GtkTreeViewColumn" id="namecolumn"> - <property name="title">Name</property> - <child> - <object class="GtkCellRendererText" id="namecell"/> - <attributes> - <attribute name="text">0</attribute> - </attributes> - </child> - </object> - </child> - <child> - <object class="GtkTreeViewColumn" id="valuecolumn"> - <property name="title">Value</property> - <child> - <object class="GtkCellRendererText" id="valuecell"/> - <attributes> - <attribute name="text">1</attribute> - </attributes> - </child> - </object> - </child> - </object> + <placeholder/> </child> </object> <packing> diff --git a/test/egg-property-cell-renderer.c b/test/egg-property-cell-renderer.c new file mode 100644 index 0000000..d6cc5d5 --- /dev/null +++ b/test/egg-property-cell-renderer.c @@ -0,0 +1,502 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang <matthias.vogelgesang@kit.edu> + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 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 Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#include <stdlib.h> +#include "egg-property-cell-renderer.h" + +G_DEFINE_TYPE (EggPropertyCellRenderer, egg_property_cell_renderer, GTK_TYPE_CELL_RENDERER) + +#define EGG_PROPERTY_CELL_RENDERER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), EGG_TYPE_PROPERTY_CELL_RENDERER, EggPropertyCellRendererPrivate)) + + +struct _EggPropertyCellRendererPrivate +{ + GObject *object; + GtkListStore *list_store; + GtkCellRenderer *renderer; + GtkCellRenderer *text_renderer; + GtkCellRenderer *spin_renderer; + GtkCellRenderer *toggle_renderer; +}; + +enum +{ + PROP_0, + PROP_PROP_NAME, + N_PROPERTIES +}; + +static GParamSpec *egg_property_cell_renderer_properties[N_PROPERTIES] = { NULL, }; + +GtkCellRenderer * +egg_property_cell_renderer_new (GObject *object, + GtkListStore *list_store) +{ + EggPropertyCellRenderer *renderer; + + renderer = EGG_PROPERTY_CELL_RENDERER (g_object_new (EGG_TYPE_PROPERTY_CELL_RENDERER, NULL)); + renderer->priv->object = object; + renderer->priv->list_store = list_store; + return GTK_CELL_RENDERER (renderer); +} + +static GParamSpec * +get_pspec_from_object (GObject *object, const gchar *prop_name) +{ + GObjectClass *oclass = G_OBJECT_GET_CLASS (object); + return g_object_class_find_property (oclass, prop_name); +} + +static void +get_string_double_repr (GObject *object, const gchar *prop_name, gchar **text, gdouble *number) +{ + GParamSpec *pspec; + GValue from = { 0 }; + GValue to_string = { 0 }; + GValue to_double = { 0 }; + + pspec = get_pspec_from_object (object, prop_name); + g_value_init (&from, pspec->value_type); + g_value_init (&to_string, G_TYPE_STRING); + g_value_init (&to_double, G_TYPE_DOUBLE); + g_object_get_property (object, prop_name, &from); + + if (g_value_transform (&from, &to_string)) + *text = g_strdup (g_value_get_string (&to_string)); + else + g_warning ("Could not convert from %s gchar*\n", g_type_name (pspec->value_type)); + + if (g_value_transform (&from, &to_double)) + *number = g_value_get_double (&to_double); + else + g_warning ("Could not convert from %s to gdouble\n", g_type_name (pspec->value_type)); +} + +static void +clear_adjustment (GObject *object) +{ + GtkAdjustment *adjustment; + + g_object_get (object, + "adjustment", &adjustment, + NULL); + + if (adjustment) + g_object_unref (adjustment); + + g_object_set (object, + "adjustment", NULL, + NULL); +} + +static void +egg_property_cell_renderer_set_renderer (EggPropertyCellRenderer *renderer, + const gchar *prop_name) +{ + EggPropertyCellRendererPrivate *priv; + GParamSpec *pspec; + gchar *text = NULL; + gdouble number; + gboolean change_adjustment = FALSE; + + priv = EGG_PROPERTY_CELL_RENDERER_GET_PRIVATE (renderer); + pspec = get_pspec_from_object (priv->object, prop_name); + + /* + * Set this renderers mode, so that any actions can be forwarded to our + * child renderers. + */ + switch (pspec->value_type) { + /* toggle renderers */ + case G_TYPE_BOOLEAN: + priv->renderer = priv->toggle_renderer; + g_object_set (renderer, "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL); + break; + + /* spin renderers */ + case G_TYPE_FLOAT: + case G_TYPE_DOUBLE: + priv->renderer = priv->spin_renderer; + g_object_set (renderer, "mode", GTK_CELL_RENDERER_MODE_EDITABLE, NULL); + g_object_set (priv->renderer, "digits", 5, NULL); + change_adjustment = TRUE; + break; + + case G_TYPE_INT: + case G_TYPE_UINT: + case G_TYPE_LONG: + case G_TYPE_ULONG: + case G_TYPE_INT64: + case G_TYPE_UINT64: + priv->renderer = priv->spin_renderer; + g_object_set (renderer, "mode", GTK_CELL_RENDERER_MODE_EDITABLE, NULL); + g_object_set (priv->renderer, "digits", 0, NULL); + change_adjustment = TRUE; + break; + + /* text renderers */ + case G_TYPE_POINTER: + case G_TYPE_STRING: + priv->renderer = priv->text_renderer; + g_object_set (renderer, "mode", GTK_CELL_RENDERER_MODE_EDITABLE, NULL); + break; + + /* combo renderers */ + default: + /* g_print ("no idea how to handle %s -> %s\n", prop_name, g_type_name (pspec->value_type)); */ + break; + } + + /* + * Set the content from the objects property. + */ + switch (pspec->value_type) { + case G_TYPE_BOOLEAN: + { + gboolean val; + + g_object_get (priv->object, prop_name, &val, NULL); + g_object_set (priv->renderer, + "active", val, + "activatable", pspec->flags & G_PARAM_WRITABLE ? TRUE : FALSE, + NULL); + break; + } + + case G_TYPE_INT: + case G_TYPE_UINT: + case G_TYPE_LONG: + case G_TYPE_ULONG: + case G_TYPE_INT64: + case G_TYPE_UINT64: + case G_TYPE_FLOAT: + case G_TYPE_DOUBLE: + get_string_double_repr (priv->object, prop_name, &text, &number); + break; + + case G_TYPE_STRING: + g_object_get (priv->object, prop_name, &text, NULL); + break; + + case G_TYPE_POINTER: + { + gpointer val; + + g_object_get (priv->object, prop_name, &val, NULL); + text = g_strdup_printf ("0x%x", GPOINTER_TO_INT (val)); + } + break; + + default: + break; + } + + if (pspec->flags & G_PARAM_WRITABLE) { + if (GTK_IS_CELL_RENDERER_TOGGLE (priv->renderer)) + g_object_set (priv->renderer, "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL); + else + g_object_set (priv->renderer, "foreground", "#000000", NULL); + + if (GTK_IS_CELL_RENDERER_TEXT (priv->renderer)) { + g_object_set (priv->renderer, + "editable", TRUE, + "mode", GTK_CELL_RENDERER_MODE_EDITABLE, + NULL); + } + + if (GTK_IS_CELL_RENDERER_SPIN (priv->renderer)) { + GtkObject *adjustment = NULL; + +#define gtk_typed_adjustment_new(type, pspec, val, step_inc, page_inc) \ + gtk_adjustment_new (val, ((type *) pspec)->minimum, ((type *) pspec)->maximum, step_inc, page_inc, 0) + + switch (pspec->value_type) { + case G_TYPE_INT: + adjustment = gtk_typed_adjustment_new (GParamSpecInt, pspec, number, 1, 10); + break; + case G_TYPE_UINT: + adjustment = gtk_typed_adjustment_new (GParamSpecUInt, pspec, number, 1, 10); + break; + case G_TYPE_LONG: + adjustment = gtk_typed_adjustment_new (GParamSpecLong, pspec, number, 1, 10); + break; + case G_TYPE_ULONG: + adjustment = gtk_typed_adjustment_new (GParamSpecULong, pspec, number, 1, 10); + break; + case G_TYPE_INT64: + adjustment = gtk_typed_adjustment_new (GParamSpecInt64, pspec, number, 1, 10); + break; + case G_TYPE_UINT64: + adjustment = gtk_typed_adjustment_new (GParamSpecUInt64, pspec, number, 1, 10); + break; + case G_TYPE_FLOAT: + adjustment = gtk_typed_adjustment_new (GParamSpecFloat, pspec, number, 0.05, 10); + break; + case G_TYPE_DOUBLE: + adjustment = gtk_typed_adjustment_new (GParamSpecDouble, pspec, number, 0.05, 10); + break; + } + + clear_adjustment (G_OBJECT (priv->renderer)); + g_object_set (priv->renderer, "adjustment", adjustment, NULL); + } + } + else { + g_object_set (priv->renderer, "mode", GTK_CELL_RENDERER_MODE_INERT, NULL); + + if (!GTK_IS_CELL_RENDERER_TOGGLE (priv->renderer)) + g_object_set (priv->renderer, "foreground", "#aaaaaa", NULL); + } + + if (text != NULL) { + g_object_set (priv->renderer, "text", text, NULL); + g_free (text); + } +} + +static gchar * +get_prop_name_from_tree_model (GtkTreeModel *model, const gchar *path) +{ + GtkTreeIter iter; + gchar *prop_name = NULL; + + /* TODO: don't assume column 0 to contain the prop name */ + if (gtk_tree_model_get_iter_from_string (model, &iter, path)) + gtk_tree_model_get (model, &iter, 0, &prop_name, -1); + + return prop_name; +} + +static void +egg_property_cell_renderer_toggle_cb (GtkCellRendererToggle *renderer, + gchar *path, + gpointer user_data) +{ + EggPropertyCellRendererPrivate *priv; + gchar *prop_name; + + priv = (EggPropertyCellRendererPrivate *) user_data; + prop_name = get_prop_name_from_tree_model (GTK_TREE_MODEL (priv->list_store), path); + + if (prop_name != NULL) { + gboolean activated; + + g_object_get (priv->object, prop_name, &activated, NULL); + g_object_set (priv->object, prop_name, !activated, NULL); + g_free (prop_name); + } +} + +static void +egg_property_cell_renderer_text_edited_cb (GtkCellRendererText *renderer, + gchar *path, + gchar *new_text, + gpointer user_data) +{ + EggPropertyCellRendererPrivate *priv; + gchar *prop_name; + + priv = (EggPropertyCellRendererPrivate *) user_data; + prop_name = get_prop_name_from_tree_model (GTK_TREE_MODEL (priv->list_store), path); + + if (prop_name != NULL) { + g_object_set (priv->object, prop_name, new_text, NULL); + g_free (prop_name); + } +} + +static void +egg_property_cell_renderer_spin_edited_cb (GtkCellRendererText *renderer, + gchar *path, + gchar *new_text, + gpointer user_data) +{ + EggPropertyCellRendererPrivate *priv; + gchar *prop_name; + + priv = (EggPropertyCellRendererPrivate *) user_data; + prop_name = get_prop_name_from_tree_model (GTK_TREE_MODEL (priv->list_store), path); + + if (prop_name != NULL) { + GParamSpec *pspec; + GValue from = { 0 }; + GValue to = { 0 }; + + pspec = get_pspec_from_object (priv->object, prop_name); + + g_value_init (&from, G_TYPE_DOUBLE); + g_value_init (&to, pspec->value_type); + g_value_set_double (&from, strtod (new_text, NULL)); + + if (g_value_transform (&from, &to)) + g_object_set_property (priv->object, prop_name, &to); + else + g_warning ("Could not transform %s to %s\n", + g_value_get_string (&from), g_type_name (pspec->value_type)); + + g_free (prop_name); + } +} + +static void +egg_property_cell_renderer_get_size (GtkCellRenderer *cell, + GtkWidget *widget, + GdkRectangle *cell_area, + gint *x_offset, + gint *y_offset, + gint *width, + gint *height) +{ + + EggPropertyCellRendererPrivate *priv = EGG_PROPERTY_CELL_RENDERER_GET_PRIVATE (cell); + + gtk_cell_renderer_get_size (priv->renderer, widget, cell_area, x_offset, y_offset, width, height); +} + +static void +egg_property_cell_renderer_render (GtkCellRenderer *cell, + GdkDrawable *window, + GtkWidget *widget, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GdkRectangle *expose_area, + GtkCellRendererState flags) +{ + EggPropertyCellRendererPrivate *priv = EGG_PROPERTY_CELL_RENDERER_GET_PRIVATE (cell); + gtk_cell_renderer_render (priv->renderer, window, widget, background_area, cell_area, expose_area, flags); +} + +static gboolean +egg_property_cell_renderer_activate (GtkCellRenderer *cell, + GdkEvent *event, + GtkWidget *widget, + const gchar *path, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GtkCellRendererState flags) +{ + EggPropertyCellRendererPrivate *priv = EGG_PROPERTY_CELL_RENDERER_GET_PRIVATE (cell); + return gtk_cell_renderer_activate (priv->renderer, event, widget, path, background_area, cell_area, flags); +} + +static GtkCellEditable * +egg_property_cell_renderer_start_editing (GtkCellRenderer *cell, + GdkEvent *event, + GtkWidget *widget, + const gchar *path, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GtkCellRendererState flags) +{ + EggPropertyCellRendererPrivate *priv = EGG_PROPERTY_CELL_RENDERER_GET_PRIVATE (cell); + return gtk_cell_renderer_start_editing (priv->renderer, event, widget, path, background_area, cell_area, flags); +} + +static void +egg_property_cell_renderer_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + g_return_if_fail (EGG_IS_PROPERTY_CELL_RENDERER (object)); + EggPropertyCellRenderer *renderer = EGG_PROPERTY_CELL_RENDERER (object); + + switch (property_id) { + case PROP_PROP_NAME: + egg_property_cell_renderer_set_renderer (renderer, g_value_get_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + return; + } +} + +static void +egg_property_cell_renderer_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + g_return_if_fail (EGG_IS_PROPERTY_CELL_RENDERER (object)); + + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + return; + } +} + +static void +egg_property_cell_renderer_class_init (EggPropertyCellRendererClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GtkCellRendererClass *cellrenderer_class = GTK_CELL_RENDERER_CLASS (klass); + + gobject_class->set_property = egg_property_cell_renderer_set_property; + gobject_class->get_property = egg_property_cell_renderer_get_property; + + cellrenderer_class->render = egg_property_cell_renderer_render; + cellrenderer_class->get_size = egg_property_cell_renderer_get_size; + cellrenderer_class->activate = egg_property_cell_renderer_activate; + cellrenderer_class->start_editing = egg_property_cell_renderer_start_editing; + + egg_property_cell_renderer_properties[PROP_PROP_NAME] = + g_param_spec_string("prop-name", + "Property name", "Property name", "", + G_PARAM_READWRITE); + + g_object_class_install_property(gobject_class, PROP_PROP_NAME, egg_property_cell_renderer_properties[PROP_PROP_NAME]); + + g_type_class_add_private (klass, sizeof (EggPropertyCellRendererPrivate)); +} + +static void +egg_property_cell_renderer_init (EggPropertyCellRenderer *renderer) +{ + EggPropertyCellRendererPrivate *priv; + + renderer->priv = priv = EGG_PROPERTY_CELL_RENDERER_GET_PRIVATE (renderer); + + priv->text_renderer = gtk_cell_renderer_text_new (); + priv->spin_renderer = gtk_cell_renderer_spin_new (); + priv->toggle_renderer = gtk_cell_renderer_toggle_new (); + priv->renderer = priv->text_renderer; + + g_object_set (priv->text_renderer, + "editable", TRUE, + NULL); + + g_object_set (priv->spin_renderer, + "editable", TRUE, + NULL); + + g_object_set (priv->toggle_renderer, + "xalign", 0.0f, + "activatable", TRUE, + "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, + NULL); + + g_signal_connect (priv->spin_renderer, "edited", + G_CALLBACK (egg_property_cell_renderer_spin_edited_cb), priv); + + g_signal_connect (priv->text_renderer, "edited", + G_CALLBACK (egg_property_cell_renderer_text_edited_cb), NULL); + + g_signal_connect (priv->toggle_renderer, "toggled", + G_CALLBACK (egg_property_cell_renderer_toggle_cb), priv); +} diff --git a/test/egg-property-cell-renderer.h b/test/egg-property-cell-renderer.h new file mode 100644 index 0000000..d4dbe02 --- /dev/null +++ b/test/egg-property-cell-renderer.h @@ -0,0 +1,55 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang <matthias.vogelgesang@kit.edu> + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 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 Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#ifndef EGG_PROPERTY_CELL_RENDERER_H +#define EGG_PROPERTY_CELL_RENDERER_H + +#include <gtk/gtk.h> + +G_BEGIN_DECLS + +#define EGG_TYPE_PROPERTY_CELL_RENDERER (egg_property_cell_renderer_get_type()) +#define EGG_PROPERTY_CELL_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), EGG_TYPE_PROPERTY_CELL_RENDERER, EggPropertyCellRenderer)) +#define EGG_IS_PROPERTY_CELL_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), EGG_TYPE_PROPERTY_CELL_RENDERER)) +#define EGG_PROPERTY_CELL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EGG_TYPE_PROPERTY_CELL_RENDERER, EggPropertyCellRendererClass)) +#define EGG_IS_PROPERTY_CELL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EGG_TYPE_PROPERTY_CELL_RENDERER)) +#define EGG_PROPERTY_CELL_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EGG_TYPE_PROPERTY_CELL_RENDERER, EggPropertyCellRendererClass)) + +typedef struct _EggPropertyCellRenderer EggPropertyCellRenderer; +typedef struct _EggPropertyCellRendererClass EggPropertyCellRendererClass; +typedef struct _EggPropertyCellRendererPrivate EggPropertyCellRendererPrivate; + +struct _EggPropertyCellRenderer +{ + GtkCellRenderer parent_instance; + + /*< private >*/ + EggPropertyCellRendererPrivate *priv; +}; + +struct _EggPropertyCellRendererClass +{ + GtkCellRendererClass parent_class; +}; + +GType egg_property_cell_renderer_get_type (void); +GtkCellRenderer* egg_property_cell_renderer_new (GObject *object, + GtkListStore *list_store); + +G_END_DECLS + +#endif diff --git a/test/egg-property-tree-view.c b/test/egg-property-tree-view.c new file mode 100644 index 0000000..f4ed2fb --- /dev/null +++ b/test/egg-property-tree-view.c @@ -0,0 +1,114 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang <matthias.vogelgesang@kit.edu> + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 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 Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + + +#include "egg-property-tree-view.h" +#include "egg-property-cell-renderer.h" + +G_DEFINE_TYPE (EggPropertyTreeView, egg_property_tree_view, GTK_TYPE_TREE_VIEW) + +#define EGG_PROPERTY_TREE_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), EGG_TYPE_PROPERTY_TREE_VIEW, EggPropertyTreeViewPrivate)) + +struct _EggPropertyTreeViewPrivate +{ + GtkListStore *list_store; +}; + +enum +{ + COLUMN_PROP_NAME, + COLUMN_PROP_ROW, + COLUMN_PROP_ADJUSTMENT, + N_COLUMNS +}; + +static void +egg_property_tree_view_populate_model_with_properties (GtkListStore *model, GObject *object) +{ + GParamSpec **pspecs; + GObjectClass *oclass; + guint n_properties; + GtkTreeIter iter; + + oclass = G_OBJECT_GET_CLASS (object); + pspecs = g_object_class_list_properties (oclass, &n_properties); + + for (guint i = 0; i < n_properties; i++) { + if (pspecs[i]->flags & G_PARAM_READABLE) { + GtkObject *adjustment; + + adjustment = gtk_adjustment_new (5, 0, 1000, 1, 10, 0); + + gtk_list_store_append (model, &iter); + gtk_list_store_set (model, &iter, + COLUMN_PROP_NAME, pspecs[i]->name, + COLUMN_PROP_ROW, FALSE, + COLUMN_PROP_ADJUSTMENT, adjustment, + -1); + } + } + + g_free (pspecs); +} + +GtkWidget * +egg_property_tree_view_new (GObject *object) +{ + EggPropertyTreeView *property_tree_view; + GtkTreeView *tree_view; + GtkTreeViewColumn *prop_column, *value_column; + GtkCellRenderer *prop_renderer, *value_renderer; + GtkListStore *list_store; + + property_tree_view = EGG_PROPERTY_TREE_VIEW (g_object_new (EGG_TYPE_PROPERTY_TREE_VIEW, NULL)); + list_store = property_tree_view->priv->list_store; + tree_view = GTK_TREE_VIEW (property_tree_view); + + egg_property_tree_view_populate_model_with_properties (list_store, object); + gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (list_store)); + + prop_renderer = gtk_cell_renderer_text_new (); + prop_column = gtk_tree_view_column_new_with_attributes ("Property", prop_renderer, + "text", COLUMN_PROP_NAME, + NULL); + + value_renderer = egg_property_cell_renderer_new (object, list_store); + value_column = gtk_tree_view_column_new_with_attributes ("Value", value_renderer, + "prop-name", COLUMN_PROP_NAME, + NULL); + + gtk_tree_view_append_column (tree_view, prop_column); + gtk_tree_view_append_column (tree_view, value_column); + + return GTK_WIDGET (tree_view); +} + +static void +egg_property_tree_view_class_init (EggPropertyTreeViewClass *klass) +{ + g_type_class_add_private (klass, sizeof (EggPropertyTreeViewPrivate)); +} + +static void +egg_property_tree_view_init (EggPropertyTreeView *tree_view) +{ + EggPropertyTreeViewPrivate *priv = EGG_PROPERTY_TREE_VIEW_GET_PRIVATE (tree_view); + + tree_view->priv = priv = EGG_PROPERTY_TREE_VIEW_GET_PRIVATE (tree_view); + priv->list_store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_BOOLEAN, GTK_TYPE_ADJUSTMENT); +} + diff --git a/test/egg-property-tree-view.h b/test/egg-property-tree-view.h new file mode 100644 index 0000000..e8fd0fe --- /dev/null +++ b/test/egg-property-tree-view.h @@ -0,0 +1,54 @@ +/* Copyright (C) 2011, 2012 Matthias Vogelgesang <matthias.vogelgesang@kit.edu> + (Karlsruhe Institute of Technology) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2.1 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 Lesser General Public License for more + details. + + You should have received a copy of the GNU Lesser General Public License along + with this library; if not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110, USA */ + +#ifndef EGG_PROPERTY_TREE_VIEW_H +#define EGG_PROPERTY_TREE_VIEW_H + +#include <gtk/gtk.h> + +G_BEGIN_DECLS + +#define EGG_TYPE_PROPERTY_TREE_VIEW (egg_property_tree_view_get_type()) +#define EGG_PROPERTY_TREE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), EGG_TYPE_PROPERTY_TREE_VIEW, EggPropertyTreeView)) +#define EGG_IS_PROPERTY_TREE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), EGG_TYPE_PROPERTY_TREE_VIEW)) +#define EGG_PROPERTY_TREE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EGG_TYPE_PROPERTY_TREE_VIEW, EggPropertyTreeViewClass)) +#define EGG_IS_PROPERTY_TREE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EGG_TYPE_PROPERTY_TREE_VIEW)) +#define EGG_PROPERTY_TREE_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EGG_TYPE_PROPERTY_TREE_VIEW, EggPropertyTreeViewClass)) + +typedef struct _EggPropertyTreeView EggPropertyTreeView; +typedef struct _EggPropertyTreeViewClass EggPropertyTreeViewClass; +typedef struct _EggPropertyTreeViewPrivate EggPropertyTreeViewPrivate; + +struct _EggPropertyTreeView +{ + GtkTreeView parent_instance; + + /*< private >*/ + EggPropertyTreeViewPrivate *priv; +}; + +struct _EggPropertyTreeViewClass +{ + GtkTreeViewClass parent_class; +}; + +GType egg_property_tree_view_get_type (void) G_GNUC_CONST; +GtkWidget* egg_property_tree_view_new (GObject *object); + +G_END_DECLS + +#endif |