Skip to content

Commit b9a5e3c

Browse files
committed
Diff view refactor
1 parent e202c3e commit b9a5e3c

File tree

8 files changed

+813
-1117
lines changed

8 files changed

+813
-1117
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@ authors = ["Luke Street <[email protected]>"]
1818
edition = "2021"
1919
license = "MIT OR Apache-2.0"
2020
repository = "https://github.com/encounter/objdiff"
21-
rust-version = "1.81"
21+
rust-version = "1.82"

objdiff-gui/src/app.rs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,14 @@ use crate::{
3333
arch_config_window, config_ui, general_config_ui, project_window, ConfigViewState,
3434
CONFIG_DISABLED_TEXT,
3535
},
36-
data_diff::data_diff_ui,
3736
debug::debug_window,
3837
demangle::{demangle_window, DemangleViewState},
39-
extab_diff::extab_diff_ui,
38+
diff::diff_view_ui,
4039
frame_history::FrameHistory,
41-
function_diff::function_diff_ui,
4240
graphics::{graphics_window, GraphicsConfig, GraphicsViewState},
4341
jobs::{jobs_menu_ui, jobs_window},
4442
rlwinm::{rlwinm_decode_window, RlwinmDecodeViewState},
45-
symbol_diff::{symbol_diff_ui, DiffViewAction, DiffViewNavigation, DiffViewState, View},
43+
symbol_diff::{DiffViewAction, DiffViewNavigation, DiffViewState, View},
4644
},
4745
};
4846

@@ -753,16 +751,7 @@ impl eframe::App for App {
753751

754752
let mut action = None;
755753
egui::CentralPanel::default().show(ctx, |ui| {
756-
let build_success = matches!(&diff_state.build, Some(b) if b.first_status.success && b.second_status.success);
757-
action = if diff_state.current_view == View::FunctionDiff && build_success {
758-
function_diff_ui(ui, diff_state, appearance)
759-
} else if diff_state.current_view == View::DataDiff && build_success {
760-
data_diff_ui(ui, diff_state, appearance)
761-
} else if diff_state.current_view == View::ExtabDiff && build_success {
762-
extab_diff_ui(ui, diff_state, appearance)
763-
} else {
764-
symbol_diff_ui(ui, diff_state, appearance)
765-
};
754+
action = diff_view_ui(ui, diff_state, appearance);
766755
});
767756

768757
project_window(ctx, state, show_project_config, config_state, appearance);

objdiff-gui/src/views/data_diff.rs

Lines changed: 6 additions & 185 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,15 @@ use std::{
44
mem::take,
55
};
66

7-
use egui::{text::LayoutJob, Id, Label, RichText, Sense, Widget};
7+
use egui::{text::LayoutJob, Label, Sense, Widget};
88
use objdiff_core::{
9-
diff::{ObjDataDiff, ObjDataDiffKind, ObjDataRelocDiff, ObjDiff},
9+
diff::{ObjDataDiff, ObjDataDiffKind, ObjDataRelocDiff},
1010
obj::ObjInfo,
1111
};
12-
use time::format_description;
1312

14-
use crate::{
15-
hotkeys,
16-
views::{
17-
appearance::Appearance,
18-
column_layout::{render_header, render_table},
19-
symbol_diff::{DiffViewAction, DiffViewNavigation, DiffViewState},
20-
write_text,
21-
},
22-
};
23-
24-
const BYTES_PER_ROW: usize = 16;
13+
use crate::views::{appearance::Appearance, write_text};
2514

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

3017
fn data_row_hover_ui(
3118
ui: &mut egui::Ui,
@@ -122,7 +109,7 @@ fn get_color_for_diff_kind(diff_kind: ObjDataDiffKind, appearance: &Appearance)
122109
}
123110
}
124111

