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 }