AaronCameron.net
No ads. No Profit. No Master, But Truth.
Not a Member? - Login or Create an Account
Tuesday the 22nd of May 2012 @ 12:50am
Front Page Journal Projects Your Profile About
[]

LibN2L-4 Library Code Reference

Classes
Compounds
Files
Members
Method Index
Full Reference

cGuiSlider.cpp

Go to the documentation of this file.
00001 /************************************************************************
00002 Nova-2 Library (libN2L, or simply n2l) Game development C++ Library
00003 Copyright (C) 2002  Aaron Cameron
00004 
00005 This library is free software; you can redistribute it and/or
00006 modify it under the terms of the GNU Lesser General Public
00007 License as published by the Free Software Foundation; either
00008 version 2.1 of the License, or (at your option) any later version.
00009 
00010 This library is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 Lesser General Public License for more details.
00014 
00015 You should have received a copy of the GNU Lesser General Public
00016 License along with this library; if not, write to the Free Software
00017 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00018 
00019 A copy of the GNU Lesser General Public License has been provided with
00020 this library in the file 'COPYING'.
00021 
00022 Contact information for the author of this library has been provided
00023 with this library in the file 'AUTHOR'.
00024 ************************************************************************/
00025 #include "gui/cGuiSlider.h"
00026 
00027 #include "n2l/dynVars.h"
00028 #include "n2l/resourceManagement.h"
00029 #include "n2l/events.h"
00030 
00031 #include "gui/cGuiFactory.h"
00032 
00033 namespace n2l
00034 {
00035 #   ifdef N2L_PASSIVE_GUI_REG
00036         tBool cGuiSlider::smRegistered =
00037             cGuiFactory::current().registerLoader(
00038             "n2l::cGuiSlider", cGuiElement::loadNew<cGuiSlider> );
00039 #   endif
00040 
00041     /**************************************************************************/
00042     cGuiSlider::cGuiSlider() :
00043         mMin(0),
00044         mMax(100),
00045         mValue(0),
00046         mRequestedRange(1),
00047         mAlignment( Align_Vertical ),
00048         mSwapWheel(false),
00049         mOverSlider(false),
00050         mDownOnSlider(false)
00051     {
00052         for (tSint i=State_Normal; i<State_NumStates; ++i) {
00053             mFills[ Prop_Background ][i].colour(
00054                 cColour(0.8f,0.8f,0.8f, 1.0f) );
00055             mFills[ Prop_Slider ][i].colour( cColour(1.0f,1.0f,1.0f, 1.0f) );
00056         }
00057 
00058         dimensionChanged();
00059     }
00060 
00061     /**************************************************************************/
00062     cGuiSlider::cGuiSlider( const cVfsNodeInterface &iNode ) :
00063         mMin(0),
00064         mMax(100),
00065         mValue(0),
00066         mRequestedRange(1),
00067         mAlignment( Align_Vertical ),
00068         mSwapWheel(false),
00069         mOverSlider(false),
00070         mDownOnSlider(false)
00071     {
00072         for (tSint i=State_Normal; i<State_NumStates; ++i) {
00073             mFills[ Prop_Background ][i].colour(
00074                 cColour(0.8f,0.8f,0.8f, 1.0f) );
00075             mFills[ Prop_Slider ][i].colour( cColour(1.0f,1.0f,1.0f, 1.0f) );
00076         }
00077 
00078         load(iNode);
00079     }
00080 
00081     /**************************************************************************/
00082     cGuiSlider::cGuiSlider( const cDynVar &iDefinition ) :
00083         mMin(0),
00084         mMax(100),
00085         mValue(0),
00086         mRequestedRange(1),
00087         mAlignment( Align_Vertical ),
00088         mSwapWheel(false),
00089         mOverSlider(false),
00090         mDownOnSlider(false)
00091     {
00092         for (tSint i=State_Normal; i<State_NumStates; ++i) {
00093             mFills[ Prop_Background ][i].colour(
00094                 cColour(0.8f,0.8f,0.8f, 1.0f) );
00095             mFills[ Prop_Slider ][i].colour( cColour(1.0f,1.0f,1.0f, 1.0f) );
00096         }
00097 
00098         load(iDefinition);
00099     }
00100 
00101     /**************************************************************************/
00102     cGuiSlider::~cGuiSlider()
00103     {
00104     }
00105 
00106     /**************************************************************************/
00107     void cGuiSlider::load( const cVfsNodeInterface &iNode )
00108     {
00109         cDynVar def;
00110         validateAndDecode( def, iNode, "n2l::cGuiSlider" );
00111         load( def );
00112     }
00113 
00114     /**************************************************************************/
00115     void cGuiSlider::load( const cDynVar & iDefinition )
00116     {
00117         // Load parent properties
00118         cGuiInteractive::load( iDefinition );
00119     
00120         if (iDefinition["fill"]) {
00121             for (tSint p=Prop_Background; p!=Prop_NumProps; ++p) {
00122                 if (iDefinition["fill"].keyExists(p)) {
00123                     for (tSint s=State_Normal; s!=State_NumStates; ++s)
00124                         if (iDefinition["fill"][p].keyExists(s)) {
00125                             if (iDefinition["fill"][p][s].isArray())
00126                                 fill(tProp(p), tState(s),
00127                                     iDefinition["fill"][p][s] );
00128                             else
00129                                 fill(tProp(p), tState(s),
00130                                     *cResourceManager::get<cGuiFill>(
00131                                         iDefinition["fill"][p][s] ) );
00132                         } // if defi..
00133                 }  // if prop
00134             } // for props
00135         } // if fills
00136 
00137         if (iDefinition.keyExists("range")) range(iDefinition["range"]);
00138         if (iDefinition.keyExists("min")) min(iDefinition["min"]);
00139         if (iDefinition.keyExists("max")) max(iDefinition["max"]);
00140         if (iDefinition.keyExists("value")) value(iDefinition["value"]);
00141         if (iDefinition.keyExists("swapWheel"))
00142             swapWheel(iDefinition["swapWheel"]);
00143 
00144         if (iDefinition.keyExists("alignment"))
00145             alignment( tAlignment(tSint(iDefinition["alignment"])) );
00146 
00147         dimensionChanged(); 
00148     }
00149 
00150     /**************************************************************************/
00151     void cGuiSlider::draw() const
00152     {
00153         tState sliderState( State_Normal );
00154         tState backgroundState( State_Normal );
00155 
00156         // What do we show?
00157         if (mDownOnSlider)
00158             sliderState = State_Down;
00159         else if (mOverSlider)
00160             sliderState = State_Over;
00161 
00162         mFills[Prop_Background][backgroundState].draw(outerPos(),outerSize());
00163         mFills[Prop_Slider][sliderState].draw( mSliderPos,mSliderSize );
00164     }
00165 
00166     /**************************************************************************/
00167     void cGuiSlider::align( const tAlignment iAlign )
00168     {
00169         mAlignment = iAlign;
00170         dimensionChanged();
00171     }
00172 
00173     /**************************************************************************/
00174     void cGuiSlider::min( const tValue &iValue )
00175     {
00176         mMin = iValue;
00177         dimensionChanged();
00178     }
00179 
00180     /**************************************************************************/
00181     void cGuiSlider::value( const tValue &iValue )
00182     {
00183         mValue = iValue;
00184         if (mValue<mMin) mValue=mMin;
00185         else if (mValue>(mMax-mRange)) mValue=(mMax-mRange);
00186         dimensionChanged();
00187         
00188         // Broadcast our event.
00189         tActionData actionData( tActionData::Array );
00190         actionData.insert("name",mName);
00191         actionData.insert("min",mMin);
00192         actionData.insert("max",mMax);
00193         actionData.insert("value",mValue);
00194         broadcastAction( GuiActionType_SliderValueChanged, actionData );
00195     }
00196 
00197     /**************************************************************************/
00198     const cGuiSlider::tValue & cGuiSlider::value() const
00199     {
00200         return mValue;
00201     }
00202 
00203     /**************************************************************************/
00204     void cGuiSlider::range( const tValue &iValue )
00205     {
00206         mRequestedRange = iValue;
00207         dimensionChanged();
00208     }
00209 
00210     /**************************************************************************/
00211     void cGuiSlider::max( const tValue &iValue )
00212     {
00213         mMax = iValue;
00214         dimensionChanged();
00215     }
00216 
00217     /**************************************************************************/
00218     void cGuiSlider::swapWheel( const tBool iSwap )
00219     {
00220         mSwapWheel = iSwap;
00221     }
00222 
00223     /**************************************************************************/
00224     const tBool cGuiSlider::swapWheel() const
00225     {
00226         return mSwapWheel;
00227     }
00228 
00229     /**************************************************************************/
00230     void cGuiSlider::fill(  const tProp iProp,
00231                             const tState iState,
00232                             const cGuiFill & iFill )
00233     {
00234         if (iProp<Prop_Background || iProp>=Prop_NumProps)
00235             throw cOutOfBoundsException( "cGuiSlider::fill",
00236                 "Property out of range" );
00237         if (iState<State_Normal || iState>=State_NumStates)
00238             throw cOutOfBoundsException( "cGuiSlider::fill",
00239                 "State out of range" );
00240 
00241         mFills[iProp][iState] = iFill;
00242     }
00243 
00244     /**************************************************************************/
00245     const cGuiSlider::tValue & cGuiSlider::min() const
00246     {
00247         return mMin;
00248     }
00249 
00250 
00251     /**************************************************************************/
00252     const cGuiSlider::tValue & cGuiSlider::max() const
00253     {
00254         return mMax;
00255     }
00256 
00257     /**************************************************************************/
00258     const cGuiSlider::tValue & cGuiSlider::range() const
00259     {
00260         return mRequestedRange;
00261     }
00262 
00263     /**************************************************************************/
00264     void cGuiSlider::systemEvent(
00265         const cAutoPtr<const cEventInterface> &i_iEvent )
00266     {
00267         switch (i_iEvent->type())
00268         {
00269             case EventType_MouseMotion: {
00270                 const cAutoPtr<const cMouseMotionEvent> Motion(i_iEvent);
00271                 mouseMove( Motion->pos() );
00272 
00273                 break;
00274             }
00275 
00276             case EventType_MouseButton: {
00277                 const cAutoPtr<const cMouseButtonEvent> Button(i_iEvent);
00278                 mouseClickAt( *Button );
00279             }
00280 
00281             default:
00282                 // Nothing.
00283                 break;
00284         } // switch
00285     }
00286 
00287     /**************************************************************************/
00288     void cGuiSlider::mouseClickAt( const cMouseButtonEvent &iClick )
00289     {
00290         // Do normal hotspot processing
00291         cGuiInteractive::mouseClickAt(iClick);
00292         if (iClick.button() == MouseButton_Left) {
00293              if (iClick.pressed()) {
00294                 // Left Pressed
00295                 if (iClick.pos().x()>=mSliderPos.x() &&
00296                     iClick.pos().x()<=(mSliderPos.x()+mSliderSize.x()) &&
00297                     iClick.pos().y()>=mSliderPos.y() &&
00298                     iClick.pos().y()<=(mSliderPos.y()+mSliderSize.y()))
00299                 {
00300                     mDownOnSlider = true;
00301                     mDownOffset = iClick.pos()-mSliderPos;
00302                 } else  if (isOver()) {
00303                     // Is over and pressed.
00304                     if (mAlignment==Align_Vertical) {
00305                         if (iClick.pos().y()<mSliderPos.y())
00306                             value(mValue-mRange);
00307                         else value(mValue+mRange);
00308                     } else {
00309                         if (iClick.pos().x()<mSliderPos.x())
00310                             value(mValue-mRange);
00311                         else value(mValue+mRange);
00312                     }
00313                 }
00314              } else {
00315                 // Left Released
00316                 mDownOnSlider = false;
00317              }
00318         } else if ( iClick.button() == MouseButton_Up &&
00319                     iClick.pressed() && collides(iClick.pos()) ) {
00320             if (mSwapWheel)
00321                 scrollMinus();
00322             else
00323                 scrollPlus();
00324         } else if ( iClick.button() == MouseButton_Down &&
00325                     iClick.pressed() && collides(iClick.pos()) ) {
00326             if (mSwapWheel)
00327                 scrollPlus();
00328             else
00329                 scrollMinus();
00330         }
00331     }
00332 
00333     /**************************************************************************/
00334     void cGuiSlider::scrollRangePCent( const tFloat &iPCent )
00335     {
00336         value( mValue + mRange*iPCent );
00337     }
00338 
00339     /**************************************************************************/    
00340     void cGuiSlider::scrollPlus()
00341     {
00342         scrollRangePCent( 0.1f );
00343     }
00344 
00345     /**************************************************************************/    
00346     void cGuiSlider::scrollMinus()
00347     {
00348         scrollRangePCent( -0.1f );
00349     }
00350 
00351     /**************************************************************************/
00352     void cGuiSlider::alignment( const tAlignment iAlignment )
00353     {
00354         if (mAlignment<0 || mAlignment>=Align_NumAlignments)
00355             throw cOutOfBoundsException( "cGuiSlider::alignment",
00356                 "No such alignment: " + asString(tUint(iAlignment)));
00357         mAlignment = iAlignment;
00358         dimensionChanged();
00359     }
00360 
00361     /**************************************************************************/
00362     void cGuiSlider::mouseMove( const tGuiPos &iPos )
00363     {
00364         // Do normal hotspot processing
00365         cGuiInteractive::mouseMove(iPos);
00366         if (isOver()) {
00367             if (iPos.x()>=mSliderPos.x() &&
00368                 iPos.x()<=(mSliderPos.x()+mSliderSize.x()) &&
00369                 iPos.y()>=mSliderPos.y() &&
00370                 iPos.y()<=(mSliderPos.y()+mSliderSize.y()))
00371                     mOverSlider = true;
00372             else mOverSlider = false;
00373         } else {
00374             mOverSlider = false;
00375         }
00376 
00377         // Regardless, if the slider is down, follow the mouse.
00378         if (mDownOnSlider) {
00379             tGuiPos newSliderPos( iPos-mDownOffset-innerPos() );
00380             if (mAlignment==Align_Vertical)
00381                 value( newSliderPos.y()/mValueToPosScale + mMin );
00382             else
00383                 value( newSliderPos.x()/mValueToPosScale + mMin );
00384         }
00385     }
00386 
00387     /**************************************************************************/
00388     void cGuiSlider::dimensionChanged()
00389     {
00390         cGuiInteractive::dimensionChanged();
00391 
00392         mRange = n2l_min(mRequestedRange,max()-min());
00393         if (mAlignment==Align_Vertical) {
00394             mValueToPosScale = innerSize().y()/(mMax-mMin);
00395             
00396             mSliderPos.x( innerPos().x() );
00397             mSliderPos.y( innerPos().y()+(mValue-mMin)*mValueToPosScale );
00398 
00399             mSliderSize.x( innerSize().x() );
00400             mSliderSize.y( mRange*mValueToPosScale );
00401 
00402         } else {
00403             mValueToPosScale = innerSize().x()/(mMax-mMin);
00404 
00405             mSliderPos.x( innerPos().x()+(mValue-mMin)*mValueToPosScale );
00406             mSliderPos.y( innerPos().y() );
00407 
00408             mSliderSize.x( mRange*mValueToPosScale );
00409             mSliderSize.y( innerSize().y() );
00410         }
00411     }
00412 
00413     /**************************************************************************/
00414     const cAutoPtr<cGuiElement> cGuiSlider::clone() const
00415     {
00416         cAutoPtr<cGuiElement> newElement( new cGuiSlider );
00417         cloneInto( newElement );
00418         return newElement;
00419     }
00420 
00421     /**************************************************************************/
00422     void cGuiSlider::cloneInto( const cAutoPtr<cGuiSlider> &i_ioElement ) const
00423     {
00424         // Parent Properties first
00425         cGuiInteractive::cloneInto( i_ioElement );
00426 
00427         for (tSint p=Prop_Background; p!=Prop_NumProps; ++p)
00428             for (tSint s=State_Normal; s!=State_NumStates; ++s)
00429                 i_ioElement->fill( tProp(p), tState(s), mFills[p][s] );
00430 
00431         i_ioElement->min( mMin );
00432         i_ioElement->max( mMax );
00433         i_ioElement->range( mRequestedRange );
00434         i_ioElement->value( mValue );
00435         i_ioElement->swapWheel( mSwapWheel );
00436         i_ioElement->alignment( mAlignment );
00437     }
00438 
00439 } // namespace n2l
©2012 Aaron Cameron