AaronCameron.net
Because you all make me very, very tired.
Not a Member? - Login or Create an Account
Sunday the 20th of May 2012 @ 04:38pm
Front Page Journal Projects Your Profile About
[]

LibN2L-4 Library Code Reference

Classes
Compounds
Files
Members
Method Index
Full Reference

cGuiButton.cpp

Go to the documentation of this file.
00001 /************************************************************************
00002 Nova-2 Library (libN2L, or simply n2l) Game development C++ Library
00003 Copyright (C) 2003  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 "cGuiButton.h"
00026 
00027 #include "n2l/dynVars.h"
00028 #include "n2l/resourceManagement.h"
00029 #include "n2l/audio.h"
00030 
00031 #include "gui/cGuiSimpleCallbackAction.h"
00032 
00033 #include "gui/cGuiFactory.h"
00034 
00035 /******************************************************************************/
00036 namespace n2l
00037 {
00038 #   ifdef N2L_PASSIVE_GUI_REG
00039         tBool cGuiButton::smRegistered =
00040             cGuiFactory::current().registerLoader(
00041             "n2l::cGuiButton", cGuiElement::loadNew<cGuiButton> );
00042 #   endif
00043 
00044     /**************************************************************************/
00045     cGuiButton::cGuiButton()
00046     {
00047         reset();
00048     }
00049 
00050     /**************************************************************************/
00051     cGuiButton::cGuiButton( const cVfsNodeInterface &iNode )
00052     {
00053         reset();
00054         load( iNode );
00055     }
00056 
00057     /**************************************************************************/
00058     cGuiButton::cGuiButton( const cDynVar &iDefinition )
00059     {
00060         reset();
00061         load( iDefinition );
00062     }
00063 
00064     /**************************************************************************/
00065     cGuiButton::~cGuiButton()
00066     {
00067     }
00068 
00069     /**************************************************************************/
00070     void cGuiButton::load( const cVfsNodeInterface &iNode )
00071     {
00072         cDynVar def;
00073         validateAndDecode( def, iNode, "n2l::cGuiButton" );
00074         load( def );
00075     }
00076 
00077     /**************************************************************************/
00078     void cGuiButton::load( const cDynVar &iDefinition )
00079     {
00080         // Load parent properties
00081         cGuiInteractive::load( iDefinition );
00082     
00083         if (iDefinition["label"])
00084             label( iDefinition["label"] );
00085 
00086         if (iDefinition["fill"]) {
00087             for (tSint i=Button_Normal; i!=Button_NumStates; ++i)
00088                 if (iDefinition["fill"][i])
00089                     if (iDefinition["fill"][i].isArray())
00090                         fill(tButtonState(i), Prop_Background,
00091                             iDefinition["fill"][i] );
00092                     else fill(tButtonState(i), Prop_Background,
00093                         *cResourceManager::get<cGuiFill>(
00094                             iDefinition["fill"][i]));
00095         }
00096 
00097         if (iDefinition["labelStyle"]) {
00098             for (tSint i=Button_Normal; i!=Button_NumStates; ++i)
00099                 if (iDefinition["labelStyle"][i])
00100                     if (iDefinition["labelStyle"][i].isArray())
00101                         labelStyle( tButtonState(i),
00102                             iDefinition["labelStyle"][i] );
00103                     else labelStyle( tButtonState(i),
00104                         *cResourceManager::get<cGuiTextStyle>(
00105                             iDefinition["labelStyle"][i]) );
00106         }
00107 
00108         if (iDefinition["audio"]) {
00109             for (tSint i=Button_Normal; i!=Button_NumStates; ++i)
00110                 if (iDefinition["audio"][i])
00111                     audio( tButtonState(i),
00112                         cResourceManager::get<cAudioChunk>(
00113                             iDefinition["audio"][i]) );
00114         }
00115 
00116         if (iDefinition.keyExists("buttonType"))
00117             type( tType(tSint(iDefinition["buttonType"])) );
00118         else if (iDefinition.keyExists("type"))
00119             type( tType(tSint(iDefinition["type"])) );
00120 
00121         if (iDefinition.keyExists("toggledOn"))
00122             toggledOn( iDefinition["toggledOn"] );
00123 
00124         if (iDefinition.keyExists("enabled"))
00125             enabled( iDefinition["enabled"] );
00126 
00127         // Load the button accelerator
00128         if (iDefinition.keyExists("accelKey")) {
00129             tKey tmpKey =
00130                 cEventTypeLookups::lookupTypeByName(iDefinition["accelKey"]);
00131             if (tmpKey == Key_Unknown)
00132                 throw cBadDataUseException("cGuiButton::load", "The provided "
00133                     "acceleration key wasn\'t recognized: " +
00134                     tString(iDefinition["accelKey"]) );
00135             tKeyMods tmpMod = KMod_None;
00136             if (iDefinition.keyExists("accelMod")) {
00137                 if (iDefinition["accelMod"] == "none")
00138                     tmpMod = KMod_None;
00139                 else if (iDefinition["accelMod"] == "shift")
00140                     tmpMod = KMod_Shift;
00141                 else if (iDefinition["accelMod"] == "ctrl")
00142                     tmpMod = KMod_Ctrl;
00143                 else if (iDefinition["accelMod"] == "alt")
00144                     tmpMod = KMod_Alt;
00145                 else if (iDefinition["accelMod"] == "meta")
00146                     tmpMod = KMod_Meta;
00147                 else throw cBadDataUseException("cGuiButton::load",
00148                     "The provided acceleration key mod wasn\'t recognized: " +
00149                     tString(iDefinition["accelMod"]) );
00150             }
00151             setAccel( tmpKey, tmpMod );
00152         }
00153     }
00154 
00155     /**************************************************************************/
00156     void cGuiButton::draw() const
00157     {
00158         tButtonState currentState =
00159             (mEnabled?Button_Normal:Button_NormalDisabled);
00160 
00161         if (mType==Type_Push) {
00162             if (isOver())
00163                 if (isDown()) {
00164                     currentState = (mEnabled?Button_Down:Button_DownDisabled);
00165                 } else {
00166                     currentState = (mEnabled?Button_Over:Button_OverDisabled);
00167                 }
00168         } else if (mType==Type_Toggle) {
00169             if (mToggledOn)
00170                 currentState = (mEnabled?Button_Down:Button_DownDisabled);
00171             else {
00172                 if (isOver())
00173                     if (isDown()) {
00174                         currentState =
00175                             (mEnabled?Button_Down:Button_DownDisabled);
00176                     } else {
00177                         currentState =
00178                             (mEnabled?Button_Over:Button_OverDisabled);
00179                     }
00180             }
00181             
00182         }
00183 
00184         mFills[currentState][Prop_Background].draw( outerPos(), outerSize() );
00185 
00186         // If it's set, draw the label
00187         if (!mLabel.empty())
00188             mLabelStyle[currentState].draw( innerPos(), innerSize(), mLabel );
00189     }
00190 
00191     /**************************************************************************/
00192     void cGuiButton::fill( const tButtonState iState, const tProp iProp,
00193         const cGuiFill &iFill )
00194     {
00195         boundCheckProp(iProp);
00196         boundCheckState(iState);
00197         mFills[iState][iProp] = iFill;
00198     }
00199 
00200     /**************************************************************************/
00201     const cGuiFill &cGuiButton::fill( const tButtonState iState,
00202         const tProp iProp ) const
00203     {
00204         boundCheckProp(iProp);
00205         boundCheckState(iState);
00206         return mFills[iState][iProp];
00207     }
00208 
00209     /**************************************************************************/
00210     void cGuiButton::label( const tString &iLabel )
00211     {
00212         mLabel = iLabel;
00213     }
00214 
00215     /**************************************************************************/
00216     const tString & cGuiButton::label() const
00217     {
00218         return mLabel;
00219     }
00220 
00221     /**************************************************************************/
00222     void cGuiButton::labelStyle( const tButtonState iState,
00223         const cGuiTextStyle & iStyle )
00224     {
00225         boundCheckState( iState );
00226         mLabelStyle[iState] = iStyle;
00227     }
00228 
00229     /**************************************************************************/
00230     void cGuiButton::boundCheckProp( const tProp iProp ) const
00231     {
00232         if (iProp<0 || iProp>=Prop_NumProps)
00233             throw cOutOfBoundsException( "cGuiButton::boundCheckProp",
00234                 "Property out of range" );
00235     }
00236 
00237     /**************************************************************************/
00238     void cGuiButton::boundCheckState( const tButtonState iState ) const
00239     {
00240         if (iState<0 || iState>=Button_NumStates)
00241             throw cOutOfBoundsException( "cGuiButton::boundCheckState",
00242                 "State out of range" );
00243     }
00244 
00245     /**************************************************************************/
00246     void cGuiButton::boundCheckType( const tType iType ) const
00247     {
00248         if (iType<0 || iType>=Type_NumTypes)
00249             throw cOutOfBoundsException( "cGuiButton::boundCheckType",
00250                 "Type out of range" );
00251     }
00252 
00253     /**************************************************************************/
00254     void cGuiButton::audio( const tButtonState iState,
00255         const cAutoPtr<const cAudioChunk> &i_ioSound )
00256     {
00257         boundCheckState( iState );
00258         mSounds[iState] = i_ioSound;
00259     }
00260 
00261     /**************************************************************************/
00262     void cGuiButton::type( const tType iType )
00263     {
00264         boundCheckType( iType );
00265         mType = iType;
00266     }
00267 
00268     /**************************************************************************/
00269     const cGuiButton::tType cGuiButton::type() const
00270     {
00271         return mType;
00272     }
00273 
00274     /**************************************************************************/
00275     void cGuiButton::toggledOn( const tBool iToggled )
00276     {
00277         mToggledOn = iToggled;
00278     }
00279 
00280     /**************************************************************************/    
00281     const tBool cGuiButton::toggledOn() const
00282     {
00283         return mToggledOn;
00284     }
00285 
00286     /**************************************************************************/    
00287     void cGuiButton::enabled( const tBool iEnabled )
00288     {
00289         mEnabled = iEnabled;
00290     }
00291 
00292     /**************************************************************************/    
00293     const tBool cGuiButton::enabled() const
00294     {
00295         return mEnabled;
00296     }
00297 
00298     /**************************************************************************/
00299     void cGuiButton::setAccel( const tKey &iKey, const tKeyMods &iMods )
00300     {
00301         mUseAccel = true;
00302         mKey = iKey;
00303         mKeyMod = iMods;
00304     }
00305     
00306     /**************************************************************************/
00307     void cGuiButton::clearAccel()
00308     {
00309         mUseAccel = false;
00310     }
00311 
00312     /**************************************************************************/
00313     const cAutoPtr<cGuiElement> cGuiButton::clone() const
00314     {
00315         cAutoPtr<cGuiElement> newElement( new cGuiButton );
00316         cloneInto( newElement );
00317         return newElement;
00318     }
00319 
00320     /**************************************************************************/
00321     void cGuiButton::cloneInto( const cAutoPtr<cGuiButton> &i_ioElement ) const
00322     {
00323         // Parent Properties first
00324         cGuiInteractive::cloneInto( i_ioElement );
00325         
00326         //  Now our properties.
00327         i_ioElement->label( mLabel );
00328         i_ioElement->toggledOn( toggledOn() );
00329         i_ioElement->type( type() );
00330         i_ioElement->enabled( enabled() );
00331 
00332         i_ioElement->mUseAccel = mUseAccel;
00333         i_ioElement->mKey = mKey;
00334         i_ioElement->mKeyMod = mKeyMod;
00335 
00336         for (tUint state=Button_Normal; state<Button_NumStates; ++state) {
00337             // Fills
00338             for (tUint prop=Prop_Background; prop<Prop_NumProps; ++prop)
00339                 i_ioElement->fill( tButtonState(state),tProp(prop),
00340                     mFills[state][prop] );
00341 
00342             // Label Styles
00343             i_ioElement->labelStyle( tButtonState(state), mLabelStyle[state] );
00344 
00345             // Audio queues
00346             i_ioElement->audio( tButtonState(state), mSounds[state] );
00347 
00348         } // for (tButtonState state=But...
00349     }
00350 
00351     /**************************************************************************/
00352     void cGuiButton::reset()
00353     {
00354         mLabel = "Button";
00355         mType = Type_Push;
00356         mToggledOn = false;
00357         mEnabled = true;
00358         for (tUint i=0; i<Button_NumStates; ++i)
00359             mSounds[i] = 0;
00360 
00361         // Clear the system callbacks here.
00362 
00363         bindAction( GuiActionType_Clicked,
00364             new cGuiSimpleCallbackAction<cGuiButton::clickedCallback>,
00365             false );
00366                     
00367         bindAction( GuiActionType_Over,
00368             new cGuiSimpleCallbackAction<cGuiButton::overAndOutCallback>,
00369             false );
00370 
00371         bindAction( GuiActionType_Out,
00372             new cGuiSimpleCallbackAction<cGuiButton::overAndOutCallback>,
00373             false );
00374 
00375         bindAction( GuiActionType_Keystroke,
00376             new cGuiSimpleCallbackAction<cGuiButton::keystrokeCallback>,
00377             false );
00378         bindAction( GuiActionType_KeystrokeOutside,
00379             new cGuiSimpleCallbackAction<cGuiButton::keystrokeCallback>,
00380             false );
00381 
00382     }
00383 
00384     /**************************************************************************/
00385     void cGuiButton::clickedCallback(   cGuiElement *const i_ioElement,
00386         const tGuiActionType iType, const tActionData &iData )
00387     {
00388         cGuiButton *const button( dynamic_cast<cGuiButton*>(i_ioElement) );
00389         // Do the toggle if we need to
00390         if (button->mType==Type_Toggle)
00391             button->mToggledOn = !button->mToggledOn;
00392 
00393         const tButtonState SoundStateToPlay(
00394             button->mEnabled?Button_Down:Button_DownDisabled);
00395         
00396         if (button->mSounds[SoundStateToPlay])
00397             button->mSounds[SoundStateToPlay]->play();
00398     }
00399 
00400     /**************************************************************************/
00401     void cGuiButton::keystrokeCallback( cGuiElement *const i_ioElement,
00402         const tGuiActionType iType, const tActionData &iData )
00403     {
00404         cGuiButton *const button( dynamic_cast<cGuiButton*>(i_ioElement) );
00405 
00406         // Do we just ignore it?
00407         if (!button->mUseAccel || !iData["pressed"]) return;
00408         tKey tmpKey = tKey(tSint(iData["key"]));
00409         tKeyMod tmpMod = tKeyMod(tSint(iData["mods"]));
00410 
00411         if (tmpKey== button->mKey && (tmpMod & button->mKeyMod ||
00412             button->mKeyMod == KMod_None) )
00413         {
00414             // This may eventually not work, but for the moment it 
00415             // should be fine.
00416 
00417             // Ok, I've already been diddled by this.  We can't set the
00418             // event up in the constructor because it is treated as a
00419             // system position (that means it may be scaled automatically).
00420             // Instead we need to use the regular set method for the position.
00421             cMouseButtonEvent tmpEvent( button->pos(), MouseButton_Left, true );
00422             tmpEvent.pos( button->pos() );
00423             button->mouseClickAt( tmpEvent );
00424             tmpEvent.pressed(false);
00425             button->mouseClickAt( tmpEvent );
00426         }
00427     }
00428 
00429     /**************************************************************************/
00430     void cGuiButton::overAndOutCallback( cGuiElement *const i_ioElement,
00431         const tGuiActionType iType, const tActionData &iData )
00432     {
00433         cGuiButton *const button( dynamic_cast<cGuiButton*>(i_ioElement) );
00434         tButtonState soundStateToPlay;
00435         
00436         if (iType==GuiActionType_Over)
00437             soundStateToPlay = 
00438                 (button->mEnabled?Button_Over:Button_OverDisabled);
00439         else
00440             soundStateToPlay =
00441                 (button->mEnabled?Button_Normal:Button_NormalDisabled);
00442 
00443         if (button->mSounds[soundStateToPlay])
00444             button->mSounds[soundStateToPlay]->play();
00445 
00446     }
00447 
00448     /**************************************************************************/
00449     void cGuiButton::addExtraClickedData( tActionData &oData )
00450     {
00451         cGuiInteractive::addExtraClickedData(oData);
00452 
00453         // Send ! toggled because we get called before the callback
00454         // which changes our status
00455         if (mType==Type_Toggle)
00456             oData.insert( "toggled", tSint(!mToggledOn) );
00457 
00458         oData.insert( "enabled", tSint(mEnabled) );
00459     }
00460 
00461     /**************************************************************************/
00462     void cGuiButton::addExtraOverData( tActionData &oData )
00463     {
00464         cGuiInteractive::addExtraOverData(oData);
00465         
00466         oData.insert( "enabled", tSint(mEnabled) );
00467     }
00468 
00469     /**************************************************************************/
00470     void cGuiButton::addExtraOutData( tActionData &oData )
00471     {
00472         cGuiInteractive::addExtraOutData(oData);
00473         
00474         oData.insert( "enabled", tSint(mEnabled) );
00475     }
00476 
00477 } // namespace n2l
©2012 Aaron Cameron