From b20f003e7fe7c0e7f3319206048cb65f46c86d5d Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Thu, 1 May 2025 14:09:05 -0700 Subject: [PATCH] tooltip coverage for all command evaluations, major top-bar simplification, anchored tooltips --- src/raddbg/generated/raddbg.meta.c | 24 +-- src/raddbg/raddbg.mdesk | 32 ++-- src/raddbg/raddbg_core.c | 246 +++++++---------------------- src/raddbg/raddbg_widgets.c | 64 ++++---- src/raddbg/raddbg_widgets.h | 2 +- src/ui/ui_core.c | 17 ++ src/ui/ui_core.h | 1 + 7 files changed, 144 insertions(+), 242 deletions(-) diff --git a/src/raddbg/generated/raddbg.meta.c b/src/raddbg/generated/raddbg.meta.c index cbfad240..b2f8aab6 100644 --- a/src/raddbg/generated/raddbg.meta.c +++ b/src/raddbg/generated/raddbg.meta.c @@ -211,8 +211,8 @@ RD_VocabInfo rd_vocab_info_table[333] = {str8_lit_comp("select_unwind"), str8_lit_comp(""), str8_lit_comp("Select Unwind"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("up_one_frame"), str8_lit_comp(""), str8_lit_comp("Up One Frame"), str8_lit_comp(""), RD_IconKind_UpArrow}, {str8_lit_comp("down_one_frame"), str8_lit_comp(""), str8_lit_comp("Down One Frame"), str8_lit_comp(""), RD_IconKind_DownArrow}, -{str8_lit_comp("select_entity"), str8_lit_comp(""), str8_lit_comp("Select Entity"), str8_lit_comp(""), RD_IconKind_RadioHollow}, -{str8_lit_comp("deselect_entity"), str8_lit_comp(""), str8_lit_comp("Deselect Entity"), str8_lit_comp(""), RD_IconKind_RadioFilled}, +{str8_lit_comp("select_entity"), str8_lit_comp(""), str8_lit_comp("Select"), str8_lit_comp(""), RD_IconKind_RadioHollow}, +{str8_lit_comp("deselect_entity"), str8_lit_comp(""), str8_lit_comp("Deselect"), str8_lit_comp(""), RD_IconKind_RadioFilled}, {str8_lit_comp("inc_window_font_size"), str8_lit_comp(""), str8_lit_comp("Increase Window Font Size"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("dec_window_font_size"), str8_lit_comp(""), str8_lit_comp("Decrease Window Font Size"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("inc_view_font_size"), str8_lit_comp(""), str8_lit_comp("Increase View Font Size"), str8_lit_comp(""), RD_IconKind_Null}, @@ -331,15 +331,15 @@ RD_VocabInfo rd_vocab_info_table[333] = {str8_lit_comp("toggle_watch_expr"), str8_lit_comp(""), str8_lit_comp("Toggle Watch Expression"), str8_lit_comp(""), RD_IconKind_Binoculars}, {str8_lit_comp("toggle_watch_expr_at_cursor"), str8_lit_comp(""), str8_lit_comp("Toggle Watch Expression At Cursor"), str8_lit_comp(""), RD_IconKind_Binoculars}, {str8_lit_comp("toggle_watch_expr_at_mouse"), str8_lit_comp(""), str8_lit_comp("Toggle Watch Expression At Mouse"), str8_lit_comp(""), RD_IconKind_Binoculars}, -{str8_lit_comp("enable_cfg"), str8_lit_comp(""), str8_lit_comp("Enable Config Tree"), str8_lit_comp(""), RD_IconKind_CheckHollow}, -{str8_lit_comp("disable_cfg"), str8_lit_comp(""), str8_lit_comp("Disable Config Tree"), str8_lit_comp(""), RD_IconKind_CheckFilled}, -{str8_lit_comp("select_cfg"), str8_lit_comp(""), str8_lit_comp("Select Config Tree"), str8_lit_comp(""), RD_IconKind_RadioHollow}, -{str8_lit_comp("deselect_cfg"), str8_lit_comp(""), str8_lit_comp("Deselect Config Tree"), str8_lit_comp(""), RD_IconKind_RadioFilled}, -{str8_lit_comp("remove_cfg"), str8_lit_comp(""), str8_lit_comp("Remove Config Tree"), str8_lit_comp(""), RD_IconKind_Trash}, -{str8_lit_comp("name_cfg"), str8_lit_comp(""), str8_lit_comp("Name Config Tree"), str8_lit_comp(""), RD_IconKind_Null}, -{str8_lit_comp("condition_cfg"), str8_lit_comp(""), str8_lit_comp("Condition Config Tree"), str8_lit_comp(""), RD_IconKind_Null}, -{str8_lit_comp("duplicate_cfg"), str8_lit_comp(""), str8_lit_comp("Duplicate Config Tree"), str8_lit_comp(""), RD_IconKind_Duplicate}, -{str8_lit_comp("relocate_cfg"), str8_lit_comp(""), str8_lit_comp("Relocate Config Tree"), str8_lit_comp(""), RD_IconKind_Null}, +{str8_lit_comp("enable_cfg"), str8_lit_comp(""), str8_lit_comp("Enable"), str8_lit_comp(""), RD_IconKind_CheckHollow}, +{str8_lit_comp("disable_cfg"), str8_lit_comp(""), str8_lit_comp("Disable"), str8_lit_comp(""), RD_IconKind_CheckFilled}, +{str8_lit_comp("select_cfg"), str8_lit_comp(""), str8_lit_comp("Select"), str8_lit_comp(""), RD_IconKind_RadioHollow}, +{str8_lit_comp("deselect_cfg"), str8_lit_comp(""), str8_lit_comp("Deselect"), str8_lit_comp(""), RD_IconKind_RadioFilled}, +{str8_lit_comp("remove_cfg"), str8_lit_comp(""), str8_lit_comp("Remove"), str8_lit_comp(""), RD_IconKind_Trash}, +{str8_lit_comp("name_cfg"), str8_lit_comp(""), str8_lit_comp("Name"), str8_lit_comp(""), RD_IconKind_Null}, +{str8_lit_comp("condition_cfg"), str8_lit_comp(""), str8_lit_comp("Condition"), str8_lit_comp(""), RD_IconKind_Null}, +{str8_lit_comp("duplicate_cfg"), str8_lit_comp(""), str8_lit_comp("Duplicate"), str8_lit_comp(""), RD_IconKind_Duplicate}, +{str8_lit_comp("relocate_cfg"), str8_lit_comp(""), str8_lit_comp("Relocate"), str8_lit_comp(""), RD_IconKind_Null}, {str8_lit_comp("add_breakpoint"), str8_lit_comp(""), str8_lit_comp("Add Breakpoint"), str8_lit_comp(""), RD_IconKind_CircleFilled}, {str8_lit_comp("add_address_breakpoint"), str8_lit_comp(""), str8_lit_comp("Add Address Breakpoint"), str8_lit_comp(""), RD_IconKind_CircleFilled}, {str8_lit_comp("toggle_breakpoint"), str8_lit_comp(""), str8_lit_comp("Toggle Breakpoint"), str8_lit_comp(""), RD_IconKind_CircleFilled}, @@ -400,7 +400,7 @@ RD_VocabInfo rd_vocab_info_table[333] = RD_NameSchemaInfo rd_name_schema_info_table[23] = { {str8_lit_comp("user"), str8_lit_comp("x:\n{\n //- rjf: animations\n @default(1) 'hover_animations': bool,\n @default(1) 'press_animations': bool,\n @default(0) 'focus_animations': bool,\n @default(1) 'tooltip_animations': bool,\n @default(1) 'menu_animations': bool,\n @default(1) 'scrolling_animations': bool,\n\n //- rjf: fonts\n @display_name('UI Font') @description(\"The name of, or path to, the font used when displaying non-code UI elements.\")\n 'main_font': string,\n @display_name('Code Font') @description(\"The name of, or path to, the font used when displaying code.\")\n 'code_font': string,\n\n //- rjf: theme\n @display_name('Theme Preset') @description(\"The selected built-in theme preset.\")\n 'theme_preset': string,\n @no_expand @display_name('Theme File') @description(\"The path from which theme data is loaded, overriding the preset.\")\n 'theme_file': path,\n @display_name('Theme Colors') @description(\"Additional theme colors which are applied on top of the theme file or preset.\")\n 'theme_colors': query,\n\n //- rjf: thread & breakpoint decorations\n @default(1) @display_name('Thread Lines') @description(\"Controls whether or not a long horizontal line is drawn before the next line or instruction that the selected thread will execute in source and disassembly views.\")\n 'thread_lines': bool,\n @default(1) @display_name('Thread Glow') @description(\"Controls whether or not a glowing effect is drawn on the selected thread in source and disassembly views.\")\n 'thread_glow': bool,\n @default(1) @display_name('Breakpoint Lines') @description(\"Controls whether or not a long horizontal line is drawn before the line or instruction at which a breakpoint is placed, in source and disassembly views.\")\n 'breakpoint_lines': bool,\n @default(1) @display_name('Breakpoint Glow') @description(\"Controls whether or not a glowing effect is drawn on breakpoints in source and disassembly views.\")\n 'breakpoint_glow': bool,\n\n //- rjf: occluding background settings\n @default(0) @display_name('Opaque Backgrounds') @description(\"Controls whether or not all floating background colors are forced to be fully opaque.\")\n 'opaque_backgrounds': bool,\n @default(1) @display_name('Background Blur') @description(\"Controls whether or not occluded regions behind floating elements are blurred.\")\n 'background_blur': bool,\n\n //- rjf: appearance settings\n @default(1) @display_name('Drop Shadows') @description(\"Controls whether or not drop shadows are drawn.\")\n 'drop_shadows': bool,\n @default(1.f) @display_name('Rounded Corner Amount') @description(\"Controls the degree to which UI corners are rounded.\")\n 'rounded_corner_amount': @range[0, 1] f32,\n\n //- rjf: code formatting settings\n @default(2) @display_name('User Tab Width') 'tab_width': @range[1, 32] u64,\n\n //- rjf: windows style menu bar\n @default(1) @display_name('Focus Menu Bar With Alt') @description(\"Mimics standard Windows behavior of focusing the menu bar using the Alt key.\")\n 'focus_menu_bar_with_alt': bool,\n}\n")}, -{str8_lit_comp("project"), str8_lit_comp("x:\n{\n @default(2) @display_name('Project Tab Width') 'tab_width': @range[1, 32] u64,\n @default(1) @display_name(\"Break On Win32 Control-C Exceptions\") @description(\"Code: 0x40010005\")\n win32_ctrl_c: bool;\n @default(1) @display_name(\"Break On Win32 Control-Break Exceptions\") @description(\"Code: 0x40010008\")\n win32_ctrl_break: bool;\n @default(0) @display_name(\"Break On Win32 WinRT Originate Error Exceptions\") @description(\"Code: 0x40080201\")\n win32_win_rt_originate_error: bool;\n @default(0) @display_name(\"Break On Win32 WinRT Transform Error Exceptions\") @description(\"Code: 0x40080202\")\n win32_win_rt_transform_error: bool;\n @default(0) @display_name(\"Break On Win32 RPC Call Cancelled Exceptions\") @description(\"Code: 0x0000071a\")\n win32_rpc_call_cancelled: bool;\n @default(0) @display_name(\"Break On Win32 Data Type Misalignment Exceptions\") @description(\"Code: 0x80000002\")\n win32_datatype_misalignment: bool;\n @default(1) @display_name(\"Break On Win32 Access Violation Exceptions\") @description(\"Code: 0xc0000005\")\n win32_access_violation: bool;\n @default(0) @display_name(\"Break On Win32 In Page Error Exceptions\") @description(\"Code: 0xc0000006\")\n win32_in_page_error: bool;\n @default(1) @display_name(\"Break On Win32 Invalid Handle Specified Exceptions\") @description(\"Code: 0xc0000008\")\n win32_invalid_handle: bool;\n @default(0) @display_name(\"Break On Win32 Not Enough Quota Exceptions\") @description(\"Code: 0xc0000017\")\n win32_not_enough_quota: bool;\n @default(0) @display_name(\"Break On Win32 Illegal Instruction Exceptions\") @description(\"Code: 0xc000001d\")\n win32_illegal_instruction: bool;\n @default(0) @display_name(\"Break On Win32 Cannot Continue From Exception Exceptions\") @description(\"Code: 0xc0000025\")\n win32_cannot_continue_exception: bool;\n @default(0) @display_name(\"Break On Win32 Invalid Exception Disposition Returned By Handler Exceptions\") @description(\"Code: 0xc0000026\")\n win32_invalid_exception_disposition: bool;\n @default(0) @display_name(\"Break On Win32 Array Bounds Exceeded Exceptions\") @description(\"Code: 0xc000008c\")\n win32_array_bounds_exceeded: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Denormal Operand Exceptions\") @description(\"Code: 0xc000008d\")\n win32_floating_point_denormal_operand: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Division By Zero Exceptions\") @description(\"Code: 0xc000008e\")\n win32_floating_point_division_by_zero: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Inexact Result Exceptions\") @description(\"Code: 0xc000008f\")\n win32_floating_point_inexact_result: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Invalid Operation Exceptions\") @description(\"Code: 0xc0000090\")\n win32_floating_point_invalid_operation: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Overflow Exceptions\") @description(\"Code: 0xc0000091\")\n win32_floating_point_overflow: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Stack Check Exceptions\") @description(\"Code: 0xc0000092\")\n win32_floating_point_stack_check: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Underflow Exceptions\") @description(\"Code: 0xc0000093\")\n win32_floating_point_underflow: bool;\n @default(0) @display_name(\"Break On Win32 Integer Division By Zero Exceptions\") @description(\"Code: 0xc0000094\")\n win32_integer_division_by_zero: bool;\n @default(0) @display_name(\"Break On Win32 Integer Overflow Exceptions\") @description(\"Code: 0xc0000095\")\n win32_integer_overflow: bool;\n @default(0) @display_name(\"Break On Win32 Privileged Instruction Exceptions\") @description(\"Code: 0xc0000096\")\n win32_privileged_instruction: bool;\n @default(0) @display_name(\"Break On Win32 Stack Overflow Exceptions\") @description(\"Code: 0xc00000fd\")\n win32_stack_overflow: bool;\n @default(0) @display_name(\"Break On Win32 Unable To Locate DLL Exceptions\") @description(\"Code: 0xc0000135\")\n win32_unable_to_locate_dll: bool;\n @default(0) @display_name(\"Break On Win32 Ordinal Not Found Exceptions\") @description(\"Code: 0xc0000138\")\n win32_ordinal_not_found: bool;\n @default(0) @display_name(\"Break On Win32 Entry Point Not Found Exceptions\") @description(\"Code: 0xc0000139\")\n win32_entry_point_not_found: bool;\n @default(0) @display_name(\"Break On Win32 DLL Initialization Failed Exceptions\") @description(\"Code: 0xc0000142\")\n win32_dll_initialization_failed: bool;\n @default(0) @display_name(\"Break On Win32 Floating Point SSE Multiple Faults Exceptions\") @description(\"Code: 0xc00002b4\")\n win32_floating_point_sse_multiple_faults: bool;\n @default(0) @display_name(\"Break On Win32 Floating Point SSE Multiple Traps Exceptions\") @description(\"Code: 0xc00002b5\")\n win32_floating_point_sse_multiple_traps: bool;\n @default(1) @display_name(\"Break On Win32 Assertion Failed Exceptions\") @description(\"Code: 0xc0000420\")\n win32_assertion_failed: bool;\n @default(0) @display_name(\"Break On Win32 Module Not Found Exceptions\") @description(\"Code: 0xc06d007e\")\n win32_module_not_found: bool;\n @default(0) @display_name(\"Break On Win32 Procedure Not Found Exceptions\") @description(\"Code: 0xc06d007f\")\n win32_procedure_not_found: bool;\n @default(1) @display_name(\"Break On Win32 Sanitizer Error Detected Exceptions\") @description(\"Code: 0xe073616e\")\n win32_sanitizer_error_detected: bool;\n @default(0) @display_name(\"Break On Win32 Sanitizer Raw Access Violation Exceptions\") @description(\"Code: 0xe0736171\")\n win32_sanitizer_raw_access_violation: bool;\n @default(1) @display_name(\"Break On Win32 DirectX Debug Layer Exceptions\") @description(\"Code: 0x0000087a\")\n win32_directx_debug_layer: bool;\n}\n")}, +{str8_lit_comp("project"), str8_lit_comp("x:\n{\n @default(2) @display_name('Project Tab Width') 'tab_width': @range[1, 32] u64,\n\n //- rjf: theme\n @display_name('Project Theme Preset') @description(\"The selected built-in project theme preset.\")\n 'theme_preset': string,\n @no_expand @display_name('Project Theme File') @description(\"The path from which project's theme data is loaded, overriding the preset.\")\n 'theme_file': path,\n @display_name('Project Theme Colors') @description(\"Additional theme colors which are applied on top of the project's theme file or preset.\")\n 'theme_colors': query,\n\n //- rjf: exception settings\n @default(1) @display_name(\"Break On Win32 Control-C Exceptions\") @description(\"Code: 0x40010005\")\n win32_ctrl_c: bool;\n @default(1) @display_name(\"Break On Win32 Control-Break Exceptions\") @description(\"Code: 0x40010008\")\n win32_ctrl_break: bool;\n @default(0) @display_name(\"Break On Win32 WinRT Originate Error Exceptions\") @description(\"Code: 0x40080201\")\n win32_win_rt_originate_error: bool;\n @default(0) @display_name(\"Break On Win32 WinRT Transform Error Exceptions\") @description(\"Code: 0x40080202\")\n win32_win_rt_transform_error: bool;\n @default(0) @display_name(\"Break On Win32 RPC Call Cancelled Exceptions\") @description(\"Code: 0x0000071a\")\n win32_rpc_call_cancelled: bool;\n @default(0) @display_name(\"Break On Win32 Data Type Misalignment Exceptions\") @description(\"Code: 0x80000002\")\n win32_datatype_misalignment: bool;\n @default(1) @display_name(\"Break On Win32 Access Violation Exceptions\") @description(\"Code: 0xc0000005\")\n win32_access_violation: bool;\n @default(0) @display_name(\"Break On Win32 In Page Error Exceptions\") @description(\"Code: 0xc0000006\")\n win32_in_page_error: bool;\n @default(1) @display_name(\"Break On Win32 Invalid Handle Specified Exceptions\") @description(\"Code: 0xc0000008\")\n win32_invalid_handle: bool;\n @default(0) @display_name(\"Break On Win32 Not Enough Quota Exceptions\") @description(\"Code: 0xc0000017\")\n win32_not_enough_quota: bool;\n @default(0) @display_name(\"Break On Win32 Illegal Instruction Exceptions\") @description(\"Code: 0xc000001d\")\n win32_illegal_instruction: bool;\n @default(0) @display_name(\"Break On Win32 Cannot Continue From Exception Exceptions\") @description(\"Code: 0xc0000025\")\n win32_cannot_continue_exception: bool;\n @default(0) @display_name(\"Break On Win32 Invalid Exception Disposition Returned By Handler Exceptions\") @description(\"Code: 0xc0000026\")\n win32_invalid_exception_disposition: bool;\n @default(0) @display_name(\"Break On Win32 Array Bounds Exceeded Exceptions\") @description(\"Code: 0xc000008c\")\n win32_array_bounds_exceeded: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Denormal Operand Exceptions\") @description(\"Code: 0xc000008d\")\n win32_floating_point_denormal_operand: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Division By Zero Exceptions\") @description(\"Code: 0xc000008e\")\n win32_floating_point_division_by_zero: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Inexact Result Exceptions\") @description(\"Code: 0xc000008f\")\n win32_floating_point_inexact_result: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Invalid Operation Exceptions\") @description(\"Code: 0xc0000090\")\n win32_floating_point_invalid_operation: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Overflow Exceptions\") @description(\"Code: 0xc0000091\")\n win32_floating_point_overflow: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Stack Check Exceptions\") @description(\"Code: 0xc0000092\")\n win32_floating_point_stack_check: bool;\n @default(0) @display_name(\"Break On Win32 Floating-Point Underflow Exceptions\") @description(\"Code: 0xc0000093\")\n win32_floating_point_underflow: bool;\n @default(0) @display_name(\"Break On Win32 Integer Division By Zero Exceptions\") @description(\"Code: 0xc0000094\")\n win32_integer_division_by_zero: bool;\n @default(0) @display_name(\"Break On Win32 Integer Overflow Exceptions\") @description(\"Code: 0xc0000095\")\n win32_integer_overflow: bool;\n @default(0) @display_name(\"Break On Win32 Privileged Instruction Exceptions\") @description(\"Code: 0xc0000096\")\n win32_privileged_instruction: bool;\n @default(0) @display_name(\"Break On Win32 Stack Overflow Exceptions\") @description(\"Code: 0xc00000fd\")\n win32_stack_overflow: bool;\n @default(0) @display_name(\"Break On Win32 Unable To Locate DLL Exceptions\") @description(\"Code: 0xc0000135\")\n win32_unable_to_locate_dll: bool;\n @default(0) @display_name(\"Break On Win32 Ordinal Not Found Exceptions\") @description(\"Code: 0xc0000138\")\n win32_ordinal_not_found: bool;\n @default(0) @display_name(\"Break On Win32 Entry Point Not Found Exceptions\") @description(\"Code: 0xc0000139\")\n win32_entry_point_not_found: bool;\n @default(0) @display_name(\"Break On Win32 DLL Initialization Failed Exceptions\") @description(\"Code: 0xc0000142\")\n win32_dll_initialization_failed: bool;\n @default(0) @display_name(\"Break On Win32 Floating Point SSE Multiple Faults Exceptions\") @description(\"Code: 0xc00002b4\")\n win32_floating_point_sse_multiple_faults: bool;\n @default(0) @display_name(\"Break On Win32 Floating Point SSE Multiple Traps Exceptions\") @description(\"Code: 0xc00002b5\")\n win32_floating_point_sse_multiple_traps: bool;\n @default(1) @display_name(\"Break On Win32 Assertion Failed Exceptions\") @description(\"Code: 0xc0000420\")\n win32_assertion_failed: bool;\n @default(0) @display_name(\"Break On Win32 Module Not Found Exceptions\") @description(\"Code: 0xc06d007e\")\n win32_module_not_found: bool;\n @default(0) @display_name(\"Break On Win32 Procedure Not Found Exceptions\") @description(\"Code: 0xc06d007f\")\n win32_procedure_not_found: bool;\n @default(1) @display_name(\"Break On Win32 Sanitizer Error Detected Exceptions\") @description(\"Code: 0xe073616e\")\n win32_sanitizer_error_detected: bool;\n @default(0) @display_name(\"Break On Win32 Sanitizer Raw Access Violation Exceptions\") @description(\"Code: 0xe0736171\")\n win32_sanitizer_raw_access_violation: bool;\n @default(1) @display_name(\"Break On Win32 DirectX Debug Layer Exceptions\") @description(\"Code: 0x0000087a\")\n win32_directx_debug_layer: bool;\n}\n")}, {str8_lit_comp("theme_color"), str8_lit_comp("@collection_commands(add_theme_color, fork_loaded_theme_colors, save_theme_colors)\n@row_commands(remove_cfg)\nx:\n{\n @display_name('Tags') tags: string,\n @display_name('Value') value: @color @hex u32,\n}\n")}, {str8_lit_comp("window"), str8_lit_comp("x:\n{\n //- rjf: text rasterization settings\n @default(1) @display_name('Smooth UI Text') @description(\"Controls whether or not UI text is fully anti-aliased, for a smoother appearance.\")\n 'smooth_ui_text': bool,\n @default(1) @display_name('Hint UI Text') @description(\"Controls whether or not UI text is hinted, for better text readability at small sizes.\")\n 'hint_ui_text': bool,\n @default(0) @display_name('Smooth Code Text') @description(\"Controls whether or not code text is fully anti-aliased, for a smoother appearance.\")\n 'smooth_code_text': bool,\n @default(1) @display_name('Hint Code Text') @description(\"Controls whether or not code text is hinted, for better text readability at small sizes.\")\n 'hint_code_text': bool,\n @default(11) @display_name('Window Font Size') @description(\"Controls the window's default font size. Does not apply to tabs with their own font size set.\")\n 'font_size': @range[6, 72] u64,\n\n //- rjf: size settings\n @default(3.f) @display_name('Window Row Height') @description(\"Controls the window's default row height, in multiples of the font size. Does not apply to tabs with their own row height set.\")\n 'row_height': @range[1.75f, 5.f] f32,\n @default(3.f) @description(\"Controls the height of tabs, in multiples of the font size.\")\n 'tab_height': @range[1.75f, 5.f] f32,\n}\n")}, {str8_lit_comp("tab"), str8_lit_comp("@row_commands(duplicate_tab, close_tab)\nx:\n{\n @default(11) @display_name('Tab Font Size') @description(\"Controls the tab's font size.\")\n 'font_size': @range[6, 72] u64,\n}\n")}, diff --git a/src/raddbg/raddbg.mdesk b/src/raddbg/raddbg.mdesk index 8cdd5a92..7a302ff9 100644 --- a/src/raddbg/raddbg.mdesk +++ b/src/raddbg/raddbg.mdesk @@ -286,6 +286,16 @@ RD_VocabTable: x: { @default(2) @display_name('Project Tab Width') 'tab_width': @range[1, 32] u64, + + //- rjf: theme + @display_name('Project Theme Preset') @description("The selected built-in project theme preset.") + 'theme_preset': string, + @no_expand @display_name('Project Theme File') @description("The path from which project's theme data is loaded, overriding the preset.") + 'theme_file': path, + @display_name('Project Theme Colors') @description("Additional theme colors which are applied on top of the project's theme file or preset.") + 'theme_colors': query, + + //- rjf: exception settings @default(1) @display_name("Break On Win32 Control-C Exceptions") @description("Code: 0x40010005") win32_ctrl_c: bool; @default(1) @display_name("Break On Win32 Control-Break Exceptions") @description("Code: 0x40010008") @@ -756,8 +766,8 @@ RD_CmdTable: // | | | | {SelectUnwind 0 1 0 0 "query:call_stack" Null null Nil Null 0 0 0 0 0 0 0 Null "select_unwind" "Select Unwind" "Selects an unwind frame number for the selected thread." "" "" } {UpOneFrame 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 UpArrow "up_one_frame" "Up One Frame" "Selects the call stack frame above the currently selected." "" "" } {DownOneFrame 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 DownArrow "down_one_frame" "Down One Frame" "Selects the call stack frame below the currently selected." "callstack,unwind" "" } - {SelectEntity 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 RadioHollow "select_entity" "Select Entity" "Selects a control entity." "" "" } - {DeselectEntity 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 RadioFilled "deselect_entity" "Deselect Entity" "Deselects a control entity." "" "" } + {SelectEntity 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 RadioHollow "select_entity" "Select" "Selects a control entity." "" "" } + {DeselectEntity 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 RadioFilled "deselect_entity" "Deselect" "Deselects a control entity." "" "" } //- rjf: font sizes {IncWindowFontSize 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "inc_window_font_size" "Increase Window Font Size" "Increases the window's font size by one point." "" "" } @@ -924,15 +934,15 @@ RD_CmdTable: // | | | | {ToggleWatchExpressionAtMouse 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Binoculars "toggle_watch_expr_at_mouse" "Toggle Watch Expression At Mouse" "Adds or removes the expression that the mouse is currently over to an opened watch view." "" "" } //- rjf: general config operations - {EnableCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 CheckHollow "enable_cfg" "Enable Config Tree" "Enables a config tree." "" "" } - {DisableCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 CheckFilled "disable_cfg" "Disable Config Tree" "Disables a config tree." "" "" } - {SelectCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 RadioHollow "select_cfg" "Select Config Tree" "Selects a config tree, disabling all others of the same kind." "" "" } - {DeselectCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 RadioFilled "deselect_cfg" "Deselect Config Tree" "Deselects a config tree." "" "" } - {RemoveCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Trash "remove_cfg" "Remove Config Tree" "Removes a config tree." "" "" } - {NameCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "name_cfg" "Name Config Tree" "Equips a config tree with a label." "" "" } - {ConditionCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "condition_cfg" "Condition Config Tree" "Equips a config tree with a condition string." "" "" } - {DuplicateCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Duplicate "duplicate_cfg" "Duplicate Config Tree" "Duplicates a config tree." "" "" } - {RelocateCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "relocate_cfg" "Relocate Config Tree" "Relocates a config tree." "" "" } + {EnableCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 CheckHollow "enable_cfg" "Enable" "Enables a config tree." "" "" } + {DisableCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 CheckFilled "disable_cfg" "Disable" "Disables a config tree." "" "" } + {SelectCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 RadioHollow "select_cfg" "Select" "Selects a config tree, disabling all others of the same kind." "" "" } + {DeselectCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 RadioFilled "deselect_cfg" "Deselect" "Deselects a config tree." "" "" } + {RemoveCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Trash "remove_cfg" "Remove" "Removes a config tree." "" "" } + {NameCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "name_cfg" "Name" "Equips a config tree with a label." "" "" } + {ConditionCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "condition_cfg" "Condition" "Equips a config tree with a condition string." "" "" } + {DuplicateCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Duplicate "duplicate_cfg" "Duplicate" "Duplicates a config tree." "" "" } + {RelocateCfg 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "relocate_cfg" "Relocate" "Relocates a config tree." "" "" } //- rjf: breakpoints {AddBreakpoint 1 1 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 CircleFilled "add_breakpoint" "Add Breakpoint" "Places a breakpoint at a given location (file path and line number, address, or symbol name)." "" "" } diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index da0c7c05..6b8f6155 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -2780,7 +2780,7 @@ rd_view_ui(Rng2F32 rect) UI_Padding(ui_pct(1, 0)) { ui_labelf("use"); - UI_TextAlignment(UI_TextAlign_Center) rd_cmd_binding_buttons(rd_cmd_kind_info_table[RD_CmdKind_OpenPalette].string, str8_zero()); + UI_TextAlignment(UI_TextAlign_Center) rd_cmd_binding_buttons(rd_cmd_kind_info_table[RD_CmdKind_OpenPalette].string, str8_zero(), 1); ui_labelf("to search for commands and options"); } } @@ -4979,6 +4979,12 @@ rd_view_ui(Rng2F32 rect) RD_RegsScope(.ctrl_entity = cell_info.entity->handle, .no_rich_tooltip = 1) rd_set_hover_regs(RD_RegSlot_CtrlEntity); } + // rjf: hover -> rich hover commands (mini only) + if(ui_hovering(sig) && cell_info.cmd_name.size != 0 && cell->px != 0) + { + RD_RegsScope(.cmd_name = cell_info.cmd_name, .ui_key = sig.box->key) rd_set_hover_regs(RD_RegSlot_CmdName); + } + // rjf: dragging -> drag/drop if(ui_dragging(sig) && !contains_2f32(sig.box->rect, ui_mouse()) && (!cell_selected || !ewv->text_editing)) @@ -6135,10 +6141,28 @@ rd_window_frame(void) RD_RegSlot slot = ((rd_state->drag_drop_regs_slot != RD_RegSlot_Null && rd_drag_is_active()) ? rd_state->drag_drop_regs_slot : rd_state->hover_regs_slot); RD_Regs *regs = (((rd_state->drag_drop_regs_slot != RD_RegSlot_Null && rd_drag_is_active()) ? rd_state->drag_drop_regs : rd_state->hover_regs)); CTRL_Entity *ctrl_entity = &ctrl_entity_nil; + ui_state->tooltip_anchor_key = regs->ui_key; + ui_state->tooltip_can_overflow_window = rd_drag_is_active(); switch(slot) { default:{}break; + //////////////////////// + //- rjf: command tooltips + // + case RD_RegSlot_CmdName: + UI_Tooltip + { + String8 cmd_name = regs->cmd_name; + DR_FStrList fstrs = rd_title_fstrs_from_code_name(scratch.arena, cmd_name); + UI_PrefWidth(ui_children_sum(1)) UI_Row UI_PrefWidth(ui_text_dim(5, 1)) + { + UI_Box *box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); + ui_box_equip_display_fstrs(box, &fstrs); + rd_cmd_binding_buttons(cmd_name, str8_zero(), 0); + } + }break; + //////////////////////// //- rjf: file path tooltips // @@ -6294,13 +6318,16 @@ rd_window_frame(void) UI_Row { rd_code_label(1.f, 0, ui_color_from_name(str8_lit("text")), rd_state->drag_drop_regs->expr); - ui_spacer(ui_em(2.f, 1.f)); E_Eval eval = e_eval_from_string(rd_state->drag_drop_regs->expr); if(eval.irtree.mode != E_Mode_Null) { EV_StringParams string_params = {.flags = EV_StringFlag_ReadOnlyDisplayRules, .radix = 10}; String8 value_string = rd_value_string_from_eval(scratch.arena, str8_zero(), &string_params, ui_top_font(), ui_top_font_size(), ui_top_font_size()*20.f, eval); - rd_code_label(1.f, 0, ui_color_from_name(str8_lit("text")), value_string); + if(value_string.size != 0) + { + ui_spacer(ui_em(2.f, 1.f)); + rd_code_label(1.f, 0, ui_color_from_name(str8_lit("text")), value_string); + } } } }break; @@ -6584,6 +6611,7 @@ rd_window_frame(void) UI_Focus(UI_FocusKind_On) UI_BlurSize(10*rd_state->popup_t) UI_Transparency(1-rd_state->popup_t) + UI_TagF("floating") { bg_box = ui_build_box_from_stringf(UI_BoxFlag_FixedSize| UI_BoxFlag_Floating| @@ -6591,7 +6619,8 @@ rd_window_frame(void) UI_BoxFlag_Scroll| UI_BoxFlag_DefaultFocusNav| UI_BoxFlag_DisableFocusOverlay| - UI_BoxFlag_DrawBackgroundBlur, "###popup_%p", ws); + UI_BoxFlag_DrawBackgroundBlur| + UI_BoxFlag_DrawBackground, "###popup_%p", ws); } if(rd_state->popup_active) UI_Parent(bg_box) UI_Transparency(1-rd_state->popup_t) { @@ -7420,7 +7449,7 @@ rd_window_frame(void) ui_labelf("Search for commands and options by pressing "); UI_Flags(UI_BoxFlag_DrawBorder) UI_TextAlignment(UI_TextAlign_Center) - rd_cmd_binding_buttons(rd_cmd_kind_info_table[RD_CmdKind_OpenPalette].string, str8_zero()); + rd_cmd_binding_buttons(rd_cmd_kind_info_table[RD_CmdKind_OpenPalette].string, str8_zero(), 1); } ui_spacer(ui_em(1.f, 1.f)); UI_TagF("pop") @@ -7577,198 +7606,41 @@ rd_window_frame(void) Temp scratch = scratch_begin(0, 0); RD_CfgList targets = rd_cfg_top_level_list_from_string(scratch.arena, str8_lit("target")); CTRL_EntityArray processes = ctrl_entity_array_from_kind(d_state->ctrl_entity_store, CTRL_EntityKind_Process); - B32 have_targets = (targets.count != 0); B32 can_send_signal = !d_ctrl_targets_running(); - B32 can_play = (have_targets && (can_send_signal || d_ctrl_last_run_frame_idx()+4 > d_frame_index())); - B32 can_pause = (!can_send_signal); - B32 can_stop = (processes.count != 0); - B32 can_step = (processes.count != 0 && can_send_signal); - - //- rjf: play button - if(can_play || !have_targets || processes.count == 0) - UI_TextAlignment(UI_TextAlign_Center) - UI_Flags((can_play ? 0 : UI_BoxFlag_Disabled)) - UI_TagF(can_play ? "good" : "weak") + typedef struct CenterButtonTask CenterButtonTask; + struct CenterButtonTask { - UI_Signal sig = ui_button(rd_icon_kind_text_table[RD_IconKind_Play]); - os_window_push_custom_title_bar_client_area(ws->os, sig.box->rect); - if(ui_hovering(sig) && !can_play) - { - UI_Tooltip RD_Font(RD_FontSlot_Main) - ui_labelf("Disabled: %s", have_targets ? "Targets are currently running" : "No active targets exist"); - } - if(ui_hovering(sig) && can_play) - { - UI_Tooltip RD_Font(RD_FontSlot_Main) - { - if(can_stop) - { - ui_labelf("Resume all processes"); - } - else - { - ui_labelf("Launch all active targets:"); - for(RD_CfgNode *n = targets.first; n != 0; n = n->next) - { - RD_Cfg *target = n->v; - B32 target_is_enabled = !rd_disabled_from_cfg(target); - if(target_is_enabled) - { - DR_FStrList title_fstrs = rd_title_fstrs_from_cfg(ui_build_arena(), target); - UI_Box *box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); - ui_box_equip_display_fstrs(box, &title_fstrs); - } - } - } - } - } - if(ui_clicked(sig)) - { - rd_cmd(RD_CmdKind_Run); - } - } - - //- rjf: restart button - else UI_TextAlignment(UI_TextAlign_Center) - UI_TagF("good") + String8 cmd_name; + String8 tag; + B32 is_enabled; + }; + CenterButtonTask center_button_tasks[] = { - UI_Signal sig = ui_button(rd_icon_kind_text_table[RD_IconKind_Redo]); + {rd_cmd_kind_info_table[RD_CmdKind_Run].string, str8_lit("good"), (can_send_signal || d_ctrl_last_run_frame_idx()+4 > d_frame_index())}, + {rd_cmd_kind_info_table[RD_CmdKind_Restart].string, str8_lit("good"), processes.count != 0}, + {rd_cmd_kind_info_table[RD_CmdKind_Halt].string, str8_lit("weak"), !can_send_signal}, + {rd_cmd_kind_info_table[RD_CmdKind_KillAll].string, str8_lit("bad"), processes.count != 0}, + {rd_cmd_kind_info_table[RD_CmdKind_StepOver].string, str8_lit("weak"), can_send_signal}, + {rd_cmd_kind_info_table[RD_CmdKind_StepInto].string, str8_lit("weak"), can_send_signal}, + {rd_cmd_kind_info_table[RD_CmdKind_StepOut].string, str8_lit("weak"), processes.count != 0 && can_send_signal}, + }; + UI_TextAlignment(UI_TextAlign_Center) + for EachElement(idx, center_button_tasks) + UI_Flags(center_button_tasks[idx].is_enabled ? 0 : UI_BoxFlag_Disabled) + UI_Tag(center_button_tasks[idx].is_enabled ? center_button_tasks[idx].tag : str8_lit("")) + { + String8 cmd_name = center_button_tasks[idx].cmd_name; + UI_Signal sig = ui_button(rd_icon_kind_text_table[rd_icon_kind_from_code_name(cmd_name)]); os_window_push_custom_title_bar_client_area(ws->os, sig.box->rect); if(ui_hovering(sig)) { - UI_Tooltip RD_Font(RD_FontSlot_Main) - { - ui_labelf("Restart"); - } + RD_RegsScope(.cmd_name = cmd_name, .ui_key = sig.box->key) rd_set_hover_regs(RD_RegSlot_CmdName); } if(ui_clicked(sig)) { - rd_cmd(RD_CmdKind_Restart); + rd_push_cmd(cmd_name, rd_regs()); } } - - //- rjf: pause button - UI_TextAlignment(UI_TextAlign_Center) UI_Flags(can_pause ? 0 : UI_BoxFlag_Disabled) - UI_TagF("weak") - { - UI_Signal sig = ui_button(rd_icon_kind_text_table[RD_IconKind_Pause]); - os_window_push_custom_title_bar_client_area(ws->os, sig.box->rect); - if(ui_hovering(sig) && !can_pause) - { - UI_Tooltip RD_Font(RD_FontSlot_Main) - ui_labelf("Disabled: Already halted"); - } - if(ui_hovering(sig) && can_pause) - { - UI_Tooltip RD_Font(RD_FontSlot_Main) - ui_labelf("Halt all attached processes"); - } - if(ui_clicked(sig)) - { - rd_cmd(RD_CmdKind_Halt); - } - } - - //- rjf: stop button - UI_TextAlignment(UI_TextAlign_Center) UI_Flags(can_stop ? 0 : UI_BoxFlag_Disabled) - UI_TagF(can_stop ? "bad" : "weak") - { - UI_Signal sig = {0}; - { - sig = ui_button(rd_icon_kind_text_table[RD_IconKind_Stop]); - os_window_push_custom_title_bar_client_area(ws->os, sig.box->rect); - } - if(ui_hovering(sig) && !can_stop) - { - UI_Tooltip RD_Font(RD_FontSlot_Main) ui_labelf("Disabled: No processes are running"); - } - if(ui_hovering(sig) && can_stop) - { - UI_Tooltip RD_Font(RD_FontSlot_Main) - ui_labelf("Kill all attached processes"); - } - if(ui_clicked(sig)) - { - rd_cmd(RD_CmdKind_KillAll); - } - } - - //- rjf: step over button - UI_TextAlignment(UI_TextAlign_Center) UI_Flags((can_play ? 0 : UI_BoxFlag_Disabled)) - UI_TagF("weak") - { - UI_Signal sig = ui_button(rd_icon_kind_text_table[RD_IconKind_StepOver]); - os_window_push_custom_title_bar_client_area(ws->os, sig.box->rect); - if(ui_hovering(sig)) - { - if(can_play) - { - UI_Tooltip RD_Font(RD_FontSlot_Main) ui_labelf("Step Over"); - } - else - { - UI_Tooltip RD_Font(RD_FontSlot_Main) - ui_labelf("Disabled: %s", have_targets ? "Targets are currently running" : "No active targets exist"); - } - } - if(ui_clicked(sig)) - { - rd_cmd(RD_CmdKind_StepOver); - } - } - - //- rjf: step into button - UI_TextAlignment(UI_TextAlign_Center) UI_Flags((can_play ? 0 : UI_BoxFlag_Disabled)) - UI_TagF("weak") - { - UI_Signal sig = ui_button(rd_icon_kind_text_table[RD_IconKind_StepInto]); - os_window_push_custom_title_bar_client_area(ws->os, sig.box->rect); - if(ui_hovering(sig)) - { - if(can_play) - { - UI_Tooltip RD_Font(RD_FontSlot_Main) - ui_labelf("Step Into"); - } - else - { - UI_Tooltip RD_Font(RD_FontSlot_Main) - ui_labelf("Disabled: %s", have_targets ? "Targets are currently running" : "No active targets exist"); - } - } - if(ui_clicked(sig)) - { - rd_cmd(RD_CmdKind_StepInto); - } - } - - //- rjf: step out button - UI_TextAlignment(UI_TextAlign_Center) UI_Flags(can_step ? 0 : UI_BoxFlag_Disabled) - UI_TagF("weak") - { - UI_Signal sig = ui_button(rd_icon_kind_text_table[RD_IconKind_StepOut]); - os_window_push_custom_title_bar_client_area(ws->os, sig.box->rect); - if(ui_hovering(sig) && !can_step && can_pause) - { - UI_Tooltip RD_Font(RD_FontSlot_Main) - ui_labelf("Disabled: Running"); - } - if(ui_hovering(sig) && !can_step && !can_stop) - { - UI_Tooltip RD_Font(RD_FontSlot_Main) - ui_labelf("Disabled: No processes are running"); - } - if(ui_hovering(sig) && can_step) - { - UI_Tooltip RD_Font(RD_FontSlot_Main) - ui_labelf("Step Out"); - } - if(ui_clicked(sig)) - { - rd_cmd(RD_CmdKind_StepOut); - } - } - scratch_end(scratch); } @@ -15917,7 +15789,7 @@ rd_frame(void) //- rjf: animate confirmation // { - F32 rate = rd_setting_b32_from_name(str8_lit("menu_animations")) ? 1 - pow_f32(2, (-10.f * rd_state->frame_dt)) : 1.f; + F32 rate = rd_setting_b32_from_name(str8_lit("menu_animations")) ? 1 - pow_f32(2, (-30.f * rd_state->frame_dt)) : 1.f; B32 popup_open = rd_state->popup_active; rd_state->popup_t += rate * ((F32)!!popup_open-rd_state->popup_t); if(abs_f32(rd_state->popup_t - (F32)!!popup_open) > 0.005f) diff --git a/src/raddbg/raddbg_widgets.c b/src/raddbg/raddbg_widgets.c index c0817f38..5ea5cddb 100644 --- a/src/raddbg/raddbg_widgets.c +++ b/src/raddbg/raddbg_widgets.c @@ -714,7 +714,7 @@ rd_loading_overlay(Rng2F32 rect, F32 loading_t, U64 progress_v, U64 progress_v_t //~ rjf: UI Widgets: Fancy Buttons internal void -rd_cmd_binding_buttons(String8 name, String8 filter) +rd_cmd_binding_buttons(String8 name, String8 filter, B32 add_new) { Temp scratch = scratch_begin(0, 0); RD_KeyMapNodePtrList key_map_nodes = rd_key_map_node_ptr_list_from_name(scratch.arena, name); @@ -722,6 +722,7 @@ rd_cmd_binding_buttons(String8 name, String8 filter) //- rjf: build buttons for each binding UI_CornerRadius(ui_top_font_size()*0.5f) for(RD_KeyMapNodePtr *n = key_map_nodes.first; n != 0; n = n->next) { + ui_spacer(ui_em(1.f, 1.f)); RD_Binding binding = n->v->binding; B32 rebinding_active_for_this_binding = (rd_state->bind_change_active && str8_match(rd_state->bind_change_cmd_name, name, 0) && @@ -826,40 +827,41 @@ rd_cmd_binding_buttons(String8 name, String8 filter) rd_state->bind_change_active = 0; } } - - //- rjf: space - ui_spacer(ui_em(1.f, 1.f)); } //- rjf: build "add new binding" button - B32 adding_new_binding = (rd_state->bind_change_active && - str8_match(rd_state->bind_change_cmd_name, name, 0) && - rd_state->bind_change_binding_id == 0); - RD_Font(RD_FontSlot_Icons) UI_TagF(adding_new_binding ? "pop" : "") UI_CornerRadius(ui_top_font_size()*0.5f) + if(add_new) { - ui_set_next_text_alignment(UI_TextAlign_Center); - ui_set_next_group_key(ui_key_zero()); - ui_set_next_pref_width(ui_text_dim(ui_top_font_size()*1.5f, 1)); - UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_DrawText| - UI_BoxFlag_Clickable| - UI_BoxFlag_DrawActiveEffects| - UI_BoxFlag_DrawHotEffects| - UI_BoxFlag_DrawBorder| - UI_BoxFlag_DrawBackground, - "%S###add_binding", rd_icon_kind_text_table[RD_IconKind_Add]); - UI_Signal sig = ui_signal_from_box(box); - if(ui_clicked(sig)) + B32 adding_new_binding = (rd_state->bind_change_active && + str8_match(rd_state->bind_change_cmd_name, name, 0) && + rd_state->bind_change_binding_id == 0); + ui_spacer(ui_em(1.f, 1.f)); + RD_Font(RD_FontSlot_Icons) UI_TagF(adding_new_binding ? "pop" : "") UI_CornerRadius(ui_top_font_size()*0.5f) { - if(!rd_state->bind_change_active && ui_clicked(sig)) + ui_set_next_text_alignment(UI_TextAlign_Center); + ui_set_next_group_key(ui_key_zero()); + ui_set_next_pref_width(ui_text_dim(ui_top_font_size()*1.5f, 1)); + UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_DrawText| + UI_BoxFlag_Clickable| + UI_BoxFlag_DrawActiveEffects| + UI_BoxFlag_DrawHotEffects| + UI_BoxFlag_DrawBorder| + UI_BoxFlag_DrawBackground, + "%S###add_binding", rd_icon_kind_text_table[RD_IconKind_Add]); + UI_Signal sig = ui_signal_from_box(box); + if(ui_clicked(sig)) { - arena_clear(rd_state->bind_change_arena); - rd_state->bind_change_active = 1; - rd_state->bind_change_cmd_name = push_str8_copy(rd_state->bind_change_arena, name); - rd_state->bind_change_binding_id = 0; - } - else if(rd_state->bind_change_active && ui_clicked(sig)) - { - rd_state->bind_change_active = 0; + if(!rd_state->bind_change_active && ui_clicked(sig)) + { + arena_clear(rd_state->bind_change_arena); + rd_state->bind_change_active = 1; + rd_state->bind_change_cmd_name = push_str8_copy(rd_state->bind_change_arena, name); + rd_state->bind_change_binding_id = 0; + } + else if(rd_state->bind_change_active && ui_clicked(sig)) + { + rd_state->bind_change_active = 0; + } } } } @@ -913,7 +915,7 @@ rd_cmd_spec_button(String8 name) UI_TagF("weak") UI_FastpathCodepoint(0) { - rd_cmd_binding_buttons(name, str8_zero()); + rd_cmd_binding_buttons(name, str8_zero(), 1); } } } @@ -3473,7 +3475,7 @@ rd_cell(RD_CellParams *params, String8 string) { UI_PrefWidth(ui_children_sum(1)) UI_Row UI_Padding(ui_em(1.f, 1.f)) { - rd_cmd_binding_buttons(params->bindings_name, params->search_needle); + rd_cmd_binding_buttons(params->bindings_name, params->search_needle, 1); } } } diff --git a/src/raddbg/raddbg_widgets.h b/src/raddbg/raddbg_widgets.h index f801fc1a..57dcd7f2 100644 --- a/src/raddbg/raddbg_widgets.h +++ b/src/raddbg/raddbg_widgets.h @@ -140,7 +140,7 @@ internal void rd_loading_overlay(Rng2F32 rect, F32 loading_t, U64 progress_v, U6 //////////////////////////////// //~ rjf: UI Widgets: Fancy Buttons -internal void rd_cmd_binding_buttons(String8 name, String8 filter); +internal void rd_cmd_binding_buttons(String8 name, String8 filter, B32 add_new); internal UI_Signal rd_menu_bar_button(String8 string); internal UI_Signal rd_cmd_spec_button(String8 name); internal void rd_cmd_list_menu_buttons(U64 count, String8 *cmd_names, U32 *fastpath_codepoints); diff --git a/src/ui/ui_core.c b/src/ui/ui_core.c index 245373d3..2ed424ff 100644 --- a/src/ui/ui_core.c +++ b/src/ui/ui_core.c @@ -805,6 +805,7 @@ ui_begin_build(OS_Handle window, UI_EventList *events, UI_IconInfo *icon_info, U ui_state->ctx_menu_changed = 0; ui_state->default_animation_rate = 1 - pow_f32(2, (-60.f * ui_state->animation_dt)); ui_state->tooltip_can_overflow_window = 0; + ui_state->tooltip_anchor_key = ui_key_zero(); ui_state->tags_key_stack_top = ui_state->tags_key_stack_free = 0; ui_state->tags_cache_slots_count = 512; ui_state->tags_cache_slots = push_array(ui_build_arena(), UI_TagsCacheSlot, ui_state->tags_cache_slots_count); @@ -1248,6 +1249,22 @@ ui_end_build(void) } } + //- rjf: anchor tooltips + if(!ui_key_match(ui_state->tooltip_anchor_key, ui_key_zero())) + { + UI_Box *anchor_box = ui_box_from_key(ui_state->tooltip_anchor_key); + if(!ui_box_is_nil(anchor_box)) + { + ui_state->tooltip_root->rect.x0 = anchor_box->rect.x0; + ui_state->tooltip_root->rect.y0 = anchor_box->rect.y1 + anchor_box->font_size*0.5f; + } + else + { + ui_state->tooltip_root->rect.x0 = 10000; + ui_state->tooltip_root->rect.y0 = 10000; + } + } + //- rjf: ensure special floating roots are within screen bounds UI_Box *floating_roots[] = {ui_state->tooltip_root, ui_state->ctx_menu_root}; B32 force_contain[] = diff --git a/src/ui/ui_core.h b/src/ui/ui_core.h index 96bcb795..d0461bf9 100644 --- a/src/ui/ui_core.h +++ b/src/ui/ui_core.h @@ -676,6 +676,7 @@ struct UI_State //- rjf: build state machine state B32 is_in_open_ctx_menu; B32 tooltip_can_overflow_window; + UI_Key tooltip_anchor_key; String8Array current_gen_tags; U64 current_gen_tags_gen; UI_TagsKeyStackNode *tags_key_stack_top;