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 	/**
114 	 * Sets our main struct and passes it to the parent class.
115 	 */
116 	public this (GtkActionGroup* gtkActionGroup, bool ownedRef = false)
117 	{
118 		this.gtkActionGroup = gtkActionGroup;
119 		super(cast(GObject*)gtkActionGroup, ownedRef);
120 	}
121 
122 	// add the Buildable capabilities
123 	mixin BuildableT!(GtkActionGroup);
124 
125 
126 	/** */
127 	public static GType getType()
128 	{
129 		return gtk_action_group_get_type();
130 	}
131 
132 	/**
133 	 * Creates a new #GtkActionGroup object. The name of the action group
134 	 * is used when associating [keybindings][Action-Accel]
135 	 * with the actions.
136 	 *
137 	 * Params:
138 	 *     name = the name of the action group.
139 	 *
140 	 * Returns: the new #GtkActionGroup
141 	 *
142 	 * Since: 2.4
143 	 *
144 	 * Throws: ConstructionException GTK+ fails to create the object.
145 	 */
146 	public this(string name)
147 	{
148 		auto p = gtk_action_group_new(Str.toStringz(name));
149 
150 		if(p is null)
151 		{
152 			throw new ConstructionException("null returned by new");
153 		}
154 
155 		this(cast(GtkActionGroup*) p, true);
156 	}
157 
158 	/**
159 	 * Adds an action object to the action group. Note that this function
160 	 * does not set up the accel path of the action, which can lead to problems
161 	 * if a user tries to modify the accelerator of a menuitem associated with
162 	 * the action. Therefore you must either set the accel path yourself with
163 	 * gtk_action_set_accel_path(), or use
164 	 * `gtk_action_group_add_action_with_accel (..., NULL)`.
165 	 *
166 	 * Params:
167 	 *     action = an action
168 	 *
169 	 * Since: 2.4
170 	 */
171 	public void addAction(Action action)
172 	{
173 		gtk_action_group_add_action(gtkActionGroup, (action is null) ? null : action.getActionStruct());
174 	}
175 
176 	/**
177 	 * Adds an action object to the action group and sets up the accelerator.
178 	 *
179 	 * If @accelerator is %NULL, attempts to use the accelerator associated
180 	 * with the stock_id of the action.
181 	 *
182 	 * Accel paths are set to `<Actions>/group-name/action-name`.
183 	 *
184 	 * Params:
185 	 *     action = the action to add
186 	 *     accelerator = the accelerator for the action, in
187 	 *         the format understood by gtk_accelerator_parse(), or "" for no accelerator, or
188 	 *         %NULL to use the stock accelerator
189 	 *
190 	 * Since: 2.4
191 	 */
192 	public void addActionWithAccel(Action action, string accelerator)
193 	{
194 		gtk_action_group_add_action_with_accel(gtkActionGroup, (action is null) ? null : action.getActionStruct(), Str.toStringz(accelerator));
195 	}
196 
197 	/**
198 	 * This is a convenience function to create a number of actions and add them
199 	 * to the action group.
200 	 *
201 	 * The “activate” signals of the actions are connected to the callbacks
202 	 * and their accel paths are set to `<Actions>/group-name/action-name`.
203 	 *
204 	 * Params:
205 	 *     entries = an array of action descriptions
206 	 *     userData = data to pass to the action callbacks
207 	 *
208 	 * Since: 2.4
209 	 */
210 	public void addActions(GtkActionEntry[] entries, void* userData)
211 	{
212 		gtk_action_group_add_actions(gtkActionGroup, entries.ptr, cast(uint)entries.length, userData);
213 	}
214 
215 	/**
216 	 * This variant of gtk_action_group_add_actions() adds a #GDestroyNotify
217 	 * callback for @user_data.
218 	 *
219 	 * Params:
220 	 *     entries = an array of action descriptions
221 	 *     userData = data to pass to the action callbacks
222 	 *     destroy = destroy notification callback for @user_data
223 	 *
224 	 * Since: 2.4
225 	 */
226 	public void addActionsFull(GtkActionEntry[] entries, void* userData, GDestroyNotify destroy)
227 	{
228 		gtk_action_group_add_actions_full(gtkActionGroup, entries.ptr, cast(uint)entries.length, userData, destroy);
229 	}
230 
231 	/**
232 	 * This is a convenience routine to create a group of radio actions and
233 	 * add them to the action group.
234 	 *
235 	 * The “changed” signal of the first radio action is connected to the
236 	 * @on_change callback and the accel paths of the actions are set to
237 	 * `<Actions>/group-name/action-name`.
238 	 *
239 	 * Params:
240 	 *     entries = an array of radio action descriptions
241 	 *     value = the value of the action to activate initially, or -1 if
242 	 *         no action should be activated
243 	 *     onChange = the callback to connect to the changed signal
244 	 *     userData = data to pass to the action callbacks
245 	 *
246 	 * Since: 2.4
247 	 */
248 	public void addRadioActions(GtkRadioActionEntry[] entries, int value, GCallback onChange, void* userData)
249 	{
250 		gtk_action_group_add_radio_actions(gtkActionGroup, entries.ptr, cast(uint)entries.length, value, onChange, userData);
251 	}
252 
253 	/**
254 	 * This variant of gtk_action_group_add_radio_actions() adds a
255 	 * #GDestroyNotify callback for @user_data.
256 	 *
257 	 * Params:
258 	 *     entries = an array of radio action descriptions
259 	 *     value = the value of the action to activate initially, or -1 if
260 	 *         no action should be activated
261 	 *     onChange = the callback to connect to the changed signal
262 	 *     userData = data to pass to the action callbacks
263 	 *     destroy = destroy notification callback for @user_data
264 	 *
265 	 * Since: 2.4
266 	 */
267 	public void addRadioActionsFull(GtkRadioActionEntry[] entries, int value, GCallback onChange, void* userData, GDestroyNotify destroy)
268 	{
269 		gtk_action_group_add_radio_actions_full(gtkActionGroup, entries.ptr, cast(uint)entries.length, value, onChange, userData, destroy);
270 	}
271 
272 	/**
273 	 * This is a convenience function to create a number of toggle actions and add them
274 	 * to the action group.
275 	 *
276 	 * The “activate” signals of the actions are connected to the callbacks
277 	 * and their accel paths are set to `<Actions>/group-name/action-name`.
278 	 *
279 	 * Params:
280 	 *     entries = an array of toggle action descriptions
281 	 *     userData = data to pass to the action callbacks
282 	 *
283 	 * Since: 2.4
284 	 */
285 	public void addToggleActions(GtkToggleActionEntry[] entries, void* userData)
286 	{
287 		gtk_action_group_add_toggle_actions(gtkActionGroup, entries.ptr, cast(uint)entries.length, userData);
288 	}
289 
290 	/**
291 	 * This variant of gtk_action_group_add_toggle_actions() adds a
292 	 * #GDestroyNotify callback for @user_data.
293 	 *
294 	 * Params:
295 	 *     entries = an array of toggle action descriptions
296 	 *     userData = data to pass to the action callbacks
297 	 *     destroy = destroy notification callback for @user_data
298 	 *
299 	 * Since: 2.4
300 	 */
301 	public void addToggleActionsFull(GtkToggleActionEntry[] entries, void* userData, GDestroyNotify destroy)
302 	{
303 		gtk_action_group_add_toggle_actions_full(gtkActionGroup, entries.ptr, cast(uint)entries.length, userData, destroy);
304 	}
305 
306 	/**
307 	 * Gets the accelerator group.
308 	 *
309 	 * Returns: the accelerator group associated with this action
310 	 *     group or %NULL if there is none.
311 	 *
312 	 * Since: 3.6
313 	 */
314 	public AccelGroup getAccelGroup()
315 	{
316 		auto p = gtk_action_group_get_accel_group(gtkActionGroup);
317 
318 		if(p is null)
319 		{
320 			return null;
321 		}
322 
323 		return ObjectG.getDObject!(AccelGroup)(cast(GtkAccelGroup*) p);
324 	}
325 
326 	/**
327 	 * Looks up an action in the action group by name.
328 	 *
329 	 * Params:
330 	 *     actionName = the name of the action
331 	 *
332 	 * Returns: the action, or %NULL if no action by that name exists
333 	 *
334 	 * Since: 2.4
335 	 */
336 	public Action getAction(string actionName)
337 	{
338 		auto p = gtk_action_group_get_action(gtkActionGroup, Str.toStringz(actionName));
339 
340 		if(p is null)
341 		{
342 			return null;
343 		}
344 
345 		return ObjectG.getDObject!(Action)(cast(GtkAction*) p);
346 	}
347 
348 	/**
349 	 * Gets the name of the action group.
350 	 *
351 	 * Returns: the name of the action group.
352 	 *
353 	 * Since: 2.4
354 	 */
355 	public string getName()
356 	{
357 		return Str.toString(gtk_action_group_get_name(gtkActionGroup));
358 	}
359 
360 	/**
361 	 * Returns %TRUE if the group is sensitive.  The constituent actions
362 	 * can only be logically sensitive (see gtk_action_is_sensitive()) if
363 	 * they are sensitive (see gtk_action_get_sensitive()) and their group
364 	 * is sensitive.
365 	 *
366 	 * Returns: %TRUE if the group is sensitive.
367 	 *
368 	 * Since: 2.4
369 	 */
370 	public bool getSensitive()
371 	{
372 		return gtk_action_group_get_sensitive(gtkActionGroup) != 0;
373 	}
374 
375 	/**
376 	 * Returns %TRUE if the group is visible.  The constituent actions
377 	 * can only be logically visible (see gtk_action_is_visible()) if
378 	 * they are visible (see gtk_action_get_visible()) and their group
379 	 * is visible.
380 	 *
381 	 * Returns: %TRUE if the group is visible.
382 	 *
383 	 * Since: 2.4
384 	 */
385 	public bool getVisible()
386 	{
387 		return gtk_action_group_get_visible(gtkActionGroup) != 0;
388 	}
389 
390 	/**
391 	 * Lists the actions in the action group.
392 	 *
393 	 * Returns: an allocated list of the action objects in the action group
394 	 *
395 	 * Since: 2.4
396 	 */
397 	public ListG listActions()
398 	{
399 		auto p = gtk_action_group_list_actions(gtkActionGroup);
400 
401 		if(p is null)
402 		{
403 			return null;
404 		}
405 
406 		return new ListG(cast(GList*) p);
407 	}
408 
409 	/**
410 	 * Removes an action object from the action group.
411 	 *
412 	 * Params:
413 	 *     action = an action
414 	 *
415 	 * Since: 2.4
416 	 */
417 	public void removeAction(Action action)
418 	{
419 		gtk_action_group_remove_action(gtkActionGroup, (action is null) ? null : action.getActionStruct());
420 	}
421 
422 	/**
423 	 * Sets the accelerator group to be used by every action in this group.
424 	 *
425 	 * Params:
426 	 *     accelGroup = a #GtkAccelGroup to set or %NULL
427 	 *
428 	 * Since: 3.6
429 	 */
430 	public void setAccelGroup(AccelGroup accelGroup)
431 	{
432 		gtk_action_group_set_accel_group(gtkActionGroup, (accelGroup is null) ? null : accelGroup.getAccelGroupStruct());
433 	}
434 
435 	/**
436 	 * Changes the sensitivity of @action_group
437 	 *
438 	 * Params:
439 	 *     sensitive = new sensitivity
440 	 *
441 	 * Since: 2.4
442 	 */
443 	public void setSensitive(bool sensitive)
444 	{
445 		gtk_action_group_set_sensitive(gtkActionGroup, sensitive);
446 	}
447 
448 	/**
449 	 * Sets a function to be used for translating the @label and @tooltip of
450 	 * #GtkActionEntrys added by gtk_action_group_add_actions().
451 	 *
452 	 * If you’re using gettext(), it is enough to set the translation domain
453 	 * with gtk_action_group_set_translation_domain().
454 	 *
455 	 * Params:
456 	 *     func = a #GtkTranslateFunc
457 	 *     data = data to be passed to @func and @notify
458 	 *     notify = a #GDestroyNotify function to be called when @action_group is
459 	 *         destroyed and when the translation function is changed again
460 	 *
461 	 * Since: 2.4
462 	 */
463 	public void setTranslateFunc(GtkTranslateFunc func, void* data, GDestroyNotify notify)
464 	{
465 		gtk_action_group_set_translate_func(gtkActionGroup, func, data, notify);
466 	}
467 
468 	/**
469 	 * Sets the translation domain and uses g_dgettext() for translating the
470 	 * @label and @tooltip of #GtkActionEntrys added by
471 	 * gtk_action_group_add_actions().
472 	 *
473 	 * If you’re not using gettext() for localization, see
474 	 * gtk_action_group_set_translate_func().
475 	 *
476 	 * Params:
477 	 *     domain = the translation domain to use for g_dgettext()
478 	 *         calls, or %NULL to use the domain set with textdomain()
479 	 *
480 	 * Since: 2.4
481 	 */
482 	public void setTranslationDomain(string domain)
483 	{
484 		gtk_action_group_set_translation_domain(gtkActionGroup, Str.toStringz(domain));
485 	}
486 
487 	/**
488 	 * Changes the visible of @action_group.
489 	 *
490 	 * Params:
491 	 *     visible = new visiblity
492 	 *
493 	 * Since: 2.4
494 	 */
495 	public void setVisible(bool visible)
496 	{
497 		gtk_action_group_set_visible(gtkActionGroup, visible);
498 	}
499 
500 	/**
501 	 * Translates a string using the function set with
502 	 * gtk_action_group_set_translate_func(). This
503 	 * is mainly intended for language bindings.
504 	 *
505 	 * Params:
506 	 *     str = a string
507 	 *
508 	 * Returns: the translation of @string
509 	 *
510 	 * Since: 2.6
511 	 */
512 	public string translateString(string str)
513 	{
514 		return Str.toString(gtk_action_group_translate_string(gtkActionGroup, Str.toStringz(str)));
515 	}
516 
517 	protected class OnConnectProxyDelegateWrapper
518 	{
519 		void delegate(Action, Widget, ActionGroup) dlg;
520 		gulong handlerId;
521 
522 		this(void delegate(Action, Widget, ActionGroup) dlg)
523 		{
524 			this.dlg = dlg;
525 			onConnectProxyListeners ~= this;
526 		}
527 
528 		void remove(OnConnectProxyDelegateWrapper source)
529 		{
530 			foreach(index, wrapper; onConnectProxyListeners)
531 			{
532 				if (wrapper.handlerId == source.handlerId)
533 				{
534 					onConnectProxyListeners[index] = null;
535 					onConnectProxyListeners = std.algorithm.remove(onConnectProxyListeners, index);
536 					break;
537 				}
538 			}
539 		}
540 	}
541 	OnConnectProxyDelegateWrapper[] onConnectProxyListeners;
542 
543 	/**
544 	 * The ::connect-proxy signal is emitted after connecting a proxy to
545 	 * an action in the group. Note that the proxy may have been connected
546 	 * to a different action before.
547 	 *
548 	 * This is intended for simple customizations for which a custom action
549 	 * class would be too clumsy, e.g. showing tooltips for menuitems in the
550 	 * statusbar.
551 	 *
552 	 * #GtkUIManager proxies the signal and provides global notification
553 	 * just before any action is connected to a proxy, which is probably more
554 	 * convenient to use.
555 	 *
556 	 * Params:
557 	 *     action = the action
558 	 *     proxy = the proxy
559 	 *
560 	 * Since: 2.4
561 	 */
562 	gulong addOnConnectProxy(void delegate(Action, Widget, ActionGroup) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
563 	{
564 		auto wrapper = new OnConnectProxyDelegateWrapper(dlg);
565 		wrapper.handlerId = Signals.connectData(
566 			this,
567 			"connect-proxy",
568 			cast(GCallback)&callBackConnectProxy,
569 			cast(void*)wrapper,
570 			cast(GClosureNotify)&callBackConnectProxyDestroy,
571 			connectFlags);
572 		return wrapper.handlerId;
573 	}
574 
575 	extern(C) static void callBackConnectProxy(GtkActionGroup* actiongroupStruct, GtkAction* action, GtkWidget* proxy, OnConnectProxyDelegateWrapper wrapper)
576 	{
577 		wrapper.dlg(ObjectG.getDObject!(Action)(action), ObjectG.getDObject!(Widget)(proxy), wrapper.outer);
578 	}
579 
580 	extern(C) static void callBackConnectProxyDestroy(OnConnectProxyDelegateWrapper wrapper, GClosure* closure)
581 	{
582 		wrapper.remove(wrapper);
583 	}
584 
585 	protected class OnDisconnectProxyDelegateWrapper
586 	{
587 		void delegate(Action, Widget, ActionGroup) dlg;
588 		gulong handlerId;
589 
590 		this(void delegate(Action, Widget, ActionGroup) dlg)
591 		{
592 			this.dlg = dlg;
593 			onDisconnectProxyListeners ~= this;
594 		}
595 
596 		void remove(OnDisconnectProxyDelegateWrapper source)
597 		{
598 			foreach(index, wrapper; onDisconnectProxyListeners)
599 			{
600 				if (wrapper.handlerId == source.handlerId)
601 				{
602 					onDisconnectProxyListeners[index] = null;
603 					onDisconnectProxyListeners = std.algorithm.remove(onDisconnectProxyListeners, index);
604 					break;
605 				}
606 			}
607 		}
608 	}
609 	OnDisconnectProxyDelegateWrapper[] onDisconnectProxyListeners;
610 
611 	/**
612 	 * The ::disconnect-proxy signal is emitted after disconnecting a proxy
613 	 * from an action in the group.
614 	 *
615 	 * #GtkUIManager proxies the signal and provides global notification
616 	 * just before any action is connected to a proxy, which is probably more
617 	 * convenient to use.
618 	 *
619 	 * Params:
620 	 *     action = the action
621 	 *     proxy = the proxy
622 	 *
623 	 * Since: 2.4
624 	 */
625 	gulong addOnDisconnectProxy(void delegate(Action, Widget, ActionGroup) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
626 	{
627 		auto wrapper = new OnDisconnectProxyDelegateWrapper(dlg);
628 		wrapper.handlerId = Signals.connectData(
629 			this,
630 			"disconnect-proxy",
631 			cast(GCallback)&callBackDisconnectProxy,
632 			cast(void*)wrapper,
633 			cast(GClosureNotify)&callBackDisconnectProxyDestroy,
634 			connectFlags);
635 		return wrapper.handlerId;
636 	}
637 
638 	extern(C) static void callBackDisconnectProxy(GtkActionGroup* actiongroupStruct, GtkAction* action, GtkWidget* proxy, OnDisconnectProxyDelegateWrapper wrapper)
639 	{
640 		wrapper.dlg(ObjectG.getDObject!(Action)(action), ObjectG.getDObject!(Widget)(proxy), wrapper.outer);
641 	}
642 
643 	extern(C) static void callBackDisconnectProxyDestroy(OnDisconnectProxyDelegateWrapper wrapper, GClosure* closure)
644 	{
645 		wrapper.remove(wrapper);
646 	}
647 
648 	protected class OnPostActivateDelegateWrapper
649 	{
650 		void delegate(Action, ActionGroup) dlg;
651 		gulong handlerId;
652 
653 		this(void delegate(Action, ActionGroup) dlg)
654 		{
655 			this.dlg = dlg;
656 			onPostActivateListeners ~= this;
657 		}
658 
659 		void remove(OnPostActivateDelegateWrapper source)
660 		{
661 			foreach(index, wrapper; onPostActivateListeners)
662 			{
663 				if (wrapper.handlerId == source.handlerId)
664 				{
665 					onPostActivateListeners[index] = null;
666 					onPostActivateListeners = std.algorithm.remove(onPostActivateListeners, index);
667 					break;
668 				}
669 			}
670 		}
671 	}
672 	OnPostActivateDelegateWrapper[] onPostActivateListeners;
673 
674 	/**
675 	 * The ::post-activate signal is emitted just after the @action in the
676 	 * @action_group is activated
677 	 *
678 	 * This is intended for #GtkUIManager to proxy the signal and provide global
679 	 * notification just after any action is activated.
680 	 *
681 	 * Params:
682 	 *     action = the action
683 	 *
684 	 * Since: 2.4
685 	 */
686 	gulong addOnPostActivate(void delegate(Action, ActionGroup) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
687 	{
688 		auto wrapper = new OnPostActivateDelegateWrapper(dlg);
689 		wrapper.handlerId = Signals.connectData(
690 			this,
691 			"post-activate",
692 			cast(GCallback)&callBackPostActivate,
693 			cast(void*)wrapper,
694 			cast(GClosureNotify)&callBackPostActivateDestroy,
695 			connectFlags);
696 		return wrapper.handlerId;
697 	}
698 
699 	extern(C) static void callBackPostActivate(GtkActionGroup* actiongroupStruct, GtkAction* action, OnPostActivateDelegateWrapper wrapper)
700 	{
701 		wrapper.dlg(ObjectG.getDObject!(Action)(action), wrapper.outer);
702 	}
703 
704 	extern(C) static void callBackPostActivateDestroy(OnPostActivateDelegateWrapper wrapper, GClosure* closure)
705 	{
706 		wrapper.remove(wrapper);
707 	}
708 
709 	protected class OnPreActivateDelegateWrapper
710 	{
711 		void delegate(Action, ActionGroup) dlg;
712 		gulong handlerId;
713 
714 		this(void delegate(Action, ActionGroup) dlg)
715 		{
716 			this.dlg = dlg;
717 			onPreActivateListeners ~= this;
718 		}
719 
720 		void remove(OnPreActivateDelegateWrapper source)
721 		{
722 			foreach(index, wrapper; onPreActivateListeners)
723 			{
724 				if (wrapper.handlerId == source.handlerId)
725 				{
726 					onPreActivateListeners[index] = null;
727 					onPreActivateListeners = std.algorithm.remove(onPreActivateListeners, index);
728 					break;
729 				}
730 			}
731 		}
732 	}
733 	OnPreActivateDelegateWrapper[] onPreActivateListeners;
734 
735 	/**
736 	 * The ::pre-activate signal is emitted just before the @action in the
737 	 * @action_group is activated
738 	 *
739 	 * This is intended for #GtkUIManager to proxy the signal and provide global
740 	 * notification just before any action is activated.
741 	 *
742 	 * Params:
743 	 *     action = the action
744 	 *
745 	 * Since: 2.4
746 	 */
747 	gulong addOnPreActivate(void delegate(Action, ActionGroup) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
748 	{
749 		auto wrapper = new OnPreActivateDelegateWrapper(dlg);
750 		wrapper.handlerId = Signals.connectData(
751 			this,
752 			"pre-activate",
753 			cast(GCallback)&callBackPreActivate,
754 			cast(void*)wrapper,
755 			cast(GClosureNotify)&callBackPreActivateDestroy,
756 			connectFlags);
757 		return wrapper.handlerId;
758 	}
759 
760 	extern(C) static void callBackPreActivate(GtkActionGroup* actiongroupStruct, GtkAction* action, OnPreActivateDelegateWrapper wrapper)
761 	{
762 		wrapper.dlg(ObjectG.getDObject!(Action)(action), wrapper.outer);
763 	}
764 
765 	extern(C) static void callBackPreActivateDestroy(OnPreActivateDelegateWrapper wrapper, GClosure* closure)
766 	{
767 		wrapper.remove(wrapper);
768 	}
769 }