forked from OSchip/llvm-project
[LLDB][GUI] Add extra keys to text field
This patch adds many new keys to the text field and implements new behaviors as follows: ``` case KEY_HOME: case KEY_CTRL_A: MoveCursorToStart(); case KEY_END: case KEY_CTRL_E: MoveCursorToEnd(); case KEY_RIGHT: case KEY_SF: MoveCursorRight(); case KEY_LEFT: case KEY_SR: MoveCursorLeft(); case KEY_BACKSPACE: case KEY_DELETE: RemovePreviousChar(); case KEY_DC: RemoveNextChar(); case KEY_EOL: case KEY_CTRL_K: ClearToEnd(); case KEY_DL: case KEY_CLEAR: Clear(); ``` This patch also refactors scrolling to be dynamic at draw time for easier handing. Differential Revision: https://reviews.llvm.org/D108385
This commit is contained in:
parent
c728bd5bba
commit
d95d2a8e4a
|
@ -85,8 +85,12 @@ using llvm::StringRef;
|
||||||
// we may want curses to be disabled for some builds for instance, windows
|
// we may want curses to be disabled for some builds for instance, windows
|
||||||
#if LLDB_ENABLE_CURSES
|
#if LLDB_ENABLE_CURSES
|
||||||
|
|
||||||
|
#define KEY_CTRL_A 1
|
||||||
|
#define KEY_CTRL_E 5
|
||||||
|
#define KEY_CTRL_K 11
|
||||||
#define KEY_RETURN 10
|
#define KEY_RETURN 10
|
||||||
#define KEY_ESCAPE 27
|
#define KEY_ESCAPE 27
|
||||||
|
#define KEY_DELETE 127
|
||||||
|
|
||||||
#define KEY_SHIFT_TAB (KEY_MAX + 1)
|
#define KEY_SHIFT_TAB (KEY_MAX + 1)
|
||||||
|
|
||||||
|
@ -1106,10 +1110,11 @@ public:
|
||||||
int GetContentLength() { return m_content.length(); }
|
int GetContentLength() { return m_content.length(); }
|
||||||
|
|
||||||
void DrawContent(Surface &surface, bool is_selected) {
|
void DrawContent(Surface &surface, bool is_selected) {
|
||||||
|
UpdateScrolling(surface.GetWidth());
|
||||||
|
|
||||||
surface.MoveCursor(0, 0);
|
surface.MoveCursor(0, 0);
|
||||||
const char *text = m_content.c_str() + m_first_visibile_char;
|
const char *text = m_content.c_str() + m_first_visibile_char;
|
||||||
surface.PutCString(text, surface.GetWidth());
|
surface.PutCString(text, surface.GetWidth());
|
||||||
m_last_drawn_content_width = surface.GetWidth();
|
|
||||||
|
|
||||||
// Highlight the cursor.
|
// Highlight the cursor.
|
||||||
surface.MoveCursor(GetCursorXPosition(), 0);
|
surface.MoveCursor(GetCursorXPosition(), 0);
|
||||||
|
@ -1156,6 +1161,22 @@ public:
|
||||||
DrawError(error_surface);
|
DrawError(error_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the position of the last visible character.
|
||||||
|
int GetLastVisibleCharPosition(int width) {
|
||||||
|
int position = m_first_visibile_char + width - 1;
|
||||||
|
return std::min(position, GetContentLength());
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateScrolling(int width) {
|
||||||
|
if (m_cursor_position < m_first_visibile_char) {
|
||||||
|
m_first_visibile_char = m_cursor_position;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_cursor_position > GetLastVisibleCharPosition(width))
|
||||||
|
m_first_visibile_char = m_cursor_position - (width - 1);
|
||||||
|
}
|
||||||
|
|
||||||
// The cursor is allowed to move one character past the string.
|
// The cursor is allowed to move one character past the string.
|
||||||
// m_cursor_position is in range [0, GetContentLength()].
|
// m_cursor_position is in range [0, GetContentLength()].
|
||||||
void MoveCursorRight() {
|
void MoveCursorRight() {
|
||||||
|
@ -1168,42 +1189,54 @@ public:
|
||||||
m_cursor_position--;
|
m_cursor_position--;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the cursor moved past the last visible character, scroll right by one
|
void MoveCursorToStart() { m_cursor_position = 0; }
|
||||||
// character.
|
|
||||||
void ScrollRightIfNeeded() {
|
void MoveCursorToEnd() { m_cursor_position = GetContentLength(); }
|
||||||
if (m_cursor_position - m_first_visibile_char == m_last_drawn_content_width)
|
|
||||||
m_first_visibile_char++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScrollLeft() {
|
void ScrollLeft() {
|
||||||
if (m_first_visibile_char > 0)
|
if (m_first_visibile_char > 0)
|
||||||
m_first_visibile_char--;
|
m_first_visibile_char--;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the cursor moved past the first visible character, scroll left by one
|
// Insert a character at the current cursor position and advance the cursor
|
||||||
// character.
|
// position.
|
||||||
void ScrollLeftIfNeeded() {
|
|
||||||
if (m_cursor_position < m_first_visibile_char)
|
|
||||||
m_first_visibile_char--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert a character at the current cursor position, advance the cursor
|
|
||||||
// position, and make sure to scroll right if needed.
|
|
||||||
void InsertChar(char character) {
|
void InsertChar(char character) {
|
||||||
m_content.insert(m_cursor_position, 1, character);
|
m_content.insert(m_cursor_position, 1, character);
|
||||||
m_cursor_position++;
|
m_cursor_position++;
|
||||||
ScrollRightIfNeeded();
|
ClearError();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the character before the cursor position, retreat the cursor
|
// Remove the character before the cursor position, retreat the cursor
|
||||||
// position, and make sure to scroll left if needed.
|
// position, and scroll left.
|
||||||
void RemoveChar() {
|
void RemovePreviousChar() {
|
||||||
if (m_cursor_position == 0)
|
if (m_cursor_position == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_content.erase(m_cursor_position - 1, 1);
|
m_content.erase(m_cursor_position - 1, 1);
|
||||||
m_cursor_position--;
|
m_cursor_position--;
|
||||||
ScrollLeft();
|
ScrollLeft();
|
||||||
|
ClearError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the character after the cursor position.
|
||||||
|
void RemoveNextChar() {
|
||||||
|
if (m_cursor_position == GetContentLength())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_content.erase(m_cursor_position, 1);
|
||||||
|
ClearError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear characters from the current cursor position to the end.
|
||||||
|
void ClearToEnd() {
|
||||||
|
m_content.erase(m_cursor_position);
|
||||||
|
ClearError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear() {
|
||||||
|
m_content.clear();
|
||||||
|
m_cursor_position = 0;
|
||||||
|
ClearError();
|
||||||
}
|
}
|
||||||
|
|
||||||
// True if the key represents a char that can be inserted in the field
|
// True if the key represents a char that can be inserted in the field
|
||||||
|
@ -1224,17 +1257,36 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
|
case KEY_HOME:
|
||||||
|
case KEY_CTRL_A:
|
||||||
|
MoveCursorToStart();
|
||||||
|
return eKeyHandled;
|
||||||
|
case KEY_END:
|
||||||
|
case KEY_CTRL_E:
|
||||||
|
MoveCursorToEnd();
|
||||||
|
return eKeyHandled;
|
||||||
case KEY_RIGHT:
|
case KEY_RIGHT:
|
||||||
|
case KEY_SF:
|
||||||
MoveCursorRight();
|
MoveCursorRight();
|
||||||
ScrollRightIfNeeded();
|
|
||||||
return eKeyHandled;
|
return eKeyHandled;
|
||||||
case KEY_LEFT:
|
case KEY_LEFT:
|
||||||
|
case KEY_SR:
|
||||||
MoveCursorLeft();
|
MoveCursorLeft();
|
||||||
ScrollLeftIfNeeded();
|
|
||||||
return eKeyHandled;
|
return eKeyHandled;
|
||||||
case KEY_BACKSPACE:
|
case KEY_BACKSPACE:
|
||||||
ClearError();
|
case KEY_DELETE:
|
||||||
RemoveChar();
|
RemovePreviousChar();
|
||||||
|
return eKeyHandled;
|
||||||
|
case KEY_DC:
|
||||||
|
RemoveNextChar();
|
||||||
|
return eKeyHandled;
|
||||||
|
case KEY_EOL:
|
||||||
|
case KEY_CTRL_K:
|
||||||
|
ClearToEnd();
|
||||||
|
return eKeyHandled;
|
||||||
|
case KEY_DL:
|
||||||
|
case KEY_CLEAR:
|
||||||
|
Clear();
|
||||||
return eKeyHandled;
|
return eKeyHandled;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -1277,9 +1329,6 @@ protected:
|
||||||
int m_cursor_position;
|
int m_cursor_position;
|
||||||
// The index of the first visible character in the content.
|
// The index of the first visible character in the content.
|
||||||
int m_first_visibile_char;
|
int m_first_visibile_char;
|
||||||
// The width of the fields content that was last drawn. Width can change, so
|
|
||||||
// this is used to determine if scrolling is needed dynamically.
|
|
||||||
int m_last_drawn_content_width;
|
|
||||||
// Optional error message. If empty, field is considered to have no error.
|
// Optional error message. If empty, field is considered to have no error.
|
||||||
std::string m_error;
|
std::string m_error;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue