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 protected override void setStruct(GObject* obj) 96 { 97 gtkListBox = cast(GtkListBox*)obj; 98 super.setStruct(obj); 99 } 100 101 /** 102 * Sets our main struct and passes it to the parent class. 103 */ 104 public this (GtkListBox* gtkListBox, bool ownedRef = false) 105 { 106 this.gtkListBox = gtkListBox; 107 super(cast(GtkContainer*)gtkListBox, ownedRef); 108 } 109 110 111 /** */ 112 public static GType getType() 113 { 114 return gtk_list_box_get_type(); 115 } 116 117 /** 118 * Creates a new #GtkListBox container. 119 * 120 * Returns: a new #GtkListBox 121 * 122 * Since: 3.10 123 * 124 * Throws: ConstructionException GTK+ fails to create the object. 125 */ 126 public this() 127 { 128 auto p = gtk_list_box_new(); 129 130 if(p is null) 131 { 132 throw new ConstructionException("null returned by new"); 133 } 134 135 this(cast(GtkListBox*) p); 136 } 137 138 /** 139 * Binds @model to @box. 140 * 141 * If @box was already bound to a model, that previous binding is 142 * destroyed. 143 * 144 * The contents of @box are cleared and then filled with widgets that 145 * represent items from @model. @box is updated whenever @model changes. 146 * If @model is %NULL, @box is left empty. 147 * 148 * It is undefined to add or remove widgets directly (for example, with 149 * gtk_list_box_insert() or gtk_container_add()) while @box is bound to a 150 * model. 151 * 152 * Note that using a model is incompatible with the filtering and sorting 153 * functionality in GtkListBox. When using a model, filtering and sorting 154 * should be implemented by the model. 155 * 156 * Params: 157 * model = the #GListModel to be bound to @box 158 * createWidgetFunc = a function that creates widgets for items 159 * or %NULL in case you also passed %NULL as @model 160 * userData = user data passed to @create_widget_func 161 * userDataFreeFunc = function for freeing @user_data 162 * 163 * Since: 3.16 164 */ 165 public void bindModel(ListModelIF model, GtkListBoxCreateWidgetFunc createWidgetFunc, void* userData, GDestroyNotify userDataFreeFunc) 166 { 167 gtk_list_box_bind_model(gtkListBox, (model is null) ? null : model.getListModelStruct(), createWidgetFunc, userData, userDataFreeFunc); 168 } 169 170 /** 171 * This is a helper function for implementing DnD onto a #GtkListBox. 172 * The passed in @row will be highlighted via gtk_drag_highlight(), 173 * and any previously highlighted row will be unhighlighted. 174 * 175 * The row will also be unhighlighted when the widget gets 176 * a drag leave event. 177 * 178 * Params: 179 * row = a #GtkListBoxRow 180 * 181 * Since: 3.10 182 */ 183 public void dragHighlightRow(ListBoxRow row) 184 { 185 gtk_list_box_drag_highlight_row(gtkListBox, (row is null) ? null : row.getListBoxRowStruct()); 186 } 187 188 /** 189 * If a row has previously been highlighted via gtk_list_box_drag_highlight_row() 190 * it will have the highlight removed. 191 * 192 * Since: 3.10 193 */ 194 public void dragUnhighlightRow() 195 { 196 gtk_list_box_drag_unhighlight_row(gtkListBox); 197 } 198 199 /** 200 * Returns whether rows activate on single clicks. 201 * 202 * Returns: %TRUE if rows are activated on single click, %FALSE otherwise 203 * 204 * Since: 3.10 205 */ 206 public bool getActivateOnSingleClick() 207 { 208 return gtk_list_box_get_activate_on_single_click(gtkListBox) != 0; 209 } 210 211 /** 212 * Gets the adjustment (if any) that the widget uses to 213 * for vertical scrolling. 214 * 215 * Returns: the adjustment 216 * 217 * Since: 3.10 218 */ 219 public Adjustment getAdjustment() 220 { 221 auto p = gtk_list_box_get_adjustment(gtkListBox); 222 223 if(p is null) 224 { 225 return null; 226 } 227 228 return ObjectG.getDObject!(Adjustment)(cast(GtkAdjustment*) p); 229 } 230 231 /** 232 * Gets the n-th child in the list (not counting headers). 233 * If @_index is negative or larger than the number of items in the 234 * list, %NULL is returned. 235 * 236 * Params: 237 * index = the index of the row 238 * 239 * Returns: the child #GtkWidget or %NULL 240 * 241 * Since: 3.10 242 */ 243 public ListBoxRow getRowAtIndex(int index) 244 { 245 auto p = gtk_list_box_get_row_at_index(gtkListBox, index); 246 247 if(p is null) 248 { 249 return null; 250 } 251 252 return ObjectG.getDObject!(ListBoxRow)(cast(GtkListBoxRow*) p); 253 } 254 255 /** 256 * Gets the row at the @y position. 257 * 258 * Params: 259 * y = position 260 * 261 * Returns: the row or %NULL 262 * in case no row exists for the given y coordinate. 263 * 264 * Since: 3.10 265 */ 266 public ListBoxRow getRowAtY(int y) 267 { 268 auto p = gtk_list_box_get_row_at_y(gtkListBox, y); 269 270 if(p is null) 271 { 272 return null; 273 } 274 275 return ObjectG.getDObject!(ListBoxRow)(cast(GtkListBoxRow*) p); 276 } 277 278 /** 279 * Gets the selected row. 280 * 281 * Note that the box may allow multiple selection, in which 282 * case you should use gtk_list_box_selected_foreach() to 283 * find all selected rows. 284 * 285 * Returns: the selected row 286 * 287 * Since: 3.10 288 */ 289 public ListBoxRow getSelectedRow() 290 { 291 auto p = gtk_list_box_get_selected_row(gtkListBox); 292 293 if(p is null) 294 { 295 return null; 296 } 297 298 return ObjectG.getDObject!(ListBoxRow)(cast(GtkListBoxRow*) p); 299 } 300 301 /** 302 * Creates a list of all selected children. 303 * 304 * Returns: A #GList containing the #GtkWidget for each selected child. 305 * Free with g_list_free() when done. 306 * 307 * Since: 3.14 308 */ 309 public ListG getSelectedRows() 310 { 311 auto p = gtk_list_box_get_selected_rows(gtkListBox); 312 313 if(p is null) 314 { 315 return null; 316 } 317 318 return new ListG(cast(GList*) p); 319 } 320 321 /** 322 * Gets the selection mode of the listbox. 323 * 324 * Returns: a #GtkSelectionMode 325 * 326 * Since: 3.10 327 */ 328 public GtkSelectionMode getSelectionMode() 329 { 330 return gtk_list_box_get_selection_mode(gtkListBox); 331 } 332 333 /** 334 * Insert the @child into the @box at @position. If a sort function is 335 * set, the widget will actually be inserted at the calculated position and 336 * this function has the same effect of gtk_container_add(). 337 * 338 * If @position is -1, or larger than the total number of items in the 339 * @box, then the @child will be appended to the end. 340 * 341 * Params: 342 * child = the #GtkWidget to add 343 * position = the position to insert @child in 344 * 345 * Since: 3.10 346 */ 347 public void insert(Widget child, int position) 348 { 349 gtk_list_box_insert(gtkListBox, (child is null) ? null : child.getWidgetStruct(), position); 350 } 351 352 /** 353 * Update the filtering for all rows. Call this when result 354 * of the filter function on the @box is changed due 355 * to an external factor. For instance, this would be used 356 * if the filter function just looked for a specific search 357 * string and the entry with the search string has changed. 358 * 359 * Since: 3.10 360 */ 361 public void invalidateFilter() 362 { 363 gtk_list_box_invalidate_filter(gtkListBox); 364 } 365 366 /** 367 * Update the separators for all rows. Call this when result 368 * of the header function on the @box is changed due 369 * to an external factor. 370 * 371 * Since: 3.10 372 */ 373 public void invalidateHeaders() 374 { 375 gtk_list_box_invalidate_headers(gtkListBox); 376 } 377 378 /** 379 * Update the sorting for all rows. Call this when result 380 * of the sort function on the @box is changed due 381 * to an external factor. 382 * 383 * Since: 3.10 384 */ 385 public void invalidateSort() 386 { 387 gtk_list_box_invalidate_sort(gtkListBox); 388 } 389 390 /** 391 * Prepend a widget to the list. If a sort function is set, the widget will 392 * actually be inserted at the calculated position and this function has the 393 * same effect of gtk_container_add(). 394 * 395 * Params: 396 * child = the #GtkWidget to add 397 * 398 * Since: 3.10 399 */ 400 public void prepend(Widget child) 401 { 402 gtk_list_box_prepend(gtkListBox, (child is null) ? null : child.getWidgetStruct()); 403 } 404 405 /** 406 * Select all children of @box, if the selection mode allows it. 407 * 408 * Since: 3.14 409 */ 410 public void selectAll() 411 { 412 gtk_list_box_select_all(gtkListBox); 413 } 414 415 /** 416 * Make @row the currently selected row. 417 * 418 * Params: 419 * row = The row to select or %NULL 420 * 421 * Since: 3.10 422 */ 423 public void selectRow(ListBoxRow row) 424 { 425 gtk_list_box_select_row(gtkListBox, (row is null) ? null : row.getListBoxRowStruct()); 426 } 427 428 /** 429 * Calls a function for each selected child. 430 * 431 * Note that the selection cannot be modified from within this function. 432 * 433 * Params: 434 * func = the function to call for each selected child 435 * data = user data to pass to the function 436 * 437 * Since: 3.14 438 */ 439 public void selectedForeach(GtkListBoxForeachFunc func, void* data) 440 { 441 gtk_list_box_selected_foreach(gtkListBox, func, data); 442 } 443 444 /** 445 * If @single is %TRUE, rows will be activated when you click on them, 446 * otherwise you need to double-click. 447 * 448 * Params: 449 * single = a boolean 450 * 451 * Since: 3.10 452 */ 453 public void setActivateOnSingleClick(bool single) 454 { 455 gtk_list_box_set_activate_on_single_click(gtkListBox, single); 456 } 457 458 /** 459 * Sets the adjustment (if any) that the widget uses to 460 * for vertical scrolling. For instance, this is used 461 * to get the page size for PageUp/Down key handling. 462 * 463 * In the normal case when the @box is packed inside 464 * a #GtkScrolledWindow the adjustment from that will 465 * be picked up automatically, so there is no need 466 * to manually do that. 467 * 468 * Params: 469 * adjustment = the adjustment, or %NULL 470 * 471 * Since: 3.10 472 */ 473 public void setAdjustment(Adjustment adjustment) 474 { 475 gtk_list_box_set_adjustment(gtkListBox, (adjustment is null) ? null : adjustment.getAdjustmentStruct()); 476 } 477 478 /** 479 * By setting a filter function on the @box one can decide dynamically which 480 * of the rows to show. For instance, to implement a search function on a list that 481 * filters the original list to only show the matching rows. 482 * 483 * The @filter_func will be called for each row after the call, and it will 484 * continue to be called each time a row changes (via gtk_list_box_row_changed()) or 485 * when gtk_list_box_invalidate_filter() is called. 486 * 487 * Note that using a filter function is incompatible with using a model 488 * (see gtk_list_box_bind_model()). 489 * 490 * Params: 491 * filterFunc = callback that lets you filter which rows to show 492 * userData = user data passed to @filter_func 493 * destroy = destroy notifier for @user_data 494 * 495 * Since: 3.10 496 */ 497 public void setFilterFunc(GtkListBoxFilterFunc filterFunc, void* userData, GDestroyNotify destroy) 498 { 499 gtk_list_box_set_filter_func(gtkListBox, filterFunc, userData, destroy); 500 } 501 502 /** 503 * By setting a header function on the @box one can dynamically add headers 504 * in front of rows, depending on the contents of the row and its position in the list. 505 * For instance, one could use it to add headers in front of the first item of a 506 * new kind, in a list sorted by the kind. 507 * 508 * The @update_header can look at the current header widget using gtk_list_box_row_get_header() 509 * and either update the state of the widget as needed, or set a new one using 510 * gtk_list_box_row_set_header(). If no header is needed, set the header to %NULL. 511 * 512 * Note that you may get many calls @update_header to this for a particular row when e.g. 513 * changing things that don’t affect the header. In this case it is important for performance 514 * to not blindly replace an existing header with an identical one. 515 * 516 * The @update_header function will be called for each row after the call, and it will 517 * continue to be called each time a row changes (via gtk_list_box_row_changed()) and when 518 * the row before changes (either by gtk_list_box_row_changed() on the previous row, or when 519 * the previous row becomes a different row). It is also called for all rows when 520 * gtk_list_box_invalidate_headers() is called. 521 * 522 * Params: 523 * updateHeader = callback that lets you add row headers 524 * userData = user data passed to @update_header 525 * destroy = destroy notifier for @user_data 526 * 527 * Since: 3.10 528 */ 529 public void setHeaderFunc(GtkListBoxUpdateHeaderFunc updateHeader, void* userData, GDestroyNotify destroy) 530 { 531 gtk_list_box_set_header_func(gtkListBox, updateHeader, userData, destroy); 532 } 533 534 /** 535 * Sets the placeholder widget that is shown in the list when 536 * it doesn't display any visible children. 537 * 538 * Params: 539 * placeholder = a #GtkWidget or %NULL 540 * 541 * Since: 3.10 542 */ 543 public void setPlaceholder(Widget placeholder) 544 { 545 gtk_list_box_set_placeholder(gtkListBox, (placeholder is null) ? null : placeholder.getWidgetStruct()); 546 } 547 548 /** 549 * Sets how selection works in the listbox. 550 * See #GtkSelectionMode for details. 551 * 552 * Params: 553 * mode = The #GtkSelectionMode 554 * 555 * Since: 3.10 556 */ 557 public void setSelectionMode(GtkSelectionMode mode) 558 { 559 gtk_list_box_set_selection_mode(gtkListBox, mode); 560 } 561 562 /** 563 * By setting a sort function on the @box one can dynamically reorder the rows 564 * of the list, based on the contents of the rows. 565 * 566 * The @sort_func will be called for each row after the call, and will continue to 567 * be called each time a row changes (via gtk_list_box_row_changed()) and when 568 * gtk_list_box_invalidate_sort() is called. 569 * 570 * Note that using a sort function is incompatible with using a model 571 * (see gtk_list_box_bind_model()). 572 * 573 * Params: 574 * sortFunc = the sort function 575 * userData = user data passed to @sort_func 576 * destroy = destroy notifier for @user_data 577 * 578 * Since: 3.10 579 */ 580 public void setSortFunc(GtkListBoxSortFunc sortFunc, void* userData, GDestroyNotify destroy) 581 { 582 gtk_list_box_set_sort_func(gtkListBox, sortFunc, userData, destroy); 583 } 584 585 /** 586 * Unselect all children of @box, if the selection mode allows it. 587 * 588 * Since: 3.14 589 */ 590 public void unselectAll() 591 { 592 gtk_list_box_unselect_all(gtkListBox); 593 } 594 595 /** 596 * Unselects a single row of @box, if the selection mode allows it. 597 * 598 * Params: 599 * row = the row to unselected 600 * 601 * Since: 3.14 602 */ 603 public void unselectRow(ListBoxRow row) 604 { 605 gtk_list_box_unselect_row(gtkListBox, (row is null) ? null : row.getListBoxRowStruct()); 606 } 607 608 protected class OnActivateCursorRowDelegateWrapper 609 { 610 void delegate(ListBox) dlg; 611 gulong handlerId; 612 613 this(void delegate(ListBox) dlg) 614 { 615 this.dlg = dlg; 616 onActivateCursorRowListeners ~= this; 617 } 618 619 void remove(OnActivateCursorRowDelegateWrapper source) 620 { 621 foreach(index, wrapper; onActivateCursorRowListeners) 622 { 623 if (wrapper.handlerId == source.handlerId) 624 { 625 onActivateCursorRowListeners[index] = null; 626 onActivateCursorRowListeners = std.algorithm.remove(onActivateCursorRowListeners, index); 627 break; 628 } 629 } 630 } 631 } 632 OnActivateCursorRowDelegateWrapper[] onActivateCursorRowListeners; 633 634 /** */ 635 gulong addOnActivateCursorRow(void delegate(ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 636 { 637 auto wrapper = new OnActivateCursorRowDelegateWrapper(dlg); 638 wrapper.handlerId = Signals.connectData( 639 this, 640 "activate-cursor-row", 641 cast(GCallback)&callBackActivateCursorRow, 642 cast(void*)wrapper, 643 cast(GClosureNotify)&callBackActivateCursorRowDestroy, 644 connectFlags); 645 return wrapper.handlerId; 646 } 647 648 extern(C) static void callBackActivateCursorRow(GtkListBox* listboxStruct, OnActivateCursorRowDelegateWrapper wrapper) 649 { 650 wrapper.dlg(wrapper.outer); 651 } 652 653 extern(C) static void callBackActivateCursorRowDestroy(OnActivateCursorRowDelegateWrapper wrapper, GClosure* closure) 654 { 655 wrapper.remove(wrapper); 656 } 657 658 protected class OnMoveCursorDelegateWrapper 659 { 660 void delegate(GtkMovementStep, int, ListBox) dlg; 661 gulong handlerId; 662 663 this(void delegate(GtkMovementStep, int, ListBox) dlg) 664 { 665 this.dlg = dlg; 666 onMoveCursorListeners ~= this; 667 } 668 669 void remove(OnMoveCursorDelegateWrapper source) 670 { 671 foreach(index, wrapper; onMoveCursorListeners) 672 { 673 if (wrapper.handlerId == source.handlerId) 674 { 675 onMoveCursorListeners[index] = null; 676 onMoveCursorListeners = std.algorithm.remove(onMoveCursorListeners, index); 677 break; 678 } 679 } 680 } 681 } 682 OnMoveCursorDelegateWrapper[] onMoveCursorListeners; 683 684 /** */ 685 gulong addOnMoveCursor(void delegate(GtkMovementStep, int, ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 686 { 687 auto wrapper = new OnMoveCursorDelegateWrapper(dlg); 688 wrapper.handlerId = Signals.connectData( 689 this, 690 "move-cursor", 691 cast(GCallback)&callBackMoveCursor, 692 cast(void*)wrapper, 693 cast(GClosureNotify)&callBackMoveCursorDestroy, 694 connectFlags); 695 return wrapper.handlerId; 696 } 697 698 extern(C) static void callBackMoveCursor(GtkListBox* listboxStruct, GtkMovementStep object, int p0, OnMoveCursorDelegateWrapper wrapper) 699 { 700 wrapper.dlg(object, p0, wrapper.outer); 701 } 702 703 extern(C) static void callBackMoveCursorDestroy(OnMoveCursorDelegateWrapper wrapper, GClosure* closure) 704 { 705 wrapper.remove(wrapper); 706 } 707 708 protected class OnRowActivatedDelegateWrapper 709 { 710 void delegate(ListBoxRow, ListBox) dlg; 711 gulong handlerId; 712 713 this(void delegate(ListBoxRow, ListBox) dlg) 714 { 715 this.dlg = dlg; 716 onRowActivatedListeners ~= this; 717 } 718 719 void remove(OnRowActivatedDelegateWrapper source) 720 { 721 foreach(index, wrapper; onRowActivatedListeners) 722 { 723 if (wrapper.handlerId == source.handlerId) 724 { 725 onRowActivatedListeners[index] = null; 726 onRowActivatedListeners = std.algorithm.remove(onRowActivatedListeners, index); 727 break; 728 } 729 } 730 } 731 } 732 OnRowActivatedDelegateWrapper[] onRowActivatedListeners; 733 734 /** 735 * The ::row-activated signal is emitted when a row has been activated by the user. 736 * 737 * Params: 738 * row = the activated row 739 * 740 * Since: 3.10 741 */ 742 gulong addOnRowActivated(void delegate(ListBoxRow, ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 743 { 744 auto wrapper = new OnRowActivatedDelegateWrapper(dlg); 745 wrapper.handlerId = Signals.connectData( 746 this, 747 "row-activated", 748 cast(GCallback)&callBackRowActivated, 749 cast(void*)wrapper, 750 cast(GClosureNotify)&callBackRowActivatedDestroy, 751 connectFlags); 752 return wrapper.handlerId; 753 } 754 755 extern(C) static void callBackRowActivated(GtkListBox* listboxStruct, GtkListBoxRow* row, OnRowActivatedDelegateWrapper wrapper) 756 { 757 wrapper.dlg(ObjectG.getDObject!(ListBoxRow)(row), wrapper.outer); 758 } 759 760 extern(C) static void callBackRowActivatedDestroy(OnRowActivatedDelegateWrapper wrapper, GClosure* closure) 761 { 762 wrapper.remove(wrapper); 763 } 764 765 protected class OnRowSelectedDelegateWrapper 766 { 767 void delegate(ListBoxRow, ListBox) dlg; 768 gulong handlerId; 769 770 this(void delegate(ListBoxRow, ListBox) dlg) 771 { 772 this.dlg = dlg; 773 onRowSelectedListeners ~= this; 774 } 775 776 void remove(OnRowSelectedDelegateWrapper source) 777 { 778 foreach(index, wrapper; onRowSelectedListeners) 779 { 780 if (wrapper.handlerId == source.handlerId) 781 { 782 onRowSelectedListeners[index] = null; 783 onRowSelectedListeners = std.algorithm.remove(onRowSelectedListeners, index); 784 break; 785 } 786 } 787 } 788 } 789 OnRowSelectedDelegateWrapper[] onRowSelectedListeners; 790 791 /** 792 * The ::row-selected signal is emitted when a new row is selected, or 793 * (with a %NULL @row) when the selection is cleared. 794 * 795 * When the @box is using #GTK_SELECTION_MULTIPLE, this signal will not 796 * give you the full picture of selection changes, and you should use 797 * the #GtkListBox::selected-rows-changed signal instead. 798 * 799 * Params: 800 * row = the selected row 801 * 802 * Since: 3.10 803 */ 804 gulong addOnRowSelected(void delegate(ListBoxRow, ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 805 { 806 auto wrapper = new OnRowSelectedDelegateWrapper(dlg); 807 wrapper.handlerId = Signals.connectData( 808 this, 809 "row-selected", 810 cast(GCallback)&callBackRowSelected, 811 cast(void*)wrapper, 812 cast(GClosureNotify)&callBackRowSelectedDestroy, 813 connectFlags); 814 return wrapper.handlerId; 815 } 816 817 extern(C) static void callBackRowSelected(GtkListBox* listboxStruct, GtkListBoxRow* row, OnRowSelectedDelegateWrapper wrapper) 818 { 819 wrapper.dlg(ObjectG.getDObject!(ListBoxRow)(row), wrapper.outer); 820 } 821 822 extern(C) static void callBackRowSelectedDestroy(OnRowSelectedDelegateWrapper wrapper, GClosure* closure) 823 { 824 wrapper.remove(wrapper); 825 } 826 827 protected class OnSelectAllDelegateWrapper 828 { 829 void delegate(ListBox) dlg; 830 gulong handlerId; 831 832 this(void delegate(ListBox) dlg) 833 { 834 this.dlg = dlg; 835 onSelectAllListeners ~= this; 836 } 837 838 void remove(OnSelectAllDelegateWrapper source) 839 { 840 foreach(index, wrapper; onSelectAllListeners) 841 { 842 if (wrapper.handlerId == source.handlerId) 843 { 844 onSelectAllListeners[index] = null; 845 onSelectAllListeners = std.algorithm.remove(onSelectAllListeners, index); 846 break; 847 } 848 } 849 } 850 } 851 OnSelectAllDelegateWrapper[] onSelectAllListeners; 852 853 /** 854 * The ::select-all signal is a [keybinding signal][GtkBindingSignal] 855 * which gets emitted to select all children of the box, if the selection 856 * mode permits it. 857 * 858 * The default bindings for this signal is Ctrl-a. 859 * 860 * Since: 3.14 861 */ 862 gulong addOnSelectAll(void delegate(ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 863 { 864 auto wrapper = new OnSelectAllDelegateWrapper(dlg); 865 wrapper.handlerId = Signals.connectData( 866 this, 867 "select-all", 868 cast(GCallback)&callBackSelectAll, 869 cast(void*)wrapper, 870 cast(GClosureNotify)&callBackSelectAllDestroy, 871 connectFlags); 872 return wrapper.handlerId; 873 } 874 875 extern(C) static void callBackSelectAll(GtkListBox* listboxStruct, OnSelectAllDelegateWrapper wrapper) 876 { 877 wrapper.dlg(wrapper.outer); 878 } 879 880 extern(C) static void callBackSelectAllDestroy(OnSelectAllDelegateWrapper wrapper, GClosure* closure) 881 { 882 wrapper.remove(wrapper); 883 } 884 885 protected class OnSelectedRowsChangedDelegateWrapper 886 { 887 void delegate(ListBox) dlg; 888 gulong handlerId; 889 890 this(void delegate(ListBox) dlg) 891 { 892 this.dlg = dlg; 893 onSelectedRowsChangedListeners ~= this; 894 } 895 896 void remove(OnSelectedRowsChangedDelegateWrapper source) 897 { 898 foreach(index, wrapper; onSelectedRowsChangedListeners) 899 { 900 if (wrapper.handlerId == source.handlerId) 901 { 902 onSelectedRowsChangedListeners[index] = null; 903 onSelectedRowsChangedListeners = std.algorithm.remove(onSelectedRowsChangedListeners, index); 904 break; 905 } 906 } 907 } 908 } 909 OnSelectedRowsChangedDelegateWrapper[] onSelectedRowsChangedListeners; 910 911 /** 912 * The ::selected-rows-changed signal is emitted when the 913 * set of selected rows changes. 914 * 915 * Since: 3.14 916 */ 917 gulong addOnSelectedRowsChanged(void delegate(ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 918 { 919 auto wrapper = new OnSelectedRowsChangedDelegateWrapper(dlg); 920 wrapper.handlerId = Signals.connectData( 921 this, 922 "selected-rows-changed", 923 cast(GCallback)&callBackSelectedRowsChanged, 924 cast(void*)wrapper, 925 cast(GClosureNotify)&callBackSelectedRowsChangedDestroy, 926 connectFlags); 927 return wrapper.handlerId; 928 } 929 930 extern(C) static void callBackSelectedRowsChanged(GtkListBox* listboxStruct, OnSelectedRowsChangedDelegateWrapper wrapper) 931 { 932 wrapper.dlg(wrapper.outer); 933 } 934 935 extern(C) static void callBackSelectedRowsChangedDestroy(OnSelectedRowsChangedDelegateWrapper wrapper, GClosure* closure) 936 { 937 wrapper.remove(wrapper); 938 } 939 940 protected class OnToggleCursorRowDelegateWrapper 941 { 942 void delegate(ListBox) dlg; 943 gulong handlerId; 944 945 this(void delegate(ListBox) dlg) 946 { 947 this.dlg = dlg; 948 onToggleCursorRowListeners ~= this; 949 } 950 951 void remove(OnToggleCursorRowDelegateWrapper source) 952 { 953 foreach(index, wrapper; onToggleCursorRowListeners) 954 { 955 if (wrapper.handlerId == source.handlerId) 956 { 957 onToggleCursorRowListeners[index] = null; 958 onToggleCursorRowListeners = std.algorithm.remove(onToggleCursorRowListeners, index); 959 break; 960 } 961 } 962 } 963 } 964 OnToggleCursorRowDelegateWrapper[] onToggleCursorRowListeners; 965 966 /** */ 967 gulong addOnToggleCursorRow(void delegate(ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 968 { 969 auto wrapper = new OnToggleCursorRowDelegateWrapper(dlg); 970 wrapper.handlerId = Signals.connectData( 971 this, 972 "toggle-cursor-row", 973 cast(GCallback)&callBackToggleCursorRow, 974 cast(void*)wrapper, 975 cast(GClosureNotify)&callBackToggleCursorRowDestroy, 976 connectFlags); 977 return wrapper.handlerId; 978 } 979 980 extern(C) static void callBackToggleCursorRow(GtkListBox* listboxStruct, OnToggleCursorRowDelegateWrapper wrapper) 981 { 982 wrapper.dlg(wrapper.outer); 983 } 984 985 extern(C) static void callBackToggleCursorRowDestroy(OnToggleCursorRowDelegateWrapper wrapper, GClosure* closure) 986 { 987 wrapper.remove(wrapper); 988 } 989 990 protected class OnUnselectAllDelegateWrapper 991 { 992 void delegate(ListBox) dlg; 993 gulong handlerId; 994 995 this(void delegate(ListBox) dlg) 996 { 997 this.dlg = dlg; 998 onUnselectAllListeners ~= this; 999 } 1000 1001 void remove(OnUnselectAllDelegateWrapper source) 1002 { 1003 foreach(index, wrapper; onUnselectAllListeners) 1004 { 1005 if (wrapper.handlerId == source.handlerId) 1006 { 1007 onUnselectAllListeners[index] = null; 1008 onUnselectAllListeners = std.algorithm.remove(onUnselectAllListeners, index); 1009 break; 1010 } 1011 } 1012 } 1013 } 1014 OnUnselectAllDelegateWrapper[] onUnselectAllListeners; 1015 1016 /** 1017 * The ::unselect-all signal is a [keybinding signal][GtkBindingSignal] 1018 * which gets emitted to unselect all children of the box, if the selection 1019 * mode permits it. 1020 * 1021 * The default bindings for this signal is Ctrl-Shift-a. 1022 * 1023 * Since: 3.14 1024 */ 1025 gulong addOnUnselectAll(void delegate(ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 1026 { 1027 auto wrapper = new OnUnselectAllDelegateWrapper(dlg); 1028 wrapper.handlerId = Signals.connectData( 1029 this, 1030 "unselect-all", 1031 cast(GCallback)&callBackUnselectAll, 1032 cast(void*)wrapper, 1033 cast(GClosureNotify)&callBackUnselectAllDestroy, 1034 connectFlags); 1035 return wrapper.handlerId; 1036 } 1037 1038 extern(C) static void callBackUnselectAll(GtkListBox* listboxStruct, OnUnselectAllDelegateWrapper wrapper) 1039 { 1040 wrapper.dlg(wrapper.outer); 1041 } 1042 1043 extern(C) static void callBackUnselectAllDestroy(OnUnselectAllDelegateWrapper wrapper, GClosure* closure) 1044 { 1045 wrapper.remove(wrapper); 1046 } 1047 }