diff --git a/common/src/app/common/logic/libraries.cljc b/common/src/app/common/logic/libraries.cljc index eb38afe4fb..8025cdf736 100644 --- a/common/src/app/common/logic/libraries.cljc +++ b/common/src/app/common/logic/libraries.cljc @@ -2416,19 +2416,20 @@ (assoc attr (get origin attr))))) dest)))) -(defn- update-swapped-placement - "Synchronizes a swapped copy head with the main shape it replaces, in the - attributes that place it in its parent: position, constraints and layout - item attributes. Its content comes from its own component. A position set - by a layout is left to the layout." - [changes shape-inst shape-main root-inst root-main container] - (let [objects (:objects container) - touched (get shape-inst :touched #{}) +(defn generate-take-placement + "Give the swapped copy head `shape-inst` the placement of `placed`, the + shape whose position it takes, expressed in the same coordinates: the + attributes that place it in its parent (position, constraints and layout + item attributes) that the user did not change. Its content comes from its + own component. With `layout-placed?`, the position is left to the layout. + `objects` holds the subtree of `shape-inst`, which moves with it." + [changes shape-inst placed objects layout-placed?] + (let [touched (get shape-inst :touched #{}) untouched? (fn [attr] (not (touched (ctk/resolve-sync-group (:type shape-inst) attr)))) placement (reduce (fn [attrs attr] - (let [value (get shape-main attr)] + (let [value (get placed attr)] (if (and (untouched? attr) (not= value (get shape-inst attr))) (assoc attrs attr value) @@ -2439,12 +2440,10 @@ position (fn [shape] (gpt/point (dm/get-in shape [:selrect :x]) (dm/get-in shape [:selrect :y]))) - delta (gpt/subtract (position (reposition-shape shape-main root-main root-inst)) - (position shape-inst)) + delta (gpt/subtract (position placed) (position shape-inst)) move? (and (untouched? :x) - (not (gpt/almost-zero? delta)) - (or (not (ctsl/any-layout-immediate-child? objects shape-inst)) - (ctsl/position-absolute? shape-inst)))] + (not layout-placed?) + (not (gpt/almost-zero? delta)))] (cond-> changes (seq placement) (pcb/update-shapes [(:id shape-inst)] @@ -2462,6 +2461,18 @@ #(gsh/move % delta) {:ignore-touched true})))) +(defn- update-swapped-placement + "Synchronizes a swapped copy head with the main shape it replaces, in the + attributes that place it in its parent." + [changes shape-inst shape-main root-inst root-main container] + (let [objects (:objects container)] + (generate-take-placement changes + shape-inst + (reposition-shape shape-main root-main root-inst) + objects + (and (ctsl/any-layout-immediate-child? objects shape-inst) + (not (ctsl/position-absolute? shape-inst)))))) + (defn- update-flex-child-copy-attrs "Synchronizes the attributes inside the flex-child items (main->copy)" [changes shape-main shape-copy main-container main-component copy-container omit-touched?] diff --git a/common/src/app/common/logic/variants.cljc b/common/src/app/common/logic/variants.cljc index e9d550388f..612cc8f7a5 100644 --- a/common/src/app/common/logic/variants.cljc +++ b/common/src/app/common/logic/variants.cljc @@ -102,6 +102,13 @@ (= (:component-file %) (:component-file related-shape-in-new))) (ctk/remove-swap-group))) + ;; and its placement, as sync would give it + (cll/generate-take-placement orig-swapped-child + related-shape-in-new + objects + (and (ctsl/any-layout-immediate-child? objects related-shape-in-new) + (not (ctsl/position-absolute? orig-swapped-child)))) + ;; Delete new non-swapped item (cls/generate-delete-shapes ldata page objects (d/ordered-set (:id related-shape-in-new)) {:allow-altering-copies true}) second))) diff --git a/common/test/common_tests/logic/swap_group_test.cljc b/common/test/common_tests/logic/swap_group_test.cljc index f199c5e23e..61d7b629af 100644 --- a/common/test/common_tests/logic/swap_group_test.cljc +++ b/common/test/common_tests/logic/swap_group_test.cljc @@ -475,3 +475,14 @@ (propagate :card) (thf/validate-file!))] (t/is (= margin (:layout-item-margin (ths/get-shape file :copy-star)))))) + +(t/deftest switch-places-the-swap-where-the-new-variant-has-its-child + (let [file (-> (setup-variants) + (move-shape :child2 30 5)) + rel (fn [file child parent] + (let [[x y] (position file child) + [px py] (position file parent)] + [(- x px) (- y py)])) + file' (tho/swap-component-in-shape file :copy01 :c02 {:keep-touched? true})] + (t/is (ctk/swapped? (ths/get-shape file' :copy-child))) + (t/is (= (rel file' :child2 :m02) (rel file' :copy-child :copy01)))))