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 #include <unx/gtk/gloactiongroup.h>
14 #include <sal/log.hxx>
20 #define G_TYPE_LO_ACTION (g_lo_action_get_type ())
21 #define G_LO_ACTION(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
22 G_TYPE_LO_ACTION, GLOAction))
27 GObject parent_instance
;
29 gint item_id
; // Menu item ID.
30 bool submenu
; // TRUE if action is a submenu action.
31 bool enabled
; // TRUE if action is enabled.
32 GVariantType
* parameter_type
; // A GVariantType with the action parameter type.
33 GVariantType
* state_type
; // A GVariantType with item state type
34 GVariant
* state_hint
; // A GVariant with state hints.
35 GVariant
* state
; // A GVariant with current item state
40 typedef GObjectClass GLOActionClass
;
43 #pragma GCC diagnostic push
44 #pragma GCC diagnostic ignored "-Wunused-function"
46 #if __has_warning("-Wdeprecated-volatile")
47 #pragma clang diagnostic ignored "-Wdeprecated-volatile"
51 G_DEFINE_TYPE (GLOAction
, g_lo_action
, G_TYPE_OBJECT
);
53 #pragma GCC diagnostic pop
59 return G_LO_ACTION (g_object_new (G_TYPE_LO_ACTION
, nullptr));
63 g_lo_action_init (GLOAction
*action
)
66 action
->submenu
= false;
67 action
->enabled
= true;
68 action
->parameter_type
= nullptr;
69 action
->state_type
= nullptr;
70 action
->state_hint
= nullptr;
71 action
->state
= nullptr;
75 g_lo_action_finalize (GObject
*object
)
77 GLOAction
* action
= G_LO_ACTION(object
);
79 if (action
->parameter_type
)
80 g_variant_type_free (action
->parameter_type
);
82 if (action
->state_type
)
83 g_variant_type_free (action
->state_type
);
85 if (action
->state_hint
)
86 g_variant_unref (action
->state_hint
);
89 g_variant_unref (action
->state
);
91 G_OBJECT_CLASS (g_lo_action_parent_class
)->finalize (object
);
95 g_lo_action_class_init (GLOActionClass
*klass
)
97 GObjectClass
*object_class
= G_OBJECT_CLASS(klass
);
99 object_class
->finalize
= g_lo_action_finalize
;
106 struct GLOActionGroupPrivate
108 GHashTable
*table
; /* string -> GLOAction */
111 static void g_lo_action_group_iface_init (GActionGroupInterface
*);
114 #pragma GCC diagnostic push
115 #pragma GCC diagnostic ignored "-Wunused-function"
116 #if defined __clang__
117 #if __has_warning("-Wdeprecated-volatile")
118 #pragma clang diagnostic ignored "-Wdeprecated-volatile"
122 G_DEFINE_TYPE_WITH_CODE (GLOActionGroup
,
123 g_lo_action_group
, G_TYPE_OBJECT
,
124 G_ADD_PRIVATE(GLOActionGroup
)
125 G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP
,
126 g_lo_action_group_iface_init
));
128 #pragma GCC diagnostic pop
132 g_lo_action_group_list_actions (GActionGroup
*group
)
134 GLOActionGroup
*loGroup
= G_LO_ACTION_GROUP (group
);
140 n
= g_hash_table_size (loGroup
->priv
->table
);
141 keys
= g_new (gchar
*, n
+ 1);
143 g_hash_table_iter_init (&iter
, loGroup
->priv
->table
);
144 while (g_hash_table_iter_next (&iter
, &key
, nullptr))
145 keys
[i
++] = g_strdup (static_cast<gchar
*>(key
));
146 g_assert_cmpint (i
, ==, n
);
153 g_lo_action_group_query_action (GActionGroup
*group
,
154 const gchar
*action_name
,
156 const GVariantType
**parameter_type
,
157 const GVariantType
**state_type
,
158 GVariant
**state_hint
,
161 //SAL_INFO("vcl.unity", "g_lo_action_group_query_action on " << group);
162 GLOActionGroup
*lo_group
= G_LO_ACTION_GROUP (group
);
163 GLOAction
* action
= G_LO_ACTION (g_hash_table_lookup (lo_group
->priv
->table
, action_name
));
165 if (action
== nullptr)
170 *enabled
= action
->enabled
;
174 *parameter_type
= action
->parameter_type
;
177 *state_type
= action
->state_type
;
180 *state_hint
= (action
->state_hint
) ? g_variant_ref (action
->state_hint
) : nullptr;
183 *state
= (action
->state
) ? g_variant_ref (action
->state
) : nullptr;
189 g_lo_action_group_perform_submenu_action (GLOActionGroup
*group
,
190 const gchar
*action_name
,
193 bool bState
= g_variant_get_boolean (state
);
194 SAL_INFO("vcl.unity", "g_lo_action_group_perform_submenu_action on " << group
<< " to " << bState
);
197 GtkSalMenu::Activate(action_name
);
199 GtkSalMenu::Deactivate(action_name
);
203 g_lo_action_group_change_state (GActionGroup
*group
,
204 const gchar
*action_name
,
207 SAL_INFO("vcl.unity", "g_lo_action_group_change_state on " << group
);
208 g_return_if_fail (value
!= nullptr);
210 g_variant_ref_sink (value
);
212 if (action_name
!= nullptr)
214 GLOActionGroup
* lo_group
= G_LO_ACTION_GROUP (group
);
215 GLOAction
* action
= G_LO_ACTION (g_hash_table_lookup (lo_group
->priv
->table
, action_name
));
217 if (action
!= nullptr)
220 g_lo_action_group_perform_submenu_action (lo_group
, action_name
, value
);
225 /* If action already exists but has no state, it should be removed and added again. */
226 if (action
->state_type
== nullptr)
228 g_action_group_action_removed (G_ACTION_GROUP (group
), action_name
);
229 action
->state_type
= g_variant_type_copy (g_variant_get_type(value
));
233 if (g_variant_is_of_type (value
, action
->state_type
))
236 g_variant_unref(action
->state
);
238 action
->state
= g_variant_ref (value
);
241 g_action_group_action_added (G_ACTION_GROUP (group
), action_name
);
243 g_action_group_action_state_changed (group
, action_name
, value
);
249 g_variant_unref (value
);
253 g_lo_action_group_activate (GActionGroup
*group
,
254 const gchar
*action_name
,
257 if (parameter
!= nullptr)
258 g_action_group_change_action_state(group
, action_name
, parameter
);
259 GtkSalMenu::DispatchCommand(action_name
);
263 g_lo_action_group_insert (GLOActionGroup
*group
,
264 const gchar
*action_name
,
268 g_lo_action_group_insert_stateful (group
, action_name
, item_id
, submenu
, nullptr, nullptr, nullptr, nullptr);
272 g_lo_action_group_insert_stateful (GLOActionGroup
*group
,
273 const gchar
*action_name
,
276 const GVariantType
*parameter_type
,
277 const GVariantType
*state_type
,
278 GVariant
*state_hint
,
281 g_return_if_fail (G_IS_LO_ACTION_GROUP (group
));
283 GLOAction
* old_action
= G_LO_ACTION (g_hash_table_lookup (group
->priv
->table
, action_name
));
285 if (old_action
!= nullptr && old_action
->item_id
== item_id
)
288 if (old_action
!= nullptr)
289 g_lo_action_group_remove (group
, action_name
);
291 GLOAction
* action
= g_lo_action_new();
293 g_hash_table_insert (group
->priv
->table
, g_strdup (action_name
), action
);
295 action
->item_id
= item_id
;
296 action
->submenu
= submenu
;
299 action
->parameter_type
= const_cast<GVariantType
*>(parameter_type
);
302 action
->state_type
= const_cast<GVariantType
*>(state_type
);
305 action
->state_hint
= g_variant_ref_sink (state_hint
);
308 action
->state
= g_variant_ref_sink (state
);
310 g_action_group_action_added (G_ACTION_GROUP (group
), action_name
);
314 g_lo_action_group_finalize (GObject
*object
)
316 GLOActionGroup
*lo_group
= G_LO_ACTION_GROUP (object
);
318 g_hash_table_unref (lo_group
->priv
->table
);
320 G_OBJECT_CLASS (g_lo_action_group_parent_class
)->finalize (object
);
324 g_lo_action_group_init (GLOActionGroup
*group
)
326 SAL_INFO("vcl.unity", "g_lo_action_group_init on " << group
);
327 group
->priv
= static_cast<GLOActionGroupPrivate
*>(g_lo_action_group_get_instance_private (group
));
328 group
->priv
->table
= g_hash_table_new_full (g_str_hash
, g_str_equal
,
329 g_free
, g_object_unref
);
333 g_lo_action_group_class_init (GLOActionGroupClass
*klass
)
335 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
337 object_class
->finalize
= g_lo_action_group_finalize
;
341 g_lo_action_group_iface_init (GActionGroupInterface
*iface
)
343 iface
->list_actions
= g_lo_action_group_list_actions
;
344 iface
->query_action
= g_lo_action_group_query_action
;
345 iface
->change_action_state
= g_lo_action_group_change_state
;
346 iface
->activate_action
= g_lo_action_group_activate
;
350 g_lo_action_group_new()
352 GLOActionGroup
* group
= G_LO_ACTION_GROUP (g_object_new (G_TYPE_LO_ACTION_GROUP
, nullptr));
357 g_lo_action_group_set_action_enabled (GLOActionGroup
*group
,
358 const gchar
*action_name
,
361 SAL_INFO("vcl.unity", "g_lo_action_group_set_action_enabled on " << group
);
362 g_return_if_fail (G_IS_LO_ACTION_GROUP (group
));
363 g_return_if_fail (action_name
!= nullptr);
365 GLOAction
* action
= G_LO_ACTION (g_hash_table_lookup (group
->priv
->table
, action_name
));
367 if (action
== nullptr)
370 action
->enabled
= enabled
;
372 g_action_group_action_enabled_changed (G_ACTION_GROUP (group
), action_name
, enabled
);
376 g_lo_action_group_remove (GLOActionGroup
*group
,
377 const gchar
*action_name
)
379 SAL_INFO("vcl.unity", "g_lo_action_group_remove on " << group
);
380 g_return_if_fail (G_IS_LO_ACTION_GROUP (group
));
382 if (action_name
!= nullptr)
384 g_action_group_action_removed (G_ACTION_GROUP (group
), action_name
);
385 g_hash_table_remove (group
->priv
->table
, action_name
);
390 g_lo_action_group_clear (GLOActionGroup
*group
)
392 SAL_INFO("vcl.unity", "g_lo_action_group_clear on " << group
);
393 g_return_if_fail (G_IS_LO_ACTION_GROUP (group
));
395 GList
* keys
= g_hash_table_get_keys (group
->priv
->table
);
397 for (GList
* element
= g_list_first (keys
); element
!= nullptr; element
= g_list_next (element
))
399 g_lo_action_group_remove (group
, static_cast<gchar
*>(element
->data
));
405 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */