use crate::{
pipeline::{
extract_output::OutputConfig, group::Group, preview_indices::PreviewIndices,
render_to_output::positions::Positions,
},
svg::{measurement_point::MeasurementPoints, universe_color_channels::UniverseColorChannels},
ui::action::UiAction,
};
use anyhow::Result;
use egui::{Context, TextureHandle, mutex::Mutex};
use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize};
use std::{collections::BTreeSet, path::Path, sync::Arc};
static MEASUREMENT_POINTS: Lazy<Mutex<Arc<MeasurementPoints>>> =
Lazy::new(|| Mutex::new(Arc::new(MeasurementPoints::new())));
#[derive(Serialize, Deserialize, PartialEq)]
pub struct Svg {
svg_contents: Arc<str>,
#[serde(skip)]
image: Option<TextureHandle>,
}
impl std::fmt::Debug for Svg {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Svg")
.field("svg_contents", &self.svg_contents)
.finish()
}
}
impl Clone for Svg {
fn clone(&self) -> Self {
Self {
svg_contents: self.svg_contents.clone(),
image: None,
}
}
}
impl Svg {
pub fn load(path: &Path) -> Result<Self> {
let svg_contents = std::fs::read_to_string(path)?;
Ok(Self {
svg_contents: svg_contents.into(),
image: None,
})
}
pub fn save(&self, path: &Path) -> Result<()> {
std::fs::write(path, self.svg_contents.as_bytes())?;
Ok(())
}
pub fn image(
&mut self,
context: &Context,
output_config: &mut OutputConfig,
) -> Option<TextureHandle> {
if self.image.is_none() {
self.image = {
let svg = crate::svg::ParsedSvg::parse(&self.svg_contents).ok()?;
let measurement_points = MeasurementPoints::from(&svg);
UniverseColorChannels::from(&svg).set();
let universes = measurement_points.universes();
*MEASUREMENT_POINTS.lock() = Arc::new(measurement_points);
let image = svg.render().ok()?;
PreviewIndices::get().send_positions();
output_config.universes = Arc::new(universes);
UiAction::SendPositions.enqueue();
let texture_handle =
context.load_texture("svg_preview", image, egui::TextureOptions::default());
Some(texture_handle)
};
}
self.image.clone()
}
pub fn reset() {
*MEASUREMENT_POINTS.lock() = Arc::new(MeasurementPoints::new());
}
fn measurement_points() -> Arc<MeasurementPoints> {
MEASUREMENT_POINTS.lock().clone()
}
pub fn groups() -> Vec<Group> {
Self::measurement_points().groups()
}
pub fn positions(group: &Group) -> Positions {
Self::measurement_points().positions(group)
}
pub fn preview_positions() -> Positions {
Self::measurement_points().preview_positions()
}
pub fn universes() -> BTreeSet<u16> {
Self::measurement_points().universes()
}
}