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 }