0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-04-01 01:21:21 -05:00

Add optimizations to order-by-indexed-shapes fn

This commit is contained in:
Andrey Antukh 2024-04-04 09:53:34 +02:00
parent 26ca36d8c6
commit 29332b67f9

View file

@ -16,6 +16,8 @@
[clojure.set :as set] [clojure.set :as set]
[cuerdas.core :as str])) [cuerdas.core :as str]))
#?(:clj (set! *warn-on-reflection* true))
(declare reduce-objects) (declare reduce-objects)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -327,12 +329,9 @@
"Selects the shape that will be the base to add the shapes over" "Selects the shape that will be the base to add the shapes over"
[objects selected] [objects selected]
(let [;; Gets the tree-index for all the shapes (let [;; Gets the tree-index for all the shapes
indexed-shapes (indexed-shapes objects) indexed-shapes (indexed-shapes objects selected)
;; Filters the selected and retrieve a list of ids ;; Filters the selected and retrieve a list of ids
sorted-ids (->> indexed-shapes sorted-ids (map val indexed-shapes)]
(filter (comp selected second))
(map second))]
;; The first id will be the top-most ;; The first id will be the top-most
(get objects (first sorted-ids)))) (get objects (first sorted-ids))))
@ -486,43 +485,62 @@
(reduce add-element (d/ordered-set) ids))) (reduce add-element (d/ordered-set) ids)))
(defn indexed-shapes (defn- indexed-shapes
"Retrieves a list with the indexes for each element in the layer tree. "Retrieves a vector with the indexes for each element in the layer
This will be used for shift+selection." tree. This will be used for shift+selection."
[objects] [objects selected]
(letfn [(red-fn [cur-idx id] (loop [index 1
(let [[prev-idx _] (first cur-idx) result (transient [])
prev-idx (or prev-idx 0) ;; Flag to start adding elements to the index
cur-idx (conj cur-idx (d/vec2 (inc prev-idx) id))] add? false
(rec-index cur-idx id))) ;; Only add elements while we're in the selection, we finish when the selection is over
(rec-index [cur-idx id] pending (set selected)
(let [object (get objects id)] shapes (-> objects
(reduce red-fn cur-idx (reverse (:shapes object)))))] (get uuid/zero)
(into {} (rec-index '() uuid/zero)))) (get :shapes)
(rseq))]
(let [shape-id (first shapes)]
(if (and (d/not-empty? pending) shape-id)
(let [shape (get objects shape-id)
add? (or add? (contains? selected shape-id))
pending (disj pending shape-id)
result (if add?
(conj! result (d/vec2 index shape-id))
result)]
(if-let [children (get shape :shapes)]
(recur (inc index)
result
add?
pending
(concat (rseq children) (rest shapes)))
(recur (inc index)
result
add?
pending
(rest shapes))))
(persistent! result)))))
(defn expand-region-selection (defn expand-region-selection
"Given a selection selects all the shapes between the first and last in "Given a selection selects all the shapes between the first and last in
an indexed manner (shift selection)" an indexed manner (shift selection)"
[objects selection] [objects selection]
(let [indexed-shapes (indexed-shapes objects) (let [selection (if (set? selection) selection (set selection))
filter-indexes (->> indexed-shapes indexed-shapes (indexed-shapes objects selection)
(filter (comp selection second)) indexes (map key indexed-shapes)
(map first)) from (apply min indexes)
to (apply max indexes)
from (apply min filter-indexes) xform (comp
to (apply max filter-indexes)] (filter (fn [[idx _]] (and (>= idx from) (<= idx to))))
(->> indexed-shapes (map val))]
(filter (fn [[idx _]] (and (>= idx from) (<= idx to)))) (into #{} xform indexed-shapes)))
(map second)
(into #{}))))
(defn order-by-indexed-shapes (defn order-by-indexed-shapes
[objects ids] "Retrieves a ordered vector for each element in the layer tree and
(let [ids (if (set? ids) ids (set ids))] filted by selected set"
(->> (indexed-shapes objects) [objects selected]
(filter (fn [o] (contains? ids (val o)))) (let [selected (if (set? selected) selected (set selected))]
(sort-by key) (sequence (map val) (indexed-shapes objects selected))))
(map val))))
(defn get-index-replacement (defn get-index-replacement
"Given a collection of shapes, calculate their positions "Given a collection of shapes, calculate their positions