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

First draft of cell display

This commit is contained in:
alonso.torres 2023-02-16 17:15:27 +01:00
parent 6f99209a62
commit 4b7e93ab84
8 changed files with 339 additions and 55 deletions

View file

@ -12,5 +12,4 @@
(dm/export glld/calc-layout-data)
(dm/export glld/get-cell-data)
(dm/export glld/get-child-coordinates)
(dm/export glp/child-modifiers)

View file

@ -6,66 +6,144 @@
(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
[parent children]
(let [parent (assoc parent
:layout-grid-columns
[{:type :percent :value 25}
{:type :percent :value 25}
{:type :fixed :value 100}
;;{:type :auto}
;;{:type :fr :value 1}
]
:layout-grid-rows
[{:type :percent :value 50}
{:type :percent :value 50}
;;{:type :fixed :value 100}
;;{:type :auto}
;;{:type :fr :value 1}
])
num-rows (count (:layout-grid-rows parent))
num-columns (count (:layout-grid-columns parent))
layout-grid-cells
(into
{}
(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)
:column (inc col-idx)
:row-span 1
:col-span 1
:shapes (when shape [(:id shape)])}]
[(:id cell-data) cell-data])))
parent (assoc parent :layout-grid-cells layout-grid-cells)]
[parent children]))
(defn calculate-initial-track-values
[{:keys [type value]} total-value]
(case type
:percent
(let [value (/ (* total-value value) 100) ]
value)
:fixed
value
:auto
0
))
(defn calc-layout-data
[_parent _children transformed-parent-bounds]
(let [num-columns 3
num-rows 2
[parent children transformed-parent-bounds]
(let [
;; TODO: Delete when there is UI
[parent children] (set-sample-data parent children)
height (gpo/height-points transformed-parent-bounds)
width (gpo/width-points transformed-parent-bounds)
row-lines
(->> (range 0 num-rows)
(reduce (fn [[result start-dist] _]
(let [height (/ height num-rows)]
[(conj result {:distance start-dist
:height height})
(+ start-dist height)]))
;; Initialize tracks
column-tracks
(->> (:layout-grid-columns parent)
(map (fn [track]
(let [initial (calculate-initial-track-values track width)]
(assoc track :value initial)))))
[[] 0])
row-tracks
(->> (:layout-grid-rows parent)
(map (fn [track]
(let [initial (calculate-initial-track-values track height)]
(assoc track :value initial)))))
;; Go through cells to adjust auto sizes
;; Once auto sizes have been calculated we get calculate the `fr` with the remainining size and adjust the size
;; Adjust final distances
acc-track-distance
(fn [[result next-distance] data]
(let [result (conj result (assoc data :distance next-distance))
next-distance (+ next-distance (:value data))]
[result next-distance]))
column-tracks
(->> column-tracks
(reduce acc-track-distance [[] 0])
first)
column-lines
(->> (range 0 num-columns)
(reduce (fn [[result start-dist] _]
(let [width (/ width num-columns)]
[(conj result {:distance start-dist
:width width})
(+ start-dist width)]))
[[] 0])
first)]
{:columns 3
:rows 3
:row-lines row-lines
:column-lines column-lines}))
row-tracks
(->> row-tracks
(reduce acc-track-distance [[] 0])
first)
(defn get-child-coordinates
[{:keys [columns]} _child child-idx]
[;; Row
(quot child-idx columns)
;; column
(mod child-idx columns)])
shape-cells
(into {}
(mapcat (fn [[_ cell]]
(->> (:shapes cell)
(map #(vector % cell)))))
(:layout-grid-cells parent))
]
{:row-tracks row-tracks
:column-tracks column-tracks
:shape-cells shape-cells}))
(defn get-cell-data
[grid-data transformed-parent-bounds row col]
[{: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 %)
vv #(gpo/start-vv transformed-parent-bounds %)
hv #(gpo/start-hv transformed-parent-bounds %)
vv #(gpo/start-vv transformed-parent-bounds %)
{col-dist :distance width :width} (dm/get-in grid-data [:column-lines col])
{row-dist :distance height :height} (dm/get-in grid-data [:row-lines row])
grid-cell (get shape-cells (:id child))]
start-p
(-> origin
(gpt/add (hv col-dist))
(gpt/add (vv row-dist)))]
{:start-p start-p
:width width
:height height
:row row
:col col}))
(when (some? grid-cell)
(let [column (nth column-tracks (dec (:column grid-cell)) nil)
row (nth row-tracks (dec (:row grid-cell)) nil)
start-p (-> origin
(gpt/add (hv (:distance column)))
(gpt/add (vv (:distance row))))
]
(assoc grid-cell :start-p start-p)))))

View file