125-
fn data_row_ui(
112+
pub(crate) fn data_row_ui(
126113
ui: &mut egui::Ui,
127114
obj: Option<&ObjInfo>,
128115
address: usize,
@@ -210,7 +197,7 @@ fn data_row_ui(
210197
}
211198
}
212199

213-
fn split_diffs(
200+
pub(crate) fn split_diffs(
214201
diffs: &[ObjDataDiff],
215202
reloc_diffs: &[ObjDataRelocDiff],
216203
) -> Vec<Vec<(ObjDataDiff, Vec<ObjDataRelocDiff>)>> {
@@ -271,169 +258,3 @@ fn split_diffs(
271258
}
272259
split_diffs
273260
}
274-
275-
#[derive(Clone, Copy)]
276-
struct SectionDiffContext<'a> {
277-
obj: &'a ObjInfo,
278-
diff: &'a ObjDiff,
279-
section_index: Option<usize>,
280-
}
281-
282-
impl<'a> SectionDiffContext<'a> {
283-
pub fn new(obj: Option<&'a (ObjInfo, ObjDiff)>, section_name: Option<&str>) -> Option<Self> {
284-
obj.map(|(obj, diff)| Self {
285-
obj,
286-
diff,
287-
section_index: section_name.and_then(|section_name| find_section(obj, section_name)),
288-
})
289-
}
290-
291-
#[inline]
292-
pub fn has_section(&self) -> bool { self.section_index.is_some() }
293-
}
294-
295-
fn data_table_ui(
296-
ui: &mut egui::Ui,
297-
available_width: f32,
298-
left_ctx: Option<SectionDiffContext<'_>>,
299-
right_ctx: Option<SectionDiffContext<'_>>,
300-
config: &Appearance,
301-
) -> Option<()> {
302-
let left_obj = left_ctx.map(|ctx| ctx.obj);
303-
let right_obj = right_ctx.map(|ctx| ctx.obj);
304-
let left_section = left_ctx
305-
.and_then(|ctx| ctx.section_index.map(|i| (&ctx.obj.sections[i], &ctx.diff.sections[i])));
306-
let right_section = right_ctx
307-
.and_then(|ctx| ctx.section_index.map(|i| (&ctx.obj.sections[i], &ctx.diff.sections[i])));
308-
let total_bytes = left_section
309-
.or(right_section)?
310-
.1
311-
.data_diff
312-
.iter()
313-
.fold(0usize, |accum, item| accum + item.len);
314-
if total_bytes == 0 {
315-
return None;
316-
}
317-
let total_rows = (total_bytes - 1) / BYTES_PER_ROW + 1;
318-
319-
let left_diffs =
320-
left_section.map(|(_, section)| split_diffs(&section.data_diff, &section.reloc_diff));
321-
let right_diffs =
322-
right_section.map(|(_, section)| split_diffs(&section.data_diff, &section.reloc_diff));
323-
324-
hotkeys::check_scroll_hotkeys(ui, true);
325-
326-
render_table(ui, available_width, 2, config.code_font.size, total_rows, |row, column| {
327-
let i = row.index();
328-
let address = i * BYTES_PER_ROW;
329-
row.col(|ui| {
330-
if column == 0 {
331-
if let Some(left_diffs) = &left_diffs {
332-
data_row_ui(ui, left_obj, address, &left_diffs[i], config);
333-
}
334-
} else if column == 1 {
335-
if let Some(right_diffs) = &right_diffs {
336-
data_row_ui(ui, right_obj, address, &right_diffs[i], config);
337-
}
338-
}
339-
});
340-
});
341-
Some(())
342-
}
343-
344-
#[must_use]
345-
pub fn data_diff_ui(
346-
ui: &mut egui::Ui,
347-
state: &DiffViewState,
348-
appearance: &Appearance,
349-
) -> Option<DiffViewAction> {
350-
let mut ret = None;
351-
let Some(result) = &state.build else {
352-
return ret;
353-
};
354-
355-
let section_name =
356-
state.symbol_state.left_symbol.as_ref().and_then(|s| s.section_name.as_deref()).or_else(
357-
|| state.symbol_state.right_symbol.as_ref().and_then(|s| s.section_name.as_deref()),
358-
);
359-
let left_ctx = SectionDiffContext::new(result.first_obj.as_ref(), section_name);
360-
let right_ctx = SectionDiffContext::new(result.second_obj.as_ref(), section_name);
361-
362-
// If both sides are missing a symbol, switch to symbol diff view
363-
if !right_ctx.is_some_and(|ctx| ctx.has_section())
364-
&& !left_ctx.is_some_and(|ctx| ctx.has_section())
365-
{
366-
return Some(DiffViewAction::Navigate(DiffViewNavigation::symbol_diff()));
367-
}
368-
369-
// Header
370-
let available_width = ui.available_width();
371-
render_header(ui, available_width, 2, |ui, column| {
372-
if column == 0 {
373-
// Left column
374-
if ui.button("⏴ Back").clicked() || hotkeys::back_pressed(ui.ctx()) {
375-
ret = Some(DiffViewAction::Navigate(DiffViewNavigation::symbol_diff()));
376-
}
377-
378-
if let Some(section) =
379-
left_ctx.and_then(|ctx| ctx.section_index.map(|i| &ctx.obj.sections[i]))
380-
{
381-
ui.label(
382-
RichText::new(section.name.clone())
383-
.font(appearance.code_font.clone())
384-
.color(appearance.highlight_color),
385-
);
386-
} else {
387-
ui.label(
388-
RichText::new("Missing")
389-
.font(appearance.code_font.clone())
390-
.color(appearance.replace_color),
391-
);
392-
}
393-
} else if column == 1 {
394-
// Right column
395-
ui.horizontal(|ui| {
396-
if ui.add_enabled(!state.build_running, egui::Button::new("Build")).clicked() {
397-
ret = Some(DiffViewAction::Build);
398-
}
399-
ui.scope(|ui| {
400-
ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);
401-
if state.build_running {
402-
ui.colored_label(appearance.replace_color, "Building…");
403-
} else {
404-
ui.label("Last built:");
405-
let format = format_description::parse("[hour]:[minute]:[second]").unwrap();
406-
ui.label(
407-
result.time.to_offset(appearance.utc_offset).format(&format).unwrap(),
408-
);
409-
}
410-
});
411-
});
412-
413-
if let Some(section) =
414-
right_ctx.and_then(|ctx| ctx.section_index.map(|i| &ctx.obj.sections[i]))
415-
{
416-
ui.label(
417-
RichText::new(section.name.clone())
418-
.font(appearance.code_font.clone())
419-
.color(appearance.highlight_color),
420-
);
421-
} else {
422-
ui.label(
423-
RichText::new("Missing")
424-
.font(appearance.code_font.clone())
425-
.color(appearance.replace_color),
426-
);
427-
}
428-
}
429-
});
430-
431-
// Table
432-
let id =
433-
Id::new(state.symbol_state.left_symbol.as_ref().and_then(|s| s.section_name.as_deref()))
434-
.with(state.symbol_state.right_symbol.as_ref().and_then(|s| s.section_name.as_deref()));
435-
ui.push_id(id, |ui| {
436-
data_table_ui(ui, available_width, left_ctx, right_ctx, appearance);
437-
});
438-
ret
439-
}

0 commit comments

Comments
 (0)