mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-07-23 15:45:05 +00:00
parent
31fb0d7148
commit
916d10980d
32 changed files with 325 additions and 382 deletions
|
@ -16,7 +16,7 @@ use crate::viewport_tools::vector_editor::vector_shape::VectorShape;
|
|||
use crate::EditorError;
|
||||
|
||||
use graphene::document::Document as GrapheneDocument;
|
||||
use graphene::layers::folder::Folder;
|
||||
use graphene::layers::folder_layer::FolderLayer;
|
||||
use graphene::layers::layer_info::LayerDataType;
|
||||
use graphene::layers::style::ViewMode;
|
||||
use graphene::{DocumentError, DocumentResponse, LayerId, Operation as DocumentOperation};
|
||||
|
@ -223,7 +223,7 @@ impl DocumentMessageHandler {
|
|||
)
|
||||
}
|
||||
|
||||
fn serialize_structure(&self, folder: &Folder, structure: &mut Vec<u64>, data: &mut Vec<LayerId>, path: &mut Vec<LayerId>) {
|
||||
fn serialize_structure(&self, folder: &FolderLayer, structure: &mut Vec<u64>, data: &mut Vec<LayerId>, path: &mut Vec<LayerId>) {
|
||||
let mut space = 0;
|
||||
for (id, layer) in folder.layer_ids.iter().zip(folder.layers()).rev() {
|
||||
data.push(*id);
|
||||
|
@ -930,7 +930,7 @@ impl MessageHandler<DocumentMessage, &InputPreprocessorMessageHandler> for Docum
|
|||
responses.push_back(ToolMessage::DocumentIsDirty.into());
|
||||
}
|
||||
Redo => {
|
||||
responses.push_back(SelectMessage::Abort.into());
|
||||
responses.push_back(SelectToolMessage::Abort.into());
|
||||
responses.push_back(DocumentHistoryForward.into());
|
||||
responses.push_back(ToolMessage::DocumentIsDirty.into());
|
||||
responses.push_back(RenderDocument.into());
|
||||
|
@ -1187,7 +1187,7 @@ impl MessageHandler<DocumentMessage, &InputPreprocessorMessageHandler> for Docum
|
|||
responses.push_back(ToolMessage::DocumentIsDirty.into());
|
||||
}
|
||||
Undo => {
|
||||
responses.push_back(SelectMessage::Abort.into());
|
||||
responses.push_back(SelectToolMessage::Abort.into());
|
||||
responses.push_back(DocumentHistoryBackward.into());
|
||||
responses.push_back(ToolMessage::DocumentIsDirty.into());
|
||||
responses.push_back(RenderDocument.into());
|
||||
|
|
|
@ -43,84 +43,84 @@ impl Default for Mapping {
|
|||
entry! {action=TransformLayerMessage::TypeDecimalPoint, key_down=KeyPeriod},
|
||||
entry! {action=TransformLayerMessage::PointerMove { slow_key: KeyShift, snap_key: KeyControl }, triggers=[KeyShift, KeyControl]},
|
||||
// Select
|
||||
entry! {action=SelectMessage::PointerMove { axis_align: KeyShift, snap_angle: KeyControl, center: KeyAlt }, message=InputMapperMessage::PointerMove},
|
||||
entry! {action=SelectMessage::DragStart { add_to_selection: KeyShift }, key_down=Lmb},
|
||||
entry! {action=SelectMessage::DragStop, key_up=Lmb},
|
||||
entry! {action=SelectMessage::EditLayer, message=InputMapperMessage::DoubleClick},
|
||||
entry! {action=SelectMessage::Abort, key_down=Rmb},
|
||||
entry! {action=SelectMessage::Abort, key_down=KeyEscape},
|
||||
entry! {action=SelectToolMessage::PointerMove { axis_align: KeyShift, snap_angle: KeyControl, center: KeyAlt }, message=InputMapperMessage::PointerMove},
|
||||
entry! {action=SelectToolMessage::DragStart { add_to_selection: KeyShift }, key_down=Lmb},
|
||||
entry! {action=SelectToolMessage::DragStop, key_up=Lmb},
|
||||
entry! {action=SelectToolMessage::EditLayer, message=InputMapperMessage::DoubleClick},
|
||||
entry! {action=SelectToolMessage::Abort, key_down=Rmb},
|
||||
entry! {action=SelectToolMessage::Abort, key_down=KeyEscape},
|
||||
// Crop
|
||||
entry! {action=CropMessage::PointerDown, key_down=Lmb},
|
||||
entry! {action=CropMessage::PointerMove { constrain_axis_or_aspect: KeyShift, center: KeyAlt }, message=InputMapperMessage::PointerMove},
|
||||
entry! {action=CropMessage::PointerUp, key_up=Lmb},
|
||||
entry! {action=CropMessage::DeleteSelected, key_down=KeyDelete},
|
||||
entry! {action=CropMessage::DeleteSelected, key_down=KeyBackspace},
|
||||
entry! {action=CropToolMessage::PointerDown, key_down=Lmb},
|
||||
entry! {action=CropToolMessage::PointerMove { constrain_axis_or_aspect: KeyShift, center: KeyAlt }, message=InputMapperMessage::PointerMove},
|
||||
entry! {action=CropToolMessage::PointerUp, key_up=Lmb},
|
||||
entry! {action=CropToolMessage::DeleteSelected, key_down=KeyDelete},
|
||||
entry! {action=CropToolMessage::DeleteSelected, key_down=KeyBackspace},
|
||||
// Navigate
|
||||
entry! {action=NavigateMessage::ClickZoom { zoom_in: false }, key_up=Lmb, modifiers=[KeyShift]},
|
||||
entry! {action=NavigateMessage::ClickZoom { zoom_in: true }, key_up=Lmb},
|
||||
entry! {action=NavigateMessage::PointerMove { snap_angle: KeyControl, snap_zoom: KeyControl }, message=InputMapperMessage::PointerMove},
|
||||
entry! {action=NavigateMessage::TranslateCanvasBegin, key_down=Mmb},
|
||||
entry! {action=NavigateMessage::RotateCanvasBegin, key_down=Rmb},
|
||||
entry! {action=NavigateMessage::ZoomCanvasBegin, key_down=Lmb},
|
||||
entry! {action=NavigateMessage::TransformCanvasEnd, key_up=Rmb},
|
||||
entry! {action=NavigateMessage::TransformCanvasEnd, key_up=Lmb},
|
||||
entry! {action=NavigateMessage::TransformCanvasEnd, key_up=Mmb},
|
||||
entry! {action=NavigateToolMessage::ClickZoom { zoom_in: false }, key_up=Lmb, modifiers=[KeyShift]},
|
||||
entry! {action=NavigateToolMessage::ClickZoom { zoom_in: true }, key_up=Lmb},
|
||||
entry! {action=NavigateToolMessage::PointerMove { snap_angle: KeyControl, snap_zoom: KeyControl }, message=InputMapperMessage::PointerMove},
|
||||
entry! {action=NavigateToolMessage::TranslateCanvasBegin, key_down=Mmb},
|
||||
entry! {action=NavigateToolMessage::RotateCanvasBegin, key_down=Rmb},
|
||||
entry! {action=NavigateToolMessage::ZoomCanvasBegin, key_down=Lmb},
|
||||
entry! {action=NavigateToolMessage::TransformCanvasEnd, key_up=Rmb},
|
||||
entry! {action=NavigateToolMessage::TransformCanvasEnd, key_up=Lmb},
|
||||
entry! {action=NavigateToolMessage::TransformCanvasEnd, key_up=Mmb},
|
||||
// Eyedropper
|
||||
entry! {action=EyedropperMessage::LeftMouseDown, key_down=Lmb},
|
||||
entry! {action=EyedropperMessage::RightMouseDown, key_down=Rmb},
|
||||
entry! {action=EyedropperToolMessage::LeftMouseDown, key_down=Lmb},
|
||||
entry! {action=EyedropperToolMessage::RightMouseDown, key_down=Rmb},
|
||||
// Text
|
||||
entry! {action=TextMessage::Interact, key_up=Lmb},
|
||||
entry! {action=TextMessage::Abort, key_down=KeyEscape},
|
||||
entry! {action=TextMessage::CommitText, key_down=KeyEnter, modifiers=[KeyControl]},
|
||||
// Rectangle
|
||||
entry! {action=RectangleMessage::DragStart, key_down=Lmb},
|
||||
entry! {action=RectangleMessage::DragStop, key_up=Lmb},
|
||||
entry! {action=RectangleMessage::Abort, key_down=Rmb},
|
||||
entry! {action=RectangleMessage::Abort, key_down=KeyEscape},
|
||||
entry! {action=RectangleMessage::Resize { center: KeyAlt, lock_ratio: KeyShift }, triggers=[KeyAlt, KeyShift]},
|
||||
entry! {action=RectangleToolMessage::DragStart, key_down=Lmb},
|
||||
entry! {action=RectangleToolMessage::DragStop, key_up=Lmb},
|
||||
entry! {action=RectangleToolMessage::Abort, key_down=Rmb},
|
||||
entry! {action=RectangleToolMessage::Abort, key_down=KeyEscape},
|
||||
entry! {action=RectangleToolMessage::Resize { center: KeyAlt, lock_ratio: KeyShift }, triggers=[KeyAlt, KeyShift]},
|
||||
// Ellipse
|
||||
entry! {action=EllipseMessage::DragStart, key_down=Lmb},
|
||||
entry! {action=EllipseMessage::DragStop, key_up=Lmb},
|
||||
entry! {action=EllipseMessage::Abort, key_down=Rmb},
|
||||
entry! {action=EllipseMessage::Abort, key_down=KeyEscape},
|
||||
entry! {action=EllipseMessage::Resize { center: KeyAlt, lock_ratio: KeyShift }, triggers=[KeyAlt, KeyShift]},
|
||||
entry! {action=EllipseToolMessage::DragStart, key_down=Lmb},
|
||||
entry! {action=EllipseToolMessage::DragStop, key_up=Lmb},
|
||||
entry! {action=EllipseToolMessage::Abort, key_down=Rmb},
|
||||
entry! {action=EllipseToolMessage::Abort, key_down=KeyEscape},
|
||||
entry! {action=EllipseToolMessage::Resize { center: KeyAlt, lock_ratio: KeyShift }, triggers=[KeyAlt, KeyShift]},
|
||||
// Shape
|
||||
entry! {action=ShapeMessage::DragStart, key_down=Lmb},
|
||||
entry! {action=ShapeMessage::DragStop, key_up=Lmb},
|
||||
entry! {action=ShapeMessage::Abort, key_down=Rmb},
|
||||
entry! {action=ShapeMessage::Abort, key_down=KeyEscape},
|
||||
entry! {action=ShapeMessage::Resize { center: KeyAlt, lock_ratio: KeyShift }, triggers=[KeyAlt, KeyShift]},
|
||||
entry! {action=ShapeToolMessage::DragStart, key_down=Lmb},
|
||||
entry! {action=ShapeToolMessage::DragStop, key_up=Lmb},
|
||||
entry! {action=ShapeToolMessage::Abort, key_down=Rmb},
|
||||
entry! {action=ShapeToolMessage::Abort, key_down=KeyEscape},
|
||||
entry! {action=ShapeToolMessage::Resize { center: KeyAlt, lock_ratio: KeyShift }, triggers=[KeyAlt, KeyShift]},
|
||||
// Line
|
||||
entry! {action=LineMessage::DragStart, key_down=Lmb},
|
||||
entry! {action=LineMessage::DragStop, key_up=Lmb},
|
||||
entry! {action=LineMessage::Abort, key_down=Rmb},
|
||||
entry! {action=LineMessage::Abort, key_down=KeyEscape},
|
||||
entry! {action=LineMessage::Redraw { center: KeyAlt, lock_angle: KeyControl, snap_angle: KeyShift }, triggers=[KeyAlt, KeyShift, KeyControl]},
|
||||
entry! {action=LineToolMessage::DragStart, key_down=Lmb},
|
||||
entry! {action=LineToolMessage::DragStop, key_up=Lmb},
|
||||
entry! {action=LineToolMessage::Abort, key_down=Rmb},
|
||||
entry! {action=LineToolMessage::Abort, key_down=KeyEscape},
|
||||
entry! {action=LineToolMessage::Redraw { center: KeyAlt, lock_angle: KeyControl, snap_angle: KeyShift }, triggers=[KeyAlt, KeyShift, KeyControl]},
|
||||
// Path
|
||||
entry! {action=PathMessage::DragStart { add_to_selection: KeyShift }, key_down=Lmb},
|
||||
entry! {action=PathMessage::PointerMove { alt_mirror_angle: KeyAlt, shift_mirror_distance: KeyShift }, message=InputMapperMessage::PointerMove},
|
||||
entry! {action=PathMessage::DragStop, key_up=Lmb},
|
||||
entry! {action=PathToolMessage::DragStart { add_to_selection: KeyShift }, key_down=Lmb},
|
||||
entry! {action=PathToolMessage::PointerMove { alt_mirror_angle: KeyAlt, shift_mirror_distance: KeyShift }, message=InputMapperMessage::PointerMove},
|
||||
entry! {action=PathToolMessage::DragStop, key_up=Lmb},
|
||||
// Pen
|
||||
entry! {action=PenMessage::PointerMove, message=InputMapperMessage::PointerMove},
|
||||
entry! {action=PenMessage::DragStart, key_down=Lmb},
|
||||
entry! {action=PenMessage::DragStop, key_up=Lmb},
|
||||
entry! {action=PenMessage::Confirm, key_down=Rmb},
|
||||
entry! {action=PenMessage::Confirm, key_down=KeyEscape},
|
||||
entry! {action=PenMessage::Confirm, key_down=KeyEnter},
|
||||
entry! {action=PenToolMessage::PointerMove, message=InputMapperMessage::PointerMove},
|
||||
entry! {action=PenToolMessage::DragStart, key_down=Lmb},
|
||||
entry! {action=PenToolMessage::DragStop, key_up=Lmb},
|
||||
entry! {action=PenToolMessage::Confirm, key_down=Rmb},
|
||||
entry! {action=PenToolMessage::Confirm, key_down=KeyEscape},
|
||||
entry! {action=PenToolMessage::Confirm, key_down=KeyEnter},
|
||||
// Freehand
|
||||
entry! {action=FreehandMessage::PointerMove, message=InputMapperMessage::PointerMove},
|
||||
entry! {action=FreehandMessage::DragStart, key_down=Lmb},
|
||||
entry! {action=FreehandMessage::DragStop, key_up=Lmb},
|
||||
entry! {action=FreehandToolMessage::PointerMove, message=InputMapperMessage::PointerMove},
|
||||
entry! {action=FreehandToolMessage::DragStart, key_down=Lmb},
|
||||
entry! {action=FreehandToolMessage::DragStop, key_up=Lmb},
|
||||
// Spline
|
||||
entry! {action=SplineMessage::PointerMove, message=InputMapperMessage::PointerMove},
|
||||
entry! {action=SplineMessage::DragStart, key_down=Lmb},
|
||||
entry! {action=SplineMessage::DragStop, key_up=Lmb},
|
||||
entry! {action=SplineMessage::Confirm, key_down=Rmb},
|
||||
entry! {action=SplineMessage::Confirm, key_down=KeyEscape},
|
||||
entry! {action=SplineMessage::Confirm, key_down=KeyEnter},
|
||||
entry! {action=SplineToolMessage::PointerMove, message=InputMapperMessage::PointerMove},
|
||||
entry! {action=SplineToolMessage::DragStart, key_down=Lmb},
|
||||
entry! {action=SplineToolMessage::DragStop, key_up=Lmb},
|
||||
entry! {action=SplineToolMessage::Confirm, key_down=Rmb},
|
||||
entry! {action=SplineToolMessage::Confirm, key_down=KeyEscape},
|
||||
entry! {action=SplineToolMessage::Confirm, key_down=KeyEnter},
|
||||
// Fill
|
||||
entry! {action=FillMessage::LeftMouseDown, key_down=Lmb},
|
||||
entry! {action=FillMessage::RightMouseDown, key_down=Rmb},
|
||||
entry! {action=FillToolMessage::LeftMouseDown, key_down=Lmb},
|
||||
entry! {action=FillToolMessage::RightMouseDown, key_down=Rmb},
|
||||
// Tool Actions
|
||||
entry! {action=ToolMessage::ActivateTool { tool_type: ToolType::Select }, key_down=KeyV},
|
||||
entry! {action=ToolMessage::ActivateTool { tool_type: ToolType::Navigate }, key_down=KeyZ},
|
||||
|
|
|
@ -72,20 +72,20 @@ pub mod message_prelude {
|
|||
pub use crate::layout::{LayoutMessage, LayoutMessageDiscriminant};
|
||||
pub use crate::misc::derivable_custom_traits::{ToDiscriminant, TransitiveChild};
|
||||
pub use crate::viewport_tools::tool_message::{ToolMessage, ToolMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::crop::{CropMessage, CropMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::ellipse::{EllipseMessage, EllipseMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::eyedropper::{EyedropperMessage, EyedropperMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::fill::{FillMessage, FillMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::freehand::{FreehandMessage, FreehandMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::line::{LineMessage, LineMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::navigate::{NavigateMessage, NavigateMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::path::{PathMessage, PathMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::pen::{PenMessage, PenMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::rectangle::{RectangleMessage, RectangleMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::select::{SelectMessage, SelectMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::shape::{ShapeMessage, ShapeMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::spline::{SplineMessage, SplineMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::text::{TextMessage, TextMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::crop_tool::{CropToolMessage, CropToolMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::ellipse_tool::{EllipseToolMessage, EllipseToolMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::eyedropper_tool::{EyedropperToolMessage, EyedropperToolMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::fill_tool::{FillToolMessage, FillToolMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::freehand_tool::{FreehandToolMessage, FreehandToolMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::line_tool::{LineToolMessage, LineToolMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::navigate_tool::{NavigateToolMessage, NavigateToolMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::path_tool::{PathToolMessage, PathToolMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::pen_tool::{PenToolMessage, PenToolMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::rectangle_tool::{RectangleToolMessage, RectangleToolMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::select_tool::{SelectToolMessage, SelectToolMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::shape_tool::{ShapeToolMessage, ShapeToolMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::spline_tool::{SplineToolMessage, SplineToolMessageDiscriminant};
|
||||
pub use crate::viewport_tools::tools::text_tool::{TextMessage, TextMessageDiscriminant};
|
||||
pub use graphite_proc_macros::*;
|
||||
|
||||
pub use std::collections::VecDeque;
|
||||
|
|
|
@ -77,12 +77,12 @@ impl Default for ToolFsmState {
|
|||
tool_data: ToolData {
|
||||
active_tool_type: ToolType::Select,
|
||||
tools: gen_tools_hash_map! {
|
||||
Select => select::Select,
|
||||
Crop => crop::Crop,
|
||||
Navigate => navigate::Navigate,
|
||||
Eyedropper => eyedropper::Eyedropper,
|
||||
Text => text::Text,
|
||||
Fill => fill::Fill,
|
||||
Select => select_tool::SelectTool,
|
||||
Crop => crop_tool::CropTool,
|
||||
Navigate => navigate_tool::NavigateTool,
|
||||
Eyedropper => eyedropper_tool::EyedropperTool,
|
||||
Text => text_tool::TextTool,
|
||||
Fill => fill_tool::FillTool,
|
||||
// Gradient => gradient::Gradient,
|
||||
// Brush => brush::Brush,
|
||||
// Heal => heal::Heal,
|
||||
|
@ -90,14 +90,14 @@ impl Default for ToolFsmState {
|
|||
// Patch => patch::Patch,
|
||||
// BlurSharpen => blursharpen::BlurSharpen,
|
||||
// Relight => relight::Relight,
|
||||
Path => path::Path,
|
||||
Pen => pen::Pen,
|
||||
Freehand => freehand::Freehand,
|
||||
Spline => spline::Spline,
|
||||
Line => line::Line,
|
||||
Rectangle => rectangle::Rectangle,
|
||||
Ellipse => ellipse::Ellipse,
|
||||
Shape => shape::Shape,
|
||||
Path => path_tool::PathTool,
|
||||
Pen => pen_tool::PenTool,
|
||||
Freehand => freehand_tool::FreehandTool,
|
||||
Spline => spline_tool::SplineTool,
|
||||
Line => line_tool::LineTool,
|
||||
Rectangle => rectangle_tool::RectangleTool,
|
||||
Ellipse => ellipse_tool::EllipseTool,
|
||||
Shape => shape_tool::ShapeTool,
|
||||
},
|
||||
},
|
||||
document_tool_data: DocumentToolData {
|
||||
|
@ -186,54 +186,54 @@ pub enum StandardToolMessageType {
|
|||
pub fn standard_tool_message(tool: ToolType, message_type: StandardToolMessageType) -> Option<ToolMessage> {
|
||||
match message_type {
|
||||
StandardToolMessageType::DocumentIsDirty => match tool {
|
||||
ToolType::Select => Some(SelectMessage::DocumentIsDirty.into()),
|
||||
ToolType::Crop => Some(CropMessage::DocumentIsDirty.into()),
|
||||
ToolType::Navigate => None, // Some(NavigateMessage::DocumentIsDirty.into()),
|
||||
ToolType::Eyedropper => None, // Some(EyedropperMessage::DocumentIsDirty.into()),
|
||||
ToolType::Select => Some(SelectToolMessage::DocumentIsDirty.into()),
|
||||
ToolType::Crop => Some(CropToolMessage::DocumentIsDirty.into()),
|
||||
ToolType::Navigate => None, // Some(NavigateToolMessage::DocumentIsDirty.into()),
|
||||
ToolType::Eyedropper => None, // Some(EyedropperToolMessage::DocumentIsDirty.into()),
|
||||
ToolType::Text => Some(TextMessage::DocumentIsDirty.into()),
|
||||
ToolType::Fill => None, // Some(FillMessage::DocumentIsDirty.into()),
|
||||
ToolType::Fill => None, // Some(FillToolMessage::DocumentIsDirty.into()),
|
||||
ToolType::Gradient => None, // Some(GradientMessage::DocumentIsDirty.into()),
|
||||
ToolType::Brush => None, // Some(BrushMessage::DocumentIsDirty.into()),
|
||||
ToolType::Heal => None, // Some(HealMessage::DocumentIsDirty.into()),
|
||||
ToolType::Clone => None, // Some(CloneMessage::DocumentIsDirty.into()),
|
||||
ToolType::Patch => None, // Some(PatchMessage::DocumentIsDirty.into()),
|
||||
ToolType::BlurSharpen => None, // Some(BlurSharpenMessage::DocumentIsDirty.into()),
|
||||
ToolType::BlurSharpen => None, // Some(BlurSharPenToolMessage::DocumentIsDirty.into()),
|
||||
ToolType::Relight => None, // Some(RelightMessage::DocumentIsDirty.into()),
|
||||
ToolType::Path => Some(PathMessage::DocumentIsDirty.into()),
|
||||
ToolType::Pen => Some(PenMessage::DocumentIsDirty.into()),
|
||||
ToolType::Freehand => None, // Some(FreehandMessage::DocumentIsDirty.into()),
|
||||
ToolType::Spline => None, // Some(SplineMessage::DocumentIsDirty.into()),
|
||||
ToolType::Line => None, // Some(LineMessage::DocumentIsDirty.into()),
|
||||
ToolType::Rectangle => None, // Some(RectangleMessage::DocumentIsDirty.into()),
|
||||
ToolType::Ellipse => None, // Some(EllipseMessage::DocumentIsDirty.into()),
|
||||
ToolType::Shape => None, // Some(ShapeMessage::DocumentIsDirty.into()),
|
||||
ToolType::Path => Some(PathToolMessage::DocumentIsDirty.into()),
|
||||
ToolType::Pen => Some(PenToolMessage::DocumentIsDirty.into()),
|
||||
ToolType::Freehand => None, // Some(FreehandToolMessage::DocumentIsDirty.into()),
|
||||
ToolType::Spline => None, // Some(SplineToolMessage::DocumentIsDirty.into()),
|
||||
ToolType::Line => None, // Some(LineToolMessage::DocumentIsDirty.into()),
|
||||
ToolType::Rectangle => None, // Some(RectangleToolMessage::DocumentIsDirty.into()),
|
||||
ToolType::Ellipse => None, // Some(EllipseToolMessage::DocumentIsDirty.into()),
|
||||
ToolType::Shape => None, // Some(ShapeToolMessage::DocumentIsDirty.into()),
|
||||
},
|
||||
StandardToolMessageType::Abort => match tool {
|
||||
ToolType::Select => Some(SelectMessage::Abort.into()),
|
||||
ToolType::Crop => Some(CropMessage::Abort.into()),
|
||||
ToolType::Navigate => Some(NavigateMessage::Abort.into()),
|
||||
ToolType::Eyedropper => Some(EyedropperMessage::Abort.into()),
|
||||
ToolType::Select => Some(SelectToolMessage::Abort.into()),
|
||||
ToolType::Crop => Some(CropToolMessage::Abort.into()),
|
||||
ToolType::Navigate => Some(NavigateToolMessage::Abort.into()),
|
||||
ToolType::Eyedropper => Some(EyedropperToolMessage::Abort.into()),
|
||||
ToolType::Text => Some(TextMessage::Abort.into()),
|
||||
ToolType::Fill => Some(FillMessage::Abort.into()),
|
||||
ToolType::Fill => Some(FillToolMessage::Abort.into()),
|
||||
// ToolType::Gradient => Some(GradientMessage::Abort.into()),
|
||||
// ToolType::Brush => Some(BrushMessage::Abort.into()),
|
||||
// ToolType::Heal => Some(HealMessage::Abort.into()),
|
||||
// ToolType::Clone => Some(CloneMessage::Abort.into()),
|
||||
// ToolType::Patch => Some(PatchMessage::Abort.into()),
|
||||
// ToolType::BlurSharpen => Some(BlurSharpenMessage::Abort.into()),
|
||||
// ToolType::BlurSharpen => Some(BlurSharPenToolMessage::Abort.into()),
|
||||
// ToolType::Relight => Some(RelightMessage::Abort.into()),
|
||||
ToolType::Path => Some(PathMessage::Abort.into()),
|
||||
ToolType::Pen => Some(PenMessage::Abort.into()),
|
||||
ToolType::Freehand => Some(FreehandMessage::Abort.into()),
|
||||
ToolType::Spline => Some(SplineMessage::Abort.into()),
|
||||
ToolType::Line => Some(LineMessage::Abort.into()),
|
||||
ToolType::Rectangle => Some(RectangleMessage::Abort.into()),
|
||||
ToolType::Ellipse => Some(EllipseMessage::Abort.into()),
|
||||
ToolType::Shape => Some(ShapeMessage::Abort.into()),
|
||||
ToolType::Path => Some(PathToolMessage::Abort.into()),
|
||||
ToolType::Pen => Some(PenToolMessage::Abort.into()),
|
||||
ToolType::Freehand => Some(FreehandToolMessage::Abort.into()),
|
||||
ToolType::Spline => Some(SplineToolMessage::Abort.into()),
|
||||
ToolType::Line => Some(LineToolMessage::Abort.into()),
|
||||
ToolType::Rectangle => Some(RectangleToolMessage::Abort.into()),
|
||||
ToolType::Ellipse => Some(EllipseToolMessage::Abort.into()),
|
||||
ToolType::Shape => Some(ShapeToolMessage::Abort.into()),
|
||||
_ => None,
|
||||
},
|
||||
StandardToolMessageType::SelectionChanged => match tool {
|
||||
ToolType::Path => Some(PathMessage::SelectionChanged.into()),
|
||||
ToolType::Path => Some(PathToolMessage::SelectionChanged.into()),
|
||||
_ => None,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -12,16 +12,16 @@ pub enum ToolMessage {
|
|||
// Sub-messages
|
||||
#[remain::unsorted]
|
||||
#[child]
|
||||
Select(SelectMessage),
|
||||
Select(SelectToolMessage),
|
||||
#[remain::unsorted]
|
||||
#[child]
|
||||
Crop(CropMessage),
|
||||
Crop(CropToolMessage),
|
||||
#[remain::unsorted]
|
||||
#[child]
|
||||
Navigate(NavigateMessage),
|
||||
Navigate(NavigateToolMessage),
|
||||
#[remain::unsorted]
|
||||
#[child]
|
||||
Eyedropper(EyedropperMessage),
|
||||
Eyedropper(EyedropperToolMessage),
|
||||
// #[remain::unsorted]
|
||||
// #[child]
|
||||
// Text(TextMessage),
|
||||
|
@ -30,7 +30,7 @@ pub enum ToolMessage {
|
|||
Text(TextMessage),
|
||||
#[remain::unsorted]
|
||||
#[child]
|
||||
Fill(FillMessage),
|
||||
Fill(FillToolMessage),
|
||||
// #[remain::unsorted]
|
||||
// #[child]
|
||||
// Gradient(GradientMessage),
|
||||
|
@ -54,28 +54,28 @@ pub enum ToolMessage {
|
|||
// Relight(RelightMessage),
|
||||
#[remain::unsorted]
|
||||
#[child]
|
||||
Path(PathMessage),
|
||||
Path(PathToolMessage),
|
||||
#[remain::unsorted]
|
||||
#[child]
|
||||
Pen(PenMessage),
|
||||
Pen(PenToolMessage),
|
||||
#[remain::unsorted]
|
||||
#[child]
|
||||
Freehand(FreehandMessage),
|
||||
Freehand(FreehandToolMessage),
|
||||
#[remain::unsorted]
|
||||
#[child]
|
||||
Spline(SplineMessage),
|
||||
Spline(SplineToolMessage),
|
||||
#[remain::unsorted]
|
||||
#[child]
|
||||
Line(LineMessage),
|
||||
Line(LineToolMessage),
|
||||
#[remain::unsorted]
|
||||
#[child]
|
||||
Rectangle(RectangleMessage),
|
||||
Rectangle(RectangleToolMessage),
|
||||
#[remain::unsorted]
|
||||
#[child]
|
||||
Ellipse(EllipseMessage),
|
||||
Ellipse(EllipseToolMessage),
|
||||
#[remain::unsorted]
|
||||
#[child]
|
||||
Shape(ShapeMessage),
|
||||
Shape(ShapeToolMessage),
|
||||
|
||||
// Messages
|
||||
#[remain::unsorted]
|
||||
|
|
|
@ -17,7 +17,7 @@ use glam::{DVec2, Vec2Swizzles};
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Crop {
|
||||
pub struct CropTool {
|
||||
fsm_state: CropToolFsmState,
|
||||
data: CropToolData,
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ pub struct Crop {
|
|||
#[remain::sorted]
|
||||
#[impl_message(Message, ToolMessage, Crop)]
|
||||
#[derive(PartialEq, Clone, Debug, Hash, Serialize, Deserialize)]
|
||||
pub enum CropMessage {
|
||||
pub enum CropToolMessage {
|
||||
// Standard messages
|
||||
#[remain::unsorted]
|
||||
Abort,
|
||||
|
@ -42,7 +42,7 @@ pub enum CropMessage {
|
|||
PointerUp,
|
||||
}
|
||||
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Crop {
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for CropTool {
|
||||
fn process_action(&mut self, action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque<Message>) {
|
||||
if action == ToolMessage::UpdateHints {
|
||||
self.fsm_state.update_hints(responses);
|
||||
|
@ -62,10 +62,10 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Crop {
|
|||
}
|
||||
}
|
||||
|
||||
advertise_actions!(CropMessageDiscriminant; PointerDown, PointerUp, PointerMove, DeleteSelected, Abort);
|
||||
advertise_actions!(CropToolMessageDiscriminant; PointerDown, PointerUp, PointerMove, DeleteSelected, Abort);
|
||||
}
|
||||
|
||||
impl PropertyHolder for Crop {}
|
||||
impl PropertyHolder for CropTool {}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
enum CropToolFsmState {
|
||||
|
@ -107,7 +107,7 @@ impl Fsm for CropToolFsmState {
|
|||
) -> Self {
|
||||
if let ToolMessage::Crop(event) = event {
|
||||
match (self, event) {
|
||||
(CropToolFsmState::Ready | CropToolFsmState::ResizingBounds | CropToolFsmState::Dragging, CropMessage::DocumentIsDirty) => {
|
||||
(CropToolFsmState::Ready | CropToolFsmState::ResizingBounds | CropToolFsmState::Dragging, CropToolMessage::DocumentIsDirty) => {
|
||||
let mut buffer = Vec::new();
|
||||
match (
|
||||
data.selected_board.map(|path| document.artboard_bounding_box_and_transform(&[path])).unwrap_or(None),
|
||||
|
@ -131,7 +131,7 @@ impl Fsm for CropToolFsmState {
|
|||
buffer.into_iter().rev().for_each(|message| responses.push_front(message));
|
||||
self
|
||||
}
|
||||
(CropToolFsmState::Ready, CropMessage::PointerDown) => {
|
||||
(CropToolFsmState::Ready, CropToolMessage::PointerDown) => {
|
||||
data.drag_start = input.mouse.position;
|
||||
data.drag_current = input.mouse.position;
|
||||
|
||||
|
@ -188,7 +188,7 @@ impl Fsm for CropToolFsmState {
|
|||
}
|
||||
}
|
||||
}
|
||||
(CropToolFsmState::ResizingBounds, CropMessage::PointerMove { constrain_axis_or_aspect, center }) => {
|
||||
(CropToolFsmState::ResizingBounds, CropToolMessage::PointerMove { constrain_axis_or_aspect, center }) => {
|
||||
if let Some(bounds) = &data.bounding_box_overlays {
|
||||
if let Some(movement) = &bounds.selected_edges {
|
||||
let from_center = input.keyboard.get(center as usize);
|
||||
|
@ -214,7 +214,7 @@ impl Fsm for CropToolFsmState {
|
|||
}
|
||||
CropToolFsmState::ResizingBounds
|
||||
}
|
||||
(CropToolFsmState::Dragging, CropMessage::PointerMove { constrain_axis_or_aspect, .. }) => {
|
||||
(CropToolFsmState::Dragging, CropToolMessage::PointerMove { constrain_axis_or_aspect, .. }) => {
|
||||
if let Some(bounds) = &data.bounding_box_overlays {
|
||||
let axis_align = input.keyboard.get(constrain_axis_or_aspect as usize);
|
||||
|
||||
|
@ -243,7 +243,7 @@ impl Fsm for CropToolFsmState {
|
|||
}
|
||||
CropToolFsmState::Dragging
|
||||
}
|
||||
(CropToolFsmState::Drawing, CropMessage::PointerMove { constrain_axis_or_aspect, center }) => {
|
||||
(CropToolFsmState::Drawing, CropToolMessage::PointerMove { constrain_axis_or_aspect, center }) => {
|
||||
let mouse_position = input.mouse.position;
|
||||
let snapped_mouse_position = data.snap_handler.snap_position(responses, input.viewport_bounds.size(), document, mouse_position);
|
||||
|
||||
|
@ -277,7 +277,7 @@ impl Fsm for CropToolFsmState {
|
|||
|
||||
CropToolFsmState::Drawing
|
||||
}
|
||||
(CropToolFsmState::Ready, CropMessage::PointerMove { .. }) => {
|
||||
(CropToolFsmState::Ready, CropToolMessage::PointerMove { .. }) => {
|
||||
let cursor = data.bounding_box_overlays.as_ref().map_or(MouseCursorIcon::Default, |bounds| bounds.get_cursor(input, false));
|
||||
|
||||
if data.cursor != cursor {
|
||||
|
@ -287,7 +287,7 @@ impl Fsm for CropToolFsmState {
|
|||
|
||||
CropToolFsmState::Ready
|
||||
}
|
||||
(CropToolFsmState::ResizingBounds, CropMessage::PointerUp) => {
|
||||
(CropToolFsmState::ResizingBounds, CropToolMessage::PointerUp) => {
|
||||
data.snap_handler.cleanup(responses);
|
||||
|
||||
if let Some(bounds) = &mut data.bounding_box_overlays {
|
||||
|
@ -296,7 +296,7 @@ impl Fsm for CropToolFsmState {
|
|||
|
||||
CropToolFsmState::Ready
|
||||
}
|
||||
(CropToolFsmState::Drawing, CropMessage::PointerUp) => {
|
||||
(CropToolFsmState::Drawing, CropToolMessage::PointerUp) => {
|
||||
data.snap_handler.cleanup(responses);
|
||||
|
||||
if let Some(bounds) = &mut data.bounding_box_overlays {
|
||||
|
@ -307,7 +307,7 @@ impl Fsm for CropToolFsmState {
|
|||
|
||||
CropToolFsmState::Ready
|
||||
}
|
||||
(CropToolFsmState::Dragging, CropMessage::PointerUp) => {
|
||||
(CropToolFsmState::Dragging, CropToolMessage::PointerUp) => {
|
||||
data.snap_handler.cleanup(responses);
|
||||
|
||||
if let Some(bounds) = &mut data.bounding_box_overlays {
|
||||
|
@ -316,14 +316,14 @@ impl Fsm for CropToolFsmState {
|
|||
|
||||
CropToolFsmState::Ready
|
||||
}
|
||||
(_, CropMessage::DeleteSelected) => {
|
||||
(_, CropToolMessage::DeleteSelected) => {
|
||||
if let Some(artboard) = data.selected_board.take() {
|
||||
responses.push_back(ArtboardMessage::DeleteArtboard { artboard }.into());
|
||||
responses.push_back(ToolMessage::DocumentIsDirty.into());
|
||||
}
|
||||
CropToolFsmState::Ready
|
||||
}
|
||||
(_, CropMessage::Abort) => {
|
||||
(_, CropToolMessage::Abort) => {
|
||||
if let Some(bounding_box_overlays) = data.bounding_box_overlays.take() {
|
||||
bounding_box_overlays.delete(responses);
|
||||
}
|
|
@ -16,7 +16,7 @@ use glam::DAffine2;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Ellipse {
|
||||
pub struct EllipseTool {
|
||||
fsm_state: EllipseToolFsmState,
|
||||
data: EllipseToolData,
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ pub struct Ellipse {
|
|||
#[remain::sorted]
|
||||
#[impl_message(Message, ToolMessage, Ellipse)]
|
||||
#[derive(PartialEq, Clone, Debug, Hash, Serialize, Deserialize)]
|
||||
pub enum EllipseMessage {
|
||||
pub enum EllipseToolMessage {
|
||||
// Standard messages
|
||||
#[remain::unsorted]
|
||||
Abort,
|
||||
|
@ -38,9 +38,9 @@ pub enum EllipseMessage {
|
|||
},
|
||||
}
|
||||
|
||||
impl PropertyHolder for Ellipse {}
|
||||
impl PropertyHolder for EllipseTool {}
|
||||
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Ellipse {
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for EllipseTool {
|
||||
fn process_action(&mut self, action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque<Message>) {
|
||||
if action == ToolMessage::UpdateHints {
|
||||
self.fsm_state.update_hints(responses);
|
||||
|
@ -65,8 +65,8 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Ellipse {
|
|||
use EllipseToolFsmState::*;
|
||||
|
||||
match self.fsm_state {
|
||||
Ready => actions!(EllipseMessageDiscriminant; DragStart),
|
||||
Drawing => actions!(EllipseMessageDiscriminant; DragStop, Abort, Resize),
|
||||
Ready => actions!(EllipseToolMessageDiscriminant; DragStart),
|
||||
Drawing => actions!(EllipseToolMessageDiscriminant; DragStop, Abort, Resize),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,8 +102,8 @@ impl Fsm for EllipseToolFsmState {
|
|||
input: &InputPreprocessorMessageHandler,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) -> Self {
|
||||
use EllipseMessage::*;
|
||||
use EllipseToolFsmState::*;
|
||||
use EllipseToolMessage::*;
|
||||
|
||||
let mut shape_data = &mut data.data;
|
||||
|
|
@ -15,7 +15,7 @@ use glam::DVec2;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Eyedropper {
|
||||
pub struct EyedropperTool {
|
||||
fsm_state: EyedropperToolFsmState,
|
||||
data: EyedropperToolData,
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ pub struct Eyedropper {
|
|||
#[remain::sorted]
|
||||
#[impl_message(Message, ToolMessage, Eyedropper)]
|
||||
#[derive(PartialEq, Clone, Debug, Hash, Serialize, Deserialize)]
|
||||
pub enum EyedropperMessage {
|
||||
pub enum EyedropperToolMessage {
|
||||
// Standard messages
|
||||
#[remain::unsorted]
|
||||
Abort,
|
||||
|
@ -33,9 +33,9 @@ pub enum EyedropperMessage {
|
|||
RightMouseDown,
|
||||
}
|
||||
|
||||
impl PropertyHolder for Eyedropper {}
|
||||
impl PropertyHolder for EyedropperTool {}
|
||||
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Eyedropper {
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for EyedropperTool {
|
||||
fn process_action(&mut self, action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque<Message>) {
|
||||
if action == ToolMessage::UpdateHints {
|
||||
self.fsm_state.update_hints(responses);
|
||||
|
@ -56,7 +56,7 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Eyedropper {
|
|||
}
|
||||
}
|
||||
|
||||
advertise_actions!(EyedropperMessageDiscriminant; LeftMouseDown, RightMouseDown);
|
||||
advertise_actions!(EyedropperToolMessageDiscriminant; LeftMouseDown, RightMouseDown);
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
|
@ -87,8 +87,8 @@ impl Fsm for EyedropperToolFsmState {
|
|||
input: &InputPreprocessorMessageHandler,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) -> Self {
|
||||
use EyedropperMessage::*;
|
||||
use EyedropperToolFsmState::*;
|
||||
use EyedropperToolMessage::*;
|
||||
|
||||
if let ToolMessage::Eyedropper(event) = event {
|
||||
match (self, event) {
|
||||
|
@ -103,8 +103,8 @@ impl Fsm for EyedropperToolFsmState {
|
|||
if let LayerDataType::Shape(shape) = &layer.data {
|
||||
if let Some(fill) = shape.style.fill() {
|
||||
match lmb_or_rmb {
|
||||
EyedropperMessage::LeftMouseDown => responses.push_back(ToolMessage::SelectPrimaryColor { color: fill.color() }.into()),
|
||||
EyedropperMessage::RightMouseDown => responses.push_back(ToolMessage::SelectSecondaryColor { color: fill.color() }.into()),
|
||||
EyedropperToolMessage::LeftMouseDown => responses.push_back(ToolMessage::SelectPrimaryColor { color: fill.color() }.into()),
|
||||
EyedropperToolMessage::RightMouseDown => responses.push_back(ToolMessage::SelectSecondaryColor { color: fill.color() }.into()),
|
||||
_ => {}
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ use glam::DVec2;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Fill {
|
||||
pub struct FillTool {
|
||||
fsm_state: FillToolFsmState,
|
||||
data: FillToolData,
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ pub struct Fill {
|
|||
#[remain::sorted]
|
||||
#[impl_message(Message, ToolMessage, Fill)]
|
||||
#[derive(PartialEq, Clone, Debug, Hash, Serialize, Deserialize)]
|
||||
pub enum FillMessage {
|
||||
pub enum FillToolMessage {
|
||||
// Standard messages
|
||||
#[remain::unsorted]
|
||||
Abort,
|
||||
|
@ -33,9 +33,9 @@ pub enum FillMessage {
|
|||
RightMouseDown,
|
||||
}
|
||||
|
||||
impl PropertyHolder for Fill {}
|
||||
impl PropertyHolder for FillTool {}
|
||||
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Fill {
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for FillTool {
|
||||
fn process_action(&mut self, action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque<Message>) {
|
||||
if action == ToolMessage::UpdateHints {
|
||||
self.fsm_state.update_hints(responses);
|
||||
|
@ -56,7 +56,7 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Fill {
|
|||
}
|
||||
}
|
||||
|
||||
advertise_actions!(FillMessageDiscriminant; LeftMouseDown, RightMouseDown);
|
||||
advertise_actions!(FillToolMessageDiscriminant; LeftMouseDown, RightMouseDown);
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
|
@ -87,8 +87,8 @@ impl Fsm for FillToolFsmState {
|
|||
input: &InputPreprocessorMessageHandler,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) -> Self {
|
||||
use FillMessage::*;
|
||||
use FillToolFsmState::*;
|
||||
use FillToolMessage::*;
|
||||
|
||||
if let ToolMessage::Fill(event) = event {
|
||||
match (self, event) {
|
|
@ -14,7 +14,7 @@ use glam::{DAffine2, DVec2};
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Freehand {
|
||||
pub struct FreehandTool {
|
||||
fsm_state: FreehandToolFsmState,
|
||||
data: FreehandToolData,
|
||||
options: FreehandOptions,
|
||||
|
@ -33,7 +33,7 @@ impl Default for FreehandOptions {
|
|||
#[remain::sorted]
|
||||
#[impl_message(Message, ToolMessage, Freehand)]
|
||||
#[derive(PartialEq, Clone, Debug, Hash, Serialize, Deserialize)]
|
||||
pub enum FreehandMessage {
|
||||
pub enum FreehandToolMessage {
|
||||
// Standard messages
|
||||
#[remain::unsorted]
|
||||
Abort,
|
||||
|
@ -42,12 +42,12 @@ pub enum FreehandMessage {
|
|||
DragStart,
|
||||
DragStop,
|
||||
PointerMove,
|
||||
UpdateOptions(FreehandMessageOptionsUpdate),
|
||||
UpdateOptions(FreehandToolMessageOptionsUpdate),
|
||||
}
|
||||
|
||||
#[remain::sorted]
|
||||
#[derive(PartialEq, Clone, Debug, Hash, Serialize, Deserialize)]
|
||||
pub enum FreehandMessageOptionsUpdate {
|
||||
pub enum FreehandToolMessageOptionsUpdate {
|
||||
LineWeight(u32),
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ enum FreehandToolFsmState {
|
|||
Drawing,
|
||||
}
|
||||
|
||||
impl PropertyHolder for Freehand {
|
||||
impl PropertyHolder for FreehandTool {
|
||||
fn properties(&self) -> WidgetLayout {
|
||||
WidgetLayout::new(vec![LayoutRow::Row {
|
||||
name: "".into(),
|
||||
|
@ -67,14 +67,14 @@ impl PropertyHolder for Freehand {
|
|||
value: self.options.line_weight as f64,
|
||||
is_integer: true,
|
||||
min: Some(1.),
|
||||
on_update: WidgetCallback::new(|number_input| FreehandMessage::UpdateOptions(FreehandMessageOptionsUpdate::LineWeight(number_input.value as u32)).into()),
|
||||
on_update: WidgetCallback::new(|number_input| FreehandToolMessage::UpdateOptions(FreehandToolMessageOptionsUpdate::LineWeight(number_input.value as u32)).into()),
|
||||
..NumberInput::default()
|
||||
}))],
|
||||
}])
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Freehand {
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for FreehandTool {
|
||||
fn process_action(&mut self, action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque<Message>) {
|
||||
if action == ToolMessage::UpdateHints {
|
||||
self.fsm_state.update_hints(responses);
|
||||
|
@ -86,9 +86,9 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Freehand {
|
|||
return;
|
||||
}
|
||||
|
||||
if let ToolMessage::Freehand(FreehandMessage::UpdateOptions(action)) = action {
|
||||
if let ToolMessage::Freehand(FreehandToolMessage::UpdateOptions(action)) = action {
|
||||
match action {
|
||||
FreehandMessageOptionsUpdate::LineWeight(line_weight) => self.options.line_weight = line_weight,
|
||||
FreehandToolMessageOptionsUpdate::LineWeight(line_weight) => self.options.line_weight = line_weight,
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -106,8 +106,8 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Freehand {
|
|||
use FreehandToolFsmState::*;
|
||||
|
||||
match self.fsm_state {
|
||||
Ready => actions!(FreehandMessageDiscriminant; DragStart, DragStop, Abort),
|
||||
Drawing => actions!(FreehandMessageDiscriminant; DragStop, PointerMove, Abort),
|
||||
Ready => actions!(FreehandToolMessageDiscriminant; DragStart, DragStop, Abort),
|
||||
Drawing => actions!(FreehandToolMessageDiscriminant; DragStop, PointerMove, Abort),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -138,8 +138,8 @@ impl Fsm for FreehandToolFsmState {
|
|||
input: &InputPreprocessorMessageHandler,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) -> Self {
|
||||
use FreehandMessage::*;
|
||||
use FreehandToolFsmState::*;
|
||||
use FreehandToolMessage::*;
|
||||
|
||||
let transform = document.graphene_document.root.transform;
|
||||
|
|
@ -17,7 +17,7 @@ use glam::{DAffine2, DVec2};
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Line {
|
||||
pub struct LineTool {
|
||||
fsm_state: LineToolFsmState,
|
||||
data: LineToolData,
|
||||
options: LineOptions,
|
||||
|
@ -36,7 +36,7 @@ impl Default for LineOptions {
|
|||
#[remain::sorted]
|
||||
#[impl_message(Message, ToolMessage, Line)]
|
||||
#[derive(PartialEq, Clone, Debug, Hash, Serialize, Deserialize)]
|
||||
pub enum LineMessage {
|
||||
pub enum LineToolMessage {
|
||||
// Standard messages
|
||||
#[remain::unsorted]
|
||||
Abort,
|
||||
|
@ -58,7 +58,7 @@ pub enum LineOptionsUpdate {
|
|||
LineWeight(u32),
|
||||
}
|
||||
|
||||
impl PropertyHolder for Line {
|
||||
impl PropertyHolder for LineTool {
|
||||
fn properties(&self) -> WidgetLayout {
|
||||
WidgetLayout::new(vec![LayoutRow::Row {
|
||||
name: "".into(),
|
||||
|
@ -68,14 +68,14 @@ impl PropertyHolder for Line {
|
|||
value: self.options.line_weight as f64,
|
||||
is_integer: true,
|
||||
min: Some(0.),
|
||||
on_update: WidgetCallback::new(|number_input| LineMessage::UpdateOptions(LineOptionsUpdate::LineWeight(number_input.value as u32)).into()),
|
||||
on_update: WidgetCallback::new(|number_input| LineToolMessage::UpdateOptions(LineOptionsUpdate::LineWeight(number_input.value as u32)).into()),
|
||||
..NumberInput::default()
|
||||
}))],
|
||||
}])
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Line {
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for LineTool {
|
||||
fn process_action(&mut self, action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque<Message>) {
|
||||
if action == ToolMessage::UpdateHints {
|
||||
self.fsm_state.update_hints(responses);
|
||||
|
@ -87,7 +87,7 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Line {
|
|||
return;
|
||||
}
|
||||
|
||||
if let ToolMessage::Line(LineMessage::UpdateOptions(action)) = action {
|
||||
if let ToolMessage::Line(LineToolMessage::UpdateOptions(action)) = action {
|
||||
match action {
|
||||
LineOptionsUpdate::LineWeight(line_weight) => self.options.line_weight = line_weight,
|
||||
}
|
||||
|
@ -107,8 +107,8 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Line {
|
|||
use LineToolFsmState::*;
|
||||
|
||||
match self.fsm_state {
|
||||
Ready => actions!(LineMessageDiscriminant; DragStart),
|
||||
Drawing => actions!(LineMessageDiscriminant; DragStop, Redraw, Abort),
|
||||
Ready => actions!(LineToolMessageDiscriminant; DragStart),
|
||||
Drawing => actions!(LineToolMessageDiscriminant; DragStop, Redraw, Abort),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -149,8 +149,8 @@ impl Fsm for LineToolFsmState {
|
|||
input: &InputPreprocessorMessageHandler,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) -> Self {
|
||||
use LineMessage::*;
|
||||
use LineToolFsmState::*;
|
||||
use LineToolMessage::*;
|
||||
|
||||
if let ToolMessage::Line(event) = event {
|
||||
match (self, event) {
|
|
@ -1,15 +1,15 @@
|
|||
pub mod crop;
|
||||
pub mod ellipse;
|
||||
pub mod eyedropper;
|
||||
pub mod fill;
|
||||
pub mod freehand;
|
||||
pub mod line;
|
||||
pub mod navigate;
|
||||
pub mod path;
|
||||
pub mod pen;
|
||||
pub mod rectangle;
|
||||
pub mod select;
|
||||
pub mod shape;
|
||||
pub mod crop_tool;
|
||||
pub mod ellipse_tool;
|
||||
pub mod eyedropper_tool;
|
||||
pub mod fill_tool;
|
||||
pub mod freehand_tool;
|
||||
pub mod line_tool;
|
||||
pub mod navigate_tool;
|
||||
pub mod path_tool;
|
||||
pub mod pen_tool;
|
||||
pub mod rectangle_tool;
|
||||
pub mod select_tool;
|
||||
pub mod shape_tool;
|
||||
pub mod shared;
|
||||
pub mod spline;
|
||||
pub mod text;
|
||||
pub mod spline_tool;
|
||||
pub mod text_tool;
|
||||
|
|
|
@ -11,7 +11,7 @@ use glam::DVec2;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Navigate {
|
||||
pub struct NavigateTool {
|
||||
fsm_state: NavigateToolFsmState,
|
||||
data: NavigateToolData,
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ pub struct Navigate {
|
|||
#[remain::sorted]
|
||||
#[impl_message(Message, ToolMessage, Navigate)]
|
||||
#[derive(PartialEq, Clone, Debug, Hash, Serialize, Deserialize)]
|
||||
pub enum NavigateMessage {
|
||||
pub enum NavigateToolMessage {
|
||||
// Standard messages
|
||||
#[remain::unsorted]
|
||||
Abort,
|
||||
|
@ -38,9 +38,9 @@ pub enum NavigateMessage {
|
|||
ZoomCanvasBegin,
|
||||
}
|
||||
|
||||
impl PropertyHolder for Navigate {}
|
||||
impl PropertyHolder for NavigateTool {}
|
||||
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Navigate {
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for NavigateTool {
|
||||
fn process_action(&mut self, action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque<Message>) {
|
||||
if action == ToolMessage::UpdateHints {
|
||||
self.fsm_state.update_hints(responses);
|
||||
|
@ -65,8 +65,8 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Navigate {
|
|||
use NavigateToolFsmState::*;
|
||||
|
||||
match self.fsm_state {
|
||||
Ready => actions!(NavigateMessageDiscriminant; TranslateCanvasBegin, RotateCanvasBegin, ZoomCanvasBegin),
|
||||
_ => actions!(NavigateMessageDiscriminant; ClickZoom, PointerMove, TransformCanvasEnd),
|
||||
Ready => actions!(NavigateToolMessageDiscriminant; TranslateCanvasBegin, RotateCanvasBegin, ZoomCanvasBegin),
|
||||
_ => actions!(NavigateToolMessageDiscriminant; ClickZoom, PointerMove, TransformCanvasEnd),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ impl Fsm for NavigateToolFsmState {
|
|||
messages: &mut VecDeque<Message>,
|
||||
) -> Self {
|
||||
if let ToolMessage::Navigate(navigate) = message {
|
||||
use NavigateMessage::*;
|
||||
use NavigateToolMessage::*;
|
||||
|
||||
match navigate {
|
||||
ClickZoom { zoom_in } => {
|
|
@ -16,7 +16,7 @@ use glam::DVec2;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Path {
|
||||
pub struct PathTool {
|
||||
fsm_state: PathToolFsmState,
|
||||
data: PathToolData,
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ pub struct Path {
|
|||
#[remain::sorted]
|
||||
#[impl_message(Message, ToolMessage, Path)]
|
||||
#[derive(PartialEq, Clone, Debug, Hash, Serialize, Deserialize)]
|
||||
pub enum PathMessage {
|
||||
pub enum PathToolMessage {
|
||||
// Standard messages
|
||||
#[remain::unsorted]
|
||||
Abort,
|
||||
|
@ -44,9 +44,9 @@ pub enum PathMessage {
|
|||
},
|
||||
}
|
||||
|
||||
impl PropertyHolder for Path {}
|
||||
impl PropertyHolder for PathTool {}
|
||||
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Path {
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for PathTool {
|
||||
fn process_action(&mut self, action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque<Message>) {
|
||||
if action == ToolMessage::UpdateHints {
|
||||
self.fsm_state.update_hints(responses);
|
||||
|
@ -72,8 +72,8 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Path {
|
|||
use PathToolFsmState::*;
|
||||
|
||||
match self.fsm_state {
|
||||
Ready => actions!(PathMessageDiscriminant; DragStart),
|
||||
Dragging => actions!(PathMessageDiscriminant; DragStop, PointerMove),
|
||||
Ready => actions!(PathToolMessageDiscriminant; DragStart),
|
||||
Dragging => actions!(PathToolMessageDiscriminant; DragStop, PointerMove),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -115,8 +115,8 @@ impl Fsm for PathToolFsmState {
|
|||
responses: &mut VecDeque<Message>,
|
||||
) -> Self {
|
||||
if let ToolMessage::Path(event) = event {
|
||||
use PathMessage::*;
|
||||
use PathToolFsmState::*;
|
||||
use PathToolMessage::*;
|
||||
|
||||
match (self, event) {
|
||||
// TODO: Capture a tool event instead of doing this?
|
|
@ -18,7 +18,7 @@ use kurbo::{PathEl, Point};
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Pen {
|
||||
pub struct PenTool {
|
||||
fsm_state: PenToolFsmState,
|
||||
data: PenToolData,
|
||||
options: PenOptions,
|
||||
|
@ -37,7 +37,7 @@ impl Default for PenOptions {
|
|||
#[remain::sorted]
|
||||
#[impl_message(Message, ToolMessage, Pen)]
|
||||
#[derive(PartialEq, Clone, Debug, Hash, Serialize, Deserialize)]
|
||||
pub enum PenMessage {
|
||||
pub enum PenToolMessage {
|
||||
// Standard messages
|
||||
#[remain::unsorted]
|
||||
DocumentIsDirty,
|
||||
|
@ -65,7 +65,7 @@ pub enum PenOptionsUpdate {
|
|||
LineWeight(u32),
|
||||
}
|
||||
|
||||
impl PropertyHolder for Pen {
|
||||
impl PropertyHolder for PenTool {
|
||||
fn properties(&self) -> WidgetLayout {
|
||||
WidgetLayout::new(vec![LayoutRow::Row {
|
||||
name: "".into(),
|
||||
|
@ -75,14 +75,14 @@ impl PropertyHolder for Pen {
|
|||
value: self.options.line_weight as f64,
|
||||
is_integer: true,
|
||||
min: Some(0.),
|
||||
on_update: WidgetCallback::new(|number_input| PenMessage::UpdateOptions(PenOptionsUpdate::LineWeight(number_input.value as u32)).into()),
|
||||
on_update: WidgetCallback::new(|number_input| PenToolMessage::UpdateOptions(PenOptionsUpdate::LineWeight(number_input.value as u32)).into()),
|
||||
..NumberInput::default()
|
||||
}))],
|
||||
}])
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Pen {
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for PenTool {
|
||||
fn process_action(&mut self, action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque<Message>) {
|
||||
if action == ToolMessage::UpdateHints {
|
||||
self.fsm_state.update_hints(responses);
|
||||
|
@ -94,7 +94,7 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Pen {
|
|||
return;
|
||||
}
|
||||
|
||||
if let ToolMessage::Pen(PenMessage::UpdateOptions(action)) = action {
|
||||
if let ToolMessage::Pen(PenToolMessage::UpdateOptions(action)) = action {
|
||||
match action {
|
||||
PenOptionsUpdate::LineWeight(line_weight) => self.options.line_weight = line_weight,
|
||||
}
|
||||
|
@ -114,8 +114,8 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Pen {
|
|||
use PenToolFsmState::*;
|
||||
|
||||
match self.fsm_state {
|
||||
Ready => actions!(PenMessageDiscriminant; Undo, DragStart, DragStop, Confirm, Abort),
|
||||
Drawing => actions!(PenMessageDiscriminant; DragStart, DragStop, PointerMove, Confirm, Abort),
|
||||
Ready => actions!(PenToolMessageDiscriminant; Undo, DragStart, DragStop, Confirm, Abort),
|
||||
Drawing => actions!(PenToolMessageDiscriminant; DragStart, DragStop, PointerMove, Confirm, Abort),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -149,8 +149,8 @@ impl Fsm for PenToolFsmState {
|
|||
input: &InputPreprocessorMessageHandler,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) -> Self {
|
||||
use PenMessage::*;
|
||||
use PenToolFsmState::*;
|
||||
use PenToolMessage::*;
|
||||
|
||||
let transform = document.graphene_document.root.transform;
|
||||
|
|
@ -16,7 +16,7 @@ use glam::DAffine2;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Rectangle {
|
||||
pub struct RectangleTool {
|
||||
fsm_state: RectangleToolFsmState,
|
||||
data: RectangleToolData,
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ pub struct Rectangle {
|
|||
#[remain::sorted]
|
||||
#[impl_message(Message, ToolMessage, Rectangle)]
|
||||
#[derive(PartialEq, Clone, Debug, Hash, Serialize, Deserialize)]
|
||||
pub enum RectangleMessage {
|
||||
pub enum RectangleToolMessage {
|
||||
// Standard messages
|
||||
#[remain::unsorted]
|
||||
Abort,
|
||||
|
@ -38,9 +38,9 @@ pub enum RectangleMessage {
|
|||
},
|
||||
}
|
||||
|
||||
impl PropertyHolder for Rectangle {}
|
||||
impl PropertyHolder for RectangleTool {}
|
||||
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Rectangle {
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for RectangleTool {
|
||||
fn process_action(&mut self, action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque<Message>) {
|
||||
if action == ToolMessage::UpdateHints {
|
||||
self.fsm_state.update_hints(responses);
|
||||
|
@ -65,8 +65,8 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Rectangle {
|
|||
use RectangleToolFsmState::*;
|
||||
|
||||
match self.fsm_state {
|
||||
Ready => actions!(RectangleMessageDiscriminant; DragStart),
|
||||
Drawing => actions!(RectangleMessageDiscriminant; DragStop, Abort, Resize),
|
||||
Ready => actions!(RectangleToolMessageDiscriminant; DragStart),
|
||||
Drawing => actions!(RectangleToolMessageDiscriminant; DragStop, Abort, Resize),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,8 +101,8 @@ impl Fsm for RectangleToolFsmState {
|
|||
input: &InputPreprocessorMessageHandler,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) -> Self {
|
||||
use RectangleMessage::*;
|
||||
use RectangleToolFsmState::*;
|
||||
use RectangleToolMessage::*;
|
||||
|
||||
let mut shape_data = &mut data.data;
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
use crate::document::DocumentMessageHandler;
|
||||
use crate::input::keyboard::Key;
|
||||
use crate::input::mouse::ViewportPosition;
|
||||
use crate::input::InputPreprocessorMessageHandler;
|
||||
use crate::message_prelude::*;
|
||||
use crate::viewport_tools::snapping::SnapHandler;
|
||||
|
||||
use graphene::Operation;
|
||||
|
||||
use glam::{DAffine2, DVec2, Vec2Swizzles};
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Resize {
|
||||
pub drag_start: ViewportPosition,
|
||||
pub path: Option<Vec<LayerId>>,
|
||||
snap_handler: SnapHandler,
|
||||
}
|
||||
impl Resize {
|
||||
/// Starts a resize, assigning the snap targets and snapping the starting position.
|
||||
pub fn start(&mut self, responses: &mut VecDeque<Message>, viewport_bounds: DVec2, document: &DocumentMessageHandler, mouse_position: DVec2) {
|
||||
let layers = document.all_layers_sorted();
|
||||
self.snap_handler.start_snap(responses, viewport_bounds, document, layers);
|
||||
self.drag_start = self.snap_handler.snap_position(document, mouse_position);
|
||||
}
|
||||
|
||||
pub fn calculate_transform(&self, document: &DocumentMessageHandler, center: Key, lock_ratio: Key, ipp: &InputPreprocessorMessageHandler) -> Option<Message> {
|
||||
if let Some(path) = &self.path {
|
||||
let mut start = self.drag_start;
|
||||
|
||||
let stop = self.snap_handler.snap_position(document, ipp.mouse.position);
|
||||
|
||||
let mut size = stop - start;
|
||||
if ipp.keyboard.get(lock_ratio as usize) {
|
||||
size = size.abs().max(size.abs().yx()) * size.signum();
|
||||
}
|
||||
if ipp.keyboard.get(center as usize) {
|
||||
start -= size;
|
||||
size *= 2.;
|
||||
}
|
||||
|
||||
Some(
|
||||
Operation::SetLayerTransformInViewport {
|
||||
path: path.to_vec(),
|
||||
transform: DAffine2::from_scale_angle_translation(size, 0., start).to_cols_array(),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cleanup(&mut self, responses: &mut VecDeque<Message>) {
|
||||
self.snap_handler.cleanup(responses);
|
||||
self.path = None;
|
||||
}
|
||||
}
|
|
@ -23,7 +23,7 @@ use glam::{DAffine2, DVec2};
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Select {
|
||||
pub struct SelectTool {
|
||||
fsm_state: SelectToolFsmState,
|
||||
data: SelectToolData,
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ pub struct Select {
|
|||
#[remain::sorted]
|
||||
#[impl_message(Message, ToolMessage, Select)]
|
||||
#[derive(PartialEq, Clone, Debug, Hash, Serialize, Deserialize)]
|
||||
pub enum SelectMessage {
|
||||
pub enum SelectToolMessage {
|
||||
// Standard messages
|
||||
#[remain::unsorted]
|
||||
Abort,
|
||||
|
@ -57,7 +57,7 @@ pub enum SelectMessage {
|
|||
},
|
||||
}
|
||||
|
||||
impl PropertyHolder for Select {
|
||||
impl PropertyHolder for SelectTool {
|
||||
fn properties(&self) -> WidgetLayout {
|
||||
WidgetLayout::new(vec![LayoutRow::Row {
|
||||
name: "".into(),
|
||||
|
@ -160,14 +160,14 @@ impl PropertyHolder for Select {
|
|||
icon: "FlipHorizontal".into(),
|
||||
tooltip: "Flip Horizontal".into(),
|
||||
size: 24,
|
||||
on_update: WidgetCallback::new(|_| SelectMessage::FlipHorizontal.into()),
|
||||
on_update: WidgetCallback::new(|_| SelectToolMessage::FlipHorizontal.into()),
|
||||
..IconButton::default()
|
||||
})),
|
||||
WidgetHolder::new(Widget::IconButton(IconButton {
|
||||
icon: "FlipVertical".into(),
|
||||
tooltip: "Flip Vertical".into(),
|
||||
size: 24,
|
||||
on_update: WidgetCallback::new(|_| SelectMessage::FlipVertical.into()),
|
||||
on_update: WidgetCallback::new(|_| SelectToolMessage::FlipVertical.into()),
|
||||
..IconButton::default()
|
||||
})),
|
||||
WidgetHolder::new(Widget::Separator(Separator {
|
||||
|
@ -230,7 +230,7 @@ impl PropertyHolder for Select {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Select {
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for SelectTool {
|
||||
fn process_action(&mut self, action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque<Message>) {
|
||||
if action == ToolMessage::UpdateHints {
|
||||
self.fsm_state.update_hints(responses);
|
||||
|
@ -254,9 +254,9 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Select {
|
|||
use SelectToolFsmState::*;
|
||||
|
||||
match self.fsm_state {
|
||||
Ready => actions!(SelectMessageDiscriminant; DragStart, PointerMove, EditLayer),
|
||||
Dragging => actions!(SelectMessageDiscriminant; DragStop, PointerMove, EditLayer),
|
||||
_ => actions!(SelectMessageDiscriminant; DragStop, PointerMove, Abort, EditLayer),
|
||||
Ready => actions!(SelectToolMessageDiscriminant; DragStart, PointerMove, EditLayer),
|
||||
Dragging => actions!(SelectToolMessageDiscriminant; DragStop, PointerMove, EditLayer),
|
||||
_ => actions!(SelectToolMessageDiscriminant; DragStop, PointerMove, Abort, EditLayer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -317,8 +317,8 @@ impl Fsm for SelectToolFsmState {
|
|||
input: &InputPreprocessorMessageHandler,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) -> Self {
|
||||
use SelectMessage::*;
|
||||
use SelectToolFsmState::*;
|
||||
use SelectToolMessage::*;
|
||||
|
||||
if let ToolMessage::Select(event) = event {
|
||||
match (self, event) {
|
||||
|
@ -446,7 +446,7 @@ impl Fsm for SelectToolFsmState {
|
|||
}
|
||||
(Dragging, PointerMove { axis_align, .. }) => {
|
||||
// TODO: This is a cheat. Break out the relevant functionality from the handler above and call it from there and here.
|
||||
responses.push_front(SelectMessage::DocumentIsDirty.into());
|
||||
responses.push_front(SelectToolMessage::DocumentIsDirty.into());
|
||||
|
||||
let mouse_position = axis_align_drag(input.keyboard.get(axis_align as usize), input.mouse.position, data.drag_start);
|
||||
|
|
@ -16,7 +16,7 @@ use glam::DAffine2;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Shape {
|
||||
pub struct ShapeTool {
|
||||
fsm_state: ShapeToolFsmState,
|
||||
data: ShapeToolData,
|
||||
options: ShapeOptions,
|
||||
|
@ -35,7 +35,7 @@ impl Default for ShapeOptions {
|
|||
#[remain::sorted]
|
||||
#[impl_message(Message, ToolMessage, Shape)]
|
||||
#[derive(PartialEq, Clone, Debug, Hash, Serialize, Deserialize)]
|
||||
pub enum ShapeMessage {
|
||||
pub enum ShapeToolMessage {
|
||||
// Standard messages
|
||||
#[remain::unsorted]
|
||||
Abort,
|
||||
|
@ -56,7 +56,7 @@ pub enum ShapeOptionsUpdate {
|
|||
Vertices(u8),
|
||||
}
|
||||
|
||||
impl PropertyHolder for Shape {
|
||||
impl PropertyHolder for ShapeTool {
|
||||
fn properties(&self) -> WidgetLayout {
|
||||
WidgetLayout::new(vec![LayoutRow::Row {
|
||||
name: "".into(),
|
||||
|
@ -66,14 +66,14 @@ impl PropertyHolder for Shape {
|
|||
is_integer: true,
|
||||
min: Some(3.),
|
||||
max: Some(256.),
|
||||
on_update: WidgetCallback::new(|number_input| ShapeMessage::UpdateOptions(ShapeOptionsUpdate::Vertices(number_input.value as u8)).into()),
|
||||
on_update: WidgetCallback::new(|number_input| ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::Vertices(number_input.value as u8)).into()),
|
||||
..NumberInput::default()
|
||||
}))],
|
||||
}])
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Shape {
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for ShapeTool {
|
||||
fn process_action(&mut self, action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque<Message>) {
|
||||
if action == ToolMessage::UpdateHints {
|
||||
self.fsm_state.update_hints(responses);
|
||||
|
@ -85,7 +85,7 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Shape {
|
|||
return;
|
||||
}
|
||||
|
||||
if let ToolMessage::Shape(ShapeMessage::UpdateOptions(action)) = action {
|
||||
if let ToolMessage::Shape(ShapeToolMessage::UpdateOptions(action)) = action {
|
||||
match action {
|
||||
ShapeOptionsUpdate::Vertices(vertices) => self.options.vertices = vertices,
|
||||
}
|
||||
|
@ -105,8 +105,8 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Shape {
|
|||
use ShapeToolFsmState::*;
|
||||
|
||||
match self.fsm_state {
|
||||
Ready => actions!(ShapeMessageDiscriminant; DragStart),
|
||||
Drawing => actions!(ShapeMessageDiscriminant; DragStop, Abort, Resize),
|
||||
Ready => actions!(ShapeToolMessageDiscriminant; DragStart),
|
||||
Drawing => actions!(ShapeToolMessageDiscriminant; DragStop, Abort, Resize),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -142,8 +142,8 @@ impl Fsm for ShapeToolFsmState {
|
|||
input: &InputPreprocessorMessageHandler,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) -> Self {
|
||||
use ShapeMessage::*;
|
||||
use ShapeToolFsmState::*;
|
||||
use ShapeToolMessage::*;
|
||||
|
||||
let mut shape_data = &mut data.data;
|
||||
|
|
@ -16,7 +16,7 @@ use glam::{DAffine2, DVec2};
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Spline {
|
||||
pub struct SplineTool {
|
||||
fsm_state: SplineToolFsmState,
|
||||
data: SplineToolData,
|
||||
options: SplineOptions,
|
||||
|
@ -35,7 +35,7 @@ impl Default for SplineOptions {
|
|||
#[remain::sorted]
|
||||
#[impl_message(Message, ToolMessage, Spline)]
|
||||
#[derive(PartialEq, Clone, Debug, Hash, Serialize, Deserialize)]
|
||||
pub enum SplineMessage {
|
||||
pub enum SplineToolMessage {
|
||||
// Standard messages
|
||||
#[remain::unsorted]
|
||||
Abort,
|
||||
|
@ -61,7 +61,7 @@ pub enum SplineOptionsUpdate {
|
|||
LineWeight(u32),
|
||||
}
|
||||
|
||||
impl PropertyHolder for Spline {
|
||||
impl PropertyHolder for SplineTool {
|
||||
fn properties(&self) -> WidgetLayout {
|
||||
WidgetLayout::new(vec![LayoutRow::Row {
|
||||
name: "".into(),
|
||||
|
@ -71,14 +71,14 @@ impl PropertyHolder for Spline {
|
|||
value: self.options.line_weight as f64,
|
||||
is_integer: true,
|
||||
min: Some(0.),
|
||||
on_update: WidgetCallback::new(|number_input| SplineMessage::UpdateOptions(SplineOptionsUpdate::LineWeight(number_input.value as u32)).into()),
|
||||
on_update: WidgetCallback::new(|number_input| SplineToolMessage::UpdateOptions(SplineOptionsUpdate::LineWeight(number_input.value as u32)).into()),
|
||||
..NumberInput::default()
|
||||
}))],
|
||||
}])
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Spline {
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for SplineTool {
|
||||
fn process_action(&mut self, action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque<Message>) {
|
||||
if action == ToolMessage::UpdateHints {
|
||||
self.fsm_state.update_hints(responses);
|
||||
|
@ -90,7 +90,7 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Spline {
|
|||
return;
|
||||
}
|
||||
|
||||
if let ToolMessage::Spline(SplineMessage::UpdateOptions(action)) = action {
|
||||
if let ToolMessage::Spline(SplineToolMessage::UpdateOptions(action)) = action {
|
||||
match action {
|
||||
SplineOptionsUpdate::LineWeight(line_weight) => self.options.line_weight = line_weight,
|
||||
}
|
||||
|
@ -110,8 +110,8 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Spline {
|
|||
use SplineToolFsmState::*;
|
||||
|
||||
match self.fsm_state {
|
||||
Ready => actions!(SplineMessageDiscriminant; Undo, DragStart, DragStop, Confirm, Abort),
|
||||
Drawing => actions!(SplineMessageDiscriminant; DragStop, PointerMove, Confirm, Abort),
|
||||
Ready => actions!(SplineToolMessageDiscriminant; Undo, DragStart, DragStop, Confirm, Abort),
|
||||
Drawing => actions!(SplineToolMessageDiscriminant; DragStop, PointerMove, Confirm, Abort),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -144,8 +144,8 @@ impl Fsm for SplineToolFsmState {
|
|||
input: &InputPreprocessorMessageHandler,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) -> Self {
|
||||
use SplineMessage::*;
|
||||
use SplineToolFsmState::*;
|
||||
use SplineToolMessage::*;
|
||||
|
||||
let transform = document.graphene_document.root.transform;
|
||||
|
|
@ -16,7 +16,7 @@ use kurbo::Shape;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Text {
|
||||
pub struct TextTool {
|
||||
fsm_state: TextToolFsmState,
|
||||
data: TextToolData,
|
||||
options: TextOptions,
|
||||
|
@ -61,7 +61,7 @@ pub enum TextOptionsUpdate {
|
|||
FontSize(u32),
|
||||
}
|
||||
|
||||
impl PropertyHolder for Text {
|
||||
impl PropertyHolder for TextTool {
|
||||
fn properties(&self) -> WidgetLayout {
|
||||
WidgetLayout::new(vec![LayoutRow::Row {
|
||||
name: "".into(),
|
||||
|
@ -78,7 +78,7 @@ impl PropertyHolder for Text {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Text {
|
||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for TextTool {
|
||||
fn process_action(&mut self, action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque<Message>) {
|
||||
if action == ToolMessage::UpdateHints {
|
||||
self.fsm_state.update_hints(responses);
|
|
@ -120,7 +120,7 @@ impl JsEditorHandle {
|
|||
pub fn send_tool_message(&self, tool: String, message: &JsValue) -> Result<(), JsValue> {
|
||||
let tool_message = match translate_tool_type(&tool) {
|
||||
Some(tool) => match tool {
|
||||
ToolType::Select => match serde_wasm_bindgen::from_value::<tools::select::SelectMessage>(message.clone()) {
|
||||
ToolType::Select => match serde_wasm_bindgen::from_value::<tools::select_tool::SelectToolMessage>(message.clone()) {
|
||||
Ok(select_message) => Ok(ToolMessage::Select(select_message)),
|
||||
Err(err) => Err(Error::new(&format!("Invalid message for {}: {}", tool, err)).into()),
|
||||
},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::consts::{F64PRECISE, RAY_FUDGE_FACTOR};
|
||||
use crate::intersection::{intersections, line_curve_intersections, valid_t, Intersect, Origin};
|
||||
use crate::layers::simple_shape::Shape;
|
||||
use crate::layers::shape_layer::ShapeLayer;
|
||||
use crate::layers::style::PathStyle;
|
||||
|
||||
use kurbo::{BezPath, CubicBez, Line, ParamCurve, ParamCurveArclen, ParamCurveArea, ParamCurveExtrema, PathEl, PathSeg, Point, QuadBez, Rect};
|
||||
|
@ -377,7 +377,7 @@ impl PathGraph {
|
|||
cycles
|
||||
}
|
||||
|
||||
pub fn get_shape(&self, cycle: &Cycle, style: &PathStyle) -> Shape {
|
||||
pub fn get_shape(&self, cycle: &Cycle, style: &PathStyle) -> ShapeLayer {
|
||||
let mut curve = Vec::new();
|
||||
let vertices = cycle.vertices();
|
||||
for index in 1..vertices.len() {
|
||||
|
@ -385,7 +385,7 @@ impl PathGraph {
|
|||
concat_paths(&mut curve, &self.edge(vertices[index - 1].0, vertices[index].0, vertices[index].1).unwrap().curve);
|
||||
}
|
||||
curve.push(PathEl::ClosePath);
|
||||
Shape::from_bez_path(BezPath::from_vec(curve), *style, false)
|
||||
ShapeLayer::from_bez_path(BezPath::from_vec(curve), *style, false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -455,7 +455,7 @@ pub fn subdivide_path_seg(p: &PathSeg, t_values: &mut [f64]) -> Vec<Option<PathS
|
|||
|
||||
// TODO: check if shapes are filled
|
||||
// TODO: Bug: shape with at least two subpaths and comprised of many unions sometimes has erroneous movetos embedded in edges
|
||||
pub fn boolean_operation(select: BooleanOperation, mut alpha: Shape, mut beta: Shape) -> Result<Vec<Shape>, BooleanOperationError> {
|
||||
pub fn boolean_operation(select: BooleanOperation, mut alpha: ShapeLayer, mut beta: ShapeLayer) -> Result<Vec<ShapeLayer>, BooleanOperationError> {
|
||||
if alpha.path.is_empty() || beta.path.is_empty() {
|
||||
return Err(BooleanOperationError::InvalidSelection);
|
||||
}
|
||||
|
@ -618,7 +618,7 @@ pub fn bounding_box(curve: &BezPath) -> Rect {
|
|||
.unwrap()
|
||||
}
|
||||
|
||||
fn collect_shapes<'a, F, G>(graph: &PathGraph, cycles: &mut Vec<Cycle>, predicate: F, style: G) -> Result<Vec<Shape>, BooleanOperationError>
|
||||
fn collect_shapes<'a, F, G>(graph: &PathGraph, cycles: &mut Vec<Cycle>, predicate: F, style: G) -> Result<Vec<ShapeLayer>, BooleanOperationError>
|
||||
where
|
||||
F: Fn(Direction) -> bool,
|
||||
G: Fn(Direction) -> &'a PathStyle,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use crate::boolean_ops::boolean_operation;
|
||||
use crate::intersection::Quad;
|
||||
use crate::layers;
|
||||
use crate::layers::folder::Folder;
|
||||
use crate::layers::folder_layer::FolderLayer;
|
||||
use crate::layers::layer_info::{Layer, LayerData, LayerDataType};
|
||||
use crate::layers::simple_shape::Shape;
|
||||
use crate::layers::shape_layer::ShapeLayer;
|
||||
use crate::layers::style::ViewMode;
|
||||
use crate::layers::text::Text;
|
||||
use crate::layers::text_layer::TextLayer;
|
||||
use crate::{DocumentError, DocumentResponse, Operation};
|
||||
|
||||
use glam::{DAffine2, DVec2};
|
||||
|
@ -29,7 +29,7 @@ pub struct Document {
|
|||
impl Default for Document {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
root: Layer::new(LayerDataType::Folder(Folder::default()), DAffine2::IDENTITY.to_cols_array()),
|
||||
root: Layer::new(LayerDataType::Folder(FolderLayer::default()), DAffine2::IDENTITY.to_cols_array()),
|
||||
state_identifier: DefaultHasher::new(),
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ impl Document {
|
|||
|
||||
/// Returns a reference to the requested folder. Fails if the path does not exist,
|
||||
/// or if the requested layer is not of type folder.
|
||||
pub fn folder(&self, path: impl AsRef<[LayerId]>) -> Result<&Folder, DocumentError> {
|
||||
pub fn folder(&self, path: impl AsRef<[LayerId]>) -> Result<&FolderLayer, DocumentError> {
|
||||
let mut root = &self.root;
|
||||
for id in path.as_ref() {
|
||||
root = root.as_folder()?.layer(*id).ok_or_else(|| DocumentError::LayerNotFound(path.as_ref().into()))?;
|
||||
|
@ -71,7 +71,7 @@ impl Document {
|
|||
/// Returns a mutable reference to the requested folder. Fails if the path does not exist,
|
||||
/// or if the requested layer is not of type folder.
|
||||
/// If you manually edit the folder you have to set the cache_dirty flag yourself.
|
||||
fn folder_mut(&mut self, path: &[LayerId]) -> Result<&mut Folder, DocumentError> {
|
||||
fn folder_mut(&mut self, path: &[LayerId]) -> Result<&mut FolderLayer, DocumentError> {
|
||||
let mut root = &mut self.root;
|
||||
for id in path {
|
||||
root = root.as_folder_mut()?.layer_mut(*id).ok_or_else(|| DocumentError::LayerNotFound(path.into()))?;
|
||||
|
@ -99,8 +99,8 @@ impl Document {
|
|||
|
||||
/// Returns vector `Shape`s for each specified in `paths`.
|
||||
/// If any path is not a shape, or does not exist, `DocumentError::InvalidPath` is returned.
|
||||
fn transformed_shapes(&self, paths: &[Vec<LayerId>]) -> Result<Vec<Shape>, DocumentError> {
|
||||
let mut shapes: Vec<Shape> = Vec::new();
|
||||
fn transformed_shapes(&self, paths: &[Vec<LayerId>]) -> Result<Vec<ShapeLayer>, DocumentError> {
|
||||
let mut shapes: Vec<ShapeLayer> = Vec::new();
|
||||
let undo_viewport = self.root.transform.inverse();
|
||||
for path in paths {
|
||||
match (self.multiply_transforms(path), &self.layer(path)?.data) {
|
||||
|
@ -263,7 +263,7 @@ impl Document {
|
|||
}
|
||||
|
||||
/// Visit each layer recursively, applies modify_shape to each non-overlay Shape
|
||||
pub fn visit_all_shapes<F: FnMut(&mut Shape)>(layer: &mut Layer, modify_shape: &mut F) -> bool {
|
||||
pub fn visit_all_shapes<F: FnMut(&mut ShapeLayer)>(layer: &mut Layer, modify_shape: &mut F) -> bool {
|
||||
match layer.data {
|
||||
LayerDataType::Shape(ref mut shape) => {
|
||||
modify_shape(shape);
|
||||
|
@ -434,14 +434,14 @@ impl Document {
|
|||
|
||||
let responses = match &operation {
|
||||
Operation::AddEllipse { path, insert_index, transform, style } => {
|
||||
let layer = Layer::new(LayerDataType::Shape(Shape::ellipse(*style)), *transform);
|
||||
let layer = Layer::new(LayerDataType::Shape(ShapeLayer::ellipse(*style)), *transform);
|
||||
|
||||
self.set_layer(path, layer, *insert_index)?;
|
||||
|
||||
Some([vec![DocumentChanged, CreatedLayer { path: path.clone() }], update_thumbnails_upstream(path)].concat())
|
||||
}
|
||||
Operation::AddOverlayEllipse { path, transform, style } => {
|
||||
let mut ellipse = Shape::ellipse(*style);
|
||||
let mut ellipse = ShapeLayer::ellipse(*style);
|
||||
ellipse.render_index = -1;
|
||||
|
||||
let layer = Layer::new(LayerDataType::Shape(ellipse), *transform);
|
||||
|
@ -450,14 +450,14 @@ impl Document {
|
|||
Some([vec![DocumentChanged, CreatedLayer { path: path.clone() }]].concat())
|
||||
}
|
||||
Operation::AddRect { path, insert_index, transform, style } => {
|
||||
let layer = Layer::new(LayerDataType::Shape(Shape::rectangle(*style)), *transform);
|
||||
let layer = Layer::new(LayerDataType::Shape(ShapeLayer::rectangle(*style)), *transform);
|
||||
|
||||
self.set_layer(path, layer, *insert_index)?;
|
||||
|
||||
Some([vec![DocumentChanged, CreatedLayer { path: path.clone() }], update_thumbnails_upstream(path)].concat())
|
||||
}
|
||||
Operation::AddOverlayRect { path, transform, style } => {
|
||||
let mut rect = Shape::rectangle(*style);
|
||||
let mut rect = ShapeLayer::rectangle(*style);
|
||||
rect.render_index = -1;
|
||||
|
||||
let layer = Layer::new(LayerDataType::Shape(rect), *transform);
|
||||
|
@ -466,14 +466,14 @@ impl Document {
|
|||
Some([vec![DocumentChanged, CreatedLayer { path: path.clone() }]].concat())
|
||||
}
|
||||
Operation::AddLine { path, insert_index, transform, style } => {
|
||||
let layer = Layer::new(LayerDataType::Shape(Shape::line(*style)), *transform);
|
||||
let layer = Layer::new(LayerDataType::Shape(ShapeLayer::line(*style)), *transform);
|
||||
|
||||
self.set_layer(path, layer, *insert_index)?;
|
||||
|
||||
Some([vec![DocumentChanged, CreatedLayer { path: path.clone() }], update_thumbnails_upstream(path)].concat())
|
||||
}
|
||||
Operation::AddOverlayLine { path, transform, style } => {
|
||||
let mut line = Shape::line(*style);
|
||||
let mut line = ShapeLayer::line(*style);
|
||||
line.render_index = -1;
|
||||
|
||||
let layer = Layer::new(LayerDataType::Shape(line), *transform);
|
||||
|
@ -490,7 +490,7 @@ impl Document {
|
|||
style,
|
||||
size,
|
||||
} => {
|
||||
let layer = Layer::new(LayerDataType::Text(Text::new(text.clone(), *style, *size)), *transform);
|
||||
let layer = Layer::new(LayerDataType::Text(TextLayer::new(text.clone(), *style, *size)), *transform);
|
||||
|
||||
self.set_layer(path, layer, *insert_index)?;
|
||||
|
||||
|
@ -514,14 +514,14 @@ impl Document {
|
|||
style,
|
||||
sides,
|
||||
} => {
|
||||
let layer = Layer::new(LayerDataType::Shape(Shape::ngon(*sides, *style)), *transform);
|
||||
let layer = Layer::new(LayerDataType::Shape(ShapeLayer::ngon(*sides, *style)), *transform);
|
||||
|
||||
self.set_layer(path, layer, *insert_index)?;
|
||||
|
||||
Some([vec![DocumentChanged, CreatedLayer { path: path.clone() }], update_thumbnails_upstream(path)].concat())
|
||||
}
|
||||
Operation::AddOverlayShape { path, style, bez_path, closed } => {
|
||||
let mut shape = Shape::from_bez_path(bez_path.clone(), *style, *closed);
|
||||
let mut shape = ShapeLayer::from_bez_path(bez_path.clone(), *style, *closed);
|
||||
shape.render_index = -1;
|
||||
|
||||
let layer = Layer::new(LayerDataType::Shape(shape), DAffine2::IDENTITY.to_cols_array());
|
||||
|
@ -537,7 +537,7 @@ impl Document {
|
|||
bez_path,
|
||||
closed,
|
||||
} => {
|
||||
let shape = Shape::from_bez_path(bez_path.clone(), *style, *closed);
|
||||
let shape = ShapeLayer::from_bez_path(bez_path.clone(), *style, *closed);
|
||||
self.set_layer(path, Layer::new(LayerDataType::Shape(shape), *transform), *insert_index)?;
|
||||
Some([vec![DocumentChanged, CreatedLayer { path: path.clone() }]].concat())
|
||||
}
|
||||
|
@ -549,7 +549,7 @@ impl Document {
|
|||
style,
|
||||
} => {
|
||||
let points: Vec<glam::DVec2> = points.iter().map(|&it| it.into()).collect();
|
||||
self.set_layer(path, Layer::new(LayerDataType::Shape(Shape::poly_line(points, *style)), *transform), *insert_index)?;
|
||||
self.set_layer(path, Layer::new(LayerDataType::Shape(ShapeLayer::poly_line(points, *style)), *transform), *insert_index)?;
|
||||
Some([vec![DocumentChanged, CreatedLayer { path: path.clone() }], update_thumbnails_upstream(path)].concat())
|
||||
}
|
||||
Operation::BooleanOperation { operation, selected } => {
|
||||
|
@ -588,11 +588,11 @@ impl Document {
|
|||
style,
|
||||
} => {
|
||||
let points: Vec<glam::DVec2> = points.iter().map(|&it| it.into()).collect();
|
||||
self.set_layer(path, Layer::new(LayerDataType::Shape(Shape::spline(points, *style)), *transform), *insert_index)?;
|
||||
self.set_layer(path, Layer::new(LayerDataType::Shape(ShapeLayer::spline(points, *style)), *transform), *insert_index)?;
|
||||
Some([vec![DocumentChanged, CreatedLayer { path: path.clone() }], update_thumbnails_upstream(path)].concat())
|
||||
}
|
||||
Operation::DeleteLayer { path } => {
|
||||
fn aggregate_deletions(folder: &Folder, path: &mut Vec<LayerId>, responses: &mut Vec<DocumentResponse>) {
|
||||
fn aggregate_deletions(folder: &FolderLayer, path: &mut Vec<LayerId>, responses: &mut Vec<DocumentResponse>) {
|
||||
for (id, layer) in folder.layer_ids.iter().zip(folder.layers()) {
|
||||
path.push(*id);
|
||||
responses.push(DocumentResponse::DeletedLayer { path: path.clone() });
|
||||
|
@ -623,7 +623,7 @@ impl Document {
|
|||
folder.add_layer(layer.clone(), Some(layer_id), *insert_index).ok_or(DocumentError::IndexOutOfBounds)?;
|
||||
self.mark_as_dirty(destination_path)?;
|
||||
|
||||
fn aggregate_insertions(folder: &Folder, path: &mut Vec<LayerId>, responses: &mut Vec<DocumentResponse>) {
|
||||
fn aggregate_insertions(folder: &FolderLayer, path: &mut Vec<LayerId>, responses: &mut Vec<DocumentResponse>) {
|
||||
for (id, layer) in folder.layer_ids.iter().zip(folder.layers()) {
|
||||
path.push(*id);
|
||||
responses.push(DocumentResponse::CreatedLayer { path: path.clone() });
|
||||
|
@ -666,7 +666,7 @@ impl Document {
|
|||
Some(vec![LayerChanged { path: path.clone() }])
|
||||
}
|
||||
Operation::CreateFolder { path } => {
|
||||
self.set_layer(path, Layer::new(LayerDataType::Folder(Folder::default()), DAffine2::IDENTITY.to_cols_array()), -1)?;
|
||||
self.set_layer(path, Layer::new(LayerDataType::Folder(FolderLayer::default()), DAffine2::IDENTITY.to_cols_array()), -1)?;
|
||||
self.mark_as_dirty(path)?;
|
||||
|
||||
Some([vec![DocumentChanged, CreatedLayer { path: path.clone() }], update_thumbnails_upstream(path)].concat())
|
||||
|
@ -705,7 +705,7 @@ impl Document {
|
|||
|
||||
if let LayerDataType::Text(t) = &mut self.layer_mut(path)?.data {
|
||||
let bezpath = t.to_bez_path();
|
||||
self.layer_mut(path)?.data = layers::layer_info::LayerDataType::Shape(Shape::from_bez_path(bezpath, t.style, true));
|
||||
self.layer_mut(path)?.data = layers::layer_info::LayerDataType::Shape(ShapeLayer::from_bez_path(bezpath, t.style, true));
|
||||
}
|
||||
|
||||
if let LayerDataType::Shape(shape) = &mut self.layer_mut(path)?.data {
|
||||
|
|
|
@ -8,13 +8,13 @@ use serde::{Deserialize, Serialize};
|
|||
use std::fmt::Write;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, Default)]
|
||||
pub struct Folder {
|
||||
pub struct FolderLayer {
|
||||
next_assignment_id: LayerId,
|
||||
pub layer_ids: Vec<LayerId>,
|
||||
layers: Vec<Layer>,
|
||||
}
|
||||
|
||||
impl LayerData for Folder {
|
||||
impl LayerData for FolderLayer {
|
||||
fn render(&mut self, svg: &mut String, transforms: &mut Vec<glam::DAffine2>, view_mode: ViewMode) {
|
||||
for layer in &mut self.layers {
|
||||
let _ = writeln!(svg, "{}", layer.render(transforms, view_mode));
|
||||
|
@ -37,7 +37,7 @@ impl LayerData for Folder {
|
|||
}
|
||||
}
|
||||
|
||||
impl Folder {
|
||||
impl FolderLayer {
|
||||
/// When a insertion id is provided, try to insert the layer with the given id.
|
||||
/// If that id is already used, return None.
|
||||
/// When no insertion id is provided, search for the next free id and insert it with that.
|
||||
|
@ -109,7 +109,7 @@ impl Folder {
|
|||
self.layer_ids.iter().position(|x| *x == layer_id).ok_or_else(|| DocumentError::LayerNotFound([layer_id].into()))
|
||||
}
|
||||
|
||||
pub fn folder(&self, id: LayerId) -> Option<&Folder> {
|
||||
pub fn folder(&self, id: LayerId) -> Option<&FolderLayer> {
|
||||
match self.layer(id) {
|
||||
Some(Layer {
|
||||
data: LayerDataType::Folder(folder), ..
|
||||
|
@ -118,7 +118,7 @@ impl Folder {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn folder_mut(&mut self, id: LayerId) -> Option<&mut Folder> {
|
||||
pub fn folder_mut(&mut self, id: LayerId) -> Option<&mut FolderLayer> {
|
||||
match self.layer_mut(id) {
|
||||
Some(Layer {
|
||||
data: LayerDataType::Folder(folder), ..
|
|
@ -1,8 +1,8 @@
|
|||
use super::blend_mode::BlendMode;
|
||||
use super::folder::Folder;
|
||||
use super::simple_shape::Shape;
|
||||
use super::folder_layer::FolderLayer;
|
||||
use super::shape_layer::ShapeLayer;
|
||||
use super::style::ViewMode;
|
||||
use super::text::Text;
|
||||
use super::text_layer::TextLayer;
|
||||
use crate::intersection::Quad;
|
||||
use crate::DocumentError;
|
||||
use crate::LayerId;
|
||||
|
@ -13,9 +13,9 @@ use std::fmt::Write;
|
|||
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
||||
pub enum LayerDataType {
|
||||
Folder(Folder),
|
||||
Shape(Shape),
|
||||
Text(Text),
|
||||
Folder(FolderLayer),
|
||||
Shape(ShapeLayer),
|
||||
Text(TextLayer),
|
||||
}
|
||||
|
||||
impl LayerDataType {
|
||||
|
@ -149,28 +149,28 @@ impl Layer {
|
|||
self.current_bounding_box_with_transform(self.transform)
|
||||
}
|
||||
|
||||
pub fn as_folder_mut(&mut self) -> Result<&mut Folder, DocumentError> {
|
||||
pub fn as_folder_mut(&mut self) -> Result<&mut FolderLayer, DocumentError> {
|
||||
match &mut self.data {
|
||||
LayerDataType::Folder(f) => Ok(f),
|
||||
_ => Err(DocumentError::NotAFolder),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_folder(&self) -> Result<&Folder, DocumentError> {
|
||||
pub fn as_folder(&self) -> Result<&FolderLayer, DocumentError> {
|
||||
match &self.data {
|
||||
LayerDataType::Folder(f) => Ok(f),
|
||||
_ => Err(DocumentError::NotAFolder),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_text_mut(&mut self) -> Result<&mut Text, DocumentError> {
|
||||
pub fn as_text_mut(&mut self) -> Result<&mut TextLayer, DocumentError> {
|
||||
match &mut self.data {
|
||||
LayerDataType::Text(t) => Ok(t),
|
||||
_ => Err(DocumentError::NotText),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_text(&self) -> Result<&Text, DocumentError> {
|
||||
pub fn as_text(&self) -> Result<&TextLayer, DocumentError> {
|
||||
match &self.data {
|
||||
LayerDataType::Text(t) => Ok(t),
|
||||
_ => Err(DocumentError::NotText),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
pub mod blend_mode;
|
||||
pub mod folder;
|
||||
pub mod folder_layer;
|
||||
pub mod layer_info;
|
||||
pub mod simple_shape;
|
||||
pub mod shape_layer;
|
||||
pub mod style;
|
||||
pub mod text;
|
||||
pub mod text_layer;
|
||||
|
|
|
@ -13,14 +13,14 @@ fn glam_to_kurbo(transform: DAffine2) -> Affine {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
||||
pub struct Shape {
|
||||
pub struct ShapeLayer {
|
||||
pub path: BezPath,
|
||||
pub style: style::PathStyle,
|
||||
pub render_index: i32,
|
||||
pub closed: bool,
|
||||
}
|
||||
|
||||
impl LayerData for Shape {
|
||||
impl LayerData for ShapeLayer {
|
||||
fn render(&mut self, svg: &mut String, transforms: &mut Vec<DAffine2>, view_mode: ViewMode) {
|
||||
let mut path = self.path.clone();
|
||||
let transform = self.transform(transforms, view_mode);
|
||||
|
@ -60,7 +60,7 @@ impl LayerData for Shape {
|
|||
}
|
||||
}
|
||||
|
||||
impl Shape {
|
||||
impl ShapeLayer {
|
||||
pub fn transform(&self, transforms: &[DAffine2], mode: ViewMode) -> DAffine2 {
|
||||
let start = match (mode, self.render_index) {
|
||||
(ViewMode::Outline, _) => 0,
|
|
@ -15,7 +15,7 @@ fn glam_to_kurbo(transform: DAffine2) -> Affine {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
||||
pub struct Text {
|
||||
pub struct TextLayer {
|
||||
pub text: String,
|
||||
pub style: style::PathStyle,
|
||||
pub size: f64,
|
||||
|
@ -26,7 +26,7 @@ pub struct Text {
|
|||
cached_path: Option<BezPath>,
|
||||
}
|
||||
|
||||
impl LayerData for Text {
|
||||
impl LayerData for TextLayer {
|
||||
fn render(&mut self, svg: &mut String, transforms: &mut Vec<DAffine2>, view_mode: ViewMode) {
|
||||
let transform = self.transform(transforms, view_mode);
|
||||
let inverse = transform.inverse();
|
||||
|
@ -84,7 +84,7 @@ impl LayerData for Text {
|
|||
}
|
||||
}
|
||||
|
||||
impl Text {
|
||||
impl TextLayer {
|
||||
pub fn transform(&self, transforms: &[DAffine2], mode: ViewMode) -> DAffine2 {
|
||||
let start = match mode {
|
||||
ViewMode::Outline => 0,
|
Loading…
Add table
Add a link
Reference in a new issue