diff --git a/Cargo.lock b/Cargo.lock index 3df4902..f2f83d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2412,7 +2412,7 @@ dependencies = [ [[package]] name = "objdiff" -version = "0.3.3" +version = "0.3.4" dependencies = [ "anyhow", "byteorder", diff --git a/Cargo.toml b/Cargo.toml index fbeba4f..610ee15 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "objdiff" -version = "0.3.3" +version = "0.3.4" edition = "2021" rust-version = "1.65" authors = ["Luke Street "] diff --git a/src/app.rs b/src/app.rs index 148d2b9..700f307 100644 --- a/src/app.rs +++ b/src/app.rs @@ -68,6 +68,21 @@ pub struct ViewConfig { pub code_font: FontId, pub diff_colors: Vec, 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 { @@ -77,6 +92,14 @@ impl Default for ViewConfig { code_font: FontId { size: 14.0, family: FontFamily::Monospace }, diff_colors: DEFAULT_COLOR_ROTATION.to_vec(), 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 config = &view_state.view_config; + let config = &mut view_state.view_config; let mut style = (*ctx.style()).clone(); style.text_styles.insert(TextStyle::Body, FontId { size: (config.ui_font.size * 0.75).floor(), @@ -262,6 +285,28 @@ impl eframe::App for App { family: config.ui_font.family.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); } @@ -323,6 +368,20 @@ impl eframe::App for App { } 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:"); egui::introspection::font_id_ui(ui, &mut view_state.view_config.ui_font); ui.separator(); @@ -359,7 +418,7 @@ impl eframe::App for App { { ui.scope(|ui| { 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() { ui.output_mut(|output| output.copied_text = demangled); @@ -367,7 +426,7 @@ impl eframe::App for App { } else { ui.scope(|ui| { 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]"); }); } }); diff --git a/src/diff.rs b/src/diff.rs index f62d2a7..1a79a57 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -406,7 +406,9 @@ pub fn diff_objs(left: &mut ObjInfo, right: &mut ObjInfo, _diff_config: &DiffCon } } } 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; }; if left_section.kind == ObjSectionKind::Data { diff --git a/src/main.rs b/src/main.rs index 4149c83..fd174a8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,7 +37,8 @@ fn main() { let exec_path: Rc>> = Rc::new(Mutex::new(None)); 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() { Ok(data) => { native_options.icon_data = Some(data); diff --git a/src/views/config.rs b/src/views/config.rs index a736686..8995da1 100644 --- a/src/views/config.rs +++ b/src/views/config.rs @@ -5,7 +5,7 @@ use std::sync::{Arc, RwLock}; #[cfg(windows)] use anyhow::{Context, Result}; use const_format::formatcp; -use egui::{output::OpenUrl, Color32}; +use egui::output::OpenUrl; use self_update::cargo_crate_version; use crate::{ @@ -79,7 +79,7 @@ pub fn config_ui(ui: &mut egui::Ui, config: &Arc>, view_state: if let Some(state) = &view_state.check_update { ui.label(format!("Latest version: {}", state.latest_release.version)); 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| { if state.found_binary && ui diff --git a/src/views/data_diff.rs b/src/views/data_diff.rs index 28a79df..301dbbf 100644 --- a/src/views/data_diff.rs +++ b/src/views/data_diff.rs @@ -1,6 +1,6 @@ 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 time::format_description; @@ -8,7 +8,7 @@ use crate::{ app::{SymbolReference, View, ViewConfig, ViewState}, jobs::Job, obj::{ObjDataDiff, ObjDataDiffKind, ObjInfo, ObjSection}, - views::{write_text, COLOR_RED}, + views::write_text, }; 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(); write_text( format!("{address:08X}: ").as_str(), - Color32::GRAY, + config.text_color, &mut job, config.code_font.clone(), ); let mut cur_addr = 0usize; for diff in diffs { let base_color = match diff.kind { - ObjDataDiffKind::None => Color32::GRAY, - ObjDataDiffKind::Replace => Color32::LIGHT_BLUE, - ObjDataDiffKind::Delete => COLOR_RED, - ObjDataDiffKind::Insert => Color32::GREEN, + ObjDataDiffKind::None => config.text_color, + ObjDataDiffKind::Replace => config.replace_color, + ObjDataDiffKind::Delete => config.delete_color, + ObjDataDiffKind::Insert => config.insert_color, }; if diff.data.is_empty() { 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(); str.push_str(" ".repeat(n).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 { let base_color = match diff.kind { - ObjDataDiffKind::None => Color32::GRAY, - ObjDataDiffKind::Replace => Color32::LIGHT_BLUE, - ObjDataDiffKind::Delete => COLOR_RED, - ObjDataDiffKind::Insert => Color32::GREEN, + ObjDataDiffKind::None => config.text_color, + ObjDataDiffKind::Replace => config.replace_color, + ObjDataDiffKind::Delete => config.delete_color, + ObjDataDiffKind::Insert => config.insert_color, }; if diff.data.is_empty() { write_text( @@ -163,7 +163,8 @@ fn data_table_ui( pub fn data_diff_ui(ui: &mut egui::Ui, view_state: &mut ViewState) -> bool { 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; }; @@ -188,7 +189,10 @@ pub fn data_diff_ui(ui: &mut egui::Ui, view_state: &mut ViewState) -> bool { ui.scope(|ui| { ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace); 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:"); }); }, diff --git a/src/views/function_diff.rs b/src/views/function_diff.rs index 30ff537..f109621 100644 --- a/src/views/function_diff.rs +++ b/src/views/function_diff.rs @@ -14,12 +14,18 @@ use crate::{ ObjInfo, ObjIns, ObjInsArg, ObjInsArgDiff, ObjInsDiff, ObjInsDiffKind, ObjReloc, 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); - 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) { Ordering::Greater => { 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 { 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); } 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); } 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); } 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); } ObjRelocKind::MipsHi16 => { 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); } ObjRelocKind::MipsLo16 => { 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); } ObjRelocKind::MipsGot16 => { 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); } ObjRelocKind::MipsCall16 => { 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); } ObjRelocKind::MipsGpRel16 => { 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); } 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 => { write_text("[INVALID]", color, job, font_id); @@ -93,16 +105,16 @@ fn write_ins( ) { let base_color = match diff_kind { ObjInsDiffKind::None | ObjInsDiffKind::OpMismatch | ObjInsDiffKind::ArgMismatch => { - Color32::GRAY + config.text_color } - ObjInsDiffKind::Replace => Color32::LIGHT_BLUE, - ObjInsDiffKind::Delete => COLOR_RED, - ObjInsDiffKind::Insert => Color32::GREEN, + ObjInsDiffKind::Replace => config.replace_color, + ObjInsDiffKind::Delete => config.delete_color, + ObjInsDiffKind::Insert => config.insert_color, }; write_text( &format!("{:<11}", ins.mnemonic), match diff_kind { - ObjInsDiffKind::OpMismatch => Color32::LIGHT_BLUE, + ObjInsDiffKind::OpMismatch => config.replace_color, _ => base_color, }, job, @@ -137,10 +149,22 @@ fn write_ins( } }, 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 => { - 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()); writing_offset = true; 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.style_mut().override_text_style = Some(egui::TextStyle::Monospace); 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 { 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 { - ui.colored_label(Color32::WHITE, format!("Section: {section}")); - ui.colored_label(Color32::WHITE, format!("Address: {:x}", reloc.target.address)); - ui.colored_label(Color32::WHITE, format!("Size: {:x}", reloc.target.size)); + ui.colored_label(config.highlight_color, format!("Section: {section}")); + ui.colored_label( + config.highlight_color, + format!("Address: {:x}", reloc.target.address), + ); + ui.colored_label(config.highlight_color, format!("Size: {:x}", reloc.target.size)); } 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 { ObjInsDiffKind::None | ObjInsDiffKind::OpMismatch | ObjInsDiffKind::ArgMismatch => { - Color32::GRAY + config.text_color } - ObjInsDiffKind::Replace => Color32::LIGHT_BLUE, - ObjInsDiffKind::Delete => COLOR_RED, - ObjInsDiffKind::Insert => Color32::GREEN, + ObjInsDiffKind::Replace => config.replace_color, + ObjInsDiffKind::Delete => config.delete_color, + ObjInsDiffKind::Insert => config.insert_color, }; let mut pad = 6; if let Some(line) = ins.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(); } 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())) - .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)); } @@ -362,7 +389,8 @@ fn asm_table_ui( pub fn function_diff_ui(ui: &mut egui::Ui, view_state: &mut ViewState) -> bool { 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; }; @@ -389,7 +417,7 @@ pub fn function_diff_ui(ui: &mut egui::Ui, view_state: &mut ViewState) -> bool { let mut job = LayoutJob::simple( name.to_string(), view_state.view_config.code_font.clone(), - Color32::WHITE, + view_state.view_config.highlight_color, column_width, ); 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) { ui.colored_label( - match_color_for_symbol(match_percent), + match_color_for_symbol(match_percent, &view_state.view_config), &format!("{match_percent:.0}%"), ); } else { diff --git a/src/views/jobs.rs b/src/views/jobs.rs index 8b67ffa..0e6df3e 100644 --- a/src/views/jobs.rs +++ b/src/views/jobs.rs @@ -1,4 +1,4 @@ -use egui::{Color32, ProgressBar, Widget}; +use egui::{ProgressBar, Widget}; 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 { let err_string = err.to_string(); ui.colored_label( - Color32::from_rgb(255, 0, 0), + view_state.view_config.delete_color, if err_string.len() > STATUS_LENGTH - 10 { format!("Error: {}...", &err_string[0..STATUS_LENGTH - 10]) } else { diff --git a/src/views/mod.rs b/src/views/mod.rs index 5585185..fb84ac5 100644 --- a/src/views/mod.rs +++ b/src/views/mod.rs @@ -6,8 +6,6 @@ pub(crate) mod function_diff; pub(crate) mod jobs; 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) { job.append(str, 0.0, TextFormat::simple(font_id, color)); } diff --git a/src/views/symbol_diff.rs b/src/views/symbol_diff.rs index 0b7b9e9..8eb7848 100644 --- a/src/views/symbol_diff.rs +++ b/src/views/symbol_diff.rs @@ -11,13 +11,13 @@ use crate::{ 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 { - Color32::GREEN + config.insert_color } else if match_percent >= 50.0 { - Color32::LIGHT_BLUE + config.replace_color } 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.style_mut().override_text_style = Some(egui::TextStyle::Monospace); ui.style_mut().wrap = Some(false); - ui.colored_label(Color32::WHITE, format!("Name: {}", symbol.name)); - ui.colored_label(Color32::WHITE, format!("Address: {:x}", symbol.address)); + ui.colored_label(config.highlight_color, format!("Name: {}", symbol.name)); + ui.colored_label(config.highlight_color, format!("Address: {:x}", symbol.address)); 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 { - 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 { 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) { - 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( - &format!("{match_percent:.0}%"), - match_color_for_symbol(match_percent), + "c", + config.replace_color, /* Color32::from_rgb(0, 255, 255) */ &mut job, 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) .ui(ui) .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 let Some(section) = section { 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| { ui.scope(|ui| { ui.style_mut().override_text_style = Some(egui::TextStyle::Monospace); 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 { - 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 { - build_log_ui(ui, &result.second_status); + build_log_ui(ui, &result.second_status, &view_state.view_config); } }); });