201 lines
4.5 KiB
Rust
201 lines
4.5 KiB
Rust
pub mod tool_message_handler;
|
|
pub mod tool_options;
|
|
pub mod tools;
|
|
|
|
use crate::document::DocumentMessageHandler;
|
|
use crate::input::InputPreprocessor;
|
|
use crate::message_prelude::*;
|
|
use crate::{
|
|
communication::{message::Message, MessageHandler},
|
|
Color,
|
|
};
|
|
use serde::{Deserialize, Serialize};
|
|
use std::collections::VecDeque;
|
|
use std::{
|
|
collections::HashMap,
|
|
fmt::{self, Debug},
|
|
};
|
|
pub use tool_message_handler::ToolMessageHandler;
|
|
use tool_options::ToolOptions;
|
|
pub use tool_options::*;
|
|
use tools::*;
|
|
|
|
pub mod tool_messages {
|
|
pub use super::tool_message_handler::{ToolMessage, ToolMessageDiscriminant};
|
|
pub use super::tools::ellipse::{EllipseMessage, EllipseMessageDiscriminant};
|
|
pub use super::tools::rectangle::{RectangleMessage, RectangleMessageDiscriminant};
|
|
}
|
|
|
|
pub type ToolActionHandlerData<'a> = (&'a DocumentMessageHandler, &'a DocumentToolData, &'a InputPreprocessor);
|
|
|
|
pub trait Fsm {
|
|
type ToolData;
|
|
|
|
fn transition(
|
|
self,
|
|
message: ToolMessage,
|
|
document: &DocumentMessageHandler,
|
|
tool_data: &DocumentToolData,
|
|
data: &mut Self::ToolData,
|
|
input: &InputPreprocessor,
|
|
messages: &mut VecDeque<Message>,
|
|
) -> Self;
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct DocumentToolData {
|
|
pub primary_color: Color,
|
|
pub secondary_color: Color,
|
|
pub tool_options: HashMap<ToolType, ToolOptions>,
|
|
}
|
|
|
|
type SubToolMessageHandler = dyn for<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>>;
|
|
pub struct ToolData {
|
|
pub active_tool_type: ToolType,
|
|
pub tools: HashMap<ToolType, Box<SubToolMessageHandler>>,
|
|
}
|
|
|
|
impl fmt::Debug for ToolData {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
f.debug_struct("ToolData").field("active_tool_type", &self.active_tool_type).field("tool_options", &"[…]").finish()
|
|
}
|
|
}
|
|
|
|
impl ToolData {
|
|
pub fn active_tool_mut(&mut self) -> &mut Box<SubToolMessageHandler> {
|
|
self.tools.get_mut(&self.active_tool_type).expect("The active tool is not initialized")
|
|
}
|
|
pub fn active_tool(&self) -> &SubToolMessageHandler {
|
|
self.tools.get(&self.active_tool_type).map(|x| x.as_ref()).expect("The active tool is not initialized")
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct ToolFsmState {
|
|
pub document_tool_data: DocumentToolData,
|
|
pub tool_data: ToolData,
|
|
}
|
|
|
|
impl Default for ToolFsmState {
|
|
fn default() -> Self {
|
|
ToolFsmState {
|
|
tool_data: ToolData {
|
|
active_tool_type: ToolType::Select,
|
|
tools: gen_tools_hash_map! {
|
|
Rectangle => rectangle::Rectangle,
|
|
Select => select::Select,
|
|
Crop => crop::Crop,
|
|
Navigate => navigate::Navigate,
|
|
Eyedropper => eyedropper::Eyedropper,
|
|
Path => path::Path,
|
|
Pen => pen::Pen,
|
|
Line => line::Line,
|
|
Shape => shape::Shape,
|
|
Ellipse => ellipse::Ellipse,
|
|
Fill => fill::Fill,
|
|
},
|
|
},
|
|
document_tool_data: DocumentToolData {
|
|
primary_color: Color::BLACK,
|
|
secondary_color: Color::WHITE,
|
|
tool_options: default_tool_options(),
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ToolFsmState {
|
|
pub fn new() -> Self {
|
|
Self::default()
|
|
}
|
|
|
|
pub fn swap_colors(&mut self) {
|
|
std::mem::swap(&mut self.document_tool_data.primary_color, &mut self.document_tool_data.secondary_color);
|
|
}
|
|
}
|
|
|
|
fn default_tool_options() -> HashMap<ToolType, ToolOptions> {
|
|
let tool_init = |tool: ToolType| (tool, tool.default_options());
|
|
std::array::IntoIter::new([
|
|
tool_init(ToolType::Select),
|
|
tool_init(ToolType::Pen),
|
|
tool_init(ToolType::Line),
|
|
tool_init(ToolType::Ellipse),
|
|
tool_init(ToolType::Shape), // TODO: Add more tool defaults
|
|
])
|
|
.collect()
|
|
}
|
|
|
|
#[repr(usize)]
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
pub enum ToolType {
|
|
Select,
|
|
Crop,
|
|
Navigate,
|
|
Eyedropper,
|
|
Text,
|
|
Fill,
|
|
Gradient,
|
|
Brush,
|
|
Heal,
|
|
Clone,
|
|
Patch,
|
|
BlurSharpen,
|
|
Relight,
|
|
Path,
|
|
Pen,
|
|
Freehand,
|
|
Spline,
|
|
Line,
|
|
Rectangle,
|
|
Ellipse,
|
|
Shape,
|
|
}
|
|
|
|
impl fmt::Display for ToolType {
|
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
use ToolType::*;
|
|
|
|
let name = match_variant_name!(match (self) {
|
|
Select,
|
|
Crop,
|
|
Navigate,
|
|
Eyedropper,
|
|
Text,
|
|
Fill,
|
|
Gradient,
|
|
Brush,
|
|
Heal,
|
|
Clone,
|
|
Patch,
|
|
BlurSharpen,
|
|
Relight,
|
|
Path,
|
|
Pen,
|
|
Freehand,
|
|
Spline,
|
|
Line,
|
|
Rectangle,
|
|
Ellipse,
|
|
Shape
|
|
});
|
|
|
|
formatter.write_str(name)
|
|
}
|
|
}
|
|
|
|
impl ToolType {
|
|
fn default_options(&self) -> ToolOptions {
|
|
match self {
|
|
ToolType::Select => ToolOptions::Select { append_mode: SelectAppendMode::New },
|
|
ToolType::Pen => ToolOptions::Pen { weight: 5 },
|
|
ToolType::Line => ToolOptions::Line { weight: 5 },
|
|
ToolType::Ellipse => ToolOptions::Ellipse {},
|
|
ToolType::Shape => ToolOptions::Shape {
|
|
shape_type: ShapeType::Polygon { vertices: 6 },
|
|
},
|
|
_ => todo!(),
|
|
}
|
|
}
|
|
}
|