cargo: rename topola-gui to topola-egui, minor refactoring

This commit is contained in:
Mikolaj Wielgus 2024-02-20 04:18:19 +00:00
parent 0cb7a015d4
commit f10f7b7ab4
6 changed files with 109 additions and 73 deletions

View File

@ -2,21 +2,21 @@
name = "topola" name = "topola"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
default-run = "topola-gui" default-run = "topola-egui"
[lib] [lib]
name = "topola" name = "topola"
[[bin]] [[bin]]
name = "topola-gui" name = "topola-egui"
required-features = ["gui"] required-features = ["egui"]
[[bin]] [[bin]]
name = "topola-sdl2-demo" name = "topola-sdl2-demo"
required-features = ["sdl2"] required-features = ["sdl2"]
[features] [features]
gui = ["dep:egui", "dep:eframe"] egui = ["dep:egui", "dep:eframe"]
sdl2 = ["dep:sdl2"] sdl2 = ["dep:sdl2"]
[dependencies] [dependencies]

View File

@ -1,7 +1,7 @@
/// Deserialize/Serialize is needed to persist app state between restarts. /// Deserialize/Serialize is needed to persist app state between restarts.
#[derive(serde::Deserialize, serde::Serialize)] #[derive(serde::Deserialize, serde::Serialize)]
#[serde(default)] #[serde(default)]
pub struct TemplateApp { pub struct App {
// Example stuff: // Example stuff:
label: String, label: String,
@ -9,7 +9,7 @@ pub struct TemplateApp {
value: f32, value: f32,
} }
impl Default for TemplateApp { impl Default for App {
fn default() -> Self { fn default() -> Self {
Self { Self {
// Example stuff: // Example stuff:
@ -19,7 +19,7 @@ impl Default for TemplateApp {
} }
} }
impl TemplateApp { impl App {
/// Called once on start. /// Called once on start.
pub fn new(cc: &eframe::CreationContext<'_>) -> Self { pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
// Load previous app state if one exists. // Load previous app state if one exists.
@ -31,7 +31,7 @@ impl TemplateApp {
} }
} }
impl eframe::App for TemplateApp { impl eframe::App for App {
/// Called to save state before shutdown. /// Called to save state before shutdown.
fn save(&mut self, storage: &mut dyn eframe::Storage) { fn save(&mut self, storage: &mut dyn eframe::Storage) {
eframe::set_value(storage, eframe::APP_KEY, self); eframe::set_value(storage, eframe::APP_KEY, self);
@ -55,6 +55,14 @@ impl eframe::App for TemplateApp {
}); });
}); });
egui::CentralPanel::default().show(ctx, |ui| {}); egui::CentralPanel::default().show(ctx, |ui| {
egui::Frame::canvas(ui.style()).show(ui, |ui| {
let (rect, response) =
ui.allocate_exact_size(egui::Vec2::splat(300.0), egui::Sense::drag());
let stroke = egui::Stroke::new(10.0, egui::Color32::from_white_alpha(255));
ui.painter()
.line_segment([[10.0, 10.0].into(), [30.0, 30.0].into()], stroke);
})
});
} }
} }

View File

@ -1,7 +1,8 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
mod app; mod app;
use app::TemplateApp; mod painter;
use app::App;
// Build to native. // Build to native.
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
@ -15,9 +16,9 @@ fn main() -> eframe::Result<()> {
..Default::default() ..Default::default()
}; };
eframe::run_native( eframe::run_native(
"eframe template", "topola-egui",
native_options, native_options,
Box::new(|cc| Box::new(TemplateApp::new(cc))), Box::new(|cc| Box::new(App::new(cc))),
) )
} }

View File

@ -0,0 +1 @@

View File

