diff --git a/objdiff-gui/src/hotkeys.rs b/objdiff-gui/src/hotkeys.rs index ba2e660..723e4a3 100644 --- a/objdiff-gui/src/hotkeys.rs +++ b/objdiff-gui/src/hotkeys.rs @@ -1,4 +1,4 @@ -use egui::{style::ScrollAnimation, vec2, Context, Key, PointerButton}; +use egui::{style::ScrollAnimation, vec2, Context, Key, Modifiers, PointerButton}; pub fn enter_pressed(ctx: &Context) -> bool { ctx.input_mut(|i| i.key_pressed(Key::Enter) || i.pointer.button_pressed(PointerButton::Extra2)) @@ -26,11 +26,11 @@ pub fn home_pressed(ctx: &Context) -> bool { ctx.input_mut(|i| i.key_pressed(Key pub fn end_pressed(ctx: &Context) -> bool { ctx.input_mut(|i| i.key_pressed(Key::End)) } -pub fn check_scroll_hotkeys(ui: &mut egui::Ui) { +pub fn check_scroll_hotkeys(ui: &mut egui::Ui, include_small_increments: bool) { let ui_height = ui.available_rect_before_wrap().height(); - if up_pressed(ui.ctx()) { + if up_pressed(ui.ctx()) && include_small_increments { ui.scroll_with_delta_animation(vec2(0.0, ui_height / 10.0), ScrollAnimation::none()); - } else if down_pressed(ui.ctx()) { + } else if down_pressed(ui.ctx()) && include_small_increments { ui.scroll_with_delta_animation(vec2(0.0, -ui_height / 10.0), ScrollAnimation::none()); } else if page_up_pressed(ui.ctx()) { ui.scroll_with_delta_animation(vec2(0.0, ui_height), ScrollAnimation::none()); @@ -42,3 +42,15 @@ pub fn check_scroll_hotkeys(ui: &mut egui::Ui) { ui.scroll_with_delta_animation(vec2(0.0, -f32::INFINITY), ScrollAnimation::none()); } } + +pub fn consume_up_key(ctx: &Context) -> bool { + ctx.input_mut(|i| { + i.consume_key(Modifiers::NONE, Key::ArrowUp) || i.consume_key(Modifiers::NONE, Key::W) + }) +} + +pub fn consume_down_key(ctx: &Context) -> bool { + ctx.input_mut(|i| { + i.consume_key(Modifiers::NONE, Key::ArrowDown) || i.consume_key(Modifiers::NONE, Key::S) + }) +} diff --git a/objdiff-gui/src/views/data_diff.rs b/objdiff-gui/src/views/data_diff.rs index c08e415..37f2a6c 100644 --- a/objdiff-gui/src/views/data_diff.rs +++ b/objdiff-gui/src/views/data_diff.rs @@ -179,7 +179,7 @@ fn data_table_ui( let left_diffs = left_section.map(|(_, section)| split_diffs(§ion.data_diff)); let right_diffs = right_section.map(|(_, section)| split_diffs(§ion.data_diff)); - hotkeys::check_scroll_hotkeys(ui); + hotkeys::check_scroll_hotkeys(ui, true); render_table(ui, available_width, 2, config.code_font.size, total_rows, |row, column| { let i = row.index(); diff --git a/objdiff-gui/src/views/extab_diff.rs b/objdiff-gui/src/views/extab_diff.rs index db391e0..5d99117 100644 --- a/objdiff-gui/src/views/extab_diff.rs +++ b/objdiff-gui/src/views/extab_diff.rs @@ -235,7 +235,7 @@ pub fn extab_diff_ui( } }); - hotkeys::check_scroll_hotkeys(ui); + hotkeys::check_scroll_hotkeys(ui, true); // Table render_strips(ui, available_width, 2, |ui, column| { diff --git a/objdiff-gui/src/views/function_diff.rs b/objdiff-gui/src/views/function_diff.rs index 1df1152..67ea175 100644 --- a/objdiff-gui/src/views/function_diff.rs +++ b/objdiff-gui/src/views/function_diff.rs @@ -435,7 +435,7 @@ fn asm_table_ui( }; if left_len.is_some() && right_len.is_some() { // Joint view - hotkeys::check_scroll_hotkeys(ui); + hotkeys::check_scroll_hotkeys(ui, true); render_table( ui, available_width, diff --git a/objdiff-gui/src/views/symbol_diff.rs b/objdiff-gui/src/views/symbol_diff.rs index 7fa185f..eed3bbd 100644 --- a/objdiff-gui/src/views/symbol_diff.rs +++ b/objdiff-gui/src/views/symbol_diff.rs @@ -1,4 +1,4 @@ -use std::{collections::BTreeMap, mem::take}; +use std::{collections::BTreeMap, mem::take, ops::Bound}; use egui::{ text::LayoutJob, CollapsingHeader, Color32, Id, OpenUrl, ScrollArea, SelectableLabel, TextEdit, @@ -649,7 +649,55 @@ pub fn symbol_list_ui( } } - hotkeys::check_scroll_hotkeys(ui); + hotkeys::check_scroll_hotkeys(ui, false); + + let mut new_key_value_to_highlight = None; + if let Some(sym_ref) = + if column == 0 { state.highlighted_symbol.0 } else { state.highlighted_symbol.1 } + { + let up = if hotkeys::consume_up_key(ui.ctx()) { + Some(true) + } else if hotkeys::consume_down_key(ui.ctx()) { + Some(false) + } else { + None + }; + if let Some(mut up) = up { + if state.reverse_fn_order { + up = !up; + } + new_key_value_to_highlight = if up { + mapping.range(..sym_ref).next_back() + } else { + mapping.range((Bound::Excluded(sym_ref), Bound::Unbounded)).next() + }; + }; + } else { + // No symbol is highlighted in this column. Select the topmost symbol instead. + // Note that we intentionally do not consume the up/down key presses in this case, but + // we do when a symbol is highlighted. This is so that if only one column has a symbol + // highlighted, that one takes precedence over the one with nothing highlighted. + if hotkeys::up_pressed(ui.ctx()) || hotkeys::down_pressed(ui.ctx()) { + new_key_value_to_highlight = if state.reverse_fn_order { + mapping.last_key_value() + } else { + mapping.first_key_value() + }; + } + } + if let Some((new_sym_ref, new_symbol_diff)) = new_key_value_to_highlight { + ret = Some(if column == 0 { + DiffViewAction::SetSymbolHighlight( + Some(*new_sym_ref), + new_symbol_diff.target_symbol, + ) + } else { + DiffViewAction::SetSymbolHighlight( + new_symbol_diff.target_symbol, + Some(*new_sym_ref), + ) + }); + } ui.scope(|ui| { ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);