Split the property editor code out for reuse, improve.
* tests/prop-editor.[ch] test/testtreeview.c tests/Makefile.am: Split the property editor code out for reuse, improve.
This commit is contained in:
		
							
								
								
									
										586
									
								
								tests/prop-editor.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										586
									
								
								tests/prop-editor.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,586 @@
 | 
			
		||||
/* prop-editor.c
 | 
			
		||||
 * Copyright (C) 2000  Red Hat, Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * 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 <gtk/gtk.h>
 | 
			
		||||
 | 
			
		||||
#include "prop-editor.h"
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
get_param_specs (GObject      *object,
 | 
			
		||||
                 GParamSpec ***specs,
 | 
			
		||||
                 gint         *n_specs)
 | 
			
		||||
{
 | 
			
		||||
  /* Use private interface for now, fix later */
 | 
			
		||||
  *specs = G_OBJECT_GET_CLASS (object)->property_specs;
 | 
			
		||||
  *n_specs = G_OBJECT_GET_CLASS (object)->n_property_specs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  gpointer instance;
 | 
			
		||||
  GObject *alive_object;
 | 
			
		||||
  guint id;
 | 
			
		||||
} DisconnectData;
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
disconnect_func (gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  DisconnectData *dd = data;
 | 
			
		||||
  
 | 
			
		||||
  g_signal_handler_disconnect (dd->instance, dd->id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
signal_removed (gpointer  data,
 | 
			
		||||
		GClosure *closure)
 | 
			
		||||
{
 | 
			
		||||
  DisconnectData *dd = data;
 | 
			
		||||
 | 
			
		||||
  g_object_steal_data (dd->alive_object, "alive-object-data");
 | 
			
		||||
  g_free (dd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
g_object_connect_property (GObject *object,
 | 
			
		||||
                           const gchar *prop_name,
 | 
			
		||||
                           GtkSignalFunc func,
 | 
			
		||||
                           gpointer data,
 | 
			
		||||
                           GObject *alive_object)
 | 
			
		||||
{
 | 
			
		||||
  GClosure *closure;
 | 
			
		||||
  gchar *with_detail = g_strconcat ("notify::", prop_name, NULL);
 | 
			
		||||
  DisconnectData *dd;
 | 
			
		||||
 | 
			
		||||
  dd = g_new (DisconnectData, 1);
 | 
			
		||||
 | 
			
		||||
  closure = g_cclosure_new (func, data, NULL);
 | 
			
		||||
 | 
			
		||||
  g_closure_add_invalidate_notifier (closure, dd, signal_removed);
 | 
			
		||||
 | 
			
		||||
  dd->id = g_signal_connect_closure (object, with_detail,
 | 
			
		||||
				     closure, FALSE);
 | 
			
		||||
 | 
			
		||||
  dd->instance = object;
 | 
			
		||||
  dd->alive_object = alive_object;
 | 
			
		||||
  
 | 
			
		||||
  g_object_set_data_full (G_OBJECT (alive_object),
 | 
			
		||||
                          "alive-object-data",
 | 
			
		||||
                          dd,
 | 
			
		||||
                          disconnect_func);
 | 
			
		||||
  
 | 
			
		||||
  g_free (with_detail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct 
 | 
			
		||||
{
 | 
			
		||||
  GObject *obj;
 | 
			
		||||
  gchar *prop;
 | 
			
		||||
} ObjectProperty;
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
free_object_property (ObjectProperty *p)
 | 
			
		||||
{
 | 
			
		||||
  g_free (p->prop);
 | 
			
		||||
  g_free (p);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
connect_controller (GObject *controller,
 | 
			
		||||
                    const gchar *signal,
 | 
			
		||||
                    GObject *model,
 | 
			
		||||
                    const gchar *prop_name,
 | 
			
		||||
                    GtkSignalFunc func)
 | 
			
		||||
{
 | 
			
		||||
  ObjectProperty *p;
 | 
			
		||||
 | 
			
		||||
  p = g_new (ObjectProperty, 1);
 | 
			
		||||
  p->obj = model;
 | 
			
		||||
  p->prop = g_strdup (prop_name);
 | 
			
		||||
 | 
			
		||||
  g_signal_connect_data (controller, signal, func, p,
 | 
			
		||||
                         (GClosureNotify)free_object_property,
 | 
			
		||||
                         FALSE, FALSE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
int_modified (GtkAdjustment *adj, gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  ObjectProperty *p = data;
 | 
			
		||||
 | 
			
		||||
  g_object_set (p->obj, p->prop, (int) adj->value, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
int_changed (GObject *object, GParamSpec *pspec, gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  GtkAdjustment *adj = GTK_ADJUSTMENT (data);
 | 
			
		||||
  GValue val = { 0, };  
 | 
			
		||||
 | 
			
		||||
  g_value_init (&val, G_TYPE_INT);
 | 
			
		||||
  g_object_get_property (object, pspec->name, &val);
 | 
			
		||||
 | 
			
		||||
  if (g_value_get_int (&val) != (int)adj->value)
 | 
			
		||||
    gtk_adjustment_set_value (adj, g_value_get_int (&val));
 | 
			
		||||
 | 
			
		||||
  g_value_unset (&val);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
float_modified (GtkAdjustment *adj, gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  ObjectProperty *p = data;
 | 
			
		||||
 | 
			
		||||
  g_object_set (p->obj, p->prop, (float) adj->value, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
float_changed (GObject *object, GParamSpec *pspec, gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  GtkAdjustment *adj = GTK_ADJUSTMENT (data);
 | 
			
		||||
  GValue val = { 0, };  
 | 
			
		||||
 | 
			
		||||
  g_value_init (&val, G_TYPE_FLOAT);
 | 
			
		||||
  g_object_get_property (object, pspec->name, &val);
 | 
			
		||||
 | 
			
		||||
  if (g_value_get_float (&val) != (float) adj->value)
 | 
			
		||||
    gtk_adjustment_set_value (adj, g_value_get_float (&val));
 | 
			
		||||
 | 
			
		||||
  g_value_unset (&val);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
string_modified (GtkEntry *entry, gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  ObjectProperty *p = data;
 | 
			
		||||
  const gchar *text;
 | 
			
		||||
 | 
			
		||||
  text = gtk_entry_get_text (entry);
 | 
			
		||||
 | 
			
		||||
  g_object_set (p->obj, p->prop, text, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
string_changed (GObject *object, GParamSpec *pspec, gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  GtkEntry *entry = GTK_ENTRY (data);
 | 
			
		||||
  GValue val = { 0, };  
 | 
			
		||||
  const gchar *str;
 | 
			
		||||
  const gchar *text;
 | 
			
		||||
  
 | 
			
		||||
  g_value_init (&val, G_TYPE_STRING);
 | 
			
		||||
  g_object_get_property (object, pspec->name, &val);
 | 
			
		||||
 | 
			
		||||
  str = g_value_get_string (&val);
 | 
			
		||||
  if (str == NULL)
 | 
			
		||||
    str = "";
 | 
			
		||||
  text = gtk_entry_get_text (entry);
 | 
			
		||||
 | 
			
		||||
  if (strcmp (str, text) != 0)
 | 
			
		||||
    gtk_entry_set_text (entry, str);
 | 
			
		||||
  
 | 
			
		||||
  g_value_unset (&val);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
bool_modified (GtkToggleButton *tb, gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  ObjectProperty *p = data;
 | 
			
		||||
 | 
			
		||||
  g_object_set (p->obj, p->prop, (int) tb->active, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
bool_changed (GObject *object, GParamSpec *pspec, gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  GtkToggleButton *tb = GTK_TOGGLE_BUTTON (data);
 | 
			
		||||
  GValue val = { 0, };  
 | 
			
		||||
  
 | 
			
		||||
  g_value_init (&val, G_TYPE_BOOLEAN);
 | 
			
		||||
  g_object_get_property (object, pspec->name, &val);
 | 
			
		||||
 | 
			
		||||
  if (g_value_get_boolean (&val) != tb->active)
 | 
			
		||||
    gtk_toggle_button_set_active (tb, g_value_get_boolean (&val));
 | 
			
		||||
 | 
			
		||||
  gtk_label_set_text (GTK_LABEL (GTK_BIN (tb)->child), g_value_get_boolean (&val) ?
 | 
			
		||||
                      "TRUE" : "FALSE");
 | 
			
		||||
  
 | 
			
		||||
  g_value_unset (&val);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
enum_modified (GtkOptionMenu *om, gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  ObjectProperty *p = data;
 | 
			
		||||
  gint i;
 | 
			
		||||
  GParamSpec *spec;
 | 
			
		||||
  GEnumClass *eclass;
 | 
			
		||||
  
 | 
			
		||||
  spec = g_object_class_find_property (G_OBJECT_GET_CLASS (p->obj),
 | 
			
		||||
                                       p->prop);
 | 
			
		||||
 | 
			
		||||
  eclass = G_ENUM_CLASS (g_type_class_peek (spec->value_type));
 | 
			
		||||
  
 | 
			
		||||
  i = gtk_option_menu_get_history (om);
 | 
			
		||||
 | 
			
		||||
  g_object_set (p->obj, p->prop, eclass->values[i].value, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
enum_changed (GObject *object, GParamSpec *pspec, gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  GtkOptionMenu *om = GTK_OPTION_MENU (data);
 | 
			
		||||
  GValue val = { 0, };  
 | 
			
		||||
  GEnumClass *eclass;
 | 
			
		||||
  gint i;
 | 
			
		||||
 | 
			
		||||
  eclass = G_ENUM_CLASS (g_type_class_peek (pspec->value_type));
 | 
			
		||||
  
 | 
			
		||||
  g_value_init (&val, pspec->value_type);
 | 
			
		||||
  g_object_get_property (object, pspec->name, &val);
 | 
			
		||||
 | 
			
		||||
  i = 0;
 | 
			
		||||
  while (i < eclass->n_values)
 | 
			
		||||
    {
 | 
			
		||||
      if (eclass->values[i].value == g_value_get_enum (&val))
 | 
			
		||||
        break;
 | 
			
		||||
      ++i;
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  if (gtk_option_menu_get_history (om) != i)
 | 
			
		||||
    gtk_option_menu_set_history (om, i);
 | 
			
		||||
  
 | 
			
		||||
  g_value_unset (&val);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gunichar
 | 
			
		||||
unichar_get_value (GtkEntry *entry)
 | 
			
		||||
{
 | 
			
		||||
  const gchar *text = gtk_entry_get_text (entry);
 | 
			
		||||
  
 | 
			
		||||
  if (text[0])
 | 
			
		||||
    return g_utf8_get_char (text);
 | 
			
		||||
  else
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
unichar_modified (GtkEntry *entry, gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  ObjectProperty *p = data;
 | 
			
		||||
  gunichar val = unichar_get_value (entry);
 | 
			
		||||
 | 
			
		||||
  g_object_set (p->obj, p->prop, val, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
unichar_changed (GObject *object, GParamSpec *pspec, gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  GtkEntry *entry = GTK_ENTRY (data);
 | 
			
		||||
  gunichar new_val;
 | 
			
		||||
  gunichar old_val = unichar_get_value (entry);
 | 
			
		||||
  gchar buf[7];
 | 
			
		||||
  gint len;
 | 
			
		||||
 | 
			
		||||
  g_object_get (object, pspec->name, &new_val, NULL);
 | 
			
		||||
 | 
			
		||||
  if (new_val != old_val)
 | 
			
		||||
    {
 | 
			
		||||
      if (!new_val)
 | 
			
		||||
	len = 0;
 | 
			
		||||
      else
 | 
			
		||||
	len = g_unichar_to_utf8 (new_val, buf);
 | 
			
		||||
      
 | 
			
		||||
      buf[len] = '\0';
 | 
			
		||||
      
 | 
			
		||||
      gtk_entry_set_text (entry, buf);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
model_destroy (gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  g_object_steal_data (data, "model-object");
 | 
			
		||||
  gtk_widget_destroy (data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
window_destroy (gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  g_object_steal_data (data, "prop-editor-win");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GtkWidget*
 | 
			
		||||
create_prop_editor (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  GtkWidget *win;
 | 
			
		||||
  GtkWidget *vbox;
 | 
			
		||||
  GtkWidget *hbox;
 | 
			
		||||
  GtkWidget *label;
 | 
			
		||||
  GtkWidget *prop_edit;
 | 
			
		||||
  GtkWidget *sw;
 | 
			
		||||
  gint n_specs = 0;
 | 
			
		||||
  GParamSpec **specs = NULL;
 | 
			
		||||
  gint i;
 | 
			
		||||
  GtkAdjustment *adj;
 | 
			
		||||
  GtkTooltips *tips;
 | 
			
		||||
 | 
			
		||||
  win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 | 
			
		||||
 | 
			
		||||
  tips = gtk_tooltips_new ();
 | 
			
		||||
  gtk_signal_connect_object (GTK_OBJECT (win), "destroy",
 | 
			
		||||
			     GTK_SIGNAL_FUNC (gtk_object_destroy), GTK_OBJECT (tips));
 | 
			
		||||
 | 
			
		||||
  /* hold a weak ref to the object we're editing */
 | 
			
		||||
  g_object_set_data_full (G_OBJECT (object), "prop-editor-win", win, model_destroy);
 | 
			
		||||
  g_object_set_data_full (G_OBJECT (win), "model-object", object, window_destroy);
 | 
			
		||||
  
 | 
			
		||||
  vbox = gtk_vbox_new (TRUE, 2);
 | 
			
		||||
 | 
			
		||||
  sw = gtk_scrolled_window_new (NULL, NULL);
 | 
			
		||||
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
 | 
			
		||||
                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 | 
			
		||||
  
 | 
			
		||||
  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), vbox);
 | 
			
		||||
  gtk_container_add (GTK_CONTAINER (win), sw);
 | 
			
		||||
  
 | 
			
		||||
  get_param_specs (object, &specs, &n_specs);
 | 
			
		||||
  
 | 
			
		||||
  i = 0;
 | 
			
		||||
  while (i < n_specs)
 | 
			
		||||
    {
 | 
			
		||||
      GParamSpec *spec = specs[i];
 | 
			
		||||
      gboolean can_modify;
 | 
			
		||||
      
 | 
			
		||||
      prop_edit = NULL;
 | 
			
		||||
 | 
			
		||||
      can_modify = ((spec->flags & G_PARAM_WRITABLE) != 0 &&
 | 
			
		||||
                    (spec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
 | 
			
		||||
      
 | 
			
		||||
      if ((spec->flags & G_PARAM_READABLE) == 0)
 | 
			
		||||
        {
 | 
			
		||||
          /* can't display unreadable properties */
 | 
			
		||||
          ++i;
 | 
			
		||||
          continue;
 | 
			
		||||
        }
 | 
			
		||||
      
 | 
			
		||||
      switch (G_PARAM_SPEC_TYPE (spec))
 | 
			
		||||
        {
 | 
			
		||||
        case G_TYPE_PARAM_INT:
 | 
			
		||||
          hbox = gtk_hbox_new (FALSE, 10);
 | 
			
		||||
          label = gtk_label_new (spec->nick);
 | 
			
		||||
          gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
 | 
			
		||||
          gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
 | 
			
		||||
          adj = GTK_ADJUSTMENT (gtk_adjustment_new (G_PARAM_SPEC_INT (spec)->default_value,
 | 
			
		||||
                                                    G_PARAM_SPEC_INT (spec)->minimum,
 | 
			
		||||
                                                    G_PARAM_SPEC_INT (spec)->maximum,
 | 
			
		||||
                                                    1,
 | 
			
		||||
                                                    MAX ((G_PARAM_SPEC_INT (spec)->maximum -
 | 
			
		||||
                                                          G_PARAM_SPEC_INT (spec)->minimum) / 10, 1),
 | 
			
		||||
                                                    0.0));
 | 
			
		||||
 | 
			
		||||
          prop_edit = gtk_spin_button_new (adj, 1.0, 0);
 | 
			
		||||
          gtk_box_pack_end (GTK_BOX (hbox), prop_edit, FALSE, FALSE, 0);
 | 
			
		||||
          
 | 
			
		||||
          gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); 
 | 
			
		||||
 | 
			
		||||
          g_object_connect_property (object, spec->name,
 | 
			
		||||
                                     GTK_SIGNAL_FUNC (int_changed),
 | 
			
		||||
                                     adj, G_OBJECT (adj));
 | 
			
		||||
 | 
			
		||||
          if (can_modify)
 | 
			
		||||
            connect_controller (G_OBJECT (adj), "value_changed",
 | 
			
		||||
                                object, spec->name, (GtkSignalFunc) int_modified);
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case G_TYPE_PARAM_FLOAT:
 | 
			
		||||
          hbox = gtk_hbox_new (FALSE, 10);
 | 
			
		||||
          label = gtk_label_new (spec->nick);
 | 
			
		||||
          gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
 | 
			
		||||
          gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
 | 
			
		||||
          adj = GTK_ADJUSTMENT (gtk_adjustment_new (G_PARAM_SPEC_FLOAT (spec)->default_value,
 | 
			
		||||
                                                    G_PARAM_SPEC_FLOAT (spec)->minimum,
 | 
			
		||||
                                                    G_PARAM_SPEC_FLOAT (spec)->maximum,
 | 
			
		||||
                                                    0.1,
 | 
			
		||||
                                                    MAX ((G_PARAM_SPEC_FLOAT (spec)->maximum -
 | 
			
		||||
                                                          G_PARAM_SPEC_FLOAT (spec)->minimum) / 10, 0.1),
 | 
			
		||||
                                                    0.0));
 | 
			
		||||
 | 
			
		||||
          prop_edit = gtk_spin_button_new (adj, 0.1, 2);
 | 
			
		||||
          
 | 
			
		||||
          gtk_box_pack_end (GTK_BOX (hbox), prop_edit, FALSE, FALSE, 0);
 | 
			
		||||
          
 | 
			
		||||
          gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); 
 | 
			
		||||
 | 
			
		||||
          g_object_connect_property (object, spec->name,
 | 
			
		||||
                                     GTK_SIGNAL_FUNC (float_changed),
 | 
			
		||||
                                     adj, G_OBJECT (adj));
 | 
			
		||||
 | 
			
		||||
          if (can_modify)
 | 
			
		||||
            connect_controller (G_OBJECT (adj), "value_changed",
 | 
			
		||||
                                object, spec->name, (GtkSignalFunc) float_modified);
 | 
			
		||||
          break;
 | 
			
		||||
          
 | 
			
		||||
        case G_TYPE_PARAM_STRING:
 | 
			
		||||
          hbox = gtk_hbox_new (FALSE, 10);
 | 
			
		||||
          label = gtk_label_new (spec->nick);
 | 
			
		||||
          gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
 | 
			
		||||
          gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
 | 
			
		||||
 | 
			
		||||
          prop_edit = gtk_entry_new ();
 | 
			
		||||
          gtk_box_pack_end (GTK_BOX (hbox), prop_edit, FALSE, FALSE, 0);
 | 
			
		||||
          
 | 
			
		||||
          gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); 
 | 
			
		||||
 | 
			
		||||
          g_object_connect_property (object, spec->name,
 | 
			
		||||
                                     GTK_SIGNAL_FUNC (string_changed),
 | 
			
		||||
                                     prop_edit, G_OBJECT (prop_edit));
 | 
			
		||||
 | 
			
		||||
          if (can_modify)
 | 
			
		||||
            connect_controller (G_OBJECT (prop_edit), "changed",
 | 
			
		||||
                                object, spec->name, (GtkSignalFunc) string_modified);
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case G_TYPE_PARAM_BOOLEAN:
 | 
			
		||||
          hbox = gtk_hbox_new (FALSE, 10);
 | 
			
		||||
          label = gtk_label_new (spec->nick);
 | 
			
		||||
          gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
 | 
			
		||||
          gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
 | 
			
		||||
 | 
			
		||||
          prop_edit = gtk_toggle_button_new_with_label ("");
 | 
			
		||||
          gtk_box_pack_end (GTK_BOX (hbox), prop_edit, FALSE, FALSE, 0);
 | 
			
		||||
          
 | 
			
		||||
          gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); 
 | 
			
		||||
 | 
			
		||||
          g_object_connect_property (object, spec->name,
 | 
			
		||||
                                     GTK_SIGNAL_FUNC (bool_changed),
 | 
			
		||||
                                     prop_edit, G_OBJECT (prop_edit));
 | 
			
		||||
 | 
			
		||||
          if (can_modify)
 | 
			
		||||
            connect_controller (G_OBJECT (prop_edit), "toggled",
 | 
			
		||||
                                object, spec->name, (GtkSignalFunc) bool_modified);
 | 
			
		||||
          break;
 | 
			
		||||
          
 | 
			
		||||
        case G_TYPE_PARAM_ENUM:
 | 
			
		||||
	  {
 | 
			
		||||
	    GtkWidget *menu;
 | 
			
		||||
	    GEnumClass *eclass;
 | 
			
		||||
	    gint i;
 | 
			
		||||
            
 | 
			
		||||
	    hbox = gtk_hbox_new (FALSE, 10);
 | 
			
		||||
	    label = gtk_label_new (spec->nick);
 | 
			
		||||
	    gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
 | 
			
		||||
	    gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
 | 
			
		||||
            
 | 
			
		||||
	    prop_edit = gtk_option_menu_new ();
 | 
			
		||||
	    
 | 
			
		||||
	    menu = gtk_menu_new ();
 | 
			
		||||
 | 
			
		||||
	    eclass = G_ENUM_CLASS (g_type_class_ref (spec->value_type));
 | 
			
		||||
	    
 | 
			
		||||
	    i = 0;
 | 
			
		||||
	    while (i < eclass->n_values)
 | 
			
		||||
	      {
 | 
			
		||||
		GtkWidget *mi;
 | 
			
		||||
                
 | 
			
		||||
		mi = gtk_menu_item_new_with_label (eclass->values[i].value_name);
 | 
			
		||||
		
 | 
			
		||||
		gtk_widget_show (mi);
 | 
			
		||||
                
 | 
			
		||||
		gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
 | 
			
		||||
                
 | 
			
		||||
                  ++i;
 | 
			
		||||
	      }
 | 
			
		||||
	    
 | 
			
		||||
	    g_type_class_unref (eclass);
 | 
			
		||||
	    
 | 
			
		||||
	    gtk_option_menu_set_menu (GTK_OPTION_MENU (prop_edit), menu);
 | 
			
		||||
	    
 | 
			
		||||
	    gtk_box_pack_end (GTK_BOX (hbox), prop_edit, FALSE, FALSE, 0);
 | 
			
		||||
            
 | 
			
		||||
	    gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); 
 | 
			
		||||
            
 | 
			
		||||
	    g_object_connect_property (object, spec->name,
 | 
			
		||||
				       GTK_SIGNAL_FUNC (enum_changed),
 | 
			
		||||
				       prop_edit, G_OBJECT (prop_edit));
 | 
			
		||||
            
 | 
			
		||||
	    if (can_modify)
 | 
			
		||||
	      connect_controller (G_OBJECT (prop_edit), "changed",
 | 
			
		||||
				  object, spec->name, (GtkSignalFunc) enum_modified);
 | 
			
		||||
	  }
 | 
			
		||||
	  
 | 
			
		||||
        case G_TYPE_PARAM_UNICHAR:
 | 
			
		||||
          hbox = gtk_hbox_new (FALSE, 10);
 | 
			
		||||
          label = gtk_label_new (spec->nick);
 | 
			
		||||
          gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
 | 
			
		||||
          gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
 | 
			
		||||
 | 
			
		||||
	  prop_edit = gtk_entry_new ();
 | 
			
		||||
	  gtk_entry_set_max_length (GTK_ENTRY (prop_edit), 1);
 | 
			
		||||
          gtk_box_pack_end (GTK_BOX (hbox), prop_edit, FALSE, FALSE, 0);
 | 
			
		||||
          
 | 
			
		||||
          gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); 
 | 
			
		||||
 | 
			
		||||
          g_object_connect_property (object, spec->name,
 | 
			
		||||
                                     GTK_SIGNAL_FUNC (unichar_changed),
 | 
			
		||||
                                     prop_edit, G_OBJECT (prop_edit));
 | 
			
		||||
 | 
			
		||||
          if (can_modify)
 | 
			
		||||
            connect_controller (G_OBJECT (prop_edit), "changed",
 | 
			
		||||
                                object, spec->name, (GtkSignalFunc) unichar_modified);
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
	  {
 | 
			
		||||
	    gchar *msg = g_strdup_printf ("%s: don't know how to edit property type %s",
 | 
			
		||||
					  spec->nick, g_type_name (G_PARAM_SPEC_TYPE (spec)));
 | 
			
		||||
	    hbox = gtk_hbox_new (FALSE, 10);
 | 
			
		||||
	    label = gtk_label_new (msg);            
 | 
			
		||||
	    g_free (msg);
 | 
			
		||||
	    gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
 | 
			
		||||
	    gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
 | 
			
		||||
	    gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
 | 
			
		||||
	  }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (prop_edit)
 | 
			
		||||
        {
 | 
			
		||||
          if (!can_modify)
 | 
			
		||||
            gtk_widget_set_sensitive (prop_edit, FALSE);
 | 
			
		||||
 | 
			
		||||
	  if (spec->blurb)
 | 
			
		||||
	    gtk_tooltips_set_tip (tips, prop_edit, spec->blurb, NULL);
 | 
			
		||||
	  
 | 
			
		||||
          /* set initial value */
 | 
			
		||||
          g_object_notify (object, spec->name);
 | 
			
		||||
        }
 | 
			
		||||
      
 | 
			
		||||
      ++i;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  gtk_window_set_default_size (GTK_WINDOW (win), 300, 500);
 | 
			
		||||
  
 | 
			
		||||
  gtk_widget_show_all (win);
 | 
			
		||||
 | 
			
		||||
  return win;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										30
									
								
								tests/prop-editor.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								tests/prop-editor.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
			
		||||
/* prop-editor.h
 | 
			
		||||
 * Copyright (C) 2000  Red Hat, Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * 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 <gtk/gtkwidget.h>
 | 
			
		||||
 | 
			
		||||
#ifndef __PROP_EDITOR_H__
 | 
			
		||||
#define __PROP_EDITOR_H__
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
GtkWidget *create_prop_editor (GObject *object);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* __PROP_EDITOR_H__ */
 | 
			
		||||
		Reference in New Issue
	
	Block a user