guiButtonBaseCtrl.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "console/console.h"
  23. #include "graphics/dgl.h"
  24. #include "console/consoleTypes.h"
  25. #include "platform/platformAudio.h"
  26. #include "gui/guiCanvas.h"
  27. #include "gui/buttons/guiButtonBaseCtrl.h"
  28. #include "gui/language/lang.h"
  29. IMPLEMENT_CONOBJECT(GuiButtonBaseCtrl);
  30. GuiButtonBaseCtrl::GuiButtonBaseCtrl()
  31. {
  32. mDepressed = false;
  33. mMouseOver = false;
  34. mActive = true;
  35. mButtonText = StringTable->insert("Button");
  36. mButtonTextID = StringTable->EmptyString;
  37. mStateOn = false;
  38. mRadioGroup = -1;
  39. mButtonType = ButtonTypePush;
  40. mUseMouseEvents = false;
  41. }
  42. bool GuiButtonBaseCtrl::onWake()
  43. {
  44. if(!Parent::onWake())
  45. return false;
  46. // is we have a script variable, make sure we're in sync
  47. if ( mConsoleVariable[0] )
  48. mStateOn = Con::getBoolVariable( mConsoleVariable );
  49. if(mButtonTextID && *mButtonTextID != 0)
  50. setTextID(mButtonTextID);
  51. return true;
  52. }
  53. ConsoleMethod( GuiButtonBaseCtrl, performClick, void, 2, 2, "() - simulates a button click from script." )
  54. {
  55. object->onAction();
  56. }
  57. ConsoleMethod( GuiButtonBaseCtrl, setText, void, 3, 3, "(string text) - Sets the text of the button to the string." )
  58. {
  59. object->setText( argv[2] );
  60. }
  61. ConsoleMethod( GuiButtonBaseCtrl, setTextID, void, 3, 3, "(string id) - Sets the text of the button to the localized string." )
  62. {
  63. object->setTextID(argv[2]);
  64. }
  65. ConsoleMethod( GuiButtonBaseCtrl, getText, const char *, 2, 2, "() - returns the text of the button.\n"
  66. "@return The text member of the button as a char string")
  67. {
  68. return object->getText( );
  69. }
  70. ConsoleMethod( GuiButtonBaseCtrl, setStateOn, void, 3, 3, "(bool isStateOn) - sets the state on member and updates siblings of the same group." )
  71. {
  72. object->setStateOn(dAtob(argv[2]));
  73. }
  74. ConsoleMethod(GuiButtonBaseCtrl, getStateOn, bool, 2, 2, "(bool getStateOn) - gets whether the state of the button is currently 'on'" )
  75. {
  76. return object->getStateOn();
  77. }
  78. static EnumTable::Enums buttonTypeEnums[] =
  79. {
  80. { GuiButtonBaseCtrl::ButtonTypePush, "PushButton" },
  81. { GuiButtonBaseCtrl::ButtonTypeCheck, "ToggleButton" },
  82. { GuiButtonBaseCtrl::ButtonTypeRadio, "RadioButton" },
  83. };
  84. static EnumTable gButtonTypeTable(3, &buttonTypeEnums[0]);
  85. void GuiButtonBaseCtrl::initPersistFields()
  86. {
  87. Parent::initPersistFields();
  88. addGroup("GuiButtonBaseCtrl");
  89. addField("text", TypeCaseString, Offset(mButtonText, GuiButtonBaseCtrl));
  90. addField("textID", TypeString, Offset(mButtonTextID, GuiButtonBaseCtrl));
  91. addField("groupNum", TypeS32, Offset(mRadioGroup, GuiButtonBaseCtrl));
  92. addField("buttonType", TypeEnum, Offset(mButtonType, GuiButtonBaseCtrl), 1, &gButtonTypeTable);
  93. addField("useMouseEvents", TypeBool, Offset(mUseMouseEvents, GuiButtonBaseCtrl));
  94. endGroup("GuiButtonBaseCtrl");
  95. }
  96. void GuiButtonBaseCtrl::setText(const char *text)
  97. {
  98. mButtonText = StringTable->insert(text);
  99. }
  100. void GuiButtonBaseCtrl::setStateOn( bool bStateOn )
  101. {
  102. if(!mActive)
  103. return;
  104. if(mButtonType == ButtonTypeCheck)
  105. {
  106. mStateOn = bStateOn;
  107. }
  108. else if(mButtonType == ButtonTypeRadio)
  109. {
  110. messageSiblings(mRadioGroup);
  111. mStateOn = bStateOn;
  112. }
  113. setUpdate();
  114. }
  115. void GuiButtonBaseCtrl::setTextID(const char *id)
  116. {
  117. S32 n = Con::getIntVariable(id, -1);
  118. if(n != -1)
  119. {
  120. mButtonTextID = StringTable->insert(id);
  121. setTextID(n);
  122. }
  123. }
  124. void GuiButtonBaseCtrl::setTextID(S32 id)
  125. {
  126. const UTF8 *str = getGUIString(id);
  127. if(str)
  128. setText((const char*)str);
  129. //mButtonTextID = id;
  130. }
  131. const char *GuiButtonBaseCtrl::getText()
  132. {
  133. return mButtonText;
  134. }
  135. //---------------------------------------------------------------------------
  136. void GuiButtonBaseCtrl::acceleratorKeyPress(U32)
  137. {
  138. if (! mActive)
  139. return;
  140. //set the bool
  141. mDepressed = true;
  142. if (mProfile->mTabable)
  143. setFirstResponder();
  144. }
  145. //---------------------------------------------------------------------------
  146. void GuiButtonBaseCtrl::acceleratorKeyRelease(U32)
  147. {
  148. if (! mActive)
  149. return;
  150. if (mDepressed)
  151. {
  152. //set the bool
  153. mDepressed = false;
  154. //perform the action
  155. onAction();
  156. }
  157. //update
  158. setUpdate();
  159. }
  160. void GuiButtonBaseCtrl::onMouseDown(const GuiEvent &event)
  161. {
  162. if (! mActive)
  163. return;
  164. if (mProfile->mCanKeyFocus)
  165. setFirstResponder();
  166. if (mProfile->mSoundButtonDown)
  167. {
  168. AUDIOHANDLE handle = alxCreateSource(mProfile->mSoundButtonDown);
  169. alxPlay(handle);
  170. }
  171. //lock the mouse
  172. mouseLock();
  173. mDepressed = true;
  174. //update
  175. setUpdate();
  176. }
  177. void GuiButtonBaseCtrl::onMouseEnter(const GuiEvent &event)
  178. {
  179. setUpdate();
  180. if(mUseMouseEvents)
  181. Con::executef( this, 1, "onMouseEnter" );
  182. if(isMouseLocked())
  183. {
  184. mDepressed = true;
  185. mMouseOver = true;
  186. }
  187. else
  188. {
  189. if ( mActive && mProfile->mSoundButtonOver )
  190. {
  191. AUDIOHANDLE handle = alxCreateSource(mProfile->mSoundButtonOver);
  192. alxPlay(handle);
  193. }
  194. mMouseOver = true;
  195. }
  196. }
  197. //Luma: Some fixes from the forums, Dave Calabrese
  198. //http://www.garagegames.com/community/forums/viewthread/93467/1#comment-669559
  199. void GuiButtonBaseCtrl::onMouseLeave(const GuiEvent &)
  200. {
  201. if(isMouseLocked())
  202. mDepressed = false;
  203. mouseUnlock();
  204. setUpdate();
  205. if(mUseMouseEvents)
  206. Con::executef( this, 1, "onMouseLeave" );
  207. mMouseOver = false;
  208. }
  209. void GuiButtonBaseCtrl::onMouseUp(const GuiEvent &event)
  210. {
  211. if (! mActive)
  212. return;
  213. mouseUnlock();
  214. setUpdate();
  215. //if we released the mouse within this control, perform the action
  216. if (mDepressed)
  217. onAction();
  218. // Execute callback
  219. if (mUseMouseEvents)
  220. {
  221. char buf[3][32];
  222. dSprintf(buf[0], 32, "%d", event.modifier);
  223. dSprintf(buf[1], 32, "%d %d", event.mousePoint.x, event.mousePoint.y);
  224. dSprintf(buf[2], 32, "%d", event.mouseClickCount);
  225. Con::executef(this, 4, "onMouseUp", buf[0], buf[1], buf[2]);
  226. }
  227. mDepressed = false;
  228. }
  229. void GuiButtonBaseCtrl::onRightMouseUp(const GuiEvent &event)
  230. {
  231. Con::executef( this, 2, "onRightClick" );
  232. Parent::onRightMouseUp( event );
  233. }
  234. //--------------------------------------------------------------------------
  235. bool GuiButtonBaseCtrl::onKeyDown(const GuiEvent &event)
  236. {
  237. //if the control is a dead end, kill the event
  238. if (!mActive)
  239. return true;
  240. //see if the key down is a return or space or not
  241. if ((event.keyCode == KEY_RETURN || event.keyCode == KEY_SPACE)
  242. && event.modifier == 0)
  243. {
  244. if ( mProfile->mSoundButtonDown )
  245. {
  246. AUDIOHANDLE handle = alxCreateSource( mProfile->mSoundButtonDown );
  247. alxPlay( handle );
  248. }
  249. return true;
  250. }
  251. //otherwise, pass the event to it's parent
  252. return Parent::onKeyDown(event);
  253. }
  254. //--------------------------------------------------------------------------
  255. bool GuiButtonBaseCtrl::onKeyUp(const GuiEvent &event)
  256. {
  257. //if the control is a dead end, kill the event
  258. if (!mActive)
  259. return true;
  260. //see if the key down is a return or space or not
  261. if (mDepressed &&
  262. (event.keyCode == KEY_RETURN || event.keyCode == KEY_SPACE) &&
  263. event.modifier == 0)
  264. {
  265. onAction();
  266. return true;
  267. }
  268. //otherwise, pass the event to it's parent
  269. return Parent::onKeyUp(event);
  270. }
  271. //---------------------------------------------------------------------------
  272. void GuiButtonBaseCtrl::setScriptValue(const char *value)
  273. {
  274. mStateOn = dAtob(value);
  275. // Update the console variable:
  276. if ( mConsoleVariable[0] )
  277. Con::setBoolVariable( mConsoleVariable, mStateOn );
  278. setUpdate();
  279. }
  280. //---------------------------------------------------------------------------
  281. const char *GuiButtonBaseCtrl::getScriptValue()
  282. {
  283. return mStateOn ? "1" : "0";
  284. }
  285. //---------------------------------------------------------------------------
  286. void GuiButtonBaseCtrl::onAction()
  287. {
  288. if(!mActive)
  289. return;
  290. if(mButtonType == ButtonTypeCheck)
  291. {
  292. mStateOn = mStateOn ? false : true;
  293. // Update the console variable:
  294. if ( mConsoleVariable[0] )
  295. Con::setBoolVariable( mConsoleVariable, mStateOn );
  296. // Execute the console command (if any). Unnecessary. Parent does this already.
  297. //if( mConsoleCommand[0] )
  298. // Con::evaluate( mConsoleCommand, false );
  299. }
  300. else if(mButtonType == ButtonTypeRadio)
  301. {
  302. mStateOn = true;
  303. messageSiblings(mRadioGroup);
  304. }
  305. setUpdate();
  306. // Provide and onClick script callback.
  307. if( isMethod("onClick") )
  308. Con::executef( this, 2, "onClick" );
  309. Parent::onAction();
  310. }
  311. //---------------------------------------------------------------------------
  312. void GuiButtonBaseCtrl::onMessage( GuiControl *sender, S32 msg )
  313. {
  314. Parent::onMessage(sender, msg);
  315. if( mRadioGroup == msg && mButtonType == ButtonTypeRadio )
  316. {
  317. setUpdate();
  318. mStateOn = ( sender == this );
  319. }
  320. }