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:
parent
55c27f140a
commit
bf66e12075
4 changed files with 128 additions and 85 deletions
|
@ -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)))))))
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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))]
|
||||
|
||||
|
|
|
@ -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)}))))))
|
||||
|
|
Loading…
Add table
Reference in a new issue