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