mirror of https://codeberg.org/topola/topola.git
egui: actually load and display the layout
This commit is contained in:
parent
f8892f64a7
commit
d8e128e81a
|
|
@ -5,8 +5,9 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use topola::{
|
use topola::{
|
||||||
dsn::design::DsnDesign,
|
dsn::{design::DsnDesign, rules::DsnRules},
|
||||||
geometry::shape::{BendShape, DotShape, SegShape, Shape},
|
geometry::shape::{BendShape, DotShape, SegShape, Shape},
|
||||||
|
layout::{graph::MakePrimitive, primitive::MakeShape, Layout},
|
||||||
math::Circle,
|
math::Circle,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -20,10 +21,10 @@ pub struct App {
|
||||||
label: String,
|
label: String,
|
||||||
|
|
||||||
#[serde(skip)] // Don't serialize this field.
|
#[serde(skip)] // Don't serialize this field.
|
||||||
file_handle_channel: (Sender<rfd::FileHandle>, Receiver<rfd::FileHandle>),
|
text_channel: (Sender<String>, Receiver<String>),
|
||||||
|
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
design: Option<DsnDesign>,
|
layout: Option<Layout<DsnRules>>,
|
||||||
|
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
from_rect: egui::emath::Rect,
|
from_rect: egui::emath::Rect,
|
||||||
|
|
@ -34,9 +35,9 @@ impl Default for App {
|
||||||
Self {
|
Self {
|
||||||
// Example stuff:
|
// Example stuff:
|
||||||
label: "Hello World!".to_owned(),
|
label: "Hello World!".to_owned(),
|
||||||
file_handle_channel: channel(),
|
text_channel: channel(),
|
||||||
design: None,
|
layout: None,
|
||||||
from_rect: egui::Rect::from_x_y_ranges(0.0..=1000.0, 0.0..=500.0),
|
from_rect: egui::Rect::from_x_y_ranges(0.0..=1000000.0, 0.0..=500000.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -61,33 +62,35 @@ impl eframe::App for App {
|
||||||
|
|
||||||
/// Called each time the UI has to be repainted.
|
/// Called each time the UI has to be repainted.
|
||||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||||
|
if cfg!(target_arch = "wasm32") {
|
||||||
|
if let Ok(file_contents) = self.text_channel.1.try_recv() {
|
||||||
|
let design = DsnDesign::load_from_string(file_contents).unwrap();
|
||||||
|
self.layout = Some(design.make_layout());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let Ok(path) = self.text_channel.1.try_recv() {
|
||||||
|
let design = DsnDesign::load_from_file(&path).unwrap();
|
||||||
|
self.layout = Some(design.make_layout());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
|
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
|
||||||
egui::menu::bar(ui, |ui| {
|
egui::menu::bar(ui, |ui| {
|
||||||
ui.menu_button("File", |ui| {
|
ui.menu_button("File", |ui| {
|
||||||
if let Ok(file_handle) = self.file_handle_channel.1.try_recv() {
|
|
||||||
dbg!(file_handle);
|
|
||||||
// TODO: actually load the file from the handle.
|
|
||||||
}
|
|
||||||
|
|
||||||
if ui.button("Open").clicked() {
|
if ui.button("Open").clicked() {
|
||||||
// `Context` is cheap to clone as it's wrapped in an `Arc`.
|
// `Context` is cheap to clone as it's wrapped in an `Arc`.
|
||||||
let ctx = ui.ctx().clone();
|
let ctx = ui.ctx().clone();
|
||||||
// NOTE: On Linux, this requires Zenity to be installed on your system.
|
// NOTE: On Linux, this requires Zenity to be installed on your system.
|
||||||
let sender = self.file_handle_channel.0.clone();
|
let sender = self.text_channel.0.clone();
|
||||||
let task = rfd::AsyncFileDialog::new().pick_file();
|
let task = rfd::AsyncFileDialog::new().pick_file();
|
||||||
|
|
||||||
execute(async move {
|
execute(async move {
|
||||||
let maybe_file_handle = task.await;
|
let maybe_file_handle = task.await;
|
||||||
|
|
||||||
if let Some(file_handle) = maybe_file_handle {
|
if let Some(file_handle) = maybe_file_handle {
|
||||||
let _ = sender.send(file_handle);
|
let _ = sender.send(channel_text(file_handle).await);
|
||||||
ctx.request_repaint();
|
ctx.request_repaint();
|
||||||
}
|
}
|
||||||
/*if let Some(file) = file {
|
|
||||||
let text = file.read().await;
|
|
||||||
let _ = sender.send(String::from_utf8_lossy(&text).to_string());
|
|
||||||
ctx.request_repaint();
|
|
||||||
}*/
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,7 +131,9 @@ impl eframe::App for App {
|
||||||
ctx.input(|i| latest_pos.to_vec2() * (new_scale - old_scale) / new_scale),
|
ctx.input(|i| latest_pos.to_vec2() * (new_scale - old_scale) / new_scale),
|
||||||
);
|
);
|
||||||
|
|
||||||
self.from_rect = self.from_rect.translate(ctx.input(|i| -i.raw_scroll_delta));
|
self.from_rect = self
|
||||||
|
.from_rect
|
||||||
|
.translate(ctx.input(|i| -i.raw_scroll_delta / new_scale));
|
||||||
|
|
||||||
let transform = egui::emath::RectTransform::from_to(self.from_rect, viewport_rect);
|
let transform = egui::emath::RectTransform::from_to(self.from_rect, viewport_rect);
|
||||||
let mut painter = Painter::new(ui, transform);
|
let mut painter = Painter::new(ui, transform);
|
||||||
|
|
@ -156,9 +161,12 @@ impl eframe::App for App {
|
||||||
width: 12.0,
|
width: 12.0,
|
||||||
});
|
});
|
||||||
|
|
||||||
painter.paint_shape(&dot_shape, egui::Color32::from_rgb(255, 0, 0));
|
if let Some(layout) = &self.layout {
|
||||||
painter.paint_shape(&seg_shape, egui::Color32::from_rgb(128, 128, 128));
|
for node in layout.nodes() {
|
||||||
painter.paint_shape(&bend_shape, egui::Color32::from_rgb(255, 255, 0));
|
let shape = node.primitive(layout).shape();
|
||||||
|
painter.paint_shape(&shape, egui::Color32::from_rgb(255, 0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -177,3 +185,15 @@ fn execute<F: Future<Output = ()> + Send + 'static>(f: F) {
|
||||||
fn execute<F: Future<Output = ()> + 'static>(f: F) {
|
fn execute<F: Future<Output = ()> + 'static>(f: F) {
|
||||||
wasm_bindgen_futures::spawn_local(f);
|
wasm_bindgen_futures::spawn_local(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
async fn channel_text(file_handle: rfd::FileHandle) -> String {
|
||||||
|
file_handle.path().to_str().unwrap().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
async fn channel_text(file_handle: rfd::FileHandle) -> String {
|
||||||
|
std::str::from_utf8(&file_handle.read().await)
|
||||||
|
.unwrap()
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -251,14 +251,19 @@ fn main() -> Result<(), anyhow::Error> {
|
||||||
]),
|
]),
|
||||||
}));*/
|
}));*/
|
||||||
|
|
||||||
let design = DsnDesign::load_from_file("tests/data/prerouted_lm317_breakout/prerouted_lm317_breakout.dsn")?;
|
let design = DsnDesign::load_from_file(
|
||||||
|
"tests/data/prerouted_lm317_breakout/prerouted_lm317_breakout.dsn",
|
||||||
|
)?;
|
||||||
//let design = DsnDesign::load_from_file("tests/data/test/test.dsn")?;
|
//let design = DsnDesign::load_from_file("tests/data/test/test.dsn")?;
|
||||||
//dbg!(&design);
|
//dbg!(&design);
|
||||||
let layout = design.make_layout();
|
let layout = design.make_layout();
|
||||||
let board = Board::new(layout);
|
let board = Board::new(layout);
|
||||||
let mut router = Router::new(board);
|
let mut router = Router::new(board);
|
||||||
|
|
||||||
let mut view = View { pan: vec2f(-80000.0, -60000.0), zoom: 0.005 };
|
let mut view = View {
|
||||||
|
pan: vec2f(-80000.0, -60000.0),
|
||||||
|
zoom: 0.005,
|
||||||
|
};
|
||||||
|
|
||||||
render_times(
|
render_times(
|
||||||
&mut event_pump,
|
&mut event_pump,
|
||||||
|
|
@ -333,12 +338,17 @@ fn render_times(
|
||||||
} => break 'running,
|
} => break 'running,
|
||||||
Event::MouseWheel { y, .. } => {
|
Event::MouseWheel { y, .. } => {
|
||||||
view.zoom *= f32::powf(1.4, y as f32);
|
view.zoom *= f32::powf(1.4, y as f32);
|
||||||
},
|
}
|
||||||
Event::MouseMotion { xrel, yrel, mousestate, .. } => {
|
Event::MouseMotion {
|
||||||
|
xrel,
|
||||||
|
yrel,
|
||||||
|
mousestate,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
if mousestate.left() {
|
if mousestate.left() {
|
||||||
view.pan += vec2f(xrel as f32, yrel as f32) / view.zoom;
|
view.pan += vec2f(xrel as f32, yrel as f32) / view.zoom;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,10 @@ pub struct DsnDesign {
|
||||||
impl DsnDesign {
|
impl DsnDesign {
|
||||||
pub fn load_from_file(filename: &str) -> Result<Self, LoadingError> {
|
pub fn load_from_file(filename: &str) -> Result<Self, LoadingError> {
|
||||||
let contents = std::fs::read_to_string(filename)?;
|
let contents = std::fs::read_to_string(filename)?;
|
||||||
|
Self::load_from_string(contents)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_from_string(contents: String) -> Result<Self, LoadingError> {
|
||||||
let pcb = de::from_str::<DsnFile>(&contents)
|
let pcb = de::from_str::<DsnFile>(&contents)
|
||||||
.map_err(|err| LoadingError::Syntax(err))?
|
.map_err(|err| LoadingError::Syntax(err))?
|
||||||
.pcb;
|
.pcb;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
mod de;
|
mod de;
|
||||||
pub mod design;
|
pub mod design;
|
||||||
mod rules;
|
pub mod rules;
|
||||||
mod structure;
|
mod structure;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue