0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-12 07:41:43 -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
[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]

View file

@ -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)))]

View file

@ -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)))))))

View file

@ -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]

View file

@ -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

View file

@ -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]

View file

@ -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

View file

@ -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))

View file

@ -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}]]]))

View file

@ -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))

View file

@ -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")

View file

@ -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)))))))

View file

@ -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"

View file

@ -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"