Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

CEGUISpinner.cpp

Go to the documentation of this file.
00001 /************************************************************************
00002         filename:       CEGUISpinner.cpp
00003         created:        3/2/2005
00004         author:         Paul D Turner
00005 *************************************************************************/
00006 /*************************************************************************
00007     Crazy Eddie's GUI System (http://www.cegui.org.uk)
00008     Copyright (C)2004 - 2005 Paul D Turner (paul@cegui.org.uk)
00009 
00010     This library is free software; you can redistribute it and/or
00011     modify it under the terms of the GNU Lesser General Public
00012     License as published by the Free Software Foundation; either
00013     version 2.1 of the License, or (at your option) any later version.
00014 
00015     This library is distributed in the hope that it will be useful,
00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018     Lesser General Public License for more details.
00019 
00020     You should have received a copy of the GNU Lesser General Public
00021     License along with this library; if not, write to the Free Software
00022     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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 // Start of CEGUI namespace section
00033 namespace CEGUI
00034 {
00036     // event strings
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     // Validator strings
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     // properties
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         // Nothing to do here.
00074     }
00075 
00076     void Spinner::initialise(void)
00077     {
00078         Window::initialise();
00079 
00080         // create all the component widgets
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         // setup component controls
00089         d_increaseButton->setWantsMultiClickEvents(false);
00090         d_increaseButton->setMouseAutoRepeatEnabled(true);
00091         d_decreaseButton->setWantsMultiClickEvents(false);
00092         d_decreaseButton->setMouseAutoRepeatEnabled(true);
00093 
00094         // perform event subscriptions.
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         // final initialisation
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             // limit input value to within valid range for spinner
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         // handle empty case
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         // Propagate to children
00293         d_editbox->setFont(getFont());
00294         // Call base class handler
00295         Window::onFontChanged(e);
00296     }
00297 
00298     void Spinner::onTextChanged(WindowEventArgs& e)
00299     {
00300         // update only if needed
00301         if (d_editbox->getText() != d_text)
00302         {
00303             // done before doing base class processing so event subscribers see
00304             // 'updated' version.
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         // mute to save doing unnecessary events work.
00328         bool wasMuted = d_editbox->isMuted();
00329         d_editbox->setMutedState(true);
00330 
00331         // Update text with new value.
00332         // (allow special 'empty' case to equal 0 with no text change required)
00333         if (!(d_currentValue == 0 && d_editbox->getText().empty()))
00334         {
00335             d_editbox->setText(getTextFromValue());
00336         }
00337         // restore previous mute state.
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         // update edit box text to reflect new mode.
00371         // mute to save doing unnecessary events work.
00372         bool wasMuted = d_editbox->isMuted();
00373         d_editbox->setMutedState(true);
00374         // Update text with new value.
00375         d_editbox->setText(getTextFromValue());
00376         // restore previous mute state.
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         // set this windows text to match
00407         setText(d_editbox->getText());
00408         // update value
00409         setCurrentValue(getValueFromText());
00410         return true;
00411     }
00412 
00413 } // End of  CEGUI namespace section

Generated on Wed Sep 7 09:56:33 2005 for Crazy Eddies GUI System by  doxygen 1.4.3