Compare commits
21 Commits
wip/matthi
...
wip/gtkmen
Author | SHA1 | Date | |
---|---|---|---|
|
4ca9f40769 | ||
|
26e5e44dc6 | ||
|
c2b9d3f5db | ||
|
cbc844e7ca | ||
|
c818cc431a | ||
|
c1eeb96126 | ||
|
0d05a8f37a | ||
|
39e99b0987 | ||
|
2258dd9a75 | ||
|
6b394b89ba | ||
|
9e9bccbaaf | ||
|
ab2129016b | ||
|
357a390fe9 | ||
|
691b37adb2 | ||
|
972374cc30 | ||
|
2869f3c492 | ||
|
7520eb6996 | ||
|
7d3b8ad9bc | ||
|
a96fc95d6d | ||
|
81845aded9 | ||
|
71e221e51a |
@@ -402,9 +402,9 @@ gtk_private_type_h_sources = \
|
||||
|
||||
# GTK+ header files that don't get installed
|
||||
gtk_private_h_sources = \
|
||||
gactionmuxer.h \
|
||||
gactionobserver.h \
|
||||
gactionobservable.h \
|
||||
gtkactionmuxer.h \
|
||||
gtkactionobserver.h \
|
||||
gtkactionobservable.h \
|
||||
gtkapplicationprivate.h \
|
||||
gtkaccelgroupprivate.h \
|
||||
gtkaccelmapprivate.h \
|
||||
@@ -497,6 +497,7 @@ gtk_private_h_sources = \
|
||||
gtkmenuitemprivate.h \
|
||||
gtkmenushellprivate.h \
|
||||
gtkmenutracker.h \
|
||||
gtkmenutrackeritem.h \
|
||||
gtkmnemonichash.h \
|
||||
gtkmodelmenuitem.h \
|
||||
gtkmodifierstyle.h \
|
||||
@@ -584,9 +585,9 @@ deprecated_c_sources = \
|
||||
|
||||
gtk_base_c_sources = \
|
||||
$(deprecated_c_sources) \
|
||||
gactionmuxer.c \
|
||||
gactionobserver.c \
|
||||
gactionobservable.c \
|
||||
gtkactionmuxer.c \
|
||||
gtkactionobserver.c \
|
||||
gtkactionobservable.c \
|
||||
gtkactionable.c \
|
||||
gtkquery.c \
|
||||
gtksearchentry.c \
|
||||
@@ -764,6 +765,7 @@ gtk_base_c_sources = \
|
||||
gtkmenuitem.c \
|
||||
gtkmenushell.c \
|
||||
gtkmenutracker.c \
|
||||
gtkmenutrackeritem.c \
|
||||
gtkmenutoolbutton.c \
|
||||
gtkmessagedialog.c \
|
||||
gtkmisc.c \
|
||||
|
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2011 Canonical Limited
|
||||
*
|
||||
* This library 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author: Ryan Lortie <desrt@desrt.ca>
|
||||
*/
|
||||
|
||||
#ifndef __G_ACTION_MUXER_H__
|
||||
#define __G_ACTION_MUXER_H__
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define G_TYPE_ACTION_MUXER (g_action_muxer_get_type ())
|
||||
#define G_ACTION_MUXER(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
|
||||
G_TYPE_ACTION_MUXER, GActionMuxer))
|
||||
#define G_IS_ACTION_MUXER(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
|
||||
G_TYPE_ACTION_MUXER))
|
||||
|
||||
typedef struct _GActionMuxer GActionMuxer;
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
GType g_action_muxer_get_type (void);
|
||||
G_GNUC_INTERNAL
|
||||
GActionMuxer * g_action_muxer_new (void);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void g_action_muxer_insert (GActionMuxer *muxer,
|
||||
const gchar *prefix,
|
||||
GActionGroup *group);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void g_action_muxer_remove (GActionMuxer *muxer,
|
||||
const gchar *prefix);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
GActionMuxer * g_action_muxer_get_parent (GActionMuxer *muxer);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void g_action_muxer_set_parent (GActionMuxer *muxer,
|
||||
GActionMuxer *parent);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_ACTION_MUXER_H__ */
|
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2011 Canonical Limited
|
||||
*
|
||||
* This library 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Ryan Lortie <desrt@desrt.ca>
|
||||
*/
|
||||
|
||||
#ifndef __G_ACTION_OBSERVABLE_H__
|
||||
#define __G_ACTION_OBSERVABLE_H__
|
||||
|
||||
#include <gtk/gactionobserver.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define G_TYPE_ACTION_OBSERVABLE (g_action_observable_get_type ())
|
||||
#define G_ACTION_OBSERVABLE(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
|
||||
G_TYPE_ACTION_OBSERVABLE, GActionObservable))
|
||||
#define G_IS_ACTION_OBSERVABLE(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
|
||||
G_TYPE_ACTION_OBSERVABLE))
|
||||
#define G_ACTION_OBSERVABLE_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), \
|
||||
G_TYPE_ACTION_OBSERVABLE, GActionObservableInterface))
|
||||
|
||||
typedef struct _GActionObservableInterface GActionObservableInterface;
|
||||
|
||||
struct _GActionObservableInterface
|
||||
{
|
||||
GTypeInterface g_iface;
|
||||
|
||||
void (* register_observer) (GActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
GActionObserver *observer);
|
||||
void (* unregister_observer) (GActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
GActionObserver *observer);
|
||||
};
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
GType g_action_observable_get_type (void);
|
||||
G_GNUC_INTERNAL
|
||||
void g_action_observable_register_observer (GActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
GActionObserver *observer);
|
||||
G_GNUC_INTERNAL
|
||||
void g_action_observable_unregister_observer (GActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
GActionObserver *observer);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_ACTION_OBSERVABLE_H__ */
|
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2011 Canonical Limited
|
||||
*
|
||||
* This library 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Ryan Lortie <desrt@desrt.ca>
|
||||
*/
|
||||
|
||||
#ifndef __G_ACTION_OBSERVER_H__
|
||||
#define __G_ACTION_OBSERVER_H__
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define G_TYPE_ACTION_OBSERVER (g_action_observer_get_type ())
|
||||
#define G_ACTION_OBSERVER(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
|
||||
G_TYPE_ACTION_OBSERVER, GActionObserver))
|
||||
#define G_IS_ACTION_OBSERVER(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
|
||||
G_TYPE_ACTION_OBSERVER))
|
||||
#define G_ACTION_OBSERVER_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), \
|
||||
G_TYPE_ACTION_OBSERVER, GActionObserverInterface))
|
||||
|
||||
typedef struct _GActionObserverInterface GActionObserverInterface;
|
||||
typedef struct _GActionObservable GActionObservable;
|
||||
typedef struct _GActionObserver GActionObserver;
|
||||
|
||||
struct _GActionObserverInterface
|
||||
{
|
||||
GTypeInterface g_iface;
|
||||
|
||||
void (* action_added) (GActionObserver *observer,
|
||||
GActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
const GVariantType *parameter_type,
|
||||
gboolean enabled,
|
||||
GVariant *state);
|
||||
void (* action_enabled_changed) (GActionObserver *observer,
|
||||
GActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
gboolean enabled);
|
||||
void (* action_state_changed) (GActionObserver *observer,
|
||||
GActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
GVariant *state);
|
||||
void (* action_removed) (GActionObserver *observer,
|
||||
GActionObservable *observable,
|
||||
const gchar *action_name);
|
||||
};
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
GType g_action_observer_get_type (void);
|
||||
G_GNUC_INTERNAL
|
||||
void g_action_observer_action_added (GActionObserver *observer,
|
||||
GActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
const GVariantType *parameter_type,
|
||||
gboolean enabled,
|
||||
GVariant *state);
|
||||
G_GNUC_INTERNAL
|
||||
void g_action_observer_action_enabled_changed (GActionObserver *observer,
|
||||
GActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
gboolean enabled);
|
||||
G_GNUC_INTERNAL
|
||||
void g_action_observer_action_state_changed (GActionObserver *observer,
|
||||
GActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
GVariant *state);
|
||||
G_GNUC_INTERNAL
|
||||
void g_action_observer_action_removed (GActionObserver *observer,
|
||||
GActionObservable *observable,
|
||||
const gchar *action_name);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_ACTION_OBSERVER_H__ */
|
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "gtkactionhelper.h"
|
||||
#include "gactionobservable.h"
|
||||
#include "gtkactionobservable.h"
|
||||
|
||||
#include "gtkwidget.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
@@ -57,7 +57,7 @@ struct _GtkActionHelper
|
||||
|
||||
GtkActionHelperGroup *group;
|
||||
|
||||
GActionMuxer *action_context;
|
||||
GtkActionMuxer *action_context;
|
||||
gchar *action_name;
|
||||
|
||||
GVariant *target;
|
||||
@@ -81,10 +81,10 @@ enum
|
||||
|
||||
static GParamSpec *gtk_action_helper_pspecs[N_PROPS];
|
||||
|
||||
static void gtk_action_helper_observer_iface_init (GActionObserverInterface *iface);
|
||||
static void gtk_action_helper_observer_iface_init (GtkActionObserverInterface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkActionHelper, gtk_action_helper, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_OBSERVER, gtk_action_helper_observer_iface_init))
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTION_OBSERVER, gtk_action_helper_observer_iface_init))
|
||||
|
||||
static void
|
||||
gtk_action_helper_report_change (GtkActionHelper *helper,
|
||||
@@ -288,38 +288,38 @@ gtk_action_helper_finalize (GObject *object)
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_action_helper_observer_action_added (GActionObserver *observer,
|
||||
GActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
const GVariantType *parameter_type,
|
||||
gboolean enabled,
|
||||
GVariant *state)
|
||||
gtk_action_helper_observer_action_added (GtkActionObserver *observer,
|
||||
GtkActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
const GVariantType *parameter_type,
|
||||
gboolean enabled,
|
||||
GVariant *state)
|
||||
{
|
||||
gtk_action_helper_action_added (GTK_ACTION_HELPER (observer), enabled, parameter_type, state, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_action_helper_observer_action_enabled_changed (GActionObserver *observer,
|
||||
GActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
gboolean enabled)
|
||||
gtk_action_helper_observer_action_enabled_changed (GtkActionObserver *observer,
|
||||
GtkActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
gboolean enabled)
|
||||
{
|
||||
gtk_action_helper_action_enabled_changed (GTK_ACTION_HELPER (observer), enabled);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_action_helper_observer_action_state_changed (GActionObserver *observer,
|
||||
GActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
GVariant *state)
|
||||
gtk_action_helper_observer_action_state_changed (GtkActionObserver *observer,
|
||||
GtkActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
GVariant *state)
|
||||
{
|
||||
gtk_action_helper_action_state_changed (GTK_ACTION_HELPER (observer), state);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_action_helper_observer_action_removed (GActionObserver *observer,
|
||||
GActionObservable *observable,
|
||||
const gchar *action_name)
|
||||
gtk_action_helper_observer_action_removed (GtkActionObserver *observer,
|
||||
GtkActionObservable *observable,
|
||||
const gchar *action_name)
|
||||
{
|
||||
gtk_action_helper_action_removed (GTK_ACTION_HELPER (observer));
|
||||
}
|
||||
@@ -345,7 +345,7 @@ gtk_action_helper_class_init (GtkActionHelperClass *class)
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_action_helper_observer_iface_init (GActionObserverInterface *iface)
|
||||
gtk_action_helper_observer_iface_init (GtkActionObserverInterface *iface)
|
||||
{
|
||||
iface->action_added = gtk_action_helper_observer_action_added;
|
||||
iface->action_enabled_changed = gtk_action_helper_observer_action_enabled_changed;
|
||||
@@ -401,7 +401,7 @@ gtk_action_helper_active_window_changed (GObject *object,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkActionHelper *helper = user_data;
|
||||
GActionMuxer *parent;
|
||||
GtkActionMuxer *parent;
|
||||
|
||||
if (helper->widget)
|
||||
g_object_unref (helper->widget);
|
||||
@@ -415,11 +415,11 @@ gtk_action_helper_active_window_changed (GObject *object,
|
||||
}
|
||||
else
|
||||
{
|
||||
parent = g_action_muxer_new ();
|
||||
g_action_muxer_insert (parent, "app", G_ACTION_GROUP (helper->application));
|
||||
parent = gtk_action_muxer_new ();
|
||||
gtk_action_muxer_insert (parent, "app", G_ACTION_GROUP (helper->application));
|
||||
}
|
||||
|
||||
g_action_muxer_set_parent (helper->action_context, parent);
|
||||
gtk_action_muxer_set_parent (helper->action_context, parent);
|
||||
g_object_unref (parent);
|
||||
}
|
||||
|
||||
@@ -433,7 +433,7 @@ gtk_action_helper_new_with_application (GtkApplication *application)
|
||||
helper = g_object_new (GTK_TYPE_ACTION_HELPER, NULL);
|
||||
helper->application = g_object_ref (application);
|
||||
|
||||
helper->action_context = g_action_muxer_new ();
|
||||
helper->action_context = gtk_action_muxer_new ();
|
||||
g_signal_connect (application, "notify::active-window", G_CALLBACK (gtk_action_helper_active_window_changed), helper);
|
||||
gtk_action_helper_active_window_changed (NULL, NULL, helper);
|
||||
|
||||
@@ -455,17 +455,17 @@ gtk_action_helper_set_action_name (GtkActionHelper *helper,
|
||||
|
||||
if (helper->action_name)
|
||||
{
|
||||
g_action_observable_unregister_observer (G_ACTION_OBSERVABLE (helper->action_context),
|
||||
helper->action_name,
|
||||
G_ACTION_OBSERVER (helper));
|
||||
gtk_action_observable_unregister_observer (GTK_ACTION_OBSERVABLE (helper->action_context),
|
||||
helper->action_name,
|
||||
GTK_ACTION_OBSERVER (helper));
|
||||
g_free (helper->action_name);
|
||||
}
|
||||
|
||||
helper->action_name = g_strdup (action_name);
|
||||
|
||||
g_action_observable_register_observer (G_ACTION_OBSERVABLE (helper->action_context),
|
||||
helper->action_name,
|
||||
G_ACTION_OBSERVER (helper));
|
||||
gtk_action_observable_register_observer (GTK_ACTION_OBSERVABLE (helper->action_context),
|
||||
helper->action_name,
|
||||
GTK_ACTION_OBSERVER (helper));
|
||||
|
||||
/* Start by recording the current state of our properties so we know
|
||||
* what notify signals we will need to send.
|
||||
|
@@ -19,18 +19,18 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gactionmuxer.h"
|
||||
#include "gtkactionmuxer.h"
|
||||
|
||||
#include "gactionobservable.h"
|
||||
#include "gactionobserver.h"
|
||||
#include "gtkactionobservable.h"
|
||||
#include "gtkactionobserver.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* SECTION:gactionmuxer
|
||||
/**
|
||||
* SECTION:gtkactionmuxer
|
||||
* @short_description: Aggregate and monitor several action groups
|
||||
*
|
||||
* #GActionMuxer is a #GActionGroup and #GActionObservable that is
|
||||
* #GtkActionMuxer is a #GActionGroup and #GtkActionObservable that is
|
||||
* capable of containing other #GActionGroup instances.
|
||||
*
|
||||
* The typical use is aggregating all of the actions applicable to a
|
||||
@@ -42,11 +42,11 @@
|
||||
* application (such as 'fullscreen').
|
||||
*
|
||||
* In this case, each of these action groups could be added to a
|
||||
* #GActionMuxer with the prefixes "app" and "win", respectively. This
|
||||
* #GtkActionMuxer with the prefixes "app" and "win", respectively. This
|
||||
* would expose the actions as "app.quit" and "win.fullscreen" on the
|
||||
* #GActionGroup interface presented by the #GActionMuxer.
|
||||
* #GActionGroup interface presented by the #GtkActionMuxer.
|
||||
*
|
||||
* Activations and state change requests on the #GActionMuxer are wired
|
||||
* Activations and state change requests on the #GtkActionMuxer are wired
|
||||
* through to the underlying action group in the expected way.
|
||||
*
|
||||
* This class is typically only used at the site of "consumption" of
|
||||
@@ -54,23 +54,23 @@
|
||||
* different objects).
|
||||
*/
|
||||
|
||||
static void g_action_muxer_group_iface_init (GActionGroupInterface *iface);
|
||||
static void g_action_muxer_observable_iface_init (GActionObservableInterface *iface);
|
||||
static void gtk_action_muxer_group_iface_init (GActionGroupInterface *iface);
|
||||
static void gtk_action_muxer_observable_iface_init (GtkActionObservableInterface *iface);
|
||||
|
||||
typedef GObjectClass GActionMuxerClass;
|
||||
typedef GObjectClass GtkActionMuxerClass;
|
||||
|
||||
struct _GActionMuxer
|
||||
struct _GtkActionMuxer
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GHashTable *observed_actions;
|
||||
GHashTable *groups;
|
||||
GActionMuxer *parent;
|
||||
GtkActionMuxer *parent;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GActionMuxer, g_action_muxer, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP, g_action_muxer_group_iface_init)
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_OBSERVABLE, g_action_muxer_observable_iface_init))
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkActionMuxer, gtk_action_muxer, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP, gtk_action_muxer_group_iface_init)
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTION_OBSERVABLE, gtk_action_muxer_observable_iface_init))
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -83,23 +83,23 @@ static GParamSpec *properties[NUM_PROPERTIES];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GActionMuxer *muxer;
|
||||
GtkActionMuxer *muxer;
|
||||
GSList *watchers;
|
||||
gchar *fullname;
|
||||
} Action;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GActionMuxer *muxer;
|
||||
GtkActionMuxer *muxer;
|
||||
GActionGroup *group;
|
||||
gchar *prefix;
|
||||
gulong handler_ids[4];
|
||||
} Group;
|
||||
|
||||
static void
|
||||
g_action_muxer_append_group_actions (gpointer key,
|
||||
gpointer value,
|
||||
gpointer user_data)
|
||||
gtk_action_muxer_append_group_actions (gpointer key,
|
||||
gpointer value,
|
||||
gpointer user_data)
|
||||
{
|
||||
const gchar *prefix = key;
|
||||
Group *group = value;
|
||||
@@ -120,9 +120,9 @@ g_action_muxer_append_group_actions (gpointer key,
|
||||
}
|
||||
|
||||
static gchar **
|
||||
g_action_muxer_list_actions (GActionGroup *action_group)
|
||||
gtk_action_muxer_list_actions (GActionGroup *action_group)
|
||||
{
|
||||
GActionMuxer *muxer = G_ACTION_MUXER (action_group);
|
||||
GtkActionMuxer *muxer = GTK_ACTION_MUXER (action_group);
|
||||
GArray *actions;
|
||||
|
||||
actions = g_array_new (TRUE, FALSE, sizeof (gchar *));
|
||||
@@ -130,7 +130,7 @@ g_action_muxer_list_actions (GActionGroup *action_group)
|
||||
for ( ; muxer != NULL; muxer = muxer->parent)
|
||||
{
|
||||
g_hash_table_foreach (muxer->groups,
|
||||
g_action_muxer_append_group_actions,
|
||||
gtk_action_muxer_append_group_actions,
|
||||
actions);
|
||||
}
|
||||
|
||||
@@ -138,9 +138,9 @@ g_action_muxer_list_actions (GActionGroup *action_group)
|
||||
}
|
||||
|
||||
static Group *
|
||||
g_action_muxer_find_group (GActionMuxer *muxer,
|
||||
const gchar *full_name,
|
||||
const gchar **action_name)
|
||||
gtk_action_muxer_find_group (GtkActionMuxer *muxer,
|
||||
const gchar *full_name,
|
||||
const gchar **action_name)
|
||||
{
|
||||
const gchar *dot;
|
||||
gchar *prefix;
|
||||
@@ -162,90 +162,90 @@ g_action_muxer_find_group (GActionMuxer *muxer,
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_action_enabled_changed (GActionMuxer *muxer,
|
||||
const gchar *action_name,
|
||||
gboolean enabled)
|
||||
gtk_action_muxer_action_enabled_changed (GtkActionMuxer *muxer,
|
||||
const gchar *action_name,
|
||||
gboolean enabled)
|
||||
{
|
||||
Action *action;
|
||||
GSList *node;
|
||||
|
||||
action = g_hash_table_lookup (muxer->observed_actions, action_name);
|
||||
for (node = action ? action->watchers : NULL; node; node = node->next)
|
||||
g_action_observer_action_enabled_changed (node->data, G_ACTION_OBSERVABLE (muxer), action_name, enabled);
|
||||
gtk_action_observer_action_enabled_changed (node->data, GTK_ACTION_OBSERVABLE (muxer), action_name, enabled);
|
||||
g_action_group_action_enabled_changed (G_ACTION_GROUP (muxer), action_name, enabled);
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_group_action_enabled_changed (GActionGroup *action_group,
|
||||
gtk_action_muxer_group_action_enabled_changed (GActionGroup *action_group,
|
||||
const gchar *action_name,
|
||||
gboolean enabled,
|
||||
gpointer user_data)
|
||||
{
|
||||
Group *group = user_data;
|
||||
gchar *fullname;
|
||||
|
||||
fullname = g_strconcat (group->prefix, ".", action_name, NULL);
|
||||
gtk_action_muxer_action_enabled_changed (group->muxer, fullname, enabled);
|
||||
|
||||
g_free (fullname);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_action_muxer_parent_action_enabled_changed (GActionGroup *action_group,
|
||||
const gchar *action_name,
|
||||
gboolean enabled,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkActionMuxer *muxer = user_data;
|
||||
|
||||
gtk_action_muxer_action_enabled_changed (muxer, action_name, enabled);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_action_muxer_action_state_changed (GtkActionMuxer *muxer,
|
||||
const gchar *action_name,
|
||||
GVariant *state)
|
||||
{
|
||||
Action *action;
|
||||
GSList *node;
|
||||
|
||||
action = g_hash_table_lookup (muxer->observed_actions, action_name);
|
||||
for (node = action ? action->watchers : NULL; node; node = node->next)
|
||||
gtk_action_observer_action_state_changed (node->data, GTK_ACTION_OBSERVABLE (muxer), action_name, state);
|
||||
g_action_group_action_state_changed (G_ACTION_GROUP (muxer), action_name, state);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_action_muxer_group_action_state_changed (GActionGroup *action_group,
|
||||
const gchar *action_name,
|
||||
gboolean enabled,
|
||||
GVariant *state,
|
||||
gpointer user_data)
|
||||
{
|
||||
Group *group = user_data;
|
||||
gchar *fullname;
|
||||
|
||||
fullname = g_strconcat (group->prefix, ".", action_name, NULL);
|
||||
g_action_muxer_action_enabled_changed (group->muxer, fullname, enabled);
|
||||
gtk_action_muxer_action_state_changed (group->muxer, fullname, state);
|
||||
|
||||
g_free (fullname);
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_parent_action_enabled_changed (GActionGroup *action_group,
|
||||
gtk_action_muxer_parent_action_state_changed (GActionGroup *action_group,
|
||||
const gchar *action_name,
|
||||
gboolean enabled,
|
||||
GVariant *state,
|
||||
gpointer user_data)
|
||||
{
|
||||
GActionMuxer *muxer = user_data;
|
||||
GtkActionMuxer *muxer = user_data;
|
||||
|
||||
g_action_muxer_action_enabled_changed (muxer, action_name, enabled);
|
||||
gtk_action_muxer_action_state_changed (muxer, action_name, state);
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_action_state_changed (GActionMuxer *muxer,
|
||||
const gchar *action_name,
|
||||
GVariant *state)
|
||||
{
|
||||
Action *action;
|
||||
GSList *node;
|
||||
|
||||
action = g_hash_table_lookup (muxer->observed_actions, action_name);
|
||||
for (node = action ? action->watchers : NULL; node; node = node->next)
|
||||
g_action_observer_action_state_changed (node->data, G_ACTION_OBSERVABLE (muxer), action_name, state);
|
||||
g_action_group_action_state_changed (G_ACTION_GROUP (muxer), action_name, state);
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_group_action_state_changed (GActionGroup *action_group,
|
||||
const gchar *action_name,
|
||||
GVariant *state,
|
||||
gpointer user_data)
|
||||
{
|
||||
Group *group = user_data;
|
||||
gchar *fullname;
|
||||
|
||||
fullname = g_strconcat (group->prefix, ".", action_name, NULL);
|
||||
g_action_muxer_action_state_changed (group->muxer, fullname, state);
|
||||
|
||||
g_free (fullname);
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_parent_action_state_changed (GActionGroup *action_group,
|
||||
const gchar *action_name,
|
||||
GVariant *state,
|
||||
gpointer user_data)
|
||||
{
|
||||
GActionMuxer *muxer = user_data;
|
||||
|
||||
g_action_muxer_action_state_changed (muxer, action_name, state);
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_action_added (GActionMuxer *muxer,
|
||||
const gchar *action_name,
|
||||
GActionGroup *original_group,
|
||||
const gchar *orignal_action_name)
|
||||
gtk_action_muxer_action_added (GtkActionMuxer *muxer,
|
||||
const gchar *action_name,
|
||||
GActionGroup *original_group,
|
||||
const gchar *orignal_action_name)
|
||||
{
|
||||
const GVariantType *parameter_type;
|
||||
gboolean enabled;
|
||||
@@ -261,8 +261,8 @@ g_action_muxer_action_added (GActionMuxer *muxer,
|
||||
GSList *node;
|
||||
|
||||
for (node = action->watchers; node; node = node->next)
|
||||
g_action_observer_action_added (node->data,
|
||||
G_ACTION_OBSERVABLE (muxer),
|
||||
gtk_action_observer_action_added (node->data,
|
||||
GTK_ACTION_OBSERVABLE (muxer),
|
||||
action_name, parameter_type, enabled, state);
|
||||
|
||||
if (state)
|
||||
@@ -273,80 +273,80 @@ g_action_muxer_action_added (GActionMuxer *muxer,
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_action_added_to_group (GActionGroup *action_group,
|
||||
const gchar *action_name,
|
||||
gpointer user_data)
|
||||
gtk_action_muxer_action_added_to_group (GActionGroup *action_group,
|
||||
const gchar *action_name,
|
||||
gpointer user_data)
|
||||
{
|
||||
Group *group = user_data;
|
||||
gchar *fullname;
|
||||
|
||||
fullname = g_strconcat (group->prefix, ".", action_name, NULL);
|
||||
g_action_muxer_action_added (group->muxer, fullname, action_group, action_name);
|
||||
gtk_action_muxer_action_added (group->muxer, fullname, action_group, action_name);
|
||||
|
||||
g_free (fullname);
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_action_added_to_parent (GActionGroup *action_group,
|
||||
const gchar *action_name,
|
||||
gpointer user_data)
|
||||
gtk_action_muxer_action_added_to_parent (GActionGroup *action_group,
|
||||
const gchar *action_name,
|
||||
gpointer user_data)
|
||||
{
|
||||
GActionMuxer *muxer = user_data;
|
||||
GtkActionMuxer *muxer = user_data;
|
||||
|
||||
g_action_muxer_action_added (muxer, action_name, action_group, action_name);
|
||||
gtk_action_muxer_action_added (muxer, action_name, action_group, action_name);
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_action_removed (GActionMuxer *muxer,
|
||||
const gchar *action_name)
|
||||
gtk_action_muxer_action_removed (GtkActionMuxer *muxer,
|
||||
const gchar *action_name)
|
||||
{
|
||||
Action *action;
|
||||
GSList *node;
|
||||
|
||||
action = g_hash_table_lookup (muxer->observed_actions, action_name);
|
||||
for (node = action ? action->watchers : NULL; node; node = node->next)
|
||||
g_action_observer_action_removed (node->data, G_ACTION_OBSERVABLE (muxer), action_name);
|
||||
gtk_action_observer_action_removed (node->data, GTK_ACTION_OBSERVABLE (muxer), action_name);
|
||||
g_action_group_action_removed (G_ACTION_GROUP (muxer), action_name);
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_action_removed_from_group (GActionGroup *action_group,
|
||||
const gchar *action_name,
|
||||
gpointer user_data)
|
||||
gtk_action_muxer_action_removed_from_group (GActionGroup *action_group,
|
||||
const gchar *action_name,
|
||||
gpointer user_data)
|
||||
{
|
||||
Group *group = user_data;
|
||||
gchar *fullname;
|
||||
|
||||
fullname = g_strconcat (group->prefix, ".", action_name, NULL);
|
||||
g_action_muxer_action_removed (group->muxer, fullname);
|
||||
gtk_action_muxer_action_removed (group->muxer, fullname);
|
||||
|
||||
g_free (fullname);
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_action_removed_from_parent (GActionGroup *action_group,
|
||||
const gchar *action_name,
|
||||
gpointer user_data)
|
||||
gtk_action_muxer_action_removed_from_parent (GActionGroup *action_group,
|
||||
const gchar *action_name,
|
||||
gpointer user_data)
|
||||
{
|
||||
GActionMuxer *muxer = user_data;
|
||||
GtkActionMuxer *muxer = user_data;
|
||||
|
||||
g_action_muxer_action_removed (muxer, action_name);
|
||||
gtk_action_muxer_action_removed (muxer, action_name);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
g_action_muxer_query_action (GActionGroup *action_group,
|
||||
const gchar *action_name,
|
||||
gboolean *enabled,
|
||||
const GVariantType **parameter_type,
|
||||
const GVariantType **state_type,
|
||||
GVariant **state_hint,
|
||||
GVariant **state)
|
||||
gtk_action_muxer_query_action (GActionGroup *action_group,
|
||||
const gchar *action_name,
|
||||
gboolean *enabled,
|
||||
const GVariantType **parameter_type,
|
||||
const GVariantType **state_type,
|
||||
GVariant **state_hint,
|
||||
GVariant **state)
|
||||
{
|
||||
GActionMuxer *muxer = G_ACTION_MUXER (action_group);
|
||||
GtkActionMuxer *muxer = GTK_ACTION_MUXER (action_group);
|
||||
Group *group;
|
||||
const gchar *unprefixed_name;
|
||||
|
||||
group = g_action_muxer_find_group (muxer, action_name, &unprefixed_name);
|
||||
group = gtk_action_muxer_find_group (muxer, action_name, &unprefixed_name);
|
||||
|
||||
if (group)
|
||||
return g_action_group_query_action (group->group, unprefixed_name, enabled,
|
||||
@@ -361,15 +361,15 @@ g_action_muxer_query_action (GActionGroup *action_group,
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_activate_action (GActionGroup *action_group,
|
||||
const gchar *action_name,
|
||||
GVariant *parameter)
|
||||
gtk_action_muxer_activate_action (GActionGroup *action_group,
|
||||
const gchar *action_name,
|
||||
GVariant *parameter)
|
||||
{
|
||||
GActionMuxer *muxer = G_ACTION_MUXER (action_group);
|
||||
GtkActionMuxer *muxer = GTK_ACTION_MUXER (action_group);
|
||||
Group *group;
|
||||
const gchar *unprefixed_name;
|
||||
|
||||
group = g_action_muxer_find_group (muxer, action_name, &unprefixed_name);
|
||||
group = gtk_action_muxer_find_group (muxer, action_name, &unprefixed_name);
|
||||
|
||||
if (group)
|
||||
g_action_group_activate_action (group->group, unprefixed_name, parameter);
|
||||
@@ -378,15 +378,15 @@ g_action_muxer_activate_action (GActionGroup *action_group,
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_change_action_state (GActionGroup *action_group,
|
||||
const gchar *action_name,
|
||||
GVariant *state)
|
||||
gtk_action_muxer_change_action_state (GActionGroup *action_group,
|
||||
const gchar *action_name,
|
||||
GVariant *state)
|
||||
{
|
||||
GActionMuxer *muxer = G_ACTION_MUXER (action_group);
|
||||
GtkActionMuxer *muxer = GTK_ACTION_MUXER (action_group);
|
||||
Group *group;
|
||||
const gchar *unprefixed_name;
|
||||
|
||||
group = g_action_muxer_find_group (muxer, action_name, &unprefixed_name);
|
||||
group = gtk_action_muxer_find_group (muxer, action_name, &unprefixed_name);
|
||||
|
||||
if (group)
|
||||
g_action_group_change_action_state (group->group, unprefixed_name, state);
|
||||
@@ -395,10 +395,10 @@ g_action_muxer_change_action_state (GActionGroup *action_group,
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_unregister_internal (Action *action,
|
||||
gpointer observer)
|
||||
gtk_action_muxer_unregister_internal (Action *action,
|
||||
gpointer observer)
|
||||
{
|
||||
GActionMuxer *muxer = action->muxer;
|
||||
GtkActionMuxer *muxer = action->muxer;
|
||||
GSList **ptr;
|
||||
|
||||
for (ptr = &action->watchers; *ptr; ptr = &(*ptr)->next)
|
||||
@@ -414,20 +414,20 @@ g_action_muxer_unregister_internal (Action *action,
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_weak_notify (gpointer data,
|
||||
GObject *where_the_object_was)
|
||||
gtk_action_muxer_weak_notify (gpointer data,
|
||||
GObject *where_the_object_was)
|
||||
{
|
||||
Action *action = data;
|
||||
|
||||
g_action_muxer_unregister_internal (action, where_the_object_was);
|
||||
gtk_action_muxer_unregister_internal (action, where_the_object_was);
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_register_observer (GActionObservable *observable,
|
||||
const gchar *name,
|
||||
GActionObserver *observer)
|
||||
gtk_action_muxer_register_observer (GtkActionObservable *observable,
|
||||
const gchar *name,
|
||||
GtkActionObserver *observer)
|
||||
{
|
||||
GActionMuxer *muxer = G_ACTION_MUXER (observable);
|
||||
GtkActionMuxer *muxer = GTK_ACTION_MUXER (observable);
|
||||
Action *action;
|
||||
|
||||
action = g_hash_table_lookup (muxer->observed_actions, name);
|
||||
@@ -443,24 +443,24 @@ g_action_muxer_register_observer (GActionObservable *observable,
|
||||
}
|
||||
|
||||
action->watchers = g_slist_prepend (action->watchers, observer);
|
||||
g_object_weak_ref (G_OBJECT (observer), g_action_muxer_weak_notify, action);
|
||||
g_object_weak_ref (G_OBJECT (observer), gtk_action_muxer_weak_notify, action);
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_unregister_observer (GActionObservable *observable,
|
||||
const gchar *name,
|
||||
GActionObserver *observer)
|
||||
gtk_action_muxer_unregister_observer (GtkActionObservable *observable,
|
||||
const gchar *name,
|
||||
GtkActionObserver *observer)
|
||||
{
|
||||
GActionMuxer *muxer = G_ACTION_MUXER (observable);
|
||||
GtkActionMuxer *muxer = GTK_ACTION_MUXER (observable);
|
||||
Action *action;
|
||||
|
||||
action = g_hash_table_lookup (muxer->observed_actions, name);
|
||||
g_object_weak_unref (G_OBJECT (observer), g_action_muxer_weak_notify, action);
|
||||
g_action_muxer_unregister_internal (action, observer);
|
||||
g_object_weak_unref (G_OBJECT (observer), gtk_action_muxer_weak_notify, action);
|
||||
gtk_action_muxer_unregister_internal (action, observer);
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_free_group (gpointer data)
|
||||
gtk_action_muxer_free_group (gpointer data)
|
||||
{
|
||||
Group *group = data;
|
||||
gint i;
|
||||
@@ -476,13 +476,13 @@ g_action_muxer_free_group (gpointer data)
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_free_action (gpointer data)
|
||||
gtk_action_muxer_free_action (gpointer data)
|
||||
{
|
||||
Action *action = data;
|
||||
GSList *it;
|
||||
|
||||
for (it = action->watchers; it; it = it->next)
|
||||
g_object_weak_unref (G_OBJECT (it->data), g_action_muxer_weak_notify, action);
|
||||
g_object_weak_unref (G_OBJECT (it->data), gtk_action_muxer_weak_notify, action);
|
||||
|
||||
g_slist_free (action->watchers);
|
||||
g_free (action->fullname);
|
||||
@@ -491,51 +491,51 @@ g_action_muxer_free_action (gpointer data)
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_finalize (GObject *object)
|
||||
gtk_action_muxer_finalize (GObject *object)
|
||||
{
|
||||
GActionMuxer *muxer = G_ACTION_MUXER (object);
|
||||
GtkActionMuxer *muxer = GTK_ACTION_MUXER (object);
|
||||
|
||||
g_assert_cmpint (g_hash_table_size (muxer->observed_actions), ==, 0);
|
||||
g_hash_table_unref (muxer->observed_actions);
|
||||
g_hash_table_unref (muxer->groups);
|
||||
|
||||
G_OBJECT_CLASS (g_action_muxer_parent_class)
|
||||
G_OBJECT_CLASS (gtk_action_muxer_parent_class)
|
||||
->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_dispose (GObject *object)
|
||||
gtk_action_muxer_dispose (GObject *object)
|
||||
{
|
||||
GActionMuxer *muxer = G_ACTION_MUXER (object);
|
||||
GtkActionMuxer *muxer = GTK_ACTION_MUXER (object);
|
||||
|
||||
if (muxer->parent)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (muxer->parent, g_action_muxer_action_added_to_parent, muxer);
|
||||
g_signal_handlers_disconnect_by_func (muxer->parent, g_action_muxer_action_removed_from_parent, muxer);
|
||||
g_signal_handlers_disconnect_by_func (muxer->parent, g_action_muxer_parent_action_enabled_changed, muxer);
|
||||
g_signal_handlers_disconnect_by_func (muxer->parent, g_action_muxer_parent_action_state_changed, muxer);
|
||||
g_signal_handlers_disconnect_by_func (muxer->parent, gtk_action_muxer_action_added_to_parent, muxer);
|
||||
g_signal_handlers_disconnect_by_func (muxer->parent, gtk_action_muxer_action_removed_from_parent, muxer);
|
||||
g_signal_handlers_disconnect_by_func (muxer->parent, gtk_action_muxer_parent_action_enabled_changed, muxer);
|
||||
g_signal_handlers_disconnect_by_func (muxer->parent, gtk_action_muxer_parent_action_state_changed, muxer);
|
||||
|
||||
g_clear_object (&muxer->parent);
|
||||
}
|
||||
|
||||
g_hash_table_remove_all (muxer->observed_actions);
|
||||
|
||||
G_OBJECT_CLASS (g_action_muxer_parent_class)
|
||||
G_OBJECT_CLASS (gtk_action_muxer_parent_class)
|
||||
->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
gtk_action_muxer_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GActionMuxer *muxer = G_ACTION_MUXER (object);
|
||||
GtkActionMuxer *muxer = GTK_ACTION_MUXER (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_PARENT:
|
||||
g_value_set_object (value, g_action_muxer_get_parent (muxer));
|
||||
g_value_set_object (value, gtk_action_muxer_get_parent (muxer));
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -544,17 +544,17 @@ g_action_muxer_get_property (GObject *object,
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
gtk_action_muxer_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GActionMuxer *muxer = G_ACTION_MUXER (object);
|
||||
GtkActionMuxer *muxer = GTK_ACTION_MUXER (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_PARENT:
|
||||
g_action_muxer_set_parent (muxer, g_value_get_object (value));
|
||||
gtk_action_muxer_set_parent (muxer, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -563,48 +563,48 @@ g_action_muxer_set_property (GObject *object,
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_init (GActionMuxer *muxer)
|
||||
gtk_action_muxer_init (GtkActionMuxer *muxer)
|
||||
{
|
||||
muxer->observed_actions = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_action_muxer_free_action);
|
||||
muxer->groups = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_action_muxer_free_group);
|
||||
muxer->observed_actions = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, gtk_action_muxer_free_action);
|
||||
muxer->groups = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, gtk_action_muxer_free_group);
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_observable_iface_init (GActionObservableInterface *iface)
|
||||
gtk_action_muxer_observable_iface_init (GtkActionObservableInterface *iface)
|
||||
{
|
||||
iface->register_observer = g_action_muxer_register_observer;
|
||||
iface->unregister_observer = g_action_muxer_unregister_observer;
|
||||
iface->register_observer = gtk_action_muxer_register_observer;
|
||||
iface->unregister_observer = gtk_action_muxer_unregister_observer;
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_group_iface_init (GActionGroupInterface *iface)
|
||||
gtk_action_muxer_group_iface_init (GActionGroupInterface *iface)
|
||||
{
|
||||
iface->list_actions = g_action_muxer_list_actions;
|
||||
iface->query_action = g_action_muxer_query_action;
|
||||
iface->activate_action = g_action_muxer_activate_action;
|
||||
iface->change_action_state = g_action_muxer_change_action_state;
|
||||
iface->list_actions = gtk_action_muxer_list_actions;
|
||||
iface->query_action = gtk_action_muxer_query_action;
|
||||
iface->activate_action = gtk_action_muxer_activate_action;
|
||||
iface->change_action_state = gtk_action_muxer_change_action_state;
|
||||
}
|
||||
|
||||
static void
|
||||
g_action_muxer_class_init (GObjectClass *class)
|
||||
gtk_action_muxer_class_init (GObjectClass *class)
|
||||
{
|
||||
class->get_property = g_action_muxer_get_property;
|
||||
class->set_property = g_action_muxer_set_property;
|
||||
class->finalize = g_action_muxer_finalize;
|
||||
class->dispose = g_action_muxer_dispose;
|
||||
class->get_property = gtk_action_muxer_get_property;
|
||||
class->set_property = gtk_action_muxer_set_property;
|
||||
class->finalize = gtk_action_muxer_finalize;
|
||||
class->dispose = gtk_action_muxer_dispose;
|
||||
|
||||
properties[PROP_PARENT] = g_param_spec_object ("parent", "Parent",
|
||||
"The parent muxer",
|
||||
G_TYPE_ACTION_MUXER,
|
||||
GTK_TYPE_ACTION_MUXER,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (class, NUM_PROPERTIES, properties);
|
||||
}
|
||||
|
||||
/*
|
||||
* g_action_muxer_insert:
|
||||
* @muxer: a #GActionMuxer
|
||||
/**
|
||||
* gtk_action_muxer_insert:
|
||||
* @muxer: a #GtkActionMuxer
|
||||
* @prefix: the prefix string for the action group
|
||||
* @action_group: a #GActionGroup
|
||||
*
|
||||
@@ -617,22 +617,22 @@ g_action_muxer_class_init (GObjectClass *class)
|
||||
* contains an action called "<literal>quit</literal>", then @muxer will
|
||||
* now contain an action called "<literal>app.quit</literal>".
|
||||
*
|
||||
* If any #GActionObservers are registered for actions in the group,
|
||||
* If any #GtkActionObservers are registered for actions in the group,
|
||||
* "action_added" notifications will be emitted, as appropriate.
|
||||
*
|
||||
* @prefix must not contain a dot ('.').
|
||||
*/
|
||||
void
|
||||
g_action_muxer_insert (GActionMuxer *muxer,
|
||||
const gchar *prefix,
|
||||
GActionGroup *action_group)
|
||||
gtk_action_muxer_insert (GtkActionMuxer *muxer,
|
||||
const gchar *prefix,
|
||||
GActionGroup *action_group)
|
||||
{
|
||||
gchar **actions;
|
||||
Group *group;
|
||||
gint i;
|
||||
|
||||
/* TODO: diff instead of ripout and replace */
|
||||
g_action_muxer_remove (muxer, prefix);
|
||||
gtk_action_muxer_remove (muxer, prefix);
|
||||
|
||||
group = g_slice_new (Group);
|
||||
group->muxer = muxer;
|
||||
@@ -643,32 +643,32 @@ g_action_muxer_insert (GActionMuxer *muxer,
|
||||
|
||||
actions = g_action_group_list_actions (group->group);
|
||||
for (i = 0; actions[i]; i++)
|
||||
g_action_muxer_action_added_to_group (group->group, actions[i], group);
|
||||
gtk_action_muxer_action_added_to_group (group->group, actions[i], group);
|
||||
g_strfreev (actions);
|
||||
|
||||
group->handler_ids[0] = g_signal_connect (group->group, "action-added",
|
||||
G_CALLBACK (g_action_muxer_action_added_to_group), group);
|
||||
G_CALLBACK (gtk_action_muxer_action_added_to_group), group);
|
||||
group->handler_ids[1] = g_signal_connect (group->group, "action-removed",
|
||||
G_CALLBACK (g_action_muxer_action_removed_from_group), group);
|
||||
G_CALLBACK (gtk_action_muxer_action_removed_from_group), group);
|
||||
group->handler_ids[2] = g_signal_connect (group->group, "action-enabled-changed",
|
||||
G_CALLBACK (g_action_muxer_group_action_enabled_changed), group);
|
||||
G_CALLBACK (gtk_action_muxer_group_action_enabled_changed), group);
|
||||
group->handler_ids[3] = g_signal_connect (group->group, "action-state-changed",
|
||||
G_CALLBACK (g_action_muxer_group_action_state_changed), group);
|
||||
G_CALLBACK (gtk_action_muxer_group_action_state_changed), group);
|
||||
}
|
||||
|
||||
/*
|
||||
* g_action_muxer_remove:
|
||||
* @muxer: a #GActionMuxer
|
||||
/**
|
||||
* gtk_action_muxer_remove:
|
||||
* @muxer: a #GtkActionMuxer
|
||||
* @prefix: the prefix of the action group to remove
|
||||
*
|
||||
* Removes a #GActionGroup from the #GActionMuxer.
|
||||
* Removes a #GActionGroup from the #GtkActionMuxer.
|
||||
*
|
||||
* If any #GActionObservers are registered for actions in the group,
|
||||
* If any #GtkActionObservers are registered for actions in the group,
|
||||
* "action_removed" notifications will be emitted, as appropriate.
|
||||
*/
|
||||
void
|
||||
g_action_muxer_remove (GActionMuxer *muxer,
|
||||
const gchar *prefix)
|
||||
gtk_action_muxer_remove (GtkActionMuxer *muxer,
|
||||
const gchar *prefix)
|
||||
{
|
||||
Group *group;
|
||||
|
||||
@@ -683,49 +683,51 @@ g_action_muxer_remove (GActionMuxer *muxer,
|
||||
|
||||
actions = g_action_group_list_actions (group->group);
|
||||
for (i = 0; actions[i]; i++)
|
||||
g_action_muxer_action_removed_from_group (group->group, actions[i], group);
|
||||
gtk_action_muxer_action_removed_from_group (group->group, actions[i], group);
|
||||
g_strfreev (actions);
|
||||
|
||||
g_action_muxer_free_group (group);
|
||||
gtk_action_muxer_free_group (group);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* g_action_muxer_new:
|
||||
/**
|
||||
* gtk_action_muxer_new:
|
||||
*
|
||||
* Creates a new #GActionMuxer.
|
||||
* Creates a new #GtkActionMuxer.
|
||||
*/
|
||||
GActionMuxer *
|
||||
g_action_muxer_new (void)
|
||||
GtkActionMuxer *
|
||||
gtk_action_muxer_new (void)
|
||||
{
|
||||
return g_object_new (G_TYPE_ACTION_MUXER, NULL);
|
||||
return g_object_new (GTK_TYPE_ACTION_MUXER, NULL);
|
||||
}
|
||||
|
||||
/* g_action_muxer_get_parent:
|
||||
* @muxer: a #GActionMuxer
|
||||
/**
|
||||
* gtk_action_muxer_get_parent:
|
||||
* @muxer: a #GtkActionMuxer
|
||||
*
|
||||
* Returns: (transfer-none): the parent of @muxer, or NULL.
|
||||
* Returns: (transfer none): the parent of @muxer, or NULL.
|
||||
*/
|
||||
GActionMuxer *
|
||||
g_action_muxer_get_parent (GActionMuxer *muxer)
|
||||
GtkActionMuxer *
|
||||
gtk_action_muxer_get_parent (GtkActionMuxer *muxer)
|
||||
{
|
||||
g_return_val_if_fail (G_IS_ACTION_MUXER (muxer), NULL);
|
||||
g_return_val_if_fail (GTK_IS_ACTION_MUXER (muxer), NULL);
|
||||
|
||||
return muxer->parent;
|
||||
}
|
||||
|
||||
/* g_action_muxer_set_parent:
|
||||
* @muxer: a #GActionMuxer
|
||||
* @parent: (allow-none): the new parent #GActionMuxer
|
||||
/**
|
||||
* gtk_action_muxer_set_parent:
|
||||
* @muxer: a #GtkActionMuxer
|
||||
* @parent: (allow-none): the new parent #GtkActionMuxer
|
||||
*
|
||||
* Sets the parent of @muxer to @parent.
|
||||
*/
|
||||
void
|
||||
g_action_muxer_set_parent (GActionMuxer *muxer,
|
||||
GActionMuxer *parent)
|
||||
gtk_action_muxer_set_parent (GtkActionMuxer *muxer,
|
||||
GtkActionMuxer *parent)
|
||||
{
|
||||
g_return_if_fail (G_IS_ACTION_MUXER (muxer));
|
||||
g_return_if_fail (parent == NULL || G_IS_ACTION_MUXER (parent));
|
||||
g_return_if_fail (GTK_IS_ACTION_MUXER (muxer));
|
||||
g_return_if_fail (parent == NULL || GTK_IS_ACTION_MUXER (parent));
|
||||
|
||||
if (muxer->parent == parent)
|
||||
return;
|
||||
@@ -737,13 +739,13 @@ g_action_muxer_set_parent (GActionMuxer *muxer,
|
||||
|
||||
actions = g_action_group_list_actions (G_ACTION_GROUP (muxer->parent));
|
||||
for (it = actions; *it; it++)
|
||||
g_action_muxer_action_removed (muxer, *it);
|
||||
gtk_action_muxer_action_removed (muxer, *it);
|
||||
g_strfreev (actions);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (muxer->parent, g_action_muxer_action_added_to_parent, muxer);
|
||||
g_signal_handlers_disconnect_by_func (muxer->parent, g_action_muxer_action_removed_from_parent, muxer);
|
||||
g_signal_handlers_disconnect_by_func (muxer->parent, g_action_muxer_parent_action_enabled_changed, muxer);
|
||||
g_signal_handlers_disconnect_by_func (muxer->parent, g_action_muxer_parent_action_state_changed, muxer);
|
||||
g_signal_handlers_disconnect_by_func (muxer->parent, gtk_action_muxer_action_added_to_parent, muxer);
|
||||
g_signal_handlers_disconnect_by_func (muxer->parent, gtk_action_muxer_action_removed_from_parent, muxer);
|
||||
g_signal_handlers_disconnect_by_func (muxer->parent, gtk_action_muxer_parent_action_enabled_changed, muxer);
|
||||
g_signal_handlers_disconnect_by_func (muxer->parent, gtk_action_muxer_parent_action_state_changed, muxer);
|
||||
|
||||
g_object_unref (muxer->parent);
|
||||
}
|
||||
@@ -759,17 +761,17 @@ g_action_muxer_set_parent (GActionMuxer *muxer,
|
||||
|
||||
actions = g_action_group_list_actions (G_ACTION_GROUP (muxer->parent));
|
||||
for (it = actions; *it; it++)
|
||||
g_action_muxer_action_added (muxer, *it, G_ACTION_GROUP (muxer->parent), *it);
|
||||
gtk_action_muxer_action_added (muxer, *it, G_ACTION_GROUP (muxer->parent), *it);
|
||||
g_strfreev (actions);
|
||||
|
||||
g_signal_connect (muxer->parent, "action-added",
|
||||
G_CALLBACK (g_action_muxer_action_added_to_parent), muxer);
|
||||
G_CALLBACK (gtk_action_muxer_action_added_to_parent), muxer);
|
||||
g_signal_connect (muxer->parent, "action-removed",
|
||||
G_CALLBACK (g_action_muxer_action_removed_from_parent), muxer);
|
||||
G_CALLBACK (gtk_action_muxer_action_removed_from_parent), muxer);
|
||||
g_signal_connect (muxer->parent, "action-enabled-changed",
|
||||
G_CALLBACK (g_action_muxer_parent_action_enabled_changed), muxer);
|
||||
G_CALLBACK (gtk_action_muxer_parent_action_enabled_changed), muxer);
|
||||
g_signal_connect (muxer->parent, "action-state-changed",
|
||||
G_CALLBACK (g_action_muxer_parent_action_state_changed), muxer);
|
||||
G_CALLBACK (gtk_action_muxer_parent_action_state_changed), muxer);
|
||||
}
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (muxer), properties[PROP_PARENT]);
|
52
gtk/gtkactionmuxer.h
Normal file
52
gtk/gtkactionmuxer.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright © 2011 Canonical Limited
|
||||
*
|
||||
* This library 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author: Ryan Lortie <desrt@desrt.ca>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_ACTION_MUXER_H__
|
||||
#define __GTK_ACTION_MUXER_H__
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_ACTION_MUXER (gtk_action_muxer_get_type ())
|
||||
#define GTK_ACTION_MUXER(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
|
||||
GTK_TYPE_ACTION_MUXER, GtkActionMuxer))
|
||||
#define GTK_IS_ACTION_MUXER(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
|
||||
GTK_TYPE_ACTION_MUXER))
|
||||
|
||||
typedef struct _GtkActionMuxer GtkActionMuxer;
|
||||
|
||||
GType gtk_action_muxer_get_type (void);
|
||||
GtkActionMuxer * gtk_action_muxer_new (void);
|
||||
|
||||
void gtk_action_muxer_insert (GtkActionMuxer *muxer,
|
||||
const gchar *prefix,
|
||||
GActionGroup *action_group);
|
||||
|
||||
void gtk_action_muxer_remove (GtkActionMuxer *muxer,
|
||||
const gchar *prefix);
|
||||
|
||||
GtkActionMuxer * gtk_action_muxer_get_parent (GtkActionMuxer *muxer);
|
||||
|
||||
void gtk_action_muxer_set_parent (GtkActionMuxer *muxer,
|
||||
GtkActionMuxer *parent);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_ACTION_MUXER_H__ */
|
@@ -19,46 +19,46 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gactionobservable.h"
|
||||
#include "gtkactionobservable.h"
|
||||
|
||||
G_DEFINE_INTERFACE (GActionObservable, g_action_observable, G_TYPE_OBJECT)
|
||||
G_DEFINE_INTERFACE (GtkActionObservable, gtk_action_observable, G_TYPE_OBJECT)
|
||||
|
||||
/*
|
||||
* SECTION:gactionobserable
|
||||
* SECTION:gtkactionobserable
|
||||
* @short_description: an interface implemented by objects that report
|
||||
* changes to actions
|
||||
*/
|
||||
|
||||
void
|
||||
g_action_observable_default_init (GActionObservableInterface *iface)
|
||||
gtk_action_observable_default_init (GtkActionObservableInterface *iface)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* g_action_observable_register_observer:
|
||||
* @observable: a #GActionObservable
|
||||
/**
|
||||
* gtk_action_observable_register_observer:
|
||||
* @observable: a #GtkActionObservable
|
||||
* @action_name: the name of the action
|
||||
* @observer: the #GActionObserver to which the events will be reported
|
||||
* @observer: the #GtkActionObserver to which the events will be reported
|
||||
*
|
||||
* Registers @observer as being interested in changes to @action_name on
|
||||
* @observable.
|
||||
*/
|
||||
void
|
||||
g_action_observable_register_observer (GActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
GActionObserver *observer)
|
||||
gtk_action_observable_register_observer (GtkActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
GtkActionObserver *observer)
|
||||
{
|
||||
g_return_if_fail (G_IS_ACTION_OBSERVABLE (observable));
|
||||
g_return_if_fail (GTK_IS_ACTION_OBSERVABLE (observable));
|
||||
|
||||
G_ACTION_OBSERVABLE_GET_IFACE (observable)
|
||||
GTK_ACTION_OBSERVABLE_GET_IFACE (observable)
|
||||
->register_observer (observable, action_name, observer);
|
||||
}
|
||||
|
||||
/*
|
||||
* g_action_observable_unregister_observer:
|
||||
* @observable: a #GActionObservable
|
||||
/**
|
||||
* gtk_action_observable_unregister_observer:
|
||||
* @observable: a #GtkActionObservable
|
||||
* @action_name: the name of the action
|
||||
* @observer: the #GActionObserver to which the events will be reported
|
||||
* @observer: the #GtkActionObserver to which the events will be reported
|
||||
*
|
||||
* Removes the registration of @observer as being interested in changes
|
||||
* to @action_name on @observable.
|
||||
@@ -67,12 +67,12 @@ g_action_observable_register_observer (GActionObservable *observable,
|
||||
* unregistered an equal number of times.
|
||||
*/
|
||||
void
|
||||
g_action_observable_unregister_observer (GActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
GActionObserver *observer)
|
||||
gtk_action_observable_unregister_observer (GtkActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
GtkActionObserver *observer)
|
||||
{
|
||||
g_return_if_fail (G_IS_ACTION_OBSERVABLE (observable));
|
||||
g_return_if_fail (GTK_IS_ACTION_OBSERVABLE (observable));
|
||||
|
||||
G_ACTION_OBSERVABLE_GET_IFACE (observable)
|
||||
GTK_ACTION_OBSERVABLE_GET_IFACE (observable)
|
||||
->unregister_observer (observable, action_name, observer);
|
||||
}
|
60
gtk/gtkactionobservable.h
Normal file
60
gtk/gtkactionobservable.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright © 2011 Canonical Limited
|
||||
*
|
||||
* This library 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Ryan Lortie <desrt@desrt.ca>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_ACTION_OBSERVABLE_H__
|
||||
#define __GTK_ACTION_OBSERVABLE_H__
|
||||
|
||||
#include "gtkactionobserver.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_ACTION_OBSERVABLE (gtk_action_observable_get_type ())
|
||||
#define GTK_ACTION_OBSERVABLE(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
|
||||
GTK_TYPE_ACTION_OBSERVABLE, GtkActionObservable))
|
||||
#define GTK_IS_ACTION_OBSERVABLE(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
|
||||
GTK_TYPE_ACTION_OBSERVABLE))
|
||||
#define GTK_ACTION_OBSERVABLE_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), \
|
||||
GTK_TYPE_ACTION_OBSERVABLE, \
|
||||
GtkActionObservableInterface))
|
||||
|
||||
typedef struct _GtkActionObservableInterface GtkActionObservableInterface;
|
||||
|
||||
struct _GtkActionObservableInterface
|
||||
{
|
||||
GTypeInterface g_iface;
|
||||
|
||||
void (* register_observer) (GtkActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
GtkActionObserver *observer);
|
||||
void (* unregister_observer) (GtkActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
GtkActionObserver *observer);
|
||||
};
|
||||
|
||||
GType gtk_action_observable_get_type (void);
|
||||
void gtk_action_observable_register_observer (GtkActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
GtkActionObserver *observer);
|
||||
void gtk_action_observable_unregister_observer (GtkActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
GtkActionObserver *observer);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_ACTION_OBSERVABLE_H__ */
|
@@ -19,16 +19,16 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gactionobserver.h"
|
||||
#include "gtkactionobserver.h"
|
||||
|
||||
G_DEFINE_INTERFACE (GActionObserver, g_action_observer, G_TYPE_OBJECT)
|
||||
G_DEFINE_INTERFACE (GtkActionObserver, gtk_action_observer, G_TYPE_OBJECT)
|
||||
|
||||
/**
|
||||
* SECTION:gactionobserver
|
||||
* SECTION:gtkactionobserver
|
||||
* @short_description: an interface implemented by objects that are
|
||||
* interested in monitoring actions for changes
|
||||
*
|
||||
* GActionObserver is a simple interface allowing objects that wish to
|
||||
* GtkActionObserver is a simple interface allowing objects that wish to
|
||||
* be notified of changes to actions to be notified of those changes.
|
||||
*
|
||||
* It is also possible to monitor changes to action groups using
|
||||
@@ -50,13 +50,13 @@ G_DEFINE_INTERFACE (GActionObserver, g_action_observer, G_TYPE_OBJECT)
|
||||
*/
|
||||
|
||||
void
|
||||
g_action_observer_default_init (GActionObserverInterface *class)
|
||||
gtk_action_observer_default_init (GtkActionObserverInterface *class)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* g_action_observer_action_added:
|
||||
* @observer: a #GActionObserver
|
||||
/**
|
||||
* gtk_action_observer_action_added:
|
||||
* @observer: a #GtkActionObserver
|
||||
* @observable: the source of the event
|
||||
* @action_name: the name of the action
|
||||
* @enabled: %TRUE if the action is now enabled
|
||||
@@ -72,22 +72,22 @@ g_action_observer_default_init (GActionObserverInterface *class)
|
||||
* observer has explicitly registered itself to receive events.
|
||||
*/
|
||||
void
|
||||
g_action_observer_action_added (GActionObserver *observer,
|
||||
GActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
const GVariantType *parameter_type,
|
||||
gboolean enabled,
|
||||
GVariant *state)
|
||||
gtk_action_observer_action_added (GtkActionObserver *observer,
|
||||
GtkActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
const GVariantType *parameter_type,
|
||||
gboolean enabled,
|
||||
GVariant *state)
|
||||
{
|
||||
g_return_if_fail (G_IS_ACTION_OBSERVER (observer));
|
||||
g_return_if_fail (GTK_IS_ACTION_OBSERVER (observer));
|
||||
|
||||
G_ACTION_OBSERVER_GET_IFACE (observer)
|
||||
GTK_ACTION_OBSERVER_GET_IFACE (observer)
|
||||
->action_added (observer, observable, action_name, parameter_type, enabled, state);
|
||||
}
|
||||
|
||||
/*
|
||||
* g_action_observer_action_enabled_changed:
|
||||
* @observer: a #GActionObserver
|
||||
/**
|
||||
* gtk_action_observer_action_enabled_changed:
|
||||
* @observer: a #GtkActionObserver
|
||||
* @observable: the source of the event
|
||||
* @action_name: the name of the action
|
||||
* @enabled: %TRUE if the action is now enabled
|
||||
@@ -99,20 +99,20 @@ g_action_observer_action_added (GActionObserver *observer,
|
||||
* observer has explicitly registered itself to receive events.
|
||||
*/
|
||||
void
|
||||
g_action_observer_action_enabled_changed (GActionObserver *observer,
|
||||
GActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
gboolean enabled)
|
||||
gtk_action_observer_action_enabled_changed (GtkActionObserver *observer,
|
||||
GtkActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
gboolean enabled)
|
||||
{
|
||||
g_return_if_fail (G_IS_ACTION_OBSERVER (observer));
|
||||
g_return_if_fail (GTK_IS_ACTION_OBSERVER (observer));
|
||||
|
||||
G_ACTION_OBSERVER_GET_IFACE (observer)
|
||||
GTK_ACTION_OBSERVER_GET_IFACE (observer)
|
||||
->action_enabled_changed (observer, observable, action_name, enabled);
|
||||
}
|
||||
|
||||
/*
|
||||
* g_action_observer_action_state_changed:
|
||||
* @observer: a #GActionObserver
|
||||
/**
|
||||
* gtk_action_observer_action_state_changed:
|
||||
* @observer: a #GtkActionObserver
|
||||
* @observable: the source of the event
|
||||
* @action_name: the name of the action
|
||||
* @state: the new state of the action
|
||||
@@ -124,20 +124,20 @@ g_action_observer_action_enabled_changed (GActionObserver *observer,
|
||||
* observer has explicitly registered itself to receive events.
|
||||
*/
|
||||
void
|
||||
g_action_observer_action_state_changed (GActionObserver *observer,
|
||||
GActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
GVariant *state)
|
||||
gtk_action_observer_action_state_changed (GtkActionObserver *observer,
|
||||
GtkActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
GVariant *state)
|
||||
{
|
||||
g_return_if_fail (G_IS_ACTION_OBSERVER (observer));
|
||||
g_return_if_fail (GTK_IS_ACTION_OBSERVER (observer));
|
||||
|
||||
G_ACTION_OBSERVER_GET_IFACE (observer)
|
||||
GTK_ACTION_OBSERVER_GET_IFACE (observer)
|
||||
->action_state_changed (observer, observable, action_name, state);
|
||||
}
|
||||
|
||||
/*
|
||||
* g_action_observer_action_removed:
|
||||
* @observer: a #GActionObserver
|
||||
/**
|
||||
* gtk_action_observer_action_removed:
|
||||
* @observer: a #GtkActionObserver
|
||||
* @observable: the source of the event
|
||||
* @action_name: the name of the action
|
||||
*
|
||||
@@ -148,12 +148,12 @@ g_action_observer_action_state_changed (GActionObserver *observer,
|
||||
* observer has explicitly registered itself to receive events.
|
||||
*/
|
||||
void
|
||||
g_action_observer_action_removed (GActionObserver *observer,
|
||||
GActionObservable *observable,
|
||||
const gchar *action_name)
|
||||
gtk_action_observer_action_removed (GtkActionObserver *observer,
|
||||
GtkActionObservable *observable,
|
||||
const gchar *action_name)
|
||||
{
|
||||
g_return_if_fail (G_IS_ACTION_OBSERVER (observer));
|
||||
g_return_if_fail (GTK_IS_ACTION_OBSERVER (observer));
|
||||
|
||||
G_ACTION_OBSERVER_GET_IFACE (observer)
|
||||
GTK_ACTION_OBSERVER_GET_IFACE (observer)
|
||||
->action_removed (observer, observable, action_name);
|
||||
}
|
83
gtk/gtkactionobserver.h
Normal file
83
gtk/gtkactionobserver.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright © 2011 Canonical Limited
|
||||
*
|
||||
* This library 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Ryan Lortie <desrt@desrt.ca>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_ACTION_OBSERVER_H__
|
||||
#define __GTK_ACTION_OBSERVER_H__
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_ACTION_OBSERVER (gtk_action_observer_get_type ())
|
||||
#define GTK_ACTION_OBSERVER(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
|
||||
GTK_TYPE_ACTION_OBSERVER, GtkActionObserver))
|
||||
#define GTK_IS_ACTION_OBSERVER(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
|
||||
GTK_TYPE_ACTION_OBSERVER))
|
||||
#define GTK_ACTION_OBSERVER_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), \
|
||||
GTK_TYPE_ACTION_OBSERVER, GtkActionObserverInterface))
|
||||
|
||||
typedef struct _GtkActionObserverInterface GtkActionObserverInterface;
|
||||
typedef struct _GtkActionObservable GtkActionObservable;
|
||||
typedef struct _GtkActionObserver GtkActionObserver;
|
||||
|
||||
struct _GtkActionObserverInterface
|
||||
{
|
||||
GTypeInterface g_iface;
|
||||
|
||||
void (* action_added) (GtkActionObserver *observer,
|
||||
GtkActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
const GVariantType *parameter_type,
|
||||
gboolean enabled,
|
||||
GVariant *state);
|
||||
void (* action_enabled_changed) (GtkActionObserver *observer,
|
||||
GtkActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
gboolean enabled);
|
||||
void (* action_state_changed) (GtkActionObserver *observer,
|
||||
GtkActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
GVariant *state);
|
||||
void (* action_removed) (GtkActionObserver *observer,
|
||||
GtkActionObservable *observable,
|
||||
const gchar *action_name);
|
||||
};
|
||||
|
||||
GType gtk_action_observer_get_type (void);
|
||||
void gtk_action_observer_action_added (GtkActionObserver *observer,
|
||||
GtkActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
const GVariantType *parameter_type,
|
||||
gboolean enabled,
|
||||
GVariant *state);
|
||||
void gtk_action_observer_action_enabled_changed (GtkActionObserver *observer,
|
||||
GtkActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
gboolean enabled);
|
||||
void gtk_action_observer_action_state_changed (GtkActionObserver *observer,
|
||||
GtkActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
GVariant *state);
|
||||
void gtk_action_observer_action_removed (GtkActionObserver *observer,
|
||||
GtkActionObservable *observable,
|
||||
const gchar *action_name);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_ACTION_OBSERVER_H__ */
|
@@ -52,6 +52,7 @@
|
||||
#include "gtkintl.h"
|
||||
#include "gtktypebuiltins.h"
|
||||
#include "gtkmodelmenuitem.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
|
||||
#include "deprecated/gtktearoffmenuitem.h"
|
||||
|
||||
@@ -2039,33 +2040,30 @@ gtk_menu_shell_get_parent_shell (GtkMenuShell *menu_shell)
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_shell_tracker_insert_func (gint position,
|
||||
GMenuModel *model,
|
||||
gint item_index,
|
||||
const gchar *action_namespace,
|
||||
gboolean is_separator,
|
||||
gpointer user_data)
|
||||
gtk_menu_shell_item_activate (GtkMenuItem *menuitem,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkMenuShell *menu_shell = user_data;
|
||||
GtkWidget *item;
|
||||
GtkMenuTrackerItem *item = user_data;
|
||||
|
||||
if (is_separator)
|
||||
{
|
||||
gchar *label;
|
||||
gtk_menu_tracker_item_activated (item);
|
||||
}
|
||||
|
||||
item = gtk_separator_menu_item_new ();
|
||||
static void
|
||||
gtk_menu_shell_submenu_shown (GtkWidget *submenu,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkMenuTrackerItem *item = user_data;
|
||||
|
||||
if (g_menu_model_get_item_attribute (model, item_index, G_MENU_ATTRIBUTE_LABEL, "s", &label))
|
||||
{
|
||||
gtk_menu_item_set_label (GTK_MENU_ITEM (item), label);
|
||||
g_free (label);
|
||||
}
|
||||
}
|
||||
else
|
||||
item = gtk_model_menu_item_new (model, item_index, action_namespace);
|
||||
gtk_menu_tracker_item_request_submenu_shown (item, TRUE);
|
||||
}
|
||||
|
||||
gtk_menu_shell_insert (menu_shell, item, position);
|
||||
gtk_widget_show (item);
|
||||
static void
|
||||
gtk_menu_shell_submenu_hidden (GtkWidget *submenu,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkMenuTrackerItem *item = user_data;
|
||||
|
||||
gtk_menu_tracker_item_request_submenu_shown (item, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2083,6 +2081,84 @@ gtk_menu_shell_tracker_remove_func (gint position,
|
||||
gtk_widget_destroy (child);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_shell_tracker_insert_func (GtkMenuTrackerItem *item,
|
||||
gint position,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkMenuShell *menu_shell = user_data;
|
||||
GtkWidget *widget;
|
||||
|
||||
if (gtk_menu_tracker_item_get_is_separator (item))
|
||||
{
|
||||
widget = gtk_separator_menu_item_new ();
|
||||
|
||||
/* For separators, we bind to the "label" property in case there
|
||||
* is a section heading.
|
||||
*/
|
||||
g_object_bind_property (item, "label", widget, "label", G_BINDING_SYNC_CREATE);
|
||||
}
|
||||
else if (gtk_menu_tracker_item_get_has_submenu (item))
|
||||
{
|
||||
GtkMenuShell *submenu;
|
||||
|
||||
widget = gtk_model_menu_item_new ();
|
||||
g_object_bind_property (item, "label", widget, "text", G_BINDING_SYNC_CREATE);
|
||||
|
||||
submenu = GTK_MENU_SHELL (gtk_menu_new ());
|
||||
|
||||
/* We recurse directly here: we could use an idle instead to
|
||||
* prevent arbitrary recursion depth. We could also do it
|
||||
* lazy...
|
||||
*/
|
||||
submenu->priv->tracker = gtk_menu_tracker_new_for_item_submenu (item,
|
||||
gtk_menu_shell_tracker_insert_func,
|
||||
gtk_menu_shell_tracker_remove_func,
|
||||
submenu);
|
||||
gtk_menu_item_set_submenu (GTK_MENU_ITEM (widget), GTK_WIDGET (submenu));
|
||||
|
||||
if (gtk_menu_tracker_item_get_should_request_show (item))
|
||||
{
|
||||
/* We don't request show in the strictest sense of the
|
||||
* word: we just notify when we are showing and don't
|
||||
* bother waiting for the reply.
|
||||
*
|
||||
* This could be fixed one day, but it would be slightly
|
||||
* complicated and would have a strange interaction with
|
||||
* the submenu pop-up delay.
|
||||
*
|
||||
* Note: 'item' is already kept alive from above.
|
||||
*/
|
||||
g_signal_connect (submenu, "show", G_CALLBACK (gtk_menu_shell_submenu_shown), item);
|
||||
g_signal_connect (submenu, "hide", G_CALLBACK (gtk_menu_shell_submenu_hidden), item);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
widget = gtk_model_menu_item_new ();
|
||||
|
||||
/* We bind to "text" instead of "label" because GtkModelMenuItem
|
||||
* uses this property (along with "icon") to control its child
|
||||
* widget. Once this is merged into GtkMenuItem we can go back to
|
||||
* using "label".
|
||||
*/
|
||||
g_object_bind_property (item, "label", widget, "text", G_BINDING_SYNC_CREATE);
|
||||
g_object_bind_property (item, "icon", widget, "icon", G_BINDING_SYNC_CREATE);
|
||||
g_object_bind_property (item, "sensitive", widget, "sensitive", G_BINDING_SYNC_CREATE);
|
||||
g_object_bind_property (item, "visible", widget, "visible", G_BINDING_SYNC_CREATE);
|
||||
g_object_bind_property (item, "role", widget, "action-role", G_BINDING_SYNC_CREATE);
|
||||
g_object_bind_property (item, "toggled", widget, "toggled", G_BINDING_SYNC_CREATE);
|
||||
g_object_bind_property (item, "accel", widget, "accel", G_BINDING_SYNC_CREATE);
|
||||
|
||||
g_signal_connect (widget, "activate", G_CALLBACK (gtk_menu_shell_item_activate), item);
|
||||
}
|
||||
|
||||
/* TODO: drop this when we have bindings that ref the source */
|
||||
g_object_set_data_full (G_OBJECT (widget), "GtkMenuTrackerItem", g_object_ref (item), g_object_unref);
|
||||
|
||||
gtk_menu_shell_insert (menu_shell, widget, position);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_menu_shell_bind_model:
|
||||
* @menu_shell: a #GtkMenuShell
|
||||
@@ -2134,16 +2210,21 @@ gtk_menu_shell_bind_model (GtkMenuShell *menu_shell,
|
||||
const gchar *action_namespace,
|
||||
gboolean with_separators)
|
||||
{
|
||||
GtkActionMuxer *muxer;
|
||||
|
||||
g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
|
||||
g_return_if_fail (model == NULL || G_IS_MENU_MODEL (model));
|
||||
|
||||
muxer = _gtk_widget_get_action_muxer (GTK_WIDGET (menu_shell));
|
||||
|
||||
g_clear_pointer (&menu_shell->priv->tracker, gtk_menu_tracker_free);
|
||||
|
||||
while (menu_shell->priv->children)
|
||||
gtk_container_remove (GTK_CONTAINER (menu_shell), menu_shell->priv->children->data);
|
||||
|
||||
if (model)
|
||||
menu_shell->priv->tracker = gtk_menu_tracker_new (model, with_separators, action_namespace,
|
||||
menu_shell->priv->tracker = gtk_menu_tracker_new (GTK_ACTION_OBSERVABLE (muxer),
|
||||
model, with_separators, action_namespace,
|
||||
gtk_menu_shell_tracker_insert_func,
|
||||
gtk_menu_shell_tracker_remove_func,
|
||||
menu_shell);
|
||||
|
@@ -27,6 +27,7 @@ typedef struct _GtkMenuTrackerSection GtkMenuTrackerSection;
|
||||
|
||||
struct _GtkMenuTracker
|
||||
{
|
||||
GtkActionObservable *observable;
|
||||
GtkMenuTrackerInsertFunc insert_func;
|
||||
GtkMenuTrackerRemoveFunc remove_func;
|
||||
gpointer user_data;
|
||||
@@ -159,7 +160,12 @@ gtk_menu_tracker_section_sync_separators (GtkMenuTrackerSection *section,
|
||||
if (should_have_separator > section->has_separator)
|
||||
{
|
||||
/* Add a separator */
|
||||
(* tracker->insert_func) (offset, parent_model, parent_index, NULL, TRUE, tracker->user_data);
|
||||
GtkMenuTrackerItem *item;
|
||||
|
||||
item = gtk_menu_tracker_item_new (tracker->observable, parent_model, parent_index, NULL, TRUE);
|
||||
(* tracker->insert_func) (item, offset, tracker->user_data);
|
||||
g_object_unref (item);
|
||||
|
||||
section->has_separator = TRUE;
|
||||
}
|
||||
else if (should_have_separator < section->has_separator)
|
||||
@@ -258,8 +264,13 @@ gtk_menu_tracker_add_items (GtkMenuTracker *tracker,
|
||||
}
|
||||
else
|
||||
{
|
||||
(* tracker->insert_func) (offset, model, position + n_items,
|
||||
section->action_namespace, FALSE, tracker->user_data);
|
||||
GtkMenuTrackerItem *item;
|
||||
|
||||
item = gtk_menu_tracker_item_new (tracker->observable, model, position + n_items,
|
||||
section->action_namespace, FALSE);
|
||||
(* tracker->insert_func) (item, offset, tracker->user_data);
|
||||
g_object_unref (item);
|
||||
|
||||
*change_point = g_slist_prepend (*change_point, NULL);
|
||||
}
|
||||
}
|
||||
@@ -400,7 +411,8 @@ gtk_menu_tracker_section_new (GtkMenuTracker *tracker,
|
||||
* gtk_menu_tracker_free() is called.
|
||||
*/
|
||||
GtkMenuTracker *
|
||||
gtk_menu_tracker_new (GMenuModel *model,
|
||||
gtk_menu_tracker_new (GtkActionObservable *observable,
|
||||
GMenuModel *model,
|
||||
gboolean with_separators,
|
||||
const gchar *action_namespace,
|
||||
GtkMenuTrackerInsertFunc insert_func,
|
||||
@@ -410,6 +422,7 @@ gtk_menu_tracker_new (GMenuModel *model,
|
||||
GtkMenuTracker *tracker;
|
||||
|
||||
tracker = g_slice_new (GtkMenuTracker);
|
||||
tracker->observable = g_object_ref (observable);
|
||||
tracker->insert_func = insert_func;
|
||||
tracker->remove_func = remove_func;
|
||||
tracker->user_data = user_data;
|
||||
@@ -420,6 +433,19 @@ gtk_menu_tracker_new (GMenuModel *model,
|
||||
return tracker;
|
||||
}
|
||||
|
||||
GtkMenuTracker *
|
||||
gtk_menu_tracker_new_for_item_submenu (GtkMenuTrackerItem *item,
|
||||
GtkMenuTrackerInsertFunc insert_func,
|
||||
GtkMenuTrackerRemoveFunc remove_func,
|
||||
gpointer user_data)
|
||||
{
|
||||
return gtk_menu_tracker_new (gtk_menu_tracker_item_get_observable (item),
|
||||
gtk_menu_tracker_item_get_submenu (item),
|
||||
TRUE,
|
||||
gtk_menu_tracker_item_get_submenu_namespace (item),
|
||||
insert_func, remove_func, user_data);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gtk_menu_tracker_free:
|
||||
* @tracker: a #GtkMenuTracker
|
||||
@@ -430,5 +456,6 @@ void
|
||||
gtk_menu_tracker_free (GtkMenuTracker *tracker)
|
||||
{
|
||||
gtk_menu_tracker_section_free (tracker->toplevel);
|
||||
g_object_unref (tracker->observable);
|
||||
g_slice_free (GtkMenuTracker, tracker);
|
||||
}
|
||||
|
@@ -22,30 +22,31 @@
|
||||
#ifndef __GTK_MENU_TRACKER_H__
|
||||
#define __GTK_MENU_TRACKER_H__
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include "gtkmenutrackeritem.h"
|
||||
|
||||
typedef struct _GtkMenuTracker GtkMenuTracker;
|
||||
|
||||
typedef void (* GtkMenuTrackerInsertFunc) (gint position,
|
||||
GMenuModel *model,
|
||||
gint item_index,
|
||||
const gchar *action_namespace,
|
||||
gboolean is_separator,
|
||||
gpointer user_data);
|
||||
typedef void (* GtkMenuTrackerInsertFunc) (GtkMenuTrackerItem *item,
|
||||
gint position,
|
||||
gpointer user_data);
|
||||
|
||||
typedef void (* GtkMenuTrackerRemoveFunc) (gint position,
|
||||
gpointer user_data);
|
||||
typedef void (* GtkMenuTrackerRemoveFunc) (gint position,
|
||||
gpointer user_data);
|
||||
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
GtkMenuTracker * gtk_menu_tracker_new (GMenuModel *model,
|
||||
gboolean with_separators,
|
||||
const gchar *action_namespace,
|
||||
GtkMenuTrackerInsertFunc insert_func,
|
||||
GtkMenuTrackerRemoveFunc remove_func,
|
||||
gpointer user_data);
|
||||
GtkMenuTracker * gtk_menu_tracker_new (GtkActionObservable *observer,
|
||||
GMenuModel *model,
|
||||
gboolean with_separators,
|
||||
const gchar *action_namespace,
|
||||
GtkMenuTrackerInsertFunc insert_func,
|
||||
GtkMenuTrackerRemoveFunc remove_func,
|
||||
gpointer user_data);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void gtk_menu_tracker_free (GtkMenuTracker *tracker);
|
||||
GtkMenuTracker * gtk_menu_tracker_new_for_item_submenu (GtkMenuTrackerItem *item,
|
||||
GtkMenuTrackerInsertFunc insert_func,
|
||||
GtkMenuTrackerRemoveFunc remove_func,
|
||||
gpointer user_data);
|
||||
|
||||
void gtk_menu_tracker_free (GtkMenuTracker *tracker);
|
||||
|
||||
#endif /* __GTK_MENU_TRACKER_H__ */
|
||||
|
715
gtk/gtkmenutrackeritem.c
Normal file
715
gtk/gtkmenutrackeritem.c
Normal file
@@ -0,0 +1,715 @@
|
||||
#include "gtkmenutrackeritem.h"
|
||||
|
||||
typedef GObjectClass GtkMenuTrackerItemClass;
|
||||
|
||||
struct _GtkMenuTrackerItem
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GtkActionObservable *observable;
|
||||
gchar *action_namespace;
|
||||
GMenuItem *item;
|
||||
GtkMenuTrackerItemRole role : 4;
|
||||
guint is_separator : 1;
|
||||
guint can_activate : 1;
|
||||
guint sensitive : 1;
|
||||
guint toggled : 1;
|
||||
guint submenu_shown : 1;
|
||||
guint submenu_requested : 1;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_IS_SEPARATOR,
|
||||
PROP_HAS_SUBMENU,
|
||||
PROP_LABEL,
|
||||
PROP_ICON,
|
||||
PROP_SENSITIVE,
|
||||
PROP_VISIBLE,
|
||||
PROP_ROLE,
|
||||
PROP_TOGGLED,
|
||||
PROP_ACCEL,
|
||||
PROP_SUBMENU,
|
||||
PROP_SUBMENU_NAMESPACE,
|
||||
PROP_SUBMENU_SHOWN,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
static GParamSpec *gtk_menu_tracker_item_pspecs[N_PROPS];
|
||||
|
||||
static void gtk_menu_tracker_item_init_observer_iface (GtkActionObserverInterface *iface);
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkMenuTrackerItem, gtk_menu_tracker_item, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTION_OBSERVER, gtk_menu_tracker_item_init_observer_iface))
|
||||
|
||||
GType
|
||||
gtk_menu_tracker_item_role_get_type (void)
|
||||
{
|
||||
static gsize gtk_menu_tracker_item_role_type;
|
||||
|
||||
if (g_once_init_enter (>k_menu_tracker_item_role_type))
|
||||
{
|
||||
static const GEnumValue values[] = {
|
||||
{ GTK_MENU_TRACKER_ITEM_ROLE_NORMAL, "GTK_MENU_TRACKER_ITEM_ROLE_NORMAL", "normal" },
|
||||
{ GTK_MENU_TRACKER_ITEM_ROLE_CHECK, "GTK_MENU_TRACKER_ITEM_ROLE_CHECK", "check" },
|
||||
{ GTK_MENU_TRACKER_ITEM_ROLE_RADIO, "GTK_MENU_TRACKER_ITEM_ROLE_RADIO", "radio" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
GType type;
|
||||
|
||||
type = g_enum_register_static ("GtkMenuTrackerItemRole", values);
|
||||
|
||||
g_once_init_leave (>k_menu_tracker_item_role_type, type);
|
||||
}
|
||||
|
||||
return gtk_menu_tracker_item_role_type;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_item_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkMenuTrackerItem *self = GTK_MENU_TRACKER_ITEM (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_IS_SEPARATOR:
|
||||
g_value_set_boolean (value, gtk_menu_tracker_item_get_is_separator (self));
|
||||
break;
|
||||
case PROP_HAS_SUBMENU:
|
||||
g_value_set_boolean (value, gtk_menu_tracker_item_get_has_submenu (self));
|
||||
break;
|
||||
case PROP_LABEL:
|
||||
g_value_set_string (value, gtk_menu_tracker_item_get_label (self));
|
||||
break;
|
||||
case PROP_ICON:
|
||||
g_value_set_object (value, gtk_menu_tracker_item_get_icon (self));
|
||||
break;
|
||||
case PROP_SENSITIVE:
|
||||
g_value_set_boolean (value, gtk_menu_tracker_item_get_sensitive (self));
|
||||
break;
|
||||
case PROP_VISIBLE:
|
||||
g_value_set_boolean (value, gtk_menu_tracker_item_get_visible (self));
|
||||
break;
|
||||
case PROP_ROLE:
|
||||
g_value_set_enum (value, gtk_menu_tracker_item_get_role (self));
|
||||
break;
|
||||
case PROP_TOGGLED:
|
||||
g_value_set_boolean (value, gtk_menu_tracker_item_get_toggled (self));
|
||||
break;
|
||||
case PROP_ACCEL:
|
||||
g_value_set_string (value, gtk_menu_tracker_item_get_accel (self));
|
||||
break;
|
||||
case PROP_SUBMENU:
|
||||
g_value_set_object (value, gtk_menu_tracker_item_get_submenu (self));
|
||||
break;
|
||||
case PROP_SUBMENU_NAMESPACE:
|
||||
g_value_set_string (value, gtk_menu_tracker_item_get_submenu_namespace (self));
|
||||
break;
|
||||
case PROP_SUBMENU_SHOWN:
|
||||
g_value_set_boolean (value, gtk_menu_tracker_item_get_submenu_shown (self));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_item_finalize (GObject *object)
|
||||
{
|
||||
GtkMenuTrackerItem *self = GTK_MENU_TRACKER_ITEM (object);
|
||||
|
||||
g_free (self->action_namespace);
|
||||
|
||||
if (self->observable)
|
||||
g_object_unref (self->observable);
|
||||
|
||||
g_object_unref (self->item);
|
||||
|
||||
G_OBJECT_CLASS (gtk_menu_tracker_item_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_item_init (GtkMenuTrackerItem * self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_item_class_init (GtkMenuTrackerItemClass *class)
|
||||
{
|
||||
class->get_property = gtk_menu_tracker_item_get_property;
|
||||
class->finalize = gtk_menu_tracker_item_finalize;
|
||||
|
||||
gtk_menu_tracker_item_pspecs[PROP_IS_SEPARATOR] =
|
||||
g_param_spec_boolean ("is-separator", "", "", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
|
||||
gtk_menu_tracker_item_pspecs[PROP_HAS_SUBMENU] =
|
||||
g_param_spec_boolean ("has-submenu", "", "", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
|
||||
gtk_menu_tracker_item_pspecs[PROP_LABEL] =
|
||||
g_param_spec_string ("label", "", "", NULL, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
|
||||
gtk_menu_tracker_item_pspecs[PROP_ICON] =
|
||||
g_param_spec_object ("icon", "", "", G_TYPE_ICON, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
|
||||
gtk_menu_tracker_item_pspecs[PROP_SENSITIVE] =
|
||||
g_param_spec_boolean ("sensitive", "", "", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
|
||||
gtk_menu_tracker_item_pspecs[PROP_VISIBLE] =
|
||||
g_param_spec_boolean ("visible", "", "", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
|
||||
gtk_menu_tracker_item_pspecs[PROP_ROLE] =
|
||||
g_param_spec_enum ("role", "", "",
|
||||
GTK_TYPE_MENU_TRACKER_ITEM_ROLE, GTK_MENU_TRACKER_ITEM_ROLE_NORMAL,
|
||||
G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
|
||||
gtk_menu_tracker_item_pspecs[PROP_TOGGLED] =
|
||||
g_param_spec_boolean ("toggled", "", "", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
|
||||
gtk_menu_tracker_item_pspecs[PROP_ACCEL] =
|
||||
g_param_spec_string ("accel", "", "", NULL, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
|
||||
gtk_menu_tracker_item_pspecs[PROP_SUBMENU] =
|
||||
g_param_spec_object ("submenu", "", "", G_TYPE_MENU_MODEL, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
|
||||
gtk_menu_tracker_item_pspecs[PROP_SUBMENU_NAMESPACE] =
|
||||
g_param_spec_string ("submenu-namespace", "", "", NULL, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
|
||||
gtk_menu_tracker_item_pspecs[PROP_SUBMENU_SHOWN] =
|
||||
g_param_spec_boolean ("submenu-shown", "", "", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
|
||||
|
||||
g_object_class_install_properties (class, N_PROPS, gtk_menu_tracker_item_pspecs);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_item_action_added (GtkActionObserver *observer,
|
||||
GtkActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
const GVariantType *parameter_type,
|
||||
gboolean enabled,
|
||||
GVariant *state)
|
||||
{
|
||||
GtkMenuTrackerItem *self = GTK_MENU_TRACKER_ITEM (observer);
|
||||
GVariant *action_target;
|
||||
|
||||
action_target = g_menu_item_get_attribute_value (self->item, G_MENU_ATTRIBUTE_TARGET, NULL);
|
||||
|
||||
self->can_activate = (action_target == NULL && parameter_type == NULL) ||
|
||||
(action_target != NULL && parameter_type != NULL &&
|
||||
g_variant_is_of_type (action_target, parameter_type));
|
||||
|
||||
if (!self->can_activate)
|
||||
{
|
||||
if (action_target)
|
||||
g_variant_unref (action_target);
|
||||
return;
|
||||
}
|
||||
|
||||
self->sensitive = enabled;
|
||||
|
||||
if (action_target != NULL && state != NULL)
|
||||
{
|
||||
self->toggled = g_variant_equal (state, action_target);
|
||||
self->role = GTK_MENU_TRACKER_ITEM_ROLE_RADIO;
|
||||
}
|
||||
|
||||
else if (state != NULL && g_variant_is_of_type (state, G_VARIANT_TYPE_BOOLEAN))
|
||||
{
|
||||
self->toggled = g_variant_get_boolean (state);
|
||||
self->role = GTK_MENU_TRACKER_ITEM_ROLE_CHECK;
|
||||
}
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
|
||||
if (self->sensitive)
|
||||
g_object_notify_by_pspec (G_OBJECT (self), gtk_menu_tracker_item_pspecs[PROP_SENSITIVE]);
|
||||
|
||||
if (self->toggled)
|
||||
g_object_notify_by_pspec (G_OBJECT (self), gtk_menu_tracker_item_pspecs[PROP_TOGGLED]);
|
||||
|
||||
if (self->role != GTK_MENU_TRACKER_ITEM_ROLE_NORMAL)
|
||||
g_object_notify_by_pspec (G_OBJECT (self), gtk_menu_tracker_item_pspecs[PROP_ROLE]);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
|
||||
if (action_target)
|
||||
g_variant_unref (action_target);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_item_action_enabled_changed (GtkActionObserver *observer,
|
||||
GtkActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
gboolean enabled)
|
||||
{
|
||||
GtkMenuTrackerItem *self = GTK_MENU_TRACKER_ITEM (observer);
|
||||
|
||||
if (!self->can_activate)
|
||||
return;
|
||||
|
||||
if (self->sensitive == enabled)
|
||||
return;
|
||||
|
||||
self->sensitive = enabled;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), gtk_menu_tracker_item_pspecs[PROP_SENSITIVE]);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_item_action_state_changed (GtkActionObserver *observer,
|
||||
GtkActionObservable *observable,
|
||||
const gchar *action_name,
|
||||
GVariant *state)
|
||||
{
|
||||
GtkMenuTrackerItem *self = GTK_MENU_TRACKER_ITEM (observer);
|
||||
GVariant *action_target;
|
||||
gboolean was_toggled;
|
||||
|
||||
if (!self->can_activate)
|
||||
return;
|
||||
|
||||
action_target = g_menu_item_get_attribute_value (self->item, G_MENU_ATTRIBUTE_TARGET, NULL);
|
||||
was_toggled = self->toggled;
|
||||
|
||||
if (action_target)
|
||||
{
|
||||
self->toggled = g_variant_equal (state, action_target);
|
||||
g_variant_unref (action_target);
|
||||
}
|
||||
|
||||
else if (g_variant_is_of_type (state, G_VARIANT_TYPE_BOOLEAN))
|
||||
self->toggled = g_variant_get_boolean (state);
|
||||
|
||||
else
|
||||
self->toggled = FALSE;
|
||||
|
||||
if (self->toggled != was_toggled)
|
||||
g_object_notify_by_pspec (G_OBJECT (self), gtk_menu_tracker_item_pspecs[PROP_TOGGLED]);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_item_action_removed (GtkActionObserver *observer,
|
||||
GtkActionObservable *observable,
|
||||
const gchar *action_name)
|
||||
{
|
||||
GtkMenuTrackerItem *self = GTK_MENU_TRACKER_ITEM (observer);
|
||||
|
||||
if (!self->can_activate)
|
||||
return;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
|
||||
if (self->sensitive)
|
||||
{
|
||||
self->sensitive = FALSE;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), gtk_menu_tracker_item_pspecs[PROP_SENSITIVE]);
|
||||
}
|
||||
|
||||
if (self->toggled)
|
||||
{
|
||||
self->toggled = FALSE;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), gtk_menu_tracker_item_pspecs[PROP_TOGGLED]);
|
||||
}
|
||||
|
||||
if (self->role != GTK_MENU_TRACKER_ITEM_ROLE_NORMAL)
|
||||
{
|
||||
self->role = GTK_MENU_TRACKER_ITEM_ROLE_NORMAL;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), gtk_menu_tracker_item_pspecs[PROP_ROLE]);
|
||||
}
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_item_init_observer_iface (GtkActionObserverInterface *iface)
|
||||
{
|
||||
iface->action_added = gtk_menu_tracker_item_action_added;
|
||||
iface->action_enabled_changed = gtk_menu_tracker_item_action_enabled_changed;
|
||||
iface->action_state_changed = gtk_menu_tracker_item_action_state_changed;
|
||||
iface->action_removed = gtk_menu_tracker_item_action_removed;
|
||||
}
|
||||
|
||||
GtkMenuTrackerItem *
|
||||
gtk_menu_tracker_item_new (GtkActionObservable *observable,
|
||||
GMenuModel *model,
|
||||
gint item_index,
|
||||
const gchar *action_namespace,
|
||||
gboolean is_separator)
|
||||
{
|
||||
GtkMenuTrackerItem *self;
|
||||
const gchar *action_name;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_ACTION_OBSERVABLE (observable), NULL);
|
||||
g_return_val_if_fail (G_IS_MENU_MODEL (model), NULL);
|
||||
|
||||
self = g_object_new (GTK_TYPE_MENU_TRACKER_ITEM, NULL);
|
||||
self->item = g_menu_item_new_from_model (model, item_index);
|
||||
self->action_namespace = g_strdup (action_namespace);
|
||||
self->observable = g_object_ref (observable);
|
||||
self->is_separator = is_separator;
|
||||
|
||||
if (!is_separator && g_menu_item_get_attribute (self->item, "action", "&s", &action_name))
|
||||
{
|
||||
GActionGroup *group = G_ACTION_GROUP (observable);
|
||||
const GVariantType *parameter_type;
|
||||
gboolean enabled;
|
||||
GVariant *state;
|
||||
gboolean found;
|
||||
|
||||
state = NULL;
|
||||
|
||||
if (action_namespace)
|
||||
{
|
||||
gchar *full_action;
|
||||
|
||||
full_action = g_strjoin (".", action_namespace, action_name, NULL);
|
||||
gtk_action_observable_register_observer (self->observable, full_action, GTK_ACTION_OBSERVER (self));
|
||||
found = g_action_group_query_action (group, full_action, &enabled, ¶meter_type, NULL, NULL, &state);
|
||||
g_free (full_action);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_action_observable_register_observer (self->observable, action_name, GTK_ACTION_OBSERVER (self));
|
||||
found = g_action_group_query_action (group, action_name, &enabled, ¶meter_type, NULL, NULL, &state);
|
||||
}
|
||||
|
||||
if (found)
|
||||
gtk_menu_tracker_item_action_added (GTK_ACTION_OBSERVER (self), observable, NULL,
|
||||
parameter_type, enabled, state);
|
||||
else
|
||||
gtk_menu_tracker_item_action_removed (GTK_ACTION_OBSERVER (self), observable, NULL);
|
||||
|
||||
if (state)
|
||||
g_variant_unref (state);
|
||||
}
|
||||
else
|
||||
self->sensitive = TRUE;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_menu_tracker_item_get_observable:
|
||||
*
|
||||
* Returns: (transfer none):
|
||||
*/
|
||||
GtkActionObservable *
|
||||
gtk_menu_tracker_item_get_observable (GtkMenuTrackerItem *self)
|
||||
{
|
||||
return self->observable;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_menu_tracker_item_get_is_separator (GtkMenuTrackerItem *self)
|
||||
{
|
||||
return self->is_separator;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_menu_tracker_item_get_has_submenu (GtkMenuTrackerItem *self)
|
||||
{
|
||||
GMenuModel *link;
|
||||
|
||||
link = g_menu_item_get_link (self->item, G_MENU_LINK_SUBMENU);
|
||||
|
||||
if (link)
|
||||
{
|
||||
g_object_unref (link);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
gtk_menu_tracker_item_get_label (GtkMenuTrackerItem *self)
|
||||
{
|
||||
const gchar *label = NULL;
|
||||
|
||||
g_menu_item_get_attribute (self->item, G_MENU_ATTRIBUTE_LABEL, "&s", &label);
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_menu_tracker_item_get_icon:
|
||||
*
|
||||
* Returns: (transfer full):
|
||||
*/
|
||||
GIcon *
|
||||
gtk_menu_tracker_item_get_icon (GtkMenuTrackerItem *self)
|
||||
{
|
||||
GVariant *icon_data;
|
||||
GIcon *icon;
|
||||
|
||||
icon_data = g_menu_item_get_attribute_value (self->item, "icon", NULL);
|
||||
|
||||
if (icon_data == NULL)
|
||||
return NULL;
|
||||
|
||||
icon = g_icon_deserialize (icon_data);
|
||||
g_variant_unref (icon_data);
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_menu_tracker_item_get_sensitive (GtkMenuTrackerItem *self)
|
||||
{
|
||||
return self->sensitive;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_menu_tracker_item_get_visible (GtkMenuTrackerItem *self)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GtkMenuTrackerItemRole
|
||||
gtk_menu_tracker_item_get_role (GtkMenuTrackerItem *self)
|
||||
{
|
||||
return self->role;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_menu_tracker_item_get_toggled (GtkMenuTrackerItem *self)
|
||||
{
|
||||
return self->toggled;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
gtk_menu_tracker_item_get_accel (GtkMenuTrackerItem *self)
|
||||
{
|
||||
const gchar *accel = NULL;
|
||||
|
||||
g_menu_item_get_attribute (self->item, "accel", "&s", &accel);
|
||||
|
||||
return accel;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_menu_tracker_item_get_submenu:
|
||||
*
|
||||
* Returns: (transfer full):
|
||||
*/
|
||||
GMenuModel *
|
||||
gtk_menu_tracker_item_get_submenu (GtkMenuTrackerItem *self)
|
||||
{
|
||||
return g_menu_item_get_link (self->item, "submenu");
|
||||
}
|
||||
|
||||
gchar *
|
||||
gtk_menu_tracker_item_get_submenu_namespace (GtkMenuTrackerItem *self)
|
||||
{
|
||||
const gchar *namespace;
|
||||
|
||||
if (g_menu_item_get_attribute (self->item, "action-namespace", "&s", &namespace))
|
||||
{
|
||||
if (self->action_namespace)
|
||||
return g_strjoin (".", self->action_namespace, namespace, NULL);
|
||||
else
|
||||
return g_strdup (namespace);
|
||||
}
|
||||
else
|
||||
return g_strdup (self->action_namespace);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_menu_tracker_item_get_should_request_show (GtkMenuTrackerItem *self)
|
||||
{
|
||||
return g_menu_item_get_attribute (self->item, "submenu-action", "&s", NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_menu_tracker_item_get_submenu_shown (GtkMenuTrackerItem *self)
|
||||
{
|
||||
return self->submenu_shown;
|
||||
}
|
||||
|
||||
/* only called from the opener, internally */
|
||||
static void
|
||||
gtk_menu_tracker_item_set_submenu_shown (GtkMenuTrackerItem *self,
|
||||
gboolean submenu_shown)
|
||||
{
|
||||
if (submenu_shown == self->submenu_shown)
|
||||
return;
|
||||
|
||||
self->submenu_shown = submenu_shown;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), gtk_menu_tracker_item_pspecs[PROP_SUBMENU_SHOWN]);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_menu_tracker_item_activated (GtkMenuTrackerItem *self)
|
||||
{
|
||||
const gchar *action_name;
|
||||
GVariant *action_target;
|
||||
|
||||
g_return_if_fail (GTK_IS_MENU_TRACKER_ITEM (self));
|
||||
|
||||
if (!self->can_activate)
|
||||
return;
|
||||
|
||||
g_menu_item_get_attribute (self->item, G_MENU_ATTRIBUTE_ACTION, "&s", &action_name);
|
||||
action_target = g_menu_item_get_attribute_value (self->item, G_MENU_ATTRIBUTE_TARGET, NULL);
|
||||
|
||||
if (self->action_namespace)
|
||||
{
|
||||
gchar *full_action;
|
||||
|
||||
full_action = g_strjoin (".", self->action_namespace, action_name, NULL);
|
||||
g_action_group_activate_action (G_ACTION_GROUP (self->observable), full_action, action_target);
|
||||
g_free (full_action);
|
||||
}
|
||||
else
|
||||
g_action_group_activate_action (G_ACTION_GROUP (self->observable), action_name, action_target);
|
||||
|
||||
if (action_target)
|
||||
g_variant_unref (action_target);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GtkMenuTrackerItem *item;
|
||||
gchar *submenu_action;
|
||||
gboolean first_time;
|
||||
} GtkMenuTrackerOpener;
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_opener_update (GtkMenuTrackerOpener *opener)
|
||||
{
|
||||
GActionGroup *group = G_ACTION_GROUP (opener->item->observable);
|
||||
gboolean is_open = TRUE;
|
||||
|
||||
/* We consider the menu as being "open" if the action does not exist
|
||||
* or if there is another problem (no state, wrong state type, etc.).
|
||||
* If the action exists, with the correct state then we consider it
|
||||
* open if we have ever seen this state equal to TRUE.
|
||||
*
|
||||
* In the event that we see the state equal to FALSE, we force it back
|
||||
* to TRUE. We do not signal that the menu was closed because this is
|
||||
* likely to create UI thrashing.
|
||||
*
|
||||
* The only way the menu can have a true-to-false submenu-shown
|
||||
* transition is if the user calls _request_submenu_shown (FALSE).
|
||||
* That is handled in _free() below.
|
||||
*/
|
||||
|
||||
if (g_action_group_has_action (group, opener->submenu_action))
|
||||
{
|
||||
GVariant *state = g_action_group_get_action_state (group, opener->submenu_action);
|
||||
|
||||
if (state)
|
||||
{
|
||||
if (g_variant_is_of_type (state, G_VARIANT_TYPE_BOOLEAN))
|
||||
is_open = g_variant_get_boolean (state);
|
||||
g_variant_unref (state);
|
||||
}
|
||||
}
|
||||
|
||||
/* If it is already open, signal that.
|
||||
*
|
||||
* If it is not open, ask it to open.
|
||||
*/
|
||||
if (is_open)
|
||||
gtk_menu_tracker_item_set_submenu_shown (opener->item, TRUE);
|
||||
|
||||
if (!is_open || opener->first_time)
|
||||
{
|
||||
g_action_group_change_action_state (group, opener->submenu_action, g_variant_new_boolean (TRUE));
|
||||
opener->first_time = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_opener_added (GActionGroup *group,
|
||||
const gchar *action_name,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkMenuTrackerOpener *opener = user_data;
|
||||
|
||||
if (g_str_equal (action_name, opener->submenu_action))
|
||||
gtk_menu_tracker_opener_update (opener);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_opener_removed (GActionGroup *action_group,
|
||||
const gchar *action_name,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkMenuTrackerOpener *opener = user_data;
|
||||
|
||||
if (g_str_equal (action_name, opener->submenu_action))
|
||||
gtk_menu_tracker_opener_update (opener);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_opener_changed (GActionGroup *action_group,
|
||||
const gchar *action_name,
|
||||
GVariant *new_state,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkMenuTrackerOpener *opener = user_data;
|
||||
|
||||
if (g_str_equal (action_name, opener->submenu_action))
|
||||
gtk_menu_tracker_opener_update (opener);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_menu_tracker_opener_free (gpointer data)
|
||||
{
|
||||
GtkMenuTrackerOpener *opener = data;
|
||||
|
||||
g_signal_handlers_disconnect_by_func (opener->item->observable, gtk_menu_tracker_opener_added, opener);
|
||||
g_signal_handlers_disconnect_by_func (opener->item->observable, gtk_menu_tracker_opener_removed, opener);
|
||||
g_signal_handlers_disconnect_by_func (opener->item->observable, gtk_menu_tracker_opener_changed, opener);
|
||||
|
||||
g_action_group_change_action_state (G_ACTION_GROUP (opener->item->observable),
|
||||
opener->submenu_action,
|
||||
g_variant_new_boolean (FALSE));
|
||||
|
||||
gtk_menu_tracker_item_set_submenu_shown (opener->item, FALSE);
|
||||
|
||||
g_free (opener->submenu_action);
|
||||
|
||||
g_slice_free (GtkMenuTrackerOpener, opener);
|
||||
}
|
||||
|
||||
static GtkMenuTrackerOpener *
|
||||
gtk_menu_tracker_opener_new (GtkMenuTrackerItem *item,
|
||||
const gchar *submenu_action)
|
||||
{
|
||||
GtkMenuTrackerOpener *opener;
|
||||
|
||||
opener = g_slice_new (GtkMenuTrackerOpener);
|
||||
opener->first_time = TRUE;
|
||||
opener->item = item;
|
||||
|
||||
if (item->action_namespace)
|
||||
opener->submenu_action = g_strjoin (".", item->action_namespace, submenu_action, NULL);
|
||||
else
|
||||
opener->submenu_action = g_strdup (submenu_action);
|
||||
|
||||
g_signal_connect (item->observable, "action-added", G_CALLBACK (gtk_menu_tracker_opener_added), opener);
|
||||
g_signal_connect (item->observable, "action-removed", G_CALLBACK (gtk_menu_tracker_opener_removed), opener);
|
||||
g_signal_connect (item->observable, "action-state-changed", G_CALLBACK (gtk_menu_tracker_opener_changed), opener);
|
||||
|
||||
gtk_menu_tracker_opener_update (opener);
|
||||
|
||||
return opener;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_menu_tracker_item_request_submenu_shown (GtkMenuTrackerItem *self,
|
||||
gboolean shown)
|
||||
{
|
||||
const gchar *submenu_action;
|
||||
gboolean okay;
|
||||
|
||||
if (shown == self->submenu_requested)
|
||||
return;
|
||||
|
||||
/* Should not be getting called unless we have submenu-action.
|
||||
*/
|
||||
okay = g_menu_item_get_attribute (self->item, "submenu-action", "&s", &submenu_action);
|
||||
g_assert (okay);
|
||||
|
||||
self->submenu_requested = shown;
|
||||
|
||||
if (shown)
|
||||
g_object_set_data_full (G_OBJECT (self), "submenu-opener",
|
||||
gtk_menu_tracker_opener_new (self, submenu_action),
|
||||
gtk_menu_tracker_opener_free);
|
||||
else
|
||||
g_object_set_data (G_OBJECT (self), "submenu-opener", NULL);
|
||||
}
|
84
gtk/gtkmenutrackeritem.h
Normal file
84
gtk/gtkmenutrackeritem.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright © 2011, 2013 Canonical Limited
|
||||
*
|
||||
* This library 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author: Ryan Lortie <desrt@desrt.ca>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_MENU_TRACKER_ITEM_H__
|
||||
#define __GTK_MENU_TRACKER_ITEM_H__
|
||||
|
||||
#include "gtkactionobservable.h"
|
||||
|
||||
#define GTK_TYPE_MENU_TRACKER_ITEM (gtk_menu_tracker_item_get_type ())
|
||||
#define GTK_MENU_TRACKER_ITEM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
|
||||
GTK_TYPE_MENU_TRACKER_ITEM, GtkMenuTrackerItem))
|
||||
#define GTK_IS_MENU_TRACKER_ITEM(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
|
||||
GTK_TYPE_MENU_TRACKER_ITEM))
|
||||
|
||||
typedef struct _GtkMenuTrackerItem GtkMenuTrackerItem;
|
||||
|
||||
#define GTK_TYPE_MENU_TRACKER_ITEM_ROLE (gtk_menu_tracker_item_role_get_type ())
|
||||
|
||||
typedef enum {
|
||||
GTK_MENU_TRACKER_ITEM_ROLE_NORMAL,
|
||||
GTK_MENU_TRACKER_ITEM_ROLE_CHECK,
|
||||
GTK_MENU_TRACKER_ITEM_ROLE_RADIO,
|
||||
} GtkMenuTrackerItemRole;
|
||||
|
||||
GType gtk_menu_tracker_item_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GType gtk_menu_tracker_item_role_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkMenuTrackerItem * gtk_menu_tracker_item_new (GtkActionObservable *observable,
|
||||
GMenuModel *model,
|
||||
gint item_index,
|
||||
const gchar *action_namespace,
|
||||
gboolean is_separator);
|
||||
|
||||
GtkActionObservable * gtk_menu_tracker_item_get_observable (GtkMenuTrackerItem *self);
|
||||
|
||||
gboolean gtk_menu_tracker_item_get_is_separator (GtkMenuTrackerItem *self);
|
||||
|
||||
gboolean gtk_menu_tracker_item_get_has_submenu (GtkMenuTrackerItem *self);
|
||||
|
||||
const gchar * gtk_menu_tracker_item_get_label (GtkMenuTrackerItem *self);
|
||||
|
||||
GIcon * gtk_menu_tracker_item_get_icon (GtkMenuTrackerItem *self);
|
||||
|
||||
gboolean gtk_menu_tracker_item_get_sensitive (GtkMenuTrackerItem *self);
|
||||
|
||||
gboolean gtk_menu_tracker_item_get_visible (GtkMenuTrackerItem *self);
|
||||
|
||||
GtkMenuTrackerItemRole gtk_menu_tracker_item_get_role (GtkMenuTrackerItem *self);
|
||||
|
||||
gboolean gtk_menu_tracker_item_get_toggled (GtkMenuTrackerItem *self);
|
||||
|
||||
const gchar * gtk_menu_tracker_item_get_accel (GtkMenuTrackerItem *self);
|
||||
|
||||
GMenuModel * gtk_menu_tracker_item_get_submenu (GtkMenuTrackerItem *self);
|
||||
|
||||
gchar * gtk_menu_tracker_item_get_submenu_namespace (GtkMenuTrackerItem *self);
|
||||
|
||||
gboolean gtk_menu_tracker_item_get_should_request_show (GtkMenuTrackerItem *self);
|
||||
|
||||
void gtk_menu_tracker_item_activated (GtkMenuTrackerItem *self);
|
||||
|
||||
void gtk_menu_tracker_item_request_submenu_shown (GtkMenuTrackerItem *self,
|
||||
gboolean shown);
|
||||
|
||||
gboolean gtk_menu_tracker_item_get_submenu_shown (GtkMenuTrackerItem *self);
|
||||
|
||||
#endif
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2011 Canonical Limited
|
||||
* Copyright © 2011, 2013 Canonical Limited
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -21,9 +21,6 @@
|
||||
|
||||
#include "gtkmodelmenuitem.h"
|
||||
|
||||
#include "gtkaccelmapprivate.h"
|
||||
#include "gtkactionhelper.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
#include "gtkaccellabel.h"
|
||||
#include "gtkimage.h"
|
||||
#include "gtkbox.h"
|
||||
@@ -31,7 +28,7 @@
|
||||
struct _GtkModelMenuItem
|
||||
{
|
||||
GtkCheckMenuItem parent_instance;
|
||||
GtkActionHelperRole role;
|
||||
GtkMenuTrackerItemRole role;
|
||||
gboolean has_indicator;
|
||||
};
|
||||
|
||||
@@ -39,7 +36,15 @@ typedef GtkCheckMenuItemClass GtkModelMenuItemClass;
|
||||
|
||||
G_DEFINE_TYPE (GtkModelMenuItem, gtk_model_menu_item, GTK_TYPE_CHECK_MENU_ITEM)
|
||||
|
||||
#define PROP_ACTION_ROLE 1
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_ACTION_ROLE,
|
||||
PROP_ICON,
|
||||
PROP_TEXT,
|
||||
PROP_TOGGLED,
|
||||
PROP_ACCEL
|
||||
};
|
||||
|
||||
static void
|
||||
gtk_model_menu_item_toggle_size_request (GtkMenuItem *menu_item,
|
||||
@@ -55,6 +60,12 @@ gtk_model_menu_item_toggle_size_request (GtkMenuItem *menu_item,
|
||||
*requisition = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_model_menu_item_activate (GtkMenuItem *item)
|
||||
{
|
||||
/* block the automatic toggle behaviour -- just do nothing */
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_model_menu_item_draw_indicator (GtkCheckMenuItem *check_item,
|
||||
cairo_t *cr)
|
||||
@@ -66,177 +77,6 @@ gtk_model_menu_item_draw_indicator (GtkCheckMenuItem *check_item,
|
||||
->draw_indicator (check_item, cr);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_actionable_set_namespaced_action_name (GtkActionable *actionable,
|
||||
const gchar *namespace,
|
||||
const gchar *action_name)
|
||||
{
|
||||
if (namespace)
|
||||
{
|
||||
gchar *name = g_strdup_printf ("%s.%s", namespace, action_name);
|
||||
gtk_actionable_set_action_name (actionable, name);
|
||||
g_free (name);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_actionable_set_action_name (actionable, action_name);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_model_menu_item_submenu_shown (GtkWidget *widget,
|
||||
gpointer user_data)
|
||||
{
|
||||
const gchar *action_name = user_data;
|
||||
GActionMuxer *muxer;
|
||||
|
||||
muxer = _gtk_widget_get_action_muxer (widget);
|
||||
g_action_group_change_action_state (G_ACTION_GROUP (muxer), action_name, g_variant_new_boolean (TRUE));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_model_menu_item_submenu_hidden (GtkWidget *widget,
|
||||
gpointer user_data)
|
||||
{
|
||||
const gchar *action_name = user_data;
|
||||
GActionMuxer *muxer;
|
||||
|
||||
muxer = _gtk_widget_get_action_muxer (widget);
|
||||
g_action_group_change_action_state (G_ACTION_GROUP (muxer), action_name, g_variant_new_boolean (FALSE));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_model_menu_item_setup (GtkModelMenuItem *item,
|
||||
GMenuModel *model,
|
||||
gint item_index,
|
||||
const gchar *action_namespace)
|
||||
{
|
||||
GMenuAttributeIter *iter;
|
||||
GMenuModel *submenu;
|
||||
const gchar *key;
|
||||
GVariant *value;
|
||||
GtkWidget *label;
|
||||
|
||||
label = NULL;
|
||||
|
||||
/* In the case that we have an icon, make an HBox and put it beside
|
||||
* the label. Otherwise, we just have a label directly.
|
||||
*/
|
||||
if ((value = g_menu_model_get_item_attribute_value (model, item_index, "icon", NULL)))
|
||||
{
|
||||
GIcon *icon;
|
||||
|
||||
icon = g_icon_deserialize (value);
|
||||
|
||||
if (icon != NULL)
|
||||
{
|
||||
GtkWidget *image;
|
||||
GtkWidget *box;
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
|
||||
image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_MENU);
|
||||
gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 0);
|
||||
g_object_unref (icon);
|
||||
|
||||
label = gtk_accel_label_new ("");
|
||||
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
|
||||
gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), GTK_WIDGET (item));
|
||||
gtk_box_pack_end (GTK_BOX (box), label, TRUE, TRUE, 0);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (item), box);
|
||||
|
||||
gtk_widget_show_all (box);
|
||||
}
|
||||
|
||||
g_variant_unref (value);
|
||||
}
|
||||
|
||||
if (label == NULL)
|
||||
{
|
||||
/* Ensure that the GtkAccelLabel has been created... */
|
||||
(void) gtk_menu_item_get_label (GTK_MENU_ITEM (item));
|
||||
label = gtk_bin_get_child (GTK_BIN (item));
|
||||
}
|
||||
|
||||
g_assert (label != NULL);
|
||||
|
||||
if ((submenu = g_menu_model_get_item_link (model, item_index, "submenu")))
|
||||
{
|
||||
gchar *section_namespace = NULL;
|
||||
GtkWidget *menu;
|
||||
|
||||
g_menu_model_get_item_attribute (model, item_index, "action-namespace", "s", §ion_namespace);
|
||||
menu = gtk_menu_new ();
|
||||
|
||||
if (action_namespace)
|
||||
{
|
||||
gchar *namespace = g_strjoin (".", action_namespace, section_namespace, NULL);
|
||||
gtk_menu_shell_bind_model (GTK_MENU_SHELL (menu), submenu, namespace, TRUE);
|
||||
g_free (namespace);
|
||||
}
|
||||
else
|
||||
gtk_menu_shell_bind_model (GTK_MENU_SHELL (menu), submenu, section_namespace, TRUE);
|
||||
|
||||
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu);
|
||||
|
||||
g_free (section_namespace);
|
||||
g_object_unref (submenu);
|
||||
}
|
||||
|
||||
iter = g_menu_model_iterate_item_attributes (model, item_index);
|
||||
while (g_menu_attribute_iter_get_next (iter, &key, &value))
|
||||
{
|
||||
if (g_str_equal (key, "label") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
|
||||
gtk_label_set_text_with_mnemonic (GTK_LABEL (label), g_variant_get_string (value, NULL));
|
||||
|
||||
else if (g_str_equal (key, "accel") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
|
||||
{
|
||||
GdkModifierType modifiers;
|
||||
guint key;
|
||||
|
||||
gtk_accelerator_parse (g_variant_get_string (value, NULL), &key, &modifiers);
|
||||
|
||||
if (key)
|
||||
gtk_accel_label_set_accel (GTK_ACCEL_LABEL (label), key, modifiers);
|
||||
}
|
||||
|
||||
else if (g_str_equal (key, "action") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
|
||||
gtk_actionable_set_namespaced_action_name (GTK_ACTIONABLE (item), action_namespace,
|
||||
g_variant_get_string (value, NULL));
|
||||
|
||||
else if (g_str_equal (key, "target"))
|
||||
gtk_actionable_set_action_target_value (GTK_ACTIONABLE (item), value);
|
||||
|
||||
else if (g_str_equal (key, "submenu-action") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
|
||||
{
|
||||
GtkWidget *submenu;
|
||||
|
||||
submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (item));
|
||||
|
||||
if (submenu != NULL)
|
||||
{
|
||||
const gchar *action = g_variant_get_string (value, NULL);
|
||||
gchar *full_action;
|
||||
|
||||
if (action_namespace)
|
||||
full_action = g_strjoin (".", action_namespace, action, NULL);
|
||||
else
|
||||
full_action = g_strdup (action);
|
||||
|
||||
g_object_set_data_full (G_OBJECT (submenu), "gtkmodelmenu-visibility-action", full_action, g_free);
|
||||
g_signal_connect (submenu, "show", G_CALLBACK (gtk_model_menu_item_submenu_shown), full_action);
|
||||
g_signal_connect (submenu, "hide", G_CALLBACK (gtk_model_menu_item_submenu_hidden), full_action);
|
||||
}
|
||||
}
|
||||
|
||||
g_variant_unref (value);
|
||||
}
|
||||
g_object_unref (iter);
|
||||
|
||||
gtk_menu_item_set_use_underline (GTK_MENU_ITEM (item), TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_model_menu_item_set_has_indicator (GtkModelMenuItem *item,
|
||||
gboolean has_indicator)
|
||||
@@ -250,36 +90,30 @@ gtk_model_menu_item_set_has_indicator (GtkModelMenuItem *item,
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_model_menu_item_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
gtk_model_menu_item_set_action_role (GtkModelMenuItem *item,
|
||||
GtkMenuTrackerItemRole role)
|
||||
{
|
||||
GtkModelMenuItem *item = GTK_MODEL_MENU_ITEM (object);
|
||||
GtkActionHelperRole role;
|
||||
AtkObject *accessible;
|
||||
AtkRole a11y_role;
|
||||
|
||||
g_assert (prop_id == PROP_ACTION_ROLE);
|
||||
|
||||
role = g_value_get_uint (value);
|
||||
|
||||
if (role == item->role)
|
||||
return;
|
||||
|
||||
gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (item), role == GTK_ACTION_HELPER_ROLE_RADIO);
|
||||
gtk_model_menu_item_set_has_indicator (item, role != GTK_ACTION_HELPER_ROLE_NORMAL);
|
||||
gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (item), role == GTK_MENU_TRACKER_ITEM_ROLE_RADIO);
|
||||
gtk_model_menu_item_set_has_indicator (item, role != GTK_MENU_TRACKER_ITEM_ROLE_NORMAL);
|
||||
|
||||
accessible = gtk_widget_get_accessible (GTK_WIDGET (item));
|
||||
switch (role)
|
||||
{
|
||||
case GTK_ACTION_HELPER_ROLE_NORMAL:
|
||||
case GTK_MENU_TRACKER_ITEM_ROLE_NORMAL:
|
||||
a11y_role = ATK_ROLE_MENU_ITEM;
|
||||
break;
|
||||
|
||||
case GTK_ACTION_HELPER_ROLE_TOGGLE:
|
||||
case GTK_MENU_TRACKER_ITEM_ROLE_CHECK:
|
||||
a11y_role = ATK_ROLE_CHECK_MENU_ITEM;
|
||||
break;
|
||||
|
||||
case GTK_ACTION_HELPER_ROLE_RADIO:
|
||||
case GTK_MENU_TRACKER_ITEM_ROLE_RADIO:
|
||||
a11y_role = ATK_ROLE_RADIO_MENU_ITEM;
|
||||
break;
|
||||
|
||||
@@ -290,6 +124,201 @@ gtk_model_menu_item_set_property (GObject *object, guint prop_id,
|
||||
atk_object_set_role (accessible, a11y_role);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_model_menu_item_set_icon (GtkModelMenuItem *item,
|
||||
GIcon *icon)
|
||||
{
|
||||
GtkWidget *child;
|
||||
|
||||
g_return_if_fail (GTK_IS_MODEL_MENU_ITEM (item));
|
||||
g_return_if_fail (icon == NULL || G_IS_ICON (icon));
|
||||
|
||||
child = gtk_bin_get_child (GTK_BIN (item));
|
||||
|
||||
/* There are only three possibilities here:
|
||||
*
|
||||
* - no child
|
||||
* - accel label child
|
||||
* - already a box
|
||||
*
|
||||
* Handle the no-child case by having GtkMenuItem create the accel
|
||||
* label, then we will only have two possible cases.
|
||||
*/
|
||||
if (child == NULL)
|
||||
{
|
||||
gtk_menu_item_get_label (GTK_MENU_ITEM (item));
|
||||
child = gtk_bin_get_child (GTK_BIN (item));
|
||||
g_assert (GTK_IS_LABEL (child));
|
||||
}
|
||||
|
||||
/* If it is a box, make sure there are no images inside of it already.
|
||||
*/
|
||||
if (GTK_IS_BOX (child))
|
||||
{
|
||||
GList *children;
|
||||
|
||||
children = gtk_container_get_children (GTK_CONTAINER (child));
|
||||
while (children)
|
||||
{
|
||||
if (GTK_IS_IMAGE (children->data))
|
||||
gtk_widget_destroy (children->data);
|
||||
|
||||
children = g_list_delete_link (children, children);
|
||||
}
|
||||
}
|
||||
|
||||
/* If it is not a box, put it into a box, at the end */
|
||||
if (!GTK_IS_BOX (child))
|
||||
{
|
||||
GtkWidget *box;
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
|
||||
/* Reparent the child without destroying it */
|
||||
g_object_ref (child);
|
||||
gtk_container_remove (GTK_CONTAINER (item), child);
|
||||
gtk_box_pack_end (GTK_BOX (box), child, TRUE, TRUE, 0);
|
||||
g_object_unref (child);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (item), box);
|
||||
gtk_widget_show (box);
|
||||
|
||||
/* Now we have a box */
|
||||
child = box;
|
||||
}
|
||||
|
||||
g_assert (GTK_IS_BOX (child));
|
||||
|
||||
/* child is now a box containing a label and no image. Add the icon,
|
||||
* if appropriate.
|
||||
*/
|
||||
if (icon != NULL)
|
||||
{
|
||||
GtkWidget *image;
|
||||
|
||||
image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_MENU);
|
||||
gtk_box_pack_start (GTK_BOX (child), image, FALSE, FALSE, 0);
|
||||
gtk_widget_show (image);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_model_menu_item_set_text (GtkModelMenuItem *item,
|
||||
const gchar *text)
|
||||
{
|
||||
GtkWidget *child;
|
||||
GList *children;
|
||||
|
||||
child = gtk_bin_get_child (GTK_BIN (item));
|
||||
if (child == NULL)
|
||||
{
|
||||
gtk_menu_item_get_label (GTK_MENU_ITEM (item));
|
||||
child = gtk_bin_get_child (GTK_BIN (item));
|
||||
g_assert (GTK_IS_LABEL (child));
|
||||
}
|
||||
|
||||
if (GTK_IS_LABEL (child))
|
||||
{
|
||||
gtk_label_set_text_with_mnemonic (GTK_LABEL (child), text);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GTK_IS_CONTAINER (child))
|
||||
return;
|
||||
|
||||
children = gtk_container_get_children (GTK_CONTAINER (child));
|
||||
|
||||
while (children)
|
||||
{
|
||||
if (GTK_IS_LABEL (children->data))
|
||||
gtk_label_set_label (GTK_LABEL (children->data), text);
|
||||
|
||||
children = g_list_delete_link (children, children);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_model_menu_item_set_accel (GtkModelMenuItem *item,
|
||||
const gchar *accel)
|
||||
{
|
||||
GtkWidget *child;
|
||||
GList *children;
|
||||
GdkModifierType modifiers;
|
||||
guint key;
|
||||
|
||||
if (accel)
|
||||
{
|
||||
gtk_accelerator_parse (accel, &key, &modifiers);
|
||||
if (!key)
|
||||
modifiers = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
key = 0;
|
||||
modifiers = 0;
|
||||
}
|
||||
|
||||
child = gtk_bin_get_child (GTK_BIN (item));
|
||||
if (child == NULL)
|
||||
{
|
||||
gtk_menu_item_get_label (GTK_MENU_ITEM (item));
|
||||
child = gtk_bin_get_child (GTK_BIN (item));
|
||||
g_assert (GTK_IS_LABEL (child));
|
||||
}
|
||||
|
||||
if (GTK_IS_LABEL (child))
|
||||
{
|
||||
gtk_accel_label_set_accel (GTK_ACCEL_LABEL (child), key, modifiers);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GTK_IS_CONTAINER (child))
|
||||
return;
|
||||
|
||||
children = gtk_container_get_children (GTK_CONTAINER (child));
|
||||
|
||||
while (children)
|
||||
{
|
||||
if (GTK_IS_ACCEL_LABEL (children->data))
|
||||
gtk_accel_label_set_accel (children->data, key, modifiers);
|
||||
|
||||
children = g_list_delete_link (children, children);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gtk_model_menu_item_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
GtkModelMenuItem *item = GTK_MODEL_MENU_ITEM (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ACTION_ROLE:
|
||||
gtk_model_menu_item_set_action_role (item, g_value_get_enum (value));
|
||||
break;
|
||||
|
||||
case PROP_ICON:
|
||||
gtk_model_menu_item_set_icon (item, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_TEXT:
|
||||
gtk_model_menu_item_set_text (item, g_value_get_string (value));
|
||||
break;
|
||||
|
||||
case PROP_TOGGLED:
|
||||
_gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_ACCEL:
|
||||
gtk_model_menu_item_set_accel (item, g_value_get_string (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_model_menu_item_init (GtkModelMenuItem *item)
|
||||
{
|
||||
@@ -305,24 +334,31 @@ gtk_model_menu_item_class_init (GtkModelMenuItemClass *class)
|
||||
check_class->draw_indicator = gtk_model_menu_item_draw_indicator;
|
||||
|
||||
item_class->toggle_size_request = gtk_model_menu_item_toggle_size_request;
|
||||
item_class->activate = gtk_model_menu_item_activate;
|
||||
|
||||
object_class->set_property = gtk_model_menu_item_set_property;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_ACTION_ROLE,
|
||||
g_param_spec_uint ("action-role", "action role", "action role",
|
||||
0, 2, 0, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
|
||||
g_param_spec_enum ("action-role", "action role", "action role",
|
||||
GTK_TYPE_MENU_TRACKER_ITEM_ROLE,
|
||||
GTK_MENU_TRACKER_ITEM_ROLE_NORMAL,
|
||||
G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (object_class, PROP_ICON,
|
||||
g_param_spec_object ("icon", "icon", "icon", G_TYPE_ICON,
|
||||
G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (object_class, PROP_TEXT,
|
||||
g_param_spec_string ("text", "text", "text", NULL,
|
||||
G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (object_class, PROP_TOGGLED,
|
||||
g_param_spec_boolean ("toggled", "toggled", "toggled", FALSE,
|
||||
G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (object_class, PROP_ACCEL,
|
||||
g_param_spec_string ("accel", "accel", "accel", NULL,
|
||||
G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gtk_model_menu_item_new (GMenuModel *model,
|
||||
gint item_index,
|
||||
const gchar *action_namespace)
|
||||
gtk_model_menu_item_new (void)
|
||||
{
|
||||
GtkModelMenuItem *item;
|
||||
|
||||
item = g_object_new (GTK_TYPE_MODEL_MENU_ITEM, NULL);
|
||||
|
||||
gtk_model_menu_item_setup (item, model, item_index, action_namespace);
|
||||
|
||||
return GTK_WIDGET (item);
|
||||
return g_object_new (GTK_TYPE_MODEL_MENU_ITEM, NULL);
|
||||
}
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#define __GTK_MODEL_MENU_ITEM_H__
|
||||
|
||||
#include <gtk/gtkcheckmenuitem.h>
|
||||
#include <gtk/gtkmenutrackeritem.h>
|
||||
|
||||
#define GTK_TYPE_MODEL_MENU_ITEM (gtk_model_menu_item_get_type ())
|
||||
#define GTK_MODEL_MENU_ITEM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
|
||||
@@ -34,8 +35,6 @@ G_GNUC_INTERNAL
|
||||
GType gtk_model_menu_item_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
GtkWidget * gtk_model_menu_item_new (GMenuModel *model,
|
||||
gint item_index,
|
||||
const gchar *action_namespace);
|
||||
GtkWidget * gtk_model_menu_item_new (void);
|
||||
|
||||
#endif /* __GTK_MODEL_MENU_ITEM_H__ */
|
||||
|
@@ -505,7 +505,7 @@ struct _GtkWidgetPrivate
|
||||
SizeRequestCache requests;
|
||||
|
||||
/* actions attached to this or any parent widget */
|
||||
GActionMuxer *muxer;
|
||||
GtkActionMuxer *muxer;
|
||||
|
||||
/* The widget's window or its parent window if it does
|
||||
* not have a window. (Which will be indicated by the
|
||||
@@ -15351,7 +15351,7 @@ void
|
||||
_gtk_widget_update_parent_muxer (GtkWidget *widget)
|
||||
{
|
||||
GtkWidget *parent;
|
||||
GActionMuxer *parent_muxer;
|
||||
GtkActionMuxer *parent_muxer;
|
||||
|
||||
if (widget->priv->muxer == NULL)
|
||||
return;
|
||||
@@ -15363,15 +15363,15 @@ _gtk_widget_update_parent_muxer (GtkWidget *widget)
|
||||
|
||||
parent_muxer = parent ? _gtk_widget_get_action_muxer (parent) : NULL;
|
||||
|
||||
g_action_muxer_set_parent (widget->priv->muxer, parent_muxer);
|
||||
gtk_action_muxer_set_parent (widget->priv->muxer, parent_muxer);
|
||||
}
|
||||
|
||||
GActionMuxer *
|
||||
GtkActionMuxer *
|
||||
_gtk_widget_get_action_muxer (GtkWidget *widget)
|
||||
{
|
||||
if (widget->priv->muxer == NULL)
|
||||
{
|
||||
widget->priv->muxer = g_action_muxer_new ();
|
||||
widget->priv->muxer = gtk_action_muxer_new ();
|
||||
_gtk_widget_update_parent_muxer (widget);
|
||||
}
|
||||
|
||||
@@ -15396,7 +15396,7 @@ gtk_widget_insert_action_group (GtkWidget *widget,
|
||||
const gchar *name,
|
||||
GActionGroup *group)
|
||||
{
|
||||
GActionMuxer *muxer;
|
||||
GtkActionMuxer *muxer;
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
g_return_if_fail (name != NULL);
|
||||
@@ -15404,9 +15404,9 @@ gtk_widget_insert_action_group (GtkWidget *widget,
|
||||
muxer = _gtk_widget_get_action_muxer (widget);
|
||||
|
||||
if (group)
|
||||
g_action_muxer_insert (muxer, name, group);
|
||||
gtk_action_muxer_insert (muxer, name, group);
|
||||
else
|
||||
g_action_muxer_remove (muxer, name);
|
||||
gtk_action_muxer_remove (muxer, name);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
|
@@ -27,7 +27,7 @@
|
||||
|
||||
#include "gtkcsstypesprivate.h"
|
||||
#include "gtkwidget.h"
|
||||
#include "gactionmuxer.h"
|
||||
#include "gtkactionmuxer.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -147,7 +147,7 @@ void _gtk_widget_invalidate_style_context (GtkWidget *widget
|
||||
void _gtk_widget_style_context_invalidated (GtkWidget *widget);
|
||||
|
||||
void _gtk_widget_update_parent_muxer (GtkWidget *widget);
|
||||
GActionMuxer * _gtk_widget_get_action_muxer (GtkWidget *widget);
|
||||
GtkActionMuxer * _gtk_widget_get_action_muxer (GtkWidget *widget);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@@ -216,6 +216,25 @@ random_menu_new (GRand *rand,
|
||||
|
||||
static void assert_menu_equality (GtkContainer *container, GMenuModel *model);
|
||||
|
||||
static const gchar *
|
||||
get_label (GtkMenuItem *item)
|
||||
{
|
||||
GList *children = gtk_container_get_children (GTK_CONTAINER (item));
|
||||
const gchar *label = NULL;
|
||||
|
||||
while (children)
|
||||
{
|
||||
if (GTK_IS_CONTAINER (children->data))
|
||||
children = g_list_concat (children, gtk_container_get_children (children->data));
|
||||
else if (GTK_IS_LABEL (children->data))
|
||||
label = gtk_label_get_text (children->data);
|
||||
|
||||
children = g_list_delete_link (children, children);
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
/* a bit complicated with the separators...
|
||||
*
|
||||
* with_separators are if subsections of this GMenuModel should have
|
||||
@@ -307,7 +326,7 @@ assert_section_equality (GSList **children,
|
||||
our_children = g_slist_remove (our_children, item);
|
||||
|
||||
/* get_label() returns "" when it ought to return NULL */
|
||||
g_assert_cmpstr (gtk_menu_item_get_label (item), ==, label ? label : "");
|
||||
g_assert_cmpstr (get_label (item), ==, label ? label : "");
|
||||
submenu_widget = gtk_menu_item_get_submenu (item);
|
||||
|
||||
if (submenu)
|
||||
|
Reference in New Issue
Block a user