From 276a5f9f7ef2f1fd5fad7339db2d2a9154ce9870 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Tue, 7 Jan 2014 23:32:02 +0300 Subject: In input fields add support for combinations Ctrl+left, Ctrl+right. --- src/gui/widgets/textfield.cpp | 371 +++++++++++++++++++++++++----------------- src/gui/widgets/textfield.h | 12 ++ 2 files changed, 235 insertions(+), 148 deletions(-) (limited to 'src/gui/widgets') diff --git a/src/gui/widgets/textfield.cpp b/src/gui/widgets/textfield.cpp index ddee77233..58a1f7e18 100644 --- a/src/gui/widgets/textfield.cpp +++ b/src/gui/widgets/textfield.cpp @@ -24,9 +24,7 @@ #include "client.h" -#if defined ANDROID || defined USE_SDL2 #include "input/inputmanager.h" -#endif #include "input/keydata.h" #include "input/keyevent.h" @@ -275,71 +273,7 @@ void TextField::keyPressed(gcn::KeyEvent &keyEvent) mLastEventPaste = 0; bool consumed(false); - switch (val) - { - case 2: // Ctrl+b - { - moveCaretBack(); - consumed = true; - break; - } - - case 6: // Ctrl+f - { - moveCaretForward(); - consumed = true; - break; - } - - case 4: // Ctrl+d - { - caretDelete(); - consumed = true; - break; - } - - case 8: // Ctrl+h - deleteCharLeft(mText, &mCaretPosition); - consumed = true; - break; - - case 5: // Ctrl+e - mCaretPosition = static_cast(mText.size()); - consumed = true; - break; - - case 11: // Ctrl+k - mText = mText.substr(0, mCaretPosition); - consumed = true; - break; - - case 21: // Ctrl+u - caretDeleteToStart(); - consumed = true; - break; - - case 3: // Ctrl+c - handleCopy(); - consumed = true; - break; - - case 22: // Control code 22, SYNCHRONOUS IDLE, sent on Ctrl+v - // hack to prevent paste key sticking - if (mLastEventPaste && mLastEventPaste > cur_time) - break; - handlePaste(); - mLastEventPaste = cur_time + 2; - consumed = true; - break; - - case 23: // Ctrl+w - caretDeleteWord(); - consumed = true; - break; - - default: - break; - } + handleSDLKeys(val, consumed); if (consumed) { @@ -352,7 +286,39 @@ void TextField::keyPressed(gcn::KeyEvent &keyEvent) } #endif - const int action = static_cast(&keyEvent)->getActionId(); + if (consumed) + { + keyEvent.consume(); + } + else + { + const int action = static_cast(&keyEvent)->getActionId(); + if (!inputManager.isActionActive(static_cast( + Input::KEY_GUI_CTRL))) + { + if (!handleNormalKeys(action, consumed)) + { + if (consumed) + keyEvent.consume(); + return; + } + } + else + { + handleCtrlKeys(action, consumed); + } + } + + if (mSendAlwaysEvents) + distributeActionEvent(); + + if (consumed) + keyEvent.consume(); + fixScroll(); +} + +bool TextField::handleNormalKeys(const int action, bool &consumed) +{ switch (action) { case Input::KEY_GUI_LEFT: @@ -407,9 +373,9 @@ void TextField::keyPressed(gcn::KeyEvent &keyEvent) case Input::KEY_GUI_SELECT2: distributeActionEvent(); - keyEvent.consume(); + consumed = true; fixScroll(); - return; + return false; case Input::KEY_GUI_HOME: mCaretPosition = 0; @@ -423,99 +389,169 @@ void TextField::keyPressed(gcn::KeyEvent &keyEvent) case Input::KEY_GUI_TAB: if (mLoseFocusOnTab) - return; + return false; consumed = true; break; default: break; } + return true; +} - if (mSendAlwaysEvents) - distributeActionEvent(); - - if (consumed) +void TextField::handleCtrlKeys(const int action, bool &consumed) +{ + switch (action) { - keyEvent.consume(); - } + case Input::KEY_GUI_LEFT: + { + moveCaretWordBack(); + consumed = true; + break; + } + case Input::KEY_GUI_RIGHT: + { + moveCaretWordForward(); + consumed = true; + break; + } #ifdef USE_SDL2 - else + case Input::KEY_GUI_B: + { + moveCaretBack(); + consumed = true; + break; + } + case Input::KEY_GUI_C: + { + handleCopy(); + consumed = true; + break; + } + case Input::KEY_GUI_D: + { + caretDelete(); + consumed = true; + break; + } + case Input::KEY_GUI_E: + { + mCaretPosition = static_cast(mText.size()); + consumed = true; + break; + } + case Input::KEY_GUI_F: + { + moveCaretBack(); + consumed = true; + break; + } + case Input::KEY_GUI_H: + { + deleteCharLeft(mText, &mCaretPosition); + consumed = true; + break; + } + case Input::KEY_GUI_U: + { + caretDeleteToStart(); + consumed = true; + break; + } + case Input::KEY_GUI_K: + { + mText = mText.substr(0, mCaretPosition); + consumed = true; + break; + } + case Input::KEY_GUI_V: + { + handlePaste(); + consumed = true; + break; + } + case Input::KEY_GUI_W: + { + caretDeleteWord(); + consumed = true; + break; + } +#endif + default: + break; + } +} + +#ifndef USE_SDL2 +void TextField::handleSDLKeys(const int val, bool &consumed) +{ + switch (val) { - if (inputManager.isActionActive(static_cast(Input::KEY_GUI_CTRL))) + case 2: // Ctrl+b { - switch (action) - { - case Input::KEY_GUI_B: - { - moveCaretBack(); - consumed = true; - break; - } - case Input::KEY_GUI_C: - { - handleCopy(); - consumed = true; - break; - } - case Input::KEY_GUI_D: - { - caretDelete(); - consumed = true; - break; - } - case Input::KEY_GUI_E: - { - mCaretPosition = static_cast(mText.size()); - consumed = true; - break; - } - case Input::KEY_GUI_F: - { - moveCaretBack(); - consumed = true; - break; - } - case Input::KEY_GUI_H: - { - deleteCharLeft(mText, &mCaretPosition); - consumed = true; - break; - } - case Input::KEY_GUI_U: - { - caretDeleteToStart(); - consumed = true; - break; - } - case Input::KEY_GUI_K: - { - mText = mText.substr(0, mCaretPosition); - consumed = true; - break; - } - case Input::KEY_GUI_V: - { - handlePaste(); - consumed = true; - break; - } - case Input::KEY_GUI_W: - { - caretDeleteWord(); - consumed = true; - break; - } + moveCaretBack(); + consumed = true; + break; + } - default: - break; - } + case 6: // Ctrl+f + { + moveCaretForward(); + consumed = true; + break; } + + case 4: // Ctrl+d + { + caretDelete(); + consumed = true; + break; + } + + case 8: // Ctrl+h + deleteCharLeft(mText, &mCaretPosition); + consumed = true; + break; + + case 5: // Ctrl+e + mCaretPosition = static_cast(mText.size()); + consumed = true; + break; + + case 11: // Ctrl+k + mText = mText.substr(0, mCaretPosition); + consumed = true; + break; + + case 21: // Ctrl+u + caretDeleteToStart(); + consumed = true; + break; + + case 3: // Ctrl+c + handleCopy(); + consumed = true; + break; + + case 22: // Control code 22, SYNCHRONOUS IDLE, sent on Ctrl+v + // hack to prevent paste key sticking + if (mLastEventPaste && mLastEventPaste > cur_time) + break; + handlePaste(); + mLastEventPaste = cur_time + 2; + consumed = true; + break; + + case 23: // Ctrl+w + caretDeleteWord(); + consumed = true; + break; + + default: + break; } - if (consumed) - keyEvent.consume(); -#endif - fixScroll(); } +#endif void TextField::moveCaretBack() { @@ -571,6 +607,45 @@ void TextField::caretDeleteToStart() } } +void TextField::moveCaretWordBack() +{ + const int oldCaret = mCaretPosition; + while (mCaretPosition > 0) + { + if (!isWordSeparator(mText[mCaretPosition - 1])) + break; + mCaretPosition --; + } + if (oldCaret != mCaretPosition) + return; + while (mCaretPosition > 0) + { + if (isWordSeparator(mText[mCaretPosition - 1])) + break; + mCaretPosition --; + } +} + +void TextField::moveCaretWordForward() +{ + const unsigned sz = static_cast(mText.size()); + const int oldCaret = mCaretPosition; + while (mCaretPosition < sz) + { + if (!isWordSeparator(mText[mCaretPosition])) + break; + mCaretPosition ++; + } + if (oldCaret != mCaretPosition) + return; + while (mCaretPosition < sz) + { + if (isWordSeparator(mText[mCaretPosition])) + break; + mCaretPosition ++; + } +} + void TextField::caretDeleteWord() { while (mCaretPosition > 0) diff --git a/src/gui/widgets/textfield.h b/src/gui/widgets/textfield.h index 675e9761d..abff9cf2a 100644 --- a/src/gui/widgets/textfield.h +++ b/src/gui/widgets/textfield.h @@ -131,6 +131,10 @@ class TextField : public gcn::TextField, void moveCaretForward(); + void moveCaretWordBack(); + + void moveCaretWordForward(); + void caretDelete(); void caretDeleteToStart(); @@ -146,6 +150,14 @@ class TextField : public gcn::TextField, bool mSendAlwaysEvents; + bool handleNormalKeys(const int action, bool &consumed); + + void handleCtrlKeys(const int action, bool &consumed); + +#ifndef USE_SDL2 + void handleSDLKeys(const int val, bool &consumed); +#endif + static Skin *mSkin; private: -- cgit v1.2.3-70-g09d2