1503 lines · 36.8 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <draw.h>#include <microui.h> #define MU_REAL_FMT "%g"#define MU_SLIDER_FMT "%.2f" #define MIN(a, b) ((a) < (b) ? (a) : (b))#define MAX(a, b) ((a) > (b) ? (a) : (b))#define CLAMP(x, a, b) MIN(b, MAX(a, x)) static mu_Rect unclipped_rect = { 0, 0, 0x1000000, 0x1000000 }; static u8int atlasraw[] = {	0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x72, 0x38,	0x67, 0x38, 0x62, 0x38, 0x61, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,	0x20, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x20,	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x33, 0x34, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,	0x20, 0x20, 0x20, 0x20, 0x32, 0x35, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,	0x32, 0x35, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x34, 0x33, 0x39, 0x20, 0x80,	0x00, 0x7c, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x78, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x7c,	0x00, 0x7c, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x34, 0x00, 0x80,	0x14, 0x00, 0x00, 0x80, 0x5c, 0x00, 0x00, 0x54, 0x1f, 0x04, 0x1b, 0x04, 0x23, 0x24, 0x13, 0x7c,	0x00, 0x3c, 0x00, 0x80, 0x20, 0x00, 0x00, 0x80, 0xc0, 0x00, 0x00, 0x04, 0x07, 0x44, 0x1f, 0x80,	0x5e, 0x00, 0x00, 0x80, 0xff, 0x00, 0x00, 0x80, 0x70, 0x00, 0x00, 0x34, 0x1b, 0x04, 0x13, 0x04,	0x1b, 0x04, 0x23, 0x24, 0x17, 0x7c, 0x00, 0x2c, 0x00, 0x80, 0x21, 0x00, 0x00, 0x80, 0xe0, 0x00,	0x00, 0x80, 0xea, 0x00, 0x00, 0x80, 0x2c, 0x00, 0x00, 0x54, 0x27, 0x14, 0x6f, 0x24, 0x8b, 0x44,	0x13, 0x14, 0x00, 0x7c, 0x00, 0x4c, 0x83, 0x80, 0x2d, 0x00, 0x00, 0x74, 0x2f, 0x24, 0x77, 0x74,	0x83, 0x7c, 0x00, 0x1c, 0x83, 0x80, 0xe1, 0x00, 0x00, 0x80, 0xeb, 0x00, 0x00, 0x7c, 0x83, 0x3c,	0x8b, 0x74, 0x83, 0x24, 0x00, 0x80, 0x0e, 0x00, 0x00, 0x7c, 0x83, 0x7c, 0x83, 0x7c, 0x87, 0x3c,	0x00, 0x14, 0x00, 0x80, 0x3d, 0x00, 0x00, 0x80, 0xed, 0x00, 0x00, 0x80, 0x45, 0x00, 0x00, 0x24,	0x17, 0x80, 0x22, 0x00, 0x00, 0x7c, 0x83, 0x7d, 0x97, 0x75, 0x97, 0x14, 0x00, 0x80, 0x13, 0x00,	0x00, 0x80, 0xd0, 0x00, 0x00, 0x80, 0xf6, 0x00, 0x00, 0x14, 0x8b, 0x24, 0x83, 0x80, 0x2e, 0x00,	0x00, 0x7c, 0x79, 0x7e, 0xa7, 0x54, 0x8b, 0x54, 0x8b, 0x80, 0x63, 0x00, 0x00, 0x7c, 0x83, 0x4c,	0x00, 0x7f, 0xb7, 0x3f, 0xb7, 0x54, 0x8b, 0x04, 0x2b, 0x80, 0xec, 0x00, 0x00, 0x7c, 0x83, 0x3c,	0x00, 0x80, 0x14, 0x00, 0x00, 0x80, 0x5c, 0x00, 0x00, 0x54, 0x1f, 0x04, 0x1b, 0x04, 0x23, 0x24,	0x13, 0x54, 0x8b, 0x80, 0xbc, 0x00, 0x00, 0x7c, 0x83, 0x7c, 0x00, 0x7c, 0x00, 0x0c, 0x00, 0x7c,	0x00, 0x7c, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x7c,	0x00, 0x7c, 0x00, 0x64, 0x00, 0x80, 0x5a, 0x00, 0x00, 0x06, 0x6b, 0x14, 0x07, 0x80, 0x8f, 0x00,	0x00, 0x44, 0x27, 0x7c, 0x00, 0x7c, 0x00, 0x64, 0x00, 0x80, 0x3c, 0x00, 0x00, 0x80, 0xaa, 0x00,	0x00, 0x04, 0x07, 0x04, 0x83, 0x54, 0x8b, 0x44, 0x17, 0x14, 0x2f, 0x7c, 0x65, 0x7c, 0x00, 0x34,	0x00, 0x54, 0x8b, 0x34, 0x17, 0x64, 0xb3, 0x7c, 0x00, 0x0c, 0x00, 0x80, 0x6e, 0x00, 0x00, 0x05,	0x03, 0x35, 0x0f, 0x64, 0x8b, 0x34, 0x17, 0x7c, 0x83, 0x7c, 0x00, 0x80, 0xa5, 0x00, 0x00, 0x15,	0x4f, 0x26, 0x1f, 0x64, 0x83, 0x74, 0xa3, 0x7c, 0x00, 0x7c, 0x00, 0x7c, 0x63, 0x81, 0x00, 0x00,	0x34, 0x27, 0x7c, 0x4d, 0x4c, 0x00, 0x80, 0x55, 0x00, 0x00, 0x80, 0x37, 0x00, 0x00, 0x04, 0x0b,	0x04, 0x07, 0x04, 0x0f, 0x04, 0x0b, 0x80, 0x1e, 0x00, 0x00, 0x04, 0x0b, 0x04, 0x07, 0x64, 0x83,	0x7c, 0x00, 0x7c, 0x00, 0x16, 0xef, 0x05, 0x8f, 0x75, 0x97, 0x54, 0x00, 0x7c, 0x00, 0x7c, 0x00,	0x7d, 0x0f, 0x0d, 0x0f, 0x64, 0x3f,}; static mu_Rect default_atlas_icons[] = {	[MU_ICON_CHECK] = {0, 0, 18, 18},	[MU_ICON_CLOSE] = {18, 0, 16, 16},	[MU_ICON_COLLAPSED] = {27, 16, 5, 7},	[MU_ICON_EXPANDED] = {0, 18, 7, 5},	[MU_ICON_RESIZE] = {18, 16, 9, 9},	[ATLAS_DIMENSIONS] = {0, 0, 34, 25},}; mu_Context mu_ctx;mu_Style mu_style = {	.font = nil,	.size = { 68, 10 },	.padding = 6,	.spacing = 4,	.indent = 24,	.title_height = 26,	.scrollbar_size = 12,	.thumb_size = 8,	.colors = {nil},}; Image *atlasimage = nil;mu_Rect *atlasicons = default_atlas_icons;u8int defaultcolors[MU_COLOR_MAX][4] = {	[MU_COLOR_BG] = {119, 119, 119, 255},	[MU_COLOR_TEXT] = {230, 230, 230, 255},	[MU_COLOR_BORDER] = {25, 25, 25, 255},	[MU_COLOR_WINDOWBG] = {50, 50, 50, 255},	[MU_COLOR_TITLEBG] = {25, 25, 25, 255},	[MU_COLOR_TITLETEXT] = {240, 240, 240, 255},	[MU_COLOR_PANELBG] = {0, 0, 0, 0},	[MU_COLOR_BUTTON] = {75, 75, 75, 255},	[MU_COLOR_BUTTONHOVER] = {95, 95, 95, 255},	[MU_COLOR_BUTTONFOCUS] = {115, 115, 115, 255},	[MU_COLOR_BASE] = {30, 30, 30, 255},	[MU_COLOR_BASEHOVER] = {35, 35, 35, 255},	[MU_COLOR_BASEFOCUS] = {40, 40, 40, 255},	[MU_COLOR_SCROLLBASE] = {43, 43, 43, 255},	[MU_COLOR_SCROLLTHUMB] = {30, 30, 30, 255},}; static voidbuffer_grow(void **buf, int onesz, int *bufmax, int bufnum){	while (*bufmax <= bufnum) {		*bufmax = MAX(16, *bufmax) * 2;		if ((*buf = realloc(*buf, *bufmax*onesz)) == nil)			sysfatal("not enough memory for %d items (%d bytes)", *bufmax, *bufmax*onesz);	}} mu_Rectmu_rect(int x, int y, int w, int h){	mu_Rect res;	res.x = x, res.y = y, res.w = w, res.h = h;	return res;} Image *mu_color(u8int r, u8int g, u8int b, u8int a){	Image *c;	if ((c = allocimage(display, Rect(0, 0, 1, 1), RGBA32, 1, setalpha(r<<24 | g<<16 | b<<8, a))) == nil)		sysfatal("couldn't allocate color");	return c;} static Rectanglescreenrect(mu_Rect r){	Rectangle rect;	rect.min = screen->r.min;	rect.min.x += r.x;	rect.min.y += r.y;	rect.max = rect.min;	rect.max.x += r.w;	rect.max.y += r.h;	return rect;} static mu_Rectexpand_rect(mu_Rect rect, int n) {	return mu_rect(rect.x - n, rect.y - n, rect.w + n * 2, rect.h + n * 2);}  static mu_Rectclip_rect(mu_Rect r1, mu_Rect r2){	int x1 = MAX(r1.x, r2.x);	int y1 = MAX(r1.y, r2.y);	int x2 = MAX(MIN(r1.x + r1.w, r2.x + r2.w), x1);	int y2 = MAX(MIN(r1.y + r1.h, r2.y + r2.h), y1);	return mu_rect(x1, y1, x2 - x1, y2 - y1);}  static intrect_overlaps_vec2(mu_Rect r, Point p){	return p.x >= r.x && p.x < r.x + r.w && p.y >= r.y && p.y < r.y + r.h;} static voiddraw_frame(mu_Rect rect, int colorid){	mu_draw_rect(rect, mu_style.colors[colorid]);	if (colorid == MU_COLOR_SCROLLBASE	|| colorid == MU_COLOR_SCROLLTHUMB || colorid == MU_COLOR_TITLEBG)		return;	/* draw border */	mu_draw_box(expand_rect(rect, 1), mu_style.colors[MU_COLOR_BORDER]);} static inttext_width(Font *font, const char *text, int len){	return stringnwidth(font, text, len >= 0 ? len : strlen(text));} voidmu_init(void){	Rectangle r;	int res, i; 	if (atlasimage == nil) {		r = Rect(0, 0, atlasicons[ATLAS_DIMENSIONS].w, atlasicons[ATLAS_DIMENSIONS].h);		atlasimage = allocimage(display, r, RGBA32, 1, DTransparent);		if (memcmp(atlasraw, "compressed\n", 11) == 0)			res = cloadimage(atlasimage, r, atlasraw+11+5*12, sizeof(atlasraw)-11-5*12);		else			res = loadimage(atlasimage, r, atlasraw, sizeof(atlasraw));		if (res < 0)			sysfatal("failed to load atlas: %r");	} 	if (mu_style.colors[0] == nil) {		for (i = 0; i < MU_COLOR_MAX; i++) {			mu_style.colors[i] = mu_color(				defaultcolors[i][0],				defaultcolors[i][1],				defaultcolors[i][2],				defaultcolors[i][3]			);		}	}} voidmu_begin(void){	mu_ctx.cmdsnum = mu_ctx.rootnum = 0;	mu_ctx.strnum = 0;	mu_ctx.scroll_target = nil;	mu_ctx.last_hover_root = mu_ctx.hover_root;	mu_ctx.hover_root = nil;	mu_ctx.mouse_delta.x = mu_ctx.mouse_pos.x - mu_ctx.last_mouse_pos.x;	mu_ctx.mouse_delta.y = mu_ctx.mouse_pos.y - mu_ctx.last_mouse_pos.y;} static intcompare_zindex(const void *a, const void *b){	return (*(mu_Container**)a)->zindex - (*(mu_Container**)b)->zindex;} voidmu_end(void){	int i, n;	/* check stacks */	assert(mu_ctx.cntnum == 0);	assert(mu_ctx.clipnum == 0);	assert(mu_ctx.idsnum == 0);	assert(mu_ctx.layoutsnum == 0); 	/* handle scroll input */	if (mu_ctx.scroll_target) {		mu_ctx.scroll_target->scroll.x += mu_ctx.scroll_delta.x;		mu_ctx.scroll_target->scroll.y += mu_ctx.scroll_delta.y;	} 	/* unset focus if focus id was not touched this frame */	if (!mu_ctx.updated_focus)		mu_ctx.focus = 0;	mu_ctx.updated_focus = 0; 	/* bring hover root to front if mouse was pressed */	if (mu_ctx.mouse_pressed && mu_ctx.hover_root && mu_ctx.hover_root->zindex < mu_ctx.last_zindex)		mu_bring_to_front(mu_ctx.hover_root); 	/* reset input state */	mu_ctx.key_pressed = 0;	mu_ctx.text_input[0] = 0;	mu_ctx.mouse_pressed = 0;	mu_ctx.scroll_delta = ZP;	mu_ctx.last_mouse_pos = mu_ctx.mouse_pos; 	/* sort root containers by zindex */	n = mu_ctx.rootnum;	qsort(mu_ctx.root, n, sizeof(*mu_ctx.root), compare_zindex); 	/* set root container jump commands */	for (i = 0; i < n; i++) {		mu_Container *cnt = mu_ctx.root[i];		/* if this is the first container then make the first command jump to it.		** otherwise set the previous container's tail to jump to this one */		if (i == 0)			mu_ctx.cmds[0].jump.dst = cnt->head + 1;		else			mu_ctx.cmds[mu_ctx.root[i - 1]->tail].jump.dst = cnt->head + 1; 		/* make the last container's tail jump to the end of command list */		if (i == n - 1)			mu_ctx.cmds[cnt->tail].jump.dst = mu_ctx.cmdsnum;	}}  voidmu_set_focus(mu_Id id){	mu_ctx.focus = id;	mu_ctx.updated_focus = 1;} /* 32bit fnv-1a hash */#define HASH_INITIAL 2166136261U static voidhash(mu_Id *hash, const void *data, int size){	const unsigned char *p = data;	while (size--) {		*hash = (*hash ^ *p++) * 16777619;	}}  mu_Idmu_get_id(const void *data, int size){	int idx = mu_ctx.idsnum;	mu_Id res = (idx > 0) ? mu_ctx.ids[idx - 1] : HASH_INITIAL;	hash(&res, data, size);	mu_ctx.last_id = res;	return res;}  voidmu_push_id(const void *data, int size){	buffer_grow(&mu_ctx.ids, sizeof(*mu_ctx.ids), &mu_ctx.idsmax, mu_ctx.idsnum);	mu_ctx.ids[mu_ctx.idsnum++] = mu_get_id(data, size);} voidmu_pop_id(void){	mu_ctx.idsnum--;} voidmu_push_clip_rect(mu_Rect rect){	mu_Rect last = mu_get_clip_rect();	buffer_grow(&mu_ctx.clip, sizeof(*mu_ctx.clip), &mu_ctx.clipmax, mu_ctx.clipnum);	mu_ctx.clip[mu_ctx.clipnum++] = clip_rect(rect, last);}  voidmu_pop_clip_rect(void){	mu_ctx.clipnum--;}  mu_Rectmu_get_clip_rect(void){	assert(mu_ctx.clipnum > 0);	return mu_ctx.clip[mu_ctx.clipnum - 1];}  intmu_check_clip(mu_Rect r){	mu_Rect cr = mu_get_clip_rect();	if (r.x > cr.x + cr.w || r.x + r.w < cr.x || r.y > cr.y + cr.h || r.y + r.h < cr.y)		return MU_CLIP_ALL;	if (r.x >= cr.x && r.x + r.w <= cr.x + cr.w && r.y >= cr.y && r.y + r.h <= cr.y + cr.h)		return MU_CLIP_NONE;	return MU_CLIP_PART;}  static voidpush_layout(mu_Rect body, Point scroll){	mu_Layout layout;	int width = 0;	memset(&layout, 0, sizeof(mu_Layout));	layout.body = mu_rect(body.x - scroll.x, body.y - scroll.y, body.w, body.h);	layout.max = Pt(-0x1000000, -0x1000000);	buffer_grow(&mu_ctx.layouts, sizeof(*mu_ctx.layouts), &mu_ctx.layoutsmax, mu_ctx.layoutsnum);	mu_ctx.layouts[mu_ctx.layoutsnum++] = layout;	mu_layout_row(1, &width, 0);} static mu_Layout *get_layout(void){	return &mu_ctx.layouts[mu_ctx.layoutsnum - 1];}  static voidpush_container(mu_Container *cnt){	buffer_grow(&mu_ctx.cnt, sizeof(*mu_ctx.cnt), &mu_ctx.cntmax, mu_ctx.cntnum);	mu_ctx.cnt[mu_ctx.cntnum++] = cnt;	mu_push_id(&cnt, sizeof(mu_Container*));}  static voidpop_container(void){	mu_Container *cnt = mu_get_container();	mu_Layout *layout = get_layout();	cnt->content_size.x = layout->max.x - layout->body.x;	cnt->content_size.y = layout->max.y - layout->body.y;	mu_ctx.cntnum--;	mu_ctx.layoutsnum--;	mu_pop_id();}  mu_Container *mu_get_container(void){	assert(mu_ctx.cntnum > 0);	return mu_ctx.cnt[mu_ctx.cntnum - 1];}  voidmu_init_window(mu_Container *cnt, int opt){	memset(cnt, 0, sizeof(*cnt));	cnt->inited = 1;	cnt->open = opt & MU_OPT_CLOSED ? 0 : 1;	cnt->rect = mu_rect(100, 100, 300, 300);	mu_bring_to_front(cnt);}  voidmu_bring_to_front(mu_Container *cnt){	cnt->zindex = ++mu_ctx.last_zindex;}  /*============================================================================** input handlers**============================================================================*/ voidmu_input_mousemove(int x, int y){	mu_ctx.mouse_pos = Pt(x, y);}  voidmu_input_mousedown(int x, int y, int btn){	mu_input_mousemove(x, y);	mu_ctx.mouse_down |= btn;	mu_ctx.mouse_pressed |= btn;}  voidmu_input_mouseup(int x, int y, int btn){	mu_input_mousemove(x, y);	mu_ctx.mouse_down &= ~btn;}  voidmu_input_scroll(int x, int y){	mu_ctx.scroll_delta.x += x;	mu_ctx.scroll_delta.y += y;}  voidmu_input_keydown(int key){	mu_ctx.key_pressed |= key;	mu_ctx.key_down |= key;}  voidmu_input_keyup(int key){	mu_ctx.key_down &= ~key;}  voidmu_input_text(const char *text){	int len = strlen(mu_ctx.text_input);	int size = strlen(text) + 1;	assert(len + size <= (int) sizeof(mu_ctx.text_input));	memcpy(mu_ctx.text_input + len, text, size);} /*============================================================================** commandlist**============================================================================*/ mu_Command *mu_push_command(int type){	mu_Command *cmd; 	buffer_grow(&mu_ctx.cmds, sizeof(mu_Command), &mu_ctx.cmdsmax, mu_ctx.cmdsnum);	cmd = &mu_ctx.cmds[mu_ctx.cmdsnum++];	memset(cmd, 0, sizeof(*cmd));	cmd->type = type; 	return cmd;} static intpush_jump(int dst){

Lines 1–500 of 1503.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t