mirror of
https://github.com/penpot/penpot.git
synced 2025-05-11 21:56:38 +02:00
✨ Fix problems with extreme values
This commit is contained in:
parent
999af63118
commit
ed9400912c
59 changed files with 359 additions and 340 deletions
|
@ -108,9 +108,12 @@
|
||||||
(= v base))
|
(= v base))
|
||||||
|
|
||||||
(defn translate-matrix
|
(defn translate-matrix
|
||||||
[{x :x y :y :as pt}]
|
([{x :x y :y :as pt}]
|
||||||
(assert (gpt/point? pt))
|
(assert (gpt/point? pt))
|
||||||
(Matrix. 1 0 0 1 x y))
|
(Matrix. 1 0 0 1 x y))
|
||||||
|
|
||||||
|
([x y]
|
||||||
|
(translate-matrix (gpt/point x y))))
|
||||||
|
|
||||||
(defn scale-matrix
|
(defn scale-matrix
|
||||||
([pt center]
|
([pt center]
|
||||||
|
|
|
@ -132,9 +132,8 @@
|
||||||
(assert (point? other))
|
(assert (point? other))
|
||||||
(let [dx (- x ox)
|
(let [dx (- x ox)
|
||||||
dy (- y oy)]
|
dy (- y oy)]
|
||||||
(-> (mth/sqrt (+ (mth/pow dx 2)
|
(mth/sqrt (+ (mth/pow dx 2)
|
||||||
(mth/pow dy 2)))
|
(mth/pow dy 2)))))
|
||||||
(mth/precision 6))))
|
|
||||||
|
|
||||||
(defn length
|
(defn length
|
||||||
[{x :x y :y :as p}]
|
[{x :x y :y :as p}]
|
||||||
|
@ -168,8 +167,7 @@
|
||||||
(* y oy))
|
(* y oy))
|
||||||
(* length-p length-other))
|
(* length-p length-other))
|
||||||
a (mth/acos (if (< a -1) -1 (if (> a 1) 1 a)))
|
a (mth/acos (if (< a -1) -1 (if (> a 1) 1 a)))
|
||||||
d (-> (mth/degrees a)
|
d (mth/degrees a)]
|
||||||
(mth/precision 6))]
|
|
||||||
(if (mth/nan? d) 0 d)))))
|
(if (mth/nan? d) 0 d)))))
|
||||||
|
|
||||||
(defn angle-sign [v1 v2]
|
(defn angle-sign [v1 v2]
|
||||||
|
@ -195,7 +193,9 @@
|
||||||
|
|
||||||
(defn round
|
(defn round
|
||||||
"Change the precision of the point coordinates."
|
"Change the precision of the point coordinates."
|
||||||
([point] (round point 0))
|
([point]
|
||||||
|
(round point 0))
|
||||||
|
|
||||||
([{:keys [x y] :as p} decimals]
|
([{:keys [x y] :as p} decimals]
|
||||||
(assert (point? p))
|
(assert (point? p))
|
||||||
(assert (number? decimals))
|
(assert (number? decimals))
|
||||||
|
|
|
@ -106,12 +106,12 @@
|
||||||
:width (- x2 x1)
|
:width (- x2 x1)
|
||||||
:height (- y2 y1)
|
:height (- y2 y1)
|
||||||
:type :rect}))
|
: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]
|
{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)
|
{:left (make-selrect bound-x1 sr-y1 sr-x1 sr-y2)
|
||||||
:top (make-selrect sr-x1 frame-y1 sr-x2 (- sr-y1 2))
|
:top (make-selrect sr-x1 bound-y1 sr-x2 sr-y1)
|
||||||
:right (make-selrect (+ sr-x2 2) sr-y1 frame-x2 sr-y2)
|
:right (make-selrect sr-x2 sr-y1 bound-x2 sr-y2)
|
||||||
:bottom (make-selrect sr-x1 (+ sr-y2 2) sr-x2 frame-y2)}))
|
:bottom (make-selrect sr-x1 sr-y2 sr-x2 bound-y2)}))
|
||||||
|
|
||||||
(defn distance-selrect [selrect other]
|
(defn distance-selrect [selrect other]
|
||||||
(let [{:keys [x1 y1]} other
|
(let [{:keys [x1 y1]} other
|
||||||
|
|
|
@ -7,8 +7,7 @@
|
||||||
(ns app.common.geom.shapes.common
|
(ns app.common.geom.shapes.common
|
||||||
(:require
|
(:require
|
||||||
[app.common.geom.matrix :as gmt]
|
[app.common.geom.matrix :as gmt]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]))
|
||||||
[app.common.math :as mth]))
|
|
||||||
|
|
||||||
(defn center-rect
|
(defn center-rect
|
||||||
[{:keys [x y width height]}]
|
[{:keys [x y width height]}]
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
(ns app.common.geom.shapes.rect
|
(ns app.common.geom.shapes.rect
|
||||||
(:require
|
(:require
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.geom.shapes.common :as gco]
|
|
||||||
[app.common.math :as mth]))
|
[app.common.math :as mth]))
|
||||||
|
|
||||||
(defn rect->points [{:keys [x y width height]}]
|
(defn rect->points [{:keys [x y width height]}]
|
||||||
|
@ -130,10 +129,3 @@
|
||||||
(>= (:y1 sr2) (:y1 sr1))
|
(>= (:y1 sr2) (:y1 sr1))
|
||||||
(<= (:y2 sr2) (:y2 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)))
|
|
||||||
|
|
|
@ -249,8 +249,8 @@
|
||||||
|
|
||||||
;; This rectangle is the new data for the current rectangle. We want to change our rectangle
|
;; This rectangle is the new data for the current rectangle. We want to change our rectangle
|
||||||
;; to have this width, height, x, y
|
;; to have this width, height, x, y
|
||||||
new-width (max 1 (:width points-temp-dim))
|
new-width (max 0.01 (:width points-temp-dim))
|
||||||
new-height (max 1 (:height points-temp-dim))
|
new-height (max 0.01 (:height points-temp-dim))
|
||||||
selrect (gco/make-centered-selrect center new-width new-height)
|
selrect (gco/make-centered-selrect center new-width new-height)
|
||||||
|
|
||||||
rect-points (gpr/rect->points selrect)
|
rect-points (gpr/rect->points selrect)
|
||||||
|
@ -263,7 +263,7 @@
|
||||||
(defn- apply-transform
|
(defn- apply-transform
|
||||||
"Given a new set of points transformed, set up the rectangle so it keeps
|
"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"
|
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)
|
(let [points' (:points shape)
|
||||||
points (gco/transform-points points' transform-mtx)
|
points (gco/transform-points points' transform-mtx)
|
||||||
|
@ -276,8 +276,8 @@
|
||||||
[(gpr/points->selrect points) nil nil]
|
[(gpr/points->selrect points) nil nil]
|
||||||
(adjust-rotated-transform shape points))
|
(adjust-rotated-transform shape points))
|
||||||
|
|
||||||
selrect (cond-> selrect
|
;;selrect (cond-> selrect
|
||||||
round-coords? gpr/round-selrect)
|
;; round-coords? gpr/round-selrect)
|
||||||
|
|
||||||
;; Redondear los points?
|
;; Redondear los points?
|
||||||
base-rotation (or (:rotation shape) 0)
|
base-rotation (or (:rotation shape) 0)
|
||||||
|
@ -345,7 +345,7 @@
|
||||||
;; need to remove the flip flags
|
;; need to remove the flip flags
|
||||||
(assoc :flip-x false)
|
(assoc :flip-x false)
|
||||||
(assoc :flip-y false)
|
(assoc :flip-y false)
|
||||||
(apply-transform (gmt/matrix) true))))
|
(apply-transform (gmt/matrix)))))
|
||||||
|
|
||||||
(defn update-mask-selrect
|
(defn update-mask-selrect
|
||||||
[masked-group children]
|
[masked-group children]
|
||||||
|
@ -525,7 +525,6 @@
|
||||||
(d/parse-double)
|
(d/parse-double)
|
||||||
(* (get-in modifiers [:resize-vector :x] 1))
|
(* (get-in modifiers [:resize-vector :x] 1))
|
||||||
(* (get-in modifiers [:resize-vector-2 :x] 1))
|
(* (get-in modifiers [:resize-vector-2 :x] 1))
|
||||||
(mth/precision 2)
|
|
||||||
(str))]
|
(str))]
|
||||||
(attrs/merge attrs {:font-size font-size})))]
|
(attrs/merge attrs {:font-size font-size})))]
|
||||||
(update shape :content #(txt/transform-nodes
|
(update shape :content #(txt/transform-nodes
|
||||||
|
@ -535,35 +534,32 @@
|
||||||
shape))
|
shape))
|
||||||
|
|
||||||
(defn apply-modifiers
|
(defn apply-modifiers
|
||||||
[shape modifiers round-coords?]
|
[shape modifiers]
|
||||||
(let [center (gco/center-shape shape)
|
(let [center (gco/center-shape shape)
|
||||||
transform (modifiers->transform center modifiers)]
|
transform (modifiers->transform center modifiers)]
|
||||||
(apply-transform shape transform round-coords?)))
|
(apply-transform shape transform)))
|
||||||
|
|
||||||
(defn transform-shape
|
(defn transform-shape
|
||||||
([shape]
|
[shape]
|
||||||
(transform-shape shape nil))
|
(let [modifiers (:modifiers shape)]
|
||||||
|
(cond
|
||||||
|
(nil? modifiers)
|
||||||
|
shape
|
||||||
|
|
||||||
([shape {:keys [round-coords?] :or {round-coords? true}}]
|
(empty-modifiers? modifiers)
|
||||||
(let [modifiers (:modifiers shape)]
|
(dissoc shape :modifiers)
|
||||||
(cond
|
|
||||||
(nil? modifiers)
|
|
||||||
shape
|
|
||||||
|
|
||||||
(empty-modifiers? modifiers)
|
:else
|
||||||
(dissoc shape :modifiers)
|
(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
|
:always
|
||||||
(let [shape (apply-displacement shape)
|
(dissoc :modifiers))))))
|
||||||
modifiers (:modifiers shape)]
|
|
||||||
(cond-> shape
|
|
||||||
(not (empty-modifiers? modifiers))
|
|
||||||
(-> (set-flip modifiers)
|
|
||||||
(apply-modifiers modifiers round-coords?)
|
|
||||||
(apply-text-resize modifiers))
|
|
||||||
|
|
||||||
:always
|
|
||||||
(dissoc :modifiers)))))))
|
|
||||||
|
|
||||||
(defn transform-selrect
|
(defn transform-selrect
|
||||||
[selrect {:keys [displacement resize-transform-inverse resize-vector resize-origin resize-vector-2 resize-origin-2]}]
|
[selrect {:keys [displacement resize-transform-inverse resize-vector resize-origin resize-vector-2 resize-origin-2]}]
|
||||||
|
|
|
@ -115,7 +115,7 @@
|
||||||
|
|
||||||
(defn precision
|
(defn precision
|
||||||
[v n]
|
[v n]
|
||||||
(when (and (number? v) (number? n))
|
(when (and (number? v) (integer? n))
|
||||||
(let [d (pow 10 n)]
|
(let [d (pow 10 n)]
|
||||||
(/ (round (* v d)) d))))
|
(/ (round (* v d)) d))))
|
||||||
|
|
||||||
|
@ -165,3 +165,7 @@
|
||||||
[v0 v1 t]
|
[v0 v1 t]
|
||||||
(+ (* (- 1 t) v0)
|
(+ (* (- 1 t) v0)
|
||||||
(* t v1)))
|
(* t v1)))
|
||||||
|
|
||||||
|
(defn max-abs
|
||||||
|
[a b]
|
||||||
|
(max (abs a) (abs b)))
|
||||||
|
|
|
@ -91,8 +91,8 @@
|
||||||
(def empty-selrect
|
(def empty-selrect
|
||||||
{:x 0 :y 0
|
{:x 0 :y 0
|
||||||
:x1 0 :y1 0
|
:x1 0 :y1 0
|
||||||
:x2 1 :y2 1
|
:x2 0.01 :y2 0.01
|
||||||
:width 1 :height 1})
|
:width 0.01 :height 0.01})
|
||||||
|
|
||||||
(defn make-minimal-shape
|
(defn make-minimal-shape
|
||||||
[type]
|
[type]
|
||||||
|
@ -111,16 +111,16 @@
|
||||||
(not= :path (:type shape))
|
(not= :path (:type shape))
|
||||||
(assoc :x 0
|
(assoc :x 0
|
||||||
:y 0
|
:y 0
|
||||||
:width 1
|
:width 0.01
|
||||||
:height 1
|
:height 0.01
|
||||||
:selrect {:x 0
|
:selrect {:x 0
|
||||||
:y 0
|
:y 0
|
||||||
:x1 0
|
:x1 0
|
||||||
:y1 0
|
:y1 0
|
||||||
:x2 1
|
:x2 0.01
|
||||||
:y2 1
|
:y2 0.01
|
||||||
:width 1
|
:width 0.01
|
||||||
:height 1}))))
|
:height 0.01}))))
|
||||||
|
|
||||||
(defn make-minimal-group
|
(defn make-minimal-group
|
||||||
[frame-id selection-rect group-name]
|
[frame-id selection-rect group-name]
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
[app.common.geom.matrix :as gmt]
|
[app.common.geom.matrix :as gmt]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.math :refer [close?]]
|
[app.common.math :as mth]
|
||||||
[app.common.pages :refer [make-minimal-shape]]
|
[app.common.pages :refer [make-minimal-shape]]
|
||||||
[clojure.test :as t]))
|
[clojure.test :as t]))
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
(t/testing "Shape without modifiers should stay the same"
|
(t/testing "Shape without modifiers should stay the same"
|
||||||
(t/are [type]
|
(t/are [type]
|
||||||
(let [shape-before (create-test-shape 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))
|
(= shape-before shape-after))
|
||||||
|
|
||||||
:rect :path))
|
:rect :path))
|
||||||
|
@ -61,7 +61,7 @@
|
||||||
(t/are [type]
|
(t/are [type]
|
||||||
(let [modifiers {:displacement (gmt/translate-matrix (gpt/point 10 -10))}]
|
(let [modifiers {:displacement (gmt/translate-matrix (gpt/point 10 -10))}]
|
||||||
(let [shape-before (create-test-shape type {:modifiers modifiers})
|
(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 (not= shape-before shape-after))
|
||||||
|
|
||||||
(t/is (close? (get-in shape-before [:selrect :x])
|
(t/is (close? (get-in shape-before [:selrect :x])
|
||||||
|
@ -82,7 +82,7 @@
|
||||||
(t/are [type]
|
(t/are [type]
|
||||||
(let [modifiers {:displacement (gmt/matrix)}
|
(let [modifiers {:displacement (gmt/matrix)}
|
||||||
shape-before (create-test-shape type {:modifiers modifiers})
|
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/are [prop]
|
||||||
(t/is (close? (get-in shape-before [:selrect prop])
|
(t/is (close? (get-in shape-before [:selrect prop])
|
||||||
(get-in shape-after [:selrect prop])))
|
(get-in shape-after [:selrect prop])))
|
||||||
|
@ -95,7 +95,7 @@
|
||||||
:resize-vector (gpt/point 2 2)
|
:resize-vector (gpt/point 2 2)
|
||||||
:resize-transform (gmt/matrix)}
|
:resize-transform (gmt/matrix)}
|
||||||
shape-before (create-test-shape type {:modifiers modifiers})
|
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 (not= shape-before shape-after))
|
||||||
|
|
||||||
(t/is (close? (get-in shape-before [:selrect :x])
|
(t/is (close? (get-in shape-before [:selrect :x])
|
||||||
|
@ -117,7 +117,7 @@
|
||||||
:resize-vector (gpt/point 1 1)
|
:resize-vector (gpt/point 1 1)
|
||||||
:resize-transform (gmt/matrix)}
|
:resize-transform (gmt/matrix)}
|
||||||
shape-before (create-test-shape type {:modifiers modifiers})
|
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/are [prop]
|
||||||
(t/is (close? (get-in shape-before [:selrect prop])
|
(t/is (close? (get-in shape-before [:selrect prop])
|
||||||
(get-in shape-after [:selrect prop])))
|
(get-in shape-after [:selrect prop])))
|
||||||
|
@ -130,7 +130,7 @@
|
||||||
:resize-vector (gpt/point 0 0)
|
:resize-vector (gpt/point 0 0)
|
||||||
:resize-transform (gmt/matrix)}
|
:resize-transform (gmt/matrix)}
|
||||||
shape-before (create-test-shape type {:modifiers modifiers})
|
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])
|
(t/is (> (get-in shape-before [:selrect :width])
|
||||||
(get-in shape-after [:selrect :width])))
|
(get-in shape-after [:selrect :width])))
|
||||||
(t/is (> (get-in shape-after [:selrect :width]) 0))
|
(t/is (> (get-in shape-after [:selrect :width]) 0))
|
||||||
|
@ -144,7 +144,7 @@
|
||||||
(t/are [type]
|
(t/are [type]
|
||||||
(let [modifiers {:rotation 30}
|
(let [modifiers {:rotation 30}
|
||||||
shape-before (create-test-shape type {:modifiers modifiers})
|
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 (not= shape-before shape-after))
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@
|
||||||
(t/are [type]
|
(t/are [type]
|
||||||
(let [modifiers {:rotation 0}
|
(let [modifiers {:rotation 0}
|
||||||
shape-before (create-test-shape type {:modifiers modifiers})
|
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/are [prop]
|
||||||
(t/is (close? (get-in shape-before [:selrect prop])
|
(t/is (close? (get-in shape-before [:selrect prop])
|
||||||
(get-in shape-after [:selrect prop])))
|
(get-in shape-after [:selrect prop])))
|
||||||
|
@ -180,7 +180,7 @@
|
||||||
(let [modifiers {:displacement (gmt/matrix)}
|
(let [modifiers {:displacement (gmt/matrix)}
|
||||||
shape-before (-> (create-test-shape type {:modifiers modifiers})
|
shape-before (-> (create-test-shape type {:modifiers modifiers})
|
||||||
(assoc :selrect selrect))
|
(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-before)
|
||||||
(:selrect shape-after)))
|
(:selrect shape-after)))
|
||||||
|
|
||||||
|
|
|
@ -241,12 +241,13 @@ $height-palette-max: 80px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.viewport-overlays {
|
.viewport-overlays {
|
||||||
|
cursor: initial;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
pointer-events: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
pointer-events: none;
|
|
||||||
cursor: initial;
|
|
||||||
|
|
||||||
.pixel-overlay {
|
.pixel-overlay {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
(ns app.main.data.workspace.comments
|
(ns app.main.data.workspace.comments
|
||||||
(:require
|
(:require
|
||||||
[app.common.math :as mth]
|
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
[app.main.data.comments :as dcm]
|
[app.main.data.comments :as dcm]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
|
@ -78,8 +77,8 @@
|
||||||
(fn [{:keys [vbox zoom] :as local}]
|
(fn [{:keys [vbox zoom] :as local}]
|
||||||
(let [pw (/ 160 zoom)
|
(let [pw (/ 160 zoom)
|
||||||
ph (/ 160 zoom)
|
ph (/ 160 zoom)
|
||||||
nw (mth/round (- (/ (:width vbox) 2) pw))
|
nw (- (/ (:width vbox) 2) pw)
|
||||||
nh (mth/round (- (/ (:height vbox) 2) ph))
|
nh (- (/ (:height vbox) 2) ph)
|
||||||
nx (- (:x position) nw)
|
nx (- (:x position) nw)
|
||||||
ny (- (:y position) nh)]
|
ny (- (:y position) nh)]
|
||||||
(update local :vbox assoc :x nx :y ny)))))))
|
(update local :vbox assoc :x nx :y ny)))))))
|
||||||
|
|
|
@ -27,8 +27,8 @@
|
||||||
shapev (gpt/point width height)
|
shapev (gpt/point width height)
|
||||||
deltav (gpt/to-vec initial point)
|
deltav (gpt/to-vec initial point)
|
||||||
scalev (-> (gpt/divide (gpt/add shapev deltav) shapev)
|
scalev (-> (gpt/divide (gpt/add shapev deltav) shapev)
|
||||||
(update :x truncate-zero 1)
|
(update :x truncate-zero 0.01)
|
||||||
(update :y truncate-zero 1))
|
(update :y truncate-zero 0.01))
|
||||||
scalev (if lock?
|
scalev (if lock?
|
||||||
(let [v (max (:x scalev) (:y scalev))]
|
(let [v (max (:x scalev) (:y scalev))]
|
||||||
(gpt/point v v))
|
(gpt/point v v))
|
||||||
|
@ -45,9 +45,7 @@
|
||||||
(defn move-drawing
|
(defn move-drawing
|
||||||
[{:keys [x y]}]
|
[{:keys [x y]}]
|
||||||
(fn [state]
|
(fn [state]
|
||||||
(let [x (mth/precision x 0)
|
(update-in state [:workspace-drawing :object] gsh/absolute-move (gpt/point x y))))
|
||||||
y (mth/precision y 0)]
|
|
||||||
(update-in state [:workspace-drawing :object] gsh/absolute-move (gpt/point x y)))))
|
|
||||||
|
|
||||||
(defn handle-drawing-box []
|
(defn handle-drawing-box []
|
||||||
(ptk/reify ::handle-drawing-box
|
(ptk/reify ::handle-drawing-box
|
||||||
|
@ -72,7 +70,7 @@
|
||||||
|
|
||||||
shape (-> state
|
shape (-> state
|
||||||
(get-in [:workspace-drawing :object])
|
(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 :frame-id fid)
|
||||||
(assoc :initialized? true)
|
(assoc :initialized? true)
|
||||||
(assoc :click-draw? true))]
|
(assoc :click-draw? true))]
|
||||||
|
@ -85,7 +83,7 @@
|
||||||
(rx/map move-drawing))
|
(rx/map move-drawing))
|
||||||
|
|
||||||
(->> ms/mouse-position
|
(->> 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/with-latest vector ms/mouse-position-shift)
|
||||||
(rx/switch-map
|
(rx/switch-map
|
||||||
(fn [[point :as current]]
|
(fn [[point :as current]]
|
||||||
|
|
|
@ -6,8 +6,9 @@
|
||||||
|
|
||||||
(ns app.main.data.workspace.drawing.common
|
(ns app.main.data.workspace.drawing.common
|
||||||
(:require
|
(:require
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.matrix :as gmt]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
|
[app.common.math :as mth]
|
||||||
[app.main.data.workspace.common :as dwc]
|
[app.main.data.workspace.common :as dwc]
|
||||||
[app.main.data.workspace.undo :as dwu]
|
[app.main.data.workspace.undo :as dwu]
|
||||||
[app.main.worker :as uw]
|
[app.main.worker :as uw]
|
||||||
|
@ -29,27 +30,30 @@
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(when (:initialized? shape)
|
(when (:initialized? shape)
|
||||||
(let [page-id (:current-page-id state)
|
(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
|
click-draw? (:click-draw? shape)
|
||||||
(= (:type shape) :text) (assoc :grow-type
|
text? (= :text (:type shape))
|
||||||
(if (:click-draw? shape) :auto-width :fixed)))
|
|
||||||
|
|
||||||
shape (-> shape
|
min-side (min 100
|
||||||
(gsh/transform-shape)
|
(mth/floor (get-in state [:workspace-local :vbox :width]))
|
||||||
(dissoc :initialized? :click-draw?))]
|
(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
|
;; Add & select the created shape to the workspace
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(if (= :text (:type shape))
|
(if (= :text (:type shape))
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
[app.common.geom.matrix :as gmt]
|
[app.common.geom.matrix :as gmt]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.math :as mth]
|
|
||||||
[app.common.pages.changes-builder :as pcb]
|
[app.common.pages.changes-builder :as pcb]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.spec :refer [max-safe-int min-safe-int]]
|
[app.common.spec :refer [max-safe-int min-safe-int]]
|
||||||
|
|
|
@ -495,12 +495,13 @@
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(let [initial (deref ms/mouse-position)
|
(let [initial (deref ms/mouse-position)
|
||||||
selected (wsh/lookup-selected state {:omit-blocked? true})
|
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)
|
(when-not (empty? selected)
|
||||||
(->> ms/mouse-position
|
(->> ms/mouse-position
|
||||||
(rx/map #(gpt/to-vec initial %))
|
(rx/map #(gpt/to-vec initial %))
|
||||||
(rx/map #(gpt/length %))
|
(rx/map #(gpt/length %))
|
||||||
(rx/filter #(> % 1))
|
(rx/filter #(> % (/ 10 zoom)))
|
||||||
(rx/take 1)
|
(rx/take 1)
|
||||||
(rx/with-latest vector ms/mouse-position-alt)
|
(rx/with-latest vector ms/mouse-position-alt)
|
||||||
(rx/mapcat
|
(rx/mapcat
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
(def ^:const snap-accuracy 10)
|
(def ^:const snap-accuracy 10)
|
||||||
(def ^:const snap-path-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
|
(defn- remove-from-snap-points
|
||||||
[remove-snap?]
|
[remove-snap?]
|
||||||
|
@ -82,13 +82,13 @@
|
||||||
;; Otherwise the root frame is the common
|
;; Otherwise the root frame is the common
|
||||||
:else zero)))
|
: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)]
|
(let [value (get point coord)]
|
||||||
(->> (uw/ask! {:cmd :snaps/range-query
|
(->> (uw/ask! {:cmd :snaps/range-query
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:frame-id frame-id
|
:frame-id frame-id
|
||||||
:axis coord
|
:axis coord
|
||||||
:ranges [[(- value 0.5) (+ value 0.5)]]})
|
:ranges [[(- value (/ 0.5 zoom)) (+ value (/ 0.5 zoom))]]})
|
||||||
(rx/take 1)
|
(rx/take 1)
|
||||||
(rx/map (remove-from-snap-points remove-snap?))
|
(rx/map (remove-from-snap-points remove-snap?))
|
||||||
(rx/map flatten-to-points))))
|
(rx/map flatten-to-points))))
|
||||||
|
@ -238,6 +238,18 @@
|
||||||
(rx/map #(or % (gpt/point 0 0)))
|
(rx/map #(or % (gpt/point 0 0)))
|
||||||
(rx/map #(gpt/add point %)))))
|
(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
|
(defn closest-snap-move
|
||||||
[page-id shapes objects layout zoom focus movev]
|
[page-id shapes objects layout zoom focus movev]
|
||||||
(let [frame-id (snap-frame-id shapes)
|
(let [frame-id (snap-frame-id shapes)
|
||||||
|
@ -256,7 +268,7 @@
|
||||||
(->> (rx/merge (closest-snap page-id frame-id shapes-points remove-snap? zoom)
|
(->> (rx/merge (closest-snap page-id frame-id shapes-points remove-snap? zoom)
|
||||||
(when (contains? layout :dynamic-alignment)
|
(when (contains? layout :dynamic-alignment)
|
||||||
(closest-distance-snap page-id shapes objects zoom movev)))
|
(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))))))
|
(rx/map #(or % (gpt/point 0 0))))))
|
||||||
|
|
||||||
|
|
||||||
|
@ -360,8 +372,8 @@
|
||||||
dy (if (not= 0 (:y snap-delta))
|
dy (if (not= 0 (:y snap-delta))
|
||||||
(- (+ (:y snap-pos) (:y snap-delta)) (:y position))
|
(- (+ (:y snap-pos) (:y snap-delta)) (:y position))
|
||||||
0)]
|
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))
|
position))
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
(ns app.main.ui.components.editable-select
|
(ns app.main.ui.components.editable-select
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.math :as math]
|
[app.common.math :as mth]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.ui.components.dropdown :refer [dropdown]]
|
[app.main.ui.components.dropdown :refer [dropdown]]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
|
@ -29,8 +29,8 @@
|
||||||
max-val (get params :max)
|
max-val (get params :max)
|
||||||
|
|
||||||
num? (fn [val] (and (number? val)
|
num? (fn [val] (and (number? val)
|
||||||
(not (math/nan? val))
|
(not (mth/nan? val))
|
||||||
(math/finite? val)))
|
(mth/finite? val)))
|
||||||
|
|
||||||
emit-blur? (mf/use-ref nil)
|
emit-blur? (mf/use-ref nil)
|
||||||
font-size-wrapper-ref (mf/use-ref)
|
font-size-wrapper-ref (mf/use-ref)
|
||||||
|
@ -58,8 +58,7 @@
|
||||||
handle-change-input
|
handle-change-input
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [value (-> event dom/get-target dom/get-value)
|
(let [value (-> event dom/get-target dom/get-value)
|
||||||
value (-> (or (d/parse-double value) value)
|
value (or (d/parse-double value) value)]
|
||||||
(math/precision 2))]
|
|
||||||
(set-value value)))
|
(set-value value)))
|
||||||
|
|
||||||
on-node-load
|
on-node-load
|
||||||
|
@ -89,8 +88,7 @@
|
||||||
(when (or up? down?)
|
(when (or up? down?)
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(let [value (-> event dom/get-target dom/get-value)
|
(let [value (-> event dom/get-target dom/get-value)
|
||||||
value (-> (or (d/parse-double value) value)
|
value (or (d/parse-double value) value)
|
||||||
(math/precision 2))
|
|
||||||
|
|
||||||
increment (cond
|
increment (cond
|
||||||
(kbd/shift? event)
|
(kbd/shift? event)
|
||||||
|
@ -102,8 +100,7 @@
|
||||||
:else
|
:else
|
||||||
(if up? 1 -1))
|
(if up? 1 -1))
|
||||||
|
|
||||||
new-value (-> (+ value increment)
|
new-value (+ value increment)
|
||||||
(math/precision 2))
|
|
||||||
|
|
||||||
new-value (cond
|
new-value (cond
|
||||||
(and (num? min-val) (< new-value min-val)) min-val
|
(and (num? min-val) (< new-value min-val)) min-val
|
||||||
|
@ -135,7 +132,7 @@
|
||||||
(let [wrapper-node (mf/ref-val font-size-wrapper-ref)
|
(let [wrapper-node (mf/ref-val font-size-wrapper-ref)
|
||||||
node (dom/get-element-by-class "checked-element is-selected" wrapper-node)
|
node (dom/get-element-by-class "checked-element is-selected" wrapper-node)
|
||||||
nodes (dom/get-elements-by-class "checked-element-value" 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))]
|
closest-value (str (closest options value))]
|
||||||
(when (:is-open? @state)
|
(when (:is-open? @state)
|
||||||
(if (some? node)
|
(if (some? node)
|
||||||
|
|
|
@ -6,23 +6,22 @@
|
||||||
|
|
||||||
(ns app.main.ui.components.numeric-input
|
(ns app.main.ui.components.numeric-input
|
||||||
(:require
|
(:require
|
||||||
|
[app.main.ui.formats :as fmt]
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.math :as math]
|
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.globals :as globals]
|
[app.util.globals :as globals]
|
||||||
[app.util.keyboard :as kbd]
|
[app.util.keyboard :as kbd]
|
||||||
[app.util.object :as obj]
|
[app.util.object :as obj]
|
||||||
[app.util.simple-math :as sm]
|
[app.util.simple-math :as sm]
|
||||||
[app.util.strings :as ust]
|
|
||||||
[goog.events :as events]
|
[goog.events :as events]
|
||||||
[rumext.alpha :as mf])
|
[rumext.alpha :as mf])
|
||||||
(:import goog.events.EventType))
|
(:import goog.events.EventType))
|
||||||
|
|
||||||
(defn num? [val]
|
(defn num? [val]
|
||||||
(and (number? val)
|
(and (number? val)
|
||||||
(not (math/nan? val))
|
(not (mth/nan? val))
|
||||||
(math/finite? val)))
|
(mth/finite? val)))
|
||||||
|
|
||||||
(mf/defc numeric-input
|
(mf/defc numeric-input
|
||||||
{::mf/wrap-props false
|
{::mf/wrap-props false
|
||||||
|
@ -37,7 +36,6 @@
|
||||||
on-blur (obj/get props "onBlur")
|
on-blur (obj/get props "onBlur")
|
||||||
title (obj/get props "title")
|
title (obj/get props "title")
|
||||||
default-val (obj/get props "default" 0)
|
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
|
;; We need a ref pointing to the input dom element, but the user
|
||||||
;; of this component may provide one (that is forwarded here).
|
;; of this component may provide one (that is forwarded here).
|
||||||
|
@ -85,10 +83,6 @@
|
||||||
(sm/expr-eval value))]
|
(sm/expr-eval value))]
|
||||||
(when (num? new-value)
|
(when (num? new-value)
|
||||||
(-> new-value
|
(-> new-value
|
||||||
(cond-> (number? precision)
|
|
||||||
(math/precision precision))
|
|
||||||
(cond-> (nil? precision)
|
|
||||||
(math/round))
|
|
||||||
(cljs.core/max us/min-safe-int)
|
(cljs.core/max us/min-safe-int)
|
||||||
(cljs.core/min us/max-safe-int)
|
(cljs.core/min us/max-safe-int)
|
||||||
(cond->
|
(cond->
|
||||||
|
@ -103,9 +97,7 @@
|
||||||
(mf/deps ref)
|
(mf/deps ref)
|
||||||
(fn [new-value]
|
(fn [new-value]
|
||||||
(let [input-node (mf/ref-val ref)]
|
(let [input-node (mf/ref-val ref)]
|
||||||
(dom/set-value! input-node (if (some? precision)
|
(dom/set-value! input-node (fmt/format-number new-value)))))
|
||||||
(ust/format-precision new-value precision)
|
|
||||||
(str new-value))))))
|
|
||||||
|
|
||||||
apply-value
|
apply-value
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
|
@ -193,17 +185,17 @@
|
||||||
(obj/set! "className" "input-text")
|
(obj/set! "className" "input-text")
|
||||||
(obj/set! "type" "text")
|
(obj/set! "type" "text")
|
||||||
(obj/set! "ref" ref)
|
(obj/set! "ref" ref)
|
||||||
(obj/set! "defaultValue" value-str)
|
(obj/set! "defaultValue" (fmt/format-number value))
|
||||||
(obj/set! "title" title)
|
(obj/set! "title" title)
|
||||||
(obj/set! "onWheel" handle-mouse-wheel)
|
(obj/set! "onWheel" handle-mouse-wheel)
|
||||||
(obj/set! "onKeyDown" handle-key-down)
|
(obj/set! "onKeyDown" handle-key-down)
|
||||||
(obj/set! "onBlur" handle-blur))]
|
(obj/set! "onBlur" handle-blur))]
|
||||||
|
|
||||||
(mf/use-effect
|
(mf/use-effect
|
||||||
(mf/deps value-str)
|
(mf/deps value)
|
||||||
(fn []
|
(fn []
|
||||||
(when-let [input-node (mf/ref-val ref)]
|
(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/use-effect
|
||||||
(mf/deps handle-blur)
|
(mf/deps handle-blur)
|
||||||
|
|
36
frontend/src/app/main/ui/formats.cljs
Normal file
36
frontend/src/app/main/ui/formats.cljs
Normal file
|
@ -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)))
|
|
@ -12,6 +12,7 @@
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.math :as mth]
|
[app.common.math :as mth]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
|
[app.main.ui.formats :as fmt]
|
||||||
[rumext.alpha :as mf]))
|
[rumext.alpha :as mf]))
|
||||||
|
|
||||||
;; ------------------------------------------------
|
;; ------------------------------------------------
|
||||||
|
@ -97,7 +98,7 @@
|
||||||
|
|
||||||
(mf/defc size-display [{:keys [selrect zoom]}]
|
(mf/defc size-display [{:keys [selrect zoom]}]
|
||||||
(let [{:keys [x y width height]} selrect
|
(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-height (/ size-display-height zoom)
|
||||||
rect-width (/ (if (<= (count size-label) 9)
|
rect-width (/ (if (<= (count size-label) 9)
|
||||||
|
@ -164,7 +165,7 @@
|
||||||
:height distance-pill-height
|
:height distance-pill-height
|
||||||
:style {:fill distance-text-color
|
:style {:fill distance-text-color
|
||||||
:font-size font-size}}
|
:font-size font-size}}
|
||||||
distance]]))
|
(fmt/format-pixels distance)]]))
|
||||||
|
|
||||||
(mf/defc selection-rect [{:keys [selrect zoom]}]
|
(mf/defc selection-rect [{:keys [selrect zoom]}]
|
||||||
(let [{:keys [x y width height]} selrect
|
(let [{:keys [x y width height]} selrect
|
||||||
|
@ -214,7 +215,7 @@
|
||||||
{:x center-x
|
{:x center-x
|
||||||
:y center-y
|
:y center-y
|
||||||
:zoom zoom
|
:zoom zoom
|
||||||
:distance (dm/str (mth/round distance) "px")
|
:distance distance
|
||||||
:bounds bounds}]])))))
|
:bounds bounds}]])))))
|
||||||
|
|
||||||
(mf/defc selection-guides [{:keys [bounds selrect zoom]}]
|
(mf/defc selection-guides [{:keys [bounds selrect zoom]}]
|
||||||
|
|
|
@ -83,7 +83,7 @@
|
||||||
base #js {:textDecoration text-decoration
|
base #js {:textDecoration text-decoration
|
||||||
:textTransform text-transform
|
:textTransform text-transform
|
||||||
:lineHeight (or line-height "inherit")
|
:lineHeight (or line-height "inherit")
|
||||||
:color (if show-text? text-color "transparent")
|
:color (if show-text? text-color "red")
|
||||||
:caretColor (or text-color "black")
|
:caretColor (or text-color "black")
|
||||||
:overflowWrap "initial"}
|
:overflowWrap "initial"}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
(ns app.main.ui.viewer.handoff.attributes.common
|
(ns app.main.ui.viewer.handoff.attributes.common
|
||||||
(:require
|
(:require
|
||||||
[app.common.math :as mth]
|
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.color-bullet :refer [color-bullet color-name]]
|
[app.main.ui.components.color-bullet :refer [color-bullet color-name]]
|
||||||
[app.main.ui.components.copy-button :refer [copy-button]]
|
[app.main.ui.components.copy-button :refer [copy-button]]
|
||||||
|
@ -50,9 +49,9 @@
|
||||||
(if (:gradient color)
|
(if (:gradient color)
|
||||||
[:& color-name {:color color}]
|
[:& color-name {:color color}]
|
||||||
(case format
|
(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)])
|
[: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)])
|
[:div (str/fmt "%s, %s, %s, %s" h s l a)])
|
||||||
[:*
|
[:*
|
||||||
[:& color-name {:color color}]
|
[:& color-name {:color color}]
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
(ns app.main.ui.viewer.handoff.attributes.layout
|
(ns app.main.ui.viewer.handoff.attributes.layout
|
||||||
(:require
|
(:require
|
||||||
[app.common.math :as mth]
|
|
||||||
[app.common.spec.radius :as ctr]
|
[app.common.spec.radius :as ctr]
|
||||||
[app.main.ui.components.copy-button :refer [copy-button]]
|
[app.main.ui.components.copy-button :refer [copy-button]]
|
||||||
[app.util.code-gen :as cg]
|
[app.util.code-gen :as cg]
|
||||||
|
@ -39,46 +38,46 @@
|
||||||
[:*
|
[:*
|
||||||
[:div.attributes-unit-row
|
[:div.attributes-unit-row
|
||||||
[:div.attributes-label (t locale "handoff.attributes.layout.width")]
|
[: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)}]]
|
[:& copy-button {:data (copy-data selrect :width)}]]
|
||||||
|
|
||||||
[:div.attributes-unit-row
|
[:div.attributes-unit-row
|
||||||
[:div.attributes-label (t locale "handoff.attributes.layout.height")]
|
[: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)}]]
|
[:& copy-button {:data (copy-data selrect :height)}]]
|
||||||
|
|
||||||
(when (not= (:x shape) 0)
|
(when (not= (:x shape) 0)
|
||||||
[:div.attributes-unit-row
|
[:div.attributes-unit-row
|
||||||
[:div.attributes-label (t locale "handoff.attributes.layout.left")]
|
[: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)}]])
|
[:& copy-button {:data (copy-data selrect :x)}]])
|
||||||
|
|
||||||
(when (not= (:y shape) 0)
|
(when (not= (:y shape) 0)
|
||||||
[:div.attributes-unit-row
|
[:div.attributes-unit-row
|
||||||
[:div.attributes-label (t locale "handoff.attributes.layout.top")]
|
[: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)}]])
|
[:& copy-button {:data (copy-data selrect :y)}]])
|
||||||
|
|
||||||
(when (ctr/radius-1? shape)
|
(when (ctr/radius-1? shape)
|
||||||
[:div.attributes-unit-row
|
[:div.attributes-unit-row
|
||||||
[:div.attributes-label (t locale "handoff.attributes.layout.radius")]
|
[: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)}]])
|
[:& copy-button {:data (copy-data shape :rx)}]])
|
||||||
|
|
||||||
(when (ctr/radius-4? shape)
|
(when (ctr/radius-4? shape)
|
||||||
[:div.attributes-unit-row
|
[:div.attributes-unit-row
|
||||||
[:div.attributes-label (t locale "handoff.attributes.layout.radius")]
|
[:div.attributes-label (t locale "handoff.attributes.layout.radius")]
|
||||||
[:div.attributes-value
|
[:div.attributes-value
|
||||||
(mth/precision (:r1 shape) 2) ", "
|
(:r1 shape) ", "
|
||||||
(mth/precision (:r2 shape) 2) ", "
|
(:r2 shape) ", "
|
||||||
(mth/precision (:r3 shape) 2) ", "
|
(:r3 shape) ", "
|
||||||
(mth/precision (:r4 shape) 2) "px"]
|
(:r4 shape) "px"]
|
||||||
[:& copy-button {:data (copy-data shape :r1)}]])
|
[:& copy-button {:data (copy-data shape :r1)}]])
|
||||||
|
|
||||||
(when (not= (:rotation shape 0) 0)
|
(when (not= (:rotation shape 0) 0)
|
||||||
[:div.attributes-unit-row
|
[:div.attributes-unit-row
|
||||||
[:div.attributes-label (t locale "handoff.attributes.layout.rotation")]
|
[: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)}]])]))
|
[:& copy-button {:data (copy-data shape :rotation)}]])]))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
(ns app.main.ui.viewer.handoff.attributes.stroke
|
(ns app.main.ui.viewer.handoff.attributes.stroke
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.math :as mth]
|
|
||||||
[app.main.ui.components.copy-button :refer [copy-button]]
|
[app.main.ui.components.copy-button :refer [copy-button]]
|
||||||
[app.main.ui.viewer.handoff.attributes.common :refer [color-row]]
|
[app.main.ui.viewer.handoff.attributes.common :refer [color-row]]
|
||||||
[app.util.code-gen :as cg]
|
[app.util.code-gen :as cg]
|
||||||
|
@ -67,7 +66,7 @@
|
||||||
stroke-alignment (or stroke-alignment :center)]
|
stroke-alignment (or stroke-alignment :center)]
|
||||||
[:div.attributes-stroke-row
|
[:div.attributes-stroke-row
|
||||||
[:div.attributes-label (t locale "handoff.attributes.stroke.width")]
|
[: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-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))]
|
[:div.attributes-label (->> stroke-alignment d/name (str "handoff.attributes.stroke.alignment.") (t locale))]
|
||||||
[:& copy-button {:data (copy-stroke-data shape)}]])]))
|
[:& copy-button {:data (copy-stroke-data shape)}]])]))
|
||||||
|
|
|
@ -6,16 +6,12 @@
|
||||||
|
|
||||||
(ns app.main.ui.viewer.handoff.attributes.svg
|
(ns app.main.ui.viewer.handoff.attributes.svg
|
||||||
(:require
|
(:require
|
||||||
#_[app.common.math :as mth]
|
|
||||||
#_[app.main.ui.icons :as i]
|
|
||||||
#_[app.util.code-gen :as cg]
|
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.main.ui.components.copy-button :refer [copy-button]]
|
[app.main.ui.components.copy-button :refer [copy-button]]
|
||||||
[app.util.i18n :refer [tr]]
|
[app.util.i18n :refer [tr]]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[rumext.alpha :as mf]))
|
[rumext.alpha :as mf]))
|
||||||
|
|
||||||
|
|
||||||
(defn map->css [attr]
|
(defn map->css [attr]
|
||||||
(->> attr
|
(->> attr
|
||||||
(map (fn [[attr-key attr-value]] (str (d/name attr-key) ":" attr-value)))
|
(map (fn [[attr-key attr-value]] (str (d/name attr-key) ":" attr-value)))
|
||||||
|
|
|
@ -6,13 +6,13 @@
|
||||||
|
|
||||||
(ns app.main.ui.viewer.header
|
(ns app.main.ui.viewer.header
|
||||||
(:require
|
(:require
|
||||||
[app.common.math :as mth]
|
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.viewer :as dv]
|
[app.main.data.viewer :as dv]
|
||||||
[app.main.data.viewer.shortcuts :as sc]
|
[app.main.data.viewer.shortcuts :as sc]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.dropdown :refer [dropdown]]
|
[app.main.ui.components.dropdown :refer [dropdown]]
|
||||||
|
[app.main.ui.formats :as fmt]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.main.ui.viewer.comments :refer [comments-menu]]
|
[app.main.ui.viewer.comments :refer [comments-menu]]
|
||||||
[app.main.ui.viewer.interactions :refer [flows-menu interactions-menu]]
|
[app.main.ui.viewer.interactions :refer [flows-menu interactions-menu]]
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
:as props}]
|
:as props}]
|
||||||
(let [show-dropdown? (mf/use-state false)]
|
(let [show-dropdown? (mf/use-state false)]
|
||||||
[:div.zoom-widget {:on-click #(reset! show-dropdown? true)}
|
[: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]
|
[:span.icon i/arrow-down]
|
||||||
[:& dropdown {:show @show-dropdown?
|
[:& dropdown {:show @show-dropdown?
|
||||||
:on-close #(reset! show-dropdown? false)}
|
:on-close #(reset! show-dropdown? false)}
|
||||||
|
@ -43,7 +43,7 @@
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(on-decrease))} "-"]
|
(on-decrease))} "-"]
|
||||||
[:p.zoom-size {} (str (mth/round (* 100 zoom)) "%")]
|
[:p.zoom-size (fmt/format-percent zoom)]
|
||||||
[:button {:on-click (fn [event]
|
[:button {:on-click (fn [event]
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
(ns app.main.ui.workspace.colorpalette
|
(ns app.main.ui.workspace.colorpalette
|
||||||
(:require
|
(:require
|
||||||
[app.common.math :as mth]
|
|
||||||
[app.main.data.workspace.colors :as mdc]
|
[app.main.data.workspace.colors :as mdc]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
|
@ -57,7 +56,7 @@
|
||||||
(let [state (mf/use-state {:show-menu false})
|
(let [state (mf/use-state {:show-menu false})
|
||||||
|
|
||||||
width (:width @state 0)
|
width (:width @state 0)
|
||||||
visible (mth/round (/ width 66))
|
visible (/ width 66)
|
||||||
|
|
||||||
offset (:offset @state 0)
|
offset (:offset @state 0)
|
||||||
max-offset (- (count current-colors)
|
max-offset (- (count current-colors)
|
||||||
|
@ -75,7 +74,7 @@
|
||||||
(swap! state update :offset
|
(swap! state update :offset
|
||||||
(fn [offset]
|
(fn [offset]
|
||||||
(if (pos? offset)
|
(if (pos? offset)
|
||||||
(max (- offset (mth/round (/ visible 2))) 0)
|
(max (- offset (/ visible 2)) 0)
|
||||||
offset)))))
|
offset)))))
|
||||||
|
|
||||||
on-right-arrow-click
|
on-right-arrow-click
|
||||||
|
@ -85,7 +84,7 @@
|
||||||
(swap! state update :offset
|
(swap! state update :offset
|
||||||
(fn [offset]
|
(fn [offset]
|
||||||
(if (< offset max-offset)
|
(if (< offset max-offset)
|
||||||
(min max-offset (+ offset (mth/round (/ visible 2))))
|
(min max-offset (+ offset (/ visible 2)))
|
||||||
offset)))))
|
offset)))))
|
||||||
|
|
||||||
on-scroll
|
on-scroll
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
(ns app.main.ui.workspace.colorpicker.color-inputs
|
(ns app.main.ui.workspace.colorpicker.color-inputs
|
||||||
(:require
|
(:require
|
||||||
[app.common.math :as math]
|
[app.common.math :as mth]
|
||||||
[app.util.color :as uc]
|
[app.util.color :as uc]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[rumext.alpha :as mf]))
|
[rumext.alpha :as mf]))
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
on-change-property
|
on-change-property
|
||||||
(fn [property max-value]
|
(fn [property max-value]
|
||||||
(fn [e]
|
(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)]
|
val (if (#{:s} property) (/ val 100) val)]
|
||||||
(when (not (nil? val))
|
(when (not (nil? val))
|
||||||
(if (#{:r :g :b} property)
|
(if (#{:r :g :b} property)
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
|
|
||||||
on-change-opacity
|
on-change-opacity
|
||||||
(fn [e]
|
(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})))]
|
(on-change {:alpha new-alpha})))]
|
||||||
|
|
||||||
|
|
||||||
|
@ -86,9 +86,9 @@
|
||||||
(when (and property-val property-ref)
|
(when (and property-val property-ref)
|
||||||
(when-let [node (mf/ref-val property-ref)]
|
(when-let [node (mf/ref-val property-ref)]
|
||||||
(case ref-key
|
(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)
|
:hex (dom/set-value! node property-val)
|
||||||
(dom/set-value! node (math/round property-val)))))))))
|
(dom/set-value! node property-val))))))))
|
||||||
|
|
||||||
[:div.color-values
|
[:div.color-values
|
||||||
{:class (when disable-opacity "disable-opacity")}
|
{:class (when disable-opacity "disable-opacity")}
|
||||||
|
@ -156,7 +156,7 @@
|
||||||
:min 0
|
:min 0
|
||||||
:step 1
|
:step 1
|
||||||
:max 100
|
:max 100
|
||||||
:default-value (if (= alpha :multiple) "" (math/precision alpha 2))
|
:default-value (if (= alpha :multiple) "" alpha)
|
||||||
:on-change on-change-opacity}])
|
:on-change on-change-opacity}])
|
||||||
|
|
||||||
[:label.hex-label {:for "hex-value"} "HEX"]
|
[:label.hex-label {:for "hex-value"} "HEX"]
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
(ns app.main.ui.workspace.colorpicker.harmony
|
(ns app.main.ui.workspace.colorpicker.harmony
|
||||||
(:require
|
(:require
|
||||||
[app.common.geom.point :as gpt]
|
[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.main.ui.workspace.colorpicker.slider-selector :refer [slider-selector]]
|
||||||
[app.util.color :as uc]
|
[app.util.color :as uc]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
|
@ -28,9 +28,9 @@
|
||||||
(.clearRect ctx 0 0 width height)
|
(.clearRect ctx 0 0 width height)
|
||||||
|
|
||||||
(doseq [degrees (range 0 360 step)]
|
(doseq [degrees (range 0 360 step)]
|
||||||
(let [degrees-rad (math/radians degrees)
|
(let [degrees-rad (mth/radians degrees)
|
||||||
x (* radius (math/cos (- degrees-rad)))
|
x (* radius (mth/cos (- degrees-rad)))
|
||||||
y (* radius (math/sin (- degrees-rad)))]
|
y (* radius (mth/sin (- degrees-rad)))]
|
||||||
(obj/set! ctx "strokeStyle" (str/format "hsl(%s, 100%, 50%)" degrees))
|
(obj/set! ctx "strokeStyle" (str/format "hsl(%s, 100%, 50%)" degrees))
|
||||||
(.beginPath ctx)
|
(.beginPath ctx)
|
||||||
(.moveTo ctx cx cy)
|
(.moveTo ctx cx cy)
|
||||||
|
@ -43,15 +43,15 @@
|
||||||
(obj/set! ctx "fillStyle" grd)
|
(obj/set! ctx "fillStyle" grd)
|
||||||
|
|
||||||
(.beginPath ctx)
|
(.beginPath ctx)
|
||||||
(.arc ctx cx cy radius 0 (* 2 math/PI) true)
|
(.arc ctx cx cy radius 0 (* 2 mth/PI) true)
|
||||||
(.closePath ctx)
|
(.closePath ctx)
|
||||||
(.fill ctx))))
|
(.fill ctx))))
|
||||||
|
|
||||||
(defn color->point
|
(defn color->point
|
||||||
[canvas-side hue saturation]
|
[canvas-side hue saturation]
|
||||||
(let [hue-rad (math/radians (- hue))
|
(let [hue-rad (mth/radians (- hue))
|
||||||
comp-x (* saturation (math/cos hue-rad))
|
comp-x (* saturation (mth/cos hue-rad))
|
||||||
comp-y (* saturation (math/sin hue-rad))
|
comp-y (* saturation (mth/sin hue-rad))
|
||||||
x (+ (/ canvas-side 2) (* comp-x (/ canvas-side 2)))
|
x (+ (/ canvas-side 2) (* comp-x (/ canvas-side 2)))
|
||||||
y (+ (/ canvas-side 2) (* comp-y (/ canvas-side 2)))]
|
y (+ (/ canvas-side 2) (* comp-y (/ canvas-side 2)))]
|
||||||
(gpt/point x y)))
|
(gpt/point x y)))
|
||||||
|
@ -68,15 +68,15 @@
|
||||||
calculate-pos (fn [ev]
|
calculate-pos (fn [ev]
|
||||||
(let [{:keys [left right top bottom]} (-> ev dom/get-target dom/get-bounding-rect)
|
(let [{:keys [left right top bottom]} (-> ev dom/get-target dom/get-bounding-rect)
|
||||||
{:keys [x y]} (-> ev dom/get-client-position)
|
{:keys [x y]} (-> ev dom/get-client-position)
|
||||||
px (math/clamp (/ (- x left) (- right left)) 0 1)
|
px (mth/clamp (/ (- x left) (- right left)) 0 1)
|
||||||
py (math/clamp (/ (- y top) (- bottom top)) 0 1)
|
py (mth/clamp (/ (- y top) (- bottom top)) 0 1)
|
||||||
|
|
||||||
px (- (* 2 px) 1)
|
px (- (* 2 px) 1)
|
||||||
py (- (* 2 py) 1)
|
py (- (* 2 py) 1)
|
||||||
|
|
||||||
angle (math/degrees (math/atan2 px py))
|
angle (mth/degrees (mth/atan2 px py))
|
||||||
new-hue (math/precision (mod (- angle 90 ) 360) 2)
|
new-hue (mod (- angle 90 ) 360)
|
||||||
new-saturation (math/clamp (math/distance [px py] [0 0]) 0 1)
|
new-saturation (mth/clamp (mth/distance [px py] [0 0]) 0 1)
|
||||||
hex (uc/hsv->hex [new-hue new-saturation value])
|
hex (uc/hsv->hex [new-hue new-saturation value])
|
||||||
[r g b] (uc/hex->rgb hex)]
|
[r g b] (uc/hex->rgb hex)]
|
||||||
(on-change {:hex hex
|
(on-change {:hex hex
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
(ns app.main.ui.workspace.colorpicker.ramp
|
(ns app.main.ui.workspace.colorpicker.ramp
|
||||||
(:require
|
(:require
|
||||||
[app.common.math :as math]
|
[app.common.math :as mth]
|
||||||
[app.main.ui.components.color-bullet :refer [color-bullet]]
|
[app.main.ui.components.color-bullet :refer [color-bullet]]
|
||||||
[app.main.ui.workspace.colorpicker.slider-selector :refer [slider-selector]]
|
[app.main.ui.workspace.colorpicker.slider-selector :refer [slider-selector]]
|
||||||
[app.util.color :as uc]
|
[app.util.color :as uc]
|
||||||
|
@ -19,8 +19,8 @@
|
||||||
(fn [ev]
|
(fn [ev]
|
||||||
(let [{:keys [left right top bottom]} (-> ev dom/get-target dom/get-bounding-rect)
|
(let [{:keys [left right top bottom]} (-> ev dom/get-target dom/get-bounding-rect)
|
||||||
{:keys [x y]} (-> ev dom/get-client-position)
|
{:keys [x y]} (-> ev dom/get-client-position)
|
||||||
px (math/clamp (/ (- x left) (- right left)) 0 1)
|
px (mth/clamp (/ (- x left) (- right left)) 0 1)
|
||||||
py (* 255 (- 1 (math/clamp (/ (- y top) (- bottom top)) 0 1)))]
|
py (* 255 (- 1 (mth/clamp (/ (- y top) (- bottom top)) 0 1)))]
|
||||||
(on-change px py)))
|
(on-change px py)))
|
||||||
|
|
||||||
handle-start-drag
|
handle-start-drag
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
(ns app.main.ui.workspace.colorpicker.slider-selector
|
(ns app.main.ui.workspace.colorpicker.slider-selector
|
||||||
(:require
|
(:require
|
||||||
[app.common.math :as math]
|
[app.common.math :as mth]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.object :as obj]
|
[app.util.object :as obj]
|
||||||
[rumext.alpha :as mf]))
|
[rumext.alpha :as mf]))
|
||||||
|
@ -41,13 +41,13 @@
|
||||||
(let [{:keys [left right top bottom]} (-> ev dom/get-target dom/get-bounding-rect)
|
(let [{:keys [left right top bottom]} (-> ev dom/get-target dom/get-bounding-rect)
|
||||||
{:keys [x y]} (-> ev dom/get-client-position)
|
{:keys [x y]} (-> ev dom/get-client-position)
|
||||||
unit-value (if vertical?
|
unit-value (if vertical?
|
||||||
(math/clamp (/ (- bottom y) (- bottom top)) 0 1)
|
(mth/clamp (/ (- bottom y) (- bottom top)) 0 1)
|
||||||
(math/clamp (/ (- x left) (- right left)) 0 1))
|
(mth/clamp (/ (- x left) (- right left)) 0 1))
|
||||||
unit-value (if reverse?
|
unit-value (if reverse?
|
||||||
(math/abs (- unit-value 1.0))
|
(mth/abs (- unit-value 1.0))
|
||||||
unit-value)
|
unit-value)
|
||||||
value (+ min-value (* unit-value (- max-value min-value)))]
|
value (+ min-value (* unit-value (- max-value min-value)))]
|
||||||
(on-change (math/precision value 2)))))]
|
(on-change value))))]
|
||||||
|
|
||||||
[:div.slider-selector
|
[:div.slider-selector
|
||||||
{:class (str (if vertical? "vertical " "") class)
|
{:class (str (if vertical? "vertical " "") class)
|
||||||
|
@ -60,7 +60,7 @@
|
||||||
(- max-value min-value)) 100)
|
(- max-value min-value)) 100)
|
||||||
|
|
||||||
value-percent (if reverse?
|
value-percent (if reverse?
|
||||||
(math/abs (- value-percent 100))
|
(mth/abs (- value-percent 100))
|
||||||
value-percent)
|
value-percent)
|
||||||
value-percent-str (str value-percent "%")
|
value-percent-str (str value-percent "%")
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
(ns app.main.ui.workspace.header
|
(ns app.main.ui.workspace.header
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.math :as mth]
|
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
[app.main.data.events :as ev]
|
[app.main.data.events :as ev]
|
||||||
[app.main.data.messages :as dm]
|
[app.main.data.messages :as dm]
|
||||||
|
@ -18,6 +17,7 @@
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.dropdown :refer [dropdown]]
|
[app.main.ui.components.dropdown :refer [dropdown]]
|
||||||
|
[app.main.ui.formats :as fmt]
|
||||||
[app.main.ui.hooks.resize :as r]
|
[app.main.ui.hooks.resize :as r]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.main.ui.workspace.presence :refer [active-sessions]]
|
[app.main.ui.workspace.presence :refer [active-sessions]]
|
||||||
|
@ -71,7 +71,7 @@
|
||||||
:as props}]
|
:as props}]
|
||||||
(let [show-dropdown? (mf/use-state false)]
|
(let [show-dropdown? (mf/use-state false)]
|
||||||
[:div.zoom-widget {:on-click #(reset! show-dropdown? true)}
|
[: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]
|
[:span.icon i/arrow-down]
|
||||||
[:& dropdown {:show @show-dropdown?
|
[:& dropdown {:show @show-dropdown?
|
||||||
:on-close #(reset! show-dropdown? false)}
|
:on-close #(reset! show-dropdown? false)}
|
||||||
|
@ -82,7 +82,7 @@
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(on-decrease))} "-"]
|
(on-decrease))} "-"]
|
||||||
[:p.zoom-size {} (str (mth/round (* 100 zoom)) "%")]
|
[:p.zoom-size {} (fmt/format-percent zoom {:precision 0})]
|
||||||
[:button {:on-click (fn [event]
|
[:button {:on-click (fn [event]
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
(ns app.main.ui.workspace.left-toolbar
|
(ns app.main.ui.workspace.left-toolbar
|
||||||
(:require
|
(:require
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.math :as mth]
|
|
||||||
[app.common.media :as cm]
|
[app.common.media :as cm]
|
||||||
[app.main.data.events :as ev]
|
[app.main.data.events :as ev]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
|
@ -40,8 +39,8 @@
|
||||||
;; We don't want to add a ref because that redraws the component
|
;; We don't want to add a ref because that redraws the component
|
||||||
;; for everychange. Better direct access on the callback.
|
;; for everychange. Better direct access on the callback.
|
||||||
(let [vbox (deref refs/vbox)
|
(let [vbox (deref refs/vbox)
|
||||||
x (mth/round (+ (:x vbox) (/ (:width vbox) 2)))
|
x (+ (:x vbox) (/ (:width vbox) 2))
|
||||||
y (mth/round (+ (:y vbox) (/ (:height vbox) 2)))
|
y (+ (:y vbox) (/ (:height vbox) 2))
|
||||||
params {:file-id (:id file)
|
params {:file-id (:id file)
|
||||||
:blobs (seq blobs)
|
:blobs (seq blobs)
|
||||||
:position (gpt/point x y)}]
|
:position (gpt/point x y)}]
|
||||||
|
|
|
@ -49,12 +49,12 @@
|
||||||
[:div.input-wrapper
|
[:div.input-wrapper
|
||||||
[:span
|
[:span
|
||||||
[:p.nudge-subtitle (tr "modals.small-nudge")]
|
[:p.nudge-subtitle (tr "modals.small-nudge")]
|
||||||
[:> numeric-input {:min 1
|
[:> numeric-input {:min 0.01
|
||||||
:value (:small nudge)
|
:value (:small nudge)
|
||||||
:on-change update-small}]]]
|
:on-change update-small}]]]
|
||||||
[:div.input-wrapper
|
[:div.input-wrapper
|
||||||
[:span
|
[:span
|
||||||
[:p.nudge-subtitle (tr "modals.big-nudge")]
|
[:p.nudge-subtitle (tr "modals.big-nudge")]
|
||||||
[:> numeric-input {:min 1
|
[:> numeric-input {:min 0.01
|
||||||
:value (:big nudge)
|
:value (:big nudge)
|
||||||
:on-change update-big}]]]]]]))
|
:on-change update-big}]]]]]]))
|
||||||
|
|
|
@ -89,6 +89,7 @@
|
||||||
:style {:cursor (cond
|
:style {:cursor (cond
|
||||||
(= edit-mode :draw) cur/pen-node
|
(= edit-mode :draw) cur/pen-node
|
||||||
(= edit-mode :move) cur/pointer-node)
|
(= edit-mode :move) cur/pointer-node)
|
||||||
|
:stroke-width 0
|
||||||
:fill "none"}}]]))
|
:fill "none"}}]]))
|
||||||
|
|
||||||
(mf/defc path-handler [{:keys [index prefix point handler zoom selected? hover? edit-mode snap-angle?]}]
|
(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-enter on-enter
|
||||||
:on-mouse-leave on-leave
|
:on-mouse-leave on-leave
|
||||||
:style {:cursor (when (= edit-mode :move) cur/pointer-move)
|
:style {:cursor (when (= edit-mode :move) cur/pointer-move)
|
||||||
:fill "none"}}]])))
|
:fill "none"
|
||||||
|
:stroke-width 0}}]])))
|
||||||
|
|
||||||
(mf/defc path-preview [{:keys [zoom command from]}]
|
(mf/defc path-preview [{:keys [zoom command from]}]
|
||||||
[:g.preview {:style {:pointer-events "none"}}
|
[:g.preview {:style {:pointer-events "none"}}
|
||||||
|
|
|
@ -209,7 +209,7 @@
|
||||||
;; and updates the selrect accordingly
|
;; and updates the selrect accordingly
|
||||||
[:*
|
[:*
|
||||||
[:g.text-shape {:ref on-change-node
|
[:g.text-shape {:ref on-change-node
|
||||||
:opacity (when show-svg-text? 0)
|
:opacity (when show-svg-text? 0.2)
|
||||||
:pointer-events "none"}
|
:pointer-events "none"}
|
||||||
|
|
||||||
;; The `:key` prop here is mandatory because the
|
;; The `:key` prop here is mandatory because the
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
(ns app.main.ui.workspace.sidebar.options.menus.frame-grid
|
(ns app.main.ui.workspace.sidebar.options.menus.frame-grid
|
||||||
(:require
|
(:require
|
||||||
[app.common.math :as mth]
|
|
||||||
[app.main.data.workspace.grid :as dw]
|
[app.main.data.workspace.grid :as dw]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
|
@ -71,8 +70,7 @@
|
||||||
(let [{:keys [margin gutter item-length]} (:params grid)
|
(let [{:keys [margin gutter item-length]} (:params grid)
|
||||||
frame-length (if (= :column (:type grid)) frame-width frame-height)
|
frame-length (if (= :column (:type grid)) frame-width frame-height)
|
||||||
item-length (if (nil? size)
|
item-length (if (nil? size)
|
||||||
(-> (gg/calculate-default-item-length frame-length margin gutter)
|
(gg/calculate-default-item-length frame-length margin gutter)
|
||||||
(mth/precision 2))
|
|
||||||
item-length)]
|
item-length)]
|
||||||
(-> grid
|
(-> grid
|
||||||
(update :params assoc :size size :item-length item-length)
|
(update :params assoc :size size :item-length item-length)
|
||||||
|
@ -140,7 +138,7 @@
|
||||||
|
|
||||||
(if (= type :square)
|
(if (= type :square)
|
||||||
[:div.input-element.pixels {:title (tr "workspace.options.size")}
|
[:div.input-element.pixels {:title (tr "workspace.options.size")}
|
||||||
[:> numeric-input {:min 1
|
[:> numeric-input {:min 0.01
|
||||||
:value (or (:size params) "")
|
:value (or (:size params) "")
|
||||||
:no-validate true
|
:no-validate true
|
||||||
:on-change (handle-change :params :size)}]]
|
:on-change (handle-change :params :size)}]]
|
||||||
|
@ -162,7 +160,7 @@
|
||||||
(when (= :square type)
|
(when (= :square type)
|
||||||
[:& input-row {:label (tr "workspace.options.grid.params.size")
|
[:& input-row {:label (tr "workspace.options.grid.params.size")
|
||||||
:class "pixels"
|
:class "pixels"
|
||||||
:min 1
|
:min 0.01
|
||||||
:value (:size params)
|
:value (:size params)
|
||||||
:on-change (handle-change :params :size)}])
|
:on-change (handle-change :params :size)}])
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
(ns app.main.ui.workspace.sidebar.options.menus.layer
|
(ns app.main.ui.workspace.sidebar.options.menus.layer
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.math :as mth]
|
|
||||||
[app.main.data.workspace.changes :as dch]
|
[app.main.data.workspace.changes :as dch]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.numeric-input :refer [numeric-input]]
|
[app.main.ui.components.numeric-input :refer [numeric-input]]
|
||||||
|
@ -23,8 +22,7 @@
|
||||||
""
|
""
|
||||||
(str (-> opacity
|
(str (-> opacity
|
||||||
(d/coalesce 1)
|
(d/coalesce 1)
|
||||||
(* 100)
|
(* 100)))))
|
||||||
(mth/round)))))
|
|
||||||
|
|
||||||
(defn select-all [event]
|
(defn select-all [event]
|
||||||
(dom/select-text! (dom/get-target event)))
|
(dom/select-text! (dom/get-target event)))
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.math :as math]
|
|
||||||
[app.common.spec.radius :as ctr]
|
[app.common.spec.radius :as ctr]
|
||||||
[app.main.data.workspace :as udw]
|
[app.main.data.workspace :as udw]
|
||||||
[app.main.data.workspace.changes :as dch]
|
[app.main.data.workspace.changes :as dch]
|
||||||
|
@ -46,9 +45,7 @@
|
||||||
(let [value (attr values)]
|
(let [value (attr values)]
|
||||||
(if (= value :multiple)
|
(if (= value :multiple)
|
||||||
""
|
""
|
||||||
(str (-> value
|
(str (-> value (d/coalesce 0))))))
|
||||||
(d/coalesce 0)
|
|
||||||
(math/precision 2))))))
|
|
||||||
|
|
||||||
(declare +size-presets+)
|
(declare +size-presets+)
|
||||||
|
|
||||||
|
@ -239,7 +236,7 @@
|
||||||
[:div.row-flex
|
[:div.row-flex
|
||||||
[:span.element-set-subtitle (tr "workspace.options.size")]
|
[:span.element-set-subtitle (tr "workspace.options.size")]
|
||||||
[:div.input-element.width {:title (tr "workspace.options.width")}
|
[:div.input-element.width {:title (tr "workspace.options.width")}
|
||||||
[:> numeric-input {:min 1
|
[:> numeric-input {:min 0.01
|
||||||
:no-validate true
|
:no-validate true
|
||||||
:placeholder "--"
|
:placeholder "--"
|
||||||
:on-click select-all
|
:on-click select-all
|
||||||
|
@ -247,7 +244,7 @@
|
||||||
:value (attr->string :width values)}]]
|
:value (attr->string :width values)}]]
|
||||||
|
|
||||||
[:div.input-element.height {:title (tr "workspace.options.height")}
|
[:div.input-element.height {:title (tr "workspace.options.height")}
|
||||||
[:> numeric-input {:min 1
|
[:> numeric-input {:min 0.01
|
||||||
:no-validate true
|
:no-validate true
|
||||||
:placeholder "--"
|
:placeholder "--"
|
||||||
:on-click select-all
|
:on-click select-all
|
||||||
|
@ -271,15 +268,13 @@
|
||||||
:placeholder "--"
|
:placeholder "--"
|
||||||
:on-click select-all
|
:on-click select-all
|
||||||
:on-change on-pos-x-change
|
:on-change on-pos-x-change
|
||||||
:value (attr->string :x values)
|
:value (attr->string :x values)}]]
|
||||||
:precision 2}]]
|
|
||||||
[:div.input-element.Yaxis {:title (tr "workspace.options.y")}
|
[:div.input-element.Yaxis {:title (tr "workspace.options.y")}
|
||||||
[:> numeric-input {:no-validate true
|
[:> numeric-input {:no-validate true
|
||||||
:placeholder "--"
|
:placeholder "--"
|
||||||
:on-click select-all
|
:on-click select-all
|
||||||
:on-change on-pos-y-change
|
:on-change on-pos-y-change
|
||||||
:value (attr->string :y values)
|
:value (attr->string :y values)}]]])
|
||||||
:precision 2}]]])
|
|
||||||
|
|
||||||
;; ROTATION
|
;; ROTATION
|
||||||
(when (options :rotation)
|
(when (options :rotation)
|
||||||
|
|
|
@ -386,7 +386,6 @@
|
||||||
{:min -200
|
{:min -200
|
||||||
:max 200
|
:max 200
|
||||||
:step 0.1
|
:step 0.1
|
||||||
:precision 2
|
|
||||||
:value (attr->string line-height)
|
:value (attr->string line-height)
|
||||||
:placeholder (tr "settings.multiple")
|
:placeholder (tr "settings.multiple")
|
||||||
:on-change #(handle-change % :line-height)
|
:on-change #(handle-change % :line-height)
|
||||||
|
@ -400,7 +399,6 @@
|
||||||
{:min -200
|
{:min -200
|
||||||
:max 200
|
:max 200
|
||||||
:step 0.1
|
:step 0.1
|
||||||
:precision 2
|
|
||||||
:value (attr->string letter-spacing)
|
:value (attr->string letter-spacing)
|
||||||
:placeholder (tr "settings.multiple")
|
:placeholder (tr "settings.multiple")
|
||||||
:on-change #(handle-change % :letter-spacing)
|
:on-change #(handle-change % :letter-spacing)
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
(ns app.main.ui.workspace.sidebar.options.rows.color-row
|
(ns app.main.ui.workspace.sidebar.options.rows.color-row
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.math :as math]
|
|
||||||
[app.common.pages :as cp]
|
[app.common.pages :as cp]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
|
@ -54,8 +53,7 @@
|
||||||
""
|
""
|
||||||
(str (-> opacity
|
(str (-> opacity
|
||||||
(d/coalesce 1)
|
(d/coalesce 1)
|
||||||
(* 100)
|
(* 100)))))
|
||||||
(math/round)))))
|
|
||||||
|
|
||||||
(defn remove-multiple [v]
|
(defn remove-multiple [v]
|
||||||
(if (= v :multiple) nil v))
|
(if (= v :multiple) nil v))
|
||||||
|
|
|
@ -97,7 +97,6 @@
|
||||||
[:> numeric-input
|
[:> numeric-input
|
||||||
{:min 0
|
{:min 0
|
||||||
:value (-> (:stroke-width stroke) width->string)
|
:value (-> (:stroke-width stroke) width->string)
|
||||||
:precision 2
|
|
||||||
:placeholder (tr "settings.multiple")
|
:placeholder (tr "settings.multiple")
|
||||||
:on-change (on-stroke-width-change index)
|
:on-change (on-stroke-width-change index)
|
||||||
:on-click select-all
|
:on-click select-all
|
||||||
|
|
|
@ -345,6 +345,7 @@
|
||||||
:zoom zoom
|
:zoom zoom
|
||||||
:transform transform
|
:transform transform
|
||||||
:selected selected
|
:selected selected
|
||||||
|
:selected-shapes selected-shapes
|
||||||
:page-id page-id}])
|
:page-id page-id}])
|
||||||
|
|
||||||
(when show-cursor-tooltip?
|
(when show-cursor-tooltip?
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
(ns app.main.ui.workspace.viewport.frame-grid
|
(ns app.main.ui.workspace.viewport.frame-grid
|
||||||
(:require
|
(:require
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.math :as mth]
|
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.util.geom.grid :as gg]
|
[app.util.geom.grid :as gg]
|
||||||
|
@ -58,10 +57,10 @@
|
||||||
[:g.grid
|
[:g.grid
|
||||||
(for [{:keys [x y width height] :as area} (gg/grid-areas frame grid)]
|
(for [{:keys [x y width height] :as area} (gg/grid-areas frame grid)]
|
||||||
[:rect {:key (str key "-" x "-" y)
|
[:rect {:key (str key "-" x "-" y)
|
||||||
:x (mth/round x)
|
:x x
|
||||||
:y (mth/round y)
|
:y y
|
||||||
:width (- (mth/round (+ x width)) (mth/round x))
|
:width (- (+ x width) x)
|
||||||
:height (- (mth/round (+ y height)) (mth/round y))
|
:height (- (+ y height) y)
|
||||||
:style style}])]))
|
:style style}])]))
|
||||||
|
|
||||||
(mf/defc grid-display-frame
|
(mf/defc grid-display-frame
|
||||||
|
|
|
@ -281,9 +281,7 @@
|
||||||
(fn [point]
|
(fn [point]
|
||||||
(let [point (gpt/transform point transform-inverse)
|
(let [point (gpt/transform point transform-inverse)
|
||||||
start-x (/ (- (:x point) x) width)
|
start-x (/ (- (:x point) x) width)
|
||||||
start-y (/ (- (:y point) y) height)
|
start-y (/ (- (:y point) y) height)]
|
||||||
start-x (mth/precision start-x 2)
|
|
||||||
start-y (mth/precision start-y 2)]
|
|
||||||
(change! {:start-x start-x :start-y start-y}))))
|
(change! {:start-x start-x :start-y start-y}))))
|
||||||
|
|
||||||
on-change-finish
|
on-change-finish
|
||||||
|
@ -292,9 +290,7 @@
|
||||||
(fn [point]
|
(fn [point]
|
||||||
(let [point (gpt/transform point transform-inverse)
|
(let [point (gpt/transform point transform-inverse)
|
||||||
end-x (/ (- (:x point) x) width)
|
end-x (/ (- (:x point) x) width)
|
||||||
end-y (/ (- (:y point) y) height)
|
end-y (/ (- (:y point) y) height)]
|
||||||
end-x (mth/precision end-x 2)
|
|
||||||
end-y (mth/precision end-y 2)]
|
|
||||||
(change! {:end-x end-x :end-y end-y}))))
|
(change! {:end-x end-x :end-y end-y}))))
|
||||||
|
|
||||||
on-change-width
|
on-change-width
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
[app.common.colors :as colors]
|
[app.common.colors :as colors]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.math :as mth]
|
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
|
@ -102,7 +101,6 @@
|
||||||
(+ start-pos delta))
|
(+ start-pos delta))
|
||||||
|
|
||||||
;; TODO: Change when pixel-grid flag exists
|
;; TODO: Change when pixel-grid flag exists
|
||||||
new-position (mth/round new-position)
|
|
||||||
new-frame-id (:id (get-hover-frame))]
|
new-frame-id (:id (get-hover-frame))]
|
||||||
(swap! state assoc
|
(swap! state assoc
|
||||||
:new-position new-position
|
:new-position new-position
|
||||||
|
@ -366,7 +364,7 @@
|
||||||
:style {:font-size (/ rules/font-size zoom)
|
:style {:font-size (/ rules/font-size zoom)
|
||||||
:font-family rules/font-family
|
:font-family rules/font-family
|
||||||
:fill colors/black}}
|
:fill colors/black}}
|
||||||
(str (mth/round pos))]]))])))
|
(str pos)]]))])))
|
||||||
|
|
||||||
(mf/defc new-guide-area
|
(mf/defc new-guide-area
|
||||||
[{:keys [vbox zoom axis get-hover-frame disabled-guides?]}]
|
[{:keys [vbox zoom axis get-hover-frame disabled-guides?]}]
|
||||||
|
|
|
@ -146,12 +146,12 @@
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(connect-to-point orig-shape
|
(connect-to-point orig-shape
|
||||||
{:x (+ (:x2 (:selrect orig-shape)) 100)
|
{:x (+ (:x2 (:selrect orig-shape)) (/ 100 zoom))
|
||||||
:y (+ (- (:y1 (:selrect orig-shape)) 50)
|
:y (+ (- (:y1 (:selrect orig-shape)) (/ 50 zoom))
|
||||||
(/ (* level 32) zoom))}))
|
(/ (* level 32) zoom))}))
|
||||||
|
|
||||||
orig-dx (if (= orig-pos :right) 100 -100)
|
orig-dx (/ (if (= orig-pos :right) 100 -100) zoom)
|
||||||
dest-dx (if (= dest-pos :right) 100 -100)
|
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]
|
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)
|
pdata (str/join " " path)
|
||||||
|
@ -182,7 +182,8 @@
|
||||||
:d pdata}]
|
:d pdata}]
|
||||||
|
|
||||||
(when dest-shape
|
(when dest-shape
|
||||||
[:& outline {:shape dest-shape
|
[:& outline {:zoom zoom
|
||||||
|
:shape dest-shape
|
||||||
:color "var(--color-primary)"}])
|
:color "var(--color-primary)"}])
|
||||||
|
|
||||||
[:& interaction-marker {:index index
|
[:& interaction-marker {:index index
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.math :as mth]
|
[app.common.math :as mth]
|
||||||
|
[app.main.ui.formats :as fmt]
|
||||||
[app.main.ui.hooks :as hooks]
|
[app.main.ui.hooks :as hooks]
|
||||||
[app.util.object :as obj]
|
[app.util.object :as obj]
|
||||||
[rumext.alpha :as mf]))
|
[rumext.alpha :as mf]))
|
||||||
|
@ -131,9 +132,9 @@
|
||||||
|
|
||||||
|
|
||||||
(let [{:keys [start end]} (get-rule-params vbox axis)
|
(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)
|
minv (* (mth/ceil (/ minv step)) step)
|
||||||
maxv (min (mth/round end) 100000)
|
maxv (min end 100000)
|
||||||
maxv (* (mth/floor (/ maxv step)) step)]
|
maxv (* (mth/floor (/ maxv step)) step)]
|
||||||
|
|
||||||
(for [step-val (range minv (inc maxv) step)]
|
(for [step-val (range minv (inc maxv) step)]
|
||||||
|
@ -149,7 +150,7 @@
|
||||||
:style {:font-size (/ font-size zoom)
|
:style {:font-size (/ font-size zoom)
|
||||||
:font-family font-family
|
:font-family font-family
|
||||||
:fill colors/gray-30}}
|
:fill colors/gray-30}}
|
||||||
(str (mth/round step-val))]
|
(fmt/format-number step-val)]
|
||||||
|
|
||||||
[:line {:key (str "line-" (d/name axis) "-" step-val)
|
[:line {:key (str "line-" (d/name axis) "-" step-val)
|
||||||
:x1 line-x1
|
:x1 line-x1
|
||||||
|
@ -184,7 +185,7 @@
|
||||||
:style {:font-size (/ font-size zoom)
|
:style {:font-size (/ font-size zoom)
|
||||||
:font-family font-family
|
:font-family font-family
|
||||||
:fill selection-area-color}}
|
:fill selection-area-color}}
|
||||||
(str (mth/round (:x1 selection-rect)))]
|
(fmt/format-number (:x1 selection-rect))]
|
||||||
|
|
||||||
[:rect {:x (:x2 selection-rect)
|
[:rect {:x (:x2 selection-rect)
|
||||||
:y (:y vbox)
|
:y (:y vbox)
|
||||||
|
@ -200,7 +201,7 @@
|
||||||
:style {:font-size (/ font-size zoom)
|
:style {:font-size (/ font-size zoom)
|
||||||
:font-family font-family
|
:font-family font-family
|
||||||
:fill selection-area-color}}
|
: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))
|
(let [center-x (+ (:x vbox) (/ rule-area-half-size zoom))
|
||||||
center-y (- (+ (:y selection-rect) (/ (:height selection-rect) 2)) (/ 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)
|
:style {:font-size (/ font-size zoom)
|
||||||
:font-family font-family
|
:font-family font-family
|
||||||
:fill selection-area-color}}
|
:fill selection-area-color}}
|
||||||
(str (mth/round (:y2 selection-rect)))]
|
(fmt/format-number (:y2 selection-rect))]
|
||||||
|
|
||||||
[:text {:x (+ center-x (/ (:height selection-rect) 2) )
|
[:text {:x (+ center-x (/ (:height selection-rect) 2) )
|
||||||
:y center-y
|
:y center-y
|
||||||
|
@ -243,7 +244,7 @@
|
||||||
:style {:font-size (/ font-size zoom)
|
:style {:font-size (/ font-size zoom)
|
||||||
:font-family font-family
|
:font-family font-family
|
||||||
:fill selection-area-color}}
|
:fill selection-area-color}}
|
||||||
(str (mth/round (:y1 selection-rect)))]])])
|
(fmt/format-number (:y1 selection-rect))]])])
|
||||||
|
|
||||||
(mf/defc rules
|
(mf/defc rules
|
||||||
{::mf/wrap-props false
|
{::mf/wrap-props false
|
||||||
|
|
|
@ -131,7 +131,7 @@
|
||||||
(let [viewport (mf/ref-val viewport-ref)
|
(let [viewport (mf/ref-val viewport-ref)
|
||||||
start-pt (mf/ref-val start-ref)
|
start-pt (mf/ref-val start-ref)
|
||||||
current-pt (dom/get-client-position event)
|
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)
|
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)
|
x-delta (/ (* (mf/ref-val width-factor-ref) (- (:x current-pt) (:x start-pt))) zoom)
|
||||||
new-v-scrollbar-y (-> current-pt-viewport
|
new-v-scrollbar-y (-> current-pt-viewport
|
||||||
|
@ -156,8 +156,9 @@
|
||||||
(fn [event axis]
|
(fn [event axis]
|
||||||
(let [viewport (mf/ref-val viewport-ref)
|
(let [viewport (mf/ref-val viewport-ref)
|
||||||
start-pt (dom/get-client-position event)
|
start-pt (dom/get-client-position event)
|
||||||
new-v-scrollbar-y (-> (utils/translate-point-to-viewport-raw viewport zoom start-pt) :y)
|
viewport-point (utils/translate-point-to-viewport viewport zoom start-pt)
|
||||||
new-h-scrollbar-x (-> (utils/translate-point-to-viewport-raw viewport zoom start-pt) :x)
|
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)
|
v-scrollbar-y-padding (- v-scrollbar-y new-v-scrollbar-y)
|
||||||
h-scrollbar-x-padding (- h-scrollbar-x new-h-scrollbar-x)
|
h-scrollbar-x-padding (- h-scrollbar-x new-h-scrollbar-x)
|
||||||
vbox-rect {:x vbox-x
|
vbox-rect {:x vbox-x
|
||||||
|
@ -206,7 +207,7 @@
|
||||||
:x v-scrollbar-x
|
:x v-scrollbar-x
|
||||||
:y v-scrollbar-y
|
:y v-scrollbar-y
|
||||||
:style {:stroke "white"
|
:style {:stroke "white"
|
||||||
:stroke-width 0.15}}]])
|
:stroke-width (/ 0.15 zoom)}}]])
|
||||||
(when show-h-scroll?
|
(when show-h-scroll?
|
||||||
[:g.h-scroll
|
[:g.h-scroll
|
||||||
[:rect {:on-mouse-move #(on-mouse-move % :x)
|
[:rect {:on-mouse-move #(on-mouse-move % :x)
|
||||||
|
@ -220,4 +221,4 @@
|
||||||
:x h-scrollbar-x
|
:x h-scrollbar-x
|
||||||
:y h-scrollbar-y
|
:y h-scrollbar-y
|
||||||
:style {:stroke "white"
|
:style {:stroke "white"
|
||||||
:stroke-width 0.15}}]])]))
|
:stroke-width (/ 0.15 zoom)}}]])]))
|
||||||
|
|
|
@ -67,38 +67,18 @@
|
||||||
:position :top-left
|
:position :top-left
|
||||||
:props {:cx x :cy y}}
|
:props {:cx x :cy y}}
|
||||||
|
|
||||||
(when show-resize-point?
|
|
||||||
{:type :resize-point
|
|
||||||
:position :top-left
|
|
||||||
:props {:cx x :cy y :align align}})
|
|
||||||
|
|
||||||
{:type :rotation
|
{:type :rotation
|
||||||
:position :top-right
|
:position :top-right
|
||||||
:props {:cx (+ x width) :cy y}}
|
: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
|
{:type :rotation
|
||||||
:position :bottom-right
|
:position :bottom-right
|
||||||
:props {:cx (+ x width) :cy (+ y height)}}
|
: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
|
{:type :rotation
|
||||||
:position :bottom-left
|
:position :bottom-left
|
||||||
:props {:cx x :cy (+ y height)}}
|
: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?
|
(when min-side-top?
|
||||||
{:type :resize-side
|
{:type :resize-side
|
||||||
:position :top
|
:position :top
|
||||||
|
@ -117,7 +97,30 @@
|
||||||
(when min-side-side?
|
(when min-side-side?
|
||||||
{:type :resize-side
|
{:type :resize-side
|
||||||
:position :left
|
: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?)))))
|
(filterv (comp not nil?)))))
|
||||||
|
|
||||||
|
@ -136,6 +139,8 @@
|
||||||
:width size
|
:width size
|
||||||
:height size
|
:height size
|
||||||
:fill (if (debug? :rotation-handler) "blue" "none")
|
:fill (if (debug? :rotation-handler) "blue" "none")
|
||||||
|
:stroke (if (debug? :rotation-handler) "blue" "none")
|
||||||
|
:stroke-width 0
|
||||||
:transform transform
|
:transform transform
|
||||||
:on-mouse-down on-rotate}]))
|
:on-mouse-down on-rotate}]))
|
||||||
|
|
||||||
|
@ -168,6 +173,8 @@
|
||||||
:height resize-point-circle-radius
|
:height resize-point-circle-radius
|
||||||
:transform (when rotation (str/fmt "rotate(%s, %s, %s)" rotation cx' cy'))
|
:transform (when rotation (str/fmt "rotate(%s, %s, %s)" rotation cx' cy'))
|
||||||
:style {:fill (if (debug? :resize-handler) "red" "none")
|
:style {:fill (if (debug? :resize-handler) "red" "none")
|
||||||
|
:stroke (if (debug? :resize-handler) "red" "none")
|
||||||
|
:stroke-width 0
|
||||||
:cursor cursor}
|
:cursor cursor}
|
||||||
:on-mouse-down #(on-resize {:x cx' :y cy'} %)}])
|
:on-mouse-down #(on-resize {:x cx' :y cy'} %)}])
|
||||||
|
|
||||||
|
@ -176,7 +183,10 @@
|
||||||
:cx cx'
|
:cx cx'
|
||||||
:cy cy'
|
:cy cy'
|
||||||
:style {:fill (if (debug? :resize-handler) "red" "none")
|
: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
|
(mf/defc resize-side-handler
|
||||||
"The side handler is always rendered horizontally and then rotated"
|
"The side handler is always rendered horizontally and then rotated"
|
||||||
|
@ -202,6 +212,8 @@
|
||||||
(gmt/rotate-matrix angle (gpt/point x y)))
|
(gmt/rotate-matrix angle (gpt/point x y)))
|
||||||
:on-mouse-down #(on-resize res-point %)
|
:on-mouse-down #(on-resize res-point %)
|
||||||
:style {:fill (if (debug? :resize-handler) "yellow" "none")
|
:style {:fill (if (debug? :resize-handler) "yellow" "none")
|
||||||
|
:stroke (if (debug? :resize-handler) "yellow" "none")
|
||||||
|
:stroke-width 0
|
||||||
:cursor (if (#{:left :right} position)
|
:cursor (if (#{:left :right} position)
|
||||||
(cur/resize-ew rotation)
|
(cur/resize-ew rotation)
|
||||||
(cur/resize-ns rotation)) }}]))
|
(cur/resize-ns rotation)) }}]))
|
||||||
|
@ -292,7 +304,7 @@
|
||||||
:pointer-events "visible"
|
:pointer-events "visible"
|
||||||
:style {:stroke color
|
:style {:stroke color
|
||||||
:stroke-width (/ 0.5 zoom)
|
:stroke-width (/ 0.5 zoom)
|
||||||
:stroke-opacity "1"
|
:stroke-opacity 1
|
||||||
:fill "none"}}]]))
|
:fill "none"}}]]))
|
||||||
|
|
||||||
(mf/defc multiple-handlers
|
(mf/defc multiple-handlers
|
||||||
|
@ -344,7 +356,7 @@
|
||||||
(mf/defc single-handlers
|
(mf/defc single-handlers
|
||||||
[{:keys [shape zoom color disable-handlers] :as props}]
|
[{:keys [shape zoom color disable-handlers] :as props}]
|
||||||
(let [shape-id (:id shape)
|
(let [shape-id (:id shape)
|
||||||
shape (geom/transform-shape shape {:round-coords? false})
|
shape (geom/transform-shape shape)
|
||||||
|
|
||||||
on-resize
|
on-resize
|
||||||
(fn [current-position _initial-position event]
|
(fn [current-position _initial-position event]
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
[app.common.math :as mth]
|
[app.common.math :as mth]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
|
[app.main.ui.formats :as fmt]
|
||||||
[app.main.worker :as uw]
|
[app.main.worker :as uw]
|
||||||
[beicon.core :as rx]
|
[beicon.core :as rx]
|
||||||
[clojure.set :as set]
|
[clojure.set :as set]
|
||||||
|
@ -54,7 +55,7 @@
|
||||||
(get sr2 (if (= :x coord) :x1 :y1)))
|
(get sr2 (if (= :x coord) :x1 :y1)))
|
||||||
|
|
||||||
distance (- to-c from-c)
|
distance (- to-c from-c)
|
||||||
distance-str (-> distance (mth/precision 0) str)
|
distance-str (str distance)
|
||||||
half-point (half-point coord sr1 sr2)
|
half-point (half-point coord sr1 sr2)
|
||||||
width (-> distance-str
|
width (-> distance-str
|
||||||
count
|
count
|
||||||
|
@ -81,7 +82,7 @@
|
||||||
:font-size (/ pill-text-font-size zoom)
|
:font-size (/ pill-text-font-size zoom)
|
||||||
:fill "var(--color-white)"
|
:fill "var(--color-white)"
|
||||||
:text-anchor "middle"}
|
:text-anchor "middle"}
|
||||||
(mth/precision distance 0)]])
|
(fmt/format-number distance)]])
|
||||||
|
|
||||||
(let [p1 [(+ from-c (/ segment-gap zoom)) (+ half-point (/ segment-gap-side zoom))]
|
(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))]
|
p2 [(+ from-c (/ segment-gap zoom)) (- half-point (/ segment-gap-side zoom))]
|
||||||
|
@ -110,7 +111,7 @@
|
||||||
sr2 (:selrect sh2)
|
sr2 (:selrect sh2)
|
||||||
c1 (if (= coord :x) :x1 :y1)
|
c1 (if (= coord :x) :x1 :y1)
|
||||||
c2 (if (= coord :x) :x2 :y2)
|
c2 (if (= coord :x) :x2 :y2)
|
||||||
dist (mth/precision (- (c1 sr2) (c2 sr1)) 0)]
|
dist (- (c1 sr2) (c2 sr1))]
|
||||||
[dist [sh1 sh2]]))
|
[dist [sh1 sh2]]))
|
||||||
|
|
||||||
(defn overlap? [coord sh1 sh2]
|
(defn overlap? [coord sh1 sh2]
|
||||||
|
@ -134,8 +135,7 @@
|
||||||
(-> (if (<= (coord sr) (coord selrect))
|
(-> (if (<= (coord sr) (coord selrect))
|
||||||
(gsh/distance-selrect sr selrect)
|
(gsh/distance-selrect sr selrect)
|
||||||
(gsh/distance-selrect selrect sr))
|
(gsh/distance-selrect selrect sr))
|
||||||
coord
|
coord)))
|
||||||
(mth/precision 0))))
|
|
||||||
|
|
||||||
get-shapes-match
|
get-shapes-match
|
||||||
(fn [pred? shapes]
|
(fn [pred? shapes]
|
||||||
|
@ -149,9 +149,9 @@
|
||||||
check-in-set
|
check-in-set
|
||||||
(fn [value number-set]
|
(fn [value number-set]
|
||||||
(->> 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
|
;; Gets the distance to the current selection
|
||||||
distances-xf (comp (map distance-to-selrect) (filter pos?))
|
distances-xf (comp (map distance-to-selrect) (filter pos?))
|
||||||
|
@ -195,6 +195,7 @@
|
||||||
(map #(vector selrect (:selrect %))))
|
(map #(vector selrect (:selrect %))))
|
||||||
|
|
||||||
segments-to-display (d/concat-set other-shapes-segments selection-segments)]
|
segments-to-display (d/concat-set other-shapes-segments selection-segments)]
|
||||||
|
|
||||||
segments-to-display))
|
segments-to-display))
|
||||||
|
|
||||||
(mf/defc shape-distance
|
(mf/defc shape-distance
|
||||||
|
@ -217,8 +218,9 @@
|
||||||
container-selrec (or (:selrect frame)
|
container-selrec (or (:selrect frame)
|
||||||
(gsh/rect->selrect @refs/vbox))
|
(gsh/rect->selrect @refs/vbox))
|
||||||
areas (gsh/selrect->areas container-selrec selrect)
|
areas (gsh/selrect->areas container-selrec selrect)
|
||||||
|
|
||||||
query-side (fn [side]
|
query-side (fn [side]
|
||||||
(let [rect (gsh/pad-selrec (areas side))]
|
(let [rect (get areas side)]
|
||||||
(if (and (> (:width rect) 0) (> (:height rect) 0))
|
(if (and (> (:width rect) 0) (> (:height rect) 0))
|
||||||
(->> (uw/ask! {:cmd :selection/query
|
(->> (uw/ask! {:cmd :selection/query
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
|
@ -264,15 +266,10 @@
|
||||||
(let [page-id (unchecked-get props "page-id")
|
(let [page-id (unchecked-get props "page-id")
|
||||||
zoom (unchecked-get props "zoom")
|
zoom (unchecked-get props "zoom")
|
||||||
selected (unchecked-get props "selected")
|
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-id (-> selected-shapes first :frame-id)
|
||||||
frame (mf/deref (refs/object-by-id frame-id))
|
frame (mf/deref (refs/object-by-id frame-id))
|
||||||
local (mf/deref refs/workspace-local)
|
selrect (gsh/selection-rect selected-shapes)]
|
||||||
|
|
||||||
update-shape (fn [shape] (-> shape
|
|
||||||
(update :modifiers merge (:modifiers local))
|
|
||||||
gsh/transform-shape))
|
|
||||||
selrect (->> selected-shapes (map update-shape) gsh/selection-rect)]
|
|
||||||
[:g.distance
|
[:g.distance
|
||||||
[:& shape-distance
|
[:& shape-distance
|
||||||
{:selrect selrect
|
{:selrect selrect
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.math :as mth]
|
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
[app.main.snap :as snap]
|
[app.main.snap :as snap]
|
||||||
|
@ -28,8 +27,6 @@
|
||||||
(mf/defc snap-point
|
(mf/defc snap-point
|
||||||
[{:keys [point zoom]}]
|
[{:keys [point zoom]}]
|
||||||
(let [{:keys [x y]} point
|
(let [{:keys [x y]} point
|
||||||
x (mth/round x)
|
|
||||||
y (mth/round y)
|
|
||||||
cross-width (/ 3 zoom)]
|
cross-width (/ 3 zoom)]
|
||||||
[:g
|
[:g
|
||||||
[:line {:x1 (- x cross-width)
|
[:line {:x1 (- x cross-width)
|
||||||
|
@ -45,15 +42,15 @@
|
||||||
|
|
||||||
(mf/defc snap-line
|
(mf/defc snap-line
|
||||||
[{:keys [snap point zoom]}]
|
[{:keys [snap point zoom]}]
|
||||||
[:line {:x1 (mth/round (:x snap))
|
[:line {:x1 (:x snap)
|
||||||
:y1 (mth/round (:y snap))
|
:y1 (:y snap)
|
||||||
:x2 (mth/round (:x point))
|
:x2 (:x point)
|
||||||
:y2 (mth/round (:y point))
|
:y2 (:y point)
|
||||||
:style {:stroke line-color :stroke-width (str (/ line-width zoom))}
|
:style {:stroke line-color :stroke-width (str (/ line-width zoom))}
|
||||||
:opacity line-opacity}])
|
:opacity line-opacity}])
|
||||||
|
|
||||||
(defn get-snap
|
(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)
|
(let [shape (if (> (count shapes) 1)
|
||||||
(->> shapes (map gsh/transform-shape) gsh/selection-rect (gsh/setup {:type :rect}))
|
(->> shapes (map gsh/transform-shape) gsh/selection-rect (gsh/setup {:type :rect}))
|
||||||
(->> shapes (first)))
|
(->> shapes (first)))
|
||||||
|
@ -69,7 +66,7 @@
|
||||||
(->> (sp/shape-snap-points shape)
|
(->> (sp/shape-snap-points shape)
|
||||||
(map #(vector frame-id %)))))
|
(map #(vector frame-id %)))))
|
||||||
(rx/flat-map (fn [[frame-id point]]
|
(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/map #(vector point % coord)))))
|
||||||
(rx/reduce conj []))))
|
(rx/reduce conj []))))
|
||||||
|
|
||||||
|
@ -119,12 +116,19 @@
|
||||||
(mf/use-effect
|
(mf/use-effect
|
||||||
(fn []
|
(fn []
|
||||||
(let [sub (->> subject
|
(let [sub (->> subject
|
||||||
(rx/switch-map #(rx/combine-latest (get-snap :x %)
|
(rx/switch-map
|
||||||
(get-snap :y %)))
|
(fn [props]
|
||||||
(rx/map (fn [result]
|
(->> (get-snap :y props)
|
||||||
(apply d/concat-vec (seq result))))
|
(rx/combine-latest (get-snap :x props)))))
|
||||||
(rx/subs #(let [rs (filter (fn [[_ snaps _]] (> (count snaps) 0)) %)]
|
|
||||||
(reset! state rs))))]
|
(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
|
;; On unmount callback
|
||||||
#(rx/dispose! sub))))
|
#(rx/dispose! sub))))
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
(ns app.main.ui.workspace.viewport.thumbnail-renderer
|
(ns app.main.ui.workspace.viewport.thumbnail-renderer
|
||||||
(:require
|
(:require
|
||||||
|
[app.common.math :as mth]
|
||||||
[app.main.data.workspace.persistence :as dwp]
|
[app.main.data.workspace.persistence :as dwp]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
|
@ -21,6 +22,10 @@
|
||||||
(let [thumbnail-img (mf/use-ref nil)
|
(let [thumbnail-img (mf/use-ref nil)
|
||||||
thumbnail-canvas (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
|
on-dom-rendered
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps (:id shape))
|
(mf/deps (:id shape))
|
||||||
|
@ -71,23 +76,23 @@
|
||||||
_ (.rect canvas-context 0 0 canvas-width canvas-height)
|
_ (.rect canvas-context 0 0 canvas-width canvas-height)
|
||||||
_ (set! (.-fillStyle canvas-context) background)
|
_ (set! (.-fillStyle canvas-context) background)
|
||||||
_ (.fill canvas-context)
|
_ (.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))))]
|
(on-thumbnail-data data))))]
|
||||||
|
|
||||||
[:div.frame-renderer {:ref on-dom-rendered
|
[:div.frame-renderer {:ref on-dom-rendered
|
||||||
:style {:display "none"}}
|
:style {:display "none"}}
|
||||||
[:img.thumbnail-img
|
[:img.thumbnail-img
|
||||||
{:ref thumbnail-img
|
{:ref thumbnail-img
|
||||||
:width (:width shape)
|
:width width
|
||||||
:height (:height shape)
|
:height height
|
||||||
:on-load on-image-load}]
|
:on-load on-image-load}]
|
||||||
|
|
||||||
[:canvas.thumbnail-canvas
|
[:canvas.thumbnail-canvas
|
||||||
{:ref thumbnail-canvas
|
{:ref thumbnail-canvas
|
||||||
:width (:width shape)
|
:width fixed-width
|
||||||
:height (:height shape)}]]))
|
:height fixed-height}]]))
|
||||||
|
|
||||||
(mf/defc frame-renderer
|
(mf/defc frame-renderer
|
||||||
"Component in charge of creating thumbnails and storing them"
|
"Component in charge of creating thumbnails and storing them"
|
||||||
|
|
|
@ -163,7 +163,7 @@
|
||||||
(:width vbox 0)
|
(:width vbox 0)
|
||||||
(:height 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)
|
(let [vbox (.. ^js viewport -viewBox -baseVal)
|
||||||
brect (dom/get-bounding-rect viewport)
|
brect (dom/get-bounding-rect viewport)
|
||||||
brect (gpt/point (d/parse-integer (:left brect))
|
brect (gpt/point (d/parse-integer (:left brect))
|
||||||
|
@ -174,10 +174,6 @@
|
||||||
(gpt/divide zoom)
|
(gpt/divide zoom)
|
||||||
(gpt/add box))))
|
(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]
|
(defn get-cursor [cursor]
|
||||||
(case cursor
|
(case cursor
|
||||||
:hand cur/hand
|
:hand cur/hand
|
||||||
|
|
|
@ -32,8 +32,8 @@
|
||||||
:pattern-units "userSpaceOnUse"}
|
:pattern-units "userSpaceOnUse"}
|
||||||
[:path {:d "M 1 0 L 0 0 0 1"
|
[:path {:d "M 1 0 L 0 0 0 1"
|
||||||
:style {:fill "none"
|
:style {:fill "none"
|
||||||
:stroke "var(--color-info)"
|
:stroke "var(--color-gray-20)"
|
||||||
:stroke-opacity "0.2"
|
:stroke-opacity "1"
|
||||||
:stroke-width (str (/ 1 zoom))}}]]]
|
:stroke-width (str (/ 1 zoom))}}]]]
|
||||||
[:rect {:x (:x vbox)
|
[:rect {:x (:x vbox)
|
||||||
:y (:y vbox)
|
:y (:y vbox)
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
(ns app.util.code-gen
|
(ns app.util.code-gen
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.math :as mth]
|
|
||||||
[app.common.text :as txt]
|
[app.common.text :as txt]
|
||||||
[app.util.color :as uc]
|
[app.util.color :as uc]
|
||||||
[cuerdas.core :as str]))
|
[cuerdas.core :as str]))
|
||||||
|
@ -109,7 +108,7 @@
|
||||||
(every? #(or (nil? %) (= % 0)) value)
|
(every? #(or (nil? %) (= % 0)) value)
|
||||||
(or (nil? value) (= value 0))))
|
(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]
|
format-property (fn [prop]
|
||||||
(let [css-prop (or (prop to-prop) (name prop))
|
(let [css-prop (or (prop to-prop) (name prop))
|
||||||
format-fn (or (prop format) default-format)
|
format-fn (or (prop format) default-format)
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.geom.shapes.path :as upg]
|
[app.common.geom.shapes.path :as upg]
|
||||||
[app.common.math :as mth]
|
|
||||||
[app.common.path.commands :as upc]
|
[app.common.path.commands :as upc]
|
||||||
[clojure.set :as set]))
|
[clojure.set :as set]))
|
||||||
|
|
||||||
|
@ -402,9 +401,7 @@
|
||||||
(rest segments))))))
|
(rest segments))))))
|
||||||
|
|
||||||
(defn calculate-merge-points [group-segments points]
|
(defn calculate-merge-points [group-segments points]
|
||||||
(let [index-merge-point (fn [group] (vector group (-> (gpt/center-points group)
|
(let [index-merge-point (fn [group] (vector group (gpt/center-points group)))
|
||||||
(update :x mth/round)
|
|
||||||
(update :y mth/round))))
|
|
||||||
index-group (fn [point] (vector point (d/seek #(contains? % point) group-segments)))
|
index-group (fn [point] (vector point (d/seek #(contains? % point) group-segments)))
|
||||||
|
|
||||||
group->merge-point (into {} (map index-merge-point) group-segments)
|
group->merge-point (into {} (map index-merge-point) group-segments)
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
"Performance profiling for react components."
|
"Performance profiling for react components."
|
||||||
(:require-macros [app.util.perf])
|
(:require-macros [app.util.perf])
|
||||||
(:require
|
(:require
|
||||||
[app.common.math :as math]
|
[app.common.math :as mth]
|
||||||
[rumext.alpha :as mf]
|
[rumext.alpha :as mf]
|
||||||
[goog.functions :as f]
|
[goog.functions :as f]
|
||||||
["react" :as react]
|
["react" :as react]
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
(ns debug
|
(ns debug
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.math :as mth]
|
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.transit :as t]
|
[app.common.transit :as t]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
|
@ -130,7 +129,7 @@
|
||||||
ts (/ 1000 (* (- cur @last)))
|
ts (/ 1000 (* (- cur @last)))
|
||||||
val (+ @avg (* (- ts @avg) 0.1))]
|
val (+ @avg (* (- ts @avg) 0.1))]
|
||||||
|
|
||||||
(obj/set! node "innerText" (mth/precision val 0))
|
(obj/set! node "innerText" val)
|
||||||
(vreset! last cur)
|
(vreset! last cur)
|
||||||
(vreset! avg val)
|
(vreset! avg val)
|
||||||
(do-thing)))))]
|
(do-thing)))))]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue