MyGUI  3.2.0
MyGUI_EditBox.cpp
Go to the documentation of this file.
1 
6 /*
7  This file is part of MyGUI.
8 
9  MyGUI is free software: you can redistribute it and/or modify
10  it under the terms of the GNU Lesser General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  (at your option) any later version.
13 
14  MyGUI is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public License
20  along with MyGUI. If not, see <http://www.gnu.org/licenses/>.
21 */
22 #include "MyGUI_Precompiled.h"
23 #include "MyGUI_EditBox.h"
24 #include "MyGUI_Gui.h"
25 #include "MyGUI_ResourceSkin.h"
26 #include "MyGUI_SkinManager.h"
27 #include "MyGUI_InputManager.h"
28 #include "MyGUI_ClipboardManager.h"
29 #include "MyGUI_PointerManager.h"
30 #include "MyGUI_ISubWidgetText.h"
31 #include "MyGUI_ScrollBar.h"
32 
33 #include <ctype.h>
34 
35 namespace MyGUI
36 {
37 
38  const float EDIT_CURSOR_TIMER = 0.7f;
39  const float EDIT_ACTION_MOUSE_TIMER = 0.05f;
40  const int EDIT_CURSOR_MAX_POSITION = 100000;
41  const int EDIT_CURSOR_MIN_POSITION = -100000;
42  const size_t EDIT_MAX_UNDO = 128;
43  const size_t EDIT_DEFAULT_MAX_TEXT_LENGTH = 2048;
44  const float EDIT_OFFSET_HORZ_CURSOR = 10.0f; // дополнительное смещение для курсора
45  const int EDIT_ACTION_MOUSE_ZONE = 1500; // область для восприятия мыши за пределом эдита
46  const std::string EDIT_CLIPBOARD_TYPE_TEXT = "Text";
47  const int EDIT_MOUSE_WHEEL = 50; // область для восприятия мыши за пределом эдита
48 
50  mIsPressed(false),
51  mIsFocus(false),
52  mCursorActive(false),
53  mCursorTimer(0),
54  mActionMouseTimer(0),
55  mCursorPosition(0),
56  mTextLength(0),
57  mStartSelect(ITEM_NONE),
58  mEndSelect(0),
59  mMouseLeftPressed(false),
60  mModeReadOnly(false),
61  mModePassword(false),
62  mModeMultiline(false),
63  mModeStatic(false),
64  mModeWordWrap(false),
65  mTabPrinting(false),
66  mCharPassword('*'),
67  mOverflowToTheLeft(false),
68  mMaxTextLength(EDIT_DEFAULT_MAX_TEXT_LENGTH),
69  mClientText(nullptr)
70  {
72  }
73 
75  {
77 
79 
80  // FIXME нам нужен фокус клавы
81  setNeedKeyFocus(true);
82 
83  assignWidget(mClient, "Client");
84  if (mClient != nullptr)
85  {
94  }
95 
96  assignWidget(mVScroll, "VScroll");
97  if (mVScroll != nullptr)
98  {
100  }
101 
102  assignWidget(mHScroll, "HScroll");
103  if (mHScroll != nullptr)
104  {
106  }
107 
109  if (mClient != nullptr)
110  {
112  if (text)
113  mClientText = text;
114  }
115 
117 
118  // первоначальная инициализация курсора
119  if (mClientText != nullptr)
121 
122  updateSelectText();
123  }
124 
126  {
127  mClient = nullptr;
128  mClientText = nullptr;
129  mVScroll = nullptr;
130  mHScroll = nullptr;
131 
133  }
134 
136  {
137  if ((_old == mClient) || (mIsFocus))
138  return;
139 
140  mIsFocus = true;
141  updateEditState();
142  }
143 
145  {
146  if ((_new == mClient) || (!mIsFocus))
147  return;
148 
149  mIsFocus = false;
150  updateEditState();
151  }
152 
153  void EditBox::notifyMousePressed(Widget* _sender, int _left, int _top, MouseButton _id)
154  {
155  if (mClientText == nullptr)
156  return;
157 
158  // в статике все недоступно
159  if (mModeStatic)
160  return;
161 
166  mCursorTimer = 0;
167  updateSelectText();
168 
169  if (_id == MouseButton::Left)
170  mMouseLeftPressed = true;
171  }
172 
173  void EditBox::notifyMouseReleased(Widget* _sender, int _left, int _top, MouseButton _id)
174  {
175  // сбрасываем всегда
176  mMouseLeftPressed = false;
177  }
178 
179  void EditBox::notifyMouseDrag(Widget* _sender, int _left, int _top, MouseButton _id)
180  {
181  if (_id != MouseButton::Left)
182  return;
183 
184  if (mClientText == nullptr)
185  return;
186 
187  // в статике все недоступно
188  if (mModeStatic)
189  return;
190 
191  // останавливаем курсор
193 
194  // сбрасываем все таймеры
195  mCursorTimer = 0;
196  mActionMouseTimer = 0;
197 
198  size_t Old = mCursorPosition;
199  IntPoint point(_left, _top);
201  if (Old == mCursorPosition)
202  return;
203 
205 
206  // если не было выделения
207  if (mStartSelect == ITEM_NONE)
208  mStartSelect = Old;
209 
210  // меняем выделение
211  mEndSelect = (size_t)mCursorPosition;
212  if (mStartSelect > mEndSelect)
214  else
216 
217  }
218 
220  {
221  if (mClientText == nullptr)
222  return;
223 
224  // в статике все недоступно
225  if (mModeStatic)
226  return;
227 
229 
230  size_t cursorPosition = mClientText->getCursorPosition(lastPressed);
231  mStartSelect = cursorPosition;
232  mEndSelect = cursorPosition;
233 
234  UString text = this->getOnlyText();
235  UString::reverse_iterator iterBack = text.rend() - cursorPosition;
236  UString::iterator iterForw = text.begin() + cursorPosition;
237 
238  while (iterBack != text.rend())
239  {
240  if (((*iterBack) < 265) && (ispunct(*iterBack) || isspace(*iterBack)))
241  break;
242  ++iterBack;
243  mStartSelect--;
244  }
245  while (iterForw != text.end())
246  {
247  if (((*iterForw) < 265) && (ispunct(*iterForw) || isspace(*iterForw)))
248  break;
249  ++iterForw;
250  mEndSelect++;
251  }
252 
255  }
256 
257  void EditBox::onMouseDrag(int _left, int _top, MouseButton _id)
258  {
259  notifyMouseDrag(nullptr, _left, _top, _id);
260 
261  Base::onMouseDrag(_left, _top, _id);
262  }
263 
265  {
266  if (!mIsPressed)
267  {
268  mIsPressed = true;
269  updateEditState();
270 
271  if (!mModeStatic)
272  {
273  if (mClientText != nullptr)
274  {
275  mCursorActive = true;
276  Gui::getInstance().eventFrameStart += newDelegate(this, &EditBox::frameEntered);
279  mCursorTimer = 0;
280  }
281  }
282  }
283 
284  Base::onKeySetFocus(_old);
285  }
286 
288  {
289  if (mIsPressed)
290  {
291  mIsPressed = false;
292  updateEditState();
293 
294  if (mClientText != nullptr)
295  {
296  mCursorActive = false;
297  Gui::getInstance().eventFrameStart -= newDelegate(this, &EditBox::frameEntered);
300  }
301  }
302 
303  Base::onKeyLostFocus(_new);
304  }
305 
307  {
308  if (mClientText == nullptr || mClient == nullptr)
309  {
310  Base::onKeyButtonPressed(_key, _char);
311  return;
312  }
313 
314  // в статическом режиме ничего не доступно
315  if (mModeStatic)
316  {
317  Base::onKeyButtonPressed(_key, _char);
318  return;
319  }
320 
322 
324  mCursorTimer = 0.0f;
325 
326  if (_key == KeyCode::Escape)
327  {
329  }
330  else if (_key == KeyCode::Backspace)
331  {
332  // если нуно то удаляем выделенный текст
333  if (!mModeReadOnly)
334  {
335  // сбрасываем повтор
336  commandResetRedo();
337 
338  if (!deleteTextSelect(true))
339  {
340  // прыгаем на одну назад и удаляем
341  if (mCursorPosition != 0)
342  {
343  mCursorPosition--;
344  eraseText(mCursorPosition, 1, true);
345  }
346  }
347  // отсылаем событие о изменении
348  eventEditTextChange(this);
349  }
350 
351  }
352  else if (_key == KeyCode::Delete)
353  {
354  if (input.isShiftPressed())
355  {
356  // сбрасываем повтор
357  commandResetRedo();
358 
359  commandCut();
360  }
361  else if (!mModeReadOnly)
362  {
363  // сбрасываем повтор
364  commandResetRedo();
365 
366  // если нуно то удаляем выделенный текст
367  if (!deleteTextSelect(true))
368  {
370  {
371  eraseText(mCursorPosition, 1, true);
372  }
373  }
374  // отсылаем событие о изменении
375  eventEditTextChange(this);
376  }
377 
378  }
379  else if (_key == KeyCode::Insert)
380  {
381  if (input.isShiftPressed())
382  {
383  // сбрасываем повтор
384  commandResetRedo();
385 
386  commandPast();
387  }
388  else if (input.isControlPressed())
389  {
390  commandCopy();
391  }
392 
393  }
394  else if ((_key == KeyCode::Return) || (_key == KeyCode::NumpadEnter))
395  {
396  // работаем только в режиме редактирования
397  if (!mModeReadOnly)
398  {
399  if ((mModeMultiline) && (!input.isControlPressed()))
400  {
401  // сбрасываем повтор
402  commandResetRedo();
403 
404  // попытка объединения двух комманд
405  size_t size = mVectorUndoChangeInfo.size();
406  // непосредственно операции
407  deleteTextSelect(true);
409  // проверяем на возможность объединения
410  if ((size + 2) == mVectorUndoChangeInfo.size())
411  commandMerge();
412  // отсылаем событие о изменении
413  eventEditTextChange(this);
414  }
415  // при сингл лайн и и мульти+сонтрол шлем эвент
416  else
417  {
418  eventEditSelectAccept(this);
419  }
420  }
421 
422  }
423  else if (_key == KeyCode::ArrowRight)
424  {
426  {
427  mCursorPosition ++;
429  updateSelectText();
430  }
431  // сбрасываем выделение
432  else if (isTextSelection() && !input.isShiftPressed())
433  {
434  resetSelect();
435  }
436 
437  }
438  else if (_key == KeyCode::ArrowLeft)
439  {
440  if (mCursorPosition != 0)
441  {
442  mCursorPosition --;
444  updateSelectText();
445  }
446  // сбрасываем выделение
447  else if (isTextSelection() && !input.isShiftPressed())
448  {
449  resetSelect();
450  }
451 
452  }
453  else if (_key == KeyCode::ArrowUp)
454  {
456  point.top -= mClientText->getFontHeight();
457  size_t old = mCursorPosition;
459  // самая верхняя строчка
460  if (old == mCursorPosition)
461  {
462  if (mCursorPosition != 0)
463  {
464  mCursorPosition = 0;
466  updateSelectText();
467  }
468  // сбрасываем выделение
469  else if (isTextSelection() && !input.isShiftPressed())
470  {
471  resetSelect();
472  }
473  }
474  else
475  {
477  updateSelectText();
478  }
479 
480  }
481  else if (_key == KeyCode::ArrowDown)
482  {
484  point.top += mClientText->getFontHeight();
485  size_t old = mCursorPosition;
487  // самая нижняя строчка
488  if (old == mCursorPosition)
489  {
491  {
494  updateSelectText();
495  }
496  // сбрасываем выделение
497  else if (isTextSelection() && !input.isShiftPressed())
498  {
499  resetSelect();
500  }
501  }
502  else
503  {
505  updateSelectText();
506  }
507 
508  }
509  else if (_key == KeyCode::Home)
510  {
511  // в начало строки
512  if (!input.isControlPressed())
513  {
516  size_t old = mCursorPosition;
518  if (old != mCursorPosition)
519  {
521  updateSelectText();
522  }
523  else if (isTextSelection() && !input.isShiftPressed())
524  {
525  resetSelect();
526  }
527  }
528  // в начало всего текста
529  else
530  {
531  if (0 != mCursorPosition)
532  {
533  mCursorPosition = 0;
535  updateSelectText();
536  }
537  else if (isTextSelection() && !input.isShiftPressed())
538  {
539  resetSelect();
540  }
541  }
542 
543  }
544  else if (_key == KeyCode::End)
545  {
546  // в конец строки
547  if (!input.isControlPressed())
548  {
551  size_t old = mCursorPosition;
553  if (old != mCursorPosition)
554  {
556  updateSelectText();
557  }
558  else if (isTextSelection() && !input.isShiftPressed())
559  {
560  resetSelect();
561  }
562  }
563  // в самый конец
564  else
565  {
567  {
570  updateSelectText();
571  }
572  else if (isTextSelection() && !input.isShiftPressed())
573  {
574  resetSelect();
575  }
576  }
577 
578  }
579  else if (_key == KeyCode::PageUp)
580  {
581  // на размер окна, но не меньше одной строки
584  size_t old = mCursorPosition;
586  // самая верхняя строчка
587  if (old == mCursorPosition)
588  {
589  if (mCursorPosition != 0)
590  {
591  mCursorPosition = 0;
593  updateSelectText();
594  }
595  // сбрасываем выделение
596  else if (isTextSelection() && !input.isShiftPressed())
597  {
598  resetSelect();
599  }
600  }
601  else
602  {
604  updateSelectText();
605  }
606 
607  }
608  else if (_key == KeyCode::PageDown)
609  {
610  // на размер окна, но не меньше одной строки
613  size_t old = mCursorPosition;
615  // самая нижняя строчка
616  if (old == mCursorPosition)
617  {
619  {
622  updateSelectText();
623  }
624  // сбрасываем выделение
625  else if (isTextSelection() && !input.isShiftPressed())
626  {
627  resetSelect();
628  }
629  }
630  else
631  {
633  updateSelectText();
634  }
635 
636  }
637  else if ((_key == KeyCode::LeftShift) || (_key == KeyCode::RightShift))
638  {
639  // для правильно выделения
640  if (mStartSelect == ITEM_NONE)
641  {
643  }
644  }
645  else if (_char != 0)
646  {
647  // если не нажат контрл, то обрабатываем как текст
648  if (!input.isControlPressed())
649  {
650  if (!mModeReadOnly)
651  {
652  // сбрасываем повтор
653  commandResetRedo();
654 
655  // таб только если нужно
656  if (_char != '\t' || mTabPrinting)
657  {
658  // попытка объединения двух комманд
659  size_t size = mVectorUndoChangeInfo.size();
660  // непосредственно операции
661  deleteTextSelect(true);
663  // проверяем на возможность объединения
664  if ((size + 2) == mVectorUndoChangeInfo.size())
665  commandMerge();
666  // отсылаем событие о изменении
667  eventEditTextChange(this);
668  }
669  }
670  }
671  else if (_key == KeyCode::C)
672  {
673  commandCopy();
674 
675  }
676  else if (_key == KeyCode::X)
677  {
678  // сбрасываем повтор
679  commandResetRedo();
680 
681  commandCut();
682 
683  }
684  else if (_key == KeyCode::V)
685  {
686  // сбрасываем повтор
687  commandResetRedo();
688 
689  commandPast();
690 
691  }
692  else if (_key == KeyCode::A)
693  {
694  // выделяем весь текст
696 
697  }
698  else if (_key == KeyCode::Z)
699  {
700  // отмена
701  commandUndo();
702 
703  }
704  else if (_key == KeyCode::Y)
705  {
706  // повтор
707  commandRedo();
708 
709  }
710  }
711 
712  Base::onKeyButtonPressed(_key, _char);
713  }
714 
715  void EditBox::frameEntered(float _frame)
716  {
717  if (mClientText == nullptr)
718  return;
719 
720  // в статике все недоступно
721  if (mModeStatic)
722  return;
723 
724  if (mCursorActive)
725  {
726  mCursorTimer += _frame;
727 
729  {
733  }
734  }
735 
736  // сдвигаем курсор по положению мыши
737  if (mMouseLeftPressed)
738  {
739  mActionMouseTimer += _frame;
740 
742  {
744  const IntRect& view = mClient->getAbsoluteRect();
745  mouse.left -= view.left;
746  mouse.top -= view.top;
747  IntPoint point;
748 
749  bool action = false;
750 
751  // вверх на одну строчку
752  if ((mouse.top < 0) && (mouse.top > -EDIT_ACTION_MOUSE_ZONE))
753  {
754  if ((mouse.left > 0) && (mouse.left <= mClient->getWidth()))
755  {
757  point.top -= mClientText->getFontHeight();
758  action = true;
759  }
760  }
761  // вниз на одну строчку
762  else if ((mouse.top > mClient->getHeight()) && (mouse.top < (mClient->getHeight() + EDIT_ACTION_MOUSE_ZONE)))
763  {
764  if ((mouse.left > 0) && (mouse.left <= mClient->getWidth()))
765  {
767  point.top += mClientText->getFontHeight();
768  action = true;
769  }
770  }
771 
772  // влево на небольшое расстояние
773  if ((mouse.left < 0) && (mouse.left > -EDIT_ACTION_MOUSE_ZONE))
774  {
776  point.left -= (int)EDIT_OFFSET_HORZ_CURSOR;
777  action = true;
778  }
779  // вправо на небольшое расстояние
780  else if ((mouse.left > mClient->getWidth()) && (mouse.left < (mClient->getWidth() + EDIT_ACTION_MOUSE_ZONE)))
781  {
783  point.left += (int)EDIT_OFFSET_HORZ_CURSOR;
784  action = true;
785  }
786 
787  if (action)
788  {
789  size_t old = mCursorPosition;
791 
792  if (old != mCursorPosition)
793  {
795 
796  mEndSelect = (size_t)mCursorPosition;
797  if (mStartSelect > mEndSelect)
799  else
801 
802  // пытаемся показать курсор
804  }
805  }
806  // если в зону не попадает то сбрасываем
807  else
808  {
809  mActionMouseTimer = 0;
810  }
811 
814  }
815 
816  } // if (mMouseLeftPressed)
817  }
818 
819  void EditBox::setTextCursor(size_t _index)
820  {
821  // сбрасываем выделение
822  resetSelect();
823 
824  // новая позиция
825  if (_index > mTextLength)
826  _index = mTextLength;
827 
828  if (mCursorPosition == _index)
829  return;
830 
831  mCursorPosition = _index;
832 
833  // обновляем по позиции
834  if (mClientText != nullptr)
836 
837  updateSelectText();
838  }
839 
840  void EditBox::setTextSelection(size_t _start, size_t _end)
841  {
842  if (_start > mTextLength)
843  _start = mTextLength;
844  if (_end > mTextLength)
845  _end = mTextLength;
846 
847  mStartSelect = _start;
848  mEndSelect = _end;
849 
850  if (mClientText != nullptr)
851  {
852  if (mStartSelect > mEndSelect)
854  else
856  }
857 
859  return;
860  // курсор на конец выделения
862 
863  // обновляем по позиции
864  if (mClientText != nullptr)
866  }
867 
868  bool EditBox::deleteTextSelect(bool _history)
869  {
870  if (!isTextSelection())
871  return false;
872 
873  // начало и конец выделения
874  size_t start = getTextSelectionStart();
875  size_t end = getTextSelectionEnd();
876 
877  eraseText(start, end - start, _history);
878 
879  return true;
880  }
881 
882  void EditBox::resetSelect()
883  {
884  if (mStartSelect != ITEM_NONE)
885  {
887  if (mClientText != nullptr)
889  }
890  }
891 
892  void EditBox::commandPosition(size_t _undo, size_t _redo, size_t _length, VectorChangeInfo* _info)
893  {
894  if (_info != nullptr)
895  _info->push_back(TextCommandInfo(_undo, _redo, _length));
896  }
897 
898  void EditBox::commandMerge()
899  {
900  if (mVectorUndoChangeInfo.size() < 2)
901  return; // на всякий
902  // сохраняем последние набор отмен
904  mVectorUndoChangeInfo.pop_back();
905 
906  // объединяем последовательности
907  for (VectorChangeInfo::iterator iter = info.begin(); iter != info.end(); ++iter)
908  {
909  mVectorUndoChangeInfo.back().push_back((*iter));
910  }
911  }
912 
913  bool EditBox::commandUndo()
914  {
915  if (mVectorUndoChangeInfo.empty())
916  return false;
917 
918  // сбрасываем выделение
919  resetSelect();
920 
921  // сохраняем последние набор отмен
923  // перекидываем последний набор отмен
924  mVectorUndoChangeInfo.pop_back();
925  mVectorRedoChangeInfo.push_back(info);
926 
927  // берем текст для издевательств
928  UString text = getRealString();
929 
930  // восстанавливаем последовательность
931  for (VectorChangeInfo::reverse_iterator iter = info.rbegin(); iter != info.rend(); ++iter)
932  {
933  if ((*iter).type == TextCommandInfo::COMMAND_INSERT)
934  text.erase((*iter).start, (*iter).text.size());
935  else if ((*iter).type == TextCommandInfo::COMMAND_ERASE)
936  text.insert((*iter).start, (*iter).text);
937  else
938  {
939  mCursorPosition = (*iter).undo;
940  mTextLength = (*iter).length;
941  }
942  }
943 
944  // возвращаем текст
945  setRealString(text);
946 
947  // обновляем по позиции
948  if (mClientText != nullptr)
950  updateSelectText();
951 
952  // отсылаем событие о изменении
953  eventEditTextChange(this);
954 
955  return true;
956  }
957 
958  bool EditBox::commandRedo()
959  {
960  if (mVectorRedoChangeInfo.empty())
961  return false;
962 
963  // сбрасываем выделение
964  resetSelect();
965 
966  // сохраняем последние набор отмен
968  // перекидываем последний набор отмен
969  mVectorRedoChangeInfo.pop_back();
970  mVectorUndoChangeInfo.push_back(info);
971 
972  // берем текст для издевательств
973  UString text = getRealString();
974 
975  // восстанавливаем последовательность
976  for (VectorChangeInfo::iterator iter = info.begin(); iter != info.end(); ++iter)
977  {
978  if ((*iter).type == TextCommandInfo::COMMAND_INSERT)
979  text.insert((*iter).start, (*iter).text);
980  else if ((*iter).type == TextCommandInfo::COMMAND_ERASE)
981  text.erase((*iter).start, (*iter).text.size());
982  else
983  {
984  mCursorPosition = (*iter).redo;
985  mTextLength = (*iter).length;
986  }
987 
988  }
989 
990  // возвращаем текст
991  setRealString(text);
992 
993  // обновляем по позиции
994  if (mClientText != nullptr)
996  updateSelectText();
997 
998  // отсылаем событие о изменении
999  eventEditTextChange(this);
1000 
1001  return true;
1002  }
1003 
1004  void EditBox::saveInHistory(VectorChangeInfo* _info)
1005  {
1006  if (_info == nullptr)
1007  return;
1008  // если нет информации об изменении
1009  if ( _info->empty())
1010  return;
1011  if ((_info->size() == 1) && (_info->back().type == TextCommandInfo::COMMAND_POSITION))
1012  return;
1013 
1014  mVectorUndoChangeInfo.push_back(*_info);
1015  // проверяем на максимальный размер
1016  if (mVectorUndoChangeInfo.size() > EDIT_MAX_UNDO)
1017  mVectorUndoChangeInfo.pop_front();
1018  }
1019 
1020  // возвращает текст
1021  UString EditBox::getTextInterval(size_t _start, size_t _count)
1022  {
1023  // подстраховка
1024  if (_start > mTextLength) _start = mTextLength;
1025  // конец диапазона
1026  size_t end = _start + _count;
1027 
1028  // итератор нашей строки
1029  TextIterator iterator(getRealString());
1030 
1031  // дефолтный цвет
1033 
1034  // нужно ли вставлять цвет
1035  bool need_colour = true;
1036 
1037  // цикл прохода по строке
1038  while (iterator.moveNext())
1039  {
1040  // текущаяя позиция
1041  size_t pos = iterator.getPosition();
1042 
1043  // еще рано
1044  if (pos < _start)
1045  {
1046  // берем цвет из позиции и запоминаем
1047  iterator.getTagColour(colour);
1048 
1049  continue;
1050  }
1051 
1052  // проверяем на надобность начального тега
1053  else if (pos == _start)
1054  {
1055  need_colour = ! iterator.getTagColour(colour);
1056  // сохраняем место откуда начинается
1057  iterator.saveStartPoint();
1058 
1059  }
1060 
1061  // а теперь просто до конца диапазона
1062  else if (pos == end)
1063  break;
1064 
1065  }
1066 
1067  // возвращаем строку
1068  if (need_colour)
1069  return colour + iterator.getFromStart();
1070  return iterator.getFromStart();
1071  }
1072 
1073  // выделяет цветом диапазон
1074  void EditBox::_setTextColour(size_t _start, size_t _count, const Colour& _colour, bool _history)
1075  {
1076  // история изменений
1077  VectorChangeInfo* history = nullptr;
1078  if (_history)
1079  history = new VectorChangeInfo();
1080 
1081  // конец диапазона
1082  size_t end = _start + _count;
1083 
1084  // итератор нашей строки
1085  TextIterator iterator(getRealString(), history);
1086 
1087  // дефолтный цвет
1089 
1090  // цикл прохода по строке
1091  while (iterator.moveNext())
1092  {
1093  // текущаяя позиция
1094  size_t pos = iterator.getPosition();
1095 
1096  // берем цвет из позиции и запоминаем
1097  iterator.getTagColour(colour);
1098 
1099  // еще рано
1100  if (pos < _start)
1101  continue;
1102 
1103  // ставим начальный тег
1104  else if (pos == _start)
1105  iterator.setTagColour(_colour);
1106 
1107  // внутри диапазона очищаем все
1108  else if (pos < end)
1109  iterator.clearTagColour();
1110 
1111  // на конец ставим последний найденный или дефолтный
1112  else if (pos == end)
1113  {
1114  iterator.setTagColour(colour);
1115  // и выходим из цикла
1116  break;
1117  }
1118 
1119  }
1120 
1121  // сохраняем позицию для восстановления курсора
1122  commandPosition(_start, _start + _count, mTextLength, history);
1123 
1124  // запоминаем в историю
1125  if (_history)
1126  {
1127  saveInHistory(history);
1128  delete history;
1129  }
1130  // сбрасываем историю
1131  else
1132  commandResetHistory();
1133 
1134  // и возвращаем строку на место
1135  setRealString(iterator.getText());
1136  }
1137 
1138  void EditBox::setTextSelectColour(const Colour& _colour, bool _history)
1139  {
1140  // нужно выделение
1141  if ( !isTextSelection())
1142  return;
1143  // начало и конец выделения
1144  size_t start = getTextSelectionStart();
1145  size_t end = getTextSelectionEnd();
1146  _setTextColour(start, end - start, _colour, _history);
1147  }
1148 
1150  {
1151  if ( !isTextSelection())
1152  return "";
1153  size_t start = getTextSelectionStart();
1154  size_t end = getTextSelectionEnd();
1155  return getTextInterval(start, end - start);
1156  }
1157 
1158  void EditBox::setEditPassword(bool _password)
1159  {
1160  if (mModePassword == _password)
1161  return;
1162  mModePassword = _password;
1163 
1164  if (mModePassword)
1165  {
1166  if (mClientText != nullptr)
1167  {
1170  }
1171  }
1172  else
1173  {
1174  if (mClientText != nullptr)
1175  {
1177  mPasswordText.clear();
1178  }
1179  }
1180  // обновляем по размерам
1181  updateView();
1182  // сбрасываем историю
1183  commandResetHistory();
1184  }
1185 
1186  void EditBox::setText(const UString& _caption, bool _history)
1187  {
1188  // сбрасываем выделение
1189  resetSelect();
1190 
1191  // история изменений
1192  VectorChangeInfo* history = nullptr;
1193  if (_history)
1194  history = new VectorChangeInfo();
1195 
1196  // итератор нашей строки
1197  TextIterator iterator(getRealString(), history);
1198 
1199  // вставляем текст
1200  iterator.setText(_caption, mModeMultiline || mModeWordWrap);
1201 
1202  if (mOverflowToTheLeft)
1203  {
1204  iterator.cutMaxLengthFromBeginning(mMaxTextLength);
1205  }
1206  else
1207  {
1208  // обрезаем по максимальной длинне
1209  iterator.cutMaxLength(mMaxTextLength);
1210  }
1211 
1212  // запоминаем размер строки
1213  size_t old = mTextLength;
1214  // новая позиция и положение на конец вставки
1215  mCursorPosition = mTextLength = iterator.getSize();
1216 
1217  // сохраняем позицию для восстановления курсора
1218  commandPosition(0, mTextLength, old, history);
1219 
1220  // запоминаем в историю
1221  if (_history)
1222  {
1223  saveInHistory(history);
1224  delete history;
1225  }
1226  // сбрасываем историю
1227  else
1228  commandResetHistory();
1229 
1230  // и возвращаем строку на место
1231  setRealString(iterator.getText());
1232 
1233  // обновляем по позиции
1234  if (mClientText != nullptr)
1236  updateSelectText();
1237  }
1238 
1239  void EditBox::insertText(const UString& _text, size_t _start, bool _history)
1240  {
1241  // сбрасываем выделение
1242  resetSelect();
1243 
1244  // если строка пустая, или размер максимален
1245  if (_text.empty())
1246  return;
1247 
1248  if ((mOverflowToTheLeft == false) && (mTextLength == mMaxTextLength))
1249  return;
1250 
1251  // история изменений
1252  VectorChangeInfo* history = nullptr;
1253  if (_history)
1254  history = new VectorChangeInfo();
1255 
1256  // итератор нашей строки
1257  TextIterator iterator(getRealString(), history);
1258 
1259  // дефолтный цвет
1260  UString colour = mClientText == nullptr ? "" : TextIterator::convertTagColour(mClientText->getTextColour());
1261  // нужен ли тег текста
1262  // потом переделать через TextIterator чтобы отвязать понятие тег от эдита
1263  bool need_colour = ( (_text.size() > 6) && (_text[0] == L'#') && (_text[1] != L'#') );
1264 
1265  // цикл прохода по строке
1266  while (iterator.moveNext())
1267  {
1268  // текущаяя позиция
1269  size_t pos = iterator.getPosition();
1270 
1271  // текущий цвет
1272  if (need_colour)
1273  iterator.getTagColour(colour);
1274 
1275  // если дошли то выходим
1276  if (pos == _start)
1277  break;
1278  }
1279 
1280  // если нужен цвет то вставляем
1281  if (need_colour)
1282  iterator.setTagColour(colour);
1283 
1284  // а теперь вставляем строку
1285  iterator.insertText(_text, mModeMultiline || mModeWordWrap);
1286 
1287  if (mOverflowToTheLeft)
1288  {
1289  iterator.cutMaxLengthFromBeginning(mMaxTextLength);
1290  }
1291  else
1292  {
1293  // обрезаем по максимальной длинне
1294  iterator.cutMaxLength(mMaxTextLength);
1295  }
1296 
1297  // запоминаем размер строки
1298  size_t old = mTextLength;
1299  // новая позиция и положение на конец вставки
1300  mTextLength = iterator.getSize();
1301  mCursorPosition += mTextLength - old;
1302 
1303  // сохраняем позицию для восстановления курсора
1304  commandPosition(_start, _start + mTextLength - old, old, history);
1305 
1306  // запоминаем в историю
1307  if (_history)
1308  {
1309  saveInHistory(history);
1310  delete history;
1311  }
1312  // сбрасываем историю
1313  else
1314  commandResetHistory();
1315 
1316  // и возвращаем строку на место
1317  setRealString(iterator.getText());
1318 
1319  // обновляем по позиции
1320  if (mClientText != nullptr)
1322  updateSelectText();
1323  }
1324 
1325  void EditBox::eraseText(size_t _start, size_t _count, bool _history)
1326  {
1327  // чета маловато
1328  if (_count == 0)
1329  return;
1330 
1331  // сбрасываем выделение
1332  resetSelect();
1333 
1334  // история изменений
1335  VectorChangeInfo* history = nullptr;
1336  if (_history)
1337  history = new VectorChangeInfo();
1338 
1339  // итератор нашей строки
1340  TextIterator iterator(getRealString(), history);
1341 
1342  // дефолтный цвет
1343  UString colour;
1344  // конец диапазона
1345  size_t end = _start + _count;
1346  bool need_colour = false;
1347 
1348  // цикл прохода по строке
1349  while (iterator.moveNext())
1350  {
1351  // текущаяя позиция
1352  size_t pos = iterator.getPosition();
1353 
1354  // еще рано
1355  if (pos < _start)
1356  {
1357  // берем цвет из позиции и запоминаем
1358  iterator.getTagColour(colour);
1359  continue;
1360  }
1361 
1362  // сохраняем место откуда начинается
1363  else if (pos == _start)
1364  {
1365  // если до диапазона был цвет, то нужно закрыть тег
1366  if (!colour.empty())
1367  {
1368  need_colour = true;
1369  colour.clear();
1370  }
1371  // берем цвет из позиции и запоминаем
1372  iterator.getTagColour(colour);
1373  iterator.saveStartPoint();
1374  }
1375 
1376  // внутри диапазона
1377  else if (pos < end)
1378  {
1379  // берем цвет из позиции и запоминаем
1380  iterator.getTagColour(colour);
1381  }
1382 
1383  // окончание диапазона
1384  else if (pos == end)
1385  {
1386  // нужно ставить тег или нет
1387  if (!colour.empty())
1388  need_colour = true;
1389  if (iterator.getTagColour(colour))
1390  need_colour = false;
1391 
1392  break;
1393  }
1394 
1395  }
1396 
1397  // удаляем диапазон
1398  iterator.eraseFromStart();
1399  // и вставляем последний цвет
1400  if (need_colour)
1401  iterator.setTagColour(colour);
1402 
1403  // сохраняем позицию для восстановления курсора
1404  commandPosition(_start + _count, _start, mTextLength, history);
1405 
1406  // на месте удаленного
1407  mCursorPosition = _start;
1408  mTextLength -= _count;
1409 
1410  // запоминаем в историю
1411  if (_history)
1412  {
1413  saveInHistory(history);
1414  delete history;
1415  }
1416  // сбрасываем историю
1417  else
1418  commandResetHistory();
1419 
1420  // и возвращаем строку на место
1421  setRealString(iterator.getText());
1422 
1423  // обновляем по позиции
1424  if (mClientText != nullptr)
1426  updateSelectText();
1427  }
1428 
1429  void EditBox::commandCut()
1430  {
1431  // вырезаем в буфер обмена
1432  if (isTextSelection() && (!mModePassword))
1433  {
1435  if (!mModeReadOnly)
1436  {
1437  deleteTextSelect(true);
1438  // отсылаем событие о изменении
1439  eventEditTextChange(this);
1440  }
1441  }
1442  else
1444  }
1445 
1446  void EditBox::commandCopy()
1447  {
1448  // копируем в буфер обмена
1449  if (isTextSelection() && (!mModePassword))
1451  else
1453  }
1454 
1455  void EditBox::commandPast()
1456  {
1457  // копируем из буфера обмена
1459  if ((!mModeReadOnly) && (!clipboard.empty()))
1460  {
1461  // попытка объединения двух комманд
1462  size_t size = mVectorUndoChangeInfo.size();
1463  // непосредственно операции
1464  deleteTextSelect(true);
1465  insertText(clipboard, mCursorPosition, true);
1466  // проверяем на возможность объединения
1467  if ((size + 2) == mVectorUndoChangeInfo.size())
1468  commandMerge();
1469  // отсылаем событие о изменении
1470  eventEditTextChange(this);
1471  }
1472  }
1473 
1474  const UString& EditBox::getRealString()
1475  {
1476  if (mModePassword)
1477  return mPasswordText;
1478  else if (mClientText == nullptr)
1479  return mPasswordText;
1480 
1481  return mClientText->getCaption();
1482  }
1483 
1484  void EditBox::setRealString(const UString& _caption)
1485  {
1486  if (mModePassword)
1487  {
1488  mPasswordText = _caption;
1489  if (mClientText != nullptr)
1491  }
1492  else
1493  {
1494  if (mClientText != nullptr)
1495  mClientText->setCaption(_caption);
1496  }
1497  }
1498 
1500  {
1501  mCharPassword = _char;
1502  if (mModePassword)
1503  {
1504  if (mClientText != nullptr)
1506  }
1507  }
1508 
1509  void EditBox::updateEditState()
1510  {
1511  if (!getEnabled())
1512  _setWidgetState("disabled");
1513  else if (mIsPressed)
1514  {
1515  if (mIsFocus)
1516  _setWidgetState("pushed");
1517  else
1518  _setWidgetState("normal_checked");
1519  }
1520  else if (mIsFocus)
1521  _setWidgetState("highlighted");
1522  else
1523  _setWidgetState("normal");
1524  }
1525 
1526  void EditBox::setPosition(const IntPoint& _point)
1527  {
1528  Base::setPosition(_point);
1529  }
1530 
1532  {
1533  // если перенос, то сбрасываем размер текста
1534  if (mModeWordWrap)
1535  {
1536  if (mClientText != nullptr)
1537  mClientText->setWordWrap(true);
1538  }
1539 
1540  updateView();
1541  }
1542 
1543  void EditBox::setSize(const IntSize& _size)
1544  {
1545  Base::setSize(_size);
1546 
1547  eraseView();
1548  }
1549 
1550  void EditBox::setCoord(const IntCoord& _coord)
1551  {
1552  Base::setCoord(_coord);
1553 
1554  eraseView();
1555  }
1556 
1557  void EditBox::setCaption(const UString& _value)
1558  {
1559  setText(_value, false);
1560  }
1561 
1563  {
1564  return getRealString();
1565  }
1566 
1567  void EditBox::updateSelectText()
1568  {
1569  if (!mModeStatic)
1570  {
1572  if ((input.isShiftPressed()) && (mStartSelect != ITEM_NONE))
1573  {
1574  // меняем выделение
1575  mEndSelect = (size_t)mCursorPosition;
1576  if (mClientText != nullptr)
1577  {
1578  if (mStartSelect > mEndSelect)
1580  else
1582  }
1583 
1584  }
1585  else if (mStartSelect != ITEM_NONE)
1586  {
1587  // сбрасываем шифт
1589  if (mClientText != nullptr)
1591  }
1592  }
1593 
1594  // пытаемся показать курсор
1596  }
1597 
1599  {
1600  Base::setTextAlign(_value);
1601 
1602  if (mClientText != nullptr)
1603  mClientText->setTextAlign(_value);
1604 
1605  // так как мы сами рулим смещениями
1606  updateView();
1607  }
1608 
1609  void EditBox::setTextColour(const Colour& _value)
1610  {
1611  Base::setTextColour(_value);
1612 
1613  if (mClientText != nullptr)
1614  mClientText->setTextColour(_value);
1615  }
1616 
1618  {
1619  if (mClientText != nullptr)
1620  return mClientText->getCoord();
1621  return Base::getTextRegion();
1622  }
1623 
1625  {
1626  if (mClientText != nullptr)
1627  return mClientText->getTextSize();
1628  return Base::getTextSize();
1629  }
1630 
1631  void EditBox::notifyScrollChangePosition(ScrollBar* _sender, size_t _position)
1632  {
1633  if (mClientText == nullptr)
1634  return;
1635 
1636  if (_sender == mVScroll)
1637  {
1638  IntPoint point = mClientText->getViewOffset();
1639  point.top = _position;
1640  mClientText->setViewOffset(point);
1641  }
1642  else if (_sender == mHScroll)
1643  {
1644  IntPoint point = mClientText->getViewOffset();
1645  point.left = _position;
1646  mClientText->setViewOffset(point);
1647  }
1648  }
1649 
1650  void EditBox::notifyMouseWheel(Widget* _sender, int _rel)
1651  {
1652  if (mClientText == nullptr)
1653  return;
1654 
1655  if (mVRange != 0)
1656  {
1657  IntPoint point = mClientText->getViewOffset();
1658  int offset = point.top;
1659  if (_rel < 0)
1660  offset += EDIT_MOUSE_WHEEL;
1661  else
1662  offset -= EDIT_MOUSE_WHEEL;
1663 
1664  if (offset < 0)
1665  offset = 0;
1666  else if (offset > (int)mVRange)
1667  offset = mVRange;
1668 
1669  if (offset != point.top)
1670  {
1671  point.top = offset;
1672  if (mVScroll != nullptr)
1673  mVScroll->setScrollPosition(offset);
1674  mClientText->setViewOffset(point);
1675  }
1676  }
1677  else if (mHRange != 0)
1678  {
1679  IntPoint point = mClientText->getViewOffset();
1680  int offset = point.left;
1681  if (_rel < 0)
1682  offset += EDIT_MOUSE_WHEEL;
1683  else
1684  offset -= EDIT_MOUSE_WHEEL;
1685 
1686  if (offset < 0)
1687  offset = 0;
1688  else if (offset > (int)mHRange)
1689  offset = mHRange;
1690 
1691  if (offset != point.left)
1692  {
1693  point.left = offset;
1694  if (mHScroll != nullptr)
1695  mHScroll->setScrollPosition(offset);
1696  mClientText->setViewOffset(point);
1697  }
1698  }
1699  }
1700 
1701  void EditBox::setEditWordWrap(bool _value)
1702  {
1703  mModeWordWrap = _value;
1704  if (mClientText != nullptr)
1706 
1707  eraseView();
1708  }
1709 
1710  void EditBox::setFontName(const std::string& _value)
1711  {
1712  Base::setFontName(_value);
1713 
1714  if (mClientText != nullptr)
1715  mClientText->setFontName(_value);
1716 
1717  eraseView();
1718  }
1719 
1720  void EditBox::setFontHeight(int _value)
1721  {
1722  Base::setFontHeight(_value);
1723 
1724  if (mClientText != nullptr)
1725  mClientText->setFontHeight(_value);
1726 
1727  eraseView();
1728  }
1729 
1731  {
1732  updateScrollSize();
1734  }
1735 
1737  {
1738  updateScrollSize();
1739  updateCursorPosition();
1741  }
1742 
1743  void EditBox::updateCursorPosition()
1744  {
1745  if (mClientText == nullptr || mClient == nullptr)
1746  return;
1747 
1748  // размер контекста текста
1749  IntSize textSize = mClientText->getTextSize();
1750 
1751  // текущее смещение контекста текста
1752  IntPoint point = mClientText->getViewOffset();
1753  // расчетное смещение
1754  IntPoint offset = point;
1755 
1756  // абсолютные координаты курсора
1758  cursor.right ++;
1759 
1760  // абсолютные координаты вью
1761  const IntRect& view = mClient->getAbsoluteRect();
1762 
1763  // проверяем и показываем курсор
1764  if (!view.inside(cursor))
1765  {
1766  // горизонтальное смещение
1767  if (textSize.width > view.width())
1768  {
1769  if (cursor.left < view.left)
1770  {
1771  offset.left = point.left - (view.left - cursor.left);
1772  // добавляем смещение, только если курсор не перепрыгнет
1773  if ((float(view.width()) - EDIT_OFFSET_HORZ_CURSOR) > EDIT_OFFSET_HORZ_CURSOR)
1774  offset.left -= int(EDIT_OFFSET_HORZ_CURSOR);
1775  }
1776  else if (cursor.right > view.right)
1777  {
1778  offset.left = point.left + (cursor.right - view.right);
1779  // добавляем смещение, только если курсор не перепрыгнет
1780  if ((float(view.width()) - EDIT_OFFSET_HORZ_CURSOR) > EDIT_OFFSET_HORZ_CURSOR)
1781  offset.left += int(EDIT_OFFSET_HORZ_CURSOR);
1782  }
1783  }
1784 
1785  // вертикальное смещение
1786  if (textSize.height > view.height())
1787  {
1788  int delta = 0;
1789  if (cursor.height() > view.height())
1790  {
1791  // if text is bigger than edit height then place it in center
1792  delta = ((cursor.bottom - view.bottom) - (view.top - cursor.top)) / 2;
1793  }
1794  else if (cursor.top < view.top)
1795  {
1796  delta = - (view.top - cursor.top);
1797  }
1798  else if (cursor.bottom > view.bottom)
1799  {
1800  delta = (cursor.bottom - view.bottom);
1801  }
1802  offset.top = point.top + delta;
1803  }
1804 
1805  }
1806 
1807  if (offset != point)
1808  {
1809  mClientText->setViewOffset(offset);
1810  // обновить скролы
1811  if (mVScroll != nullptr)
1812  mVScroll->setScrollPosition(offset.top);
1813  if (mHScroll != nullptr)
1814  mHScroll->setScrollPosition(offset.left);
1815  }
1816  }
1817 
1818  void EditBox::setContentPosition(const IntPoint& _point)
1819  {
1820  if (mClientText != nullptr)
1821  mClientText->setViewOffset(_point);
1822  }
1823 
1824  IntSize EditBox::getViewSize()
1825  {
1826  if (mClientText != nullptr)
1827  return mClientText->getSize();
1828  return ScrollViewBase::getViewSize();
1829  }
1830 
1831  IntSize EditBox::getContentSize()
1832  {
1833  if (mClientText != nullptr)
1834  return mClientText->getTextSize();
1836  }
1837 
1838  size_t EditBox::getVScrollPage()
1839  {
1840  if (mClientText != nullptr)
1841  return (size_t)mClientText->getFontHeight();
1843  }
1844 
1845  size_t EditBox::getHScrollPage()
1846  {
1847  if (mClientText != nullptr)
1848  return (size_t)mClientText->getFontHeight();
1850  }
1851 
1852  IntPoint EditBox::getContentPosition()
1853  {
1854  if (mClientText != nullptr)
1855  return mClientText->getViewOffset();
1857  }
1858 
1859  Align EditBox::getContentAlign()
1860  {
1861  if (mClientText != nullptr)
1862  return mClientText->getTextAlign();
1864  }
1865 
1866  void EditBox::setTextIntervalColour(size_t _start, size_t _count, const Colour& _colour)
1867  {
1868  _setTextColour(_start, _count, _colour, false);
1869  }
1870 
1872  {
1874  }
1875 
1877  {
1879  }
1880 
1882  {
1883  return (mStartSelect != ITEM_NONE) && (mStartSelect != mEndSelect);
1884  }
1885 
1887  {
1888  deleteTextSelect(false);
1889  }
1890 
1892  {
1893  setTextSelectColour(_colour, false);
1894  }
1895 
1897  {
1898  return mEndSelect - mStartSelect;
1899  }
1900 
1901  void EditBox::setOnlyText(const UString& _text)
1902  {
1903  setText(TextIterator::toTagsString(_text), false);
1904  }
1905 
1907  {
1908  return TextIterator::getOnlyText(getRealString());
1909  }
1910 
1911  void EditBox::insertText(const UString& _text, size_t _index)
1912  {
1913  insertText(_text, _index, false);
1914  }
1915 
1916  void EditBox::addText(const UString& _text)
1917  {
1918  insertText(_text, ITEM_NONE, false);
1919  }
1920 
1921  void EditBox::eraseText(size_t _start, size_t _count)
1922  {
1923  eraseText(_start, _count, false);
1924  }
1925 
1926  void EditBox::setEditReadOnly(bool _value)
1927  {
1928  mModeReadOnly = _value;
1929  // сбрасываем историю
1930  commandResetHistory();
1931  }
1932 
1933  void EditBox::setEditMultiLine(bool _value)
1934  {
1935  mModeMultiline = _value;
1936  // на всякий, для убирания переносов
1937  if (!mModeMultiline)
1938  {
1939  setText(getRealString(), false);
1940  }
1941  // обновляем по размерам
1942  else
1943  {
1944  updateView();
1945  }
1946  // сбрасываем историю
1947  commandResetHistory();
1948  }
1949 
1950  void EditBox::setEditStatic(bool _value)
1951  {
1952  mModeStatic = _value;
1953  resetSelect();
1954 
1955  if (mClient != nullptr)
1956  {
1957  if (mModeStatic)
1958  mClient->setPointer("");
1959  else
1961  }
1962  }
1963 
1964  void EditBox::setPasswordChar(const UString& _value)
1965  {
1966  if (!_value.empty())
1967  setPasswordChar(_value[0]);
1968  }
1969 
1970  void EditBox::setVisibleVScroll(bool _value)
1971  {
1972  mVisibleVScroll = _value;
1973  updateView();
1974  }
1975 
1976  void EditBox::setVisibleHScroll(bool _value)
1977  {
1978  mVisibleHScroll = _value;
1979  updateView();
1980  }
1981 
1983  {
1984  return mVRange + 1;
1985  }
1986 
1988  {
1989  return mClientText == nullptr ? 0 : mClientText->getViewOffset().top;
1990  }
1991 
1992  void EditBox::setVScrollPosition(size_t _index)
1993  {
1994  if (mClientText == nullptr)
1995  return;
1996 
1997  if (_index > mVRange)
1998  _index = mVRange;
1999 
2000  IntPoint point = mClientText->getViewOffset();
2001  point.top = _index;
2002 
2003  mClientText->setViewOffset(point);
2004  // обновить скролы
2005  if (mVScroll != nullptr)
2006  mVScroll->setScrollPosition(point.top);
2007  }
2008 
2010  {
2011  return mHRange + 1;
2012  }
2013 
2015  {
2016  return mClientText == nullptr ? 0 : mClientText->getViewOffset().left;
2017  }
2018 
2019  void EditBox::setHScrollPosition(size_t _index)
2020  {
2021  if (mClientText == nullptr)
2022  return;
2023 
2024  if (_index > mHRange)
2025  _index = mHRange;
2026 
2027  IntPoint point = mClientText->getViewOffset();
2028  point.left = _index;
2029 
2030  mClientText->setViewOffset(point);
2031  // обновить скролы
2032  if (mHScroll != nullptr)
2034  }
2035 
2037  {
2038  return mClientText == nullptr ? false : mClientText->getInvertSelected();
2039  }
2040 
2041  void EditBox::setInvertSelected(bool _value)
2042  {
2043  if (mClientText != nullptr)
2044  mClientText->setInvertSelected(_value);
2045  }
2046 
2047  void EditBox::setPropertyOverride(const std::string& _key, const std::string& _value)
2048  {
2049  if (_key == "CursorPosition")
2050  setTextCursor(utility::parseValue<size_t>(_value));
2051  else if (_key == "TextSelect")
2053  else if (_key == "ReadOnly")
2054  setEditReadOnly(utility::parseValue<bool>(_value));
2055  else if (_key == "Password")
2056  setEditPassword(utility::parseValue<bool>(_value));
2057  else if (_key == "MultiLine")
2058  setEditMultiLine(utility::parseValue<bool>(_value));
2059  else if (_key == "PasswordChar")
2060  setPasswordChar(_value);
2061  else if (_key == "MaxTextLength")
2062  setMaxTextLength(utility::parseValue<size_t>(_value));
2063  else if (_key == "OverflowToTheLeft")
2064  setOverflowToTheLeft(utility::parseValue<bool>(_value));
2065  else if (_key == "Static")
2066  setEditStatic(utility::parseValue<bool>(_value));
2067  else if (_key == "VisibleVScroll")
2068  setVisibleVScroll(utility::parseValue<bool>(_value));
2069  else if (_key == "VisibleHScroll")
2070  setVisibleHScroll(utility::parseValue<bool>(_value));
2071  else if (_key == "WordWrap")
2072  setEditWordWrap(utility::parseValue<bool>(_value));
2073  else if (_key == "TabPrinting")
2074  setTabPrinting(utility::parseValue<bool>(_value));
2075  else if (_key == "InvertSelected")
2076  setInvertSelected(utility::parseValue<bool>(_value));
2077  else
2078  {
2079  Base::setPropertyOverride(_key, _value);
2080  return;
2081  }
2082  eventChangeProperty(this, _key, _value);
2083  }
2084 
2085  size_t EditBox::getTextCursor() const
2086  {
2087  return mCursorPosition;
2088  }
2089 
2090  size_t EditBox::getTextLength() const
2091  {
2092  return mTextLength;
2093  }
2094 
2096  {
2097  mOverflowToTheLeft = _value;
2098  }
2099 
2101  {
2102  return mOverflowToTheLeft;
2103  }
2104 
2105  void EditBox::setMaxTextLength(size_t _value)
2106  {
2107  mMaxTextLength = _value;
2108  }
2109 
2111  {
2112  return mMaxTextLength;
2113  }
2114 
2116  {
2117  return mModeReadOnly;
2118  }
2119 
2121  {
2122  return mModePassword;
2123  }
2124 
2126  {
2127  return mModeMultiline;
2128  }
2129 
2131  {
2132  return mModeStatic;
2133  }
2134 
2136  {
2137  return mCharPassword;
2138  }
2139 
2141  {
2142  return mModeWordWrap;
2143  }
2144 
2145  void EditBox::setTabPrinting(bool _value)
2146  {
2147  mTabPrinting = _value;
2148  }
2149 
2151  {
2152  return mTabPrinting;
2153  }
2154 
2155  void EditBox::setPosition(int _left, int _top)
2156  {
2157  setPosition(IntPoint(_left, _top));
2158  }
2159 
2160  void EditBox::setSize(int _width, int _height)
2161  {
2162  setSize(IntSize(_width, _height));
2163  }
2164 
2165  void EditBox::setCoord(int _left, int _top, int _width, int _height)
2166  {
2167  setCoord(IntCoord(_left, _top, _width, _height));
2168  }
2169 
2171  {
2172  return mVisibleVScroll;
2173  }
2174 
2176  {
2177  return mVisibleHScroll;
2178  }
2179 
2180  void EditBox::commandResetRedo()
2181  {
2182  mVectorRedoChangeInfo.clear();
2183  }
2184 
2185  void EditBox::commandResetHistory()
2186  {
2187  mVectorRedoChangeInfo.clear();
2188  mVectorUndoChangeInfo.clear();
2189  }
2190 
2192  {
2193  Base::setTextShadowColour(_value);
2194 
2195  if (mClientText != nullptr)
2196  mClientText->setShadowColour(_value);
2197  }
2198 
2199  void EditBox::setTextShadow(bool _value)
2200  {
2201  Base::setTextShadow(_value);
2202 
2203  if (mClientText != nullptr)
2204  mClientText->setShadow(_value);
2205  }
2206 
2207 } // namespace MyGUI