Branch libreoffice-5-0-4
[LibreOffice.git] / vcl / unx / gtk / window / gloactiongroup.cxx
blob23307fd2a8df27d6dfe9f2e3c74278dc2c06a7c4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <unx/gtk/gtksalmenu.hxx>
12 #ifdef ENABLE_GMENU_INTEGRATION
14 #include <unx/gtk/gloactiongroup.h>
15 #include <unx/gtk/gtkinst.hxx>
16 #include <unx/gtk/gtkframe.hxx>
19 * GLOAction
22 #define G_TYPE_LO_ACTION (g_lo_action_get_type ())
23 #define G_LO_ACTION(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
24 G_TYPE_LO_ACTION, GLOAction))
26 struct _GLOAction
28 GObject parent_instance;
30 gint item_id; // Menu item ID.
31 gboolean submenu; // TRUE if action is a submenu action.
32 gboolean enabled; // TRUE if action is enabled.
33 GVariantType* parameter_type; // A GVariantType with the action parameter type.
34 GVariantType* state_type; // A GVariantType with item state type
35 GVariant* state_hint; // A GVariant with state hints.
36 GVariant* state; // A GVariant with current item state
39 typedef GObjectClass GLOActionClass;
40 typedef struct _GLOAction GLOAction;
42 #ifdef __GNUC__
43 #pragma GCC diagnostic push
44 #pragma GCC diagnostic ignored "-Wunused-function"
45 #endif
46 G_DEFINE_TYPE (GLOAction, g_lo_action, G_TYPE_OBJECT);
47 #ifdef __GNUC__
48 #pragma GCC diagnostic pop
49 #endif
51 GLOAction*
52 g_lo_action_new()
54 return G_LO_ACTION (g_object_new (G_TYPE_LO_ACTION, NULL));
57 static void
58 g_lo_action_init (GLOAction *action)
60 action->item_id = -1;
61 action->submenu = FALSE;
62 action->enabled = TRUE;
63 action->parameter_type = NULL;
64 action->state_type = NULL;
65 action->state_hint = NULL;
66 action->state = NULL;
69 static void
70 g_lo_action_finalize (GObject *object)
72 GLOAction* action = G_LO_ACTION(object);
74 if (action->parameter_type)
75 g_variant_type_free (action->parameter_type);
77 if (action->state_type)
78 g_variant_type_free (action->state_type);
80 if (action->state_hint)
81 g_variant_unref (action->state_hint);
83 if (action->state)
84 g_variant_unref (action->state);
86 G_OBJECT_CLASS (g_lo_action_parent_class)->finalize (object);
89 static void
90 g_lo_action_class_init (GLOActionClass *klass)
92 GObjectClass *object_class = G_OBJECT_CLASS(klass);
94 object_class->finalize = g_lo_action_finalize;
98 * GLOActionGroup
101 struct _GLOActionGroupPrivate
103 GHashTable *table; /* string -> GLOAction */
104 GtkSalFrame *frame; /* Frame to which GActionGroup is associated. */
107 static void g_lo_action_group_iface_init (GActionGroupInterface *);
109 #ifdef __GNUC__
110 #pragma GCC diagnostic push
111 #pragma GCC diagnostic ignored "-Wunused-function"
112 #endif
113 G_DEFINE_TYPE_WITH_CODE (GLOActionGroup,
114 g_lo_action_group, G_TYPE_OBJECT,
115 G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP,
116 g_lo_action_group_iface_init));
117 #ifdef __GNUC__
118 #pragma GCC diagnostic pop
119 #endif
121 static gchar **
122 g_lo_action_group_list_actions (GActionGroup *group)
124 GLOActionGroup *loGroup = G_LO_ACTION_GROUP (group);
125 GHashTableIter iter;
126 gint n, i = 0;
127 gchar **keys;
128 gpointer key;
130 n = g_hash_table_size (loGroup->priv->table);
131 keys = g_new (gchar *, n + 1);
133 g_hash_table_iter_init (&iter, loGroup->priv->table);
134 while (g_hash_table_iter_next (&iter, &key, NULL))
135 keys[i++] = g_strdup (static_cast<gchar*>(key));
136 g_assert_cmpint (i, ==, n);
137 keys[n] = NULL;
139 return keys;
142 static gboolean
143 g_lo_action_group_query_action (GActionGroup *group,
144 const gchar *action_name,
145 gboolean *enabled,
146 const GVariantType **parameter_type,
147 const GVariantType **state_type,
148 GVariant **state_hint,
149 GVariant **state)
151 //SAL_INFO("vcl.unity", "g_lo_action_group_query_action on " << group);
152 GLOActionGroup *lo_group = G_LO_ACTION_GROUP (group);
153 GLOAction* action;
155 action = G_LO_ACTION (g_hash_table_lookup (lo_group->priv->table, action_name));
157 if (action == NULL)
158 return FALSE;
160 if (enabled)
162 GtkSalFrame* pFrame = lo_group->priv->frame;
163 if (pFrame) {
164 pFrame->EnsureDbusMenuSynced();
166 *enabled = action->enabled;
169 if (parameter_type)
170 *parameter_type = action->parameter_type;
172 if (state_type)
173 *state_type = action->state_type;
175 if (state_hint)
176 *state_hint = (action->state_hint) ? g_variant_ref (action->state_hint) : NULL;
178 if (state)
179 *state = (action->state) ? g_variant_ref (action->state) : NULL;
181 return TRUE;
184 static void
185 g_lo_action_group_perform_submenu_action (GLOActionGroup *group,
186 const gchar *action_name,
187 GVariant *state)
190 GtkSalFrame* pFrame = group->priv->frame;
191 SAL_INFO("vcl.unity", "g_lo_action_group_perform_submenu_action on " << group << " for frame " << pFrame);
193 if (pFrame == NULL)
194 return;
196 GtkSalMenu* pSalMenu = static_cast<GtkSalMenu*> (pFrame->GetMenu());
197 SAL_INFO("vcl.unity", "g_lo_action_group_perform_submenu_action on " << group << " for menu " << pSalMenu);
199 if (pSalMenu != NULL) {
200 gboolean bState = g_variant_get_boolean (state);
201 SAL_INFO("vcl.unity", "g_lo_action_group_perform_submenu_action on " << group << " to " << bState);
203 if (bState)
204 pSalMenu->Activate();
205 else
206 pSalMenu->Deactivate (action_name);
210 static void
211 g_lo_action_group_change_state (GActionGroup *group,
212 const gchar *action_name,
213 GVariant *value)
215 SAL_INFO("vcl.unity", "g_lo_action_group_change_state on " << group );
216 g_return_if_fail (value != NULL);
218 g_variant_ref_sink (value);
220 if (action_name != NULL)
222 GLOActionGroup* lo_group = G_LO_ACTION_GROUP (group);
223 GLOAction* action = G_LO_ACTION (g_hash_table_lookup (lo_group->priv->table, action_name));
225 if (action != NULL)
227 if (action->submenu)
228 g_lo_action_group_perform_submenu_action (lo_group, action_name, value);
229 else
231 gboolean is_new = FALSE;
233 /* If action already exists but has no state, it should be removed and added again. */
234 if (action->state_type == NULL)
236 g_action_group_action_removed (G_ACTION_GROUP (group), action_name);
237 action->state_type = g_variant_type_copy (g_variant_get_type(value));
238 is_new = TRUE;
241 if (g_variant_is_of_type (value, action->state_type))
243 if (action->state)
244 g_variant_unref(action->state);
246 action->state = g_variant_ref (value);
248 if (is_new)
249 g_action_group_action_added (G_ACTION_GROUP (group), action_name);
250 else
251 g_action_group_action_state_changed (group, action_name, value);
257 g_variant_unref (value);
260 static void
261 g_lo_action_group_activate (GActionGroup *group,
262 const gchar *action_name,
263 GVariant *parameter)
265 GLOActionGroup *lo_group = G_LO_ACTION_GROUP (group);
266 GtkSalFrame *pFrame = lo_group->priv->frame;
267 SAL_INFO("vcl.unity", "g_lo_action_group_activate on group " << group << " for frame " << pFrame << " with parameter " << parameter);
269 if ( parameter != NULL )
270 g_action_group_change_action_state( group, action_name, parameter );
272 if ( pFrame != NULL )
274 GtkSalMenu* pSalMenu = static_cast< GtkSalMenu* >( pFrame->GetMenu() );
275 SAL_INFO("vcl.unity", "g_lo_action_group_activate for menu " << pSalMenu);
277 if ( pSalMenu != NULL )
279 GLOAction* action = G_LO_ACTION (g_hash_table_lookup (lo_group->priv->table, action_name));
280 SAL_INFO("vcl.unity", "g_lo_action_group_activate dispatching action " << action << " named " << action_name << " on menu " << pSalMenu);
281 pSalMenu->DispatchCommand( action->item_id, action_name );
286 void
287 g_lo_action_group_insert (GLOActionGroup *group,
288 const gchar *action_name,
289 gint item_id,
290 gboolean submenu)
292 g_lo_action_group_insert_stateful (group, action_name, item_id, submenu, NULL, NULL, NULL, NULL);
295 void
296 g_lo_action_group_insert_stateful (GLOActionGroup *group,
297 const gchar *action_name,
298 gint item_id,
299 gboolean submenu,
300 const GVariantType *parameter_type,
301 const GVariantType *state_type,
302 GVariant *state_hint,
303 GVariant *state)
305 g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
307 GLOAction* old_action = G_LO_ACTION (g_hash_table_lookup (group->priv->table, action_name));
309 if (old_action == NULL || old_action->item_id != item_id)
311 if (old_action != NULL)
312 g_lo_action_group_remove (group, action_name);
313 // g_action_group_action_removed (G_ACTION_GROUP (group), action_name);
315 GLOAction* action = g_lo_action_new();
317 g_hash_table_insert (group->priv->table, g_strdup (action_name), action);
319 action->item_id = item_id;
320 action->submenu = submenu;
322 if (parameter_type)
323 action->parameter_type = const_cast<GVariantType*>(parameter_type);
325 if (state_type)
326 action->state_type = const_cast<GVariantType*>(state_type);
328 if (state_hint)
329 action->state_hint = g_variant_ref_sink (state_hint);
331 if (state)
332 action->state = g_variant_ref_sink (state);
334 g_action_group_action_added (G_ACTION_GROUP (group), action_name);
338 static void
339 g_lo_action_group_finalize (GObject *object)
341 GLOActionGroup *lo_group = G_LO_ACTION_GROUP (object);
343 g_hash_table_unref (lo_group->priv->table);
345 G_OBJECT_CLASS (g_lo_action_group_parent_class)->finalize (object);
348 static void
349 g_lo_action_group_init (GLOActionGroup *group)
351 SAL_INFO("vcl.unity", "g_lo_action_group_init on " << group);
352 group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
353 G_TYPE_LO_ACTION_GROUP,
354 GLOActionGroupPrivate);
355 group->priv->table = g_hash_table_new_full (g_str_hash, g_str_equal,
356 g_free, g_object_unref);
357 group->priv->frame = NULL;
360 static void
361 g_lo_action_group_class_init (GLOActionGroupClass *klass)
363 GObjectClass *object_class = G_OBJECT_CLASS (klass);
365 object_class->finalize = g_lo_action_group_finalize;
367 g_type_class_add_private (klass, sizeof (GLOActionGroupPrivate));
370 static void
371 g_lo_action_group_iface_init (GActionGroupInterface *iface)
373 iface->list_actions = g_lo_action_group_list_actions;
374 iface->query_action = g_lo_action_group_query_action;
375 iface->change_action_state = g_lo_action_group_change_state;
376 iface->activate_action = g_lo_action_group_activate;
379 GLOActionGroup *
380 g_lo_action_group_new (gpointer frame)
382 GLOActionGroup* group = G_LO_ACTION_GROUP (g_object_new (G_TYPE_LO_ACTION_GROUP, NULL));
383 group->priv->frame = static_cast< GtkSalFrame* > (frame);
385 return group;
388 void
389 g_lo_action_group_set_action_enabled (GLOActionGroup *group,
390 const gchar *action_name,
391 gboolean enabled)
393 SAL_INFO("vcl.unity", "g_lo_action_group_set_action_enabled on " << group);
394 g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
395 g_return_if_fail (action_name != NULL);
397 GLOAction* action = G_LO_ACTION (g_hash_table_lookup (group->priv->table, action_name));
399 if (action == NULL)
400 return;
402 action->enabled = enabled;
404 g_action_group_action_enabled_changed (G_ACTION_GROUP (group), action_name, enabled);
407 void
408 g_lo_action_group_remove (GLOActionGroup *group,
409 const gchar *action_name)
411 SAL_INFO("vcl.unity", "g_lo_action_group_remove on " << group);
412 g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
414 if (action_name != NULL)
416 g_action_group_action_removed (G_ACTION_GROUP (group), action_name);
417 g_hash_table_remove (group->priv->table, action_name);
421 void
422 g_lo_action_group_clear (GLOActionGroup *group)
424 SAL_INFO("vcl.unity", "g_lo_action_group_clear on " << group);
425 g_return_if_fail (G_IS_LO_ACTION_GROUP (group));
427 GList* keys = g_hash_table_get_keys (group->priv->table);
429 for (GList* element = g_list_first (keys); element != NULL; element = g_list_next (element))
431 g_lo_action_group_remove (group, static_cast<gchar*>(element->data));
434 g_list_free (keys);
437 #endif
439 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */