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 }