diff --git a/code/sectr/app/logger_scope.odin b/code/sectr/app/logger_scope.odin index d12baf2..9b0f4dc 100644 --- a/code/sectr/app/logger_scope.odin +++ b/code/sectr/app/logger_scope.odin @@ -2,11 +2,23 @@ package sectr UI_LoggerScope :: struct { - + using window : UI_Window, } -ui_logger_scope :: proc( captures : rawptr = nil ) -> ( should_raise : b32 = false ) +ui_logger_scope_builder :: proc( captures : rawptr = nil ) -> ( should_raise : b32 = false ) { profile("Logger Scope") + + logger_scope := cast(^UI_LoggerScope) captures + using logger_scope + + scope(theme_window_panel) + dragged, resized, maximized := ui_window_begin( & window, "Logger Scope: Window") + + should_raise |= dragged | resized | maximized return } + +ui_logger_scope_open :: #force_inline proc "contextless" () { + get_state().screen_ui.logger_scope.is_open = true +} diff --git a/code/sectr/app/screen.odin b/code/sectr/app/screen.odin index fb41742..4f670ca 100644 --- a/code/sectr/app/screen.odin +++ b/code/sectr/app/screen.odin @@ -1,12 +1,10 @@ package sectr UI_ScreenMenuBar :: struct { - pos, size : Vec2, - container : UI_HBox, - settings_btn : struct - { - using widget : UI_Widget, - } + pos, size : Vec2, + container : UI_HBox, + logger_scope_btn : UI_Widget, + settings_btn : UI_Widget } UI_ScreenState :: struct @@ -19,6 +17,7 @@ UI_ScreenState :: struct // docked : UI_Docking, menu_bar : UI_ScreenMenuBar, + logger_scope : UI_LoggerScope, settings_menu : UI_SettingsMenu } @@ -37,6 +36,7 @@ ui_screen_tick :: proc( screen_ui : ^UI_ScreenState ) { ui_graph_build( screen_ui ) ui_floating_manager( & screen_ui.floating ) ui_floating("Menu Bar", & screen_ui.menu_bar, ui_screen_menu_bar_builder) + ui_floating("Logger Scope", & screen_ui.logger_scope, ui_logger_scope_builder) ui_floating("Settings Menu", & screen_ui.settings_menu, ui_settings_menu_builder) } @@ -98,7 +98,12 @@ ui_screen_menu_bar_builder :: proc( captures : rawptr = nil ) -> (should_raise : 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.flags = { + .Fixed_Position_X, .Fixed_Position_Y, + // .Min_Size_To_Content_X, + .Fixed_Width, .Fixed_Height, + .Origin_At_Anchor_Center + } layout.pos = pos layout.size = range2( size, {}) text = str_intern("menu_bar") @@ -120,10 +125,19 @@ ui_screen_menu_bar_builder :: proc( captures : rawptr = nil ) -> (should_raise : spacer.layout.flags |= {.Fixed_Width} spacer.layout.size.min.x = 30 + scope(theme_button) + Build_Logger_Scope_Btn: { + using logger_scope_btn + logger_scope_btn = ui_button("Menu Bar: Logger Scope Btn") + text = str_intern("Log Scope") + layout.flags = { .Scale_Width_By_Height_Ratio } + layout.size.ratio.x = 2.0 + if pressed do ui_logger_scope_open() + } + Build_Settings_Btn: { - scope(theme_button) using settings_btn - widget = ui_button("Menu Bar: Settings Btn") + settings_btn = ui_button("Menu Bar: Settings Btn") text = str_intern("Settings") layout.flags = { .Scale_Width_By_Height_Ratio } layout.size.ratio.x = 2.0 diff --git a/code/sectr/app/settings_menu.odin b/code/sectr/app/settings_menu.odin index 7fde283..dc778fa 100644 --- a/code/sectr/app/settings_menu.odin +++ b/code/sectr/app/settings_menu.odin @@ -23,8 +23,8 @@ ui_settings_menu_builder :: proc( captures : rawptr = nil ) -> ( should_raise : { profile("Settings Menu") settings_menu := cast(^UI_SettingsMenu) captures - if ! settings_menu.is_open do return + app_color := app_color_theme() using settings_menu @@ -32,7 +32,7 @@ ui_settings_menu_builder :: proc( captures : rawptr = nil ) -> ( should_raise : if size.y < min_size.y do size.y = min_size.y scope(theme_window_panel) - container = ui_widget("Settings Menu", {}); + container = ui_widget("Settings Menu: Window", {}); setup_container: { using container @@ -57,6 +57,7 @@ ui_settings_menu_builder :: proc( captures : rawptr = nil ) -> ( should_raise : dragged := ui_resizable_handles( & container, & pos, & size) should_raise |= dragged + // TODO(Ed): This demonstrated a minimum viable-size window to content, however we still need to support a scroll box and switch this window to that. old_vbox := ui_box_from_key(get_ui_context_mut().prev_cache, ui_key_from_string("Settings Menu: VBox")) if old_vbox != nil { @@ -77,7 +78,7 @@ ui_settings_menu_builder :: proc( captures : rawptr = nil ) -> ( should_raise : vbox := ui_vbox_begin( .Top_To_Bottom, "Settings Menu: VBox", {.Mouse_Clickable}, compute_layout = true ) { - // should_raise |= b32(vbox.active) + should_raise |= b32(vbox.active) ui_parent(vbox) Frame_Bar: @@ -124,6 +125,7 @@ ui_settings_menu_builder :: proc( captures : rawptr = nil ) -> ( should_raise : app_config_closed: { dd_app_config.title.layout.font_size = 12 + should_raise |= cast(b32) dd_app_config.btn.active if ! dd_app_config.is_open do break app_config_closed ui_settings_entry_inputbox :: proc( input_box : ^UI_TextInputBox, is_even : bool, label : string, setting_title : StrRunesPair, input_policy : UI_TextInput_Policy ) diff --git a/code/sectr/app/state.odin b/code/sectr/app/state.odin index 9a449ca..b6c6690 100644 --- a/code/sectr/app/state.odin +++ b/code/sectr/app/state.odin @@ -285,10 +285,7 @@ get_frametime :: #force_inline proc "contextless" () -> FrameTime { retur get_default_font :: #force_inline proc "contextless" () -> FontID { return get_state().default_font } get_input_state :: #force_inline proc "contextless" () -> InputState { return (get_state().input ^) } -get_ui_context_mut :: #force_inline proc "contextless" () -> ^UI_State { return get_state().ui_context } - -set_ui_context :: #force_inline proc "contextless" ( ui : ^UI_State ) { - get_state().ui_context = ui -} +get_ui_context_mut :: #force_inline proc "contextless" () -> ^UI_State { return get_state().ui_context } +set_ui_context :: #force_inline proc "contextless" ( ui : ^UI_State ) { get_state().ui_context = ui } #endregion("State") diff --git a/code/sectr/engine/client_api.odin b/code/sectr/engine/client_api.odin index 24986d3..f2efae5 100644 --- a/code/sectr/engine/client_api.odin +++ b/code/sectr/engine/client_api.odin @@ -313,8 +313,9 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem using screen_ui menu_bar.pos = { -260, -200 } // menu_bar.pos = Vec2(app_window.extent) * { -1, 1 } - menu_bar.size = {140, 40} + menu_bar.size = {240, 40} + logger_scope.min_size = {360, 200} settings_menu.min_size = {360, 200} } diff --git a/code/sectr/ui/widgets.odin b/code/sectr/ui/widgets.odin index da3237d..8f023aa 100644 --- a/code/sectr/ui/widgets.odin +++ b/code/sectr/ui/widgets.odin @@ -320,7 +320,7 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2, name :: proc( label : string ) -> string { parent_label := (transmute(^string) context.user_ptr) ^ - return str_intern(str_fmt("%v: %v", parent_label, label )).str + return str_intern(str_fmt("%v.%v", parent_label, label )).str } context.user_ptr = & parent.label @@ -345,7 +345,7 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2, handle_top.layout.alignment = { 0, 0 } } if bottom { - handle_bottom = ui_widget("resize_handle_bottom", flags) + handle_bottom = ui_widget(name("resize_handle_bottom"), flags) handle_bottom.layout.anchor.top = 1 handle_bottom.layout.alignment = { 0, 1 } } @@ -361,12 +361,12 @@ ui_resizable_handles :: proc( parent : ^UI_Widget, pos : ^Vec2, size : ^Vec2, handle_corner_tr.layout.alignment = { 0, 0 } } if corner_bl { - handle_corner_bl = ui_widget("corner_bottom_left", flags) + handle_corner_bl = ui_widget(name("corner_bottom_left"), flags) handle_corner_bl.layout.anchor = range2({}, {0, 1}) handle_corner_bl.layout.alignment = { 1, 1 } } if corner_br { - handle_corner_br = ui_widget("corner_bottom_right", flags) + handle_corner_br = ui_widget(name("corner_bottom_right"), flags) handle_corner_br.layout.anchor = range2({1, 0}, {0, 1}) handle_corner_br.layout.alignment = { 0, 1 } } diff --git a/code/sectr/ui/window.odin b/code/sectr/ui/window.odin new file mode 100644 index 0000000..3ddab5e --- /dev/null +++ b/code/sectr/ui/window.odin @@ -0,0 +1,97 @@ +package sectr + +UI_Window :: struct +{ + frame : UI_Widget, + frame_bar : UI_HBox, + tile_text : UI_Widget, + maximize_btn : UI_Widget, + close_btn : UI_Widget, + position : Vec2, + size : Vec2, + min_size : Vec2, + is_open : b32, + is_maximized : b32, +} + +ui_window_begin :: proc( window : ^UI_Window, label : string, + title : StrRunesPair = {}, + closable := true, + maximizable := true, + draggable := true, + resizable := true +) -> (dragged, resized, maximized : b32) +{ + using window + if ! is_open do return + + if size.x < min_size.x do size.x = min_size.x + if size.y < min_size.y do size.y = min_size.y + + frame = ui_widget(label, {}) + using frame + + if ! is_maximized + { + layout.flags = { + // .Size_To_Content, + .Fixed_Width, .Fixed_Height, + // .Min_Size_To_Content_Y, + .Fixed_Position_X, .Fixed_Position_Y, + .Origin_At_Anchor_Center + } + layout.pos = position + layout.size = range2( size, {}) + } + else + { + layout.flags = {.Origin_At_Anchor_Center } + layout.pos = {} + } + + if resizable { + resized = ui_resizable_handles( & frame, & position, & size) + } + + if len(title.str) == 0 && ! closable && ! maximizable && ! draggable do return + ui_parent(frame) + + draggable_flag : UI_BoxFlags = draggable ? {.Mouse_Clickable} : {} + + scope(theme_window_bar) + frame_bar = ui_hbox(.Left_To_Right, str_intern_fmt("%v.frame_bar", label). str, draggable_flag); + ui_parent(frame_bar) + + scope(theme_text) + tile_text = ui_text( str_intern_fmt("%v.title_text", label).str, title, {.Disabled}); { + using tile_text + layout.anchor.ratio.x = 1.0 + layout.margins = { 0, 0, 15, 0} + layout.font_size = 14 + } + + scope(theme_window_bar_btn) + maximize_btn = ui_button( str_intern_fmt("%v.maximize_btn", label).str ); { + using maximize_btn + if maximize_btn.pressed { + is_maximized = ~is_maximized + maximized = true + } + if is_maximized do text = str_intern("min") + else do text = str_intern("max") + } + close_btn = ui_button( str_intern_fmt("%v.close_btn", label).str ); { + using close_btn + text = str_intern("close") + if close_btn.hot do style.bg_color = app_color_theme().window_btn_close_bg_hot + if close_btn.pressed do is_open = false + style.corner_radii = { 0, 0, 0, 0 } + } + + if frame_bar.active { + position += get_input_state().mouse.delta + dragged = true + } + + return +}