mirror of
https://github.com/penpot/penpot.git
synced 2025-06-06 09:11:42 +02:00
Complete refactor of shapes rendering.
This commit is contained in:
parent
2fed551cf1
commit
1572c4cdd3
18 changed files with 403 additions and 261 deletions
|
@ -31,14 +31,6 @@
|
||||||
[shape & params]
|
[shape & params]
|
||||||
(:type shape))
|
(:type shape))
|
||||||
|
|
||||||
(defmulti -render
|
|
||||||
dispatch-by-type
|
|
||||||
:hierarchy #'+hierarchy+)
|
|
||||||
|
|
||||||
(defmulti -render-svg
|
|
||||||
dispatch-by-type
|
|
||||||
:hierarchy #'+hierarchy+)
|
|
||||||
|
|
||||||
(defmulti -move
|
(defmulti -move
|
||||||
dispatch-by-type
|
dispatch-by-type
|
||||||
:hierarchy #'+hierarchy+)
|
:hierarchy #'+hierarchy+)
|
||||||
|
|
13
src/uxbox/ui/core.cljs
Normal file
13
src/uxbox/ui/core.cljs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
(ns uxbox.ui.core
|
||||||
|
(:require [beicon.core :as rx]))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Actions
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defonce actions-s (rx/bus))
|
||||||
|
|
||||||
|
(defn emit-action!
|
||||||
|
[type]
|
||||||
|
(rx/push! actions-s type))
|
||||||
|
|
|
@ -7,11 +7,11 @@
|
||||||
[uxbox.rstore :as rs]
|
[uxbox.rstore :as rs]
|
||||||
[uxbox.schema :as sc]
|
[uxbox.schema :as sc]
|
||||||
[uxbox.library :as library]
|
[uxbox.library :as library]
|
||||||
[uxbox.shapes :as shapes]
|
|
||||||
[uxbox.data.dashboard :as dd]
|
[uxbox.data.dashboard :as dd]
|
||||||
[uxbox.util.lens :as ul]
|
[uxbox.util.lens :as ul]
|
||||||
[uxbox.ui.icons :as i]
|
[uxbox.ui.icons :as i]
|
||||||
[uxbox.ui.form :as form]
|
[uxbox.ui.form :as form]
|
||||||
|
[uxbox.ui.shapes.core :as uusc]
|
||||||
[uxbox.ui.lightbox :as lightbox]
|
[uxbox.ui.lightbox :as lightbox]
|
||||||
[uxbox.util.dom :as dom]
|
[uxbox.util.dom :as dom]
|
||||||
[uxbox.ui.mixins :as mx]))
|
[uxbox.ui.mixins :as mx]))
|
||||||
|
@ -111,7 +111,7 @@
|
||||||
[:div.dashboard-grid-content
|
[:div.dashboard-grid-content
|
||||||
(for [icon (:icons coll)]
|
(for [icon (:icons coll)]
|
||||||
[:div.grid-item.small-item.project-th {}
|
[:div.grid-item.small-item.project-th {}
|
||||||
[:span.grid-item-image #_i/toggle (shapes/-render-svg icon nil)]
|
[:span.grid-item-image #_i/toggle (uusc/render-shape-svg icon nil)]
|
||||||
[:h3 (:name icon)]
|
[:h3 (:name icon)]
|
||||||
#_[:div.project-th-actions
|
#_[:div.project-th-actions
|
||||||
[:div.project-th-icon.edit i/pencil]
|
[:div.project-th-icon.edit i/pencil]
|
||||||
|
|
|
@ -1,115 +1,10 @@
|
||||||
(ns uxbox.ui.shapes
|
(ns uxbox.ui.shapes
|
||||||
"A ui related implementation for uxbox.shapes ns."
|
"A ui related implementation for uxbox.shapes ns."
|
||||||
(:require [sablono.core :refer-macros [html]]
|
(:require [uxbox.ui.shapes.core :as usc]
|
||||||
[cuerdas.core :as str]
|
[uxbox.ui.shapes.icon]
|
||||||
[rum.core :as rum]
|
[uxbox.ui.shapes.rect]
|
||||||
[uxbox.state :as st]
|
[uxbox.ui.shapes.group]
|
||||||
[uxbox.shapes :as sh]
|
[uxbox.ui.shapes.line]
|
||||||
[uxbox.ui.icons :as i]
|
[uxbox.ui.shapes.circle]))
|
||||||
[uxbox.util.math :as mth]
|
|
||||||
[uxbox.util.data :refer (remove-nil-vals)]))
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
(def ^:const shape usc/shape)
|
||||||
;; Attribute transformations
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
(def ^:static ^:private +style-attrs+
|
|
||||||
#{:fill :opacity :stroke :stroke-opacity :stroke-width :stroke-type :rx :ry})
|
|
||||||
|
|
||||||
(defn- transform-stroke-type
|
|
||||||
[attrs]
|
|
||||||
(if-let [type (:stroke-type attrs)]
|
|
||||||
(let [value (case type
|
|
||||||
:dotted "1,1"
|
|
||||||
:dashed "10,10")]
|
|
||||||
(-> attrs
|
|
||||||
(assoc! :stroke-dasharray value)
|
|
||||||
(dissoc! :stroke-type)))
|
|
||||||
attrs))
|
|
||||||
|
|
||||||
(defn- extract-style-attrs
|
|
||||||
"Extract predefinet attrs from shapes."
|
|
||||||
[shape]
|
|
||||||
(let [attrs (select-keys shape +style-attrs+)]
|
|
||||||
(-> (transient attrs)
|
|
||||||
(transform-stroke-type)
|
|
||||||
(persistent!))))
|
|
||||||
|
|
||||||
(defn- make-debug-attrs
|
|
||||||
[shape]
|
|
||||||
(let [attrs (select-keys shape [:rotation :width :height :x :y])
|
|
||||||
xf (map (fn [[x v]]
|
|
||||||
[(keyword (str "data-" (name x))) v]))]
|
|
||||||
(into {} xf attrs)))
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;; Implementation
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
(defmethod sh/-render :builtin/icon
|
|
||||||
[{:keys [data id] :as shape} _]
|
|
||||||
(let [key (str id)
|
|
||||||
rfm (sh/-transformation shape)
|
|
||||||
attrs (merge {:id key :key key :transform (str rfm)}
|
|
||||||
(extract-style-attrs shape)
|
|
||||||
(make-debug-attrs shape))]
|
|
||||||
(html
|
|
||||||
[:g attrs data])))
|
|
||||||
|
|
||||||
(defmethod sh/-render :builtin/line
|
|
||||||
[{:keys [id x1 y1 x2 y2] :as shape}]
|
|
||||||
(let [key (str id)
|
|
||||||
props (select-keys shape [:x1 :x2 :y2 :y1])
|
|
||||||
attrs (-> (extract-style-attrs shape)
|
|
||||||
(merge {:id key :key key})
|
|
||||||
(merge props))]
|
|
||||||
(html
|
|
||||||
[:line attrs])))
|
|
||||||
|
|
||||||
|
|
||||||
(defmethod sh/-render :builtin/circle
|
|
||||||
[{:keys [id] :as shape}]
|
|
||||||
(let [key (str id)
|
|
||||||
rfm (sh/-transformation shape)
|
|
||||||
props (select-keys shape [:cx :cy :rx :ry])
|
|
||||||
attrs (-> (extract-style-attrs shape)
|
|
||||||
(merge {:id key :key key :transform (str rfm)})
|
|
||||||
(merge props))]
|
|
||||||
(html
|
|
||||||
[:ellipse attrs])))
|
|
||||||
|
|
||||||
(defmethod sh/-render :builtin/rect
|
|
||||||
[{:keys [id x1 y1 x2 y2] :as shape}]
|
|
||||||
(let [key (str id)
|
|
||||||
rfm (sh/-transformation shape)
|
|
||||||
size (sh/-size shape)
|
|
||||||
props {:x x1 :y y1 :id key :key key :transform (str rfm)}
|
|
||||||
attrs (-> (extract-style-attrs shape)
|
|
||||||
(merge props size))]
|
|
||||||
(html
|
|
||||||
[:rect attrs])))
|
|
||||||
|
|
||||||
(defmethod sh/-render :builtin/group
|
|
||||||
[{:keys [items id dx dy rotation] :as shape} factory]
|
|
||||||
(let [key (str "group-" id)
|
|
||||||
rfm (sh/-transformation shape)
|
|
||||||
attrs (merge {:id key :key key :transform (str rfm)}
|
|
||||||
(extract-style-attrs shape)
|
|
||||||
(make-debug-attrs shape))
|
|
||||||
shapes-by-id (get @st/state :shapes-by-id)]
|
|
||||||
(html
|
|
||||||
[:g attrs
|
|
||||||
(for [item (->> items
|
|
||||||
(map #(get shapes-by-id %))
|
|
||||||
(remove :hidden)
|
|
||||||
(reverse))]
|
|
||||||
(-> (factory item)
|
|
||||||
(rum/with-key (str (:id item)))))])))
|
|
||||||
|
|
||||||
(defmethod sh/-render-svg :builtin/icon
|
|
||||||
[{:keys [data id view-box] :as shape}]
|
|
||||||
(let [key (str "icon-svg-" id)
|
|
||||||
view-box (apply str (interpose " " view-box))
|
|
||||||
props {:view-box view-box :id key :key key}]
|
|
||||||
(html
|
|
||||||
[:svg props data])))
|
|
||||||
|
|
24
src/uxbox/ui/shapes/circle.cljs
Normal file
24
src/uxbox/ui/shapes/circle.cljs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
(ns uxbox.ui.shapes.circle
|
||||||
|
(:require [sablono.core :refer-macros [html]]
|
||||||
|
[cuerdas.core :as str]
|
||||||
|
[rum.core :as rum]
|
||||||
|
[cats.labs.lens :as l]
|
||||||
|
[uxbox.rstore :as rs]
|
||||||
|
[uxbox.state :as st]
|
||||||
|
[uxbox.shapes :as ush]
|
||||||
|
[uxbox.data.workspace :as dw]
|
||||||
|
[uxbox.ui.core :as uuc]
|
||||||
|
[uxbox.ui.keyboard :as kbd]
|
||||||
|
[uxbox.ui.shapes.core :as uusc]
|
||||||
|
[uxbox.util.dom :as dom]))
|
||||||
|
|
||||||
|
(defmethod uusc/render-shape :builtin/circle
|
||||||
|
[{:keys [id] :as shape}]
|
||||||
|
(let [key (str id)
|
||||||
|
rfm (ush/-transformation shape)
|
||||||
|
props (select-keys shape [:cx :cy :rx :ry])
|
||||||
|
attrs (-> (uusc/extract-style-attrs shape)
|
||||||
|
(merge {:id key :key key :transform (str rfm)})
|
||||||
|
(merge props))]
|
||||||
|
(html
|
||||||
|
[:ellipse attrs])))
|
86
src/uxbox/ui/shapes/core.cljs
Normal file
86
src/uxbox/ui/shapes/core.cljs
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
(ns uxbox.ui.shapes.core
|
||||||
|
(:require [cats.labs.lens :as l]
|
||||||
|
[cuerdas.core :as str]
|
||||||
|
[rum.core :as rum]
|
||||||
|
[beicon.core :as rx]
|
||||||
|
[uxbox.state :as st]
|
||||||
|
[uxbox.shapes :as sh]
|
||||||
|
[uxbox.ui.mixins :as mx]))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Implementation Api
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defmulti render-component
|
||||||
|
(fn [own shape] (:type shape))
|
||||||
|
:hierarchy #'sh/+hierarchy+)
|
||||||
|
|
||||||
|
(defmulti render-shape
|
||||||
|
sh/dispatch-by-type
|
||||||
|
:hierarchy #'sh/+hierarchy+)
|
||||||
|
|
||||||
|
(defmulti render-shape-svg
|
||||||
|
sh/dispatch-by-type
|
||||||
|
:hierarchy #'sh/+hierarchy+)
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Lenses
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(def ^:const selected-shapes-l
|
||||||
|
(as-> (l/in [:workspace :selected]) $
|
||||||
|
(l/focus-atom $ st/state)))
|
||||||
|
|
||||||
|
(defn- focus-shape
|
||||||
|
[id]
|
||||||
|
(as-> (l/in [:shapes-by-id id]) $
|
||||||
|
(l/focus-atom $ st/state)))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Component Api
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defn- shape-render
|
||||||
|
[own id]
|
||||||
|
(let [shape-l (focus-shape id)
|
||||||
|
shape (rum/react shape-l)]
|
||||||
|
(render-component own shape)))
|
||||||
|
|
||||||
|
(def ^:const shape
|
||||||
|
(mx/component
|
||||||
|
{:render shape-render
|
||||||
|
:name "shape"
|
||||||
|
:mixins [(mx/local) mx/static rum/reactive]}))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Attribute transformations
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(def ^:static ^:private +style-attrs+
|
||||||
|
#{:fill :opacity :stroke :stroke-opacity :stroke-width :stroke-type :rx :ry})
|
||||||
|
|
||||||
|
(defn- transform-stroke-type
|
||||||
|
[attrs]
|
||||||
|
(if-let [type (:stroke-type attrs)]
|
||||||
|
(let [value (case type
|
||||||
|
:dotted "1,1"
|
||||||
|
:dashed "10,10")]
|
||||||
|
(-> attrs
|
||||||
|
(assoc! :stroke-dasharray value)
|
||||||
|
(dissoc! :stroke-type)))
|
||||||
|
attrs))
|
||||||
|
|
||||||
|
(defn- extract-style-attrs
|
||||||
|
"Extract predefinet attrs from shapes."
|
||||||
|
[shape]
|
||||||
|
(let [attrs (select-keys shape +style-attrs+)]
|
||||||
|
(-> (transient attrs)
|
||||||
|
(transform-stroke-type)
|
||||||
|
(persistent!))))
|
||||||
|
|
||||||
|
(defn- make-debug-attrs
|
||||||
|
[shape]
|
||||||
|
(let [attrs (select-keys shape [:rotation :width :height :x :y])
|
||||||
|
xf (map (fn [[x v]]
|
||||||
|
[(keyword (str "data-" (name x))) v]))]
|
||||||
|
(into {} xf attrs)))
|
31
src/uxbox/ui/shapes/group.cljs
Normal file
31
src/uxbox/ui/shapes/group.cljs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
(ns uxbox.ui.shapes.group
|
||||||
|
(:require [sablono.core :refer-macros [html]]
|
||||||
|
[cuerdas.core :as str]
|
||||||
|
[rum.core :as rum]
|
||||||
|
[cats.labs.lens :as l]
|
||||||
|
[uxbox.rstore :as rs]
|
||||||
|
[uxbox.state :as st]
|
||||||
|
[uxbox.shapes :as ush]
|
||||||
|
[uxbox.data.workspace :as dw]
|
||||||
|
[uxbox.ui.core :as uuc]
|
||||||
|
[uxbox.ui.keyboard :as kbd]
|
||||||
|
[uxbox.ui.shapes.core :as uusc]
|
||||||
|
[uxbox.util.dom :as dom]))
|
||||||
|
|
||||||
|
(defmethod uusc/render-shape :builtin/group
|
||||||
|
[{:keys [items id dx dy rotation] :as shape} factory]
|
||||||
|
(let [key (str "group-" id)
|
||||||
|
rfm (ush/-transformation shape)
|
||||||
|
attrs (merge {:id key :key key :transform (str rfm)}
|
||||||
|
(uusc/extract-style-attrs shape)
|
||||||
|
(uusc/make-debug-attrs shape))
|
||||||
|
shapes-by-id (get @st/state :shapes-by-id)]
|
||||||
|
(html
|
||||||
|
[:g attrs
|
||||||
|
(for [item (->> items
|
||||||
|
(map #(get shapes-by-id %))
|
||||||
|
(remove :hidden)
|
||||||
|
(reverse))]
|
||||||
|
(-> (factory (:id item))
|
||||||
|
(rum/with-key (str (:id item)))))])))
|
||||||
|
|
132
src/uxbox/ui/shapes/icon.cljs
Normal file
132
src/uxbox/ui/shapes/icon.cljs
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
(ns uxbox.ui.shapes.icon
|
||||||
|
(:require [sablono.core :refer-macros [html]]
|
||||||
|
[cuerdas.core :as str]
|
||||||
|
[rum.core :as rum]
|
||||||
|
[cats.labs.lens :as l]
|
||||||
|
[uxbox.rstore :as rs]
|
||||||
|
[uxbox.state :as st]
|
||||||
|
[uxbox.shapes :as sh]
|
||||||
|
[uxbox.data.workspace :as dw]
|
||||||
|
[uxbox.ui.core :as uuc]
|
||||||
|
[uxbox.ui.mixins :as mx]
|
||||||
|
[uxbox.ui.keyboard :as kbd]
|
||||||
|
[uxbox.ui.shapes.core :as uusc]
|
||||||
|
[uxbox.util.dom :as dom]))
|
||||||
|
|
||||||
|
(def ^:private ^:const selection-circle-style
|
||||||
|
{:fillOpacity "0.5"
|
||||||
|
:strokeWidth "1px"
|
||||||
|
:vectorEffect "non-scaling-stroke"})
|
||||||
|
|
||||||
|
(def ^:private ^:const default-selection-props
|
||||||
|
{:r 5 :style selection-circle-style
|
||||||
|
:fill "#333"
|
||||||
|
:stroke "#333"})
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Icon Component
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defn on-mouse-down
|
||||||
|
[event {:keys [id group] :as shape} selected]
|
||||||
|
(let [selected? (contains? selected id)]
|
||||||
|
(when-not (:blocked shape)
|
||||||
|
(cond
|
||||||
|
(and group (:locked (sh/resolve-parent shape)))
|
||||||
|
nil
|
||||||
|
|
||||||
|
(and (not selected?) (empty? selected))
|
||||||
|
(do
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(uuc/emit-action! :shape/movement)
|
||||||
|
(rs/emit! (dw/select-shape id)))
|
||||||
|
|
||||||
|
(and (not selected?) (not (empty? selected)))
|
||||||
|
(do
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(if (kbd/shift? event)
|
||||||
|
(rs/emit! (dw/select-shape id))
|
||||||
|
(rs/emit! (dw/deselect-all)
|
||||||
|
(dw/select-shape id))))
|
||||||
|
|
||||||
|
:else
|
||||||
|
(do
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(uuc/emit-action! :shape/movement))))))
|
||||||
|
|
||||||
|
(defn on-mouse-up
|
||||||
|
[event {:keys [id group] :as shape}]
|
||||||
|
(cond
|
||||||
|
(and group (:locked (sh/resolve-parent shape)))
|
||||||
|
nil
|
||||||
|
|
||||||
|
:else
|
||||||
|
(do
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(uuc/emit-action! :nothing))))
|
||||||
|
|
||||||
|
(declare handlers)
|
||||||
|
|
||||||
|
(defmethod uusc/render-component :default ;; :builtin/icon
|
||||||
|
[own shape]
|
||||||
|
(let [{:keys [id x y width height group]} shape
|
||||||
|
selected (rum/react uusc/selected-shapes-l)
|
||||||
|
selected? (contains? selected id)
|
||||||
|
on-mouse-down #(on-mouse-down % shape selected)
|
||||||
|
on-mouse-up #(on-mouse-up % shape)]
|
||||||
|
(html
|
||||||
|
[:g.shape {:class (when selected? "selected")
|
||||||
|
:on-mouse-down on-mouse-down
|
||||||
|
:on-mouse-up on-mouse-up}
|
||||||
|
(uusc/render-shape shape #(uusc/shape %))
|
||||||
|
(when selected?
|
||||||
|
(handlers shape))])))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Icon Handlers
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defn- handlers-render
|
||||||
|
[own shape]
|
||||||
|
(let [{:keys [x y width height]} (sh/-outer-rect shape)]
|
||||||
|
(html
|
||||||
|
[:g.controls
|
||||||
|
[:rect {:x x :y y :width width :height height :stroke-dasharray "5,5"
|
||||||
|
:style {:stroke "#333" :fill "transparent"
|
||||||
|
:stroke-opacity "1"}}]
|
||||||
|
[:circle.top-left (merge default-selection-props
|
||||||
|
{:cx x :cy y})]
|
||||||
|
[:circle.top-right (merge default-selection-props
|
||||||
|
{:cx (+ x width) :cy y})]
|
||||||
|
[:circle.bottom-left (merge default-selection-props
|
||||||
|
{:cx x :cy (+ y height)})]
|
||||||
|
[:circle.bottom-right (merge default-selection-props
|
||||||
|
{:cx (+ x width) :cy (+ y height)})]])))
|
||||||
|
|
||||||
|
(def ^:const handlers
|
||||||
|
(mx/component
|
||||||
|
{:render handlers-render
|
||||||
|
:name "handlers"
|
||||||
|
:mixins [mx/static]}))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Shape & Shape Svg
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defmethod uusc/render-shape :builtin/icon
|
||||||
|
[{:keys [data id] :as shape} _]
|
||||||
|
(let [key (str id)
|
||||||
|
rfm (sh/-transformation shape)
|
||||||
|
attrs (merge {:id key :key key :transform (str rfm)}
|
||||||
|
(uusc/extract-style-attrs shape)
|
||||||
|
(uusc/make-debug-attrs shape))]
|
||||||
|
(html
|
||||||
|
[:g attrs data])))
|
||||||
|
|
||||||
|
(defmethod uusc/render-shape-svg :builtin/icon
|
||||||
|
[{:keys [data id view-box] :as shape}]
|
||||||
|
(let [key (str "icon-svg-" id)
|
||||||
|
view-box (apply str (interpose " " view-box))
|
||||||
|
props {:view-box view-box :id key :key key}]
|
||||||
|
(html
|
||||||
|
[:svg props data])))
|
23
src/uxbox/ui/shapes/line.cljs
Normal file
23
src/uxbox/ui/shapes/line.cljs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
(ns uxbox.ui.shapes.line
|
||||||
|
(:require [sablono.core :refer-macros [html]]
|
||||||
|
[cuerdas.core :as str]
|
||||||
|
[rum.core :as rum]
|
||||||
|
[cats.labs.lens :as l]
|
||||||
|
[uxbox.rstore :as rs]
|
||||||
|
[uxbox.state :as st]
|
||||||
|
[uxbox.shapes :as ush]
|
||||||
|
[uxbox.data.workspace :as dw]
|
||||||
|
[uxbox.ui.core :as uuc]
|
||||||
|
[uxbox.ui.keyboard :as kbd]
|
||||||
|
[uxbox.ui.shapes.core :as uusc]
|
||||||
|
[uxbox.util.dom :as dom]))
|
||||||
|
|
||||||
|
(defmethod uusc/render-shape :builtin/line
|
||||||
|
[{:keys [id x1 y1 x2 y2] :as shape}]
|
||||||
|
(let [key (str id)
|
||||||
|
props (select-keys shape [:x1 :x2 :y2 :y1])
|
||||||
|
attrs (-> (uusc/extract-style-attrs shape)
|
||||||
|
(merge {:id key :key key})
|
||||||
|
(merge props))]
|
||||||
|
(html
|
||||||
|
[:line attrs])))
|
25
src/uxbox/ui/shapes/rect.cljs
Normal file
25
src/uxbox/ui/shapes/rect.cljs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
(ns uxbox.ui.shapes.rect
|
||||||
|
(:require [sablono.core :refer-macros [html]]
|
||||||
|
[cuerdas.core :as str]
|
||||||
|
[rum.core :as rum]
|
||||||
|
[cats.labs.lens :as l]
|
||||||
|
[uxbox.rstore :as rs]
|
||||||
|
[uxbox.state :as st]
|
||||||
|
[uxbox.shapes :as ush]
|
||||||
|
[uxbox.data.workspace :as dw]
|
||||||
|
[uxbox.ui.core :as uuc]
|
||||||
|
[uxbox.ui.keyboard :as kbd]
|
||||||
|
[uxbox.ui.shapes.core :as uusc]
|
||||||
|
[uxbox.util.dom :as dom]))
|
||||||
|
|
||||||
|
(defmethod uusc/render-shape :builtin/rect
|
||||||
|
[{:keys [id x1 y1 x2 y2] :as shape}]
|
||||||
|
(let [key (str id)
|
||||||
|
rfm (ush/-transformation shape)
|
||||||
|
size (ush/-size shape)
|
||||||
|
props {:x x1 :y y1 :id key :key key :transform (str rfm)}
|
||||||
|
attrs (-> (uusc/extract-style-attrs shape)
|
||||||
|
(merge props size))]
|
||||||
|
(html
|
||||||
|
[:rect attrs])))
|
||||||
|
|
|
@ -8,9 +8,10 @@
|
||||||
[uxbox.data.workspace :as dw]
|
[uxbox.data.workspace :as dw]
|
||||||
[uxbox.util.geom.point :as gpt]
|
[uxbox.util.geom.point :as gpt]
|
||||||
[uxbox.util.data :refer (classnames)]
|
[uxbox.util.data :refer (classnames)]
|
||||||
|
[uxbox.ui.core :as uuc]
|
||||||
[uxbox.ui.icons :as i]
|
[uxbox.ui.icons :as i]
|
||||||
[uxbox.ui.mixins :as mx]
|
[uxbox.ui.mixins :as mx]
|
||||||
[uxbox.ui.workspace.base :as wb]
|
[uxbox.ui.workspace.base :as uuwb]
|
||||||
[uxbox.ui.workspace.shortcuts :as wshortcuts]
|
[uxbox.ui.workspace.shortcuts :as wshortcuts]
|
||||||
[uxbox.ui.workspace.header :refer (header)]
|
[uxbox.ui.workspace.header :refer (header)]
|
||||||
[uxbox.ui.workspace.rules :refer (horizontal-rule vertical-rule)]
|
[uxbox.ui.workspace.rules :refer (horizontal-rule vertical-rule)]
|
||||||
|
@ -27,7 +28,7 @@
|
||||||
(let [target (.-target event)
|
(let [target (.-target event)
|
||||||
top (.-scrollTop target)
|
top (.-scrollTop target)
|
||||||
left (.-scrollLeft target)]
|
left (.-scrollLeft target)]
|
||||||
(rx/push! wb/scroll-b (gpt/point left top))))
|
(rx/push! uuwb/scroll-b (gpt/point left top))))
|
||||||
|
|
||||||
(defn- on-key-down
|
(defn- on-key-down
|
||||||
[event]
|
[event]
|
||||||
|
@ -39,7 +40,7 @@
|
||||||
|
|
||||||
(defn- workspace-render
|
(defn- workspace-render
|
||||||
[own projectid]
|
[own projectid]
|
||||||
(let [{:keys [flags] :as workspace} (rum/react wb/workspace-l)
|
(let [{:keys [flags] :as workspace} (rum/react uuwb/workspace-l)
|
||||||
left-sidebar? (not (empty? (keep flags [:layers :sitemap :document-history])))
|
left-sidebar? (not (empty? (keep flags [:layers :sitemap :document-history])))
|
||||||
right-sidebar? (not (empty? (keep flags [:icons :drawtools
|
right-sidebar? (not (empty? (keep flags [:icons :drawtools
|
||||||
:element-options])))
|
:element-options])))
|
||||||
|
@ -85,13 +86,13 @@
|
||||||
(defn- workspace-did-mount
|
(defn- workspace-did-mount
|
||||||
[own]
|
[own]
|
||||||
(letfn [(handle-scroll-interaction []
|
(letfn [(handle-scroll-interaction []
|
||||||
(let [stoper (->> wb/interactions-b
|
(let [stoper (->> uuc/actions-s
|
||||||
(rx/filter #(not= % :scroll/viewport))
|
(rx/filter #(not= % :scroll/viewport))
|
||||||
(rx/take 1))
|
(rx/take 1))
|
||||||
local (:rum/local own)
|
local (:rum/local own)
|
||||||
initial @wb/mouse-viewport-a]
|
initial @uuwb/mouse-viewport-a]
|
||||||
(swap! local assoc :scrolling true)
|
(swap! local assoc :scrolling true)
|
||||||
(as-> wb/mouse-viewport-s $
|
(as-> uuwb/mouse-viewport-s $
|
||||||
(rx/take-until stoper $)
|
(rx/take-until stoper $)
|
||||||
(rx/subscribe $ #(on-scroll % initial) nil on-scroll-end))))
|
(rx/subscribe $ #(on-scroll % initial) nil on-scroll-end))))
|
||||||
|
|
||||||
|
@ -108,12 +109,12 @@
|
||||||
(set! (.-scrollTop el) (- cy y))))]
|
(set! (.-scrollTop el) (- cy y))))]
|
||||||
|
|
||||||
(let [el (mx/get-ref-dom own "workspace-canvas")
|
(let [el (mx/get-ref-dom own "workspace-canvas")
|
||||||
sub (as-> wb/interactions-b $
|
sub (as-> uuc/actions-s $
|
||||||
(rx/dedupe $)
|
(rx/dedupe $)
|
||||||
(rx/filter #(= :scroll/viewport %) $)
|
(rx/filter #(= :scroll/viewport %) $)
|
||||||
(rx/on-value $ handle-scroll-interaction))]
|
(rx/on-value $ handle-scroll-interaction))]
|
||||||
(set! (.-scrollLeft el) wb/canvas-start-scroll-x)
|
(set! (.-scrollLeft el) uuwb/canvas-start-scroll-x)
|
||||||
(set! (.-scrollTop el) wb/canvas-start-scroll-y)
|
(set! (.-scrollTop el) uuwb/canvas-start-scroll-y)
|
||||||
(assoc own ::sub sub))))
|
(assoc own ::sub sub))))
|
||||||
|
|
||||||
(defn- workspace-will-unmount
|
(defn- workspace-will-unmount
|
||||||
|
|
|
@ -71,16 +71,6 @@
|
||||||
(defonce scroll-a
|
(defonce scroll-a
|
||||||
(rx/to-atom scroll-s))
|
(rx/to-atom scroll-s))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;; Interactions
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
(defonce interactions-b (rx/bus))
|
|
||||||
|
|
||||||
(defn emit-interaction!
|
|
||||||
[type]
|
|
||||||
(rx/push! interactions-b type))
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Mouse Position Stream
|
;; Mouse Position Stream
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
|
@ -4,21 +4,18 @@
|
||||||
[beicon.core :as rx]
|
[beicon.core :as rx]
|
||||||
[cats.labs.lens :as l]
|
[cats.labs.lens :as l]
|
||||||
[goog.events :as events]
|
[goog.events :as events]
|
||||||
[uxbox.router :as r]
|
|
||||||
[uxbox.rstore :as rs]
|
[uxbox.rstore :as rs]
|
||||||
[uxbox.state :as st]
|
|
||||||
[uxbox.xforms :as xf]
|
|
||||||
[uxbox.shapes :as sh]
|
[uxbox.shapes :as sh]
|
||||||
[uxbox.util.lens :as ul]
|
|
||||||
[uxbox.library.icons :as _icons]
|
|
||||||
[uxbox.data.projects :as dp]
|
[uxbox.data.projects :as dp]
|
||||||
[uxbox.data.workspace :as dw]
|
[uxbox.data.workspace :as dw]
|
||||||
[uxbox.ui.mixins :as mx]
|
|
||||||
[uxbox.util.geom.point :as gpt]
|
[uxbox.util.geom.point :as gpt]
|
||||||
[uxbox.util.dom :as dom]
|
[uxbox.util.dom :as dom]
|
||||||
[uxbox.util.data :refer (parse-int)]
|
[uxbox.util.data :refer (parse-int)]
|
||||||
|
[uxbox.ui.core :as uuc]
|
||||||
[uxbox.ui.keyboard :as kbd]
|
[uxbox.ui.keyboard :as kbd]
|
||||||
[uxbox.ui.workspace.base :as wb]
|
[uxbox.ui.shapes :as uus]
|
||||||
|
[uxbox.ui.mixins :as mx]
|
||||||
|
[uxbox.ui.workspace.base :as uuwb]
|
||||||
[uxbox.ui.workspace.canvas.movement]
|
[uxbox.ui.workspace.canvas.movement]
|
||||||
[uxbox.ui.workspace.canvas.draw :refer (draw-area)]
|
[uxbox.ui.workspace.canvas.draw :refer (draw-area)]
|
||||||
[uxbox.ui.workspace.canvas.ruler :refer (ruler)]
|
[uxbox.ui.workspace.canvas.ruler :refer (ruler)]
|
||||||
|
@ -43,97 +40,27 @@
|
||||||
:name "background"
|
:name "background"
|
||||||
:mixins [mx/static]}))
|
:mixins [mx/static]}))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;; Shape
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
(declare shape)
|
|
||||||
|
|
||||||
(defn shape-render
|
|
||||||
[own item selected]
|
|
||||||
(let [{:keys [id x y width height group] :as item} item
|
|
||||||
selected? (contains? selected id)
|
|
||||||
local (:rum/local own)]
|
|
||||||
(letfn [(on-mouse-down [event]
|
|
||||||
(when-not (:blocked item)
|
|
||||||
(cond
|
|
||||||
(and group (:locked (sh/resolve-parent item)))
|
|
||||||
nil
|
|
||||||
|
|
||||||
(and (not selected?) (empty? selected))
|
|
||||||
(do
|
|
||||||
(dom/stop-propagation event)
|
|
||||||
(swap! local assoc :init-coords [x y])
|
|
||||||
(wb/emit-interaction! :shape/movement)
|
|
||||||
(rs/emit! (dw/select-shape id)))
|
|
||||||
|
|
||||||
(and (not selected?) (not (empty? selected)))
|
|
||||||
(do
|
|
||||||
(dom/stop-propagation event)
|
|
||||||
(swap! local assoc :init-coords [x y])
|
|
||||||
(if (kbd/shift? event)
|
|
||||||
(rs/emit! (dw/select-shape id))
|
|
||||||
(rs/emit! (dw/deselect-all)
|
|
||||||
(dw/select-shape id))))
|
|
||||||
|
|
||||||
:else
|
|
||||||
(do
|
|
||||||
(dom/stop-propagation event)
|
|
||||||
(swap! local assoc :init-coords [x y])
|
|
||||||
(wb/emit-interaction! :shape/movement)))))
|
|
||||||
|
|
||||||
(on-mouse-up [event]
|
|
||||||
(cond
|
|
||||||
(and group (:locked (sh/resolve-parent item)))
|
|
||||||
nil
|
|
||||||
|
|
||||||
:else
|
|
||||||
(do
|
|
||||||
(dom/stop-propagation event)
|
|
||||||
(wb/emit-interaction! :nothing)
|
|
||||||
)))]
|
|
||||||
(html
|
|
||||||
[:g.shape {:class (when selected? "selected")
|
|
||||||
:on-mouse-down on-mouse-down
|
|
||||||
:on-mouse-up on-mouse-up}
|
|
||||||
(sh/-render item #(shape % selected))]))))
|
|
||||||
|
|
||||||
(def ^:static shape
|
|
||||||
(mx/component
|
|
||||||
{:render shape-render
|
|
||||||
:name "shape"
|
|
||||||
:mixins [(mx/local {}) rum/reactive]}))
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Canvas
|
;; Canvas
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(defn- canvas-render
|
(defn- canvas-render
|
||||||
[own {:keys [width height id] :as page}]
|
[own {:keys [width height id] :as page}]
|
||||||
(let [workspace (rum/react wb/workspace-l)
|
(let [workspace (rum/react uuwb/workspace-l)]
|
||||||
shapes-by-id (rum/react wb/shapes-by-id-l)
|
|
||||||
workspace-selected (:selected workspace)
|
|
||||||
xf (comp
|
|
||||||
(map #(get shapes-by-id %))
|
|
||||||
(remove :hidden))
|
|
||||||
shapes (->> (vals shapes-by-id)
|
|
||||||
(filter #(= (:page %) id)))
|
|
||||||
shapes-selected (filter (comp workspace-selected :id) shapes)
|
|
||||||
shapes-notselected (filter (comp not workspace-selected :id) shapes)]
|
|
||||||
(html
|
(html
|
||||||
[:svg.page-canvas {:x wb/canvas-start-x
|
[:svg.page-canvas {:x uuwb/canvas-start-x
|
||||||
:y wb/canvas-start-y
|
:y uuwb/canvas-start-y
|
||||||
:ref (str "canvas" id)
|
:ref (str "canvas" id)
|
||||||
:width width
|
:width width
|
||||||
:height height}
|
:height height}
|
||||||
(background)
|
(background)
|
||||||
(grid 1)
|
(grid 1)
|
||||||
[:svg.page-layout {}
|
[:svg.page-layout {}
|
||||||
(shapes-selection shapes-selected)
|
#_(shapes-selection shapes-selected)
|
||||||
[:g.main {}
|
[:g.main {}
|
||||||
(for [item (reverse (sequence xf (:shapes page)))]
|
(for [item (:shapes page)]
|
||||||
(-> (shape item workspace-selected)
|
(-> (uus/shape item)
|
||||||
(rum/with-key (str (:id item)))))
|
(rum/with-key (str item))))
|
||||||
(draw-area)]]])))
|
(draw-area)]]])))
|
||||||
|
|
||||||
(def canvas
|
(def canvas
|
||||||
|
@ -148,8 +75,8 @@
|
||||||
|
|
||||||
(defn viewport-render
|
(defn viewport-render
|
||||||
[own]
|
[own]
|
||||||
(let [workspace (rum/react wb/workspace-l)
|
(let [workspace (rum/react uuwb/workspace-l)
|
||||||
page (rum/react wb/page-l)
|
page (rum/react uuwb/page-l)
|
||||||
drawing? (:drawing workspace)
|
drawing? (:drawing workspace)
|
||||||
zoom 1]
|
zoom 1]
|
||||||
(letfn [(on-mouse-down [event]
|
(letfn [(on-mouse-down [event]
|
||||||
|
@ -157,14 +84,14 @@
|
||||||
(when-not (empty? (:selected workspace))
|
(when-not (empty? (:selected workspace))
|
||||||
(rs/emit! (dw/deselect-all)))
|
(rs/emit! (dw/deselect-all)))
|
||||||
(if-let [shape (:drawing workspace)]
|
(if-let [shape (:drawing workspace)]
|
||||||
(wb/emit-interaction! :draw/shape)
|
(uuc/emit-action! :draw/shape)
|
||||||
(wb/emit-interaction! :draw/selrect)))
|
(uuc/emit-action! :draw/selrect)))
|
||||||
(on-mouse-up [event]
|
(on-mouse-up [event]
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(wb/emit-interaction! :nothing))]
|
(uuc/emit-action! :nothing))]
|
||||||
(html
|
(html
|
||||||
[:svg.viewport {:width wb/viewport-width
|
[:svg.viewport {:width uuwb/viewport-width
|
||||||
:height wb/viewport-height
|
:height uuwb/viewport-height
|
||||||
:ref "viewport"
|
:ref "viewport"
|
||||||
:class (when drawing? "drawing")
|
:class (when drawing? "drawing")
|
||||||
:on-mouse-down on-mouse-down
|
:on-mouse-down on-mouse-down
|
||||||
|
@ -197,11 +124,11 @@
|
||||||
|
|
||||||
(on-key-down [event]
|
(on-key-down [event]
|
||||||
(when (kbd/space? event)
|
(when (kbd/space? event)
|
||||||
(wb/emit-interaction! :scroll/viewport)))
|
(uuc/emit-action! :scroll/viewport)))
|
||||||
|
|
||||||
(on-key-up [event]
|
(on-key-up [event]
|
||||||
(when (kbd/space? event)
|
(when (kbd/space? event)
|
||||||
(wb/emit-interaction! :nothing)))
|
(uuc/emit-action! :nothing)))
|
||||||
|
|
||||||
(on-mousemove [event]
|
(on-mousemove [event]
|
||||||
(let [wpt (gpt/point (.-clientX event)
|
(let [wpt (gpt/point (.-clientX event)
|
||||||
|
@ -213,7 +140,7 @@
|
||||||
:window-coords wpt
|
:window-coords wpt
|
||||||
:viewport-coords vppt
|
:viewport-coords vppt
|
||||||
:canvas-coords cvpt}]
|
:canvas-coords cvpt}]
|
||||||
(rx/push! wb/mouse-b event)))]
|
(rx/push! uuwb/mouse-b event)))]
|
||||||
|
|
||||||
(let [key1 (events/listen js/document EventType.MOUSEMOVE on-mousemove)
|
(let [key1 (events/listen js/document EventType.MOUSEMOVE on-mousemove)
|
||||||
key2 (events/listen js/document EventType.KEYDOWN on-key-down)
|
key2 (events/listen js/document EventType.KEYDOWN on-key-down)
|
||||||
|
|
|
@ -5,9 +5,10 @@
|
||||||
[beicon.core :as rx]
|
[beicon.core :as rx]
|
||||||
[cats.labs.lens :as l]
|
[cats.labs.lens :as l]
|
||||||
[uxbox.rstore :as rs]
|
[uxbox.rstore :as rs]
|
||||||
[uxbox.state :as st]
|
[uxbox.shapes :as ush]
|
||||||
[uxbox.shapes :as sh]
|
|
||||||
[uxbox.data.workspace :as dw]
|
[uxbox.data.workspace :as dw]
|
||||||
|
[uxbox.ui.core :as uuc]
|
||||||
|
[uxbox.ui.shapes.core :as uusc]
|
||||||
[uxbox.ui.workspace.base :as wb]
|
[uxbox.ui.workspace.base :as wb]
|
||||||
[uxbox.ui.mixins :as mx]
|
[uxbox.ui.mixins :as mx]
|
||||||
[uxbox.util.geom.point :as gpt]
|
[uxbox.util.geom.point :as gpt]
|
||||||
|
@ -25,8 +26,8 @@
|
||||||
(let [shape (rum/react +drawing-shape+)
|
(let [shape (rum/react +drawing-shape+)
|
||||||
position (rum/react +drawing-position+)]
|
position (rum/react +drawing-position+)]
|
||||||
(when shape
|
(when shape
|
||||||
(-> (sh/-resize shape position)
|
(-> (ush/-resize shape position)
|
||||||
(sh/-render identity)))))
|
(uusc/render-shape identity)))))
|
||||||
|
|
||||||
(def ^:static draw-area
|
(def ^:static draw-area
|
||||||
(mx/component
|
(mx/component
|
||||||
|
@ -44,11 +45,11 @@
|
||||||
(define-once :drawing-subscriptions
|
(define-once :drawing-subscriptions
|
||||||
(letfn [(init-shape [shape]
|
(letfn [(init-shape [shape]
|
||||||
(let [{:keys [x y] :as point} @wb/mouse-canvas-a
|
(let [{:keys [x y] :as point} @wb/mouse-canvas-a
|
||||||
shape (sh/-initialize shape {:x1 x :y1 y :x2 x :y2 y})]
|
shape (ush/-initialize shape {:x1 x :y1 y :x2 x :y2 y})]
|
||||||
(reset! +drawing-shape+ shape)
|
(reset! +drawing-shape+ shape)
|
||||||
(reset! +drawing-position+ (assoc point :lock false))
|
(reset! +drawing-position+ (assoc point :lock false))
|
||||||
|
|
||||||
(let [stoper (->> wb/interactions-b
|
(let [stoper (->> uuc/actions-s
|
||||||
(rx/filter #(not= % :shape/movement))
|
(rx/filter #(not= % :shape/movement))
|
||||||
(rx/take 1))]
|
(rx/take 1))]
|
||||||
(as-> wb/mouse-canvas-s $
|
(as-> wb/mouse-canvas-s $
|
||||||
|
@ -62,7 +63,7 @@
|
||||||
(on-complete []
|
(on-complete []
|
||||||
(let [shape @+drawing-shape+
|
(let [shape @+drawing-shape+
|
||||||
shpos @+drawing-position+
|
shpos @+drawing-position+
|
||||||
shape (sh/-resize shape shpos)]
|
shape (ush/-resize shape shpos)]
|
||||||
(rs/emit! (dw/add-shape shape)
|
(rs/emit! (dw/add-shape shape)
|
||||||
(dw/select-for-drawing nil))
|
(dw/select-for-drawing nil))
|
||||||
(reset! +drawing-position+ nil)
|
(reset! +drawing-position+ nil)
|
||||||
|
@ -71,7 +72,7 @@
|
||||||
(init-icon [shape]
|
(init-icon [shape]
|
||||||
(let [{:keys [x y]} @wb/mouse-canvas-a
|
(let [{:keys [x y]} @wb/mouse-canvas-a
|
||||||
props {:x1 x :y1 y :x2 (+ x 100) :y2 (+ y 100)}
|
props {:x1 x :y1 y :x2 (+ x 100) :y2 (+ y 100)}
|
||||||
shape (sh/-initialize shape props)]
|
shape (ush/-initialize shape props)]
|
||||||
(rs/emit! (dw/add-shape shape)
|
(rs/emit! (dw/add-shape shape)
|
||||||
(dw/select-for-drawing nil))))
|
(dw/select-for-drawing nil))))
|
||||||
(init []
|
(init []
|
||||||
|
@ -82,7 +83,7 @@
|
||||||
:builtin/circle (init-shape shape)
|
:builtin/circle (init-shape shape)
|
||||||
:builtin/line (init-shape shape))))]
|
:builtin/line (init-shape shape))))]
|
||||||
|
|
||||||
(as-> wb/interactions-b $
|
(as-> uuc/actions-s $
|
||||||
(rx/dedupe $)
|
(rx/dedupe $)
|
||||||
(rx/filter #(= :draw/shape %) $)
|
(rx/filter #(= :draw/shape %) $)
|
||||||
(rx/on-value $ init))))
|
(rx/on-value $ init))))
|
||||||
|
|
|
@ -3,28 +3,29 @@
|
||||||
(:require [beicon.core :as rx]
|
(:require [beicon.core :as rx]
|
||||||
[cats.labs.lens :as l]
|
[cats.labs.lens :as l]
|
||||||
[uxbox.rstore :as rs]
|
[uxbox.rstore :as rs]
|
||||||
[uxbox.state :as st]
|
[uxbox.state :as ust]
|
||||||
[uxbox.ui.workspace.base :as wb]
|
[uxbox.ui.core :as uuc]
|
||||||
|
[uxbox.ui.workspace.base :as uuwb]
|
||||||
[uxbox.data.workspace :as dw]))
|
[uxbox.data.workspace :as dw]))
|
||||||
|
|
||||||
(define-once :movement-subscription
|
(define-once :movement-subscription
|
||||||
(letfn [(on-value [delta]
|
(letfn [(on-value [delta]
|
||||||
(let [pageid (get-in @st/state [:workspace :page])
|
(let [pageid (get-in @ust/state [:workspace :page])
|
||||||
selected (get-in @st/state [:workspace :selected])
|
selected (get-in @ust/state [:workspace :selected])
|
||||||
shapes (->> (vals @wb/shapes-by-id-l)
|
shapes (->> (vals @uuwb/shapes-by-id-l)
|
||||||
(filter #(= (:page %) pageid))
|
(filter #(= (:page %) pageid))
|
||||||
(filter (comp selected :id)))]
|
(filter (comp selected :id)))]
|
||||||
(doseq [{:keys [id group]} shapes]
|
(doseq [{:keys [id group]} shapes]
|
||||||
(rs/emit! (dw/move-shape id delta)))))
|
(rs/emit! (dw/move-shape id delta)))))
|
||||||
|
|
||||||
(init []
|
(init []
|
||||||
(as-> wb/interactions-b $
|
(as-> uuc/actions-s $
|
||||||
(rx/filter #(not= % :shape/movement) $)
|
(rx/filter #(not= % :shape/movement) $)
|
||||||
(rx/take 1 $)
|
(rx/take 1 $)
|
||||||
(rx/take-until $ wb/mouse-delta-s)
|
(rx/take-until $ uuwb/mouse-delta-s)
|
||||||
(rx/on-value $ on-value)))]
|
(rx/on-value $ on-value)))]
|
||||||
|
|
||||||
(as-> wb/interactions-b $
|
(as-> uuc/actions-s $
|
||||||
(rx/dedupe $)
|
(rx/dedupe $)
|
||||||
(rx/filter #(= :shape/movement %) $)
|
(rx/filter #(= :shape/movement %) $)
|
||||||
(rx/on-value $ init))))
|
(rx/on-value $ init))))
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
[uxbox.state :as st]
|
[uxbox.state :as st]
|
||||||
[uxbox.shapes :as sh]
|
[uxbox.shapes :as sh]
|
||||||
[uxbox.data.workspace :as dw]
|
[uxbox.data.workspace :as dw]
|
||||||
|
[uxbox.ui.core :as uuc]
|
||||||
[uxbox.ui.workspace.base :as wb]
|
[uxbox.ui.workspace.base :as wb]
|
||||||
[uxbox.ui.mixins :as mx]
|
[uxbox.ui.mixins :as mx]
|
||||||
[uxbox.util.geom.point :as gpt]
|
[uxbox.util.geom.point :as gpt]
|
||||||
|
@ -74,7 +75,7 @@
|
||||||
(reset! selrect-pos nil)))
|
(reset! selrect-pos nil)))
|
||||||
|
|
||||||
(init []
|
(init []
|
||||||
(let [stoper (->> wb/interactions-b
|
(let [stoper (->> uuc/actions-s
|
||||||
(rx/filter #(not= % :draw/selrect))
|
(rx/filter #(not= % :draw/selrect))
|
||||||
(rx/take 1))
|
(rx/take 1))
|
||||||
pos @wb/mouse-viewport-a]
|
pos @wb/mouse-viewport-a]
|
||||||
|
@ -84,7 +85,7 @@
|
||||||
(rx/take-until stoper $)
|
(rx/take-until stoper $)
|
||||||
(rx/subscribe $ on-value nil on-complete))))]
|
(rx/subscribe $ on-value nil on-complete))))]
|
||||||
|
|
||||||
(as-> wb/interactions-b $
|
(as-> uuc/actions-s $
|
||||||
(rx/dedupe $)
|
(rx/dedupe $)
|
||||||
(rx/filter #(= :draw/selrect %) $)
|
(rx/filter #(= :draw/selrect %) $)
|
||||||
(rx/on-value $ init))))
|
(rx/on-value $ init))))
|
||||||
|
|
|
@ -5,20 +5,20 @@
|
||||||
[uxbox.router :as r]
|
[uxbox.router :as r]
|
||||||
[uxbox.rstore :as rs]
|
[uxbox.rstore :as rs]
|
||||||
[uxbox.state :as st]
|
[uxbox.state :as st]
|
||||||
[uxbox.shapes :as shapes]
|
|
||||||
[uxbox.library :as library]
|
[uxbox.library :as library]
|
||||||
[uxbox.util.data :refer (read-string)]
|
|
||||||
[uxbox.data.workspace :as dw]
|
[uxbox.data.workspace :as dw]
|
||||||
|
[uxbox.ui.shapes.core :as uusc]
|
||||||
[uxbox.ui.workspace.base :as wb]
|
[uxbox.ui.workspace.base :as wb]
|
||||||
[uxbox.ui.icons :as i]
|
[uxbox.ui.icons :as i]
|
||||||
[uxbox.ui.mixins :as mx]
|
[uxbox.ui.mixins :as mx]
|
||||||
[uxbox.util.dom :as dom]))
|
[uxbox.util.dom :as dom]
|
||||||
|
[uxbox.util.data :refer (read-string)]))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Lenses
|
;; Lenses
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(def ^:private ^:static drawing-shape
|
(def ^:private ^:const drawing-shape
|
||||||
"A focused vision of the drawing property
|
"A focused vision of the drawing property
|
||||||
of the workspace status. This avoids
|
of the workspace status. This avoids
|
||||||
rerender the whole toolbox on each workspace
|
rerender the whole toolbox on each workspace
|
||||||
|
@ -45,7 +45,7 @@
|
||||||
|
|
||||||
(defn- icon-wrapper-render
|
(defn- icon-wrapper-render
|
||||||
[own icon]
|
[own icon]
|
||||||
(shapes/-render-svg icon nil))
|
(uusc/render-shape-svg icon nil))
|
||||||
|
|
||||||
(def ^:static ^:private icon-wrapper
|
(def ^:static ^:private icon-wrapper
|
||||||
(mx/component
|
(mx/component
|
||||||
|
|
|
@ -7,10 +7,10 @@
|
||||||
[uxbox.router :as r]
|
[uxbox.router :as r]
|
||||||
[uxbox.rstore :as rs]
|
[uxbox.rstore :as rs]
|
||||||
[uxbox.state :as st]
|
[uxbox.state :as st]
|
||||||
[uxbox.shapes :as shapes]
|
|
||||||
[uxbox.library :as library]
|
[uxbox.library :as library]
|
||||||
[uxbox.util.data :refer (read-string classnames)]
|
[uxbox.util.data :refer (read-string classnames)]
|
||||||
[uxbox.data.workspace :as dw]
|
[uxbox.data.workspace :as dw]
|
||||||
|
[uxbox.ui.shapes.core :as uusc]
|
||||||
[uxbox.ui.workspace.base :as wb]
|
[uxbox.ui.workspace.base :as wb]
|
||||||
[uxbox.ui.icons :as i]
|
[uxbox.ui.icons :as i]
|
||||||
[uxbox.ui.mixins :as mx]
|
[uxbox.ui.mixins :as mx]
|
||||||
|
@ -86,7 +86,7 @@
|
||||||
(defn- element-icon
|
(defn- element-icon
|
||||||
[item]
|
[item]
|
||||||
(case (:type item)
|
(case (:type item)
|
||||||
:builtin/icon (shapes/-render-svg item)
|
:builtin/icon (uusc/render-shape-svg item)
|
||||||
:builtin/line i/line
|
:builtin/line i/line
|
||||||
:builtin/circle i/circle
|
:builtin/circle i/circle
|
||||||
:builtin/rect i/box
|
:builtin/rect i/box
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue