mirror of
https://github.com/penpot/penpot.git
synced 2025-05-12 19:26:38 +02:00
Merge pull request #2217 from penpot/alotor-fix-nested-boards
Fixes on nested artboards and texts
This commit is contained in:
commit
7e58e2f5eb
8 changed files with 171 additions and 107 deletions
|
@ -1,5 +1,13 @@
|
||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
|
||||||
|
## 1.15.3-beta
|
||||||
|
|
||||||
|
### :bug: Bugs fixed
|
||||||
|
|
||||||
|
- Fix error when moving nested frames outside [Taiga #4017](https://tree.taiga.io/project/penpot/issue/4017)
|
||||||
|
- Fix problem when hovering over nested frames [Taiga #4018](https://tree.taiga.io/project/penpot/issue/4018)
|
||||||
|
- Fix problem editing rotated texts [Taiga #4026](https://tree.taiga.io/project/penpot/issue/4026)
|
||||||
|
|
||||||
## 1.15.2-beta
|
## 1.15.2-beta
|
||||||
|
|
||||||
### :bug: Bugs fixed
|
### :bug: Bugs fixed
|
||||||
|
|
|
@ -17,16 +17,22 @@
|
||||||
:width width
|
:width width
|
||||||
:height height})
|
:height height})
|
||||||
|
|
||||||
(defn position-data-points
|
(defn position-data-selrect
|
||||||
[{:keys [position-data] :as shape}]
|
[shape]
|
||||||
(let [points (->> position-data
|
(let [points (->> shape
|
||||||
(mapcat (comp gpr/rect->points position-data->rect)))
|
:position-data
|
||||||
transform (gtr/transform-matrix shape)]
|
(mapcat (comp gpr/rect->points position-data->rect)))]
|
||||||
(gco/transform-points points transform)))
|
(-> points (gpr/points->selrect))))
|
||||||
|
|
||||||
(defn position-data-bounding-box
|
(defn position-data-bounding-box
|
||||||
[shape]
|
[shape]
|
||||||
(gpr/points->selrect (position-data-points shape)))
|
(let [points (->> shape
|
||||||
|
:position-data
|
||||||
|
(mapcat (comp gpr/rect->points position-data->rect)))
|
||||||
|
transform (gtr/transform-matrix shape)]
|
||||||
|
(-> points
|
||||||
|
(gco/transform-points transform)
|
||||||
|
(gpr/points->selrect ))))
|
||||||
|
|
||||||
(defn overlaps-position-data?
|
(defn overlaps-position-data?
|
||||||
"Checks if the given position data is inside the shape"
|
"Checks if the given position data is inside the shape"
|
||||||
|
|
|
@ -44,6 +44,10 @@
|
||||||
[{:keys [type]}]
|
[{:keys [type]}]
|
||||||
(= type :group))
|
(= type :group))
|
||||||
|
|
||||||
|
(defn bool-shape?
|
||||||
|
[{:keys [type]}]
|
||||||
|
(= type :bool))
|
||||||
|
|
||||||
(defn text-shape?
|
(defn text-shape?
|
||||||
[{:keys [type]}]
|
[{:keys [type]}]
|
||||||
(= type :text))
|
(= type :text))
|
||||||
|
@ -268,7 +272,7 @@
|
||||||
(= id-a id-b)
|
(= id-a id-b)
|
||||||
0
|
0
|
||||||
|
|
||||||
(is-shape-over-shape? objects id-a id-b options)
|
(is-shape-over-shape? objects id-a id-b {:top-frames? true})
|
||||||
1
|
1
|
||||||
|
|
||||||
:else
|
:else
|
||||||
|
|
|
@ -32,7 +32,8 @@
|
||||||
(declare group-wrapper)
|
(declare group-wrapper)
|
||||||
(declare svg-raw-wrapper)
|
(declare svg-raw-wrapper)
|
||||||
(declare bool-wrapper)
|
(declare bool-wrapper)
|
||||||
(declare frame-wrapper)
|
(declare root-frame-wrapper)
|
||||||
|
(declare nested-frame-wrapper)
|
||||||
|
|
||||||
(def circle-wrapper (common/generic-wrapper-factory circle/circle-shape))
|
(def circle-wrapper (common/generic-wrapper-factory circle/circle-shape))
|
||||||
(def image-wrapper (common/generic-wrapper-factory image/image-shape))
|
(def image-wrapper (common/generic-wrapper-factory image/image-shape))
|
||||||
|
@ -62,15 +63,25 @@
|
||||||
(mapcat #(cph/get-children-with-self objects (:id %))))]
|
(mapcat #(cph/get-children-with-self objects (:id %))))]
|
||||||
[:& ff/fontfaces-style {:shapes (into [] xform shapes)}])
|
[:& ff/fontfaces-style {:shapes (into [] xform shapes)}])
|
||||||
|
|
||||||
(for [item shapes]
|
(for [shape shapes]
|
||||||
(if (cph/frame-shape? item)
|
(cond
|
||||||
[:& frame-wrapper {:shape item
|
(not (cph/frame-shape? shape))
|
||||||
:key (:id item)
|
[:& shape-wrapper
|
||||||
:objects (get frame-objects (:id item))
|
{:shape shape
|
||||||
:thumbnail? (not (contains? active-frames (:id item)))}]
|
:key (:id shape)}]
|
||||||
|
|
||||||
[:& shape-wrapper {:shape item
|
(cph/root-frame? shape)
|
||||||
:key (:id item)}]))]))
|
[:& root-frame-wrapper
|
||||||
|
{:shape shape
|
||||||
|
:key (:id shape)
|
||||||
|
:objects (get frame-objects (:id shape))
|
||||||
|
:thumbnail? (not (contains? active-frames (:id shape)))}]
|
||||||
|
|
||||||
|
:else
|
||||||
|
[:& nested-frame-wrapper
|
||||||
|
{:shape shape
|
||||||
|
:key (:id shape)
|
||||||
|
:objects (get frame-objects (:id shape))}]))]))
|
||||||
|
|
||||||
(mf/defc shape-wrapper
|
(mf/defc shape-wrapper
|
||||||
{::mf/wrap [#(mf/memo' % (mf/check-props ["shape"]))]
|
{::mf/wrap [#(mf/memo' % (mf/check-props ["shape"]))]
|
||||||
|
@ -98,12 +109,13 @@
|
||||||
:bool [:> bool-wrapper opts]
|
:bool [:> bool-wrapper opts]
|
||||||
|
|
||||||
;; Only used when drawing a new frame.
|
;; Only used when drawing a new frame.
|
||||||
:frame [:> frame-wrapper opts]
|
:frame [:> nested-frame-wrapper opts]
|
||||||
|
|
||||||
nil))))
|
nil))))
|
||||||
|
|
||||||
(def group-wrapper (group/group-wrapper-factory shape-wrapper))
|
(def group-wrapper (group/group-wrapper-factory shape-wrapper))
|
||||||
(def svg-raw-wrapper (svg-raw/svg-raw-wrapper-factory shape-wrapper))
|
(def svg-raw-wrapper (svg-raw/svg-raw-wrapper-factory shape-wrapper))
|
||||||
(def bool-wrapper (bool/bool-wrapper-factory shape-wrapper))
|
(def bool-wrapper (bool/bool-wrapper-factory shape-wrapper))
|
||||||
(def frame-wrapper (frame/frame-wrapper-factory shape-wrapper))
|
(def root-frame-wrapper (frame/root-frame-wrapper-factory shape-wrapper))
|
||||||
|
(def nested-frame-wrapper (frame/nested-frame-wrapper-factory shape-wrapper))
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
(= (unchecked-get new-props "thumbnail?") (unchecked-get old-props "thumbnail?"))
|
(= (unchecked-get new-props "thumbnail?") (unchecked-get old-props "thumbnail?"))
|
||||||
(= (unchecked-get new-props "shape") (unchecked-get old-props "shape"))))
|
(= (unchecked-get new-props "shape") (unchecked-get old-props "shape"))))
|
||||||
|
|
||||||
(defn frame-wrapper-factory
|
(defn nested-frame-wrapper-factory
|
||||||
[shape-wrapper]
|
[shape-wrapper]
|
||||||
|
|
||||||
(let [frame-shape (frame-shape-factory shape-wrapper)]
|
(let [frame-shape (frame-shape-factory shape-wrapper)]
|
||||||
|
@ -60,22 +60,33 @@
|
||||||
|
|
||||||
(let [shape (unchecked-get props "shape")
|
(let [shape (unchecked-get props "shape")
|
||||||
frame-id (:id shape)
|
frame-id (:id shape)
|
||||||
|
|
||||||
;; References to the current rendered node and the its parentn
|
|
||||||
node-ref (mf/use-var nil)
|
|
||||||
|
|
||||||
objects (wsh/lookup-page-objects @st/state)
|
objects (wsh/lookup-page-objects @st/state)
|
||||||
|
node-ref (mf/use-var nil)
|
||||||
|
modifiers-ref (mf/use-memo (mf/deps frame-id) #(refs/workspace-modifiers-by-frame-id frame-id))
|
||||||
|
modifiers (mf/deref modifiers-ref)]
|
||||||
|
|
||||||
;; Modifiers
|
(fdm/use-dynamic-modifiers objects @node-ref modifiers)
|
||||||
|
(let [shape (unchecked-get props "shape")]
|
||||||
|
[:& frame-shape {:shape shape :ref node-ref}])))))
|
||||||
|
|
||||||
|
(defn root-frame-wrapper-factory
|
||||||
|
[shape-wrapper]
|
||||||
|
|
||||||
|
(let [frame-shape (frame-shape-factory shape-wrapper)]
|
||||||
|
(mf/fnc frame-wrapper
|
||||||
|
{::mf/wrap [#(mf/memo' % check-props)]
|
||||||
|
::mf/wrap-props false}
|
||||||
|
[props]
|
||||||
|
|
||||||
|
(let [shape (unchecked-get props "shape")
|
||||||
|
frame-id (:id shape)
|
||||||
|
objects (wsh/lookup-page-objects @st/state)
|
||||||
|
node-ref (mf/use-var nil)
|
||||||
modifiers-ref (mf/use-memo (mf/deps frame-id) #(refs/workspace-modifiers-by-frame-id frame-id))
|
modifiers-ref (mf/use-memo (mf/deps frame-id) #(refs/workspace-modifiers-by-frame-id frame-id))
|
||||||
modifiers (mf/deref modifiers-ref)]
|
modifiers (mf/deref modifiers-ref)]
|
||||||
|
|
||||||
(fdm/use-dynamic-modifiers objects @node-ref modifiers)
|
(fdm/use-dynamic-modifiers objects @node-ref modifiers)
|
||||||
|
|
||||||
(if-not (cph/root-frame? shape)
|
|
||||||
[:& frame-shape {:shape shape :ref node-ref}]
|
|
||||||
|
|
||||||
;; If the current shape is root we handle its thumbnail and the dynamic modifiers
|
|
||||||
(let [thumbnail? (unchecked-get props "thumbnail?")
|
(let [thumbnail? (unchecked-get props "thumbnail?")
|
||||||
fonts (mf/use-memo (mf/deps shape objects) #(ff/shape->fonts shape objects))
|
fonts (mf/use-memo (mf/deps shape objects) #(ff/shape->fonts shape objects))
|
||||||
fonts (-> fonts (hooks/use-equal-memo))
|
fonts (-> fonts (hooks/use-equal-memo))
|
||||||
|
@ -135,4 +146,4 @@
|
||||||
{:id (dm/str "thumbnail-container-" (:id shape))
|
{:id (dm/str "thumbnail-container-" (:id shape))
|
||||||
;; Hide the thumbnail when not displaying
|
;; Hide the thumbnail when not displaying
|
||||||
:opacity (when (and @rendered? (not thumbnail?) (not render-frame?)) 0)}
|
:opacity (when (and @rendered? (not thumbnail?) (not render-frame?)) 0)}
|
||||||
thumbnail-renderer]]]))))))
|
thumbnail-renderer]]])))))
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
|
[app.common.geom.shapes :as gsh]
|
||||||
|
[app.common.geom.shapes.text :as gsht]
|
||||||
[app.common.math :as mth]
|
[app.common.math :as mth]
|
||||||
[app.main.data.workspace.texts :as dwt]
|
[app.main.data.workspace.texts :as dwt]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
|
@ -37,6 +39,15 @@
|
||||||
[:& text/text-shape {:shape shape}]]
|
[:& text/text-shape {:shape shape}]]
|
||||||
|
|
||||||
(when (and (debug? :text-outline) (d/not-empty? (:position-data shape)))
|
(when (and (debug? :text-outline) (d/not-empty? (:position-data shape)))
|
||||||
|
[:g {:transform (gsh/transform-str shape {:no-flip true})}
|
||||||
|
(let [bounding-box (gsht/position-data-selrect shape)]
|
||||||
|
[:rect {
|
||||||
|
:x (:x bounding-box)
|
||||||
|
:y (:y bounding-box)
|
||||||
|
:width (:width bounding-box)
|
||||||
|
:height (:height bounding-box)
|
||||||
|
:style { :fill "none" :stroke "orange"}}])
|
||||||
|
|
||||||
(for [[index data] (d/enumerate (:position-data shape))]
|
(for [[index data] (d/enumerate (:position-data shape))]
|
||||||
(let [{:keys [x y width height]} data]
|
(let [{:keys [x y width height]} data]
|
||||||
[:g {:key (dm/str index)}
|
[:g {:key (dm/str index)}
|
||||||
|
@ -52,4 +63,4 @@
|
||||||
:y1 (mth/round (- (:y data) (:height data)))
|
:y1 (mth/round (- (:y data) (:height data)))
|
||||||
:x2 (mth/round (+ x width))
|
:x2 (mth/round (+ x width))
|
||||||
:y2 (mth/round (- (:y data) (:height data)))
|
:y2 (mth/round (- (:y data) (:height data)))
|
||||||
:style {:stroke "blue"}}]])))]))
|
:style {:stroke "blue"}}]]))])]))
|
||||||
|
|
|
@ -272,7 +272,7 @@
|
||||||
(some? text-modifier)
|
(some? text-modifier)
|
||||||
(dwt/apply-text-modifier text-modifier))
|
(dwt/apply-text-modifier text-modifier))
|
||||||
|
|
||||||
bounding-box (gsht/position-data-bounding-box shape)
|
bounding-box (gsht/position-data-selrect shape)
|
||||||
|
|
||||||
x (min (:x bounding-box) (:x shape))
|
x (min (:x bounding-box) (:x shape))
|
||||||
y (min (:y bounding-box) (:y shape))
|
y (min (:y bounding-box) (:y shape))
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
(ns app.main.ui.workspace.viewport.pixel-overlay
|
(ns app.main.ui.workspace.viewport.pixel-overlay
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.workspace.colors :as dwc]
|
[app.main.data.workspace.colors :as dwc]
|
||||||
|
@ -41,13 +42,24 @@
|
||||||
shapes (->> (:shapes root)
|
shapes (->> (:shapes root)
|
||||||
(map (d/getf objects)))]
|
(map (d/getf objects)))]
|
||||||
[:g.shapes
|
[:g.shapes
|
||||||
(for [item shapes]
|
(for [shape shapes]
|
||||||
(if (= (:type item) :frame)
|
(cond
|
||||||
[:& shapes/frame-wrapper {:shape item
|
(not (cph/frame-shape? shape))
|
||||||
:key (:id item)
|
[:& shapes/shape-wrapper
|
||||||
|
{:shape shape
|
||||||
|
:key (:id shape)}]
|
||||||
|
|
||||||
|
(cph/root-frame? shape)
|
||||||
|
[:& shapes/root-frame-wrapper
|
||||||
|
{:shape shape
|
||||||
|
:key (:id shape)
|
||||||
:objects objects}]
|
:objects objects}]
|
||||||
[:& shapes/shape-wrapper {:shape item
|
|
||||||
:key (:id item)}]))]))
|
:else
|
||||||
|
[:& shapes/nested-frame-wrapper
|
||||||
|
{:shape shape
|
||||||
|
:key (:id shape)
|
||||||
|
:objects objects}]))]))
|
||||||
|
|
||||||
(mf/defc pixel-overlay
|
(mf/defc pixel-overlay
|
||||||
{::mf/wrap-props false}
|
{::mf/wrap-props false}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue