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