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.MenuModel;
26 
27 private import gio.MenuAttributeIter;
28 private import gio.MenuLinkIter;
29 private import gio.c.functions;
30 public  import gio.c.types;
31 private import glib.Str;
32 private import glib.Variant;
33 private import glib.VariantType;
34 private import gobject.ObjectG;
35 private import gobject.Signals;
36 public  import gtkc.giotypes;
37 private import std.algorithm;
38 
39 
40 /**
41  * #GMenuModel represents the contents of a menu -- an ordered list of
42  * menu items. The items are associated with actions, which can be
43  * activated through them. Items can be grouped in sections, and may
44  * have submenus associated with them. Both items and sections usually
45  * have some representation data, such as labels or icons. The type of
46  * the associated action (ie whether it is stateful, and what kind of
47  * state it has) can influence the representation of the item.
48  * 
49  * The conceptual model of menus in #GMenuModel is hierarchical:
50  * sections and submenus are again represented by #GMenuModels.
51  * Menus themselves do not define their own roles. Rather, the role
52  * of a particular #GMenuModel is defined by the item that references
53  * it (or, in the case of the 'root' menu, is defined by the context
54  * in which it is used).
55  * 
56  * As an example, consider the visible portions of this menu:
57  * 
58  * ## An example menu # {#menu-example}
59  * 
60  * ![](menu-example.png)
61  * 
62  * There are 8 "menus" visible in the screenshot: one menubar, two
63  * submenus and 5 sections:
64  * 
65  * - the toplevel menubar (containing 4 items)
66  * - the View submenu (containing 3 sections)
67  * - the first section of the View submenu (containing 2 items)
68  * - the second section of the View submenu (containing 1 item)
69  * - the final section of the View submenu (containing 1 item)
70  * - the Highlight Mode submenu (containing 2 sections)
71  * - the Sources section (containing 2 items)
72  * - the Markup section (containing 2 items)
73  * 
74  * The [example][menu-model] illustrates the conceptual connection between
75  * these 8 menus. Each large block in the figure represents a menu and the
76  * smaller blocks within the large block represent items in that menu. Some
77  * items contain references to other menus.
78  * 
79  * ## A menu example # {#menu-model}
80  * 
81  * ![](menu-model.png)
82  * 
83  * Notice that the separators visible in the [example][menu-example]
84  * appear nowhere in the [menu model][menu-model]. This is because
85  * separators are not explicitly represented in the menu model. Instead,
86  * a separator is inserted between any two non-empty sections of a menu.
87  * Section items can have labels just like any other item. In that case,
88  * a display system may show a section header instead of a separator.
89  * 
90  * The motivation for this abstract model of application controls is
91  * that modern user interfaces tend to make these controls available
92  * outside the application. Examples include global menus, jumplists,
93  * dash boards, etc. To support such uses, it is necessary to 'export'
94  * information about actions and their representation in menus, which
95  * is exactly what the [GActionGroup exporter][gio-GActionGroup-exporter]
96  * and the [GMenuModel exporter][gio-GMenuModel-exporter] do for
97  * #GActionGroup and #GMenuModel. The client-side counterparts to
98  * make use of the exported information are #GDBusActionGroup and
99  * #GDBusMenuModel.
100  * 
101  * The API of #GMenuModel is very generic, with iterators for the
102  * attributes and links of an item, see g_menu_model_iterate_item_attributes()
103  * and g_menu_model_iterate_item_links(). The 'standard' attributes and
104  * link types have predefined names: %G_MENU_ATTRIBUTE_LABEL,
105  * %G_MENU_ATTRIBUTE_ACTION, %G_MENU_ATTRIBUTE_TARGET, %G_MENU_LINK_SECTION
106  * and %G_MENU_LINK_SUBMENU.
107  * 
108  * Items in a #GMenuModel represent active controls if they refer to
109  * an action that can get activated when the user interacts with the
110  * menu item. The reference to the action is encoded by the string id
111  * in the %G_MENU_ATTRIBUTE_ACTION attribute. An action id uniquely
112  * identifies an action in an action group. Which action group(s) provide
113  * actions depends on the context in which the menu model is used.
114  * E.g. when the model is exported as the application menu of a
115  * #GtkApplication, actions can be application-wide or window-specific
116  * (and thus come from two different action groups). By convention, the
117  * application-wide actions have names that start with "app.", while the
118  * names of window-specific actions start with "win.".
119  * 
120  * While a wide variety of stateful actions is possible, the following
121  * is the minimum that is expected to be supported by all users of exported
122  * menu information:
123  * - an action with no parameter type and no state
124  * - an action with no parameter type and boolean state
125  * - an action with string parameter type and string state
126  * 
127  * ## Stateless
128  * 
129  * A stateless action typically corresponds to an ordinary menu item.
130  * 
131  * Selecting such a menu item will activate the action (with no parameter).
132  * 
133  * ## Boolean State
134  * 
135  * An action with a boolean state will most typically be used with a "toggle"
136  * or "switch" menu item. The state can be set directly, but activating the
137  * action (with no parameter) results in the state being toggled.
138  * 
139  * Selecting a toggle menu item will activate the action. The menu item should
140  * be rendered as "checked" when the state is true.
141  * 
142  * ## String Parameter and State
143  * 
144  * Actions with string parameters and state will most typically be used to
145  * represent an enumerated choice over the items available for a group of
146  * radio menu items. Activating the action with a string parameter is
147  * equivalent to setting that parameter as the state.
148  * 
149  * Radio menu items, in addition to being associated with the action, will
150  * have a target value. Selecting that menu item will result in activation
151  * of the action with the target value as the parameter. The menu item should
152  * be rendered as "selected" when the state of the action is equal to the
153  * target value of the menu item.
154  *
155  * Since: 2.32
156  */
157 public class MenuModel : ObjectG
158 {
159 	/** the main Gtk struct */
160 	protected GMenuModel* gMenuModel;
161 
162 	/** Get the main Gtk struct */
163 	public GMenuModel* getMenuModelStruct(bool transferOwnership = false)
164 	{
165 		if (transferOwnership)
166 			ownedRef = false;
167 		return gMenuModel;
168 	}
169 
170 	/** the main Gtk struct as a void* */
171 	protected override void* getStruct()
172 	{
173 		return cast(void*)gMenuModel;
174 	}
175 
176 	protected override void setStruct(GObject* obj)
177 	{
178 		gMenuModel = cast(GMenuModel*)obj;
179 		super.setStruct(obj);
180 	}
181 
182 	/**
183 	 * Sets our main struct and passes it to the parent class.
184 	 */
185 	public this (GMenuModel* gMenuModel, bool ownedRef = false)
186 	{
187 		this.gMenuModel = gMenuModel;
188 		super(cast(GObject*)gMenuModel, ownedRef);
189 	}
190 
191 
192 	/** */
193 	public static GType getType()
194 	{
195 		return g_menu_model_get_type();
196 	}
197 
198 	/**
199 	 * Queries the item at position @item_index in @model for the attribute
200 	 * specified by @attribute.
201 	 *
202 	 * If @expected_type is non-%NULL then it specifies the expected type of
203 	 * the attribute.  If it is %NULL then any type will be accepted.
204 	 *
205 	 * If the attribute exists and matches @expected_type (or if the
206 	 * expected type is unspecified) then the value is returned.
207 	 *
208 	 * If the attribute does not exist, or does not match the expected type
209 	 * then %NULL is returned.
210 	 *
211 	 * Params:
212 	 *     itemIndex = the index of the item
213 	 *     attribute = the attribute to query
214 	 *     expectedType = the expected type of the attribute, or
215 	 *         %NULL
216 	 *
217 	 * Returns: the value of the attribute
218 	 *
219 	 * Since: 2.32
220 	 */
221 	public Variant getItemAttributeValue(int itemIndex, string attribute, VariantType expectedType)
222 	{
223 		auto p = g_menu_model_get_item_attribute_value(gMenuModel, itemIndex, Str.toStringz(attribute), (expectedType is null) ? null : expectedType.getVariantTypeStruct());
224 
225 		if(p is null)
226 		{
227 			return null;
228 		}
229 
230 		return new Variant(cast(GVariant*) p, true);
231 	}
232 
233 	/**
234 	 * Queries the item at position @item_index in @model for the link
235 	 * specified by @link.
236 	 *
237 	 * If the link exists, the linked #GMenuModel is returned.  If the link
238 	 * does not exist, %NULL is returned.
239 	 *
240 	 * Params:
241 	 *     itemIndex = the index of the item
242 	 *     link = the link to query
243 	 *
244 	 * Returns: the linked #GMenuModel, or %NULL
245 	 *
246 	 * Since: 2.32
247 	 */
248 	public MenuModel getItemLink(int itemIndex, string link)
249 	{
250 		auto p = g_menu_model_get_item_link(gMenuModel, itemIndex, Str.toStringz(link));
251 
252 		if(p is null)
253 		{
254 			return null;
255 		}
256 
257 		return ObjectG.getDObject!(MenuModel)(cast(GMenuModel*) p, true);
258 	}
259 
260 	/**
261 	 * Query the number of items in @model.
262 	 *
263 	 * Returns: the number of items
264 	 *
265 	 * Since: 2.32
266 	 */
267 	public int getNItems()
268 	{
269 		return g_menu_model_get_n_items(gMenuModel);
270 	}
271 
272 	/**
273 	 * Queries if @model is mutable.
274 	 *
275 	 * An immutable #GMenuModel will never emit the #GMenuModel::items-changed
276 	 * signal. Consumers of the model may make optimisations accordingly.
277 	 *
278 	 * Returns: %TRUE if the model is mutable (ie: "items-changed" may be
279 	 *     emitted).
280 	 *
281 	 * Since: 2.32
282 	 */
283 	public bool isMutable()
284 	{
285 		return g_menu_model_is_mutable(gMenuModel) != 0;
286 	}
287 
288 	/**
289 	 * Requests emission of the #GMenuModel::items-changed signal on @model.
290 	 *
291 	 * This function should never be called except by #GMenuModel
292 	 * subclasses.  Any other calls to this function will very likely lead
293 	 * to a violation of the interface of the model.
294 	 *
295 	 * The implementation should update its internal representation of the
296 	 * menu before emitting the signal.  The implementation should further
297 	 * expect to receive queries about the new state of the menu (and
298 	 * particularly added menu items) while signal handlers are running.
299 	 *
300 	 * The implementation must dispatch this call directly from a mainloop
301 	 * entry and not in response to calls -- particularly those from the
302 	 * #GMenuModel API.  Said another way: the menu must not change while
303 	 * user code is running without returning to the mainloop.
304 	 *
305 	 * Params:
306 	 *     position = the position of the change
307 	 *     removed = the number of items removed
308 	 *     added = the number of items added
309 	 *
310 	 * Since: 2.32
311 	 */
312 	public void itemsChanged(int position, int removed, int added)
313 	{
314 		g_menu_model_items_changed(gMenuModel, position, removed, added);
315 	}
316 
317 	/**
318 	 * Creates a #GMenuAttributeIter to iterate over the attributes of
319 	 * the item at position @item_index in @model.
320 	 *
321 	 * You must free the iterator with g_object_unref() when you are done.
322 	 *
323 	 * Params:
324 	 *     itemIndex = the index of the item
325 	 *
326 	 * Returns: a new #GMenuAttributeIter
327 	 *
328 	 * Since: 2.32
329 	 */
330 	public MenuAttributeIter iterateItemAttributes(int itemIndex)
331 	{
332 		auto p = g_menu_model_iterate_item_attributes(gMenuModel, itemIndex);
333 
334 		if(p is null)
335 		{
336 			return null;
337 		}
338 
339 		return ObjectG.getDObject!(MenuAttributeIter)(cast(GMenuAttributeIter*) p, true);
340 	}
341 
342 	/**
343 	 * Creates a #GMenuLinkIter to iterate over the links of the item at
344 	 * position @item_index in @model.
345 	 *
346 	 * You must free the iterator with g_object_unref() when you are done.
347 	 *
348 	 * Params:
349 	 *     itemIndex = the index of the item
350 	 *
351 	 * Returns: a new #GMenuLinkIter
352 	 *
353 	 * Since: 2.32
354 	 */
355 	public MenuLinkIter iterateItemLinks(int itemIndex)
356 	{
357 		auto p = g_menu_model_iterate_item_links(gMenuModel, itemIndex);
358 
359 		if(p is null)
360 		{
361 			return null;
362 		}
363 
364 		return ObjectG.getDObject!(MenuLinkIter)(cast(GMenuLinkIter*) p, true);
365 	}
366 
367 	protected class OnItemsChangedDelegateWrapper
368 	{
369 		void delegate(int, int, int, MenuModel) dlg;
370 		gulong handlerId;
371 
372 		this(void delegate(int, int, int, MenuModel) dlg)
373 		{
374 			this.dlg = dlg;
375 			onItemsChangedListeners ~= this;
376 		}
377 
378 		void remove(OnItemsChangedDelegateWrapper source)
379 		{
380 			foreach(index, wrapper; onItemsChangedListeners)
381 			{
382 				if (wrapper.handlerId == source.handlerId)
383 				{
384 					onItemsChangedListeners[index] = null;
385 					onItemsChangedListeners = std.algorithm.remove(onItemsChangedListeners, index);
386 					break;
387 				}
388 			}
389 		}
390 	}
391 	OnItemsChangedDelegateWrapper[] onItemsChangedListeners;
392 
393 	/**
394 	 * Emitted when a change has occured to the menu.
395 	 *
396 	 * The only changes that can occur to a menu is that items are removed
397 	 * or added.  Items may not change (except by being removed and added
398 	 * back in the same location).  This signal is capable of describing
399 	 * both of those changes (at the same time).
400 	 *
401 	 * The signal means that starting at the index @position, @removed
402 	 * items were removed and @added items were added in their place.  If
403 	 * @removed is zero then only items were added.  If @added is zero
404 	 * then only items were removed.
405 	 *
406 	 * As an example, if the menu contains items a, b, c, d (in that
407 	 * order) and the signal (2, 1, 3) occurs then the new composition of
408 	 * the menu will be a, b, _, _, _, d (with each _ representing some
409 	 * new item).
410 	 *
411 	 * Signal handlers may query the model (particularly the added items)
412 	 * and expect to see the results of the modification that is being
413 	 * reported.  The signal is emitted after the modification.
414 	 *
415 	 * Params:
416 	 *     position = the position of the change
417 	 *     removed = the number of items removed
418 	 *     added = the number of items added
419 	 */
420 	gulong addOnItemsChanged(void delegate(int, int, int, MenuModel) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
421 	{
422 		auto wrapper = new OnItemsChangedDelegateWrapper(dlg);
423 		wrapper.handlerId = Signals.connectData(
424 			this,
425 			"items-changed",
426 			cast(GCallback)&callBackItemsChanged,
427 			cast(void*)wrapper,
428 			cast(GClosureNotify)&callBackItemsChangedDestroy,
429 			connectFlags);
430 		return wrapper.handlerId;
431 	}
432 
433 	extern(C) static void callBackItemsChanged(GMenuModel* menumodelStruct, int position, int removed, int added, OnItemsChangedDelegateWrapper wrapper)
434 	{
435 		wrapper.dlg(position, removed, added, wrapper.outer);
436 	}
437 
438 	extern(C) static void callBackItemsChangedDestroy(OnItemsChangedDelegateWrapper wrapper, GClosure* closure)
439 	{
440 		wrapper.remove(wrapper);
441 	}
442 }