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