diff --git a/CHANGES.md b/CHANGES.md index ad8b9f9da..a5e769979 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,7 @@ ### :sparkles: New features - Add an option to hide artboards names on the viewport [Taiga #2034](https://tree.taiga.io/project/penpot/issue/2034). +- Limit pasted object position to container boundaries [Taiga #2449](https://tree.taiga.io/project/penpot/us/2449). - Add new options for zoom widget in workspace and viewer mode [Taiga #896](https://tree.taiga.io/project/penpot/us/896). - Allow decimals on stroke width and positions [Taiga #2035](https://tree.taiga.io/project/penpot/issue/2035). - Ability to ignore background when exporting an artboard [Taiga #1395](https://tree.taiga.io/project/penpot/us/1395). diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 9b2e6c1aa..d11e75f37 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1707,7 +1707,36 @@ (cond (and (selected-frame? state) (not has-frame?)) (let [frame-id (first page-selected) - delta (get page-objects frame-id)] + frame-object (get page-objects frame-id) + + origin-frame-id (:frame-id (first selected-objs)) + origin-frame-object (get page-objects origin-frame-id) + + ;; - The pasted object position must be limited to container boundaries. If the pasted object doesn't fit we try to: + ;; - Align it to the limits on the x and y axis + ;; - Respect the distance of the object to the right and bottom in the original frame + margin-x (if origin-frame-object + (- (:width origin-frame-object) (+ (:x wrapper) (:width wrapper))) + 0) + margin-x (min margin-x (- (:width frame-object) (:width wrapper))) + + margin-y (if origin-frame-object + (- (:height origin-frame-object) (+ (:y wrapper) (:height wrapper))) + 0) + margin-y (min margin-y (- (:height frame-object) (:height wrapper))) + + ;; Pasted objects mustn't exceed the selected frame x limit + paste-x (if (> (+ (:width wrapper) (:x1 wrapper)) (:width frame-object)) + (+ (- (:x frame-object) (:x orig-pos)) (- (:width frame-object) (:width wrapper) margin-x)) + (:x frame-object)) + + ;; Pasted objects mustn't exceed the selected frame y limit + paste-y (if (> (+ (:height wrapper) (:y1 wrapper)) (:height frame-object)) + (+ (- (:y frame-object) (:y orig-pos)) (- (:height frame-object) (:height wrapper) margin-y)) + (:y frame-object)) + + delta (gpt/point paste-x paste-y)] + [frame-id frame-id delta]) (empty? page-selected)