Compare commits
3 Commits
be1476d107
...
df18be7bf6
Author | SHA1 | Date | |
---|---|---|---|
df18be7bf6 | |||
48d1b29537 | |||
915f395b5a |
@ -309,9 +309,18 @@ fn Rect? Ctx.layout_string(&ctx, String text, Rect bounds, Anchor anchor, int z_
|
|||||||
short line_height = (short)font.line_height();
|
short line_height = (short)font.line_height();
|
||||||
Rect cursor_rect = {.h = line_height};
|
Rect cursor_rect = {.h = line_height};
|
||||||
|
|
||||||
if (text == "" || bounds.w <= 0 || bounds.h <= 0) return cursor_rect;
|
if (bounds.w <= 0 || bounds.h <= 0) return cursor_rect;
|
||||||
ctx.push_scissor(bounds, z_index)!;
|
ctx.push_scissor(bounds, z_index)!;
|
||||||
|
|
||||||
|
if (text == "") {
|
||||||
|
// when text is empty but we need to draw a cursor use a visually empty string
|
||||||
|
if (cursor >= 0) {
|
||||||
|
text = "\f";
|
||||||
|
} else {
|
||||||
|
return cursor_rect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Id texture_id = font.id;
|
Id texture_id = font.id;
|
||||||
short baseline = (short)font.ascender;
|
short baseline = (short)font.ascender;
|
||||||
short line_gap = (short)font.linegap;
|
short line_gap = (short)font.linegap;
|
||||||
@ -356,6 +365,7 @@ fn Rect? Ctx.layout_string(&ctx, String text, Rect bounds, Anchor anchor, int z_
|
|||||||
|
|
||||||
switch {
|
switch {
|
||||||
case cp == '\n':
|
case cp == '\n':
|
||||||
|
off += x;
|
||||||
break ITER;
|
break ITER;
|
||||||
case cp == '\t':
|
case cp == '\t':
|
||||||
o.x += tab_width;
|
o.x += tab_width;
|
||||||
@ -377,28 +387,42 @@ fn Rect? Ctx.layout_string(&ctx, String text, Rect bounds, Anchor anchor, int z_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
line_end = off;
|
line_end = off;
|
||||||
if (line_end == line_start) break;
|
if (line_end == line_start) unreachable("something went wrong in measuring the line");
|
||||||
|
|
||||||
// with the line width calculate the right origin and layout the line
|
// with the line width calculate the right origin and layout the line
|
||||||
origin.x = bounds.x;
|
origin.x = bounds.x;
|
||||||
|
short next_line_x = bounds.x; // the x coordinate of the origin if the line_width is zero
|
||||||
switch (anchor) {
|
switch (anchor) {
|
||||||
case TOP_LEFT: nextcase;
|
case TOP_LEFT: nextcase;
|
||||||
case LEFT: nextcase;
|
case LEFT: nextcase;
|
||||||
case BOTTOM_LEFT:
|
case BOTTOM_LEFT:
|
||||||
// TODO: we didn't need to measure the line width with this alignment
|
// TODO: we didn't need to measure the line width with this alignment
|
||||||
origin.x += 0;
|
origin.x += 0;
|
||||||
|
next_line_x += 0;
|
||||||
case TOP: nextcase;
|
case TOP: nextcase;
|
||||||
case CENTER: nextcase;
|
case CENTER: nextcase;
|
||||||
case BOTTOM:
|
case BOTTOM:
|
||||||
origin.x += (short)(bounds.w - line_width)/2+1;
|
origin.x += (short)(bounds.w - line_width)/2+1;
|
||||||
|
next_line_x += bounds.w/2;
|
||||||
case TOP_RIGHT: nextcase;
|
case TOP_RIGHT: nextcase;
|
||||||
case RIGHT: nextcase;
|
case RIGHT: nextcase;
|
||||||
case BOTTOM_RIGHT:
|
case BOTTOM_RIGHT:
|
||||||
origin.x += (short)(bounds.w - line_width);
|
origin.x += (short)(bounds.w - line_width);
|
||||||
|
next_line_x += bounds.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor_rect.x = origin.x;
|
// reset the cursor to the line
|
||||||
cursor_rect.y = origin.y;
|
if (line_start <= cursor && cursor <= line_end) {
|
||||||
|
cursor_rect.x = origin.x;
|
||||||
|
cursor_rect.y = origin.y;
|
||||||
|
cursor_rect.w = 0;
|
||||||
|
if (cursor && text[cursor-1] == '\n') {
|
||||||
|
cursor_rect.x = next_line_x;
|
||||||
|
cursor_rect.y += line_height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Point line_origin = origin;
|
||||||
|
|
||||||
// see the fixme when measuring the height
|
// see the fixme when measuring the height
|
||||||
//ctx.push_rect({.x = origin.x,.y=origin.y,.w=(short)line_width,.h=(short)string_height}, z_index, &&(Style){.bg=0xff000042u.@to_rgba()})!;
|
//ctx.push_rect({.x = origin.x,.y=origin.y,.w=(short)line_width,.h=(short)string_height}, z_index, &&(Style){.bg=0xff000042u.@to_rgba()})!;
|
||||||
@ -407,7 +431,6 @@ fn Rect? Ctx.layout_string(&ctx, String text, Rect bounds, Anchor anchor, int z_
|
|||||||
for (usz x; (cp = str_to_codepoint(line[off..], &x)) != 0 && off < line.len; off += x) {
|
for (usz x; (cp = str_to_codepoint(line[off..], &x)) != 0 && off < line.len; off += x) {
|
||||||
Glyph* gp = font.get_glyph(cp)!;
|
Glyph* gp = font.get_glyph(cp)!;
|
||||||
|
|
||||||
// update the text bounds
|
|
||||||
switch {
|
switch {
|
||||||
case cp == '\t':
|
case cp == '\t':
|
||||||
origin.x += tab_width;
|
origin.x += tab_width;
|
||||||
@ -428,16 +451,17 @@ fn Rect? Ctx.layout_string(&ctx, String text, Rect bounds, Anchor anchor, int z_
|
|||||||
};
|
};
|
||||||
ctx.push_sprite(b, uv, texture_id, z_index, hue)!;
|
ctx.push_sprite(b, uv, texture_id, z_index, hue)!;
|
||||||
//ctx.push_rect(b, z_index, &&(Style){.bg=0x0000ff66u.@to_rgba()})!;
|
//ctx.push_rect(b, z_index, &&(Style){.bg=0x0000ff66u.@to_rgba()})!;
|
||||||
|
|
||||||
if (line_start + off < cursor) {
|
|
||||||
cursor_rect.x = origin.x + gp.adv;
|
|
||||||
cursor_rect.y = origin.y;
|
|
||||||
cursor_rect.w = gp.adv;
|
|
||||||
}
|
|
||||||
|
|
||||||
origin.x += gp.adv;
|
origin.x += gp.adv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (line_start + off < cursor && text[cursor-1] != '\n') {
|
||||||
|
cursor_rect.x = origin.x;
|
||||||
|
cursor_rect.y = origin.y;
|
||||||
|
cursor_rect.w = gp.adv;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// done with the line
|
// done with the line
|
||||||
line_start = line_end;
|
line_start = line_end;
|
||||||
origin.y += line_height + line_gap;
|
origin.y += line_height + line_gap;
|
||||||
|
@ -31,8 +31,12 @@ struct Layout {
|
|||||||
struct origin {
|
struct origin {
|
||||||
short x, y;
|
short x, y;
|
||||||
}
|
}
|
||||||
LayoutDirection dir;
|
// false: the element is laid out according to the parent
|
||||||
Anchor anchor;
|
// true: the element is laid out separate from all other children and the relative position to
|
||||||
|
// the parent is the .origin field
|
||||||
|
bool absolute;
|
||||||
|
LayoutDirection dir; // the direction the children are laid out
|
||||||
|
Anchor anchor; // how the children are positioned
|
||||||
Rect content_offset; // combined effect of margin, border and padding
|
Rect content_offset; // combined effect of margin, border and padding
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,6 +116,9 @@ 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;
|
||||||
|
|
||||||
|
// if the element has absolute position do not update the parent
|
||||||
|
if (cl.absolute) return;
|
||||||
|
|
||||||
Point child_size = cl.get_dimensions();
|
Point child_size = cl.get_dimensions();
|
||||||
|
|
||||||
switch (pl.dir) {
|
switch (pl.dir) {
|
||||||
@ -163,6 +170,9 @@ fn void resolve_dimensions(Elem* e, Elem* p)
|
|||||||
Point elem_dimensions = el.get_dimensions();
|
Point elem_dimensions = el.get_dimensions();
|
||||||
e.bounds.w = elem_dimensions.x;
|
e.bounds.w = elem_dimensions.x;
|
||||||
e.bounds.h = elem_dimensions.y;
|
e.bounds.h = elem_dimensions.y;
|
||||||
|
|
||||||
|
// if the element has absolute position do not update the parent
|
||||||
|
if (el.absolute) return;
|
||||||
|
|
||||||
switch (pl.dir) {
|
switch (pl.dir) {
|
||||||
case ROW:
|
case ROW:
|
||||||
@ -209,6 +219,13 @@ fn void resolve_placement(Elem* c, Elem* p)
|
|||||||
.y = p.bounds.y + pl.origin.y + pl.content_offset.y,
|
.y = p.bounds.y + pl.origin.y + pl.content_offset.y,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// if the element has absolute position assign the origin and do not update the parent
|
||||||
|
if (cl.absolute) {
|
||||||
|
c.bounds.x = p.bounds.x + pl.content_offset.x + cl.origin.x;
|
||||||
|
c.bounds.y = p.bounds.x + pl.content_offset.x + cl.origin.y;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (pl.anchor) {
|
switch (pl.anchor) {
|
||||||
case TOP_LEFT:
|
case TOP_LEFT:
|
||||||
c.bounds.x = off.x;
|
c.bounds.x = off.x;
|
||||||
|
@ -25,12 +25,13 @@ macro Ctx.@div(&ctx,
|
|||||||
Size width = @grow, Size height = @grow,
|
Size width = @grow, Size height = @grow,
|
||||||
LayoutDirection dir = ROW,
|
LayoutDirection dir = ROW,
|
||||||
Anchor anchor = TOP_LEFT,
|
Anchor anchor = TOP_LEFT,
|
||||||
|
bool absolute = false, Point off = {},
|
||||||
bool scroll_x = false, bool scroll_y = false,
|
bool scroll_x = false, bool scroll_y = false,
|
||||||
...;
|
...;
|
||||||
@body()
|
@body()
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ctx.div_begin(width, height, dir, anchor, scroll_x, scroll_y, $vasplat)!;
|
ctx.div_begin(width, height, dir, anchor, absolute, off, scroll_x, scroll_y, $vasplat)!;
|
||||||
@body();
|
@body();
|
||||||
return ctx.div_end()!;
|
return ctx.div_end()!;
|
||||||
}
|
}
|
||||||
@ -39,11 +40,12 @@ macro Ctx.div_begin(&ctx,
|
|||||||
Size width = @grow(), Size height = @grow(),
|
Size width = @grow(), Size height = @grow(),
|
||||||
LayoutDirection dir = ROW,
|
LayoutDirection dir = ROW,
|
||||||
Anchor anchor = TOP_LEFT,
|
Anchor anchor = TOP_LEFT,
|
||||||
|
bool absolute = false, Point off = {},
|
||||||
bool scroll_x = false, bool scroll_y = false,
|
bool scroll_x = false, bool scroll_y = false,
|
||||||
...
|
...
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return ctx.div_begin_id(@compute_id($vasplat), width, height, dir, anchor, scroll_x, scroll_y);
|
return ctx.div_begin_id(@compute_id($vasplat), width, height, dir, anchor, absolute, off, scroll_x, scroll_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn void? Ctx.div_begin_id(&ctx,
|
fn void? Ctx.div_begin_id(&ctx,
|
||||||
@ -51,6 +53,7 @@ fn void? Ctx.div_begin_id(&ctx,
|
|||||||
Size width, Size height,
|
Size width, Size height,
|
||||||
LayoutDirection dir,
|
LayoutDirection dir,
|
||||||
Anchor anchor,
|
Anchor anchor,
|
||||||
|
bool absolute, Point off,
|
||||||
bool scroll_x, bool scroll_y
|
bool scroll_x, bool scroll_y
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -75,7 +78,12 @@ fn void? Ctx.div_begin_id(&ctx,
|
|||||||
.dir = dir,
|
.dir = dir,
|
||||||
.anchor = anchor,
|
.anchor = anchor,
|
||||||
.content_offset = style.margin + style.border + style.padding,
|
.content_offset = style.margin + style.border + style.padding,
|
||||||
|
.absolute = absolute,
|
||||||
};
|
};
|
||||||
|
if (absolute) {
|
||||||
|
elem.layout.origin.x = off.x;
|
||||||
|
elem.layout.origin.y = off.y;
|
||||||
|
}
|
||||||
|
|
||||||
ctx.push_rect(elem.bounds.pad(style.margin), elem.div.z_index, style)!;
|
ctx.push_rect(elem.bounds.pad(style.margin), elem.div.z_index, style)!;
|
||||||
|
|
||||||
|
@ -76,14 +76,11 @@ fn ElemEvents? Ctx.text_box_id(&ctx, Id id, Size w, Size h, TextEdit* te)
|
|||||||
cur = ctx.layout_string(elem.text.te.to_string(), text_bounds, TOP_LEFT, parent.div.z_index, style.fg, elem.text.te.cursor)!;
|
cur = ctx.layout_string(elem.text.te.to_string(), text_bounds, TOP_LEFT, parent.div.z_index, style.fg, elem.text.te.cursor)!;
|
||||||
|
|
||||||
// draw the cursor if the element has focus
|
// draw the cursor if the element has focus
|
||||||
|
cur.w = 2;
|
||||||
if (elem.events.has_focus) {
|
if (elem.events.has_focus) {
|
||||||
cur.w = 2;
|
ctx.push_scissor(text_bounds, parent.div.z_index)!;
|
||||||
// FIXME: gross hack for when text is empty
|
|
||||||
if (cur.x == 0 && cur.y == 0) {
|
|
||||||
cur.x = text_bounds.x;
|
|
||||||
cur.y = text_bounds.y;
|
|
||||||
}
|
|
||||||
ctx.push_rect(cur, parent.div.z_index, &&(Style){.bg = style.fg})!;
|
ctx.push_rect(cur, parent.div.z_index, &&(Style){.bg = style.fg})!;
|
||||||
|
ctx.reset_scissor(parent.div.z_index)!;
|
||||||
}
|
}
|
||||||
return elem.events;
|
return elem.events;
|
||||||
}
|
}
|
22
src/main.c3
22
src/main.c3
@ -52,6 +52,9 @@ const char[*] FS_PATH = "resources/shaders/compiled/ugui.frag.spv";
|
|||||||
|
|
||||||
const char[*] STYLESHEET_PATH = "resources/style.css";
|
const char[*] STYLESHEET_PATH = "resources/style.css";
|
||||||
|
|
||||||
|
const bool LIMIT_FPS = false;
|
||||||
|
const bool VSYNC = false;
|
||||||
|
|
||||||
fn int main(String[] args)
|
fn int main(String[] args)
|
||||||
{
|
{
|
||||||
ArenaAllocator arena;
|
ArenaAllocator arena;
|
||||||
@ -64,7 +67,7 @@ fn int main(String[] args)
|
|||||||
defer ui.free();
|
defer ui.free();
|
||||||
|
|
||||||
ren::Renderer ren;
|
ren::Renderer ren;
|
||||||
ren.init("Ugui Test", 800, 600, true);
|
ren.init("Ugui Test", 800, 600, VSYNC);
|
||||||
defer ren.free();
|
defer ren.free();
|
||||||
ui.input_window_size(800, 600)!!;
|
ui.input_window_size(800, 600)!!;
|
||||||
|
|
||||||
@ -216,15 +219,10 @@ $endswitch
|
|||||||
TimeStats dts = draw_times.get_stats();
|
TimeStats dts = draw_times.get_stats();
|
||||||
TimeStats uts = ui_times.get_stats();
|
TimeStats uts = ui_times.get_stats();
|
||||||
|
|
||||||
/*
|
ui.@div(ugui::@fit(), ugui::@fit(), COLUMN, TOP_LEFT, true) {
|
||||||
ui.layout_set_floating()!!;
|
ui.text(string::tformat("frame %d, fps = %.2f", frame, fps))!!;
|
||||||
ui.@div({0, ui.height-150, -300, 150}) {
|
ui.text(string::tformat("ui avg: %s\ndraw avg: %s\nTOT: %s", uts.avg, dts.avg, uts.avg+dts.avg))!!;
|
||||||
ui.layout_set_column()!!;
|
|
||||||
ui.text_unbounded(string::tformat("frame %d, fps = %.2f", frame, fps))!!;
|
|
||||||
ui.text_unbounded(string::tformat("ui avg: %s\ndraw avg: %s\nTOT: %s", uts.avg, dts.avg, uts.avg+dts.avg))!!;
|
|
||||||
ui.text_unbounded(string::tformat("%s %s", mod.lctrl, (String)ui.input.keyboard.text[:ui.input.keyboard.text_len]))!!;
|
|
||||||
}!!;
|
}!!;
|
||||||
*/
|
|
||||||
|
|
||||||
ui.frame_end()!!;
|
ui.frame_end()!!;
|
||||||
/* End UI Handling */
|
/* End UI Handling */
|
||||||
@ -243,8 +241,8 @@ $endswitch
|
|||||||
/* End Drawing */
|
/* End Drawing */
|
||||||
|
|
||||||
// wait for the next event, timeout after 100ms
|
// wait for the next event, timeout after 100ms
|
||||||
|
int timeout = LIMIT_FPS ? (int)(100.0-sleep_clock.mark().to_ms()-0.5) : 0;
|
||||||
sdl::wait_event_timeout(&e, (int)(100.0-sleep_clock.mark().to_ms()-0.5));
|
sdl::wait_event_timeout(&e, timeout);
|
||||||
|
|
||||||
fps = 1.0 / fps_clock.mark().to_sec();
|
fps = 1.0 / fps_clock.mark().to_sec();
|
||||||
frame++;
|
frame++;
|
||||||
@ -356,7 +354,7 @@ fn void calculator(ugui::Ctx* ui, TextEdit* te)
|
|||||||
case "9":
|
case "9":
|
||||||
buffer[len++] = ui.get_keys()[0];
|
buffer[len++] = ui.get_keys()[0];
|
||||||
case "\n":
|
case "\n":
|
||||||
eval = true;
|
eval = len != 0;
|
||||||
case "c":
|
case "c":
|
||||||
len = 0;
|
len = 0;
|
||||||
case "d":
|
case "d":
|
||||||
|
Loading…
x
Reference in New Issue
Block a user