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 gio.ActionGroupT;
26 
27 public  import glib.Str;
28 public  import glib.Variant;
29 public  import glib.VariantType;
30 public  import gobject.Signals;
31 public  import gtkc.gdktypes;
32 public  import gtkc.gio;
33 public  import gtkc.giotypes;
34 public  import std.algorithm;
35 
36 
37 /**
38  * #GActionGroup represents a group of actions. Actions can be used to
39  * expose functionality in a structured way, either from one part of a
40  * program to another, or to the outside world. Action groups are often
41  * used together with a #GMenuModel that provides additional
42  * representation data for displaying the actions to the user, e.g. in
43  * a menu.
44  * 
45  * The main way to interact with the actions in a GActionGroup is to
46  * activate them with g_action_group_activate_action(). Activating an
47  * action may require a #GVariant parameter. The required type of the
48  * parameter can be inquired with g_action_group_get_action_parameter_type().
49  * Actions may be disabled, see g_action_group_get_action_enabled().
50  * Activating a disabled action has no effect.
51  * 
52  * Actions may optionally have a state in the form of a #GVariant. The
53  * current state of an action can be inquired with
54  * g_action_group_get_action_state(). Activating a stateful action may
55  * change its state, but it is also possible to set the state by calling
56  * g_action_group_change_action_state().
57  * 
58  * As typical example, consider a text editing application which has an
59  * option to change the current font to 'bold'. A good way to represent
60  * this would be a stateful action, with a boolean state. Activating the
61  * action would toggle the state.
62  * 
63  * Each action in the group has a unique name (which is a string).  All
64  * method calls, except g_action_group_list_actions() take the name of
65  * an action as an argument.
66  * 
67  * The #GActionGroup API is meant to be the 'public' API to the action
68  * group.  The calls here are exactly the interaction that 'external
69  * forces' (eg: UI, incoming D-Bus messages, etc.) are supposed to have
70  * with actions.  'Internal' APIs (ie: ones meant only to be accessed by
71  * the action group implementation) are found on subclasses.  This is
72  * why you will find - for example - g_action_group_get_action_enabled()
73  * but not an equivalent set() call.
74  * 
75  * Signals are emitted on the action group in response to state changes
76  * on individual actions.
77  * 
78  * Implementations of #GActionGroup should provide implementations for
79  * the virtual functions g_action_group_list_actions() and
80  * g_action_group_query_action().  The other virtual functions should
81  * not be implemented - their "wrappers" are actually implemented with
82  * calls to g_action_group_query_action().
83  */
84 public template ActionGroupT(TStruct)
85 {
86 	/** Get the main Gtk struct */
87 	public GActionGroup* getActionGroupStruct()
88 	{
89 		return cast(GActionGroup*)getStruct();
90 	}
91 
92 
93 	/**
94 	 * Emits the #GActionGroup::action-added signal on @action_group.
95 	 *
96 	 * This function should only be called by #GActionGroup implementations.
97 	 *
98 	 * Params:
99 	 *     actionName = the name of an action in the group
100 	 *
101 	 * Since: 2.28
102 	 */
103 	public void actionAdded(string actionName)
104 	{
105 		g_action_group_action_added(getActionGroupStruct(), Str.toStringz(actionName));
106 	}
107 
108 	/**
109 	 * Emits the #GActionGroup::action-enabled-changed signal on @action_group.
110 	 *
111 	 * This function should only be called by #GActionGroup implementations.
112 	 *
113 	 * Params:
114 	 *     actionName = the name of an action in the group
115 	 *     enabled = whether or not the action is now enabled
116 	 *
117 	 * Since: 2.28
118 	 */
119 	public void actionEnabledChanged(string actionName, bool enabled)
120 	{
121 		g_action_group_action_enabled_changed(getActionGroupStruct(), Str.toStringz(actionName), enabled);
122 	}
123 
124 	/**
125 	 * Emits the #GActionGroup::action-removed signal on @action_group.
126 	 *
127 	 * This function should only be called by #GActionGroup implementations.
128 	 *
129 	 * Params:
130 	 *     actionName = the name of an action in the group
131 	 *
132 	 * Since: 2.28
133 	 */
134 	public void actionRemoved(string actionName)
135 	{
136 		g_action_group_action_removed(getActionGroupStruct(), Str.toStringz(actionName));
137 	}
138 
139 	/**
140 	 * Emits the #GActionGroup::action-state-changed signal on @action_group.
141 	 *
142 	 * This function should only be called by #GActionGroup implementations.
143 	 *
144 	 * Params:
145 	 *     actionName = the name of an action in the group
146 	 *     state = the new state of the named action
147 	 *
148 	 * Since: 2.28
149 	 */
150 	public void actionStateChanged(string actionName, Variant state)
151 	{
152 		g_action_group_action_state_changed(getActionGroupStruct(), Str.toStringz(actionName), (state is null) ? null : state.getVariantStruct());
153 	}
154 
155 	/**
156 	 * Activate the named action within @action_group.
157 	 *
158 	 * If the action is expecting a parameter, then the correct type of
159 	 * parameter must be given as @parameter.  If the action is expecting no
160 	 * parameters then @parameter must be %NULL.  See
161 	 * g_action_group_get_action_parameter_type().
162 	 *
163 	 * Params:
164 	 *     actionName = the name of the action to activate
165 	 *     parameter = parameters to the activation
166 	 *
167 	 * Since: 2.28
168 	 */
169 	public void activateAction(string actionName, Variant parameter)
170 	{
171 		g_action_group_activate_action(getActionGroupStruct(), Str.toStringz(actionName), (parameter is null) ? null : parameter.getVariantStruct());
172 	}
173 
174 	/**
175 	 * Request for the state of the named action within @action_group to be
176 	 * changed to @value.
177 	 *
178 	 * The action must be stateful and @value must be of the correct type.
179 	 * See g_action_group_get_action_state_type().
180 	 *
181 	 * This call merely requests a change.  The action may refuse to change
182 	 * its state or may change its state to something other than @value.
183 	 * See g_action_group_get_action_state_hint().
184 	 *
185 	 * If the @value GVariant is floating, it is consumed.
186 	 *
187 	 * Params:
188 	 *     actionName = the name of the action to request the change on
189 	 *     value = the new state
190 	 *
191 	 * Since: 2.28
192 	 */
193 	public void changeActionState(string actionName, Variant value)
194 	{
195 		g_action_group_change_action_state(getActionGroupStruct(), Str.toStringz(actionName), (value is null) ? null : value.getVariantStruct());
196 	}
197 
198 	/**
199 	 * Checks if the named action within @action_group is currently enabled.
200 	 *
201 	 * An action must be enabled in order to be activated or in order to
202 	 * have its state changed from outside callers.
203 	 *
204 	 * Params:
205 	 *     actionName = the name of the action to query
206 	 *
207 	 * Return: whether or not the action is currently enabled
208 	 *
209 	 * Since: 2.28
210 	 */
211 	public bool getActionEnabled(string actionName)
212 	{
213 		return g_action_group_get_action_enabled(getActionGroupStruct(), Str.toStringz(actionName)) != 0;
214 	}
215 
216 	/**
217 	 * Queries the type of the parameter that must be given when activating
218 	 * the named action within @action_group.
219 	 *
220 	 * When activating the action using g_action_group_activate_action(),
221 	 * the #GVariant given to that function must be of the type returned
222 	 * by this function.
223 	 *
224 	 * In the case that this function returns %NULL, you must not give any
225 	 * #GVariant, but %NULL instead.
226 	 *
227 	 * The parameter type of a particular action will never change but it is
228 	 * possible for an action to be removed and for a new action to be added
229 	 * with the same name but a different parameter type.
230 	 *
231 	 * Params:
232 	 *     actionName = the name of the action to query
233 	 *
234 	 * Return: the parameter type
235 	 *
236 	 * Since: 2.28
237 	 */
238 	public VariantType getActionParameterType(string actionName)
239 	{
240 		auto p = g_action_group_get_action_parameter_type(getActionGroupStruct(), Str.toStringz(actionName));
241 		
242 		if(p is null)
243 		{
244 			return null;
245 		}
246 		
247 		return new VariantType(cast(GVariantType*) p);
248 	}
249 
250 	/**
251 	 * Queries the current state of the named action within @action_group.
252 	 *
253 	 * If the action is not stateful then %NULL will be returned.  If the
254 	 * action is stateful then the type of the return value is the type
255 	 * given by g_action_group_get_action_state_type().
256 	 *
257 	 * The return value (if non-%NULL) should be freed with
258 	 * g_variant_unref() when it is no longer required.
259 	 *
260 	 * Params:
261 	 *     actionName = the name of the action to query
262 	 *
263 	 * Return: the current state of the action
264 	 *
265 	 * Since: 2.28
266 	 */
267 	public Variant getActionState(string actionName)
268 	{
269 		auto p = g_action_group_get_action_state(getActionGroupStruct(), Str.toStringz(actionName));
270 		
271 		if(p is null)
272 		{
273 			return null;
274 		}
275 		
276 		return new Variant(cast(GVariant*) p, true);
277 	}
278 
279 	/**
280 	 * Requests a hint about the valid range of values for the state of the
281 	 * named action within @action_group.
282 	 *
283 	 * If %NULL is returned it either means that the action is not stateful
284 	 * or that there is no hint about the valid range of values for the
285 	 * state of the action.
286 	 *
287 	 * If a #GVariant array is returned then each item in the array is a
288 	 * possible value for the state.  If a #GVariant pair (ie: two-tuple) is
289 	 * returned then the tuple specifies the inclusive lower and upper bound
290 	 * of valid values for the state.
291 	 *
292 	 * In any case, the information is merely a hint.  It may be possible to
293 	 * have a state value outside of the hinted range and setting a value
294 	 * within the range may fail.
295 	 *
296 	 * The return value (if non-%NULL) should be freed with
297 	 * g_variant_unref() when it is no longer required.
298 	 *
299 	 * Params:
300 	 *     actionName = the name of the action to query
301 	 *
302 	 * Return: the state range hint
303 	 *
304 	 * Since: 2.28
305 	 */
306 	public Variant getActionStateHint(string actionName)
307 	{
308 		auto p = g_action_group_get_action_state_hint(getActionGroupStruct(), Str.toStringz(actionName));
309 		
310 		if(p is null)
311 		{
312 			return null;
313 		}
314 		
315 		return new Variant(cast(GVariant*) p, true);
316 	}
317 
318 	/**
319 	 * Queries the type of the state of the named action within
320 	 * @action_group.
321 	 *
322 	 * If the action is stateful then this function returns the
323 	 * #GVariantType of the state.  All calls to
324 	 * g_action_group_change_action_state() must give a #GVariant of this
325 	 * type and g_action_group_get_action_state() will return a #GVariant
326 	 * of the same type.
327 	 *
328 	 * If the action is not stateful then this function will return %NULL.
329 	 * In that case, g_action_group_get_action_state() will return %NULL
330 	 * and you must not call g_action_group_change_action_state().
331 	 *
332 	 * The state type of a particular action will never change but it is
333 	 * possible for an action to be removed and for a new action to be added
334 	 * with the same name but a different state type.
335 	 *
336 	 * Params:
337 	 *     actionName = the name of the action to query
338 	 *
339 	 * Return: the state type, if the action is stateful
340 	 *
341 	 * Since: 2.28
342 	 */
343 	public VariantType getActionStateType(string actionName)
344 	{
345 		auto p = g_action_group_get_action_state_type(getActionGroupStruct(), Str.toStringz(actionName));
346 		
347 		if(p is null)
348 		{
349 			return null;
350 		}
351 		
352 		return new VariantType(cast(GVariantType*) p);
353 	}
354 
355 	/**
356 	 * Checks if the named action exists within @action_group.
357 	 *
358 	 * Params:
359 	 *     actionName = the name of the action to check for
360 	 *
361 	 * Return: whether the named action exists
362 	 *
363 	 * Since: 2.28
364 	 */
365 	public bool hasAction(string actionName)
366 	{
367 		return g_action_group_has_action(getActionGroupStruct(), Str.toStringz(actionName)) != 0;
368 	}
369 
370 	/**
371 	 * Lists the actions contained within @action_group.
372 	 *
373 	 * The caller is responsible for freeing the list with g_strfreev() when
374 	 * it is no longer required.
375 	 *
376 	 * Return: a %NULL-terminated array of the names of the
377 	 *     actions in the group
378 	 *
379 	 * Since: 2.28
380 	 */
381 	public string[] listActions()
382 	{
383 		auto retStr = g_action_group_list_actions(getActionGroupStruct());
384 		
385 		scope(exit) Str.freeStringArray(retStr);
386 		return Str.toStringArray(retStr);
387 	}
388 
389 	/**
390 	 * Queries all aspects of the named action within an @action_group.
391 	 *
392 	 * This function acquires the information available from
393 	 * g_action_group_has_action(), g_action_group_get_action_enabled(),
394 	 * g_action_group_get_action_parameter_type(),
395 	 * g_action_group_get_action_state_type(),
396 	 * g_action_group_get_action_state_hint() and
397 	 * g_action_group_get_action_state() with a single function call.
398 	 *
399 	 * This provides two main benefits.
400 	 *
401 	 * The first is the improvement in efficiency that comes with not having
402 	 * to perform repeated lookups of the action in order to discover
403 	 * different things about it.  The second is that implementing
404 	 * #GActionGroup can now be done by only overriding this one virtual
405 	 * function.
406 	 *
407 	 * The interface provides a default implementation of this function that
408 	 * calls the individual functions, as required, to fetch the
409 	 * information.  The interface also provides default implementations of
410 	 * those functions that call this function.  All implementations,
411 	 * therefore, must override either this function or all of the others.
412 	 *
413 	 * If the action exists, %TRUE is returned and any of the requested
414 	 * fields (as indicated by having a non-%NULL reference passed in) are
415 	 * filled.  If the action doesn't exist, %FALSE is returned and the
416 	 * fields may or may not have been modified.
417 	 *
418 	 * Params:
419 	 *     actionName = the name of an action in the group
420 	 *     enabled = if the action is presently enabled
421 	 *     parameterType = the parameter type, or %NULL if none needed
422 	 *     stateType = the state type, or %NULL if stateless
423 	 *     stateHint = the state hint, or %NULL if none
424 	 *     state = the current state, or %NULL if stateless
425 	 *
426 	 * Return: %TRUE if the action exists, else %FALSE
427 	 *
428 	 * Since: 2.32
429 	 */
430 	public bool queryAction(string actionName, out bool enabled, out VariantType parameterType, out VariantType stateType, out Variant stateHint, out Variant state)
431 	{
432 		int outenabled;
433 		GVariantType* outparameterType = null;
434 		GVariantType* outstateType = null;
435 		GVariant* outstateHint = null;
436 		GVariant* outstate = null;
437 		
438 		auto p = g_action_group_query_action(getActionGroupStruct(), Str.toStringz(actionName), &outenabled, &outparameterType, &outstateType, &outstateHint, &outstate) != 0;
439 		
440 		enabled = (outenabled == 1);
441 		parameterType = new VariantType(outparameterType);
442 		stateType = new VariantType(outstateType);
443 		stateHint = new Variant(outstateHint);
444 		state = new Variant(outstate);
445 		
446 		return p;
447 	}
448 
449 	protected class OnActionAddedDelegateWrapper
450 	{
451 		void delegate(string, ActionGroupIF) dlg;
452 		gulong handlerId;
453 		ConnectFlags flags;
454 		this(void delegate(string, ActionGroupIF) dlg, gulong handlerId, ConnectFlags flags)
455 		{
456 			this.dlg = dlg;
457 			this.handlerId = handlerId;
458 			this.flags = flags;
459 		}
460 	}
461 	protected OnActionAddedDelegateWrapper[] onActionAddedListeners;
462 
463 	/**
464 	 * Signals that a new action was just added to the group.
465 	 * This signal is emitted after the action has been added
466 	 * and is now visible.
467 	 *
468 	 * Params:
469 	 *     actionName = the name of the action in @action_group
470 	 *
471 	 * Since: 2.28
472 	 */
473 	gulong addOnActionAdded(void delegate(string, ActionGroupIF) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
474 	{
475 		onActionAddedListeners ~= new OnActionAddedDelegateWrapper(dlg, 0, connectFlags);
476 		onActionAddedListeners[onActionAddedListeners.length - 1].handlerId = Signals.connectData(
477 			this,
478 			"action-added",
479 			cast(GCallback)&callBackActionAdded,
480 			cast(void*)onActionAddedListeners[onActionAddedListeners.length - 1],
481 			cast(GClosureNotify)&callBackActionAddedDestroy,
482 			connectFlags);
483 		return onActionAddedListeners[onActionAddedListeners.length - 1].handlerId;
484 	}
485 	
486 	extern(C) static void callBackActionAdded(GActionGroup* actiongroupStruct, char* actionName,OnActionAddedDelegateWrapper wrapper)
487 	{
488 		wrapper.dlg(Str.toString(actionName), wrapper.outer);
489 	}
490 	
491 	extern(C) static void callBackActionAddedDestroy(OnActionAddedDelegateWrapper wrapper, GClosure* closure)
492 	{
493 		wrapper.outer.internalRemoveOnActionAdded(wrapper);
494 	}
495 
496 	protected void internalRemoveOnActionAdded(OnActionAddedDelegateWrapper source)
497 	{
498 		foreach(index, wrapper; onActionAddedListeners)
499 		{
500 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
501 			{
502 				onActionAddedListeners[index] = null;
503 				onActionAddedListeners = std.algorithm.remove(onActionAddedListeners, index);
504 				break;
505 			}
506 		}
507 	}
508 	
509 
510 	protected class OnActionEnabledChangedDelegateWrapper
511 	{
512 		void delegate(string, bool, ActionGroupIF) dlg;
513 		gulong handlerId;
514 		ConnectFlags flags;
515 		this(void delegate(string, bool, ActionGroupIF) dlg, gulong handlerId, ConnectFlags flags)
516 		{
517 			this.dlg = dlg;
518 			this.handlerId = handlerId;
519 			this.flags = flags;
520 		}
521 	}
522 	protected OnActionEnabledChangedDelegateWrapper[] onActionEnabledChangedListeners;
523 
524 	/**
525 	 * Signals that the enabled status of the named action has changed.
526 	 *
527 	 * Params:
528 	 *     actionName = the name of the action in @action_group
529 	 *     enabled = whether the action is enabled or not
530 	 *
531 	 * Since: 2.28
532 	 */
533 	gulong addOnActionEnabledChanged(void delegate(string, bool, ActionGroupIF) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
534 	{
535 		onActionEnabledChangedListeners ~= new OnActionEnabledChangedDelegateWrapper(dlg, 0, connectFlags);
536 		onActionEnabledChangedListeners[onActionEnabledChangedListeners.length - 1].handlerId = Signals.connectData(
537 			this,
538 			"action-enabled-changed",
539 			cast(GCallback)&callBackActionEnabledChanged,
540 			cast(void*)onActionEnabledChangedListeners[onActionEnabledChangedListeners.length - 1],
541 			cast(GClosureNotify)&callBackActionEnabledChangedDestroy,
542 			connectFlags);
543 		return onActionEnabledChangedListeners[onActionEnabledChangedListeners.length - 1].handlerId;
544 	}
545 	
546 	extern(C) static void callBackActionEnabledChanged(GActionGroup* actiongroupStruct, char* actionName, bool enabled,OnActionEnabledChangedDelegateWrapper wrapper)
547 	{
548 		wrapper.dlg(Str.toString(actionName), enabled, wrapper.outer);
549 	}
550 	
551 	extern(C) static void callBackActionEnabledChangedDestroy(OnActionEnabledChangedDelegateWrapper wrapper, GClosure* closure)
552 	{
553 		wrapper.outer.internalRemoveOnActionEnabledChanged(wrapper);
554 	}
555 
556 	protected void internalRemoveOnActionEnabledChanged(OnActionEnabledChangedDelegateWrapper source)
557 	{
558 		foreach(index, wrapper; onActionEnabledChangedListeners)
559 		{
560 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
561 			{
562 				onActionEnabledChangedListeners[index] = null;
563 				onActionEnabledChangedListeners = std.algorithm.remove(onActionEnabledChangedListeners, index);
564 				break;
565 			}
566 		}
567 	}
568 	
569 
570 	protected class OnActionRemovedDelegateWrapper
571 	{
572 		void delegate(string, ActionGroupIF) dlg;
573 		gulong handlerId;
574 		ConnectFlags flags;
575 		this(void delegate(string, ActionGroupIF) dlg, gulong handlerId, ConnectFlags flags)
576 		{
577 			this.dlg = dlg;
578 			this.handlerId = handlerId;
579 			this.flags = flags;
580 		}
581 	}
582 	protected OnActionRemovedDelegateWrapper[] onActionRemovedListeners;
583 
584 	/**
585 	 * Signals that an action is just about to be removed from the group.
586 	 * This signal is emitted before the action is removed, so the action
587 	 * is still visible and can be queried from the signal handler.
588 	 *
589 	 * Params:
590 	 *     actionName = the name of the action in @action_group
591 	 *
592 	 * Since: 2.28
593 	 */
594 	gulong addOnActionRemoved(void delegate(string, ActionGroupIF) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
595 	{
596 		onActionRemovedListeners ~= new OnActionRemovedDelegateWrapper(dlg, 0, connectFlags);
597 		onActionRemovedListeners[onActionRemovedListeners.length - 1].handlerId = Signals.connectData(
598 			this,
599 			"action-removed",
600 			cast(GCallback)&callBackActionRemoved,
601 			cast(void*)onActionRemovedListeners[onActionRemovedListeners.length - 1],
602 			cast(GClosureNotify)&callBackActionRemovedDestroy,
603 			connectFlags);
604 		return onActionRemovedListeners[onActionRemovedListeners.length - 1].handlerId;
605 	}
606 	
607 	extern(C) static void callBackActionRemoved(GActionGroup* actiongroupStruct, char* actionName,OnActionRemovedDelegateWrapper wrapper)
608 	{
609 		wrapper.dlg(Str.toString(actionName), wrapper.outer);
610 	}
611 	
612 	extern(C) static void callBackActionRemovedDestroy(OnActionRemovedDelegateWrapper wrapper, GClosure* closure)
613 	{
614 		wrapper.outer.internalRemoveOnActionRemoved(wrapper);
615 	}
616 
617 	protected void internalRemoveOnActionRemoved(OnActionRemovedDelegateWrapper source)
618 	{
619 		foreach(index, wrapper; onActionRemovedListeners)
620 		{
621 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
622 			{
623 				onActionRemovedListeners[index] = null;
624 				onActionRemovedListeners = std.algorithm.remove(onActionRemovedListeners, index);
625 				break;
626 			}
627 		}
628 	}
629 	
630 
631 	protected class OnActionStateChangedDelegateWrapper
632 	{
633 		void delegate(string, Variant, ActionGroupIF) dlg;
634 		gulong handlerId;
635 		ConnectFlags flags;
636 		this(void delegate(string, Variant, ActionGroupIF) dlg, gulong handlerId, ConnectFlags flags)
637 		{
638 			this.dlg = dlg;
639 			this.handlerId = handlerId;
640 			this.flags = flags;
641 		}
642 	}
643 	protected OnActionStateChangedDelegateWrapper[] onActionStateChangedListeners;
644 
645 	/**
646 	 * Signals that the state of the named action has changed.
647 	 *
648 	 * Params:
649 	 *     actionName = the name of the action in @action_group
650 	 *     value = the new value of the state
651 	 *
652 	 * Since: 2.28
653 	 */
654 	gulong addOnActionStateChanged(void delegate(string, Variant, ActionGroupIF) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
655 	{
656 		onActionStateChangedListeners ~= new OnActionStateChangedDelegateWrapper(dlg, 0, connectFlags);
657 		onActionStateChangedListeners[onActionStateChangedListeners.length - 1].handlerId = Signals.connectData(
658 			this,
659 			"action-state-changed",
660 			cast(GCallback)&callBackActionStateChanged,
661 			cast(void*)onActionStateChangedListeners[onActionStateChangedListeners.length - 1],
662 			cast(GClosureNotify)&callBackActionStateChangedDestroy,
663 			connectFlags);
664 		return onActionStateChangedListeners[onActionStateChangedListeners.length - 1].handlerId;
665 	}
666 	
667 	extern(C) static void callBackActionStateChanged(GActionGroup* actiongroupStruct, char* actionName, GVariant* value,OnActionStateChangedDelegateWrapper wrapper)
668 	{
669 		wrapper.dlg(Str.toString(actionName), new Variant(value), wrapper.outer);
670 	}
671 	
672 	extern(C) static void callBackActionStateChangedDestroy(OnActionStateChangedDelegateWrapper wrapper, GClosure* closure)
673 	{
674 		wrapper.outer.internalRemoveOnActionStateChanged(wrapper);
675 	}
676 
677 	protected void internalRemoveOnActionStateChanged(OnActionStateChangedDelegateWrapper source)
678 	{
679 		foreach(index, wrapper; onActionStateChangedListeners)
680 		{
681 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
682 			{
683 				onActionStateChangedListeners[index] = null;
684 				onActionStateChangedListeners = std.algorithm.remove(onActionStateChangedListeners, index);
685 				break;
686 			}
687 		}
688 	}
689 	
690 }