Add demo artwork

This commit is contained in:
Keavon Chambers
2023-08-22 03:26:59 -07:00
parent 0e97a256b7
commit 0dcfafbf64
33 changed files with 2133 additions and 1050 deletions

File diff suppressed because one or more lines are too long

View File

@@ -79,7 +79,7 @@ pub const DEFAULT_FONT_FAMILY: &str = "Merriweather";
pub const DEFAULT_FONT_STYLE: &str = "Normal (400)";
// Document
pub const GRAPHITE_DOCUMENT_VERSION: &str = "0.0.17"; // Remember to save a simple document and replace the test file `graphite-test-document.graphite`
pub const GRAPHITE_DOCUMENT_VERSION: &str = "0.0.17"; // Remember to update the demo artwork in /demos with both this version number and the contents so it remains editable
pub const DEFAULT_DOCUMENT_NAME: &str = "Untitled Document";
pub const FILE_SAVE_SUFFIX: &str = ".graphite";
pub const MAX_UNDO_HISTORY_LEN: usize = 100; // TODO: Add this to user preferences

View File

@@ -555,7 +555,8 @@ mod test {
println!("-------------------------------------------------");
println!("Failed test due to receiving a DisplayDialogError while loading the Graphite sample file.");
println!("This is most likely caused by forgetting to bump the `GRAPHITE_DOCUMENT_VERSION` in `editor/src/consts.rs`");
println!("After bumping this version number, replace `graphite-test-document.graphite` with a valid file by saving a document from the editor.");
println!("After bumping this version number, update the documents in `/demo-artwork` by editing their JSON to");
println!("ensure they remain compatible with both the bumped version number and the serialization format change.");
println!("DisplayDialogError details:");
println!();
println!("Description: {}", value);
@@ -567,19 +568,25 @@ mod test {
init_logger();
let mut editor = Editor::create();
let test_file = include_str!("../graphite-test-document.graphite");
let responses = editor.handle_message(PortfolioMessage::OpenDocumentFile {
document_name: "Graphite Version Test".into(),
document_serialized_content: test_file.into(),
});
let test_files = [
("Just a Potted Cactus", include_str!("../../demo-artwork/just-a-potted-cactus.graphite")),
("Valley of Spires", include_str!("../../demo-artwork/valley-of-spires.graphite")),
];
for response in responses {
// Check for the existence of the file format incompatibility warning dialog after opening the test file
if let FrontendMessage::UpdateDialogDetails { layout_target: _, diff } = response {
if let DiffUpdate::SubLayout(sub_layout) = &diff[0].new_value {
if let LayoutGroup::Row { widgets } = &sub_layout[0] {
if let Widget::TextLabel(TextLabel { value, .. }) = &widgets[0].widget {
print_problem_to_terminal_on_failure(value);
for (document_name, document_serialized_content) in test_files {
let responses = editor.handle_message(PortfolioMessage::OpenDocumentFile {
document_name: document_name.into(),
document_serialized_content: document_serialized_content.into(),
});
for response in responses {
// Check for the existence of the file format incompatibility warning dialog after opening the test file
if let FrontendMessage::UpdateDialogDetails { layout_target: _, diff } = response {
if let DiffUpdate::SubLayout(sub_layout) = &diff[0].new_value {
if let LayoutGroup::Row { widgets } = &sub_layout[0] {
if let Widget::TextLabel(TextLabel { value, .. }) = &widgets[0].widget {
print_problem_to_terminal_on_failure(value);
}
}
}
}

View File

@@ -33,6 +33,7 @@ pub enum DialogMessage {
RequestComingSoonDialog {
issue: Option<i32>,
},
RequestDemoArtworkDialog,
RequestExportDialog,
RequestNewDocumentDialog,
RequestPreferencesDialog,

View File

@@ -1,7 +1,8 @@
use super::simple_dialogs::{self, AboutGraphiteDialog, ComingSoonDialog};
use super::simple_dialogs::{self, AboutGraphiteDialog, ComingSoonDialog, DemoArtworkDialog};
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::prelude::*;
/// Stores the dialogs which require state. These are the ones that have their own message handlers, and are not the ones defined in `simple_dialogs`.
#[derive(Debug, Default, Clone)]
pub struct DialogMessageHandler {
export_dialog: ExportDialogMessageHandler,
@@ -53,6 +54,11 @@ impl MessageHandler<DialogMessage, (&PortfolioMessageHandler, &PreferencesMessag
coming_soon.send_layout(responses, LayoutTarget::DialogDetails);
responses.add(FrontendMessage::DisplayDialog { icon: "Warning".to_string() });
}
DialogMessage::RequestDemoArtworkDialog => {
let demo_artwork_dialog = DemoArtworkDialog;
demo_artwork_dialog.send_layout(responses, LayoutTarget::DialogDetails);
responses.add(FrontendMessage::DisplayDialog { icon: "Image".to_string() });
}
DialogMessage::RequestExportDialog => {
if let Some(document) = portfolio.active_document() {
let artboard_handler = &document.artboard_message_handler;

View File

@@ -50,7 +50,7 @@ impl MessageHandler<NewDocumentDialogMessage, ()> for NewDocumentDialogMessageHa
impl LayoutHolder for NewDocumentDialogMessageHandler {
fn layout(&self) -> Layout {
let title = vec![TextLabel::new("New document").bold(true).widget_holder()];
let title = vec![TextLabel::new("New Document").bold(true).widget_holder()];
let name = vec![
TextLabel::new("Name").table_align(true).widget_holder(),

View File

@@ -8,6 +8,7 @@ impl LayoutHolder for CloseAllDocumentsDialog {
fn layout(&self) -> Layout {
let discard = TextButton::new("Discard All")
.min_width(96)
.emphasized(true)
.on_update(|_| {
DialogMessage::CloseDialogAndThen {
followups: vec![PortfolioMessage::CloseAllDocuments.into()],

View File

@@ -0,0 +1,50 @@
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::prelude::*;
/// A dialog to let the user browse a gallery of demo artwork that can be opened.
pub struct DemoArtworkDialog;
impl LayoutHolder for DemoArtworkDialog {
fn layout(&self) -> Layout {
let artwork = [
(
"Valley of Spires",
"ThumbnailValleyOfSpires",
"https://raw.githubusercontent.com/GraphiteEditor/Graphite/master/demo-artwork/valley-of-spires.graphite",
),
(
"Just a Potted Cactus",
"ThumbnailJustAPottedCactus",
"https://raw.githubusercontent.com/GraphiteEditor/Graphite/master/demo-artwork/just-a-potted-cactus.graphite",
),
];
let image_widgets = artwork
.into_iter()
.map(|(_, thumbnail, _)| ImageLabel::new(thumbnail.to_string()).width(Some("256px".into())).widget_holder())
.collect();
let button_widgets = artwork
.into_iter()
.map(|(label, _, url)| {
TextButton::new(label)
.min_width(256)
.on_update(|_| {
DialogMessage::CloseDialogAndThen {
followups: vec![FrontendMessage::TriggerFetchAndOpenDocument { url: url.to_string() }.into()],
}
.into()
})
.widget_holder()
})
.collect();
Layout::WidgetLayout(WidgetLayout::new(vec![
LayoutGroup::Row {
widgets: vec![TextLabel::new("Demo Artwork".to_string()).bold(true).widget_holder()],
},
LayoutGroup::Row { widgets: image_widgets },
LayoutGroup::Row { widgets: button_widgets },
]))
}
}

View File

@@ -2,10 +2,12 @@ mod about_graphite_dialog;
mod close_all_documents_dialog;
mod close_document_dialog;
mod coming_soon_dialog;
mod demo_artwork_dialog;
mod error_dialog;
pub use about_graphite_dialog::AboutGraphiteDialog;
pub use close_all_documents_dialog::CloseAllDocumentsDialog;
pub use close_document_dialog::CloseDocumentDialog;
pub use coming_soon_dialog::ComingSoonDialog;
pub use demo_artwork_dialog::DemoArtworkDialog;
pub use error_dialog::ErrorDialog;

View File

@@ -67,6 +67,9 @@ pub enum FrontendMessage {
document: String,
name: String,
},
TriggerFetchAndOpenDocument {
url: String,
},
TriggerFontLoad {
font: Font,
#[serde(rename = "isDefault")]

View File

@@ -158,6 +158,7 @@ impl<F: Fn(&MessageDiscriminant) -> Vec<KeysGroup>> MessageHandler<LayoutMessage
responses.add(callback_message);
}
Widget::IconLabel(_) => {}
Widget::ImageLabel(_) => {}
Widget::InvisibleStandinInput(invisible) => {
let callback_message = (invisible.on_update.callback)(&());
responses.add(callback_message);

View File

@@ -288,6 +288,7 @@ impl LayoutGroup {
Widget::FontInput(x) => &mut x.tooltip,
Widget::IconButton(x) => &mut x.tooltip,
Widget::IconLabel(x) => &mut x.tooltip,
Widget::ImageLabel(x) => &mut x.tooltip,
Widget::LayerReferenceInput(x) => &mut x.tooltip,
Widget::NumberInput(x) => &mut x.tooltip,
Widget::OptionalInput(x) => &mut x.tooltip,
@@ -438,6 +439,7 @@ pub enum Widget {
FontInput(FontInput),
IconButton(IconButton),
IconLabel(IconLabel),
ImageLabel(ImageLabel),
InvisibleStandinInput(InvisibleStandinInput),
LayerReferenceInput(LayerReferenceInput),
NumberInput(NumberInput),
@@ -516,6 +518,7 @@ impl DiffUpdate {
Widget::PopoverButton(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),
Widget::TextButton(widget) => Some((&mut widget.tooltip, &mut widget.tooltip_shortcut)),
Widget::IconLabel(_)
| Widget::ImageLabel(_)
| Widget::CurveInput(_)
| Widget::InvisibleStandinInput(_)
| Widget::PivotAssist(_)

View File

@@ -12,6 +12,18 @@ pub struct IconLabel {
pub tooltip: String,
}
#[derive(Clone, Serialize, Deserialize, Derivative, Debug, Default, PartialEq, Eq, WidgetBuilder, specta::Type)]
pub struct ImageLabel {
#[widget_builder(constructor)]
pub image: String,
pub width: Option<String>,
pub height: Option<String>,
pub tooltip: String,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, WidgetBuilder, specta::Type)]
pub struct Separator {
pub direction: SeparatorDirection,

View File

@@ -49,10 +49,17 @@ impl LayoutHolder for MenuBarMessageHandler {
},
MenuBarEntry {
label: "Open…".into(),
icon: Some("Folder".into()),
shortcut: action_keys!(PortfolioMessageDiscriminant::OpenDocument),
action: MenuBarEntry::create_action(|_| PortfolioMessage::OpenDocument.into()),
..MenuBarEntry::default()
},
MenuBarEntry {
label: "Open Demo Artwork…".into(),
icon: Some("Image".into()),
action: MenuBarEntry::create_action(|_| DialogMessage::RequestDemoArtworkDialog.into()),
..MenuBarEntry::default()
},
],
vec![
MenuBarEntry {