diff --git a/include/nana/gui/widgets/skeletons/text_editor.hpp b/include/nana/gui/widgets/skeletons/text_editor.hpp index 976c168d..952d6ba2 100644 --- a/include/nana/gui/widgets/skeletons/text_editor.hpp +++ b/include/nana/gui/widgets/skeletons/text_editor.hpp @@ -157,8 +157,8 @@ namespace nana{ namespace widgets void set_accept(std::function); void set_accept(accepts); - bool respond_char(char_type); - bool respond_key(char_type); + bool respond_char(const arg_keyboard& arg); + bool respond_key(const arg_keyboard& arg); void typeface_changed(); @@ -286,6 +286,8 @@ namespace nana{ namespace widgets unsigned _m_char_by_pixels(const nana::char_t*, std::size_t len, unsigned* pxbuf, int str_px, int pixels, bool is_rtl); unsigned _m_pixels_by_char(const nana::string&, std::size_t pos) const; static bool _m_is_right_text(const unicode_bidi::entity&); + void _handle_move_key(const arg_keyboard& arg); + private: std::unique_ptr behavior_; undoable undo_; diff --git a/source/gui/widgets/combox.cpp b/source/gui/widgets/combox.cpp index b1d401f5..24dfd5e1 100644 --- a/source/gui/widgets/combox.cpp +++ b/source/gui/widgets/combox.cpp @@ -685,7 +685,7 @@ namespace nana { case keyboard::os_arrow_left: case keyboard::os_arrow_right: - drawer_->editor()->respond_key(arg.key); + drawer_->editor()->respond_key(arg); drawer_->editor()->reset_caret(); break; case keyboard::os_arrow_up: @@ -714,14 +714,14 @@ namespace nana } } if (call_other_keys) - drawer_->editor()->respond_key(arg.key); + drawer_->editor()->respond_key(arg); API::lazy_refresh(); } void trigger::key_char(graph_reference graph, const arg_keyboard& arg) { - if (drawer_->editor()->respond_char(arg.key)) + if (drawer_->editor()->respond_char(arg)) API::lazy_refresh(); } //end class trigger diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index 0a2f9261..562446b5 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -461,6 +461,7 @@ namespace nana{ namespace widgets editor_._m_scrollbar(); return (adjusted_cond || adjusted_cond2); } + private: std::size_t _m_textline_from_screen(int y) const { @@ -1349,8 +1350,9 @@ namespace nana{ namespace widgets attributes_.acceptive = acceptive; } - bool text_editor::respond_char(char_type key) //key is a character of ASCII code + bool text_editor::respond_char(const arg_keyboard& arg) //key is a character of ASCII code { + char_type key = arg.key; switch (key) { case keyboard::end_of_text: @@ -1400,14 +1402,28 @@ namespace nana{ namespace widgets return false; } - bool text_editor::respond_key(char_type key) + bool text_editor::respond_key(const arg_keyboard& arg) { + char_type key = arg.key; switch (key) - { + { +#if 0 case keyboard::os_arrow_left: move_left(); break; case keyboard::os_arrow_right: move_right(); break; case keyboard::os_arrow_up: move_ns(true); break; case keyboard::os_arrow_down: move_ns(false); break; +#else + case keyboard::os_arrow_left: + case keyboard::os_arrow_right: + case keyboard::os_arrow_up: + case keyboard::os_arrow_down: + case keyboard::os_home: + case keyboard::os_end: + case keyboard::os_pageup: + case keyboard::os_pagedown: + _handle_move_key(arg); + break; +#endif case keyboard::os_del: if (this->attr().editable) del(); @@ -2217,6 +2233,149 @@ namespace nana{ namespace widgets points_.xpos = points_.caret.x; } + void text_editor::_handle_move_key(const arg_keyboard& arg) + { + bool changed = false; + nana::upoint caret = points_.caret; + char_t key = arg.key; + size_t nlines = textbase_.lines(); + if (arg.ctrl) { + switch (key) { + case keyboard::os_arrow_left: + case keyboard::os_arrow_right: + // TODO: move the caret word by word + break; + case keyboard::os_home: + if (caret.y != 0) { + caret.y = 0; + points_.offset.y = 0; + changed = true; + } + break; + case keyboard::os_end: + if (caret.y != nlines - 1) { + caret.y = nlines - 1; + changed = true; + } + break; + } + } + size_t lnsz = textbase_.getline(caret.y).size(); + switch (key) { + case keyboard::os_arrow_left: + if (caret.x != 0) { + --caret.x; + changed = true; + }else { + if (caret.y != 0) { + --caret.y; + caret.x = textbase_.getline(caret.y).size(); + changed = true; + } + } + break; + case keyboard::os_arrow_right: + if (caret.x < lnsz) { + ++caret.x; + changed = true; + }else { + if (caret.y != nlines - 1) { + ++caret.y; + caret.x = 0; + changed = true; + } + } + break; + case keyboard::os_arrow_up: + case keyboard::os_arrow_down: + { + auto screen_pt = behavior_->caret_to_screen(caret); + int offset = line_height(); + if (key == keyboard::os_arrow_up) { + offset = -offset; + } + screen_pt.y += offset; + auto new_caret = behavior_->screen_to_caret(screen_pt); + if (new_caret != caret) { + caret = new_caret; + if (screen_pt.y < 0) { + scroll(true, true); + } + changed = true; + } + } + break; + case keyboard::os_home: + if (caret.x != 0) { + caret.x = 0; + changed = true; + } + break; + case keyboard::os_end: + if (caret.x < lnsz) { + caret.x = lnsz; + changed = true; + } + break; + case keyboard::os_pageup: + if (caret.y >= (int)screen_lines() && points_.offset.y >= (int)screen_lines()) { + points_.offset.y -= screen_lines(); + caret.y -= screen_lines(); + changed = true; + } + break; + case keyboard::os_pagedown: + if (caret.y + screen_lines() <= behavior_->take_lines()) { + points_.offset.y += screen_lines(); + caret.y += screen_lines(); + changed = true; + } + break; + } + if (select_.a != caret || select_.b != caret) { + changed = true; + } + if (changed) { + if (arg.shift) { + switch (key) { + case keyboard::os_arrow_left: + case keyboard::os_arrow_up: + case keyboard::os_home: + case keyboard::os_pageup: + if (points_.caret == select_.b) { + select_.b = select_.a; + }else { + select_.b = std::max(select_.b, points_.caret); + } + select_.a = caret; + break; + case keyboard::os_arrow_right: + case keyboard::os_arrow_down: + case keyboard::os_end: + case keyboard::os_pagedown: + if (select_.b == points_.caret) { + select_.a = std::min(select_.a, points_.caret); + }else { + select_.a = std::max(select_.b, points_.caret); + } + select_.b = caret; + break; + } + }else { + select_.b = caret; + select_.a = caret; + } + if (select_.a > select_.b) { + std::swap(select_.a, select_.b); + } + points_.caret = caret; + behavior_->adjust_caret_into_screen(); + render(true); + _m_scrollbar(); + points_.xpos = points_.caret.x; + } + } + nana::upoint text_editor::mouse_caret(const point& scrpos) //From screen position { points_.caret = behavior_->screen_to_caret(scrpos); diff --git a/source/gui/widgets/spinbox.cpp b/source/gui/widgets/spinbox.cpp index 6be8deb2..c5830b1f 100644 --- a/source/gui/widgets/spinbox.cpp +++ b/source/gui/widgets/spinbox.cpp @@ -560,7 +560,7 @@ namespace nana void drawer::key_press(graph_reference, const arg_keyboard& arg) { - if (impl_->editor()->respond_key(arg.key)) + if (impl_->editor()->respond_key(arg)) { impl_->editor()->reset_caret(); impl_->draw_spins(); @@ -570,7 +570,7 @@ namespace nana void drawer::key_char(graph_reference, const arg_keyboard& arg) { - if (impl_->editor()->respond_char(arg.key)) + if (impl_->editor()->respond_char(arg)) { if (!impl_->value(impl_->editor()->text())) impl_->draw_spins(); diff --git a/source/gui/widgets/textbox.cpp b/source/gui/widgets/textbox.cpp index 4bb6a670..fd2d9c86 100644 --- a/source/gui/widgets/textbox.cpp +++ b/source/gui/widgets/textbox.cpp @@ -136,7 +136,7 @@ namespace drawerbase { void drawer::key_press(graph_reference, const arg_keyboard& arg) { - if(editor_->respond_key(arg.key)) + if(editor_->respond_key(arg)) { editor_->reset_caret(); API::lazy_refresh(); @@ -145,7 +145,7 @@ namespace drawerbase { void drawer::key_char(graph_reference, const arg_keyboard& arg) { - if (editor_->respond_char(arg.key)) + if (editor_->respond_char(arg)) API::lazy_refresh(); }