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