Skip to content

Commit 40d5960

Browse files
committed
Massively reorganize and clean up the whole Rust codebase (#478)
* Massively reorganize and clean up the whole Rust codebase * Additional changes during code review
1 parent f63424b commit 40d5960

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+2505
-2179
lines changed

editor/src/communication/dispatcher.rs

Lines changed: 93 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
1+
use crate::document::PortfolioMessageHandler;
2+
use crate::global::GlobalMessageHandler;
3+
use crate::input::{InputMapperMessageHandler, InputPreprocessorMessageHandler};
14
use crate::message_prelude::*;
5+
use crate::viewport_tools::tool_message_handler::ToolMessageHandler;
26

3-
pub use crate::document::PortfolioMessageHandler;
4-
pub use crate::input::{InputMapper, InputPreprocessor};
5-
pub use crate::tool::ToolMessageHandler;
6-
7-
use crate::global::GlobalMessageHandler;
87
use std::collections::VecDeque;
98

109
#[derive(Debug, Default)]
1110
pub struct Dispatcher {
12-
input_preprocessor: InputPreprocessor,
13-
input_mapper: InputMapper,
11+
message_queue: VecDeque<Message>,
12+
pub responses: Vec<FrontendMessage>,
13+
message_handlers: DispatcherMessageHandlers,
14+
}
15+
16+
#[remain::sorted]
17+
#[derive(Debug, Default)]
18+
struct DispatcherMessageHandlers {
1419
global_message_handler: GlobalMessageHandler,
15-
tool_message_handler: ToolMessageHandler,
20+
input_mapper_message_handler: InputMapperMessageHandler,
21+
input_preprocessor_message_handler: InputPreprocessorMessageHandler,
1622
portfolio_message_handler: PortfolioMessageHandler,
17-
messages: VecDeque<Message>,
18-
pub responses: Vec<FrontendMessage>,
23+
tool_message_handler: ToolMessageHandler,
1924
}
2025

21-
// For optimization, these are messages guaranteed to be redundant when repeated
22-
// The last occurrence of the message in the message queue is sufficient to ensure correctness
23-
// In addition, these messages do not change any state in the backend (aside from caches)
26+
// For optimization, these are messages guaranteed to be redundant when repeated.
27+
// The last occurrence of the message in the message queue is sufficient to ensure correct behavior.
28+
// In addition, these messages do not change any state in the backend (aside from caches).
2429
const SIDE_EFFECT_FREE_MESSAGES: &[MessageDiscriminant] = &[
2530
MessageDiscriminant::Portfolio(PortfolioMessageDiscriminant::Document(DocumentMessageDiscriminant::RenderDocument)),
2631
MessageDiscriminant::Portfolio(PortfolioMessageDiscriminant::Document(DocumentMessageDiscriminant::FolderChanged)),
@@ -35,28 +40,54 @@ impl Dispatcher {
3540
Self::default()
3641
}
3742

43+
#[remain::check]
3844
pub fn handle_message<T: Into<Message>>(&mut self, message: T) {
39-
self.messages.push_back(message.into());
45+
self.message_queue.push_back(message.into());
4046

4147
use Message::*;
42-
while let Some(message) = self.messages.pop_front() {
48+
while let Some(message) = self.message_queue.pop_front() {
4349
// Skip processing of this message if it will be processed later
44-
if SIDE_EFFECT_FREE_MESSAGES.contains(&message.to_discriminant()) && self.messages.contains(&message) {
50+
if SIDE_EFFECT_FREE_MESSAGES.contains(&message.to_discriminant()) && self.message_queue.contains(&message) {
4551
continue;
4652
}
53+
54+
// Print the message at a verbosity level of `log`
4755
self.log_message(&message);
56+
57+
// Process the action by forwarding it to the relevant message handler, or saving the FrontendMessage to be sent to the frontend
58+
#[remain::sorted]
4859
match message {
49-
NoOp => (),
50-
Portfolio(message) => self.portfolio_message_handler.process_action(message, &self.input_preprocessor, &mut self.messages),
51-
Global(message) => self.global_message_handler.process_action(message, (), &mut self.messages),
52-
Tool(message) => self
53-
.tool_message_handler
54-
.process_action(message, (self.portfolio_message_handler.active_document(), &self.input_preprocessor), &mut self.messages),
55-
Frontend(message) => self.responses.push(message),
56-
InputPreprocessor(message) => self.input_preprocessor.process_action(message, (), &mut self.messages),
60+
Frontend(message) => {
61+
// `FrontendMessage`s are saved and will be sent to the frontend after the message queue is done being processed
62+
self.responses.push(message);
63+
}
64+
Global(message) => {
65+
self.message_handlers.global_message_handler.process_action(message, (), &mut self.message_queue);
66+
}
5767
InputMapper(message) => {
5868
let actions = self.collect_actions();
59-
self.input_mapper.process_action(message, (&self.input_preprocessor, actions), &mut self.messages)
69+
self.message_handlers
70+
.input_mapper_message_handler
71+
.process_action(message, (&self.message_handlers.input_preprocessor_message_handler, actions), &mut self.message_queue);
72+
}
73+
InputPreprocessor(message) => {
74+
self.message_handlers.input_preprocessor_message_handler.process_action(message, (), &mut self.message_queue);
75+
}
76+
NoOp => {}
77+
Portfolio(message) => {
78+
self.message_handlers
79+
.portfolio_message_handler
80+
.process_action(message, &self.message_handlers.input_preprocessor_message_handler, &mut self.message_queue);
81+
}
82+
Tool(message) => {
83+
self.message_handlers.tool_message_handler.process_action(
84+
message,
85+
(
86+
self.message_handlers.portfolio_message_handler.active_document(),
87+
&self.message_handlers.input_preprocessor_message_handler,
88+
),
89+
&mut self.message_queue,
90+
);
6091
}
6192
}
6293
}
@@ -65,11 +96,11 @@ impl Dispatcher {
6596
pub fn collect_actions(&self) -> ActionList {
6697
// TODO: Reduce the number of heap allocations
6798
let mut list = Vec::new();
68-
list.extend(self.input_preprocessor.actions());
69-
list.extend(self.input_mapper.actions());
70-
list.extend(self.global_message_handler.actions());
71-
list.extend(self.tool_message_handler.actions());
72-
list.extend(self.portfolio_message_handler.actions());
99+
list.extend(self.message_handlers.input_preprocessor_message_handler.actions());
100+
list.extend(self.message_handlers.input_mapper_message_handler.actions());
101+
list.extend(self.message_handlers.global_message_handler.actions());
102+
list.extend(self.message_handlers.tool_message_handler.actions());
103+
list.extend(self.message_handlers.portfolio_message_handler.actions());
73104
list
74105
}
75106

@@ -82,21 +113,21 @@ impl Dispatcher {
82113
) || MessageDiscriminant::from(message).local_name().ends_with("MouseMove"))
83114
{
84115
log::trace!("Message: {:?}", message);
85-
// log::trace!("Hints: {:?}", self.input_mapper.hints(self.collect_actions()));
116+
// log::trace!("Hints: {:?}", self.input_mapper_message_handler.hints(self.collect_actions()));
86117
}
87118
}
88119
}
89120

90121
#[cfg(test)]
91122
mod test {
92-
use crate::{
93-
communication::set_uuid_seed,
94-
document::{Clipboard::*, DocumentMessageHandler},
95-
message_prelude::*,
96-
misc::test_utils::EditorTestUtils,
97-
Editor,
98-
};
99-
use graphene::{color::Color, Operation};
123+
use crate::communication::set_uuid_seed;
124+
use crate::document::clipboards::Clipboard;
125+
use crate::document::DocumentMessageHandler;
126+
use crate::message_prelude::*;
127+
use crate::misc::test_utils::EditorTestUtils;
128+
use crate::Editor;
129+
use graphene::color::Color;
130+
use graphene::Operation;
100131

101132
fn init_logger() {
102133
let _ = env_logger::builder().is_test(true).try_init();
@@ -129,14 +160,14 @@ mod test {
129160
init_logger();
130161
let mut editor = create_editor_with_three_layers();
131162

132-
let document_before_copy = editor.dispatcher.portfolio_message_handler.active_document().graphene_document.clone();
133-
editor.handle_message(PortfolioMessage::Copy(User));
163+
let document_before_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone();
164+
editor.handle_message(PortfolioMessage::Copy(Clipboard::User));
134165
editor.handle_message(PortfolioMessage::PasteIntoFolder {
135-
clipboard: User,
166+
clipboard: Clipboard::User,
136167
path: vec![],
137168
insert_index: -1,
138169
});
139-
let document_after_copy = editor.dispatcher.portfolio_message_handler.active_document().graphene_document.clone();
170+
let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone();
140171

141172
let layers_before_copy = document_before_copy.root.as_folder().unwrap().layers();
142173
let layers_after_copy = document_after_copy.root.as_folder().unwrap().layers();
@@ -163,18 +194,18 @@ mod test {
163194
init_logger();
164195
let mut editor = create_editor_with_three_layers();
165196

166-
let document_before_copy = editor.dispatcher.portfolio_message_handler.active_document().graphene_document.clone();
197+
let document_before_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone();
167198
let shape_id = document_before_copy.root.as_folder().unwrap().layer_ids[1];
168199

169200
editor.handle_message(DocumentMessage::SetSelectedLayers(vec![vec![shape_id]]));
170-
editor.handle_message(PortfolioMessage::Copy(User));
201+
editor.handle_message(PortfolioMessage::Copy(Clipboard::User));
171202
editor.handle_message(PortfolioMessage::PasteIntoFolder {
172-
clipboard: User,
203+
clipboard: Clipboard::User,
173204
path: vec![],
174205
insert_index: -1,
175206
});
176207

177-
let document_after_copy = editor.dispatcher.portfolio_message_handler.active_document().graphene_document.clone();
208+
let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone();
178209

179210
let layers_before_copy = document_before_copy.root.as_folder().unwrap().layers();
180211
let layers_after_copy = document_after_copy.root.as_folder().unwrap().layers();
@@ -206,7 +237,7 @@ mod test {
206237

207238
editor.handle_message(DocumentMessage::CreateEmptyFolder(vec![]));
208239

209-
let document_before_added_shapes = editor.dispatcher.portfolio_message_handler.active_document().graphene_document.clone();
240+
let document_before_added_shapes = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone();
210241
let folder_id = document_before_added_shapes.root.as_folder().unwrap().layer_ids[FOLDER_INDEX];
211242

212243
// TODO: This adding of a Line and Pen should be rewritten using the corresponding functions in EditorTestUtils.
@@ -228,22 +259,22 @@ mod test {
228259

229260
editor.handle_message(DocumentMessage::SetSelectedLayers(vec![vec![folder_id]]));
230261

231-
let document_before_copy = editor.dispatcher.portfolio_message_handler.active_document().graphene_document.clone();
262+
let document_before_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone();
232263

233-
editor.handle_message(PortfolioMessage::Copy(User));
264+
editor.handle_message(PortfolioMessage::Copy(Clipboard::User));
234265
editor.handle_message(DocumentMessage::DeleteSelectedLayers);
235266
editor.handle_message(PortfolioMessage::PasteIntoFolder {
236-
clipboard: User,
267+
clipboard: Clipboard::User,
237268
path: vec![],
238269
insert_index: -1,
239270
});
240271
editor.handle_message(PortfolioMessage::PasteIntoFolder {
241-
clipboard: User,
272+
clipboard: Clipboard::User,
242273
path: vec![],
243274
insert_index: -1,
244275
});
245276

246-
let document_after_copy = editor.dispatcher.portfolio_message_handler.active_document().graphene_document.clone();
277+
let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone();
247278

248279
let layers_before_copy = document_before_copy.root.as_folder().unwrap().layers();
249280
let layers_after_copy = document_after_copy.root.as_folder().unwrap().layers();
@@ -294,26 +325,26 @@ mod test {
294325
const SHAPE_INDEX: usize = 1;
295326
const RECT_INDEX: usize = 0;
296327

297-
let document_before_copy = editor.dispatcher.portfolio_message_handler.active_document().graphene_document.clone();
328+
let document_before_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone();
298329
let rect_id = document_before_copy.root.as_folder().unwrap().layer_ids[RECT_INDEX];
299330
let ellipse_id = document_before_copy.root.as_folder().unwrap().layer_ids[ELLIPSE_INDEX];
300331

301332
editor.handle_message(DocumentMessage::SetSelectedLayers(vec![vec![rect_id], vec![ellipse_id]]));
302-
editor.handle_message(PortfolioMessage::Copy(User));
333+
editor.handle_message(PortfolioMessage::Copy(Clipboard::User));
303334
editor.handle_message(DocumentMessage::DeleteSelectedLayers);
304335
editor.draw_rect(0., 800., 12., 200.);
305336
editor.handle_message(PortfolioMessage::PasteIntoFolder {
306-
clipboard: User,
337+
clipboard: Clipboard::User,
307338
path: vec![],
308339
insert_index: -1,
309340
});
310341
editor.handle_message(PortfolioMessage::PasteIntoFolder {
311-
clipboard: User,
342+
clipboard: Clipboard::User,
312343
path: vec![],
313344
insert_index: -1,
314345
});
315346

316-
let document_after_copy = editor.dispatcher.portfolio_message_handler.active_document().graphene_document.clone();
347+
let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone();
317348

318349
let layers_before_copy = document_before_copy.root.as_folder().unwrap().layers();
319350
let layers_after_copy = document_after_copy.root.as_folder().unwrap().layers();
@@ -343,7 +374,7 @@ mod test {
343374
fn map_to_vec(paths: Vec<&[LayerId]>) -> Vec<Vec<LayerId>> {
344375
paths.iter().map(|layer| layer.to_vec()).collect::<Vec<_>>()
345376
}
346-
let sorted_layers = map_to_vec(editor.dispatcher.portfolio_message_handler.active_document().all_layers_sorted());
377+
let sorted_layers = map_to_vec(editor.dispatcher.message_handlers.portfolio_message_handler.active_document().all_layers_sorted());
347378
println!("Sorted layers: {:?}", sorted_layers);
348379

349380
let verify_order = |handler: &mut DocumentMessageHandler| {
@@ -357,15 +388,15 @@ mod test {
357388
editor.handle_message(DocumentMessage::SetSelectedLayers(sorted_layers[..2].to_vec()));
358389

359390
editor.handle_message(DocumentMessage::ReorderSelectedLayers(1));
360-
let (all, non_selected, selected) = verify_order(editor.dispatcher.portfolio_message_handler.active_document_mut());
391+
let (all, non_selected, selected) = verify_order(editor.dispatcher.message_handlers.portfolio_message_handler.active_document_mut());
361392
assert_eq!(all, non_selected.into_iter().chain(selected.into_iter()).collect::<Vec<_>>());
362393

363394
editor.handle_message(DocumentMessage::ReorderSelectedLayers(-1));
364-
let (all, non_selected, selected) = verify_order(editor.dispatcher.portfolio_message_handler.active_document_mut());
395+
let (all, non_selected, selected) = verify_order(editor.dispatcher.message_handlers.portfolio_message_handler.active_document_mut());
365396
assert_eq!(all, selected.into_iter().chain(non_selected.into_iter()).collect::<Vec<_>>());
366397

367398
editor.handle_message(DocumentMessage::ReorderSelectedLayers(i32::MAX));
368-
let (all, non_selected, selected) = verify_order(editor.dispatcher.portfolio_message_handler.active_document_mut());
399+
let (all, non_selected, selected) = verify_order(editor.dispatcher.message_handlers.portfolio_message_handler.active_document_mut());
369400
assert_eq!(all, non_selected.into_iter().chain(selected.into_iter()).collect::<Vec<_>>());
370401
}
371402
}

editor/src/communication/message.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use crate::message_prelude::*;
2+
23
use graphite_proc_macros::*;
4+
35
use serde::{Deserialize, Serialize};
4-
use std::{
5-
collections::hash_map::DefaultHasher,
6-
hash::{Hash, Hasher},
7-
};
6+
use std::collections::hash_map::DefaultHasher;
7+
use std::hash::{Hash, Hasher};
88

99
pub trait AsMessage: TransitiveChild
1010
where
@@ -16,35 +16,37 @@ where
1616
}
1717
}
1818

19+
#[remain::sorted]
1920
#[impl_message]
2021
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
2122
pub enum Message {
22-
NoOp,
2323
#[child]
24-
Portfolio(PortfolioMessage),
24+
Frontend(FrontendMessage),
2525
#[child]
2626
Global(GlobalMessage),
2727
#[child]
28-
Tool(ToolMessage),
29-
#[child]
30-
Frontend(FrontendMessage),
28+
InputMapper(InputMapperMessage),
3129
#[child]
3230
InputPreprocessor(InputPreprocessorMessage),
31+
NoOp,
3332
#[child]
34-
InputMapper(InputMapperMessage),
33+
Portfolio(PortfolioMessage),
34+
#[child]
35+
Tool(ToolMessage),
3536
}
3637

3738
impl Message {
3839
/// Returns the byte representation of the message.
3940
///
4041
/// # Safety
4142
/// This function reads from uninitialized memory!!!
42-
/// Only use if you know what you are doing
43+
/// Only use if you know what you are doing.
4344
unsafe fn as_slice(&self) -> &[u8] {
4445
core::slice::from_raw_parts(self as *const Message as *const u8, std::mem::size_of::<Message>())
4546
}
47+
4648
/// Returns a pseudo hash that should uniquely identify the message.
47-
/// This is needed because `Hash` is not implemented for f64s
49+
/// This is needed because `Hash` is not implemented for `f64`s
4850
///
4951
/// # Safety
5052
/// This function reads from uninitialized memory but the generated value should be fine.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
pub use crate::communication::dispatcher::*;
2+
pub use crate::input::InputPreprocessorMessageHandler;
3+
use crate::message_prelude::*;
4+
5+
use std::collections::VecDeque;
6+
7+
pub type ActionList = Vec<Vec<MessageDiscriminant>>;
8+
9+
// TODO: Add Send + Sync requirement
10+
// Use something like rw locks for synchronization
11+
pub trait MessageHandlerData {}
12+
13+
pub trait MessageHandler<A: ToDiscriminant, T>
14+
where
15+
A::Discriminant: AsMessage,
16+
<A::Discriminant as TransitiveChild>::TopParent: TransitiveChild<Parent = <A::Discriminant as TransitiveChild>::TopParent, TopParent = <A::Discriminant as TransitiveChild>::TopParent> + AsMessage,
17+
{
18+
/// Return true if the Action is consumed.
19+
fn process_action(&mut self, action: A, data: T, responses: &mut VecDeque<Message>);
20+
21+
fn actions(&self) -> ActionList;
22+
}

0 commit comments

Comments
 (0)