mirror of
https://github.com/penpot/penpot.git
synced 2025-01-26 08:29:42 -05:00
🎉 Duplicate move
This commit is contained in:
parent
d6c97f9d19
commit
174b9db1d2
10 changed files with 428 additions and 320 deletions
|
@ -25,6 +25,7 @@
|
||||||
[uxbox.main.data.workspace.persistence :as dwp]
|
[uxbox.main.data.workspace.persistence :as dwp]
|
||||||
[uxbox.main.data.workspace.texts :as dwtxt]
|
[uxbox.main.data.workspace.texts :as dwtxt]
|
||||||
[uxbox.main.data.workspace.transforms :as dwt]
|
[uxbox.main.data.workspace.transforms :as dwt]
|
||||||
|
[uxbox.main.data.workspace.selection :as dws]
|
||||||
[uxbox.main.repo :as rp]
|
[uxbox.main.repo :as rp]
|
||||||
[uxbox.main.store :as st]
|
[uxbox.main.store :as st]
|
||||||
[uxbox.main.streams :as ms]
|
[uxbox.main.streams :as ms]
|
||||||
|
@ -438,101 +439,6 @@
|
||||||
(assoc :zoom zoom)
|
(assoc :zoom zoom)
|
||||||
(update :vbox merge srect)))))))))))
|
(update :vbox merge srect)))))))))))
|
||||||
|
|
||||||
;; --- Selection Rect
|
|
||||||
|
|
||||||
(declare select-shapes-by-current-selrect)
|
|
||||||
(declare deselect-all)
|
|
||||||
|
|
||||||
(defn update-selrect
|
|
||||||
[selrect]
|
|
||||||
(ptk/reify ::update-selrect
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(assoc-in state [:workspace-local :selrect] selrect))))
|
|
||||||
|
|
||||||
(def handle-selection
|
|
||||||
(letfn [(data->selrect [data]
|
|
||||||
(let [start (:start data)
|
|
||||||
stop (:stop data)
|
|
||||||
start-x (min (:x start) (:x stop))
|
|
||||||
start-y (min (:y start) (:y stop))
|
|
||||||
end-x (max (:x start) (:x stop))
|
|
||||||
end-y (max (:y start) (:y stop))]
|
|
||||||
{:type :rect
|
|
||||||
:x start-x
|
|
||||||
:y start-y
|
|
||||||
:width (mth/abs (- end-x start-x))
|
|
||||||
:height (mth/abs (- end-y start-y))}))]
|
|
||||||
(ptk/reify ::handle-selection
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state stream]
|
|
||||||
(let [stoper (rx/filter #(or (interrupt? %)
|
|
||||||
(ms/mouse-up? %))
|
|
||||||
stream)]
|
|
||||||
(rx/concat
|
|
||||||
(rx/of deselect-all)
|
|
||||||
(->> ms/mouse-position
|
|
||||||
(rx/scan (fn [data pos]
|
|
||||||
(if data
|
|
||||||
(assoc data :stop pos)
|
|
||||||
{:start pos :stop pos}))
|
|
||||||
nil)
|
|
||||||
(rx/map data->selrect)
|
|
||||||
(rx/filter #(or (> (:width %) 10)
|
|
||||||
(> (:height %) 10)))
|
|
||||||
(rx/map update-selrect)
|
|
||||||
(rx/take-until stoper))
|
|
||||||
(rx/of select-shapes-by-current-selrect)))))))
|
|
||||||
|
|
||||||
;; --- Toggle shape's selection status (selected or deselected)
|
|
||||||
|
|
||||||
(declare expand-all-parents)
|
|
||||||
|
|
||||||
(defn select-shape
|
|
||||||
([id] (select-shape id false))
|
|
||||||
([id toggle?]
|
|
||||||
(us/verify ::us/uuid id)
|
|
||||||
(ptk/reify ::select-shape
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(update-in state [:workspace-local :selected]
|
|
||||||
(fn [selected]
|
|
||||||
(if-not toggle?
|
|
||||||
(conj selected id)
|
|
||||||
(if (contains? selected id)
|
|
||||||
(disj selected id)
|
|
||||||
(conj selected id))))))
|
|
||||||
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state stream]
|
|
||||||
(let [page-id (get-in state [:workspace-page :id])
|
|
||||||
objects (get-in state [:workspace-data page-id :objects])]
|
|
||||||
(rx/of (expand-all-parents [id] objects)))))))
|
|
||||||
|
|
||||||
(defn select-shapes
|
|
||||||
[ids]
|
|
||||||
(us/verify ::set-of-uuid ids)
|
|
||||||
(ptk/reify ::select-shapes
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(assoc-in state [:workspace-local :selected] ids))
|
|
||||||
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state stream]
|
|
||||||
(let [page-id (get-in state [:workspace-page :id])
|
|
||||||
objects (get-in state [:workspace-data page-id :objects])]
|
|
||||||
(rx/of (expand-all-parents ids objects))))))
|
|
||||||
|
|
||||||
(def deselect-all
|
|
||||||
"Clear all possible state of drawing, edition
|
|
||||||
or any similar action taken by the user."
|
|
||||||
(ptk/reify ::deselect-all
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(update state :workspace-local #(-> %
|
|
||||||
(assoc :selected #{})
|
|
||||||
(dissoc :selected-frame))))))
|
|
||||||
|
|
||||||
|
|
||||||
;; --- Add shape to Workspace
|
;; --- Add shape to Workspace
|
||||||
|
|
||||||
|
@ -598,161 +504,12 @@
|
||||||
:id id}]
|
:id id}]
|
||||||
|
|
||||||
(rx/of (dwc/commit-changes [rchange] [uchange] {:commit-local? true})
|
(rx/of (dwc/commit-changes [rchange] [uchange] {:commit-local? true})
|
||||||
(select-shapes #{id})
|
(dws/select-shapes #{id})
|
||||||
(when (= :text (:type attrs))
|
(when (= :text (:type attrs))
|
||||||
(start-edition-mode id)))))))
|
(start-edition-mode id)))))))
|
||||||
|
|
||||||
|
|
||||||
;; --- Duplicate Shapes
|
|
||||||
|
|
||||||
(declare prepare-duplicate-changes)
|
|
||||||
(declare prepare-duplicate-change)
|
|
||||||
(declare prepare-duplicate-frame-change)
|
|
||||||
(declare prepare-duplicate-shape-change)
|
|
||||||
|
|
||||||
(def ^:private change->name #(get-in % [:obj :name]))
|
|
||||||
|
|
||||||
(defn- prepare-duplicate-changes
|
|
||||||
"Prepare objects to paste: generate new id, give them unique names,
|
|
||||||
move to the position of mouse pointer, and find in what frame they
|
|
||||||
fit."
|
|
||||||
[objects names ids delta]
|
|
||||||
(loop [names names
|
|
||||||
chgs []
|
|
||||||
id (first ids)
|
|
||||||
ids (rest ids)]
|
|
||||||
(if (nil? id)
|
|
||||||
chgs
|
|
||||||
(let [result (prepare-duplicate-change objects names id delta)
|
|
||||||
result (if (vector? result) result [result])]
|
|
||||||
(recur
|
|
||||||
(into names (map change->name) result)
|
|
||||||
(into chgs result)
|
|
||||||
(first ids)
|
|
||||||
(rest ids))))))
|
|
||||||
|
|
||||||
(defn- prepare-duplicate-change
|
|
||||||
[objects names id delta]
|
|
||||||
(let [obj (get objects id)]
|
|
||||||
(if (= :frame (:type obj))
|
|
||||||
(prepare-duplicate-frame-change objects names obj delta)
|
|
||||||
(prepare-duplicate-shape-change objects names obj delta nil nil))))
|
|
||||||
|
|
||||||
(defn- prepare-duplicate-shape-change
|
|
||||||
[objects names obj delta frame-id parent-id]
|
|
||||||
(let [id (uuid/next)
|
|
||||||
name (generate-unique-name names (:name obj))
|
|
||||||
renamed-obj (assoc obj :id id :name name)
|
|
||||||
moved-obj (geom/move renamed-obj delta)
|
|
||||||
frames (cp/select-frames objects)
|
|
||||||
frame-id (if frame-id
|
|
||||||
frame-id
|
|
||||||
(dwc/calculate-frame-overlap frames moved-obj))
|
|
||||||
|
|
||||||
parent-id (or parent-id frame-id)
|
|
||||||
|
|
||||||
children-changes
|
|
||||||
(loop [names names
|
|
||||||
result []
|
|
||||||
cid (first (:shapes obj))
|
|
||||||
cids (rest (:shapes obj))]
|
|
||||||
(if (nil? cid)
|
|
||||||
result
|
|
||||||
(let [obj (get objects cid)
|
|
||||||
changes (prepare-duplicate-shape-change objects names obj delta frame-id id)]
|
|
||||||
(recur
|
|
||||||
(into names (map change->name changes))
|
|
||||||
(into result changes)
|
|
||||||
(first cids)
|
|
||||||
(rest cids)))))
|
|
||||||
|
|
||||||
reframed-obj (-> moved-obj
|
|
||||||
(assoc :frame-id frame-id)
|
|
||||||
(dissoc :shapes))]
|
|
||||||
(into [{:type :add-obj
|
|
||||||
:id id
|
|
||||||
:old-id (:id obj)
|
|
||||||
:frame-id frame-id
|
|
||||||
:parent-id parent-id
|
|
||||||
:obj (dissoc reframed-obj :shapes)}]
|
|
||||||
children-changes)))
|
|
||||||
|
|
||||||
(defn- prepare-duplicate-frame-change
|
|
||||||
[objects names obj delta]
|
|
||||||
(let [frame-id (uuid/next)
|
|
||||||
frame-name (generate-unique-name names (:name obj))
|
|
||||||
sch (->> (map #(get objects %) (:shapes obj))
|
|
||||||
(mapcat #(prepare-duplicate-shape-change objects names % delta frame-id frame-id)))
|
|
||||||
|
|
||||||
renamed-frame (-> obj
|
|
||||||
(assoc :id frame-id)
|
|
||||||
(assoc :name frame-name)
|
|
||||||
(assoc :frame-id uuid/zero)
|
|
||||||
(dissoc :shapes))
|
|
||||||
|
|
||||||
moved-frame (geom/move renamed-frame delta)
|
|
||||||
|
|
||||||
fch {:type :add-obj
|
|
||||||
:old-id (:id obj)
|
|
||||||
:id frame-id
|
|
||||||
:frame-id uuid/zero
|
|
||||||
:obj moved-frame}]
|
|
||||||
|
|
||||||
(into [fch] sch)))
|
|
||||||
|
|
||||||
(declare select-shapes)
|
|
||||||
|
|
||||||
(def duplicate-selected
|
|
||||||
(ptk/reify ::duplicate-selected
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state stream]
|
|
||||||
(let [page-id (:current-page-id state)
|
|
||||||
selected (get-in state [:workspace-local :selected])
|
|
||||||
objects (get-in state [:workspace-data page-id :objects])
|
|
||||||
delta (gpt/point 0 0)
|
|
||||||
unames (retrieve-used-names objects)
|
|
||||||
|
|
||||||
rchanges (prepare-duplicate-changes objects unames selected delta)
|
|
||||||
uchanges (mapv #(array-map :type :del-obj :id (:id %))
|
|
||||||
(reverse rchanges))
|
|
||||||
|
|
||||||
selected (->> rchanges
|
|
||||||
(filter #(selected (:old-id %)))
|
|
||||||
(map #(get-in % [:obj :id]))
|
|
||||||
(into #{}))]
|
|
||||||
|
|
||||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
|
||||||
(select-shapes selected))))))
|
|
||||||
|
|
||||||
|
|
||||||
;; --- Select Shapes (By selrect)
|
|
||||||
|
|
||||||
(def select-shapes-by-current-selrect
|
|
||||||
(ptk/reify ::select-shapes-by-current-selrect
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state stream]
|
|
||||||
(let [page-id (get-in state [:workspace-page :id])
|
|
||||||
selrect (get-in state [:workspace-local :selrect])]
|
|
||||||
(rx/merge
|
|
||||||
(rx/of (update-selrect nil))
|
|
||||||
(when selrect
|
|
||||||
(->> (uw/ask! {:cmd :selection/query
|
|
||||||
:page-id page-id
|
|
||||||
:rect selrect})
|
|
||||||
(rx/map select-shapes))))))))
|
|
||||||
|
|
||||||
(defn select-inside-group
|
|
||||||
[group-id position]
|
|
||||||
(ptk/reify ::select-inside-group
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state stream]
|
|
||||||
(let [page-id (:current-page-id state)
|
|
||||||
objects (get-in state [:workspace-data page-id :objects])
|
|
||||||
group (get objects group-id)
|
|
||||||
children (map #(get objects %) (:shapes group))
|
|
||||||
selected (->> children (filter #(geom/has-point? % position)) first)]
|
|
||||||
(when selected
|
|
||||||
(rx/of deselect-all (select-shape (:id selected))))))))
|
|
||||||
|
|
||||||
;; --- Update Shape Attrs
|
;; --- Update Shape Attrs
|
||||||
|
|
||||||
|
@ -906,7 +663,7 @@
|
||||||
shapes (map lookup selected)
|
shapes (map lookup selected)
|
||||||
shape? #(not= (:type %) :frame)]
|
shape? #(not= (:type %) :frame)]
|
||||||
(rx/of (delete-shapes selected)
|
(rx/of (delete-shapes selected)
|
||||||
deselect-all)))))
|
dws/deselect-all)))))
|
||||||
|
|
||||||
|
|
||||||
;; --- Rename Shape
|
;; --- Rename Shape
|
||||||
|
@ -1186,21 +943,6 @@
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(update state :workspace-local dissoc :expanded))))
|
(update state :workspace-local dissoc :expanded))))
|
||||||
|
|
||||||
(defn expand-all-parents
|
|
||||||
[ids objects]
|
|
||||||
(ptk/reify ::expand-all-parents
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(let [expand-fn (fn [expanded]
|
|
||||||
(merge expanded
|
|
||||||
(->> ids
|
|
||||||
(map #(cp/get-all-parents % objects))
|
|
||||||
flatten
|
|
||||||
(filter #(not= % uuid/zero))
|
|
||||||
(map (fn [id] {id true}))
|
|
||||||
(into {}))))]
|
|
||||||
(update-in state [:workspace-local :expanded] expand-fn)))))
|
|
||||||
|
|
||||||
(defn recursive-assign
|
(defn recursive-assign
|
||||||
"A helper for assign recursively a shape attr."
|
"A helper for assign recursively a shape attr."
|
||||||
[id attr value]
|
[id attr value]
|
||||||
|
@ -1284,7 +1026,7 @@
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(rx/of (select-shape (:id shape))))))
|
(rx/of (dws/select-shape (:id shape))))))
|
||||||
|
|
||||||
(def hide-context-menu
|
(def hide-context-menu
|
||||||
(ptk/reify ::hide-context-menu
|
(ptk/reify ::hide-context-menu
|
||||||
|
@ -1342,7 +1084,7 @@
|
||||||
unames (-> (get-in state [:workspace-data page-id :objects])
|
unames (-> (get-in state [:workspace-data page-id :objects])
|
||||||
(retrieve-used-names))
|
(retrieve-used-names))
|
||||||
|
|
||||||
rchanges (prepare-duplicate-changes objects unames selected delta)
|
rchanges (dws/prepare-duplicate-changes objects unames selected delta)
|
||||||
uchanges (mapv #(array-map :type :del-obj :id (:id %))
|
uchanges (mapv #(array-map :type :del-obj :id (:id %))
|
||||||
(reverse rchanges))
|
(reverse rchanges))
|
||||||
|
|
||||||
|
@ -1351,7 +1093,7 @@
|
||||||
(map #(get-in % [:obj :id]))
|
(map #(get-in % [:obj :id]))
|
||||||
(into #{}))]
|
(into #{}))]
|
||||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
||||||
(select-shapes selected))))))
|
(dws/select-shapes selected))))))
|
||||||
|
|
||||||
(def paste
|
(def paste
|
||||||
(ptk/reify ::paste
|
(ptk/reify ::paste
|
||||||
|
@ -1432,7 +1174,7 @@
|
||||||
{:type :del-obj
|
{:type :del-obj
|
||||||
:id id}]]
|
:id id}]]
|
||||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
||||||
(select-shapes #{id}))))))))
|
(dws/select-shapes #{id}))))))))
|
||||||
|
|
||||||
(def remove-group
|
(def remove-group
|
||||||
(ptk/reify ::remove-group
|
(ptk/reify ::remove-group
|
||||||
|
@ -1551,6 +1293,14 @@
|
||||||
(def delete-page dwp/delete-page)
|
(def delete-page dwp/delete-page)
|
||||||
(def create-empty-page dwp/create-empty-page)
|
(def create-empty-page dwp/create-empty-page)
|
||||||
|
|
||||||
|
;; Selection
|
||||||
|
(def select-shape dws/select-shape)
|
||||||
|
(def deselect-all dws/deselect-all)
|
||||||
|
(def select-shapes dws/select-shapes)
|
||||||
|
(def duplicate-selected dws/duplicate-selected)
|
||||||
|
(def handle-selection dws/handle-selection)
|
||||||
|
(def select-inside-group dws/select-inside-group)
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Shortcuts
|
;; Shortcuts
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
|
@ -298,3 +298,17 @@
|
||||||
(update state :workspace-local dissoc :undo-index :undo))))
|
(update state :workspace-local dissoc :undo-index :undo))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn expand-all-parents
|
||||||
|
[ids objects]
|
||||||
|
(ptk/reify ::expand-all-parents
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(let [expand-fn (fn [expanded]
|
||||||
|
(merge expanded
|
||||||
|
(->> ids
|
||||||
|
(map #(cp/get-all-parents % objects))
|
||||||
|
flatten
|
||||||
|
(filter #(not= % uuid/zero))
|
||||||
|
(map (fn [id] {id true}))
|
||||||
|
(into {}))))]
|
||||||
|
(update-in state [:workspace-local :expanded] expand-fn)))))
|
||||||
|
|
299
frontend/src/uxbox/main/data/workspace/selection.cljs
Normal file
299
frontend/src/uxbox/main/data/workspace/selection.cljs
Normal file
|
@ -0,0 +1,299 @@
|
||||||
|
;; 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/.
|
||||||
|
;;
|
||||||
|
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||||
|
;; defined by the Mozilla Public License, v. 2.0.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) 2020 UXBOX Labs SL
|
||||||
|
|
||||||
|
(ns uxbox.main.data.workspace.selection
|
||||||
|
(:require
|
||||||
|
[beicon.core :as rx]
|
||||||
|
[cljs.spec.alpha :as s]
|
||||||
|
[potok.core :as ptk]
|
||||||
|
[uxbox.main.data.workspace.common :as dwc]
|
||||||
|
[uxbox.main.worker :as uw]
|
||||||
|
[uxbox.main.streams :as ms]
|
||||||
|
[uxbox.common.pages :as cp]
|
||||||
|
[uxbox.common.spec :as us]
|
||||||
|
[uxbox.common.uuid :as uuid]
|
||||||
|
[uxbox.common.data :as d]
|
||||||
|
[uxbox.common.geom.shapes :as geom]
|
||||||
|
[uxbox.common.geom.point :as gpt]
|
||||||
|
[uxbox.common.math :as mth]))
|
||||||
|
|
||||||
|
(s/def ::set-of-uuid
|
||||||
|
(s/every uuid? :kind set?))
|
||||||
|
|
||||||
|
(s/def ::set-of-string
|
||||||
|
(s/every string? :kind set?))
|
||||||
|
|
||||||
|
;; Duplicate from workspace.
|
||||||
|
;; FIXME: Move these functions to a common place
|
||||||
|
|
||||||
|
(defn interrupt? [e] (= e :interrupt))
|
||||||
|
|
||||||
|
(defn- retrieve-used-names
|
||||||
|
[objects]
|
||||||
|
(into #{} (map :name) (vals objects)))
|
||||||
|
|
||||||
|
(defn- extract-numeric-suffix
|
||||||
|
[basename]
|
||||||
|
(if-let [[match p1 p2] (re-find #"(.*)-([0-9]+)$" basename)]
|
||||||
|
[p1 (+ 1 (d/parse-integer p2))]
|
||||||
|
[basename 1]))
|
||||||
|
|
||||||
|
(defn- generate-unique-name
|
||||||
|
"A unique name generator"
|
||||||
|
[used basename]
|
||||||
|
(s/assert ::set-of-string used)
|
||||||
|
(s/assert ::us/string basename)
|
||||||
|
(let [[prefix initial] (extract-numeric-suffix basename)]
|
||||||
|
(loop [counter initial]
|
||||||
|
(let [candidate (str prefix "-" counter)]
|
||||||
|
(if (contains? used candidate)
|
||||||
|
(recur (inc counter))
|
||||||
|
candidate)))))
|
||||||
|
|
||||||
|
;; --- Selection Rect
|
||||||
|
|
||||||
|
(declare select-shapes-by-current-selrect)
|
||||||
|
(declare deselect-all)
|
||||||
|
|
||||||
|
(defn update-selrect
|
||||||
|
[selrect]
|
||||||
|
(ptk/reify ::update-selrect
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(assoc-in state [:workspace-local :selrect] selrect))))
|
||||||
|
|
||||||
|
(def handle-selection
|
||||||
|
(letfn [(data->selrect [data]
|
||||||
|
(let [start (:start data)
|
||||||
|
stop (:stop data)
|
||||||
|
start-x (min (:x start) (:x stop))
|
||||||
|
start-y (min (:y start) (:y stop))
|
||||||
|
end-x (max (:x start) (:x stop))
|
||||||
|
end-y (max (:y start) (:y stop))]
|
||||||
|
{:type :rect
|
||||||
|
:x start-x
|
||||||
|
:y start-y
|
||||||
|
:width (mth/abs (- end-x start-x))
|
||||||
|
:height (mth/abs (- end-y start-y))}))]
|
||||||
|
(ptk/reify ::handle-selection
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state stream]
|
||||||
|
(let [stoper (rx/filter #(or (interrupt? %)
|
||||||
|
(ms/mouse-up? %))
|
||||||
|
stream)]
|
||||||
|
(rx/concat
|
||||||
|
(rx/of deselect-all)
|
||||||
|
(->> ms/mouse-position
|
||||||
|
(rx/scan (fn [data pos]
|
||||||
|
(if data
|
||||||
|
(assoc data :stop pos)
|
||||||
|
{:start pos :stop pos}))
|
||||||
|
nil)
|
||||||
|
(rx/map data->selrect)
|
||||||
|
(rx/filter #(or (> (:width %) 10)
|
||||||
|
(> (:height %) 10)))
|
||||||
|
(rx/map update-selrect)
|
||||||
|
(rx/take-until stoper))
|
||||||
|
(rx/of select-shapes-by-current-selrect)))))))
|
||||||
|
|
||||||
|
;; --- Toggle shape's selection status (selected or deselected)
|
||||||
|
|
||||||
|
(defn select-shape
|
||||||
|
([id] (select-shape id false))
|
||||||
|
([id toggle?]
|
||||||
|
(us/verify ::us/uuid id)
|
||||||
|
(ptk/reify ::select-shape
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(update-in state [:workspace-local :selected]
|
||||||
|
(fn [selected]
|
||||||
|
(if-not toggle?
|
||||||
|
(conj selected id)
|
||||||
|
(if (contains? selected id)
|
||||||
|
(disj selected id)
|
||||||
|
(conj selected id))))))
|
||||||
|
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state stream]
|
||||||
|
(let [page-id (get-in state [:workspace-page :id])
|
||||||
|
objects (get-in state [:workspace-data page-id :objects])]
|
||||||
|
(rx/of (dwc/expand-all-parents [id] objects)))))))
|
||||||
|
|
||||||
|
(defn select-shapes
|
||||||
|
[ids]
|
||||||
|
(us/verify ::set-of-uuid ids)
|
||||||
|
(ptk/reify ::select-shapes
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(assoc-in state [:workspace-local :selected] ids))
|
||||||
|
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state stream]
|
||||||
|
(let [page-id (get-in state [:workspace-page :id])
|
||||||
|
objects (get-in state [:workspace-data page-id :objects])]
|
||||||
|
(rx/of (dwc/expand-all-parents ids objects))))))
|
||||||
|
|
||||||
|
(def deselect-all
|
||||||
|
"Clear all possible state of drawing, edition
|
||||||
|
or any similar action taken by the user."
|
||||||
|
(ptk/reify ::deselect-all
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(update state :workspace-local #(-> %
|
||||||
|
(assoc :selected #{})
|
||||||
|
(dissoc :selected-frame))))))
|
||||||
|
|
||||||
|
|
||||||
|
;; --- Select Shapes (By selrect)
|
||||||
|
|
||||||
|
(def select-shapes-by-current-selrect
|
||||||
|
(ptk/reify ::select-shapes-by-current-selrect
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state stream]
|
||||||
|
(let [page-id (get-in state [:workspace-page :id])
|
||||||
|
selrect (get-in state [:workspace-local :selrect])]
|
||||||
|
(rx/merge
|
||||||
|
(rx/of (update-selrect nil))
|
||||||
|
(when selrect
|
||||||
|
(->> (uw/ask! {:cmd :selection/query
|
||||||
|
:page-id page-id
|
||||||
|
:rect selrect})
|
||||||
|
(rx/map select-shapes))))))))
|
||||||
|
|
||||||
|
(defn select-inside-group
|
||||||
|
[group-id position]
|
||||||
|
(ptk/reify ::select-inside-group
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state stream]
|
||||||
|
(let [page-id (:current-page-id state)
|
||||||
|
objects (get-in state [:workspace-data page-id :objects])
|
||||||
|
group (get objects group-id)
|
||||||
|
children (map #(get objects %) (:shapes group))
|
||||||
|
selected (->> children (filter #(geom/has-point? % position)) first)]
|
||||||
|
(when selected
|
||||||
|
(rx/of deselect-all (select-shape (:id selected))))))))
|
||||||
|
|
||||||
|
|
||||||
|
;; --- Duplicate Shapes
|
||||||
|
(declare prepare-duplicate-changes)
|
||||||
|
(declare prepare-duplicate-change)
|
||||||
|
(declare prepare-duplicate-frame-change)
|
||||||
|
(declare prepare-duplicate-shape-change)
|
||||||
|
|
||||||
|
(def ^:private change->name #(get-in % [:obj :name]))
|
||||||
|
|
||||||
|
(defn- prepare-duplicate-changes
|
||||||
|
"Prepare objects to paste: generate new id, give them unique names,
|
||||||
|
move to the position of mouse pointer, and find in what frame they
|
||||||
|
fit."
|
||||||
|
[objects names ids delta]
|
||||||
|
(loop [names names
|
||||||
|
chgs []
|
||||||
|
id (first ids)
|
||||||
|
ids (rest ids)]
|
||||||
|
(if (nil? id)
|
||||||
|
chgs
|
||||||
|
(let [result (prepare-duplicate-change objects names id delta)
|
||||||
|
result (if (vector? result) result [result])]
|
||||||
|
(recur
|
||||||
|
(into names (map change->name) result)
|
||||||
|
(into chgs result)
|
||||||
|
(first ids)
|
||||||
|
(rest ids))))))
|
||||||
|
|
||||||
|
(defn- prepare-duplicate-change
|
||||||
|
[objects names id delta]
|
||||||
|
(let [obj (get objects id)]
|
||||||
|
(if (= :frame (:type obj))
|
||||||
|
(prepare-duplicate-frame-change objects names obj delta)
|
||||||
|
(prepare-duplicate-shape-change objects names obj delta nil nil))))
|
||||||
|
|
||||||
|
(defn- prepare-duplicate-shape-change
|
||||||
|
[objects names obj delta frame-id parent-id]
|
||||||
|
(let [id (uuid/next)
|
||||||
|
name (generate-unique-name names (:name obj))
|
||||||
|
renamed-obj (assoc obj :id id :name name)
|
||||||
|
moved-obj (geom/move renamed-obj delta)
|
||||||
|
frames (cp/select-frames objects)
|
||||||
|
frame-id (if frame-id
|
||||||
|
frame-id
|
||||||
|
(dwc/calculate-frame-overlap frames moved-obj))
|
||||||
|
|
||||||
|
parent-id (or parent-id frame-id)
|
||||||
|
|
||||||
|
children-changes
|
||||||
|
(loop [names names
|
||||||
|
result []
|
||||||
|
cid (first (:shapes obj))
|
||||||
|
cids (rest (:shapes obj))]
|
||||||
|
(if (nil? cid)
|
||||||
|
result
|
||||||
|
(let [obj (get objects cid)
|
||||||
|
changes (prepare-duplicate-shape-change objects names obj delta frame-id id)]
|
||||||
|
(recur
|
||||||
|
(into names (map change->name changes))
|
||||||
|
(into result changes)
|
||||||
|
(first cids)
|
||||||
|
(rest cids)))))
|
||||||
|
|
||||||
|
reframed-obj (-> moved-obj
|
||||||
|
(assoc :frame-id frame-id)
|
||||||
|
(dissoc :shapes))]
|
||||||
|
(into [{:type :add-obj
|
||||||
|
:id id
|
||||||
|
:old-id (:id obj)
|
||||||
|
:frame-id frame-id
|
||||||
|
:parent-id parent-id
|
||||||
|
:obj (dissoc reframed-obj :shapes)}]
|
||||||
|
children-changes)))
|
||||||
|
|
||||||
|
(defn- prepare-duplicate-frame-change
|
||||||
|
[objects names obj delta]
|
||||||
|
(let [frame-id (uuid/next)
|
||||||
|
frame-name (generate-unique-name names (:name obj))
|
||||||
|
sch (->> (map #(get objects %) (:shapes obj))
|
||||||
|
(mapcat #(prepare-duplicate-shape-change objects names % delta frame-id frame-id)))
|
||||||
|
|
||||||
|
renamed-frame (-> obj
|
||||||
|
(assoc :id frame-id)
|
||||||
|
(assoc :name frame-name)
|
||||||
|
(assoc :frame-id uuid/zero)
|
||||||
|
(dissoc :shapes))
|
||||||
|
|
||||||
|
moved-frame (geom/move renamed-frame delta)
|
||||||
|
|
||||||
|
fch {:type :add-obj
|
||||||
|
:old-id (:id obj)
|
||||||
|
:id frame-id
|
||||||
|
:frame-id uuid/zero
|
||||||
|
:obj moved-frame}]
|
||||||
|
|
||||||
|
(into [fch] sch)))
|
||||||
|
|
||||||
|
(def duplicate-selected
|
||||||
|
(ptk/reify ::duplicate-selected
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state stream]
|
||||||
|
(let [page-id (:current-page-id state)
|
||||||
|
selected (get-in state [:workspace-local :selected])
|
||||||
|
objects (get-in state [:workspace-data page-id :objects])
|
||||||
|
delta (gpt/point 0 0)
|
||||||
|
unames (retrieve-used-names objects)
|
||||||
|
|
||||||
|
rchanges (prepare-duplicate-changes objects unames selected delta)
|
||||||
|
uchanges (mapv #(array-map :type :del-obj :id (:id %))
|
||||||
|
(reverse rchanges))
|
||||||
|
|
||||||
|
selected (->> rchanges
|
||||||
|
(filter #(selected (:old-id %)))
|
||||||
|
(map #(get-in % [:obj :id]))
|
||||||
|
(into #{}))]
|
||||||
|
|
||||||
|
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
||||||
|
(select-shapes selected))))))
|
|
@ -18,6 +18,7 @@
|
||||||
[uxbox.common.spec :as us]
|
[uxbox.common.spec :as us]
|
||||||
[uxbox.common.pages :as cp]
|
[uxbox.common.pages :as cp]
|
||||||
[uxbox.main.data.workspace.common :as dwc]
|
[uxbox.main.data.workspace.common :as dwc]
|
||||||
|
[uxbox.main.data.workspace.selection :as dws]
|
||||||
[uxbox.main.refs :as refs]
|
[uxbox.main.refs :as refs]
|
||||||
[uxbox.main.store :as st]
|
[uxbox.main.store :as st]
|
||||||
[uxbox.main.streams :as ms]
|
[uxbox.main.streams :as ms]
|
||||||
|
@ -191,6 +192,7 @@
|
||||||
;; -- MOVE
|
;; -- MOVE
|
||||||
|
|
||||||
(declare start-move)
|
(declare start-move)
|
||||||
|
(declare start-move-duplicate)
|
||||||
|
|
||||||
(defn start-move-selected
|
(defn start-move-selected
|
||||||
[]
|
[]
|
||||||
|
@ -206,33 +208,52 @@
|
||||||
(rx/map #(gpt/length %))
|
(rx/map #(gpt/length %))
|
||||||
(rx/filter #(> % 1))
|
(rx/filter #(> % 1))
|
||||||
(rx/take 1)
|
(rx/take 1)
|
||||||
(rx/map #(start-move initial selected)))))))
|
(rx/with-latest vector ms/mouse-position-alt)
|
||||||
|
(rx/flat-map
|
||||||
(defn start-move
|
(fn [[_ alt?]]
|
||||||
[from-position ids]
|
(if alt?
|
||||||
(ptk/reify ::start-move
|
;; When alt is down we start a duplicate+move
|
||||||
ptk/UpdateEvent
|
(rx/of (start-move-duplicate initial)
|
||||||
(update [_ state]
|
dws/duplicate-selected)
|
||||||
(-> state
|
;; Otherwise just plain old move
|
||||||
(assoc-in [:workspace-local :transform] :move)))
|
(rx/of (start-move initial selected))))))))))
|
||||||
|
|
||||||
|
(defn start-move-duplicate [from-position]
|
||||||
|
(ptk/reify ::start-move-selected
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(let [page-id (get state :current-page-id)
|
(->> stream
|
||||||
objects (get-in state [:workspace-data page-id :objects])
|
(rx/filter (ptk/type? ::dws/duplicate-selected))
|
||||||
shapes (mapv #(get-in state [:workspace-data page-id :objects %]) ids)
|
(rx/first)
|
||||||
stopper (rx/filter ms/mouse-up? stream)
|
(rx/map #(start-move from-position))))))
|
||||||
layout (get state :workspace-layout)]
|
|
||||||
(rx/concat
|
|
||||||
(->> ms/mouse-position
|
|
||||||
(rx/take-until stopper)
|
|
||||||
(rx/map #(gpt/to-vec from-position %))
|
|
||||||
(rx/switch-map #(snap/closest-snap-move page-id shapes objects layout %))
|
|
||||||
(rx/map gmt/translate-matrix)
|
|
||||||
(rx/map #(set-modifiers ids {:displacement %})))
|
|
||||||
|
|
||||||
(rx/of (apply-modifiers ids)
|
(defn start-move
|
||||||
finish-transform))))))
|
([from-position] (start-move from-position nil))
|
||||||
|
([from-position ids]
|
||||||
|
(ptk/reify ::start-move
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(-> state
|
||||||
|
(assoc-in [:workspace-local :transform] :move)))
|
||||||
|
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state stream]
|
||||||
|
(let [page-id (get state :current-page-id)
|
||||||
|
objects (get-in state [:workspace-data page-id :objects])
|
||||||
|
ids (if (nil? ids) (get-in state [:workspace-local :selected]) ids)
|
||||||
|
shapes (mapv #(get-in state [:workspace-data page-id :objects %]) ids)
|
||||||
|
stopper (rx/filter ms/mouse-up? stream)
|
||||||
|
layout (get state :workspace-layout)]
|
||||||
|
(rx/concat
|
||||||
|
(->> ms/mouse-position
|
||||||
|
(rx/take-until stopper)
|
||||||
|
(rx/map #(gpt/to-vec from-position %))
|
||||||
|
(rx/switch-map #(snap/closest-snap-move page-id shapes objects layout %))
|
||||||
|
(rx/map gmt/translate-matrix)
|
||||||
|
(rx/map #(set-modifiers ids {:displacement %})))
|
||||||
|
|
||||||
|
(rx/of (apply-modifiers ids)
|
||||||
|
finish-transform)))))))
|
||||||
|
|
||||||
(defn- get-displacement-with-grid
|
(defn- get-displacement-with-grid
|
||||||
"Retrieve the correct displacement delta point for the
|
"Retrieve the correct displacement delta point for the
|
||||||
|
|
|
@ -14,13 +14,13 @@
|
||||||
|
|
||||||
;; --- User Events
|
;; --- User Events
|
||||||
|
|
||||||
(defrecord KeyboardEvent [type key shift ctrl])
|
(defrecord KeyboardEvent [type key shift ctrl alt])
|
||||||
|
|
||||||
(defn keyboard-event?
|
(defn keyboard-event?
|
||||||
[v]
|
[v]
|
||||||
(instance? KeyboardEvent v))
|
(instance? KeyboardEvent v))
|
||||||
|
|
||||||
(defrecord MouseEvent [type ctrl shift])
|
(defrecord MouseEvent [type ctrl shift alt])
|
||||||
|
|
||||||
(defn mouse-event?
|
(defn mouse-event?
|
||||||
[v]
|
[v]
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
(and (mouse-event? v)
|
(and (mouse-event? v)
|
||||||
(= :click (:type v))))
|
(= :click (:type v))))
|
||||||
|
|
||||||
(defrecord PointerEvent [source pt ctrl shift])
|
(defrecord PointerEvent [source pt ctrl shift alt])
|
||||||
|
|
||||||
(defn pointer-event?
|
(defn pointer-event?
|
||||||
[v]
|
[v]
|
||||||
|
@ -73,6 +73,24 @@
|
||||||
(rx/subscribe-with ob sub)
|
(rx/subscribe-with ob sub)
|
||||||
sub))
|
sub))
|
||||||
|
|
||||||
|
(defonce mouse-position-alt
|
||||||
|
(let [sub (rx/behavior-subject nil)
|
||||||
|
ob (->> st/stream
|
||||||
|
(rx/filter pointer-event?)
|
||||||
|
(rx/map :alt)
|
||||||
|
(rx/dedupe))]
|
||||||
|
(rx/subscribe-with ob sub)
|
||||||
|
sub))
|
||||||
|
|
||||||
|
(defonce keyboard-alt
|
||||||
|
(let [sub (rx/behavior-subject nil)
|
||||||
|
ob (->> st/stream
|
||||||
|
(rx/filter keyboard-event?)
|
||||||
|
(rx/map :alt)
|
||||||
|
(rx/dedupe))]
|
||||||
|
(rx/subscribe-with ob sub)
|
||||||
|
sub))
|
||||||
|
|
||||||
(defn mouse-position-deltas
|
(defn mouse-position-deltas
|
||||||
[current]
|
[current]
|
||||||
(->> (rx/concat (rx/of current)
|
(->> (rx/concat (rx/of current)
|
||||||
|
@ -97,4 +115,3 @@
|
||||||
(rx/map :point))]
|
(rx/map :point))]
|
||||||
(rx/subscribe-with sob sub)
|
(rx/subscribe-with sob sub)
|
||||||
sub))
|
sub))
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
transform (if rotation (str " transform='rotate(" rotation ")'") "")
|
transform (if rotation (str " transform='rotate(" rotation ")'") "")
|
||||||
data (clojure.pprint/cl-format
|
data (clojure.pprint/cl-format
|
||||||
nil
|
nil
|
||||||
"url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' width='24px' height='24px'~A%3E~A%3C/svg%3E\") ~A ~A, auto"
|
"url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' width='20px' height='20px'~A%3E~A%3C/svg%3E\") ~A ~A, auto"
|
||||||
transform data x y)]
|
transform data x y)]
|
||||||
data))
|
data))
|
||||||
|
|
||||||
|
|
|
@ -53,4 +53,3 @@
|
||||||
|
|
||||||
[:span {:style {:white-space "nowrap"
|
[:span {:style {:white-space "nowrap"
|
||||||
:margin-right "1rem"}} (pr-str key)]])))]))
|
:margin-right "1rem"}} (pr-str key)]])))]))
|
||||||
|
|
||||||
|
|
|
@ -227,3 +227,10 @@
|
||||||
|
|
||||||
[(deref state) ref]))
|
[(deref state) ref]))
|
||||||
|
|
||||||
|
|
||||||
|
(defn use-stream
|
||||||
|
"Wraps the subscription to a strem into a `use-effect` call"
|
||||||
|
[stream on-subscribe]
|
||||||
|
(mf/use-effect (fn []
|
||||||
|
(let [sub (->> stream (rx/subs on-subscribe))]
|
||||||
|
#(rx/dispose! sub)))))
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
"A workspace specific shapes wrappers."
|
"A workspace specific shapes wrappers."
|
||||||
(:require
|
(:require
|
||||||
[rumext.alpha :as mf]
|
[rumext.alpha :as mf]
|
||||||
|
[beicon.core :as rx]
|
||||||
|
[uxbox.main.streams :as ms]
|
||||||
|
[uxbox.main.ui.hooks :as hooks]
|
||||||
|
[uxbox.main.ui.cursors :as cur]
|
||||||
[uxbox.main.ui.shapes.rect :as rect]
|
[uxbox.main.ui.shapes.rect :as rect]
|
||||||
[uxbox.main.ui.shapes.circle :as circle]
|
[uxbox.main.ui.shapes.circle :as circle]
|
||||||
[uxbox.main.ui.shapes.icon :as icon]
|
[uxbox.main.ui.shapes.icon :as icon]
|
||||||
|
@ -55,9 +59,13 @@
|
||||||
(let [shape (unchecked-get props "shape")
|
(let [shape (unchecked-get props "shape")
|
||||||
frame (unchecked-get props "frame")
|
frame (unchecked-get props "frame")
|
||||||
opts #js {:shape (->> shape (geom/transform-shape frame))
|
opts #js {:shape (->> shape (geom/transform-shape frame))
|
||||||
:frame frame}]
|
:frame frame}
|
||||||
|
alt? (mf/use-state false)]
|
||||||
|
|
||||||
|
(hooks/use-stream ms/keyboard-alt #(reset! alt? %))
|
||||||
|
|
||||||
(when (and shape (not (:hidden shape)))
|
(when (and shape (not (:hidden shape)))
|
||||||
[:*
|
[:g.shape {:style {:cursor (if @alt? cur/duplicate nil)}}
|
||||||
(case (:type shape)
|
(case (:type shape)
|
||||||
:curve [:> path/path-wrapper opts]
|
:curve [:> path/path-wrapper opts]
|
||||||
:path [:> path/path-wrapper opts]
|
:path [:> path/path-wrapper opts]
|
||||||
|
|
|
@ -154,9 +154,8 @@
|
||||||
(let [event (.-nativeEvent event)
|
(let [event (.-nativeEvent event)
|
||||||
ctrl? (kbd/ctrl? event)
|
ctrl? (kbd/ctrl? event)
|
||||||
shift? (kbd/shift? event)
|
shift? (kbd/shift? event)
|
||||||
opts {:shift? shift?
|
alt? (kbd/alt? event)]
|
||||||
:ctrl? ctrl?}]
|
(st/emit! (ms/->MouseEvent :down ctrl? shift? alt?))
|
||||||
(st/emit! (ms/->MouseEvent :down ctrl? shift?))
|
|
||||||
|
|
||||||
(cond
|
(cond
|
||||||
(and (not edition) (= 1 (.-which event)))
|
(and (not edition) (= 1 (.-which event)))
|
||||||
|
@ -183,9 +182,8 @@
|
||||||
(let [event (.-nativeEvent event)
|
(let [event (.-nativeEvent event)
|
||||||
ctrl? (kbd/ctrl? event)
|
ctrl? (kbd/ctrl? event)
|
||||||
shift? (kbd/shift? event)
|
shift? (kbd/shift? event)
|
||||||
opts {:shift? shift?
|
alt? (kbd/alt? event)]
|
||||||
:ctrl? ctrl?}]
|
(st/emit! (ms/->MouseEvent :up ctrl? shift? alt?))
|
||||||
(st/emit! (ms/->MouseEvent :up ctrl? shift?))
|
|
||||||
|
|
||||||
(when (= 2 (.-which event))
|
(when (= 2 (.-which event))
|
||||||
(st/emit! dw/finish-pan
|
(st/emit! dw/finish-pan
|
||||||
|
@ -213,9 +211,8 @@
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(let [ctrl? (kbd/ctrl? event)
|
(let [ctrl? (kbd/ctrl? event)
|
||||||
shift? (kbd/shift? event)
|
shift? (kbd/shift? event)
|
||||||
opts {:shift? shift?
|
alt? (kbd/alt? event)]
|
||||||
:ctrl? ctrl?}]
|
(st/emit! (ms/->MouseEvent :click ctrl? shift? alt?)))))
|
||||||
(st/emit! (ms/->MouseEvent :click ctrl? shift?)))))
|
|
||||||
|
|
||||||
on-double-click
|
on-double-click
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
|
@ -223,9 +220,8 @@
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(let [ctrl? (kbd/ctrl? event)
|
(let [ctrl? (kbd/ctrl? event)
|
||||||
shift? (kbd/shift? event)
|
shift? (kbd/shift? event)
|
||||||
opts {:shift? shift?
|
alt? (kbd/alt? event)]
|
||||||
:ctrl? ctrl?}]
|
(st/emit! (ms/->MouseEvent :double-click ctrl? shift? alt?)))))
|
||||||
(st/emit! (ms/->MouseEvent :double-click ctrl? shift?)))))
|
|
||||||
|
|
||||||
on-key-down
|
on-key-down
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
|
@ -234,13 +230,11 @@
|
||||||
key (.-keyCode event)
|
key (.-keyCode event)
|
||||||
ctrl? (kbd/ctrl? event)
|
ctrl? (kbd/ctrl? event)
|
||||||
shift? (kbd/shift? event)
|
shift? (kbd/shift? event)
|
||||||
opts {:key key
|
alt? (kbd/alt? event)
|
||||||
:shift? shift?
|
|
||||||
:ctrl? ctrl?}
|
|
||||||
target (dom/get-target event)]
|
target (dom/get-target event)]
|
||||||
|
|
||||||
(when-not (.-repeat bevent)
|
(when-not (.-repeat bevent)
|
||||||
(st/emit! (ms/->KeyboardEvent :down key ctrl? shift?))
|
(st/emit! (ms/->KeyboardEvent :down key ctrl? shift? alt?))
|
||||||
(when (and (kbd/space? event)
|
(when (and (kbd/space? event)
|
||||||
(not= "rich-text" (obj/get target "className")))
|
(not= "rich-text" (obj/get target "className")))
|
||||||
(handle-viewport-positioning viewport-ref))))))
|
(handle-viewport-positioning viewport-ref))))))
|
||||||
|
@ -251,13 +245,10 @@
|
||||||
(let [key (.-keyCode event)
|
(let [key (.-keyCode event)
|
||||||
ctrl? (kbd/ctrl? event)
|
ctrl? (kbd/ctrl? event)
|
||||||
shift? (kbd/shift? event)
|
shift? (kbd/shift? event)
|
||||||
opts {:key key
|
alt? (kbd/alt? event)]
|
||||||
:shift? shift?
|
|
||||||
:ctrl? ctrl?}]
|
|
||||||
(when (kbd/space? event)
|
(when (kbd/space? event)
|
||||||
(st/emit! dw/finish-pan
|
(st/emit! dw/finish-pan ::finish-positioning))
|
||||||
::finish-positioning))
|
(st/emit! (ms/->KeyboardEvent :up key ctrl? shift? alt?)))))
|
||||||
(st/emit! (ms/->KeyboardEvent :up key ctrl? shift?)))))
|
|
||||||
|
|
||||||
translate-point-to-viewport
|
translate-point-to-viewport
|
||||||
(fn [pt]
|
(fn [pt]
|
||||||
|
@ -282,10 +273,12 @@
|
||||||
(.-movementY event))]
|
(.-movementY event))]
|
||||||
(st/emit! (ms/->PointerEvent :delta delta
|
(st/emit! (ms/->PointerEvent :delta delta
|
||||||
(kbd/ctrl? event)
|
(kbd/ctrl? event)
|
||||||
(kbd/shift? event)))
|
(kbd/shift? event)
|
||||||
|
(kbd/alt? event)))
|
||||||
(st/emit! (ms/->PointerEvent :viewport pt
|
(st/emit! (ms/->PointerEvent :viewport pt
|
||||||
(kbd/ctrl? event)
|
(kbd/ctrl? event)
|
||||||
(kbd/shift? event)))))
|
(kbd/shift? event)
|
||||||
|
(kbd/alt? event)))))
|
||||||
|
|
||||||
on-mouse-wheel
|
on-mouse-wheel
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
|
|
Loading…
Add table
Reference in a new issue