.
This commit is contained in:
parent
4117b3daaf
commit
6a381b539c
@ -21,11 +21,12 @@ int fullscreen_window::ncurses_streambuf::overflow(int c) {
|
||||
}
|
||||
|
||||
fullscreen_window::fullscreen_window(std::string title) {
|
||||
// Initialize ncurses
|
||||
initscr();
|
||||
cbreak();
|
||||
raw(); // Use raw mode for better control
|
||||
noecho();
|
||||
keypad(stdscr, TRUE);
|
||||
curs_set(0);
|
||||
keypad(stdscr, TRUE); // Enable keypad
|
||||
curs_set(0); // Hide cursor
|
||||
refresh();
|
||||
|
||||
// Create display window (takes up all but bottom 4 lines)
|
||||
@ -33,11 +34,13 @@ fullscreen_window::fullscreen_window(std::string title) {
|
||||
getmaxyx(stdscr, max_y, max_x);
|
||||
display_win = newwin(max_y - 4, max_x, 0, 0);
|
||||
scrollok(display_win, TRUE);
|
||||
keypad(display_win, TRUE); // Enable keypad for display window
|
||||
wrefresh(display_win);
|
||||
|
||||
// Create input window (bottom 4 lines)
|
||||
input_win = newwin(4, max_x, max_y - 4, 0);
|
||||
box(input_win, 0, 0);
|
||||
keypad(input_win, TRUE); // Enable keypad for input window
|
||||
wrefresh(input_win);
|
||||
|
||||
// Set up output redirection
|
||||
@ -138,6 +141,9 @@ std::string fullscreen_window::set_input_multiple_choice(std::string prompt, std
|
||||
std::string filter = "";
|
||||
auto last_key_time = std::chrono::steady_clock::now();
|
||||
int scroll_offset = 0;
|
||||
std::vector<std::string> last_filtered_choices;
|
||||
int last_selected = -1;
|
||||
int last_scroll_offset = -1;
|
||||
|
||||
while (true) {
|
||||
// Filter choices based on input
|
||||
@ -153,12 +159,6 @@ std::string fullscreen_window::set_input_multiple_choice(std::string prompt, std
|
||||
filter = "";
|
||||
}
|
||||
|
||||
// Calculate total width needed
|
||||
int total_width = 0;
|
||||
for (const auto& choice : filtered_choices) {
|
||||
total_width += choice.length() + 3; // +3 for " | " separator
|
||||
}
|
||||
|
||||
// Get window dimensions
|
||||
int max_y, max_x;
|
||||
getmaxyx(input_win, max_y, max_x);
|
||||
@ -179,76 +179,104 @@ std::string fullscreen_window::set_input_multiple_choice(std::string prompt, std
|
||||
}
|
||||
}
|
||||
|
||||
// Display filtered choices horizontally
|
||||
int x = 2 - scroll_offset;
|
||||
for (size_t i = 0; i < filtered_choices.size(); i++) {
|
||||
if (i == selected) {
|
||||
wattron(input_win, A_REVERSE);
|
||||
}
|
||||
// Only redraw if something changed
|
||||
if (filtered_choices != last_filtered_choices ||
|
||||
selected != last_selected ||
|
||||
scroll_offset != last_scroll_offset) {
|
||||
|
||||
// Only draw if visible
|
||||
if (x + filtered_choices[i].length() > 0 && x < max_x - 2) {
|
||||
mvwprintw(input_win, 2, x, "%s", filtered_choices[i].c_str());
|
||||
}
|
||||
// Clear the input window except for the prompt
|
||||
werase(input_win);
|
||||
box(input_win, 0, 0);
|
||||
mvwprintw(input_win, 1, 2, "%s", prompt.c_str());
|
||||
|
||||
if (i == selected) {
|
||||
wattroff(input_win, A_REVERSE);
|
||||
}
|
||||
|
||||
x += filtered_choices[i].length() + 3; // +3 for " | " separator
|
||||
|
||||
// Draw separator if not last item
|
||||
if (i < filtered_choices.size() - 1) {
|
||||
if (x - 3 + 3 > 0 && x - 3 < max_x - 2) {
|
||||
mvwprintw(input_win, 2, x - 3, " | ");
|
||||
// Display filtered choices horizontally
|
||||
int x = 2 - scroll_offset;
|
||||
for (size_t i = 0; i < filtered_choices.size(); i++) {
|
||||
if (i == selected) {
|
||||
wattron(input_win, A_REVERSE);
|
||||
}
|
||||
|
||||
// Only draw if visible
|
||||
if (x + filtered_choices[i].length() > 0 && x < max_x - 2) {
|
||||
mvwprintw(input_win, 2, x, "%s", filtered_choices[i].c_str());
|
||||
}
|
||||
|
||||
if (i == selected) {
|
||||
wattroff(input_win, A_REVERSE);
|
||||
}
|
||||
|
||||
x += filtered_choices[i].length() + 3; // +3 for " | " separator
|
||||
|
||||
// Draw separator if not last item
|
||||
if (i < filtered_choices.size() - 1) {
|
||||
if (x - 3 + 3 > 0 && x - 3 < max_x - 2) {
|
||||
mvwprintw(input_win, 2, x - 3, " | ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wrefresh(input_win);
|
||||
|
||||
// Update last state
|
||||
last_filtered_choices = filtered_choices;
|
||||
last_selected = selected;
|
||||
last_scroll_offset = scroll_offset;
|
||||
}
|
||||
|
||||
wrefresh(input_win);
|
||||
|
||||
int ch = wgetch(input_win);
|
||||
|
||||
// Handle key input
|
||||
if (ch == '\n') {
|
||||
if (!filtered_choices.empty()) {
|
||||
return filtered_choices[selected];
|
||||
}
|
||||
} else if (ch == 27) { // ESC key
|
||||
if (!filter.empty()) {
|
||||
// Clear the filter and reset selection
|
||||
filter = "";
|
||||
selected = 0;
|
||||
scroll_offset = 0;
|
||||
} else {
|
||||
// Only return if filter is already empty
|
||||
return "";
|
||||
}
|
||||
} else if (ch == KEY_LEFT || ch == KEY_UP) {
|
||||
if (selected > 0) {
|
||||
selected--;
|
||||
} else {
|
||||
selected = filtered_choices.size() - 1; // Wrap to end
|
||||
}
|
||||
continue; // Skip the rest of the loop
|
||||
} else if (ch == KEY_RIGHT || ch == KEY_DOWN) {
|
||||
if (selected < filtered_choices.size() - 1) {
|
||||
selected++;
|
||||
} else {
|
||||
selected = 0; // Wrap to beginning
|
||||
}
|
||||
continue; // Skip the rest of the loop
|
||||
} else if (isprint(ch)) {
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - last_key_time).count();
|
||||
|
||||
if (elapsed > 500) { // Reset filter if too much time has passed
|
||||
filter = "";
|
||||
}
|
||||
|
||||
filter += ch;
|
||||
selected = 0;
|
||||
last_key_time = now;
|
||||
switch (ch) {
|
||||
case '\n':
|
||||
if (!filtered_choices.empty()) {
|
||||
return filtered_choices[selected];
|
||||
}
|
||||
break;
|
||||
|
||||
case 27: // ESC key
|
||||
if (!filter.empty()) {
|
||||
// Clear the filter and reset selection
|
||||
filter = "";
|
||||
selected = 0;
|
||||
scroll_offset = 0;
|
||||
} else {
|
||||
// Only return if filter is already empty
|
||||
return "";
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY_LEFT:
|
||||
case KEY_UP:
|
||||
if (selected > 0) {
|
||||
selected--;
|
||||
} else {
|
||||
selected = filtered_choices.size() - 1; // Wrap to end
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY_RIGHT:
|
||||
case KEY_DOWN:
|
||||
if (selected < filtered_choices.size() - 1) {
|
||||
selected++;
|
||||
} else {
|
||||
selected = 0; // Wrap to beginning
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isalnum(ch)) {
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - last_key_time).count();
|
||||
|
||||
if (elapsed > 500) { // Reset filter if too much time has passed
|
||||
filter = "";
|
||||
}
|
||||
|
||||
filter += ch;
|
||||
selected = 0;
|
||||
last_key_time = now;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user