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 min_size = style.size;
|
||||||
ushort half_lh = (ushort)(ctx.font.line_height() / 2);
|
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 inner_pad = label != "" && icon != "" ? half_lh : 0;
|
||||||
ushort right_pad = left_pad;
|
/*
|
||||||
|
* +--------------------------------------+
|
||||||
/* |left_pad
|
* | +--------+ |
|
||||||
* +--v-----------------------------------+
|
|
||||||
* |<->+--------+ |
|
|
||||||
* | | | +-----------------+ |
|
* | | | +-----------------+ |
|
||||||
* | | icon | | label | |
|
* | | icon | | label | |
|
||||||
* | | | +-----------------+ |
|
* | | | +-----------------+ |
|
||||||
* | +--------+<->| |<->|
|
* | +--------+<->| |
|
||||||
* +-------------^--------------------^---+
|
* +-------------^------------------------+
|
||||||
* |inner_pad |right_pad
|
* |inner_pad
|
||||||
*/
|
*/
|
||||||
|
Point content_size = {
|
||||||
elem.layout.w = {
|
.x = icon_size.w + inner_pad, // text sizing is handled differently
|
||||||
.min = (short)max(min_size, left_pad + icon_size.w + inner_pad + text_size.width.min + right_pad),
|
.y = icon_size.h + inner_pad,
|
||||||
.max = (short)max(min_size, left_pad + icon_size.w + inner_pad + text_size.width.max + right_pad),
|
|
||||||
};
|
};
|
||||||
elem.layout.h = {
|
//elem.layout.w = @fit(min_size);
|
||||||
.min = (short)max(min_size, left_pad + icon_size.h + text_size.height.min + right_pad),
|
elem.layout.w = @fit(min_size);
|
||||||
.max = (short)max(min_size, left_pad + icon_size.w + text_size.height.max + right_pad),
|
elem.layout.h = @fit(min_size);
|
||||||
};
|
elem.layout.children.w = @exact(content_size.x);
|
||||||
// add style border and padding
|
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.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_grow(elem, parent);
|
||||||
update_parent_size(elem, parent);
|
update_parent_size(elem, parent);
|
||||||
|
|
||||||
elem.events = ctx.get_elem_events(elem);
|
elem.events = ctx.get_elem_events(elem);
|
||||||
Rect content_bounds = elem.content_bounds();
|
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 = {
|
Rect icon_bounds = {
|
||||||
.x = content_bounds.x,
|
.x = content_bounds.x,
|
||||||
.y = content_bounds.y,
|
.y = content_bounds.y,
|
||||||
.w = icon_size.w + right_pad + inner_pad,
|
.w = icon_size.w,
|
||||||
.h = (short)max(icon_size.h, content_bounds.h)
|
.h = icon_size.h
|
||||||
};
|
};
|
||||||
icon_bounds = icon_size.center_to(icon_bounds);
|
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;
|
bool is_active = ctx.elem_focus(elem) || elem.events.mouse_hover;
|
||||||
Style s = *style;
|
Style s = *style;
|
||||||
if (is_active) {
|
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)!;
|
ctx.push_sprite(icon_bounds, sprite.uv(), ctx.sprite_atlas.id, parent.div.z_index, type: sprite.type)!;
|
||||||
}
|
}
|
||||||
if (label != "") {
|
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, true)!;
|
||||||
ctx.push_string(text_bounds, label, parent.div.z_index, style.fg)!;
|
|
||||||
}
|
}
|
||||||
return elem.events;
|
return elem.events;
|
||||||
}
|
}
|
||||||
|
@ -335,6 +335,7 @@ fn Rect? Ctx.get_text_bounds(&ctx, String text)
|
|||||||
|
|
||||||
struct TextSize {
|
struct TextSize {
|
||||||
Size width, height;
|
Size width, height;
|
||||||
|
int area;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Measeure the size of a string.
|
// Measeure the size of a string.
|
||||||
@ -393,8 +394,12 @@ fn TextSize? Ctx.measure_string(&ctx, String text)
|
|||||||
word_width = 0;
|
word_width = 0;
|
||||||
words++;
|
words++;
|
||||||
default:
|
default:
|
||||||
word_width += gp.w + gp.ox;
|
//word_width += gp.w + gp.ox;
|
||||||
if (off < text.len) word_width += gp.adv;
|
if (off < text.len) {
|
||||||
|
word_width += gp.adv;
|
||||||
|
} else {
|
||||||
|
word_width += gp.w + gp.ox;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// end of string is also end of word
|
// 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.width.max = bounds.w;
|
||||||
ts.height.min = bounds.h;
|
ts.height.min = bounds.h;
|
||||||
ts.height.max = words * line_height + line_gap * (words-1);
|
ts.height.max = words * line_height + line_gap * (words-1);
|
||||||
|
ts.area = bounds.w * bounds.h;
|
||||||
|
|
||||||
return ts;
|
return ts;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ struct Layout {
|
|||||||
struct children { // the children size includes the children's margin/border/pading
|
struct children { // the children size includes the children's margin/border/pading
|
||||||
Size w, h;
|
Size w, h;
|
||||||
}
|
}
|
||||||
|
TextSize text;
|
||||||
ushort grow_children;
|
ushort grow_children;
|
||||||
short occupied;
|
short occupied;
|
||||||
struct origin {
|
struct origin {
|
||||||
@ -51,6 +52,32 @@ macro Size Layout.total_height(&el)
|
|||||||
return {.min = min.h, .max = max.h};
|
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
|
// The content space of the element
|
||||||
macro Point Elem.content_space(&e)
|
macro Point Elem.content_space(&e)
|
||||||
{
|
{
|
||||||
@ -76,14 +103,16 @@ fn void update_parent_size(Elem* child, Elem* parent)
|
|||||||
{
|
{
|
||||||
Layout* cl = &child.layout;
|
Layout* cl = &child.layout;
|
||||||
Layout* pl = &parent.layout;
|
Layout* pl = &parent.layout;
|
||||||
|
|
||||||
|
Point child_size = cl.get_dimensions();
|
||||||
|
|
||||||
switch (pl.dir) {
|
switch (pl.dir) {
|
||||||
case ROW: // on rows grow the ch width by the child width and only grow ch height if it exceeds
|
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.w += @exact(child_size.x);
|
||||||
pl.children.h = pl.children.h.comb_max(cl.total_height());
|
pl.children.h = pl.children.h.comb_max(@exact(child_size.y));
|
||||||
case COLUMN: // do the opposite on column
|
case COLUMN: // do the opposite on column
|
||||||
pl.children.w = pl.children.w.comb_max(cl.total_width());
|
pl.children.w = pl.children.w.comb_max(@exact(child_size.x));
|
||||||
pl.children.h += cl.total_height();
|
pl.children.h += @exact(child_size.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +149,10 @@ fn void resolve_dimensions(Elem* e, Elem* p)
|
|||||||
{
|
{
|
||||||
Layout* el = &e.layout;
|
Layout* el = &e.layout;
|
||||||
Layout* pl = &p.layout;
|
Layout* pl = &p.layout;
|
||||||
|
|
||||||
|
Point elem_dimensions = el.get_dimensions();
|
||||||
|
|
||||||
|
short text_min_height;
|
||||||
// ASSIGN WIDTH
|
// ASSIGN WIDTH
|
||||||
switch {
|
switch {
|
||||||
case el.w.@is_exact():
|
case el.w.@is_exact():
|
||||||
@ -130,16 +162,7 @@ fn void resolve_dimensions(Elem* e, Elem* p)
|
|||||||
// done in another pass
|
// done in another pass
|
||||||
break;
|
break;
|
||||||
case el.w.@is_fit(): // fit the element's children
|
case el.w.@is_fit(): // fit the element's children
|
||||||
Size elem_width = el.w; // the element's content width
|
e.bounds.w = elem_dimensions.x;
|
||||||
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);
|
|
||||||
}
|
|
||||||
default: unreachable("width is not exact, grow or fit");
|
default: unreachable("width is not exact, grow or fit");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,16 +175,7 @@ fn void resolve_dimensions(Elem* e, Elem* p)
|
|||||||
break;
|
break;
|
||||||
// done in another pass
|
// done in another pass
|
||||||
case el.h.@is_fit(): // fit the element's children
|
case el.h.@is_fit(): // fit the element's children
|
||||||
Size elem_height = el.h; // the element's content width
|
e.bounds.h = elem_dimensions.y;
|
||||||
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);
|
|
||||||
}
|
|
||||||
default: unreachable("width is not exact, grow or fit");
|
default: unreachable("width is not exact, grow or fit");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,7 +247,8 @@ struct Size {
|
|||||||
|
|
||||||
macro Size @grow() => {.min = 0, .max = 0};
|
macro Size @grow() => {.min = 0, .max = 0};
|
||||||
macro Size @exact(short s) => {.min = s, .max = s};
|
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_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_exact(s) => (s.min == s.max && s.min != 0);
|
||||||
macro bool Size.@is_fit(s) => (s.min != s.max);
|
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.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_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 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;
|
bg: #282828ff;
|
||||||
fg: #fbf1c7ff;
|
fg: #fbf1c7ff;
|
||||||
primary: #cc241dff;
|
primary: #cc241dff;
|
||||||
secondary: #458588ff;
|
secondary: #6c19ca8f;
|
||||||
accent: #fabd2fff;
|
accent: #fabd2fff;
|
||||||
border: 0;
|
border: 1;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 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 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(ugui::@grow(), ugui::@exact(100), ROW, RIGHT) {
|
||||||
ui.@div({0,0,250,50}) {
|
ui.button("TODO")!!;
|
||||||
ui.text_unbounded((String)buffer[:len])!!;
|
|
||||||
}!!;
|
}!!;
|
||||||
*/
|
ui.@div(ugui::@fit(), ugui::@fit(), ROW, TOP_LEFT) {
|
||||||
|
ui.@div(ugui::@fit(), ugui::@fit(), COLUMN) {
|
||||||
ui.@div(ugui::@fit(), ugui::@fit(), COLUMN) {
|
ui.button("7")!!.mouse_press ? buffer[len++] = '7' : 0;
|
||||||
ui.button("7")!!.mouse_press ? buffer[len++] = '7' : 0;
|
ui.button("4")!!.mouse_press ? buffer[len++] = '4' : 0;
|
||||||
ui.button("4")!!.mouse_press ? buffer[len++] = '4' : 0;
|
ui.button("1")!!.mouse_press ? buffer[len++] = '1' : 0;
|
||||||
ui.button("1")!!.mouse_press ? buffer[len++] = '1' : 0;
|
ui.button("0")!!.mouse_press ? buffer[len++] = '0' : 0;
|
||||||
ui.button("0")!!.mouse_press ? buffer[len++] = '0' : 0;
|
}!!;
|
||||||
}!!;
|
ui.@div(ugui::@fit(), ugui::@fit(), COLUMN) {
|
||||||
ui.@div(ugui::@fit(), ugui::@fit(), COLUMN) {
|
ui.button("8")!!.mouse_press ? buffer[len++] = '8' : 0;
|
||||||
ui.button("8")!!.mouse_press ? buffer[len++] = '8' : 0;
|
ui.button("5")!!.mouse_press ? buffer[len++] = '5' : 0;
|
||||||
ui.button("5")!!.mouse_press ? buffer[len++] = '5' : 0;
|
ui.button("2")!!.mouse_press ? buffer[len++] = '2' : 0;
|
||||||
ui.button("2")!!.mouse_press ? buffer[len++] = '2' : 0;
|
ui.button(".")!!.mouse_press ? buffer[len++] = '.' : 0;
|
||||||
ui.button(".")!!.mouse_press ? buffer[len++] = '.' : 0;
|
}!!;
|
||||||
}!!;
|
ui.@div(ugui::@fit(), ugui::@fit(), COLUMN) {
|
||||||
ui.@div(ugui::@fit(), ugui::@fit(), COLUMN) {
|
ui.button("9")!!.mouse_press ? buffer[len++] = '9' : 0;
|
||||||
ui.button("9")!!.mouse_press ? buffer[len++] = '9' : 0;
|
ui.button("6")!!.mouse_press ? buffer[len++] = '6' : 0;
|
||||||
ui.button("6")!!.mouse_press ? buffer[len++] = '6' : 0;
|
ui.button("3")!!.mouse_press ? buffer[len++] = '3' : 0;
|
||||||
ui.button("3")!!.mouse_press ? buffer[len++] = '3' : 0;
|
ui.button("(")!!.mouse_press ? buffer[len++] = '(' : 0;
|
||||||
ui.button("(")!!.mouse_press ? buffer[len++] = '(' : 0;
|
}!!;
|
||||||
}!!;
|
|
||||||
|
ui.@div(ugui::@exact(10), ugui::@exact(10)) {}!!;
|
||||||
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;
|
|
||||||
|
|
||||||
// eval the expression with 'bc'
|
ui.@div(ugui::@fit(), ugui::@fit(), COLUMN) {
|
||||||
if (ui.button("=")!!.mouse_press || eval) {
|
ui.button("x")!!.mouse_press ? buffer[len++] = '*' : 0;
|
||||||
char[128] out;
|
ui.button("/")!!.mouse_press ? buffer[len++] = '/' : 0;
|
||||||
String y = string::tformat("echo '%s' | bc", (String)buffer[:len]);
|
ui.button("+")!!.mouse_press ? buffer[len++] = '+' : 0;
|
||||||
String x = process::execute_stdout_to_buffer(out[:128], (String[]){"sh", "-c", y}) ?? "";
|
ui.button(")")!!.mouse_press ? buffer[len++] = ')' : 0;
|
||||||
buffer[:x.len] = x[..];
|
}!!;
|
||||||
len = x.len;
|
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