diff --git a/frontend/src/app/main.cljs b/frontend/src/app/main.cljs index 7ed4bd059e..868d4b9ea8 100644 --- a/frontend/src/app/main.cljs +++ b/frontend/src/app/main.cljs @@ -117,17 +117,17 @@ (st/emit! (initialize))) (defn ^:export reinit - [] - ;; NOTE: in cases of some strange behavior after hot-reload, - ;; uncomment this lines; they make a hard-rerender instead - ;; soft-rerender. - ;; - ;; (mf/unmount! app-root) - ;; (mf/unmount! modal-root) - ;; (set! app-root (mf/create-root (dom/get-element "app"))) - ;; (set! modal-root (mf/create-root (dom/get-element "modal"))) - (st/emit! (ev/initialize)) - (init-ui)) + ([] + (reinit false)) + ([hard?] + ;; The hard flag will force to unmount the whole UI and will redraw every component + (when hard? + (mf/unmount! app-root) + (mf/unmount! modal-root) + (set! app-root (mf/create-root (dom/get-element "app"))) + (set! modal-root (mf/create-root (dom/get-element "modal")))) + (st/emit! (ev/initialize)) + (init-ui))) (defn ^:dev/after-load after-load [] diff --git a/frontend/src/app/main/ui/workspace/shapes/bool.cljs b/frontend/src/app/main/ui/workspace/shapes/bool.cljs index 6a07eeed85..a3080b704e 100644 --- a/frontend/src/app/main/ui/workspace/shapes/bool.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/bool.cljs @@ -11,6 +11,7 @@ [app.main.ui.shapes.bool :as bool] [app.main.ui.shapes.shape :refer [shape-container]] [app.main.ui.workspace.shapes.common :refer [check-shape-props]] + [app.main.ui.workspace.shapes.debug :as wsd] [rumext.v2 :as mf])) (defn bool-wrapper-factory @@ -38,5 +39,7 @@ [:> shape-container {:shape shape} [:& bool-shape {:shape shape - :childs childs}]])))) + :childs childs}] + (when *assert* + [:& wsd/shape-debug {:shape shape}])])))) diff --git a/frontend/src/app/main/ui/workspace/shapes/common.cljs b/frontend/src/app/main/ui/workspace/shapes/common.cljs index c407b8db8f..4af042e877 100644 --- a/frontend/src/app/main/ui/workspace/shapes/common.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/common.cljs @@ -8,6 +8,7 @@ (:require [app.common.record :as cr] [app.main.ui.shapes.shape :refer [shape-container]] + [app.main.ui.workspace.shapes.debug :as wsd] [rumext.v2 :as mf])) (def ^:private excluded-attrs @@ -34,4 +35,6 @@ [props] (let [shape (unchecked-get props "shape")] [:> shape-container {:shape shape} - [:& component {:shape shape}]]))) + [:& component {:shape shape}] + (when *assert* + [:& wsd/shape-debug {:shape shape}])]))) diff --git a/frontend/src/app/main/ui/workspace/shapes/debug.cljs b/frontend/src/app/main/ui/workspace/shapes/debug.cljs new file mode 100644 index 0000000000..71cec7d268 --- /dev/null +++ b/frontend/src/app/main/ui/workspace/shapes/debug.cljs @@ -0,0 +1,99 @@ +;; 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) KALEIDOS INC + +(ns app.main.ui.workspace.shapes.debug + (:require + [app.common.data :as d] + [app.common.data.macros :as dm] + [app.common.files.helpers :as cfh] + [app.common.geom.shapes :as gsh] + [app.common.geom.shapes.text :as gst] + [app.common.math :as mth] + [app.main.refs :as refs] + [app.util.color :as uc] + [app.util.debug :as dbg] + [app.util.dom :as dom] + [cuerdas.core :as str] + [rumext.v2 :as mf])) + +(mf/defc debug-bounding-boxes + [{:keys [shape]}] + (let [points (->> (:points shape) + (map #(dm/fmt "%,%" (dm/get-prop % :x) (dm/get-prop % :y))) + (str/join " ")) + color (mf/use-memo #(uc/random-color)) + sr (:selrect shape)] + [:g.debug-bounding-boxes + [:rect {:transform (gsh/transform-str shape) + :x (:x sr) + :y (:y sr) + :width (:width sr) + :height (:height sr) + :fill color + :opacity 0.2}] + (for [p (:points shape)] + [:circle {:cx (dm/get-prop p :x) + :cy (dm/get-prop p :y) + :r 2 + :fill color}]) + [:polygon {:points points + :stroke-width 1 + :stroke color}]])) + +(mf/defc debug-text-bounds + {::mf/wrap-props false} + [props] + (let [shape (unchecked-get props "shape") + zoom (mf/deref refs/selected-zoom) + bounding-box (gst/shape->rect shape) + ctx (js* "document.createElement(\"canvas\").getContext(\"2d\")")] + [:g {:transform (gsh/transform-str shape)} + [:rect {:x (:x bounding-box) + :y (:y bounding-box) + :width (:width bounding-box) + :height (:height bounding-box) + :style {:fill "none" + :stroke "orange" + :stroke-width (/ 1 zoom)}}] + + (for [[index data] (d/enumerate (:position-data shape))] + (let [{:keys [x y width height]} data + res (dom/measure-text ctx (:font-size data) (:font-family data) (:text data))] + [:g {:key (dm/str index)} + ;; Text fragment bounding box + [:rect {:x x + :y (- y height) + :width width + :height height + :style {:fill "none" + :stroke "red" + :stroke-width (/ 1 zoom)}}] + + ;; Text baseline + [:line {:x1 (mth/round x) + :y1 (mth/round (- (:y data) (:height data))) + :x2 (mth/round (+ x width)) + :y2 (mth/round (- (:y data) (:height data))) + :style {:stroke "blue" + :stroke-width (/ 1 zoom)}}] + + [:line {:x1 (:x data) + :y1 (- (:y data) (:descent res)) + :x2 (+ (:x data) (:width data)) + :y2 (- (:y data) (:descent res)) + :style {:stroke "green" + :stroke-width (/ 2 zoom)}}]]))])) + +(mf/defc shape-debug + [{:keys [shape]}] + [:* + (when ^boolean (dbg/enabled? :bounding-boxes) + [:& debug-bounding-boxes]) + + (when (and ^boolean (cfh/text-shape? shape) + ^boolean (dbg/enabled? :text-outline) + ^boolean (seq (:position-data shape))) + [:& debug-text-bounds {:shape shape}])]) diff --git a/frontend/src/app/main/ui/workspace/shapes/frame.cljs b/frontend/src/app/main/ui/workspace/shapes/frame.cljs index 2dc7e32890..9ecddd1e20 100644 --- a/frontend/src/app/main/ui/workspace/shapes/frame.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/frame.cljs @@ -20,6 +20,7 @@ [app.main.ui.shapes.frame :as frame] [app.main.ui.shapes.shape :refer [shape-container]] [app.main.ui.workspace.shapes.common :refer [check-shape-props]] + [app.main.ui.workspace.shapes.debug :as wsd] [app.main.ui.workspace.shapes.frame.dynamic-modifiers :as fdm] [app.util.debug :as dbg] [app.util.dom :as dom] @@ -193,5 +194,8 @@ [:g.frame-content {:id (dm/str "frame-content-" frame-id) :ref container-ref} - [:& frame-shape {:shape shape :ref content-ref}]])]])))) + [:& frame-shape {:shape shape :ref content-ref}]])] + + (when *assert* + [:& wsd/shape-debug {:shape shape}])])))) diff --git a/frontend/src/app/main/ui/workspace/shapes/group.cljs b/frontend/src/app/main/ui/workspace/shapes/group.cljs index 5fbd2ad16b..d98d58a2f7 100644 --- a/frontend/src/app/main/ui/workspace/shapes/group.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/group.cljs @@ -11,6 +11,7 @@ [app.main.ui.shapes.group :as group] [app.main.ui.shapes.shape :refer [shape-container]] [app.main.ui.workspace.shapes.common :refer [check-shape-props]] + [app.main.ui.workspace.shapes.debug :as wsd] [rumext.v2 :as mf])) (defn group-wrapper-factory @@ -30,5 +31,7 @@ [:> shape-container {:shape shape} [:& group-shape {:shape shape - :childs childs}]])))) + :childs childs}] + (when *assert* + [:& wsd/shape-debug {:shape shape}])])))) diff --git a/frontend/src/app/main/ui/workspace/shapes/path.cljs b/frontend/src/app/main/ui/workspace/shapes/path.cljs index b20f65b1da..110238be4b 100644 --- a/frontend/src/app/main/ui/workspace/shapes/path.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/path.cljs @@ -11,6 +11,7 @@ [app.main.refs :as refs] [app.main.ui.shapes.path :as path] [app.main.ui.shapes.shape :refer [shape-container]] + [app.main.ui.workspace.shapes.debug :as wsd] [app.main.ui.workspace.shapes.path.common :as pc] [rumext.v2 :as mf])) @@ -38,4 +39,6 @@ [:> shape-container {:shape shape :pointer-events (when editing? "none")} - [:& path/path-shape {:shape shape}]])) + [:& path/path-shape {:shape shape}] + (when *assert* + [:& wsd/shape-debug {:shape shape}])])) diff --git a/frontend/src/app/main/ui/workspace/shapes/svg_raw.cljs b/frontend/src/app/main/ui/workspace/shapes/svg_raw.cljs index 774fa61faa..de1701e016 100644 --- a/frontend/src/app/main/ui/workspace/shapes/svg_raw.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/svg_raw.cljs @@ -10,6 +10,7 @@ [app.main.refs :as refs] [app.main.ui.shapes.shape :refer [shape-container]] [app.main.ui.shapes.svg-raw :as svg-raw] + [app.main.ui.workspace.shapes.debug :as wsd] [rumext.v2 :as mf])) (defn svg-raw-wrapper-factory @@ -26,7 +27,9 @@ (if (contains? csvg/svg-group-safe-tags svg-tag) [:> shape-container {:shape shape} [:& svg-raw-shape {:shape shape - :childs childs}]] + :childs childs}] + (when *assert* + [:& wsd/shape-debug {:shape shape}])] [:& svg-raw-shape {:shape shape :childs childs}]))))) diff --git a/frontend/src/app/main/ui/workspace/shapes/text.cljs b/frontend/src/app/main/ui/workspace/shapes/text.cljs index eb9b5e68a6..cdaeda400f 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text.cljs @@ -6,63 +6,14 @@ (ns app.main.ui.workspace.shapes.text (:require - [app.common.data :as d] [app.common.data.macros :as dm] - [app.common.geom.shapes :as gsh] - [app.common.geom.shapes.text :as gst] - [app.common.math :as mth] [app.main.data.workspace.texts :as dwt] [app.main.refs :as refs] [app.main.ui.shapes.shape :refer [shape-container]] [app.main.ui.shapes.text :as text] - [app.util.debug :as dbg] - [app.util.dom :as dom] + [app.main.ui.workspace.shapes.debug :as wsd] [rumext.v2 :as mf])) -(mf/defc debug-text-bounds - {::mf/wrap-props false} - [props] - (let [shape (unchecked-get props "shape") - zoom (mf/deref refs/selected-zoom) - bounding-box (gst/shape->rect shape) - ctx (js* "document.createElement(\"canvas\").getContext(\"2d\")")] - [:g {:transform (gsh/transform-str shape)} - [:rect {:x (:x bounding-box) - :y (:y bounding-box) - :width (:width bounding-box) - :height (:height bounding-box) - :style {:fill "none" - :stroke "orange" - :stroke-width (/ 1 zoom)}}] - - (for [[index data] (d/enumerate (:position-data shape))] - (let [{:keys [x y width height]} data - res (dom/measure-text ctx (:font-size data) (:font-family data) (:text data))] - [:g {:key (dm/str index)} - ;; Text fragment bounding box - [:rect {:x x - :y (- y height) - :width width - :height height - :style {:fill "none" - :stroke "red" - :stroke-width (/ 1 zoom)}}] - - ;; Text baseline - [:line {:x1 (mth/round x) - :y1 (mth/round (- (:y data) (:height data))) - :x2 (mth/round (+ x width)) - :y2 (mth/round (- (:y data) (:height data))) - :style {:stroke "blue" - :stroke-width (/ 1 zoom)}}] - - [:line {:x1 (:x data) - :y1 (- (:y data) (:descent res)) - :x2 (+ (:x data) (:width data)) - :y2 (- (:y data) (:descent res)) - :style {:stroke "green" - :stroke-width (/ 2 zoom)}}]]))])) - ;; --- Text Wrapper for workspace (mf/defc text-wrapper {::mf/wrap-props false} @@ -84,6 +35,5 @@ [:g.text-shape {:key (dm/str shape-id)} [:& text/text-shape {:shape shape}]] - (when (and ^boolean (dbg/enabled? :text-outline) - ^boolean (seq (:position-data shape))) - [:& debug-text-bounds {:shape shape}])])) + (when *assert* + [:& wsd/shape-debug {:shape shape}])])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/debug.cljs b/frontend/src/app/main/ui/workspace/sidebar/debug.cljs index 1168e8dc29..b49371e5ff 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/debug.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/debug.cljs @@ -24,7 +24,7 @@ (dom/prevent-default event) (dom/stop-propagation event) (dbg/toggle! option) - (js* "app.main.reinit()"))) + (js* "app.main.reinit(true)"))) handle-close (mf/use-fn diff --git a/frontend/src/app/util/color.cljs b/frontend/src/app/util/color.cljs index d7fc4a2bd3..79989b3894 100644 --- a/frontend/src/app/util/color.cljs +++ b/frontend/src/app/util/color.cljs @@ -12,6 +12,8 @@ (:require [app.common.colors :as cc] [app.common.data :as d] + [app.common.data.macros :as dm] + [app.common.math :as mth] [app.util.i18n :as i18n :refer [tr]] [cuerdas.core :as str])) @@ -82,3 +84,10 @@ (:name color) (:color color) (gradient-type->string (:type (:gradient color))))) + +(defn random-color + [] + (dm/fmt "rgb(%, %, %)" + (mth/floor (* (js/Math.random) 256)) + (mth/floor (* (js/Math.random) 256)) + (mth/floor (* (js/Math.random) 256))))