mirror of
https://github.com/penpot/penpot.git
synced 2025-06-01 04:51:37 +02: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)]
|
(let [selected (wsh/lookup-selected state)]
|
||||||
(rx/of (ungroup-shapes selected :change-selection? true))))))
|
(rx/of (ungroup-shapes selected :change-selection? true))))))
|
||||||
|
|
||||||
(def mask-group
|
(defn mask-group
|
||||||
(ptk/reify ::mask-group
|
([]
|
||||||
ptk/WatchEvent
|
(mask-group nil))
|
||||||
(watch [it state _]
|
([ids]
|
||||||
(let [page-id (:current-page-id state)
|
(ptk/reify ::mask-group
|
||||||
objects (wsh/lookup-page-objects state page-id)
|
ptk/WatchEvent
|
||||||
selected (->> (wsh/lookup-selected state)
|
(watch [it state _]
|
||||||
(cfh/clean-loops objects)
|
(let [page-id (:current-page-id state)
|
||||||
(remove #(ctn/has-any-copy-parent? objects (get objects %))))
|
objects (wsh/lookup-page-objects state page-id)
|
||||||
shapes (shapes-for-grouping objects selected)
|
selected (->> (d/nilv ids (wsh/lookup-selected state))
|
||||||
first-shape (first shapes)]
|
(cfh/clean-loops objects)
|
||||||
(when-not (empty? shapes)
|
(remove #(ctn/has-any-copy-parent? objects (get objects %))))
|
||||||
(let [;; If the selected shape is a group, we can use it. If not,
|
shapes (shapes-for-grouping objects selected)
|
||||||
;; create a new group and set it as masked.
|
first-shape (first shapes)]
|
||||||
[group changes]
|
(when-not (empty? shapes)
|
||||||
(if (and (= (count shapes) 1)
|
(let [;; If the selected shape is a group, we can use it. If not,
|
||||||
(= (:type (first shapes)) :group))
|
;; create a new group and set it as masked.
|
||||||
[first-shape (-> (pcb/empty-changes it page-id)
|
[group changes]
|
||||||
(pcb/with-objects objects))]
|
(if (and (= (count shapes) 1)
|
||||||
(prepare-create-group (pcb/empty-changes it) (uuid/next) objects page-id shapes "Mask" true))
|
(= (: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
|
changes (-> changes
|
||||||
(pcb/update-shapes (:shapes group)
|
(pcb/update-shapes (:shapes group)
|
||||||
(fn [shape]
|
(fn [shape]
|
||||||
(assoc shape
|
(assoc shape
|
||||||
:constraints-h :scale
|
:constraints-h :scale
|
||||||
:constraints-v :scale)))
|
:constraints-v :scale)))
|
||||||
(pcb/update-shapes [(:id group)]
|
(pcb/update-shapes [(:id group)]
|
||||||
(fn [group]
|
(fn [group]
|
||||||
(assoc group
|
(assoc group
|
||||||
:masked-group true
|
:masked-group true
|
||||||
:selrect (:selrect first-shape)
|
:selrect (:selrect first-shape)
|
||||||
:points (:points first-shape)
|
:points (:points first-shape)
|
||||||
:transform (:transform first-shape)
|
:transform (:transform first-shape)
|
||||||
:transform-inverse (:transform-inverse first-shape))))
|
:transform-inverse (:transform-inverse first-shape))))
|
||||||
(pcb/resize-parents [(:id group)]))
|
(pcb/resize-parents [(:id group)]))
|
||||||
undo-id (js/Symbol)]
|
undo-id (js/Symbol)]
|
||||||
|
|
||||||
(rx/of (dwu/start-undo-transaction undo-id)
|
(rx/of (dwu/start-undo-transaction undo-id)
|
||||||
(dch/commit-changes changes)
|
(dch/commit-changes changes)
|
||||||
(dws/select-shapes (d/ordered-set (:id group)))
|
(dws/select-shapes (d/ordered-set (:id group)))
|
||||||
(ptk/data-event :layout/update {:ids [(:id group)]})
|
(ptk/data-event :layout/update {:ids [(:id group)]})
|
||||||
(dwu/commit-undo-transaction undo-id))))))))
|
(dwu/commit-undo-transaction undo-id)))))))))
|
||||||
|
|
||||||
(def unmask-group
|
(defn unmask-group
|
||||||
(ptk/reify ::unmask-group
|
([]
|
||||||
ptk/WatchEvent
|
(unmask-group nil))
|
||||||
(watch [it state _]
|
|
||||||
(let [page-id (:current-page-id state)
|
|
||||||
objects (wsh/lookup-page-objects state page-id)
|
|
||||||
|
|
||||||
masked-groups (->> (wsh/lookup-selected state)
|
([ids]
|
||||||
(map #(get objects %))
|
(ptk/reify ::unmask-group
|
||||||
(filter #(or (= :bool (:type %)) (= :group (:type %)))))
|
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]
|
masked-groups (->> (d/nilv ids (wsh/lookup-selected state))
|
||||||
(-> changes
|
(map #(get objects %))
|
||||||
(pcb/update-shapes [(:id mask)]
|
(filter #(or (= :bool (:type %)) (= :group (:type %)))))
|
||||||
(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))))))
|
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")
|
:mask {:tooltip (ds/meta "M")
|
||||||
:command (ds/c-mod "m")
|
:command (ds/c-mod "m")
|
||||||
:subsections [:modify-layers]
|
: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")
|
:unmask {:tooltip (ds/meta-shift "M")
|
||||||
:command (ds/c-mod "shift+m")
|
:command (ds/c-mod "shift+m")
|
||||||
:subsections [:modify-layers]
|
: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")
|
:create-component {:tooltip (ds/meta "K")
|
||||||
:command (ds/c-mod "k")
|
:command (ds/c-mod "k")
|
||||||
|
|
|
@ -244,9 +244,9 @@
|
||||||
is-bool? (and single? has-bool?)
|
is-bool? (and single? has-bool?)
|
||||||
|
|
||||||
do-create-group #(st/emit! dw/group-selected)
|
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-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
|
do-create-artboard-from-selection
|
||||||
#(st/emit! (dwsh/create-artboard-from-selection))]
|
#(st/emit! (dwsh/create-artboard-from-selection))]
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
[app.common.types.shape.radius :as ctsr]
|
[app.common.types.shape.radius :as ctsr]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.data.workspace :as udw]
|
[app.main.data.workspace :as udw]
|
||||||
|
[app.main.data.workspace.groups :as dwg]
|
||||||
[app.main.data.workspace.selection :as dws]
|
[app.main.data.workspace.selection :as dws]
|
||||||
[app.main.data.workspace.shape-layout :as dwsl]
|
[app.main.data.workspace.shape-layout :as dwsl]
|
||||||
[app.main.data.workspace.shapes :as dwsh]
|
[app.main.data.workspace.shapes :as dwsh]
|
||||||
|
@ -27,6 +28,7 @@
|
||||||
[app.plugins.grid :as grid]
|
[app.plugins.grid :as grid]
|
||||||
[app.plugins.utils :as utils :refer [locate-objects locate-shape proxy->shape array-to-js]]
|
[app.plugins.utils :as utils :refer [locate-objects locate-shape proxy->shape array-to-js]]
|
||||||
[app.util.object :as obj]
|
[app.util.object :as obj]
|
||||||
|
[app.util.path.format :as upf]
|
||||||
[app.util.text-editor :as ted]))
|
[app.util.text-editor :as ted]))
|
||||||
|
|
||||||
(declare shape-proxy)
|
(declare shape-proxy)
|
||||||
|
@ -58,30 +60,68 @@
|
||||||
;; Only for frames + groups + booleans
|
;; Only for frames + groups + booleans
|
||||||
(getChildren
|
(getChildren
|
||||||
[_]
|
[_]
|
||||||
(apply array (->> (locate-shape $file $page $id)
|
(let [shape (locate-shape $file $page $id)]
|
||||||
:shapes
|
(if (or (cfh/frame-shape? shape) (cfh/group-shape? shape) (cfh/svg-raw-shape? shape) (cfh/bool-shape? shape))
|
||||||
(map #(shape-proxy $file $page %)))))
|
(apply array (->> (locate-shape $file $page $id)
|
||||||
|
:shapes
|
||||||
|
(map #(shape-proxy $file $page %))))
|
||||||
|
(utils/display-not-valid :getChildren (:type shape)))))
|
||||||
|
|
||||||
(appendChild
|
(appendChild
|
||||||
[_ child]
|
[_ child]
|
||||||
(let [child-id (obj/get child "$id")]
|
(let [shape (locate-shape $file $page $id)]
|
||||||
(st/emit! (udw/relocate-shapes #{child-id} $id 0))))
|
(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
|
(insertChild
|
||||||
[_ index child]
|
[_ index child]
|
||||||
(let [child-id (obj/get child "$id")]
|
(let [shape (locate-shape $file $page $id)]
|
||||||
(st/emit! (udw/relocate-shapes #{child-id} $id index))))
|
(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
|
;; Only for frames
|
||||||
(addFlexLayout
|
(addFlexLayout
|
||||||
[_]
|
[_]
|
||||||
(st/emit! (dwsl/create-layout-from-id $id :flex :from-frame? true :calculate-params? false))
|
(let [shape (locate-shape $file $page $id)]
|
||||||
(grid/grid-layout-proxy $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
|
(addGridLayout
|
||||||
[_]
|
[_]
|
||||||
(st/emit! (dwsl/create-layout-from-id $id :grid :from-frame? true :calculate-params? false))
|
(let [shape (locate-shape $file $page $id)]
|
||||||
(grid/grid-layout-proxy $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!
|
(crc/define-properties!
|
||||||
ShapeProxy
|
ShapeProxy
|
||||||
|
@ -388,11 +428,6 @@
|
||||||
:enumerable false
|
:enumerable false
|
||||||
:get #(.getChildren ^js %)}))
|
: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)
|
(cond-> (cfh/frame-shape? data)
|
||||||
(-> (crc/add-properties!
|
(-> (crc/add-properties!
|
||||||
{:name "grid"
|
{:name "grid"
|
||||||
|
@ -440,10 +475,6 @@
|
||||||
(when (contains? #{:fix :auto} value)
|
(when (contains? #{:fix :auto} value)
|
||||||
(st/emit! (dwsl/update-layout #{id} {:layout-item-v-sizing 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)
|
(cond-> (cfh/text-shape? data)
|
||||||
(crc/add-properties!
|
(crc/add-properties!
|
||||||
{:name "characters"
|
{:name "characters"
|
||||||
|
@ -534,4 +565,9 @@
|
||||||
:set
|
:set
|
||||||
(fn [self value]
|
(fn [self value]
|
||||||
(let [id (obj/get self "$id")]
|
(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
Add a link
Reference in a new issue