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