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.Popover;
26 
27 private import gio.MenuModel;
28 private import glib.ConstructionException;
29 private import glib.Str;
30 private import gobject.ObjectG;
31 private import gobject.Signals;
32 private import gtk.Bin;
33 private import gtk.Widget;
34 public  import gtkc.gdktypes;
35 private import gtkc.gtk;
36 public  import gtkc.gtktypes;
37 private import std.algorithm;
38 
39 
40 /**
41  * GtkPopover is a bubble-like context window, primarily meant to
42  * provide context-dependent information or options. Popovers are
43  * attached to a widget, passed at construction time on gtk_popover_new(),
44  * or updated afterwards through gtk_popover_set_relative_to(), by
45  * default they will point to the whole widget area, although this
46  * behavior can be changed through gtk_popover_set_pointing_to().
47  * 
48  * The position of a popover relative to the widget it is attached to
49  * can also be changed through gtk_popover_set_position().
50  * 
51  * By default, #GtkPopover performs a GTK+ grab, in order to ensure
52  * input events get redirected to it while it is shown, and also so
53  * the popover is dismissed in the expected situations (clicks outside
54  * the popover, or the Esc key being pressed). If no such modal behavior
55  * is desired on a popover, gtk_popover_set_modal() may be called on it
56  * to tweak its behavior.
57  * 
58  * ## GtkPopover as menu replacement
59  * 
60  * GtkPopover is often used to replace menus. To facilitate this, it
61  * supports being populated from a #GMenuModel, using
62  * gtk_popover_new_from_model(). In addition to all the regular menu
63  * model features, this function supports rendering sections in the
64  * model in a more compact form, as a row of icon buttons instead of
65  * menu items.
66  * 
67  * To use this rendering, set the ”display-hint” attribute of the
68  * section to ”horizontal-buttons” and set the icons of your items
69  * with the ”verb-icon” attribute.
70  * 
71  * |[
72  * <section>
73  * <attribute name="display-hint">horizontal-buttons</attribute>
74  * <item>
75  * <attribute name="label">Cut</attribute>
76  * <attribute name="action">app.cut</attribute>
77  * <attribute name="verb-icon">edit-cut-symbolic</attribute>
78  * </item>
79  * <item>
80  * <attribute name="label">Copy</attribute>
81  * <attribute name="action">app.copy</attribute>
82  * <attribute name="verb-icon">edit-copy-symbolic</attribute>
83  * </item>
84  * <item>
85  * <attribute name="label">Paste</attribute>
86  * <attribute name="action">app.paste</attribute>
87  * <attribute name="verb-icon">edit-paste-symbolic</attribute>
88  * </item>
89  * </section>
90  * ]|
91  * 
92  * # CSS nodes
93  * 
94  * GtkPopover has a single css node called popover. It always gets the
95  * .background style class and it gets the .menu style class if it is
96  * menu-like (e.g. #GtkPopoverMenu or created using gtk_popover_new_from_model().
97  * 
98  * Particular uses of GtkPopover, such as touch selection popups
99  * or magnifiers in #GtkEntry or #GtkTextView get style classes
100  * like .touch-selection or .magnifier to differentiate from
101  * plain popovers.
102  */
103 public class Popover : Bin
104 {
105 	/** the main Gtk struct */
106 	protected GtkPopover* gtkPopover;
107 
108 	/** Get the main Gtk struct */
109 	public GtkPopover* getPopoverStruct()
110 	{
111 		return gtkPopover;
112 	}
113 
114 	/** the main Gtk struct as a void* */
115 	protected override void* getStruct()
116 	{
117 		return cast(void*)gtkPopover;
118 	}
119 
120 	protected override void setStruct(GObject* obj)
121 	{
122 		gtkPopover = cast(GtkPopover*)obj;
123 		super.setStruct(obj);
124 	}
125 
126 	/**
127 	 * Sets our main struct and passes it to the parent class.
128 	 */
129 	public this (GtkPopover* gtkPopover, bool ownedRef = false)
130 	{
131 		this.gtkPopover = gtkPopover;
132 		super(cast(GtkBin*)gtkPopover, ownedRef);
133 	}
134 
135 
136 	/** */
137 	public static GType getType()
138 	{
139 		return gtk_popover_get_type();
140 	}
141 
142 	/**
143 	 * Creates a new popover to point to @relative_to
144 	 *
145 	 * Params:
146 	 *     relativeTo = #GtkWidget the popover is related to
147 	 *
148 	 * Return: a new #GtkPopover
149 	 *
150 	 * Since: 3.12
151 	 *
152 	 * Throws: ConstructionException GTK+ fails to create the object.
153 	 */
154 	public this(Widget relativeTo)
155 	{
156 		auto p = gtk_popover_new((relativeTo is null) ? null : relativeTo.getWidgetStruct());
157 		
158 		if(p is null)
159 		{
160 			throw new ConstructionException("null returned by new");
161 		}
162 		
163 		this(cast(GtkPopover*) p);
164 	}
165 
166 	/**
167 	 * Creates a #GtkPopover and populates it according to
168 	 * @model. The popover is pointed to the @relative_to widget.
169 	 *
170 	 * The created buttons are connected to actions found in the
171 	 * #GtkApplicationWindow to which the popover belongs - typically
172 	 * by means of being attached to a widget that is contained within
173 	 * the #GtkApplicationWindows widget hierarchy.
174 	 *
175 	 * Actions can also be added using gtk_widget_insert_action_group()
176 	 * on the menus attach widget or on any of its parent widgets.
177 	 *
178 	 * Params:
179 	 *     relativeTo = #GtkWidget the popover is related to
180 	 *     model = a #GMenuModel
181 	 *
182 	 * Return: the new #GtkPopover
183 	 *
184 	 * Since: 3.12
185 	 *
186 	 * Throws: ConstructionException GTK+ fails to create the object.
187 	 */
188 	public this(Widget relativeTo, MenuModel model)
189 	{
190 		auto p = gtk_popover_new_from_model((relativeTo is null) ? null : relativeTo.getWidgetStruct(), (model is null) ? null : model.getMenuModelStruct());
191 		
192 		if(p is null)
193 		{
194 			throw new ConstructionException("null returned by new_from_model");
195 		}
196 		
197 		this(cast(GtkPopover*) p);
198 	}
199 
200 	/**
201 	 * Establishes a binding between a #GtkPopover and a #GMenuModel.
202 	 *
203 	 * The contents of @popover are removed and then refilled with menu items
204 	 * according to @model.  When @model changes, @popover is updated.
205 	 * Calling this function twice on @popover with different @model will
206 	 * cause the first binding to be replaced with a binding to the new
207 	 * model. If @model is %NULL then any previous binding is undone and
208 	 * all children are removed.
209 	 *
210 	 * If @action_namespace is non-%NULL then the effect is as if all
211 	 * actions mentioned in the @model have their names prefixed with the
212 	 * namespace, plus a dot.  For example, if the action “quit” is
213 	 * mentioned and @action_namespace is “app” then the effective action
214 	 * name is “app.quit”.
215 	 *
216 	 * This function uses #GtkActionable to define the action name and
217 	 * target values on the created menu items.  If you want to use an
218 	 * action group other than “app” and “win”, or if you want to use a
219 	 * #GtkMenuShell outside of a #GtkApplicationWindow, then you will need
220 	 * to attach your own action group to the widget hierarchy using
221 	 * gtk_widget_insert_action_group().  As an example, if you created a
222 	 * group with a “quit” action and inserted it with the name “mygroup”
223 	 * then you would use the action name “mygroup.quit” in your
224 	 * #GMenuModel.
225 	 *
226 	 * Params:
227 	 *     model = the #GMenuModel to bind to or %NULL to remove
228 	 *         binding
229 	 *     actionNamespace = the namespace for actions in @model
230 	 *
231 	 * Since: 3.12
232 	 */
233 	public void bindModel(MenuModel model, string actionNamespace)
234 	{
235 		gtk_popover_bind_model(gtkPopover, (model is null) ? null : model.getMenuModelStruct(), Str.toStringz(actionNamespace));
236 	}
237 
238 	/**
239 	 * Returns the constraint for placing this popover.
240 	 * See gtk_popover_set_constrain_to().
241 	 *
242 	 * Return: the constraint for placing this popover.
243 	 *
244 	 * Since: 3.20
245 	 */
246 	public GtkPopoverConstraint getConstrainTo()
247 	{
248 		return gtk_popover_get_constrain_to(gtkPopover);
249 	}
250 
251 	/**
252 	 * Gets the widget that should be set as the default while
253 	 * the popover is shown.
254 	 *
255 	 * Return: the default widget,
256 	 *     or %NULL if there is none
257 	 *
258 	 * Since: 3.18
259 	 */
260 	public Widget getDefaultWidget()
261 	{
262 		auto p = gtk_popover_get_default_widget(gtkPopover);
263 		
264 		if(p is null)
265 		{
266 			return null;
267 		}
268 		
269 		return ObjectG.getDObject!(Widget)(cast(GtkWidget*) p);
270 	}
271 
272 	/**
273 	 * Returns whether the popover is modal, see gtk_popover_set_modal to
274 	 * see the implications of this.
275 	 *
276 	 * Return: #TRUE if @popover is modal
277 	 *
278 	 * Since: 3.12
279 	 */
280 	public bool getModal()
281 	{
282 		return gtk_popover_get_modal(gtkPopover) != 0;
283 	}
284 
285 	/**
286 	 * If a rectangle to point to has been set, this function will
287 	 * return %TRUE and fill in @rect with such rectangle, otherwise
288 	 * it will return %FALSE and fill in @rect with the attached
289 	 * widget coordinates.
290 	 *
291 	 * Params:
292 	 *     rect = location to store the rectangle
293 	 *
294 	 * Return: %TRUE if a rectangle to point to was set.
295 	 */
296 	public bool getPointingTo(out GdkRectangle rect)
297 	{
298 		return gtk_popover_get_pointing_to(gtkPopover, &rect) != 0;
299 	}
300 
301 	/**
302 	 * Returns the preferred position of @popover.
303 	 *
304 	 * Return: The preferred position.
305 	 */
306 	public GtkPositionType getPosition()
307 	{
308 		return gtk_popover_get_position(gtkPopover);
309 	}
310 
311 	/**
312 	 * Returns the widget @popover is currently attached to
313 	 *
314 	 * Return: a #GtkWidget
315 	 *
316 	 * Since: 3.12
317 	 */
318 	public Widget getRelativeTo()
319 	{
320 		auto p = gtk_popover_get_relative_to(gtkPopover);
321 		
322 		if(p is null)
323 		{
324 			return null;
325 		}
326 		
327 		return ObjectG.getDObject!(Widget)(cast(GtkWidget*) p);
328 	}
329 
330 	/**
331 	 * Returns whether show/hide transitions are enabled on this popover.
332 	 *
333 	 * Deprecated: You can show or hide the popover without transitions
334 	 * using gtk_widget_show() and gtk_widget_hide() while gtk_popover_popup()
335 	 * and gtk_popover_popdown() will use transitions.
336 	 *
337 	 * Return: #TRUE if the show and hide transitions of the given
338 	 *     popover are enabled, #FALSE otherwise.
339 	 *
340 	 * Since: 3.16
341 	 */
342 	public bool getTransitionsEnabled()
343 	{
344 		return gtk_popover_get_transitions_enabled(gtkPopover) != 0;
345 	}
346 
347 	/**
348 	 * Pops @popover down.This is different than a gtk_widget_hide() call
349 	 * in that it shows the popover with a transition. If you want to hide
350 	 * the popover without a transition, use gtk_widget_hide().
351 	 *
352 	 * Since: 3.22
353 	 */
354 	public void popdown()
355 	{
356 		gtk_popover_popdown(gtkPopover);
357 	}
358 
359 	/**
360 	 * Pops @popover up. This is different than a gtk_widget_show() call
361 	 * in that it shows the popover with a transition. If you want to show
362 	 * the popover without a transition, use gtk_widget_show().
363 	 *
364 	 * Since: 3.22
365 	 */
366 	public void popup()
367 	{
368 		gtk_popover_popup(gtkPopover);
369 	}
370 
371 	/**
372 	 * Sets a constraint for positioning this popover.
373 	 *
374 	 * Note that not all platforms support placing popovers freely,
375 	 * and may already impose constraints.
376 	 *
377 	 * Params:
378 	 *     constraint = the new constraint
379 	 *
380 	 * Since: 3.20
381 	 */
382 	public void setConstrainTo(GtkPopoverConstraint constraint)
383 	{
384 		gtk_popover_set_constrain_to(gtkPopover, constraint);
385 	}
386 
387 	/**
388 	 * Sets the widget that should be set as default widget while
389 	 * the popover is shown (see gtk_window_set_default()). #GtkPopover
390 	 * remembers the previous default widget and reestablishes it
391 	 * when the popover is dismissed.
392 	 *
393 	 * Params:
394 	 *     widget = the new default widget, or %NULL
395 	 *
396 	 * Since: 3.18
397 	 */
398 	public void setDefaultWidget(Widget widget)
399 	{
400 		gtk_popover_set_default_widget(gtkPopover, (widget is null) ? null : widget.getWidgetStruct());
401 	}
402 
403 	/**
404 	 * Sets whether @popover is modal, a modal popover will grab all input
405 	 * within the toplevel and grab the keyboard focus on it when being
406 	 * displayed. Clicking outside the popover area or pressing Esc will
407 	 * dismiss the popover and ungrab input.
408 	 *
409 	 * Params:
410 	 *     modal = #TRUE to make popover claim all input within the toplevel
411 	 *
412 	 * Since: 3.12
413 	 */
414 	public void setModal(bool modal)
415 	{
416 		gtk_popover_set_modal(gtkPopover, modal);
417 	}
418 
419 	/**
420 	 * Sets the rectangle that @popover will point to, in the
421 	 * coordinate space of the widget @popover is attached to,
422 	 * see gtk_popover_set_relative_to().
423 	 *
424 	 * Params:
425 	 *     rect = rectangle to point to
426 	 *
427 	 * Since: 3.12
428 	 */
429 	public void setPointingTo(GdkRectangle* rect)
430 	{
431 		gtk_popover_set_pointing_to(gtkPopover, rect);
432 	}
433 
434 	/**
435 	 * Sets the preferred position for @popover to appear. If the @popover
436 	 * is currently visible, it will be immediately updated.
437 	 *
438 	 * This preference will be respected where possible, although
439 	 * on lack of space (eg. if close to the window edges), the
440 	 * #GtkPopover may choose to appear on the opposite side
441 	 *
442 	 * Params:
443 	 *     position = preferred popover position
444 	 *
445 	 * Since: 3.12
446 	 */
447 	public void setPosition(GtkPositionType position)
448 	{
449 		gtk_popover_set_position(gtkPopover, position);
450 	}
451 
452 	/**
453 	 * Sets a new widget to be attached to @popover. If @popover is
454 	 * visible, the position will be updated.
455 	 *
456 	 * Note: the ownership of popovers is always given to their @relative_to
457 	 * widget, so if @relative_to is set to %NULL on an attached @popover, it
458 	 * will be detached from its previous widget, and consequently destroyed
459 	 * unless extra references are kept.
460 	 *
461 	 * Params:
462 	 *     relativeTo = a #GtkWidget
463 	 *
464 	 * Since: 3.12
465 	 */
466 	public void setRelativeTo(Widget relativeTo)
467 	{
468 		gtk_popover_set_relative_to(gtkPopover, (relativeTo is null) ? null : relativeTo.getWidgetStruct());
469 	}
470 
471 	/**
472 	 * Sets whether show/hide transitions are enabled on this popover
473 	 *
474 	 * Deprecated: You can show or hide the popover without transitions
475 	 * using gtk_widget_show() and gtk_widget_hide() while gtk_popover_popup()
476 	 * and gtk_popover_popdown() will use transitions.
477 	 *
478 	 * Params:
479 	 *     transitionsEnabled = Whether transitions are enabled
480 	 *
481 	 * Since: 3.16
482 	 */
483 	public void setTransitionsEnabled(bool transitionsEnabled)
484 	{
485 		gtk_popover_set_transitions_enabled(gtkPopover, transitionsEnabled);
486 	}
487 
488 	protected class OnClosedDelegateWrapper
489 	{
490 		void delegate(Popover) dlg;
491 		gulong handlerId;
492 		ConnectFlags flags;
493 		this(void delegate(Popover) dlg, gulong handlerId, ConnectFlags flags)
494 		{
495 			this.dlg = dlg;
496 			this.handlerId = handlerId;
497 			this.flags = flags;
498 		}
499 	}
500 	protected OnClosedDelegateWrapper[] onClosedListeners;
501 
502 	/** */
503 	gulong addOnClosed(void delegate(Popover) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
504 	{
505 		onClosedListeners ~= new OnClosedDelegateWrapper(dlg, 0, connectFlags);
506 		onClosedListeners[onClosedListeners.length - 1].handlerId = Signals.connectData(
507 			this,
508 			"closed",
509 			cast(GCallback)&callBackClosed,
510 			cast(void*)onClosedListeners[onClosedListeners.length - 1],
511 			cast(GClosureNotify)&callBackClosedDestroy,
512 			connectFlags);
513 		return onClosedListeners[onClosedListeners.length - 1].handlerId;
514 	}
515 	
516 	extern(C) static void callBackClosed(GtkPopover* popoverStruct,OnClosedDelegateWrapper wrapper)
517 	{
518 		wrapper.dlg(wrapper.outer);
519 	}
520 	
521 	extern(C) static void callBackClosedDestroy(OnClosedDelegateWrapper wrapper, GClosure* closure)
522 	{
523 		wrapper.outer.internalRemoveOnClosed(wrapper);
524 	}
525 
526 	protected void internalRemoveOnClosed(OnClosedDelegateWrapper source)
527 	{
528 		foreach(index, wrapper; onClosedListeners)
529 		{
530 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
531 			{
532 				onClosedListeners[index] = null;
533 				onClosedListeners = std.algorithm.remove(onClosedListeners, index);
534 				break;
535 			}
536 		}
537 	}
538 	
539 }