diff --git a/common/src/app/common/geom/shapes/flex_layout/drop_area.cljc b/common/src/app/common/geom/shapes/flex_layout/drop_area.cljc index 00de11f3a5..b68057a179 100644 --- a/common/src/app/common/geom/shapes/flex_layout/drop_area.cljc +++ b/common/src/app/common/geom/shapes/flex_layout/drop_area.cljc @@ -141,7 +141,7 @@ [frame layout-data children] (let [reverse? (:reverse? layout-data) - children (vec (cond->> (d/enumerate children) reverse? reverse)) + children (vec (cond->> (d/enumerate children) (not reverse?) reverse)) lines (:layout-lines layout-data)] (loop [areas [] @@ -169,7 +169,7 @@ areas (let [[child-area child-area-start child-area-end] - (drop-child-areas frame line-area child index reverse? prev-child-x prev-child-y (nil? (first children)))] + (drop-child-areas frame line-area child index (not reverse?) prev-child-x prev-child-y (nil? (first children)))] (recur (conj areas child-area-start child-area-end) (+ (:x child-area) (:width child-area)) (+ (:y child-area) (:height child-area)) diff --git a/common/src/app/common/geom/shapes/flex_layout/lines.cljc b/common/src/app/common/geom/shapes/flex_layout/lines.cljc index 5b0fafdbca..41dea20ea0 100644 --- a/common/src/app/common/geom/shapes/flex_layout/lines.cljc +++ b/common/src/app/common/geom/shapes/flex_layout/lines.cljc @@ -304,7 +304,7 @@ (let [layout-bounds (layout-bounds shape) reverse? (ctl/reverse? shape) - children (cond->> children reverse? reverse) + children (cond->> children (not reverse?) reverse) ;; Creates the layout lines information layout-lines diff --git a/common/src/app/common/geom/shapes/modifiers.cljc b/common/src/app/common/geom/shapes/modifiers.cljc index 36265536ab..c23e07258e 100644 --- a/common/src/app/common/geom/shapes/modifiers.cljc +++ b/common/src/app/common/geom/shapes/modifiers.cljc @@ -159,7 +159,7 @@ (let [children (map (d/getf objects) (:shapes parent)) children (->> children (map (partial apply-modifiers modif-tree))) layout-data (gcl/calc-layout-data parent children) - children (into [] (cond-> children (:reverse? layout-data) reverse)) + children (into [] (cond-> children (not (:reverse? layout-data)) reverse)) max-idx (dec (count children)) layout-lines (:layout-lines layout-data)] diff --git a/common/src/app/common/geom/shapes/transforms.cljc b/common/src/app/common/geom/shapes/transforms.cljc index e8c942fd63..43b4dad21d 100644 --- a/common/src/app/common/geom/shapes/transforms.cljc +++ b/common/src/app/common/geom/shapes/transforms.cljc @@ -43,11 +43,12 @@ (defn move-position-data [position-data dx dy] - (cond->> position-data - (d/num? dx dy) - (mapv #(-> % - (update :x + dx) - (update :y + dy))))) + (when (some? position-data) + (cond->> position-data + (d/num? dx dy) + (mapv #(-> % + (update :x + dx) + (update :y + dy)))))) (defn move "Move the shape relatively to its current @@ -284,6 +285,8 @@ [shape transform-mtx] (let [bool? (= (:type shape) :bool) path? (= (:type shape) :path) + text? (= (:type shape) :text) + {dx :x dy :y} (gpt/transform (gpt/point) transform-mtx) points (gco/transform-points (:points shape) transform-mtx) selrect (gco/transform-selrect (:selrect shape) transform-mtx)] (-> shape @@ -291,6 +294,8 @@ (update :bool-content gpa/transform-content transform-mtx)) (cond-> path? (update :content gpa/transform-content transform-mtx)) + (cond-> text? + (update :position-data move-position-data dx dy)) (cond-> (not path?) (assoc :x (:x selrect) :y (:y selrect) diff --git a/common/src/app/common/pages/helpers.cljc b/common/src/app/common/pages/helpers.cljc index 3428d47974..8ada915fc8 100644 --- a/common/src/app/common/pages/helpers.cljc +++ b/common/src/app/common/pages/helpers.cljc @@ -109,6 +109,11 @@ (recur (conj result parent-id) parent-id) result)))) +(defn get-siblings-ids + [objects id] + (let [parent (get-parent objects id)] + (into [] (->> (:shapes parent) (remove #(= % id)))))) + (defn get-frame "Get the frame that contains the shape. If the shape is already a frame, get itself. If no shape is provided, returns the root frame." diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index a63cf23c56..c658a3c9f3 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1553,7 +1553,8 @@ (into (d/ordered-set)))] (rx/of (dch/commit-changes changes) - (dws/select-shapes selected))))] + (dws/select-shapes selected) + (dwul/update-layout-positions [frame-id]))))] (ptk/reify ::paste-shape ptk/WatchEvent diff --git a/frontend/src/app/main/data/workspace/modifiers.cljs b/frontend/src/app/main/data/workspace/modifiers.cljs index 9b3766e595..2f153442bd 100644 --- a/frontend/src/app/main/data/workspace/modifiers.cljs +++ b/frontend/src/app/main/data/workspace/modifiers.cljs @@ -15,6 +15,7 @@ [app.common.pages.helpers :as cph] [app.common.spec :as us] [app.common.types.modifiers :as ctm] + [app.common.types.shape :as cts] [app.common.types.shape.layout :as ctl] [app.main.data.workspace.changes :as dch] [app.main.data.workspace.comments :as-alias dwcm] @@ -188,6 +189,42 @@ [(get-in objects [k :name]) v])) modif-tree))) +(defn apply-text-modifiers + [objects text-modifiers] + (letfn [(apply-text-modifier + [shape {:keys [width height]}] + (cond-> shape + (some? width) + (assoc :width width) + + (some? height) + (assoc :height height) + + (or (some? width) (some? height)) + (cts/setup-rect-selrect)))] + (loop [modifiers (seq text-modifiers) + result objects] + (if (empty? modifiers) + result + (let [[id text-modifier] (first modifiers)] + (recur (rest modifiers) + (update objects id apply-text-modifier text-modifier))))))) + +#_(defn apply-path-modifiers + [objects path-modifiers] + (letfn [(apply-path-modifier + [shape {:keys [content-modifiers]}] + (let [shape (update shape :content upc/apply-content-modifiers content-modifiers) + [points selrect] (helpers/content->points+selrect shape (:content shape))] + (assoc shape :selrect selrect :points points)))] + (loop [modifiers (seq path-modifiers) + result objects] + (if (empty? modifiers) + result + (let [[id path-modifier] (first modifiers)] + (recur (rest modifiers) + (update objects id apply-path-modifier path-modifier))))))) + (defn set-modifiers ([modif-tree] (set-modifiers modif-tree false)) @@ -206,7 +243,10 @@ (and (not ignore-snap-pixel) (contains? (:workspace-layout state) :snap-pixel-grid)) modif-tree - (gsh/set-objects-modifiers modif-tree objects ignore-constraints snap-pixel?)] + (as-> objects $ + (apply-text-modifiers $ (get state :workspace-text-modifier)) + ;;(apply-path-modifiers $ (get-in state [:workspace-local :edit-path])) + (gsh/set-objects-modifiers modif-tree $ ignore-constraints snap-pixel?))] (assoc state :workspace-modifiers modif-tree)))))) diff --git a/frontend/src/app/main/data/workspace/path/edition.cljs b/frontend/src/app/main/data/workspace/path/edition.cljs index 7ecf800c8f..a5b4a30a5b 100644 --- a/frontend/src/app/main/data/workspace/path/edition.cljs +++ b/frontend/src/app/main/data/workspace/path/edition.cljs @@ -21,6 +21,7 @@ [app.main.data.workspace.path.state :as st] [app.main.data.workspace.path.streams :as streams] [app.main.data.workspace.path.undo :as undo] + [app.main.data.workspace.shapes-update-layout :as dwul] [app.main.data.workspace.state-helpers :as wsh] [app.main.streams :as ms] [app.util.path.tools :as upt] @@ -297,22 +298,25 @@ ptk/WatchEvent (watch [_ state stream] - (let [mode (get-in state [:workspace-local :edit-path id :edit-mode])] + (let [mode (get-in state [:workspace-local :edit-path id :edit-mode]) + stopper (->> stream (rx/filter (ptk/type? ::start-path-edit))) + interrupt (->> stream (rx/filter #(= % :interrupt)) (rx/take 1))] (rx/concat (rx/of (undo/start-path-undo)) (rx/of (drawing/change-edit-mode mode)) - (->> stream - (rx/take-until (->> stream (rx/filter (ptk/type? ::start-path-edit)))) - (rx/filter #(= % :interrupt)) - (rx/take 1) - (rx/map #(stop-path-edit)))))))) + (->> interrupt + (rx/map #(stop-path-edit id)) + (rx/take-until stopper))))))) -(defn stop-path-edit [] +(defn stop-path-edit [id] (ptk/reify ::stop-path-edit ptk/UpdateEvent (update [_ state] - (let [id (get-in state [:workspace-local :edition])] - (update state :workspace-local dissoc :edit-path id))))) + (update state :workspace-local dissoc :edit-path id)) + + ptk/WatchEvent + (watch [_ _ _] + (rx/of (dwul/update-layout-positions [id]))))) (defn split-segments [{:keys [from-p to-p t]}] diff --git a/frontend/src/app/main/data/workspace/shapes_update_layout.cljs b/frontend/src/app/main/data/workspace/shapes_update_layout.cljs index 3274d23563..710fd10c69 100644 --- a/frontend/src/app/main/data/workspace/shapes_update_layout.cljs +++ b/frontend/src/app/main/data/workspace/shapes_update_layout.cljs @@ -8,9 +8,7 @@ (:require [app.common.data :as d] [app.common.types.modifiers :as ctm] - [app.common.types.shape.layout :as ctl] [app.main.data.workspace.modifiers :as dwm] - [app.main.data.workspace.state-helpers :as wsh] [beicon.core :as rx] [potok.core :as ptk])) @@ -18,11 +16,9 @@ [ids] (ptk/reify ::update-layout-positions ptk/WatchEvent - (watch [_ state _] - (let [objects (wsh/lookup-page-objects state) - ids (->> ids (filter (partial ctl/layout? objects)))] - (if (d/not-empty? ids) - (let [modif-tree (dwm/create-modif-tree ids (ctm/reflow-modifiers))] - (rx/of (dwm/set-modifiers modif-tree) - (dwm/apply-modifiers))) - (rx/empty)))))) + (watch [_ _ _] + (if (d/not-empty? ids) + (let [modif-tree (dwm/create-modif-tree ids (ctm/reflow-modifiers))] + (rx/of (dwm/set-modifiers modif-tree) + (dwm/apply-modifiers))) + (rx/empty))))) diff --git a/frontend/src/app/main/data/workspace/texts.cljs b/frontend/src/app/main/data/workspace/texts.cljs index d4cf5995fe..b0ff747d6c 100644 --- a/frontend/src/app/main/data/workspace/texts.cljs +++ b/frontend/src/app/main/data/workspace/texts.cljs @@ -14,11 +14,13 @@ [app.common.pages.helpers :as cph] [app.common.text :as txt] [app.common.types.modifiers :as ctm] + [app.common.types.shape :as cts] [app.common.uuid :as uuid] [app.main.data.workspace.changes :as dch] [app.main.data.workspace.common :as dwc] [app.main.data.workspace.selection :as dws] [app.main.data.workspace.shapes :as dwsh] + [app.main.data.workspace.shapes-update-layout :as dwul] [app.main.data.workspace.state-helpers :as wsh] [app.main.data.workspace.undo :as dwu] [app.util.router :as rt] @@ -75,7 +77,8 @@ (dch/update-shapes [id] (fn [shape] (-> shape (assoc :content content) - (merge modifiers)))) + (merge modifiers) + (cts/setup-rect-selrect)))) (dwu/commit-undo-transaction))))) (when (some? id) @@ -316,19 +319,24 @@ [id new-width new-height] (ptk/reify ::resize-text ptk/WatchEvent - (watch [_ _ _] - (letfn [(update-fn [shape] - (let [{:keys [selrect grow-type]} shape - {shape-width :width shape-height :height} selrect] - (cond-> shape - (and (not-changed? shape-width new-width) (= grow-type :auto-width)) - (gsh/transform-shape (ctm/change-dimensions-modifiers shape :width new-width)) + (watch [_ state _] + (let [shape (wsh/lookup-shape state id)] + (letfn [(update-fn [shape] + (let [{:keys [selrect grow-type]} shape + {shape-width :width shape-height :height} selrect] + (cond-> shape + (and (not-changed? shape-width new-width) (= grow-type :auto-width)) + (gsh/transform-shape (ctm/change-dimensions-modifiers shape :width new-width)) - (and (not-changed? shape-height new-height) - (or (= grow-type :auto-height) (= grow-type :auto-width))) - (gsh/transform-shape (ctm/change-dimensions-modifiers shape :height new-height)))))] + (and (not-changed? shape-height new-height) + (or (= grow-type :auto-height) (= grow-type :auto-width))) + (gsh/transform-shape (ctm/change-dimensions-modifiers shape :height new-height)))))] - (rx/of (dch/update-shapes [id] update-fn {:reg-objects? true :save-undo? false})))))) + (when (or (and (not-changed? (:width shape) new-width) (= (:grow-type shape) :auto-width)) + (and (not-changed? (:height shape) new-height) + (or (= (:grow-type shape) :auto-height) (= (:grow-type shape) :auto-width)))) + (rx/of (dch/update-shapes [id] update-fn {:reg-objects? true :save-undo? false}) + (dwul/update-layout-positions [id])))))))) (defn save-font [data] @@ -358,11 +366,9 @@ (gpt/subtract (gpt/point (:selrect new-shape)) (gpt/point (:selrect shape))) - new-shape (update new-shape :position-data gsh/move-position-data (:x delta-move) (:y delta-move))] - new-shape)) (defn update-text-modifier @@ -370,7 +376,16 @@ (ptk/reify ::update-text-modifier ptk/UpdateEvent (update [_ state] - (update-in state [:workspace-text-modifier id] (fnil merge {}) props)))) + (update-in state [:workspace-text-modifier id] (fnil merge {}) props)) + + ptk/WatchEvent + (watch [_ state _] + (let [shape (wsh/lookup-shape state id)] + (when (or (and (some? (:width props)) + (not (mth/close? (:width props) (:width shape)))) + (and (some? (:height props)) + (not (mth/close? (:height props) (:height shape))))) + (rx/of (dwul/update-layout-positions [id]))))))) (defn clean-text-modifier [id] diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index 2658720efd..be5bf599c4 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -435,9 +435,15 @@ zoom (get-in state [:workspace-local :zoom] 1) focus (:workspace-focus-selected state) - exclude-frames (into #{} - (filter (partial cph/frame-shape? objects)) - (cph/selected-with-children objects selected)) + exclude-frames + (into #{} + (filter (partial cph/frame-shape? objects)) + (cph/selected-with-children objects selected)) + + exclude-frames-siblings + (into exclude-frames + (mapcat (partial cph/get-siblings-ids objects)) + selected) fix-axis (fn [[position shift?]] @@ -471,9 +477,12 @@ ;; We try to use the previous snap so we don't have to wait for the result of the new (rx/map snap/correct-snap-point) + (rx/with-latest vector ms/mouse-position-mod) + (rx/map - (fn [move-vector] + (fn [[move-vector mod?]] (let [position (gpt/add from-position move-vector) + exclude-frames (if mod? exclude-frames exclude-frames-siblings) target-frame (ctst/top-nested-frame objects position exclude-frames) layout? (ctl/layout? objects target-frame) drop-index (when layout? (gsl/get-drop-index target-frame objects position))] diff --git a/frontend/src/app/main/ui/workspace/shapes/path/common.cljs b/frontend/src/app/main/ui/workspace/shapes/path/common.cljs index c88f5e7b58..8c6215304b 100644 --- a/frontend/src/app/main/ui/workspace/shapes/path/common.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/path/common.cljs @@ -28,9 +28,12 @@ (let [selfn #(get-in % [:edit-path id])] #(l/derived selfn refs/workspace-local)))) +(defn content-modifiers-ref + [id] + (l/derived #(get-in % [:edit-path id :content-modifiers]) refs/workspace-local)) + (defn make-content-modifiers-ref [id] (mf/use-memo (mf/deps id) - (let [selfn #(get-in % [:edit-path id :content-modifiers])] - #(l/derived selfn refs/workspace-local)))) + #(content-modifiers-ref id))) diff --git a/frontend/src/app/main/ui/workspace/shapes/text/viewport_texts_html.cljs b/frontend/src/app/main/ui/workspace/shapes/text/viewport_texts_html.cljs index e13e2fcede..02c0724340 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/viewport_texts_html.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/viewport_texts_html.cljs @@ -155,7 +155,11 @@ (not (identical? old-shape new-shape)) (not= (dissoc old-shape :migrate) (dissoc new-shape :migrate))) - (not= new-modifiers old-modifiers) + (and (not= new-modifiers old-modifiers) + (or (nil? new-modifiers) + (nil? old-modifiers) + (not (ctm/only-move? new-modifiers)) + (not (ctm/only-move? old-modifiers)))) ;; When the position data is nil we force to recalculate (:migrate new-shape))))