diff --git a/.serena/memories/common/component-swap-pipeline.md b/.serena/memories/common/component-swap-pipeline.md index cffcb524be..7494dc905b 100644 --- a/.serena/memories/common/component-swap-pipeline.md +++ b/.serena/memories/common/component-swap-pipeline.md @@ -48,3 +48,8 @@ The clean target already has the copy's rotation, which can turn 100 into 99.99999999999994. Exact dimension equality drops valid resize overrides (F160). Fixed layout sizes and composite geometry use the same tolerance; nongeometry scalar attributes still compare exactly. + +After carrying geometry, the switch syncs its new subtree once from the +updated builder objects. Untouched children must follow a retained root +size through constraints; copying only root attrs leaves them in the old +frame (F162). The direct sync keeps carried groups and child swaps. diff --git a/common/src/app/common/logic/libraries.cljc b/common/src/app/common/logic/libraries.cljc index a60e083bbb..b6732279b7 100644 --- a/common/src/app/common/logic/libraries.cljc +++ b/common/src/app/common/logic/libraries.cljc @@ -285,7 +285,7 @@ (reduce #(update %1 %2 turn) objects (cfh/get-children-ids-with-self objects (:id shape-main))))))))) -(defn- generate-sync-shape-direct +(defn generate-sync-shape-direct "Generate changes to synchronize one shape that is the root of a component instance, and all its children, from the given component." [changes file libraries container shape-id reset?] diff --git a/common/src/app/common/logic/variants.cljc b/common/src/app/common/logic/variants.cljc index c887e3a4fb..6afbcf53cf 100644 --- a/common/src/app/common/logic/variants.cljc +++ b/common/src/app/common/logic/variants.cljc @@ -430,7 +430,14 @@ (ctk/touched-group? % :geometry-group)) orig-touched) (keep-orientation-override original-shape new-shape page (or (get-in libraries [(:component-file new-shape) :data]) ldata) - (:component-id new-shape) nil))] + (:component-id new-shape) nil)) + ;; A carried size changes the frame its untouched children follow. + ;; Place them through the same constraints as an ordinary copy sync. + changes (cond-> changes + (some #(ctk/touched-group? % :geometry-group) orig-touched) + (cll/generate-sync-shape-direct + nil libraries (assoc container :objects (pcb/get-objects changes)) + (:id new-shape) false))] [changes (mapv (comp :parent-id :new) pairs)])) (defn- shape-index diff --git a/common/test/common_tests/logic/variants_switch_test.cljc b/common/test/common_tests/logic/variants_switch_test.cljc index 35acbf5c2b..3ff93e59e5 100644 --- a/common/test/common_tests/logic/variants_switch_test.cljc +++ b/common/test/common_tests/logic/variants_switch_test.cljc @@ -49,6 +49,34 @@ (t/is (mth/close? 80 (get-in copy [:selrect :height]) 1e-10)) (t/is (contains? (:touched copy) :geometry-group))))) +(t/deftest switch-places-children-through-a-carried-root-resize + (doseq [angle [0 45]] + (let [root-params {:width 100 :height 100} + child-params {:x 10 :y 10 :width 20 :height 20 + :constraints-h :left :constraints-v :top} + file (-> (thf/sample-file :file1) + (thv/add-variant-with-child + :v01 :c01 :m01 :c02 :m02 :r01 :r02 + {:variant1-params root-params :variant2-params root-params + :child1-params child-params :child2-params child-params}) + (thc/instantiate-component :c01 :copy01)) + file (reduce (fn [file modifiers] + (let [shape (ths/get-shape file :copy01)] + (thf/apply-changes file + (n/transform-changes (thf/current-page file) shape + (modifiers shape))))) + file [#(ctm/rotation-modifiers % (gsh/shape->center %) angle) + #(ctm/change-size % nil 80)]) + switched (tho/swap-component-in-shape file :copy01 :c02 {:keep-touched? true}) + relative (fn [file] + (let [root (ths/get-shape file :copy01) + child (get-in (thf/current-page file) [:objects (first (:shapes root))])] + (gpt/subtract (first (:points child)) (first (:points root))))) + child (get-in (thf/current-page switched) + [:objects (first (:shapes (ths/get-shape switched :copy01)))])] + (t/is (< (gpt/distance (relative file) (relative switched)) 0.01)) + (t/is (empty? (:touched child)))))) + ;; ============================================================ ;; BASIC SWITCH TESTS (no overrides) ;; ============================================================