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