[glade/gbinding] Add support for setting transformation functions from "Bind to source..."
- From: Denis Washington <denisw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glade/gbinding] Add support for setting transformation functions from "Bind to source..."
- Date: Mon, 1 Aug 2011 11:04:39 +0000 (UTC)
commit 03aa243b282b94c6eb62ed080ede14ba197ac360
Author: Denis Washington <denisw src gnome org>
Date: Mon Aug 1 13:00:48 2011 +0200
Add support for setting transformation functions from "Bind to source..."
There is now a new checkbutton in the "Bind to source..." dialog to set
a transformation for a binding. Because we don't have the transformation
function and the source and target properties might have different types,
there is no in-workspace preview of the binding; instead, a property with
a transformed binding is shown as having its default value.
gladeui/glade-command.c | 16 ++++-
gladeui/glade-command.h | 3 +-
gladeui/glade-editor-property.c | 174 ++++++++++++++++++++++++++++++++++-----
gladeui/glade-editor-property.h | 3 +-
gladeui/glade-popup.c | 11 ++-
gladeui/glade-property.c | 47 ++++++++---
6 files changed, 217 insertions(+), 37 deletions(-)
---
diff --git a/gladeui/glade-command.c b/gladeui/glade-command.c
index 9bb4685..b1e4c3c 100644
--- a/gladeui/glade-command.c
+++ b/gladeui/glade-command.c
@@ -799,6 +799,8 @@ typedef struct
GladeProperty *target;
GladeProperty *new_source;
GladeProperty *old_source;
+ gchar *old_transform;
+ gchar *new_transform;
GValue old_value;
gboolean undo;
} GladeCommandBindProperty;
@@ -827,14 +829,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);
if (!source && G_IS_VALUE (&bcmd->old_value))
glade_property_set_value (target, &bcmd->old_value);
@@ -846,6 +851,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,7 +889,9 @@ glade_command_bind_property_collapse (GladeCommand * this_cmd,
}
void
-glade_command_bind_property (GladeProperty * target, GladeProperty * source)
+glade_command_bind_property (GladeProperty * target,
+ GladeProperty * source,
+ const gchar * transform_func)
{
GladeCommandBindProperty *me;
GladeCommand *cmd;
@@ -892,6 +904,8 @@ glade_command_bind_property (GladeProperty * target, GladeProperty * source)
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);
diff --git a/gladeui/glade-command.h b/gladeui/glade-command.h
index 4e1c26d..897f8b8 100644
--- a/gladeui/glade-command.h
+++ b/gladeui/glade-command.h
@@ -96,7 +96,8 @@ void glade_command_set_properties_list (GladeProject *project,
GList *props); /* list of GCSetPropData */
void glade_command_bind_property (GladeProperty *target,
- GladeProperty *source);
+ GladeProperty *source,
+ const gchar *transform_func);
/************************** name ******************************/
diff --git a/gladeui/glade-editor-property.c b/gladeui/glade-editor-property.c
index 6fc340e..7e92fe5 100644
--- a/gladeui/glade-editor-property.c
+++ b/gladeui/glade-editor-property.c
@@ -175,8 +175,7 @@ GladePropertyClass *
glade_editor_property_get_pclass (GladeEditorProperty *eprop)
{
g_return_val_if_fail (GLADE_IS_EDITOR_PROPERTY (eprop), NULL);
-
- return eprop->priv->klass;
+ return eprop->priv->klass;
}
GladeProperty *
@@ -201,6 +200,7 @@ typedef struct {
GtkWidget *object_view;
GtkWidget *property_view;
gboolean transform_func_enabled;
+ gboolean transform_func_valid;
} GladeBindDialog;
enum {
@@ -269,11 +269,37 @@ 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);
}
}
+static void
+glade_bind_dialog_update_buttons (GladeBindDialog *dialog,
+ GtkTreeSelection *prop_selection)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ if ((!dialog->transform_func_enabled || dialog->transform_func_valid) &&
+ gtk_tree_selection_get_selected (prop_selection, &model, &iter))
+ {
+ gboolean selectable;
+
+ gtk_tree_model_get (model, &iter,
+ PROPERTY_COLUMN_PROP_SELECTABLE, &selectable,
+ -1);
+
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog->widget),
+ GTK_RESPONSE_OK, selectable);
+ }
+ else
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog->widget),
+ GTK_RESPONSE_OK, FALSE);
+
+}
+
static int
property_sort_func (GtkTreeModel *model,
GtkTreeIter *a,
@@ -375,30 +401,76 @@ glade_bind_dialog_setup_property_view (GladeBindDialog *dialog)
while (gtk_tree_model_iter_next (model, &iter));
}
+ glade_bind_dialog_update_buttons (dialog, selection);
return view_widget;
}
static void
-glade_bind_dialog_update_buttons (GladeBindDialog *dialog,
- GtkTreeSelection *prop_selection)
+glade_bind_dialog_update_property_selectability (GladeBindDialog *dialog,
+ GtkWidget *checkbutton)
{
- GtkTreeModel *model;
+ gboolean active;
+ GtkTreeView *prop_view;
+ GtkTreeModel *prop_model;
+ GtkTreeSelection *prop_selection;
GtkTreeIter iter;
-
- if (gtk_tree_selection_get_selected (prop_selection, &model, &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
{
- gboolean selectable;
+ GladeProperty *prop;
+ GladePropertyClass *pclass;
+ GType type;
- gtk_tree_model_get (model, &iter,
- PROPERTY_COLUMN_PROP_SELECTABLE, &selectable,
- -1);
-
- gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog->widget),
- GTK_RESPONSE_OK, selectable);
+ 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);
}
- else
- gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog->widget),
- GTK_RESPONSE_OK, FALSE);
+ 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);
}
/**
@@ -413,7 +485,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;
@@ -423,6 +496,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);
@@ -503,6 +580,32 @@ glade_editor_property_show_bind_dialog (GladeProject * project,
prop_view = dialog->property_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),
@@ -511,6 +614,23 @@ glade_editor_property_show_bind_dialog (GladeProject * project,
"changed",
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));
@@ -519,11 +639,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 cddcdcb..82b3564 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 84e713f..860f62f 100644
--- a/gladeui/glade-property.c
+++ b/gladeui/glade-property.c
@@ -1842,11 +1842,13 @@ void
glade_property_set_binding_source (GladeProperty *property,
GladeProperty *binding_source)
{
+ GladeProperty *old_source;
GValue source_val = {0};
g_return_if_fail (GLADE_IS_PROPERTY (property));
g_return_if_fail (!binding_source || GLADE_IS_PROPERTY (binding_source));
+ old_source = glade_property_get_binding_source (property);
glade_property_remove_binding_source (property);
property->priv->binding_source = binding_source;
@@ -1860,11 +1862,7 @@ glade_property_set_binding_source (GladeProperty *property,
(GWeakNotify) glade_property_binding_source_weak_notify_cb,
property);
- property->priv->binding_handler =
- g_signal_connect (binding_source, "value-changed",
- G_CALLBACK (glade_property_binding_source_value_changed_cb),
- property);
-
+ /* To be called when the binding source widget is deleted */
closure =
g_cclosure_new (G_CALLBACK (glade_property_binding_source_widget_cb),
G_OBJECT (property), NULL);
@@ -1883,9 +1881,23 @@ glade_property_set_binding_source (GladeProperty *property,
property->priv->binding_source_valid = TRUE;
- /* Synchronize the source and target property values once */
- glade_property_get_value (binding_source, &source_val);
- glade_property_set_value (property, &source_val);
+ /* Synchronize the source and target property values if there
+ * is no transformation function; if there is, the best thing we
+ * can do is to reset the target property to the default value
+ * (the source and target property types might not be compatible)
+ */
+ if (glade_property_get_binding_transform_func (property))
+ glade_property_reset (property);
+ else
+ {
+ property->priv->binding_handler =
+ g_signal_connect (binding_source, "value-changed",
+ G_CALLBACK (glade_property_binding_source_value_changed_cb),
+ property);
+
+ glade_property_get_value (binding_source, &source_val);
+ glade_property_set_value (property, &source_val);
+ }
}
else
{
@@ -1894,7 +1906,9 @@ glade_property_set_binding_source (GladeProperty *property,
property->priv->binding_widget_add_handler = 0;
}
- g_object_notify_by_pspec (G_OBJECT (property), properties[PROP_BINDING_SOURCE]);
+ if (binding_source != old_source)
+ g_object_notify_by_pspec (G_OBJECT (property),
+ properties[PROP_BINDING_SOURCE]);
}
const gchar *
@@ -1902,7 +1916,10 @@ glade_property_get_binding_transform_func (GladeProperty *property)
{
g_return_val_if_fail (GLADE_IS_PROPERTY (property), NULL);
- return property->priv->binding_transform_func;
+ if (property->priv->binding_source_valid)
+ return property->priv->binding_transform_func;
+ else
+ return NULL;
}
void
@@ -1912,8 +1929,16 @@ glade_property_set_binding_transform_func (GladeProperty *property,
g_return_if_fail (GLADE_IS_PROPERTY (property));
g_free (property->priv->binding_transform_func);
- property->priv->binding_transform_func = g_strdup (transform_func);
+ if (transform_func)
+ property->priv->binding_transform_func = g_strdup (transform_func);
+ else
+ property->priv->binding_transform_func = NULL;
+ /* Call glade_property_set_binding_source() to adjust to the new
+ * transformation function setting */
+ glade_property_set_binding_source (property,
+ glade_property_get_binding_source (property));
+
g_object_notify_by_pspec (G_OBJECT (property),
properties[PROP_BINDING_TRANSFORM_FUNC]);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]