• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

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

Generated on Sun Jan 30 2011 for MyGUI by  doxygen 1.7.1