improve cursor move keys support in text editor refs refs #1
This commit is contained in:
parent
e7c9708b4f
commit
2da65827a0
@ -157,8 +157,8 @@ namespace nana{ namespace widgets
|
|||||||
|
|
||||||
void set_accept(std::function<bool(char_type)>);
|
void set_accept(std::function<bool(char_type)>);
|
||||||
void set_accept(accepts);
|
void set_accept(accepts);
|
||||||
bool respond_char(char_type);
|
bool respond_char(const arg_keyboard& arg);
|
||||||
bool respond_key(char_type);
|
bool respond_key(const arg_keyboard& arg);
|
||||||
|
|
||||||
void typeface_changed();
|
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_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;
|
unsigned _m_pixels_by_char(const nana::string&, std::size_t pos) const;
|
||||||
static bool _m_is_right_text(const unicode_bidi::entity&);
|
static bool _m_is_right_text(const unicode_bidi::entity&);
|
||||||
|
void _handle_move_key(const arg_keyboard& arg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<editor_behavior_interface> behavior_;
|
std::unique_ptr<editor_behavior_interface> behavior_;
|
||||||
undoable<command> undo_;
|
undoable<command> undo_;
|
||||||
|
@ -685,7 +685,7 @@ namespace nana
|
|||||||
{
|
{
|
||||||
case keyboard::os_arrow_left:
|
case keyboard::os_arrow_left:
|
||||||
case keyboard::os_arrow_right:
|
case keyboard::os_arrow_right:
|
||||||
drawer_->editor()->respond_key(arg.key);
|
drawer_->editor()->respond_key(arg);
|
||||||
drawer_->editor()->reset_caret();
|
drawer_->editor()->reset_caret();
|
||||||
break;
|
break;
|
||||||
case keyboard::os_arrow_up:
|
case keyboard::os_arrow_up:
|
||||||
@ -714,14 +714,14 @@ namespace nana
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (call_other_keys)
|
if (call_other_keys)
|
||||||
drawer_->editor()->respond_key(arg.key);
|
drawer_->editor()->respond_key(arg);
|
||||||
|
|
||||||
API::lazy_refresh();
|
API::lazy_refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
void trigger::key_char(graph_reference graph, const arg_keyboard& arg)
|
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();
|
API::lazy_refresh();
|
||||||
}
|
}
|
||||||
//end class trigger
|
//end class trigger
|
||||||
|
@ -461,6 +461,7 @@ namespace nana{ namespace widgets
|
|||||||
editor_._m_scrollbar();
|
editor_._m_scrollbar();
|
||||||
return (adjusted_cond || adjusted_cond2);
|
return (adjusted_cond || adjusted_cond2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::size_t _m_textline_from_screen(int y) const
|
std::size_t _m_textline_from_screen(int y) const
|
||||||
{
|
{
|
||||||
@ -1349,8 +1350,9 @@ namespace nana{ namespace widgets
|
|||||||
attributes_.acceptive = acceptive;
|
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)
|
switch (key)
|
||||||
{
|
{
|
||||||
case keyboard::end_of_text:
|
case keyboard::end_of_text:
|
||||||
@ -1400,14 +1402,28 @@ namespace nana{ namespace widgets
|
|||||||
return false;
|
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)
|
switch (key)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
case keyboard::os_arrow_left: move_left(); break;
|
case keyboard::os_arrow_left: move_left(); break;
|
||||||
case keyboard::os_arrow_right: move_right(); break;
|
case keyboard::os_arrow_right: move_right(); break;
|
||||||
case keyboard::os_arrow_up: move_ns(true); break;
|
case keyboard::os_arrow_up: move_ns(true); break;
|
||||||
case keyboard::os_arrow_down: move_ns(false); 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:
|
case keyboard::os_del:
|
||||||
if (this->attr().editable)
|
if (this->attr().editable)
|
||||||
del();
|
del();
|
||||||
@ -2217,6 +2233,149 @@ namespace nana{ namespace widgets
|
|||||||
points_.xpos = points_.caret.x;
|
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
|
nana::upoint text_editor::mouse_caret(const point& scrpos) //From screen position
|
||||||
{
|
{
|
||||||
points_.caret = behavior_->screen_to_caret(scrpos);
|
points_.caret = behavior_->screen_to_caret(scrpos);
|
||||||
|
@ -560,7 +560,7 @@ namespace nana
|
|||||||
|
|
||||||
void drawer::key_press(graph_reference, const arg_keyboard& arg)
|
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_->editor()->reset_caret();
|
||||||
impl_->draw_spins();
|
impl_->draw_spins();
|
||||||
@ -570,7 +570,7 @@ namespace nana
|
|||||||
|
|
||||||
void drawer::key_char(graph_reference, const arg_keyboard& arg)
|
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()))
|
if (!impl_->value(impl_->editor()->text()))
|
||||||
impl_->draw_spins();
|
impl_->draw_spins();
|
||||||
|
@ -136,7 +136,7 @@ namespace drawerbase {
|
|||||||
|
|
||||||
void drawer::key_press(graph_reference, const arg_keyboard& arg)
|
void drawer::key_press(graph_reference, const arg_keyboard& arg)
|
||||||
{
|
{
|
||||||
if(editor_->respond_key(arg.key))
|
if(editor_->respond_key(arg))
|
||||||
{
|
{
|
||||||
editor_->reset_caret();
|
editor_->reset_caret();
|
||||||
API::lazy_refresh();
|
API::lazy_refresh();
|
||||||
@ -145,7 +145,7 @@ namespace drawerbase {
|
|||||||
|
|
||||||
void drawer::key_char(graph_reference, const arg_keyboard& arg)
|
void drawer::key_char(graph_reference, const arg_keyboard& arg)
|
||||||
{
|
{
|
||||||
if (editor_->respond_char(arg.key))
|
if (editor_->respond_char(arg))
|
||||||
API::lazy_refresh();
|
API::lazy_refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user