0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-12 18:18:24 -05:00

Allow masks, booleans, and some path read only

This commit is contained in:
alonso.torres 2024-06-03 16:20:14 +02:00 committed by Andrey Antukh
parent 55c27f140a
commit bf66e12075
4 changed files with 128 additions and 85 deletions

View file

@ -265,69 +265,76 @@
(let [selected (wsh/lookup-selected state)]
(rx/of (ungroup-shapes selected :change-selection? true))))))
(def mask-group
(ptk/reify ::mask-group
ptk/WatchEvent
(watch [it state _]
(let [page-id (:current-page-id state)
objects (wsh/lookup-page-objects state page-id)
selected (->> (wsh/lookup-selected state)
(cfh/clean-loops objects)
(remove #(ctn/has-any-copy-parent? objects (get objects %))))
shapes (shapes-for-grouping objects selected)
first-shape (first shapes)]
(when-not (empty? shapes)
(let [;; If the selected shape is a group, we can use it. If not,
;; create a new group and set it as masked.
[group changes]
(if (and (= (count shapes) 1)
(= (:type (first shapes)) :group))
[first-shape (-> (pcb/empty-changes it page-id)
(pcb/with-objects objects))]
(prepare-create-group (pcb/empty-changes it) (uuid/next) objects page-id shapes "Mask" true))
(defn mask-group
([]
(mask-group nil))
([ids]
(ptk/reify ::mask-group
ptk/WatchEvent
(watch [it state _]
(let [page-id (:current-page-id state)
objects (wsh/lookup-page-objects state page-id)
selected (->> (d/nilv ids (wsh/lookup-selected state))
(cfh/clean-loops objects)
(remove #(ctn/has-any-copy-parent? objects (get objects %))))
shapes (shapes-for-grouping objects selected)
first-shape (first shapes)]
(when-not (empty? shapes)
(let [;; If the selected shape is a group, we can use it. If not,
;; create a new group and set it as masked.
[group changes]
(if (and (= (count shapes) 1)
(= (:type (first shapes)) :group))
[first-shape (-> (pcb/empty-changes it page-id)
(pcb/with-objects objects))]
(prepare-create-group (pcb/empty-changes it) (uuid/next) objects page-id shapes "Mask" true))
changes (-> changes
(pcb/update-shapes (:shapes group)
(fn [shape]
(assoc shape
:constraints-h :scale
:constraints-v :scale)))
(pcb/update-shapes [(:id group)]
(fn [group]
(assoc group
:masked-group true
:selrect (:selrect first-shape)
:points (:points first-shape)
:transform (:transform first-shape)
:transform-inverse (:transform-inverse first-shape))))
(pcb/resize-parents [(:id group)]))
undo-id (js/Symbol)]
changes (-> changes
(pcb/update-shapes (:shapes group)
(fn [shape]
(assoc shape
:constraints-h :scale
:constraints-v :scale)))
(pcb/update-shapes [(:id group)]
(fn [group]
(assoc group
:masked-group true
:selrect (:selrect first-shape)
:points (:points first-shape)
:transform (:transform first-shape)
:transform-inverse (:transform-inverse first-shape))))
(pcb/resize-parents [(:id group)]))
undo-id (js/Symbol)]
(rx/of (dwu/start-undo-transaction undo-id)
(dch/commit-changes changes)
(dws/select-shapes (d/ordered-set (:id group)))
(ptk/data-event :layout/update {:ids [(:id group)]})
(dwu/commit-undo-transaction undo-id))))))))
(rx/of (dwu/start-undo-transaction undo-id)
(dch/commit-changes changes)
(dws/select-shapes (d/ordered-set (:id group)))
(ptk/data-event :layout/update {:ids [(:id group)]})
(dwu/commit-undo-transaction undo-id)))))))))
(def unmask-group
(ptk/reify ::unmask-group
ptk/WatchEvent
(watch [it state _]
(let [page-id (:current-page-id state)
objects (wsh/lookup-page-objects state page-id)
(defn unmask-group
([]
(unmask-group nil))
masked-groups (->> (wsh/lookup-selected state)
(map #(get objects %))
(filter #(or (= :bool (:type %)) (= :group (:type %)))))
([ids]
(ptk/reify ::unmask-group
ptk/WatchEvent
(watch [it state _]
(let [page-id (:current-page-id state)
objects (wsh/lookup-page-objects state page-id)
changes (reduce (fn [changes mask]
(-> changes
(pcb/update-shapes [(:id mask)]
(fn [shape]
(dissoc shape :masked-group)))
(pcb/resize-parents [(:id mask)])))
(-> (pcb/empty-changes it page-id)
(pcb/with-objects objects))
masked-groups)]
masked-groups (->> (d/nilv ids (wsh/lookup-selected state))
(map #(get objects %))
(filter #(or (= :bool (:type %)) (= :group (:type %)))))
(rx/of (dch/commit-changes changes))))))
changes (reduce (fn [changes mask]
(-> changes
(pcb/update-shapes [(:id mask)]
(fn [shape]
(dissoc shape :masked-group)))
(pcb/resize-parents [(:id mask)])))
(-> (pcb/empty-changes it page-id)
(pcb/with-objects objects))
masked-groups)]
(rx/of (dch/commit-changes changes)))))))

View file

@ -129,12 +129,12 @@
:mask {:tooltip (ds/meta "M")
:command (ds/c-mod "m")
:subsections [:modify-layers]
:fn #(emit-when-no-readonly dw/mask-group)}
:fn #(emit-when-no-readonly (dw/mask-group))}
:unmask {:tooltip (ds/meta-shift "M")
:command (ds/c-mod "shift+m")
:subsections [:modify-layers]
:fn #(emit-when-no-readonly dw/unmask-group)}
:fn #(emit-when-no-readonly (dw/unmask-group))}
:create-component {:tooltip (ds/meta "K")
:command (ds/c-mod "k")

View file

@ -244,9 +244,9 @@
is-bool? (and single? has-bool?)
do-create-group #(st/emit! dw/group-selected)
do-mask-group #(st/emit! dw/mask-group)
do-remove-group #(st/emit! dw/ungroup-selected)
do-unmask-group #(st/emit! dw/unmask-group)
do-mask-group #(st/emit! (dw/mask-group))
do-unmask-group #(st/emit! (dw/unmask-group))
do-create-artboard-from-selection
#(st/emit! (dwsh/create-artboard-from-selection))]

View file

@ -18,6 +18,7 @@
[app.common.types.shape.radius :as ctsr]
[app.common.uuid :as uuid]
[app.main.data.workspace :as udw]
[app.main.data.workspace.groups :as dwg]
[app.main.data.workspace.selection :as dws]
[app.main.data.workspace.shape-layout :as dwsl]
[app.main.data.workspace.shapes :as dwsh]
@ -27,6 +28,7 @@
[app.plugins.grid :as grid]
[app.plugins.utils :as utils :refer [locate-objects locate-shape proxy->shape array-to-js]]
[app.util.object :as obj]
[app.util.path.format :as upf]
[app.util.text-editor :as ted]))
(declare shape-proxy)
@ -58,30 +60,68 @@
;; Only for frames + groups + booleans
(getChildren
[_]
(apply array (->> (locate-shape $file $page $id)
:shapes
(map #(shape-proxy $file $page %)))))
(let [shape (locate-shape $file $page $id)]
(if (or (cfh/frame-shape? shape) (cfh/group-shape? shape) (cfh/svg-raw-shape? shape) (cfh/bool-shape? shape))
(apply array (->> (locate-shape $file $page $id)
:shapes
(map #(shape-proxy $file $page %))))
(utils/display-not-valid :getChildren (:type shape)))))
(appendChild
[_ child]
(let [child-id (obj/get child "$id")]
(st/emit! (udw/relocate-shapes #{child-id} $id 0))))
(let [shape (locate-shape $file $page $id)]
(if (or (cfh/frame-shape? shape) (cfh/group-shape? shape) (cfh/svg-raw-shape? shape) (cfh/bool-shape? shape))
(let [child-id (obj/get child "$id")]
(st/emit! (udw/relocate-shapes #{child-id} $id 0)))
(utils/display-not-valid :appendChild (:type shape)))))
(insertChild
[_ index child]
(let [child-id (obj/get child "$id")]
(st/emit! (udw/relocate-shapes #{child-id} $id index))))
(let [shape (locate-shape $file $page $id)]
(if (or (cfh/frame-shape? shape) (cfh/group-shape? shape) (cfh/svg-raw-shape? shape) (cfh/bool-shape? shape))
(let [child-id (obj/get child "$id")]
(st/emit! (udw/relocate-shapes #{child-id} $id index)))
(utils/display-not-valid :insertChild (:type shape)))))
;; Only for frames
(addFlexLayout
[_]
(st/emit! (dwsl/create-layout-from-id $id :flex :from-frame? true :calculate-params? false))
(grid/grid-layout-proxy $file $page $id))
(let [shape (locate-shape $file $page $id)]
(if (cfh/frame-shape? shape)
(do (st/emit! (dwsl/create-layout-from-id $id :flex :from-frame? true :calculate-params? false))
(grid/grid-layout-proxy $file $page $id))
(utils/display-not-valid :addFlexLayout (:type shape)))))
(addGridLayout
[_]
(st/emit! (dwsl/create-layout-from-id $id :grid :from-frame? true :calculate-params? false))
(grid/grid-layout-proxy $file $page $id)))
(let [shape (locate-shape $file $page $id)]
(if (cfh/frame-shape? shape)
(do (st/emit! (dwsl/create-layout-from-id $id :grid :from-frame? true :calculate-params? false))
(grid/grid-layout-proxy $file $page $id))
(utils/display-not-valid :addGridLayout (:type shape)))))
;; Make masks for groups
(makeMask
[_]
(let [shape (locate-shape $file $page $id)]
(if (cfh/group-shape? shape)
(st/emit! (dwg/mask-group #{$id}))
(utils/display-not-valid :makeMask (:type shape)))))
(removeMask
[_]
(let [shape (locate-shape $file $page $id)]
(if (cfh/mask-shape? shape)
(st/emit! (dwg/unmask-group #{$id}))
(utils/display-not-valid :removeMask (:type shape)))))
;; Only for path and bool shapes
(toD
[_]
(let [shape (locate-shape $file $page $id)]
(if (cfh/path-shape? shape)
(upf/format-path (:content shape))
(utils/display-not-valid :makeMask (:type shape))))))
(crc/define-properties!
ShapeProxy
@ -388,11 +428,6 @@
:enumerable false
:get #(.getChildren ^js %)}))
(cond-> (not (or (cfh/frame-shape? data) (cfh/group-shape? data) (cfh/svg-raw-shape? data) (cfh/bool-shape? data)))
(-> (obj/unset! "appendChild")
(obj/unset! "insertChild")
(obj/unset! "getChildren")))
(cond-> (cfh/frame-shape? data)
(-> (crc/add-properties!
{:name "grid"
@ -440,10 +475,6 @@
(when (contains? #{:fix :auto} value)
(st/emit! (dwsl/update-layout #{id} {:layout-item-v-sizing value})))))})))
(cond-> (not (cfh/frame-shape? data))
(-> (obj/unset! "addGridLayout")
(obj/unset! "addFlexLayout")))
(cond-> (cfh/text-shape? data)
(crc/add-properties!
{:name "characters"
@ -534,4 +565,9 @@
:set
(fn [self value]
(let [id (obj/get self "$id")]
(st/emit! (dwt/update-attrs id {:text-transform value}))))}))))))
(st/emit! (dwt/update-attrs id {:text-transform value}))))}))
(cond-> (or (cfh/path-shape? data) (cfh/bool-shape? data))
(crc/add-properties!
{:name "content"
:get #(-> % proxy->shape :content array-to-js)}))))))