1 /*
2  * This file is part of gtkD.
3  *
4  * gtkD is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 3
7  * of the License, or (at your option) any later version, with
8  * some exceptions, please read the COPYING file.
9  *
10  * gtkD is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with gtkD; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
18  */
19 
20 // generated automatically - do not change
21 // find conversion definition on APILookup.txt
22 // implement new conversion functionalities on the wrap.utils pakage
23 
24 
25 module gtk.ActionGroup;
26 
27 private import glib.ConstructionException;
28 private import glib.ListG;
29 private import glib.Str;
30 private import gobject.ObjectG;
31 private import gobject.Signals;
32 private import gtk.AccelGroup;
33 private import gtk.Action;
34 private import gtk.BuildableIF;
35 private import gtk.BuildableT;
36 private import gtk.Widget;
37 private import gtk.c.functions;
38 public  import gtk.c.types;
39 public  import gtkc.gtktypes;
40 private import std.algorithm;
41 
42 
43 /**
44  * Actions are organised into groups. An action group is essentially a
45  * map from names to #GtkAction objects.
46  * 
47  * All actions that would make sense to use in a particular context
48  * should be in a single group. Multiple action groups may be used for a
49  * particular user interface. In fact, it is expected that most nontrivial
50  * applications will make use of multiple groups. For example, in an
51  * application that can edit multiple documents, one group holding global
52  * actions (e.g. quit, about, new), and one group per document holding
53  * actions that act on that document (eg. save, cut/copy/paste, etc). Each
54  * window’s menus would be constructed from a combination of two action
55  * groups.
56  * 
57  * ## Accelerators ## {#Action-Accel}
58  * 
59  * Accelerators are handled by the GTK+ accelerator map. All actions are
60  * assigned an accelerator path (which normally has the form
61  * `<Actions>/group-name/action-name`) and a shortcut is associated with
62  * this accelerator path. All menuitems and toolitems take on this accelerator
63  * path. The GTK+ accelerator map code makes sure that the correct shortcut
64  * is displayed next to the menu item.
65  * 
66  * # GtkActionGroup as GtkBuildable # {#GtkActionGroup-BUILDER-UI}
67  * 
68  * The #GtkActionGroup implementation of the #GtkBuildable interface accepts
69  * #GtkAction objects as <child> elements in UI definitions.
70  * 
71  * Note that it is probably more common to define actions and action groups
72  * in the code, since they are directly related to what the code can do.
73  * 
74  * The GtkActionGroup implementation of the GtkBuildable interface supports
75  * a custom <accelerator> element, which has attributes named “key“ and
76  * “modifiers“ and allows to specify accelerators. This is similar to the
77  * <accelerator> element of #GtkWidget, the main difference is that
78  * it doesn’t allow you to specify a signal.
79  * 
80  * ## A #GtkDialog UI definition fragment. ##
81  * |[
82  * <object class="GtkActionGroup" id="actiongroup">
83  * <child>
84  * <object class="GtkAction" id="About">
85  * <property name="name">About</property>
86  * <property name="stock_id">gtk-about</property>
87  * <signal handler="about_activate" name="activate"/>
88  * </object>
89  * <accelerator key="F1" modifiers="GDK_CONTROL_MASK | GDK_SHIFT_MASK"/>
90  * </child>
91  * </object>
92  * ]|
93  */
94 public class ActionGroup : ObjectG, BuildableIF
95 {
96 	/** the main Gtk struct */
97 	protected GtkActionGroup* gtkActionGroup;
98 
99 	/** Get the main Gtk struct */
100 	public GtkActionGroup* getActionGroupStruct(bool transferOwnership = false)
101 	{
102 		if (transferOwnership)
103 			ownedRef = false;
104 		return gtkActionGroup;
105 	}
106 
107 	/** the main Gtk struct as a void* */
108 	protected override void* getStruct()
109 	{
110 		return cast(void*)gtkActionGroup;
111 	}
112 
113 	protected override void setStruct(GObject* obj)
114 	{
115 		gtkActionGroup = cast(GtkActionGroup*)obj;
116 		super.setStruct(obj);
117 	}
118 
119 	/**
120 	 * Sets our main struct and passes it to the parent class.
121 	 */
122 	public this (GtkActionGroup* gtkActionGroup, bool ownedRef = false)
123 	{
124 		this.gtkActionGroup = gtkActionGroup;
125 		super(cast(GObject*)gtkActionGroup, ownedRef);
126 	}
127 
128 	// add the Buildable capabilities
129 	mixin BuildableT!(GtkActionGroup);
130 
131 
132 	/** */
133 	public static GType getType()
134 	{
135 		return gtk_action_group_get_type();
136 	}
137 
138 	/**
139 	 * Creates a new #GtkActionGroup object. The name of the action group
140 	 * is used when associating [keybindings][Action-Accel]
141 	 * with the actions.
142 	 *
143 	 * Params:
144 	 *     name = the name of the action group.
145 	 *
146 	 * Returns: the new #GtkActionGroup
147 	 *
148 	 * Since: 2.4
149 	 *
150 	 * Throws: ConstructionException GTK+ fails to create the object.
151 	 */
152 	public this(string name)
153 	{
154 		auto p = gtk_action_group_new(Str.toStringz(name));
155 
156 		if(p is null)
157 		{
158 			throw new ConstructionException("null returned by new");
159 		}
160 
161 		this(cast(GtkActionGroup*) p, true);
162 	}
163 
164 	/**
165 	 * Adds an action object to the action group. Note that this function
166 	 * does not set up the accel path of the action, which can lead to problems
167 	 * if a user tries to modify the accelerator of a menuitem associated with
168 	 * the action. Therefore you must either set the accel path yourself with
169 	 * gtk_action_set_accel_path(), or use
170 	 * `gtk_action_group_add_action_with_accel (..., NULL)`.
171 	 *
172 	 * Params:
173 	 *     action = an action
174 	 *
175 	 * Since: 2.4
176 	 */
177 	public void addAction(Action action)
178 	{
179 		gtk_action_group_add_action(gtkActionGroup, (action is null) ? null : action.getActionStruct());
180 	}
181 
182 	/**
183 	 * Adds an action object to the action group and sets up the accelerator.
184 	 *
185 	 * If @accelerator is %NULL, attempts to use the accelerator associated
186 	 * with the stock_id of the action.
187 	 *
188 	 * Accel paths are set to `<Actions>/group-name/action-name`.
189 	 *
190 	 * Params:
191 	 *     action = the action to add
192 	 *     accelerator = the accelerator for the action, in
193 	 *         the format understood by gtk_accelerator_parse(), or "" for no accelerator, or
194 	 *         %NULL to use the stock accelerator
195 	 *
196 	 * Since: 2.4
197 	 */
198 	public void addActionWithAccel(Action action, string accelerator)
199 	{
200 		gtk_action_group_add_action_with_accel(gtkActionGroup, (action is null) ? null : action.getActionStruct(), Str.toStringz(accelerator));
201 	}
202 
203 	/**
204 	 * This is a convenience function to create a number of actions and add them
205 	 * to the action group.
206 	 *
207 	 * The “activate” signals of the actions are connected to the callbacks
208 	 * and their accel paths are set to `<Actions>/group-name/action-name`.
209 	 *
210 	 * Params:
211 	 *     entries = an array of action descriptions
212 	 *     userData = data to pass to the action callbacks
213 	 *
214 	 * Since: 2.4
215 	 */
216 	public void addActions(GtkActionEntry[] entries, void* userData)
217 	{
218 		gtk_action_group_add_actions(gtkActionGroup, entries.ptr, cast(uint)entries.length, userData);
219 	}
220 
221 	/**
222 	 * This variant of gtk_action_group_add_actions() adds a #GDestroyNotify
223 	 * callback for @user_data.
224 	 *
225 	 * Params:
226 	 *     entries = an array of action descriptions
227 	 *     userData = data to pass to the action callbacks
228 	 *     destroy = destroy notification callback for @user_data
229 	 *
230 	 * Since: 2.4
231 	 */
232 	public void addActionsFull(GtkActionEntry[] entries, void* userData, GDestroyNotify destroy)
233 	{
234 		gtk_action_group_add_actions_full(gtkActionGroup, entries.ptr, cast(uint)entries.length, userData, destroy);
235 	}
236 
237 	/**
238 	 * This is a convenience routine to create a group of radio actions and
239 	 * add them to the action group.
240 	 *
241 	 * The “changed” signal of the first radio action is connected to the
242 	 * @on_change callback and the accel paths of the actions are set to
243 	 * `<Actions>/group-name/action-name`.
244 	 *
245 	 * Params:
246 	 *     entries = an array of radio action descriptions
247 	 *     value = the value of the action to activate initially, or -1 if
248 	 *         no action should be activated
249 	 *     onChange = the callback to connect to the changed signal
250 	 *     userData = data to pass to the action callbacks
251 	 *
252 	 * Since: 2.4
253 	 */
254 	public void addRadioActions(GtkRadioActionEntry[] entries, int value, GCallback onChange, void* userData)
255 	{
256 		gtk_action_group_add_radio_actions(gtkActionGroup, entries.ptr, cast(uint)entries.length, value, onChange, userData);
257 	}
258 
259 	/**
260 	 * This variant of gtk_action_group_add_radio_actions() adds a
261 	 * #GDestroyNotify callback for @user_data.
262 	 *
263 	 * Params:
264 	 *     entries = an array of radio action descriptions
265 	 *     value = the value of the action to activate initially, or -1 if
266 	 *         no action should be activated
267 	 *     onChange = the callback to connect to the changed signal
268 	 *     userData = data to pass to the action callbacks
269 	 *     destroy = destroy notification callback for @user_data
270 	 *
271 	 * Since: 2.4
272 	 */
273 	public void addRadioActionsFull(GtkRadioActionEntry[] entries, int value, GCallback onChange, void* userData, GDestroyNotify destroy)
274 	{
275 		gtk_action_group_add_radio_actions_full(gtkActionGroup, entries.ptr, cast(uint)entries.length, value, onChange, userData, destroy);
276 	}
277 
278 	/**
279 	 * This is a convenience function to create a number of toggle actions and add them
280 	 * to the action group.
281 	 *
282 	 * The “activate” signals of the actions are connected to the callbacks
283 	 * and their accel paths are set to `<Actions>/group-name/action-name`.
284 	 *
285 	 * Params:
286 	 *     entries = an array of toggle action descriptions
287 	 *     userData = data to pass to the action callbacks
288 	 *
289 	 * Since: 2.4
290 	 */
291 	public void addToggleActions(GtkToggleActionEntry[] entries, void* userData)
292 	{
293 		gtk_action_group_add_toggle_actions(gtkActionGroup, entries.ptr, cast(uint)entries.length, userData);
294 	}
295 
296 	/**
297 	 * This variant of gtk_action_group_add_toggle_actions() adds a
298 	 * #GDestroyNotify callback for @user_data.
299 	 *
300 	 * Params:
301 	 *     entries = an array of toggle action descriptions
302 	 *     userData = data to pass to the action callbacks
303 	 *     destroy = destroy notification callback for @user_data
304 	 *
305 	 * Since: 2.4
306 	 */
307 	public void addToggleActionsFull(GtkToggleActionEntry[] entries, void* userData, GDestroyNotify destroy)
308 	{
309 		gtk_action_group_add_toggle_actions_full(gtkActionGroup, entries.ptr, cast(uint)entries.length, userData, destroy);
310 	}
311 
312 	/**
313 	 * Gets the accelerator group.
314 	 *
315 	 * Returns: the accelerator group associated with this action
316 	 *     group or %NULL if there is none.
317 	 *
318 	 * Since: 3.6
319 	 */
320 	public AccelGroup getAccelGroup()
321 	{
322 		auto p = gtk_action_group_get_accel_group(gtkActionGroup);
323 
324 		if(p is null)
325 		{
326 			return null;
327 		}
328 
329 		return ObjectG.getDObject!(AccelGroup)(cast(GtkAccelGroup*) p);
330 	}
331 
332 	/**
333 	 * Looks up an action in the action group by name.
334 	 *
335 	 * Params:
336 	 *     actionName = the name of the action
337 	 *
338 	 * Returns: the action, or %NULL if no action by that name exists
339 	 *
340 	 * Since: 2.4
341 	 */
342 	public Action getAction(string actionName)
343 	{
344 		auto p = gtk_action_group_get_action(gtkActionGroup, Str.toStringz(actionName));
345 
346 		if(p is null)
347 		{
348 			return null;
349 		}
350 
351 		return ObjectG.getDObject!(Action)(cast(GtkAction*) p);
352 	}
353 
354 	/**
355 	 * Gets the name of the action group.
356 	 *
357 	 * Returns: the name of the action group.
358 	 *
359 	 * Since: 2.4
360 	 */
361 	public string getName()
362 	{
363 		return Str.toString(gtk_action_group_get_name(gtkActionGroup));
364 	}
365 
366 	/**
367 	 * Returns %TRUE if the group is sensitive.  The constituent actions
368 	 * can only be logically sensitive (see gtk_action_is_sensitive()) if
369 	 * they are sensitive (see gtk_action_get_sensitive()) and their group
370 	 * is sensitive.
371 	 *
372 	 * Returns: %TRUE if the group is sensitive.
373 	 *
374 	 * Since: 2.4
375 	 */
376 	public bool getSensitive()
377 	{
378 		return gtk_action_group_get_sensitive(gtkActionGroup) != 0;
379 	}
380 
381 	/**
382 	 * Returns %TRUE if the group is visible.  The constituent actions
383 	 * can only be logically visible (see gtk_action_is_visible()) if
384 	 * they are visible (see gtk_action_get_visible()) and their group
385 	 * is visible.
386 	 *
387 	 * Returns: %TRUE if the group is visible.
388 	 *
389 	 * Since: 2.4
390 	 */
391 	public bool getVisible()
392 	{
393 		return gtk_action_group_get_visible(gtkActionGroup) != 0;
394 	}
395 
396 	/**
397 	 * Lists the actions in the action group.
398 	 *
399 	 * Returns: an allocated list of the action objects in the action group
400 	 *
401 	 * Since: 2.4
402 	 */
403 	public ListG listActions()
404 	{
405 		auto p = gtk_action_group_list_actions(gtkActionGroup);
406 
407 		if(p is null)
408 		{
409 			return null;
410 		}
411 
412 		return new ListG(cast(GList*) p);
413 	}
414 
415 	/**
416 	 * Removes an action object from the action group.
417 	 *
418 	 * Params:
419 	 *     action = an action
420 	 *
421 	 * Since: 2.4
422 	 */
423 	public void removeAction(Action action)
424 	{
425 		gtk_action_group_remove_action(gtkActionGroup, (action is null) ? null : action.getActionStruct());
426 	}
427 
428 	/**
429 	 * Sets the accelerator group to be used by every action in this group.
430 	 *
431 	 * Params:
432 	 *     accelGroup = a #GtkAccelGroup to set or %NULL
433 	 *
434 	 * Since: 3.6
435 	 */
436 	public void setAccelGroup(AccelGroup accelGroup)
437 	{
438 		gtk_action_group_set_accel_group(gtkActionGroup, (accelGroup is null) ? null : accelGroup.getAccelGroupStruct());
439 	}
440 
441 	/**
442 	 * Changes the sensitivity of @action_group
443 	 *
444 	 * Params:
445 	 *     sensitive = new sensitivity
446 	 *
447 	 * Since: 2.4
448 	 */
449 	public void setSensitive(bool sensitive)
450 	{
451 		gtk_action_group_set_sensitive(gtkActionGroup, sensitive);
452 	}
453 
454 	/**
455 	 * Sets a function to be used for translating the @label and @tooltip of
456 	 * #GtkActionEntrys added by gtk_action_group_add_actions().
457 	 *
458 	 * If you’re using gettext(), it is enough to set the translation domain
459 	 * with gtk_action_group_set_translation_domain().
460 	 *
461 	 * Params:
462 	 *     func = a #GtkTranslateFunc
463 	 *     data = data to be passed to @func and @notify
464 	 *     notify = a #GDestroyNotify function to be called when @action_group is
465 	 *         destroyed and when the translation function is changed again
466 	 *
467 	 * Since: 2.4
468 	 */
469 	public void setTranslateFunc(GtkTranslateFunc func, void* data, GDestroyNotify notify)
470 	{
471 		gtk_action_group_set_translate_func(gtkActionGroup, func, data, notify);
472 	}
473 
474 	/**
475 	 * Sets the translation domain and uses g_dgettext() for translating the
476 	 * @label and @tooltip of #GtkActionEntrys added by
477 	 * gtk_action_group_add_actions().
478 	 *
479 	 * If you’re not using gettext() for localization, see
480 	 * gtk_action_group_set_translate_func().
481 	 *
482 	 * Params:
483 	 *     domain = the translation domain to use for g_dgettext()
484 	 *         calls, or %NULL to use the domain set with textdomain()
485 	 *
486 	 * Since: 2.4
487 	 */
488 	public void setTranslationDomain(string domain)
489 	{
490 		gtk_action_group_set_translation_domain(gtkActionGroup, Str.toStringz(domain));
491 	}
492 
493 	/**
494 	 * Changes the visible of @action_group.
495 	 *
496 	 * Params:
497 	 *     visible = new visiblity
498 	 *
499 	 * Since: 2.4
500 	 */
501 	public void setVisible(bool visible)
502 	{
503 		gtk_action_group_set_visible(gtkActionGroup, visible);
504 	}
505 
506 	/**
507 	 * Translates a string using the function set with
508 	 * gtk_action_group_set_translate_func(). This
509 	 * is mainly intended for language bindings.
510 	 *
511 	 * Params:
512 	 *     str = a string
513 	 *
514 	 * Returns: the translation of @string
515 	 *
516 	 * Since: 2.6
517 	 */
518 	public string translateString(string str)
519 	{
520 		return Str.toString(gtk_action_group_translate_string(gtkActionGroup, Str.toStringz(str)));
521 	}
522 
523 	protected class OnConnectProxyDelegateWrapper
524 	{
525 		void delegate(Action, Widget, ActionGroup) dlg;
526 		gulong handlerId;
527 
528 		this(void delegate(Action, Widget, ActionGroup) dlg)
529 		{
530 			this.dlg = dlg;
531 			onConnectProxyListeners ~= this;
532 		}
533 
534 		void remove(OnConnectProxyDelegateWrapper source)
535 		{
536 			foreach(index, wrapper; onConnectProxyListeners)
537 			{
538 				if (wrapper.handlerId == source.handlerId)
539 				{
540 					onConnectProxyListeners[index] = null;
541 					onConnectProxyListeners = std.algorithm.remove(onConnectProxyListeners, index);
542 					break;
543 				}
544 			}
545 		}
546 	}
547 	OnConnectProxyDelegateWrapper[] onConnectProxyListeners;
548 
549 	/**
550 	 * The ::connect-proxy signal is emitted after connecting a proxy to
551 	 * an action in the group. Note that the proxy may have been connected
552 	 * to a different action before.
553 	 *
554 	 * This is intended for simple customizations for which a custom action
555 	 * class would be too clumsy, e.g. showing tooltips for menuitems in the
556 	 * statusbar.
557 	 *
558 	 * #GtkUIManager proxies the signal and provides global notification
559 	 * just before any action is connected to a proxy, which is probably more
560 	 * convenient to use.
561 	 *
562 	 * Params:
563 	 *     action = the action
564 	 *     proxy = the proxy
565 	 *
566 	 * Since: 2.4
567 	 */
568 	gulong addOnConnectProxy(void delegate(Action, Widget, ActionGroup) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
569 	{
570 		auto wrapper = new OnConnectProxyDelegateWrapper(dlg);
571 		wrapper.handlerId = Signals.connectData(
572 			this,
573 			"connect-proxy",
574 			cast(GCallback)&callBackConnectProxy,
575 			cast(void*)wrapper,
576 			cast(GClosureNotify)&callBackConnectProxyDestroy,
577 			connectFlags);
578 		return wrapper.handlerId;
579 	}
580 
581 	extern(C) static void callBackConnectProxy(GtkActionGroup* actiongroupStruct, GtkAction* action, GtkWidget* proxy, OnConnectProxyDelegateWrapper wrapper)
582 	{
583 		wrapper.dlg(ObjectG.getDObject!(Action)(action), ObjectG.getDObject!(Widget)(proxy), wrapper.outer);
584 	}
585 
586 	extern(C) static void callBackConnectProxyDestroy(OnConnectProxyDelegateWrapper wrapper, GClosure* closure)
587 	{
588 		wrapper.remove(wrapper);
589 	}
590 
591 	protected class OnDisconnectProxyDelegateWrapper
592 	{
593 		void delegate(Action, Widget, ActionGroup) dlg;
594 		gulong handlerId;
595 
596 		this(void delegate(Action, Widget, ActionGroup) dlg)
597 		{
598 			this.dlg = dlg;
599 			onDisconnectProxyListeners ~= this;
600 		}
601 
602 		void remove(OnDisconnectProxyDelegateWrapper source)
603 		{
604 			foreach(index, wrapper; onDisconnectProxyListeners)
605 			{
606 				if (wrapper.handlerId == source.handlerId)
607 				{
608 					onDisconnectProxyListeners[index] = null;
609 					onDisconnectProxyListeners = std.algorithm.remove(onDisconnectProxyListeners, index);
610 					break;
611 				}
612 			}
613 		}
614 	}
615 	OnDisconnectProxyDelegateWrapper[] onDisconnectProxyListeners;
616 
617 	/**
618 	 * The ::disconnect-proxy signal is emitted after disconnecting a proxy
619 	 * from an action in the group.
620 	 *
621 	 * #GtkUIManager proxies the signal and provides global notification
622 	 * just before any action is connected to a proxy, which is probably more
623 	 * convenient to use.
624 	 *
625 	 * Params:
626 	 *     action = the action
627 	 *     proxy = the proxy
628 	 *
629 	 * Since: 2.4
630 	 */
631 	gulong addOnDisconnectProxy(void delegate(Action, Widget, ActionGroup) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
632 	{
633 		auto wrapper = new OnDisconnectProxyDelegateWrapper(dlg);
634 		wrapper.handlerId = Signals.connectData(
635 			this,
636 			"disconnect-proxy",
637 			cast(GCallback)&callBackDisconnectProxy,
638 			cast(void*)wrapper,
639 			cast(GClosureNotify)&callBackDisconnectProxyDestroy,
640 			connectFlags);
641 		return wrapper.handlerId;
642 	}
643 
644 	extern(C) static void callBackDisconnectProxy(GtkActionGroup* actiongroupStruct, GtkAction* action, GtkWidget* proxy, OnDisconnectProxyDelegateWrapper wrapper)
645 	{
646 		wrapper.dlg(ObjectG.getDObject!(Action)(action), ObjectG.getDObject!(Widget)(proxy), wrapper.outer);
647 	}
648 
649 	extern(C) static void callBackDisconnectProxyDestroy(OnDisconnectProxyDelegateWrapper wrapper, GClosure* closure)
650 	{
651 		wrapper.remove(wrapper);
652 	}
653 
654 	protected class OnPostActivateDelegateWrapper
655 	{
656 		void delegate(Action, ActionGroup) dlg;
657 		gulong handlerId;
658 
659 		this(void delegate(Action, ActionGroup) dlg)
660 		{
661 			this.dlg = dlg;
662 			onPostActivateListeners ~= this;
663 		}
664 
665 		void remove(OnPostActivateDelegateWrapper source)
666 		{
667 			foreach(index, wrapper; onPostActivateListeners)
668 			{
669 				if (wrapper.handlerId == source.handlerId)
670 				{
671 					onPostActivateListeners[index] = null;
672 					onPostActivateListeners = std.algorithm.remove(onPostActivateListeners, index);
673 					break;
674 				}
675 			}
676 		}
677 	}
678 	OnPostActivateDelegateWrapper[] onPostActivateListeners;
679 
680 	/**
681 	 * The ::post-activate signal is emitted just after the @action in the
682 	 * @action_group is activated
683 	 *
684 	 * This is intended for #GtkUIManager to proxy the signal and provide global
685 	 * notification just after any action is activated.
686 	 *
687 	 * Params:
688 	 *     action = the action
689 	 *
690 	 * Since: 2.4
691 	 */
692 	gulong addOnPostActivate(void delegate(Action, ActionGroup) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
693 	{
694 		auto wrapper = new OnPostActivateDelegateWrapper(dlg);
695 		wrapper.handlerId = Signals.connectData(
696 			this,
697 			"post-activate",
698 			cast(GCallback)&callBackPostActivate,
699 			cast(void*)wrapper,
700 			cast(GClosureNotify)&callBackPostActivateDestroy,
701 			connectFlags);
702 		return wrapper.handlerId;
703 	}
704 
705 	extern(C) static void callBackPostActivate(GtkActionGroup* actiongroupStruct, GtkAction* action, OnPostActivateDelegateWrapper wrapper)
706 	{
707 		wrapper.dlg(ObjectG.getDObject!(Action)(action), wrapper.outer);
708 	}
709 
710 	extern(C) static void callBackPostActivateDestroy(OnPostActivateDelegateWrapper wrapper, GClosure* closure)
711 	{
712 		wrapper.remove(wrapper);
713 	}
714 
715 	protected class OnPreActivateDelegateWrapper
716 	{
717 		void delegate(Action, ActionGroup) dlg;
718 		gulong handlerId;
719 
720 		this(void delegate(Action, ActionGroup) dlg)
721 		{
722 			this.dlg = dlg;
723 			onPreActivateListeners ~= this;
724 		}
725 
726 		void remove(OnPreActivateDelegateWrapper source)
727 		{
728 			foreach(index, wrapper; onPreActivateListeners)
729 			{
730 				if (wrapper.handlerId == source.handlerId)
731 				{
732 					onPreActivateListeners[index] = null;
733 					onPreActivateListeners = std.algorithm.remove(onPreActivateListeners, index);
734 					break;
735 				}
736 			}
737 		}
738 	}
739 	OnPreActivateDelegateWrapper[] onPreActivateListeners;
740 
741 	/**
742 	 * The ::pre-activate signal is emitted just before the @action in the
743 	 * @action_group is activated
744 	 *
745 	 * This is intended for #GtkUIManager to proxy the signal and provide global
746 	 * notification just before any action is activated.
747 	 *
748 	 * Params:
749 	 *     action = the action
750 	 *
751 	 * Since: 2.4
752 	 */
753 	gulong addOnPreActivate(void delegate(Action, ActionGroup) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
754 	{
755 		auto wrapper = new OnPreActivateDelegateWrapper(dlg);
756 		wrapper.handlerId = Signals.connectData(
757 			this,
758 			"pre-activate",
759 			cast(GCallback)&callBackPreActivate,
760 			cast(void*)wrapper,
761 			cast(GClosureNotify)&callBackPreActivateDestroy,
762 			connectFlags);
763 		return wrapper.handlerId;
764 	}
765 
766 	extern(C) static void callBackPreActivate(GtkActionGroup* actiongroupStruct, GtkAction* action, OnPreActivateDelegateWrapper wrapper)
767 	{
768 		wrapper.dlg(ObjectG.getDObject!(Action)(action), wrapper.outer);
769 	}
770 
771 	extern(C) static void callBackPreActivateDestroy(OnPreActivateDelegateWrapper wrapper, GClosure* closure)
772 	{
773 		wrapper.remove(wrapper);
774 	}
775 }