diff --git a/backend/src/app/rpc/queries/files.clj b/backend/src/app/rpc/queries/files.clj index 8efc073d3..40886f3e1 100644 --- a/backend/src/app/rpc/queries/files.clj +++ b/backend/src/app/rpc/queries/files.clj @@ -9,6 +9,7 @@ [app.common.data :as d] [app.common.data.macros :as dm] [app.common.exceptions :as ex] + [app.common.geom.shapes :as gsh] [app.common.pages.helpers :as cph] [app.common.pages.migrations :as pmg] [app.common.spec :as us] @@ -289,7 +290,7 @@ frame (-> page :objects cph/get-frames)] (assoc frame :page-id (:id page))))) - ;; function responsible to filter objects data strucuture of + ;; function responsible to filter objects data structure of ;; all unneded shapes if a concrete frame is provided. If no ;; frame, the objects is returned untouched. (filter-objects [objects frame-id] @@ -307,10 +308,24 @@ object-id (str page-id frame-id) frame (if-let [thumb (get thumbnails object-id)] (assoc frame :thumbnail thumb :shapes []) - (dissoc frame :thumbnail))] + (dissoc frame :thumbnail)) + + children-ids + (cph/get-children-ids objects frame-id) + + bounds + (when (:show-content frame) + (gsh/selection-rect (->> children-ids (map (d/getf objects))))) + + frame + (cond-> frame + (some? bounds) + (assoc :children-bounds bounds))] + (if (:thumbnail frame) - (recur (-> (assoc objects frame-id frame) - (d/without-keys (cph/get-children-ids objects frame-id))) + (recur (-> objects + (assoc frame-id frame) + (d/without-keys children-ids)) (rest frames)) (recur (assoc objects frame-id frame) (rest frames)))) diff --git a/common/src/app/common/geom/shapes.cljc b/common/src/app/common/geom/shapes.cljc index 90debd442..6f054ab83 100644 --- a/common/src/app/common/geom/shapes.cljc +++ b/common/src/app/common/geom/shapes.cljc @@ -172,6 +172,7 @@ (dm/export gtr/merge-modifiers) (dm/export gtr/transform-shape) (dm/export gtr/transform-selrect) +(dm/export gtr/transform-selrect-matrix) (dm/export gtr/transform-bounds) (dm/export gtr/modifiers->transform) (dm/export gtr/empty-modifiers?) diff --git a/common/src/app/common/geom/shapes/transforms.cljc b/common/src/app/common/geom/shapes/transforms.cljc index 0f254b9a5..a727947c4 100644 --- a/common/src/app/common/geom/shapes/transforms.cljc +++ b/common/src/app/common/geom/shapes/transforms.cljc @@ -645,6 +645,13 @@ (transform-bounds center modifiers) (gpr/points->selrect)))) +(defn transform-selrect-matrix + [selrect mtx] + (-> selrect + (gpr/rect->points) + (gco/transform-points mtx) + (gpr/points->selrect))) + (defn selection-rect "Returns a rect that contains all the shapes and is aware of the rotation of each shape. Mainly used for multiple selection." diff --git a/frontend/src/app/main/render.cljs b/frontend/src/app/main/render.cljs index 429e5b4d0..c9f62c7b8 100644 --- a/frontend/src/app/main/render.cljs +++ b/frontend/src/app/main/render.cljs @@ -61,8 +61,12 @@ (defn- calculate-dimensions [objects] - (let [shapes (cph/get-immediate-children objects) - rect (gsh/selection-rect shapes)] + (let [rect + (->> (cph/get-immediate-children objects) + (map #(if (some? (:children-bounds %)) + (:children-bounds %) + (:selrect %))) + (gsh/join-selrects))] (-> rect (update :x mth/finite 0) (update :y mth/finite 0) @@ -77,9 +81,12 @@ frame-shape (frame/frame-shape shape-wrapper)] (mf/fnc frame-wrapper [{:keys [shape] :as props}] + (let [childs (mapv #(get objects %) (:shapes shape)) shape (gsh/transform-shape shape)] - [:& frame-shape {:shape shape :childs childs}])))) + (if (some? (:thumbnail shape)) + [:& frame/frame-thumbnail {:shape shape :bounds (:children-bounds shape)}] + [:& frame-shape {:shape shape :childs childs}]))))) (defn group-wrapper-factory [objects] @@ -251,7 +258,7 @@ (cond (and frame? thumbnails? (some? (:thumbnail item))) [:> shape-container {:shape item} - [:& frame/frame-thumbnail {:shape item}]] + [:& frame/frame-thumbnail {:shape item :bounds (:children-bounds item)}]] frame? [:> shape-container {:shape item} @@ -271,9 +278,11 @@ (let [frame-id (:id frame) include-metadata? (mf/use-ctx export/include-metadata-ctx) + bounds (or (:children-bounds frame) (:selrect frame)) + modifier - (mf/with-memo [(:x frame) (:y frame)] - (-> (gpt/point (:x frame) (:y frame)) + (mf/with-memo [(:x bounds) (:y bounds)] + (-> (gpt/point (:x bounds) (:y bounds)) (gpt/negate) (gmt/translate-matrix))) @@ -292,9 +301,9 @@ (mf/with-memo [objects] (frame-wrapper-factory objects)) - width (* (:width frame) zoom) - height (* (:height frame) zoom) - vbox (format-viewbox {:width (:width frame 0) :height (:height frame 0)})] + width (* (:width bounds) zoom) + height (* (:height bounds) zoom) + vbox (format-viewbox {:width (:width bounds 0) :height (:height bounds 0)})] [:svg {:view-box vbox :width (ust/format-precision width viewbox-decimal-precision) @@ -310,7 +319,7 @@ ;; Render the frame thumbnail (let [frame (gsh/transform-shape frame)] [:> shape-container {:shape frame} - [:& frame/frame-thumbnail {:shape frame}]]))])) + [:& frame/frame-thumbnail {:shape frame :bounds (assoc bounds :x 0 :y 0)}]]))])) ;; Component for rendering a thumbnail of a single componenent. Mainly diff --git a/frontend/src/app/main/ui/workspace/shapes/frame/dynamic_modifiers.cljs b/frontend/src/app/main/ui/workspace/shapes/frame/dynamic_modifiers.cljs index 1722af34e..0ce9b0a6a 100644 --- a/frontend/src/app/main/ui/workspace/shapes/frame/dynamic_modifiers.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/frame/dynamic_modifiers.cljs @@ -77,14 +77,15 @@ (defn get-nodes "Retrieve the DOM nodes to apply the matrix transformation" - [base-node {:keys [id type masked-group?]}] - (let [shape-node (dom/query base-node (str "#shape-" id)) + [base-node {:keys [id type masked-group?] :as shape}] + (let [shape-node (if (= (.-id base-node) (dm/str "shape-" id)) + base-node + (dom/query base-node (dm/str "#shape-" id))) frame? (= :frame type) group? (= :group type) text? (= :text type) mask? (and group? masked-group?)] - (cond frame? [shape-node