🔧 Adapt shapes to use new rumext macros.

This commit is contained in:
Andrey Antukh 2019-08-07 20:12:35 +02:00
parent 204f180ec9
commit fada526f5d
13 changed files with 225 additions and 344 deletions

View file

@ -6,20 +6,21 @@
(ns uxbox.main.exports
"The main logic for SVG export functionality."
(:require [uxbox.main.store :as st]
[uxbox.main.ui.shapes.rect :refer [rect-shape]]
[uxbox.main.ui.shapes.icon :refer [icon-shape]]
[uxbox.main.ui.shapes.text :refer [text-shape]]
[uxbox.main.ui.shapes.group :refer [group-shape]]
[uxbox.main.ui.shapes.path :refer [path-shape]]
[uxbox.main.ui.shapes.circle :refer [circle-shape]]
[uxbox.main.ui.shapes.image :refer [image-shape]]
[uxbox.util.dom :as dom]
[rumext.core :as mx :include-macros true]))
(:require
[rumext.alpha :as mf]
[uxbox.main.store :as st]
[uxbox.main.ui.shapes.circle :refer [circle-shape]]
[uxbox.main.ui.shapes.group :refer [group-shape]]
[uxbox.main.ui.shapes.icon :refer [icon-shape]]
[uxbox.main.ui.shapes.image :refer [image-shape]]
[uxbox.main.ui.shapes.path :refer [path-shape]]
[uxbox.main.ui.shapes.rect :refer [rect-shape]]
[uxbox.main.ui.shapes.text :refer [text-shape]]
[uxbox.util.dom :as dom]))
(def ^:dynamic *state* st/state)
(mx/defc background
(mf/defc background
[]
[:rect
{:x 0 :y 0
@ -30,27 +31,22 @@
(declare shape-component)
(declare shape-wrapper)
(mx/defc shape-wrapper
[{:keys [type] :as shape}]
(case type
:group (group-shape shape shape-component)
:text (text-shape shape)
:icon (icon-shape shape)
:rect (rect-shape shape)
:path (path-shape shape)
:circle (circle-shape shape)
:image (let [image-id (:image shape)
image (get-in @*state* [:images image-id])]
(image-shape (assoc shape :image image)))))
(defn- make-shape-element
[state shape]
(mf/html
(case (:type shape)
;; :text [:& text-shape {:shape shape}]
:icon [:& icon-shape {:shape shape}]
:rect [:& rect-shape {:shape shape}]
:path [:& path-shape {:shape shape}]
:circle [:& circle-shape {:shape shape}]
:image (let [image-id (:image shape)
image (get-in state [:images image-id])]
[:& image-shape {:shape shape :image image}]))))
(mx/defc shape-component
[id]
(when-let [shape (get-in @*state* [:shapes id])]
(shape-wrapper shape)))
(mx/defc page-svg
[{:keys [id metadata] :as page}]
(let [{:keys [width height]} metadata]
(mf/defc page-svg
[{:keys [page state] :as props}]
(let [{:keys [width height]} (:metadata page)]
[:svg {:width width
:height height
:view-box (str "0 0 " width " " height)
@ -59,16 +55,18 @@
:xmlns "http://www.w3.org/2000/svg"}
;; TODO: properly handle background
#_(background)
(for [item (reverse (:shapes page))]
(-> (shape-component item)
(mx/with-key (str item))))]))
(for [sid (reverse (:shapes page))]
(when-let [shape (get-in state [:shapes sid])]
[:g {:key sid} (make-shape-element state shape)]))]))
(defn render-page
[id]
(try
(let [page (get-in @*state* [:pages id])]
(let [state (deref st/state)
page (get-in state [:pages id])]
(when (:shapes page)
(dom/render-to-html (page-svg page))))
(dom/render-to-html
(mf/element page-svg #js {:page page :state state}))))
(catch :default e
(js/console.log e)
nil)))

View file

@ -304,7 +304,8 @@
:on-change toggle-selection
:checked selected?}]
[:label {:for (:id icon)}]]
[:span.grid-item-icon (icon/icon-svg icon)]
[:span.grid-item-icon
[:& icon/icon-svg {:shape icon}]]
[:div.item-info {:on-click ignore-click}
(if edition?
[:input.element-name {:type "text"

View file

@ -2,58 +2,37 @@
;; 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/.
;;
;; Copyright (c) 2016-2017 Andrey Antukh <niwi@niwi.nz>
;; Copyright (c) 2016-2019 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.main.ui.shapes
(:require
[lentes.core :as l]
[rumext.alpha :as mf]
[rumext.core :as mx]
[uxbox.main.geom :as geom]
[uxbox.main.refs :as refs]
[uxbox.main.store :as st]
[uxbox.main.ui.shapes.attrs :as attrs]
[uxbox.main.ui.shapes.circle :as circle]
[uxbox.main.ui.shapes.common :as common]
[uxbox.main.ui.shapes.icon :as icon]
[uxbox.main.ui.shapes.image :as image]
[uxbox.main.ui.shapes.path :as path]
[uxbox.main.ui.shapes.rect :as rect]
[uxbox.main.ui.shapes.text :as text]
[uxbox.util.data :refer [classnames]]
[uxbox.util.geom.matrix :as gmt]))
;; (def render-component group/render-component)
;; (def shape group/component-container)
[uxbox.main.ui.shapes.text :as text]))
(defn render-shape
[shape]
(case (:type shape)
;; :group (group-component shape)
:text (text/text-component shape)
:icon (icon/icon-component shape)
:rect (rect/rect-component shape)
:path (path/path-component shape)
:image (image/image-component shape)
:circle (circle/circle-component shape)))
(mf/html
(case (:type shape)
:text [:& text/text-component {:shape shape}]
:icon [:& icon/icon-component {:shape shape}]
:rect [:& rect/rect-component {:shape shape}]
:path [:& path/path-component {:shape shape}]
:image [:& image/image-component {:shape shape}]
:circle [:& circle/circle-component {:shape shape}])))
(mf/def shape-container
:mixins [mf/reactive mf/memo]
:init
(fn [own {:keys [id] :as props}]
(assoc own ::shape-ref (-> (l/in [:shapes id])
(l/derive st/state))))
:render
(fn [own {:keys [id] :as props}]
(when-let [shape (mf/react (::shape-ref own))]
(mf/defc shape-component
{:wrap [mf/wrap-memo]}
[{:keys [id] :as props}]
(let [shape-iref (mf/use-memo {:deps #js [id]
:init #(-> (l/in [:shapes id])
(l/derive st/state))})]
(when-let [shape (mf/deref shape-iref)]
(when-not (:hidden shape)
(render-shape shape)))))
;; NOTE: temporal workaround
(mx/defc shape
[id]
(mf/element shape-container {:id id}))

View file

@ -2,41 +2,39 @@
;; 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/.
;;
;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz>
;; Copyright (c) 2016-2019 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.main.ui.shapes.circle
(:require [lentes.core :as l]
[uxbox.main.refs :as refs]
[uxbox.main.geom :as geom]
[uxbox.main.ui.shapes.common :as common]
[uxbox.main.ui.shapes.attrs :as attrs]
[uxbox.util.data :refer [classnames normalize-props]]
[uxbox.util.geom.matrix :as gmt]
[uxbox.util.geom.point :as gpt]
[rumext.core :as mx :include-macros true]))
(:require
[rumext.alpha :as mf]
[uxbox.main.geom :as geom]
[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.geom.matrix :as gmt]
[uxbox.util.geom.point :as gpt]))
;; --- Circle Component
(declare circle-shape)
(mx/defc circle-component
{:mixins [mx/reactive mx/static]}
(mf/defc circle-component
[{:keys [id] :as shape}]
(let [modifiers (mx/react (refs/selected-modifiers id))
selected (mx/react refs/selected-shapes)
(let [modifiers (mf/deref (refs/selected-modifiers id))
selected (mf/deref refs/selected-shapes)
selected? (contains? selected id)
on-mouse-down #(common/on-mouse-down % shape selected)
shape (assoc shape :modifiers modifiers)]
on-mouse-down #(common/on-mouse-down % shape selected)]
[:g.shape {:class (when selected? "selected")
:on-mouse-down on-mouse-down}
(circle-shape shape)]))
[:& circle-shape {:shape shape :modifiers modifiers}]]))
;; --- Circle Shape
(mx/defc circle-shape
{:mixins [mx/static]}
[{:keys [id modifiers rotation cx cy] :as shape}]
(let [{:keys [resize displacement]} modifiers
(mf/defc circle-shape
[{:keys [shape modifiers] :as props}]
(let [{:keys [id rotation cx cy]} shape
{:keys [resize displacement]} modifiers
shape (cond-> shape
displacement (geom/transform displacement)

View file

@ -5,31 +5,32 @@
;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.main.ui.shapes.icon
(:require [uxbox.main.geom :as geom]
[uxbox.main.refs :as refs]
[uxbox.main.ui.shapes.common :as common]
[uxbox.main.ui.shapes.attrs :as attrs]
[uxbox.util.data :refer [classnames normalize-props]]
[uxbox.util.geom.matrix :as gmt]
[uxbox.util.geom.point :as gpt]
[rumext.core :as mx :include-macros true]))
(:require
[rumext.alpha :as mf]
[rumext.core :as mx]
[uxbox.main.geom :as geom]
[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.geom.matrix :as gmt]
[uxbox.util.geom.point :as gpt]))
;; --- Icon Component
(declare icon-shape)
(mx/defc icon-component
{:mixins [mx/static mx/reactive]}
[{:keys [id] :as shape}]
(let [modifiers (mx/react (refs/selected-modifiers id))
selected (mx/react refs/selected-shapes)
(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)
on-mouse-down #(common/on-mouse-down % shape selected)
shape (assoc shape :modifiers modifiers)]
on-mouse-down #(common/on-mouse-down % shape selected)]
[:g.shape {:class (when selected? "selected")
:on-mouse-down on-mouse-down}
(icon-shape shape)]))
[:& icon-shape {:shape shape :modifiers modifiers}]]))
;; --- Icon Shape
@ -41,10 +42,10 @@
center (gpt/point x-center y-center)]
(gmt/rotate* mt rotation center)))
(mx/defc icon-shape
{:mixins [mx/static]}
[{:keys [id content metadata rotation x1 y1 modifiers] :as shape}]
(let [{:keys [resize displacement]} modifiers
(mf/defc icon-shape
[{:keys [shape modifiers] :as props}]
(let [{:keys [id content metadata rotation x1 y1]} shape
{:keys [resize displacement]} modifiers
xfmt (cond-> (gmt/matrix)
displacement (gmt/multiply displacement)
@ -74,10 +75,10 @@
;; --- Icon SVG
(mx/defc icon-svg
{:mixins [mx/static]}
[{:keys [content id metadata] :as shape}]
(let [view-box (apply str (interpose " " (:view-box metadata)))
(mf/defc icon-svg
[{:keys [shape] :as props}]
(let [{:keys [content id metadata]} shape
view-box (apply str (interpose " " (:view-box metadata)))
props {:view-box view-box
:id (str "shape-" id)
:dangerouslySetInnerHTML #js {:__html content}}]

View file

@ -2,21 +2,20 @@
;; 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/.
;;
;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz>
;; Copyright (c) 2016-2019 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.main.ui.shapes.image
(:require [beicon.core :as rx]
[lentes.core :as l]
[potok.core :as ptk]
[uxbox.main.geom :as geom]
[uxbox.main.refs :as refs]
[uxbox.main.store :as st]
[uxbox.main.ui.shapes.common :as common]
[uxbox.main.ui.shapes.attrs :as attrs]
[uxbox.main.data.images :as udi]
[uxbox.util.data :refer [classnames normalize-props]]
[uxbox.util.geom.matrix :as gmt]
[rumext.core :as mx :include-macros true]))
(:require
[lentes.core :as l]
[rumext.alpha :as mf]
[uxbox.main.data.images :as udi]
[uxbox.main.geom :as geom]
[uxbox.main.refs :as refs]
[uxbox.main.store :as st]
[uxbox.main.ui.shapes.attrs :as attrs]
[uxbox.main.ui.shapes.common :as common]
[uxbox.util.data :refer [classnames normalize-props]]
[uxbox.util.geom.matrix :as gmt]))
;; --- Refs
@ -29,34 +28,29 @@
(declare image-shape)
(mx/defcs image-component
{:mixins [mx/static mx/reactive]
:init (fn [own]
;; TODO: maybe do it conditionally
;; (only fetch when it's not fetched)
(when-let [id (-> own ::mx/props first :image)]
(st/emit! (udi/fetch-image id)))
own)}
[own {:keys [id image] :as shape}]
(let [modifiers (mx/react (refs/selected-modifiers id))
selected (mx/react refs/selected-shapes)
image (mx/react (image-ref image))
selected? (contains? selected id)
on-mouse-down #(common/on-mouse-down % shape selected)
shape (assoc shape
:modifiers modifiers
:image image)]
(mf/defc image-component
[{:keys [shape] :as props}]
(let [modifiers (mf/deref (refs/selected-modifiers (:id shape)))
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)]
(mf/use-effect
{:init #(st/emit! (udi/fetch-image (:image shape)))})
(when image
[:g.shape {:class (when selected? "selected")
:on-mouse-down on-mouse-down}
(image-shape shape)])))
[:& image-shape {:shape shape
:image image
:modifiers modifiers}]])))
;; --- Image Shape
(mx/defc image-shape
{:mixins [mx/static]}
[{:keys [id x1 y1 image modifiers] :as shape}]
(let [{:keys [width height]} (geom/size 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
xfmt (cond-> (gmt/matrix)

View file

@ -2,34 +2,31 @@
;; 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/.
;;
;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz>
;; Copyright (c) 2016-2019 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.main.ui.shapes.path
(:require [potok.core :as ptk]
[cuerdas.core :as str :include-macros true]
[uxbox.main.geom :as geom]
[uxbox.main.store :as st]
[uxbox.main.refs :as refs]
[uxbox.main.data.shapes :as uds]
[uxbox.main.ui.shapes.common :as common]
[uxbox.main.ui.shapes.attrs :as attrs]
[uxbox.util.data :refer [classnames normalize-props]]
[uxbox.util.geom.matrix :as gmt]
[uxbox.util.geom.point :as gpt]
[rumext.core :as mx :include-macros true]))
(:require
[cuerdas.core :as str :include-macros true]
[rumext.alpha :as mf]
[uxbox.main.data.shapes :as uds]
[uxbox.main.geom :as geom]
[uxbox.main.refs :as refs]
[uxbox.main.store :as st]
[uxbox.main.ui.shapes.attrs :as attrs]
[uxbox.main.ui.shapes.common :as common]
[uxbox.util.data :refer [classnames normalize-props]]
[uxbox.util.geom.matrix :as gmt]
[uxbox.util.geom.point :as gpt]))
;; --- Path Component
(declare path-shape)
(mx/defc path-component
{:mixins [mx/static mx/reactive]}
(mf/defc path-component
[{:keys [id] :as shape}]
(let [modifiers (mx/react (refs/selected-modifiers id))
selected (mx/react refs/selected-shapes)
selected? (contains? selected id)
shape (assoc shape
:modifiers modifiers
:background? true)]
(let [modifiers (mf/deref (refs/selected-modifiers id))
selected (mf/deref refs/selected-shapes)
selected? (contains? selected id)]
(letfn [(on-mouse-down [event]
(common/on-mouse-down event shape selected))
(on-double-click [event]
@ -38,7 +35,9 @@
[:g.shape {:class (when selected? "selected")
:on-double-click on-double-click
:on-mouse-down on-mouse-down}
(path-shape shape)])))
[:& path-shape {:shape shape
:modifiers modifiers
:background? true}]])))
;; --- Path Shape
@ -63,9 +62,8 @@
buffer (conj buffer (str/istr "L~{x},~{y}"))]
(recur buffer (inc index)))))))
(mx/defc path-shape
{:mixins [mx/static]}
[{:keys [id modifiers background?] :as shape}]
(mf/defc path-shape
[{:keys [shape modifiers background?] :as props}]
(let [{:keys [resize displacement]} modifiers
shape (cond-> shape
displacement (geom/transform displacement)
@ -73,13 +71,13 @@
moving? (boolean displacement)
pdata (render-path shape)
props {:id (str id)
props {:id (str (:id shape))
:class (classnames :move-cursor moving?)
:d pdata}
attrs (merge (attrs/extract-style-attrs shape) props)]
(if background?
[:g {}
[:g
[:path {:stroke "transparent"
:fill "transparent"
:stroke-width "20px"

View file

@ -5,31 +5,33 @@
;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.main.ui.shapes.rect
(:require [uxbox.main.geom :as geom]
[uxbox.main.refs :as refs]
[uxbox.main.ui.shapes.common :as common]
[uxbox.main.ui.shapes.attrs :as attrs]
[uxbox.util.geom.matrix :as gmt]
[uxbox.util.geom.point :as gpt]
[rumext.core :as mx :include-macros true]
[uxbox.util.data :refer [classnames normalize-props]]
[uxbox.util.dom :as dom]))
(:require
[rumext.alpha :as mf]
[uxbox.main.geom :as geom]
[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.geom.matrix :as gmt]
[uxbox.util.geom.point :as gpt]))
;; --- Rect Component
(declare rect-shape)
(mx/defc rect-component
{:mixins [mx/reactive mx/static]}
[{:keys [id] :as shape}]
(let [modifiers (mx/react (refs/selected-modifiers id))
selected (mx/react refs/selected-shapes)
(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)
on-mouse-down #(common/on-mouse-down % shape selected)
shape (assoc shape :modifiers modifiers)]
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 identity)]))
[:& rect-shape {:shape shape
:modifiers modifiers}]]))
;; --- Rect Shape
@ -40,10 +42,11 @@
center (gpt/point x-center y-center)]
(gmt/rotate* mt rotation center)))
(mx/defc rect-shape
{:mixins [mx/static]}
[{:keys [id rotation modifiers] :as shape}]
(let [{:keys [displacement resize]} modifiers
(mf/defc rect-shape
[{:keys [shape modifiers] :as props}]
(let [{:keys [id rotation]} shape
{:keys [displacement resize]} modifiers
xfmt (cond-> (gmt/matrix)
displacement (gmt/multiply displacement)
resize (gmt/multiply resize))

View file

@ -2,7 +2,7 @@
;; 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/.
;;
;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz>
;; Copyright (c) 2016-2019 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.main.ui.shapes.text
(:require
@ -28,8 +28,7 @@
[event {:keys [id group] :as shape} selected]
(if (and (not (:blocked shape))
(or @refs/selected-drawing-tool
@refs/selected-edition
(and group (:locked (geom/resolve-parent shape)))))
@refs/selected-edition))
(dom/stop-propagation event)
(common/on-mouse-down event shape selected)))
@ -40,12 +39,13 @@
(declare text-shape-edit)
(mf/def text-component
:mixins [mf/memo mx/reactive]
:mixins [mf/memo mf/reactive]
:render
(fn [own {:keys [id x1 y1 content group] :as shape}]
(let [modifiers (mx/react (refs/selected-modifiers id))
selected (mx/react refs/selected-shapes)
edition? (= (mx/react refs/selected-edition) id)
(fn [own {:keys [shape] :as props}]
(let [{:keys [id x1 y1 content group]} shape
modifiers (mf/react (refs/selected-modifiers id))
selected (mf/react refs/selected-shapes)
edition? (= (mf/react refs/selected-edition) id)
selected? (and (contains? selected id)
(= (count selected) 1))
shape (assoc shape :modifiers modifiers)]
@ -60,8 +60,8 @@
:on-double-click on-double-click
:on-mouse-down on-mouse-down}
(if edition?
(text-shape-edit shape)
(text-shape-wrapper shape))]))))
[:& text-shape-edit {:shape shape}]
[:& text-shape-wrapper {:shape shape}])]))))
;; --- Text Styles Helpers
@ -113,15 +113,15 @@
:did-mount
(fn [own]
(let [shape (::mf/props own)
dom (mx/ref-node (::container own))]
(let [shape (get-in own [::mf/props :shape])
dom (mf/ref-node (::container own))]
(set! (.-textContent dom) (:content shape ""))
(.focus dom)
own))
:render
(fn [own {:keys [id x1 y1 content] :as shape}]
(let [{:keys [width height]} (geom/size shape)
(fn [own {:keys [shape] :as props}]
(let [{:keys [id x1 y1 content width height]} (geom/size shape)
style (make-style shape)
on-input (fn [ev]
(let [content (dom/event->inner-text ev)]
@ -136,7 +136,6 @@
(mf/def text-shape-wrapper
:mixins [mf/memo]
:key-fn pr-str
:init
(fn [own props]
@ -152,15 +151,16 @@
:did-mount
(fn [own]
(let [shape (::mf/props own)
(let [shape (get-in own [::mf/props :shape])
dom (mf/ref-node (::fobject own))
html (dom/render-to-html (text-shape-html shape))]
(set! (.-innerHTML dom) html))
own)
:render
(fn [own {:keys [id modifiers] :as shape}]
(let [{:keys [displacement resize]} modifiers
(fn [own {:keys [shape] :as props}]
(let [{:keys [id modifiers]} shape
{:keys [displacement resize]} modifiers
xfmt (cond-> (gmt/matrix)
displacement (gmt/multiply displacement)
resize (gmt/multiply resize))

View file

@ -43,9 +43,8 @@
[:& background metadata]
[:svg.page-layout
[:g.main
(for [item (reverse (:shapes page))]
(-> (uus/shape item)
(mf/with-key (str item))))
(for [id (reverse (:shapes page))]
[:& uus/shape-component {:id id :key id}])
[:& selection-handlers {:wst wst}]
(when-let [dshape (:drawing wst)]
[:& draw-area {:shape dshape

View file

@ -67,7 +67,6 @@
(defn- start-resize
[vid ids shape]
(prn "start-resize" vid ids shape)
(letfn [(on-resize [shape [point lock?]]
(let [result (geom/resize-shape vid shape point lock?)
scale (geom/calculate-scale-ratio shape result)

View file

@ -23,6 +23,7 @@
[uxbox.util.data :refer (read-string classnames)]
[uxbox.util.dom :as dom]
[uxbox.util.dom.dnd :as dnd]
[uxbox.util.timers :as tm]
[uxbox.util.router :as r])
(:import goog.events.EventType))
@ -134,12 +135,13 @@
:drag-top (= :top (:over @local))
:drag-bottom (= :bottom (:over @local))
:drag-inside (= :middle (:over @local)))]
;; TODO: consider using http://react-dnd.github.io/react-dnd/docs/overview
(letfn [(on-drag-start [event]
(let [target (dom/event->target event)]
(dnd/set-allowed-effect! event "move")
(dnd/set-data! event (:id shape))
(dnd/set-image! event target 50 10)
(swap! local assoc :dragging true)))
(tm/schedule #(swap! local assoc :dragging true))))
(on-drag-end [event]
(swap! local assoc :dragging false :over nil))
(on-drop [event]
@ -189,94 +191,6 @@
;; --- Layer Group (Component)
#_(mx/defcs layer-group
{:mixins [mx/static mx/reactive (mx/local)]}
[{:keys [::mx/local]} {:keys [id] :as item} selected]
(let [selected? (contains? selected (:id item))
collapsed? (:collapsed item true)
shapes-map (mx/react refs/shapes-by-id)
classes (classnames
:selected selected?
:drag-top (= :top (:over @local))
:drag-bottom (= :bottom (:over @local))
:drag-inside (= :middle (:over @local)))
select #(select-shape selected item %)
toggle-visibility #(toggle-visibility selected item %)
toggle-blocking #(toggle-blocking item %)]
(letfn [(toggle-collapse [event]
(dom/stop-propagation event)
(if (:collapsed item true)
(st/emit! (uds/uncollapse-shape id))
(st/emit! (uds/collapse-shape id))))
(toggle-locking [event]
(dom/stop-propagation event)
(if (:locked item)
(st/emit! (uds/unlock-shape id))
(st/emit! (uds/lock-shape id))))
(on-drag-start [event]
(let [target (dom/event->target event)]
(dnd/set-allowed-effect! event "move")
(dnd/set-data! event (:id item))
(swap! local assoc :dragging true)))
(on-drag-end [event]
(swap! local assoc :dragging false :over nil))
(on-drop [event]
(dom/stop-propagation event)
(let [coming-id (dnd/get-data event)
over (:over @local)]
(case (:over @local)
:top (st/emit! (uds/drop-shape coming-id id :before))
:bottom (st/emit! (uds/drop-shape coming-id id :after))
:middle (st/emit! (uds/drop-shape coming-id id :inside)))
(swap! local assoc :dragging false :over nil)))
(on-drag-over [event]
(dom/prevent-default event)
(dnd/set-drop-effect! event "move")
(let [over (dnd/get-hover-position event true)]
(swap! local assoc :over over)))
(on-drag-enter [event]
(swap! local assoc :over true))
(on-drag-leave [event]
(swap! local assoc :over false))]
[:li.group {:class (when-not collapsed? "open")}
[:div.element-list-body
{:class classes
:draggable true
:on-drag-start on-drag-start
:on-drag-enter on-drag-enter
:on-drag-leave on-drag-leave
:on-drag-over on-drag-over
:on-drag-end on-drag-end
:on-drop on-drop
:on-click select}
[:div.element-actions {}
[:div.toggle-element
{:class (when-not (:hidden item) "selected")
:on-click toggle-visibility}
i/eye]
[:div.block-element
{:class (when (:blocked item) "selected")
:on-click toggle-blocking}
i/lock]
[:div.chain-element
{:class (when (:locked item) "selected")
:on-click toggle-locking}
i/chain]]
[:div.element-icon i/folder]
(shape-name item)
[:span.toggle-content
{:on-click toggle-collapse
:class (when-not collapsed? "inverse")}
i/arrow-slide]]
(if-not collapsed?
[:ul {}
(for [{:keys [id] :as shape} (map #(get shapes-map %) (:items item))]
(if (= (:type shape) :group)
(-> (layer-group shape selected)
(mx/with-key id))
(-> (layer-simple shape selected)
(mx/with-key id))))])])))
;; --- Layers Tools (Buttons Component)
;; (defn- allow-grouping?
@ -340,30 +254,25 @@
;; --- Layers Toolbox (Component)
(mf/def layers-toolbox
:mixins [mx/static mx/reactive]
(def ^:private shapes-iref
(-> (l/key :shapes)
(l/derive st/state)))
:init
(fn [own {:keys [id]}]
(assoc own ::shapes-ref (-> (l/key :shapes)
(l/derive st/state))))
(mf/defc layers-toolbox
[{:keys [page selected] :as props}]
(let [shapes (mf/deref shapes-iref)
on-click #(st/emit! (udw/toggle-flag :layers))]
[:div#layers.tool-window
[:div.tool-window-bar
[:div.tool-window-icon i/layers]
[:span "Layers"]
[:div.tool-window-close {:on-click on-click} i/close]]
[:div.tool-window-content
[:ul.element-list
(for [id (:shapes page)]
[:& layer-item {:shape (get shapes id)
:selected selected
:key id}])]]
[:& layers-tools {:selected selected
:shapes shapes}]]))
:render
(fn [own {:keys [page selected] :as props}]
(let [shapes (mx/react (::shapes-ref own))
close #(st/emit! (udw/toggle-flag :layers))
dragel (volatile! nil)]
[:div#layers.tool-window
[:div.tool-window-bar
[:div.tool-window-icon i/layers]
[:span "Layers"]
[:div.tool-window-close {:on-click close} i/close]]
[:div.tool-window-content
[:ul.element-list
(for [id (:shapes page)]
(let [shape (get shapes id)]
[:& layer-item {:shape shape
:key id
:selected selected}]))]]
[:& layers-tools {:selected selected
:shapes shapes}]])))

View file

@ -8,11 +8,13 @@
(:require [beicon.core :as rx]))
(defn schedule
[ms func]
(let [sem (js/setTimeout #(func) ms)]
(reify rx/ICancellable
(-cancel [_]
(js/clearTimeout sem)))))
([func]
(schedule 0 func))
([ms func]
(let [sem (js/setTimeout #(func) ms)]
(reify rx/ICancellable
(-cancel [_]
(js/clearTimeout sem))))))
(defn interval
[ms func]