Skip to content

Generate a visualization of the editor's hierarchical message system tree #2499

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 29 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
43f5323
Feat: implement the hierarchical tree for visualization
MohdMohsin97 Mar 29, 2025
f9ee826
rename HierarchicalTree trait function
MohdMohsin97 Mar 29, 2025
11e104f
Merge branch 'GraphiteEditor:master' into hierarchical-tree
MohdMohsin97 Apr 11, 2025
0afbaf5
Merge branch 'hierarchical-tree' of https://github.com/MohdMohsin97/G…
MohdMohsin97 Apr 11, 2025
0f9e491
feat: change the HierarchicalTree from String to DebugMessageTree struct
MohdMohsin97 Apr 12, 2025
d1a0294
Merge branch 'master' into hierarchical-tree
Keavon Apr 18, 2025
e232c5d
Nits
Keavon Apr 18, 2025
9fec71c
Merge branch 'GraphiteEditor:master' into hierarchical-tree
MohdMohsin97 Apr 19, 2025
9f5ad94
feat: impliment proc macro to extract field from messagedata structs
MohdMohsin97 Apr 19, 2025
9395617
Merge branch 'hierarchical-tree' of https://github.com/MohdMohsin97/G…
MohdMohsin97 Apr 19, 2025
dcfbb97
update the hierarchical-tree for hanlder data
MohdMohsin97 Apr 23, 2025
1e11239
Merge branch 'GraphiteEditor:master' into hierarchical-tree
MohdMohsin97 Apr 27, 2025
730db02
Merge branch 'GraphiteEditor:master' into hierarchical-tree
MohdMohsin97 May 1, 2025
fc9e258
feat: added message handler struct to hierarchical tree
MohdMohsin97 May 1, 2025
1af7c6e
Merge branch 'hierarchical-tree' of https://github.com/MohdMohsin97/G…
MohdMohsin97 May 1, 2025
160a9d0
Merge branch 'GraphiteEditor:master' into hierarchical-tree
MohdMohsin97 May 1, 2025
ee272e5
Merge branch 'hierarchical-tree' of https://github.com/MohdMohsin97/G…
MohdMohsin97 May 1, 2025
c2c629d
feat: add the line number to message handler struct
MohdMohsin97 May 10, 2025
c2c6ac5
feat: added handler path to tree and NITS
MohdMohsin97 May 12, 2025
6d4c29c
Merge branch 'master' into hierarchical-tree
MohdMohsin97 May 13, 2025
d034c4c
clean the white spaces in type string
MohdMohsin97 May 19, 2025
396ed0c
Merge branch 'hierarchical-tree' of https://github.com/MohdMohsin97/G…
MohdMohsin97 May 19, 2025
0a9741f
Merge branch 'master' into hierarchical-tree
Keavon May 19, 2025
4ee1bcf
Merge branch 'master' into hierarchical-tree
Keavon May 19, 2025
065af10
fixes some white spaces
MohdMohsin97 May 25, 2025
007610b
Merge branch 'hierarchical-tree' of https://github.com/MohdMohsin97/G…
MohdMohsin97 May 25, 2025
7bc5397
feat: added path to message enum in hierarchical tree
MohdMohsin97 May 26, 2025
ca8dbfb
feat: add file creation of hierarchical message system tree
MohdMohsin97 May 28, 2025
cff1d81
Merge branch 'GraphiteEditor:master' into hierarchical-tree
MohdMohsin97 May 28, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions editor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ pub mod node_graph_executor;
#[cfg(test)]
pub mod test_utils;
pub mod utility_traits;
pub mod utility_types;
3 changes: 2 additions & 1 deletion editor/src/messages/animation/animation_message_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -57,6 +57,7 @@ impl AnimationMessageHandler {
}
}

