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