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

View file

@ -304,7 +304,8 @@
:on-change toggle-selection :on-change toggle-selection
:checked selected?}] :checked selected?}]
[:label {:for (:id icon)}]] [: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} [:div.item-info {:on-click ignore-click}
(if edition? (if edition?
[:input.element-name {:type "text" [: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 ;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/. ;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;; ;;
;; Copyright (c) 2016-2017 Andrey Antukh <niwi@niwi.nz> ;; Copyright (c) 2016-2019 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.main.ui.shapes (ns uxbox.main.ui.shapes
(:require (:require
[lentes.core :as l] [lentes.core :as l]
[rumext.alpha :as mf] [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.store :as st]
[uxbox.main.ui.shapes.attrs :as attrs]
[uxbox.main.ui.shapes.circle :as circle] [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.icon :as icon]
[uxbox.main.ui.shapes.image :as image] [uxbox.main.ui.shapes.image :as image]
[uxbox.main.ui.shapes.path :as path] [uxbox.main.ui.shapes.path :as path]
[uxbox.main.ui.shapes.rect :as rect] [uxbox.main.ui.shapes.rect :as rect]
[uxbox.main.ui.shapes.text :as text] [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)
(defn render-shape (defn render-shape
[shape] [shape]
(mf/html
(case (:type shape) (case (:type shape)
;; :group (group-component shape) :text [:& text/text-component {:shape shape}]
:text (text/text-component shape) :icon [:& icon/icon-component {:shape shape}]
:icon (icon/icon-component shape) :rect [:& rect/rect-component {:shape shape}]
:rect (rect/rect-component shape) :path [:& path/path-component {:shape shape}]
:path (path/path-component shape) :image [:& image/image-component {:shape shape}]
:image (image/image-component shape) :circle [:& circle/circle-component {:shape shape}])))
:circle (circle/circle-component shape)))
(mf/defc shape-component
(mf/def shape-container {:wrap [mf/wrap-memo]}
:mixins [mf/reactive mf/memo] [{:keys [id] :as props}]
:init (let [shape-iref (mf/use-memo {:deps #js [id]
(fn [own {:keys [id] :as props}] :init #(-> (l/in [:shapes id])
(assoc own ::shape-ref (-> (l/in [:shapes id]) (l/derive st/state))})]
(l/derive st/state)))) (when-let [shape (mf/deref shape-iref)]
:render
(fn [own {:keys [id] :as props}]
(when-let [shape (mf/react (::shape-ref own))]
(when-not (:hidden shape) (when-not (:hidden shape)
(render-shape 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 ;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/. ;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;; ;;
;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz> ;; Copyright (c) 2016-2019 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.main.ui.shapes.circle (ns uxbox.main.ui.shapes.circle
(:require [lentes.core :as l] (:require
[uxbox.main.refs :as refs] [rumext.alpha :as mf]
[uxbox.main.geom :as geom] [uxbox.main.geom :as geom]
[uxbox.main.ui.shapes.common :as common] [uxbox.main.refs :as refs]
[uxbox.main.ui.shapes.attrs :as attrs] [uxbox.main.ui.shapes.attrs :as attrs]
[uxbox.main.ui.shapes.common :as common]
[uxbox.util.data :refer [classnames normalize-props]] [uxbox.util.data :refer [classnames normalize-props]]
[uxbox.util.geom.matrix :as gmt] [uxbox.util.geom.matrix :as gmt]
[uxbox.util.geom.point :as gpt] [uxbox.util.geom.point :as gpt]))
[rumext.core :as mx :include-macros true]))
;; --- Circle Component ;; --- Circle Component
(declare circle-shape) (declare circle-shape)
(mx/defc circle-component (mf/defc circle-component
{:mixins [mx/reactive mx/static]}
[{:keys [id] :as shape}] [{:keys [id] :as shape}]
(let [modifiers (mx/react (refs/selected-modifiers id)) (let [modifiers (mf/deref (refs/selected-modifiers id))
selected (mx/react refs/selected-shapes) selected (mf/deref refs/selected-shapes)
selected? (contains? selected id) selected? (contains? selected id)
on-mouse-down #(common/on-mouse-down % shape selected) on-mouse-down #(common/on-mouse-down % shape selected)]
shape (assoc shape :modifiers modifiers)]
[:g.shape {:class (when selected? "selected") [:g.shape {:class (when selected? "selected")
:on-mouse-down on-mouse-down} :on-mouse-down on-mouse-down}
(circle-shape shape)])) [:& circle-shape {:shape shape :modifiers modifiers}]]))
;; --- Circle Shape ;; --- Circle Shape
(mx/defc circle-shape (mf/defc circle-shape
{:mixins [mx/static]} [{:keys [shape modifiers] :as props}]
[{:keys [id modifiers rotation cx cy] :as shape}] (let [{:keys [id rotation cx cy]} shape
(let [{:keys [resize displacement]} modifiers {:keys [resize displacement]} modifiers
shape (cond-> shape shape (cond-> shape
displacement (geom/transform displacement) displacement (geom/transform displacement)

View file

@ -5,31 +5,32 @@
;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz> ;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.main.ui.shapes.icon (ns uxbox.main.ui.shapes.icon
(:require [uxbox.main.geom :as geom] (:require
[rumext.alpha :as mf]
[rumext.core :as mx]
[uxbox.main.geom :as geom]
[uxbox.main.refs :as refs] [uxbox.main.refs :as refs]
[uxbox.main.ui.shapes.common :as common]
[uxbox.main.ui.shapes.attrs :as attrs] [uxbox.main.ui.shapes.attrs :as attrs]
[uxbox.main.ui.shapes.common :as common]
[uxbox.util.data :refer [classnames normalize-props]] [uxbox.util.data :refer [classnames normalize-props]]
[uxbox.util.geom.matrix :as gmt] [uxbox.util.geom.matrix :as gmt]
[uxbox.util.geom.point :as gpt] [uxbox.util.geom.point :as gpt]))
[rumext.core :as mx :include-macros true]))
;; --- Icon Component ;; --- Icon Component
(declare icon-shape) (declare icon-shape)
(mx/defc icon-component (mf/defc icon-component
{:mixins [mx/static mx/reactive]} [{:keys [shape] :as props}]
[{:keys [id] :as shape}] (let [id (:id shape)
(let [modifiers (mx/react (refs/selected-modifiers id)) modifiers (mf/deref (refs/selected-modifiers id))
selected (mx/react refs/selected-shapes) selected (mf/deref refs/selected-shapes)
selected? (contains? selected id) selected? (contains? selected id)
on-mouse-down #(common/on-mouse-down % shape selected) on-mouse-down #(common/on-mouse-down % shape selected)]
shape (assoc shape :modifiers modifiers)]
[:g.shape {:class (when selected? "selected") [:g.shape {:class (when selected? "selected")
:on-mouse-down on-mouse-down} :on-mouse-down on-mouse-down}
(icon-shape shape)])) [:& icon-shape {:shape shape :modifiers modifiers}]]))
;; --- Icon Shape ;; --- Icon Shape
@ -41,10 +42,10 @@
center (gpt/point x-center y-center)] center (gpt/point x-center y-center)]
(gmt/rotate* mt rotation center))) (gmt/rotate* mt rotation center)))
(mx/defc icon-shape (mf/defc icon-shape
{:mixins [mx/static]} [{:keys [shape modifiers] :as props}]
[{:keys [id content metadata rotation x1 y1 modifiers] :as shape}] (let [{:keys [id content metadata rotation x1 y1]} shape
(let [{:keys [resize displacement]} modifiers {:keys [resize displacement]} modifiers
xfmt (cond-> (gmt/matrix) xfmt (cond-> (gmt/matrix)
displacement (gmt/multiply displacement) displacement (gmt/multiply displacement)
@ -74,10 +75,10 @@
;; --- Icon SVG ;; --- Icon SVG
(mx/defc icon-svg (mf/defc icon-svg
{:mixins [mx/static]} [{:keys [shape] :as props}]
[{:keys [content id metadata] :as shape}] (let [{:keys [content id metadata]} shape
(let [view-box (apply str (interpose " " (:view-box metadata))) view-box (apply str (interpose " " (:view-box metadata)))
props {:view-box view-box props {:view-box view-box
:id (str "shape-" id) :id (str "shape-" id)
:dangerouslySetInnerHTML #js {:__html content}}] :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 ;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/. ;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;; ;;
;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz> ;; Copyright (c) 2016-2019 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.main.ui.shapes.image (ns uxbox.main.ui.shapes.image
(:require [beicon.core :as rx] (:require
[lentes.core :as l] [lentes.core :as l]
[potok.core :as ptk] [rumext.alpha :as mf]
[uxbox.main.data.images :as udi]
[uxbox.main.geom :as geom] [uxbox.main.geom :as geom]
[uxbox.main.refs :as refs] [uxbox.main.refs :as refs]
[uxbox.main.store :as st] [uxbox.main.store :as st]
[uxbox.main.ui.shapes.common :as common]
[uxbox.main.ui.shapes.attrs :as attrs] [uxbox.main.ui.shapes.attrs :as attrs]
[uxbox.main.data.images :as udi] [uxbox.main.ui.shapes.common :as common]
[uxbox.util.data :refer [classnames normalize-props]] [uxbox.util.data :refer [classnames normalize-props]]
[uxbox.util.geom.matrix :as gmt] [uxbox.util.geom.matrix :as gmt]))
[rumext.core :as mx :include-macros true]))
;; --- Refs ;; --- Refs
@ -29,34 +28,29 @@
(declare image-shape) (declare image-shape)
(mx/defcs image-component (mf/defc image-component
{:mixins [mx/static mx/reactive] [{:keys [shape] :as props}]
:init (fn [own] (let [modifiers (mf/deref (refs/selected-modifiers (:id shape)))
;; TODO: maybe do it conditionally selected (mf/deref refs/selected-shapes)
;; (only fetch when it's not fetched) image (mf/deref (image-ref (:image shape)))
(when-let [id (-> own ::mx/props first :image)] selected? (contains? selected (:id shape))
(st/emit! (udi/fetch-image id))) on-mouse-down #(common/on-mouse-down % shape selected)]
own)}
[own {:keys [id image] :as shape}] (mf/use-effect
(let [modifiers (mx/react (refs/selected-modifiers id)) {:init #(st/emit! (udi/fetch-image (:image shape)))})
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)]
(when image (when image
[:g.shape {:class (when selected? "selected") [:g.shape {:class (when selected? "selected")
:on-mouse-down on-mouse-down} :on-mouse-down on-mouse-down}
(image-shape shape)]))) [:& image-shape {:shape shape
:image image
:modifiers modifiers}]])))
;; --- Image Shape ;; --- Image Shape
(mx/defc image-shape (mf/defc image-shape
{:mixins [mx/static]} [{:keys [shape image modifiers] :as props}]
[{:keys [id x1 y1 image modifiers] :as shape}] (let [{:keys [id x1 y1 width height]} (geom/size shape)
(let [{:keys [width height]} (geom/size shape)
{:keys [resize displacement]} modifiers {:keys [resize displacement]} modifiers
xfmt (cond-> (gmt/matrix) 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 ;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/. ;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;; ;;
;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz> ;; Copyright (c) 2016-2019 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.main.ui.shapes.path (ns uxbox.main.ui.shapes.path
(:require [potok.core :as ptk] (:require
[cuerdas.core :as str :include-macros true] [cuerdas.core :as str :include-macros true]
[uxbox.main.geom :as geom] [rumext.alpha :as mf]
[uxbox.main.store :as st]
[uxbox.main.refs :as refs]
[uxbox.main.data.shapes :as uds] [uxbox.main.data.shapes :as uds]
[uxbox.main.ui.shapes.common :as common] [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.attrs :as attrs]
[uxbox.main.ui.shapes.common :as common]
[uxbox.util.data :refer [classnames normalize-props]] [uxbox.util.data :refer [classnames normalize-props]]
[uxbox.util.geom.matrix :as gmt] [uxbox.util.geom.matrix :as gmt]
[uxbox.util.geom.point :as gpt] [uxbox.util.geom.point :as gpt]))
[rumext.core :as mx :include-macros true]))
;; --- Path Component ;; --- Path Component
(declare path-shape) (declare path-shape)
(mx/defc path-component (mf/defc path-component
{:mixins [mx/static mx/reactive]}
[{:keys [id] :as shape}] [{:keys [id] :as shape}]
(let [modifiers (mx/react (refs/selected-modifiers id)) (let [modifiers (mf/deref (refs/selected-modifiers id))
selected (mx/react refs/selected-shapes) selected (mf/deref refs/selected-shapes)
selected? (contains? selected id) selected? (contains? selected id)]
shape (assoc shape
:modifiers modifiers
:background? true)]
(letfn [(on-mouse-down [event] (letfn [(on-mouse-down [event]
(common/on-mouse-down event shape selected)) (common/on-mouse-down event shape selected))
(on-double-click [event] (on-double-click [event]
@ -38,7 +35,9 @@
[:g.shape {:class (when selected? "selected") [:g.shape {:class (when selected? "selected")
:on-double-click on-double-click :on-double-click on-double-click
:on-mouse-down on-mouse-down} :on-mouse-down on-mouse-down}
(path-shape shape)]))) [:& path-shape {:shape shape
:modifiers modifiers
:background? true}]])))
;; --- Path Shape ;; --- Path Shape
@ -63,9 +62,8 @@
buffer (conj buffer (str/istr "L~{x},~{y}"))] buffer (conj buffer (str/istr "L~{x},~{y}"))]
(recur buffer (inc index))))))) (recur buffer (inc index)))))))
(mx/defc path-shape (mf/defc path-shape
{:mixins [mx/static]} [{:keys [shape modifiers background?] :as props}]
[{:keys [id modifiers background?] :as shape}]
(let [{:keys [resize displacement]} modifiers (let [{:keys [resize displacement]} modifiers
shape (cond-> shape shape (cond-> shape
displacement (geom/transform displacement) displacement (geom/transform displacement)
@ -73,13 +71,13 @@
moving? (boolean displacement) moving? (boolean displacement)
pdata (render-path shape) pdata (render-path shape)
props {:id (str id) props {:id (str (:id shape))
:class (classnames :move-cursor moving?) :class (classnames :move-cursor moving?)
:d pdata} :d pdata}
attrs (merge (attrs/extract-style-attrs shape) props)] attrs (merge (attrs/extract-style-attrs shape) props)]
(if background? (if background?
[:g {} [:g
[:path {:stroke "transparent" [:path {:stroke "transparent"
:fill "transparent" :fill "transparent"
:stroke-width "20px" :stroke-width "20px"

View file

@ -5,31 +5,33 @@
;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz> ;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.main.ui.shapes.rect (ns uxbox.main.ui.shapes.rect
(:require [uxbox.main.geom :as geom] (:require
[rumext.alpha :as mf]
[uxbox.main.geom :as geom]
[uxbox.main.refs :as refs] [uxbox.main.refs :as refs]
[uxbox.main.ui.shapes.common :as common]
[uxbox.main.ui.shapes.attrs :as attrs] [uxbox.main.ui.shapes.attrs :as attrs]
[uxbox.util.geom.matrix :as gmt] [uxbox.main.ui.shapes.common :as common]
[uxbox.util.geom.point :as gpt]
[rumext.core :as mx :include-macros true]
[uxbox.util.data :refer [classnames normalize-props]] [uxbox.util.data :refer [classnames normalize-props]]
[uxbox.util.dom :as dom])) [uxbox.util.dom :as dom]
[uxbox.util.geom.matrix :as gmt]
[uxbox.util.geom.point :as gpt]))
;; --- Rect Component ;; --- Rect Component
(declare rect-shape) (declare rect-shape)
(mx/defc rect-component (mf/defc rect-component
{:mixins [mx/reactive mx/static]} [{:keys [shape] :as props}]
[{:keys [id] :as shape}] (let [id (:id shape)
(let [modifiers (mx/react (refs/selected-modifiers id)) modifiers (mf/deref (refs/selected-modifiers id))
selected (mx/react refs/selected-shapes) selected (mf/deref refs/selected-shapes)
selected? (contains? selected id) selected? (contains? selected id)
on-mouse-down #(common/on-mouse-down % shape selected) on-mouse-down #(common/on-mouse-down % shape selected)]
shape (assoc shape :modifiers modifiers)] ;; shape (assoc shape :modifiers modifiers)]
[:g.shape {:class (when selected? "selected") [:g.shape {:class (when selected? "selected")
:on-mouse-down on-mouse-down} :on-mouse-down on-mouse-down}
(rect-shape shape identity)])) [:& rect-shape {:shape shape
:modifiers modifiers}]]))
;; --- Rect Shape ;; --- Rect Shape
@ -40,10 +42,11 @@
center (gpt/point x-center y-center)] center (gpt/point x-center y-center)]
(gmt/rotate* mt rotation center))) (gmt/rotate* mt rotation center)))
(mx/defc rect-shape (mf/defc rect-shape
{:mixins [mx/static]} [{:keys [shape modifiers] :as props}]
[{:keys [id rotation modifiers] :as shape}] (let [{:keys [id rotation]} shape
(let [{:keys [displacement resize]} modifiers {:keys [displacement resize]} modifiers
xfmt (cond-> (gmt/matrix) xfmt (cond-> (gmt/matrix)
displacement (gmt/multiply displacement) displacement (gmt/multiply displacement)
resize (gmt/multiply resize)) 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 ;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/. ;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;; ;;
;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz> ;; Copyright (c) 2016-2019 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.main.ui.shapes.text (ns uxbox.main.ui.shapes.text
(:require (:require
@ -28,8 +28,7 @@
[event {:keys [id group] :as shape} selected] [event {:keys [id group] :as shape} selected]
(if (and (not (:blocked shape)) (if (and (not (:blocked shape))
(or @refs/selected-drawing-tool (or @refs/selected-drawing-tool
@refs/selected-edition @refs/selected-edition))
(and group (:locked (geom/resolve-parent shape)))))
(dom/stop-propagation event) (dom/stop-propagation event)
(common/on-mouse-down event shape selected))) (common/on-mouse-down event shape selected)))
@ -40,12 +39,13 @@
(declare text-shape-edit) (declare text-shape-edit)
(mf/def text-component (mf/def text-component
:mixins [mf/memo mx/reactive] :mixins [mf/memo mf/reactive]
:render :render
(fn [own {:keys [id x1 y1 content group] :as shape}] (fn [own {:keys [shape] :as props}]
(let [modifiers (mx/react (refs/selected-modifiers id)) (let [{:keys [id x1 y1 content group]} shape
selected (mx/react refs/selected-shapes) modifiers (mf/react (refs/selected-modifiers id))
edition? (= (mx/react refs/selected-edition) id) selected (mf/react refs/selected-shapes)
edition? (= (mf/react refs/selected-edition) id)
selected? (and (contains? selected id) selected? (and (contains? selected id)
(= (count selected) 1)) (= (count selected) 1))
shape (assoc shape :modifiers modifiers)] shape (assoc shape :modifiers modifiers)]
@ -60,8 +60,8 @@
:on-double-click on-double-click :on-double-click on-double-click
:on-mouse-down on-mouse-down} :on-mouse-down on-mouse-down}
(if edition? (if edition?
(text-shape-edit shape) [:& text-shape-edit {:shape shape}]
(text-shape-wrapper shape))])))) [:& text-shape-wrapper {:shape shape}])]))))
;; --- Text Styles Helpers ;; --- Text Styles Helpers
@ -113,15 +113,15 @@
:did-mount :did-mount
(fn [own] (fn [own]
(let [shape (::mf/props own) (let [shape (get-in own [::mf/props :shape])
dom (mx/ref-node (::container own))] dom (mf/ref-node (::container own))]
(set! (.-textContent dom) (:content shape "")) (set! (.-textContent dom) (:content shape ""))
(.focus dom) (.focus dom)
own)) own))
:render :render
(fn [own {:keys [id x1 y1 content] :as shape}] (fn [own {:keys [shape] :as props}]
(let [{:keys [width height]} (geom/size shape) (let [{:keys [id x1 y1 content width height]} (geom/size shape)
style (make-style shape) style (make-style shape)
on-input (fn [ev] on-input (fn [ev]
(let [content (dom/event->inner-text ev)] (let [content (dom/event->inner-text ev)]
@ -136,7 +136,6 @@
(mf/def text-shape-wrapper (mf/def text-shape-wrapper
:mixins [mf/memo] :mixins [mf/memo]
:key-fn pr-str
:init :init
(fn [own props] (fn [own props]
@ -152,15 +151,16 @@
:did-mount :did-mount
(fn [own] (fn [own]
(let [shape (::mf/props own) (let [shape (get-in own [::mf/props :shape])
dom (mf/ref-node (::fobject own)) dom (mf/ref-node (::fobject own))
html (dom/render-to-html (text-shape-html shape))] html (dom/render-to-html (text-shape-html shape))]
(set! (.-innerHTML dom) html)) (set! (.-innerHTML dom) html))
own) own)
:render :render
(fn [own {:keys [id modifiers] :as shape}] (fn [own {:keys [shape] :as props}]
(let [{:keys [displacement resize]} modifiers (let [{:keys [id modifiers]} shape
{:keys [displacement resize]} modifiers
xfmt (cond-> (gmt/matrix) xfmt (cond-> (gmt/matrix)
displacement (gmt/multiply displacement) displacement (gmt/multiply displacement)
resize (gmt/multiply resize)) resize (gmt/multiply resize))

View file

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

View file

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

View file

@ -23,6 +23,7 @@
[uxbox.util.data :refer (read-string classnames)] [uxbox.util.data :refer (read-string classnames)]
[uxbox.util.dom :as dom] [uxbox.util.dom :as dom]
[uxbox.util.dom.dnd :as dnd] [uxbox.util.dom.dnd :as dnd]
[uxbox.util.timers :as tm]
[uxbox.util.router :as r]) [uxbox.util.router :as r])
(:import goog.events.EventType)) (:import goog.events.EventType))
@ -134,12 +135,13 @@
:drag-top (= :top (:over @local)) :drag-top (= :top (:over @local))
:drag-bottom (= :bottom (:over @local)) :drag-bottom (= :bottom (:over @local))
:drag-inside (= :middle (:over @local)))] :drag-inside (= :middle (:over @local)))]
;; TODO: consider using http://react-dnd.github.io/react-dnd/docs/overview
(letfn [(on-drag-start [event] (letfn [(on-drag-start [event]
(let [target (dom/event->target event)] (let [target (dom/event->target event)]
(dnd/set-allowed-effect! event "move") (dnd/set-allowed-effect! event "move")
(dnd/set-data! event (:id shape)) (dnd/set-data! event (:id shape))
(dnd/set-image! event target 50 10) (dnd/set-image! event target 50 10)
(swap! local assoc :dragging true))) (tm/schedule #(swap! local assoc :dragging true))))
(on-drag-end [event] (on-drag-end [event]
(swap! local assoc :dragging false :over nil)) (swap! local assoc :dragging false :over nil))
(on-drop [event] (on-drop [event]
@ -189,94 +191,6 @@
;; --- Layer Group (Component) ;; --- 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) ;; --- Layers Tools (Buttons Component)
;; (defn- allow-grouping? ;; (defn- allow-grouping?
@ -340,30 +254,25 @@
;; --- Layers Toolbox (Component) ;; --- Layers Toolbox (Component)
(mf/def layers-toolbox (def ^:private shapes-iref
:mixins [mx/static mx/reactive] (-> (l/key :shapes)
(l/derive st/state)))
:init (mf/defc layers-toolbox
(fn [own {:keys [id]}] [{:keys [page selected] :as props}]
(assoc own ::shapes-ref (-> (l/key :shapes) (let [shapes (mf/deref shapes-iref)
(l/derive st/state)))) on-click #(st/emit! (udw/toggle-flag :layers))]
: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#layers.tool-window
[:div.tool-window-bar [:div.tool-window-bar
[:div.tool-window-icon i/layers] [:div.tool-window-icon i/layers]
[:span "Layers"] [:span "Layers"]
[:div.tool-window-close {:on-click close} i/close]] [:div.tool-window-close {:on-click on-click} i/close]]
[:div.tool-window-content [:div.tool-window-content
[:ul.element-list [:ul.element-list
(for [id (:shapes page)] (for [id (:shapes page)]
(let [shape (get shapes id)] [:& layer-item {:shape (get shapes id)
[:& layer-item {:shape shape :selected selected
:key id :key id}])]]
:selected selected}]))]]
[:& layers-tools {:selected selected [:& layers-tools {:selected selected
:shapes shapes}]]))) :shapes shapes}]]))

View file

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