From ed9400912c1c868c4c5f32f614c1ec08001af16f Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 2 Mar 2022 15:50:06 +0100 Subject: [PATCH] :sparkles: Fix problems with extreme values --- common/src/app/common/geom/matrix.cljc | 9 ++- common/src/app/common/geom/point.cljc | 12 ++-- common/src/app/common/geom/shapes.cljc | 10 ++-- common/src/app/common/geom/shapes/common.cljc | 3 +- common/src/app/common/geom/shapes/rect.cljc | 8 --- .../app/common/geom/shapes/transforms.cljc | 54 ++++++++--------- common/src/app/common/math.cljc | 6 +- common/src/app/common/pages/init.cljc | 16 ++--- common/test/app/common/geom_shapes_test.cljc | 20 +++---- .../styles/main/partials/workspace.scss | 7 ++- .../src/app/main/data/workspace/comments.cljs | 5 +- .../app/main/data/workspace/drawing/box.cljs | 12 ++-- .../main/data/workspace/drawing/common.cljs | 44 +++++++------- .../app/main/data/workspace/svg_upload.cljs | 1 - .../app/main/data/workspace/transforms.cljs | 5 +- frontend/src/app/main/snap.cljs | 26 +++++--- .../main/ui/components/editable_select.cljs | 17 +++--- .../app/main/ui/components/numeric_input.cljs | 22 +++---- frontend/src/app/main/ui/formats.cljs | 36 +++++++++++ frontend/src/app/main/ui/measurements.cljs | 7 ++- .../src/app/main/ui/shapes/text/styles.cljs | 2 +- .../ui/viewer/handoff/attributes/common.cljs | 5 +- .../ui/viewer/handoff/attributes/layout.cljs | 21 ++++--- .../ui/viewer/handoff/attributes/stroke.cljs | 3 +- .../ui/viewer/handoff/attributes/svg.cljs | 4 -- frontend/src/app/main/ui/viewer/header.cljs | 6 +- .../app/main/ui/workspace/colorpalette.cljs | 7 +-- .../workspace/colorpicker/color_inputs.cljs | 12 ++-- .../ui/workspace/colorpicker/harmony.cljs | 26 ++++---- .../main/ui/workspace/colorpicker/ramp.cljs | 6 +- .../colorpicker/slider_selector.cljs | 12 ++-- .../src/app/main/ui/workspace/header.cljs | 6 +- .../app/main/ui/workspace/left_toolbar.cljs | 5 +- frontend/src/app/main/ui/workspace/nudge.cljs | 4 +- .../main/ui/workspace/shapes/path/editor.cljs | 4 +- .../app/main/ui/workspace/shapes/text.cljs | 2 +- .../sidebar/options/menus/frame_grid.cljs | 8 +-- .../sidebar/options/menus/layer.cljs | 4 +- .../sidebar/options/menus/measures.cljs | 15 ++--- .../sidebar/options/menus/typography.cljs | 2 - .../sidebar/options/rows/color_row.cljs | 4 +- .../sidebar/options/rows/stroke_row.cljs | 1 - .../src/app/main/ui/workspace/viewport.cljs | 1 + .../ui/workspace/viewport/frame_grid.cljs | 9 ++- .../main/ui/workspace/viewport/gradients.cljs | 8 +-- .../main/ui/workspace/viewport/guides.cljs | 4 +- .../ui/workspace/viewport/interactions.cljs | 11 ++-- .../app/main/ui/workspace/viewport/rules.cljs | 15 ++--- .../ui/workspace/viewport/scroll_bars.cljs | 11 ++-- .../main/ui/workspace/viewport/selection.cljs | 60 +++++++++++-------- .../ui/workspace/viewport/snap_distances.cljs | 27 ++++----- .../ui/workspace/viewport/snap_points.cljs | 34 ++++++----- .../viewport/thumbnail_renderer.cljs | 17 ++++-- .../app/main/ui/workspace/viewport/utils.cljs | 6 +- .../main/ui/workspace/viewport/widgets.cljs | 4 +- frontend/src/app/util/code_gen.cljs | 3 +- frontend/src/app/util/path/tools.cljs | 5 +- frontend/src/app/util/perf.cljs | 2 +- frontend/src/debug.cljs | 3 +- 59 files changed, 359 insertions(+), 340 deletions(-) create mode 100644 frontend/src/app/main/ui/formats.cljs diff --git a/common/src/app/common/geom/matrix.cljc b/common/src/app/common/geom/matrix.cljc index ed9d8bf0f..f07363d61 100644 --- a/common/src/app/common/geom/matrix.cljc +++ b/common/src/app/common/geom/matrix.cljc @@ -108,9 +108,12 @@ (= v base)) (defn translate-matrix - [{x :x y :y :as pt}] - (assert (gpt/point? pt)) - (Matrix. 1 0 0 1 x y)) + ([{x :x y :y :as pt}] + (assert (gpt/point? pt)) + (Matrix. 1 0 0 1 x y)) + + ([x y] + (translate-matrix (gpt/point x y)))) (defn scale-matrix ([pt center] diff --git a/common/src/app/common/geom/point.cljc b/common/src/app/common/geom/point.cljc index c2b81b248..b93b31a91 100644 --- a/common/src/app/common/geom/point.cljc +++ b/common/src/app/common/geom/point.cljc @@ -132,9 +132,8 @@ (assert (point? other)) (let [dx (- x ox) dy (- y oy)] - (-> (mth/sqrt (+ (mth/pow dx 2) - (mth/pow dy 2))) - (mth/precision 6)))) + (mth/sqrt (+ (mth/pow dx 2) + (mth/pow dy 2))))) (defn length [{x :x y :y :as p}] @@ -168,8 +167,7 @@ (* y oy)) (* length-p length-other)) a (mth/acos (if (< a -1) -1 (if (> a 1) 1 a))) - d (-> (mth/degrees a) - (mth/precision 6))] + d (mth/degrees a)] (if (mth/nan? d) 0 d))))) (defn angle-sign [v1 v2] @@ -195,7 +193,9 @@ (defn round "Change the precision of the point coordinates." - ([point] (round point 0)) + ([point] + (round point 0)) + ([{:keys [x y] :as p} decimals] (assert (point? p)) (assert (number? decimals)) diff --git a/common/src/app/common/geom/shapes.cljc b/common/src/app/common/geom/shapes.cljc index 412e0b44f..ed5bdd233 100644 --- a/common/src/app/common/geom/shapes.cljc +++ b/common/src/app/common/geom/shapes.cljc @@ -106,12 +106,12 @@ :width (- x2 x1) :height (- y2 y1) :type :rect})) - {frame-x1 :x1 frame-x2 :x2 frame-y1 :y1 frame-y2 :y2} bounds + {bound-x1 :x1 bound-x2 :x2 bound-y1 :y1 bound-y2 :y2} bounds {sr-x1 :x1 sr-x2 :x2 sr-y1 :y1 sr-y2 :y2} selrect] - {:left (make-selrect frame-x1 sr-y1 (- sr-x1 2) sr-y2) - :top (make-selrect sr-x1 frame-y1 sr-x2 (- sr-y1 2)) - :right (make-selrect (+ sr-x2 2) sr-y1 frame-x2 sr-y2) - :bottom (make-selrect sr-x1 (+ sr-y2 2) sr-x2 frame-y2)})) + {:left (make-selrect bound-x1 sr-y1 sr-x1 sr-y2) + :top (make-selrect sr-x1 bound-y1 sr-x2 sr-y1) + :right (make-selrect sr-x2 sr-y1 bound-x2 sr-y2) + :bottom (make-selrect sr-x1 sr-y2 sr-x2 bound-y2)})) (defn distance-selrect [selrect other] (let [{:keys [x1 y1]} other diff --git a/common/src/app/common/geom/shapes/common.cljc b/common/src/app/common/geom/shapes/common.cljc index 0cd9d4704..9134186f2 100644 --- a/common/src/app/common/geom/shapes/common.cljc +++ b/common/src/app/common/geom/shapes/common.cljc @@ -7,8 +7,7 @@ (ns app.common.geom.shapes.common (:require [app.common.geom.matrix :as gmt] - [app.common.geom.point :as gpt] - [app.common.math :as mth])) + [app.common.geom.point :as gpt])) (defn center-rect [{:keys [x y width height]}] diff --git a/common/src/app/common/geom/shapes/rect.cljc b/common/src/app/common/geom/shapes/rect.cljc index 740c91677..293e98ff9 100644 --- a/common/src/app/common/geom/shapes/rect.cljc +++ b/common/src/app/common/geom/shapes/rect.cljc @@ -7,7 +7,6 @@ (ns app.common.geom.shapes.rect (:require [app.common.geom.point :as gpt] - [app.common.geom.shapes.common :as gco] [app.common.math :as mth])) (defn rect->points [{:keys [x y width height]}] @@ -130,10 +129,3 @@ (>= (:y1 sr2) (:y1 sr1)) (<= (:y2 sr2) (:y2 sr1)))) -(defn round-selrect - [selrect] - (-> selrect - (update :x mth/round) - (update :y mth/round) - (update :width mth/round) - (update :height mth/round))) diff --git a/common/src/app/common/geom/shapes/transforms.cljc b/common/src/app/common/geom/shapes/transforms.cljc index 0cd7a31af..8bb74240f 100644 --- a/common/src/app/common/geom/shapes/transforms.cljc +++ b/common/src/app/common/geom/shapes/transforms.cljc @@ -249,8 +249,8 @@ ;; This rectangle is the new data for the current rectangle. We want to change our rectangle ;; to have this width, height, x, y - new-width (max 1 (:width points-temp-dim)) - new-height (max 1 (:height points-temp-dim)) + new-width (max 0.01 (:width points-temp-dim)) + new-height (max 0.01 (:height points-temp-dim)) selrect (gco/make-centered-selrect center new-width new-height) rect-points (gpr/rect->points selrect) @@ -263,7 +263,7 @@ (defn- apply-transform "Given a new set of points transformed, set up the rectangle so it keeps its properties. We adjust de x,y,width,height and create a custom transform" - [shape transform-mtx round-coords?] + [shape transform-mtx] (let [points' (:points shape) points (gco/transform-points points' transform-mtx) @@ -276,8 +276,8 @@ [(gpr/points->selrect points) nil nil] (adjust-rotated-transform shape points)) - selrect (cond-> selrect - round-coords? gpr/round-selrect) + ;;selrect (cond-> selrect + ;; round-coords? gpr/round-selrect) ;; Redondear los points? base-rotation (or (:rotation shape) 0) @@ -345,7 +345,7 @@ ;; need to remove the flip flags (assoc :flip-x false) (assoc :flip-y false) - (apply-transform (gmt/matrix) true)))) + (apply-transform (gmt/matrix))))) (defn update-mask-selrect [masked-group children] @@ -525,7 +525,6 @@ (d/parse-double) (* (get-in modifiers [:resize-vector :x] 1)) (* (get-in modifiers [:resize-vector-2 :x] 1)) - (mth/precision 2) (str))] (attrs/merge attrs {:font-size font-size})))] (update shape :content #(txt/transform-nodes @@ -535,35 +534,32 @@ shape)) (defn apply-modifiers - [shape modifiers round-coords?] + [shape modifiers] (let [center (gco/center-shape shape) transform (modifiers->transform center modifiers)] - (apply-transform shape transform round-coords?))) + (apply-transform shape transform))) (defn transform-shape - ([shape] - (transform-shape shape nil)) + [shape] + (let [modifiers (:modifiers shape)] + (cond + (nil? modifiers) + shape - ([shape {:keys [round-coords?] :or {round-coords? true}}] - (let [modifiers (:modifiers shape)] - (cond - (nil? modifiers) - shape + (empty-modifiers? modifiers) + (dissoc shape :modifiers) - (empty-modifiers? modifiers) - (dissoc shape :modifiers) + :else + (let [shape (apply-displacement shape) + modifiers (:modifiers shape)] + (cond-> shape + (not (empty-modifiers? modifiers)) + (-> (set-flip modifiers) + (apply-modifiers modifiers) + (apply-text-resize modifiers)) - :else - (let [shape (apply-displacement shape) - modifiers (:modifiers shape)] - (cond-> shape - (not (empty-modifiers? modifiers)) - (-> (set-flip modifiers) - (apply-modifiers modifiers round-coords?) - (apply-text-resize modifiers)) - - :always - (dissoc :modifiers))))))) + :always + (dissoc :modifiers)))))) (defn transform-selrect [selrect {:keys [displacement resize-transform-inverse resize-vector resize-origin resize-vector-2 resize-origin-2]}] diff --git a/common/src/app/common/math.cljc b/common/src/app/common/math.cljc index 6b61b3d73..d695504c4 100644 --- a/common/src/app/common/math.cljc +++ b/common/src/app/common/math.cljc @@ -115,7 +115,7 @@ (defn precision [v n] - (when (and (number? v) (number? n)) + (when (and (number? v) (integer? n)) (let [d (pow 10 n)] (/ (round (* v d)) d)))) @@ -165,3 +165,7 @@ [v0 v1 t] (+ (* (- 1 t) v0) (* t v1))) + +(defn max-abs + [a b] + (max (abs a) (abs b))) diff --git a/common/src/app/common/pages/init.cljc b/common/src/app/common/pages/init.cljc index 10bfba88b..8107c17cb 100644 --- a/common/src/app/common/pages/init.cljc +++ b/common/src/app/common/pages/init.cljc @@ -91,8 +91,8 @@ (def empty-selrect {:x 0 :y 0 :x1 0 :y1 0 - :x2 1 :y2 1 - :width 1 :height 1}) + :x2 0.01 :y2 0.01 + :width 0.01 :height 0.01}) (defn make-minimal-shape [type] @@ -111,16 +111,16 @@ (not= :path (:type shape)) (assoc :x 0 :y 0 - :width 1 - :height 1 + :width 0.01 + :height 0.01 :selrect {:x 0 :y 0 :x1 0 :y1 0 - :x2 1 - :y2 1 - :width 1 - :height 1})))) + :x2 0.01 + :y2 0.01 + :width 0.01 + :height 0.01})))) (defn make-minimal-group [frame-id selection-rect group-name] diff --git a/common/test/app/common/geom_shapes_test.cljc b/common/test/app/common/geom_shapes_test.cljc index a7b190e00..fd486d7a6 100644 --- a/common/test/app/common/geom_shapes_test.cljc +++ b/common/test/app/common/geom_shapes_test.cljc @@ -9,7 +9,7 @@ [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] - [app.common.math :refer [close?]] + [app.common.math :as mth] [app.common.pages :refer [make-minimal-shape]] [clojure.test :as t])) @@ -52,7 +52,7 @@ (t/testing "Shape without modifiers should stay the same" (t/are [type] (let [shape-before (create-test-shape type) - shape-after (gsh/transform-shape shape-before {:round-coords? false})] + shape-after (gsh/transform-shape shape-before)] (= shape-before shape-after)) :rect :path)) @@ -61,7 +61,7 @@ (t/are [type] (let [modifiers {:displacement (gmt/translate-matrix (gpt/point 10 -10))}] (let [shape-before (create-test-shape type {:modifiers modifiers}) - shape-after (gsh/transform-shape shape-before {:round-coords? false})] + shape-after (gsh/transform-shape shape-before)] (t/is (not= shape-before shape-after)) (t/is (close? (get-in shape-before [:selrect :x]) @@ -82,7 +82,7 @@ (t/are [type] (let [modifiers {:displacement (gmt/matrix)} shape-before (create-test-shape type {:modifiers modifiers}) - shape-after (gsh/transform-shape shape-before {:round-coords? false})] + shape-after (gsh/transform-shape shape-before)] (t/are [prop] (t/is (close? (get-in shape-before [:selrect prop]) (get-in shape-after [:selrect prop]))) @@ -95,7 +95,7 @@ :resize-vector (gpt/point 2 2) :resize-transform (gmt/matrix)} shape-before (create-test-shape type {:modifiers modifiers}) - shape-after (gsh/transform-shape shape-before {:round-coords? false})] + shape-after (gsh/transform-shape shape-before)] (t/is (not= shape-before shape-after)) (t/is (close? (get-in shape-before [:selrect :x]) @@ -117,7 +117,7 @@ :resize-vector (gpt/point 1 1) :resize-transform (gmt/matrix)} shape-before (create-test-shape type {:modifiers modifiers}) - shape-after (gsh/transform-shape shape-before {:round-coords? false})] + shape-after (gsh/transform-shape shape-before)] (t/are [prop] (t/is (close? (get-in shape-before [:selrect prop]) (get-in shape-after [:selrect prop]))) @@ -130,7 +130,7 @@ :resize-vector (gpt/point 0 0) :resize-transform (gmt/matrix)} shape-before (create-test-shape type {:modifiers modifiers}) - shape-after (gsh/transform-shape shape-before {:round-coords? false})] + shape-after (gsh/transform-shape shape-before)] (t/is (> (get-in shape-before [:selrect :width]) (get-in shape-after [:selrect :width]))) (t/is (> (get-in shape-after [:selrect :width]) 0)) @@ -144,7 +144,7 @@ (t/are [type] (let [modifiers {:rotation 30} shape-before (create-test-shape type {:modifiers modifiers}) - shape-after (gsh/transform-shape shape-before {:round-coords? false})] + shape-after (gsh/transform-shape shape-before)] (t/is (not= shape-before shape-after)) @@ -168,7 +168,7 @@ (t/are [type] (let [modifiers {:rotation 0} shape-before (create-test-shape type {:modifiers modifiers}) - shape-after (gsh/transform-shape shape-before {:round-coords? false})] + shape-after (gsh/transform-shape shape-before)] (t/are [prop] (t/is (close? (get-in shape-before [:selrect prop]) (get-in shape-after [:selrect prop]))) @@ -180,7 +180,7 @@ (let [modifiers {:displacement (gmt/matrix)} shape-before (-> (create-test-shape type {:modifiers modifiers}) (assoc :selrect selrect)) - shape-after (gsh/transform-shape shape-before {:round-coords? false})] + shape-after (gsh/transform-shape shape-before)] (= (:selrect shape-before) (:selrect shape-after))) diff --git a/frontend/resources/styles/main/partials/workspace.scss b/frontend/resources/styles/main/partials/workspace.scss index 7cead65b3..48b943526 100644 --- a/frontend/resources/styles/main/partials/workspace.scss +++ b/frontend/resources/styles/main/partials/workspace.scss @@ -241,12 +241,13 @@ $height-palette-max: 80px; position: relative; .viewport-overlays { + cursor: initial; + height: 100%; + overflow: hidden; + pointer-events: none; position: absolute; width: 100%; - height: 100%; z-index: 10; - pointer-events: none; - cursor: initial; .pixel-overlay { height: 100%; diff --git a/frontend/src/app/main/data/workspace/comments.cljs b/frontend/src/app/main/data/workspace/comments.cljs index c3a7f572e..b7f9f2030 100644 --- a/frontend/src/app/main/data/workspace/comments.cljs +++ b/frontend/src/app/main/data/workspace/comments.cljs @@ -6,7 +6,6 @@ (ns app.main.data.workspace.comments (:require - [app.common.math :as mth] [app.common.spec :as us] [app.main.data.comments :as dcm] [app.main.data.workspace :as dw] @@ -78,8 +77,8 @@ (fn [{:keys [vbox zoom] :as local}] (let [pw (/ 160 zoom) ph (/ 160 zoom) - nw (mth/round (- (/ (:width vbox) 2) pw)) - nh (mth/round (- (/ (:height vbox) 2) ph)) + nw (- (/ (:width vbox) 2) pw) + nh (- (/ (:height vbox) 2) ph) nx (- (:x position) nw) ny (- (:y position) nh)] (update local :vbox assoc :x nx :y ny))))))) diff --git a/frontend/src/app/main/data/workspace/drawing/box.cljs b/frontend/src/app/main/data/workspace/drawing/box.cljs index f8c9a7592..f2dd60954 100644 --- a/frontend/src/app/main/data/workspace/drawing/box.cljs +++ b/frontend/src/app/main/data/workspace/drawing/box.cljs @@ -27,8 +27,8 @@ shapev (gpt/point width height) deltav (gpt/to-vec initial point) scalev (-> (gpt/divide (gpt/add shapev deltav) shapev) - (update :x truncate-zero 1) - (update :y truncate-zero 1)) + (update :x truncate-zero 0.01) + (update :y truncate-zero 0.01)) scalev (if lock? (let [v (max (:x scalev) (:y scalev))] (gpt/point v v)) @@ -45,9 +45,7 @@ (defn move-drawing [{:keys [x y]}] (fn [state] - (let [x (mth/precision x 0) - y (mth/precision y 0)] - (update-in state [:workspace-drawing :object] gsh/absolute-move (gpt/point x y))))) + (update-in state [:workspace-drawing :object] gsh/absolute-move (gpt/point x y)))) (defn handle-drawing-box [] (ptk/reify ::handle-drawing-box @@ -72,7 +70,7 @@ shape (-> state (get-in [:workspace-drawing :object]) - (gsh/setup {:x (:x initial) :y (:y initial) :width 1 :height 1}) + (gsh/setup {:x (:x initial) :y (:y initial) :width 0.01 :height 0.01}) (assoc :frame-id fid) (assoc :initialized? true) (assoc :click-draw? true))] @@ -85,7 +83,7 @@ (rx/map move-drawing)) (->> ms/mouse-position - (rx/filter #(> (gpt/distance % initial) 2)) + (rx/filter #(> (gpt/distance % initial) (/ 2 zoom))) (rx/with-latest vector ms/mouse-position-shift) (rx/switch-map (fn [[point :as current]] diff --git a/frontend/src/app/main/data/workspace/drawing/common.cljs b/frontend/src/app/main/data/workspace/drawing/common.cljs index 624bbf308..d43c54f96 100644 --- a/frontend/src/app/main/data/workspace/drawing/common.cljs +++ b/frontend/src/app/main/data/workspace/drawing/common.cljs @@ -6,8 +6,9 @@ (ns app.main.data.workspace.drawing.common (:require - [app.common.geom.point :as gpt] + [app.common.geom.matrix :as gmt] [app.common.geom.shapes :as gsh] + [app.common.math :as mth] [app.main.data.workspace.common :as dwc] [app.main.data.workspace.undo :as dwu] [app.main.worker :as uw] @@ -29,27 +30,30 @@ (rx/concat (when (:initialized? shape) (let [page-id (:current-page-id state) - shape-click-width (case (:type shape) - :text 3 - 20) - shape-click-height (case (:type shape) - :text 16 - 20) - shape (if (:click-draw? shape) - (-> shape - (assoc-in [:modifiers :resize-vector] - (gpt/point shape-click-width shape-click-height)) - (assoc-in [:modifiers :resize-origin] - (gpt/point (:x shape) (:y shape)))) - shape) - shape (cond-> shape - (= (:type shape) :text) (assoc :grow-type - (if (:click-draw? shape) :auto-width :fixed))) + click-draw? (:click-draw? shape) + text? (= :text (:type shape)) - shape (-> shape - (gsh/transform-shape) - (dissoc :initialized? :click-draw?))] + min-side (min 100 + (mth/floor (get-in state [:workspace-local :vbox :width])) + (mth/floor (get-in state [:workspace-local :vbox :height]))) + + shape + (cond-> shape + (and click-draw? (not text?)) + (-> (assoc :width min-side :height min-side) + (assoc-in [:modifiers :displacement] + (gmt/translate-matrix (- (/ min-side 2)) (- (/ min-side 2))))) + + (and click-draw? text?) + (assoc :height 17 :width 4 :grow-type :auto-width) + + click-draw? + (gsh/setup-selrect) + + :always + (-> (gsh/transform-shape) + (dissoc :initialized? :click-draw?)))] ;; Add & select the created shape to the workspace (rx/concat (if (= :text (:type shape)) diff --git a/frontend/src/app/main/data/workspace/svg_upload.cljs b/frontend/src/app/main/data/workspace/svg_upload.cljs index 0495075eb..1b9f108a2 100644 --- a/frontend/src/app/main/data/workspace/svg_upload.cljs +++ b/frontend/src/app/main/data/workspace/svg_upload.cljs @@ -11,7 +11,6 @@ [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] - [app.common.math :as mth] [app.common.pages.changes-builder :as pcb] [app.common.pages.helpers :as cph] [app.common.spec :refer [max-safe-int min-safe-int]] diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index 71562c0a0..d56bcb9af 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -495,12 +495,13 @@ (watch [_ state stream] (let [initial (deref ms/mouse-position) selected (wsh/lookup-selected state {:omit-blocked? true}) - stopper (rx/filter ms/mouse-up? stream)] + stopper (rx/filter ms/mouse-up? stream) + zoom (get-in state [:workspace-local :zoom] 1)] (when-not (empty? selected) (->> ms/mouse-position (rx/map #(gpt/to-vec initial %)) (rx/map #(gpt/length %)) - (rx/filter #(> % 1)) + (rx/filter #(> % (/ 10 zoom))) (rx/take 1) (rx/with-latest vector ms/mouse-position-alt) (rx/mapcat diff --git a/frontend/src/app/main/snap.cljs b/frontend/src/app/main/snap.cljs index a78524c7e..74306e6b4 100644 --- a/frontend/src/app/main/snap.cljs +++ b/frontend/src/app/main/snap.cljs @@ -22,7 +22,7 @@ (def ^:const snap-accuracy 10) (def ^:const snap-path-accuracy 10) -(def ^:const snap-distance-accuracy 10) +(def ^:const snap-distance-accuracy 20) (defn- remove-from-snap-points [remove-snap?] @@ -82,13 +82,13 @@ ;; Otherwise the root frame is the common :else zero))) -(defn get-snap-points [page-id frame-id remove-snap? point coord] +(defn get-snap-points [page-id frame-id remove-snap? zoom point coord] (let [value (get point coord)] (->> (uw/ask! {:cmd :snaps/range-query :page-id page-id :frame-id frame-id :axis coord - :ranges [[(- value 0.5) (+ value 0.5)]]}) + :ranges [[(- value (/ 0.5 zoom)) (+ value (/ 0.5 zoom))]]}) (rx/take 1) (rx/map (remove-from-snap-points remove-snap?)) (rx/map flatten-to-points)))) @@ -238,6 +238,18 @@ (rx/map #(or % (gpt/point 0 0))) (rx/map #(gpt/add point %))))) +(defn combine-snaps-points + ([] nil) + ([p1] p1) + ([p1 p2] + (cond + (nil? p2) p1 + (nil? p1) p2 + + :else + (gpt/point (mth/max-abs (:x p1) (:x p2)) + (mth/max-abs (:y p1) (:y p2)))))) + (defn closest-snap-move [page-id shapes objects layout zoom focus movev] (let [frame-id (snap-frame-id shapes) @@ -256,7 +268,7 @@ (->> (rx/merge (closest-snap page-id frame-id shapes-points remove-snap? zoom) (when (contains? layout :dynamic-alignment) (closest-distance-snap page-id shapes objects zoom movev))) - (rx/reduce gpt/min) + (rx/reduce combine-snaps-points) (rx/map #(or % (gpt/point 0 0)))))) @@ -360,8 +372,8 @@ dy (if (not= 0 (:y snap-delta)) (- (+ (:y snap-pos) (:y snap-delta)) (:y position)) 0)] + (-> position + (update :x + dx) + (update :y + dy))) - (cond-> position - (<= (mth/abs dx) snap-accuracy) (update :x + dx) - (<= (mth/abs dy) snap-accuracy) (update :y + dy))) position)) diff --git a/frontend/src/app/main/ui/components/editable_select.cljs b/frontend/src/app/main/ui/components/editable_select.cljs index 42013291f..98a723b06 100644 --- a/frontend/src/app/main/ui/components/editable_select.cljs +++ b/frontend/src/app/main/ui/components/editable_select.cljs @@ -7,7 +7,7 @@ (ns app.main.ui.components.editable-select (:require [app.common.data :as d] - [app.common.math :as math] + [app.common.math :as mth] [app.common.uuid :as uuid] [app.main.ui.components.dropdown :refer [dropdown]] [app.main.ui.icons :as i] @@ -29,8 +29,8 @@ max-val (get params :max) num? (fn [val] (and (number? val) - (not (math/nan? val)) - (math/finite? val))) + (not (mth/nan? val)) + (mth/finite? val))) emit-blur? (mf/use-ref nil) font-size-wrapper-ref (mf/use-ref) @@ -58,8 +58,7 @@ handle-change-input (fn [event] (let [value (-> event dom/get-target dom/get-value) - value (-> (or (d/parse-double value) value) - (math/precision 2))] + value (or (d/parse-double value) value)] (set-value value))) on-node-load @@ -89,8 +88,7 @@ (when (or up? down?) (dom/prevent-default event) (let [value (-> event dom/get-target dom/get-value) - value (-> (or (d/parse-double value) value) - (math/precision 2)) + value (or (d/parse-double value) value) increment (cond (kbd/shift? event) @@ -102,8 +100,7 @@ :else (if up? 1 -1)) - new-value (-> (+ value increment) - (math/precision 2)) + new-value (+ value increment) new-value (cond (and (num? min-val) (< new-value min-val)) min-val @@ -135,7 +132,7 @@ (let [wrapper-node (mf/ref-val font-size-wrapper-ref) node (dom/get-element-by-class "checked-element is-selected" wrapper-node) nodes (dom/get-elements-by-class "checked-element-value" wrapper-node) - closest (fn [a b] (first (sort-by #(math/abs (- % b)) a))) + closest (fn [a b] (first (sort-by #(mth/abs (- % b)) a))) closest-value (str (closest options value))] (when (:is-open? @state) (if (some? node) diff --git a/frontend/src/app/main/ui/components/numeric_input.cljs b/frontend/src/app/main/ui/components/numeric_input.cljs index c2e81f837..ec178253a 100644 --- a/frontend/src/app/main/ui/components/numeric_input.cljs +++ b/frontend/src/app/main/ui/components/numeric_input.cljs @@ -6,23 +6,22 @@ (ns app.main.ui.components.numeric-input (:require + [app.main.ui.formats :as fmt] [app.common.data :as d] - [app.common.math :as math] [app.common.spec :as us] [app.util.dom :as dom] [app.util.globals :as globals] [app.util.keyboard :as kbd] [app.util.object :as obj] [app.util.simple-math :as sm] - [app.util.strings :as ust] [goog.events :as events] [rumext.alpha :as mf]) (:import goog.events.EventType)) (defn num? [val] (and (number? val) - (not (math/nan? val)) - (math/finite? val))) + (not (mth/nan? val)) + (mth/finite? val))) (mf/defc numeric-input {::mf/wrap-props false @@ -37,7 +36,6 @@ on-blur (obj/get props "onBlur") title (obj/get props "title") default-val (obj/get props "default" 0) - precision (obj/get props "precision") ;; We need a ref pointing to the input dom element, but the user ;; of this component may provide one (that is forwarded here). @@ -85,10 +83,6 @@ (sm/expr-eval value))] (when (num? new-value) (-> new-value - (cond-> (number? precision) - (math/precision precision)) - (cond-> (nil? precision) - (math/round)) (cljs.core/max us/min-safe-int) (cljs.core/min us/max-safe-int) (cond-> @@ -103,9 +97,7 @@ (mf/deps ref) (fn [new-value] (let [input-node (mf/ref-val ref)] - (dom/set-value! input-node (if (some? precision) - (ust/format-precision new-value precision) - (str new-value)))))) + (dom/set-value! input-node (fmt/format-number new-value))))) apply-value (mf/use-callback @@ -193,17 +185,17 @@ (obj/set! "className" "input-text") (obj/set! "type" "text") (obj/set! "ref" ref) - (obj/set! "defaultValue" value-str) + (obj/set! "defaultValue" (fmt/format-number value)) (obj/set! "title" title) (obj/set! "onWheel" handle-mouse-wheel) (obj/set! "onKeyDown" handle-key-down) (obj/set! "onBlur" handle-blur))] (mf/use-effect - (mf/deps value-str) + (mf/deps value) (fn [] (when-let [input-node (mf/ref-val ref)] - (dom/set-value! input-node value-str)))) + (dom/set-value! input-node (fmt/format-number value))))) (mf/use-effect (mf/deps handle-blur) diff --git a/frontend/src/app/main/ui/formats.cljs b/frontend/src/app/main/ui/formats.cljs new file mode 100644 index 000000000..18e0e2aba --- /dev/null +++ b/frontend/src/app/main/ui/formats.cljs @@ -0,0 +1,36 @@ +;; 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/. +;; +;; Copyright (c) UXBOX Labs SL + +(ns app.main.ui.formats + (:require + [app.common.data.macros :as dm] + [app.common.math :as mth])) + +(defn format-percent + ([value] + (format-percent value nil)) + ([value {:keys [precision] :or {precision 2}}] + (let [percent-val (mth/precision (* value 100) precision)] + (dm/str percent-val "%")))) + +(defn format-number + ([value] + (format-number value nil)) + ([value {:keys [precision] :or {precision 2}}] + (let [value (mth/precision value precision)] + (dm/str value)))) + +(defn format-pixels + ([value] + (format-pixels value nil)) + ([value {:keys [precision] :or {precision 2}}] + (let [value (mth/precision value precision)] + (dm/str value "px")))) + +(defn format-int + [value] + (let [value (mth/precision value 0)] + (dm/str value))) diff --git a/frontend/src/app/main/ui/measurements.cljs b/frontend/src/app/main/ui/measurements.cljs index 08a4cd8d4..2f3181c0e 100644 --- a/frontend/src/app/main/ui/measurements.cljs +++ b/frontend/src/app/main/ui/measurements.cljs @@ -12,6 +12,7 @@ [app.common.geom.shapes :as gsh] [app.common.math :as mth] [app.common.uuid :as uuid] + [app.main.ui.formats :as fmt] [rumext.alpha :as mf])) ;; ------------------------------------------------ @@ -97,7 +98,7 @@ (mf/defc size-display [{:keys [selrect zoom]}] (let [{:keys [x y width height]} selrect - size-label (dm/str (mth/round width) " x " (mth/round height)) + size-label (dm/str (fmt/format-number width) " x " (fmt/format-number height)) rect-height (/ size-display-height zoom) rect-width (/ (if (<= (count size-label) 9) @@ -164,7 +165,7 @@ :height distance-pill-height :style {:fill distance-text-color :font-size font-size}} - distance]])) + (fmt/format-pixels distance)]])) (mf/defc selection-rect [{:keys [selrect zoom]}] (let [{:keys [x y width height]} selrect @@ -214,7 +215,7 @@ {:x center-x :y center-y :zoom zoom - :distance (dm/str (mth/round distance) "px") + :distance distance :bounds bounds}]]))))) (mf/defc selection-guides [{:keys [bounds selrect zoom]}] diff --git a/frontend/src/app/main/ui/shapes/text/styles.cljs b/frontend/src/app/main/ui/shapes/text/styles.cljs index 232aa2acd..fc6a60c25 100644 --- a/frontend/src/app/main/ui/shapes/text/styles.cljs +++ b/frontend/src/app/main/ui/shapes/text/styles.cljs @@ -83,7 +83,7 @@ base #js {:textDecoration text-decoration :textTransform text-transform :lineHeight (or line-height "inherit") - :color (if show-text? text-color "transparent") + :color (if show-text? text-color "red") :caretColor (or text-color "black") :overflowWrap "initial"} diff --git a/frontend/src/app/main/ui/viewer/handoff/attributes/common.cljs b/frontend/src/app/main/ui/viewer/handoff/attributes/common.cljs index c7fa443ed..624ae2ab4 100644 --- a/frontend/src/app/main/ui/viewer/handoff/attributes/common.cljs +++ b/frontend/src/app/main/ui/viewer/handoff/attributes/common.cljs @@ -6,7 +6,6 @@ (ns app.main.ui.viewer.handoff.attributes.common (:require - [app.common.math :as mth] [app.main.store :as st] [app.main.ui.components.color-bullet :refer [color-bullet color-name]] [app.main.ui.components.copy-button :refer [copy-button]] @@ -50,9 +49,9 @@ (if (:gradient color) [:& color-name {:color color}] (case format - :rgba (let [[r g b a] (->> (uc/hex->rgba (:color color) (:opacity color)) (map #(mth/precision % 2)))] + :rgba (let [[r g b a] (uc/hex->rgba (:color color) (:opacity color))] [:div (str/fmt "%s, %s, %s, %s" r g b a)]) - :hsla (let [[h s l a] (->> (uc/hex->hsla (:color color) (:opacity color)) (map #(mth/precision % 2)))] + :hsla (let [[h s l a] (uc/hex->hsla (:color color) (:opacity color))] [:div (str/fmt "%s, %s, %s, %s" h s l a)]) [:* [:& color-name {:color color}] diff --git a/frontend/src/app/main/ui/viewer/handoff/attributes/layout.cljs b/frontend/src/app/main/ui/viewer/handoff/attributes/layout.cljs index b2da8eba3..ccbd9abc9 100644 --- a/frontend/src/app/main/ui/viewer/handoff/attributes/layout.cljs +++ b/frontend/src/app/main/ui/viewer/handoff/attributes/layout.cljs @@ -6,7 +6,6 @@ (ns app.main.ui.viewer.handoff.attributes.layout (:require - [app.common.math :as mth] [app.common.spec.radius :as ctr] [app.main.ui.components.copy-button :refer [copy-button]] [app.util.code-gen :as cg] @@ -39,46 +38,46 @@ [:* [:div.attributes-unit-row [:div.attributes-label (t locale "handoff.attributes.layout.width")] - [:div.attributes-value (mth/precision width 2) "px"] + [:div.attributes-value width "px"] [:& copy-button {:data (copy-data selrect :width)}]] [:div.attributes-unit-row [:div.attributes-label (t locale "handoff.attributes.layout.height")] - [:div.attributes-value (mth/precision height 2) "px"] + [:div.attributes-value height "px"] [:& copy-button {:data (copy-data selrect :height)}]] (when (not= (:x shape) 0) [:div.attributes-unit-row [:div.attributes-label (t locale "handoff.attributes.layout.left")] - [:div.attributes-value (mth/precision x 2) "px"] + [:div.attributes-value x "px"] [:& copy-button {:data (copy-data selrect :x)}]]) (when (not= (:y shape) 0) [:div.attributes-unit-row [:div.attributes-label (t locale "handoff.attributes.layout.top")] - [:div.attributes-value (mth/precision y 2) "px"] + [:div.attributes-value y "px"] [:& copy-button {:data (copy-data selrect :y)}]]) (when (ctr/radius-1? shape) [:div.attributes-unit-row [:div.attributes-label (t locale "handoff.attributes.layout.radius")] - [:div.attributes-value (mth/precision (:rx shape 0) 2) "px"] + [:div.attributes-value (:rx shape 0) "px"] [:& copy-button {:data (copy-data shape :rx)}]]) (when (ctr/radius-4? shape) [:div.attributes-unit-row [:div.attributes-label (t locale "handoff.attributes.layout.radius")] [:div.attributes-value - (mth/precision (:r1 shape) 2) ", " - (mth/precision (:r2 shape) 2) ", " - (mth/precision (:r3 shape) 2) ", " - (mth/precision (:r4 shape) 2) "px"] + (:r1 shape) ", " + (:r2 shape) ", " + (:r3 shape) ", " + (:r4 shape) "px"] [:& copy-button {:data (copy-data shape :r1)}]]) (when (not= (:rotation shape 0) 0) [:div.attributes-unit-row [:div.attributes-label (t locale "handoff.attributes.layout.rotation")] - [:div.attributes-value (mth/precision (:rotation shape) 2) "deg"] + [:div.attributes-value (:rotation shape) "deg"] [:& copy-button {:data (copy-data shape :rotation)}]])])) diff --git a/frontend/src/app/main/ui/viewer/handoff/attributes/stroke.cljs b/frontend/src/app/main/ui/viewer/handoff/attributes/stroke.cljs index d04f8832c..1564d73c5 100644 --- a/frontend/src/app/main/ui/viewer/handoff/attributes/stroke.cljs +++ b/frontend/src/app/main/ui/viewer/handoff/attributes/stroke.cljs @@ -7,7 +7,6 @@ (ns app.main.ui.viewer.handoff.attributes.stroke (:require [app.common.data :as d] - [app.common.math :as mth] [app.main.ui.components.copy-button :refer [copy-button]] [app.main.ui.viewer.handoff.attributes.common :refer [color-row]] [app.util.code-gen :as cg] @@ -67,7 +66,7 @@ stroke-alignment (or stroke-alignment :center)] [:div.attributes-stroke-row [:div.attributes-label (t locale "handoff.attributes.stroke.width")] - [:div.attributes-value (mth/precision (:stroke-width shape) 2) "px"] + [:div.attributes-value (:stroke-width shape) "px"] [:div.attributes-value (->> stroke-style d/name (str "handoff.attributes.stroke.style.") (t locale))] [:div.attributes-label (->> stroke-alignment d/name (str "handoff.attributes.stroke.alignment.") (t locale))] [:& copy-button {:data (copy-stroke-data shape)}]])])) diff --git a/frontend/src/app/main/ui/viewer/handoff/attributes/svg.cljs b/frontend/src/app/main/ui/viewer/handoff/attributes/svg.cljs index 8e126e014..ea0f6c4e5 100644 --- a/frontend/src/app/main/ui/viewer/handoff/attributes/svg.cljs +++ b/frontend/src/app/main/ui/viewer/handoff/attributes/svg.cljs @@ -6,16 +6,12 @@ (ns app.main.ui.viewer.handoff.attributes.svg (:require - #_[app.common.math :as mth] - #_[app.main.ui.icons :as i] - #_[app.util.code-gen :as cg] [app.common.data :as d] [app.main.ui.components.copy-button :refer [copy-button]] [app.util.i18n :refer [tr]] [cuerdas.core :as str] [rumext.alpha :as mf])) - (defn map->css [attr] (->> attr (map (fn [[attr-key attr-value]] (str (d/name attr-key) ":" attr-value))) diff --git a/frontend/src/app/main/ui/viewer/header.cljs b/frontend/src/app/main/ui/viewer/header.cljs index 4427c7767..b32adfbc1 100644 --- a/frontend/src/app/main/ui/viewer/header.cljs +++ b/frontend/src/app/main/ui/viewer/header.cljs @@ -6,13 +6,13 @@ (ns app.main.ui.viewer.header (:require - [app.common.math :as mth] [app.main.data.modal :as modal] [app.main.data.viewer :as dv] [app.main.data.viewer.shortcuts :as sc] [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.components.dropdown :refer [dropdown]] + [app.main.ui.formats :as fmt] [app.main.ui.icons :as i] [app.main.ui.viewer.comments :refer [comments-menu]] [app.main.ui.viewer.interactions :refer [flows-menu interactions-menu]] @@ -32,7 +32,7 @@ :as props}] (let [show-dropdown? (mf/use-state false)] [:div.zoom-widget {:on-click #(reset! show-dropdown? true)} - [:span.label {} (str (mth/round (* 100 zoom)) "%")] + [:span.label (fmt/format-percent zoom)] [:span.icon i/arrow-down] [:& dropdown {:show @show-dropdown? :on-close #(reset! show-dropdown? false)} @@ -43,7 +43,7 @@ (dom/stop-propagation event) (dom/prevent-default event) (on-decrease))} "-"] - [:p.zoom-size {} (str (mth/round (* 100 zoom)) "%")] + [:p.zoom-size (fmt/format-percent zoom)] [:button {:on-click (fn [event] (dom/stop-propagation event) (dom/prevent-default event) diff --git a/frontend/src/app/main/ui/workspace/colorpalette.cljs b/frontend/src/app/main/ui/workspace/colorpalette.cljs index ceec91be7..64eb5bc8f 100644 --- a/frontend/src/app/main/ui/workspace/colorpalette.cljs +++ b/frontend/src/app/main/ui/workspace/colorpalette.cljs @@ -6,7 +6,6 @@ (ns app.main.ui.workspace.colorpalette (:require - [app.common.math :as mth] [app.main.data.workspace.colors :as mdc] [app.main.refs :as refs] [app.main.store :as st] @@ -57,7 +56,7 @@ (let [state (mf/use-state {:show-menu false}) width (:width @state 0) - visible (mth/round (/ width 66)) + visible (/ width 66) offset (:offset @state 0) max-offset (- (count current-colors) @@ -75,7 +74,7 @@ (swap! state update :offset (fn [offset] (if (pos? offset) - (max (- offset (mth/round (/ visible 2))) 0) + (max (- offset (/ visible 2)) 0) offset))))) on-right-arrow-click @@ -85,7 +84,7 @@ (swap! state update :offset (fn [offset] (if (< offset max-offset) - (min max-offset (+ offset (mth/round (/ visible 2)))) + (min max-offset (+ offset (/ visible 2))) offset))))) on-scroll diff --git a/frontend/src/app/main/ui/workspace/colorpicker/color_inputs.cljs b/frontend/src/app/main/ui/workspace/colorpicker/color_inputs.cljs index 00a0c7851..b1645d3f6 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker/color_inputs.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker/color_inputs.cljs @@ -6,7 +6,7 @@ (ns app.main.ui.workspace.colorpicker.color-inputs (:require - [app.common.math :as math] + [app.common.math :as mth] [app.util.color :as uc] [app.util.dom :as dom] [rumext.alpha :as mf])) @@ -52,7 +52,7 @@ on-change-property (fn [property max-value] (fn [e] - (let [val (-> e dom/get-target-val (math/clamp 0 max-value)) + (let [val (-> e dom/get-target-val (mth/clamp 0 max-value)) val (if (#{:s} property) (/ val 100) val)] (when (not (nil? val)) (if (#{:r :g :b} property) @@ -72,7 +72,7 @@ on-change-opacity (fn [e] - (when-let [new-alpha (-> e dom/get-target-val (math/clamp 0 100) (/ 100))] + (when-let [new-alpha (-> e dom/get-target-val (mth/clamp 0 100) (/ 100))] (on-change {:alpha new-alpha})))] @@ -86,9 +86,9 @@ (when (and property-val property-ref) (when-let [node (mf/ref-val property-ref)] (case ref-key - (:s :alpha) (dom/set-value! node (math/round (* property-val 100))) + (:s :alpha) (dom/set-value! node (* property-val 100)) :hex (dom/set-value! node property-val) - (dom/set-value! node (math/round property-val))))))))) + (dom/set-value! node property-val)))))))) [:div.color-values {:class (when disable-opacity "disable-opacity")} @@ -156,7 +156,7 @@ :min 0 :step 1 :max 100 - :default-value (if (= alpha :multiple) "" (math/precision alpha 2)) + :default-value (if (= alpha :multiple) "" alpha) :on-change on-change-opacity}]) [:label.hex-label {:for "hex-value"} "HEX"] diff --git a/frontend/src/app/main/ui/workspace/colorpicker/harmony.cljs b/frontend/src/app/main/ui/workspace/colorpicker/harmony.cljs index 69247a2d0..b73e85843 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker/harmony.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker/harmony.cljs @@ -7,7 +7,7 @@ (ns app.main.ui.workspace.colorpicker.harmony (:require [app.common.geom.point :as gpt] - [app.common.math :as math] + [app.common.math :as mth] [app.main.ui.workspace.colorpicker.slider-selector :refer [slider-selector]] [app.util.color :as uc] [app.util.dom :as dom] @@ -28,9 +28,9 @@ (.clearRect ctx 0 0 width height) (doseq [degrees (range 0 360 step)] - (let [degrees-rad (math/radians degrees) - x (* radius (math/cos (- degrees-rad))) - y (* radius (math/sin (- degrees-rad)))] + (let [degrees-rad (mth/radians degrees) + x (* radius (mth/cos (- degrees-rad))) + y (* radius (mth/sin (- degrees-rad)))] (obj/set! ctx "strokeStyle" (str/format "hsl(%s, 100%, 50%)" degrees)) (.beginPath ctx) (.moveTo ctx cx cy) @@ -43,15 +43,15 @@ (obj/set! ctx "fillStyle" grd) (.beginPath ctx) - (.arc ctx cx cy radius 0 (* 2 math/PI) true) + (.arc ctx cx cy radius 0 (* 2 mth/PI) true) (.closePath ctx) (.fill ctx)))) (defn color->point [canvas-side hue saturation] - (let [hue-rad (math/radians (- hue)) - comp-x (* saturation (math/cos hue-rad)) - comp-y (* saturation (math/sin hue-rad)) + (let [hue-rad (mth/radians (- hue)) + comp-x (* saturation (mth/cos hue-rad)) + comp-y (* saturation (mth/sin hue-rad)) x (+ (/ canvas-side 2) (* comp-x (/ canvas-side 2))) y (+ (/ canvas-side 2) (* comp-y (/ canvas-side 2)))] (gpt/point x y))) @@ -68,15 +68,15 @@ calculate-pos (fn [ev] (let [{:keys [left right top bottom]} (-> ev dom/get-target dom/get-bounding-rect) {:keys [x y]} (-> ev dom/get-client-position) - px (math/clamp (/ (- x left) (- right left)) 0 1) - py (math/clamp (/ (- y top) (- bottom top)) 0 1) + px (mth/clamp (/ (- x left) (- right left)) 0 1) + py (mth/clamp (/ (- y top) (- bottom top)) 0 1) px (- (* 2 px) 1) py (- (* 2 py) 1) - angle (math/degrees (math/atan2 px py)) - new-hue (math/precision (mod (- angle 90 ) 360) 2) - new-saturation (math/clamp (math/distance [px py] [0 0]) 0 1) + angle (mth/degrees (mth/atan2 px py)) + new-hue (mod (- angle 90 ) 360) + new-saturation (mth/clamp (mth/distance [px py] [0 0]) 0 1) hex (uc/hsv->hex [new-hue new-saturation value]) [r g b] (uc/hex->rgb hex)] (on-change {:hex hex diff --git a/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs b/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs index e9bd1d91d..09a8cfa41 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs @@ -6,7 +6,7 @@ (ns app.main.ui.workspace.colorpicker.ramp (:require - [app.common.math :as math] + [app.common.math :as mth] [app.main.ui.components.color-bullet :refer [color-bullet]] [app.main.ui.workspace.colorpicker.slider-selector :refer [slider-selector]] [app.util.color :as uc] @@ -19,8 +19,8 @@ (fn [ev] (let [{:keys [left right top bottom]} (-> ev dom/get-target dom/get-bounding-rect) {:keys [x y]} (-> ev dom/get-client-position) - px (math/clamp (/ (- x left) (- right left)) 0 1) - py (* 255 (- 1 (math/clamp (/ (- y top) (- bottom top)) 0 1)))] + px (mth/clamp (/ (- x left) (- right left)) 0 1) + py (* 255 (- 1 (mth/clamp (/ (- y top) (- bottom top)) 0 1)))] (on-change px py))) handle-start-drag diff --git a/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.cljs b/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.cljs index 5e72584c4..9c47681d2 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.cljs @@ -6,7 +6,7 @@ (ns app.main.ui.workspace.colorpicker.slider-selector (:require - [app.common.math :as math] + [app.common.math :as mth] [app.util.dom :as dom] [app.util.object :as obj] [rumext.alpha :as mf])) @@ -41,13 +41,13 @@ (let [{:keys [left right top bottom]} (-> ev dom/get-target dom/get-bounding-rect) {:keys [x y]} (-> ev dom/get-client-position) unit-value (if vertical? - (math/clamp (/ (- bottom y) (- bottom top)) 0 1) - (math/clamp (/ (- x left) (- right left)) 0 1)) + (mth/clamp (/ (- bottom y) (- bottom top)) 0 1) + (mth/clamp (/ (- x left) (- right left)) 0 1)) unit-value (if reverse? - (math/abs (- unit-value 1.0)) + (mth/abs (- unit-value 1.0)) unit-value) value (+ min-value (* unit-value (- max-value min-value)))] - (on-change (math/precision value 2)))))] + (on-change value))))] [:div.slider-selector {:class (str (if vertical? "vertical " "") class) @@ -60,7 +60,7 @@ (- max-value min-value)) 100) value-percent (if reverse? - (math/abs (- value-percent 100)) + (mth/abs (- value-percent 100)) value-percent) value-percent-str (str value-percent "%") diff --git a/frontend/src/app/main/ui/workspace/header.cljs b/frontend/src/app/main/ui/workspace/header.cljs index 81b236140..0862decdb 100644 --- a/frontend/src/app/main/ui/workspace/header.cljs +++ b/frontend/src/app/main/ui/workspace/header.cljs @@ -7,7 +7,6 @@ (ns app.main.ui.workspace.header (:require [app.common.data :as d] - [app.common.math :as mth] [app.config :as cf] [app.main.data.events :as ev] [app.main.data.messages :as dm] @@ -18,6 +17,7 @@ [app.main.repo :as rp] [app.main.store :as st] [app.main.ui.components.dropdown :refer [dropdown]] + [app.main.ui.formats :as fmt] [app.main.ui.hooks.resize :as r] [app.main.ui.icons :as i] [app.main.ui.workspace.presence :refer [active-sessions]] @@ -71,7 +71,7 @@ :as props}] (let [show-dropdown? (mf/use-state false)] [:div.zoom-widget {:on-click #(reset! show-dropdown? true)} - [:span.label {} (str (mth/round (* 100 zoom)) "%")] + [:span.label (fmt/format-percent zoom {:precision 0})] [:span.icon i/arrow-down] [:& dropdown {:show @show-dropdown? :on-close #(reset! show-dropdown? false)} @@ -82,7 +82,7 @@ (dom/stop-propagation event) (dom/prevent-default event) (on-decrease))} "-"] - [:p.zoom-size {} (str (mth/round (* 100 zoom)) "%")] + [:p.zoom-size {} (fmt/format-percent zoom {:precision 0})] [:button {:on-click (fn [event] (dom/stop-propagation event) (dom/prevent-default event) diff --git a/frontend/src/app/main/ui/workspace/left_toolbar.cljs b/frontend/src/app/main/ui/workspace/left_toolbar.cljs index 584d8ce6c..11a0b2ae2 100644 --- a/frontend/src/app/main/ui/workspace/left_toolbar.cljs +++ b/frontend/src/app/main/ui/workspace/left_toolbar.cljs @@ -7,7 +7,6 @@ (ns app.main.ui.workspace.left-toolbar (:require [app.common.geom.point :as gpt] - [app.common.math :as mth] [app.common.media :as cm] [app.main.data.events :as ev] [app.main.data.workspace :as dw] @@ -40,8 +39,8 @@ ;; We don't want to add a ref because that redraws the component ;; for everychange. Better direct access on the callback. (let [vbox (deref refs/vbox) - x (mth/round (+ (:x vbox) (/ (:width vbox) 2))) - y (mth/round (+ (:y vbox) (/ (:height vbox) 2))) + x (+ (:x vbox) (/ (:width vbox) 2)) + y (+ (:y vbox) (/ (:height vbox) 2)) params {:file-id (:id file) :blobs (seq blobs) :position (gpt/point x y)}] diff --git a/frontend/src/app/main/ui/workspace/nudge.cljs b/frontend/src/app/main/ui/workspace/nudge.cljs index 8574be246..0bab8bed1 100644 --- a/frontend/src/app/main/ui/workspace/nudge.cljs +++ b/frontend/src/app/main/ui/workspace/nudge.cljs @@ -49,12 +49,12 @@ [:div.input-wrapper [:span [:p.nudge-subtitle (tr "modals.small-nudge")] - [:> numeric-input {:min 1 + [:> numeric-input {:min 0.01 :value (:small nudge) :on-change update-small}]]] [:div.input-wrapper [:span [:p.nudge-subtitle (tr "modals.big-nudge")] - [:> numeric-input {:min 1 + [:> numeric-input {:min 0.01 :value (:big nudge) :on-change update-big}]]]]]])) diff --git a/frontend/src/app/main/ui/workspace/shapes/path/editor.cljs b/frontend/src/app/main/ui/workspace/shapes/path/editor.cljs index 2ccc1583d..f89dd55f7 100644 --- a/frontend/src/app/main/ui/workspace/shapes/path/editor.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/path/editor.cljs @@ -89,6 +89,7 @@ :style {:cursor (cond (= edit-mode :draw) cur/pen-node (= edit-mode :move) cur/pointer-node) + :stroke-width 0 :fill "none"}}]])) (mf/defc path-handler [{:keys [index prefix point handler zoom selected? hover? edit-mode snap-angle?]}] @@ -147,7 +148,8 @@ :on-mouse-enter on-enter :on-mouse-leave on-leave :style {:cursor (when (= edit-mode :move) cur/pointer-move) - :fill "none"}}]]))) + :fill "none" + :stroke-width 0}}]]))) (mf/defc path-preview [{:keys [zoom command from]}] [:g.preview {:style {:pointer-events "none"}} diff --git a/frontend/src/app/main/ui/workspace/shapes/text.cljs b/frontend/src/app/main/ui/workspace/shapes/text.cljs index 18bf8fc09..1798a24ee 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text.cljs @@ -209,7 +209,7 @@ ;; and updates the selrect accordingly [:* [:g.text-shape {:ref on-change-node - :opacity (when show-svg-text? 0) + :opacity (when show-svg-text? 0.2) :pointer-events "none"} ;; The `:key` prop here is mandatory because the diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs index 0fa376e89..b7fdf6146 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs @@ -6,7 +6,6 @@ (ns app.main.ui.workspace.sidebar.options.menus.frame-grid (:require - [app.common.math :as mth] [app.main.data.workspace.grid :as dw] [app.main.refs :as refs] [app.main.store :as st] @@ -71,8 +70,7 @@ (let [{:keys [margin gutter item-length]} (:params grid) frame-length (if (= :column (:type grid)) frame-width frame-height) item-length (if (nil? size) - (-> (gg/calculate-default-item-length frame-length margin gutter) - (mth/precision 2)) + (gg/calculate-default-item-length frame-length margin gutter) item-length)] (-> grid (update :params assoc :size size :item-length item-length) @@ -140,7 +138,7 @@ (if (= type :square) [:div.input-element.pixels {:title (tr "workspace.options.size")} - [:> numeric-input {:min 1 + [:> numeric-input {:min 0.01 :value (or (:size params) "") :no-validate true :on-change (handle-change :params :size)}]] @@ -162,7 +160,7 @@ (when (= :square type) [:& input-row {:label (tr "workspace.options.grid.params.size") :class "pixels" - :min 1 + :min 0.01 :value (:size params) :on-change (handle-change :params :size)}]) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.cljs index cbcbaf7d8..a1a195991 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layer.cljs @@ -7,7 +7,6 @@ (ns app.main.ui.workspace.sidebar.options.menus.layer (:require [app.common.data :as d] - [app.common.math :as mth] [app.main.data.workspace.changes :as dch] [app.main.store :as st] [app.main.ui.components.numeric-input :refer [numeric-input]] @@ -23,8 +22,7 @@ "" (str (-> opacity (d/coalesce 1) - (* 100) - (mth/round))))) + (* 100))))) (defn select-all [event] (dom/select-text! (dom/get-target event))) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs index 5b7a59747..8ea1e112b 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/measures.cljs @@ -8,7 +8,6 @@ (:require [app.common.data :as d] [app.common.geom.shapes :as gsh] - [app.common.math :as math] [app.common.spec.radius :as ctr] [app.main.data.workspace :as udw] [app.main.data.workspace.changes :as dch] @@ -46,9 +45,7 @@ (let [value (attr values)] (if (= value :multiple) "" - (str (-> value - (d/coalesce 0) - (math/precision 2)))))) + (str (-> value (d/coalesce 0)))))) (declare +size-presets+) @@ -239,7 +236,7 @@ [:div.row-flex [:span.element-set-subtitle (tr "workspace.options.size")] [:div.input-element.width {:title (tr "workspace.options.width")} - [:> numeric-input {:min 1 + [:> numeric-input {:min 0.01 :no-validate true :placeholder "--" :on-click select-all @@ -247,7 +244,7 @@ :value (attr->string :width values)}]] [:div.input-element.height {:title (tr "workspace.options.height")} - [:> numeric-input {:min 1 + [:> numeric-input {:min 0.01 :no-validate true :placeholder "--" :on-click select-all @@ -271,15 +268,13 @@ :placeholder "--" :on-click select-all :on-change on-pos-x-change - :value (attr->string :x values) - :precision 2}]] + :value (attr->string :x values)}]] [:div.input-element.Yaxis {:title (tr "workspace.options.y")} [:> numeric-input {:no-validate true :placeholder "--" :on-click select-all :on-change on-pos-y-change - :value (attr->string :y values) - :precision 2}]]]) + :value (attr->string :y values)}]]]) ;; ROTATION (when (options :rotation) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs index 2f2d08f9b..0cb9906db 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs @@ -386,7 +386,6 @@ {:min -200 :max 200 :step 0.1 - :precision 2 :value (attr->string line-height) :placeholder (tr "settings.multiple") :on-change #(handle-change % :line-height) @@ -400,7 +399,6 @@ {:min -200 :max 200 :step 0.1 - :precision 2 :value (attr->string letter-spacing) :placeholder (tr "settings.multiple") :on-change #(handle-change % :letter-spacing) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs index 862826575..41ce9d1d1 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs @@ -7,7 +7,6 @@ (ns app.main.ui.workspace.sidebar.options.rows.color-row (:require [app.common.data :as d] - [app.common.math :as math] [app.common.pages :as cp] [app.main.data.modal :as modal] [app.main.refs :as refs] @@ -54,8 +53,7 @@ "" (str (-> opacity (d/coalesce 1) - (* 100) - (math/round))))) + (* 100))))) (defn remove-multiple [v] (if (= v :multiple) nil v)) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs index 6f462ded7..c27501057 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs @@ -97,7 +97,6 @@ [:> numeric-input {:min 0 :value (-> (:stroke-width stroke) width->string) - :precision 2 :placeholder (tr "settings.multiple") :on-change (on-stroke-width-change index) :on-click select-all diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index dcc160f25..45736a9c6 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -345,6 +345,7 @@ :zoom zoom :transform transform :selected selected + :selected-shapes selected-shapes :page-id page-id}]) (when show-cursor-tooltip? diff --git a/frontend/src/app/main/ui/workspace/viewport/frame_grid.cljs b/frontend/src/app/main/ui/workspace/viewport/frame_grid.cljs index b3169b12c..a23397356 100644 --- a/frontend/src/app/main/ui/workspace/viewport/frame_grid.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/frame_grid.cljs @@ -7,7 +7,6 @@ (ns app.main.ui.workspace.viewport.frame-grid (:require [app.common.geom.shapes :as gsh] - [app.common.math :as mth] [app.common.uuid :as uuid] [app.main.refs :as refs] [app.util.geom.grid :as gg] @@ -58,10 +57,10 @@ [:g.grid (for [{:keys [x y width height] :as area} (gg/grid-areas frame grid)] [:rect {:key (str key "-" x "-" y) - :x (mth/round x) - :y (mth/round y) - :width (- (mth/round (+ x width)) (mth/round x)) - :height (- (mth/round (+ y height)) (mth/round y)) + :x x + :y y + :width (- (+ x width) x) + :height (- (+ y height) y) :style style}])])) (mf/defc grid-display-frame diff --git a/frontend/src/app/main/ui/workspace/viewport/gradients.cljs b/frontend/src/app/main/ui/workspace/viewport/gradients.cljs index 2fdcc2372..cb052cf61 100644 --- a/frontend/src/app/main/ui/workspace/viewport/gradients.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/gradients.cljs @@ -281,9 +281,7 @@ (fn [point] (let [point (gpt/transform point transform-inverse) start-x (/ (- (:x point) x) width) - start-y (/ (- (:y point) y) height) - start-x (mth/precision start-x 2) - start-y (mth/precision start-y 2)] + start-y (/ (- (:y point) y) height)] (change! {:start-x start-x :start-y start-y})))) on-change-finish @@ -292,9 +290,7 @@ (fn [point] (let [point (gpt/transform point transform-inverse) end-x (/ (- (:x point) x) width) - end-y (/ (- (:y point) y) height) - end-x (mth/precision end-x 2) - end-y (mth/precision end-y 2)] + end-y (/ (- (:y point) y) height)] (change! {:end-x end-x :end-y end-y})))) on-change-width diff --git a/frontend/src/app/main/ui/workspace/viewport/guides.cljs b/frontend/src/app/main/ui/workspace/viewport/guides.cljs index 36e040e09..7615b3b4d 100644 --- a/frontend/src/app/main/ui/workspace/viewport/guides.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/guides.cljs @@ -9,7 +9,6 @@ [app.common.colors :as colors] [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] - [app.common.math :as mth] [app.common.uuid :as uuid] [app.main.data.workspace :as dw] [app.main.refs :as refs] @@ -102,7 +101,6 @@ (+ start-pos delta)) ;; TODO: Change when pixel-grid flag exists - new-position (mth/round new-position) new-frame-id (:id (get-hover-frame))] (swap! state assoc :new-position new-position @@ -366,7 +364,7 @@ :style {:font-size (/ rules/font-size zoom) :font-family rules/font-family :fill colors/black}} - (str (mth/round pos))]]))]))) + (str pos)]]))]))) (mf/defc new-guide-area [{:keys [vbox zoom axis get-hover-frame disabled-guides?]}] diff --git a/frontend/src/app/main/ui/workspace/viewport/interactions.cljs b/frontend/src/app/main/ui/workspace/viewport/interactions.cljs index 602115855..20a51b826 100644 --- a/frontend/src/app/main/ui/workspace/viewport/interactions.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/interactions.cljs @@ -146,12 +146,12 @@ :else (connect-to-point orig-shape - {:x (+ (:x2 (:selrect orig-shape)) 100) - :y (+ (- (:y1 (:selrect orig-shape)) 50) + {:x (+ (:x2 (:selrect orig-shape)) (/ 100 zoom)) + :y (+ (- (:y1 (:selrect orig-shape)) (/ 50 zoom)) (/ (* level 32) zoom))})) - orig-dx (if (= orig-pos :right) 100 -100) - dest-dx (if (= dest-pos :right) 100 -100) + orig-dx (/ (if (= orig-pos :right) 100 -100) zoom) + dest-dx (/ (if (= dest-pos :right) 100 -100) zoom) path ["M" orig-x orig-y "C" (+ orig-x orig-dx) orig-y (+ dest-x dest-dx) dest-y dest-x dest-y] pdata (str/join " " path) @@ -182,7 +182,8 @@ :d pdata}] (when dest-shape - [:& outline {:shape dest-shape + [:& outline {:zoom zoom + :shape dest-shape :color "var(--color-primary)"}]) [:& interaction-marker {:index index diff --git a/frontend/src/app/main/ui/workspace/viewport/rules.cljs b/frontend/src/app/main/ui/workspace/viewport/rules.cljs index 57a27c106..e6440786e 100644 --- a/frontend/src/app/main/ui/workspace/viewport/rules.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/rules.cljs @@ -10,6 +10,7 @@ [app.common.data :as d] [app.common.geom.shapes :as gsh] [app.common.math :as mth] + [app.main.ui.formats :as fmt] [app.main.ui.hooks :as hooks] [app.util.object :as obj] [rumext.alpha :as mf])) @@ -131,9 +132,9 @@ (let [{:keys [start end]} (get-rule-params vbox axis) - minv (max (mth/round start) -100000) + minv (max start -100000) minv (* (mth/ceil (/ minv step)) step) - maxv (min (mth/round end) 100000) + maxv (min end 100000) maxv (* (mth/floor (/ maxv step)) step)] (for [step-val (range minv (inc maxv) step)] @@ -149,7 +150,7 @@ :style {:font-size (/ font-size zoom) :font-family font-family :fill colors/gray-30}} - (str (mth/round step-val))] + (fmt/format-number step-val)] [:line {:key (str "line-" (d/name axis) "-" step-val) :x1 line-x1 @@ -184,7 +185,7 @@ :style {:font-size (/ font-size zoom) :font-family font-family :fill selection-area-color}} - (str (mth/round (:x1 selection-rect)))] + (fmt/format-number (:x1 selection-rect))] [:rect {:x (:x2 selection-rect) :y (:y vbox) @@ -200,7 +201,7 @@ :style {:font-size (/ font-size zoom) :font-family font-family :fill selection-area-color}} - (str (mth/round (:x2 selection-rect)))]] + (fmt/format-number (:x2 selection-rect))]] (let [center-x (+ (:x vbox) (/ rule-area-half-size zoom)) center-y (- (+ (:y selection-rect) (/ (:height selection-rect) 2)) (/ rule-area-half-size zoom))] @@ -234,7 +235,7 @@ :style {:font-size (/ font-size zoom) :font-family font-family :fill selection-area-color}} - (str (mth/round (:y2 selection-rect)))] + (fmt/format-number (:y2 selection-rect))] [:text {:x (+ center-x (/ (:height selection-rect) 2) ) :y center-y @@ -243,7 +244,7 @@ :style {:font-size (/ font-size zoom) :font-family font-family :fill selection-area-color}} - (str (mth/round (:y1 selection-rect)))]])]) + (fmt/format-number (:y1 selection-rect))]])]) (mf/defc rules {::mf/wrap-props false diff --git a/frontend/src/app/main/ui/workspace/viewport/scroll_bars.cljs b/frontend/src/app/main/ui/workspace/viewport/scroll_bars.cljs index 3de69d6b2..910733a89 100644 --- a/frontend/src/app/main/ui/workspace/viewport/scroll_bars.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/scroll_bars.cljs @@ -131,7 +131,7 @@ (let [viewport (mf/ref-val viewport-ref) start-pt (mf/ref-val start-ref) current-pt (dom/get-client-position event) - current-pt-viewport (utils/translate-point-to-viewport-raw viewport zoom current-pt) + current-pt-viewport (utils/translate-point-to-viewport viewport zoom current-pt) y-delta (/ (* (mf/ref-val height-factor-ref) (- (:y current-pt) (:y start-pt))) zoom) x-delta (/ (* (mf/ref-val width-factor-ref) (- (:x current-pt) (:x start-pt))) zoom) new-v-scrollbar-y (-> current-pt-viewport @@ -156,8 +156,9 @@ (fn [event axis] (let [viewport (mf/ref-val viewport-ref) start-pt (dom/get-client-position event) - new-v-scrollbar-y (-> (utils/translate-point-to-viewport-raw viewport zoom start-pt) :y) - new-h-scrollbar-x (-> (utils/translate-point-to-viewport-raw viewport zoom start-pt) :x) + viewport-point (utils/translate-point-to-viewport viewport zoom start-pt) + new-h-scrollbar-x (:x viewport-point) + new-v-scrollbar-y (:y viewport-point) v-scrollbar-y-padding (- v-scrollbar-y new-v-scrollbar-y) h-scrollbar-x-padding (- h-scrollbar-x new-h-scrollbar-x) vbox-rect {:x vbox-x @@ -206,7 +207,7 @@ :x v-scrollbar-x :y v-scrollbar-y :style {:stroke "white" - :stroke-width 0.15}}]]) + :stroke-width (/ 0.15 zoom)}}]]) (when show-h-scroll? [:g.h-scroll [:rect {:on-mouse-move #(on-mouse-move % :x) @@ -220,4 +221,4 @@ :x h-scrollbar-x :y h-scrollbar-y :style {:stroke "white" - :stroke-width 0.15}}]])])) + :stroke-width (/ 0.15 zoom)}}]])])) diff --git a/frontend/src/app/main/ui/workspace/viewport/selection.cljs b/frontend/src/app/main/ui/workspace/viewport/selection.cljs index 99c85734d..62abcd9ec 100644 --- a/frontend/src/app/main/ui/workspace/viewport/selection.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/selection.cljs @@ -67,38 +67,18 @@ :position :top-left :props {:cx x :cy y}} - (when show-resize-point? - {:type :resize-point - :position :top-left - :props {:cx x :cy y :align align}}) - {:type :rotation :position :top-right :props {:cx (+ x width) :cy y}} - (when show-resize-point? - {:type :resize-point - :position :top-right - :props {:cx (+ x width) :cy y :align align}}) - {:type :rotation :position :bottom-right :props {:cx (+ x width) :cy (+ y height)}} - (when show-resize-point? - {:type :resize-point - :position :bottom-right - :props {:cx (+ x width) :cy (+ y height) :align align}}) - {:type :rotation :position :bottom-left :props {:cx x :cy (+ y height)}} - (when show-resize-point? - {:type :resize-point - :position :bottom-left - :props {:cx x :cy (+ y height) :align align}}) - (when min-side-top? {:type :resize-side :position :top @@ -117,7 +97,30 @@ (when min-side-side? {:type :resize-side :position :left - :props {:x x :y (+ y height) :length height :angle 270 :align align}})] + :props {:x x :y (+ y height) :length height :angle 270 :align align}}) + + (when show-resize-point? + {:type :resize-point + :position :top-left + :props {:cx x :cy y :align align}}) + + (when show-resize-point? + {:type :resize-point + :position :top-right + :props {:cx (+ x width) :cy y :align align}}) + + (when show-resize-point? + {:type :resize-point + :position :bottom-right + :props {:cx (+ x width) :cy (+ y height) :align align}}) + + (when show-resize-point? + {:type :resize-point + :position :bottom-left + :props {:cx x :cy (+ y height) :align align}}) + + + ] (filterv (comp not nil?))))) @@ -136,6 +139,8 @@ :width size :height size :fill (if (debug? :rotation-handler) "blue" "none") + :stroke (if (debug? :rotation-handler) "blue" "none") + :stroke-width 0 :transform transform :on-mouse-down on-rotate}])) @@ -168,6 +173,8 @@ :height resize-point-circle-radius :transform (when rotation (str/fmt "rotate(%s, %s, %s)" rotation cx' cy')) :style {:fill (if (debug? :resize-handler) "red" "none") + :stroke (if (debug? :resize-handler) "red" "none") + :stroke-width 0 :cursor cursor} :on-mouse-down #(on-resize {:x cx' :y cy'} %)}]) @@ -176,7 +183,10 @@ :cx cx' :cy cy' :style {:fill (if (debug? :resize-handler) "red" "none") - :cursor cursor}}])])) + :stroke (if (debug? :resize-handler) "red" "none") + :stroke-width 0 + :cursor cursor}}] + )])) (mf/defc resize-side-handler "The side handler is always rendered horizontally and then rotated" @@ -202,6 +212,8 @@ (gmt/rotate-matrix angle (gpt/point x y))) :on-mouse-down #(on-resize res-point %) :style {:fill (if (debug? :resize-handler) "yellow" "none") + :stroke (if (debug? :resize-handler) "yellow" "none") + :stroke-width 0 :cursor (if (#{:left :right} position) (cur/resize-ew rotation) (cur/resize-ns rotation)) }}])) @@ -292,7 +304,7 @@ :pointer-events "visible" :style {:stroke color :stroke-width (/ 0.5 zoom) - :stroke-opacity "1" + :stroke-opacity 1 :fill "none"}}]])) (mf/defc multiple-handlers @@ -344,7 +356,7 @@ (mf/defc single-handlers [{:keys [shape zoom color disable-handlers] :as props}] (let [shape-id (:id shape) - shape (geom/transform-shape shape {:round-coords? false}) + shape (geom/transform-shape shape) on-resize (fn [current-position _initial-position event] diff --git a/frontend/src/app/main/ui/workspace/viewport/snap_distances.cljs b/frontend/src/app/main/ui/workspace/viewport/snap_distances.cljs index ca450b2a8..63572334f 100644 --- a/frontend/src/app/main/ui/workspace/viewport/snap_distances.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/snap_distances.cljs @@ -11,6 +11,7 @@ [app.common.math :as mth] [app.common.pages.helpers :as cph] [app.main.refs :as refs] + [app.main.ui.formats :as fmt] [app.main.worker :as uw] [beicon.core :as rx] [clojure.set :as set] @@ -54,7 +55,7 @@ (get sr2 (if (= :x coord) :x1 :y1))) distance (- to-c from-c) - distance-str (-> distance (mth/precision 0) str) + distance-str (str distance) half-point (half-point coord sr1 sr2) width (-> distance-str count @@ -81,7 +82,7 @@ :font-size (/ pill-text-font-size zoom) :fill "var(--color-white)" :text-anchor "middle"} - (mth/precision distance 0)]]) + (fmt/format-number distance)]]) (let [p1 [(+ from-c (/ segment-gap zoom)) (+ half-point (/ segment-gap-side zoom))] p2 [(+ from-c (/ segment-gap zoom)) (- half-point (/ segment-gap-side zoom))] @@ -110,7 +111,7 @@ sr2 (:selrect sh2) c1 (if (= coord :x) :x1 :y1) c2 (if (= coord :x) :x2 :y2) - dist (mth/precision (- (c1 sr2) (c2 sr1)) 0)] + dist (- (c1 sr2) (c2 sr1))] [dist [sh1 sh2]])) (defn overlap? [coord sh1 sh2] @@ -134,8 +135,7 @@ (-> (if (<= (coord sr) (coord selrect)) (gsh/distance-selrect sr selrect) (gsh/distance-selrect selrect sr)) - coord - (mth/precision 0)))) + coord))) get-shapes-match (fn [pred? shapes] @@ -149,9 +149,9 @@ check-in-set (fn [value number-set] (->> number-set - (some #(<= (mth/abs (- value %)) 1)))) + (some #(<= (mth/abs (- value %)) 0.01)))) - ;; Left/Top shapes and right/bottom shapes (depends on `coord` parameter + ;; Left/Top shapes and right/bottom shapes (depends on `coord` parameter) ;; Gets the distance to the current selection distances-xf (comp (map distance-to-selrect) (filter pos?)) @@ -195,6 +195,7 @@ (map #(vector selrect (:selrect %)))) segments-to-display (d/concat-set other-shapes-segments selection-segments)] + segments-to-display)) (mf/defc shape-distance @@ -217,8 +218,9 @@ container-selrec (or (:selrect frame) (gsh/rect->selrect @refs/vbox)) areas (gsh/selrect->areas container-selrec selrect) + query-side (fn [side] - (let [rect (gsh/pad-selrec (areas side))] + (let [rect (get areas side)] (if (and (> (:width rect) 0) (> (:height rect) 0)) (->> (uw/ask! {:cmd :selection/query :page-id page-id @@ -264,15 +266,10 @@ (let [page-id (unchecked-get props "page-id") zoom (unchecked-get props "zoom") selected (unchecked-get props "selected") - selected-shapes (mf/deref (refs/objects-by-id selected)) + selected-shapes (unchecked-get props "selected-shapes") frame-id (-> selected-shapes first :frame-id) frame (mf/deref (refs/object-by-id frame-id)) - local (mf/deref refs/workspace-local) - - update-shape (fn [shape] (-> shape - (update :modifiers merge (:modifiers local)) - gsh/transform-shape)) - selrect (->> selected-shapes (map update-shape) gsh/selection-rect)] + selrect (gsh/selection-rect selected-shapes)] [:g.distance [:& shape-distance {:selrect selrect diff --git a/frontend/src/app/main/ui/workspace/viewport/snap_points.cljs b/frontend/src/app/main/ui/workspace/viewport/snap_points.cljs index d5dd3b0a5..a89825675 100644 --- a/frontend/src/app/main/ui/workspace/viewport/snap_points.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/snap_points.cljs @@ -8,7 +8,6 @@ (:require [app.common.data :as d] [app.common.geom.shapes :as gsh] - [app.common.math :as mth] [app.common.pages.helpers :as cph] [app.common.spec :as us] [app.main.snap :as snap] @@ -28,8 +27,6 @@ (mf/defc snap-point [{:keys [point zoom]}] (let [{:keys [x y]} point - x (mth/round x) - y (mth/round y) cross-width (/ 3 zoom)] [:g [:line {:x1 (- x cross-width) @@ -45,15 +42,15 @@ (mf/defc snap-line [{:keys [snap point zoom]}] - [:line {:x1 (mth/round (:x snap)) - :y1 (mth/round (:y snap)) - :x2 (mth/round (:x point)) - :y2 (mth/round (:y point)) + [:line {:x1 (:x snap) + :y1 (:y snap) + :x2 (:x point) + :y2 (:y point) :style {:stroke line-color :stroke-width (str (/ line-width zoom))} :opacity line-opacity}]) (defn get-snap - [coord {:keys [shapes page-id remove-snap? modifiers]}] + [coord {:keys [shapes page-id remove-snap? zoom modifiers]}] (let [shape (if (> (count shapes) 1) (->> shapes (map gsh/transform-shape) gsh/selection-rect (gsh/setup {:type :rect})) (->> shapes (first))) @@ -69,7 +66,7 @@ (->> (sp/shape-snap-points shape) (map #(vector frame-id %))))) (rx/flat-map (fn [[frame-id point]] - (->> (snap/get-snap-points page-id frame-id remove-snap? point coord) + (->> (snap/get-snap-points page-id frame-id remove-snap? zoom point coord) (rx/map #(vector point % coord))))) (rx/reduce conj [])))) @@ -119,12 +116,19 @@ (mf/use-effect (fn [] (let [sub (->> subject - (rx/switch-map #(rx/combine-latest (get-snap :x %) - (get-snap :y %))) - (rx/map (fn [result] - (apply d/concat-vec (seq result)))) - (rx/subs #(let [rs (filter (fn [[_ snaps _]] (> (count snaps) 0)) %)] - (reset! state rs))))] + (rx/switch-map + (fn [props] + (->> (get-snap :y props) + (rx/combine-latest (get-snap :x props))))) + + (rx/map + (fn [result] + (apply d/concat-vec (seq result)))) + + (rx/subs + (fn [data] + (let [rs (filter (fn [[_ snaps _]] (> (count snaps) 0)) data)] + (reset! state rs)))))] ;; On unmount callback #(rx/dispose! sub)))) diff --git a/frontend/src/app/main/ui/workspace/viewport/thumbnail_renderer.cljs b/frontend/src/app/main/ui/workspace/viewport/thumbnail_renderer.cljs index 6e0ff85fe..634c54c89 100644 --- a/frontend/src/app/main/ui/workspace/viewport/thumbnail_renderer.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/thumbnail_renderer.cljs @@ -6,6 +6,7 @@ (ns app.main.ui.workspace.viewport.thumbnail-renderer (:require + [app.common.math :as mth] [app.main.data.workspace.persistence :as dwp] [app.main.store :as st] [app.util.dom :as dom] @@ -21,6 +22,10 @@ (let [thumbnail-img (mf/use-ref nil) thumbnail-canvas (mf/use-ref nil) + {:keys [width height]} shape + fixed-width (mth/clamp width 250 2000) + fixed-height (/ (* height fixed-width) width) + on-dom-rendered (mf/use-callback (mf/deps (:id shape)) @@ -71,23 +76,23 @@ _ (.rect canvas-context 0 0 canvas-width canvas-height) _ (set! (.-fillStyle canvas-context) background) _ (.fill canvas-context) - _ (.drawImage canvas-context img-node 0 0) + _ (.drawImage canvas-context img-node 0 0 canvas-width canvas-height) - data (.toDataURL canvas-node "image/jpeg" 0.8)] + data (.toDataURL canvas-node "image/jpg" 1)] (on-thumbnail-data data))))] [:div.frame-renderer {:ref on-dom-rendered :style {:display "none"}} [:img.thumbnail-img {:ref thumbnail-img - :width (:width shape) - :height (:height shape) + :width width + :height height :on-load on-image-load}] [:canvas.thumbnail-canvas {:ref thumbnail-canvas - :width (:width shape) - :height (:height shape)}]])) + :width fixed-width + :height fixed-height}]])) (mf/defc frame-renderer "Component in charge of creating thumbnails and storing them" diff --git a/frontend/src/app/main/ui/workspace/viewport/utils.cljs b/frontend/src/app/main/ui/workspace/viewport/utils.cljs index 6e7db9411..4caedeeb1 100644 --- a/frontend/src/app/main/ui/workspace/viewport/utils.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/utils.cljs @@ -163,7 +163,7 @@ (:width vbox 0) (:height vbox 0)])) -(defn translate-point-to-viewport-raw [viewport zoom pt] +(defn translate-point-to-viewport [viewport zoom pt] (let [vbox (.. ^js viewport -viewBox -baseVal) brect (dom/get-bounding-rect viewport) brect (gpt/point (d/parse-integer (:left brect)) @@ -174,10 +174,6 @@ (gpt/divide zoom) (gpt/add box)))) -(defn translate-point-to-viewport [viewport zoom pt] - (-> (translate-point-to-viewport-raw viewport zoom pt) - (gpt/round 0))) - (defn get-cursor [cursor] (case cursor :hand cur/hand diff --git a/frontend/src/app/main/ui/workspace/viewport/widgets.cljs b/frontend/src/app/main/ui/workspace/viewport/widgets.cljs index a9661c26f..a4361ad65 100644 --- a/frontend/src/app/main/ui/workspace/viewport/widgets.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/widgets.cljs @@ -32,8 +32,8 @@ :pattern-units "userSpaceOnUse"} [:path {:d "M 1 0 L 0 0 0 1" :style {:fill "none" - :stroke "var(--color-info)" - :stroke-opacity "0.2" + :stroke "var(--color-gray-20)" + :stroke-opacity "1" :stroke-width (str (/ 1 zoom))}}]]] [:rect {:x (:x vbox) :y (:y vbox) diff --git a/frontend/src/app/util/code_gen.cljs b/frontend/src/app/util/code_gen.cljs index 19978d5a8..3c9162378 100644 --- a/frontend/src/app/util/code_gen.cljs +++ b/frontend/src/app/util/code_gen.cljs @@ -7,7 +7,6 @@ (ns app.util.code-gen (:require [app.common.data :as d] - [app.common.math :as mth] [app.common.text :as txt] [app.util.color :as uc] [cuerdas.core :as str])) @@ -109,7 +108,7 @@ (every? #(or (nil? %) (= % 0)) value) (or (nil? value) (= value 0)))) - default-format (fn [value] (str (mth/precision value 2) "px")) + default-format (fn [value] (str value "px")) format-property (fn [prop] (let [css-prop (or (prop to-prop) (name prop)) format-fn (or (prop format) default-format) diff --git a/frontend/src/app/util/path/tools.cljs b/frontend/src/app/util/path/tools.cljs index 97a8a0ddd..fffd3816b 100644 --- a/frontend/src/app/util/path/tools.cljs +++ b/frontend/src/app/util/path/tools.cljs @@ -9,7 +9,6 @@ [app.common.data :as d] [app.common.geom.point :as gpt] [app.common.geom.shapes.path :as upg] - [app.common.math :as mth] [app.common.path.commands :as upc] [clojure.set :as set])) @@ -402,9 +401,7 @@ (rest segments)))))) (defn calculate-merge-points [group-segments points] - (let [index-merge-point (fn [group] (vector group (-> (gpt/center-points group) - (update :x mth/round) - (update :y mth/round)))) + (let [index-merge-point (fn [group] (vector group (gpt/center-points group))) index-group (fn [point] (vector point (d/seek #(contains? % point) group-segments))) group->merge-point (into {} (map index-merge-point) group-segments) diff --git a/frontend/src/app/util/perf.cljs b/frontend/src/app/util/perf.cljs index 87a0273be..d894f477e 100644 --- a/frontend/src/app/util/perf.cljs +++ b/frontend/src/app/util/perf.cljs @@ -8,7 +8,7 @@ "Performance profiling for react components." (:require-macros [app.util.perf]) (:require - [app.common.math :as math] + [app.common.math :as mth] [rumext.alpha :as mf] [goog.functions :as f] ["react" :as react] diff --git a/frontend/src/debug.cljs b/frontend/src/debug.cljs index 8e469a0d4..a7153c69c 100644 --- a/frontend/src/debug.cljs +++ b/frontend/src/debug.cljs @@ -7,7 +7,6 @@ (ns debug (:require [app.common.data :as d] - [app.common.math :as mth] [app.common.pages.helpers :as cph] [app.common.transit :as t] [app.common.uuid :as uuid] @@ -130,7 +129,7 @@ ts (/ 1000 (* (- cur @last))) val (+ @avg (* (- ts @avg) 0.1))] - (obj/set! node "innerText" (mth/precision val 0)) + (obj/set! node "innerText" val) (vreset! last cur) (vreset! avg val) (do-thing)))))]