diff options
author | quou <quou@disroot.org> | 2024-08-03 16:15:02 +1000 |
---|---|---|
committer | quou <quou@disroot.org> | 2024-08-03 16:15:02 +1000 |
commit | 496db167337e246cc12beb1ace2bdec35b916479 (patch) | |
tree | c3235b99c1605f62b29bf1b4d8e36133d9f64c4b /gui.c | |
parent | ee3406af08853b0ffb30efd203a373460300077f (diff) |
scrollbars
Diffstat (limited to 'gui.c')
-rw-r--r-- | gui.c | 158 |
1 files changed, 158 insertions, 0 deletions
@@ -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; } |