2021-05-07 13:13:58 +02:00

167 lines
5.6 KiB
Clojure

;; 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) UXBOX Labs SL
(ns app.main.data.workspace.path.selection
(:require
[app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh]
[app.main.data.workspace.common :as dwc]
[app.main.data.workspace.path.state :as st]
[app.main.streams :as ms]
[beicon.core :as rx]
[potok.core :as ptk]))
(defn path-pointer-enter [position]
(ptk/reify ::path-pointer-enter
ptk/UpdateEvent
(update [_ state]
(let [id (st/get-path-id state)]
(update-in state [:workspace-local :edit-path id :hover-points] (fnil conj #{}) position)))))
(defn path-pointer-leave [position]
(ptk/reify ::path-pointer-leave
ptk/UpdateEvent
(update [_ state]
(let [id (st/get-path-id state)]
(update-in state [:workspace-local :edit-path id :hover-points] disj position)))))
(defn path-handler-enter [index prefix]
(ptk/reify ::path-handler-enter
ptk/UpdateEvent
(update [_ state]
(let [id (st/get-path-id state)]
(update-in state [:workspace-local :edit-path id :hover-handlers] (fnil conj #{}) [index prefix])))))
(defn path-handler-leave [index prefix]
(ptk/reify ::path-handler-leave
ptk/UpdateEvent
(update [_ state]
(let [id (st/get-path-id state)]
(update-in state [:workspace-local :edit-path id :hover-handlers] disj [index prefix])))))
(defn select-node-area [shift?]
(ptk/reify ::select-node-area
ptk/UpdateEvent
(update [_ state]
(let [selrect (get-in state [:workspace-local :selrect])
id (get-in state [:workspace-local :edition])
content (get-in state (st/get-path state :content))
selected-point? #(gsh/has-point-rect? selrect %)
selected-points (get-in state [:workspace-local :edit-path id :selected-points])
positions (into (if shift? selected-points #{})
(comp (filter #(not (= (:command %) :close-path)))
(map (comp gpt/point :params))
(filter selected-point?))
content)]
(cond-> state
(some? id)
(assoc-in [:workspace-local :edit-path id :selected-points] positions))))))
(defn select-node [position shift? kk]
(ptk/reify ::select-node
ptk/UpdateEvent
(update [_ state]
(let [id (get-in state [:workspace-local :edition])
selected-points (or (get-in state [:workspace-local :edit-path id :selected-points]) #{})
selected-points (cond
(and shift? (contains? selected-points position))
(disj selected-points position)
shift?
(conj selected-points position)
:else
#{position})]
(cond-> state
(some? id)
(assoc-in [:workspace-local :edit-path id :selected-points] selected-points))))))
(defn deselect-node [position shift?]
(ptk/reify ::deselect-node
ptk/UpdateEvent
(update [_ state]
(let [id (get-in state [:workspace-local :edition])]
(-> state
(update-in [:workspace-local :edit-path id :selected-points] (fnil disj #{}) position))))))
(defn add-to-selection-handler [index type]
(ptk/reify ::add-to-selection-handler
ptk/UpdateEvent
(update [_ state]
state)))
(defn add-to-selection-node [index]
(ptk/reify ::add-to-selection-node
ptk/UpdateEvent
(update [_ state]
state)))
(defn remove-from-selection-handler [index]
(ptk/reify ::remove-from-selection-handler
ptk/UpdateEvent
(update [_ state]
state)))
(defn remove-from-selection-node [index]
(ptk/reify ::remove-from-selection-handler
ptk/UpdateEvent
(update [_ state]
state)))
(defn deselect-all []
(ptk/reify ::deselect-all
ptk/UpdateEvent
(update [_ state]
(let [id (st/get-path-id state)]
(-> state
(assoc-in [:workspace-local :edit-path id :selected-points] #{}))))))
(defn update-area-selection
[rect]
(ptk/reify ::update-area-selection
ptk/UpdateEvent
(update [_ state]
(assoc-in state [:workspace-local :selrect] rect))))
(defn clear-area-selection
[]
(ptk/reify ::clear-area-selection
ptk/UpdateEvent
(update [_ state]
(update state :workspace-local dissoc :selrect))))
(defn handle-selection
[shift?]
(letfn [(valid-rect? [{width :width height :height}]
(or (> width 10) (> height 10)))]
(ptk/reify ::handle-selection
ptk/WatchEvent
(watch [_ state stream]
(let [stop? (fn [event] (or (dwc/interrupt? event) (ms/mouse-up? event)))
stoper (->> stream (rx/filter stop?))
from-p @ms/mouse-position]
(rx/concat
(->> ms/mouse-position
(rx/take-until stoper)
(rx/map #(gsh/points->rect [from-p %]))
(rx/filter valid-rect?)
(rx/map update-area-selection))
(rx/of (select-node-area shift?)
(clear-area-selection))))))))
(defn update-selection
[point-change]
(ptk/reify ::update-selection
ptk/UpdateEvent
(update [_ state]
(let [id (st/get-path-id state)
selected-points (get-in state [:workspace-local :edit-path id :selected-points] #{})
selected-points (into #{} (map point-change) selected-points)]
(-> state
(assoc-in [:workspace-local :edit-path id :selected-points] selected-points))))))