use std::sync::Arc;
use eframe::egui::{self, Color32, FontFamily, FontId, Pos2, Rect, Vec2};
#[derive(Clone, Copy, Debug)]
pub struct View {
pub origin: Pos2,
pub zoom: f32,
}
impl View {
pub fn rect(&self, r: &[f64; 4]) -> Rect {
Rect::from_min_size(
self.origin + Vec2::new(r[0] as f32, r[1] as f32) * self.zoom,
Vec2::new(r[2] as f32, r[3] as f32) * self.zoom,
)
}
pub fn pos(&self, x: f64, y: f64) -> Pos2 {
self.origin + Vec2::new(x as f32, y as f32) * self.zoom
}
}
pub fn color(c: &bob::Color) -> Color32 {
Color32::from_rgba_unmultiplied(c.r, c.g, c.b, c.a)
}
pub fn named(name: &str) -> Color32 {
color(&bob::named_color(name))
}
pub fn severity_color(sev: pv::Severity) -> Option<Color32> {
match sev {
pv::Severity::NoAlarm => None,
pv::Severity::Minor => Some(named("MINOR")),
pv::Severity::Major => Some(named("MAJOR")),
pv::Severity::Invalid => Some(named("INVALID")),
}
}
pub const BOLD: &str = "bold";
pub const ITALIC: &str = "italic";
pub const BOLD_ITALIC: &str = "bold-italic";
pub fn font_id(font: &bob::Font, zoom: f32) -> FontId {
let family = if font.is_bold() && font.is_italic() {
FontFamily::Name(BOLD_ITALIC.into())
} else if font.is_bold() {
FontFamily::Name(BOLD.into())
} else if font.is_italic() {
FontFamily::Name(ITALIC.into())
} else if font.family.to_lowercase().contains("mono") {
FontFamily::Monospace
} else {
FontFamily::Proportional
};
FontId::new((font.size * zoom * 0.95).max(4.0), family)
}
pub fn install_fonts(ctx: &egui::Context) {
let mut fonts = egui::FontDefinitions::default();
let mut add = |key: &str, data: &'static [u8]| {
fonts
.font_data
.insert(key.into(), Arc::new(egui::FontData::from_static(data)));
key.to_string()
};
let regular = add(
"liberation",
include_bytes!("../fonts/LiberationSans-Regular.ttf"),
);
let bold = add(
"liberation-bold",
include_bytes!("../fonts/LiberationSans-Bold.ttf"),
);
let italic = add(
"liberation-italic",
include_bytes!("../fonts/LiberationSans-Italic.ttf"),
);
let bold_italic = add(
"liberation-bold-italic",
include_bytes!("../fonts/LiberationSans-BoldItalic.ttf"),
);
let symbols = add(
"noto-math-symbols",
include_bytes!("../fonts/NotoSansMath-Symbols.ttf"),
);
let mut fallback = fonts.families[&FontFamily::Proportional].clone();
fallback.push(symbols.clone());
fonts
.families
.entry(FontFamily::Monospace)
.or_default()
.push(symbols);
let with = |first: String| {
std::iter::once(first)
.chain(fallback.iter().cloned())
.collect::<Vec<_>>()
};
fonts
.families
.insert(FontFamily::Name(BOLD.into()), with(bold));
fonts
.families
.insert(FontFamily::Name(ITALIC.into()), with(italic));
fonts
.families
.insert(FontFamily::Name(BOLD_ITALIC.into()), with(bold_italic));
fonts
.families
.insert(FontFamily::Proportional, with(regular));
ctx.set_fonts(fonts);
}
pub fn align(h: i64, v: i64) -> egui::Align2 {
let a = |n| match n {
1 => egui::Align::Center,
2 => egui::Align::Max,
_ => egui::Align::Min,
};
egui::Align2([a(h), a(v)])
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn each_style_has_its_own_face() {
let family = |style| {
let font = bob::Font {
style,
..Default::default()
};
font_id(&font, 1.0).family
};
use bob::FontStyle as S;
assert_eq!(family(S::Regular), FontFamily::Proportional);
assert_eq!(family(S::Bold), FontFamily::Name(BOLD.into()));
assert_eq!(family(S::Italic), FontFamily::Name(ITALIC.into()));
assert_eq!(family(S::BoldItalic), FontFamily::Name(BOLD_ITALIC.into()));
}
}