mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-25 16:58:12 +08:00
Add a checkered background to transparent artboards and the infinite canvas (#4022)
* Add checkered transparency rendering to infinite canvas and artboards * Enable artboard clipping by default * Make new infinite canvas documents begin with a white background layer * Remove the export dialog's transparency option now that it's redundant * Make exporting transparent JPGs use white not black * Code review
This commit is contained in:
@@ -6,7 +6,6 @@ use crate::messages::prelude::*;
|
||||
pub enum ExportDialogMessage {
|
||||
FileType { file_type: FileType },
|
||||
ScaleFactor { factor: f64 },
|
||||
TransparentBackground { transparent: bool },
|
||||
ExportBounds { bounds: ExportBounds },
|
||||
|
||||
Submit,
|
||||
|
||||
@@ -14,7 +14,6 @@ pub struct ExportDialogMessageHandler {
|
||||
pub file_type: FileType,
|
||||
pub scale_factor: f64,
|
||||
pub bounds: ExportBounds,
|
||||
pub transparent_background: bool,
|
||||
pub artboards: HashMap<LayerNodeIdentifier, String>,
|
||||
pub has_selection: bool,
|
||||
}
|
||||
@@ -25,7 +24,6 @@ impl Default for ExportDialogMessageHandler {
|
||||
file_type: Default::default(),
|
||||
scale_factor: 1.,
|
||||
bounds: Default::default(),
|
||||
transparent_background: false,
|
||||
artboards: Default::default(),
|
||||
has_selection: false,
|
||||
}
|
||||
@@ -40,11 +38,17 @@ impl MessageHandler<ExportDialogMessage, ExportDialogMessageContext<'_>> for Exp
|
||||
match message {
|
||||
ExportDialogMessage::FileType { file_type } => self.file_type = file_type,
|
||||
ExportDialogMessage::ScaleFactor { factor } => self.scale_factor = factor,
|
||||
ExportDialogMessage::TransparentBackground { transparent } => self.transparent_background = transparent,
|
||||
ExportDialogMessage::ExportBounds { bounds } => self.bounds = bounds,
|
||||
|
||||
ExportDialogMessage::Submit => {
|
||||
let artboard_name = match self.bounds {
|
||||
// Fall back to "All Artwork" if "Selection" was chosen but nothing is currently selected
|
||||
let bounds = if !self.has_selection && self.bounds == ExportBounds::Selection {
|
||||
ExportBounds::AllArtwork
|
||||
} else {
|
||||
self.bounds
|
||||
};
|
||||
|
||||
let artboard_name = match bounds {
|
||||
ExportBounds::Artboard(layer) => self.artboards.get(&layer).cloned(),
|
||||
_ => None,
|
||||
};
|
||||
@@ -52,8 +56,7 @@ impl MessageHandler<ExportDialogMessage, ExportDialogMessageContext<'_>> for Exp
|
||||
name: portfolio.active_document().map(|document| document.name.clone()).unwrap_or_default(),
|
||||
file_type: self.file_type,
|
||||
scale_factor: self.scale_factor,
|
||||
bounds: self.bounds,
|
||||
transparent_background: self.file_type != FileType::Jpg && self.transparent_background,
|
||||
bounds,
|
||||
artboard_name,
|
||||
artboard_count: self.artboards.len(),
|
||||
})
|
||||
@@ -127,6 +130,7 @@ impl LayoutHolder for ExportDialogMessageHandler {
|
||||
let artboards = self.artboards.iter().map(|(&layer, name)| (ExportBounds::Artboard(layer), name.to_string(), false)).collect();
|
||||
let choices = [standard_bounds, artboards];
|
||||
|
||||
// Fall back to "All Artwork" if "Selection" was chosen but nothing is currently selected
|
||||
let current_bounds = if !self.has_selection && self.bounds == ExportBounds::Selection {
|
||||
ExportBounds::AllArtwork
|
||||
} else {
|
||||
@@ -159,22 +163,6 @@ impl LayoutHolder for ExportDialogMessageHandler {
|
||||
DropdownInput::new(entries).selected_index(Some(index as u32)).widget_instance(),
|
||||
];
|
||||
|
||||
let checkbox_id = CheckboxId::new();
|
||||
let transparent_background = vec![
|
||||
TextLabel::new("Transparency").table_align(true).min_width(100).for_checkbox(checkbox_id).widget_instance(),
|
||||
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
|
||||
CheckboxInput::new(self.transparent_background)
|
||||
.disabled(self.file_type == FileType::Jpg)
|
||||
.on_update(move |value: &CheckboxInput| ExportDialogMessage::TransparentBackground { transparent: value.checked }.into())
|
||||
.for_label(checkbox_id)
|
||||
.widget_instance(),
|
||||
];
|
||||
|
||||
Layout(vec![
|
||||
LayoutGroup::row(export_type),
|
||||
LayoutGroup::row(resolution),
|
||||
LayoutGroup::row(export_area),
|
||||
LayoutGroup::row(transparent_background),
|
||||
])
|
||||
Layout(vec![LayoutGroup::row(export_type), LayoutGroup::row(resolution), LayoutGroup::row(export_area)])
|
||||
}
|
||||
}
|
||||
|
||||
+29
-13
@@ -1,7 +1,9 @@
|
||||
use crate::messages::layout::utility_types::widget_prelude::*;
|
||||
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
|
||||
use crate::messages::prelude::*;
|
||||
use glam::{IVec2, UVec2};
|
||||
use graph_craft::document::NodeId;
|
||||
use graphene_std::Color;
|
||||
|
||||
/// A dialog to allow users to set some initial options about a new document.
|
||||
#[derive(Debug, Clone, Default, ExtractField)]
|
||||
@@ -22,26 +24,40 @@ impl MessageHandler<NewDocumentDialogMessage, ()> for NewDocumentDialogMessageHa
|
||||
NewDocumentDialogMessage::Submit => {
|
||||
responses.add(PortfolioMessage::NewDocumentWithName { name: self.name.clone() });
|
||||
|
||||
let create_artboard = !self.infinite && self.dimensions.x > 0 && self.dimensions.y > 0;
|
||||
if create_artboard {
|
||||
if self.infinite {
|
||||
// Infinite canvas: add a locked white background layer
|
||||
let node_id = NodeId::new();
|
||||
responses.add(GraphOperationMessage::NewColorFillLayer {
|
||||
node_id,
|
||||
color: Color::WHITE,
|
||||
parent: LayerNodeIdentifier::ROOT_PARENT,
|
||||
insert_index: 0,
|
||||
});
|
||||
responses.add(NodeGraphMessage::SetDisplayNameImpl {
|
||||
node_id,
|
||||
alias: "Background".to_string(),
|
||||
});
|
||||
responses.add(NodeGraphMessage::SetLocked { node_id, locked: true });
|
||||
} else if self.dimensions.x > 0 && self.dimensions.y > 0 {
|
||||
// Finite canvas: create an artboard with the specified dimensions
|
||||
responses.add(GraphOperationMessage::NewArtboard {
|
||||
id: NodeId::new(),
|
||||
artboard: graphene_std::Artboard::new(IVec2::ZERO, self.dimensions.as_ivec2()),
|
||||
});
|
||||
responses.add(NavigationMessage::CanvasPan { delta: self.dimensions.as_dvec2() });
|
||||
responses.add(NodeGraphMessage::RunDocumentGraph);
|
||||
|
||||
responses.add(ViewportMessage::RepropagateUpdate);
|
||||
|
||||
responses.add(DeferMessage::AfterNavigationReady {
|
||||
messages: vec![
|
||||
DocumentMessage::ZoomCanvasToFitAll.into(),
|
||||
DocumentMessage::DeselectAllLayers.into(),
|
||||
PortfolioMessage::AutoSaveActiveDocument.into(),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
responses.add(NodeGraphMessage::RunDocumentGraph);
|
||||
responses.add(ViewportMessage::RepropagateUpdate);
|
||||
|
||||
responses.add(DeferMessage::AfterNavigationReady {
|
||||
messages: vec![
|
||||
DocumentMessage::ZoomCanvasToFitAll.into(),
|
||||
DocumentMessage::DeselectAllLayers.into(),
|
||||
PortfolioMessage::AutoSaveActiveDocument.into(),
|
||||
],
|
||||
});
|
||||
|
||||
responses.add(DocumentMessage::MarkAsSaved);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user