From 2b4305b89e0aee24e0f6d5470e4be9abb4854943 Mon Sep 17 00:00:00 2001 From: Jack Jamison Date: Tue, 28 Oct 2025 01:40:34 -0400 Subject: non fancy scroll --- config.h | 2 +- font.c | 2 +- graphics.c | 4 +- input_field.c | 8 +--- input_field.h | 1 - keybind.c | 7 +++- layout.c | 123 +++++++++++++++++++++++++++++++++++++++++----------------- layout.h | 3 +- main.c | 7 ++-- state.h | 9 ++++- 10 files changed, 110 insertions(+), 56 deletions(-) diff --git a/config.h b/config.h index 27cac24..8deca15 100644 --- a/config.h +++ b/config.h @@ -8,7 +8,7 @@ typedef struct { float r,g,b,a; } color_t; -static const bool fancy_scroll = true; +static const bool fancy_scroll = false; static const uint32_t min_width = 500; static const uint32_t font_size = 16; static const color_t text_color = {0.85, 0.85, 0.85, 1.0}; diff --git a/font.c b/font.c index 0ce3561..7c08bf8 100644 --- a/font.c +++ b/font.c @@ -70,7 +70,7 @@ bool freetype_init(client_state* state, const char* file) { } state->load_flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL; state->line_height = state->ft_face->size->metrics.height >> 6; - state->horizontal_spacing = state->line_height / 2.0f; + state->horizontal_spacing = state->line_height / 1.3f; return true; } diff --git a/graphics.c b/graphics.c index 7ae5c51..285d3e0 100644 --- a/graphics.c +++ b/graphics.c @@ -179,7 +179,7 @@ void render_frame(client_state *state) { // calculate input buffer size rect_t prompt, input, options; - calculate_layout(state, &prompt, &input, &options, false); + calculate_layout(state, &prompt, &input, &options, false, false); if (state->prompt && *state->prompt) { glScissor(prompt.x, prompt.y, prompt.dx, prompt.dy); @@ -248,7 +248,7 @@ void render_frame(client_state *state) { glUniform4f(state->t_color_uniform, text_color.r,text_color.g,text_color.b,text_color.a); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, state->atlas.texture); - for (uint32_t i = 0; i < array_size(state->filtered_items); ++i) { + for (uint32_t i = state->displayed_item_start; i < state->displayed_item_end; ++i) { item_display_t* display = &state->filtered_items[i]; item_t* item = display->item; diff --git a/input_field.c b/input_field.c index 4eba923..ad94104 100644 --- a/input_field.c +++ b/input_field.c @@ -9,11 +9,6 @@ int compare(const void *a, const void *b) { return strlen(((item_display_t*)a)->item->text) > strlen(((item_display_t*)b)->item->text); } -void update_layout(client_state* state) { - rect_t prompt, input, options; - calculate_layout(state, &prompt, &input, &options, true); -} - void filter_items(client_state* state) { if (!state->items) return; @@ -43,7 +38,8 @@ void filter_items(client_state* state) { } // update layout - update_layout(state); + rect_t prompt, input, options; + calculate_layout(state, &prompt, &input, &options, true, true); } void update_text_buffer(client_state* state) { diff --git a/input_field.h b/input_field.h index b338b1f..6ec588e 100644 --- a/input_field.h +++ b/input_field.h @@ -8,6 +8,5 @@ key_repeat_t type_key(client_state* state, xkb_keysym_t keysym); void filter_items(client_state* state); void update_text_buffer(client_state* state); -void update_layout(client_state* state); #endif diff --git a/keybind.c b/keybind.c index c9b875a..17baad1 100644 --- a/keybind.c +++ b/keybind.c @@ -1,6 +1,7 @@ #include "keybind.h" #include "array.h" #include "input_field.h" +#include "layout.h" key_repeat_t quit(client_state* state) { state->running = false; @@ -40,7 +41,8 @@ key_repeat_t insert_selected(client_state* state) { key_repeat_t select_next(client_state* state) { if (state->selected_filtered_item != -1) { state->selected_filtered_item = MIN(state->selected_filtered_item + 1, (int)array_size(state->filtered_items) - 1); - update_layout(state); + rect_t prompt, input, options; + calculate_layout(state, &prompt, &input, &options, true, false); } return KEY_REPEAT; } @@ -48,7 +50,8 @@ key_repeat_t select_next(client_state* state) { key_repeat_t select_previous(client_state* state) { if (state->selected_filtered_item != -1) { state->selected_filtered_item = MAX(state->selected_filtered_item - 1, 0); - update_layout(state); + rect_t prompt, input, options; + calculate_layout(state, &prompt, &input, &options, true, false); } return KEY_REPEAT; } diff --git a/layout.c b/layout.c index 11706d6..d9051cd 100644 --- a/layout.c +++ b/layout.c @@ -2,13 +2,9 @@ #include "array.h" #include "config.h" -void init_layout(client_state* state) { - -} - -void calculate_layout(client_state* state, rect_t* prompt, rect_t* input, rect_t* options, bool recalc_options) { - +void calculate_layout(client_state* state, rect_t* prompt, rect_t* input, rect_t* options, bool recalc_options, bool recalc_pages) { if (state->prompt && *state->prompt) { + *prompt = (rect_t){ .x = 0, .y = state->line_height * state->lines, .dx = state->prompt_text_buffer.pixel_len + state->horizontal_spacing, .dy = state->line_height }; } else { @@ -31,7 +27,7 @@ void calculate_layout(client_state* state, rect_t* prompt, rect_t* input, rect_t options->dy = state->line_height; } - if (recalc_options) { + if (recalc_options || recalc_pages) { // calculate starting conditions rect_t cur; @@ -56,49 +52,104 @@ void calculate_layout(client_state* state, rect_t* prompt, rect_t* input, rect_t } } - // calculate fancy scroll - if (fancy_scroll && array_size(state->filtered_items) != 0) { + // calculate page indices + if (recalc_pages && !fancy_scroll) { + state->current_page = 0; + array_clear(state->page_indices); - // calculate if we should adjust scrolling if (state->lines) { - // calc vertical scroll - float selected_bot = state->fancy_scroll + state->filtered_items[state->selected_filtered_item].r.y; - float selected_top = selected_bot + state->filtered_items[state->selected_filtered_item].r.dy; - if (selected_bot < options->y) { - state->fancy_scroll -= selected_bot; - } - float diff = selected_top - (options->y + options->dy); - if (diff > 0) { - state->fancy_scroll -= diff; + // this won't work if we add sized images and bullshit to the option list + for (size_t i = 0; i < array_size(state->filtered_items); i += state->lines) { + array_add(state->page_indices, i); } } else { - // calc horizontal scroll - item_display_t* selected = &state->filtered_items[state->selected_filtered_item]; - float selected_left = state->fancy_scroll + selected->r.x; - float selected_right = selected_left + selected->r.dx; - float right_diff = selected_right - (options->x + options->dx); - float left_diff = selected_left - options->x; - - if (selected->r.dx > options->dx) { - state->fancy_scroll -= left_diff; + array_add(state->page_indices, 0); + float page_x = options->x; + size_t i = 0; + array_for_all(item_display_t, display, state->filtered_items) { + // check if past the end of the page + if (((display->r.x + display->r.dx) - page_x) / options->dx >= 1.f) { + page_x = display->r.x; + array_add(state->page_indices, i); + } + ++i; + } + } + } + + if (array_size(state->filtered_items) != 0) { + if (fancy_scroll) { + // calculate fancy scroll offset + if (state->lines) { + // calc vertical scroll + float selected_bot = state->scroll_offset + state->filtered_items[state->selected_filtered_item].r.y; + float selected_top = selected_bot + state->filtered_items[state->selected_filtered_item].r.dy; + if (selected_bot < options->y) { + state->scroll_offset -= selected_bot; + } + float diff = selected_top - (options->y + options->dy); + if (diff > 0) { + state->scroll_offset -= diff; + } + } else { + // calc horizontal scroll + item_display_t* selected = &state->filtered_items[state->selected_filtered_item]; + float selected_left = state->scroll_offset + selected->r.x; + float selected_right = selected_left + selected->r.dx; + float right_diff = selected_right - (options->x + options->dx); + float left_diff = selected_left - options->x; + + if (selected->r.dx > options->dx) { + state->scroll_offset -= left_diff; + } + else if (right_diff > 0) { + state->scroll_offset -= right_diff; + } + else if (left_diff < 0) { + state->scroll_offset -= left_diff; + } } - else if (right_diff > 0) { - state->fancy_scroll -= right_diff; + + // display all filtered items (could be optimized) + state->displayed_item_start = 0; + state->displayed_item_end = array_size(state->filtered_items); + + } else { + // calculate page scroll offset + + // determine what page the selected item is in + size_t selected_page = 0; + size_t selected_page_index = 0; + for(size_t i = 0; i < array_size(state->page_indices); ++i) { + if (state->selected_filtered_item < state->page_indices[i]) { + break; + } + selected_page = i; + selected_page_index = state->page_indices[i]; } - else if (left_diff < 0) { - state->fancy_scroll -= left_diff; + + // determine scroll to put that page at the start + if (state->lines) { + rect_t r = state->filtered_items[selected_page_index].r; + state->scroll_offset = (options->y + options->dy) - (r.y + r.dy); + } else { + rect_t r = state->filtered_items[selected_page_index].r; + state->scroll_offset = options->x - r.x; } + + // display filtered items on the page + state->displayed_item_start = state->page_indices[selected_page]; + state->displayed_item_end = (selected_page + 1 < array_size(state->page_indices)) ? state->page_indices[selected_page + 1] : array_size(state->filtered_items); } // apply scroll offset array_for_all(item_display_t, display, state->filtered_items) { if (state->lines) { - display->r.y += state->fancy_scroll; + display->r.y += state->scroll_offset; } else { - display->r.x += state->fancy_scroll; + display->r.x += state->scroll_offset; } } - - } + } } } diff --git a/layout.h b/layout.h index 4bb7899..af8f524 100644 --- a/layout.h +++ b/layout.h @@ -3,7 +3,6 @@ #include "state.h" -void init_layout(client_state* state); -void calculate_layout(client_state* state, rect_t* prompt, rect_t* input, rect_t* options, bool recalc_options); +void calculate_layout(client_state* state, rect_t* prompt, rect_t* input, rect_t* options, bool recalc_options, bool recalc_pages); #endif diff --git a/main.c b/main.c index 8d8569e..f0c53b9 100644 --- a/main.c +++ b/main.c @@ -12,6 +12,7 @@ #include "font.h" #include "array.h" #include "args.h" +#include "layout.h" void poll_events(client_state* state); @@ -39,6 +40,7 @@ int main(int argc, char* argv[]) { state.input_buffer = array_new(char, 0); state.filtered_items = array_new(item_display_t, 0); state.selected_filtered_item = -1; + state.page_indices = array_new(size_t, 0); // check locale setlocale(LC_ALL, ""); @@ -52,8 +54,6 @@ int main(int argc, char* argv[]) { parse_args(&state, argc, argv); read_stdin(&state); - array_dump(state.items, item_t, item, "%s: %lu", item->text, strlen(item->text)); - // find font char* font = get_font("Monospace"); if (!freetype_init(&state, font)) { @@ -90,11 +90,10 @@ int main(int argc, char* argv[]) { // create font altas textures atlas_create_texture(&state); + // create text buffers if (state.prompt && *state.prompt) { init_text_buffer(&state, &state.prompt_text_buffer, state.prompt, strlen(state.prompt)); } - - // create text buffers init_text_buffer(&state, &state.input_buffer_grafix, "", 0); array_for_all(item_t, item, state.items) { init_text_buffer(&state, &item->text_buffer, item->text, strlen(item->text)); diff --git a/state.h b/state.h index ebbc962..695ad2f 100644 --- a/state.h +++ b/state.h @@ -132,7 +132,14 @@ typedef struct { int selected_filtered_item; char* input_buffer; size_t cursor_index; - float fancy_scroll; + + // scrolling + float scroll_offset; + size_t displayed_item_start; + size_t displayed_item_end; + // page scroll + size_t* page_indices; // page indices into filtered items + size_t current_page; } client_state; -- cgit v1.2.3