X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgsimpleaction.c;h=610e2fa1dcddaa1a902db2ccc25a46be74a8dbe9;hb=f14a66e3df9e5e3f0f170b68e976011c80ffc041;hp=915a2e6ebd40c89186df463e4c85e780b694c77b;hpb=695a9a799355713dc6df089801b7f67a010e3b13;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gsimpleaction.c b/gio/gsimpleaction.c index 915a2e6..610e2fa 100644 --- a/gio/gsimpleaction.c +++ b/gio/gsimpleaction.c @@ -12,9 +12,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. + * Public License along with this library; if not, see . * * Authors: Ryan Lortie */ @@ -29,14 +27,15 @@ /** * SECTION:gsimpleaction * @title: GSimpleAction - * @short_description: A simple GSimpleAction + * @short_description: A simple GAction implementation + * @include: gio/gio.h * * A #GSimpleAction is the obvious simple implementation of the #GAction - * interface. This is the easiest way to create an action for purposes of + * interface. This is the easiest way to create an action for purposes of * adding it to a #GSimpleActionGroup. * * See also #GtkAction. - **/ + */ struct _GSimpleAction { GObject parent_instance; @@ -45,6 +44,7 @@ struct _GSimpleAction GVariantType *parameter_type; gboolean enabled; GVariant *state; + gboolean state_set_already; }; typedef GObjectClass GSimpleActionClass; @@ -65,6 +65,7 @@ enum enum { + SIGNAL_CHANGE_STATE, SIGNAL_ACTIVATE, NR_SIGNALS }; @@ -79,7 +80,7 @@ g_simple_action_get_name (GAction *action) return simple->name; } -const GVariantType * +static const GVariantType * g_simple_action_get_parameter_type (GAction *action) { GSimpleAction *simple = G_SIMPLE_ACTION (action); @@ -118,7 +119,15 @@ g_simple_action_change_state (GAction *action, { GSimpleAction *simple = G_SIMPLE_ACTION (action); - g_simple_action_set_state (simple, value); + /* If the user connected a signal handler then they are responsible + * for handling state changes. + */ + if (g_signal_has_handler_pending (action, g_simple_action_signals[SIGNAL_CHANGE_STATE], 0, TRUE)) + g_signal_emit (action, g_simple_action_signals[SIGNAL_CHANGE_STATE], 0, value); + + /* If not, then the default behaviour is to just set the state. */ + else + g_simple_action_set_state (simple, value); } /** @@ -135,6 +144,8 @@ g_simple_action_change_state (GAction *action, * property. Instead, they should call g_action_change_state() to * request the change. * + * If the @value GVariant is floating, it is consumed. + * * Since: 2.30 **/ void @@ -192,34 +203,70 @@ g_simple_action_activate (GAction *action, g_variant_ref_sink (parameter); if (simple->enabled) - g_signal_emit (simple, g_simple_action_signals[SIGNAL_ACTIVATE], 0, parameter); + { + /* If the user connected a signal handler then they are responsible + * for handling activation. + */ + if (g_signal_has_handler_pending (action, g_simple_action_signals[SIGNAL_ACTIVATE], 0, TRUE)) + g_signal_emit (action, g_simple_action_signals[SIGNAL_ACTIVATE], 0, parameter); + + /* If not, do some reasonable defaults for stateful actions. */ + else if (simple->state) + { + /* If we have no parameter and this is a boolean action, toggle. */ + if (parameter == NULL && g_variant_is_of_type (simple->state, G_VARIANT_TYPE_BOOLEAN)) + { + gboolean was_enabled = g_variant_get_boolean (simple->state); + g_simple_action_change_state (action, g_variant_new_boolean (!was_enabled)); + } + + /* else, if the parameter and state type are the same, do a change-state */ + else if (g_variant_is_of_type (simple->state, g_variant_get_type (parameter))) + g_simple_action_change_state (action, parameter); + } + } if (parameter != NULL) g_variant_unref (parameter); } static void -g_simple_action_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) +g_simple_action_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) { - GSimpleAction *simple = G_SIMPLE_ACTION (object); + GSimpleAction *action = G_SIMPLE_ACTION (object); switch (prop_id) { case PROP_NAME: - g_assert (simple->name == NULL); - simple->name = g_value_dup_string (value); + action->name = g_strdup (g_value_get_string (value)); break; case PROP_PARAMETER_TYPE: - g_assert (simple->parameter_type == NULL); - simple->parameter_type = g_value_dup_boxed (value); + action->parameter_type = g_value_dup_boxed (value); break; case PROP_ENABLED: - g_simple_action_set_enabled (simple, g_value_get_boolean (value)); + action->enabled = g_value_get_boolean (value); + break; + + case PROP_STATE: + /* The first time we see this (during construct) we should just + * take the state as it was handed to us. + * + * After that, we should make sure we go through the same checks + * as the C API. + */ + if (!action->state_set_already) + { + action->state = g_value_dup_variant (value); + action->state_set_already = TRUE; + } + else + g_simple_action_set_state (action, g_value_get_variant (value)); + break; default: @@ -280,6 +327,7 @@ g_simple_action_finalize (GObject *object) void g_simple_action_init (GSimpleAction *simple) { + simple->enabled = TRUE; } void @@ -300,8 +348,8 @@ g_simple_action_class_init (GSimpleActionClass *class) { GObjectClass *object_class = G_OBJECT_CLASS (class); - object_class->get_property = g_simple_action_get_property; object_class->set_property = g_simple_action_set_property; + object_class->get_property = g_simple_action_get_property; object_class->finalize = g_simple_action_finalize; /** @@ -314,6 +362,14 @@ g_simple_action_class_init (GSimpleActionClass *class) * @parameter will always be of the expected type. In the event that * an incorrect type was given, no signal will be emitted. * + * Since GLib 2.40, if no handler is connected to this signal then the + * default behaviour for boolean-stated actions with a %NULL parameter + * type is to toggle them via the #GSimpleAction::change-state signal. + * For stateful actions where the state type is equal to the parameter + * type, the default is to forward them directly to + * #GSimpleAction::change-state. This should allow almost all users + * of #GSimpleAction to connect only one handler or the other. + * * Since: 2.28 */ g_simple_action_signals[SIGNAL_ACTIVATE] = @@ -326,9 +382,57 @@ g_simple_action_class_init (GSimpleActionClass *class) G_TYPE_VARIANT); /** + * GSimpleAction::change-state: + * @simple: the #GSimpleAction + * @value: (allow-none): the requested value for the state + * + * Indicates that the action just received a request to change its + * state. + * + * @value will always be of the correct state type. In the event that + * an incorrect type was given, no signal will be emitted. + * + * If no handler is connected to this signal then the default + * behaviour is to call g_simple_action_set_state() to set the state + * to the requested value. If you connect a signal handler then no + * default action is taken. If the state should change then you must + * call g_simple_action_set_state() from the handler. + * + * An example of a 'change-state' handler: + * |[ + * static void + * change_volume_state (GSimpleAction *action, + * GVariant *value, + * gpointer user_data) + * { + * gint requested; + * + * requested = g_variant_get_int32 (value); + * + * // Volume only goes from 0 to 10 + * if (0 <= requested && requested <= 10) + * g_simple_action_set_state (action, value); + * } + * ]| + * + * The handler need not set the state to the requested value. + * It could set it to any value at all, or take some other action. + * + * Since: 2.30 + */ + g_simple_action_signals[SIGNAL_CHANGE_STATE] = + g_signal_new (I_("change-state"), + G_TYPE_SIMPLE_ACTION, + G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VARIANT, + G_TYPE_NONE, 1, + G_TYPE_VARIANT); + + /** * GSimpleAction:name: * - * The name of the action. This is mostly meaningful for identifying + * The name of the action. This is mostly meaningful for identifying * the action once it has been added to a #GSimpleActionGroup. * * Since: 2.28 @@ -364,8 +468,8 @@ g_simple_action_class_init (GSimpleActionClass *class) * * If @action is currently enabled. * - * If the action is disabled then calls to g_simple_action_activate() and - * g_simple_action_change_state() have no effect. + * If the action is disabled then calls to g_action_activate() and + * g_action_change_state() have no effect. * * Since: 2.28 **/ @@ -374,7 +478,6 @@ g_simple_action_class_init (GSimpleActionClass *class) P_("Enabled"), P_("If the action can be activated"), TRUE, - G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); @@ -407,7 +510,7 @@ g_simple_action_class_init (GSimpleActionClass *class) P_("The state the action is in"), G_VARIANT_TYPE_ANY, NULL, - G_PARAM_READABLE | + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); } @@ -485,15 +588,9 @@ g_simple_action_new_stateful (const gchar *name, const GVariantType *parameter_type, GVariant *state) { - GSimpleAction *simple; - - simple = g_object_new (G_TYPE_SIMPLE_ACTION, - "name", name, - "parameter-type", parameter_type, - NULL); - - if (state) - simple->state = g_variant_ref_sink (state); - - return simple; + return g_object_new (G_TYPE_SIMPLE_ACTION, + "name", name, + "parameter-type", parameter_type, + "state", state, + NULL); }