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