Disallow zero-area artboards (#794)

* Fix zero-area artboard

* Add artboard only when user starts dragging

* Rename variables for clarity

* Revert regression caused by commit a11c9ef6ef9c4daa35140148cec9ff85b3a3d8c8

* Fix zero-area artboard properly
This commit is contained in:
Kit PANG 2022-10-23 00:14:37 +08:00 committed by Keavon Chambers
parent 7b4c43ff8d
commit b10d7a93b6
3 changed files with 53 additions and 35 deletions

View File

@ -94,7 +94,14 @@ impl MessageHandler<ArtboardMessage, &FontCache> for ArtboardMessageHandler {
);
}
}
ResizeArtboard { artboard, position, size } => {
ResizeArtboard { artboard, position, mut size } => {
if size.0.abs() == 0. {
size.0 = size.0.signum();
}
if size.1.abs() == 0. {
size.1 = size.1.signum();
}
responses.push_back(
ArtboardMessage::DispatchOperation(Box::new(DocumentOperation::SetLayerTransform {
path: vec![artboard],

View File

@ -147,6 +147,8 @@ pub fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDequ
value: Some(layer.bounding_transform(&persistent_data.font_cache).scale_x()),
label: "W".into(),
unit: " px".into(),
is_integer: true,
min: Some(1.),
on_update: WidgetCallback::new(|number_input: &NumberInput| {
PropertiesPanelMessage::ModifyTransform {
value: number_input.value.unwrap(),
@ -164,6 +166,8 @@ pub fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDequ
value: Some(layer.bounding_transform(&persistent_data.font_cache).scale_y()),
label: "H".into(),
unit: " px".into(),
is_integer: true,
min: Some(1.),
on_update: WidgetCallback::new(|number_input: &NumberInput| {
PropertiesPanelMessage::ModifyTransform {
value: number_input.value.unwrap(),

View File

@ -117,7 +117,7 @@ impl Default for ArtboardToolFsmState {
#[derive(Clone, Debug, Default)]
struct ArtboardToolData {
bounding_box_overlays: Option<BoundingBoxOverlays>,
selected_board: Option<LayerId>,
selected_artboard: Option<LayerId>,
snap_manager: SnapManager,
cursor: MouseCursorIcon,
drag_start: DVec2,
@ -140,7 +140,10 @@ impl Fsm for ArtboardToolFsmState {
match (self, event) {
(ArtboardToolFsmState::Ready | ArtboardToolFsmState::ResizingBounds | ArtboardToolFsmState::Dragging, ArtboardToolMessage::DocumentIsDirty) => {
match (
tool_data.selected_board.map(|path| document.artboard_bounding_box_and_transform(&[path], font_cache)).unwrap_or(None),
tool_data
.selected_artboard
.map(|path| document.artboard_bounding_box_and_transform(&[path], font_cache))
.unwrap_or(None),
tool_data.bounding_box_overlays.take(),
) {
(None, Some(bounding_box_overlays)) => bounding_box_overlays.delete(responses),
@ -157,7 +160,7 @@ impl Fsm for ArtboardToolFsmState {
responses.push_back(OverlaysMessage::Rerender.into());
responses.push_back(
PropertiesPanelMessage::SetActiveLayers {
paths: vec![vec![tool_data.selected_board.unwrap()]],
paths: vec![vec![tool_data.selected_artboard.unwrap()]],
document: TargetDocument::Artboard,
}
.into(),
@ -190,12 +193,12 @@ impl Fsm for ArtboardToolFsmState {
let snap_x = selected_edges.2 || selected_edges.3;
let snap_y = selected_edges.0 || selected_edges.1;
let board = tool_data.selected_board.unwrap();
tool_data.snap_manager.start_snap(document, document.bounding_boxes(None, Some(board), font_cache), snap_x, snap_y);
let artboard = tool_data.selected_artboard.unwrap();
tool_data.snap_manager.start_snap(document, document.bounding_boxes(None, Some(artboard), font_cache), snap_x, snap_y);
tool_data.snap_manager.add_all_document_handles(document, &[], &[], &[]);
if let Some(bounds) = &mut tool_data.bounding_box_overlays {
let pivot = document.artboard_message_handler.artboards_graphene_document.pivot(&[board], font_cache).unwrap_or_default();
let pivot = document.artboard_message_handler.artboards_graphene_document.pivot(&[artboard], font_cache).unwrap_or_default();
let root = document.graphene_document.root.transform;
let pivot = root.inverse().transform_point2(pivot);
bounds.center_of_transformation = pivot;
@ -209,7 +212,7 @@ impl Fsm for ArtboardToolFsmState {
responses.push_back(BroadcastEvent::DocumentIsDirty.into());
if let Some(intersection) = intersection.last() {
tool_data.selected_board = Some(intersection[0]);
tool_data.selected_artboard = Some(intersection[0]);
tool_data
.snap_manager
@ -226,20 +229,7 @@ impl Fsm for ArtboardToolFsmState {
ArtboardToolFsmState::Dragging
} else {
let id = generate_uuid();
tool_data.selected_board = Some(id);
tool_data.snap_manager.start_snap(document, document.bounding_boxes(None, Some(id), font_cache), true, true);
tool_data.snap_manager.add_all_document_handles(document, &[], &[], &[]);
responses.push_back(
ArtboardMessage::AddArtboard {
id: Some(id),
position: (0., 0.),
size: (0., 0.),
}
.into(),
);
tool_data.selected_artboard = None;
responses.push_back(PropertiesPanelMessage::ClearSelection.into());
@ -259,7 +249,7 @@ impl Fsm for ArtboardToolFsmState {
let (position, size) = movement.new_size(snapped_mouse_position, bounds.transform, from_center, bounds.center_of_transformation, constrain_square);
responses.push_back(
ArtboardMessage::ResizeArtboard {
artboard: tool_data.selected_board.unwrap(),
artboard: tool_data.selected_artboard.unwrap(),
position: position.round().into(),
size: size.round().into(),
}
@ -287,7 +277,7 @@ impl Fsm for ArtboardToolFsmState {
responses.push_back(
ArtboardMessage::ResizeArtboard {
artboard: tool_data.selected_board.unwrap(),
artboard: tool_data.selected_artboard.unwrap(),
position: position.round().into(),
size: size.round().into(),
}
@ -321,20 +311,37 @@ impl Fsm for ArtboardToolFsmState {
let start = root_transform.transform_point2(start);
let size = root_transform.transform_vector2(size);
responses.push_back(
ArtboardMessage::ResizeArtboard {
artboard: tool_data.selected_board.unwrap(),
position: start.round().into(),
size: size.round().into(),
}
.into(),
);
if let Some(artboard) = tool_data.selected_artboard {
responses.push_back(
ArtboardMessage::ResizeArtboard {
artboard,
position: start.round().into(),
size: size.round().into(),
}
.into(),
);
} else {
let id = generate_uuid();
tool_data.selected_artboard = Some(id);
tool_data.snap_manager.start_snap(document, document.bounding_boxes(None, Some(id), font_cache), true, true);
tool_data.snap_manager.add_all_document_handles(document, &[], &[], &[]);
responses.push_back(
ArtboardMessage::AddArtboard {
id: Some(id),
position: start.round().into(),
size: (1., 1.),
}
.into(),
);
}
// Have to put message here instead of when Artboard is created
// This might result in a few more calls but it is not reliant on the order of messages
responses.push_back(
PropertiesPanelMessage::SetActiveLayers {
paths: vec![vec![tool_data.selected_board.unwrap()]],
paths: vec![vec![tool_data.selected_artboard.unwrap()]],
document: TargetDocument::Artboard,
}
.into(),
@ -384,7 +391,7 @@ impl Fsm for ArtboardToolFsmState {
ArtboardToolFsmState::Ready
}
(_, ArtboardToolMessage::DeleteSelected) => {
if let Some(artboard) = tool_data.selected_board.take() {
if let Some(artboard) = tool_data.selected_artboard.take() {
responses.push_back(ArtboardMessage::DeleteArtboard { artboard }.into());
responses.push_back(BroadcastEvent::DocumentIsDirty.into());
}
@ -394,7 +401,7 @@ impl Fsm for ArtboardToolFsmState {
if let Some(bounds) = &mut tool_data.bounding_box_overlays {
responses.push_back(
ArtboardMessage::ResizeArtboard {
artboard: tool_data.selected_board.unwrap(),
artboard: tool_data.selected_artboard.unwrap(),
position: (bounds.bounds[0].x + delta_x, bounds.bounds[0].y + delta_y),
size: (bounds.bounds[1] - bounds.bounds[0]).round().into(),
}