0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-23 21:21:22 -05:00

Merge pull request #2706 from penpot/alotor-flex-improvements

Flex improvements
This commit is contained in:
Alejandro 2022-12-29 12:06:47 +01:00 committed by GitHub
commit 690090acb4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 226 additions and 105 deletions

View file

@ -184,6 +184,7 @@
(let [frame (get objects frame-id)
position (gmt/transform-point-center position (gco/center-shape frame) (:transform-inverse frame))
children (->> (cph/get-immediate-children objects frame-id)
(remove :hidden)
(map #(vector (gpo/parent-coords-bounds (:points %) (:points frame)) %)))
layout-data (fli/calc-layout-data frame children (:points frame))
drop-areas (layout-drop-areas frame layout-data children)

View file

@ -169,8 +169,9 @@
[layout-line modif-tree]))]
(let [children (->> (:shapes parent)
(map (comp apply-modifiers (d/getf objects))))
(let [children (->> (cph/get-immediate-children objects (:id parent))
(remove :hidden)
(map apply-modifiers))
layout-data (gcl/calc-layout-data parent children @transformed-parent-bounds)
children (into [] (cond-> children (not (:reverse? layout-data)) reverse))
max-idx (dec (count children))
@ -209,7 +210,9 @@
(-> modifiers
(ctm/resize-parent (gpt/point 1 scale-height) origin (:transform parent) (:transform-inverse parent)))))
children (->> parent :shapes (map (d/getf objects)))
children (->> (cph/get-immediate-children objects parent-id)
(remove :hidden))
content-bounds
(when (and (d/not-empty? children) (or (ctl/auto-height? parent) (ctl/auto-width? parent)))
(gcl/layout-content-bounds bounds parent children))

View file

@ -193,7 +193,7 @@
m4 (or m4 0)]
(if (= layout-item-margin-type :multiple)
[m1 m2 m3 m4]
[m1 m1 m1 m1])))
[m1 m2 m1 m2])))
(defn child-height-margin
[child]

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" viewBox="0 0 132.292 132.292">
<path d="M11.583 0v11.232h11.306V0H11.583zm23.832 0v11.232h12.32V0h-12.32zm24.847 0v11.232h12.32V0h-12.32zM85.11 0v11.232h12.32V0H85.11zm24.847 0v11.232h11V0h-11zM22.399 22.608V60.45h-.016v11.18l.016.001v38.147h87.557v-87.17H22.399zm-10.816 98.451v11.233H22.89v-11.233H11.583zm98.373 0v11.233h11v-11.233h-11zm-74.541.001v11.233h12.32V121.06h-12.32zm24.847 0v11.233h12.32V121.06h-12.32zm24.847 0v11.233h12.32V121.06h-12.32z"/>
</svg>

After

Width:  |  Height:  |  Size: 531 B

View file

@ -1717,13 +1717,17 @@
padding: 1px;
}
.gap-group {
.gap-group,
.margin-item-group {
display: flex;
margin-top: 3px;
margin-bottom: 8px;
height: 26px;
.gap-row,
.gap-column,
.margin-item-row,
.margin-item-column,
.padding-row {
display: flex;
justify-content: center;
@ -1789,23 +1793,28 @@
grid-template-columns: auto 30px;
}
.margin-item-row {
grid-template-columns: auto 30px;
margin-bottom: 1rem;
}
.margin-row {
grid-template-columns: 65px auto;
}
.padding-row,
.margin-row {
.margin-item-row {
display: grid;
height: 26px;
.padding-icons,
.margin-icons {
.margin-item-icons {
display: flex;
padding: 0;
border: 1px solid $color-gray-60;
border-radius: 3px;
.padding-icon,
.margin-icon {
.margin-item-icon {
display: flex;
justify-content: center;
align-items: center;
@ -1832,7 +1841,8 @@
}
}
.padding-icons {
.padding-icons,
.margin-item-icons {
margin-bottom: 8px;
margin-top: 3px;
margin-right: 1px;

View file

@ -30,6 +30,7 @@
(s/every ::us/uuid))
(defonce page-change? #{:add-page :mod-page :del-page :mov-page})
(defonce update-layout-attr? #{:hidden})
(declare commit-changes)
@ -50,18 +51,30 @@
objects (wsh/lookup-page-objects state page-id)
ids (into [] (filter some?) ids)
changes (reduce
(fn [changes id]
(let [opts {:attrs attrs :ignore-geometry? (get ignore-tree id)}]
(pcb/update-shapes changes [id] update-fn opts)))
(-> (pcb/empty-changes it page-id)
(pcb/set-save-undo? save-undo?)
(pcb/with-objects objects))
ids)]
update-layout-ids
(->> ids
(map (d/getf objects))
(filter #(some update-layout-attr? (pcb/changed-attrs % update-fn {:attrs attrs})))
(map :id))
(when (seq (:redo-changes changes))
(let [changes (cond-> changes reg-objects? (pcb/resize-parents ids))]
(rx/of (commit-changes changes)))))))))
changes (reduce
(fn [changes id]
(let [opts {:attrs attrs :ignore-geometry? (get ignore-tree id)}]
(pcb/update-shapes changes [id] update-fn opts)))
(-> (pcb/empty-changes it page-id)
(pcb/set-save-undo? save-undo?)
(pcb/with-objects objects))
ids)]
(rx/concat
(if (seq (:redo-changes changes))
(let [changes (cond-> changes reg-objects? (pcb/resize-parents ids))]
(rx/of (commit-changes changes)))
(rx/empty))
;; Update layouts for properties marked
(if (d/not-empty? update-layout-ids)
(rx/of (ptk/data-event :layout/update update-layout-ids))
(rx/empty))))))))
(defn send-update-indices
[]

View file

@ -8,6 +8,7 @@
"Events related with shapes transformations"
(: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 :as gsh]
@ -516,14 +517,70 @@
(s/def ::direction #{:up :down :right :left})
(defn move-selected
(defn reorder-selected-layout-child
[direction]
(ptk/reify ::reorder-layout-child
ptk/WatchEvent
(watch [it state _]
(let [selected (wsh/lookup-selected state {:omit-blocked? true})
objects (wsh/lookup-page-objects state)
page-id (:current-page-id state)
get-new-position
(fn [parent-id position]
(let [parent (get objects parent-id)]
(when (ctl/layout? parent)
(if (or
(and (ctl/reverse? parent)
(or (= direction :left)
(= direction :up)))
(and (not (ctl/reverse? parent))
(or (= direction :right)
(= direction :down))))
(dec position)
(+ position 2)))))
add-children-position
(fn [[parent-id children]]
(let [children+position
(->> children
(keep #(let [new-position (get-new-position
parent-id
(cph/get-position-on-parent objects %))]
(when new-position
(vector % new-position))))
(sort-by second >))]
[parent-id children+position]))
change-parents-and-position
(->> selected
(group-by #(dm/get-in objects [% :parent-id]))
(map add-children-position)
(into {}))
changes
(->> change-parents-and-position
(reduce
(fn [changes [parent-id children]]
(->> children
(reduce
(fn [changes [child-id index]]
(pcb/change-parent changes parent-id
[(get objects child-id)]
index))
changes)))
(-> (pcb/empty-changes it page-id)
(pcb/with-objects objects))))]
(rx/of (dch/commit-changes changes)
(ptk/data-event :layout/update selected))))))
(defn nudge-selected-shapes
"Move shapes a fixed increment in one direction, from a keyboard action."
[direction shift?]
(us/verify ::direction direction)
(us/verify boolean? shift?)
(let [same-event (js/Symbol "same-event")]
(ptk/reify ::move-selected
(ptk/reify ::nudge-selected-shapes
IDeref
(-deref [_] direction)
@ -541,7 +598,7 @@
(let [selected (wsh/lookup-selected state {:omit-blocked? true})
nudge (get-in state [:profile :props :nudge] {:big 10 :small 1})
move-events (->> stream
(rx/filter (ptk/type? ::move-selected))
(rx/filter (ptk/type? ::nudge-selected-shapes))
(rx/filter #(= direction (deref %))))
stopper (->> move-events
(rx/debounce 100)
@ -556,12 +613,28 @@
(rx/map #(dwm/create-modif-tree selected (ctm/move-modifiers %)))
(rx/map (partial dwm/set-modifiers))
(rx/take-until stopper))
(rx/of (move-selected direction shift?)))
(rx/of (nudge-selected-shapes direction shift?)))
(rx/of (dwm/apply-modifiers)
(finish-transform))))
(rx/empty))))))
(defn move-selected
"Move shapes a fixed increment in one direction, from a keyboard action."
[direction shift?]
(us/verify ::direction direction)
(us/verify boolean? shift?)
(ptk/reify ::move-selected
ptk/WatchEvent
(watch [_ state _]
(let [objects (wsh/lookup-page-objects state)
selected (wsh/lookup-selected state {:omit-blocked? true})
selected-shapes (->> selected (map (d/getf objects)))]
(if (every? (partial ctl/layout-child? objects) selected-shapes)
(rx/of (reorder-selected-layout-child direction))
(rx/of (nudge-selected-shapes direction shift?)))))))
(s/def ::x number?)
(s/def ::y number?)
(s/def ::position

View file

@ -65,6 +65,7 @@
(def auto-height (icon-xref :auto-height))
(def auto-hug (icon-xref :auto-hug))
(def auto-margin-side (icon-xref :auto-margin-side))
(def auto-margin-both-sides (icon-xref :auto-margin-both-sides))
(def auto-margin (icon-xref :auto-margin))
(def auto-padding (icon-xref :auto-padding))
(def auto-padding-side (icon-xref :auto-padding-side))

View file

@ -35,39 +35,43 @@
[{:keys [values change-margin-style on-margin-change] :as props}]
(let [margin-type (or (:layout-item-margin-type values) :simple)
margins (if (nil? (:layout-item-margin values))
{:m1 0 :m2 0 :m3 0 :m4 0}
(:layout-item-margin values))
rx (if (or (= :multiple margins) (not (apply = (vals margins))))
"--"
(:m1 margins))]
m1 (if (and (not (= :multiple (:layout-item-margin values)))
(= (dm/get-in values [:layout-item-margin :m1])
(dm/get-in values [:layout-item-margin :m3])))
(dm/get-in values [:layout-item-margin :m1])
"--")
[:div.margin-row
[:div.margin-icons
[:div.margin-icon.tooltip.tooltip-bottom
{:class (dom/classnames :selected (= margin-type :simple))
:alt (tr "workspace.options.layout.margin-simple")
:on-click #(change-margin-style :simple)}
i/auto-margin]
[:div.margin-icon.tooltip.tooltip-bottom
{:class (dom/classnames :selected (= margin-type :multiple))
:alt (tr "workspace.options.layout.margin")
:on-click #(change-margin-style :multiple)}
i/auto-margin-side]]
[:div.wrapper
(cond
(= margin-type :simple)
[:div.tooltip.tooltip-bottom
{:alt (tr "workspace.options.layout.margin-all")}
[:div.input-element.mini
m2 (if (and (not (= :multiple (:layout-item-margin values)))
(= (dm/get-in values [:layout-item-margin :m2])
(dm/get-in values [:layout-item-margin :m4])))
(dm/get-in values [:layout-item-margin :m2])
"--")]
[:> numeric-input
{:placeholder "--"
:on-click #(dom/select-target %)
:on-change (partial on-margin-change :simple)
:value rx}]]]
[:div.layout-row.margin-item-row
(cond
(= margin-type :simple)
(= margin-type :multiple)
[:div.margin-item-group
[:div.margin-item-row.tooltip.tooltip-bottom-left
{:alt "Vertical margin"}
[:span.icon i/auto-margin-both-sides]
[:> numeric-input
{:placeholder "--"
:on-click #(dom/select-target %)
:on-change (partial on-margin-change :simple :m1)
:value m1}]]
[:div.margin-item-column.tooltip.tooltip-bottom-left
{:alt "Horizontal margin"}
[:span.icon.rotated i/auto-margin-both-sides]
[:> numeric-input
{:placeholder "--"
:on-click #(dom/select-target %)
:on-change (partial on-margin-change :simple :m2)
:value m2}]]]
(= margin-type :multiple)
[:div.wrapper
(for [num [:m1 :m2 :m3 :m4]]
[:div.tooltip.tooltip-bottom
{:key (dm/str "margin-" (d/name num))
@ -76,12 +80,19 @@
:m2 "Right"
:m3 "Bottom"
:m4 "Left")}
[:div.input-element.mini
[:div.input-element.auto
[:> numeric-input
{:placeholder "--"
:on-click #(dom/select-target %)
:on-change (partial on-margin-change num)
:value (or (-> values :layout-item-margin num) 0)}]]]))]]))
:on-change (partial on-margin-change :multiple num)
:value (num (:layout-item-margin values))}]]])])
[:div.margin-item-icons
[:div.margin-item-icon.tooltip.tooltip-bottom
{:class (dom/classnames :selected (= margin-type :multiple))
:alt "Margin - multiple"
:on-click #(change-margin-style (if (= margin-type :multiple) :simple :multiple))}
i/auto-margin]]]))
(mf/defc element-behavior
[{:keys [is-layout-container? is-layout-child? layout-item-h-sizing layout-item-v-sizing on-change-behavior] :as props}]
@ -146,10 +157,7 @@
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values" "type" "is-layout-child?"]))]}
[{:keys [ids values is-layout-child? is-layout-container?] :as props}]
(let [open? (mf/use-state false)
toggle-open (fn [] (swap! open? not))
selection-parents-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
(let [selection-parents-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
selection-parents (mf/deref selection-parents-ref)
change-margin-style
@ -165,10 +173,16 @@
is-col? (every? ctl/col? selection-parents)
on-margin-change
(fn [type val]
(if (= type :simple)
(st/emit! (dwsl/update-layout-child ids {:layout-item-margin {:m1 val :m2 val :m3 val :m4 val}}))
(st/emit! (dwsl/update-layout-child ids {:layout-item-margin {type val}}))))
(fn [type prop val]
(cond
(and (= type :simple) (= prop :m1))
(st/emit! (dwsl/update-layout-child ids {:layout-item-margin {:m1 val :m3 val}}))
(and (= type :simple) (= prop :m2))
(st/emit! (dwsl/update-layout-child ids {:layout-item-margin {:m2 val :m4 val}}))
:else
(st/emit! (dwsl/update-layout-child ids {:layout-item-margin {prop val}}))))
on-change-behavior
(fn [dir value]
@ -199,39 +213,38 @@
:change-margin-style change-margin-style
:on-margin-change on-margin-change}])
[:div.advanced-ops-container
[:button.advanced-ops.toltip.tooltip-bottom
{:on-click toggle-open
:alt (tr "workspace.options.layout-item.advanced-ops")}
[:span.icon i/actions]
[:span (tr "workspace.options.layout-item.advanced-ops")]]]
(when is-layout-child?
[:div.layout-row
[:div.row-title "Align"]
[:div.btn-wrapper
[:& align-self-row {:is-col? is-col?
:align-self align-self
:set-align-self set-align-self}]]])
(when @open?
[:div.advanced-ops-body
(when is-layout-child?
[:div.layout-row
[:div.direction-wrap.row-title "Align"]
[:div.btn-wrapper
[:& align-self-row {:is-col? is-col?
:align-self align-self
:set-align-self set-align-self}]]])
[:div.input-wrapper
(for [item [:layout-item-max-h :layout-item-min-h :layout-item-max-w :layout-item-min-w]]
[:div.tooltip.tooltip-bottom
{:key (d/name item)
:alt (tr (dm/str "workspace.options.layout-item.title." (d/name item)))
:class (dom/classnames "maxH" (= item :layout-item-max-h)
"minH" (= item :layout-item-min-h)
"maxW" (= item :layout-item-max-w)
"minW" (= item :layout-item-min-w))}
[:div.input-element
{:alt (tr (dm/str "workspace.options.layout-item." (d/name item)))}
[:> numeric-input
{:no-validate true
:min 0
:data-wrap true
:placeholder "--"
:on-click #(dom/select-target %)
:on-change (partial on-size-change item)
:value (get values item)
:nillable true}]]])]])]]))
[:div.advanced-ops-body
[:div.input-wrapper
(for [item (cond-> []
(= (:layout-item-h-sizing values) :fill)
(conj :layout-item-min-w :layout-item-max-w)
(= (:layout-item-v-sizing values) :fill)
(conj :layout-item-min-h :layout-item-max-h))]
[:div.tooltip.tooltip-bottom
{:key (d/name item)
:alt (tr (dm/str "workspace.options.layout-item.title." (d/name item)))
:class (dom/classnames "maxH" (= item :layout-item-max-h)
"minH" (= item :layout-item-min-h)
"maxW" (= item :layout-item-max-w)
"minW" (= item :layout-item-min-w))}
[:div.input-element
{:alt (tr (dm/str "workspace.options.layout-item." (d/name item)))}
[:> numeric-input
{:no-validate true
:min 0
:data-wrap true
:placeholder "--"
:on-click #(dom/select-target %)
:on-change (partial on-size-change item)
:value (get values item)
:nillable true}]]])]]]]))

