mirror of
https://github.com/penpot/penpot.git
synced 2026-10-29 14:00:37 +00:00
🐛 Place reset replacement children in the main frame
Reset clears the parent's geometry override, but replacing a swapped child cloned its new children through the parent's old rotation. Drop that override from the whole sync context so existing and new children use the main's orientation in the same undo group. F185: portable checks at 45 and 90 degrees fail six assertions before the fix and pass all fourteen after it. Original and shrunk programs pass. The focused suite passes 139 tests / 2590 assertions with unchanged goldens. Live WASM checks reset placement, exact undo/redo, later sync and no phantom overrides at both angles. Frontend passes 1538 tests / 9253 assertions; plugin 68 cases, lint/format and isolated Stage 3 checks pass. Common JVM/JS, backend and exporter suites pass. Phase 1e benchmark ratios: mains 10/100/1000 .50/.55/.57, levels .50, chain .50, library .52, many shapes .42, variant switch .60. AI-assisted-by: GPT-6
This commit is contained in:
parent
c79b97c34f
commit
a568b1d6cf
@ -72,3 +72,9 @@ change builder (F182). Its content and position reference can have different
|
||||
sizes, so rotating the content rigidly can leave its untransformed anchor
|
||||
different from full sync. Keep the swapped head/children untouched and put
|
||||
the derived correction in the same undo group. Authored geometry stays.
|
||||
|
||||
Reset drops the root's geometry override from the whole sync context
|
||||
(F185), including the branch that clones replacement children. Clearing it
|
||||
only while updating existing shapes can turn a newly added child by the
|
||||
old override after its parent has already reset. The reset and replacement
|
||||
children share one undo group and stay stable through later sync.
|
||||
|
||||
@ -321,7 +321,8 @@
|
||||
:main-container main-container
|
||||
:component component
|
||||
:library library
|
||||
:root-inst shape-inst
|
||||
;; Reset also places new children in the main's frame.
|
||||
:root-inst (cond-> shape-inst reset? (dissoc :touched))
|
||||
:root-main shape-main
|
||||
:reset? reset?}
|
||||
shape-inst
|
||||
@ -366,10 +367,7 @@
|
||||
as it follows its near main."
|
||||
[changes {:keys [container main-container root-inst root-main reset?]}
|
||||
shape-inst shape-main]
|
||||
(let [omit-touched? (not reset?)
|
||||
;; Reset takes the main's orientation too. Its old geometry override
|
||||
;; must not turn the main into the copy's frame before overwriting it.
|
||||
root-inst (cond-> root-inst reset? (dissoc :touched))]
|
||||
(let [omit-touched? (not reset?)]
|
||||
(cond-> (update-attrs changes shape-inst shape-main root-inst root-main container omit-touched?)
|
||||
;; the children refer to the children of `shape-main`, in the
|
||||
;; container of the walk's main shapes
|
||||
|
||||
@ -36,6 +36,40 @@
|
||||
|
||||
(t/use-fixtures :each thi/test-fixture)
|
||||
|
||||
(t/deftest resetting-a-turned-copy-places-replacement-children-in-the-main-frame
|
||||
(doseq [angle [45 90]]
|
||||
(let [file (-> (thf/sample-file :file)
|
||||
(tho/add-simple-component :a :main-a :rect-a
|
||||
:root-params {:width 100 :height 100}
|
||||
:child-params {:width 20 :height 20 :x 10 :y 10})
|
||||
(tho/add-simple-component :other :main-other :rect-other
|
||||
:root-params {:width 100 :height 100}
|
||||
:child-params {:width 20 :height 20 :x 10 :y 10})
|
||||
(tho/add-frame :main-b {:width 200 :height 200})
|
||||
(thc/instantiate-component :a :b-a :parent-label :main-b)
|
||||
(thc/make-component :b :main-b)
|
||||
(thc/instantiate-component :b :copy-b :children-labels [:copy-a]))
|
||||
turned (-> (tm/make-situation file)
|
||||
(r/step (n/swap-shape :copy-a :other)) r/settle
|
||||
(r/step (n/rotate :copy-b angle)) r/settle)
|
||||
reset (-> turned (r/step (n/reset :copy-b)) r/settle)
|
||||
head (tm/resolve-shape reset :copy-a)
|
||||
child (tm/shape-by-id reset (first (:shapes head)))
|
||||
expected (gsh/move (ths/get-shape file :rect-a)
|
||||
(gpt/subtract (gsh/shape->center head)
|
||||
(gsh/shape->center (ths/get-shape file :main-a))))
|
||||
file (tm/file reset)
|
||||
full (:file (r/sync-cascade file {} (keys (get-in file [:data :components]))))]
|
||||
(t/is (mth/close? 0 (:rotation head) 0.001))
|
||||
(t/is (mth/close? 0 (:rotation child) 0.001))
|
||||
(t/is (empty? (:touched head)))
|
||||
(t/is (empty? (:touched child)))
|
||||
(t/is (gsh/close-attrs? :points (:points expected) (:points child) 0.001))
|
||||
(t/is (gsh/close-attrs? :points (:points child)
|
||||
(:points (ths/get-shape-by-id full (:id child))) 0.001))
|
||||
(t/is (= (thn/normalize-file (tm/file turned))
|
||||
(thn/normalize-file (tm/file (r/step reset (n/undo)))))))))
|
||||
|
||||
(t/deftest turning-a-parent-settles-a-swapped-head-with-a-different-position-size
|
||||
(doseq [angle [45 90]]
|
||||
(let [file (-> (thf/sample-file :file)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user