Skip to content

Commit

Permalink
Diff view refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
encounter committed Feb 3, 2025
1 parent e202c3e commit b9a5e3c
Show file tree
Hide file tree
Showing 8 changed files with 813 additions and 1,117 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ authors = ["Luke Street <luke@street.dev>"]
edition = "2021"
license = "MIT OR Apache-2.0"
repository = "https://github.com/encounter/objdiff"
rust-version = "1.81"
rust-version = "1.82"
17 changes: 3 additions & 14 deletions objdiff-gui/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,14 @@ use crate::{
arch_config_window, config_ui, general_config_ui, project_window, ConfigViewState,
CONFIG_DISABLED_TEXT,
},
data_diff::data_diff_ui,
debug::debug_window,
demangle::{demangle_window, DemangleViewState},
extab_diff::extab_diff_ui,
diff::diff_view_ui,
frame_history::FrameHistory,
function_diff::function_diff_ui,
graphics::{graphics_window, GraphicsConfig, GraphicsViewState},
jobs::{jobs_menu_ui, jobs_window},
rlwinm::{rlwinm_decode_window, RlwinmDecodeViewState},
symbol_diff::{symbol_diff_ui, DiffViewAction, DiffViewNavigation, DiffViewState, View},
symbol_diff::{DiffViewAction, DiffViewNavigation, DiffViewState, View},
},
};

Expand Down Expand Up @@ -753,16 +751,7 @@ impl eframe::App for App {

let mut action = None;
egui::CentralPanel::default().show(ctx, |ui| {
let build_success = matches!(&diff_state.build, Some(b) if b.first_status.success && b.second_status.success);
action = if diff_state.current_view == View::FunctionDiff && build_success {
function_diff_ui(ui, diff_state, appearance)
} else if diff_state.current_view == View::DataDiff && build_success {
data_diff_ui(ui, diff_state, appearance)
} else if diff_state.current_view == View::ExtabDiff && build_success {
extab_diff_ui(ui, diff_state, appearance)
} else {
symbol_diff_ui(ui, diff_state, appearance)
};
action = diff_view_ui(ui, diff_state, appearance);
});

project_window(ctx, state, show_project_config, config_state, appearance);
Expand Down
191 changes: 6 additions & 185 deletions objdiff-gui/src/views/data_diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,15 @@ use std::{
mem::take,
};

use egui::{text::LayoutJob, Id, Label, RichText, Sense, Widget};
use egui::{text::LayoutJob, Label, Sense, Widget};
use objdiff_core::{
diff::{ObjDataDiff, ObjDataDiffKind, ObjDataRelocDiff, ObjDiff},
diff::{ObjDataDiff, ObjDataDiffKind, ObjDataRelocDiff},
obj::ObjInfo,
};
use time::format_description;

use crate::{
hotkeys,
views::{
appearance::Appearance,
column_layout::{render_header, render_table},
symbol_diff::{DiffViewAction, DiffViewNavigation, DiffViewState},
write_text,
},
};

const BYTES_PER_ROW: usize = 16;
use crate::views::{appearance::Appearance, write_text};

fn find_section(obj: &ObjInfo, section_name: &str) -> Option<usize> {
obj.sections.iter().position(|section| section.name == section_name)
}
pub(crate) const BYTES_PER_ROW: usize = 16;

fn data_row_hover_ui(
ui: &mut egui::Ui,
Expand Down Expand Up @@ -122,7 +109,7 @@ fn get_color_for_diff_kind(diff_kind: ObjDataDiffKind, appearance: &Appearance)
}
}

