Last active
June 14, 2022 01:35
-
-
Save vurtun/65fdc6ef77dd85706ec08ed153a3f929 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
enum gui_lay_type { | |
GUI_LAY_ROW, | |
GUI_LAY_COL | |
}; | |
struct gui_lay { | |
struct gui_box box; /* in */ | |
/* internal */ | |
enum gui_lay_type type; | |
struct gui_box sub; | |
int idx, cnt; | |
int gap[2], item; | |
}; | |
static void | |
gui__lay_init(struct gui_ctx *ctx, struct gui_lay *lay, | |
enum gui_lay_type, int cnt, int item, | |
int row_gap, int col_gap) { | |
lay->idx = lay->cnt = cnt; | |
lay->gap[0] = (col_gap < 0) ? ctx->cfg.gap; | |
lay->gap[1] = (row_gap < 0) ? ctx->cfg.gap; | |
lay->item = item < 0 ? ctx->cfg.item : item; | |
lay->type = type; | |
} | |
static int | |
gui__hlay(struct gui_ctx *ctx, struct gui_lay *lay, int *items, | |
const int *def, int cnt, int row_h, int row_gap, int col_gap, | |
const int *con, struct gui_sol *sol) { | |
gui__lay_init(ctx, lay, GUI_LAY_ROW, cnt, item, row_gap, col_gap); | |
return gui_solve(items, lay->box.x.ext, def, cnt, col_gap, con, sol); | |
} | |
static int | |
gui__vlay(struct gui_ctx *ctx, struct gui_lay *lay, int *items, | |
const int *def, int cnt, int col_w, int row_gap, int col_gap, | |
const int *con, struct gui_sol *sol) { | |
gui__lay_init(ctx, lay, GUI_LAY_COL, cnt, item, row_gap, col_gap); | |
return gui_solve(items, lay->box.y.ext, def, cnt, col_gap, con, sol); | |
} | |
static struct gui_box | |
gui_hlay_cut(struct gui_lay *lay, int row_h) { | |
lay->idx = lay->cnt; | |
return gui_cut_top(&lay->box, row_h, lay->gap[1]); | |
} | |
static struct gui_box | |
gui_hlay_cut(struct gui_lay *lay, int col_w) { | |
lay->idx = lay->cnt; | |
return gui_cut_lhs(&lay->box, col_w, lay->gap[0]); | |
} | |
static struct gui_box | |
gui_hlay_item(struct gui_lay *lay, const int *items) { | |
if (lay->idx >= lay->cnt) { | |
lay->sub = gui_cut_top(&lay->box, lay->item, lay->gap[1]); | |
lay->idx = 0; | |
} | |
return gui_cut_lhs(&lay->sub, items[lay->idx++], lay->gap[0]); | |
} | |
static struct gui_box | |
gui_vlay_item(struct gui_lay *lay, const int *items) { | |
if (lay->idx >= lay->cnt) { | |
lay->sub = gui_cut_lhs(&lay->box, lay->item, lay->gap[0]); | |
lay->idx = 0; | |
} | |
return gui_cut_top(&lay->sub, items[lay->idx++], lay->gap[1]); | |
} | |
static struct gui_box | |
gui_lay_item(struct gui_lay *lay, const int *items) { | |
switch (lay->type) { | |
case GUI_LAY_ROW: return gui_layh_item(lay, items); | |
case GUI_LAY_COL: return gui_layv_item(lay, items); | |
} | |
} | |
#define gui_row(lay, row, def, gap, con, sol) \ | |
for (int lay[cntof((int[])def)], \ | |
uniqid(_i_) = (gui_solve(lay, (row).x.ext, (int[])def, cntof((int[])def), gap, (int[])con, sol), 0); \ | |
uniqid(_i_) < 1; ++uniqid(_i_)) | |
#define gui_hlay(ctx, items, lay, def, row_h, row_gap, col_gap, con, sol)\ | |
for (int items[cntof((int[])def)], \ | |
uniqid(_i_) = (gui__hlay(ctx, lay, items, def, cntof(def), row_h, row_gap, col_gap, con, sol), 0); \ | |
uniqid(_i_) < 1; ++uniqid(_i_)) | |
#define gui_vlay(ctx, items, lay, def, col_w, row_gap, col_gap, con, sol)\ | |
for (int items[cntof((int[])def)], \ | |
uniqid(_i_) = (gui__vlay(ctx, lay, items, def, cntof(def), col_w, row_gap, col_gap, con, sol), 0); \ | |
uniqid(_i_) < 1; ++uniqid(_i_)) | |
// first base version with direct call to `gui_solve` and layouting via cut API. | |
// `gui_solve` takes definitions array (positive numbers for fixed pixel and negative values | |
// for dynamic weights) and optional constraints array (min,max per element) in pixel. | |
static const int lay_def[] = {-1, -1}; | |
static const int lay_con[] = {50,400, 50,400}; | |
struct gui_panel lay = pan->box; | |
{ | |
int items[cntof(lay_def)]; | |
struct gui_box row = gui_cut_top(&lay, -1, -1); | |
gui_solve(items, row.x.ext, lay_def, cntof(lay_def), -1, lay_con, 0) | |
{ | |
int idx = 0; | |
struct gui_panel lbl = {.box = gui_cut_lhs(&row, items[idx++], -1)}; | |
gui_txt(ctx, &lbl, "Import:"); | |
struct gui_btn btn = {.box = gui_cut_lhs(&row, items[idx++], -1)}; | |
if (gui_btn_txt(ctx, &btn, "Button")) { | |
} | |
} | |
{ | |
int idx = 0; | |
struct gui_panel lbl = {.box = gui_cut_lhs(&row, items[idx++], -1)}; | |
gui_txt(ctx, &lbl, "Value:"); | |
struct gui_spin spin = {.box = gui_cut_lhs(&row, items[idx++], -1)}; | |
gui_spin_i(ctx, &spin, 0, &val, 100); | |
} | |
} | |
// second version abstracting `gui_solve` using `gui_row` macro while | |
// still using cut API | |
static const int lay_def[] = {-1, -1}; | |
static const int lay_con[] = {50,400, 50,400}; | |
struct gui_panel lay = pan->box; | |
{ | |
struct gui_box row = gui_cut_top(&lay, -1, -1); | |
gui_row(ctx, items, idx, row, lay_def, -1, lay_con) { | |
struct gui_panel lbl = {.box = gui_cut_lhs(&row, items[idx++], -1)}; | |
gui_txt(ctx, &lbl, "Import:"); | |
struct gui_btn btn = {.box = gui_cut_lhs(&row, items[idx++], -1)}; | |
if (gui_btn_txt(ctx, &btn, "Button")) { | |
} | |
} | |
row = gui_cut_top(&lay, -1, -1); | |
gui_row(ctx, items, idx, row, lay_def, -1, lay_con) { | |
struct gui_panel lbl = {.box = gui_cut_lhs(&row, items[idx++], -1)}; | |
gui_txt(ctx, &lbl, "Value:"); | |
struct gui_spin spin = {.box = gui_cut_lhs(&row, items[idx++], -1)}; | |
gui_spin_i(ctx, &spin, 0, &val, 100); | |
} | |
} | |
// third version with additional abstraction `gui_hlay`. No more cutting | |
// but still using a struct for each widget call | |
struct gui_lay lay = {.box = pan->box}; | |
gui_hlay(ctx, items, lay, (int[]){-1, -1}, -1, (int[]){50,400, 50,400}) { | |
struct gui_panel lbl = {.box = gui_lay_item(&lay, items)}; | |
gui_txt(ctx, &lbl, "Import:"); | |
struct gui_btn btn = {.box = gui_lay_item(&lay, items)}; | |
if (gui_btn_txt(ctx, &btn, "Button")) { | |
} | |
struct gui_panel lbl = {.box = gui_lay_item(&lay, items)}; | |
gui_txt(ctx, &lbl, "Value:"); | |
struct gui_spin spin = {.box = gui_lay_item(&lay, items)}; | |
gui_spin_i(ctx, &spin, 0, &val, 100); | |
} | |
// nuklear version using single widget per line | |
struct gui_lay lay = {.box = pan->box}; | |
gui_hlay(ctx, items, &lay, (int[]){-1, -1}, -1, -1, -1, (int[]){50,400, 50,400}) { | |
// first row | |
gui_hlay_txt(ctx, &lay, items, "Import:"); | |
if (gui_hlay_btn(ctx, &lay, items, "Button")) { | |
} | |
// second row | |
gui_hlay_txt(ctx, &lay, items, "Value:"); | |
if (gui_hlay_spin_i(ctx, &lay, items, 0, &val, 100)) { | |
} | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment