aboutsummaryrefslogtreecommitdiff
path: root/layout.c
blob: 11706d65e8ccdde80d05b9f7666cef89f1ddca9d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include "layout.h"
#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) {

	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 {
		*prompt = (rect_t){ 0 };
	}
	// calculate input rect
	*input = (rect_t){ .x = prompt->dx, .y = state->line_height * state->lines, .dx = state->width - prompt->dx, .dy = state->line_height };
	if (state->lines == 0 && array_size(state->filtered_items) != 0) {
		input->dx = state->width / 3.0f - input->x;
	}

	// calculate options rect
	*options = (rect_t){0};
	if (state->lines) {
		options->dx = state->width;
		options->dy = input->y;
	} else {
		options->x = input->x + input->dx;
		options->dx = state->width - options->x;
		options->dy = state->line_height;
	}

	if (recalc_options) {

		// calculate starting conditions
		rect_t cur;
		if (state->lines) {
			cur = (rect_t){ .x = options->x, .y = input->y - state->line_height, .dx = options->dx, .dy = state->line_height };
		} else {
			cur = (rect_t){ .x = options->x, .y = options->y, .dx = 0.0f, .dy = state->line_height };
		}

		// calculate base filtered item rects
		array_for_all(item_display_t, display, state->filtered_items) {
			if (!state->lines) {
				cur.dx = display->item->pixel_len + state->horizontal_spacing;
			}

			display->r = cur;

			if (state->lines) {
				cur.y -= state->line_height;
			} else {
				cur.x += cur.dx;
			}
		}

		// calculate fancy scroll
		if (fancy_scroll && array_size(state->filtered_items) != 0) {

			// 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;
				}
			} 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;
				}
				else if (right_diff > 0) {
					state->fancy_scroll -= right_diff;
				}
				else if (left_diff < 0) {
					state->fancy_scroll -= left_diff;
				}
			}

			// apply scroll offset
			array_for_all(item_display_t, display, state->filtered_items) {
				if (state->lines) {
					display->r.y += state->fancy_scroll;
				} else {
					display->r.x += state->fancy_scroll;
				}
			}

		}
	}
}