Get rid of buggy reactive locks and refactor all related code.

This commit is contained in:
Andrey Antukh 2017-01-30 17:08:02 +01:00
parent bce58df413
commit b0de23b011
No known key found for this signature in database
GPG key ID: 4DFEBCB8316A8B95
18 changed files with 611 additions and 516 deletions

View file

@ -16,7 +16,6 @@
[uxbox.main.data.shapes :as uds]
[uxbox.main.ui.keyboard :as kbd]
[uxbox.util.geom.point :as gpt]
[uxbox.util.rlocks :as rlocks]
[uxbox.util.dom :as dom]))
;; --- Refs
@ -37,12 +36,13 @@
;; --- Movement
;; TODO: implement in the same way as drawing (move under uxbox.main.data.workspace.)
(defn start-move
[]
(letfn [(on-move [shape delta]
(st/emit! (uds/apply-temporal-displacement shape delta)))
(on-stop [{:keys [id] :as shape}]
(rlocks/release! :shape/move)
(st/emit! (uds/apply-displacement shape)))
(on-start [shape]
(let [stoper (->> streams/events
@ -55,7 +55,6 @@
(when @refs/selected-alignment
(st/emit! (uds/initial-align-shape shape)))
(rx/subscribe stream on-move nil on-stop)))]
(rlocks/acquire! :shape/move)
(run! on-start @selected-ref)))
;; --- Events

View file

@ -48,6 +48,7 @@
(mx/defc path-shape
{:mixins [mx/static]}
[{:keys [id tmp-resize-xform tmp-displacement rotation] :as shape}]
(let [shape (cond-> shape
tmp-displacement (geom/transform (gmt/translate-matrix tmp-displacement))
tmp-resize-xform (geom/transform tmp-resize-xform)

View file

@ -20,7 +20,6 @@
[uxbox.main.ui.shapes.common :as scommon]
[uxbox.main.geom :as geom]
[uxbox.util.mixins :as mx :include-macros true]
[uxbox.util.rlocks :as rlocks]
[uxbox.util.geom.matrix :as gmt]
[uxbox.util.geom.point :as gpt]
[uxbox.util.dom :as dom]))
@ -209,8 +208,7 @@
(apply st/emit! (sequence xf ids))))
(on-end []
(apply st/emit! (map uds/apply-resize-matrix ids))
(rlocks/release! :shape/resize))]
(apply st/emit! (map uds/apply-resize-matrix ids)))]
(let [shape (->> (geom/shape->rect-shape shape)
(geom/size))
@ -229,7 +227,6 @@
(rx/with-latest-from vector streams/mouse-position-ctrl)
(rx/scan accumulate-width shape)
(rx/map (partial calculate-ratio shape)))]
(rlocks/acquire! :shape/resize)
(rx/subscribe stream
(partial on-resize shape)
nil
@ -316,27 +313,30 @@
;; --- Selection Handlers (Component)
(defn get-path-edition-stoper
[stream]
(letfn [(stoper-event? [{:keys [type shift] :as event}]
(and (uev/mouse-event? event) (= type :up)))]
(rx/merge
(rx/filter stoper-event? stream)
(->> stream
(rx/filter #(= % ::uev/interrupt))
(rx/take 1)))))
(defn start-path-edition
[shape-id index]
(letfn [(on-move [delta]
(st/emit! (uds/update-path shape-id index delta)))
(on-end []
(rlocks/release! :shape/resize))]
(let [stoper (->> streams/events
(rx/map first)
(rx/filter #(= % :mouse/up))
(rx/take 1))
(st/emit! (uds/update-path shape-id index delta)))]
(let [stoper (get-path-edition-stoper streams/events)
stream (rx/take-until stoper streams/mouse-position-deltas)]
(rlocks/acquire! :shape/resize)
(when @refs/selected-alignment
(st/emit! (uds/initial-path-point-align shape-id index)))
(rx/subscribe stream on-move nil on-end))))
(rx/subscribe stream on-move))))
(mx/defc path-edition-selection-handlers
[{:keys [id points] :as shape} zoom]
(letfn [(on-mouse-down [index event]
(dom/stop-propagation event)
(rlocks/acquire! :shape/resize)
(start-path-edition id index))]
[:g.controls
(for [[index {:keys [x y]}] (map-indexed vector points)]

View file

@ -17,7 +17,6 @@
[uxbox.util.color :as color]
[uxbox.util.dom :as dom]
[uxbox.util.geom.matrix :as gmt]
[uxbox.util.rlocks :as rlocks]
[uxbox.util.mixins :as mx :include-macros true])
(:import goog.events.EventType))
@ -48,6 +47,8 @@
(letfn [(on-mouse-down [event]
(handle-mouse-down event shape selected))
(on-double-click [event]
;; TODO: handle grouping event propagation
;; TODO: handle actions locking properly
(dom/stop-propagation event)
(st/emit! (uds/start-edition-mode id)))]
[:g.shape {:class (when selected? "selected")
@ -149,11 +150,9 @@
own))
(mx/defc text-shape-wrapper
{
:did-mount text-shape-wrapper-did-mount
{:did-mount text-shape-wrapper-did-mount
:did-remount text-shape-wrapper-did-remount}
[{:keys [id tmp-resize-xform tmp-displacement drawing?] :as shape}]
(println "text-shape-wrapper" shape)
(let [xfmt (cond-> (gmt/matrix)
tmp-displacement (gmt/translate tmp-displacement)
tmp-resize-xform (gmt/multiply tmp-resize-xform))
@ -182,7 +181,6 @@
(let [style (make-style shape)]
[:div {:style style} content]))
;; --- Text Shape Html
(mx/defc text-shape

View file

@ -15,22 +15,21 @@
[uxbox.main.refs :as refs]
[uxbox.main.streams :as streams]
[uxbox.main.user-events :as uev]
[uxbox.main.geom :as geom]
[uxbox.main.data.projects :as dp]
[uxbox.main.data.workspace :as dw]
[uxbox.main.data.workspace :as udw]
[uxbox.main.data.shapes :as uds]
[uxbox.main.ui.keyboard :as kbd]
[uxbox.main.ui.shapes :as uus]
[uxbox.main.ui.shapes.selection :refer (selection-handlers)]
[uxbox.main.ui.shapes.selection :refer [selection-handlers]]
[uxbox.main.ui.workspace.scroll :as scroll]
[uxbox.main.ui.workspace.drawarea :refer (draw-area)]
[uxbox.main.ui.workspace.ruler :refer (ruler)]
[uxbox.main.ui.workspace.selrect :refer (selrect)]
[uxbox.main.ui.workspace.grid :refer (grid)]
[uxbox.main.ui.workspace.drawarea :refer [draw-area]]
[uxbox.main.ui.workspace.ruler :refer [ruler]]
[uxbox.main.ui.workspace.grid :refer [grid]]
[uxbox.util.geom.point :as gpt]
[uxbox.util.dom :as dom]
[uxbox.util.data :refer (parse-int)]
[uxbox.util.mixins :as mx :include-macros true]
[uxbox.util.rlocks :as rlocks])
[uxbox.util.data :refer [parse-int]]
[uxbox.util.mixins :as mx :include-macros true])
(:import goog.events.EventType))
;; --- Background
@ -59,6 +58,23 @@
[:span {:alt "y"}
(str "Y: " (:y coords "-"))]]))
;; --- Selection Rect
(def selrect-ref
(-> (l/key :selrect)
(l/derive refs/workspace)))
(mx/defc selrect
{:mixins [mx/static mx/reactive]}
[]
(when-let [rect (mx/react selrect-ref)]
(let [{:keys [x1 y1 width height]} (geom/size rect)]
[:rect.selection-rect
{:x x1
:y y1
:width width
:height height}])))
;; --- Cursor tooltip
(defn- get-shape-tooltip
@ -137,12 +153,8 @@
:shift? shift?
:ctrl? ctrl?}]
(st/emit! (uev/keyboard-event :down key ctrl? shift?))
;; TODO: remove (deprecated)
#_(rx/push! streams/events-b [:key/down opts])
(when (kbd/space? event)
(st/emit! (dw/start-viewport-positioning)))))
#_(rlocks/acquire! :workspace/scroll)
(st/emit! (udw/start-viewport-positioning)))))
(on-key-up [event]
(let [key (.-keyCode event)
@ -152,10 +164,8 @@
:shift? shift?
:ctrl? ctrl?}]
(when (kbd/space? event)
(st/emit! (dw/stop-viewport-positioning)))
(st/emit! (uev/keyboard-event :up key ctrl? shift?))
;; TODO: remove (deprecated)
#_(rx/push! streams/events-b [:key/up opts])))
(st/emit! (udw/stop-viewport-positioning)))
(st/emit! (uev/keyboard-event :up key ctrl? shift?))))
(on-mousemove [event]
(let [wpt (gpt/point (.-clientX event)
@ -169,9 +179,7 @@
:window-coords wpt
:viewport-coords vpt
:canvas-coords cpt}]
(st/emit! (uev/pointer-event wpt vpt cpt ctrl? shift?))
;; TODO: remove (deprecated)
#_(rx/push! streams/mouse-b event)))]
(st/emit! (uev/pointer-event wpt vpt cpt ctrl? shift?))))]
(let [key1 (events/listen js/document EventType.MOUSEMOVE on-mousemove)
key2 (events/listen js/document EventType.KEYDOWN on-key-down)
@ -207,15 +215,10 @@
shift? (kbd/shift? event)
opts {:shift? shift?
:ctrl? ctrl?}]
(st/emit! (uev/mouse-event :down ctrl? shift?))
;; TODO: remove (deprecated)
#_(rx/push! streams/events-b [:mouse/down opts]))
(if (:drawing workspace)
(rlocks/acquire! :ui/draw)
(do
(when (seq (:selected workspace))
(rlocks/release! :shape/edition))
(rlocks/acquire! :ui/selrect))))
(st/emit! (uev/mouse-event :down ctrl? shift?)))
(if-let [object (:drawing workspace)]
(st/emit! (udw/start-drawing object))
(st/emit! (udw/start-selrect))))
(on-context-menu [event]
(dom/prevent-default event)
(dom/stop-propagation event)
@ -223,36 +226,28 @@
shift? (kbd/shift? event)
opts {:shift? shift?
:ctrl? ctrl?}]
(st/emit! (uev/mouse-event :context-menu ctrl? shift?))
;; TODO: remove (deprecated)
#_(rx/push! streams/events-b [:mouse/right-click opts])))
(st/emit! (uev/mouse-event :context-menu ctrl? shift?))))
(on-mouse-up [event]
(dom/stop-propagation event)
(let [ctrl? (kbd/ctrl? event)
shift? (kbd/shift? event)
opts {:shift? shift?
:ctrl? ctrl?}]
(st/emit! (uev/mouse-event :up ctrl? shift?))
;; TODO: remove (deprecated)
#_(rx/push! streams/events-b [:mouse/up])))
(st/emit! (uev/mouse-event :up ctrl? shift?))))
(on-click [event]
(dom/stop-propagation event)
(let [ctrl? (kbd/ctrl? event)
shift? (kbd/shift? event)
opts {:shift? shift?
:ctrl? ctrl?}]
(st/emit! (uev/mouse-event :click ctrl? shift?))
;; TODO: remove (deprecated)
#_(rx/push! streams/events-b [:mouse/click opts])))
(st/emit! (uev/mouse-event :click ctrl? shift?))))
(on-double-click [event]
(dom/stop-propagation event)
(let [ctrl? (kbd/ctrl? event)
shift? (kbd/shift? event)
opts {:shift? shift?
:ctrl? ctrl?}]
(st/emit! (uev/mouse-event :double-click ctrl? shift?))
;; TODO: remove (deprecated)
#_(rx/push! streams/events-b [:mouse/double-click opts])))]
(st/emit! (uev/mouse-event :double-click ctrl? shift?))))]
[:div
(coordinates)
(when tooltip

View file

@ -8,14 +8,13 @@
"Draw interaction and component."
(:require [beicon.core :as rx]
[potok.core :as ptk]
[lentes.core :as l]
[uxbox.util.mixins :as mx :include-macros true]
[uxbox.util.rlocks :as rlocks]
[uxbox.main.store :as st]
[uxbox.main.constants :as c]
[uxbox.main.refs :as refs]
[uxbox.main.streams :as streams]
[uxbox.main.workers :as uwrk]
[uxbox.main.user-events :as uev]
[uxbox.main.data.workspace :as udw]
[uxbox.main.data.shapes :as uds]
[uxbox.main.ui.shapes :as shapes]
@ -24,67 +23,36 @@
[uxbox.util.geom.path :as path]
[uxbox.util.dom :as dom]))
;; --- State
;; --- Refs
(defonce drawing-stoper (rx/subject))
(defonce drawing-shape (atom nil))
(defonce drawing-position (atom nil))
(def drawing-shape
(-> (l/key :drawing)
(l/derive refs/workspace)))
(def ^:private canvas-coords
(gpt/point c/canvas-start-x
c/canvas-start-y))
;; --- Components
;; --- Draw Area (Component)
(declare watch-draw-actions)
(declare on-init-draw)
(defn- watch-draw-actions
[]
(let [stream (->> (rx/map first rlocks/stream)
(rx/filter #(= % :ui/draw)))]
(rx/subscribe stream on-init-draw)))
(defn- draw-area-will-mount
[own]
(assoc own ::sub (watch-draw-actions)))
(defn- draw-area-will-unmount
[own]
(.close (::sub own))
(dissoc own ::sub))
(declare generic-shape-draw-area)
(declare path-shape-draw-area)
(declare generic-draw-area)
(declare path-draw-area)
(mx/defc draw-area
{:will-mount draw-area-will-mount
:will-unmount draw-area-will-unmount
:mixins [mx/static mx/reactive]}
{:mixins [mx/static mx/reactive]}
[]
(let [shape (mx/react drawing-shape)
position (mx/react drawing-position)]
(when shape
(if (= (:type shape) :path)
(path-shape-draw-area shape)
(generic-shape-draw-area shape position)))))
(when-let [shape (mx/react drawing-shape)]
(if (= (:type shape) :path)
(path-draw-area shape)
(generic-draw-area shape))))
(mx/defc generic-shape-draw-area
[shape position]
(if position
(-> (assoc shape :drawing? true)
(geom/resize position)
(shapes/render-component))
(-> (assoc shape :drawing? true)
(shapes/render-component))))
(mx/defc generic-draw-area
[shape]
(-> (assoc shape :drawing? true)
(shapes/render-component)))
(mx/defc path-shape-draw-area
(mx/defc path-draw-area
[{:keys [points] :as shape}]
(letfn [(on-click [event]
(dom/stop-propagation event)
(swap! drawing-shape drop-last-point)
(st/emit! (udw/set-tooltip nil))
(rx/push! drawing-stoper true))
(st/emit! (udw/set-tooltip nil)
(udw/close-drawing-path)))
(on-mouse-enter [event]
(st/emit! (udw/set-tooltip "Click to close the path")))
(on-mouse-leave [event]
@ -93,227 +61,14 @@
(let [points (:points shape)
points (vec (butlast points))]
(assoc shape :points points :close? true)))]
(let [{:keys [x y]} (first points)]
(when-let [{:keys [x y]} (first points)]
[:g
(-> (assoc shape :drawing? true)
(shapes/render-component))
(when-not (:free shape)
[:circle.close-bezier {:cx x
:cy y
:r 5
:on-click on-click
:on-mouse-enter on-mouse-enter
:on-mouse-leave on-mouse-leave}])])))
;; --- Drawing Initialization
(declare on-init-draw-icon)
(declare on-init-draw-path)
(declare on-init-draw-free-path)
(declare on-init-draw-generic)
(defn- on-init-draw
"Function execution when draw shape operation is requested.
This is a entry point for the draw interaction."
[]
(when-let [shape (:drawing @refs/workspace)]
(case (:type shape)
:icon (on-init-draw-icon shape)
:image (on-init-draw-icon shape)
:path (if (:free shape)
(on-init-draw-free-path shape)
(on-init-draw-path shape))
(on-init-draw-generic shape))))
;; --- Icon Drawing
(defn- on-init-draw-icon
[{:keys [metadata] :as shape}]
(let [{:keys [x y]} (gpt/divide @refs/canvas-mouse-position @refs/selected-zoom)
{:keys [width height]} metadata
proportion (/ width height)
props {:x1 x
:y1 y
:x2 (+ x 200)
:y2 (+ y (/ 200 proportion))}
shape (geom/setup shape props)]
(st/emit! (uds/add-shape shape)
(udw/select-for-drawing nil)
(uds/select-first-shape))
(rlocks/release! :ui/draw)))
;; --- Path Drawing
(def ^:private immanted-zones
(let [transform #(vector (- % 7) (+ % 7) %)]
(concat
(mapv transform (range 0 181 15))
(mapv (comp transform -) (range 0 181 15)))))
(defn- align-position
[angle pos]
(reduce (fn [pos [a1 a2 v]]
(if (< a1 angle a2)
(reduced (gpt/update-angle pos v))
pos))
pos
immanted-zones))
(defn- translate-to-canvas
[point]
(let [zoom @refs/selected-zoom
ccords (gpt/multiply canvas-coords zoom)]
(-> point
(gpt/subtract ccords)
(gpt/divide zoom))))
(defn- conditional-align
[point]
(if @refs/selected-alignment
(uwrk/align-point point)
(rx/of point)))
(defn- on-init-draw-path
[shape]
(letfn [(stoper-event? [{:keys [type shift] :as event}]
(or (and (uev/mouse-event? event)
(or (and (= type :double-click) shift)
(= type :context-menu)))
(and (uev/keyboard-event? event)
(= type :down)
(= 13 (:key event)))))
(new-point-event? [[type opts]]
(and (= type :mouse/click)
(false? (:shift? opts))))]
(let [mouse (->> (rx/sample 10 streams/viewport-mouse-position)
(rx/mapcat conditional-align)
(rx/map translate-to-canvas))
stoper (->> (rx/merge
(rx/take 1 drawing-stoper)
(rx/filter stoper-event? streams/events))
(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 streams/mouse-position-ctrl))
ptstream (->> (rx/take-until stoper streams/events)
(rx/filter new-point-event?)
(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 points] :as shape} point index]
(let [point (gpt/point point)
points (:points shape)]
(assoc-in shape [:points index] point)))
(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-assisted-draw [point]
(let [center (get-in @drawing-shape [:points (dec @counter)])
point (as-> point $
(gpt/subtract $ center)
(align-position (gpt/angle $) $)
(gpt/add $ center))]
(->> (update-point @drawing-shape point @counter)
(reset! drawing-shape))))
(on-free-draw [point]
(->> (update-point @drawing-shape point @counter)
(reset! drawing-shape)))
(on-draw [[point ctrl?]]
(if ctrl?
(on-assisted-draw point)
(on-free-draw point)))
(on-end []
(let [shape @drawing-shape]
(st/emit! (uds/add-shape shape)
(udw/select-for-drawing nil)
(uds/select-first-shape))
(reset! drawing-shape nil)
(reset! drawing-position 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-free-path
[shape]
(let [mouse (->> (rx/sample 10 streams/viewport-mouse-position)
(rx/mapcat conditional-align)
(rx/map translate-to-canvas))
stoper (->> streams/events
(rx/filter uev/mouse-up?)
(rx/take 1))
stream (rx/take-until stoper mouse)]
(letfn [(simplify-shape [{:keys [points] :as shape}]
(let [prevnum (count points)
points (path/simplify points 0.2)]
(println "path simplification: previous=" prevnum
" current=" (count points))
(assoc shape :points points)))
(on-draw [point]
(let [point (gpt/point point)
shape (-> (or @drawing-shape shape)
(update :points conj point))]
(reset! drawing-shape shape)))
(on-end []
(let [shape (simplify-shape @drawing-shape)]
(st/emit! (uds/add-shape shape)
(udw/select-for-drawing nil)
(uds/select-first-shape))
(reset! drawing-shape nil)
(reset! drawing-position nil)
(rlocks/release! :ui/draw)))]
(rx/subscribe stream on-draw nil on-end))))
(defn- on-init-draw-generic
[shape]
(let [mouse (->> streams/viewport-mouse-position
(rx/mapcat conditional-align)
(rx/map translate-to-canvas))
stoper (->> streams/events
(rx/filter uev/mouse-up?)
(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 streams/mouse-position-ctrl))]
(letfn [(on-start [{:keys [x y] :as pt}]
(let [shape (geom/setup shape {:x1 x :y1 y :x2 x :y2 y})]
(reset! drawing-shape shape)))
(on-draw [[pt ctrl?]]
(reset! drawing-position (assoc pt :lock ctrl?)))
(on-end []
(let [shape @drawing-shape
shpos @drawing-position
shape (geom/resize shape shpos)]
(st/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-start)
(rx/subscribe stream on-draw nil on-end))))
:cy y
:r 5
:on-click on-click
:on-mouse-enter on-mouse-enter
:on-mouse-leave on-mouse-leave}])])))

View file

@ -11,7 +11,6 @@
[potok.core :as ptk]
[uxbox.main.refs :as refs]
[uxbox.util.mixins :as mx :include-macros true]
[uxbox.util.rlocks :as rlocks]
[uxbox.util.dom :as dom]
[uxbox.util.geom.point :as gpt]))

View file

@ -1,112 +0,0 @@
;; 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) 2015-2017 Andrey Antukh <niwi@niwi.nz>
;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
(ns uxbox.main.ui.workspace.selrect
"Mouse selection interaction and component."
(:require [beicon.core :as rx]
[potok.core :as ptk]
[uxbox.main.store :as st]
[uxbox.main.constants :as c]
[uxbox.main.refs :as refs]
[uxbox.main.streams :as streams]
[uxbox.main.user-events :as uev]
[uxbox.main.geom :as geom]
[uxbox.main.data.workspace :as dw]
[uxbox.main.data.shapes :as uds]
[uxbox.util.mixins :as mx :include-macros true]
[uxbox.util.rlocks :as rlocks]))
(defonce position (atom nil))
;; --- Selrect (Component)
(declare selrect->rect)
(declare watch-selrect-actions)
(defn- will-mount
[own]
(assoc own ::sub (watch-selrect-actions)))
(defn- will-unmount
[own]
(.close (::sub own))
(dissoc own ::sub))
(mx/defc selrect
{:will-mount will-mount
:will-unmount will-unmount
:mixins [mx/static mx/reactive]}
[]
(when-let [data (mx/react position)]
(let [{:keys [x1 y1 width height]} (geom/size (selrect->rect data))]
[:rect.selection-rect
{:x x1
:y y1
:width width
:height height}])))
;; --- Interaction
(defn- selrect->rect
[{:keys [start current] :as data}]
(let [start-x (min (:x start) (:x current))
start-y (min (:y start) (:y current))
end-x (max (:x start) (:x current))
end-y (max (:y start) (:y current))]
{:x1 start-x
:y1 start-y
:x2 end-x
:y2 end-y
:type :rect}))
(defn- translate-to-canvas
"Translate the given rect to the canvas coordinates system."
[rect]
(let [zoom @refs/selected-zoom
startx (* c/canvas-start-x zoom)
starty (* c/canvas-start-y zoom)]
(assoc rect
:x1 (/ (- (:x1 rect) startx) zoom)
:y1 (/ (- (:y1 rect) starty) zoom)
:x2 (/ (- (:x2 rect) startx) zoom)
:y2 (/ (- (:y2 rect) starty) zoom))))
(declare on-start)
(defn- watch-selrect-actions
[]
(let [stream (->> (rx/map first rlocks/stream)
(rx/filter #(= % :ui/selrect)))]
(rx/subscribe stream on-start)))
(defn- on-move
"Function executed on each mouse movement while selrect
interaction is active."
[pos]
(swap! position assoc :current pos))
(defn- on-complete
"Function executed when the selection rect
interaction is terminated."
[]
(let [rect (-> (selrect->rect @position)
(translate-to-canvas))]
(st/emit! (uds/deselect-all)
(uds/select-shapes-by-selrect rect))
(rlocks/release! :ui/selrect)
(reset! position nil)))
(defn- on-start
"Function execution when selrect action is started."
[]
(let [stoper (->> streams/events
(rx/filter uev/mouse-up?)
(rx/take 1))
stream (rx/take-until stoper streams/viewport-mouse-position)
pos @refs/viewport-mouse-position]
(reset! position {:start pos :current pos})
(rx/subscribe stream on-move nil on-complete)))

View file

@ -12,6 +12,7 @@
[uxbox.main.store :as st]
[uxbox.main.refs :as refs]
[uxbox.main.data.workspace :as dw]
[uxbox.main.user-events :as uev]
[uxbox.builtins.icons :as i]
[uxbox.util.i18n :refer (tr)]
[uxbox.util.router :as r]
@ -82,7 +83,8 @@
(defn- select-for-draw
[shape]
(st/emit! (dw/select-for-drawing shape)))
(st/emit! ::uev/interrupt
(dw/select-for-drawing shape)))
(mx/defc draw-toolbox
{:mixins [mx/static mx/reactive]}