2015-12-28 11:28:01 +02:00
|
|
|
(ns uxbox.ui.workspace.canvas
|
|
|
|
(:require [sablono.core :as html :refer-macros [html]]
|
|
|
|
[rum.core :as rum]
|
2015-12-28 20:06:59 +02:00
|
|
|
[beicon.core :as rx]
|
2015-12-28 11:28:01 +02:00
|
|
|
[uxbox.router :as r]
|
|
|
|
[uxbox.rstore :as rs]
|
|
|
|
[uxbox.state :as s]
|
|
|
|
[uxbox.shapes :as shapes]
|
|
|
|
[uxbox.library.icons :as _icons]
|
2015-12-28 20:06:59 +02:00
|
|
|
[uxbox.data.projects :as dp]
|
2015-12-28 20:40:02 +02:00
|
|
|
[uxbox.data.workspace :as dw]
|
2015-12-28 11:28:01 +02:00
|
|
|
[uxbox.ui.mixins :as mx]
|
2015-12-28 20:06:59 +02:00
|
|
|
[uxbox.ui.dom :as dom]
|
2015-12-28 11:28:01 +02:00
|
|
|
[uxbox.ui.util :as util]
|
|
|
|
[uxbox.ui.workspace.base :as wb]
|
|
|
|
[uxbox.ui.workspace.rules :as wr]
|
|
|
|
[uxbox.ui.workspace.toolboxes :as toolboxes]))
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; Background
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
|
|
(defn background-render
|
|
|
|
[]
|
|
|
|
(html
|
|
|
|
[:rect
|
|
|
|
{:x 0 :y 0 :width "100%" :height "100%" :fill "white"}]))
|
|
|
|
|
|
|
|
(def background
|
|
|
|
(util/component
|
|
|
|
{:render background-render
|
|
|
|
:name "background"
|
|
|
|
:mixins [mx/static]}))
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; Shape
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
|
|
(def ^:private
|
|
|
|
selection-circle-style
|
|
|
|
{:fillOpacity "0.5"
|
|
|
|
:strokeWidth "1px"
|
|
|
|
:vectorEffect "non-scaling-stroke"
|
|
|
|
:cursor "move"})
|
|
|
|
|
|
|
|
(def ^:private
|
|
|
|
default-selection-props
|
|
|
|
{:r 4 :style selection-circle-style
|
|
|
|
:fill "lavender"
|
|
|
|
:stroke "gray"})
|
|
|
|
|
|
|
|
(defn- shape-render
|
2015-12-28 20:40:02 +02:00
|
|
|
[own {:keys [id x y width height] :as shape}]
|
|
|
|
(let [local (:rum/local own)
|
|
|
|
selected (rum/react wb/selected-state)]
|
2015-12-28 20:06:59 +02:00
|
|
|
(html
|
|
|
|
[:g {
|
|
|
|
:on-mouse-down
|
|
|
|
(fn [event]
|
2015-12-28 21:05:52 +02:00
|
|
|
(dom/stop-propagation event)
|
2015-12-28 20:40:02 +02:00
|
|
|
(swap! local assoc :init-coords [x y])
|
2015-12-28 21:05:52 +02:00
|
|
|
(reset! wb/shapes-dragging? true))
|
2015-12-28 20:06:59 +02:00
|
|
|
|
2015-12-28 20:40:02 +02:00
|
|
|
:on-click
|
2015-12-28 21:05:52 +02:00
|
|
|
(fn [event]
|
2015-12-28 20:40:02 +02:00
|
|
|
(when (= (:init-coords @local) [x y])
|
2015-12-28 21:05:52 +02:00
|
|
|
(if (.-ctrlKey event)
|
|
|
|
(rs/emit! (dw/select-shape id))
|
|
|
|
(rs/emit! (dw/deselect-all)
|
|
|
|
(dw/select-shape id)))))
|
2015-12-28 20:06:59 +02:00
|
|
|
|
|
|
|
:on-mouse-up
|
|
|
|
(fn [event]
|
2015-12-28 21:05:52 +02:00
|
|
|
(dom/stop-propagation event)
|
|
|
|
(reset! wb/shapes-dragging? false))
|
2015-12-28 20:06:59 +02:00
|
|
|
}
|
2015-12-28 20:40:02 +02:00
|
|
|
(shapes/render shape)
|
|
|
|
(if (contains? selected id)
|
|
|
|
[:g {:class "controls"}
|
|
|
|
[:rect {:x x :y y :width width :height height
|
|
|
|
:style {:stroke "black" :fill "transparent"
|
|
|
|
:stroke-opacity "0.5"}}]
|
|
|
|
[:circle (merge default-selection-props
|
|
|
|
{:cx x :cy y})]
|
|
|
|
[:circle (merge default-selection-props
|
|
|
|
{:cx (+ x width) :cy y})]
|
|
|
|
[:circle (merge default-selection-props
|
|
|
|
{:cx x :cy (+ y height)})]
|
|
|
|
[:circle (merge default-selection-props
|
|
|
|
{:cx (+ x width) :cy (+ y height)})]])])))
|
|
|
|
|
2015-12-28 14:31:57 +02:00
|
|
|
|
|
|
|
;; (defn- shape-render
|
|
|
|
;; [own shape]
|
|
|
|
;; (let [local (:rum/local own)
|
|
|
|
;; x 30
|
|
|
|
;; y 30
|
|
|
|
;; width 100
|
|
|
|
;; height 100]
|
|
|
|
;; (html
|
|
|
|
;; [:g
|
|
|
|
;; (shapes/render shape {:x x :y y :width width :height height})
|
|
|
|
;; [:g {:class "controls"}
|
|
|
|
;; [:rect {:x x :y y :width width :height height
|
|
|
|
;; :style {:stroke "black" :fill "transparent"
|
|
|
|
;; :stroke-opacity "0.5"}}]
|
|
|
|
;; [:circle (merge default-selection-props
|
|
|
|
;; {:cx x :cy y})]
|
|
|
|
;; [:circle (merge default-selection-props
|
|
|
|
;; {:cx (+ x width) :cy y})]
|
|
|
|
;; [:circle (merge default-selection-props
|
|
|
|
;; {:cx x :cy (+ y height)})]
|
|
|
|
;; [:circle (merge default-selection-props
|
|
|
|
;; {:cx (+ x width) :cy (+ y height)})]]])))
|
2015-12-28 11:28:01 +02:00
|
|
|
|
|
|
|
(def shape
|
|
|
|
(util/component
|
|
|
|
{:render shape-render
|
|
|
|
:name "shape"
|
2015-12-28 20:40:02 +02:00
|
|
|
:mixins [mx/static rum/reactive (mx/local {})]}))
|
2015-12-28 11:28:01 +02:00
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; Canvas
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
|
|
(defn canvas-render
|
|
|
|
[]
|
|
|
|
(let [page (rum/react wb/page-state)
|
|
|
|
page-width (:width page)
|
2015-12-28 20:40:20 +02:00
|
|
|
page-height (:height page)]
|
2015-12-28 11:28:01 +02:00
|
|
|
(html
|
2015-12-28 14:31:17 +02:00
|
|
|
[:svg.page-canvas
|
2015-12-28 11:28:01 +02:00
|
|
|
{:x wb/document-start-x
|
|
|
|
:y wb/document-start-y
|
|
|
|
:ref "canvas"
|
|
|
|
:width page-width
|
|
|
|
:height page-height
|
2015-12-28 21:05:52 +02:00
|
|
|
|
|
|
|
:on-mouse-down
|
|
|
|
(fn [event]
|
|
|
|
(dom/stop-propagation event)
|
|
|
|
(rs/emit! (dw/deselect-all)))
|
|
|
|
|
2015-12-28 20:06:59 +02:00
|
|
|
:on-mouse-up
|
|
|
|
(fn [event]
|
2015-12-28 21:05:52 +02:00
|
|
|
(dom/stop-propagation event)
|
|
|
|
(reset! wb/shapes-dragging? false))
|
2015-12-28 11:28:01 +02:00
|
|
|
}
|
|
|
|
(background)
|
2015-12-28 20:06:59 +02:00
|
|
|
[:svg.page-layout {}
|
|
|
|
(for [shapeid (:shapes page)
|
|
|
|
:let [item (get-in page [:shapes-by-id shapeid])]]
|
2015-12-28 20:40:20 +02:00
|
|
|
(rum/with-key (shape item) (str shapeid)))]])))
|
2015-12-28 11:28:01 +02:00
|
|
|
|
|
|
|
(def canvas
|
|
|
|
(util/component
|
|
|
|
{:render canvas-render
|
|
|
|
:name "canvas"
|
|
|
|
:mixins [rum/reactive wb/mouse-mixin]}))
|
|
|
|
|