From: Brendan Hansen Date: Tue, 5 Oct 2021 21:22:21 +0000 (-0500) Subject: started work on automatic settings window X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=da48ded925d6cef233b87aac81f78004681b3902;p=onyx-wasm-analyzer.git started work on automatic settings window --- diff --git a/src/app/app.onyx b/src/app/app.onyx index d1acebb..6ab1cc2 100644 --- a/src/app/app.onyx +++ b/src/app/app.onyx @@ -352,7 +352,7 @@ draw :: () { gfx.identity(); ui.menubar(menu_bar, ^search_buffer, ui.Menu_Bar_Option.[ .{ label = "File" }, - .{ label = "Test" }, + .{ label = "Settings", action = settings_window_show }, ]); } diff --git a/src/app/debug_log.onyx b/src/app/debug_log.onyx index 47cfacf..d743fd1 100644 --- a/src/app/debug_log.onyx +++ b/src/app/debug_log.onyx @@ -53,7 +53,7 @@ debug_log_clear :: () { debug_log :: (severity: Severity, format: str, args: ..any) { if severity < minimum_severity do return; - buffer1: [4096] u8; + buffer1, buffer2: [4096] u8; s := conv.str_format_va(buffer1, format, args); lines := string.split(s, #char "\n", context.temp_allocator); @@ -61,7 +61,6 @@ debug_log :: (severity: Severity, format: str, args: ..any) { for l: lines { if l.count == 0 do continue; - buffer2: [4096] u8; s = conv.str_format(buffer2, "[{}] {}\n", severity, l); line := string.alloc_copy(s, line_alloc); @@ -72,32 +71,39 @@ debug_log :: (severity: Severity, format: str, args: ..any) { draw_debug_log :: (window_rectangle: ui.Rectangle, site := #callsite) { if debug_log_y_offset == 0.0f do return; + Font_Size :: 0.75f; + + ui.use_font(config.Fonts.FiraCode.index); + line_height := ui.get_text_height("M", size=Font_Size); + r, _ := ui.Flow.split_horizontal(window_rectangle, top_percent=.5); height := ui.Rectangle.height(r); r.y0 -= height * (1 - debug_log_y_offset); r.y1 -= height * (1 - debug_log_y_offset); sh := ui.scrollable_region_start(r, state=^scrollable_region, .{ - minimum_x = 0, maximum_x = 0, - minimum_y = 32.0f * ~~(log_buffer.lines.count - ~~(height / 32)), + minimum_x = 0, maximum_x = ui.Rectangle.width(window_rectangle), + minimum_y = line_height * ~~(log_buffer.lines.count - ~~(height / line_height)), maximum_y = 0, }); defer ui.scrollable_region_stop(); - r.y0 -= 32.0f * ~~log_buffer.lines.count; + r.y0 -= line_height * ~~log_buffer.lines.count; visible_rectangle := sh->get_visible_rectangle(); - background_color := config.Colors.background; - background_color.a = 0.8; + // background_color := config.Colors.background; + // background_color.a = 0.8; + background_color := gfx.Color4.{ 0, 0, 0, 0.8 }; ui.draw_rect(visible_rectangle, color=background_color); text_theme := ui.default_text_theme; text_theme.font = config.Fonts.FiraCode.index; - text_theme.text_color = .{ 0.2, 0.5, 0.2 }; + text_theme.font_size = Font_Size; + text_theme.text_color = .{ 0.2, 0.8, 0.2 }; text_rect: ui.Rectangle; while i := cast(i32) log_buffer.lines.count - 1; i >= 0 { - r, text_rect = ui.Flow.split_horizontal(r, bottom_height=32); + r, text_rect = ui.Flow.split_horizontal(r, bottom_height=line_height); if ui.Rectangle.intersects(text_rect, visible_rectangle) { ui.draw_text(text_rect, log_buffer.lines[i], theme=^text_theme); @@ -107,6 +113,7 @@ draw_debug_log :: (window_rectangle: ui.Rectangle, site := #callsite) { } r = visible_rectangle; + text_theme.font_size = 1; clear_button_rect := ui.Rectangle.{ x0 = r.x1 - 200, x1 = r.x1, y0 = r.y0, y1 = r.y0 + 50, diff --git a/src/app/settings.onyx b/src/app/settings.onyx index b9b9d34..04ed206 100644 --- a/src/app/settings.onyx +++ b/src/app/settings.onyx @@ -12,6 +12,24 @@ package app Application_Settings :: struct { colorscheme := Colorscheme.Undefined; + + coolness : Slider_Option(i32) = .{ 5, 0, 5 }; + badness : Slider_Option(f32) = .{ 0, 0, 10 }; + + test : Test = .{ 5, 5 }; + test2 : Test = .{ 0, 0 }; + wrapped : Wrapper = .{ value = 40 }; + + Test :: struct { x: i32; y: f32; } + Wrapper :: struct { + test := Test.{ 10, 10 }; + value: i32; + } +} + +Slider_Option :: struct (T: type_expr) { + value: T; + min, max: T; } settings_save :: (settings: ^Application_Settings) { @@ -43,3 +61,155 @@ settings_load :: (settings: ^Application_Settings) { if colorscheme != .Undefined do settings.colorscheme = colorscheme; else do settings.colorscheme = .Dark; } + + + + +// +// Settings Window +// + +#private_file { + window_id :: "settings" + window_name :: "Settings" + + ui :: package ui + + @Temporary + settings_any: any; +} + +make_any :: macro (v: $T) => any.{ ^v, T }; + +settings_window_show :: () { + settings_any = make_any(state.settings); + + open_window(window_id, window_name, .{ 0, 0 }, settings_window_draw, draw_data=^settings_any); + focus_window(window_id); + move_window_to_top(window_id); + + open_window("settings_dummy", "Settings Dummy", .{ 0, 0 }, (_, win) => { + buffer: [1024] u8; + msg := conv.str_format(buffer, "{*p}", ^state.settings); + ui.draw_text(.{ 0, 0, win.window_state.size.x, win.window_state.size.y }, msg); + }); +} + +settings_window_draw :: (obj: ^any, win: ^Application_Window) { + // Uniqueness counter + #persist counter: i32; + counter = 0; + + rect := ui.Rectangle.{ 0, 0, win.window_state.size.x, win.window_state.size.y }; + + #persist scrollable_region := ui.Scrollable_Region_State.{}; + handle := ui.scrollable_region_start(rect, state=^scrollable_region, .{ + minimum_x = 0, maximum_x = 0, + minimum_y = 0, maximum_y = 100000.0f, + }); + defer ui.scrollable_region_stop(); + + // Rectangle of the visible scroll region, transformed to have the top-left of + // the window at 0, 0 + win_rect := handle->get_visible_rectangle(); + + rect = ui.Flow.padding(rect, left=8, right=8); + rect.y1 = 1000000.0f; + + render_settings(^rect, win_rect, obj); + + // Needs to be separate because this part is recursive + render_settings :: (rect: ^ui.Rectangle, win_rect: ui.Rectangle, obj: ^any) { + use type_info; + + #persist msg_buffer : [512] u8; + #persist tmp_rect : ui.Rectangle; + + type := get_type_info(obj.type); + assert(type.kind == .Struct, "Expected a struct type"); + + settings_type := cast(^Type_Info_Struct) type; + + heading_theme := ui.default_text_theme; + heading_theme.font_size = 1.25f; + + for ^member: settings_type.members { + counter += 1; + member_type := get_type_info(member.type); + + tmp_rect, *rect = ui.Flow.split_horizontal(*rect, top_height=48); + if ui.Rectangle.intersects(tmp_rect, win_rect) { + ui.draw_text(tmp_rect, member.name, theme=^heading_theme); + } + + switch member_type.kind { + case .Enum { + value := cast(^i32) (cast(^u8) obj.data + member.offset); + + enum_type := cast(^Type_Info_Enum) member_type; + for ^enum_member: enum_type.members { + counter += 1; + tmp_rect, *rect = ui.Flow.split_horizontal(*rect, top_height=32); + + if ui.Rectangle.intersects(tmp_rect, win_rect) { + ui.radio(ui.Flow.padding(tmp_rect, left=32), + value, cast(i32) enum_member.value, + enum_member.name, increment=counter); + } + } + } + + case .Struct { + struct_type := cast(^Type_Info_Struct) member_type; + sub_object := cast(rawptr) (cast(^u8) obj.data + member.offset); + + switch member.type { + case #type Slider_Option(i32) do render_slider_option(i32, sub_object); + case #type Slider_Option(f32) do render_slider_option(f32, sub_object); + + case #default { + rect.x0 += 32; + defer rect.x0 -= 32; + + sub_object_any := any.{ sub_object, member.type }; + render_settings(rect, win_rect, ^sub_object_any); + } + } + } + + case .Basic do switch member.type { + case i32 { + value := cast(^i32) (cast(^u8) obj.data + member.offset); + + tmp_rect, *rect = ui.Flow.split_horizontal(*rect, top_height=32); + if ui.Rectangle.intersects(tmp_rect, win_rect) { + ui.slider(tmp_rect, value, -10, 10, increment=counter); + ui.draw_text(tmp_rect, conv.str_format(msg_buffer, " Current: {}", *value)); + } + } + + case f32 { + value := cast(^f32) (cast(^u8) obj.data + member.offset); + + tmp_rect, *rect = ui.Flow.split_horizontal(*rect, top_height=32); + if ui.Rectangle.intersects(tmp_rect, win_rect) { + ui.slider(tmp_rect, value, 0, 100, increment=counter); + ui.draw_text(tmp_rect, conv.str_format(msg_buffer, " Current: {}", *value)); + } + } + } + } + } + } + + render_slider_option :: macro ($T: type_expr, so: rawptr) { + so_ := cast(^Slider_Option(T)) so; + + tmp_rect, *rect = ui.Flow.split_horizontal(*rect, top_height=32); + + if ui.Rectangle.intersects(tmp_rect, win_rect) { + ui.slider(tmp_rect, ^so_.value, so_.min, so_.max, increment=counter); + ui.draw_text(tmp_rect, conv.str_format(msg_buffer, " Current: {}", so_.value)); + } + } +} diff --git a/src/ui/menubar.onyx b/src/ui/menubar.onyx index c3fbcc9..efa0cd5 100644 --- a/src/ui/menubar.onyx +++ b/src/ui/menubar.onyx @@ -32,7 +32,9 @@ menubar :: (r: Rectangle, @Temporary search_buffer: ^String_Buffer, options: [] for option: options |> iter.from_array() |> iter.enumerate() { button_rect, menu_rect = Flow.split_vertical(menu_rect, left_width=100); - button(button_rect, option.value.label, theme=^menu_button_theme, increment=option.index); + if button(button_rect, option.value.label, theme=^menu_button_theme, increment=option.index) { + option.value.action(); + } } _, search_rect := Flow.split_vertical(menu_rect, right_width=300); diff --git a/src/ui/window.onyx b/src/ui/window.onyx index 5b11afe..7913ca5 100644 --- a/src/ui/window.onyx +++ b/src/ui/window.onyx @@ -136,6 +136,8 @@ window_start :: (use state: ^Window_State, site := #callsite, increment := 0) -> close_theme := default_button_theme; close_theme.border_width = 0; + close_theme.background_color = .{ 0.5, 0.2, 0.2 }; + close_theme.hover_color = .{ 1.0, 0.4, 0.4 }; if button(.{ x + w - 48, y - bar_height - border_width, x + w + border_width, y }, "X", theme=^close_theme, increment=increment + hash) { state.should_close = true; }