use crate::automation::hit_keys::HitKeyDoc;
use crate::diagnostics::Diagnostics;
use eframe::egui;
use std::collections::HashMap;
const PROJECT_LICENCE: &str = include_str!("../../LICENSE.md");
const THIRD_PARTY_NOTICES: &str = include_str!("../../THIRD-PARTY-NOTICES.md");
const INVENTORY_URL: &str = "help/licences/third-party-crates.html";
#[derive(Default)]
pub struct InfoPanel {
pub open: bool,
hits: HashMap<String, egui::Rect>,
}
impl InfoPanel {
pub fn new() -> Self {
Self::default()
}
pub fn show(&mut self, ctx: &egui::Context, diagnostics: &Diagnostics) {
if !self.open {
return;
}
let mut open = true;
egui::Window::new("Info")
.open(&mut open)
.movable(true)
.resizable(true)
.default_size([560.0, 520.0])
.default_pos([120.0, 120.0])
.show(ctx, |ui| self.body(ui, diagnostics));
self.open = open;
if crate::automation::registry::enabled() {
crate::automation::registry::publish(
"__brepInfoHit",
"info window widget rects (copy, inventory, licence:*)",
&self.hits_json(),
);
}
}
fn body(&mut self, ui: &mut egui::Ui, diagnostics: &Diagnostics) {
self.hits.clear();
egui::ScrollArea::vertical()
.auto_shrink([false; 2])
.show(ui, |ui| {
self.diagnostics_section(ui, diagnostics);
ui.add_space(12.0);
ui.separator();
ui.add_space(6.0);
self.licences_section(ui);
});
}
fn diagnostics_section(&mut self, ui: &mut egui::Ui, diagnostics: &Diagnostics) {
ui.heading("Diagnostics");
ui.label(
egui::RichText::new("Sent with every problem report from the Submit Bug button.")
.weak()
.small(),
);
ui.add_space(4.0);
egui::Grid::new("brep-info-diagnostics")
.num_columns(2)
.spacing([12.0, 4.0])
.striped(true)
.show(ui, |ui| {
for (label, value) in diagnostics.rows() {
ui.label(egui::RichText::new(label).strong());
ui.label(egui::RichText::new(value).monospace());
ui.end_row();
}
});
ui.add_space(6.0);
let copy = ui.button("Copy diagnostics");
self.hit("copy", ©);
if copy.clicked() {
ui.ctx().copy_text(diagnostics.report_text());
}
}
fn licences_section(&mut self, ui: &mut egui::Ui) {
ui.heading("Licences");
ui.add_space(4.0);
let project = egui::CollapsingHeader::new("Project licence (LICENSE.md)")
.id_salt("brep-info-licence-project")
.show(ui, |ui| licence_text(ui, PROJECT_LICENCE));
self.hit("licence:project", &project.header_response);
let notices = egui::CollapsingHeader::new("Third-party notices (THIRD-PARTY-NOTICES.md)")
.id_salt("brep-info-licence-notices")
.show(ui, |ui| licence_text(ui, THIRD_PARTY_NOTICES));
self.hit("licence:notices", ¬ices.header_response);
ui.add_space(6.0);
ui.label(
egui::RichText::new(
"Every crate this application ships, grouped by its licence, is generated \
into the help site from the dependency graph itself:",
)
.weak()
.small(),
);
let inventory = ui.button("Open the third-party crate inventory");
self.hit("inventory", &inventory);
if inventory.clicked() {
ui.ctx().open_url(egui::OpenUrl::new_tab(INVENTORY_URL));
}
}
fn hit(&mut self, key: &str, resp: &egui::Response) {
self.hits.insert(key.to_string(), resp.rect);
}
pub fn hits_json(&self) -> String {
let map: serde_json::Map<String, serde_json::Value> = self
.hits
.iter()
.map(|(k, r)| {
(
k.clone(),
serde_json::json!([r.center().x, r.center().y, r.width(), r.height()]),
)
})
.collect();
serde_json::Value::Object(map).to_string()
}
}
fn licence_text(ui: &mut egui::Ui, text: &str) {
ui.add(egui::Label::new(egui::RichText::new(text).monospace().small()).wrap());
}
pub static HIT_KEYS: &[HitKeyDoc] = &[
HitKeyDoc { panel: "info", prefix: "copy", meaning: "copy the diagnostics block to the clipboard (the same rows `diagnostics` returns)", command: None },
HitKeyDoc { panel: "info", prefix: "inventory", meaning: "open the generated third-party crate inventory on the help site", command: None },
HitKeyDoc { panel: "info", prefix: "licence:", meaning: "expand a licence text (licence:project, licence:notices)", command: None },
];