From 5af40e0a33d50916db1f8d137449002b5e4e1c64 Mon Sep 17 00:00:00 2001 From: LagoLunatic Date: Thu, 28 Nov 2024 17:07:14 -0500 Subject: [PATCH] Auto-scroll the keyboard-selected symbols into view if offscreen --- objdiff-gui/src/views/function_diff.rs | 16 +++++++------ objdiff-gui/src/views/symbol_diff.rs | 32 ++++++++++++++++++-------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/objdiff-gui/src/views/function_diff.rs b/objdiff-gui/src/views/function_diff.rs index 42db981..3344463 100644 --- a/objdiff-gui/src/views/function_diff.rs +++ b/objdiff-gui/src/views/function_diff.rs @@ -409,7 +409,7 @@ fn asm_table_ui( right_ctx: Option>, appearance: &Appearance, ins_view_state: &FunctionViewState, - symbol_state: &SymbolViewState, + symbol_state: &mut SymbolViewState, ) -> Option { let mut ret = None; let left_len = left_ctx.and_then(|ctx| { @@ -516,8 +516,9 @@ fn asm_table_ui( SymbolRefByName::new(right_symbol, right_section), )); } - DiffViewAction::SetSymbolHighlight(_, _) => { - // Ignore + DiffViewAction::SetSymbolHighlight(left, right, scroll) => { + symbol_state.highlighted_symbol = (left, right); + symbol_state.scroll_highlighted_symbol_into_view = scroll; } _ => { ret = Some(action); @@ -576,8 +577,9 @@ fn asm_table_ui( right_symbol_ref, )); } - DiffViewAction::SetSymbolHighlight(_, _) => { - // Ignore + DiffViewAction::SetSymbolHighlight(left, right, scroll) => { + symbol_state.highlighted_symbol = (left, right); + symbol_state.scroll_highlighted_symbol_into_view = scroll; } _ => { ret = Some(action); @@ -620,7 +622,7 @@ impl<'a> FunctionDiffContext<'a> { #[must_use] pub fn function_diff_ui( ui: &mut egui::Ui, - state: &DiffViewState, + state: &mut DiffViewState, appearance: &Appearance, ) -> Option { let mut ret = None; @@ -823,7 +825,7 @@ pub fn function_diff_ui( right_ctx, appearance, &state.function_state, - &state.symbol_state, + &mut state.symbol_state, ) }) .inner diff --git a/objdiff-gui/src/views/symbol_diff.rs b/objdiff-gui/src/views/symbol_diff.rs index cc37edf..0041e92 100644 --- a/objdiff-gui/src/views/symbol_diff.rs +++ b/objdiff-gui/src/views/symbol_diff.rs @@ -1,8 +1,8 @@ use std::{collections::BTreeMap, mem::take, ops::Bound}; use egui::{ - text::LayoutJob, CollapsingHeader, Color32, Id, OpenUrl, ScrollArea, SelectableLabel, TextEdit, - Ui, Widget, + style::ScrollAnimation, text::LayoutJob, CollapsingHeader, Color32, Id, OpenUrl, ScrollArea, + SelectableLabel, TextEdit, Ui, Widget, }; use objdiff_core::{ arch::ObjArch, @@ -57,8 +57,8 @@ pub enum DiffViewAction { Build, /// Navigate to a new diff view Navigate(DiffViewNavigation), - /// Set the highlighted symbols in the symbols view - SetSymbolHighlight(Option, Option), + /// Set the highlighted symbols in the symbols view, optionally scrolling them into view. + SetSymbolHighlight(Option, Option, bool), /// Set the symbols view search filter SetSearch(String), /// Submit the current function to decomp.me @@ -136,6 +136,7 @@ pub struct DiffViewState { #[derive(Default)] pub struct SymbolViewState { pub highlighted_symbol: (Option, Option), + pub scroll_highlighted_symbol_into_view: bool, pub left_symbol: Option, pub right_symbol: Option, pub reverse_fn_order: bool, @@ -247,8 +248,9 @@ impl DiffViewState { self.post_build_nav = Some(nav); } } - DiffViewAction::SetSymbolHighlight(left, right) => { + DiffViewAction::SetSymbolHighlight(left, right, scroll) => { self.symbol_state.highlighted_symbol = (left, right); + self.symbol_state.scroll_highlighted_symbol_into_view = scroll; } DiffViewAction::SetSearch(search) => { self.search_regex = if search.is_empty() { @@ -471,7 +473,7 @@ fn symbol_ui( symbol: &ObjSymbol, symbol_diff: &ObjSymbolDiff, section: Option<&ObjSection>, - state: &SymbolViewState, + state: &mut SymbolViewState, appearance: &Appearance, column: usize, ) -> Option { @@ -534,6 +536,14 @@ fn symbol_ui( ret = Some(DiffViewAction::Navigate(result)); } }); + if selected && state.scroll_highlighted_symbol_into_view { + // Scroll the view to encompass the selected symbol in case the user selected an offscreen + // symbol by using a keyboard shortcut. + ui.scroll_to_rect_animation(response.rect, None, ScrollAnimation::none()); + // Then reset this flag so that we don't repeatedly scroll the view back when the user is + // trying to manually scroll away. + state.scroll_highlighted_symbol_into_view = false; + } if response.clicked() || (selected && hotkeys::enter_pressed(ui.ctx())) { if let Some(section) = section { match section.kind { @@ -565,11 +575,13 @@ fn symbol_ui( DiffViewAction::SetSymbolHighlight( Some(symbol_diff.symbol_ref), symbol_diff.target_symbol, + false, ) } else { DiffViewAction::SetSymbolHighlight( symbol_diff.target_symbol, Some(symbol_diff.symbol_ref), + false, ) }); } @@ -603,7 +615,7 @@ pub fn symbol_list_ui( ui: &mut Ui, ctx: SymbolDiffContext<'_>, other_ctx: Option>, - state: &SymbolViewState, + state: &mut SymbolViewState, filter: SymbolFilter<'_>, appearance: &Appearance, column: usize, @@ -685,11 +697,13 @@ pub fn symbol_list_ui( DiffViewAction::SetSymbolHighlight( Some(*new_sym_ref), new_symbol_diff.target_symbol, + true, ) } else { DiffViewAction::SetSymbolHighlight( new_symbol_diff.target_symbol, Some(*new_sym_ref), + true, ) }); } @@ -941,7 +955,7 @@ pub fn symbol_diff_ui( .second_obj .as_ref() .map(|(obj, diff)| SymbolDiffContext { obj, diff }), - &state.symbol_state, + &mut state.symbol_state, filter, appearance, column, @@ -965,7 +979,7 @@ pub fn symbol_diff_ui( .first_obj .as_ref() .map(|(obj, diff)| SymbolDiffContext { obj, diff }), - &state.symbol_state, + &mut state.symbol_state, filter, appearance, column,