From 76cd1a48b849248b7a05910ff067df11c1366eab Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 26 Jan 2016 23:10:45 +0200 Subject: [PATCH] Refactor interactions in workspace. --- src/uxbox/ui/workspace/base.cljs | 77 ++++----------------- src/uxbox/ui/workspace/canvas.cljs | 19 +++-- src/uxbox/ui/workspace/canvas/movement.cljs | 22 ++++++ src/uxbox/ui/workspace/canvas/selrect.cljs | 65 ++++++++++++++++- 4 files changed, 107 insertions(+), 76 deletions(-) create mode 100644 src/uxbox/ui/workspace/canvas/movement.cljs diff --git a/src/uxbox/ui/workspace/base.cljs b/src/uxbox/ui/workspace/base.cljs index da9c90a01..a9555c640 100644 --- a/src/uxbox/ui/workspace/base.cljs +++ b/src/uxbox/ui/workspace/base.cljs @@ -72,12 +72,22 @@ (defonce scroll-left (rx/to-atom scroll-left-s)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Mouse Position Stream +;; Interactions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(defonce shapes-dragging? (atom false)) -(defonce selrect-dragging? (atom false)) -(defonce selrect-pos (atom nil)) +;; (defonce shapes-dragging? (atom false)) +;; (defonce selrect-dragging? (atom false)) +(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-s @@ -109,65 +119,6 @@ (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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/src/uxbox/ui/workspace/canvas.cljs b/src/uxbox/ui/workspace/canvas.cljs index 54a722f40..dab3cc2de 100644 --- a/src/uxbox/ui/workspace/canvas.cljs +++ b/src/uxbox/ui/workspace/canvas.cljs @@ -16,6 +16,7 @@ [uxbox.ui.mixins :as mx] [uxbox.ui.dom :as dom] [uxbox.ui.workspace.base :as wb] + [uxbox.ui.workspace.canvas.movement] [uxbox.ui.workspace.canvas.selection :refer (shapes-selection)] [uxbox.ui.workspace.canvas.selrect :refer (selrect)] [uxbox.ui.workspace.grid :refer (grid)] @@ -51,9 +52,6 @@ local (:rum/local own)] (letfn [(on-mouse-down [event] (when-not (:blocked item) - ;; (let [local (:rum/local own)] - ;; (swap! local assoc :init-coords [x y]) - ;; (reset! wb/shapes-dragging? true)) (cond (and group (:locked (sh/resolve-parent item))) nil @@ -62,15 +60,14 @@ (do (dom/stop-propagation event) (swap! local assoc :init-coords [x y]) - (reset! wb/shapes-dragging? true) - + (wb/emit-interaction! :shape/movement) (rs/emit! (dw/select-shape id))) (and (not selected?) (not (empty? selected))) (do (dom/stop-propagation event) (swap! local assoc :init-coords [x y]) - (reset! wb/shapes-dragging? true) + #_(reset! wb/shapes-dragging? true) (if (.-ctrlKey event) (rs/emit! (dw/select-shape id)) (rs/emit! (dw/deselect-all) @@ -80,7 +77,7 @@ (do (dom/stop-propagation event) (swap! local assoc :init-coords [x y]) - (reset! wb/shapes-dragging? true))))) + (wb/emit-interaction! :shape/movement))))) (on-mouse-up [event] (cond @@ -90,7 +87,8 @@ :else (do (dom/stop-propagation event) - (reset! wb/shapes-dragging? false))))] + (wb/emit-interaction! :nothing) + )))] (html [:g.shape {:class (when selected? "selected") :on-mouse-down on-mouse-down @@ -189,11 +187,10 @@ (dom/stop-propagation event) (when-not (empty? (:selected workspace)) (rs/emit! (dw/deselect-all))) - (reset! wb/selrect-dragging? true)) + (wb/emit-interaction! :selrect/draw)) (on-mouse-up [event] (dom/stop-propagation event) - (reset! wb/shapes-dragging? false) - (reset! wb/selrect-dragging? false)) + (wb/emit-interaction! :nothing)) (on-click [event wstate] (let [mousepos @wb/mouse-position scroll-top @wb/scroll-top diff --git a/src/uxbox/ui/workspace/canvas/movement.cljs b/src/uxbox/ui/workspace/canvas/movement.cljs new file mode 100644 index 000000000..1c46461ce --- /dev/null +++ b/src/uxbox/ui/workspace/canvas/movement.cljs @@ -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)))))))) + diff --git a/src/uxbox/ui/workspace/canvas/selrect.cljs b/src/uxbox/ui/workspace/canvas/selrect.cljs index 5943816e1..c3bf282ae 100644 --- a/src/uxbox/ui/workspace/canvas/selrect.cljs +++ b/src/uxbox/ui/workspace/canvas/selrect.cljs @@ -1,5 +1,6 @@ (ns uxbox.ui.workspace.canvas.selrect "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]] [rum.core :as rum] [beicon.core :as rx] @@ -7,18 +8,23 @@ [uxbox.rstore :as rs] [uxbox.state :as st] [uxbox.shapes :as sh] + [uxbox.data.workspace :as dw] [uxbox.ui.workspace.base :as wb] [uxbox.ui.mixins :as mx] [uxbox.ui.dom :as dom])) +(defonce selrect-pos (atom nil)) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Component ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(declare selrect->rect) + (defn selrect-render [own] - (when-let [data (rum/react wb/selrect-pos)] - (let [{:keys [x y width height]} (wb/selrect->rect data)] + (when-let [data (rum/react selrect-pos)] + (let [{:keys [x y width height]} (selrect->rect data)] (html [:rect.selection-rect {:x x @@ -31,3 +37,58 @@ {:render selrect-render :name "selrect" :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)))))))