guiTextCtrl.cc 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  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/consoleTypes.h"
  23. #include "console/console.h"
  24. #include "graphics/gColor.h"
  25. #include "gui/guiTextCtrl.h"
  26. #include "graphics/dgl.h"
  27. #include "gui/language/lang.h"
  28. // -----------------------------------------------------------------------------
  29. IMPLEMENT_CONOBJECT(GuiTextCtrl);
  30. GuiTextCtrl::GuiTextCtrl()
  31. {
  32. //default fonts
  33. mInitialText = StringTable->EmptyString;
  34. mInitialTextID = StringTable->EmptyString;
  35. mText[0] = '\0';
  36. mMaxStrLen = GuiTextCtrl::MAX_STRING_LENGTH;
  37. mTruncateWhenUnfocused = false;
  38. }
  39. ConsoleMethod( GuiTextCtrl, setText, void, 3, 3, "( newText ) Use the setText method to set the content of label to newText.\n"
  40. "@param newText A string representing the new value for this label.\n"
  41. "@return No return value")
  42. {
  43. object->setText( argv[2] );
  44. }
  45. ConsoleMethod( GuiTextCtrl, setTextID, void, 3, 3, "( int newTextID ) Set the textID to a new value.\n"
  46. "@param newTextID The desired new ID\n"
  47. "@return No return value.")
  48. {
  49. object->setTextID( argv[2] );
  50. }
  51. void GuiTextCtrl::initPersistFields()
  52. {
  53. Parent::initPersistFields();
  54. //addField( "text", TypeCaseString, Offset( mInitialText, GuiTextCtrl ) );
  55. addProtectedField("text", TypeCaseString, Offset(mInitialText, GuiTextCtrl), setText, getTextProperty, "");
  56. addField( "textID", TypeString, Offset( mInitialTextID, GuiTextCtrl ) );
  57. addField( "maxLength", TypeS32, Offset( mMaxStrLen, GuiTextCtrl ) );
  58. addField("truncate", TypeBool, Offset(mTruncateWhenUnfocused, GuiTextCtrl));
  59. }
  60. // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
  61. bool GuiTextCtrl::onAdd()
  62. {
  63. if(!Parent::onAdd())
  64. return false;
  65. dStrncpy(mText, (UTF8*)mInitialText, MAX_STRING_LENGTH);
  66. mText[MAX_STRING_LENGTH] = '\0';
  67. return true;
  68. }
  69. void GuiTextCtrl::inspectPostApply()
  70. {
  71. Parent::inspectPostApply();
  72. if(mInitialTextID && *mInitialTextID != 0)
  73. setTextID(mInitialTextID);
  74. else
  75. setText(mInitialText);
  76. }
  77. bool GuiTextCtrl::onWake()
  78. {
  79. if ( !Parent::onWake() )
  80. return false;
  81. mFont = mProfile->mFont;
  82. AssertFatal(mFont, "GuiTextCtrl::onWake: invalid font in profile" );
  83. if(mInitialTextID && *mInitialTextID != 0)
  84. setTextID(mInitialTextID);
  85. if ( mConsoleVariable[0] )
  86. {
  87. const char *txt = Con::getVariable( mConsoleVariable );
  88. if ( txt )
  89. {
  90. if ( dStrlen( txt ) > (U32)mMaxStrLen )
  91. {
  92. char* buf = new char[mMaxStrLen + 1];
  93. dStrncpy( buf, txt, mMaxStrLen );
  94. buf[mMaxStrLen] = 0;
  95. setScriptValue( buf );
  96. delete [] buf;
  97. }
  98. else
  99. setScriptValue( txt );
  100. }
  101. }
  102. //resize
  103. //DEPRECIATED
  104. /*
  105. if ( mProfile->mAutoSizeWidth )
  106. {
  107. if ( mProfile->mAutoSizeHeight )
  108. resize( mBounds.point, Point2I( mFont->getStrWidth((const UTF8 *) mText ), mFont->getHeight() + 4 ) );
  109. else
  110. resize( mBounds.point, Point2I( mFont->getStrWidth((const UTF8 *) mText ), mBounds.extent.y ) );
  111. }
  112. else if ( mProfile->mAutoSizeHeight )
  113. resize( mBounds.point, Point2I( mBounds.extent.x, mFont->getHeight() + 4 ) );
  114. */
  115. return true;
  116. }
  117. void GuiTextCtrl::onSleep()
  118. {
  119. Parent::onSleep();
  120. mFont = NULL;
  121. }
  122. // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
  123. void GuiTextCtrl::setText(const char *txt)
  124. {
  125. //make sure we don't call this before onAdd();
  126. if( !mProfile )
  127. return;
  128. if (txt)
  129. dStrncpy(mText, (UTF8*)txt, MAX_STRING_LENGTH);
  130. mText[MAX_STRING_LENGTH] = '\0';
  131. //Make sure we have a font
  132. mProfile->incRefCount();
  133. mFont = mProfile->mFont;
  134. //Luma: If the font isn't found, we want to decrement the profile usage and return now or we may crash!
  135. if (mFont.isNull())
  136. {
  137. //decrement the profile referrence
  138. mProfile->decRefCount();
  139. return;
  140. }
  141. //resize
  142. //DEPRECIATED
  143. /*
  144. if (mProfile->mAutoSizeWidth)
  145. {
  146. if (mProfile->mAutoSizeHeight)
  147. resize(mBounds.point, Point2I(mFont->getStrWidth((const UTF8 *)mText), mFont->getHeight() + 4));
  148. else
  149. resize(mBounds.point, Point2I(mFont->getStrWidth((const UTF8 *)mText), mBounds.extent.y));
  150. }
  151. else if (mProfile->mAutoSizeHeight)
  152. {
  153. resize(mBounds.point, Point2I(mBounds.extent.x, mFont->getHeight() + 4));
  154. }
  155. */
  156. setVariable((char*)mText);
  157. setUpdate();
  158. //decrement the profile referrence
  159. mProfile->decRefCount();
  160. }
  161. void GuiTextCtrl::setTextID(const char *id)
  162. {
  163. S32 n = Con::getIntVariable(id, -1);
  164. if(n != -1)
  165. {
  166. mInitialTextID = StringTable->insert(id);
  167. setTextID(n);
  168. }
  169. }
  170. void GuiTextCtrl::setTextID(S32 id)
  171. {
  172. const UTF8 *str = getGUIString(id);
  173. if(str)
  174. setText((const char*)str);
  175. //mInitialTextID = id;
  176. }
  177. //------------------------------------------------------------------------------
  178. void GuiTextCtrl::onPreRender()
  179. {
  180. const char * var = getVariable();
  181. if(var && var[0] && dStricmp((char*)mText, var))
  182. setText(var);
  183. }
  184. //------------------------------------------------------------------------------
  185. void GuiTextCtrl::onRender(Point2I offset, const RectI &updateRect)
  186. {
  187. StringBuffer textBuffer(mText);
  188. ColorI fontColor = mProfile->mFontColor;
  189. if (mTruncateWhenUnfocused)
  190. {
  191. StringBuffer terminationString = "...";
  192. S32 width = mBounds.extent.x;
  193. StringBuffer truncatedBuffer = truncate(textBuffer, terminationString, width);
  194. const UTF8* truncatedBufferPtr = truncatedBuffer.getPtr8();
  195. dglSetBitmapModulation(fontColor);
  196. renderText(offset, mBounds.extent, (char*)truncatedBufferPtr, mProfile);
  197. }
  198. else
  199. {
  200. dglSetBitmapModulation(fontColor);
  201. renderText(offset, mBounds.extent, (char*)mText, mProfile);
  202. }
  203. //render the child controls
  204. renderChildControls(offset, mBounds, updateRect);
  205. }
  206. // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
  207. const char *GuiTextCtrl::getScriptValue()
  208. {
  209. return getText();
  210. }
  211. void GuiTextCtrl::setScriptValue(const char *val)
  212. {
  213. setText(val);
  214. }
  215. StringBuffer GuiTextCtrl::truncate(StringBuffer buffer, StringBuffer terminationString, S32 width)
  216. {
  217. // Check if the buffer width exceeds the specified width
  218. S32 bufferWidth = textBufferWidth(buffer);
  219. // If not, just return the unmodified buffer
  220. if (bufferWidth <= width)
  221. return buffer;
  222. // Get the width of the termination string
  223. S32 terminationWidth = textBufferWidth(terminationString) + 6; // add an extra bit of space at the end
  224. // Calculate the new target width with space allowed for the termination string
  225. S32 targetWidth = width - terminationWidth;
  226. // If the target width is zero or less, just replace the entire buffer with the termination string
  227. if (targetWidth <= 0)
  228. return terminationString;
  229. // Step backwards in the buffer until we find the character that fits within the target width
  230. S32 currentWidth = 0;
  231. S32 count = 0;
  232. for(S32 i = 0; i < (S32)buffer.length(); i++)
  233. {
  234. if (currentWidth >= targetWidth)
  235. break;
  236. UTF16 c = buffer.getChar(i);
  237. currentWidth += mFont->getCharXIncrement( c );
  238. count++;
  239. }
  240. // Get the substring
  241. StringBuffer retBuffer = buffer.substring(0, count-2);
  242. // Append terminating string
  243. retBuffer.append(terminationString);
  244. return retBuffer;
  245. }
  246. S32 GuiTextCtrl::textBufferWidth(StringBuffer buffer)
  247. {
  248. S32 charLength = 0;
  249. for(S32 count=0; count< (S32)buffer.length(); count++)
  250. {
  251. UTF16 c = buffer.getChar(count);
  252. if(!mFont->isValidChar(c))
  253. continue;
  254. charLength += mFont->getCharXIncrement( c );
  255. }
  256. return charLength;
  257. }
  258. // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
  259. // EOF //