mirror of
https://github.com/penpot/penpot.git
synced 2025-03-13 08:11:30 -05:00
Add resize using mouse and vertext handlers.
Signed-off-by: Andrey Antukh <niwi@niwi.nz>
This commit is contained in:
parent
4dd97ca8ab
commit
99da1c21d1
7 changed files with 219 additions and 28 deletions
|
@ -125,6 +125,13 @@
|
|||
size (merge (sh/size shape) opts)]
|
||||
(update-in state [:shapes-by-id sid] sh/resize' size)))))
|
||||
|
||||
(defn update-vertex-position
|
||||
[id {:keys [vid delta]}]
|
||||
(reify
|
||||
rs/UpdateEvent
|
||||
(-apply-update [_ state]
|
||||
(update-in state [:shapes-by-id id] sh/move-vertex vid delta))))
|
||||
|
||||
(defn update-position
|
||||
"Update the start position coordenate of the shape."
|
||||
[sid {:keys [x y] :as opts}]
|
||||
|
|
|
@ -39,6 +39,10 @@
|
|||
dispatch-by-type
|
||||
:hierarchy #'+hierarchy+)
|
||||
|
||||
(defmulti move-vertex
|
||||
dispatch-by-type
|
||||
:hierarchy #'+hierarchy+)
|
||||
|
||||
(defmulti resize
|
||||
dispatch-by-type
|
||||
:hierarchy #'+hierarchy+)
|
||||
|
@ -112,6 +116,38 @@
|
|||
:rx (mth/abs (- x2 x1))
|
||||
:ry (mth/abs (- y2 y1))))
|
||||
|
||||
(defmethod move-vertex ::rect
|
||||
[shape vid {dx :x dy :y}]
|
||||
(case vid
|
||||
1 (assoc shape
|
||||
:x1 (+ (:x1 shape) dx)
|
||||
:y1 (+ (:y1 shape) dy))
|
||||
2 (assoc shape
|
||||
:x2 (+ (:x2 shape) dx)
|
||||
:y1 (+ (:y1 shape) dy))
|
||||
3 (assoc shape
|
||||
:x1 (+ (:x1 shape) dx)
|
||||
:y2 (+ (:y2 shape) dy))
|
||||
4 (assoc shape
|
||||
:x2 (+ (:x2 shape) dx)
|
||||
:y2 (+ (:y2 shape) dy))))
|
||||
|
||||
(defmethod move-vertex :builtin/circle
|
||||
[shape vid {dx :x dy :y}]
|
||||
(case vid
|
||||
1 (assoc shape
|
||||
:rx (- (:rx shape) dx)
|
||||
:ry (- (:ry shape) dy))
|
||||
2 (assoc shape
|
||||
:rx (+ (:rx shape) dx)
|
||||
:ry (- (:ry shape) dy))
|
||||
3 (assoc shape
|
||||
:rx (- (:rx shape) dx)
|
||||
:ry (+ (:ry shape) dy))
|
||||
4 (assoc shape
|
||||
:rx (+ (:rx shape) dx)
|
||||
:ry (+ (:ry shape) dy))))
|
||||
|
||||
;; FIXME: lock mode
|
||||
|
||||
(defmethod resize :builtin/line
|
||||
|
|
|
@ -8,10 +8,89 @@
|
|||
[uxbox.shapes :as ush]
|
||||
[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.ui.shapes.icon :as uusi]
|
||||
[uxbox.util.dom :as dom]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Circle Component
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(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 #(uusi/on-mouse-down % shape selected)
|
||||
on-mouse-up #(uusi/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 (and selected? (= (count selected) 1))
|
||||
(handlers shape))])))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Circle Handlers
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn- handlers-render
|
||||
[own shape]
|
||||
(letfn [(on-mouse-down [vid event]
|
||||
(println "on-mouse-down" vid)
|
||||
(dom/stop-propagation event)
|
||||
(uuc/acquire-action! :resize/shape {:vid vid :shape (:id shape)}))
|
||||
|
||||
(on-mouse-up [vid event]
|
||||
(println "on-mouse-up" vid)
|
||||
(dom/stop-propagation event)
|
||||
(uuc/release-action! :resize/shape))]
|
||||
(let [{:keys [x y width height]} (ush/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 uusc/+circle-props+
|
||||
{:on-mouse-up #(on-mouse-up 1 %)
|
||||
:on-mouse-down #(on-mouse-down 1 %)
|
||||
:cx x
|
||||
:cy y})]
|
||||
[:circle.top-right
|
||||
(merge uusc/+circle-props+
|
||||
{:on-mouse-up #(on-mouse-up 2 %)
|
||||
:on-mouse-down #(on-mouse-down 2 %)
|
||||
:cx (+ x width)
|
||||
:cy y})]
|
||||
[:circle.bottom-left
|
||||
(merge uusc/+circle-props+
|
||||
{:on-mouse-up #(on-mouse-up 3 %)
|
||||
:on-mouse-down #(on-mouse-down 3 %)
|
||||
:cx x
|
||||
:cy (+ y height)})]
|
||||
[:circle.bottom-right
|
||||
(merge uusc/+circle-props+
|
||||
{:on-mouse-up #(on-mouse-up 4 %)
|
||||
:on-mouse-down #(on-mouse-down 4 %)
|
||||
:cx (+ x width)
|
||||
:cy (+ y height)})]]))))
|
||||
|
||||
(def ^:const handlers
|
||||
(mx/component
|
||||
{:render handlers-render
|
||||
:name "handlers"
|
||||
:mixins [mx/static]}))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Shape
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defmethod uusc/render-shape :builtin/circle
|
||||
[{:keys [id] :as shape}]
|
||||
(let [key (str id)
|
||||
|
|
|
@ -7,6 +7,18 @@
|
|||
[uxbox.shapes :as sh]
|
||||
[uxbox.ui.mixins :as mx]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Common constants
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(def ^:const +circle-props+
|
||||
{:r 5
|
||||
:style {:fillOpacity "0.5"
|
||||
:strokeWidth "1px"
|
||||
:vectorEffect "non-scaling-stroke"}
|
||||
:fill "#333"
|
||||
:stroke "#333"})
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Implementation Api
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
[lentes.core :as l]
|
||||
[uxbox.rstore :as rs]
|
||||
[uxbox.state :as st]
|
||||
[uxbox.shapes :as sh]
|
||||
[uxbox.shapes :as ush]
|
||||
[uxbox.data.workspace :as dw]
|
||||
[uxbox.ui.core :as uuc]
|
||||
[uxbox.ui.mixins :as mx]
|
||||
|
@ -13,16 +13,6 @@
|
|||
[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
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -32,7 +22,7 @@
|
|||
(let [selected? (contains? selected id)]
|
||||
(when-not (:blocked shape)
|
||||
(cond
|
||||
(and group (:locked (sh/resolve-parent shape)))
|
||||
(and group (:locked (ush/resolve-parent shape)))
|
||||
nil
|
||||
|
||||
(and (not selected?) (empty? selected))
|
||||
|
@ -57,7 +47,7 @@
|
|||
(defn on-mouse-up
|
||||
[event {:keys [id group] :as shape}]
|
||||
(cond
|
||||
(and group (:locked (sh/resolve-parent shape)))
|
||||
(and group (:locked (ush/resolve-parent shape)))
|
||||
nil
|
||||
|
||||
:else
|
||||
|
@ -88,20 +78,45 @@
|
|||
|
||||
(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)})]])))
|
||||
(letfn [(on-mouse-down [vid event]
|
||||
(println "on-mouse-down" vid)
|
||||
(dom/stop-propagation event)
|
||||
(uuc/acquire-action! :resize/shape {:vid vid :shape (:id shape)}))
|
||||
|
||||
(on-mouse-up [vid event]
|
||||
(println "on-mouse-up" vid)
|
||||
(dom/stop-propagation event)
|
||||
(uuc/release-action! :resize/shape))]
|
||||
(let [{:keys [x y width height]} (ush/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 uusc/+circle-props+
|
||||
{:on-mouse-up #(on-mouse-up 1 %)
|
||||
:on-mouse-down #(on-mouse-down 1 %)
|
||||
:cx x
|
||||
:cy y})]
|
||||
[:circle.top-right
|
||||
(merge uusc/+circle-props+
|
||||
{:on-mouse-up #(on-mouse-up 2 %)
|
||||
:on-mouse-down #(on-mouse-down 2 %)
|
||||
:cx (+ x width)
|
||||
:cy y})]
|
||||
[:circle.bottom-left
|
||||
(merge uusc/+circle-props+
|
||||
{:on-mouse-up #(on-mouse-up 3 %)
|
||||
:on-mouse-down #(on-mouse-down 3 %)
|
||||
:cx x
|
||||
:cy (+ y height)})]
|
||||
[:circle.bottom-right
|
||||
(merge uusc/+circle-props+
|
||||
{:on-mouse-up #(on-mouse-up 4 %)
|
||||
:on-mouse-down #(on-mouse-down 4 %)
|
||||
:cx (+ x width)
|
||||
:cy (+ y height)})]]))))
|
||||
|
||||
(def ^:const handlers
|
||||
(mx/component
|
||||
|
@ -116,7 +131,7 @@
|
|||
(defmethod uusc/render-shape :builtin/icon
|
||||
[{:keys [data id] :as shape} _]
|
||||
(let [key (str id)
|
||||
rfm (sh/transformation shape)
|
||||
rfm (ush/transformation shape)
|
||||
attrs (merge {:id key :key key :transform (str rfm)}
|
||||
(uusc/extract-style-attrs shape)
|
||||
(uusc/make-debug-attrs shape))]
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
[uxbox.ui.mixins :as mx]
|
||||
[uxbox.ui.workspace.base :as uuwb]
|
||||
[uxbox.ui.workspace.canvas.movement]
|
||||
[uxbox.ui.workspace.canvas.resize]
|
||||
[uxbox.ui.workspace.canvas.draw :refer (draw-area)]
|
||||
[uxbox.ui.workspace.canvas.ruler :refer (ruler)]
|
||||
[uxbox.ui.workspace.canvas.selection :refer (shapes-selection)]
|
||||
|
|
41
src/uxbox/ui/workspace/canvas/resize.cljs
Normal file
41
src/uxbox/ui/workspace/canvas/resize.cljs
Normal file
|
@ -0,0 +1,41 @@
|
|||
(ns uxbox.ui.workspace.canvas.resize
|
||||
(:require-macros [uxbox.util.syntax :refer [define-once]])
|
||||
(:require [sablono.core :as html :refer-macros [html]]
|
||||
[rum.core :as rum]
|
||||
[beicon.core :as rx]
|
||||
[lentes.core :as l]
|
||||
[uxbox.rstore :as rs]
|
||||
[uxbox.shapes :as ush]
|
||||
[uxbox.data.workspace :as udw]
|
||||
[uxbox.data.shapes :as uds]
|
||||
[uxbox.ui.core :as uuc]
|
||||
[uxbox.ui.shapes.core :as uusc]
|
||||
[uxbox.ui.workspace.base :as uuwb]
|
||||
[uxbox.ui.mixins :as mx]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.dom :as dom]))
|
||||
|
||||
(define-once :resize-subscriptions
|
||||
(letfn [(init [{:keys [payload]}]
|
||||
(println payload)
|
||||
(let [stoper (->> uuc/actions-s
|
||||
(rx/map :type)
|
||||
(rx/pr-log "kaka:")
|
||||
(rx/filter #(= :nothing %))
|
||||
(rx/take 1))]
|
||||
(as-> uuwb/mouse-delta-s $
|
||||
(rx/take-until stoper $)
|
||||
(rx/subscribe
|
||||
$ #(on-value payload %) nil on-complete))))
|
||||
|
||||
(on-complete []
|
||||
(println "on-complete"))
|
||||
|
||||
(on-value [{:keys [vid shape]} delta]
|
||||
(let [params {:vid vid :delta delta}]
|
||||
(rs/emit! (uds/update-vertex-position shape params))))]
|
||||
|
||||
(as-> uuc/actions-s $
|
||||
(rx/dedupe $)
|
||||
(rx/filter #(= (:type %) :resize/shape) $)
|
||||
(rx/on-value $ init))))
|
Loading…
Add table
Reference in a new issue