mirror of
https://github.com/penpot/penpot.git
synced 2025-04-05 03:21:26 -05:00
Adapt the application to use the new point abstraction.
This commit is contained in:
parent
b102c19ea7
commit
5d5b84a0a1
9 changed files with 126 additions and 105 deletions
|
@ -10,6 +10,7 @@
|
|||
[uxbox.time :as time]
|
||||
[uxbox.xforms :as xf]
|
||||
[uxbox.shapes :as sh]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.data :refer (index-of)]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -156,7 +157,8 @@
|
|||
|
||||
(defn move-shape
|
||||
"Mark a shape selected for drawing in the canvas."
|
||||
[sid [dx dy :as delta]]
|
||||
[sid delta]
|
||||
{:pre [(gpt/point? delta)]}
|
||||
(reify
|
||||
rs/UpdateEvent
|
||||
(-apply-update [_ state]
|
||||
|
|
|
@ -116,14 +116,16 @@
|
|||
;; Resize
|
||||
|
||||
(defmethod -resize :builtin/line
|
||||
[shape {:keys [x2 y2] :as pos}]
|
||||
[shape {:keys [x y] :as pos}]
|
||||
(assoc shape
|
||||
:x2 x2 :y2 y2))
|
||||
:x2 x :y2 x))
|
||||
|
||||
(defmethod -resize :builtin/circle
|
||||
[{:keys [cx cy rx ry] :as shape} {:keys [x2 y2 lock] :as pos}]
|
||||
[{:keys [cx cy rx ry] :as shape} {:keys [x y lock] :as pos}]
|
||||
(let [x1 (- cx rx)
|
||||
y1 (- cy ry)
|
||||
x2 x
|
||||
y2 y
|
||||
|
||||
width (- x2 x1)
|
||||
height (if lock
|
||||
|
@ -140,15 +142,14 @@
|
|||
(assoc shape :rx rx :ry ry :cx cx :cy cy))))
|
||||
|
||||
(defmethod -resize :builtin/rect
|
||||
[shape {:keys [x2 y2 lock] :as pos}]
|
||||
(let [{:keys [x y]} shape]
|
||||
(if lock
|
||||
(assoc shape
|
||||
:width (- x2 x)
|
||||
:height (- x2 x))
|
||||
(assoc shape
|
||||
:width (- x2 x)
|
||||
:height (- y2 y)))))
|
||||
[shape {:keys [x y lock] :as pos}]
|
||||
(if lock
|
||||
(assoc shape
|
||||
:width (- x (:x shape))
|
||||
:height (- x (:x shape)))
|
||||
(assoc shape
|
||||
:width (- x (:x shape))
|
||||
:height (- y (:y shape)))))
|
||||
|
||||
(defmethod -resize :default
|
||||
[shape _]
|
||||
|
@ -167,19 +168,19 @@
|
|||
;; Move
|
||||
|
||||
(defmethod -move ::rect
|
||||
[shape [dx dy]]
|
||||
[shape {dx :x dy :y}]
|
||||
(assoc shape
|
||||
:x (+ (:x shape) dx)
|
||||
:y (+ (:y shape) dy)))
|
||||
|
||||
(defmethod -move :builtin/group
|
||||
[shape [dx dy]]
|
||||
[shape {dx :x dy :y}]
|
||||
(assoc shape
|
||||
:dx (+ (:dx shape 0) dx)
|
||||
:dy (+ (:dy shape 0) dy)))
|
||||
|
||||
(defmethod -move :builtin/line
|
||||
[shape [dx dy]]
|
||||
[shape {dx :x dy :y}]
|
||||
(assoc shape
|
||||
:x1 (+ (:x1 shape) dx)
|
||||
:y1 (+ (:y1 shape) dy)
|
||||
|
@ -187,7 +188,7 @@
|
|||
:y2 (+ (:y2 shape) dy)))
|
||||
|
||||
(defmethod -move :builtin/circle
|
||||
[shape [dx dy]]
|
||||
[shape {dx :x dy :y}]
|
||||
(assoc shape
|
||||
:cx (+ (:cx shape) dx)
|
||||
:cy (+ (:cy shape) dy)))
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
(defn- coordenates-render
|
||||
[own]
|
||||
(let [[x y] (rum/react wb/mouse-position)]
|
||||
(let [{:keys [x y]} (rum/react wb/mouse-position)]
|
||||
(html
|
||||
[:div {:style {:position "absolute" :left "80px" :top "20px"}}
|
||||
[:table
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
[uxbox.state :as st]
|
||||
[uxbox.data.projects :as dp]
|
||||
[uxbox.data.workspace :as dw]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.lens :as ul]
|
||||
[goog.events :as events])
|
||||
(:import goog.events.EventType))
|
||||
|
@ -51,25 +52,15 @@
|
|||
;; Scroll Stream
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defonce ^:private scroll-b (rx/bus))
|
||||
(defonce scroll-b (rx/bus))
|
||||
|
||||
(defonce scroll-s
|
||||
(as-> scroll-b $
|
||||
(rx/merge $ (rx/of {:top 0 :left 0}))
|
||||
(rx/merge $ (rx/of (gpt/point)))
|
||||
(rx/dedupe $)))
|
||||
|
||||
(defonce scroll-top-s
|
||||
(->> scroll-s
|
||||
(rx/map :top)
|
||||
(rx/dedupe)))
|
||||
|
||||
(defonce scroll-left-s
|
||||
(->> scroll-s
|
||||
(rx/map :left)
|
||||
(rx/dedupe)))
|
||||
|
||||
(defonce scroll-top (rx/to-atom scroll-top-s))
|
||||
(defonce scroll-left (rx/to-atom scroll-left-s))
|
||||
(defonce scroll
|
||||
(rx/to-atom scroll-s))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Interactions
|
||||
|
@ -107,10 +98,7 @@
|
|||
|
||||
(defn- coords-delta
|
||||
[[old new]]
|
||||
(let [[oldx oldy] old
|
||||
[newx newy] new]
|
||||
[(- newx oldx)
|
||||
(- newy oldy)]))
|
||||
(gpt/subtract new old))
|
||||
|
||||
(defonce mouse-delta-s
|
||||
(->> mouse-s
|
||||
|
@ -135,4 +123,3 @@
|
|||
|
||||
(def document-start-x 50)
|
||||
(def document-start-y 50)
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
[uxbox.data.projects :as dp]
|
||||
[uxbox.data.workspace :as dw]
|
||||
[uxbox.ui.mixins :as mx]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.ui.keyboard :as kbd]
|
||||
[uxbox.ui.workspace.base :as wb]
|
||||
|
@ -109,19 +110,19 @@
|
|||
|
||||
(defn- canvas-did-mount
|
||||
[own]
|
||||
(letfn [(on-mousemove [event page [offset-x offset-y]]
|
||||
(let [x (.-clientX event)
|
||||
y (.-clientY event)
|
||||
(letfn [(on-mousemove [event page offset-pt]
|
||||
(let [wpt (gpt/point (.-clientX event) (.-clientY event))
|
||||
cpt (gpt/subtract wpt offset-pt)
|
||||
event {:id (:id page)
|
||||
:ctrl (kbd/ctrl? event)
|
||||
:window-coords [x y]
|
||||
:canvas-coords [(- x offset-x)
|
||||
(- y offset-y)]}]
|
||||
:shift (kbd/shift? event)
|
||||
:window-coords wpt
|
||||
:canvas-coords cpt}]
|
||||
(rx/push! wb/mouse-b event)))]
|
||||
(let [[page] (:rum/props own)
|
||||
canvas (mx/get-ref-dom own (str "canvas" (:id page)))
|
||||
brect (.getBoundingClientRect canvas)
|
||||
brect [(.-left brect) (.-top brect)]
|
||||
brect (gpt/point (.-left brect) (.-top brect))
|
||||
key (events/listen js/document EventType.MOUSEMOVE
|
||||
#(on-mousemove % page brect))]
|
||||
(swap! wb/bounding-rect assoc (:id page) brect)
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
[uxbox.data.workspace :as dw]
|
||||
[uxbox.ui.workspace.base :as wb]
|
||||
[uxbox.ui.mixins :as mx]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.dom :as dom]))
|
||||
|
||||
(defonce +drawing-shape+ (atom nil))
|
||||
|
@ -37,13 +38,13 @@
|
|||
;; Subscriptions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; FIXME: this works for now, but should be refactored when advanced rendering
|
||||
;; is introduced such as polyline, polygon and path.
|
||||
|
||||
(define-once :drawing-subscriptions
|
||||
(letfn [(init-shape [shape]
|
||||
(let [[x y :as mpos] @wb/mouse-position
|
||||
stop @wb/scroll-top
|
||||
y (+ stop y)
|
||||
(let [{:keys [x y]} (gpt/subtract @wb/mouse-position @wb/scroll)
|
||||
shape (sh/-initialize shape {:x1 x :y1 y :x2 x :y2 y})]
|
||||
|
||||
(reset! +drawing-shape+ shape)
|
||||
(reset! +drawing-position+ {:x2 x :y2 y :lock false})
|
||||
|
||||
|
@ -54,10 +55,9 @@
|
|||
(rx/with-latest-from vector wb/mouse-ctrl-s $)
|
||||
(rx/subscribe $ on-value nil on-complete))))
|
||||
|
||||
(on-value [[[x y :as pos] ctrl?]]
|
||||
(let [stop @wb/scroll-top]
|
||||
(reset! +drawing-position+
|
||||
{:x2 x :y2 (+ y stop) :lock ctrl?})))
|
||||
(on-value [[pos ctrl?]]
|
||||
(let [{:keys [x y] :as pos} (gpt/subtract pos @wb/scroll)]
|
||||
(reset! +drawing-position+ {:x2 x :y2 y :lock ctrl?})))
|
||||
|
||||
(on-complete []
|
||||
(let [shape @+drawing-shape+
|
||||
|
@ -69,9 +69,7 @@
|
|||
(reset! +drawing-shape+ nil)))
|
||||
|
||||
(init-icon [shape]
|
||||
(let [[x y] @wb/mouse-position
|
||||
stop @wb/scroll-top
|
||||
y (+ stop y)
|
||||
(let [{:keys [x y]} (gpt/subtract @wb/mouse-position @wb/scroll)
|
||||
props {:x1 x :y1 y :x2 (+ x 100) :y2 (+ y 100)}
|
||||
shape (sh/-initialize shape props)]
|
||||
(rs/emit! (dw/add-shape shape)
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
[uxbox.util.math :as mth]
|
||||
[uxbox.ui.workspace.base :as wb]
|
||||
[uxbox.ui.mixins :as mx]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.dom :as dom]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -18,17 +19,17 @@
|
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn- resolve-position
|
||||
[own [x y]]
|
||||
[own pt]
|
||||
(let [overlay (mx/get-ref-dom own "overlay")
|
||||
brect (.getBoundingClientRect overlay)]
|
||||
[(- x (.-left brect))
|
||||
(- y (.-top brect))]))
|
||||
brect (.getBoundingClientRect overlay)
|
||||
bpt (gpt/point (.-left brect) (.-top brect))]
|
||||
(gpt/subtract pt bpt)))
|
||||
|
||||
(defn- get-position
|
||||
[own event]
|
||||
(let [x (.-clientX event)
|
||||
y (.-clientY event)]
|
||||
(resolve-position own [x y])))
|
||||
(->> (gpt/point (.-clientX event)
|
||||
(.-clientY event))
|
||||
(resolve-position own)))
|
||||
|
||||
(defn- on-mouse-down
|
||||
[own local event]
|
||||
|
@ -41,41 +42,77 @@
|
|||
(dom/stop-propagation event)
|
||||
(swap! local assoc :active false))
|
||||
|
||||
(defn- overlay-line-render
|
||||
[own center pt]
|
||||
(let [distance (-> (gpt/distance pt center)
|
||||
(mth/precision 4))
|
||||
angle (-> (gpt/angle pt center)
|
||||
(mth/precision 4))
|
||||
{x1 :x y1 :y} center
|
||||
{x2 :x y2 :y} pt]
|
||||
(html
|
||||
[:g
|
||||
[:line {:x1 x1 :y1 y1
|
||||
:x2 x2 :y2 y2
|
||||
:style {:cursor "cell"}
|
||||
:stroke-width "2"
|
||||
:stroke "red"}]
|
||||
[:text
|
||||
{:transform (str "translate(" (+ x2 15) "," (- y2 10) ")")}
|
||||
[:tspan {:x "0" :dy="1.2em"}
|
||||
(str "distance=" distance)]
|
||||
[:tspan {:x "0" :y "20" :dy="1.2em"}
|
||||
(str "angle=" angle)]]])))
|
||||
|
||||
(defn- overlay-render
|
||||
[own local]
|
||||
(let [[x1 y1 :as p1] (:pos1 @local)
|
||||
[x2 y2 :as p2] (:pos2 @local)
|
||||
distance (mth/distance p1 p2)]
|
||||
(let [p1 (:pos1 @local)
|
||||
p2 (:pos2 @local)]
|
||||
(html
|
||||
[:svg {:on-mouse-down #(on-mouse-down own local %)
|
||||
:on-mouse-up #(on-mouse-up own local %)
|
||||
:ref "overlay"}
|
||||
[:rect {:style {:fill "transparent" :stroke "transparent" :cursor "cell"}
|
||||
[:rect {:style {:fill "transparent"
|
||||
:stroke "transparent"
|
||||
:cursor "cell"}
|
||||
:width wb/viewport-width
|
||||
:height wb/viewport-height}]
|
||||
(if (and x1 x2)
|
||||
[:g
|
||||
[:line {:x1 x1 :y1 y1 :x2 x2 :y2 y2
|
||||
:style {:cursor "cell"}
|
||||
:stroke-width "2"
|
||||
:stroke "red"}]
|
||||
[:text {:x (+ x2 15) :y y2}
|
||||
[:tspan (str distance)]]])])))
|
||||
(if (and p1 p2)
|
||||
(overlay-line-render own p1 p2))])))
|
||||
|
||||
(def ^:private ^:static +immanted-zones+
|
||||
(let [transform #(vector (- % 7) (+ % 7) %)]
|
||||
(concat
|
||||
(mapv transform (range 0 181 10))
|
||||
(mapv (comp transform -) (range 0 181 10)))))
|
||||
|
||||
(defn- overlay-will-mount
|
||||
[own local]
|
||||
(letfn [(on-value [[[x y :as pos] ctrl?]]
|
||||
(letfn [(align-position [angle pos]
|
||||
(reduce (fn [pos [a1 a2 v]]
|
||||
(if (< a1 angle a2)
|
||||
(reduced (gpt/update-angle pos v))
|
||||
pos))
|
||||
pos
|
||||
+immanted-zones+))
|
||||
|
||||
(on-value-aligned [pos2]
|
||||
(let [center (:pos1 @local)]
|
||||
(as-> pos2 $
|
||||
(gpt/subtract $ center)
|
||||
(align-position (gpt/angle $) $)
|
||||
(gpt/add $ center)
|
||||
(swap! local assoc :pos2 $))))
|
||||
|
||||
(on-value-simple [pos2]
|
||||
(swap! local assoc :pos2 pos2))
|
||||
|
||||
(on-value [[pos ctrl?]]
|
||||
(if ctrl?
|
||||
(let [[sx sy] (:pos1 @local)
|
||||
dx (mth/abs (- x sx))
|
||||
dy (mth/abs (- y sy))]
|
||||
(cond
|
||||
(> dx dy) (swap! local assoc :pos2 [x sy])
|
||||
(> dy dx) (swap! local assoc :pos2 [sx y])
|
||||
:else (swap! local assoc :pos2 pos)))
|
||||
(swap! local assoc :pos2 pos)))]
|
||||
(on-value-aligned pos)
|
||||
(on-value-simple pos)))]
|
||||
|
||||
(as-> wb/mouse-absolute-s $
|
||||
(rx/dedupe $)
|
||||
(rx/filter #(:active @local) $)
|
||||
(rx/map #(resolve-position own %) $)
|
||||
(rx/with-latest-from vector wb/mouse-ctrl-s $)
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
[uxbox.data.workspace :as dw]
|
||||
[uxbox.ui.workspace.base :as wb]
|
||||
[uxbox.ui.mixins :as mx]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.dom :as dom]))
|
||||
|
||||
(defonce selrect-pos (atom nil))
|
||||
|
@ -46,10 +47,10 @@
|
|||
[data]
|
||||
(let [start (:start data)
|
||||
current (:current data )
|
||||
start-x (min (first start) (first current))
|
||||
start-y (min (second start) (second current))
|
||||
current-x (max (first start) (first current))
|
||||
current-y (max (second start) (second current))
|
||||
start-x (min (:x start) (:x current))
|
||||
start-y (min (:y start) (:y current))
|
||||
current-x (max (:x start) (:x current))
|
||||
current-y (max (:y start) (:y current))
|
||||
width (- current-x start-x)
|
||||
height (- current-y start-y)]
|
||||
{:x start-x
|
||||
|
@ -58,9 +59,8 @@
|
|||
:height (- current-y start-y)}))
|
||||
|
||||
(define-once :selrect-subscriptions
|
||||
(letfn [(on-value [[x y :as pos]]
|
||||
(let [scroll (or @wb/scroll-top 0)
|
||||
pos [x (+ y scroll)]]
|
||||
(letfn [(on-value [pos]
|
||||
(let [pos (gpt/subtract pos @wb/scroll)]
|
||||
(if (nil? @selrect-pos)
|
||||
(reset! selrect-pos {:start pos :current pos})
|
||||
(swap! selrect-pos assoc :current pos))))
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
[uxbox.data.workspace :as dw]
|
||||
[uxbox.ui.icons :as i]
|
||||
[uxbox.ui.mixins :as mx]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.ui.colorpicker :refer (colorpicker)]
|
||||
[uxbox.ui.workspace.recent-colors :refer (recent-colors)]
|
||||
|
@ -53,19 +54,12 @@
|
|||
;; Helpers
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn- viewportcoord->clientcoord
|
||||
[pageid viewport-x viewport-y]
|
||||
(let [[offset-x offset-y] (get @wb/bounding-rect pageid)
|
||||
new-x (+ viewport-x offset-x)
|
||||
new-y (+ viewport-y offset-y)]
|
||||
[new-x new-y]))
|
||||
|
||||
(defn- get-position
|
||||
[{:keys [page] :as shape}]
|
||||
(let [{:keys [x y width]} (sh/-outer-rect shape)
|
||||
vx (+ x width 50)
|
||||
vy (- y 50)]
|
||||
(viewportcoord->clientcoord page vx vy)))
|
||||
bpt (get @wb/bounding-rect page)
|
||||
vpt (gpt/point (+ x width 50) (- y 50))]
|
||||
(gpt/add vpt bpt)))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Implementation
|
||||
|
@ -496,16 +490,17 @@
|
|||
(defn element-opts-render
|
||||
[own shape]
|
||||
(let [local (:rum/local own)
|
||||
shape (rum/react shape)
|
||||
[popup-x popup-y] (get-position shape)
|
||||
scroll (or (rum/react wb/scroll-top) 0)
|
||||
zoom 1
|
||||
shape (rum/react shape)
|
||||
scroll (rum/react wb/scroll)
|
||||
pos (-> (get-position shape)
|
||||
(gpt/subtract scroll)) ;; and multiply by zoom in future
|
||||
menus (get +menus-map+ (:type shape))
|
||||
active-menu (:menu @local (first menus))]
|
||||
(when (seq menus)
|
||||
(html
|
||||
[:div#element-options.element-options
|
||||
{:style {:left (* popup-x zoom) :top (- (* popup-y zoom) scroll)}}
|
||||
{:style {:left (:x pos) :top (:y pos)}}
|
||||
[:ul.element-icons
|
||||
(for [menu-id (get +menus-map+ (:type shape))
|
||||
:let [menu (get +menus-by-id+ menu-id)
|
||||
|
|
Loading…
Add table
Reference in a new issue