diff --git a/src/main.rs b/src/main.rs index 8d2edf5..40d8995 100644 --- a/src/main.rs +++ b/src/main.rs @@ -71,6 +71,10 @@ pub fn main() { tool_params: CanvasToolParams::Eraser, selected: false, }, + CanvasToolIconState { + tool_params: CanvasToolParams::RectangularSelection, + selected: false, + }, ], current_tool: 0, eraser_tool_id: 2, diff --git a/src/tool.rs b/src/tool.rs index 2c57785..8639cc0 100644 --- a/src/tool.rs +++ b/src/tool.rs @@ -20,11 +20,13 @@ use druid::{Color, Data}; pub enum CanvasToolParams { Pen { thickness: f64, color: Color }, Eraser, + RectangularSelection, } #[derive(Clone, PartialEq)] pub enum CanvasToolType { Pen, Eraser, + RectangularSelection, } diff --git a/src/widget/tool_ctx.rs b/src/widget/tool_ctx.rs index 2dc95f1..7f7f1cb 100644 --- a/src/widget/tool_ctx.rs +++ b/src/widget/tool_ctx.rs @@ -19,7 +19,9 @@ use crate::canvas::{Canvas, CanvasElement}; use crate::history::VersionedCanvas; use druid::kurbo::BezPath; -use druid::{Data, Env, Event, EventCtx, MouseButton, MouseEvent, PaintCtx}; +use druid::{Color, Data, Env, Event, EventCtx, MouseButton, MouseEvent, PaintCtx, RenderContext}; + +use im::Vector; #[derive(Clone, Data)] pub enum CanvasToolState { @@ -29,6 +31,10 @@ pub enum CanvasToolState { current_path: CanvasElement, }, Erasing, + SelectingRect { + origin: druid::Point, + current_rect: druid::Rect, + } } #[derive(Clone, Data)] @@ -42,6 +48,7 @@ impl CanvasToolParams { match self { CanvasToolParams::Pen { .. } => CanvasToolType::Pen, CanvasToolParams::Eraser => CanvasToolType::Eraser, + CanvasToolParams::RectangularSelection => CanvasToolType::RectangularSelection, } } } @@ -69,6 +76,7 @@ impl CanvasToolCtx { 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), + CanvasToolType::RectangularSelection => self.handle_rectangular_select_event(&ctx, &event, &mut vcanvas, &env), } } @@ -137,7 +145,7 @@ impl CanvasToolCtx { .. }, Event::MouseMove(mouse_event), - ) => if pressed(mouse_event) { + ) if pressed(mouse_event) => { if let CanvasElement::Freehand { ref mut path, .. } = current_path { path.kurbo_path .line_to((mouse_event.pos.x, mouse_event.pos.y)); @@ -166,6 +174,47 @@ impl CanvasToolCtx { } } + pub fn handle_rectangular_select_event( + &mut self, + _ctx: &EventCtx, + event: &Event, + vcanvas: &mut VersionedCanvas, + _env: &Env, + ) { + match (&mut self.state, event) { + (CanvasToolState::Idle, Event::MouseDown(mouse_event)) if pressed(mouse_event) => { + self.state = CanvasToolState::SelectingRect { + origin: mouse_event.pos, + current_rect: druid::Rect::from_origin_size(mouse_event.pos, (0.0, 0.0)) + }; + } + + (CanvasToolState::SelectingRect{ ref mut current_rect, ref origin }, Event::MouseMove(mouse_event)) if pressed(mouse_event) => { + *current_rect = druid::Rect::from_origin_size(*origin, (0.0, 0.0)) + .union_pt(mouse_event.pos); + } + + (CanvasToolState::SelectingRect{ ref mut current_rect, ref origin }, Event::MouseUp(mouse_event)) if pressed(mouse_event) => { + *current_rect = druid::Rect::from_origin_size(*origin, (0.0, 0.0)) + .union_pt(mouse_event.pos); + let elements = vcanvas.get().elements(); + let selected_elements_idx = elements.iter().enumerate() + .filter_map(|(i, elem)| { + let bbox = elem.bounding_box(); + let p0 = druid::Point::new(bbox.x0, bbox.y0); + let p1 = druid::Point::new(bbox.x1, bbox.y1); + if current_rect.contains(p0) && current_rect.contains(p1) { + return Some(i); + } + None + }).collect::>(); + dbg!(selected_elements_idx); + self.state = CanvasToolState::Idle; + } + _ => {} + } + } + pub fn needs_repaint(&self) -> bool { true } @@ -173,6 +222,7 @@ impl CanvasToolCtx { pub fn paint(&self, ctx: &mut PaintCtx, _env: &Env) { match &self.state { CanvasToolState::DrawingFreehand { current_path, .. } => current_path.draw(ctx), + CanvasToolState::SelectingRect { current_rect, .. } => ctx.stroke(current_rect, &Color::BLACK, 0.5), _ => {} } } diff --git a/src/widget/tool_icon.rs b/src/widget/tool_icon.rs index 4bcfb36..8910ea7 100644 --- a/src/widget/tool_icon.rs +++ b/src/widget/tool_icon.rs @@ -34,6 +34,9 @@ impl CanvasToolIconState { CanvasToolParams::Eraser => include_str!("../../icons/eraser.svg") .parse::() .unwrap(), + CanvasToolParams::RectangularSelection => include_str!("../../icons/eraser.svg") + .parse::() + .unwrap(), } } }