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