Improve message ordering to use a stack (#707)
* Improve message ordering * Resovle bug with widgets * Less code duplication for UpdateOpenDocumentsList * Fix layer panel
This commit is contained in:
parent
d12d805e2f
commit
b2eae904d8
|
|
@ -10,7 +10,7 @@ use std::collections::VecDeque;
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Dispatcher {
|
pub struct Dispatcher {
|
||||||
message_queue: VecDeque<Message>,
|
message_queues: Vec<VecDeque<Message>>,
|
||||||
pub responses: Vec<FrontendMessage>,
|
pub responses: Vec<FrontendMessage>,
|
||||||
message_handlers: DispatcherMessageHandlers,
|
message_handlers: DispatcherMessageHandlers,
|
||||||
}
|
}
|
||||||
|
|
@ -38,8 +38,9 @@ const SIDE_EFFECT_FREE_MESSAGES: &[MessageDiscriminant] = &[
|
||||||
ArtboardMessageDiscriminant::RenderArtboards,
|
ArtboardMessageDiscriminant::RenderArtboards,
|
||||||
))),
|
))),
|
||||||
MessageDiscriminant::Portfolio(PortfolioMessageDiscriminant::Document(DocumentMessageDiscriminant::FolderChanged)),
|
MessageDiscriminant::Portfolio(PortfolioMessageDiscriminant::Document(DocumentMessageDiscriminant::FolderChanged)),
|
||||||
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateDocumentLayerDetails),
|
MessageDiscriminant::Portfolio(PortfolioMessageDiscriminant::Document(DocumentMessageDiscriminant::DocumentStructureChanged)),
|
||||||
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateDocumentLayerTreeStructure),
|
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateDocumentLayerTreeStructure),
|
||||||
|
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateActiveDocument),
|
||||||
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateOpenDocumentsList),
|
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateOpenDocumentsList),
|
||||||
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::TriggerFontLoad),
|
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::TriggerFontLoad),
|
||||||
MessageDiscriminant::Tool(ToolMessageDiscriminant::DocumentIsDirty),
|
MessageDiscriminant::Tool(ToolMessageDiscriminant::DocumentIsDirty),
|
||||||
|
|
@ -54,17 +55,31 @@ impl Dispatcher {
|
||||||
pub fn handle_message<T: Into<Message>>(&mut self, message: T) {
|
pub fn handle_message<T: Into<Message>>(&mut self, message: T) {
|
||||||
use Message::*;
|
use Message::*;
|
||||||
|
|
||||||
self.message_queue.push_back(message.into());
|
self.message_queues.push(VecDeque::from_iter([message.into()]));
|
||||||
|
|
||||||
while let Some(message) = self.message_queue.pop_front() {
|
while let Some(message) = self.message_queues.last_mut().and_then(VecDeque::pop_front) {
|
||||||
// Skip processing of this message if it will be processed later
|
// If the deepest queue is now empty (after being popped from) then remove it
|
||||||
if SIDE_EFFECT_FREE_MESSAGES.contains(&message.to_discriminant()) && self.message_queue.contains(&message) {
|
if self.message_queues.last().filter(|queue| queue.is_empty()).is_some() {
|
||||||
continue;
|
self.message_queues.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip processing of this message if it will be processed later (at the end of the shallowest level queue)
|
||||||
|
if SIDE_EFFECT_FREE_MESSAGES.contains(&message.to_discriminant()) {
|
||||||
|
let already_in_queue = self.message_queues.first().filter(|queue| queue.contains(&message)).is_some();
|
||||||
|
if already_in_queue {
|
||||||
|
continue;
|
||||||
|
} else if self.message_queues.len() > 1 {
|
||||||
|
self.message_queues[0].push_back(message);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print the message at a verbosity level of `log`
|
// Print the message at a verbosity level of `log`
|
||||||
self.log_message(&message);
|
self.log_message(&message);
|
||||||
|
|
||||||
|
// Create a new queue for the child messages
|
||||||
|
let mut queue = VecDeque::new();
|
||||||
|
|
||||||
// Process the action by forwarding it to the relevant message handler, or saving the FrontendMessage to be sent to the frontend
|
// Process the action by forwarding it to the relevant message handler, or saving the FrontendMessage to be sent to the frontend
|
||||||
#[remain::sorted]
|
#[remain::sorted]
|
||||||
match message {
|
match message {
|
||||||
|
|
@ -73,7 +88,7 @@ impl Dispatcher {
|
||||||
Dialog(message) => {
|
Dialog(message) => {
|
||||||
self.message_handlers
|
self.message_handlers
|
||||||
.dialog_message_handler
|
.dialog_message_handler
|
||||||
.process_action(message, &self.message_handlers.portfolio_message_handler, &mut self.message_queue);
|
.process_action(message, &self.message_handlers.portfolio_message_handler, &mut queue);
|
||||||
}
|
}
|
||||||
Frontend(message) => {
|
Frontend(message) => {
|
||||||
// Image and font loading should be immediately handled
|
// Image and font loading should be immediately handled
|
||||||
|
|
@ -86,22 +101,22 @@ impl Dispatcher {
|
||||||
self.responses.push(message);
|
self.responses.push(message);
|
||||||
}
|
}
|
||||||
Global(message) => {
|
Global(message) => {
|
||||||
self.message_handlers.global_message_handler.process_action(message, (), &mut self.message_queue);
|
self.message_handlers.global_message_handler.process_action(message, (), &mut queue);
|
||||||
}
|
}
|
||||||
InputMapper(message) => {
|
InputMapper(message) => {
|
||||||
let actions = self.collect_actions();
|
let actions = self.collect_actions();
|
||||||
self.message_handlers
|
self.message_handlers
|
||||||
.input_mapper_message_handler
|
.input_mapper_message_handler
|
||||||
.process_action(message, (&self.message_handlers.input_preprocessor_message_handler, actions), &mut self.message_queue);
|
.process_action(message, (&self.message_handlers.input_preprocessor_message_handler, actions), &mut queue);
|
||||||
}
|
}
|
||||||
InputPreprocessor(message) => {
|
InputPreprocessor(message) => {
|
||||||
self.message_handlers.input_preprocessor_message_handler.process_action(message, (), &mut self.message_queue);
|
self.message_handlers.input_preprocessor_message_handler.process_action(message, (), &mut queue);
|
||||||
}
|
}
|
||||||
Layout(message) => self.message_handlers.layout_message_handler.process_action(message, (), &mut self.message_queue),
|
Layout(message) => self.message_handlers.layout_message_handler.process_action(message, (), &mut queue),
|
||||||
Portfolio(message) => {
|
Portfolio(message) => {
|
||||||
self.message_handlers
|
self.message_handlers
|
||||||
.portfolio_message_handler
|
.portfolio_message_handler
|
||||||
.process_action(message, &self.message_handlers.input_preprocessor_message_handler, &mut self.message_queue);
|
.process_action(message, &self.message_handlers.input_preprocessor_message_handler, &mut queue);
|
||||||
}
|
}
|
||||||
Tool(message) => {
|
Tool(message) => {
|
||||||
self.message_handlers.tool_message_handler.process_action(
|
self.message_handlers.tool_message_handler.process_action(
|
||||||
|
|
@ -111,15 +126,20 @@ impl Dispatcher {
|
||||||
&self.message_handlers.input_preprocessor_message_handler,
|
&self.message_handlers.input_preprocessor_message_handler,
|
||||||
self.message_handlers.portfolio_message_handler.font_cache(),
|
self.message_handlers.portfolio_message_handler.font_cache(),
|
||||||
),
|
),
|
||||||
&mut self.message_queue,
|
&mut queue,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Workspace(message) => {
|
Workspace(message) => {
|
||||||
self.message_handlers
|
self.message_handlers
|
||||||
.workspace_message_handler
|
.workspace_message_handler
|
||||||
.process_action(message, &self.message_handlers.input_preprocessor_message_handler, &mut self.message_queue);
|
.process_action(message, &self.message_handlers.input_preprocessor_message_handler, &mut queue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there are child messages, append the queue to the list of queues
|
||||||
|
if !queue.is_empty() {
|
||||||
|
self.message_queues.push(queue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,20 +85,7 @@ impl PortfolioMessageHandler {
|
||||||
|
|
||||||
self.documents.insert(document_id, new_document);
|
self.documents.insert(document_id, new_document);
|
||||||
|
|
||||||
// Send the new list of document tab names
|
responses.push_back(PortfolioMessage::UpdateOpenDocumentsList.into());
|
||||||
let open_documents = self
|
|
||||||
.document_ids
|
|
||||||
.iter()
|
|
||||||
.filter_map(|id| {
|
|
||||||
self.documents.get(id).map(|document| FrontendDocumentDetails {
|
|
||||||
is_saved: document.is_saved(),
|
|
||||||
id: *id,
|
|
||||||
name: document.name.clone(),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
responses.push_back(FrontendMessage::UpdateOpenDocumentsList { open_documents }.into());
|
|
||||||
|
|
||||||
responses.push_back(PortfolioMessage::SelectDocument { document_id }.into());
|
responses.push_back(PortfolioMessage::SelectDocument { document_id }.into());
|
||||||
}
|
}
|
||||||
|
|
@ -209,19 +196,7 @@ impl MessageHandler<PortfolioMessage, &InputPreprocessorMessageHandler> for Port
|
||||||
};
|
};
|
||||||
|
|
||||||
// Send the new list of document tab names
|
// Send the new list of document tab names
|
||||||
let open_documents = self
|
responses.push_back(UpdateOpenDocumentsList.into());
|
||||||
.document_ids
|
|
||||||
.iter()
|
|
||||||
.filter_map(|id| {
|
|
||||||
self.documents.get(id).map(|doc| FrontendDocumentDetails {
|
|
||||||
is_saved: doc.is_saved(),
|
|
||||||
id: *id,
|
|
||||||
name: doc.name.clone(),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
responses.push_back(FrontendMessage::UpdateOpenDocumentsList { open_documents }.into());
|
|
||||||
responses.push_back(FrontendMessage::UpdateActiveDocument { document_id: self.active_document_id }.into());
|
responses.push_back(FrontendMessage::UpdateActiveDocument { document_id: self.active_document_id }.into());
|
||||||
responses.push_back(FrontendMessage::TriggerIndexedDbRemoveDocument { document_id }.into());
|
responses.push_back(FrontendMessage::TriggerIndexedDbRemoveDocument { document_id }.into());
|
||||||
responses.push_back(RenderDocument.into());
|
responses.push_back(RenderDocument.into());
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@ impl MessageHandler<LayoutMessage, ()> for LayoutMessageHandler {
|
||||||
self.send_layout(layout_target, responses);
|
self.send_layout(layout_target, responses);
|
||||||
}
|
}
|
||||||
UpdateLayout { layout_target, widget_id, value } => {
|
UpdateLayout { layout_target, widget_id, value } => {
|
||||||
|
self.send_layout(layout_target, responses);
|
||||||
let layout = &mut self.layouts[layout_target as usize];
|
let layout = &mut self.layouts[layout_target as usize];
|
||||||
let widget_holder = layout.iter_mut().find(|widget| widget.widget_id == widget_id);
|
let widget_holder = layout.iter_mut().find(|widget| widget.widget_id == widget_id);
|
||||||
if widget_holder.is_none() {
|
if widget_holder.is_none() {
|
||||||
|
|
@ -183,7 +184,6 @@ impl MessageHandler<LayoutMessage, ()> for LayoutMessageHandler {
|
||||||
}
|
}
|
||||||
Widget::TextLabel(_) => {}
|
Widget::TextLabel(_) => {}
|
||||||
};
|
};
|
||||||
self.send_layout(layout_target, responses);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ impl PathOutline {
|
||||||
|
|
||||||
/// Clears overlays for the seleted paths and removes references
|
/// Clears overlays for the seleted paths and removes references
|
||||||
pub fn clear_selected(&mut self, responses: &mut VecDeque<Message>) {
|
pub fn clear_selected(&mut self, responses: &mut VecDeque<Message>) {
|
||||||
if let Some(path) = self.selected_overlay_paths.pop() {
|
while let Some(path) = self.selected_overlay_paths.pop() {
|
||||||
let operation = Operation::DeleteLayer { path };
|
let operation = Operation::DeleteLayer { path };
|
||||||
responses.push_back(DocumentMessage::Overlays(operation.into()).into());
|
responses.push_back(DocumentMessage::Overlays(operation.into()).into());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue