0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-24 07:29:08 -05:00

Merge pull request #2659 from penpot/alotor-flex-layout-features

Flex layout features
This commit is contained in:
Andrey Antukh 2022-12-14 09:07:40 +01:00 committed by GitHub
commit 507800ae4e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 195 additions and 58 deletions

View file

@ -8,7 +8,6 @@
(:require
[app.common.geom.point :as gpt]
[app.common.geom.shapes.points :as gpo]
[app.common.math :as mth]
[app.common.types.shape.layout :as ctl]))
(defn child-layout-bound-points
@ -55,38 +54,32 @@
(gpt/add (hv (/ width 2)))
(and col? h-end?)
(gpt/add (hv width)))]
(gpt/add (hv width)))
(cond-> [base-p]
(and (mth/almost-zero? min-width) (mth/almost-zero? min-height))
(conj (cond-> base-p
row?
(gpt/add (hv width))
;; We need some height/width to calculate the bounds. We stablish the minimum
min-width (max min-width 0.01)
min-height (max min-height 0.01)]
col?
(gpt/add (vv height))))
(-> [base-p]
(conj (cond-> base-p
(or row? h-start?)
(gpt/add (hv min-width))
(not (mth/almost-zero? min-width))
(conj (cond-> base-p
(or row? h-start?)
(gpt/add (hv min-width))
(and col? h-center?)
(gpt/add (hv (/ min-width 2)))
(and col? h-center?)
(gpt/add (hv (/ min-width 2)))
(and col? h-center?)
(gpt/subtract (hv min-width))))
(and col? h-center?)
(gpt/subtract (hv min-width))))
(conj (cond-> base-p
(or col? v-start?)
(gpt/add (vv min-height))
(not (mth/almost-zero? min-height))
(conj (cond-> base-p
(or col? v-start?)
(gpt/add (vv min-height))
(and row? v-center?)
(gpt/add (vv (/ min-height 2)))
(and row? v-center?)
(gpt/add (vv (/ min-height 2)))
(and row? v-end?)
(gpt/subtract (vv min-height)))))))
(and row? v-end?)
(gpt/subtract (vv min-height)))))))
(defn layout-content-bounds
[bounds {:keys [layout-padding] :as parent} children]
@ -107,8 +100,11 @@
child-bounds
(if (or (ctl/fill-height? child) (ctl/fill-height? child))
(child-layout-bound-points parent child parent-bounds child-bounds)
child-bounds)]
(gpo/parent-coords-bounds child-bounds parent-bounds)))]
child-bounds)
[margin-top margin-right margin-bottom margin-left] (ctl/child-margins child)]
(-> (gpo/parent-coords-bounds child-bounds parent-bounds)
(gpo/pad-points (- margin-top) (- margin-right) (- margin-bottom) (- margin-left)))))]
(as-> children $
(map child-bounds $)

View file

@ -32,6 +32,7 @@
ratio-width (/ target-width curr-width)
ratio-height (/ target-height curr-height)
scalev (gpt/point ratio-width ratio-height)]
(-> modifiers
(ctm/resize scalev origin transform transform-inverse))))
@ -41,7 +42,6 @@
corner (gpt/point bounds)
target-corner (gpt/round corner)
deltav (gpt/to-vec corner target-corner)]
(ctm/move modifiers deltav)))
(defn set-pixel-precision
@ -56,8 +56,10 @@
has-resize? (size-pixel-precision shape points))
points
(cond-> (:points shape)
has-resize? (gco/transform-points (ctm/modifiers->transform modifiers)))]
(if has-resize?
(-> (:points shape)
(gco/transform-points (ctm/modifiers->transform modifiers)) )
points)]
[modifiers points])]
(position-pixel-precision modifiers shape points)))

View file

@ -76,7 +76,6 @@
:layout :layout-container
:layout-dir :layout-container
:layout-gap :layout-container
:layout-type :layout-container
:layout-wrap-type :layout-container
:layout-padding-type :layout-container
:layout-padding :layout-container

View file

@ -50,7 +50,6 @@
(s/def ::row-gap ::us/safe-number)
(s/def ::column-gap ::us/safe-number)
(s/def ::layout-type #{:flex :grid})
(s/def ::layout-gap
(s/keys :opt-un [::row-gap ::column-gap]))
@ -60,7 +59,6 @@
::layout-flex-dir
::layout-gap
::layout-gap-type
::layout-type
::layout-wrap-type
::layout-padding-type
::layout-padding

View file

@ -28,6 +28,7 @@
[app.main.data.workspace.undo :as dwu]
[app.main.snap :as snap]
[app.main.streams :as ms]
[app.util.dom :as dom]
[beicon.core :as rx]
[cljs.spec.alpha :as s]
[potok.core :as ptk]))
@ -415,6 +416,14 @@
(rx/take 1)
(rx/map #(start-move from-position))))))
(defn set-ghost-displacement
[move-vector]
(ptk/reify ::set-ghost-displacement
ptk/EffectEvent
(effect [_ _ _]
(when-let [node (dom/get-element-by-class "ghost-outline")]
(dom/set-property! node "transform" (gmt/translate-matrix move-vector))))))
(defn- start-move
([from-position] (start-move from-position nil))
([from-position ids]
@ -501,6 +510,9 @@
(dwm/build-change-frame-modifiers objects selected target-frame drop-index)
(dwm/set-modifiers)))))
(->> move-stream
(rx/map (comp set-ghost-displacement first)))
;; Last event will write the modifiers creating the changes
(->> move-stream
(rx/last)
@ -508,10 +520,10 @@
(fn [[_ target-frame drop-index]]
(let [undo-id (uuid/next)]
(rx/of (dwu/start-undo-transaction undo-id)
(move-shapes-to-frame ids target-frame drop-index)
(dwm/apply-modifiers {:undo-transation? false})
(finish-transform)
(dwu/commit-undo-transaction undo-id))))))))))))))
(move-shapes-to-frame ids target-frame drop-index)
(dwm/apply-modifiers {:undo-transation? false})
(finish-transform)
(dwu/commit-undo-transaction undo-id))))))))))))))
(s/def ::direction #{:up :down :right :left})

View file

@ -332,16 +332,84 @@
:penpot:preserve-scroll ((d/nilf str) (:preserve-scroll interaction))}])])))
(defn- export-layout-container-data
[{:keys [layout
layout-flex-dir
layout-gap
layout-gap-type
layout-wrap-type
layout-padding-type
layout-padding
layout-justify-content
layout-align-items
layout-align-content]}]
(when layout
(mf/html
[:> "penpot:layout"
#js {:penpot:layout (d/name layout)
:penpot:layout-flex-dir (d/name layout-flex-dir)
:penpot:layout-gap-type (d/name layout-gap-type)
:penpot:layout-gap-row (:row-gap layout-gap)
:penpot:layout-gap-column (:column-gap layout-gap)
:penpot:layout-wrap-type (d/name layout-wrap-type)
:penpot:layout-padding-type (d/name layout-padding-type)
:penpot:layout-padding-p1 (:p1 layout-padding)
:penpot:layout-padding-p2 (:p2 layout-padding)
:penpot:layout-padding-p3 (:p3 layout-padding)
:penpot:layout-padding-p4 (:p4 layout-padding)
:penpot:layout-justify-content (d/name layout-justify-content)
:penpot:layout-align-items (d/name layout-align-items)
:penpot:layout-align-content (d/name layout-align-content)}])))
(defn- export-layout-item-data
[{:keys [layout-item-margin
layout-item-margin-type
layout-item-h-sizing
layout-item-v-sizing
layout-item-max-h
layout-item-min-h
layout-item-max-w
layout-item-min-w
layout-item-align-self]}]
(when (or layout-item-margin
layout-item-margin-type
layout-item-h-sizing
layout-item-v-sizing
layout-item-max-h
layout-item-min-h
layout-item-max-w
layout-item-min-w
layout-item-align-self)
(mf/html
[:> "penpot:layout-item"
#js {:penpot:layout-item-margin-m1 (:m1 layout-item-margin)
:penpot:layout-item-margin-m2 (:m2 layout-item-margin)
:penpot:layout-item-margin-m3 (:m3 layout-item-margin)
:penpot:layout-item-margin-m4 (:m4 layout-item-margin)
:penpot:layout-item-margin-type (d/name layout-item-margin-type)
:penpot:layout-item-h-sizing (d/name layout-item-h-sizing)
:penpot:layout-item-v-sizing (d/name layout-item-v-sizing)
:penpot:layout-item-max-h layout-item-max-h
:penpot:layout-item-min-h layout-item-min-h
:penpot:layout-item-max-w layout-item-max-w
:penpot:layout-item-min-w layout-item-min-w
:penpot:layout-item-align-self (d/name layout-item-align-self)}])))
(mf/defc export-data
[{:keys [shape]}]
(let [props (-> (obj/create) (add-data shape) (add-library-refs shape))]
[:> "penpot:shape" props
(export-shadow-data shape)
(export-blur-data shape)
(export-exports-data shape)
(export-svg-data shape)
(export-interactions-data shape)
(export-fills-data shape)
(export-strokes-data shape)
(export-grid-data shape)]))
(export-shadow-data shape)
(export-blur-data shape)
(export-exports-data shape)
(export-svg-data shape)
(export-interactions-data shape)
(export-fills-data shape)
(export-strokes-data shape)
(export-grid-data shape)
(export-layout-container-data shape)
(export-layout-item-data shape)]))

