Implement property proxy widget creation.
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.
This commit is contained in:
parent
f11b76b6ef
commit
a9eb81a016
2 changed files with 246 additions and 3 deletions
|
@ -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
|
||||
|
@ -10,3 +10,237 @@
|
|||
*/
|
||||
|
||||
#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;
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
Loading…
Reference in a new issue