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