@ -218,14 +218,14 @@
(map apply-modifiers))
grid-data (gcgl/calc-layout-data parent children @transformed-parent-bounds)]
(loop [modif-tree modif-tree
child-idx 0
child (first children)
pending (rest children)]
(if (some? child)
(let [[row col] (gcgl/get-child-coordinates grid-data child child-idx)
cell-data (gcgl/get-cell-data grid-data @transformed-parent-bounds row col)
modif-tree (set-child-modifiers modif-tree cell-data child)]
(recur modif-tree (inc child-idx) (first pending) (rest pending)))
(let [cell-data (gcgl/get-cell-data grid-data @transformed-parent-bounds child)
modif-tree (cond-> modif-tree
(some? cell-data)
(set-child-modifiers cell-data child))]
(recur modif-tree (first pending) (rest pending)))
modif-tree)))))
(defn- calc-auto-modifiers

View file

@ -68,6 +68,7 @@
(defn get-layout-initializer
[type from-frame?]
(prn "??type" type)
(let [initial-layout-data
(case type
:flex initial-flex-layout
@ -156,6 +157,7 @@
(defn create-layout-from-id
[ids type from-frame?]
(.trace js/console "create-layout-from-id" type)
(ptk/reify ::create-layout-from-id
ptk/WatchEvent
(watch [_ state _]

View file

@ -403,7 +403,7 @@
:active (= :grid layout-type))} "Grid"]]
[:button.remove-layout {:on-click on-remove-layout} i/minus]]
[:button.add-page {:on-click on-add-layout} i/close])]]
[:button.add-page {:on-click #(on-add-layout :flex)} i/close])]]
(when (:layout values)
(when (not= :multiple layout-type)

View file

@ -6,6 +6,7 @@
(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]
@ -476,6 +477,11 @@
:disabled-guides? disabled-guides?
:modifiers modifiers}])
[:& grid-layout/editor
{:zoom zoom
:objects base-objects
:shape (first selected-shapes)}]
;; DEBUG LAYOUT DROP-ZONES
(when (debug? :layout-drop-zones)
[:& wvd/debug-drop-zones {:selected-shapes selected-shapes

View file

@ -215,7 +215,8 @@
(when (and (some? parent) (not= uuid/zero (:id parent)))
(let [children (->> (cph/get-immediate-children objects (:id parent))
(remove :hidden))
(remove :hidden)
(map #(vector (gpo/parent-coords-bounds (:points %) (:points parent)) %)))
hv #(gpo/start-hv parent-bounds %)
vv #(gpo/start-vv parent-bounds %)
@ -224,10 +225,11 @@
height (gpo/height-points parent-bounds)
origin (gpo/origin parent-bounds)
grid-layout (gsg/calc-layout-data parent children parent-bounds)]
{:keys [row-tracks column-tracks shape-cells]}
(gsg/calc-layout-data parent children parent-bounds)]
[:*
(for [row-data (:row-lines grid-layout)]
(for [row-data row-tracks]
(let [start-p (gpt/add origin (vv (:distance row-data)))
end-p (gpt/add start-p (hv width))]
[:line {:x1 (:x start-p)
@ -236,7 +238,7 @@
:y2 (:y end-p)
:style {:stroke "red"}}]))
(for [column-data (:column-lines grid-layout)]
(for [column-data column-tracks]
(let [start-p (gpt/add origin (hv (:distance column-data)))
end-p (gpt/add start-p (vv height))]
[:line {:x1 (:x start-p)

View file

@ -0,0 +1,197 @@
;; 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/.
;;
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.viewport.grid-layout-editor
(:require
[app.main.ui.icons :as i]
[app.common.geom.shapes.grid-layout.layout-data :refer [set-sample-data] ]
[cuerdas.core :as str]
[app.common.geom.point :as gpt]
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.geom.shapes.grid-layout :as gsg]
[app.common.geom.shapes.points :as gpo]
[app.common.pages.helpers :as cph]
[app.common.types.shape.layout :as ctl]
[app.main.refs :as refs]
[app.main.store :as st]
[rumext.v2 :as mf]))
(mf/defc track-marker
{::mf/wrap-props false}
[props]
(let [center (unchecked-get props "center")
value (unchecked-get props "value")
zoom (unchecked-get props "zoom")
p1 (-> center
(update :x - (/ 13 zoom))
(update :y - (/ 16 zoom)))
p2 (-> p1
(update :x + (/ 26 zoom)))
p3 (-> p2
(update :y + (/ 24 zoom)))
p4 (-> p3
(update :x - (/ 13 zoom))
(update :y + (/ 8 zoom)))
p5 (-> p4
(update :x - (/ 13 zoom))
(update :y - (/ 8 zoom)))
text-x (:x center)
text-y (:y center)]
[:g.grid-track-marker
[:polygon {:points (->> [p1 p2 p3 p4 p5]
(map #(dm/fmt "%,%" (:x %) (:y %)))
(str/join " "))
:style {:fill "#DB00FF"
:fill-opacity 0.3}}]
[:text {:x text-x
:y text-y
:width (/ 26.26 zoom)
:height (/ 32 zoom)
:font-size (/ 16 zoom)
:text-anchor "middle"
:dominant-baseline "middle"
:style {:fill "#DB00FF"}}
(dm/str value)]]))
(mf/defc editor
{::mf/wrap-props false}
[props]
(let [shape (unchecked-get props "shape")
objects (unchecked-get props "objects")
zoom (unchecked-get props "zoom")
bounds (:points shape)]
(when (ctl/grid-layout? shape)
(let [children (->> (cph/get-immediate-children objects (:id shape))
(remove :hidden)
(map #(vector (gpo/parent-coords-bounds (:points %) (:points shape)) %)))
hv #(gpo/start-hv bounds %)
vv #(gpo/start-vv bounds %)
width (gpo/width-points bounds)
height (gpo/height-points bounds)
origin (gpo/origin bounds)
{:keys [row-tracks column-tracks shape-cells]}
(gsg/calc-layout-data shape children bounds)
[shape children] (set-sample-data shape children)]
[:g.grid-editor
[:polygon {:points (->> [origin
(-> origin
(gpt/add (hv width)))
(-> origin
(gpt/add (hv width))
(gpt/subtract (vv (/ 40 zoom))))
(-> origin
(gpt/add (hv width))
(gpt/subtract (vv (/ 40 zoom)))
(gpt/subtract (hv (+ width (/ 40 zoom)))))
(-> origin
(gpt/add (hv width))
(gpt/subtract (vv (/ 40 zoom)))
(gpt/subtract (hv (+ width (/ 40 zoom))))
(gpt/add (vv (+ height (/ 40 zoom)))))
(-> origin
(gpt/add (hv width))
(gpt/subtract (vv (/ 40 zoom)))
(gpt/subtract (hv (+ width (/ 40 zoom))))
(gpt/add (vv (+ height (/ 40 zoom))))
(gpt/add (hv (/ 40 zoom))))]
(map #(dm/fmt "%,%" (:x %) (:y %)))
(str/join " "))
:style {:stroke "#DB00FF"
:stroke-width (/ 1 zoom)}}]
(let [start-p (-> origin (gpt/add (hv width)))]
[:*
[:rect {:x (:x start-p)
:y (- (:y start-p) (/ 40 zoom))
:width (/ 40 zoom)
:height (/ 40 zoom)
:style {:fill "#DB00FF"
:stroke "#DB00FF"
:stroke-width (/ 1 zoom)}}]
[:use {:x (+ (:x start-p) (/ 12 zoom))
:y (- (:y start-p) (/ 28 zoom))
:width (/ 16 zoom)
:height (/ 16 zoom)
:href (dm/str "#icon-plus")
:fill "white"}]])
(let [start-p (-> origin (gpt/add (vv height)))]
[:rect {:x (- (:x start-p) (/ 40 zoom))
:y (:y start-p)
:width (/ 40 zoom)
:height (/ 40 zoom)
:style {:fill "#DB00FF"
:stroke "#DB00FF"
:stroke-width (/ 1 zoom)}}])
(for [[idx column-data] (d/enumerate column-tracks)]
(let [start-p (-> origin
(gpt/add (hv (:distance column-data)))
(gpt/subtract (vv (/ 20 zoom))))]
[:& track-marker {:center start-p
:value (dm/str (inc idx))
:zoom zoom}]))
(for [[idx row-data] (d/enumerate row-tracks)]
(let [start-p (-> origin
(gpt/add (vv (:distance row-data)))
(gpt/subtract (hv (/ 20 zoom))))]
[:g {:transform (dm/fmt "rotate(-90 % %)" (:x start-p) (:y start-p))}
[:& track-marker {:center start-p
:value (dm/str (inc idx))
:zoom zoom}]]))
(for [[_ grid-cell] (:layout-grid-cells shape)]
(let [column (nth column-tracks (dec (:column grid-cell)) nil)
row (nth row-tracks (dec (:row grid-cell)) nil)
start-p (-> origin
(gpt/add (hv (:distance column)))
(gpt/add (vv (:distance row))))
end-p (-> start-p
(gpt/add (hv (:value column)))
(gpt/add (vv (:value row))))]
[:*
#_[:rect {:x (:x start-p)
:y (- (:y start-p) (/ 32 zoom) (/ 8 zoom))
:width (/ 26.26 zoom)
:height (/ 32 zoom)
:style {:fill "#DB00FF"
:fill-opacity 0.3}
}]
[:rect.cell-editor {:x (:x start-p)
:y (:y start-p)
:width (- (:x end-p) (:x start-p))
:height (- (:y end-p) (:y start-p))
:style {:stroke "#DB00FF"
:stroke-dasharray (str/join " " (map #(/ % zoom) [0 8]) )
:stroke-linecap "round"
:stroke-width (/ 2 zoom)}
}]]))]))))