diff --git a/include/IEventReceiver.h b/include/IEventReceiver.h index e1c78a6..4b0af17 100644 --- a/include/IEventReceiver.h +++ b/include/IEventReceiver.h @@ -34,7 +34,11 @@ namespace irr IrrlichtDevice::postEventFromUser. They take the same path as mouse events. */ EET_KEY_INPUT_EVENT, - //! A touch input event. + //! A string input event. + /** This event is created when multiple characters are sent at a time (e.g. using an IME). */ + EET_STRING_INPUT_EVENT, + + //! A touch input event. EET_TOUCH_INPUT_EVENT, //! A accelerometer event. @@ -413,7 +417,14 @@ struct SEvent bool Control:1; }; - //! Any kind of touch event. + //! String input event. + struct SStringInput + { + //! The string that is entered + core::stringw *Str; + }; + + //! Any kind of touch event. struct STouchInput { // Touch ID. @@ -581,6 +592,7 @@ struct SEvent struct SGUIEvent GUIEvent; struct SMouseInput MouseInput; struct SKeyInput KeyInput; + struct SStringInput StringInput; struct STouchInput TouchInput; struct SAccelerometerEvent AccelerometerEvent; struct SGyroscopeEvent GyroscopeEvent; diff --git a/include/IGUIElement.h b/include/IGUIElement.h index 5968430..c6f275b 100644 --- a/include/IGUIElement.h +++ b/include/IGUIElement.h @@ -789,6 +789,13 @@ public: } + //! Returns whether the element takes input from the IME + virtual bool acceptsIME() + { + return false; + } + + //! Writes attributes of the scene node. /** Implement this to expose the attributes of your scene node for scripting languages, editors, debuggers or xml serialization purposes. */ diff --git a/source/Irrlicht/CGUIEditBox.cpp b/source/Irrlicht/CGUIEditBox.cpp index a55664e..5d25601 100644 --- a/source/Irrlicht/CGUIEditBox.cpp +++ b/source/Irrlicht/CGUIEditBox.cpp @@ -252,6 +252,10 @@ bool CGUIEditBox::OnEvent(const SEvent& event) if (processMouse(event)) return true; break; + case EET_STRING_INPUT_EVENT: + inputString(*event.StringInput.Str); + return true; + break; default: break; } @@ -1391,76 +1395,91 @@ s32 CGUIEditBox::getLineFromPos(s32 pos) void CGUIEditBox::inputChar(wchar_t c) +{ + if (c == 0) + return; + core::stringw s(&c, 1); + inputString(s); +} + +void CGUIEditBox::inputString(const core::stringw &str) { if (!isEnabled()) return; - if (c != 0) + core::stringw s; + u32 len = str.size(); + + if (MarkBegin != MarkEnd) { + // replace marked text + const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; + const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; + + s = Text.subString(0, realmbgn); + s.append(str); + s.append( Text.subString(realmend, Text.size()-realmend) ); + Text = s; + CursorPos = realmbgn+len; + } + else if ( OverwriteMode ) + { + //check to see if we are at the end of the text + if ( (u32)CursorPos+len < Text.size()) { - core::stringw s; - - if (MarkBegin != MarkEnd) + bool isEOL = false; + s32 EOLPos; + for (u32 i = CursorPos; i < CursorPos+len && i < Max; i++) { - // replace marked text - const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; - const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; - - s = Text.subString(0, realmbgn); - s.append(c); - s.append( Text.subString(realmend, Text.size()-realmend) ); - Text = s; - CursorPos = realmbgn+1; - } - else if ( OverwriteMode ) - { - //check to see if we are at the end of the text - if ( (u32)CursorPos != Text.size()) + if (Text[i] == L'\n' || Text[i] == L'\r') { - bool isEOL = (Text[CursorPos] == L'\n' ||Text[CursorPos] == L'\r' ); - if (!isEOL || Text.size() < Max || Max == 0) - { - s = Text.subString(0, CursorPos); - s.append(c); - if ( isEOL ) - { - //just keep appending to the current line - //This follows the behavior of other gui libraries behaviors - s.append( Text.subString(CursorPos, Text.size()-CursorPos) ); - } - else - { - //replace the next character - s.append( Text.subString(CursorPos + 1,Text.size() - CursorPos + 1)); - } - Text = s; - ++CursorPos; - } - } - else if (Text.size() < Max || Max == 0) - { - // add new character because we are at the end of the string - s = Text.subString(0, CursorPos); - s.append(c); - s.append( Text.subString(CursorPos, Text.size()-CursorPos) ); - Text = s; - ++CursorPos; + isEOL = true; + EOLPos = i; + break; } } - else if (Text.size() < Max || Max == 0) + if (!isEOL || Text.size()+len <= Max || Max == 0) { - // add new character s = Text.subString(0, CursorPos); - s.append(c); - s.append( Text.subString(CursorPos, Text.size()-CursorPos) ); + s.append(str); + if ( isEOL ) + { + //just keep appending to the current line + //This follows the behavior of other gui libraries behaviors + s.append( Text.subString(EOLPos, Text.size()-EOLPos) ); + } + else + { + //replace the next character + s.append( Text.subString(CursorPos + len,Text.size() - CursorPos - len)); + } Text = s; - ++CursorPos; + CursorPos+=len; } - - BlinkStartTime = os::Timer::getTime(); - setTextMarkers(0, 0); + } + else if (Text.size()+len <= Max || Max == 0) + { + // add new character because we are at the end of the string + s = Text.subString(0, CursorPos); + s.append(str); + s.append( Text.subString(CursorPos+len, Text.size()-CursorPos-len) ); + Text = s; + CursorPos+=len; } } + else if (Text.size()+len <= Max || Max == 0) + { + // add new character + s = Text.subString(0, CursorPos); + s.append(str); + s.append( Text.subString(CursorPos, Text.size()-CursorPos) ); + Text = s; + CursorPos+=len; + } + + BlinkStartTime = os::Timer::getTime(); + setTextMarkers(0, 0); + breakText(); calculateScrollPos(); sendGuiEvent(EGET_EDITBOX_CHANGED); @@ -1625,6 +1644,12 @@ void CGUIEditBox::sendGuiEvent(EGUI_EVENT_TYPE type) } } +//! Returns whether the element takes input from the IME +bool CGUIEditBox::acceptsIME() +{ + return isEnabled(); +} + //! Writes attributes of the element. void CGUIEditBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { diff --git a/source/Irrlicht/CGUIEditBox.h b/source/Irrlicht/CGUIEditBox.h index f251e5e..4943567 100644 --- a/source/Irrlicht/CGUIEditBox.h +++ b/source/Irrlicht/CGUIEditBox.h @@ -139,6 +139,10 @@ namespace gui //! Updates the absolute position, splits text if required virtual void updateAbsolutePosition() _IRR_OVERRIDE_; + //! Returns whether the element takes input from the IME + virtual bool acceptsIME() _IRR_OVERRIDE_; + + //! Writes attributes of the element. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const _IRR_OVERRIDE_; @@ -154,6 +158,8 @@ namespace gui s32 getLineFromPos(s32 pos); //! adds a letter to the edit box void inputChar(wchar_t c); + //! adds a string to the edit box + void inputString(const core::stringw &str); //! calculates the current scroll position void calculateScrollPos(); //! calculated the FrameRect diff --git a/source/Irrlicht/CGUIEnvironment.cpp b/source/Irrlicht/CGUIEnvironment.cpp index e970d64..6a04b1e 100644 --- a/source/Irrlicht/CGUIEnvironment.cpp +++ b/source/Irrlicht/CGUIEnvironment.cpp @@ -656,6 +656,10 @@ bool CGUIEnvironment::postEventFromUser(const SEvent& event) } } break; + case EET_STRING_INPUT_EVENT: + if (Focus && Focus->OnEvent(event)) + return true; + break; default: break; } // end switch diff --git a/source/Irrlicht/CIrrDeviceStub.cpp b/source/Irrlicht/CIrrDeviceStub.cpp index 0ecf128..31e21ab 100644 --- a/source/Irrlicht/CIrrDeviceStub.cpp +++ b/source/Irrlicht/CIrrDeviceStub.cpp @@ -6,6 +6,7 @@ #include "ISceneManager.h" #include "IEventReceiver.h" #include "IFileSystem.h" +#include "IGUIElement.h" #include "IGUIEnvironment.h" #include "os.h" #include "IrrCompileConfig.h" @@ -503,6 +504,14 @@ void CIrrDeviceStub::clearSystemMessages() { } +//! Checks whether the input device should take input from the IME +bool CIrrDeviceStub::acceptsIME() +{ + if (!GUIEnvironment) + return false; + gui::IGUIElement *elem = GUIEnvironment->getFocus(); + return elem && elem->acceptsIME(); +} } // end namespace irr diff --git a/source/Irrlicht/CIrrDeviceStub.h b/source/Irrlicht/CIrrDeviceStub.h index 367faf1..7ea05bc 100644 --- a/source/Irrlicht/CIrrDeviceStub.h +++ b/source/Irrlicht/CIrrDeviceStub.h @@ -194,6 +194,9 @@ namespace irr void calculateGammaRamp ( u16 *ramp, f32 gamma, f32 relativebrightness, f32 relativecontrast ); void calculateGammaFromRamp ( f32 &gamma, const u16 *ramp ); + //! Checks whether the input device should take input from the IME + bool acceptsIME(); + video::IVideoDriver* VideoDriver; gui::IGUIEnvironment* GUIEnvironment; scene::ISceneManager* SceneManager;