]> spindle.queued.net Git - midori/commitdiff
Implement property proxy widget creation.
authorChristian Dywan <christian@twotoasts.de>
Sun, 13 Apr 2008 19:21:39 +0000 (21:21 +0200)
committerChristian Dywan <christian@twotoasts.de>
Sun, 13 Apr 2008 19:21:39 +0000 (21:21 +0200)
The functions katze_property_proxy and katze_propery_label
can intelligently create widgets that represent properties
of a particular object. This allows for building up a
configuration interface with few to no code dealing with
specific settings.

katze/katze-utils.c
katze/katze-utils.h

index 620a5d0166be133982a13ed47604f090db263421..ee8d41fd6e0490e3729d49d97bc2ab27a14a8617 100644 (file)
@@ -1,5 +1,5 @@
 /*
- Copyright (C) 2007 Christian Dywan <christian@twotoasts.de>
+ Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
 
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
 */
 
 #include "katze-utils.h"
+
+#include <glib/gi18n.h>
+
+static void
+proxy_toggle_button_toggled_cb (GtkToggleButton* button, GObject* object)
+{
+    gboolean toggled = gtk_toggle_button_get_active (button);
+    const gchar* property = g_object_get_data (G_OBJECT (button), "property");
+    g_object_set (object, property, toggled, NULL);
+}
+
+static void
+proxy_file_file_set_cb (GtkFileChooser* button,
+                        GObject*        object)
+{
+    const gchar* file = gtk_file_chooser_get_filename (button);
+    const gchar* property = g_object_get_data (G_OBJECT (button), "property");
+    g_object_set (object, property, file, NULL);
+}
+
+static void
+proxy_folder_file_set_cb (GtkFileChooser* button,
+                          GObject*        object)
+{
+    const gchar* file = gtk_file_chooser_get_current_folder (button);
+    const gchar* property = g_object_get_data (G_OBJECT (button), "property");
+    g_object_set (object, property, file, NULL);
+}
+
+static void
+proxy_uri_file_set_cb (GtkFileChooser* button,
+                       GObject*        object)
+{
+    const gchar* file = gtk_file_chooser_get_uri (button);
+    const gchar* property = g_object_get_data (G_OBJECT (button), "property");
+    g_object_set (object, property, file, NULL);
+}
+
+static gboolean
+proxy_entry_focus_out_event_cb (GtkEntry*      entry,
+                                GdkEventFocus* event,
+                                GObject*       object)
+{
+    const gchar* text = gtk_entry_get_text (entry);
+    const gchar* property = g_object_get_data (G_OBJECT (entry), "property");
+    g_object_set (object, property, text, NULL);
+    return FALSE;
+}
+
+static gboolean
+proxy_spin_button_changed_cb (GtkSpinButton* button, GObject* object)
+{
+    gdouble value = gtk_spin_button_get_value (button);
+    const gchar* property = g_object_get_data (G_OBJECT (button), "property");
+    g_object_set (object, property, value, NULL);
+    return FALSE;
+}
+
+static gchar*
+proxy_combo_box_changed_cb (GtkComboBox* button, GObject* object)
+{
+    gint value = gtk_combo_box_get_active (button);
+    const gchar* property = g_object_get_data (G_OBJECT (button), "property");
+    g_object_set (object, property, value, NULL);
+    return FALSE;
+}
+
+/**
+ * katze_property_proxy:
+ * @object: a #GObject
+ * @property: the name of a property
+ * @hint: a special hint
+ *
+ * Create a widget of an appropriate type to represent the specified
+ * object's property. If the property is writable changes of the value
+ * through the widget will be reflected in the value of the property.
+ *
+ * Supported values for @hint are as follows:
+ *     "blurb": the blurb of the property will be used to provide a kind
+ *         of label, instead of the name.
+ *     "file": the widget created will be particularly suitable for
+ *         choosing an existing filename.
+ *     "folder": the widget created will be particularly suitable for
+ *         choosing an existing folder.
+ *     "uri": the widget created will be particularly suitable for
+ *         choosing an existing filename, encoded as an URI.
+ *
+ * Any other values for @hint are silently ignored.
+ *
+ * Return value: a new widget
+ **/
+GtkWidget*
+katze_property_proxy (gpointer     object,
+                      const gchar* property,
+                      const gchar* hint)
+{
+    g_return_val_if_fail (G_IS_OBJECT (object), NULL);
+    GObjectClass* class = G_OBJECT_GET_CLASS (object);
+    GParamSpec* pspec = g_object_class_find_property (class, property);
+    if (!pspec)
+    {
+        g_warning ("Property '%s' is invalid for %s",
+                   property, G_OBJECT_CLASS_NAME (class));
+        return gtk_label_new (property);
+    }
+    GType type = G_PARAM_SPEC_TYPE (pspec);
+    const gchar* nick = g_param_spec_get_nick (pspec);
+    const gchar* _hint = g_intern_string (hint);
+    if (_hint == g_intern_string ("blurb"))
+        nick = g_param_spec_get_blurb (pspec);
+    GtkWidget* widget;
+    const gchar* string;
+    if (type == G_TYPE_PARAM_BOOLEAN)
+    {
+        widget = gtk_check_button_new_with_label (nick);
+        gboolean toggled;
+        g_object_get (object, property, &toggled, NULL);
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), toggled);
+        g_signal_connect (widget, "toggled",
+                          G_CALLBACK (proxy_toggle_button_toggled_cb), object);
+    }
+    else if (type == G_TYPE_PARAM_STRING && _hint == g_intern_string ("file"))
+    {
+        widget = gtk_file_chooser_button_new (_("Choose file"),
+            GTK_FILE_CHOOSER_ACTION_OPEN);
+        g_object_get (object, property, &string, NULL);
+        if (!string)
+            string = G_PARAM_SPEC_STRING (pspec)->default_value;
+        gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget),
+                                       string ? string : "");
+        g_signal_connect (widget, "file-set",
+                          G_CALLBACK (proxy_file_file_set_cb), object);
+    }
+    else if (type == G_TYPE_PARAM_STRING && _hint == g_intern_string ("folder"))
+    {
+        widget = gtk_file_chooser_button_new (_("Choose folder"),
+            GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
+        g_object_get (object, property, &string, NULL);
+        if (!string)
+            string = G_PARAM_SPEC_STRING (pspec)->default_value;
+        gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (widget),
+                                             string ? string : "");
+        g_signal_connect (widget, "file-set",
+                          G_CALLBACK (proxy_folder_file_set_cb), object);
+    }
+    else if (type == G_TYPE_PARAM_STRING && _hint == g_intern_string ("uri"))
+    {
+        widget = gtk_file_chooser_button_new (_("Choose file"),
+            GTK_FILE_CHOOSER_ACTION_OPEN);
+        g_object_get (object, property, &string, NULL);
+        if (!string)
+            string = G_PARAM_SPEC_STRING (pspec)->default_value;
+        gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (widget),
+                                  string ? string : "");
+        g_signal_connect (widget, "file-set",
+                          G_CALLBACK (proxy_uri_file_set_cb), object);
+    }
+    else if (type == G_TYPE_PARAM_STRING)
+    {
+        widget = gtk_entry_new ();
+        g_object_get (object, property, &string, NULL);
+        if (!string)
+            string = G_PARAM_SPEC_STRING (pspec)->default_value;
+        gtk_entry_set_text (GTK_ENTRY (widget), string ? string : "");
+        g_signal_connect (widget, "focus-out-event",
+                          G_CALLBACK (proxy_entry_focus_out_event_cb), object);
+    }
+    else if (type == G_TYPE_PARAM_INT)
+    {
+        widget = gtk_spin_button_new_with_range (
+            G_PARAM_SPEC_INT (pspec)->minimum,
+            G_PARAM_SPEC_INT (pspec)->maximum, 1);
+        gdouble value;
+        g_object_get (object, property, &value, NULL);
+        gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), value);
+        g_signal_connect (widget, "changed",
+                          G_CALLBACK (proxy_spin_button_changed_cb), object);
+    }
+    else if (type == G_TYPE_PARAM_ENUM)
+    {
+        GEnumClass* enum_class = G_ENUM_CLASS (
+            g_type_class_ref (pspec->value_type));
+        widget = gtk_combo_box_new_text ();
+        gint i = 0;
+        while (i < enum_class->n_values)
+        {
+            const gchar* label = enum_class->values[i].value_nick;
+            gtk_combo_box_append_text (GTK_COMBO_BOX (widget), label);
+            i++;
+        }
+        gint value;
+        g_object_get (object, property, &value, NULL);
+        gtk_combo_box_set_active (GTK_COMBO_BOX (widget), value);
+        g_signal_connect (widget, "changed",
+                          G_CALLBACK (proxy_combo_box_changed_cb), object);
+        g_type_class_unref (enum_class);
+    }
+    else
+        widget = gtk_label_new (nick);
+
+    gtk_widget_set_sensitive (widget, pspec->flags & G_PARAM_WRITABLE);
+
+    g_object_set_data (G_OBJECT (widget), "property", (gchar*)property);
+
+    return widget;
+}
+
+/**
+ * katze_property_label:
+ * @object: a #GObject
+ * @property: the name of a property
+ *
+ * Create a label widget displaying the name of the specified object's property.
+ *
+ * Return value: a new label widget
+ **/
+GtkWidget*
+katze_property_label (gpointer     object,
+                      const gchar* property)
+{
+    g_return_val_if_fail (G_IS_OBJECT (object), NULL);
+    GObjectClass* class = G_OBJECT_GET_CLASS (object);
+    GParamSpec* pspec = g_object_class_find_property (class, property);
+    if (!pspec)
+    {
+        g_warning ("Property '%s' is invalid for %s",
+                   property, G_OBJECT_CLASS_NAME (class));
+        return gtk_label_new (property);
+    }
+    const gchar* nick = g_param_spec_get_nick (pspec);
+    GtkWidget* widget = gtk_label_new (nick);
+
+    return widget;
+}
index 45dda897a0c076071ee9ea8ae3b5bd62438ed91e..c42267d6e8e47cf081fa0679ae0032ce95569f66 100644 (file)
@@ -1,5 +1,5 @@
 /*
- Copyright (C) 2007 Christian Dywan <christian@twotoasts.de>
+ Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
 
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
@@ -12,7 +12,7 @@
 #ifndef __KATZE_UTILS_H__
 #define __KATZE_UTILS_H__
 
-#include <glib-object.h>
+#include <gtk/gtk.h>
 
 G_BEGIN_DECLS
 
@@ -45,6 +45,15 @@ G_BEGIN_DECLS
         lvalue = rvalue; \
     }
 
+GtkWidget*
+katze_property_proxy                (gpointer     object,
+                                     const gchar* property,
+                                     const gchar* hint);
+
+GtkWidget*
+katze_property_label                (gpointer     object,
+                                     const gchar* property);
+
 G_END_DECLS
 
 #endif /* __KATZE_UTILS_H__ */