diff --git a/common/src/app/common/types/shape/layout.cljc b/common/src/app/common/types/shape/layout.cljc index 183d16c8a2..08645a098a 100644 --- a/common/src/app/common/types/shape/layout.cljc +++ b/common/src/app/common/types/shape/layout.cljc @@ -622,7 +622,7 @@ (defn remove-cell-areas "Remove the areas in the given `index` before and after the index" [parent prop index] - (let [prop-span (if (= prop :column) :row-span :column-span) + (let [prop-span (if (= prop :column) :column-span :row-span) cells (if (= prop :column) (cells-by-column parent index) (cells-by-row parent index))] (->> cells (filter #(> (get % prop-span) 1)) @@ -654,7 +654,7 @@ "Remove the areas in the given `index` but only after the index." [parent prop index] (let [prop-span (if (= prop :column) :column-span :row-span) - cells (if (= type :column) (cells-by-column parent index) (cells-by-row parent index))] + cells (if (= prop :column) (cells-by-column parent index) (cells-by-row parent index))] (->> cells (filter #(> (get % prop-span) 1)) (reduce @@ -923,8 +923,8 @@ parent (cond-> parent move-content? - (-> (remove-cell-areas prop (dec from-track)) - (remove-cell-areas prop (dec to-track)))) + (-> (remove-cell-areas prop from-index) + (remove-cell-areas-after prop to-index))) parent (reorder-grid-tracks parent tracks-props from-index to-index)] @@ -1376,24 +1376,43 @@ (cells-by-row parent index true)) ([parent index check-span?] (->> (:layout-grid-cells parent) - (filter (fn [[_ {:keys [row row-span]}]] - (if check-span? - (and (>= (inc index) row) - (< (inc index) (+ row row-span))) - (= (inc index) row)))) - (map second)))) + (vals) + (filter + (fn [{:keys [row row-span]}] + (if check-span? + (and (>= (inc index) row) + (< (inc index) (+ row row-span))) + (= (inc index) row))))))) (defn cells-by-column ([parent index] (cells-by-column parent index true)) ([parent index check-span?] (->> (:layout-grid-cells parent) - (filter (fn [[_ {:keys [column column-span]}]] - (if check-span? - (and (>= (inc index) column) - (< (inc index) (+ column column-span))) - (= (inc index) column)))) - (map second)))) + (vals) + (filter + (fn [{:keys [column column-span] :as cell}] + (if check-span? + (and (>= (inc index) column) + (< (inc index) (+ column column-span))) + (= (inc index) column))))))) + +(defn cells-in-area + [parent first-row last-row first-column last-column] + (->> (:layout-grid-cells parent) + (vals) + (filter + (fn [{:keys [row column row-span column-span] :as cell}] + (and + (or (<= row first-row (+ row row-span -1)) + (<= row last-row (+ row row-span -1)) + (<= first-row row last-row) + (<= first-row (+ row row-span -1) last-row)) + + (or (<= column first-column (+ column column-span -1)) + (<= column last-column (+ column column-span -1)) + (<= first-column column last-column) + (<= first-column (+ column column-span -1) last-column))))))) (defn shapes-by-row ([parent index] diff --git a/frontend/src/app/main/data/workspace/grid_layout/editor.cljs b/frontend/src/app/main/data/workspace/grid_layout/editor.cljs index dc6e99fa59..9af194119f 100644 --- a/frontend/src/app/main/data/workspace/grid_layout/editor.cljs +++ b/frontend/src/app/main/data/workspace/grid_layout/editor.cljs @@ -6,6 +6,7 @@ (ns app.main.data.workspace.grid-layout.editor (:require + [app.common.data.macros :as dm] [app.common.geom.rect :as grc] [app.common.types.shape.layout :as ctl] [app.main.data.workspace.state-helpers :as wsh] @@ -25,14 +26,34 @@ (conj hover-set cell-id) (disj hover-set cell-id)))))))) -(defn select-grid-cell - [grid-id cell-id add?] - (ptk/reify ::select-grid-cell +(defn add-to-selection + ([grid-id cell-id] + (add-to-selection grid-id cell-id false)) + ([grid-id cell-id shift?] + (ptk/reify ::add-to-selection + ptk/UpdateEvent + (update [_ state] + (if shift? + (let [objects (wsh/lookup-page-objects state) + grid (get objects grid-id) + selected (or (dm/get-in state [:workspace-grid-edition grid-id :selected]) #{}) + selected (into selected [cell-id]) + cells (->> selected (map #(dm/get-in grid [:layout-grid-cells %]))) + + {:keys [first-row last-row first-column last-column]} (ctl/cells-coordinates cells) + new-selected + (into #{} + (map :id) + (ctl/cells-in-area grid first-row last-row first-column last-column))] + (assoc-in state [:workspace-grid-edition grid-id :selected] new-selected)) + (update-in state [:workspace-grid-edition grid-id :selected] (fnil conj #{}) cell-id)))))) + +(defn set-selection + [grid-id cell-id] + (ptk/reify ::set-selection ptk/UpdateEvent (update [_ state] - (if add? - (update-in state [:workspace-grid-edition grid-id :selected] (fnil conj #{}) cell-id) - (assoc-in state [:workspace-grid-edition grid-id :selected] #{cell-id}))))) + (assoc-in state [:workspace-grid-edition grid-id :selected] #{cell-id})))) (defn remove-selection [grid-id cell-id] diff --git a/frontend/src/app/main/data/workspace/shape_layout.cljs b/frontend/src/app/main/data/workspace/shape_layout.cljs index f5a1cb9368..2f8c397fa6 100644 --- a/frontend/src/app/main/data/workspace/shape_layout.cljs +++ b/frontend/src/app/main/data/workspace/shape_layout.cljs @@ -24,7 +24,7 @@ [app.main.data.workspace.grid-layout.editor :as dwge] [app.main.data.workspace.modifiers :as dwm] [app.main.data.workspace.selection :as dwse] - [app.main.data.workspace.shapes :as dws] + [app.main.data.workspace.shapes :as dwsh] [app.main.data.workspace.state-helpers :as wsh] [app.main.data.workspace.undo :as dwu] [beicon.v2.core :as rx] @@ -170,18 +170,18 @@ group-index (cfh/get-index-replacement selected objects)] (rx/of (dwse/select-shapes ordered-ids) - (dws/create-artboard-from-selection new-shape-id parent-id group-index (:name (first selected-shapes))) + (dwsh/create-artboard-from-selection new-shape-id parent-id group-index (:name (first selected-shapes))) (cl/remove-all-fills [new-shape-id] {:color clr/black :opacity 1}) (create-layout-from-id new-shape-id type false) (dch/update-shapes [new-shape-id] #(assoc % :layout-item-h-sizing :auto :layout-item-v-sizing :auto)) (dch/update-shapes selected #(assoc % :layout-item-h-sizing :fix :layout-item-v-sizing :fix)) - (dws/delete-shapes page-id selected) + (dwsh/delete-shapes page-id selected) (ptk/data-event :layout/update [new-shape-id]) (dwu/commit-undo-transaction undo-id))) ;; Create Layout from selection (rx/of - (dws/create-artboard-from-selection new-shape-id) + (dwsh/create-artboard-from-selection new-shape-id) (cl/remove-all-fills [new-shape-id] {:color clr/black :opacity 1}) (create-layout-from-id new-shape-id type false) (dch/update-shapes [new-shape-id] #(assoc % :layout-item-h-sizing :auto :layout-item-v-sizing :auto)) @@ -269,23 +269,38 @@ (dwu/commit-undo-transaction undo-id))))))) (defn remove-layout-track - [ids type index] + [ids type index & {:keys [with-shapes?] :or {with-shapes? false}}] (assert (#{:row :column} type)) (ptk/reify ::remove-layout-track ptk/WatchEvent - (watch [_ _ _] + (watch [_ state _] (let [undo-id (js/Symbol)] - (rx/of (dwu/start-undo-transaction undo-id) - (dch/update-shapes - ids - (fn [shape objects] - (case type - :row (ctl/remove-grid-row shape index objects) - :column (ctl/remove-grid-column shape index objects))) - {:with-objects? true}) - (ptk/data-event :layout/update ids) - (dwu/commit-undo-transaction undo-id)))))) + (let [objects (wsh/lookup-page-objects state) + + shapes-to-delete + (when with-shapes? + (->> ids + (mapcat + (fn [id] + (let [shape (get objects id)] + (if (= type :column) + (ctl/shapes-by-column shape index) + (ctl/shapes-by-row shape index))))) + (into #{})))] + (rx/of (dwu/start-undo-transaction undo-id) + (if shapes-to-delete + (dwsh/delete-shapes shapes-to-delete) + (rx/empty)) + (dch/update-shapes + ids + (fn [shape objects] + (case type + :row (ctl/remove-grid-row shape index objects) + :column (ctl/remove-grid-column shape index objects))) + {:with-objects? true}) + (ptk/data-event :layout/update ids) + (dwu/commit-undo-transaction undo-id))))))) (defn duplicate-layout-track [ids type index] diff --git a/frontend/src/app/main/ui/viewer/inspect/right_sidebar.scss b/frontend/src/app/main/ui/viewer/inspect/right_sidebar.scss index 874935b245..f002dc630b 100644 --- a/frontend/src/app/main/ui/viewer/inspect/right_sidebar.scss +++ b/frontend/src/app/main/ui/viewer/inspect/right_sidebar.scss @@ -58,6 +58,7 @@ @include titleTipography; text-align: center; width: $s-200; + color: $df-secondary; } } .more-info-btn { diff --git a/frontend/src/app/main/ui/workspace/context_menu.cljs b/frontend/src/app/main/ui/workspace/context_menu.cljs index e8140696aa..af84fffa69 100644 --- a/frontend/src/app/main/ui/workspace/context_menu.cljs +++ b/frontend/src/app/main/ui/workspace/context_menu.cljs @@ -548,26 +548,35 @@ (mf/use-callback (mf/deps grid-id type index) (fn [] - (st/emit! (dwsl/duplicate-layout-track [grid-id] type index))))] + (st/emit! (dwsl/duplicate-layout-track [grid-id] type index)))) + + do-delete-track-shapes + (mf/use-callback + (mf/deps grid-id type index) + (fn [] + (st/emit! (dwsl/remove-layout-track [grid-id] type index {:with-shapes? true}))))] (if (= type :column) [:* [:& menu-entry {:title (tr "workspace.context-menu.grid-track.column.duplicate") :on-click do-duplicate-track}] [:& menu-entry {:title (tr "workspace.context-menu.grid-track.column.add-before") :on-click do-add-track-before}] [:& menu-entry {:title (tr "workspace.context-menu.grid-track.column.add-after") :on-click do-add-track-after}] - [:& menu-entry {:title (tr "workspace.context-menu.grid-track.column.delete") :on-click do-delete-track}]] + [:& menu-entry {:title (tr "workspace.context-menu.grid-track.column.delete") :on-click do-delete-track}] + [:& menu-entry {:title (tr "workspace.context-menu.grid-track.column.delete-shapes") :on-click do-delete-track-shapes}]] [:* [:& menu-entry {:title (tr "workspace.context-menu.grid-track.row.duplicate") :on-click do-duplicate-track}] [:& menu-entry {:title (tr "workspace.context-menu.grid-track.row.add-before") :on-click do-add-track-before}] [:& menu-entry {:title (tr "workspace.context-menu.grid-track.row.add-after") :on-click do-add-track-after}] - [:& menu-entry {:title (tr "workspace.context-menu.grid-track.row.delete") :on-click do-delete-track}]]))) + [:& menu-entry {:title (tr "workspace.context-menu.grid-track.row.delete") :on-click do-delete-track}] + [:& menu-entry {:title (tr "workspace.context-menu.grid-track.row.delete-shapes") :on-click do-delete-track-shapes}]]))) (mf/defc grid-cells-context-menu [{:keys [mdata] :as props}] (let [{:keys [grid cells]} mdata single? (= (count cells) 1) + can-merge? (mf/use-memo (mf/deps cells) @@ -595,7 +604,8 @@ :on-click do-merge-cells}]) [:& menu-entry {:title (tr "workspace.context-menu.grid-cells.create-board") - :on-click do-create-board}]])) + :on-click do-create-board + :disabled (and (not single?) (not can-merge?))}]])) (mf/defc context-menu diff --git a/frontend/src/app/main/ui/workspace/sidebar/history.scss b/frontend/src/app/main/ui/workspace/sidebar/history.scss index 9a23cda6cc..bafe0cff74 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/history.scss +++ b/frontend/src/app/main/ui/workspace/sidebar/history.scss @@ -95,6 +95,7 @@ } .history-entry-summary-text { margin: 0 $s-8; + color: $df-primary; } .history-entry-summary-button { opacity: $op-0; diff --git a/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.cljs b/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.cljs index ddc740d96d..7b99e9f618 100644 --- a/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.cljs @@ -337,10 +337,19 @@ (mf/use-callback (mf/deps (:id shape) (:id cell) selected?) (fn [event] - (when (or (dom/left-mouse? event) (not selected?)) - (if (and (kbd/shift? event) selected?) + (when (dom/left-mouse? event) + (cond + (and selected? (or (kbd/mod? event) (kbd/shift? event))) (st/emit! (dwge/remove-selection (:id shape) (:id cell))) - (st/emit! (dwge/select-grid-cell (:id shape) (:id cell) (kbd/shift? event))))))) + + (and (not selected?) (kbd/mod? event)) + (st/emit! (dwge/add-to-selection (:id shape) (:id cell))) + + (and (not selected?) (kbd/shift? event)) + (st/emit! (dwge/add-to-selection (:id shape) (:id cell) true)) + + :else + (st/emit! (dwge/set-selection (:id shape) (:id cell))))))) handle-context-menu (mf/use-callback diff --git a/frontend/translations/en.po b/frontend/translations/en.po index 3d32f6632e..b01c7a11c4 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -5070,6 +5070,9 @@ msgstr "Add 1 column to the right" msgid "workspace.context-menu.grid-track.column.delete" msgstr "Delete column" +msgid "workspace.context-menu.grid-track.column.delete-shapes" +msgstr "Delete column and shapes" + msgid "workspace.context-menu.grid-track.row.duplicate" msgstr "Duplicate row" @@ -5082,6 +5085,9 @@ msgstr "Add 1 row bellow" msgid "workspace.context-menu.grid-track.row.delete" msgstr "Delete row" +msgid "workspace.context-menu.grid-track.row.delete-shapes" +msgstr "Delete row and shapes" + msgid "workspace.context-menu.grid-cells.merge" msgstr "Merge cells" diff --git a/frontend/translations/es.po b/frontend/translations/es.po index 9fcdbdbcf0..8845dc4848 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -5159,6 +5159,9 @@ msgstr "Añadir 1 columna a la derecha" msgid "workspace.context-menu.grid-track.column.delete" msgstr "Borrar columna" +msgid "workspace.context-menu.grid-track.column.delete-shapes" +msgstr "Borrar columna con el contenido" + msgid "workspace.context-menu.grid-track.row.duplicate" msgstr "Duplicar fila" @@ -5171,6 +5174,9 @@ msgstr "Añadir 1 fila debajo" msgid "workspace.context-menu.grid-track.row.delete" msgstr "Borrar fila" +msgid "workspace.context-menu.grid-track.row.delete-shapes" +msgstr "Borrar fila con el contenido" + msgid "workspace.context-menu.grid-cells.merge" msgstr "Fusionar celdas"