xref: /haiku/src/kits/interface/Spinner.cpp (revision 9c274ccd098ee3b2674efde2d1582d4e0c68d878)
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 
110 
111 BSpinner::~BSpinner()
112 {
113 }
114 
115 
116 BArchivable*
117 BSpinner::Instantiate(BMessage* data)
118 {
119 	if (validate_instantiation(data, "Spinner"))
120 		return new BSpinner(data);
121 
122 	return NULL;
123 }
124 
125 
126 status_t
127 BSpinner::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 
142 status_t
143 BSpinner::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 
154 void
155 BSpinner::AttachedToWindow()
156 {
157 	SetValue(Value());
158 
159 	BAbstractSpinner::AttachedToWindow();
160 }
161 
162 
163 void
164 BSpinner::Decrement()
165 {
166 	SetValue(Value() - 1);
167 }
168 
169 
170 void
171 BSpinner::Increment()
172 {
173 	SetValue(Value() + 1);
174 }
175 
176 
177 void
178 BSpinner::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 
190 void
191 BSpinner::SetMinValue(int32 min)
192 {
193 	fMinValue = min;
194 	SetValue(Value());
195 }
196 
197 
198 void
199 BSpinner::SetMaxValue(int32 max)
200 {
201 	fMaxValue = max;
202 	SetValue(Value());
203 }
204 
205 
206 void
207 BSpinner::Range(int32* min, int32* max)
208 {
209 	*min = fMinValue;
210 	*max = fMaxValue;
211 }
212 
213 
214 void
215 BSpinner::SetRange(int32 min, int32 max)
216 {
217 	SetMinValue(min);
218 	SetMaxValue(max);
219 }
220 
221 
222 void
223 BSpinner::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 
251 void
252 BSpinner::SetValueFromText()
253 {
254 	SetValue(atol(TextView()->Text()));
255 }
256 
257 
258 //	#pragma mark - BSpinner private methods
259 
260 
261 void
262 BSpinner::_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 
283 void BSpinner::_ReservedSpinner20() {}
284 void BSpinner::_ReservedSpinner19() {}
285 void BSpinner::_ReservedSpinner18() {}
286 void BSpinner::_ReservedSpinner17() {}
287 void BSpinner::_ReservedSpinner16() {}
288 void BSpinner::_ReservedSpinner15() {}
289 void BSpinner::_ReservedSpinner14() {}
290 void BSpinner::_ReservedSpinner13() {}
291 void BSpinner::_ReservedSpinner12() {}
292 void BSpinner::_ReservedSpinner11() {}
293 void BSpinner::_ReservedSpinner10() {}
294 void BSpinner::_ReservedSpinner9() {}
295 void BSpinner::_ReservedSpinner8() {}
296 void BSpinner::_ReservedSpinner7() {}
297 void BSpinner::_ReservedSpinner6() {}
298 void BSpinner::_ReservedSpinner5() {}
299 void BSpinner::_ReservedSpinner4() {}
300 void BSpinner::_ReservedSpinner3() {}
301 void BSpinner::_ReservedSpinner2() {}
302 void BSpinner::_ReservedSpinner1() {}
303