Skip to content

Welcome screen #702

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

Merged
merged 24 commits into from
Jul 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
2fb1365
unfinished implementation
mfish33 Jun 27, 2022
5bac4c5
Add frontend for the empty panel screen
Keavon Jun 29, 2022
b5720a6
Add an icon for Folder based on NodeFolder
Keavon Jun 30, 2022
dd7c73f
fixed messages causing peicees of ui not to render on new document
mfish33 Jun 30, 2022
370e7c1
Standardize nextTick syntax
Keavon Jul 1, 2022
6f61399
WIP generisization of component subscriptions (not compiling yet)
Keavon Jul 1, 2022
73293b0
Merge branch 'master' into welcome-screen
Keavon Jul 8, 2022
d327423
Merge branch 'master' into welcome-screen
Keavon Jul 13, 2022
8658a31
Fix crash when loading font and there is no active document
Keavon Jul 13, 2022
fb0918b
Only advertise tool actions with a document
0HyperCube Jul 14, 2022
a6a664f
Fix failure to create new document
Keavon Jul 15, 2022
2d63e80
Initalise the properties panel
0HyperCube Jul 16, 2022
ec9c338
Fix highlight tab, canvas jump, warns and layer tree
0HyperCube Jul 16, 2022
ad30227
Fix tests
0HyperCube Jul 16, 2022
4e1d8f7
Possibly fix some things?
0HyperCube Jul 17, 2022
fcd0249
Merge branch 'master' into welcome-screen
Keavon Jul 19, 2022
15abda5
Move WorkingColors layout definition to backend
Keavon Jul 20, 2022
b917e93
Standardize action macro formatting
Keavon Jul 21, 2022
f28f2ab
Provide typing for widgets in TS/Vue and associated cleanup
Keavon Jul 21, 2022
17d2933
Fix viewport positioning initialization
Keavon Jul 21, 2022
cc19dd3
Fix menu bar init at startup not document creation
Keavon Jul 21, 2022
f5b8c6a
Fix no viewport bounds bug
0HyperCube Jul 22, 2022
9c12c5b
Change !=0 to >0
0HyperCube Jul 22, 2022
cf3dae6
Simplify the init system
Keavon Jul 22, 2022
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
82 changes: 52 additions & 30 deletions editor/src/communication/dispatcher.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::broadcast_message_handler::BroadcastMessageHandler;
use crate::consts::{DEFAULT_FONT_FAMILY, DEFAULT_FONT_STYLE};
use crate::document::PortfolioMessageHandler;
use crate::global::GlobalMessageHandler;
use crate::input::{InputMapperMessageHandler, InputPreprocessorMessageHandler};
Expand All @@ -7,6 +8,8 @@ use crate::message_prelude::*;
use crate::viewport_tools::tool_message_handler::ToolMessageHandler;
use crate::workspace::WorkspaceMessageHandler;

use graphene::layers::text_layer::Font;

use std::collections::VecDeque;

#[derive(Debug, Default)]
Expand Down Expand Up @@ -42,8 +45,6 @@ const SIDE_EFFECT_FREE_MESSAGES: &[MessageDiscriminant] = &[
MessageDiscriminant::Portfolio(PortfolioMessageDiscriminant::Document(DocumentMessageDiscriminant::FolderChanged)),
MessageDiscriminant::Portfolio(PortfolioMessageDiscriminant::Document(DocumentMessageDiscriminant::DocumentStructureChanged)),
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateDocumentLayerTreeStructure),
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateActiveDocument),
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateOpenDocumentsList),
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::TriggerFontLoad),
MessageDiscriminant::Broadcast(BroadcastMessageDiscriminant::TriggerSignal(BroadcastSignalDiscriminant::DocumentIsDirty)),
];
Expand Down Expand Up @@ -87,21 +88,35 @@ impl Dispatcher {
match message {
#[remain::unsorted]
NoOp => {}
#[remain::unsorted]
Init => {
// Display the menu bar at the top of the window
let message = MenuBarMessage::SendLayout.into();
queue.push_back(message);

// Load the default font
let font = Font::new(DEFAULT_FONT_FAMILY.into(), DEFAULT_FONT_STYLE.into());
let message = FrontendMessage::TriggerFontLoad { font, is_default: true }.into();
queue.push_back(message);
}

Broadcast(message) => self.message_handlers.broadcast_message_handler.process_action(message, (), &mut queue),
Dialog(message) => {
self.message_handlers
.dialog_message_handler
.process_action(message, &self.message_handlers.portfolio_message_handler, &mut queue);
}
Frontend(message) => {
// Image and font loading should be immediately handled
if let FrontendMessage::UpdateImageData { .. } | FrontendMessage::TriggerFontLoad { .. } = message {
// Handle these messages immediately by returning early
if let FrontendMessage::UpdateImageData { .. } | FrontendMessage::TriggerFontLoad { .. } | FrontendMessage::TriggerRefreshBoundsOfViewports = message {
self.responses.push(message);

// Return early to avoid running the code after the match block
return;
} else {
// `FrontendMessage`s are saved and will be sent to the frontend after the message queue is done being processed
self.responses.push(message);
}

// `FrontendMessage`s are saved and will be sent to the frontend after the message queue is done being processed
self.responses.push(message);
}
Global(message) => {
self.message_handlers.global_message_handler.process_action(message, (), &mut queue);
Expand All @@ -122,15 +137,19 @@ impl Dispatcher {
.process_action(message, &self.message_handlers.input_preprocessor_message_handler, &mut queue);
}
Tool(message) => {
self.message_handlers.tool_message_handler.process_action(
message,
(
self.message_handlers.portfolio_message_handler.active_document(),
&self.message_handlers.input_preprocessor_message_handler,
self.message_handlers.portfolio_message_handler.font_cache(),
),
&mut queue,
);
if let Some(document) = self.message_handlers.portfolio_message_handler.active_document() {
self.message_handlers.tool_message_handler.process_action(
message,
(
document,
&self.message_handlers.input_preprocessor_message_handler,
self.message_handlers.portfolio_message_handler.font_cache(),
),
&mut queue,
);
} else {
log::warn!("Called ToolMessage without an active document.\nGot {:?}", message);
}
}
Workspace(message) => {
self.message_handlers
Expand All @@ -153,7 +172,9 @@ impl Dispatcher {
list.extend(self.message_handlers.input_preprocessor_message_handler.actions());
list.extend(self.message_handlers.input_mapper_message_handler.actions());
list.extend(self.message_handlers.global_message_handler.actions());
list.extend(self.message_handlers.tool_message_handler.actions());
if self.message_handlers.portfolio_message_handler.active_document().is_some() {
list.extend(self.message_handlers.tool_message_handler.actions());
}
list.extend(self.message_handlers.portfolio_message_handler.actions());
list
}
Expand Down Expand Up @@ -192,6 +213,7 @@ mod test {
set_uuid_seed(0);
let mut editor = Editor::new();

editor.new_document();
editor.select_primary_color(Color::RED);
editor.draw_rect(100., 200., 300., 400.);
editor.select_primary_color(Color::BLUE);
Expand All @@ -211,14 +233,14 @@ mod test {
init_logger();
let mut editor = create_editor_with_three_layers();

let document_before_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone();
let document_before_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().graphene_document.clone();
editor.handle_message(PortfolioMessage::Copy { clipboard: Clipboard::Internal });
editor.handle_message(PortfolioMessage::PasteIntoFolder {
clipboard: Clipboard::Internal,
folder_path: vec![],
insert_index: -1,
});
let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone();
let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().graphene_document.clone();

let layers_before_copy = document_before_copy.root.as_folder().unwrap().layers();
let layers_after_copy = document_after_copy.root.as_folder().unwrap().layers();
Expand All @@ -245,7 +267,7 @@ mod test {
init_logger();
let mut editor = create_editor_with_three_layers();

let document_before_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone();
let document_before_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().graphene_document.clone();
let shape_id = document_before_copy.root.as_folder().unwrap().layer_ids[1];

editor.handle_message(DocumentMessage::SetSelectedLayers {
Expand All @@ -258,7 +280,7 @@ mod test {
insert_index: -1,
});

let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone();
let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().graphene_document.clone();

let layers_before_copy = document_before_copy.root.as_folder().unwrap().layers();
let layers_after_copy = document_after_copy.root.as_folder().unwrap().layers();
Expand Down Expand Up @@ -290,7 +312,7 @@ mod test {

editor.handle_message(DocumentMessage::CreateEmptyFolder { container_path: vec![] });

let document_before_added_shapes = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone();
let document_before_added_shapes = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().graphene_document.clone();
let folder_id = document_before_added_shapes.root.as_folder().unwrap().layer_ids[FOLDER_INDEX];

// TODO: This adding of a Line and Pen should be rewritten using the corresponding functions in EditorTestUtils.
Expand All @@ -314,7 +336,7 @@ mod test {
replacement_selected_layers: vec![vec![folder_id]],
});

let document_before_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone();
let document_before_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().graphene_document.clone();

editor.handle_message(PortfolioMessage::Copy { clipboard: Clipboard::Internal });
editor.handle_message(DocumentMessage::DeleteSelectedLayers);
Expand All @@ -329,7 +351,7 @@ mod test {
insert_index: -1,
});

let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone();
let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().graphene_document.clone();

let layers_before_copy = document_before_copy.root.as_folder().unwrap().layers();
let layers_after_copy = document_after_copy.root.as_folder().unwrap().layers();
Expand Down Expand Up @@ -380,7 +402,7 @@ mod test {
const SHAPE_INDEX: usize = 1;
const RECT_INDEX: usize = 0;

let document_before_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone();
let document_before_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().graphene_document.clone();
let rect_id = document_before_copy.root.as_folder().unwrap().layer_ids[RECT_INDEX];
let ellipse_id = document_before_copy.root.as_folder().unwrap().layer_ids[ELLIPSE_INDEX];

Expand All @@ -401,7 +423,7 @@ mod test {
insert_index: -1,
});

let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone();
let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().graphene_document.clone();

let layers_before_copy = document_before_copy.root.as_folder().unwrap().layers();
let layers_after_copy = document_after_copy.root.as_folder().unwrap().layers();
Expand Down Expand Up @@ -431,7 +453,7 @@ mod test {
fn map_to_vec(paths: Vec<&[LayerId]>) -> Vec<Vec<LayerId>> {
paths.iter().map(|layer| layer.to_vec()).collect::<Vec<_>>()
}
let sorted_layers = map_to_vec(editor.dispatcher.message_handlers.portfolio_message_handler.active_document().all_layers_sorted());
let sorted_layers = map_to_vec(editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().all_layers_sorted());
println!("Sorted layers: {:?}", sorted_layers);

let verify_order = |handler: &mut DocumentMessageHandler| {
Expand All @@ -447,15 +469,15 @@ mod test {
});

editor.handle_message(DocumentMessage::ReorderSelectedLayers { relative_index_offset: 1 });
let (all, non_selected, selected) = verify_order(editor.dispatcher.message_handlers.portfolio_message_handler.active_document_mut());
let (all, non_selected, selected) = verify_order(editor.dispatcher.message_handlers.portfolio_message_handler.active_document_mut().unwrap());
assert_eq!(all, non_selected.into_iter().chain(selected.into_iter()).collect::<Vec<_>>());

editor.handle_message(DocumentMessage::ReorderSelectedLayers { relative_index_offset: -1 });
let (all, non_selected, selected) = verify_order(editor.dispatcher.message_handlers.portfolio_message_handler.active_document_mut());
let (all, non_selected, selected) = verify_order(editor.dispatcher.message_handlers.portfolio_message_handler.active_document_mut().unwrap());
assert_eq!(all, selected.into_iter().chain(non_selected.into_iter()).collect::<Vec<_>>());

editor.handle_message(DocumentMessage::ReorderSelectedLayers { relative_index_offset: isize::MAX });
let (all, non_selected, selected) = verify_order(editor.dispatcher.message_handlers.portfolio_message_handler.active_document_mut());
let (all, non_selected, selected) = verify_order(editor.dispatcher.message_handlers.portfolio_message_handler.active_document_mut().unwrap());
assert_eq!(all, non_selected.into_iter().chain(selected.into_iter()).collect::<Vec<_>>());
}

Expand Down
2 changes: 2 additions & 0 deletions editor/src/communication/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ where
pub enum Message {
#[remain::unsorted]
NoOp,
#[remain::unsorted]
Init,
#[child]
Broadcast(BroadcastMessage),
#[child]
Expand Down
2 changes: 1 addition & 1 deletion editor/src/dialog/dialog_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub enum DialogMessage {
// Messages
CloseAllDocumentsWithConfirmation,
CloseDialogAndThen {
followup: Box<Message>,
followups: Vec<Message>,
},
DisplayDialogError {
title: String,
Expand Down
72 changes: 40 additions & 32 deletions editor/src/dialog/dialog_message_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ impl MessageHandler<DialogMessage, &PortfolioMessageHandler> for DialogMessageHa
dialog.register_properties(responses, LayoutTarget::DialogDetails);
responses.push_back(FrontendMessage::DisplayDialog { icon: "Copy".to_string() }.into());
}
DialogMessage::CloseDialogAndThen { followup } => {
DialogMessage::CloseDialogAndThen { followups } => {
responses.push_back(FrontendMessage::DisplayDialogDismiss.into());
responses.push_back(*followup);
for message in followups.into_iter() {
responses.push_back(message);
}
}
DialogMessage::DisplayDialogError { title, description } => {
let dialog = dialogs::Error { title, description };
Expand All @@ -54,36 +56,38 @@ impl MessageHandler<DialogMessage, &PortfolioMessageHandler> for DialogMessageHa
responses.push_back(FrontendMessage::DisplayDialog { icon: "Warning".to_string() }.into());
}
DialogMessage::RequestExportDialog => {
let artboard_handler = &portfolio.active_document().artboard_message_handler;
let mut index = 0;
let artboards = artboard_handler
.artboard_ids
.iter()
.rev()
.filter_map(|&artboard| artboard_handler.artboards_graphene_document.layer(&[artboard]).ok().map(|layer| (artboard, layer)))
.map(|(artboard, layer)| {
(
artboard,
format!(
"Artboard: {}",
layer.name.clone().unwrap_or_else(|| {
index += 1;
format!("Untitled {index}")
})
),
)
})
.collect();
if let Some(document) = portfolio.active_document() {
let artboard_handler = &document.artboard_message_handler;
let mut index = 0;
let artboards = artboard_handler
.artboard_ids
.iter()
.rev()
.filter_map(|&artboard| artboard_handler.artboards_graphene_document.layer(&[artboard]).ok().map(|layer| (artboard, layer)))
.map(|(artboard, layer)| {
(
artboard,
format!(
"Artboard: {}",
layer.name.clone().unwrap_or_else(|| {
index += 1;
format!("Untitled {index}")
})
),
)
})
.collect();

self.export_dialog = Export {
file_name: portfolio.active_document().name.clone(),
scale_factor: 1.,
artboards,
has_selection: portfolio.active_document().selected_layers().next().is_some(),
..Default::default()
};
self.export_dialog.register_properties(responses, LayoutTarget::DialogDetails);
responses.push_back(FrontendMessage::DisplayDialog { icon: "File".to_string() }.into());
self.export_dialog = Export {
file_name: document.name.clone(),
scale_factor: 1.,
artboards,
has_selection: document.selected_layers().next().is_some(),
..Default::default()
};
self.export_dialog.register_properties(responses, LayoutTarget::DialogDetails);
responses.push_back(FrontendMessage::DisplayDialog { icon: "File".to_string() }.into());
}
}
DialogMessage::RequestNewDocumentDialog => {
self.new_document_dialog = NewDocument {
Expand All @@ -97,5 +101,9 @@ impl MessageHandler<DialogMessage, &PortfolioMessageHandler> for DialogMessageHa
}
}

advertise_actions!(DialogMessageDiscriminant;RequestNewDocumentDialog,RequestExportDialog,CloseAllDocumentsWithConfirmation);
advertise_actions!(DialogMessageDiscriminant;
RequestNewDocumentDialog,
RequestExportDialog,
CloseAllDocumentsWithConfirmation,
);
}
2 changes: 1 addition & 1 deletion editor/src/dialog/dialogs/close_all_documents_dialog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ impl PropertyHolder for CloseAllDocuments {
min_width: 96,
on_update: WidgetCallback::new(|_| {
DialogMessage::CloseDialogAndThen {
followup: Box::new(PortfolioMessage::CloseAllDocuments.into()),
followups: vec![PortfolioMessage::CloseAllDocuments.into()],
}
.into()
}),
Expand Down
6 changes: 3 additions & 3 deletions editor/src/dialog/dialogs/close_document_dialog.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::layout::widgets::*;
use crate::message_prelude::{DialogMessage, DocumentMessage, FrontendMessage, PortfolioMessage};
use crate::message_prelude::*;

/// A dialog for confirming the closing a document with unsaved changes.
pub struct CloseDocument {
Expand All @@ -18,7 +18,7 @@ impl PropertyHolder for CloseDocument {
emphasized: true,
on_update: WidgetCallback::new(|_| {
DialogMessage::CloseDialogAndThen {
followup: Box::new(DocumentMessage::SaveDocument.into()),
followups: vec![DocumentMessage::SaveDocument.into()],
}
.into()
}),
Expand All @@ -29,7 +29,7 @@ impl PropertyHolder for CloseDocument {
min_width: 96,
on_update: WidgetCallback::new(move |_| {
DialogMessage::CloseDialogAndThen {
followup: Box::new(PortfolioMessage::CloseDocument { document_id }.into()),
followups: vec![BroadcastSignal::ToolAbort.into(), PortfolioMessage::CloseDocument { document_id }.into()],
}
.into()
}),
Expand Down
3 changes: 2 additions & 1 deletion editor/src/dialog/dialogs/export_dialog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ impl PropertyHolder for Export {
WidgetHolder::new(Widget::TextInput(TextInput {
value: self.file_name.clone(),
on_update: WidgetCallback::new(|text_input: &TextInput| ExportDialogUpdate::FileName(text_input.value.clone()).into()),
..Default::default()
})),
];

Expand Down Expand Up @@ -123,7 +124,7 @@ impl PropertyHolder for Export {
emphasized: true,
on_update: WidgetCallback::new(|_| {
DialogMessage::CloseDialogAndThen {
followup: Box::new(ExportDialogUpdate::Submit.into()),
followups: vec![ExportDialogUpdate::Submit.into()],
}
.into()
}),
Expand Down
Loading