View file

@ -382,7 +382,6 @@
on-padding-change
(fn [type prop val]
(prn "??" type prop val)
(cond
(and (= type :simple) (= prop :p1))
(st/emit! (dwsl/update-layout ids {:layout-padding {:p1 val :p3 val}}))

View file

@ -11,6 +11,7 @@
[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.refs :as refs]
[app.main.ui.context :as ctx]
[app.main.ui.hooks :as ui-hooks]
@ -293,14 +294,25 @@
:modifiers modifiers}])
(when show-frame-outline?
[:& outline/shape-outlines
{:objects objects-modified
:hover #{(->> @hover-ids
(filter #(cph/frame-shape? (get base-objects %)))
(remove selected)
(first))}
:zoom zoom
:modifiers modifiers}])
(let [outlined-frame-id
(->> @hover-ids
(filter #(cph/frame-shape? (get base-objects %)))
(remove selected)
(first))
outlined-frame (get objects outlined-frame-id)]
[:*
[:& outline/shape-outlines
{:objects objects-modified
:hover #{outlined-frame-id}
:zoom zoom
:modifiers modifiers}]
(when (ctl/layout? outlined-frame)
[:g.ghost-outline
[:& outline/shape-outlines
{:objects base-objects
:selected selected
:zoom zoom}]])]))
(when show-outlines?
[:& outline/shape-outlines

View file

@ -75,8 +75,8 @@
points [start-p
(-> start-p (gpt/add (xv line-width)))
(-> start-p (gpt/add (xv line-width)) (gpt/add (yv line-height)))
(-> start-p (gpt/add (yv line-height)))
]]
(-> start-p (gpt/add (yv line-height)))]]
[:g.layout-line {:key (dm/str "line-" idx)}
[:polygon {:points (->> points (map #(dm/fmt "%, %" (:x %) (:y %))) (str/join " "))
:style {:stroke "red" :stroke-width (/ 2 zoom) :stroke-dasharray (dm/str (/ 10 zoom) " " (/ 5 zoom))}}]]))]))))

View file

@ -869,6 +869,54 @@
:style
parse-style))))
(defn add-layout-container-data [props node]
(if-let [data (get-data node :penpot:layout)]
(merge props
(d/without-nils
{:layout (get-meta data :layout keyword)
:layout-flex-dir (get-meta data :layout-flex-dir keyword)
:layout-wrap-type (get-meta data :layout-wrap-type keyword)
:layout-gap-type (get-meta data :layout-gap-type keyword)
:layout-gap
(d/without-nils
{:row-gap (get-meta data :layout-gap-row d/parse-double)
:column-gap (get-meta data :layout-gap-column d/parse-double)})
:layout-padding-type (get-meta data :layout-padding-type keyword)
:layout-padding
(d/without-nils
{:p1 (get-meta data :layout-padding-p1 d/parse-double)
:p2 (get-meta data :layout-padding-p2 d/parse-double)
:p3 (get-meta data :layout-padding-p3 d/parse-double)
:p4 (get-meta data :layout-padding-p4 d/parse-double)})
:layout-justify-content (get-meta data :layout-justify-content keyword)
:layout-align-items (get-meta data :layout-align-items keyword)
:layout-align-content (get-meta data :layout-align-content keyword)}))
props))
(defn add-layout-item-data [props node]
(if-let [data (get-data node :penpot:layout-item)]
(merge props
(d/without-nils
{:layout-item-margin
(d/without-nils
{:m1 (get-meta data :layout-item-margin-m1 d/parse-double)
:m2 (get-meta data :layout-item-margin-m2 d/parse-double)
:m3 (get-meta data :layout-item-margin-m3 d/parse-double)
:m4 (get-meta data :layout-item-margin-m4 d/parse-double)})
:layout-item-margin-type (get-meta data :layout-item-margin-type keyword)
:layout-item-h-sizing (get-meta data :layout-item-h-sizing keyword)
:layout-item-v-sizing (get-meta data :layout-item-v-sizing keyword)
:layout-item-max-h (get-meta data :layout-item-max-h d/parse-double)
:layout-item-min-h (get-meta data :layout-item-min-h d/parse-double)
:layout-item-max-w (get-meta data :layout-item-max-w d/parse-double)
:layout-item-min-w (get-meta data :layout-item-min-w d/parse-double)
:layout-item-align-self (get-meta data :layout-item-align-self keyword)}))
props))
(defn parse-data
[type node]
@ -894,7 +942,10 @@
(add-svg-content node))
(cond-> (= :frame type)
(add-frame-data node))
(-> (add-frame-data node)
(add-layout-container-data node)))
(add-layout-item-data node)
(cond-> (= :group type)
(add-group-data node))