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.FlowBox; 26 27 private import gio.ListModelIF; 28 private import glib.ConstructionException; 29 private import glib.ListG; 30 private import gobject.ObjectG; 31 private import gobject.Signals; 32 private import gtk.Adjustment; 33 private import gtk.Container; 34 private import gtk.FlowBoxChild; 35 private import gtk.OrientableIF; 36 private import gtk.OrientableT; 37 private import gtk.Widget; 38 private import gtk.c.functions; 39 public import gtk.c.types; 40 public import gtkc.gtktypes; 41 private import std.algorithm; 42 43 44 /** 45 * A GtkFlowBox positions child widgets in sequence according to its 46 * orientation. 47 * 48 * For instance, with the horizontal orientation, the widgets will be 49 * arranged from left to right, starting a new row under the previous 50 * row when necessary. Reducing the width in this case will require more 51 * rows, so a larger height will be requested. 52 * 53 * Likewise, with the vertical orientation, the widgets will be arranged 54 * from top to bottom, starting a new column to the right when necessary. 55 * Reducing the height will require more columns, so a larger width will 56 * be requested. 57 * 58 * The size request of a GtkFlowBox alone may not be what you expect; if you 59 * need to be able to shrink it along both axes and dynamically reflow its 60 * children, you may have to wrap it in a #GtkScrolledWindow to enable that. 61 * 62 * The children of a GtkFlowBox can be dynamically sorted and filtered. 63 * 64 * Although a GtkFlowBox must have only #GtkFlowBoxChild children, 65 * you can add any kind of widget to it via gtk_container_add(), and 66 * a GtkFlowBoxChild widget will automatically be inserted between 67 * the box and the widget. 68 * 69 * Also see #GtkListBox. 70 * 71 * GtkFlowBox was added in GTK+ 3.12. 72 * 73 * # CSS nodes 74 * 75 * |[<!-- language="plain" --> 76 * flowbox 77 * ├── flowboxchild 78 * │ ╰── <child> 79 * ├── flowboxchild 80 * │ ╰── <child> 81 * ┊ 82 * ╰── [rubberband] 83 * ]| 84 * 85 * GtkFlowBox uses a single CSS node with name flowbox. GtkFlowBoxChild 86 * uses a single CSS node with name flowboxchild. 87 * For rubberband selection, a subnode with name rubberband is used. 88 */ 89 public class FlowBox : Container, OrientableIF 90 { 91 /** the main Gtk struct */ 92 protected GtkFlowBox* gtkFlowBox; 93 94 /** Get the main Gtk struct */ 95 public GtkFlowBox* getFlowBoxStruct(bool transferOwnership = false) 96 { 97 if (transferOwnership) 98 ownedRef = false; 99 return gtkFlowBox; 100 } 101 102 /** the main Gtk struct as a void* */ 103 protected override void* getStruct() 104 { 105 return cast(void*)gtkFlowBox; 106 } 107 108 protected override void setStruct(GObject* obj) 109 { 110 gtkFlowBox = cast(GtkFlowBox*)obj; 111 super.setStruct(obj); 112 } 113 114 /** 115 * Sets our main struct and passes it to the parent class. 116 */ 117 public this (GtkFlowBox* gtkFlowBox, bool ownedRef = false) 118 { 119 this.gtkFlowBox = gtkFlowBox; 120 super(cast(GtkContainer*)gtkFlowBox, ownedRef); 121 } 122 123 // add the Orientable capabilities 124 mixin OrientableT!(GtkFlowBox); 125 126 127 /** */ 128 public static GType getType() 129 { 130 return gtk_flow_box_get_type(); 131 } 132 133 /** 134 * Creates a GtkFlowBox. 135 * 136 * Returns: a new #GtkFlowBox container 137 * 138 * Since: 3.12 139 * 140 * Throws: ConstructionException GTK+ fails to create the object. 141 */ 142 public this() 143 { 144 auto p = gtk_flow_box_new(); 145 146 if(p is null) 147 { 148 throw new ConstructionException("null returned by new"); 149 } 150 151 this(cast(GtkFlowBox*) p); 152 } 153 154 /** 155 * Binds @model to @box. 156 * 157 * If @box was already bound to a model, that previous binding is 158 * destroyed. 159 * 160 * The contents of @box are cleared and then filled with widgets that 161 * represent items from @model. @box is updated whenever @model changes. 162 * If @model is %NULL, @box is left empty. 163 * 164 * It is undefined to add or remove widgets directly (for example, with 165 * gtk_flow_box_insert() or gtk_container_add()) while @box is bound to a 166 * model. 167 * 168 * Note that using a model is incompatible with the filtering and sorting 169 * functionality in GtkFlowBox. When using a model, filtering and sorting 170 * should be implemented by the model. 171 * 172 * Params: 173 * model = the #GListModel to be bound to @box 174 * createWidgetFunc = a function that creates widgets for items 175 * userData = user data passed to @create_widget_func 176 * userDataFreeFunc = function for freeing @user_data 177 * 178 * Since: 3.18 179 */ 180 public void bindModel(ListModelIF model, GtkFlowBoxCreateWidgetFunc createWidgetFunc, void* userData, GDestroyNotify userDataFreeFunc) 181 { 182 gtk_flow_box_bind_model(gtkFlowBox, (model is null) ? null : model.getListModelStruct(), createWidgetFunc, userData, userDataFreeFunc); 183 } 184 185 /** 186 * Returns whether children activate on single clicks. 187 * 188 * Returns: %TRUE if children are activated on single click, 189 * %FALSE otherwise 190 * 191 * Since: 3.12 192 */ 193 public bool getActivateOnSingleClick() 194 { 195 return gtk_flow_box_get_activate_on_single_click(gtkFlowBox) != 0; 196 } 197 198 /** 199 * Gets the nth child in the @box. 200 * 201 * Params: 202 * idx = the position of the child 203 * 204 * Returns: the child widget, which will 205 * always be a #GtkFlowBoxChild or %NULL in case no child widget 206 * with the given index exists. 207 * 208 * Since: 3.12 209 */ 210 public FlowBoxChild getChildAtIndex(int idx) 211 { 212 auto p = gtk_flow_box_get_child_at_index(gtkFlowBox, idx); 213 214 if(p is null) 215 { 216 return null; 217 } 218 219 return ObjectG.getDObject!(FlowBoxChild)(cast(GtkFlowBoxChild*) p); 220 } 221 222 /** 223 * Gets the child in the (@x, @y) position. 224 * 225 * Params: 226 * x = the x coordinate of the child 227 * y = the y coordinate of the child 228 * 229 * Returns: the child widget, which will 230 * always be a #GtkFlowBoxChild or %NULL in case no child widget 231 * exists for the given x and y coordinates. 232 * 233 * Since: 3.22.6 234 */ 235 public FlowBoxChild getChildAtPos(int x, int y) 236 { 237 auto p = gtk_flow_box_get_child_at_pos(gtkFlowBox, x, y); 238 239 if(p is null) 240 { 241 return null; 242 } 243 244 return ObjectG.getDObject!(FlowBoxChild)(cast(GtkFlowBoxChild*) p); 245 } 246 247 /** 248 * Gets the horizontal spacing. 249 * 250 * Returns: the horizontal spacing 251 * 252 * Since: 3.12 253 */ 254 public uint getColumnSpacing() 255 { 256 return gtk_flow_box_get_column_spacing(gtkFlowBox); 257 } 258 259 /** 260 * Returns whether the box is homogeneous (all children are the 261 * same size). See gtk_box_set_homogeneous(). 262 * 263 * Returns: %TRUE if the box is homogeneous. 264 * 265 * Since: 3.12 266 */ 267 public bool getHomogeneous() 268 { 269 return gtk_flow_box_get_homogeneous(gtkFlowBox) != 0; 270 } 271 272 /** 273 * Gets the maximum number of children per line. 274 * 275 * Returns: the maximum number of children per line 276 * 277 * Since: 3.12 278 */ 279 public uint getMaxChildrenPerLine() 280 { 281 return gtk_flow_box_get_max_children_per_line(gtkFlowBox); 282 } 283 284 /** 285 * Gets the minimum number of children per line. 286 * 287 * Returns: the minimum number of children per line 288 * 289 * Since: 3.12 290 */ 291 public uint getMinChildrenPerLine() 292 { 293 return gtk_flow_box_get_min_children_per_line(gtkFlowBox); 294 } 295 296 /** 297 * Gets the vertical spacing. 298 * 299 * Returns: the vertical spacing 300 * 301 * Since: 3.12 302 */ 303 public uint getRowSpacing() 304 { 305 return gtk_flow_box_get_row_spacing(gtkFlowBox); 306 } 307 308 /** 309 * Creates a list of all selected children. 310 * 311 * Returns: A #GList containing the #GtkWidget for each selected child. 312 * Free with g_list_free() when done. 313 * 314 * Since: 3.12 315 */ 316 public ListG getSelectedChildren() 317 { 318 auto p = gtk_flow_box_get_selected_children(gtkFlowBox); 319 320 if(p is null) 321 { 322 return null; 323 } 324 325 return new ListG(cast(GList*) p); 326 } 327 328 /** 329 * Gets the selection mode of @box. 330 * 331 * Returns: the #GtkSelectionMode 332 * 333 * Since: 3.12 334 */ 335 public GtkSelectionMode getSelectionMode() 336 { 337 return gtk_flow_box_get_selection_mode(gtkFlowBox); 338 } 339 340 /** 341 * Inserts the @widget into @box at @position. 342 * 343 * If a sort function is set, the widget will actually be inserted 344 * at the calculated position and this function has the same effect 345 * as gtk_container_add(). 346 * 347 * If @position is -1, or larger than the total number of children 348 * in the @box, then the @widget will be appended to the end. 349 * 350 * Params: 351 * widget = the #GtkWidget to add 352 * position = the position to insert @child in 353 * 354 * Since: 3.12 355 */ 356 public void insert(Widget widget, int position) 357 { 358 gtk_flow_box_insert(gtkFlowBox, (widget is null) ? null : widget.getWidgetStruct(), position); 359 } 360 361 /** 362 * Updates the filtering for all children. 363 * 364 * Call this function when the result of the filter 365 * function on the @box is changed due ot an external 366 * factor. For instance, this would be used if the 367 * filter function just looked for a specific search 368 * term, and the entry with the string has changed. 369 * 370 * Since: 3.12 371 */ 372 public void invalidateFilter() 373 { 374 gtk_flow_box_invalidate_filter(gtkFlowBox); 375 } 376 377 /** 378 * Updates the sorting for all children. 379 * 380 * Call this when the result of the sort function on 381 * @box is changed due to an external factor. 382 * 383 * Since: 3.12 384 */ 385 public void invalidateSort() 386 { 387 gtk_flow_box_invalidate_sort(gtkFlowBox); 388 } 389 390 /** 391 * Select all children of @box, if the selection 392 * mode allows it. 393 * 394 * Since: 3.12 395 */ 396 public void selectAll() 397 { 398 gtk_flow_box_select_all(gtkFlowBox); 399 } 400 401 /** 402 * Selects a single child of @box, if the selection 403 * mode allows it. 404 * 405 * Params: 406 * child = a child of @box 407 * 408 * Since: 3.12 409 */ 410 public void selectChild(FlowBoxChild child) 411 { 412 gtk_flow_box_select_child(gtkFlowBox, (child is null) ? null : child.getFlowBoxChildStruct()); 413 } 414 415 /** 416 * Calls a function for each selected child. 417 * 418 * Note that the selection cannot be modified from within 419 * this function. 420 * 421 * Params: 422 * func = the function to call for each selected child 423 * data = user data to pass to the function 424 * 425 * Since: 3.12 426 */ 427 public void selectedForeach(GtkFlowBoxForeachFunc func, void* data) 428 { 429 gtk_flow_box_selected_foreach(gtkFlowBox, func, data); 430 } 431 432 /** 433 * If @single is %TRUE, children will be activated when you click 434 * on them, otherwise you need to double-click. 435 * 436 * Params: 437 * single = %TRUE to emit child-activated on a single click 438 * 439 * Since: 3.12 440 */ 441 public void setActivateOnSingleClick(bool single) 442 { 443 gtk_flow_box_set_activate_on_single_click(gtkFlowBox, single); 444 } 445 446 /** 447 * Sets the horizontal space to add between children. 448 * See the #GtkFlowBox:column-spacing property. 449 * 450 * Params: 451 * spacing = the spacing to use 452 * 453 * Since: 3.12 454 */ 455 public void setColumnSpacing(uint spacing) 456 { 457 gtk_flow_box_set_column_spacing(gtkFlowBox, spacing); 458 } 459 460 /** 461 * By setting a filter function on the @box one can decide dynamically 462 * which of the children to show. For instance, to implement a search 463 * function that only shows the children matching the search terms. 464 * 465 * The @filter_func will be called for each child after the call, and 466 * it will continue to be called each time a child changes (via 467 * gtk_flow_box_child_changed()) or when gtk_flow_box_invalidate_filter() 468 * is called. 469 * 470 * Note that using a filter function is incompatible with using a model 471 * (see gtk_flow_box_bind_model()). 472 * 473 * Params: 474 * filterFunc = callback that 475 * lets you filter which children to show 476 * userData = user data passed to @filter_func 477 * destroy = destroy notifier for @user_data 478 * 479 * Since: 3.12 480 */ 481 public void setFilterFunc(GtkFlowBoxFilterFunc filterFunc, void* userData, GDestroyNotify destroy) 482 { 483 gtk_flow_box_set_filter_func(gtkFlowBox, filterFunc, userData, destroy); 484 } 485 486 /** 487 * Hooks up an adjustment to focus handling in @box. 488 * The adjustment is also used for autoscrolling during 489 * rubberband selection. See gtk_scrolled_window_get_hadjustment() 490 * for a typical way of obtaining the adjustment, and 491 * gtk_flow_box_set_vadjustment()for setting the vertical 492 * adjustment. 493 * 494 * The adjustments have to be in pixel units and in the same 495 * coordinate system as the allocation for immediate children 496 * of the box. 497 * 498 * Params: 499 * adjustment = an adjustment which should be adjusted 500 * when the focus is moved among the descendents of @container 501 * 502 * Since: 3.12 503 */ 504 public void setHadjustment(Adjustment adjustment) 505 { 506 gtk_flow_box_set_hadjustment(gtkFlowBox, (adjustment is null) ? null : adjustment.getAdjustmentStruct()); 507 } 508 509 /** 510 * Sets the #GtkFlowBox:homogeneous property of @box, controlling 511 * whether or not all children of @box are given equal space 512 * in the box. 513 * 514 * Params: 515 * homogeneous = %TRUE to create equal allotments, 516 * %FALSE for variable allotments 517 * 518 * Since: 3.12 519 */ 520 public void setHomogeneous(bool homogeneous) 521 { 522 gtk_flow_box_set_homogeneous(gtkFlowBox, homogeneous); 523 } 524 525 /** 526 * Sets the maximum number of children to request and 527 * allocate space for in @box’s orientation. 528 * 529 * Setting the maximum number of children per line 530 * limits the overall natural size request to be no more 531 * than @n_children children long in the given orientation. 532 * 533 * Params: 534 * nChildren = the maximum number of children per line 535 * 536 * Since: 3.12 537 */ 538 public void setMaxChildrenPerLine(uint nChildren) 539 { 540 gtk_flow_box_set_max_children_per_line(gtkFlowBox, nChildren); 541 } 542 543 /** 544 * Sets the minimum number of children to line up 545 * in @box’s orientation before flowing. 546 * 547 * Params: 548 * nChildren = the minimum number of children per line 549 * 550 * Since: 3.12 551 */ 552 public void setMinChildrenPerLine(uint nChildren) 553 { 554 gtk_flow_box_set_min_children_per_line(gtkFlowBox, nChildren); 555 } 556 557 /** 558 * Sets the vertical space to add between children. 559 * See the #GtkFlowBox:row-spacing property. 560 * 561 * Params: 562 * spacing = the spacing to use 563 * 564 * Since: 3.12 565 */ 566 public void setRowSpacing(uint spacing) 567 { 568 gtk_flow_box_set_row_spacing(gtkFlowBox, spacing); 569 } 570 571 /** 572 * Sets how selection works in @box. 573 * See #GtkSelectionMode for details. 574 * 575 * Params: 576 * mode = the new selection mode 577 * 578 * Since: 3.12 579 */ 580 public void setSelectionMode(GtkSelectionMode mode) 581 { 582 gtk_flow_box_set_selection_mode(gtkFlowBox, mode); 583 } 584 585 /** 586 * By setting a sort function on the @box, one can dynamically 587 * reorder the children of the box, based on the contents of 588 * the children. 589 * 590 * The @sort_func will be called for each child after the call, 591 * and will continue to be called each time a child changes (via 592 * gtk_flow_box_child_changed()) and when gtk_flow_box_invalidate_sort() 593 * is called. 594 * 595 * Note that using a sort function is incompatible with using a model 596 * (see gtk_flow_box_bind_model()). 597 * 598 * Params: 599 * sortFunc = the sort function 600 * userData = user data passed to @sort_func 601 * destroy = destroy notifier for @user_data 602 * 603 * Since: 3.12 604 */ 605 public void setSortFunc(GtkFlowBoxSortFunc sortFunc, void* userData, GDestroyNotify destroy) 606 { 607 gtk_flow_box_set_sort_func(gtkFlowBox, sortFunc, userData, destroy); 608 } 609 610 /** 611 * Hooks up an adjustment to focus handling in @box. 612 * The adjustment is also used for autoscrolling during 613 * rubberband selection. See gtk_scrolled_window_get_vadjustment() 614 * for a typical way of obtaining the adjustment, and 615 * gtk_flow_box_set_hadjustment()for setting the horizontal 616 * adjustment. 617 * 618 * The adjustments have to be in pixel units and in the same 619 * coordinate system as the allocation for immediate children 620 * of the box. 621 * 622 * Params: 623 * adjustment = an adjustment which should be adjusted 624 * when the focus is moved among the descendents of @container 625 * 626 * Since: 3.12 627 */ 628 public void setVadjustment(Adjustment adjustment) 629 { 630 gtk_flow_box_set_vadjustment(gtkFlowBox, (adjustment is null) ? null : adjustment.getAdjustmentStruct()); 631 } 632 633 /** 634 * Unselect all children of @box, if the selection 635 * mode allows it. 636 * 637 * Since: 3.12 638 */ 639 public void unselectAll() 640 { 641 gtk_flow_box_unselect_all(gtkFlowBox); 642 } 643 644 /** 645 * Unselects a single child of @box, if the selection 646 * mode allows it. 647 * 648 * Params: 649 * child = a child of @box 650 * 651 * Since: 3.12 652 */ 653 public void unselectChild(FlowBoxChild child) 654 { 655 gtk_flow_box_unselect_child(gtkFlowBox, (child is null) ? null : child.getFlowBoxChildStruct()); 656 } 657 658 protected class OnActivateCursorChildDelegateWrapper 659 { 660 void delegate(FlowBox) dlg; 661 gulong handlerId; 662 663 this(void delegate(FlowBox) dlg) 664 { 665 this.dlg = dlg; 666 onActivateCursorChildListeners ~= this; 667 } 668 669 void remove(OnActivateCursorChildDelegateWrapper source) 670 { 671 foreach(index, wrapper; onActivateCursorChildListeners) 672 { 673 if (wrapper.handlerId == source.handlerId) 674 { 675 onActivateCursorChildListeners[index] = null; 676 onActivateCursorChildListeners = std.algorithm.remove(onActivateCursorChildListeners, index); 677 break; 678 } 679 } 680 } 681 } 682 OnActivateCursorChildDelegateWrapper[] onActivateCursorChildListeners; 683 684 /** 685 * The ::activate-cursor-child signal is a 686 * [keybinding signal][GtkBindingSignal] 687 * which gets emitted when the user activates the @box. 688 */ 689 gulong addOnActivateCursorChild(void delegate(FlowBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 690 { 691 auto wrapper = new OnActivateCursorChildDelegateWrapper(dlg); 692 wrapper.handlerId = Signals.connectData( 693 this, 694 "activate-cursor-child", 695 cast(GCallback)&callBackActivateCursorChild, 696 cast(void*)wrapper, 697 cast(GClosureNotify)&callBackActivateCursorChildDestroy, 698 connectFlags); 699 return wrapper.handlerId; 700 } 701 702 extern(C) static void callBackActivateCursorChild(GtkFlowBox* flowboxStruct, OnActivateCursorChildDelegateWrapper wrapper) 703 { 704 wrapper.dlg(wrapper.outer); 705 } 706 707 extern(C) static void callBackActivateCursorChildDestroy(OnActivateCursorChildDelegateWrapper wrapper, GClosure* closure) 708 { 709 wrapper.remove(wrapper); 710 } 711 712 protected class OnChildActivatedDelegateWrapper 713 { 714 void delegate(FlowBoxChild, FlowBox) dlg; 715 gulong handlerId; 716 717 this(void delegate(FlowBoxChild, FlowBox) dlg) 718 { 719 this.dlg = dlg; 720 onChildActivatedListeners ~= this; 721 } 722 723 void remove(OnChildActivatedDelegateWrapper source) 724 { 725 foreach(index, wrapper; onChildActivatedListeners) 726 { 727 if (wrapper.handlerId == source.handlerId) 728 { 729 onChildActivatedListeners[index] = null; 730 onChildActivatedListeners = std.algorithm.remove(onChildActivatedListeners, index); 731 break; 732 } 733 } 734 } 735 } 736 OnChildActivatedDelegateWrapper[] onChildActivatedListeners; 737 738 /** 739 * The ::child-activated signal is emitted when a child has been 740 * activated by the user. 741 * 742 * Params: 743 * child = the child that is activated 744 */ 745 gulong addOnChildActivated(void delegate(FlowBoxChild, FlowBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 746 { 747 auto wrapper = new OnChildActivatedDelegateWrapper(dlg); 748 wrapper.handlerId = Signals.connectData( 749 this, 750 "child-activated", 751 cast(GCallback)&callBackChildActivated, 752 cast(void*)wrapper, 753 cast(GClosureNotify)&callBackChildActivatedDestroy, 754 connectFlags); 755 return wrapper.handlerId; 756 } 757 758 extern(C) static void callBackChildActivated(GtkFlowBox* flowboxStruct, GtkFlowBoxChild* child, OnChildActivatedDelegateWrapper wrapper) 759 { 760 wrapper.dlg(ObjectG.getDObject!(FlowBoxChild)(child), wrapper.outer); 761 } 762 763 extern(C) static void callBackChildActivatedDestroy(OnChildActivatedDelegateWrapper wrapper, GClosure* closure) 764 { 765 wrapper.remove(wrapper); 766 } 767 768 protected class OnMoveCursorDelegateWrapper 769 { 770 bool delegate(GtkMovementStep, int, FlowBox) dlg; 771 gulong handlerId; 772 773 this(bool delegate(GtkMovementStep, int, FlowBox) dlg) 774 { 775 this.dlg = dlg; 776 onMoveCursorListeners ~= this; 777 } 778 779 void remove(OnMoveCursorDelegateWrapper source) 780 { 781 foreach(index, wrapper; onMoveCursorListeners) 782 { 783 if (wrapper.handlerId == source.handlerId) 784 { 785 onMoveCursorListeners[index] = null; 786 onMoveCursorListeners = std.algorithm.remove(onMoveCursorListeners, index); 787 break; 788 } 789 } 790 } 791 } 792 OnMoveCursorDelegateWrapper[] onMoveCursorListeners; 793 794 /** 795 * The ::move-cursor signal is a 796 * [keybinding signal][GtkBindingSignal] 797 * which gets emitted when the user initiates a cursor movement. 798 * 799 * Applications should not connect to it, but may emit it with 800 * g_signal_emit_by_name() if they need to control the cursor 801 * programmatically. 802 * 803 * The default bindings for this signal come in two variants, 804 * the variant with the Shift modifier extends the selection, 805 * the variant without the Shift modifer does not. 806 * There are too many key combinations to list them all here. 807 * - Arrow keys move by individual children 808 * - Home/End keys move to the ends of the box 809 * - PageUp/PageDown keys move vertically by pages 810 * 811 * Params: 812 * step = the granularity fo the move, as a #GtkMovementStep 813 * count = the number of @step units to move 814 * 815 * Returns: %TRUE to stop other handlers from being invoked for the event. 816 * %FALSE to propagate the event further. 817 */ 818 gulong addOnMoveCursor(bool delegate(GtkMovementStep, int, FlowBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 819 { 820 auto wrapper = new OnMoveCursorDelegateWrapper(dlg); 821 wrapper.handlerId = Signals.connectData( 822 this, 823 "move-cursor", 824 cast(GCallback)&callBackMoveCursor, 825 cast(void*)wrapper, 826 cast(GClosureNotify)&callBackMoveCursorDestroy, 827 connectFlags); 828 return wrapper.handlerId; 829 } 830 831 extern(C) static int callBackMoveCursor(GtkFlowBox* flowboxStruct, GtkMovementStep step, int count, OnMoveCursorDelegateWrapper wrapper) 832 { 833 return wrapper.dlg(step, count, wrapper.outer); 834 } 835 836 extern(C) static void callBackMoveCursorDestroy(OnMoveCursorDelegateWrapper wrapper, GClosure* closure) 837 { 838 wrapper.remove(wrapper); 839 } 840 841 protected class OnSelectAllDelegateWrapper 842 { 843 void delegate(FlowBox) dlg; 844 gulong handlerId; 845 846 this(void delegate(FlowBox) dlg) 847 { 848 this.dlg = dlg; 849 onSelectAllListeners ~= this; 850 } 851 852 void remove(OnSelectAllDelegateWrapper source) 853 { 854 foreach(index, wrapper; onSelectAllListeners) 855 { 856 if (wrapper.handlerId == source.handlerId) 857 { 858 onSelectAllListeners[index] = null; 859 onSelectAllListeners = std.algorithm.remove(onSelectAllListeners, index); 860 break; 861 } 862 } 863 } 864 } 865 OnSelectAllDelegateWrapper[] onSelectAllListeners; 866 867 /** 868 * The ::select-all signal is a 869 * [keybinding signal][GtkBindingSignal] 870 * which gets emitted to select all children of the box, if 871 * the selection mode permits it. 872 * 873 * The default bindings for this signal is Ctrl-a. 874 */ 875 gulong addOnSelectAll(void delegate(FlowBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 876 { 877 auto wrapper = new OnSelectAllDelegateWrapper(dlg); 878 wrapper.handlerId = Signals.connectData( 879 this, 880 "select-all", 881 cast(GCallback)&callBackSelectAll, 882 cast(void*)wrapper, 883 cast(GClosureNotify)&callBackSelectAllDestroy, 884 connectFlags); 885 return wrapper.handlerId; 886 } 887 888 extern(C) static void callBackSelectAll(GtkFlowBox* flowboxStruct, OnSelectAllDelegateWrapper wrapper) 889 { 890 wrapper.dlg(wrapper.outer); 891 } 892 893 extern(C) static void callBackSelectAllDestroy(OnSelectAllDelegateWrapper wrapper, GClosure* closure) 894 { 895 wrapper.remove(wrapper); 896 } 897 898 protected class OnSelectedChildrenChangedDelegateWrapper 899 { 900 void delegate(FlowBox) dlg; 901 gulong handlerId; 902 903 this(void delegate(FlowBox) dlg) 904 { 905 this.dlg = dlg; 906 onSelectedChildrenChangedListeners ~= this; 907 } 908 909 void remove(OnSelectedChildrenChangedDelegateWrapper source) 910 { 911 foreach(index, wrapper; onSelectedChildrenChangedListeners) 912 { 913 if (wrapper.handlerId == source.handlerId) 914 { 915 onSelectedChildrenChangedListeners[index] = null; 916 onSelectedChildrenChangedListeners = std.algorithm.remove(onSelectedChildrenChangedListeners, index); 917 break; 918 } 919 } 920 } 921 } 922 OnSelectedChildrenChangedDelegateWrapper[] onSelectedChildrenChangedListeners; 923 924 /** 925 * The ::selected-children-changed signal is emitted when the 926 * set of selected children changes. 927 * 928 * Use gtk_flow_box_selected_foreach() or 929 * gtk_flow_box_get_selected_children() to obtain the 930 * selected children. 931 */ 932 gulong addOnSelectedChildrenChanged(void delegate(FlowBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 933 { 934 auto wrapper = new OnSelectedChildrenChangedDelegateWrapper(dlg); 935 wrapper.handlerId = Signals.connectData( 936 this, 937 "selected-children-changed", 938 cast(GCallback)&callBackSelectedChildrenChanged, 939 cast(void*)wrapper, 940 cast(GClosureNotify)&callBackSelectedChildrenChangedDestroy, 941 connectFlags); 942 return wrapper.handlerId; 943 } 944 945 extern(C) static void callBackSelectedChildrenChanged(GtkFlowBox* flowboxStruct, OnSelectedChildrenChangedDelegateWrapper wrapper) 946 { 947 wrapper.dlg(wrapper.outer); 948 } 949 950 extern(C) static void callBackSelectedChildrenChangedDestroy(OnSelectedChildrenChangedDelegateWrapper wrapper, GClosure* closure) 951 { 952 wrapper.remove(wrapper); 953 } 954 955 protected class OnToggleCursorChildDelegateWrapper 956 { 957 void delegate(FlowBox) dlg; 958 gulong handlerId; 959 960 this(void delegate(FlowBox) dlg) 961 { 962 this.dlg = dlg; 963 onToggleCursorChildListeners ~= this; 964 } 965 966 void remove(OnToggleCursorChildDelegateWrapper source) 967 { 968 foreach(index, wrapper; onToggleCursorChildListeners) 969 { 970 if (wrapper.handlerId == source.handlerId) 971 { 972 onToggleCursorChildListeners[index] = null; 973 onToggleCursorChildListeners = std.algorithm.remove(onToggleCursorChildListeners, index); 974 break; 975 } 976 } 977 } 978 } 979 OnToggleCursorChildDelegateWrapper[] onToggleCursorChildListeners; 980 981 /** 982 * The ::toggle-cursor-child signal is a 983 * [keybinding signal][GtkBindingSignal] 984 * which toggles the selection of the child that has the focus. 985 * 986 * The default binding for this signal is Ctrl-Space. 987 */ 988 gulong addOnToggleCursorChild(void delegate(FlowBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 989 { 990 auto wrapper = new OnToggleCursorChildDelegateWrapper(dlg); 991 wrapper.handlerId = Signals.connectData( 992 this, 993 "toggle-cursor-child", 994 cast(GCallback)&callBackToggleCursorChild, 995 cast(void*)wrapper, 996 cast(GClosureNotify)&callBackToggleCursorChildDestroy, 997 connectFlags); 998 return wrapper.handlerId; 999 } 1000 1001 extern(C) static void callBackToggleCursorChild(GtkFlowBox* flowboxStruct, OnToggleCursorChildDelegateWrapper wrapper) 1002 { 1003 wrapper.dlg(wrapper.outer); 1004 } 1005 1006 extern(C) static void callBackToggleCursorChildDestroy(OnToggleCursorChildDelegateWrapper wrapper, GClosure* closure) 1007 { 1008 wrapper.remove(wrapper); 1009 } 1010 1011 protected class OnUnselectAllDelegateWrapper 1012 { 1013 void delegate(FlowBox) dlg; 1014 gulong handlerId; 1015 1016 this(void delegate(FlowBox) dlg) 1017 { 1018 this.dlg = dlg; 1019 onUnselectAllListeners ~= this; 1020 } 1021 1022 void remove(OnUnselectAllDelegateWrapper source) 1023 { 1024 foreach(index, wrapper; onUnselectAllListeners) 1025 { 1026 if (wrapper.handlerId == source.handlerId) 1027 { 1028 onUnselectAllListeners[index] = null; 1029 onUnselectAllListeners = std.algorithm.remove(onUnselectAllListeners, index); 1030 break; 1031 } 1032 } 1033 } 1034 } 1035 OnUnselectAllDelegateWrapper[] onUnselectAllListeners; 1036 1037 /** 1038 * The ::unselect-all signal is a 1039 * [keybinding signal][GtkBindingSignal] 1040 * which gets emitted to unselect all children of the box, if 1041 * the selection mode permits it. 1042 * 1043 * The default bindings for this signal is Ctrl-Shift-a. 1044 */ 1045 gulong addOnUnselectAll(void delegate(FlowBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 1046 { 1047 auto wrapper = new OnUnselectAllDelegateWrapper(dlg); 1048 wrapper.handlerId = Signals.connectData( 1049 this, 1050 "unselect-all", 1051 cast(GCallback)&callBackUnselectAll, 1052 cast(void*)wrapper, 1053 cast(GClosureNotify)&callBackUnselectAllDestroy, 1054 connectFlags); 1055 return wrapper.handlerId; 1056 } 1057 1058 extern(C) static void callBackUnselectAll(GtkFlowBox* flowboxStruct, OnUnselectAllDelegateWrapper wrapper) 1059 { 1060 wrapper.dlg(wrapper.outer); 1061 } 1062 1063 extern(C) static void callBackUnselectAllDestroy(OnUnselectAllDelegateWrapper wrapper, GClosure* closure) 1064 { 1065 wrapper.remove(wrapper); 1066 } 1067 }