0
Fork 0
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:
Andrey Antukh 2019-08-22 20:02:14 +02:00
parent 1fa9faa314
commit 6483800e49
14 changed files with 144 additions and 339 deletions

View file

@ -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

View file

@ -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}]

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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))]

View file

@ -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)]))

View file

@ -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}])))

View file

@ -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]}]

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)}]]]))))

View file

@ -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)