mirror of
https://github.com/penpot/penpot.git
synced 2025-05-21 08:36:11 +02:00
♻️ Initial refactor of page data structure (wip).
Still work in progress but is a necessary step for a future (re)introduction of groups.
This commit is contained in:
parent
cbad98b783
commit
ba373573e0
29 changed files with 1116 additions and 787 deletions
|
@ -9,8 +9,8 @@
|
|||
(def viewport-width 4000)
|
||||
(def viewport-height 4000)
|
||||
|
||||
(def canvas-start-x 1200)
|
||||
(def canvas-start-y 1200)
|
||||
(def frame-start-x 1200)
|
||||
(def frame-start-y 1200)
|
||||
|
||||
(def grid-x-axis 10)
|
||||
(def grid-y-axis 10)
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -11,7 +11,7 @@
|
|||
[rumext.alpha :as mf]
|
||||
[uxbox.util.math :as mth]
|
||||
[uxbox.main.geom :as geom]
|
||||
[uxbox.main.ui.shapes.canvas :as canvas]
|
||||
[uxbox.main.ui.shapes.frame :as frame]
|
||||
[uxbox.main.ui.shapes.circle :as circle]
|
||||
[uxbox.main.ui.shapes.icon :as icon]
|
||||
[uxbox.main.ui.shapes.image :as image]
|
||||
|
@ -40,7 +40,7 @@
|
|||
[{:keys [shape] :as props}]
|
||||
(when (and shape (not (:hidden shape)))
|
||||
(case (:type shape)
|
||||
:canvas [:& rect/rect-shape {:shape shape}]
|
||||
:frame [:& rect/rect-shape {:shape shape}]
|
||||
:curve [:& path/path-shape {:shape shape}]
|
||||
:text [:& text/text-shape {:shape shape}]
|
||||
:icon [:& icon/icon-shape {:shape shape}]
|
||||
|
@ -53,7 +53,7 @@
|
|||
[{:keys [data] :as props}]
|
||||
(let [shapes-by-id (:shapes-by-id data)
|
||||
shapes (map #(get shapes-by-id %) (:shapes data []))
|
||||
canvas (map #(get shapes-by-id %) (:canvas data []))
|
||||
frame (map #(get shapes-by-id %) (:frame data []))
|
||||
dim (calculate-dimensions data)]
|
||||
[:svg {:view-box (str "0 0 " (:width dim 0) " " (:height dim 0))
|
||||
:version "1.1"
|
||||
|
@ -61,7 +61,7 @@
|
|||
:xmlns "http://www.w3.org/2000/svg"}
|
||||
(background)
|
||||
[:*
|
||||
(for [item canvas]
|
||||
(for [item frame]
|
||||
[:& shape-wrapper {:shape item :key (:id item)}])
|
||||
(for [item shapes]
|
||||
[:& shape-wrapper {:shape item :key (:id item)}])]]))
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
:icon (move-rect shape dpoint)
|
||||
:image (move-rect shape dpoint)
|
||||
:rect (move-rect shape dpoint)
|
||||
:canvas (move-rect shape dpoint)
|
||||
:frame (move-rect shape dpoint)
|
||||
:text (move-rect shape dpoint)
|
||||
:curve (move-path shape dpoint)
|
||||
:path (move-path shape dpoint)
|
||||
|
@ -69,7 +69,7 @@
|
|||
[shape position]
|
||||
(case (:type shape)
|
||||
:icon (absolute-move-rect shape position)
|
||||
:canvas (absolute-move-rect shape position)
|
||||
:frame (absolute-move-rect shape position)
|
||||
:image (absolute-move-rect shape position)
|
||||
:rect (absolute-move-rect shape position)
|
||||
:circle (absolute-move-circle shape position)))
|
||||
|
@ -482,6 +482,25 @@
|
|||
:width width
|
||||
:height height)))
|
||||
|
||||
;; --- Resolve Shape
|
||||
|
||||
(declare resolve-rect-shape)
|
||||
(declare translate-from-frame)
|
||||
(declare translate-to-frame)
|
||||
|
||||
(defn resolve-shape
|
||||
[objects shape]
|
||||
(case (:type shape)
|
||||
:rect (resolve-rect-shape objects shape)
|
||||
:frame (resolve-rect-shape objects shape)))
|
||||
|
||||
(defn- resolve-rect-shape
|
||||
[objects {:keys [parent] :as shape}]
|
||||
(loop [pobj (get objects parent)]
|
||||
(if (= :frame (:type pobj))
|
||||
(translate-from-frame shape pobj)
|
||||
(recur (get objects (:parent pobj))))))
|
||||
|
||||
;; --- Transform Shape
|
||||
|
||||
(declare transform-rect)
|
||||
|
@ -492,7 +511,7 @@
|
|||
"Apply the matrix transformation to shape."
|
||||
[{:keys [type] :as shape} xfmt]
|
||||
(case type
|
||||
:canvas (transform-rect shape xfmt)
|
||||
:frame (transform-rect shape xfmt)
|
||||
:rect (transform-rect shape xfmt)
|
||||
:icon (transform-rect shape xfmt)
|
||||
:text (transform-rect shape xfmt)
|
||||
|
@ -599,6 +618,14 @@
|
|||
:height (- maxy miny)
|
||||
:type :rect}))
|
||||
|
||||
(defn translate-to-frame
|
||||
[shape {:keys [x y] :as frame}]
|
||||
(move shape (gpt/point (- x) (- y))))
|
||||
|
||||
(defn translate-from-frame
|
||||
[shape {:keys [x y] :as frame}]
|
||||
(move shape (gpt/point (+ x) (+ y))))
|
||||
|
||||
;; --- Helpers
|
||||
|
||||
(defn contained-in?
|
||||
|
|
|
@ -59,8 +59,8 @@
|
|||
(-> (l/lens #(contains? % id))
|
||||
(l/derive selected-shapes)))
|
||||
|
||||
(def selected-canvas
|
||||
(-> (l/key :selected-canvas)
|
||||
(def selected-frame
|
||||
(-> (l/key :selected-frame)
|
||||
(l/derive workspace-local)))
|
||||
|
||||
(def toolboxes
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
[rumext.alpha :as mf]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.ui.shapes.canvas :as canvas]))
|
||||
[uxbox.main.ui.shapes.frame :as frame]))
|
||||
|
||||
(def shape-wrapper canvas/shape-wrapper)
|
||||
(def canvas-wrapper canvas/canvas-wrapper)
|
||||
(def shape-wrapper frame/shape-wrapper)
|
||||
(def frame-wrapper frame/frame-wrapper)
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
;; Copyright (c) 2016-2017 Andrey Antukh <niwi@niwi.nz>
|
||||
|
||||
(ns uxbox.main.ui.shapes.attrs
|
||||
(:require [cuerdas.core :as str]))
|
||||
(:require
|
||||
[cuerdas.core :as str]
|
||||
[uxbox.util.interop :as interop]))
|
||||
|
||||
|
||||
;; (defn camel-case
|
||||
|
@ -58,7 +60,8 @@
|
|||
(case style
|
||||
:mixed "5,5,1,5"
|
||||
:dotted "5,5"
|
||||
:dashed "10,10"))
|
||||
:dashed "10,10"
|
||||
nil))
|
||||
|
||||
(defn- transform-stroke-attrs
|
||||
[{:keys [stroke-style] :or {stroke-style :none} :as attrs}]
|
||||
|
@ -75,3 +78,21 @@
|
|||
(-> (select-keys shape shape-style-attrs)
|
||||
(transform-stroke-attrs)
|
||||
(process-attrs)))
|
||||
|
||||
|
||||
;; TODO: migrate all the code to use this function and then, rename.
|
||||
|
||||
(defn extract-style-attrs2
|
||||
[shape]
|
||||
(let [stroke-style (:stroke-style shape :none)
|
||||
attrs #js {:fill (:fill-color shape nil)
|
||||
:opacity (:opacity shape nil)
|
||||
:rx (:rx shape nil)
|
||||
:ry (:ry shape nil)}]
|
||||
(when (not= :none stroke-style)
|
||||
(interop/obj-assign! attrs
|
||||
#js {:stroke (:stroke-color shape nil)
|
||||
:strokeWidth (:stroke-width shape nil)
|
||||
:strokeOpacity (:stroke-opacity shape nil)
|
||||
:strokeDasharray (stroke-type->dasharray stroke-style)}))
|
||||
attrs))
|
||||
|
|
|
@ -43,21 +43,21 @@
|
|||
(rx/of (dw/materialize-displacement-in-bulk selected)
|
||||
::dw/page-data-update))))))
|
||||
|
||||
(def start-move-canvas
|
||||
(def start-move-frame
|
||||
(ptk/reify ::start-move-selected
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [flags (get-in state [:workspace-local :flags])
|
||||
selected (get-in state [:workspace-local :selected])
|
||||
stoper (rx/filter uws/mouse-up? stream)
|
||||
canvas-id (first selected)
|
||||
frame-id (first selected)
|
||||
position @uws/mouse-position]
|
||||
|
||||
(rx/concat
|
||||
(->> (uws/mouse-position-deltas position)
|
||||
(rx/map #(dw/apply-canvas-displacement canvas-id %))
|
||||
(rx/map #(dw/apply-frame-displacement frame-id %))
|
||||
(rx/take-until stoper))
|
||||
(rx/of (dw/materialize-canvas-displacement canvas-id)))))))
|
||||
(rx/of (dw/materialize-frame-displacement frame-id)))))))
|
||||
|
||||
(defn on-mouse-down
|
||||
([event shape] (on-mouse-down event shape nil))
|
||||
|
@ -70,10 +70,10 @@
|
|||
drawing?
|
||||
nil
|
||||
|
||||
(= type :canvas)
|
||||
(= type :frame)
|
||||
(when selected?
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! start-move-canvas))
|
||||
(st/emit! start-move-frame))
|
||||
|
||||
(and (not selected?) (empty? selected))
|
||||
(do
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
;; Copyright (c) 2015-2020 Andrey Antukh <niwi@niwi.nz>
|
||||
;; Copyright (c) 2015-2020 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
(ns uxbox.main.ui.shapes.canvas
|
||||
(ns uxbox.main.ui.shapes.frame
|
||||
(:require
|
||||
[lentes.core :as l]
|
||||
[rumext.alpha :as mf]
|
||||
|
@ -30,14 +30,24 @@
|
|||
[uxbox.util.geom.matrix :as gmt]
|
||||
[uxbox.util.geom.point :as gpt]))
|
||||
|
||||
(declare canvas-wrapper)
|
||||
(declare frame-wrapper)
|
||||
|
||||
|
||||
(defn wrap-memo-shape
|
||||
([component]
|
||||
(js/React.memo
|
||||
component
|
||||
(fn [np op]
|
||||
(let [n-shape (aget np "shape")
|
||||
o-shape (aget op "shape")]
|
||||
(= n-shape o-shape))))))
|
||||
|
||||
(mf/defc shape-wrapper
|
||||
{:wrap [#(mf/wrap-memo % =)]}
|
||||
{:wrap [wrap-memo-shape]}
|
||||
[{:keys [shape] :as props}]
|
||||
(when (and shape (not (:hidden shape)))
|
||||
(case (:type shape)
|
||||
:canvas [:& canvas-wrapper {:shape shape :childs []}]
|
||||
:frame [:& frame-wrapper {:shape shape :childs []}]
|
||||
:curve [:& path/path-wrapper {:shape shape}]
|
||||
:text [:& text/text-wrapper {:shape shape}]
|
||||
:icon [:& icon/icon-wrapper {:shape shape}]
|
||||
|
@ -46,22 +56,48 @@
|
|||
:image [:& image/image-wrapper {:shape shape}]
|
||||
:circle [:& circle/circle-wrapper {:shape shape}])))
|
||||
|
||||
(def canvas-default-props
|
||||
(def frame-default-props
|
||||
{:fill-color "#ffffff"})
|
||||
|
||||
(declare canvas-shape)
|
||||
(declare translate-to-canvas)
|
||||
(declare frame-shape)
|
||||
(declare translate-to-frame)
|
||||
|
||||
(mf/defc canvas-wrapper
|
||||
{:wrap [#(mf/wrap-memo % =)]}
|
||||
[{:keys [shape childs] :as props}]
|
||||
(def kaka [1 2 3])
|
||||
|
||||
(defn wrap-memo-frame
|
||||
([component]
|
||||
(js/React.memo
|
||||
component
|
||||
(fn [np op]
|
||||
(let [n-shape (aget np "shape")
|
||||
o-shape (aget op "shape")
|
||||
n-objs (aget np "objects")
|
||||
o-objs (aget op "objects")
|
||||
|
||||
ids (:shapes n-shape)]
|
||||
(and (identical? n-shape o-shape)
|
||||
(loop [id (first ids)
|
||||
ids (rest ids)]
|
||||
(if (nil? id)
|
||||
true
|
||||
(if (identical? (get n-objs id)
|
||||
(get o-objs id))
|
||||
(recur (first ids) (rest ids))
|
||||
false)))))))))
|
||||
|
||||
|
||||
(mf/defc frame-wrapper
|
||||
{:wrap [wrap-memo-frame]}
|
||||
[{:keys [shape objects] :as props}]
|
||||
(when (and shape (not (:hidden shape)))
|
||||
(let [selected-iref (mf/use-memo
|
||||
{:fn #(refs/make-selected (:id shape))
|
||||
:deps (mf/deps (:id shape))})
|
||||
selected? (mf/deref selected-iref)
|
||||
on-mouse-down #(common/on-mouse-down % shape)
|
||||
shape (merge canvas-default-props shape)
|
||||
shape (merge frame-default-props shape)
|
||||
|
||||
childs (mapv #(get objects %) (:shapes shape))
|
||||
|
||||
on-double-click
|
||||
(fn [event]
|
||||
|
@ -71,9 +107,9 @@
|
|||
[:g {:class (when selected? "selected")
|
||||
:on-double-click on-double-click
|
||||
:on-mouse-down on-mouse-down}
|
||||
[:& canvas-shape {:shape shape :childs childs}]])))
|
||||
[:& frame-shape {:shape shape :childs childs}]])))
|
||||
|
||||
(mf/defc canvas-shape
|
||||
(mf/defc frame-shape
|
||||
[{:keys [shape childs] :as props}]
|
||||
(let [rotation (:rotation shape)
|
||||
ds-modifier (:displacement-modifier shape)
|
||||
|
@ -93,7 +129,7 @@
|
|||
:height height
|
||||
))
|
||||
|
||||
translate #(translate-to-canvas % ds-modifier (gpt/point (- x) (- y)))
|
||||
translate #(translate-to-frame % ds-modifier (gpt/point (- x) (- y)))
|
||||
]
|
||||
|
||||
[:svg {:x x :y y :width width :height height}
|
||||
|
@ -101,12 +137,12 @@
|
|||
(for [item childs]
|
||||
[:& shape-wrapper {:shape (translate item) :key (:id item)}])]))
|
||||
|
||||
(defn- translate-to-canvas
|
||||
[shape canvas-ds-modifier pt]
|
||||
(defn- translate-to-frame
|
||||
[shape frame-ds-modifier pt]
|
||||
(let [rz-modifier (:resize-modifier shape)
|
||||
shape (cond-> shape
|
||||
(gmt/matrix? canvas-ds-modifier)
|
||||
(geom/transform canvas-ds-modifier)
|
||||
(gmt/matrix? frame-ds-modifier)
|
||||
(geom/transform frame-ds-modifier)
|
||||
|
||||
(gmt/matrix? rz-modifier)
|
||||
(-> (geom/transform rz-modifier)
|
|
@ -12,8 +12,7 @@
|
|||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.ui.shapes.attrs :as attrs]
|
||||
[uxbox.main.ui.shapes.common :as common]
|
||||
[uxbox.util.data :refer [classnames normalize-props]]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.interop :as interop]
|
||||
[uxbox.util.geom.matrix :as gmt]
|
||||
[uxbox.util.geom.point :as gpt]))
|
||||
|
||||
|
@ -21,23 +20,19 @@
|
|||
|
||||
(declare rect-shape)
|
||||
|
||||
(mf/defc rect-wrapper
|
||||
{:wrap [#(mf/wrap-memo % =)]}
|
||||
[{:keys [shape] :as props}]
|
||||
(let [selected-iref (mf/use-memo
|
||||
{:fn #(refs/make-selected (:id shape))
|
||||
:deps (mf/deps (:id shape))})
|
||||
selected? (mf/deref selected-iref)
|
||||
(mf/defrc rect-wrapper
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
on-mouse-down #(common/on-mouse-down % shape)]
|
||||
[:g.shape {:class (when selected? "selected")
|
||||
:on-mouse-down on-mouse-down}
|
||||
[:g.shape {:on-mouse-down on-mouse-down}
|
||||
[:& rect-shape {:shape shape}]]))
|
||||
|
||||
;; --- Rect Shape
|
||||
|
||||
(mf/defc rect-shape
|
||||
[{:keys [shape] :as props}]
|
||||
(let [ds-modifier (:displacement-modifier shape)
|
||||
(mf/defrc rect-shape
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
ds-modifier (:displacement-modifier shape)
|
||||
rz-modifier (:resize-modifier shape)
|
||||
|
||||
shape (cond-> shape
|
||||
|
@ -52,12 +47,13 @@
|
|||
(+ x (/ width 2))
|
||||
(+ y (/ height 2))))
|
||||
|
||||
props (-> (attrs/extract-style-attrs shape)
|
||||
(assoc :x x
|
||||
:y y
|
||||
:transform transform
|
||||
:id (str "shape-" id)
|
||||
:width width
|
||||
:height height
|
||||
))]
|
||||
[:& "rect" props]))
|
||||
props (-> (attrs/extract-style-attrs2 shape)
|
||||
(interop/obj-assign!
|
||||
#js {:x x
|
||||
:y y
|
||||
:transform transform
|
||||
:id (str "shape-" id)
|
||||
:width width
|
||||
:height height}))]
|
||||
|
||||
[:> "rect" props]))
|
||||
|
|
|
@ -45,10 +45,10 @@
|
|||
(st/emit! (ms/->ScrollEvent (gpt/point left top)))))
|
||||
|
||||
(defn- on-wheel
|
||||
[event canvas]
|
||||
[event frame]
|
||||
(when (kbd/ctrl? event)
|
||||
(let [prev-zoom @refs/selected-zoom
|
||||
dom (mf/ref-node canvas)
|
||||
dom (mf/ref-node frame)
|
||||
scroll-position (scroll/get-current-position-absolute dom)
|
||||
mouse-point @ms/mouse-position]
|
||||
(dom/prevent-default event)
|
||||
|
@ -60,7 +60,7 @@
|
|||
|
||||
(mf/defc workspace-content
|
||||
[{:keys [page file flags] :as params}]
|
||||
(let [canvas (mf/use-ref nil)
|
||||
(let [frame (mf/use-ref nil)
|
||||
layout (mf/deref refs/workspace-layout)
|
||||
left-sidebar? (not (empty? (keep layout [:layers :sitemap
|
||||
:document-history])))
|
||||
|
@ -77,7 +77,7 @@
|
|||
[:section.workspace-content
|
||||
{:class classes
|
||||
:on-scroll on-scroll
|
||||
:on-wheel #(on-wheel % canvas)}
|
||||
:on-wheel #(on-wheel % frame)}
|
||||
|
||||
[:& history-dialog]
|
||||
|
||||
|
@ -87,7 +87,7 @@
|
|||
[:& horizontal-rule]
|
||||
[:& vertical-rule]])
|
||||
|
||||
[:section.workspace-viewport {:id "workspace-viewport" :ref canvas}
|
||||
[:section.workspace-viewport {:id "workspace-viewport" :ref frame}
|
||||
[:& viewport {:page page}]]]
|
||||
|
||||
;; Aside
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
:fill-color "#000000"
|
||||
:fill-opacity 0
|
||||
:segments []}
|
||||
{:type :canvas
|
||||
{:type :frame
|
||||
:name "Canvas"}
|
||||
{:type :curve
|
||||
:name "Path"
|
||||
|
@ -281,8 +281,8 @@
|
|||
shape (dissoc shape ::initialized? :resize-modifier)]
|
||||
;; Add & select the created shape to the workspace
|
||||
(rx/of dw/deselect-all
|
||||
(if (= :canvas (:type shape))
|
||||
(dw/add-canvas shape)
|
||||
(if (= :frame (:type shape))
|
||||
(dw/add-frame shape)
|
||||
(dw/add-shape shape))))))))))
|
||||
|
||||
(def close-drawing-path
|
||||
|
|
|
@ -94,9 +94,9 @@
|
|||
[:div.workspace-options
|
||||
[:ul.options-btn
|
||||
[:li.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.header.canvas")
|
||||
:class (when (= selected-drawtool :canvas) "selected")
|
||||
:on-click (partial select-drawtool :canvas)}
|
||||
{:alt (tr "workspace.header.frame")
|
||||
:class (when (= selected-drawtool :frame) "selected")
|
||||
:on-click (partial select-drawtool :frame)}
|
||||
i/artboard]
|
||||
[:li.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.header.rect")
|
||||
|
|
|
@ -133,7 +133,7 @@
|
|||
:stroke-opacity "1"}}]
|
||||
|
||||
(when (and (fn? on-rotate)
|
||||
(not= :canvas (:type shape)))
|
||||
(not= :frame (:type shape)))
|
||||
[:*
|
||||
[:path {:stroke "#31EFB8"
|
||||
:stroke-opacity "1"
|
||||
|
@ -255,7 +255,7 @@
|
|||
:on-resize on-resize}]))
|
||||
|
||||
(mf/defc single-selection-handlers
|
||||
[{:keys [shape zoom] :as props}]
|
||||
[{:keys [shape zoom objects] :as props}]
|
||||
(let [on-resize #(do (dom/stop-propagation %2)
|
||||
(st/emit! (start-resize %1 #{(:id shape)} shape)))
|
||||
on-rotate #(do (dom/stop-propagation %)
|
||||
|
@ -263,6 +263,7 @@
|
|||
|
||||
ds-modifier (:displacement-modifier shape)
|
||||
rz-modifier (:resize-modifier shape)
|
||||
;; shape (geom/resolve-shape objects shape)
|
||||
shape (cond-> (geom/shape->rect-shape shape)
|
||||
(gmt/matrix? rz-modifier) (geom/transform rz-modifier)
|
||||
(gmt/matrix? ds-modifier) (geom/transform ds-modifier))]
|
||||
|
@ -274,11 +275,13 @@
|
|||
|
||||
(mf/defc selection-handlers
|
||||
[{:keys [selected edition zoom] :as props}]
|
||||
(let [data (mf/deref refs/workspace-data)
|
||||
(let [data (mf/deref refs/workspace-data)
|
||||
objects (:objects data)
|
||||
|
||||
;; We need remove posible nil values because on shape
|
||||
;; deletion many shape will reamin selected and deleted
|
||||
;; in the same time for small instant of time
|
||||
shapes (->> (map #(get-in data [:shapes-by-id %]) selected)
|
||||
shapes (->> (map #(get objects %) selected)
|
||||
(remove nil?))
|
||||
num (count shapes)
|
||||
{:keys [id type] :as shape} (first shapes)]
|
||||
|
@ -303,4 +306,5 @@
|
|||
|
||||
:else
|
||||
[:& single-selection-handlers {:shape shape
|
||||
:objects objects
|
||||
:zoom zoom}])))
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
[uxbox.main.ui.shapes.icon :as icon]
|
||||
[uxbox.main.ui.workspace.sortable :refer [use-sortable]]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.uuid :as uuid]
|
||||
[uxbox.util.i18n :as i18n :refer [t]]))
|
||||
|
||||
(def ^:private shapes-iref
|
||||
|
@ -76,34 +77,35 @@
|
|||
{:on-double-click on-click}
|
||||
(:name shape "")])))
|
||||
|
||||
;; --- Layer Item
|
||||
|
||||
(def strip-attrs
|
||||
#(select-keys % [:id :frame :name :type :hidden :blocked]))
|
||||
|
||||
(mf/defc layer-item
|
||||
{:wrap [#(mf/wrap-memo % =)]}
|
||||
[{:keys [shape selected index] :as props}]
|
||||
(let [selected? (contains? selected (:id shape))
|
||||
|
||||
{:wrap [mf/wrap-memo]}
|
||||
[{:keys [index item selected] :as props}]
|
||||
(let [selected? (contains? selected (:id item))
|
||||
toggle-blocking
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(if (:blocked shape)
|
||||
(st/emit! (dw/unblock-shape (:id shape)))
|
||||
(st/emit! (dw/block-shape (:id shape)))))
|
||||
(if (:blocked item)
|
||||
(st/emit! (dw/unblock-shape (:id item)))
|
||||
(st/emit! (dw/block-shape (:id item)))))
|
||||
|
||||
toggle-visibility
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(if (:hidden shape)
|
||||
(st/emit! (dw/show-shape (:id shape)))
|
||||
(st/emit! (dw/hide-shape (:id shape)))))
|
||||
(if (:hidden item)
|
||||
(st/emit! (dw/show-shape (:id item)))
|
||||
(st/emit! (dw/hide-shape (:id item)))))
|
||||
|
||||
select-shape
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(let [id (:id shape)]
|
||||
(let [id (:id item)]
|
||||
(cond
|
||||
(or (:blocked shape)
|
||||
(:hidden shape))
|
||||
(or (:blocked item)
|
||||
(:hidden item))
|
||||
nil
|
||||
|
||||
(.-ctrlKey event)
|
||||
|
@ -118,7 +120,7 @@
|
|||
|
||||
on-drop
|
||||
(fn [item monitor]
|
||||
(st/emit! (dw/commit-shape-order-change (:shape-id item))))
|
||||
#_(st/emit! (dw/commit-shape-order-change (:shape-id item))))
|
||||
|
||||
on-hover
|
||||
(fn [item monitor]
|
||||
|
@ -126,8 +128,8 @@
|
|||
|
||||
[dprops dnd-ref] (use-sortable
|
||||
{:type "layer-item"
|
||||
:data {:shape-id (:id shape)
|
||||
:page-id (:page shape)
|
||||
:data {:shape-id (:id item)
|
||||
:page-id (:page item)
|
||||
:index index}
|
||||
:on-hover on-hover
|
||||
:on-drop on-drop})]
|
||||
|
@ -139,24 +141,22 @@
|
|||
:on-click select-shape
|
||||
:on-double-click #(dom/stop-propagation %)}
|
||||
[:div.element-actions
|
||||
[:div.toggle-element {:class (when-not (:hidden shape) "selected")
|
||||
[:div.toggle-element {:class (when-not (:hidden item) "selected")
|
||||
:on-click toggle-visibility}
|
||||
i/eye]
|
||||
[:div.block-element {:class (when (:blocked shape) "selected")
|
||||
[:div.block-element {:class (when (:blocked item) "selected")
|
||||
:on-click toggle-blocking}
|
||||
i/lock]]
|
||||
[:& element-icon {:shape shape}]
|
||||
[:& layer-name {:shape shape}]]]))
|
||||
[:& element-icon {:shape item}]
|
||||
[:& layer-name {:shape item}]]]))
|
||||
|
||||
(mf/defc canvas-item
|
||||
(mf/defc layer-frame-item
|
||||
{:wrap [#(mf/wrap-memo % =)]}
|
||||
[{:keys [canvas shapes selected index] :as props}]
|
||||
(let [selected? (contains? selected (:id canvas))
|
||||
[{:keys [item selected index objects] :as props}]
|
||||
(let [selected? (contains? selected (:id item))
|
||||
local (mf/use-state {:collapsed false})
|
||||
collapsed? (:collapsed @local)
|
||||
|
||||
shapes (filter #(= (:canvas (second %)) (:id canvas)) shapes)
|
||||
|
||||
toggle-collapse
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
|
@ -165,24 +165,24 @@
|
|||
toggle-blocking
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(if (:blocked canvas)
|
||||
(st/emit! (dw/unblock-shape (:id canvas)))
|
||||
(st/emit! (dw/block-shape (:id canvas)))))
|
||||
(if (:blocked item)
|
||||
(st/emit! (dw/unblock-shape (:id item)))
|
||||
(st/emit! (dw/block-shape (:id item)))))
|
||||
|
||||
toggle-visibility
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(if (:hidden canvas)
|
||||
(st/emit! (dw/show-canvas (:id canvas)))
|
||||
(st/emit! (dw/hide-canvas (:id canvas)))))
|
||||
(if (:hidden item)
|
||||
(st/emit! (dw/show-frame (:id item)))
|
||||
(st/emit! (dw/hide-frame (:id item)))))
|
||||
|
||||
select-shape
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(let [id (:id canvas)]
|
||||
(let [id (:id item)]
|
||||
(cond
|
||||
(or (:blocked canvas)
|
||||
(:hidden canvas))
|
||||
(or (:blocked item)
|
||||
(:hidden item))
|
||||
nil
|
||||
|
||||
(.-ctrlKey event)
|
||||
|
@ -201,13 +201,13 @@
|
|||
|
||||
on-hover
|
||||
(fn [item monitor]
|
||||
(st/emit! (dw/change-canvas-order {:id (:canvas-id item)
|
||||
(st/emit! (dw/change-frame-order {:id (:frame-id item)
|
||||
:index index})))
|
||||
|
||||
[dprops dnd-ref] (use-sortable
|
||||
{:type "canvas-item"
|
||||
:data {:canvas-id (:id canvas)
|
||||
:page-id (:page canvas)
|
||||
{:type "frame-item"
|
||||
:data {:frame-id (:id item)
|
||||
:page-id (:page item)
|
||||
:index index}
|
||||
:on-hover on-hover
|
||||
:on-drop on-drop})]
|
||||
|
@ -219,84 +219,68 @@
|
|||
:on-click select-shape
|
||||
:on-double-click #(dom/stop-propagation %)}
|
||||
[:div.element-actions
|
||||
[:div.toggle-element {:class (when-not (:hidden canvas) "selected")
|
||||
[:div.toggle-element {:class (when-not (:hidden item) "selected")
|
||||
:on-click toggle-visibility}
|
||||
i/eye]
|
||||
#_[:div.block-element {:class (when (:blocked canvas) "selected")
|
||||
#_[:div.block-element {:class (when (:blocked item) "selected")
|
||||
:on-click toggle-blocking}
|
||||
i/lock]]
|
||||
[:div.element-icon i/folder]
|
||||
[:& layer-name {:shape canvas}]
|
||||
[:& layer-name {:shape item}]
|
||||
[:span.toggle-content
|
||||
{:on-click toggle-collapse
|
||||
:class (when-not collapsed? "inverse")}
|
||||
i/arrow-slide]]
|
||||
(when-not collapsed?
|
||||
[:ul
|
||||
(for [[index shape] shapes]
|
||||
[:& layer-item {:shape shape
|
||||
:selected selected
|
||||
:index index
|
||||
:key (:id shape)}])])]))
|
||||
(for [[index id] (d/enumerate (:shapes item))]
|
||||
(let [item (get objects id)]
|
||||
(if (= (:type item) :frame)
|
||||
[:& layer-frame-item
|
||||
{:item item
|
||||
:key (:id item)
|
||||
:objects objects
|
||||
:index index}]
|
||||
[:& layer-item
|
||||
{:item item
|
||||
:index index
|
||||
:key (:id item)}])))])]))
|
||||
|
||||
;; --- Layers List
|
||||
|
||||
(mf/defc layers-list
|
||||
{:wrap [#(mf/wrap-memo % =)]}
|
||||
[{:keys [shapes selected] :as props}]
|
||||
[:ul.element-list
|
||||
(for [[index shape] shapes]
|
||||
[:& layer-item {:shape shape
|
||||
:selected selected
|
||||
:index index
|
||||
:key (:id shape)}])])
|
||||
|
||||
(mf/defc canvas-list
|
||||
{:wrap [#(mf/wrap-memo % =)]}
|
||||
[{:keys [shapes canvas selected] :as props}]
|
||||
[:ul.element-list
|
||||
(for [[index item] canvas]
|
||||
[:& canvas-item {:canvas item
|
||||
:shapes shapes
|
||||
:selected selected
|
||||
:index index
|
||||
:key (:id item)}])])
|
||||
(mf/defc layers-tree
|
||||
{:wrap [mf/wrap-memo]}
|
||||
[props]
|
||||
(let [selected (mf/deref refs/selected-shapes)
|
||||
data (mf/deref refs/workspace-data)
|
||||
objects (:objects data)
|
||||
root (get objects uuid/zero)]
|
||||
[:ul.element-list
|
||||
(for [[index id] (d/enumerate (:shapes root))]
|
||||
(let [item (get objects id)]
|
||||
(if (= (:type item) :frame)
|
||||
[:& layer-frame-item
|
||||
{:item item
|
||||
:key (:id item)
|
||||
:objects objects
|
||||
:index index}]
|
||||
[:& layer-item
|
||||
{:item item
|
||||
:index index
|
||||
:key (:id item)}])))]))
|
||||
|
||||
;; --- Layers Toolbox
|
||||
|
||||
;; NOTE: we need to consider using something like react window for
|
||||
;; only render visible items instead of all.
|
||||
|
||||
(mf/defc layers-toolbox
|
||||
{:wrap [mf/wrap-memo]}
|
||||
[{:keys [page] :as props}]
|
||||
(let [locale (i18n/use-locale)
|
||||
on-click #(st/emit! (dw/toggle-layout-flag :layers))
|
||||
|
||||
selected (mf/deref refs/selected-shapes)
|
||||
data (mf/deref refs/workspace-data)
|
||||
|
||||
shapes-map (:shapes-by-id data)
|
||||
strip #(select-keys % [:id :canvas :name :type :hidden :blocked])
|
||||
|
||||
canvas (->> (:canvas data)
|
||||
(map #(get shapes-map %))
|
||||
(map strip)
|
||||
(d/enumerate))
|
||||
|
||||
shapes (->> (:shapes data)
|
||||
(map #(get shapes-map %))
|
||||
(map strip))
|
||||
|
||||
all-shapes (d/enumerate shapes)
|
||||
unc-shapes (->> shapes
|
||||
(filter #(nil? (:canvas %)))
|
||||
(d/enumerate))]
|
||||
on-click #(st/emit! (dw/toggle-layout-flag :layers))]
|
||||
[:div#layers.tool-window
|
||||
[:div.tool-window-bar
|
||||
[:div.tool-window-icon i/layers]
|
||||
[:span (t locale "workspace.sidebar.layers")]
|
||||
#_[:div.tool-window-close {:on-click on-click} i/close]]
|
||||
[:div.tool-window-content
|
||||
[:& canvas-list {:canvas canvas
|
||||
:shapes all-shapes
|
||||
:selected selected}]
|
||||
[:& layers-list {:shapes unc-shapes
|
||||
:selected selected}]]]))
|
||||
[:& layers-tree]]]))
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
[uxbox.main.data.workspace :as udw]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.ui.workspace.sidebar.options.canvas :as canvas]
|
||||
[uxbox.main.ui.workspace.sidebar.options.frame :as frame]
|
||||
[uxbox.main.ui.workspace.sidebar.options.rect :as rect]
|
||||
[uxbox.main.ui.workspace.sidebar.options.icon :as icon]
|
||||
[uxbox.main.ui.workspace.sidebar.options.circle :as circle]
|
||||
|
@ -29,7 +29,7 @@
|
|||
[{:keys [shape] :as props}]
|
||||
[:div
|
||||
(case (:type shape)
|
||||
:canvas [:& canvas/options {:shape shape}]
|
||||
:frame [:& frame/options {:shape shape}]
|
||||
:text [:& text/options {:shape shape}]
|
||||
:rect [:& rect/options {:shape shape}]
|
||||
:icon [:& icon/options {:shape shape}]
|
||||
|
@ -43,7 +43,7 @@
|
|||
[{:keys [shape-id] :as props}]
|
||||
(let [shape-iref (mf/use-memo
|
||||
{:deps (mf/deps shape-id)
|
||||
:fn #(-> (l/in [:workspace-data :shapes-by-id shape-id])
|
||||
:fn #(-> (l/in [:workspace-data :objects shape-id])
|
||||
(l/derive st/state))})
|
||||
shape (mf/deref shape-iref)]
|
||||
[:& shape-options {:shape shape}]))
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
;; Copyright (c) 2015-2020 Andrey Antukh <niwi@niwi.nz>
|
||||
;; Copyright (c) 2015-2020 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
(ns uxbox.main.ui.workspace.sidebar.options.canvas
|
||||
(ns uxbox.main.ui.workspace.sidebar.options.frame
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.common.data :as d]
|
||||
|
@ -43,8 +43,8 @@
|
|||
delta (if (= attr :x)
|
||||
(gpt/point (math/neg (- pval cval)) 0)
|
||||
(gpt/point 0 (math/neg (- pval cval))))]
|
||||
(st/emit! (udw/apply-canvas-displacement (:id shape) delta)
|
||||
(udw/materialize-canvas-displacement (:id shape)))))
|
||||
(st/emit! (udw/apply-frame-displacement (:id shape) delta)
|
||||
(udw/materialize-frame-displacement (:id shape)))))
|
||||
|
||||
on-width-change #(on-size-change % :width)
|
||||
on-height-change #(on-size-change % :height)
|
|
@ -22,13 +22,13 @@
|
|||
[uxbox.main.ui.workspace.grid :refer [grid]]
|
||||
[uxbox.main.ui.workspace.ruler :refer [ruler]]
|
||||
[uxbox.main.ui.workspace.drawarea :refer [start-drawing]]
|
||||
|
||||
[uxbox.main.ui.shapes :refer [shape-wrapper canvas-wrapper]]
|
||||
[uxbox.main.ui.shapes :refer [shape-wrapper frame-wrapper]]
|
||||
[uxbox.main.ui.workspace.drawarea :refer [draw-area]]
|
||||
[uxbox.main.ui.workspace.selection :refer [selection-handlers]]
|
||||
|
||||
[uxbox.util.data :refer [parse-int]]
|
||||
[uxbox.util.perf :as perf]
|
||||
[uxbox.util.components :refer [use-rxsub]]
|
||||
[uxbox.util.uuid :as uuid]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.geom.point :as gpt])
|
||||
(:import goog.events.EventType))
|
||||
|
@ -142,22 +142,23 @@
|
|||
|
||||
(declare remote-user-cursors)
|
||||
|
||||
(mf/defc canvas-and-shapes
|
||||
(mf/defc frame-and-shapes
|
||||
{:wrap [mf/wrap-memo]}
|
||||
[props]
|
||||
(let [data (mf/deref refs/workspace-data)
|
||||
shapes-map (:shapes-by-id data)
|
||||
shapes (->> (map #(get shapes-map %) (:shapes data []))
|
||||
(group-by :canvas))
|
||||
canvas (map #(get shapes-map %) (:canvas data []))]
|
||||
objects (:objects data)
|
||||
root (get objects uuid/zero)
|
||||
shapes (->> (:shapes root)
|
||||
(map #(get objects %)))]
|
||||
[:g.shapes
|
||||
(for [item canvas]
|
||||
[:& canvas-wrapper {:shape item
|
||||
:key (:id item)
|
||||
:childs (reverse (get shapes (:id item)))}])
|
||||
(for [item (reverse (get shapes nil))]
|
||||
[:& shape-wrapper {:shape item
|
||||
:key (:id item)}])]))
|
||||
(for [item shapes]
|
||||
(if (= (:type item) :frame)
|
||||
[:& frame-wrapper {:shape item
|
||||
:key (:id item)
|
||||
:objects objects}]
|
||||
[:& shape-wrapper {:shape item
|
||||
:key (:id item)}]))]))
|
||||
|
||||
|
||||
(mf/defc viewport
|
||||
[{:keys [page] :as props}]
|
||||
|
@ -169,139 +170,157 @@
|
|||
selected]
|
||||
:as local} (mf/deref refs/workspace-local)
|
||||
viewport-ref (mf/use-ref nil)
|
||||
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! (ms/->MouseEvent :down ctrl? shift?)))
|
||||
(when (not edition)
|
||||
(if drawing-tool
|
||||
(st/emit! (start-drawing drawing-tool))
|
||||
(st/emit! handle-selrect))))
|
||||
zoom (or zoom 1)
|
||||
|
||||
(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! (ms/->MouseEvent :context-menu ctrl? shift?))))
|
||||
on-mouse-down
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(let [ctrl? (kbd/ctrl? event)
|
||||
shift? (kbd/shift? event)
|
||||
opts {:shift? shift?
|
||||
:ctrl? ctrl?}]
|
||||
(st/emit! (ms/->MouseEvent :down ctrl? shift?)))
|
||||
(when (not edition)
|
||||
(if drawing-tool
|
||||
(st/emit! (start-drawing drawing-tool))
|
||||
(st/emit! handle-selrect))))
|
||||
|
||||
(on-mouse-up [event]
|
||||
(dom/stop-propagation event)
|
||||
(let [ctrl? (kbd/ctrl? event)
|
||||
shift? (kbd/shift? event)
|
||||
opts {:shift? shift?
|
||||
:ctrl? ctrl?}]
|
||||
(st/emit! (ms/->MouseEvent :up ctrl? shift?))))
|
||||
on-context-menu
|
||||
(fn [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! (ms/->MouseEvent :context-menu 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! (ms/->MouseEvent :click ctrl? shift?))))
|
||||
on-mouse-up
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(let [ctrl? (kbd/ctrl? event)
|
||||
shift? (kbd/shift? event)
|
||||
opts {:shift? shift?
|
||||
:ctrl? ctrl?}]
|
||||
(st/emit! (ms/->MouseEvent :up 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! (ms/->MouseEvent :double-click ctrl? shift?))))
|
||||
on-click
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(let [ctrl? (kbd/ctrl? event)
|
||||
shift? (kbd/shift? event)
|
||||
opts {:shift? shift?
|
||||
:ctrl? ctrl?}]
|
||||
(st/emit! (ms/->MouseEvent :click ctrl? shift?))))
|
||||
|
||||
(translate-point-to-viewport [pt]
|
||||
(let [viewport (mf/ref-node viewport-ref)
|
||||
brect (.getBoundingClientRect viewport)
|
||||
brect (gpt/point (parse-int (.-left brect))
|
||||
(parse-int (.-top brect)))]
|
||||
(gpt/subtract pt brect)))
|
||||
on-double-click
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(let [ctrl? (kbd/ctrl? event)
|
||||
shift? (kbd/shift? event)
|
||||
opts {:shift? shift?
|
||||
:ctrl? ctrl?}]
|
||||
(st/emit! (ms/->MouseEvent :double-click ctrl? shift?))))
|
||||
|
||||
(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! (ms/->KeyboardEvent :down key ctrl? shift?))
|
||||
(when (kbd/space? event)
|
||||
(st/emit! handle-viewport-positioning)
|
||||
#_(st/emit! (dw/start-viewport-positioning))))))
|
||||
on-key-down
|
||||
(fn [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! (ms/->KeyboardEvent :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! (ms/->KeyboardEvent :up key ctrl? shift?))))
|
||||
on-key-up
|
||||
(fn [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! (ms/->KeyboardEvent :up key ctrl? shift?))))
|
||||
|
||||
(on-mouse-move [event]
|
||||
(let [pt (gpt/point (.-clientX event)
|
||||
(.-clientY event))
|
||||
pt (translate-point-to-viewport pt)]
|
||||
(st/emit! (ms/->PointerEvent :viewport pt
|
||||
(kbd/ctrl? event)
|
||||
(kbd/shift? event)))))
|
||||
;; translate-point-to-viewport
|
||||
;; (fn [pt]
|
||||
;; (let [viewport (mf/ref-node viewport-ref)
|
||||
;; brect (.getBoundingClientRect viewport)
|
||||
;; brect (gpt/point (parse-int (.-left brect))
|
||||
;; (parse-int (.-top brect)))]
|
||||
;; (gpt/subtract pt brect)))
|
||||
|
||||
(on-mount []
|
||||
(let [key1 (events/listen js/document EventType.KEYDOWN on-key-down)
|
||||
key2 (events/listen js/document EventType.KEYUP on-key-up)]
|
||||
(fn []
|
||||
(events/unlistenByKey key1)
|
||||
(events/unlistenByKey key2))))]
|
||||
(mf/use-effect on-mount)
|
||||
[:*
|
||||
[:& coordinates {:zoom zoom}]
|
||||
[:svg.viewport {:width (* c/viewport-width zoom)
|
||||
:height (* c/viewport-height zoom)
|
||||
:ref viewport-ref
|
||||
:class (when drawing-tool "drawing")
|
||||
:on-context-menu on-context-menu
|
||||
:on-click on-click
|
||||
:on-double-click on-double-click
|
||||
:on-mouse-move on-mouse-move
|
||||
:on-mouse-down on-mouse-down
|
||||
:on-mouse-up on-mouse-up}
|
||||
[:g.zoom {:transform (str "scale(" zoom ", " zoom ")")}
|
||||
[:*
|
||||
[:& canvas-and-shapes]
|
||||
on-mouse-move
|
||||
(fn [event]
|
||||
;; NOTE: offsetX and offsetY are marked as "experimental" on
|
||||
;; MDN site but seems like they are supported on all
|
||||
;; browsers so we can avoid translation opetation just using
|
||||
;; this attributes.
|
||||
(let [;; pt (gpt/point (.-clientX event)
|
||||
;; (.-clientY event))
|
||||
;; pt (translate-point-to-viewport pt)
|
||||
pt (gpt/point (.-offsetX (.-nativeEvent event))
|
||||
(.-offsetY (.-nativeEvent event)))]
|
||||
(st/emit! (ms/->PointerEvent :viewport pt
|
||||
(kbd/ctrl? event)
|
||||
(kbd/shift? event)))))
|
||||
|
||||
(when (seq selected)
|
||||
[:& selection-handlers {:selected selected
|
||||
:zoom zoom
|
||||
:edition edition}])
|
||||
on-mount
|
||||
(fn []
|
||||
(let [key1 (events/listen js/document EventType.KEYDOWN on-key-down)
|
||||
key2 (events/listen js/document EventType.KEYUP on-key-up)]
|
||||
(fn []
|
||||
(events/unlistenByKey key1)
|
||||
(events/unlistenByKey key2))))]
|
||||
|
||||
(when-let [drawing-shape (:drawing local)]
|
||||
[:& draw-area {:shape drawing-shape
|
||||
:zoom zoom
|
||||
:modifiers (:modifiers local)}])]
|
||||
(mf/use-effect on-mount)
|
||||
[:*
|
||||
[:& coordinates {:zoom zoom}]
|
||||
[:svg.viewport {:width (* c/viewport-width zoom)
|
||||
:height (* c/viewport-height zoom)
|
||||
:ref viewport-ref
|
||||
:class (when drawing-tool "drawing")
|
||||
:on-context-menu on-context-menu
|
||||
:on-click on-click
|
||||
:on-double-click on-double-click
|
||||
:on-mouse-move on-mouse-move
|
||||
:on-mouse-down on-mouse-down
|
||||
:on-mouse-up on-mouse-up}
|
||||
[:g.zoom {:transform (str "scale(" zoom ", " zoom ")")}
|
||||
;; [:> js/React.Profiler
|
||||
;; {:id "foobar"
|
||||
;; :on-render (perf/react-on-profile)}
|
||||
;; [:& frame-and-shapes]]
|
||||
[:& frame-and-shapes]
|
||||
|
||||
(if (contains? flags :grid)
|
||||
[:& grid])]
|
||||
(when (seq selected)
|
||||
[:& selection-handlers {:selected selected
|
||||
:zoom zoom
|
||||
:edition edition}])
|
||||
|
||||
(when tooltip
|
||||
[:& cursor-tooltip {:zoom zoom :tooltip tooltip}])
|
||||
(when-let [drawing-shape (:drawing local)]
|
||||
[:& draw-area {:shape drawing-shape
|
||||
:zoom zoom
|
||||
:modifiers (:modifiers local)}])
|
||||
|
||||
(when (contains? flags :ruler)
|
||||
[:& ruler {:zoom zoom :ruler (:ruler local)}])
|
||||
(if (contains? flags :grid)
|
||||
[:& grid])]
|
||||
|
||||
(when tooltip
|
||||
[:& cursor-tooltip {:zoom zoom :tooltip tooltip}])
|
||||
|
||||
;; -- METER CURSOR MULTIUSUARIO
|
||||
[:& remote-user-cursors {:page page}]
|
||||
(when (contains? flags :ruler)
|
||||
[:& ruler {:zoom zoom :ruler (:ruler local)}])
|
||||
|
||||
[:& selrect {:data (:selrect local)}]]])))
|
||||
[:& remote-user-cursors {:page page}]
|
||||
[:& selrect {:data (:selrect local)}]]]))
|
||||
|
||||
|
||||
(mf/defc remote-user-cursor
|
||||
|
|
|
@ -11,3 +11,7 @@
|
|||
"Convert an es6 iterable into cljs Seq."
|
||||
[v]
|
||||
(seq (js/Array.from v)))
|
||||
|
||||
(defn obj-assign!
|
||||
[obj1 obj2]
|
||||
(js/Object.assign obj1 obj2))
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
|
||||
(ns uxbox.util.perf
|
||||
"Performance and debugging tools."
|
||||
#?(:cljs (:require-macros [uxbox.util.perf])))
|
||||
#?(:cljs (:require-macros [uxbox.util.perf]))
|
||||
#?(:cljs (:require [uxbox.util.math :as math])))
|
||||
|
||||
#?(:clj
|
||||
(defmacro with-measure
|
||||
|
@ -17,3 +18,25 @@
|
|||
time# (.toFixed (- end# start#) 2)]
|
||||
(println (str "[perf|" ~name "] => " time#))
|
||||
res#)))
|
||||
|
||||
|
||||
;; id, // the "id" prop of the Profiler tree that has just committed
|
||||
;; phase, // either "mount" (if the tree just mounted) or "update" (if it re-rendered)
|
||||
;; actualDuration, // time spent rendering the committed update
|
||||
;; baseDuration, // estimated time to render the entire subtree without memoization
|
||||
;; startTime, // when React began rendering this update
|
||||
;; commitTime, // when React committed this update
|
||||
;; interactions // the Set of interactions belonging to this update
|
||||
|
||||
#?(:cljs
|
||||
(defn react-on-profile
|
||||
[]
|
||||
(let [sum (volatile! 0)
|
||||
ctr (volatile! 0)]
|
||||
(fn [id phase adur, bdur, st, ct, itx]
|
||||
(vswap! sum (fn [prev] (+ prev adur)))
|
||||
(vswap! ctr inc)
|
||||
(js/console.log (str "[profile:" id ":" phase "]")
|
||||
""
|
||||
(str "time=" (math/precision adur 4))
|
||||
(str "avg=" (math/precision (/ @sum @ctr) 4)))))))
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
[uxbox.util.data :refer [seek]]
|
||||
[uxbox.view.data.viewer :as dv]
|
||||
[uxbox.view.store :as st]
|
||||
[uxbox.view.ui.viewer.canvas :refer [canvas]]
|
||||
[uxbox.view.ui.viewer.frame :refer [frame]]
|
||||
[uxbox.view.ui.viewer.nav :refer [nav]]
|
||||
[uxbox.view.ui.viewer.sitemap :refer [sitemap]]
|
||||
[lentes.core :as l]))
|
||||
|
@ -45,4 +45,4 @@
|
|||
:pages pages
|
||||
:selected id}])
|
||||
[:& nav {:flags flags}]
|
||||
[:& canvas {:page (seek #(= id (:id %)) pages)}]])))
|
||||
[:& frame {:page (seek #(= id (:id %)) pages)}]])))
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
;; Copyright (c) 2016-2017 Andrey Antukh <niwi@niwi.nz>
|
||||
;; Copyright (c) 2016-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
(ns uxbox.view.ui.viewer.canvas
|
||||
(ns uxbox.view.ui.viewer.frame
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.view.ui.viewer.shapes :as shapes]))
|
||||
|
@ -25,12 +25,12 @@
|
|||
|
||||
(declare shape)
|
||||
|
||||
(mf/defc canvas
|
||||
(mf/defc frame
|
||||
{:wrap [mf/wrap-memo]}
|
||||
[{:keys [page] :as props}]
|
||||
#_(let [{:keys [metadata id]} page
|
||||
{:keys [width height]} metadata]
|
||||
[:div.view-canvas
|
||||
[:div.view-frame
|
||||
[:svg.page-layout {:width width
|
||||
:height height}
|
||||
[:& background metadata]
|
Loading…
Add table
Add a link
Reference in a new issue