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.FlowBoxChild; 34 private import gtk.OrientableIF; 35 private import gtk.OrientableT; 36 private import gtk.Widget; 37 private import gtk.c.functions; 38 public import gtk.c.types; 39 private import std.algorithm; 40 41 42 /** 43 * A `GtkFlowBox` puts child widgets in reflowing grid. 44 * 45 * For instance, with the horizontal orientation, the widgets will be 46 * arranged from left to right, starting a new row under the previous 47 * row when necessary. Reducing the width in this case will require more 48 * rows, so a larger height will be requested. 49 * 50 * Likewise, with the vertical orientation, the widgets will be arranged 51 * from top to bottom, starting a new column to the right when necessary. 52 * Reducing the height will require more columns, so a larger width will 53 * be requested. 54 * 55 * The size request of a `GtkFlowBox` alone may not be what you expect; 56 * if you need to be able to shrink it along both axes and dynamically 57 * reflow its children, you may have to wrap it in a `GtkScrolledWindow` 58 * to enable that. 59 * 60 * The children of a `GtkFlowBox` can be dynamically sorted and filtered. 61 * 62 * Although a `GtkFlowBox` must have only `GtkFlowBoxChild` children, you 63 * can add any kind of widget to it via [method@Gtk.FlowBox.insert], and a 64 * `GtkFlowBoxChild` widget will automatically be inserted between the box 65 * and the widget. 66 * 67 * Also see [class@Gtk.ListBox]. 68 * 69 * # CSS nodes 70 * 71 * ``` 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. For rubberband selection, 83 * a subnode with name rubberband is used. 84 * 85 * # Accessibility 86 * 87 * `GtkFlowBox` uses the %GTK_ACCESSIBLE_ROLE_GRID role, and `GtkFlowBoxChild` 88 * uses the %GTK_ACCESSIBLE_ROLE_GRID_CELL role. 89 */ 90 public class FlowBox : Widget, OrientableIF 91 { 92 /** the main Gtk struct */ 93 protected GtkFlowBox* gtkFlowBox; 94 95 /** Get the main Gtk struct */ 96 public GtkFlowBox* getFlowBoxStruct(bool transferOwnership = false) 97 { 98 if (transferOwnership) 99 ownedRef = false; 100 return gtkFlowBox; 101 } 102 103 /** the main Gtk struct as a void* */ 104 protected override void* getStruct() 105 { 106 return cast(void*)gtkFlowBox; 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(GtkWidget*)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` 132 * 133 * Throws: ConstructionException GTK+ fails to create the object. 134 */ 135 public this() 136 { 137 auto __p = gtk_flow_box_new(); 138 139 if(__p is null) 140 { 141 throw new ConstructionException("null returned by new"); 142 } 143 144 this(cast(GtkFlowBox*) __p); 145 } 146 147 /** 148 * Binds @model to @box. 149 * 150 * If @box was already bound to a model, that previous binding is 151 * destroyed. 152 * 153 * The contents of @box are cleared and then filled with widgets that 154 * represent items from @model. @box is updated whenever @model changes. 155 * If @model is %NULL, @box is left empty. 156 * 157 * It is undefined to add or remove widgets directly (for example, with 158 * [method@Gtk.FlowBox.insert]) while @box is bound to a model. 159 * 160 * Note that using a model is incompatible with the filtering and sorting 161 * functionality in `GtkFlowBox`. When using a model, filtering and sorting 162 * should be implemented by the model. 163 * 164 * Params: 165 * model = the `GListModel` to be bound to @box 166 * createWidgetFunc = a function that creates widgets for items 167 * userData = user data passed to @create_widget_func 168 * userDataFreeFunc = function for freeing @user_data 169 */ 170 public void bindModel(ListModelIF model, GtkFlowBoxCreateWidgetFunc createWidgetFunc, void* userData, GDestroyNotify userDataFreeFunc) 171 { 172 gtk_flow_box_bind_model(gtkFlowBox, (model is null) ? null : model.getListModelStruct(), createWidgetFunc, userData, userDataFreeFunc); 173 } 174 175 /** 176 * Returns whether children activate on single clicks. 177 * 178 * Returns: %TRUE if children are activated on single click, 179 * %FALSE otherwise 180 */ 181 public bool getActivateOnSingleClick() 182 { 183 return gtk_flow_box_get_activate_on_single_click(gtkFlowBox) != 0; 184 } 185 186 /** 187 * Gets the nth child in the @box. 188 * 189 * Params: 190 * idx = the position of the child 191 * 192 * Returns: the child widget, which will 193 * always be a `GtkFlowBoxChild` or %NULL in case no child widget 194 * with the given index exists. 195 */ 196 public FlowBoxChild getChildAtIndex(int idx) 197 { 198 auto __p = gtk_flow_box_get_child_at_index(gtkFlowBox, idx); 199 200 if(__p is null) 201 { 202 return null; 203 } 204 205 return ObjectG.getDObject!(FlowBoxChild)(cast(GtkFlowBoxChild*) __p); 206 } 207 208 /** 209 * Gets the child in the (@x, @y) position. 210 * 211 * Both @x and @y are assumed to be relative to the origin of @box. 212 * 213 * Params: 214 * x = the x coordinate of the child 215 * y = the y coordinate of the child 216 * 217 * Returns: the child widget, which will 218 * always be a `GtkFlowBoxChild` or %NULL in case no child widget 219 * exists for the given x and y coordinates. 220 */ 221 public FlowBoxChild getChildAtPos(int x, int y) 222 { 223 auto __p = gtk_flow_box_get_child_at_pos(gtkFlowBox, x, y); 224 225 if(__p is null) 226 { 227 return null; 228 } 229 230 return ObjectG.getDObject!(FlowBoxChild)(cast(GtkFlowBoxChild*) __p); 231 } 232 233 /** 234 * Gets the horizontal spacing. 235 * 236 * Returns: the horizontal spacing 237 */ 238 public uint getColumnSpacing() 239 { 240 return gtk_flow_box_get_column_spacing(gtkFlowBox); 241 } 242 243 /** 244 * Returns whether the box is homogeneous. 245 * 246 * Returns: %TRUE if the box is homogeneous. 247 */ 248 public bool getHomogeneous() 249 { 250 return gtk_flow_box_get_homogeneous(gtkFlowBox) != 0; 251 } 252 253 /** 254 * Gets the maximum number of children per line. 255 * 256 * Returns: the maximum number of children per line 257 */ 258 public uint getMaxChildrenPerLine() 259 { 260 return gtk_flow_box_get_max_children_per_line(gtkFlowBox); 261 } 262 263 /** 264 * Gets the minimum number of children per line. 265 * 266 * Returns: the minimum number of children per line 267 */ 268 public uint getMinChildrenPerLine() 269 { 270 return gtk_flow_box_get_min_children_per_line(gtkFlowBox); 271 } 272 273 /** 274 * Gets the vertical spacing. 275 * 276 * Returns: the vertical spacing 277 */ 278 public uint getRowSpacing() 279 { 280 return gtk_flow_box_get_row_spacing(gtkFlowBox); 281 } 282 283 /** 284 * Creates a list of all selected children. 285 * 286 * Returns: A `GList` containing the `GtkWidget` for each selected child. 287 * Free with g_list_free() when done. 288 */ 289 public ListG getSelectedChildren() 290 { 291 auto __p = gtk_flow_box_get_selected_children(gtkFlowBox); 292 293 if(__p is null) 294 { 295 return null; 296 } 297 298 return new ListG(cast(GList*) __p); 299 } 300 301 /** 302 * Gets the selection mode of @box. 303 * 304 * Returns: the `GtkSelectionMode` 305 */ 306 public GtkSelectionMode getSelectionMode() 307 { 308 return gtk_flow_box_get_selection_mode(gtkFlowBox); 309 } 310 311 /** 312 * Inserts the @widget into @box at @position. 313 * 314 * If a sort function is set, the widget will actually be inserted 315 * at the calculated position. 316 * 317 * If @position is -1, or larger than the total number of children 318 * in the @box, then the @widget will be appended to the end. 319 * 320 * Params: 321 * widget = the `GtkWidget` to add 322 * position = the position to insert @child in 323 */ 324 public void insert(Widget widget, int position) 325 { 326 gtk_flow_box_insert(gtkFlowBox, (widget is null) ? null : widget.getWidgetStruct(), position); 327 } 328 329 /** 330 * Updates the filtering for all children. 331 * 332 * Call this function when the result of the filter 333 * function on the @box is changed due ot an external 334 * factor. For instance, this would be used if the 335 * filter function just looked for a specific search 336 * term, and the entry with the string has changed. 337 */ 338 public void invalidateFilter() 339 { 340 gtk_flow_box_invalidate_filter(gtkFlowBox); 341 } 342 343 /** 344 * Updates the sorting for all children. 345 * 346 * Call this when the result of the sort function on 347 * @box is changed due to an external factor. 348 */ 349 public void invalidateSort() 350 { 351 gtk_flow_box_invalidate_sort(gtkFlowBox); 352 } 353 354 /** 355 * Removes a child from @box. 356 * 357 * Params: 358 * widget = the child widget to remove 359 */ 360 public void remove(Widget widget) 361 { 362 gtk_flow_box_remove(gtkFlowBox, (widget is null) ? null : widget.getWidgetStruct()); 363 } 364 365 /** 366 * Select all children of @box, if the selection 367 * mode allows it. 368 */ 369 public void selectAll() 370 { 371 gtk_flow_box_select_all(gtkFlowBox); 372 } 373 374 /** 375 * Selects a single child of @box, if the selection 376 * mode allows it. 377 * 378 * Params: 379 * child = a child of @box 380 */ 381 public void selectChild(FlowBoxChild child) 382 { 383 gtk_flow_box_select_child(gtkFlowBox, (child is null) ? null : child.getFlowBoxChildStruct()); 384 } 385 386 /** 387 * Calls a function for each selected child. 388 * 389 * Note that the selection cannot be modified from within 390 * this function. 391 * 392 * Params: 393 * func = the function to call for each selected child 394 * data = user data to pass to the function 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 public void setActivateOnSingleClick(bool single) 409 { 410 gtk_flow_box_set_activate_on_single_click(gtkFlowBox, single); 411 } 412 413 /** 414 * Sets the horizontal space to add between children. 415 * 416 * Params: 417 * spacing = the spacing to use 418 */ 419 public void setColumnSpacing(uint spacing) 420 { 421 gtk_flow_box_set_column_spacing(gtkFlowBox, spacing); 422 } 423 424 /** 425 * By setting a filter function on the @box one can decide dynamically 426 * which of the children to show. 427 * 428 * For instance, to implement a search function that only shows the 429 * children matching the search terms. 430 * 431 * The @filter_func will be called for each child after the call, and 432 * it will continue to be called each time a child changes (via 433 * [method@Gtk.FlowBoxChild.changed]) or when 434 * [method@Gtk.FlowBox.invalidate_filter] is called. 435 * 436 * Note that using a filter function is incompatible with using a model 437 * (see [method@Gtk.FlowBox.bind_model]). 438 * 439 * Params: 440 * filterFunc = callback that 441 * lets you filter which children to show 442 * userData = user data passed to @filter_func 443 * destroy = destroy notifier for @user_data 444 */ 445 public void setFilterFunc(GtkFlowBoxFilterFunc filterFunc, void* userData, GDestroyNotify destroy) 446 { 447 gtk_flow_box_set_filter_func(gtkFlowBox, filterFunc, userData, destroy); 448 } 449 450 /** 451 * Hooks up an adjustment to focus handling in @box. 452 * 453 * The adjustment is also used for autoscrolling during 454 * rubberband selection. See [method@Gtk.ScrolledWindow.get_hadjustment] 455 * for a typical way of obtaining the adjustment, and 456 * [method@Gtk.FlowBox.set_vadjustment] for setting the vertical 457 * adjustment. 458 * 459 * The adjustments have to be in pixel units and in the same 460 * coordinate system as the allocation for immediate children 461 * of the box. 462 * 463 * Params: 464 * adjustment = an adjustment which should be adjusted 465 * when the focus is moved among the descendents of @container 466 */ 467 public void setHadjustment(Adjustment adjustment) 468 { 469 gtk_flow_box_set_hadjustment(gtkFlowBox, (adjustment is null) ? null : adjustment.getAdjustmentStruct()); 470 } 471 472 /** 473 * Sets whether or not all children of @box are given 474 * equal space in the box. 475 * 476 * Params: 477 * homogeneous = %TRUE to create equal allotments, 478 * %FALSE for variable allotments 479 */ 480 public void setHomogeneous(bool homogeneous) 481 { 482 gtk_flow_box_set_homogeneous(gtkFlowBox, homogeneous); 483 } 484 485 /** 486 * Sets the maximum number of children to request and 487 * allocate space for in @box’s orientation. 488 * 489 * Setting the maximum number of children per line 490 * limits the overall natural size request to be no more 491 * than @n_children children long in the given orientation. 492 * 493 * Params: 494 * nChildren = the maximum number of children per line 495 */ 496 public void setMaxChildrenPerLine(uint nChildren) 497 { 498 gtk_flow_box_set_max_children_per_line(gtkFlowBox, nChildren); 499 } 500 501 /** 502 * Sets the minimum number of children to line up 503 * in @box’s orientation before flowing. 504 * 505 * Params: 506 * nChildren = the minimum number of children per line 507 */ 508 public void setMinChildrenPerLine(uint nChildren) 509 { 510 gtk_flow_box_set_min_children_per_line(gtkFlowBox, nChildren); 511 } 512 513 /** 514 * Sets the vertical space to add between children. 515 * 516 * Params: 517 * spacing = the spacing to use 518 */ 519 public void setRowSpacing(uint spacing) 520 { 521 gtk_flow_box_set_row_spacing(gtkFlowBox, spacing); 522 } 523 524 /** 525 * Sets how selection works in @box. 526 * 527 * Params: 528 * mode = the new selection mode 529 */ 530 public void setSelectionMode(GtkSelectionMode mode) 531 { 532 gtk_flow_box_set_selection_mode(gtkFlowBox, mode); 533 } 534 535 /** 536 * By setting a sort function on the @box, one can dynamically 537 * reorder the children of the box, based on the contents of 538 * the children. 539 * 540 * The @sort_func will be called for each child after the call, 541 * and will continue to be called each time a child changes (via 542 * [method@Gtk.FlowBoxChild.changed]) and when 543 * [method@Gtk.FlowBox.invalidate_sort] is called. 544 * 545 * Note that using a sort function is incompatible with using a model 546 * (see [method@Gtk.FlowBox.bind_model]). 547 * 548 * Params: 549 * sortFunc = the sort function 550 * userData = user data passed to @sort_func 551 * destroy = destroy notifier for @user_data 552 */ 553 public void setSortFunc(GtkFlowBoxSortFunc sortFunc, void* userData, GDestroyNotify destroy) 554 { 555 gtk_flow_box_set_sort_func(gtkFlowBox, sortFunc, userData, destroy); 556 } 557 558 /** 559 * Hooks up an adjustment to focus handling in @box. 560 * 561 * The adjustment is also used for autoscrolling during 562 * rubberband selection. See [method@Gtk.ScrolledWindow.get_vadjustment] 563 * for a typical way of obtaining the adjustment, and 564 * [method@Gtk.FlowBox.set_hadjustment] for setting the horizontal 565 * adjustment. 566 * 567 * The adjustments have to be in pixel units and in the same 568 * coordinate system as the allocation for immediate children 569 * of the box. 570 * 571 * Params: 572 * adjustment = an adjustment which should be adjusted 573 * when the focus is moved among the descendents of @container 574 */ 575 public void setVadjustment(Adjustment adjustment) 576 { 577 gtk_flow_box_set_vadjustment(gtkFlowBox, (adjustment is null) ? null : adjustment.getAdjustmentStruct()); 578 } 579 580 /** 581 * Unselect all children of @box, if the selection 582 * mode allows it. 583 */ 584 public void unselectAll() 585 { 586 gtk_flow_box_unselect_all(gtkFlowBox); 587 } 588 589 /** 590 * Unselects a single child of @box, if the selection 591 * mode allows it. 592 * 593 * Params: 594 * child = a child of @box 595 */ 596 public void unselectChild(FlowBoxChild child) 597 { 598 gtk_flow_box_unselect_child(gtkFlowBox, (child is null) ? null : child.getFlowBoxChildStruct()); 599 } 600 601 /** 602 * Emitted when the user activates the @box. 603 * 604 * This is a [keybinding signal](class.SignalAction.html). 605 */ 606 gulong addOnActivateCursorChild(void delegate(FlowBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 607 { 608 return Signals.connect(this, "activate-cursor-child", dlg, connectFlags ^ ConnectFlags.SWAPPED); 609 } 610 611 /** 612 * Emitted when a child has been activated by the user. 613 * 614 * Params: 615 * child = the child that is activated 616 */ 617 gulong addOnChildActivated(void delegate(FlowBoxChild, FlowBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 618 { 619 return Signals.connect(this, "child-activated", dlg, connectFlags ^ ConnectFlags.SWAPPED); 620 } 621 622 /** 623 * Emitted when the user initiates a cursor movement. 624 * 625 * This is a [keybinding signal](class.SignalAction.html). 626 * Applications should not connect to it, but may emit it with 627 * g_signal_emit_by_name() if they need to control the cursor 628 * programmatically. 629 * 630 * The default bindings for this signal come in two variants, 631 * the variant with the Shift modifier extends the selection, 632 * the variant without the Shift modifier does not. 633 * There are too many key combinations to list them all here. 634 * 635 * - <kbd>←</kbd>, <kbd>→</kbd>, <kbd>↑</kbd>, <kbd>↓</kbd> 636 * move by individual children 637 * - <kbd>Home</kbd>, <kbd>End</kbd> move to the ends of the box 638 * - <kbd>PgUp</kbd>, <kbd>PgDn</kbd> move vertically by pages 639 * 640 * Params: 641 * step = the granularity fo the move, as a #GtkMovementStep 642 * count = the number of @step units to move 643 * extend = whether to extend the selection 644 * modify = whether to modify the selection 645 * 646 * Returns: %TRUE to stop other handlers from being invoked for the event. 647 * %FALSE to propagate the event further. 648 */ 649 gulong addOnMoveCursor(bool delegate(GtkMovementStep, int, bool, bool, FlowBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 650 { 651 return Signals.connect(this, "move-cursor", dlg, connectFlags ^ ConnectFlags.SWAPPED); 652 } 653 654 /** 655 * Emitted to select all children of the box, 656 * if the selection mode permits it. 657 * 658 * This is a [keybinding signal](class.SignalAction.html). 659 * 660 * The default bindings for this signal is <kbd>Ctrl</kbd>-<kbd>a</kbd>. 661 */ 662 gulong addOnSelectAll(void delegate(FlowBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 663 { 664 return Signals.connect(this, "select-all", dlg, connectFlags ^ ConnectFlags.SWAPPED); 665 } 666 667 /** 668 * Emitted when the set of selected children changes. 669 * 670 * Use [method@Gtk.FlowBox.selected_foreach] or 671 * [method@Gtk.FlowBox.get_selected_children] to obtain the 672 * selected children. 673 */ 674 gulong addOnSelectedChildrenChanged(void delegate(FlowBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 675 { 676 return Signals.connect(this, "selected-children-changed", dlg, connectFlags ^ ConnectFlags.SWAPPED); 677 } 678 679 /** 680 * Emitted to toggle the selection of the child that has the focus. 681 * 682 * This is a [keybinding signal](class.SignalAction.html). 683 * 684 * The default binding for this signal is <kbd>Ctrl</kbd>-<kbd>Space</kbd>. 685 */ 686 gulong addOnToggleCursorChild(void delegate(FlowBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 687 { 688 return Signals.connect(this, "toggle-cursor-child", dlg, connectFlags ^ ConnectFlags.SWAPPED); 689 } 690 691 /** 692 * Emitted to unselect all children of the box, 693 * if the selection mode permits it. 694 * 695 * This is a [keybinding signal](class.SignalAction.html). 696 * 697 * The default bindings for this signal is <kbd>Ctrl</kbd>-<kbd>Shift</kbd>-<kbd>a</kbd>. 698 */ 699 gulong addOnUnselectAll(void delegate(FlowBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 700 { 701 return Signals.connect(this, "unselect-all", dlg, connectFlags ^ ConnectFlags.SWAPPED); 702 } 703 }