mirror of
https://github.com/penpot/penpot.git
synced 2026-09-11 06:28:47 +00:00
Refactor interactions in workspace.
This commit is contained in:
parent
de5036bc9b
commit
76cd1a48b8
@ -72,12 +72,22 @@
|
|||||||
(defonce scroll-left (rx/to-atom scroll-left-s))
|
(defonce scroll-left (rx/to-atom scroll-left-s))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Mouse Position Stream
|
;; Interactions
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(defonce shapes-dragging? (atom false))
|
;; (defonce shapes-dragging? (atom false))
|
||||||
(defonce selrect-dragging? (atom false))
|
;; (defonce selrect-dragging? (atom false))
|
||||||
(defonce selrect-pos (atom nil))
|
(defonce interactions-b (rx/bus))
|
||||||
|
|
||||||
|
(defn emit-interaction!
|
||||||
|
([type]
|
||||||
|
(rx/push! interactions-b {:type type}))
|
||||||
|
([type payload]
|
||||||
|
(rx/push! interactions-b {:type type :payload payload})))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Mouse Position Stream
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(defonce mouse-b (rx/bus))
|
(defonce mouse-b (rx/bus))
|
||||||
(defonce mouse-s
|
(defonce mouse-s
|
||||||
@ -109,65 +119,6 @@
|
|||||||
|
|
||||||
(defonce bounding-rect (atom {}))
|
(defonce bounding-rect (atom {}))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;; Subscriptions
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
(define-once :mouse-subscriptions
|
|
||||||
(as-> mouse-delta-s $
|
|
||||||
(rx/filter #(deref shapes-dragging?) $)
|
|
||||||
(rx/on-value $ (fn [delta]
|
|
||||||
(let [pageid (get-in @st/state [:workspace :page])
|
|
||||||
selected (get-in @st/state [:workspace :selected])
|
|
||||||
shapes (->> (vals @shapes-by-id)
|
|
||||||
(filter #(= (:page %) pageid))
|
|
||||||
(filter (comp selected :id)))]
|
|
||||||
(doseq [{:keys [id group]} shapes]
|
|
||||||
(rs/emit! (dw/move-shape id delta))))))))
|
|
||||||
|
|
||||||
(defn selrect->rect
|
|
||||||
[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))
|
|
||||||
width (- current-x start-x)
|
|
||||||
height (- current-y start-y)]
|
|
||||||
{:x start-x
|
|
||||||
:y start-y
|
|
||||||
:width (- current-x start-x)
|
|
||||||
:height (- current-y start-y)}))
|
|
||||||
|
|
||||||
(define-once :selrect-subscriptions
|
|
||||||
(let [ss (as-> (rx/from-atom selrect-dragging?) $
|
|
||||||
(rx/dedupe $)
|
|
||||||
(rx/merge $ (rx/of false))
|
|
||||||
(rx/buffer 2 1 $)
|
|
||||||
(rx/share $))]
|
|
||||||
(as-> ss $
|
|
||||||
(rx/filter #(= (vec %) [false true]) $)
|
|
||||||
(rx/with-latest-from vector mouse-s $)
|
|
||||||
(rx/on-value $ (fn [[_ [x y :as pos]]]
|
|
||||||
(let [scroll (or @scroll-top 0)
|
|
||||||
pos [x (+ y scroll)]]
|
|
||||||
(swap! selrect-pos assoc
|
|
||||||
:start pos
|
|
||||||
:current pos)))))
|
|
||||||
(as-> ss $
|
|
||||||
(rx/filter #(= (vec %) [true false]) $)
|
|
||||||
(rx/on-value $ (fn []
|
|
||||||
(let [selrect (selrect->rect @selrect-pos)]
|
|
||||||
(rs/emit! (dw/select-shapes selrect))
|
|
||||||
(reset! selrect-pos nil)))))
|
|
||||||
(as-> mouse-s $
|
|
||||||
(rx/filter #(deref selrect-dragging?) $)
|
|
||||||
(rx/on-value $ (fn [[x y :as pos]]
|
|
||||||
(let [scroll (or @scroll-top 0)
|
|
||||||
pos [x (+ y scroll)]]
|
|
||||||
(swap! selrect-pos assoc :current pos)))))))
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Constants
|
;; Constants
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
[uxbox.ui.mixins :as mx]
|
[uxbox.ui.mixins :as mx]
|
||||||
[uxbox.ui.dom :as dom]
|
[uxbox.ui.dom :as dom]
|
||||||
[uxbox.ui.workspace.base :as wb]
|
[uxbox.ui.workspace.base :as wb]
|
||||||
|
[uxbox.ui.workspace.canvas.movement]
|
||||||
[uxbox.ui.workspace.canvas.selection :refer (shapes-selection)]
|
[uxbox.ui.workspace.canvas.selection :refer (shapes-selection)]
|
||||||
[uxbox.ui.workspace.canvas.selrect :refer (selrect)]
|
[uxbox.ui.workspace.canvas.selrect :refer (selrect)]
|
||||||
[uxbox.ui.workspace.grid :refer (grid)]
|
[uxbox.ui.workspace.grid :refer (grid)]
|
||||||
@ -51,9 +52,6 @@
|
|||||||
local (:rum/local own)]
|
local (:rum/local own)]
|
||||||
(letfn [(on-mouse-down [event]
|
(letfn [(on-mouse-down [event]
|
||||||
(when-not (:blocked item)
|
(when-not (:blocked item)
|
||||||
;; (let [local (:rum/local own)]
|
|
||||||
;; (swap! local assoc :init-coords [x y])
|
|
||||||
;; (reset! wb/shapes-dragging? true))
|
|
||||||
(cond
|
(cond
|
||||||
(and group (:locked (sh/resolve-parent item)))
|
(and group (:locked (sh/resolve-parent item)))
|
||||||
nil
|
nil
|
||||||
@ -62,15 +60,14 @@
|
|||||||
(do
|
(do
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(swap! local assoc :init-coords [x y])
|
(swap! local assoc :init-coords [x y])
|
||||||
(reset! wb/shapes-dragging? true)
|
(wb/emit-interaction! :shape/movement)
|
||||||
|
|
||||||
(rs/emit! (dw/select-shape id)))
|
(rs/emit! (dw/select-shape id)))
|
||||||
|
|
||||||
(and (not selected?) (not (empty? selected)))
|
(and (not selected?) (not (empty? selected)))
|
||||||
(do
|
(do
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(swap! local assoc :init-coords [x y])
|
(swap! local assoc :init-coords [x y])
|
||||||
(reset! wb/shapes-dragging? true)
|
#_(reset! wb/shapes-dragging? true)
|
||||||
(if (.-ctrlKey event)
|
(if (.-ctrlKey event)
|
||||||
(rs/emit! (dw/select-shape id))
|
(rs/emit! (dw/select-shape id))
|
||||||
(rs/emit! (dw/deselect-all)
|
(rs/emit! (dw/deselect-all)
|
||||||
@ -80,7 +77,7 @@
|
|||||||
(do
|
(do
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(swap! local assoc :init-coords [x y])
|
(swap! local assoc :init-coords [x y])
|
||||||
(reset! wb/shapes-dragging? true)))))
|
(wb/emit-interaction! :shape/movement)))))
|
||||||
|
|
||||||
(on-mouse-up [event]
|
(on-mouse-up [event]
|
||||||
(cond
|
(cond
|
||||||
@ -90,7 +87,8 @@
|
|||||||
:else
|
:else
|
||||||
(do
|
(do
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(reset! wb/shapes-dragging? false))))]
|
(wb/emit-interaction! :nothing)
|
||||||
|
)))]
|
||||||
(html
|
(html
|
||||||
[:g.shape {:class (when selected? "selected")
|
[:g.shape {:class (when selected? "selected")
|
||||||
:on-mouse-down on-mouse-down
|
:on-mouse-down on-mouse-down
|
||||||
@ -189,11 +187,10 @@
|
|||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(when-not (empty? (:selected workspace))
|
(when-not (empty? (:selected workspace))
|
||||||
(rs/emit! (dw/deselect-all)))
|
(rs/emit! (dw/deselect-all)))
|
||||||
(reset! wb/selrect-dragging? true))
|
(wb/emit-interaction! :selrect/draw))
|
||||||
(on-mouse-up [event]
|
(on-mouse-up [event]
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(reset! wb/shapes-dragging? false)
|
(wb/emit-interaction! :nothing))
|
||||||
(reset! wb/selrect-dragging? false))
|
|
||||||
(on-click [event wstate]
|
(on-click [event wstate]
|
||||||
(let [mousepos @wb/mouse-position
|
(let [mousepos @wb/mouse-position
|
||||||
scroll-top @wb/scroll-top
|
scroll-top @wb/scroll-top
|
||||||
|
|||||||
22
src/uxbox/ui/workspace/canvas/movement.cljs
Normal file
22
src/uxbox/ui/workspace/canvas/movement.cljs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
(ns uxbox.ui.workspace.canvas.movement
|
||||||
|
(:require-macros [uxbox.util.syntax :refer [define-once]])
|
||||||
|
(:require [beicon.core :as rx]
|
||||||
|
[cats.labs.lens :as l]
|
||||||
|
[uxbox.rstore :as rs]
|
||||||
|
[uxbox.state :as st]
|
||||||
|
[uxbox.ui.workspace.base :as wb]
|
||||||
|
[uxbox.data.workspace :as dw]))
|
||||||
|
|
||||||
|
(define-once :mouse-subscriptions
|
||||||
|
(as-> (rx/with-latest-from vector wb/interactions-b wb/mouse-delta-s) $
|
||||||
|
(rx/filter #(= (:type (second %)) :shape/movement) $)
|
||||||
|
(rx/map first $)
|
||||||
|
(rx/on-value $ (fn [delta]
|
||||||
|
(let [pageid (get-in @st/state [:workspace :page])
|
||||||
|
selected (get-in @st/state [:workspace :selected])
|
||||||
|
shapes (->> (vals @wb/shapes-by-id)
|
||||||
|
(filter #(= (:page %) pageid))
|
||||||
|
(filter (comp selected :id)))]
|
||||||
|
(doseq [{:keys [id group]} shapes]
|
||||||
|
(rs/emit! (dw/move-shape id delta))))))))
|
||||||
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
(ns uxbox.ui.workspace.canvas.selrect
|
(ns uxbox.ui.workspace.canvas.selrect
|
||||||
"Components for indicate the user selection and selected shapes group."
|
"Components for indicate the user selection and selected shapes group."
|
||||||
|
(:require-macros [uxbox.util.syntax :refer [define-once]])
|
||||||
(:require [sablono.core :as html :refer-macros [html]]
|
(:require [sablono.core :as html :refer-macros [html]]
|
||||||
[rum.core :as rum]
|
[rum.core :as rum]
|
||||||
[beicon.core :as rx]
|
[beicon.core :as rx]
|
||||||
@ -7,18 +8,23 @@
|
|||||||
[uxbox.rstore :as rs]
|
[uxbox.rstore :as rs]
|
||||||
[uxbox.state :as st]
|
[uxbox.state :as st]
|
||||||
[uxbox.shapes :as sh]
|
[uxbox.shapes :as sh]
|
||||||
|
[uxbox.data.workspace :as dw]
|
||||||
[uxbox.ui.workspace.base :as wb]
|
[uxbox.ui.workspace.base :as wb]
|
||||||
[uxbox.ui.mixins :as mx]
|
[uxbox.ui.mixins :as mx]
|
||||||
[uxbox.ui.dom :as dom]))
|
[uxbox.ui.dom :as dom]))
|
||||||
|
|
||||||
|
(defonce selrect-pos (atom nil))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Component
|
;; Component
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(declare selrect->rect)
|
||||||
|
|
||||||
(defn selrect-render
|
(defn selrect-render
|
||||||
[own]
|
[own]
|
||||||
(when-let [data (rum/react wb/selrect-pos)]
|
(when-let [data (rum/react selrect-pos)]
|
||||||
(let [{:keys [x y width height]} (wb/selrect->rect data)]
|
(let [{:keys [x y width height]} (selrect->rect data)]
|
||||||
(html
|
(html
|
||||||
[:rect.selection-rect
|
[:rect.selection-rect
|
||||||
{:x x
|
{:x x
|
||||||
@ -31,3 +37,58 @@
|
|||||||
{:render selrect-render
|
{:render selrect-render
|
||||||
:name "selrect"
|
:name "selrect"
|
||||||
:mixins [mx/static rum/reactive]}))
|
:mixins [mx/static rum/reactive]}))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Subscriptions
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defn selrect->rect
|
||||||
|
[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))
|
||||||
|
width (- current-x start-x)
|
||||||
|
height (- current-y start-y)]
|
||||||
|
{:x start-x
|
||||||
|
:y start-y
|
||||||
|
:width (- current-x start-x)
|
||||||
|
:height (- current-y start-y)}))
|
||||||
|
|
||||||
|
(define-once :selrect-subscriptions
|
||||||
|
(let [events #{:selrect/draw :nothing}
|
||||||
|
ss (as-> wb/interactions-b $
|
||||||
|
(rx/filter #(contains? events (:type %)) $)
|
||||||
|
(rx/dedupe $)
|
||||||
|
(rx/merge (rx/of {:type :nothing}) $)
|
||||||
|
(rx/map (fn [event]
|
||||||
|
(case (:type event)
|
||||||
|
:selrect/draw true
|
||||||
|
:nothing false)) $)
|
||||||
|
(rx/buffer 2 1 $)
|
||||||
|
(rx/share $))]
|
||||||
|
(as-> ss $
|
||||||
|
(rx/filter #(= (vec %) [false true]) $)
|
||||||
|
(rx/with-latest-from vector wb/mouse-s $)
|
||||||
|
(rx/pr-log "kaka1" $)
|
||||||
|
(rx/on-value $ (fn [[_ [x y :as pos]]]
|
||||||
|
(let [scroll (or @wb/scroll-top 0)
|
||||||
|
pos [x (+ y scroll)]]
|
||||||
|
(swap! selrect-pos assoc
|
||||||
|
:start pos
|
||||||
|
:current pos)))))
|
||||||
|
(as-> ss $
|
||||||
|
(rx/filter #(= (vec %) [true false]) $)
|
||||||
|
(rx/on-value $ (fn []
|
||||||
|
(let [selrect (selrect->rect @selrect-pos)]
|
||||||
|
(rs/emit! (dw/select-shapes selrect))
|
||||||
|
(reset! selrect-pos nil)))))
|
||||||
|
(as-> (rx/with-latest-from vector wb/interactions-b wb/mouse-s) $
|
||||||
|
(rx/filter #(= (:type (second %)) :selrect/draw) $)
|
||||||
|
(rx/map first $)
|
||||||
|
(rx/on-value $ (fn [[x y :as pos]]
|
||||||
|
(let [scroll (or @wb/scroll-top 0)
|
||||||
|
pos [x (+ y scroll)]]
|
||||||
|
(swap! selrect-pos assoc :current pos)))))))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user