diff --git a/common/src/app/common/geom/shapes/grid_layout.cljc b/common/src/app/common/geom/shapes/grid_layout.cljc index 36f9270818..eb45960f89 100644 --- a/common/src/app/common/geom/shapes/grid_layout.cljc +++ b/common/src/app/common/geom/shapes/grid_layout.cljc @@ -13,3 +13,7 @@ (dm/export glld/calc-layout-data) (dm/export glld/get-cell-data) (dm/export glp/child-modifiers) + +(defn get-drop-index + [frame objects _position] + (dec (count (get-in objects [frame :shapes])))) diff --git a/common/src/app/common/geom/shapes/grid_layout/layout_data.cljc b/common/src/app/common/geom/shapes/grid_layout/layout_data.cljc index 08caa33eb7..e797b1c643 100644 --- a/common/src/app/common/geom/shapes/grid_layout/layout_data.cljc +++ b/common/src/app/common/geom/shapes/grid_layout/layout_data.cljc @@ -6,13 +6,10 @@ (ns app.common.geom.shapes.grid-layout.layout-data (:require - [app.common.data :as d] - [app.common.uuid :as uuid] - [app.common.data.macros :as dm] [app.common.geom.point :as gpt] [app.common.geom.shapes.points :as gpo])) -(defn set-sample-data +#_(defn set-sample-data [parent children] (let [parent (assoc parent @@ -38,8 +35,8 @@ layout-grid-cells (into {} - (for [[row-idx row] (d/enumerate (:layout-grid-rows parent)) - [col-idx col] (d/enumerate (:layout-grid-columns parent))] + (for [[row-idx _row] (d/enumerate (:layout-grid-rows parent)) + [col-idx _col] (d/enumerate (:layout-grid-columns parent))] (let [[_bounds shape] (nth children (+ (* row-idx num-columns) col-idx) nil) cell-data {:id (uuid/next) :row (inc row-idx) @@ -69,7 +66,7 @@ )) (defn calc-layout-data - [parent children transformed-parent-bounds] + [parent _children transformed-parent-bounds] (let [height (gpo/height-points transformed-parent-bounds) width (gpo/width-points transformed-parent-bounds) @@ -124,7 +121,7 @@ :shape-cells shape-cells})) (defn get-cell-data - [{:keys [row-tracks column-tracks shape-cells]} transformed-parent-bounds [child-bounds child]] + [{:keys [row-tracks column-tracks shape-cells]} transformed-parent-bounds [_child-bounds child]] (let [origin (gpo/origin transformed-parent-bounds) hv #(gpo/start-hv transformed-parent-bounds %) @@ -138,7 +135,6 @@ start-p (-> origin (gpt/add (hv (:distance column))) - (gpt/add (vv (:distance row)))) - ] + (gpt/add (vv (:distance row))))] (assoc grid-cell :start-p start-p))))) diff --git a/common/src/app/common/geom/shapes/pixel_precision.cljc b/common/src/app/common/geom/shapes/pixel_precision.cljc index e85c708932..9994b09788 100644 --- a/common/src/app/common/geom/shapes/pixel_precision.cljc +++ b/common/src/app/common/geom/shapes/pixel_precision.cljc @@ -80,7 +80,7 @@ (fn [modif-tree shape] (let [modifiers (dm/get-in modif-tree [(:id shape) :modifiers])] (cond-> modif-tree - (ctm/has-geometry? modifiers) + (and (some? modifiers) (ctm/has-geometry? modifiers)) (update-in [(:id shape) :modifiers] set-pixel-precision shape precision ignore-axis))))] (->> (keys modif-tree) diff --git a/common/src/app/common/types/shape/layout.cljc b/common/src/app/common/types/shape/layout.cljc index 17639f9a18..e7d8867b98 100644 --- a/common/src/app/common/types/shape/layout.cljc +++ b/common/src/app/common/types/shape/layout.cljc @@ -6,8 +6,10 @@ (ns app.common.types.shape.layout (:require + [app.common.data :as d] [app.common.data.macros :as dm] [app.common.spec :as us] + [app.common.uuid :as uuid] [clojure.spec.alpha :as s])) ;; :layout ;; :flex, :grid in the future @@ -41,6 +43,7 @@ (s/def ::layout #{:flex :grid}) (s/def ::layout-flex-dir #{:row :reverse-row :row-reverse :column :reverse-column :column-reverse}) ;;TODO remove reverse-column and reverse-row after script +(s/def ::layout-grid-dir #{:row :column}) (s/def ::layout-gap-type #{:simple :multiple}) (s/def ::layout-gap ::us/safe-number) @@ -53,11 +56,34 @@ (s/def :grid/type #{:percent :flex :auto :fixed}) (s/def :grid/value (s/nilable ::us/safe-number)) -(s/def ::grid-definition (s/keys :opt-un [:grid/type - :grid/value])) +(s/def ::grid-definition (s/keys :req-un [:grid/type] + :opt-un [:grid/value])) (s/def ::layout-grid-rows (s/coll-of ::grid-definition :kind vector?)) (s/def ::layout-grid-columns (s/coll-of ::grid-definition :kind vector?)) +(s/def :grid-cell/id uuid?) +(s/def :grid-cell/area-name ::us/string) +(s/def :grid-cell/row-start ::us/safe-integer) +(s/def :grid-cell/row-span ::us/safe-integer) +(s/def :grid-cell/column-start ::us/safe-integer) +(s/def :grid-cell/column-span ::us/safe-integer) +(s/def :grid-cell/position #{:auto :manual :area}) +(s/def :grid-cell/align-self #{:auto :start :end :center :stretch}) +(s/def :grid-cell/justify-self #{:auto :start :end :center :stretch}) +(s/def :grid-cell/shapes (s/coll-of uuid?)) + +(s/def ::grid-cell (s/keys :opt-un [:grid-cell/id + :grid-cell/area-name + :grid-cell/row-start + :grid-cell/row-span + :grid-cell/column-start + :grid-cell/column-span + :grid-cell/position ;; auto, manual, area + :grid-cell/align-self + :grid-cell/justify-self + :grid-cell/shapes])) +(s/def ::layout-grid-cells (s/map-of uuid? ::grid-cell)) + (s/def ::p1 ::us/safe-number) (s/def ::p2 ::us/safe-number) (s/def ::p3 ::us/safe-number) @@ -85,9 +111,11 @@ ::layout-align-content ;; grid + ::layout-grid-dir ::layout-justify-items ::layout-grid-rows ::layout-grid-columns + ::layout-grid-cells ])) (s/def ::m1 ::us/safe-number) @@ -448,7 +476,12 @@ :layout-padding :layout-justify-content :layout-align-items - :layout-align-content)) + :layout-align-content + :layout-grid-dir + :layout-justify-items + :layout-grid-columns + :layout-grid-rows + )) (defn remove-layout-item-data [shape] @@ -464,3 +497,91 @@ :layout-item-align-self :layout-item-absolute :layout-item-z-index)) +(declare assign-cells) + +(def grid-cell-defaults + {:row-span 1 + :column-span 1 + :position :auto + :align-self :auto + :justify-self :auto + :shapes []}) + +;; TODO: GRID ASSIGNMENTS + +;; Adding a track creates the cells. We should check the shapes that are not tracked (with default values) and assign to the correct tracked values +(defn add-grid-column + [parent value] + (us/assert ::grid-definition value) + (let [rows (:layout-grid-rows parent) + new-col-num (count (:layout-grid-columns parent)) + + layout-grid-cells + (->> (d/enumerate rows) + (reduce (fn [result [row-idx _row]] + (let [id (uuid/next)] + (assoc result id + (merge {:id id + :row (inc row-idx) + :column new-col-num + :track? true} + grid-cell-defaults)))) + (:layout-grid-cells parent)))] + (-> parent + (update :layout-grid-columns (fnil conj []) value) + (assoc :layout-grid-cells layout-grid-cells)))) + +(defn add-grid-row + [parent value] + (us/assert ::grid-definition value) + (let [cols (:layout-grid-columns parent) + new-row-num (inc (count (:layout-grid-rows parent))) + + layout-grid-cells + (->> (d/enumerate cols) + (reduce (fn [result [col-idx _col]] + (let [id (uuid/next)] + (assoc result id + (merge {:id id + :column (inc col-idx) + :row new-row-num + :track? true} + grid-cell-defaults)))) + (:layout-grid-cells parent)))] + (-> parent + (update :layout-grid-rows (fnil conj []) value) + (assoc :layout-grid-cells layout-grid-cells)))) + +;; TODO: Remove a track and its corresponding cells. We need to reassign the orphaned shapes into not-tracked cells +(defn remove-grid-column + [parent _index] + parent) + +(defn remove-grid-row + [parent _index] + parent) + +;; TODO: Mix the cells given as arguments leaving only one. It should move all the shapes in those cells in the direction for the grid +;; and lastly use assign-cells to reassing the orphaned shapes +(defn merge-cells + [parent _cells] + parent) + + +;; TODO +;; Assign cells takes the children and move them into the aloted cells. If there are not enough cells it creates +;; not-tracked rows/columns and put the shapes there +;; Should be caled each time a child can be added like: +;; - On shape creation +;; - When moving a child from layers +;; - Moving from the transform into a cell and there are shapes without cell +;; - Shape duplication +;; - (maybe) create group/frames. This case will assigna a cell that had one of its children +(defn assign-cells + [parent] + #_(let [allocated-shapes + (into #{} (mapcat :shapes) (:layout-grid-cells parent)) + + no-cell-shapes + (->> (:shapes parent) (remove allocated-shapes))]) + parent) diff --git a/frontend/src/app/main/data/workspace/shape_layout.cljs b/frontend/src/app/main/data/workspace/shape_layout.cljs index 612cd16464..026b721440 100644 --- a/frontend/src/app/main/data/workspace/shape_layout.cljs +++ b/frontend/src/app/main/data/workspace/shape_layout.cljs @@ -1,4 +1,4 @@ -;; This Source Code Form is subject to the terms of the Mozilla Public +; This Source Code Form is subject to the terms of the Mozilla Public ;; License, v. 2.0. If a copy of the MPL was not distributed with this ;; file, You can obtain one at http://mozilla.org/MPL/2.0/. ;; @@ -54,6 +54,7 @@ (def initial-grid-layout ;; TODO {:layout :grid + :layout-grid-dir :row :layout-gap-type :multiple :layout-gap {:row-gap 0 :column-gap 0} :layout-align-items :start @@ -62,7 +63,6 @@ :layout-justify-content :start :layout-padding-type :simple :layout-padding {:p1 0 :p2 0 :p3 0 :p4 0} - :layout-grid-rows [] :layout-grid-columns []}) @@ -75,6 +75,7 @@ (fn [shape] (-> shape (merge initial-layout-data) + (cond-> (= type :grid) ctl/assign-cells) ;; If the original shape is not a frame we set clip content and show-viewer to false (cond-> (not from-frame?) (assoc :show-content true :hide-in-viewer true)))))) @@ -154,6 +155,13 @@ :layout-align-items :center :layout-gap layout-gap))))) +(defn shapes->grid-params + "Given the shapes calculate its flex parameters (horizontal vs vertical, gaps, etc)" + ([objects shapes] + (shapes->flex-params objects shapes nil)) + ([_objects _shapes _parent] + {})) + (defn create-layout-from-id [ids type from-frame?] (ptk/reify ::create-layout-from-id @@ -163,8 +171,10 @@ children-ids (into [] (mapcat #(get-in objects [% :shapes])) ids) children-shapes (map (d/getf objects) children-ids) parent (get objects (first ids)) - flex-params (when (d/not-empty? children-shapes) - (shapes->flex-params objects children-shapes parent)) + layout-params (when (d/not-empty? children-shapes) + (case type + :flex (shapes->flex-params objects children-shapes parent) + :grid (shapes->grid-params objects children-shapes parent))) undo-id (js/Symbol)] (rx/of (dwu/start-undo-transaction undo-id) (dwc/update-shapes ids (get-layout-initializer type from-frame?)) @@ -175,7 +185,7 @@ (not from-frame?) (-> (assoc :layout-item-h-sizing :auto :layout-item-v-sizing :auto) - (merge flex-params))))) + (merge layout-params))))) (ptk/data-event :layout/update ids) (dwc/update-shapes children-ids #(dissoc % :constraints-h :constraints-v)) (dwu/commit-undo-transaction undo-id)))))) @@ -183,7 +193,6 @@ ;; Never call this directly but through the data-event `:layout/update` ;; Otherwise a lot of cycle dependencies could be generated -(declare check-grid-cells-update) (defn- update-layout-positions [ids] (ptk/reify ::update-layout-positions @@ -191,16 +200,10 @@ (watch [_ state _] (let [objects (wsh/lookup-page-objects state) ids (->> ids (filter #(contains? objects %)))] - - (rx/concat - ;; Update grids if necesary - (rx/of (check-grid-cells-update - (->> (concat ids (map #(cph/get-parent-id objects %) ids)) - (filter #(ctl/grid-layout? objects %))))) - (if (d/not-empty? ids) - (let [modif-tree (dwm/create-modif-tree ids (ctm/reflow-modifiers))] - (rx/of (dwm/apply-modifiers {:modifiers modif-tree}))) - (rx/empty))))))) + (if (d/not-empty? ids) + (let [modif-tree (dwm/create-modif-tree ids (ctm/reflow-modifiers))] + (rx/of (dwm/apply-modifiers {:modifiers modif-tree}))) + (rx/empty)))))) (defn initialize [] @@ -321,15 +324,12 @@ is-frame? (= :frame (:type (first selected-shapes))) undo-id (js/Symbol)] - (if (and single? is-frame?) - (rx/of - (dwu/start-undo-transaction undo-id) + (rx/of + (dwu/start-undo-transaction undo-id) + (if (and single? is-frame?) (create-layout-from-id [(first selected)] type true) - (dwu/commit-undo-transaction undo-id)) - (rx/of - (dwu/start-undo-transaction undo-id) - (create-layout-from-selection type) - (dwu/commit-undo-transaction undo-id))))))) + (create-layout-from-selection type)) + (dwu/commit-undo-transaction undo-id)))))) (defn toggle-layout-flex [] @@ -359,14 +359,20 @@ (ptk/data-event :layout/update ids) (dwu/commit-undo-transaction undo-id)))))) -(defn update-grid-cells +#_(defn update-grid-cells [parent objects] - (let [children (cph/get-immediate-children objects (:id parent)) layout-grid-rows (:layout-grid-rows parent) layout-grid-columns (:layout-grid-columns parent) num-rows (count layout-grid-columns) num-columns (count layout-grid-columns) + layout-grid-cells (:layout-grid-cells parent) + + allocated-shapes + (into #{} (mapcat :shapes) (:layout-grid-cells parent)) + + no-cell-shapes + (->> children (:shapes parent) (remove allocated-shapes)) layout-grid-cells (for [[row-idx row] (d/enumerate layout-grid-rows) @@ -380,9 +386,9 @@ :col-span 1 :shapes (when shape [(:id shape)])}] [(:id cell-data) cell-data]))] - (assoc parent :layout-grid-cells layout-grid-cells))) + (assoc parent :layout-grid-cells (into {} layout-grid-cells)))) -(defn check-grid-cells-update +#_(defn check-grid-cells-update [ids] (ptk/reify ::check-grid-cells-update ptk/WatchEvent @@ -395,54 +401,56 @@ (-> shape (update-grid-cells objects))))))))) -(defn add-layout-column - [ids property value] +(defn add-layout-track + [ids type value] + (assert (#{:row :column} type)) (ptk/reify ::add-layout-column ptk/WatchEvent - (watch [_ state _] - (let [objects (wsh/lookup-page-objects state) - undo-id (js/Symbol)] + (watch [_ _ _] + (let [undo-id (js/Symbol)] (rx/of (dwu/start-undo-transaction undo-id) (dwc/update-shapes ids (fn [shape] - (-> shape - (update property (fnil conj []) value) - (update-grid-cells objects)))) + (case type + :row (ctl/add-grid-row shape value) + :column (ctl/add-grid-column shape value)))) (ptk/data-event :layout/update ids) (dwu/commit-undo-transaction undo-id)))))) -(defn remove-layout-column - [ids property index] +(defn remove-layout-track + [ids type index] + (assert (#{:row :column} type)) + (ptk/reify ::remove-layout-column ptk/WatchEvent - (watch [_ state _] - (let [objects (wsh/lookup-page-objects state) - undo-id (js/Symbol)] + (watch [_ _ _] + (let [undo-id (js/Symbol)] (rx/of (dwu/start-undo-transaction undo-id) (dwc/update-shapes ids (fn [shape] - (-> shape - (update property d/remove-at-index index) - (update-grid-cells objects)))) + (case type + :row (ctl/remove-grid-row shape index) + :column (ctl/remove-grid-column shape index)))) (ptk/data-event :layout/update ids) (dwu/commit-undo-transaction undo-id)))))) -(defn change-layout-column - [ids property index props] +(defn change-layout-track + [ids type index props] + (assert (#{:row :column} type)) (ptk/reify ::change-layout-column ptk/WatchEvent - (watch [_ state _] - (let [objects (wsh/lookup-page-objects state) - undo-id (js/Symbol)] + (watch [_ _ _] + (let [undo-id (js/Symbol) + property (case :row :layout-grid-rows + :column :layout-grid-columns)] (rx/of (dwu/start-undo-transaction undo-id) (dwc/update-shapes ids (fn [shape] (-> shape - (update-in [property index] merge props) - (update-grid-cells objects)))) + (update-in [property index] merge props)))) (ptk/data-event :layout/update ids) (dwu/commit-undo-transaction undo-id)))))) diff --git a/frontend/src/app/main/data/workspace/shapes.cljs b/frontend/src/app/main/data/workspace/shapes.cljs index f123efb69f..b79c545fc0 100644 --- a/frontend/src/app/main/data/workspace/shapes.cljs +++ b/frontend/src/app/main/data/workspace/shapes.cljs @@ -82,6 +82,7 @@ (ptk/reify ::add-shape ptk/WatchEvent (watch [it state _] + (.log js/console (clj->js attrs)) (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) selected (wsh/lookup-selected state) @@ -95,6 +96,7 @@ selected) index (:index (meta attrs)) + changes (-> (pcb/empty-changes it page-id) (pcb/with-objects objects) (cond-> (some? index) @@ -102,7 +104,10 @@ (cond-> (nil? index) (pcb/add-object shape)) (cond-> (some? (:parent-id attrs)) - (pcb/change-parent (:parent-id attrs) [shape]))) + (pcb/change-parent (:parent-id attrs) [shape])) + (cond-> (ctl/grid-layout? objects (:parent-id shape)) + (pcb/update-shapes [(:parent-id shape)] ctl/assign-cells)) + ) undo-id (js/Symbol)] (rx/concat @@ -133,7 +138,9 @@ (pcb/with-objects objects) (cond-> (not (ctl/any-layout? objects frame-id)) (pcb/update-shapes ordered-indexes ctl/remove-layout-item-data)) - (pcb/change-parent frame-id to-move-shapes 0)))] + (pcb/change-parent frame-id to-move-shapes 0) + (cond-> (ctl/grid-layout? objects frame-id) + (pcb/update-shapes [frame-id] ctl/assign-cells))))] (if (some? changes) (rx/of (dch/commit-changes changes)) diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index 656d2e9fbe..08c23c20f1 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -12,7 +12,8 @@ [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] - [app.common.geom.shapes.flex-layout :as gsl] + [app.common.geom.shapes.flex-layout :as gslf] + [app.common.geom.shapes.grid-layout :as gslg] [app.common.math :as mth] [app.common.pages.changes-builder :as pcb] [app.common.pages.helpers :as cph] @@ -474,7 +475,10 @@ exclude-frames (if mod? exclude-frames exclude-frames-siblings) target-frame (ctst/top-nested-frame objects position exclude-frames) flex-layout? (ctl/flex-layout? objects target-frame) - drop-index (when flex-layout? (gsl/get-drop-index target-frame objects position))] + grid-layout? (ctl/grid-layout? objects target-frame) + drop-index (cond + flex-layout? (gslf/get-drop-index target-frame objects position) + grid-layout? (gslg/get-drop-index target-frame objects position))] [move-vector target-frame drop-index]))) (rx/take-until stopper))] diff --git a/frontend/src/app/main/ui/workspace/sidebar/options.cljs b/frontend/src/app/main/ui/workspace/sidebar/options.cljs index 1847962c0a..9c98a763f1 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options.cljs @@ -6,7 +6,6 @@ (ns app.main.ui.workspace.sidebar.options (:require - [app.main.ui.workspace.sidebar.options.shapes.grid-cell :as grid-cell] [app.common.data :as d] [app.common.geom.shapes :as gsh] [app.common.pages.helpers :as cph] @@ -24,6 +23,7 @@ [app.main.ui.workspace.sidebar.options.shapes.bool :as bool] [app.main.ui.workspace.sidebar.options.shapes.circle :as circle] [app.main.ui.workspace.sidebar.options.shapes.frame :as frame] + [app.main.ui.workspace.sidebar.options.shapes.grid-cell :as grid-cell] [app.main.ui.workspace.sidebar.options.shapes.group :as group] [app.main.ui.workspace.sidebar.options.shapes.image :as image] [app.main.ui.workspace.sidebar.options.shapes.multiple :as multiple] @@ -74,9 +74,7 @@ shape-parent-frame (cph/get-frame objects (:frame-id first-selected-shape)) [grid-id {[row-selected col-selected] :selected}] - (d/seek (fn [[grid-id {:keys [selected]}]] - (some? selected)) - grid-edition) + (d/seek (fn [[_ {:keys [selected]}]] (some? selected)) grid-edition) grid-cell-selected? (and (some? grid-id) (some? row-selected) (some? col-selected)) 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 a25b8e75c6..1cc0397c6d 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 @@ -10,6 +10,7 @@ [app.common.data.macros :as dm] [app.main.data.workspace :as udw] [app.main.data.workspace.shape-layout :as dwsl] + [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.components.numeric-input :refer [numeric-input]] [app.main.ui.components.select :refer [select]] @@ -34,8 +35,7 @@ :layout-grid-dir ;; :row :column :layout-justify-items :layout-grid-columns - :layout-grid-rows - ]) + :layout-grid-rows]) (defn get-layout-flex-icon [type val is-col?] @@ -54,7 +54,7 @@ :center i/align-items-row-center :stretch i/align-items-row-strech :baseline i/align-items-row-baseline)) - + :justify-content (if is-col? (case val @@ -343,14 +343,24 @@ :disabled (and (= :nowrap wrap-type) (not is-col?))}]]]]) (mf/defc grid-edit-mode - [{:keys [active toggle-edit-mode] :as props}] - [:* - [:button.tooltip.tooltip-bottom-left - {:class (dom/classnames :active (= active true)) - :alt "Grid edit mode" - :on-click #(toggle-edit-mode) - :style {:padding 0}} - i/grid-layout-mode]]) + [{:keys [id] :as props}] + (let [edition (mf/deref refs/selected-edition) + active? (= id edition) + + toggle-edit-mode + (mf/use-callback + (mf/deps id edition) + (fn [] + (if-not active? + (st/emit! (udw/start-edition-mode id)) + (st/emit! :interrupt))))] + + [:button.tooltip.tooltip-bottom-left + {:class (dom/classnames :active active?) + :alt "Grid edit mode" + :on-click #(toggle-edit-mode) + :style {:padding 0}} + i/grid-layout-mode])) (mf/defc align-grid-row [{:keys [is-col? align-items set-align] :as props}] @@ -456,14 +466,15 @@ (st/emit! (dwsl/remove-layout ids)) (reset! open? false)) - ;; Uncomment when activating the grid options - set-flex (fn [] - (st/emit! (dwsl/remove-layout ids)) - (on-add-layout :flex)) + _set-flex + (fn [] + (st/emit! (dwsl/remove-layout ids)) + (on-add-layout :flex)) - set-grid (fn [] - (st/emit! (dwsl/remove-layout ids)) - (on-add-layout :grid)) + _set-grid + (fn [] + (st/emit! (dwsl/remove-layout ids)) + (on-add-layout :grid)) ;; Flex-direction @@ -575,33 +586,25 @@ (mf/use-callback (mf/deps ids) (fn [type value] - (if (= type :row) - (st/emit! (dwsl/add-layout-column ids :layout-grid-rows value)) - (st/emit! (dwsl/add-layout-column ids :layout-grid-columns value))))) + (st/emit! (dwsl/add-layout-track ids type value)))) remove-element (mf/use-callback (mf/deps ids) (fn [type index] - (if (= type :row) - (st/emit! (dwsl/remove-layout-column ids :layout-grid-rows index)) - (st/emit! (dwsl/remove-layout-column ids :layout-grid-columns index))))) + (st/emit! (dwsl/remove-layout-track ids type index)))) set-column-value (mf/use-callback (mf/deps ids) (fn [type index value] - (if (= type :row) - (st/emit! (dwsl/change-layout-column ids :layout-grid-rows index {:value value})) - (st/emit! (dwsl/change-layout-column ids :layout-grid-columns index {:value value}))))) + (st/emit! (dwsl/change-layout-track ids type index {:value value})))) set-column-type (mf/use-callback (mf/deps ids) - (fn [type index col-type] - (if (= type :row) - (st/emit! (dwsl/change-layout-column ids :layout-grid-rows index {:type col-type})) - (st/emit! (dwsl/change-layout-column ids :layout-grid-columns index {:type col-type})))))] + (fn [type index track-type] + (st/emit! (dwsl/change-layout-track ids type index {:type track-type}))))] [:div.element-set [:div.element-set-title @@ -609,7 +612,7 @@ [:span "Layout"] (if (and (not multiple) (:layout values)) [:div.title-actions - [:div.layout-btns + #_[:div.layout-btns [:button {:on-click set-flex :class (dom/classnames :active (= :flex layout-type))} "Flex"] @@ -622,8 +625,9 @@ (when (:layout values) (when (not= :multiple layout-type) - (if (= :flex layout-type) - ;; FLEX + (case layout-type + :flex + [:div.element-set-content.layout-menu [:div.layout-row [:div.direction-wrap.row-title "Direction"] @@ -673,7 +677,8 @@ :on-change-style change-padding-type :on-change on-padding-change}]] - ;; GRID + :grid + [:div.element-set-content.layout-menu [:div.layout-row [:div.direction-wrap.row-title "Direction"] @@ -687,10 +692,9 @@ :set-direction #(set-direction dir :grid) :icon? false}])]] - [:div.edit-mode - [:& grid-edit-mode - {:active false - :toggle-edit-mode ()}]]]] + (when (= 1 (count ids)) + [:div.edit-mode + [:& grid-edit-mode {:id (first ids)}]])]] [:div.layout-row [:div.align-items-grid.row-title "Align"] @@ -739,4 +743,8 @@ [:& padding-section {:values values :on-change-style change-padding-type - :on-change on-padding-change}]])))])) + :on-change on-padding-change}]] + + + ;; Default if not grid or flex + nil)))])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/grid_cell.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/grid_cell.cljs index f7afd62771..5b4f96dd87 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/grid_cell.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/grid_cell.cljs @@ -31,7 +31,7 @@ (mf/defc options {::mf/wrap [mf/memo]} - [{:keys [shape row column] :as props}] + [{:keys [_shape row column] :as props}] (let [position-mode (mf/use-state :auto) ;; TODO this should come from shape @@ -57,8 +57,9 @@ row-end (inc row) on-change - (fn [side orientation value] - (if (= orientation :column) + (fn [_side _orientation _value] + ;; TODO + #_(if (= orientation :column) (case side :all ((reset! column-start value) (reset! column-end value)) @@ -74,7 +75,7 @@ on-area-name-change (fn [value] (reset! area-name value)) - on-key-press (fn [event])] + on-key-press (fn [_event])] [:div.element-set [:div.element-set-title diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 007754eb76..18a1e6f77c 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -6,7 +6,6 @@ (ns app.main.ui.workspace.viewport (:require - [app.main.ui.workspace.viewport.grid-layout-editor :as grid-layout] [app.common.colors :as clr] [app.common.data :as d] [app.common.data.macros :as dm] @@ -30,6 +29,7 @@ [app.main.ui.workspace.viewport.drawarea :as drawarea] [app.main.ui.workspace.viewport.frame-grid :as frame-grid] [app.main.ui.workspace.viewport.gradients :as gradients] + [app.main.ui.workspace.viewport.grid-layout-editor :as grid-layout] [app.main.ui.workspace.viewport.guides :as guides] [app.main.ui.workspace.viewport.hooks :as hooks] [app.main.ui.workspace.viewport.interactions :as interactions] @@ -158,6 +158,7 @@ (and (some? drawing-obj) (= :path (:type drawing-obj)))) node-editing? (and edition (not= :text (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)) workspace-read-only? (mf/use-ctx ctx/workspace-read-only?) mode-inspect? (= options-mode :inspect) @@ -168,7 +169,7 @@ on-drag-enter (actions/on-drag-enter) on-drag-over (actions/on-drag-over) on-drop (actions/on-drop file) - on-mouse-down (actions/on-mouse-down @hover selected edition drawing-tool text-editing? node-editing? + on-mouse-down (actions/on-mouse-down @hover selected edition drawing-tool text-editing? node-editing? grid-editing? drawing-path? create-comment? space? panning z? workspace-read-only?) on-mouse-up (actions/on-mouse-up disable-paste) on-pointer-down (actions/on-pointer-down) @@ -199,6 +200,7 @@ show-pixel-grid? (and (contains? layout :show-pixel-grid) (>= zoom 8)) show-text-editor? (and editing-shape (= :text (:type editing-shape))) + show-grid-editor? (and editing-shape (ctl/grid-layout? editing-shape)) show-presence? page-id show-prototypes? (= options-mode :prototype) show-selection-handlers? (and (seq selected) (not show-text-editor?)) @@ -540,10 +542,9 @@ {:id (first selected) :zoom zoom}]) - (when-let [selected (first selected-shapes)] - (when (ctl/grid-layout? selected) - [:& grid-layout/editor - {:zoom zoom - :objects base-objects - :shape selected}])) + (when show-grid-editor? + [:& grid-layout/editor + {:zoom zoom + :objects base-objects + :shape (get 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 8cf782224f..237f2ef30c 100644 --- a/frontend/src/app/main/ui/workspace/viewport/actions.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/actions.cljs @@ -34,10 +34,10 @@ (defn on-mouse-down [{:keys [id blocked hidden type]} selected edition drawing-tool text-editing? - node-editing? drawing-path? create-comment? space? panning z? workspace-read-only?] + node-editing? grid-editing? drawing-path? create-comment? space? panning z? workspace-read-only?] (mf/use-callback (mf/deps id blocked hidden type selected edition drawing-tool text-editing? - node-editing? drawing-path? create-comment? @z? @space? + node-editing? grid-editing? drawing-path? create-comment? @z? @space? panning workspace-read-only?) (fn [bevent] (when (or (dom/class? (dom/get-target bevent) "viewport-controls") @@ -70,7 +70,7 @@ (do (st/emit! (ms/->MouseEvent :down ctrl? shift? alt? meta?)) - (when (and (not= edition id) text-editing?) + (when (and (not= edition id) (or text-editing? grid-editing?)) (st/emit! dw/clear-edition-mode)) (when (and (not text-editing?) diff --git a/frontend/src/app/main/ui/workspace/viewport/debug.cljs b/frontend/src/app/main/ui/workspace/viewport/debug.cljs index 8cd73894cc..1719fd2aad 100644 --- a/frontend/src/app/main/ui/workspace/viewport/debug.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/debug.cljs @@ -225,7 +225,7 @@ height (gpo/height-points parent-bounds) origin (gpo/origin parent-bounds) - {:keys [row-tracks column-tracks shape-cells]} + {:keys [row-tracks column-tracks]} (gsg/calc-layout-data parent children parent-bounds)] [:* @@ -236,7 +236,8 @@ :y1 (:y start-p) :x2 (:x end-p) :y2 (:y end-p) - :style {:stroke "red"}}])) + :style {:stroke "red" + :stroke-width (/ 1 zoom)}}])) (for [column-data column-tracks] (let [start-p (gpt/add origin (hv (:distance column-data))) @@ -245,4 +246,5 @@ :y1 (:y start-p) :x2 (:x end-p) :y2 (:y end-p) - :style {:stroke "red"}}]))])))) + :style {:stroke "red" + :stroke-width (/ 1 zoom)}}]))])))) 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 9910f63002..4bbfb68b8e 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 @@ -10,15 +10,12 @@ [app.common.data.macros :as dm] [app.common.geom.point :as gpt] [app.common.geom.shapes.grid-layout :as gsg] - [app.common.geom.shapes.grid-layout.layout-data :refer [set-sample-data] ] [app.common.geom.shapes.points :as gpo] [app.common.pages.helpers :as cph] - [app.common.types.shape.layout :as ctl] [app.main.data.workspace.grid-layout.editor :as dwge] [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.cursors :as cur] - [app.main.ui.icons :as i] [app.util.dom :as dom] [cuerdas.core :as str] [rumext.v2 :as mf])) @@ -211,7 +208,7 @@ (when (mf/ref-val dragging-ref) (let [start (mf/ref-val start-ref) pos (dom/get-client-position event) - delta (-> (gpt/to-vec start pos) + _delta (-> (gpt/to-vec start pos) (get (if (= type :column) :x :y)))] ;; TODO Implement resize @@ -268,7 +265,7 @@ height (gpo/height-points bounds) origin (gpo/origin bounds) - {:keys [row-tracks column-tracks shape-cells] :as layout-data} + {:keys [row-tracks column-tracks] :as layout-data} (gsg/calc-layout-data shape children bounds)] (mf/use-effect @@ -289,16 +286,15 @@ :type :row}]) (for [[_ {:keys [column row]}] (:layout-grid-cells shape)] - (let [] - [:& grid-cell {:shape shape - :layout-data layout-data - :row row - :column column - :bounds bounds - :zoom zoom - :hover? (contains? hover-cells [row column]) - :selected? (= selected-cells [row column]) - }])) + [:& grid-cell {:shape shape + :layout-data layout-data + :row row + :column column + :bounds bounds + :zoom zoom + :hover? (contains? hover-cells [row column]) + :selected? (= selected-cells [row column]) + }]) (for [[idx column-data] (d/enumerate column-tracks)] (let [start-p (-> origin (gpt/add (hv (:distance column-data)))) diff --git a/frontend/src/app/main/ui/workspace/viewport/widgets.cljs b/frontend/src/app/main/ui/workspace/viewport/widgets.cljs index be1d5372eb..261361df69 100644 --- a/frontend/src/app/main/ui/workspace/viewport/widgets.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/widgets.cljs @@ -9,6 +9,7 @@ [app.common.data :as d] [app.common.data.macros :as dm] [app.common.geom.point :as gpt] + [app.common.pages.helpers :as cph] [app.common.types.shape-tree :as ctt] [app.common.uuid :as uuid] [app.main.data.workspace :as dw] @@ -55,8 +56,11 @@ drawing (mf/deref refs/workspace-drawing) drawing-obj (:object drawing) shape (or drawing-obj (-> selected first))] - (when (or (and (= (count selected) 1) (= (:id shape) edition) (not= :text (:type shape))) - (and (some? drawing-obj) (= :path (:type drawing-obj)) + (when (or (and (= (count selected) 1) + (= (:id shape) edition) + (cph/path-shape? shape)) + (and (some? drawing-obj) + (cph/path-shape? drawing-obj) (not= :curve (:tool drawing)))) [:div.viewport-actions [:& path-actions {:shape shape}]])))