mirror of
https://github.com/penpot/penpot.git
synced 2025-03-18 18:51:29 -05:00
✨ Adds integration with new UI
This commit is contained in:
parent
11f347941e
commit
af098bb64d
13 changed files with 431 additions and 336 deletions
|
@ -13,8 +13,8 @@
|
|||
[app.common.geom.shapes.common :as gco]
|
||||
[app.common.geom.shapes.constraints :as gct]
|
||||
[app.common.geom.shapes.corners :as gsc]
|
||||
[app.common.geom.shapes.flex-layout :as gcl]
|
||||
[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]
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.common.geom.shapes.layout
|
||||
(ns app.common.geom.shapes.flex-layout
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.matrix :as gmt]
|
||||
|
@ -16,52 +16,95 @@
|
|||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.modifiers :as ctm]))
|
||||
|
||||
;; :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 ;; :flex, :grid in the future
|
||||
;; :layout-flex-dir ;; :row, :reverse-row, :column, :reverse-column
|
||||
;; :layout-gap-type ;; :simple, :multiple
|
||||
;; :layout-gap ;; {:row-gap number , :column-gap number}
|
||||
;; :layout-align-items ;; :start :end :center :strech
|
||||
;; :layout-justify-content ;; :start :center :end :space-between :space-around
|
||||
;; :layout-align-content ;; :start :center :end :space-between :space-around :strech (by default)
|
||||
;; :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
|
||||
|
||||
;; ITEMS
|
||||
;; :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
|
||||
|
||||
(defn col?
|
||||
[{:keys [layout-dir]}]
|
||||
(or (= :right layout-dir) (= :left layout-dir)))
|
||||
[{:keys [layout-flex-dir]}]
|
||||
(or (= :column layout-flex-dir) (= :reverse-column layout-flex-dir)))
|
||||
|
||||
(defn row?
|
||||
[{:keys [layout-dir]}]
|
||||
(or (= :top layout-dir) (= :bottom layout-dir)))
|
||||
[{:keys [layout-flex-dir]}]
|
||||
(or (= :row layout-flex-dir) (= :reverse-row layout-flex-dir)))
|
||||
|
||||
(defn h-start?
|
||||
[{:keys [layout-h-orientation]}]
|
||||
(= layout-h-orientation :left))
|
||||
[{:keys [layout-align-items layout-justify-content] :as shape}]
|
||||
(or (and (col? shape)
|
||||
(= layout-align-items :start))
|
||||
(and (row? shape)
|
||||
(= layout-justify-content :start))))
|
||||
|
||||
(defn h-center?
|
||||
[{:keys [layout-h-orientation]}]
|
||||
(= layout-h-orientation :center))
|
||||
[{:keys [layout-align-items layout-justify-content] :as shape}]
|
||||
(or (and (col? shape)
|
||||
(= layout-align-items :center))
|
||||
(and (row? shape)
|
||||
(= layout-justify-content :center))))
|
||||
|
||||
(defn h-end?
|
||||
[{:keys [layout-h-orientation]}]
|
||||
(= layout-h-orientation :right))
|
||||
[{:keys [layout-align-items layout-justify-content] :as shape}]
|
||||
(or (and (col? shape)
|
||||
(= layout-align-items :end))
|
||||
(and (row? shape)
|
||||
(= layout-justify-content :end))))
|
||||
|
||||
(defn v-start?
|
||||
[{:keys [layout-v-orientation]}]
|
||||
(= layout-v-orientation :top))
|
||||
[{:keys [layout-align-items layout-justify-content] :as shape}]
|
||||
(or (and (row? shape)
|
||||
(= layout-align-items :start))
|
||||
(and (col? shape)
|
||||
(= layout-justify-content :start))))
|
||||
|
||||
(defn v-center?
|
||||
[{:keys [layout-v-orientation]}]
|
||||
(= layout-v-orientation :center))
|
||||
[{:keys [layout-align-items layout-justify-content] :as shape}]
|
||||
(or (and (row? shape)
|
||||
(= layout-align-items :center))
|
||||
(and (col? shape)
|
||||
(= layout-justify-content :center))))
|
||||
|
||||
(defn v-end?
|
||||
[{:keys [layout-v-orientation]}]
|
||||
(= layout-v-orientation :bottom))
|
||||
[{:keys [layout-align-items layout-justify-content] :as shape}]
|
||||
(or (and (row? shape)
|
||||
(= layout-align-items :end))
|
||||
(and (col? shape)
|
||||
(= layout-justify-content :end))))
|
||||
|
||||
(defn gaps
|
||||
[{:keys [layout-gap layout-gap-type]}]
|
||||
(let [layout-gap-row (or (-> layout-gap :row-gap) 0)
|
||||
layout-gap-col (if (= layout-gap-type :simple)
|
||||
layout-gap-row
|
||||
(or (-> layout-gap :column-gap) 0))]
|
||||
[layout-gap-row layout-gap-col]))
|
||||
|
||||
(defn calc-layout-lines
|
||||
[{:keys [layout-gap layout-wrap-type] :as parent} children layout-bounds]
|
||||
"Calculates the lines basic data and accumulated values. The positions will be calculated in a different operation"
|
||||
[{:keys [layout-wrap-type] :as parent} children layout-bounds]
|
||||
|
||||
(let [wrap? (= layout-wrap-type :wrap)
|
||||
col? (col? parent)
|
||||
row? (row? parent)
|
||||
|
||||
[layout-gap-row layout-gap-col] (gaps parent)
|
||||
|
||||
layout-width (gpo/width-points layout-bounds)
|
||||
layout-height (gpo/height-points layout-bounds)
|
||||
|
||||
|
@ -71,39 +114,36 @@
|
|||
child-width (gpo/width-points child-bounds)
|
||||
child-height (gpo/height-points child-bounds)
|
||||
|
||||
col? (col? parent)
|
||||
row? (row? parent)
|
||||
|
||||
cur-child-fill?
|
||||
(or (and col? (= :fill (:layout-h-behavior child)))
|
||||
(and row? (= :fill (:layout-v-behavior child))))
|
||||
|
||||
cur-line-fill?
|
||||
(or (and row? (= :fill (:layout-h-behavior child)))
|
||||
(and col? (= :fill (:layout-v-behavior child))))
|
||||
|
||||
cur-line-fill?
|
||||
(or (and col? (= :fill (:layout-h-behavior child)))
|
||||
(and row? (= :fill (:layout-v-behavior child))))
|
||||
|
||||
;; TODO LAYOUT: ADD MINWIDTH/HEIGHT
|
||||
next-width (if (or (and col? cur-child-fill?)
|
||||
(and row? cur-line-fill?))
|
||||
next-width (if (or (and row? cur-child-fill?)
|
||||
(and col? cur-line-fill?))
|
||||
0
|
||||
child-width)
|
||||
|
||||
next-height (if (or (and row? cur-child-fill?)
|
||||
(and col? cur-line-fill?))
|
||||
next-height (if (or (and col? cur-child-fill?)
|
||||
(and row? cur-line-fill?))
|
||||
0
|
||||
child-height)
|
||||
|
||||
next-total-width (+ line-width next-width (* layout-gap (dec num-children)))
|
||||
next-total-height (+ line-height next-height (* layout-gap (dec num-children)))]
|
||||
next-total-width (+ line-width next-width (* layout-gap-row (dec num-children)))
|
||||
next-total-height (+ line-height next-height (* layout-gap-col (dec num-children)))]
|
||||
|
||||
(if (and (some? line-data)
|
||||
(or (not wrap?)
|
||||
(and col? (<= next-total-width layout-width))
|
||||
(and row? (<= next-total-height layout-height))))
|
||||
(and row? (<= next-total-width layout-width))
|
||||
(and col? (<= next-total-height layout-height))))
|
||||
|
||||
;; When :fill we add min width (0 by default)
|
||||
[{:line-width (if col? (+ line-width next-width) (max line-width next-width))
|
||||
:line-height (if row? (+ line-height next-height) (max line-height next-height))
|
||||
[{:line-width (if row? (+ line-width next-width) (max line-width next-width))
|
||||
:line-height (if col? (+ line-height next-height) (max line-height next-height))
|
||||
:num-children (inc num-children)
|
||||
:child-fill? (or cur-child-fill? child-fill?)
|
||||
:line-fill? (or cur-line-fill? line-fill?)
|
||||
|
@ -123,14 +163,16 @@
|
|||
(cond-> layout-lines (some? line-data) (conj line-data))))
|
||||
|
||||
(defn calc-layout-lines-position
|
||||
[{:keys [layout-gap] :as parent} layout-bounds layout-lines]
|
||||
[{:keys [layout-justify-content] :as parent} layout-bounds layout-lines]
|
||||
|
||||
(let [layout-width (gpo/width-points layout-bounds)
|
||||
layout-height (gpo/height-points layout-bounds)
|
||||
[layout-gap-row layout-gap-col] (gaps parent)
|
||||
|
||||
row? (row? parent)
|
||||
col? (col? parent)
|
||||
space-between? (= :space-between (:layout-type parent))
|
||||
space-around? (= :space-around (:layout-type parent))
|
||||
space-between? (= layout-justify-content :space-between)
|
||||
space-around? (= layout-justify-content :space-around)
|
||||
h-center? (h-center? parent)
|
||||
h-end? (h-end? parent)
|
||||
v-center? (v-center? parent)
|
||||
|
@ -148,61 +190,62 @@
|
|||
[total-width total-height]
|
||||
|
||||
(cond-> (gpo/origin layout-bounds)
|
||||
(and row? h-center?)
|
||||
(and col? h-center?)
|
||||
(gpt/add (xv (/ (- layout-width total-width) 2)))
|
||||
|
||||
(and row? h-end?)
|
||||
(and col? h-end?)
|
||||
(gpt/add (xv (- layout-width total-width)))
|
||||
|
||||
(and col? v-center?)
|
||||
(and row? v-center?)
|
||||
(gpt/add (yv (/ (- layout-height total-height) 2)))
|
||||
|
||||
(and col? v-end?)
|
||||
(and row? v-end?)
|
||||
(gpt/add (yv (- layout-height total-height)))))
|
||||
|
||||
(get-start-line
|
||||
[{:keys [line-width line-height num-children child-fill?]} base-p]
|
||||
|
||||
(let [children-gap (* layout-gap (dec num-children))
|
||||
(let [children-gap-width (* layout-gap-row (dec num-children))
|
||||
children-gap-height (* layout-gap-col (dec num-children))
|
||||
|
||||
line-width (if (and col? child-fill?)
|
||||
(- layout-width (* layout-gap (dec num-children)))
|
||||
line-width (if (and row? child-fill?)
|
||||
(- layout-width (* layout-gap-row (dec num-children)))
|
||||
line-width)
|
||||
|
||||
line-height (if (and row? child-fill?)
|
||||
(- layout-height (* layout-gap (dec num-children)))
|
||||
line-height (if (and col? child-fill?)
|
||||
(- layout-height (* layout-gap-col (dec num-children)))
|
||||
line-height)
|
||||
|
||||
start-p
|
||||
(cond-> base-p
|
||||
;; X AXIS
|
||||
(and col? h-center? (not space-around?) (not space-between?))
|
||||
(and row? h-center? (not space-around?) (not space-between?))
|
||||
(-> (gpt/add (xv (/ layout-width 2)))
|
||||
(gpt/subtract (xv (/ (+ line-width children-gap) 2))))
|
||||
(gpt/subtract (xv (/ (+ line-width children-gap-width) 2))))
|
||||
|
||||
(and col? h-end? (not space-around?) (not space-between?))
|
||||
(and row? h-end? (not space-around?) (not space-between?))
|
||||
(-> (gpt/add (xv layout-width))
|
||||
(gpt/subtract (xv (+ line-width children-gap))))
|
||||
(gpt/subtract (xv (+ line-width children-gap-width))))
|
||||
|
||||
(and row? h-center?)
|
||||
(and col? h-center?)
|
||||
(gpt/add (xv (/ line-width 2)))
|
||||
|
||||
(and row? h-end?)
|
||||
(and col? h-end?)
|
||||
(gpt/add (xv line-width))
|
||||
|
||||
;; Y AXIS
|
||||
(and row? v-center? (not space-around?) (not space-between?))
|
||||
(and col? v-center? (not space-around?) (not space-between?))
|
||||
(-> (gpt/add (yv (/ layout-height 2)))
|
||||
(gpt/subtract (yv (/ (+ line-height children-gap) 2))))
|
||||
(gpt/subtract (yv (/ (+ line-height children-gap-height) 2))))
|
||||
|
||||
(and row? v-end? (not space-around?) (not space-between?))
|
||||
(and col? v-end? (not space-around?) (not space-between?))
|
||||
(-> (gpt/add (yv layout-height))
|
||||
(gpt/subtract (yv (+ line-height children-gap))))
|
||||
(gpt/subtract (yv (+ line-height children-gap-height))))
|
||||
|
||||
(and col? v-center?)
|
||||
(and row? v-center?)
|
||||
(gpt/add (yv (/ line-height 2)))
|
||||
|
||||
(and col? v-end?)
|
||||
(and row? v-end?)
|
||||
(gpt/add (yv line-height)))]
|
||||
|
||||
start-p))
|
||||
|
@ -211,11 +254,11 @@
|
|||
[{:keys [line-width line-height]} base-p]
|
||||
|
||||
(cond-> base-p
|
||||
row?
|
||||
(gpt/add (xv (+ line-width layout-gap)))
|
||||
|
||||
col?
|
||||
(gpt/add (yv (+ line-height layout-gap)))))
|
||||
(gpt/add (xv (+ line-width layout-gap-row)))
|
||||
|
||||
row?
|
||||
(gpt/add (yv (+ line-height layout-gap-col)))))
|
||||
|
||||
(add-lines [[total-width total-height] {:keys [line-width line-height]}]
|
||||
[(+ total-width line-width)
|
||||
|
@ -230,24 +273,25 @@
|
|||
|
||||
(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))))
|
||||
total-width (+ total-width (* layout-gap-row (dec (count layout-lines))))
|
||||
total-height (+ total-height (* layout-gap-col (dec (count layout-lines))))
|
||||
|
||||
vertical-fill-space (- layout-height total-height)
|
||||
|
||||
horizontal-fill-space (- layout-width total-width)
|
||||
num-line-fill (count (->> layout-lines (filter :line-fill?)))
|
||||
|
||||
layout-lines
|
||||
(->> layout-lines
|
||||
(mapv #(cond-> %
|
||||
(and col? (:line-fill? %))
|
||||
(and row? (:line-fill? %))
|
||||
(update :line-height + (/ vertical-fill-space num-line-fill))
|
||||
|
||||
(and row? (:line-fill? %))
|
||||
(and col? (:line-fill? %))
|
||||
(update :line-width + (/ horizontal-fill-space num-line-fill)))))
|
||||
|
||||
total-height (if (and col? (> num-line-fill 0)) layout-height total-height)
|
||||
total-width (if (and row? (> num-line-fill 0)) layout-width total-width)
|
||||
total-width (if (and col? (> num-line-fill 0)) layout-width total-width)
|
||||
total-height (if (and row? (> num-line-fill 0)) layout-height total-height)
|
||||
|
||||
base-p (get-base-line total-width total-height)
|
||||
|
||||
|
@ -257,40 +301,54 @@
|
|||
|
||||
(defn calc-layout-line-data
|
||||
"Calculates the baseline for a flex layout"
|
||||
[{:keys [layout-type layout-gap] :as shape}
|
||||
[{:keys [layout-justify-content] :as shape}
|
||||
layout-bounds
|
||||
{:keys [num-children line-width line-height child-fill?] :as line-data}]
|
||||
{:keys [num-children line-width line-height] :as line-data}]
|
||||
|
||||
(let [width (gpo/width-points layout-bounds)
|
||||
height (gpo/height-points layout-bounds)
|
||||
|
||||
layout-gap
|
||||
(cond
|
||||
(or (= :packed layout-type) child-fill?)
|
||||
layout-gap
|
||||
row? (row? shape)
|
||||
col? (col? shape)
|
||||
space-between? (= layout-justify-content :space-between)
|
||||
space-around? (= layout-justify-content :space-around)
|
||||
|
||||
(= :space-around layout-type)
|
||||
0
|
||||
[layout-gap-row layout-gap-col] (gaps shape)
|
||||
|
||||
(and (col? shape) (= :space-between layout-type))
|
||||
(/ (- width line-width) (dec num-children))
|
||||
layout-gap-row
|
||||
(cond (and row? space-around?)
|
||||
0
|
||||
|
||||
(and (row? shape) (= :space-between layout-type))
|
||||
(/ (- height line-height) (dec num-children)))
|
||||
(and row? space-between?)
|
||||
(/ (- width line-width) (dec num-children))
|
||||
|
||||
:else
|
||||
layout-gap-row)
|
||||
|
||||
layout-gap-col
|
||||
(cond (and col? space-around?)
|
||||
0
|
||||
|
||||
(and col? space-between?)
|
||||
(/ (- height line-height) (dec num-children))
|
||||
|
||||
:else
|
||||
layout-gap-col)
|
||||
|
||||
margin-x
|
||||
(if (and (col? shape) (= :space-around layout-type))
|
||||
(if (and row? space-around?)
|
||||
(/ (- width line-width) (inc num-children))
|
||||
0)
|
||||
|
||||
margin-y
|
||||
(if (and (row? shape) (= :space-around layout-type))
|
||||
(if (and col? space-around?)
|
||||
(/ (- height line-height) (inc num-children))
|
||||
0)]
|
||||
|
||||
(assoc line-data
|
||||
:layout-bounds layout-bounds
|
||||
:layout-gap layout-gap
|
||||
:layout-gap-row layout-gap-row
|
||||
:layout-gap-col layout-gap-col
|
||||
:margin-x margin-x
|
||||
:margin-y margin-y)))
|
||||
|
||||
|
@ -298,7 +356,7 @@
|
|||
"Calculates the position for the current shape given the layout-data context"
|
||||
[parent
|
||||
child-width child-height
|
||||
{:keys [start-p layout-gap margin-x margin-y] :as layout-data}]
|
||||
{:keys [start-p layout-gap-row layout-gap-col margin-x margin-y] :as layout-data}]
|
||||
|
||||
(let [row? (row? parent)
|
||||
col? (col? parent)
|
||||
|
@ -314,16 +372,16 @@
|
|||
|
||||
corner-p
|
||||
(cond-> start-p
|
||||
(and row? h-center?)
|
||||
(and col? h-center?)
|
||||
(gpt/add (xv (- (/ child-width 2))))
|
||||
|
||||
(and row? h-end?)
|
||||
(and col? h-end?)
|
||||
(gpt/add (xv (- child-width)))
|
||||
|
||||
(and col? v-center?)
|
||||
(and row? v-center?)
|
||||
(gpt/add (yv (- (/ child-height 2))))
|
||||
|
||||
(and col? v-end?)
|
||||
(and row? v-end?)
|
||||
(gpt/add (yv (- child-height)))
|
||||
|
||||
(some? margin-x)
|
||||
|
@ -334,11 +392,11 @@
|
|||
|
||||
next-p
|
||||
(cond-> start-p
|
||||
col?
|
||||
(gpt/add (xv (+ child-width layout-gap)))
|
||||
|
||||
row?
|
||||
(gpt/add (yv (+ child-height layout-gap)))
|
||||
(gpt/add (xv (+ child-width layout-gap-row)))
|
||||
|
||||
col?
|
||||
(gpt/add (yv (+ child-height layout-gap-col)))
|
||||
|
||||
(some? margin-x)
|
||||
(gpt/add (xv margin-x))
|
||||
|
@ -353,46 +411,48 @@
|
|||
|
||||
(defn calc-fill-width-data
|
||||
"Calculates the size and modifiers for the width of an auto-fill child"
|
||||
[{:keys [layout-gap transform transform-inverse] :as parent}
|
||||
[{:keys [transform transform-inverse] :as parent}
|
||||
{:keys [layout-h-behavior] :as child}
|
||||
child-origin child-width
|
||||
{:keys [num-children line-width line-fill? child-fill? layout-bounds] :as layout-data}]
|
||||
|
||||
(cond
|
||||
(and (col? parent) (= :fill layout-h-behavior) child-fill?)
|
||||
(let [layout-width (gpo/width-points layout-bounds)
|
||||
fill-space (- layout-width line-width (* layout-gap (dec num-children)))
|
||||
fill-width (/ fill-space (:num-child-fill layout-data))
|
||||
fill-scale (/ fill-width child-width)]
|
||||
(let [[layout-gap-row _] (gaps parent)]
|
||||
(cond
|
||||
(and (row? parent) (= :fill layout-h-behavior) child-fill?)
|
||||
(let [layout-width (gpo/width-points layout-bounds)
|
||||
fill-space (- layout-width line-width (* layout-gap-row (dec num-children)))
|
||||
fill-width (/ fill-space (:num-child-fill layout-data))
|
||||
fill-scale (/ fill-width child-width)]
|
||||
|
||||
{:width fill-width
|
||||
:modifiers (ctm/resize (gpt/point fill-scale 1) child-origin transform transform-inverse)})
|
||||
{:width fill-width
|
||||
:modifiers (ctm/resize (gpt/point fill-scale 1) child-origin transform transform-inverse)})
|
||||
|
||||
(and (row? parent) (= :fill layout-h-behavior) line-fill?)
|
||||
(let [fill-scale (/ line-width child-width)]
|
||||
{:width line-width
|
||||
:modifiers (ctm/resize (gpt/point fill-scale 1) child-origin transform transform-inverse)})))
|
||||
(and (col? parent) (= :fill layout-h-behavior) line-fill?)
|
||||
(let [fill-scale (/ line-width child-width)]
|
||||
{:width line-width
|
||||
:modifiers (ctm/resize (gpt/point fill-scale 1) child-origin transform transform-inverse)}))))
|
||||
|
||||
(defn calc-fill-height-data
|
||||
"Calculates the size and modifiers for the height of an auto-fill child"
|
||||
[{:keys [layout-gap transform transform-inverse] :as parent}
|
||||
[{:keys [transform transform-inverse] :as parent}
|
||||
{:keys [layout-v-behavior] :as child}
|
||||
child-origin child-height
|
||||
{:keys [num-children line-height layout-bounds line-fill? child-fill?] :as layout-data}]
|
||||
|
||||
(cond
|
||||
(and (row? parent) (= :fill layout-v-behavior) child-fill?)
|
||||
(let [layout-height (gpo/height-points layout-bounds)
|
||||
fill-space (- layout-height line-height (* layout-gap (dec num-children)))
|
||||
fill-height (/ fill-space (:num-child-fill layout-data))
|
||||
fill-scale (/ fill-height child-height)]
|
||||
{:height fill-height
|
||||
:modifiers (ctm/resize (gpt/point 1 fill-scale) child-origin transform transform-inverse)})
|
||||
(let [[_ layout-gap-col] (gaps parent)]
|
||||
(cond
|
||||
(and (col? parent) (= :fill layout-v-behavior) child-fill?)
|
||||
(let [layout-height (gpo/height-points layout-bounds)
|
||||
fill-space (- layout-height line-height (* layout-gap-col (dec num-children)))
|
||||
fill-height (/ fill-space (:num-child-fill layout-data))
|
||||
fill-scale (/ fill-height child-height)]
|
||||
{:height fill-height
|
||||
:modifiers (ctm/resize (gpt/point 1 fill-scale) child-origin transform transform-inverse)})
|
||||
|
||||
(and (col? parent) (= :fill layout-v-behavior) line-fill?)
|
||||
(let [fill-scale (/ line-height child-height)]
|
||||
{:height line-height
|
||||
:modifiers (ctm/resize (gpt/point 1 fill-scale) child-origin transform transform-inverse)})))
|
||||
(and (row? parent) (= :fill layout-v-behavior) line-fill?)
|
||||
(let [fill-scale (/ line-height child-height)]
|
||||
{:height line-height
|
||||
:modifiers (ctm/resize (gpt/point 1 fill-scale) child-origin transform transform-inverse)}))))
|
||||
|
||||
(defn normalize-child-modifiers
|
||||
"Apply the modifiers and then normalized them against the parent coordinates"
|
||||
|
@ -412,7 +472,7 @@
|
|||
|
||||
(defn calc-layout-data
|
||||
"Digest the layout data to pass it to the constrains"
|
||||
[{:keys [layout-dir layout-padding layout-padding-type] :as parent} children]
|
||||
[{:keys [layout-flex-dir layout-padding layout-padding-type] :as parent} children]
|
||||
|
||||
(let [;; Add padding to the bounds
|
||||
{pad-top :p1 pad-right :p2 pad-bottom :p3 pad-left :p4} layout-padding
|
||||
|
@ -427,7 +487,7 @@
|
|||
layout-bounds (gpo/pad-points points pad-top pad-right pad-bottom pad-left)
|
||||
|
||||
;; Reverse
|
||||
reverse? (or (= :left layout-dir) (= :bottom layout-dir))
|
||||
reverse? (or (= :reverse-row layout-flex-dir) (= :reverse-column layout-flex-dir))
|
||||
children (cond->> children reverse? reverse)
|
||||
|
||||
;; Creates the layout lines information
|
||||
|
@ -476,7 +536,9 @@
|
|||
h-end? (and row? (h-end? frame))
|
||||
v-center? (and col? (v-center? frame))
|
||||
v-end? (and row? (v-end? frame))
|
||||
layout-gap (:layout-gap frame 0)
|
||||
layout-gap-row (or (-> frame :layout-gap :row-gap) 0)
|
||||
;;layout-gap-col (or (-> frame :layout-gap :column-gap) 0)
|
||||
layout-gap layout-gap-row ;; TODO LAYOUT: FIXME
|
||||
reverse? (:reverse? layout-data)
|
||||
|
||||
children (vec (cond->> (d/enumerate children)
|
||||
|
@ -499,31 +561,31 @@
|
|||
box-width (-> child :selrect :width)
|
||||
box-height (-> child :selrect :height)
|
||||
|
||||
x (if row? (:x parent-rect) prev-x)
|
||||
y (if col? (:y parent-rect) prev-y)
|
||||
x (if col? (:x parent-rect) prev-x)
|
||||
y (if row? (:y parent-rect) prev-y)
|
||||
|
||||
width (cond
|
||||
(and col? last?)
|
||||
(and row? last?)
|
||||
(- (+ (:x parent-rect) (:width parent-rect)) x)
|
||||
|
||||
row?
|
||||
col?
|
||||
(:width parent-rect)
|
||||
|
||||
:else
|
||||
(+ box-width (- box-x prev-x) (/ layout-gap 2)))
|
||||
|
||||
height (cond
|
||||
(and row? last?)
|
||||
(and col? last?)
|
||||
(- (+ (:y parent-rect) (:height parent-rect)) y)
|
||||
|
||||
col?
|
||||
row?
|
||||
(:height parent-rect)
|
||||
|
||||
:else
|
||||
(+ box-height (- box-y prev-y) (/ layout-gap 2)))
|
||||
|
||||
[line-area-1 line-area-2]
|
||||
(if col?
|
||||
(if row?
|
||||
(let [half-point-width (+ (- box-x x) (/ box-width 2))]
|
||||
[(-> (gsr/make-rect x y half-point-width height)
|
||||
(assoc :index (if reverse? (inc index) index)))
|
||||
|
@ -555,16 +617,16 @@
|
|||
last? (nil? next)
|
||||
|
||||
line-width
|
||||
(if col?
|
||||
(if row?
|
||||
(:width frame)
|
||||
(+ line-width margin-x
|
||||
(if col? (* layout-gap (dec num-children)) 0)))
|
||||
(if row? (* layout-gap (dec num-children)) 0)))
|
||||
|
||||
line-height
|
||||
(if row?
|
||||
(if col?
|
||||
(:height frame)
|
||||
(+ line-height margin-y
|
||||
(if row?
|
||||
(if col?
|
||||
(* layout-gap (dec num-children))
|
||||
0)))
|
||||
|
||||
|
@ -582,24 +644,24 @@
|
|||
v-end? line-height
|
||||
:else 0))
|
||||
|
||||
x (if col? (:x frame) prev-x)
|
||||
y (if row? (:y frame) prev-y)
|
||||
x (if row? (:x frame) prev-x)
|
||||
y (if col? (:y frame) prev-y)
|
||||
|
||||
width (cond
|
||||
(and row? last?)
|
||||
(and col? last?)
|
||||
(- (+ (:x frame) (:width frame)) x)
|
||||
|
||||
col?
|
||||
row?
|
||||
(:width frame)
|
||||
|
||||
:else
|
||||
(+ line-width (- box-x prev-x) (/ layout-gap 2)))
|
||||
|
||||
height (cond
|
||||
(and col? last?)
|
||||
(and row? last?)
|
||||
(- (+ (:y frame) (:height frame)) y)
|
||||
|
||||
row?
|
||||
col?
|
||||
(:height frame)
|
||||
|
||||
:else
|
|
@ -8,9 +8,10 @@
|
|||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.shapes.constraints :as gct]
|
||||
[app.common.geom.shapes.layout :as gcl]
|
||||
[app.common.geom.shapes.flex-layout :as gcl]
|
||||
[app.common.geom.shapes.pixel-precision :as gpp]
|
||||
[app.common.geom.shapes.transforms :as gtr]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.modifiers :as ctm]
|
||||
[app.common.uuid :as uuid]))
|
||||
|
||||
|
@ -101,7 +102,7 @@
|
|||
|
||||
modif-tree)))))
|
||||
|
||||
(defn get-first-layout
|
||||
(defn get-tree-root
|
||||
[id objects]
|
||||
|
||||
(loop [current id
|
||||
|
@ -127,24 +128,40 @@
|
|||
(recur (:id parent) result)))))
|
||||
|
||||
(defn resolve-tree-sequence
|
||||
;; TODO LAYOUT: Esta ahora puesto al zero pero tiene que mirar todas las raices
|
||||
"Given the ids that have changed search for layout roots to recalculate"
|
||||
[_ids objects]
|
||||
(->> (tree-seq
|
||||
#(d/not-empty? (get-in objects [% :shapes]))
|
||||
#(get-in objects [% :shapes])
|
||||
uuid/zero)
|
||||
[modif-tree objects]
|
||||
|
||||
(map #(get objects %))))
|
||||
(let [redfn
|
||||
(fn [result id]
|
||||
(if (= id uuid/zero)
|
||||
result
|
||||
(let [root (get-tree-root id objects)
|
||||
|
||||
(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]
|
||||
;; Remove the children from the current root
|
||||
result
|
||||
(into #{} (remove #(cph/is-child? objects root %)) result)
|
||||
|
||||
(into (d/ordered-set)
|
||||
(map #(get-first-layout % objects))
|
||||
ids))
|
||||
contains-parent?
|
||||
(some #(cph/is-child? objects % root) result)]
|
||||
|
||||
(cond-> result
|
||||
(not contains-parent?)
|
||||
(conj root)))))
|
||||
|
||||
generate-tree
|
||||
(fn [id]
|
||||
(->> (tree-seq
|
||||
#(d/not-empty? (get-in objects [% :shapes]))
|
||||
#(get-in objects [% :shapes])
|
||||
id)
|
||||
|
||||
(map #(get objects %))))
|
||||
|
||||
roots (->> modif-tree keys (reduce redfn #{}))]
|
||||
|
||||
(concat
|
||||
(when (contains? modif-tree uuid/zero) [(get objects uuid/zero)])
|
||||
(mapcat generate-tree roots))))
|
||||
|
||||
(defn inside-layout?
|
||||
[objects shape]
|
||||
|
@ -170,34 +187,31 @@
|
|||
;; modif-tree))))
|
||||
|
||||
(defn set-objects-modifiers
|
||||
[ids objects get-modifier ignore-constraints snap-pixel?]
|
||||
[modif-tree objects ignore-constraints snap-pixel?]
|
||||
|
||||
(let [set-modifiers
|
||||
(fn [modif-tree id]
|
||||
(let [root? (= uuid/zero id)
|
||||
shape (get objects id)
|
||||
modifiers (cond-> (get-modifier shape)
|
||||
(and (not root?) snap-pixel?)
|
||||
(gpp/set-pixel-precision shape))]
|
||||
(-> modif-tree
|
||||
(assoc id {:modifiers modifiers}))))
|
||||
|
||||
modif-tree (reduce set-modifiers {} ids)
|
||||
shapes-tree (resolve-tree-sequence ids objects)
|
||||
(let [shapes-tree (resolve-tree-sequence modif-tree objects)
|
||||
|
||||
modif-tree
|
||||
(->> shapes-tree
|
||||
(reduce
|
||||
(fn [modif-tree shape]
|
||||
|
||||
(let [root? (= uuid/zero (:id shape))
|
||||
|
||||
modifiers (get-in modif-tree [(:id shape) :modifiers])
|
||||
has-modifiers? (some? modifiers)
|
||||
modifiers (cond-> modifiers
|
||||
(and (not root?) (ctm/has-geometry? modifiers) snap-pixel?)
|
||||
(gpp/set-pixel-precision shape))
|
||||
|
||||
modif-tree (-> modif-tree (assoc-in [(:id shape) :modifiers] modifiers))
|
||||
|
||||
has-modifiers? (ctm/child-modifiers? modifiers)
|
||||
is-layout? (layout? shape)
|
||||
is-parent? (or (group? shape) (and (frame? shape) (not (layout? shape))))
|
||||
|
||||
;; If the current child is inside the layout we ignore the constraints
|
||||
is-inside-layout? (inside-layout? objects shape)]
|
||||
|
||||
|
||||
(cond-> modif-tree
|
||||
(and has-modifiers? is-parent? (not root?))
|
||||
(set-children-modifiers objects shape (or ignore-constraints is-inside-layout?) snap-pixel?)
|
||||
|
@ -207,6 +221,6 @@
|
|||
|
||||
modif-tree))]
|
||||
|
||||
;; #?(:cljs
|
||||
;; (.log js/console ">result" (modif->js modif-tree objects)))
|
||||
;;#?(:cljs
|
||||
;; (.log js/console ">result" (modif->js modif-tree objects)))
|
||||
modif-tree))
|
||||
|
|
|
@ -31,8 +31,10 @@
|
|||
ratio-width (/ target-width curr-width)
|
||||
ratio-height (/ target-height curr-height)
|
||||
scalev (gpt/point ratio-width ratio-height)]
|
||||
(-> modifiers
|
||||
(ctm/set-resize scalev origin transform transform-inverse))))
|
||||
(cond-> modifiers
|
||||
(or (not (mth/almost-zero? (- ratio-width 1)))
|
||||
(not (mth/almost-zero? (- ratio-height 1))))
|
||||
(ctm/set-resize scalev origin transform transform-inverse))))
|
||||
|
||||
(defn position-pixel-precision
|
||||
[modifiers shape]
|
||||
|
@ -41,8 +43,10 @@
|
|||
corner (gpt/point bounds)
|
||||
target-corner (gpt/round corner)
|
||||
deltav (gpt/to-vec corner target-corner)]
|
||||
(-> modifiers
|
||||
(ctm/set-move deltav))))
|
||||
(cond-> modifiers
|
||||
(or (not (mth/almost-zero? (:x deltav)))
|
||||
(not (mth/almost-zero? (:y deltav))))
|
||||
(ctm/set-move deltav))))
|
||||
|
||||
(defn set-pixel-precision
|
||||
"Adjust modifiers so they adjust to the pixel grid"
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
;; - structure-parent: Structure non recursive
|
||||
;; * add-children
|
||||
;; * remove-children
|
||||
;; - structure-child: Structre recursive
|
||||
;; * reflow
|
||||
;; - structure-child: Structure recursive
|
||||
;; * scale-content
|
||||
;;
|
||||
|
||||
|
@ -47,44 +48,48 @@
|
|||
([modifiers vector origin]
|
||||
(-> modifiers
|
||||
(update :geometry conjv {:type :resize
|
||||
:vector vector
|
||||
:origin origin})))
|
||||
:vector vector
|
||||
:origin origin})))
|
||||
|
||||
([modifiers vector origin transform transform-inverse]
|
||||
(-> modifiers
|
||||
(update :geometry conjv {:type :resize
|
||||
:vector vector
|
||||
:origin origin
|
||||
:transform transform
|
||||
:transform-inverse transform-inverse}))))
|
||||
:vector vector
|
||||
:origin origin
|
||||
:transform transform
|
||||
:transform-inverse transform-inverse}))))
|
||||
|
||||
(defn set-rotation
|
||||
[modifiers center angle]
|
||||
(-> modifiers
|
||||
(update :geometry conjv {:type :rotation
|
||||
:center center
|
||||
:rotation angle})))
|
||||
:center center
|
||||
:rotation angle})))
|
||||
|
||||
(defn set-remove-children
|
||||
[modifiers shapes]
|
||||
(-> modifiers
|
||||
(update :structure-parent conjv {:type :remove-children
|
||||
:value shapes}))
|
||||
:value shapes}))
|
||||
)
|
||||
|
||||
(defn set-add-children
|
||||
[modifiers shapes index]
|
||||
(-> modifiers
|
||||
(update :structure-parent conjv {:type :add-children
|
||||
:value shapes
|
||||
:index index})))
|
||||
:value shapes
|
||||
:index index})))
|
||||
|
||||
(defn set-reflow
|
||||
[modifiers]
|
||||
(-> modifiers
|
||||
(update :structure-parent conjv {:type :reflow})))
|
||||
|
||||
(defn set-scale-content
|
||||
[modifiers value]
|
||||
(-> modifiers
|
||||
(update :structure-child conjv {:type :scale-content :value value})))
|
||||
|
||||
|
||||
(defn add-modifiers
|
||||
[modifiers new-modifiers]
|
||||
|
||||
|
@ -124,7 +129,7 @@
|
|||
|
||||
(-> (empty-modifiers)
|
||||
(set-rotation shape-center angle)
|
||||
(set-move (gpt/transform (gpt/point 1 1) rotation)))))
|
||||
(set-move (gpt/transform (gpt/point 0 0) rotation)))))
|
||||
|
||||
(defn remove-children
|
||||
[shapes]
|
||||
|
@ -136,11 +141,21 @@
|
|||
(-> (empty-modifiers)
|
||||
(set-add-children shapes index)))
|
||||
|
||||
(defn reflow
|
||||
[]
|
||||
(-> (empty-modifiers)
|
||||
(set-reflow)))
|
||||
|
||||
(defn scale-content
|
||||
[value]
|
||||
(-> (empty-modifiers)
|
||||
(set-scale-content value)))
|
||||
|
||||
(defn child-modifiers?
|
||||
[{:keys [geometry structure-child]}]
|
||||
(or (d/not-empty? geometry)
|
||||
(d/not-empty? structure-child)))
|
||||
|
||||
(defn select-child-modifiers
|
||||
[modifiers]
|
||||
(select-keys modifiers [:geometry :structure-child]))
|
||||
|
@ -337,3 +352,7 @@
|
|||
(as-> shape $
|
||||
(reduce apply-modifier $ (:structure-parent modifiers))
|
||||
(reduce apply-modifier $ (:structure-child modifiers)))))
|
||||
|
||||
(defn has-geometry?
|
||||
[{:keys [geometry]}]
|
||||
(d/not-empty? geometry))
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.math :as mth :refer [close?]]
|
||||
[app.common.types.modifiers :as ctm]
|
||||
[app.common.types.shape :as cts]
|
||||
[clojure.test :as t]))
|
||||
|
||||
|
@ -59,7 +60,7 @@
|
|||
|
||||
(t/testing "Transform shape with translation modifiers"
|
||||
(t/are [type]
|
||||
(let [modifiers {:displacement (gmt/translate-matrix (gpt/point 10 -10))}]
|
||||
(let [modifiers (ctm/move (gpt/point 10 -10))]
|
||||
(let [shape-before (create-test-shape type {:modifiers modifiers})
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
(t/is (not= shape-before shape-after))
|
||||
|
@ -91,9 +92,7 @@
|
|||
|
||||
(t/testing "Transform shape with resize modifiers"
|
||||
(t/are [type]
|
||||
(let [modifiers {:resize-origin (gpt/point 0 0)
|
||||
:resize-vector (gpt/point 2 2)
|
||||
:resize-transform (gmt/matrix)}
|
||||
(let [modifiers (ctm/resize (gpt/point 2 2) (gpt/point 0 0))
|
||||
shape-before (create-test-shape type {:modifiers modifiers})
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
(t/is (not= shape-before shape-after))
|
||||
|
@ -113,9 +112,7 @@
|
|||
|
||||
(t/testing "Transform with empty resize"
|
||||
(t/are [type]
|
||||
(let [modifiers {:resize-origin (gpt/point 0 0)
|
||||
:resize-vector (gpt/point 1 1)
|
||||
:resize-transform (gmt/matrix)}
|
||||
(let [modifiers (ctm/resize (gpt/point 1 1) (gpt/point 0 0))
|
||||
shape-before (create-test-shape type {:modifiers modifiers})
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
(t/are [prop]
|
||||
|
@ -126,9 +123,7 @@
|
|||
|
||||
(t/testing "Transform with resize=0"
|
||||
(t/are [type]
|
||||
(let [modifiers {:resize-origin (gpt/point 0 0)
|
||||
:resize-vector (gpt/point 0 0)
|
||||
:resize-transform (gmt/matrix)}
|
||||
(let [modifiers (ctm/resize (gpt/point 0 0) (gpt/point 0 0))
|
||||
shape-before (create-test-shape type {:modifiers modifiers})
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
(t/is (> (get-in shape-before [:selrect :width])
|
||||
|
@ -142,13 +137,13 @@
|
|||
|
||||
(t/testing "Transform shape with rotation modifiers"
|
||||
(t/are [type]
|
||||
(let [modifiers {:rotation 30}
|
||||
shape-before (create-test-shape type {:modifiers modifiers})
|
||||
(let [shape-before (create-test-shape type)
|
||||
modifiers (ctm/rotation shape-before (gsh/center-shape shape-before) 30 )
|
||||
shape-before (assoc shape-before :modifiers modifiers)
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
|
||||
(t/is (not= shape-before shape-after))
|
||||
(t/is (not= (:selrect shape-before) (:selrect shape-after)))
|
||||
|
||||
;; Selrect won't change with a rotation, but points will
|
||||
(t/is (close? (get-in shape-before [:selrect :x])
|
||||
(get-in shape-after [:selrect :x])))
|
||||
|
||||
|
@ -166,9 +161,9 @@
|
|||
|
||||
(t/testing "Transform shape with rotation = 0 should leave equal selrect"
|
||||
(t/are [type]
|
||||
(let [modifiers {:rotation 0}
|
||||
shape-before (create-test-shape type {:modifiers modifiers})
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
(let [shape-before (create-test-shape type)
|
||||
modifiers (ctm/rotation shape-before (gsh/center-shape shape-before) 0)
|
||||
shape-after (gsh/transform-shape (assoc shape-before :modifiers modifiers))]
|
||||
(t/are [prop]
|
||||
(t/is (close? (get-in shape-before [:selrect prop])
|
||||
(get-in shape-after [:selrect prop])))
|
||||
|
@ -177,12 +172,13 @@
|
|||
|
||||
(t/testing "Transform shape with invalid selrect fails gracefully"
|
||||
(t/are [type selrect]
|
||||
(let [modifiers {:displacement (gmt/matrix)}
|
||||
(let [modifiers (ctm/move 0 0)
|
||||
shape-before (-> (create-test-shape type {:modifiers modifiers})
|
||||
(assoc :selrect selrect))
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
(= (:selrect shape-before)
|
||||
(:selrect shape-after)))
|
||||
|
||||
(t/is (not= (:selrect shape-before)
|
||||
(:selrect shape-after))))
|
||||
|
||||
:rect {:x 0.0 :y 0.0 :x1 0.0 :y1 0.0 :x2 ##Inf :y2 ##Inf :width ##Inf :height ##Inf}
|
||||
:path {:x 0.0 :y 0.0 :x1 0.0 :y1 0.0 :x2 ##Inf :y2 ##Inf :width ##Inf :height ##Inf}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.modifiers :as ctm]
|
||||
[app.main.data.workspace.changes :as dwc]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.transforms :as dwt]
|
||||
|
@ -25,8 +26,7 @@
|
|||
:layout-wrap-type
|
||||
:layout-padding-type
|
||||
:layout-padding
|
||||
])
|
||||
|
||||
:layout-gap-type])
|
||||
|
||||
(def initial-flex-layout
|
||||
{:layout :flex
|
||||
|
@ -51,8 +51,9 @@
|
|||
(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))
|
||||
(let [modif-tree (dwt/create-modif-tree ids (ctm/reflow))]
|
||||
(rx/of (dwt/set-modifiers modif-tree)
|
||||
(dwt/apply-modifiers)))
|
||||
(rx/empty))))))
|
||||
|
||||
;; TODO LAYOUT: Remove constraints from children
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.geom.shapes.layout :as gsl]
|
||||
[app.common.geom.shapes.flex-layout :as gsl]
|
||||
[app.common.math :as mth]
|
||||
[app.common.pages.changes-builder :as pcb]
|
||||
[app.common.pages.common :as cpc]
|
||||
|
@ -117,46 +117,69 @@
|
|||
|
||||
(declare get-ignore-tree)
|
||||
|
||||
(defn create-modif-tree
|
||||
[ids modifiers]
|
||||
(us/verify (s/coll-of uuid?) ids)
|
||||
(into {} (map #(vector % {:modifiers modifiers})) ids))
|
||||
|
||||
(defn build-modif-tree
|
||||
[ids objects get-modifier]
|
||||
(us/verify (s/coll-of uuid?) ids)
|
||||
(into {} (map #(vector % {:modifiers (get-modifier (get objects %))})) ids))
|
||||
|
||||
(defn build-change-frame-modifiers
|
||||
[modif-tree objects selected target-frame position]
|
||||
|
||||
(let [origin-frame-ids (->> selected (group-by #(get-in objects [% :frame-id])))
|
||||
layout? (get-in objects [target-frame :layout])
|
||||
child-set (set (get-in objects [target-frame :shapes]))
|
||||
drop-index (when layout? (gsl/get-drop-index target-frame objects position))
|
||||
|
||||
update-frame-modifiers
|
||||
(fn [modif-tree [original-frame shapes]]
|
||||
(let [shapes (->> shapes (d/removev #(= target-frame %)))
|
||||
shapes (cond->> shapes
|
||||
(and layout? (= original-frame target-frame))
|
||||
;; When movining inside a layout frame remove the shapes that are not immediate children
|
||||
(filterv #(contains? child-set %)))]
|
||||
(cond-> modif-tree
|
||||
(not= original-frame target-frame)
|
||||
(-> (update-in [original-frame :modifiers] ctm/set-remove-children shapes)
|
||||
(update-in [target-frame :modifiers] ctm/set-add-children shapes drop-index))
|
||||
|
||||
(and layout? (= original-frame target-frame))
|
||||
(update-in [target-frame :modifiers] ctm/set-add-children shapes drop-index))))]
|
||||
|
||||
(reduce update-frame-modifiers modif-tree origin-frame-ids)))
|
||||
|
||||
(defn modif->js
|
||||
[modif-tree objects]
|
||||
(clj->js (into {}
|
||||
(map (fn [[k v]]
|
||||
[(get-in objects [k :name]) v]))
|
||||
modif-tree)))
|
||||
|
||||
(defn set-modifiers
|
||||
([ids]
|
||||
(set-modifiers ids nil false))
|
||||
([modif-tree]
|
||||
(set-modifiers modif-tree false))
|
||||
|
||||
([ids modifiers]
|
||||
(set-modifiers ids modifiers false))
|
||||
([modif-tree ignore-constraints]
|
||||
(set-modifiers modif-tree ignore-constraints false))
|
||||
|
||||
([ids modifiers ignore-constraints]
|
||||
(set-modifiers ids modifiers ignore-constraints false))
|
||||
|
||||
([ids modifiers ignore-constraints ignore-snap-pixel]
|
||||
(us/verify (s/coll-of uuid?) ids)
|
||||
([modif-tree ignore-constraints ignore-snap-pixel]
|
||||
(ptk/reify ::set-modifiers
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
ids (into #{} (remove #(get-in objects [% :blocked] false)) ids)
|
||||
(let [objects
|
||||
(wsh/lookup-page-objects state)
|
||||
|
||||
snap-pixel? (and (not ignore-snap-pixel)
|
||||
(contains? (:workspace-layout state) :snap-pixel-grid))
|
||||
|
||||
workspace-modifiers (:workspace-modifiers state)
|
||||
snap-pixel?
|
||||
(and (not ignore-snap-pixel) (contains? (:workspace-layout state) :snap-pixel-grid))
|
||||
|
||||
modif-tree
|
||||
(gsh/set-objects-modifiers
|
||||
;; TODO LAYOUT: I don't like this
|
||||
(concat (keys workspace-modifiers) ids)
|
||||
objects
|
||||
(fn [shape]
|
||||
(let [
|
||||
modifiers (if (contains? ids (:id shape)) modifiers (ctm/empty-modifiers))
|
||||
(gsh/set-objects-modifiers modif-tree objects ignore-constraints snap-pixel?)]
|
||||
|
||||
structure-modifiers (ctm/select-structure
|
||||
(get-in state [:workspace-modifiers (:id shape) :modifiers]))]
|
||||
(cond-> modifiers
|
||||
(some? structure-modifiers)
|
||||
(ctm/add-modifiers structure-modifiers))))
|
||||
ignore-constraints snap-pixel?)]
|
||||
|
||||
(update state :workspace-modifiers merge modif-tree))))))
|
||||
(assoc state :workspace-modifiers modif-tree))))))
|
||||
|
||||
;; Rotation use different algorithm to calculate children modifiers (and do not use child constraints).
|
||||
(defn- set-rotation-modifiers
|
||||
|
@ -171,8 +194,6 @@
|
|||
ids
|
||||
(->> shapes
|
||||
(remove #(get % :blocked false))
|
||||
#_(mapcat #(cph/get-children objects (:id %)))
|
||||
#_(concat shapes)
|
||||
(filter #((cpc/editable-attrs (:type %)) :rotation))
|
||||
(map :id))
|
||||
|
||||
|
@ -181,9 +202,10 @@
|
|||
(ctm/rotation shape center angle))
|
||||
|
||||
modif-tree
|
||||
(gsh/set-objects-modifiers ids objects get-modifier false false)]
|
||||
(-> (build-modif-tree ids objects get-modifier)
|
||||
(gsh/set-objects-modifiers objects false false))]
|
||||
|
||||
(update state :workspace-modifiers merge modif-tree))))))
|
||||
(assoc state :workspace-modifiers modif-tree))))))
|
||||
|
||||
(defn- update-grow-type
|
||||
[shape old-shape]
|
||||
|
@ -408,9 +430,11 @@
|
|||
(ctm/set-resize scalev resize-origin shape-transform shape-transform-inverse)
|
||||
|
||||
(cond-> scale-text
|
||||
(ctm/set-scale-content (:x scalev))))]
|
||||
(ctm/set-scale-content (:x scalev))))
|
||||
|
||||
(rx/of (set-modifiers ids modifiers))))
|
||||
modif-tree (create-modif-tree ids modifiers)]
|
||||
|
||||
(rx/of (set-modifiers modif-tree))))
|
||||
|
||||
;; Unifies the instantaneous proportion lock modifier
|
||||
;; activated by Shift key and the shapes own proportion
|
||||
|
@ -463,7 +487,8 @@
|
|||
(fn [shape] (ctm/change-dimensions shape attr value))
|
||||
|
||||
modif-tree
|
||||
(gsh/set-objects-modifiers ids objects get-modifier false snap-pixel?)]
|
||||
(-> (build-modif-tree ids objects get-modifier)
|
||||
(gsh/set-objects-modifiers objects false snap-pixel?))]
|
||||
|
||||
(assoc state :workspace-modifiers modif-tree)))
|
||||
|
||||
|
@ -487,7 +512,8 @@
|
|||
(fn [shape] (ctm/change-orientation-modifiers shape orientation))
|
||||
|
||||
modif-tree
|
||||
(gsh/set-objects-modifiers ids objects get-modifier false snap-pixel?)]
|
||||
(-> (build-modif-tree ids objects get-modifier)
|
||||
(gsh/set-objects-modifiers objects false snap-pixel?))]
|
||||
|
||||
(assoc state :workspace-modifiers modif-tree)))
|
||||
|
||||
|
@ -621,37 +647,6 @@
|
|||
(rx/take 1)
|
||||
(rx/map #(start-move from-position))))))
|
||||
|
||||
(defn set-change-frame-modifiers
|
||||
[selected target-frame position]
|
||||
|
||||
(ptk/reify ::set-change-frame-modifiers
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
|
||||
origin-frame-ids (->> selected (group-by #(get-in objects [% :frame-id])))
|
||||
|
||||
layout? (get-in objects [target-frame :layout])
|
||||
|
||||
drop-index
|
||||
(when layout? (gsl/get-drop-index target-frame objects position))
|
||||
|
||||
modif-tree
|
||||
(into {}
|
||||
(mapcat
|
||||
(fn [original-frame]
|
||||
(let [shapes (->> (get origin-frame-ids original-frame)
|
||||
(d/removev #(= target-frame %)))]
|
||||
(cond
|
||||
(not= original-frame target-frame)
|
||||
[[original-frame {:modifiers (ctm/remove-children shapes)}]
|
||||
[target-frame {:modifiers (ctm/add-children shapes drop-index)}]]
|
||||
|
||||
layout?
|
||||
[[target-frame {:modifiers (ctm/add-children shapes drop-index)}]]))))
|
||||
(keys origin-frame-ids))]
|
||||
|
||||
(assoc state :workspace-modifiers modif-tree)))))
|
||||
|
||||
(defn- start-move
|
||||
([from-position] (start-move from-position nil))
|
||||
|
@ -699,22 +694,21 @@
|
|||
(rx/of (finish-transform))
|
||||
(rx/concat
|
||||
(rx/merge
|
||||
(->> position
|
||||
(rx/map (fn [delta]
|
||||
(let [position (gpt/add from-position delta)
|
||||
target-frame (ctst/top-nested-frame objects position)]
|
||||
(set-change-frame-modifiers selected target-frame position))))
|
||||
(rx/take-until stopper))
|
||||
|
||||
(->> position
|
||||
;; We ask for the snap position but we continue even if the result is not available
|
||||
(rx/with-latest vector snap-delta)
|
||||
|
||||
;; We try to use the previous snap so we don't have to wait for the result of the new
|
||||
(rx/map snap/correct-snap-point)
|
||||
(rx/map ctm/move)
|
||||
|
||||
(rx/map (partial set-modifiers ids))
|
||||
(rx/map
|
||||
(fn [move-vector]
|
||||
(let [position (gpt/add from-position move-vector)
|
||||
target-frame (ctst/top-nested-frame objects position)]
|
||||
(-> (create-modif-tree ids (ctm/move move-vector))
|
||||
(build-change-frame-modifiers objects selected target-frame position)
|
||||
(set-modifiers)))))
|
||||
|
||||
(rx/take-until stopper)))
|
||||
|
||||
(rx/of (dwu/start-undo-transaction)
|
||||
|
@ -762,8 +756,8 @@
|
|||
(rx/merge
|
||||
(->> move-events
|
||||
(rx/scan #(gpt/add %1 mov-vec) (gpt/point 0 0))
|
||||
(rx/map #(ctm/move %))
|
||||
(rx/map (partial set-modifiers selected))
|
||||
(rx/map #(create-modif-tree selected (ctm/move %)))
|
||||
(rx/map (partial set-modifiers))
|
||||
(rx/take-until stopper))
|
||||
(rx/of (move-selected direction shift?)))
|
||||
|
||||
|
@ -793,11 +787,12 @@
|
|||
cpos (gpt/point (:x bbox) (:y bbox))
|
||||
pos (gpt/point (or (:x position) (:x bbox))
|
||||
(or (:y position) (:y bbox)))
|
||||
delta (gpt/subtract pos cpos)]
|
||||
delta (gpt/subtract pos cpos)
|
||||
|
||||
(rx/of
|
||||
(set-modifiers [id] (ctm/move delta))
|
||||
(apply-modifiers [id]))))))
|
||||
modif-tree (create-modif-tree [id] (ctm/move delta))]
|
||||
|
||||
(rx/of (set-modifiers modif-tree)
|
||||
(apply-modifiers))))))
|
||||
|
||||
(defn- calculate-frame-for-move
|
||||
[ids]
|
||||
|
@ -816,7 +811,11 @@
|
|||
moving-shapes
|
||||
(cond->> shapes
|
||||
(not layout?)
|
||||
(remove #(= (:frame-id %) frame-id)))
|
||||
(remove #(= (:frame-id %) frame-id))
|
||||
|
||||
layout?
|
||||
(remove #(and (= (:frame-id %) frame-id)
|
||||
(not= (:parent-id %) frame-id))))
|
||||
|
||||
drop-index (when layout? (gsl/get-drop-index frame-id objects position))
|
||||
|
||||
|
@ -850,13 +849,15 @@
|
|||
selected (wsh/lookup-selected state {:omit-blocked? true})
|
||||
shapes (map #(get objects %) selected)
|
||||
selrect (gsh/selection-rect shapes)
|
||||
origin (gpt/point (:x selrect) (+ (:y selrect) (/ (:height selrect) 2)))]
|
||||
origin (gpt/point (:x selrect) (+ (:y selrect) (/ (:height selrect) 2)))
|
||||
|
||||
(rx/of (set-modifiers selected
|
||||
(-> (ctm/empty-modifiers)
|
||||
(ctm/set-resize (gpt/point -1.0 1.0) origin)
|
||||
(ctm/move (gpt/point (:width selrect) 0)))
|
||||
true)
|
||||
modif-tree (create-modif-tree
|
||||
selected
|
||||
(-> (ctm/empty-modifiers)
|
||||
(ctm/set-resize (gpt/point -1.0 1.0) origin)
|
||||
(ctm/move (gpt/point (:width selrect) 0))))]
|
||||
|
||||
(rx/of (set-modifiers modif-tree true)
|
||||
(apply-modifiers))))))
|
||||
|
||||
(defn flip-vertical-selected []
|
||||
|
@ -867,11 +868,13 @@
|
|||
selected (wsh/lookup-selected state {:omit-blocked? true})
|
||||
shapes (map #(get objects %) selected)
|
||||
selrect (gsh/selection-rect shapes)
|
||||
origin (gpt/point (+ (:x selrect) (/ (:width selrect) 2)) (:y selrect))]
|
||||
origin (gpt/point (+ (:x selrect) (/ (:width selrect) 2)) (:y selrect))
|
||||
|
||||
(rx/of (set-modifiers selected
|
||||
(-> (ctm/empty-modifiers)
|
||||
(ctm/set-resize (gpt/point 1.0 -1.0) origin)
|
||||
(ctm/move (gpt/point 0 (:height selrect))))
|
||||
true)
|
||||
modif-tree (create-modif-tree
|
||||
selected
|
||||
(-> (ctm/empty-modifiers)
|
||||
(ctm/set-resize (gpt/point 1.0 -1.0) origin)
|
||||
(ctm/move (gpt/point 0 (:height selrect)))))]
|
||||
|
||||
(rx/of (set-modifiers modif-tree true)
|
||||
(apply-modifiers))))))
|
||||
|
|
|
@ -358,7 +358,8 @@
|
|||
"Snaps a position given an old snap to a different position. We use this to provide a temporal
|
||||
snap while the new is being processed."
|
||||
[[position [snap-pos snap-delta]]]
|
||||
(if (some? snap-delta)
|
||||
(if (nil? snap-delta)
|
||||
position
|
||||
(let [dx (if (not= 0 (:x snap-delta))
|
||||
(- (+ (:x snap-pos) (:x snap-delta)) (:x position))
|
||||
0)
|
||||
|
@ -372,6 +373,4 @@
|
|||
dy (if (> (mth/abs dy) snap-accuracy) 0 dy)]
|
||||
(-> position
|
||||
(update :x + dx)
|
||||
(update :y + dy)))
|
||||
|
||||
position))
|
||||
(update :y + dy)))))
|
||||
|
|
|
@ -68,24 +68,21 @@
|
|||
|
||||
[:g.frame-children
|
||||
(for [shape shapes]
|
||||
[:g.ws-shape-wrapper
|
||||
[:g.ws-shape-wrapper {:key (:id shape)}
|
||||
(cond
|
||||
(not (cph/frame-shape? shape))
|
||||
[:& shape-wrapper
|
||||
{:shape shape
|
||||
:key (:id shape)}]
|
||||
{:shape shape}]
|
||||
|
||||
(cph/root-frame? shape)
|
||||
[:& root-frame-wrapper
|
||||
{:shape shape
|
||||
:key (:id shape)
|
||||
:objects (get frame-objects (:id shape))
|
||||
:thumbnail? (not (contains? active-frames (:id shape)))}]
|
||||
|
||||
:else
|
||||
[:& nested-frame-wrapper
|
||||
{:shape shape
|
||||
:key (:id shape)
|
||||
:objects (get frame-objects (:id shape))}])])]]]))
|
||||
|
||||
(mf/defc shape-wrapper
|
||||
|
|
|
@ -84,38 +84,38 @@
|
|||
[:div.layout-behavior.horizontal
|
||||
[:button.behavior-btn.tooltip.tooltip-bottom
|
||||
{:alt "Fix width"
|
||||
:class (dom/classnames :activated (= layout-h-behavior :fix))
|
||||
:class (dom/classnames :active (= layout-h-behavior :fix))
|
||||
:on-click #(on-change-behavior :h :fix)}
|
||||
i/auto-fix-layout]
|
||||
(when fill?
|
||||
[:button.behavior-btn.tooltip.tooltip-bottom
|
||||
{:alt "Width 100%"
|
||||
:class (dom/classnames :activated (= layout-h-behavior :fill))
|
||||
:class (dom/classnames :active (= layout-h-behavior :fill))
|
||||
:on-click #(on-change-behavior :h :fill)}
|
||||
i/auto-fill])
|
||||
(when auto?
|
||||
[:button.behavior-btn.tooltip.tooltip-bottom
|
||||
{:alt "Fit content"
|
||||
:class (dom/classnames :activated (= layout-v-behavior :auto))
|
||||
:class (dom/classnames :active (= layout-v-behavior :auto))
|
||||
:on-click #(on-change-behavior :h :auto)}
|
||||
i/auto-hug])]
|
||||
|
||||
[:div.layout-behavior
|
||||
[:button.behavior-btn.tooltip.tooltip-bottom
|
||||
{:alt "Fix height"
|
||||
:class (dom/classnames :activated (= layout-v-behavior :fix))
|
||||
:class (dom/classnames :active (= layout-v-behavior :fix))
|
||||
:on-click #(on-change-behavior :v :fix)}
|
||||
i/auto-fix-layout]
|
||||
(when fill?
|
||||
[:button.behavior-btn.tooltip.tooltip-bottom
|
||||
{:alt "Height 100%"
|
||||
:class (dom/classnames :activated (= layout-v-behavior :fill))
|
||||
:class (dom/classnames :active (= layout-v-behavior :fill))
|
||||
:on-click #(on-change-behavior :v :fill)}
|
||||
i/auto-fill])
|
||||
(when auto?
|
||||
[:button.behavior-btn.tooltip.tooltip-bottom-left
|
||||
{:alt "Fit content"
|
||||
:class (dom/classnames :activated (= layout-v-behavior :auto))
|
||||
:class (dom/classnames :active (= layout-v-behavior :auto))
|
||||
:on-click #(on-change-behavior :v :auto)}
|
||||
i/auto-hug])]]))
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
[:*
|
||||
[:& layout-container-menu {:type type :ids [(:id shape)] :values layout-container-values}]
|
||||
|
||||
(when (or (:layout shape) is-layout-child?)
|
||||
(when is-layout-child?
|
||||
[:& layout-item-menu
|
||||
{:ids ids
|
||||
:type type
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.geom.shapes.layout :as gsl]
|
||||
[app.common.geom.shapes.flex-layout :as gsl]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue