Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions objdiff-gui/src/hotkeys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ pub fn end_pressed(ctx: &Context) -> bool { ctx.input_mut(|i| i.key_pressed(Key:

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()) && include_small_increments {
if include_small_increments && consume_up_key(ui.ctx()) {
ui.scroll_with_delta_animation(vec2(0.0, ui_height / 10.0), ScrollAnimation::none());
} else if down_pressed(ui.ctx()) && include_small_increments {
} else if include_small_increments && consume_down_key(ui.ctx()) {
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());
Expand Down Expand Up @@ -106,3 +106,15 @@ const CHANGE_BASE_SHORTCUT: KeyboardShortcut = KeyboardShortcut::new(Modifiers::
pub fn consume_change_base_shortcut(ctx: &Context) -> bool {
ctx.input_mut(|i| i.consume_shortcut(&CHANGE_BASE_SHORTCUT))
}

const PREV_DIFF_SHORTCUT: KeyboardShortcut = KeyboardShortcut::new(Modifiers::CTRL, Key::ArrowUp);

pub fn consume_prev_diff_shortcut(ctx: &Context) -> bool {
ctx.input_mut(|i| i.consume_shortcut(&PREV_DIFF_SHORTCUT))
}

const NEXT_DIFF_SHORTCUT: KeyboardShortcut = KeyboardShortcut::new(Modifiers::CTRL, Key::ArrowDown);

pub fn consume_next_diff_shortcut(ctx: &Context) -> bool {
ctx.input_mut(|i| i.consume_shortcut(&NEXT_DIFF_SHORTCUT))
}
96 changes: 91 additions & 5 deletions objdiff-gui/src/views/diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use egui::{Id, Layout, RichText, ScrollArea, TextEdit, Ui, Widget, text::LayoutJ
use objdiff_core::{
build::BuildStatus,
diff::{
DiffObjConfig, ObjectDiff, SymbolDiff,
DataDiffKind, DiffObjConfig, InstructionDiffKind, ObjectDiff, SymbolDiff,
data::BYTES_PER_ROW,
display::{
ContextItem, DiffText, HoverItem, HoverItemColor, SymbolFilter, SymbolNavigationKind,
Expand Down Expand Up @@ -185,6 +185,9 @@ pub fn diff_view_ui(
let available_width = ui.available_width();
let mut open_sections = (None, None);

let mut scroll_to_prev_diff = false;
let mut scroll_to_next_diff = false;

render_header(ui, available_width, 2, |ui, column| {
if column == 0 {
// Left column
Expand Down Expand Up @@ -450,6 +453,31 @@ pub fn diff_view_ui(
{
ret = Some(DiffViewAction::SelectingRight(symbol_ref.clone()));
}
needs_separator = true;
}

if state.current_view == View::FunctionDiff
|| state.current_view == View::DataDiff
{
if needs_separator {
ui.separator();
}
if ui
.button("⏴ Prev diff")
.on_hover_text_at_pointer("Scroll to the previous difference (Ctrl+Up)")
.clicked()
|| hotkeys::consume_prev_diff_shortcut(ui.ctx())
{
scroll_to_prev_diff = true;
}
if ui
.button("Next diff ⏵")
.on_hover_text_at_pointer("Scroll to the next difference (Ctrl+Down)")
.clicked()
|| hotkeys::consume_next_diff_shortcut(ui.ctx())
{
scroll_to_next_diff = true;
}
}
} else if right_ctx.status.success && !right_ctx.has_symbol() {
let mut search = state.search.clone();
Expand Down Expand Up @@ -493,14 +521,21 @@ pub fn diff_view_ui(
return;
}
let instructions_len = left_symbol_diff.instruction_rows.len();
let mut min_row = None;
let mut max_row = None;
render_table(
ui,
available_width,
2,
appearance.code_font.size,
instructions_len,
state.function_state.scroll_to_row,
state.scroll_to_diff_row,
|row, column| {
if min_row.is_none() {
min_row = Some(row.index());
}
max_row = Some(row.index());

if column == 0 {
if let Some(action) = asm_col_ui(
row,
Expand Down Expand Up @@ -537,6 +572,27 @@ pub fn diff_view_ui(
}
},
);

if scroll_to_prev_diff && let Some(min_row) = min_row {
for (ins_idx, ins_diff) in
right_diff.symbols[right_symbol_idx].instruction_rows.iter().enumerate().rev()
{
if ins_idx <= min_row && ins_diff.kind != InstructionDiffKind::None {
ret = Some(DiffViewAction::ScrollToRow(ins_idx));
break;
}
}
}
if scroll_to_next_diff && let Some(max_row) = max_row {
for (ins_idx, ins_diff) in
right_diff.symbols[right_symbol_idx].instruction_rows.iter().enumerate()
{
if ins_idx >= max_row - 1 && ins_diff.kind != InstructionDiffKind::None {
ret = Some(DiffViewAction::ScrollToRow(ins_idx));
break;
}
}
}
} else if let (
View::DataDiff,
Some((left_obj, _left_diff)),
Expand All @@ -556,14 +612,21 @@ pub fn diff_view_ui(
if total_rows == 0 {
return;
}
let mut min_row = None;
let mut max_row = None;
render_table(
ui,
available_width,
2,
appearance.code_font.size,
total_rows,
None,
state.scroll_to_diff_row,
|row, column| {
if min_row.is_none() {
min_row = Some(row.index());
}
max_row = Some(row.index());

let i = row.index();
let row_offset = i as u64 * BYTES_PER_ROW as u64;
row.col(|ui| {
Expand Down Expand Up @@ -591,6 +654,29 @@ pub fn diff_view_ui(
});
},
);

if scroll_to_prev_diff && let Some(min_row) = min_row {
for (row_idx, diff_row) in right_symbol_diff.data_rows.iter().enumerate().rev() {
if row_idx <= min_row
&& (diff_row.segments.iter().any(|dd| dd.kind != DataDiffKind::None)
|| diff_row.relocations.iter().any(|rd| rd.kind != DataDiffKind::None))
{
ret = Some(DiffViewAction::ScrollToRow(row_idx));
break;
}
}
}
if scroll_to_next_diff && let Some(max_row) = max_row {
for (row_idx, diff_row) in right_symbol_diff.data_rows.iter().enumerate() {
if row_idx >= max_row - 1
&& (diff_row.segments.iter().any(|dd| dd.kind != DataDiffKind::None)
|| diff_row.relocations.iter().any(|rd| rd.kind != DataDiffKind::None))
{
ret = Some(DiffViewAction::ScrollToRow(row_idx));
break;
}
}
}
} else {
// Split view
render_strips(ui, available_width, 2, |ui, column| {
Expand Down Expand Up @@ -693,7 +779,7 @@ fn diff_col_ui(
1,
appearance.code_font.size,
total_rows,
None,
state.scroll_to_diff_row,
|row, _column| {
let i = row.index();
let row_offset = i as u64 * BYTES_PER_ROW as u64;
Expand All @@ -717,7 +803,7 @@ fn diff_col_ui(
1,
appearance.code_font.size,
symbol_diff.instruction_rows.len(),
state.function_state.scroll_to_row,
state.scroll_to_diff_row,
|row, column| {
if let Some(action) = asm_col_ui(
row,
Expand Down
1 change: 0 additions & 1 deletion objdiff-gui/src/views/function_diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ use crate::views::{
pub struct FunctionViewState {
left_highlight: HighlightKind,
right_highlight: HighlightKind,
pub scroll_to_row: Option<usize>,
}

impl FunctionViewState {
Expand Down
5 changes: 3 additions & 2 deletions objdiff-gui/src/views/symbol_diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ pub struct DiffViewState {
pub function_state: FunctionViewState,
pub search: String,
pub search_regex: Option<Regex>,
pub scroll_to_diff_row: Option<usize>,
pub build_running: bool,
pub scratch_available: bool,
pub scratch_running: bool,
Expand Down Expand Up @@ -197,7 +198,7 @@ impl DiffViewState {

// Clear the scroll flags to prevent it from scrolling continuously.
self.symbol_state.autoscroll_to_highlighted_symbols = false;
self.function_state.scroll_to_row = None;
self.scroll_to_diff_row = None;

let Some(action) = action else {
return;
Expand Down Expand Up @@ -366,7 +367,7 @@ impl DiffViewState {
state.config.diff_obj_config.show_data_flow = value;
}
DiffViewAction::ScrollToRow(row) => {
self.function_state.scroll_to_row = Some(row);
self.scroll_to_diff_row = Some(row);
}
}
}
Expand Down
Loading