1 // Copyright (C) 2006-2012 Michael Zeilfelder
\r
2 // This file uses the licence of the Irrlicht Engine.
\r
4 #include "CGUISpinBox.h"
\r
5 #ifdef _IRR_COMPILE_WITH_GUI_
\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
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
29 setDebugName("CGUISpinBox");
\r
32 CurrentIconColor = video::SColor(255,255,255,255);
\r
33 s32 ButtonWidth = 16;
\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
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
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
54 EditBox->setSubElement(true);
\r
55 EditBox->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
\r
62 CGUISpinBox::~CGUISpinBox()
\r
65 ButtonSpinUp->drop();
\r
67 ButtonSpinDown->drop();
\r
72 void CGUISpinBox::refreshSprites()
\r
74 IGUISpriteBank *sb = 0;
\r
75 if (Environment && Environment->getSkin())
\r
77 sb = Environment->getSkin()->getSpriteBank();
\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
93 ButtonSpinDown->setText(L"-");
\r
94 ButtonSpinUp->setText(L"+");
\r
98 IGUIEditBox* CGUISpinBox::getEditBox() const
\r
104 void CGUISpinBox::setValue(f32 val)
\r
108 swprintf_irr(str, 99, FormatString.c_str(), val);
\r
109 EditBox->setText(str);
\r
110 verifyValueRange();
\r
114 f32 CGUISpinBox::getValue() const
\r
116 const wchar_t* val = EditBox->getText();
\r
119 core::stringc tmp(val);
\r
120 return core::fast_atof(tmp.c_str());
\r
124 void CGUISpinBox::setRange(f32 min, f32 max)
\r
127 core::swap(min, max);
\r
131 // we have to round the range - otherwise we can get into an infinte setValue/verifyValueRange cycle.
\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
138 verifyValueRange();
\r
142 f32 CGUISpinBox::getMin() const
\r
148 f32 CGUISpinBox::getMax() const
\r
154 f32 CGUISpinBox::getStepSize() const
\r
159 void CGUISpinBox::setStepSize(f32 step)
\r
165 //! Sets the number of decimal places to display.
\r
166 void CGUISpinBox::setDecimalPlaces(s32 places)
\r
168 DecimalPlaces = places;
\r
170 FormatString = "%f";
\r
173 FormatString = "%.";
\r
174 FormatString += places;
\r
175 FormatString += "f";
\r
177 setRange( RangeMin, RangeMax );
\r
178 setValue(getValue());
\r
181 //! Sets when the spinbox has to validate entered text.
\r
182 void CGUISpinBox::setValidateOn(u32 validateOn)
\r
184 ValidateOn = validateOn;
\r
187 //! Gets when the spinbox has to validate entered text.
\r
188 u32 CGUISpinBox::getValidateOn() const
\r
193 bool CGUISpinBox::OnEvent(const SEvent& event)
\r
197 bool changeEvent = false;
\r
198 bool eatEvent = false;
\r
199 switch(event.EventType)
\r
201 case EET_MOUSE_INPUT_EVENT:
\r
202 switch(event.MouseInput.Event)
\r
204 case EMIE_MOUSE_WHEEL:
\r
206 f32 val = getValue() + (StepSize * (event.MouseInput.Wheel < 0 ? -1.f : 1.f));
\r
208 changeEvent = true;
\r
217 case EET_GUI_EVENT:
\r
219 if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED)
\r
221 if (event.GUIEvent.Caller == ButtonSpinUp)
\r
223 f32 val = getValue();
\r
226 changeEvent = true;
\r
228 else if ( event.GUIEvent.Caller == ButtonSpinDown)
\r
230 f32 val = getValue();
\r
233 changeEvent = true;
\r
236 if (event.GUIEvent.Caller == EditBox)
\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
243 verifyValueRange();
\r
244 changeEvent = true;
\r
255 e.EventType = EET_GUI_EVENT;
\r
256 e.GUIEvent.Caller = this;
\r
257 e.GUIEvent.Element = 0;
\r
259 e.GUIEvent.EventType = EGET_SPINBOX_CHANGED;
\r
261 Parent->OnEvent(e);
\r
267 return IGUIElement::OnEvent(event);
\r
271 void CGUISpinBox::draw()
\r
273 if ( !isVisible() )
\r
276 IGUISkin* skin = Environment->getSkin();
\r
280 video::SColor iconColor = skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL);
\r
281 if ( iconColor != CurrentIconColor )
\r
286 IGUISpinBox::draw();
\r
289 void CGUISpinBox::verifyValueRange()
\r
291 f32 val = getValue();
\r
292 if ( val+core::ROUNDING_ERROR_f32 < RangeMin )
\r
294 else if ( val-core::ROUNDING_ERROR_f32 > RangeMax )
\r
303 //! Sets the new caption of the element
\r
304 void CGUISpinBox::setText(const wchar_t* text)
\r
306 EditBox->setText(text);
\r
307 setValue(getValue());
\r
308 verifyValueRange();
\r
312 //! Returns caption of this element.
\r
313 const wchar_t* CGUISpinBox::getText() const
\r
315 return EditBox->getText();
\r
319 //! Writes attributes of the element.
\r
320 void CGUISpinBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
\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
331 //! Reads attributes of the element
\r
332 void CGUISpinBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
\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
342 } // end namespace gui
\r
343 } // end namespace irr
\r
345 #endif // _IRR_COMPILE_WITH_GUI_
\r