diff --git a/src/main.rs b/src/main.rs
index 287e5f0..b59f028 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -31,7 +31,8 @@ use druid::{
use im::Vector;
-use stiletto::tool::{CanvasToolCtx, CanvasToolParams};
+use stiletto::tool::CanvasToolParams;
+use stiletto::widget::tool_ctx::{CanvasToolCtx};
use stiletto::widget::{build_simple_tool_widget, CanvasState, CanvasToolIconState, CanvasWidget};
use stiletto::DocumentSnapshot;
diff --git a/src/tool.rs b/src/tool.rs
index 47fec7b..2c57785 100644
--- a/src/tool.rs
+++ b/src/tool.rs
@@ -14,12 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use druid::kurbo::BezPath;
-use druid::{Color, Data, Env, Event, EventCtx, PaintCtx};
-
-use crate::canvas;
-use crate::canvas::{Canvas, CanvasElement};
-use crate::history::VersionedCanvas;
+use druid::{Color, Data};
#[derive(Clone, Data)]
pub enum CanvasToolParams {
@@ -33,154 +28,3 @@ pub enum CanvasToolType {
Eraser,
}
-#[derive(Clone, Data)]
-pub enum CanvasToolState {
- Idle,
- DrawingFreehand {
- pen_params: CanvasToolParams,
- current_path: CanvasElement,
- },
- Erasing,
-}
-
-#[derive(Clone, Data)]
-pub struct CanvasToolCtx {
- initial_params: CanvasToolParams,
- state: CanvasToolState,
-}
-
-impl CanvasToolParams {
- pub fn tool_type(&self) -> CanvasToolType {
- match self {
- CanvasToolParams::Pen { .. } => CanvasToolType::Pen,
- CanvasToolParams::Eraser => CanvasToolType::Eraser,
- }
- }
-}
-
-impl CanvasToolCtx {
- pub fn new(params: CanvasToolParams) -> Self {
- CanvasToolCtx {
- initial_params: params,
- state: CanvasToolState::Idle,
- }
- }
-
- pub fn handle_event(
- &mut self,
- ctx: &EventCtx,
- event: &Event,
- mut vcanvas: &mut VersionedCanvas,
- env: &Env,
- ) {
- match self.initial_params.tool_type() {
- CanvasToolType::Pen => self.handle_pen_event(&ctx, &event, &mut vcanvas, &env),
- CanvasToolType::Eraser => self.handle_erase_event(&ctx, &event, &mut vcanvas, &env),
- }
- }
-
- pub fn handle_erase_event(
- &mut self,
- _ctx: &EventCtx,
- event: &Event,
- vcanvas: &mut VersionedCanvas,
- _env: &Env,
- ) {
- match (&mut self.state, event) {
- (CanvasToolState::Idle, Event::MouseDown(_)) => {
- self.state = CanvasToolState::Erasing;
- }
- (CanvasToolState::Erasing, Event::MouseMove(mouse_event)) => {
- let eraser_rect = druid::Rect::from_center_size(mouse_event.pos, (5.0, 5.0));
- let old_elements = vcanvas.get().elements();
- let mut new_elements = old_elements.clone();
- new_elements.retain(|elem| {
- // Check if the element intersects the eraser rect
- if elem.bounding_box().intersect(eraser_rect).area() > 0.0 {
- if elem.intersects_rect(eraser_rect) {
- return false;
- }
- }
- return true;
- });
- if new_elements.len() != old_elements.len() {
- vcanvas.update(|canvas: &mut Canvas| {
- *canvas = Canvas::new_with_elements(new_elements);
- });
- }
- }
- (CanvasToolState::Erasing, Event::MouseUp(_)) => {
- self.state = CanvasToolState::Idle;
- }
- _ => {}
- }
- }
-
- pub fn handle_pen_event(
- &mut self,
- _ctx: &EventCtx,
- event: &Event,
- vcanvas: &mut VersionedCanvas,
- _env: &Env,
- ) {
- match (&mut self.state, event) {
- (CanvasToolState::Idle, Event::MouseDown(mouse_event)) => {
- let mut kurbo_path = BezPath::new();
- kurbo_path.move_to((mouse_event.pos.x, mouse_event.pos.y));
- if let CanvasToolParams::Pen { thickness, color } = &self.initial_params {
- self.state = CanvasToolState::DrawingFreehand {
- pen_params: self.initial_params.clone(),
- current_path: CanvasElement::Freehand {
- path: canvas::Path { kurbo_path },
- thickness: *thickness,
- stroke_color: color.clone(),
- },
- };
- }
- }
- (
- CanvasToolState::DrawingFreehand {
- ref mut current_path,
- ..
- },
- Event::MouseMove(mouse_event),
- ) => {
- if let CanvasElement::Freehand { ref mut path, .. } = current_path {
- path.kurbo_path
- .line_to((mouse_event.pos.x, mouse_event.pos.y));
- }
- }
- (CanvasToolState::DrawingFreehand { .. }, Event::MouseUp(_)) => {
- vcanvas.update(move |canvas: &mut Canvas| {
- let current_state = std::mem::replace(&mut self.state, CanvasToolState::Idle);
- if let CanvasToolState::DrawingFreehand { current_path, .. } = current_state {
- if let CanvasElement::Freehand {
- mut path,
- mut thickness,
- stroke_color,
- } = current_path
- {
- canvas.add_element(CanvasElement::Freehand {
- path,
- thickness,
- stroke_color,
- });
- }
- }
- });
- }
- _ => {}
- }
- }
-
- pub fn needs_repaint(&self) -> bool {
- true
- }
-
- pub fn paint(&self, ctx: &mut PaintCtx, _env: &Env) {
- match &self.state {
- CanvasToolState::DrawingFreehand { current_path, .. } => current_path.draw(ctx),
- _ => {}
- }
- }
-}
diff --git a/src/widget/canvas.rs b/src/widget/canvas.rs
index bb64c03..f29cce4 100644
--- a/src/widget/canvas.rs
+++ b/src/widget/canvas.rs
@@ -16,9 +16,9 @@
use im::Vector;
+use super::tool_ctx::{CanvasToolCtx};
use crate::canvas::Canvas;
use crate::history::VersionedCanvas;
-use crate::tool::CanvasToolCtx;
use crate::DocumentSnapshot;
use druid::widget::prelude::*;
diff --git a/src/widget/mod.rs b/src/widget/mod.rs
index 5d05f31..fbca189 100644
--- a/src/widget/mod.rs
+++ b/src/widget/mod.rs
@@ -1,5 +1,6 @@
pub mod canvas;
pub mod tool_icon;
+pub mod tool_ctx;
pub use canvas::*;
pub use tool_icon::*;
diff --git a/src/widget/tool_ctx.rs b/src/widget/tool_ctx.rs
new file mode 100644
index 0000000..5154866
--- /dev/null
+++ b/src/widget/tool_ctx.rs
@@ -0,0 +1,174 @@
+// Stiletto
+// Copyright (C) 2020 Stiletto Authors
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+use crate::tool::{CanvasToolParams, CanvasToolType};
+use crate::canvas::{Canvas, CanvasElement};
+use crate::history::VersionedCanvas;
+
+use druid::kurbo::BezPath;
+use druid::{Data, Env, Event, EventCtx, PaintCtx};
+
+#[derive(Clone, Data)]
+pub enum CanvasToolState {
+ Idle,
+ DrawingFreehand {
+ pen_params: CanvasToolParams,
+ current_path: CanvasElement,
+ },
+ Erasing,
+}
+
+#[derive(Clone, Data)]
+pub struct CanvasToolCtx {
+ initial_params: CanvasToolParams,
+ state: CanvasToolState,
+}
+
+impl CanvasToolParams {
+ pub fn tool_type(&self) -> CanvasToolType {
+ match self {
+ CanvasToolParams::Pen { .. } => CanvasToolType::Pen,
+ CanvasToolParams::Eraser => CanvasToolType::Eraser,
+ }
+ }
+}
+
+impl CanvasToolCtx {
+ pub fn new(params: CanvasToolParams) -> Self {
+ CanvasToolCtx {
+ initial_params: params,
+ state: CanvasToolState::Idle,
+ }
+ }
+
+ pub fn handle_event(
+ &mut self,
+ ctx: &EventCtx,
+ event: &Event,
+ mut vcanvas: &mut VersionedCanvas,
+ env: &Env,
+ ) {
+ match self.initial_params.tool_type() {
+ CanvasToolType::Pen => self.handle_pen_event(&ctx, &event, &mut vcanvas, &env),
+ CanvasToolType::Eraser => self.handle_erase_event(&ctx, &event, &mut vcanvas, &env),
+ }
+ }
+
+ pub fn handle_erase_event(
+ &mut self,
+ _ctx: &EventCtx,
+ event: &Event,
+ vcanvas: &mut VersionedCanvas,
+ _env: &Env,
+ ) {
+ match (&mut self.state, event) {
+ (CanvasToolState::Idle, Event::MouseDown(_)) => {
+ self.state = CanvasToolState::Erasing;
+ }
+ (CanvasToolState::Erasing, Event::MouseMove(mouse_event)) => {
+ let eraser_rect = druid::Rect::from_center_size(mouse_event.pos, (5.0, 5.0));
+ let old_elements = vcanvas.get().elements();
+ let mut new_elements = old_elements.clone();
+ new_elements.retain(|elem| {
+ // Check if the element intersects the eraser rect
+ if elem.bounding_box().intersect(eraser_rect).area() > 0.0 {
+ if elem.intersects_rect(eraser_rect) {
+ return false;
+ }
+ }
+ return true;
+ });
+ if new_elements.len() != old_elements.len() {
+ vcanvas.update(|canvas: &mut Canvas| {
+ *canvas = Canvas::new_with_elements(new_elements);
+ });
+ }
+ }
+ (CanvasToolState::Erasing, Event::MouseUp(_)) => {
+ self.state = CanvasToolState::Idle;
+ }
+ _ => {}
+ }
+ }
+
+ pub fn handle_pen_event(
+ &mut self,
+ _ctx: &EventCtx,
+ event: &Event,
+ vcanvas: &mut VersionedCanvas,
+ _env: &Env,
+ ) {
+ match (&mut self.state, event) {
+ (CanvasToolState::Idle, Event::MouseDown(mouse_event)) => {
+ let mut kurbo_path = BezPath::new();
+ kurbo_path.move_to((mouse_event.pos.x, mouse_event.pos.y));
+ if let CanvasToolParams::Pen { thickness, color } = &self.initial_params {
+ self.state = CanvasToolState::DrawingFreehand {
+ pen_params: self.initial_params.clone(),
+ current_path: CanvasElement::Freehand {
+ path: crate::canvas::Path { kurbo_path },
+ thickness: *thickness,
+ stroke_color: color.clone(),
+ },
+ };
+ }
+ }
+ (
+ CanvasToolState::DrawingFreehand {
+ ref mut current_path,
+ ..
+ },
+ Event::MouseMove(mouse_event),
+ ) => {
+ if let CanvasElement::Freehand { ref mut path, .. } = current_path {
+ path.kurbo_path
+ .line_to((mouse_event.pos.x, mouse_event.pos.y));
+ }
+ }
+ (CanvasToolState::DrawingFreehand { .. }, Event::MouseUp(_)) => {
+ vcanvas.update(move |canvas: &mut Canvas| {
+ let current_state = std::mem::replace(&mut self.state, CanvasToolState::Idle);
+ if let CanvasToolState::DrawingFreehand { current_path, .. } = current_state {
+ if let CanvasElement::Freehand {
+ mut path,
+ mut thickness,
+ stroke_color,
+ } = current_path
+ {
+ canvas.add_element(CanvasElement::Freehand {
+ path,
+ thickness,
+ stroke_color,
+ });
+ }
+ }
+ });
+ }
+ _ => {}
+ }
+ }
+
+ pub fn needs_repaint(&self) -> bool {
+ true
+ }
+
+ pub fn paint(&self, ctx: &mut PaintCtx, _env: &Env) {
+ match &self.state {
+ CanvasToolState::DrawingFreehand { current_path, .. } => current_path.draw(ctx),
+ _ => {}
+ }
+ }
+}