0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-12 15:51:37 -05:00

Grid layout polishing

This commit is contained in:
alonso.torres 2023-05-30 17:52:11 +02:00
parent 03c64303f5
commit b13db69cf9
14 changed files with 179 additions and 116 deletions

View file

@ -8,9 +8,7 @@
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.geom.matrix :as gmt]
[app.common.geom.point :as gpt] [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.grid-layout.layout-data :as ld]
[app.common.geom.shapes.points :as gpo] [app.common.geom.shapes.points :as gpo]
[app.common.geom.shapes.transforms :as gtr] [app.common.geom.shapes.transforms :as gtr]

View file

@ -6,8 +6,11 @@
(ns app.main.data.workspace.common (ns app.main.data.workspace.common
(:require (:require
[app.common.data.macros :as dm]
[app.common.logging :as log] [app.common.logging :as log]
[app.common.types.shape.layout :as ctl]
[app.main.data.workspace.changes :as dch] [app.main.data.workspace.changes :as dch]
[app.main.data.workspace.state-helpers :as wsh]
[app.main.data.workspace.undo :as dwu] [app.main.data.workspace.undo :as dwu]
[app.util.router :as rt] [app.util.router :as rt]
[beicon.core :as rx] [beicon.core :as rx]
@ -53,10 +56,13 @@
(ptk/reify ::undo (ptk/reify ::undo
ptk/WatchEvent ptk/WatchEvent
(watch [it state _] (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)] drawing (get state :workspace-drawing)]
;; Editors handle their own undo's ;; 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) (let [undo (:workspace-undo state)
items (:items undo) items (:items undo)
index (or (:index undo) (dec (count items)))] index (or (:index undo) (dec (count items)))]
@ -64,14 +70,17 @@
(let [item (get items index) (let [item (get items index)
changes (:undo-changes item) changes (:undo-changes item)
undo-group (:undo-group 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
(find-first-group-idx index))] (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 (if undo-group
(rx/of (undo-to-index (dec undo-group-index))) (rx/of (undo-to-index (dec undo-group-index)))
(rx/of (dwu/materialize-undo changes (dec index)) (rx/of (dwu/materialize-undo changes (dec index))
@ -117,9 +126,11 @@
(ptk/reify ::undo-to-index (ptk/reify ::undo-to-index
ptk/WatchEvent ptk/WatchEvent
(watch [it state _] (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)] 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) (let [undo (:workspace-undo state)
items (:items undo) items (:items undo)
index (or (:index undo) (dec (count items)))] index (or (:index undo) (dec (count items)))]

View file

@ -45,4 +45,5 @@
(let [id (get-in state [:workspace-local :edition])] (let [id (get-in state [:workspace-local :edition])]
(-> state (-> state
(update :workspace-local dissoc :edition) (update :workspace-local dissoc :edition)
(dissoc :workspace-grid-edition)
(cond-> (some? id) (update-in [:workspace-local :edit-path] dissoc id))))))) (cond-> (some? id) (update-in [:workspace-local :edit-path] dissoc id)))))))

View file

@ -343,22 +343,21 @@
(create-layout-from-selection type)) (create-layout-from-selection type))
(dwu/commit-undo-transaction undo-id)))))) (dwu/commit-undo-transaction undo-id))))))
(defn toggle-layout-flex (defn toggle-layout
[] [type]
(ptk/reify ::toggle-layout-flex (ptk/reify ::toggle-layout-flex
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [page-id (:current-page-id state) (let [objects (wsh/lookup-page-objects state)
objects (wsh/lookup-page-objects state page-id)
selected (wsh/lookup-selected state) selected (wsh/lookup-selected state)
selected-shapes (map (d/getf objects) selected) selected-shapes (map (d/getf objects) selected)
single? (= (count selected-shapes) 1) 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)) (when (not= 0 (count selected))
(if has-flex-layout? (if has-layout?
(rx/of (remove-layout selected)) (rx/of (remove-layout selected))
(rx/of (create-layout :flex)))))))) (rx/of (create-layout type))))))))
(defn update-layout (defn update-layout
[ids changes] [ids changes]

View file

@ -219,7 +219,12 @@
:toggle-layout-flex {:tooltip (ds/shift "A") :toggle-layout-flex {:tooltip (ds/shift "A")
:command "shift+a" :command "shift+a"
:subsections [:modify-layers] :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 ;; TOOLS

View file

@ -413,9 +413,10 @@
is-frame? (and single? has-frame?) is-frame? (and single? has-frame?)
is-flex-container? (and is-frame? (= :flex (:layout (first shapes)))) is-flex-container? (and is-frame? (= :flex (:layout (first shapes))))
ids (->> shapes (map :id)) ids (->> shapes (map :id))
add-flex #(st/emit! (if is-frame? add-layout (fn [type]
(dwsl/create-layout-from-id ids :flex true) (st/emit! (if is-frame?
(dwsl/create-layout-from-selection :flex))) (dwsl/create-layout-from-id ids type true)
(dwsl/create-layout-from-selection type))))
remove-flex #(st/emit! (dwsl/remove-layout ids))] remove-flex #(st/emit! (dwsl/remove-layout ids))]
[:* [:*
@ -424,7 +425,10 @@
[:& menu-separator] [:& menu-separator]
[:& menu-entry {:title (tr "workspace.shape.menu.add-flex") [:& menu-entry {:title (tr "workspace.shape.menu.add-flex")
:shortcut (sc/get-tooltip :toggle-layout-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? (when is-flex-container?
[:div [:div
[:& menu-separator] [:& menu-separator]

View file

@ -7,8 +7,10 @@
(ns app.main.ui.workspace.sidebar.options (ns app.main.ui.workspace.sidebar.options
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.geom.shapes :as gsh] [app.common.geom.shapes :as gsh]
[app.common.pages.helpers :as cph] [app.common.pages.helpers :as cph]
[app.common.types.shape.layout :as ctl]
[app.main.data.workspace :as udw] [app.main.data.workspace :as udw]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [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.exports :refer [exports-menu]]
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell] [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.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.page :as page]
[app.main.ui.workspace.sidebar.options.shapes.bool :as bool] [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.circle :as circle]
@ -68,15 +71,15 @@
(let [drawing (mf/deref refs/workspace-drawing) (let [drawing (mf/deref refs/workspace-drawing)
objects (mf/deref refs/workspace-page-objects) objects (mf/deref refs/workspace-page-objects)
shared-libs (mf/deref refs/workspace-libraries) shared-libs (mf/deref refs/workspace-libraries)
edition (mf/deref refs/selected-edition)
grid-edition (mf/deref refs/workspace-grid-edition) grid-edition (mf/deref refs/workspace-grid-edition)
selected-shapes (into [] (keep (d/getf objects)) selected) selected-shapes (into [] (keep (d/getf objects)) selected)
first-selected-shape (first selected-shapes) first-selected-shape (first selected-shapes)
shape-parent-frame (cph/get-frame objects (:frame-id first-selected-shape)) shape-parent-frame (cph/get-frame objects (:frame-id first-selected-shape))
[grid-id {cell-id :selected}] edit-grid? (ctl/grid-layout? objects edition)
(d/seek (fn [[_ {:keys [selected]}]] (some? selected)) grid-edition) selected-cell (dm/get-in grid-edition [edition :selected])
grid-cell-selected? (and (some? grid-id) (some? cell-id))
on-change-tab on-change-tab
(fn [options-mode] (fn [options-mode]
@ -96,10 +99,15 @@
[:& align-options] [:& align-options]
[:& bool-options] [:& bool-options]
(cond (cond
grid-cell-selected? (some? selected-cell)
[:& grid-cell/options [:& grid-cell/options
{:shape (get objects grid-id) {:shape (get objects edition)
:cell (get-in objects [grid-id :layout-grid-cells cell-id])}] :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) (d/not-empty? drawing)
[:& shape-options [:& shape-options

View file

@ -238,7 +238,8 @@
[:button.btn-options {:disabled is-default [:button.btn-options {:disabled is-default
:on-click handle-set-as-default} (tr "workspace.options.grid.params.set-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) (let [id (:id shape)
saved-grids (mf/deref workspace-saved-grids) saved-grids (mf/deref workspace-saved-grids)
default-grid-params (mf/use-memo (mf/deps saved-grids) #(merge dw/default-grid-params saved-grids)) default-grid-params (mf/use-memo (mf/deps saved-grids) #(merge dw/default-grid-params saved-grids))

View file

@ -477,7 +477,7 @@
(mf/defc layout-container-menu (mf/defc layout-container-menu
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values" "multiple"]))]} {::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) (let [open? (mf/use-state false)
;; Display ;; Display
@ -594,53 +594,7 @@
(fn [value type] (fn [value type]
(if (= type :row) (if (= type :row)
(st/emit! (dwsl/update-layout ids {:layout-align-content value})) (st/emit! (dwsl/update-layout ids {:layout-align-content value}))
(st/emit! (dwsl/update-layout ids {:layout-justify-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})))))]
[:div.element-set [:div.element-set
[:div.element-set-title [:div.element-set-title
@ -751,36 +705,112 @@
:set-justify set-justify-grid}] :set-justify set-justify-grid}]
[:& justify-grid-row {:is-col? false [:& justify-grid-row {:is-col? false
:justify-items grid-justify-content-row :justify-items grid-justify-content-row
:set-justify set-justify-grid}]]] :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}]]
;; Default if not grid or flex ;; Default if not grid or flex
nil)))])) 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}]]]))

View file

@ -159,7 +159,7 @@
create-comment? (= :comments drawing-tool) create-comment? (= :comments drawing-tool)
drawing-path? (or (and edition (= :draw (get-in edit-path [edition :edit-mode]))) drawing-path? (or (and edition (= :draw (get-in edit-path [edition :edit-mode])))
(and (some? drawing-obj) (= :path (:type drawing-obj)))) (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]))) text-editing? (and edition (= :text (get-in base-objects [edition :type])))
grid-editing? (and edition (ctl/grid-layout? base-objects edition)) grid-editing? (and edition (ctl/grid-layout? base-objects edition))

View file

@ -231,8 +231,8 @@
(mf/use-fn (mf/use-fn
(mf/deps @hover @hover-ids workspace-read-only?) (mf/deps @hover @hover-ids workspace-read-only?)
(fn [event] (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") (when (or (dom/class? (dom/get-target event) "viewport-controls")
(dom/child? (dom/get-target event) (dom/query ".viewport-controls")) (dom/child? (dom/get-target event) (dom/query ".viewport-controls"))
(dom/class? (dom/get-target event) "viewport-selrect") (dom/class? (dom/get-target event) "viewport-selrect")

View file

@ -354,5 +354,5 @@
(do (st/emit! (dsc/push-shortcuts ::path psc/shortcuts)) (do (st/emit! (dsc/push-shortcuts ::path psc/shortcuts))
#(st/emit! (dsc/pop-shortcuts ::path))) #(st/emit! (dsc/pop-shortcuts ::path)))
text-editing? text-editing?
(do (st/emit! (dsc/push-shortcuts ::text tsc/shortcuts)) (do (st/emit! (dsc/push-shortcuts ::text tsc/shortcuts))
#(st/emit! (dsc/pop-shortcuts ::text))))))) #(st/emit! (dsc/pop-shortcuts ::text)))))))

View file

@ -4379,6 +4379,9 @@ msgstr "Updating %s..."
msgid "workspace.shape.menu.add-flex" msgid "workspace.shape.menu.add-flex"
msgstr "Add flex layout" msgstr "Add flex layout"
msgid "workspace.shape.menu.add-grid"
msgstr "Add grid layout"
#: src/app/main/ui/workspace/context_menu.cljs #: src/app/main/ui/workspace/context_menu.cljs
msgid "workspace.shape.menu.back" msgid "workspace.shape.menu.back"
msgstr "Send to back" msgstr "Send to back"

View file

@ -4481,6 +4481,9 @@ msgstr "Actualizando %s..."
msgid "workspace.shape.menu.add-flex" msgid "workspace.shape.menu.add-flex"
msgstr "Añadir flex layout" msgstr "Añadir flex layout"
msgid "workspace.shape.menu.add-grid"
msgstr "Añadir grid layout"
#: src/app/main/ui/workspace/context_menu.cljs #: src/app/main/ui/workspace/context_menu.cljs
msgid "workspace.shape.menu.back" msgid "workspace.shape.menu.back"
msgstr "Enviar al fondo" msgstr "Enviar al fondo"