aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.h2
-rw-r--r--font.c2
-rw-r--r--graphics.c4
-rw-r--r--input_field.c8
-rw-r--r--input_field.h1
-rw-r--r--keybind.c7
-rw-r--r--layout.c123
-rw-r--r--layout.h3
-rw-r--r--main.c7
-rw-r--r--state.h9
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;