Merge pull request #262 from uxbox/other/coll-of-issues

Fixes
This commit is contained in:
Hirunatan 2020-06-16 15:51:47 +02:00 committed by GitHub
commit 249a9558f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 147 additions and 257 deletions

View File

@ -165,115 +165,6 @@
res (cp/process-changes data [chg])] res (cp/process-changes data [chg])]
(t/is (= 0 (count (:objects res)))))) (t/is (= 0 (count (:objects res))))))
(t/deftest process-change-mod-obj-abs-order
(let [id1 (uuid/next)
id2 (uuid/next)
id3 (uuid/next)
data (-> cp/default-page-data
(assoc-in [:objects uuid/zero :shapes] [id1 id2 id3]))]
(t/testing "abs order 1"
(let [chg {:type :mod-obj
:id uuid/zero
:operations [{:type :abs-order
:id id3
:index 0}]}
res (cp/process-changes data [chg])]
;; (clojure.pprint/pprint data)
;; (clojure.pprint/pprint res)
(t/is (= [id3 id1 id2] (get-in res [:objects uuid/zero :shapes])))))
(t/testing "abs order 2"
(let [chg {:type :mod-obj
:id uuid/zero
:operations [{:type :abs-order
:id id1
:index 100}]}
res (cp/process-changes data [chg])]
;; (clojure.pprint/pprint data)
;; (clojure.pprint/pprint res)
(t/is (= [id2 id3 id1] (get-in res [:objects uuid/zero :shapes])))))
(t/testing "abs order 3"
(let [chg {:type :mod-obj
:id uuid/zero
:operations [{:type :abs-order
:id id3
:index 1}]}
res (cp/process-changes data [chg])]
;; (clojure.pprint/pprint data)
;; (clojure.pprint/pprint res)
(t/is (= [id1 id3 id2] (get-in res [:objects uuid/zero :shapes])))))
))
(t/deftest process-change-mod-obj-rel-order
(let [id1 (uuid/next)
id2 (uuid/next)
id3 (uuid/next)
data (-> cp/default-page-data
(assoc-in [:objects uuid/zero :shapes] [id1 id2 id3]))]
(t/testing "rel order 1"
(let [chg {:type :mod-obj
:id uuid/zero
:operations [{:type :rel-order
:id id3
:loc :down}]}
res (cp/process-changes data [chg])]
;; (clojure.pprint/pprint data)
;; (clojure.pprint/pprint res)
(t/is (= [id1 id3 id2] (get-in res [:objects uuid/zero :shapes])))))
(t/testing "rel order 2"
(let [chg {:type :mod-obj
:id uuid/zero
:operations [{:type :rel-order
:id id1
:loc :top}]}
res (cp/process-changes data [chg])]
;; (clojure.pprint/pprint data)
;; (clojure.pprint/pprint res)
(t/is (= [id2 id3 id1] (get-in res [:objects uuid/zero :shapes])))))
(t/testing "rel order 3"
(let [chg {:type :mod-obj
:id uuid/zero
:operations [{:type :rel-order
:id id2
:loc :up}]}
res (cp/process-changes data [chg])]
;; (clojure.pprint/pprint data)
;; (clojure.pprint/pprint res)
(t/is (= [id1 id3 id2] (get-in res [:objects uuid/zero :shapes])))))
(t/testing "rel order 4"
(let [chg {:type :mod-obj
:id uuid/zero
:operations [{:type :rel-order
:id id3
:loc :bottom}]}
res (cp/process-changes data [chg])]
;; (clojure.pprint/pprint data)
;; (clojure.pprint/pprint res)
(t/is (= [id3 id1 id2] (get-in res [:objects uuid/zero :shapes])))))
))
(t/deftest process-change-move-objects (t/deftest process-change-move-objects
(let [frame-a-id (uuid/custom 1) (let [frame-a-id (uuid/custom 1)
frame-b-id (uuid/custom 2) frame-b-id (uuid/custom 2)

View File

@ -255,15 +255,17 @@
(declare transform-shape-point) (declare transform-shape-point)
(defn shape->points [shape] (defn shape->points [shape]
(let [points (let [points (case (:type shape)
(case (:type shape) (:curve :path) (:segments shape)
(:curve :path) (:segments shape) (let [{:keys [x y width height]} shape]
(let [{:keys [x y width height]} shape] [(gpt/point x y)
[(gpt/point x y) (gpt/point (+ x width) y)
(gpt/point (+ x width) y) (gpt/point (+ x width) (+ y height))
(gpt/point (+ x width) (+ y height)) (gpt/point x (+ y height))]))]
(gpt/point x (+ y height))]))] (->> points
(mapv #(transform-shape-point % shape (:transform shape (gmt/matrix))) points))) (map #(transform-shape-point % shape (:transform shape (gmt/matrix))))
(map gpt/round)
(vec))))
(defn points->selrect [points] (defn points->selrect [points]
(let [minx (transduce (map :x) min ##Inf points) (let [minx (transduce (map :x) min ##Inf points)
@ -756,8 +758,10 @@
new-shape (as-> shape $ new-shape (as-> shape $
(merge $ rec) (merge $ rec)
(update $ :x #(mth/precision % 2)) (update $ :x #(mth/precision % 0))
(update $ :y #(mth/precision % 2)) (update $ :y #(mth/precision % 0))
(update $ :width #(mth/precision % 0))
(update $ :height #(mth/precision % 0))
(fix-invalid-rect-values $) (fix-invalid-rect-values $)
(update $ :transform #(gmt/multiply (or % (gmt/matrix)) stretch-matrix)) (update $ :transform #(gmt/multiply (or % (gmt/matrix)) stretch-matrix))
(update $ :transform-inverse #(gmt/multiply stretch-matrix-inverse (or % (gmt/matrix)))) (update $ :transform-inverse #(gmt/multiply stretch-matrix-inverse (or % (gmt/matrix))))
@ -766,7 +770,6 @@
(update $ :rotation #(mod (+ % (get-in $ [:modifiers :rotation] 0)) 360)) (update $ :rotation #(mod (+ % (get-in $ [:modifiers :rotation] 0)) 360))
)] )]
new-shape)) new-shape))
(declare update-path-selrect) (declare update-path-selrect)

View File

@ -98,8 +98,8 @@
(defn precision (defn precision
[v n] [v n]
(when (and (number? v) (number? n)) (when (and (number? v) (number? n))
#?(:cljs (js/parseFloat (.toFixed v n)) (let [d (pow 10 n)]
:clj (.. (BigDecimal/valueOf v) (setScale n java.math.RoundingMode/HALF_UP) (doubleValue))))) (/ (round (* v d)) d))))
(defn radians (defn radians
"Converts degrees to radians." "Converts degrees to radians."

View File

@ -156,21 +156,14 @@
(s/def ::ids (s/coll-of ::us/uuid)) (s/def ::ids (s/coll-of ::us/uuid))
(s/def ::attr keyword?) (s/def ::attr keyword?)
(s/def ::val any?) (s/def ::val any?)
(s/def ::frame-id uuid?) (s/def ::frame-id uuid?)
(s/def ::loc #{:top :bottom :up :down})
(defmulti operation-spec-impl :type) (defmulti operation-spec-impl :type)
(defmethod operation-spec-impl :set [_] (defmethod operation-spec-impl :set [_]
(s/keys :req-un [::attr ::val])) (s/keys :req-un [::attr ::val]))
(defmethod operation-spec-impl :abs-order [_]
(s/keys :req-un [::id ::index]))
(defmethod operation-spec-impl :rel-order [_]
(s/keys :req-un [::id ::loc]))
(s/def ::operation (s/multi-spec operation-spec-impl :type)) (s/def ::operation (s/multi-spec operation-spec-impl :type))
(s/def ::operations (s/coll-of ::operation)) (s/def ::operations (s/coll-of ::operation))
@ -465,7 +458,6 @@
(reduce remove-from-old-parent $ shapes) (reduce remove-from-old-parent $ shapes)
(reduce update-frame-ids $ (get-in $ [:objects parent-id :shapes])))))) (reduce update-frame-ids $ (get-in $ [:objects parent-id :shapes]))))))
(defmethod process-operation :set (defmethod process-operation :set
[shape op] [shape op]
(let [attr (:attr op) (let [attr (:attr op)
@ -474,32 +466,6 @@
(dissoc shape attr) (dissoc shape attr)
(assoc shape attr val)))) (assoc shape attr val))))
(defmethod process-operation :abs-order
[obj {:keys [id index]}]
(assert (vector? (:shapes obj)) ":shapes should be a vector")
(update obj :shapes (fn [items]
(let [[b a] (->> (remove #(= % id) items)
(split-at index))]
(vec (concat b [id] a))))))
(defmethod process-operation :rel-order
[obj {:keys [id loc] :as change}]
(assert (vector? (:shapes obj)) ":shapes should be a vector")
(let [shapes (:shapes obj)
cindex (d/index-of shapes id)
nindex (case loc
:top (- (count shapes) 1)
:down (max 0 (- cindex 1))
:up (min (- (count shapes) 1) (inc cindex))
:bottom 0)]
(update obj :shapes
(fn [shapes]
(let [[fst snd] (->> (remove #(= % id) shapes)
(split-at nindex))]
(d/concat [] fst [id] snd))))))
(defmethod process-operation :default (defmethod process-operation :default
[shape op] [shape op]
(ex/raise :type :operation-not-implemented (ex/raise :type :operation-not-implemented

View File

@ -748,23 +748,33 @@
(ptk/reify ::vertical-order-selected-shpes (ptk/reify ::vertical-order-selected-shpes
ptk/WatchEvent ptk/WatchEvent
(watch [_ state stream] (watch [_ state stream]
(let [page-id (:current-page-id state) (let [page-id (:current-page-id state)
objects (get-in state [:workspace-data page-id :objects]) objects (get-in state [:workspace-data page-id :objects])
selected (seq (get-in state [:workspace-local :selected])) selected (get-in state [:workspace-local :selected])
rchanges (mapv (fn [id] rchanges (mapv (fn [id]
(let [frame-id (get-in objects [id :frame-id])] (let [obj (get objects id)
{:type :mod-obj parent (get objects (:parent-id obj))
:id frame-id shapes (:shapes parent)
:operations [{:type :rel-order :id id :loc loc}]})) cindex (d/index-of shapes id)
nindex (case loc
:top (count shapes)
:down (max 0 (- cindex 1))
:up (min (count shapes) (+ (inc cindex) 1))
:bottom 0)]
{:type :mov-objects
:parent-id (:parent-id obj)
:frame-id (:frame-id obj)
:index nindex
:shapes [id]}))
selected) selected)
uchanges (mapv (fn [id]
(let [frame-id (get-in objects [id :frame-id]) uchanges (mapv (fn [id]
shapes (get-in objects [frame-id :shapes]) (let [obj (get objects id)]
cindex (d/index-of shapes id)] {:type :mov-objects
{:type :mod-obj :parent-id (:parent-id obj)
:id frame-id :frame-id (:frame-id obj)
:operations [{:type :abs-order :id id :index cindex}]})) :shapes [id]
:index (cph/position-on-parent id objects)}))
selected)] selected)]
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})))))) (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))))))

View File

@ -76,24 +76,25 @@
[ma mb] [ma mb]
(let [ma-keys (set (keys ma)) (let [ma-keys (set (keys ma))
mb-keys (set (keys mb)) mb-keys (set (keys mb))
added (set/difference mb-keys ma-keys) added (set/difference mb-keys ma-keys)
removed (set/difference ma-keys mb-keys) removed (set/difference ma-keys mb-keys)
both (set/intersection ma-keys mb-keys)] both (set/intersection ma-keys mb-keys)]
(d/concat (d/concat
(mapv #(array-map :type :set :attr % :val (get mb %)) added) (mapv #(array-map :type :set :attr % :val (get mb %)) added)
(mapv #(array-map :type :set :attr % :val nil) removed) (mapv #(array-map :type :set :attr % :val nil) removed)
(loop [k (first both) (loop [items (seq both)
r (rest both) result []]
rs []] (if items
(if k (let [k (first items)
(let [vma (get ma k) vma (get ma k)
vmb (get mb k)] vmb (get mb k)]
(if (= vma vmb) (if (= vma vmb)
(recur (first r) (rest r) rs) (recur (next items) result)
(recur (first r) (rest r) (conj rs {:type :set (recur (next items)
:attr k (conj result {:type :set
:val vmb})))) :attr k
rs))))) :val vmb}))))
result)))))
(defn- generate-changes (defn- generate-changes
[prev curr] [prev curr]

View File

@ -211,7 +211,7 @@
(rx/filter #(> % 1)) (rx/filter #(> % 1))
(rx/take 1) (rx/take 1)
(rx/with-latest vector ms/mouse-position-alt) (rx/with-latest vector ms/mouse-position-alt)
(rx/flat-map (rx/mapcat
(fn [[_ alt?]] (fn [[_ alt?]]
(if alt? (if alt?
;; When alt is down we start a duplicate+move ;; When alt is down we start a duplicate+move
@ -242,15 +242,16 @@
(watch [_ state stream] (watch [_ state stream]
(let [page-id (get state :current-page-id) (let [page-id (get state :current-page-id)
objects (get-in state [:workspace-data page-id :objects]) objects (get-in state [:workspace-data page-id :objects])
ids (if (nil? ids) (get-in state [:workspace-local :selected]) ids) ids (if (nil? ids) (get-in state [:workspace-local :selected]) ids)
shapes (mapv #(get-in state [:workspace-data page-id :objects %]) ids) shapes (mapv #(get objects %) ids)
stopper (rx/filter ms/mouse-up? stream) stopper (rx/filter ms/mouse-up? stream)
layout (get state :workspace-layout)] layout (get state :workspace-layout)]
(rx/concat (rx/concat
(->> ms/mouse-position (->> ms/mouse-position
(rx/take-until stopper) (rx/take-until stopper)
(rx/map #(gpt/to-vec from-position %)) (rx/map #(gpt/to-vec from-position %))
(rx/switch-map #(snap/closest-snap-move page-id shapes objects layout %)) (rx/switch-map #(snap/closest-snap-move page-id shapes objects layout %))
(rx/map #(gpt/round % 0))
(rx/map gmt/translate-matrix) (rx/map gmt/translate-matrix)
(rx/map #(set-modifiers ids {:displacement %}))) (rx/map #(set-modifiers ids {:displacement %})))

View File

@ -23,7 +23,8 @@
(def ^:private snap-accuracy 5) (def ^:private snap-accuracy 5)
(def ^:private snap-distance-accuracy 10) (def ^:private snap-distance-accuracy 10)
(defn- remove-from-snap-points [remove-id?] (defn- remove-from-snap-points
[remove-id?]
(fn [query-result] (fn [query-result]
(->> query-result (->> query-result
(map (fn [[value data]] [value (remove (comp remove-id? second) data)])) (map (fn [[value data]] [value (remove (comp remove-id? second) data)]))
@ -57,12 +58,12 @@
:else zero))) :else zero)))
(defn get-snap-points [page-id frame-id filter-shapes point coord] (defn get-snap-points [page-id frame-id filter-shapes point coord]
(let [value (coord point)] (let [value (get point coord)]
(->> (uw/ask! {:cmd :snaps/range-query (->> (uw/ask! {:cmd :snaps/range-query
:page-id page-id :page-id page-id
:frame-id frame-id :frame-id frame-id
:coord coord :coord coord
:ranges [[(- value 1) (+ value 1)]]}) :ranges [[value value]]})
(rx/first) (rx/first)
(rx/map (remove-from-snap-points filter-shapes)) (rx/map (remove-from-snap-points filter-shapes))
(rx/map flatten-to-points)))) (rx/map flatten-to-points))))
@ -147,7 +148,8 @@
(if (mth/finite? min-snap) [0 min-snap] nil))))))) (if (mth/finite? min-snap) [0 min-snap] nil)))))))
(defn select-shapes-area [page-id shapes objects area-selrect] (defn select-shapes-area
[page-id shapes objects area-selrect]
(->> (uw/ask! {:cmd :selection/query (->> (uw/ask! {:cmd :selection/query
:page-id page-id :page-id page-id
:frame-id (->> shapes first :frame-id) :frame-id (->> shapes first :frame-id)
@ -155,13 +157,15 @@
(rx/map #(set/difference % (into #{} (map :id shapes)))) (rx/map #(set/difference % (into #{} (map :id shapes))))
(rx/map (fn [ids] (map #(get objects %) ids))))) (rx/map (fn [ids] (map #(get objects %) ids)))))
(defn closest-distance-snap [page-id shapes objects movev] (defn closest-distance-snap
[page-id shapes objects movev]
(->> (rx/of shapes) (->> (rx/of shapes)
(rx/map #(vector (->> % first :frame-id (get objects)) (rx/map #(vector (->> % first :frame-id (get objects))
(-> % gsh/selection-rect (gsh/move movev)))) (-> % gsh/selection-rect (gsh/move movev))))
(rx/merge-map (rx/merge-map
(fn [[frame selrect]] (fn [[frame selrect]]
(let [areas (->> (gsh/selrect->areas (or (:selrect frame) (gsh/rect->rect-shape @refs/vbox)) selrect) (let [areas (->> (gsh/selrect->areas (or (:selrect frame)
(gsh/rect->rect-shape @refs/vbox)) selrect)
(d/mapm #(select-shapes-area page-id shapes objects %2))) (d/mapm #(select-shapes-area page-id shapes objects %2)))
snap-x (search-snap-distance selrect :x (:left areas) (:right areas)) snap-x (search-snap-distance selrect :x (:left areas) (:right areas))
snap-y (search-snap-distance selrect :y (:top areas) (:bottom areas))] snap-y (search-snap-distance selrect :y (:top areas) (:bottom areas))]
@ -178,8 +182,7 @@
(not (contains? layout :dynamic-alignment)))))] (not (contains? layout :dynamic-alignment)))))]
(->> (closest-snap page-id frame-id [point] filter-shapes) (->> (closest-snap page-id frame-id [point] filter-shapes)
(rx/map #(or % (gpt/point 0 0))) (rx/map #(or % (gpt/point 0 0)))
(rx/map #(gpt/add point %)) (rx/map #(gpt/add point %)))))
)))
(defn closest-snap-move (defn closest-snap-move
[page-id shapes objects layout movev] [page-id shapes objects layout movev]
@ -201,4 +204,7 @@
(closest-distance-snap page-id shapes objects movev))) (closest-distance-snap page-id shapes objects movev)))
(rx/reduce gpt/min) (rx/reduce gpt/min)
(rx/map #(or % (gpt/point 0 0))) (rx/map #(or % (gpt/point 0 0)))
(rx/map #(gpt/add movev %))))) (rx/map #(gpt/add movev %))
(rx/map #(gpt/round % 0))
)))

View File

@ -73,7 +73,6 @@
on-pos-x-change #(on-position-change % :x) on-pos-x-change #(on-position-change % :x)
on-pos-y-change #(on-position-change % :y) on-pos-y-change #(on-position-change % :y)
select-all #(-> % (dom/get-target) (.select))] select-all #(-> % (dom/get-target) (.select))]
[:div.element-set [:div.element-set
[:div.element-set-content [:div.element-set-content

View File

@ -53,7 +53,7 @@
(get sr2 (if (= :x coord) :x1 :y1))) (get sr2 (if (= :x coord) :x1 :y1)))
distance (- to-c from-c) distance (- to-c from-c)
distance-str (-> distance (mth/precision 2) str) distance-str (-> distance (mth/precision 0) str)
half-point (half-point coord sr1 sr2) half-point (half-point coord sr1 sr2)
width (-> distance-str width (-> distance-str
count count
@ -80,7 +80,7 @@
:font-size (/ pill-text-font-size zoom) :font-size (/ pill-text-font-size zoom)
:fill "white" :fill "white"
:text-anchor "middle"} :text-anchor "middle"}
(mth/precision distance 2)]]) (mth/precision distance 0)]])
(let [p1 [(+ from-c (/ segment-gap zoom)) (+ half-point (/ segment-gap-side zoom))] (let [p1 [(+ from-c (/ segment-gap zoom)) (+ half-point (/ segment-gap-side zoom))]
p2 [(+ from-c (/ segment-gap zoom)) (- half-point (/ segment-gap-side zoom))] p2 [(+ from-c (/ segment-gap zoom)) (- half-point (/ segment-gap-side zoom))]
@ -110,7 +110,7 @@
pair->distance+pair pair->distance+pair
(fn [[sh1 sh2]] (fn [[sh1 sh2]]
[(-> (gsh/distance-shapes sh1 sh2) coord (mth/precision 2)) [sh1 sh2]]) [(-> (gsh/distance-shapes sh1 sh2) coord (mth/precision 0)) [sh1 sh2]])
contains-selected? contains-selected?
(fn [selected pairs] (fn [selected pairs]
@ -136,7 +136,7 @@
(->> (query-side lt-side) (->> (query-side lt-side)
(rx/combine-latest vector (query-side gt-side))))) (rx/combine-latest vector (query-side gt-side)))))
distance-to-selrect distance-to-selrect
(fn [shape] (fn [shape]
(let [sr (:selrect shape)] (let [sr (:selrect shape)]
@ -144,11 +144,11 @@
(gsh/distance-selrect sr selrect) (gsh/distance-selrect sr selrect)
(gsh/distance-selrect selrect sr)) (gsh/distance-selrect selrect sr))
coord coord
(mth/precision 2)))) (mth/precision 0))))
get-shapes-match get-shapes-match
(fn [pred? shapes] (fn [pred? shapes]
(->> shapes (->> shapes
(sort-by coord) (sort-by coord)
(d/map-perm vector) (d/map-perm vector)
(filter (fn [[sh1 sh2]] (gsh/overlap-coord? coord sh1 sh2))) (filter (fn [[sh1 sh2]] (gsh/overlap-coord? coord sh1 sh2)))

View File

@ -9,7 +9,8 @@
(def ^:private line-color "#D383DA") (def ^:private line-color "#D383DA")
(mf/defc snap-point [{:keys [point zoom]}] (mf/defc snap-point
[{:keys [point zoom]}]
(let [{:keys [x y]} point (let [{:keys [x y]} point
cross-width (/ 3 zoom)] cross-width (/ 3 zoom)]
[:g [:g
@ -24,7 +25,8 @@
:y2 (- y cross-width) :y2 (- y cross-width)
:style {:stroke line-color :stroke-width (str (/ 1 zoom))}}]])) :style {:stroke line-color :stroke-width (str (/ 1 zoom))}}]]))
(mf/defc snap-line [{:keys [snap point zoom]}] (mf/defc snap-line
[{:keys [snap point zoom]}]
[:line {:x1 (:x snap) [:line {:x1 (:x snap)
:y1 (:y snap) :y1 (:y snap)
:x2 (:x point) :x2 (:x point)
@ -32,7 +34,8 @@
:style {:stroke line-color :stroke-width (str (/ 1 zoom))} :style {:stroke line-color :stroke-width (str (/ 1 zoom))}
:opacity 0.4}]) :opacity 0.4}])
(defn get-snap [coord {:keys [shapes page-id filter-shapes]}] (defn get-snap
[coord {:keys [shapes page-id filter-shapes]}]
(->> (rx/from shapes) (->> (rx/from shapes)
(rx/flat-map (fn [shape] (rx/flat-map (fn [shape]
(->> (sp/shape-snap-points shape) (->> (sp/shape-snap-points shape)
@ -50,10 +53,11 @@
;; We use sets to store points/lines so there are no points/lines repeated ;; We use sets to store points/lines so there are no points/lines repeated
;; can cause problems with react keys ;; can cause problems with react keys
snap-points (into #{} (mapcat (fn [[point snaps coord]] snap-points (into #{} (mapcat (fn [[point snaps coord]]
(when (not-empty snaps) (concat [point] snaps))) @state)) (cons point snaps))
@state))
snap-lines (into #{} (mapcat (fn [[point snaps coord]] snap-lines (into #{} (mapcat (fn [[point snaps coord]]
(when (not-empty snaps) (map #(vector point %) snaps))) @state))] (when (not-empty snaps) (map #(vector point %) snaps))) @state))]
(mf/use-effect (mf/use-effect
(fn [] (fn []
(let [sub (let [sub
@ -63,7 +67,7 @@
(get-snap :y %) (get-snap :y %)
(get-snap :x %))) (get-snap :x %)))
(rx/subs #(reset! state %)))] (rx/subs #(reset! state %)))]
;; On unmount callback ;; On unmount callback
#(rx/dispose! sub)))) #(rx/dispose! sub))))
@ -72,35 +76,36 @@
(fn [] (fn []
(rx/push! subject props))) (rx/push! subject props)))
[:g.snap-feedback [:g.snap-feedback
(for [[from-point to-point] snap-lines] (for [[from-point to-point] snap-lines]
[:& snap-line {:key (str "line-" (:x from-point) "-" (:y from-point) "-" (:x to-point) "-" (:y to-point) "-") [:& snap-line {:key (str "line-" (:x from-point)
"-" (:y from-point)
"-" (:x to-point)
"-" (:y to-point) "-")
:snap from-point :snap from-point
:point to-point :point to-point
:zoom zoom}]) :zoom zoom}])
(for [point snap-points] (for [point snap-points]
[:& snap-point {:key (str "point-" (:x point) "-" (:y point)) [:& snap-point {:key (str "point-" (:x point)
"-" (:y point))
:point point :point point
:zoom zoom}])])) :zoom zoom}])]))
(mf/defc snap-points [{:keys [layout]}] (mf/defc snap-points
(let [page-id (mf/deref refs/workspace-page-id) {::mf/wrap [mf/memo]}
selected (mf/deref refs/selected-shapes) [{:keys [layout zoom selected page-id drawing transform] :as props}]
selected-shapes (mf/deref (refs/objects-by-id selected)) (let [shapes (mf/deref (refs/objects-by-id selected))
drawing (mf/deref refs/current-drawing-shape)
filter-shapes (mf/deref refs/selected-shapes-with-children) filter-shapes (mf/deref refs/selected-shapes-with-children)
filter-shapes (fn [id] (if (= id :layout) filter-shapes (fn [id]
(or (not (contains? layout :display-grid)) (if (= id :layout)
(not (contains? layout :snap-grid))) (or (not (contains? layout :display-grid))
(or (filter-shapes id) (not (contains? layout :snap-grid)))
(not (contains? layout :dynamic-alignment))))) (or (filter-shapes id)
current-transform (mf/deref refs/current-transform) (not (contains? layout :dynamic-alignment)))))
snap-data (mf/deref refs/workspace-snap-data) ;; current-transform (mf/deref refs/current-transform)
shapes (if drawing [drawing] selected-shapes) ;; snap-data (mf/deref refs/workspace-snap-data)
zoom (mf/deref refs/selected-zoom)] shapes (if drawing [drawing] shapes)]
(when (or drawing transform)
(when (or drawing current-transform)
[:& snap-feedback {:shapes shapes [:& snap-feedback {:shapes shapes
:page-id page-id :page-id page-id
:filter-shapes filter-shapes :filter-shapes filter-shapes

View File

@ -50,7 +50,7 @@
(mf/defc coordinates (mf/defc coordinates
[] []
(let [coords (some-> (hooks/use-rxsub ms/mouse-position) (let [coords (some-> (hooks/use-rxsub ms/mouse-position)
(gpt/round 0))] (gpt/round))]
[:ul.coordinates [:ul.coordinates
[:span {:alt "x"} [:span {:alt "x"}
(str "X: " (:x coords "-"))] (str "X: " (:x coords "-"))]
@ -290,12 +290,13 @@
] ]
(-> (gpt/subtract pt brect) (-> (gpt/subtract pt brect)
(gpt/divide (gpt/point @refs/selected-zoom)) (gpt/divide (gpt/point @refs/selected-zoom))
(gpt/add box)))) (gpt/add box)
(gpt/round 0))))
on-mouse-move on-mouse-move
(fn [event] (fn [event]
(let [event (.getBrowserEvent event) (let [event (.getBrowserEvent event)
pt (gpt/point (.-clientX event) (.-clientY event)) pt (dom/get-client-position event)
pt (translate-point-to-viewport pt) pt (translate-point-to-viewport pt)
delta (gpt/point (.-movementX event) delta (gpt/point (.-movementX event)
(.-movementY event))] (.-movementY event))]
@ -457,7 +458,13 @@
(when (contains? layout :display-grid) (when (contains? layout :display-grid)
[:& frame-grid {:zoom zoom}]) [:& frame-grid {:zoom zoom}])
[:& snap-points {:layout layout}] [:& snap-points {:layout layout
:transform (:transform local)
:drawing (:drawing local)
:zoom zoom
:page-id (:id page)
:selected selected}]
[:& snap-distances {:layout layout}] [:& snap-distances {:layout layout}]
(when tooltip (when tooltip

View File

@ -28,6 +28,8 @@
[shape] [shape]
(let [shape (gsh/transform-shape shape) (let [shape (gsh/transform-shape shape)
shape-center (gsh/center shape)] shape-center (gsh/center shape)]
(case (:type shape) (if (= :frame (:type shape))
:frame (-> shape gsh/shape->rect-shape frame-snap-points) (-> shape
(into #{shape-center} (-> shape :points))))) (gsh/shape->rect-shape)
(frame-snap-points))
(into #{shape-center} (:points shape)))))

View File

@ -1,4 +1,4 @@
/* /*
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
@ -10,7 +10,7 @@
*/ */
/* /*
* Balanced Binary Search Tree based on the red-black BST * Balanced Binary Search Tree based on the red-black BST
* described at "Algorithms" by Robert Sedwick & Kevin Wayne * described at "Algorithms" by Robert Sedwick & Kevin Wayne
*/ */
"use strict"; "use strict";
@ -27,7 +27,7 @@ goog.scope(function() {
RED: 1, RED: 1,
BLACK: 2 BLACK: 2
} }
class Node { class Node {
constructor(value, data) { constructor(value, data) {
this.value = value; this.value = value;
@ -37,7 +37,7 @@ goog.scope(function() {
this.color = Color.BLACK; this.color = Color.BLACK;
} }
} }
// Will store a map from key to list of data // Will store a map from key to list of data
// value => [ data ] // value => [ data ]
// The values can be queried in range and the data stored will be retrived whole // The values can be queried in range and the data stored will be retrived whole
@ -46,13 +46,13 @@ goog.scope(function() {
constructor() { constructor() {
this.root = null; this.root = null;
} }
insert(value, data) { insert(value, data) {
this.root = recInsert(this.root, value, data); this.root = recInsert(this.root, value, data);
this.root.color = Color.BLACK; this.root.color = Color.BLACK;
return this; return this;
} }
remove(value, data) { remove(value, data) {
if (!this.root) { if (!this.root) {
return this; return this;
@ -76,16 +76,16 @@ goog.scope(function() {
return this; return this;
} }
update (value, oldData, newData) { update (value, oldData, newData) {
this.root = recUpdate(this.root, value, oldData, newData); this.root = recUpdate(this.root, value, oldData, newData);
return this; return this;
} }
get(value) { get(value) {
return recGet(this.root, value); return recGet(this.root, value);
} }
rangeQuery (fromValue, toValue) { rangeQuery (fromValue, toValue) {
return recRangeQuery(this.root, fromValue, toValue, []); return recRangeQuery(this.root, fromValue, toValue, []);
} }
@ -227,7 +227,7 @@ goog.scope(function() {
return recGet(branch.right, value); return recGet(branch.right, value);
} }
} }
function recUpdate(branch, value, oldData, newData) { function recUpdate(branch, value, oldData, newData) {
if (branch === null) { if (branch === null) {
return branch; return branch;

View File

@ -31,9 +31,9 @@
(map #(vector % (:id shape)) points)) (map #(vector % (:id shape)) points))
;; The grid points are only added by the "root" of the coord-dat ;; The grid points are only added by the "root" of the coord-dat
(if (= (:id shape) frame-id) (when (= (:id shape) frame-id)
(let [points (gg/grid-snap-points shape coord)] (let [points (gg/grid-snap-points shape coord)]
(map #(vector % :layout) points)))))) (map #(vector % :layout) points))))))
into-tree (fn [tree [point _ :as data]] into-tree (fn [tree [point _ :as data]]
(rt/insert tree (coord point) data))] (rt/insert tree (coord point) data))]
(->> shapes (->> shapes
@ -48,9 +48,10 @@
(group-by :frame-id)) (group-by :frame-id))
frame-shapes (->> (cph/select-frames objects) frame-shapes (->> (cph/select-frames objects)
(reduce #(update %1 (:id %2) conj %2) frame-shapes))] (reduce #(update %1 (:id %2) conj %2) frame-shapes))]
(d/mapm (fn [frame-id shapes] {:x (create-coord-data frame-id shapes :x) (d/mapm (fn [frame-id shapes] {:x (create-coord-data frame-id shapes :x)
:y (create-coord-data frame-id shapes :y)}) :y (create-coord-data frame-id shapes :y)})
frame-shapes))) frame-shapes)))
(defn- log-state (defn- log-state
"Helper function to print a friendly version of the snap tree. Debugging purposes" "Helper function to print a friendly version of the snap tree. Debugging purposes"
@ -74,7 +75,7 @@
(index-page state id objects)))] (index-page state id objects)))]
(swap! state #(reduce process-page % pages))) (swap! state #(reduce process-page % pages)))
#_(log-state) ;; (log-state)
;; Return nil so the worker will not answer anything back ;; Return nil so the worker will not answer anything back
nil) nil)
@ -82,7 +83,7 @@
[{:keys [page-id objects] :as message}] [{:keys [page-id objects] :as message}]
;; TODO: Check the difference and update the index acordingly ;; TODO: Check the difference and update the index acordingly
(swap! state index-page page-id objects) (swap! state index-page page-id objects)
#_(log-state) ;; (log-state)
nil) nil)
(defmethod impl/handler :snaps/range-query (defmethod impl/handler :snaps/range-query
@ -96,3 +97,4 @@
set ;; unique set ;; unique
(into [])))) (into []))))

3
package-lock.json generated
View File

@ -1,3 +0,0 @@
{
"lockfileVersion": 1
}