mirror of
https://github.com/penpot/penpot.git
synced 2025-05-24 00:06:11 +02:00
Improve unique name generation for shapes in a page.
This commit is contained in:
parent
28d18a07a0
commit
bfce5f8a00
2 changed files with 89 additions and 66 deletions
|
@ -35,17 +35,17 @@
|
||||||
|
|
||||||
;; --- Shapes CRUD
|
;; --- Shapes CRUD
|
||||||
|
|
||||||
(defn add-shape
|
(deftype AddShape [data]
|
||||||
"Create and add shape to the current selected page."
|
|
||||||
[shape]
|
|
||||||
(reify
|
|
||||||
udp/IPageUpdate
|
udp/IPageUpdate
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(let [page (get-in state [:workspace :page])
|
(let [shape (geom/setup-proportions data)
|
||||||
used-names (map #(get-in state [:shapes % :name]) (get-in state [:pages page :shapes]))
|
page (l/focus ul/selected-page state)]
|
||||||
shape (geom/setup-proportions shape)]
|
(impl/assoc-shape-to-page state shape page))))
|
||||||
(impl/assoc-shape-to-page state shape used-names page)))))
|
|
||||||
|
(defn add-shape
|
||||||
|
[data]
|
||||||
|
(AddShape. data))
|
||||||
|
|
||||||
(defn delete-shape
|
(defn delete-shape
|
||||||
"Remove the shape using its id."
|
"Remove the shape using its id."
|
||||||
|
@ -605,18 +605,18 @@
|
||||||
selected (get-in state [:workspace :selected])]
|
selected (get-in state [:workspace :selected])]
|
||||||
(impl/degroup-shapes state selected pid)))))
|
(impl/degroup-shapes state selected pid)))))
|
||||||
|
|
||||||
;; TODO: maybe split in two separate events
|
;; --- Duplicate Selected
|
||||||
(defn duplicate-selected
|
|
||||||
[]
|
(deftype DuplicateSelected []
|
||||||
(reify
|
|
||||||
udp/IPageUpdate
|
udp/IPageUpdate
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(let [pid (get-in state [:workspace :page])
|
(let [selected (get-in state [:workspace :selected])]
|
||||||
selected (get-in state [:workspace :selected])
|
(impl/duplicate-shapes state selected))))
|
||||||
used-names (map #(get-in state [:shapes % :name])
|
|
||||||
(get-in state [:pages pid :shapes]))]
|
(defn duplicate-selected
|
||||||
(impl/duplicate-shapes state selected used-names)))))
|
[]
|
||||||
|
(DuplicateSelected.))
|
||||||
|
|
||||||
(defn delete-selected
|
(defn delete-selected
|
||||||
"Deselect all and remove all selected shapes."
|
"Deselect all and remove all selected shapes."
|
||||||
|
|
|
@ -5,67 +5,89 @@
|
||||||
;; Copyright (c) 2015-2016 Andrey Antukh <niwi@niwi.nz>
|
;; Copyright (c) 2015-2016 Andrey Antukh <niwi@niwi.nz>
|
||||||
|
|
||||||
(ns uxbox.main.data.shapes-impl
|
(ns uxbox.main.data.shapes-impl
|
||||||
(:require [uxbox.util.uuid :as uuid]
|
(:require [lentes.core :as l]
|
||||||
[uxbox.util.data :refer (index-of)]
|
[uxbox.main.geom :as geom]
|
||||||
[uxbox.main.geom :as geom]))
|
[uxbox.main.lenses :as ul]
|
||||||
|
[uxbox.util.uuid :as uuid]
|
||||||
|
[uxbox.util.data :refer (index-of)]))
|
||||||
|
|
||||||
;; --- Shape Creation
|
;; --- Shape Creation
|
||||||
|
|
||||||
(defn generate-uniq-name
|
(defn retrieve-used-names
|
||||||
[used-names new-name counter]
|
"Returns a set of already used names by shapes
|
||||||
(if (nil? counter)
|
in the current page."
|
||||||
(if (some #(= % new-name) used-names)
|
[{:keys [shapes] :as state}]
|
||||||
(generate-uniq-name used-names new-name 1)
|
(let [page (l/focus ul/selected-page state)
|
||||||
new-name)
|
xform (comp (map second)
|
||||||
(if (some #(= % (str new-name "-" counter)) used-names)
|
(filter #(= page (:page %)))
|
||||||
(generate-uniq-name used-names new-name (inc counter))
|
(map :name))]
|
||||||
(str new-name "-" counter))))
|
(into #{} xform shapes)))
|
||||||
|
|
||||||
|
(defn generate-unique-name
|
||||||
|
"A unique name generator based on the previous
|
||||||
|
state of the used names."
|
||||||
|
[state basename]
|
||||||
|
(let [used (retrieve-used-names state)]
|
||||||
|
(loop [counter 1]
|
||||||
|
(let [candidate (str basename "-" counter)]
|
||||||
|
(if (contains? used candidate)
|
||||||
|
(recur (inc counter))
|
||||||
|
candidate)))))
|
||||||
|
|
||||||
(defn assoc-shape-to-page
|
(defn assoc-shape-to-page
|
||||||
[state shape used-names page]
|
[state shape page]
|
||||||
(let [sid (uuid/random)
|
(let [shape-id (uuid/random)
|
||||||
shape (merge shape {:id sid :page page :name (generate-uniq-name used-names (:name shape) nil)})]
|
shape-name (generate-unique-name state (:name shape))
|
||||||
(as-> state $
|
shape (assoc shape
|
||||||
(update-in $ [:pages page :shapes] #(into [] (cons sid %)))
|
:page page
|
||||||
(assoc-in $ [:shapes sid] shape))))
|
:id shape-id
|
||||||
|
:name shape-name)]
|
||||||
|
(-> state
|
||||||
|
(update-in [:pages page :shapes] #(into [] (cons shape-id %)))
|
||||||
|
(assoc-in [:shapes shape-id] shape))))
|
||||||
|
|
||||||
(defn duplicate-shapes'
|
(defn duplicate-shapes'
|
||||||
([state shapes used-names page]
|
([state shapes page]
|
||||||
(duplicate-shapes' state shapes used-names page nil))
|
(duplicate-shapes' state shapes page nil))
|
||||||
([state shapes used-names page group]
|
([state shapes page group]
|
||||||
(letfn [(duplicate-shape [state shape used-names page group]
|
(letfn [(duplicate-shape [state shape page group]
|
||||||
(if (= (:type shape) :group)
|
(if (= (:type shape) :group)
|
||||||
(let [id (uuid/random)
|
(let [id (uuid/random)
|
||||||
items (:items shape)
|
items (:items shape)
|
||||||
shape (assoc shape :id id :page page :items [] :name (generate-uniq-name used-names (str (:name shape) " copy") nil))
|
name (generate-unique-name state (str (:name shape) "-copy"))
|
||||||
|
shape (assoc shape
|
||||||
|
:id id
|
||||||
|
:page page
|
||||||
|
:items []
|
||||||
|
:name name)
|
||||||
state (if (nil? group)
|
state (if (nil? group)
|
||||||
(as-> state $
|
(-> state
|
||||||
(update-in $ [:pages page :shapes] #(into [] (cons id %)))
|
(update-in [:pages page :shapes] #(into [] (cons id %)))
|
||||||
(assoc-in $ [:shapes id] shape))
|
(assoc-in [:shapes id] shape))
|
||||||
(as-> state $
|
(-> state
|
||||||
(update-in $ [:shapes group :items] #(into [] (cons id %)))
|
(update-in [:shapes group :items] #(into [] (cons id %)))
|
||||||
(assoc-in $ [:shapes id] shape)))]
|
(assoc-in [:shapes id] shape)))]
|
||||||
(->> (map #(get-in state [:shapes %]) items)
|
(->> (map #(get-in state [:shapes %]) items)
|
||||||
(reverse)
|
(reverse)
|
||||||
(reduce #(duplicate-shape %1 %2 used-names page id) state)))
|
(reduce #(duplicate-shape %1 %2 page id) state)))
|
||||||
(let [id (uuid/random)
|
(let [id (uuid/random)
|
||||||
|
name (generate-unique-name state (str (:name shape) "-copy"))
|
||||||
shape (-> (dissoc shape :group)
|
shape (-> (dissoc shape :group)
|
||||||
(assoc :id id :page page :name (generate-uniq-name used-names (str (:name shape) " copy") nil))
|
(assoc :id id :page page :name name)
|
||||||
(merge (when group {:group group})))]
|
(merge (when group {:group group})))]
|
||||||
(if (nil? group)
|
(if (nil? group)
|
||||||
(as-> state $
|
(-> state
|
||||||
(update-in $ [:pages page :shapes] #(into [] (cons id %)))
|
(update-in [:pages page :shapes] #(into [] (cons id %)))
|
||||||
(assoc-in $ [:shapes id] shape))
|
(assoc-in [:shapes id] shape))
|
||||||
(as-> state $
|
(-> state
|
||||||
(update-in $ [:shapes group :items] #(into [] (cons id %)))
|
(update-in [:shapes group :items] #(into [] (cons id %)))
|
||||||
(assoc-in $ [:shapes id] shape))))))]
|
(assoc-in [:shapes id] shape))))))]
|
||||||
|
(reduce #(duplicate-shape %1 %2 page group) state shapes))))
|
||||||
(reduce #(duplicate-shape %1 %2 used-names page group) state shapes))))
|
|
||||||
|
|
||||||
(defn duplicate-shapes
|
(defn duplicate-shapes
|
||||||
([state shapes used-names]
|
([state shapes]
|
||||||
(duplicate-shapes state shapes used-names nil))
|
(duplicate-shapes state shapes nil))
|
||||||
([state shapes used-names page]
|
([state shapes page]
|
||||||
(letfn [(all-toplevel? [coll]
|
(letfn [(all-toplevel? [coll]
|
||||||
(every? #(nil? (:group %)) coll))
|
(every? #(nil? (:group %)) coll))
|
||||||
(all-same-group? [coll]
|
(all-same-group? [coll]
|
||||||
|
@ -75,16 +97,16 @@
|
||||||
(cond
|
(cond
|
||||||
(all-toplevel? shapes)
|
(all-toplevel? shapes)
|
||||||
(let [page (or page (:page (first shapes)))]
|
(let [page (or page (:page (first shapes)))]
|
||||||
(duplicate-shapes' state shapes used-names page))
|
(duplicate-shapes' state shapes page))
|
||||||
|
|
||||||
(all-same-group? shapes)
|
(all-same-group? shapes)
|
||||||
(let [page (or page (:page (first shapes)))
|
(let [page (or page (:page (first shapes)))
|
||||||
group (:group (first shapes))]
|
group (:group (first shapes))]
|
||||||
(duplicate-shapes' state shapes used-names page group))
|
(duplicate-shapes' state shapes page group))
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(let [page (or page (:page (first shapes)))]
|
(let [page (or page (:page (first shapes)))]
|
||||||
(duplicate-shapes' state shapes used-names page)))))))
|
(duplicate-shapes' state shapes page)))))))
|
||||||
|
|
||||||
;; --- Delete Shapes
|
;; --- Delete Shapes
|
||||||
|
|
||||||
|
@ -329,8 +351,9 @@
|
||||||
(not= 1 (count distinct-groups)) :multi
|
(not= 1 (count distinct-groups)) :multi
|
||||||
(nil? (first distinct-groups)) :page
|
(nil? (first distinct-groups)) :page
|
||||||
:else (first distinct-groups))
|
:else (first distinct-groups))
|
||||||
|
name (generate-unique-name state "Group")
|
||||||
group {:type :group
|
group {:type :group
|
||||||
:name (generate-uniq-name used-names "Group" nil)
|
:name name
|
||||||
:items (into [] shapes)
|
:items (into [] shapes)
|
||||||
:id sid
|
:id sid
|
||||||
:page page}]
|
:page page}]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue