Skip to content

Commit

Permalink
Make rectangle tool generic
Browse files Browse the repository at this point in the history
  • Loading branch information
sak96 committed Apr 26, 2024
1 parent a261de8 commit c7959c9
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 13 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Drawing canvas app written in Rust.
# Road Map

- [x] draw rectangle
- [x] draw ellipse
- [ ] select individual
- [ ] select group
- [ ] resize selection
Expand All @@ -15,7 +16,6 @@ Drawing canvas app written in Rust.

# Future Road Map Choice

- [ ] draw ellipse
- [ ] zoom
- [ ] export/import
- [ ] undo/redo
14 changes: 11 additions & 3 deletions src/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,16 @@ macro_rules! handle_canvas_by_tool {

#[function_component(App)]
pub fn app() -> Html {
let tools: Vec<Box<dyn tools::Tool>> =
vec![Box::<tools::rectangle_tool::RectangleTool>::default()];
let tools: Vec<Box<dyn tools::Tool>> = vec![
Box::new(tools::shape_tool::ShapeTool::<shapes::Rectangle>::new(
"\u{2B1B}",
"Rectangle drawing tool.",
)),
Box::new(tools::shape_tool::ShapeTool::<shapes::Ellipse>::new(
"\u{26AB}",
"Ellipse drawing tool.",
)),
];
let tools = use_mut_ref(|| tools);
let canvas_ref = use_node_ref();
let shapes = use_mut_ref(Vec::<Box<dyn Draw>>::new);
Expand All @@ -58,7 +66,7 @@ pub fn app() -> Html {
};
{
move_to_current_scope!(canvas_ref, shapes);
use_effect(move || {
use_effect(move || {
let canvas: HtmlCanvasElement = canvas_ref.cast::<HtmlCanvasElement>().unwrap();
canvas::refresh_canvas(canvas, &shapes.borrow(), None);
})
Expand Down
48 changes: 48 additions & 0 deletions src/app/shapes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,51 @@ impl Draw for Rectangle {
}
}
}

#[derive(Default)]
pub struct Ellipse {
center_x: f64,
center_y: f64,
radius_x: f64,
radius_y: f64,
}

impl Draw for Ellipse {
fn bbox(&self) -> BBox {
BBox {
left: self.center_x - self.radius_x,
top: self.center_y - self.radius_y,
width: self.radius_x + self.radius_x,
height: self.radius_y + self.radius_y,
}
}

fn draw(&self, context: &CanvasRenderingContext2d) {
context.set_stroke_style(&JsValue::from_str("red"));
context.begin_path();
context
.ellipse(
self.center_x,
self.center_y,
self.radius_x,
self.radius_y,
0.0,
0.0,
std::f64::consts::TAU,
)
.unwrap();
context.stroke();
}

fn resize_to_bbox(&mut self, bbox: BBox) -> bool {
if self.bbox() != bbox {
self.radius_x = bbox.width / 2.0;
self.radius_y = bbox.height / 2.0;
self.center_x = bbox.left + self.radius_x;
self.center_y = bbox.top + self.radius_y;
true
} else {
false
}
}
}
2 changes: 1 addition & 1 deletion src/app/tools/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement};

use super::shapes::Draw;
pub mod rectangle_tool;
pub mod shape_tool;

#[allow(unused_variables)]
pub trait Tool {
Expand Down
28 changes: 20 additions & 8 deletions src/app/tools/rectangle_tool.rs → src/app/tools/shape_tool.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
use super::Tool;
use crate::app::shapes::{BBox, Draw, Rectangle};
use crate::app::shapes::{BBox, Draw};
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement};

#[derive(Default)]
pub struct RectangleTool {
pub struct ShapeTool<T: Draw + Default> {
start: Option<(f64, f64)>,
shape: Box<Rectangle>,
icon: &'static str,
title: &'static str,
shape: Box<T>,
}

impl<T: Draw + Default> ShapeTool<T> {
pub fn new(icon: &'static str, title: &'static str) -> Self {
Self {
icon,
title,
shape: Default::default(),
start: None,
}
}
}

#[allow(unused_variables)]
impl Tool for RectangleTool {
impl<T: Draw + Default + 'static> Tool for ShapeTool<T> {
fn button_icon(&self) -> &'static str {
"\u{2B1B}"
self.icon
}

fn button_title(&self) -> &'static str {
"Rectangle drawing tool."
self.title
}

fn onmousedown(
Expand All @@ -37,7 +49,7 @@ impl Tool for RectangleTool {
shapes: &mut Vec<Box<dyn Draw>>,
) -> bool {
if let Some(start) = self.start.take() {
let mut shape = Box::<Rectangle>::default();
let mut shape = Box::<T>::default();
let changed = shape.resize_to_bbox(BBox::from_corner(start, position));
shapes.push(shape);
changed
Expand Down

0 comments on commit c7959c9

Please sign in to comment.