diff --git a/common/src/app/common/geom/shapes/grid_layout/positions.cljc b/common/src/app/common/geom/shapes/grid_layout/positions.cljc index 3c0e2a60c..cea3162d4 100644 --- a/common/src/app/common/geom/shapes/grid_layout/positions.cljc +++ b/common/src/app/common/geom/shapes/grid_layout/positions.cljc @@ -8,9 +8,7 @@ (:require [app.common.data :as d] [app.common.data.macros :as dm] - [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] - [app.common.geom.shapes.common :as gco] [app.common.geom.shapes.grid-layout.layout-data :as ld] [app.common.geom.shapes.points :as gpo] [app.common.geom.shapes.transforms :as gtr] diff --git a/frontend/src/app/main/data/workspace/common.cljs b/frontend/src/app/main/data/workspace/common.cljs index 11fef1fd5..5aecdc0b9 100644 --- a/frontend/src/app/main/data/workspace/common.cljs +++ b/frontend/src/app/main/data/workspace/common.cljs @@ -6,8 +6,11 @@ (ns app.main.data.workspace.common (:require + [app.common.data.macros :as dm] [app.common.logging :as log] + [app.common.types.shape.layout :as ctl] [app.main.data.workspace.changes :as dch] + [app.main.data.workspace.state-helpers :as wsh] [app.main.data.workspace.undo :as dwu] [app.util.router :as rt] [beicon.core :as rx] @@ -53,10 +56,13 @@ (ptk/reify ::undo ptk/WatchEvent (watch [it state _] - (let [edition (get-in state [:workspace-local :edition]) + (let [objects (wsh/lookup-page-objects state) + edition (get-in state [:workspace-local :edition]) drawing (get state :workspace-drawing)] + ;; Editors handle their own undo's - (when (and (nil? edition) (nil? (:object drawing))) + (when (or (and (nil? edition) (nil? (:object drawing))) + (ctl/grid-layout? objects edition)) (let [undo (:workspace-undo state) items (:items undo) index (or (:index undo) (dec (count items)))] @@ -64,14 +70,17 @@ (let [item (get items index) changes (:undo-changes item) undo-group (:undo-group item) - find-first-group-idx (fn ffgidx[index] - (let [item (get items index)] - (if (= (:undo-group item) undo-group) - (ffgidx (dec index)) - (inc index)))) - undo-group-index (when undo-group - (find-first-group-idx index))] + find-first-group-idx + (fn [index] + (if (= (dm/get-in items [index :undo-group]) undo-group) + (recur (dec index)) + (inc index))) + + undo-group-index + (when undo-group + (find-first-group-idx index))] + (if undo-group (rx/of (undo-to-index (dec undo-group-index))) (rx/of (dwu/materialize-undo changes (dec index)) @@ -117,9 +126,11 @@ (ptk/reify ::undo-to-index ptk/WatchEvent (watch [it state _] - (let [edition (get-in state [:workspace-local :edition]) + (let [objects (wsh/lookup-page-objects state) + edition (get-in state [:workspace-local :edition]) drawing (get state :workspace-drawing)] - (when-not (or (some? edition) (not-empty drawing)) + (when-not (and (or (some? edition) (not-empty drawing)) + (not (ctl/grid-layout? objects edition))) (let [undo (:workspace-undo state) items (:items undo) index (or (:index undo) (dec (count items)))] diff --git a/frontend/src/app/main/data/workspace/edition.cljs b/frontend/src/app/main/data/workspace/edition.cljs index 66a33acf5..531842413 100644 --- a/frontend/src/app/main/data/workspace/edition.cljs +++ b/frontend/src/app/main/data/workspace/edition.cljs @@ -45,4 +45,5 @@ (let [id (get-in state [:workspace-local :edition])] (-> state (update :workspace-local dissoc :edition) + (dissoc :workspace-grid-edition) (cond-> (some? id) (update-in [:workspace-local :edit-path] dissoc id))))))) diff --git a/frontend/src/app/main/data/workspace/shape_layout.cljs b/frontend/src/app/main/data/workspace/shape_layout.cljs index 777d9552d..2642bb3b7 100644 --- a/frontend/src/app/main/data/workspace/shape_layout.cljs +++ b/frontend/src/app/main/data/workspace/shape_layout.cljs @@ -343,22 +343,21 @@ (create-layout-from-selection type)) (dwu/commit-undo-transaction undo-id)))))) -(defn toggle-layout-flex - [] +(defn toggle-layout + [type] (ptk/reify ::toggle-layout-flex ptk/WatchEvent (watch [_ state _] - (let [page-id (:current-page-id state) - objects (wsh/lookup-page-objects state page-id) + (let [objects (wsh/lookup-page-objects state) selected (wsh/lookup-selected state) selected-shapes (map (d/getf objects) selected) single? (= (count selected-shapes) 1) - has-flex-layout? (and single? (ctl/flex-layout? objects (:id (first selected-shapes))))] + has-layout? (and single? (ctl/any-layout? objects (:id (first selected-shapes))))] (when (not= 0 (count selected)) - (if has-flex-layout? + (if has-layout? (rx/of (remove-layout selected)) - (rx/of (create-layout :flex)))))))) + (rx/of (create-layout type)))))))) (defn update-layout [ids changes] diff --git a/frontend/src/app/main/data/workspace/shortcuts.cljs b/frontend/src/app/main/data/workspace/shortcuts.cljs index 4cf059c95..6f2bb6c50 100644 --- a/frontend/src/app/main/data/workspace/shortcuts.cljs +++ b/frontend/src/app/main/data/workspace/shortcuts.cljs @@ -219,7 +219,12 @@ :toggle-layout-flex {:tooltip (ds/shift "A") :command "shift+a" :subsections [:modify-layers] - :fn #(emit-when-no-readonly (dwsl/toggle-layout-flex))} + :fn #(emit-when-no-readonly (dwsl/toggle-layout :flex))} + + :toggle-layout-grid {:tooltip (ds/meta-shift "A") + :command (ds/c-mod "shift+a") + :subsections [:modify-layers] + :fn #(emit-when-no-readonly (dwsl/toggle-layout :grid))} ;; TOOLS diff --git a/frontend/src/app/main/ui/workspace/context_menu.cljs b/frontend/src/app/main/ui/workspace/context_menu.cljs index c2d899545..59c5d7ed6 100644 --- a/frontend/src/app/main/ui/workspace/context_menu.cljs +++ b/frontend/src/app/main/ui/workspace/context_menu.cljs @@ -413,9 +413,10 @@ is-frame? (and single? has-frame?) is-flex-container? (and is-frame? (= :flex (:layout (first shapes)))) ids (->> shapes (map :id)) - add-flex #(st/emit! (if is-frame? - (dwsl/create-layout-from-id ids :flex true) - (dwsl/create-layout-from-selection :flex))) + add-layout (fn [type] + (st/emit! (if is-frame? + (dwsl/create-layout-from-id ids type true) + (dwsl/create-layout-from-selection type)))) remove-flex #(st/emit! (dwsl/remove-layout ids))] [:* @@ -424,7 +425,10 @@ [:& menu-separator] [:& menu-entry {:title (tr "workspace.shape.menu.add-flex") :shortcut (sc/get-tooltip :toggle-layout-flex) - :on-click add-flex}]]) + :on-click #(add-layout :flex)}] + [:& menu-entry {:title (tr "workspace.shape.menu.add-grid") + :shortcut (sc/get-tooltip :toggle-layout-grid) + :on-click #(add-layout :grid)}]]) (when is-flex-container? [:div [:& menu-separator] diff --git a/frontend/src/app/main/ui/workspace/sidebar/options.cljs b/frontend/src/app/main/ui/workspace/sidebar/options.cljs index c2e44baf3..6151dade2 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options.cljs @@ -7,8 +7,10 @@ (ns app.main.ui.workspace.sidebar.options (:require [app.common.data :as d] + [app.common.data.macros :as dm] [app.common.geom.shapes :as gsh] [app.common.pages.helpers :as cph] + [app.common.types.shape.layout :as ctl] [app.main.data.workspace :as udw] [app.main.refs :as refs] [app.main.store :as st] @@ -20,6 +22,7 @@ [app.main.ui.workspace.sidebar.options.menus.exports :refer [exports-menu]] [app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell] [app.main.ui.workspace.sidebar.options.menus.interactions :refer [interactions-menu]] + [app.main.ui.workspace.sidebar.options.menus.layout-container :as layout-container] [app.main.ui.workspace.sidebar.options.page :as page] [app.main.ui.workspace.sidebar.options.shapes.bool :as bool] [app.main.ui.workspace.sidebar.options.shapes.circle :as circle] @@ -68,15 +71,15 @@ (let [drawing (mf/deref refs/workspace-drawing) objects (mf/deref refs/workspace-page-objects) shared-libs (mf/deref refs/workspace-libraries) + edition (mf/deref refs/selected-edition) grid-edition (mf/deref refs/workspace-grid-edition) + selected-shapes (into [] (keep (d/getf objects)) selected) first-selected-shape (first selected-shapes) shape-parent-frame (cph/get-frame objects (:frame-id first-selected-shape)) - [grid-id {cell-id :selected}] - (d/seek (fn [[_ {:keys [selected]}]] (some? selected)) grid-edition) - - grid-cell-selected? (and (some? grid-id) (some? cell-id)) + edit-grid? (ctl/grid-layout? objects edition) + selected-cell (dm/get-in grid-edition [edition :selected]) on-change-tab (fn [options-mode] @@ -96,10 +99,15 @@ [:& align-options] [:& bool-options] (cond - grid-cell-selected? + (some? selected-cell) [:& grid-cell/options - {:shape (get objects grid-id) - :cell (get-in objects [grid-id :layout-grid-cells cell-id])}] + {:shape (get objects edition) + :cell (dm/get-in objects [edition :layout-grid-cells selected-cell])}] + + edit-grid? + [:& layout-container/grid-layout-edition + {:ids [edition] + :values (get objects edition)}] (d/not-empty? drawing) [:& shape-options diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs index 0573166a3..aba9e6c67 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs @@ -238,7 +238,8 @@ [:button.btn-options {:disabled is-default :on-click handle-set-as-default} (tr "workspace.options.grid.params.set-default")]]]])) -(mf/defc frame-grid [{:keys [shape]}] +(mf/defc frame-grid + [{:keys [shape]}] (let [id (:id shape) saved-grids (mf/deref workspace-saved-grids) default-grid-params (mf/use-memo (mf/deps saved-grids) #(merge dw/default-grid-params saved-grids)) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs index c4ef62818..ce38aede0 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs @@ -477,7 +477,7 @@ (mf/defc layout-container-menu {::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values" "multiple"]))]} - [{:keys [ids values multiple] :as props}] + [{:keys [ids values multiple] :as props}] (let [open? (mf/use-state false) ;; Display @@ -594,53 +594,7 @@ (fn [value type] (if (= type :row) (st/emit! (dwsl/update-layout ids {:layout-align-content value})) - (st/emit! (dwsl/update-layout ids {:layout-justify-content value}))))) - - - ;;Grid columns - column-grid-values (:layout-grid-columns values) - grid-columns-open? (mf/use-state false) - toggle-columns-info (mf/use-callback - (fn [_] - (swap! grid-columns-open? not))) - - ; Grid rows / columns - rows-grid-values (:layout-grid-rows values) - grid-rows-open? (mf/use-state false) - toggle-rows-info - (mf/use-callback - (fn [_] - (swap! grid-rows-open? not))) - - add-new-element - (mf/use-callback - (mf/deps ids) - (fn [type value] - (st/emit! (dwsl/add-layout-track ids type value)))) - - remove-element - (mf/use-callback - (mf/deps ids) - (fn [type index] - (st/emit! (dwsl/remove-layout-track ids type index)))) - - set-column-value - (mf/use-callback - (mf/deps ids) - (fn [type index value] - (st/emit! (dwsl/change-layout-track ids type index {:value value})))) - - set-column-type - (mf/use-callback - (mf/deps ids) - (fn [type index track-type] - (let [value (case track-type - :auto nil - :flex 1 - :percent 20 - :fixed 100)] - (st/emit! (dwsl/change-layout-track ids type index {:value value - :type track-type})))))] + (st/emit! (dwsl/update-layout ids {:layout-justify-content value})))))] [:div.element-set [:div.element-set-title @@ -751,36 +705,112 @@ :set-justify set-justify-grid}] [:& justify-grid-row {:is-col? false :justify-items grid-justify-content-row - :set-justify set-justify-grid}]]] - - [:& grid-columns-row {:is-col? true - :expanded? @grid-columns-open? - :toggle toggle-columns-info - :column-values column-grid-values - :add-new-element add-new-element - :set-column-value set-column-value - :set-column-type set-column-type - :remove-element remove-element}] - - [:& grid-columns-row {:is-col? false - :expanded? @grid-rows-open? - :toggle toggle-rows-info - :column-values rows-grid-values - :add-new-element add-new-element - :set-column-value set-column-value - :set-column-type set-column-type - :remove-element remove-element}] - - [:& gap-section {:is-col? is-col? - :wrap-type wrap-type - :gap-selected? gap-selected? - :set-gap set-gap - :gap-value (:layout-gap values)}] - - [:& padding-section {:values values - :on-change-style change-padding-type - :on-change on-padding-change}]] - + :set-justify set-justify-grid}]]]] ;; Default if not grid or flex nil)))])) + +(mf/defc grid-layout-edition + {::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values"]))]} + [{:keys [ids values] :as props}] + (let [;; Gap + gap-selected? (mf/use-state :none) + + set-gap + (fn [gap-multiple? type val] + (if gap-multiple? + (st/emit! (dwsl/update-layout ids {:layout-gap {:row-gap val :column-gap val}})) + (st/emit! (dwsl/update-layout ids {:layout-gap {type val}})))) + + ;; Padding + change-padding-type + (fn [type] + (st/emit! (dwsl/update-layout ids {:layout-padding-type type}))) + + on-padding-change + (fn [type prop val] + (cond + (and (= type :simple) (= prop :p1)) + (st/emit! (dwsl/update-layout ids {:layout-padding {:p1 val :p3 val}})) + + (and (= type :simple) (= prop :p2)) + (st/emit! (dwsl/update-layout ids {:layout-padding {:p2 val :p4 val}})) + + :else + (st/emit! (dwsl/update-layout ids {:layout-padding {prop val}})))) + + ;;Grid columns + column-grid-values (:layout-grid-columns values) + grid-columns-open? (mf/use-state false) + toggle-columns-info (mf/use-callback + (fn [_] + (swap! grid-columns-open? not))) + + ; Grid rows / columns + rows-grid-values (:layout-grid-rows values) + grid-rows-open? (mf/use-state false) + toggle-rows-info + (mf/use-callback + (fn [_] + (swap! grid-rows-open? not))) + + add-new-element + (mf/use-callback + (mf/deps ids) + (fn [type value] + (st/emit! (dwsl/add-layout-track ids type value)))) + + remove-element + (mf/use-callback + (mf/deps ids) + (fn [type index] + (st/emit! (dwsl/remove-layout-track ids type index)))) + + set-column-value + (mf/use-callback + (mf/deps ids) + (fn [type index value] + (st/emit! (dwsl/change-layout-track ids type index {:value value})))) + + set-column-type + (mf/use-callback + (mf/deps ids) + (fn [type index track-type] + (let [value (case track-type + :auto nil + :flex 1 + :percent 20 + :fixed 100)] + (st/emit! (dwsl/change-layout-track ids type index {:value value + :type track-type})))))] + + [:div.element-set + [:div.element-set-title + [:span "Grid Layout"]] + + [:div.element-set-content.layout-menu + [:& grid-columns-row {:is-col? true + :expanded? @grid-columns-open? + :toggle toggle-columns-info + :column-values column-grid-values + :add-new-element add-new-element + :set-column-value set-column-value + :set-column-type set-column-type + :remove-element remove-element}] + + [:& grid-columns-row {:is-col? false + :expanded? @grid-rows-open? + :toggle toggle-rows-info + :column-values rows-grid-values + :add-new-element add-new-element + :set-column-value set-column-value + :set-column-type set-column-type + :remove-element remove-element}] + + [:& gap-section {:gap-selected? gap-selected? + :set-gap set-gap + :gap-value (:layout-gap values)}] + + [:& padding-section {:values values + :on-change-style change-padding-type + :on-change on-padding-change}]]])) diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index a9b04c51d..c355a684a 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -159,7 +159,7 @@ create-comment? (= :comments drawing-tool) drawing-path? (or (and edition (= :draw (get-in edit-path [edition :edit-mode]))) (and (some? drawing-obj) (= :path (:type drawing-obj)))) - node-editing? (and edition (not= :text (get-in base-objects [edition :type]))) + node-editing? (and edition (= :path (get-in base-objects [edition :type]))) text-editing? (and edition (= :text (get-in base-objects [edition :type]))) grid-editing? (and edition (ctl/grid-layout? base-objects edition)) diff --git a/frontend/src/app/main/ui/workspace/viewport/actions.cljs b/frontend/src/app/main/ui/workspace/viewport/actions.cljs index 6d9e67d38..1d04c715b 100644 --- a/frontend/src/app/main/ui/workspace/viewport/actions.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/actions.cljs @@ -231,8 +231,8 @@ (mf/use-fn (mf/deps @hover @hover-ids workspace-read-only?) (fn [event] - (if workspace-read-only? - (dom/prevent-default event) + (dom/prevent-default event) + (when-not workspace-read-only? (when (or (dom/class? (dom/get-target event) "viewport-controls") (dom/child? (dom/get-target event) (dom/query ".viewport-controls")) (dom/class? (dom/get-target event) "viewport-selrect") diff --git a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs index 0a1245239..bb46c1efa 100644 --- a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs @@ -354,5 +354,5 @@ (do (st/emit! (dsc/push-shortcuts ::path psc/shortcuts)) #(st/emit! (dsc/pop-shortcuts ::path))) text-editing? - (do (st/emit! (dsc/push-shortcuts ::text tsc/shortcuts)) - #(st/emit! (dsc/pop-shortcuts ::text))))))) + (do (st/emit! (dsc/push-shortcuts ::text tsc/shortcuts)) + #(st/emit! (dsc/pop-shortcuts ::text))))))) diff --git a/frontend/translations/en.po b/frontend/translations/en.po index 964aceddf..da1727af8 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -4379,6 +4379,9 @@ msgstr "Updating %s..." msgid "workspace.shape.menu.add-flex" msgstr "Add flex layout" +msgid "workspace.shape.menu.add-grid" +msgstr "Add grid layout" + #: src/app/main/ui/workspace/context_menu.cljs msgid "workspace.shape.menu.back" msgstr "Send to back" diff --git a/frontend/translations/es.po b/frontend/translations/es.po index 16a40b937..6bb5d6012 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -4481,6 +4481,9 @@ msgstr "Actualizando %s..." msgid "workspace.shape.menu.add-flex" msgstr "Añadir flex layout" +msgid "workspace.shape.menu.add-grid" +msgstr "Añadir grid layout" + #: src/app/main/ui/workspace/context_menu.cljs msgid "workspace.shape.menu.back" msgstr "Enviar al fondo"