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 protected class OnActivateCursorRowDelegateWrapper 603 { 604 void delegate(ListBox) dlg; 605 gulong handlerId; 606 607 this(void delegate(ListBox) dlg) 608 { 609 this.dlg = dlg; 610 onActivateCursorRowListeners ~= this; 611 } 612 613 void remove(OnActivateCursorRowDelegateWrapper source) 614 { 615 foreach(index, wrapper; onActivateCursorRowListeners) 616 { 617 if (wrapper.handlerId == source.handlerId) 618 { 619 onActivateCursorRowListeners[index] = null; 620 onActivateCursorRowListeners = std.algorithm.remove(onActivateCursorRowListeners, index); 621 break; 622 } 623 } 624 } 625 } 626 OnActivateCursorRowDelegateWrapper[] onActivateCursorRowListeners; 627 628 /** */ 629 gulong addOnActivateCursorRow(void delegate(ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 630 { 631 auto wrapper = new OnActivateCursorRowDelegateWrapper(dlg); 632 wrapper.handlerId = Signals.connectData( 633 this, 634 "activate-cursor-row", 635 cast(GCallback)&callBackActivateCursorRow, 636 cast(void*)wrapper, 637 cast(GClosureNotify)&callBackActivateCursorRowDestroy, 638 connectFlags); 639 return wrapper.handlerId; 640 } 641 642 extern(C) static void callBackActivateCursorRow(GtkListBox* listboxStruct, OnActivateCursorRowDelegateWrapper wrapper) 643 { 644 wrapper.dlg(wrapper.outer); 645 } 646 647 extern(C) static void callBackActivateCursorRowDestroy(OnActivateCursorRowDelegateWrapper wrapper, GClosure* closure) 648 { 649 wrapper.remove(wrapper); 650 } 651 652 protected class OnMoveCursorDelegateWrapper 653 { 654 void delegate(GtkMovementStep, int, ListBox) dlg; 655 gulong handlerId; 656 657 this(void delegate(GtkMovementStep, int, ListBox) dlg) 658 { 659 this.dlg = dlg; 660 onMoveCursorListeners ~= this; 661 } 662 663 void remove(OnMoveCursorDelegateWrapper source) 664 { 665 foreach(index, wrapper; onMoveCursorListeners) 666 { 667 if (wrapper.handlerId == source.handlerId) 668 { 669 onMoveCursorListeners[index] = null; 670 onMoveCursorListeners = std.algorithm.remove(onMoveCursorListeners, index); 671 break; 672 } 673 } 674 } 675 } 676 OnMoveCursorDelegateWrapper[] onMoveCursorListeners; 677 678 /** */ 679 gulong addOnMoveCursor(void delegate(GtkMovementStep, int, ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 680 { 681 auto wrapper = new OnMoveCursorDelegateWrapper(dlg); 682 wrapper.handlerId = Signals.connectData( 683 this, 684 "move-cursor", 685 cast(GCallback)&callBackMoveCursor, 686 cast(void*)wrapper, 687 cast(GClosureNotify)&callBackMoveCursorDestroy, 688 connectFlags); 689 return wrapper.handlerId; 690 } 691 692 extern(C) static void callBackMoveCursor(GtkListBox* listboxStruct, GtkMovementStep object, int p0, OnMoveCursorDelegateWrapper wrapper) 693 { 694 wrapper.dlg(object, p0, wrapper.outer); 695 } 696 697 extern(C) static void callBackMoveCursorDestroy(OnMoveCursorDelegateWrapper wrapper, GClosure* closure) 698 { 699 wrapper.remove(wrapper); 700 } 701 702 protected class OnRowActivatedDelegateWrapper 703 { 704 void delegate(ListBoxRow, ListBox) dlg; 705 gulong handlerId; 706 707 this(void delegate(ListBoxRow, ListBox) dlg) 708 { 709 this.dlg = dlg; 710 onRowActivatedListeners ~= this; 711 } 712 713 void remove(OnRowActivatedDelegateWrapper source) 714 { 715 foreach(index, wrapper; onRowActivatedListeners) 716 { 717 if (wrapper.handlerId == source.handlerId) 718 { 719 onRowActivatedListeners[index] = null; 720 onRowActivatedListeners = std.algorithm.remove(onRowActivatedListeners, index); 721 break; 722 } 723 } 724 } 725 } 726 OnRowActivatedDelegateWrapper[] onRowActivatedListeners; 727 728 /** 729 * The ::row-activated signal is emitted when a row has been activated by the user. 730 * 731 * Params: 732 * row = the activated row 733 * 734 * Since: 3.10 735 */ 736 gulong addOnRowActivated(void delegate(ListBoxRow, ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 737 { 738 auto wrapper = new OnRowActivatedDelegateWrapper(dlg); 739 wrapper.handlerId = Signals.connectData( 740 this, 741 "row-activated", 742 cast(GCallback)&callBackRowActivated, 743 cast(void*)wrapper, 744 cast(GClosureNotify)&callBackRowActivatedDestroy, 745 connectFlags); 746 return wrapper.handlerId; 747 } 748 749 extern(C) static void callBackRowActivated(GtkListBox* listboxStruct, GtkListBoxRow* row, OnRowActivatedDelegateWrapper wrapper) 750 { 751 wrapper.dlg(ObjectG.getDObject!(ListBoxRow)(row), wrapper.outer); 752 } 753 754 extern(C) static void callBackRowActivatedDestroy(OnRowActivatedDelegateWrapper wrapper, GClosure* closure) 755 { 756 wrapper.remove(wrapper); 757 } 758 759 protected class OnRowSelectedDelegateWrapper 760 { 761 void delegate(ListBoxRow, ListBox) dlg; 762 gulong handlerId; 763 764 this(void delegate(ListBoxRow, ListBox) dlg) 765 { 766 this.dlg = dlg; 767 onRowSelectedListeners ~= this; 768 } 769 770 void remove(OnRowSelectedDelegateWrapper source) 771 { 772 foreach(index, wrapper; onRowSelectedListeners) 773 { 774 if (wrapper.handlerId == source.handlerId) 775 { 776 onRowSelectedListeners[index] = null; 777 onRowSelectedListeners = std.algorithm.remove(onRowSelectedListeners, index); 778 break; 779 } 780 } 781 } 782 } 783 OnRowSelectedDelegateWrapper[] onRowSelectedListeners; 784 785 /** 786 * The ::row-selected signal is emitted when a new row is selected, or 787 * (with a %NULL @row) when the selection is cleared. 788 * 789 * When the @box is using #GTK_SELECTION_MULTIPLE, this signal will not 790 * give you the full picture of selection changes, and you should use 791 * the #GtkListBox::selected-rows-changed signal instead. 792 * 793 * Params: 794 * row = the selected row 795 * 796 * Since: 3.10 797 */ 798 gulong addOnRowSelected(void delegate(ListBoxRow, ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 799 { 800 auto wrapper = new OnRowSelectedDelegateWrapper(dlg); 801 wrapper.handlerId = Signals.connectData( 802 this, 803 "row-selected", 804 cast(GCallback)&callBackRowSelected, 805 cast(void*)wrapper, 806 cast(GClosureNotify)&callBackRowSelectedDestroy, 807 connectFlags); 808 return wrapper.handlerId; 809 } 810 811 extern(C) static void callBackRowSelected(GtkListBox* listboxStruct, GtkListBoxRow* row, OnRowSelectedDelegateWrapper wrapper) 812 { 813 wrapper.dlg(ObjectG.getDObject!(ListBoxRow)(row), wrapper.outer); 814 } 815 816 extern(C) static void callBackRowSelectedDestroy(OnRowSelectedDelegateWrapper wrapper, GClosure* closure) 817 { 818 wrapper.remove(wrapper); 819 } 820 821 protected class OnSelectAllDelegateWrapper 822 { 823 void delegate(ListBox) dlg; 824 gulong handlerId; 825 826 this(void delegate(ListBox) dlg) 827 { 828 this.dlg = dlg; 829 onSelectAllListeners ~= this; 830 } 831 832 void remove(OnSelectAllDelegateWrapper source) 833 { 834 foreach(index, wrapper; onSelectAllListeners) 835 { 836 if (wrapper.handlerId == source.handlerId) 837 { 838 onSelectAllListeners[index] = null; 839 onSelectAllListeners = std.algorithm.remove(onSelectAllListeners, index); 840 break; 841 } 842 } 843 } 844 } 845 OnSelectAllDelegateWrapper[] onSelectAllListeners; 846 847 /** 848 * The ::select-all signal is a [keybinding signal][GtkBindingSignal] 849 * which gets emitted to select all children of the box, if the selection 850 * mode permits it. 851 * 852 * The default bindings for this signal is Ctrl-a. 853 * 854 * Since: 3.14 855 */ 856 gulong addOnSelectAll(void delegate(ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 857 { 858 auto wrapper = new OnSelectAllDelegateWrapper(dlg); 859 wrapper.handlerId = Signals.connectData( 860 this, 861 "select-all", 862 cast(GCallback)&callBackSelectAll, 863 cast(void*)wrapper, 864 cast(GClosureNotify)&callBackSelectAllDestroy, 865 connectFlags); 866 return wrapper.handlerId; 867 } 868 869 extern(C) static void callBackSelectAll(GtkListBox* listboxStruct, OnSelectAllDelegateWrapper wrapper) 870 { 871 wrapper.dlg(wrapper.outer); 872 } 873 874 extern(C) static void callBackSelectAllDestroy(OnSelectAllDelegateWrapper wrapper, GClosure* closure) 875 { 876 wrapper.remove(wrapper); 877 } 878 879 protected class OnSelectedRowsChangedDelegateWrapper 880 { 881 void delegate(ListBox) dlg; 882 gulong handlerId; 883 884 this(void delegate(ListBox) dlg) 885 { 886 this.dlg = dlg; 887 onSelectedRowsChangedListeners ~= this; 888 } 889 890 void remove(OnSelectedRowsChangedDelegateWrapper source) 891 { 892 foreach(index, wrapper; onSelectedRowsChangedListeners) 893 { 894 if (wrapper.handlerId == source.handlerId) 895 { 896 onSelectedRowsChangedListeners[index] = null; 897 onSelectedRowsChangedListeners = std.algorithm.remove(onSelectedRowsChangedListeners, index); 898 break; 899 } 900 } 901 } 902 } 903 OnSelectedRowsChangedDelegateWrapper[] onSelectedRowsChangedListeners; 904 905 /** 906 * The ::selected-rows-changed signal is emitted when the 907 * set of selected rows changes. 908 * 909 * Since: 3.14 910 */ 911 gulong addOnSelectedRowsChanged(void delegate(ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 912 { 913 auto wrapper = new OnSelectedRowsChangedDelegateWrapper(dlg); 914 wrapper.handlerId = Signals.connectData( 915 this, 916 "selected-rows-changed", 917 cast(GCallback)&callBackSelectedRowsChanged, 918 cast(void*)wrapper, 919 cast(GClosureNotify)&callBackSelectedRowsChangedDestroy, 920 connectFlags); 921 return wrapper.handlerId; 922 } 923 924 extern(C) static void callBackSelectedRowsChanged(GtkListBox* listboxStruct, OnSelectedRowsChangedDelegateWrapper wrapper) 925 { 926 wrapper.dlg(wrapper.outer); 927 } 928 929 extern(C) static void callBackSelectedRowsChangedDestroy(OnSelectedRowsChangedDelegateWrapper wrapper, GClosure* closure) 930 { 931 wrapper.remove(wrapper); 932 } 933 934 protected class OnToggleCursorRowDelegateWrapper 935 { 936 void delegate(ListBox) dlg; 937 gulong handlerId; 938 939 this(void delegate(ListBox) dlg) 940 { 941 this.dlg = dlg; 942 onToggleCursorRowListeners ~= this; 943 } 944 945 void remove(OnToggleCursorRowDelegateWrapper source) 946 { 947 foreach(index, wrapper; onToggleCursorRowListeners) 948 { 949 if (wrapper.handlerId == source.handlerId) 950 { 951 onToggleCursorRowListeners[index] = null; 952 onToggleCursorRowListeners = std.algorithm.remove(onToggleCursorRowListeners, index); 953 break; 954 } 955 } 956 } 957 } 958 OnToggleCursorRowDelegateWrapper[] onToggleCursorRowListeners; 959 960 /** */ 961 gulong addOnToggleCursorRow(void delegate(ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 962 { 963 auto wrapper = new OnToggleCursorRowDelegateWrapper(dlg); 964 wrapper.handlerId = Signals.connectData( 965 this, 966 "toggle-cursor-row", 967 cast(GCallback)&callBackToggleCursorRow, 968 cast(void*)wrapper, 969 cast(GClosureNotify)&callBackToggleCursorRowDestroy, 970 connectFlags); 971 return wrapper.handlerId; 972 } 973 974 extern(C) static void callBackToggleCursorRow(GtkListBox* listboxStruct, OnToggleCursorRowDelegateWrapper wrapper) 975 { 976 wrapper.dlg(wrapper.outer); 977 } 978 979 extern(C) static void callBackToggleCursorRowDestroy(OnToggleCursorRowDelegateWrapper wrapper, GClosure* closure) 980 { 981 wrapper.remove(wrapper); 982 } 983 984 protected class OnUnselectAllDelegateWrapper 985 { 986 void delegate(ListBox) dlg; 987 gulong handlerId; 988 989 this(void delegate(ListBox) dlg) 990 { 991 this.dlg = dlg; 992 onUnselectAllListeners ~= this; 993 } 994 995 void remove(OnUnselectAllDelegateWrapper source) 996 { 997 foreach(index, wrapper; onUnselectAllListeners) 998 { 999 if (wrapper.handlerId == source.handlerId) 1000 { 1001 onUnselectAllListeners[index] = null; 1002 onUnselectAllListeners = std.algorithm.remove(onUnselectAllListeners, index); 1003 break; 1004 } 1005 } 1006 } 1007 } 1008 OnUnselectAllDelegateWrapper[] onUnselectAllListeners; 1009 1010 /** 1011 * The ::unselect-all signal is a [keybinding signal][GtkBindingSignal] 1012 * which gets emitted to unselect all children of the box, if the selection 1013 * mode permits it. 1014 * 1015 * The default bindings for this signal is Ctrl-Shift-a. 1016 * 1017 * Since: 3.14 1018 */ 1019 gulong addOnUnselectAll(void delegate(ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 1020 { 1021 auto wrapper = new OnUnselectAllDelegateWrapper(dlg); 1022 wrapper.handlerId = Signals.connectData( 1023 this, 1024 "unselect-all", 1025 cast(GCallback)&callBackUnselectAll, 1026 cast(void*)wrapper, 1027 cast(GClosureNotify)&callBackUnselectAllDestroy, 1028 connectFlags); 1029 return wrapper.handlerId; 1030 } 1031 1032 extern(C) static void callBackUnselectAll(GtkListBox* listboxStruct, OnUnselectAllDelegateWrapper wrapper) 1033 { 1034 wrapper.dlg(wrapper.outer); 1035 } 1036 1037 extern(C) static void callBackUnselectAllDestroy(OnUnselectAllDelegateWrapper wrapper, GClosure* closure) 1038 { 1039 wrapper.remove(wrapper); 1040 } 1041 }