00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "elements/CEGUISpinner.h"
00025 #include "elements/CEGUIPushButton.h"
00026 #include "elements/CEGUIEditbox.h"
00027 #include "CEGUIExceptions.h"
00028 #include <stdio.h>
00029 #include <sstream>
00030 #include <iomanip>
00031
00032
00033 namespace CEGUI
00034 {
00036
00037 const String Spinner::EventNamespace("Spinner");
00038 const String Spinner::EventValueChanged("ValueChanged");
00039 const String Spinner::EventStepChanged("StepChanged");
00040 const String Spinner::EventMaximumValueChanged("MaximumValueChanged");
00041 const String Spinner::EventMinimumValueChanged("MinimumValueChanged");
00042 const String Spinner::EventTextInputModeChanged("TextInputModeChanged");
00043
00044 const String Spinner::FloatValidator("-?\\d*\\.?\\d*");
00045 const String Spinner::IntegerValidator("-?\\d*");
00046 const String Spinner::HexValidator("[0-9a-fA-F]*");
00047 const String Spinner::OctalValidator("[0-7]*");
00048
00049 SpinnerProperties::CurrentValue Spinner::d_currentValueProperty;
00050 SpinnerProperties::StepSize Spinner::d_stepSizeProperty;
00051 SpinnerProperties::MaximumValue Spinner::d_maxValueProperty;
00052 SpinnerProperties::MinimumValue Spinner::d_minValueProperty;
00053 SpinnerProperties::TextInputMode Spinner::d_textInputModeProperty;
00055
00056 Spinner::Spinner(const String& type, const String& name) :
00057 Window(type, name),
00058 d_increaseButton(0),
00059 d_decreaseButton(0),
00060 d_editbox(0),
00061 d_stepSize(1.0f),
00062 d_currentValue(1.0f),
00063 d_maxValue(32767.0f),
00064 d_minValue(-32768.0f),
00065 d_inputMode((TextInputMode)-1)
00066 {
00067 addSpinnerEvents();
00068 addSpinnerProperties();
00069 }
00070
00071 Spinner::~Spinner(void)
00072 {
00073
00074 }
00075
00076 void Spinner::initialise(void)
00077 {
00078 Window::initialise();
00079
00080
00081 d_increaseButton = createIncreaseButton(getName() + "__auto_incbtn__");
00082 addChildWindow(d_increaseButton);
00083 d_decreaseButton = createDecreaseButton(getName() + "__auto_decbtn__");
00084 addChildWindow(d_decreaseButton);
00085 d_editbox = createEditbox(getName() + "__auto_editbox__");
00086 addChildWindow(d_editbox);
00087
00088
00089 d_increaseButton->setWantsMultiClickEvents(false);
00090 d_increaseButton->setMouseAutoRepeatEnabled(true);
00091 d_decreaseButton->setWantsMultiClickEvents(false);
00092 d_decreaseButton->setMouseAutoRepeatEnabled(true);
00093
00094
00095 d_increaseButton->subscribeEvent(Window::EventMouseButtonDown, Event::Subscriber(&Spinner::handleIncreaseButton, this));
00096 d_decreaseButton->subscribeEvent(Window::EventMouseButtonDown, Event::Subscriber(&Spinner::handleDecreaseButton, this));
00097 d_editbox->subscribeEvent(Window::EventTextChanged, Event::Subscriber(&Spinner::handleEditTextChange, this));
00098
00099
00100 setTextInputMode(Integer);
00101 setCurrentValue(0.0f);
00102 performChildWindowLayout();
00103 }
00104
00105 float Spinner::getCurrentValue(void) const
00106 {
00107 return d_currentValue;
00108 }
00109
00110 float Spinner::getStepSize(void) const
00111 {
00112 return d_stepSize;
00113 }
00114
00115 float Spinner::getMaximumValue(void) const
00116 {
00117 return d_maxValue;
00118 }
00119
00120 float Spinner::getMinimumValue(void) const
00121 {
00122 return d_minValue;
00123 }
00124
00125 Spinner::TextInputMode Spinner::getTextInputMode(void) const
00126 {
00127 return d_inputMode;
00128 }
00129
00130 void Spinner::setCurrentValue(float value)
00131 {
00132 if (value != d_currentValue)
00133 {
00134
00135 value = ceguimax(ceguimin(value, d_maxValue), d_minValue);
00136
00137 d_currentValue = value;
00138
00139 WindowEventArgs args(this);
00140 onValueChanged(args);
00141 }
00142 }
00143
00144 void Spinner::setStepSize(float step)
00145 {
00146 if (step != d_stepSize)
00147 {
00148 d_stepSize = step;
00149
00150 WindowEventArgs args(this);
00151 onStepChanged(args);
00152 }
00153 }
00154
00155 void Spinner::setMaximumValue(float maxValue)
00156 {
00157 if (maxValue != d_maxValue)
00158 {
00159 d_maxValue = maxValue;
00160
00161 WindowEventArgs args(this);
00162 onMaximumValueChanged(args);
00163 }
00164 }
00165
00166 void Spinner::setMinimumValue(float minVaue)
00167 {
00168 if (minVaue != d_minValue)
00169 {
00170 d_minValue = minVaue;
00171
00172 WindowEventArgs args(this);
00173 onMinimumValueChanged(args);
00174 }
00175 }
00176
00177 void Spinner::setTextInputMode(TextInputMode mode)
00178 {
00179 if (mode != d_inputMode)
00180 {
00181 switch (mode)
00182 {
00183 case FloatingPoint:
00184 d_editbox->setValidationString(FloatValidator);
00185 break;
00186 case Integer:
00187 d_editbox->setValidationString(IntegerValidator);
00188 break;
00189 case Hexadecimal:
00190 d_editbox->setValidationString(HexValidator);
00191 break;
00192 case Octal:
00193 d_editbox->setValidationString(OctalValidator);
00194 break;
00195 default:
00196 throw InvalidRequestException("Spinner::setTextInputMode - An unknown TextInputMode was specified.");
00197 }
00198
00199 d_inputMode = mode;
00200
00201 WindowEventArgs args(this);
00202 onTextInputModeChanged(args);
00203 }
00204 }
00205
00206 void Spinner::addSpinnerEvents(void)
00207 {
00208 addEvent(EventValueChanged);
00209 addEvent(EventStepChanged);
00210 addEvent(EventMaximumValueChanged);
00211 addEvent(EventMinimumValueChanged);
00212 addEvent(EventTextInputModeChanged);
00213 }
00214
00215 void Spinner::addSpinnerProperties(void)
00216 {
00217 addProperty(&d_currentValueProperty);
00218 addProperty(&d_stepSizeProperty);
00219 addProperty(&d_maxValueProperty);
00220 addProperty(&d_minValueProperty);
00221 addProperty(&d_textInputModeProperty);
00222 }
00223
00224 float Spinner::getValueFromText(void) const
00225 {
00226
00227 if (d_editbox->getText().empty())
00228 {
00229 return 0.0f;
00230 }
00231
00232 int res, tmp;
00233 uint utmp;
00234 float val;
00235
00236 switch (d_inputMode)
00237 {
00238 case FloatingPoint:
00239 res = sscanf(d_editbox->getText().c_str(), "%f", &val);
00240 break;
00241 case Integer:
00242 res = sscanf(d_editbox->getText().c_str(), "%d", &tmp);
00243 val = static_cast<float>(tmp);
00244 break;
00245 case Hexadecimal:
00246 res = sscanf(d_editbox->getText().c_str(), "%x", &utmp);
00247 val = static_cast<float>(utmp);
00248 break;
00249 case Octal:
00250 res = sscanf(d_editbox->getText().c_str(), "%o", &utmp);
00251 val = static_cast<float>(utmp);
00252 break;
00253 default:
00254 throw InvalidRequestException("Spinner::getValueFromText - An unknown TextInputMode was encountered.");
00255 }
00256
00257 if (res)
00258 {
00259 return val;
00260 }
00261
00262 throw InvalidRequestException("Spinner::getValueFromText - The string '" + d_editbox->getText() + "' ca not be converted to numerical representation.");
00263 }
00264
00265 String Spinner::getTextFromValue(void) const
00266 {
00267 std::stringstream tmp;
00268
00269 switch (d_inputMode)
00270 {
00271 case FloatingPoint:
00272 tmp << d_currentValue;
00273 break;
00274 case Integer:
00275 tmp << static_cast<int>(d_currentValue);
00276 break;
00277 case Hexadecimal:
00278 tmp << std::hex << std::uppercase << static_cast<int>(d_currentValue);
00279 break;
00280 case Octal:
00281 tmp << std::oct << static_cast<int>(d_currentValue);
00282 break;
00283 default:
00284 throw InvalidRequestException("Spinner::getValueFromText - An unknown TextInputMode was encountered.");
00285 }
00286
00287 return String(tmp.str());
00288 }
00289
00290 void Spinner::onFontChanged(WindowEventArgs& e)
00291 {
00292
00293 d_editbox->setFont(getFont());
00294
00295 Window::onFontChanged(e);
00296 }
00297
00298 void Spinner::onTextChanged(WindowEventArgs& e)
00299 {
00300
00301 if (d_editbox->getText() != d_text)
00302 {
00303
00304
00305 d_editbox->setText(d_text);
00306 e.handled = true;
00307
00308 Window::onTextChanged(e);
00309 }
00310 }
00311
00312 void Spinner::onActivated(ActivationEventArgs& e)
00313 {
00314 if (!isActive())
00315 {
00316 Window::onActivated(e);
00317
00318 if (!d_editbox->isActive())
00319 {
00320 d_editbox->activate();
00321 }
00322 }
00323 }
00324
00325 void Spinner::onValueChanged(WindowEventArgs& e)
00326 {
00327
00328 bool wasMuted = d_editbox->isMuted();
00329 d_editbox->setMutedState(true);
00330
00331
00332
00333 if (!(d_currentValue == 0 && d_editbox->getText().empty()))
00334 {
00335 d_editbox->setText(getTextFromValue());
00336 }
00337
00338 d_editbox->setMutedState(wasMuted);
00339
00340 fireEvent(EventValueChanged, e, EventNamespace);
00341 }
00342
00343 void Spinner::onStepChanged(WindowEventArgs& e)
00344 {
00345 fireEvent(EventStepChanged, e, EventNamespace);
00346 }
00347
00348 void Spinner::onMaximumValueChanged(WindowEventArgs& e)
00349 {
00350 fireEvent(EventMaximumValueChanged, e, EventNamespace);
00351
00352 if (d_currentValue > d_maxValue)
00353 {
00354 setCurrentValue(d_maxValue);
00355 }
00356 }
00357
00358 void Spinner::onMinimumValueChanged(WindowEventArgs& e)
00359 {
00360 fireEvent(EventMinimumValueChanged, e, EventNamespace);
00361
00362 if (d_currentValue < d_minValue)
00363 {
00364 setCurrentValue(d_minValue);
00365 }
00366 }
00367
00368 void Spinner::onTextInputModeChanged(WindowEventArgs& e)
00369 {
00370
00371
00372 bool wasMuted = d_editbox->isMuted();
00373 d_editbox->setMutedState(true);
00374
00375 d_editbox->setText(getTextFromValue());
00376
00377 d_editbox->setMutedState(wasMuted);
00378
00379 fireEvent(EventTextInputModeChanged, e, EventNamespace);
00380 }
00381
00382 bool Spinner::handleIncreaseButton(const EventArgs& e)
00383 {
00384 if (((const MouseEventArgs&)e).button == LeftButton)
00385 {
00386 setCurrentValue(d_currentValue + d_stepSize);
00387 return true;
00388 }
00389
00390 return false;
00391 }
00392
00393 bool Spinner::handleDecreaseButton(const EventArgs& e)
00394 {
00395 if (((const MouseEventArgs&)e).button == LeftButton)
00396 {
00397 setCurrentValue(d_currentValue - d_stepSize);
00398 return true;
00399 }
00400
00401 return false;
00402 }
00403
00404 bool Spinner::handleEditTextChange(const EventArgs& e)
00405 {
00406
00407 setText(d_editbox->getText());
00408
00409 setCurrentValue(getValueFromText());
00410 return true;
00411 }
00412
00413 }