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.SpinButton;
26 
27 private import glib.ConstructionException;
28 private import gobject.ObjectG;
29 private import gobject.Signals;
30 private import gtk.Adjustment;
31 private import gtk.Entry;
32 private import gtk.OrientableIF;
33 private import gtk.OrientableT;
34 private import gtk.Widget;
35 private import gtkc.gtk;
36 public  import gtkc.gtktypes;
37 private import std.algorithm;
38 
39 
40 /**
41  * A #GtkSpinButton is an ideal way to allow the user to set the value of
42  * some attribute. Rather than having to directly type a number into a
43  * #GtkEntry, GtkSpinButton allows the user to click on one of two arrows
44  * to increment or decrement the displayed value. A value can still be
45  * typed in, with the bonus that it can be checked to ensure it is in a
46  * given range.
47  * 
48  * The main properties of a GtkSpinButton are through an adjustment.
49  * See the #GtkAdjustment section for more details about an adjustment's
50  * properties. Note that GtkSpinButton will by default make its entry
51  * large enough to accomodate the lower and upper bounds of the adjustment,
52  * which can lead to surprising results. Best practice is to set both
53  * the #GtkEntry:width-chars and #GtkEntry:max-width-chars poperties
54  * to the desired number of characters to display in the entry.
55  * 
56  * # CSS nodes
57  * 
58  * |[<!-- language="plain" -->
59  * spinbutton.horizontal
60  * ├── undershoot.left
61  * ├── undershoot.right
62  * ├── entry
63  * │   ╰── ...
64  * ├── button.down
65  * ╰── button.up
66  * ]|
67  * 
68  * |[<!-- language="plain" -->
69  * spinbutton.vertical
70  * ├── undershoot.left
71  * ├── undershoot.right
72  * ├── button.up
73  * ├── entry
74  * │   ╰── ...
75  * ╰── button.down
76  * ]|
77  * 
78  * GtkSpinButtons main CSS node has the name spinbutton. It creates subnodes
79  * for the entry and the two buttons, with these names. The button nodes have
80  * the style classes .up and .down. The GtkEntry subnodes (if present) are put
81  * below the entry node. The orientation of the spin button is reflected in
82  * the .vertical or .horizontal style class on the main node.
83  * 
84  * ## Using a GtkSpinButton to get an integer
85  * 
86  * |[<!-- language="C" -->
87  * // Provides a function to retrieve an integer value from a GtkSpinButton
88  * // and creates a spin button to model percentage values.
89  * 
90  * gint
91  * grab_int_value (GtkSpinButton *button,
92  * gpointer       user_data)
93  * {
94  * return gtk_spin_button_get_value_as_int (button);
95  * }
96  * 
97  * void
98  * create_integer_spin_button (void)
99  * {
100  * 
101  * GtkWidget *window, *button;
102  * GtkAdjustment *adjustment;
103  * 
104  * adjustment = gtk_adjustment_new (50.0, 0.0, 100.0, 1.0, 5.0, 0.0);
105  * 
106  * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
107  * gtk_container_set_border_width (GTK_CONTAINER (window), 5);
108  * 
109  * // creates the spinbutton, with no decimal places
110  * button = gtk_spin_button_new (adjustment, 1.0, 0);
111  * gtk_container_add (GTK_CONTAINER (window), button);
112  * 
113  * gtk_widget_show_all (window);
114  * }
115  * ]|
116  * 
117  * ## Using a GtkSpinButton to get a floating point value
118  * 
119  * |[<!-- language="C" -->
120  * // Provides a function to retrieve a floating point value from a
121  * // GtkSpinButton, and creates a high precision spin button.
122  * 
123  * gfloat
124  * grab_float_value (GtkSpinButton *button,
125  * gpointer       user_data)
126  * {
127  * return gtk_spin_button_get_value (button);
128  * }
129  * 
130  * void
131  * create_floating_spin_button (void)
132  * {
133  * GtkWidget *window, *button;
134  * GtkAdjustment *adjustment;
135  * 
136  * adjustment = gtk_adjustment_new (2.500, 0.0, 5.0, 0.001, 0.1, 0.0);
137  * 
138  * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
139  * gtk_container_set_border_width (GTK_CONTAINER (window), 5);
140  * 
141  * // creates the spinbutton, with three decimal places
142  * button = gtk_spin_button_new (adjustment, 0.001, 3);
143  * gtk_container_add (GTK_CONTAINER (window), button);
144  * 
145  * gtk_widget_show_all (window);
146  * }
147  * ]|
148  */
149 public class SpinButton : Entry, OrientableIF
150 {
151 	/** the main Gtk struct */
152 	protected GtkSpinButton* gtkSpinButton;
153 
154 	/** Get the main Gtk struct */
155 	public GtkSpinButton* getSpinButtonStruct(bool transferOwnership = false)
156 	{
157 		if (transferOwnership)
158 			ownedRef = false;
159 		return gtkSpinButton;
160 	}
161 
162 	/** the main Gtk struct as a void* */
163 	protected override void* getStruct()
164 	{
165 		return cast(void*)gtkSpinButton;
166 	}
167 
168 	protected override void setStruct(GObject* obj)
169 	{
170 		gtkSpinButton = cast(GtkSpinButton*)obj;
171 		super.setStruct(obj);
172 	}
173 
174 	/**
175 	 * Sets our main struct and passes it to the parent class.
176 	 */
177 	public this (GtkSpinButton* gtkSpinButton, bool ownedRef = false)
178 	{
179 		this.gtkSpinButton = gtkSpinButton;
180 		super(cast(GtkEntry*)gtkSpinButton, ownedRef);
181 	}
182 
183 	// add the Orientable capabilities
184 	mixin OrientableT!(GtkSpinButton);
185 
186 
187 	/** */
188 	public static GType getType()
189 	{
190 		return gtk_spin_button_get_type();
191 	}
192 
193 	/**
194 	 * Creates a new #GtkSpinButton.
195 	 *
196 	 * Params:
197 	 *     adjustment = the #GtkAdjustment object that this spin
198 	 *         button should use, or %NULL
199 	 *     climbRate = specifies how much the spin button changes when an arrow
200 	 *         is clicked on
201 	 *     digits = the number of decimal places to display
202 	 *
203 	 * Returns: The new spin button as a #GtkWidget
204 	 *
205 	 * Throws: ConstructionException GTK+ fails to create the object.
206 	 */
207 	public this(Adjustment adjustment, double climbRate, uint digits)
208 	{
209 		auto p = gtk_spin_button_new((adjustment is null) ? null : adjustment.getAdjustmentStruct(), climbRate, digits);
210 		
211 		if(p is null)
212 		{
213 			throw new ConstructionException("null returned by new");
214 		}
215 		
216 		this(cast(GtkSpinButton*) p);
217 	}
218 
219 	/**
220 	 * This is a convenience constructor that allows creation of a numeric
221 	 * #GtkSpinButton without manually creating an adjustment. The value is
222 	 * initially set to the minimum value and a page increment of 10 * @step
223 	 * is the default. The precision of the spin button is equivalent to the
224 	 * precision of @step.
225 	 *
226 	 * Note that the way in which the precision is derived works best if @step
227 	 * is a power of ten. If the resulting precision is not suitable for your
228 	 * needs, use gtk_spin_button_set_digits() to correct it.
229 	 *
230 	 * Params:
231 	 *     min = Minimum allowable value
232 	 *     max = Maximum allowable value
233 	 *     step = Increment added or subtracted by spinning the widget
234 	 *
235 	 * Returns: The new spin button as a #GtkWidget
236 	 *
237 	 * Throws: ConstructionException GTK+ fails to create the object.
238 	 */
239 	public this(double min, double max, double step)
240 	{
241 		auto p = gtk_spin_button_new_with_range(min, max, step);
242 		
243 		if(p is null)
244 		{
245 			throw new ConstructionException("null returned by new_with_range");
246 		}
247 		
248 		this(cast(GtkSpinButton*) p);
249 	}
250 
251 	/**
252 	 * Changes the properties of an existing spin button. The adjustment,
253 	 * climb rate, and number of decimal places are all changed accordingly,
254 	 * after this function call.
255 	 *
256 	 * Params:
257 	 *     adjustment = a #GtkAdjustment
258 	 *     climbRate = the new climb rate
259 	 *     digits = the number of decimal places to display in the spin button
260 	 */
261 	public void configure(Adjustment adjustment, double climbRate, uint digits)
262 	{
263 		gtk_spin_button_configure(gtkSpinButton, (adjustment is null) ? null : adjustment.getAdjustmentStruct(), climbRate, digits);
264 	}
265 
266 	/**
267 	 * Get the adjustment associated with a #GtkSpinButton
268 	 *
269 	 * Returns: the #GtkAdjustment of @spin_button
270 	 */
271 	public Adjustment getAdjustment()
272 	{
273 		auto p = gtk_spin_button_get_adjustment(gtkSpinButton);
274 		
275 		if(p is null)
276 		{
277 			return null;
278 		}
279 		
280 		return ObjectG.getDObject!(Adjustment)(cast(GtkAdjustment*) p);
281 	}
282 
283 	/**
284 	 * Fetches the precision of @spin_button. See gtk_spin_button_set_digits().
285 	 *
286 	 * Returns: the current precision
287 	 */
288 	public uint getDigits()
289 	{
290 		return gtk_spin_button_get_digits(gtkSpinButton);
291 	}
292 
293 	/**
294 	 * Gets the current step and page the increments used by @spin_button. See
295 	 * gtk_spin_button_set_increments().
296 	 *
297 	 * Params:
298 	 *     step = location to store step increment, or %NULL
299 	 *     page = location to store page increment, or %NULL
300 	 */
301 	public void getIncrements(out double step, out double page)
302 	{
303 		gtk_spin_button_get_increments(gtkSpinButton, &step, &page);
304 	}
305 
306 	/**
307 	 * Returns whether non-numeric text can be typed into the spin button.
308 	 * See gtk_spin_button_set_numeric().
309 	 *
310 	 * Returns: %TRUE if only numeric text can be entered
311 	 */
312 	public bool getNumeric()
313 	{
314 		return gtk_spin_button_get_numeric(gtkSpinButton) != 0;
315 	}
316 
317 	/**
318 	 * Gets the range allowed for @spin_button.
319 	 * See gtk_spin_button_set_range().
320 	 *
321 	 * Params:
322 	 *     min = location to store minimum allowed value, or %NULL
323 	 *     max = location to store maximum allowed value, or %NULL
324 	 */
325 	public void getRange(out double min, out double max)
326 	{
327 		gtk_spin_button_get_range(gtkSpinButton, &min, &max);
328 	}
329 
330 	/**
331 	 * Returns whether the values are corrected to the nearest step.
332 	 * See gtk_spin_button_set_snap_to_ticks().
333 	 *
334 	 * Returns: %TRUE if values are snapped to the nearest step
335 	 */
336 	public bool getSnapToTicks()
337 	{
338 		return gtk_spin_button_get_snap_to_ticks(gtkSpinButton) != 0;
339 	}
340 
341 	/**
342 	 * Gets the update behavior of a spin button.
343 	 * See gtk_spin_button_set_update_policy().
344 	 *
345 	 * Returns: the current update policy
346 	 */
347 	public GtkSpinButtonUpdatePolicy getUpdatePolicy()
348 	{
349 		return gtk_spin_button_get_update_policy(gtkSpinButton);
350 	}
351 
352 	/**
353 	 * Get the value in the @spin_button.
354 	 *
355 	 * Returns: the value of @spin_button
356 	 */
357 	public double getValue()
358 	{
359 		return gtk_spin_button_get_value(gtkSpinButton);
360 	}
361 
362 	/**
363 	 * Get the value @spin_button represented as an integer.
364 	 *
365 	 * Returns: the value of @spin_button
366 	 */
367 	public int getValueAsInt()
368 	{
369 		return gtk_spin_button_get_value_as_int(gtkSpinButton);
370 	}
371 
372 	/**
373 	 * Returns whether the spin button’s value wraps around to the
374 	 * opposite limit when the upper or lower limit of the range is
375 	 * exceeded. See gtk_spin_button_set_wrap().
376 	 *
377 	 * Returns: %TRUE if the spin button wraps around
378 	 */
379 	public bool getWrap()
380 	{
381 		return gtk_spin_button_get_wrap(gtkSpinButton) != 0;
382 	}
383 
384 	/**
385 	 * Replaces the #GtkAdjustment associated with @spin_button.
386 	 *
387 	 * Params:
388 	 *     adjustment = a #GtkAdjustment to replace the existing adjustment
389 	 */
390 	public void setAdjustment(Adjustment adjustment)
391 	{
392 		gtk_spin_button_set_adjustment(gtkSpinButton, (adjustment is null) ? null : adjustment.getAdjustmentStruct());
393 	}
394 
395 	/**
396 	 * Set the precision to be displayed by @spin_button. Up to 20 digit precision
397 	 * is allowed.
398 	 *
399 	 * Params:
400 	 *     digits = the number of digits after the decimal point to be displayed for the spin button’s value
401 	 */
402 	public void setDigits(uint digits)
403 	{
404 		gtk_spin_button_set_digits(gtkSpinButton, digits);
405 	}
406 
407 	/**
408 	 * Sets the step and page increments for spin_button.  This affects how
409 	 * quickly the value changes when the spin button’s arrows are activated.
410 	 *
411 	 * Params:
412 	 *     step = increment applied for a button 1 press.
413 	 *     page = increment applied for a button 2 press.
414 	 */
415 	public void setIncrements(double step, double page)
416 	{
417 		gtk_spin_button_set_increments(gtkSpinButton, step, page);
418 	}
419 
420 	/**
421 	 * Sets the flag that determines if non-numeric text can be typed
422 	 * into the spin button.
423 	 *
424 	 * Params:
425 	 *     numeric = flag indicating if only numeric entry is allowed
426 	 */
427 	public void setNumeric(bool numeric)
428 	{
429 		gtk_spin_button_set_numeric(gtkSpinButton, numeric);
430 	}
431 
432 	/**
433 	 * Sets the minimum and maximum allowable values for @spin_button.
434 	 *
435 	 * If the current value is outside this range, it will be adjusted
436 	 * to fit within the range, otherwise it will remain unchanged.
437 	 *
438 	 * Params:
439 	 *     min = minimum allowable value
440 	 *     max = maximum allowable value
441 	 */
442 	public void setRange(double min, double max)
443 	{
444 		gtk_spin_button_set_range(gtkSpinButton, min, max);
445 	}
446 
447 	/**
448 	 * Sets the policy as to whether values are corrected to the
449 	 * nearest step increment when a spin button is activated after
450 	 * providing an invalid value.
451 	 *
452 	 * Params:
453 	 *     snapToTicks = a flag indicating if invalid values should be corrected
454 	 */
455 	public void setSnapToTicks(bool snapToTicks)
456 	{
457 		gtk_spin_button_set_snap_to_ticks(gtkSpinButton, snapToTicks);
458 	}
459 
460 	/**
461 	 * Sets the update behavior of a spin button.
462 	 * This determines whether the spin button is always updated
463 	 * or only when a valid value is set.
464 	 *
465 	 * Params:
466 	 *     policy = a #GtkSpinButtonUpdatePolicy value
467 	 */
468 	public void setUpdatePolicy(GtkSpinButtonUpdatePolicy policy)
469 	{
470 		gtk_spin_button_set_update_policy(gtkSpinButton, policy);
471 	}
472 
473 	/**
474 	 * Sets the value of @spin_button.
475 	 *
476 	 * Params:
477 	 *     value = the new value
478 	 */
479 	public void setValue(double value)
480 	{
481 		gtk_spin_button_set_value(gtkSpinButton, value);
482 	}
483 
484 	/**
485 	 * Sets the flag that determines if a spin button value wraps
486 	 * around to the opposite limit when the upper or lower limit
487 	 * of the range is exceeded.
488 	 *
489 	 * Params:
490 	 *     wrap = a flag indicating if wrapping behavior is performed
491 	 */
492 	public void setWrap(bool wrap)
493 	{
494 		gtk_spin_button_set_wrap(gtkSpinButton, wrap);
495 	}
496 
497 	/**
498 	 * Increment or decrement a spin button’s value in a specified
499 	 * direction by a specified amount.
500 	 *
501 	 * Params:
502 	 *     direction = a #GtkSpinType indicating the direction to spin
503 	 *     increment = step increment to apply in the specified direction
504 	 */
505 	public void spin(GtkSpinType direction, double increment)
506 	{
507 		gtk_spin_button_spin(gtkSpinButton, direction, increment);
508 	}
509 
510 	/**
511 	 * Manually force an update of the spin button.
512 	 */
513 	public void update()
514 	{
515 		gtk_spin_button_update(gtkSpinButton);
516 	}
517 
518 	protected class OnChangeValueDelegateWrapper
519 	{
520 		static OnChangeValueDelegateWrapper[] listeners;
521 		void delegate(GtkScrollType, SpinButton) dlg;
522 		gulong handlerId;
523 		
524 		this(void delegate(GtkScrollType, SpinButton) dlg)
525 		{
526 			this.dlg = dlg;
527 			this.listeners ~= this;
528 		}
529 		
530 		void remove(OnChangeValueDelegateWrapper source)
531 		{
532 			foreach(index, wrapper; listeners)
533 			{
534 				if (wrapper.handlerId == source.handlerId)
535 				{
536 					listeners[index] = null;
537 					listeners = std.algorithm.remove(listeners, index);
538 					break;
539 				}
540 			}
541 		}
542 	}
543 
544 	/**
545 	 * The ::change-value signal is a [keybinding signal][GtkBindingSignal]
546 	 * which gets emitted when the user initiates a value change.
547 	 *
548 	 * Applications should not connect to it, but may emit it with
549 	 * g_signal_emit_by_name() if they need to control the cursor
550 	 * programmatically.
551 	 *
552 	 * The default bindings for this signal are Up/Down and PageUp and/PageDown.
553 	 *
554 	 * Params:
555 	 *     scroll = a #GtkScrollType to specify the speed and amount of change
556 	 */
557 	gulong addOnChangeValue(void delegate(GtkScrollType, SpinButton) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
558 	{
559 		auto wrapper = new OnChangeValueDelegateWrapper(dlg);
560 		wrapper.handlerId = Signals.connectData(
561 			this,
562 			"change-value",
563 			cast(GCallback)&callBackChangeValue,
564 			cast(void*)wrapper,
565 			cast(GClosureNotify)&callBackChangeValueDestroy,
566 			connectFlags);
567 		return wrapper.handlerId;
568 	}
569 	
570 	extern(C) static void callBackChangeValue(GtkSpinButton* spinbuttonStruct, GtkScrollType scroll, OnChangeValueDelegateWrapper wrapper)
571 	{
572 		wrapper.dlg(scroll, wrapper.outer);
573 	}
574 	
575 	extern(C) static void callBackChangeValueDestroy(OnChangeValueDelegateWrapper wrapper, GClosure* closure)
576 	{
577 		wrapper.remove(wrapper);
578 	}
579 
580 	protected class OnInputDelegateWrapper
581 	{
582 		static OnInputDelegateWrapper[] listeners;
583 		int delegate(void*, SpinButton) dlg;
584 		gulong handlerId;
585 		
586 		this(int delegate(void*, SpinButton) dlg)
587 		{
588 			this.dlg = dlg;
589 			this.listeners ~= this;
590 		}
591 		
592 		void remove(OnInputDelegateWrapper source)
593 		{
594 			foreach(index, wrapper; listeners)
595 			{
596 				if (wrapper.handlerId == source.handlerId)
597 				{
598 					listeners[index] = null;
599 					listeners = std.algorithm.remove(listeners, index);
600 					break;
601 				}
602 			}
603 		}
604 	}
605 
606 	/**
607 	 * The ::input signal can be used to influence the conversion of
608 	 * the users input into a double value. The signal handler is
609 	 * expected to use gtk_entry_get_text() to retrieve the text of
610 	 * the entry and set @new_value to the new value.
611 	 *
612 	 * The default conversion uses g_strtod().
613 	 *
614 	 * Params:
615 	 *     newValue = return location for the new value
616 	 *
617 	 * Returns: %TRUE for a successful conversion, %FALSE if the input
618 	 *     was not handled, and %GTK_INPUT_ERROR if the conversion failed.
619 	 */
620 	gulong addOnInput(int delegate(void*, SpinButton) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
621 	{
622 		auto wrapper = new OnInputDelegateWrapper(dlg);
623 		wrapper.handlerId = Signals.connectData(
624 			this,
625 			"input",
626 			cast(GCallback)&callBackInput,
627 			cast(void*)wrapper,
628 			cast(GClosureNotify)&callBackInputDestroy,
629 			connectFlags);
630 		return wrapper.handlerId;
631 	}
632 	
633 	extern(C) static int callBackInput(GtkSpinButton* spinbuttonStruct, void* newValue, OnInputDelegateWrapper wrapper)
634 	{
635 		return wrapper.dlg(newValue, wrapper.outer);
636 	}
637 	
638 	extern(C) static void callBackInputDestroy(OnInputDelegateWrapper wrapper, GClosure* closure)
639 	{
640 		wrapper.remove(wrapper);
641 	}
642 
643 	protected class OnOutputDelegateWrapper
644 	{
645 		static OnOutputDelegateWrapper[] listeners;
646 		bool delegate(SpinButton) dlg;
647 		gulong handlerId;
648 		
649 		this(bool delegate(SpinButton) dlg)
650 		{
651 			this.dlg = dlg;
652 			this.listeners ~= this;
653 		}
654 		
655 		void remove(OnOutputDelegateWrapper source)
656 		{
657 			foreach(index, wrapper; listeners)
658 			{
659 				if (wrapper.handlerId == source.handlerId)
660 				{
661 					listeners[index] = null;
662 					listeners = std.algorithm.remove(listeners, index);
663 					break;
664 				}
665 			}
666 		}
667 	}
668 
669 	/**
670 	 * The ::output signal can be used to change to formatting
671 	 * of the value that is displayed in the spin buttons entry.
672 	 * |[<!-- language="C" -->
673 	 * // show leading zeros
674 	 * static gboolean
675 	 * on_output (GtkSpinButton *spin,
676 	 * gpointer       data)
677 	 * {
678 	 * GtkAdjustment *adjustment;
679 	 * gchar *text;
680 	 * int value;
681 	 *
682 	 * adjustment = gtk_spin_button_get_adjustment (spin);
683 	 * value = (int)gtk_adjustment_get_value (adjustment);
684 	 * text = g_strdup_printf ("%02d", value);
685 	 * gtk_entry_set_text (GTK_ENTRY (spin), text);
686 	 * g_free (text);
687 	 *
688 	 * return TRUE;
689 	 * }
690 	 * ]|
691 	 *
692 	 * Returns: %TRUE if the value has been displayed
693 	 */
694 	gulong addOnOutput(bool delegate(SpinButton) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
695 	{
696 		auto wrapper = new OnOutputDelegateWrapper(dlg);
697 		wrapper.handlerId = Signals.connectData(
698 			this,
699 			"output",
700 			cast(GCallback)&callBackOutput,
701 			cast(void*)wrapper,
702 			cast(GClosureNotify)&callBackOutputDestroy,
703 			connectFlags);
704 		return wrapper.handlerId;
705 	}
706 	
707 	extern(C) static int callBackOutput(GtkSpinButton* spinbuttonStruct, OnOutputDelegateWrapper wrapper)
708 	{
709 		return wrapper.dlg(wrapper.outer);
710 	}
711 	
712 	extern(C) static void callBackOutputDestroy(OnOutputDelegateWrapper wrapper, GClosure* closure)
713 	{
714 		wrapper.remove(wrapper);
715 	}
716 
717 	protected class OnValueChangedDelegateWrapper
718 	{
719 		static OnValueChangedDelegateWrapper[] listeners;
720 		void delegate(SpinButton) dlg;
721 		gulong handlerId;
722 		
723 		this(void delegate(SpinButton) dlg)
724 		{
725 			this.dlg = dlg;
726 			this.listeners ~= this;
727 		}
728 		
729 		void remove(OnValueChangedDelegateWrapper source)
730 		{
731 			foreach(index, wrapper; listeners)
732 			{
733 				if (wrapper.handlerId == source.handlerId)
734 				{
735 					listeners[index] = null;
736 					listeners = std.algorithm.remove(listeners, index);
737 					break;
738 				}
739 			}
740 		}
741 	}
742 
743 	/**
744 	 * The ::value-changed signal is emitted when the value represented by
745 	 * @spinbutton changes. Also see the #GtkSpinButton::output signal.
746 	 */
747 	gulong addOnValueChanged(void delegate(SpinButton) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
748 	{
749 		auto wrapper = new OnValueChangedDelegateWrapper(dlg);
750 		wrapper.handlerId = Signals.connectData(
751 			this,
752 			"value-changed",
753 			cast(GCallback)&callBackValueChanged,
754 			cast(void*)wrapper,
755 			cast(GClosureNotify)&callBackValueChangedDestroy,
756 			connectFlags);
757 		return wrapper.handlerId;
758 	}
759 	
760 	extern(C) static void callBackValueChanged(GtkSpinButton* spinbuttonStruct, OnValueChangedDelegateWrapper wrapper)
761 	{
762 		wrapper.dlg(wrapper.outer);
763 	}
764 	
765 	extern(C) static void callBackValueChangedDestroy(OnValueChangedDelegateWrapper wrapper, GClosure* closure)
766 	{
767 		wrapper.remove(wrapper);
768 	}
769 
770 	protected class OnWrappedDelegateWrapper
771 	{
772 		static OnWrappedDelegateWrapper[] listeners;
773 		void delegate(SpinButton) dlg;
774 		gulong handlerId;
775 		
776 		this(void delegate(SpinButton) dlg)
777 		{
778 			this.dlg = dlg;
779 			this.listeners ~= this;
780 		}
781 		
782 		void remove(OnWrappedDelegateWrapper source)
783 		{
784 			foreach(index, wrapper; listeners)
785 			{
786 				if (wrapper.handlerId == source.handlerId)
787 				{
788 					listeners[index] = null;
789 					listeners = std.algorithm.remove(listeners, index);
790 					break;
791 				}
792 			}
793 		}
794 	}
795 
796 	/**
797 	 * The ::wrapped signal is emitted right after the spinbutton wraps
798 	 * from its maximum to minimum value or vice-versa.
799 	 *
800 	 * Since: 2.10
801 	 */
802 	gulong addOnWrapped(void delegate(SpinButton) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
803 	{
804 		auto wrapper = new OnWrappedDelegateWrapper(dlg);
805 		wrapper.handlerId = Signals.connectData(
806 			this,
807 			"wrapped",
808 			cast(GCallback)&callBackWrapped,
809 			cast(void*)wrapper,
810 			cast(GClosureNotify)&callBackWrappedDestroy,
811 			connectFlags);
812 		return wrapper.handlerId;
813 	}
814 	
815 	extern(C) static void callBackWrapped(GtkSpinButton* spinbuttonStruct, OnWrappedDelegateWrapper wrapper)
816 	{
817 		wrapper.dlg(wrapper.outer);
818 	}
819 	
820 	extern(C) static void callBackWrappedDestroy(OnWrappedDelegateWrapper wrapper, GClosure* closure)
821 	{
822 		wrapper.remove(wrapper);
823 	}
824 }