fn data_row_ui(
pub(crate) fn data_row_ui(
ui: &mut egui::Ui,
obj: Option<&ObjInfo>,
address: usize,
Expand Down Expand Up @@ -210,7 +197,7 @@ fn data_row_ui(
}
}

fn split_diffs(
pub(crate) fn split_diffs(
diffs: &[ObjDataDiff],
reloc_diffs: &[ObjDataRelocDiff],
) -> Vec<Vec<(ObjDataDiff, Vec<ObjDataRelocDiff>)>> {
Expand Down Expand Up @@ -271,169 +258,3 @@ fn split_diffs(
}
split_diffs
}

#[derive(Clone, Copy)]
struct SectionDiffContext<'a> {
obj: &'a ObjInfo,
diff: &'a ObjDiff,
section_index: Option<usize>,
}

impl<'a> SectionDiffContext<'a> {
pub fn new(obj: Option<&'a (ObjInfo, ObjDiff)>, section_name: Option<&str>) -> Option<Self> {
obj.map(|(obj, diff)| Self {
obj,
diff,
section_index: section_name.and_then(|section_name| find_section(obj, section_name)),
})
}

#[inline]
pub fn has_section(&self) -> bool { self.section_index.is_some() }
}

fn data_table_ui(
ui: &mut egui::Ui,
available_width: f32,
left_ctx: Option<SectionDiffContext<'_>>,
right_ctx: Option<SectionDiffContext<'_>>,
config: &Appearance,
) -> Option<()> {
let left_obj = left_ctx.map(|ctx| ctx.obj);
let right_obj = right_ctx.map(|ctx| ctx.obj);
let left_section = left_ctx
.and_then(|ctx| ctx.section_index.map(|i| (&ctx.obj.sections[i], &ctx.diff.sections[i])));
let right_section = right_ctx
.and_then(|ctx| ctx.section_index.map(|i| (&ctx.obj.sections[i], &ctx.diff.sections[i])));
let total_bytes = left_section
.or(right_section)?
.1
.data_diff
.iter()
.fold(0usize, |accum, item| accum + item.len);
if total_bytes == 0 {
return None;
}
let total_rows = (total_bytes - 1) / BYTES_PER_ROW + 1;

let left_diffs =
left_section.map(|(_, section)| split_diffs(&section.data_diff, &section.reloc_diff));
let right_diffs =
right_section.map(|(_, section)| split_diffs(&section.data_diff, &section.reloc_diff));

hotkeys::check_scroll_hotkeys(ui, true);

render_table(ui, available_width, 2, config.code_font.size, total_rows, |row, column| {
let i = row.index();
let address = i * BYTES_PER_ROW;
row.col(|ui| {
if column == 0 {
if let Some(left_diffs) = &left_diffs {
data_row_ui(ui, left_obj, address, &left_diffs[i], config);
}
} else if column == 1 {
if let Some(right_diffs) = &right_diffs {
data_row_ui(ui, right_obj, address, &right_diffs[i], config);
}
}
});
});
Some(())
}

#[must_use]
pub fn data_diff_ui(
ui: &mut egui::Ui,
state: &DiffViewState,
appearance: &Appearance,
) -> Option<DiffViewAction> {
let mut ret = None;
let Some(result) = &state.build else {
return ret;
};

let section_name =
state.symbol_state.left_symbol.as_ref().and_then(|s| s.section_name.as_deref()).or_else(
|| state.symbol_state.right_symbol.as_ref().and_then(|s| s.section_name.as_deref()),
);
let left_ctx = SectionDiffContext::new(result.first_obj.as_ref(), section_name);
let right_ctx = SectionDiffContext::new(result.second_obj.as_ref(), section_name);

// If both sides are missing a symbol, switch to symbol diff view
if !right_ctx.is_some_and(|ctx| ctx.has_section())
&& !left_ctx.is_some_and(|ctx| ctx.has_section())
{
return Some(DiffViewAction::Navigate(DiffViewNavigation::symbol_diff()));
}

// Header
let available_width = ui.available_width();
render_header(ui, available_width, 2, |ui, column| {
if column == 0 {
// Left column
if ui.button("⏴ Back").clicked() || hotkeys::back_pressed(ui.ctx()) {
ret = Some(DiffViewAction::Navigate(DiffViewNavigation::symbol_diff()));
}

if let Some(section) =
left_ctx.and_then(|ctx| ctx.section_index.map(|i| &ctx.obj.sections[i]))
{
ui.label(
RichText::new(section.name.clone())
.font(appearance.code_font.clone())
.color(appearance.highlight_color),
);
} else {
ui.label(
RichText::new("Missing")
.font(appearance.code_font.clone())
.color(appearance.replace_color),
);
}
} else if column == 1 {
// Right column
ui.horizontal(|ui| {
if ui.add_enabled(!state.build_running, egui::Button::new("Build")).clicked() {
ret = Some(DiffViewAction::Build);
}
ui.scope(|ui| {
ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);
if state.build_running {
ui.colored_label(appearance.replace_color, "Building…");
} else {
ui.label("Last built:");
let format = format_description::parse("[hour]:[minute]:[second]").unwrap();
ui.label(
result.time.to_offset(appearance.utc_offset).format(&format).unwrap(),
);
}
});
});

if let Some(section) =
right_ctx.and_then(|ctx| ctx.section_index.map(|i| &ctx.obj.sections[i]))
{
ui.label(
RichText::new(section.name.clone())
.font(appearance.code_font.clone())
.color(appearance.highlight_color),
);
} else {
ui.label(
RichText::new("Missing")
.font(appearance.code_font.clone())
.color(appearance.replace_color),
);
}
}
});

// Table
let id =
Id::new(state.symbol_state.left_symbol.as_ref().and_then(|s| s.section_name.as_deref()))
.with(state.symbol_state.right_symbol.as_ref().and_then(|s| s.section_name.as_deref()));
ui.push_id(id, |ui| {
data_table_ui(ui, available_width, left_ctx, right_ctx, appearance);
});
ret
}
Loading

0 comments on commit b9a5e3c

Please sign in to comment.