guiTextCtrl.cc 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  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/color.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. if ( mProfile->mAutoSizeWidth )
  104. {
  105. if ( mProfile->mAutoSizeHeight )
  106. resize( mBounds.point, Point2I( mFont->getStrWidth((const UTF8 *) mText ), mFont->getHeight() + 4 ) );
  107. else
  108. resize( mBounds.point, Point2I( mFont->getStrWidth((const UTF8 *) mText ), mBounds.extent.y ) );
  109. }
  110. else if ( mProfile->mAutoSizeHeight )
  111. resize( mBounds.point, Point2I( mBounds.extent.x, mFont->getHeight() + 4 ) );
  112. return true;
  113. }
  114. void GuiTextCtrl::onSleep()
  115. {
  116. Parent::onSleep();
  117. mFont = NULL;
  118. }
  119. // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
  120. void GuiTextCtrl::setText(const char *txt)
  121. {
  122. //make sure we don't call this before onAdd();
  123. if( !mProfile )
  124. return;
  125. if (txt)
  126. dStrncpy(mText, (UTF8*)txt, MAX_STRING_LENGTH);
  127. mText[MAX_STRING_LENGTH] = '\0';
  128. //Make sure we have a font
  129. mProfile->incRefCount();
  130. mFont = mProfile->mFont;
  131. //Luma: If the font isn't found, we want to decrement the profile usage and return now or we may crash!
  132. if (mFont.isNull())
  133. {
  134. //decrement the profile referrence
  135. mProfile->decRefCount();
  136. return;
  137. }
  138. //resize
  139. if (mProfile->mAutoSizeWidth)
  140. {
  141. if (mProfile->mAutoSizeHeight)
  142. resize(mBounds.point, Point2I(mFont->getStrWidth((const UTF8 *)mText), mFont->getHeight() + 4));
  143. else
  144. resize(mBounds.point, Point2I(mFont->getStrWidth((const UTF8 *)mText), mBounds.extent.y));
  145. }
  146. else if (mProfile->mAutoSizeHeight)
  147. {
  148. resize(mBounds.point, Point2I(mBounds.extent.x, mFont->getHeight() + 4));
  149. }
  150. setVariable((char*)mText);
  151. setUpdate();
  152. //decrement the profile referrence
  153. mProfile->decRefCount();
  154. }
  155. void GuiTextCtrl::setTextID(const char *id)
  156. {
  157. S32 n = Con::getIntVariable(id, -1);
  158. if(n != -1)
  159. {
  160. mInitialTextID = StringTable->insert(id);
  161. setTextID(n);
  162. }
  163. }
  164. void GuiTextCtrl::setTextID(S32 id)
  165. {
  166. const UTF8 *str = getGUIString(id);
  167. if(str)
  168. setText((const char*)str);
  169. //mInitialTextID = id;
  170. }
  171. //------------------------------------------------------------------------------
  172. void GuiTextCtrl::onPreRender()
  173. {
  174. const char * var = getVariable();
  175. if(var && var[0] && dStricmp((char*)mText, var))
  176. setText(var);
  177. }
  178. //------------------------------------------------------------------------------
  179. void GuiTextCtrl::onRender(Point2I offset, const RectI &updateRect)
  180. {
  181. StringBuffer textBuffer(mText);
  182. ColorI fontColor = mProfile->mFontColor;
  183. if (mTruncateWhenUnfocused)
  184. {
  185. StringBuffer terminationString = "...";
  186. S32 width = mBounds.extent.x;
  187. StringBuffer truncatedBuffer = truncate(textBuffer, terminationString, width);
  188. const UTF8* truncatedBufferPtr = truncatedBuffer.getPtr8();
  189. dglSetBitmapModulation(fontColor);
  190. renderJustifiedText(offset, mBounds.extent, (char*)truncatedBufferPtr);
  191. }
  192. else
  193. {
  194. dglSetBitmapModulation(fontColor);
  195. renderJustifiedText(offset, mBounds.extent, (char*)mText);
  196. }
  197. //render the child controls
  198. renderChildControls(offset, updateRect);
  199. }
  200. // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
  201. const char *GuiTextCtrl::getScriptValue()
  202. {
  203. return getText();
  204. }
  205. void GuiTextCtrl::setScriptValue(const char *val)
  206. {
  207. setText(val);
  208. }
  209. StringBuffer GuiTextCtrl::truncate(StringBuffer buffer, StringBuffer terminationString, S32 width)
  210. {
  211. // Check if the buffer width exceeds the specified width
  212. S32 bufferWidth = textBufferWidth(buffer);
  213. // If not, just return the unmodified buffer
  214. if (bufferWidth <= width)
  215. return buffer;
  216. // Get the width of the termination string
  217. S32 terminationWidth = textBufferWidth(terminationString) + 6; // add an extra bit of space at the end
  218. // Calculate the new target width with space allowed for the termination string
  219. S32 targetWidth = width - terminationWidth;
  220. // If the target width is zero or less, just replace the entire buffer with the termination string
  221. if (targetWidth <= 0)
  222. return terminationString;
  223. // Step backwards in the buffer until we find the character that fits within the target width
  224. S32 currentWidth = 0;
  225. S32 count = 0;
  226. for(S32 i = 0; i < (S32)buffer.length(); i++)
  227. {
  228. if (currentWidth >= targetWidth)
  229. break;
  230. UTF16 c = buffer.getChar(i);
  231. currentWidth += mFont->getCharXIncrement( c );
  232. count++;
  233. }
  234. // Get the substring
  235. StringBuffer retBuffer = buffer.substring(0, count-2);
  236. // Append terminating string
  237. retBuffer.append(terminationString);
  238. return retBuffer;
  239. }
  240. S32 GuiTextCtrl::textBufferWidth(StringBuffer buffer)
  241. {
  242. S32 charLength = 0;
  243. for(S32 count=0; count< (S32)buffer.length(); count++)
  244. {
  245. UTF16 c = buffer.getChar(count);
  246. if(!mFont->isValidChar(c))
  247. continue;
  248. charLength += mFont->getCharXIncrement( c );
  249. }
  250. return charLength;
  251. }
  252. // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
  253. // EOF //