From fada526f5d418e53c37109976df581d301bb041b Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 7 Aug 2019 20:12:35 +0200 Subject: [PATCH] :wrench: Adapt shapes to use new rumext macros. --- frontend/src/uxbox/main/exports.cljs | 70 +++++---- .../src/uxbox/main/ui/dashboard/icons.cljs | 3 +- frontend/src/uxbox/main/ui/shapes.cljs | 55 +++---- frontend/src/uxbox/main/ui/shapes/circle.cljs | 40 +++-- frontend/src/uxbox/main/ui/shapes/icon.cljs | 49 ++++--- frontend/src/uxbox/main/ui/shapes/image.cljs | 64 ++++---- frontend/src/uxbox/main/ui/shapes/path.cljs | 52 ++++--- frontend/src/uxbox/main/ui/shapes/rect.cljs | 45 +++--- frontend/src/uxbox/main/ui/shapes/text.cljs | 36 ++--- .../src/uxbox/main/ui/workspace/canvas.cljs | 5 +- .../uxbox/main/ui/workspace/selection.cljs | 1 - .../main/ui/workspace/sidebar/layers.cljs | 137 +++--------------- frontend/src/uxbox/util/timers.cljs | 12 +- 13 files changed, 225 insertions(+), 344 deletions(-) diff --git a/frontend/src/uxbox/main/exports.cljs b/frontend/src/uxbox/main/exports.cljs index 6ff65121fc..3392566f02 100644 --- a/frontend/src/uxbox/main/exports.cljs +++ b/frontend/src/uxbox/main/exports.cljs @@ -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))) diff --git a/frontend/src/uxbox/main/ui/dashboard/icons.cljs b/frontend/src/uxbox/main/ui/dashboard/icons.cljs index f06dce3d01..0db699a5f3 100644 --- a/frontend/src/uxbox/main/ui/dashboard/icons.cljs +++ b/frontend/src/uxbox/main/ui/dashboard/icons.cljs @@ -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" diff --git a/frontend/src/uxbox/main/ui/shapes.cljs b/frontend/src/uxbox/main/ui/shapes.cljs index b2163d7b78..e2f28d7aba 100644 --- a/frontend/src/uxbox/main/ui/shapes.cljs +++ b/frontend/src/uxbox/main/ui/shapes.cljs @@ -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 +;; Copyright (c) 2016-2019 Andrey Antukh (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})) - - diff --git a/frontend/src/uxbox/main/ui/shapes/circle.cljs b/frontend/src/uxbox/main/ui/shapes/circle.cljs index 554d85cc96..4c5cc6e9e8 100644 --- a/frontend/src/uxbox/main/ui/shapes/circle.cljs +++ b/frontend/src/uxbox/main/ui/shapes/circle.cljs @@ -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 +;; Copyright (c) 2016-2019 Andrey Antukh (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) diff --git a/frontend/src/uxbox/main/ui/shapes/icon.cljs b/frontend/src/uxbox/main/ui/shapes/icon.cljs index 79379ae1c1..85d36efbf3 100644 --- a/frontend/src/uxbox/main/ui/shapes/icon.cljs +++ b/frontend/src/uxbox/main/ui/shapes/icon.cljs @@ -5,31 +5,32 @@ ;; Copyright (c) 2016 Andrey Antukh (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}}] diff --git a/frontend/src/uxbox/main/ui/shapes/image.cljs b/frontend/src/uxbox/main/ui/shapes/image.cljs index ce60dc8b80..fc34a3dc1e 100644 --- a/frontend/src/uxbox/main/ui/shapes/image.cljs +++ b/frontend/src/uxbox/main/ui/shapes/image.cljs @@ -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 +;; Copyright (c) 2016-2019 Andrey Antukh (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) diff --git a/frontend/src/uxbox/main/ui/shapes/path.cljs b/frontend/src/uxbox/main/ui/shapes/path.cljs index 60e0b84086..77e03c524d 100644 --- a/frontend/src/uxbox/main/ui/shapes/path.cljs +++ b/frontend/src/uxbox/main/ui/shapes/path.cljs @@ -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 +;; Copyright (c) 2016-2019 Andrey Antukh (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" diff --git a/frontend/src/uxbox/main/ui/shapes/rect.cljs b/frontend/src/uxbox/main/ui/shapes/rect.cljs index 61357a17cb..b4b5d9a984 100644 --- a/frontend/src/uxbox/main/ui/shapes/rect.cljs +++ b/frontend/src/uxbox/main/ui/shapes/rect.cljs @@ -5,31 +5,33 @@ ;; Copyright (c) 2016 Andrey Antukh (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)) diff --git a/frontend/src/uxbox/main/ui/shapes/text.cljs b/frontend/src/uxbox/main/ui/shapes/text.cljs index 457c4b1160..457a7869ed 100644 --- a/frontend/src/uxbox/main/ui/shapes/text.cljs +++ b/frontend/src/uxbox/main/ui/shapes/text.cljs @@ -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 +;; Copyright (c) 2016-2019 Andrey Antukh (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)) diff --git a/frontend/src/uxbox/main/ui/workspace/canvas.cljs b/frontend/src/uxbox/main/ui/workspace/canvas.cljs index 37be30d414..a0ff4a7b49 100644 --- a/frontend/src/uxbox/main/ui/workspace/canvas.cljs +++ b/frontend/src/uxbox/main/ui/workspace/canvas.cljs @@ -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 diff --git a/frontend/src/uxbox/main/ui/workspace/selection.cljs b/frontend/src/uxbox/main/ui/workspace/selection.cljs index 2860b7c857..9d0b7fb783 100644 --- a/frontend/src/uxbox/main/ui/workspace/selection.cljs +++ b/frontend/src/uxbox/main/ui/workspace/selection.cljs @@ -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) diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs index 92318e9b02..4db402ac5f 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs @@ -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}]]))) diff --git a/frontend/src/uxbox/util/timers.cljs b/frontend/src/uxbox/util/timers.cljs index fa239a601e..9e60b1d1e3 100644 --- a/frontend/src/uxbox/util/timers.cljs +++ b/frontend/src/uxbox/util/timers.cljs @@ -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]