mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-25 23:16:14 +01:00
binding: Add G_BINDING_INVERT_BOOLEAN
Since GSettings got the same functionality and flag in commit ca3b7b75b
GBinding should also have the ability to automatically invert a boolean
value without requiring a custom transformation function.
This commit is contained in:
parent
3be3ad61d1
commit
90f7f171e6
@ -124,6 +124,7 @@ g_binding_flags_get_type (void)
|
||||
{ G_BINDING_DEFAULT, "G_BINDING_DEFAULT", "default" },
|
||||
{ G_BINDING_BIDIRECTIONAL, "G_BINDING_BIDIRECTIONAL", "bidirectional" },
|
||||
{ G_BINDING_SYNC_CREATE, "G_BINDING_SYNC_CREATE", "sync-create" },
|
||||
{ G_BINDING_INVERT_BOOLEAN, "G_BINDING_INVERT_BOOLEAN", "invert-boolean" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
GType g_define_type_id =
|
||||
@ -301,21 +302,44 @@ done:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
default_invert_boolean_transform (const GValue *value_a,
|
||||
GValue *value_b)
|
||||
{
|
||||
gboolean value;
|
||||
|
||||
g_assert (G_VALUE_HOLDS_BOOLEAN (value_a));
|
||||
g_assert (G_VALUE_HOLDS_BOOLEAN (value_b));
|
||||
|
||||
value = g_value_get_boolean (value_a);
|
||||
value = !value;
|
||||
|
||||
g_value_set_boolean (value_b, value);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
default_transform_to (GBinding *binding G_GNUC_UNUSED,
|
||||
default_transform_to (GBinding *binding,
|
||||
const GValue *value_a,
|
||||
GValue *value_b,
|
||||
gpointer user_data G_GNUC_UNUSED)
|
||||
{
|
||||
if (binding->flags & G_BINDING_INVERT_BOOLEAN)
|
||||
return default_invert_boolean_transform (value_a, value_b);
|
||||
|
||||
return default_transform (value_a, value_b);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
default_transform_from (GBinding *binding G_GNUC_UNUSED,
|
||||
default_transform_from (GBinding *binding,
|
||||
const GValue *value_a,
|
||||
GValue *value_b,
|
||||
gpointer user_data G_GNUC_UNUSED)
|
||||
{
|
||||
if (binding->flags & G_BINDING_INVERT_BOOLEAN)
|
||||
return default_invert_boolean_transform (value_a, value_b);
|
||||
|
||||
return default_transform (value_a, value_b);
|
||||
}
|
||||
|
||||
@ -809,6 +833,15 @@ g_object_bind_property_full (gpointer source,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* remove the G_BINDING_INVERT_BOOLEAN flag in case we have
|
||||
* custom transformation functions
|
||||
*/
|
||||
if ((flags & G_BINDING_INVERT_BOOLEAN) &&
|
||||
(transform_to != NULL || transform_from != NULL))
|
||||
{
|
||||
flags &= ~G_BINDING_INVERT_BOOLEAN;
|
||||
}
|
||||
|
||||
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (source), source_property);
|
||||
if (pspec == NULL)
|
||||
{
|
||||
@ -838,6 +871,18 @@ g_object_bind_property_full (gpointer source,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((flags & G_BINDING_INVERT_BOOLEAN) &&
|
||||
!(G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_BOOLEAN))
|
||||
{
|
||||
g_warning ("%s: The G_BINDING_INVERT_BOOLEAN flag can only be used "
|
||||
"when binding boolean properties; the source property '%s' "
|
||||
"is of type '%s'",
|
||||
G_STRLOC,
|
||||
source_property,
|
||||
g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (target), target_property);
|
||||
if (pspec == NULL)
|
||||
{
|
||||
@ -867,6 +912,18 @@ g_object_bind_property_full (gpointer source,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((flags & G_BINDING_INVERT_BOOLEAN) &&
|
||||
!(G_PARAM_SPEC_VALUE_TYPE (pspec) == G_TYPE_BOOLEAN))
|
||||
{
|
||||
g_warning ("%s: The G_BINDING_INVERT_BOOLEAN flag can only be used "
|
||||
"when binding boolean properties; the target property '%s' "
|
||||
"is of type '%s'",
|
||||
G_STRLOC,
|
||||
target_property,
|
||||
g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
binding = g_object_new (G_TYPE_BINDING,
|
||||
"source", source,
|
||||
"source-property", source_property,
|
||||
|
@ -72,13 +72,18 @@ typedef gboolean (* GBindingTransformFunc) (GBinding *binding,
|
||||
/**
|
||||
* GBindingFlags:
|
||||
* @G_BINDING_DEFAULT: The default binding; if the source property
|
||||
* changes, the target property is updated with its value
|
||||
* changes, the target property is updated with its value.
|
||||
* @G_BINDING_BIDIRECTIONAL: Bidirectional binding; if either the
|
||||
* property of the source or the property of the target changes,
|
||||
* the other is updated
|
||||
* the other is updated.
|
||||
* @G_BINDING_SYNC_CREATE: Synchronize the values of the source and
|
||||
* target properties when creating the binding; the direction of
|
||||
* the synchronization is always from the source to the target
|
||||
* the synchronization is always from the source to the target.
|
||||
* @G_BINDING_INVERT_BOOLEAN: If the two properties being bound are
|
||||
* booleans, setting one to %TRUE will result in the other being
|
||||
* set to %FALSE and vice versa. This flag will only work for
|
||||
* boolean properties, and cannot be used when passing custom
|
||||
* transformation functions to g_object_bind_property_full().
|
||||
*
|
||||
* Flags to be passed to g_object_bind_property() or
|
||||
* g_object_bind_property_full().
|
||||
@ -91,7 +96,8 @@ typedef enum { /*< prefix=G_BINDING >*/
|
||||
G_BINDING_DEFAULT = 0,
|
||||
|
||||
G_BINDING_BIDIRECTIONAL = 1 << 0,
|
||||
G_BINDING_SYNC_CREATE = 1 << 1
|
||||
G_BINDING_SYNC_CREATE = 1 << 1,
|
||||
G_BINDING_INVERT_BOOLEAN = 1 << 2
|
||||
} GBindingFlags;
|
||||
|
||||
GType g_binding_flags_get_type (void) G_GNUC_CONST;
|
||||
|
@ -8,6 +8,7 @@ typedef struct _BindingSource
|
||||
|
||||
gint foo;
|
||||
gdouble value;
|
||||
gboolean toggle;
|
||||
} BindingSource;
|
||||
|
||||
typedef struct _BindingSourceClass
|
||||
@ -20,8 +21,8 @@ enum
|
||||
PROP_SOURCE_0,
|
||||
|
||||
PROP_SOURCE_FOO,
|
||||
|
||||
PROP_SOURCE_VALUE
|
||||
PROP_SOURCE_VALUE,
|
||||
PROP_SOURCE_TOGGLE
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (BindingSource, binding_source, G_TYPE_OBJECT);
|
||||
@ -44,6 +45,10 @@ binding_source_set_property (GObject *gobject,
|
||||
source->value = g_value_get_double (value);
|
||||
break;
|
||||
|
||||
case PROP_SOURCE_TOGGLE:
|
||||
source->toggle = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
}
|
||||
@ -67,6 +72,10 @@ binding_source_get_property (GObject *gobject,
|
||||
g_value_set_double (value, source->value);
|
||||
break;
|
||||
|
||||
case PROP_SOURCE_TOGGLE:
|
||||
g_value_set_boolean (value, source->toggle);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
}
|
||||
@ -90,6 +99,10 @@ binding_source_class_init (BindingSourceClass *klass)
|
||||
-100.0, 200.0,
|
||||
0.0,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (gobject_class, PROP_SOURCE_TOGGLE,
|
||||
g_param_spec_boolean ("toggle", "Toggle", "Toggle",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -103,6 +116,7 @@ typedef struct _BindingTarget
|
||||
|
||||
gint bar;
|
||||
gdouble value;
|
||||
gboolean toggle;
|
||||
} BindingTarget;
|
||||
|
||||
typedef struct _BindingTargetClass
|
||||
@ -115,8 +129,8 @@ enum
|
||||
PROP_TARGET_0,
|
||||
|
||||
PROP_TARGET_BAR,
|
||||
|
||||
PROP_TARGET_VALUE
|
||||
PROP_TARGET_VALUE,
|
||||
PROP_TARGET_TOGGLE
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (BindingTarget, binding_target, G_TYPE_OBJECT);
|
||||
@ -139,6 +153,10 @@ binding_target_set_property (GObject *gobject,
|
||||
target->value = g_value_get_double (value);
|
||||
break;
|
||||
|
||||
case PROP_TARGET_TOGGLE:
|
||||
target->toggle = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
}
|
||||
@ -162,6 +180,10 @@ binding_target_get_property (GObject *gobject,
|
||||
g_value_set_double (value, target->value);
|
||||
break;
|
||||
|
||||
case PROP_TARGET_TOGGLE:
|
||||
g_value_set_boolean (value, target->toggle);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
}
|
||||
@ -180,11 +202,15 @@ binding_target_class_init (BindingTargetClass *klass)
|
||||
-1, 100,
|
||||
0,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (gobject_class, PROP_SOURCE_VALUE,
|
||||
g_object_class_install_property (gobject_class, PROP_TARGET_VALUE,
|
||||
g_param_spec_double ("value", "Value", "Value",
|
||||
-100.0, 200.0,
|
||||
0.0,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (gobject_class, PROP_TARGET_TOGGLE,
|
||||
g_param_spec_boolean ("toggle", "Toggle", "Toggle",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -469,6 +495,33 @@ binding_sync_create (void)
|
||||
g_object_unref (target);
|
||||
}
|
||||
|
||||
static void
|
||||
binding_invert_boolean (void)
|
||||
{
|
||||
BindingSource *source = g_object_new (binding_source_get_type (),
|
||||
"toggle", TRUE,
|
||||
NULL);
|
||||
BindingTarget *target = g_object_new (binding_target_get_type (),
|
||||
"toggle", FALSE,
|
||||
NULL);
|
||||
GBinding *binding;
|
||||
|
||||
binding = g_object_bind_property (source, "toggle",
|
||||
target, "toggle",
|
||||
G_BINDING_DEFAULT | G_BINDING_INVERT_BOOLEAN);
|
||||
|
||||
g_assert (source->toggle);
|
||||
g_assert (!target->toggle);
|
||||
|
||||
g_object_set (source, "toggle", FALSE, NULL);
|
||||
g_assert (!source->toggle);
|
||||
g_assert (target->toggle);
|
||||
|
||||
g_object_unref (binding);
|
||||
g_object_unref (source);
|
||||
g_object_unref (target);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
@ -481,6 +534,7 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/binding/transform-closure", binding_transform_closure);
|
||||
g_test_add_func ("/binding/chain", binding_chain);
|
||||
g_test_add_func ("/binding/sync-create", binding_sync_create);
|
||||
g_test_add_func ("/binding/invert-boolean", binding_invert_boolean);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user