[glade/gbinding-transform] Transformation function support for the "gbinding" branch
- From: Denis Washington <denisw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glade/gbinding-transform] Transformation function support for the "gbinding" branch
- Date: Fri, 19 Aug 2011 17:25:46 +0000 (UTC)
commit b0ff85ee143784a696a17c65166b24fa84e8d4d0
Author: Denis Washington <denisw src gnome org>
Date: Fri Aug 19 19:24:10 2011 +0200
Transformation function support for the "gbinding" branch
Moved here from the original "gbinding" branch.
gladeui/glade-command.c | 54 ++++++++++++---
gladeui/glade-command.h | 5 +-
gladeui/glade-editor-property.c | 139 ++++++++++++++++++++++++++++++++++++++-
gladeui/glade-editor-property.h | 3 +-
gladeui/glade-popup.c | 11 ++-
gladeui/glade-property.c | 73 ++++++++++++++++++++-
gladeui/glade-property.h | 5 ++
7 files changed, 269 insertions(+), 21 deletions(-)
---
diff --git a/gladeui/glade-command.c b/gladeui/glade-command.c
index e63184c..3ca2667 100644
--- a/gladeui/glade-command.c
+++ b/gladeui/glade-command.c
@@ -747,8 +747,9 @@ glade_command_set_properties (GladeProperty * property,
for (t = glade_property_get_binding_targets (property); t; t = t->next)
{
target = t->data;
- list = glade_command_add_to_set_properties_list (list, target,
- old_value, new_value);
+ if (!glade_property_get_binding_transform_func (target))
+ list = glade_command_add_to_set_properties_list (list, target,
+ old_value, new_value);
}
va_start (vl, new_value);
@@ -766,9 +767,11 @@ glade_command_set_properties (GladeProperty * property,
for (t = glade_property_get_binding_targets (prop); t; t = t->next)
{
+ printf ("set target\n");
target = t->data;
- list = glade_command_add_to_set_properties_list (list, target,
- ovalue, nvalue);
+ if (!glade_property_get_binding_transform_func (target))
+ list = glade_command_add_to_set_properties_list (list, target,
+ ovalue, nvalue);
}
}
@@ -820,6 +823,8 @@ typedef struct
GladeProperty *target;
GladeProperty *new_source;
GladeProperty *old_source;
+ gchar *old_transform;
+ gchar *new_transform;
GValue old_value;
gboolean undo;
} GladeCommandBindProperty;
@@ -848,14 +853,17 @@ glade_command_bind_property_execute (GladeCommand * cmd)
{
GladeCommandBindProperty *bcmd;
GladeProperty *target, *source;
+ gchar *transform_func;
g_return_val_if_fail (GLADE_IS_COMMAND_BIND_PROPERTY (cmd), TRUE);
bcmd = GLADE_COMMAND_BIND_PROPERTY (cmd);
target = bcmd->target;
source = bcmd->undo ? bcmd->old_source : bcmd->new_source;
+ transform_func = bcmd->undo ? bcmd->old_transform : bcmd->new_transform;
glade_property_set_binding_source (target, source);
+ glade_property_set_binding_transform_func (target, transform_func);
bcmd->undo = !bcmd->undo;
return TRUE;
@@ -864,6 +872,11 @@ glade_command_bind_property_execute (GladeCommand * cmd)
static void
glade_command_bind_property_finalize (GObject * obj)
{
+ GladeCommandBindProperty *cmd = GLADE_COMMAND_BIND_PROPERTY (obj);
+
+ g_free (cmd->old_transform);
+ g_free (cmd->new_transform);
+
glade_command_finalize (obj);
}
@@ -879,8 +892,9 @@ glade_command_bind_property_unifies (GladeCommand * this_cmd,
cmd1 = GLADE_COMMAND_BIND_PROPERTY (this_cmd);
cmd2 = GLADE_COMMAND_BIND_PROPERTY (other_cmd);
- return (cmd1->target == cmd2->target &&
- cmd1->new_source == cmd2->new_source);
+ return (cmd1->target == cmd2->target
+ && cmd1->new_source == cmd2->new_source
+ && cmd1->new_transform == cmd2->new_transform);
}
return FALSE;
@@ -898,7 +912,8 @@ glade_command_bind_property_collapse (GladeCommand * this_cmd,
void
glade_command_bind_property (GladeProperty * target,
- GladeProperty * source)
+ GladeProperty * source,
+ const gchar * transform_func)
{
GladeCommandBindProperty *me;
GladeCommand *cmd;
@@ -911,6 +926,8 @@ glade_command_bind_property (GladeProperty * target,
me->target = target;
me->old_source = glade_property_get_binding_source (target);
me->new_source = source;
+ me->old_transform = g_strdup (glade_property_get_binding_transform_func (target));
+ me->new_transform = g_strdup (transform_func);
if (!me->old_source)
glade_property_get_value (target, &me->old_value);
@@ -927,9 +944,26 @@ glade_command_bind_property (GladeProperty * target,
glade_widget_get_name (glade_property_get_widget (target)));
- /* Adjust the target's value to match the source */
+ /* Adjust the target's value to match the source (or reset it if a
+ * transformation function is involved, in which case we cannot know
+ * how the target value looks like)
+ */
if (source)
- glade_command_set_property_value (target, glade_property_inline_value (source));
+ {
+ const GValue *value;
+
+ if (transform_func)
+ {
+ GladePropertyClass *pclass;
+
+ pclass = glade_property_get_class (source);
+ value = glade_property_class_get_default (pclass);
+ }
+ else
+ value = glade_property_inline_value (source);
+
+ glade_command_set_property_value (target, value);
+ }
glade_command_check_group (GLADE_COMMAND (me));
@@ -1327,7 +1361,7 @@ glade_command_delete_binding_refs (GladeWidget * widget)
for (t = targets; t; t = t->next)
{
GladeProperty *target = t->data;
- glade_command_bind_property (target, NULL);
+ glade_command_bind_property (target, NULL, NULL);
}
g_list_free (targets);
diff --git a/gladeui/glade-command.h b/gladeui/glade-command.h
index 39bf662..897f8b8 100644
--- a/gladeui/glade-command.h
+++ b/gladeui/glade-command.h
@@ -95,8 +95,9 @@ void glade_command_set_properties (GladeProperty *property,
void glade_command_set_properties_list (GladeProject *project,
GList *props); /* list of GCSetPropData */
-void glade_command_bind_property (GladeProperty *target,
- GladeProperty *source);
+void glade_command_bind_property (GladeProperty *target,
+ GladeProperty *source,
+ const gchar *transform_func);
/************************** name ******************************/
diff --git a/gladeui/glade-editor-property.c b/gladeui/glade-editor-property.c
index a6a4055..779f894 100644
--- a/gladeui/glade-editor-property.c
+++ b/gladeui/glade-editor-property.c
@@ -184,6 +184,8 @@ typedef struct {
GtkWidget *widget;
GtkWidget *object_view;
GtkWidget *property_view;
+ gboolean transform_func_enabled;
+ gboolean transform_func_valid;
} GladeBindDialog;
enum {
@@ -254,6 +256,7 @@ glade_bind_dialog_update_property_view (GladeBindDialog *dialog,
PROPERTY_COLUMN_PROP_NAME,
glade_property_class_get_name (pclass),
PROPERTY_COLUMN_PROP_SELECTABLE,
+ dialog->transform_func_enabled ||
g_type_is_a (type, target_type),
-1);
}
@@ -266,7 +269,8 @@ glade_bind_dialog_update_buttons (GladeBindDialog *dialog,
GtkTreeModel *model;
GtkTreeIter iter;
- if (gtk_tree_selection_get_selected (prop_selection, &model, &iter))
+ if (gtk_tree_selection_get_selected (prop_selection, &model, &iter) &&
+ (!dialog->transform_func_enabled || dialog->transform_func_valid))
{
gboolean selectable;
@@ -388,6 +392,74 @@ glade_bind_dialog_setup_property_view (GladeBindDialog *dialog)
return view_widget;
}
+static void
+glade_bind_dialog_update_property_selectability (GladeBindDialog *dialog,
+ GtkWidget *checkbutton)
+{
+ gboolean active;
+ GtkTreeView *prop_view;
+ GtkTreeModel *prop_model;
+ GtkTreeSelection *prop_selection;
+ GtkTreeIter iter;
+ GladePropertyClass *target_pclass ;
+ GType target_type;
+
+ active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbutton));
+ dialog->transform_func_enabled = active;
+
+ prop_view = GTK_TREE_VIEW (dialog->property_view);
+ prop_model = gtk_tree_view_get_model (prop_view);
+
+ target_pclass = glade_property_get_class (dialog->target);
+ target_type = G_PARAM_SPEC_TYPE (glade_property_class_get_pspec (target_pclass));
+
+ /* Temporarily disable sorting, otherwise the tree model iteration
+ * code below might get confused */
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (prop_model),
+ GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID,
+ GTK_SORT_ASCENDING);
+
+ gtk_tree_model_get_iter_first (prop_model, &iter);
+ do
+ {
+ GladeProperty *prop;
+ GladePropertyClass *pclass;
+ GType type;
+
+ gtk_tree_model_get (prop_model, &iter,
+ PROPERTY_COLUMN_PROP, &prop, -1);
+
+ pclass = glade_property_get_class (prop);
+ type = G_PARAM_SPEC_TYPE (glade_property_class_get_pspec (pclass));
+
+ gtk_list_store_set (GTK_LIST_STORE (prop_model), &iter,
+ PROPERTY_COLUMN_PROP_SELECTABLE,
+ dialog->transform_func_enabled ||
+ g_type_is_a (type, target_type), -1);
+ }
+ while (gtk_tree_model_iter_next (prop_model, &iter));
+
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (prop_model),
+ GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
+ GTK_SORT_ASCENDING);
+
+ prop_selection = gtk_tree_view_get_selection (prop_view);
+ glade_bind_dialog_update_buttons (dialog, prop_selection);
+}
+
+static void
+glade_bind_dialog_transform_func_changed (GladeBindDialog *dialog,
+ GParamSpec *pspec,
+ GtkEntry *entry)
+{
+ GtkTreeSelection *selection;
+
+ dialog->transform_func_valid = (strlen (gtk_entry_get_text (entry)) > 0);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->property_view));
+ glade_bind_dialog_update_buttons (dialog, selection);
+}
+
/*
* Forward-declared GladeEditorPropertyObjectClass functions needed
* by glade_editor_property_show_bind_dialog()
@@ -421,7 +493,8 @@ gboolean
glade_editor_property_show_bind_dialog (GladeProject * project,
GtkWidget * parent,
GladeProperty *target,
- GladeProperty **source)
+ GladeProperty **source,
+ gchar **transform_func)
{
GladeBindDialog *dialog;
GtkWidget *content_area, *action_area;
@@ -431,6 +504,10 @@ glade_editor_property_show_bind_dialog (GladeProject * project,
GtkWidget *obj_view, *prop_view;
GladeProperty *current_source;
GList *selected = NULL;
+ GtkWidget *frame, *frame_label;
+ GtkWidget *trans_vbox, *trans_hbox;
+ GtkWidget *trans_check, *trans_label, *trans_entry;
+ const gchar *current_transform;
gint res;
g_return_val_if_fail (GLADE_IS_PROJECT (project), FALSE);
@@ -513,6 +590,32 @@ glade_editor_property_show_bind_dialog (GladeProject * project,
gtk_label_set_mnemonic_widget (GTK_LABEL (prop_label), prop_view);
gtk_container_add (GTK_CONTAINER (prop_sw), prop_view);
+ frame = gtk_frame_new (_("<b>Transformation Function</b>"));
+ frame_label = GTK_WIDGET (gtk_frame_get_label_widget (GTK_FRAME (frame)));
+ gtk_label_set_use_markup (GTK_LABEL (frame_label), TRUE);
+ gtk_box_pack_start (GTK_BOX (content_area), frame, FALSE, FALSE, 0);
+
+ trans_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+ gtk_widget_set_margin_top (trans_vbox, 6);
+ gtk_widget_set_margin_left (trans_vbox, 12);
+ gtk_container_add (GTK_CONTAINER (frame), trans_vbox);
+
+ trans_check = gtk_check_button_new_with_mnemonic (_("_Connect a function for "
+ "source-to-target value "
+ "transformation"));
+ gtk_box_pack_start (GTK_BOX (trans_vbox), trans_check, FALSE, FALSE, 0);
+
+ trans_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+ gtk_widget_set_margin_left (trans_hbox, 12);
+ gtk_box_pack_start (GTK_BOX (trans_vbox), trans_hbox, FALSE, FALSE, 0);
+
+ trans_label = gtk_label_new_with_mnemonic (_("_Transformation function:"));
+ gtk_box_pack_start (GTK_BOX (trans_hbox), trans_label, FALSE, FALSE, 0);
+
+ trans_entry = gtk_entry_new ();
+ gtk_label_set_mnemonic_widget (GTK_LABEL (trans_label), trans_entry);
+ gtk_box_pack_start (GTK_BOX (trans_hbox), trans_entry, TRUE, TRUE, 0);
+
g_signal_connect_swapped (gtk_tree_view_get_selection (GTK_TREE_VIEW (obj_view)),
"changed",
G_CALLBACK (glade_bind_dialog_update_property_view),
@@ -522,6 +625,23 @@ glade_editor_property_show_bind_dialog (GladeProject * project,
G_CALLBACK (glade_bind_dialog_update_buttons),
dialog);
+ g_object_bind_property (trans_check, "active",
+ trans_hbox, "sensitive",
+ G_BINDING_SYNC_CREATE);
+ g_signal_connect_swapped (trans_check, "toggled",
+ G_CALLBACK (glade_bind_dialog_update_property_selectability),
+ dialog);
+ g_signal_connect_swapped (trans_entry, "notify::text",
+ G_CALLBACK (glade_bind_dialog_transform_func_changed),
+ dialog);
+
+ current_transform = glade_property_get_binding_transform_func (target);
+ if (current_transform)
+ {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (trans_check), TRUE);
+ gtk_entry_set_text (GTK_ENTRY (trans_entry), current_transform);
+ }
+
gtk_widget_show_all (content_area);
res = gtk_dialog_run (GTK_DIALOG (dialog->widget));
if (res == GTK_RESPONSE_OK)
@@ -529,10 +649,25 @@ glade_editor_property_show_bind_dialog (GladeProject * project,
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreeIter iter;
+ gchar *trans_text;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prop_view));
gtk_tree_selection_get_selected (selection, &model, &iter);
gtk_tree_model_get (model, &iter, PROPERTY_COLUMN_PROP, source, -1);
+
+ if (dialog->transform_func_enabled)
+ {
+ trans_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (trans_entry)));
+ if (strlen (g_strstrip (trans_text)) == 0)
+ {
+ g_free (trans_text);
+ *transform_func = NULL;
+ }
+ else
+ *transform_func = g_strdup (trans_text);
+ }
+ else
+ *transform_func = NULL;
}
gtk_widget_destroy (dialog->widget);
diff --git a/gladeui/glade-editor-property.h b/gladeui/glade-editor-property.h
index b63e840..af052ee 100644
--- a/gladeui/glade-editor-property.h
+++ b/gladeui/glade-editor-property.h
@@ -135,7 +135,8 @@ gboolean glade_editor_property_show_object_dialog (GladeProject
gboolean glade_editor_property_show_bind_dialog (GladeProject *project,
GtkWidget *parent,
GladeProperty *target,
- GladeProperty **source);
+ GladeProperty **source,
+ gchar **transform_func);
/* Generic eprops */
#define GLADE_TYPE_EPROP_NUMERIC (glade_eprop_numeric_get_type())
diff --git a/gladeui/glade-popup.c b/gladeui/glade-popup.c
index b8e974a..16c0b5e 100644
--- a/gladeui/glade-popup.c
+++ b/gladeui/glade-popup.c
@@ -623,17 +623,22 @@ glade_popup_bind_property_cb (GtkMenuItem * item, GladeProperty * property)
GladeWidget *widget = glade_property_get_widget (property);
GladeProject *project = glade_widget_get_project (widget);
GladeProperty *source;
+ gchar *transform_func;
GtkWidget *parent =
gtk_widget_get_toplevel (GTK_WIDGET (glade_widget_get_object (widget)));
- if (glade_editor_property_show_bind_dialog (project, parent, property, &source))
- glade_command_bind_property (property, source);
+ if (glade_editor_property_show_bind_dialog (project, parent, property,
+ &source, &transform_func))
+ {
+ glade_command_bind_property (property, source, transform_func);
+ g_free (transform_func);
+ }
}
static void
glade_popup_unbind_property_cb (GtkMenuItem * item, GladeProperty * property)
{
- glade_command_bind_property (property, NULL);
+ glade_command_bind_property (property, NULL, NULL);
}
static void
diff --git a/gladeui/glade-property.c b/gladeui/glade-property.c
index df5e621..df2916b 100644
--- a/gladeui/glade-property.c
+++ b/gladeui/glade-property.c
@@ -111,6 +111,10 @@ struct _GladePropertyPrivate {
GList *binding_targets; /* The properties that this property is the binding
source of */
+ gchar *binding_transform_func; /* the transformation function for
+ * the property's binding
+ */
+
/* For resolving a binding source read from a project file */
gchar *binding_source_object_name;
gchar *binding_source_property_name;
@@ -138,6 +142,7 @@ enum
PROP_ENABLED,
PROP_SENSITIVE,
PROP_BINDING_SOURCE,
+ PROP_BINDING_TRANSFORM_FUNC,
PROP_I18N_TRANSLATABLE,
PROP_I18N_CONTEXT,
PROP_I18N_COMMENT,
@@ -524,6 +529,10 @@ glade_property_set_real_property (GObject * object,
glade_property_set_binding_source (property,
g_value_get_pointer (value));
break;
+ case PROP_BINDING_TRANSFORM_FUNC:
+ glade_property_set_binding_transform_func (property,
+ g_value_get_string (value));
+ break;
case PROP_I18N_TRANSLATABLE:
glade_property_i18n_set_translatable (property,
g_value_get_boolean (value));
@@ -562,6 +571,10 @@ glade_property_get_real_property (GObject * object,
g_value_set_pointer (value,
glade_property_get_binding_source (property));
break;
+ case PROP_BINDING_TRANSFORM_FUNC:
+ g_value_set_string (value,
+ glade_property_get_binding_transform_func (property));
+ break;
case PROP_I18N_TRANSLATABLE:
g_value_set_boolean (value,
glade_property_i18n_get_translatable (property));
@@ -597,6 +610,8 @@ glade_property_finalize (GObject * object)
g_free (property->priv->binding_source_property_name);
if (property->priv->binding_targets)
g_list_free (property->priv->binding_targets);
+ if (property->priv->binding_transform_func)
+ g_free (property->priv->binding_transform_func);
if (property->priv->i18n_comment)
g_free (property->priv->i18n_comment);
if (property->priv->i18n_context)
@@ -622,6 +637,7 @@ glade_property_init (GladeProperty * property)
property->priv->binding_source_object_name = NULL;
property->priv->binding_source_property_name = NULL;
property->priv->binding_targets = NULL;
+ property->priv->binding_transform_func = NULL;
property->priv->i18n_translatable = TRUE;
property->priv->i18n_comment = NULL;
property->priv->sync_tolerance = 1;
@@ -677,6 +693,15 @@ glade_property_klass_init (GladePropertyKlass * prop_class)
"binding, this is the property it is bound to"),
G_PARAM_READWRITE);
+ properties[PROP_BINDING_TRANSFORM_FUNC] =
+ g_param_spec_string ("binding-transform-func",
+ _("Binding Transform Function"),
+ _("The name of a function that transforms the value "
+ "of the property's binding source before it is "
+ "adopted"),
+ NULL,
+ G_PARAM_READWRITE);
+
properties[PROP_I18N_CONTEXT] =
g_param_spec_string ("i18n-context",
_("Context"),
@@ -1304,6 +1329,17 @@ glade_property_binding_read (GladeXmlNode *node,
if (from && source)
{
+ gchar *transform_func;
+
+ transform_func =
+ glade_xml_get_property_string (node, GLADE_XML_TAG_TRANSFORM_FUNC);
+
+ if (transform_func)
+ {
+ glade_property_set_binding_transform_func (target, transform_func);
+ g_free (transform_func);
+ }
+
target->priv->binding_source_object_name = g_strdup (source);
target->priv->binding_source_property_name = g_strdup (from);
}
@@ -1327,7 +1363,7 @@ glade_property_binding_write (GladeProperty *property,
{
GladeXmlNode *binding_node;
GladeProperty *source_prop;
- const gchar *to, *from, *source;
+ const gchar *to, *from, *source, *transform_func;
GladeWidget *widget;
g_return_if_fail (GLADE_IS_PROPERTY (property));
@@ -1359,6 +1395,12 @@ glade_property_binding_write (GladeProperty *property,
glade_xml_node_set_property_string (binding_node,
GLADE_XML_TAG_SOURCE,
source);
+
+ transform_func = glade_property_get_binding_transform_func (property);
+ if (transform_func)
+ glade_xml_node_set_property_string (binding_node,
+ GLADE_XML_TAG_TRANSFORM_FUNC,
+ transform_func);
}
/**
@@ -1760,8 +1802,10 @@ glade_property_set_binding_source (GladeProperty *property,
g_return_if_fail (glade_property_get_enabled (binding_source));
g_return_if_fail (glade_property_get_sensitive (binding_source));
g_return_if_fail (glade_widget_in_project (source_widget));
- g_return_if_fail (g_type_is_a (G_PARAM_SPEC_TYPE (source_pspec),
- G_PARAM_SPEC_TYPE (prop_pspec)));
+
+ if (property->priv->binding_transform_func)
+ g_return_if_fail (g_type_is_a (G_PARAM_SPEC_TYPE (source_pspec),
+ G_PARAM_SPEC_TYPE (prop_pspec)));
if (!g_list_find (binding_source->priv->binding_targets, property))
binding_source->priv->binding_targets =
@@ -1784,6 +1828,29 @@ glade_property_get_binding_targets (GladeProperty *property)
return property->priv->binding_targets;
}
+const gchar *
+glade_property_get_binding_transform_func (GladeProperty *property)
+{
+ g_return_val_if_fail (GLADE_IS_PROPERTY (property), NULL);
+
+ return property->priv->binding_transform_func;
+}
+
+void
+glade_property_set_binding_transform_func (GladeProperty *property,
+ const gchar *transform_func)
+{
+ g_return_if_fail (GLADE_IS_PROPERTY (property));
+
+ g_free (property->priv->binding_transform_func);
+ property->priv->binding_transform_func = (transform_func)
+ ? g_strdup (transform_func)
+ : NULL;
+
+ g_object_notify_by_pspec (G_OBJECT (property),
+ properties[PROP_BINDING_TRANSFORM_FUNC]);
+}
+
static gint glade_property_su_stack = 0;
void
diff --git a/gladeui/glade-property.h b/gladeui/glade-property.h
index 1eee30b..744771c 100644
--- a/gladeui/glade-property.h
+++ b/gladeui/glade-property.h
@@ -174,6 +174,11 @@ void glade_property_set_binding_source (GladeProperty
GList *glade_property_get_binding_targets (GladeProperty *property);
+const gchar *glade_property_get_binding_transform_func (GladeProperty *property);
+
+void glade_property_set_binding_transform_func (GladeProperty *property,
+ const gchar *transform_func);
+
void glade_property_i18n_set_comment (GladeProperty *property,
const gchar *str);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]