mirror of
https://github.com/penpot/penpot.git
synced 2025-02-13 10:38:13 -05:00
Merge pull request #2088 from penpot/alotor-autolayout
Autolayout basics
This commit is contained in:
commit
dd180d93f4
30 changed files with 1309 additions and 557 deletions
|
@ -14,6 +14,8 @@
|
|||
[app.common.geom.shapes.constraints :as gct]
|
||||
[app.common.geom.shapes.corners :as gsc]
|
||||
[app.common.geom.shapes.intersect :as gin]
|
||||
[app.common.geom.shapes.layout :as gcl]
|
||||
[app.common.geom.shapes.modifiers :as gsm]
|
||||
[app.common.geom.shapes.path :as gsp]
|
||||
[app.common.geom.shapes.rect :as gpr]
|
||||
[app.common.geom.shapes.transforms :as gtr]
|
||||
|
@ -170,10 +172,15 @@
|
|||
(dm/export gtr/modifiers->transform)
|
||||
(dm/export gtr/empty-modifiers?)
|
||||
(dm/export gtr/move-position-data)
|
||||
(dm/export gtr/apply-transform)
|
||||
|
||||
;; Constratins
|
||||
(dm/export gct/calc-child-modifiers)
|
||||
|
||||
;; Layout
|
||||
(dm/export gcl/calc-layout-data)
|
||||
(dm/export gcl/calc-layout-modifiers)
|
||||
|
||||
;; PATHS
|
||||
(dm/export gsp/content->selrect)
|
||||
(dm/export gsp/transform-content)
|
||||
|
@ -196,3 +203,6 @@
|
|||
;; Corners
|
||||
(dm/export gsc/shape-corners-1)
|
||||
(dm/export gsc/shape-corners-4)
|
||||
|
||||
;; Modifiers
|
||||
(dm/export gsm/set-objects-modifiers)
|
||||
|
|
|
@ -197,6 +197,9 @@
|
|||
;; Build final child modifiers. Apply transform again to the result, to get the
|
||||
;; real modifiers that need to be applied to the child, including rotation as needed.
|
||||
(cond-> {}
|
||||
(some? (:displacement-after modifiers))
|
||||
(assoc :displacement-after (:displacement-after modifiers))
|
||||
|
||||
(or (contains? modifiers-h :displacement)
|
||||
(contains? modifiers-v :displacement))
|
||||
(assoc :displacement (cond-> (gpt/point (get-in modifiers-h [:displacement :x] 0)
|
||||
|
|
327
common/src/app/common/geom/shapes/layout.cljc
Normal file
327
common/src/app/common/geom/shapes/layout.cljc
Normal file
|
@ -0,0 +1,327 @@
|
|||
;; 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) UXBOX Labs SL
|
||||
|
||||
(ns app.common.geom.shapes.layout
|
||||
(:require
|
||||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes.rect :as gre]))
|
||||
|
||||
;; :layout ;; true if active, false if not
|
||||
;; :layout-dir ;; :right, :left, :top, :bottom
|
||||
;; :layout-gap ;; number could be negative
|
||||
;; :layout-type ;; :packed, :space-between, :space-around
|
||||
;; :layout-wrap-type ;; :wrap, :no-wrap
|
||||
;; :layout-padding-type ;; :simple, :multiple
|
||||
;; :layout-padding ;; {:p1 num :p2 num :p3 num :p4 num} number could be negative
|
||||
;; :layout-h-orientation ;; :top, :center, :bottom
|
||||
;; :layout-v-orientation ;; :left, :center, :right
|
||||
|
||||
(defn col?
|
||||
[{:keys [layout-dir]}]
|
||||
(or (= :right layout-dir) (= :left layout-dir)))
|
||||
|
||||
(defn row?
|
||||
[{:keys [layout-dir]}]
|
||||
(or (= :top layout-dir) (= :bottom layout-dir)))
|
||||
|
||||
(defn h-start?
|
||||
[{:keys [layout-h-orientation]}]
|
||||
(= layout-h-orientation :left))
|
||||
|
||||
(defn h-center?
|
||||
[{:keys [layout-h-orientation]}]
|
||||
(= layout-h-orientation :center))
|
||||
|
||||
(defn h-end?
|
||||
[{:keys [layout-h-orientation]}]
|
||||
(= layout-h-orientation :right))
|
||||
|
||||
(defn v-start?
|
||||
[{:keys [layout-v-orientation]}]
|
||||
(= layout-v-orientation :top))
|
||||
|
||||
(defn v-center?
|
||||
[{:keys [layout-v-orientation]}]
|
||||
(= layout-v-orientation :center))
|
||||
|
||||
(defn v-end?
|
||||
[{:keys [layout-v-orientation]}]
|
||||
(= layout-v-orientation :bottom))
|
||||
|
||||
(defn add-padding [transformed-rect {:keys [layout-padding-type layout-padding]}]
|
||||
(let [{:keys [p1 p2 p3 p4]} layout-padding
|
||||
[p1 p2 p3 p4]
|
||||
(if (= layout-padding-type :multiple)
|
||||
[p1 p2 p3 p4]
|
||||
[p1 p1 p1 p1])]
|
||||
|
||||
(-> transformed-rect
|
||||
(update :y + p1)
|
||||
(update :width - p2 p3)
|
||||
(update :x + p3)
|
||||
(update :height - p1 p4))))
|
||||
|
||||
(defn calc-layout-lines
|
||||
[{:keys [layout-gap layout-wrap-type] :as shape} children {:keys [width height] :as layout-bounds}]
|
||||
|
||||
(let [wrap? (= layout-wrap-type :wrap)
|
||||
|
||||
reduce-fn
|
||||
(fn [[{:keys [line-width line-height num-children] :as line-data} result] child]
|
||||
(let [child-bounds (-> child :points gre/points->rect)
|
||||
next-width (-> child-bounds :width)
|
||||
next-height (-> child-bounds :height)]
|
||||
|
||||
(if (and (some? line-data)
|
||||
(or (not wrap?)
|
||||
(and (col? shape) (<= (+ line-width next-width (* layout-gap num-children)) width))
|
||||
(and (row? shape) (<= (+ line-height next-height (* layout-gap num-children)) height))))
|
||||
|
||||
[{:line-width (if (col? shape) (+ line-width next-width) (max line-width next-width))
|
||||
:line-height (if (row? shape) (+ line-height next-height) (max line-height next-height))
|
||||
:num-children (inc num-children)}
|
||||
result]
|
||||
|
||||
[{:line-width next-width
|
||||
:line-height next-height
|
||||
:num-children 1}
|
||||
(cond-> result (some? line-data) (conj line-data))])))
|
||||
|
||||
[line-data layout-lines] (reduce reduce-fn [nil []] children)]
|
||||
|
||||
(cond-> layout-lines (some? line-data) (conj line-data))))
|
||||
|
||||
(defn calc-layout-lines-position
|
||||
[{:keys [layout-gap layout-type] :as shape} {:keys [x y width height]} layout-lines]
|
||||
|
||||
(letfn [(get-base-line
|
||||
[total-width total-height]
|
||||
|
||||
(let [base-x
|
||||
(cond
|
||||
(and (row? shape) (h-center? shape))
|
||||
(+ x (/ (- width total-width) 2))
|
||||
|
||||
(and (row? shape) (h-end? shape))
|
||||
(+ x width (- total-width))
|
||||
|
||||
:else x)
|
||||
|
||||
base-y
|
||||
(cond
|
||||
(and (col? shape) (v-center? shape))
|
||||
(+ y (/ (- height total-height) 2))
|
||||
|
||||
(and (col? shape) (v-end? shape))
|
||||
(+ y height (- total-height))
|
||||
|
||||
:else y)]
|
||||
|
||||
[base-x base-y]))
|
||||
|
||||
(get-start-line
|
||||
[{:keys [line-width line-height num-children]} base-x base-y]
|
||||
|
||||
(let [children-gap (* layout-gap (dec num-children))
|
||||
|
||||
start-x
|
||||
(cond
|
||||
(or (and (col? shape) (= :space-between layout-type))
|
||||
(and (col? shape) (= :space-around layout-type)))
|
||||
x
|
||||
|
||||
(and (col? shape) (h-center? shape))
|
||||
(- (+ x (/ width 2)) (/ (+ line-width children-gap) 2))
|
||||
|
||||
(and (col? shape) (h-end? shape))
|
||||
(- (+ x width) (+ line-width children-gap))
|
||||
|
||||
(and (row? shape) (h-center? shape))
|
||||
(+ base-x (/ line-width 2))
|
||||
|
||||
(and (row? shape) (h-end? shape))
|
||||
(+ base-x line-width)
|
||||
|
||||
(row? shape)
|
||||
base-x
|
||||
|
||||
:else
|
||||
x)
|
||||
|
||||
start-y
|
||||
(cond
|
||||
(or (and (row? shape) (= :space-between layout-type))
|
||||
(and (row? shape) (= :space-around layout-type)))
|
||||
y
|
||||
|
||||
(and (row? shape) (v-center? shape))
|
||||
(- (+ y (/ height 2)) (/ (+ line-height children-gap) 2))
|
||||
|
||||
(and (row? shape) (v-end? shape))
|
||||
(- (+ y height) (+ line-height children-gap))
|
||||
|
||||
(and (col? shape) (v-center? shape))
|
||||
(+ base-y (/ line-height 2))
|
||||
|
||||
(and (col? shape) (v-end? shape))
|
||||
(+ base-y line-height)
|
||||
|
||||
(col? shape)
|
||||
base-y
|
||||
|
||||
:else
|
||||
y)]
|
||||
[start-x start-y]))
|
||||
|
||||
(get-next-line
|
||||
[{:keys [line-width line-height]} base-x base-y]
|
||||
(let [next-x (if (col? shape) base-x (+ base-x line-width layout-gap))
|
||||
next-y (if (row? shape) base-y (+ base-y line-height layout-gap))]
|
||||
[next-x next-y]))
|
||||
|
||||
(add-lines [[total-width total-height] {:keys [line-width line-height]}]
|
||||
[(+ total-width line-width)
|
||||
(+ total-height line-height)])
|
||||
|
||||
(add-starts [[result base-x base-y] layout-line]
|
||||
(let [[start-x start-y] (get-start-line layout-line base-x base-y)
|
||||
[next-x next-y] (get-next-line layout-line base-x base-y)]
|
||||
[(conj result
|
||||
(assoc layout-line
|
||||
:start-x start-x
|
||||
:start-y start-y))
|
||||
next-x
|
||||
next-y]))]
|
||||
|
||||
(let [[total-width total-height]
|
||||
(->> layout-lines (reduce add-lines [0 0]))
|
||||
|
||||
total-width (+ total-width (* layout-gap (dec (count layout-lines))))
|
||||
total-height (+ total-height (* layout-gap (dec (count layout-lines))))
|
||||
|
||||
[base-x base-y]
|
||||
(get-base-line total-width total-height)
|
||||
|
||||
[layout-lines _ _ _ _]
|
||||
(reduce add-starts [[] base-x base-y] layout-lines)]
|
||||
layout-lines)))
|
||||
|
||||
(defn calc-layout-line-data
|
||||
[{:keys [layout-type layout-gap] :as shape}
|
||||
{:keys [width height] :as layout-bounds}
|
||||
{:keys [num-children line-width line-height] :as line-data}]
|
||||
|
||||
(let [layout-gap
|
||||
(cond
|
||||
(= :packed layout-type)
|
||||
layout-gap
|
||||
|
||||
(= :space-around layout-type)
|
||||
0
|
||||
|
||||
(and (col? shape) (= :space-between layout-type))
|
||||
(/ (- width line-width) (dec num-children))
|
||||
|
||||
(and (row? shape) (= :space-between layout-type))
|
||||
(/ (- height line-height) (dec num-children)))
|
||||
|
||||
margin-x
|
||||
(if (and (col? shape) (= :space-around layout-type))
|
||||
(/ (- width line-width) (inc num-children) )
|
||||
0)
|
||||
|
||||
margin-y
|
||||
(if (and (row? shape) (= :space-around layout-type))
|
||||
(/ (- height line-height) (inc num-children))
|
||||
0)]
|
||||
|
||||
(assoc line-data
|
||||
:layout-gap layout-gap
|
||||
:margin-x margin-x
|
||||
:margin-y margin-y)))
|
||||
|
||||
|
||||
(defn calc-layout-data
|
||||
"Digest the layout data to pass it to the constrains"
|
||||
[{:keys [layout-dir] :as shape} children layout-bounds]
|
||||
|
||||
(let [reverse? (or (= :left layout-dir) (= :bottom layout-dir))
|
||||
layout-bounds (-> layout-bounds (add-padding shape))
|
||||
children (cond->> children reverse? reverse)
|
||||
layout-lines
|
||||
(->> (calc-layout-lines shape children layout-bounds)
|
||||
(calc-layout-lines-position shape layout-bounds)
|
||||
(map (partial calc-layout-line-data shape layout-bounds)))]
|
||||
|
||||
{:layout-lines layout-lines
|
||||
:reverse? reverse?}))
|
||||
|
||||
(defn next-p
|
||||
"Calculates the position for the current shape given the layout-data context"
|
||||
[shape
|
||||
{:keys [width height]}
|
||||
{:keys [start-x start-y layout-gap margin-x margin-y] :as layout-data}]
|
||||
|
||||
(let [pos-x
|
||||
(cond
|
||||
(and (row? shape) (h-center? shape))
|
||||
(- start-x (/ width 2))
|
||||
|
||||
(and (row? shape) (h-end? shape))
|
||||
(- start-x width)
|
||||
|
||||
:else
|
||||
start-x)
|
||||
|
||||
pos-y
|
||||
(cond
|
||||
(and (col? shape) (v-center? shape))
|
||||
(- start-y (/ height 2))
|
||||
|
||||
(and (col? shape) (v-end? shape))
|
||||
(- start-y height)
|
||||
|
||||
:else
|
||||
start-y)
|
||||
|
||||
pos-x (cond-> pos-x (some? margin-x) (+ margin-x))
|
||||
pos-y (cond-> pos-y (some? margin-y) (+ margin-y))
|
||||
|
||||
corner-p (gpt/point pos-x pos-y)
|
||||
|
||||
next-x
|
||||
(if (col? shape)
|
||||
(+ start-x width layout-gap)
|
||||
start-x)
|
||||
|
||||
next-y
|
||||
(if (row? shape)
|
||||
(+ start-y height layout-gap)
|
||||
start-y)
|
||||
|
||||
next-x (cond-> next-x (some? margin-x) (+ margin-x))
|
||||
next-y (cond-> next-y (some? margin-y) (+ margin-y))
|
||||
|
||||
layout-data
|
||||
(assoc layout-data :start-x next-x :start-y next-y)]
|
||||
[corner-p layout-data]))
|
||||
|
||||
(defn calc-layout-modifiers
|
||||
"Calculates the modifiers for the layout"
|
||||
[parent transform child layout-data]
|
||||
|
||||
(let [bounds (-> child :points gre/points->selrect)
|
||||
|
||||
[corner-p layout-data] (next-p parent bounds layout-data)
|
||||
|
||||
delta-p (-> corner-p
|
||||
(gpt/subtract (gpt/point bounds))
|
||||
(cond-> (some? transform) (gpt/transform transform)))
|
||||
|
||||
modifiers {:displacement-after (gmt/translate-matrix delta-p)}]
|
||||
|
||||
[modifiers layout-data]))
|
286
common/src/app/common/geom/shapes/modifiers.cljc
Normal file
286
common/src/app/common/geom/shapes/modifiers.cljc
Normal file
|
@ -0,0 +1,286 @@
|
|||
;; 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) UXBOX Labs SL
|
||||
|
||||
(ns app.common.geom.shapes.modifiers
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes.common :as gco]
|
||||
[app.common.geom.shapes.constraints :as gct]
|
||||
[app.common.geom.shapes.layout :as gcl]
|
||||
[app.common.geom.shapes.rect :as gpr]
|
||||
[app.common.geom.shapes.transforms :as gtr]
|
||||
[app.common.math :as mth]
|
||||
[app.common.uuid :as uuid]))
|
||||
|
||||
(defn set-pixel-precision
|
||||
"Adjust modifiers so they adjust to the pixel grid"
|
||||
[modifiers shape]
|
||||
|
||||
(if (some? (:resize-transform modifiers))
|
||||
;; If we're working with a rotation we don't handle pixel precision because
|
||||
;; the transformation won't have the precision anyway
|
||||
modifiers
|
||||
|
||||
(let [center (gco/center-shape shape)
|
||||
base-bounds (-> (:points shape) (gpr/points->rect))
|
||||
|
||||
raw-bounds
|
||||
(-> (gtr/transform-bounds (:points shape) center modifiers)
|
||||
(gpr/points->rect))
|
||||
|
||||
flip-x? (neg? (get-in modifiers [:resize-vector :x]))
|
||||
flip-y? (or (neg? (get-in modifiers [:resize-vector :y]))
|
||||
(neg? (get-in modifiers [:resize-vector-2 :y])))
|
||||
|
||||
path? (= :path (:type shape))
|
||||
vertical-line? (and path? (<= (:width raw-bounds) 0.01))
|
||||
horizontal-line? (and path? (<= (:height raw-bounds) 0.01))
|
||||
|
||||
target-width (if vertical-line?
|
||||
(:width raw-bounds)
|
||||
(max 1 (mth/round (:width raw-bounds))))
|
||||
|
||||
target-height (if horizontal-line?
|
||||
(:height raw-bounds)
|
||||
(max 1 (mth/round (:height raw-bounds))))
|
||||
|
||||
target-p (cond-> (gpt/round (gpt/point raw-bounds))
|
||||
flip-x?
|
||||
(update :x + target-width)
|
||||
|
||||
flip-y?
|
||||
(update :y + target-height))
|
||||
|
||||
ratio-width (/ target-width (:width raw-bounds))
|
||||
ratio-height (/ target-height (:height raw-bounds))
|
||||
|
||||
modifiers
|
||||
(-> modifiers
|
||||
(d/without-nils)
|
||||
(d/update-in-when
|
||||
[:resize-vector :x] #(* % ratio-width))
|
||||
|
||||
;; If the resize-vector-2 modifier arrives means the resize-vector
|
||||
;; will only resize on the x axis
|
||||
(cond-> (nil? (:resize-vector-2 modifiers))
|
||||
(d/update-in-when
|
||||
[:resize-vector :y] #(* % ratio-height)))
|
||||
|
||||
(d/update-in-when
|
||||
[:resize-vector-2 :y] #(* % ratio-height)))
|
||||
|
||||
origin (get modifiers :resize-origin)
|
||||
origin-2 (get modifiers :resize-origin-2)
|
||||
|
||||
resize-v (get modifiers :resize-vector)
|
||||
resize-v-2 (get modifiers :resize-vector-2)
|
||||
displacement (get modifiers :displacement)
|
||||
|
||||
target-p-inv
|
||||
(-> target-p
|
||||
(gpt/transform
|
||||
(cond-> (gmt/matrix)
|
||||
(some? displacement)
|
||||
(gmt/multiply (gmt/inverse displacement))
|
||||
|
||||
(and (some? resize-v) (some? origin))
|
||||
(gmt/scale (gpt/inverse resize-v) origin)
|
||||
|
||||
(and (some? resize-v-2) (some? origin-2))
|
||||
(gmt/scale (gpt/inverse resize-v-2) origin-2))))
|
||||
|
||||
delta-v (gpt/subtract target-p-inv (gpt/point base-bounds))
|
||||
|
||||
modifiers
|
||||
(-> modifiers
|
||||
(d/update-when :displacement #(gmt/multiply (gmt/translate-matrix delta-v) %))
|
||||
(cond-> (nil? (:displacement modifiers))
|
||||
(assoc :displacement (gmt/translate-matrix delta-v))))]
|
||||
modifiers)))
|
||||
|
||||
|
||||
(defn set-children-modifiers
|
||||
[modif-tree shape objects ignore-constraints snap-pixel?]
|
||||
(letfn [(set-child [transformed-rect snap-pixel? modif-tree child]
|
||||
(let [modifiers (get-in modif-tree [(:id shape) :modifiers])
|
||||
child-modifiers (gct/calc-child-modifiers shape child modifiers ignore-constraints transformed-rect)
|
||||
child-modifiers (cond-> child-modifiers snap-pixel? (set-pixel-precision child))]
|
||||
(cond-> modif-tree
|
||||
(not (gtr/empty-modifiers? child-modifiers))
|
||||
(update-in [(:id child) :modifiers] #(merge child-modifiers %)))))]
|
||||
(let [children (map (d/getf objects) (:shapes shape))
|
||||
modifiers (get-in modif-tree [(:id shape) :modifiers])
|
||||
transformed-rect (gtr/transform-selrect (:selrect shape) modifiers)
|
||||
resize-modif? (or (:resize-vector modifiers) (:resize-vector-2 modifiers))]
|
||||
(reduce (partial set-child transformed-rect (and snap-pixel? resize-modif?)) modif-tree children))))
|
||||
|
||||
(defn group? [shape]
|
||||
(or (= :group (:type shape))
|
||||
(= :bool (:type shape))))
|
||||
|
||||
(defn merge-modifiers
|
||||
[modif-tree ids modifiers]
|
||||
(reduce
|
||||
(fn [modif-tree id]
|
||||
(update-in modif-tree [id :modifiers] #(merge % modifiers)))
|
||||
modif-tree
|
||||
ids))
|
||||
|
||||
(defn set-layout-modifiers
|
||||
[modif-tree objects id]
|
||||
|
||||
(letfn [(transform-child [parent child]
|
||||
(let [modifiers (get modif-tree (:id child))
|
||||
|
||||
child
|
||||
(cond-> child
|
||||
(not (group? child))
|
||||
(-> (merge modifiers) gtr/transform-shape)
|
||||
|
||||
(group? child)
|
||||
(gtr/apply-group-modifiers objects modif-tree))
|
||||
|
||||
child
|
||||
(-> child
|
||||
(gtr/apply-transform (gmt/transform-in (gco/center-shape parent) (:transform-inverse parent))))]
|
||||
|
||||
child))
|
||||
|
||||
(set-layout-modifiers [parent transform [layout-data modif-tree] child]
|
||||
(let [[modifiers layout-data]
|
||||
(gcl/calc-layout-modifiers parent transform child layout-data)
|
||||
|
||||
modif-tree
|
||||
(cond-> modif-tree
|
||||
(not (gtr/empty-modifiers? modifiers))
|
||||
(merge-modifiers [(:id child)] modifiers)
|
||||
|
||||
(and (not (gtr/empty-modifiers? modifiers)) (group? child))
|
||||
(merge-modifiers (:shapes child) modifiers))]
|
||||
|
||||
[layout-data modif-tree]))]
|
||||
|
||||
(let [modifiers (get modif-tree id)
|
||||
|
||||
shape (-> (get objects id) (merge modifiers) gtr/transform-shape)
|
||||
|
||||
|
||||
children (->> (:shapes shape)
|
||||
(map (d/getf objects))
|
||||
(map (partial transform-child shape)))
|
||||
|
||||
center (gco/center-shape shape)
|
||||
{:keys [transform transform-inverse]} shape
|
||||
|
||||
shape
|
||||
(-> shape
|
||||
(gtr/apply-transform (gmt/transform-in center transform-inverse)))
|
||||
|
||||
transformed-rect (:selrect shape)
|
||||
|
||||
layout-data (gcl/calc-layout-data shape children transformed-rect)
|
||||
children (into [] (cond-> children (:reverse? layout-data) reverse))
|
||||
|
||||
max-idx (dec (count children))
|
||||
layout-lines (:layout-lines layout-data)]
|
||||
|
||||
(loop [modif-tree modif-tree
|
||||
layout-line (first layout-lines)
|
||||
pending (rest layout-lines)
|
||||
from-idx 0]
|
||||
(if (and (some? layout-line) (<= from-idx max-idx))
|
||||
(let [to-idx (+ from-idx (:num-children layout-line))
|
||||
children (subvec children from-idx to-idx)
|
||||
|
||||
[_ modif-tree]
|
||||
(reduce (partial set-layout-modifiers shape transform) [layout-line modif-tree] children)]
|
||||
|
||||
(recur modif-tree (first pending) (rest pending) to-idx))
|
||||
|
||||
modif-tree)))))
|
||||
|
||||
(defn get-first-layout
|
||||
[id objects]
|
||||
|
||||
(loop [current id
|
||||
result id]
|
||||
(let [shape (get objects current)
|
||||
parent (get objects (:parent-id shape))]
|
||||
(cond
|
||||
(or (not shape) (= uuid/zero current))
|
||||
result
|
||||
|
||||
;; Frame found, but not layout we return the last layout found (or the id)
|
||||
(and (= :frame (:type parent))
|
||||
(not (:layout parent)))
|
||||
result
|
||||
|
||||
;; Layout found. We continue upward but we mark this layout
|
||||
(and (= :frame (:type parent))
|
||||
(:layout parent))
|
||||
(:id parent)
|
||||
|
||||
;; If group or boolean or other type of group we continue with the last result
|
||||
:else
|
||||
(recur (:id parent) result)))))
|
||||
|
||||
(defn resolve-layout-ids
|
||||
"Given a list of ids, resolve the parent layouts that will need to update. This will go upwards
|
||||
in the tree while a layout is found"
|
||||
[ids objects]
|
||||
|
||||
(into (d/ordered-set)
|
||||
(map #(get-first-layout % objects))
|
||||
ids))
|
||||
|
||||
(defn set-objects-modifiers
|
||||
[ids objects get-modifier ignore-constraints snap-pixel?]
|
||||
|
||||
(let [set-modifiers
|
||||
(fn [modif-tree id]
|
||||
(assoc modif-tree id {:modifiers (get-modifier (get objects id))}))
|
||||
|
||||
modif-tree (reduce set-modifiers {} ids)
|
||||
|
||||
ids (resolve-layout-ids ids objects)
|
||||
|
||||
;; First: Calculate children modifiers (constraints, etc)
|
||||
[modif-tree touched-layouts]
|
||||
(loop [current (first ids)
|
||||
pending (rest ids)
|
||||
modif-tree modif-tree
|
||||
touched-layouts (d/ordered-set)]
|
||||
(if (some? current)
|
||||
(let [shape (get objects current)
|
||||
pending (concat pending (:shapes shape))
|
||||
|
||||
touched-layouts
|
||||
(cond-> touched-layouts
|
||||
(:layout shape)
|
||||
(conj (:id shape)))
|
||||
|
||||
modif-tree
|
||||
(-> modif-tree
|
||||
(set-children-modifiers shape objects ignore-constraints snap-pixel?))]
|
||||
|
||||
(recur (first pending) (rest pending) modif-tree touched-layouts))
|
||||
|
||||
[modif-tree touched-layouts]))
|
||||
|
||||
;; Second: Calculate layout positioning
|
||||
modif-tree
|
||||
(loop [current (first touched-layouts)
|
||||
pending (rest touched-layouts)
|
||||
modif-tree modif-tree]
|
||||
|
||||
(if (some? current)
|
||||
(let [modif-tree (set-layout-modifiers modif-tree objects current)]
|
||||
(recur (first pending) (rest pending) modif-tree))
|
||||
modif-tree))]
|
||||
|
||||
modif-tree))
|
|
@ -278,7 +278,7 @@
|
|||
(if transform (gmt/multiply transform matrix) matrix)
|
||||
(if transform-inverse (gmt/multiply matrix-inverse transform-inverse) matrix-inverse)]))
|
||||
|
||||
(defn- apply-transform
|
||||
(defn apply-transform
|
||||
"Given a new set of points transformed, set up the rectangle so it keeps
|
||||
its properties. We adjust de x,y,width,height and create a custom transform"
|
||||
[shape transform-mtx]
|
||||
|
@ -491,6 +491,7 @@
|
|||
|
||||
([center modifiers]
|
||||
(let [displacement (:displacement modifiers)
|
||||
displacement-after (:displacement-after modifiers)
|
||||
resize-v1 (:resize-vector modifiers)
|
||||
resize-v2 (:resize-vector-2 modifiers)
|
||||
origin-1 (:resize-origin modifiers (gpt/point))
|
||||
|
@ -512,6 +513,9 @@
|
|||
rt-modif (:rotation modifiers)]
|
||||
|
||||
(cond-> (gmt/matrix)
|
||||
(some? displacement-after)
|
||||
(gmt/multiply displacement-after)
|
||||
|
||||
(some? resize-1)
|
||||
(-> (gmt/translate origin-1)
|
||||
(cond-> (some? resize-transform)
|
||||
|
@ -610,7 +614,7 @@
|
|||
(dissoc :modifiers))))))
|
||||
|
||||
(defn transform-bounds
|
||||
[points center {:keys [displacement resize-transform-inverse resize-vector resize-origin resize-vector-2 resize-origin-2]}]
|
||||
[points center {:keys [displacement displacement-after resize-transform-inverse resize-vector resize-origin resize-vector-2 resize-origin-2]}]
|
||||
;; FIXME: Improve Performance
|
||||
(let [resize-transform-inverse (or resize-transform-inverse (gmt/matrix))
|
||||
|
||||
|
@ -624,9 +628,10 @@
|
|||
|
||||
resize-origin-2
|
||||
(when (some? resize-origin-2)
|
||||
(transform-point-center resize-origin-2 center resize-transform-inverse))]
|
||||
(transform-point-center resize-origin-2 center resize-transform-inverse))
|
||||
]
|
||||
|
||||
(if (and (nil? displacement) (nil? resize-origin) (nil? resize-origin-2))
|
||||
(if (and (nil? displacement) (nil? resize-origin) (nil? resize-origin-2) (nil? displacement-after))
|
||||
points
|
||||
|
||||
(cond-> points
|
||||
|
@ -637,7 +642,10 @@
|
|||
(gco/transform-points resize-origin (gmt/scale-matrix resize-vector))
|
||||
|
||||
(some? resize-origin-2)
|
||||
(gco/transform-points resize-origin-2 (gmt/scale-matrix resize-vector-2))))))
|
||||
(gco/transform-points resize-origin-2 (gmt/scale-matrix resize-vector-2))
|
||||
|
||||
(some? displacement-after)
|
||||
(gco/transform-points displacement-after)))))
|
||||
|
||||
(defn transform-selrect
|
||||
[selrect modifiers]
|
||||
|
@ -662,3 +670,17 @@
|
|||
(map (comp gpr/points->selrect :points transform-shape))
|
||||
(gpr/join-selrects)))
|
||||
|
||||
(defn apply-group-modifiers
|
||||
"Apply the modifiers to the group children to calculate its selection rect"
|
||||
[group objects modif-tree]
|
||||
|
||||
(let [children
|
||||
(->> (:shapes group)
|
||||
(map (d/getf objects))
|
||||
(map (fn [shape]
|
||||
(let [modifiers (get modif-tree (:id shape))
|
||||
shape (-> shape (merge modifiers) transform-shape)]
|
||||
(if (= :group (:type shape))
|
||||
(apply-group-modifiers shape objects modif-tree)
|
||||
shape)))))]
|
||||
(update-group-selrect group children)))
|
||||
|
|
|
@ -218,7 +218,7 @@
|
|||
(->> (get-root-shapes objects)
|
||||
(mapv :id)))
|
||||
|
||||
(defn- get-base
|
||||
(defn get-base
|
||||
[objects id-a id-b]
|
||||
|
||||
(let [parents-a (reverse (get-parents-seq objects id-a))
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
[app.common.types.shape.blur :as ctsb]
|
||||
[app.common.types.shape.export :as ctse]
|
||||
[app.common.types.shape.interactions :as ctsi]
|
||||
[app.common.types.shape.layout :as ctsl]
|
||||
[app.common.types.shape.radius :as ctsr]
|
||||
[app.common.types.shape.shadow :as ctss]
|
||||
[clojure.set :as set]
|
||||
|
@ -156,68 +157,71 @@
|
|||
:luminosity})
|
||||
|
||||
(s/def ::shape-attrs
|
||||
(s/keys :opt-un [::id
|
||||
::type
|
||||
::name
|
||||
::component-id
|
||||
::component-file
|
||||
::component-root?
|
||||
::shape-ref
|
||||
::selrect
|
||||
::points
|
||||
::blocked
|
||||
::collapsed
|
||||
::fills
|
||||
::fill-color ;; TODO: remove these attributes
|
||||
::fill-opacity ;; when backward compatibility
|
||||
::fill-color-gradient ;; is no longer needed
|
||||
::fill-color-ref-file ;;
|
||||
::fill-color-ref-id ;;
|
||||
::hide-fill-on-export
|
||||
::font-family
|
||||
::font-size
|
||||
::font-style
|
||||
::font-weight
|
||||
::hidden
|
||||
::letter-spacing
|
||||
::line-height
|
||||
::locked
|
||||
::proportion
|
||||
::proportion-lock
|
||||
::constraints-h
|
||||
::constraints-v
|
||||
::fixed-scroll
|
||||
::ctsr/rx
|
||||
::ctsr/ry
|
||||
::ctsr/r1
|
||||
::ctsr/r2
|
||||
::ctsr/r3
|
||||
::ctsr/r4
|
||||
::x
|
||||
::y
|
||||
::exports
|
||||
::shapes
|
||||
::strokes
|
||||
::stroke-color ;; TODO: same thing
|
||||
::stroke-color-ref-file ;;
|
||||
::stroke-color-ref-i ;;
|
||||
::stroke-opacity ;;
|
||||
::stroke-style
|
||||
::stroke-width
|
||||
::stroke-alignment
|
||||
::stroke-cap-start
|
||||
::stroke-cap-end
|
||||
::text-align
|
||||
::transform
|
||||
::transform-inverse
|
||||
::width
|
||||
::height
|
||||
::masked-group?
|
||||
::ctsi/interactions
|
||||
::ctss/shadow
|
||||
::ctsb/blur
|
||||
::opacity
|
||||
::blend-mode]))
|
||||
(s/and
|
||||
::ctsl/layout-container-props
|
||||
::ctsl/layout-child-props
|
||||
(s/keys :opt-un [::id
|
||||
::type
|
||||
::name
|
||||
::component-id
|
||||
::component-file
|
||||
::component-root?
|
||||
::shape-ref
|
||||
::selrect
|
||||
::points
|
||||
::blocked
|
||||
::collapsed
|
||||
::fills
|
||||
::fill-color ;; TODO: remove these attributes
|
||||
::fill-opacity ;; when backward compatibility
|
||||
::fill-color-gradient ;; is no longer needed
|
||||
::fill-color-ref-file ;;
|
||||
::fill-color-ref-id ;;
|
||||
::hide-fill-on-export
|
||||
::font-family
|
||||
::font-size
|
||||
::font-style
|
||||
::font-weight
|
||||
::hidden
|
||||
::letter-spacing
|
||||
::line-height
|
||||
::locked
|
||||
::proportion
|
||||
::proportion-lock
|
||||
::constraints-h
|
||||
::constraints-v
|
||||
::fixed-scroll
|
||||
::ctsr/rx
|
||||
::ctsr/ry
|
||||
::ctsr/r1
|
||||
::ctsr/r2
|
||||
::ctsr/r3
|
||||
::ctsr/r4
|
||||
::x
|
||||
::y
|
||||
::exports
|
||||
::shapes
|
||||
::strokes
|
||||
::stroke-color ;; TODO: same thing
|
||||
::stroke-color-ref-file ;;
|
||||
::stroke-color-ref-i ;;
|
||||
::stroke-opacity ;;
|
||||
::stroke-style
|
||||
::stroke-width
|
||||
::stroke-alignment
|
||||
::stroke-cap-start
|
||||
::stroke-cap-end
|
||||
::text-align
|
||||
::transform
|
||||
::transform-inverse
|
||||
::width
|
||||
::height
|
||||
::masked-group?
|
||||
::ctsi/interactions
|
||||
::ctss/shadow
|
||||
::ctsb/blur
|
||||
::opacity
|
||||
::blend-mode])))
|
||||
|
||||
(s/def :internal.shape.text/type #{"root" "paragraph-set" "paragraph"})
|
||||
(s/def :internal.shape.text/children
|
||||
|
|
61
common/src/app/common/types/shape/layout.cljc
Normal file
61
common/src/app/common/types/shape/layout.cljc
Normal file
|
@ -0,0 +1,61 @@
|
|||
;; 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) UXBOX Labs SL
|
||||
|
||||
(ns app.common.types.shape.layout
|
||||
(:require
|
||||
[app.common.spec :as us]
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
||||
(s/def ::layout boolean?)
|
||||
(s/def ::layout-dir #{:right :left :top :bottom})
|
||||
(s/def ::layout-gap ::us/safe-number)
|
||||
(s/def ::layout-type #{:packed :space-between :space-around})
|
||||
(s/def ::layout-wrap-type #{:wrap :no-wrap})
|
||||
(s/def ::layout-padding-type #{:simple :multiple})
|
||||
|
||||
(s/def ::p1 ::us/safe-number)
|
||||
(s/def ::p2 ::us/safe-number)
|
||||
(s/def ::p3 ::us/safe-number)
|
||||
(s/def ::p4 ::us/safe-number)
|
||||
|
||||
(s/def ::layout-padding
|
||||
(s/keys :req-un [::p1]
|
||||
:opt-un [::p2 ::p3 ::p4]))
|
||||
|
||||
(s/def ::layout-h-orientation #{:left :center :right})
|
||||
(s/def ::layout-v-orientation #{:top :center :bottom})
|
||||
|
||||
(s/def ::layout-container-props
|
||||
(s/keys :opt-un [::layout
|
||||
::layout-dir
|
||||
::layout-gap
|
||||
::layout-type
|
||||
::layout-wrap-type
|
||||
::layout-padding-type
|
||||
::layout-padding
|
||||
::layout-h-orientation
|
||||
::layout-v-orientation]))
|
||||
|
||||
(s/def ::layout-margin (s/keys :req-un [::m1]
|
||||
:opt-un [::m2 ::m3 ::m4]))
|
||||
|
||||
(s/def ::layout-margin-type #{:simple :multiple})
|
||||
(s/def ::layout-h-behavior #{:fill :fix :auto})
|
||||
(s/def ::layout-v-behavior #{:fill :fix :auto})
|
||||
(s/def ::layout-max-h ::us/safe-number)
|
||||
(s/def ::layout-min-h ::us/safe-number)
|
||||
(s/def ::layout-max-w ::us/safe-number)
|
||||
(s/def ::layout-min-w ::us/safe-number)
|
||||
|
||||
(s/def ::layout-child-props
|
||||
(s/keys :opt-un [::layout-margin
|
||||
::layout-margin-type
|
||||
::layout-h-behavior
|
||||
::layout-v-behavior
|
||||
::layout-max-h
|
||||
::layout-min-h
|
||||
::layout-max-w
|
||||
::layout-min-w]))
|
|
@ -23,8 +23,6 @@
|
|||
:grid-alignment true
|
||||
:background "var(--color-white)"})
|
||||
|
||||
(def has-layout-item false)
|
||||
|
||||
(def size-presets
|
||||
[{:name "APPLE"}
|
||||
{:name "iPhone 12/12 Pro"
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
[app.main.data.workspace.path.shapes-to-path :as dwps]
|
||||
[app.main.data.workspace.persistence :as dwp]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.shape-layout :as dwsl]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.thumbnails :as dwth]
|
||||
|
@ -799,7 +800,8 @@
|
|||
ids)]
|
||||
|
||||
(rx/of (dch/commit-changes changes)
|
||||
(dwco/expand-collapse parent-id))))))
|
||||
(dwco/expand-collapse parent-id)
|
||||
(dwsl/update-layout-positions [parent-id]))))))
|
||||
|
||||
(defn relocate-selected-shapes
|
||||
[parent-id to-index]
|
||||
|
|
84
frontend/src/app/main/data/workspace/shape_layout.cljs
Normal file
84
frontend/src/app/main/data/workspace/shape_layout.cljs
Normal file
|
@ -0,0 +1,84 @@
|
|||
;; 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) UXBOX Labs SL
|
||||
|
||||
(ns app.main.data.workspace.shape-layout
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.main.data.workspace.changes :as dwc]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.transforms :as dwt]
|
||||
[beicon.core :as rx]
|
||||
[potok.core :as ptk]))
|
||||
|
||||
(def layout-keys
|
||||
[:layout
|
||||
:layout-dir
|
||||
:layout-gap
|
||||
:layout-type
|
||||
:layout-wrap-type
|
||||
:layout-padding-type
|
||||
:layout-padding
|
||||
:layout-h-orientation
|
||||
:layout-v-orientation])
|
||||
|
||||
(def initial-layout
|
||||
{:layout true
|
||||
:layout-dir :left
|
||||
:layout-gap 0
|
||||
:layout-type :packed
|
||||
:layout-wrap-type :wrap
|
||||
:layout-padding-type :simple
|
||||
:layout-padding {:p1 0 :p2 0 :p3 0 :p4 0}
|
||||
:layout-h-orientation :left
|
||||
:layout-v-orientation :top})
|
||||
|
||||
(defn update-layout-positions
|
||||
[ids]
|
||||
(ptk/reify ::update-layout-positions
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
ids (->> ids (filter #(get-in objects [% :layout])))]
|
||||
(if (d/not-empty? ids)
|
||||
(rx/of (dwt/set-modifiers ids)
|
||||
(dwt/apply-modifiers))
|
||||
(rx/empty))))))
|
||||
|
||||
;; TODO: Remove constraints from children
|
||||
(defn create-layout
|
||||
[ids]
|
||||
(ptk/reify ::create-layout
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(rx/of (dwc/update-shapes ids #(merge % initial-layout))
|
||||
(update-layout-positions ids)))))
|
||||
|
||||
(defn remove-layout
|
||||
[ids]
|
||||
(ptk/reify ::remove-layout
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(rx/of (dwc/update-shapes ids #(apply dissoc % layout-keys))
|
||||
(update-layout-positions ids)))))
|
||||
|
||||
(defn update-layout
|
||||
[ids changes]
|
||||
(ptk/reify ::update-layout
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(rx/of (dwc/update-shapes ids #(d/deep-merge % changes))
|
||||
(update-layout-positions ids)))))
|
||||
|
||||
(defn update-layout-child
|
||||
[ids changes]
|
||||
(ptk/reify ::update-layout-child
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
parent-ids (->> ids (map #(cph/get-parent-id objects %)))]
|
||||
(rx/of (dwc/update-shapes ids #(d/deep-merge (or % {}) changes))
|
||||
(update-layout-positions parent-ids))))))
|
|
@ -19,6 +19,7 @@
|
|||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.edition :as dwe]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.shape-layout :as dwsl]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.streams :as ms]
|
||||
[app.util.names :as un]
|
||||
|
@ -98,6 +99,7 @@
|
|||
|
||||
(rx/concat
|
||||
(rx/of (dch/commit-changes changes)
|
||||
(dwsl/update-layout-positions [(:parent-id shape)])
|
||||
(when-not no-select?
|
||||
(dws/select-shapes (d/ordered-set id))))
|
||||
(when (= :text (:type attrs))
|
||||
|
@ -239,7 +241,8 @@
|
|||
flows
|
||||
starting-flows)))))]
|
||||
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
(rx/of (dch/commit-changes changes)
|
||||
(dwsl/update-layout-positions all-parents))))))
|
||||
|
||||
(defn- viewport-center
|
||||
[state]
|
||||
|
|
|
@ -110,10 +110,10 @@
|
|||
;; geometric attributes of the shapes.
|
||||
|
||||
(declare clear-local-transform)
|
||||
(declare set-objects-modifiers)
|
||||
|
||||
(declare get-ignore-tree)
|
||||
|
||||
(defn- set-modifiers
|
||||
(defn set-modifiers
|
||||
([ids]
|
||||
(set-modifiers ids nil false))
|
||||
|
||||
|
@ -128,20 +128,16 @@
|
|||
(ptk/reify ::set-modifiers
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [modifiers (or modifiers (get-in state [:workspace-local :modifiers] {}))
|
||||
page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
ids (into #{} (remove #(get-in objects [% :blocked] false)) ids)
|
||||
layout (get state :workspace-layout)
|
||||
snap-pixel? (and (not ignore-snap-pixel) (contains? layout :snap-pixel-grid))
|
||||
|
||||
setup-modifiers
|
||||
(fn [state id]
|
||||
(let [shape (get objects id)]
|
||||
(update state :workspace-modifiers
|
||||
#(set-objects-modifiers % objects shape modifiers ignore-constraints snap-pixel?))))]
|
||||
snap-pixel? (and (not ignore-snap-pixel)
|
||||
(contains? (:workspace-layout state) :snap-pixel-grid))
|
||||
|
||||
(reduce setup-modifiers state ids))))))
|
||||
modif-tree
|
||||
(gsh/set-objects-modifiers ids objects (constantly modifiers) ignore-constraints snap-pixel?)]
|
||||
|
||||
(update state :workspace-modifiers merge modif-tree))))))
|
||||
|
||||
;; Rotation use different algorithm to calculate children modifiers (and do not use child constraints).
|
||||
(defn- set-rotation-modifiers
|
||||
|
@ -152,19 +148,23 @@
|
|||
(ptk/reify ::set-rotation-modifiers
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
shapes (->> shapes
|
||||
(remove #(get % :blocked false))
|
||||
(mapcat #(cph/get-children objects (:id %)))
|
||||
(concat shapes)
|
||||
(filter #((cpc/editable-attrs (:type %)) :rotation)))
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
ids
|
||||
(->> shapes
|
||||
(remove #(get % :blocked false))
|
||||
(mapcat #(cph/get-children objects (:id %)))
|
||||
(concat shapes)
|
||||
(filter #((cpc/editable-attrs (:type %)) :rotation))
|
||||
(map :id))
|
||||
|
||||
update-shape
|
||||
(fn [modifiers shape]
|
||||
(let [rotate-modifiers (gsh/rotation-modifiers shape center angle)]
|
||||
(assoc-in modifiers [(:id shape) :modifiers] rotate-modifiers)))]
|
||||
get-modifier
|
||||
(fn [shape]
|
||||
(gsh/rotation-modifiers shape center angle))
|
||||
|
||||
(update state :workspace-modifiers #(reduce update-shape % shapes)))))))
|
||||
modif-tree
|
||||
(gsh/set-objects-modifiers ids objects get-modifier false false)]
|
||||
|
||||
(update state :workspace-modifiers merge modif-tree))))))
|
||||
|
||||
(defn- update-grow-type
|
||||
[shape old-shape]
|
||||
|
@ -180,18 +180,20 @@
|
|||
change-to-fixed?
|
||||
(assoc :grow-type :fixed))))
|
||||
|
||||
(defn- apply-modifiers
|
||||
([ids]
|
||||
(apply-modifiers ids nil))
|
||||
(defn apply-modifiers
|
||||
([]
|
||||
(apply-modifiers nil))
|
||||
|
||||
([ids {:keys [undo-transation?] :or {undo-transation? true}}]
|
||||
(us/verify (s/coll-of uuid?) ids)
|
||||
([{:keys [undo-transation?] :or {undo-transation? true}}]
|
||||
(ptk/reify ::apply-modifiers
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
ids-with-children (into (vec ids) (mapcat #(cph/get-children-ids objects %)) ids)
|
||||
object-modifiers (get state :workspace-modifiers)
|
||||
|
||||
ids (keys object-modifiers)
|
||||
ids-with-children (into (vec ids) (mapcat #(cph/get-children-ids objects %)) ids)
|
||||
|
||||
shapes (map (d/getf objects) ids)
|
||||
ignore-tree (->> (map #(get-ignore-tree object-modifiers objects %) shapes)
|
||||
(reduce merge {}))]
|
||||
|
@ -202,7 +204,7 @@
|
|||
(rx/empty))
|
||||
(rx/of (dwg/move-frame-guides ids-with-children)
|
||||
(dch/update-shapes
|
||||
ids-with-children
|
||||
ids
|
||||
(fn [shape]
|
||||
(let [modif (get object-modifiers (:id shape))
|
||||
text-shape? (cph/text-shape? shape)]
|
||||
|
@ -280,119 +282,9 @@
|
|||
|
||||
[root transformed-root ignore-geometry?]))
|
||||
|
||||
(defn set-pixel-precision
|
||||
"Adjust modifiers so they adjust to the pixel grid"
|
||||
[modifiers shape]
|
||||
|
||||
(if (some? (:resize-transform modifiers))
|
||||
;; If we're working with a rotation we don't handle pixel precision because
|
||||
;; the transformation won't have the precision anyway
|
||||
modifiers
|
||||
|
||||
(let [center (gsh/center-shape shape)
|
||||
base-bounds (-> (:points shape) (gsh/points->rect))
|
||||
|
||||
raw-bounds
|
||||
(-> (gsh/transform-bounds (:points shape) center modifiers)
|
||||
(gsh/points->rect))
|
||||
|
||||
flip-x? (neg? (get-in modifiers [:resize-vector :x]))
|
||||
flip-y? (or (neg? (get-in modifiers [:resize-vector :y]))
|
||||
(neg? (get-in modifiers [:resize-vector-2 :y])))
|
||||
|
||||
path? (= :path (:type shape))
|
||||
vertical-line? (and path? (<= (:width raw-bounds) 0.01))
|
||||
horizontal-line? (and path? (<= (:height raw-bounds) 0.01))
|
||||
|
||||
target-width (if vertical-line?
|
||||
(:width raw-bounds)
|
||||
(max 1 (mth/round (:width raw-bounds))))
|
||||
|
||||
target-height (if horizontal-line?
|
||||
(:height raw-bounds)
|
||||
(max 1 (mth/round (:height raw-bounds))))
|
||||
|
||||
target-p (cond-> (gpt/round (gpt/point raw-bounds))
|
||||
flip-x?
|
||||
(update :x + target-width)
|
||||
|
||||
flip-y?
|
||||
(update :y + target-height))
|
||||
|
||||
ratio-width (/ target-width (:width raw-bounds))
|
||||
ratio-height (/ target-height (:height raw-bounds))
|
||||
|
||||
modifiers
|
||||
(-> modifiers
|
||||
(d/without-nils)
|
||||
(d/update-in-when
|
||||
[:resize-vector :x] #(* % ratio-width))
|
||||
|
||||
;; If the resize-vector-2 modifier arrives means the resize-vector
|
||||
;; will only resize on the x axis
|
||||
(cond-> (nil? (:resize-vector-2 modifiers))
|
||||
(d/update-in-when
|
||||
[:resize-vector :y] #(* % ratio-height)))
|
||||
|
||||
(d/update-in-when
|
||||
[:resize-vector-2 :y] #(* % ratio-height)))
|
||||
|
||||
origin (get modifiers :resize-origin)
|
||||
origin-2 (get modifiers :resize-origin-2)
|
||||
|
||||
resize-v (get modifiers :resize-vector)
|
||||
resize-v-2 (get modifiers :resize-vector-2)
|
||||
displacement (get modifiers :displacement)
|
||||
|
||||
target-p-inv
|
||||
(-> target-p
|
||||
(gpt/transform
|
||||
(cond-> (gmt/matrix)
|
||||
(some? displacement)
|
||||
(gmt/multiply (gmt/inverse displacement))
|
||||
|
||||
(and (some? resize-v) (some? origin))
|
||||
(gmt/scale (gpt/inverse resize-v) origin)
|
||||
|
||||
(and (some? resize-v-2) (some? origin-2))
|
||||
(gmt/scale (gpt/inverse resize-v-2) origin-2))))
|
||||
|
||||
delta-v (gpt/subtract target-p-inv (gpt/point base-bounds))
|
||||
|
||||
modifiers
|
||||
(-> modifiers
|
||||
(d/update-when :displacement #(gmt/multiply (gmt/translate-matrix delta-v) %))
|
||||
(cond-> (nil? (:displacement modifiers))
|
||||
(assoc :displacement (gmt/translate-matrix delta-v))))]
|
||||
modifiers)))
|
||||
|
||||
(defn- set-objects-modifiers
|
||||
[modif-tree objects shape modifiers ignore-constraints snap-pixel?]
|
||||
(letfn [(set-modifiers-rec
|
||||
[modif-tree shape modifiers]
|
||||
|
||||
(let [children (map (d/getf objects) (:shapes shape))
|
||||
transformed-rect (gsh/transform-selrect (:selrect shape) modifiers)
|
||||
|
||||
set-child
|
||||
(fn [snap-pixel? modif-tree child]
|
||||
(let [child-modifiers (gsh/calc-child-modifiers shape child modifiers ignore-constraints transformed-rect)
|
||||
child-modifiers (cond-> child-modifiers snap-pixel? (set-pixel-precision child))]
|
||||
(cond-> modif-tree
|
||||
(not (gsh/empty-modifiers? child-modifiers))
|
||||
(set-modifiers-rec child child-modifiers))))
|
||||
|
||||
modif-tree
|
||||
(-> modif-tree
|
||||
(assoc-in [(:id shape) :modifiers] modifiers))
|
||||
|
||||
resize-modif?
|
||||
(or (:resize-vector modifiers) (:resize-vector-2 modifiers))]
|
||||
|
||||
(reduce (partial set-child (and snap-pixel? resize-modif?)) modif-tree children)))]
|
||||
|
||||
(let [modifiers (cond-> modifiers snap-pixel? (set-pixel-precision shape))]
|
||||
(set-modifiers-rec modif-tree shape modifiers))))
|
||||
|
||||
(defn- get-ignore-tree
|
||||
"Retrieves a map with the flag `ignore-geometry?` given a tree of modifiers"
|
||||
|
@ -534,7 +426,7 @@
|
|||
(rx/map #(conj current %)))))
|
||||
(rx/mapcat (partial resize shape initial-position layout))
|
||||
(rx/take-until stoper))
|
||||
(rx/of (apply-modifiers ids)
|
||||
(rx/of (apply-modifiers)
|
||||
(finish-transform))))))))
|
||||
|
||||
(defn update-dimensions
|
||||
|
@ -547,22 +439,20 @@
|
|||
(ptk/reify ::update-dimensions
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
layout (get state :workspace-layout)
|
||||
snap-pixel? (contains? layout :snap-pixel-grid)
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
snap-pixel? (and (contains? (:workspace-layout state) :snap-pixel-grid)
|
||||
(int? value))
|
||||
get-modifier
|
||||
(fn [shape] (gsh/resize-modifiers shape attr value))
|
||||
|
||||
update-modifiers
|
||||
(fn [state id]
|
||||
(let [shape (get objects id)
|
||||
modifiers (gsh/resize-modifiers shape attr value)]
|
||||
(-> state
|
||||
(update :workspace-modifiers
|
||||
#(set-objects-modifiers % objects shape modifiers false (and snap-pixel? (int? value)))))))]
|
||||
(reduce update-modifiers state ids)))
|
||||
modif-tree
|
||||
(gsh/set-objects-modifiers ids objects get-modifier false snap-pixel?)]
|
||||
|
||||
(assoc state :workspace-modifiers modif-tree)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(rx/of (apply-modifiers ids)))))
|
||||
(rx/of (apply-modifiers)))))
|
||||
|
||||
(defn change-orientation
|
||||
"Change orientation of shapes, from the sidebar options form.
|
||||
|
@ -574,21 +464,19 @@
|
|||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
layout (get state :workspace-layout)
|
||||
snap-pixel? (contains? layout :snap-pixel-grid)
|
||||
snap-pixel? (contains? (get state :workspace-layout) :snap-pixel-grid)
|
||||
|
||||
update-modifiers
|
||||
(fn [state id]
|
||||
(let [shape (get objects id)
|
||||
modifiers (gsh/change-orientation-modifiers shape orientation)]
|
||||
(-> state
|
||||
(update :workspace-modifiers
|
||||
#(set-objects-modifiers % objects shape modifiers false snap-pixel?)))))]
|
||||
(reduce update-modifiers state ids)))
|
||||
get-modifier
|
||||
(fn [shape] (gsh/change-orientation-modifiers shape orientation))
|
||||
|
||||
modif-tree
|
||||
(gsh/set-objects-modifiers ids objects get-modifier false snap-pixel?)]
|
||||
|
||||
(assoc state :workspace-modifiers modif-tree)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(rx/of (apply-modifiers ids)))))
|
||||
(rx/of (apply-modifiers)))))
|
||||
|
||||
;; -- Rotate --------------------------------------------------------
|
||||
|
||||
|
@ -631,7 +519,7 @@
|
|||
(let [delta-angle (calculate-angle pos mod? shift?)]
|
||||
(set-rotation-modifiers delta-angle shapes group-center))))
|
||||
(rx/take-until stoper))
|
||||
(rx/of (apply-modifiers (map :id shapes))
|
||||
(rx/of (apply-modifiers)
|
||||
(finish-transform)))))))
|
||||
|
||||
(defn increase-rotation
|
||||
|
@ -648,7 +536,7 @@
|
|||
(set-rotation-modifiers delta [shape])))]
|
||||
(rx/concat
|
||||
(rx/from (->> ids (map #(get objects %)) (map rotate-shape)))
|
||||
(rx/of (apply-modifiers ids)))))))
|
||||
(rx/of (apply-modifiers)))))))
|
||||
|
||||
|
||||
;; -- Move ----------------------------------------------------------
|
||||
|
@ -772,7 +660,7 @@
|
|||
|
||||
(rx/of (dwu/start-undo-transaction)
|
||||
(calculate-frame-for-move ids)
|
||||
(apply-modifiers ids {:undo-transation? false})
|
||||
(apply-modifiers {:undo-transation? false})
|
||||
(finish-transform)
|
||||
(dwu/commit-undo-transaction)))))))))
|
||||
|
||||
|
@ -820,7 +708,7 @@
|
|||
(rx/take-until stopper))
|
||||
(rx/of (move-selected direction shift?)))
|
||||
|
||||
(rx/of (apply-modifiers selected)
|
||||
(rx/of (apply-modifiers)
|
||||
(finish-transform))))
|
||||
(rx/empty))))))
|
||||
|
||||
|
@ -850,7 +738,7 @@
|
|||
displ (gmt/translate-matrix delta)]
|
||||
|
||||
(rx/of (set-modifiers [id] {:displacement displ} false true)
|
||||
(apply-modifiers [id]))))))
|
||||
(apply-modifiers))))))
|
||||
|
||||
(defn check-frame-move?
|
||||
[target-frame-id objects position shape]
|
||||
|
@ -911,7 +799,7 @@
|
|||
:resize-origin origin
|
||||
:displacement (gmt/translate-matrix (gpt/point (- (:width selrect)) 0))}
|
||||
true)
|
||||
(apply-modifiers selected))))))
|
||||
(apply-modifiers))))))
|
||||
|
||||
(defn flip-vertical-selected []
|
||||
(ptk/reify ::flip-vertical-selected
|
||||
|
@ -928,4 +816,4 @@
|
|||
:resize-origin origin
|
||||
:displacement (gmt/translate-matrix (gpt/point 0 (- (:height selrect))))}
|
||||
true)
|
||||
(apply-modifiers selected))))))
|
||||
(apply-modifiers))))))
|
||||
|
|
|
@ -410,3 +410,11 @@
|
|||
|
||||
(defn workspace-text-modifier-by-id [id]
|
||||
(l/derived #(get % id) workspace-text-modifier =))
|
||||
|
||||
(defn is-layout-child?
|
||||
[ids]
|
||||
(l/derived
|
||||
(fn [objects]
|
||||
(->> ids
|
||||
(some #(-> (cph/get-parent objects %) :layout))))
|
||||
workspace-page-objects))
|
||||
|
|
|
@ -4,10 +4,12 @@
|
|||
;;
|
||||
;; Copyright (c) UXBOX Labs SL
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.menus.layout
|
||||
(ns app.main.ui.workspace.sidebar.options.menus.layout-container
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.data.workspace.shape-layout :as dwsl]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.numeric-input :refer [numeric-input]]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
|
@ -15,16 +17,16 @@
|
|||
[cuerdas.core :as str]
|
||||
[rumext.alpha :as mf]))
|
||||
|
||||
(def layout-attrs
|
||||
[:layout ;; true if active, false if not
|
||||
:layout-dir ;; :right, :left, :top, :bottom
|
||||
:gap ;; number could be negative
|
||||
:layout-type ;; :packed, :space-between, :space-around
|
||||
:wrap-type ;; :wrap, :no-wrap
|
||||
:padding-type ;; :simple, :multiple
|
||||
:padding ;; {:p1 num :p2 num :p3 num :p4 num} number could be negative
|
||||
:h-orientation ;; :top, :center, :bottom
|
||||
:v-orientation]) ;; :left, :center, :right
|
||||
(def layout-container-attrs
|
||||
[:layout ;; true if active, false if not
|
||||
:layout-dir ;; :right, :left, :top, :bottom
|
||||
:layout-gap ;; number could be negative
|
||||
:layout-type ;; :packed, :space-between, :space-around
|
||||
:layout-wrap-type ;; :wrap, :no-wrap
|
||||
:layout-padding-type ;; :simple, :multiple
|
||||
:layout-padding ;; {:p1 num :p2 num :p3 num :p4 num} number could be negative
|
||||
:layout-h-orientation ;; :left, :center, :right
|
||||
:layout-v-orientation]) ;; :top, :center, :bottom
|
||||
|
||||
(def grid-pos [[:top :left]
|
||||
[:top :center]
|
||||
|
@ -35,35 +37,65 @@
|
|||
[:bottom :left]
|
||||
[:bottom :center]
|
||||
[:bottom :right]])
|
||||
|
||||
(def grid-rows [:top :center :bottom])
|
||||
(def grid-cols [:left :center :right])
|
||||
|
||||
(defn- get-layout-icon
|
||||
[dir layout-type v h]
|
||||
(let [row? (or (= dir :right) (= dir :left))
|
||||
manage-text-icon
|
||||
(if row?
|
||||
(case v
|
||||
:top i/text-align-left
|
||||
:center i/text-align-center
|
||||
:bottom i/text-align-right
|
||||
i/text-align-center)
|
||||
(case h
|
||||
:left i/text-align-left
|
||||
:center i/text-align-center
|
||||
:right i/text-align-right
|
||||
i/text-align-center))]
|
||||
(case layout-type
|
||||
:packed manage-text-icon
|
||||
:space-around i/space-around
|
||||
:space-between i/space-between)))
|
||||
|
||||
(mf/defc direction-row
|
||||
[{:keys [dir saved-dir set-direction] :as props}]
|
||||
[:button.dir.tooltip.tooltip-bottom
|
||||
{:class (dom/classnames :active (= saved-dir dir)
|
||||
:left (= :left dir)
|
||||
:right (= :right dir)
|
||||
:top (= :top dir)
|
||||
:bottom (= :bottom dir))
|
||||
:key (dm/str "direction-" dir)
|
||||
:alt (tr (dm/str "workspace.options.layout.direction." (d/name dir)))
|
||||
:on-click #(set-direction dir)}
|
||||
i/auto-direction])
|
||||
(let [handle-on-click
|
||||
(mf/use-callback
|
||||
(mf/deps set-direction dir)
|
||||
(fn []
|
||||
(when (some? set-direction)
|
||||
(set-direction dir))))]
|
||||
|
||||
[:button.dir.tooltip.tooltip-bottom
|
||||
{:class (dom/classnames :active (= saved-dir dir)
|
||||
:left (= :left dir)
|
||||
:right (= :right dir)
|
||||
:top (= :top dir)
|
||||
:bottom (= :bottom dir))
|
||||
:key (dm/str "direction-" dir)
|
||||
:alt (tr (dm/str "workspace.options.layout.direction." (d/name dir)))
|
||||
:on-click handle-on-click}
|
||||
i/auto-direction]))
|
||||
|
||||
(mf/defc orientation-grid
|
||||
[{:keys [manage-orientation test-values get-icon] :as props}]
|
||||
(let [dir (:layout-dir @test-values)
|
||||
type (:layout-type @test-values)
|
||||
[{:keys [on-change-orientation values] :as props}]
|
||||
(let [dir (:layout-dir values)
|
||||
type (:layout-type values)
|
||||
is-col? (or (= dir :top)
|
||||
(= dir :bottom))
|
||||
saved-pos [(:h-orientation @test-values) (:v-orientation @test-values)]]
|
||||
saved-pos [(:layout-v-orientation values)
|
||||
(:layout-h-orientation values)]]
|
||||
|
||||
(if (= type :packed)
|
||||
[:div.orientation-grid
|
||||
[:div.button-wrapper
|
||||
(for [[pv ph] grid-pos]
|
||||
[:button.orientation
|
||||
{:on-click (partial manage-orientation pv ph type)
|
||||
{:on-click (partial on-change-orientation pv ph type)
|
||||
:class (dom/classnames
|
||||
:active (= [pv ph] saved-pos)
|
||||
:top (= :top pv)
|
||||
|
@ -75,35 +107,14 @@
|
|||
:key (dm/str pv ph)}
|
||||
[:span.icon
|
||||
{:class (dom/classnames
|
||||
:rotated is-col?)}
|
||||
(get-icon dir type pv ph)]])]]
|
||||
|
||||
(if is-col?
|
||||
[:div.orientation-grid.col
|
||||
[:div.button-wrapper
|
||||
(for [col grid-cols]
|
||||
[:button.orientation
|
||||
{:on-click (partial manage-orientation :top col type)
|
||||
:class (dom/classnames
|
||||
:active (= col (second saved-pos))
|
||||
:top (= :left col)
|
||||
:centered (= :center col)
|
||||
:bottom (= :right col))}
|
||||
[:span.icon
|
||||
{:class (dom/classnames :rotated is-col?)}
|
||||
(get-icon dir type nil col)]
|
||||
[:span.icon
|
||||
{:class (dom/classnames :rotated is-col?)}
|
||||
(get-icon dir type nil col)]
|
||||
[:span.icon
|
||||
{:class (dom/classnames :rotated is-col?)}
|
||||
(get-icon dir type nil col)]])]]
|
||||
|
||||
:rotated (not is-col?))}
|
||||
(get-layout-icon dir type pv ph)]])]]
|
||||
(if (not is-col?)
|
||||
[:div.orientation-grid.row
|
||||
[:div.button-wrapper
|
||||
(for [row grid-rows]
|
||||
[:button.orientation
|
||||
{:on-click (partial manage-orientation row :left type)
|
||||
{:on-click (partial on-change-orientation row :left type)
|
||||
:class (dom/classnames
|
||||
:active (= row (first saved-pos))
|
||||
:top (= :top row)
|
||||
|
@ -111,30 +122,51 @@
|
|||
:bottom (= :bottom row))}
|
||||
[:span.icon
|
||||
{:class (dom/classnames :rotated is-col?)}
|
||||
(get-icon dir type row nil)]
|
||||
(get-layout-icon dir type nil row)]
|
||||
[:span.icon
|
||||
{:class (dom/classnames :rotated is-col?)}
|
||||
(get-icon dir type row nil)]
|
||||
(get-layout-icon dir type nil row)]
|
||||
[:span.icon
|
||||
{:class (dom/classnames :rotated is-col?)}
|
||||
(get-icon dir type row nil)]])]]))))
|
||||
(get-layout-icon dir type nil row)]])]]
|
||||
|
||||
[:div.orientation-grid.col
|
||||
[:div.button-wrapper
|
||||
(for [[idx col] (d/enumerate grid-cols)]
|
||||
[:button.orientation
|
||||
{:key (dm/str idx col)
|
||||
:on-click (partial on-change-orientation :top col type)
|
||||
:class (dom/classnames
|
||||
:active (= col (second saved-pos))
|
||||
:top (= :left col)
|
||||
:centered (= :center col)
|
||||
:bottom (= :right col))}
|
||||
[:span.icon
|
||||
{:class (dom/classnames :rotated is-col?)}
|
||||
(get-layout-icon dir type col nil)]
|
||||
[:span.icon
|
||||
{:class (dom/classnames :rotated is-col?)}
|
||||
(get-layout-icon dir type col nil)]
|
||||
[:span.icon
|
||||
{:class (dom/classnames :rotated is-col?)}
|
||||
(get-layout-icon dir type col nil)]])]]))))
|
||||
|
||||
(mf/defc padding-section
|
||||
[{:keys [test-values change-padding-style select-all on-padding-change] :as props}]
|
||||
[{:keys [values on-change-style on-change] :as props}]
|
||||
|
||||
(let [padding-type (:padding-type @test-values)]
|
||||
(let [padding-type (:layout-padding-type values)]
|
||||
|
||||
[:div.row-flex
|
||||
[:div.padding-options
|
||||
[:div.padding-icon.tooltip.tooltip-bottom
|
||||
{:class (dom/classnames :selected (= padding-type :simple))
|
||||
:alt (tr "workspace.options.layout.padding-simple")
|
||||
:on-click #(change-padding-style :simple)}
|
||||
:on-click #(on-change-style :simple)}
|
||||
i/auto-padding]
|
||||
[:div.padding-icon.tooltip.tooltip-bottom
|
||||
{:class (dom/classnames :selected (= padding-type :multiple))
|
||||
:alt (tr "workspace.options.layout.padding")
|
||||
:on-click #(change-padding-style :multiple)}
|
||||
:on-click #(on-change-style :multiple)}
|
||||
i/auto-padding-side]]
|
||||
|
||||
(cond
|
||||
|
@ -145,9 +177,9 @@
|
|||
|
||||
[:> numeric-input
|
||||
{:placeholder "--"
|
||||
:on-click select-all
|
||||
:on-change (partial on-padding-change :simple)
|
||||
:value (:p1 (:padding @test-values))}]]]
|
||||
:on-click #(dom/select-target %)
|
||||
:on-change (partial on-change :simple)
|
||||
:value (:p1 (:layout-padding values))}]]]
|
||||
|
||||
(= padding-type :multiple)
|
||||
(for [num [:p1 :p2 :p3 :p4]]
|
||||
|
@ -161,82 +193,55 @@
|
|||
[:div.input-element.mini
|
||||
[:> numeric-input
|
||||
{:placeholder "--"
|
||||
:on-click select-all
|
||||
:on-change (partial on-padding-change num)
|
||||
:value (num (:padding @test-values))}]]]))]))
|
||||
:on-click #(dom/select-target %)
|
||||
:on-change (partial on-change num)
|
||||
:value (num (:layout-padding values))}]]]))]))
|
||||
|
||||
|
||||
|
||||
(mf/defc layout-menu
|
||||
(mf/defc layout-container-menu
|
||||
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values" "type"]))]}
|
||||
[{:keys [_ids _type _values] :as props}]
|
||||
(let [test-values (mf/use-state {:layout false
|
||||
:layout-dir nil
|
||||
:gap 0
|
||||
:layout-type nil
|
||||
:wrap-type nil
|
||||
:padding-type nil
|
||||
:padding {:p1 0 :p2 0 :p3 0 :p4 0}
|
||||
:h-orientation nil
|
||||
:v-orientation nil})
|
||||
|
||||
open? (mf/use-state false)
|
||||
[{:keys [ids _type values] :as props}]
|
||||
(let [open? (mf/use-state false)
|
||||
gap-selected? (mf/use-state false)
|
||||
toggle-open (fn [] (swap! open? not))
|
||||
|
||||
on-add-layout
|
||||
(fn [_]
|
||||
(reset! test-values {:layout true
|
||||
:layout-dir :left
|
||||
:gap 0
|
||||
:layout-type :packed
|
||||
:wrap-type :wrap
|
||||
:padding-type :simple
|
||||
:padding {:p1 0 :p2 0 :p3 0 :p4 0}
|
||||
:h-orientation :top
|
||||
:v-orientation :left}))
|
||||
(st/emit! (dwsl/create-layout ids)))
|
||||
|
||||
on-remove-layout
|
||||
(fn [_]
|
||||
(reset! test-values {:layout false
|
||||
:layout-dir nil
|
||||
:gap 0
|
||||
:layout-type nil
|
||||
:wrap-type nil
|
||||
:padding-type nil
|
||||
:padding {:p1 0 :p2 0 :p3 0 :p4 0}
|
||||
:h-orientation nil
|
||||
:v-orientation nil})
|
||||
(st/emit! (dwsl/remove-layout ids))
|
||||
(reset! open? false))
|
||||
|
||||
set-direction
|
||||
(fn [dir]
|
||||
(swap! test-values assoc :layout-dir dir))
|
||||
(st/emit! (dwsl/update-layout ids {:layout-dir dir})))
|
||||
|
||||
set-gap
|
||||
(fn [event]
|
||||
(swap! test-values assoc :gap event))
|
||||
|
||||
(fn [gap]
|
||||
(st/emit! (dwsl/update-layout ids {:layout-gap gap})))
|
||||
|
||||
change-padding-style
|
||||
(fn [type]
|
||||
(swap! test-values assoc :padding-type type))
|
||||
(st/emit! (dwsl/update-layout ids {:layout-padding-type type})))
|
||||
|
||||
select-all #(dom/select-target %)
|
||||
|
||||
select-all-gap #(do (reset! gap-selected? true)
|
||||
(dom/select-target %))
|
||||
select-all-gap
|
||||
(fn [event]
|
||||
(reset! gap-selected? true)
|
||||
(dom/select-target event))
|
||||
|
||||
on-padding-change
|
||||
(fn [type val]
|
||||
(if (= type :simple)
|
||||
(swap! test-values assoc :padding {:p1 val :p2 val :p3 val :p4 val})
|
||||
(swap! test-values assoc-in [:padding type] val)))
|
||||
(st/emit! (dwsl/update-layout ids {:layout-padding {:p1 val :p2 val :p3 val :p4 val}}))
|
||||
(st/emit! (dwsl/update-layout ids {:layout-padding {type val}}))))
|
||||
|
||||
handle-change-type
|
||||
(fn [event]
|
||||
(let [target (dom/get-target event)
|
||||
value (dom/get-value target)
|
||||
value (keyword value)]
|
||||
(swap! test-values assoc :layout-type value)))
|
||||
(st/emit! (dwsl/update-layout ids {:layout-type value}))))
|
||||
|
||||
handle-wrap-type
|
||||
(mf/use-callback
|
||||
|
@ -244,47 +249,30 @@
|
|||
(let [target (dom/get-target event)
|
||||
value (dom/get-value target)
|
||||
value (keyword value)]
|
||||
(swap! test-values assoc :wrap-type value))))
|
||||
(st/emit! (dwsl/update-layout ids {:layout-wrap-type value})))))
|
||||
|
||||
manage-orientation
|
||||
(fn [h v]
|
||||
(swap! test-values assoc :h-orientation h :v-orientation v))
|
||||
|
||||
get-icon
|
||||
(fn [dir layout-type v h]
|
||||
(let [col? (= dir (or :left :right))
|
||||
manage-text-icon
|
||||
(if col?
|
||||
(case h
|
||||
:left i/text-align-left
|
||||
:center i/text-align-center
|
||||
:right i/text-align-right
|
||||
i/text-align-center)
|
||||
|
||||
(case v
|
||||
:top i/text-align-left
|
||||
:center i/text-align-center
|
||||
:bottom i/text-align-right
|
||||
i/text-align-center))]
|
||||
(case layout-type
|
||||
:packed manage-text-icon
|
||||
:space-around i/space-around
|
||||
:space-between i/space-between)))
|
||||
handle-change-orientation
|
||||
(fn [v-orientation h-orientation]
|
||||
(st/emit! (dwsl/update-layout ids {:layout-h-orientation h-orientation :layout-v-orientation v-orientation})))
|
||||
|
||||
layout-info
|
||||
(fn []
|
||||
(let [type (:layout-type @test-values)
|
||||
dir (:layout-dir @test-values)
|
||||
is-col? (or (= dir :top)
|
||||
(= dir :bottom))
|
||||
h (:v-orientation @test-values)
|
||||
v (:h-orientation @test-values)
|
||||
wrap (:wrap-type @test-values)
|
||||
orientation (if (= type :packed)
|
||||
(dm/str (tr (dm/str "workspace.options.layout.v." (d/name v))) ", " (tr (dm/str "workspace.options.layout.h." (d/name h))) ", ")
|
||||
(if is-col?
|
||||
(dm/str (tr (dm/str "workspace.options.layout.h." (d/name h))) ", ")
|
||||
(dm/str (tr (dm/str "workspace.options.layout.v." (d/name v))) ", ")))]
|
||||
(let [type (:layout-type values)
|
||||
dir (:layout-dir values)
|
||||
is-col? (or (= dir :top) (= dir :bottom))
|
||||
h (:layout-h-orientation values)
|
||||
v (:layout-v-orientation values)
|
||||
|
||||
wrap (:layout-wrap-type values)
|
||||
|
||||
orientation
|
||||
(if (= type :packed)
|
||||
(dm/str (tr (dm/str "workspace.options.layout.v." (d/name v))) ", "
|
||||
(tr (dm/str "workspace.options.layout.h." (d/name h))) ", ")
|
||||
|
||||
(if is-col?
|
||||
(dm/str (tr (dm/str "workspace.options.layout.h." (d/name h))) ", ")
|
||||
(dm/str (tr (dm/str "workspace.options.layout.v." (d/name v))) ", ")))]
|
||||
|
||||
(dm/str orientation
|
||||
(str/replace (tr (dm/str "workspace.options.layout." (d/name type))) "-" " ") ", "
|
||||
|
@ -294,26 +282,27 @@
|
|||
[:div.element-set-title
|
||||
[:*
|
||||
[:span (tr "workspace.options.layout.title")]
|
||||
(if (= true (:layout @test-values))
|
||||
(if (:layout values)
|
||||
[:div.add-page {:on-click on-remove-layout} i/minus]
|
||||
[:div.add-page {:on-click on-add-layout} i/close])]]
|
||||
|
||||
(when (= true (:layout @test-values))
|
||||
(when (:layout values)
|
||||
[:div.element-set-content.layout-menu
|
||||
;; DIRECTION-GAP
|
||||
[:div.direction-gap
|
||||
[:div.direction
|
||||
[:*
|
||||
(for [dir [:left :right :bottom :top]]
|
||||
[:& direction-row {:dir dir
|
||||
:saved-dir (:layout-dir @test-values)
|
||||
[:& direction-row {:key (d/name dir)
|
||||
:dir dir
|
||||
:saved-dir (:layout-dir values)
|
||||
:set-direction set-direction}])]]
|
||||
[:div.gap.tooltip.tooltip-bottom-left
|
||||
{:alt (tr "workspace.options.layout.gap")}
|
||||
[:span.icon
|
||||
{:class (dom/classnames
|
||||
:rotated (or (= (:layout-dir @test-values) :top)
|
||||
(= (:layout-dir @test-values) :bottom))
|
||||
:rotated (or (= (:layout-dir values) :top)
|
||||
(= (:layout-dir values) :bottom))
|
||||
:activated (= @gap-selected? true))}
|
||||
i/auto-gap]
|
||||
[:> numeric-input {:no-validate true
|
||||
|
@ -321,7 +310,7 @@
|
|||
:on-click select-all-gap
|
||||
:on-change set-gap
|
||||
:on-blur #(reset! gap-selected? false)
|
||||
:value (:gap @test-values)}]]]
|
||||
:value (:layout-gap values)}]]]
|
||||
|
||||
;; LAYOUT FLEX
|
||||
[:div.layout-container
|
||||
|
@ -329,25 +318,24 @@
|
|||
{:on-click toggle-open
|
||||
:alt (layout-info)}
|
||||
[:div.element-set-actions-button i/actions]
|
||||
[:div.layout-info
|
||||
(layout-info)]]
|
||||
(when (= true @open?)
|
||||
[:div.layout-info (layout-info)]]
|
||||
|
||||
(when @open?
|
||||
[:div.layout-body
|
||||
[:& orientation-grid {:manage-orientation manage-orientation :test-values test-values :get-icon get-icon}]
|
||||
[:& orientation-grid {:on-change-orientation handle-change-orientation :values values}]
|
||||
|
||||
[:div.selects-wrapper
|
||||
[:select.input-select {:value (d/name (:layout-type @test-values))
|
||||
[:select.input-select {:value (d/name (:layout-type values))
|
||||
:on-change handle-change-type}
|
||||
[:option {:value "packed" :label (tr "workspace.options.layout.packed")}]
|
||||
[:option {:value "space-between" :label (tr "workspace.options.layout.space-between")}]
|
||||
[:option {:value "space-around" :label (tr "workspace.options.layout.space-around")}]]
|
||||
|
||||
[:select.input-select {:value (d/name (:wrap-type @test-values))
|
||||
[:select.input-select {:value (d/name (:layout-wrap-type values))
|
||||
:on-change handle-wrap-type}
|
||||
[:option {:value "wrap" :label (tr "workspace.options.layout.wrap")}]
|
||||
[:option {:value "no-wrap" :label (tr "workspace.options.layout.no-wrap")}]]]])]
|
||||
|
||||
[:& padding-section {:test-values test-values
|
||||
:change-padding-style change-padding-style
|
||||
:select-all select-all
|
||||
:on-padding-change on-padding-change}]])]))
|
||||
[:& padding-section {:values values
|
||||
:on-change-style change-padding-style
|
||||
:on-change on-padding-change}]])]))
|
|
@ -8,6 +8,8 @@
|
|||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.data.workspace.shape-layout :as dwsl]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.numeric-input :refer [numeric-input]]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
|
@ -15,18 +17,19 @@
|
|||
[rumext.alpha :as mf]))
|
||||
|
||||
(def layout-item-attrs
|
||||
[:margin ;; {:m1 0 :m2 0 :m3 0 :m4 0}
|
||||
:margin-type ;; :simple :multiple
|
||||
:h-behavior ;; :fill :fix :auto
|
||||
:v-behavior ;; :fill :fix :auto
|
||||
:max-h ;; num
|
||||
:min-h ;; num
|
||||
:max-w ;; num
|
||||
:min-w ]) ;; num
|
||||
(mf/defc margin-section
|
||||
[{:keys [test-values change-margin-style select-all on-margin-change] :as props}]
|
||||
[:layout-margin ;; {:m1 0 :m2 0 :m3 0 :m4 0}
|
||||
:layout-margin-type ;; :simple :multiple
|
||||
:layout-h-behavior ;; :fill :fix :auto
|
||||
:layout-v-behavior ;; :fill :fix :auto
|
||||
:layout-max-h ;; num
|
||||
:layout-min-h ;; num
|
||||
:layout-max-w ;; num
|
||||
:layout-min-w ]) ;; num
|
||||
|
||||
(let [margin-type (:margin-type @test-values)]
|
||||
(mf/defc margin-section
|
||||
[{:keys [values change-margin-style on-margin-change] :as props}]
|
||||
|
||||
(let [margin-type (or (:layout-margin-type values) :simple)]
|
||||
|
||||
[:div.row-flex
|
||||
[:div.margin-options
|
||||
|
@ -49,9 +52,9 @@
|
|||
|
||||
[:> numeric-input
|
||||
{:placeholder "--"
|
||||
:on-click select-all
|
||||
:on-click #(dom/select-target %)
|
||||
:on-change (partial on-margin-change :simple)
|
||||
:value (:m1 (:margin @test-values))}]]]
|
||||
:value (or (-> values :layout-margin :m1) 0)}]]]
|
||||
|
||||
(= margin-type :multiple)
|
||||
[:*
|
||||
|
@ -67,101 +70,93 @@
|
|||
[:div.input-element.mini
|
||||
[:> numeric-input
|
||||
{:placeholder "--"
|
||||
:on-click select-all
|
||||
:on-click #(dom/select-target %)
|
||||
:on-change (partial on-margin-change num)
|
||||
:value (num (:margin @test-values))}]]])])]))
|
||||
:value (or (-> values :layout-margin num) 0)}]]])])]))
|
||||
|
||||
(mf/defc element-behavior
|
||||
[{:keys [is-layout-container? is-layout-item? h-behavior v-behavior on-change-behavior] :as props}]
|
||||
(let [auto? is-layout-container?
|
||||
fill? (and (= true is-layout-item?) (not= true is-layout-container?))]
|
||||
[{:keys [is-layout-container? is-layout-child? layout-h-behavior layout-v-behavior on-change-behavior] :as props}]
|
||||
(let [fill? is-layout-child?
|
||||
auto? is-layout-container?]
|
||||
|
||||
[:div.layout-behavior
|
||||
[:div.button-wrapper.horizontal
|
||||
[:button.behavior-btn.tooltip.tooltip-bottom
|
||||
{:alt "horizontal fix"
|
||||
:class (dom/classnames :activated (= h-behavior :fix))
|
||||
:class (dom/classnames :activated (= layout-h-behavior :fix))
|
||||
:on-click #(on-change-behavior :h :fix)}
|
||||
[:span.icon i/auto-fix-layout]]
|
||||
(when fill?
|
||||
[:button.behavior-btn.tooltip.tooltip-bottom
|
||||
{:alt "horizontal fill"
|
||||
:class (dom/classnames :activated (= h-behavior :fill))
|
||||
:class (dom/classnames :activated (= layout-h-behavior :fill))
|
||||
:on-click #(on-change-behavior :h :fill)}
|
||||
[:span.icon i/auto-fill]])
|
||||
(when auto?
|
||||
[:button.behavior-btn.tooltip.tooltip-bottom
|
||||
{:alt "horizontal auto"
|
||||
:class (dom/classnames :activated (= h-behavior :auto))
|
||||
:class (dom/classnames :activated (= layout-v-behavior :auto))
|
||||
:on-click #(on-change-behavior :h :auto)}
|
||||
[:span.icon i/auto-hug]])]
|
||||
|
||||
[:div.button-wrapper
|
||||
[:button.behavior-btn.tooltip.tooltip-bottom
|
||||
{:alt "vertical fix"
|
||||
:class (dom/classnames :activated (= v-behavior :fix))
|
||||
:class (dom/classnames :activated (= layout-v-behavior :fix))
|
||||
:on-click #(on-change-behavior :v :fix)}
|
||||
[:span.icon i/auto-fix-layout]]
|
||||
(when fill?
|
||||
[:button.behavior-btn.tooltip.tooltip-bottom
|
||||
{:alt "vertical fill"
|
||||
:class (dom/classnames :activated (= v-behavior :fill))
|
||||
:class (dom/classnames :activated (= layout-v-behavior :fill))
|
||||
:on-click #(on-change-behavior :v :fill)}
|
||||
[:span.icon i/auto-fill]])
|
||||
(when auto?
|
||||
[:button.behavior-btn.tooltip.tooltip-bottom
|
||||
{:alt "vertical auto"
|
||||
:class (dom/classnames :activated (= v-behavior :auto))
|
||||
:class (dom/classnames :activated (= layout-v-behavior :auto))
|
||||
:on-click #(on-change-behavior :v :auto)}
|
||||
[:span.icon i/auto-hug]])]]))
|
||||
|
||||
(mf/defc layout-item-menu
|
||||
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values" "type"]))]}
|
||||
[{:keys [_ids _type _values] :as props}]
|
||||
(let [test-values (mf/use-state {:margin {:m1 0 :m2 0 :m3 0 :m4 0}
|
||||
:margin-type :simple
|
||||
:h-behavior :fill
|
||||
:v-behavior :fill
|
||||
:max-h 100
|
||||
:min-h 100
|
||||
:max-w 100
|
||||
:min-w 100})
|
||||
open? (mf/use-state false)
|
||||
[{:keys [ids _type values is-layout-child? is-layout-container?] :as props}]
|
||||
(let [open? (mf/use-state false)
|
||||
toggle-open (fn [] (swap! open? not))
|
||||
is-layout-container? true
|
||||
is-layout-item? true
|
||||
|
||||
change-margin-style
|
||||
(fn [type]
|
||||
(swap! test-values assoc :margin-type type))
|
||||
|
||||
select-all #(dom/select-target %)
|
||||
(st/emit! (dwsl/update-layout-child ids {:layout-margin-type type})))
|
||||
|
||||
on-margin-change
|
||||
(fn [type val]
|
||||
(if (= type :simple)
|
||||
(swap! test-values assoc :margin {:m1 val :m2 val :m3 val :m4 val})
|
||||
(swap! test-values assoc-in [:margin type] val)))
|
||||
(st/emit! (dwsl/update-layout-child ids {:layout-margin {:m1 val :m2 val :m3 val :m4 val}}))
|
||||
(st/emit! (dwsl/update-layout-child ids {:layout-margin {type val}}))))
|
||||
|
||||
on-change-behavior
|
||||
(fn [dir value]
|
||||
(if (= dir :h)
|
||||
(swap! test-values assoc :h-behavior value)
|
||||
(swap! test-values assoc :v-behavior value)))
|
||||
(st/emit! (dwsl/update-layout-child ids {:layout-h-behavior value}))
|
||||
(st/emit! (dwsl/update-layout-child ids {:layout-v-behavior value}))))
|
||||
|
||||
on-size-change
|
||||
(fn [measure value]
|
||||
(swap! test-values assoc measure value))]
|
||||
(st/emit! (dwsl/update-layout-child ids {measure value})))]
|
||||
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
[:span (tr "workspace.options.layout-item.title")]]
|
||||
|
||||
[:div.element-set-content.layout-item-menu
|
||||
[:& element-behavior {:is-layout-container? is-layout-container?
|
||||
:is-layout-item? is-layout-item?
|
||||
:v-behavior (:v-behavior @test-values)
|
||||
:h-behavior (:h-behavior @test-values)
|
||||
[:& element-behavior {:is-layout-child? is-layout-child?
|
||||
:is-layout-container? is-layout-container?
|
||||
:layout-v-behavior (or (:layout-v-behavior values) :fix)
|
||||
:layout-h-behavior (or (:layout-h-behavior values) :fix)
|
||||
:on-change-behavior on-change-behavior}]
|
||||
[:div.margin [:& margin-section {:test-values test-values
|
||||
|
||||
[:div.margin [:& margin-section {:values values
|
||||
:change-margin-style change-margin-style
|
||||
:select-all select-all
|
||||
:on-margin-change on-margin-change}]]
|
||||
[:div.advanced-ops-container
|
||||
[:div.advanced-ops.toltip.tooltip-bottom
|
||||
|
@ -169,22 +164,24 @@
|
|||
:alt (tr "workspace.options.layout-item.advanced-ops")}
|
||||
[:div.element-set-actions-button i/actions]
|
||||
[:span (tr "workspace.options.layout-item.advanced-ops")]]]
|
||||
(when (= true @open?)
|
||||
|
||||
(when @open?
|
||||
[:div.advanced-ops-body
|
||||
(for [item [:max-h :min-h :max-w :min-w]]
|
||||
(for [item [:layout-max-h :layout-min-h :layout-max-w :layout-min-w]]
|
||||
[:div.input-element
|
||||
{:alt (tr (dm/str "workspace.options.layout-item." (d/name item)))
|
||||
{:key (d/name item)
|
||||
:alt (tr (dm/str "workspace.options.layout-item." (d/name item)))
|
||||
:title (tr (dm/str "workspace.options.layout-item." (d/name item)))
|
||||
:class (dom/classnames "maxH" (= item :max-h)
|
||||
"minH" (= item :min-h)
|
||||
"maxW" (= item :max-w)
|
||||
"minW" (= item :min-w))
|
||||
:key item}
|
||||
:class (dom/classnames "maxH" (= item :layout-max-h)
|
||||
"minH" (= item :layout-min-h)
|
||||
"maxW" (= item :layout-max-w)
|
||||
"minW" (= item :layout-min-w))}
|
||||
|
||||
[:> numeric-input
|
||||
{:no-validate true
|
||||
:min 0
|
||||
:data-wrap true
|
||||
:placeholder "--"
|
||||
:on-click select-all
|
||||
:on-click #(dom/select-target %)
|
||||
:on-change (partial on-size-change item)
|
||||
:value (item @test-values)}]])])]]))
|
||||
:value (get values item)}]])])]]))
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
(ns app.main.ui.workspace.sidebar.options.shapes.bool
|
||||
(:require
|
||||
[app.main.constants :refer [has-layout-item]]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs fill-menu]]
|
||||
|
@ -25,17 +25,22 @@
|
|||
stroke-values (select-keys shape stroke-attrs)
|
||||
layer-values (select-keys shape layer-attrs)
|
||||
constraint-values (select-keys shape constraint-attrs)
|
||||
layout-item-values (select-keys shape layout-item-attrs)]
|
||||
layout-item-values (select-keys shape layout-item-attrs)
|
||||
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)]
|
||||
[:*
|
||||
[:& measures-menu {:ids ids
|
||||
:type type
|
||||
:values measure-values
|
||||
:shape shape}]
|
||||
(when has-layout-item
|
||||
[:& layout-item-menu {:ids ids
|
||||
:type type
|
||||
:values layout-item-values
|
||||
:shape shape}])
|
||||
(when is-layout-child?
|
||||
[:& layout-item-menu
|
||||
{:ids ids
|
||||
:type type
|
||||
:values layout-item-values
|
||||
:is-layout-child? true
|
||||
:shape shape}])
|
||||
[:& constraints-menu {:ids ids
|
||||
:values constraint-values}]
|
||||
[:& layer-menu {:ids ids
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
(ns app.main.ui.workspace.sidebar.options.shapes.circle
|
||||
(:require
|
||||
[app.main.constants :refer [has-layout-item]]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs fill-menu]]
|
||||
|
@ -22,20 +22,26 @@
|
|||
[{:keys [shape] :as props}]
|
||||
(let [ids [(:id shape)]
|
||||
type (:type shape)
|
||||
|
||||
measure-values (select-keys shape measure-attrs)
|
||||
stroke-values (select-keys shape stroke-attrs)
|
||||
layer-values (select-keys shape layer-attrs)
|
||||
constraint-values (select-keys shape constraint-attrs)
|
||||
layout-item-values (select-keys shape layout-item-attrs)]
|
||||
layout-item-values (select-keys shape layout-item-attrs)
|
||||
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)]
|
||||
[:*
|
||||
[:& measures-menu {:ids ids
|
||||
:type type
|
||||
:values measure-values
|
||||
:shape shape}]
|
||||
(when has-layout-item
|
||||
(when is-layout-child?
|
||||
[:& layout-item-menu {:ids ids
|
||||
:type type
|
||||
:values layout-item-values
|
||||
:is-layout-child? true
|
||||
:is-layout-container? false
|
||||
:shape shape}])
|
||||
[:& constraints-menu {:ids ids
|
||||
:values constraint-values}]
|
||||
|
|
|
@ -6,13 +6,14 @@
|
|||
|
||||
(ns app.main.ui.workspace.sidebar.options.shapes.frame
|
||||
(:require
|
||||
[app.main.constants :refer [has-layout-item]]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.features :as features]
|
||||
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs-shape fill-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.frame-grid :refer [frame-grid]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.layout :refer [layout-attrs layout-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-attrs layout-container-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.measures :refer [measure-attrs measures-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.shadow :refer [shadow-menu]]
|
||||
|
@ -23,12 +24,18 @@
|
|||
[{:keys [shape] :as props}]
|
||||
(let [ids [(:id shape)]
|
||||
type (:type shape)
|
||||
|
||||
layout-active? (features/use-feature :auto-layout)
|
||||
|
||||
stroke-values (select-keys shape stroke-attrs)
|
||||
layer-values (select-keys shape layer-attrs)
|
||||
measure-values (select-keys shape measure-attrs)
|
||||
constraint-values (select-keys shape constraint-attrs)
|
||||
layout-values (select-keys shape layout-attrs)
|
||||
layout-item-values (select-keys shape layout-item-attrs)]
|
||||
layout-container-values (select-keys shape layout-container-attrs)
|
||||
layout-item-values (select-keys shape layout-item-attrs)
|
||||
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)]
|
||||
[:*
|
||||
[:& measures-menu {:ids [(:id shape)]
|
||||
:values measure-values
|
||||
|
@ -36,14 +43,19 @@
|
|||
:shape shape}]
|
||||
[:& constraints-menu {:ids ids
|
||||
:values constraint-values}]
|
||||
(when has-layout-item
|
||||
[:& layout-menu {:type type :ids [(:id shape)] :values layout-values}])
|
||||
|
||||
(when has-layout-item
|
||||
[:& layout-item-menu {:ids ids
|
||||
:type type
|
||||
:values layout-item-values
|
||||
:shape shape}])
|
||||
(when layout-active?
|
||||
[:*
|
||||
[:& layout-container-menu {:type type :ids [(:id shape)] :values layout-container-values}]
|
||||
|
||||
(when (or (:layout shape) is-layout-child?)
|
||||
[:& layout-item-menu
|
||||
{:ids ids
|
||||
:type type
|
||||
:values layout-item-values
|
||||
:is-layout-child? is-layout-child?
|
||||
:is-layout-container? (:layout shape)
|
||||
:shape shape}])])
|
||||
|
||||
[:& layer-menu {:ids ids
|
||||
:type type
|
||||
:values layer-values}]
|
||||
|
|
|
@ -7,14 +7,13 @@
|
|||
(ns app.main.ui.workspace.sidebar.options.shapes.group
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.main.constants :refer [has-layout-item]]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.color-selection :refer [color-selection-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.component :refer [component-attrs component-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraints-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.layout :refer [layout-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.measures :refer [measures-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.shadow :refer [shadow-menu]]
|
||||
|
@ -34,6 +33,10 @@
|
|||
objects (->> shape-with-children (group-by :id) (d/mapm (fn [_ v] (first v))))
|
||||
file-id (unchecked-get props "file-id")
|
||||
|
||||
ids [(:id shape)]
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)
|
||||
|
||||
type :group
|
||||
[measure-ids measure-values] (get-attrs [shape] objects :measure)
|
||||
[layer-ids layer-values] (get-attrs [shape] objects :layer)
|
||||
|
@ -45,17 +48,20 @@
|
|||
[text-ids text-values] (get-attrs [shape] objects :text)
|
||||
[svg-ids svg-values] [[(:id shape)] (select-keys shape [:svg-attrs])]
|
||||
[comp-ids comp-values] [[(:id shape)] (select-keys shape component-attrs)]
|
||||
[layout-ids layout-values] (get-attrs [shape] objects :layout)
|
||||
[layout-item-ids layout-item-values] (get-attrs [shape] objects :layout-item)
|
||||
]
|
||||
[layout-item-ids layout-item-values] (get-attrs [shape] objects :layout-item)]
|
||||
|
||||
[:div.options
|
||||
[:& measures-menu {:type type :ids measure-ids :values measure-values :shape shape}]
|
||||
[:& component-menu {:ids comp-ids :values comp-values :shape-name (:name shape)}]
|
||||
(when-not (empty? layout-ids)
|
||||
[:& layout-menu {:type type :ids layout-ids :values layout-values}])
|
||||
(when has-layout-item
|
||||
[:& layout-item-menu {:type type :ids layout-item-ids :values layout-item-values}])
|
||||
|
||||
(when is-layout-child?
|
||||
[:& layout-item-menu
|
||||
{:type type
|
||||
:ids layout-item-ids
|
||||
:is-layout-child? true
|
||||
:is-layout-container? false
|
||||
:values layout-item-values}])
|
||||
|
||||
[:& constraints-menu {:ids constraint-ids :values constraint-values}]
|
||||
[:& layer-menu {:type type :ids layer-ids :values layer-values}]
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
(ns app.main.ui.workspace.sidebar.options.shapes.image
|
||||
(:require
|
||||
[app.main.constants :refer [has-layout-item]]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs fill-menu]]
|
||||
|
@ -21,22 +21,28 @@
|
|||
[{:keys [shape] :as props}]
|
||||
(let [ids [(:id shape)]
|
||||
type (:type shape)
|
||||
|
||||
measure-values (select-keys shape measure-attrs)
|
||||
layer-values (select-keys shape layer-attrs)
|
||||
constraint-values (select-keys shape constraint-attrs)
|
||||
fill-values (select-keys shape fill-attrs)
|
||||
stroke-values (select-keys shape stroke-attrs)
|
||||
layout-item-values (select-keys shape layout-item-attrs)]
|
||||
layout-item-values (select-keys shape layout-item-attrs)
|
||||
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)]
|
||||
[:*
|
||||
[:& measures-menu {:ids ids
|
||||
:type type
|
||||
:values measure-values
|
||||
:shape shape}]
|
||||
(when has-layout-item
|
||||
[:& layout-item-menu {:ids ids
|
||||
:type type
|
||||
:values layout-item-values
|
||||
:shape shape}])
|
||||
(when is-layout-child?
|
||||
[:& layout-item-menu
|
||||
{:ids ids
|
||||
:type type
|
||||
:values layout-item-values
|
||||
:is-layout-child? true
|
||||
:shape shape}])
|
||||
|
||||
[:& constraints-menu {:ids ids
|
||||
:values constraint-values}]
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.pages.common :as cpc]
|
||||
[app.common.text :as txt]
|
||||
[app.main.constants :refer [has-layout-item]]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-attrs blur-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.color-selection :refer [color-selection-menu]]
|
||||
|
@ -19,7 +19,7 @@
|
|||
[app.main.ui.workspace.sidebar.options.menus.exports :refer [exports-attrs exports-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs fill-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.layout :refer [layout-attrs layout-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-attrs layout-container-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.measures :refer [measure-attrs measures-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.shadow :refer [shadow-attrs shadow-menu]]
|
||||
|
@ -142,7 +142,7 @@
|
|||
:stroke stroke-attrs
|
||||
:text ot/attrs
|
||||
:exports exports-attrs
|
||||
:layout layout-attrs
|
||||
:layout layout-container-attrs
|
||||
:layout-item layout-item-attrs})
|
||||
|
||||
(def shadow-keys [:style :color :offset-x :offset-y :blur :spread])
|
||||
|
@ -247,6 +247,10 @@
|
|||
type :multiple
|
||||
all-types (into #{} (map :type shapes))
|
||||
|
||||
ids (->> shapes (map :id))
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)
|
||||
|
||||
has-text? (contains? all-types :text)
|
||||
|
||||
[measure-ids measure-values] (get-attrs shapes objects :measure)
|
||||
|
@ -260,7 +264,7 @@
|
|||
stroke-ids stroke-values
|
||||
text-ids text-values
|
||||
exports-ids exports-values
|
||||
layout-ids layout-values
|
||||
layout-ids layout-container-values
|
||||
layout-item-ids layout-item-values]
|
||||
(mf/use-memo
|
||||
(mf/deps objects-no-measures)
|
||||
|
@ -284,11 +288,16 @@
|
|||
(when-not (empty? measure-ids)
|
||||
[:& measures-menu {:type type :all-types all-types :ids measure-ids :values measure-values :shape shapes}])
|
||||
|
||||
(when-not (empty? layout-ids)
|
||||
[:& layout-menu {:type type :ids layout-ids :values layout-values}])
|
||||
(when (:layout layout-container-values)
|
||||
[:& layout-container-menu {:type type :ids layout-ids :values layout-container-values}])
|
||||
|
||||
(when has-layout-item
|
||||
[:& layout-item-menu {:type type :ids layout-item-ids :values layout-item-values}])
|
||||
(when is-layout-child?
|
||||
[:& layout-item-menu
|
||||
{:type type
|
||||
:ids layout-item-ids
|
||||
:is-layout-child? true
|
||||
:is-layout-container? true
|
||||
:values layout-item-values}])
|
||||
|
||||
(when-not (empty? constraint-ids)
|
||||
[:& constraints-menu {:ids constraint-ids :values constraint-values}])
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
(ns app.main.ui.workspace.sidebar.options.shapes.path
|
||||
(:require
|
||||
[app.main.constants :refer [has-layout-item]]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs fill-menu]]
|
||||
|
@ -22,20 +22,26 @@
|
|||
[{:keys [shape] :as props}]
|
||||
(let [ids [(:id shape)]
|
||||
type (:type shape)
|
||||
|
||||
measure-values (select-keys shape measure-attrs)
|
||||
stroke-values (select-keys shape stroke-attrs)
|
||||
layer-values (select-keys shape layer-attrs)
|
||||
constraint-values (select-keys shape constraint-attrs)
|
||||
layout-item-values (select-keys shape layout-item-attrs)]
|
||||
layout-item-values (select-keys shape layout-item-attrs)
|
||||
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)]
|
||||
[:*
|
||||
[:& measures-menu {:ids ids
|
||||
:type type
|
||||
:values measure-values
|
||||
:shape shape}]
|
||||
(when has-layout-item
|
||||
(when is-layout-child?
|
||||
[:& layout-item-menu {:ids ids
|
||||
:type type
|
||||
:values layout-item-values
|
||||
:is-layout-child? true
|
||||
:is-layout-container? false
|
||||
:shape shape}])
|
||||
[:& constraints-menu {:ids ids
|
||||
:values constraint-values}]
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
(ns app.main.ui.workspace.sidebar.options.shapes.rect
|
||||
(:require
|
||||
[app.main.constants :refer [has-layout-item]]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs fill-menu]]
|
||||
|
@ -23,22 +23,28 @@
|
|||
[{:keys [shape] :as props}]
|
||||
(let [ids [(:id shape)]
|
||||
type (:type shape)
|
||||
|
||||
measure-values (select-keys shape measure-attrs)
|
||||
layer-values (select-keys shape layer-attrs)
|
||||
constraint-values (select-keys shape constraint-attrs)
|
||||
fill-values (select-keys shape fill-attrs)
|
||||
stroke-values (select-keys shape stroke-attrs)
|
||||
layout-item-values (select-keys shape layout-item-attrs)]
|
||||
layout-item-values (select-keys shape layout-item-attrs)
|
||||
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)]
|
||||
[:*
|
||||
[:& measures-menu {:ids ids
|
||||
:type type
|
||||
:values measure-values
|
||||
:shape shape}]
|
||||
(when has-layout-item
|
||||
[:& layout-item-menu {:ids ids
|
||||
:type type
|
||||
:values layout-item-values
|
||||
:shape shape}])
|
||||
(when is-layout-child?
|
||||
[:& layout-item-menu
|
||||
{:ids ids
|
||||
:type type
|
||||
:values layout-item-values
|
||||
:is-layout-child? true
|
||||
:shape shape}])
|
||||
[:& constraints-menu {:ids ids
|
||||
:values constraint-values}]
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
(:require
|
||||
[app.common.colors :as clr]
|
||||
[app.common.data :as d]
|
||||
[app.main.constants :refer [has-layout-item]]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs fill-menu]]
|
||||
|
@ -95,12 +95,16 @@
|
|||
|
||||
(let [ids [(:id shape)]
|
||||
type (:type shape)
|
||||
|
||||
{:keys [tag] :as content} (:content shape)
|
||||
measure-values (select-keys shape measure-attrs)
|
||||
constraint-values (select-keys shape constraint-attrs)
|
||||
fill-values (get-fill-values shape)
|
||||
stroke-values (get-stroke-values shape)
|
||||
layout-item-values (select-keys shape layout-item-attrs)]
|
||||
layout-item-values (select-keys shape layout-item-attrs)
|
||||
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)]
|
||||
|
||||
(when (contains? svg-elements tag)
|
||||
[:*
|
||||
|
@ -108,11 +112,13 @@
|
|||
:type type
|
||||
:values measure-values
|
||||
:shape shape}]
|
||||
(when has-layout-item
|
||||
[:& layout-item-menu {:ids ids
|
||||
:type type
|
||||
:values layout-item-values
|
||||
:shape shape}])
|
||||
(when is-layout-child?
|
||||
[:& layout-item-menu
|
||||
{:ids ids
|
||||
:type type
|
||||
:values layout-item-values
|
||||
:is-layout-child? true
|
||||
:shape shape}])
|
||||
|
||||
[:& constraints-menu {:ids ids
|
||||
:values constraint-values}]
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
(ns app.main.ui.workspace.sidebar.options.shapes.text
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.main.constants :refer [has-layout-item]]
|
||||
[app.main.data.workspace.texts :as dwt]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
|
||||
|
@ -27,6 +26,8 @@
|
|||
(let [ids [(:id shape)]
|
||||
type (:type shape)
|
||||
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)
|
||||
state-map (mf/deref refs/workspace-editor-state)
|
||||
shared-libs (mf/deref refs/workspace-libraries)
|
||||
|
||||
|
@ -69,11 +70,14 @@
|
|||
:type type
|
||||
:values (select-keys shape measure-attrs)
|
||||
:shape shape}]
|
||||
(when has-layout-item
|
||||
[:& layout-item-menu {:ids ids
|
||||
:type type
|
||||
:values layout-item-values
|
||||
:shape shape}])
|
||||
|
||||
(when is-layout-child?
|
||||
[:& layout-item-menu
|
||||
{:ids ids
|
||||
:type type
|
||||
:values layout-item-values
|
||||
:is-layout-child? true
|
||||
:shape shape}])
|
||||
[:& constraints-menu
|
||||
{:ids ids
|
||||
:values (select-keys shape constraint-attrs)}]
|
||||
|
|
|
@ -106,9 +106,7 @@
|
|||
"Extract the target from event instance and select it"
|
||||
[^js event]
|
||||
(when (some? event)
|
||||
(-> event
|
||||
(.-target)
|
||||
(.-select))))
|
||||
(-> event (.-target) (.select))))
|
||||
|
||||
(defn select-node
|
||||
"Select element by node"
|
||||
|
|
|
@ -353,3 +353,10 @@
|
|||
(let [root-node (dom/query ".viewport .render-shapes")
|
||||
num-nodes (->> (dom/seq-nodes root-node) count)]
|
||||
#js {:number num-nodes}))
|
||||
|
||||
#_(defn modif->js
|
||||
[modif-tree objects]
|
||||
(clj->js (into {}
|
||||
(map (fn [[k v]]
|
||||
[(get-in objects [k :name]) v]))
|
||||
modif-tree)))
|
||||
|
|
|
@ -3503,19 +3503,19 @@ msgid "workspace.options.layout-item.advanced-ops"
|
|||
msgstr "Advanced options"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
|
||||
msgid "workspace.options.layout-item.max-h"
|
||||
msgid "workspace.options.layout-item.layout-max-h"
|
||||
msgstr "Max.Height"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
|
||||
msgid "workspace.options.layout-item.max-w"
|
||||
msgid "workspace.options.layout-item.layout-max-w"
|
||||
msgstr "Max.Width"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
|
||||
msgid "workspace.options.layout-item.min-h"
|
||||
msgid "workspace.options.layout-item.layout-min-h"
|
||||
msgstr "Min.Height"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
|
||||
msgid "workspace.options.layout-item.min-w"
|
||||
msgid "workspace.options.layout-item.layout-min-w"
|
||||
msgstr "Min.Width"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
|
||||
|
@ -3523,19 +3523,19 @@ msgid "workspace.options.layout-item.title"
|
|||
msgstr "Element resizing"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
|
||||
msgid "workspace.options.layout-item.title.max-h"
|
||||
msgid "workspace.options.layout-item.title.layout-max-h"
|
||||
msgstr "Maximum height"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
|
||||
msgid "workspace.options.layout-item.title.max-w"
|
||||
msgid "workspace.options.layout-item.title.layout-max-w"
|
||||
msgstr "Maximum width"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
|
||||
msgid "workspace.options.layout-item.title.min-h"
|
||||
msgid "workspace.options.layout-item.title.layout-min-h"
|
||||
msgstr "Minimum height"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
|
||||
msgid "workspace.options.layout-item.title.min-w"
|
||||
msgid "workspace.options.layout-item.title.layout-min-w"
|
||||
msgstr "Minimum width"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs
|
||||
|
@ -4368,4 +4368,4 @@ msgid "workspace.updates.update"
|
|||
msgstr "Update"
|
||||
|
||||
msgid "workspace.viewport.click-to-close-path"
|
||||
msgstr "Click to close the path"
|
||||
msgstr "Click to close the path"
|
||||
|
|
|
@ -3661,19 +3661,19 @@ msgid "workspace.options.layout-item.advanced-ops"
|
|||
msgstr "Opciones avanzadas"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
|
||||
msgid "workspace.options.layout-item.max-h"
|
||||
msgid "workspace.options.layout-item.layout-max-h"
|
||||
msgstr "AlturaMax."
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
|
||||
msgid "workspace.options.layout-item.max-w"
|
||||
msgid "workspace.options.layout-item.layout-max-w"
|
||||
msgstr "AnchoMax."
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
|
||||
msgid "workspace.options.layout-item.min-h"
|
||||
msgid "workspace.options.layout-item.layout-min-h"
|
||||
msgstr "AlturaMin."
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
|
||||
msgid "workspace.options.layout-item.min-w"
|
||||
msgid "workspace.options.layout-item.layout-min-w"
|
||||
msgstr "AnchoMin."
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
|
||||
|
@ -3681,19 +3681,19 @@ msgid "workspace.options.layout-item.title"
|
|||
msgstr "Redimensionado de elemento"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
|
||||
msgid "workspace.options.layout-item.title.max-h"
|
||||
msgid "workspace.options.layout-item.title.layout-max-h"
|
||||
msgstr "Altura máxima"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
|
||||
msgid "workspace.options.layout-item.title.max-w"
|
||||
msgid "workspace.options.layout-item.title.layout-max-w"
|
||||
msgstr "Ancho máximo"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
|
||||
msgid "workspace.options.layout-item.title.min-h"
|
||||
msgid "workspace.options.layout-item.title.layout-min-h"
|
||||
msgstr "Altura mínima"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs
|
||||
msgid "workspace.options.layout-item.title.min-w"
|
||||
msgid "workspace.options.layout-item.title.layout-min-w"
|
||||
msgstr "Ancho mínimo"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs
|
||||
|
@ -4547,4 +4547,4 @@ msgid "workspace.updates.update"
|
|||
msgstr "Actualizar"
|
||||
|
||||
msgid "workspace.viewport.click-to-close-path"
|
||||
msgstr "Pulsar para cerrar la ruta"
|
||||
msgstr "Pulsar para cerrar la ruta"
|
||||
|
|
Loading…
Add table
Reference in a new issue