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