#[message_handler_data]
impl MessageHandler<AnimationMessage, ()> for AnimationMessageHandler {
fn process_message(&mut self, message: AnimationMessage, responses: &mut VecDeque<Message>, _data: ()) {
match message {
Expand Down
3 changes: 2 additions & 1 deletion editor/src/messages/broadcast/broadcast_message_handler.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::messages::prelude::*;

#[derive(Debug, Clone, Default)]
#[derive(Debug, Clone, Default, ExtractField)]
pub struct BroadcastMessageHandler {
listeners: HashMap<BroadcastEvent, Vec<Message>>,
}

#[message_handler_data]
impl MessageHandler<BroadcastMessage, ()> for BroadcastMessageHandler {
fn process_message(&mut self, message: BroadcastMessage, responses: &mut VecDeque<Message>, _data: ()) {
match message {
Expand Down
3 changes: 2 additions & 1 deletion editor/src/messages/debug/debug_message_handler.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use super::utility_types::MessageLoggingVerbosity;
use crate::messages::prelude::*;

#[derive(Debug, Default)]
#[derive(Debug, Default, ExtractField)]
pub struct DebugMessageHandler {
pub message_logging_verbosity: MessageLoggingVerbosity,
}

#[message_handler_data]
impl MessageHandler<DebugMessage, ()> for DebugMessageHandler {
fn process_message(&mut self, message: DebugMessage, responses: &mut VecDeque<Message>, _data: ()) {
match message {
Expand Down
4 changes: 3 additions & 1 deletion editor/src/messages/dialog/dialog_message_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,21 @@ 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,
}

/// 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,
preferences_dialog: PreferencesDialogMessageHandler,
}

#[message_handler_data]
impl MessageHandler<DialogMessage, DialogMessageData<'_>> for DialogMessageHandler {
fn process_message(&mut self, message: DialogMessage, responses: &mut VecDeque<Message>, data: DialogMessageData) {
let DialogMessageData { portfolio, preferences } = data;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ 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,
}

/// 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,
Expand All @@ -31,6 +32,7 @@ impl Default for ExportDialogMessageHandler {
}
}

#[message_handler_data]
impl MessageHandler<ExportDialogMessage, ExportDialogMessageData<'_>> for ExportDialogMessageHandler {
fn process_message(&mut self, message: ExportDialogMessage, responses: &mut VecDeque<Message>, data: ExportDialogMessageData) {
let ExportDialogMessageData { portfolio } = data;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ 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,
pub dimensions: UVec2,
}

#[message_handler_data]
impl MessageHandler<NewDocumentDialogMessage, ()> for NewDocumentDialogMessageHandler {
fn process_message(&mut self, message: NewDocumentDialogMessage, responses: &mut VecDeque<Message>, _data: ()) {
match message {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ 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,
}

/// 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]
impl MessageHandler<PreferencesDialogMessage, PreferencesDialogMessageData<'_>> for PreferencesDialogMessageHandler {
fn process_message(&mut self, message: PreferencesDialogMessage, responses: &mut VecDeque<Message>, data: PreferencesDialogMessageData) {
let PreferencesDialogMessageData { preferences } = data;
Expand Down
3 changes: 2 additions & 1 deletion editor/src/messages/globals/globals_message_handler.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::messages::prelude::*;

#[derive(Debug, Default)]
#[derive(Debug, Default, ExtractField)]
pub struct GlobalsMessageHandler {}

#[message_handler_data]
impl MessageHandler<GlobalsMessage, ()> for GlobalsMessageHandler {
fn process_message(&mut self, message: GlobalsMessage, _responses: &mut VecDeque<Message>, _data: ()) {
match message {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ 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,
}

#[derive(Debug, Default)]
#[derive(Debug, Default, ExtractField)]
pub struct InputMapperMessageHandler {
mapping: Mapping,
}

#[message_handler_data]
impl MessageHandler<InputMapperMessage, InputMapperMessageData<'_>> for InputMapperMessageHandler {
fn process_message(&mut self, message: InputMapperMessage, responses: &mut VecDeque<Message>, data: InputMapperMessageData) {
let InputMapperMessageData { input, actions } = data;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ 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,
}

#[derive(Debug, Default)]
#[derive(Debug, Default, ExtractField)]
pub struct KeyMappingMessageHandler {
mapping_handler: InputMapperMessageHandler,
}

#[message_handler_data]
impl MessageHandler<KeyMappingMessage, KeyMappingMessageData<'_>> for KeyMappingMessageHandler {
fn process_message(&mut self, message: KeyMappingMessage, responses: &mut VecDeque<Message>, data: KeyMappingMessageData) {
let KeyMappingMessageData { input, actions } = data;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ use crate::messages::prelude::*;
use glam::DVec2;
use std::time::Duration;

#[derive(ExtractField)]
pub struct InputPreprocessorMessageData {
pub keyboard_platform: KeyboardPlatformLayout,
}

#[derive(Debug, Default)]
#[derive(Debug, Default, ExtractField)]
pub struct InputPreprocessorMessageHandler {
pub frame_time: FrameTimeInfo,
pub time: u64,
Expand All @@ -19,6 +20,7 @@ pub struct InputPreprocessorMessageHandler {
pub viewport_bounds: ViewportBounds,
}

#[message_handler_data]
impl MessageHandler<InputPreprocessorMessage, InputPreprocessorMessageData> for InputPreprocessorMessageHandler {
fn process_message(&mut self, message: InputPreprocessorMessage, responses: &mut VecDeque<Message>, data: InputPreprocessorMessageData) {
let InputPreprocessorMessageData { keyboard_platform } = data;
Expand Down
7 changes: 6 additions & 1 deletion editor/src/messages/layout/layout_message_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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],
}
Expand Down Expand Up @@ -338,6 +338,11 @@ impl LayoutMessageHandler {
}
}

pub fn custom_data() -> MessageData {
MessageData::new(String::from("Function"), vec![(String::from("Fn(&MessageDiscriminant) -> Vec<KeysGroup>"), 346)], file!())
}

#[message_handler_data(CustomData)]
impl<F: Fn(&MessageDiscriminant) -> Vec<KeysGroup>> MessageHandler<LayoutMessage, F> for LayoutMessageHandler {
fn process_message(&mut self, message: LayoutMessage, responses: &mut std::collections::VecDeque<Message>, action_input_mapping: F) {
match message {
Expand Down
83 changes: 83 additions & 0 deletions editor/src/messages/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,86 @@ impl specta::Type for MessageDiscriminant {
specta::DataType::Any
}
}

#[cfg(test)]
mod test {
use super::*;
use std::io::Write;

#[test]
fn generate_message_tree() {
let res = Message::build_message_tree();
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, &mut file);
}
}
}

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))
} else {
if is_last {
("└── ", format!("{} ", prefix))
} else {
("├── ", format!("{}│ ", prefix))
}
};

if tree.path().is_empty() {
file.write_all(format!("{}{}{}\n", prefix, branch, tree.name()).as_bytes()).unwrap();
} else {
file.write_all(format!("{}{}{} `{}`\n", prefix, branch, tree.name(), tree.path()).as_bytes()).unwrap();
}

// 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, file);
}
}

// 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))
};
if data.path().is_empty() {
file.write_all(format!("{}{}{}\n", prefix, branch, data.name()).as_bytes()).unwrap();
} else {
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 { "├── " };

file.write_all(format!("{}{}{}\n", child_prefix, branch, field.0).as_bytes()).unwrap();
}
}

// Print data field if any
if let Some(data) = tree.message_handler_data_fields() {
let len = data.fields().len();
if data.path().is_empty() {
file.write_all(format!("{}{}{}\n", prefix, "└── ", data.name()).as_bytes()).unwrap();
} else {
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 { "├── " };
file.write_all(format!("{}{}{}\n", format!("{} ", prefix), branch, field.0).as_bytes()).unwrap();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,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,
Expand All @@ -46,7 +47,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 {
// ======================
Expand Down Expand Up @@ -166,6 +167,7 @@ impl Default for DocumentMessageHandler {
}
}

#[message_handler_data]
impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessageHandler {
fn process_message(&mut self, message: DocumentMessage, responses: &mut VecDeque<Message>, data: DocumentMessageData) {
let DocumentMessageData {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,19 @@ struct ArtboardInfo {
merge_node: NodeId,
}

#[derive(ExtractField)]
pub struct GraphOperationMessageData<'a> {
pub network_interface: &'a mut NodeNetworkInterface,
pub collapsed: &'a mut CollapsedLayers,
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.
// 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<GraphOperationMessage, GraphOperationMessageData<'_>> for GraphOperationMessageHandler {
fn process_message(&mut self, message: GraphOperationMessage, responses: &mut VecDeque<Message>, data: GraphOperationMessageData) {
let network_interface = data.network_interface;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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],
Expand All @@ -23,14 +24,15 @@ 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,
finish_operation_with_click: bool,
abortable_pan_start: Option<f64>,
}

#[message_handler_data]
impl MessageHandler<NavigationMessage, NavigationMessageData<'_>> for NavigationMessageHandler {
fn process_message(&mut self, message: NavigationMessage, responses: &mut VecDeque<Message>, data: NavigationMessageData) {
let NavigationMessageData {
Expand Down
Loading