From 43f532320a740865a453d808ec3bc2c439450811 Mon Sep 17 00:00:00 2001 From: Mohd Mohsin Date: Sat, 29 Mar 2025 15:57:13 +0530 Subject: [PATCH 01/13] Feat: implement the hierarchical tree for visualization --- .../src/messages/broadcast/broadcast_event.rs | 2 +- editor/src/messages/prelude.rs | 2 +- editor/src/utility_traits.rs | 5 ++ proc-macros/src/combined_message_attrs.rs | 4 +- proc-macros/src/hierarchical_tree.rs | 59 +++++++++++++++++++ proc-macros/src/lib.rs | 7 +++ 6 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 proc-macros/src/hierarchical_tree.rs diff --git a/editor/src/messages/broadcast/broadcast_event.rs b/editor/src/messages/broadcast/broadcast_event.rs index c0f5f96a56..0e8c3d40dd 100644 --- a/editor/src/messages/broadcast/broadcast_event.rs +++ b/editor/src/messages/broadcast/broadcast_event.rs @@ -1,7 +1,7 @@ use crate::messages::prelude::*; -#[derive(PartialEq, Eq, Clone, Debug, serde::Serialize, serde::Deserialize, Hash)] #[impl_message(Message, BroadcastMessage, TriggerEvent)] +#[derive(PartialEq, Eq, Clone, Debug, serde::Serialize, serde::Deserialize, Hash)] pub enum BroadcastEvent { AnimationFrame, CanvasTransformed, diff --git a/editor/src/messages/prelude.rs b/editor/src/messages/prelude.rs index 9e5a4a2c99..aa475770c6 100644 --- a/editor/src/messages/prelude.rs +++ b/editor/src/messages/prelude.rs @@ -1,5 +1,5 @@ // Root -pub use crate::utility_traits::{ActionList, AsMessage, MessageHandler, ToDiscriminant, TransitiveChild}; +pub use crate::utility_traits::{ActionList, AsMessage, MessageHandler, ToDiscriminant, TransitiveChild, HierarchicalTree}; // Message, MessageData, MessageDiscriminant, MessageHandler pub use crate::messages::animation::{AnimationMessage, AnimationMessageDiscriminant, AnimationMessageHandler}; diff --git a/editor/src/utility_traits.rs b/editor/src/utility_traits.rs index 711a8cc34b..d9fbed2883 100644 --- a/editor/src/utility_traits.rs +++ b/editor/src/utility_traits.rs @@ -45,3 +45,8 @@ pub trait TransitiveChild: Into + Into { pub trait Hint { fn hints(&self) -> HashMap; } + +pub trait HierarchicalTree { + fn display_tree() -> Vec; + fn display_enum_variants(depth: usize, tree: &mut Vec); +} diff --git a/proc-macros/src/combined_message_attrs.rs b/proc-macros/src/combined_message_attrs.rs index aadca6384e..943457cd1c 100644 --- a/proc-macros/src/combined_message_attrs.rs +++ b/proc-macros/src/combined_message_attrs.rs @@ -61,7 +61,7 @@ pub fn combined_message_attrs_impl(attr: TokenStream, input_item: TokenStream) - <#parent as ToDiscriminant>::Discriminant }; - input.attrs.push(syn::parse_quote! { #[derive(ToDiscriminant, TransitiveChild)] }); + input.attrs.push(syn::parse_quote! { #[derive(ToDiscriminant, TransitiveChild, HierarchicalTree)] }); input.attrs.push(syn::parse_quote! { #[parent(#parent, #parent::#variant)] }); if parent_is_top { input.attrs.push(syn::parse_quote! { #[parent_is_top] }); @@ -97,7 +97,7 @@ pub fn combined_message_attrs_impl(attr: TokenStream, input_item: TokenStream) - fn top_level_impl(input_item: TokenStream) -> syn::Result { let mut input = syn::parse2::(input_item)?; - input.attrs.push(syn::parse_quote! { #[derive(ToDiscriminant)] }); + input.attrs.push(syn::parse_quote! { #[derive(ToDiscriminant, HierarchicalTree)] }); input.attrs.push(syn::parse_quote! { #[discriminant_attr(derive(Debug, Copy, Clone, PartialEq, Eq, Hash, AsMessage))] }); for var in &mut input.variants { diff --git a/proc-macros/src/hierarchical_tree.rs b/proc-macros/src/hierarchical_tree.rs new file mode 100644 index 0000000000..b32bbb427a --- /dev/null +++ b/proc-macros/src/hierarchical_tree.rs @@ -0,0 +1,59 @@ +use proc_macro2::{Span, TokenStream}; +use quote::{ToTokens, quote}; +use syn::{Data, DeriveInput, Fields, Type, parse2}; + +pub fn generate_hierarchical_tree(input: TokenStream) -> syn::Result { + let input = parse2::(input)?; + let input_type = &input.ident; + + let data = match &input.data { + Data::Enum(data) => data, + _ => return Err(syn::Error::new(Span::call_site(), "Tried to derive HierarchicalTree for non-enum")), + }; + + let variant_prints = data.variants.iter().enumerate().map(|(index, variant)| { + let variant_type = &variant.ident; + let is_last = index == data.variants.len() - 1; + let tree_symbol = if is_last { "└──" } else { "├──" }; + + let has_child = variant + .attrs + .iter() + .any(|attr| attr.path().get_ident().map_or(false, |ident| ident == "sub_discriminant" || ident == "child")); + + if has_child { + if let Fields::Unnamed(fields) = &variant.fields { + let field_type = &fields.unnamed.first().unwrap().ty; + quote! { + tree.push(format!("{}{}{}", "│ ".repeat(depth), #tree_symbol, stringify!(#variant_type))); + <#field_type>::display_enum_variants(depth + 1, tree); + } + } else { + quote! { + tree.push(format!("{}{}{}", "│ ".repeat(depth), #tree_symbol, stringify!(#variant_type))); + } + } + } else { + quote! { + tree.push(format!("{}{}{}", "│ ".repeat(depth), #tree_symbol, stringify!(#variant_type))); + } + } + }); + + let res = quote! { + impl HierarchicalTree for #input_type { + fn display_tree() -> Vec { + let mut hierarchical_tree = Vec::new(); + hierarchical_tree.push(format!("{}", stringify!(#input_type))); + Self::display_enum_variants(0, &mut hierarchical_tree); + hierarchical_tree + } + + fn display_enum_variants(depth: usize, tree: &mut Vec) { + #(#variant_prints)* + } + } + }; + + Ok(res) +} diff --git a/proc-macros/src/lib.rs b/proc-macros/src/lib.rs index 88ded95c6c..4404df00b1 100644 --- a/proc-macros/src/lib.rs +++ b/proc-macros/src/lib.rs @@ -5,6 +5,7 @@ mod combined_message_attrs; mod discriminant; mod helper_structs; mod helpers; +mod hierarchical_tree; mod hint; mod transitive_child; mod widget_builder; @@ -16,6 +17,7 @@ use crate::helper_structs::AttrInnerSingleString; use crate::hint::derive_hint_impl; use crate::transitive_child::derive_transitive_child_impl; use crate::widget_builder::derive_widget_builder_impl; +use hierarchical_tree::generate_hierarchical_tree; use proc_macro::TokenStream; /// Derive the `ToDiscriminant` trait and create a `Discriminant` enum @@ -281,6 +283,11 @@ pub fn derive_widget_builder(input_item: TokenStream) -> TokenStream { TokenStream::from(derive_widget_builder_impl(input_item.into()).unwrap_or_else(|err| err.to_compile_error())) } +#[proc_macro_derive(HierarchicalTree)] +pub fn derive_hierarchical_tree(input_item: TokenStream) -> TokenStream { + TokenStream::from(generate_hierarchical_tree(input_item.into()).unwrap_or_else(|err| err.to_compile_error())) +} + #[cfg(test)] mod tests { use super::*; From f9ee826a8c7c4437138b5fe0a1011fea0d572e06 Mon Sep 17 00:00:00 2001 From: Mohd Mohsin Date: Sun, 30 Mar 2025 04:36:14 +0530 Subject: [PATCH 02/13] rename HierarchicalTree trait function --- editor/src/utility_traits.rs | 4 ++-- proc-macros/src/hierarchical_tree.rs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/editor/src/utility_traits.rs b/editor/src/utility_traits.rs index d9fbed2883..8b2c6251b3 100644 --- a/editor/src/utility_traits.rs +++ b/editor/src/utility_traits.rs @@ -47,6 +47,6 @@ pub trait Hint { } pub trait HierarchicalTree { - fn display_tree() -> Vec; - fn display_enum_variants(depth: usize, tree: &mut Vec); + fn generate_hierarchical_tree() -> Vec; + fn generate_enum_variants(depth: usize, tree: &mut Vec); } diff --git a/proc-macros/src/hierarchical_tree.rs b/proc-macros/src/hierarchical_tree.rs index b32bbb427a..d8cb20bb00 100644 --- a/proc-macros/src/hierarchical_tree.rs +++ b/proc-macros/src/hierarchical_tree.rs @@ -26,7 +26,7 @@ pub fn generate_hierarchical_tree(input: TokenStream) -> syn::Result::display_enum_variants(depth + 1, tree); + <#field_type>::generate_enum_variants(depth + 1, tree); } } else { quote! { @@ -42,14 +42,14 @@ pub fn generate_hierarchical_tree(input: TokenStream) -> syn::Result Vec { + fn generate_hierarchical_tree() -> Vec { let mut hierarchical_tree = Vec::new(); hierarchical_tree.push(format!("{}", stringify!(#input_type))); - Self::display_enum_variants(0, &mut hierarchical_tree); + Self::generate_enum_variants(0, &mut hierarchical_tree); hierarchical_tree } - fn display_enum_variants(depth: usize, tree: &mut Vec) { + fn generate_enum_variants(depth: usize, tree: &mut Vec) { #(#variant_prints)* } } From 0f9e49183663a1968777b48d05807edf63d5b380 Mon Sep 17 00:00:00 2001 From: Mohd Mohsin Date: Sat, 12 Apr 2025 21:17:20 +0530 Subject: [PATCH 03/13] feat: change the HierarchicalTree from String to DebugMessageTree struct --- editor/src/messages/debug/mod.rs | 2 ++ editor/src/messages/debug/utility_types.rs | 30 +++++++++++++++++++ editor/src/messages/message.rs | 35 ++++++++++++++++++++++ editor/src/messages/prelude.rs | 4 +-- editor/src/utility_traits.rs | 3 +- proc-macros/src/hierarchical_tree.rs | 33 ++++++++++---------- 6 files changed, 87 insertions(+), 20 deletions(-) diff --git a/editor/src/messages/debug/mod.rs b/editor/src/messages/debug/mod.rs index 79ad968d15..696c0ffb5a 100644 --- a/editor/src/messages/debug/mod.rs +++ b/editor/src/messages/debug/mod.rs @@ -3,6 +3,8 @@ mod debug_message_handler; pub mod utility_types; +pub use utility_types::DebugMessageTree; + #[doc(inline)] pub use debug_message::{DebugMessage, DebugMessageDiscriminant}; #[doc(inline)] diff --git a/editor/src/messages/debug/utility_types.rs b/editor/src/messages/debug/utility_types.rs index 027dd14f2a..c8459d2334 100644 --- a/editor/src/messages/debug/utility_types.rs +++ b/editor/src/messages/debug/utility_types.rs @@ -5,3 +5,33 @@ pub enum MessageLoggingVerbosity { Names, Contents, } + +pub struct DebugMessageTree { + name: String, + variants: Option>, +} + +impl DebugMessageTree { + pub fn new(name: &str) -> DebugMessageTree { + DebugMessageTree { + name: name.to_string(), + variants: None, + } + } + + pub fn add_variant(&mut self, variant: DebugMessageTree) { + if let Some(variants) = &mut self.variants { + variants.push(variant); + } else { + self.variants = Some(vec![variant]); + } + } + + pub fn name(&self) -> &str { + &self.name + } + + pub fn variants(&self) -> Option<&Vec> { + self.variants.as_ref() + } +} diff --git a/editor/src/messages/message.rs b/editor/src/messages/message.rs index 80323d9309..4c84d55c53 100644 --- a/editor/src/messages/message.rs +++ b/editor/src/messages/message.rs @@ -45,3 +45,38 @@ impl specta::Type for MessageDiscriminant { specta::DataType::Any } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn generate_message_tree() { + let res = Message::build_message_tree(); + println!("{}", res.name()); + if let Some(variants) = res.variants() { + for (i, variant) in variants.iter().enumerate() { + let is_last = i == variants.len() - 1; + print_tree_node(variant, "", is_last); + } + } + } + + fn print_tree_node(tree: &DebugMessageTree, prefix: &str, is_last: bool) { + // Print the current node + let branch = if is_last { "└── " } else { "├── " }; + println!("{}{}{}", prefix, branch, tree.name()); + + // Prepare prefix for children + let child_prefix = if is_last { format!("{} ", prefix) } else { format!("{}│ ", prefix) }; + + // Print children if any + if let Some(variants) = tree.variants() { + let len = variants.len(); + for (i, variant) in variants.iter().enumerate() { + let is_last_child = i == len - 1; + print_tree_node(variant, &child_prefix, is_last_child); + } + } + } +} diff --git a/editor/src/messages/prelude.rs b/editor/src/messages/prelude.rs index aa475770c6..338b3bd975 100644 --- a/editor/src/messages/prelude.rs +++ b/editor/src/messages/prelude.rs @@ -1,10 +1,10 @@ // Root -pub use crate::utility_traits::{ActionList, AsMessage, MessageHandler, ToDiscriminant, TransitiveChild, HierarchicalTree}; +pub use crate::utility_traits::{ActionList, AsMessage, HierarchicalTree, MessageHandler, ToDiscriminant, TransitiveChild}; // Message, MessageData, MessageDiscriminant, MessageHandler pub use crate::messages::animation::{AnimationMessage, AnimationMessageDiscriminant, AnimationMessageHandler}; pub use crate::messages::broadcast::{BroadcastMessage, BroadcastMessageDiscriminant, BroadcastMessageHandler}; -pub use crate::messages::debug::{DebugMessage, DebugMessageDiscriminant, DebugMessageHandler}; +pub use crate::messages::debug::{DebugMessage, DebugMessageDiscriminant, DebugMessageHandler, DebugMessageTree}; pub use crate::messages::dialog::export_dialog::{ExportDialogMessage, ExportDialogMessageData, ExportDialogMessageDiscriminant, ExportDialogMessageHandler}; pub use crate::messages::dialog::new_document_dialog::{NewDocumentDialogMessage, NewDocumentDialogMessageDiscriminant, NewDocumentDialogMessageHandler}; pub use crate::messages::dialog::preferences_dialog::{PreferencesDialogMessage, PreferencesDialogMessageData, PreferencesDialogMessageDiscriminant, PreferencesDialogMessageHandler}; diff --git a/editor/src/utility_traits.rs b/editor/src/utility_traits.rs index 8b2c6251b3..d5b4a361b2 100644 --- a/editor/src/utility_traits.rs +++ b/editor/src/utility_traits.rs @@ -47,6 +47,5 @@ pub trait Hint { } pub trait HierarchicalTree { - fn generate_hierarchical_tree() -> Vec; - fn generate_enum_variants(depth: usize, tree: &mut Vec); + fn build_message_tree() -> DebugMessageTree; } diff --git a/proc-macros/src/hierarchical_tree.rs b/proc-macros/src/hierarchical_tree.rs index d8cb20bb00..7ca61fc3a1 100644 --- a/proc-macros/src/hierarchical_tree.rs +++ b/proc-macros/src/hierarchical_tree.rs @@ -11,10 +11,8 @@ pub fn generate_hierarchical_tree(input: TokenStream) -> syn::Result return Err(syn::Error::new(Span::call_site(), "Tried to derive HierarchicalTree for non-enum")), }; - let variant_prints = data.variants.iter().enumerate().map(|(index, variant)| { + let build_message_tree = data.variants.iter().map(|variant| { let variant_type = &variant.ident; - let is_last = index == data.variants.len() - 1; - let tree_symbol = if is_last { "└──" } else { "├──" }; let has_child = variant .attrs @@ -25,32 +23,35 @@ pub fn generate_hierarchical_tree(input: TokenStream) -> syn::Result::generate_enum_variants(depth + 1, tree); + { + let mut variant_tree = DebugMessageTree::new(stringify!(#variant_type)); + let field_name = stringify!(#field_type); + if "Message" == &field_name[field_name.len().saturating_sub(7)..] { + // The field is a Message type, recursively build its tree + let sub_tree = #field_type::build_message_tree(); + variant_tree.add_variant(sub_tree); + } + message_tree.add_variant(variant_tree); + } } } else { quote! { - tree.push(format!("{}{}{}", "│ ".repeat(depth), #tree_symbol, stringify!(#variant_type))); + message_tree.add_variant(DebugMessageTree::new(stringify!(#variant_type))); } } } else { quote! { - tree.push(format!("{}{}{}", "│ ".repeat(depth), #tree_symbol, stringify!(#variant_type))); + message_tree.add_variant(DebugMessageTree::new(stringify!(#variant_type))); } } }); let res = quote! { impl HierarchicalTree for #input_type { - fn generate_hierarchical_tree() -> Vec { - let mut hierarchical_tree = Vec::new(); - hierarchical_tree.push(format!("{}", stringify!(#input_type))); - Self::generate_enum_variants(0, &mut hierarchical_tree); - hierarchical_tree - } - - fn generate_enum_variants(depth: usize, tree: &mut Vec) { - #(#variant_prints)* + fn build_message_tree() -> DebugMessageTree { + let mut message_tree = DebugMessageTree::new(stringify!(#input_type)); + #(#build_message_tree)* + message_tree } } }; From e232c5dea4232c6a42234638010373f3b10b1c9a Mon Sep 17 00:00:00 2001 From: Keavon Chambers Date: Thu, 17 Apr 2025 18:07:15 -0700 Subject: [PATCH 04/13] Nits --- editor/src/messages/broadcast/broadcast_event.rs | 2 +- proc-macros/src/hierarchical_tree.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/editor/src/messages/broadcast/broadcast_event.rs b/editor/src/messages/broadcast/broadcast_event.rs index 8d8ec0d054..ebe2318aae 100644 --- a/editor/src/messages/broadcast/broadcast_event.rs +++ b/editor/src/messages/broadcast/broadcast_event.rs @@ -1,7 +1,7 @@ use crate::messages::prelude::*; -#[impl_message(Message, BroadcastMessage, TriggerEvent)] #[derive(PartialEq, Eq, Clone, Debug, serde::Serialize, serde::Deserialize, Hash)] +#[impl_message(Message, BroadcastMessage, TriggerEvent)] pub enum BroadcastEvent { /// Triggered by requestAnimationFrame in JS AnimationFrame, diff --git a/proc-macros/src/hierarchical_tree.rs b/proc-macros/src/hierarchical_tree.rs index 7ca61fc3a1..7cce612729 100644 --- a/proc-macros/src/hierarchical_tree.rs +++ b/proc-macros/src/hierarchical_tree.rs @@ -17,7 +17,7 @@ pub fn generate_hierarchical_tree(input: TokenStream) -> syn::Result Date: Sat, 19 Apr 2025 15:23:55 +0530 Subject: [PATCH 05/13] feat: impliment proc macro to extract field from messagedata structs --- .../messages/dialog/dialog_message_handler.rs | 1 + .../export_dialog_message_handler.rs | 1 + .../preferences_dialog_message_handler.rs | 1 + .../input_mapper_message_handler.rs | 1 + .../key_mapping_message_handler.rs | 1 + .../input_preprocessor_message_handler.rs | 1 + .../document/document_message_handler.rs | 1 + .../graph_operation_message_handler.rs | 1 + .../navigation/navigation_message_handler.rs | 1 + .../node_graph/node_graph_message_handler.rs | 2 +- .../overlays/overlays_message_handler.rs | 1 + .../portfolio/portfolio_message_handler.rs | 1 + .../src/messages/tool/tool_message_handler.rs | 11 +++++ proc-macros/src/extract_fields.rs | 48 +++++++++++++++++++ proc-macros/src/lib.rs | 7 +++ 15 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 proc-macros/src/extract_fields.rs diff --git a/editor/src/messages/dialog/dialog_message_handler.rs b/editor/src/messages/dialog/dialog_message_handler.rs index 3e9c80e46a..5979f3b1c3 100644 --- a/editor/src/messages/dialog/dialog_message_handler.rs +++ b/editor/src/messages/dialog/dialog_message_handler.rs @@ -2,6 +2,7 @@ use super::simple_dialogs::{self, AboutGraphiteDialog, ComingSoonDialog, DemoArt use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::prelude::*; +#[derive(ExtractField)] pub struct DialogMessageData<'a> { pub portfolio: &'a PortfolioMessageHandler, pub preferences: &'a PreferencesMessageHandler, diff --git a/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs b/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs index 5c4d6b4924..ba41a52964 100644 --- a/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs +++ b/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs @@ -3,6 +3,7 @@ use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::prelude::*; +#[derive(ExtractField)] pub struct ExportDialogMessageData<'a> { pub portfolio: &'a PortfolioMessageHandler, } diff --git a/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs b/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs index 5c4aa75f8e..778bbd9107 100644 --- a/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs +++ b/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs @@ -4,6 +4,7 @@ use crate::messages::portfolio::document::node_graph::utility_types::GraphWireSt use crate::messages::preferences::SelectionMode; use crate::messages::prelude::*; +#[derive(ExtractField)] pub struct PreferencesDialogMessageData<'a> { pub preferences: &'a PreferencesMessageHandler, } diff --git a/editor/src/messages/input_mapper/input_mapper_message_handler.rs b/editor/src/messages/input_mapper/input_mapper_message_handler.rs index 744f86d976..78926104bd 100644 --- a/editor/src/messages/input_mapper/input_mapper_message_handler.rs +++ b/editor/src/messages/input_mapper/input_mapper_message_handler.rs @@ -5,6 +5,7 @@ use crate::messages::portfolio::utility_types::KeyboardPlatformLayout; use crate::messages::prelude::*; use std::fmt::Write; +#[derive(ExtractField)] pub struct InputMapperMessageData<'a> { pub input: &'a InputPreprocessorMessageHandler, pub actions: ActionList, diff --git a/editor/src/messages/input_mapper/key_mapping/key_mapping_message_handler.rs b/editor/src/messages/input_mapper/key_mapping/key_mapping_message_handler.rs index 0378bf0ccb..225ea0f4b4 100644 --- a/editor/src/messages/input_mapper/key_mapping/key_mapping_message_handler.rs +++ b/editor/src/messages/input_mapper/key_mapping/key_mapping_message_handler.rs @@ -2,6 +2,7 @@ use crate::messages::input_mapper::input_mapper_message_handler::InputMapperMess use crate::messages::input_mapper::utility_types::input_keyboard::KeysGroup; use crate::messages::prelude::*; +#[derive(ExtractField)] pub struct KeyMappingMessageData<'a> { pub input: &'a InputPreprocessorMessageHandler, pub actions: ActionList, diff --git a/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs b/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs index b78022575d..ffc4edc1a5 100644 --- a/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs +++ b/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs @@ -5,6 +5,7 @@ use crate::messages::portfolio::utility_types::KeyboardPlatformLayout; use crate::messages::prelude::*; use glam::DVec2; +#[derive(ExtractField)] pub struct InputPreprocessorMessageData { pub keyboard_platform: KeyboardPlatformLayout, } diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index 8039c62e3c..8549159d78 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -35,6 +35,7 @@ use graphene_std::renderer::{ClickTarget, Quad}; use graphene_std::vector::{PointId, path_bool_lib}; use std::time::Duration; +#[derive(ExtractField)] pub struct DocumentMessageData<'a> { pub document_id: DocumentId, pub ipp: &'a InputPreprocessorMessageHandler, diff --git a/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs b/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs index 645b66a1d9..9e753fd6f2 100644 --- a/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs +++ b/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs @@ -20,6 +20,7 @@ struct ArtboardInfo { merge_node: NodeId, } +#[derive(ExtractField)] pub struct GraphOperationMessageData<'a> { pub network_interface: &'a mut NodeNetworkInterface, pub collapsed: &'a mut CollapsedLayers, diff --git a/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs b/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs index 881505706b..1208eacc78 100644 --- a/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs +++ b/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs @@ -13,6 +13,7 @@ use crate::messages::tool::utility_types::{HintData, HintGroup, HintInfo}; use glam::{DAffine2, DVec2}; use graph_craft::document::NodeId; +#[derive(ExtractField)] pub struct NavigationMessageData<'a> { pub network_interface: &'a mut NodeNetworkInterface, pub breadcrumb_network_path: &'a [NodeId], diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs index 3757372a05..2a6e1270c1 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs @@ -24,7 +24,7 @@ use graphene_core::*; use renderer::Quad; use std::cmp::Ordering; -#[derive(Debug)] +#[derive(Debug, ExtractField)] pub struct NodeGraphHandlerData<'a> { pub network_interface: &'a mut NodeNetworkInterface, pub selection_network_path: &'a [NodeId], diff --git a/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs b/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs index 6a78d2cac8..7b937cc446 100644 --- a/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs +++ b/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs @@ -1,6 +1,7 @@ use super::utility_types::OverlayProvider; use crate::messages::prelude::*; +#[derive(ExtractField)] pub struct OverlaysMessageData<'a> { pub overlays_visible: bool, pub ipp: &'a InputPreprocessorMessageHandler, diff --git a/editor/src/messages/portfolio/portfolio_message_handler.rs b/editor/src/messages/portfolio/portfolio_message_handler.rs index a74d6ce8f7..53dcbd02c2 100644 --- a/editor/src/messages/portfolio/portfolio_message_handler.rs +++ b/editor/src/messages/portfolio/portfolio_message_handler.rs @@ -28,6 +28,7 @@ use interpreted_executor::dynamic_executor::IntrospectError; use std::sync::Arc; use std::vec; +#[derive(ExtractField)] pub struct PortfolioMessageData<'a> { pub ipp: &'a InputPreprocessorMessageHandler, pub preferences: &'a PreferencesMessageHandler, diff --git a/editor/src/messages/tool/tool_message_handler.rs b/editor/src/messages/tool/tool_message_handler.rs index 3eaffb86c0..495ddfbe44 100644 --- a/editor/src/messages/tool/tool_message_handler.rs +++ b/editor/src/messages/tool/tool_message_handler.rs @@ -11,6 +11,7 @@ use graphene_core::raster::color::Color; const ARTBOARD_OVERLAY_PROVIDER: OverlayProvider = |context| DocumentMessage::DrawArtboardOverlays(context).into(); +#[derive(ExtractField)] pub struct ToolMessageData<'a> { pub document_id: DocumentId, pub document: &'a mut DocumentMessageHandler, @@ -327,3 +328,13 @@ impl MessageHandler> for ToolMessageHandler { list } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn print_field() { + ToolMessageData::print_field_types(); + } +} diff --git a/proc-macros/src/extract_fields.rs b/proc-macros/src/extract_fields.rs new file mode 100644 index 0000000000..015191ccec --- /dev/null +++ b/proc-macros/src/extract_fields.rs @@ -0,0 +1,48 @@ +use proc_macro2::{Span, TokenStream}; +use quote::{ToTokens, format_ident, quote}; +use syn::{Data, DeriveInput, Fields, Type, parse2}; + +pub fn derive_extract_field_impl(input: TokenStream) -> syn::Result { + let input = parse2::(input)?; + let struct_name = &input.ident; + let generics = &input.generics; + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + let fields = match &input.data { + Data::Struct(data) => match &data.fields { + Fields::Named(fields) => &fields.named, + _ => return Err(syn::Error::new(Span::call_site(), "ExtractField only works on structs with named fields")), + }, + _ => return Err(syn::Error::new(Span::call_site(), "ExtractField only works on structs")), + }; + + // Extract field names and types as strings at compile time + let field_info = fields + .iter() + .map(|field| { + let name = field.ident.as_ref().unwrap().to_string(); + let ty = field.ty.to_token_stream().to_string(); + (name, ty) + }) + .collect::>(); + + let field_str = field_info.into_iter().map(|(name, ty)| format!("{}: {}", name, ty)); + + let res = quote! { + impl #impl_generics #struct_name #ty_generics #where_clause { + pub fn field_types() -> Vec { + vec![ + #(String::from(#field_str)),* + ] + } + + pub fn print_field_types() { + for field in Self::field_types() { + println!("{}", field); + } + } + } + }; + + Ok(res) +} diff --git a/proc-macros/src/lib.rs b/proc-macros/src/lib.rs index 4404df00b1..22bf332500 100644 --- a/proc-macros/src/lib.rs +++ b/proc-macros/src/lib.rs @@ -3,6 +3,7 @@ mod as_message; mod combined_message_attrs; mod discriminant; +mod extract_fields; mod helper_structs; mod helpers; mod hierarchical_tree; @@ -13,6 +14,7 @@ mod widget_builder; use crate::as_message::derive_as_message_impl; use crate::combined_message_attrs::combined_message_attrs_impl; use crate::discriminant::derive_discriminant_impl; +use crate::extract_fields::derive_extract_field_impl; use crate::helper_structs::AttrInnerSingleString; use crate::hint::derive_hint_impl; use crate::transitive_child::derive_transitive_child_impl; @@ -288,6 +290,11 @@ pub fn derive_hierarchical_tree(input_item: TokenStream) -> TokenStream { TokenStream::from(generate_hierarchical_tree(input_item.into()).unwrap_or_else(|err| err.to_compile_error())) } +#[proc_macro_derive(ExtractField)] +pub fn derive_extract_field(input_item: TokenStream) -> TokenStream { + TokenStream::from(derive_extract_field_impl(input_item.into()).unwrap_or_else(|err| err.to_compile_error())) +} + #[cfg(test)] mod tests { use super::*; From dcfbb97bf14f22763d125a336bd98e55fff3868d Mon Sep 17 00:00:00 2001 From: Mohd Mohsin Date: Wed, 23 Apr 2025 21:25:13 +0530 Subject: [PATCH 06/13] update the hierarchical-tree for hanlder data --- .../animation/animation_message_handler.rs | 1 + .../broadcast/broadcast_message_handler.rs | 1 + .../messages/debug/debug_message_handler.rs | 1 + editor/src/messages/debug/utility_types.rs | 27 +++++++ .../messages/dialog/dialog_message_handler.rs | 1 + .../export_dialog_message_handler.rs | 1 + .../new_document_dialog_message_handler.rs | 1 + .../preferences_dialog_message_handler.rs | 1 + .../globals/globals_message_handler.rs | 1 + .../input_mapper_message_handler.rs | 1 + .../key_mapping_message_handler.rs | 1 + .../input_preprocessor_message_handler.rs | 1 + .../messages/layout/layout_message_handler.rs | 5 ++ editor/src/messages/message.rs | 26 +++++-- .../document/document_message_handler.rs | 1 + .../graph_operation_message_handler.rs | 1 + .../navigation/navigation_message_handler.rs | 1 + .../node_graph/node_graph_message_handler.rs | 1 + .../overlays/overlays_message_handler.rs | 1 + .../properties_panel_message_handler.rs | 1 + .../menu_bar/menu_bar_message_handler.rs | 1 + .../portfolio/portfolio_message_handler.rs | 1 + .../spreadsheet_message_handler.rs | 1 + .../preferences_message_handler.rs | 1 + .../src/messages/tool/tool_message_handler.rs | 11 +-- .../transform_layer_message_handler.rs | 11 +++ .../workspace/workspace_message_handler.rs | 1 + editor/src/utility_traits.rs | 4 ++ proc-macros/src/hierarchical_tree.rs | 4 ++ proc-macros/src/lib.rs | 9 ++- proc-macros/src/message_handler_data_attr.rs | 72 +++++++++++++++++++ 31 files changed, 176 insertions(+), 15 deletions(-) create mode 100644 proc-macros/src/message_handler_data_attr.rs diff --git a/editor/src/messages/animation/animation_message_handler.rs b/editor/src/messages/animation/animation_message_handler.rs index eb7ceba2e0..a265197075 100644 --- a/editor/src/messages/animation/animation_message_handler.rs +++ b/editor/src/messages/animation/animation_message_handler.rs @@ -57,6 +57,7 @@ impl AnimationMessageHandler { } } +#[message_handler_data] impl MessageHandler for AnimationMessageHandler { fn process_message(&mut self, message: AnimationMessage, responses: &mut VecDeque, _data: ()) { match message { diff --git a/editor/src/messages/broadcast/broadcast_message_handler.rs b/editor/src/messages/broadcast/broadcast_message_handler.rs index 51d64b5852..21d572a511 100644 --- a/editor/src/messages/broadcast/broadcast_message_handler.rs +++ b/editor/src/messages/broadcast/broadcast_message_handler.rs @@ -5,6 +5,7 @@ pub struct BroadcastMessageHandler { listeners: HashMap>, } +#[message_handler_data] impl MessageHandler for BroadcastMessageHandler { fn process_message(&mut self, message: BroadcastMessage, responses: &mut VecDeque, _data: ()) { match message { diff --git a/editor/src/messages/debug/debug_message_handler.rs b/editor/src/messages/debug/debug_message_handler.rs index 6044ce9108..270ae9bfa9 100644 --- a/editor/src/messages/debug/debug_message_handler.rs +++ b/editor/src/messages/debug/debug_message_handler.rs @@ -6,6 +6,7 @@ pub struct DebugMessageHandler { pub message_logging_verbosity: MessageLoggingVerbosity, } +#[message_handler_data] impl MessageHandler for DebugMessageHandler { fn process_message(&mut self, message: DebugMessage, responses: &mut VecDeque, _data: ()) { match message { diff --git a/editor/src/messages/debug/utility_types.rs b/editor/src/messages/debug/utility_types.rs index c8459d2334..047e52cdfb 100644 --- a/editor/src/messages/debug/utility_types.rs +++ b/editor/src/messages/debug/utility_types.rs @@ -6,9 +6,27 @@ pub enum MessageLoggingVerbosity { Contents, } +#[derive(Debug)] +pub struct MessageData { + name: String, + fields: Vec, +} + +impl MessageData { + pub fn name(&self) -> &str { + &self.name + } + + pub fn fields(&self) -> &Vec { + &self.fields + } +} + +#[derive(Debug)] pub struct DebugMessageTree { name: String, variants: Option>, + data: Option, } impl DebugMessageTree { @@ -16,6 +34,7 @@ impl DebugMessageTree { DebugMessageTree { name: name.to_string(), variants: None, + data: None, } } @@ -27,6 +46,10 @@ impl DebugMessageTree { } } + pub fn add_data_field(&mut self, name: String, fields: Vec) { + self.data = Some(MessageData { name, fields }); + } + pub fn name(&self) -> &str { &self.name } @@ -34,4 +57,8 @@ impl DebugMessageTree { pub fn variants(&self) -> Option<&Vec> { self.variants.as_ref() } + + pub fn data_fields(&self) -> Option<&MessageData> { + self.data.as_ref() + } } diff --git a/editor/src/messages/dialog/dialog_message_handler.rs b/editor/src/messages/dialog/dialog_message_handler.rs index 5979f3b1c3..8530ea2f94 100644 --- a/editor/src/messages/dialog/dialog_message_handler.rs +++ b/editor/src/messages/dialog/dialog_message_handler.rs @@ -16,6 +16,7 @@ pub struct DialogMessageHandler { preferences_dialog: PreferencesDialogMessageHandler, } +#[message_handler_data] impl MessageHandler> for DialogMessageHandler { fn process_message(&mut self, message: DialogMessage, responses: &mut VecDeque, data: DialogMessageData) { let DialogMessageData { portfolio, preferences } = data; diff --git a/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs b/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs index ba41a52964..63f53c4ac1 100644 --- a/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs +++ b/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs @@ -32,6 +32,7 @@ impl Default for ExportDialogMessageHandler { } } +#[message_handler_data] impl MessageHandler> for ExportDialogMessageHandler { fn process_message(&mut self, message: ExportDialogMessage, responses: &mut VecDeque, data: ExportDialogMessageData) { let ExportDialogMessageData { portfolio } = data; diff --git a/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs b/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs index fd095df90e..c712ba9d3c 100644 --- a/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs +++ b/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs @@ -11,6 +11,7 @@ pub struct NewDocumentDialogMessageHandler { pub dimensions: UVec2, } +#[message_handler_data] impl MessageHandler for NewDocumentDialogMessageHandler { fn process_message(&mut self, message: NewDocumentDialogMessage, responses: &mut VecDeque, _data: ()) { match message { diff --git a/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs b/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs index 778bbd9107..e82d4f9316 100644 --- a/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs +++ b/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs @@ -13,6 +13,7 @@ pub struct PreferencesDialogMessageData<'a> { #[derive(Debug, Clone, Default)] pub struct PreferencesDialogMessageHandler {} +#[message_handler_data] impl MessageHandler> for PreferencesDialogMessageHandler { fn process_message(&mut self, message: PreferencesDialogMessage, responses: &mut VecDeque, data: PreferencesDialogMessageData) { let PreferencesDialogMessageData { preferences } = data; diff --git a/editor/src/messages/globals/globals_message_handler.rs b/editor/src/messages/globals/globals_message_handler.rs index 5651555f60..d46872d2ed 100644 --- a/editor/src/messages/globals/globals_message_handler.rs +++ b/editor/src/messages/globals/globals_message_handler.rs @@ -3,6 +3,7 @@ use crate::messages::prelude::*; #[derive(Debug, Default)] pub struct GlobalsMessageHandler {} +#[message_handler_data] impl MessageHandler for GlobalsMessageHandler { fn process_message(&mut self, message: GlobalsMessage, _responses: &mut VecDeque, _data: ()) { match message { diff --git a/editor/src/messages/input_mapper/input_mapper_message_handler.rs b/editor/src/messages/input_mapper/input_mapper_message_handler.rs index 78926104bd..6cb2c458b7 100644 --- a/editor/src/messages/input_mapper/input_mapper_message_handler.rs +++ b/editor/src/messages/input_mapper/input_mapper_message_handler.rs @@ -16,6 +16,7 @@ pub struct InputMapperMessageHandler { mapping: Mapping, } +#[message_handler_data] impl MessageHandler> for InputMapperMessageHandler { fn process_message(&mut self, message: InputMapperMessage, responses: &mut VecDeque, data: InputMapperMessageData) { let InputMapperMessageData { input, actions } = data; diff --git a/editor/src/messages/input_mapper/key_mapping/key_mapping_message_handler.rs b/editor/src/messages/input_mapper/key_mapping/key_mapping_message_handler.rs index 225ea0f4b4..a886bebe72 100644 --- a/editor/src/messages/input_mapper/key_mapping/key_mapping_message_handler.rs +++ b/editor/src/messages/input_mapper/key_mapping/key_mapping_message_handler.rs @@ -13,6 +13,7 @@ pub struct KeyMappingMessageHandler { mapping_handler: InputMapperMessageHandler, } +#[message_handler_data] impl MessageHandler> for KeyMappingMessageHandler { fn process_message(&mut self, message: KeyMappingMessage, responses: &mut VecDeque, data: KeyMappingMessageData) { let KeyMappingMessageData { input, actions } = data; diff --git a/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs b/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs index 7aab89bd70..714f54f31c 100644 --- a/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs +++ b/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs @@ -20,6 +20,7 @@ pub struct InputPreprocessorMessageHandler { pub viewport_bounds: ViewportBounds, } +#[message_handler_data] impl MessageHandler for InputPreprocessorMessageHandler { fn process_message(&mut self, message: InputPreprocessorMessage, responses: &mut VecDeque, data: InputPreprocessorMessageData) { let InputPreprocessorMessageData { keyboard_platform } = data; diff --git a/editor/src/messages/layout/layout_message_handler.rs b/editor/src/messages/layout/layout_message_handler.rs index a35861d680..b4d5c38fe1 100644 --- a/editor/src/messages/layout/layout_message_handler.rs +++ b/editor/src/messages/layout/layout_message_handler.rs @@ -338,6 +338,7 @@ impl LayoutMessageHandler { } } +#[message_handler_data(CustomData)] impl Vec> MessageHandler for LayoutMessageHandler { fn process_message(&mut self, message: LayoutMessage, responses: &mut std::collections::VecDeque, action_input_mapping: F) { match message { @@ -438,3 +439,7 @@ impl LayoutMessageHandler { responses.add(message); } } + +pub fn custom_data() -> Vec { + vec![String::from("Fn(&MessageDiscriminant) -> Vec")] +} diff --git a/editor/src/messages/message.rs b/editor/src/messages/message.rs index 4c84d55c53..80f9c187e8 100644 --- a/editor/src/messages/message.rs +++ b/editor/src/messages/message.rs @@ -64,11 +64,18 @@ mod test { fn print_tree_node(tree: &DebugMessageTree, prefix: &str, is_last: bool) { // Print the current node - let branch = if is_last { "└── " } else { "├── " }; - println!("{}{}{}", prefix, branch, tree.name()); + let (branch, child_prefix) = match &tree.data_fields() { + Some(_) => ("├── ", format!("{}│ ", prefix)), + None => { + if is_last { + ("└── ", format!("{} ", prefix)) + } else { + ("├── ", format!("{}│ ", prefix)) + } + } + }; - // Prepare prefix for children - let child_prefix = if is_last { format!("{} ", prefix) } else { format!("{}│ ", prefix) }; + println!("{}{}{}", prefix, branch, tree.name()); // Print children if any if let Some(variants) = tree.variants() { @@ -78,5 +85,16 @@ mod test { print_tree_node(variant, &child_prefix, is_last_child); } } + + // Print data field if any + if let Some(data) = tree.data_fields() { + let len = data.fields().len(); + println!("{}{}{}", prefix, "└── ", data.name()); + for (i, field) in data.fields().iter().enumerate() { + let is_last_field = i == len - 1; + let branch = if is_last_field { "└── " } else { "├── " }; + println!("{}{}{}", format!("{} ", prefix), branch, field); + } + } } } diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index 6b5647a1f9..bccca63edc 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -166,6 +166,7 @@ impl Default for DocumentMessageHandler { } } +#[message_handler_data] impl MessageHandler> for DocumentMessageHandler { fn process_message(&mut self, message: DocumentMessage, responses: &mut VecDeque, data: DocumentMessageData) { let DocumentMessageData { diff --git a/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs b/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs index b2f08deda9..4c4f61854f 100644 --- a/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs +++ b/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs @@ -32,6 +32,7 @@ pub struct GraphOperationMessageHandler {} // GraphOperationMessageHandler always modified the document network. This is so changes to the layers panel will only affect the document network. // For changes to the selected network, use NodeGraphMessageHandler. No NodeGraphMessage's should be added here, since they will affect the selected nested network. +#[message_handler_data] impl MessageHandler> for GraphOperationMessageHandler { fn process_message(&mut self, message: GraphOperationMessage, responses: &mut VecDeque, data: GraphOperationMessageData) { let network_interface = data.network_interface; diff --git a/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs b/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs index 1208eacc78..7d2e76eb3b 100644 --- a/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs +++ b/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs @@ -32,6 +32,7 @@ pub struct NavigationMessageHandler { abortable_pan_start: Option, } +#[message_handler_data] impl MessageHandler> for NavigationMessageHandler { fn process_message(&mut self, message: NavigationMessage, responses: &mut VecDeque, data: NavigationMessageData) { let NavigationMessageData { diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs index c02483762c..d964b1bd20 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs @@ -84,6 +84,7 @@ pub struct NodeGraphMessageHandler { } /// NodeGraphMessageHandler always modifies the network which the selected nodes are in. No GraphOperationMessages should be added here, since those messages will always affect the document network. +#[message_handler_data] impl<'a> MessageHandler> for NodeGraphMessageHandler { fn process_message(&mut self, message: NodeGraphMessage, responses: &mut VecDeque, data: NodeGraphHandlerData<'a>) { let NodeGraphHandlerData { diff --git a/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs b/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs index 776a96b90e..1d74bb558d 100644 --- a/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs +++ b/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs @@ -17,6 +17,7 @@ pub struct OverlaysMessageHandler { context: Option, } +#[message_handler_data] impl MessageHandler> for OverlaysMessageHandler { fn process_message(&mut self, message: OverlaysMessage, responses: &mut VecDeque, data: OverlaysMessageData) { let OverlaysMessageData { overlays_visible, ipp, .. } = data; diff --git a/editor/src/messages/portfolio/document/properties_panel/properties_panel_message_handler.rs b/editor/src/messages/portfolio/document/properties_panel/properties_panel_message_handler.rs index a783b24aae..090d2ec022 100644 --- a/editor/src/messages/portfolio/document/properties_panel/properties_panel_message_handler.rs +++ b/editor/src/messages/portfolio/document/properties_panel/properties_panel_message_handler.rs @@ -7,6 +7,7 @@ use crate::messages::prelude::*; #[derive(Debug, Clone, Default)] pub struct PropertiesPanelMessageHandler {} +#[message_handler_data] impl MessageHandler)> for PropertiesPanelMessageHandler { fn process_message(&mut self, message: PropertiesPanelMessage, responses: &mut VecDeque, (persistent_data, data): (&PersistentData, PropertiesPanelMessageHandlerData)) { let PropertiesPanelMessageHandlerData { diff --git a/editor/src/messages/portfolio/menu_bar/menu_bar_message_handler.rs b/editor/src/messages/portfolio/menu_bar/menu_bar_message_handler.rs index cabb466374..530c805d94 100644 --- a/editor/src/messages/portfolio/menu_bar/menu_bar_message_handler.rs +++ b/editor/src/messages/portfolio/menu_bar/menu_bar_message_handler.rs @@ -19,6 +19,7 @@ pub struct MenuBarMessageHandler { pub reset_node_definitions_on_open: bool, } +#[message_handler_data] impl MessageHandler for MenuBarMessageHandler { fn process_message(&mut self, message: MenuBarMessage, responses: &mut VecDeque, _data: ()) { match message { diff --git a/editor/src/messages/portfolio/portfolio_message_handler.rs b/editor/src/messages/portfolio/portfolio_message_handler.rs index 1918639845..3b3225df6f 100644 --- a/editor/src/messages/portfolio/portfolio_message_handler.rs +++ b/editor/src/messages/portfolio/portfolio_message_handler.rs @@ -54,6 +54,7 @@ pub struct PortfolioMessageHandler { pub reset_node_definitions_on_open: bool, } +#[message_handler_data] impl MessageHandler> for PortfolioMessageHandler { fn process_message(&mut self, message: PortfolioMessage, responses: &mut VecDeque, data: PortfolioMessageData) { let PortfolioMessageData { diff --git a/editor/src/messages/portfolio/spreadsheet/spreadsheet_message_handler.rs b/editor/src/messages/portfolio/spreadsheet/spreadsheet_message_handler.rs index 5f5b2f2452..ade62ca04a 100644 --- a/editor/src/messages/portfolio/spreadsheet/spreadsheet_message_handler.rs +++ b/editor/src/messages/portfolio/spreadsheet/spreadsheet_message_handler.rs @@ -23,6 +23,7 @@ pub struct SpreadsheetMessageHandler { viewing_vector_data_domain: VectorDataDomain, } +#[message_handler_data] impl MessageHandler for SpreadsheetMessageHandler { fn process_message(&mut self, message: SpreadsheetMessage, responses: &mut VecDeque, _data: ()) { match message { diff --git a/editor/src/messages/preferences/preferences_message_handler.rs b/editor/src/messages/preferences/preferences_message_handler.rs index b1f607b985..b1a975dc69 100644 --- a/editor/src/messages/preferences/preferences_message_handler.rs +++ b/editor/src/messages/preferences/preferences_message_handler.rs @@ -49,6 +49,7 @@ impl Default for PreferencesMessageHandler { } } +#[message_handler_data] impl MessageHandler for PreferencesMessageHandler { fn process_message(&mut self, message: PreferencesMessage, responses: &mut VecDeque, _data: ()) { match message { diff --git a/editor/src/messages/tool/tool_message_handler.rs b/editor/src/messages/tool/tool_message_handler.rs index c7b13aedfa..035e76f23b 100644 --- a/editor/src/messages/tool/tool_message_handler.rs +++ b/editor/src/messages/tool/tool_message_handler.rs @@ -29,6 +29,7 @@ pub struct ToolMessageHandler { pub tool_is_active: bool, } +#[message_handler_data] impl MessageHandler> for ToolMessageHandler { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, data: ToolMessageData) { let ToolMessageData { @@ -327,13 +328,3 @@ impl MessageHandler> for ToolMessageHandler { list } } - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn print_field() { - ToolMessageData::print_field_types(); - } -} diff --git a/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs b/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs index 30f1c239e1..096e5e837d 100644 --- a/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs +++ b/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs @@ -134,6 +134,8 @@ fn update_colinear_handles(selected_layers: &[LayerNodeIdentifier], document: &D } type TransformData<'a> = (&'a DocumentMessageHandler, &'a InputPreprocessorMessageHandler, &'a ToolData, &'a mut ShapeState); + +#[message_handler_data(CustomData)] impl MessageHandler> for TransformLayerMessageHandler { fn process_message(&mut self, message: TransformLayerMessage, responses: &mut VecDeque, (document, input, tool_data, shape_editor): TransformData) { let using_path_tool = tool_data.active_tool_type == ToolType::Path; @@ -711,6 +713,15 @@ impl MessageHandler> for TransformLayer } } +pub fn custom_data() -> Vec { + vec![ + String::from("&'a DocumentMessageHandler"), + String::from("&'a InputPreprocessorMessageHandler"), + String::from("&'a ToolData"), + String::from("&'a mut ShapeState"), + ] +} + #[cfg(test)] mod test_transform_layer { use crate::messages::portfolio::document::graph_operation::{transform_utils, utility_types::ModifyInputsContext}; diff --git a/editor/src/messages/workspace/workspace_message_handler.rs b/editor/src/messages/workspace/workspace_message_handler.rs index 397e7cf00b..dc64efad8c 100644 --- a/editor/src/messages/workspace/workspace_message_handler.rs +++ b/editor/src/messages/workspace/workspace_message_handler.rs @@ -5,6 +5,7 @@ pub struct WorkspaceMessageHandler { node_graph_visible: bool, } +#[message_handler_data] impl MessageHandler for WorkspaceMessageHandler { fn process_message(&mut self, message: WorkspaceMessage, _responses: &mut VecDeque, _data: ()) { match message { diff --git a/editor/src/utility_traits.rs b/editor/src/utility_traits.rs index d5b4a361b2..7f137b9832 100644 --- a/editor/src/utility_traits.rs +++ b/editor/src/utility_traits.rs @@ -48,4 +48,8 @@ pub trait Hint { pub trait HierarchicalTree { fn build_message_tree() -> DebugMessageTree; + + fn message_handler_data_str() -> Vec { + Vec::new() + } } diff --git a/proc-macros/src/hierarchical_tree.rs b/proc-macros/src/hierarchical_tree.rs index 7cce612729..18307e95c9 100644 --- a/proc-macros/src/hierarchical_tree.rs +++ b/proc-macros/src/hierarchical_tree.rs @@ -51,6 +51,10 @@ pub fn generate_hierarchical_tree(input: TokenStream) -> syn::Result DebugMessageTree { let mut message_tree = DebugMessageTree::new(stringify!(#input_type)); #(#build_message_tree)* + let data_str = #input_type::message_handler_data_str(); + if data_str.len() > 0 { + message_tree.add_data_field(format!("{}Data", stringify!(#input_type)), data_str); + } message_tree } } diff --git a/proc-macros/src/lib.rs b/proc-macros/src/lib.rs index 22bf332500..820ed34fe6 100644 --- a/proc-macros/src/lib.rs +++ b/proc-macros/src/lib.rs @@ -8,6 +8,7 @@ mod helper_structs; mod helpers; mod hierarchical_tree; mod hint; +mod message_handler_data_attr; mod transitive_child; mod widget_builder; @@ -16,10 +17,11 @@ use crate::combined_message_attrs::combined_message_attrs_impl; use crate::discriminant::derive_discriminant_impl; use crate::extract_fields::derive_extract_field_impl; use crate::helper_structs::AttrInnerSingleString; +use crate::hierarchical_tree::generate_hierarchical_tree; use crate::hint::derive_hint_impl; +use crate::message_handler_data_attr::message_handler_data_attr_impl; use crate::transitive_child::derive_transitive_child_impl; use crate::widget_builder::derive_widget_builder_impl; -use hierarchical_tree::generate_hierarchical_tree; use proc_macro::TokenStream; /// Derive the `ToDiscriminant` trait and create a `Discriminant` enum @@ -295,6 +297,11 @@ pub fn derive_extract_field(input_item: TokenStream) -> TokenStream { TokenStream::from(derive_extract_field_impl(input_item.into()).unwrap_or_else(|err| err.to_compile_error())) } +#[proc_macro_attribute] +pub fn message_handler_data(attr: TokenStream, input_item: TokenStream) -> TokenStream { + TokenStream::from(message_handler_data_attr_impl(attr.into(), input_item.into()).unwrap_or_else(|err| err.to_compile_error())) +} + #[cfg(test)] mod tests { use super::*; diff --git a/proc-macros/src/message_handler_data_attr.rs b/proc-macros/src/message_handler_data_attr.rs new file mode 100644 index 0000000000..8358b9b7e1 --- /dev/null +++ b/proc-macros/src/message_handler_data_attr.rs @@ -0,0 +1,72 @@ +use proc_macro2::{Span, TokenStream}; +use quote::quote; +use syn::{ItemImpl, parse2, spanned::Spanned}; + +pub fn message_handler_data_attr_impl(attr: TokenStream, input_item: TokenStream) -> syn::Result { + // Parse the input as an impl block + let impl_block = parse2::(input_item.clone())?; + + // Extract the message type from the trait path + let trait_path = match &impl_block.trait_ { + Some((_, path, _)) => path, + None => return Err(syn::Error::new(impl_block.span(), "Expected trait implementation")), + }; + + // Get the trait generics (should be MessageHandler) + if let Some(segment) = trait_path.segments.last() { + if segment.ident != "MessageHandler" { + return Err(syn::Error::new(segment.ident.span(), "Expected MessageHandler trait")); + } + if let syn::PathArguments::AngleBracketed(args) = &segment.arguments { + if args.args.len() >= 2 { + // Extract the message type (M) and data type (D) from the trait params + let message_type = &args.args[0]; + let data_type = &args.args[1]; + + // Check if the attribute is "CustomData" + let is_custom_data = attr.to_string().contains("CustomData"); + + let impl_item = match data_type { + syn::GenericArgument::Type(t) => { + match t { + syn::Type::Path(type_path) if !type_path.path.segments.is_empty() => { + // Get just the base identifier (ToolMessageData) without generics + let type_name = &type_path.path.segments.first().unwrap().ident; + + if is_custom_data { + quote! { + #input_item + impl #message_type { + pub fn message_handler_data_str() -> Vec { + custom_data() + } + } + } + } else { + quote! { + #input_item + impl #message_type { + pub fn message_handler_data_str() -> Vec { + #type_name::field_types() + } + } + } + } + } + syn::Type::Tuple(_) => quote! { + #input_item + }, + _ => return Err(syn::Error::new(t.span(), "Unsupported type format")), + } + } + + _ => quote! { + #input_item + }, + }; + return Ok(impl_item); + } + } + } + Ok(input_item) +} From fc9e258a517b156e02d9401937990934ea366637 Mon Sep 17 00:00:00 2001 From: Mohd Mohsin Date: Thu, 1 May 2025 21:31:09 +0530 Subject: [PATCH 07/13] feat: added message handler struct to hierarchical tree --- .../animation/animation_message_handler.rs | 2 +- .../broadcast/broadcast_message_handler.rs | 2 +- .../messages/debug/debug_message_handler.rs | 2 +- editor/src/messages/debug/utility_types.rs | 36 +++++++++++++++---- .../messages/dialog/dialog_message_handler.rs | 2 +- .../export_dialog_message_handler.rs | 2 +- .../new_document_dialog_message_handler.rs | 2 +- .../preferences_dialog_message_handler.rs | 2 +- .../globals/globals_message_handler.rs | 2 +- .../input_mapper_message_handler.rs | 2 +- .../key_mapping_message_handler.rs | 2 +- .../input_preprocessor_message_handler.rs | 2 +- .../messages/layout/layout_message_handler.rs | 2 +- editor/src/messages/message.rs | 33 ++++++++++++----- .../document/document_message_handler.rs | 2 +- .../graph_operation_message_handler.rs | 2 +- .../navigation/navigation_message_handler.rs | 2 +- .../node_graph/node_graph_message_handler.rs | 2 +- .../overlays/overlays_message_handler.rs | 2 +- .../properties_panel_message_handler.rs | 2 +- .../menu_bar/menu_bar_message_handler.rs | 2 +- .../portfolio/portfolio_message_handler.rs | 2 +- .../spreadsheet_message_handler.rs | 2 +- .../preferences_message_handler.rs | 2 +- .../src/messages/tool/tool_message_handler.rs | 2 +- .../transform_layer_message_handler.rs | 2 +- .../workspace/workspace_message_handler.rs | 2 +- editor/src/utility_traits.rs | 4 +++ proc-macros/src/hierarchical_tree.rs | 11 ++++-- proc-macros/src/message_handler_data_attr.rs | 24 +++++++++++-- 30 files changed, 113 insertions(+), 45 deletions(-) diff --git a/editor/src/messages/animation/animation_message_handler.rs b/editor/src/messages/animation/animation_message_handler.rs index a265197075..211d22c87c 100644 --- a/editor/src/messages/animation/animation_message_handler.rs +++ b/editor/src/messages/animation/animation_message_handler.rs @@ -24,7 +24,7 @@ enum AnimationState { }, } -#[derive(Default, Debug, Clone, PartialEq)] +#[derive(Default, Debug, Clone, PartialEq, ExtractField)] pub struct AnimationMessageHandler { /// Used to re-send the UI on the next frame after playback starts live_preview_recently_zero: bool, diff --git a/editor/src/messages/broadcast/broadcast_message_handler.rs b/editor/src/messages/broadcast/broadcast_message_handler.rs index 21d572a511..489df47ab7 100644 --- a/editor/src/messages/broadcast/broadcast_message_handler.rs +++ b/editor/src/messages/broadcast/broadcast_message_handler.rs @@ -1,6 +1,6 @@ use crate::messages::prelude::*; -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, ExtractField)] pub struct BroadcastMessageHandler { listeners: HashMap>, } diff --git a/editor/src/messages/debug/debug_message_handler.rs b/editor/src/messages/debug/debug_message_handler.rs index 270ae9bfa9..064ad2510c 100644 --- a/editor/src/messages/debug/debug_message_handler.rs +++ b/editor/src/messages/debug/debug_message_handler.rs @@ -1,7 +1,7 @@ use super::utility_types::MessageLoggingVerbosity; use crate::messages::prelude::*; -#[derive(Debug, Default)] +#[derive(Debug, Default, ExtractField)] pub struct DebugMessageHandler { pub message_logging_verbosity: MessageLoggingVerbosity, } diff --git a/editor/src/messages/debug/utility_types.rs b/editor/src/messages/debug/utility_types.rs index 047e52cdfb..2de0c83aac 100644 --- a/editor/src/messages/debug/utility_types.rs +++ b/editor/src/messages/debug/utility_types.rs @@ -26,7 +26,8 @@ impl MessageData { pub struct DebugMessageTree { name: String, variants: Option>, - data: Option, + message_handler: Option, + message_handler_data: Option, } impl DebugMessageTree { @@ -34,7 +35,8 @@ impl DebugMessageTree { DebugMessageTree { name: name.to_string(), variants: None, - data: None, + message_handler: None, + message_handler_data: None, } } @@ -46,8 +48,12 @@ impl DebugMessageTree { } } - pub fn add_data_field(&mut self, name: String, fields: Vec) { - self.data = Some(MessageData { name, fields }); + pub fn add_message_handler_data_field(&mut self, name: String, fields: Vec) { + self.message_handler_data = Some(MessageData { name, fields }); + } + + pub fn add_message_handler_field(&mut self, name: String, fields: Vec) { + self.message_handler = Some(MessageData { name, fields }); } pub fn name(&self) -> &str { @@ -58,7 +64,25 @@ impl DebugMessageTree { self.variants.as_ref() } - pub fn data_fields(&self) -> Option<&MessageData> { - self.data.as_ref() + pub fn message_handler_data_fields(&self) -> Option<&MessageData> { + self.message_handler_data.as_ref() + } + + pub fn message_handler_fields(&self) -> Option<&MessageData> { + self.message_handler.as_ref() + } + + pub fn has_message_handler_data_fields(&self) -> bool { + match self.message_handler_data_fields() { + Some(_) => true, + None => false, + } + } + + pub fn has_message_handler_fields(&self) -> bool { + match self.message_handler_fields() { + Some(_) => true, + None => false, + } } } diff --git a/editor/src/messages/dialog/dialog_message_handler.rs b/editor/src/messages/dialog/dialog_message_handler.rs index 8530ea2f94..8e6bbde2f8 100644 --- a/editor/src/messages/dialog/dialog_message_handler.rs +++ b/editor/src/messages/dialog/dialog_message_handler.rs @@ -9,7 +9,7 @@ pub struct DialogMessageData<'a> { } /// Stores the dialogs which require state. These are the ones that have their own message handlers, and are not the ones defined in `simple_dialogs`. -#[derive(Debug, Default, Clone)] +#[derive(Debug, Default, Clone, ExtractField)] pub struct DialogMessageHandler { export_dialog: ExportDialogMessageHandler, new_document_dialog: NewDocumentDialogMessageHandler, diff --git a/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs b/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs index 63f53c4ac1..994d5543b9 100644 --- a/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs +++ b/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs @@ -9,7 +9,7 @@ pub struct ExportDialogMessageData<'a> { } /// A dialog to allow users to customize their file export. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, ExtractField)] pub struct ExportDialogMessageHandler { pub file_type: FileType, pub scale_factor: f64, diff --git a/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs b/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs index c712ba9d3c..3b6ff84e18 100644 --- a/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs +++ b/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs @@ -4,7 +4,7 @@ use glam::{IVec2, UVec2}; use graph_craft::document::NodeId; /// A dialog to allow users to set some initial options about a new document. -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, ExtractField)] pub struct NewDocumentDialogMessageHandler { pub name: String, pub infinite: bool, diff --git a/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs b/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs index e82d4f9316..339f1a4ddf 100644 --- a/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs +++ b/editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs @@ -10,7 +10,7 @@ pub struct PreferencesDialogMessageData<'a> { } /// A dialog to allow users to customize Graphite editor options -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, ExtractField)] pub struct PreferencesDialogMessageHandler {} #[message_handler_data] diff --git a/editor/src/messages/globals/globals_message_handler.rs b/editor/src/messages/globals/globals_message_handler.rs index d46872d2ed..9a72ffa6dc 100644 --- a/editor/src/messages/globals/globals_message_handler.rs +++ b/editor/src/messages/globals/globals_message_handler.rs @@ -1,6 +1,6 @@ use crate::messages::prelude::*; -#[derive(Debug, Default)] +#[derive(Debug, Default, ExtractField)] pub struct GlobalsMessageHandler {} #[message_handler_data] diff --git a/editor/src/messages/input_mapper/input_mapper_message_handler.rs b/editor/src/messages/input_mapper/input_mapper_message_handler.rs index 6cb2c458b7..1bd470fa44 100644 --- a/editor/src/messages/input_mapper/input_mapper_message_handler.rs +++ b/editor/src/messages/input_mapper/input_mapper_message_handler.rs @@ -11,7 +11,7 @@ pub struct InputMapperMessageData<'a> { pub actions: ActionList, } -#[derive(Debug, Default)] +#[derive(Debug, Default, ExtractField)] pub struct InputMapperMessageHandler { mapping: Mapping, } diff --git a/editor/src/messages/input_mapper/key_mapping/key_mapping_message_handler.rs b/editor/src/messages/input_mapper/key_mapping/key_mapping_message_handler.rs index a886bebe72..8550123599 100644 --- a/editor/src/messages/input_mapper/key_mapping/key_mapping_message_handler.rs +++ b/editor/src/messages/input_mapper/key_mapping/key_mapping_message_handler.rs @@ -8,7 +8,7 @@ pub struct KeyMappingMessageData<'a> { pub actions: ActionList, } -#[derive(Debug, Default)] +#[derive(Debug, Default, ExtractField)] pub struct KeyMappingMessageHandler { mapping_handler: InputMapperMessageHandler, } diff --git a/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs b/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs index 714f54f31c..144652fdc5 100644 --- a/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs +++ b/editor/src/messages/input_preprocessor/input_preprocessor_message_handler.rs @@ -11,7 +11,7 @@ pub struct InputPreprocessorMessageData { pub keyboard_platform: KeyboardPlatformLayout, } -#[derive(Debug, Default)] +#[derive(Debug, Default, ExtractField)] pub struct InputPreprocessorMessageHandler { pub frame_time: FrameTimeInfo, pub time: u64, diff --git a/editor/src/messages/layout/layout_message_handler.rs b/editor/src/messages/layout/layout_message_handler.rs index b4d5c38fe1..685c525290 100644 --- a/editor/src/messages/layout/layout_message_handler.rs +++ b/editor/src/messages/layout/layout_message_handler.rs @@ -6,7 +6,7 @@ use graphene_core::text::Font; use graphene_std::vector::style::{FillChoice, GradientStops}; use serde_json::Value; -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, ExtractField)] pub struct LayoutMessageHandler { layouts: [Layout; LayoutTarget::LayoutTargetLength as usize], } diff --git a/editor/src/messages/message.rs b/editor/src/messages/message.rs index 80f9c187e8..a7dfc133b9 100644 --- a/editor/src/messages/message.rs +++ b/editor/src/messages/message.rs @@ -64,14 +64,13 @@ mod test { fn print_tree_node(tree: &DebugMessageTree, prefix: &str, is_last: bool) { // Print the current node - let (branch, child_prefix) = match &tree.data_fields() { - Some(_) => ("├── ", format!("{}│ ", prefix)), - None => { - if is_last { - ("└── ", format!("{} ", prefix)) - } else { - ("├── ", format!("{}│ ", prefix)) - } + let (branch, child_prefix) = if tree.has_message_handler_data_fields() || tree.has_message_handler_fields() { + ("├── ", format!("{}│ ", prefix)) + } else { + if is_last { + ("└── ", format!("{} ", prefix)) + } else { + ("├── ", format!("{}│ ", prefix)) } }; @@ -86,8 +85,24 @@ mod test { } } + // Print handler field if any + if let Some(data) = tree.message_handler_fields() { + let len = data.fields().len(); + let (branch, child_prefix) = if tree.has_message_handler_data_fields() { + ("├── ", format!("{}│ ", prefix)) + } else { + ("└── ", format!("{} ", prefix)) + }; + println!("{}{}{}", prefix, branch, data.name()); + for (i, field) in data.fields().iter().enumerate() { + let is_last_field = i == len - 1; + let branch = if is_last_field { "└── " } else { "├── " }; + println!("{}{}{}", child_prefix, branch, field); + } + } + // Print data field if any - if let Some(data) = tree.data_fields() { + if let Some(data) = tree.message_handler_data_fields() { let len = data.fields().len(); println!("{}{}{}", prefix, "└── ", data.name()); for (i, field) in data.fields().iter().enumerate() { diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index bccca63edc..6ba3a7ade5 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -46,7 +46,7 @@ pub struct DocumentMessageData<'a> { pub device_pixel_ratio: f64, } -#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] +#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, ExtractField)] #[serde(default)] pub struct DocumentMessageHandler { // ====================== diff --git a/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs b/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs index 4c4f61854f..79baf5c937 100644 --- a/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs +++ b/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs @@ -27,7 +27,7 @@ pub struct GraphOperationMessageData<'a> { pub node_graph: &'a mut NodeGraphMessageHandler, } -#[derive(Debug, Clone, PartialEq, Default, serde::Serialize, serde::Deserialize)] +#[derive(Debug, Clone, PartialEq, Default, serde::Serialize, serde::Deserialize, ExtractField)] pub struct GraphOperationMessageHandler {} // GraphOperationMessageHandler always modified the document network. This is so changes to the layers panel will only affect the document network. diff --git a/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs b/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs index 7d2e76eb3b..604b61c507 100644 --- a/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs +++ b/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs @@ -24,7 +24,7 @@ pub struct NavigationMessageData<'a> { pub preferences: &'a PreferencesMessageHandler, } -#[derive(Debug, Clone, PartialEq, Default)] +#[derive(Debug, Clone, PartialEq, Default, ExtractField)] pub struct NavigationMessageHandler { navigation_operation: NavigationOperation, mouse_position: ViewportPosition, diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs index d964b1bd20..da28264885 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs @@ -38,7 +38,7 @@ pub struct NodeGraphHandlerData<'a> { pub preferences: &'a PreferencesMessageHandler, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, ExtractField)] pub struct NodeGraphMessageHandler { // TODO: Remove network and move to NodeNetworkInterface pub network: Vec, diff --git a/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs b/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs index 1d74bb558d..cea9396cff 100644 --- a/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs +++ b/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs @@ -8,7 +8,7 @@ pub struct OverlaysMessageData<'a> { pub device_pixel_ratio: f64, } -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, ExtractField)] pub struct OverlaysMessageHandler { pub overlay_providers: HashSet, #[cfg(target_arch = "wasm32")] diff --git a/editor/src/messages/portfolio/document/properties_panel/properties_panel_message_handler.rs b/editor/src/messages/portfolio/document/properties_panel/properties_panel_message_handler.rs index 090d2ec022..3ca9f350f3 100644 --- a/editor/src/messages/portfolio/document/properties_panel/properties_panel_message_handler.rs +++ b/editor/src/messages/portfolio/document/properties_panel/properties_panel_message_handler.rs @@ -4,7 +4,7 @@ use crate::messages::portfolio::document::node_graph::document_node_definitions: use crate::messages::portfolio::utility_types::PersistentData; use crate::messages::prelude::*; -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, ExtractField)] pub struct PropertiesPanelMessageHandler {} #[message_handler_data] diff --git a/editor/src/messages/portfolio/menu_bar/menu_bar_message_handler.rs b/editor/src/messages/portfolio/menu_bar/menu_bar_message_handler.rs index 530c805d94..f836652562 100644 --- a/editor/src/messages/portfolio/menu_bar/menu_bar_message_handler.rs +++ b/editor/src/messages/portfolio/menu_bar/menu_bar_message_handler.rs @@ -6,7 +6,7 @@ use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, use crate::messages::prelude::*; use graphene_std::vector::misc::BooleanOperation; -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, ExtractField)] pub struct MenuBarMessageHandler { pub has_active_document: bool, pub rulers_visible: bool, diff --git a/editor/src/messages/portfolio/portfolio_message_handler.rs b/editor/src/messages/portfolio/portfolio_message_handler.rs index 3b3225df6f..8f28287f9d 100644 --- a/editor/src/messages/portfolio/portfolio_message_handler.rs +++ b/editor/src/messages/portfolio/portfolio_message_handler.rs @@ -37,7 +37,7 @@ pub struct PortfolioMessageData<'a> { pub animation: &'a AnimationMessageHandler, } -#[derive(Debug, Default)] +#[derive(Debug, Default, ExtractField)] pub struct PortfolioMessageHandler { menu_bar_message_handler: MenuBarMessageHandler, pub documents: HashMap, diff --git a/editor/src/messages/portfolio/spreadsheet/spreadsheet_message_handler.rs b/editor/src/messages/portfolio/spreadsheet/spreadsheet_message_handler.rs index ade62ca04a..d535be95d7 100644 --- a/editor/src/messages/portfolio/spreadsheet/spreadsheet_message_handler.rs +++ b/editor/src/messages/portfolio/spreadsheet/spreadsheet_message_handler.rs @@ -13,7 +13,7 @@ use std::any::Any; use std::sync::Arc; /// The spreadsheet UI allows for instance data to be previewed. -#[derive(Default, Debug, Clone)] +#[derive(Default, Debug, Clone, ExtractField)] pub struct SpreadsheetMessageHandler { /// Sets whether or not the spreadsheet is drawn. pub spreadsheet_view_open: bool, diff --git a/editor/src/messages/preferences/preferences_message_handler.rs b/editor/src/messages/preferences/preferences_message_handler.rs index b1a975dc69..dc93cda1a2 100644 --- a/editor/src/messages/preferences/preferences_message_handler.rs +++ b/editor/src/messages/preferences/preferences_message_handler.rs @@ -5,7 +5,7 @@ use crate::messages::preferences::SelectionMode; use crate::messages::prelude::*; use graph_craft::wasm_application_io::EditorPreferences; -#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, specta::Type)] +#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize, specta::Type, ExtractField)] pub struct PreferencesMessageHandler { // pub imaginate_server_hostname: String, // pub imaginate_refresh_frequency: f64, diff --git a/editor/src/messages/tool/tool_message_handler.rs b/editor/src/messages/tool/tool_message_handler.rs index 035e76f23b..0fdef82393 100644 --- a/editor/src/messages/tool/tool_message_handler.rs +++ b/editor/src/messages/tool/tool_message_handler.rs @@ -21,7 +21,7 @@ pub struct ToolMessageData<'a> { pub preferences: &'a PreferencesMessageHandler, } -#[derive(Debug, Default)] +#[derive(Debug, Default, ExtractField)] pub struct ToolMessageHandler { pub tool_state: ToolFsmState, pub transform_layer_handler: TransformLayerMessageHandler, diff --git a/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs b/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs index 096e5e837d..8d527f30b7 100644 --- a/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs +++ b/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs @@ -20,7 +20,7 @@ const TRANSFORM_GRS_OVERLAY_PROVIDER: OverlayProvider = |context| TransformLayer const SLOW_KEY: Key = Key::Shift; const INCREMENTS_KEY: Key = Key::Control; -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, ExtractField)] pub struct TransformLayerMessageHandler { pub transform_operation: TransformOperation, diff --git a/editor/src/messages/workspace/workspace_message_handler.rs b/editor/src/messages/workspace/workspace_message_handler.rs index dc64efad8c..47c81aab0e 100644 --- a/editor/src/messages/workspace/workspace_message_handler.rs +++ b/editor/src/messages/workspace/workspace_message_handler.rs @@ -1,6 +1,6 @@ use crate::messages::prelude::*; -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, ExtractField)] pub struct WorkspaceMessageHandler { node_graph_visible: bool, } diff --git a/editor/src/utility_traits.rs b/editor/src/utility_traits.rs index 7f137b9832..914a7248b0 100644 --- a/editor/src/utility_traits.rs +++ b/editor/src/utility_traits.rs @@ -52,4 +52,8 @@ pub trait HierarchicalTree { fn message_handler_data_str() -> Vec { Vec::new() } + + fn message_handler_str() -> Vec { + Vec::new() + } } diff --git a/proc-macros/src/hierarchical_tree.rs b/proc-macros/src/hierarchical_tree.rs index 18307e95c9..11d63b4948 100644 --- a/proc-macros/src/hierarchical_tree.rs +++ b/proc-macros/src/hierarchical_tree.rs @@ -51,9 +51,14 @@ pub fn generate_hierarchical_tree(input: TokenStream) -> syn::Result DebugMessageTree { let mut message_tree = DebugMessageTree::new(stringify!(#input_type)); #(#build_message_tree)* - let data_str = #input_type::message_handler_data_str(); - if data_str.len() > 0 { - message_tree.add_data_field(format!("{}Data", stringify!(#input_type)), data_str); + let message_handler_str = #input_type::message_handler_str(); + if message_handler_str.len() > 0 { + message_tree.add_message_handler_field(format!("{}Handler", stringify!(#input_type)), message_handler_str); + } + + let message_handler_data_str = #input_type::message_handler_data_str(); + if message_handler_data_str.len() > 0 { + message_tree.add_message_handler_data_field(format!("{}Data", stringify!(#input_type)), message_handler_data_str); } message_tree } diff --git a/proc-macros/src/message_handler_data_attr.rs b/proc-macros/src/message_handler_data_attr.rs index 8358b9b7e1..52665c1ace 100644 --- a/proc-macros/src/message_handler_data_attr.rs +++ b/proc-macros/src/message_handler_data_attr.rs @@ -1,15 +1,24 @@ use proc_macro2::{Span, TokenStream}; use quote::quote; -use syn::{ItemImpl, parse2, spanned::Spanned}; +use syn::{ItemImpl, Type, parse2, spanned::Spanned}; pub fn message_handler_data_attr_impl(attr: TokenStream, input_item: TokenStream) -> syn::Result { // Parse the input as an impl block let impl_block = parse2::(input_item.clone())?; + let self_ty = &impl_block.self_ty; + + let path = match &**self_ty { + Type::Path(path) => &path.path, + _ => return Err(syn::Error::new(Span::call_site(), "Expected impl implementation")), + }; + + let input_type = path.segments.last().map(|s| &s.ident).unwrap(); + // Extract the message type from the trait path let trait_path = match &impl_block.trait_ { Some((_, path, _)) => path, - None => return Err(syn::Error::new(impl_block.span(), "Expected trait implementation")), + None => return Err(syn::Error::new(Span::call_site(), "Expected trait implementation")), }; // Get the trait generics (should be MessageHandler) @@ -40,6 +49,9 @@ pub fn message_handler_data_attr_impl(attr: TokenStream, input_item: TokenStream pub fn message_handler_data_str() -> Vec { custom_data() } + pub fn message_handler_str() -> Vec { + #input_type::field_types() + } } } } else { @@ -49,12 +61,20 @@ pub fn message_handler_data_attr_impl(attr: TokenStream, input_item: TokenStream pub fn message_handler_data_str() -> Vec { #type_name::field_types() } + pub fn message_handler_str() -> Vec { + #input_type::field_types() + } } } } } syn::Type::Tuple(_) => quote! { #input_item + impl #message_type { + pub fn message_handler_str() -> Vec { + #input_type::field_types() + } + } }, _ => return Err(syn::Error::new(t.span(), "Unsupported type format")), } From c2c629d29214ba67aa45b79c95d0f2cc9306a499 Mon Sep 17 00:00:00 2001 From: Mohd Mohsin Date: Sat, 10 May 2025 16:08:22 +0530 Subject: [PATCH 08/13] feat: add the line number to message handler struct --- Cargo.lock | 4 ++-- editor/src/messages/debug/utility_types.rs | 8 ++++---- .../messages/layout/layout_message_handler.rs | 8 ++++---- editor/src/messages/message.rs | 9 +++++++-- .../transform_layer_message_handler.rs | 18 +++++++++--------- editor/src/utility_traits.rs | 4 ++-- proc-macros/src/extract_fields.rs | 16 ++++++++++------ proc-macros/src/message_handler_data_attr.rs | 10 +++++----- 8 files changed, 43 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 42c2c4865e..e0fc035dcf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4708,9 +4708,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] diff --git a/editor/src/messages/debug/utility_types.rs b/editor/src/messages/debug/utility_types.rs index 2de0c83aac..0e747389dc 100644 --- a/editor/src/messages/debug/utility_types.rs +++ b/editor/src/messages/debug/utility_types.rs @@ -9,7 +9,7 @@ pub enum MessageLoggingVerbosity { #[derive(Debug)] pub struct MessageData { name: String, - fields: Vec, + fields: Vec<(String, usize)>, } impl MessageData { @@ -17,7 +17,7 @@ impl MessageData { &self.name } - pub fn fields(&self) -> &Vec { + pub fn fields(&self) -> &Vec<(String, usize)> { &self.fields } } @@ -48,11 +48,11 @@ impl DebugMessageTree { } } - pub fn add_message_handler_data_field(&mut self, name: String, fields: Vec) { + pub fn add_message_handler_data_field(&mut self, name: String, fields: Vec<(String, usize)>) { self.message_handler_data = Some(MessageData { name, fields }); } - pub fn add_message_handler_field(&mut self, name: String, fields: Vec) { + pub fn add_message_handler_field(&mut self, name: String, fields: Vec<(String, usize)>) { self.message_handler = Some(MessageData { name, fields }); } diff --git a/editor/src/messages/layout/layout_message_handler.rs b/editor/src/messages/layout/layout_message_handler.rs index 4f303fb288..bd84ef0f49 100644 --- a/editor/src/messages/layout/layout_message_handler.rs +++ b/editor/src/messages/layout/layout_message_handler.rs @@ -338,6 +338,10 @@ impl LayoutMessageHandler { } } +pub fn custom_data() -> Vec<(String, usize)> { + vec![(String::from("Fn(&MessageDiscriminant) -> Vec"), 346)] +} + #[message_handler_data(CustomData)] impl Vec> MessageHandler for LayoutMessageHandler { fn process_message(&mut self, message: LayoutMessage, responses: &mut std::collections::VecDeque, action_input_mapping: F) { @@ -439,7 +443,3 @@ impl LayoutMessageHandler { responses.add(message); } } - -pub fn custom_data() -> Vec { - vec![String::from("Fn(&MessageDiscriminant) -> Vec")] -} diff --git a/editor/src/messages/message.rs b/editor/src/messages/message.rs index a7dfc133b9..b2f23a90ba 100644 --- a/editor/src/messages/message.rs +++ b/editor/src/messages/message.rs @@ -50,6 +50,11 @@ impl specta::Type for MessageDiscriminant { mod test { use super::*; + #[test] + fn print_tool_message_handler() { + ToolMessageHandler::print_field_types(); + } + #[test] fn generate_message_tree() { let res = Message::build_message_tree(); @@ -97,7 +102,7 @@ mod test { for (i, field) in data.fields().iter().enumerate() { let is_last_field = i == len - 1; let branch = if is_last_field { "└── " } else { "├── " }; - println!("{}{}{}", child_prefix, branch, field); + println!("{}{}{}", child_prefix, branch, field.0); } } @@ -108,7 +113,7 @@ mod test { for (i, field) in data.fields().iter().enumerate() { let is_last_field = i == len - 1; let branch = if is_last_field { "└── " } else { "├── " }; - println!("{}{}{}", format!("{} ", prefix), branch, field); + println!("{}{}{}", format!("{} ", prefix), branch, field.0); } } } diff --git a/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs b/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs index 2d80d5515e..d1eefbf954 100644 --- a/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs +++ b/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs @@ -135,6 +135,15 @@ fn update_colinear_handles(selected_layers: &[LayerNodeIdentifier], document: &D type TransformData<'a> = (&'a DocumentMessageHandler, &'a InputPreprocessorMessageHandler, &'a ToolData, &'a mut ShapeState); +pub fn custom_data() -> Vec<(String, usize)> { + vec![ + (String::from("&'a DocumentMessageHandler"), 136), + (String::from("&'a InputPreprocessorMessageHandler"), 136), + (String::from("&'a ToolData"), 136), + (String::from("&'a mut ShapeState"), 136), + ] +} + #[message_handler_data(CustomData)] impl MessageHandler> for TransformLayerMessageHandler { fn process_message(&mut self, message: TransformLayerMessage, responses: &mut VecDeque, (document, input, tool_data, shape_editor): TransformData) { @@ -718,15 +727,6 @@ impl MessageHandler> for TransformLayer } } -pub fn custom_data() -> Vec { - vec![ - String::from("&'a DocumentMessageHandler"), - String::from("&'a InputPreprocessorMessageHandler"), - String::from("&'a ToolData"), - String::from("&'a mut ShapeState"), - ] -} - #[cfg(test)] mod test_transform_layer { use crate::messages::portfolio::document::graph_operation::{transform_utils, utility_types::ModifyInputsContext}; diff --git a/editor/src/utility_traits.rs b/editor/src/utility_traits.rs index 914a7248b0..40769930b2 100644 --- a/editor/src/utility_traits.rs +++ b/editor/src/utility_traits.rs @@ -49,11 +49,11 @@ pub trait Hint { pub trait HierarchicalTree { fn build_message_tree() -> DebugMessageTree; - fn message_handler_data_str() -> Vec { + fn message_handler_data_str() -> Vec<(String, usize)> { Vec::new() } - fn message_handler_str() -> Vec { + fn message_handler_str() -> Vec<(String, usize)> { Vec::new() } } diff --git a/proc-macros/src/extract_fields.rs b/proc-macros/src/extract_fields.rs index 015191ccec..efd8652ac7 100644 --- a/proc-macros/src/extract_fields.rs +++ b/proc-macros/src/extract_fields.rs @@ -16,29 +16,33 @@ pub fn derive_extract_field_impl(input: TokenStream) -> syn::Result _ => return Err(syn::Error::new(Span::call_site(), "ExtractField only works on structs")), }; + let mut field_line = Vec::new(); // Extract field names and types as strings at compile time let field_info = fields .iter() .map(|field| { - let name = field.ident.as_ref().unwrap().to_string(); + let ident = field.ident.as_ref().unwrap(); + let name = ident.to_string(); let ty = field.ty.to_token_stream().to_string(); + let line = ident.span().start().line; + field_line.push(line); (name, ty) }) .collect::>(); - let field_str = field_info.into_iter().map(|(name, ty)| format!("{}: {}", name, ty)); + let field_str = field_info.into_iter().map(|(name, ty)| (format!("{}: {}", name, ty))); let res = quote! { impl #impl_generics #struct_name #ty_generics #where_clause { - pub fn field_types() -> Vec { + pub fn field_types() -> Vec<(String, usize)> { vec![ - #(String::from(#field_str)),* + #((String::from(#field_str), #field_line)),* ] } pub fn print_field_types() { - for field in Self::field_types() { - println!("{}", field); + for (field, line) in Self::field_types() { + println!("{} at line {}", field, line); } } } diff --git a/proc-macros/src/message_handler_data_attr.rs b/proc-macros/src/message_handler_data_attr.rs index 52665c1ace..1a9689a1dd 100644 --- a/proc-macros/src/message_handler_data_attr.rs +++ b/proc-macros/src/message_handler_data_attr.rs @@ -46,10 +46,10 @@ pub fn message_handler_data_attr_impl(attr: TokenStream, input_item: TokenStream quote! { #input_item impl #message_type { - pub fn message_handler_data_str() -> Vec { + pub fn message_handler_data_str() -> Vec<(String, usize)> { custom_data() } - pub fn message_handler_str() -> Vec { + pub fn message_handler_str() -> Vec<(String, usize)> { #input_type::field_types() } } @@ -58,10 +58,10 @@ pub fn message_handler_data_attr_impl(attr: TokenStream, input_item: TokenStream quote! { #input_item impl #message_type { - pub fn message_handler_data_str() -> Vec { + pub fn message_handler_data_str() -> Vec<(String, usize)> { #type_name::field_types() } - pub fn message_handler_str() -> Vec { + pub fn message_handler_str() -> Vec<(String, usize)> { #input_type::field_types() } } @@ -71,7 +71,7 @@ pub fn message_handler_data_attr_impl(attr: TokenStream, input_item: TokenStream syn::Type::Tuple(_) => quote! { #input_item impl #message_type { - pub fn message_handler_str() -> Vec { + pub fn message_handler_str() -> Vec<(String, usize)> { #input_type::field_types() } } From c2c6ac5fb1a91b8dbbcab027c0f97b88e6c96ebc Mon Sep 17 00:00:00 2001 From: Mohd Mohsin Date: Mon, 12 May 2025 16:38:22 +0530 Subject: [PATCH 09/13] feat: added handler path to tree and NITS --- editor/src/messages/debug/mod.rs | 2 - editor/src/messages/debug/utility_types.rs | 81 ------------- .../messages/layout/layout_message_handler.rs | 4 +- editor/src/messages/message.rs | 4 +- editor/src/messages/prelude.rs | 5 +- .../tool/tool_messages/artboard_tool.rs | 3 +- .../messages/tool/tool_messages/brush_tool.rs | 3 +- .../tool/tool_messages/ellipse_tool.rs | 3 +- .../tool/tool_messages/eyedropper_tool.rs | 3 +- .../messages/tool/tool_messages/fill_tool.rs | 3 +- .../tool/tool_messages/freehand_tool.rs | 3 +- .../tool/tool_messages/gradient_tool.rs | 3 +- .../tool/tool_messages/imaginate_tool.rs | 3 +- .../messages/tool/tool_messages/line_tool.rs | 3 +- .../tool/tool_messages/navigate_tool.rs | 3 +- .../messages/tool/tool_messages/path_tool.rs | 3 +- .../messages/tool/tool_messages/pen_tool.rs | 3 +- .../tool/tool_messages/polygon_tool.rs | 4 +- .../tool/tool_messages/rectangle_tool.rs | 3 +- .../tool/tool_messages/select_tool.rs | 3 +- .../tool/tool_messages/spline_tool.rs | 3 +- .../messages/tool/tool_messages/text_tool.rs | 3 +- .../transform_layer_message_handler.rs | 17 +-- editor/src/messages/tool/utility_types.rs | 1 + editor/src/utility_traits.rs | 107 +++++++++++++++++- proc-macros/src/hierarchical_tree.rs | 11 +- proc-macros/src/message_handler_data_attr.rs | 61 ++++++++-- 27 files changed, 214 insertions(+), 131 deletions(-) diff --git a/editor/src/messages/debug/mod.rs b/editor/src/messages/debug/mod.rs index 696c0ffb5a..79ad968d15 100644 --- a/editor/src/messages/debug/mod.rs +++ b/editor/src/messages/debug/mod.rs @@ -3,8 +3,6 @@ mod debug_message_handler; pub mod utility_types; -pub use utility_types::DebugMessageTree; - #[doc(inline)] pub use debug_message::{DebugMessage, DebugMessageDiscriminant}; #[doc(inline)] diff --git a/editor/src/messages/debug/utility_types.rs b/editor/src/messages/debug/utility_types.rs index 0e747389dc..027dd14f2a 100644 --- a/editor/src/messages/debug/utility_types.rs +++ b/editor/src/messages/debug/utility_types.rs @@ -5,84 +5,3 @@ pub enum MessageLoggingVerbosity { Names, Contents, } - -#[derive(Debug)] -pub struct MessageData { - name: String, - fields: Vec<(String, usize)>, -} - -impl MessageData { - pub fn name(&self) -> &str { - &self.name - } - - pub fn fields(&self) -> &Vec<(String, usize)> { - &self.fields - } -} - -#[derive(Debug)] -pub struct DebugMessageTree { - name: String, - variants: Option>, - message_handler: Option, - message_handler_data: Option, -} - -impl DebugMessageTree { - pub fn new(name: &str) -> DebugMessageTree { - DebugMessageTree { - name: name.to_string(), - variants: None, - message_handler: None, - message_handler_data: None, - } - } - - pub fn add_variant(&mut self, variant: DebugMessageTree) { - if let Some(variants) = &mut self.variants { - variants.push(variant); - } else { - self.variants = Some(vec![variant]); - } - } - - pub fn add_message_handler_data_field(&mut self, name: String, fields: Vec<(String, usize)>) { - self.message_handler_data = Some(MessageData { name, fields }); - } - - pub fn add_message_handler_field(&mut self, name: String, fields: Vec<(String, usize)>) { - self.message_handler = Some(MessageData { name, fields }); - } - - pub fn name(&self) -> &str { - &self.name - } - - pub fn variants(&self) -> Option<&Vec> { - self.variants.as_ref() - } - - pub fn message_handler_data_fields(&self) -> Option<&MessageData> { - self.message_handler_data.as_ref() - } - - pub fn message_handler_fields(&self) -> Option<&MessageData> { - self.message_handler.as_ref() - } - - pub fn has_message_handler_data_fields(&self) -> bool { - match self.message_handler_data_fields() { - Some(_) => true, - None => false, - } - } - - pub fn has_message_handler_fields(&self) -> bool { - match self.message_handler_fields() { - Some(_) => true, - None => false, - } - } -} diff --git a/editor/src/messages/layout/layout_message_handler.rs b/editor/src/messages/layout/layout_message_handler.rs index bd84ef0f49..27bcd44b0f 100644 --- a/editor/src/messages/layout/layout_message_handler.rs +++ b/editor/src/messages/layout/layout_message_handler.rs @@ -338,8 +338,8 @@ impl LayoutMessageHandler { } } -pub fn custom_data() -> Vec<(String, usize)> { - vec![(String::from("Fn(&MessageDiscriminant) -> Vec"), 346)] +pub fn custom_data() -> MessageData { + MessageData::new(String::from("Function"), vec![(String::from("Fn(&MessageDiscriminant) -> Vec"), 346)]) } #[message_handler_data(CustomData)] diff --git a/editor/src/messages/message.rs b/editor/src/messages/message.rs index b2f23a90ba..ea27272d3b 100644 --- a/editor/src/messages/message.rs +++ b/editor/src/messages/message.rs @@ -58,7 +58,7 @@ mod test { #[test] fn generate_message_tree() { let res = Message::build_message_tree(); - println!("{}", res.name()); + println!("{} {}", res.name(), res.path()); if let Some(variants) = res.variants() { for (i, variant) in variants.iter().enumerate() { let is_last = i == variants.len() - 1; @@ -79,7 +79,7 @@ mod test { } }; - println!("{}{}{}", prefix, branch, tree.name()); + println!("{}{}{} {}", prefix, branch, tree.name(), tree.path()); // Print children if any if let Some(variants) = tree.variants() { diff --git a/editor/src/messages/prelude.rs b/editor/src/messages/prelude.rs index 226817b9cf..24c3ea193b 100644 --- a/editor/src/messages/prelude.rs +++ b/editor/src/messages/prelude.rs @@ -1,10 +1,9 @@ // Root -pub use crate::utility_traits::{ActionList, AsMessage, HierarchicalTree, MessageHandler, ToDiscriminant, TransitiveChild}; - +pub use crate::utility_traits::{ActionList, AsMessage, DebugMessageTree, HierarchicalTree, MessageData, MessageHandler, ToDiscriminant, TransitiveChild}; // Message, MessageData, MessageDiscriminant, MessageHandler pub use crate::messages::animation::{AnimationMessage, AnimationMessageDiscriminant, AnimationMessageHandler}; pub use crate::messages::broadcast::{BroadcastMessage, BroadcastMessageDiscriminant, BroadcastMessageHandler}; -pub use crate::messages::debug::{DebugMessage, DebugMessageDiscriminant, DebugMessageHandler, DebugMessageTree}; +pub use crate::messages::debug::{DebugMessage, DebugMessageDiscriminant, DebugMessageHandler}; pub use crate::messages::dialog::export_dialog::{ExportDialogMessage, ExportDialogMessageData, ExportDialogMessageDiscriminant, ExportDialogMessageHandler}; pub use crate::messages::dialog::new_document_dialog::{NewDocumentDialogMessage, NewDocumentDialogMessageDiscriminant, NewDocumentDialogMessageHandler}; pub use crate::messages::dialog::preferences_dialog::{PreferencesDialogMessage, PreferencesDialogMessageData, PreferencesDialogMessageDiscriminant, PreferencesDialogMessageHandler}; diff --git a/editor/src/messages/tool/tool_messages/artboard_tool.rs b/editor/src/messages/tool/tool_messages/artboard_tool.rs index 8b2e685ae1..034dd3eb6f 100644 --- a/editor/src/messages/tool/tool_messages/artboard_tool.rs +++ b/editor/src/messages/tool/tool_messages/artboard_tool.rs @@ -13,7 +13,7 @@ use crate::messages::tool::common_functionality::transformation_cage::*; use graph_craft::document::NodeId; use graphene_core::renderer::Quad; -#[derive(Default)] +#[derive(Default, ExtractField)] pub struct ArtboardTool { fsm_state: ArtboardToolFsmState, data: ArtboardToolData, @@ -48,6 +48,7 @@ impl ToolMetadata for ArtboardTool { } } +#[message_handler_data()] impl<'a> MessageHandler> for ArtboardTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, tool_data: &mut ToolActionHandlerData<'a>) { self.fsm_state.process_event(message, &mut self.data, tool_data, &(), responses, false); diff --git a/editor/src/messages/tool/tool_messages/brush_tool.rs b/editor/src/messages/tool/tool_messages/brush_tool.rs index ac7e38830e..c2207f4467 100644 --- a/editor/src/messages/tool/tool_messages/brush_tool.rs +++ b/editor/src/messages/tool/tool_messages/brush_tool.rs @@ -20,7 +20,7 @@ pub enum DrawMode { Restore, } -#[derive(Default)] +#[derive(Default, ExtractField)] pub struct BrushTool { fsm_state: BrushToolFsmState, data: BrushToolData, @@ -185,6 +185,7 @@ impl LayoutHolder for BrushTool { } } +#[message_handler_data()] impl<'a> MessageHandler> for BrushTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, tool_data: &mut ToolActionHandlerData<'a>) { let ToolMessage::Brush(BrushToolMessage::UpdateOptions(action)) = message else { diff --git a/editor/src/messages/tool/tool_messages/ellipse_tool.rs b/editor/src/messages/tool/tool_messages/ellipse_tool.rs index e86a3763d8..0d5c2d311c 100644 --- a/editor/src/messages/tool/tool_messages/ellipse_tool.rs +++ b/editor/src/messages/tool/tool_messages/ellipse_tool.rs @@ -13,7 +13,7 @@ use graph_craft::document::value::TaggedValue; use graph_craft::document::{NodeId, NodeInput}; use graphene_core::Color; -#[derive(Default)] +#[derive(Default, ExtractField)] pub struct EllipseTool { fsm_state: EllipseToolFsmState, data: EllipseToolData, @@ -110,6 +110,7 @@ impl LayoutHolder for EllipseTool { } } +#[message_handler_data()] impl<'a> MessageHandler> for EllipseTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, tool_data: &mut ToolActionHandlerData<'a>) { let ToolMessage::Ellipse(EllipseToolMessage::UpdateOptions(action)) = message else { diff --git a/editor/src/messages/tool/tool_messages/eyedropper_tool.rs b/editor/src/messages/tool/tool_messages/eyedropper_tool.rs index 3b3f324972..f993613928 100644 --- a/editor/src/messages/tool/tool_messages/eyedropper_tool.rs +++ b/editor/src/messages/tool/tool_messages/eyedropper_tool.rs @@ -1,7 +1,7 @@ use super::tool_prelude::*; use crate::messages::tool::utility_types::DocumentToolData; -#[derive(Default)] +#[derive(Default, ExtractField)] pub struct EyedropperTool { fsm_state: EyedropperToolFsmState, data: EyedropperToolData, @@ -39,6 +39,7 @@ impl LayoutHolder for EyedropperTool { } } +#[message_handler_data()] impl<'a> MessageHandler> for EyedropperTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, tool_data: &mut ToolActionHandlerData<'a>) { self.fsm_state.process_event(message, &mut self.data, tool_data, &(), responses, true); diff --git a/editor/src/messages/tool/tool_messages/fill_tool.rs b/editor/src/messages/tool/tool_messages/fill_tool.rs index 0eae252bcd..91abbecbbb 100644 --- a/editor/src/messages/tool/tool_messages/fill_tool.rs +++ b/editor/src/messages/tool/tool_messages/fill_tool.rs @@ -3,7 +3,7 @@ use crate::messages::portfolio::document::overlays::utility_types::OverlayContex use crate::messages::tool::common_functionality::graph_modification_utils::NodeGraphLayer; use graphene_core::vector::style::Fill; -#[derive(Default)] +#[derive(Default, ExtractField)] pub struct FillTool { fsm_state: FillToolFsmState, } @@ -41,6 +41,7 @@ impl LayoutHolder for FillTool { } } +#[message_handler_data()] impl<'a> MessageHandler> for FillTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, tool_data: &mut ToolActionHandlerData<'a>) { self.fsm_state.process_event(message, &mut (), tool_data, &(), responses, true); diff --git a/editor/src/messages/tool/tool_messages/freehand_tool.rs b/editor/src/messages/tool/tool_messages/freehand_tool.rs index 3b7af8880a..a4c0b8c6d1 100644 --- a/editor/src/messages/tool/tool_messages/freehand_tool.rs +++ b/editor/src/messages/tool/tool_messages/freehand_tool.rs @@ -13,7 +13,7 @@ use graphene_core::Color; use graphene_core::vector::VectorModificationType; use graphene_std::vector::{PointId, SegmentId}; -#[derive(Default)] +#[derive(Default, ExtractField)] pub struct FreehandTool { fsm_state: FreehandToolFsmState, data: FreehandToolData, @@ -116,6 +116,7 @@ impl LayoutHolder for FreehandTool { } } +#[message_handler_data()] impl<'a> MessageHandler> for FreehandTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, tool_data: &mut ToolActionHandlerData<'a>) { let ToolMessage::Freehand(FreehandToolMessage::UpdateOptions(action)) = message else { diff --git a/editor/src/messages/tool/tool_messages/gradient_tool.rs b/editor/src/messages/tool/tool_messages/gradient_tool.rs index 12b8f17b30..ed761dd3b0 100644 --- a/editor/src/messages/tool/tool_messages/gradient_tool.rs +++ b/editor/src/messages/tool/tool_messages/gradient_tool.rs @@ -7,7 +7,7 @@ use crate::messages::tool::common_functionality::graph_modification_utils::{Node use crate::messages::tool::common_functionality::snapping::SnapManager; use graphene_core::vector::style::{Fill, Gradient, GradientType}; -#[derive(Default)] +#[derive(Default, ExtractField)] pub struct GradientTool { fsm_state: GradientToolFsmState, data: GradientToolData, @@ -53,6 +53,7 @@ impl ToolMetadata for GradientTool { } } +#[message_handler_data()] impl<'a> MessageHandler> for GradientTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, tool_data: &mut ToolActionHandlerData<'a>) { let ToolMessage::Gradient(GradientToolMessage::UpdateOptions(action)) = message else { diff --git a/editor/src/messages/tool/tool_messages/imaginate_tool.rs b/editor/src/messages/tool/tool_messages/imaginate_tool.rs index 79a952865d..cfe238d398 100644 --- a/editor/src/messages/tool/tool_messages/imaginate_tool.rs +++ b/editor/src/messages/tool/tool_messages/imaginate_tool.rs @@ -1,7 +1,7 @@ use super::tool_prelude::*; use crate::messages::tool::common_functionality::resize::Resize; -#[derive(Default)] +#[derive(Default, ExtractField)] pub struct ImaginateTool { fsm_state: ImaginateToolFsmState, tool_data: ImaginateToolData, @@ -25,6 +25,7 @@ impl LayoutHolder for ImaginateTool { } } +#[message_handler_data()] impl<'a> MessageHandler> for ImaginateTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, tool_data: &mut ToolActionHandlerData<'a>) { self.fsm_state.process_event(message, &mut self.tool_data, tool_data, &(), responses, true); diff --git a/editor/src/messages/tool/tool_messages/line_tool.rs b/editor/src/messages/tool/tool_messages/line_tool.rs index 0bd281a620..9e2436d453 100644 --- a/editor/src/messages/tool/tool_messages/line_tool.rs +++ b/editor/src/messages/tool/tool_messages/line_tool.rs @@ -12,7 +12,7 @@ use graph_craft::document::value::TaggedValue; use graph_craft::document::{NodeId, NodeInput}; use graphene_core::Color; -#[derive(Default)] +#[derive(Default, ExtractField)] pub struct LineTool { fsm_state: LineToolFsmState, tool_data: LineToolData, @@ -95,6 +95,7 @@ impl LayoutHolder for LineTool { } } +#[message_handler_data()] impl<'a> MessageHandler> for LineTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, tool_data: &mut ToolActionHandlerData<'a>) { let ToolMessage::Line(LineToolMessage::UpdateOptions(action)) = message else { diff --git a/editor/src/messages/tool/tool_messages/navigate_tool.rs b/editor/src/messages/tool/tool_messages/navigate_tool.rs index 0a76a331dc..4b9446553f 100644 --- a/editor/src/messages/tool/tool_messages/navigate_tool.rs +++ b/editor/src/messages/tool/tool_messages/navigate_tool.rs @@ -1,6 +1,6 @@ use super::tool_prelude::*; -#[derive(Default)] +#[derive(Default, ExtractField)] pub struct NavigateTool { fsm_state: NavigateToolFsmState, tool_data: NavigateToolData, @@ -38,6 +38,7 @@ impl LayoutHolder for NavigateTool { } } +#[message_handler_data()] impl<'a> MessageHandler> for NavigateTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, tool_data: &mut ToolActionHandlerData<'a>) { self.fsm_state.process_event(message, &mut self.tool_data, tool_data, &(), responses, true); diff --git a/editor/src/messages/tool/tool_messages/path_tool.rs b/editor/src/messages/tool/tool_messages/path_tool.rs index 30a05ed198..8efa8dd139 100644 --- a/editor/src/messages/tool/tool_messages/path_tool.rs +++ b/editor/src/messages/tool/tool_messages/path_tool.rs @@ -21,7 +21,7 @@ use graphene_core::vector::{ManipulatorPointId, PointId, VectorModificationType} use graphene_std::vector::{HandleId, NoHashBuilder, SegmentId, VectorData}; use std::vec; -#[derive(Default)] +#[derive(Default, ExtractField)] pub struct PathTool { fsm_state: PathToolFsmState, tool_data: PathToolData, @@ -226,6 +226,7 @@ impl LayoutHolder for PathTool { } } +#[message_handler_data()] impl<'a> MessageHandler> for PathTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, tool_data: &mut ToolActionHandlerData<'a>) { let updating_point = message == ToolMessage::Path(PathToolMessage::SelectedPointUpdated); diff --git a/editor/src/messages/tool/tool_messages/pen_tool.rs b/editor/src/messages/tool/tool_messages/pen_tool.rs index f0ceb00b9c..cfa313fb45 100644 --- a/editor/src/messages/tool/tool_messages/pen_tool.rs +++ b/editor/src/messages/tool/tool_messages/pen_tool.rs @@ -17,7 +17,7 @@ use graphene_core::Color; use graphene_core::vector::{PointId, VectorModificationType}; use graphene_std::vector::{HandleId, ManipulatorPointId, NoHashBuilder, SegmentId, StrokeId, VectorData}; -#[derive(Default)] +#[derive(Default, ExtractField)] pub struct PenTool { fsm_state: PenToolFsmState, tool_data: PenToolData, @@ -186,6 +186,7 @@ impl LayoutHolder for PenTool { } } +#[message_handler_data()] impl<'a> MessageHandler> for PenTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, tool_data: &mut ToolActionHandlerData<'a>) { let ToolMessage::Pen(PenToolMessage::UpdateOptions(action)) = message else { diff --git a/editor/src/messages/tool/tool_messages/polygon_tool.rs b/editor/src/messages/tool/tool_messages/polygon_tool.rs index 51cce795f8..3d0dc01486 100644 --- a/editor/src/messages/tool/tool_messages/polygon_tool.rs +++ b/editor/src/messages/tool/tool_messages/polygon_tool.rs @@ -14,7 +14,7 @@ use graph_craft::document::value::TaggedValue; use graph_craft::document::{NodeId, NodeInput}; use graphene_core::Color; -#[derive(Default)] +#[derive(Default, ExtractField)] pub struct PolygonTool { fsm_state: PolygonToolFsmState, tool_data: PolygonToolData, @@ -153,6 +153,8 @@ impl LayoutHolder for PolygonTool { Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row { widgets }])) } } + +#[message_handler_data()] impl<'a> MessageHandler> for PolygonTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, tool_data: &mut ToolActionHandlerData<'a>) { let ToolMessage::Polygon(PolygonToolMessage::UpdateOptions(action)) = message else { diff --git a/editor/src/messages/tool/tool_messages/rectangle_tool.rs b/editor/src/messages/tool/tool_messages/rectangle_tool.rs index ee5e73e1bf..c451bce221 100644 --- a/editor/src/messages/tool/tool_messages/rectangle_tool.rs +++ b/editor/src/messages/tool/tool_messages/rectangle_tool.rs @@ -13,7 +13,7 @@ use graph_craft::document::value::TaggedValue; use graph_craft::document::{NodeId, NodeInput}; use graphene_core::Color; -#[derive(Default)] +#[derive(Default, ExtractField)] pub struct RectangleTool { fsm_state: RectangleToolFsmState, tool_data: RectangleToolData, @@ -98,6 +98,7 @@ impl LayoutHolder for RectangleTool { } } +#[message_handler_data()] impl<'a> MessageHandler> for RectangleTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, tool_data: &mut ToolActionHandlerData<'a>) { let ToolMessage::Rectangle(RectangleToolMessage::UpdateOptions(action)) = message else { diff --git a/editor/src/messages/tool/tool_messages/select_tool.rs b/editor/src/messages/tool/tool_messages/select_tool.rs index 9affd74bc6..65141683ea 100644 --- a/editor/src/messages/tool/tool_messages/select_tool.rs +++ b/editor/src/messages/tool/tool_messages/select_tool.rs @@ -32,7 +32,7 @@ use graphene_std::transform::ReferencePoint; use graphene_std::vector::misc::BooleanOperation; use std::fmt; -#[derive(Default)] +#[derive(Default, ExtractField)] pub struct SelectTool { fsm_state: SelectToolFsmState, tool_data: SelectToolData, @@ -246,6 +246,7 @@ impl LayoutHolder for SelectTool { } } +#[message_handler_data()] impl<'a> MessageHandler> for SelectTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, tool_data: &mut ToolActionHandlerData<'a>) { if let ToolMessage::Select(SelectToolMessage::SelectOptions(SelectOptionsUpdate::NestedSelectionBehavior(nested_selection_behavior))) = message { diff --git a/editor/src/messages/tool/tool_messages/spline_tool.rs b/editor/src/messages/tool/tool_messages/spline_tool.rs index bcec6aaf52..ea14a13b74 100644 --- a/editor/src/messages/tool/tool_messages/spline_tool.rs +++ b/editor/src/messages/tool/tool_messages/spline_tool.rs @@ -14,7 +14,7 @@ use graph_craft::document::{NodeId, NodeInput}; use graphene_core::Color; use graphene_std::vector::{PointId, SegmentId, VectorModificationType}; -#[derive(Default)] +#[derive(Default, ExtractField)] pub struct SplineTool { fsm_state: SplineToolFsmState, tool_data: SplineToolData, @@ -123,6 +123,7 @@ impl LayoutHolder for SplineTool { } } +#[message_handler_data()] impl<'a> MessageHandler> for SplineTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, tool_data: &mut ToolActionHandlerData<'a>) { let ToolMessage::Spline(SplineToolMessage::UpdateOptions(action)) = message else { diff --git a/editor/src/messages/tool/tool_messages/text_tool.rs b/editor/src/messages/tool/tool_messages/text_tool.rs index 40c5469aae..eaff0782c4 100644 --- a/editor/src/messages/tool/tool_messages/text_tool.rs +++ b/editor/src/messages/tool/tool_messages/text_tool.rs @@ -21,7 +21,7 @@ use graphene_core::renderer::Quad; use graphene_core::text::{Font, FontCache, TypesettingConfig, lines_clipping, load_face}; use graphene_core::vector::style::Fill; -#[derive(Default)] +#[derive(Default, ExtractField)] pub struct TextTool { fsm_state: TextToolFsmState, tool_data: TextToolData, @@ -169,6 +169,7 @@ impl LayoutHolder for TextTool { } } +#[message_handler_data()] impl<'a> MessageHandler> for TextTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, tool_data: &mut ToolActionHandlerData<'a>) { let ToolMessage::Text(TextToolMessage::UpdateOptions(action)) = message else { diff --git a/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs b/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs index d1eefbf954..ab76ae3c8b 100644 --- a/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs +++ b/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs @@ -135,13 +135,16 @@ fn update_colinear_handles(selected_layers: &[LayerNodeIdentifier], document: &D type TransformData<'a> = (&'a DocumentMessageHandler, &'a InputPreprocessorMessageHandler, &'a ToolData, &'a mut ShapeState); -pub fn custom_data() -> Vec<(String, usize)> { - vec![ - (String::from("&'a DocumentMessageHandler"), 136), - (String::from("&'a InputPreprocessorMessageHandler"), 136), - (String::from("&'a ToolData"), 136), - (String::from("&'a mut ShapeState"), 136), - ] +pub fn custom_data() -> MessageData { + MessageData::new( + String::from("TransformData<'a>"), + vec![ + (String::from("&'a DocumentMessageHandler"), 136), + (String::from("&'a InputPreprocessorMessageHandler"), 136), + (String::from("&'a ToolData"), 136), + (String::from("&'a mut ShapeState"), 136), + ], + ) } #[message_handler_data(CustomData)] diff --git a/editor/src/messages/tool/utility_types.rs b/editor/src/messages/tool/utility_types.rs index 88a1a8423d..822585b013 100644 --- a/editor/src/messages/tool/utility_types.rs +++ b/editor/src/messages/tool/utility_types.rs @@ -17,6 +17,7 @@ use graphene_core::text::FontCache; use std::borrow::Cow; use std::fmt::{self, Debug}; +#[derive(ExtractField)] pub struct ToolActionHandlerData<'a> { pub document: &'a mut DocumentMessageHandler, pub document_id: DocumentId, diff --git a/editor/src/utility_traits.rs b/editor/src/utility_traits.rs index 40769930b2..d6085083f6 100644 --- a/editor/src/utility_traits.rs +++ b/editor/src/utility_traits.rs @@ -49,11 +49,110 @@ pub trait Hint { pub trait HierarchicalTree { fn build_message_tree() -> DebugMessageTree; - fn message_handler_data_str() -> Vec<(String, usize)> { - Vec::new() + fn message_handler_data_str() -> MessageData { + MessageData::new(String::new(), Vec::new()) } - fn message_handler_str() -> Vec<(String, usize)> { - Vec::new() + fn message_handler_str() -> MessageData { + MessageData::new(String::new(), Vec::new()) + } + + fn path() -> &'static str { + "" + } +} + +#[derive(Debug)] +pub struct MessageData { + name: String, + fields: Vec<(String, usize)>, +} + +impl MessageData { + pub fn new(name: String, fields: Vec<(String, usize)>) -> MessageData { + MessageData { name, fields } + } + + pub fn name(&self) -> &str { + &self.name + } + + pub fn fields(&self) -> &Vec<(String, usize)> { + &self.fields + } +} + +#[derive(Debug)] +pub struct DebugMessageTree { + name: String, + variants: Option>, + message_handler: Option, + message_handler_data: Option, + path: &'static str, +} + +impl DebugMessageTree { + pub fn new(name: &str) -> DebugMessageTree { + DebugMessageTree { + name: name.to_string(), + variants: None, + message_handler: None, + message_handler_data: None, + path: "", + } + } + + pub fn add_path(&mut self, path: &'static str) { + self.path = path; + } + + pub fn add_variant(&mut self, variant: DebugMessageTree) { + if let Some(variants) = &mut self.variants { + variants.push(variant); + } else { + self.variants = Some(vec![variant]); + } + } + + pub fn add_message_handler_data_field(&mut self, message_handler_data: MessageData) { + self.message_handler_data = Some(message_handler_data); + } + + pub fn add_message_handler_field(&mut self, message_handler: MessageData) { + self.message_handler = Some(message_handler); + } + + pub fn name(&self) -> &str { + &self.name + } + + pub fn path(&self) -> &'static str { + self.path + } + + pub fn variants(&self) -> Option<&Vec> { + self.variants.as_ref() + } + + pub fn message_handler_data_fields(&self) -> Option<&MessageData> { + self.message_handler_data.as_ref() + } + + pub fn message_handler_fields(&self) -> Option<&MessageData> { + self.message_handler.as_ref() + } + + pub fn has_message_handler_data_fields(&self) -> bool { + match self.message_handler_data_fields() { + Some(_) => true, + None => false, + } + } + + pub fn has_message_handler_fields(&self) -> bool { + match self.message_handler_fields() { + Some(_) => true, + None => false, + } } } diff --git a/proc-macros/src/hierarchical_tree.rs b/proc-macros/src/hierarchical_tree.rs index 11d63b4948..721dc9c854 100644 --- a/proc-macros/src/hierarchical_tree.rs +++ b/proc-macros/src/hierarchical_tree.rs @@ -52,14 +52,17 @@ pub fn generate_hierarchical_tree(input: TokenStream) -> syn::Result 0 { - message_tree.add_message_handler_field(format!("{}Handler", stringify!(#input_type)), message_handler_str); + if message_handler_str.fields().len() > 0 { + message_tree.add_message_handler_field(message_handler_str); } let message_handler_data_str = #input_type::message_handler_data_str(); - if message_handler_data_str.len() > 0 { - message_tree.add_message_handler_data_field(format!("{}Data", stringify!(#input_type)), message_handler_data_str); + if message_handler_data_str.fields().len() > 0 { + message_tree.add_message_handler_data_field(message_handler_data_str); } + + message_tree.add_path(#input_type::path()); + message_tree } } diff --git a/proc-macros/src/message_handler_data_attr.rs b/proc-macros/src/message_handler_data_attr.rs index 1a9689a1dd..5c6b3dc325 100644 --- a/proc-macros/src/message_handler_data_attr.rs +++ b/proc-macros/src/message_handler_data_attr.rs @@ -2,6 +2,8 @@ use proc_macro2::{Span, TokenStream}; use quote::quote; use syn::{ItemImpl, Type, parse2, spanned::Spanned}; +use crate::helpers::call_site_ident; + pub fn message_handler_data_attr_impl(attr: TokenStream, input_item: TokenStream) -> syn::Result { // Parse the input as an impl block let impl_block = parse2::(input_item.clone())?; @@ -46,11 +48,15 @@ pub fn message_handler_data_attr_impl(attr: TokenStream, input_item: TokenStream quote! { #input_item impl #message_type { - pub fn message_handler_data_str() -> Vec<(String, usize)> { + pub fn message_handler_data_str() -> MessageData { custom_data() } - pub fn message_handler_str() -> Vec<(String, usize)> { - #input_type::field_types() + pub fn message_handler_str() -> MessageData { + MessageData::new(format!("{}",stringify!(#input_type)), #input_type::field_types()) + + } + pub fn path() -> &'static str { + file!() } } } @@ -58,11 +64,17 @@ pub fn message_handler_data_attr_impl(attr: TokenStream, input_item: TokenStream quote! { #input_item impl #message_type { - pub fn message_handler_data_str() -> Vec<(String, usize)> { - #type_name::field_types() + pub fn message_handler_data_str() -> MessageData + { + MessageData::new(format!("{}",stringify!(#type_name)), #type_name::field_types()) + } - pub fn message_handler_str() -> Vec<(String, usize)> { - #input_type::field_types() + pub fn message_handler_str() -> MessageData { + MessageData::new(format!("{}",stringify!(#input_type)), #input_type::field_types()) + + } + pub fn path() -> &'static str { + file!() } } } @@ -71,17 +83,48 @@ pub fn message_handler_data_attr_impl(attr: TokenStream, input_item: TokenStream syn::Type::Tuple(_) => quote! { #input_item impl #message_type { - pub fn message_handler_str() -> Vec<(String, usize)> { - #input_type::field_types() + pub fn message_handler_str() -> MessageData { + MessageData::new(format!("{}",stringify!(#input_type)), #input_type::field_types()) } + pub fn path() -> &'static str { + file!() + } } }, + syn::Type::Reference(type_reference) => { + let message_type = call_site_ident(format!("{input_type}Message")); + let type_ident = match &*type_reference.elem { + syn::Type::Path(type_path) => &type_path.path.segments.first().unwrap().ident, + _ => return Err(syn::Error::new(type_reference.elem.span(), "Expected type path")), + }; + quote! { + #input_item + impl #message_type { + pub fn message_handler_data_str() -> MessageData { + MessageData::new(format!("{}",stringify!(#type_reference)),#type_ident::field_types()) + } + + pub fn message_handler_str() -> MessageData { + MessageData::new(format!("{}",stringify!(#input_type)), #input_type::field_types()) + + } + pub fn path() -> &'static str { + file!() + } + } + } + } _ => return Err(syn::Error::new(t.span(), "Unsupported type format")), } } _ => quote! { #input_item + impl #message_type { + pub fn path() -> &'static str { + file!() + } + } }, }; return Ok(impl_item); From d034c4c4df8974f690ec0a4ea93c9a1501245959 Mon Sep 17 00:00:00 2001 From: Mohd Mohsin Date: Mon, 19 May 2025 15:47:13 +0530 Subject: [PATCH 10/13] clean the white spaces in type string --- proc-macros/src/extract_fields.rs | 3 +- proc-macros/src/helpers.rs | 39 ++++++++++++++++++++ proc-macros/src/message_handler_data_attr.rs | 7 ++-- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/proc-macros/src/extract_fields.rs b/proc-macros/src/extract_fields.rs index efd8652ac7..13a4761f1e 100644 --- a/proc-macros/src/extract_fields.rs +++ b/proc-macros/src/extract_fields.rs @@ -1,3 +1,4 @@ +use crate::helpers::clean_rust_type_syntax; use proc_macro2::{Span, TokenStream}; use quote::{ToTokens, format_ident, quote}; use syn::{Data, DeriveInput, Fields, Type, parse2}; @@ -23,7 +24,7 @@ pub fn derive_extract_field_impl(input: TokenStream) -> syn::Result .map(|field| { let ident = field.ident.as_ref().unwrap(); let name = ident.to_string(); - let ty = field.ty.to_token_stream().to_string(); + let ty = clean_rust_type_syntax(field.ty.to_token_stream().to_string()); let line = ident.span().start().line; field_line.push(line); (name, ty) diff --git a/proc-macros/src/helpers.rs b/proc-macros/src/helpers.rs index 11c18c8b41..0abca93164 100644 --- a/proc-macros/src/helpers.rs +++ b/proc-macros/src/helpers.rs @@ -42,6 +42,45 @@ pub fn two_segment_path(left_ident: Ident, right_ident: Ident) -> Path { Path { leading_colon: None, segments } } +pub fn clean_rust_type_syntax(input: String) -> String { + let mut result = String::new(); + let mut chars = input.chars().peekable(); + + while let Some(c) = chars.next() { + match c { + '&' => { + result.push('&'); + while let Some(' ') = chars.peek() { + chars.next(); + } + } + '<' => { + while let Some(' ') = result.chars().rev().next() { + result.pop(); + } + result.push('<'); + while let Some(' ') = chars.peek() { + chars.next(); + } + } + '>' => { + while let Some(' ') = result.chars().rev().next() { + result.pop(); + } + result.push('>'); + while let Some(' ') = chars.peek() { + chars.next(); + } + } + _ => { + result.push(c); + } + } + } + + result +} + #[cfg(test)] mod tests { use super::*; diff --git a/proc-macros/src/message_handler_data_attr.rs b/proc-macros/src/message_handler_data_attr.rs index 5c6b3dc325..7d97e21162 100644 --- a/proc-macros/src/message_handler_data_attr.rs +++ b/proc-macros/src/message_handler_data_attr.rs @@ -1,8 +1,8 @@ use proc_macro2::{Span, TokenStream}; -use quote::quote; +use quote::{ToTokens, quote}; use syn::{ItemImpl, Type, parse2, spanned::Spanned}; -use crate::helpers::call_site_ident; +use crate::helpers::{call_site_ident, clean_rust_type_syntax}; pub fn message_handler_data_attr_impl(attr: TokenStream, input_item: TokenStream) -> syn::Result { // Parse the input as an impl block @@ -97,11 +97,12 @@ pub fn message_handler_data_attr_impl(attr: TokenStream, input_item: TokenStream syn::Type::Path(type_path) => &type_path.path.segments.first().unwrap().ident, _ => return Err(syn::Error::new(type_reference.elem.span(), "Expected type path")), }; + let tr = clean_rust_type_syntax(type_reference.to_token_stream().to_string()); quote! { #input_item impl #message_type { pub fn message_handler_data_str() -> MessageData { - MessageData::new(format!("{}",stringify!(#type_reference)),#type_ident::field_types()) + MessageData::new(format!("{}", #tr),#type_ident::field_types()) } pub fn message_handler_str() -> MessageData { From 065af10d781286e2f2d506a710e066dcc24084de Mon Sep 17 00:00:00 2001 From: Mohd Mohsin Date: Sun, 25 May 2025 16:31:02 +0530 Subject: [PATCH 11/13] fixes some white spaces --- editor/src/messages/message.rs | 6 +++++- proc-macros/src/helpers.rs | 13 +++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/editor/src/messages/message.rs b/editor/src/messages/message.rs index ea27272d3b..5723aacbb0 100644 --- a/editor/src/messages/message.rs +++ b/editor/src/messages/message.rs @@ -79,7 +79,11 @@ mod test { } }; - println!("{}{}{} {}", prefix, branch, tree.name(), tree.path()); + if tree.path().is_empty() { + println!("{}{}{}", prefix, branch, tree.name()); + } else { + println!("{}{}{} {}", prefix, branch, tree.name(), tree.path()); + } // Print children if any if let Some(variants) = tree.variants() { diff --git a/proc-macros/src/helpers.rs b/proc-macros/src/helpers.rs index 0abca93164..230f792c0f 100644 --- a/proc-macros/src/helpers.rs +++ b/proc-macros/src/helpers.rs @@ -72,6 +72,19 @@ pub fn clean_rust_type_syntax(input: String) -> String { chars.next(); } } + ':' => { + if let Some(':') = chars.peek() { + while let Some(' ') = result.chars().rev().next() { + result.pop(); + } + } + result.push(':'); + chars.next(); + result.push(':'); + while let Some(' ') = chars.peek() { + chars.next(); + } + } _ => { result.push(c); } From 7bc5397a16be595075ac008ea2a1a85849a7571e Mon Sep 17 00:00:00 2001 From: Mohd Mohsin Date: Mon, 26 May 2025 15:42:25 +0530 Subject: [PATCH 12/13] feat: added path to message enum in hierarchical tree --- editor/src/lib.rs | 1 + .../messages/layout/layout_message_handler.rs | 2 +- editor/src/messages/message.rs | 18 ++-- editor/src/messages/prelude.rs | 3 +- .../transform_layer_message_handler.rs | 1 + editor/src/utility_traits.rs | 99 +------------------ editor/src/utility_types.rs | 99 +++++++++++++++++++ proc-macros/src/extract_fields.rs | 4 + proc-macros/src/hierarchical_tree.rs | 2 +- proc-macros/src/message_handler_data_attr.rs | 29 ++---- 10 files changed, 128 insertions(+), 130 deletions(-) create mode 100644 editor/src/utility_types.rs diff --git a/editor/src/lib.rs b/editor/src/lib.rs index 80d80b5305..2c59945136 100644 --- a/editor/src/lib.rs +++ b/editor/src/lib.rs @@ -15,3 +15,4 @@ pub mod node_graph_executor; #[cfg(test)] pub mod test_utils; pub mod utility_traits; +pub mod utility_types; diff --git a/editor/src/messages/layout/layout_message_handler.rs b/editor/src/messages/layout/layout_message_handler.rs index 27bcd44b0f..8328ca7971 100644 --- a/editor/src/messages/layout/layout_message_handler.rs +++ b/editor/src/messages/layout/layout_message_handler.rs @@ -339,7 +339,7 @@ impl LayoutMessageHandler { } pub fn custom_data() -> MessageData { - MessageData::new(String::from("Function"), vec![(String::from("Fn(&MessageDiscriminant) -> Vec"), 346)]) + MessageData::new(String::from("Function"), vec![(String::from("Fn(&MessageDiscriminant) -> Vec"), 346)], file!()) } #[message_handler_data(CustomData)] diff --git a/editor/src/messages/message.rs b/editor/src/messages/message.rs index 5723aacbb0..8f71b66c42 100644 --- a/editor/src/messages/message.rs +++ b/editor/src/messages/message.rs @@ -50,11 +50,6 @@ impl specta::Type for MessageDiscriminant { mod test { use super::*; - #[test] - fn print_tool_message_handler() { - ToolMessageHandler::print_field_types(); - } - #[test] fn generate_message_tree() { let res = Message::build_message_tree(); @@ -102,10 +97,15 @@ mod test { } else { ("└── ", format!("{} ", prefix)) }; - println!("{}{}{}", prefix, branch, data.name()); + if data.path().is_empty() { + println!("{}{}{}", prefix, branch, data.name()); + } else { + println!("{}{}{} {}", prefix, branch, data.name(), data.path()); + } for (i, field) in data.fields().iter().enumerate() { let is_last_field = i == len - 1; let branch = if is_last_field { "└── " } else { "├── " }; + println!("{}{}{}", child_prefix, branch, field.0); } } @@ -113,7 +113,11 @@ mod test { // Print data field if any if let Some(data) = tree.message_handler_data_fields() { let len = data.fields().len(); - println!("{}{}{}", prefix, "└── ", data.name()); + if data.path().is_empty() { + println!("{}{}{}", prefix, "└── ", data.name()); + } else { + println!("{}{}{} {}", prefix, "└── ", data.name(), data.path()); + } for (i, field) in data.fields().iter().enumerate() { let is_last_field = i == len - 1; let branch = if is_last_field { "└── " } else { "├── " }; diff --git a/editor/src/messages/prelude.rs b/editor/src/messages/prelude.rs index 24c3ea193b..3c537bbbc9 100644 --- a/editor/src/messages/prelude.rs +++ b/editor/src/messages/prelude.rs @@ -1,5 +1,6 @@ // Root -pub use crate::utility_traits::{ActionList, AsMessage, DebugMessageTree, HierarchicalTree, MessageData, MessageHandler, ToDiscriminant, TransitiveChild}; +pub use crate::utility_traits::{ActionList, AsMessage, HierarchicalTree, MessageHandler, ToDiscriminant, TransitiveChild}; +pub use crate::utility_types::{DebugMessageTree, MessageData}; // Message, MessageData, MessageDiscriminant, MessageHandler pub use crate::messages::animation::{AnimationMessage, AnimationMessageDiscriminant, AnimationMessageHandler}; pub use crate::messages::broadcast::{BroadcastMessage, BroadcastMessageDiscriminant, BroadcastMessageHandler}; diff --git a/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs b/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs index ab76ae3c8b..73dbde2954 100644 --- a/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs +++ b/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs @@ -144,6 +144,7 @@ pub fn custom_data() -> MessageData { (String::from("&'a ToolData"), 136), (String::from("&'a mut ShapeState"), 136), ], + file!(), ) } diff --git a/editor/src/utility_traits.rs b/editor/src/utility_traits.rs index d6085083f6..850d730b13 100644 --- a/editor/src/utility_traits.rs +++ b/editor/src/utility_traits.rs @@ -50,109 +50,14 @@ pub trait HierarchicalTree { fn build_message_tree() -> DebugMessageTree; fn message_handler_data_str() -> MessageData { - MessageData::new(String::new(), Vec::new()) + MessageData::new(String::new(), Vec::new(), "") } fn message_handler_str() -> MessageData { - MessageData::new(String::new(), Vec::new()) + MessageData::new(String::new(), Vec::new(), "") } fn path() -> &'static str { "" } } - -#[derive(Debug)] -pub struct MessageData { - name: String, - fields: Vec<(String, usize)>, -} - -impl MessageData { - pub fn new(name: String, fields: Vec<(String, usize)>) -> MessageData { - MessageData { name, fields } - } - - pub fn name(&self) -> &str { - &self.name - } - - pub fn fields(&self) -> &Vec<(String, usize)> { - &self.fields - } -} - -#[derive(Debug)] -pub struct DebugMessageTree { - name: String, - variants: Option>, - message_handler: Option, - message_handler_data: Option, - path: &'static str, -} - -impl DebugMessageTree { - pub fn new(name: &str) -> DebugMessageTree { - DebugMessageTree { - name: name.to_string(), - variants: None, - message_handler: None, - message_handler_data: None, - path: "", - } - } - - pub fn add_path(&mut self, path: &'static str) { - self.path = path; - } - - pub fn add_variant(&mut self, variant: DebugMessageTree) { - if let Some(variants) = &mut self.variants { - variants.push(variant); - } else { - self.variants = Some(vec![variant]); - } - } - - pub fn add_message_handler_data_field(&mut self, message_handler_data: MessageData) { - self.message_handler_data = Some(message_handler_data); - } - - pub fn add_message_handler_field(&mut self, message_handler: MessageData) { - self.message_handler = Some(message_handler); - } - - pub fn name(&self) -> &str { - &self.name - } - - pub fn path(&self) -> &'static str { - self.path - } - - pub fn variants(&self) -> Option<&Vec> { - self.variants.as_ref() - } - - pub fn message_handler_data_fields(&self) -> Option<&MessageData> { - self.message_handler_data.as_ref() - } - - pub fn message_handler_fields(&self) -> Option<&MessageData> { - self.message_handler.as_ref() - } - - pub fn has_message_handler_data_fields(&self) -> bool { - match self.message_handler_data_fields() { - Some(_) => true, - None => false, - } - } - - pub fn has_message_handler_fields(&self) -> bool { - match self.message_handler_fields() { - Some(_) => true, - None => false, - } - } -} diff --git a/editor/src/utility_types.rs b/editor/src/utility_types.rs new file mode 100644 index 0000000000..6b5dc6de6b --- /dev/null +++ b/editor/src/utility_types.rs @@ -0,0 +1,99 @@ +#[derive(Debug)] +pub struct MessageData { + name: String, + fields: Vec<(String, usize)>, + path: &'static str, +} + +impl MessageData { + pub fn new(name: String, fields: Vec<(String, usize)>, path: &'static str) -> MessageData { + MessageData { name, fields, path } + } + + pub fn name(&self) -> &str { + &self.name + } + + pub fn fields(&self) -> &Vec<(String, usize)> { + &self.fields + } + + pub fn path(&self) -> &'static str { + self.path + } +} + +#[derive(Debug)] +pub struct DebugMessageTree { + name: String, + variants: Option>, + message_handler: Option, + message_handler_data: Option, + path: &'static str, +} + +impl DebugMessageTree { + pub fn new(name: &str) -> DebugMessageTree { + DebugMessageTree { + name: name.to_string(), + variants: None, + message_handler: None, + message_handler_data: None, + path: "", + } + } + + pub fn set_path(&mut self, path: &'static str) { + self.path = path; + } + + pub fn add_variant(&mut self, variant: DebugMessageTree) { + if let Some(variants) = &mut self.variants { + variants.push(variant); + } else { + self.variants = Some(vec![variant]); + } + } + + pub fn add_message_handler_data_field(&mut self, message_handler_data: MessageData) { + self.message_handler_data = Some(message_handler_data); + } + + pub fn add_message_handler_field(&mut self, message_handler: MessageData) { + self.message_handler = Some(message_handler); + } + + pub fn name(&self) -> &str { + &self.name + } + + pub fn path(&self) -> &'static str { + self.path + } + + pub fn variants(&self) -> Option<&Vec> { + self.variants.as_ref() + } + + pub fn message_handler_data_fields(&self) -> Option<&MessageData> { + self.message_handler_data.as_ref() + } + + pub fn message_handler_fields(&self) -> Option<&MessageData> { + self.message_handler.as_ref() + } + + pub fn has_message_handler_data_fields(&self) -> bool { + match self.message_handler_data_fields() { + Some(_) => true, + None => false, + } + } + + pub fn has_message_handler_fields(&self) -> bool { + match self.message_handler_fields() { + Some(_) => true, + None => false, + } + } +} diff --git a/proc-macros/src/extract_fields.rs b/proc-macros/src/extract_fields.rs index 13a4761f1e..606b3b8a37 100644 --- a/proc-macros/src/extract_fields.rs +++ b/proc-macros/src/extract_fields.rs @@ -46,6 +46,10 @@ pub fn derive_extract_field_impl(input: TokenStream) -> syn::Result println!("{} at line {}", field, line); } } + + pub fn path() -> &'static str { + file!() + } } }; diff --git a/proc-macros/src/hierarchical_tree.rs b/proc-macros/src/hierarchical_tree.rs index 721dc9c854..d93ff58866 100644 --- a/proc-macros/src/hierarchical_tree.rs +++ b/proc-macros/src/hierarchical_tree.rs @@ -61,7 +61,7 @@ pub fn generate_hierarchical_tree(input: TokenStream) -> syn::Result MessageData { - MessageData::new(format!("{}",stringify!(#input_type)), #input_type::field_types()) + MessageData::new(format!("{}",stringify!(#input_type)), #input_type::field_types(), #input_type::path()) } - pub fn path() -> &'static str { - file!() - } } } } else { @@ -66,16 +63,13 @@ pub fn message_handler_data_attr_impl(attr: TokenStream, input_item: TokenStream impl #message_type { pub fn message_handler_data_str() -> MessageData { - MessageData::new(format!("{}",stringify!(#type_name)), #type_name::field_types()) + MessageData::new(format!("{}",stringify!(#type_name)), #type_name::field_types(), #type_name::path()) } pub fn message_handler_str() -> MessageData { - MessageData::new(format!("{}",stringify!(#input_type)), #input_type::field_types()) + MessageData::new(format!("{}",stringify!(#input_type)), #input_type::field_types(), #input_type::path()) } - pub fn path() -> &'static str { - file!() - } } } } @@ -84,11 +78,8 @@ pub fn message_handler_data_attr_impl(attr: TokenStream, input_item: TokenStream #input_item impl #message_type { pub fn message_handler_str() -> MessageData { - MessageData::new(format!("{}",stringify!(#input_type)), #input_type::field_types()) + MessageData::new(format!("{}",stringify!(#input_type)), #input_type::field_types(), #input_type::path()) } - pub fn path() -> &'static str { - file!() - } } }, syn::Type::Reference(type_reference) => { @@ -102,16 +93,13 @@ pub fn message_handler_data_attr_impl(attr: TokenStream, input_item: TokenStream #input_item impl #message_type { pub fn message_handler_data_str() -> MessageData { - MessageData::new(format!("{}", #tr),#type_ident::field_types()) + MessageData::new(format!("{}", #tr),#type_ident::field_types(), #type_ident::path()) } pub fn message_handler_str() -> MessageData { - MessageData::new(format!("{}",stringify!(#input_type)), #input_type::field_types()) + MessageData::new(format!("{}",stringify!(#input_type)), #input_type::field_types(), #input_type::path()) } - pub fn path() -> &'static str { - file!() - } } } } @@ -121,11 +109,6 @@ pub fn message_handler_data_attr_impl(attr: TokenStream, input_item: TokenStream _ => quote! { #input_item - impl #message_type { - pub fn path() -> &'static str { - file!() - } - } }, }; return Ok(impl_item); From ca8dbfb482d24c44982f503650f923ededa1fab8 Mon Sep 17 00:00:00 2001 From: Mohd Mohsin Date: Wed, 28 May 2025 16:25:40 +0530 Subject: [PATCH 13/13] feat: add file creation of hierarchical message system tree --- editor/src/messages/message.rs | 26 +- hierarchical_message_system_tree.txt | 1110 ++++++++++++++++++++++++++ 2 files changed, 1124 insertions(+), 12 deletions(-) create mode 100644 hierarchical_message_system_tree.txt diff --git a/editor/src/messages/message.rs b/editor/src/messages/message.rs index 8f71b66c42..2b74d49f1d 100644 --- a/editor/src/messages/message.rs +++ b/editor/src/messages/message.rs @@ -49,20 +49,22 @@ impl specta::Type for MessageDiscriminant { #[cfg(test)] mod test { use super::*; + use std::io::Write; #[test] fn generate_message_tree() { let res = Message::build_message_tree(); - println!("{} {}", res.name(), res.path()); + let mut file = std::fs::File::create("../hierarchical_message_system_tree.txt").unwrap(); + file.write_all(format!("{} `{}`\n", res.name(), res.path()).as_bytes()).unwrap(); if let Some(variants) = res.variants() { for (i, variant) in variants.iter().enumerate() { let is_last = i == variants.len() - 1; - print_tree_node(variant, "", is_last); + print_tree_node(variant, "", is_last, &mut file); } } } - fn print_tree_node(tree: &DebugMessageTree, prefix: &str, is_last: bool) { + fn print_tree_node(tree: &DebugMessageTree, prefix: &str, is_last: bool, file: &mut std::fs::File) { // Print the current node let (branch, child_prefix) = if tree.has_message_handler_data_fields() || tree.has_message_handler_fields() { ("├── ", format!("{}│ ", prefix)) @@ -75,9 +77,9 @@ mod test { }; if tree.path().is_empty() { - println!("{}{}{}", prefix, branch, tree.name()); + file.write_all(format!("{}{}{}\n", prefix, branch, tree.name()).as_bytes()).unwrap(); } else { - println!("{}{}{} {}", prefix, branch, tree.name(), tree.path()); + file.write_all(format!("{}{}{} `{}`\n", prefix, branch, tree.name(), tree.path()).as_bytes()).unwrap(); } // Print children if any @@ -85,7 +87,7 @@ mod test { let len = variants.len(); for (i, variant) in variants.iter().enumerate() { let is_last_child = i == len - 1; - print_tree_node(variant, &child_prefix, is_last_child); + print_tree_node(variant, &child_prefix, is_last_child, file); } } @@ -98,15 +100,15 @@ mod test { ("└── ", format!("{} ", prefix)) }; if data.path().is_empty() { - println!("{}{}{}", prefix, branch, data.name()); + file.write_all(format!("{}{}{}\n", prefix, branch, data.name()).as_bytes()).unwrap(); } else { - println!("{}{}{} {}", prefix, branch, data.name(), data.path()); + file.write_all(format!("{}{}{} `{}`\n", prefix, branch, data.name(), data.path()).as_bytes()).unwrap(); } for (i, field) in data.fields().iter().enumerate() { let is_last_field = i == len - 1; let branch = if is_last_field { "└── " } else { "├── " }; - println!("{}{}{}", child_prefix, branch, field.0); + file.write_all(format!("{}{}{}\n", child_prefix, branch, field.0).as_bytes()).unwrap(); } } @@ -114,14 +116,14 @@ mod test { if let Some(data) = tree.message_handler_data_fields() { let len = data.fields().len(); if data.path().is_empty() { - println!("{}{}{}", prefix, "└── ", data.name()); + file.write_all(format!("{}{}{}\n", prefix, "└── ", data.name()).as_bytes()).unwrap(); } else { - println!("{}{}{} {}", prefix, "└── ", data.name(), data.path()); + file.write_all(format!("{}{}{} `{}`\n", prefix, "└── ", data.name(), data.path()).as_bytes()).unwrap(); } for (i, field) in data.fields().iter().enumerate() { let is_last_field = i == len - 1; let branch = if is_last_field { "└── " } else { "├── " }; - println!("{}{}{}", format!("{} ", prefix), branch, field.0); + file.write_all(format!("{}{}{}\n", format!("{} ", prefix), branch, field.0).as_bytes()).unwrap(); } } } diff --git a/hierarchical_message_system_tree.txt b/hierarchical_message_system_tree.txt new file mode 100644 index 0000000000..dbe0153c28 --- /dev/null +++ b/hierarchical_message_system_tree.txt @@ -0,0 +1,1110 @@ +Message `editor\src\messages\message.rs` +├── NoOp +├── Init +├── Batched +├── StartBuffer +├── EndBuffer +├── Animation +│ ├── AnimationMessage `editor\src\messages\animation\animation_message.rs` +│ │ ├── ToggleLivePreview +│ │ ├── EnableLivePreview +│ │ ├── DisableLivePreview +│ │ ├── RestartAnimation +│ │ ├── SetFrameIndex +│ │ ├── SetTime +│ │ ├── UpdateTime +│ │ ├── IncrementFrameCounter +│ │ └── SetAnimationTimeMode +│ └── AnimationMessageHandler `editor\src\messages\animation\animation_message_handler.rs` +│ ├── live_preview_recently_zero: bool +│ ├── timestamp: f64 +│ ├── frame_index: f64 +│ ├── animation_state: AnimationState +│ ├── fps: f64 +│ └── animation_time_mode: AnimationTimeMode +├── Broadcast +│ ├── BroadcastMessage `editor\src\messages\broadcast\broadcast_message.rs` +│ │ ├── TriggerEvent +│ │ ├── SubscribeEvent +│ │ └── UnsubscribeEvent +│ └── BroadcastMessageHandler `editor\src\messages\broadcast\broadcast_message_handler.rs` +│ └── listeners: HashMap> +├── Debug +│ ├── DebugMessage `editor\src\messages\debug\debug_message.rs` +│ │ ├── ToggleTraceLogs +│ │ ├── MessageOff +│ │ ├── MessageNames +│ │ └── MessageContents +│ └── DebugMessageHandler `editor\src\messages\debug\debug_message_handler.rs` +│ └── message_logging_verbosity: MessageLoggingVerbosity +├── Dialog +│ ├── DialogMessage `editor\src\messages\dialog\dialog_message.rs` +│ │ ├── ExportDialog +│ │ │ ├── ExportDialogMessage `editor\src\messages\dialog\export_dialog\export_dialog_message.rs` +│ │ │ │ ├── FileType +│ │ │ │ ├── ScaleFactor +│ │ │ │ ├── TransparentBackground +│ │ │ │ ├── ExportBounds +│ │ │ │ └── Submit +│ │ │ ├── ExportDialogMessageHandler `editor\src\messages\dialog\export_dialog\export_dialog_message_handler.rs` +│ │ │ │ ├── file_type: FileType +│ │ │ │ ├── scale_factor: f64 +│ │ │ │ ├── bounds: ExportBounds +│ │ │ │ ├── transparent_background: bool +│ │ │ │ ├── artboards: HashMap +│ │ │ │ └── has_selection: bool +│ │ │ └── ExportDialogMessageData `editor\src\messages\dialog\export_dialog\export_dialog_message_handler.rs` +│ │ │ └── portfolio: &'a PortfolioMessageHandler +│ │ ├── NewDocumentDialog +│ │ │ ├── NewDocumentDialogMessage `editor\src\messages\dialog\new_document_dialog\new_document_dialog_message.rs` +│ │ │ │ ├── Name +│ │ │ │ ├── Infinite +│ │ │ │ ├── DimensionsX +│ │ │ │ ├── DimensionsY +│ │ │ │ └── Submit +│ │ │ └── NewDocumentDialogMessageHandler `editor\src\messages\dialog\new_document_dialog\new_document_dialog_message_handler.rs` +│ │ │ ├── name: String +│ │ │ ├── infinite: bool +│ │ │ └── dimensions: UVec2 +│ │ ├── PreferencesDialog +│ │ │ ├── PreferencesDialogMessage `editor\src\messages\dialog\preferences_dialog\preferences_dialog_message.rs` +│ │ │ │ └── Confirm +│ │ │ └── PreferencesDialogMessageData `editor\src\messages\dialog\preferences_dialog\preferences_dialog_message_handler.rs` +│ │ │ └── preferences: &'a PreferencesMessageHandler +│ │ ├── CloseAllDocumentsWithConfirmation +│ │ ├── CloseDialogAndThen +│ │ ├── DisplayDialogError +│ │ ├── RequestAboutGraphiteDialog +│ │ ├── RequestAboutGraphiteDialogWithLocalizedCommitDate +│ │ ├── RequestComingSoonDialog +│ │ ├── RequestDemoArtworkDialog +│ │ ├── RequestExportDialog +│ │ ├── RequestLicensesDialogWithLocalizedCommitDate +│ │ ├── RequestNewDocumentDialog +│ │ └── RequestPreferencesDialog +│ ├── DialogMessageHandler `editor\src\messages\dialog\dialog_message_handler.rs` +│ │ ├── export_dialog: ExportDialogMessageHandler +│ │ ├── new_document_dialog: NewDocumentDialogMessageHandler +│ │ └── preferences_dialog: PreferencesDialogMessageHandler +│ └── DialogMessageData `editor\src\messages\dialog\dialog_message_handler.rs` +│ ├── portfolio: &'a PortfolioMessageHandler +│ └── preferences: &'a PreferencesMessageHandler +├── Frontend +│ └── FrontendMessage `editor\src\messages\frontend\frontend_message.rs` +│ ├── DisplayDialog +│ ├── DisplayDialogDismiss +│ ├── DisplayDialogPanic +│ ├── DisplayEditableTextbox +│ ├── DisplayEditableTextboxTransform +│ ├── DisplayRemoveEditableTextbox +│ ├── SendUIMetadata +│ ├── TriggerAboutGraphiteLocalizedCommitDate +│ ├── TriggerDelayedZoomCanvasToFitAll +│ ├── TriggerDownloadImage +│ ├── TriggerDownloadTextFile +│ ├── TriggerFetchAndOpenDocument +│ ├── TriggerFontLoad +│ ├── TriggerImport +│ ├── TriggerIndexedDbRemoveDocument +│ ├── TriggerIndexedDbWriteDocument +│ ├── TriggerLoadFirstAutoSaveDocument +│ ├── TriggerLoadRestAutoSaveDocuments +│ ├── TriggerLoadPreferences +│ ├── TriggerOpenDocument +│ ├── TriggerPaste +│ ├── TriggerSavePreferences +│ ├── TriggerSaveActiveDocument +│ ├── TriggerTextCommit +│ ├── TriggerTextCopy +│ ├── TriggerUpgradeDocumentToVectorManipulationFormat +│ ├── TriggerVisitLink +│ ├── UpdateActiveDocument +│ ├── UpdateImportsExports +│ ├── UpdateInSelectedNetwork +│ ├── UpdateBox +│ ├── UpdateContextMenuInformation +│ ├── UpdateClickTargets +│ ├── UpdateGraphViewOverlay +│ ├── UpdateSpreadsheetState +│ ├── UpdateSpreadsheetLayout +│ ├── UpdateImportReorderIndex +│ ├── UpdateExportReorderIndex +│ ├── UpdateLayerWidths +│ ├── UpdateDialogButtons +│ ├── UpdateDialogColumn1 +│ ├── UpdateDialogColumn2 +│ ├── UpdateDocumentArtwork +│ ├── UpdateDocumentBarLayout +│ ├── UpdateDocumentLayerDetails +│ ├── UpdateDocumentLayerStructure +│ ├── UpdateDocumentLayerStructureJs +│ ├── UpdateDocumentModeLayout +│ ├── UpdateDocumentRulers +│ ├── UpdateDocumentScrollbars +│ ├── UpdateEyedropperSamplingState +│ ├── UpdateGraphFadeArtwork +│ ├── UpdateInputHints +│ ├── UpdateLayersPanelControlBarLayout +│ ├── UpdateMenuBarLayout +│ ├── UpdateMouseCursor +│ ├── UpdateNodeGraph +│ ├── UpdateNodeGraphControlBarLayout +│ ├── UpdateNodeGraphSelection +│ ├── UpdateNodeGraphTransform +│ ├── UpdateNodeThumbnail +│ ├── UpdateOpenDocumentsList +│ ├── UpdatePropertyPanelSectionsLayout +│ ├── UpdateToolOptionsLayout +│ ├── UpdateToolShelfLayout +│ ├── UpdateWirePathInProgress +│ └── UpdateWorkingColorsLayout +├── Globals +│ └── GlobalsMessage `editor\src\messages\globals\globals_message.rs` +│ └── SetPlatform +├── InputPreprocessor +│ ├── InputPreprocessorMessage `editor\src\messages\input_preprocessor\input_preprocessor_message.rs` +│ │ ├── BoundsOfViewports +│ │ ├── DoubleClick +│ │ ├── KeyDown +│ │ ├── KeyUp +│ │ ├── PointerDown +│ │ ├── PointerMove +│ │ ├── PointerUp +│ │ ├── CurrentTime +│ │ └── WheelScroll +│ ├── InputPreprocessorMessageHandler `editor\src\messages\input_preprocessor\input_preprocessor_message_handler.rs` +│ │ ├── frame_time: FrameTimeInfo +│ │ ├── time: u64 +│ │ ├── keyboard: KeyStates +│ │ ├── mouse: MouseState +│ │ └── viewport_bounds: ViewportBounds +│ └── InputPreprocessorMessageData `editor\src\messages\input_preprocessor\input_preprocessor_message_handler.rs` +│ └── keyboard_platform: KeyboardPlatformLayout +├── KeyMapping +│ ├── KeyMappingMessage `editor\src\messages\input_mapper\key_mapping\key_mapping_message.rs` +│ │ ├── Lookup +│ │ │ ├── InputMapperMessage `editor\src\messages\input_mapper\input_mapper_message.rs` +│ │ │ │ ├── KeyDown +│ │ │ │ ├── KeyUp +│ │ │ │ ├── KeyDownNoRepeat +│ │ │ │ ├── KeyUpNoRepeat +│ │ │ │ ├── DoubleClick +│ │ │ │ ├── PointerMove +│ │ │ │ └── WheelScroll +│ │ │ ├── InputMapperMessageHandler `editor\src\messages\input_mapper\input_mapper_message_handler.rs` +│ │ │ │ └── mapping: Mapping +│ │ │ └── InputMapperMessageData `editor\src\messages\input_mapper\input_mapper_message_handler.rs` +│ │ │ ├── input: &'a InputPreprocessorMessageHandler +│ │ │ └── actions: ActionList +│ │ └── ModifyMapping +│ ├── KeyMappingMessageHandler `editor\src\messages\input_mapper\key_mapping\key_mapping_message_handler.rs` +│ │ └── mapping_handler: InputMapperMessageHandler +│ └── KeyMappingMessageData `editor\src\messages\input_mapper\key_mapping\key_mapping_message_handler.rs` +│ ├── input: &'a InputPreprocessorMessageHandler +│ └── actions: ActionList +├── Layout +│ ├── LayoutMessage `editor\src\messages\layout\layout_message.rs` +│ │ ├── ResendActiveWidget +│ │ ├── SendLayout +│ │ ├── WidgetValueCommit +│ │ └── WidgetValueUpdate +│ ├── LayoutMessageHandler `editor\src\messages\layout\layout_message_handler.rs` +│ │ └── layouts: [Layout; LayoutTarget::LayoutTargetLength as usize] +│ └── Function `editor\src\messages\layout\layout_message_handler.rs` +│ └── Fn(&MessageDiscriminant) -> Vec +├── Portfolio +│ ├── PortfolioMessage `editor\src\messages\portfolio\portfolio_message.rs` +│ │ ├── MenuBar +│ │ │ ├── MenuBarMessage `editor\src\messages\portfolio\menu_bar\menu_bar_message.rs` +│ │ │ │ └── SendLayout +│ │ │ └── MenuBarMessageHandler `editor\src\messages\portfolio\menu_bar\menu_bar_message_handler.rs` +│ │ │ ├── has_active_document: bool +│ │ │ ├── canvas_tilted: bool +│ │ │ ├── canvas_flipped: bool +│ │ │ ├── rulers_visible: bool +│ │ │ ├── node_graph_open: bool +│ │ │ ├── has_selected_nodes: bool +│ │ │ ├── has_selected_layers: bool +│ │ │ ├── has_selection_history: (bool, bool) +│ │ │ ├── spreadsheet_view_open: bool +│ │ │ ├── message_logging_verbosity: MessageLoggingVerbosity +│ │ │ └── reset_node_definitions_on_open: bool +│ │ ├── Document +│ │ │ ├── DocumentMessage `editor\src\messages\portfolio\document\document_message.rs` +│ │ │ │ ├── Noop +│ │ │ │ ├── GraphOperation +│ │ │ │ │ ├── GraphOperationMessage `editor\src\messages\portfolio\document\graph_operation\graph_operation_message.rs` +│ │ │ │ │ │ ├── FillSet +│ │ │ │ │ │ ├── OpacitySet +│ │ │ │ │ │ ├── BlendModeSet +│ │ │ │ │ │ ├── StrokeSet +│ │ │ │ │ │ ├── TransformChange +│ │ │ │ │ │ ├── TransformSet +│ │ │ │ │ │ ├── TransformSetPivot +│ │ │ │ │ │ ├── Vector +│ │ │ │ │ │ ├── Brush +│ │ │ │ │ │ ├── SetUpstreamToChain +│ │ │ │ │ │ ├── NewArtboard +│ │ │ │ │ │ ├── NewBitmapLayer +│ │ │ │ │ │ ├── NewBooleanOperationLayer +│ │ │ │ │ │ ├── NewCustomLayer +│ │ │ │ │ │ ├── NewVectorLayer +│ │ │ │ │ │ ├── NewTextLayer +│ │ │ │ │ │ ├── ResizeArtboard +│ │ │ │ │ │ ├── RemoveArtboards +│ │ │ │ │ │ └── NewSvg +│ │ │ │ │ └── GraphOperationMessageData `editor\src\messages\portfolio\document\graph_operation\graph_operation_message_handler.rs` +│ │ │ │ │ ├── network_interface: &'a mut NodeNetworkInterface +│ │ │ │ │ ├── collapsed: &'a mut CollapsedLayers +│ │ │ │ │ └── node_graph: &'a mut NodeGraphMessageHandler +│ │ │ │ ├── Navigation +│ │ │ │ │ ├── NavigationMessage `editor\src\messages\portfolio\document\navigation\navigation_message.rs` +│ │ │ │ │ │ ├── BeginCanvasPan +│ │ │ │ │ │ ├── BeginCanvasTilt +│ │ │ │ │ │ ├── BeginCanvasZoom +│ │ │ │ │ │ ├── CanvasPan +│ │ │ │ │ │ ├── CanvasPanAbortPrepare +│ │ │ │ │ │ ├── CanvasPanAbort +│ │ │ │ │ │ ├── CanvasPanByViewportFraction +│ │ │ │ │ │ ├── CanvasPanMouseWheel +│ │ │ │ │ │ ├── CanvasTiltResetAndZoomTo100Percent +│ │ │ │ │ │ ├── CanvasTiltSet +│ │ │ │ │ │ ├── CanvasZoomDecrease +│ │ │ │ │ │ ├── CanvasZoomIncrease +│ │ │ │ │ │ ├── CanvasZoomMouseWheel +│ │ │ │ │ │ ├── CanvasZoomSet +│ │ │ │ │ │ ├── CanvasFlip +│ │ │ │ │ │ ├── EndCanvasPTZ +│ │ │ │ │ │ ├── EndCanvasPTZWithClick +│ │ │ │ │ │ ├── FitViewportToBounds +│ │ │ │ │ │ ├── FitViewportToSelection +│ │ │ │ │ │ └── PointerMove +│ │ │ │ │ ├── NavigationMessageHandler `editor\src\messages\portfolio\document\navigation\navigation_message_handler.rs` +│ │ │ │ │ │ ├── navigation_operation: NavigationOperation +│ │ │ │ │ │ ├── mouse_position: ViewportPosition +│ │ │ │ │ │ ├── finish_operation_with_click: bool +│ │ │ │ │ │ └── abortable_pan_start: Option +│ │ │ │ │ └── NavigationMessageData `editor\src\messages\portfolio\document\navigation\navigation_message_handler.rs` +│ │ │ │ │ ├── network_interface: &'a mut NodeNetworkInterface +│ │ │ │ │ ├── breadcrumb_network_path: &'a [NodeId] +│ │ │ │ │ ├── ipp: &'a InputPreprocessorMessageHandler +│ │ │ │ │ ├── selection_bounds: Option<[DVec2; 2]> +│ │ │ │ │ ├── document_ptz: &'a mut PTZ +│ │ │ │ │ ├── graph_view_overlay_open: bool +│ │ │ │ │ └── preferences: &'a PreferencesMessageHandler +│ │ │ │ ├── NodeGraph +│ │ │ │ │ ├── NodeGraphMessage `editor\src\messages\portfolio\document\node_graph\node_graph_message.rs` +│ │ │ │ │ │ ├── AddNodes +│ │ │ │ │ │ ├── AddImport +│ │ │ │ │ │ ├── AddExport +│ │ │ │ │ │ ├── Init +│ │ │ │ │ │ ├── SelectedNodesUpdated +│ │ │ │ │ │ ├── Copy +│ │ │ │ │ │ ├── CreateNodeInLayerNoTransaction +│ │ │ │ │ │ ├── CreateNodeInLayerWithTransaction +│ │ │ │ │ │ ├── CreateNodeFromContextMenu +│ │ │ │ │ │ ├── CreateWire +│ │ │ │ │ │ ├── ConnectUpstreamOutputToInput +│ │ │ │ │ │ ├── Cut +│ │ │ │ │ │ ├── DeleteNodes +│ │ │ │ │ │ ├── DeleteSelectedNodes +│ │ │ │ │ │ ├── DisconnectInput +│ │ │ │ │ │ ├── DisconnectRootNode +│ │ │ │ │ │ ├── EnterNestedNetwork +│ │ │ │ │ │ ├── DuplicateSelectedNodes +│ │ │ │ │ │ ├── ExposeInput +│ │ │ │ │ │ ├── InsertNode +│ │ │ │ │ │ ├── InsertNodeBetween +│ │ │ │ │ │ ├── MergeSelectedNodes +│ │ │ │ │ │ ├── MoveLayerToStack +│ │ │ │ │ │ ├── MoveNodeToChainStart +│ │ │ │ │ │ ├── PasteNodes +│ │ │ │ │ │ ├── PointerDown +│ │ │ │ │ │ ├── PointerMove +│ │ │ │ │ │ ├── PointerUp +│ │ │ │ │ │ ├── PointerOutsideViewport +│ │ │ │ │ │ ├── RemoveImport +│ │ │ │ │ │ ├── RemoveExport +│ │ │ │ │ │ ├── ReorderImport +│ │ │ │ │ │ ├── ReorderExport +│ │ │ │ │ │ ├── RunDocumentGraph +│ │ │ │ │ │ ├── ForceRunDocumentGraph +│ │ │ │ │ │ ├── SelectedNodesAdd +│ │ │ │ │ │ ├── SelectedNodesRemove +│ │ │ │ │ │ ├── SelectedNodesSet +│ │ │ │ │ │ ├── SendClickTargets +│ │ │ │ │ │ ├── EndSendClickTargets +│ │ │ │ │ │ ├── SendGraph +│ │ │ │ │ │ ├── SetGridAlignedEdges +│ │ │ │ │ │ ├── SetInputValue +│ │ │ │ │ │ ├── SetInput +│ │ │ │ │ │ ├── SetDisplayName +│ │ │ │ │ │ ├── SetDisplayNameImpl +│ │ │ │ │ │ ├── SetToNodeOrLayer +│ │ │ │ │ │ ├── ShiftNodePosition +│ │ │ │ │ │ ├── ShiftSelectedNodes +│ │ │ │ │ │ ├── ShiftSelectedNodesByAmount +│ │ │ │ │ │ ├── TogglePreview +│ │ │ │ │ │ ├── TogglePreviewImpl +│ │ │ │ │ │ ├── SetImportExportName +│ │ │ │ │ │ ├── SetImportExportNameImpl +│ │ │ │ │ │ ├── ToggleSelectedAsLayersOrNodes +│ │ │ │ │ │ ├── ToggleSelectedLocked +│ │ │ │ │ │ ├── ToggleLocked +│ │ │ │ │ │ ├── SetLocked +│ │ │ │ │ │ ├── ToggleSelectedIsPinned +│ │ │ │ │ │ ├── ToggleSelectedVisibility +│ │ │ │ │ │ ├── ToggleVisibility +│ │ │ │ │ │ ├── SetPinned +│ │ │ │ │ │ ├── SetVisibility +│ │ │ │ │ │ ├── SetLockedOrVisibilitySideEffects +│ │ │ │ │ │ ├── UpdateEdges +│ │ │ │ │ │ ├── UpdateBoxSelection +│ │ │ │ │ │ ├── UpdateImportsExports +│ │ │ │ │ │ ├── UpdateLayerPanel +│ │ │ │ │ │ ├── UpdateNewNodeGraph +│ │ │ │ │ │ ├── UpdateTypes +│ │ │ │ │ │ ├── UpdateActionButtons +│ │ │ │ │ │ ├── UpdateGraphBarRight +│ │ │ │ │ │ ├── UpdateInSelectedNetwork +│ │ │ │ │ │ ├── UpdateHints +│ │ │ │ │ │ └── SendSelectedNodes +│ │ │ │ │ ├── NodeGraphMessageHandler `editor\src\messages\portfolio\document\node_graph\node_graph_message_handler.rs` +│ │ │ │ │ │ ├── network: Vec +│ │ │ │ │ │ ├── node_graph_errors: GraphErrors +│ │ │ │ │ │ ├── has_selection: bool +│ │ │ │ │ │ ├── widgets: [LayoutGroup; 2] +│ │ │ │ │ │ ├── begin_dragging: bool +│ │ │ │ │ │ ├── node_has_moved_in_drag: bool +│ │ │ │ │ │ ├── drag_start: Option<(DragStart, bool)> +│ │ │ │ │ │ ├── box_selection_start: Option<(DVec2, bool)> +│ │ │ │ │ │ ├── selection_before_pointer_down: Vec +│ │ │ │ │ │ ├── shift_without_push: bool +│ │ │ │ │ │ ├── disconnecting: Option +│ │ │ │ │ │ ├── initial_disconnecting: bool +│ │ │ │ │ │ ├── select_if_not_dragged: Option +│ │ │ │ │ │ ├── wire_in_progress_from_connector: Option +│ │ │ │ │ │ ├── wire_in_progress_to_connector: Option +│ │ │ │ │ │ ├── context_menu: Option +│ │ │ │ │ │ ├── deselect_on_pointer_up: Option +│ │ │ │ │ │ ├── auto_panning: AutoPanning +│ │ │ │ │ │ ├── preview_on_mouse_up: Option +│ │ │ │ │ │ ├── reordering_import: Option +│ │ │ │ │ │ ├── reordering_export: Option +│ │ │ │ │ │ └── end_index: Option +│ │ │ │ │ └── NodeGraphHandlerData `editor\src\messages\portfolio\document\node_graph\node_graph_message_handler.rs` +│ │ │ │ │ ├── network_interface: &'a mut NodeNetworkInterface +│ │ │ │ │ ├── selection_network_path: &'a [NodeId] +│ │ │ │ │ ├── breadcrumb_network_path: &'a [NodeId] +│ │ │ │ │ ├── document_id: DocumentId +│ │ │ │ │ ├── collapsed: &'a mut CollapsedLayers +│ │ │ │ │ ├── ipp: &'a InputPreprocessorMessageHandler +│ │ │ │ │ ├── graph_view_overlay_open: bool +│ │ │ │ │ ├── graph_fade_artwork_percentage: f64 +│ │ │ │ │ ├── navigation_handler: &'a NavigationMessageHandler +│ │ │ │ │ └── preferences: &'a PreferencesMessageHandler +│ │ │ │ ├── Overlays +│ │ │ │ │ ├── OverlaysMessage `editor\src\messages\portfolio\document\overlays\overlays_message.rs` +│ │ │ │ │ │ ├── Draw +│ │ │ │ │ │ ├── AddProvider +│ │ │ │ │ │ └── RemoveProvider +│ │ │ │ │ ├── OverlaysMessageHandler `editor\src\messages\portfolio\document\overlays\overlays_message_handler.rs` +│ │ │ │ │ │ └── overlay_providers: HashSet +│ │ │ │ │ └── OverlaysMessageData `editor\src\messages\portfolio\document\overlays\overlays_message_handler.rs` +│ │ │ │ │ ├── visibility_settings: OverlaysVisibilitySettings +│ │ │ │ │ ├── ipp: &'a InputPreprocessorMessageHandler +│ │ │ │ │ └── device_pixel_ratio: f64 +│ │ │ │ ├── PropertiesPanel +│ │ │ │ │ └── PropertiesPanelMessage `editor\src\messages\portfolio\document\properties_panel\properties_panel_message.rs` +│ │ │ │ │ ├── Clear +│ │ │ │ │ └── Refresh +│ │ │ │ ├── AlignSelectedLayers +│ │ │ │ ├── RemoveArtboards +│ │ │ │ ├── ClearLayersPanel +│ │ │ │ ├── CreateEmptyFolder +│ │ │ │ ├── DeleteNode +│ │ │ │ ├── DeleteSelectedLayers +│ │ │ │ ├── DeselectAllLayers +│ │ │ │ ├── DocumentHistoryBackward +│ │ │ │ ├── DocumentHistoryForward +│ │ │ │ ├── DocumentStructureChanged +│ │ │ │ ├── DrawArtboardOverlays +│ │ │ │ ├── DuplicateSelectedLayers +│ │ │ │ ├── EnterNestedNetwork +│ │ │ │ ├── Escape +│ │ │ │ ├── ExitNestedNetwork +│ │ │ │ ├── FlipSelectedLayers +│ │ │ │ ├── RotateSelectedLayers +│ │ │ │ ├── GraphViewOverlay +│ │ │ │ ├── GraphViewOverlayToggle +│ │ │ │ ├── GridOptions +│ │ │ │ ├── GridOverlays +│ │ │ │ ├── GridVisibility +│ │ │ │ ├── GroupSelectedLayers +│ │ │ │ ├── MoveSelectedLayersTo +│ │ │ │ ├── MoveSelectedLayersToGroup +│ │ │ │ ├── NudgeSelectedLayers +│ │ │ │ ├── PasteImage +│ │ │ │ ├── PasteSvg +│ │ │ │ ├── Redo +│ │ │ │ ├── RenameDocument +│ │ │ │ ├── RenderRulers +│ │ │ │ ├── RenderScrollbars +│ │ │ │ ├── SaveDocument +│ │ │ │ ├── SelectParentLayer +│ │ │ │ ├── SelectAllLayers +│ │ │ │ ├── SelectedLayersLower +│ │ │ │ ├── SelectedLayersLowerToBack +│ │ │ │ ├── SelectedLayersRaise +│ │ │ │ ├── SelectedLayersRaiseToFront +│ │ │ │ ├── SelectedLayersReverse +│ │ │ │ ├── SelectedLayersReorder +│ │ │ │ ├── SelectLayer +│ │ │ │ ├── SetActivePanel +│ │ │ │ ├── SetBlendModeForSelectedLayers +│ │ │ │ ├── SetGraphFadeArtwork +│ │ │ │ ├── SetNodePinned +│ │ │ │ ├── SetOpacityForSelectedLayers +│ │ │ │ ├── SetOverlaysVisibility +│ │ │ │ ├── SetRangeSelectionLayer +│ │ │ │ ├── SetSnapping +│ │ │ │ ├── SetToNodeOrLayer +│ │ │ │ ├── SetViewMode +│ │ │ │ ├── AddTransaction +│ │ │ │ ├── StartTransaction +│ │ │ │ ├── EndTransaction +│ │ │ │ ├── CommitTransaction +│ │ │ │ ├── AbortTransaction +│ │ │ │ ├── RepeatedAbortTransaction +│ │ │ │ ├── ToggleLayerExpansion +│ │ │ │ ├── ToggleSelectedVisibility +│ │ │ │ ├── ToggleSelectedLocked +│ │ │ │ ├── ToggleGridVisibility +│ │ │ │ ├── ToggleOverlaysVisibility +│ │ │ │ ├── ToggleSnapping +│ │ │ │ ├── UpdateUpstreamTransforms +│ │ │ │ ├── UpdateClickTargets +│ │ │ │ ├── UpdateClipTargets +│ │ │ │ ├── Undo +│ │ │ │ ├── UngroupSelectedLayers +│ │ │ │ ├── UngroupLayer +│ │ │ │ ├── PTZUpdate +│ │ │ │ ├── SelectionStepBack +│ │ │ │ ├── SelectionStepForward +│ │ │ │ ├── WrapContentInArtboard +│ │ │ │ ├── ZoomCanvasTo100Percent +│ │ │ │ ├── ZoomCanvasTo200Percent +│ │ │ │ └── ZoomCanvasToFitAll +│ │ │ ├── DocumentMessageHandler `editor\src\messages\portfolio\document\document_message_handler.rs` +│ │ │ │ ├── navigation_handler: NavigationMessageHandler +│ │ │ │ ├── node_graph_handler: NodeGraphMessageHandler +│ │ │ │ ├── overlays_message_handler: OverlaysMessageHandler +│ │ │ │ ├── properties_panel_message_handler: PropertiesPanelMessageHandler +│ │ │ │ ├── network_interface: NodeNetworkInterface +│ │ │ │ ├── collapsed: CollapsedLayers +│ │ │ │ ├── name: String +│ │ │ │ ├── commit_hash: String +│ │ │ │ ├── document_ptz: PTZ +│ │ │ │ ├── document_mode: DocumentMode +│ │ │ │ ├── view_mode: ViewMode +│ │ │ │ ├── overlays_visibility_settings: OverlaysVisibilitySettings +│ │ │ │ ├── rulers_visible: bool +│ │ │ │ ├── snapping_state: SnappingState +│ │ │ │ ├── graph_view_overlay_open: bool +│ │ │ │ ├── graph_fade_artwork_percentage: f64 +│ │ │ │ ├── breadcrumb_network_path: Vec +│ │ │ │ ├── selection_network_path: Vec +│ │ │ │ ├── document_undo_history: VecDeque +│ │ │ │ ├── document_redo_history: VecDeque +│ │ │ │ ├── saved_hash: Option +│ │ │ │ ├── auto_saved_hash: Option +│ │ │ │ ├── layer_range_selection_reference: Option +│ │ │ │ └── is_loaded: bool +│ │ │ └── DocumentMessageData `editor\src\messages\portfolio\document\document_message_handler.rs` +│ │ │ ├── document_id: DocumentId +│ │ │ ├── ipp: &'a InputPreprocessorMessageHandler +│ │ │ ├── persistent_data: &'a PersistentData +│ │ │ ├── executor: &'a mut NodeGraphExecutor +│ │ │ ├── current_tool: &'a ToolType +│ │ │ ├── preferences: &'a PreferencesMessageHandler +│ │ │ └── device_pixel_ratio: f64 +│ │ ├── Spreadsheet +│ │ │ ├── SpreadsheetMessage `editor\src\messages\portfolio\spreadsheet\spreadsheet_message.rs` +│ │ │ │ ├── ToggleOpen +│ │ │ │ ├── UpdateLayout +│ │ │ │ ├── PushToInstancePath +│ │ │ │ ├── TruncateInstancePath +│ │ │ │ └── ViewVectorDataDomain +│ │ │ └── SpreadsheetMessageHandler `editor\src\messages\portfolio\spreadsheet\spreadsheet_message_handler.rs` +│ │ │ ├── spreadsheet_view_open: bool +│ │ │ ├── inspect_node: Option +│ │ │ ├── introspected_data: Option> +│ │ │ ├── instances_path: Vec +│ │ │ └── viewing_vector_data_domain: VectorDataDomain +│ │ ├── DocumentPassMessage +│ │ ├── AutoSaveActiveDocument +│ │ ├── AutoSaveAllDocuments +│ │ ├── AutoSaveDocument +│ │ ├── CloseActiveDocumentWithConfirmation +│ │ ├── CloseAllDocuments +│ │ ├── CloseAllDocumentsWithConfirmation +│ │ ├── CloseDocument +│ │ ├── CloseDocumentWithConfirmation +│ │ ├── Copy +│ │ ├── Cut +│ │ ├── DeleteDocument +│ │ ├── DestroyAllDocuments +│ │ ├── EditorPreferences +│ │ ├── FontLoaded +│ │ ├── Import +│ │ ├── LoadDocumentResources +│ │ ├── LoadFont +│ │ ├── NewDocumentWithName +│ │ ├── NextDocument +│ │ ├── OpenDocument +│ │ ├── OpenDocumentFile +│ │ ├── ToggleResetNodesToDefinitionsOnOpen +│ │ ├── OpenDocumentFileWithId +│ │ ├── PasteIntoFolder +│ │ ├── PasteSerializedData +│ │ ├── PasteImage +│ │ ├── PasteSvg +│ │ ├── PrevDocument +│ │ ├── SetActivePanel +│ │ ├── SetDevicePixelRatio +│ │ ├── SelectDocument +│ │ ├── SubmitDocumentExport +│ │ ├── SubmitActiveGraphRender +│ │ ├── SubmitGraphRender +│ │ ├── ToggleRulers +│ │ ├── UpdateDocumentWidgets +│ │ ├── UpdateOpenDocumentsList +│ │ └── UpdateVelloPreference +│ ├── PortfolioMessageHandler `editor\src\messages\portfolio\portfolio_message_handler.rs` +│ │ ├── menu_bar_message_handler: MenuBarMessageHandler +│ │ ├── documents: HashMap +│ │ ├── document_ids: VecDeque +│ │ ├── active_panel: PanelType +│ │ ├── active_document_id: Option +│ │ ├── copy_buffer: [Vec; INTERNAL_CLIPBOARD_COUNT as usize] +│ │ ├── persistent_data: PersistentData +│ │ ├── executor: NodeGraphExecutor +│ │ ├── selection_mode: SelectionMode +│ │ ├── spreadsheet: SpreadsheetMessageHandler +│ │ ├── device_pixel_ratio: Option +│ │ └── reset_node_definitions_on_open: bool +│ └── PortfolioMessageData `editor\src\messages\portfolio\portfolio_message_handler.rs` +│ ├── ipp: &'a InputPreprocessorMessageHandler +│ ├── preferences: &'a PreferencesMessageHandler +│ ├── current_tool: &'a ToolType +│ ├── message_logging_verbosity: MessageLoggingVerbosity +│ ├── reset_node_definitions_on_open: bool +│ ├── timing_information: TimingInformation +│ └── animation: &'a AnimationMessageHandler +├── Preferences +│ ├── PreferencesMessage `editor\src\messages\preferences\preferences_message.rs` +│ │ ├── Load +│ │ ├── ResetToDefaults +│ │ ├── UseVello +│ │ ├── SelectionMode +│ │ ├── VectorMeshes +│ │ ├── ModifyLayout +│ │ ├── GraphWireStyle +│ │ └── ViewportZoomWheelRate +│ └── PreferencesMessageHandler `editor\src\messages\preferences\preferences_message_handler.rs` +│ ├── selection_mode: SelectionMode +│ ├── zoom_with_scroll: bool +│ ├── use_vello: bool +│ ├── vector_meshes: bool +│ ├── graph_wire_style: GraphWireStyle +│ └── viewport_zoom_wheel_rate: f64 +├── Tool +│ ├── ToolMessage `editor\src\messages\tool\tool_message.rs` +│ │ ├── TransformLayer +│ │ │ ├── TransformLayerMessage `editor\src\messages\tool\transform_layer\transform_layer_message.rs` +│ │ │ │ ├── Overlays +│ │ │ │ ├── ApplyTransformOperation +│ │ │ │ ├── BeginGrab +│ │ │ │ ├── BeginRotate +│ │ │ │ ├── BeginScale +│ │ │ │ ├── BeginGRS +│ │ │ │ ├── BeginGrabPen +│ │ │ │ ├── BeginRotatePen +│ │ │ │ ├── BeginScalePen +│ │ │ │ ├── CancelTransformOperation +│ │ │ │ ├── ConstrainX +│ │ │ │ ├── ConstrainY +│ │ │ │ ├── PointerMove +│ │ │ │ ├── SelectionChanged +│ │ │ │ ├── TypeBackspace +│ │ │ │ ├── TypeDecimalPoint +│ │ │ │ ├── TypeDigit +│ │ │ │ └── TypeNegate +│ │ │ ├── TransformLayerMessageHandler `editor\src\messages\tool\transform_layer\transform_layer_message_handler.rs` +│ │ │ │ ├── transform_operation: TransformOperation +│ │ │ │ ├── slow: bool +│ │ │ │ ├── increments: bool +│ │ │ │ ├── local: bool +│ │ │ │ ├── layer_bounding_box: Quad +│ │ │ │ ├── typing: Typing +│ │ │ │ ├── mouse_position: ViewportPosition +│ │ │ │ ├── start_mouse: ViewportPosition +│ │ │ │ ├── original_transforms: OriginalTransforms +│ │ │ │ ├── pivot: ViewportPosition +│ │ │ │ ├── local_pivot: DocumentPosition +│ │ │ │ ├── local_mouse_start: DocumentPosition +│ │ │ │ ├── grab_target: DocumentPosition +│ │ │ │ ├── ptz: PTZ +│ │ │ │ ├── initial_transform: DAffine2 +│ │ │ │ ├── operation_count: usize +│ │ │ │ ├── handle: DVec2 +│ │ │ │ ├── last_point: DVec2 +│ │ │ │ └── grs_pen_handle: bool +│ │ │ └── TransformData<'a> `editor\src\messages\tool\transform_layer\transform_layer_message_handler.rs` +│ │ │ ├── &'a DocumentMessageHandler +│ │ │ ├── &'a InputPreprocessorMessageHandler +│ │ │ ├── &'a ToolData +│ │ │ └── &'a mut ShapeState +│ │ ├── Select +│ │ │ ├── SelectToolMessage `editor\src\messages\tool\tool_messages\select_tool.rs` +│ │ │ │ ├── Abort +│ │ │ │ ├── Overlays +│ │ │ │ ├── DragStart +│ │ │ │ ├── DragStop +│ │ │ │ ├── EditLayer +│ │ │ │ ├── Enter +│ │ │ │ ├── PointerMove +│ │ │ │ ├── PointerOutsideViewport +│ │ │ │ ├── SelectOptions +│ │ │ │ └── SetPivot +│ │ │ ├── SelectTool `editor\src\messages\tool\tool_messages\select_tool.rs` +│ │ │ │ ├── fsm_state: SelectToolFsmState +│ │ │ │ └── tool_data: SelectToolData +│ │ │ └── &mut ToolActionHandlerData<'a> `editor\src\messages\tool\utility_types.rs` +│ │ │ ├── document: &'a mut DocumentMessageHandler +│ │ │ ├── document_id: DocumentId +│ │ │ ├── global_tool_data: &'a DocumentToolData +│ │ │ ├── input: &'a InputPreprocessorMessageHandler +│ │ │ ├── font_cache: &'a FontCache +│ │ │ ├── shape_editor: &'a mut ShapeState +│ │ │ ├── node_graph: &'a NodeGraphExecutor +│ │ │ └── preferences: &'a PreferencesMessageHandler +│ │ ├── Artboard +│ │ │ ├── ArtboardToolMessage `editor\src\messages\tool\tool_messages\artboard_tool.rs` +│ │ │ │ ├── Abort +│ │ │ │ ├── Overlays +│ │ │ │ ├── UpdateSelectedArtboard +│ │ │ │ ├── DeleteSelected +│ │ │ │ ├── NudgeSelected +│ │ │ │ ├── PointerDown +│ │ │ │ ├── PointerMove +│ │ │ │ ├── PointerOutsideViewport +│ │ │ │ └── PointerUp +│ │ │ ├── ArtboardTool `editor\src\messages\tool\tool_messages\artboard_tool.rs` +│ │ │ │ ├── fsm_state: ArtboardToolFsmState +│ │ │ │ └── data: ArtboardToolData +│ │ │ └── &mut ToolActionHandlerData<'a> `editor\src\messages\tool\utility_types.rs` +│ │ │ ├── document: &'a mut DocumentMessageHandler +│ │ │ ├── document_id: DocumentId +│ │ │ ├── global_tool_data: &'a DocumentToolData +│ │ │ ├── input: &'a InputPreprocessorMessageHandler +│ │ │ ├── font_cache: &'a FontCache +│ │ │ ├── shape_editor: &'a mut ShapeState +│ │ │ ├── node_graph: &'a NodeGraphExecutor +│ │ │ └── preferences: &'a PreferencesMessageHandler +│ │ ├── Navigate +│ │ │ ├── NavigateToolMessage `editor\src\messages\tool\tool_messages\navigate_tool.rs` +│ │ │ │ ├── Abort +│ │ │ │ ├── PointerUp +│ │ │ │ ├── PointerMove +│ │ │ │ ├── TiltCanvasBegin +│ │ │ │ ├── ZoomCanvasBegin +│ │ │ │ └── End +│ │ │ ├── NavigateTool `editor\src\messages\tool\tool_messages\navigate_tool.rs` +│ │ │ │ ├── fsm_state: NavigateToolFsmState +│ │ │ │ └── tool_data: NavigateToolData +│ │ │ └── &mut ToolActionHandlerData<'a> `editor\src\messages\tool\utility_types.rs` +│ │ │ ├── document: &'a mut DocumentMessageHandler +│ │ │ ├── document_id: DocumentId +│ │ │ ├── global_tool_data: &'a DocumentToolData +│ │ │ ├── input: &'a InputPreprocessorMessageHandler +│ │ │ ├── font_cache: &'a FontCache +│ │ │ ├── shape_editor: &'a mut ShapeState +│ │ │ ├── node_graph: &'a NodeGraphExecutor +│ │ │ └── preferences: &'a PreferencesMessageHandler +│ │ ├── Eyedropper +│ │ │ ├── EyedropperToolMessage `editor\src\messages\tool\tool_messages\eyedropper_tool.rs` +│ │ │ │ ├── Abort +│ │ │ │ ├── SamplePrimaryColorBegin +│ │ │ │ ├── SamplePrimaryColorEnd +│ │ │ │ ├── PointerMove +│ │ │ │ ├── SampleSecondaryColorBegin +│ │ │ │ └── SampleSecondaryColorEnd +│ │ │ ├── EyedropperTool `editor\src\messages\tool\tool_messages\eyedropper_tool.rs` +│ │ │ │ ├── fsm_state: EyedropperToolFsmState +│ │ │ │ └── data: EyedropperToolData +│ │ │ └── &mut ToolActionHandlerData<'a> `editor\src\messages\tool\utility_types.rs` +│ │ │ ├── document: &'a mut DocumentMessageHandler +│ │ │ ├── document_id: DocumentId +│ │ │ ├── global_tool_data: &'a DocumentToolData +│ │ │ ├── input: &'a InputPreprocessorMessageHandler +│ │ │ ├── font_cache: &'a FontCache +│ │ │ ├── shape_editor: &'a mut ShapeState +│ │ │ ├── node_graph: &'a NodeGraphExecutor +│ │ │ └── preferences: &'a PreferencesMessageHandler +│ │ ├── Fill +│ │ │ ├── FillToolMessage `editor\src\messages\tool\tool_messages\fill_tool.rs` +│ │ │ │ ├── Abort +│ │ │ │ ├── WorkingColorChanged +│ │ │ │ ├── Overlays +│ │ │ │ ├── PointerMove +│ │ │ │ ├── PointerUp +│ │ │ │ ├── FillPrimaryColor +│ │ │ │ └── FillSecondaryColor +│ │ │ ├── FillTool `editor\src\messages\tool\tool_messages\fill_tool.rs` +│ │ │ │ └── fsm_state: FillToolFsmState +│ │ │ └── &mut ToolActionHandlerData<'a> `editor\src\messages\tool\utility_types.rs` +│ │ │ ├── document: &'a mut DocumentMessageHandler +│ │ │ ├── document_id: DocumentId +│ │ │ ├── global_tool_data: &'a DocumentToolData +│ │ │ ├── input: &'a InputPreprocessorMessageHandler +│ │ │ ├── font_cache: &'a FontCache +│ │ │ ├── shape_editor: &'a mut ShapeState +│ │ │ ├── node_graph: &'a NodeGraphExecutor +│ │ │ └── preferences: &'a PreferencesMessageHandler +│ │ ├── Gradient +│ │ │ ├── GradientToolMessage `editor\src\messages\tool\tool_messages\gradient_tool.rs` +│ │ │ │ ├── Abort +│ │ │ │ ├── Overlays +│ │ │ │ ├── DeleteStop +│ │ │ │ ├── InsertStop +│ │ │ │ ├── PointerDown +│ │ │ │ ├── PointerMove +│ │ │ │ ├── PointerOutsideViewport +│ │ │ │ ├── PointerUp +│ │ │ │ └── UpdateOptions +│ │ │ ├── GradientTool `editor\src\messages\tool\tool_messages\gradient_tool.rs` +│ │ │ │ ├── fsm_state: GradientToolFsmState +│ │ │ │ ├── data: GradientToolData +│ │ │ │ └── options: GradientOptions +│ │ │ └── &mut ToolActionHandlerData<'a> `editor\src\messages\tool\utility_types.rs` +│ │ │ ├── document: &'a mut DocumentMessageHandler +│ │ │ ├── document_id: DocumentId +│ │ │ ├── global_tool_data: &'a DocumentToolData +│ │ │ ├── input: &'a InputPreprocessorMessageHandler +│ │ │ ├── font_cache: &'a FontCache +│ │ │ ├── shape_editor: &'a mut ShapeState +│ │ │ ├── node_graph: &'a NodeGraphExecutor +│ │ │ └── preferences: &'a PreferencesMessageHandler +│ │ ├── Path +│ │ │ ├── PathToolMessage `editor\src\messages\tool\tool_messages\path_tool.rs` +│ │ │ │ ├── Abort +│ │ │ │ ├── Overlays +│ │ │ │ ├── SelectionChanged +│ │ │ │ ├── BreakPath +│ │ │ │ ├── DeselectAllPoints +│ │ │ │ ├── Delete +│ │ │ │ ├── DeleteAndBreakPath +│ │ │ │ ├── DragStop +│ │ │ │ ├── Enter +│ │ │ │ ├── Escape +│ │ │ │ ├── ClosePath +│ │ │ │ ├── FlipSmoothSharp +│ │ │ │ ├── GRS +│ │ │ │ ├── ManipulatorMakeHandlesFree +│ │ │ │ ├── ManipulatorMakeHandlesColinear +│ │ │ │ ├── MouseDown +│ │ │ │ ├── NudgeSelectedPoints +│ │ │ │ ├── PointerMove +│ │ │ │ ├── PointerOutsideViewport +│ │ │ │ ├── RightClick +│ │ │ │ ├── SelectAllAnchors +│ │ │ │ ├── SelectedPointUpdated +│ │ │ │ ├── SelectedPointXChanged +│ │ │ │ ├── SelectedPointYChanged +│ │ │ │ ├── SwapSelectedHandles +│ │ │ │ ├── UpdateOptions +│ │ │ │ └── UpdateSelectedPointsStatus +│ │ │ ├── PathTool `editor\src\messages\tool\tool_messages\path_tool.rs` +│ │ │ │ ├── fsm_state: PathToolFsmState +│ │ │ │ ├── tool_data: PathToolData +│ │ │ │ └── options: PathToolOptions +│ │ │ └── &mut ToolActionHandlerData<'a> `editor\src\messages\tool\utility_types.rs` +│ │ │ ├── document: &'a mut DocumentMessageHandler +│ │ │ ├── document_id: DocumentId +│ │ │ ├── global_tool_data: &'a DocumentToolData +│ │ │ ├── input: &'a InputPreprocessorMessageHandler +│ │ │ ├── font_cache: &'a FontCache +│ │ │ ├── shape_editor: &'a mut ShapeState +│ │ │ ├── node_graph: &'a NodeGraphExecutor +│ │ │ └── preferences: &'a PreferencesMessageHandler +│ │ ├── Pen +│ │ │ ├── PenToolMessage `editor\src\messages\tool\tool_messages\pen_tool.rs` +│ │ │ │ ├── Abort +│ │ │ │ ├── SelectionChanged +│ │ │ │ ├── WorkingColorChanged +│ │ │ │ ├── Overlays +│ │ │ │ ├── AddPointLayerPosition +│ │ │ │ ├── Confirm +│ │ │ │ ├── DragStart +│ │ │ │ ├── DragStop +│ │ │ │ ├── PointerMove +│ │ │ │ ├── PointerOutsideViewport +│ │ │ │ ├── Redo +│ │ │ │ ├── Undo +│ │ │ │ ├── UpdateOptions +│ │ │ │ ├── RecalculateLatestPointsPosition +│ │ │ │ ├── RemovePreviousHandle +│ │ │ │ ├── GRS +│ │ │ │ ├── FinalPosition +│ │ │ │ └── SwapHandles +│ │ │ ├── PenTool `editor\src\messages\tool\tool_messages\pen_tool.rs` +│ │ │ │ ├── fsm_state: PenToolFsmState +│ │ │ │ ├── tool_data: PenToolData +│ │ │ │ └── options: PenOptions +│ │ │ └── &mut ToolActionHandlerData<'a> `editor\src\messages\tool\utility_types.rs` +│ │ │ ├── document: &'a mut DocumentMessageHandler +│ │ │ ├── document_id: DocumentId +│ │ │ ├── global_tool_data: &'a DocumentToolData +│ │ │ ├── input: &'a InputPreprocessorMessageHandler +│ │ │ ├── font_cache: &'a FontCache +│ │ │ ├── shape_editor: &'a mut ShapeState +│ │ │ ├── node_graph: &'a NodeGraphExecutor +│ │ │ └── preferences: &'a PreferencesMessageHandler +│ │ ├── Freehand +│ │ │ ├── FreehandToolMessage `editor\src\messages\tool\tool_messages\freehand_tool.rs` +│ │ │ │ ├── Overlays +│ │ │ │ ├── Abort +│ │ │ │ ├── WorkingColorChanged +│ │ │ │ ├── DragStart +│ │ │ │ ├── DragStop +│ │ │ │ ├── PointerMove +│ │ │ │ └── UpdateOptions +│ │ │ ├── FreehandTool `editor\src\messages\tool\tool_messages\freehand_tool.rs` +│ │ │ │ ├── fsm_state: FreehandToolFsmState +│ │ │ │ ├── data: FreehandToolData +│ │ │ │ └── options: FreehandOptions +│ │ │ └── &mut ToolActionHandlerData<'a> `editor\src\messages\tool\utility_types.rs` +│ │ │ ├── document: &'a mut DocumentMessageHandler +│ │ │ ├── document_id: DocumentId +│ │ │ ├── global_tool_data: &'a DocumentToolData +│ │ │ ├── input: &'a InputPreprocessorMessageHandler +│ │ │ ├── font_cache: &'a FontCache +│ │ │ ├── shape_editor: &'a mut ShapeState +│ │ │ ├── node_graph: &'a NodeGraphExecutor +│ │ │ └── preferences: &'a PreferencesMessageHandler +│ │ ├── Spline +│ │ │ ├── SplineToolMessage `editor\src\messages\tool\tool_messages\spline_tool.rs` +│ │ │ │ ├── Overlays +│ │ │ │ ├── CanvasTransformed +│ │ │ │ ├── Abort +│ │ │ │ ├── WorkingColorChanged +│ │ │ │ ├── Confirm +│ │ │ │ ├── DragStart +│ │ │ │ ├── DragStop +│ │ │ │ ├── MergeEndpoints +│ │ │ │ ├── PointerMove +│ │ │ │ ├── PointerOutsideViewport +│ │ │ │ ├── Undo +│ │ │ │ └── UpdateOptions +│ │ │ ├── SplineTool `editor\src\messages\tool\tool_messages\spline_tool.rs` +│ │ │ │ ├── fsm_state: SplineToolFsmState +│ │ │ │ ├── tool_data: SplineToolData +│ │ │ │ └── options: SplineOptions +│ │ │ └── &mut ToolActionHandlerData<'a> `editor\src\messages\tool\utility_types.rs` +│ │ │ ├── document: &'a mut DocumentMessageHandler +│ │ │ ├── document_id: DocumentId +│ │ │ ├── global_tool_data: &'a DocumentToolData +│ │ │ ├── input: &'a InputPreprocessorMessageHandler +│ │ │ ├── font_cache: &'a FontCache +│ │ │ ├── shape_editor: &'a mut ShapeState +│ │ │ ├── node_graph: &'a NodeGraphExecutor +│ │ │ └── preferences: &'a PreferencesMessageHandler +│ │ ├── Line +│ │ │ ├── LineToolMessage `editor\src\messages\tool\tool_messages\line_tool.rs` +│ │ │ │ ├── Overlays +│ │ │ │ ├── Abort +│ │ │ │ ├── WorkingColorChanged +│ │ │ │ ├── DragStart +│ │ │ │ ├── DragStop +│ │ │ │ ├── PointerMove +│ │ │ │ ├── PointerOutsideViewport +│ │ │ │ └── UpdateOptions +│ │ │ ├── LineTool `editor\src\messages\tool\tool_messages\line_tool.rs` +│ │ │ │ ├── fsm_state: LineToolFsmState +│ │ │ │ ├── tool_data: LineToolData +│ │ │ │ └── options: LineOptions +│ │ │ └── &mut ToolActionHandlerData<'a> `editor\src\messages\tool\utility_types.rs` +│ │ │ ├── document: &'a mut DocumentMessageHandler +│ │ │ ├── document_id: DocumentId +│ │ │ ├── global_tool_data: &'a DocumentToolData +│ │ │ ├── input: &'a InputPreprocessorMessageHandler +│ │ │ ├── font_cache: &'a FontCache +│ │ │ ├── shape_editor: &'a mut ShapeState +│ │ │ ├── node_graph: &'a NodeGraphExecutor +│ │ │ └── preferences: &'a PreferencesMessageHandler +│ │ ├── Rectangle +│ │ │ ├── RectangleToolMessage `editor\src\messages\tool\tool_messages\rectangle_tool.rs` +│ │ │ │ ├── Overlays +│ │ │ │ ├── Abort +│ │ │ │ ├── WorkingColorChanged +│ │ │ │ ├── DragStart +│ │ │ │ ├── DragStop +│ │ │ │ ├── PointerMove +│ │ │ │ ├── PointerOutsideViewport +│ │ │ │ └── UpdateOptions +│ │ │ ├── RectangleTool `editor\src\messages\tool\tool_messages\rectangle_tool.rs` +│ │ │ │ ├── fsm_state: RectangleToolFsmState +│ │ │ │ ├── tool_data: RectangleToolData +│ │ │ │ └── options: RectangleToolOptions +│ │ │ └── &mut ToolActionHandlerData<'a> `editor\src\messages\tool\utility_types.rs` +│ │ │ ├── document: &'a mut DocumentMessageHandler +│ │ │ ├── document_id: DocumentId +│ │ │ ├── global_tool_data: &'a DocumentToolData +│ │ │ ├── input: &'a InputPreprocessorMessageHandler +│ │ │ ├── font_cache: &'a FontCache +│ │ │ ├── shape_editor: &'a mut ShapeState +│ │ │ ├── node_graph: &'a NodeGraphExecutor +│ │ │ └── preferences: &'a PreferencesMessageHandler +│ │ ├── Ellipse +│ │ │ ├── EllipseToolMessage `editor\src\messages\tool\tool_messages\ellipse_tool.rs` +│ │ │ │ ├── Overlays +│ │ │ │ ├── Abort +│ │ │ │ ├── WorkingColorChanged +│ │ │ │ ├── DragStart +│ │ │ │ ├── DragStop +│ │ │ │ ├── PointerMove +│ │ │ │ ├── PointerOutsideViewport +│ │ │ │ └── UpdateOptions +│ │ │ ├── EllipseTool `editor\src\messages\tool\tool_messages\ellipse_tool.rs` +│ │ │ │ ├── fsm_state: EllipseToolFsmState +│ │ │ │ ├── data: EllipseToolData +│ │ │ │ └── options: EllipseToolOptions +│ │ │ └── &mut ToolActionHandlerData<'a> `editor\src\messages\tool\utility_types.rs` +│ │ │ ├── document: &'a mut DocumentMessageHandler +│ │ │ ├── document_id: DocumentId +│ │ │ ├── global_tool_data: &'a DocumentToolData +│ │ │ ├── input: &'a InputPreprocessorMessageHandler +│ │ │ ├── font_cache: &'a FontCache +│ │ │ ├── shape_editor: &'a mut ShapeState +│ │ │ ├── node_graph: &'a NodeGraphExecutor +│ │ │ └── preferences: &'a PreferencesMessageHandler +│ │ ├── Polygon +│ │ │ ├── PolygonToolMessage `editor\src\messages\tool\tool_messages\polygon_tool.rs` +│ │ │ │ ├── Overlays +│ │ │ │ ├── Abort +│ │ │ │ ├── WorkingColorChanged +│ │ │ │ ├── DragStart +│ │ │ │ ├── DragStop +│ │ │ │ ├── PointerMove +│ │ │ │ ├── PointerOutsideViewport +│ │ │ │ └── UpdateOptions +│ │ │ ├── PolygonTool `editor\src\messages\tool\tool_messages\polygon_tool.rs` +│ │ │ │ ├── fsm_state: PolygonToolFsmState +│ │ │ │ ├── tool_data: PolygonToolData +│ │ │ │ └── options: PolygonOptions +│ │ │ └── &mut ToolActionHandlerData<'a> `editor\src\messages\tool\utility_types.rs` +│ │ │ ├── document: &'a mut DocumentMessageHandler +│ │ │ ├── document_id: DocumentId +│ │ │ ├── global_tool_data: &'a DocumentToolData +│ │ │ ├── input: &'a InputPreprocessorMessageHandler +│ │ │ ├── font_cache: &'a FontCache +│ │ │ ├── shape_editor: &'a mut ShapeState +│ │ │ ├── node_graph: &'a NodeGraphExecutor +│ │ │ └── preferences: &'a PreferencesMessageHandler +│ │ ├── Text +│ │ │ ├── TextToolMessage `editor\src\messages\tool\tool_messages\text_tool.rs` +│ │ │ │ ├── Abort +│ │ │ │ ├── WorkingColorChanged +│ │ │ │ ├── Overlays +│ │ │ │ ├── DragStart +│ │ │ │ ├── DragStop +│ │ │ │ ├── EditSelected +│ │ │ │ ├── Interact +│ │ │ │ ├── PointerMove +│ │ │ │ ├── PointerOutsideViewport +│ │ │ │ ├── TextChange +│ │ │ │ ├── UpdateBounds +│ │ │ │ └── UpdateOptions +│ │ │ ├── TextTool `editor\src\messages\tool\tool_messages\text_tool.rs` +│ │ │ │ ├── fsm_state: TextToolFsmState +│ │ │ │ ├── tool_data: TextToolData +│ │ │ │ └── options: TextOptions +│ │ │ └── &mut ToolActionHandlerData<'a> `editor\src\messages\tool\utility_types.rs` +│ │ │ ├── document: &'a mut DocumentMessageHandler +│ │ │ ├── document_id: DocumentId +│ │ │ ├── global_tool_data: &'a DocumentToolData +│ │ │ ├── input: &'a InputPreprocessorMessageHandler +│ │ │ ├── font_cache: &'a FontCache +│ │ │ ├── shape_editor: &'a mut ShapeState +│ │ │ ├── node_graph: &'a NodeGraphExecutor +│ │ │ └── preferences: &'a PreferencesMessageHandler +│ │ ├── Brush +│ │ │ ├── BrushToolMessage `editor\src\messages\tool\tool_messages\brush_tool.rs` +│ │ │ │ ├── Abort +│ │ │ │ ├── WorkingColorChanged +│ │ │ │ ├── DragStart +│ │ │ │ ├── DragStop +│ │ │ │ ├── PointerMove +│ │ │ │ └── UpdateOptions +│ │ │ ├── BrushTool `editor\src\messages\tool\tool_messages\brush_tool.rs` +│ │ │ │ ├── fsm_state: BrushToolFsmState +│ │ │ │ ├── data: BrushToolData +│ │ │ │ └── options: BrushOptions +│ │ │ └── &mut ToolActionHandlerData<'a> `editor\src\messages\tool\utility_types.rs` +│ │ │ ├── document: &'a mut DocumentMessageHandler +│ │ │ ├── document_id: DocumentId +│ │ │ ├── global_tool_data: &'a DocumentToolData +│ │ │ ├── input: &'a InputPreprocessorMessageHandler +│ │ │ ├── font_cache: &'a FontCache +│ │ │ ├── shape_editor: &'a mut ShapeState +│ │ │ ├── node_graph: &'a NodeGraphExecutor +│ │ │ └── preferences: &'a PreferencesMessageHandler +│ │ ├── ActivateToolSelect +│ │ ├── ActivateToolArtboard +│ │ ├── ActivateToolNavigate +│ │ ├── ActivateToolEyedropper +│ │ ├── ActivateToolText +│ │ ├── ActivateToolFill +│ │ ├── ActivateToolGradient +│ │ ├── ActivateToolPath +│ │ ├── ActivateToolPen +│ │ ├── ActivateToolFreehand +│ │ ├── ActivateToolSpline +│ │ ├── ActivateToolLine +│ │ ├── ActivateToolRectangle +│ │ ├── ActivateToolEllipse +│ │ ├── ActivateToolPolygon +│ │ ├── ActivateToolBrush +│ │ ├── ActivateTool +│ │ ├── DeactivateTools +│ │ ├── InitTools +│ │ ├── PreUndo +│ │ ├── Redo +│ │ ├── RefreshToolOptions +│ │ ├── ResetColors +│ │ ├── SelectPrimaryColor +│ │ ├── SelectRandomPrimaryColor +│ │ ├── SelectSecondaryColor +│ │ ├── SwapColors +│ │ ├── Undo +│ │ ├── UpdateCursor +│ │ ├── UpdateHints +│ │ └── UpdateSelectionMode +│ ├── ToolMessageHandler `editor\src\messages\tool\tool_message_handler.rs` +│ │ ├── tool_state: ToolFsmState +│ │ ├── transform_layer_handler: TransformLayerMessageHandler +│ │ ├── shape_editor: ShapeState +│ │ └── tool_is_active: bool +│ └── ToolMessageData `editor\src\messages\tool\tool_message_handler.rs` +│ ├── document_id: DocumentId +│ ├── document: &'a mut DocumentMessageHandler +│ ├── input: &'a InputPreprocessorMessageHandler +│ ├── persistent_data: &'a PersistentData +│ ├── node_graph: &'a NodeGraphExecutor +│ └── preferences: &'a PreferencesMessageHandler +└── Workspace + ├── WorkspaceMessage `editor\src\messages\workspace\workspace_message.rs` + │ └── NodeGraphToggleVisibility + └── WorkspaceMessageHandler `editor\src\messages\workspace\workspace_message_handler.rs` + └── node_graph_visible: bool