LineEdit.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2011 Lasse Öörni
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. #include "Precompiled.h"
  24. #include "LineEdit.h"
  25. #include "Text.h"
  26. #include "UIEvents.h"
  27. #include "DebugNew.h"
  28. LineEdit::LineEdit(const std::string& name, const std::string& text) :
  29. BorderImage(name),
  30. mEchoCharacter(0),
  31. mCursorBlinkRate(1.0f),
  32. mCursorBlinkTimer(0.0f),
  33. mMaxLength(0),
  34. mDefocus(false)
  35. {
  36. mClipChildren = true;
  37. mEnabled = true;
  38. mFocusable = true;
  39. mText = new Text();
  40. mCursor = new BorderImage();
  41. addChild(mText);
  42. addChild(mCursor);
  43. // Show cursor on top of text
  44. mCursor->setPriority(1);
  45. setText(text);
  46. }
  47. LineEdit::~LineEdit()
  48. {
  49. }
  50. void LineEdit::setStyle(const XMLElement& element, ResourceCache* cache)
  51. {
  52. BorderImage::setStyle(element, cache);
  53. if (element.hasChildElement("cursorblinkrate"))
  54. setCursorBlinkRate(element.getChildElement("cursorblinkrate").getFloat("value"));
  55. if (element.hasChildElement("echocharacter"))
  56. {
  57. std::string text = element.getChildElement("echocharacter").getString("value");
  58. if (text.length())
  59. setEchoCharacter(text[0]);
  60. }
  61. if (element.hasChildElement("maxlength"))
  62. setMaxLength(element.getChildElement("maxlength").getInt("value"));
  63. XMLElement textElem = element.getChildElement("text");
  64. if (textElem)
  65. {
  66. if (textElem.hasAttribute("value"))
  67. setText(textElem.getString("value"));
  68. mText->setStyle(textElem, cache);
  69. }
  70. XMLElement cursorElem = element.getChildElement("cursor");
  71. if (cursorElem)
  72. mCursor->setStyle(cursorElem, cache);
  73. }
  74. void LineEdit::update(float timeStep)
  75. {
  76. if (mCursorBlinkRate > 0.0f)
  77. mCursorBlinkTimer = fmodf(mCursorBlinkTimer + mCursorBlinkRate * timeStep, 1.0f);
  78. else
  79. mCursorBlinkTimer = 0.0f;
  80. bool cursorVisible = false;
  81. if (mFocus)
  82. {
  83. int textLength = 0;
  84. const std::vector<int>& rowWidths = mText->getRowWidths();
  85. if (rowWidths.size())
  86. textLength = rowWidths[0];
  87. // This assumes text alignment is top-left
  88. mCursor->setPosition(mText->getPosition() + IntVector2(textLength, 0));
  89. mCursor->setSize(mCursor->getWidth(), mText->getRowHeight());
  90. cursorVisible = mCursorBlinkTimer < 0.5f;
  91. // Scroll if text is longer than what can be visible at once
  92. int scrollThreshold = max(getWidth() - mClipBorder.mLeft - mClipBorder.mRight - mCursor->getWidth(), 0);
  93. if (textLength > scrollThreshold)
  94. setChildOffset(IntVector2(-(textLength - scrollThreshold), 0));
  95. else
  96. setChildOffset(IntVector2::sZero);
  97. }
  98. mCursor->setVisible(cursorVisible);
  99. if (mDefocus)
  100. {
  101. setFocus(false);
  102. mDefocus = false;
  103. }
  104. }
  105. void LineEdit::onChar(unsigned char c)
  106. {
  107. unsigned currentLength = mLine.length();
  108. bool changed = false;
  109. if (c == '\b')
  110. {
  111. if (mLine.length())
  112. {
  113. mLine = mLine.substr(0, currentLength - 1);
  114. changed = true;
  115. }
  116. }
  117. else if (c == '\r')
  118. {
  119. using namespace TextFinished;
  120. VariantMap eventData;
  121. eventData[P_ELEMENT] = (void*)this;
  122. sendEvent(EVENT_TEXTFINISHED, eventData);
  123. mDefocus = true;
  124. }
  125. else if (c == 27)
  126. mDefocus = true;
  127. else if ((c >= 0x20) && ((!mMaxLength) || (currentLength < mMaxLength)))
  128. {
  129. mLine += (char)c;
  130. changed = true;
  131. }
  132. if (changed)
  133. {
  134. // Restart cursor blinking from the visible state
  135. mCursorBlinkTimer = 0.0f;
  136. updateText();
  137. using namespace TextChanged;
  138. VariantMap eventData;
  139. eventData[P_ELEMENT] = (void*)this;
  140. eventData[P_TEXT] = mLine;
  141. sendEvent(EVENT_TEXTFINISHED, eventData);
  142. }
  143. }
  144. void LineEdit::setText(const std::string& text)
  145. {
  146. mLine = text;
  147. mText->setText(text);
  148. updateText();
  149. }
  150. void LineEdit::setEchoCharacter(char c)
  151. {
  152. mEchoCharacter = c;
  153. updateText();
  154. }
  155. void LineEdit::setCursorBlinkRate(float rate)
  156. {
  157. mCursorBlinkRate = max(rate, 0.0f);
  158. }
  159. void LineEdit::setMaxLength(unsigned length)
  160. {
  161. mMaxLength = length;
  162. }
  163. void LineEdit::updateText()
  164. {
  165. if (!mEchoCharacter)
  166. mText->setText(mLine);
  167. else
  168. {
  169. std::string echoText;
  170. echoText.resize(mLine.length());
  171. for (unsigned i = 0; i < mLine.length(); ++i)
  172. echoText[i] = mEchoCharacter;
  173. mText->setText(echoText);
  174. }
  175. }