@ -1,5 +1,7 @@
extern crate sdl2; extern crate sdl2;
mod painter;
macro_rules! dbg_dot { macro_rules! dbg_dot {
($graph:expr) => { ($graph:expr) => {
use petgraph::dot::Dot; use petgraph::dot::Dot;
@ -8,6 +10,7 @@ macro_rules! dbg_dot {
} }
use geo::point; use geo::point;
use painter::Painter;
use petgraph::visit::{EdgeRef, IntoEdgeReferences}; use petgraph::visit::{EdgeRef, IntoEdgeReferences};
use topola::draw::DrawException; use topola::draw::DrawException;
use topola::layout::connectivity::BandIndex; use topola::layout::connectivity::BandIndex;
@ -665,6 +668,7 @@ fn render_times(
let window_size = window.size(); let window_size = window.size();
let mut canvas = Canvas::new(vec2f(window_size.0 as f32, window_size.1 as f32)) let mut canvas = Canvas::new(vec2f(window_size.0 as f32, window_size.1 as f32))
.get_context_2d(font_context.clone()); .get_context_2d(font_context.clone());
let mut painter = Painter::new(&mut canvas);
let layout = match router_or_layout { let layout = match router_or_layout {
RouterOrLayout::Router(ref mut router) => { RouterOrLayout::Router(ref mut router) => {
@ -701,17 +705,17 @@ fn render_times(
}; };
let shape = node.primitive(layout).shape(); let shape = node.primitive(layout).shape();
render_shape(&mut canvas, &shape, color); painter.paint_shape(&shape, color);
} }
for ghost in ghosts { for ghost in ghosts {
render_shape(&mut canvas, &ghost, ColorU::new(75, 75, 150, 255)); painter.paint_shape(&ghost, ColorU::new(75, 75, 150, 255));
} }
if let Some(ref mesh) = maybe_mesh { if let Some(ref mesh) = maybe_mesh {
for edge in mesh.edge_references() { for edge in mesh.edge_references() {
let start_point = edge.source().primitive(layout).shape().center(); let to = edge.source().primitive(layout).shape().center();
let end_point = edge.target().primitive(layout).shape().center(); let from = edge.target().primitive(layout).shape().center();
let color = 'blk: { let color = 'blk: {
if let (Some(source_pos), Some(target_pos)) = ( if let (Some(source_pos), Some(target_pos)) = (
@ -726,12 +730,7 @@ fn render_times(
ColorU::new(125, 125, 125, 255) ColorU::new(125, 125, 125, 255)
}; };
let mut path = Path2D::new(); painter.paint_edge(from, to, color);
path.move_to(vec2f(start_point.x() as f32, start_point.y() as f32));
path.line_to(vec2f(end_point.x() as f32, end_point.y() as f32));
canvas.set_stroke_style(color);
canvas.set_line_width(1.0);
canvas.stroke_path(path);
} }
} }
//}); //});
@ -752,54 +751,3 @@ fn render_times(
::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60)); ::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
} }
} }
fn render_shape(canvas: &mut CanvasRenderingContext2D, shape: &Shape, color: ColorU) {
canvas.set_stroke_style(color);
canvas.set_fill_style(color);
match shape {
Shape::Dot(dot) => {
let mut path = Path2D::new();
path.ellipse(
vec2f(dot.c.pos.x() as f32, dot.c.pos.y() as f32),
dot.c.r as f32,
0.0,
0.0,
std::f32::consts::TAU,
);
canvas.fill_path(path, FillRule::Winding);
}
Shape::Seg(seg) => {
let mut path = Path2D::new();
path.move_to(vec2f(seg.from.x() as f32, seg.from.y() as f32));
path.line_to(vec2f(seg.to.x() as f32, seg.to.y() as f32));
canvas.set_line_width(seg.width as f32);
canvas.stroke_path(path);
}
Shape::Bend(bend) => {
let delta1 = bend.from - bend.c.pos;
let delta2 = bend.to - bend.c.pos;
let angle1 = delta1.y().atan2(delta1.x());
let angle2 = delta2.y().atan2(delta2.x());
let mut path = Path2D::new();
path.arc(
vec2f(bend.c.pos.x() as f32, bend.c.pos.y() as f32),
bend.circle().r as f32,
angle1 as f32,
angle2 as f32,
ArcDirection::CW,
);
canvas.set_line_width(bend.width as f32);
canvas.stroke_path(path);
}
}
let envelope = ShapeTrait::envelope(shape, 0.0);
// XXX: points represented as arrays can't be conveniently converted to vector types
let topleft = vec2f(envelope.lower()[0] as f32, envelope.lower()[1] as f32);
let bottomright = vec2f(envelope.upper()[0] as f32, envelope.upper()[1] as f32);
canvas.set_line_width(1.0);
canvas.set_stroke_style(ColorU::new(100, 100, 100, 255));
canvas.stroke_rect(RectF::new(topleft, bottomright - topleft));
}

View File

@ -0,0 +1,78 @@
use geo::Point;
use pathfinder_canvas::{
vec2f, ArcDirection, Canvas, CanvasRenderingContext2D, ColorU, FillRule, Path2D, RectF,
};
use topola::layout::geometry::shape::{Shape, ShapeTrait};
pub struct Painter<'a> {
canvas: &'a mut CanvasRenderingContext2D,
}
impl<'a> Painter<'a> {
pub fn new(canvas: &'a mut CanvasRenderingContext2D) -> Self {
Self { canvas }
}
pub fn paint_shape(&mut self, shape: &Shape, color: ColorU) {
self.canvas.set_stroke_style(color);
self.canvas.set_fill_style(color);
match shape {
Shape::Dot(dot) => {
let mut path = Path2D::new();
path.ellipse(
vec2f(dot.c.pos.x() as f32, dot.c.pos.y() as f32),
dot.c.r as f32,
0.0,
0.0,
std::f32::consts::TAU,
);
self.canvas.fill_path(path, FillRule::Winding);
}
Shape::Seg(seg) => {
let mut path = Path2D::new();
path.move_to(vec2f(seg.from.x() as f32, seg.from.y() as f32));
path.line_to(vec2f(seg.to.x() as f32, seg.to.y() as f32));
self.canvas.set_line_width(seg.width as f32);
self.canvas.stroke_path(path);
}
Shape::Bend(bend) => {
let delta1 = bend.from - bend.c.pos;
let delta2 = bend.to - bend.c.pos;
let angle1 = delta1.y().atan2(delta1.x());
let angle2 = delta2.y().atan2(delta2.x());
let mut path = Path2D::new();
path.arc(
vec2f(bend.c.pos.x() as f32, bend.c.pos.y() as f32),
bend.circle().r as f32,
angle1 as f32,
angle2 as f32,
ArcDirection::CW,
);
self.canvas.set_line_width(bend.width as f32);
self.canvas.stroke_path(path);
}
}
let envelope = ShapeTrait::envelope(shape, 0.0);
// XXX: points represented as arrays can't be conveniently converted to vector types
let topleft = vec2f(envelope.lower()[0] as f32, envelope.lower()[1] as f32);
let bottomright = vec2f(envelope.upper()[0] as f32, envelope.upper()[1] as f32);
self.canvas.set_line_width(1.0);
self.canvas
.set_stroke_style(ColorU::new(100, 100, 100, 255));
self.canvas
.stroke_rect(RectF::new(topleft, bottomright - topleft));
}
pub fn paint_edge(&mut self, from: Point, to: Point, color: ColorU) {
let mut path = Path2D::new();
path.move_to(vec2f(from.x() as f32, from.y() as f32));
path.line_to(vec2f(to.x() as f32, to.y() as f32));
self.canvas.set_stroke_style(color);
self.canvas.set_line_width(1.0);
self.canvas.stroke_path(path);
}
}