mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-26 15:36: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_DEFAULT, "G_BINDING_DEFAULT", "default" },
|
||||||
{ G_BINDING_BIDIRECTIONAL, "G_BINDING_BIDIRECTIONAL", "bidirectional" },
|
{ G_BINDING_BIDIRECTIONAL, "G_BINDING_BIDIRECTIONAL", "bidirectional" },
|
||||||
{ G_BINDING_SYNC_CREATE, "G_BINDING_SYNC_CREATE", "sync-create" },
|
{ G_BINDING_SYNC_CREATE, "G_BINDING_SYNC_CREATE", "sync-create" },
|
||||||
|
{ G_BINDING_INVERT_BOOLEAN, "G_BINDING_INVERT_BOOLEAN", "invert-boolean" },
|
||||||
{ 0, NULL, NULL }
|
{ 0, NULL, NULL }
|
||||||
};
|
};
|
||||||
GType g_define_type_id =
|
GType g_define_type_id =
|
||||||
@ -301,21 +302,44 @@ done:
|
|||||||
return TRUE;
|
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
|
static gboolean
|
||||||
default_transform_to (GBinding *binding G_GNUC_UNUSED,
|
default_transform_to (GBinding *binding,
|
||||||
const GValue *value_a,
|
const GValue *value_a,
|
||||||
GValue *value_b,
|
GValue *value_b,
|
||||||
gpointer user_data G_GNUC_UNUSED)
|
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);
|
return default_transform (value_a, value_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
default_transform_from (GBinding *binding G_GNUC_UNUSED,
|
default_transform_from (GBinding *binding,
|
||||||
const GValue *value_a,
|
const GValue *value_a,
|
||||||
GValue *value_b,
|
GValue *value_b,
|
||||||
gpointer user_data G_GNUC_UNUSED)
|
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);
|
return default_transform (value_a, value_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -809,6 +833,15 @@ g_object_bind_property_full (gpointer source,
|
|||||||
return NULL;
|
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);
|
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (source), source_property);
|
||||||
if (pspec == NULL)
|
if (pspec == NULL)
|
||||||
{
|
{
|
||||||
@ -838,6 +871,18 @@ g_object_bind_property_full (gpointer source,
|
|||||||
return NULL;
|
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);
|
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (target), target_property);
|
||||||
if (pspec == NULL)
|
if (pspec == NULL)
|
||||||
{
|
{
|
||||||
@ -867,6 +912,18 @@ g_object_bind_property_full (gpointer source,
|
|||||||
return NULL;
|
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,
|
binding = g_object_new (G_TYPE_BINDING,
|
||||||
"source", source,
|
"source", source,
|
||||||
"source-property", source_property,
|
"source-property", source_property,
|
||||||
|
@ -72,13 +72,18 @@ typedef gboolean (* GBindingTransformFunc) (GBinding *binding,
|
|||||||
/**
|
/**
|
||||||
* GBindingFlags:
|
* GBindingFlags:
|
||||||
* @G_BINDING_DEFAULT: The default binding; if the source property
|
* @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
|
* @G_BINDING_BIDIRECTIONAL: Bidirectional binding; if either the
|
||||||
* property of the source or the property of the target changes,
|
* 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
|
* @G_BINDING_SYNC_CREATE: Synchronize the values of the source and
|
||||||
* target properties when creating the binding; the direction of
|
* 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
|
* Flags to be passed to g_object_bind_property() or
|
||||||
* g_object_bind_property_full().
|
* g_object_bind_property_full().
|
||||||
@ -91,7 +96,8 @@ typedef enum { /*< prefix=G_BINDING >*/
|
|||||||
G_BINDING_DEFAULT = 0,
|
G_BINDING_DEFAULT = 0,
|
||||||
|
|
||||||
G_BINDING_BIDIRECTIONAL = 1 << 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;
|
} GBindingFlags;
|
||||||
|
|
||||||
GType g_binding_flags_get_type (void) G_GNUC_CONST;
|
GType g_binding_flags_get_type (void) G_GNUC_CONST;
|
||||||
|
@ -8,6 +8,7 @@ typedef struct _BindingSource
|
|||||||
|
|
||||||
gint foo;
|
gint foo;
|
||||||
gdouble value;
|
gdouble value;
|
||||||
|
gboolean toggle;
|
||||||
} BindingSource;
|
} BindingSource;
|
||||||
|
|
||||||
typedef struct _BindingSourceClass
|
typedef struct _BindingSourceClass
|
||||||
@ -20,8 +21,8 @@ enum
|
|||||||
PROP_SOURCE_0,
|
PROP_SOURCE_0,
|
||||||
|
|
||||||
PROP_SOURCE_FOO,
|
PROP_SOURCE_FOO,
|
||||||
|
PROP_SOURCE_VALUE,
|
||||||
PROP_SOURCE_VALUE
|
PROP_SOURCE_TOGGLE
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (BindingSource, binding_source, G_TYPE_OBJECT);
|
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);
|
source->value = g_value_get_double (value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_SOURCE_TOGGLE:
|
||||||
|
source->toggle = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
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);
|
g_value_set_double (value, source->value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_SOURCE_TOGGLE:
|
||||||
|
g_value_set_boolean (value, source->toggle);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
}
|
}
|
||||||
@ -90,6 +99,10 @@ binding_source_class_init (BindingSourceClass *klass)
|
|||||||
-100.0, 200.0,
|
-100.0, 200.0,
|
||||||
0.0,
|
0.0,
|
||||||
G_PARAM_READWRITE));
|
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
|
static void
|
||||||
@ -103,6 +116,7 @@ typedef struct _BindingTarget
|
|||||||
|
|
||||||
gint bar;
|
gint bar;
|
||||||
gdouble value;
|
gdouble value;
|
||||||
|
gboolean toggle;
|
||||||
} BindingTarget;
|
} BindingTarget;
|
||||||
|
|
||||||
typedef struct _BindingTargetClass
|
typedef struct _BindingTargetClass
|
||||||
@ -115,8 +129,8 @@ enum
|
|||||||
PROP_TARGET_0,
|
PROP_TARGET_0,
|
||||||
|
|
||||||
PROP_TARGET_BAR,
|
PROP_TARGET_BAR,
|
||||||
|
PROP_TARGET_VALUE,
|
||||||
PROP_TARGET_VALUE
|
PROP_TARGET_TOGGLE
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (BindingTarget, binding_target, G_TYPE_OBJECT);
|
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);
|
target->value = g_value_get_double (value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_TARGET_TOGGLE:
|
||||||
|
target->toggle = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
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);
|
g_value_set_double (value, target->value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_TARGET_TOGGLE:
|
||||||
|
g_value_set_boolean (value, target->toggle);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
}
|
}
|
||||||
@ -180,11 +202,15 @@ binding_target_class_init (BindingTargetClass *klass)
|
|||||||
-1, 100,
|
-1, 100,
|
||||||
0,
|
0,
|
||||||
G_PARAM_READWRITE));
|
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",
|
g_param_spec_double ("value", "Value", "Value",
|
||||||
-100.0, 200.0,
|
-100.0, 200.0,
|
||||||
0.0,
|
0.0,
|
||||||
G_PARAM_READWRITE));
|
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
|
static void
|
||||||
@ -469,6 +495,33 @@ binding_sync_create (void)
|
|||||||
g_object_unref (target);
|
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
|
int
|
||||||
main (int argc, char *argv[])
|
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/transform-closure", binding_transform_closure);
|
||||||
g_test_add_func ("/binding/chain", binding_chain);
|
g_test_add_func ("/binding/chain", binding_chain);
|
||||||
g_test_add_func ("/binding/sync-create", binding_sync_create);
|
g_test_add_func ("/binding/sync-create", binding_sync_create);
|
||||||
|
g_test_add_func ("/binding/invert-boolean", binding_invert_boolean);
|
||||||
|
|
||||||
return g_test_run ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user