diff --git a/common/src/app/common/logic/variants.cljc b/common/src/app/common/logic/variants.cljc index 5947d4dc95..e022f29e74 100644 --- a/common/src/app/common/logic/variants.cljc +++ b/common/src/app/common/logic/variants.cljc @@ -435,8 +435,9 @@ "The variant component that the variant copy head `shape` switches to when its property at position `pos` takes the value `val`: among the other variants with that value, the one whose properties are nearest to the - current ones. Nil when the property already has that value or no variant - has it." + current ones; between equally near ones, the first among the children of + the variant container. Nil when the property already has that value or no + variant has it." [libraries shape pos val] (let [component-id (:component-id shape) component (ctf/get-component libraries (:component-file shape) component-id @@ -446,12 +447,16 @@ objects (-> (ctf/get-component-page ldata component) :objects) target-props (-> (:variant-properties component) (update pos assoc :value val)) + distance #(ctv/distance target-props (:variant-properties %)) + ;; in the order of the container's children candidates (->> (cfv/find-variant-components ldata objects (:variant-id component)) (remove #(= (:id %) component-id)) (filter #(= (get-in % [:variant-properties pos :value]) val)) (reverse))] - (when (seq candidates) - (apply min-key #(ctv/distance target-props (:variant-properties %)) candidates)))))) + (reduce (fn [nearest candidate] + (if (< (distance candidate) (distance nearest)) candidate nearest)) + (first candidates) + (rest candidates)))))) (defn valid-switch? "Whether the variant copy head `shape` can switch its property at position diff --git a/common/test/common_tests/logic/variants_switch_target_test.cljc b/common/test/common_tests/logic/variants_switch_target_test.cljc index c098fb6004..58ca9ed299 100644 --- a/common/test/common_tests/logic/variants_switch_target_test.cljc +++ b/common/test/common_tests/logic/variants_switch_target_test.cljc @@ -66,6 +66,25 @@ target (clv/find-switch-target (libraries file) (ths/get-shape file :copy01) 0 "p1v2")] (t/is (= (thi/id :c03) (:id target))))) +(t/deftest switch-target-between-equally-near-variants-is-the-first-of-the-container + ;; From p1v1, p2v1, setting Property 1 to p1v2 can give c02 (p1v2, p2v2) or + ;; c03 (p1v2, p2v3), both one value away; the one placed first among the + ;; container's children wins. + (let [file (-> (thf/sample-file :file1) + (thv/add-variant-two-properties :v01 :c01 :m01 :c02 :m02) + (ths/add-sample-shape :m03 :type :frame :parent-label :v01 + :variant-id (thi/id :v01) :variant-name "p1v2, p2v3") + (thc/make-component :c03 :m03) + (thc/update-component :c03 {:variant-id (thi/id :v01) + :variant-properties [{:name "Property 1" :value "p1v2"} + {:name "Property 2" :value "p2v3"}]}) + (thc/instantiate-component :c01 :copy01)) + target (fn [order] + (let [file (ths/update-shape file :v01 :shapes (mapv thi/id order))] + (:id (clv/find-switch-target (libraries file) (ths/get-shape file :copy01) 0 "p1v2"))))] + (t/is (= (thi/id :c02) (target [:m01 :m02 :m03]))) + (t/is (= (thi/id :c03) (target [:m01 :m03 :m02]))))) + (t/deftest switch-into-own-main-is-a-nesting-loop (let [file (-> (thf/sample-file :file1) (thv/add-variant :v01 :c01 :m01 :c02 :m02)