]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/CGUISpinBox.cpp
Fix some more problems with OSX build file.
[irrlicht.git] / source / Irrlicht / CGUISpinBox.cpp
1 // Copyright (C) 2006-2012 Michael Zeilfelder\r
2 // This file uses the licence of the Irrlicht Engine.\r
3 \r
4 #include "CGUISpinBox.h"\r
5 #ifdef _IRR_COMPILE_WITH_GUI_\r
6 \r
7 #include "CGUIEditBox.h"\r
8 #include "CGUIButton.h"\r
9 #include "IGUIEnvironment.h"\r
10 #include "IEventReceiver.h"\r
11 #include "fast_atof.h"\r
12 #include <wchar.h>\r
13 \r
14 \r
15 namespace irr\r
16 {\r
17 namespace gui\r
18 {\r
19 \r
20 //! constructor\r
21 CGUISpinBox::CGUISpinBox(const wchar_t* text, bool border,IGUIEnvironment* environment,\r
22                         IGUIElement* parent, s32 id, const core::rect<s32>& rectangle)\r
23 : IGUISpinBox(environment, parent, id, rectangle),\r
24         EditBox(0), ButtonSpinUp(0), ButtonSpinDown(0), StepSize(1.f),\r
25         RangeMin(-FLT_MAX), RangeMax(FLT_MAX), FormatString(L"%f"),\r
26         DecimalPlaces(-1), ValidateOn(EGUI_SBV_ENTER|EGUI_SBV_LOSE_FOCUS)\r
27 {\r
28         #ifdef _DEBUG\r
29         setDebugName("CGUISpinBox");\r
30         #endif\r
31 \r
32         CurrentIconColor = video::SColor(255,255,255,255);\r
33         s32 ButtonWidth = 16;\r
34 \r
35         ButtonSpinDown = Environment->addButton(\r
36                 core::rect<s32>(rectangle.getWidth() - ButtonWidth, rectangle.getHeight()/2 +1,\r
37                                                 rectangle.getWidth(), rectangle.getHeight()), this);\r
38         ButtonSpinDown->grab();\r
39         ButtonSpinDown->setSubElement(true);\r
40         ButtonSpinDown->setTabStop(false);\r
41         ButtonSpinDown->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_CENTER, EGUIA_LOWERRIGHT);\r
42 \r
43         ButtonSpinUp = Environment->addButton(\r
44                 core::rect<s32>(rectangle.getWidth() - ButtonWidth, 0,\r
45                                                 rectangle.getWidth(), rectangle.getHeight()/2), this);\r
46         ButtonSpinUp->grab();\r
47         ButtonSpinUp->setSubElement(true);\r
48         ButtonSpinUp->setTabStop(false);\r
49         ButtonSpinUp->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_CENTER);\r
50 \r
51         const core::rect<s32> rectEdit(0, 0, rectangle.getWidth() - ButtonWidth - 1, rectangle.getHeight());\r
52         EditBox = Environment->addEditBox(text, rectEdit, border, this, -1);\r
53         EditBox->grab();\r
54         EditBox->setSubElement(true);\r
55         EditBox->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);\r
56 \r
57         refreshSprites();\r
58 }\r
59 \r
60 \r
61 //! destructor\r
62 CGUISpinBox::~CGUISpinBox()\r
63 {\r
64         if (ButtonSpinUp)\r
65                 ButtonSpinUp->drop();\r
66         if (ButtonSpinDown)\r
67                 ButtonSpinDown->drop();\r
68         if (EditBox)\r
69                 EditBox->drop();\r
70 }\r
71 \r
72 void CGUISpinBox::refreshSprites()\r
73 {\r
74         IGUISpriteBank *sb = 0;\r
75         if (Environment && Environment->getSkin())\r
76         {\r
77                 sb = Environment->getSkin()->getSpriteBank();\r
78         }\r
79 \r
80         if (sb)\r
81         {\r
82                 IGUISkin * skin = Environment->getSkin();\r
83                 CurrentIconColor = skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL);\r
84                 ButtonSpinDown->setSpriteBank(sb);\r
85                 ButtonSpinDown->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_SMALL_CURSOR_DOWN), CurrentIconColor);\r
86                 ButtonSpinDown->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_SMALL_CURSOR_DOWN), CurrentIconColor);\r
87                 ButtonSpinUp->setSpriteBank(sb);\r
88                 ButtonSpinUp->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_SMALL_CURSOR_UP), CurrentIconColor);\r
89                 ButtonSpinUp->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_SMALL_CURSOR_UP), CurrentIconColor);\r
90         }\r
91         else\r
92         {\r
93                 ButtonSpinDown->setText(L"-");\r
94                 ButtonSpinUp->setText(L"+");\r
95         }\r
96 }\r
97 \r
98 IGUIEditBox* CGUISpinBox::getEditBox() const\r
99 {\r
100         return EditBox;\r
101 }\r
102 \r
103 \r
104 void CGUISpinBox::setValue(f32 val)\r
105 {\r
106         wchar_t str[100];\r
107 \r
108         swprintf_irr(str, 99, FormatString.c_str(), val);\r
109         EditBox->setText(str);\r
110         verifyValueRange();\r
111 }\r
112 \r
113 \r
114 f32 CGUISpinBox::getValue() const\r
115 {\r
116         const wchar_t* val = EditBox->getText();\r
117         if ( !val )\r
118                 return 0.f;\r
119         core::stringc tmp(val);\r
120         return core::fast_atof(tmp.c_str());\r
121 }\r
122 \r
123 \r
124 void CGUISpinBox::setRange(f32 min, f32 max)\r
125 {\r
126         if (max<min)\r
127                 core::swap(min, max);\r
128         RangeMin = min;\r
129         RangeMax = max;\r
130 \r
131         // we have to round the range - otherwise we can get into an infinte setValue/verifyValueRange cycle.\r
132         wchar_t str[100];\r
133         swprintf_irr(str, 99, FormatString.c_str(), RangeMin);\r
134         RangeMin = core::fast_atof(core::stringc(str).c_str());\r
135         swprintf_irr(str, 99, FormatString.c_str(), RangeMax);\r
136         RangeMax = core::fast_atof(core::stringc(str).c_str());\r
137 \r
138         verifyValueRange();\r
139 }\r
140 \r
141 \r
142 f32 CGUISpinBox::getMin() const\r
143 {\r
144         return RangeMin;\r
145 }\r
146 \r
147 \r
148 f32 CGUISpinBox::getMax() const\r
149 {\r
150         return RangeMax;\r
151 }\r
152 \r
153 \r
154 f32 CGUISpinBox::getStepSize() const\r
155 {\r
156         return StepSize;\r
157 }\r
158 \r
159 void CGUISpinBox::setStepSize(f32 step)\r
160 {\r
161         StepSize = step;\r
162 }\r
163 \r
164 \r
165 //! Sets the number of decimal places to display.\r
166 void CGUISpinBox::setDecimalPlaces(s32 places)\r
167 {\r
168         DecimalPlaces = places;\r
169         if (places == -1)\r
170                 FormatString = "%f";\r
171         else\r
172         {\r
173                 FormatString = "%.";\r
174                 FormatString += places;\r
175                 FormatString += "f";\r
176         }\r
177         setRange( RangeMin, RangeMax );\r
178         setValue(getValue());\r
179 }\r
180 \r
181 //! Sets when the spinbox has to validate entered text.\r
182 void CGUISpinBox::setValidateOn(u32 validateOn)\r
183 {\r
184         ValidateOn = validateOn;\r
185 }\r
186 \r
187 //! Gets when the spinbox has to validate entered text.\r
188 u32 CGUISpinBox::getValidateOn() const\r
189 {\r
190         return ValidateOn;\r
191 }\r
192 \r
193 bool CGUISpinBox::OnEvent(const SEvent& event)\r
194 {\r
195         if (IsEnabled)\r
196         {\r
197                 bool changeEvent = false;\r
198                 bool eatEvent = false;\r
199                 switch(event.EventType)\r
200                 {\r
201                 case EET_MOUSE_INPUT_EVENT:\r
202                         switch(event.MouseInput.Event)\r
203                         {\r
204                         case EMIE_MOUSE_WHEEL:\r
205                                 {\r
206                                         f32 val = getValue() + (StepSize * (event.MouseInput.Wheel < 0 ? -1.f : 1.f));\r
207                                         setValue(val);\r
208                                         changeEvent = true;\r
209                                         eatEvent = true;\r
210                                 }\r
211                                 break;\r
212                         default:\r
213                                 break;\r
214                         }\r
215                         break;\r
216 \r
217                 case EET_GUI_EVENT:\r
218 \r
219                         if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED)\r
220                         {\r
221                                 if (event.GUIEvent.Caller == ButtonSpinUp)\r
222                                 {\r
223                                         f32 val = getValue();\r
224                                         val += StepSize;\r
225                                         setValue(val);\r
226                                         changeEvent = true;\r
227                                 }\r
228                                 else if ( event.GUIEvent.Caller == ButtonSpinDown)\r
229                                 {\r
230                                         f32 val = getValue();\r
231                                         val -= StepSize;\r
232                                         setValue(val);\r
233                                         changeEvent = true;\r
234                                 }\r
235                         }\r
236                         if (event.GUIEvent.Caller == EditBox)\r
237                         {\r
238                                 if (    (event.GUIEvent.EventType == EGET_EDITBOX_CHANGED && ValidateOn & EGUI_SBV_CHANGE)\r
239                                         ||      (event.GUIEvent.EventType == EGET_EDITBOX_ENTER && ValidateOn & EGUI_SBV_ENTER)\r
240                                         ||      (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST && ValidateOn & EGUI_SBV_LOSE_FOCUS)\r
241                                         )\r
242                                 {\r
243                                         verifyValueRange();\r
244                                         changeEvent = true;\r
245                                 }\r
246                         }\r
247                         break;\r
248                 default:\r
249                 break;\r
250                 }\r
251 \r
252                 if ( changeEvent )\r
253                 {\r
254                         SEvent e;\r
255                         e.EventType = EET_GUI_EVENT;\r
256                         e.GUIEvent.Caller = this;\r
257                         e.GUIEvent.Element = 0;\r
258 \r
259                         e.GUIEvent.EventType = EGET_SPINBOX_CHANGED;\r
260                         if ( Parent )\r
261                                 Parent->OnEvent(e);\r
262                         if ( eatEvent )\r
263                                 return true;\r
264                 }\r
265         }\r
266 \r
267         return IGUIElement::OnEvent(event);\r
268 }\r
269 \r
270 \r
271 void CGUISpinBox::draw()\r
272 {\r
273         if ( !isVisible() )\r
274                 return;\r
275 \r
276         IGUISkin* skin = Environment->getSkin();\r
277         if (!skin)\r
278                 return;\r
279 \r
280         video::SColor iconColor = skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL);\r
281         if ( iconColor != CurrentIconColor )\r
282         {\r
283                 refreshSprites();\r
284         }\r
285 \r
286         IGUISpinBox::draw();\r
287 }\r
288 \r
289 void CGUISpinBox::verifyValueRange()\r
290 {\r
291         f32 val = getValue();\r
292         if ( val+core::ROUNDING_ERROR_f32 < RangeMin )\r
293                 val = RangeMin;\r
294         else if ( val-core::ROUNDING_ERROR_f32 > RangeMax )\r
295                 val = RangeMax;\r
296         else\r
297                 return;\r
298 \r
299         setValue(val);\r
300 }\r
301 \r
302 \r
303 //! Sets the new caption of the element\r
304 void CGUISpinBox::setText(const wchar_t* text)\r
305 {\r
306         EditBox->setText(text);\r
307         setValue(getValue());\r
308         verifyValueRange();\r
309 }\r
310 \r
311 \r
312 //! Returns caption of this element.\r
313 const wchar_t* CGUISpinBox::getText() const\r
314 {\r
315         return EditBox->getText();\r
316 }\r
317 \r
318 \r
319 //! Writes attributes of the element.\r
320 void CGUISpinBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const\r
321 {\r
322         IGUIElement::serializeAttributes(out, options);\r
323         out->addFloat("Min", getMin());\r
324         out->addFloat("Max", getMax());\r
325         out->addFloat("Step", getStepSize());\r
326         out->addInt("DecimalPlaces", DecimalPlaces);\r
327         out->addInt("ValidateOn", (s32)ValidateOn);\r
328 }\r
329 \r
330 \r
331 //! Reads attributes of the element\r
332 void CGUISpinBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)\r
333 {\r
334         IGUIElement::deserializeAttributes(in, options);\r
335         setRange(in->getAttributeAsFloat("Min", RangeMin), in->getAttributeAsFloat("Max", RangeMax));\r
336         setStepSize(in->getAttributeAsFloat("Step", StepSize));\r
337         setDecimalPlaces(in->getAttributeAsInt("DecimalPlaces", DecimalPlaces));\r
338         setValidateOn((u32)in->getAttributeAsInt("ValidateOn", (s32)ValidateOn) );\r
339 }\r
340 \r
341 \r
342 } // end namespace gui\r
343 } // end namespace irr\r
344 \r
345 #endif // _IRR_COMPILE_WITH_GUI_\r
346 \r