Skip to content

Instantly share code, notes, and snippets.

@vurtun
Last active June 14, 2022 01:35
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vurtun/65fdc6ef77dd85706ec08ed153a3f929 to your computer and use it in GitHub Desktop.
Save vurtun/65fdc6ef77dd85706ec08ed153a3f929 to your computer and use it in GitHub Desktop.
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