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]]
name = "objdiff"
version = "0.3.3"
version = "0.3.4"
dependencies = [
"anyhow",
"byteorder",

View File

@ -1,6 +1,6 @@
[package]
name = "objdiff"
version = "0.3.3"
version = "0.3.4"
edition = "2021"
rust-version = "1.65"
authors = ["Luke Street <luke@street.dev>"]

View File

@ -68,6 +68,21 @@ pub struct ViewConfig {
pub code_font: FontId,
pub diff_colors: Vec<Color32>,
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]");
});
}
});

View File

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

View File

@ -37,7 +37,8 @@ fn main() {
let exec_path: Rc<Mutex<Option<PathBuf>>> = 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);

View File

@ -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<RwLock<AppConfig>>, 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

View File

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

View File

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

View File

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

View File

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

View File

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