* 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 <http://www.gnu.org/licenses/>.
*
* Authors: Ryan Lortie <desrt@desrt.ca>
*/
/**
* 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;
GVariantType *parameter_type;
gboolean enabled;
GVariant *state;
+ gboolean state_set_already;
};
typedef GObjectClass GSimpleActionClass;
return simple->name;
}
-const GVariantType *
+static const GVariantType *
g_simple_action_get_parameter_type (GAction *action)
{
GSimpleAction *simple = G_SIMPLE_ACTION (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
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)
+{
+ GSimpleAction *action = G_SIMPLE_ACTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_NAME:
+ action->name = g_strdup (g_value_get_string (value));
+ break;
+
+ case PROP_PARAMETER_TYPE:
+ action->parameter_type = g_value_dup_boxed (value);
+ break;
+
+ case PROP_ENABLED:
+ 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:
+ g_assert_not_reached ();
+ }
+}
+
+static void
g_simple_action_get_property (GObject *object,
guint prop_id,
GValue *value,
void
g_simple_action_init (GSimpleAction *simple)
{
+ simple->enabled = TRUE;
}
void
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
+ 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;
* @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] =
*
* 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
+ * 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.
*
- * <example>
- * <title>Example 'change-state' handler</title>
- * <programlisting>
+ * An example of a 'change-state' handler:
+ * |[<!-- language="C" -->
* static void
* change_volume_state (GSimpleAction *action,
* GVariant *value,
* if (0 <= requested && requested <= 10)
* g_simple_action_set_state (action, value);
* }
- * </programlisting>
- * </example>
+ * ]|
*
- * 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.
+ * 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
*/
/**
* 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
P_("Action Name"),
P_("The name used to invoke the action"),
NULL,
- G_PARAM_READABLE |
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
/**
P_("Parameter Type"),
P_("The type of GVariant passed to activate()"),
G_TYPE_VARIANT_TYPE,
- G_PARAM_READABLE |
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
/**
*
* 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
**/
P_("Enabled"),
P_("If the action can be activated"),
TRUE,
- G_PARAM_READABLE |
+ G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
/**
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));
}
g_simple_action_new (const gchar *name,
const GVariantType *parameter_type)
{
- GSimpleAction *simple;
-
- g_return_val_if_fail (name != NULL, NULL);
-
- simple = g_object_new (G_TYPE_SIMPLE_ACTION, NULL);
- simple->name = g_strdup (name);
-
- if (parameter_type)
- simple->parameter_type = g_variant_type_copy (parameter_type);
-
- simple->enabled = TRUE;
-
- return simple;
+ return g_object_new (G_TYPE_SIMPLE_ACTION,
+ "name", name,
+ "parameter-type", parameter_type,
+ NULL);
}
/**
const GVariantType *parameter_type,
GVariant *state)
{
- GSimpleAction *simple;
-
- g_return_val_if_fail (name != NULL);
- g_return_val_if_fail (state != NULL);
-
- simple = g_object_new (G_TYPE_SIMPLE_ACTION, NULL);
- simple->name = g_strdup (name);
-
- if (parameter_type)
- simple->parameter_type = g_variant_type_copy (parameter_type);
-
- simple->state = g_variant_ref_sink (state);
-
- simple->enabled = TRUE;
-
- return simple;
+ return g_object_new (G_TYPE_SIMPLE_ACTION,
+ "name", name,
+ "parameter-type", parameter_type,
+ "state", state,
+ NULL);
}