![[]](/images/special/trans.gif)
LibN2L-4 Library Code ReferenceClassesCompounds Files Members Method Index Full Reference cGuiButton.cppGo 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 |