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