Support for Page Up/Down

(changes from ocornut/imgui/commit/ec945f44)
This commit is contained in:
Louis Schnellbach 2020-11-19 15:59:51 +01:00 committed by Fabian Giesen
parent 76a0a00874
commit 85bc8060be

View File

@ -142,6 +142,8 @@
// STB_TEXTEDIT_K_RIGHT keyboard input to move cursor right // STB_TEXTEDIT_K_RIGHT keyboard input to move cursor right
// STB_TEXTEDIT_K_UP keyboard input to move cursor up // STB_TEXTEDIT_K_UP keyboard input to move cursor up
// STB_TEXTEDIT_K_DOWN keyboard input to move cursor down // STB_TEXTEDIT_K_DOWN keyboard input to move cursor down
// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page
// STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page
// STB_TEXTEDIT_K_LINESTART keyboard input to move cursor to start of line // e.g. HOME // STB_TEXTEDIT_K_LINESTART keyboard input to move cursor to start of line // e.g. HOME
// STB_TEXTEDIT_K_LINEEND keyboard input to move cursor to end of line // e.g. END // STB_TEXTEDIT_K_LINEEND keyboard input to move cursor to end of line // e.g. END
// STB_TEXTEDIT_K_TEXTSTART keyboard input to move cursor to start of text // e.g. ctrl-HOME // STB_TEXTEDIT_K_TEXTSTART keyboard input to move cursor to start of text // e.g. ctrl-HOME
@ -164,10 +166,6 @@
// STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text // STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text
// STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text // STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text
// //
// Todo:
// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page
// STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page
//
// Keyboard input must be encoded as a single integer value; e.g. a character code // Keyboard input must be encoded as a single integer value; e.g. a character code
// and some bitflags that represent shift states. to simplify the interface, SHIFT must // and some bitflags that represent shift states. to simplify the interface, SHIFT must
// be a bitflag, so we can test the shifted state of cursor movements to allow selection, // be a bitflag, so we can test the shifted state of cursor movements to allow selection,
@ -331,6 +329,10 @@ typedef struct
// each textfield keeps its own insert mode state. to keep an app-wide // each textfield keeps its own insert mode state. to keep an app-wide
// insert mode, copy this value in/out of the app state // insert mode, copy this value in/out of the app state
int row_count_per_page;
// page size in number of row.
// this value MUST be set to >0 for pageup or pagedown in multilines documents.
///////////////////// /////////////////////
// //
// private data // private data
@ -849,12 +851,16 @@ retry:
break; break;
case STB_TEXTEDIT_K_DOWN: case STB_TEXTEDIT_K_DOWN:
case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT: { case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT:
case STB_TEXTEDIT_K_PGDOWN:
case STB_TEXTEDIT_K_PGDOWN | STB_TEXTEDIT_K_SHIFT: {
StbFindState find; StbFindState find;
StbTexteditRow row; StbTexteditRow row;
int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; int i, j, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGDOWN;
int row_count = is_page ? state->row_count_per_page : 1;
if (state->single_line) { if (!is_page && state->single_line) {
// on windows, up&down in single-line behave like left&right // on windows, up&down in single-line behave like left&right
key = STB_TEXTEDIT_K_RIGHT | (key & STB_TEXTEDIT_K_SHIFT); key = STB_TEXTEDIT_K_RIGHT | (key & STB_TEXTEDIT_K_SHIFT);
goto retry; goto retry;
@ -863,17 +869,20 @@ retry:
if (sel) if (sel)
stb_textedit_prep_selection_at_cursor(state); stb_textedit_prep_selection_at_cursor(state);
else if (STB_TEXT_HAS_SELECTION(state)) else if (STB_TEXT_HAS_SELECTION(state))
stb_textedit_move_to_last(str,state); stb_textedit_move_to_last(str, state);
// compute current position of cursor point // compute current position of cursor point
stb_textedit_clamp(str, state); stb_textedit_clamp(str, state);
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
// now find character position down a row for (j = 0; j < row_count; ++j) {
if (find.length) { float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x;
float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
float x;
int start = find.first_char + find.length; int start = find.first_char + find.length;
if (find.length == 0)
break;
// now find character position down a row
state->cursor = start; state->cursor = start;
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor); STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
x = row.x0; x = row.x0;
@ -895,17 +904,25 @@ retry:
if (sel) if (sel)
state->select_end = state->cursor; state->select_end = state->cursor;
// go to next line
find.first_char = find.first_char + find.length;
find.length = row.num_chars;
} }
break; break;
} }
case STB_TEXTEDIT_K_UP: case STB_TEXTEDIT_K_UP:
case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: { case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT:
case STB_TEXTEDIT_K_PGUP:
case STB_TEXTEDIT_K_PGUP | STB_TEXTEDIT_K_SHIFT: {
StbFindState find; StbFindState find;
StbTexteditRow row; StbTexteditRow row;
int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; int i, j, prev_scan, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGUP;
int row_count = is_page ? state->row_count_per_page : 1;
if (state->single_line) { if (!is_page && state->single_line) {
// on windows, up&down become left&right // on windows, up&down become left&right
key = STB_TEXTEDIT_K_LEFT | (key & STB_TEXTEDIT_K_SHIFT); key = STB_TEXTEDIT_K_LEFT | (key & STB_TEXTEDIT_K_SHIFT);
goto retry; goto retry;
@ -920,11 +937,14 @@ retry:
stb_textedit_clamp(str, state); stb_textedit_clamp(str, state);
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
// can only go up if there's a previous row for (j = 0; j < row_count; ++j) {
if (find.prev_first != find.first_char) { float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x;
// can only go up if there's a previous row
if (find.prev_first == find.first_char)
break;
// now find character position up a row // now find character position up a row
float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
float x;
state->cursor = find.prev_first; state->cursor = find.prev_first;
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor); STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
x = row.x0; x = row.x0;
@ -946,6 +966,14 @@ retry:
if (sel) if (sel)
state->select_end = state->cursor; state->select_end = state->cursor;
// go to previous line
// (we need to scan previous line the hard way. maybe we could expose this as a new API function?)
prev_scan = find.prev_first > 0 ? find.prev_first - 1 : 0;
while (prev_scan > 0 && STB_TEXTEDIT_GETCHAR(str, prev_scan - 1) != STB_TEXTEDIT_NEWLINE)
--prev_scan;
find.first_char = find.prev_first;
find.prev_first = prev_scan;
} }
break; break;
} }
@ -1069,10 +1097,6 @@ retry:
state->has_preferred_x = 0; state->has_preferred_x = 0;
break; break;
} }
// @TODO:
// STB_TEXTEDIT_K_PGUP - move cursor up a page
// STB_TEXTEDIT_K_PGDOWN - move cursor down a page
} }
} }
@ -1337,6 +1361,7 @@ static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_lin
state->initialized = 1; state->initialized = 1;
state->single_line = (unsigned char) is_single_line; state->single_line = (unsigned char) is_single_line;
state->insert_mode = 0; state->insert_mode = 0;
state->row_count_per_page = 0;
} }
// API initialize // API initialize