mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
Move file filter creation from frontend to editor (#4351)
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use super::IconName;
|
||||
use super::utility_types::{MouseCursorIcon, PersistedState};
|
||||
use crate::messages::app_window::app_window_message_handler::AppWindowPlatform;
|
||||
use crate::messages::frontend::utility_types::{DocumentInfo, EyedropperPreviewImage, RasterizedImage};
|
||||
use crate::messages::frontend::utility_types::{DocumentInfo, EyedropperPreviewImage, FileFilter, RasterizedImage};
|
||||
use crate::messages::input_mapper::utility_types::misc::ActionShortcut;
|
||||
use crate::messages::layout::utility_types::widget_prelude::*;
|
||||
use crate::messages::portfolio::document::node_graph::utility_types::{
|
||||
@@ -87,16 +87,24 @@ pub enum FrontendMessage {
|
||||
commit_date: String,
|
||||
},
|
||||
TriggerDisplayThirdPartyLicensesDialog,
|
||||
TriggerOpen {
|
||||
filters: Vec<FileFilter>,
|
||||
},
|
||||
TriggerImport {
|
||||
filters: Vec<FileFilter>,
|
||||
},
|
||||
TriggerSaveDocument {
|
||||
document_id: DocumentId,
|
||||
name: String,
|
||||
path: Option<PathBuf>,
|
||||
folder: Option<PathBuf>,
|
||||
filters: Vec<FileFilter>,
|
||||
content: serde_bytes::ByteBuf,
|
||||
},
|
||||
TriggerSaveFile {
|
||||
name: String,
|
||||
folder: Option<PathBuf>,
|
||||
filters: Vec<FileFilter>,
|
||||
content: serde_bytes::ByteBuf,
|
||||
},
|
||||
TriggerExportImage {
|
||||
@@ -128,8 +136,6 @@ pub enum FrontendMessage {
|
||||
},
|
||||
TriggerOpenLaunchDocuments,
|
||||
TriggerLoadPreferences,
|
||||
TriggerOpen,
|
||||
TriggerImport,
|
||||
TriggerSavePreferences {
|
||||
#[cfg_attr(feature = "wasm", tsify(type = "unknown"))]
|
||||
preferences: PreferencesMessageHandler,
|
||||
|
||||
@@ -64,6 +64,26 @@ impl FileType {
|
||||
FileType::Svg => "image/svg+xml",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extension(self) -> &'static str {
|
||||
match self {
|
||||
FileType::Png => "png",
|
||||
FileType::Jpg => "jpg",
|
||||
FileType::Svg => "svg",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn file_filter(self) -> FileFilter {
|
||||
let name = match self {
|
||||
FileType::Png => "PNG Image",
|
||||
FileType::Jpg => "JPEG Image",
|
||||
FileType::Svg => "SVG Image",
|
||||
};
|
||||
FileFilter {
|
||||
name: name.into(),
|
||||
extensions: vec![self.extension().into()],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
|
||||
@@ -91,3 +111,10 @@ pub struct RasterizedImage {
|
||||
pub height: u32,
|
||||
pub pixels: serde_bytes::ByteBuf,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize)]
|
||||
pub struct FileFilter {
|
||||
pub name: String,
|
||||
pub extensions: Vec<String>,
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ use crate::consts::{
|
||||
ASYMPTOTIC_EFFECT, BLEND_COUNT_PER_LAYER, COLOR_OVERLAY_GRAY, DEFAULT_DOCUMENT_NAME, FILE_EXTENSION, GDD_FILE_EXTENSION, LAYER_INDENT_OFFSET, NODE_CHAIN_WIDTH, SCALE_EFFECT, SCROLLBAR_SPACING,
|
||||
VIEWPORT_ROTATE_SNAP_INTERVAL,
|
||||
};
|
||||
use crate::messages::frontend::utility_types::FileFilter;
|
||||
use crate::messages::input_mapper::utility_types::macros::action_shortcut;
|
||||
use crate::messages::layout::utility_types::widget_prelude::*;
|
||||
use crate::messages::portfolio::document::data_panel::{DataPanelMessageContext, DataPanelMessageHandler};
|
||||
@@ -1089,6 +1090,10 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
|
||||
name,
|
||||
path,
|
||||
folder,
|
||||
filters: vec![FileFilter {
|
||||
name: "Graphite Document".into(),
|
||||
extensions: vec![extension.into()],
|
||||
}],
|
||||
content: content.into(),
|
||||
})
|
||||
});
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::application::{Editor, generate_uuid};
|
||||
use crate::consts::{DEFAULT_DOCUMENT_NAME, FILE_EXTENSION, GDD_FILE_EXTENSION};
|
||||
use crate::messages::animation::TimingInformation;
|
||||
use crate::messages::dialog::simple_dialogs;
|
||||
use crate::messages::frontend::utility_types::{DocumentInfo, PersistedState};
|
||||
use crate::messages::frontend::utility_types::{DocumentInfo, FileFilter, PersistedState};
|
||||
use crate::messages::input_mapper::utility_types::keyboard::Key;
|
||||
use crate::messages::input_mapper::utility_types::macros::{action_shortcut, action_shortcut_manual};
|
||||
use crate::messages::layout::utility_types::widget_prelude::*;
|
||||
@@ -501,6 +501,10 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
|
||||
responses.add(FrontendMessage::TriggerSaveFile {
|
||||
name: filename,
|
||||
folder: None,
|
||||
filters: vec![FileFilter {
|
||||
name: "Graphite Document".into(),
|
||||
extensions: vec![FILE_EXTENSION.into()],
|
||||
}],
|
||||
content: serde_bytes::ByteBuf::from(content),
|
||||
});
|
||||
} else {
|
||||
@@ -508,6 +512,10 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
|
||||
Ok(zip_bytes) => responses.add(FrontendMessage::TriggerSaveFile {
|
||||
name: format!("{FOLDER_NAME}.zip"),
|
||||
folder: None,
|
||||
filters: vec![FileFilter {
|
||||
name: "Zip Archive".into(),
|
||||
extensions: vec!["zip".into()],
|
||||
}],
|
||||
content: serde_bytes::ByteBuf::from(zip_bytes),
|
||||
}),
|
||||
Err(e) => {
|
||||
@@ -652,11 +660,28 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
|
||||
}
|
||||
PortfolioMessage::Open => {
|
||||
// This portfolio message wraps the frontend message so it can be listed as an action, which isn't possible for frontend messages
|
||||
responses.add(FrontendMessage::TriggerOpen);
|
||||
responses.add(FrontendMessage::TriggerOpen {
|
||||
filters: vec![
|
||||
FileFilter {
|
||||
name: "Graphite Document".into(),
|
||||
extensions: vec![FILE_EXTENSION.into(), GDD_FILE_EXTENSION.into()],
|
||||
},
|
||||
FileFilter {
|
||||
name: "Image".into(),
|
||||
extensions: vec!["svg".into(), "png".into(), "jpg".into(), "jpeg".into(), "bmp".into(), "gif".into()],
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
PortfolioMessage::Import => {
|
||||
// This portfolio message wraps the frontend message so it can be listed as an action, which isn't possible for frontend messages
|
||||
responses.add(FrontendMessage::TriggerImport);
|
||||
// TODO: Also offer the Graphite document filter once importing Graphite documents as nodes is supported
|
||||
responses.add(FrontendMessage::TriggerImport {
|
||||
filters: vec![FileFilter {
|
||||
name: "Image".into(),
|
||||
extensions: vec!["svg".into(), "png".into(), "jpg".into(), "jpeg".into(), "bmp".into(), "gif".into()],
|
||||
}],
|
||||
});
|
||||
}
|
||||
PortfolioMessage::OpenFile { path, content } => {
|
||||
let name = path.file_stem().map(|n| n.to_string_lossy().to_string());
|
||||
|
||||
@@ -730,17 +730,13 @@ impl NodeGraphExecutor {
|
||||
..
|
||||
} = export_config;
|
||||
|
||||
let file_extension = match file_type {
|
||||
FileType::Svg => "svg",
|
||||
FileType::Png => "png",
|
||||
FileType::Jpg => "jpg",
|
||||
};
|
||||
let base_name = match (artboard_name, artboard_count) {
|
||||
(Some(artboard_name), count) if count > 1 => format!("{name} - {artboard_name}"),
|
||||
_ => name,
|
||||
};
|
||||
let name = format!("{base_name}.{file_extension}");
|
||||
let name = format!("{base_name}.{}", file_type.extension());
|
||||
let folder = document.path.as_ref().and_then(|path| path.parent()).map(|parent| parent.to_path_buf());
|
||||
let filters = vec![file_type.file_filter()];
|
||||
|
||||
match node_graph_output {
|
||||
TaggedValue::RenderOutput(RenderOutput {
|
||||
@@ -751,6 +747,7 @@ impl NodeGraphExecutor {
|
||||
responses.add(FrontendMessage::TriggerSaveFile {
|
||||
name,
|
||||
folder,
|
||||
filters,
|
||||
content: svg.into_bytes().into(),
|
||||
});
|
||||
} else {
|
||||
@@ -804,6 +801,7 @@ impl NodeGraphExecutor {
|
||||
responses.add(FrontendMessage::TriggerSaveFile {
|
||||
name,
|
||||
folder,
|
||||
filters,
|
||||
content: encoded.into(),
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user