diff --git a/frontend/src/app/main/ui/components/dropdown.cljs b/frontend/src/app/main/ui/components/dropdown.cljs index 209224bff..9903c528e 100644 --- a/frontend/src/app/main/ui/components/dropdown.cljs +++ b/frontend/src/app/main/ui/components/dropdown.cljs @@ -20,7 +20,7 @@ (if ref (let [target (dom/get-target event) parent (mf/ref-val ref)] - (when-not (.contains parent target) + (when-not (or (not parent) (.contains parent target)) (on-close))) (on-close))) diff --git a/frontend/src/app/main/ui/measurements.cljs b/frontend/src/app/main/ui/measurements.cljs new file mode 100644 index 000000000..808548d6c --- /dev/null +++ b/frontend/src/app/main/ui/measurements.cljs @@ -0,0 +1,256 @@ +;; 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/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.main.ui.measurements + (:require + [rumext.alpha :as mf] + [cuerdas.core :as str] + [okulary.core :as l] + [app.common.data :as d] + [app.common.math :as mth] + [app.common.geom.shapes :as gsh] + [app.common.geom.point :as gpt] + [app.main.store :as st])) + +;; ------------------------------------------------ +;; CONSTANTS +;; ------------------------------------------------ + +(def font-size 10) +(def selection-rect-width 1) + +(def select-color "#1FDEA7") +(def select-guide-width 1) +(def select-guide-dasharray 5) + +(def hover-color "#DB00FF") +(def hover-color-text "#FFF") +(def hover-guide-width 1) + +(def size-display-color "#FFF") +(def size-display-opacity 0.7) +(def size-display-text-color "#000") +(def size-display-width-min 50) +(def size-display-width-max 75) +(def size-display-height 16) + +(def distance-color "#DB00FF") +(def distance-text-color "#FFF") +(def distance-border-radius 2) +(def distance-pill-width 40) +(def distance-pill-height 16) +(def distance-line-stroke 1) + +;; ------------------------------------------------ +;; HELPERS +;; ------------------------------------------------ + +(defn bound->selrect [bounds] + {:x (:x bounds) + :y (:y bounds) + :x1 (:x bounds) + :y1 (:y bounds) + :x2 (+ (:x bounds) (:width bounds)) + :y2 (+ (:y bounds) (:height bounds)) + :width (:width bounds) + :height (:height bounds)}) + +(defn calculate-guides + "Calculates coordinates for the selection guides" + [bounds selrect] + (let [{bounds-width :width bounds-height :height} bounds + {:keys [x y width height]} selrect] + [[(:x bounds) y (+ (:x bounds) bounds-width) y] + [(:x bounds) (+ y height) (+ (:x bounds) bounds-width) (+ y height)] + [x (:y bounds) x (+ (:y bounds) bounds-height)] + [(+ x width) (:y bounds) (+ x width) (+ (:y bounds) bounds-height)]])) + +(defn calculate-distance-lines + "Given a start/end from two shapes gives the distance lines" + [from-s from-e to-s to-e] + (let [ss (- to-s from-s) + se (- to-e from-s) + es (- to-s from-e) + ee (- to-e from-e)] + (cond-> [] + (or (and (neg? ss) (pos? se)) + (and (pos? ss) (neg? ee)) + (and (neg? ss) (> ss se))) + (conj [ from-s (+ from-s ss) ]) + + (or (and (neg? se) (<= ss se))) + (conj [ from-s (+ from-s se) ]) + + (or (and (pos? es) (<= es ee))) + (conj [ from-e (+ from-e es) ]) + + (or (and (pos? ee) (neg? es)) + (and (neg? ee) (pos? ss)) + (and (pos? ee) (< ee es))) + (conj [ from-e (+ from-e ee) ])))) + +;; ------------------------------------------------ +;; COMPONENTS +;; ------------------------------------------------ + +(mf/defc size-display [{:keys [type selrect zoom]}] + (let [{:keys [x y width height]} selrect + size-label (str/fmt "%s x %s" (mth/round width) (mth/round height)) + + rect-height (/ size-display-height zoom) + rect-width (/ (if (<= (count size-label) 9) + size-display-width-min + size-display-width-max) + zoom) + text-padding (/ 4 zoom)] + [:g.size-display + [:rect {:x (+ x (/ width 2) (- (/ rect-width 2))) + :y (- (+ y height) rect-height) + :width rect-width + :height rect-height + :style {:fill size-display-color + :fill-opacity size-display-opacity}}] + + [:text {:x (+ (+ x (/ width 2) (- (/ rect-width 2))) (/ rect-width 2)) + :y (- (+ y height (+ text-padding (/ rect-height 2))) rect-height) + :width rect-width + :height rect-height + :text-anchor "middle" + :style {:fill size-display-text-color + :font-size (/ font-size zoom)}} + size-label]])) + +(mf/defc distance-display-pill [{:keys [x y zoom distance bounds]}] + (let [distance-pill-width (/ distance-pill-width zoom) + distance-pill-height (/ distance-pill-height zoom) + distance-line-stroke (/ distance-line-stroke zoom) + font-size (/ font-size zoom) + text-padding (/ 3 zoom) + distance-border-radius (/ distance-border-radius zoom) + + {bounds-width :width bounds-height :height} bounds + + rect-x (- x (/ distance-pill-width 2)) + rect-y (- y (/ distance-pill-height 2)) + + text-x x + text-y (+ y text-padding) + + offset-x (cond (< rect-x (:x bounds)) (- (:x bounds) rect-x) + (> (+ rect-x distance-pill-width) (+ (:x bounds) bounds-width)) + (- (+ (:x bounds) bounds-width) (+ rect-x distance-pill-width)) + :else 0) + + offset-y (cond (< rect-y (:y bounds)) (- (:y bounds) rect-y) + (> (+ rect-y distance-pill-height) (+ (:y bounds) bounds-height)) + (- (+ (:y bounds) bounds-height) (+ rect-y distance-pill-height)) + :else 0)] + [:g.distance-pill + [:rect {:x (+ rect-x offset-x) + :y (+ rect-y offset-y) + :rx distance-border-radius + :ry distance-border-radius + :width distance-pill-width + :height distance-pill-height + :style {:fill distance-color}}] + + [:text {:x (+ text-x offset-x) + :y (+ text-y offset-y) + :rx distance-border-radius + :ry distance-border-radius + :text-anchor "middle" + :width distance-pill-width + :height distance-pill-height + :style {:fill distance-text-color + :font-size font-size}} + distance]])) + +(mf/defc selection-rect [{:keys [frame selrect zoom]}] + (let [{:keys [x y width height]} selrect + selection-rect-width (/ selection-rect-width zoom)] + [:g.selection-rect + [:rect {:x x + :y y + :width width + :height height + :style {:fill "transparent" + :stroke hover-color + :stroke-width selection-rect-width}}]])) + +(mf/defc distance-display [{:keys [type from to zoom frame bounds]}] + (let [fixed-x (if (gsh/fully-contained? from to) + (+ (:x to) (/ (:width to) 2)) + (+ (:x from) (/ (:width from) 2))) + fixed-y (if (gsh/fully-contained? from to) + (+ (:y to) (/ (:height to) 2)) + (+ (:y from) (/ (:height from) 2))) + + v-lines (->> (calculate-distance-lines (:y1 from) (:y2 from) (:y1 to) (:y2 to)) + (map (fn [[start end]] [fixed-x start fixed-x end]))) + + h-lines (->> (calculate-distance-lines (:x1 from) (:x2 from) (:x1 to) (:x2 to)) + (map (fn [[start end]] [start fixed-y end fixed-y]))) + + lines (d/concat [] v-lines h-lines)] + + (for [[x1 y1 x2 y2] lines] + (let [center-x (+ x1 (/ (- x2 x1) 2)) + center-y (+ y1 (/ (- y2 y1) 2)) + distance (gpt/distance (gpt/point x1 y1) (gpt/point x2 y2))] + [:g.distance-line {:key (str "line-%s-%s-%s-%s" x1 y1 x2 y2)} + [:line + {:x1 x1 + :y1 y1 + :x2 x2 + :y2 y2 + :style {:stroke distance-color + :stroke-width distance-line-stroke}}] + + [:& distance-display-pill + {:x center-x + :y center-y + :zoom zoom + :distance (str (mth/round distance) "px") + :bounds bounds}]])))) + +(mf/defc selection-guides [{:keys [bounds selrect zoom]}] + [:g.selection-guides + (for [[x1 y1 x2 y2] (calculate-guides bounds selrect)] + [:line {:x1 x1 + :y1 y1 + :x2 x2 + :y2 y2 + :style {:stroke select-color + :stroke-width (/ select-guide-width zoom) + :stroke-dasharray (/ select-guide-dasharray zoom)}}])]) + +(mf/defc measurement [{:keys [bounds frame selected-shapes hover-shape zoom]}] + (let [selected-selrect (gsh/selection-rect selected-shapes) + hover-selrect (:selrect hover-shape) + bounds-selrect (bound->selrect bounds)] + + (when (seq selected-shapes) + [:g.measurement-feedback {:pointer-events "none"} + [:& selection-guides {:selrect selected-selrect :bounds bounds :zoom zoom}] + [:& size-display {:selrect selected-selrect :zoom zoom}] + + (if (not hover-shape) + (when frame + [:g.hover-shapes + [:& distance-display {:from (:selrect frame) + :to selected-selrect + :zoom zoom + :bounds bounds-selrect}]]) + + [:g.hover-shapes + [:& selection-rect {:type :hover :selrect hover-selrect :zoom zoom}] + [:& size-display {:selrect hover-selrect :zoom zoom}] + [:& distance-display {:from hover-selrect :to selected-selrect :zoom zoom :bounds bounds-selrect}]])]))) + + diff --git a/frontend/src/app/main/ui/viewer/handoff/selection_feedback.cljs b/frontend/src/app/main/ui/viewer/handoff/selection_feedback.cljs index 116ea6da5..01bbae2a6 100644 --- a/frontend/src/app/main/ui/viewer/handoff/selection_feedback.cljs +++ b/frontend/src/app/main/ui/viewer/handoff/selection_feedback.cljs @@ -16,36 +16,17 @@ [app.common.math :as mth] [app.common.geom.shapes :as gsh] [app.common.geom.point :as gpt] - [app.main.store :as st])) + [app.main.store :as st] + [app.main.ui.measurements :refer [selection-guides size-display measurement]])) ;; ------------------------------------------------ ;; CONSTANTS ;; ------------------------------------------------ (def select-color "#1FDEA7") -(def hover-color "#DB00FF") -(def hover-color-text "#FFF") -(def font-size 10) - (def selection-rect-width 1) - (def select-guide-width 1) (def select-guide-dasharray 5) -(def hover-guide-width 1) - -(def size-display-color "#FFF") -(def size-display-opacity 0.7) -(def size-display-text-color "#000") -(def size-display-width-min 50) -(def size-display-width-max 75) -(def size-display-height 16) - -(def distance-color "#DB00FF") -(def distance-text-color "#FFF") -(def distance-border-radius 2) -(def distance-pill-width 40) -(def distance-pill-height 16) -(def distance-line-stroke 1) ;; ------------------------------------------------ ;; LENSES @@ -87,182 +68,28 @@ :width (:width frame) :height (:height frame)}) -(defn calculate-guides - "Calculates coordinates for the selection guides" - [frame selrect] - (let [{frame-width :width frame-height :height} frame - {:keys [x y width height]} selrect] - [[0 y frame-width y] - [0 (+ y height) frame-width (+ y height)] - [x 0 x frame-height] - [(+ x width) 0 (+ x width) frame-height]])) - -(defn calculate-distance-lines - "Given a start/end from two shapes gives the distance lines" - [from-s from-e to-s to-e] - (let [ss (- to-s from-s) - se (- to-e from-s) - es (- to-s from-e) - ee (- to-e from-e)] - (cond-> [] - (or (and (neg? ss) (pos? se)) - (and (pos? ss) (neg? ee)) - (and (neg? ss) (> ss se))) - (conj [ from-s (+ from-s ss) ]) - - (or (and (neg? se) (<= ss se))) - (conj [ from-s (+ from-s se) ]) - - (or (and (pos? es) (<= es ee))) - (conj [ from-e (+ from-e es) ]) - - (or (and (pos? ee) (neg? es)) - (and (neg? ee) (pos? ss)) - (and (pos? ee) (< ee es))) - (conj [ from-e (+ from-e ee) ])))) - ;; ------------------------------------------------ ;; COMPONENTS ;; ------------------------------------------------ -(mf/defc selection-guides [{:keys [frame selrect zoom]}] - [:g.selection-guides - (for [[x1 y1 x2 y2] (calculate-guides frame selrect)] - [:line {:x1 x1 - :y1 y1 - :x2 x2 - :y2 y2 - :style {:stroke select-color - :stroke-width (/ select-guide-width zoom) - :stroke-dasharray (/ select-guide-dasharray zoom)}}])]) - -(mf/defc selection-rect [{:keys [type frame selrect zoom]}] +(mf/defc selection-rect [{:keys [frame selrect zoom]}] (let [{:keys [x y width height]} selrect - stroke-color (case type - :selection select-color - :hover hover-color)] + selection-rect-width (/ selection-rect-width zoom)] [:g.selection-rect [:rect {:x x :y y :width width :height height :style {:fill "transparent" - :stroke stroke-color - :stroke-width (/ selection-rect-width zoom)}}]])) - -(mf/defc size-display [{:keys [type selrect zoom]}] - (let [{:keys [x y width height]} selrect - size-label (str/fmt "%s x %s" (mth/round width) (mth/round height)) - - rect-height (/ size-display-height zoom) - rect-width (/ (if (<= (count size-label) 9) - size-display-width-min - size-display-width-max) - zoom) - text-padding (/ 4 zoom)] - [:g.size-display - [:rect {:x (+ x (/ width 2) (- (/ rect-width 2))) - :y (- (+ y height) rect-height) - :width rect-width - :height rect-height - :style {:fill size-display-color - :fill-opacity size-display-opacity}}] - - [:text {:x (+ (+ x (/ width 2) (- (/ rect-width 2))) (/ rect-width 2)) - :y (- (+ y height (+ text-padding (/ rect-height 2))) rect-height) - :width rect-width - :height rect-height - :text-anchor "middle" - :style {:fill size-display-text-color - :font-size (/ font-size zoom)}} - size-label]])) - -(mf/defc distance-display-pill [{:keys [x y zoom distance frame]}] - (let [distance-pill-width (/ distance-pill-width zoom) - distance-pill-height (/ distance-pill-height zoom) - distance-line-stroke (/ distance-line-stroke zoom) - font-size (/ font-size zoom) - text-padding (/ 3 zoom) - distance-border-radius (/ distance-border-radius zoom) - - {frame-width :width frame-height :height} frame - - rect-x (- x (/ distance-pill-width 2)) - rect-y (- y (/ distance-pill-height 2)) - - text-x x - text-y (+ y text-padding) - - offset-x (cond (< rect-x 0) (- rect-x) - (> (+ rect-x distance-pill-width) frame-width) (- frame-width (+ rect-x distance-pill-width)) - :else 0) - - offset-y (cond (< rect-y 0) (- rect-y) - (> (+ rect-y distance-pill-height) frame-height) (- frame-height (+ rect-y distance-pill-height)) - :else 0) - - ] - [:g.distance-pill - [:rect {:x (+ rect-x offset-x) - :y (+ rect-y offset-y) - :rx distance-border-radius - :ry distance-border-radius - :width distance-pill-width - :height distance-pill-height - :style {:fill distance-color}}] - - [:text {:x (+ text-x offset-x) - :y (+ text-y offset-y) - :rx distance-border-radius - :ry distance-border-radius - :text-anchor "middle" - :width distance-pill-width - :height distance-pill-height - :style {:fill distance-text-color - :font-size font-size}} - distance]]) - ) - -(mf/defc distance-display [{:keys [type from to zoom frame]}] - (let [fixed-x (if (gsh/fully-contained? from to) - (+ (:x to) (/ (:width to) 2)) - (+ (:x from) (/ (:width from) 2))) - fixed-y (if (gsh/fully-contained? from to) - (+ (:y to) (/ (:height to) 2)) - (+ (:y from) (/ (:height from) 2))) - - v-lines (->> (calculate-distance-lines (:y1 from) (:y2 from) (:y1 to) (:y2 to)) - (map (fn [[start end]] [fixed-x start fixed-x end]))) - - h-lines (->> (calculate-distance-lines (:x1 from) (:x2 from) (:x1 to) (:x2 to)) - (map (fn [[start end]] [start fixed-y end fixed-y]))) - - lines (d/concat [] v-lines h-lines)] - - (for [[x1 y1 x2 y2] lines] - (let [center-x (+ x1 (/ (- x2 x1) 2)) - center-y (+ y1 (/ (- y2 y1) 2)) - distance (gpt/distance (gpt/point x1 y1) (gpt/point x2 y2))] - [:g.distance-line {:key (str "line-%s-%s-%s-%s" x1 y1 x2 y2)} - [:line - {:x1 x1 - :y1 y1 - :x2 x2 - :y2 y2 - :style {:stroke distance-color - :stroke-width distance-line-stroke}}] - - [:& distance-display-pill - {:x center-x - :y center-y - :zoom zoom - :distance (str (mth/round distance) "px") - :frame frame}]])))) + :stroke select-color + :stroke-width selection-rect-width}}]])) (mf/defc selection-feedback [{:keys [frame]}] (let [zoom (mf/deref selected-zoom) + hover-shapes-ref (mf/use-memo (make-hover-shapes-iref)) - hover-shape (mf/deref hover-shapes-ref) + hover-shape (-> (mf/deref hover-shapes-ref) + (gsh/translate-to-frame frame)) selected-shapes-ref (mf/use-memo (make-selected-shapes-iref)) selected-shapes (->> (mf/deref selected-shapes-ref) @@ -271,19 +98,13 @@ selrect (gsh/selection-rect selected-shapes)] (when (seq selected-shapes) - [:g.measurement-feedback {:pointer-events "none"} + [:g.selection-feedback {:pointer-events "none"} [:g.selected-shapes [:& selection-guides {:selrect selrect :frame frame :zoom zoom}] - [:& selection-rect {:type :selection :selrect selrect :zoom zoom}] + [:& selection-rect {:selrect selrect :zoom zoom}] [:& size-display {:selrect selrect :zoom zoom}]] - (if (and (not-empty selected-shapes) (not hover-shape)) - [:g.hover-shapes - [:& distance-display {:from (frame->selrect frame) :to selrect :zoom zoom :frame frame}]] - - (let [hover-selrect (-> hover-shape (gsh/translate-to-frame frame) :selrect)] - [:g.hover-shapes - [:& selection-rect {:type :hover :selrect hover-selrect :zoom zoom}] - [:& size-display {:selrect hover-selrect :zoom zoom}] - [:& distance-display {:from hover-selrect :to selrect :zoom zoom :frame frame}]]))]))) - + [:& measurement {:bounds frame + :selected-shapes selected-shapes + :hover-shape hover-shape + :zoom zoom}]]))) diff --git a/frontend/src/app/main/ui/workspace/selection.cljs b/frontend/src/app/main/ui/workspace/selection.cljs index eda6c1888..4c149c3cb 100644 --- a/frontend/src/app/main/ui/workspace/selection.cljs +++ b/frontend/src/app/main/ui/workspace/selection.cljs @@ -15,6 +15,8 @@ [potok.core :as ptk] [rumext.alpha :as mf] [rumext.util :refer [map->obj]] + [app.common.uuid :as uuid] + [app.util.data :as d] [app.main.data.workspace :as dw] [app.main.data.workspace.common :as dwc] [app.main.refs :as refs] @@ -28,7 +30,8 @@ [app.common.geom.point :as gpt] [app.common.geom.matrix :as gmt] [app.util.debug :refer [debug?]] - [app.main.ui.workspace.shapes.outline :refer [outline]])) + [app.main.ui.workspace.shapes.outline :refer [outline]] + [app.main.ui.measurements :as msr])) (def rotation-handler-size 25) (def resize-point-radius 4) @@ -138,8 +141,7 @@ [:circle {:r (/ resize-point-radius zoom) :style {:fillOpacity "1" :strokeWidth "1px" - :vectorEffect "non-scaling-stroke" - } + :vectorEffect "non-scaling-stroke"} :fill "#FFFFFF" :stroke (if (and (= position :bottom-right) overflow-text) "red" color) :cx cx' @@ -266,9 +268,16 @@ :fill "transparent"}}]])) (mf/defc multiple-selection-handlers - [{:keys [shapes selected zoom color] :as props}] + [{:keys [shapes selected zoom color show-distances] :as props}] (let [shape (geom/selection-rect shapes) shape-center (geom/center shape) + + hover-id (-> (mf/deref refs/current-hover) first) + hover-id (when-not (d/seek #(= hover-id (:id %)) shapes) hover-id) + hover-shape (mf/deref (refs/object-by-id hover-id)) + + vbox (mf/deref refs/vbox) + on-resize (fn [current-position initial-position event] (dom/stop-propagation event) (st/emit! (dw/start-resize current-position initial-position selected shape))) @@ -282,13 +291,29 @@ :color color :on-resize on-resize :on-rotate on-rotate}] + + (when show-distances + [:& msr/measurement {:bounds vbox + :selected-shapes shapes + :hover-shape hover-shape + :zoom zoom}]) + (when (debug? :selection-center) [:circle {:cx (:x shape-center) :cy (:y shape-center) :r 5 :fill "yellow"}])])) (mf/defc single-selection-handlers - [{:keys [shape zoom color] :as props}] + [{:keys [shape zoom color show-distances] :as props}] (let [shape-id (:id shape) shape (geom/transform-shape shape) + + frame (mf/deref (refs/object-by-id (:frame-id shape))) + frame (when-not (= (:id frame) uuid/zero) frame) + vbox (mf/deref refs/vbox) + + hover-id (-> (mf/deref refs/current-hover) first) + hover-id (when-not (= shape-id hover-id) hover-id) + hover-shape (mf/deref (refs/object-by-id hover-id)) + shape' (if (debug? :simple-selection) (geom/selection-rect [shape]) shape) on-resize (fn [current-position initial-position event] (dom/stop-propagation event) @@ -303,10 +328,17 @@ :zoom zoom :color color :on-rotate on-rotate - :on-resize on-resize}]])) + :on-resize on-resize}] + + (when show-distances + [:& msr/measurement {:bounds vbox + :frame frame + :selected-shapes [shape] + :hover-shape hover-shape + :zoom zoom}])])) (mf/defc selection-handlers - [{:keys [selected edition zoom] :as props}] + [{:keys [selected edition zoom show-distances] :as props}] (let [;; We need remove posible nil values because on shape ;; deletion many shape will reamin selected and deleted ;; in the same time for small instant of time @@ -326,7 +358,8 @@ [:& multiple-selection-handlers {:shapes shapes :selected selected :zoom zoom - :color color}] + :color color + :show-distances show-distances}] (and (= type :text) (= edition (:id shape))) @@ -343,4 +376,5 @@ :else [:& single-selection-handlers {:shape shape :zoom zoom - :color color}]))) + :color color + :show-distances show-distances}]))) diff --git a/frontend/src/app/main/ui/workspace/snap_distances.cljs b/frontend/src/app/main/ui/workspace/snap_distances.cljs index fc7f00f3c..a2559c01b 100644 --- a/frontend/src/app/main/ui/workspace/snap_distances.cljs +++ b/frontend/src/app/main/ui/workspace/snap_distances.cljs @@ -216,7 +216,7 @@ (filter #(show-distance? (distance-to-selrect %))) (map #(vector selrect (:selrect %)))) - segments-to-display (concat other-shapes-segments selection-segments)] + segments-to-display (d/concat #{} other-shapes-segments selection-segments)] (mf/use-effect (fn [] diff --git a/frontend/src/app/main/ui/workspace/snap_points.cljs b/frontend/src/app/main/ui/workspace/snap_points.cljs index b0934c370..480d1d57c 100644 --- a/frontend/src/app/main/ui/workspace/snap_points.cljs +++ b/frontend/src/app/main/ui/workspace/snap_points.cljs @@ -116,8 +116,9 @@ ;; can cause problems with react keys snap-points (into #{} (mapcat add-point-to-snaps) @state) - snap-lines (into (process-snap-lines @state :x) - (process-snap-lines @state :y))] + snap-lines (->> (into (process-snap-lines @state :x) + (process-snap-lines @state :y)) + (into #{}))] (mf/use-effect (fn [] diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 8f9d77ae2..402399bd6 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -210,6 +210,7 @@ (assoc :modifiers (:modifiers local)) (gsh/transform-shape)) + alt? (mf/use-state false) viewport-ref (mf/use-ref nil) zoom-view-ref (mf/use-ref nil) last-position (mf/use-var nil) @@ -498,6 +499,7 @@ (timers/schedule #(st/emit! (dw/initialize-viewport size)))))) (mf/use-layout-effect (mf/deps layout) on-resize) + (hooks/use-stream ms/keyboard-alt #(reset! alt? %)) [:* (when picking-color? @@ -513,9 +515,7 @@ :zoom (:zoom local) :drawing drawing :page-id page-id - :file-id (:id file)} - ]) - + :file-id (:id file)}]) [:svg.viewport {:preserveAspectRatio "xMidYMid meet" @@ -569,7 +569,8 @@ (when (seq selected) [:& selection-handlers {:selected selected :zoom zoom - :edition edition}]) + :edition edition + :show-distances (and (not (:transform local)) @alt?)}]) (when (= (count selected) 1) [:& gradient-handlers {:id (first selected)