diff --git a/Cargo.toml b/Cargo.toml index ef5c70d..03a16a5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,10 +16,11 @@ name = "topola-sdl2-demo" required-features = ["sdl2"] [features] -egui = ["dep:egui", "dep:eframe"] +egui = ["dep:eframe", "dep:egui"] sdl2 = ["dep:sdl2"] [dependencies] +rfd = "0.14.0" gl = "0.14.0" pathfinder_canvas = { git = "https://github.com/servo/pathfinder" } pathfinder_geometry = { git = "https://github.com/servo/pathfinder" } @@ -34,6 +35,7 @@ petgraph = "0.6.3" spade = "2.2.0" enum_dispatch = "0.3.12" itertools = "0.8.2" +futures = "0.3.30" contracts = "0.6.3" log = "0.4" @@ -41,16 +43,16 @@ log = "0.4" version = "1" features = ["derive"] -[dependencies.egui] -optional = true -version = "0.26.0" - [dependencies.eframe] optional = true version = "0.26.0" default-features = false features = ["accesskit", "default_fonts", "glow", "persistence"] +[dependencies.egui] +optional = true +version = "0.26.0" + [dependencies.sdl2] optional = true version = "0.35.2" diff --git a/src/bin/topola-egui/app.rs b/src/bin/topola-egui/app.rs index 5d7f480..7a7209d 100644 --- a/src/bin/topola-egui/app.rs +++ b/src/bin/topola-egui/app.rs @@ -1,5 +1,12 @@ +use futures::executor; +use std::{ + future::Future, + sync::mpsc::{channel, Receiver, Sender}, +}; + use topola::{ - layout::geometry::shape::{BendShape, DotShape, SegShape, Shape}, + dsn::design::DsnDesign, + geometry::shape::{BendShape, DotShape, SegShape, Shape}, math::Circle, }; @@ -12,8 +19,10 @@ pub struct App { // Example stuff: label: String, - #[serde(skip)] // Don't serialize this field. - value: f32, + //#[serde(skip)] // Don't serialize this field. + //text_channel: (Sender, Receiver), + #[serde(skip)] + design: Option, } impl Default for App { @@ -21,7 +30,8 @@ impl Default for App { Self { // Example stuff: label: "Hello World!".to_owned(), - value: 2.7, + //text_channel: channel(), + design: None, } } } @@ -48,15 +58,36 @@ impl eframe::App for App { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { egui::TopBottomPanel::top("top_panel").show(ctx, |ui| { egui::menu::bar(ui, |ui| { - let is_web = cfg!(target_arch = "wasm32"); - if !is_web { - ui.menu_button("File", |ui| { - if ui.button("Quit").clicked() { - ctx.send_viewport_cmd(egui::ViewportCommand::Close); + ui.menu_button("File", |ui| { + if ui.button("Open").clicked() { + // `Context` is cheap to clone as it's wrapped in an `Arc`. + let ctx = ui.ctx().clone(); + // NOTE: This requires Zenity to be installed on your system. + + // Doing this synchronously may not work on WASM. I haven't tested this + // yet, so I'm leaving a commented-out asynchronous version further below. + let maybe_path = rfd::FileDialog::new().pick_file(); + + if let Some(path) = maybe_path { + self.design = DsnDesign::load_from_file(path.to_str().unwrap()).ok(); } - }); - ui.add_space(16.0); - } + + //let task = rfd::AsyncFileDialog::new().pick_file(); + /*execute(async move { + let file = task.await; + if let Some(file) = file { + let text = file.read().await; + let _ = sender.send(String::from_utf8_lossy(&text).to_string()); + ctx.request_repaint(); + } + });*/ + } + + if ui.button("Quit").clicked() { + ctx.send_viewport_cmd(egui::ViewportCommand::Close); + } + }); + ui.add_space(16.0); egui::widgets::global_dark_light_mode_buttons(ui); }); @@ -105,3 +136,13 @@ impl eframe::App for App { }); } } + +#[cfg(not(target_arch = "wasm32"))] +fn execute + Send + 'static>(f: F) { + std::thread::spawn(move || futures::executor::block_on(f)); +} + +#[cfg(target_arch = "wasm32")] +fn execute + 'static>(f: F) { + wasm_bindgen_futures::spawn_local(f); +} diff --git a/src/bin/topola-egui/painter.rs b/src/bin/topola-egui/painter.rs index 6f88469..2f2a8e7 100644 --- a/src/bin/topola-egui/painter.rs +++ b/src/bin/topola-egui/painter.rs @@ -1,6 +1,6 @@ use egui::{emath::RectTransform, epaint, Color32, Pos2, Ui}; use geo::Point; -use topola::layout::geometry::shape::Shape; +use topola::geometry::shape::Shape; pub struct Painter<'a> { ui: &'a mut egui::Ui, diff --git a/src/dsn/rules.rs b/src/dsn/rules.rs index 0a7cd61..c390058 100644 --- a/src/dsn/rules.rs +++ b/src/dsn/rules.rs @@ -35,7 +35,8 @@ impl Rules { pub fn from_pcb(pcb: &Pcb) -> Self { // keeping this as a separate iter pass because it might be moved into a different struct later? let net_ids = HashMap::from_iter( - pcb.network.classes + pcb.network + .classes .iter() .flat_map(|class| &class.nets) .enumerate() diff --git a/src/dsn/structure.rs b/src/dsn/structure.rs index 05a52ce..fb9c6f3 100644 --- a/src/dsn/structure.rs +++ b/src/dsn/structure.rs @@ -1,4 +1,4 @@ -use serde::{Deserialize, Deserializer, de::Error}; +use serde::{de::Error, Deserialize, Deserializer}; #[derive(Deserialize, Debug)] #[serde(rename = "pcb")] @@ -251,15 +251,16 @@ pub struct Point { } fn de_points<'de, D>(deserializer: D) -> Result, D::Error> - where D: Deserializer<'de> +where + D: Deserializer<'de>, { Vec::::deserialize(deserializer)? .chunks(2) .map(|pair| { let x = pair[0]; - let y = *pair.get(1).ok_or( - Error::custom("expected paired x y coordinates, list ended at x") - )?; + let y = *pair.get(1).ok_or(Error::custom( + "expected paired x y coordinates, list ended at x", + ))?; Ok(Point { x, y }) })