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.Scale;
26 
27 private import glib.ConstructionException;
28 private import glib.Str;
29 private import gobject.ObjectG;
30 private import gobject.Signals;
31 private import gtk.Adjustment;
32 private import gtk.Range;
33 private import gtk.Widget;
34 private import gtkc.gtk;
35 public  import gtkc.gtktypes;
36 private import pango.PgLayout;
37 private import std.algorithm;
38 
39 
40 /**
41  * A GtkScale is a slider control used to select a numeric value.
42  * To use it, you’ll probably want to investigate the methods on
43  * its base class, #GtkRange, in addition to the methods for GtkScale itself.
44  * To set the value of a scale, you would normally use gtk_range_set_value().
45  * To detect changes to the value, you would normally use the
46  * #GtkRange::value-changed signal.
47  * 
48  * Note that using the same upper and lower bounds for the #GtkScale (through
49  * the #GtkRange methods) will hide the slider itself. This is useful for
50  * applications that want to show an undeterminate value on the scale, without
51  * changing the layout of the application (such as movie or music players).
52  * 
53  * # GtkScale as GtkBuildable
54  * 
55  * GtkScale supports a custom <marks> element, which can contain multiple
56  * <mark> elements. The “value” and “position” attributes have the same
57  * meaning as gtk_scale_add_mark() parameters of the same name. If the
58  * element is not empty, its content is taken as the markup to show at
59  * the mark. It can be translated with the usual ”translatable” and
60  * “context” attributes.
61  * 
62  * # CSS nodes
63  * 
64  * |[<!-- language="plain" -->
65  * scale[.fine-tune][.marks-before][.marks-after]
66  * ├── marks.top
67  * │   ├── mark
68  * │   ┊    ├── [label]
69  * │   ┊    ╰── indicator
70  * ┊   ┊
71  * │   ╰── mark
72  * ├── [value]
73  * ├── contents
74  * │   ╰── trough
75  * │       ├── slider
76  * │       ├── [highlight]
77  * │       ╰── [fill]
78  * ╰── marks.bottom
79  * ├── mark
80  * ┊    ├── indicator
81  * ┊    ╰── [label]
82  * ╰── mark
83  * ]|
84  * 
85  * GtkScale has a main CSS node with name scale and a subnode for its contents,
86  * with subnodes named trough and slider.
87  * 
88  * The main node gets the style class .fine-tune added when the scale is in
89  * 'fine-tuning' mode.
90  * 
91  * If the scale has an origin (see gtk_scale_set_has_origin()), there is a
92  * subnode with name highlight below the trough node that is used for rendering
93  * the highlighted part of the trough.
94  * 
95  * If the scale is showing a fill level (see gtk_range_set_show_fill_level()),
96  * there is a subnode with name fill below the trough node that is used for
97  * rendering the filled in part of the trough.
98  * 
99  * If marks are present, there is a marks subnode before or after the contents
100  * node, below which each mark gets a node with name mark. The marks nodes get
101  * either the .top or .bottom style class.
102  * 
103  * The mark node has a subnode named indicator. If the mark has text, it also
104  * has a subnode named label. When the mark is either above or left of the
105  * scale, the label subnode is the first when present. Otherwise, the indicator
106  * subnode is the first.
107  * 
108  * The main CSS node gets the 'marks-before' and/or 'marks-after' style classes
109  * added depending on what marks are present.
110  * 
111  * If the scale is displaying the value (see #GtkScale:draw-value), there is
112  * subnode with name value.
113  */
114 public class Scale : Range
115 {
116 	/** the main Gtk struct */
117 	protected GtkScale* gtkScale;
118 
119 	/** Get the main Gtk struct */
120 	public GtkScale* getScaleStruct(bool transferOwnership = false)
121 	{
122 		if (transferOwnership)
123 			ownedRef = false;
124 		return gtkScale;
125 	}
126 
127 	/** the main Gtk struct as a void* */
128 	protected override void* getStruct()
129 	{
130 		return cast(void*)gtkScale;
131 	}
132 
133 	protected override void setStruct(GObject* obj)
134 	{
135 		gtkScale = cast(GtkScale*)obj;
136 		super.setStruct(obj);
137 	}
138 
139 	/**
140 	 * Sets our main struct and passes it to the parent class.
141 	 */
142 	public this (GtkScale* gtkScale, bool ownedRef = false)
143 	{
144 		this.gtkScale = gtkScale;
145 		super(cast(GtkRange*)gtkScale, ownedRef);
146 	}
147 
148 
149 	/** */
150 	public static GType getType()
151 	{
152 		return gtk_scale_get_type();
153 	}
154 
155 	/**
156 	 * Creates a new #GtkScale.
157 	 *
158 	 * Params:
159 	 *     orientation = the scale’s orientation.
160 	 *     adjustment = the #GtkAdjustment which sets the range
161 	 *         of the scale, or %NULL to create a new adjustment.
162 	 *
163 	 * Returns: a new #GtkScale
164 	 *
165 	 * Since: 3.0
166 	 *
167 	 * Throws: ConstructionException GTK+ fails to create the object.
168 	 */
169 	public this(GtkOrientation orientation, Adjustment adjustment)
170 	{
171 		auto p = gtk_scale_new(orientation, (adjustment is null) ? null : adjustment.getAdjustmentStruct());
172 		
173 		if(p is null)
174 		{
175 			throw new ConstructionException("null returned by new");
176 		}
177 		
178 		this(cast(GtkScale*) p);
179 	}
180 
181 	/**
182 	 * Creates a new scale widget with the given orientation that lets the
183 	 * user input a number between @min and @max (including @min and @max)
184 	 * with the increment @step.  @step must be nonzero; it’s the distance
185 	 * the slider moves when using the arrow keys to adjust the scale
186 	 * value.
187 	 *
188 	 * Note that the way in which the precision is derived works best if @step
189 	 * is a power of ten. If the resulting precision is not suitable for your
190 	 * needs, use gtk_scale_set_digits() to correct it.
191 	 *
192 	 * Params:
193 	 *     orientation = the scale’s orientation.
194 	 *     min = minimum value
195 	 *     max = maximum value
196 	 *     step = step increment (tick size) used with keyboard shortcuts
197 	 *
198 	 * Returns: a new #GtkScale
199 	 *
200 	 * Since: 3.0
201 	 *
202 	 * Throws: ConstructionException GTK+ fails to create the object.
203 	 */
204 	public this(GtkOrientation orientation, double min, double max, double step)
205 	{
206 		auto p = gtk_scale_new_with_range(orientation, min, max, step);
207 		
208 		if(p is null)
209 		{
210 			throw new ConstructionException("null returned by new_with_range");
211 		}
212 		
213 		this(cast(GtkScale*) p);
214 	}
215 
216 	/**
217 	 * Adds a mark at @value.
218 	 *
219 	 * A mark is indicated visually by drawing a tick mark next to the scale,
220 	 * and GTK+ makes it easy for the user to position the scale exactly at the
221 	 * marks value.
222 	 *
223 	 * If @markup is not %NULL, text is shown next to the tick mark.
224 	 *
225 	 * To remove marks from a scale, use gtk_scale_clear_marks().
226 	 *
227 	 * Params:
228 	 *     value = the value at which the mark is placed, must be between
229 	 *         the lower and upper limits of the scales’ adjustment
230 	 *     position = where to draw the mark. For a horizontal scale, #GTK_POS_TOP
231 	 *         and %GTK_POS_LEFT are drawn above the scale, anything else below.
232 	 *         For a vertical scale, #GTK_POS_LEFT and %GTK_POS_TOP are drawn to
233 	 *         the left of the scale, anything else to the right.
234 	 *     markup = Text to be shown at the mark, using [Pango markup][PangoMarkupFormat], or %NULL
235 	 *
236 	 * Since: 2.16
237 	 */
238 	public void addMark(double value, GtkPositionType position, string markup)
239 	{
240 		gtk_scale_add_mark(gtkScale, value, position, Str.toStringz(markup));
241 	}
242 
243 	/**
244 	 * Removes any marks that have been added with gtk_scale_add_mark().
245 	 *
246 	 * Since: 2.16
247 	 */
248 	public void clearMarks()
249 	{
250 		gtk_scale_clear_marks(gtkScale);
251 	}
252 
253 	/**
254 	 * Gets the number of decimal places that are displayed in the value.
255 	 *
256 	 * Returns: the number of decimal places that are displayed
257 	 */
258 	public int getDigits()
259 	{
260 		return gtk_scale_get_digits(gtkScale);
261 	}
262 
263 	/**
264 	 * Returns whether the current value is displayed as a string
265 	 * next to the slider.
266 	 *
267 	 * Returns: whether the current value is displayed as a string
268 	 */
269 	public bool getDrawValue()
270 	{
271 		return gtk_scale_get_draw_value(gtkScale) != 0;
272 	}
273 
274 	/**
275 	 * Returns whether the scale has an origin.
276 	 *
277 	 * Returns: %TRUE if the scale has an origin.
278 	 *
279 	 * Since: 3.4
280 	 */
281 	public bool getHasOrigin()
282 	{
283 		return gtk_scale_get_has_origin(gtkScale) != 0;
284 	}
285 
286 	/**
287 	 * Gets the #PangoLayout used to display the scale. The returned
288 	 * object is owned by the scale so does not need to be freed by
289 	 * the caller.
290 	 *
291 	 * Returns: the #PangoLayout for this scale,
292 	 *     or %NULL if the #GtkScale:draw-value property is %FALSE.
293 	 *
294 	 * Since: 2.4
295 	 */
296 	public PgLayout getLayout()
297 	{
298 		auto p = gtk_scale_get_layout(gtkScale);
299 		
300 		if(p is null)
301 		{
302 			return null;
303 		}
304 		
305 		return ObjectG.getDObject!(PgLayout)(cast(PangoLayout*) p);
306 	}
307 
308 	/**
309 	 * Obtains the coordinates where the scale will draw the
310 	 * #PangoLayout representing the text in the scale. Remember
311 	 * when using the #PangoLayout function you need to convert to
312 	 * and from pixels using PANGO_PIXELS() or #PANGO_SCALE.
313 	 *
314 	 * If the #GtkScale:draw-value property is %FALSE, the return
315 	 * values are undefined.
316 	 *
317 	 * Params:
318 	 *     x = location to store X offset of layout, or %NULL
319 	 *     y = location to store Y offset of layout, or %NULL
320 	 *
321 	 * Since: 2.4
322 	 */
323 	public void getLayoutOffsets(out int x, out int y)
324 	{
325 		gtk_scale_get_layout_offsets(gtkScale, &x, &y);
326 	}
327 
328 	/**
329 	 * Gets the position in which the current value is displayed.
330 	 *
331 	 * Returns: the position in which the current value is displayed
332 	 */
333 	public GtkPositionType getValuePos()
334 	{
335 		return gtk_scale_get_value_pos(gtkScale);
336 	}
337 
338 	/**
339 	 * Sets the number of decimal places that are displayed in the value. Also
340 	 * causes the value of the adjustment to be rounded to this number of digits,
341 	 * so the retrieved value matches the displayed one, if #GtkScale:draw-value is
342 	 * %TRUE when the value changes. If you want to enforce rounding the value when
343 	 * #GtkScale:draw-value is %FALSE, you can set #GtkRange:round-digits instead.
344 	 *
345 	 * Note that rounding to a small number of digits can interfere with
346 	 * the smooth autoscrolling that is built into #GtkScale. As an alternative,
347 	 * you can use the #GtkScale::format-value signal to format the displayed
348 	 * value yourself.
349 	 *
350 	 * Params:
351 	 *     digits = the number of decimal places to display,
352 	 *         e.g. use 1 to display 1.0, 2 to display 1.00, etc
353 	 */
354 	public void setDigits(int digits)
355 	{
356 		gtk_scale_set_digits(gtkScale, digits);
357 	}
358 
359 	/**
360 	 * Specifies whether the current value is displayed as a string next
361 	 * to the slider.
362 	 *
363 	 * Params:
364 	 *     drawValue = %TRUE to draw the value
365 	 */
366 	public void setDrawValue(bool drawValue)
367 	{
368 		gtk_scale_set_draw_value(gtkScale, drawValue);
369 	}
370 
371 	/**
372 	 * If #GtkScale:has-origin is set to %TRUE (the default), the scale will
373 	 * highlight the part of the trough between the origin (bottom or left side)
374 	 * and the current value.
375 	 *
376 	 * Params:
377 	 *     hasOrigin = %TRUE if the scale has an origin
378 	 *
379 	 * Since: 3.4
380 	 */
381 	public void setHasOrigin(bool hasOrigin)
382 	{
383 		gtk_scale_set_has_origin(gtkScale, hasOrigin);
384 	}
385 
386 	/**
387 	 * Sets the position in which the current value is displayed.
388 	 *
389 	 * Params:
390 	 *     pos = the position in which the current value is displayed
391 	 */
392 	public void setValuePos(GtkPositionType pos)
393 	{
394 		gtk_scale_set_value_pos(gtkScale, pos);
395 	}
396 
397 	protected class OnFormatValueDelegateWrapper
398 	{
399 		static OnFormatValueDelegateWrapper[] listeners;
400 		string delegate(double, Scale) dlg;
401 		gulong handlerId;
402 		
403 		this(string delegate(double, Scale) dlg)
404 		{
405 			this.dlg = dlg;
406 			this.listeners ~= this;
407 		}
408 		
409 		void remove(OnFormatValueDelegateWrapper source)
410 		{
411 			foreach(index, wrapper; listeners)
412 			{
413 				if (wrapper.handlerId == source.handlerId)
414 				{
415 					listeners[index] = null;
416 					listeners = std.algorithm.remove(listeners, index);
417 					break;
418 				}
419 			}
420 		}
421 	}
422 
423 	/**
424 	 * Signal which allows you to change how the scale value is displayed.
425 	 * Connect a signal handler which returns an allocated string representing
426 	 * @value. That string will then be used to display the scale's value.
427 	 *
428 	 * If no user-provided handlers are installed, the value will be displayed on
429 	 * its own, rounded according to the value of the #GtkScale:digits property.
430 	 *
431 	 * Here's an example signal handler which displays a value 1.0 as
432 	 * with "-->1.0<--".
433 	 * |[<!-- language="C" -->
434 	 * static gchar*
435 	 * format_value_callback (GtkScale *scale,
436 	 * gdouble   value)
437 	 * {
438 	 * return g_strdup_printf ("-->\%0.*g<--",
439 	 * gtk_scale_get_digits (scale), value);
440 	 * }
441 	 * ]|
442 	 *
443 	 * Params:
444 	 *     value = the value to format
445 	 *
446 	 * Returns: allocated string representing @value
447 	 */
448 	gulong addOnFormatValue(string delegate(double, Scale) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
449 	{
450 		auto wrapper = new OnFormatValueDelegateWrapper(dlg);
451 		wrapper.handlerId = Signals.connectData(
452 			this,
453 			"format-value",
454 			cast(GCallback)&callBackFormatValue,
455 			cast(void*)wrapper,
456 			cast(GClosureNotify)&callBackFormatValueDestroy,
457 			connectFlags);
458 		return wrapper.handlerId;
459 	}
460 	
461 	extern(C) static string callBackFormatValue(GtkScale* scaleStruct, double value, OnFormatValueDelegateWrapper wrapper)
462 	{
463 		return wrapper.dlg(value, wrapper.outer);
464 	}
465 	
466 	extern(C) static void callBackFormatValueDestroy(OnFormatValueDelegateWrapper wrapper, GClosure* closure)
467 	{
468 		wrapper.remove(wrapper);
469 	}
470 }