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