Cleanup and setup of drop down widget
Got an initial variant of the drop down widget, not completely set on it.. I put some more time to figuring out how I'm going to be ideomatically constructing the widgets. screen.odin I think its getting pretty close to what it will be like. I'm ready to start lifting the input box. I'll be adding the constraints when I lift it. Added the option to toggle the debug text in screenspace Added the fixes from the ui_layout_children_horizontally for margins to ui_layout_children_vertically Known issue: There is a bug with test_whitespace that forced me todo a null check on a box. Not sure why. It needs to be redone anyway.. (compose it with the h/vboxes instead) There is some sublime files added in, started to use it.
This commit is contained in:
parent
cdfc3d65bb
commit
e5be246d30
22
Sectr.sublime-project
Normal file
22
Sectr.sublime-project
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"folders":
|
||||
[
|
||||
{
|
||||
"path": ".",
|
||||
}
|
||||
],
|
||||
"settings":
|
||||
{
|
||||
"LSP":
|
||||
{
|
||||
"ols":
|
||||
{
|
||||
"enabled": true,
|
||||
},
|
||||
"odin":
|
||||
{
|
||||
"enabled": true
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
23292
Sectr.sublime-workspace
Normal file
23292
Sectr.sublime-workspace
Normal file
File diff suppressed because it is too large
Load Diff
@ -8,6 +8,7 @@ DebugData :: struct {
|
||||
square_size : i32,
|
||||
square_pos : rl.Vector2,
|
||||
|
||||
debug_text_vis : b32,
|
||||
draw_debug_text_y : f32,
|
||||
|
||||
cursor_locked : b32,
|
||||
|
@ -20,8 +20,9 @@ UI_ScreenState :: struct
|
||||
},
|
||||
settings_menu : struct
|
||||
{
|
||||
pos, size, min_size : Vec2,
|
||||
container : UI_Widget,
|
||||
cfg_drop_down : UI_DropDown,
|
||||
pos, size, min_size : Vec2,
|
||||
is_open : b32,
|
||||
is_maximized : b32,
|
||||
},
|
||||
@ -34,21 +35,16 @@ ui_screen_tick :: proc() {
|
||||
ui_graph_build( & screen_ui )
|
||||
ui := ui_context
|
||||
|
||||
ui_floating_manager_begin( & screen_ui.floating )
|
||||
{
|
||||
ui_floating("Menu Bar", ui_screen_menu_bar)
|
||||
ui_floating("Settings Menu", ui_screen_settings_menu)
|
||||
}
|
||||
ui_floating_manager_end()
|
||||
ui_floating_manager( & screen_ui.floating )
|
||||
ui_floating("Menu Bar", ui_screen_menu_bar)
|
||||
ui_floating("Settings Menu", ui_screen_settings_menu)
|
||||
}
|
||||
|
||||
ui_screen_menu_bar :: proc( captures : rawptr = nil ) -> (should_raise : b32 = false )
|
||||
{
|
||||
profile("App Menu Bar")
|
||||
fmt :: str_fmt_alloc
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_app_menu_bar_default :: proc()
|
||||
theme_app_menu_bar :: proc() -> UI_Theme
|
||||
{
|
||||
@static theme : UI_Theme
|
||||
@static loaded : b32 = false
|
||||
@ -63,7 +59,7 @@ ui_screen_menu_bar :: proc( captures : rawptr = nil ) -> (should_raise : b32 = f
|
||||
font_size = 12,
|
||||
margins = {0, 0, 0, 0},
|
||||
padding = {0, 0, 0, 0},
|
||||
border_width = 0.6,
|
||||
border_width = 1.0,
|
||||
pos = {0, 0},
|
||||
size = range2({},{})
|
||||
}
|
||||
@ -93,58 +89,46 @@ ui_screen_menu_bar :: proc( captures : rawptr = nil ) -> (should_raise : b32 = f
|
||||
theme = UI_Theme { layout_combo, style_combo }
|
||||
loaded = true
|
||||
}
|
||||
ui_layout_push(theme.layout)
|
||||
ui_style_push(theme.style)
|
||||
return theme
|
||||
}
|
||||
|
||||
using state := get_state()
|
||||
using screen_ui
|
||||
{
|
||||
using screen_ui.menu_bar
|
||||
ui_theme_app_menu_bar_default()
|
||||
container = ui_hbox_begin( .Left_To_Right, "Menu Bar" )
|
||||
ui_parent(container)
|
||||
{
|
||||
using container
|
||||
layout.flags = {.Fixed_Position_X, .Fixed_Position_Y, .Fixed_Width, .Fixed_Height, .Origin_At_Anchor_Center}
|
||||
layout.pos = pos
|
||||
layout.size = range2( size, {})
|
||||
text = str_intern("menu_bar")
|
||||
using screen_ui.menu_bar
|
||||
|
||||
scope(theme_app_menu_bar)
|
||||
container = ui_hbox( .Left_To_Right, "Menu Bar" ); {
|
||||
using container
|
||||
layout.flags = {.Fixed_Position_X, .Fixed_Position_Y, .Fixed_Width, .Fixed_Height, .Origin_At_Anchor_Center}
|
||||
layout.pos = pos
|
||||
layout.size = range2( size, {})
|
||||
text = str_intern("menu_bar")
|
||||
}
|
||||
scope(theme_transparent)
|
||||
|
||||
move_box : UI_Widget; {
|
||||
scope(theme_button)
|
||||
move_box = ui_button("Move Box")
|
||||
using move_box
|
||||
layout.size.min.x = 20
|
||||
if active {
|
||||
pos += input.mouse.delta
|
||||
should_raise = true
|
||||
}
|
||||
}
|
||||
|
||||
ui_theme_btn()
|
||||
move_box := ui_button("Move Box");
|
||||
{
|
||||
using move_box
|
||||
if active {
|
||||
pos += input.mouse.delta
|
||||
should_raise = true
|
||||
}
|
||||
layout.anchor.ratio.x = 1.0
|
||||
}
|
||||
spacer := ui_spacer("Menu Bar: Move Spacer")
|
||||
spacer.layout.flags |= {.Fixed_Width}
|
||||
spacer.layout.size.min.x = 30
|
||||
|
||||
spacer := ui_spacer("Menu Bar: Move Spacer")
|
||||
spacer.layout.flags |= {.Fixed_Width}
|
||||
spacer.layout.size.min.x = 30
|
||||
|
||||
// TODO(Ed): Implement an external composition for theme interpolation using the settings btn
|
||||
settings_btn.widget = ui_button("Menu Bar: Settings Btn")
|
||||
{
|
||||
using settings_btn
|
||||
text = str_intern("Settings")
|
||||
layout.flags = {
|
||||
.Scale_Width_By_Height_Ratio,
|
||||
// .Fixed_Width
|
||||
}
|
||||
layout.size.ratio.x = 2.0
|
||||
if pressed {
|
||||
screen_ui.settings_menu.is_open = true
|
||||
}
|
||||
}
|
||||
spacer = ui_spacer("Menu Bar: End Spacer")
|
||||
spacer.layout.anchor.ratio.x = 2.0
|
||||
|
||||
ui_hbox_end(container, compute_layout = false)
|
||||
Build_Settings_Btn: {
|
||||
scope(theme_button)
|
||||
using settings_btn
|
||||
widget = ui_button("Menu Bar: Settings Btn")
|
||||
text = str_intern("Settings")
|
||||
layout.flags = { .Scale_Width_By_Height_Ratio }
|
||||
layout.size.ratio.x = 2.0
|
||||
if pressed do screen_ui.settings_menu.is_open = true
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -154,6 +138,7 @@ ui_screen_settings_menu :: proc( captures : rawptr = nil ) -> ( should_raise : b
|
||||
profile("Settings Menu")
|
||||
using state := get_state()
|
||||
using state.screen_ui
|
||||
|
||||
if ! settings_menu.is_open do return
|
||||
app_color := app_color_theme()
|
||||
|
||||
@ -161,169 +146,182 @@ ui_screen_settings_menu :: proc( captures : rawptr = nil ) -> ( should_raise : b
|
||||
if size.x < min_size.x do size.x = min_size.x
|
||||
if size.y < min_size.y do size.y = min_size.y
|
||||
|
||||
ui_theme_window_panel()
|
||||
container = ui_widget("Settings Menu", {}); {
|
||||
using container
|
||||
layout.flags = { .Fixed_Width, .Fixed_Height, .Fixed_Position_X, .Fixed_Position_Y, .Origin_At_Anchor_Center }
|
||||
layout.pos = pos
|
||||
layout.size = range2( size, {})
|
||||
Construct_Container:
|
||||
{
|
||||
scope(theme_window_panel)
|
||||
container = ui_widget("Settings Menu", {}); {
|
||||
using container
|
||||
layout.flags = { .Fixed_Width, .Fixed_Height, .Fixed_Position_X, .Fixed_Position_Y, .Origin_At_Anchor_Center }
|
||||
layout.pos = pos
|
||||
layout.size = range2( size, {})
|
||||
}
|
||||
if settings_menu.is_maximized {
|
||||
using container
|
||||
layout.flags = {.Origin_At_Anchor_Center }
|
||||
layout.pos = {}
|
||||
}
|
||||
|
||||
should_raise |= ui_resizable_handles( & container, & pos, & size)
|
||||
}
|
||||
ui_parent(container)
|
||||
if settings_menu.is_maximized {
|
||||
using container
|
||||
layout.flags = {.Origin_At_Anchor_Center }
|
||||
layout.pos = {}
|
||||
}
|
||||
should_raise |= ui_resizable_handles( & container, & pos, & size)
|
||||
|
||||
vbox := ui_vbox_begin( .Top_To_Bottom, "Settings Menu: VBox", {.Mouse_Clickable}, compute_layout = true)
|
||||
{
|
||||
should_raise |= b32(vbox.active)
|
||||
ui_parent(vbox)
|
||||
|
||||
ui_theme_window_bar()
|
||||
frame_bar := ui_hbox_begin(.Left_To_Right, "Settings Menu: Frame Bar", { .Mouse_Clickable })
|
||||
Frame_Bar:
|
||||
{
|
||||
ui_parent(frame_bar)
|
||||
ui_theme_text()
|
||||
title := ui_text("Settings Menu: Title", str_intern("Settings Menu"), {.Disabled}); {
|
||||
using title
|
||||
layout.anchor.ratio.x = 1.0
|
||||
layout.margins = { 0, 0, 15, 0}
|
||||
layout.font_size = 16
|
||||
}
|
||||
ui_theme_window_bar_btn()
|
||||
maximize_btn := ui_button("Settings Menu: Maximize Btn"); {
|
||||
using maximize_btn
|
||||
if maximize_btn.pressed {
|
||||
settings_menu.is_maximized = ~settings_menu.is_maximized
|
||||
should_raise = true
|
||||
scope(theme_window_bar)
|
||||
frame_bar := ui_hbox(.Left_To_Right, "Settings Menu: Frame Bar", { .Mouse_Clickable })
|
||||
{
|
||||
ui_parent(frame_bar)
|
||||
|
||||
scope(theme_text)
|
||||
title := ui_text("Settings Menu: Title", str_intern("Settings Menu"), {.Disabled}); {
|
||||
using title
|
||||
layout.anchor.ratio.x = 1.0
|
||||
layout.margins = { 0, 0, 15, 0}
|
||||
layout.font_size = 16
|
||||
}
|
||||
|
||||
scope(theme_window_bar_btn)
|
||||
maximize_btn := ui_button("Settings Menu: Maximize Btn"); {
|
||||
using maximize_btn
|
||||
if maximize_btn.pressed {
|
||||
settings_menu.is_maximized = ~settings_menu.is_maximized
|
||||
should_raise = true
|
||||
}
|
||||
if settings_menu.is_maximized do text = str_intern("min")
|
||||
else do text = str_intern("max")
|
||||
}
|
||||
close_btn := ui_button("Settings Menu: Close Btn"); {
|
||||
using close_btn
|
||||
text = str_intern("close")
|
||||
if close_btn.hot do style.bg_color = app_color.window_btn_close_bg_hot
|
||||
if close_btn.pressed do settings_menu.is_open = false
|
||||
}
|
||||
if settings_menu.is_maximized do text = str_intern("min")
|
||||
else do text = str_intern("max")
|
||||
}
|
||||
close_btn := ui_button("Settings Menu: Close Btn"); {
|
||||
using close_btn
|
||||
text = str_intern("close")
|
||||
if close_btn.hot do style.bg_color = app_color.window_btn_close_bg_hot
|
||||
if close_btn.pressed do settings_menu.is_open = false
|
||||
if frame_bar.active {
|
||||
pos += input.mouse.delta
|
||||
should_raise = true
|
||||
}
|
||||
ui_hbox_end(frame_bar, compute_layout = true)
|
||||
}
|
||||
if frame_bar.active {
|
||||
pos += input.mouse.delta
|
||||
should_raise = true
|
||||
}
|
||||
|
||||
@static config_drop_down_open := false
|
||||
ui_theme_drop_down()
|
||||
drop_down_bar := ui_hbox_begin(.Left_To_Right, "settings_menu.vbox: config drop_down_bar", {.Mouse_Clickable })
|
||||
if ui_drop_down( & cfg_drop_down, "settings_menu.config", str_intern("App Config"), vb_compute_layout = true).is_open
|
||||
{
|
||||
ui_parent_push(drop_down_bar)
|
||||
Engien_Refresh_Hz:
|
||||
{
|
||||
using drop_down_bar
|
||||
text = str_intern("drop_down_bar")
|
||||
layout.text_alignment = {1, 0}
|
||||
layout.anchor.ratio.y = 1.0
|
||||
}
|
||||
ui_theme_text()
|
||||
title := ui_text("drop_down_bar.btn", str_intern("drop_down_bar.btn")); {
|
||||
using title
|
||||
text = str_intern("App Config")
|
||||
style.text_color = drop_down_bar.style.text_color
|
||||
layout.alignment = {0.0, 0.0}
|
||||
layout.text_alignment = {0.0, 0.5}
|
||||
layout.anchor.ratio.x = 1.0
|
||||
}
|
||||
ui_parent_pop()
|
||||
ui_hbox_end(drop_down_bar, compute_layout = true)
|
||||
if drop_down_bar.pressed do config_drop_down_open = !config_drop_down_open
|
||||
}
|
||||
|
||||
if config_drop_down_open
|
||||
{
|
||||
{
|
||||
ui_theme_table_row(is_even = false)
|
||||
scope(theme_table_row(is_even = false))
|
||||
hb := ui_hbox(.Left_To_Right, "settings_menu.engine_refresh_hz.hb"); { using hb
|
||||
layout.size.min = {0, 30}
|
||||
layout.flags = {.Fixed_Height}
|
||||
layout.padding = to_ui_layout_side(4)
|
||||
layout.flags = {.Fixed_Height}
|
||||
layout.padding = to_ui_layout_side(4)
|
||||
}
|
||||
ui_theme_text(); title := ui_text("settings_menu.engine_refresh_hz.title", str_intern("Engine Refresh Hz")); { using title
|
||||
layout.anchor.ratio.x = 1.0
|
||||
layout.margins.left = 10
|
||||
layout.text_alignment = {0, 0.5}
|
||||
|
||||
title : UI_Widget; {
|
||||
scope(theme_text)
|
||||
title = ui_text("settings_menu.engine_refresh_hz.title", str_intern("Engine Refresh Hz"))
|
||||
using title
|
||||
layout.anchor.ratio.x = 1.0
|
||||
layout.margins.left = 10
|
||||
layout.text_alignment = {0, 0.5}
|
||||
}
|
||||
input_box := ui_widget("settings_menu.engine_refresh.input_box", {.Mouse_Clickable, .Focusable, .Click_To_Focus}); { using input_box
|
||||
layout.flags = {.Fixed_Width}
|
||||
layout.margins.left = 5
|
||||
layout.padding.right = 10
|
||||
layout.size.min.x = 80
|
||||
if input_box.active do style.bg_color = app_color.input_box_bg_active
|
||||
else if input_box.hot do style.bg_color = app_color.input_box_bg_hot
|
||||
else do style.bg_color = app_color.input_box_bg
|
||||
|
||||
input_box := ui_widget("settings_menu.engine_refresh.input_box", {.Mouse_Clickable, .Focusable, .Click_To_Focus}); {
|
||||
using input_box
|
||||
layout.flags = {.Fixed_Width}
|
||||
layout.margins.left = 5
|
||||
layout.padding.right = 10
|
||||
layout.size.min.x = 80
|
||||
style.corner_radii[0] = 0.35
|
||||
}
|
||||
@static value_str : Array(rune)
|
||||
if value_str.header == nil {
|
||||
error : AllocatorError
|
||||
value_str, error = array_init_reserve(rune, persistent_slab_allocator(), Kilo)
|
||||
ensure(error == AllocatorError.None, "Failed to allocate array for value_str of input_box")
|
||||
}
|
||||
if input_box.pressed {
|
||||
array_clear( value_str )
|
||||
}
|
||||
if input_box.active {
|
||||
array_append( & value_str, input.keyboard_events.chars_pressed )
|
||||
array_clear( input.keyboard_events.chars_pressed )
|
||||
}
|
||||
else if input_box.was_active {
|
||||
value, success := parse_uint(to_string(array_to_slice(value_str)))
|
||||
if success {
|
||||
config.engine_refresh_hz = value
|
||||
|
||||
if input_box.active do style.bg_color = app_color.input_box_bg_active
|
||||
else if input_box.hot do style.bg_color = app_color.input_box_bg_hot
|
||||
else do style.bg_color = app_color.input_box_bg
|
||||
|
||||
@static value_str : Array(rune)
|
||||
if value_str.header == nil {
|
||||
error : AllocatorError
|
||||
value_str, error = array_init_reserve(rune, persistent_slab_allocator(), Kilo)
|
||||
ensure(error == AllocatorError.None, "Failed to allocate array for value_str of input_box")
|
||||
}
|
||||
|
||||
if input_box.pressed {
|
||||
array_clear( value_str )
|
||||
}
|
||||
|
||||
if input_box.active {
|
||||
array_append( & value_str, input.keyboard_events.chars_pressed )
|
||||
array_clear( input.keyboard_events.chars_pressed )
|
||||
}
|
||||
else if input_box.was_active
|
||||
{
|
||||
value, success := parse_uint(to_string(array_to_slice(value_str)))
|
||||
if success {
|
||||
config.engine_refresh_hz = value
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
array_clear( value_str)
|
||||
array_append( & value_str, to_runes(str_fmt_alloc("%v", config.engine_refresh_hz)))
|
||||
}
|
||||
ui_parent(input_box)
|
||||
|
||||
value_txt : UI_Widget; {
|
||||
scope(theme_text)
|
||||
value_txt = ui_text("settings_menu.engine_refresh.input_box.value", to_str_runes_pair(array_to_slice(value_str)))
|
||||
using value_txt
|
||||
layout.alignment = {1, 0.0}
|
||||
layout.text_alignment = {0, 0.5}
|
||||
layout.anchor.left = 1.0
|
||||
layout.flags = {.Fixed_Width}
|
||||
layout.size.min = cast(Vec2) measure_text_size( value_txt.text.str, value_txt.style.font, value_txt.layout.font_size, 0 )
|
||||
}
|
||||
}
|
||||
else {
|
||||
array_clear( value_str)
|
||||
array_append( & value_str, to_runes(str_fmt_alloc("%v", config.engine_refresh_hz)))
|
||||
}
|
||||
// input_box
|
||||
{
|
||||
ui_parent(input_box)
|
||||
value_txt := ui_text("settings_menu.engine_refresh.refresh_value", to_str_runes_pair(array_to_slice(value_str)))
|
||||
value_txt.layout.text_alignment = vec2(1, 0.5)
|
||||
}
|
||||
|
||||
spacer := ui_spacer("settings_menu.engine_refresh.end_spacer")
|
||||
spacer.layout.flags = {.Fixed_Width}
|
||||
spacer.layout.size.min.x = 10
|
||||
// input_text := ui_text("settings_menu.engine_refresh", str_fmt_alloc(value_str))
|
||||
}
|
||||
|
||||
// scope(theme_transparent)
|
||||
// spacer := ui_spacer("settings_menu.engine_refresh.end_spacer")
|
||||
// spacer.layout.flags = {.Fixed_Height}
|
||||
// spacer.layout.size.min.y = 10
|
||||
|
||||
Min_Zoom:
|
||||
{
|
||||
ui_theme_table_row(is_even = true)
|
||||
hb := ui_hbox(.Left_To_Right, "settings_menu.cam_min_zoom.hb"); { using hb
|
||||
scope( theme_table_row(is_even = true))
|
||||
hb := ui_hbox(.Left_To_Right, "settings_menu.cam_min_zoom.hb"); {
|
||||
using hb
|
||||
layout.size.min = {0, 30}
|
||||
layout.flags = {.Fixed_Height}
|
||||
layout.flags = {.Fixed_Height}
|
||||
layout.padding = to_ui_layout_side(4)
|
||||
}
|
||||
ui_theme_text(); title := ui_text("settings_menu.cam_min_zoom.title", str_intern("Camera: Min Zoom")); { using title
|
||||
scope(theme_text)
|
||||
title := ui_text("settings_menu.cam_min_zoom.title", str_intern("Camera: Min Zoom")); {
|
||||
using title
|
||||
layout.anchor.ratio.x = 1.0
|
||||
layout.margins.left = 10
|
||||
}
|
||||
}
|
||||
|
||||
Max_Zoom:
|
||||
{
|
||||
ui_theme_table_row(is_even = false)
|
||||
hb := ui_hbox(.Left_To_Right, "settings_menu.cam_max_zoom.hb"); { using hb
|
||||
scope( theme_table_row(is_even = false))
|
||||
hb := ui_hbox(.Left_To_Right, "settings_menu.cam_max_zoom.hb"); {
|
||||
using hb
|
||||
layout.size.min = {0, 30}
|
||||
layout.flags = {.Fixed_Height}
|
||||
layout.flags = {.Fixed_Height}
|
||||
layout.padding = to_ui_layout_side(4)
|
||||
}
|
||||
ui_theme_text(); title := ui_text("settings_menu.cam_max_zoom.title", str_intern("Camera: Max Zoom")); { using title
|
||||
scope(theme_text)
|
||||
title := ui_text("settings_menu.cam_max_zoom.title", str_intern("Camera: Max Zoom")); {
|
||||
using title
|
||||
layout.anchor.ratio.x = 1.0
|
||||
layout.margins.left = 10
|
||||
}
|
||||
}
|
||||
}
|
||||
ui_vbox_end(vbox, compute_layout = false )
|
||||
}
|
||||
ui_vbox_end(vbox, compute_layout = false )
|
||||
return
|
||||
}
|
||||
|
@ -4,11 +4,13 @@ package sectr
|
||||
UI Themes: Comprise of UI_Box's layout & style
|
||||
|
||||
Provides presets for themes and their interface for manipulating the combo stacks in UI_State in pairs
|
||||
|
||||
The preset UI_Theme structs are populated using theme_<name> procedures.
|
||||
There are boilerplate procedures that do ui_theme( theme_<name>()) for the user as ui_theme_<name>().
|
||||
*/
|
||||
// TODO(Ed): Eventually this will have a configuration wizard, and we'll save the presets
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_btn :: proc()
|
||||
theme_button :: proc() -> UI_Theme
|
||||
{
|
||||
@static theme : UI_Theme
|
||||
@static loaded : b32 = false
|
||||
@ -54,12 +56,10 @@ ui_theme_btn :: proc()
|
||||
theme = UI_Theme { layout_combo, style_combo }
|
||||
loaded = true
|
||||
}
|
||||
ui_layout_push(theme.layout)
|
||||
ui_style_push(theme.style)
|
||||
return theme
|
||||
}
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_drop_down :: proc()
|
||||
theme_drop_down_btn :: proc() -> UI_Theme
|
||||
{
|
||||
@static theme : UI_Theme
|
||||
@static loaded : b32 = false
|
||||
@ -106,16 +106,14 @@ ui_theme_drop_down :: proc()
|
||||
theme = UI_Theme { layout_combo, style_combo }
|
||||
loaded = true
|
||||
}
|
||||
ui_layout_push(theme.layout)
|
||||
ui_style_push(theme.style)
|
||||
return theme
|
||||
}
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_table_row :: proc(is_even : bool)
|
||||
theme_table_row :: proc( is_even : bool ) -> UI_Theme
|
||||
{
|
||||
@static theme : UI_Theme
|
||||
@static loaded : b32 = false
|
||||
// if ! loaded
|
||||
if ! loaded
|
||||
{
|
||||
app_color := app_color_theme()
|
||||
table_bg : Color
|
||||
@ -163,16 +161,14 @@ ui_theme_table_row :: proc(is_even : bool)
|
||||
theme = UI_Theme { layout_combo, style_combo }
|
||||
loaded = true
|
||||
}
|
||||
ui_layout_push(theme.layout)
|
||||
ui_style_push(theme.style)
|
||||
return theme
|
||||
}
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_window_bar :: proc()
|
||||
theme_window_bar :: proc() -> UI_Theme
|
||||
{
|
||||
@static theme : UI_Theme
|
||||
@static loaded : b32 = false
|
||||
if ! loaded || true
|
||||
if ! loaded
|
||||
{
|
||||
app_color := app_color_theme()
|
||||
layout := UI_Layout {
|
||||
@ -217,12 +213,10 @@ ui_theme_window_bar :: proc()
|
||||
theme = UI_Theme { layout_combo, style_combo }
|
||||
loaded = true
|
||||
}
|
||||
ui_layout_push(theme.layout)
|
||||
ui_style_push(theme.style)
|
||||
return theme
|
||||
}
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_window_bar_title :: proc()
|
||||
theme_window_bar_title :: proc() -> UI_Theme
|
||||
{
|
||||
@static theme : UI_Theme
|
||||
@static loaded : b32 = false
|
||||
@ -267,12 +261,10 @@ ui_theme_window_bar_title :: proc()
|
||||
theme = UI_Theme { layout_combo, style_combo }
|
||||
loaded = true
|
||||
}
|
||||
ui_layout_push(theme.layout)
|
||||
ui_style_push(theme.style)
|
||||
return theme
|
||||
}
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_window_bar_btn :: proc()
|
||||
theme_window_bar_btn :: proc() -> UI_Theme
|
||||
{
|
||||
@static theme : UI_Theme
|
||||
@static loaded : b32 = false
|
||||
@ -318,12 +310,10 @@ ui_theme_window_bar_btn :: proc()
|
||||
theme = UI_Theme { layout_combo, style_combo }
|
||||
loaded = true
|
||||
}
|
||||
ui_layout_push(theme.layout)
|
||||
ui_style_push(theme.style)
|
||||
return theme
|
||||
}
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_window_panel :: proc()
|
||||
theme_window_panel :: proc() -> UI_Theme
|
||||
{
|
||||
@static theme : UI_Theme
|
||||
@static loaded : b32 = false
|
||||
@ -368,12 +358,10 @@ ui_theme_window_panel :: proc()
|
||||
theme = UI_Theme { layout_combo, style_combo }
|
||||
loaded = true
|
||||
}
|
||||
ui_layout_push(theme.layout)
|
||||
ui_style_push(theme.style)
|
||||
return theme
|
||||
}
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_transparent :: proc()
|
||||
theme_transparent :: proc() -> UI_Theme
|
||||
{
|
||||
@static theme : UI_Theme
|
||||
@static loaded : b32 = false
|
||||
@ -418,12 +406,10 @@ ui_theme_transparent :: proc()
|
||||
theme = UI_Theme { layout_combo, style_combo }
|
||||
loaded = true
|
||||
}
|
||||
ui_layout_push(theme.layout)
|
||||
ui_style_push(theme.style)
|
||||
return theme
|
||||
}
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_text :: proc()
|
||||
theme_text :: proc() -> UI_Theme
|
||||
{
|
||||
@static theme : UI_Theme
|
||||
@static loaded : b32 = false
|
||||
@ -468,6 +454,5 @@ ui_theme_text :: proc()
|
||||
theme = UI_Theme { layout_combo, style_combo }
|
||||
loaded = true
|
||||
}
|
||||
ui_layout_push(theme.layout)
|
||||
ui_style_push(theme.style)
|
||||
return theme
|
||||
}
|
||||
|
@ -69,6 +69,43 @@ AppColorTheme :: struct {
|
||||
: Color
|
||||
}
|
||||
|
||||
App_Thm_Dark :: AppColorTheme {
|
||||
light_limit = Color {185, 185, 185, 255},
|
||||
dark_limit = Color { 6, 6, 6, 255},
|
||||
|
||||
bg = Color {16, 16, 16, 255},
|
||||
|
||||
border_default = Color { 54, 54, 54, 255},
|
||||
|
||||
btn_bg_default = Color { 32, 32, 32, 255},
|
||||
btn_bg_hot = Color { 80, 80, 100, 255},
|
||||
btn_bg_active = Color { 100, 130, 180, 255},
|
||||
|
||||
input_box_bg = Color { 20, 20, 20, 255},
|
||||
input_box_bg_hot = Color { 25, 25, 25, 255},
|
||||
input_box_bg_active = Color { 15, 15, 15, 255},
|
||||
|
||||
resize_hndl_default = Color_Transparent,
|
||||
resize_hndl_hot = Color { 72, 72, 72, 90},
|
||||
resize_hndl_active = Color { 88, 88, 88, 90},
|
||||
|
||||
table_even_bg_color = Color { 35, 35, 35, 255},
|
||||
table_odd_bg_color = Color { 30, 30, 30, 255},
|
||||
|
||||
text_default = Color {140, 137, 135, 255},
|
||||
text_hot = Color {210, 210, 210, 255},
|
||||
text_active = Color {255, 255, 255, 255},
|
||||
|
||||
translucent_panel = Color { 30, 30, 30, 50},
|
||||
|
||||
window_bar_border = Color{74, 74, 74, 255}, // border_default
|
||||
window_bar_bg = Color{32, 32, 32, 255},
|
||||
window_btn_close_bg_hot = Color{65, 45, 45, 255},
|
||||
|
||||
window_panel_bg = Color{ 20, 20, 20, 50}, // translucent_panel
|
||||
window_panel_border = Color{ 84, 84, 84, 255},
|
||||
}
|
||||
|
||||
App_Thm_Dusk :: AppColorTheme {
|
||||
light_limit = Color {125, 125, 125, 255},
|
||||
dark_limit = Color { 10, 10, 10, 255},
|
||||
|
@ -124,7 +124,7 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
|
||||
cam_zoom_sensitivity_digital = 0.2
|
||||
cam_zoom_sensitivity_smooth = 4.0
|
||||
|
||||
engine_refresh_hz = 30
|
||||
engine_refresh_hz = 0
|
||||
|
||||
timing_fps_moving_avg_alpha = 0.9
|
||||
|
||||
@ -162,7 +162,10 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
|
||||
// Determining current monitor and setting the target frametime based on it..
|
||||
monitor_id = rl.GetCurrentMonitor()
|
||||
monitor_refresh_hz = rl.GetMonitorRefreshRate( monitor_id )
|
||||
log( str_fmt_tmp( "Set target FPS to: %v", monitor_refresh_hz ) )
|
||||
|
||||
if config.engine_refresh_hz == 0 {
|
||||
config.engine_refresh_hz = uint(monitor_refresh_hz)
|
||||
}
|
||||
}
|
||||
|
||||
// Basic Font Setup
|
||||
@ -188,7 +191,7 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
|
||||
using screen_ui
|
||||
menu_bar.pos = { -60, 0 }
|
||||
// menu_bar.pos = Vec2(app_window.extent) * { -1, 1 }
|
||||
menu_bar.size = {200, 40}
|
||||
menu_bar.size = {140, 40}
|
||||
|
||||
settings_menu.min_size = {250, 200}
|
||||
}
|
||||
@ -335,8 +338,9 @@ tick :: proc( host_delta_time : f64, host_delta_ns : Duration ) -> b32
|
||||
debug.draw_UI_padding_bounds = false
|
||||
debug.draw_ui_content_bounds = false
|
||||
|
||||
config.color_theme = App_Thm_Light
|
||||
// config.color_theme = App_Thm_Light
|
||||
// config.color_theme = App_Thm_Dusk
|
||||
config.color_theme = App_Thm_Dark
|
||||
should_close = update( host_delta_time )
|
||||
render()
|
||||
|
||||
|
@ -117,6 +117,10 @@ logger_interface :: proc(
|
||||
str_to_file_ln( logger.file, to_string(builder) )
|
||||
}
|
||||
|
||||
// TODO(Ed): Use a fixed size block allocation for message formatting used by core_log
|
||||
// This will prevent stack overflows with the virtual arena debug logs at worst case and not need to do
|
||||
// some inline arena allocation on-site such as with the memory tracker
|
||||
|
||||
log :: proc( msg : string, level := LogLevel.Info, loc := #caller_location ) {
|
||||
core_log.log( level, msg, location = loc )
|
||||
}
|
||||
|
@ -221,11 +221,6 @@ render_mode_screenspace :: proc ()
|
||||
|
||||
render_screen_ui()
|
||||
|
||||
fps_msg := str_fmt_tmp( "FPS: %f", fps_avg)
|
||||
fps_msg_width := measure_text_size( fps_msg, default_font, 12.0, 0.0 ).x
|
||||
fps_msg_pos := screen_get_corners().top_right - { fps_msg_width, 0 } - { 5, 5 }
|
||||
debug_draw_text( fps_msg, fps_msg_pos, 12.0, color = rl.GREEN )
|
||||
|
||||
debug_text :: proc( format : string, args : ..any )
|
||||
{
|
||||
@static draw_text_scratch : [Kilobyte * 64]u8
|
||||
@ -248,8 +243,13 @@ render_mode_screenspace :: proc ()
|
||||
debug.draw_debug_text_y += 14
|
||||
}
|
||||
|
||||
// Debug Text
|
||||
if debug.debug_text_vis
|
||||
{
|
||||
fps_msg := str_fmt_tmp( "FPS: %f", fps_avg)
|
||||
fps_msg_width := measure_text_size( fps_msg, default_font, 12.0, 0.0 ).x
|
||||
fps_msg_pos := screen_get_corners().top_right - { fps_msg_width, 0 } - { 5, 5 }
|
||||
debug_draw_text( fps_msg, fps_msg_pos, 12.0, color = rl.GREEN )
|
||||
|
||||
// debug_text( "Screen Width : %v", rl.GetScreenWidth () )
|
||||
// debug_text( "Screen Height: %v", rl.GetScreenHeight() )
|
||||
// debug_text( "frametime_target_ms : %f ms", frametime_target_ms )
|
||||
@ -262,61 +262,52 @@ render_mode_screenspace :: proc ()
|
||||
debug_text( "Replaying Input")
|
||||
}
|
||||
// debug_text("Zoom Target: %v", project.workspace.zoom_target)
|
||||
}
|
||||
|
||||
if debug.mouse_vis {
|
||||
debug_text("Mouse Vertical Wheel: %v", input.mouse.vertical_wheel )
|
||||
debug_text("Mouse Delta : %v", input.mouse.delta )
|
||||
debug_text("Mouse Position (Render) : %v", input.mouse.raw_pos )
|
||||
debug_text("Mouse Position (Screen) : %v", input.mouse.pos )
|
||||
debug_text("Mouse Position (Workspace View): %v", screen_to_ws_view_pos(input.mouse.pos) )
|
||||
rl.DrawCircleV( input.mouse.raw_pos, 10, Color_White_A125 )
|
||||
rl.DrawCircleV( screen_to_render_pos(input.mouse.pos), 2, Color_BG )
|
||||
}
|
||||
|
||||
ui := & project.workspace.ui
|
||||
|
||||
if false
|
||||
{
|
||||
debug_text("Box Count (Workspace): %v", ui.built_box_count )
|
||||
|
||||
hot_box := ui_box_from_key( ui.curr_cache, ui.hot )
|
||||
active_box := ui_box_from_key( ui.curr_cache, ui.active )
|
||||
if hot_box != nil {
|
||||
debug_text("Worksapce Hot Box : %v", hot_box.label.str )
|
||||
debug_text("Workspace Hot Range2: %v", hot_box.computed.bounds.pts)
|
||||
if debug.mouse_vis {
|
||||
debug_text("Mouse Vertical Wheel: %v", input.mouse.vertical_wheel )
|
||||
debug_text("Mouse Delta : %v", input.mouse.delta )
|
||||
debug_text("Mouse Position (Render) : %v", input.mouse.raw_pos )
|
||||
debug_text("Mouse Position (Screen) : %v", input.mouse.pos )
|
||||
debug_text("Mouse Position (Workspace View): %v", screen_to_ws_view_pos(input.mouse.pos) )
|
||||
rl.DrawCircleV( input.mouse.raw_pos, 10, Color_White_A125 )
|
||||
rl.DrawCircleV( screen_to_render_pos(input.mouse.pos), 2, Color_BG )
|
||||
}
|
||||
if active_box != nil{
|
||||
debug_text("Workspace Active Box: %v", active_box.label.str )
|
||||
|
||||
ui := & project.workspace.ui
|
||||
|
||||
if true
|
||||
{
|
||||
debug_text("Box Count (Workspace): %v", ui.built_box_count )
|
||||
|
||||
hot_box := ui_box_from_key( ui.curr_cache, ui.hot )
|
||||
active_box := ui_box_from_key( ui.curr_cache, ui.active )
|
||||
if hot_box != nil {
|
||||
debug_text("Worksapce Hot Box : %v", hot_box.label.str )
|
||||
debug_text("Workspace Hot Range2: %v", hot_box.computed.bounds.pts)
|
||||
}
|
||||
if active_box != nil{
|
||||
debug_text("Workspace Active Box: %v", active_box.label.str )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui = & screen_ui
|
||||
ui = & screen_ui
|
||||
|
||||
if true
|
||||
{
|
||||
debug_text("Box Count: %v", ui.built_box_count )
|
||||
if true
|
||||
{
|
||||
debug_text("Box Count: %v", ui.built_box_count )
|
||||
|
||||
hot_box := ui_box_from_key( ui.curr_cache, ui.hot )
|
||||
active_box := ui_box_from_key( ui.curr_cache, ui.active )
|
||||
if hot_box != nil {
|
||||
debug_text("Hot Box : %v", hot_box.label.str )
|
||||
debug_text("Hot Range2: %v", hot_box.computed.bounds.pts)
|
||||
hot_box := ui_box_from_key( ui.curr_cache, ui.hot )
|
||||
active_box := ui_box_from_key( ui.curr_cache, ui.active )
|
||||
if hot_box != nil {
|
||||
debug_text("Hot Box : %v", hot_box.label.str )
|
||||
debug_text("Hot Range2: %v", hot_box.computed.bounds.pts)
|
||||
}
|
||||
if active_box != nil{
|
||||
debug_text("Active Box: %v", active_box.label.str )
|
||||
}
|
||||
}
|
||||
if active_box != nil{
|
||||
debug_text("Active Box: %v", active_box.label.str )
|
||||
}
|
||||
}
|
||||
|
||||
view := view_get_bounds()
|
||||
debug.draw_debug_text_y = 14
|
||||
|
||||
// Define the triangle vertices and colors
|
||||
vertices := []f32{
|
||||
// Positions // Colors (RGBA)
|
||||
-0.5, -0.5, 0.0, 1.0, 0.0, 0.0, 1.0, // Vertex 1: Red
|
||||
0.5, -0.5, 0.0, 0.0, 1.0, 0.0, 1.0, // Vertex 2: Green
|
||||
0.0, 0.5, 0.0, 0.0, 0.0, 1.0, 1.0 // Vertex 3: Blue
|
||||
debug.draw_debug_text_y = 14
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,8 @@ DebugActions :: struct {
|
||||
record_replay : b32,
|
||||
play_replay : b32,
|
||||
|
||||
show_mouse_pos : b32,
|
||||
show_debug_text : b32,
|
||||
show_mouse_pos : b32,
|
||||
|
||||
mouse_select : b32,
|
||||
|
||||
@ -48,7 +49,8 @@ poll_debug_actions :: proc( actions : ^ DebugActions, input : ^ InputState )
|
||||
record_replay = base_replay_bind && keyboard.right_shift.ended_down
|
||||
play_replay = base_replay_bind && ! keyboard.right_shift.ended_down
|
||||
|
||||
show_mouse_pos = keyboard.right_alt.ended_down && pressed(keyboard.M)
|
||||
show_debug_text = keyboard.right_alt.ended_down && pressed(keyboard.T)
|
||||
show_mouse_pos = keyboard.right_alt.ended_down && pressed(keyboard.M)
|
||||
|
||||
mouse_select = pressed(mouse.left)
|
||||
|
||||
@ -146,6 +148,9 @@ update :: proc( delta_time : f64 ) -> b32
|
||||
if debug_actions.show_mouse_pos {
|
||||
debug.mouse_vis = !debug.mouse_vis
|
||||
}
|
||||
if debug_actions.show_debug_text {
|
||||
debug.debug_text_vis = !debug.debug_text_vis
|
||||
}
|
||||
|
||||
//region 2D Camera Manual Nav
|
||||
// TODO(Ed): This should be per workspace view
|
||||
@ -223,17 +228,17 @@ update :: proc( delta_time : f64 ) -> b32
|
||||
// size = range2( { 1000, 1000 }, {}),
|
||||
// padding = { 20, 20, 20, 20 }
|
||||
}
|
||||
ui_layout( default_layout )
|
||||
scope( default_layout )
|
||||
frame_style_default := UI_Style {
|
||||
bg_color = Color_BG_TextBox,
|
||||
font = default_font,
|
||||
text_color = Color_White,
|
||||
}
|
||||
frame_theme := to_ui_style_combo(frame_style_default)
|
||||
frame_theme.disabled.bg_color = Color_Frame_Disabled
|
||||
frame_theme.hot. bg_color = Color_Frame_Hover
|
||||
frame_theme.active. bg_color = Color_Frame_Select
|
||||
ui_style( frame_theme )
|
||||
frame_style := to_ui_style_combo(frame_style_default)
|
||||
frame_style.disabled.bg_color = Color_Frame_Disabled
|
||||
frame_style.hot. bg_color = Color_Frame_Hover
|
||||
frame_style.active. bg_color = Color_Frame_Select
|
||||
scope( frame_style )
|
||||
|
||||
config.ui_resize_border_width = 2.5
|
||||
// test_hover_n_click()
|
||||
|
@ -68,7 +68,7 @@ array_init_reserve :: proc
|
||||
|
||||
result.header = cast( ^ArrayHeader(Type)) raw_mem
|
||||
result.backing = allocator
|
||||
// result.dbg_name = dbg_name
|
||||
result.dbg_name = dbg_name
|
||||
result.fixed_cap = fixed_cap
|
||||
result.capacity = capacity
|
||||
result.data = cast( [^]Type ) (cast( [^]ArrayHeader(Type)) result.header)[ 1:]
|
||||
@ -123,10 +123,6 @@ array_append_slice :: proc( using self : ^Array( $ Type ), items : []Type ) -> A
|
||||
}
|
||||
}
|
||||
|
||||
// Note(Ed) : Original code from gencpp
|
||||
// libc.memcpy( ptr_offset(data, num), raw_data(items), len(items) * size_of(Type) )
|
||||
|
||||
// TODO(Ed) : VERIFY VIA DEBUG THIS COPY IS FINE.
|
||||
target := ptr_offset( data, num )
|
||||
copy( slice_ptr(target, int(capacity - num)), items )
|
||||
|
||||
|
@ -214,6 +214,15 @@ pressed :: proc {
|
||||
push :: proc {
|
||||
stack_push,
|
||||
stack_allocator_push,
|
||||
|
||||
ui_layout_push_layout,
|
||||
ui_layout_push_combo,
|
||||
|
||||
ui_style_push_style,
|
||||
ui_style_push_combo,
|
||||
|
||||
ui_theme_push_via_proc,
|
||||
ui_theme_push_via_theme,
|
||||
}
|
||||
|
||||
rotor3 :: proc {
|
||||
@ -242,6 +251,19 @@ inverse_sqrt :: proc {
|
||||
inverse_sqrt_f32,
|
||||
}
|
||||
|
||||
scope :: proc {
|
||||
ui_layout_scope_via_layout,
|
||||
ui_layout_scope_via_combo,
|
||||
|
||||
ui_style_scope_via_style,
|
||||
ui_style_scope_via_combo,
|
||||
|
||||
ui_theme_scope_via_layout_style,
|
||||
ui_theme_scope_via_combos,
|
||||
ui_theme_scope_via_proc,
|
||||
ui_theme_scope_via_theme,
|
||||
}
|
||||
|
||||
sub :: proc {
|
||||
sub_point3,
|
||||
sub_range2,
|
||||
@ -302,12 +324,12 @@ ui_floating :: proc {
|
||||
|
||||
ui_layout_push :: proc {
|
||||
ui_layout_push_layout,
|
||||
ui_layout_push_theme,
|
||||
ui_layout_push_combo,
|
||||
}
|
||||
|
||||
ui_layout :: proc {
|
||||
ui_layout_via_layout,
|
||||
ui_layout_via_combo,
|
||||
ui_layout_scope_via_layout,
|
||||
ui_layout_scope_via_combo,
|
||||
}
|
||||
|
||||
ui_style_push :: proc {
|
||||
@ -315,15 +337,20 @@ ui_style_push :: proc {
|
||||
ui_style_push_combo,
|
||||
}
|
||||
|
||||
ui_style :: proc {
|
||||
ui_style_via_style,
|
||||
ui_style_via_combo,
|
||||
ui_style_scope :: proc {
|
||||
ui_style_scope_via_style,
|
||||
ui_style_scope_via_combo,
|
||||
}
|
||||
|
||||
ui_theme :: proc {
|
||||
ui_theme_via_layout_style,
|
||||
ui_theme_via_combos,
|
||||
ui_theme_via_theme,
|
||||
ui_theme_push :: proc {
|
||||
ui_theme_push_via_proc,
|
||||
ui_theme_push_via_theme,
|
||||
}
|
||||
|
||||
ui_theme_scope :: proc {
|
||||
ui_theme_scope_via_layout_style,
|
||||
ui_theme_scope_via_combos,
|
||||
ui_theme_scope_via_theme,
|
||||
}
|
||||
|
||||
wedge :: proc {
|
||||
|
@ -1,13 +1,12 @@
|
||||
/*
|
||||
This is a quick and dirty string table.
|
||||
IT uses the HMapZPL for the hashtable of strings, and the string's content is stored in a dedicated slab.
|
||||
|
||||
Future Plans (IF needed for performance):
|
||||
The goal is to eventually swap out the slab with possilby a dedicated growing vmem arena for the strings.
|
||||
The table would be swapped with a table stored in the general slab and uses either linear probing or open addressing
|
||||
String Intering Table using its own dedicated slab & chained hashtable
|
||||
|
||||
If linear probing, the hash node list per table bucket is store with the strigns in the same arena.
|
||||
If open addressing, we just keep the open addressed array of node slots in the general slab (but hopefully better perf)
|
||||
|
||||
TODO(Ed): Move the string cache to its own virtual arena?
|
||||
Its going to be used heavily and we can better utilize memory that way.
|
||||
The arena can deal with alignment just fine or we can pad in a min amount per string.
|
||||
*/
|
||||
package sectr
|
||||
|
||||
@ -19,6 +18,10 @@ import "core:strings"
|
||||
StringKey :: distinct u64
|
||||
RunesCached :: []rune
|
||||
|
||||
// TODO(Ed): There doesn't seem to be a need for caching the runes.
|
||||
// It seems like no one has had a bottleneck just iterating through the code points on demand when needed.
|
||||
// So we should problably scrap storing them that way.
|
||||
|
||||
StrRunesPair :: struct {
|
||||
str : string,
|
||||
runes : []rune,
|
||||
@ -36,9 +39,10 @@ str_cache_init :: proc( /*allocator : Allocator*/ ) -> ( cache : StringCache ) {
|
||||
|
||||
policy : SlabPolicy
|
||||
policy_ptr := & policy
|
||||
push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 16, alignment })
|
||||
push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 32, alignment })
|
||||
push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 64, alignment })
|
||||
// push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 8, alignment })
|
||||
// push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 16, alignment })
|
||||
push( policy_ptr, SlabSizeClass { 128 * Kilobyte, 32, alignment })
|
||||
push( policy_ptr, SlabSizeClass { 128 * Kilobyte, 64, alignment })
|
||||
push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 128, alignment })
|
||||
push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 256, alignment })
|
||||
push( policy_ptr, SlabSizeClass { 64 * Kilobyte, 512, alignment })
|
||||
@ -69,9 +73,7 @@ str_cache_init :: proc( /*allocator : Allocator*/ ) -> ( cache : StringCache ) {
|
||||
str_intern_key :: #force_inline proc( content : string ) -> StringKey { return cast(StringKey) crc32( transmute([]byte) content ) }
|
||||
str_intern_lookup :: #force_inline proc( key : StringKey ) -> (^StrRunesPair) { return zpl_hmap_get( & get_state().string_cache.table, transmute(u64) key ) }
|
||||
|
||||
str_intern :: proc(
|
||||
content : string
|
||||
) -> StrRunesPair
|
||||
str_intern :: proc( content : string ) -> StrRunesPair
|
||||
{
|
||||
// profile(#procedure)
|
||||
cache := & get_state().string_cache
|
||||
@ -110,6 +112,10 @@ str_intern :: proc(
|
||||
return (result ^)
|
||||
}
|
||||
|
||||
str_intern_fmt :: #force_inline proc( format : string, args : ..any, allocator := context.allocator ) -> StrRunesPair {
|
||||
return str_intern(str_fmt_alloc(format, args, allocator = allocator))
|
||||
}
|
||||
|
||||
// runes_intern :: proc( content : []rune ) -> StrRunesPair
|
||||
// {
|
||||
// cache := get_state().string_cache
|
||||
|
@ -91,7 +91,7 @@ PWS_ParseError :: struct {
|
||||
PWS_ParseError_Max :: 32
|
||||
PWS_TokenArray_ReserveSize :: 128
|
||||
PWS_NodeArray_ReserveSize :: 32 * Kilobyte
|
||||
PWS_LineArray_ReserveSize :: 32
|
||||
PWS_LineArray_ReserveSize :: 32 * Kilobyte
|
||||
|
||||
// TODO(Ed) : The ast arrays should be handled by a slab allocator dedicated to PWS_ASTs
|
||||
// This can grow in undeterministic ways, persistent will get very polluted otherwise.
|
||||
|
@ -113,8 +113,7 @@ ui_box_make :: proc( flags : UI_BoxFlags, label : string ) -> (^ UI_Box)
|
||||
curr_box.links = {}
|
||||
curr_box.num_children = 0
|
||||
|
||||
// If there is a parent, setup the relevant references
|
||||
parent := stack_peek( & parent_stack )
|
||||
parent := ui_parent_peek()
|
||||
if parent != nil
|
||||
{
|
||||
dll_full_push_back( parent, curr_box, nil )
|
||||
|
@ -160,10 +160,10 @@ ui_layout_peek :: #force_inline proc() -> UI_LayoutCombo { return stack_peek( &
|
||||
ui_layout_ref :: #force_inline proc() -> ^UI_LayoutCombo { return stack_peek_ref( & get_state().ui_context.layout_combo_stack) }
|
||||
|
||||
ui_layout_push_layout :: #force_inline proc( layout : UI_Layout ) { push( & get_state().ui_context.layout_combo_stack, to_ui_layout_combo(layout)) }
|
||||
ui_layout_push_theme :: #force_inline proc( combo : UI_LayoutCombo ) { push( & get_state().ui_context.layout_combo_stack, combo ) }
|
||||
ui_layout_push_combo :: #force_inline proc( combo : UI_LayoutCombo ) { push( & get_state().ui_context.layout_combo_stack, combo ) }
|
||||
ui_layout_pop :: #force_inline proc() { pop( & get_state().ui_context.layout_combo_stack ) }
|
||||
|
||||
@(deferred_none = ui_layout_pop) ui_layout_via_layout :: #force_inline proc( layout : UI_Layout ) { ui_layout_push( layout) }
|
||||
@(deferred_none = ui_layout_pop) ui_layout_via_combo :: #force_inline proc( combo : UI_LayoutCombo ) { ui_layout_push( combo) }
|
||||
@(deferred_none = ui_layout_pop) ui_layout_scope_via_layout :: #force_inline proc( layout : UI_Layout ) { ui_layout_push( layout) }
|
||||
@(deferred_none = ui_layout_pop) ui_layout_scope_via_combo :: #force_inline proc( combo : UI_LayoutCombo ) { ui_layout_push( combo) }
|
||||
|
||||
ui_set_layout :: #force_inline proc( layout : UI_Layout, preset : UI_StylePreset ) { stack_peek_ref( & get_state().ui_context.layout_combo_stack).array[preset] = layout }
|
||||
|
@ -274,6 +274,8 @@ ui_key_from_string :: #force_inline proc "contextless" ( value : string ) -> UI_
|
||||
ui_parent_push :: #force_inline proc( ui : ^ UI_Box ) { stack_push( & ui_context().parent_stack, ui ) }
|
||||
ui_parent_pop :: #force_inline proc() { stack_pop( & get_state().ui_context.parent_stack ) }
|
||||
|
||||
ui_parent_peek :: #force_inline proc() -> ^UI_Box { return stack_peek( & ui_context().parent_stack )}
|
||||
|
||||
@(deferred_none = ui_parent_pop)
|
||||
ui_parent :: #force_inline proc( ui : ^UI_Box) { ui_parent_push( ui ) }
|
||||
|
||||
|
@ -66,7 +66,7 @@ ui_style_push_style :: #force_inline proc( style : UI_Style ) { push( & get
|
||||
ui_style_push_combo :: #force_inline proc( combo : UI_StyleCombo ) { push( & get_state().ui_context.style_combo_stack, combo ) }
|
||||
ui_style_pop :: #force_inline proc() { pop( & get_state().ui_context.style_combo_stack ) }
|
||||
|
||||
@(deferred_none = ui_style_pop) ui_style_via_style :: #force_inline proc( style : UI_Style ) { ui_style_push( style) }
|
||||
@(deferred_none = ui_style_pop) ui_style_via_combo :: #force_inline proc( combo : UI_StyleCombo ) { ui_style_push( combo) }
|
||||
@(deferred_none = ui_style_pop) ui_style_scope_via_style :: #force_inline proc( style : UI_Style ) { ui_style_push( style) }
|
||||
@(deferred_none = ui_style_pop) ui_style_scope_via_combo :: #force_inline proc( combo : UI_StyleCombo ) { ui_style_push( combo) }
|
||||
|
||||
ui_style_set :: #force_inline proc ( style : UI_Style, preset : UI_StylePreset ) { stack_peek_ref( & get_state().ui_context.style_combo_stack ).array[preset] = style }
|
||||
|
@ -10,28 +10,36 @@ UI_Theme :: struct {
|
||||
style : UI_StyleCombo,
|
||||
}
|
||||
|
||||
ui_theme_push_via_proc :: #force_inline proc( procedure : #type proc() -> UI_Theme ) { ui_theme_push(procedure()) }
|
||||
ui_theme_push_via_theme ::#force_inline proc( theme : UI_Theme ) {
|
||||
ui_layout_push( theme.layout )
|
||||
ui_style_push( theme.style )
|
||||
}
|
||||
|
||||
ui_theme_pop :: #force_inline proc() {
|
||||
ui_layout_pop()
|
||||
ui_style_pop()
|
||||
}
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_via_layout_style :: #force_inline proc( layout : UI_Layout, style : UI_Style ) {
|
||||
ui_theme_scope_via_layout_style :: #force_inline proc( layout : UI_Layout, style : UI_Style ) {
|
||||
using ui := get_state().ui_context
|
||||
ui_layout_push( layout )
|
||||
ui_style_push( style )
|
||||
}
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_via_combos :: #force_inline proc( layout : UI_LayoutCombo, style : UI_StyleCombo ) {
|
||||
ui_theme_scope_via_combos :: #force_inline proc( layout : UI_LayoutCombo, style : UI_StyleCombo ) {
|
||||
using ui := get_state().ui_context
|
||||
ui_layout_push( layout )
|
||||
ui_style_push( style )
|
||||
}
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_via_theme :: #force_inline proc( theme : UI_Theme ) {
|
||||
ui_theme_scope_via_proc :: #force_inline proc( procedure : #type proc() -> UI_Theme ) { ui_theme_push(procedure()) }
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
ui_theme_scope_via_theme :: #force_inline proc( theme : UI_Theme ) {
|
||||
using ui := get_state().ui_context
|
||||
ui_layout_push( theme.layout )
|
||||
ui_style_push( theme.style )
|
||||
ui_theme_push(theme)
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package sectr
|
||||
|
||||
import "base:runtime"
|
||||
import lalg "core:math/linalg"
|
||||
|
||||
/*
|
||||
Widget Layout Ops
|
||||
@ -35,6 +36,7 @@ ui_layout_children_horizontally :: proc( container : ^UI_Box, direction : UI_Lay
|
||||
continue
|
||||
}
|
||||
|
||||
size_req_children += size.min.x
|
||||
total_stretch_ratio += anchor.ratio.x
|
||||
}
|
||||
|
||||
@ -48,14 +50,15 @@ ui_layout_children_horizontally :: proc( container : ^UI_Box, direction : UI_Lay
|
||||
space_allocated = size.min.x * container_height
|
||||
}
|
||||
else if ! (.Fixed_Width in flags) {
|
||||
size.min.x = anchor.ratio.x * (1 / total_stretch_ratio) * avail_flex_space
|
||||
space_allocated = size.min.x
|
||||
potential_size := anchor.ratio.x * (1 / total_stretch_ratio) * avail_flex_space
|
||||
space_allocated = lalg.max(potential_size, size.min.x)
|
||||
size.min.x = space_allocated
|
||||
}
|
||||
else {
|
||||
space_allocated = size.min.x
|
||||
}
|
||||
space_allocated -= child.layout.margins.left - child.layout.margins.right
|
||||
size.min.x -= child.layout.margins.left - child.layout.margins.right
|
||||
space_allocated -= margins.left - margins.right
|
||||
size.min.x -= margins.left - margins.right
|
||||
flags |= {.Fixed_Width}
|
||||
return
|
||||
}
|
||||
@ -67,7 +70,6 @@ ui_layout_children_horizontally :: proc( container : ^UI_Box, direction : UI_Lay
|
||||
using child.layout
|
||||
child_width := allocate_space(child, total_stretch_ratio, avail_flex_space, container_height)
|
||||
anchor = range2({0, 0}, {0, 0})
|
||||
width : f32
|
||||
pos.x = space_used
|
||||
space_used += child_width + child.layout.margins.left + child.layout.margins.right
|
||||
}
|
||||
@ -76,7 +78,6 @@ ui_layout_children_horizontally :: proc( container : ^UI_Box, direction : UI_Lay
|
||||
using child.layout
|
||||
child_width := allocate_space(child, total_stretch_ratio, avail_flex_space, container_height)
|
||||
anchor = range2({0, 0}, {0, 0})
|
||||
width : f32
|
||||
pos.x = space_used
|
||||
space_used += child_width + child.layout.margins.left + child.layout.margins.right
|
||||
}
|
||||
@ -92,6 +93,7 @@ ui_layout_children_vertically :: proc( container : ^UI_Box, direction : UI_Layou
|
||||
else {
|
||||
container_height = container.computed.content.max.y - container.computed.content.min.y
|
||||
}
|
||||
container_width := container.computed.content.max.x - container.computed.content.min.x
|
||||
|
||||
// do layout calculations for the children
|
||||
total_stretch_ratio : f32 = 0.0
|
||||
@ -99,33 +101,42 @@ ui_layout_children_vertically :: proc( container : ^UI_Box, direction : UI_Layou
|
||||
for child := container.first; child != nil; child = child.next
|
||||
{
|
||||
using child.layout
|
||||
scaled_width_by_height : b32 = b32(.Scale_Width_By_Height_Ratio in flags)
|
||||
scaled_height_by_width : b32 = b32(.Scale_Height_By_Width_Ratio in flags)
|
||||
if scaled_height_by_width {
|
||||
size_req_children += size.min.y * container_width
|
||||
continue
|
||||
}
|
||||
if .Fixed_Height in flags
|
||||
{
|
||||
if scaled_width_by_height {
|
||||
width := size.max.x != 0 ? size.max.x : container_height
|
||||
height := width * size.min.y
|
||||
|
||||
size_req_children += height
|
||||
continue
|
||||
}
|
||||
|
||||
size_req_children += size.min.y
|
||||
continue
|
||||
}
|
||||
|
||||
size_req_children += size.min.y
|
||||
total_stretch_ratio += anchor.ratio.y
|
||||
}
|
||||
|
||||
avail_flex_space := container_height - size_req_children
|
||||
|
||||
allocate_space :: proc( child : ^UI_Box, total_stretch_ratio, avail_flex_space : f32 )
|
||||
allocate_space :: proc( child : ^UI_Box, total_stretch_ratio, avail_flex_space, container_width : f32 ) -> (space_allocated : f32)
|
||||
{
|
||||
using child.layout
|
||||
if ! (.Fixed_Height in flags) {
|
||||
size.min.y = (anchor.ratio.y * (1 / total_stretch_ratio) * avail_flex_space)
|
||||
if .Scale_Height_By_Width_Ratio in flags {
|
||||
size.min.x = container_width
|
||||
space_allocated = size.min.y * container_width
|
||||
}
|
||||
if ! (.Fixed_Height in flags) {
|
||||
potential_size := (anchor.ratio.y * (1 / total_stretch_ratio) * avail_flex_space)
|
||||
space_allocated = lalg.max(potential_size, size.min.y)
|
||||
size.min.y = space_allocated
|
||||
}
|
||||
else {
|
||||
space_allocated = size.min.y
|
||||
}
|
||||
space_allocated -= margins.top - margins.bottom
|
||||
size.min.y -= margins.top - margins.bottom
|
||||
flags |= {.Fixed_Height}
|
||||
return
|
||||
}
|
||||
|
||||
space_used : f32 = 0.0
|
||||
@ -133,21 +144,19 @@ ui_layout_children_vertically :: proc( container : ^UI_Box, direction : UI_Layou
|
||||
{
|
||||
case .Bottom_To_Top:
|
||||
for child := container.last; child != nil; child = child.prev {
|
||||
allocate_space(child, total_stretch_ratio, avail_flex_space)
|
||||
using child.layout
|
||||
anchor = range2({0,0}, {0, 0})
|
||||
pos.y = -space_used
|
||||
space_used += size.min.y + child.layout.margins.top + child.layout.margins.bottom
|
||||
size.min.x = container.computed.content.max.x + container.computed.content.min.x
|
||||
child_height := allocate_space(child, total_stretch_ratio, avail_flex_space, container_width)
|
||||
anchor = range2({0,0}, {0, 0})
|
||||
pos.y = -space_used
|
||||
space_used += child_height + child.layout.margins.top + child.layout.margins.bottom
|
||||
}
|
||||
case .Top_To_Bottom:
|
||||
for child := container.first; child != nil; child = child.next {
|
||||
allocate_space(child, total_stretch_ratio, avail_flex_space)
|
||||
using child.layout
|
||||
child_height := allocate_space(child, total_stretch_ratio, avail_flex_space, container_width)
|
||||
anchor = range2({0, 0}, {0, 0})
|
||||
pos.y = -space_used
|
||||
space_used += size.min.y + child.layout.margins.top + child.layout.margins.bottom
|
||||
size.min.x = container.computed.content.max.x - container.computed.content.min.x
|
||||
space_used += child_height + child.layout.margins.top + child.layout.margins.bottom
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ test_hover_n_click :: proc()
|
||||
state := get_state(); using state
|
||||
|
||||
first_btn := ui_button( "FIRST BOX!" )
|
||||
first_btn.layout.size.min = {1000, 1000}
|
||||
if first_btn.left_clicked || debug.frame_2_created {
|
||||
debug.frame_2_created = true
|
||||
|
||||
@ -37,8 +38,8 @@ test_draggable :: proc()
|
||||
pos = { 0, 0 },
|
||||
size = range2({ 200, 200 }, {}),
|
||||
}
|
||||
ui_layout( draggable_layout )
|
||||
ui_style( UI_Style {
|
||||
scope( draggable_layout )
|
||||
scope( UI_Style {
|
||||
corner_radii = { 0.3, 0.3, 0.3, 0.3 },
|
||||
})
|
||||
|
||||
@ -82,10 +83,10 @@ test_parenting :: proc( default_layout : ^UI_Layout, frame_style_default : ^UI_S
|
||||
.Fixed_Width, .Fixed_Height,
|
||||
.Origin_At_Anchor_Center
|
||||
}
|
||||
ui_layout(parent_layout)
|
||||
scope(parent_layout)
|
||||
|
||||
parent_style := frame_style_default ^
|
||||
ui_style(parent_style)
|
||||
scope(parent_style)
|
||||
|
||||
parent := ui_widget( "Parent", { .Mouse_Clickable })
|
||||
ui_parent_push(parent)
|
||||
@ -107,7 +108,7 @@ test_parenting :: proc( default_layout : ^UI_Layout, frame_style_default : ^UI_S
|
||||
|
||||
child_layout := default_layout ^
|
||||
child_layout.size = range2({ 100, 100 }, { 0, 0 })
|
||||
child_layout.alignment = { 0.0, 0.0 }
|
||||
child_layout.alignment = { 1.0, 0.0 }
|
||||
// child_layout.margins = { 20, 20, 20, 20 }
|
||||
child_layout.padding = { 5, 5, 5, 5 }
|
||||
// child_layout.anchor = range2({ 0.2, 0.1 }, { 0.1, 0.15 })
|
||||
@ -119,7 +120,7 @@ test_parenting :: proc( default_layout : ^UI_Layout, frame_style_default : ^UI_S
|
||||
|
||||
child_style := frame_style_default ^
|
||||
child_style.bg_color = Color_GreyRed
|
||||
ui_theme(child_layout, child_style)
|
||||
scope(child_layout, child_style)
|
||||
child := ui_widget( "Child", { .Mouse_Clickable })
|
||||
ui_parent_pop()
|
||||
}
|
||||
@ -174,7 +175,7 @@ test_whitespace_ast :: proc( default_layout : ^UI_Layout, frame_style_default :
|
||||
text_style_combo.disabled.bg_color = Color_Frame_Disabled
|
||||
text_style_combo.hot.bg_color = Color_Frame_Hover
|
||||
text_style_combo.active.bg_color = Color_Frame_Select
|
||||
ui_theme( text_layout, text_style )
|
||||
scope( text_layout, text_style )
|
||||
|
||||
alloc_error : AllocatorError; success : bool
|
||||
// debug.lorem_content, success = os.read_entire_file( debug.path_lorem, frame_allocator() )
|
||||
@ -216,7 +217,7 @@ test_whitespace_ast :: proc( default_layout : ^UI_Layout, frame_style_default :
|
||||
chunk_layout.flags = { .Fixed_Position_X, .Size_To_Text }
|
||||
|
||||
chunk_style := text_style
|
||||
ui_theme( to_ui_layout_combo(chunk_layout), to_ui_style_combo(chunk_style) )
|
||||
scope( chunk_layout, chunk_style )
|
||||
|
||||
head := line.first
|
||||
for ; head != nil;
|
||||
@ -289,7 +290,10 @@ test_whitespace_ast :: proc( default_layout : ^UI_Layout, frame_style_default :
|
||||
text_layout.pos.y += size_range2(line_hbox.computed.bounds).y
|
||||
}
|
||||
else {
|
||||
text_layout.pos.y += size_range2( (& widgets.data[ widgets.num - 1 ]).computed.bounds ).y
|
||||
widget := & widgets.data[ widgets.num - 1 ]
|
||||
if widget.box != nil {
|
||||
text_layout.pos.y += size_range2( widget.computed.bounds ).y
|
||||
}
|
||||
}
|
||||
|
||||
line_id += 1
|
||||
|
@ -3,6 +3,9 @@ package sectr
|
||||
import "base:runtime"
|
||||
import lalg "core:math/linalg"
|
||||
|
||||
// Problably cursed way to setup a 'scope' for a widget
|
||||
ui_build :: #force_inline proc( captures : $Type, $maker : #type proc(captures : Type) -> $ReturnType ) -> ReturnType { return maker(captures) }
|
||||
|
||||
UI_Widget :: struct {
|
||||
using box : ^UI_Box,
|
||||
using signal : UI_Signal,
|
||||
@ -23,6 +26,80 @@ ui_button :: proc( label : string, flags : UI_BoxFlags = {} ) -> (btn : UI_Widge
|
||||
return
|
||||
}
|
||||
|
||||
#region("Drop Down")
|
||||
/* TODO(Ed): Don't feel very good about the abstraction...
|
||||
*/
|
||||
UI_DropDown :: struct {
|
||||
btn : UI_Widget,
|
||||
title : UI_Widget,
|
||||
vbox : UI_VBox,
|
||||
is_open : bool,
|
||||
}
|
||||
|
||||
@(deferred_out = ui_drop_down_end_auto)
|
||||
ui_drop_down :: proc( drop_down : ^UI_DropDown, label : string, title_text : StrRunesPair,
|
||||
direction := UI_LayoutDirectionY.Top_To_Bottom,
|
||||
btn_flags := UI_BoxFlags{},
|
||||
vb_flags := UI_BoxFlags{},
|
||||
vb_compute_layout := true,
|
||||
btn_theme : ^UI_Theme = nil,
|
||||
title_theme : ^UI_Theme = nil
|
||||
) -> (deferred : ^UI_DropDown)
|
||||
{
|
||||
deferred = drop_down
|
||||
ui_drop_down_begin(drop_down, label, title_text, direction, btn_flags, vb_flags, btn_theme, title_theme)
|
||||
if ! drop_down.is_open do return
|
||||
ui_parent_push(drop_down.vbox)
|
||||
return
|
||||
}
|
||||
|
||||
// Its assumed that the drop down has a vertical box parent already pushed
|
||||
ui_drop_down_begin :: proc( drop_down : ^UI_DropDown, label : string, title_text : StrRunesPair,
|
||||
direction := UI_LayoutDirectionY.Top_To_Bottom,
|
||||
btn_flags := UI_BoxFlags{},
|
||||
vb_flags := UI_BoxFlags{},
|
||||
btn_theme : ^UI_Theme = nil,
|
||||
title_theme : ^UI_Theme = nil,
|
||||
vb_compute_layout := true )
|
||||
{
|
||||
using drop_down
|
||||
|
||||
if btn_theme == nil do push(theme_drop_down_btn)
|
||||
else do push(btn_theme ^)
|
||||
defer ui_theme_pop()
|
||||
btn = ui_button( str_intern_fmt("%s.btn", label).str );
|
||||
{
|
||||
btn.layout.padding.left = 4
|
||||
ui_parent(btn)
|
||||
|
||||
if title_theme == nil do push(theme_text)
|
||||
else do push(title_theme ^)
|
||||
defer ui_theme_pop()
|
||||
title = ui_text( str_intern_fmt("%s.btn.title", label).str, title_text)
|
||||
}
|
||||
|
||||
if btn.pressed {
|
||||
is_open = !is_open
|
||||
}
|
||||
if is_open == false do return
|
||||
|
||||
scope(theme_transparent)
|
||||
vbox = ui_vbox_begin( direction, str_intern_fmt("%v : vbox", label).str, compute_layout = vb_compute_layout )
|
||||
vbox.layout.anchor.ratio.y = 1.0
|
||||
}
|
||||
|
||||
ui_drop_down_end :: proc( drop_down : ^UI_DropDown ) {
|
||||
if ! drop_down.is_open do return
|
||||
ui_vbox_end(drop_down.vbox)
|
||||
}
|
||||
|
||||
ui_drop_down_end_auto :: proc( drop_down : ^UI_DropDown) {
|
||||
if ! drop_down.is_open do return
|
||||
ui_vbox_end(drop_down.vbox, compute_layout = true)
|
||||
ui_parent_pop()
|
||||
}
|
||||
#endregion("Drop Down")
|
||||
|
||||
#region("Horizontal Box")
|
||||
/*
|
||||
Horizontal Boxes automatically manage a collection of widgets and
|
||||
@ -39,13 +116,11 @@ The hbox will use the anchor's (range2) ratio.x value to determine the "stretch
|
||||
Keep in mind the stretch ratio is only respected if no size.min.x value is violated for each of the widgets.
|
||||
*/
|
||||
|
||||
// Horizontal Widget
|
||||
UI_HBox :: struct {
|
||||
using widget : UI_Widget,
|
||||
direction : UI_LayoutDirectionX,
|
||||
}
|
||||
|
||||
// Boilerplate creation
|
||||
ui_hbox_begin :: proc( direction : UI_LayoutDirectionX, label : string, flags : UI_BoxFlags = {} ) -> (hbox : UI_HBox) {
|
||||
// profile(#procedure)
|
||||
hbox.direction = direction
|
||||
@ -171,7 +246,6 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2,
|
||||
handle_corner_tl : UI_Widget
|
||||
handle_corner_br : UI_Widget
|
||||
handle_corner_bl : UI_Widget
|
||||
ui_parent(parent)
|
||||
|
||||
@(deferred_none = ui_theme_pop)
|
||||
theme_handle :: proc( base : ^UI_Theme, margins, size : Vec2, flags : UI_LayoutFlags = {})
|
||||
@ -247,50 +321,52 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2,
|
||||
}
|
||||
context.user_ptr = & parent.label
|
||||
|
||||
#region("Handle & Corner construction")
|
||||
theme_handle( theme, {handle_width, 0}, {handle_width,0})
|
||||
if left {
|
||||
handle_left = ui_widget(name("resize_handle_left"), flags )
|
||||
handle_left.layout.anchor.left = 0
|
||||
handle_left.layout.anchor.right = 1
|
||||
handle_left.layout.alignment = {1, 0}
|
||||
Handle_Construction:
|
||||
{
|
||||
ui_parent(parent)
|
||||
theme_handle( theme, {handle_width, 0}, {handle_width,0})
|
||||
if left {
|
||||
handle_left = ui_widget(name("resize_handle_left"), flags )
|
||||
handle_left.layout.anchor.left = 0
|
||||
handle_left.layout.anchor.right = 1
|
||||
handle_left.layout.alignment = {1, 0}
|
||||
}
|
||||
if right {
|
||||
handle_right = ui_widget(name("resize_handle_right"), flags )
|
||||
handle_right.layout.anchor.left = 1
|
||||
}
|
||||
theme_handle( theme, {0, handle_width}, {0, handle_width})
|
||||
if top {
|
||||
handle_top = ui_widget(name("resize_handle_top"), flags )
|
||||
handle_top.layout.anchor.bottom = 1
|
||||
handle_top.layout.alignment = {0, -1}
|
||||
}
|
||||
if bottom {
|
||||
handle_bottom = ui_widget("resize_handle_bottom", flags)
|
||||
handle_bottom.layout.anchor.top = 1
|
||||
handle_bottom.layout.alignment = { 0, 0 }
|
||||
}
|
||||
theme_handle( theme, {0,0}, {handle_width, handle_width}, {.Fixed_Width, .Fixed_Height} )
|
||||
if corner_tl {
|
||||
handle_corner_tl = ui_widget(name("corner_top_left"), flags)
|
||||
handle_corner_tl.layout.alignment = {1, -1}
|
||||
}
|
||||
if corner_tr {
|
||||
handle_corner_tr = ui_widget(name("corner_top_right"), flags)
|
||||
handle_corner_tr.layout.anchor = range2({1, 0}, {})
|
||||
handle_corner_tr.layout.alignment = {0, -1}
|
||||
}
|
||||
if corner_bl {
|
||||
handle_corner_bl = ui_widget("corner_bottom_left", flags)
|
||||
handle_corner_bl.layout.anchor = range2({}, {0, 1})
|
||||
handle_corner_bl.layout.alignment = { 1, 0 }
|
||||
}
|
||||
if corner_br {
|
||||
handle_corner_br = ui_widget("corner_bottom_right", flags)
|
||||
handle_corner_br.layout.anchor = range2({1, 0}, {0, 1})
|
||||
handle_corner_br.layout.alignment = {0, 0}
|
||||
}
|
||||
}
|
||||
if right {
|
||||
handle_right = ui_widget(name("resize_handle_right"), flags )
|
||||
handle_right.layout.anchor.left = 1
|
||||
}
|
||||
theme_handle( theme, {0, handle_width}, {0, handle_width})
|
||||
if top {
|
||||
handle_top = ui_widget(name("resize_handle_top"), flags )
|
||||
handle_top.layout.anchor.bottom = 1
|
||||
handle_top.layout.alignment = {0, -1}
|
||||
}
|
||||
if bottom {
|
||||
handle_bottom = ui_widget("resize_handle_bottom", flags)
|
||||
handle_bottom.layout.anchor.top = 1
|
||||
handle_bottom.layout.alignment = { 0, 0 }
|
||||
}
|
||||
theme_handle( theme, {0,0}, {handle_width, handle_width}, {.Fixed_Width, .Fixed_Height} )
|
||||
if corner_tl {
|
||||
handle_corner_tl = ui_widget(name("corner_top_left"), flags)
|
||||
handle_corner_tl.layout.alignment = {1, -1}
|
||||
}
|
||||
if corner_tr {
|
||||
handle_corner_tr = ui_widget(name("corner_top_right"), flags)
|
||||
handle_corner_tr.layout.anchor = range2({1, 0}, {})
|
||||
handle_corner_tr.layout.alignment = {0, -1}
|
||||
}
|
||||
if corner_bl {
|
||||
handle_corner_bl = ui_widget("corner_bottom_left", flags)
|
||||
handle_corner_bl.layout.anchor = range2({}, {0, 1})
|
||||
handle_corner_bl.layout.alignment = { 1, 0 }
|
||||
}
|
||||
if corner_br {
|
||||
handle_corner_br = ui_widget("corner_bottom_right", flags)
|
||||
handle_corner_br.layout.anchor = range2({1, 0}, {0, 1})
|
||||
handle_corner_br.layout.alignment = {0, 0}
|
||||
}
|
||||
#endregion("Handle & Corner construction")
|
||||
|
||||
process_handle_drag :: #force_inline proc ( handle : ^UI_Widget,
|
||||
direction : Vec2,
|
||||
@ -319,8 +395,6 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2,
|
||||
|
||||
shift_changed := (left_shift_held != prev_left_shift_held)
|
||||
|
||||
need_to_change_alignment_and_pos := pressed || shift_changed
|
||||
|
||||
if active
|
||||
{
|
||||
if pressed
|
||||
@ -379,8 +453,6 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2,
|
||||
was_dragging = false
|
||||
start_size = 0
|
||||
}
|
||||
// text = active_context.root.label
|
||||
// style.text_color = Color_White
|
||||
|
||||
prev_left_shift_held = handle.left_shift_held
|
||||
prev_alignment = align_adjsutment
|
||||
@ -433,14 +505,13 @@ UI_ScrollBox :: struct {
|
||||
}
|
||||
|
||||
ui_scroll_box :: proc( label : string, flags : UI_BoxFlags ) -> (scroll_box : UI_ScrollBox) {
|
||||
fatal("NOT IMPLEMENTED")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ui_scrollable_view( )
|
||||
|
||||
#region("Text")
|
||||
|
||||
ui_text :: proc( label : string, content : StrRunesPair, flags : UI_BoxFlags = {} ) -> UI_Widget
|
||||
{
|
||||
// profile(#procedure)
|
||||
@ -510,7 +581,6 @@ UI_VBox :: struct {
|
||||
direction : UI_LayoutDirectionY,
|
||||
}
|
||||
|
||||
// Boilerplate creation
|
||||
ui_vbox_begin :: proc( direction : UI_LayoutDirectionY, label : string, flags : UI_BoxFlags = {}, compute_layout := false ) -> (vbox : UI_VBox) {
|
||||
// profile(#procedure)
|
||||
vbox.direction = direction
|
||||
|
Loading…
Reference in New Issue
Block a user