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.Paned;
26 
27 private import gdk.Window;
28 private import glib.ConstructionException;
29 private import gobject.ObjectG;
30 private import gobject.Signals;
31 private import gtk.Container;
32 private import gtk.OrientableIF;
33 private import gtk.OrientableT;
34 private import gtk.Widget;
35 private import gtk.c.functions;
36 public  import gtk.c.types;
37 public  import gtkc.gtktypes;
38 private import std.algorithm;
39 
40 
41 /**
42  * #GtkPaned has two panes, arranged either
43  * horizontally or vertically. The division between
44  * the two panes is adjustable by the user by dragging
45  * a handle.
46  * 
47  * Child widgets are
48  * added to the panes of the widget with gtk_paned_pack1() and
49  * gtk_paned_pack2(). The division between the two children is set by default
50  * from the size requests of the children, but it can be adjusted by the
51  * user.
52  * 
53  * A paned widget draws a separator between the two child widgets and a
54  * small handle that the user can drag to adjust the division. It does not
55  * draw any relief around the children or around the separator. (The space
56  * in which the separator is called the gutter.) Often, it is useful to put
57  * each child inside a #GtkFrame with the shadow type set to %GTK_SHADOW_IN
58  * so that the gutter appears as a ridge. No separator is drawn if one of
59  * the children is missing.
60  * 
61  * Each child has two options that can be set, @resize and @shrink. If
62  * @resize is true, then when the #GtkPaned is resized, that child will
63  * expand or shrink along with the paned widget. If @shrink is true, then
64  * that child can be made smaller than its requisition by the user.
65  * Setting @shrink to %FALSE allows the application to set a minimum size.
66  * If @resize is false for both children, then this is treated as if
67  * @resize is true for both children.
68  * 
69  * The application can set the position of the slider as if it were set
70  * by the user, by calling gtk_paned_set_position().
71  * 
72  * # CSS nodes
73  * 
74  * |[<!-- language="plain" -->
75  * paned
76  * ├── <child>
77  * ├── separator[.wide]
78  * ╰── <child>
79  * ]|
80  * 
81  * GtkPaned has a main CSS node with name paned, and a subnode for
82  * the separator with name separator. The subnode gets a .wide style
83  * class when the paned is supposed to be wide.
84  * 
85  * In horizontal orientation, the nodes of the children are always arranged
86  * from left to right. So :first-child will always select the leftmost child,
87  * regardless of text direction.
88  * 
89  * ## Creating a paned widget with minimum sizes.
90  * 
91  * |[<!-- language="C" -->
92  * GtkWidget *hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
93  * GtkWidget *frame1 = gtk_frame_new (NULL);
94  * GtkWidget *frame2 = gtk_frame_new (NULL);
95  * gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_IN);
96  * gtk_frame_set_shadow_type (GTK_FRAME (frame2), GTK_SHADOW_IN);
97  * 
98  * gtk_widget_set_size_request (hpaned, 200, -1);
99  * 
100  * gtk_paned_pack1 (GTK_PANED (hpaned), frame1, TRUE, FALSE);
101  * gtk_widget_set_size_request (frame1, 50, -1);
102  * 
103  * gtk_paned_pack2 (GTK_PANED (hpaned), frame2, FALSE, FALSE);
104  * gtk_widget_set_size_request (frame2, 50, -1);
105  * ]|
106  */
107 public class Paned : Container, OrientableIF
108 {
109 	/** the main Gtk struct */
110 	protected GtkPaned* gtkPaned;
111 
112 	/** Get the main Gtk struct */
113 	public GtkPaned* getPanedStruct(bool transferOwnership = false)
114 	{
115 		if (transferOwnership)
116 			ownedRef = false;
117 		return gtkPaned;
118 	}
119 
120 	/** the main Gtk struct as a void* */
121 	protected override void* getStruct()
122 	{
123 		return cast(void*)gtkPaned;
124 	}
125 
126 	/**
127 	 * Sets our main struct and passes it to the parent class.
128 	 */
129 	public this (GtkPaned* gtkPaned, bool ownedRef = false)
130 	{
131 		this.gtkPaned = gtkPaned;
132 		super(cast(GtkContainer*)gtkPaned, ownedRef);
133 	}
134 
135 	// add the Orientable capabilities
136 	mixin OrientableT!(GtkPaned);
137 
138 	/** */
139 	public void add(Widget child1, Widget child2)
140 	{
141 		add1(child1);
142 		add2(child2);
143 	}
144 
145 	/**
146 	 */
147 
148 	/** */
149 	public static GType getType()
150 	{
151 		return gtk_paned_get_type();
152 	}
153 
154 	/**
155 	 * Creates a new #GtkPaned widget.
156 	 *
157 	 * Params:
158 	 *     orientation = the paned’s orientation.
159 	 *
160 	 * Returns: a new #GtkPaned.
161 	 *
162 	 * Since: 3.0
163 	 *
164 	 * Throws: ConstructionException GTK+ fails to create the object.
165 	 */
166 	public this(GtkOrientation orientation)
167 	{
168 		auto p = gtk_paned_new(orientation);
169 
170 		if(p is null)
171 		{
172 			throw new ConstructionException("null returned by new");
173 		}
174 
175 		this(cast(GtkPaned*) p);
176 	}
177 
178 	/**
179 	 * Adds a child to the top or left pane with default parameters. This is
180 	 * equivalent to
181 	 * `gtk_paned_pack1 (paned, child, FALSE, TRUE)`.
182 	 *
183 	 * Params:
184 	 *     child = the child to add
185 	 */
186 	public void add1(Widget child)
187 	{
188 		gtk_paned_add1(gtkPaned, (child is null) ? null : child.getWidgetStruct());
189 	}
190 
191 	/**
192 	 * Adds a child to the bottom or right pane with default parameters. This
193 	 * is equivalent to
194 	 * `gtk_paned_pack2 (paned, child, TRUE, TRUE)`.
195 	 *
196 	 * Params:
197 	 *     child = the child to add
198 	 */
199 	public void add2(Widget child)
200 	{
201 		gtk_paned_add2(gtkPaned, (child is null) ? null : child.getWidgetStruct());
202 	}
203 
204 	/**
205 	 * Obtains the first child of the paned widget.
206 	 *
207 	 * Returns: first child, or %NULL if it is not set.
208 	 *
209 	 * Since: 2.4
210 	 */
211 	public Widget getChild1()
212 	{
213 		auto p = gtk_paned_get_child1(gtkPaned);
214 
215 		if(p is null)
216 		{
217 			return null;
218 		}
219 
220 		return ObjectG.getDObject!(Widget)(cast(GtkWidget*) p);
221 	}
222 
223 	/**
224 	 * Obtains the second child of the paned widget.
225 	 *
226 	 * Returns: second child, or %NULL if it is not set.
227 	 *
228 	 * Since: 2.4
229 	 */
230 	public Widget getChild2()
231 	{
232 		auto p = gtk_paned_get_child2(gtkPaned);
233 
234 		if(p is null)
235 		{
236 			return null;
237 		}
238 
239 		return ObjectG.getDObject!(Widget)(cast(GtkWidget*) p);
240 	}
241 
242 	/**
243 	 * Returns the #GdkWindow of the handle. This function is
244 	 * useful when handling button or motion events because it
245 	 * enables the callback to distinguish between the window
246 	 * of the paned, a child and the handle.
247 	 *
248 	 * Returns: the paned’s handle window.
249 	 *
250 	 * Since: 2.20
251 	 */
252 	public Window getHandleWindow()
253 	{
254 		auto p = gtk_paned_get_handle_window(gtkPaned);
255 
256 		if(p is null)
257 		{
258 			return null;
259 		}
260 
261 		return ObjectG.getDObject!(Window)(cast(GdkWindow*) p);
262 	}
263 
264 	/**
265 	 * Obtains the position of the divider between the two panes.
266 	 *
267 	 * Returns: position of the divider
268 	 */
269 	public int getPosition()
270 	{
271 		return gtk_paned_get_position(gtkPaned);
272 	}
273 
274 	/**
275 	 * Gets the #GtkPaned:wide-handle property.
276 	 *
277 	 * Returns: %TRUE if the paned should have a wide handle
278 	 *
279 	 * Since: 3.16
280 	 */
281 	public bool getWideHandle()
282 	{
283 		return gtk_paned_get_wide_handle(gtkPaned) != 0;
284 	}
285 
286 	/**
287 	 * Adds a child to the top or left pane.
288 	 *
289 	 * Params:
290 	 *     child = the child to add
291 	 *     resize = should this child expand when the paned widget is resized.
292 	 *     shrink = can this child be made smaller than its requisition.
293 	 */
294 	public void pack1(Widget child, bool resize, bool shrink)
295 	{
296 		gtk_paned_pack1(gtkPaned, (child is null) ? null : child.getWidgetStruct(), resize, shrink);
297 	}
298 
299 	/**
300 	 * Adds a child to the bottom or right pane.
301 	 *
302 	 * Params:
303 	 *     child = the child to add
304 	 *     resize = should this child expand when the paned widget is resized.
305 	 *     shrink = can this child be made smaller than its requisition.
306 	 */
307 	public void pack2(Widget child, bool resize, bool shrink)
308 	{
309 		gtk_paned_pack2(gtkPaned, (child is null) ? null : child.getWidgetStruct(), resize, shrink);
310 	}
311 
312 	/**
313 	 * Sets the position of the divider between the two panes.
314 	 *
315 	 * Params:
316 	 *     position = pixel position of divider, a negative value means that the position
317 	 *         is unset.
318 	 */
319 	public void setPosition(int position)
320 	{
321 		gtk_paned_set_position(gtkPaned, position);
322 	}
323 
324 	/**
325 	 * Sets the #GtkPaned:wide-handle property.
326 	 *
327 	 * Params:
328 	 *     wide = the new value for the #GtkPaned:wide-handle property
329 	 *
330 	 * Since: 3.16
331 	 */
332 	public void setWideHandle(bool wide)
333 	{
334 		gtk_paned_set_wide_handle(gtkPaned, wide);
335 	}
336 
337 	protected class OnAcceptPositionDelegateWrapper
338 	{
339 		bool delegate(Paned) dlg;
340 		gulong handlerId;
341 
342 		this(bool delegate(Paned) dlg)
343 		{
344 			this.dlg = dlg;
345 			onAcceptPositionListeners ~= this;
346 		}
347 
348 		void remove(OnAcceptPositionDelegateWrapper source)
349 		{
350 			foreach(index, wrapper; onAcceptPositionListeners)
351 			{
352 				if (wrapper.handlerId == source.handlerId)
353 				{
354 					onAcceptPositionListeners[index] = null;
355 					onAcceptPositionListeners = std.algorithm.remove(onAcceptPositionListeners, index);
356 					break;
357 				}
358 			}
359 		}
360 	}
361 	OnAcceptPositionDelegateWrapper[] onAcceptPositionListeners;
362 
363 	/**
364 	 * The ::accept-position signal is a
365 	 * [keybinding signal][GtkBindingSignal]
366 	 * which gets emitted to accept the current position of the handle when
367 	 * moving it using key bindings.
368 	 *
369 	 * The default binding for this signal is Return or Space.
370 	 *
371 	 * Since: 2.0
372 	 */
373 	gulong addOnAcceptPosition(bool delegate(Paned) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
374 	{
375 		auto wrapper = new OnAcceptPositionDelegateWrapper(dlg);
376 		wrapper.handlerId = Signals.connectData(
377 			this,
378 			"accept-position",
379 			cast(GCallback)&callBackAcceptPosition,
380 			cast(void*)wrapper,
381 			cast(GClosureNotify)&callBackAcceptPositionDestroy,
382 			connectFlags);
383 		return wrapper.handlerId;
384 	}
385 
386 	extern(C) static int callBackAcceptPosition(GtkPaned* panedStruct, OnAcceptPositionDelegateWrapper wrapper)
387 	{
388 		return wrapper.dlg(wrapper.outer);
389 	}
390 
391 	extern(C) static void callBackAcceptPositionDestroy(OnAcceptPositionDelegateWrapper wrapper, GClosure* closure)
392 	{
393 		wrapper.remove(wrapper);
394 	}
395 
396 	protected class OnCancelPositionDelegateWrapper
397 	{
398 		bool delegate(Paned) dlg;
399 		gulong handlerId;
400 
401 		this(bool delegate(Paned) dlg)
402 		{
403 			this.dlg = dlg;
404 			onCancelPositionListeners ~= this;
405 		}
406 
407 		void remove(OnCancelPositionDelegateWrapper source)
408 		{
409 			foreach(index, wrapper; onCancelPositionListeners)
410 			{
411 				if (wrapper.handlerId == source.handlerId)
412 				{
413 					onCancelPositionListeners[index] = null;
414 					onCancelPositionListeners = std.algorithm.remove(onCancelPositionListeners, index);
415 					break;
416 				}
417 			}
418 		}
419 	}
420 	OnCancelPositionDelegateWrapper[] onCancelPositionListeners;
421 
422 	/**
423 	 * The ::cancel-position signal is a
424 	 * [keybinding signal][GtkBindingSignal]
425 	 * which gets emitted to cancel moving the position of the handle using key
426 	 * bindings. The position of the handle will be reset to the value prior to
427 	 * moving it.
428 	 *
429 	 * The default binding for this signal is Escape.
430 	 *
431 	 * Since: 2.0
432 	 */
433 	gulong addOnCancelPosition(bool delegate(Paned) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
434 	{
435 		auto wrapper = new OnCancelPositionDelegateWrapper(dlg);
436 		wrapper.handlerId = Signals.connectData(
437 			this,
438 			"cancel-position",
439 			cast(GCallback)&callBackCancelPosition,
440 			cast(void*)wrapper,
441 			cast(GClosureNotify)&callBackCancelPositionDestroy,
442 			connectFlags);
443 		return wrapper.handlerId;
444 	}
445 
446 	extern(C) static int callBackCancelPosition(GtkPaned* panedStruct, OnCancelPositionDelegateWrapper wrapper)
447 	{
448 		return wrapper.dlg(wrapper.outer);
449 	}
450 
451 	extern(C) static void callBackCancelPositionDestroy(OnCancelPositionDelegateWrapper wrapper, GClosure* closure)
452 	{
453 		wrapper.remove(wrapper);
454 	}
455 
456 	protected class OnCycleChildFocusDelegateWrapper
457 	{
458 		bool delegate(bool, Paned) dlg;
459 		gulong handlerId;
460 
461 		this(bool delegate(bool, Paned) dlg)
462 		{
463 			this.dlg = dlg;
464 			onCycleChildFocusListeners ~= this;
465 		}
466 
467 		void remove(OnCycleChildFocusDelegateWrapper source)
468 		{
469 			foreach(index, wrapper; onCycleChildFocusListeners)
470 			{
471 				if (wrapper.handlerId == source.handlerId)
472 				{
473 					onCycleChildFocusListeners[index] = null;
474 					onCycleChildFocusListeners = std.algorithm.remove(onCycleChildFocusListeners, index);
475 					break;
476 				}
477 			}
478 		}
479 	}
480 	OnCycleChildFocusDelegateWrapper[] onCycleChildFocusListeners;
481 
482 	/**
483 	 * The ::cycle-child-focus signal is a
484 	 * [keybinding signal][GtkBindingSignal]
485 	 * which gets emitted to cycle the focus between the children of the paned.
486 	 *
487 	 * The default binding is f6.
488 	 *
489 	 * Params:
490 	 *     reversed = whether cycling backward or forward
491 	 *
492 	 * Since: 2.0
493 	 */
494 	gulong addOnCycleChildFocus(bool delegate(bool, Paned) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
495 	{
496 		auto wrapper = new OnCycleChildFocusDelegateWrapper(dlg);
497 		wrapper.handlerId = Signals.connectData(
498 			this,
499 			"cycle-child-focus",
500 			cast(GCallback)&callBackCycleChildFocus,
501 			cast(void*)wrapper,
502 			cast(GClosureNotify)&callBackCycleChildFocusDestroy,
503 			connectFlags);
504 		return wrapper.handlerId;
505 	}
506 
507 	extern(C) static int callBackCycleChildFocus(GtkPaned* panedStruct, bool reversed, OnCycleChildFocusDelegateWrapper wrapper)
508 	{
509 		return wrapper.dlg(reversed, wrapper.outer);
510 	}
511 
512 	extern(C) static void callBackCycleChildFocusDestroy(OnCycleChildFocusDelegateWrapper wrapper, GClosure* closure)
513 	{
514 		wrapper.remove(wrapper);
515 	}
516 
517 	protected class OnCycleHandleFocusDelegateWrapper
518 	{
519 		bool delegate(bool, Paned) dlg;
520 		gulong handlerId;
521 
522 		this(bool delegate(bool, Paned) dlg)
523 		{
524 			this.dlg = dlg;
525 			onCycleHandleFocusListeners ~= this;
526 		}
527 
528 		void remove(OnCycleHandleFocusDelegateWrapper source)
529 		{
530 			foreach(index, wrapper; onCycleHandleFocusListeners)
531 			{
532 				if (wrapper.handlerId == source.handlerId)
533 				{
534 					onCycleHandleFocusListeners[index] = null;
535 					onCycleHandleFocusListeners = std.algorithm.remove(onCycleHandleFocusListeners, index);
536 					break;
537 				}
538 			}
539 		}
540 	}
541 	OnCycleHandleFocusDelegateWrapper[] onCycleHandleFocusListeners;
542 
543 	/**
544 	 * The ::cycle-handle-focus signal is a
545 	 * [keybinding signal][GtkBindingSignal]
546 	 * which gets emitted to cycle whether the paned should grab focus to allow
547 	 * the user to change position of the handle by using key bindings.
548 	 *
549 	 * The default binding for this signal is f8.
550 	 *
551 	 * Params:
552 	 *     reversed = whether cycling backward or forward
553 	 *
554 	 * Since: 2.0
555 	 */
556 	gulong addOnCycleHandleFocus(bool delegate(bool, Paned) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
557 	{
558 		auto wrapper = new OnCycleHandleFocusDelegateWrapper(dlg);
559 		wrapper.handlerId = Signals.connectData(
560 			this,
561 			"cycle-handle-focus",
562 			cast(GCallback)&callBackCycleHandleFocus,
563 			cast(void*)wrapper,
564 			cast(GClosureNotify)&callBackCycleHandleFocusDestroy,
565 			connectFlags);
566 		return wrapper.handlerId;
567 	}
568 
569 	extern(C) static int callBackCycleHandleFocus(GtkPaned* panedStruct, bool reversed, OnCycleHandleFocusDelegateWrapper wrapper)
570 	{
571 		return wrapper.dlg(reversed, wrapper.outer);
572 	}
573 
574 	extern(C) static void callBackCycleHandleFocusDestroy(OnCycleHandleFocusDelegateWrapper wrapper, GClosure* closure)
575 	{
576 		wrapper.remove(wrapper);
577 	}
578 
579 	protected class OnMoveHandleDelegateWrapper
580 	{
581 		bool delegate(GtkScrollType, Paned) dlg;
582 		gulong handlerId;
583 
584 		this(bool delegate(GtkScrollType, Paned) dlg)
585 		{
586 			this.dlg = dlg;
587 			onMoveHandleListeners ~= this;
588 		}
589 
590 		void remove(OnMoveHandleDelegateWrapper source)
591 		{
592 			foreach(index, wrapper; onMoveHandleListeners)
593 			{
594 				if (wrapper.handlerId == source.handlerId)
595 				{
596 					onMoveHandleListeners[index] = null;
597 					onMoveHandleListeners = std.algorithm.remove(onMoveHandleListeners, index);
598 					break;
599 				}
600 			}
601 		}
602 	}
603 	OnMoveHandleDelegateWrapper[] onMoveHandleListeners;
604 
605 	/**
606 	 * The ::move-handle signal is a
607 	 * [keybinding signal][GtkBindingSignal]
608 	 * which gets emitted to move the handle when the user is using key bindings
609 	 * to move it.
610 	 *
611 	 * Params:
612 	 *     scrollType = a #GtkScrollType
613 	 *
614 	 * Since: 2.0
615 	 */
616 	gulong addOnMoveHandle(bool delegate(GtkScrollType, Paned) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
617 	{
618 		auto wrapper = new OnMoveHandleDelegateWrapper(dlg);
619 		wrapper.handlerId = Signals.connectData(
620 			this,
621 			"move-handle",
622 			cast(GCallback)&callBackMoveHandle,
623 			cast(void*)wrapper,
624 			cast(GClosureNotify)&callBackMoveHandleDestroy,
625 			connectFlags);
626 		return wrapper.handlerId;
627 	}
628 
629 	extern(C) static int callBackMoveHandle(GtkPaned* panedStruct, GtkScrollType scrollType, OnMoveHandleDelegateWrapper wrapper)
630 	{
631 		return wrapper.dlg(scrollType, wrapper.outer);
632 	}
633 
634 	extern(C) static void callBackMoveHandleDestroy(OnMoveHandleDelegateWrapper wrapper, GClosure* closure)
635 	{
636 		wrapper.remove(wrapper);
637 	}
638 
639 	protected class OnToggleHandleFocusDelegateWrapper
640 	{
641 		bool delegate(Paned) dlg;
642 		gulong handlerId;
643 
644 		this(bool delegate(Paned) dlg)
645 		{
646 			this.dlg = dlg;
647 			onToggleHandleFocusListeners ~= this;
648 		}
649 
650 		void remove(OnToggleHandleFocusDelegateWrapper source)
651 		{
652 			foreach(index, wrapper; onToggleHandleFocusListeners)
653 			{
654 				if (wrapper.handlerId == source.handlerId)
655 				{
656 					onToggleHandleFocusListeners[index] = null;
657 					onToggleHandleFocusListeners = std.algorithm.remove(onToggleHandleFocusListeners, index);
658 					break;
659 				}
660 			}
661 		}
662 	}
663 	OnToggleHandleFocusDelegateWrapper[] onToggleHandleFocusListeners;
664 
665 	/**
666 	 * The ::toggle-handle-focus is a
667 	 * [keybinding signal][GtkBindingSignal]
668 	 * which gets emitted to accept the current position of the handle and then
669 	 * move focus to the next widget in the focus chain.
670 	 *
671 	 * The default binding is Tab.
672 	 *
673 	 * Since: 2.0
674 	 */
675 	gulong addOnToggleHandleFocus(bool delegate(Paned) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
676 	{
677 		auto wrapper = new OnToggleHandleFocusDelegateWrapper(dlg);
678 		wrapper.handlerId = Signals.connectData(
679 			this,
680 			"toggle-handle-focus",
681 			cast(GCallback)&callBackToggleHandleFocus,
682 			cast(void*)wrapper,
683 			cast(GClosureNotify)&callBackToggleHandleFocusDestroy,
684 			connectFlags);
685 		return wrapper.handlerId;
686 	}
687 
688 	extern(C) static int callBackToggleHandleFocus(GtkPaned* panedStruct, OnToggleHandleFocusDelegateWrapper wrapper)
689 	{
690 		return wrapper.dlg(wrapper.outer);
691 	}
692 
693 	extern(C) static void callBackToggleHandleFocusDestroy(OnToggleHandleFocusDelegateWrapper wrapper, GClosure* closure)
694 	{
695 		wrapper.remove(wrapper);
696 	}
697 }