1/*
2 * Copyright 2015 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT license.
4 *
5 * Authors:
6 *		John Scipione, jscipione@gmail.com
7 */
8
9
10#include <Spinner.h>
11
12#include <stdint.h>
13#include <stdlib.h>
14
15#include <PropertyInfo.h>
16#include <String.h>
17#include <TextView.h>
18
19
20static property_info sProperties[] = {
21	{
22		"MaxValue",
23		{ B_GET_PROPERTY, 0 },
24		{ B_DIRECT_SPECIFIER, 0 },
25		"Returns the maximum value of the spinner.",
26		0,
27		{ B_INT32_TYPE }
28	},
29	{
30		"MaxValue",
31		{ B_SET_PROPERTY, 0 },
32		{ B_DIRECT_SPECIFIER, 0},
33		"Sets the maximum value of the spinner.",
34		0,
35		{ B_INT32_TYPE }
36	},
37
38	{
39		"MinValue",
40		{ B_GET_PROPERTY, 0 },
41		{ B_DIRECT_SPECIFIER, 0 },
42		"Returns the minimum value of the spinner.",
43		0,
44		{ B_INT32_TYPE }
45	},
46	{
47		"MinValue",
48		{ B_SET_PROPERTY, 0 },
49		{ B_DIRECT_SPECIFIER, 0},
50		"Sets the minimum value of the spinner.",
51		0,
52		{ B_INT32_TYPE }
53	},
54
55	{
56		"Value",
57		{ B_GET_PROPERTY, 0 },
58		{ B_DIRECT_SPECIFIER, 0 },
59		"Returns the value of the spinner.",
60		0,
61		{ B_INT32_TYPE }
62	},
63	{
64		"Value",
65		{ B_SET_PROPERTY, 0 },
66		{ B_DIRECT_SPECIFIER, 0},
67		"Sets the value of the spinner.",
68		0,
69		{ B_INT32_TYPE }
70	},
71
72	{ 0 }
73};
74
75
76//	#pragma mark - BSpinner
77
78
79BSpinner::BSpinner(BRect frame, const char* name, const char* label,
80	BMessage* message, uint32 resizingMode, uint32 flags)
81	:
82	BAbstractSpinner(frame, name, label, message, resizingMode, flags)
83{
84	_InitObject();
85}
86
87
88BSpinner::BSpinner(const char* name, const char* label,
89	BMessage* message, uint32 flags)
90	:
91	BAbstractSpinner(name, label, message, flags)
92{
93	_InitObject();
94}
95
96
97BSpinner::BSpinner(BMessage* data)
98	:
99	BAbstractSpinner(data)
100{
101	_InitObject();
102
103	if (data->FindInt32("_min", &fMinValue) != B_OK)
104		fMinValue = INT32_MIN;
105
106	if (data->FindInt32("_max", &fMaxValue) != B_OK)
107		fMaxValue = INT32_MAX;
108}
109
110
111BSpinner::~BSpinner()
112{
113}
114
115
116BArchivable*
117BSpinner::Instantiate(BMessage* data)
118{
119	if (validate_instantiation(data, "Spinner"))
120		return new BSpinner(data);
121
122	return NULL;
123}
124
125
126status_t
127BSpinner::Archive(BMessage* data, bool deep) const
128{
129	status_t status = BAbstractSpinner::Archive(data, deep);
130	data->AddString("class", "Spinner");
131
132	if (status == B_OK)
133		status = data->AddInt32("_min", fMinValue);
134
135	if (status == B_OK)
136		status = data->AddInt32("_max", fMaxValue);
137
138	return status;
139}
140
141
142status_t
143BSpinner::GetSupportedSuites(BMessage* message)
144{
145	message->AddString("suites", "suite/vnd.Haiku-intenger-spinner");
146
147	BPropertyInfo prop_info(sProperties);
148	message->AddFlat("messages", &prop_info);
149
150	return BView::GetSupportedSuites(message);
151}
152
153
154void
155BSpinner::AttachedToWindow()
156{
157	SetValue(Value());
158
159	BAbstractSpinner::AttachedToWindow();
160}
161
162
163void
164BSpinner::Decrement()
165{
166	SetValue(Value() - 1);
167}
168
169
170void
171BSpinner::Increment()
172{
173	SetValue(Value() + 1);
174}
175
176
177void
178BSpinner::SetEnabled(bool enable)
179{
180	if (IsEnabled() == enable)
181		return;
182
183	SetIncrementEnabled(enable && Value() < fMaxValue);
184	SetDecrementEnabled(enable && Value() > fMinValue);
185
186	BAbstractSpinner::SetEnabled(enable);
187}
188
189
190void
191BSpinner::SetMinValue(int32 min)
192{
193	fMinValue = min;
194	SetValue(Value());
195}
196
197
198void
199BSpinner::SetMaxValue(int32 max)
200{
201	fMaxValue = max;
202	SetValue(Value());
203}
204
205
206void
207BSpinner::Range(int32* min, int32* max)
208{
209	*min = fMinValue;
210	*max = fMaxValue;
211}
212
213
214void
215BSpinner::SetRange(int32 min, int32 max)
216{
217	SetMinValue(min);
218	SetMaxValue(max);
219}
220
221
222void
223BSpinner::SetValue(int32 value)
224{
225	// clip to range
226	if (value < fMinValue)
227		value = fMinValue;
228	else if (value > fMaxValue)
229		value = fMaxValue;
230
231	// update the text view
232	BString valueString;
233	valueString << value;
234	TextView()->SetText(valueString.String());
235
236	// update the up and down arrows
237	SetIncrementEnabled(IsEnabled() && value < fMaxValue);
238	SetDecrementEnabled(IsEnabled() && value > fMinValue);
239
240	if (value == Value())
241		return;
242
243	BControl::SetValue(value);
244	ValueChanged();
245
246	Invoke();
247	Invalidate();
248}
249
250
251void
252BSpinner::SetValueFromText()
253{
254	SetValue(atol(TextView()->Text()));
255}
256
257
258//	#pragma mark - BSpinner private methods
259
260
261void
262BSpinner::_InitObject()
263{
264	fMinValue = INT32_MIN;
265	fMaxValue = INT32_MAX;
266
267	TextView()->SetAlignment(B_ALIGN_RIGHT);
268	for (uint32 c = 0; c <= 42; c++)
269		TextView()->DisallowChar(c);
270
271	TextView()->DisallowChar(',');
272
273	for (uint32 c = 46; c <= 47; c++)
274		TextView()->DisallowChar(c);
275
276	for (uint32 c = 58; c <= 127; c++)
277		TextView()->DisallowChar(c);
278}
279
280
281// FBC padding
282
283void BSpinner::_ReservedSpinner20() {}
284void BSpinner::_ReservedSpinner19() {}
285void BSpinner::_ReservedSpinner18() {}
286void BSpinner::_ReservedSpinner17() {}
287void BSpinner::_ReservedSpinner16() {}
288void BSpinner::_ReservedSpinner15() {}
289void BSpinner::_ReservedSpinner14() {}
290void BSpinner::_ReservedSpinner13() {}
291void BSpinner::_ReservedSpinner12() {}
292void BSpinner::_ReservedSpinner11() {}
293void BSpinner::_ReservedSpinner10() {}
294void BSpinner::_ReservedSpinner9() {}
295void BSpinner::_ReservedSpinner8() {}
296void BSpinner::_ReservedSpinner7() {}
297void BSpinner::_ReservedSpinner6() {}
298void BSpinner::_ReservedSpinner5() {}
299void BSpinner::_ReservedSpinner4() {}
300void BSpinner::_ReservedSpinner3() {}
301void BSpinner::_ReservedSpinner2() {}
302void BSpinner::_ReservedSpinner1() {}
303