mirror of
https://github.com/penpot/penpot.git
synced 2025-03-20 19:51:23 -05:00
✨ Add more incremental improvements to shapes rendering.
That helps for make a good foundation for proper canvas painting and manipulation.
This commit is contained in:
parent
1fa9faa314
commit
6483800e49
14 changed files with 144 additions and 339 deletions
|
@ -479,9 +479,11 @@
|
|||
:fast (gpt/point (if align? (* 3 gx) 10)
|
||||
(if align? (* 3 gy) 10))}))
|
||||
|
||||
(declare apply-temporal-displacement)
|
||||
(declare initial-shape-align)
|
||||
(declare apply-displacement)
|
||||
(declare assoc-temporal-modifier)
|
||||
(declare materialize-current-modifier)
|
||||
(declare apply-temporal-displacement)
|
||||
|
||||
(defrecord MoveSelected [direction speed]
|
||||
ptk/WatchEvent
|
||||
|
@ -500,7 +502,7 @@
|
|||
(rx/from-coll (map initial-shape-align selected))
|
||||
(rx/from-coll (map apply-displacement selected))))
|
||||
(rx/from-coll (map #(apply-temporal-displacement % displacement) selected))
|
||||
(rx/from-coll (map apply-displacement selected))))))
|
||||
(rx/from-coll (map materialize-current-modifier selected))))))
|
||||
|
||||
(s/def ::direction #{:up :down :right :left})
|
||||
(s/def ::speed #{:std :fast})
|
||||
|
@ -597,69 +599,38 @@
|
|||
|
||||
;; --- Apply Temporal Displacement
|
||||
|
||||
(defrecord ApplyTemporalDisplacement [id delta]
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [pid (get-in state [:workspace :current])
|
||||
prev (get-in state [:workspace pid :modifiers id :displacement] (gmt/matrix))
|
||||
curr (gmt/translate prev delta)]
|
||||
(assoc-in state [:workspace pid :modifiers id :displacement] curr))))
|
||||
|
||||
(defn apply-temporal-displacement
|
||||
[id pt]
|
||||
{:pre [(uuid? id) (gpt/point? pt)]}
|
||||
(ApplyTemporalDisplacement. id pt))
|
||||
[id delta]
|
||||
{:pre [(uuid? id) (gpt/point? delta)]}
|
||||
(reify
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [prev (get-in state [:shapes id :modifier-mtx] (gmt/matrix))
|
||||
curr (gmt/translate prev delta)]
|
||||
(rx/of (assoc-temporal-modifier id curr))))))
|
||||
|
||||
;; --- Apply Displacement
|
||||
;; --- Modifiers
|
||||
|
||||
(defrecord ApplyDisplacement [id]
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [pid (get-in state [:workspace :current])
|
||||
displacement (get-in state [:workspace pid :modifiers id :displacement])]
|
||||
(if (gmt/matrix? displacement)
|
||||
(rx/of #(ds/materialize-xfmt % id displacement)
|
||||
#(update-in % [:workspace pid :modifiers id] dissoc :displacement)
|
||||
::udp/page-update)
|
||||
(rx/empty)))))
|
||||
|
||||
(defn apply-displacement
|
||||
[id]
|
||||
{:pre [(uuid? id)]}
|
||||
(ApplyDisplacement. id))
|
||||
|
||||
;; --- Apply Temporal Resize Matrix
|
||||
|
||||
(deftype ApplyTemporalResize [sid xfmt]
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [pid (get-in state [:workspace :current])]
|
||||
(assoc-in state [:workspace pid :modifiers sid :resize] xfmt))))
|
||||
|
||||
(defn apply-temporal-resize
|
||||
"Attach temporal resize transformation to the shape."
|
||||
(defn assoc-temporal-modifier
|
||||
[id xfmt]
|
||||
{:pre [(gmt/matrix? xfmt) (uuid? id)]}
|
||||
(ApplyTemporalResize. id xfmt))
|
||||
{:pre [(uuid? id)
|
||||
(gmt/matrix? xfmt)]}
|
||||
(reify
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:shapes id :modifier-mtx] xfmt))))
|
||||
|
||||
;; --- Apply Resize Matrix
|
||||
|
||||
(deftype ApplyResize [id]
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [pid (get-in state [:workspace :current])
|
||||
resize (get-in state [:workspace pid :modifiers id :resize])]
|
||||
(if (gmt/matrix? resize)
|
||||
(rx/of #(ds/materialize-xfmt % id resize)
|
||||
#(update-in % [:workspace pid :modifiers id] dissoc :resize)
|
||||
::udp/page-update)
|
||||
(rx/empty)))))
|
||||
|
||||
(defn apply-resize
|
||||
"Apply definitivelly the resize matrix transformation to the shape."
|
||||
(defn materialize-current-modifier
|
||||
[id]
|
||||
{:pre [(uuid? id)]}
|
||||
(ApplyResize. id))
|
||||
(reify
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [xfmt (get-in state [:shapes id :modifier-mtx])]
|
||||
(when (gmt/matrix? xfmt)
|
||||
(rx/of #(update-in % [:shapes id] geom/transform xfmt)
|
||||
#(update-in % [:shapes id] dissoc :modifier-mtx)
|
||||
::udp/page-update))))))
|
||||
|
||||
;; --- Start shape "edition mode"
|
||||
|
||||
|
@ -694,16 +665,16 @@
|
|||
(= (::type (meta e)) ::select-for-drawing))
|
||||
|
||||
(defn select-for-drawing
|
||||
[tool]
|
||||
(reify
|
||||
IMeta
|
||||
(-meta [_] {::type ::select-for-drawing})
|
||||
([tool] (select-for-drawing tool nil))
|
||||
([tool data]
|
||||
(reify
|
||||
IMeta
|
||||
(-meta [_] {::type ::select-for-drawing})
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(prn "select-for-drawing" tool)
|
||||
(let [pid (get-in state [:workspace :current])]
|
||||
(update-in state [:workspace pid] assoc :drawing-tool tool)))))
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [pid (get-in state [:workspace :current])]
|
||||
(update-in state [:workspace pid] assoc :drawing-tool tool :drawing data))))))
|
||||
|
||||
;; --- Shape Proportions
|
||||
|
||||
|
|
|
@ -127,12 +127,9 @@
|
|||
[shape]
|
||||
(case (:type shape)
|
||||
:circle (size-circle shape)
|
||||
:text (size-rect shape)
|
||||
:rect (size-rect shape)
|
||||
:icon (size-rect shape)
|
||||
:image (size-rect shape)
|
||||
:curve (size-path shape)
|
||||
:path (size-path shape)))
|
||||
:path (size-path shape)
|
||||
(size-rect shape)))
|
||||
|
||||
(defn- size-path
|
||||
[{:keys [segments x1 y1 x2 y2] :as shape}]
|
||||
|
|
|
@ -21,37 +21,37 @@
|
|||
|
||||
(mf/defc circle-component
|
||||
[{:keys [shape] :as props}]
|
||||
(let [modifiers (mf/deref (refs/selected-modifiers (:id shape)))
|
||||
selected (mf/deref refs/selected-shapes)
|
||||
(let [selected (mf/deref refs/selected-shapes)
|
||||
selected? (contains? selected (:id shape))
|
||||
on-mouse-down #(common/on-mouse-down % shape selected)]
|
||||
[:g.shape {:class (when selected? "selected")
|
||||
:on-mouse-down on-mouse-down}
|
||||
[:& circle-shape {:shape shape :modifiers modifiers}]]))
|
||||
[:& circle-shape {:shape shape}]]))
|
||||
|
||||
;; --- Circle Shape
|
||||
|
||||
(mf/defc circle-shape
|
||||
[{:keys [shape modifiers] :as props}]
|
||||
(let [{:keys [id rotation cx cy]} shape
|
||||
{:keys [resize displacement]} modifiers
|
||||
[{:keys [shape] :as props}]
|
||||
(let [{:keys [id rotation cx cy modifier-mtx]} shape
|
||||
|
||||
shape (cond-> shape
|
||||
displacement (geom/transform displacement)
|
||||
resize (geom/transform resize))
|
||||
shape (cond
|
||||
(gmt/matrix? modifier-mtx) (geom/transform shape modifier-mtx)
|
||||
:else shape)
|
||||
|
||||
center (gpt/point (:cx shape)
|
||||
(:cy shape))
|
||||
|
||||
rotation (or rotation 0)
|
||||
|
||||
moving? (boolean displacement)
|
||||
moving? (boolean modifier-mtx)
|
||||
|
||||
xfmt (-> (gmt/matrix)
|
||||
(gmt/rotate* rotation center))
|
||||
transform (when (pos? rotation)
|
||||
(str (-> (gmt/matrix)
|
||||
(gmt/rotate* rotation center))))
|
||||
|
||||
props {:id (str "shape-" id)
|
||||
:class (classnames :move-cursor moving?)
|
||||
:transform (str xfmt)}
|
||||
:transform transform}
|
||||
|
||||
attrs (merge props
|
||||
(attrs/extract-style-attrs shape)
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.ui.keyboard :as kbd]
|
||||
[uxbox.main.ui.workspace.streams :as ws]
|
||||
[uxbox.main.ui.workspace.streams :as uws]
|
||||
[uxbox.util.geom.matrix :as gmt]
|
||||
[uxbox.util.dom :as dom]))
|
||||
|
||||
;; --- Shape Movement (by mouse)
|
||||
|
@ -24,17 +25,15 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [pid (get-in state [:workspace :current])
|
||||
wst (get-in state [:workspace pid])
|
||||
stoper (->> stream
|
||||
(rx/filter ws/mouse-up?)
|
||||
(rx/take 1))
|
||||
stream (->> ws/mouse-position-deltas
|
||||
(rx/take-until stoper))]
|
||||
(rx/concat
|
||||
(when (refs/alignment-activated? (:flags wst))
|
||||
(rx/of (dw/initial-shape-align id)))
|
||||
(rx/map #(dw/apply-temporal-displacement id %) stream)
|
||||
(rx/of (dw/apply-displacement id)))))))
|
||||
flags (get-in state [:workspace pid :flags])
|
||||
stoper (rx/filter uws/mouse-up? stream)]
|
||||
(rx/concat
|
||||
(when (refs/alignment-activated? flags)
|
||||
(rx/of (dw/initial-shape-align id)))
|
||||
(->> uws/mouse-position-deltas
|
||||
(rx/map #(dw/apply-temporal-displacement id %))
|
||||
(rx/take-until stoper))
|
||||
(rx/of (dw/materialize-current-modifier id)))))))
|
||||
|
||||
(defn start-move-selected
|
||||
[]
|
||||
|
@ -45,7 +44,6 @@
|
|||
selected (get-in state [:workspace pid :selected])]
|
||||
(rx/from-coll (map start-move selected))))))
|
||||
|
||||
|
||||
(defn on-mouse-down
|
||||
[event {:keys [id] :as shape} selected]
|
||||
(let [selected? (contains? selected id)
|
||||
|
|
|
@ -23,14 +23,12 @@
|
|||
|
||||
(mf/defc icon-component
|
||||
[{:keys [shape] :as props}]
|
||||
(let [id (:id shape)
|
||||
modifiers (mf/deref (refs/selected-modifiers id))
|
||||
selected (mf/deref refs/selected-shapes)
|
||||
selected? (contains? selected id)
|
||||
(let [selected (mf/deref refs/selected-shapes)
|
||||
selected? (contains? selected (:id shape))
|
||||
on-mouse-down #(common/on-mouse-down % shape selected)]
|
||||
[:g.shape {:class (when selected? "selected")
|
||||
:on-mouse-down on-mouse-down}
|
||||
[:& icon-shape {:shape shape :modifiers modifiers}]]))
|
||||
[:& icon-shape {:shape shape}]]))
|
||||
|
||||
;; --- Icon Shape
|
||||
|
||||
|
@ -43,22 +41,20 @@
|
|||
(gmt/rotate* mt rotation center)))
|
||||
|
||||
(mf/defc icon-shape
|
||||
[{:keys [shape modifiers] :as props}]
|
||||
(let [{:keys [id content metadata rotation x1 y1]} shape
|
||||
{:keys [resize displacement]} modifiers
|
||||
[{:keys [shape] :as props}]
|
||||
(let [{:keys [id content metadata rotation modifier-mtx]} shape
|
||||
|
||||
xfmt (cond-> (gmt/matrix)
|
||||
displacement (gmt/multiply displacement)
|
||||
resize (gmt/multiply resize))
|
||||
shape (cond
|
||||
(gmt/matrix? modifier-mtx) (geom/transform shape modifier-mtx)
|
||||
:else shape)
|
||||
|
||||
{:keys [x1 y1 width height] :as shape} (-> (geom/transform shape xfmt)
|
||||
(geom/size))
|
||||
{:keys [x1 y1 width height] :as shape} (geom/size shape)
|
||||
|
||||
transform (when (pos? rotation)
|
||||
(str (rotate (gmt/matrix) shape)))
|
||||
|
||||
view-box (apply str (interpose " " (:view-box metadata)))
|
||||
xfmt (cond-> (gmt/matrix)
|
||||
(pos? rotation) (rotate shape))
|
||||
|
||||
moving? (boolean displacement)
|
||||
moving? (boolean modifier-mtx)
|
||||
props {:id (str id)
|
||||
:x x1
|
||||
:y y1
|
||||
|
@ -70,7 +66,7 @@
|
|||
:dangerouslySetInnerHTML #js {:__html content}}
|
||||
|
||||
attrs (merge props (attrs/extract-style-attrs shape))]
|
||||
[:g {:transform (str xfmt)}
|
||||
[:g {:transform transform}
|
||||
[:> :svg (normalize-props attrs) ]]))
|
||||
|
||||
;; --- Icon SVG
|
||||
|
|
|
@ -30,8 +30,7 @@
|
|||
|
||||
(mf/defc image-component
|
||||
[{:keys [shape] :as props}]
|
||||
(let [modifiers (mf/deref (refs/selected-modifiers (:id shape)))
|
||||
selected (mf/deref refs/selected-shapes)
|
||||
(let [selected (mf/deref refs/selected-shapes)
|
||||
image (mf/deref (image-ref (:image shape)))
|
||||
selected? (contains? selected (:id shape))
|
||||
on-mouse-down #(common/on-mouse-down % shape selected)]
|
||||
|
@ -42,27 +41,23 @@
|
|||
[:g.shape {:class (when selected? "selected")
|
||||
:on-mouse-down on-mouse-down}
|
||||
[:& image-shape {:shape shape
|
||||
:image image
|
||||
:modifiers modifiers}]])))
|
||||
:image image}]])))
|
||||
|
||||
;; --- Image Shape
|
||||
|
||||
(mf/defc image-shape
|
||||
[{:keys [shape image modifiers] :as props}]
|
||||
(let [{:keys [id x1 y1 width height]} (geom/size shape)
|
||||
{:keys [resize displacement]} modifiers
|
||||
[{:keys [shape image] :as props}]
|
||||
(let [{:keys [id x1 y1 width height modifier-mtx]} (geom/size shape)
|
||||
moving? (boolean modifier-mtx)
|
||||
transform (when (gmt/matrix? modifier-mtx)
|
||||
(str modifier-mtx))
|
||||
|
||||
xfmt (cond-> (gmt/matrix)
|
||||
resize (gmt/multiply resize)
|
||||
displacement (gmt/multiply displacement))
|
||||
|
||||
moving? (boolean displacement)
|
||||
props {:x x1 :y y1
|
||||
:id (str "shape-" id)
|
||||
:preserve-aspect-ratio "none"
|
||||
:class (classnames :move-cursor moving?)
|
||||
:xlink-href (:url image)
|
||||
:transform (str xfmt)
|
||||
:transform transform
|
||||
:width width
|
||||
:height height}
|
||||
attrs (merge props (attrs/extract-style-attrs shape))]
|
||||
|
|
|
@ -22,16 +22,13 @@
|
|||
|
||||
(mf/defc rect-component
|
||||
[{:keys [shape] :as props}]
|
||||
(let [id (:id shape)
|
||||
modifiers (mf/deref (refs/selected-modifiers id))
|
||||
selected (mf/deref refs/selected-shapes)
|
||||
selected? (contains? selected id)
|
||||
(let [selected (mf/deref refs/selected-shapes)
|
||||
selected? (contains? selected (:id shape))
|
||||
on-mouse-down #(common/on-mouse-down % shape selected)]
|
||||
;; shape (assoc shape :modifiers modifiers)]
|
||||
[:g.shape {:class (when selected? "selected")
|
||||
:on-mouse-down on-mouse-down}
|
||||
[:& rect-shape {:shape shape
|
||||
:modifiers modifiers}]]))
|
||||
[:& rect-shape {:shape shape}]]))
|
||||
|
||||
;; --- Rect Shape
|
||||
|
||||
|
@ -43,27 +40,25 @@
|
|||
(gmt/rotate* mt rotation center)))
|
||||
|
||||
(mf/defc rect-shape
|
||||
[{:keys [shape modifiers] :as props}]
|
||||
(let [{:keys [id rotation]} shape
|
||||
{:keys [displacement resize]} modifiers
|
||||
[{:keys [shape] :as props}]
|
||||
(let [{:keys [id rotation modifier-mtx]} shape
|
||||
|
||||
xfmt (cond-> (gmt/matrix)
|
||||
displacement (gmt/multiply displacement)
|
||||
resize (gmt/multiply resize))
|
||||
shape (cond
|
||||
(gmt/matrix? modifier-mtx) (geom/transform shape modifier-mtx)
|
||||
:else shape)
|
||||
|
||||
{:keys [x1 y1 width height] :as shape} (-> (geom/transform shape xfmt)
|
||||
(geom/size))
|
||||
{:keys [x1 y1 width height] :as shape} (geom/size shape)
|
||||
|
||||
xfmt (cond-> (gmt/matrix)
|
||||
(pos? rotation) (rotate shape))
|
||||
transform (when (pos? rotation)
|
||||
(str (rotate (gmt/matrix) shape)))
|
||||
|
||||
moving? (boolean displacement)
|
||||
moving? (boolean modifier-mtx)
|
||||
|
||||
props {:x x1 :y y1
|
||||
:id (str "shape-" id)
|
||||
:class-name (classnames :move-cursor moving?)
|
||||
:width width
|
||||
:height height
|
||||
:transform (str xfmt)}
|
||||
:transform transform}
|
||||
attrs (merge (attrs/extract-style-attrs shape) props)]
|
||||
[:> :rect (normalize-props attrs)]))
|
||||
|
|
|
@ -7,11 +7,12 @@
|
|||
|
||||
(ns uxbox.main.ui.workspace.canvas
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[lentes.core :as l]
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.main.constants :as c]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.data.workspace :as dw]
|
||||
[uxbox.main.geom :as geom]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.ui.keyboard :as kbd]
|
||||
[uxbox.main.ui.shapes :as uus]
|
||||
|
@ -33,20 +34,26 @@
|
|||
|
||||
(mf/defc canvas
|
||||
[{:keys [id] :as props}]
|
||||
(letfn [(on-double-click [event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (dw/select-canvas id)))]
|
||||
(let [canvas-iref (mf/use-memo #(make-canvas-iref id) #js [id])
|
||||
canvas (mf/deref canvas-iref)
|
||||
selected (mf/deref selected-canvas)
|
||||
selected? (= id selected)]
|
||||
(let [canvas-iref (mf/use-memo #(make-canvas-iref id) #js [id])
|
||||
canvas (-> (mf/deref canvas-iref)
|
||||
(geom/size))
|
||||
selected (mf/deref selected-canvas)
|
||||
selected? (= id selected)]
|
||||
(letfn [(on-double-click [event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (dw/select-canvas id)))
|
||||
(on-mouse-down [event]
|
||||
(when selected?
|
||||
(dom/stop-propagation event)
|
||||
#_(st/emit! (start-move id))))]
|
||||
[:rect.page-canvas
|
||||
{:x (:x canvas)
|
||||
{:x (:x1 canvas)
|
||||
:class (when selected? "selected")
|
||||
:y (:y canvas)
|
||||
:y (:y1 canvas)
|
||||
:fill (:background canvas "#ffffff")
|
||||
:width (:width canvas)
|
||||
:height (:height canvas)
|
||||
:on-mouse-down on-mouse-down
|
||||
:on-double-click on-double-click}])))
|
||||
|
||||
|
||||
|
|
|
@ -26,10 +26,6 @@
|
|||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.uuid :as uuid]))
|
||||
|
||||
(defn- rxfinalize
|
||||
[f ob]
|
||||
(.pipe ob (.finalize js/rxjs.operators f)))
|
||||
|
||||
;; --- Events
|
||||
|
||||
(declare handle-drawing)
|
||||
|
@ -64,6 +60,7 @@
|
|||
[{:type :rect
|
||||
:name "Rect"
|
||||
:stroke-color "#000000"}
|
||||
{:type :image}
|
||||
{:type :circle
|
||||
:name "Circle"}
|
||||
{:type :path
|
||||
|
@ -74,6 +71,9 @@
|
|||
:fill-color "#000000"
|
||||
:fill-opacity 0
|
||||
:segments []}
|
||||
{:type :canvas
|
||||
:name "Canvas"
|
||||
:stroke-color "#000000"}
|
||||
{:type :curve
|
||||
:name "Path"
|
||||
:stroke-style :solid
|
||||
|
@ -98,8 +98,8 @@
|
|||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [pid (get-in state [:workspace :current])
|
||||
shape (make-minimal-shape type)]
|
||||
(assoc-in state [:workspace pid :drawing] shape)))
|
||||
data (make-minimal-shape type)]
|
||||
(update-in state [:workspace pid :drawing] merge data)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
|
@ -118,7 +118,7 @@
|
|||
:y2 (+ (:y point) 2)})]
|
||||
(assoc-in state [:workspace pid :drawing] (assoc shape ::initialized? true))))
|
||||
|
||||
;; TODO: this is a new approach for resizing, when all the
|
||||
;; NOTE: this is a new approach for resizing, when all the
|
||||
;; subsystem are migrated to the new resize approach, this
|
||||
;; function should be moved into uxbox.main.geom ns.
|
||||
(resize-shape [shape point lock?]
|
||||
|
@ -331,11 +331,12 @@
|
|||
(declare path-draw-area)
|
||||
|
||||
(mf/defc draw-area
|
||||
[{:keys [zoom shape modifiers] :as props}]
|
||||
(case (:type shape)
|
||||
(:path :curve) [:& path-draw-area {:shape shape}]
|
||||
[:& generic-draw-area {:shape (assoc shape :modifiers modifiers)
|
||||
:zoom zoom}]))
|
||||
[{:keys [zoom shape] :as props}]
|
||||
(when (:id shape)
|
||||
(case (:type shape)
|
||||
(:path :curve) [:& path-draw-area {:shape shape}]
|
||||
[:& generic-draw-area {:shape shape
|
||||
:zoom zoom}])))
|
||||
|
||||
(mf/defc generic-draw-area
|
||||
[{:keys [shape zoom]}]
|
||||
|
|
|
@ -48,13 +48,11 @@
|
|||
|
||||
(on-uploaded [[image]]
|
||||
(let [{:keys [id name width height]} image
|
||||
shape {:type :image
|
||||
:name name
|
||||
:id (uuid/random)
|
||||
shape {:name name
|
||||
:metadata {:width width
|
||||
:height height}
|
||||
:image id}]
|
||||
(st/emit! (dw/select-for-drawing shape))
|
||||
(st/emit! (dw/select-for-drawing :image shape))
|
||||
(modal/hide!)))
|
||||
|
||||
(on-files-selected [event]
|
||||
|
@ -93,13 +91,11 @@
|
|||
(mf/defc image-item
|
||||
[{:keys [image] :as props}]
|
||||
(letfn [(on-click [event]
|
||||
(let [shape {:type :image
|
||||
:name (:name image)
|
||||
:id (uuid/random)
|
||||
(let [shape {:name (:name image)
|
||||
:metadata {:width (:width image)
|
||||
:height (:height image)}
|
||||
:image (:id image)}]
|
||||
(st/emit! (dw/select-for-drawing shape))
|
||||
(st/emit! (dw/select-for-drawing :image shape))
|
||||
(modal/hide!)))]
|
||||
[:div.library-item {:on-click on-click}
|
||||
[:div.library-item-th
|
||||
|
|
|
@ -40,11 +40,11 @@
|
|||
(let [result (geom/resize-shape vid shape point lock?)
|
||||
scale (geom/calculate-scale-ratio shape result)
|
||||
mtx (geom/generate-resize-matrix vid shape scale)
|
||||
xfm (map #(dw/apply-temporal-resize % mtx))]
|
||||
xfm (map #(dw/assoc-temporal-modifier % mtx))]
|
||||
(apply st/emit! (sequence xfm ids))))
|
||||
|
||||
(on-end []
|
||||
(apply st/emit! (map dw/apply-resize ids)))
|
||||
(apply st/emit! (map dw/materialize-current-modifier ids)))
|
||||
|
||||
;; Unifies the instantaneous proportion lock modifier
|
||||
;; activated by Ctrl key and the shapes own proportion
|
||||
|
|
|
@ -81,15 +81,17 @@
|
|||
ob (->> st/stream
|
||||
(rx/filter pointer-event?)
|
||||
(rx/filter #(= :viewport (:source %)))
|
||||
(rx/map :pt)
|
||||
)]
|
||||
(rx/map :pt))]
|
||||
(rx/subscribe-with ob sub)
|
||||
sub))
|
||||
|
||||
(defonce mouse-position-ctrl
|
||||
(let [sub (rx/behavior-subject nil)]
|
||||
(-> (rx/map :ctrl mouse-position)
|
||||
(rx/subscribe-with sub))
|
||||
(let [sub (rx/behavior-subject nil)
|
||||
ob (->> st/stream
|
||||
(rx/filter pointer-event?)
|
||||
(rx/map :ctrl)
|
||||
(rx/dedupe))]
|
||||
(rx/subscribe-with ob sub)
|
||||
sub))
|
||||
|
||||
(defonce mouse-position-deltas
|
||||
|
|
|
@ -284,156 +284,3 @@
|
|||
[:& ruler {:zoom zoom :ruler (:ruler wst)}])
|
||||
[:& selrect {:data (:selrect wst)}]]])))
|
||||
|
||||
|
||||
#_(mf/def viewport
|
||||
:init
|
||||
(fn [own props]
|
||||
(assoc own ::viewport (mf/create-ref)))
|
||||
|
||||
:did-mount
|
||||
(fn [own]
|
||||
(letfn [
|
||||
(translate-point-to-viewport [pt]
|
||||
(let [viewport (mf/ref-node (::viewport own))
|
||||
brect (.getBoundingClientRect viewport)
|
||||
brect (gpt/point (parse-int (.-left brect))
|
||||
(parse-int (.-top brect)))]
|
||||
(gpt/subtract pt brect)))
|
||||
|
||||
(on-key-down [event]
|
||||
(let [bevent (.getBrowserEvent event)
|
||||
key (.-keyCode event)
|
||||
ctrl? (kbd/ctrl? event)
|
||||
shift? (kbd/shift? event)
|
||||
opts {:key key
|
||||
:shift? shift?
|
||||
:ctrl? ctrl?}]
|
||||
(when-not (.-repeat bevent)
|
||||
(st/emit! (uws/keyboard-event :down key ctrl? shift?))
|
||||
(when (kbd/space? event)
|
||||
(st/emit! handle-viewport-positioning)
|
||||
#_(st/emit! (dw/start-viewport-positioning))))))
|
||||
|
||||
(on-key-up [event]
|
||||
(let [key (.-keyCode event)
|
||||
ctrl? (kbd/ctrl? event)
|
||||
shift? (kbd/shift? event)
|
||||
opts {:key key
|
||||
:shift? shift?
|
||||
:ctrl? ctrl?}]
|
||||
(when (kbd/space? event)
|
||||
(st/emit! ::finish-positioning #_(dw/stop-viewport-positioning)))
|
||||
(st/emit! (uws/keyboard-event :up key ctrl? shift?))))
|
||||
|
||||
(on-mousemove [event]
|
||||
(let [wpt (gpt/point (.-clientX event)
|
||||
(.-clientY event))
|
||||
vpt (translate-point-to-viewport wpt)
|
||||
ctrl? (kbd/ctrl? event)
|
||||
shift? (kbd/shift? event)
|
||||
event {:ctrl ctrl?
|
||||
:shift shift?
|
||||
:window-coords wpt
|
||||
:viewport-coords vpt}]
|
||||
(st/emit! (uws/pointer-event wpt vpt ctrl? shift?))))]
|
||||
|
||||
(let [key1 (events/listen js/document EventType.MOUSEMOVE on-mousemove)
|
||||
key2 (events/listen js/document EventType.KEYDOWN on-key-down)
|
||||
key3 (events/listen js/document EventType.KEYUP on-key-up)]
|
||||
(assoc own
|
||||
::key1 key1
|
||||
::key2 key2
|
||||
::key3 key3))))
|
||||
|
||||
:will-unmount
|
||||
(fn [own]
|
||||
(events/unlistenByKey (::key1 own))
|
||||
(events/unlistenByKey (::key2 own))
|
||||
(events/unlistenByKey (::key3 own))
|
||||
(dissoc own ::key1 ::key2 ::key3))
|
||||
|
||||
:mixins [mf/reactive]
|
||||
|
||||
:render
|
||||
(fn [own {:keys [page] :as props}]
|
||||
(let [{:keys [drawing-tool tooltip zoom flags edition] :as wst} (mf/react refs/workspace)
|
||||
tooltip (or tooltip (get-shape-tooltip drawing-tool))
|
||||
zoom (or zoom 1)]
|
||||
(letfn [(on-mouse-down [event]
|
||||
(dom/stop-propagation event)
|
||||
(let [ctrl? (kbd/ctrl? event)
|
||||
shift? (kbd/shift? event)
|
||||
opts {:shift? shift?
|
||||
:ctrl? ctrl?}]
|
||||
(st/emit! (uws/mouse-event :down ctrl? shift?)))
|
||||
(when (not edition)
|
||||
(if drawing-tool
|
||||
(st/emit! (start-drawing drawing-tool))
|
||||
(st/emit! :interrupt handle-selrect))))
|
||||
(on-context-menu [event]
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(let [ctrl? (kbd/ctrl? event)
|
||||
shift? (kbd/shift? event)
|
||||
opts {:shift? shift?
|
||||
:ctrl? ctrl?}]
|
||||
(st/emit! (uws/mouse-event :context-menu ctrl? shift?))))
|
||||
(on-mouse-up [event]
|
||||
(dom/stop-propagation event)
|
||||
(let [ctrl? (kbd/ctrl? event)
|
||||
shift? (kbd/shift? event)
|
||||
opts {:shift? shift?
|
||||
:ctrl? ctrl?}]
|
||||
(st/emit! (uws/mouse-event :up ctrl? shift?))))
|
||||
(on-click [event]
|
||||
(dom/stop-propagation event)
|
||||
(let [ctrl? (kbd/ctrl? event)
|
||||
shift? (kbd/shift? event)
|
||||
opts {:shift? shift?
|
||||
:ctrl? ctrl?}]
|
||||
(st/emit! (uws/mouse-event :click ctrl? shift?))))
|
||||
(on-double-click [event]
|
||||
(dom/stop-propagation event)
|
||||
(let [ctrl? (kbd/ctrl? event)
|
||||
shift? (kbd/shift? event)
|
||||
opts {:shift? shift?
|
||||
:ctrl? ctrl?}]
|
||||
(st/emit! (uws/mouse-event :double-click ctrl? shift?))))]
|
||||
[:*
|
||||
[:& coordinates {:zoom zoom}]
|
||||
[:div.tooltip-container
|
||||
(when tooltip
|
||||
[:& cursor-tooltip {:tooltip tooltip}])]
|
||||
[:svg.viewport {:width (* c/viewport-width zoom)
|
||||
:height (* c/viewport-height zoom)
|
||||
:ref (::viewport own)
|
||||
:class (when drawing-tool "drawing")
|
||||
:on-context-menu on-context-menu
|
||||
:on-click on-click
|
||||
:on-double-click on-double-click
|
||||
:on-mouse-down on-mouse-down
|
||||
:on-mouse-up on-mouse-up}
|
||||
[:g.zoom {:transform (str "scale(" zoom ", " zoom ")")}
|
||||
(when page
|
||||
[:& canvas {:page page :wst wst}])
|
||||
|
||||
(when page
|
||||
[:*
|
||||
(for [id (reverse (:shapes page))]
|
||||
[:& uus/shape-component {:id id :key id}])
|
||||
|
||||
(when (seq (:selected wst))
|
||||
[:& selection-handlers {:wst wst}])
|
||||
|
||||
(when-let [dshape (:drawing wst)]
|
||||
[:& draw-area {:shape dshape
|
||||
:zoom (:zoom wst)
|
||||
:modifiers (:modifiers wst)}])])
|
||||
|
||||
|
||||
|
||||
(if (contains? flags :grid)
|
||||
[:& grid {:page page}])]
|
||||
(when (contains? flags :ruler)
|
||||
[:& ruler {:zoom zoom :ruler (:ruler wst)}])
|
||||
[:& selrect {:data (:selrect wst)}]]]))))
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
(:require [cljs.test :as t :include-macros true]
|
||||
[cljs.pprint :refer [pprint]]
|
||||
[uxbox.util.uuid :as uuid]
|
||||
[uxbox.main.data.shapes-impl :as impl]))
|
||||
[uxbox.main.data.shapes :as impl]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Duplicate (one shape)
|
||||
|
|
Loading…
Add table
Reference in a new issue