/// Tool system for the toolbar /// /// Defines the available drawing/editing tools use serde::{Deserialize, Serialize}; use std::collections::HashMap; use uuid::Uuid; use vello::kurbo::Point; /// Drawing and editing tools #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub enum Tool { /// Selection tool - select and move objects Select, /// Draw/Pen tool - freehand drawing Draw, /// Transform tool - scale, rotate, skew Transform, /// Rectangle shape tool Rectangle, /// Ellipse/Circle shape tool Ellipse, /// Paint bucket - fill areas with color PaintBucket, /// Eyedropper - pick colors from the canvas Eyedropper, /// Line tool - draw straight lines Line, /// Polygon tool - draw polygons Polygon, /// Bezier edit tool - edit bezier curve control points BezierEdit, /// Text tool - add and edit text Text, } /// Tool state tracking for interactive operations #[derive(Debug, Clone)] pub enum ToolState { /// Tool is idle (no operation in progress) Idle, /// Drawing a freehand path DrawingPath { points: Vec, simplify_mode: SimplifyMode, }, /// Dragging selected objects DraggingSelection { start_pos: Point, start_mouse: Point, original_positions: HashMap, }, /// Creating a marquee selection rectangle MarqueeSelecting { start: Point, current: Point, }, /// Creating a rectangle shape CreatingRectangle { start_point: Point, // Starting point (corner or center depending on modifiers) current_point: Point, // Current mouse position centered: bool, // If true, start_point is center; if false, it's a corner constrain_square: bool, // If true, constrain to square (equal width/height) }, /// Creating an ellipse shape CreatingEllipse { start_point: Point, // Starting point (center or corner depending on modifiers) current_point: Point, // Current mouse position corner_mode: bool, // If true, start is corner; if false, start is center constrain_circle: bool, // If true, constrain to circle (equal radii) }, /// Transforming selected objects (scale, rotate) Transforming { mode: TransformMode, original_transforms: HashMap, pivot: Point, start_mouse: Point, // Mouse position when transform started current_mouse: Point, // Current mouse position during drag original_bbox: vello::kurbo::Rect, // Bounding box at start of transform (fixed) }, /// Creating a line CreatingLine { start_point: Point, // Starting point of the line current_point: Point, // Current mouse position (end point) }, /// Creating a polygon CreatingPolygon { center: Point, // Center point of the polygon current_point: Point, // Current mouse position (determines radius) num_sides: u32, // Number of sides (from properties, default 5) }, /// Editing a vertex (dragging it and connected curves) EditingVertex { shape_id: Uuid, // Which shape is being edited vertex_index: usize, // Which vertex in the vertices array start_pos: Point, // Vertex position when drag started start_mouse: Point, // Mouse position when drag started affected_curve_indices: Vec, // Which curves connect to this vertex }, /// Editing a curve (reshaping with moldCurve algorithm) EditingCurve { shape_id: Uuid, // Which shape is being edited curve_index: usize, // Which curve in the curves array original_curve: vello::kurbo::CubicBez, // The curve when drag started start_mouse: Point, // Mouse position when drag started parameter_t: f64, // Parameter where the drag started (0.0-1.0) }, /// Editing a control point (BezierEdit tool only) EditingControlPoint { shape_id: Uuid, // Which shape is being edited curve_index: usize, // Which curve owns this control point point_index: u8, // 1 or 2 (p1 or p2 of the cubic bezier) original_curve: vello::kurbo::CubicBez, // The curve when drag started start_pos: Point, // Control point position when drag started }, } /// Path simplification mode for the draw tool #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum SimplifyMode { /// Ramer-Douglas-Peucker corner detection Corners, /// Schneider curve fitting for smooth curves Smooth, /// No simplification (use raw points) Verbatim, } /// Transform mode for the transform tool #[derive(Debug, Clone, Copy, PartialEq)] pub enum TransformMode { /// Scale from a corner ScaleCorner { origin: Point }, /// Scale along an edge ScaleEdge { axis: Axis, origin: Point }, /// Rotate around a pivot Rotate { center: Point }, /// Skew along an edge Skew { axis: Axis, origin: Point }, } /// Axis for edge scaling #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Axis { Horizontal, Vertical, } impl Default for ToolState { fn default() -> Self { Self::Idle } } impl Tool { /// Get display name for the tool pub fn display_name(self) -> &'static str { match self { Tool::Select => "Select", Tool::Draw => "Draw", Tool::Transform => "Transform", Tool::Rectangle => "Rectangle", Tool::Ellipse => "Ellipse", Tool::PaintBucket => "Paint Bucket", Tool::Eyedropper => "Eyedropper", Tool::Line => "Line", Tool::Polygon => "Polygon", Tool::BezierEdit => "Bezier Edit", Tool::Text => "Text", } } /// Get SVG icon file name for the tool pub fn icon_file(self) -> &'static str { match self { Tool::Select => "select.svg", Tool::Draw => "draw.svg", Tool::Transform => "transform.svg", Tool::Rectangle => "rectangle.svg", Tool::Ellipse => "ellipse.svg", Tool::PaintBucket => "paint_bucket.svg", Tool::Eyedropper => "eyedropper.svg", Tool::Line => "line.svg", Tool::Polygon => "polygon.svg", Tool::BezierEdit => "bezier_edit.svg", Tool::Text => "text.svg", } } /// Get all available tools pub fn all() -> &'static [Tool] { &[ Tool::Select, Tool::Draw, Tool::Transform, Tool::Rectangle, Tool::Ellipse, Tool::PaintBucket, Tool::Eyedropper, Tool::Line, Tool::Polygon, Tool::BezierEdit, Tool::Text, ] } /// Get keyboard shortcut hint pub fn shortcut_hint(self) -> &'static str { match self { Tool::Select => "V", Tool::Draw => "P", Tool::Transform => "Q", Tool::Rectangle => "R", Tool::Ellipse => "E", Tool::PaintBucket => "B", Tool::Eyedropper => "I", Tool::Line => "L", Tool::Polygon => "G", Tool::BezierEdit => "A", Tool::Text => "T", } } }