View file

@ -35,7 +35,8 @@
shape (or selected-frame (get objects hover-top-frame-id))]
(when (and shape (:layout shape))
(let [children (cph/get-immediate-children objects (:id shape))
(let [children (->> (cph/get-immediate-children objects (:id shape))
(remove :hidden))
layout-bounds (gsl/layout-content-bounds (d/lazy-map (keys objects) #(dm/get-in objects [% :points])) shape children)]
[:g.debug-layout {:pointer-events "none"}
[:polygon {:points (->> layout-bounds (map #(dm/fmt "%, %" (:x %) (:y %))) (str/join " "))
@ -61,7 +62,8 @@
(let [row? (ctl/row? shape)
col? (ctl/col? shape)
children (cph/get-immediate-children objects (:id shape))
children (->> (cph/get-immediate-children objects (:id shape))
(remove :hidden))
layout-data (gsl/calc-layout-data shape children (:points shape))
layout-bounds (:layout-bounds layout-data)
@ -99,6 +101,7 @@
(when (and shape (:layout shape))
(let [children (->> (cph/get-immediate-children objects (:id shape))
(remove :hidden)
(map #(vector (gpo/parent-coords-bounds (:points %) (:points shape)) %)))
layout-data (gsl/calc-layout-data shape children (:points shape))
drop-areas (gsl/layout-drop-areas shape layout-data children)]
@ -164,7 +167,8 @@
parent-bounds (:points parent)]
(when (and (some? parent) (not= uuid/zero (:id parent)))
(let [children (cph/get-immediate-children objects (:id parent))]
(let [children (->> (cph/get-immediate-children objects (:id parent))
(remove :hidden))]
[:g.debug-parent-bounds {:pointer-events "none"}
(for [[idx child] (d/enumerate children)]
[:*