mirror of https://github.com/encounter/objdiff.git
Add dark/light theme toggle (light theme WIP)
This commit is contained in:
parent
c7a326b160
commit
b02e32f2b7
|
@ -2412,7 +2412,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objdiff"
|
name = "objdiff"
|
||||||
version = "0.3.3"
|
version = "0.3.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "objdiff"
|
name = "objdiff"
|
||||||
version = "0.3.3"
|
version = "0.3.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.65"
|
rust-version = "1.65"
|
||||||
authors = ["Luke Street <luke@street.dev>"]
|
authors = ["Luke Street <luke@street.dev>"]
|
||||||
|
|
65
src/app.rs
65
src/app.rs
|
@ -68,6 +68,21 @@ pub struct ViewConfig {
|
||||||
pub code_font: FontId,
|
pub code_font: FontId,
|
||||||
pub diff_colors: Vec<Color32>,
|
pub diff_colors: Vec<Color32>,
|
||||||
pub reverse_fn_order: bool,
|
pub reverse_fn_order: bool,
|
||||||
|
pub theme: eframe::Theme,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub text_color: Color32, // GRAY
|
||||||
|
#[serde(skip)]
|
||||||
|
pub emphasized_text_color: Color32, // LIGHT_GRAY
|
||||||
|
#[serde(skip)]
|
||||||
|
pub deemphasized_text_color: Color32, // DARK_GRAY
|
||||||
|
#[serde(skip)]
|
||||||
|
pub highlight_color: Color32, // WHITE
|
||||||
|
#[serde(skip)]
|
||||||
|
pub replace_color: Color32, // LIGHT_BLUE
|
||||||
|
#[serde(skip)]
|
||||||
|
pub insert_color: Color32, // GREEN
|
||||||
|
#[serde(skip)]
|
||||||
|
pub delete_color: Color32, // RED
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ViewConfig {
|
impl Default for ViewConfig {
|
||||||
|
@ -77,6 +92,14 @@ impl Default for ViewConfig {
|
||||||
code_font: FontId { size: 14.0, family: FontFamily::Monospace },
|
code_font: FontId { size: 14.0, family: FontFamily::Monospace },
|
||||||
diff_colors: DEFAULT_COLOR_ROTATION.to_vec(),
|
diff_colors: DEFAULT_COLOR_ROTATION.to_vec(),
|
||||||
reverse_fn_order: false,
|
reverse_fn_order: false,
|
||||||
|
theme: eframe::Theme::Dark,
|
||||||
|
text_color: Color32::GRAY,
|
||||||
|
emphasized_text_color: Color32::LIGHT_GRAY,
|
||||||
|
deemphasized_text_color: Color32::DARK_GRAY,
|
||||||
|
highlight_color: Color32::WHITE,
|
||||||
|
replace_color: Color32::LIGHT_BLUE,
|
||||||
|
insert_color: Color32::GREEN,
|
||||||
|
delete_color: Color32::from_rgb(200, 40, 41),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -249,7 +272,7 @@ impl eframe::App for App {
|
||||||
let Self { config, view_state, .. } = self;
|
let Self { config, view_state, .. } = self;
|
||||||
|
|
||||||
{
|
{
|
||||||
let config = &view_state.view_config;
|
let config = &mut view_state.view_config;
|
||||||
let mut style = (*ctx.style()).clone();
|
let mut style = (*ctx.style()).clone();
|
||||||
style.text_styles.insert(TextStyle::Body, FontId {
|
style.text_styles.insert(TextStyle::Body, FontId {
|
||||||
size: (config.ui_font.size * 0.75).floor(),
|
size: (config.ui_font.size * 0.75).floor(),
|
||||||
|
@ -262,6 +285,28 @@ impl eframe::App for App {
|
||||||
family: config.ui_font.family.clone(),
|
family: config.ui_font.family.clone(),
|
||||||
});
|
});
|
||||||
style.text_styles.insert(TextStyle::Monospace, config.code_font.clone());
|
style.text_styles.insert(TextStyle::Monospace, config.code_font.clone());
|
||||||
|
match config.theme {
|
||||||
|
eframe::Theme::Dark => {
|
||||||
|
style.visuals = egui::Visuals::dark();
|
||||||
|
config.text_color = Color32::GRAY;
|
||||||
|
config.emphasized_text_color = Color32::LIGHT_GRAY;
|
||||||
|
config.deemphasized_text_color = Color32::DARK_GRAY;
|
||||||
|
config.highlight_color = Color32::WHITE;
|
||||||
|
config.replace_color = Color32::LIGHT_BLUE;
|
||||||
|
config.insert_color = Color32::GREEN;
|
||||||
|
config.delete_color = Color32::from_rgb(200, 40, 41);
|
||||||
|
}
|
||||||
|
eframe::Theme::Light => {
|
||||||
|
style.visuals = egui::Visuals::light();
|
||||||
|
config.text_color = Color32::GRAY;
|
||||||
|
config.emphasized_text_color = Color32::DARK_GRAY;
|
||||||
|
config.deemphasized_text_color = Color32::LIGHT_GRAY;
|
||||||
|
config.highlight_color = Color32::BLACK;
|
||||||
|
config.replace_color = Color32::DARK_BLUE;
|
||||||
|
config.insert_color = Color32::DARK_GREEN;
|
||||||
|
config.delete_color = Color32::from_rgb(200, 40, 41);
|
||||||
|
}
|
||||||
|
}
|
||||||
ctx.set_style(style);
|
ctx.set_style(style);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,6 +368,20 @@ impl eframe::App for App {
|
||||||
}
|
}
|
||||||
|
|
||||||
egui::Window::new("Config").open(&mut view_state.show_config).show(ctx, |ui| {
|
egui::Window::new("Config").open(&mut view_state.show_config).show(ctx, |ui| {
|
||||||
|
egui::ComboBox::from_label("Theme")
|
||||||
|
.selected_text(format!("{:?}", view_state.view_config.theme))
|
||||||
|
.show_ui(ui, |ui| {
|
||||||
|
ui.selectable_value(
|
||||||
|
&mut view_state.view_config.theme,
|
||||||
|
eframe::Theme::Dark,
|
||||||
|
"Dark",
|
||||||
|
);
|
||||||
|
ui.selectable_value(
|
||||||
|
&mut view_state.view_config.theme,
|
||||||
|
eframe::Theme::Light,
|
||||||
|
"Light",
|
||||||
|
);
|
||||||
|
});
|
||||||
ui.label("UI font:");
|
ui.label("UI font:");
|
||||||
egui::introspection::font_id_ui(ui, &mut view_state.view_config.ui_font);
|
egui::introspection::font_id_ui(ui, &mut view_state.view_config.ui_font);
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
@ -359,7 +418,7 @@ impl eframe::App for App {
|
||||||
{
|
{
|
||||||
ui.scope(|ui| {
|
ui.scope(|ui| {
|
||||||
ui.style_mut().override_text_style = Some(TextStyle::Monospace);
|
ui.style_mut().override_text_style = Some(TextStyle::Monospace);
|
||||||
ui.colored_label(Color32::LIGHT_BLUE, &demangled);
|
ui.colored_label(view_state.view_config.replace_color, &demangled);
|
||||||
});
|
});
|
||||||
if ui.button("Copy").clicked() {
|
if ui.button("Copy").clicked() {
|
||||||
ui.output_mut(|output| output.copied_text = demangled);
|
ui.output_mut(|output| output.copied_text = demangled);
|
||||||
|
@ -367,7 +426,7 @@ impl eframe::App for App {
|
||||||
} else {
|
} else {
|
||||||
ui.scope(|ui| {
|
ui.scope(|ui| {
|
||||||
ui.style_mut().override_text_style = Some(TextStyle::Monospace);
|
ui.style_mut().override_text_style = Some(TextStyle::Monospace);
|
||||||
ui.colored_label(Color32::LIGHT_RED, "[invalid]");
|
ui.colored_label(view_state.view_config.replace_color, "[invalid]");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -406,7 +406,9 @@ pub fn diff_objs(left: &mut ObjInfo, right: &mut ObjInfo, _diff_config: &DiffCon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let Some(right_section) = right.sections.iter_mut().find(|s| s.name == left_section.name) else {
|
let Some(right_section) =
|
||||||
|
right.sections.iter_mut().find(|s| s.name == left_section.name)
|
||||||
|
else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if left_section.kind == ObjSectionKind::Data {
|
if left_section.kind == ObjSectionKind::Data {
|
||||||
|
|
|
@ -37,7 +37,8 @@ fn main() {
|
||||||
|
|
||||||
let exec_path: Rc<Mutex<Option<PathBuf>>> = Rc::new(Mutex::new(None));
|
let exec_path: Rc<Mutex<Option<PathBuf>>> = Rc::new(Mutex::new(None));
|
||||||
let exec_path_clone = exec_path.clone();
|
let exec_path_clone = exec_path.clone();
|
||||||
let mut native_options = eframe::NativeOptions::default();
|
let mut native_options =
|
||||||
|
eframe::NativeOptions { follow_system_theme: false, ..Default::default() };
|
||||||
match load_icon() {
|
match load_icon() {
|
||||||
Ok(data) => {
|
Ok(data) => {
|
||||||
native_options.icon_data = Some(data);
|
native_options.icon_data = Some(data);
|
||||||
|
|
|
@ -5,7 +5,7 @@ use std::sync::{Arc, RwLock};
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use const_format::formatcp;
|
use const_format::formatcp;
|
||||||
use egui::{output::OpenUrl, Color32};
|
use egui::output::OpenUrl;
|
||||||
use self_update::cargo_crate_version;
|
use self_update::cargo_crate_version;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -79,7 +79,7 @@ pub fn config_ui(ui: &mut egui::Ui, config: &Arc<RwLock<AppConfig>>, view_state:
|
||||||
if let Some(state) = &view_state.check_update {
|
if let Some(state) = &view_state.check_update {
|
||||||
ui.label(format!("Latest version: {}", state.latest_release.version));
|
ui.label(format!("Latest version: {}", state.latest_release.version));
|
||||||
if state.update_available {
|
if state.update_available {
|
||||||
ui.colored_label(Color32::LIGHT_GREEN, "Update available");
|
ui.colored_label(view_state.view_config.insert_color, "Update available");
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
if state.found_binary
|
if state.found_binary
|
||||||
&& ui
|
&& ui
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{cmp::min, default::Default, mem::take};
|
use std::{cmp::min, default::Default, mem::take};
|
||||||
|
|
||||||
use egui::{text::LayoutJob, Align, Color32, Label, Layout, Sense, Vec2};
|
use egui::{text::LayoutJob, Align, Label, Layout, Sense, Vec2};
|
||||||
use egui_extras::{Column, TableBuilder};
|
use egui_extras::{Column, TableBuilder};
|
||||||
use time::format_description;
|
use time::format_description;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ use crate::{
|
||||||
app::{SymbolReference, View, ViewConfig, ViewState},
|
app::{SymbolReference, View, ViewConfig, ViewState},
|
||||||
jobs::Job,
|
jobs::Job,
|
||||||
obj::{ObjDataDiff, ObjDataDiffKind, ObjInfo, ObjSection},
|
obj::{ObjDataDiff, ObjDataDiffKind, ObjInfo, ObjSection},
|
||||||
views::{write_text, COLOR_RED},
|
views::write_text,
|
||||||
};
|
};
|
||||||
|
|
||||||
const BYTES_PER_ROW: usize = 16;
|
const BYTES_PER_ROW: usize = 16;
|
||||||
|
@ -24,17 +24,17 @@ fn data_row_ui(ui: &mut egui::Ui, address: usize, diffs: &[ObjDataDiff], config:
|
||||||
let mut job = LayoutJob::default();
|
let mut job = LayoutJob::default();
|
||||||
write_text(
|
write_text(
|
||||||
format!("{address:08X}: ").as_str(),
|
format!("{address:08X}: ").as_str(),
|
||||||
Color32::GRAY,
|
config.text_color,
|
||||||
&mut job,
|
&mut job,
|
||||||
config.code_font.clone(),
|
config.code_font.clone(),
|
||||||
);
|
);
|
||||||
let mut cur_addr = 0usize;
|
let mut cur_addr = 0usize;
|
||||||
for diff in diffs {
|
for diff in diffs {
|
||||||
let base_color = match diff.kind {
|
let base_color = match diff.kind {
|
||||||
ObjDataDiffKind::None => Color32::GRAY,
|
ObjDataDiffKind::None => config.text_color,
|
||||||
ObjDataDiffKind::Replace => Color32::LIGHT_BLUE,
|
ObjDataDiffKind::Replace => config.replace_color,
|
||||||
ObjDataDiffKind::Delete => COLOR_RED,
|
ObjDataDiffKind::Delete => config.delete_color,
|
||||||
ObjDataDiffKind::Insert => Color32::GREEN,
|
ObjDataDiffKind::Insert => config.insert_color,
|
||||||
};
|
};
|
||||||
if diff.data.is_empty() {
|
if diff.data.is_empty() {
|
||||||
let mut str = " ".repeat(diff.len);
|
let mut str = " ".repeat(diff.len);
|
||||||
|
@ -58,15 +58,15 @@ fn data_row_ui(ui: &mut egui::Ui, address: usize, diffs: &[ObjDataDiff], config:
|
||||||
let mut str = " ".to_string();
|
let mut str = " ".to_string();
|
||||||
str.push_str(" ".repeat(n).as_str());
|
str.push_str(" ".repeat(n).as_str());
|
||||||
str.push_str(" ".repeat(n / 8).as_str());
|
str.push_str(" ".repeat(n / 8).as_str());
|
||||||
write_text(str.as_str(), Color32::GRAY, &mut job, config.code_font.clone());
|
write_text(str.as_str(), config.text_color, &mut job, config.code_font.clone());
|
||||||
}
|
}
|
||||||
write_text(" ", Color32::GRAY, &mut job, config.code_font.clone());
|
write_text(" ", config.text_color, &mut job, config.code_font.clone());
|
||||||
for diff in diffs {
|
for diff in diffs {
|
||||||
let base_color = match diff.kind {
|
let base_color = match diff.kind {
|
||||||
ObjDataDiffKind::None => Color32::GRAY,
|
ObjDataDiffKind::None => config.text_color,
|
||||||
ObjDataDiffKind::Replace => Color32::LIGHT_BLUE,
|
ObjDataDiffKind::Replace => config.replace_color,
|
||||||
ObjDataDiffKind::Delete => COLOR_RED,
|
ObjDataDiffKind::Delete => config.delete_color,
|
||||||
ObjDataDiffKind::Insert => Color32::GREEN,
|
ObjDataDiffKind::Insert => config.insert_color,
|
||||||
};
|
};
|
||||||
if diff.data.is_empty() {
|
if diff.data.is_empty() {
|
||||||
write_text(
|
write_text(
|
||||||
|
@ -163,7 +163,8 @@ fn data_table_ui(
|
||||||
|
|
||||||
pub fn data_diff_ui(ui: &mut egui::Ui, view_state: &mut ViewState) -> bool {
|
pub fn data_diff_ui(ui: &mut egui::Ui, view_state: &mut ViewState) -> bool {
|
||||||
let mut rebuild = false;
|
let mut rebuild = false;
|
||||||
let (Some(result), Some(selected_symbol)) = (&view_state.build, &view_state.selected_symbol) else {
|
let (Some(result), Some(selected_symbol)) = (&view_state.build, &view_state.selected_symbol)
|
||||||
|
else {
|
||||||
return rebuild;
|
return rebuild;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -188,7 +189,10 @@ pub fn data_diff_ui(ui: &mut egui::Ui, view_state: &mut ViewState) -> bool {
|
||||||
ui.scope(|ui| {
|
ui.scope(|ui| {
|
||||||
ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);
|
ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);
|
||||||
ui.style_mut().wrap = Some(false);
|
ui.style_mut().wrap = Some(false);
|
||||||
ui.colored_label(Color32::WHITE, &selected_symbol.symbol_name);
|
ui.colored_label(
|
||||||
|
view_state.view_config.highlight_color,
|
||||||
|
&selected_symbol.symbol_name,
|
||||||
|
);
|
||||||
ui.label("Diff target:");
|
ui.label("Diff target:");
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,12 +14,18 @@ use crate::{
|
||||||
ObjInfo, ObjIns, ObjInsArg, ObjInsArgDiff, ObjInsDiff, ObjInsDiffKind, ObjReloc,
|
ObjInfo, ObjIns, ObjInsArg, ObjInsArgDiff, ObjInsDiff, ObjInsDiffKind, ObjReloc,
|
||||||
ObjRelocKind, ObjSymbol,
|
ObjRelocKind, ObjSymbol,
|
||||||
},
|
},
|
||||||
views::{symbol_diff::match_color_for_symbol, write_text, COLOR_RED},
|
views::{symbol_diff::match_color_for_symbol, write_text},
|
||||||
};
|
};
|
||||||
|
|
||||||
fn write_reloc_name(reloc: &ObjReloc, color: Color32, job: &mut LayoutJob, font_id: FontId) {
|
fn write_reloc_name(
|
||||||
|
reloc: &ObjReloc,
|
||||||
|
color: Color32,
|
||||||
|
job: &mut LayoutJob,
|
||||||
|
font_id: FontId,
|
||||||
|
config: &ViewConfig,
|
||||||
|
) {
|
||||||
let name = reloc.target.demangled_name.as_ref().unwrap_or(&reloc.target.name);
|
let name = reloc.target.demangled_name.as_ref().unwrap_or(&reloc.target.name);
|
||||||
write_text(name, Color32::LIGHT_GRAY, job, font_id.clone());
|
write_text(name, config.emphasized_text_color, job, font_id.clone());
|
||||||
match reloc.target.addend.cmp(&0i64) {
|
match reloc.target.addend.cmp(&0i64) {
|
||||||
Ordering::Greater => {
|
Ordering::Greater => {
|
||||||
write_text(&format!("+{:#X}", reloc.target.addend), color, job, font_id)
|
write_text(&format!("+{:#X}", reloc.target.addend), color, job, font_id)
|
||||||
|
@ -31,51 +37,57 @@ fn write_reloc_name(reloc: &ObjReloc, color: Color32, job: &mut LayoutJob, font_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_reloc(reloc: &ObjReloc, color: Color32, job: &mut LayoutJob, font_id: FontId) {
|
fn write_reloc(
|
||||||
|
reloc: &ObjReloc,
|
||||||
|
color: Color32,
|
||||||
|
job: &mut LayoutJob,
|
||||||
|
font_id: FontId,
|
||||||
|
config: &ViewConfig,
|
||||||
|
) {
|
||||||
match reloc.kind {
|
match reloc.kind {
|
||||||
ObjRelocKind::PpcAddr16Lo => {
|
ObjRelocKind::PpcAddr16Lo => {
|
||||||
write_reloc_name(reloc, color, job, font_id.clone());
|
write_reloc_name(reloc, color, job, font_id.clone(), config);
|
||||||
write_text("@l", color, job, font_id);
|
write_text("@l", color, job, font_id);
|
||||||
}
|
}
|
||||||
ObjRelocKind::PpcAddr16Hi => {
|
ObjRelocKind::PpcAddr16Hi => {
|
||||||
write_reloc_name(reloc, color, job, font_id.clone());
|
write_reloc_name(reloc, color, job, font_id.clone(), config);
|
||||||
write_text("@h", color, job, font_id);
|
write_text("@h", color, job, font_id);
|
||||||
}
|
}
|
||||||
ObjRelocKind::PpcAddr16Ha => {
|
ObjRelocKind::PpcAddr16Ha => {
|
||||||
write_reloc_name(reloc, color, job, font_id.clone());
|
write_reloc_name(reloc, color, job, font_id.clone(), config);
|
||||||
write_text("@ha", color, job, font_id);
|
write_text("@ha", color, job, font_id);
|
||||||
}
|
}
|
||||||
ObjRelocKind::PpcEmbSda21 => {
|
ObjRelocKind::PpcEmbSda21 => {
|
||||||
write_reloc_name(reloc, color, job, font_id.clone());
|
write_reloc_name(reloc, color, job, font_id.clone(), config);
|
||||||
write_text("@sda21", color, job, font_id);
|
write_text("@sda21", color, job, font_id);
|
||||||
}
|
}
|
||||||
ObjRelocKind::MipsHi16 => {
|
ObjRelocKind::MipsHi16 => {
|
||||||
write_text("%hi(", color, job, font_id.clone());
|
write_text("%hi(", color, job, font_id.clone());
|
||||||
write_reloc_name(reloc, color, job, font_id.clone());
|
write_reloc_name(reloc, color, job, font_id.clone(), config);
|
||||||
write_text(")", color, job, font_id);
|
write_text(")", color, job, font_id);
|
||||||
}
|
}
|
||||||
ObjRelocKind::MipsLo16 => {
|
ObjRelocKind::MipsLo16 => {
|
||||||
write_text("%lo(", color, job, font_id.clone());
|
write_text("%lo(", color, job, font_id.clone());
|
||||||
write_reloc_name(reloc, color, job, font_id.clone());
|
write_reloc_name(reloc, color, job, font_id.clone(), config);
|
||||||
write_text(")", color, job, font_id);
|
write_text(")", color, job, font_id);
|
||||||
}
|
}
|
||||||
ObjRelocKind::MipsGot16 => {
|
ObjRelocKind::MipsGot16 => {
|
||||||
write_text("%got(", color, job, font_id.clone());
|
write_text("%got(", color, job, font_id.clone());
|
||||||
write_reloc_name(reloc, color, job, font_id.clone());
|
write_reloc_name(reloc, color, job, font_id.clone(), config);
|
||||||
write_text(")", color, job, font_id);
|
write_text(")", color, job, font_id);
|
||||||
}
|
}
|
||||||
ObjRelocKind::MipsCall16 => {
|
ObjRelocKind::MipsCall16 => {
|
||||||
write_text("%call16(", color, job, font_id.clone());
|
write_text("%call16(", color, job, font_id.clone());
|
||||||
write_reloc_name(reloc, color, job, font_id.clone());
|
write_reloc_name(reloc, color, job, font_id.clone(), config);
|
||||||
write_text(")", color, job, font_id);
|
write_text(")", color, job, font_id);
|
||||||
}
|
}
|
||||||
ObjRelocKind::MipsGpRel16 => {
|
ObjRelocKind::MipsGpRel16 => {
|
||||||
write_text("%gp_rel(", color, job, font_id.clone());
|
write_text("%gp_rel(", color, job, font_id.clone());
|
||||||
write_reloc_name(reloc, color, job, font_id.clone());
|
write_reloc_name(reloc, color, job, font_id.clone(), config);
|
||||||
write_text(")", color, job, font_id);
|
write_text(")", color, job, font_id);
|
||||||
}
|
}
|
||||||
ObjRelocKind::PpcRel24 | ObjRelocKind::PpcRel14 | ObjRelocKind::Mips26 => {
|
ObjRelocKind::PpcRel24 | ObjRelocKind::PpcRel14 | ObjRelocKind::Mips26 => {
|
||||||
write_reloc_name(reloc, color, job, font_id);
|
write_reloc_name(reloc, color, job, font_id, config);
|
||||||
}
|
}
|
||||||
ObjRelocKind::Absolute | ObjRelocKind::MipsGpRel32 => {
|
ObjRelocKind::Absolute | ObjRelocKind::MipsGpRel32 => {
|
||||||
write_text("[INVALID]", color, job, font_id);
|
write_text("[INVALID]", color, job, font_id);
|
||||||
|
@ -93,16 +105,16 @@ fn write_ins(
|
||||||
) {
|
) {
|
||||||
let base_color = match diff_kind {
|
let base_color = match diff_kind {
|
||||||
ObjInsDiffKind::None | ObjInsDiffKind::OpMismatch | ObjInsDiffKind::ArgMismatch => {
|
ObjInsDiffKind::None | ObjInsDiffKind::OpMismatch | ObjInsDiffKind::ArgMismatch => {
|
||||||
Color32::GRAY
|
config.text_color
|
||||||
}
|
}
|
||||||
ObjInsDiffKind::Replace => Color32::LIGHT_BLUE,
|
ObjInsDiffKind::Replace => config.replace_color,
|
||||||
ObjInsDiffKind::Delete => COLOR_RED,
|
ObjInsDiffKind::Delete => config.delete_color,
|
||||||
ObjInsDiffKind::Insert => Color32::GREEN,
|
ObjInsDiffKind::Insert => config.insert_color,
|
||||||
};
|
};
|
||||||
write_text(
|
write_text(
|
||||||
&format!("{:<11}", ins.mnemonic),
|
&format!("{:<11}", ins.mnemonic),
|
||||||
match diff_kind {
|
match diff_kind {
|
||||||
ObjInsDiffKind::OpMismatch => Color32::LIGHT_BLUE,
|
ObjInsDiffKind::OpMismatch => config.replace_color,
|
||||||
_ => base_color,
|
_ => base_color,
|
||||||
},
|
},
|
||||||
job,
|
job,
|
||||||
|
@ -137,10 +149,22 @@ fn write_ins(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ObjInsArg::Reloc => {
|
ObjInsArg::Reloc => {
|
||||||
write_reloc(ins.reloc.as_ref().unwrap(), base_color, job, config.code_font.clone());
|
write_reloc(
|
||||||
|
ins.reloc.as_ref().unwrap(),
|
||||||
|
base_color,
|
||||||
|
job,
|
||||||
|
config.code_font.clone(),
|
||||||
|
config,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
ObjInsArg::RelocWithBase => {
|
ObjInsArg::RelocWithBase => {
|
||||||
write_reloc(ins.reloc.as_ref().unwrap(), base_color, job, config.code_font.clone());
|
write_reloc(
|
||||||
|
ins.reloc.as_ref().unwrap(),
|
||||||
|
base_color,
|
||||||
|
job,
|
||||||
|
config.code_font.clone(),
|
||||||
|
config,
|
||||||
|
);
|
||||||
write_text("(", base_color, job, config.code_font.clone());
|
write_text("(", base_color, job, config.code_font.clone());
|
||||||
writing_offset = true;
|
writing_offset = true;
|
||||||
continue;
|
continue;
|
||||||
|
@ -176,7 +200,7 @@ fn write_ins(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ins_hover_ui(ui: &mut egui::Ui, ins: &ObjIns) {
|
fn ins_hover_ui(ui: &mut egui::Ui, ins: &ObjIns, config: &ViewConfig) {
|
||||||
ui.scope(|ui| {
|
ui.scope(|ui| {
|
||||||
ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);
|
ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);
|
||||||
ui.style_mut().wrap = Some(false);
|
ui.style_mut().wrap = Some(false);
|
||||||
|
@ -202,13 +226,16 @@ fn ins_hover_ui(ui: &mut egui::Ui, ins: &ObjIns) {
|
||||||
|
|
||||||
if let Some(reloc) = &ins.reloc {
|
if let Some(reloc) = &ins.reloc {
|
||||||
ui.label(format!("Relocation type: {:?}", reloc.kind));
|
ui.label(format!("Relocation type: {:?}", reloc.kind));
|
||||||
ui.colored_label(Color32::WHITE, format!("Name: {}", reloc.target.name));
|
ui.colored_label(config.highlight_color, format!("Name: {}", reloc.target.name));
|
||||||
if let Some(section) = &reloc.target_section {
|
if let Some(section) = &reloc.target_section {
|
||||||
ui.colored_label(Color32::WHITE, format!("Section: {section}"));
|
ui.colored_label(config.highlight_color, format!("Section: {section}"));
|
||||||
ui.colored_label(Color32::WHITE, format!("Address: {:x}", reloc.target.address));
|
ui.colored_label(
|
||||||
ui.colored_label(Color32::WHITE, format!("Size: {:x}", reloc.target.size));
|
config.highlight_color,
|
||||||
|
format!("Address: {:x}", reloc.target.address),
|
||||||
|
);
|
||||||
|
ui.colored_label(config.highlight_color, format!("Size: {:x}", reloc.target.size));
|
||||||
} else {
|
} else {
|
||||||
ui.colored_label(Color32::WHITE, "Extern".to_string());
|
ui.colored_label(config.highlight_color, "Extern".to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -291,16 +318,16 @@ fn asm_row_ui(ui: &mut egui::Ui, ins_diff: &ObjInsDiff, symbol: &ObjSymbol, conf
|
||||||
|
|
||||||
let base_color = match ins_diff.kind {
|
let base_color = match ins_diff.kind {
|
||||||
ObjInsDiffKind::None | ObjInsDiffKind::OpMismatch | ObjInsDiffKind::ArgMismatch => {
|
ObjInsDiffKind::None | ObjInsDiffKind::OpMismatch | ObjInsDiffKind::ArgMismatch => {
|
||||||
Color32::GRAY
|
config.text_color
|
||||||
}
|
}
|
||||||
ObjInsDiffKind::Replace => Color32::LIGHT_BLUE,
|
ObjInsDiffKind::Replace => config.replace_color,
|
||||||
ObjInsDiffKind::Delete => COLOR_RED,
|
ObjInsDiffKind::Delete => config.delete_color,
|
||||||
ObjInsDiffKind::Insert => Color32::GREEN,
|
ObjInsDiffKind::Insert => config.insert_color,
|
||||||
};
|
};
|
||||||
let mut pad = 6;
|
let mut pad = 6;
|
||||||
if let Some(line) = ins.line {
|
if let Some(line) = ins.line {
|
||||||
let line_str = format!("{line} ");
|
let line_str = format!("{line} ");
|
||||||
write_text(&line_str, Color32::DARK_GRAY, &mut job, config.code_font.clone());
|
write_text(&line_str, config.deemphasized_text_color, &mut job, config.code_font.clone());
|
||||||
pad = 12 - line_str.len();
|
pad = 12 - line_str.len();
|
||||||
}
|
}
|
||||||
write_text(
|
write_text(
|
||||||
|
@ -329,7 +356,7 @@ fn asm_row_ui(ui: &mut egui::Ui, ins_diff: &ObjInsDiff, symbol: &ObjSymbol, conf
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ui.add(Label::new(job).sense(Sense::click()))
|
ui.add(Label::new(job).sense(Sense::click()))
|
||||||
.on_hover_ui_at_pointer(|ui| ins_hover_ui(ui, ins))
|
.on_hover_ui_at_pointer(|ui| ins_hover_ui(ui, ins, config))
|
||||||
.context_menu(|ui| ins_context_menu(ui, ins));
|
.context_menu(|ui| ins_context_menu(ui, ins));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,7 +389,8 @@ fn asm_table_ui(
|
||||||
|
|
||||||
pub fn function_diff_ui(ui: &mut egui::Ui, view_state: &mut ViewState) -> bool {
|
pub fn function_diff_ui(ui: &mut egui::Ui, view_state: &mut ViewState) -> bool {
|
||||||
let mut rebuild = false;
|
let mut rebuild = false;
|
||||||
let (Some(result), Some(selected_symbol)) = (&view_state.build, &view_state.selected_symbol) else {
|
let (Some(result), Some(selected_symbol)) = (&view_state.build, &view_state.selected_symbol)
|
||||||
|
else {
|
||||||
return rebuild;
|
return rebuild;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -389,7 +417,7 @@ pub fn function_diff_ui(ui: &mut egui::Ui, view_state: &mut ViewState) -> bool {
|
||||||
let mut job = LayoutJob::simple(
|
let mut job = LayoutJob::simple(
|
||||||
name.to_string(),
|
name.to_string(),
|
||||||
view_state.view_config.code_font.clone(),
|
view_state.view_config.code_font.clone(),
|
||||||
Color32::WHITE,
|
view_state.view_config.highlight_color,
|
||||||
column_width,
|
column_width,
|
||||||
);
|
);
|
||||||
job.wrap.break_anywhere = true;
|
job.wrap.break_anywhere = true;
|
||||||
|
@ -443,7 +471,7 @@ pub fn function_diff_ui(ui: &mut egui::Ui, view_state: &mut ViewState) -> bool {
|
||||||
.and_then(|symbol| symbol.match_percent)
|
.and_then(|symbol| symbol.match_percent)
|
||||||
{
|
{
|
||||||
ui.colored_label(
|
ui.colored_label(
|
||||||
match_color_for_symbol(match_percent),
|
match_color_for_symbol(match_percent, &view_state.view_config),
|
||||||
&format!("{match_percent:.0}%"),
|
&format!("{match_percent:.0}%"),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use egui::{Color32, ProgressBar, Widget};
|
use egui::{ProgressBar, Widget};
|
||||||
|
|
||||||
use crate::app::ViewState;
|
use crate::app::ViewState;
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ pub fn jobs_ui(ui: &mut egui::Ui, view_state: &mut ViewState) {
|
||||||
if let Some(err) = &status.error {
|
if let Some(err) = &status.error {
|
||||||
let err_string = err.to_string();
|
let err_string = err.to_string();
|
||||||
ui.colored_label(
|
ui.colored_label(
|
||||||
Color32::from_rgb(255, 0, 0),
|
view_state.view_config.delete_color,
|
||||||
if err_string.len() > STATUS_LENGTH - 10 {
|
if err_string.len() > STATUS_LENGTH - 10 {
|
||||||
format!("Error: {}...", &err_string[0..STATUS_LENGTH - 10])
|
format!("Error: {}...", &err_string[0..STATUS_LENGTH - 10])
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -6,8 +6,6 @@ pub(crate) mod function_diff;
|
||||||
pub(crate) mod jobs;
|
pub(crate) mod jobs;
|
||||||
pub(crate) mod symbol_diff;
|
pub(crate) mod symbol_diff;
|
||||||
|
|
||||||
const COLOR_RED: Color32 = Color32::from_rgb(200, 40, 41);
|
|
||||||
|
|
||||||
fn write_text(str: &str, color: Color32, job: &mut LayoutJob, font_id: FontId) {
|
fn write_text(str: &str, color: Color32, job: &mut LayoutJob, font_id: FontId) {
|
||||||
job.append(str, 0.0, TextFormat::simple(font_id, color));
|
job.append(str, 0.0, TextFormat::simple(font_id, color));
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,13 @@ use crate::{
|
||||||
views::write_text,
|
views::write_text,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn match_color_for_symbol(match_percent: f32) -> Color32 {
|
pub fn match_color_for_symbol(match_percent: f32, config: &ViewConfig) -> Color32 {
|
||||||
if match_percent == 100.0 {
|
if match_percent == 100.0 {
|
||||||
Color32::GREEN
|
config.insert_color
|
||||||
} else if match_percent >= 50.0 {
|
} else if match_percent >= 50.0 {
|
||||||
Color32::LIGHT_BLUE
|
config.replace_color
|
||||||
} else {
|
} else {
|
||||||
Color32::RED
|
config.delete_color
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,17 +39,17 @@ fn symbol_context_menu_ui(ui: &mut Ui, symbol: &ObjSymbol) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn symbol_hover_ui(ui: &mut Ui, symbol: &ObjSymbol) {
|
fn symbol_hover_ui(ui: &mut Ui, symbol: &ObjSymbol, config: &ViewConfig) {
|
||||||
ui.scope(|ui| {
|
ui.scope(|ui| {
|
||||||
ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);
|
ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);
|
||||||
ui.style_mut().wrap = Some(false);
|
ui.style_mut().wrap = Some(false);
|
||||||
|
|
||||||
ui.colored_label(Color32::WHITE, format!("Name: {}", symbol.name));
|
ui.colored_label(config.highlight_color, format!("Name: {}", symbol.name));
|
||||||
ui.colored_label(Color32::WHITE, format!("Address: {:x}", symbol.address));
|
ui.colored_label(config.highlight_color, format!("Address: {:x}", symbol.address));
|
||||||
if symbol.size_known {
|
if symbol.size_known {
|
||||||
ui.colored_label(Color32::WHITE, format!("Size: {:x}", symbol.size));
|
ui.colored_label(config.highlight_color, format!("Size: {:x}", symbol.size));
|
||||||
} else {
|
} else {
|
||||||
ui.colored_label(Color32::WHITE, format!("Size: {:x} (assumed)", symbol.size));
|
ui.colored_label(config.highlight_color, format!("Size: {:x} (assumed)", symbol.size));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -70,33 +70,38 @@ fn symbol_ui(
|
||||||
if let Some(sym) = highlighted_symbol {
|
if let Some(sym) = highlighted_symbol {
|
||||||
selected = sym == &symbol.name;
|
selected = sym == &symbol.name;
|
||||||
}
|
}
|
||||||
write_text("[", Color32::GRAY, &mut job, config.code_font.clone());
|
write_text("[", config.text_color, &mut job, config.code_font.clone());
|
||||||
if symbol.flags.0.contains(ObjSymbolFlags::Common) {
|
if symbol.flags.0.contains(ObjSymbolFlags::Common) {
|
||||||
write_text("c", Color32::from_rgb(0, 255, 255), &mut job, config.code_font.clone());
|
|
||||||
} else if symbol.flags.0.contains(ObjSymbolFlags::Global) {
|
|
||||||
write_text("g", Color32::GREEN, &mut job, config.code_font.clone());
|
|
||||||
} else if symbol.flags.0.contains(ObjSymbolFlags::Local) {
|
|
||||||
write_text("l", Color32::GRAY, &mut job, config.code_font.clone());
|
|
||||||
}
|
|
||||||
if symbol.flags.0.contains(ObjSymbolFlags::Weak) {
|
|
||||||
write_text("w", Color32::GRAY, &mut job, config.code_font.clone());
|
|
||||||
}
|
|
||||||
write_text("] ", Color32::GRAY, &mut job, config.code_font.clone());
|
|
||||||
if let Some(match_percent) = symbol.match_percent {
|
|
||||||
write_text("(", Color32::GRAY, &mut job, config.code_font.clone());
|
|
||||||
write_text(
|
write_text(
|
||||||
&format!("{match_percent:.0}%"),
|
"c",
|
||||||
match_color_for_symbol(match_percent),
|
config.replace_color, /* Color32::from_rgb(0, 255, 255) */
|
||||||
&mut job,
|
&mut job,
|
||||||
config.code_font.clone(),
|
config.code_font.clone(),
|
||||||
);
|
);
|
||||||
write_text(") ", Color32::GRAY, &mut job, config.code_font.clone());
|
} else if symbol.flags.0.contains(ObjSymbolFlags::Global) {
|
||||||
|
write_text("g", config.insert_color, &mut job, config.code_font.clone());
|
||||||
|
} else if symbol.flags.0.contains(ObjSymbolFlags::Local) {
|
||||||
|
write_text("l", config.text_color, &mut job, config.code_font.clone());
|
||||||
}
|
}
|
||||||
write_text(name, Color32::WHITE, &mut job, config.code_font.clone());
|
if symbol.flags.0.contains(ObjSymbolFlags::Weak) {
|
||||||
|
write_text("w", config.text_color, &mut job, config.code_font.clone());
|
||||||
|
}
|
||||||
|
write_text("] ", config.text_color, &mut job, config.code_font.clone());
|
||||||
|
if let Some(match_percent) = symbol.match_percent {
|
||||||
|
write_text("(", config.text_color, &mut job, config.code_font.clone());
|
||||||
|
write_text(
|
||||||
|
&format!("{match_percent:.0}%"),
|
||||||
|
match_color_for_symbol(match_percent, config),
|
||||||
|
&mut job,
|
||||||
|
config.code_font.clone(),
|
||||||
|
);
|
||||||
|
write_text(") ", config.text_color, &mut job, config.code_font.clone());
|
||||||
|
}
|
||||||
|
write_text(name, config.highlight_color, &mut job, config.code_font.clone());
|
||||||
let response = SelectableLabel::new(selected, job)
|
let response = SelectableLabel::new(selected, job)
|
||||||
.ui(ui)
|
.ui(ui)
|
||||||
.context_menu(|ui| symbol_context_menu_ui(ui, symbol))
|
.context_menu(|ui| symbol_context_menu_ui(ui, symbol))
|
||||||
.on_hover_ui_at_pointer(|ui| symbol_hover_ui(ui, symbol));
|
.on_hover_ui_at_pointer(|ui| symbol_hover_ui(ui, symbol, config));
|
||||||
if response.clicked() {
|
if response.clicked() {
|
||||||
if let Some(section) = section {
|
if let Some(section) = section {
|
||||||
if section.kind == ObjSectionKind::Code {
|
if section.kind == ObjSectionKind::Code {
|
||||||
|
@ -200,13 +205,13 @@ fn symbol_list_ui(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_log_ui(ui: &mut Ui, status: &BuildStatus) {
|
fn build_log_ui(ui: &mut Ui, status: &BuildStatus, config: &ViewConfig) {
|
||||||
ScrollArea::both().auto_shrink([false, false]).show(ui, |ui| {
|
ScrollArea::both().auto_shrink([false, false]).show(ui, |ui| {
|
||||||
ui.scope(|ui| {
|
ui.scope(|ui| {
|
||||||
ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);
|
ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace);
|
||||||
ui.style_mut().wrap = Some(false);
|
ui.style_mut().wrap = Some(false);
|
||||||
|
|
||||||
ui.colored_label(Color32::from_rgb(255, 0, 0), &status.log);
|
ui.colored_label(config.replace_color, &status.log);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -296,7 +301,7 @@ pub fn symbol_diff_ui(ui: &mut Ui, view_state: &mut ViewState) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
build_log_ui(ui, &result.first_status);
|
build_log_ui(ui, &result.first_status, &view_state.view_config);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -315,7 +320,7 @@ pub fn symbol_diff_ui(ui: &mut Ui, view_state: &mut ViewState) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
build_log_ui(ui, &result.second_status);
|
build_log_ui(ui, &result.second_status, &view_state.view_config);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue