diff --git a/specter/include/Specter/DeferredWindowEvents.hpp b/specter/include/Specter/DeferredWindowEvents.hpp index 83baf910c..8237ab890 100644 --- a/specter/include/Specter/DeferredWindowEvents.hpp +++ b/specter/include/Specter/DeferredWindowEvents.hpp @@ -50,7 +50,8 @@ struct DeferredWindowEvents : public boo::IWindowCallback SpecialKeyDown, SpecialKeyUp, ModKeyDown, - ModKeyUp + ModKeyUp, + UTF8FragmentDown } m_type; boo::SWindowCoord m_coord; @@ -62,6 +63,7 @@ struct DeferredWindowEvents : public boo::IWindowCallback unsigned long m_charcode; boo::ESpecialKey m_special; bool m_isRepeat; + std::string m_fragment; void dispatch(Receiver& rec) const { @@ -112,6 +114,9 @@ struct DeferredWindowEvents : public boo::IWindowCallback case Type::ModKeyUp: rec.modKeyUp(m_mods); break; + case Type::UTF8FragmentDown: + rec.utf8FragmentDown(m_fragment); + break; default: break; } } @@ -240,6 +245,13 @@ struct DeferredWindowEvents : public boo::IWindowCallback m_cmds.back().m_mods = mod; } + void utf8FragmentDown(const std::string& str) + { + std::unique_lock lk(m_mt); + m_cmds.emplace_back(Command::Type::UTF8FragmentDown); + m_cmds.back().m_fragment = str; + } + void dispatchEvents() { std::unique_lock lk(m_mt); diff --git a/specter/include/Specter/RootView.hpp b/specter/include/Specter/RootView.hpp index db52de261..3e04fc226 100644 --- a/specter/include/Specter/RootView.hpp +++ b/specter/include/Specter/RootView.hpp @@ -56,6 +56,7 @@ public: void specialKeyUp(boo::ESpecialKey key, boo::EModifierKey mods); void modKeyDown(boo::EModifierKey mod, bool isRepeat); void modKeyUp(boo::EModifierKey mod); + void utf8FragmentDown(const std::string& str); void dispatchEvents() {m_events.dispatchEvents();} void draw(boo::IGraphicsCommandQueue* gfxQ); @@ -73,10 +74,7 @@ public: m_activeTextView->setActive(false); m_activeTextView = textView; if (textView) - { textView->setActive(true); - m_window->claimKeyboardFocus(); - } } void setActiveDragView(View* dragView) { diff --git a/specter/include/Specter/TextField.hpp b/specter/include/Specter/TextField.hpp index 907e47eba..b2ecb0ee5 100644 --- a/specter/include/Specter/TextField.hpp +++ b/specter/include/Specter/TextField.hpp @@ -52,6 +52,7 @@ public: void mouseLeave(const boo::SWindowCoord&); void charKeyDown(unsigned long, boo::EModifierKey, bool); void specialKeyDown(boo::ESpecialKey, boo::EModifierKey, bool); + void utf8FragmentDown(const std::string&); void think(); void resized(const boo::SWindowRect& rootView, const boo::SWindowRect& sub); void draw(boo::IGraphicsCommandQueue* gfxQ); diff --git a/specter/include/Specter/View.hpp b/specter/include/Specter/View.hpp index 9f0e33e2a..76e1610c1 100644 --- a/specter/include/Specter/View.hpp +++ b/specter/include/Specter/View.hpp @@ -203,6 +203,7 @@ public: virtual void specialKeyUp(boo::ESpecialKey, boo::EModifierKey) {} virtual void modKeyDown(boo::EModifierKey, bool) {} virtual void modKeyUp(boo::EModifierKey) {} + virtual void utf8FragmentDown(const std::string&) {} virtual void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); virtual void think() {} diff --git a/specter/lib/RootView.cpp b/specter/lib/RootView.cpp index de44bc4f8..687acd26f 100644 --- a/specter/lib/RootView.cpp +++ b/specter/lib/RootView.cpp @@ -157,6 +157,12 @@ void RootView::modKeyUp(boo::EModifierKey mod) m_activeTextView->modKeyUp(mod); } +void RootView::utf8FragmentDown(const std::string& str) +{ + if (m_activeTextView) + m_activeTextView->utf8FragmentDown(str); +} + View* RootView::setContentView(View* view) { View* ret = m_view; diff --git a/specter/lib/TextField.cpp b/specter/lib/TextField.cpp index 866e20e1c..9ccc320de 100644 --- a/specter/lib/TextField.cpp +++ b/specter/lib/TextField.cpp @@ -94,8 +94,6 @@ void TextField::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton butt if (!m_active) { rootView().setActiveTextView(this); - if (!m_selectionCount) - setSelectionRange(0, m_text->accessGlyphs().size()); } else if (m_clickFrames2 < 15) { @@ -335,6 +333,40 @@ void TextField::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, boo } } +void TextField::utf8FragmentDown(const std::string& str) +{ + if (m_selectionCount) + { + std::string newStr(m_textStr.cbegin(), (UTF8Iterator(m_textStr.cbegin()) + m_selectionStart).iter()); + newStr += str; + UTF8Iterator countIt(newStr.cbegin()); + size_t newSel = 0; + while (countIt.iter() < newStr.cend()) + { + ++newSel; + ++countIt; + } + newStr.append((UTF8Iterator(m_textStr.cbegin()) + m_selectionStart + m_selectionCount).iter(), m_textStr.cend()); + setText(newStr); + setCursorPos(newSel); + } + else + { + std::string newStr(m_textStr.cbegin(), (UTF8Iterator(m_textStr.cbegin()) + m_cursorPos).iter()); + newStr += str; + UTF8Iterator countIt(newStr.cbegin()); + size_t newSel = 0; + while (countIt.iter() < newStr.cend()) + { + ++newSel; + ++countIt; + } + newStr.append((UTF8Iterator(m_textStr.cbegin()) + m_cursorPos).iter(), m_textStr.cend()); + setText(newStr); + setCursorPos(newSel); + } +} + void TextField::think() { ++m_cursorFrames; @@ -346,7 +378,12 @@ void TextField::setActive(bool active) { m_active = active; if (!active) + { clearSelectionRange(); + rootView().window()->claimKeyboardFocus(nullptr); + } + else if (!m_selectionCount) + setSelectionRange(0, m_text->accessGlyphs().size()); } void TextField::setCursorPos(size_t pos) @@ -363,6 +400,9 @@ void TextField::setCursorPos(size_t pos) m_verts[30].m_pos.assign(offset2, 18 * pf, 0); m_verts[31].m_pos.assign(offset2, 4 * pf, 0); m_bVertsBuf->load(m_verts, sizeof(m_verts)); + + int focusRect[2] = {subRect().location[0] + offset1, subRect().location[1]}; + rootView().window()->claimKeyboardFocus(focusRect); } void TextField::setSelectionRange(size_t start, size_t count) @@ -397,6 +437,9 @@ void TextField::setSelectionRange(size_t start, size_t count) m_verts[30].m_pos.assign(offset2, 18 * pf, 0); m_verts[31].m_pos.assign(offset2, 4 * pf, 0); m_bVertsBuf->load(m_verts, sizeof(m_verts)); + + int focusRect[2] = {subRect().location[0] + offset1, subRect().location[1]}; + rootView().window()->claimKeyboardFocus(focusRect); } void TextField::clearSelectionRange() @@ -408,6 +451,9 @@ void TextField::clearSelectionRange() for (size_t i=0 ; iupdateGlyphs(); + + int focusRect[2] = {subRect().location[0], subRect().location[1]}; + rootView().window()->claimKeyboardFocus(focusRect); } void TextField::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)