 
 (defn- paste-impl
   [{:keys [selected objects] :as data}]
-  (letfn [(prepare-change [delta id]
+  (letfn [(prepare-changes [state delta]
+            "Prepare objects to paste: generate new id, give them unique names,
+            and move to the position of mouse pointer"
+            (let [page-id (::page-id state)]
+              (loop [existing-objs (get-in state [:workspace-data page-id :objects])
+                     chgs []
+                     id   (first selected)
+                     ids  (rest selected)]
+                (if (nil? id)
+                  chgs
+                  (let [result (prepare-change id existing-objs delta)
+                        result (if (vector? result) result [result])]
+                    (recur
+                     (reduce conj existing-objs (map (fn [item] {(:id item) (:obj item)}) result))
+                     (into chgs result)
+                     (first ids)
+                     (rest ids)))))))
+
+          (prepare-change [id existing-objs delta]
             (let [obj (get objects id)]
               (if (= :frame (:type obj))
-                (prepare-frame-change obj delta)
-                (prepare-shape-change obj delta uuid/zero))))
-
-          (prepare-shape-change [obj delta frame-id]
+                (prepare-frame-change existing-objs obj delta)
+                (prepare-shape-change existing-objs obj delta uuid/zero))))
+
+          (prepare-shape-change [objects obj delta frame-id]
             (let [id (uuid/next)
-                  renamed-obj (assoc obj :id id :frame-id frame-id)
+                  name (impl-generate-unique-name objects (:name obj))
+                  renamed-obj (assoc obj :id id :frame-id frame-id :name name)
                   moved-obj (geom/move renamed-obj delta)]
               {:type :add-obj
                :id id
                :frame-id frame-id
                :obj moved-obj}))
 
-          (prepare-frame-change [obj delta]
+          (prepare-frame-change [objects obj delta]
             (let [frame-id (uuid/next)
+                  frame-name (impl-generate-unique-name objects (:name obj))
                   sch (->> (map #(get objects %) (:shapes obj))
-                           (map #(prepare-shape-change % delta frame-id)))
+                           (map #(prepare-shape-change objects % delta frame-id)))
                   renamed-frame (-> obj
                                     (assoc :id frame-id)
+                                    (assoc :name frame-name)
                                     (assoc :frame-id uuid/zero)
                                     (assoc :shapes (mapv :id sch)))
                   moved-frame (geom/move renamed-frame delta)

;; --- Add shape to Workspace

(defn impl-retrieve-used-names
  "Returns a set of already used names by shapes
  in the current workspace page."
  [state]
  (let [page-id (::page-id state)
        objects (get-in state [:workspace-data page-id :objects])]
    (into #{} (map :name) (vals objects))))

(defn impl-generate-unique-name
  "A unique name generator based on the current workspace page."
  [state basename]
  (let [used (impl-retrieve-used-names state)]
    (loop [counter 1]
      (let [candidate (str basename "-" counter)]
        (if (contains? used candidate)
          (recur (inc counter))
          candidate)))))

(defn impl-assoc-shape
  [state {:keys [id frame-id] :as data}]
  (let [name (impl-generate-unique-name state (:name data))
        shape (assoc data :name name)
        page-id (::page-id state)]
    (-> state

            delta {:x (- (:x mouse-pos) (:x orig-pos))
                   :y (- (:y mouse-pos) (:y orig-pos))}

            rchanges (prepare-changes state delta)
            uchanges (map (fn [ch]
                            {:type :del-obj
                             :id (:id ch)})
