layout actually works now
This commit is contained in:
parent
869c7871f9
commit
db63b2c6b1
@ -25,57 +25,51 @@ fn ElemEvents? Ctx.button_id(&ctx, Id id, String label, String icon)
|
||||
|
||||
ushort min_size = style.size;
|
||||
ushort half_lh = (ushort)(ctx.font.line_height() / 2);
|
||||
ushort left_pad = label != "" ? half_lh : 0;
|
||||
ushort inner_pad = label != "" && icon != "" ? half_lh : 0;
|
||||
ushort right_pad = left_pad;
|
||||
|
||||
/* |left_pad
|
||||
* +--v-----------------------------------+
|
||||
* |<->+--------+ |
|
||||
/*
|
||||
* +--------------------------------------+
|
||||
* | +--------+ |
|
||||
* | | | +-----------------+ |
|
||||
* | | icon | | label | |
|
||||
* | | | +-----------------+ |
|
||||
* | +--------+<->| |<->|
|
||||
* +-------------^--------------------^---+
|
||||
* |inner_pad |right_pad
|
||||
* | +--------+<->| |
|
||||
* +-------------^------------------------+
|
||||
* |inner_pad
|
||||
*/
|
||||
|
||||
elem.layout.w = {
|
||||
.min = (short)max(min_size, left_pad + icon_size.w + inner_pad + text_size.width.min + right_pad),
|
||||
.max = (short)max(min_size, left_pad + icon_size.w + inner_pad + text_size.width.max + right_pad),
|
||||
Point content_size = {
|
||||
.x = icon_size.w + inner_pad, // text sizing is handled differently
|
||||
.y = icon_size.h + inner_pad,
|
||||
};
|
||||
elem.layout.h = {
|
||||
.min = (short)max(min_size, left_pad + icon_size.h + text_size.height.min + right_pad),
|
||||
.max = (short)max(min_size, left_pad + icon_size.w + text_size.height.max + right_pad),
|
||||
};
|
||||
// add style border and padding
|
||||
//elem.layout.w = @fit(min_size);
|
||||
elem.layout.w = @fit(min_size);
|
||||
elem.layout.h = @fit(min_size);
|
||||
elem.layout.children.w = @exact(content_size.x);
|
||||
elem.layout.children.h = @exact(content_size.y);
|
||||
elem.layout.text = text_size;
|
||||
elem.layout.content_offset = style.margin + style.border + style.padding;
|
||||
|
||||
elem.layout.children.w = elem.layout.w;
|
||||
elem.layout.children.h = elem.layout.h;
|
||||
|
||||
update_parent_grow(elem, parent);
|
||||
update_parent_size(elem, parent);
|
||||
|
||||
elem.events = ctx.get_elem_events(elem);
|
||||
Rect content_bounds = elem.content_bounds();
|
||||
|
||||
Rect text_bounds = {
|
||||
.x = content_bounds.x + icon_size.w + left_pad + inner_pad,
|
||||
.y = content_bounds.y,
|
||||
.w = content_bounds.w - icon_size.w - left_pad - inner_pad - right_pad,
|
||||
.h = content_bounds.h
|
||||
};
|
||||
//text_bounds = text_size.center_to(text_bounds);
|
||||
|
||||
|
||||
Rect icon_bounds = {
|
||||
.x = content_bounds.x,
|
||||
.y = content_bounds.y,
|
||||
.w = icon_size.w + right_pad + inner_pad,
|
||||
.h = (short)max(icon_size.h, content_bounds.h)
|
||||
.w = icon_size.w,
|
||||
.h = icon_size.h
|
||||
};
|
||||
icon_bounds = icon_size.center_to(icon_bounds);
|
||||
|
||||
Rect text_bounds = {
|
||||
.x = content_bounds.x + icon_bounds.w + inner_pad,
|
||||
.y = content_bounds.y,
|
||||
.w = content_bounds.w - icon_bounds.w - inner_pad,
|
||||
.h = content_bounds.h,
|
||||
};
|
||||
//text_bounds = text_size.center_to(text_bounds);
|
||||
|
||||
bool is_active = ctx.elem_focus(elem) || elem.events.mouse_hover;
|
||||
Style s = *style;
|
||||
if (is_active) {
|
||||
@ -88,8 +82,7 @@ fn ElemEvents? Ctx.button_id(&ctx, Id id, String label, String icon)
|
||||
ctx.push_sprite(icon_bounds, sprite.uv(), ctx.sprite_atlas.id, parent.div.z_index, type: sprite.type)!;
|
||||
}
|
||||
if (label != "") {
|
||||
ctx.push_rect(text_bounds, parent.div.z_index, &&{.bg=0xff0000abu.@to_rgba()})!;
|
||||
ctx.push_string(text_bounds, label, parent.div.z_index, style.fg)!;
|
||||
ctx.push_string(text_bounds, label, parent.div.z_index, style.fg, true)!;
|
||||
}
|
||||
return elem.events;
|
||||
}
|
||||
|
@ -335,6 +335,7 @@ fn Rect? Ctx.get_text_bounds(&ctx, String text)
|
||||
|
||||
struct TextSize {
|
||||
Size width, height;
|
||||
int area;
|
||||
}
|
||||
|
||||
// Measeure the size of a string.
|
||||
@ -393,8 +394,12 @@ fn TextSize? Ctx.measure_string(&ctx, String text)
|
||||
word_width = 0;
|
||||
words++;
|
||||
default:
|
||||
word_width += gp.w + gp.ox;
|
||||
if (off < text.len) word_width += gp.adv;
|
||||
//word_width += gp.w + gp.ox;
|
||||
if (off < text.len) {
|
||||
word_width += gp.adv;
|
||||
} else {
|
||||
word_width += gp.w + gp.ox;
|
||||
}
|
||||
}
|
||||
}
|
||||
// end of string is also end of word
|
||||
@ -403,6 +408,7 @@ fn TextSize? Ctx.measure_string(&ctx, String text)
|
||||
ts.width.max = bounds.w;
|
||||
ts.height.min = bounds.h;
|
||||
ts.height.max = words * line_height + line_gap * (words-1);
|
||||
ts.area = bounds.w * bounds.h;
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ struct Layout {
|
||||
struct children { // the children size includes the children's margin/border/pading
|
||||
Size w, h;
|
||||
}
|
||||
TextSize text;
|
||||
ushort grow_children;
|
||||
short occupied;
|
||||
struct origin {
|
||||
@ -51,6 +52,32 @@ macro Size Layout.total_height(&el)
|
||||
return {.min = min.h, .max = max.h};
|
||||
}
|
||||
|
||||
// Returns the width and height of a @FIT() element based on it's wanted size (min/max)
|
||||
// and the content size, this function is used to both update the parent's children size and
|
||||
// give the dimensions of a fit element
|
||||
macro Point Layout.get_dimensions(&el)
|
||||
{
|
||||
Size content_width = el.children.w + el.text.width;
|
||||
Size width = el.w.combine(content_width);
|
||||
short final_width = width.greater();
|
||||
|
||||
short text_height;
|
||||
if (el.text.area != 0) {
|
||||
short text_width = (@exact(final_width) - el.children.w).combine(el.text.width).min;
|
||||
text_height = @exact((short)(el.text.area / text_width)).combine(el.text.height).min;
|
||||
}
|
||||
|
||||
Size content_height = el.children.h + @exact(text_height);
|
||||
Size height = el.h.combine(content_height);
|
||||
short final_height = height.greater();
|
||||
|
||||
Point dim = {
|
||||
.x = final_width + el.content_offset.x + el.content_offset.w,
|
||||
.y = final_height + el.content_offset.y + el.content_offset.h,
|
||||
};
|
||||
return dim;
|
||||
}
|
||||
|
||||
// The content space of the element
|
||||
macro Point Elem.content_space(&e)
|
||||
{
|
||||
@ -76,14 +103,16 @@ fn void update_parent_size(Elem* child, Elem* parent)
|
||||
{
|
||||
Layout* cl = &child.layout;
|
||||
Layout* pl = &parent.layout;
|
||||
|
||||
Point child_size = cl.get_dimensions();
|
||||
|
||||
switch (pl.dir) {
|
||||
case ROW: // on rows grow the ch width by the child width and only grow ch height if it exceeds
|
||||
pl.children.w += cl.total_width();
|
||||
pl.children.h = pl.children.h.comb_max(cl.total_height());
|
||||
pl.children.w += @exact(child_size.x);
|
||||
pl.children.h = pl.children.h.comb_max(@exact(child_size.y));
|
||||
case COLUMN: // do the opposite on column
|
||||
pl.children.w = pl.children.w.comb_max(cl.total_width());
|
||||
pl.children.h += cl.total_height();
|
||||
pl.children.w = pl.children.w.comb_max(@exact(child_size.x));
|
||||
pl.children.h += @exact(child_size.y);
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,7 +149,10 @@ fn void resolve_dimensions(Elem* e, Elem* p)
|
||||
{
|
||||
Layout* el = &e.layout;
|
||||
Layout* pl = &p.layout;
|
||||
|
||||
Point elem_dimensions = el.get_dimensions();
|
||||
|
||||
short text_min_height;
|
||||
// ASSIGN WIDTH
|
||||
switch {
|
||||
case el.w.@is_exact():
|
||||
@ -130,16 +162,7 @@ fn void resolve_dimensions(Elem* e, Elem* p)
|
||||
// done in another pass
|
||||
break;
|
||||
case el.w.@is_fit(): // fit the element's children
|
||||
Size elem_width = el.w; // the element's content width
|
||||
Size children_width = el.children.w; // element children (content) width
|
||||
Size combined = elem_width.combine(children_width);
|
||||
|
||||
if (combined.min <= combined.max) { // OK!
|
||||
// the final element width is the content width plus padding and border
|
||||
e.bounds.w = min(elem_width.max, children_width.max) + el.content_offset.x + el.content_offset.w;
|
||||
} else {
|
||||
unreachable("Cannot fit children width: min:%d max:%d", combined.min, combined.max);
|
||||
}
|
||||
e.bounds.w = elem_dimensions.x;
|
||||
default: unreachable("width is not exact, grow or fit");
|
||||
}
|
||||
|
||||
@ -152,16 +175,7 @@ fn void resolve_dimensions(Elem* e, Elem* p)
|
||||
break;
|
||||
// done in another pass
|
||||
case el.h.@is_fit(): // fit the element's children
|
||||
Size elem_height = el.h; // the element's content width
|
||||
Size children_height = el.children.h; // element children (content) width
|
||||
Size combined = elem_height.combine(children_height);
|
||||
|
||||
if (combined.min <= combined.max) { // OK!
|
||||
// the final element width is the content width plus padding and border
|
||||
e.bounds.h = min(elem_height.max, children_height.max) + el.content_offset.y + el.content_offset.h;
|
||||
} else {
|
||||
unreachable("Cannot fit children height: min:%d max:%d", combined.min, combined.max);
|
||||
}
|
||||
e.bounds.h = elem_dimensions.y;
|
||||
default: unreachable("width is not exact, grow or fit");
|
||||
}
|
||||
|
||||
|
@ -247,7 +247,8 @@ struct Size {
|
||||
|
||||
macro Size @grow() => {.min = 0, .max = 0};
|
||||
macro Size @exact(short s) => {.min = s, .max = s};
|
||||
macro Size @fit(short min = 0, short max = short.max/2) => {.min = min, .max = max};
|
||||
// PROBLEM WE ARE OVERFLOWING
|
||||
macro Size @fit(short min = 0, short max = 999) => {.min = min, .max = max};
|
||||
macro bool Size.@is_grow(s) => (s.min == 0 && s.max == 0);
|
||||
macro bool Size.@is_exact(s) => (s.min == s.max && s.min != 0);
|
||||
macro bool Size.@is_fit(s) => (s.min != s.max);
|
||||
@ -258,3 +259,5 @@ macro Size Size.sub(a, Size b) @operator_s(-) => {.min = a.min-b.min, .max = a.m
|
||||
macro Size Size.combine(a, Size b) => {.min = max(a.min, b.min), .max = min(a.max, b.max)};
|
||||
macro Size Size.comb_max(a, Size b) => {.min = max(a.min, b.min), .max = max(a.max, b.max)};
|
||||
macro Size Size.comb_min(a, Size b) => {.min = min(a.min, b.min), .max = min(a.max, b.max)};
|
||||
|
||||
macro short Size.greater(a) => a.min > a.max ? a.min : a.max;
|
||||
|
@ -2,9 +2,9 @@ default {
|
||||
bg: #282828ff;
|
||||
fg: #fbf1c7ff;
|
||||
primary: #cc241dff;
|
||||
secondary: #458588ff;
|
||||
secondary: #6c19ca8f;
|
||||
accent: #fabd2fff;
|
||||
border: 0;
|
||||
border: 1;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
92
src/main.c3
92
src/main.c3
@ -363,54 +363,54 @@ fn void calculator(ugui::Ctx* ui)
|
||||
}
|
||||
|
||||
// ui input/output
|
||||
ui.@div(ugui::@grow(), ugui::@grow(), ROW, CENTER) {
|
||||
ui.@div(ugui::@grow(), ugui::@grow(), ROW, CENTER) { // center everything on the screen
|
||||
ui.@div(ugui::@fit(), ugui::@fit(), COLUMN, TOP_LEFT) {
|
||||
|
||||
/*
|
||||
ui.@div({0,0,250,50}) {
|
||||
ui.text_unbounded((String)buffer[:len])!!;
|
||||
ui.@div(ugui::@grow(), ugui::@exact(100), ROW, RIGHT) {
|
||||
ui.button("TODO")!!;
|
||||
}!!;
|
||||
*/
|
||||
|
||||
ui.@div(ugui::@fit(), ugui::@fit(), COLUMN) {
|
||||
ui.button("7")!!.mouse_press ? buffer[len++] = '7' : 0;
|
||||
ui.button("4")!!.mouse_press ? buffer[len++] = '4' : 0;
|
||||
ui.button("1")!!.mouse_press ? buffer[len++] = '1' : 0;
|
||||
ui.button("0")!!.mouse_press ? buffer[len++] = '0' : 0;
|
||||
}!!;
|
||||
ui.@div(ugui::@fit(), ugui::@fit(), COLUMN) {
|
||||
ui.button("8")!!.mouse_press ? buffer[len++] = '8' : 0;
|
||||
ui.button("5")!!.mouse_press ? buffer[len++] = '5' : 0;
|
||||
ui.button("2")!!.mouse_press ? buffer[len++] = '2' : 0;
|
||||
ui.button(".")!!.mouse_press ? buffer[len++] = '.' : 0;
|
||||
}!!;
|
||||
ui.@div(ugui::@fit(), ugui::@fit(), COLUMN) {
|
||||
ui.button("9")!!.mouse_press ? buffer[len++] = '9' : 0;
|
||||
ui.button("6")!!.mouse_press ? buffer[len++] = '6' : 0;
|
||||
ui.button("3")!!.mouse_press ? buffer[len++] = '3' : 0;
|
||||
ui.button("(")!!.mouse_press ? buffer[len++] = '(' : 0;
|
||||
}!!;
|
||||
|
||||
ui.@div(ugui::@exact(10), ugui::@exact(10)) {}!!;
|
||||
|
||||
ui.@div(ugui::@fit(), ugui::@fit(), COLUMN) {
|
||||
ui.button("x")!!.mouse_press ? buffer[len++] = '*' : 0;
|
||||
ui.button("/")!!.mouse_press ? buffer[len++] = '/' : 0;
|
||||
ui.button("+")!!.mouse_press ? buffer[len++] = '+' : 0;
|
||||
ui.button(")")!!.mouse_press ? buffer[len++] = ')' : 0;
|
||||
}!!;
|
||||
ui.@div(ugui::@fit(), ugui::@fit(), COLUMN) {
|
||||
ui.button("C")!!.mouse_press ? len = 0 : 0;
|
||||
ui.button("D")!!.mouse_press ? len-- : 0;
|
||||
ui.button("-")!!.mouse_press ? buffer[len++] = '-' : 0;
|
||||
ui.@div(ugui::@fit(), ugui::@fit(), ROW, TOP_LEFT) {
|
||||
ui.@div(ugui::@fit(), ugui::@fit(), COLUMN) {
|
||||
ui.button("7")!!.mouse_press ? buffer[len++] = '7' : 0;
|
||||
ui.button("4")!!.mouse_press ? buffer[len++] = '4' : 0;
|
||||
ui.button("1")!!.mouse_press ? buffer[len++] = '1' : 0;
|
||||
ui.button("0")!!.mouse_press ? buffer[len++] = '0' : 0;
|
||||
}!!;
|
||||
ui.@div(ugui::@fit(), ugui::@fit(), COLUMN) {
|
||||
ui.button("8")!!.mouse_press ? buffer[len++] = '8' : 0;
|
||||
ui.button("5")!!.mouse_press ? buffer[len++] = '5' : 0;
|
||||
ui.button("2")!!.mouse_press ? buffer[len++] = '2' : 0;
|
||||
ui.button(".")!!.mouse_press ? buffer[len++] = '.' : 0;
|
||||
}!!;
|
||||
ui.@div(ugui::@fit(), ugui::@fit(), COLUMN) {
|
||||
ui.button("9")!!.mouse_press ? buffer[len++] = '9' : 0;
|
||||
ui.button("6")!!.mouse_press ? buffer[len++] = '6' : 0;
|
||||
ui.button("3")!!.mouse_press ? buffer[len++] = '3' : 0;
|
||||
ui.button("(")!!.mouse_press ? buffer[len++] = '(' : 0;
|
||||
}!!;
|
||||
|
||||
ui.@div(ugui::@exact(10), ugui::@exact(10)) {}!!;
|
||||
|
||||
// eval the expression with 'bc'
|
||||
if (ui.button("=")!!.mouse_press || eval) {
|
||||
char[128] out;
|
||||
String y = string::tformat("echo '%s' | bc", (String)buffer[:len]);
|
||||
String x = process::execute_stdout_to_buffer(out[:128], (String[]){"sh", "-c", y}) ?? "";
|
||||
buffer[:x.len] = x[..];
|
||||
len = x.len;
|
||||
}
|
||||
ui.@div(ugui::@fit(), ugui::@fit(), COLUMN) {
|
||||
ui.button("x")!!.mouse_press ? buffer[len++] = '*' : 0;
|
||||
ui.button("/")!!.mouse_press ? buffer[len++] = '/' : 0;
|
||||
ui.button("+")!!.mouse_press ? buffer[len++] = '+' : 0;
|
||||
ui.button(")")!!.mouse_press ? buffer[len++] = ')' : 0;
|
||||
}!!;
|
||||
ui.@div(ugui::@fit(), ugui::@fit(), COLUMN) {
|
||||
ui.button("C")!!.mouse_press ? len = 0 : 0;
|
||||
ui.button("D")!!.mouse_press ? len-- : 0;
|
||||
ui.button("-")!!.mouse_press ? buffer[len++] = '-' : 0;
|
||||
|
||||
// eval the expression with 'bc'
|
||||
if (ui.button("=")!!.mouse_press || eval) {
|
||||
char[128] out;
|
||||
String y = string::tformat("echo '%s' | bc", (String)buffer[:len]);
|
||||
String x = process::execute_stdout_to_buffer(out[:128], (String[]){"sh", "-c", y}) ?? "";
|
||||
buffer[:x.len] = x[..];
|
||||
len = x.len;
|
||||
}
|
||||
}!!;
|
||||
}!!;
|
||||
}!!;
|
||||
}!!; }!!;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user