1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
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>
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))
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
;
43 #pragma GCC diagnostic push
44 #pragma GCC diagnostic ignored "-Wunused-function"
46 G_DEFINE_TYPE (GLOAction
, g_lo_action
, G_TYPE_OBJECT
);
48 #pragma GCC diagnostic pop
54 return G_LO_ACTION (g_object_new (G_TYPE_LO_ACTION
, NULL
));
58 g_lo_action_init (GLOAction
*action
)
61 action
->submenu
= FALSE
;
62 action
->enabled
= TRUE
;
63 action
->parameter_type
= NULL
;
64 action
->state_type
= NULL
;
65 action
->state_hint
= NULL
;
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
);
84 g_variant_unref (action
->state
);
86 G_OBJECT_CLASS (g_lo_action_parent_class
)->finalize (object
);
90 g_lo_action_class_init (GLOActionClass
*klass
)
92 GObjectClass
*object_class
= G_OBJECT_CLASS(klass
);
94 object_class
->finalize
= g_lo_action_finalize
;
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
*);
110 #pragma GCC diagnostic push
111 #pragma GCC diagnostic ignored "-Wunused-function"
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
));
118 #pragma GCC diagnostic pop
122 g_lo_action_group_list_actions (GActionGroup
*group
)
124 GLOActionGroup
*loGroup
= G_LO_ACTION_GROUP (group
);
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
);
143 g_lo_action_group_query_action (GActionGroup
*group
,
144 const gchar
*action_name
,
146 const GVariantType
**parameter_type
,
147 const GVariantType
**state_type
,
148 GVariant
**state_hint
,
151 //SAL_INFO("vcl.unity", "g_lo_action_group_query_action on " << group);
152 GLOActionGroup
*lo_group
= G_LO_ACTION_GROUP (group
);
155 action
= G_LO_ACTION (g_hash_table_lookup (lo_group
->priv
->table
, action_name
));
162 GtkSalFrame
* pFrame
= lo_group
->priv
->frame
;
164 pFrame
->EnsureDbusMenuSynced();
166 *enabled
= action
->enabled
;
170 *parameter_type
= action
->parameter_type
;
173 *state_type
= action
->state_type
;
176 *state_hint
= (action
->state_hint
) ? g_variant_ref (action
->state_hint
) : NULL
;
179 *state
= (action
->state
) ? g_variant_ref (action
->state
) : NULL
;
185 g_lo_action_group_perform_submenu_action (GLOActionGroup
*group
,
186 const gchar
*action_name
,
190 GtkSalFrame
* pFrame
= group
->priv
->frame
;
191 SAL_INFO("vcl.unity", "g_lo_action_group_perform_submenu_action on " << group
<< " for frame " << pFrame
);
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
);
204 pSalMenu
->Activate();
206 pSalMenu
->Deactivate (action_name
);
211 g_lo_action_group_change_state (GActionGroup
*group
,
212 const gchar
*action_name
,
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
));
228 g_lo_action_group_perform_submenu_action (lo_group
, action_name
, value
);
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
));
241 if (g_variant_is_of_type (value
, action
->state_type
))
244 g_variant_unref(action
->state
);
246 action
->state
= g_variant_ref (value
);
249 g_action_group_action_added (G_ACTION_GROUP (group
), action_name
);
251 g_action_group_action_state_changed (group
, action_name
, value
);
257 g_variant_unref (value
);
261 g_lo_action_group_activate (GActionGroup
*group
,
262 const gchar
*action_name
,
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
);
287 g_lo_action_group_insert (GLOActionGroup
*group
,
288 const gchar
*action_name
,
292 g_lo_action_group_insert_stateful (group
, action_name
, item_id
, submenu
, NULL
, NULL
, NULL
, NULL
);
296 g_lo_action_group_insert_stateful (GLOActionGroup
*group
,
297 const gchar
*action_name
,
300 const GVariantType
*parameter_type
,
301 const GVariantType
*state_type
,
302 GVariant
*state_hint
,
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
;
323 action
->parameter_type
= const_cast<GVariantType
*>(parameter_type
);
326 action
->state_type
= const_cast<GVariantType
*>(state_type
);
329 action
->state_hint
= g_variant_ref_sink (state_hint
);
332 action
->state
= g_variant_ref_sink (state
);
334 g_action_group_action_added (G_ACTION_GROUP (group
), action_name
);
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
);
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
;
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
));
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
;
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
);
389 g_lo_action_group_set_action_enabled (GLOActionGroup
*group
,
390 const gchar
*action_name
,
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
));
402 action
->enabled
= enabled
;
404 g_action_group_action_enabled_changed (G_ACTION_GROUP (group
), action_name
, enabled
);
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
);
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
));
439 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */