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.ListBox; 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.ListBoxRow; 34 private import gtk.Widget; 35 private import gtk.c.functions; 36 public import gtk.c.types; 37 private import std.algorithm; 38 39 40 /** 41 * `GtkListBox` is a vertical list. 42 * 43 * A `GtkListBox` only contains `GtkListBoxRow` children. These rows can 44 * by dynamically sorted and filtered, and headers can be added dynamically 45 * depending on the row content. It also allows keyboard and mouse navigation 46 * and selection like a typical list. 47 * 48 * Using `GtkListBox` is often an alternative to `GtkTreeView`, especially 49 * when the list contents has a more complicated layout than what is allowed 50 * by a `GtkCellRenderer`, or when the contents is interactive (i.e. has a 51 * button in it). 52 * 53 * Although a `GtkListBox` must have only `GtkListBoxRow` children, you can 54 * add any kind of widget to it via [method@Gtk.ListBox.prepend], 55 * [method@Gtk.ListBox.append] and [method@Gtk.ListBox.insert] and a 56 * `GtkListBoxRow` widget will automatically be inserted between the list 57 * and the widget. 58 * 59 * `GtkListBoxRows` can be marked as activatable or selectable. If a row is 60 * activatable, [signal@Gtk.ListBox::row-activated] will be emitted for it when 61 * the user tries to activate it. If it is selectable, the row will be marked 62 * as selected when the user tries to select it. 63 * 64 * # GtkListBox as GtkBuildable 65 * 66 * The `GtkListBox` implementation of the `GtkBuildable` interface supports 67 * setting a child as the placeholder by specifying “placeholder” as the “type” 68 * attribute of a <child> element. See [method@Gtk.ListBox.set_placeholder] 69 * for info. 70 * 71 * # CSS nodes 72 * 73 * |[<!-- language="plain" --> 74 * list[.separators][.rich-list][.navigation-sidebar] 75 * ╰── row[.activatable] 76 * ]| 77 * 78 * `GtkListBox` uses a single CSS node named list. It may carry the .separators 79 * style class, when the [property@Gtk.ListBox:show-separators] property is set. 80 * Each `GtkListBoxRow` uses a single CSS node named row. The row nodes get the 81 * .activatable style class added when appropriate. 82 * 83 * The main list node may also carry style classes to select 84 * the style of [list presentation](section-list-widget.html#list-styles): 85 * .rich-list, .navigation-sidebar or .data-table. 86 * 87 * # Accessibility 88 * 89 * `GtkListBox` uses the %GTK_ACCESSIBLE_ROLE_LIST role and `GtkListBoxRow` uses 90 * the %GTK_ACCESSIBLE_ROLE_LIST_ITEM role. 91 */ 92 public class ListBox : Widget 93 { 94 /** the main Gtk struct */ 95 protected GtkListBox* gtkListBox; 96 97 /** Get the main Gtk struct */ 98 public GtkListBox* getListBoxStruct(bool transferOwnership = false) 99 { 100 if (transferOwnership) 101 ownedRef = false; 102 return gtkListBox; 103 } 104 105 /** the main Gtk struct as a void* */ 106 protected override void* getStruct() 107 { 108 return cast(void*)gtkListBox; 109 } 110 111 /** 112 * Sets our main struct and passes it to the parent class. 113 */ 114 public this (GtkListBox* gtkListBox, bool ownedRef = false) 115 { 116 this.gtkListBox = gtkListBox; 117 super(cast(GtkWidget*)gtkListBox, ownedRef); 118 } 119 120 121 /** */ 122 public static GType getType() 123 { 124 return gtk_list_box_get_type(); 125 } 126 127 /** 128 * Creates a new `GtkListBox` container. 129 * 130 * Returns: a new `GtkListBox` 131 * 132 * Throws: ConstructionException GTK+ fails to create the object. 133 */ 134 public this() 135 { 136 auto __p = gtk_list_box_new(); 137 138 if(__p is null) 139 { 140 throw new ConstructionException("null returned by new"); 141 } 142 143 this(cast(GtkListBox*) __p); 144 } 145 146 /** 147 * Append a widget to the list. 148 * 149 * If a sort function is set, the widget will 150 * actually be inserted at the calculated position. 151 * 152 * Params: 153 * child = the `GtkWidget` to add 154 */ 155 public void append(Widget child) 156 { 157 gtk_list_box_append(gtkListBox, (child is null) ? null : child.getWidgetStruct()); 158 } 159 160 /** 161 * Binds @model to @box. 162 * 163 * If @box was already bound to a model, that previous binding is 164 * destroyed. 165 * 166 * The contents of @box are cleared and then filled with widgets that 167 * represent items from @model. @box is updated whenever @model changes. 168 * If @model is %NULL, @box is left empty. 169 * 170 * It is undefined to add or remove widgets directly (for example, with 171 * [method@Gtk.ListBox.insert]) while @box is bound to a model. 172 * 173 * Note that using a model is incompatible with the filtering and sorting 174 * functionality in `GtkListBox`. When using a model, filtering and sorting 175 * should be implemented by the model. 176 * 177 * Params: 178 * model = the `GListModel` to be bound to @box 179 * createWidgetFunc = a function that creates widgets for items 180 * or %NULL in case you also passed %NULL as @model 181 * userData = user data passed to @create_widget_func 182 * userDataFreeFunc = function for freeing @user_data 183 */ 184 public void bindModel(ListModelIF model, GtkListBoxCreateWidgetFunc createWidgetFunc, void* userData, GDestroyNotify userDataFreeFunc) 185 { 186 gtk_list_box_bind_model(gtkListBox, (model is null) ? null : model.getListModelStruct(), createWidgetFunc, userData, userDataFreeFunc); 187 } 188 189 /** 190 * Add a drag highlight to a row. 191 * 192 * This is a helper function for implementing DnD onto a `GtkListBox`. 193 * The passed in @row will be highlighted by setting the 194 * %GTK_STATE_FLAG_DROP_ACTIVE state and any previously highlighted 195 * row will be unhighlighted. 196 * 197 * The row will also be unhighlighted when the widget gets 198 * a drag leave event. 199 * 200 * Params: 201 * row = a `GtkListBoxRow` 202 */ 203 public void dragHighlightRow(ListBoxRow row) 204 { 205 gtk_list_box_drag_highlight_row(gtkListBox, (row is null) ? null : row.getListBoxRowStruct()); 206 } 207 208 /** 209 * If a row has previously been highlighted via gtk_list_box_drag_highlight_row(), 210 * it will have the highlight removed. 211 */ 212 public void dragUnhighlightRow() 213 { 214 gtk_list_box_drag_unhighlight_row(gtkListBox); 215 } 216 217 /** 218 * Returns whether rows activate on single clicks. 219 * 220 * Returns: %TRUE if rows are activated on single click, %FALSE otherwise 221 */ 222 public bool getActivateOnSingleClick() 223 { 224 return gtk_list_box_get_activate_on_single_click(gtkListBox) != 0; 225 } 226 227 /** 228 * Gets the adjustment (if any) that the widget uses to 229 * for vertical scrolling. 230 * 231 * Returns: the adjustment 232 */ 233 public Adjustment getAdjustment() 234 { 235 auto __p = gtk_list_box_get_adjustment(gtkListBox); 236 237 if(__p is null) 238 { 239 return null; 240 } 241 242 return ObjectG.getDObject!(Adjustment)(cast(GtkAdjustment*) __p); 243 } 244 245 /** 246 * Gets the n-th child in the list (not counting headers). 247 * 248 * If @index_ is negative or larger than the number of items in the 249 * list, %NULL is returned. 250 * 251 * Params: 252 * index = the index of the row 253 * 254 * Returns: the child `GtkWidget` or %NULL 255 */ 256 public ListBoxRow getRowAtIndex(int index) 257 { 258 auto __p = gtk_list_box_get_row_at_index(gtkListBox, index); 259 260 if(__p is null) 261 { 262 return null; 263 } 264 265 return ObjectG.getDObject!(ListBoxRow)(cast(GtkListBoxRow*) __p); 266 } 267 268 /** 269 * Gets the row at the @y position. 270 * 271 * Params: 272 * y = position 273 * 274 * Returns: the row or %NULL 275 * in case no row exists for the given y coordinate. 276 */ 277 public ListBoxRow getRowAtY(int y) 278 { 279 auto __p = gtk_list_box_get_row_at_y(gtkListBox, y); 280 281 if(__p is null) 282 { 283 return null; 284 } 285 286 return ObjectG.getDObject!(ListBoxRow)(cast(GtkListBoxRow*) __p); 287 } 288 289 /** 290 * Gets the selected row, or %NULL if no rows are selected. 291 * 292 * Note that the box may allow multiple selection, in which 293 * case you should use [method@Gtk.ListBox.selected_foreach] to 294 * find all selected rows. 295 * 296 * Returns: the selected row or %NULL 297 */ 298 public ListBoxRow getSelectedRow() 299 { 300 auto __p = gtk_list_box_get_selected_row(gtkListBox); 301 302 if(__p is null) 303 { 304 return null; 305 } 306 307 return ObjectG.getDObject!(ListBoxRow)(cast(GtkListBoxRow*) __p); 308 } 309 310 /** 311 * Creates a list of all selected children. 312 * 313 * Returns: A `GList` containing the `GtkWidget` for each selected child. 314 * Free with g_list_free() when done. 315 */ 316 public ListG getSelectedRows() 317 { 318 auto __p = gtk_list_box_get_selected_rows(gtkListBox); 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 the listbox. 330 * 331 * Returns: a `GtkSelectionMode` 332 */ 333 public GtkSelectionMode getSelectionMode() 334 { 335 return gtk_list_box_get_selection_mode(gtkListBox); 336 } 337 338 /** 339 * Returns whether the list box should show separators 340 * between rows. 341 * 342 * Returns: %TRUE if the list box shows separators 343 */ 344 public bool getShowSeparators() 345 { 346 return gtk_list_box_get_show_separators(gtkListBox) != 0; 347 } 348 349 /** 350 * Insert the @child into the @box at @position. 351 * 352 * If a sort function is 353 * set, the widget will actually be inserted at the calculated position. 354 * 355 * If @position is -1, or larger than the total number of items in the 356 * @box, then the @child will be appended to the end. 357 * 358 * Params: 359 * child = the `GtkWidget` to add 360 * position = the position to insert @child in 361 */ 362 public void insert(Widget child, int position) 363 { 364 gtk_list_box_insert(gtkListBox, (child is null) ? null : child.getWidgetStruct(), position); 365 } 366 367 /** 368 * Update the filtering for all rows. 369 * 370 * Call this when result 371 * of the filter function on the @box is changed due 372 * to an external factor. For instance, this would be used 373 * if the filter function just looked for a specific search 374 * string and the entry with the search string has changed. 375 */ 376 public void invalidateFilter() 377 { 378 gtk_list_box_invalidate_filter(gtkListBox); 379 } 380 381 /** 382 * Update the separators for all rows. 383 * 384 * Call this when result 385 * of the header function on the @box is changed due 386 * to an external factor. 387 */ 388 public void invalidateHeaders() 389 { 390 gtk_list_box_invalidate_headers(gtkListBox); 391 } 392 393 /** 394 * Update the sorting for all rows. 395 * 396 * Call this when result 397 * of the sort function on the @box is changed due 398 * to an external factor. 399 */ 400 public void invalidateSort() 401 { 402 gtk_list_box_invalidate_sort(gtkListBox); 403 } 404 405 /** 406 * Prepend a widget to the list. 407 * 408 * If a sort function is set, the widget will 409 * actually be inserted at the calculated position. 410 * 411 * Params: 412 * child = the `GtkWidget` to add 413 */ 414 public void prepend(Widget child) 415 { 416 gtk_list_box_prepend(gtkListBox, (child is null) ? null : child.getWidgetStruct()); 417 } 418 419 /** 420 * Removes a child from @box. 421 * 422 * Params: 423 * child = the child to remove 424 */ 425 public void remove(Widget child) 426 { 427 gtk_list_box_remove(gtkListBox, (child is null) ? null : child.getWidgetStruct()); 428 } 429 430 /** 431 * Select all children of @box, if the selection mode allows it. 432 */ 433 public void selectAll() 434 { 435 gtk_list_box_select_all(gtkListBox); 436 } 437 438 /** 439 * Make @row the currently selected row. 440 * 441 * Params: 442 * row = The row to select or %NULL 443 */ 444 public void selectRow(ListBoxRow row) 445 { 446 gtk_list_box_select_row(gtkListBox, (row is null) ? null : row.getListBoxRowStruct()); 447 } 448 449 /** 450 * Calls a function for each selected child. 451 * 452 * Note that the selection cannot be modified from within this function. 453 * 454 * Params: 455 * func = the function to call for each selected child 456 * data = user data to pass to the function 457 */ 458 public void selectedForeach(GtkListBoxForeachFunc func, void* data) 459 { 460 gtk_list_box_selected_foreach(gtkListBox, func, data); 461 } 462 463 /** 464 * If @single is %TRUE, rows will be activated when you click on them, 465 * otherwise you need to double-click. 466 * 467 * Params: 468 * single = a boolean 469 */ 470 public void setActivateOnSingleClick(bool single) 471 { 472 gtk_list_box_set_activate_on_single_click(gtkListBox, single); 473 } 474 475 /** 476 * Sets the adjustment (if any) that the widget uses to 477 * for vertical scrolling. 478 * 479 * For instance, this is used to get the page size for 480 * PageUp/Down key handling. 481 * 482 * In the normal case when the @box is packed inside 483 * a `GtkScrolledWindow` the adjustment from that will 484 * be picked up automatically, so there is no need 485 * to manually do that. 486 * 487 * Params: 488 * adjustment = the adjustment, or %NULL 489 */ 490 public void setAdjustment(Adjustment adjustment) 491 { 492 gtk_list_box_set_adjustment(gtkListBox, (adjustment is null) ? null : adjustment.getAdjustmentStruct()); 493 } 494 495 /** 496 * By setting a filter function on the @box one can decide dynamically which 497 * of the rows to show. 498 * 499 * For instance, to implement a search function on a list that 500 * filters the original list to only show the matching rows. 501 * 502 * The @filter_func will be called for each row after the call, and 503 * it will continue to be called each time a row changes (via 504 * [method@Gtk.ListBoxRow.changed]) or when [method@Gtk.ListBox.invalidate_filter] 505 * is called. 506 * 507 * Note that using a filter function is incompatible with using a model 508 * (see [method@Gtk.ListBox.bind_model]). 509 * 510 * Params: 511 * filterFunc = callback that lets you filter which rows to show 512 * userData = user data passed to @filter_func 513 * destroy = destroy notifier for @user_data 514 */ 515 public void setFilterFunc(GtkListBoxFilterFunc filterFunc, void* userData, GDestroyNotify destroy) 516 { 517 gtk_list_box_set_filter_func(gtkListBox, filterFunc, userData, destroy); 518 } 519 520 /** 521 * Sets a header function. 522 * 523 * By setting a header function on the @box one can dynamically add headers 524 * in front of rows, depending on the contents of the row and its position 525 * in the list. 526 * 527 * For instance, one could use it to add headers in front of the first item 528 * of a new kind, in a list sorted by the kind. 529 * 530 * The @update_header can look at the current header widget using 531 * [method@Gtk.ListBoxRow.get_header] and either update the state of the widget 532 * as needed, or set a new one using [method@Gtk.ListBoxRow.set_header]. If no 533 * header is needed, set the header to %NULL. 534 * 535 * Note that you may get many calls @update_header to this for a particular 536 * row when e.g. changing things that don’t affect the header. In this case 537 * it is important for performance to not blindly replace an existing header 538 * with an identical one. 539 * 540 * The @update_header function will be called for each row after the call, 541 * and it will continue to be called each time a row changes (via 542 * [method@Gtk.ListBoxRow.changed]) and when the row before changes (either 543 * by [method@Gtk.ListBoxRow.changed] on the previous row, or when the previous 544 * row becomes a different row). It is also called for all rows when 545 * [method@Gtk.ListBox.invalidate_headers] is called. 546 * 547 * Params: 548 * updateHeader = callback that lets you add row headers 549 * userData = user data passed to @update_header 550 * destroy = destroy notifier for @user_data 551 */ 552 public void setHeaderFunc(GtkListBoxUpdateHeaderFunc updateHeader, void* userData, GDestroyNotify destroy) 553 { 554 gtk_list_box_set_header_func(gtkListBox, updateHeader, userData, destroy); 555 } 556 557 /** 558 * Sets the placeholder widget that is shown in the list when 559 * it doesn't display any visible children. 560 * 561 * Params: 562 * placeholder = a #GtkWidget or %NULL 563 */ 564 public void setPlaceholder(Widget placeholder) 565 { 566 gtk_list_box_set_placeholder(gtkListBox, (placeholder is null) ? null : placeholder.getWidgetStruct()); 567 } 568 569 /** 570 * Sets how selection works in the listbox. 571 * 572 * Params: 573 * mode = The `GtkSelectionMode` 574 */ 575 public void setSelectionMode(GtkSelectionMode mode) 576 { 577 gtk_list_box_set_selection_mode(gtkListBox, mode); 578 } 579 580 /** 581 * Sets whether the list box should show separators 582 * between rows. 583 * 584 * Params: 585 * showSeparators = %TRUE to show separators 586 */ 587 public void setShowSeparators(bool showSeparators) 588 { 589 gtk_list_box_set_show_separators(gtkListBox, showSeparators); 590 } 591 592 /** 593 * Sets a sort function. 594 * 595 * By setting a sort function on the @box one can dynamically reorder 596 * the rows of the list, based on the contents of the rows. 597 * 598 * The @sort_func will be called for each row after the call, and will 599 * continue to be called each time a row changes (via 600 * [method@Gtk.ListBoxRow.changed]) and when [method@Gtk.ListBox.invalidate_sort] 601 * is called. 602 * 603 * Note that using a sort function is incompatible with using a model 604 * (see [method@Gtk.ListBox.bind_model]). 605 * 606 * Params: 607 * sortFunc = the sort function 608 * userData = user data passed to @sort_func 609 * destroy = destroy notifier for @user_data 610 */ 611 public void setSortFunc(GtkListBoxSortFunc sortFunc, void* userData, GDestroyNotify destroy) 612 { 613 gtk_list_box_set_sort_func(gtkListBox, sortFunc, userData, destroy); 614 } 615 616 /** 617 * Unselect all children of @box, if the selection mode allows it. 618 */ 619 public void unselectAll() 620 { 621 gtk_list_box_unselect_all(gtkListBox); 622 } 623 624 /** 625 * Unselects a single row of @box, if the selection mode allows it. 626 * 627 * Params: 628 * row = the row to unselected 629 */ 630 public void unselectRow(ListBoxRow row) 631 { 632 gtk_list_box_unselect_row(gtkListBox, (row is null) ? null : row.getListBoxRowStruct()); 633 } 634 635 /** */ 636 gulong addOnActivateCursorRow(void delegate(ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 637 { 638 return Signals.connect(this, "activate-cursor-row", dlg, connectFlags ^ ConnectFlags.SWAPPED); 639 } 640 641 /** */ 642 gulong addOnMoveCursor(void delegate(GtkMovementStep, int, bool, bool, ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 643 { 644 return Signals.connect(this, "move-cursor", dlg, connectFlags ^ ConnectFlags.SWAPPED); 645 } 646 647 /** 648 * Emitted when a row has been activated by the user. 649 * 650 * Params: 651 * row = the activated row 652 */ 653 gulong addOnRowActivated(void delegate(ListBoxRow, ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 654 { 655 return Signals.connect(this, "row-activated", dlg, connectFlags ^ ConnectFlags.SWAPPED); 656 } 657 658 /** 659 * Emitted when a new row is selected, or (with a %NULL @row) 660 * when the selection is cleared. 661 * 662 * When the @box is using %GTK_SELECTION_MULTIPLE, this signal will not 663 * give you the full picture of selection changes, and you should use 664 * the [signal@Gtk.ListBox::selected-rows-changed] signal instead. 665 * 666 * Params: 667 * row = the selected row 668 */ 669 gulong addOnRowSelected(void delegate(ListBoxRow, ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 670 { 671 return Signals.connect(this, "row-selected", dlg, connectFlags ^ ConnectFlags.SWAPPED); 672 } 673 674 /** 675 * Emitted to select all children of the box, if the selection 676 * mode permits it. 677 * 678 * This is a [keybinding signal](class.SignalAction.html). 679 * 680 * The default binding for this signal is <kbd>Ctrl</kbd>-<kbd>a</kbd>. 681 */ 682 gulong addOnSelectAll(void delegate(ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 683 { 684 return Signals.connect(this, "select-all", dlg, connectFlags ^ ConnectFlags.SWAPPED); 685 } 686 687 /** 688 * Emitted when the set of selected rows changes. 689 */ 690 gulong addOnSelectedRowsChanged(void delegate(ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 691 { 692 return Signals.connect(this, "selected-rows-changed", dlg, connectFlags ^ ConnectFlags.SWAPPED); 693 } 694 695 /** */ 696 gulong addOnToggleCursorRow(void delegate(ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 697 { 698 return Signals.connect(this, "toggle-cursor-row", dlg, connectFlags ^ ConnectFlags.SWAPPED); 699 } 700 701 /** 702 * Emitted to unselect all children of the box, if the selection 703 * mode permits it. 704 * 705 * This is a [keybinding signal](class.SignalAction.html). 706 * 707 * The default binding for this signal is 708 * <kbd>Ctrl</kbd>-<kbd>Shift</kbd>-<kbd>a</kbd>. 709 */ 710 gulong addOnUnselectAll(void delegate(ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 711 { 712 return Signals.connect(this, "unselect-all", dlg, connectFlags ^ ConnectFlags.SWAPPED); 713 } 714 }