mirror of
https://github.com/penpot/penpot.git
synced 2025-05-10 04:06:38 +02:00
🔧 Adapt shapes to use new rumext macros.
This commit is contained in:
parent
204f180ec9
commit
fada526f5d
13 changed files with 225 additions and 344 deletions
|
@ -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)))
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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}))
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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}}]
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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}]])))
|
||||
|
|
|
@ -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]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue