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