Don't trigger page persistence on simple shape selection.

This commit is contained in:
Andrey Antukh 2017-01-31 16:58:10 +01:00
parent 422f2aed64
commit 3fdce853d0
No known key found for this signature in database
GPG key ID: 4DFEBCB8316A8B95
11 changed files with 133 additions and 141 deletions

View file

@ -433,7 +433,8 @@
(rx/take 1))] (rx/take 1))]
(rx/merge (rx/merge
(->> stream (->> stream
(rx/filter #(satisfies? IPageUpdate %)) (rx/filter #(or (satisfies? IPageUpdate %)
(= ::page-update %)))
(rx/take-until stopper) (rx/take-until stopper)
(rx/debounce 1000) (rx/debounce 1000)
(rx/mapcat #(rx/merge (rx/of (persist-page id)) (rx/mapcat #(rx/merge (rx/of (persist-page id))

View file

@ -14,8 +14,8 @@
[uxbox.main.lenses :as ul] [uxbox.main.lenses :as ul]
[uxbox.main.geom :as geom] [uxbox.main.geom :as geom]
[uxbox.main.workers :as uwrk] [uxbox.main.workers :as uwrk]
[uxbox.main.data.shapes-impl :as impl]
[uxbox.main.data.pages :as udp] [uxbox.main.data.pages :as udp]
[uxbox.main.data.shapes-impl :as impl]
[uxbox.main.user-events :as uev] [uxbox.main.user-events :as uev]
[uxbox.util.data :refer [dissoc-in]] [uxbox.util.data :refer [dissoc-in]]
[uxbox.util.forms :as sc] [uxbox.util.forms :as sc]
@ -177,13 +177,11 @@
;; --- Apply Temporal Displacement ;; --- Apply Temporal Displacement
(deftype ApplyTemporalDisplacement [id delta] (deftype ApplyTemporalDisplacement [id delta]
udp/IPageUpdate
ptk/UpdateEvent ptk/UpdateEvent
(update [_ state] (update [_ state]
(let [shape (get-in state [:shapes id]) (let [prev (get-in state [:workspace :modifiers id :displacement] (gmt/matrix))
displ (:tmp-displacement shape (gpt/point 0 0)) curr (gmt/translate prev delta)]
delta (gpt/add displ delta)] (assoc-in state [:workspace :modifiers id :displacement] curr))))
(assoc-in state [:shapes id :tmp-displacement] delta))))
(defn apply-temporal-displacement (defn apply-temporal-displacement
[id pt] [id pt]
@ -192,30 +190,15 @@
;; --- Apply Displacement ;; --- Apply Displacement
;; TODO: move to shapes-impl ns.
(deftype ApplyDisplacement [id] (deftype ApplyDisplacement [id]
udp/IPageUpdate ptk/WatchEvent
ptk/UpdateEvent (watch [_ state stream]
(update [_ state] (let [displacement (get-in state [:workspace :modifiers id :displacement])]
(let [{:keys [tmp-displacement type] :as shape} (get-in state [:shapes id]) (if (gmt/matrix? displacement)
xfmt (gmt/translate-matrix tmp-displacement)] (rx/of #(impl/materialize-xfmt % id displacement)
#(update-in % [:workspace :modifiers id] dissoc :displacement)
(if (= type :group) ::udp/page-update)
(letfn [(update-item [state id] (rx/empty)))))
(let [{:keys [type items] :as shape} (get-in state [:shapes id])]
(if (= type :group)
(reduce update-item state items)
(update-in state [:shapes id]
(fn [shape]
(as-> (dissoc shape :tmp-displacement) $
(geom/transform state $ xfmt)))))))]
(-> (reduce update-item state (:items shape))
(update-in [:shapes id] dissoc :tmp-displacement)))
(update-in state [:shapes id] (fn [shape]
(as-> (dissoc shape :tmp-displacement) $
(geom/transform state $ xfmt))))))))
(defn apply-displacement (defn apply-displacement
[id] [id]
@ -224,48 +207,34 @@
;; --- Apply Temporal Resize Matrix ;; --- Apply Temporal Resize Matrix
(deftype ApplyTemporalResizeMatrix [id mx] (deftype ApplyTemporalResize [id xfmt]
udp/IPageUpdate
ptk/UpdateEvent ptk/UpdateEvent
(update [_ state] (update [_ state]
(assoc-in state [:shapes id :tmp-resize-xform] mx))) (assoc-in state [:workspace :modifiers id :resize] xfmt)))
(defn apply-temporal-resize-matrix (defn apply-temporal-resize
"Attach temporal resize matrix transformation to the shape." "Attach temporal resize transformation to the shape."
[id mx] [id xfmt]
(ApplyTemporalResizeMatrix. id mx)) {:pre [(gmt/matrix? xfmt)]}
(ApplyTemporalResize. id xfmt))
;; --- Apply Resize Matrix ;; --- Apply Resize Matrix
(declare apply-resize-matrix) (deftype ApplyResize [id]
ptk/WatchEvent
(watch [_ state stream]
(let [resize (get-in state [:workspace :modifiers id :resize])]
(if (gmt/matrix? resize)
(rx/of #(impl/materialize-xfmt % id resize)
#(update-in % [:workspace :modifiers id] dissoc :resize)
::udp/page-update)
(rx/empty)))))
(deftype ApplyResizeMatrix [id] (defn apply-resize
udp/IPageUpdate
ptk/UpdateEvent
(update [_ state]
(let [{:keys [type tmp-resize-xform]
:or {tmp-resize-xform (gmt/matrix)}
:as shape} (get-in state [:shapes id])]
(if (= type :group)
(letfn [(update-item [state id]
(let [{:keys [type items] :as shape} (get-in state [:shapes id])]
(if (= type :group)
(reduce update-item state items)
(update-in state [:shapes id]
(fn [shape]
(as-> (dissoc shape :tmp-resize-xform) $
(geom/transform state $ tmp-resize-xform)))))))]
(-> (reduce update-item state (:items shape))
(update-in [:shapes id] dissoc :tmp-resize-xform)))
(update-in state [:shapes id] (fn [shape]
(as-> (dissoc shape :tmp-resize-xform) $
(geom/transform state $ tmp-resize-xform))))))))
(defn apply-resize-matrix
"Apply definitivelly the resize matrix transformation to the shape." "Apply definitivelly the resize matrix transformation to the shape."
[id] [id]
{:pre [(uuid? id)]} {:pre [(uuid? id)]}
(ApplyResizeMatrix. id)) (ApplyResize. id))
(defn update-position (defn update-position
"Update the start position coordenate of the shape." "Update the start position coordenate of the shape."

View file

@ -2,12 +2,13 @@
;; 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/.
;; ;;
;; Copyright (c) 2015-2016 Andrey Antukh <niwi@niwi.nz> ;; Copyright (c) 2015-2017 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.main.data.shapes-impl (ns uxbox.main.data.shapes-impl
(:require [lentes.core :as l] (:require [lentes.core :as l]
[uxbox.main.geom :as geom] [uxbox.main.geom :as geom]
[uxbox.main.lenses :as ul] [uxbox.main.lenses :as ul]
[uxbox.util.geom.matrix :as gmt]
[uxbox.util.uuid :as uuid] [uxbox.util.uuid :as uuid]
[uxbox.util.data :refer (index-of)])) [uxbox.util.data :refer (index-of)]))
@ -413,3 +414,11 @@
(as-> state $ (as-> state $
(empty-groups $ page groups-ids) (empty-groups $ page groups-ids)
(update $ :workspace assoc :selected (set groups-items)))))) (update $ :workspace assoc :selected (set groups-items))))))
(defn materialize-xfmt
[state id xfmt]
(let [{:keys [type items] :as shape} (get-in state [:shapes id])]
(if (= type :group)
(-> (reduce #(materialize-xfmt %1 %2 xfmt) state items)
(update-in [:shapes id] geom/transform xfmt))
(update-in state [:shapes id] geom/transform xfmt))))

View file

@ -438,15 +438,14 @@
(defn transform (defn transform
"Apply the matrix transformation to shape." "Apply the matrix transformation to shape."
([shape xfmt] (transform @st/state shape xfmt)) [{:keys [type] :as shape} xfmt]
([state {:keys [type] :as shape} xfmt] (case type
(case type :rect (transform-rect shape xfmt)
:rect (transform-rect shape xfmt) :icon (transform-rect shape xfmt)
:icon (transform-rect shape xfmt) :text (transform-rect shape xfmt)
:text (transform-rect shape xfmt) :image (transform-rect shape xfmt)
:image (transform-rect shape xfmt) :path (transform-path shape xfmt)
:path (transform-path shape xfmt) :circle (transform-circle shape xfmt)))
:circle (transform-circle shape xfmt))))
(defn- transform-rect (defn- transform-rect
[{:keys [x1 y1] :as shape} mx] [{:keys [x1 y1] :as shape} mx]
@ -524,29 +523,24 @@
(defn- selection-rect-generic (defn- selection-rect-generic
[state {:keys [id x1 y1 x2 y2] :as shape}] [state {:keys [id x1 y1 x2 y2] :as shape}]
(let [resize-xf (:tmp-resize-xform shape (gmt/matrix)) (let [{:keys [displacement resize]} (get-in state [:workspace :modifiers id])]
displc-xf (-> (:tmp-displacement shape (gpt/point 0 0))
(gmt/translate-matrix))]
(-> (shape->rect-shape shape) (-> (shape->rect-shape shape)
(assoc :type :rect :id id) (assoc :type :rect :id id)
(transform resize-xf) (transform (or resize (gmt/matrix)))
(transform displc-xf) (transform (or displacement (gmt/matrix)))
(rotate-shape) (rotate-shape)
(size)))) (size))))
(defn- selection-rect-group (defn- selection-rect-group
[state {:keys [id group items] :as shape}] [state {:keys [id group items] :as shape}]
(let [resize-xf (:tmp-resize-xform shape (gmt/matrix)) (let [{:keys [displacement resize]} (get-in state [:workspace :modifiers id])
displc-xf (-> (:tmp-displacement shape (gpt/point 0 0))
(gmt/translate-matrix))
shapes (->> items shapes (->> items
(map #(get-in state [:shapes %])) (map #(get-in state [:shapes %]))
(map #(selection-rect state %)))] (map #(selection-rect state %)))]
(-> (shapes->rect-shape shapes) (-> (shapes->rect-shape shapes)
(assoc :id id) (assoc :id id)
(transform resize-xf) (transform (or resize (gmt/matrix)))
(transform displc-xf) (transform (or displacement (gmt/matrix)))
(rotate-shape) (rotate-shape)
(size)))) (size))))

View file

@ -19,23 +19,27 @@
(mx/defc circle-component (mx/defc circle-component
{:mixins [mx/reactive mx/static]} {:mixins [mx/reactive mx/static]}
[shape] [{:keys [id] :as shape}]
(let [{:keys [id x y width height group]} shape (let [modifiers (mx/react (common/modifiers-ref id))
selected (mx/react common/selected-ref) selected (mx/react common/selected-ref)
selected? (contains? selected id) selected? (contains? selected id)
on-mouse-down #(common/on-mouse-down % shape selected)] on-mouse-down #(common/on-mouse-down % shape selected)
shape (assoc shape :modifiers modifiers)]
[:g.shape {:class (when selected? "selected") [:g.shape {:class (when selected? "selected")
:on-mouse-down on-mouse-down} :on-mouse-down on-mouse-down}
(circle-shape shape identity)])) (circle-shape shape)]))
;; --- Circle Shape ;; --- Circle Shape
(mx/defc circle-shape (mx/defc circle-shape
{:mixins [mx/static]} {:mixins [mx/static]}
[{:keys [id tmp-resize-xform tmp-displacement rotation cx cy] :as shape}] [{:keys [id modifiers rotation cx cy] :as shape}]
(let [shape (cond-> shape (let [{:keys [resize displacement]} modifiers
tmp-displacement (geom/transform (gmt/translate-matrix tmp-displacement))
tmp-resize-xform (geom/transform tmp-resize-xform)) shape (cond-> shape
displacement (geom/transform displacement)
resize (geom/transform resize))
center (gpt/point (:cx shape) center (gpt/point (:cx shape)
(:cy shape)) (:cy shape))
rotation (or rotation 0) rotation (or rotation 0)

View file

@ -20,8 +20,6 @@
;; --- Refs ;; --- Refs
;; FIXME: use the predefined lenses under uxbox.main.lenses
(def edition-ref (def edition-ref
(-> (l/in [:workspace :edition]) (-> (l/in [:workspace :edition])
(l/derive st/state))) (l/derive st/state)))
@ -31,8 +29,13 @@
(l/derive st/state))) (l/derive st/state)))
(def selected-ref (def selected-ref
(-> (l/in [:workspace :selected]) (-> (l/in [:selected])
(l/derive st/state))) (l/derive refs/workspace)))
(defn modifiers-ref
[id]
(-> (l/in [:modifiers id])
(l/derive refs/workspace)))
;; --- Movement ;; --- Movement

View file

@ -19,34 +19,36 @@
(mx/defc icon-component (mx/defc icon-component
{:mixins [mx/static mx/reactive]} {:mixins [mx/static mx/reactive]}
[{:keys [id] :as shape}] [{:keys [id] :as shape}]
(let [selected (mx/react common/selected-ref) (let [modifiers (mx/react (common/modifiers-ref id))
selected (mx/react common/selected-ref)
selected? (contains? selected id) selected? (contains? selected id)
on-mouse-down #(common/on-mouse-down % shape selected)] on-mouse-down #(common/on-mouse-down % shape selected)
shape (assoc shape :modifiers modifiers)]
[:g.shape {:class (when selected? "selected") [:g.shape {:class (when selected? "selected")
:on-mouse-down on-mouse-down} :on-mouse-down on-mouse-down}
(icon-shape shape identity)])) (icon-shape shape)]))
;; --- Icon Shape ;; --- Icon Shape
(mx/defc icon-shape (mx/defc icon-shape
{:mixins [mx/static]} {:mixins [mx/static]}
[shape] [{:keys [id content metadata rotation x1 y1 modifiers] :as shape}]
(let [{:keys [x1 y1 content id metadata (let [{:keys [width height]} (geom/size shape)
width height rotation {:keys [resize displacement]} modifiers
tmp-resize-xform
tmp-displacement]} (geom/size shape)
view-box (apply str (interpose " " (:view-box metadata))) view-box (apply str (interpose " " (:view-box metadata)))
xfmt (cond-> (gmt/matrix) xfmt (cond-> (gmt/matrix)
tmp-resize-xform (gmt/multiply tmp-resize-xform) resize (gmt/multiply resize)
tmp-displacement (gmt/translate tmp-displacement) displacement (gmt/multiply displacement)
rotation (gmt/rotate* rotation (gpt/point (+ x1 (/ width 2)) rotation (gmt/rotate* rotation (gpt/point (+ x1 (/ width 2))
(+ y1 (/ height 2))))) (+ y1 (/ height 2)))))
props {:id (str id) props {:id (str id)
:x x1 :y y1 :view-box view-box :x x1
:width width :height height :y y1
:view-box view-box
:width width
:height height
:preserve-aspect-ratio "none" :preserve-aspect-ratio "none"
:dangerouslySetInnerHTML {:__html content}} :dangerouslySetInnerHTML {:__html content}}

View file

@ -36,27 +36,30 @@
(st/emit! (udi/fetch-image id))) (st/emit! (udi/fetch-image id)))
own)} own)}
[own {:keys [id image] :as shape}] [own {:keys [id image] :as shape}]
(let [selected (mx/react common/selected-ref) (let [modifiers (mx/react (common/modifiers-ref id))
selected (mx/react common/selected-ref)
image (mx/react (image-ref image)) image (mx/react (image-ref image))
selected? (contains? selected id) selected? (contains? selected id)
on-mouse-down #(common/on-mouse-down % shape selected)] on-mouse-down #(common/on-mouse-down % shape selected)
shape (assoc shape
:modifiers modifiers
:image image)]
(when image (when image
[:g.shape {:class (when selected? "selected") [:g.shape {:class (when selected? "selected")
:on-mouse-down on-mouse-down} :on-mouse-down on-mouse-down}
(image-shape (assoc shape :image image))]))) (image-shape shape)])))
;; --- Image Shape ;; --- Image Shape
(mx/defc image-shape (mx/defc image-shape
{:mixins [mx/static]} {:mixins [mx/static]}
[shape] [{:keys [id x1 y1 image modifiers] :as shape}]
(let [{:keys [id x1 y1 image (let [{:keys [width height]} (geom/size shape)
width height {:keys [resize displacement]} modifiers
tmp-resize-xform
tmp-displacement]} (geom/size shape)
xfmt (cond-> (or tmp-resize-xform (gmt/matrix)) xfmt (cond-> (gmt/matrix)
tmp-displacement (gmt/translate tmp-displacement)) resize (gmt/multiply resize)
displacement (gmt/multiply displacement))
props {:x x1 :y y1 props {:x x1 :y y1
:id (str "shape-" id) :id (str "shape-" id)

View file

@ -22,8 +22,10 @@
(mx/defc path-component (mx/defc path-component
{:mixins [mx/static mx/reactive]} {:mixins [mx/static mx/reactive]}
[{:keys [id] :as shape}] [{:keys [id] :as shape}]
(let [selected (mx/react common/selected-ref) (let [modifiers (mx/react (common/modifiers-ref id))
selected? (contains? selected id)] selected (mx/react common/selected-ref)
selected? (contains? selected id)
shape (assoc shape :modifiers modifiers)]
(letfn [(on-mouse-down [event] (letfn [(on-mouse-down [event]
(common/on-mouse-down event shape selected)) (common/on-mouse-down event shape selected))
(on-double-click [event] (on-double-click [event]
@ -32,13 +34,12 @@
[:g.shape {:class (when selected? "selected") [:g.shape {:class (when selected? "selected")
:on-double-click on-double-click :on-double-click on-double-click
:on-mouse-down on-mouse-down} :on-mouse-down on-mouse-down}
(path-shape shape identity)]))) (path-shape shape)])))
;; --- Path Shape ;; --- Path Shape
(defn- render-path (defn- render-path
[{:keys [points close?] :as shape}] [{:keys [points close?] :as shape}]
{:pre [(pos? (count points))]}
(let [start (first points) (let [start (first points)
init (str "M " (:x start) " " (:y start)) init (str "M " (:x start) " " (:y start))
path (reduce #(str %1 " L" (:x %2) " " (:y %2)) init points)] path (reduce #(str %1 " L" (:x %2) " " (:y %2)) init points)]
@ -47,11 +48,11 @@
(mx/defc path-shape (mx/defc path-shape
{:mixins [mx/static]} {:mixins [mx/static]}
[{:keys [id tmp-resize-xform tmp-displacement rotation] :as shape}] [{:keys [id modifiers rotation] :as shape}]
(let [{:keys [resize displacement]} modifiers
(let [shape (cond-> shape shape (cond-> shape
tmp-displacement (geom/transform (gmt/translate-matrix tmp-displacement)) displacement (geom/transform displacement)
tmp-resize-xform (geom/transform tmp-resize-xform) resize (geom/transform resize)
(pos? rotation) (geom/rotate-shape)) (pos? rotation) (geom/rotate-shape))
props {:id (str id) props {:id (str id)

View file

@ -19,11 +19,12 @@
(mx/defc rect-component (mx/defc rect-component
{:mixins [mx/reactive mx/static]} {:mixins [mx/reactive mx/static]}
[shape] [{:keys [id] :as shape}]
(let [{:keys [id x y width height group]} shape (let [modifiers (mx/react (common/modifiers-ref id))
selected (mx/react common/selected-ref) selected (mx/react common/selected-ref)
selected? (contains? selected id) selected? (contains? selected id)
on-mouse-down #(common/on-mouse-down % shape selected)] on-mouse-down #(common/on-mouse-down % shape selected)
shape (assoc shape :modifiers modifiers)]
[:g.shape {:class (when selected? "selected") [:g.shape {:class (when selected? "selected")
:on-mouse-down on-mouse-down} :on-mouse-down on-mouse-down}
(rect-shape shape identity)])) (rect-shape shape identity)]))
@ -40,10 +41,11 @@
(mx/defc rect-shape (mx/defc rect-shape
{:mixins [mx/static]} {:mixins [mx/static]}
[{:keys [id tmp-displacement tmp-resize-xform rotation] :as shape}] [{:keys [id rotation modifiers] :as shape}]
(let [xfmt (cond-> (gmt/matrix) (let [{:keys [displacement resize]} modifiers
tmp-displacement (gmt/translate tmp-displacement) xfmt (cond-> (gmt/matrix)
tmp-resize-xform (gmt/multiply tmp-resize-xform)) displacement (gmt/multiply displacement)
resize (gmt/multiply resize))
{:keys [x1 y1 width height] :as shape} (-> (geom/transform shape xfmt) {:keys [x1 y1 width height] :as shape} (-> (geom/transform shape xfmt)
(geom/size)) (geom/size))

View file

@ -44,6 +44,9 @@
(l/derive st/state))) (l/derive st/state)))
(def ^:private edition-ref scommon/edition-ref) (def ^:private edition-ref scommon/edition-ref)
(def ^:private modifiers-ref
(-> (l/key :modifiers)
(l/derive refs/workspace)))
;; --- Resize Implementation ;; --- Resize Implementation
@ -204,11 +207,11 @@
)) ))
(on-resize [shape scale] (on-resize [shape scale]
(let [mt (gen-matrix shape scale) (let [mt (gen-matrix shape scale)
xf (map #(uds/apply-temporal-resize-matrix % mt))] xf (map #(uds/apply-temporal-resize % mt))]
(apply st/emit! (sequence xf ids)))) (apply st/emit! (sequence xf ids))))
(on-end [] (on-end []
(apply st/emit! (map uds/apply-resize-matrix ids)))] (apply st/emit! (map uds/apply-resize ids)))]
(let [shape (->> (geom/shape->rect-shape shape) (let [shape (->> (geom/shape->rect-shape shape)
(geom/size)) (geom/size))
@ -349,7 +352,7 @@
(mx/defc multiple-selection-handlers (mx/defc multiple-selection-handlers
{:mixins [mx/static]} {:mixins [mx/static]}
[[shape & rest :as shapes] zoom] [[shape & rest :as shapes] modifiers zoom]
(let [selection (-> (map #(geom/selection-rect %) shapes) (let [selection (-> (map #(geom/selection-rect %) shapes)
(geom/shapes->rect-shape) (geom/shapes->rect-shape)
(geom/selection-rect)) (geom/selection-rect))
@ -360,7 +363,7 @@
(mx/defc single-selection-handlers (mx/defc single-selection-handlers
{:mixins [mx/static]} {:mixins [mx/static]}
[{:keys [id] :as shape} zoom] [{:keys [id] :as shape} modifiers zoom]
(let [on-click #(do (dom/stop-propagation %2) (let [on-click #(do (dom/stop-propagation %2)
(start-resize %1 #{id} shape)) (start-resize %1 #{id} shape))
shape (geom/selection-rect shape)] shape (geom/selection-rect shape)]
@ -384,6 +387,7 @@
{:mixins [mx/reactive mx/static]} {:mixins [mx/reactive mx/static]}
[] []
(let [shapes (mx/react selected-shapes-ref) (let [shapes (mx/react selected-shapes-ref)
modifiers (mx/react modifiers-ref)
edition? (mx/react edition-ref) edition? (mx/react edition-ref)
zoom (mx/react refs/selected-zoom) zoom (mx/react refs/selected-zoom)
num (count shapes) num (count shapes)
@ -393,7 +397,7 @@
nil nil
(> num 1) (> num 1)
(multiple-selection-handlers shapes zoom) (multiple-selection-handlers shapes modifiers zoom)
(and (= type :text) edition?) (and (= type :text) edition?)
(text-edition-selection-handlers shape zoom) (text-edition-selection-handlers shape zoom)
@ -401,7 +405,7 @@
(= type :path) (= type :path)
(if (= @edition-ref (:id shape)) (if (= @edition-ref (:id shape))
(path-edition-selection-handlers shape zoom) (path-edition-selection-handlers shape zoom)
(single-selection-handlers shape zoom)) (single-selection-handlers shape modifiers zoom))
:else :else
(single-selection-handlers shape zoom)))) (single-selection-handlers shape modifiers zoom))))