Event broadcasting system (#692)

* broadcast system implemented but not everywhere

* unused types

* code review with keavon

* - optional signal mappings
- tool.rs simplification

* Cleanup

* reduced code duplication in `tool.rs`

* ran cargo fmt

* code review changes

* fix merge error

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
mfish33
2022-07-03 08:06:27 -06:00
committed by Keavon Chambers
co-authored by Keavon Chambers
parent c343aaa3ab
commit a6c91204d6
35 changed files with 634 additions and 451 deletions
+130 -249
View File
@@ -31,8 +31,61 @@ pub struct DocumentToolData {
pub secondary_color: Color,
}
pub trait ToolCommon: for<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> + PropertyHolder {}
impl<T> ToolCommon for T where T: for<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> + PropertyHolder {}
#[derive(Clone, Debug)]
pub struct SignalToMessageMap {
pub document_dirty: Option<ToolMessage>,
pub selection_changed: Option<ToolMessage>,
pub tool_abort: Option<ToolMessage>,
}
pub trait ToolTransition {
fn signal_to_message_map(&self) -> SignalToMessageMap;
fn activate(&self, responses: &mut VecDeque<Message>) {
let mut subscribe_message = |broadcast_to_tool_mapping: Option<ToolMessage>, signal: BroadcastSignal| {
if let Some(mapping) = broadcast_to_tool_mapping {
responses.push_back(
BroadcastMessage::SubscribeSignal {
on: signal,
send: Box::new(mapping.into()),
}
.into(),
);
};
};
let signal_to_tool_map = self.signal_to_message_map();
subscribe_message(signal_to_tool_map.document_dirty, BroadcastSignal::DocumentIsDirty);
subscribe_message(signal_to_tool_map.tool_abort, BroadcastSignal::ToolAbort);
subscribe_message(signal_to_tool_map.selection_changed, BroadcastSignal::SelectionChanged);
}
fn deactivate(&self, responses: &mut VecDeque<Message>) {
let mut unsubscribe_message = |broadcast_to_tool_mapping: Option<ToolMessage>, signal: BroadcastSignal| {
if let Some(mapping) = broadcast_to_tool_mapping {
responses.push_back(
BroadcastMessage::UnsubscribeSignal {
on: signal,
message: Box::new(mapping.into()),
}
.into(),
);
};
};
let signal_to_tool_map = self.signal_to_message_map();
unsubscribe_message(signal_to_tool_map.document_dirty, BroadcastSignal::DocumentIsDirty);
unsubscribe_message(signal_to_tool_map.tool_abort, BroadcastSignal::ToolAbort);
unsubscribe_message(signal_to_tool_map.selection_changed, BroadcastSignal::SelectionChanged);
}
}
pub trait ToolMetadata {
fn icon_name(&self) -> String;
fn tooltip(&self) -> String;
fn tool_type(&self) -> ToolType;
}
pub trait ToolCommon: for<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> + PropertyHolder + ToolTransition + ToolMetadata {}
impl<T> ToolCommon for T where T: for<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> + PropertyHolder + ToolTransition + ToolMetadata {}
type Tool = dyn ToolCommon;
@@ -57,24 +110,33 @@ impl ToolData {
}
}
#[derive(Debug)]
pub struct ToolBarMetadataGroup {
pub tooltip: String,
pub icon_name: String,
pub tool_type: ToolType,
}
impl PropertyHolder for ToolData {
fn properties(&self) -> Layout {
let tool_groups_layout = ToolType::list_tools_in_groups()
let tool_groups_layout = list_tools_in_groups()
.iter()
.map(|tool_group| tool_group.iter().map(|tool| ToolBarMetadataGroup {tooltip: tool.tooltip(), icon_name: tool.icon_name(), tool_type: tool.tool_type()}).collect::<Vec<_>>())
.chain(coming_soon_tools())
.flat_map(|group| {
let separator = std::iter::once(WidgetHolder::new(Widget::Separator(Separator {
direction: SeparatorDirection::Vertical,
separator_type: SeparatorType::Section,
})));
let buttons = group.iter().map(|tool_type| {
let buttons = group.into_iter().map(|ToolBarMetadataGroup {tooltip, tool_type, icon_name}| {
WidgetHolder::new(Widget::IconButton(IconButton {
icon: tool_type.icon_name(),
icon: icon_name,
size: 32,
tooltip: tool_type.tooltip(),
active: self.active_tool_type == *tool_type,
on_update: WidgetCallback::new(|_| {
if !tool_type.tooltip().contains("Coming Soon") {
ToolMessage::ActivateTool { tool_type: *tool_type }.into()
tooltip: tooltip.clone(),
active: self.active_tool_type == tool_type,
on_update: WidgetCallback::new(move |_| {
if !tooltip.contains("Coming Soon") {
ToolMessage::ActivateTool { tool_type }.into()
} else {
DialogMessage::RequestComingSoonDialog { issue: None }.into()
}
@@ -105,34 +167,7 @@ impl Default for ToolFsmState {
ToolFsmState {
tool_data: ToolData {
active_tool_type: ToolType::Select,
tools: gen_tools_hash_map! {
// General
Select => select_tool::SelectTool,
Artboard => artboard_tool::ArtboardTool,
Navigate => navigate_tool::NavigateTool,
Eyedropper => eyedropper_tool::EyedropperTool,
Fill => fill_tool::FillTool,
Gradient => gradient_tool::GradientTool,
// Vector
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,
Text => text_tool::TextTool,
// Raster
// Brush => brush_tool::BrushTool,
// Heal => heal_tool::HealTool,
// Clone => clone_tool:::CloneTool,
// Patch => patch_tool:::PatchTool,
// Relight => relight_tool:::RelightTool,
// Detail => detail_tool:::DetailTool,
},
tools: list_tools_in_groups().into_iter().flatten().map(|tool| (tool.tool_type(), tool)).collect(),
},
document_tool_data: DocumentToolData {
primary_color: Color::BLACK,
@@ -183,213 +218,66 @@ pub enum ToolType {
Relight,
}
impl ToolType {
/// List of all the tools in their conventional ordering and grouping.
pub fn list_tools_in_groups() -> [&'static [ToolType]; 3] {
[
&[
// General tool group
ToolType::Select,
ToolType::Artboard,
ToolType::Navigate,
ToolType::Eyedropper,
ToolType::Fill,
ToolType::Gradient,
],
&[
// Vector tool group
ToolType::Path,
ToolType::Pen,
ToolType::Freehand,
ToolType::Spline,
ToolType::Line,
ToolType::Rectangle,
ToolType::Ellipse,
ToolType::Shape,
ToolType::Text,
],
&[
// Raster tool group
ToolType::Brush,
ToolType::Heal,
ToolType::Clone,
ToolType::Patch,
ToolType::Detail,
ToolType::Relight,
],
]
}
pub fn icon_name(&self) -> String {
match self {
/// List of all the tools in their conventional ordering and grouping.
pub fn list_tools_in_groups() -> Vec<Vec<Box<Tool>>> {
vec![
vec![
// General tool group
ToolType::Select => "GeneralSelectTool".into(),
ToolType::Artboard => "GeneralArtboardTool".into(),
ToolType::Navigate => "GeneralNavigateTool".into(),
ToolType::Eyedropper => "GeneralEyedropperTool".into(),
ToolType::Fill => "GeneralFillTool".into(),
ToolType::Gradient => "GeneralGradientTool".into(),
Box::new(select_tool::SelectTool::default()),
Box::new(artboard_tool::ArtboardTool::default()),
Box::new(navigate_tool::NavigateTool::default()),
Box::new(eyedropper_tool::EyedropperTool::default()),
Box::new(fill_tool::FillTool::default()),
Box::new(gradient_tool::GradientTool::default()),
],
vec![
// Vector tool group
ToolType::Path => "VectorPathTool".into(),
ToolType::Pen => "VectorPenTool".into(),
ToolType::Freehand => "VectorFreehandTool".into(),
ToolType::Spline => "VectorSplineTool".into(),
ToolType::Line => "VectorLineTool".into(),
ToolType::Rectangle => "VectorRectangleTool".into(),
ToolType::Ellipse => "VectorEllipseTool".into(),
ToolType::Shape => "VectorShapeTool".into(),
ToolType::Text => "VectorTextTool".into(),
// Raster tool group
ToolType::Brush => "RasterBrushTool".into(),
ToolType::Heal => "RasterHealTool".into(),
ToolType::Clone => "RasterCloneTool".into(),
ToolType::Patch => "RasterPatchTool".into(),
ToolType::Detail => "RasterDetailTool".into(),
ToolType::Relight => "RasterRelightTool".into(),
}
}
pub fn tooltip(&self) -> String {
match self {
// General tool group
ToolType::Select => "Select Tool (V)".into(),
ToolType::Artboard => "Artboard Tool".into(),
ToolType::Navigate => "Navigate Tool (Z)".into(),
ToolType::Eyedropper => "Eyedropper Tool (I)".into(),
ToolType::Fill => "Fill Tool (F)".into(),
ToolType::Gradient => "Gradient Tool (H)".into(),
// Vector tool group
ToolType::Path => "Path Tool (A)".into(),
ToolType::Pen => "Pen Tool (P)".into(),
ToolType::Freehand => "Freehand Tool (N)".into(),
ToolType::Spline => "Spline Tool".into(),
ToolType::Line => "Line Tool (L)".into(),
ToolType::Rectangle => "Rectangle Tool (M)".into(),
ToolType::Ellipse => "Ellipse Tool (E)".into(),
ToolType::Shape => "Shape Tool (Y)".into(),
ToolType::Text => "Text Tool (T)".into(),
// Raster tool group
ToolType::Brush => "Coming Soon: Brush Tool (B)".into(),
ToolType::Heal => "Coming Soon: Heal Tool (J)".into(),
ToolType::Clone => "Coming Soon: Clone Tool (C)".into(),
ToolType::Patch => "Coming Soon: Patch Tool".into(),
ToolType::Detail => "Coming Soon: Detail Tool (D)".into(),
ToolType::Relight => "Coming Soon: Relight Tool (O)".into(),
}
}
Box::new(path_tool::PathTool::default()),
Box::new(pen_tool::PenTool::default()),
Box::new(freehand_tool::FreehandTool::default()),
Box::new(spline_tool::SplineTool::default()),
Box::new(line_tool::LineTool::default()),
Box::new(rectangle_tool::RectangleTool::default()),
Box::new(ellipse_tool::EllipseTool::default()),
Box::new(shape_tool::ShapeTool::default()),
Box::new(text_tool::TextTool::default()),
],
]
}
impl fmt::Display for ToolType {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
use ToolType::*;
let name = match_variant_name!(match (self) {
// General tool group
Select,
Artboard,
Navigate,
Eyedropper,
Fill,
Gradient,
// Vector tool group
Path,
Pen,
Freehand,
Spline,
Line,
Rectangle,
Ellipse,
Shape,
Text,
// Raster tool group
Brush,
Heal,
Clone,
Patch,
Detail,
Relight,
});
formatter.write_str(name)
}
}
pub enum StandardToolMessageType {
Abort,
DocumentIsDirty,
SelectionChanged,
}
// TODO: Find a nicer way in Rust to make this generic so we don't have to manually map to enum variants
pub fn standard_tool_message(tool: ToolType, message_type: StandardToolMessageType) -> Option<ToolMessage> {
match message_type {
StandardToolMessageType::DocumentIsDirty => match tool {
// General tool group
ToolType::Select => Some(SelectToolMessage::DocumentIsDirty.into()),
ToolType::Artboard => Some(ArtboardToolMessage::DocumentIsDirty.into()),
ToolType::Navigate => None, // Some(NavigateToolMessage::DocumentIsDirty.into()),
ToolType::Eyedropper => None, // Some(EyedropperToolMessage::DocumentIsDirty.into()),
ToolType::Fill => None, // Some(FillToolMessage::DocumentIsDirty.into()),
ToolType::Gradient => Some(GradientToolMessage::DocumentIsDirty.into()),
// Vector tool group
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()),
ToolType::Text => Some(TextMessage::DocumentIsDirty.into()),
// Raster tool group
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::Detail => None, // Some(DetailToolMessage::DocumentIsDirty.into()),
ToolType::Relight => None, // Some(RelightMessage::DocumentIsDirty.into()),
pub fn coming_soon_tools() -> Vec<Vec<ToolBarMetadataGroup>> {
vec![vec![
ToolBarMetadataGroup {
tool_type: ToolType::Brush,
icon_name: "RasterBrushTool".into(),
tooltip: "Coming Soon: Brush Tool (B)".into(),
},
StandardToolMessageType::Abort => match tool {
// General tool group
ToolType::Select => Some(SelectToolMessage::Abort.into()),
ToolType::Artboard => Some(ArtboardToolMessage::Abort.into()),
ToolType::Navigate => Some(NavigateToolMessage::Abort.into()),
ToolType::Eyedropper => Some(EyedropperToolMessage::Abort.into()),
ToolType::Fill => Some(FillToolMessage::Abort.into()),
ToolType::Gradient => Some(GradientToolMessage::Abort.into()),
// Vector tool group
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()),
ToolType::Text => Some(TextMessage::Abort.into()),
// Raster tool group
ToolType::Brush => None, // Some(BrushMessage::Abort.into()),
ToolType::Heal => None, // Some(HealMessage::Abort.into()),
ToolType::Clone => None, // Some(CloneMessage::Abort.into()),
ToolType::Patch => None, // Some(PatchMessage::Abort.into()),
ToolType::Detail => None, // Some(DetailToolMessage::Abort.into()),
ToolType::Relight => None, // Some(RelightMessage::Abort.into()),
ToolBarMetadataGroup {
tool_type: ToolType::Heal,
icon_name: "RasterHealTool".into(),
tooltip: "Coming Soon: Heal Tool (J)".into(),
},
StandardToolMessageType::SelectionChanged => match tool {
ToolType::Path => Some(PathToolMessage::SelectionChanged.into()),
_ => None,
ToolBarMetadataGroup {
tool_type: ToolType::Clone,
icon_name: "RasterCloneTool".into(),
tooltip: "Coming Soon: Clone Tool (C))".into(),
},
}
ToolBarMetadataGroup {
tool_type: ToolType::Patch,
icon_name: "RasterPatchTool".into(),
tooltip: "Coming Soon: Patch Tool".into(),
},
ToolBarMetadataGroup {
tool_type: ToolType::Detail,
icon_name: "RasterDetailTool".into(),
tooltip: "Coming Soon: Detail Tool (D)".into(),
},
ToolBarMetadataGroup {
tool_type: ToolType::Relight,
icon_name: "RasterRelightTool".into(),
tooltip: "Coming Soon: Relight Tool (O".into(),
},
]]
}
pub fn message_to_tool_type(message: &ToolMessage) -> ToolType {
@@ -422,16 +310,9 @@ pub fn message_to_tool_type(message: &ToolMessage) -> ToolType {
// Patch(_) => ToolType::Patch,
// Detail(_) => ToolType::Detail,
// Relight(_) => ToolType::Relight,
_ => panic!("Conversion from message to tool type impossible because the given ToolMessage does not belong to a tool"),
_ => panic!(
"Conversion from message to tool type impossible because the given ToolMessage does not belong to a tool. Got: {:?}",
message
),
}
}
pub fn update_working_colors(document_data: &DocumentToolData, responses: &mut VecDeque<Message>) {
responses.push_back(
FrontendMessage::UpdateWorkingColors {
primary: document_data.primary_color,
secondary: document_data.secondary_color,
}
.into(),
);
}
@@ -76,15 +76,11 @@ pub enum ToolMessage {
// Messages
#[remain::unsorted]
NoOp,
AbortCurrentTool,
ActivateTool {
tool_type: ToolType,
},
DocumentIsDirty,
InitTools,
ResetColors,
SelectionChanged,
SelectPrimaryColor {
color: Color,
},
@@ -1,4 +1,4 @@
use super::tool::{message_to_tool_type, standard_tool_message, update_working_colors, StandardToolMessageType, ToolFsmState};
use super::tool::{message_to_tool_type, DocumentToolData, ToolFsmState};
use crate::document::DocumentMessageHandler;
use crate::input::InputPreprocessorMessageHandler;
use crate::layout::layout_message::LayoutTarget;
@@ -24,11 +24,6 @@ impl MessageHandler<ToolMessage, (&DocumentMessageHandler, &InputPreprocessorMes
#[remain::sorted]
match message {
// Messages
AbortCurrentTool => {
if let Some(tool_message) = standard_tool_message(self.tool_state.tool_data.active_tool_type, StandardToolMessageType::Abort) {
responses.push_front(tool_message.into());
}
}
ActivateTool { tool_type } => {
let tool_data = &mut self.tool_state.tool_data;
let document_data = &self.tool_state.document_tool_data;
@@ -40,9 +35,11 @@ impl MessageHandler<ToolMessage, (&DocumentMessageHandler, &InputPreprocessorMes
}
// Send the Abort state transition to the tool
let mut send_abort_to_tool = |tool_type, message: ToolMessage, update_hints_and_cursor: bool| {
let mut send_abort_to_tool = |tool_type, update_hints_and_cursor: bool| {
if let Some(tool) = tool_data.tools.get_mut(&tool_type) {
tool.process_action(message, (document, document_data, input, font_cache), responses);
if let Some(tool_abort_message) = tool.signal_to_message_map().tool_abort {
tool.process_action(tool_abort_message, (document, document_data, input, font_cache), responses);
}
if update_hints_and_cursor {
tool.process_action(ToolMessage::UpdateHints, (document, document_data, input, font_cache), responses);
@@ -50,45 +47,40 @@ impl MessageHandler<ToolMessage, (&DocumentMessageHandler, &InputPreprocessorMes
}
}
};
// Send the old and new tools a transition to their FSM Abort states
if let Some(tool_message) = standard_tool_message(tool_type, StandardToolMessageType::Abort) {
send_abort_to_tool(tool_type, 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_abort_to_tool(tool_type, true);
send_abort_to_tool(old_tool, false);
// Send the SelectionChanged message to the active tool, this will ensure the selection is updated
if let Some(message) = standard_tool_message(tool_type, StandardToolMessageType::SelectionChanged) {
responses.push_back(message.into());
}
// Send the DocumentIsDirty message to the active tool's sub-tool message handler
if let Some(message) = standard_tool_message(tool_type, StandardToolMessageType::DocumentIsDirty) {
responses.push_back(message.into());
}
// Unsubscribe old tool from the broadcaster
tool_data.tools.get(&tool_type).unwrap().deactivate(responses);
// Store the new active tool
tool_data.active_tool_type = tool_type;
// Subscribe new tool
tool_data.tools.get(&tool_type).unwrap().activate(responses);
// Send the SelectionChanged message to the active tool, this will ensure the selection is updated
responses.push_back(BroadcastSignal::SelectionChanged.into());
// Send the DocumentIsDirty message to the active tool's sub-tool message handler
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
// Send Properties to the frontend
tool_data.tools.get(&tool_type).unwrap().register_properties(responses, LayoutTarget::ToolOptions);
// Notify the frontend about the new active tool to be displayed
tool_data.register_properties(responses, LayoutTarget::ToolShelf);
}
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());
}
}
InitTools => {
let tool_data = &mut self.tool_state.tool_data;
let document_data = &self.tool_state.document_tool_data;
let active_tool = &tool_data.active_tool_type;
// subscribe tool to broadcast messages
tool_data.tools.get(active_tool).unwrap().activate(responses);
// Register initial properties
tool_data.tools.get(active_tool).unwrap().register_properties(responses, LayoutTarget::ToolOptions);
@@ -111,12 +103,6 @@ impl MessageHandler<ToolMessage, (&DocumentMessageHandler, &InputPreprocessorMes
update_working_colors(document_data, responses);
}
SelectionChanged => {
let active_tool = self.tool_state.tool_data.active_tool_type;
if let Some(message) = standard_tool_message(active_tool, StandardToolMessageType::SelectionChanged) {
responses.push_back(message.into());
}
}
SelectPrimaryColor { color } => {
let document_data = &mut self.tool_state.document_tool_data;
document_data.primary_color = color;
@@ -176,3 +162,13 @@ impl MessageHandler<ToolMessage, (&DocumentMessageHandler, &InputPreprocessorMes
list
}
}
fn update_working_colors(document_data: &DocumentToolData, responses: &mut VecDeque<Message>) {
responses.push_back(
FrontendMessage::UpdateWorkingColors {
primary: document_data.primary_color,
secondary: document_data.secondary_color,
}
.into(),
);
}
@@ -6,7 +6,7 @@ use crate::layout::widgets::PropertyHolder;
use crate::message_prelude::*;
use crate::misc::{HintData, HintGroup, HintInfo, KeysGroup};
use crate::viewport_tools::snapping::SnapHandler;
use crate::viewport_tools::tool::{Fsm, ToolActionHandlerData};
use crate::viewport_tools::tool::{Fsm, SignalToMessageMap, ToolActionHandlerData, ToolMetadata, ToolTransition, ToolType};
use graphene::intersection::Quad;
@@ -41,6 +41,18 @@ pub enum ArtboardToolMessage {
PointerUp,
}
impl ToolMetadata for ArtboardTool {
fn icon_name(&self) -> String {
"GeneralArtboardTool".into()
}
fn tooltip(&self) -> String {
"Artboard Tool".into()
}
fn tool_type(&self) -> crate::viewport_tools::tool::ToolType {
ToolType::Artboard
}
}
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for ArtboardTool {
fn process_action(&mut self, action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque<Message>) {
if action == ToolMessage::UpdateHints {
@@ -66,6 +78,16 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for ArtboardTool
impl PropertyHolder for ArtboardTool {}
impl ToolTransition for ArtboardTool {
fn signal_to_message_map(&self) -> SignalToMessageMap {
SignalToMessageMap {
document_dirty: Some(ArtboardToolMessage::DocumentIsDirty.into()),
tool_abort: Some(ArtboardToolMessage::Abort.into()),
selection_changed: None,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum ArtboardToolFsmState {
Ready,
@@ -168,7 +190,7 @@ impl Fsm for ArtboardToolFsmState {
let quad = Quad::from_box([input.mouse.position - tolerance, input.mouse.position + tolerance]);
let intersection = document.artboard_message_handler.artboards_graphene_document.intersects_quad_root(quad, font_cache);
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
if let Some(intersection) = intersection.last() {
tool_data.selected_board = Some(intersection[0]);
@@ -229,7 +251,7 @@ impl Fsm for ArtboardToolFsmState {
.into(),
);
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
}
}
ArtboardToolFsmState::ResizingBounds
@@ -257,7 +279,7 @@ impl Fsm for ArtboardToolFsmState {
.into(),
);
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
tool_data.drag_current = mouse_position + closest_move;
}
@@ -303,7 +325,7 @@ impl Fsm for ArtboardToolFsmState {
.into(),
);
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
ArtboardToolFsmState::Drawing
}
@@ -333,7 +355,7 @@ impl Fsm for ArtboardToolFsmState {
bounds.original_transforms.clear();
}
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
ArtboardToolFsmState::Ready
}
@@ -349,7 +371,7 @@ impl Fsm for ArtboardToolFsmState {
(_, ArtboardToolMessage::DeleteSelected) => {
if let Some(artboard) = tool_data.selected_board.take() {
responses.push_back(ArtboardMessage::DeleteArtboard { artboard }.into());
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
}
ArtboardToolFsmState::Ready
}
@@ -5,7 +5,7 @@ use crate::input::keyboard::{Key, MouseMotion};
use crate::layout::widgets::PropertyHolder;
use crate::message_prelude::*;
use crate::misc::{HintData, HintGroup, HintInfo, KeysGroup};
use crate::viewport_tools::tool::{Fsm, ToolActionHandlerData};
use crate::viewport_tools::tool::{Fsm, SignalToMessageMap, ToolActionHandlerData, ToolMetadata, ToolTransition, ToolType};
use graphene::layers::style;
use graphene::Operation;
@@ -36,6 +36,18 @@ pub enum EllipseToolMessage {
},
}
impl ToolMetadata for EllipseTool {
fn icon_name(&self) -> String {
"VectorEllipseTool".into()
}
fn tooltip(&self) -> String {
"Ellipse Tool (E)".into()
}
fn tool_type(&self) -> crate::viewport_tools::tool::ToolType {
ToolType::Ellipse
}
}
impl PropertyHolder for EllipseTool {}
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for EllipseTool {
@@ -69,6 +81,16 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for EllipseTool
}
}
impl ToolTransition for EllipseTool {
fn signal_to_message_map(&self) -> SignalToMessageMap {
SignalToMessageMap {
document_dirty: None,
tool_abort: Some(EllipseToolMessage::Abort.into()),
selection_changed: None,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum EllipseToolFsmState {
Ready,
@@ -4,7 +4,7 @@ use crate::input::keyboard::MouseMotion;
use crate::layout::widgets::PropertyHolder;
use crate::message_prelude::*;
use crate::misc::{HintData, HintGroup, HintInfo};
use crate::viewport_tools::tool::{Fsm, ToolActionHandlerData};
use crate::viewport_tools::tool::{Fsm, SignalToMessageMap, ToolActionHandlerData, ToolMetadata, ToolTransition, ToolType};
use graphene::intersection::Quad;
use graphene::layers::layer_info::LayerDataType;
@@ -31,6 +31,18 @@ pub enum EyedropperToolMessage {
RightMouseDown,
}
impl ToolMetadata for EyedropperTool {
fn icon_name(&self) -> String {
"GeneralEyedropperTool".into()
}
fn tooltip(&self) -> String {
"Eyedropper Tool (I)".into()
}
fn tool_type(&self) -> crate::viewport_tools::tool::ToolType {
ToolType::Eyedropper
}
}
impl PropertyHolder for EyedropperTool {}
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for EyedropperTool {
@@ -57,6 +69,16 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for EyedropperTo
advertise_actions!(EyedropperToolMessageDiscriminant; LeftMouseDown, RightMouseDown);
}
impl ToolTransition for EyedropperTool {
fn signal_to_message_map(&self) -> SignalToMessageMap {
SignalToMessageMap {
document_dirty: None,
tool_abort: Some(EyedropperToolMessage::Abort.into()),
selection_changed: None,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum EyedropperToolFsmState {
Ready,
+23 -1
View File
@@ -4,7 +4,7 @@ use crate::input::keyboard::MouseMotion;
use crate::layout::widgets::PropertyHolder;
use crate::message_prelude::*;
use crate::misc::{HintData, HintGroup, HintInfo};
use crate::viewport_tools::tool::{Fsm, ToolActionHandlerData};
use crate::viewport_tools::tool::{Fsm, SignalToMessageMap, ToolActionHandlerData, ToolMetadata, ToolTransition, ToolType};
use graphene::intersection::Quad;
use graphene::Operation;
@@ -32,6 +32,18 @@ pub enum FillToolMessage {
RightMouseDown,
}
impl ToolMetadata for FillTool {
fn icon_name(&self) -> String {
"GeneralFillTool".into()
}
fn tooltip(&self) -> String {
"Fill Tool (F)".into()
}
fn tool_type(&self) -> crate::viewport_tools::tool::ToolType {
ToolType::Fill
}
}
impl PropertyHolder for FillTool {}
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for FillTool {
@@ -58,6 +70,16 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for FillTool {
advertise_actions!(FillToolMessageDiscriminant; LeftMouseDown, RightMouseDown);
}
impl ToolTransition for FillTool {
fn signal_to_message_map(&self) -> SignalToMessageMap {
SignalToMessageMap {
document_dirty: None,
tool_abort: Some(FillToolMessage::Abort.into()),
selection_changed: None,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum FillToolFsmState {
Ready,
@@ -3,7 +3,7 @@ use crate::input::keyboard::MouseMotion;
use crate::layout::widgets::{Layout, LayoutGroup, NumberInput, PropertyHolder, Widget, WidgetCallback, WidgetHolder, WidgetLayout};
use crate::message_prelude::*;
use crate::misc::{HintData, HintGroup, HintInfo};
use crate::viewport_tools::tool::{DocumentToolData, Fsm, ToolActionHandlerData};
use crate::viewport_tools::tool::{DocumentToolData, Fsm, SignalToMessageMap, ToolActionHandlerData, ToolMetadata, ToolTransition, ToolType};
use graphene::layers::style;
use graphene::Operation;
@@ -55,6 +55,18 @@ enum FreehandToolFsmState {
Drawing,
}
impl ToolMetadata for FreehandTool {
fn icon_name(&self) -> String {
"VectorFreehandTool".into()
}
fn tooltip(&self) -> String {
"Freehand Tool (N)".into()
}
fn tool_type(&self) -> crate::viewport_tools::tool::ToolType {
ToolType::Freehand
}
}
impl PropertyHolder for FreehandTool {
fn properties(&self) -> Layout {
Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row {
@@ -109,6 +121,16 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for FreehandTool
}
}
impl ToolTransition for FreehandTool {
fn signal_to_message_map(&self) -> SignalToMessageMap {
SignalToMessageMap {
document_dirty: None,
tool_abort: Some(FreehandToolMessage::Abort.into()),
selection_changed: None,
}
}
}
impl Default for FreehandToolFsmState {
fn default() -> Self {
FreehandToolFsmState::Ready
@@ -6,7 +6,7 @@ use crate::layout::widgets::{Layout, LayoutGroup, PropertyHolder, RadioEntryData
use crate::message_prelude::*;
use crate::misc::{HintData, HintGroup, HintInfo, KeysGroup};
use crate::viewport_tools::snapping::SnapHandler;
use crate::viewport_tools::tool::{Fsm, ToolActionHandlerData};
use crate::viewport_tools::tool::{Fsm, SignalToMessageMap, ToolActionHandlerData, ToolMetadata, ToolTransition, ToolType};
use graphene::color::Color;
use graphene::intersection::Quad;
@@ -60,6 +60,18 @@ pub enum GradientOptionsUpdate {
Type(GradientType),
}
impl ToolMetadata for GradientTool {
fn icon_name(&self) -> String {
"GeneralGradientTool".into()
}
fn tooltip(&self) -> String {
"Gradient Tool (H))".into()
}
fn tool_type(&self) -> crate::viewport_tools::tool::ToolType {
ToolType::Gradient
}
}
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for GradientTool {
fn process_action(&mut self, action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque<Message>) {
if action == ToolMessage::UpdateHints {
@@ -284,6 +296,16 @@ impl SelectedGradient {
}
}
impl ToolTransition for GradientTool {
fn signal_to_message_map(&self) -> SignalToMessageMap {
SignalToMessageMap {
document_dirty: Some(GradientToolMessage::DocumentIsDirty.into()),
tool_abort: Some(GradientToolMessage::Abort.into()),
selection_changed: None,
}
}
}
#[derive(Clone, Debug, Default)]
struct GradientToolData {
gradient_overlays: Vec<GradientOverlay>,
@@ -332,7 +354,7 @@ impl Fsm for GradientToolFsmState {
self
}
(GradientToolFsmState::Ready, GradientToolMessage::PointerDown) => {
responses.push_back(ToolMessage::DocumentIsDirty.into());
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
let mouse = input.mouse.position;
let tolerance = VECTOR_MANIPULATOR_ANCHOR_MARKER_SIZE.powi(2);
+23 -1
View File
@@ -6,7 +6,7 @@ use crate::layout::widgets::{Layout, LayoutGroup, NumberInput, PropertyHolder, W
use crate::message_prelude::*;
use crate::misc::{HintData, HintGroup, HintInfo, KeysGroup};
use crate::viewport_tools::snapping::SnapHandler;
use crate::viewport_tools::tool::{Fsm, ToolActionHandlerData};
use crate::viewport_tools::tool::{Fsm, SignalToMessageMap, ToolActionHandlerData, ToolMetadata, ToolTransition, ToolType};
use graphene::layers::style;
use graphene::Operation;
@@ -56,6 +56,18 @@ pub enum LineOptionsUpdate {
LineWeight(f64),
}
impl ToolMetadata for LineTool {
fn icon_name(&self) -> String {
"VectorLineTool".into()
}
fn tooltip(&self) -> String {
"Line Tool (L)".into()
}
fn tool_type(&self) -> crate::viewport_tools::tool::ToolType {
ToolType::Line
}
}
impl PropertyHolder for LineTool {
fn properties(&self) -> Layout {
Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row {
@@ -110,6 +122,16 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for LineTool {
}
}
impl ToolTransition for LineTool {
fn signal_to_message_map(&self) -> SignalToMessageMap {
SignalToMessageMap {
document_dirty: None,
tool_abort: Some(LineToolMessage::Abort.into()),
selection_changed: None,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum LineToolFsmState {
Ready,
@@ -3,7 +3,7 @@ use crate::input::keyboard::{Key, MouseMotion};
use crate::layout::widgets::PropertyHolder;
use crate::message_prelude::*;
use crate::misc::{HintData, HintGroup, HintInfo, KeysGroup};
use crate::viewport_tools::tool::{Fsm, ToolActionHandlerData};
use crate::viewport_tools::tool::{Fsm, SignalToMessageMap, ToolActionHandlerData, ToolMetadata, ToolTransition, ToolType};
use glam::DVec2;
use serde::{Deserialize, Serialize};
@@ -36,6 +36,18 @@ pub enum NavigateToolMessage {
ZoomCanvasBegin,
}
impl ToolMetadata for NavigateTool {
fn icon_name(&self) -> String {
"GeneralNavigateTool".into()
}
fn tooltip(&self) -> String {
"Navigate Tool (Z)".into()
}
fn tool_type(&self) -> crate::viewport_tools::tool::ToolType {
ToolType::Navigate
}
}
impl PropertyHolder for NavigateTool {}
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for NavigateTool {
@@ -69,6 +81,16 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for NavigateTool
}
}
impl ToolTransition for NavigateTool {
fn signal_to_message_map(&self) -> SignalToMessageMap {
SignalToMessageMap {
document_dirty: None,
tool_abort: Some(NavigateToolMessage::Abort.into()),
selection_changed: None,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum NavigateToolFsmState {
Ready,
+23 -1
View File
@@ -5,7 +5,7 @@ use crate::layout::widgets::PropertyHolder;
use crate::message_prelude::*;
use crate::misc::{HintData, HintGroup, HintInfo, KeysGroup};
use crate::viewport_tools::snapping::SnapHandler;
use crate::viewport_tools::tool::{Fsm, ToolActionHandlerData};
use crate::viewport_tools::tool::{Fsm, SignalToMessageMap, ToolActionHandlerData, ToolMetadata, ToolTransition, ToolType};
use crate::viewport_tools::vector_editor::shape_editor::ShapeEditor;
use graphene::intersection::Quad;
@@ -42,6 +42,18 @@ pub enum PathToolMessage {
},
}
impl ToolMetadata for PathTool {
fn icon_name(&self) -> String {
"VectorPathTool".into()
}
fn tooltip(&self) -> String {
"Path Tool (A)".into()
}
fn tool_type(&self) -> crate::viewport_tools::tool::ToolType {
ToolType::Path
}
}
impl PropertyHolder for PathTool {}
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for PathTool {
@@ -76,6 +88,16 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for PathTool {
}
}
impl ToolTransition for PathTool {
fn signal_to_message_map(&self) -> SignalToMessageMap {
SignalToMessageMap {
document_dirty: Some(PathToolMessage::DocumentIsDirty.into()),
tool_abort: Some(PathToolMessage::Abort.into()),
selection_changed: Some(PathToolMessage::SelectionChanged.into()),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum PathToolFsmState {
Ready,
+23 -1
View File
@@ -7,7 +7,7 @@ use crate::layout::widgets::{Layout, LayoutGroup, NumberInput, PropertyHolder, W
use crate::message_prelude::*;
use crate::misc::{HintData, HintGroup, HintInfo, KeysGroup};
use crate::viewport_tools::snapping::SnapHandler;
use crate::viewport_tools::tool::{Fsm, ToolActionHandlerData};
use crate::viewport_tools::tool::{Fsm, SignalToMessageMap, ToolActionHandlerData, ToolMetadata, ToolTransition, ToolType};
use crate::viewport_tools::vector_editor::constants::ControlPointType;
use crate::viewport_tools::vector_editor::shape_editor::ShapeEditor;
use crate::viewport_tools::vector_editor::vector_shape::VectorShape;
@@ -67,6 +67,18 @@ pub enum PenOptionsUpdate {
LineWeight(f64),
}
impl ToolMetadata for PenTool {
fn icon_name(&self) -> String {
"VectorPenTool".into()
}
fn tooltip(&self) -> String {
"Pen Tool (P)".into()
}
fn tool_type(&self) -> crate::viewport_tools::tool::ToolType {
ToolType::Pen
}
}
impl PropertyHolder for PenTool {
fn properties(&self) -> Layout {
Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row {
@@ -121,6 +133,16 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for PenTool {
}
}
impl ToolTransition for PenTool {
fn signal_to_message_map(&self) -> SignalToMessageMap {
SignalToMessageMap {
document_dirty: Some(PenToolMessage::DocumentIsDirty.into()),
tool_abort: Some(PenToolMessage::Abort.into()),
selection_changed: None,
}
}
}
impl Default for PenToolFsmState {
fn default() -> Self {
PenToolFsmState::Ready
@@ -5,7 +5,7 @@ use crate::input::keyboard::{Key, MouseMotion};
use crate::layout::widgets::PropertyHolder;
use crate::message_prelude::*;
use crate::misc::{HintData, HintGroup, HintInfo, KeysGroup};
use crate::viewport_tools::tool::{Fsm, ToolActionHandlerData};
use crate::viewport_tools::tool::{Fsm, SignalToMessageMap, ToolActionHandlerData, ToolMetadata, ToolTransition, ToolType};
use graphene::layers::style;
use graphene::Operation;
@@ -69,6 +69,28 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for RectangleToo
}
}
impl ToolMetadata for RectangleTool {
fn icon_name(&self) -> String {
"VectorRectangleTool".into()
}
fn tooltip(&self) -> String {
"Rectangle Tool (M)".into()
}
fn tool_type(&self) -> crate::viewport_tools::tool::ToolType {
ToolType::Rectangle
}
}
impl ToolTransition for RectangleTool {
fn signal_to_message_map(&self) -> SignalToMessageMap {
SignalToMessageMap {
document_dirty: None,
tool_abort: Some(RectangleToolMessage::Abort.into()),
selection_changed: None,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum RectangleToolFsmState {
Ready,
+24 -1
View File
@@ -8,7 +8,7 @@ use crate::layout::widgets::{IconButton, Layout, LayoutGroup, PopoverButton, Pro
use crate::message_prelude::*;
use crate::misc::{HintData, HintGroup, HintInfo, KeysGroup};
use crate::viewport_tools::snapping::{self, SnapHandler};
use crate::viewport_tools::tool::{Fsm, ToolActionHandlerData, ToolType};
use crate::viewport_tools::tool::{Fsm, SignalToMessageMap, ToolActionHandlerData, ToolMetadata, ToolTransition, ToolType};
use graphene::boolean_ops::BooleanOperation;
use graphene::document::Document;
use graphene::intersection::Quad;
@@ -56,6 +56,18 @@ pub enum SelectToolMessage {
},
}
impl ToolMetadata for SelectTool {
fn icon_name(&self) -> String {
"GeneralSelectTool".into()
}
fn tooltip(&self) -> String {
"Select Tool (V)".into()
}
fn tool_type(&self) -> crate::viewport_tools::tool::ToolType {
ToolType::Select
}
}
impl PropertyHolder for SelectTool {
fn properties(&self) -> Layout {
Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row {
@@ -258,6 +270,16 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for SelectTool {
}
}
impl ToolTransition for SelectTool {
fn signal_to_message_map(&self) -> SignalToMessageMap {
SignalToMessageMap {
document_dirty: Some(SelectToolMessage::DocumentIsDirty.into()),
tool_abort: Some(SelectToolMessage::Abort.into()),
selection_changed: None,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
enum SelectToolFsmState {
Ready,
@@ -317,6 +339,7 @@ impl Fsm for SelectToolFsmState {
use SelectToolMessage::*;
if let ToolMessage::Select(event) = event {
log::debug!("self: {:?}, even: {:?}", self, event);
match (self, event) {
(_, DocumentIsDirty) => {
let mut buffer = Vec::new();
+23 -1
View File
@@ -5,7 +5,7 @@ use crate::input::keyboard::{Key, MouseMotion};
use crate::layout::widgets::{Layout, LayoutGroup, NumberInput, PropertyHolder, Widget, WidgetCallback, WidgetHolder, WidgetLayout};
use crate::message_prelude::*;
use crate::misc::{HintData, HintGroup, HintInfo, KeysGroup};
use crate::viewport_tools::tool::{Fsm, ToolActionHandlerData};
use crate::viewport_tools::tool::{Fsm, SignalToMessageMap, ToolActionHandlerData, ToolMetadata, ToolTransition, ToolType};
use graphene::layers::style;
use graphene::Operation;
@@ -54,6 +54,18 @@ pub enum ShapeOptionsUpdate {
Vertices(u32),
}
impl ToolMetadata for ShapeTool {
fn icon_name(&self) -> String {
"VectorShapeTool".into()
}
fn tooltip(&self) -> String {
"Shape Tool (Y)".into()
}
fn tool_type(&self) -> crate::viewport_tools::tool::ToolType {
ToolType::Shape
}
}
impl PropertyHolder for ShapeTool {
fn properties(&self) -> Layout {
Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row {
@@ -108,6 +120,16 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for ShapeTool {
}
}
impl ToolTransition for ShapeTool {
fn signal_to_message_map(&self) -> SignalToMessageMap {
SignalToMessageMap {
document_dirty: None,
tool_abort: Some(ShapeToolMessage::Abort.into()),
selection_changed: None,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum ShapeToolFsmState {
Ready,
+23 -1
View File
@@ -5,7 +5,7 @@ use crate::layout::widgets::{Layout, LayoutGroup, NumberInput, PropertyHolder, W
use crate::message_prelude::*;
use crate::misc::{HintData, HintGroup, HintInfo, KeysGroup};
use crate::viewport_tools::snapping::SnapHandler;
use crate::viewport_tools::tool::{DocumentToolData, Fsm, ToolActionHandlerData};
use crate::viewport_tools::tool::{DocumentToolData, Fsm, SignalToMessageMap, ToolActionHandlerData, ToolMetadata, ToolTransition, ToolType};
use graphene::layers::style;
use graphene::Operation;
@@ -59,6 +59,18 @@ pub enum SplineOptionsUpdate {
LineWeight(f64),
}
impl ToolMetadata for SplineTool {
fn icon_name(&self) -> String {
"VectorSplineTool".into()
}
fn tooltip(&self) -> String {
"Spline Tool".into()
}
fn tool_type(&self) -> crate::viewport_tools::tool::ToolType {
ToolType::Spline
}
}
impl PropertyHolder for SplineTool {
fn properties(&self) -> Layout {
Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row {
@@ -113,6 +125,16 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for SplineTool {
}
}
impl ToolTransition for SplineTool {
fn signal_to_message_map(&self) -> SignalToMessageMap {
SignalToMessageMap {
document_dirty: None,
tool_abort: Some(SplineToolMessage::Abort.into()),
selection_changed: None,
}
}
}
impl Default for SplineToolFsmState {
fn default() -> Self {
SplineToolFsmState::Ready
+23 -1
View File
@@ -6,7 +6,7 @@ use crate::layout::layout_message::LayoutTarget;
use crate::layout::widgets::{FontInput, Layout, LayoutGroup, NumberInput, PropertyHolder, Separator, SeparatorDirection, SeparatorType, Widget, WidgetCallback, WidgetHolder, WidgetLayout};
use crate::message_prelude::*;
use crate::misc::{HintData, HintGroup, HintInfo, KeysGroup};
use crate::viewport_tools::tool::{Fsm, ToolActionHandlerData};
use crate::viewport_tools::tool::{Fsm, SignalToMessageMap, ToolActionHandlerData, ToolMetadata, ToolTransition, ToolType};
use graphene::intersection::Quad;
use graphene::layers::style::{self, Fill, Stroke};
@@ -70,6 +70,18 @@ pub enum TextOptionsUpdate {
FontSize(u32),
}
impl ToolMetadata for TextTool {
fn icon_name(&self) -> String {
"VectorTextTool".into()
}
fn tooltip(&self) -> String {
"Text Tool (T)".into()
}
fn tool_type(&self) -> crate::viewport_tools::tool::ToolType {
ToolType::Text
}
}
impl PropertyHolder for TextTool {
fn properties(&self) -> Layout {
Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row {
@@ -164,6 +176,16 @@ impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for TextTool {
}
}
impl ToolTransition for TextTool {
fn signal_to_message_map(&self) -> SignalToMessageMap {
SignalToMessageMap {
document_dirty: Some(TextMessage::DocumentIsDirty.into()),
tool_abort: Some(TextMessage::Abort.into()),
selection_changed: None,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum TextToolFsmState {
Ready,