Graphite/editor/src/viewport_tools/tool_message_handler.rs

124 lines
4.5 KiB
Rust

use super::tool::{message_to_tool_type, standard_tool_message, update_working_colors, StandardToolMessageType, ToolFsmState};
use crate::document::DocumentMessageHandler;
use crate::input::InputPreprocessorMessageHandler;
use crate::message_prelude::*;
use graphene::color::Color;
use std::collections::VecDeque;
#[derive(Debug, Default)]
pub struct ToolMessageHandler {
tool_state: ToolFsmState,
}
impl MessageHandler<ToolMessage, (&DocumentMessageHandler, &InputPreprocessorMessageHandler)> for ToolMessageHandler {
#[remain::check]
fn process_action(&mut self, message: ToolMessage, data: (&DocumentMessageHandler, &InputPreprocessorMessageHandler), responses: &mut VecDeque<Message>) {
use ToolMessage::*;
let (document, input) = data;
#[remain::sorted]
match message {
ActivateTool(new_tool) => {
let tool_data = &mut self.tool_state.tool_data;
let document_data = &self.tool_state.document_tool_data;
let old_tool = tool_data.active_tool_type;
// Do nothing if switching to the same tool
if new_tool == old_tool {
return;
}
// Send the Abort state transition to the tool
let mut send_abort_to_tool = |tool_type, message: ToolMessage, update_hints: bool| {
if let Some(tool) = tool_data.tools.get_mut(&tool_type) {
tool.process_action(message, (document, document_data, input), responses);
if update_hints {
tool.process_action(ToolMessage::UpdateHints, (document, document_data, input), responses);
}
}
};
// Send the old and new tools a transition to their FSM Abort states
if let Some(tool_message) = standard_tool_message(new_tool, StandardToolMessageType::Abort) {
send_abort_to_tool(new_tool, tool_message, true);
}
if let Some(tool_message) = standard_tool_message(old_tool, StandardToolMessageType::Abort) {
send_abort_to_tool(old_tool, tool_message, false);
}
// Send the DocumentIsDirty message to the active tool's sub-tool message handler
if let Some(message) = standard_tool_message(new_tool, StandardToolMessageType::DocumentIsDirty) {
responses.push_back(message.into());
}
// Store the new active tool
tool_data.active_tool_type = new_tool;
// Notify the frontend about the new active tool to be displayed
let tool_name = new_tool.to_string();
let tool_options = self.tool_state.document_tool_data.tool_options.get(&new_tool).copied();
responses.push_back(FrontendMessage::UpdateActiveTool { tool_name, tool_options }.into());
}
DocumentIsDirty => {
// Send the DocumentIsDirty message to the active tool's sub-tool message handler
let active_tool = self.tool_state.tool_data.active_tool_type;
if let Some(message) = standard_tool_message(active_tool, StandardToolMessageType::DocumentIsDirty) {
responses.push_back(message.into());
}
}
ResetColors => {
let document_data = &mut self.tool_state.document_tool_data;
document_data.primary_color = Color::BLACK;
document_data.secondary_color = Color::WHITE;
update_working_colors(document_data, responses);
}
SelectPrimaryColor(color) => {
let document_data = &mut self.tool_state.document_tool_data;
document_data.primary_color = color;
update_working_colors(&self.tool_state.document_tool_data, responses);
}
SelectSecondaryColor(color) => {
let document_data = &mut self.tool_state.document_tool_data;
document_data.secondary_color = color;
update_working_colors(document_data, responses);
}
SetToolOptions(tool_type, tool_options) => {
let document_data = &mut self.tool_state.document_tool_data;
document_data.tool_options.insert(tool_type, tool_options);
}
SwapColors => {
let document_data = &mut self.tool_state.document_tool_data;
std::mem::swap(&mut document_data.primary_color, &mut document_data.secondary_color);
update_working_colors(document_data, responses);
}
tool_message => {
let tool_type = message_to_tool_type(&tool_message);
let document_data = &self.tool_state.document_tool_data;
let tool_data = &mut self.tool_state.tool_data;
if let Some(tool) = tool_data.tools.get_mut(&tool_type) {
if tool_type == tool_data.active_tool_type {
tool.process_action(tool_message, (document, document_data, input), responses);
}
}
}
}
}
fn actions(&self) -> ActionList {
let mut list = actions!(ToolMessageDiscriminant; ResetColors, SwapColors, ActivateTool, SetToolOptions);
list.extend(self.tool_state.tool_data.active_tool().actions());
list
}
}