Fix Entry bugs handling the text caret

Added more checks and improve performance in Entry::setCaretPos()
This commit is contained in:
David Capello 2016-03-14 12:39:45 -03:00
parent 29f6db6f35
commit 69a1161f69
1 changed files with 30 additions and 27 deletions

View File

@ -1,5 +1,5 @@
// Aseprite UI Library // Aseprite UI Library
// Copyright (C) 2001-2015 David Capello // Copyright (C) 2001-2016 David Capello
// //
// This file is released under the terms of the MIT license. // This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information. // Read LICENSE.txt for more information.
@ -102,29 +102,33 @@ void Entry::hideCaret()
void Entry::setCaretPos(int pos) void Entry::setCaretPos(int pos)
{ {
base::utf8_const_iterator utf8_begin = base::utf8_const_iterator(text().begin()); auto utf8_begin = base::utf8_const_iterator(text().begin());
auto utf8_end = base::utf8_const_iterator(text().end());
int textlen = base::utf8_length(text()); int textlen = base::utf8_length(text());
int x, c;
m_caret = pos; m_caret = MID(0, pos, textlen);
// Backward scroll // Backward scroll
if (m_caret < m_scroll) if (m_scroll > m_caret)
m_scroll = m_caret; m_scroll = m_caret;
// Forward scroll // Forward scroll
m_scroll--; --m_scroll;
do { int c;
x = bounds().x + border().left(); while (true) {
for (c=++m_scroll; ; c++) { c = ++m_scroll;
int ch = (c < textlen ? *(utf8_begin+c) : ' '); auto utf8_it = utf8_begin + MID(0, c, textlen);
int x = bounds().x + border().left()
- font()->charWidth(' '); // Space for the carret
for (; utf8_it != utf8_end; ++c, ++utf8_it) {
int ch = *utf8_it;
x += font()->charWidth(ch); x += font()->charWidth(ch);
if (x >= bounds().x2()-border().right()) if (x >= bounds().x2()-border().right())
break; break;
} }
} while (m_caret >= c); if (m_caret < c || utf8_it == utf8_end)
break;
}
m_timer.start(); m_timer.start();
m_state = true; m_state = true;
@ -322,8 +326,8 @@ bool Entry::onProcessMessage(Message* msg)
case kMouseMoveMessage: case kMouseMoveMessage:
if (hasCapture()) { if (hasCapture()) {
gfx::Point mousePos = static_cast<MouseMessage*>(msg)->position(); gfx::Point mousePos = static_cast<MouseMessage*>(msg)->position();
base::utf8_const_iterator utf8_begin = base::utf8_const_iterator(text().begin()); auto utf8_begin = base::utf8_const_iterator(text().begin());
base::utf8_const_iterator utf8_end = base::utf8_const_iterator(text().end()); auto utf8_end = base::utf8_const_iterator(text().end());
int textlen = base::utf8_length(text()); int textlen = base::utf8_length(text());
int c, x; int c, x;
@ -342,10 +346,12 @@ bool Entry::onProcessMessage(Message* msg)
// Forward scroll // Forward scroll
else if (mousePos.x >= bounds().x2()) { else if (mousePos.x >= bounds().x2()) {
if (m_scroll < textlen - getAvailableTextLength()) { if (m_scroll < textlen - getAvailableTextLength()) {
m_scroll++; ++m_scroll;
x = bounds().x + border().left(); x = bounds().x + border().left();
for (c=m_scroll; utf8_begin != utf8_end; ++c) {
int ch = (c < textlen ? *(utf8_begin+c) : ' '); auto utf8_it = utf8_begin + MID(0, m_scroll, textlen);
for (c=m_scroll; utf8_it != utf8_end; ++c, ++utf8_it) {
int ch = (c < textlen ? *utf8_it: ' ');
x += font()->charWidth(ch); x += font()->charWidth(ch);
if (x > bounds().x2()-border().right()) { if (x > bounds().x2()-border().right()) {
@ -353,7 +359,7 @@ bool Entry::onProcessMessage(Message* msg)
break; break;
} }
} }
m_caret = c; m_caret = MID(0, c, textlen);
move = false; move = false;
is_dirty = true; is_dirty = true;
invalidate(); invalidate();
@ -450,8 +456,9 @@ void Entry::onSetText()
{ {
Widget::onSetText(); Widget::onSetText();
if (m_caret >= 0 && (std::size_t)m_caret > textLength()) int textlen = textLength();
m_caret = (int)textLength(); if (m_caret >= 0 && m_caret > textlen)
m_caret = textlen;
} }
void Entry::onChange() void Entry::onChange()
@ -482,11 +489,7 @@ int Entry::getCaretFromMouse(MouseMessage* mousemsg)
int x = bounds.x; int x = bounds.x;
base::utf8_const_iterator utf8_it = auto utf8_it = utf8_begin + MID(0, m_scroll, textlen);
(m_scroll < textlen ?
utf8_begin + m_scroll:
utf8_end);
int c = m_scroll; int c = m_scroll;
for (; utf8_it != utf8_end; ++c, ++utf8_it) { for (; utf8_it != utf8_end; ++c, ++utf8_it) {
int w = font()->charWidth(*utf8_it); int w = font()->charWidth(*utf8_it);
@ -505,7 +508,7 @@ int Entry::getCaretFromMouse(MouseMessage* mousemsg)
} }
} }
return caret; return MID(0, caret, textlen);
} }
void Entry::executeCmd(EntryCmd cmd, int unicodeChar, bool shift_pressed) void Entry::executeCmd(EntryCmd cmd, int unicodeChar, bool shift_pressed)