0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-23 23:18:48 -05:00

Start use one unique stream for send user events (mouse and keyboard).

This commit is contained in:
Andrey Antukh 2017-01-15 23:01:27 +01:00
parent bc1ffc7f4f
commit 7a7059e172
No known key found for this signature in database
GPG key ID: 4DFEBCB8316A8B95
12 changed files with 225 additions and 104 deletions

View file

@ -9,6 +9,7 @@
are related to UI logic."
(:require [beicon.core :as rx]
[potok.core :as ptk]
[uxbox.main.refs :as refs]
[uxbox.main.streams :as streams]
[uxbox.util.mixins :as mx :include-macros true]
[uxbox.util.rlocks :as rlocks]
@ -23,9 +24,9 @@
[stream]
(let [stoper (->> (rx/filter stop-viewport-positioning? stream)
(rx/take 1))
reference @streams/mouse-viewport-a
reference @refs/viewport-mouse-position
dom (dom/get-element "workspace-canvas")]
(->> streams/mouse-viewport-s
(->> streams/viewport-mouse-position
(rx/take-until stoper)
(rx/map (fn [point]
(let [{:keys [x y]} (gpt/subtract point reference)

View file

@ -73,6 +73,18 @@
(-> (l/lens alignment-activated?)
(l/derive flags)))
(def canvas-mouse-position
(-> (l/in [:pointer :canvas])
(l/derive workspace)))
(def viewport-mouse-position
(-> (l/in [:pointer :viewport])
(l/derive workspace)))
(def window-mouse-position
(-> (l/in [:pointer :window])
(l/derive workspace)))

View file

@ -7,6 +7,8 @@
(ns uxbox.main.streams
"A collection of derived streams."
(:require [beicon.core :as rx]
[uxbox.main.store :as st]
[uxbox.main.user-events :as uev]
[uxbox.main.refs :as refs]
[uxbox.main.workers :as uwrk]
[uxbox.util.geom.point :as gpt]))
@ -28,40 +30,36 @@
;; --- Events
(defonce events-b (rx/subject))
(defonce events-s (rx/dedupe events-b))
(defn- user-interaction-event?
[event]
(or (uev/keyboard-event? event)
(uev/mouse-event? event)))
(defonce events
(rx/filter user-interaction-event? st/stream))
;; --- Mouse Position Stream
(defonce mouse-b (rx/subject))
(defonce mouse-s (rx/dedupe mouse-b))
(defonce mouse-position
(rx/filter uev/pointer-event? st/stream))
(defonce mouse-canvas-s
(->> mouse-s
(rx/map :canvas-coords)
(defonce canvas-mouse-position
(->> mouse-position
(rx/map :canvas)
(rx/share)))
(defonce mouse-canvas-a
(rx/to-atom mouse-canvas-s))
(defonce mouse-viewport-s
(->> mouse-s
(rx/map :viewport-coords)
(defonce viewport-mouse-position
(->> mouse-position
(rx/map :viewport)
(rx/share)))
(defonce mouse-viewport-a
(rx/to-atom mouse-viewport-s))
(defonce mouse-absolute-s
(->> mouse-s
(rx/map :window-coords)
(defonce window-mouse-position
(->> mouse-position
(rx/map :window)
(rx/share)))
(defonce mouse-absolute-a
(rx/to-atom mouse-absolute-s))
(defonce mouse-ctrl-s
(->> mouse-s
(defonce mouse-position-ctrl
(->> mouse-position
(rx/map :ctrl)
(rx/share)))
@ -69,8 +67,8 @@
[[old new]]
(gpt/subtract new old))
(defonce mouse-delta-s
(->> mouse-viewport-s
(defonce mouse-position-deltas
(->> viewport-mouse-position
(rx/sample 10)
(rx/map #(gpt/divide % @refs/selected-zoom))
(rx/mapcat (fn [point]

View file

@ -12,6 +12,7 @@
[uxbox.main.refs :as refs]
[uxbox.main.streams :as streams]
[uxbox.main.geom :as geom]
[uxbox.main.user-events :as uev]
[uxbox.main.data.shapes :as uds]
[uxbox.main.ui.keyboard :as kbd]
[uxbox.util.geom.point :as gpt]
@ -20,6 +21,8 @@
;; --- Refs
;; FIXME: use the predefined lenses under uxbox.main.lenses
(def edition-ref
(-> (l/in [:workspace :edition])
(l/derive st/state)))
@ -42,17 +45,16 @@
(rlocks/release! :shape/move)
(st/emit! (uds/apply-displacement shape)))
(on-start [shape]
(let [stoper (->> (rx/map first streams/events-s)
(rx/filter #(= % :mouse/up))
(let [stoper (->> streams/events
(rx/filter uev/mouse-up?)
(rx/take 1))
stream (->> streams/mouse-delta-s
stream (->> streams/mouse-position-deltas
(rx/take-until stoper))
on-move (partial on-move shape)
on-stop (partial on-stop shape)]
(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)))

View file

@ -15,6 +15,7 @@
[uxbox.main.refs :as refs]
[uxbox.main.streams :as streams]
[uxbox.main.workers :as uwrk]
[uxbox.main.user-events :as uev]
[uxbox.main.data.shapes :as uds]
[uxbox.main.ui.shapes.common :as scommon]
[uxbox.main.geom :as geom]
@ -213,18 +214,19 @@
(let [shape (->> (geom/shape->rect-shape shape)
(geom/size))
stoper (->> streams/events-s
(rx/map first)
(rx/filter #(= % :mouse/up))
stoper (->> streams/events
(rx/filter uev/mouse-up?)
(rx/take 1))
stream (->> streams/mouse-canvas-s
stream (->> streams/canvas-mouse-position
(rx/map #(gpt/divide % @refs/selected-zoom))
(rx/mapcat (fn [point]
(if @refs/selected-alignment
(uwrk/align-point point)
(rx/of point))))
(rx/take-until stoper)
(rx/with-latest-from vector streams/mouse-ctrl-s)
(rx/with-latest-from vector streams/mouse-position-ctrl)
(rx/scan accumulate-width shape)
(rx/map (partial calculate-ratio shape)))]
(rlocks/acquire! :shape/resize)
@ -320,11 +322,11 @@
(st/emit! (uds/update-path shape-id index delta)))
(on-end []
(rlocks/release! :shape/resize))]
(let [stoper (->> streams/events-s
(let [stoper (->> streams/events
(rx/map first)
(rx/filter #(= % :mouse/up))
(rx/take 1))
stream (rx/take-until stoper streams/mouse-delta-s)]
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)))

View file

@ -92,7 +92,7 @@
(let [prev-zoom @refs/selected-zoom
dom (mx/ref-node own "workspace-canvas")
scroll-position (scroll/get-current-position-absolute dom)
mouse-point @streams/mouse-viewport-a]
mouse-point @refs/viewport-mouse-position]
(dom/prevent-default event)
(dom/stop-propagation event)
(if (pos? (.-deltaY event))

View file

@ -14,6 +14,7 @@
[uxbox.main.constants :as c]
[uxbox.main.refs :as refs]
[uxbox.main.streams :as streams]
[uxbox.main.user-events :as uev]
[uxbox.main.data.projects :as dp]
[uxbox.main.data.workspace :as dw]
[uxbox.main.data.shapes :as uds]
@ -49,7 +50,7 @@
{:mixins [mx/reactive mx/static]}
[]
(let [zoom (mx/react refs/selected-zoom)
coords (some-> (mx/react streams/mouse-canvas-a)
coords (some-> (mx/react refs/canvas-mouse-position)
(gpt/divide zoom)
(gpt/round 0))]
[:ul.coordinates
@ -75,7 +76,7 @@
(mx/defc cursor-tooltip
{:mixins [mx/reactive mx/static]}
[tooltip]
(let [coords (mx/react streams/mouse-absolute-a)]
(let [coords (mx/react refs/window-mouse-position)]
[:span.cursor-tooltip
{:style
{:position "fixed"
@ -129,36 +130,48 @@
(gpt/subtract brect))))))
(on-key-down [event]
(let [opts {:key (.-keyCode event)
:shift? (kbd/shift? event)
:ctrl? (kbd/ctrl? event)}]
(rx/push! streams/events-b [:key/down opts])
(let [key (.-keyCode event)
ctrl? (kbd/ctrl? event)
shift? (kbd/shift? event)
opts {:key key
: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)
(on-key-up [event]
(let [opts {:key (.-keyCode event)
:shift? (kbd/shift? event)
:ctrl? (kbd/ctrl? event)}]
(let [key (.-keyCode event)
ctrl? (kbd/ctrl? event)
shift? (kbd/shift? event)
opts {:key key
:shift? shift?
:ctrl? ctrl?}]
(when (kbd/space? event)
(st/emit! (dw/stop-viewport-positioning)))
(rx/push! streams/events-b [:key/up opts])))
(st/emit! (uev/keyboard-event :up key ctrl? shift?))
;; TODO: remove (deprecated)
#_(rx/push! streams/events-b [:key/up opts])))
(on-mousemove [event]
(let [wpt (gpt/point (.-clientX event)
(.-clientY event))
vppt (translate-point-to-viewport wpt)
cvpt (translate-point-to-canvas wpt)
event {:ctrl (kbd/ctrl? event)
:shift (kbd/shift? event)
vpt (translate-point-to-viewport wpt)
cpt (translate-point-to-canvas wpt)
ctrl? (kbd/ctrl? event)
shift? (kbd/shift? event)
event {:ctrl ctrl?
:shift shift?
:window-coords wpt
:viewport-coords vppt
:canvas-coords cvpt}]
;; FIXME: refactor streams in order to use the streams/events-b
;; for all keyboard and mouse events and then derive
;; all the other from it.
(rx/push! streams/mouse-b event)))]
: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)))]
(let [key1 (events/listen js/document EventType.MOUSEMOVE on-mousemove)
key2 (events/listen js/document EventType.KEYDOWN on-key-down)
@ -190,9 +203,13 @@
zoom (or (:zoom workspace) 1)]
(letfn [(on-mouse-down [event]
(dom/stop-propagation event)
(let [opts {:shift? (kbd/shift? event)
:ctrl? (kbd/ctrl? event)}]
(rx/push! streams/events-b [:mouse/down opts]))
(let [ctrl? (kbd/ctrl? event)
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
@ -202,24 +219,40 @@
(on-context-menu [event]
(dom/prevent-default event)
(dom/stop-propagation event)
(let [opts {:shift? (kbd/shift? event)
:ctrl? (kbd/ctrl? event)}]
(rx/push! streams/events-b [:mouse/right-click opts])))
(let [ctrl? (kbd/ctrl? event)
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])))
(on-mouse-up [event]
(dom/stop-propagation event)
(let [opts {:shift? (kbd/shift? event)
:ctrl? (kbd/ctrl? event)}]
(rx/push! streams/events-b [:mouse/up])))
(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])))
(on-click [event]
(dom/stop-propagation event)
(let [opts {:shift? (kbd/shift? event)
:ctrl? (kbd/ctrl? event)}]
(rx/push! streams/events-b [:mouse/click opts])))
(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])))
(on-double-click [event]
(dom/stop-propagation event)
(let [opts {:shift? (kbd/shift? event)
:ctrl? (kbd/ctrl? event)}]
(rx/push! streams/events-b [:mouse/double-click opts])))]
(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])))]
[:div
(coordinates)
(when tooltip

View file

@ -15,6 +15,7 @@
[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]
@ -128,7 +129,7 @@
(defn- on-init-draw-icon
[{:keys [metadata] :as shape}]
(let [{:keys [x y]} (gpt/divide @streams/mouse-canvas-a @refs/selected-zoom)
(let [{:keys [x y]} (gpt/divide @refs/canvas-mouse-position @refs/selected-zoom)
{:keys [width height]} metadata
proportion (/ width height)
props {:x1 x
@ -174,29 +175,30 @@
(defn- on-init-draw-path
[shape]
(letfn [(stoper-event? [[type opts]]
(or (and (= type :key/down)
(= (:key opts) 13))
(and (= type :mouse/double-click)
(true? (:shift? opts)))
(= type :mouse/right-click)))
(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/mouse-viewport-s)
(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-s))
(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-ctrl-s))
ptstream (->> (rx/take-until stoper streams/events-s)
(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))
@ -253,12 +255,11 @@
(defn- on-init-draw-free-path
[shape]
(let [mouse (->> (rx/sample 10 streams/mouse-viewport-s)
(let [mouse (->> (rx/sample 10 streams/viewport-mouse-position)
(rx/mapcat conditional-align)
(rx/map translate-to-canvas))
stoper (->> streams/events-s
(rx/map first)
(rx/filter #(= % :mouse/up))
stoper (->> streams/events
(rx/filter uev/mouse-up?)
(rx/take 1))
stream (rx/take-until stoper mouse)]
(letfn [(simplify-shape [{:keys [points] :as shape}]
@ -287,17 +288,16 @@
(defn- on-init-draw-generic
[shape]
(let [mouse (->> streams/mouse-viewport-s
(let [mouse (->> streams/viewport-mouse-position
(rx/mapcat conditional-align)
(rx/map translate-to-canvas))
stoper (->> streams/events-s
(rx/map first)
(rx/filter #(= % :mouse/up))
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-ctrl-s))]
(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})]

View file

@ -2,8 +2,8 @@
;; 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-2016 Andrey Antukh <niwi@niwi.nz>
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
;; 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.ruler
(:require [sablono.core :as html :refer-macros [html]]
@ -75,10 +75,10 @@
(on-value-aligned pos)
(on-value-simple pos)))]
(let [stream (->> streams/mouse-absolute-s
(let [stream (->> streams/window-mouse-position
(rx/filter #(:active @local))
(rx/map #(resolve-position own %))
(rx/with-latest-from vector streams/mouse-ctrl-s))
(rx/with-latest-from vector streams/mouse-position-ctrl))
sub (rx/on-value stream on-value)]
(assoc own ::sub sub))))

View file

@ -15,6 +15,8 @@
[uxbox.util.dom :as dom]
[uxbox.util.geom.point :as gpt]))
;; FIXME: revisit this ns in order to find a better location for its functions
(defn set-scroll-position
[dom position]
(set! (.-scrollLeft dom) (:x position))

View file

@ -13,6 +13,7 @@
[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]
@ -102,11 +103,10 @@
(defn- on-start
"Function execution when selrect action is started."
[]
(let [stoper (->> streams/events-s
(rx/map first)
(rx/filter #(= % :mouse/up))
(let [stoper (->> streams/events
(rx/filter uev/mouse-up?)
(rx/take 1))
stream (rx/take-until stoper streams/mouse-viewport-s)
pos @streams/mouse-viewport-a]
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

@ -0,0 +1,71 @@
;; 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>
(ns uxbox.main.user-events
"Workspace user (keyboard, mouse and pointer) events."
(:require [beicon.core :as rx]
[potok.core :as ptk]
[uxbox.util.geom.point :as gpt]))
(defrecord KeyboardEvent [type key shift ctrl])
(defrecord MouseEvent [type ctrl shift])
(defrecord PointerEvent [window
viewport
canvas
ctrl
shift]
ptk/UpdateEvent
(update [it state]
(assoc-in state [:workspace :pointer] it)))
(defn keyboard-event
[type key ctrl shift]
{:pre [(keyword? type)
(integer? key)
(boolean? ctrl)
(boolean? shift)]}
(KeyboardEvent. type key ctrl shift))
(defn keyboard-event?
[v]
(instance? KeyboardEvent v))
(defn mouse-event
[type ctrl shift]
{:pre [(keyword? type)
(boolean? ctrl)
(boolean? shift)]}
(MouseEvent. type ctrl shift))
(defn mouse-event?
[v]
(instance? MouseEvent v))
(defn mouse-up?
[v]
(and (mouse-event? v)
(= :up (:type v))))
;; TODO: add spec
(defn pointer-event
[window viewport canvas ctrl shift]
{:pre [(gpt/point? window)
(gpt/point? viewport)
(or (gpt/point? canvas)
(nil? canvas))
(boolean? ctrl)
(boolean? shift)]}
(PointerEvent. window
viewport
canvas
ctrl
shift))
(defn pointer-event?
[v]
(instance? PointerEvent v))