PageRenderTime 49ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/cocos2d/cocos/2d/CCTextFieldTTF.cpp

https://gitlab.com/gasabr/flappy-test
C++ | 711 lines | 555 code | 93 blank | 63 comment | 94 complexity | 92c03302e8ea0b3b4df93fe4173cdefb MD5 | raw file
  1. /****************************************************************************
  2. Copyright (c) 2010-2012 cocos2d-x.org
  3. Copyright (c) 2013-2014 Chukong Technologies Inc.
  4. http://www.cocos2d-x.org
  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. The above copyright notice and this permission notice shall be included in
  12. all copies or substantial portions of the Software.
  13. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. THE SOFTWARE.
  20. ****************************************************************************/
  21. #include "2d/CCTextFieldTTF.h"
  22. #include "base/CCDirector.h"
  23. #include "platform/CCFileUtils.h"
  24. #include "base/ccUTF8.h"
  25. #include "2d/CCSprite.h"
  26. NS_CC_BEGIN
  27. #define CURSOR_TIME_SHOW_HIDE 0.5f
  28. #define CURSOR_DEFAULT_CHAR '|'
  29. static int _calcCharCount(const char * text)
  30. {
  31. int n = 0;
  32. char ch = 0;
  33. while ((ch = *text))
  34. {
  35. CC_BREAK_IF(! ch);
  36. if (0x80 != (0xC0 & ch))
  37. {
  38. ++n;
  39. }
  40. ++text;
  41. }
  42. return n;
  43. }
  44. //////////////////////////////////////////////////////////////////////////
  45. // constructor and destructor
  46. //////////////////////////////////////////////////////////////////////////
  47. TextFieldTTF::TextFieldTTF()
  48. : _delegate(0)
  49. , _charCount(0)
  50. , _inputText("")
  51. , _placeHolder("") // prevent Label initWithString assertion
  52. , _colorText(Color4B::WHITE)
  53. , _secureTextEntry(false)
  54. ,_passwordStyleText("\u25CF")
  55. , _cursorEnabled(false)
  56. , _cursorPosition(0)
  57. , _cursorChar(CURSOR_DEFAULT_CHAR)
  58. , _cursorShowingTime(0.0f)
  59. , _isAttachWithIME(false)
  60. {
  61. _colorSpaceHolder.r = _colorSpaceHolder.g = _colorSpaceHolder.b = 127;
  62. _colorSpaceHolder.a = 255;
  63. }
  64. TextFieldTTF::~TextFieldTTF()
  65. {
  66. }
  67. //////////////////////////////////////////////////////////////////////////
  68. // static constructor
  69. //////////////////////////////////////////////////////////////////////////
  70. TextFieldTTF * TextFieldTTF::textFieldWithPlaceHolder(const std::string& placeholder, const Size& dimensions, TextHAlignment alignment, const std::string& fontName, float fontSize)
  71. {
  72. TextFieldTTF *ret = new (std::nothrow) TextFieldTTF();
  73. if(ret && ret->initWithPlaceHolder("", dimensions, alignment, fontName, fontSize))
  74. {
  75. ret->autorelease();
  76. if (placeholder.size()>0)
  77. {
  78. ret->setPlaceHolder(placeholder);
  79. }
  80. return ret;
  81. }
  82. CC_SAFE_DELETE(ret);
  83. return nullptr;
  84. }
  85. TextFieldTTF * TextFieldTTF::textFieldWithPlaceHolder(const std::string& placeholder, const std::string& fontName, float fontSize)
  86. {
  87. TextFieldTTF *ret = new (std::nothrow) TextFieldTTF();
  88. if(ret && ret->initWithPlaceHolder("", fontName, fontSize))
  89. {
  90. ret->autorelease();
  91. if (placeholder.size()>0)
  92. {
  93. ret->setPlaceHolder(placeholder);
  94. }
  95. return ret;
  96. }
  97. CC_SAFE_DELETE(ret);
  98. return nullptr;
  99. }
  100. //////////////////////////////////////////////////////////////////////////
  101. // initialize
  102. //////////////////////////////////////////////////////////////////////////
  103. bool TextFieldTTF::initWithPlaceHolder(const std::string& placeholder, const Size& dimensions, TextHAlignment alignment, const std::string& fontName, float fontSize)
  104. {
  105. setDimensions(dimensions.width, dimensions.height);
  106. setAlignment(alignment, TextVAlignment::CENTER);
  107. return initWithPlaceHolder(placeholder, fontName, fontSize);
  108. }
  109. bool TextFieldTTF::initWithPlaceHolder(const std::string& placeholder, const std::string& fontName, float fontSize)
  110. {
  111. _placeHolder = placeholder;
  112. do
  113. {
  114. // If fontName is ttf file and it corrected, use TTFConfig
  115. if (FileUtils::getInstance()->isFileExist(fontName))
  116. {
  117. TTFConfig ttfConfig(fontName.c_str(), fontSize, GlyphCollection::DYNAMIC);
  118. if (setTTFConfig(ttfConfig))
  119. {
  120. break;
  121. }
  122. }
  123. setSystemFontName(fontName);
  124. setSystemFontSize(fontSize);
  125. } while (false);
  126. Label::setTextColor(_colorSpaceHolder);
  127. Label::setString(_placeHolder);
  128. #if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
  129. // On desktop default enable cursor
  130. if (_currentLabelType == LabelType::TTF)
  131. {
  132. setCursorEnabled(true);
  133. }
  134. #endif
  135. return true;
  136. }
  137. //////////////////////////////////////////////////////////////////////////
  138. // IMEDelegate
  139. //////////////////////////////////////////////////////////////////////////
  140. bool TextFieldTTF::attachWithIME()
  141. {
  142. bool ret = IMEDelegate::attachWithIME();
  143. if (ret)
  144. {
  145. // open keyboard
  146. auto pGlView = Director::getInstance()->getOpenGLView();
  147. if (pGlView)
  148. {
  149. pGlView->setIMEKeyboardState(true);
  150. }
  151. }
  152. return ret;
  153. }
  154. bool TextFieldTTF::detachWithIME()
  155. {
  156. bool ret = IMEDelegate::detachWithIME();
  157. if (ret)
  158. {
  159. // close keyboard
  160. auto glView = Director::getInstance()->getOpenGLView();
  161. if (glView)
  162. {
  163. glView->setIMEKeyboardState(false);
  164. }
  165. }
  166. return ret;
  167. }
  168. void TextFieldTTF::didAttachWithIME()
  169. {
  170. setAttachWithIME(true);
  171. }
  172. void TextFieldTTF::didDetachWithIME()
  173. {
  174. setAttachWithIME(false);
  175. }
  176. bool TextFieldTTF::canAttachWithIME()
  177. {
  178. return (_delegate) ? (! _delegate->onTextFieldAttachWithIME(this)) : true;
  179. }
  180. bool TextFieldTTF::canDetachWithIME()
  181. {
  182. return (_delegate) ? (! _delegate->onTextFieldDetachWithIME(this)) : true;
  183. }
  184. void TextFieldTTF::insertText(const char * text, size_t len)
  185. {
  186. std::string insert(text, len);
  187. // insert \n means input end
  188. int pos = static_cast<int>(insert.find((char)TextFormatter::NewLine));
  189. if ((int)insert.npos != pos)
  190. {
  191. len = pos;
  192. insert.erase(pos);
  193. }
  194. if (len > 0)
  195. {
  196. if (_delegate && _delegate->onTextFieldInsertText(this, insert.c_str(), len))
  197. {
  198. // delegate doesn't want to insert text
  199. return;
  200. }
  201. int countInsertChar = _calcCharCount(insert.c_str());
  202. _charCount += countInsertChar;
  203. if (_cursorEnabled)
  204. {
  205. StringUtils::StringUTF8 stringUTF8;
  206. stringUTF8.replace(_inputText);
  207. stringUTF8.insert(_cursorPosition, insert);
  208. setCursorPosition(_cursorPosition + countInsertChar);
  209. setString(stringUTF8.getAsCharSequence());
  210. }
  211. else
  212. {
  213. std::string sText(_inputText);
  214. sText.append(insert);
  215. setString(sText);
  216. }
  217. }
  218. if ((int)insert.npos == pos) {
  219. return;
  220. }
  221. // '\n' inserted, let delegate process first
  222. if (_delegate && _delegate->onTextFieldInsertText(this, "\n", 1))
  223. {
  224. return;
  225. }
  226. // if delegate hasn't processed, detach from IME by default
  227. detachWithIME();
  228. }
  229. void TextFieldTTF::deleteBackward()
  230. {
  231. size_t len = _inputText.length();
  232. if (! len)
  233. {
  234. // there is no string
  235. return;
  236. }
  237. // get the delete byte number
  238. size_t deleteLen = 1; // default, erase 1 byte
  239. while(0x80 == (0xC0 & _inputText.at(len - deleteLen)))
  240. {
  241. ++deleteLen;
  242. }
  243. if (_delegate && _delegate->onTextFieldDeleteBackward(this, _inputText.c_str() + len - deleteLen, static_cast<int>(deleteLen)))
  244. {
  245. // delegate doesn't want to delete backwards
  246. return;
  247. }
  248. // if all text deleted, show placeholder string
  249. if (len <= deleteLen)
  250. {
  251. _inputText = "";
  252. _charCount = 0;
  253. setCursorPosition(0);
  254. setString(_inputText);
  255. return;
  256. }
  257. // set new input text
  258. if (_cursorEnabled)
  259. {
  260. if (_cursorPosition)
  261. {
  262. setCursorPosition(_cursorPosition - 1);
  263. StringUtils::StringUTF8 stringUTF8;
  264. stringUTF8.replace(_inputText);
  265. stringUTF8.deleteChar(_cursorPosition);
  266. _charCount = stringUTF8.length();
  267. setString(stringUTF8.getAsCharSequence());
  268. }
  269. }
  270. else
  271. {
  272. std::string text(_inputText.c_str(), len - deleteLen);
  273. setString(text);
  274. }
  275. }
  276. const std::string& TextFieldTTF::getContentText()
  277. {
  278. return _inputText;
  279. }
  280. void TextFieldTTF::setCursorPosition(std::size_t cursorPosition)
  281. {
  282. if (_cursorEnabled && cursorPosition <= (std::size_t)_charCount)
  283. {
  284. _cursorPosition = cursorPosition;
  285. _cursorShowingTime = CURSOR_TIME_SHOW_HIDE*2.0;
  286. }
  287. }
  288. void TextFieldTTF::setCursorFromPoint(const Vec2 &point, const Camera* camera)
  289. {
  290. if (_cursorEnabled)
  291. {
  292. // Reset Label, no cursor
  293. bool oldIsAttachWithIME = _isAttachWithIME;
  294. _isAttachWithIME = false;
  295. updateCursorDisplayText();
  296. Rect rect;
  297. rect.size = getContentSize();
  298. if (isScreenPointInRect(point, camera, getWorldToNodeTransform(), rect, nullptr))
  299. {
  300. int latterPosition = 0;
  301. for (; latterPosition < _lengthOfString; ++latterPosition)
  302. {
  303. if (_lettersInfo[latterPosition].valid)
  304. {
  305. auto sprite = getLetter(latterPosition);
  306. rect.size = sprite->getContentSize();
  307. if (isScreenPointInRect(point, camera, sprite->getWorldToNodeTransform(), rect, nullptr))
  308. {
  309. setCursorPosition(latterPosition);
  310. break;
  311. }
  312. }
  313. }
  314. if (latterPosition == _lengthOfString)
  315. {
  316. setCursorPosition(latterPosition);
  317. }
  318. }
  319. // Set cursor
  320. _isAttachWithIME = oldIsAttachWithIME;
  321. updateCursorDisplayText();
  322. }
  323. }
  324. void TextFieldTTF::setAttachWithIME(bool isAttachWithIME)
  325. {
  326. if (isAttachWithIME != _isAttachWithIME)
  327. {
  328. _isAttachWithIME = isAttachWithIME;
  329. if (_isAttachWithIME)
  330. {
  331. setCursorPosition(_charCount);
  332. }
  333. updateCursorDisplayText();
  334. }
  335. }
  336. void TextFieldTTF::setTextColor(const Color4B &color)
  337. {
  338. _colorText = color;
  339. if (!_inputText.empty())
  340. {
  341. Label::setTextColor(_colorText);
  342. }
  343. }
  344. void TextFieldTTF::visit(Renderer *renderer, const Mat4 &parentTransform, uint32_t parentFlags)
  345. {
  346. if (_delegate && _delegate->onVisit(this,renderer,parentTransform,parentFlags))
  347. {
  348. return;
  349. }
  350. Label::visit(renderer,parentTransform,parentFlags);
  351. }
  352. void TextFieldTTF::update(float delta)
  353. {
  354. if (_cursorEnabled && _isAttachWithIME)
  355. {
  356. _cursorShowingTime -= delta;
  357. if (_cursorShowingTime < -CURSOR_TIME_SHOW_HIDE)
  358. {
  359. _cursorShowingTime = CURSOR_TIME_SHOW_HIDE;
  360. }
  361. // before cursor inserted '\b', need next letter
  362. auto sprite = getLetter((int)_cursorPosition + 1);
  363. if (sprite)
  364. {
  365. if (_cursorShowingTime >= 0.0f)
  366. {
  367. sprite->setOpacity(255);
  368. }
  369. else
  370. {
  371. sprite->setOpacity(0);
  372. }
  373. sprite->setDirty(true);
  374. }
  375. }
  376. }
  377. const Color4B& TextFieldTTF::getColorSpaceHolder()
  378. {
  379. return _colorSpaceHolder;
  380. }
  381. void TextFieldTTF::setColorSpaceHolder(const Color3B& color)
  382. {
  383. _colorSpaceHolder.r = color.r;
  384. _colorSpaceHolder.g = color.g;
  385. _colorSpaceHolder.b = color.b;
  386. _colorSpaceHolder.a = 255;
  387. if (_inputText.empty())
  388. {
  389. Label::setTextColor(_colorSpaceHolder);
  390. }
  391. }
  392. void TextFieldTTF::setColorSpaceHolder(const Color4B& color)
  393. {
  394. _colorSpaceHolder = color;
  395. if (_inputText.empty())
  396. {
  397. Label::setTextColor(_colorSpaceHolder);
  398. }
  399. }
  400. //////////////////////////////////////////////////////////////////////////
  401. // properties
  402. //////////////////////////////////////////////////////////////////////////
  403. // input text property
  404. void TextFieldTTF::setString(const std::string &text)
  405. {
  406. std::string displayText;
  407. int charCount = 0;
  408. if (!text.empty())
  409. {
  410. _inputText = text;
  411. displayText = _inputText;
  412. charCount = _calcCharCount(_inputText.c_str());
  413. if (_secureTextEntry)
  414. {
  415. displayText = "";
  416. size_t length = charCount;
  417. while (length)
  418. {
  419. displayText.append(_passwordStyleText);
  420. --length;
  421. }
  422. }
  423. }
  424. else
  425. {
  426. _inputText = "";
  427. }
  428. if (_cursorEnabled && charCount != _charCount)
  429. {
  430. _cursorPosition = charCount;
  431. }
  432. if (_cursorEnabled)
  433. {
  434. // Need for recreate all letters in Label
  435. Label::removeAllChildrenWithCleanup(false);
  436. }
  437. // if there is no input text, display placeholder instead
  438. if (_inputText.empty() && (!_cursorEnabled || !_isAttachWithIME))
  439. {
  440. Label::setTextColor(_colorSpaceHolder);
  441. Label::setString(_placeHolder);
  442. }
  443. else
  444. {
  445. makeStringSupportCursor(displayText);
  446. Label::setTextColor(_colorText);
  447. Label::setString(displayText);
  448. }
  449. _charCount = charCount;
  450. }
  451. void TextFieldTTF::appendString(const std::string& text)
  452. {
  453. insertText(text.c_str(), text.length());
  454. }
  455. void TextFieldTTF::makeStringSupportCursor(std::string& displayText)
  456. {
  457. if (_cursorEnabled && _isAttachWithIME)
  458. {
  459. if (displayText.empty())
  460. {
  461. // \b - Next char not change x position
  462. displayText.push_back((char)TextFormatter::NextCharNoChangeX);
  463. displayText.push_back(_cursorChar);
  464. }
  465. else
  466. {
  467. StringUtils::StringUTF8 stringUTF8;
  468. stringUTF8.replace(displayText);
  469. if (_cursorPosition > stringUTF8.length())
  470. {
  471. _cursorPosition = stringUTF8.length();
  472. }
  473. std::string cursorChar;
  474. // \b - Next char not change x position
  475. cursorChar.push_back((char)TextFormatter::NextCharNoChangeX);
  476. cursorChar.push_back(_cursorChar);
  477. stringUTF8.insert(_cursorPosition, cursorChar);
  478. displayText = stringUTF8.getAsCharSequence();
  479. }
  480. }
  481. }
  482. void TextFieldTTF::updateCursorDisplayText()
  483. {
  484. // Update Label content
  485. setString(_inputText);
  486. }
  487. void TextFieldTTF::setCursorChar(char cursor)
  488. {
  489. if (_cursorChar != cursor)
  490. {
  491. _cursorChar = cursor;
  492. updateCursorDisplayText();
  493. }
  494. }
  495. void TextFieldTTF::controlKey(EventKeyboard::KeyCode keyCode)
  496. {
  497. if (_cursorEnabled)
  498. {
  499. switch (keyCode)
  500. {
  501. case EventKeyboard::KeyCode::KEY_HOME:
  502. case EventKeyboard::KeyCode::KEY_KP_HOME:
  503. setCursorPosition(0);
  504. updateCursorDisplayText();
  505. break;
  506. case EventKeyboard::KeyCode::KEY_END:
  507. setCursorPosition(_charCount);
  508. updateCursorDisplayText();
  509. break;
  510. case EventKeyboard::KeyCode::KEY_DELETE:
  511. case EventKeyboard::KeyCode::KEY_KP_DELETE:
  512. if (_cursorPosition < (std::size_t)_charCount)
  513. {
  514. StringUtils::StringUTF8 stringUTF8;
  515. stringUTF8.replace(_inputText);
  516. stringUTF8.deleteChar(_cursorPosition);
  517. setCursorPosition(_cursorPosition);
  518. _charCount = stringUTF8.length();
  519. setString(stringUTF8.getAsCharSequence());
  520. }
  521. break;
  522. case EventKeyboard::KeyCode::KEY_LEFT_ARROW:
  523. if (_cursorPosition)
  524. {
  525. setCursorPosition(_cursorPosition - 1);
  526. updateCursorDisplayText();
  527. }
  528. break;
  529. case EventKeyboard::KeyCode::KEY_RIGHT_ARROW:
  530. if (_cursorPosition < (std::size_t)_charCount)
  531. {
  532. setCursorPosition(_cursorPosition + 1);
  533. updateCursorDisplayText();
  534. }
  535. break;
  536. case EventKeyboard::KeyCode::KEY_ESCAPE:
  537. detachWithIME();
  538. break;
  539. default:
  540. break;
  541. }
  542. }
  543. }
  544. const std::string& TextFieldTTF::getString() const
  545. {
  546. return _inputText;
  547. }
  548. // place holder text property
  549. void TextFieldTTF::setPlaceHolder(const std::string& text)
  550. {
  551. _placeHolder = text;
  552. if (_inputText.empty())
  553. {
  554. Label::setTextColor(_colorSpaceHolder);
  555. Label::setString(_placeHolder);
  556. }
  557. }
  558. const std::string& TextFieldTTF::getPlaceHolder() const
  559. {
  560. return _placeHolder;
  561. }
  562. void TextFieldTTF::setCursorEnabled(bool enabled)
  563. {
  564. if (_currentLabelType == LabelType::TTF)
  565. {
  566. if (_cursorEnabled != enabled)
  567. {
  568. _cursorEnabled = enabled;
  569. if (_cursorEnabled)
  570. {
  571. _cursorPosition = _charCount;
  572. scheduleUpdate();
  573. }
  574. else
  575. {
  576. _cursorPosition = 0;
  577. unscheduleUpdate();
  578. }
  579. }
  580. }
  581. else
  582. {
  583. CCLOG("TextFieldTTF cursor worked only LabelType::TTF");
  584. }
  585. }
  586. // secureTextEntry
  587. void TextFieldTTF::setSecureTextEntry(bool value)
  588. {
  589. if (_secureTextEntry != value)
  590. {
  591. _secureTextEntry = value;
  592. setString(_inputText);
  593. }
  594. }
  595. void TextFieldTTF::setPasswordTextStyle(const std::string &text)
  596. {
  597. if (text.length() < 1)
  598. {
  599. return;
  600. }
  601. if (text != _passwordStyleText) {
  602. _passwordStyleText = text;
  603. setString(_inputText);
  604. }
  605. }
  606. std::string TextFieldTTF::getPasswordTextStyle()const
  607. {
  608. return _passwordStyleText;
  609. }
  610. bool TextFieldTTF::isSecureTextEntry() const
  611. {
  612. return _secureTextEntry;
  613. }
  614. NS_CC_END