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:
parent
6f99209a62
commit
4b7e93ab84
8 changed files with 339 additions and 55 deletions
|
@ -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)
|
||||
|
|
|
@ -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)))))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 _]
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)}
|
||||
}]]))]))))
|
Loading…
Add table
Reference in a new issue