summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorquou <quou@disroot.org>2024-08-03 16:15:02 +1000
committerquou <quou@disroot.org>2024-08-03 16:15:02 +1000
commit496db167337e246cc12beb1ace2bdec35b916479 (patch)
treec3235b99c1605f62b29bf1b4d8e36133d9f64c4b
parentee3406af08853b0ffb30efd203a373460300077f (diff)
scrollbars
-rw-r--r--editor.c8
-rw-r--r--gui.c158
-rw-r--r--gui.h23
3 files changed, 186 insertions, 3 deletions
diff --git a/editor.c b/editor.c
index 0aae694..b59ce32 100644
--- a/editor.c
+++ b/editor.c
@@ -12,18 +12,22 @@ void draw_map_scrollable(
const Rect* rect,
const GUI_Scroll_State* ss
) {
+ Rect re = { 0, 0, 500, 500 };
+ re.x = rect->x - ss->x;
+ re.y = rect->y - ss->y;
(void)g;
(void)ss;
- ren_texture(r, rect, get_texture(asset_id_floorboards_texture));
+ ren_texture(r, &re, get_texture(asset_id_floorboards_texture));
}
void edit_map(Editor* e, GUI* g, Map* m) {
Rect b = gui_viewport(g);
Rect t = gui_cut_up(&b, gui_text_height() + 4);
+ int mcs[] = { 500, 500 };
(void)e;
(void)m;
gui_btn(g, gui_cut_left(&t, gui_text_width("Load", 4) + 4), "Save");
gui_btn(g, gui_cut_left(&t, gui_text_width("Save", 4) + 4), "Load");
- gui_scrollable(g, b, &map_ss, draw_map_scrollable);
+ gui_scrollable(g, b, mcs, &map_ss, draw_map_scrollable);
}
diff --git a/gui.c b/gui.c
index 0fe1f69..366e420 100644
--- a/gui.c
+++ b/gui.c
@@ -1,4 +1,5 @@
#include "gui.h"
+#include "maths.h"
#include "memory.h"
#include "plat.h"
#include "render.h"
@@ -103,14 +104,109 @@ int gui_btn(GUI* g, Rect r, const char* text) {
void gui_scrollable(
GUI* g,
Rect r,
+ const int* cs,
GUI_Scroll_State* state,
GUI_Scrollable_Draw_Fn fn
) {
GUI_Scrollable* e = gui_alloc(g, sizeof *e);
+ Rect srx, sry;
+ int nx, ny, h = mouse_over(g->app, &r);
+ int size = 15;
e->el.type = gui_el_type_scrollable;
e->el.r = r;
+ e->cs[0] = cs[0];
+ e->cs[1] = cs[1];
e->ss = state;
e->draw = fn;
+ e->vp[0] = r.w - 2;
+ e->vp[1] = r.h - 2;
+ if ((nx = cs[0] - r.w) > 0) {
+ srx.h = size;
+ srx.w = r.w;
+ srx.x = r.x;
+ srx.y = r.y + r.h - srx.h;
+ e->vp[1] -= srx.h;
+ if (h)
+ state->x -= g->app->scrollx;
+ }
+ if ((ny = cs[1] - r.h) > 0) {
+ sry.w = size;
+ sry.h = r.h;
+ sry.x = r.x + r.w - sry.w;
+ sry.y = r.y;
+ e->vp[0] -= sry.w;
+ if (h)
+ state->y -= g->app->scrolly;
+ }
+ if (nx > 0 && ny > 0) {
+ srx.w -= size;
+ sry.h -= size;
+ nx = cs[0] - (r.w - size);
+ ny = cs[1] - (r.h - size);
+ }
+ if (nx > 0) {
+ state->x = clamp(state->x, 0, nx);
+ gui_scrollbar(g, state, srx, nx, 1);
+ }
+ if (ny > 0) {
+ state->y = clamp(state->y, 0, ny);
+ gui_scrollbar(g, state, sry, ny, 0);
+ }
+}
+
+void gui_scrollbar(
+ GUI* g,
+ GUI_Scroll_State* state,
+ Rect r,
+ int diff,
+ int horizontal
+) {
+ GUI_Scrollbar* e = gui_alloc(g, sizeof *e);
+ int ls = g->app->mbtn_states[mbtn_left];
+ int mh = 30;
+ e->el.type = gui_el_type_scrollbar;
+ e->el.r = r;
+ if (horizontal) {
+ e->handle.x = r.x + state->x * (r.w - e->handle.w) / diff;
+ e->handle.y = r.y;
+ e->handle.w = r.w * r.w / (r.w + diff);
+ e->handle.w = maxi(e->handle.w, mh);
+ e->handle.h = r.h;
+ } else {
+ e->handle.x = r.x;
+ e->handle.y = r.y + state->y * (r.h - e->handle.h) / diff;
+ e->handle.w = r.w;
+ e->handle.h = r.h * r.h / (r.h + diff);
+ e->handle.h = maxi(e->handle.h, mh);
+ }
+ e->s = state;
+ e->h = horizontal;
+ e->hover = 0;
+ e->active = 0;
+ if (
+ mouse_over(g->app, &e->handle) &&
+ ls & key_state_just_pressed
+ ) {
+ state->grabbed[horizontal] = 1;
+ state->graboff[horizontal] =
+ (e->handle.x - g->app->mx);
+ }
+#define doscroll(a, ad) \
+ int scroll = state->a + g->app->dm ## a; \
+ scroll = clamp(scroll, 0, diff); \
+ state->a = scroll; \
+ e->handle.a = scroll * (r.ad - e->handle.ad) / diff + r.a;
+ if (state->grabbed[horizontal]) {
+ if (horizontal) {
+ doscroll(x, w)
+ } else {
+ doscroll(y, h)
+ }
+ if (ls & key_state_just_released)
+ state->grabbed[horizontal] = 0;
+ if (ls & key_state_just_released)
+ state->grabbed[horizontal] = 0;
+ }
}
void rect_cfit(Rect* r) {
@@ -177,11 +273,70 @@ void draw_scrollable(
Rect rect = s->el.r;
draw_container(r, &s->el.r, 0);
rect_cfit(&rect);
+ rect.w = s->vp[0];
+ rect.h = s->vp[1];
ren_clip(r, &rect);
s->draw(g, r, &rect, s->ss);
ren_clipr(r);
}
+void draw_scrollbar(
+ GUI* g,
+ Renderer* r,
+ const GUI_Scrollbar* s
+) {
+ int a = s->s->grabbed[s->h];
+ Colour out1 = make_colour(0xffffff, 0xff);
+ Colour out2 = make_colour(0x000000, 0xff);
+ Rect rect, h = s->handle;
+ (void)g;
+ if (a) {
+ Colour t = out1;
+ out1 = out2;
+ out2 = t;
+ }
+ draw_container(r, &s->el.r, 0);
+ if (s->h) {
+ int i;
+ h.x++;
+ h.w -= 2;
+ rect.w = 1;
+ rect.h = 7;
+ rect.x = s->handle.x + s->handle.w / 2 - 7;
+ rect.y = s->handle.y + s->handle.h / 2 - rect.h / 2;
+ if (a) {
+ rect.x++;
+ rect.y++;
+ }
+ draw_container(r, &h, a);
+ for (i = 0; i < 3; i++) {
+ ren_rect(r, out1, &rect);
+ rect.x++;
+ ren_rect(r, out2, &rect);
+ rect.x += 4;
+ }
+ } else {
+ int i;
+ h.y++;
+ h.h -= 2;
+ rect.w = 7;
+ rect.h = 1;
+ rect.x = s->handle.x + s->handle.w / 2 - rect.w / 2;
+ rect.y = s->handle.y + s->handle.h / 2 - 7;
+ if (a) {
+ rect.x++;
+ rect.y++;
+ }
+ draw_container(r, &h, a);
+ for (i = 0; i < 3; i++) {
+ ren_rect(r, out1, &rect);
+ rect.y++;
+ ren_rect(r, out2, &rect);
+ rect.y += 4;
+ }
+ }
+}
+
void gui_end(GUI* g, Renderer* r) {
GUI_El* el = g->first;
while (el) {
@@ -192,6 +347,9 @@ void gui_end(GUI* g, Renderer* r) {
case gui_el_type_scrollable:
draw_scrollable(g, r, (GUI_Scrollable*)el);
break;
+ case gui_el_type_scrollbar:
+ draw_scrollbar(g, r, (GUI_Scrollbar*)el);
+ break;
}
el = el->next;
}
diff --git a/gui.h b/gui.h
index 50927f4..5b3063b 100644
--- a/gui.h
+++ b/gui.h
@@ -10,7 +10,8 @@ struct Renderer;
typedef enum {
gui_el_type_btn,
- gui_el_type_scrollable
+ gui_el_type_scrollable,
+ gui_el_type_scrollbar
} GUI_El_Type;
typedef struct GUI_El {
@@ -27,8 +28,18 @@ typedef struct {
typedef struct {
int x, y;
+ short grabbed[2];
+ short graboff[2];
} GUI_Scroll_State;
+typedef struct {
+ GUI_El el;
+ GUI_Scroll_State* s;
+ Rect handle;
+ int h;
+ int hover, active;
+} GUI_Scrollbar;
+
typedef void (*GUI_Scrollable_Draw_Fn)(
struct GUI*,
struct Renderer*,
@@ -40,6 +51,8 @@ typedef struct {
GUI_El el;
GUI_Scrollable_Draw_Fn draw;
GUI_Scroll_State* ss;
+ int cs[2];
+ int vp[2];
} GUI_Scrollable;
typedef struct GUI {
@@ -63,8 +76,16 @@ int gui_btn(GUI* g, Rect r, const char* text);
void gui_scrollable(
GUI* g,
Rect r,
+ const int* cs,
GUI_Scroll_State* state,
GUI_Scrollable_Draw_Fn fn
);
+void gui_scrollbar(
+ GUI* g,
+ GUI_Scroll_State* state,
+ Rect r,
+ int diff,
+ int horizontal
+);
#endif