MyGUI
3.0.1
|
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