SectrPrototype/code/ui_layout.odin
2024-03-12 20:55:29 -04:00

146 lines
3.4 KiB
Odin

package sectr
ui_compute_layout :: proc()
{
profile(#procedure)
state := get_state()
root := state.project.workspace.ui.root
{
computed := & root.computed
bounds := & computed.bounds
style := root.style
layout := & style.layout
bounds.min = layout.pos
bounds.max = layout.size
computed.content = bounds^
computed.padding = {}
}
current := root.first
for ; current != nil;
{
profile("Layout Box")
parent := current.parent
parent_content := parent.computed.content
computed := & current.computed
style := current.style
layout := & style.layout
margins := range2(
{ layout.margins.left, -layout.margins.top },
{ -layout.margins.right, layout.margins.bottom },
)
margined_bounds := range2(
parent_content.p0 + margins.p0,
parent_content.p1 + margins.p1,
)
margined_size := margined_bounds.p1 - margined_bounds.p0
anchored_bounds := range2(
margined_bounds.p0 + margined_size * layout.anchor.p0,
margined_bounds.p0 + margined_size * layout.anchor.p1,
)
anchored_size := Vec2 {
anchored_bounds.max.x - anchored_bounds.min.x,
anchored_bounds.max.y - anchored_bounds.min.y,
}
anchor := & layout.anchor
pos : Vec2
if UI_StyleFlag.Fixed_Position_X in style.flags {
pos.x = layout.pos.x
pos.x += anchored_bounds.p0.x
}
if UI_StyleFlag.Fixed_Position_Y in style.flags {
pos.y = layout.pos.y
pos.y += anchored_bounds.p0.y
}
text_size : Vec2
// If the computed matches, we alreayd have the size, don't bother.
// if computed.text_size.y == style.font_size {
if current.first_frame || ! style.size_to_text || computed.text_size.y != size_range2(computed.bounds).y {
text_size = cast(Vec2) measure_text_size( current.text.str, style.font, style.font_size, 0 )
}
else {
text_size = computed.text_size
}
size : Vec2
if UI_StyleFlag.Fixed_Width in style.flags {
size.x = layout.size.x
}
else {
size.x = anchored_size.x
}
if UI_StyleFlag.Fixed_Height in style.flags {
size.y = layout.size.y
}
else {
size.y = anchored_size.y
}
if style.size_to_text {
size = text_size
}
half_size := size * 0.5
size_bounds := range2(
Vec2 {},
{ size.x, -size.y },
)
aligned_bounds := range2(
size_bounds.p0 + size * { -layout.alignment.x, layout.alignment.y },
size_bounds.p1 - size * { layout.alignment.x, -layout.alignment.y },
)
bounds := & computed.bounds
(bounds^) = aligned_bounds
(bounds^) = range2(
pos + aligned_bounds.p0,
pos + aligned_bounds.p1,
)
border_offset := Vec2 { layout.border_width, layout.border_width }
padding := & computed.padding
(padding^) = range2(
bounds.p0 + border_offset,
bounds.p1 + border_offset,
)
content := & computed.content
(content^) = range2(
bounds.p0 + { layout.padding.left, -layout.padding.top },
bounds.p1 + { -layout.padding.right, layout.padding.bottom },
)
// Text
if len(current.text.str) > 0
{
// profile("Text")
top_left := content.p0
bottom_right := content.p1
content_size := Vec2 { top_left.x - bottom_right.x, top_left.y - bottom_right.y }
text_pos : Vec2
text_pos = top_left
text_pos.x += (-content_size.x - text_size.x) * layout.text_alignment.x
text_pos.y += (-content_size.y + text_size.y) * layout.text_alignment.y
computed.text_size = text_size
computed.text_pos = { text_pos.x, -text_pos.y }
}
current = ui_box_tranverse_next( current )
}
}