Large refactor of the entire codebase
Saw that layout really should be separated from the style struct, so went ahead and pulled the trigger... A bunch of other refactors have also been done * Lifted layout out of style, its not separate in UI_Box and in UI_State there is not a UI_LayoutCombo stack. * UI_StyleTheme renamed to UI_StyleCombo * UI_Theme has both UI_StyleCombo & UI_LayoutCombo * Made files for the "project" related code * ui_layout_compute moved to its own file, ui_layout now used for layout related data structures and interfacing * Impovements to horizontal & vertical box impl * UI_Box now keeps track of how many ancestors it has
This commit is contained in:
@ -47,92 +47,101 @@ ui_hbox_begin :: proc( direction : UI_LayoutDirectionX, label : string, flags :
|
||||
// profile(#procedure)
|
||||
hbox.direction = direction
|
||||
hbox.box = ui_box_make( flags, label )
|
||||
hbox.signal = ui_signal_from_box( hbox.box )
|
||||
hbox.signal = ui_signal_from_box(hbox.box)
|
||||
return
|
||||
}
|
||||
|
||||
// Auto-layout children
|
||||
ui_hbox_end :: proc( hbox : UI_HBox, width_ref : ^f32 = nil ) {
|
||||
ui_hbox_end :: proc( hbox : UI_HBox, width_ref : ^f32 = nil )
|
||||
{
|
||||
// profile(#procedure)
|
||||
hbox_width : f32
|
||||
if width_ref != nil {
|
||||
hbox_width = width_ref ^
|
||||
}
|
||||
else {
|
||||
hbox_width = hbox.computed.content.max.x - hbox.computed.content.min.x
|
||||
}
|
||||
|
||||
// do layout calculations for the children
|
||||
total_stretch_ratio : f32 = 0.0
|
||||
size_req_children : f32 = 0
|
||||
for child := hbox.first; child != nil; child = child.next
|
||||
// ui_box_compute_layout(hox.widget)
|
||||
|
||||
// ui_layout_children_horizontally( & hbox.box, hbox.direction, width_ref )
|
||||
{
|
||||
using child
|
||||
using style.layout
|
||||
scaled_width_by_height : b32 = b32(.Scale_Width_By_Height_Ratio in style.flags)
|
||||
if .Fixed_Width in style.flags
|
||||
{
|
||||
if scaled_width_by_height {
|
||||
height := size.max.y != 0 ? size.max.y : hbox_width
|
||||
width := height * size.min.x
|
||||
hbox_width : f32
|
||||
if width_ref != nil {
|
||||
hbox_width = width_ref ^
|
||||
}
|
||||
else {
|
||||
hbox_width = hbox.computed.content.max.x - hbox.computed.content.min.x
|
||||
}
|
||||
|
||||
size_req_children += width
|
||||
// do layout calculations for the children
|
||||
total_stretch_ratio : f32 = 0.0
|
||||
size_req_children : f32 = 0
|
||||
for child := hbox.first; child != nil; child = child.next
|
||||
{
|
||||
using child.layout
|
||||
scaled_width_by_height : b32 = b32(.Scale_Width_By_Height_Ratio in flags)
|
||||
if .Fixed_Width in flags
|
||||
{
|
||||
if scaled_width_by_height {
|
||||
height := size.max.y != 0 ? size.max.y : hbox_width
|
||||
width := height * size.min.x
|
||||
|
||||
size_req_children += width
|
||||
continue
|
||||
}
|
||||
|
||||
size_req_children += size.min.x
|
||||
continue
|
||||
}
|
||||
|
||||
size_req_children += size.min.x
|
||||
continue
|
||||
total_stretch_ratio += anchor.ratio.x
|
||||
}
|
||||
|
||||
total_stretch_ratio += anchor.ratio.x
|
||||
}
|
||||
avail_flex_space := hbox_width - size_req_children
|
||||
|
||||
avail_flex_space := hbox_width - size_req_children
|
||||
|
||||
allocate_space :: proc( child : ^UI_Box, total_stretch_ratio, avail_flex_space : f32 )
|
||||
{
|
||||
using child.style
|
||||
if ! (.Fixed_Width in child.style.flags) {
|
||||
size.min.x = anchor.ratio.x * (1 / total_stretch_ratio) * avail_flex_space
|
||||
allocate_space :: proc( child : ^UI_Box, total_stretch_ratio, avail_flex_space : f32 )
|
||||
{
|
||||
using child.layout
|
||||
if ! (.Fixed_Width in flags) {
|
||||
size.min.x = anchor.ratio.x * (1 / total_stretch_ratio) * avail_flex_space
|
||||
}
|
||||
flags |= {.Fixed_Width}
|
||||
}
|
||||
|
||||
space_used : f32 = 0.0
|
||||
switch hbox.direction{
|
||||
case .Right_To_Left:
|
||||
for child := hbox.last; child != nil; child = child.prev {
|
||||
allocate_space(child, total_stretch_ratio, avail_flex_space)
|
||||
using child.layout
|
||||
anchor = range2({0, 0}, {0, 0})
|
||||
alignment = { 0, 1 }// - hbox.layout.alignment
|
||||
pos.x = space_used
|
||||
space_used += size.min.x
|
||||
size.min.y = hbox.computed.content.max.y - hbox.computed.content.min.y
|
||||
}
|
||||
case .Left_To_Right:
|
||||
for child := hbox.first; child != nil; child = child.next {
|
||||
allocate_space(child, total_stretch_ratio, avail_flex_space)
|
||||
using child.layout
|
||||
anchor = range2({0, 0}, {0, 0})
|
||||
alignment = { 0, 1 }
|
||||
pos.x = space_used
|
||||
space_used += size.min.x
|
||||
size.min.y = hbox.computed.content.max.y - hbox.computed.content.min.y
|
||||
}
|
||||
}
|
||||
flags |= {.Fixed_Width}
|
||||
alignment = {0, 1}
|
||||
}
|
||||
|
||||
space_used : f32 = 0.0
|
||||
switch hbox.direction{
|
||||
case .Right_To_Left:
|
||||
for child := hbox.last; child != nil; child = child.prev {
|
||||
allocate_space(child, total_stretch_ratio, avail_flex_space)
|
||||
using child.style
|
||||
anchor = range2({0, 0}, {0, 0})
|
||||
pos.x = space_used
|
||||
space_used += size.min.x
|
||||
}
|
||||
case .Left_To_Right:
|
||||
for child := hbox.first; child != nil; child = child.next {
|
||||
allocate_space(child, total_stretch_ratio, avail_flex_space)
|
||||
using child.style
|
||||
anchor = range2({0, 0}, {0, 0})
|
||||
pos.x = space_used
|
||||
space_used += size.min.x
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@(deferred_out = ui_hbox_end_auto)
|
||||
ui_hbox :: #force_inline proc( direction : UI_LayoutDirectionX, label : string, flags : UI_BoxFlags = {} ) -> (hbox : UI_HBox) {
|
||||
hbox = ui_hbox_begin(direction, label, flags)
|
||||
ui_parent_push(hbox.box)
|
||||
return
|
||||
}
|
||||
|
||||
// Auto-layout children and pop parent from parent stack
|
||||
ui_hbox_end_pop_parent :: proc( hbox : UI_HBox ) {
|
||||
// ui_box_compute_layout(hox.widget)
|
||||
ui_hbox_end_auto :: proc( hbox : UI_HBox ) {
|
||||
ui_parent_pop()
|
||||
ui_hbox_end(hbox)
|
||||
}
|
||||
|
||||
@(deferred_out = ui_hbox_end_pop_parent)
|
||||
ui_hbox :: #force_inline proc( direction : UI_LayoutDirectionX, label : string, flags : UI_BoxFlags = {} ) -> (hbox : UI_HBox) {
|
||||
hbox = ui_hbox_begin(direction, label, flags)
|
||||
ui_parent_push(hbox.widget)
|
||||
return
|
||||
}
|
||||
//endregion Horizontal Box
|
||||
|
||||
// Adds resizable handles to a widget
|
||||
@ -164,23 +173,26 @@ ui_resizable_handles :: proc( parent : ^UI_Widget,
|
||||
ui_parent(parent)
|
||||
flags := UI_BoxFlags { .Mouse_Clickable, .Focusable }
|
||||
|
||||
style_bar := UI_Style {
|
||||
layout_bar_width := UI_Layout {
|
||||
flags = { .Fixed_Width },
|
||||
size = range2({handle_width, 0}, {}),
|
||||
bg_color = Color_ResizeHandle,
|
||||
alignment = {1, 1},
|
||||
margins = { handle_width, handle_width, 0, 0 },
|
||||
size = range2({handle_width, 0}, {}),
|
||||
}
|
||||
style_bar := UI_Style {
|
||||
bg_color = Color_ResizeHandle,
|
||||
corner_radii = { 5, 0, 0, 0 }
|
||||
}
|
||||
theme_bar := to_ui_styletheme(style_bar)
|
||||
theme_bar := to_ui_style_combo(style_bar)
|
||||
theme_bar.default.bg_color = handle_color_default
|
||||
theme_bar.default.corner_radii[0] = 0
|
||||
ui_style_theme(theme_bar)
|
||||
style_resize_height := style_bar
|
||||
style_resize_height.flags = {.Fixed_Height}
|
||||
style_resize_height.size.min = {0, handle_width}
|
||||
style_resize_height.margins = { 0, 0, handle_width, handle_width }
|
||||
style_resize_height.alignment = {0, 0}
|
||||
ui_layout(layout_bar_width)
|
||||
ui_style(theme_bar)
|
||||
layout_bar_height := layout_bar_width
|
||||
layout_bar_height.flags = {.Fixed_Height}
|
||||
layout_bar_height.size.min = {0, handle_width}
|
||||
layout_bar_height.margins = { 0, 0, handle_width, handle_width }
|
||||
layout_bar_height.alignment = {0, 0}
|
||||
|
||||
context.user_ptr = & parent.label
|
||||
name :: proc( ) -> StrRunesPair {
|
||||
@ -188,47 +200,50 @@ ui_resizable_handles :: proc( parent : ^UI_Widget,
|
||||
return str_intern(str_fmt_tmp("%v: %v", ))
|
||||
}
|
||||
|
||||
if left do handle_left = ui_widget("Settings Menu: Resize Left Border", flags )
|
||||
if left do handle_left = ui_widget("Settings Menu: Resize Left Handle", flags )
|
||||
if right {
|
||||
handle_right = ui_widget("Settings Menu: Resize Right Border", flags)
|
||||
handle_right.style.anchor.left = 1
|
||||
handle_right.style.alignment = { 0, 1 }
|
||||
handle_right = ui_widget("Settings Menu: Resize Right Handle", flags)
|
||||
handle_right.layout.anchor.left = 1
|
||||
handle_right.layout.alignment = { 0, 1 }
|
||||
}
|
||||
|
||||
ui_theme_via_style(style_resize_height)
|
||||
ui_style_theme_ref().default.bg_color = handle_color_default
|
||||
ui_layout(layout_bar_height)
|
||||
ui_style_ref().default.bg_color = handle_color_default
|
||||
if top do handle_top = ui_widget("Settings Menu: Resize Top Border", flags )
|
||||
if bottom {
|
||||
handle_bottom = ui_widget("Settings Menu: Resize Bottom Border", flags)
|
||||
handle_bottom.style.anchor.top = 1
|
||||
handle_bottom.style.alignment = { 0, 1 }
|
||||
using handle_bottom.layout
|
||||
anchor.top = 1
|
||||
alignment = { 0, 1 }
|
||||
}
|
||||
|
||||
style_corner := UI_Style {
|
||||
layout_corner := UI_Layout {
|
||||
flags = { .Fixed_Width, .Fixed_Height },
|
||||
size = range2({handle_width, handle_width}, {}),
|
||||
bg_color = Color_ResizeHandle,
|
||||
alignment = {1, 0},
|
||||
size = range2({handle_width, handle_width}, {}),
|
||||
}
|
||||
style_corner := UI_Style {
|
||||
bg_color = Color_ResizeHandle,
|
||||
corner_radii = { 5, 0, 0, 0 },
|
||||
}
|
||||
ui_theme_via_style(style_corner)
|
||||
ui_style_theme_ref().default.bg_color = handle_color_default
|
||||
ui_theme(layout_corner, style_corner)
|
||||
ui_style_ref().default.bg_color = handle_color_default
|
||||
if corner_tl do handle_corner_tl = ui_widget("Settings Menu: Corner TL", flags)
|
||||
if corner_tr {
|
||||
handle_corner_tr = ui_widget("Settings Menu: Corner TR", flags)
|
||||
handle_corner_tr.style.anchor = range2({1, 0}, {})
|
||||
handle_corner_tr.style.alignment = {0, 0}
|
||||
handle_corner_tr.layout.anchor = range2({1, 0}, {})
|
||||
handle_corner_tr.layout.alignment = {0, 0}
|
||||
}
|
||||
|
||||
if corner_bl {
|
||||
handle_corner_bl = ui_widget("Settings Menu: Corner BL", flags)
|
||||
handle_corner_bl.style.anchor = range2({}, {0, 1})
|
||||
handle_corner_bl.style.alignment = { 1, 1 }
|
||||
handle_corner_bl.layout.anchor = range2({}, {0, 1})
|
||||
handle_corner_bl.layout.alignment = { 1, 1 }
|
||||
}
|
||||
if corner_br {
|
||||
handle_corner_br = ui_widget("Settings Menu: Corner BR", flags)
|
||||
handle_corner_br.style.anchor = range2({1, 0}, {0, 1})
|
||||
handle_corner_br.style.alignment = {0, 1}
|
||||
handle_corner_br.layout.anchor = range2({1, 0}, {0, 1})
|
||||
handle_corner_br.layout.alignment = {0, 1}
|
||||
}
|
||||
|
||||
process_handle_drag :: #force_inline proc ( handle : ^UI_Widget,
|
||||
@ -268,7 +283,7 @@ ui_resizable_handles :: proc( parent : ^UI_Widget,
|
||||
}
|
||||
|
||||
delta := get_state().input.mouse.delta
|
||||
alignment := & parent.style.alignment
|
||||
alignment := & parent.layout.alignment
|
||||
if right do process_handle_drag( & handle_right, { 1, 0 }, delta, {0, 0}, pos, size, alignment )
|
||||
if left do process_handle_drag( & handle_left, { -1, 0 }, delta, {1, 0}, pos, size, alignment )
|
||||
if top do process_handle_drag( & handle_top, { 0, 1 }, delta, {0, 0}, pos, size, alignment )
|
||||
@ -363,75 +378,78 @@ ui_vbox_begin :: proc( direction : UI_LayoutDirectionY, label : string, flags :
|
||||
ui_vbox_end :: proc( vbox : UI_VBox, height_ref : ^f32 = nil ) {
|
||||
// profile(#procedure)
|
||||
|
||||
vbox_height : f32
|
||||
if height_ref != nil {
|
||||
vbox_height = height_ref ^
|
||||
}
|
||||
else {
|
||||
vbox_height = vbox.computed.bounds.max.y - vbox.computed.bounds.min.y
|
||||
}
|
||||
// ui_box_compute_layout(vbox)
|
||||
|
||||
// do layout calculations for the children
|
||||
total_stretch_ratio : f32 = 0.0
|
||||
size_req_children : f32 = 0
|
||||
for child := vbox.first; child != nil; child = child.next
|
||||
// ui_layout_children_vertically( & hbox.box, hbox.direction, width_ref )
|
||||
{
|
||||
using child
|
||||
using style.layout
|
||||
scaled_width_by_height : b32 = b32(.Scale_Width_By_Height_Ratio in style.flags)
|
||||
if .Fixed_Height in style.flags
|
||||
{
|
||||
if scaled_width_by_height {
|
||||
width := size.max.x != 0 ? size.max.x : vbox_height
|
||||
height := width * size.min.y
|
||||
vbox_height : f32
|
||||
if height_ref != nil {
|
||||
vbox_height = height_ref ^
|
||||
}
|
||||
else {
|
||||
vbox_height = vbox.computed.bounds.max.y - vbox.computed.bounds.min.y
|
||||
}
|
||||
|
||||
size_req_children += height
|
||||
// do layout calculations for the children
|
||||
total_stretch_ratio : f32 = 0.0
|
||||
size_req_children : f32 = 0
|
||||
for child := vbox.first; child != nil; child = child.next
|
||||
{
|
||||
using child.layout
|
||||
scaled_width_by_height : b32 = b32(.Scale_Width_By_Height_Ratio in flags)
|
||||
if .Fixed_Height in flags
|
||||
{
|
||||
if scaled_width_by_height {
|
||||
width := size.max.x != 0 ? size.max.x : vbox_height
|
||||
height := width * size.min.y
|
||||
|
||||
size_req_children += height
|
||||
continue
|
||||
}
|
||||
|
||||
size_req_children += size.min.y
|
||||
continue
|
||||
}
|
||||
|
||||
size_req_children += size.min.y
|
||||
continue
|
||||
total_stretch_ratio += anchor.ratio.y
|
||||
}
|
||||
|
||||
total_stretch_ratio += anchor.ratio.y
|
||||
}
|
||||
avail_flex_space := vbox_height - size_req_children
|
||||
|
||||
avail_flex_space := vbox_height - size_req_children
|
||||
|
||||
allocate_space :: proc( child : ^UI_Box, total_stretch_ratio, avail_flex_space : f32 )
|
||||
{
|
||||
using child.style
|
||||
if ! (.Fixed_Height in child.style.flags) {
|
||||
size.min.y = anchor.ratio.y * (1 / total_stretch_ratio) * avail_flex_space
|
||||
allocate_space :: proc( child : ^UI_Box, total_stretch_ratio, avail_flex_space : f32 )
|
||||
{
|
||||
using child.layout
|
||||
if ! (.Fixed_Height in flags) {
|
||||
size.min.y = anchor.ratio.y * (1 / total_stretch_ratio) * avail_flex_space
|
||||
}
|
||||
flags |= {.Fixed_Height}
|
||||
alignment = {0, 0}
|
||||
}
|
||||
flags |= {.Fixed_Height}
|
||||
alignment = {0, 0}
|
||||
}
|
||||
|
||||
space_used : f32 = 0.0
|
||||
switch vbox.direction {
|
||||
case .Top_To_Bottom:
|
||||
for child := vbox.last; child != nil; child = child.prev {
|
||||
allocate_space(child, total_stretch_ratio, avail_flex_space)
|
||||
using child.style
|
||||
anchor = range2({0, 0}, {0, 1})
|
||||
pos.y = space_used
|
||||
space_used += size.min.y
|
||||
}
|
||||
case .Bottom_To_Top:
|
||||
for child := vbox.first; child != nil; child = child.next {
|
||||
allocate_space(child, total_stretch_ratio, avail_flex_space)
|
||||
using child.style
|
||||
anchor = range2({0, 0}, {0, 1})
|
||||
pos.y = space_used
|
||||
space_used += size.min.y
|
||||
}
|
||||
space_used : f32 = 0.0
|
||||
switch vbox.direction {
|
||||
case .Top_To_Bottom:
|
||||
for child := vbox.last; child != nil; child = child.prev {
|
||||
allocate_space(child, total_stretch_ratio, avail_flex_space)
|
||||
using child.layout
|
||||
anchor = range2({0, 0}, {0, 1})
|
||||
pos.y = space_used
|
||||
space_used += size.min.y
|
||||
}
|
||||
case .Bottom_To_Top:
|
||||
for child := vbox.first; child != nil; child = child.next {
|
||||
allocate_space(child, total_stretch_ratio, avail_flex_space)
|
||||
using child.layout
|
||||
anchor = range2({0, 0}, {0, 1})
|
||||
pos.y = space_used
|
||||
space_used += size.min.y
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-layout children and pop parent from parent stack
|
||||
ui_vbox_end_pop_parent :: proc( vbox : UI_VBox ) {
|
||||
// ui_box_compute_layout(vbox)
|
||||
ui_parent_pop()
|
||||
ui_vbox_end(vbox)
|
||||
}
|
||||
|
Reference in New Issue
Block a user