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