Add dark/light theme toggle (light theme WIP)

This commit is contained in:
Luke Street 2023-07-15 11:17:59 -04:00
parent c7a326b160
commit b02e32f2b7
11 changed files with 192 additions and 95 deletions

2
Cargo.lock generated
View File

@ -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",

View File

@ -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>"]

View File

@ -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]");
}); });
} }
}); });

View File

@ -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 {

View File

@ -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);

View File

@ -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

View File

@ -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:");
}); });
}, },

View File

@ -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 {

View File

@ -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 {

View File

@ -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));
} }

View File

@ -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);
} }
}); });
}); });