mirror of
https://github.com/penpot/penpot.git
synced 2025-01-26 00:19:07 -05:00
✨ Move frames with guides move the guides
This commit is contained in:
parent
3f89baa1fe
commit
62f7323acf
5 changed files with 122 additions and 105 deletions
|
@ -6,7 +6,10 @@
|
||||||
|
|
||||||
(ns app.main.data.workspace.guides
|
(ns app.main.data.workspace.guides
|
||||||
(:require
|
(:require
|
||||||
|
[app.common.geom.point :as gpt]
|
||||||
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
|
[app.common.types.page-options :as tpo]
|
||||||
[app.main.data.workspace.changes :as dwc]
|
[app.main.data.workspace.changes :as dwc]
|
||||||
[app.main.data.workspace.state-helpers :as wsh]
|
[app.main.data.workspace.state-helpers :as wsh]
|
||||||
[beicon.core :as rx]
|
[beicon.core :as rx]
|
||||||
|
@ -20,7 +23,7 @@
|
||||||
(merge guide))))
|
(merge guide))))
|
||||||
|
|
||||||
(defn update-guides [guide]
|
(defn update-guides [guide]
|
||||||
;; TODO CHECK SPEC
|
(us/verify ::tpo/guide guide)
|
||||||
(ptk/reify ::update-guides
|
(ptk/reify ::update-guides
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [it state _]
|
(watch [it state _]
|
||||||
|
@ -44,7 +47,7 @@
|
||||||
:origin it}))))))
|
:origin it}))))))
|
||||||
|
|
||||||
(defn remove-guide [guide]
|
(defn remove-guide [guide]
|
||||||
;; TODO CHECK SPEC
|
(us/verify ::tpo/guide guide)
|
||||||
(ptk/reify ::remove-guide
|
(ptk/reify ::remove-guide
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [it state _]
|
(watch [it state _]
|
||||||
|
@ -75,26 +78,24 @@
|
||||||
|
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [objects (wsh/lookup-page-objects state)
|
(let [objects (wsh/lookup-page-objects state)
|
||||||
frame-ids (->> ids (filter #(= :frame (get-in objects [% :type]))) (into #{}))
|
frame-ids? (->> ids (filter #(= :frame (get-in objects [% :type]))) (into #{}))
|
||||||
object-modifiers (get state :workspace-modifiers)
|
object-modifiers (get state :workspace-modifiers)
|
||||||
|
|
||||||
moved-guide?
|
|
||||||
(fn [guide]
|
|
||||||
(let [frame-id (:frame-id guide)]
|
|
||||||
(and (contains? frame-ids frame-id)
|
|
||||||
(some? (get-in object-modifiers [frame-id :modifiers :displacement])))))
|
|
||||||
|
|
||||||
build-move-event
|
build-move-event
|
||||||
(fn [guide]
|
(fn [guide]
|
||||||
(let [disp (get-in object-modifiers [(:frame-id guide) :modifiers :displacement])
|
(let [frame (get objects (:frame-id guide))
|
||||||
guide (if (= :x (:axis guide))
|
frame' (-> (merge frame (get object-modifiers (:frame-id guide)))
|
||||||
(update guide :position + (:e disp))
|
(gsh/transform-shape))
|
||||||
(update guide :position + (:f disp)))]
|
|
||||||
|
moved (gpt/to-vec (gpt/point (:x frame) (:y frame))
|
||||||
|
(gpt/point (:x frame') (:y frame')))
|
||||||
|
|
||||||
|
guide (update guide :position + (get moved (:axis guide)))]
|
||||||
(update-guides guide)))]
|
(update-guides guide)))]
|
||||||
|
|
||||||
(->> (wsh/lookup-page-options state)
|
(->> (wsh/lookup-page-options state)
|
||||||
:guides
|
:guides
|
||||||
(vals)
|
(vals)
|
||||||
(filter moved-guide?)
|
(filter (comp frame-ids? :frame-id))
|
||||||
(map build-move-event)
|
(map build-move-event)
|
||||||
(rx/from))))))
|
(rx/from))))))
|
||||||
|
|
|
@ -171,6 +171,7 @@
|
||||||
ignore-tree (get-ignore-tree object-modifiers objects ids)]
|
ignore-tree (get-ignore-tree object-modifiers objects ids)]
|
||||||
|
|
||||||
(rx/of (dwu/start-undo-transaction)
|
(rx/of (dwu/start-undo-transaction)
|
||||||
|
(dwg/move-frame-guides ids-with-children)
|
||||||
(dch/update-shapes
|
(dch/update-shapes
|
||||||
ids-with-children
|
ids-with-children
|
||||||
(fn [shape]
|
(fn [shape]
|
||||||
|
@ -189,7 +190,6 @@
|
||||||
:rotation
|
:rotation
|
||||||
:flip-x
|
:flip-x
|
||||||
:flip-y]})
|
:flip-y]})
|
||||||
(dwg/move-frame-guides ids-with-children)
|
|
||||||
(clear-local-transform)
|
(clear-local-transform)
|
||||||
(dwu/commit-undo-transaction))))))
|
(dwu/commit-undo-transaction))))))
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,7 @@
|
||||||
(mf/defc export-guides
|
(mf/defc export-guides
|
||||||
[{:keys [guides]}]
|
[{:keys [guides]}]
|
||||||
[:> "penpot:guides" #js {}
|
[:> "penpot:guides" #js {}
|
||||||
(for [{:keys [id position frame-id axis]} (vals guides)]
|
(for [{:keys [position frame-id axis]} (vals guides)]
|
||||||
[:> "penpot:guide" #js {:position position
|
[:> "penpot:guide" #js {:position position
|
||||||
:frame-id frame-id
|
:frame-id frame-id
|
||||||
:axis (d/name axis)}])])
|
:axis (d/name axis)}])])
|
||||||
|
|
|
@ -370,5 +370,6 @@
|
||||||
{:zoom zoom
|
{:zoom zoom
|
||||||
:vbox vbox
|
:vbox vbox
|
||||||
:hover-frame frame-parent
|
:hover-frame frame-parent
|
||||||
|
:modifiers modifiers
|
||||||
:disabled-guides? disabled-guides?}]])]]]))
|
:disabled-guides? disabled-guides?}]])]]]))
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
(ns app.main.ui.workspace.viewport.guides
|
(ns app.main.ui.workspace.viewport.guides
|
||||||
(:require
|
(:require
|
||||||
[app.common.colors :as colors]
|
[app.common.colors :as colors]
|
||||||
|
[app.common.geom.point :as gpt]
|
||||||
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.math :as mth]
|
[app.common.math :as mth]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
|
@ -137,11 +139,7 @@
|
||||||
{:x (+ (:x vbox) rules-pos)
|
{:x (+ (:x vbox) rules-pos)
|
||||||
:y (- pos (/ guide-active-area 2))
|
:y (- pos (/ guide-active-area 2))
|
||||||
:width (:width vbox)
|
:width (:width vbox)
|
||||||
:height guide-active-area}
|
:height guide-active-area})))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
)))
|
|
||||||
|
|
||||||
(defn guide-line-axis
|
(defn guide-line-axis
|
||||||
([pos vbox axis]
|
([pos vbox axis]
|
||||||
|
@ -232,9 +230,19 @@
|
||||||
:width (:width vbox)
|
:width (:width vbox)
|
||||||
:height (/ 24 zoom)}))
|
:height (/ 24 zoom)}))
|
||||||
|
|
||||||
|
(defn is-guide-inside-frame?
|
||||||
|
[guide frame]
|
||||||
|
|
||||||
|
(if (= :x (:axis guide))
|
||||||
|
(and (>= (:position guide) (:x frame) )
|
||||||
|
(<= (:position guide) (+ (:x frame) (:width frame)) ))
|
||||||
|
|
||||||
|
(and (>= (:position guide) (:y frame) )
|
||||||
|
(<= (:position guide) (+ (:y frame) (:height frame)) ))))
|
||||||
|
|
||||||
(mf/defc guide
|
(mf/defc guide
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/wrap [mf/memo]}
|
||||||
[{:keys [guide hover? on-guide-change get-hover-frame vbox zoom hover-frame disabled-guides?]}]
|
[{:keys [guide hover? on-guide-change get-hover-frame vbox zoom hover-frame disabled-guides? frame-modifier]}]
|
||||||
|
|
||||||
(let [axis (:axis guide)
|
(let [axis (:axis guide)
|
||||||
|
|
||||||
|
@ -254,96 +262,102 @@
|
||||||
state
|
state
|
||||||
frame]} (use-guide handle-change-position get-hover-frame zoom guide)
|
frame]} (use-guide handle-change-position get-hover-frame zoom guide)
|
||||||
|
|
||||||
frame (or frame hover-frame)
|
base-frame (or frame hover-frame)
|
||||||
pos (or (:new-position @state) (:position guide))
|
frame (gsh/transform-shape (merge base-frame frame-modifier))
|
||||||
|
|
||||||
|
move-vec (gpt/to-vec (gpt/point (:x base-frame) (:y base-frame))
|
||||||
|
(gpt/point (:x frame) (:y frame)))
|
||||||
|
|
||||||
|
pos (+ (or (:new-position @state) (:position guide)) (get move-vec axis))
|
||||||
guide-width (/ guide-width zoom)
|
guide-width (/ guide-width zoom)
|
||||||
guide-pill-corner-radius (/ guide-pill-corner-radius zoom)]
|
guide-pill-corner-radius (/ guide-pill-corner-radius zoom)]
|
||||||
|
|
||||||
[:g.guide-area {:data-guide-frame-id (when (some? frame) (str (:id frame)))}
|
(when (or (nil? frame) (is-guide-inside-frame? (assoc guide :position pos) frame))
|
||||||
(when-not disabled-guides?
|
[:g.guide-area {:data-guide-frame-id (when (some? frame) (str (:id frame)))}
|
||||||
(let [{:keys [x y width height]} (guide-area-axis pos vbox zoom frame axis)]
|
(when-not disabled-guides?
|
||||||
[:rect {:x x
|
(let [{:keys [x y width height]} (guide-area-axis pos vbox zoom frame axis)]
|
||||||
:y y
|
[:rect {:x x
|
||||||
:width width
|
:y y
|
||||||
:height height
|
:width width
|
||||||
:style {:fill "none"
|
:height height
|
||||||
:pointer-events "fill"
|
:style {:fill "none"
|
||||||
:cursor (if (= axis :x) "ew-resize" "ns-resize")}
|
:pointer-events "fill"
|
||||||
:on-pointer-enter on-pointer-enter
|
:cursor (if (= axis :x) "ew-resize" "ns-resize")}
|
||||||
:on-pointer-leave on-pointer-leave
|
:on-pointer-enter on-pointer-enter
|
||||||
:on-pointer-down on-pointer-down
|
:on-pointer-leave on-pointer-leave
|
||||||
:on-pointer-up on-pointer-up
|
:on-pointer-down on-pointer-down
|
||||||
:on-lost-pointer-capture on-lost-pointer-capture
|
:on-pointer-up on-pointer-up
|
||||||
:on-mouse-move on-mouse-move}]))
|
:on-lost-pointer-capture on-lost-pointer-capture
|
||||||
|
:on-mouse-move on-mouse-move}]))
|
||||||
|
|
||||||
(if (some? frame)
|
(if (some? frame)
|
||||||
(let [{:keys [l1-x1 l1-y1 l1-x2 l1-y2
|
(let [{:keys [l1-x1 l1-y1 l1-x2 l1-y2
|
||||||
l2-x1 l2-y1 l2-x2 l2-y2
|
l2-x1 l2-y1 l2-x2 l2-y2
|
||||||
l3-x1 l3-y1 l3-x2 l3-y2]}
|
l3-x1 l3-y1 l3-x2 l3-y2]}
|
||||||
(guide-line-axis pos vbox frame axis)]
|
(guide-line-axis pos vbox frame axis)]
|
||||||
[:g
|
[:g
|
||||||
(when (or hover? (:hover @state))
|
(when (or hover? (:hover @state))
|
||||||
[:line {:x1 l1-x1
|
[:line {:x1 l1-x1
|
||||||
:y1 l1-y1
|
:y1 l1-y1
|
||||||
:x2 l1-x2
|
:x2 l1-x2
|
||||||
:y2 l1-y2
|
:y2 l1-y2
|
||||||
|
:style {:stroke guide-color
|
||||||
|
:stroke-opacity guide-opacity-hover
|
||||||
|
:stroke-dasharray (str "0, " (/ 6 zoom))
|
||||||
|
:stroke-linecap "round"
|
||||||
|
:stroke-width guide-width}}])
|
||||||
|
[:line {:x1 l2-x1
|
||||||
|
:y1 l2-y1
|
||||||
|
:x2 l2-x2
|
||||||
|
:y2 l2-y2
|
||||||
:style {:stroke guide-color
|
:style {:stroke guide-color
|
||||||
:stroke-opacity guide-opacity-hover
|
|
||||||
:stroke-dasharray (str "0, " (/ 6 zoom))
|
|
||||||
:stroke-linecap "round"
|
|
||||||
:stroke-width guide-width}}])
|
|
||||||
[:line {:x1 l2-x1
|
|
||||||
:y1 l2-y1
|
|
||||||
:x2 l2-x2
|
|
||||||
:y2 l2-y2
|
|
||||||
:style {:stroke guide-color
|
|
||||||
:stroke-width guide-width
|
|
||||||
:stroke-opacity (if (or hover? (:hover @state))
|
|
||||||
guide-opacity-hover
|
|
||||||
guide-opacity)}}]
|
|
||||||
(when (or hover? (:hover @state))
|
|
||||||
[:line {:x1 l3-x1
|
|
||||||
:y1 l3-y1
|
|
||||||
:x2 l3-x2
|
|
||||||
:y2 l3-y2
|
|
||||||
:style {:stroke guide-color
|
|
||||||
:stroke-opacity guide-opacity-hover
|
|
||||||
:stroke-width guide-width
|
:stroke-width guide-width
|
||||||
:stroke-dasharray (str "0, " (/ 6 zoom))
|
:stroke-opacity (if (or hover? (:hover @state))
|
||||||
:stroke-linecap "round"}}])])
|
guide-opacity-hover
|
||||||
|
guide-opacity)}}]
|
||||||
|
(when (or hover? (:hover @state))
|
||||||
|
[:line {:x1 l3-x1
|
||||||
|
:y1 l3-y1
|
||||||
|
:x2 l3-x2
|
||||||
|
:y2 l3-y2
|
||||||
|
:style {:stroke guide-color
|
||||||
|
:stroke-opacity guide-opacity-hover
|
||||||
|
:stroke-width guide-width
|
||||||
|
:stroke-dasharray (str "0, " (/ 6 zoom))
|
||||||
|
:stroke-linecap "round"}}])])
|
||||||
|
|
||||||
(let [{:keys [x1 y1 x2 y2]} (guide-line-axis pos vbox axis)]
|
(let [{:keys [x1 y1 x2 y2]} (guide-line-axis pos vbox axis)]
|
||||||
[:line {:x1 x1
|
[:line {:x1 x1
|
||||||
:y1 y1
|
:y1 y1
|
||||||
:x2 x2
|
:x2 x2
|
||||||
:y2 y2
|
:y2 y2
|
||||||
:style {:stroke guide-color
|
:style {:stroke guide-color
|
||||||
:stroke-width guide-width
|
:stroke-width guide-width
|
||||||
:stroke-opacity (if (or hover? (:hover @state))
|
:stroke-opacity (if (or hover? (:hover @state))
|
||||||
guide-opacity-hover
|
guide-opacity-hover
|
||||||
guide-opacity)}}]))
|
guide-opacity)}}]))
|
||||||
|
|
||||||
(when (or hover? (:hover @state))
|
(when (or hover? (:hover @state))
|
||||||
(let [{:keys [rect-x rect-y rect-width rect-height text-x text-y]}
|
(let [{:keys [rect-x rect-y rect-width rect-height text-x text-y]}
|
||||||
(guide-pill-axis pos vbox zoom axis)]
|
(guide-pill-axis pos vbox zoom axis)]
|
||||||
[:g.guide-pill
|
[:g.guide-pill
|
||||||
[:rect {:x rect-x
|
[:rect {:x rect-x
|
||||||
:y rect-y
|
:y rect-y
|
||||||
:width rect-width
|
:width rect-width
|
||||||
:height rect-height
|
:height rect-height
|
||||||
:rx guide-pill-corner-radius
|
:rx guide-pill-corner-radius
|
||||||
:ry guide-pill-corner-radius
|
:ry guide-pill-corner-radius
|
||||||
:style {:fill guide-color}}]
|
:style {:fill guide-color}}]
|
||||||
|
|
||||||
[:text {:x text-x
|
[:text {:x text-x
|
||||||
:y text-y
|
:y text-y
|
||||||
:text-anchor "middle"
|
:text-anchor "middle"
|
||||||
:dominant-baseline "middle"
|
:dominant-baseline "middle"
|
||||||
:transform (when (= axis :y) (str "rotate(-90 " text-x "," text-y ")"))
|
:transform (when (= axis :y) (str "rotate(-90 " text-x "," text-y ")"))
|
||||||
:style {:font-size (/ 13 zoom)
|
:style {:font-size (/ 13 zoom)
|
||||||
:font-family "sourcesanspro"
|
:font-family "sourcesanspro"
|
||||||
:fill colors/black}}
|
:fill colors/black}}
|
||||||
(str (mth/round pos))]]))]))
|
(str (mth/round pos))]]))])))
|
||||||
|
|
||||||
(mf/defc new-guide-area
|
(mf/defc new-guide-area
|
||||||
[{:keys [vbox zoom axis get-hover-frame disabled-guides?]}]
|
[{:keys [vbox zoom axis get-hover-frame disabled-guides?]}]
|
||||||
|
@ -395,7 +409,7 @@
|
||||||
|
|
||||||
(mf/defc viewport-guides
|
(mf/defc viewport-guides
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/wrap [mf/memo]}
|
||||||
[{:keys [zoom vbox hover-frame disabled-guides?]}]
|
[{:keys [zoom vbox hover-frame disabled-guides? modifiers]}]
|
||||||
|
|
||||||
(let [page (mf/deref refs/workspace-page)
|
(let [page (mf/deref refs/workspace-page)
|
||||||
|
|
||||||
|
@ -445,6 +459,7 @@
|
||||||
:guide current
|
:guide current
|
||||||
:vbox vbox
|
:vbox vbox
|
||||||
:zoom zoom
|
:zoom zoom
|
||||||
|
:frame-modifier (get modifiers (:frame-id current))
|
||||||
:get-hover-frame get-hover-frame
|
:get-hover-frame get-hover-frame
|
||||||
:on-guide-change on-guide-change
|
:on-guide-change on-guide-change
|
||||||
:disabled-guides? disabled-guides?}])]))
|
:disabled-guides? disabled-guides?}])]))
|
||||||
|
|
Loading…
Add table
Reference in a new issue