Commit 88ec007b authored by Allison Karlitskaya's avatar Allison Karlitskaya

Add new GtkActionable interface

This is the interface for GtkWidgets that can be associated with an
action on a GtkAppicationWindow or associated GtkApplication.

It essentially features 'action-name' and 'action-target' properties
with some associated convenience API.

This interface is implemented by GtkButton and GtkToolButton.

https://bugzilla.gnome.org/show_bug.cgi?id=667394
parent a3629592
...@@ -172,6 +172,7 @@ gtk_public_h_sources = \ ...@@ -172,6 +172,7 @@ gtk_public_h_sources = \
gtkaccellabel.h \ gtkaccellabel.h \
gtkaccelmap.h \ gtkaccelmap.h \
gtkaccessible.h \ gtkaccessible.h \
gtkactionable.h \
gtkaction.h \ gtkaction.h \
gtkactiongroup.h \ gtkactiongroup.h \
gtkactivatable.h \ gtkactivatable.h \
...@@ -392,6 +393,7 @@ gtk_private_type_h_sources = \ ...@@ -392,6 +393,7 @@ gtk_private_type_h_sources = \
# GTK+ header files that don't get installed # GTK+ header files that don't get installed
gtk_private_h_sources = \ gtk_private_h_sources = \
gactionmuxer.h \ gactionmuxer.h \
gsimpleactionobserver.h \
gactionobserver.h \ gactionobserver.h \
gactionobservable.h \ gactionobservable.h \
gtkapplicationprivate.h \ gtkapplicationprivate.h \
...@@ -512,8 +514,10 @@ deprecated_c_sources = \ ...@@ -512,8 +514,10 @@ deprecated_c_sources = \
gtk_base_c_sources = \ gtk_base_c_sources = \
$(deprecated_c_sources) \ $(deprecated_c_sources) \
gactionmuxer.c \ gactionmuxer.c \
gsimpleactionobserver.c \
gactionobserver.c \ gactionobserver.c \
gactionobservable.c \ gactionobservable.c \
gtkactionable.c \
gtkquery.c \ gtkquery.c \
gtksearchengine.c \ gtksearchengine.c \
gtksearchenginesimple.c \ gtksearchenginesimple.c \
......
/*
* Copyright © 2012 Canonical Limited
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2 of the
* licence or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* 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.
*
* Authors: Ryan Lortie <desrt@desrt.ca>
*/
#include "config.h"
#include "gsimpleactionobserver.h"
#include "gactionobservable.h"
typedef GObjectClass GSimpleActionObserverClass;
struct _GSimpleActionObserver
{
GObject parent_instance;
GActionGroup *action_group;
gchar *action_name;
GVariant *target;
gboolean can_activate;
gboolean active;
gboolean enabled;
gint reporting;
};
static void g_simple_action_observer_init_iface (GActionObserverInterface *iface);
G_DEFINE_TYPE_WITH_CODE (GSimpleActionObserver, g_simple_action_observer, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_OBSERVER, g_simple_action_observer_init_iface));
enum
{
PROP_0,
PROP_ACTIVE,
PROP_ENABLED,
N_PROPS
};
static GParamSpec *g_simple_action_observer_pspecs[N_PROPS];
static void
g_simple_action_observer_action_added (GActionObserver *g_observer,
GActionObservable *observable,
const gchar *action_name,
const GVariantType *parameter_type,
gboolean enabled,
GVariant *state)
{
GSimpleActionObserver *observer = G_SIMPLE_ACTION_OBSERVER (g_observer);
gboolean active;
/* we can only activate if we have the correct type of parameter */
observer->can_activate = (observer->target == NULL && parameter_type == NULL) ||
(observer->target != NULL && parameter_type != NULL &&
g_variant_is_of_type (observer->target, parameter_type));
if (observer->can_activate)
{
if (observer->target != NULL && state != NULL)
active = g_variant_equal (state, observer->target);
else if (state != NULL && g_variant_is_of_type (state, G_VARIANT_TYPE_BOOLEAN))
active = g_variant_get_boolean (state);
else
active = FALSE;
if (active != observer->active)
{
observer->active = active;
observer->reporting++;
g_object_notify_by_pspec (G_OBJECT (observer), g_simple_action_observer_pspecs[PROP_ACTIVE]);
observer->reporting--;
}
if (enabled != observer->enabled)
{
observer->enabled = enabled;
g_object_notify_by_pspec (G_OBJECT (observer), g_simple_action_observer_pspecs[PROP_ENABLED]);
}
}
}
static void
g_simple_action_observer_action_enabled_changed (GActionObserver *g_observer,
GActionObservable *observable,
const gchar *action_name,
gboolean enabled)
{
GSimpleActionObserver *observer = G_SIMPLE_ACTION_OBSERVER (g_observer);
if (!observer->can_activate)
return;
if (enabled != observer->enabled)
{
observer->enabled = enabled;
g_object_notify_by_pspec (G_OBJECT (observer), g_simple_action_observer_pspecs[PROP_ENABLED]);
}
}
static void
g_simple_action_observer_action_state_changed (GActionObserver *g_observer,
GActionObservable *observable,
const gchar *action_name,
GVariant *state)
{
GSimpleActionObserver *observer = G_SIMPLE_ACTION_OBSERVER (g_observer);
gboolean active = FALSE;
if (!observer->can_activate)
return;
if (observer->target)
active = g_variant_equal (state, observer->target);
else if (g_variant_is_of_type (state, G_VARIANT_TYPE_BOOLEAN))
active = g_variant_get_boolean (state);
if (active != observer->active)
{
observer->active = active;
observer->reporting++;
g_object_notify_by_pspec (G_OBJECT (observer), g_simple_action_observer_pspecs[PROP_ACTIVE]);
observer->reporting--;
}
}
static void
g_simple_action_observer_action_removed (GActionObserver *g_observer,
GActionObservable *observable,
const gchar *action_name)
{
GSimpleActionObserver *observer = G_SIMPLE_ACTION_OBSERVER (g_observer);
if (!observer->can_activate)
return;
observer->can_activate = FALSE;
if (observer->active)
{
observer->active = FALSE;
observer->reporting++;
g_object_notify_by_pspec (G_OBJECT (observer), g_simple_action_observer_pspecs[PROP_ACTIVE]);
observer->reporting--;
}
if (observer->enabled)
{
observer->enabled = FALSE;
g_object_notify_by_pspec (G_OBJECT (observer), g_simple_action_observer_pspecs[PROP_ENABLED]);
}
}
static void
g_simple_action_observer_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
GSimpleActionObserver *observer = G_SIMPLE_ACTION_OBSERVER (object);
switch (prop_id)
{
case PROP_ACTIVE:
g_value_set_boolean (value, observer->active);
break;
case PROP_ENABLED:
g_value_set_boolean (value, observer->enabled);
break;
default:
g_assert_not_reached ();
}
}
static void
g_simple_action_observer_finalize (GObject *object)
{
GSimpleActionObserver *observer = G_SIMPLE_ACTION_OBSERVER (object);
g_object_unref (observer->action_group);
g_free (observer->action_name);
if (observer->target)
g_variant_unref (observer->target);
G_OBJECT_CLASS (g_simple_action_observer_parent_class)
->finalize (object);
}
static void
g_simple_action_observer_init (GSimpleActionObserver *observer)
{
}
static void
g_simple_action_observer_init_iface (GActionObserverInterface *iface)
{
iface->action_added = g_simple_action_observer_action_added;
iface->action_enabled_changed = g_simple_action_observer_action_enabled_changed;
iface->action_state_changed = g_simple_action_observer_action_state_changed;
iface->action_removed = g_simple_action_observer_action_removed;
}
static void
g_simple_action_observer_class_init (GObjectClass *class)
{
class->get_property = g_simple_action_observer_get_property;
class->finalize = g_simple_action_observer_finalize;
g_simple_action_observer_pspecs[PROP_ACTIVE] = g_param_spec_boolean ("active", "active", "active", FALSE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_simple_action_observer_pspecs[PROP_ENABLED] = g_param_spec_boolean ("enabled", "enabled", "enabled", FALSE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (class, N_PROPS, g_simple_action_observer_pspecs);
}
GSimpleActionObserver *
g_simple_action_observer_new (GActionObservable *observable,
const gchar *action_name,
GVariant *target)
{
GSimpleActionObserver *observer;
const GVariantType *type;
gboolean enabled;
GVariant *state;
observer = g_object_new (G_TYPE_SIMPLE_ACTION_OBSERVER, NULL);
observer->action_group = g_object_ref (observable);
observer->action_name = g_strdup (action_name);
if (target)
observer->target = g_variant_ref_sink (target);
g_action_observable_register_observer (observable, action_name, G_ACTION_OBSERVER (observer));
if (g_action_group_query_action (observer->action_group, action_name, &enabled, &type, NULL, NULL, &state))
{
g_simple_action_observer_action_added (G_ACTION_OBSERVER (observer), observable,
action_name, type, enabled, state);
if (state)
g_variant_unref (state);
}
return observer;
}
void
g_simple_action_observer_activate (GSimpleActionObserver *observer)
{
g_return_if_fail (G_IS_SIMPLE_ACTION_OBSERVER (observer));
if (observer->can_activate && !observer->reporting)
g_action_group_activate_action (G_ACTION_GROUP (observer->action_group),
observer->action_name, observer->target);
}
gboolean
g_simple_action_observer_get_active (GSimpleActionObserver *observer)
{
g_return_val_if_fail (G_IS_SIMPLE_ACTION_OBSERVER (observer), FALSE);
return observer->active;
}
gboolean
g_simple_action_observer_get_enabled (GSimpleActionObserver *observer)
{
g_return_val_if_fail (G_IS_SIMPLE_ACTION_OBSERVER (observer), FALSE);
return observer->enabled;
}
/*
* Copyright © 2012 Canonical Limited
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2 of the
* licence or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* 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.
*
* Authors: Ryan Lortie <desrt@desrt.ca>
*/
#ifndef __G_SIMPLE_ACTION_OBSERVER_H__
#define __G_SIMPLE_ACTION_OBSERVER_H__
#include "gactionobserver.h"
G_BEGIN_DECLS
#define G_TYPE_SIMPLE_ACTION_OBSERVER (g_simple_action_observer_get_type ())
#define G_SIMPLE_ACTION_OBSERVER(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
G_TYPE_SIMPLE_ACTION_OBSERVER, \
GSimpleActionObserver))
#define G_IS_SIMPLE_ACTION_OBSERVER(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
G_TYPE_SIMPLE_ACTION_OBSERVER))
typedef struct _GSimpleActionObserver GSimpleActionObserver;
G_GNUC_INTERNAL
GType g_simple_action_observer_get_type (void);
G_GNUC_INTERNAL
GSimpleActionObserver * g_simple_action_observer_new (GActionObservable *observable,
const gchar *action_name,
GVariant *target);
G_GNUC_INTERNAL
void g_simple_action_observer_activate (GSimpleActionObserver *observer);
G_GNUC_INTERNAL
gboolean g_simple_action_observer_get_active (GSimpleActionObserver *observer);
G_GNUC_INTERNAL
gboolean g_simple_action_observer_get_enabled (GSimpleActionObserver *observer);
G_END_DECLS
#endif /* __G_SIMPLE_ACTION_OBSERVER_H__ */
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <gtk/gtkaccelmap.h> #include <gtk/gtkaccelmap.h>
#include <gtk/gtkaccessible.h> #include <gtk/gtkaccessible.h>
#include <gtk/gtkaction.h> #include <gtk/gtkaction.h>
#include <gtk/gtkactionable.h>
#include <gtk/gtkactiongroup.h> #include <gtk/gtkactiongroup.h>
#include <gtk/gtkactivatable.h> #include <gtk/gtkactivatable.h>
#include <gtk/gtkadjustment.h> #include <gtk/gtkadjustment.h>
......
/*
* Copyright © 2012 Canonical Limited
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2 of the
* licence or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* 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.
*
* Authors: Ryan Lortie <desrt@desrt.ca>
*/
#include "config.h"
#include "gtkactionable.h"
#include "gtkwidget.h"
#include "gtkintl.h"
G_DEFINE_INTERFACE (GtkActionable, gtk_actionable, GTK_TYPE_WIDGET)
static void
gtk_actionable_default_init (GtkActionableInterface *iface)
{
g_object_interface_install_property (iface,
g_param_spec_string ("action-name", P_("action name"),
P_("The name of the associated action, like 'app.quit'"),
NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_interface_install_property (iface,
g_param_spec_variant ("action-target", P_("action target value"),
P_("The parameter for action invocations"),
G_VARIANT_TYPE_ANY, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
const gchar *
gtk_actionable_get_action_name (GtkActionable *actionable)
{
g_return_val_if_fail (GTK_IS_ACTIONABLE (actionable), NULL);
return GTK_ACTIONABLE_GET_IFACE (actionable)
->get_action_name (actionable);
}
void
gtk_actionable_set_action_name (GtkActionable *actionable,
const gchar *action_name)
{
g_return_if_fail (GTK_IS_ACTIONABLE (actionable));
GTK_ACTIONABLE_GET_IFACE (actionable)
->set_action_name (actionable, action_name);
}
GVariant *
gtk_actionable_get_action_target_value (GtkActionable *actionable)
{
g_return_val_if_fail (GTK_IS_ACTIONABLE (actionable), NULL);
return GTK_ACTIONABLE_GET_IFACE (actionable)
->get_action_target_value (actionable);
}
void
gtk_actionable_set_action_target_value (GtkActionable *actionable,
GVariant *target_value)
{
g_return_if_fail (GTK_IS_ACTIONABLE (actionable));
GTK_ACTIONABLE_GET_IFACE (actionable)
->set_action_target_value (actionable, target_value);
}
void
gtk_actionable_set_action_target (GtkActionable *actionable,
const gchar *format_string,
...)
{
va_list ap;
va_start (ap, format_string);
gtk_actionable_set_action_target_value (actionable, g_variant_new_va (format_string, NULL, &ap));
va_end (ap);
}
void
gtk_actionable_set_detailed_action_name (GtkActionable *actionable,
const gchar *detailed_action_name)
{
gchar **parts;
g_return_if_fail (GTK_IS_ACTIONABLE (actionable));
if (detailed_action_name == NULL)
{
gtk_actionable_set_action_name (actionable, NULL);
gtk_actionable_set_action_target_value (actionable, NULL);
return;
}
parts = g_strsplit (detailed_action_name, "::", 2);
gtk_actionable_set_action_name (actionable, parts[0]);
if (parts[0] && parts[1])
gtk_actionable_set_action_target (actionable, "s", parts[1]);
else
gtk_actionable_set_action_target_value (actionable, NULL);
g_strfreev (parts);
}
/*
* Copyright © 2012 Canonical Limited
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2 of the
* licence or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* 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.
*
* Authors: Ryan Lortie <desrt@desrt.ca>
*/
#ifndef __GTK_ACTIONABLE_H__
#define __GTK_ACTIONABLE_H__
#include <glib-object.h>
G_BEGIN_DECLS
#define GTK_TYPE_ACTIONABLE (gtk_actionable_get_type ())
#define GTK_ACTIONABLE(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
GTK_TYPE_ACTIONABLE, GtkActionable))
#define GTK_IS_ACTIONABLE(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
GTK_TYPE_ACTIONABLE))
#define GTK_ACTIONABLE_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), \
GTK_TYPE_ACTIONABLE, GtkActionableInterface))
typedef struct _GtkActionableInterface GtkActionableInterface;
typedef struct _GtkActionable GtkActionable;
struct _GtkActionableInterface
{
GTypeInterface g_iface;
const gchar * (* get_action_name) (GtkActionable *actionable);
void (* set_action_name) (GtkActionable *actionable,
const gchar *action_name);
GVariant * (* get_action_target_value) (GtkActionable *actionable);
void (* set_action_target_value) (GtkActionable *actionable,
GVariant *action_target_value);
};
GType gtk_actionable_get_type (void) G_GNUC_CONST;
const gchar * gtk_actionable_get_action_name (GtkActionable *actionable);
void gtk_actionable_set_action_name (GtkActionable *actionable,
const gchar *action_name);
GVariant * gtk_actionable_get_action_target_value (GtkActionable *actionable);
void gtk_actionable_set_action_target_value (GtkActionable *actionable,
GVariant *target_value);
void gtk_actionable_set_action_target (GtkActionable *actionable,
const gchar *format_string,
...);
void gtk_actionable_set_detailed_action_name (GtkActionable *actionable,
const gchar *detailed_action_name);
G_END_DECLS
#endif /* __GTK_ACTIONABLE_H__ */
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#ifndef __GTK_APPLICATION_PRIVATE_H__ #ifndef __GTK_APPLICATION_PRIVATE_H__
#define __GTK_APPLICATION_PRIVATE_H__ #define __GTK_APPLICATION_PRIVATE_H__
#include "gsimpleactionobserver.h"
#include "gtkapplicationwindow.h" #include "gtkapplicationwindow.h"
G_GNUC_INTERNAL G_GNUC_INTERNAL
...@@ -33,4 +34,9 @@ gboolean gtk_application_window_publish (GtkAppl ...@@ -33,4 +34,9 @@ gboolean gtk_application_window_publish (GtkAppl
G_GNUC_INTERNAL G_GNUC_INTERNAL
void gtk_application_window_unpublish (GtkApplicationWindow *window); void gtk_application_window_unpublish (GtkApplicationWindow *window);
G_GNUC_INTERNAL
GSimpleActionObserver * gtk_application_window_get_observer (GtkApplicationWindow *window,
const gchar *action_name,
GVariant *target);
#endif /* __GTK_APPLICATION_PRIVATE_H__ */ #endif /* __GTK_APPLICATION_PRIVATE_H__ */
...@@ -182,6 +182,7 @@ struct _GtkApplicationWindowPrivate ...@@ -182,6 +182,7 @@ struct _GtkApplicationWindowPrivate
{ {
GSimpleActionGroup *actions; GSimpleActionGroup *actions;
GActionObservable *muxer; GActionObservable *muxer;
gboolean muxer_initialised;
GtkWidget *menubar; GtkWidget *menubar;
GtkAccelGroup *accels; GtkAccelGroup *accels;
GSList *accel_closures; GSList *accel_closures;
...@@ -671,14 +672,11 @@ gtk_application_window_real_realize (GtkWidget *widget) ...@@ -671,14 +672,11 @@ gtk_application_window_real_realize (GtkWidget *widget)
g_signal_connect (settings, "notify::gtk-shell-shows-menubar", g_signal_connect (settings, "notify::gtk-shell-shows-menubar",
G_CALLBACK (gtk_application_window_shell_shows_menubar_changed), window); G_CALLBACK (gtk_application_window_shell_shows_menubar_changed), window);
if (window->priv->muxer == NULL) if (!window->priv->muxer_initialised)
{ {
GActionMuxer *muxer; g_action_muxer_insert (G_ACTION_MUXER (window->priv->muxer), "app", G_ACTION_GROUP (application));
g_action_muxer_insert (G_ACTION_MUXER (window->priv->muxer), "win", G_ACTION_GROUP (window));
muxer = g_action_muxer_new (); window->priv->muxer_initialised = TRUE;
g_action_muxer_insert (muxer, "app", G_ACTION_GROUP (application));
g_action_muxer_insert (muxer, "win", G_ACTION_GROUP (window));
window->priv->muxer = G_ACTION_OBSERVABLE (muxer);
} }
gtk_application_window_update_shell_shows_app_menu (window, settings); gtk_application_window_update_shell_shows_app_menu (window, settings);
...@@ -875,6 +873,8 @@ gtk_application_window_init (GtkApplicationWindow *window) ...@@ -875,6 +873,8 @@ gtk_application_window_init (GtkApplicationWindow *window)
G_CALLBACK (g_action_group_action_state_changed), window); G_CALLBACK (g_action_group_action_state_changed), window);
g_signal_connect_swapped (window->priv->actions, "action-removed", g_signal_connect_swapped (window->priv->actions, "action-removed",
G_CALLBACK (g_action_group_action_removed), window); G_CALLBACK (g_action_group_action_removed), window);
window->priv->muxer = G_ACTION_OBSERVABLE (g_action_muxer_new ());
} }
static void static void
...@@ -982,3 +982,13 @@ gtk_application_window_set_show_menubar (GtkApplicationWindow *window, ...@@ -982,3 +982,13 @@ gtk_application_window_set_show_menubar (GtkApplicationWindow *window,
g_object_notify_by_pspec (G_OBJECT (window), gtk_application_window_properties[PROP_SHOW_MENUBAR]); g_object_notify_by_pspec (G_OBJECT (window), gtk_application_window_properties[PROP_SHOW_MENUBAR]);
} }
} }
GSimpleActionObserver *
gtk_application_window_get_observer (GtkApplicationWindow *window,
const gchar *action_name,
GVariant *target)
{
g_return_val_if_fail (GTK_IS_APPLICATION_WINDOW (window), NULL);
return g_simple_action_observer_new (window->priv->muxer, action_name, target);
}
...@@ -58,7 +58,8 @@ ...@@ -58,7 +58,8 @@
#include "gtkprivate.h" #include "gtkprivate.h"
#include "gtkintl.h" #include "gtkintl.h"
#include "a11y/gtkbuttonaccessible.h" #include "a11y/gtkbuttonaccessible.h"
#include "gtkapplicationprivate.h"
#include "gtkactionable.h"
static const GtkBorder default_default_border = { 1, 1, 1, 1 }; static const GtkBorder default_default_border = { 1, 1, 1, 1 };
static const GtkBorder default_default_outside_border = { 0, 0, 0, 0 }; static const GtkBorder default_default_outside_border = { 0, 0, 0, 0 };
...@@ -90,6 +91,8 @@ enum { ...@@ -90,6 +91,8 @@ enum {
PROP_XALIGN, PROP_XALIGN,
PROP_YALIGN, PROP_YALIGN,
PROP_IMAGE_POSITION, PROP_IMAGE_POSITION,
PROP_ACTION_NAME,
PROP_ACTION_TARGET,
/* activatable properties */ /* activatable properties */
PROP_ACTIVATABLE_RELATED_ACTION, PROP_ACTIVATABLE_RELATED_ACTION,
...@@ -147,8 +150,11 @@ static void gtk_button_state_changed (GtkWidget *widget, ...@@ -147,8 +150,11 @@ static void gtk_button_state_changed (GtkWidget *widget,
GtkStateType previous_state); GtkStateType previous_state);
static void gtk_button_grab_notify (GtkWidget *widget, static void gtk_button_grab_notify (GtkWidget *widget,
gboolean was_grabbed); gboolean was_grabbed);
static void gtk_button_hierarchy_changed (GtkWidget *widget,
GtkWidget *previous_toplevel);
static void gtk_button_actionable_iface_init (GtkActionableInterface *iface);
static void gtk_button_activatable_interface_init(GtkActivatableIface *iface); static void gtk_button_activatable_interface_init(GtkActivatableIface *iface);
static void gtk_button_update (GtkActivatable *activatable, static void gtk_button_update (GtkActivatable *activatable,
GtkAction *action, GtkAction *action,
...@@ -170,6 +176,7 @@ static void gtk_button_get_preferred_height (GtkWidget *widget, ...@@ -170,6 +176,7 @@ static void gtk_button_get_preferred_height (GtkWidget *widget,
static guint button_signals[LAST_SIGNAL] = { 0 }; static guint button_signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE_WITH_CODE (GtkButton, gtk_button, GTK_TYPE_BIN, G_DEFINE_TYPE_WITH_CODE (GtkButton, gtk_button, GTK_TYPE_BIN,
G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIONABLE, gtk_button_actionable_iface_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE, G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
gtk_button_activatable_interface_init)) gtk_button_activatable_interface_init))
...@@ -208,6 +215,7 @@ gtk_button_class_init (GtkButtonClass *klass) ...@@ -208,6 +215,7 @@ gtk_button_class_init (GtkButtonClass *klass)
widget_class->leave_notify_event = gtk_button_leave_notify; widget_class->leave_notify_event = gtk_button_leave_notify;
widget_class->state_changed = gtk_button_state_changed; widget_class->state_changed = gtk_button_state_changed;
widget_class->grab_notify = gtk_button_grab_notify; widget_class->grab_notify = gtk_button_grab_notify;
widget_class->hierarchy_changed = gtk_button_hierarchy_changed;
container_class->child_type = gtk_button_child_type; container_class->child_type = gtk_button_child_type;
container_class->add = gtk_button_add; container_class->add = gtk_button_add;
...@@ -330,6 +338,9 @@ gtk_button_class_init (GtkButtonClass *klass) ...@@ -330,6 +338,9 @@ gtk_button_class_init (GtkButtonClass *klass)
GTK_POS_LEFT, GTK_POS_LEFT,
GTK_PARAM_READWRITE)); GTK_PARAM_READWRITE));
g_object_class_override_property (gobject_class, PROP_ACTION_NAME, "action-name");