diff --git a/common/uxbox/common/geom/shapes.cljc b/common/uxbox/common/geom/shapes.cljc index e09cb4802..463d5e7b0 100644 --- a/common/uxbox/common/geom/shapes.cljc +++ b/common/uxbox/common/geom/shapes.cljc @@ -798,13 +798,13 @@ ([frame shape] (let [new-shape (if (:modifiers shape) - (as-> (case (:type shape) - (:curve :path) (transform-path-shape shape) - (transform-rect-shape shape)) $ - (dissoc $ :modifiers)) + (-> (case (:type shape) + (:curve :path) (transform-path-shape shape) + (transform-rect-shape shape)) + (dissoc :modifiers)) shape)] - (-> new-shape - (translate-to-frame frame))))) + (cond-> new-shape + frame (translate-to-frame frame))))) (defn transform-matrix diff --git a/common/uxbox/common/pages.cljc b/common/uxbox/common/pages.cljc index bee30ed4e..b648a2f10 100644 --- a/common/uxbox/common/pages.cljc +++ b/common/uxbox/common/pages.cljc @@ -15,6 +15,8 @@ [uxbox.common.pages-helpers :as cph] [uxbox.common.exceptions :as ex] [uxbox.common.geom.shapes :as geom] + [uxbox.common.geom.matrix :as gmt] + [uxbox.common.geom.point :as gpt] [uxbox.common.spec :as us] [uxbox.common.uuid :as uuid])) @@ -382,33 +384,53 @@ (seq shapes) ; Recursive delete all dependend objects (as-> $ (reduce #(or (process-change %1 {:type :del-obj :id %2}) %1) $ shapes)))))) + +(defn rotation-modifiers + [center shape angle] + (let [displacement (let [shape-center (geom/center shape)] + (-> (gmt/matrix) + (gmt/rotate angle center) + (gmt/rotate (- angle) shape-center)))] + {:rotation angle + :displacement displacement})) + (defmethod process-change :reg-objects [data {:keys [shapes]}] - (let [objects (:objects data)] - (loop [shapes shapes data data] - (if (seq shapes) - (let [item (get objects (first shapes))] - (if (= :group (:type item)) - (recur - (rest shapes) - (update-in data [:objects (:id item)] - (fn [{:keys [shapes] :as obj}] - (let [shapes (->> shapes - (map (partial get objects)) - (filter identity))] - (if (seq shapes) - (let [selrect (geom/selection-rect shapes)] - (as-> obj $ - (assoc $ - :x (:x selrect) - :y (:y selrect) - :width (:width selrect) - :height (:height selrect)) - (assoc $ :points (geom/shape->points $)) - (assoc $ :selrect (geom/points->selrect (:points $))))) - obj))))) - (recur (rest shapes) data))) - data)))) + (let [objects (:objects data) + xfm (comp + (mapcat #(cons % (cph/get-parents % objects))) + (map #(get objects %)) + (filter #(= (:type %) :group)) + (map :id) + (distinct)) + + ids (into [] xfm shapes) + + update-group + (fn [group data] + (let [objects (:objects data) + gcenter (geom/center group) + + gxfm (comp + (map #(get objects %)) + (map #(-> % + (assoc :modifiers + (rotation-modifiers gcenter % (- (:rotation group 0)))) + (geom/transform-shape)))) + + selrect (-> (into [] gxfm (:shapes group)) + (geom/selection-rect))] + + ;; Rotate the group shape change the data and rotate back again + (-> group + (assoc-in [:modifiers :rotation] (- (:rotation group))) + (geom/transform-shape) + (merge (select-keys selrect [:x :y :width :height])) + (assoc-in [:modifiers :rotation] (:rotation group)) + (geom/transform-shape))))] + + (reduce #(update-in %1 [:objects %2] update-group %1) data ids))) + (defmethod process-change :mov-objects [data {:keys [parent-id shapes index] :as change}] diff --git a/common/uxbox/common/pages_helpers.cljc b/common/uxbox/common/pages_helpers.cljc index 2516c274e..81e21cfd2 100644 --- a/common/uxbox/common/pages_helpers.cljc +++ b/common/uxbox/common/pages_helpers.cljc @@ -39,15 +39,6 @@ (when parent-id (lazy-seq (cons parent-id (get-parents parent-id objects)))))) -(defn get-common-parents - [ids objects] - (loop [res (d/ordered-set) - ids (seq ids)] - (if ids - (recur (into res (get-parents (first ids) objects)) - (next ids)) - res))) - (defn generate-child-parent-index [objects] (reduce-kv diff --git a/frontend/src/uxbox/main/data/workspace.cljs b/frontend/src/uxbox/main/data/workspace.cljs index a9cb2b7df..ab1449383 100644 --- a/frontend/src/uxbox/main/data/workspace.cljs +++ b/frontend/src/uxbox/main/data/workspace.cljs @@ -54,7 +54,6 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (declare initialized) -(declare initialize-group-check) ;; --- Initialize Workspace @@ -158,8 +157,7 @@ ptk/WatchEvent (watch [_ state stream] - (rx/of (dwp/initialize-page-persistence page-id) - initialize-group-check)))) + (rx/of (dwp/initialize-page-persistence page-id))))) (defn finalize-page [page-id] @@ -176,19 +174,6 @@ (watch [_ state stream] (rx/of ::dwp/finalize)))) -(declare adjust-group-shapes) - -(def initialize-group-check - (ptk/reify ::initialize-group-check - ptk/WatchEvent - (watch [_ state stream] - (let [stoper (rx/filter (ptk/type? ::finalize-page) stream)] - (->> stream - (rx/filter #(satisfies? dwc/IUpdateGroup %)) - (rx/map #(adjust-group-shapes (dwc/get-ids %))) - (rx/take-until stoper)))))) - - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Workspace State Manipulation ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -277,52 +262,6 @@ (assoc :left-offset left-offset))))))))))) -;; TODO: this event is mainly replaced by `:reg-objects` change, but many events -;; are still implemented in function of this so we need to maintain it until -;; all is ported to use `:reg-objects`. - -;; TODO: Additioanlly: many stuff related to rotation is not ported so -;; we need to port it before completelly remove this. - -(defn adjust-group-shapes - [ids] - (ptk/reify ::adjust-group-shapes - dwc/IBatchedChange - ptk/UpdateEvent - (update [_ state] - (let [page-id (:current-page-id state) - objects (get-in state [:workspace-data page-id :objects]) - groups-to-adjust (->> ids - (mapcat #(cph/get-parents % objects)) - (map #(get objects %)) - (filter #(= (:type %) :group)) - (map #(:id %)) - distinct) - update-group - (fn [state group] - (let [objects (get-in state [:workspace-data page-id :objects]) - group-center (geom/center group) - group-objects (->> (:shapes group) - (map #(get objects %)) - (map #(-> % - (assoc :modifiers - (dwt/rotation-modifiers group-center % (- (:rotation group 0)))) - (geom/transform-shape)))) - selrect (geom/selection-rect group-objects)] - - ;; Rotate the group shape change the data and rotate back again - (-> group - (assoc-in [:modifiers :rotation] (- (:rotation group))) - (geom/transform-shape) - (merge (select-keys selrect [:x :y :width :height])) - (assoc-in [:modifiers :rotation] (:rotation group)) - (geom/transform-shape)))) - - reduce-fn - #(update-in %1 [:workspace-data page-id :objects %2] (partial update-group %1))] - - (reduce reduce-fn state groups-to-adjust))))) - (defn start-pan [state] (-> state (assoc-in [:workspace-local :panning] true))) @@ -762,14 +701,21 @@ (watch [_ state stream] (let [page-id (:current-page-id state) objects (get-in state [:workspace-data page-id :objects]) - parents (cph/get-common-parents ids objects) + + parents (loop [res #{parent-id} + ids (seq ids)] + (if (nil? ids) + (vec res) + (recur + (conj res (cph/get-parent (first ids) objects)) + (next ids)))) rchanges [{:type :mov-objects :parent-id parent-id :index to-index :shapes (vec (reverse ids))} {:type :reg-objects - :shapes (vec (conj parents parent-id))}] + :shapes parents}] uchanges (reduce (fn [res id] @@ -782,8 +728,12 @@ [] (reverse ids)) uchanges (conj uchanges {:type :reg-objects - :shapes (vec parents)})] + :shapes parents})] + ;; (println "================ rchanges") + ;; (cljs.pprint/pprint rchanges) + ;; (println "================ uchanges") + ;; (cljs.pprint/pprint uchanges) (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})))))) @@ -828,17 +778,35 @@ [axis] (us/verify ::geom/align-axis axis) (ptk/reify :align-objects - dwc/IBatchedChange - ptk/UpdateEvent - (update [_ state] - (let [page-id (:current-page-id state) - objects (get-in state [:workspace-data page-id :objects]) + ptk/WatchEvent + (watch [_ state stream] + (let [page-id (:current-page-id state) + objects (get-in state [:workspace-data page-id :objects]) selected (get-in state [:workspace-local :selected]) - moved-objs (if (= 1 (count selected)) - (align-object-to-frame objects (first selected) axis) - (align-objects-list objects selected axis)) - updated-objs (merge objects (d/index-by :id moved-objs))] - (assoc-in state [:workspace-data page-id :objects] updated-objs))))) + moved (if (= 1 (count selected)) + (align-object-to-frame objects (first selected) axis) + (align-objects-list objects selected axis))] + (loop [moved (seq moved) + rchanges [] + uchanges []] + (if (nil? moved) + (do + ;; (println "================ rchanges") + ;; (cljs.pprint/pprint rchanges) + ;; (println "================ uchanges") + ;; (cljs.pprint/pprint uchanges) + (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))) + (let [curr (first moved) + prev (get objects (:id curr)) + ops1 (dwc/generate-operations prev curr) + ops2 (dwc/generate-operations curr prev)] + (recur (next moved) + (conj rchanges {:type :mod-obj + :operations ops1 + :id (:id curr)}) + (conj uchanges {:type :mod-obj + :operations ops2 + :id (:id curr)}))))))))) (defn align-object-to-frame [objects object-id axis] @@ -856,16 +824,35 @@ [axis] (us/verify ::geom/dist-axis axis) (ptk/reify :align-objects - dwc/IBatchedChange - ptk/UpdateEvent - (update [_ state] - (let [page-id (:current-page-id state) - objects (get-in state [:workspace-data page-id :objects]) + ptk/WatchEvent + (watch [_ state stream] + (let [page-id (:current-page-id state) + objects (get-in state [:workspace-data page-id :objects]) selected (get-in state [:workspace-local :selected]) - selected-objs (map #(get objects %) selected) - moved-objs (geom/distribute-space selected-objs axis objects) - updated-objs (merge objects (d/index-by :id moved-objs))] - (assoc-in state [:workspace-data page-id :objects] updated-objs))))) + + moved (-> (map #(get objects %) selected) + (geom/distribute-space axis objects))] + (loop [moved (seq moved) + rchanges [] + uchanges []] + (if (nil? moved) + (do + ;; (println "================ rchanges") + ;; (cljs.pprint/pprint rchanges) + ;; (println "================ uchanges") + ;; (cljs.pprint/pprint uchanges) + (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))) + (let [curr (first moved) + prev (get objects (:id curr)) + ops1 (dwc/generate-operations prev curr) + ops2 (dwc/generate-operations curr prev)] + (recur (next moved) + (conj rchanges {:type :mod-obj + :operations ops1 + :id (:id curr)}) + (conj uchanges {:type :mod-obj + :operations ops2 + :id (:id curr)}))))))))) ;; --- Start shape "edition mode" @@ -923,6 +910,8 @@ ;; Event mainly used for handling user modification of the size of the ;; object from workspace sidebar options inputs. +;; TODO: maybe replace directly with dwc/update-shapes? + (defn update-dimensions [ids attr value] (us/verify (s/coll-of ::us/uuid) ids) diff --git a/frontend/src/uxbox/main/data/workspace/common.cljs b/frontend/src/uxbox/main/data/workspace/common.cljs index 09214988a..e2d42ea95 100644 --- a/frontend/src/uxbox/main/data/workspace/common.cljs +++ b/frontend/src/uxbox/main/data/workspace/common.cljs @@ -25,8 +25,6 @@ ;; --- Protocols (defprotocol IBatchedChange) -(defprotocol IUpdateGroup - (get-ids [this])) (declare setup-selection-index) (declare update-page-indices) @@ -96,7 +94,7 @@ :val vmb})))) result))))) -(defn- generate-changes +(defn generate-changes [prev curr] (letfn [(impl-diff [res id] (let [prev-obj (get-in prev [:objects id]) diff --git a/frontend/src/uxbox/main/data/workspace/grid.cljs b/frontend/src/uxbox/main/data/workspace/grid.cljs index 7519e7cba..57e1b85bd 100644 --- a/frontend/src/uxbox/main/data/workspace/grid.cljs +++ b/frontend/src/uxbox/main/data/workspace/grid.cljs @@ -12,6 +12,7 @@ [beicon.core :as rx] [potok.core :as ptk] [uxbox.common.data :as d] + [uxbox.common.spec :as us] [uxbox.main.data.workspace.common :as dwc])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -37,42 +38,39 @@ :column default-layout-params :row default-layout-params}) -(defn add-frame-grid [frame-id] - (ptk/reify ::set-frame-grid - dwc/IBatchedChange - ptk/UpdateEvent - (update [_ state] - (let [pid (:current-page-id state) - default-params (or - (get-in state [:workspace-data pid :options :saved-grids :square]) - (:square default-grid-params)) - prop-path [:workspace-data pid :objects frame-id :grids] - grid {:type :square - :params default-params - :display true}] - (-> state - (update-in prop-path #(if (nil? %) [grid] (conj % grid)))))))) +(defn add-frame-grid + [frame-id] + (us/assert ::us/uuid frame-id) + (ptk/reify ::add-frame-grid + ptk/WatchEvent + (watch [_ state stream] + (let [page-id (:current-page-id state) + data (get-in state [:workspace-data page-id]) + params (or (get-in data [:options :saved-grids :square]) + (:square default-grid-params)) + grid {:type :square + :params params + :display true}] + (rx/of (dwc/update-shapes [frame-id] + (fn [obj] (update obj :grids (fnil #(conj % grid) []))))))))) -(defn remove-frame-grid [frame-id index] - (ptk/reify ::set-frame-grid - dwc/IBatchedChange - ptk/UpdateEvent - (update [_ state] - (let [pid (:current-page-id state)] - (-> state - (update-in [:workspace-data pid :objects frame-id :grids] #(d/remove-at-index % index))))))) -(defn set-frame-grid [frame-id index data] +(defn remove-frame-grid + [frame-id index] (ptk/reify ::set-frame-grid - dwc/IBatchedChange - ptk/UpdateEvent - (update [_ state] - (let [pid (:current-page-id state)] - (-> - state - (assoc-in [:workspace-data pid :objects frame-id :grids index] data)))))) + ptk/WatchEvent + (watch [_ state stream] + (rx/of (dwc/update-shapes [frame-id] (fn [o] (update o :grids (fnil #(d/remove-at-index % index) [])))))))) -(defn set-default-grid [type params] +(defn set-frame-grid + [frame-id index data] + (ptk/reify ::set-frame-grid + ptk/WatchEvent + (watch [_ state stream] + (rx/of (dwc/update-shapes [frame-id] #(assoc-in % [:grids index] data)))))) + +(defn set-default-grid + [type params] (ptk/reify ::set-default-grid ptk/WatchEvent (watch [_ state stream] diff --git a/frontend/src/uxbox/main/data/workspace/transforms.cljs b/frontend/src/uxbox/main/data/workspace/transforms.cljs index 46e61fc50..ebbae44ed 100644 --- a/frontend/src/uxbox/main/data/workspace/transforms.cljs +++ b/frontend/src/uxbox/main/data/workspace/transforms.cljs @@ -400,27 +400,30 @@ [ids] (us/verify (s/coll-of uuid?) ids) (ptk/reify ::apply-modifiers - dwc/IUpdateGroup - (get-ids [_] ids) - - ptk/UpdateEvent - (update [_ state] - (let [page-id (:current-page-id state) - objects (get-in state [:workspace-data page-id :objects]) - - ;; ID's + Children - ids-with-children (concat ids (mapcat #(cph/get-children % objects) ids)) - - ;; For each shape applies the modifiers by transforming the objects - update-shape - (fn [state shape-id] - (update-in state [:workspace-data page-id :objects shape-id] gsh/transform-shape))] - - (reduce update-shape state ids-with-children))) - ptk/WatchEvent (watch [_ state stream] - (let [page-id (:current-page-id state)] - (rx/of (dwc/diff-and-commit-changes page-id) - (dwc/rehash-shape-frame-relationship ids)))))) + (let [page-id (:current-page-id state) + objects0 (get-in state [:workspace-pages page-id :data :objects]) + objects1 (get-in state [:workspace-data page-id :objects]) + ;; ID's + Children ID's + ids-with-children (d/concat [] (mapcat #(cph/get-children % objects1) ids) ids) + + ;; For each shape applies the modifiers by transforming the objects + update-shape #(update %1 %2 gsh/transform-shape) + objects2 (reduce update-shape objects1 ids-with-children) + + regchg {:type :reg-objects :shapes (vec ids)} + + ;; we need to generate redo chages from current + ;; state (with current temporal values) to new state but + ;; the undo should be calculated from clear current + ;; state (without temporal values in it, for this reason + ;; we have 3 different objects references). + + rchanges (conj (dwc/generate-changes {:objects objects1} {:objects objects2}) regchg) + uchanges (conj (dwc/generate-changes {:objects objects2} {:objects objects0}) regchg) + ] + + (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}) + (dwc/rehash-shape-frame-relationship ids)))))) diff --git a/frontend/src/uxbox/main/ui.cljs b/frontend/src/uxbox/main/ui.cljs index 2c55f8bf2..574d08c85 100644 --- a/frontend/src/uxbox/main/ui.cljs +++ b/frontend/src/uxbox/main/ui.cljs @@ -137,7 +137,6 @@ :render-object (do - (prn route) (let [page-id (uuid (get-in route [:params :path :page-id])) object-id (uuid (get-in route [:params :path :object-id]))] [:& render/render-object {:page-id page-id