182 lines
5.7 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) KALEIDOS INC Sucursal en España SL
(ns app.main.data.workspace.guides
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.files.changes-builder :as pcb]
[app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh]
[app.common.types.page :as ctp]
[app.main.data.changes :as dwc]
[app.main.data.event :as ev]
[app.main.data.helpers :as dsh]
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(defn update-guides
[{:keys [id] :as guide}]
(dm/assert!
"expected valid guide"
(ctp/valid-guide? guide))
(ptk/reify ::update-guides
ev/Event
(-data [_]
(assoc guide ::ev/name "update-guide"))
ptk/WatchEvent
(watch [it state _]
(let [page (dsh/lookup-page state)
changes
(-> (pcb/empty-changes it)
(pcb/with-page page)
(pcb/set-guide id guide))]
(rx/of (dwc/commit-changes changes))))))
(defn remove-guide
[{:keys [id] :as guide}]
(dm/assert!
"expected valid guide"
(ctp/valid-guide? guide))
(ptk/reify ::remove-guide
ev/Event
(-data [_] guide)
ptk/UpdateEvent
(update [_ state]
(let [sdisj (fnil disj #{})]
(update-in state [:workspace-guides :hover] sdisj id)))
ptk/WatchEvent
(watch [it state _]
(let [page (dsh/lookup-page state)
changes
(-> (pcb/empty-changes it)
(pcb/with-page page)
(pcb/set-guide id nil))]
(rx/of (dwc/commit-changes changes))))))
(defn remove-guides
[ids]
(dm/assert!
"expected a set of ids"
(every? uuid? ids))
(ptk/reify ::remove-guides
ptk/WatchEvent
(watch [_ state _]
(let [{:keys [guides] :as page} (dsh/lookup-page state)
guides (-> (select-keys guides ids) (vals))]
(rx/from (mapv remove-guide guides))))))
(defn remove-frame-guides
[frame-ids]
(assert (every? uuid? frame-ids) "expected a coll of uuids")
(ptk/reify ::remove-frame-guides
ptk/UpdateEvent
(update [_ state]
(let [{:keys [guides]} (dsh/lookup-page state)
frame-ids-set (set frame-ids)
guide-ids (into #{}
(comp (filter #(contains? frame-ids-set (:frame-id %)))
d/xf:map-id)
(vals guides))]
(update-in state [:workspace-guides :hover]
(fn [hover] (reduce disj (or hover #{}) guide-ids)))))
ptk/WatchEvent
(watch [it state _]
(let [{:keys [guides] :as page} (dsh/lookup-page state)
frame-ids-set (set frame-ids)
to-remove (filter #(contains? frame-ids-set (:frame-id %)) (vals guides))
changes (reduce
(fn [acc {:keys [id]}]
(pcb/set-guide acc id nil))
(-> (pcb/empty-changes it)
(pcb/with-page page))
to-remove)]
(rx/of (dwc/commit-changes changes))))))
(defmethod ptk/resolve ::move-frame-guides
[_ args]
(dm/assert!
"expected a coll of uuids"
(every? uuid? (:ids args)))
(ptk/reify ::move-frame-guides
ptk/WatchEvent
(watch [_ state _]
(let [ids (:ids args)
object-modifiers (:modifiers args)
object-transforms (:transforms args)
objects (dsh/lookup-page-objects state)
is-frame? (fn [id] (= :frame (get-in objects [id :type])))
frame-ids? (into #{} (filter is-frame?) ids)
build-move-event
(fn [guide]
(let [frame-id (:frame-id guide)
frame (get objects frame-id)
modifier (get-in object-modifiers [frame-id :modifiers])
transform (get object-transforms frame-id)
frame'
(cond-> frame
(some? modifier)
(gsh/transform-shape modifier)
(some? transform)
(gsh/apply-transform transform))
moved (gpt/to-vec (gpt/point (:x frame) (:y frame))
(gpt/point (:x frame') (:y frame')))
guide (update guide :position + (get moved (:axis guide)))]
(update-guides guide)))
guides (-> state dsh/lookup-page :guides vals)]
(->> guides
(filter (comp frame-ids? :frame-id))
(map build-move-event)
(rx/from))))))
(defn update-guide-color
[guide-id color]
(ptk/reify ::update-guide-color
ptk/WatchEvent
(watch [it state _]
(let [{:keys [guides] :as page} (dsh/lookup-page state)
guide (get guides guide-id)]
(when (some? guide)
(let [updated-guide (if (some? color)
(assoc guide :color color)
(dissoc guide :color))
changes
(-> (pcb/empty-changes it)
(pcb/with-page page)
(pcb/set-guide guide-id updated-guide))]
(rx/of (dwc/commit-changes changes))))))))
(defn set-hover-guide
[id hover?]
(ptk/reify ::set-hover-guide
ptk/UpdateEvent
(update [_ state]
(let [sconj (fnil conj #{})
sdisj (fnil disj #{})]
(if hover?
(update-in state [:workspace-guides :hover] sconj id)
(update-in state [:workspace-guides :hover] sdisj id))))))