improve cursor move keys support in text editor refs refs #1

This commit is contained in:
beru
2015-05-05 14:13:16 +09:00
parent e7c9708b4f
commit 2da65827a0
5 changed files with 173 additions and 12 deletions

View File

@@ -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);