mirror of
https://github.com/penpot/penpot.git
synced 2025-06-03 08:31:39 +02:00
✨ Changes to the editor UI
This commit is contained in:
parent
3c8934e847
commit
5925d2520f
16 changed files with 350 additions and 168 deletions
|
@ -349,6 +349,9 @@
|
|||
column-tracks (add-auto-size column-tracks column-add-auto)
|
||||
row-tracks (add-auto-size row-tracks row-add-auto)
|
||||
|
||||
column-total-size (tracks-total-size column-tracks)
|
||||
row-total-size (tracks-total-size row-tracks)
|
||||
|
||||
start-p
|
||||
(cond-> bound-corner
|
||||
(= :end (:layout-align-content parent))
|
||||
|
|
|
@ -123,6 +123,10 @@
|
|||
padding: $size-1;
|
||||
svg {
|
||||
fill: $color-gray-20;
|
||||
|
||||
&.icon-close {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background: transparent;
|
||||
|
|
|
@ -367,7 +367,8 @@ $height-palette-max: 80px;
|
|||
z-index: 12;
|
||||
pointer-events: none;
|
||||
|
||||
.path-actions {
|
||||
.path-actions,
|
||||
.grid-actions {
|
||||
pointer-events: initial;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
@ -378,6 +379,27 @@ $height-palette-max: 80px;
|
|||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.grid-actions {
|
||||
padding-left: 1rem;
|
||||
gap: 12px;
|
||||
color: var(--color-gray-60);
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
|
||||
.btn-primary,
|
||||
.btn-secondary {
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.grid-edit-title {
|
||||
margin-right: 2rem;
|
||||
}
|
||||
|
||||
.grid-edit-board-name {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.viewport-actions-group {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
(:require
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.geom.shapes.flex-layout :as gsl]
|
||||
[app.common.geom.shapes.flex-layout :as gslf]
|
||||
[app.common.geom.shapes.grid-layout :as gslg]
|
||||
[app.common.math :as mth]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.modifiers :as ctm]
|
||||
|
@ -84,7 +85,10 @@
|
|||
fid (ctst/top-nested-frame objects initial)
|
||||
|
||||
flex-layout? (ctl/flex-layout? objects fid)
|
||||
drop-index (when flex-layout? (gsl/get-drop-index fid objects initial))
|
||||
grid-layout? (ctl/grid-layout? objects fid)
|
||||
|
||||
drop-index (when flex-layout? (gslf/get-drop-index fid objects initial))
|
||||
drop-cell (when grid-layout? (gslg/get-drop-cell fid objects initial))
|
||||
|
||||
shape (get-in state [:workspace-drawing :object])
|
||||
shape (-> shape
|
||||
|
@ -101,6 +105,9 @@
|
|||
(cond-> (some? drop-index)
|
||||
(with-meta {:index drop-index}))
|
||||
|
||||
(cond-> (some? drop-cell)
|
||||
(with-meta {:cell drop-cell}))
|
||||
|
||||
(assoc :initialized? true)
|
||||
(assoc :click-draw? true))]
|
||||
(rx/concat
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
(:require
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.geom.shapes.flex-layout :as gsl]
|
||||
[app.common.geom.shapes.flex-layout :as gslf]
|
||||
[app.common.geom.shapes.grid-layout :as gslg]
|
||||
[app.common.geom.shapes.path :as gsp]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
|
@ -53,11 +54,15 @@
|
|||
position (when start (gpt/point start))
|
||||
frame-id (ctst/top-nested-frame objects position)
|
||||
flex-layout? (ctl/flex-layout? objects frame-id)
|
||||
drop-index (when flex-layout? (gsl/get-drop-index frame-id objects position))]
|
||||
grid-layout? (ctl/grid-layout? objects frame-id)
|
||||
drop-index (when flex-layout? (gslf/get-drop-index frame-id objects position))
|
||||
drop-cell (when grid-layout? (gslg/get-drop-cell frame-id objects position))]
|
||||
(-> state
|
||||
(assoc-in [:workspace-drawing :object :frame-id] frame-id)
|
||||
(cond-> (some? drop-index)
|
||||
(update-in [:workspace-drawing :object] with-meta {:index drop-index})))))))
|
||||
(update-in [:workspace-drawing :object] with-meta {:index drop-index}))
|
||||
(cond-> (some? drop-cell)
|
||||
(update-in [:workspace-drawing :object] with-meta {:cell drop-cell})))))))
|
||||
|
||||
(defn curve-to-path [{:keys [segments] :as shape}]
|
||||
(let [content (gsp/segments->content segments)
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
(ns app.main.data.workspace.grid-layout.editor
|
||||
(:require
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[potok.core :as ptk]))
|
||||
|
||||
(defn hover-grid-cell
|
||||
|
@ -42,3 +44,21 @@
|
|||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :workspace-grid-edition dissoc grid-id))))
|
||||
|
||||
(defn locate-board
|
||||
[grid-id]
|
||||
(ptk/reify ::locate-board
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
srect (get-in objects [grid-id :selrect])]
|
||||
(prn srect)
|
||||
(-> state
|
||||
(update :workspace-local
|
||||
(fn [{:keys [zoom vport] :as local}]
|
||||
(let [{:keys [x y width height]} srect
|
||||
x (+ x (/ width 2) (- (/ (:width vport) 2 zoom)))
|
||||
y (+ y (/ height 2) (- (/ (:height vport) 2 zoom)))
|
||||
srect (gsh/make-selrect x y width height)]
|
||||
(-> local
|
||||
(update :vbox merge (select-keys srect [:x :y :x1 :x2 :y1 :y2])))))))))))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
|
|
|
@ -82,6 +82,7 @@
|
|||
selected)
|
||||
|
||||
index (:index (meta attrs))
|
||||
[row column :as cell] (:cell (meta attrs))
|
||||
|
||||
changes (-> changes
|
||||
(pcb/with-objects objects)
|
||||
|
@ -91,6 +92,8 @@
|
|||
(pcb/add-object shape))
|
||||
(cond-> (some? (:parent-id attrs))
|
||||
(pcb/change-parent (:parent-id attrs) [shape] index))
|
||||
(cond-> (some? cell)
|
||||
(pcb/update-shapes [(:parent-id shape)] #(ctl/push-into-cell % [id] row column)))
|
||||
(cond-> (ctl/grid-layout? objects (:parent-id shape))
|
||||
(pcb/update-shapes [(:parent-id shape)] ctl/assign-cells)))]
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@
|
|||
(dom/class? node "frame-title")
|
||||
(let [shape (gsh/transform-shape shape modifiers)
|
||||
zoom (get-in @st/state [:workspace-local :zoom] 1)
|
||||
mtx (vwu/title-transform shape zoom)]
|
||||
mtx (vwu/title-transform shape zoom false)]
|
||||
(override-transform-att! node "transform" mtx))
|
||||
|
||||
(or (= (dom/get-tag-name node) "mask")
|
||||
|
|
|
@ -53,9 +53,9 @@
|
|||
(.setPointerCapture editor (.-pointerId bevent))
|
||||
(.setPointerCapture target (.-pointerId bevent))))
|
||||
|
||||
|
||||
(when (or (dom/class? (dom/get-target bevent) "viewport-controls")
|
||||
(dom/class? (dom/get-target bevent) "viewport-selrect"))
|
||||
(dom/child? (dom/get-target bevent) (dom/query ".viewport-controls")))
|
||||
|
||||
(dom/stop-propagation bevent)
|
||||
|
||||
(when-not @z?
|
||||
|
@ -79,7 +79,6 @@
|
|||
(st/emit! (dw/start-zooming pt)))
|
||||
(st/emit! (dw/start-panning))))
|
||||
|
||||
|
||||
left-click?
|
||||
(do
|
||||
(st/emit! (ms/->MouseEvent :down ctrl? shift? alt? meta?))
|
||||
|
|
|
@ -38,48 +38,6 @@
|
|||
:flex (dm/str (fmt/format-number value) "FR")
|
||||
:auto "AUTO"))
|
||||
|
||||
(mf/defc track-marker
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
|
||||
(let [center (unchecked-get props "center")
|
||||
value (unchecked-get props "value")
|
||||
zoom (unchecked-get props "zoom")
|
||||
|
||||
marker-width (/ 24 zoom)
|
||||
marker-h1 (/ 22 zoom)
|
||||
marker-h2 (/ 8 zoom)
|
||||
|
||||
marker-half-width (/ marker-width 2)
|
||||
marker-half-height (/ (+ marker-h1 marker-h2) 2)
|
||||
|
||||
marker-points
|
||||
(reduce
|
||||
apply-to-point
|
||||
[(gpt/subtract center
|
||||
(gpt/point marker-half-width marker-half-height))]
|
||||
[#(gpt/add % (gpt/point marker-width 0))
|
||||
#(gpt/add % (gpt/point 0 marker-h1))
|
||||
#(gpt/add % (gpt/point (- marker-half-width) marker-h2))
|
||||
#(gpt/subtract % (gpt/point marker-half-width marker-h2))])
|
||||
|
||||
text-x (:x center)
|
||||
text-y (:y center)]
|
||||
|
||||
[:g {:class (css :grid-track-marker)}
|
||||
[:polygon {:class (css :marker-shape)
|
||||
:points (->> marker-points
|
||||
(map #(dm/fmt "%,%" (:x %) (:y %)))
|
||||
(str/join " "))}]
|
||||
[:text {:class (css :marker-text)
|
||||
:x text-x
|
||||
:y text-y
|
||||
:width (/ 26.26 zoom)
|
||||
:height (/ 32 zoom)
|
||||
:text-anchor "middle"
|
||||
:dominant-baseline "middle"}
|
||||
(dm/str value)]]))
|
||||
|
||||
(mf/defc grid-editor-frame
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
|
@ -282,7 +240,22 @@
|
|||
cell-bounds (gsg/cell-bounds layout-data cell)
|
||||
cell-origin (gpo/origin cell-bounds)
|
||||
cell-width (gpo/width-points cell-bounds)
|
||||
cell-height (gpo/height-points cell-bounds)]
|
||||
cell-height (gpo/height-points cell-bounds)
|
||||
|
||||
handle-pointer-enter
|
||||
(mf/use-callback
|
||||
(fn []
|
||||
(st/emit! (dwge/hover-grid-cell (:id shape) (:id cell) true))))
|
||||
|
||||
handle-pointer-leave
|
||||
(mf/use-callback
|
||||
(fn []
|
||||
(st/emit! (dwge/hover-grid-cell (:id shape) (:id cell) false))))
|
||||
|
||||
handle-pointer-down
|
||||
(mf/use-callback
|
||||
(fn []
|
||||
(st/emit! (dwge/select-grid-cell (:id shape) (:id cell)))))]
|
||||
|
||||
[:g.cell-editor
|
||||
[:rect
|
||||
|
@ -294,9 +267,9 @@
|
|||
:width cell-width
|
||||
:height cell-height
|
||||
|
||||
:on-pointer-enter #(st/emit! (dwge/hover-grid-cell (:id shape) (:id cell) true))
|
||||
:on-pointer-leave #(st/emit! (dwge/hover-grid-cell (:id shape) (:id cell) false))
|
||||
:on-click #(st/emit! (dwge/select-grid-cell (:id shape) (:id cell)))}]
|
||||
:on-pointer-enter handle-pointer-enter
|
||||
:on-pointer-leave handle-pointer-leave
|
||||
:on-pointer-down handle-pointer-down}]
|
||||
|
||||
(when selected?
|
||||
(let [handlers
|
||||
|
@ -318,31 +291,17 @@
|
|||
:direction dir
|
||||
:layout-data layout-data}])]))]))
|
||||
|
||||
(mf/defc resize-track-handler
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(defn use-resize-track
|
||||
[type shape index track-before track-after zoom snap-pixel?]
|
||||
|
||||
(let [shape (unchecked-get props "shape")
|
||||
index (unchecked-get props "index")
|
||||
track-before (unchecked-get props "track-before")
|
||||
track-after (unchecked-get props "track-after")
|
||||
|
||||
{:keys [column-total-size column-total-gap row-total-size row-total-gap]} (unchecked-get props "layout-data")
|
||||
start-p (unchecked-get props "start-p")
|
||||
type (unchecked-get props "type")
|
||||
zoom (unchecked-get props "zoom")
|
||||
|
||||
[layout-gap-row layout-gap-col] (ctl/gaps shape)
|
||||
|
||||
start-size-before (mf/use-var nil)
|
||||
(let [start-size-before (mf/use-var nil)
|
||||
start-size-after (mf/use-var nil)
|
||||
|
||||
snap-pixel? (mf/deref refs/snap-pixel?)
|
||||
|
||||
handle-drag-start
|
||||
(mf/use-callback
|
||||
(mf/deps shape track-before track-after)
|
||||
(fn []
|
||||
(prn "???" type (:name shape) index track-before track-after zoom snap-pixel?)
|
||||
(reset! start-size-before (:size track-before))
|
||||
(reset! start-size-after (:size track-after))
|
||||
(let [tracks-prop
|
||||
|
@ -387,23 +346,42 @@
|
|||
(fn []
|
||||
(reset! start-size-before nil)
|
||||
(reset! start-size-after nil)
|
||||
(st/emit! (dwm/apply-modifiers))))
|
||||
(st/emit! (dwm/apply-modifiers))))]
|
||||
|
||||
(use-drag {:on-drag-start handle-drag-start
|
||||
:on-drag-delta handle-drag-position
|
||||
:on-drag-end handle-drag-end})))
|
||||
|
||||
(mf/defc resize-track-handler
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
|
||||
(let [shape (unchecked-get props "shape")
|
||||
index (unchecked-get props "index")
|
||||
track-before (unchecked-get props "track-before")
|
||||
track-after (unchecked-get props "track-after")
|
||||
snap-pixel? (unchecked-get props "snap-pixel?")
|
||||
|
||||
{:keys [column-total-size column-total-gap row-total-size row-total-gap]} (unchecked-get props "layout-data")
|
||||
start-p (unchecked-get props "start-p")
|
||||
type (unchecked-get props "type")
|
||||
zoom (unchecked-get props "zoom")
|
||||
|
||||
[layout-gap-row layout-gap-col] (ctl/gaps shape)
|
||||
|
||||
{:keys [handle-pointer-down handle-lost-pointer-capture handle-pointer-move]}
|
||||
(use-drag {:on-drag-start handle-drag-start
|
||||
:on-drag-delta handle-drag-position
|
||||
:on-drag-end handle-drag-end})
|
||||
(use-resize-track type shape index track-before track-after zoom snap-pixel?)
|
||||
|
||||
[x y width height]
|
||||
(if (= type :column)
|
||||
[(- (:x start-p) (max layout-gap-col (/ 8 zoom)))
|
||||
(- (:y start-p) (/ 40 zoom))
|
||||
[(- (:x start-p) layout-gap-col (/ (- (max layout-gap-col (/ 16 zoom)) layout-gap-col) 2))
|
||||
(:y start-p)
|
||||
(max layout-gap-col (/ 16 zoom))
|
||||
(+ row-total-size row-total-gap (/ 40 zoom))]
|
||||
(+ row-total-size row-total-gap)]
|
||||
|
||||
[(- (:x start-p) (/ 40 zoom))
|
||||
(- (:y start-p) (max layout-gap-row (/ 8 zoom)))
|
||||
(+ column-total-size column-total-gap (/ 40 zoom))
|
||||
[(:x start-p)
|
||||
(- (:y start-p) layout-gap-row (/ (- (max layout-gap-row (/ 16 zoom)) layout-gap-row) 2))
|
||||
(+ column-total-size column-total-gap)
|
||||
(max layout-gap-row (/ 16 zoom))])]
|
||||
|
||||
[:rect.resize-track-handler
|
||||
|
@ -419,6 +397,63 @@
|
|||
:on-pointer-move handle-pointer-move
|
||||
:style {:fill "transparent"}}]))
|
||||
|
||||
(mf/defc track-marker
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
|
||||
(let [center (unchecked-get props "center")
|
||||
value (unchecked-get props "value")
|
||||
zoom (unchecked-get props "zoom")
|
||||
shape (unchecked-get props "shape")
|
||||
index (unchecked-get props "index")
|
||||
type (unchecked-get props "type")
|
||||
track-before (unchecked-get props "track-before")
|
||||
track-after (unchecked-get props "track-after")
|
||||
snap-pixel? (unchecked-get props "snap-pixel?")
|
||||
|
||||
marker-width (/ 24 zoom)
|
||||
marker-h1 (/ 22 zoom)
|
||||
marker-h2 (/ 8 zoom)
|
||||
|
||||
marker-half-width (/ marker-width 2)
|
||||
marker-half-height (/ (+ marker-h1 marker-h2) 2)
|
||||
|
||||
marker-points
|
||||
(reduce
|
||||
apply-to-point
|
||||
[(gpt/subtract center
|
||||
(gpt/point marker-half-width marker-half-height))]
|
||||
[#(gpt/add % (gpt/point marker-width 0))
|
||||
#(gpt/add % (gpt/point 0 marker-h1))
|
||||
#(gpt/add % (gpt/point (- marker-half-width) marker-h2))
|
||||
#(gpt/subtract % (gpt/point marker-half-width marker-h2))])
|
||||
|
||||
text-x (:x center)
|
||||
text-y (:y center)
|
||||
|
||||
{:keys [handle-pointer-down handle-lost-pointer-capture handle-pointer-move]}
|
||||
(use-resize-track type shape index track-before track-after zoom snap-pixel?)]
|
||||
|
||||
[:g {:on-pointer-down handle-pointer-down
|
||||
:on-lost-pointer-capture handle-lost-pointer-capture
|
||||
:on-pointer-move handle-pointer-move
|
||||
:class (css :grid-track-marker)
|
||||
:style {:cursor (if (= type :column)
|
||||
(cur/resize-ew 0)
|
||||
(cur/resize-ns 0))}}
|
||||
[:polygon {:class (css :marker-shape)
|
||||
:points (->> marker-points
|
||||
(map #(dm/fmt "%,%" (:x %) (:y %)))
|
||||
(str/join " "))}]
|
||||
[:text {:class (css :marker-text)
|
||||
:x text-x
|
||||
:y text-y
|
||||
:width (/ 26.26 zoom)
|
||||
:height (/ 32 zoom)
|
||||
:text-anchor "middle"
|
||||
:dominant-baseline "middle"}
|
||||
(dm/str value)]]))
|
||||
|
||||
(mf/defc track
|
||||
{::mf/wrap [#(mf/memo' % (mf/check-props ["shape" "zoom" "index" "type" "track-data" "layout-data"]))]
|
||||
::mf/wrap-props false}
|
||||
|
@ -427,32 +462,40 @@
|
|||
zoom (unchecked-get props "zoom")
|
||||
type (unchecked-get props "type")
|
||||
index (unchecked-get props "index")
|
||||
snap-pixel? (unchecked-get props "snap-pixel?")
|
||||
track-data (unchecked-get props "track-data")
|
||||
layout-data (unchecked-get props "layout-data")
|
||||
|
||||
track-input-ref (mf/use-ref)
|
||||
[layout-gap-row layout-gap-col] (ctl/gaps shape)
|
||||
bounds (:points shape)
|
||||
origin (gpo/origin bounds)
|
||||
vv #(gpo/start-vv bounds %)
|
||||
hv #(gpo/start-hv bounds %)
|
||||
|
||||
start-p (:start-p track-data)
|
||||
relative (gpt/to-vec origin start-p)
|
||||
|
||||
marker-p
|
||||
(if (= type :column)
|
||||
(-> start-p
|
||||
(-> origin
|
||||
(gpt/add (hv (:x relative)))
|
||||
(gpt/subtract (vv (/ 20 zoom)))
|
||||
(cond-> (not= index 0)
|
||||
(gpt/subtract (hv (/ layout-gap-col 2)))))
|
||||
(-> start-p
|
||||
(-> origin
|
||||
(gpt/add (vv (:y relative)))
|
||||
(gpt/subtract (hv (/ 20 zoom)))
|
||||
(cond-> (not= index 0)
|
||||
(gpt/subtract (vv (/ layout-gap-row 2))))))
|
||||
|
||||
text-p
|
||||
(if (= type :column)
|
||||
(-> start-p
|
||||
(-> origin
|
||||
(gpt/add (hv (:x relative)))
|
||||
(gpt/subtract (vv (/ 36 zoom))))
|
||||
(-> start-p
|
||||
(-> origin
|
||||
(gpt/add (vv (:y relative)))
|
||||
(gpt/subtract (hv (/ (:size track-data) 2)))
|
||||
(gpt/subtract (hv (/ 16 zoom)))
|
||||
(gpt/add (vv (/ (:size track-data) 2)))
|
||||
|
@ -499,7 +542,9 @@
|
|||
[text-x text-y text-width text-height]
|
||||
(if (= type :column)
|
||||
[(:x text-p) (:y text-p) (max 0 (- (:size track-data) 4)) (/ 32 zoom)]
|
||||
[(:x text-p) (:y text-p) (:size track-data) (/ 36 zoom)])]
|
||||
[(:x text-p) (:y text-p) (:size track-data) (/ 36 zoom)])
|
||||
|
||||
track-before (get-in layout-data [track-list-prop (dec index)])]
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps track-data)
|
||||
|
@ -509,6 +554,12 @@
|
|||
[:g.track
|
||||
[:g {:transform (when (= type :row) (dm/fmt "rotate(-90 % %)" (:x marker-p) (:y marker-p)))}
|
||||
[:& track-marker {:center marker-p
|
||||
:index index
|
||||
:shape shape
|
||||
:snap-pixel? snap-pixel?
|
||||
:track-after track-data
|
||||
:track-before track-before
|
||||
:type type
|
||||
:value (dm/str (inc index))
|
||||
:zoom zoom}]]
|
||||
[:g {:transform (when (= type :row) (dm/fmt "rotate(-90 % %)" (+ (:x text-p) (/ (:size track-data) 2)) (+ (:y text-p) (/ 36 zoom 2))))}
|
||||
|
@ -522,16 +573,17 @@
|
|||
:on-key-down handle-keydown-track-input
|
||||
:on-blur handle-blur-track-input}]]]
|
||||
|
||||
(let [track-before (get-in layout-data [track-list-prop (dec index)])]
|
||||
[:& resize-track-handler
|
||||
{:index index
|
||||
:shape shape
|
||||
:layout-data layout-data
|
||||
:start-p start-p
|
||||
:type type
|
||||
:track-before track-before
|
||||
:track-after track-data
|
||||
:zoom zoom}])]))
|
||||
|
||||
[:& resize-track-handler
|
||||
{:index index
|
||||
:layout-data layout-data
|
||||
:shape shape
|
||||
:snap-pixel? snap-pixel?
|
||||
:start-p start-p
|
||||
:track-after track-data
|
||||
:track-before track-before
|
||||
:type type
|
||||
:zoom zoom}]]))
|
||||
|
||||
(mf/defc editor
|
||||
{::mf/wrap [mf/memo]
|
||||
|
@ -547,6 +599,8 @@
|
|||
shape-ref (mf/use-memo (mf/deps (:id shape)) #(refs/object-by-id (:id shape)))
|
||||
base-shape (mf/deref shape-ref)
|
||||
|
||||
snap-pixel? (mf/deref refs/snap-pixel?)
|
||||
|
||||
grid-edition-id-ref (mf/use-memo #(refs/workspace-grid-edition-id (:id shape)))
|
||||
grid-edition (mf/deref grid-edition-id-ref)
|
||||
|
||||
|
@ -565,9 +619,18 @@
|
|||
height (gpo/height-points bounds)
|
||||
origin (gpo/origin bounds)
|
||||
|
||||
[layout-gap-row layout-gap-col] (ctl/gaps shape)
|
||||
|
||||
{:keys [row-tracks column-tracks] :as layout-data}
|
||||
(gsg/calc-layout-data shape children bounds)
|
||||
|
||||
handle-pointer-down
|
||||
(mf/use-callback
|
||||
(fn [event]
|
||||
(let [left-click? (= 1 (.-which (.-nativeEvent event)))]
|
||||
(when left-click?
|
||||
(dom/stop-propagation event)))))
|
||||
|
||||
handle-add-column
|
||||
(mf/use-callback
|
||||
(mf/deps (:id shape))
|
||||
|
@ -581,10 +644,11 @@
|
|||
(st/emit! (st/emit! (dwsl/add-layout-track [(:id shape)] :row ctl/default-track-value)))))]
|
||||
|
||||
(mf/use-effect
|
||||
(fn []
|
||||
#(st/emit! (dwge/stop-grid-layout-editing (:id shape)))))
|
||||
(fn []
|
||||
#(st/emit! (dwge/stop-grid-layout-editing (:id shape)))))
|
||||
|
||||
[:g.grid-editor {:pointer-events (when view-only "none")}
|
||||
[:g.grid-editor {:pointer-events (when view-only "none")
|
||||
:on-pointer-down handle-pointer-down}
|
||||
(when-not view-only
|
||||
[:*
|
||||
[:& grid-editor-frame {:zoom zoom
|
||||
|
@ -608,57 +672,76 @@
|
|||
:type :column
|
||||
:index idx
|
||||
:layout-data layout-data
|
||||
:snap-pixel? snap-pixel?
|
||||
:track-data column-data}])
|
||||
|
||||
;; Last track resize handler
|
||||
(let [last-track (last column-tracks)
|
||||
start-p (:start-p (last column-tracks))
|
||||
marker-p (-> start-p
|
||||
(gpt/subtract (vv (/ 20 zoom)))
|
||||
(gpt/add (hv (:size last-track))))]
|
||||
[:g.track
|
||||
[:& track-marker {:center marker-p
|
||||
:value (dm/str (inc (count column-tracks)))
|
||||
:zoom zoom}]
|
||||
[:& resize-track-handler
|
||||
{:index (count column-tracks)
|
||||
:shape shape
|
||||
:layout-data layout-data
|
||||
:start-p (-> start-p
|
||||
(gpt/add (hv (:size last-track)))
|
||||
(gpt/add (hv (/ 20 zoom))))
|
||||
:type :column
|
||||
:track-before (last column-tracks)
|
||||
:zoom zoom}]])
|
||||
(when-not (empty? column-tracks)
|
||||
(let [last-track (last column-tracks)
|
||||
start-p (:start-p (last column-tracks))
|
||||
relative (gpt/to-vec origin start-p)
|
||||
marker-p (-> origin
|
||||
(gpt/add (hv (:x relative)))
|
||||
(gpt/subtract (vv (/ 20 zoom)))
|
||||
(gpt/add (hv (:size last-track))))]
|
||||
[:g.track
|
||||
[:& track-marker {:center marker-p
|
||||
:index (count column-tracks)
|
||||
:shape shape
|
||||
:snap-pixel? snap-pixel?
|
||||
:track-before (last column-tracks)
|
||||
:type :column
|
||||
:value (dm/str (inc (count column-tracks)))
|
||||
:zoom zoom}]
|
||||
[:& resize-track-handler
|
||||
{:index (count column-tracks)
|
||||
:shape shape
|
||||
:layout-data layout-data
|
||||
:snap-pixel? snap-pixel?
|
||||
:start-p (-> start-p (gpt/add (hv (+ layout-gap-col (:size last-track)))))
|
||||
:type :column
|
||||
:track-before (last column-tracks)
|
||||
:zoom zoom}]]))
|
||||
|
||||
(for [[idx row-data] (d/enumerate row-tracks)]
|
||||
[:& track {:key (dm/str "row-track-" idx)
|
||||
:shape shape
|
||||
:zoom zoom
|
||||
:type :row
|
||||
:index idx
|
||||
[:& track {:index idx
|
||||
:key (dm/str "row-track-" idx)
|
||||
:layout-data layout-data
|
||||
:track-data row-data}])
|
||||
:shape shape
|
||||
:snap-pixel? snap-pixel?
|
||||
:track-data row-data
|
||||
:type :row
|
||||
:zoom zoom}])
|
||||
|
||||
(let [last-track (last row-tracks)
|
||||
start-p (:start-p (last row-tracks))
|
||||
marker-p (-> start-p
|
||||
(gpt/subtract (hv (/ 20 zoom)))
|
||||
(gpt/add (vv (:size last-track))))]
|
||||
[:g.track
|
||||
[:g {:transform (dm/fmt "rotate(-90 % %)" (:x marker-p) (:y marker-p))}
|
||||
[:& track-marker {:center marker-p
|
||||
:value (dm/str (inc (count row-tracks)))
|
||||
:zoom zoom}]]
|
||||
[:& resize-track-handler
|
||||
{:index (count row-tracks)
|
||||
:shape shape
|
||||
:layout-data layout-data
|
||||
:start-p (-> start-p
|
||||
(gpt/add (vv (:size last-track))))
|
||||
:type :row
|
||||
:track-before (last row-tracks)
|
||||
:zoom zoom}]])
|
||||
(when-not (empty? row-tracks)
|
||||
(let [last-track (last row-tracks)
|
||||
start-p (:start-p (last row-tracks))
|
||||
relative (gpt/to-vec origin start-p)
|
||||
marker-p
|
||||
(-> origin
|
||||
(gpt/add (vv (:y relative)))
|
||||
(gpt/subtract (hv (/ 20 zoom)))
|
||||
(gpt/add (vv (:size last-track))))]
|
||||
[:g.track
|
||||
[:g {:transform (dm/fmt "rotate(-90 % %)" (:x marker-p) (:y marker-p))}
|
||||
[:& track-marker {:center marker-p
|
||||
:index (count row-tracks)
|
||||
:shape shape
|
||||
:snap-pixel? snap-pixel?
|
||||
:track-before (last row-tracks)
|
||||
:type :row
|
||||
:value (dm/str (inc (count row-tracks)))
|
||||
:zoom zoom}]]
|
||||
[:& resize-track-handler
|
||||
{:index (count row-tracks)
|
||||
:shape shape
|
||||
:layout-data layout-data
|
||||
:start-p (-> start-p
|
||||
(gpt/add (vv (+ layout-gap-row (:size last-track)))))
|
||||
:type :row
|
||||
:track-before (last row-tracks)
|
||||
:snap-pixel? snap-pixel?
|
||||
:zoom zoom}]]))
|
||||
|
||||
(for [[_ cell] (:layout-grid-cells shape)]
|
||||
[:& grid-cell {:key (dm/str "cell-" (:id cell))
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
}
|
||||
|
||||
.grid-frame {
|
||||
fill: transparent;
|
||||
fill: #F6F6F6;
|
||||
stroke: var(--color-distance);
|
||||
stroke-width: calc(1 / var(--zoom));
|
||||
}
|
||||
|
|
|
@ -69,7 +69,8 @@
|
|||
(> (:x cand) (:x cur)) cand
|
||||
:else cur)))
|
||||
|
||||
(defn title-transform [{:keys [points] :as shape} zoom]
|
||||
(defn title-transform
|
||||
[{:keys [points] :as shape} zoom grid-edition?]
|
||||
(let [leftmost (->> points (reduce left?))
|
||||
topmost (->> points (remove #{leftmost}) (reduce top?))
|
||||
rightmost (->> points (remove #{leftmost topmost}) (reduce right?))
|
||||
|
@ -81,14 +82,18 @@
|
|||
top-right-angle (gpt/angle top-right)
|
||||
|
||||
;; Choose the position that creates the less angle between left-side and top-side
|
||||
[label-pos angle v-pos]
|
||||
[label-pos angle h-pos v-pos]
|
||||
(if (< (mth/abs left-top-angle) (mth/abs top-right-angle))
|
||||
[leftmost left-top-angle (gpt/perpendicular left-top)]
|
||||
[topmost top-right-angle (gpt/perpendicular top-right)])
|
||||
[leftmost left-top-angle left-top (gpt/perpendicular left-top)]
|
||||
[topmost top-right-angle top-right (gpt/perpendicular top-right)])
|
||||
|
||||
delta-x (if grid-edition? 40 0)
|
||||
delta-y (if grid-edition? 50 10)
|
||||
|
||||
label-pos
|
||||
(gpt/subtract label-pos (gpt/scale (gpt/unit v-pos) (/ 10 zoom)))]
|
||||
(-> label-pos
|
||||
(gpt/subtract (gpt/scale (gpt/unit v-pos) (/ delta-y zoom)))
|
||||
(gpt/subtract (gpt/scale (gpt/unit h-pos) (/ delta-x zoom))))]
|
||||
|
||||
(dm/fmt "rotate(% %,%) scale(%, %) translate(%, %)"
|
||||
;; rotate
|
||||
|
|
|
@ -12,8 +12,10 @@
|
|||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.container :as ctn]
|
||||
[app.common.types.shape-tree :as ctt]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.grid-layout.editor :as dwge]
|
||||
[app.main.data.workspace.interactions :as dwi]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
|
@ -24,6 +26,7 @@
|
|||
[app.main.ui.workspace.viewport.path-actions :refer [path-actions]]
|
||||
[app.main.ui.workspace.viewport.utils :as vwu]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[app.util.timers :as ts]
|
||||
[debug :refer [debug?]]
|
||||
[rumext.v2 :as mf]))
|
||||
|
@ -56,16 +59,34 @@
|
|||
selected (mf/deref refs/selected-objects)
|
||||
drawing (mf/deref refs/workspace-drawing)
|
||||
drawing-obj (:object drawing)
|
||||
shape (or drawing-obj (-> selected first))]
|
||||
(when (or (and (= (count selected) 1)
|
||||
(= (:id shape) edition)
|
||||
(and (not (cph/text-shape? shape))
|
||||
(not (cph/frame-shape? shape))))
|
||||
(and (some? drawing-obj)
|
||||
(cph/path-shape? drawing-obj)
|
||||
(not= :curve (:tool drawing))))
|
||||
shape (or drawing-obj (-> selected first))
|
||||
|
||||
single? (= (count selected) 1)
|
||||
editing? (= (:id shape) edition)
|
||||
draw-path? (and (some? drawing-obj)
|
||||
(cph/path-shape? drawing-obj)
|
||||
(not= :curve (:tool drawing)))
|
||||
|
||||
path-edition? (or (and single? editing?
|
||||
(and (not (cph/text-shape? shape))
|
||||
(not (cph/frame-shape? shape))))
|
||||
draw-path?)
|
||||
|
||||
grid-edition? (and single? editing? (ctl/grid-layout? shape))]
|
||||
|
||||
(cond
|
||||
path-edition?
|
||||
[:div.viewport-actions
|
||||
[:& path-actions {:shape shape}]])))
|
||||
[:& path-actions {:shape shape}]]
|
||||
|
||||
grid-edition?
|
||||
[:div.viewport-actions
|
||||
[:div.grid-actions
|
||||
[:div.grid-edit-title
|
||||
(tr "workspace.layout_grid.editor.title") " " [:span.grid-edit-board-name (:name shape)]]
|
||||
[:button.btn-secondary {:on-click #(st/emit! (dwge/locate-board (:id shape)))} "Locate"]
|
||||
[:button.btn-primary {:on-click #(st/emit! dw/clear-edition-mode)} "Done"]
|
||||
[:button.btn-icon-basic {:on-click #(st/emit! dw/clear-edition-mode)} i/close]]])))
|
||||
|
||||
(mf/defc cursor-tooltip
|
||||
[{:keys [zoom tooltip] :as props}]
|
||||
|
@ -97,7 +118,7 @@
|
|||
(mf/defc frame-title
|
||||
{::mf/wrap [mf/memo
|
||||
#(mf/deferred % ts/raf)]}
|
||||
[{:keys [frame selected? zoom show-artboard-names? show-id? on-frame-enter on-frame-leave on-frame-select]}]
|
||||
[{:keys [frame selected? zoom show-artboard-names? show-id? on-frame-enter on-frame-leave on-frame-select grid-edition?]}]
|
||||
(let [workspace-read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||
|
||||
;; Note that we don't use mf/deref to avoid a repaint dependency here
|
||||
|
@ -114,8 +135,8 @@
|
|||
(fn [bevent]
|
||||
(let [event (.-nativeEvent bevent)]
|
||||
(when (= 1 (.-which event))
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(dom/prevent-default bevent)
|
||||
(dom/stop-propagation bevent)
|
||||
(on-frame-select event (:id frame))))))
|
||||
|
||||
on-double-click
|
||||
|
@ -150,7 +171,7 @@
|
|||
|
||||
(when (not (:hidden frame))
|
||||
[:g.frame-title {:id (dm/str "frame-title-" (:id frame))
|
||||
:transform (vwu/title-transform frame zoom)
|
||||
:transform (vwu/title-transform frame zoom grid-edition?)
|
||||
:pointer-events (when (:blocked frame) "none")}
|
||||
(when (:use-for-thumbnail? frame)
|
||||
[:svg {:x 0
|
||||
|
@ -195,7 +216,10 @@
|
|||
(map (d/getf objects))
|
||||
selected)
|
||||
shapes)
|
||||
focus (unchecked-get props "focus")]
|
||||
focus (unchecked-get props "focus")
|
||||
|
||||
edition (mf/deref refs/selected-edition)
|
||||
grid-edition? (ctl/grid-layout? objects edition)]
|
||||
|
||||
[:g.frame-titles
|
||||
(for [{:keys [id parent-id] :as shape} shapes]
|
||||
|
@ -211,7 +235,8 @@
|
|||
:show-id? (debug? :shape-titles)
|
||||
:on-frame-enter on-frame-enter
|
||||
:on-frame-leave on-frame-leave
|
||||
:on-frame-select on-frame-select}]))]))
|
||||
:on-frame-select on-frame-select
|
||||
:grid-edition? (and (= id edition) grid-edition?)}]))]))
|
||||
|
||||
(mf/defc frame-flow
|
||||
[{:keys [flow frame selected? zoom on-frame-enter on-frame-leave on-frame-select]}]
|
||||
|
|
|
@ -4957,3 +4957,6 @@ msgstr "Marketing"
|
|||
#: src/app/main/ui/onboarding/questions.cljs
|
||||
msgid "questions.student-teacher"
|
||||
msgstr "Student or teacher"
|
||||
|
||||
msgid "workspace.layout_grid.editor.title"
|
||||
msgstr "Editing grid"
|
||||
|
|
|
@ -5075,3 +5075,6 @@ msgstr "Marketing"
|
|||
#: src/app/main/ui/onboarding/questions.cljs
|
||||
msgid "questions.student-teacher"
|
||||
msgstr "Estudiante o profesorado"
|
||||
|
||||
msgid "workspace.layout_grid.editor.title"
|
||||
msgstr "Editando rejilla"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue