Desktop: Open file dialogs in the folder containing the document (#3934)
Desktop: Open save file dialogs in document parent folder
This commit is contained in:
parent
5b1e1cb2fb
commit
4a37ce4576
|
|
@ -1,7 +1,6 @@
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
use graphite_editor::messages::layout::utility_types::layout_widget::LayoutTarget;
|
use graphite_editor::messages::layout::utility_types::layout_widget::LayoutTarget;
|
||||||
use graphite_editor::messages::prelude::FrontendMessage;
|
use graphite_editor::messages::prelude::FrontendMessage;
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use super::DesktopWrapperMessageDispatcher;
|
use super::DesktopWrapperMessageDispatcher;
|
||||||
use super::messages::{DesktopFrontendMessage, Document, FileFilter, OpenFileDialogContext, SaveFileDialogContext};
|
use super::messages::{DesktopFrontendMessage, Document, FileFilter, OpenFileDialogContext, SaveFileDialogContext};
|
||||||
|
|
@ -25,7 +24,13 @@ pub(super) fn intercept_frontend_message(dispatcher: &mut DesktopWrapperMessageD
|
||||||
context: OpenFileDialogContext::Import,
|
context: OpenFileDialogContext::Import,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
FrontendMessage::TriggerSaveDocument { document_id, name, path, content } => {
|
FrontendMessage::TriggerSaveDocument {
|
||||||
|
document_id,
|
||||||
|
name,
|
||||||
|
path,
|
||||||
|
folder,
|
||||||
|
content,
|
||||||
|
} => {
|
||||||
let content = content.into_vec();
|
let content = content.into_vec();
|
||||||
if let Some(path) = path {
|
if let Some(path) = path {
|
||||||
dispatcher.respond(DesktopFrontendMessage::WriteFile { path, content });
|
dispatcher.respond(DesktopFrontendMessage::WriteFile { path, content });
|
||||||
|
|
@ -33,7 +38,7 @@ pub(super) fn intercept_frontend_message(dispatcher: &mut DesktopWrapperMessageD
|
||||||
dispatcher.respond(DesktopFrontendMessage::SaveFileDialog {
|
dispatcher.respond(DesktopFrontendMessage::SaveFileDialog {
|
||||||
title: "Save Document".to_string(),
|
title: "Save Document".to_string(),
|
||||||
default_filename: name,
|
default_filename: name,
|
||||||
default_folder: path.and_then(|p| p.parent().map(PathBuf::from)),
|
default_folder: folder,
|
||||||
filters: vec![FileFilter {
|
filters: vec![FileFilter {
|
||||||
name: "Graphite".to_string(),
|
name: "Graphite".to_string(),
|
||||||
extensions: vec!["graphite".to_string()],
|
extensions: vec!["graphite".to_string()],
|
||||||
|
|
@ -42,12 +47,12 @@ pub(super) fn intercept_frontend_message(dispatcher: &mut DesktopWrapperMessageD
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FrontendMessage::TriggerSaveFile { name, content } => {
|
FrontendMessage::TriggerSaveFile { name, folder, content } => {
|
||||||
let content = content.into_vec();
|
let content = content.into_vec();
|
||||||
dispatcher.respond(DesktopFrontendMessage::SaveFileDialog {
|
dispatcher.respond(DesktopFrontendMessage::SaveFileDialog {
|
||||||
title: "Save File".to_string(),
|
title: "Save File".to_string(),
|
||||||
default_filename: name,
|
default_filename: name,
|
||||||
default_folder: None,
|
default_folder: folder,
|
||||||
filters: Vec::new(),
|
filters: Vec::new(),
|
||||||
context: SaveFileDialogContext::File { content },
|
context: SaveFileDialogContext::File { content },
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,10 @@ pub(crate) use graphite_editor::messages::prelude::Message as EditorMessage;
|
||||||
|
|
||||||
pub use graphite_editor::messages::input_mapper::utility_types::input_keyboard::{Key, ModifierKeys};
|
pub use graphite_editor::messages::input_mapper::utility_types::input_keyboard::{Key, ModifierKeys};
|
||||||
pub use graphite_editor::messages::input_mapper::utility_types::input_mouse::{EditorMouseState as MouseState, EditorPosition as Position, MouseKeys};
|
pub use graphite_editor::messages::input_mapper::utility_types::input_mouse::{EditorMouseState as MouseState, EditorPosition as Position, MouseKeys};
|
||||||
pub use graphite_editor::messages::prelude::InputPreprocessorMessage as InputMessage;
|
|
||||||
|
|
||||||
pub use graphite_editor::messages::prelude::DocumentId;
|
pub use graphite_editor::messages::prelude::DocumentId;
|
||||||
|
pub use graphite_editor::messages::prelude::InputPreprocessorMessage as InputMessage;
|
||||||
pub use graphite_editor::messages::prelude::PreferencesMessageHandler as Preferences;
|
pub use graphite_editor::messages::prelude::PreferencesMessageHandler as Preferences;
|
||||||
|
|
||||||
pub enum DesktopFrontendMessage {
|
pub enum DesktopFrontendMessage {
|
||||||
ToWeb(Vec<FrontendMessage>),
|
ToWeb(Vec<FrontendMessage>),
|
||||||
OpenLaunchDocuments,
|
OpenLaunchDocuments,
|
||||||
|
|
|
||||||
|
|
@ -89,10 +89,12 @@ pub enum FrontendMessage {
|
||||||
document_id: DocumentId,
|
document_id: DocumentId,
|
||||||
name: String,
|
name: String,
|
||||||
path: Option<PathBuf>,
|
path: Option<PathBuf>,
|
||||||
|
folder: Option<PathBuf>,
|
||||||
content: serde_bytes::ByteBuf,
|
content: serde_bytes::ByteBuf,
|
||||||
},
|
},
|
||||||
TriggerSaveFile {
|
TriggerSaveFile {
|
||||||
name: String,
|
name: String,
|
||||||
|
folder: Option<PathBuf>,
|
||||||
content: serde_bytes::ByteBuf,
|
content: serde_bytes::ByteBuf,
|
||||||
},
|
},
|
||||||
TriggerExportImage {
|
TriggerExportImage {
|
||||||
|
|
|
||||||
|
|
@ -835,26 +835,28 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
DocumentMessage::SaveDocument | DocumentMessage::SaveDocumentAs => {
|
DocumentMessage::SaveDocument | DocumentMessage::SaveDocumentAs => {
|
||||||
if let DocumentMessage::SaveDocumentAs = message {
|
responses.add(PortfolioMessage::AutoSaveActiveDocument);
|
||||||
self.path = None;
|
|
||||||
|
let path = if let DocumentMessage::SaveDocumentAs = message { None } else { self.path.clone() };
|
||||||
|
if path.is_some() {
|
||||||
|
responses.add(DocumentMessage::MarkAsSaved);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.set_save_state(true);
|
let folder = self.path.as_ref().and_then(|path| path.parent()).map(|parent| parent.to_path_buf());
|
||||||
responses.add(PortfolioMessage::AutoSaveActiveDocument);
|
|
||||||
// Update the save status of the just saved document
|
|
||||||
responses.add(PortfolioMessage::UpdateOpenDocumentsList);
|
|
||||||
|
|
||||||
responses.add(FrontendMessage::TriggerSaveDocument {
|
responses.add(FrontendMessage::TriggerSaveDocument {
|
||||||
document_id,
|
document_id,
|
||||||
name: format!("{}.{}", self.name.clone(), FILE_EXTENSION),
|
name: format!("{}.{}", self.name.clone(), FILE_EXTENSION),
|
||||||
path: self.path.clone(),
|
path,
|
||||||
|
folder,
|
||||||
content: self.serialize_document().into_bytes().into(),
|
content: self.serialize_document().into_bytes().into(),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
DocumentMessage::SavedDocument { path } => {
|
DocumentMessage::SavedDocument { path } => {
|
||||||
self.path = path;
|
self.path = path;
|
||||||
|
|
||||||
responses.add(PortfolioMessage::AutoSaveActiveDocument);
|
responses.add(PortfolioMessage::AutoSaveActiveDocument);
|
||||||
|
responses.add(DocumentMessage::MarkAsSaved);
|
||||||
|
|
||||||
// Update the name to match the file stem
|
// Update the name to match the file stem
|
||||||
let document_name_from_path = self.path.as_ref().and_then(|path| {
|
let document_name_from_path = self.path.as_ref().and_then(|path| {
|
||||||
|
|
|
||||||
|
|
@ -485,9 +485,10 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
|
||||||
let name = path.file_stem().map(|n| n.to_string_lossy().to_string());
|
let name = path.file_stem().map(|n| n.to_string_lossy().to_string());
|
||||||
match Self::read_file(&path, content) {
|
match Self::read_file(&path, content) {
|
||||||
FileContent::Document(content) => {
|
FileContent::Document(content) => {
|
||||||
|
let document_path = if path.is_absolute() { Some(path) } else { None };
|
||||||
responses.add(PortfolioMessage::OpenDocumentFile {
|
responses.add(PortfolioMessage::OpenDocumentFile {
|
||||||
document_name: name,
|
document_name: name,
|
||||||
document_path: Some(path),
|
document_path,
|
||||||
document_serialized_content: content,
|
document_serialized_content: content,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -332,7 +332,7 @@ impl NodeGraphExecutor {
|
||||||
|
|
||||||
if let Some(export_config) = execution_context.export_config {
|
if let Some(export_config) = execution_context.export_config {
|
||||||
// Special handling for exporting the artwork
|
// Special handling for exporting the artwork
|
||||||
self.process_export(node_graph_output, export_config, responses)?;
|
self.process_export(node_graph_output, export_config, document, responses)?;
|
||||||
} else {
|
} else {
|
||||||
self.process_node_graph_output(node_graph_output, responses)?;
|
self.process_node_graph_output(node_graph_output, responses)?;
|
||||||
}
|
}
|
||||||
|
|
@ -435,7 +435,7 @@ impl NodeGraphExecutor {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_export(&self, node_graph_output: TaggedValue, export_config: ExportConfig, responses: &mut VecDeque<Message>) -> Result<(), String> {
|
fn process_export(&self, node_graph_output: TaggedValue, export_config: ExportConfig, document: &DocumentMessageHandler, responses: &mut VecDeque<Message>) -> Result<(), String> {
|
||||||
let ExportConfig {
|
let ExportConfig {
|
||||||
file_type,
|
file_type,
|
||||||
name,
|
name,
|
||||||
|
|
@ -455,6 +455,7 @@ impl NodeGraphExecutor {
|
||||||
_ => name,
|
_ => name,
|
||||||
};
|
};
|
||||||
let name = format!("{base_name}.{file_extension}");
|
let name = format!("{base_name}.{file_extension}");
|
||||||
|
let folder = document.path.as_ref().and_then(|path| path.parent()).map(|parent| parent.to_path_buf());
|
||||||
|
|
||||||
match node_graph_output {
|
match node_graph_output {
|
||||||
TaggedValue::RenderOutput(RenderOutput {
|
TaggedValue::RenderOutput(RenderOutput {
|
||||||
|
|
@ -464,6 +465,7 @@ impl NodeGraphExecutor {
|
||||||
if file_type == FileType::Svg {
|
if file_type == FileType::Svg {
|
||||||
responses.add(FrontendMessage::TriggerSaveFile {
|
responses.add(FrontendMessage::TriggerSaveFile {
|
||||||
name,
|
name,
|
||||||
|
folder,
|
||||||
content: svg.into_bytes().into(),
|
content: svg.into_bytes().into(),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -506,7 +508,11 @@ impl NodeGraphExecutor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
responses.add(FrontendMessage::TriggerSaveFile { name, content: encoded.into() });
|
responses.add(FrontendMessage::TriggerSaveFile {
|
||||||
|
name,
|
||||||
|
folder,
|
||||||
|
content: encoded.into(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(format!("Incorrect render type for exporting to an SVG ({file_type:?}, {node_graph_output})"));
|
return Err(format!("Incorrect render type for exporting to an SVG ({file_type:?}, {node_graph_output})"));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue