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;  	} |