MyGUI  3.2.0
MyGUI_EditBox.cpp
Go to the documentation of this file.
00001 
00006 /*
00007     This file is part of MyGUI.
00008 
00009     MyGUI is free software: you can redistribute it and/or modify
00010     it under the terms of the GNU Lesser General Public License as published by
00011     the Free Software Foundation, either version 3 of the License, or
00012     (at your option) any later version.
00013 
00014     MyGUI is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017     GNU Lesser General Public License for more details.
00018 
00019     You should have received a copy of the GNU Lesser General Public License
00020     along with MyGUI.  If not, see <http://www.gnu.org/licenses/>.
00021 */
00022 #include "MyGUI_Precompiled.h"
00023 #include "MyGUI_EditBox.h"
00024 #include "MyGUI_Gui.h"
00025 #include "MyGUI_ResourceSkin.h"
00026 #include "MyGUI_SkinManager.h"
00027 #include "MyGUI_InputManager.h"
00028 #include "MyGUI_ClipboardManager.h"
00029 #include "MyGUI_PointerManager.h"
00030 #include "MyGUI_ISubWidgetText.h"
00031 #include "MyGUI_ScrollBar.h"
00032 
00033 #include <ctype.h>
00034 
00035 namespace MyGUI
00036 {
00037 
00038     const float EDIT_CURSOR_TIMER  = 0.7f;
00039     const float EDIT_ACTION_MOUSE_TIMER  = 0.05f;
00040     const int EDIT_CURSOR_MAX_POSITION = 100000;
00041     const int EDIT_CURSOR_MIN_POSITION = -100000;
00042     const size_t EDIT_MAX_UNDO = 128;
00043     const size_t EDIT_DEFAULT_MAX_TEXT_LENGTH = 2048;
00044     const float EDIT_OFFSET_HORZ_CURSOR = 10.0f; // дополнительное смещение для курсора
00045     const int EDIT_ACTION_MOUSE_ZONE = 1500; // область для восприятия мыши за пределом эдита
00046     const std::string EDIT_CLIPBOARD_TYPE_TEXT = "Text";
00047     const int EDIT_MOUSE_WHEEL = 50; // область для восприятия мыши за пределом эдита
00048 
00049     EditBox::EditBox() :
00050         mIsPressed(false),
00051         mIsFocus(false),
00052         mCursorActive(false),
00053         mCursorTimer(0),
00054         mActionMouseTimer(0),
00055         mCursorPosition(0),
00056         mTextLength(0),
00057         mStartSelect(ITEM_NONE),
00058         mEndSelect(0),
00059         mMouseLeftPressed(false),
00060         mModeReadOnly(false),
00061         mModePassword(false),
00062         mModeMultiline(false),
00063         mModeStatic(false),
00064         mModeWordWrap(false),
00065         mTabPrinting(false),
00066         mCharPassword('*'),
00067         mOverflowToTheLeft(false),
00068         mMaxTextLength(EDIT_DEFAULT_MAX_TEXT_LENGTH),
00069         mClientText(nullptr)
00070     {
00071         mChangeContentByResize = true;
00072     }
00073 
00074     void EditBox::initialiseOverride()
00075     {
00076         Base::initialiseOverride();
00077 
00078         mOriginalPointer = getPointer();
00079 
00080         // FIXME нам нужен фокус клавы
00081         setNeedKeyFocus(true);
00082 
00083         assignWidget(mClient, "Client");
00084         if (mClient != nullptr)
00085         {
00086             mClient->eventMouseSetFocus += newDelegate(this, &EditBox::notifyMouseSetFocus);
00087             mClient->eventMouseLostFocus += newDelegate(this, &EditBox::notifyMouseLostFocus);
00088             mClient->eventMouseButtonPressed += newDelegate(this, &EditBox::notifyMousePressed);
00089             mClient->eventMouseButtonReleased += newDelegate(this, &EditBox::notifyMouseReleased);
00090             mClient->eventMouseDrag += newDelegate(this, &EditBox::notifyMouseDrag);
00091             mClient->eventMouseButtonDoubleClick += newDelegate(this, &EditBox::notifyMouseButtonDoubleClick);
00092             mClient->eventMouseWheel += newDelegate(this, &EditBox::notifyMouseWheel);
00093             setWidgetClient(mClient);
00094         }
00095 
00096         assignWidget(mVScroll, "VScroll");
00097         if (mVScroll != nullptr)
00098         {
00099             mVScroll->eventScrollChangePosition += newDelegate(this, &EditBox::notifyScrollChangePosition);
00100         }
00101 
00102         assignWidget(mHScroll, "HScroll");
00103         if (mHScroll != nullptr)
00104         {
00105             mHScroll->eventScrollChangePosition += newDelegate(this, &EditBox::notifyScrollChangePosition);
00106         }
00107 
00108         mClientText = getSubWidgetText();
00109         if (mClient != nullptr)
00110         {
00111             ISubWidgetText* text = mClient->getSubWidgetText();
00112             if (text)
00113                 mClientText = text;
00114         }
00115 
00116         updateScrollSize();
00117 
00118         // первоначальная инициализация курсора
00119         if (mClientText != nullptr)
00120             mClientText->setCursorPosition(mCursorPosition);
00121 
00122         updateSelectText();
00123     }
00124 
00125     void EditBox::shutdownOverride()
00126     {
00127         mClient = nullptr;
00128         mClientText = nullptr;
00129         mVScroll = nullptr;
00130         mHScroll = nullptr;
00131 
00132         Base::shutdownOverride();
00133     }
00134 
00135     void EditBox::notifyMouseSetFocus(Widget* _sender, Widget* _old)
00136     {
00137         if ((_old == mClient) || (mIsFocus))
00138             return;
00139 
00140         mIsFocus = true;
00141         updateEditState();
00142     }
00143 
00144     void EditBox::notifyMouseLostFocus(Widget* _sender, Widget* _new)
00145     {
00146         if ((_new == mClient) || (!mIsFocus))
00147             return;
00148 
00149         mIsFocus = false;
00150         updateEditState();
00151     }
00152 
00153     void EditBox::notifyMousePressed(Widget* _sender, int _left, int _top, MouseButton _id)
00154     {
00155         if (mClientText == nullptr)
00156             return;
00157 
00158         // в статике все недоступно
00159         if (mModeStatic)
00160             return;
00161 
00162         IntPoint point = InputManager::getInstance().getLastPressedPosition(MouseButton::Left);
00163         mCursorPosition = mClientText->getCursorPosition(point);
00164         mClientText->setCursorPosition(mCursorPosition);
00165         mClientText->setVisibleCursor(true);
00166         mCursorTimer = 0;
00167         updateSelectText();
00168 
00169         if (_id == MouseButton::Left)
00170             mMouseLeftPressed = true;
00171     }
00172 
00173     void EditBox::notifyMouseReleased(Widget* _sender, int _left, int _top, MouseButton _id)
00174     {
00175         // сбрасываем всегда
00176         mMouseLeftPressed = false;
00177     }
00178 
00179     void EditBox::notifyMouseDrag(Widget* _sender, int _left, int _top, MouseButton _id)
00180     {
00181         if (_id != MouseButton::Left)
00182             return;
00183 
00184         if (mClientText == nullptr)
00185             return;
00186 
00187         // в статике все недоступно
00188         if (mModeStatic)
00189             return;
00190 
00191         // останавливаем курсор
00192         mClientText->setVisibleCursor(true);
00193 
00194         // сбрасываем все таймеры
00195         mCursorTimer = 0;
00196         mActionMouseTimer = 0;
00197 
00198         size_t Old = mCursorPosition;
00199         IntPoint point(_left, _top);
00200         mCursorPosition = mClientText->getCursorPosition(point);
00201         if (Old == mCursorPosition)
00202             return;
00203 
00204         mClientText->setCursorPosition(mCursorPosition);
00205 
00206         // если не было выделения
00207         if (mStartSelect == ITEM_NONE)
00208             mStartSelect = Old;
00209 
00210         // меняем выделение
00211         mEndSelect = (size_t)mCursorPosition;
00212         if (mStartSelect > mEndSelect)
00213             mClientText->setTextSelection(mEndSelect, mStartSelect);
00214         else
00215             mClientText->setTextSelection(mStartSelect, mEndSelect);
00216 
00217     }
00218 
00219     void EditBox::notifyMouseButtonDoubleClick(Widget* _sender)
00220     {
00221         if (mClientText == nullptr)
00222             return;
00223 
00224         // в статике все недоступно
00225         if (mModeStatic)
00226             return;
00227 
00228         const IntPoint& lastPressed = InputManager::getInstance().getLastPressedPosition(MouseButton::Left);
00229 
00230         size_t cursorPosition = mClientText->getCursorPosition(lastPressed);
00231         mStartSelect = cursorPosition;
00232         mEndSelect = cursorPosition;
00233 
00234         UString text = this->getOnlyText();
00235         UString::reverse_iterator iterBack = text.rend() - cursorPosition;
00236         UString::iterator iterForw = text.begin() + cursorPosition;
00237 
00238         while (iterBack != text.rend())
00239         {
00240             if (((*iterBack) < 265) && (ispunct(*iterBack) || isspace(*iterBack)))
00241                 break;
00242             ++iterBack;
00243             mStartSelect--;
00244         }
00245         while (iterForw != text.end())
00246         {
00247             if (((*iterForw) < 265) && (ispunct(*iterForw) || isspace(*iterForw)))
00248                 break;
00249             ++iterForw;
00250             mEndSelect++;
00251         }
00252 
00253         mClientText->setCursorPosition(mEndSelect);
00254         mClientText->setTextSelection(mStartSelect, mEndSelect);
00255     }
00256 
00257     void EditBox::onMouseDrag(int _left, int _top, MouseButton _id)
00258     {
00259         notifyMouseDrag(nullptr, _left, _top, _id);
00260 
00261         Base::onMouseDrag(_left, _top, _id);
00262     }
00263 
00264     void EditBox::onKeySetFocus(Widget* _old)
00265     {
00266         if (!mIsPressed)
00267         {
00268             mIsPressed = true;
00269             updateEditState();
00270 
00271             if (!mModeStatic)
00272             {
00273                 if (mClientText != nullptr)
00274                 {
00275                     mCursorActive = true;
00276                     Gui::getInstance().eventFrameStart += newDelegate(this, &EditBox::frameEntered);
00277                     mClientText->setVisibleCursor(true);
00278                     mClientText->setSelectBackground(true);
00279                     mCursorTimer = 0;
00280                 }
00281             }
00282         }
00283 
00284         Base::onKeySetFocus(_old);
00285     }
00286 
00287     void EditBox::onKeyLostFocus(Widget* _new)
00288     {
00289         if (mIsPressed)
00290         {
00291             mIsPressed = false;
00292             updateEditState();
00293 
00294             if (mClientText != nullptr)
00295             {
00296                 mCursorActive = false;
00297                 Gui::getInstance().eventFrameStart -= newDelegate(this, &EditBox::frameEntered);
00298                 mClientText->setVisibleCursor(false);
00299                 mClientText->setSelectBackground(false);
00300             }
00301         }
00302 
00303         Base::onKeyLostFocus(_new);
00304     }
00305 
00306     void EditBox::onKeyButtonPressed(KeyCode _key, Char _char)
00307     {
00308         if (mClientText == nullptr || mClient == nullptr)
00309         {
00310             Base::onKeyButtonPressed(_key, _char);
00311             return;
00312         }
00313 
00314         // в статическом режиме ничего не доступно
00315         if (mModeStatic)
00316         {
00317             Base::onKeyButtonPressed(_key, _char);
00318             return;
00319         }
00320 
00321         InputManager& input = InputManager::getInstance();
00322 
00323         mClientText->setVisibleCursor(true);
00324         mCursorTimer = 0.0f;
00325 
00326         if (_key == KeyCode::Escape)
00327         {
00328             InputManager::getInstance().setKeyFocusWidget(nullptr);
00329         }
00330         else if (_key == KeyCode::Backspace)
00331         {
00332             // если нуно то удаляем выделенный текст
00333             if (!mModeReadOnly)
00334             {
00335                 // сбрасываем повтор
00336                 commandResetRedo();
00337 
00338                 if (!deleteTextSelect(true))
00339                 {
00340                     // прыгаем на одну назад и удаляем
00341                     if (mCursorPosition != 0)
00342                     {
00343                         mCursorPosition--;
00344                         eraseText(mCursorPosition, 1, true);
00345                     }
00346                 }
00347                 // отсылаем событие о изменении
00348                 eventEditTextChange(this);
00349             }
00350 
00351         }
00352         else if (_key == KeyCode::Delete)
00353         {
00354             if (input.isShiftPressed())
00355             {
00356                 // сбрасываем повтор
00357                 commandResetRedo();
00358 
00359                 commandCut();
00360             }
00361             else if (!mModeReadOnly)
00362             {
00363                 // сбрасываем повтор
00364                 commandResetRedo();
00365 
00366                 // если нуно то удаляем выделенный текст
00367                 if (!deleteTextSelect(true))
00368                 {
00369                     if (mCursorPosition != mTextLength)
00370                     {
00371                         eraseText(mCursorPosition, 1, true);
00372                     }
00373                 }
00374                 // отсылаем событие о изменении
00375                 eventEditTextChange(this);
00376             }
00377 
00378         }
00379         else if (_key == KeyCode::Insert)
00380         {
00381             if (input.isShiftPressed())
00382             {
00383                 // сбрасываем повтор
00384                 commandResetRedo();
00385 
00386                 commandPast();
00387             }
00388             else if (input.isControlPressed())
00389             {
00390                 commandCopy();
00391             }
00392 
00393         }
00394         else if ((_key == KeyCode::Return) || (_key == KeyCode::NumpadEnter))
00395         {
00396             // работаем только в режиме редактирования
00397             if (!mModeReadOnly)
00398             {
00399                 if ((mModeMultiline) && (!input.isControlPressed()))
00400                 {
00401                     // сбрасываем повтор
00402                     commandResetRedo();
00403 
00404                     // попытка объединения двух комманд
00405                     size_t size = mVectorUndoChangeInfo.size();
00406                     // непосредственно операции
00407                     deleteTextSelect(true);
00408                     insertText(TextIterator::getTextNewLine(), mCursorPosition, true);
00409                     // проверяем на возможность объединения
00410                     if ((size + 2) == mVectorUndoChangeInfo.size())
00411                         commandMerge();
00412                     // отсылаем событие о изменении
00413                     eventEditTextChange(this);
00414                 }
00415                 // при сингл лайн и и мульти+сонтрол шлем эвент
00416                 else
00417                 {
00418                     eventEditSelectAccept(this);
00419                 }
00420             }
00421 
00422         }
00423         else if (_key == KeyCode::ArrowRight)
00424         {
00425             if ((mCursorPosition) < mTextLength)
00426             {
00427                 mCursorPosition ++;
00428                 mClientText->setCursorPosition(mCursorPosition);
00429                 updateSelectText();
00430             }
00431             // сбрасываем выделение
00432             else if (isTextSelection() && !input.isShiftPressed())
00433             {
00434                 resetSelect();
00435             }
00436 
00437         }
00438         else if (_key == KeyCode::ArrowLeft)
00439         {
00440             if (mCursorPosition != 0)
00441             {
00442                 mCursorPosition --;
00443                 mClientText->setCursorPosition(mCursorPosition);
00444                 updateSelectText();
00445             }
00446             // сбрасываем выделение
00447             else if (isTextSelection() && !input.isShiftPressed())
00448             {
00449                 resetSelect();
00450             }
00451 
00452         }
00453         else if (_key == KeyCode::ArrowUp)
00454         {
00455             IntPoint point = mClientText->getCursorPoint(mCursorPosition);
00456             point.top -= mClientText->getFontHeight();
00457             size_t old = mCursorPosition;
00458             mCursorPosition = mClientText->getCursorPosition(point);
00459             // самая верхняя строчка
00460             if (old == mCursorPosition)
00461             {
00462                 if (mCursorPosition != 0)
00463                 {
00464                     mCursorPosition = 0;
00465                     mClientText->setCursorPosition(mCursorPosition);
00466                     updateSelectText();
00467                 }
00468                 // сбрасываем выделение
00469                 else if (isTextSelection() && !input.isShiftPressed())
00470                 {
00471                     resetSelect();
00472                 }
00473             }
00474             else
00475             {
00476                 mClientText->setCursorPosition(mCursorPosition);
00477                 updateSelectText();
00478             }
00479 
00480         }
00481         else if (_key == KeyCode::ArrowDown)
00482         {
00483             IntPoint point = mClientText->getCursorPoint(mCursorPosition);
00484             point.top += mClientText->getFontHeight();
00485             size_t old = mCursorPosition;
00486             mCursorPosition = mClientText->getCursorPosition(point);
00487             // самая нижняя строчка
00488             if (old == mCursorPosition)
00489             {
00490                 if (mCursorPosition != mTextLength)
00491                 {
00492                     mCursorPosition = mTextLength;
00493                     mClientText->setCursorPosition(mCursorPosition);
00494                     updateSelectText();
00495                 }
00496                 // сбрасываем выделение
00497                 else if (isTextSelection() && !input.isShiftPressed())
00498                 {
00499                     resetSelect();
00500                 }
00501             }
00502             else
00503             {
00504                 mClientText->setCursorPosition(mCursorPosition);
00505                 updateSelectText();
00506             }
00507 
00508         }
00509         else if (_key == KeyCode::Home)
00510         {
00511             // в начало строки
00512             if (!input.isControlPressed())
00513             {
00514                 IntPoint point = mClientText->getCursorPoint(mCursorPosition);
00515                 point.left = EDIT_CURSOR_MIN_POSITION;
00516                 size_t old = mCursorPosition;
00517                 mCursorPosition = mClientText->getCursorPosition(point);
00518                 if (old != mCursorPosition)
00519                 {
00520                     mClientText->setCursorPosition(mCursorPosition);
00521                     updateSelectText();
00522                 }
00523                 else if (isTextSelection() && !input.isShiftPressed())
00524                 {
00525                     resetSelect();
00526                 }
00527             }
00528             // в начало всего текста
00529             else
00530             {
00531                 if (0 != mCursorPosition)
00532                 {
00533                     mCursorPosition = 0;
00534                     mClientText->setCursorPosition(mCursorPosition);
00535                     updateSelectText();
00536                 }
00537                 else if (isTextSelection() && !input.isShiftPressed())
00538                 {
00539                     resetSelect();
00540                 }
00541             }
00542 
00543         }
00544         else if (_key == KeyCode::End)
00545         {
00546             // в конец строки
00547             if (!input.isControlPressed())
00548             {
00549                 IntPoint point = mClientText->getCursorPoint(mCursorPosition);
00550                 point.left = EDIT_CURSOR_MAX_POSITION;
00551                 size_t old = mCursorPosition;
00552                 mCursorPosition = mClientText->getCursorPosition(point);
00553                 if (old != mCursorPosition)
00554                 {
00555                     mClientText->setCursorPosition(mCursorPosition);
00556                     updateSelectText();
00557                 }
00558                 else if (isTextSelection() && !input.isShiftPressed())
00559                 {
00560                     resetSelect();
00561                 }
00562             }
00563             // в самый конец
00564             else
00565             {
00566                 if (mTextLength != mCursorPosition)
00567                 {
00568                     mCursorPosition = mTextLength;
00569                     mClientText->setCursorPosition(mCursorPosition);
00570                     updateSelectText();
00571                 }
00572                 else if (isTextSelection() && !input.isShiftPressed())
00573                 {
00574                     resetSelect();
00575                 }
00576             }
00577 
00578         }
00579         else if (_key == KeyCode::PageUp)
00580         {
00581             // на размер окна, но не меньше одной строки
00582             IntPoint point = mClientText->getCursorPoint(mCursorPosition);
00583             point.top -= (mClient->getHeight() > mClientText->getFontHeight()) ? mClient->getHeight() : mClientText->getFontHeight();
00584             size_t old = mCursorPosition;
00585             mCursorPosition = mClientText->getCursorPosition(point);
00586             // самая верхняя строчка
00587             if (old == mCursorPosition)
00588             {
00589                 if (mCursorPosition != 0)
00590                 {
00591                     mCursorPosition = 0;
00592                     mClientText->setCursorPosition(mCursorPosition);
00593                     updateSelectText();
00594                 }
00595                 // сбрасываем выделение
00596                 else if (isTextSelection() && !input.isShiftPressed())
00597                 {
00598                     resetSelect();
00599                 }
00600             }
00601             else
00602             {
00603                 mClientText->setCursorPosition(mCursorPosition);
00604                 updateSelectText();
00605             }
00606 
00607         }
00608         else if (_key == KeyCode::PageDown)
00609         {
00610             // на размер окна, но не меньше одной строки
00611             IntPoint point = mClientText->getCursorPoint(mCursorPosition);
00612             point.top += (mClient->getHeight() > mClientText->getFontHeight()) ? mClient->getHeight() : mClientText->getFontHeight();
00613             size_t old = mCursorPosition;
00614             mCursorPosition = mClientText->getCursorPosition(point);
00615             // самая нижняя строчка
00616             if (old == mCursorPosition)
00617             {
00618                 if (mCursorPosition != mTextLength)
00619                 {
00620                     mCursorPosition = mTextLength;
00621                     mClientText->setCursorPosition(mCursorPosition);
00622                     updateSelectText();
00623                 }
00624                 // сбрасываем выделение
00625                 else if (isTextSelection() && !input.isShiftPressed())
00626                 {
00627                     resetSelect();
00628                 }
00629             }
00630             else
00631             {
00632                 mClientText->setCursorPosition(mCursorPosition);
00633                 updateSelectText();
00634             }
00635 
00636         }
00637         else if ((_key == KeyCode::LeftShift) || (_key == KeyCode::RightShift))
00638         {
00639             // для правильно выделения
00640             if (mStartSelect == ITEM_NONE)
00641             {
00642                 mStartSelect = mEndSelect = mCursorPosition;
00643             }
00644         }
00645         else if (_char != 0)
00646         {
00647             // если не нажат контрл, то обрабатываем как текст
00648             if (!input.isControlPressed())
00649             {
00650                 if (!mModeReadOnly)
00651                 {
00652                     // сбрасываем повтор
00653                     commandResetRedo();
00654 
00655                     // таб только если нужно
00656                     if (_char != '\t' || mTabPrinting)
00657                     {
00658                         // попытка объединения двух комманд
00659                         size_t size = mVectorUndoChangeInfo.size();
00660                         // непосредственно операции
00661                         deleteTextSelect(true);
00662                         insertText(TextIterator::getTextCharInfo(_char), mCursorPosition, true);
00663                         // проверяем на возможность объединения
00664                         if ((size + 2) == mVectorUndoChangeInfo.size())
00665                             commandMerge();
00666                         // отсылаем событие о изменении
00667                         eventEditTextChange(this);
00668                     }
00669                 }
00670             }
00671             else if (_key == KeyCode::C)
00672             {
00673                 commandCopy();
00674 
00675             }
00676             else if (_key == KeyCode::X)
00677             {
00678                 // сбрасываем повтор
00679                 commandResetRedo();
00680 
00681                 commandCut();
00682 
00683             }
00684             else if (_key == KeyCode::V)
00685             {
00686                 // сбрасываем повтор
00687                 commandResetRedo();
00688 
00689                 commandPast();
00690 
00691             }
00692             else if (_key == KeyCode::A)
00693             {
00694                 // выделяем весь текст
00695                 setTextSelection(0, mTextLength);
00696 
00697             }
00698             else if (_key == KeyCode::Z)
00699             {
00700                 // отмена
00701                 commandUndo();
00702 
00703             }
00704             else if (_key == KeyCode::Y)
00705             {
00706                 // повтор
00707                 commandRedo();
00708 
00709             }
00710         }
00711 
00712         Base::onKeyButtonPressed(_key, _char);
00713     }
00714 
00715     void EditBox::frameEntered(float _frame)
00716     {
00717         if (mClientText == nullptr)
00718             return;
00719 
00720         // в статике все недоступно
00721         if (mModeStatic)
00722             return;
00723 
00724         if (mCursorActive)
00725         {
00726             mCursorTimer += _frame;
00727 
00728             if (mCursorTimer > EDIT_CURSOR_TIMER)
00729             {
00730                 mClientText->setVisibleCursor(!mClientText->isVisibleCursor());
00731                 while (mCursorTimer > EDIT_CURSOR_TIMER)
00732                     mCursorTimer -= EDIT_CURSOR_TIMER;
00733             }
00734         }
00735 
00736         // сдвигаем курсор по положению мыши
00737         if (mMouseLeftPressed)
00738         {
00739             mActionMouseTimer += _frame;
00740 
00741             if (mActionMouseTimer > EDIT_ACTION_MOUSE_TIMER)
00742             {
00743                 IntPoint mouse = InputManager::getInstance().getMousePositionByLayer();
00744                 const IntRect& view = mClient->getAbsoluteRect();
00745                 mouse.left -= view.left;
00746                 mouse.top -= view.top;
00747                 IntPoint point;
00748 
00749                 bool action = false;
00750 
00751                 // вверх на одну строчку
00752                 if ((mouse.top < 0) && (mouse.top > -EDIT_ACTION_MOUSE_ZONE))
00753                 {
00754                     if ((mouse.left > 0) && (mouse.left <= mClient->getWidth()))
00755                     {
00756                         point = mClientText->getCursorPoint(mCursorPosition);
00757                         point.top -= mClientText->getFontHeight();
00758                         action = true;
00759                     }
00760                 }
00761                 // вниз на одну строчку
00762                 else if ((mouse.top > mClient->getHeight()) && (mouse.top < (mClient->getHeight() + EDIT_ACTION_MOUSE_ZONE)))
00763                 {
00764                     if ((mouse.left > 0) && (mouse.left <= mClient->getWidth()))
00765                     {
00766                         point = mClientText->getCursorPoint(mCursorPosition);
00767                         point.top += mClientText->getFontHeight();
00768                         action = true;
00769                     }
00770                 }
00771 
00772                 // влево на небольшое расстояние
00773                 if ((mouse.left < 0) && (mouse.left > -EDIT_ACTION_MOUSE_ZONE))
00774                 {
00775                     point = mClientText->getCursorPoint(mCursorPosition);
00776                     point.left -= (int)EDIT_OFFSET_HORZ_CURSOR;
00777                     action = true;
00778                 }
00779                 // вправо на небольшое расстояние
00780                 else if ((mouse.left > mClient->getWidth()) && (mouse.left < (mClient->getWidth() + EDIT_ACTION_MOUSE_ZONE)))
00781                 {
00782                     point = mClientText->getCursorPoint(mCursorPosition);
00783                     point.left += (int)EDIT_OFFSET_HORZ_CURSOR;
00784                     action = true;
00785                 }
00786 
00787                 if (action)
00788                 {
00789                     size_t old = mCursorPosition;
00790                     mCursorPosition = mClientText->getCursorPosition(point);
00791 
00792                     if (old != mCursorPosition)
00793                     {
00794                         mClientText->setCursorPosition(mCursorPosition);
00795 
00796                         mEndSelect = (size_t)mCursorPosition;
00797                         if (mStartSelect > mEndSelect)
00798                             mClientText->setTextSelection(mEndSelect, mStartSelect);
00799                         else
00800                             mClientText->setTextSelection(mStartSelect, mEndSelect);
00801 
00802                         // пытаемся показать курсор
00803                         updateViewWithCursor();
00804                     }
00805                 }
00806                 // если в зону не попадает то сбрасываем
00807                 else
00808                 {
00809                     mActionMouseTimer = 0;
00810                 }
00811 
00812                 while (mActionMouseTimer > EDIT_ACTION_MOUSE_TIMER)
00813                     mActionMouseTimer -= EDIT_ACTION_MOUSE_TIMER;
00814             }
00815 
00816         } // if (mMouseLeftPressed)
00817     }
00818 
00819     void EditBox::setTextCursor(size_t _index)
00820     {
00821         // сбрасываем выделение
00822         resetSelect();
00823 
00824         // новая позиция
00825         if (_index > mTextLength)
00826             _index = mTextLength;
00827 
00828         if (mCursorPosition == _index)
00829             return;
00830 
00831         mCursorPosition = _index;
00832 
00833         // обновляем по позиции
00834         if (mClientText != nullptr)
00835             mClientText->setCursorPosition(mCursorPosition);
00836 
00837         updateSelectText();
00838     }
00839 
00840     void EditBox::setTextSelection(size_t _start, size_t _end)
00841     {
00842         if (_start > mTextLength)
00843             _start = mTextLength;
00844         if (_end > mTextLength)
00845             _end = mTextLength;
00846 
00847         mStartSelect = _start;
00848         mEndSelect = _end;
00849 
00850         if (mClientText != nullptr)
00851         {
00852             if (mStartSelect > mEndSelect)
00853                 mClientText->setTextSelection(mEndSelect, mStartSelect);
00854             else
00855                 mClientText->setTextSelection(mStartSelect, mEndSelect);
00856         }
00857 
00858         if (mCursorPosition == mEndSelect)
00859             return;
00860         // курсор на конец выделения
00861         mCursorPosition = mEndSelect;
00862 
00863         // обновляем по позиции
00864         if (mClientText != nullptr)
00865             mClientText->setCursorPosition(mCursorPosition);
00866     }
00867 
00868     bool EditBox::deleteTextSelect(bool _history)
00869     {
00870         if (!isTextSelection())
00871             return false;
00872 
00873         // начало и конец выделения
00874         size_t start = getTextSelectionStart();
00875         size_t end =  getTextSelectionEnd();
00876 
00877         eraseText(start, end - start, _history);
00878 
00879         return true;
00880     }
00881 
00882     void EditBox::resetSelect()
00883     {
00884         if (mStartSelect != ITEM_NONE)
00885         {
00886             mStartSelect = ITEM_NONE;
00887             if (mClientText != nullptr)
00888                 mClientText->setTextSelection(0, 0);
00889         }
00890     }
00891 
00892     void EditBox::commandPosition(size_t _undo, size_t _redo, size_t _length, VectorChangeInfo* _info)
00893     {
00894         if (_info != nullptr)
00895             _info->push_back(TextCommandInfo(_undo, _redo, _length));
00896     }
00897 
00898     void EditBox::commandMerge()
00899     {
00900         if (mVectorUndoChangeInfo.size() < 2)
00901             return; // на всякий
00902         // сохраняем последние набор отмен
00903         VectorChangeInfo info = mVectorUndoChangeInfo.back();
00904         mVectorUndoChangeInfo.pop_back();
00905 
00906         // объединяем последовательности
00907         for (VectorChangeInfo::iterator iter = info.begin(); iter != info.end(); ++iter)
00908         {
00909             mVectorUndoChangeInfo.back().push_back((*iter));
00910         }
00911     }
00912 
00913     bool EditBox::commandUndo()
00914     {
00915         if (mVectorUndoChangeInfo.empty())
00916             return false;
00917 
00918         // сбрасываем выделение
00919         resetSelect();
00920 
00921         // сохраняем последние набор отмен
00922         VectorChangeInfo info = mVectorUndoChangeInfo.back();
00923         // перекидываем последний набор отмен
00924         mVectorUndoChangeInfo.pop_back();
00925         mVectorRedoChangeInfo.push_back(info);
00926 
00927         // берем текст для издевательств
00928         UString text = getRealString();
00929 
00930         // восстанавливаем последовательность
00931         for (VectorChangeInfo::reverse_iterator iter = info.rbegin(); iter != info.rend(); ++iter)
00932         {
00933             if ((*iter).type == TextCommandInfo::COMMAND_INSERT)
00934                 text.erase((*iter).start, (*iter).text.size());
00935             else if ((*iter).type == TextCommandInfo::COMMAND_ERASE)
00936                 text.insert((*iter).start, (*iter).text);
00937             else
00938             {
00939                 mCursorPosition = (*iter).undo;
00940                 mTextLength = (*iter).length;
00941             }
00942         }
00943 
00944         // возвращаем текст
00945         setRealString(text);
00946 
00947         // обновляем по позиции
00948         if (mClientText != nullptr)
00949             mClientText->setCursorPosition(mCursorPosition);
00950         updateSelectText();
00951 
00952         // отсылаем событие о изменении
00953         eventEditTextChange(this);
00954 
00955         return true;
00956     }
00957 
00958     bool EditBox::commandRedo()
00959     {
00960         if (mVectorRedoChangeInfo.empty())
00961             return false;
00962 
00963         // сбрасываем выделение
00964         resetSelect();
00965 
00966         // сохраняем последние набор отмен
00967         VectorChangeInfo info = mVectorRedoChangeInfo.back();
00968         // перекидываем последний набор отмен
00969         mVectorRedoChangeInfo.pop_back();
00970         mVectorUndoChangeInfo.push_back(info);
00971 
00972         // берем текст для издевательств
00973         UString text = getRealString();
00974 
00975         // восстанавливаем последовательность
00976         for (VectorChangeInfo::iterator iter = info.begin(); iter != info.end(); ++iter)
00977         {
00978             if ((*iter).type == TextCommandInfo::COMMAND_INSERT)
00979                 text.insert((*iter).start, (*iter).text);
00980             else if ((*iter).type == TextCommandInfo::COMMAND_ERASE)
00981                 text.erase((*iter).start, (*iter).text.size());
00982             else
00983             {
00984                 mCursorPosition = (*iter).redo;
00985                 mTextLength = (*iter).length;
00986             }
00987 
00988         }
00989 
00990         // возвращаем текст
00991         setRealString(text);
00992 
00993         // обновляем по позиции
00994         if (mClientText != nullptr)
00995             mClientText->setCursorPosition(mCursorPosition);
00996         updateSelectText();
00997 
00998         // отсылаем событие о изменении
00999         eventEditTextChange(this);
01000 
01001         return true;
01002     }
01003 
01004     void EditBox::saveInHistory(VectorChangeInfo* _info)
01005     {
01006         if (_info == nullptr)
01007             return;
01008         // если нет информации об изменении
01009         if ( _info->empty())
01010             return;
01011         if ((_info->size() == 1) && (_info->back().type == TextCommandInfo::COMMAND_POSITION))
01012             return;
01013 
01014         mVectorUndoChangeInfo.push_back(*_info);
01015         // проверяем на максимальный размер
01016         if (mVectorUndoChangeInfo.size() > EDIT_MAX_UNDO)
01017             mVectorUndoChangeInfo.pop_front();
01018     }
01019 
01020     // возвращает текст
01021     UString EditBox::getTextInterval(size_t _start, size_t _count)
01022     {
01023         // подстраховка
01024         if (_start > mTextLength) _start = mTextLength;
01025         // конец диапазона
01026         size_t end = _start + _count;
01027 
01028         // итератор нашей строки
01029         TextIterator iterator(getRealString());
01030 
01031         // дефолтный цвет
01032         UString colour = mClientText == nullptr ? "" : TextIterator::convertTagColour(mClientText->getTextColour());
01033 
01034         // нужно ли вставлять цвет
01035         bool need_colour = true;
01036 
01037         // цикл прохода по строке
01038         while (iterator.moveNext())
01039         {
01040             // текущаяя позиция
01041             size_t pos = iterator.getPosition();
01042 
01043             // еще рано
01044             if (pos < _start)
01045             {
01046                 // берем цвет из позиции и запоминаем
01047                 iterator.getTagColour(colour);
01048 
01049                 continue;
01050             }
01051 
01052             // проверяем на надобность начального тега
01053             else if (pos == _start)
01054             {
01055                 need_colour = ! iterator.getTagColour(colour);
01056                 // сохраняем место откуда начинается
01057                 iterator.saveStartPoint();
01058 
01059             }
01060 
01061             // а теперь просто до конца диапазона
01062             else if (pos == end)
01063                 break;
01064 
01065         }
01066 
01067         // возвращаем строку
01068         if (need_colour)
01069             return colour + iterator.getFromStart();
01070         return iterator.getFromStart();
01071     }
01072 
01073     // выделяет цветом диапазон
01074     void EditBox::_setTextColour(size_t _start, size_t _count, const Colour& _colour, bool _history)
01075     {
01076         // история изменений
01077         VectorChangeInfo* history = nullptr;
01078         if (_history)
01079             history = new VectorChangeInfo();
01080 
01081         // конец диапазона
01082         size_t end = _start + _count;
01083 
01084         // итератор нашей строки
01085         TextIterator iterator(getRealString(), history);
01086 
01087         // дефолтный цвет
01088         UString colour = mClientText == nullptr ? "" : TextIterator::convertTagColour(mClientText->getTextColour());
01089 
01090         // цикл прохода по строке
01091         while (iterator.moveNext())
01092         {
01093             // текущаяя позиция
01094             size_t pos = iterator.getPosition();
01095 
01096             // берем цвет из позиции и запоминаем
01097             iterator.getTagColour(colour);
01098 
01099             // еще рано
01100             if (pos < _start)
01101                 continue;
01102 
01103             // ставим начальный тег
01104             else if (pos == _start)
01105                 iterator.setTagColour(_colour);
01106 
01107             // внутри диапазона очищаем все
01108             else if (pos < end)
01109                 iterator.clearTagColour();
01110 
01111             // на конец ставим последний найденный или дефолтный
01112             else if (pos == end)
01113             {
01114                 iterator.setTagColour(colour);
01115                 // и выходим из цикла
01116                 break;
01117             }
01118 
01119         }
01120 
01121         // сохраняем позицию для восстановления курсора
01122         commandPosition(_start, _start + _count, mTextLength, history);
01123 
01124         // запоминаем в историю
01125         if (_history)
01126         {
01127             saveInHistory(history);
01128             delete history;
01129         }
01130         // сбрасываем историю
01131         else
01132             commandResetHistory();
01133 
01134         // и возвращаем строку на место
01135         setRealString(iterator.getText());
01136     }
01137 
01138     void EditBox::setTextSelectColour(const Colour& _colour, bool _history)
01139     {
01140         // нужно выделение
01141         if ( !isTextSelection())
01142             return;
01143         // начало и конец выделения
01144         size_t start = getTextSelectionStart();
01145         size_t end =  getTextSelectionEnd();
01146         _setTextColour(start, end - start, _colour, _history);
01147     }
01148 
01149     UString EditBox::getTextSelection()
01150     {
01151         if ( !isTextSelection())
01152             return "";
01153         size_t start = getTextSelectionStart();
01154         size_t end =  getTextSelectionEnd();
01155         return getTextInterval(start, end - start);
01156     }
01157 
01158     void EditBox::setEditPassword(bool _password)
01159     {
01160         if (mModePassword == _password)
01161             return;
01162         mModePassword = _password;
01163 
01164         if (mModePassword)
01165         {
01166             if (mClientText != nullptr)
01167             {
01168                 mPasswordText = mClientText->getCaption();
01169                 mClientText->setCaption(UString(mTextLength, '*'));
01170             }
01171         }
01172         else
01173         {
01174             if (mClientText != nullptr)
01175             {
01176                 mClientText->setCaption(mPasswordText);
01177                 mPasswordText.clear();
01178             }
01179         }
01180         // обновляем по размерам
01181         updateView();
01182         // сбрасываем историю
01183         commandResetHistory();
01184     }
01185 
01186     void EditBox::setText(const UString& _caption, bool _history)
01187     {
01188         // сбрасываем выделение
01189         resetSelect();
01190 
01191         // история изменений
01192         VectorChangeInfo* history = nullptr;
01193         if (_history)
01194             history = new VectorChangeInfo();
01195 
01196         // итератор нашей строки
01197         TextIterator iterator(getRealString(), history);
01198 
01199         // вставляем текст
01200         iterator.setText(_caption, mModeMultiline || mModeWordWrap);
01201 
01202         if (mOverflowToTheLeft)
01203         {
01204             iterator.cutMaxLengthFromBeginning(mMaxTextLength);
01205         }
01206         else
01207         {
01208             // обрезаем по максимальной длинне
01209             iterator.cutMaxLength(mMaxTextLength);
01210         }
01211 
01212         // запоминаем размер строки
01213         size_t old = mTextLength;
01214         // новая позиция и положение на конец вставки
01215         mCursorPosition = mTextLength = iterator.getSize();
01216 
01217         // сохраняем позицию для восстановления курсора
01218         commandPosition(0, mTextLength, old, history);
01219 
01220         // запоминаем в историю
01221         if (_history)
01222         {
01223             saveInHistory(history);
01224             delete history;
01225         }
01226         // сбрасываем историю
01227         else
01228             commandResetHistory();
01229 
01230         // и возвращаем строку на место
01231         setRealString(iterator.getText());
01232 
01233         // обновляем по позиции
01234         if (mClientText != nullptr)
01235             mClientText->setCursorPosition(mCursorPosition);
01236         updateSelectText();
01237     }
01238 
01239     void EditBox::insertText(const UString& _text, size_t _start, bool _history)
01240     {
01241         // сбрасываем выделение
01242         resetSelect();
01243 
01244         // если строка пустая, или размер максимален
01245         if (_text.empty())
01246             return;
01247 
01248         if ((mOverflowToTheLeft == false) && (mTextLength == mMaxTextLength))
01249             return;
01250 
01251         // история изменений
01252         VectorChangeInfo* history = nullptr;
01253         if (_history)
01254             history = new VectorChangeInfo();
01255 
01256         // итератор нашей строки
01257         TextIterator iterator(getRealString(), history);
01258 
01259         // дефолтный цвет
01260         UString colour = mClientText == nullptr ? "" : TextIterator::convertTagColour(mClientText->getTextColour());
01261         // нужен ли тег текста
01262         // потом переделать через TextIterator чтобы отвязать понятие тег от эдита
01263         bool need_colour = ( (_text.size() > 6) && (_text[0] == L'#') && (_text[1] != L'#') );
01264 
01265         // цикл прохода по строке
01266         while (iterator.moveNext())
01267         {
01268             // текущаяя позиция
01269             size_t pos = iterator.getPosition();
01270 
01271             // текущий цвет
01272             if (need_colour)
01273                 iterator.getTagColour(colour);
01274 
01275             // если дошли то выходим
01276             if (pos == _start)
01277                 break;
01278         }
01279 
01280         // если нужен цвет то вставляем
01281         if (need_colour)
01282             iterator.setTagColour(colour);
01283 
01284         // а теперь вставляем строку
01285         iterator.insertText(_text, mModeMultiline || mModeWordWrap);
01286 
01287         if (mOverflowToTheLeft)
01288         {
01289             iterator.cutMaxLengthFromBeginning(mMaxTextLength);
01290         }
01291         else
01292         {
01293             // обрезаем по максимальной длинне
01294             iterator.cutMaxLength(mMaxTextLength);
01295         }
01296 
01297         // запоминаем размер строки
01298         size_t old = mTextLength;
01299         // новая позиция и положение на конец вставки
01300         mTextLength = iterator.getSize();
01301             mCursorPosition += mTextLength - old;
01302 
01303         // сохраняем позицию для восстановления курсора
01304         commandPosition(_start, _start + mTextLength - old, old, history);
01305 
01306         // запоминаем в историю
01307         if (_history)
01308         {
01309             saveInHistory(history);
01310             delete history;
01311         }
01312         // сбрасываем историю
01313         else
01314             commandResetHistory();
01315 
01316         // и возвращаем строку на место
01317         setRealString(iterator.getText());
01318 
01319         // обновляем по позиции
01320         if (mClientText != nullptr)
01321             mClientText->setCursorPosition(mCursorPosition);
01322         updateSelectText();
01323     }
01324 
01325     void EditBox::eraseText(size_t _start, size_t _count, bool _history)
01326     {
01327         // чета маловато
01328         if (_count == 0)
01329             return;
01330 
01331         // сбрасываем выделение
01332         resetSelect();
01333 
01334         // история изменений
01335         VectorChangeInfo* history = nullptr;
01336         if (_history)
01337             history = new VectorChangeInfo();
01338 
01339         // итератор нашей строки
01340         TextIterator iterator(getRealString(), history);
01341 
01342         // дефолтный цвет
01343         UString colour;
01344         // конец диапазона
01345         size_t end = _start + _count;
01346         bool need_colour = false;
01347 
01348         // цикл прохода по строке
01349         while (iterator.moveNext())
01350         {
01351             // текущаяя позиция
01352             size_t pos = iterator.getPosition();
01353 
01354             // еще рано
01355             if (pos < _start)
01356             {
01357                 // берем цвет из позиции и запоминаем
01358                 iterator.getTagColour(colour);
01359                 continue;
01360             }
01361 
01362             // сохраняем место откуда начинается
01363             else if (pos == _start)
01364             {
01365                 // если до диапазона был цвет, то нужно закрыть тег
01366                 if (!colour.empty())
01367                 {
01368                     need_colour = true;
01369                     colour.clear();
01370                 }
01371                 // берем цвет из позиции и запоминаем
01372                 iterator.getTagColour(colour);
01373                 iterator.saveStartPoint();
01374             }
01375 
01376             // внутри диапазона
01377             else if (pos < end)
01378             {
01379                 // берем цвет из позиции и запоминаем
01380                 iterator.getTagColour(colour);
01381             }
01382 
01383             // окончание диапазона
01384             else if (pos == end)
01385             {
01386                 // нужно ставить тег или нет
01387                 if (!colour.empty())
01388                     need_colour = true;
01389                 if (iterator.getTagColour(colour))
01390                     need_colour = false;
01391 
01392                 break;
01393             }
01394 
01395         }
01396 
01397         // удаляем диапазон
01398         iterator.eraseFromStart();
01399         // и вставляем последний цвет
01400         if (need_colour)
01401             iterator.setTagColour(colour);
01402 
01403         // сохраняем позицию для восстановления курсора
01404         commandPosition(_start + _count, _start, mTextLength, history);
01405 
01406         // на месте удаленного
01407         mCursorPosition = _start;
01408         mTextLength -= _count;
01409 
01410         // запоминаем в историю
01411         if (_history)
01412         {
01413             saveInHistory(history);
01414             delete history;
01415         }
01416         // сбрасываем историю
01417         else
01418             commandResetHistory();
01419 
01420         // и возвращаем строку на место
01421         setRealString(iterator.getText());
01422 
01423         // обновляем по позиции
01424         if (mClientText != nullptr)
01425             mClientText->setCursorPosition(mCursorPosition);
01426         updateSelectText();
01427     }
01428 
01429     void EditBox::commandCut()
01430     {
01431         // вырезаем в буфер обмена
01432         if (isTextSelection() && (!mModePassword))
01433         {
01434             ClipboardManager::getInstance().setClipboardData(EDIT_CLIPBOARD_TYPE_TEXT, getTextSelection());
01435             if (!mModeReadOnly)
01436             {
01437                 deleteTextSelect(true);
01438                 // отсылаем событие о изменении
01439                 eventEditTextChange(this);
01440             }
01441         }
01442         else
01443             ClipboardManager::getInstance().clearClipboardData(EDIT_CLIPBOARD_TYPE_TEXT);
01444     }
01445 
01446     void EditBox::commandCopy()
01447     {
01448         // копируем в буфер обмена
01449         if (isTextSelection() && (!mModePassword))
01450             ClipboardManager::getInstance().setClipboardData(EDIT_CLIPBOARD_TYPE_TEXT, getTextSelection());
01451         else
01452             ClipboardManager::getInstance().clearClipboardData(EDIT_CLIPBOARD_TYPE_TEXT);
01453     }
01454 
01455     void EditBox::commandPast()
01456     {
01457         // копируем из буфера обмена
01458         std::string clipboard = ClipboardManager::getInstance().getClipboardData(EDIT_CLIPBOARD_TYPE_TEXT);
01459         if ((!mModeReadOnly) && (!clipboard.empty()))
01460         {
01461             // попытка объединения двух комманд
01462             size_t size = mVectorUndoChangeInfo.size();
01463             // непосредственно операции
01464             deleteTextSelect(true);
01465             insertText(clipboard, mCursorPosition, true);
01466             // проверяем на возможность объединения
01467             if ((size + 2) == mVectorUndoChangeInfo.size())
01468                 commandMerge();
01469             // отсылаем событие о изменении
01470             eventEditTextChange(this);
01471         }
01472     }
01473 
01474     const UString& EditBox::getRealString()
01475     {
01476         if (mModePassword)
01477             return mPasswordText;
01478         else if (mClientText == nullptr)
01479             return mPasswordText;
01480 
01481         return mClientText->getCaption();
01482     }
01483 
01484     void EditBox::setRealString(const UString& _caption)
01485     {
01486         if (mModePassword)
01487         {
01488             mPasswordText = _caption;
01489             if (mClientText != nullptr)
01490                 mClientText->setCaption(UString(mTextLength, (UString::code_point)mCharPassword));
01491         }
01492         else
01493         {
01494             if (mClientText != nullptr)
01495                 mClientText->setCaption(_caption);
01496         }
01497     }
01498 
01499     void EditBox::setPasswordChar(Char _char)
01500     {
01501         mCharPassword = _char;
01502         if (mModePassword)
01503         {
01504             if (mClientText != nullptr)
01505                 mClientText->setCaption(UString(mTextLength, (UString::code_point)mCharPassword));
01506         }
01507     }
01508 
01509     void EditBox::updateEditState()
01510     {
01511         if (!getEnabled())
01512             _setWidgetState("disabled");
01513         else if (mIsPressed)
01514         {
01515             if (mIsFocus)
01516                 _setWidgetState("pushed");
01517             else
01518                 _setWidgetState("normal_checked");
01519         }
01520         else if (mIsFocus)
01521             _setWidgetState("highlighted");
01522         else
01523             _setWidgetState("normal");
01524     }
01525 
01526     void EditBox::setPosition(const IntPoint& _point)
01527     {
01528         Base::setPosition(_point);
01529     }
01530 
01531     void EditBox::eraseView()
01532     {
01533         // если перенос, то сбрасываем размер текста
01534         if (mModeWordWrap)
01535         {
01536             if (mClientText != nullptr)
01537                 mClientText->setWordWrap(true);
01538         }
01539 
01540         updateView();
01541     }
01542 
01543     void EditBox::setSize(const IntSize& _size)
01544     {
01545         Base::setSize(_size);
01546 
01547         eraseView();
01548     }
01549 
01550     void EditBox::setCoord(const IntCoord& _coord)
01551     {
01552         Base::setCoord(_coord);
01553 
01554         eraseView();
01555     }
01556 
01557     void EditBox::setCaption(const UString& _value)
01558     {
01559         setText(_value, false);
01560     }
01561 
01562     const UString& EditBox::getCaption()
01563     {
01564         return getRealString();
01565     }
01566 
01567     void EditBox::updateSelectText()
01568     {
01569         if (!mModeStatic)
01570         {
01571             InputManager& input = InputManager::getInstance();
01572             if ((input.isShiftPressed()) && (mStartSelect != ITEM_NONE))
01573             {
01574                 // меняем выделение
01575                 mEndSelect = (size_t)mCursorPosition;
01576                 if (mClientText != nullptr)
01577                 {
01578                     if (mStartSelect > mEndSelect)
01579                         mClientText->setTextSelection(mEndSelect, mStartSelect);
01580                     else
01581                         mClientText->setTextSelection(mStartSelect, mEndSelect);
01582                 }
01583 
01584             }
01585             else if (mStartSelect != ITEM_NONE)
01586             {
01587                 // сбрасываем шифт
01588                 mStartSelect = ITEM_NONE;
01589                 if (mClientText != nullptr)
01590                     mClientText->setTextSelection(0, 0);
01591             }
01592         }
01593 
01594         // пытаемся показать курсор
01595         updateViewWithCursor();
01596     }
01597 
01598     void EditBox::setTextAlign(Align _value)
01599     {
01600         Base::setTextAlign(_value);
01601 
01602         if (mClientText != nullptr)
01603             mClientText->setTextAlign(_value);
01604 
01605         // так как мы сами рулим смещениями
01606         updateView();
01607     }
01608 
01609     void EditBox::setTextColour(const Colour& _value)
01610     {
01611         Base::setTextColour(_value);
01612 
01613         if (mClientText != nullptr)
01614             mClientText->setTextColour(_value);
01615     }
01616 
01617     IntCoord EditBox::getTextRegion()
01618     {
01619         if (mClientText != nullptr)
01620             return mClientText->getCoord();
01621         return Base::getTextRegion();
01622     }
01623 
01624     IntSize EditBox::getTextSize()
01625     {
01626         if (mClientText != nullptr)
01627             return mClientText->getTextSize();
01628         return Base::getTextSize();
01629     }
01630 
01631     void EditBox::notifyScrollChangePosition(ScrollBar* _sender, size_t _position)
01632     {
01633         if (mClientText == nullptr)
01634             return;
01635 
01636         if (_sender == mVScroll)
01637         {
01638             IntPoint point = mClientText->getViewOffset();
01639             point.top = _position;
01640             mClientText->setViewOffset(point);
01641         }
01642         else if (_sender == mHScroll)
01643         {
01644             IntPoint point = mClientText->getViewOffset();
01645             point.left = _position;
01646             mClientText->setViewOffset(point);
01647         }
01648     }
01649 
01650     void EditBox::notifyMouseWheel(Widget* _sender, int _rel)
01651     {
01652         if (mClientText == nullptr)
01653             return;
01654 
01655         if (mVRange != 0)
01656         {
01657             IntPoint point = mClientText->getViewOffset();
01658             int offset = point.top;
01659             if (_rel < 0)
01660                 offset += EDIT_MOUSE_WHEEL;
01661             else
01662                 offset -= EDIT_MOUSE_WHEEL;
01663 
01664             if (offset < 0)
01665                 offset = 0;
01666             else if (offset > (int)mVRange)
01667                 offset = mVRange;
01668 
01669             if (offset != point.top)
01670             {
01671                 point.top = offset;
01672                 if (mVScroll != nullptr)
01673                     mVScroll->setScrollPosition(offset);
01674                 mClientText->setViewOffset(point);
01675             }
01676         }
01677         else if (mHRange != 0)
01678         {
01679             IntPoint point = mClientText->getViewOffset();
01680             int offset = point.left;
01681             if (_rel < 0)
01682                 offset += EDIT_MOUSE_WHEEL;
01683             else
01684                 offset -= EDIT_MOUSE_WHEEL;
01685 
01686             if (offset < 0)
01687                 offset = 0;
01688             else if (offset > (int)mHRange)
01689                 offset = mHRange;
01690 
01691             if (offset != point.left)
01692             {
01693                 point.left = offset;
01694                 if (mHScroll != nullptr)
01695                     mHScroll->setScrollPosition(offset);
01696                 mClientText->setViewOffset(point);
01697             }
01698         }
01699     }
01700 
01701     void EditBox::setEditWordWrap(bool _value)
01702     {
01703         mModeWordWrap = _value;
01704         if (mClientText != nullptr)
01705             mClientText->setWordWrap(mModeWordWrap);
01706 
01707         eraseView();
01708     }
01709 
01710     void EditBox::setFontName(const std::string& _value)
01711     {
01712         Base::setFontName(_value);
01713 
01714         if (mClientText != nullptr)
01715             mClientText->setFontName(_value);
01716 
01717         eraseView();
01718     }
01719 
01720     void EditBox::setFontHeight(int _value)
01721     {
01722         Base::setFontHeight(_value);
01723 
01724         if (mClientText != nullptr)
01725             mClientText->setFontHeight(_value);
01726 
01727         eraseView();
01728     }
01729 
01730     void EditBox::updateView()
01731     {
01732         updateScrollSize();
01733         updateScrollPosition();
01734     }
01735 
01736     void EditBox::updateViewWithCursor()
01737     {
01738         updateScrollSize();
01739         updateCursorPosition();
01740         updateScrollPosition();
01741     }
01742 
01743     void EditBox::updateCursorPosition()
01744     {
01745         if (mClientText == nullptr || mClient == nullptr)
01746             return;
01747 
01748         // размер контекста текста
01749         IntSize textSize = mClientText->getTextSize();
01750 
01751         // текущее смещение контекста текста
01752         IntPoint point = mClientText->getViewOffset();
01753         // расчетное смещение
01754         IntPoint offset = point;
01755 
01756         // абсолютные координаты курсора
01757         IntRect cursor = mClientText->getCursorRect(mCursorPosition);
01758         cursor.right ++;
01759 
01760         // абсолютные координаты вью
01761         const IntRect& view = mClient->getAbsoluteRect();
01762 
01763         // проверяем и показываем курсор
01764         if (!view.inside(cursor))
01765         {
01766             // горизонтальное смещение
01767             if (textSize.width > view.width())
01768             {
01769                 if (cursor.left < view.left)
01770                 {
01771                     offset.left = point.left - (view.left - cursor.left);
01772                     // добавляем смещение, только если курсор не перепрыгнет
01773                     if ((float(view.width()) - EDIT_OFFSET_HORZ_CURSOR) > EDIT_OFFSET_HORZ_CURSOR)
01774                         offset.left -= int(EDIT_OFFSET_HORZ_CURSOR);
01775                 }
01776                 else if (cursor.right > view.right)
01777                 {
01778                     offset.left = point.left + (cursor.right - view.right);
01779                     // добавляем смещение, только если курсор не перепрыгнет
01780                     if ((float(view.width()) - EDIT_OFFSET_HORZ_CURSOR) > EDIT_OFFSET_HORZ_CURSOR)
01781                         offset.left += int(EDIT_OFFSET_HORZ_CURSOR);
01782                 }
01783             }
01784 
01785             // вертикальное смещение
01786             if (textSize.height > view.height())
01787             {
01788                 int delta = 0;
01789                 if (cursor.height() > view.height())
01790                 {
01791                     // if text is bigger than edit height then place it in center
01792                     delta = ((cursor.bottom - view.bottom) - (view.top - cursor.top)) / 2;
01793                 }
01794                 else if (cursor.top < view.top)
01795                 {
01796                     delta = - (view.top - cursor.top);
01797                 }
01798                 else if (cursor.bottom > view.bottom)
01799                 {
01800                     delta = (cursor.bottom - view.bottom);
01801                 }
01802                 offset.top = point.top + delta;
01803             }
01804 
01805         }
01806 
01807         if (offset != point)
01808         {
01809             mClientText->setViewOffset(offset);
01810             // обновить скролы
01811             if (mVScroll != nullptr)
01812                 mVScroll->setScrollPosition(offset.top);
01813             if (mHScroll != nullptr)
01814                 mHScroll->setScrollPosition(offset.left);
01815         }
01816     }
01817 
01818     void EditBox::setContentPosition(const IntPoint& _point)
01819     {
01820         if (mClientText != nullptr)
01821             mClientText->setViewOffset(_point);
01822     }
01823 
01824     IntSize EditBox::getViewSize()
01825     {
01826         if (mClientText != nullptr)
01827             return mClientText->getSize();
01828         return ScrollViewBase::getViewSize();
01829     }
01830 
01831     IntSize EditBox::getContentSize()
01832     {
01833         if (mClientText != nullptr)
01834             return mClientText->getTextSize();
01835         return ScrollViewBase::getContentSize();
01836     }
01837 
01838     size_t EditBox::getVScrollPage()
01839     {
01840         if (mClientText != nullptr)
01841             return (size_t)mClientText->getFontHeight();
01842         return ScrollViewBase::getVScrollPage();
01843     }
01844 
01845     size_t EditBox::getHScrollPage()
01846     {
01847         if (mClientText != nullptr)
01848             return (size_t)mClientText->getFontHeight();
01849         return ScrollViewBase::getHScrollPage();
01850     }
01851 
01852     IntPoint EditBox::getContentPosition()
01853     {
01854         if (mClientText != nullptr)
01855             return mClientText->getViewOffset();
01856         return ScrollViewBase::getContentPosition();
01857     }
01858 
01859     Align EditBox::getContentAlign()
01860     {
01861         if (mClientText != nullptr)
01862             return mClientText->getTextAlign();
01863         return ScrollViewBase::getContentAlign();
01864     }
01865 
01866     void EditBox::setTextIntervalColour(size_t _start, size_t _count, const Colour& _colour)
01867     {
01868         _setTextColour(_start, _count, _colour, false);
01869     }
01870 
01871     size_t EditBox::getTextSelectionStart() const
01872     {
01873         return (mStartSelect == ITEM_NONE) ? ITEM_NONE : (mStartSelect > mEndSelect ? mEndSelect : mStartSelect);
01874     }
01875 
01876     size_t EditBox::getTextSelectionEnd() const
01877     {
01878         return (mStartSelect == ITEM_NONE) ? ITEM_NONE : (mStartSelect > mEndSelect ? mStartSelect : mEndSelect);
01879     }
01880 
01881     bool EditBox::isTextSelection() const
01882     {
01883         return (mStartSelect != ITEM_NONE) && (mStartSelect != mEndSelect);
01884     }
01885 
01886     void EditBox::deleteTextSelection()
01887     {
01888         deleteTextSelect(false);
01889     }
01890 
01891     void EditBox::setTextSelectionColour(const Colour& _colour)
01892     {
01893         setTextSelectColour(_colour, false);
01894     }
01895 
01896     size_t EditBox::getTextSelectionLength() const
01897     {
01898         return mEndSelect - mStartSelect;
01899     }
01900 
01901     void EditBox::setOnlyText(const UString& _text)
01902     {
01903         setText(TextIterator::toTagsString(_text), false);
01904     }
01905 
01906     UString EditBox::getOnlyText()
01907     {
01908         return TextIterator::getOnlyText(getRealString());
01909     }
01910 
01911     void EditBox::insertText(const UString& _text, size_t _index)
01912     {
01913         insertText(_text, _index, false);
01914     }
01915 
01916     void EditBox::addText(const UString& _text)
01917     {
01918         insertText(_text, ITEM_NONE, false);
01919     }
01920 
01921     void EditBox::eraseText(size_t _start, size_t _count)
01922     {
01923         eraseText(_start, _count, false);
01924     }
01925 
01926     void EditBox::setEditReadOnly(bool _value)
01927     {
01928         mModeReadOnly = _value;
01929         // сбрасываем историю
01930         commandResetHistory();
01931     }
01932 
01933     void EditBox::setEditMultiLine(bool _value)
01934     {
01935         mModeMultiline = _value;
01936         // на всякий, для убирания переносов
01937         if (!mModeMultiline)
01938         {
01939             setText(getRealString(), false);
01940         }
01941         // обновляем по размерам
01942         else
01943         {
01944             updateView();
01945         }
01946         // сбрасываем историю
01947         commandResetHistory();
01948     }
01949 
01950     void EditBox::setEditStatic(bool _value)
01951     {
01952         mModeStatic = _value;
01953         resetSelect();
01954 
01955         if (mClient != nullptr)
01956         {
01957             if (mModeStatic)
01958                 mClient->setPointer("");
01959             else
01960                 mClient->setPointer(mOriginalPointer);
01961         }
01962     }
01963 
01964     void EditBox::setPasswordChar(const UString& _value)
01965     {
01966         if (!_value.empty())
01967             setPasswordChar(_value[0]);
01968     }
01969 
01970     void EditBox::setVisibleVScroll(bool _value)
01971     {
01972         mVisibleVScroll = _value;
01973         updateView();
01974     }
01975 
01976     void EditBox::setVisibleHScroll(bool _value)
01977     {
01978         mVisibleHScroll = _value;
01979         updateView();
01980     }
01981 
01982     size_t EditBox::getVScrollRange() const
01983     {
01984         return mVRange + 1;
01985     }
01986 
01987     size_t EditBox::getVScrollPosition()
01988     {
01989         return mClientText == nullptr ? 0 : mClientText->getViewOffset().top;
01990     }
01991 
01992     void EditBox::setVScrollPosition(size_t _index)
01993     {
01994         if (mClientText == nullptr)
01995             return;
01996 
01997         if (_index > mVRange)
01998             _index = mVRange;
01999 
02000         IntPoint point = mClientText->getViewOffset();
02001         point.top = _index;
02002 
02003         mClientText->setViewOffset(point);
02004         // обновить скролы
02005         if (mVScroll != nullptr)
02006             mVScroll->setScrollPosition(point.top);
02007     }
02008 
02009     size_t EditBox::getHScrollRange() const
02010     {
02011         return mHRange + 1;
02012     }
02013 
02014     size_t EditBox::getHScrollPosition()
02015     {
02016         return mClientText == nullptr ? 0 : mClientText->getViewOffset().left;
02017     }
02018 
02019     void EditBox::setHScrollPosition(size_t _index)
02020     {
02021         if (mClientText == nullptr)
02022             return;
02023 
02024         if (_index > mHRange)
02025             _index = mHRange;
02026 
02027         IntPoint point = mClientText->getViewOffset();
02028         point.left = _index;
02029 
02030         mClientText->setViewOffset(point);
02031         // обновить скролы
02032         if (mHScroll != nullptr)
02033             mHScroll->setScrollPosition(point.left);
02034     }
02035 
02036     bool EditBox::getInvertSelected()
02037     {
02038         return mClientText == nullptr ? false : mClientText->getInvertSelected();
02039     }
02040 
02041     void EditBox::setInvertSelected(bool _value)
02042     {
02043         if (mClientText != nullptr)
02044             mClientText->setInvertSelected(_value);
02045     }
02046 
02047     void EditBox::setPropertyOverride(const std::string& _key, const std::string& _value)
02048     {
02049         if (_key == "CursorPosition")
02050             setTextCursor(utility::parseValue<size_t>(_value));
02051         else if (_key == "TextSelect")
02052             setTextSelection(utility::parseValue< types::TSize<size_t> >(_value).width, utility::parseValue< types::TSize<size_t> >(_value).height);
02053         else if (_key == "ReadOnly")
02054             setEditReadOnly(utility::parseValue<bool>(_value));
02055         else if (_key == "Password")
02056             setEditPassword(utility::parseValue<bool>(_value));
02057         else if (_key == "MultiLine")
02058             setEditMultiLine(utility::parseValue<bool>(_value));
02059         else if (_key == "PasswordChar")
02060             setPasswordChar(_value);
02061         else if (_key == "MaxTextLength")
02062             setMaxTextLength(utility::parseValue<size_t>(_value));
02063         else if (_key == "OverflowToTheLeft")
02064             setOverflowToTheLeft(utility::parseValue<bool>(_value));
02065         else if (_key == "Static")
02066             setEditStatic(utility::parseValue<bool>(_value));
02067         else if (_key == "VisibleVScroll")
02068             setVisibleVScroll(utility::parseValue<bool>(_value));
02069         else if (_key == "VisibleHScroll")
02070             setVisibleHScroll(utility::parseValue<bool>(_value));
02071         else if (_key == "WordWrap")
02072             setEditWordWrap(utility::parseValue<bool>(_value));
02073         else if (_key == "TabPrinting")
02074             setTabPrinting(utility::parseValue<bool>(_value));
02075         else if (_key == "InvertSelected")
02076             setInvertSelected(utility::parseValue<bool>(_value));
02077         else
02078         {
02079             Base::setPropertyOverride(_key, _value);
02080             return;
02081         }
02082         eventChangeProperty(this, _key, _value);
02083     }
02084 
02085     size_t EditBox::getTextCursor() const
02086     {
02087         return mCursorPosition;
02088     }
02089 
02090     size_t EditBox::getTextLength() const
02091     {
02092         return mTextLength;
02093     }
02094 
02095     void EditBox::setOverflowToTheLeft(bool _value)
02096     {
02097         mOverflowToTheLeft = _value;
02098     }
02099 
02100     bool EditBox::getOverflowToTheLeft() const
02101     {
02102         return mOverflowToTheLeft;
02103     }
02104 
02105     void EditBox::setMaxTextLength(size_t _value)
02106     {
02107         mMaxTextLength = _value;
02108     }
02109 
02110     size_t EditBox::getMaxTextLength() const
02111     {
02112         return mMaxTextLength;
02113     }
02114 
02115     bool EditBox::getEditReadOnly() const
02116     {
02117         return mModeReadOnly;
02118     }
02119 
02120     bool EditBox::getEditPassword() const
02121     {
02122         return mModePassword;
02123     }
02124 
02125     bool EditBox::getEditMultiLine() const
02126     {
02127         return mModeMultiline;
02128     }
02129 
02130     bool EditBox::getEditStatic() const
02131     {
02132         return mModeStatic;
02133     }
02134 
02135     Char EditBox::getPasswordChar() const
02136     {
02137         return mCharPassword;
02138     }
02139 
02140     bool EditBox::getEditWordWrap() const
02141     {
02142         return mModeWordWrap;
02143     }
02144 
02145     void EditBox::setTabPrinting(bool _value)
02146     {
02147         mTabPrinting = _value;
02148     }
02149 
02150     bool EditBox::getTabPrinting() const
02151     {
02152         return mTabPrinting;
02153     }
02154 
02155     void EditBox::setPosition(int _left, int _top)
02156     {
02157         setPosition(IntPoint(_left, _top));
02158     }
02159 
02160     void EditBox::setSize(int _width, int _height)
02161     {
02162         setSize(IntSize(_width, _height));
02163     }
02164 
02165     void EditBox::setCoord(int _left, int _top, int _width, int _height)
02166     {
02167         setCoord(IntCoord(_left, _top, _width, _height));
02168     }
02169 
02170     bool EditBox::isVisibleVScroll() const
02171     {
02172         return mVisibleVScroll;
02173     }
02174 
02175     bool EditBox::isVisibleHScroll() const
02176     {
02177         return mVisibleHScroll;
02178     }
02179 
02180     void EditBox::commandResetRedo()
02181     {
02182         mVectorRedoChangeInfo.clear();
02183     }
02184 
02185     void EditBox::commandResetHistory()
02186     {
02187         mVectorRedoChangeInfo.clear();
02188         mVectorUndoChangeInfo.clear();
02189     }
02190 
02191     void EditBox::setTextShadowColour(const Colour& _value)
02192     {
02193         Base::setTextShadowColour(_value);
02194 
02195         if (mClientText != nullptr)
02196             mClientText->setShadowColour(_value);
02197     }
02198 
02199     void EditBox::setTextShadow(bool _value)
02200     {
02201         Base::setTextShadow(_value);
02202 
02203         if (mClientText != nullptr)
02204             mClientText->setShadow(_value);
02205     }
02206 
02207 } // namespace MyGUI