Skip to content

Commit 1512c4a

Browse files
committed
Merge branch 'master' into rfc-dropdowns-refactor
2 parents 672e6c8 + a376832 commit 1512c4a

22 files changed

+1611
-1192
lines changed

demo-artwork/changing-seasons.graphite

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

demo-artwork/procedural-string-lights.graphite

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

editor/src/messages/portfolio/document/document_message_handler.rs

+114
Original file line numberDiff line numberDiff line change
@@ -2785,6 +2785,7 @@ mod document_message_handler_tests {
27852785
assert!(!selected_nodes.selected_layers_contains(layers[1], document.metadata()));
27862786
assert!(selected_nodes.selected_layers_contains(layers[2], document.metadata()));
27872787
}
2788+
27882789
#[tokio::test]
27892790
async fn test_layer_rearrangement() {
27902791
let mut editor = EditorTestUtils::create();
@@ -2831,6 +2832,7 @@ mod document_message_handler_tests {
28312832
let new_index_middle = get_layer_index(&mut editor, layer_middle).await.unwrap();
28322833
assert!(new_index_middle < initial_index_middle, "Middle layer should have moved up");
28332834
}
2835+
28342836
#[tokio::test]
28352837
async fn test_move_folder_into_itself_doesnt_crash() {
28362838
let mut editor = EditorTestUtils::create();
@@ -2859,4 +2861,116 @@ mod document_message_handler_tests {
28592861
editor.handle_message(DocumentMessage::CreateEmptyFolder).await;
28602862
assert!(true, "Application didn't crash after folder move operation");
28612863
}
2864+
#[tokio::test]
2865+
async fn test_moving_folder_with_children() {
2866+
let mut editor = EditorTestUtils::create();
2867+
editor.new_document().await;
2868+
2869+
// Creating two folders at root level
2870+
editor.handle_message(DocumentMessage::CreateEmptyFolder).await;
2871+
editor.handle_message(DocumentMessage::CreateEmptyFolder).await;
2872+
2873+
let folder1 = editor.active_document().metadata().all_layers().next().unwrap();
2874+
let folder2 = editor.active_document().metadata().all_layers().nth(1).unwrap();
2875+
2876+
editor.drag_tool(ToolType::Rectangle, 0., 0., 100., 100., ModifierKeys::empty()).await;
2877+
let rect_layer = editor.active_document().metadata().all_layers().next().unwrap();
2878+
2879+
// First move rectangle into folder1
2880+
editor.handle_message(NodeGraphMessage::SelectedNodesSet { nodes: vec![rect_layer.to_node()] }).await;
2881+
editor.handle_message(DocumentMessage::MoveSelectedLayersTo { parent: folder1, insert_index: 0 }).await;
2882+
2883+
// Verifying rectagle is now in folder1
2884+
let rect_parent = rect_layer.parent(editor.active_document().metadata()).unwrap();
2885+
assert_eq!(rect_parent, folder1, "Rectangle should be inside folder1");
2886+
2887+
// Moving folder1 into folder2
2888+
editor.handle_message(NodeGraphMessage::SelectedNodesSet { nodes: vec![folder1.to_node()] }).await;
2889+
editor.handle_message(DocumentMessage::MoveSelectedLayersTo { parent: folder2, insert_index: 0 }).await;
2890+
2891+
// Verifing hirarchy: folder2 > folder1 > rectangle
2892+
let document = editor.active_document();
2893+
let folder1_parent = folder1.parent(document.metadata()).unwrap();
2894+
assert_eq!(folder1_parent, folder2, "Folder1 should be inside folder2");
2895+
2896+
// Verifing rectangle moved with its parent
2897+
let rect_parent = rect_layer.parent(document.metadata()).unwrap();
2898+
assert_eq!(rect_parent, folder1, "Rectangle should still be inside folder1");
2899+
2900+
let rect_grandparent = rect_parent.parent(document.metadata()).unwrap();
2901+
assert_eq!(rect_grandparent, folder2, "Rectangle's grandparent should be folder2");
2902+
}
2903+
2904+
#[tokio::test]
2905+
async fn test_moving_layers_retains_transforms() {
2906+
let mut editor = EditorTestUtils::create();
2907+
editor.new_document().await;
2908+
2909+
editor.handle_message(DocumentMessage::CreateEmptyFolder).await;
2910+
editor.handle_message(DocumentMessage::CreateEmptyFolder).await;
2911+
2912+
let folder2 = editor.active_document().metadata().all_layers().next().unwrap();
2913+
let folder1 = editor.active_document().metadata().all_layers().nth(1).unwrap();
2914+
2915+
// Applying transform to folder1 (translation)
2916+
editor.handle_message(NodeGraphMessage::SelectedNodesSet { nodes: vec![folder1.to_node()] }).await;
2917+
editor.handle_message(TransformLayerMessage::BeginGrab).await;
2918+
editor.move_mouse(100.0, 50.0, ModifierKeys::empty(), MouseKeys::NONE).await;
2919+
editor
2920+
.handle_message(TransformLayerMessage::PointerMove {
2921+
slow_key: Key::Shift,
2922+
increments_key: Key::Control,
2923+
})
2924+
.await;
2925+
editor.handle_message(TransformLayerMessage::ApplyTransformOperation { final_transform: true }).await;
2926+
2927+
// Applying different transform to folder2 (translation)
2928+
editor.handle_message(NodeGraphMessage::SelectedNodesSet { nodes: vec![folder2.to_node()] }).await;
2929+
editor.handle_message(TransformLayerMessage::BeginGrab).await;
2930+
editor.move_mouse(200.0, 100.0, ModifierKeys::empty(), MouseKeys::NONE).await;
2931+
editor
2932+
.handle_message(TransformLayerMessage::PointerMove {
2933+
slow_key: Key::Shift,
2934+
increments_key: Key::Control,
2935+
})
2936+
.await;
2937+
editor.handle_message(TransformLayerMessage::ApplyTransformOperation { final_transform: true }).await;
2938+
2939+
// Creating rectangle in folder1
2940+
editor.handle_message(NodeGraphMessage::SelectedNodesSet { nodes: vec![folder1.to_node()] }).await;
2941+
editor.drag_tool(ToolType::Rectangle, 0., 0., 100., 100., ModifierKeys::empty()).await;
2942+
let rect_layer = editor.active_document().metadata().all_layers().next().unwrap();
2943+
2944+
// Moving the rectangle to folder1 to ensure it's inside
2945+
editor.handle_message(NodeGraphMessage::SelectedNodesSet { nodes: vec![rect_layer.to_node()] }).await;
2946+
editor.handle_message(DocumentMessage::MoveSelectedLayersTo { parent: folder1, insert_index: 0 }).await;
2947+
2948+
editor.handle_message(TransformLayerMessage::BeginGrab).await;
2949+
editor.move_mouse(50.0, 25.0, ModifierKeys::empty(), MouseKeys::NONE).await;
2950+
editor
2951+
.handle_message(TransformLayerMessage::PointerMove {
2952+
slow_key: Key::Shift,
2953+
increments_key: Key::Control,
2954+
})
2955+
.await;
2956+
editor.handle_message(TransformLayerMessage::ApplyTransformOperation { final_transform: true }).await;
2957+
2958+
// Rectangle's viewport position before moving
2959+
let document = editor.active_document();
2960+
let rect_bbox_before = document.metadata().bounding_box_viewport(rect_layer).unwrap();
2961+
2962+
// Moving rectangle from folder1 --> folder2
2963+
editor.handle_message(DocumentMessage::MoveSelectedLayersTo { parent: folder2, insert_index: 0 }).await;
2964+
2965+
// Rectangle's viewport position after moving
2966+
let document = editor.active_document();
2967+
let rect_bbox_after = document.metadata().bounding_box_viewport(rect_layer).unwrap();
2968+
2969+
// Verifing the rectangle maintains approximately the same position in viewport space
2970+
let before_center = (rect_bbox_before[0] + rect_bbox_before[1]) / 2.0;
2971+
let after_center = (rect_bbox_after[0] + rect_bbox_after[1]) / 2.0;
2972+
let distance = before_center.distance(after_center);
2973+
2974+
assert!(distance < 1.0, "Rectangle should maintain its viewport position after moving between transformed groups");
2975+
}
28622976
}

0 commit comments

Comments
 (0)