xref: /haiku/src/kits/interface/Spinner.cpp (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
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 
20 static 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 
79 BSpinner::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 
88 BSpinner::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 
97 BSpinner::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 	if (data->FindInt32("_val", &fValue) != B_OK)
110 		fValue = 0;
111 }
112 
113 
114 BSpinner::~BSpinner()
115 {
116 }
117 
118 
119 BArchivable*
120 BSpinner::Instantiate(BMessage* data)
121 {
122 	if (validate_instantiation(data, "Spinner"))
123 		return new BSpinner(data);
124 
125 	return NULL;
126 }
127 
128 
129 status_t
130 BSpinner::Archive(BMessage* data, bool deep) const
131 {
132 	status_t status = BAbstractSpinner::Archive(data, deep);
133 	data->AddString("class", "Spinner");
134 
135 	if (status == B_OK)
136 		status = data->AddInt32("_min", fMinValue);
137 
138 	if (status == B_OK)
139 		status = data->AddInt32("_max", fMaxValue);
140 
141 	if (status == B_OK)
142 		status = data->AddInt32("_val", fValue);
143 
144 	return status;
145 }
146 
147 
148 status_t
149 BSpinner::GetSupportedSuites(BMessage* message)
150 {
151 	message->AddString("suites", "suite/vnd.Haiku-intenger-spinner");
152 
153 	BPropertyInfo prop_info(sProperties);
154 	message->AddFlat("messages", &prop_info);
155 
156 	return BView::GetSupportedSuites(message);
157 }
158 
159 
160 void
161 BSpinner::AttachedToWindow()
162 {
163 	SetValue(fValue);
164 
165 	BAbstractSpinner::AttachedToWindow();
166 }
167 
168 
169 void
170 BSpinner::Decrement()
171 {
172 	SetValue(Value() - 1);
173 }
174 
175 
176 void
177 BSpinner::Increment()
178 {
179 	SetValue(Value() + 1);
180 }
181 
182 
183 void
184 BSpinner::SetEnabled(bool enable)
185 {
186 	if (IsEnabled() == enable)
187 		return;
188 
189 	SetIncrementEnabled(enable && Value() < fMaxValue);
190 	SetDecrementEnabled(enable && Value() > fMinValue);
191 
192 	BAbstractSpinner::SetEnabled(enable);
193 }
194 
195 
196 void
197 BSpinner::SetMinValue(int32 min)
198 {
199 	fMinValue = min;
200 	if (fValue < fMinValue)
201 		SetValue(fMinValue);
202 }
203 
204 
205 void
206 BSpinner::SetMaxValue(int32 max)
207 {
208 	fMaxValue = max;
209 	if (fValue > fMaxValue)
210 		SetValue(fMaxValue);
211 }
212 
213 
214 void
215 BSpinner::Range(int32* min, int32* max)
216 {
217 	*min = fMinValue;
218 	*max = fMaxValue;
219 }
220 
221 
222 void
223 BSpinner::SetRange(int32 min, int32 max)
224 {
225 	SetMinValue(min);
226 	SetMaxValue(max);
227 }
228 
229 
230 void
231 BSpinner::SetValue(int32 value)
232 {
233 	// clip to range
234 	if (value < fMinValue)
235 		value = fMinValue;
236 	else if (value > fMaxValue)
237 		value = fMaxValue;
238 
239 	// update the text view
240 	BString valueString;
241 	valueString << value;
242 	TextView()->SetText(valueString.String());
243 
244 	// update the up and down arrows
245 	SetIncrementEnabled(IsEnabled() && value < fMaxValue);
246 	SetDecrementEnabled(IsEnabled() && value > fMinValue);
247 
248 	if (value == fValue)
249 		return;
250 
251 	fValue = value;
252 	ValueChanged();
253 
254 	Invoke();
255 	Invalidate();
256 }
257 
258 
259 void
260 BSpinner::SetValueFromText()
261 {
262 	SetValue(atol(TextView()->Text()));
263 }
264 
265 
266 //	#pragma mark - BSpinner private methods
267 
268 
269 void
270 BSpinner::_InitObject()
271 {
272 	fMinValue = INT32_MIN;
273 	fMaxValue = INT32_MAX;
274 	fValue = 0;
275 
276 	TextView()->SetAlignment(B_ALIGN_RIGHT);
277 	for (uint32 c = 0; c <= 42; c++)
278 		TextView()->DisallowChar(c);
279 
280 	TextView()->DisallowChar(',');
281 
282 	for (uint32 c = 46; c <= 47; c++)
283 		TextView()->DisallowChar(c);
284 
285 	for (uint32 c = 58; c <= 127; c++)
286 		TextView()->DisallowChar(c);
287 }
288 
289 
290 // FBC padding
291 
292 void BSpinner::_ReservedSpinner20() {}
293 void BSpinner::_ReservedSpinner19() {}
294 void BSpinner::_ReservedSpinner18() {}
295 void BSpinner::_ReservedSpinner17() {}
296 void BSpinner::_ReservedSpinner16() {}
297 void BSpinner::_ReservedSpinner15() {}
298 void BSpinner::_ReservedSpinner14() {}
299 void BSpinner::_ReservedSpinner13() {}
300 void BSpinner::_ReservedSpinner12() {}
301 void BSpinner::_ReservedSpinner11() {}
302 void BSpinner::_ReservedSpinner10() {}
303 void BSpinner::_ReservedSpinner9() {}
304 void BSpinner::_ReservedSpinner8() {}
305 void BSpinner::_ReservedSpinner7() {}
306 void BSpinner::_ReservedSpinner6() {}
307 void BSpinner::_ReservedSpinner5() {}
308 void BSpinner::_ReservedSpinner4() {}
309 void BSpinner::_ReservedSpinner3() {}
310 void BSpinner::_ReservedSpinner2() {}
311 void BSpinner::_ReservedSpinner1() {}
312