mirror of
https://github.com/penpot/penpot.git
synced 2025-06-02 04:21:38 +02:00
Add missing stuff in order to make path usable.
This commit is contained in:
parent
8f935b4d60
commit
0dff98801c
10 changed files with 202 additions and 36 deletions
|
@ -29,6 +29,7 @@
|
|||
;; --- Relative Movement
|
||||
|
||||
(declare move-rect)
|
||||
(declare move-path)
|
||||
(declare move-circle)
|
||||
(declare move-group)
|
||||
|
||||
|
@ -41,6 +42,7 @@
|
|||
:rect (move-rect shape dpoint)
|
||||
:text (move-rect shape dpoint)
|
||||
:line (move-rect shape dpoint)
|
||||
:path (move-path shape dpoint)
|
||||
:circle (move-circle shape dpoint)
|
||||
:group (move-group shape dpoint)))
|
||||
|
||||
|
@ -70,6 +72,16 @@
|
|||
:dx (mth/round (+ (:dx shape 0) dx))
|
||||
:dy (mth/round (+ (:dy shape 0) dy))))
|
||||
|
||||
(defn- move-path
|
||||
"A specialized function for relative movement
|
||||
for path shapes."
|
||||
[shape {dx :x dy :y}]
|
||||
(let [points (:points shape)
|
||||
xf (comp
|
||||
(map #(update % :x + dx))
|
||||
(map #(update % :y + dy)))]
|
||||
(assoc shape :points (into [] xf points))))
|
||||
|
||||
;; --- Absolute Movement
|
||||
|
||||
(declare absolute-move-rect)
|
||||
|
@ -353,6 +365,7 @@
|
|||
|
||||
(declare apply-rotation-transformation)
|
||||
(declare generic-inner-rect)
|
||||
(declare path-inner-rect)
|
||||
(declare circle-inner-rect)
|
||||
(declare group-inner-rect)
|
||||
|
||||
|
@ -364,6 +377,7 @@
|
|||
:rect (generic-inner-rect state shape)
|
||||
:text (generic-inner-rect shape shape)
|
||||
:line (generic-inner-rect state shape)
|
||||
:path (path-inner-rect state shape)
|
||||
:circle (circle-inner-rect state shape)
|
||||
:group (group-inner-rect state shape))))
|
||||
|
||||
|
@ -373,6 +387,19 @@
|
|||
(merge (size shape))
|
||||
(apply-rotation-transformation)))
|
||||
|
||||
(defn- path-inner-rect
|
||||
[state {:keys [points] :as shape}]
|
||||
(let [minx (apply min (map :x points))
|
||||
miny (apply min (map :y points))
|
||||
maxx (apply max (map :x points))
|
||||
maxy (apply max (map :y points))
|
||||
props {:x minx
|
||||
:y miny
|
||||
:width (- maxx minx)
|
||||
:height (- maxy miny)}]
|
||||
(-> (merge shape props)
|
||||
(apply-rotation-transformation))))
|
||||
|
||||
(defn- circle-inner-rect
|
||||
[state {:keys [cx cy rx ry group] :as shape}]
|
||||
(let [props {:x (- cx rx)
|
||||
|
@ -402,6 +429,7 @@
|
|||
|
||||
(declare generic-outer-rect)
|
||||
(declare circle-outer-rect)
|
||||
(declare path-outer-rect)
|
||||
(declare group-outer-rect)
|
||||
(declare apply-rotation-transformation)
|
||||
(declare apply-parent-deltas)
|
||||
|
@ -415,6 +443,7 @@
|
|||
:text (generic-outer-rect state shape)
|
||||
:icon (generic-outer-rect state shape)
|
||||
:line (generic-outer-rect state shape)
|
||||
:path (path-outer-rect state shape)
|
||||
:circle (circle-outer-rect state shape)
|
||||
:group (group-outer-rect state shape))]
|
||||
(if (:group shape)
|
||||
|
@ -450,6 +479,22 @@
|
|||
(-> (merge shape props)
|
||||
(apply-rotation-transformation))))
|
||||
|
||||
(defn- path-outer-rect
|
||||
[state {:keys [points group] :as shape}]
|
||||
(let [group (get-in state [:shapes-by-id group])
|
||||
minx (apply min (map :x points))
|
||||
miny (apply min (map :y points))
|
||||
maxx (apply max (map :x points))
|
||||
maxy (apply max (map :y points))
|
||||
|
||||
props {:x (+ minx (:dx group 0))
|
||||
:y (+ miny (:dy group 0))
|
||||
:width (- maxx minx)
|
||||
:height (- maxy miny)}]
|
||||
(-> (merge shape props)
|
||||
(apply-rotation-transformation))))
|
||||
|
||||
|
||||
(defn- group-outer-rect
|
||||
[state {:keys [id group rotation dx dy] :as shape}]
|
||||
(let [shapes (->> (:items shape)
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
|
||||
(defn render-component
|
||||
[{:keys [type] :as shape}]
|
||||
;; (println "render-component" shape)
|
||||
(case type
|
||||
:group (group-component shape)
|
||||
:text (text/text-component shape)
|
||||
|
|
48
src/uxbox/main/ui/shapes/path.cljs
Normal file
48
src/uxbox/main/ui/shapes/path.cljs
Normal file
|
@ -0,0 +1,48 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; 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>
|
||||
|
||||
(ns uxbox.main.ui.shapes.path
|
||||
(:require [uxbox.util.mixins :as mx :include-macros true]
|
||||
[uxbox.main.ui.shapes.common :as common]
|
||||
[uxbox.main.ui.shapes.attrs :as attrs]
|
||||
[uxbox.main.geom :as geom]))
|
||||
|
||||
;; --- Path Component
|
||||
|
||||
(declare path-shape)
|
||||
|
||||
(mx/defc path-component
|
||||
{:mixins [mx/static mx/reactive]}
|
||||
[{:keys [id] :as shape}]
|
||||
(let [selected (mx/react common/selected-shapes-ref)
|
||||
selected? (contains? selected id)
|
||||
on-mouse-down #(common/on-mouse-down % shape selected)
|
||||
]
|
||||
[:g.shape {:class (when selected? "selected")
|
||||
:on-mouse-down on-mouse-down
|
||||
}
|
||||
(path-shape shape identity)]))
|
||||
|
||||
;; --- Path Shape
|
||||
|
||||
(defn- render-path
|
||||
[{:keys [points close?] :as shape}]
|
||||
{:pre [(pos? (count points))]}
|
||||
(let [start (first points)
|
||||
init (str "M " (:x start) " " (:y start))
|
||||
path (reduce #(str %1 " L" (:x %2) " " (:y %2)) init points)]
|
||||
(cond-> path
|
||||
close? (str " Z"))))
|
||||
|
||||
(mx/defc path-shape
|
||||
{:mixins [mx/static]}
|
||||
[{:keys [id] :as shape}]
|
||||
(let [key (str "shape-" id)
|
||||
props {:d (render-path shape)}
|
||||
attrs (-> (attrs/extract-style-attrs shape)
|
||||
(merge {:id key :key key})
|
||||
(merge props))]
|
||||
[:path attrs]))
|
|
@ -80,9 +80,16 @@
|
|||
|
||||
;; --- Events
|
||||
|
||||
;; TODO: this should replace mouse-events-s and keyboard-events-b
|
||||
(defonce events-b (rx/bus))
|
||||
(defonce events-s (rx/dedupe events-b))
|
||||
|
||||
(defonce mouse-events-b (rx/bus))
|
||||
(defonce mouse-events-s (rx/dedupe mouse-events-b))
|
||||
|
||||
;; (defonce kaka
|
||||
;; (rx/subscribe mouse-events-s #(println "event:" %)))
|
||||
|
||||
(defonce keyboard-events-b (rx/bus))
|
||||
(defonce keyboard-events-s (rx/dedupe keyboard-events-b))
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
[uxbox.util.data :refer (parse-int)]
|
||||
[uxbox.main.ui.keyboard :as kbd]
|
||||
[uxbox.main.ui.shapes :as uus]
|
||||
;; [uxbox.main.ui.shapes.path :as spath]
|
||||
[uxbox.util.mixins :as mx :include-macros true]
|
||||
[uxbox.main.ui.workspace.base :as wb]
|
||||
[uxbox.main.ui.workspace.rlocks :as rlocks]
|
||||
|
@ -42,19 +41,6 @@
|
|||
|
||||
;; --- Canvas
|
||||
|
||||
;; (def ^:private test-path-shape
|
||||
;; {:type :path
|
||||
;; :id #uuid "042951a0-804a-4cf1-b606-3e97157f55b5"
|
||||
;; :stroke-type :solid
|
||||
;; :stroke "#000000"
|
||||
;; :stroke-width 2
|
||||
;; :fill "transparent"
|
||||
;; :close? true
|
||||
;; :points [(gpt/point 100 100)
|
||||
;; (gpt/point 300 100)
|
||||
;; (gpt/point 200 300)
|
||||
;; ]})
|
||||
|
||||
(mx/defc canvas
|
||||
{:mixins [mx/reactive]}
|
||||
[{:keys [width height id] :as page}]
|
||||
|
@ -71,7 +57,6 @@
|
|||
(for [item (reverse (:shapes page))]
|
||||
(-> (uus/shape item)
|
||||
(mx/with-key (str item))))
|
||||
;; (spath/path-component test-path-shape)
|
||||
(selection-handlers)
|
||||
(draw-area)]]]))
|
||||
|
||||
|
@ -150,17 +135,25 @@
|
|||
zoom (or (:zoom workspace) 1)]
|
||||
(letfn [(on-mouse-down [event]
|
||||
(dom/stop-propagation event)
|
||||
(rx/push! wb/mouse-events-b :mouse/down)
|
||||
(rx/push! wb/events-b [:mouse/down])
|
||||
(if (:drawing workspace)
|
||||
(rlocks/acquire! :ui/draw)
|
||||
(rlocks/acquire! :ui/selrect)))
|
||||
(on-mouse-up [event]
|
||||
(rx/push! wb/mouse-events-b :mouse/up)
|
||||
(dom/stop-propagation event))]
|
||||
(dom/stop-propagation event)
|
||||
(rx/push! wb/events-b [:mouse/up]))
|
||||
(on-click [event]
|
||||
(dom/stop-propagation event)
|
||||
(rx/push! wb/events-b [:mouse/click]))
|
||||
(on-double-click [event]
|
||||
(dom/stop-propagation event)
|
||||
(rx/push! wb/events-b [:mouse/double-click]))]
|
||||
[:svg.viewport {:width (* c/viewport-width zoom)
|
||||
:height (* c/viewport-height zoom)
|
||||
:ref "viewport"
|
||||
:class (when drawing? "drawing")
|
||||
:on-click on-click
|
||||
:on-double-click on-double-click
|
||||
:on-mouse-down on-mouse-down
|
||||
:on-mouse-up on-mouse-up}
|
||||
[:g.zoom {:transform (str "scale(" zoom ", " zoom ")")}
|
||||
|
|
|
@ -49,15 +49,19 @@
|
|||
[own]
|
||||
(let [shape (mx/react drawing-shape)
|
||||
position (mx/react drawing-position)]
|
||||
(when (and shape position)
|
||||
(-> (assoc shape :drawing? true)
|
||||
(geom/resize position)
|
||||
(shapes/render-component)))))
|
||||
(when shape
|
||||
(if position
|
||||
(-> (assoc shape :drawing? true)
|
||||
(geom/resize position)
|
||||
(shapes/render-component))
|
||||
(-> (assoc shape :drawing? true)
|
||||
(shapes/render-component))))))
|
||||
|
||||
;; --- Drawing Initialization
|
||||
|
||||
(declare on-init)
|
||||
(declare on-init-draw-icon)
|
||||
(declare on-init-draw-path)
|
||||
(declare on-init-draw-generic)
|
||||
(declare on-draw-start)
|
||||
(declare on-draw)
|
||||
|
@ -76,6 +80,7 @@
|
|||
(when-let [shape (:drawing @wb/workspace-ref)]
|
||||
(case (:type shape)
|
||||
:icon (on-init-draw-icon shape)
|
||||
:path (on-init-draw-path shape)
|
||||
(on-init-draw-generic shape))))
|
||||
|
||||
(defn- on-init-draw-icon
|
||||
|
@ -88,6 +93,65 @@
|
|||
(uds/select-first-shape))
|
||||
(rlocks/release! :ui/draw)))
|
||||
|
||||
(defn- on-init-draw-path
|
||||
[shape]
|
||||
(let [mouse (->> (rx/sample 10 wb/mouse-viewport-s)
|
||||
(rx/mapcat (fn [point]
|
||||
(if @wb/alignment-ref
|
||||
(uds/align-point point)
|
||||
(rx/of point))))
|
||||
(rx/map #(gpt/subtract % canvas-coords)))
|
||||
|
||||
stoper (->> wb/events-s
|
||||
(rx/map first)
|
||||
(rx/filter #(= % :mouse/double-click))
|
||||
(rx/take 1))
|
||||
;; stoper (rx/empty)
|
||||
firstpos (rx/take 1 mouse)
|
||||
stream (->> (rx/take-until stoper mouse)
|
||||
(rx/skip-while #(nil? @drawing-shape))
|
||||
(rx/with-latest-from vector wb/mouse-ctrl-s))
|
||||
ptstream (->> wb/events-s
|
||||
(rx/map first)
|
||||
(rx/filter #(= % :mouse/click))
|
||||
(rx/with-latest-from vector mouse)
|
||||
(rx/map second))
|
||||
counter (atom 0)]
|
||||
(letfn [(append-point [{:keys [type] :as shape} point]
|
||||
(let [point (gpt/point point)]
|
||||
(update shape :points conj point)))
|
||||
|
||||
(update-point [{:keys [type] :as shape} point index]
|
||||
(let [point (gpt/point point)
|
||||
points (:points shape)]
|
||||
(if (= (count points) index)
|
||||
(append-point shape point)
|
||||
(assoc-in shape [:points index] point))))
|
||||
(on-first-point [point]
|
||||
(println "on-first-point" point)
|
||||
(let [shape (append-point shape point)]
|
||||
(swap! counter inc)
|
||||
(reset! drawing-shape shape)))
|
||||
(on-click [point]
|
||||
(let [shape (append-point @drawing-shape point)]
|
||||
(swap! counter inc)
|
||||
(reset! drawing-shape shape)))
|
||||
(on-draw [[point ctrl?]]
|
||||
(let [shape (update-point @drawing-shape point @counter)]
|
||||
(reset! drawing-shape shape)))
|
||||
(on-end []
|
||||
(let [shape @drawing-shape]
|
||||
(rs/emit! (uds/add-shape shape)
|
||||
(udw/select-for-drawing nil)
|
||||
(uds/select-first-shape))
|
||||
(reset! drawing-position nil)
|
||||
(reset! drawing-shape nil)
|
||||
(rlocks/release! :ui/draw)))]
|
||||
|
||||
(rx/subscribe firstpos on-first-point)
|
||||
(rx/subscribe ptstream on-click)
|
||||
(rx/subscribe stream on-draw nil on-end))))
|
||||
|
||||
(defn- on-init-draw-generic
|
||||
[shape]
|
||||
(let [mouse (->> (rx/sample 10 wb/mouse-viewport-s)
|
||||
|
@ -97,23 +161,25 @@
|
|||
(rx/of point))))
|
||||
(rx/map #(gpt/subtract % canvas-coords)))
|
||||
|
||||
stoper (->> wb/mouse-events-s
|
||||
stoper (->> wb/events-s
|
||||
(rx/map first)
|
||||
(rx/filter #(= % :mouse/up))
|
||||
(rx/pr-log "mouse-events-s")
|
||||
(rx/take 1))
|
||||
|
||||
firstpos (rx/take 1 mouse)
|
||||
stream (->> (rx/take-until stoper mouse)
|
||||
(rx/skip-while #(nil? @drawing-shape))
|
||||
(rx/with-latest-from vector wb/mouse-ctrl-s))]
|
||||
|
||||
(rx/subscribe firstpos #(on-draw-start shape %))
|
||||
(rx/subscribe firstpos (fn [{:keys [x y] :as pt}]
|
||||
(let [shape (geom/setup shape {:x1 x :y1 y
|
||||
:x2 x :y2 y})]
|
||||
(reset! drawing-shape shape))))
|
||||
(rx/subscribe stream on-draw nil on-draw-complete)))
|
||||
|
||||
(defn- on-draw-start
|
||||
[shape {:keys [x y] :as pt}]
|
||||
(let [shape (geom/setup shape {:x1 x :y1 y :x2 x :y2 y})]
|
||||
(reset! drawing-shape shape)))
|
||||
;; (defn- on-draw-start
|
||||
;; [shape {:keys [x y] :as pt}]
|
||||
;; (let [shape (geom/setup shape {:x1 x :y1 y :x2 x :y2 y})]
|
||||
;; (reset! drawing-shape shape)))
|
||||
|
||||
(defn- on-draw
|
||||
[[pt ctrl?]]
|
||||
|
@ -124,7 +190,7 @@
|
|||
[]
|
||||
(let [shape @drawing-shape
|
||||
shpos @drawing-position
|
||||
shape (geom/resize shape shpos)]
|
||||
shape (geom/resize shape shpos)]
|
||||
(rs/emit! (uds/add-shape shape)
|
||||
(udw/select-for-drawing nil)
|
||||
(uds/select-first-shape))
|
||||
|
|
|
@ -60,7 +60,8 @@
|
|||
|
||||
(defn- on-resize-start
|
||||
[[vid shape]]
|
||||
(let [stoper (->> wb/mouse-events-s
|
||||
(let [stoper (->> wb/events-s
|
||||
(rx/map first)
|
||||
(rx/filter #(= % :mouse/up))
|
||||
(rx/take 1))
|
||||
stream (->> wb/mouse-delta-s
|
||||
|
@ -81,7 +82,8 @@
|
|||
|
||||
(defn- on-move-start
|
||||
[shape]
|
||||
(let [stoper (->> wb/mouse-events-s
|
||||
(let [stoper (->> wb/events-s
|
||||
(rx/map first)
|
||||
(rx/filter #(= % :mouse/up))
|
||||
(rx/take 1))
|
||||
stream (rx/take-until stoper wb/mouse-delta-s)
|
||||
|
|
|
@ -101,7 +101,8 @@
|
|||
(defn- on-start
|
||||
"Function execution when selrect action is started."
|
||||
[]
|
||||
(let [stoper (->> wb/mouse-events-s
|
||||
(let [stoper (->> wb/events-s
|
||||
(rx/map first)
|
||||
(rx/filter #(= % :mouse/up))
|
||||
(rx/take 1))
|
||||
stream (rx/take-until stoper wb/mouse-viewport-s)
|
||||
|
|
|
@ -51,7 +51,11 @@
|
|||
{:type :path
|
||||
:name "Path"
|
||||
:stroke-type :solid
|
||||
:stroke "#000000"})
|
||||
:stroke "#000000"
|
||||
:stroke-width 2
|
||||
:fill "transparent"
|
||||
;; :close? true
|
||||
:points []})
|
||||
|
||||
(def +draw-tool-text+
|
||||
{:type :text
|
||||
|
|
|
@ -96,6 +96,7 @@
|
|||
:icon (icon/icon-svg item)
|
||||
:line i/line
|
||||
:circle i/circle
|
||||
:path i/curve
|
||||
:rect i/box
|
||||
:text i/text
|
||||
:group i/folder))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue