0
Fork 0
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:
Andrey Antukh 2016-02-29 17:20:55 +02:00
parent 4dd97ca8ab
commit 99da1c21d1
7 changed files with 219 additions and 28 deletions

View file

@ -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}]

View file

@ -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

View file

@ -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)

View file

@ -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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View file

@ -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))]

View file

@ -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)]

View 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))))