summaryrefslogtreecommitdiff
path: root/src/ui_elements/UI.c
blob: 85c7a027abb9b901982df8135a1fcd6330025cff (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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include "UI.h"
#include <raylib.h>
#include <stdio.h>
#include "../resources/resources.h"

const int MAX_LINES = 8192;
const int SPACING_H = 1;

void DrawRecBordered(Rectangle rec, Color bg, Color border_color, int border_width) {
    DrawRectangleRounded(rec, ROUNDNESS, ROUNDNESS_SEGMENTS, bg); 
    DrawRectangleRoundedLinesEx(rec, ROUNDNESS, ROUNDNESS_SEGMENTS, border_width, border_color);
}

float MeasureChar(Font *font, int height, char symbol) {
    char buf[2] = { symbol, 0 };
    return MeasureTextEx(*font, buf, height, SPACING_H).x;
}

int CalculateSpans(Rectangle rec, char *text, Font *font, int height, int *spans) {
    spans[0] = 0;
    int ptr = 0, span_ptr = 1;
    int last_space_ptr = -1;
    float acc = 0;

    while (text[ptr] != 0x0) {
        char symbol = text[ptr];
        float char_width = MeasureChar(font, height, symbol);
        acc += char_width + SPACING_H;

        if (symbol == ' ' || symbol == '\n') {
            last_space_ptr = ptr;
        }
        if (acc > rec.width || symbol == '\n') {
            if (last_space_ptr < spans[span_ptr - 1] || symbol == '\n' && last_space_ptr == -1) {
                spans[span_ptr] = (ptr > spans[span_ptr - 1]) ? ptr : ptr + 1;
                last_space_ptr = spans[span_ptr];
                ptr = spans[span_ptr] - 1;
            } else {
                if (spans[span_ptr - 1] == last_space_ptr) {
                    spans[span_ptr] = ptr;
                    last_space_ptr = ptr;
                } else {
                    spans[span_ptr] = last_space_ptr + 1;
                }
                ptr = last_space_ptr;
            }
            // printf("span %d = '%.*s'\n", span_ptr, spans[span_ptr] - spans[span_ptr - 1], text + spans[span_ptr - 1]);
            span_ptr++;
            acc = 0;
        }
        ptr++;
        if (span_ptr >= MAX_LINES) break;
    }

    spans[span_ptr] = ptr; 
    // printf("span %d = '%.*s'\n", span_ptr, spans[span_ptr] - spans[span_ptr - 1], text + spans[span_ptr - 1]);
    return span_ptr + 1;
}

bool IsMouseInRec(Rectangle rec) {
    Vector2 MousePos = GetMousePosition();
    return CheckCollisionPointRec(MousePos, rec);
}

void DrawTextInRec(Rectangle rec, char *text, Font *font, int height, Color color, float padding, int *scroll) {
    if (text == NULL) return;
    int spans[MAX_LINES];
    rec.x += padding;
    rec.y += padding;
    rec.width -= 2 * padding;
    rec.height -= 2 * padding;
    int lines = CalculateSpans(rec, text, font, height, spans);

    if (lines == 2) {
        Vector2 pos = {.x = rec.x, .y = rec.y};
        DrawTextEx(*font, text, pos, height, SPACING_H, color);
        return;
    }

    int vertical_acc = scroll == NULL? rec.y : rec.y - *scroll;
    int text_height = lines * height;
    int max_scroll = text_height - rec.height;

    if (text_height >= rec.height && IsMouseInRec(rec)) {
        *scroll -= GetMouseWheelMove() * SCROLL_SENC;
        if (*scroll < 0) *scroll = 0;
        if (*scroll > max_scroll) *scroll = max_scroll;
    }

    BeginScissorMode(rec.x, rec.y, rec.width, rec.height);
    for (int i = 1; i < lines; i++) {
        if (i == MAX_LINES) break;
        Vector2 pos = { .x = rec.x, .y = vertical_acc };
        char *line_start = text + spans[i-1];
        int line_length = spans[i] - spans[i-1];
        // printf("Drawing text '%.*s' at %f;%f\n", line_length, line_start, pos.x, pos.y);
        DrawTextEx(*font, 
                TextFormat("%.*s", line_length, line_start), 
                pos, height, SPACING_H, color);
        vertical_acc += height;
    }
    EndScissorMode();
}

void GetPanesSplit(Rectangle *pane1, Rectangle *pane2, Rectangle body, float proportion_h, float proportion_v) {
    if (body.height >= body.width) {
        // vertical split
        pane1->x = body.x;
        pane1->y = body.y;
        pane1->width = body.width;
        pane1->height = (body.height - PADDING) * proportion_v;

        pane2->x = body.x;
        pane2->y = body.y + pane1->height + PADDING;
        pane2->width = body.width;
        pane2->height = (body.height - PADDING) * (1 - proportion_v);
        return;
    }

    // horizontal split
    pane1->x = body.x;
    pane1->y = body.y;
    pane1->height = body.height;
    pane1->width = (body.width - PADDING) * proportion_h;

    pane2->y = body.y;
    pane2->x = body.x + pane1->width + PADDING;
    pane2->height = body.height;
    pane2->width = (body.width - PADDING) * (1 - proportion_h);
}

void DrawPageView(int y, unsigned int pages, unsigned int current_page) {
    if (pages == 0) return;
    float width = 2 * PAGE_DOTS_PADDING 
            + PAGE_DOTS_RADIUS * 2 * pages 
            + PAGE_DOTS_SPACING * (pages - 1);

    Rectangle rec = {
        .x = (GetScreenWidth() - width) / 2, // TODO
        .y = y,
        .height = PAGE_DOTS_RADIUS * 2 + 2 * PAGE_DOTS_PADDING,
        .width = width,
    };

    Color color = { 
        .r = COLORSCHEME_WHITE.r,
        .g = COLORSCHEME_WHITE.g,
        .b = COLORSCHEME_WHITE.b,
        .a = COLORSCHEME_WHITE.a & PAGE_DOTS_TRANSPARENCY };

    DrawRectangleRounded(rec, ROUNDNESS, ROUNDNESS_SEGMENTS, color); 

    int x_pos = (int)rec.x + PAGE_DOTS_PADDING + PAGE_DOTS_RADIUS;
    int y_pos = (int)rec.y + PAGE_DOTS_PADDING + PAGE_DOTS_RADIUS;
    for (int i = 0; i < pages; ++i) {
        Color color = i == current_page ? COLORSCHEME_ORANGE : COLORSCHEME_BROWN;
        DrawCircle(x_pos, y_pos, PAGE_DOTS_RADIUS, color);
        x_pos += PAGE_DOTS_SPACING + PAGE_DOTS_RADIUS * 2;
    }
}