From 84007e6ad1b95254f72b031ad18def0879c2577c Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 22 Dec 2020 17:44:51 +0100 Subject: [PATCH 01/10] :sparkles: Allows rotation for shapes --- common/app/common/data.cljc | 4 +- common/app/common/geom/shapes.cljc | 5 +- common/app/common/geom/shapes/transforms.cljc | 29 +++++++---- frontend/src/app/main/data/workspace.cljs | 10 ++-- .../app/main/data/workspace/drawing/path.cljs | 49 ++++++++++++++----- .../app/main/data/workspace/transforms.cljs | 14 ++++++ frontend/src/app/main/ui/shapes/path.cljs | 6 +-- .../src/app/main/ui/workspace/selection.cljs | 27 +++++----- .../ui/workspace/shapes/bounding_box.cljs | 7 +-- .../app/main/ui/workspace/shapes/outline.cljs | 3 +- 10 files changed, 105 insertions(+), 49 deletions(-) diff --git a/common/app/common/data.cljc b/common/app/common/data.cljc index 99a643129d..972843b5d2 100644 --- a/common/app/common/data.cljc +++ b/common/app/common/data.cljc @@ -293,7 +293,9 @@ "Function that checks if a number is nil or nan. Will return 0 when not valid and the number otherwise." [v] - (if (or (not v) (mth/nan? v)) 0 v)) + (if (or (not v) + (not (mth/finite? v)) + (mth/nan? v)) 0 v)) (defmacro export diff --git a/common/app/common/geom/shapes.cljc b/common/app/common/geom/shapes.cljc index 22b5dd3283..50d9e07bbf 100644 --- a/common/app/common/geom/shapes.cljc +++ b/common/app/common/geom/shapes.cljc @@ -48,7 +48,7 @@ (us/assert #{:width :height} attr) (us/assert number? value) (let [{:keys [proportion proportion-lock]} shape - size (select-keys shape [:width :height]) + size (select-keys (:selrect shape) [:width :height]) new-size (if-not proportion-lock (assoc size attr value) (if (= attr :width) @@ -260,6 +260,7 @@ (d/export gco/center-shape) (d/export gco/center-selrect) (d/export gco/center-rect) +(d/export gco/center-points) (d/export gpr/rect->selrect) (d/export gpr/rect->points) (d/export gpr/points->selrect) @@ -268,7 +269,9 @@ (d/export gtr/transform-point-center) (d/export gtr/transform-rect) (d/export gtr/update-group-selrect) +(d/export gtr/transform-points) ;; PATHS (d/export gsp/content->points) (d/export gsp/content->selrect) +(d/export gsp/transform-content) diff --git a/common/app/common/geom/shapes/transforms.cljc b/common/app/common/geom/shapes/transforms.cljc index 0430f0ea2e..d126c8cddc 100644 --- a/common/app/common/geom/shapes/transforms.cljc +++ b/common/app/common/geom/shapes/transforms.cljc @@ -14,7 +14,13 @@ [app.common.geom.shapes.common :as gco] [app.common.geom.shapes.path :as gpa] [app.common.geom.shapes.rect :as gpr] - [app.common.math :as mth])) + [app.common.math :as mth] + [app.common.data :as d])) + +(defn- modif-rotation [shape] + (let [cur-rotation (d/check-num (:rotation shape)) + delta-angle (d/check-num (get-in shape [:modifiers :rotation]))] + (mod (+ cur-rotation delta-angle) 360))) (defn transform-matrix "Returns a transformation matrix without changing the shape properties. @@ -191,18 +197,23 @@ (defn apply-transform-path [shape transform] (let [content (gpa/transform-content (:content shape) transform) - selrect (gpa/content->selrect content) - points (gpr/rect->points selrect) - ;;rotation (mod (+ (:rotation shape 0) - ;; (or (get-in shape [:modifiers :rotation]) 0)) - ;; 360) - ] + + ;; Calculate the new selrect by "unrotate" the shape + rotation (modif-rotation shape) + center (gpt/transform (gco/center-shape shape) transform) + content-rotated (gpa/transform-content content (gmt/rotate-matrix (- rotation) center)) + selrect (gpa/content->selrect content-rotated) + + ;; Transform the points + points (-> (:points shape) + (transform-points transform))] (assoc shape :content content :points points :selrect selrect - ;;:rotation rotation - ))) + :transform (gmt/rotate-matrix rotation) + :transform-inverse (gmt/rotate-matrix (- rotation)) + :rotation rotation))) (defn apply-transform-rect "Given a new set of points transformed, set up the rectangle so it keeps diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index d68a1c24ec..638731dc12 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1038,9 +1038,12 @@ (let [page-id (:current-page-id state) objects (dwc/lookup-page-objects state page-id) shape (get objects id) - cpos (gpt/point (:x shape) (:y shape)) - pos (gpt/point (or (:x position) (:x shape)) - (or (:y position) (:y shape))) + + bbox (-> shape :points gsh/points->selrect) + + cpos (gpt/point (:x bbox) (:y bbox)) + pos (gpt/point (or (:x position) (:x bbox)) + (or (:y position) (:y bbox))) displ (gmt/translate-matrix (gpt/subtract pos cpos))] (rx/of (dwt/set-modifiers [id] {:displacement displ}) (dwt/apply-modifiers [id])))))) @@ -1544,6 +1547,7 @@ (d/export dwt/start-move-selected) (d/export dwt/move-selected) (d/export dwt/set-rotation) +(d/export dwt/increase-rotation) (d/export dwt/set-modifiers) (d/export dwt/apply-modifiers) (d/export dwt/update-dimensions) diff --git a/frontend/src/app/main/data/workspace/drawing/path.cljs b/frontend/src/app/main/data/workspace/drawing/path.cljs index 4599e903b0..25515a45c1 100644 --- a/frontend/src/app/main/data/workspace/drawing/path.cljs +++ b/frontend/src/app/main/data/workspace/drawing/path.cljs @@ -16,6 +16,7 @@ [app.common.math :as mth] [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] + [app.common.geom.matrix :as gmt] [app.util.data :as ud] [app.common.data :as cd] [app.util.geom.path :as ugp] @@ -87,12 +88,37 @@ [:workspace-drawing :object]) path))) +(defn- points->components [shape content] + (let [rotation (:rotation shape 0) + center (gsh/center-shape shape) + content-rotated (gsh/transform-content content (gmt/rotate-matrix (- rotation) center)) + + ;; Calculates the new selrect with points given the old center + points (-> (gsh/content->selrect content-rotated) + (gsh/rect->points) + (gsh/transform-points center (:transform shape (gmt/matrix)))) + + points-center (gsh/center-points points) + + ;; Points is now the selrect but the center is different so we can create the selrect + ;; through points + selrect (-> points + (gsh/transform-points points-center (:transform-inverse shape (gmt/matrix))) + (gsh/points->selrect))] + [points selrect])) + (defn update-selrect "Updates the selrect and points for a path" [shape] - (let [selrect (gsh/content->selrect (:content shape)) - points (gsh/rect->points selrect)] - (assoc shape :points points :selrect selrect))) + (if (= (:rotation shape 0) 0) + (let [content (:content shape) + selrect (gsh/content->selrect content) + points (gsh/rect->points selrect)] + (assoc shape :points points :selrect selrect)) + + (let [content (:content shape) + [points selrect] (points->components shape content)] + (assoc shape :points points :selrect selrect)))) (defn closest-angle [angle] (cond @@ -157,13 +183,12 @@ ;; TODO: Enter now finish path but can finish drawing/editing as well (= enter-keycode (:key event))))) -(defn generate-path-changes [page-id shape-id old-content new-content] +(defn generate-path-changes [page-id shape old-content new-content] (us/verify ::content old-content) (us/verify ::content new-content) - (let [old-selrect (gsh/content->selrect old-content) - old-points (gsh/rect->points old-selrect) - new-selrect (gsh/content->selrect new-content) - new-points (gsh/rect->points new-selrect) + (let [shape-id (:id shape) + [old-points old-selrect] (points->components shape old-content) + [new-points new-selrect] (points->components shape new-content) rch [{:type :mod-obj :id shape-id @@ -393,7 +418,7 @@ shape (get-in state (get-path state)) selected-points (get-in state [:workspace-local :edit-path id :selected-points] #{}) new-content (reduce ugp/make-corner-point (:content shape) selected-points) - [rch uch] (generate-path-changes page-id id (:content shape) new-content)] + [rch uch] (generate-path-changes page-id shape (:content shape) new-content)] (rx/of (dwc/commit-changes rch uch {:commit-local? true})))))) (defn make-curve [] @@ -405,7 +430,7 @@ shape (get-in state (get-path state)) selected-points (get-in state [:workspace-local :edit-path id :selected-points] #{}) new-content (reduce ugp/make-curve-point (:content shape) selected-points) - [rch uch] (generate-path-changes page-id id (:content shape) new-content)] + [rch uch] (generate-path-changes page-id shape (:content shape) new-content)] (rx/of (dwc/commit-changes rch uch {:commit-local? true})))))) (defn path-handler-enter [index prefix] @@ -552,7 +577,7 @@ shape (get-in state (get-path state)) content-modifiers (get-in state [:workspace-local :edit-path id :content-modifiers]) new-content (ugp/apply-content-modifiers (:content shape) content-modifiers) - [rch uch] (generate-path-changes page-id (:id shape) (:content shape) new-content)] + [rch uch] (generate-path-changes page-id shape (:content shape) new-content)] (rx/of (dwc/commit-changes rch uch {:commit-local? true}) (fn [state] (update-in state [:workspace-local :edit-path id] dissoc :content-modifiers))))))) @@ -573,7 +598,7 @@ shape (get-in state (get-path state)) page-id (:current-page-id state) old-content (get-in state [:workspace-local :edit-path id :old-content]) - [rch uch] (generate-path-changes page-id id old-content (:content shape))] + [rch uch] (generate-path-changes page-id shape old-content (:content shape))] (rx/of (dwc/commit-changes rch uch {:commit-local? true})))))) (declare start-draw-mode) diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index dfeb88ddb9..a62761cc00 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -431,6 +431,20 @@ (let [page-id (:current-page-id state)] (d/update-in-when state [:workspace-data :pages-index page-id :objects] set-rotation))))))) +(defn increase-rotation [ids rotation] + (ptk/reify ::increase-rotation + ptk/WatchEvent + (watch [_ state stream] + + (let [page-id (:current-page-id state) + objects (dwc/lookup-page-objects state page-id) + rotate-shape (fn [shape] + (let [delta (- rotation (:rotation shape))] + (set-rotation delta [shape])))] + (rx/concat + (rx/from (->> ids (map #(get objects %)) (map rotate-shape))) + (rx/of (apply-modifiers ids))))))) + (defn apply-modifiers [ids] (us/verify (s/coll-of uuid?) ids) diff --git a/frontend/src/app/main/ui/shapes/path.cljs b/frontend/src/app/main/ui/shapes/path.cljs index 90f485a0a1..da40a1ef7f 100644 --- a/frontend/src/app/main/ui/shapes/path.cljs +++ b/frontend/src/app/main/ui/shapes/path.cljs @@ -13,7 +13,6 @@ [rumext.alpha :as mf] [app.main.ui.shapes.attrs :as attrs] [app.main.ui.shapes.custom-stroke :refer [shape-custom-stroke]] - [app.common.geom.shapes :as geom] [app.util.object :as obj] [app.util.geom.path :as ugp])) @@ -24,14 +23,11 @@ [props] (let [shape (unchecked-get props "shape") background? (unchecked-get props "background?") - ;; {:keys [id x y width height]} (geom/shape->rect-shape shape) {:keys [id x y width height]} (:selrect shape) - transform (geom/transform-matrix shape) pdata (ugp/content->path (:content shape)) props (-> (attrs/extract-style-attrs shape) (obj/merge! - #js {:transform transform - :d pdata}))] + #js {:d pdata}))] (if background? [:g [:path {:stroke "transparent" diff --git a/frontend/src/app/main/ui/workspace/selection.cljs b/frontend/src/app/main/ui/workspace/selection.cljs index 4d53b68027..117f53a4bd 100644 --- a/frontend/src/app/main/ui/workspace/selection.cljs +++ b/frontend/src/app/main/ui/workspace/selection.cljs @@ -44,16 +44,17 @@ (def selection-rect-width 1) (mf/defc selection-rect [{:keys [transform rect zoom color]}] - (let [{:keys [x y width height]} rect] - [:rect.main - {:x x - :y y - :width width - :height height - :transform transform - :style {:stroke color - :stroke-width (/ selection-rect-width zoom) - :fill "transparent"}}])) + (when rect + (let [{:keys [x y width height]} rect] + [:rect.main + {:x x + :y y + :width width + :height height + :transform transform + :style {:stroke color + :stroke-width (/ selection-rect-width zoom) + :fill "transparent"}}]))) (defn- handlers-for-selection [{:keys [x y width height]}] [;; TOP-LEFT @@ -181,9 +182,7 @@ current-transform (mf/deref refs/current-transform) selrect (:selrect shape) - transform (geom/transform-matrix shape {:no-flip true}) - - tr-shape (geom/transform-shape shape)] + transform (geom/transform-matrix shape {:no-flip true})] (when (not (#{:move :rotate} current-transform)) [:g.controls @@ -193,7 +192,7 @@ :transform transform :zoom zoom :color color}] - [:& outline {:shape tr-shape :color color}] + [:& outline {:shape shape :color color}] ;; Handlers (for [{:keys [type position props]} (handlers-for-selection selrect)] diff --git a/frontend/src/app/main/ui/workspace/shapes/bounding_box.cljs b/frontend/src/app/main/ui/workspace/shapes/bounding_box.cljs index dc3597a949..30f903fe37 100644 --- a/frontend/src/app/main/ui/workspace/shapes/bounding_box.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/bounding_box.cljs @@ -35,11 +35,12 @@ :stroke-width "1px" :stroke-opacity 0.5}]])) -(mf/defc render-rect [{{:keys [x y width height]} :rect :keys [color]}] +(mf/defc render-rect [{{:keys [x y width height]} :rect :keys [color transform]}] [:rect {:x x :y y :width width :height height + :transform (or transform "none") :style {:stroke color :fill "transparent" :stroke-width "1px" @@ -76,7 +77,7 @@ :fill line-color :stroke "white" :stroke-width 0.1} - (str/format "%s - (%s, %s)" (str/slice (str (:id shape)) 0 8) (fixed (:x shape)) (fixed (:y shape)))] + (str/format "%s - (%s, %s)" (str/slice (str (:id shape)) 0 8) (fixed (:x selrect)) (fixed (:y selrect)))] [:& cross-point {:point shape-center :zoom zoom @@ -87,7 +88,7 @@ :zoom zoom :color line-color}]) - [:& render-rect-points {:rect selrect + [:& render-rect-points {:points (:points shape) :color line-color}] [:& render-rect {:rect selrect diff --git a/frontend/src/app/main/ui/workspace/shapes/outline.cljs b/frontend/src/app/main/ui/workspace/shapes/outline.cljs index 309bdc5ffc..102d761cf0 100644 --- a/frontend/src/app/main/ui/workspace/shapes/outline.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/outline.cljs @@ -45,7 +45,8 @@ :ry (/ height 2)} :path - {:d (ugp/content->path (:content shape))} + {:d (ugp/content->path (:content shape)) + :transform nil} {:x x :y y From e1923468a4ad59854f9fce72a361d77a55b9fcad Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 22 Dec 2020 18:05:37 +0100 Subject: [PATCH 02/10] :bug: Fixes issues with empty input in options --- .../app/main/ui/components/numeric_input.cljs | 120 ++++++++++++++---- .../ui/workspace/sidebar/options/frame.cljs | 20 +-- .../workspace/sidebar/options/frame_grid.cljs | 10 +- .../workspace/sidebar/options/measures.cljs | 84 ++++++------ .../ui/workspace/sidebar/options/path.cljs | 5 + .../sidebar/options/rows/color_row.cljs | 18 +-- .../sidebar/options/rows/input_row.cljs | 17 +-- .../ui/workspace/sidebar/options/shadow.cljs | 25 ++-- .../src/app/main/ui/workspace/viewport.cljs | 9 +- frontend/src/app/util/dom.cljs | 3 + 10 files changed, 181 insertions(+), 130 deletions(-) diff --git a/frontend/src/app/main/ui/components/numeric_input.cljs b/frontend/src/app/main/ui/components/numeric_input.cljs index d2c005729c..6ee38c6d15 100644 --- a/frontend/src/app/main/ui/components/numeric_input.cljs +++ b/frontend/src/app/main/ui/components/numeric_input.cljs @@ -13,36 +13,110 @@ [app.main.ui.keyboard :as kbd] [app.common.data :as d] [app.util.dom :as dom] - [app.util.object :as obj])) + [app.util.object :as obj] + [app.common.math :as math])) (mf/defc numeric-input {::mf/wrap-props false ::mf/forward-ref true} [props ref] - (let [on-key-down + (let [value (obj/get props "value") + on-change (obj/get props "onChange") + min-val (obj/get props "min") + max-val (obj/get props "max") + wrap-value? (obj/get props "data-wrap") + + stored-val (mf/use-var value) + local-ref (mf/use-ref nil) + ref (or ref local-ref) + + min-val (cond-> min-val + (string? min-val) (d/parse-integer nil)) + + max-val (cond-> max-val + (string? max-val) (d/parse-integer nil)) + + + num? (fn [value] (and (number? value) + (not (math/nan? value)) + (math/finite? value))) + + parse-value (fn [event] + (let [value (-> (dom/get-target-val event) (d/parse-integer nil))] + (when (num? value) + (cond-> value + (num? min-val) (cljs.core/max min-val) + (num? max-val) (cljs.core/min max-val))))) + handle-change (mf/use-callback - (fn [event] - (when (and (or (kbd/up-arrow? event) (kbd/down-arrow? event)) - (kbd/shift? event)) - (let [increment (if (kbd/up-arrow? event) 9 -9) ; this is added to the - target (dom/get-target event) ; default 1 or -1 step - min-value (-> (dom/get-attribute target "min") - (d/parse-integer ##-Inf)) - max-value (-> (dom/get-attribute target "max") - (d/parse-integer ##Inf)) - new-value (-> target - (dom/get-value) - (d/parse-integer 0) - (+ increment) - (cljs.core/min max-value) - (cljs.core/max min-value))] - (dom/set-value! target new-value))))) + (mf/deps on-change) + (fn [event] + (let [value (parse-value event)] + (when (and on-change (num? value)) + (on-change value))))) - props (-> props - (obj/set! "className" "input-text") - (obj/set! "type" "number") - (obj/set! "ref" ref) - (obj/set! "onKeyDown" on-key-down))] + set-delta + (mf/use-callback + (mf/deps on-change wrap-value? min-val max-val) + (fn [event up? down?] + (let [value (parse-value event) + increment (if up? 9 -9)] + (when (and (or up? down?) (num? value)) + (cond + (kbd/shift? event) + (let [new-value (+ value increment) + new-value (cond + (and wrap-value? (num? max-val) (num? min-val) (> new-value max-val) up?) + (+ min-val (- max-val new-value)) + (and wrap-value? (num? min-val) (num? max-val) (< new-value min-val) down?) + (- max-val (- new-value min-val)) + + (and (num? min-val) (< new-value min-val)) min-val + (and (num? max-val) (> new-value max-val)) max-val + :else new-value)] + (dom/set-value! (dom/get-target event) new-value)) + + (and wrap-value? (num? max-val) (num? min-val) (= value max-val) up?) + (dom/set-value! (dom/get-target event) min-val) + + (and wrap-value? (num? min-val) (num? max-val) (= value min-val) down?) + (dom/set-value! (dom/get-target event) max-val)))))) + + handle-key-down + (mf/use-callback + (mf/deps set-delta) + (fn [event] + (set-delta event (kbd/up-arrow? event) (kbd/down-arrow? event)))) + + handle-mouse-wheel + (mf/use-callback + (mf/deps set-delta) + (fn [event] + (set-delta event (< (.-deltaY event) 0) (> (.-deltaY event) 0)))) + + handle-blur + (fn [event] + (when-let [input-node (and ref (mf/ref-val ref))] + (dom/set-value! input-node @stored-val))) + + props (-> props + (obj/without ["value" "onChange"]) + (obj/set! "className" "input-text") + (obj/set! "type" "number") + (obj/set! "ref" ref) + (obj/set! "defaultValue" value) + (obj/set! "onWheel" handle-mouse-wheel) + (obj/set! "onKeyDown" handle-key-down) + (obj/set! "onChange" handle-change) + (obj/set! "onBlur" handle-blur))] + + (mf/use-effect + (mf/deps value) + (fn [] + (when-let [input-node (and ref (mf/ref-val ref))] + (if-not (dom/active? input-node) + (dom/set-value! input-node value) + (reset! stored-val value))))) [:> :input props])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/frame.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/frame.cljs index 90489cee25..8e5c77c863 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/frame.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/frame.cljs @@ -49,24 +49,16 @@ (udw/update-dimensions [(:id shape)] :height new-height)))) on-size-change - (fn [event attr] - (let [value (-> (dom/get-target event) - (dom/get-value) - (d/parse-integer 1))] - (st/emit! (udw/update-dimensions [(:id shape)] attr value)))) + (fn [value attr] + (st/emit! (udw/update-dimensions [(:id shape)] attr value))) on-proportion-lock-change (fn [event] (st/emit! (udw/set-shape-proportion-lock (:id shape) (not (:proportion-lock shape))))) on-position-change - (fn [event attr] - (let [cval (-> (dom/get-target event) - (dom/get-value) - (d/parse-integer 0))] - ;; TODO: Change so not apply the modifiers until blur - (when cval - (st/emit! (udw/update-position (:id shape) {attr cval}))))) + (fn [value attr] + (st/emit! (udw/update-position (:id shape) {attr value}))) on-width-change #(on-size-change % :width) on-height-change #(on-size-change % :height) @@ -105,7 +97,7 @@ i/lock i/unlock)] [:div.input-element.pixels - [:> numeric-input {:min "1" + [:> numeric-input {:min 1 :on-click select-all :on-change on-width-change :value (-> (:width shape) @@ -114,7 +106,7 @@ [:div.input-element.pixels - [:> numeric-input {:min "1" + [:> numeric-input {:min 1 :on-click select-all :on-change on-height-change :value (-> (:height shape) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/frame_grid.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/frame_grid.cljs index ed4c96295c..cc0e881755 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/frame_grid.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/frame_grid.cljs @@ -74,12 +74,6 @@ (fn [value] (emit-changes! #(assoc-in % keys value)))) - handle-change-event - (fn [& keys] - (fn [event] - (let [change-fn (apply handle-change keys)] - (-> event dom/get-target dom/get-value parse-integer change-fn)))) - handle-change-size (fn [size] (let [grid (d/deep-merge grid (:changes @state)) @@ -136,10 +130,10 @@ (if (= type :square) [:div.input-element.pixels - [:> numeric-input {:min "1" + [:> numeric-input {:min 1 :no-validate true :value (:size params) - :on-change (handle-change-event :params :size)}]] + :on-change (handle-change :params :size)}]] [:& editable-select {:value (:size params) :type (when (number? (:size params)) "number" ) :class "input-option" diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs index c26a11a8c2..2361965064 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs @@ -54,57 +54,54 @@ (not= (:x values) :multiple) (assoc :x x) (not= (:y values) :multiple) (assoc :y y))) + values (let [{:keys [width height]} (-> shapes first :selrect)] + (cond-> values + (not= (:width values) :multiple) (assoc :width width) + (not= (:height values) :multiple) (assoc :height height))) + proportion-lock (:proportion-lock values) on-size-change - (fn [event attr] - (let [value (-> (dom/get-target event) - (dom/get-value) - (d/parse-integer 1))] - (st/emit! (udw/update-dimensions ids attr value)))) + (mf/use-callback + (mf/deps ids) + (fn [value attr] + (st/emit! (udw/update-dimensions ids attr value)))) on-proportion-lock-change - (fn [event] - (let [new-lock (if (= proportion-lock :multiple) true (not proportion-lock))] - (run! #(st/emit! (udw/set-shape-proportion-lock % new-lock)) ids))) + (mf/use-callback + (mf/deps ids) + (fn [event] + (let [new-lock (if (= proportion-lock :multiple) true (not proportion-lock))] + (run! #(st/emit! (udw/set-shape-proportion-lock % new-lock)) ids)))) do-position-change - (fn [shape' frame' value attr] - (let [from (-> shape' :points gsh/points->selrect attr) - to (+ value (attr frame')) - target (+ (attr shape') (- to from))] - (st/emit! (udw/update-position (:id shape') {attr target})))) + (mf/use-callback + (mf/deps ids) + (fn [shape' frame' value attr] + (let [to (+ value (attr frame'))] + (st/emit! (udw/update-position (:id shape') { attr to }))))) on-position-change - (fn [event attr] - (let [value (-> (dom/get-target event) - (dom/get-value) - (d/parse-integer 0))] - (when value - (doall (map #(do-position-change %1 %2 value attr) shapes frames))))) - - do-rotation-change - (fn [shape' old-shape' value] - (st/emit! (udw/set-rotation (- value (:rotation shape')) [old-shape']) - (udw/apply-modifiers #{(:id shape')}))) + (mf/use-callback + (mf/deps ids) + (fn [value attr] + (doall (map #(do-position-change %1 %2 value attr) shapes frames)))) on-rotation-change - (fn [event] - (let [value (-> (dom/get-target event) - (dom/get-value) - (d/parse-integer 0))] - (doall (map #(do-rotation-change %1 %2 value) shapes old-shapes)))) + (mf/use-callback + (mf/deps ids) + (fn [value] + (st/emit! (udw/increase-rotation ids value)))) on-radius-change - (fn [event] - (let [value (-> (dom/get-target event) - (dom/get-value) - (d/parse-integer 0))] - (st/emit! (dwc/update-shapes - ids-with-children - #(if (:rx %) - (assoc % :rx value :ry value) - %))))) + (mf/use-callback + (mf/deps ids) + (fn [value] + (let [radius-update + (fn [shape] + (cond-> shape + (:rx shape) (assoc :rx value :ry value)))] + (st/emit! (dwc/update-shapes ids-with-children radius-update))))) on-width-change #(on-size-change % :width) on-height-change #(on-size-change % :height) @@ -120,7 +117,7 @@ [:div.row-flex [:span.element-set-subtitle (t locale "workspace.options.size")] [:div.input-element.width - [:> numeric-input {:min "1" + [:> numeric-input {:min 1 :no-validate true :placeholder "--" :on-click select-all @@ -128,7 +125,7 @@ :value (attr->string :width values)}]] [:div.input-element.height - [:> numeric-input {:min "1" + [:> numeric-input {:min 1 :no-validate true :placeholder "--" :on-click select-all @@ -167,8 +164,9 @@ [:div.input-element.degrees [:> numeric-input {:no-validate true - :min "0" - :max "359" + :min 0 + :max 359 + :data-wrap true :placeholder "--" :on-click select-all :on-change on-rotation-change @@ -189,7 +187,7 @@ [:div.input-element.pixels [:> numeric-input {:placeholder "--" - :min "0" + :min 0 :on-click select-all :on-change on-radius-change :value (attr->string :rx values)}]] diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/path.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/path.cljs index 0f01f9522c..363385f2f8 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/path.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/path.cljs @@ -11,6 +11,7 @@ (:require [rumext.alpha :as mf] [app.common.data :as d] + [app.main.ui.workspace.sidebar.options.measures :refer [measure-attrs measures-menu]] [app.main.ui.workspace.sidebar.options.fill :refer [fill-attrs fill-menu]] [app.main.ui.workspace.sidebar.options.stroke :refer [stroke-attrs stroke-menu]] [app.main.ui.workspace.sidebar.options.shadow :refer [shadow-menu]] @@ -20,8 +21,12 @@ [{:keys [shape] :as props}] (let [ids [(:id shape)] type (:type shape) + measure-values (select-keys shape measure-attrs) stroke-values (select-keys shape stroke-attrs)] [:* + [:& measures-menu {:ids ids + :type type + :values measure-values}] [:& fill-menu {:ids ids :type type :values (select-keys shape fill-attrs)}] diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs index f5b771dcef..58a378da57 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs @@ -55,11 +55,6 @@ (* 100) (math/round))))) -(defn string->opacity [opacity-str] - (-> opacity-str - (d/parse-integer 1) - (/ 100))) - (defn remove-multiple [v] (if (= v :multiple) nil v)) @@ -103,13 +98,8 @@ append-hash change-value)))) - handle-opacity-change (fn [event] - (let [target (dom/get-target event)] - (when (dom/valid? target) - (-> target - dom/get-value - string->opacity - change-opacity)))) + handle-opacity-change (fn [value] + (change-opacity (/ value 100))) select-all (fn [event] (dom/select-text! (dom/get-target event))) @@ -171,6 +161,6 @@ :placeholder (tr "settings.multiple") :on-click select-all :on-change handle-opacity-change - :min "0" - :max "100"}]])])])) + :min 0 + :max 100}]])])])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/input_row.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/rows/input_row.cljs index a04be184d2..c21ff370d8 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/rows/input_row.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/rows/input_row.cljs @@ -36,16 +36,9 @@ :placeholder placeholder :on-change on-change}] - (let [handle-change - (fn [event] - (let [value (-> event dom/get-target dom/get-value d/parse-integer)] - (when (and (not (nil? on-change)) - (or (not min) (>= value min)) - (or (not max) (<= value max))) - (on-change value))))] - [:> numeric-input {:placeholder placeholder - :min (when min (str min)) - :max (when max (str max)) - :on-change handle-change - :value (or value "")}]))]]) + [:> numeric-input {:placeholder placeholder + :min min + :max max + :on-change on-change + :value (or value "")}])]]) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs index fe99c537ff..4525a4c909 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs @@ -70,13 +70,10 @@ (update-attr index attr valid? nil)) ([index attr valid? update-ref] - (fn [event] - (let [value (dom/get-value (dom/get-target event))] - (when (or (not valid?) (valid? value)) - (do - (when update-ref - (dom/set-value! (mf/ref-val update-ref) value)) - (st/emit! (dwc/update-shapes ids #(assoc-in % [:shadow index attr] (js/parseInt value 10)))))))))) + (fn [value] + (when (or (not valid?) (valid? value)) + (do (st/emit! (dwc/update-shapes ids #(assoc-in % [:shadow index attr] value))) + (when update-ref (dom/set-value! (mf/ref-val update-ref) value))))))) update-color (fn [index] @@ -101,16 +98,16 @@ [:> numeric-input {:ref basic-offset-x-ref :on-change (update-attr index :offset-x valid-number?) :on-click (select-text basic-offset-x-ref) - :default-value (:offset-x value)}] + :value (:offset-x value)}] [:> numeric-input {:ref basic-offset-y-ref :on-change (update-attr index :offset-y valid-number?) :on-click (select-text basic-offset-y-ref) - :default-value (:offset-y value)}] + :value (:offset-y value)}] [:> numeric-input {:ref basic-blur-ref :on-click (select-text basic-blur-ref) :on-change (update-attr index :blur valid-number?) :min 0 - :default-value (:blur value)}] + :value (:blur value)}] [:div.element-set-actions [:div.element-set-actions-button {:on-click (toggle-visibility index)} @@ -136,7 +133,7 @@ :placeholder "--" :on-click (select-text adv-offset-x-ref) :on-change (update-attr index :offset-x valid-number? basic-offset-x-ref) - :default-value (:offset-x value)}] + :value (:offset-x value)}] [:span.after (t locale "workspace.options.shadow-options.offsetx")]] [:div.input-element @@ -145,7 +142,7 @@ :placeholder "--" :on-click (select-text adv-offset-y-ref) :on-change (update-attr index :offset-y valid-number? basic-offset-y-ref) - :default-value (:offset-y value)}] + :value (:offset-y value)}] [:span.after (t locale "workspace.options.shadow-options.offsety")]]] [:div.row-grid-2 @@ -156,7 +153,7 @@ :on-click (select-text adv-blur-ref) :on-change (update-attr index :blur valid-number? basic-blur-ref) :min 0 - :default-value (:blur value)}] + :value (:blur value)}] [:span.after (t locale "workspace.options.shadow-options.blur")]] [:div.input-element @@ -166,7 +163,7 @@ :on-click (select-text adv-spread-ref) :on-change (update-attr index :spread valid-number?) :min 0 - :default-value (:spread value)}] + :value (:spread value)}] [:span.after (t locale "workspace.options.shadow-options.spread")]]] [:div.color-row-wrap diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 8747752a3e..a9ace2171c 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -134,9 +134,11 @@ (let [objects (unchecked-get props "objects") selected (or (unchecked-get props "selected") #{}) hover (or (unchecked-get props "hover") #{}) + edition (unchecked-get props "edition") outline? (set/union selected hover) show-outline? (fn [shape] (and (not (:hidden shape)) (not (:blocked shape)) + (not= edition (:id shape)) (outline? (:id shape)))) shapes (->> (vals objects) (filter show-outline?)) transform (mf/deref refs/current-transform) @@ -158,6 +160,7 @@ selected (unchecked-get props "selected") ids (unchecked-get props "ids") ghost? (unchecked-get props "ghost?") + edition (unchecked-get props "edition") data (mf/deref refs/workspace-page) objects (:objects data) root (get objects uuid/zero) @@ -183,7 +186,8 @@ (when (not ghost?) [:& shape-outlines {:objects objects :selected selected - :hover hover}])])) + :hover hover + :edition edition}])])) (mf/defc ghost-frames {::mf/wrap-props false} @@ -611,7 +615,8 @@ "auto")}} [:& frames {:key page-id :hover (:hover local) - :selected selected}] + :selected selected + :edition edition}] (when (= :move (:transform local)) [:& ghost-frames {:modifiers (:modifiers local) diff --git a/frontend/src/app/util/dom.cljs b/frontend/src/app/util/dom.cljs index 1dad84d487..bf42d709f0 100644 --- a/frontend/src/app/util/dom.cljs +++ b/frontend/src/app/util/dom.cljs @@ -250,3 +250,6 @@ (defn get-user-agent [] (.-userAgent js/navigator)) + +(defn active? [node] + (= (.-activeElement js/document) node)) From c1c01aab0262c82d889b4f290ce4674b76b394dc Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 23 Dec 2020 09:58:43 +0100 Subject: [PATCH 03/10] :bug: Fixes problems with gradients when rotation --- common/app/common/geom/shapes.cljc | 1 + common/app/common/geom/shapes/transforms.cljc | 38 +++++++++++++++++++ .../src/app/main/ui/shapes/gradients.cljs | 25 ++++++++---- 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/common/app/common/geom/shapes.cljc b/common/app/common/geom/shapes.cljc index 50d9e07bbf..f99994ee7e 100644 --- a/common/app/common/geom/shapes.cljc +++ b/common/app/common/geom/shapes.cljc @@ -266,6 +266,7 @@ (d/export gpr/points->selrect) (d/export gtr/transform-shape) (d/export gtr/transform-matrix) +(d/export gtr/inverse-transform-matrix) (d/export gtr/transform-point-center) (d/export gtr/transform-rect) (d/export gtr/update-group-selrect) diff --git a/common/app/common/geom/shapes/transforms.cljc b/common/app/common/geom/shapes/transforms.cljc index d126c8cddc..698524501a 100644 --- a/common/app/common/geom/shapes/transforms.cljc +++ b/common/app/common/geom/shapes/transforms.cljc @@ -38,6 +38,18 @@ (and (not no-flip) flip-y) (gmt/scale (gpt/point 1 -1))) (gmt/translate (gpt/negate shape-center)))))) +(defn inverse-transform-matrix + ([shape] + (let [shape-center (or (gco/center-shape shape) + (gpt/point 0 0))] + (inverse-transform-matrix shape shape-center))) + ([shape center] + (let [] + (-> (gmt/matrix) + (gmt/translate center) + (gmt/multiply (:transform-inverse shape (gmt/matrix))) + (gmt/translate (gpt/negate center)))))) + (defn transform-point-center "Transform a point around the shape center" [point center matrix] @@ -257,6 +269,30 @@ apply-transform-rect)] (apply-transform-fn shape transform))) +(defn transform-gradients [shape modifiers] + (let [angle (d/check-num (get modifiers :rotation)) + ;; Gradients are represented with unit vectors so its center is 0.5, 0.5 + center (gpt/point 0.5 0.5) + transform (gmt/rotate-matrix angle center) + transform-gradient + (fn [{:keys [start-x start-y end-x end-y] :as gradient}] + (let [start-point (gpt/point start-x start-y) + end-point (gpt/point end-x end-y) + {start-x :x start-y :y} (gpt/transform start-point transform) + {end-x :x end-y :y} (gpt/transform end-point transform)] + + (assoc gradient + :start-x start-x + :start-y start-y + :end-x end-x + :end-y end-y)))] + (cond-> shape + (:fill-color-gradient shape) + (update :fill-color-gradient transform-gradient) + + (:stroke-color-gradient shape) + (update :stroke-color-gradient transform-gradient)))) + (defn set-flip [shape modifiers] (let [rx (get-in modifiers [:resize-vector :x]) ry (get-in modifiers [:resize-vector :y])] @@ -271,6 +307,7 @@ (-> shape (set-flip (:modifiers shape)) (apply-transform transform) + (transform-gradients (:modifiers shape)) (dissoc :modifiers))) shape))) @@ -296,3 +333,4 @@ (assoc :selrect new-selrect) (assoc :points new-points) (apply-transform-rect (gmt/matrix))))) + diff --git a/frontend/src/app/main/ui/shapes/gradients.cljs b/frontend/src/app/main/ui/shapes/gradients.cljs index 7d60bb88d5..fe10056a99 100644 --- a/frontend/src/app/main/ui/shapes/gradients.cljs +++ b/frontend/src/app/main/ui/shapes/gradients.cljs @@ -14,15 +14,21 @@ [app.util.object :as obj] [app.common.uuid :as uuid] [app.main.ui.context :as muc] - [app.common.geom.point :as gpt])) + [app.common.geom.point :as gpt] + [app.common.geom.matrix :as gmt] + [app.common.geom.shapes :as gsh])) (mf/defc linear-gradient [{:keys [id gradient shape]}] - (let [{:keys [x y width height]} shape] + (let [{:keys [x y width height]} (:selrect shape) + transform (case (:type shape) + :path (gmt/matrix) + (gsh/inverse-transform-matrix shape (gpt/point 0.5 0.5)))] [:linearGradient {:id id :x1 (:start-x gradient) :y1 (:start-y gradient) :x2 (:end-x gradient) - :y2 (:end-y gradient)} + :y2 (:end-y gradient) + :gradient-transform transform} (for [{:keys [offset color opacity]} (:stops gradient)] [:stop {:key (str id "-stop-" offset) :offset (or offset 0) @@ -30,7 +36,10 @@ :stop-opacity opacity}])])) (mf/defc radial-gradient [{:keys [id gradient shape]}] - (let [{:keys [x y width height]} shape] + (let [{:keys [x y width height]} (:selrect shape) + transform (case (:type shape) + :path (gmt/matrix) + (gsh/inverse-transform-matrix shape))] (let [[x y] (if (= (:type shape) :frame) [0 0] [x y]) translate-vec (gpt/point (+ x (* width (:start-x gradient))) (+ y (* height (:start-y gradient)))) @@ -51,10 +60,10 @@ scale-vec (gpt/point (* scale-factor-y (/ height 2)) (* scale-factor-x (/ width 2))) - tr-translate (str/fmt "translate(%s, %s)" (:x translate-vec) (:y translate-vec)) - tr-rotate (str/fmt "rotate(%s)" angle) - tr-scale (str/fmt "scale(%s, %s)" (:x scale-vec) (:y scale-vec)) - transform (str/fmt "%s %s %s" tr-translate tr-rotate tr-scale)] + transform (gmt/multiply transform + (gmt/translate-matrix translate-vec) + (gmt/rotate-matrix angle) + (gmt/scale-matrix scale-vec))] [:radialGradient {:id id :cx 0 :cy 0 From b53fceefb93559daf0bca7d1c3483019bd70e5c7 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 23 Dec 2020 10:04:33 +0100 Subject: [PATCH 04/10] :bug: Fixed problem with opacity in stroke --- frontend/src/app/main/data/colors.cljs | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/app/main/data/colors.cljs b/frontend/src/app/main/data/colors.cljs index a063fe787d..9029656adc 100644 --- a/frontend/src/app/main/data/colors.cljs +++ b/frontend/src/app/main/data/colors.cljs @@ -148,6 +148,7 @@ (cond-> s true (assoc :stroke-color (:color color) + :stroke-opacity (:opacity color) :stroke-color-gradient (:gradient color) :stroke-color-ref-id (:id color) :stroke-color-ref-file (:file-id color)) From 507550edadef5af5678bc8284aec882ef00769f1 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 23 Dec 2020 10:11:31 +0100 Subject: [PATCH 05/10] :bug: Fixes problem with image in profile --- .../resources/styles/main/partials/dashboard-settings.scss | 3 +-- frontend/src/app/main/ui/settings/profile.cljs | 7 ++++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/resources/styles/main/partials/dashboard-settings.scss b/frontend/resources/styles/main/partials/dashboard-settings.scss index c09e6d40a0..c273e3b711 100644 --- a/frontend/resources/styles/main/partials/dashboard-settings.scss +++ b/frontend/resources/styles/main/partials/dashboard-settings.scss @@ -100,8 +100,7 @@ } &:hover { - img {display: none;} - .update-overlay {opacity: 1}; + .update-overlay {opacity: 0.8}; } } } diff --git a/frontend/src/app/main/ui/settings/profile.cljs b/frontend/src/app/main/ui/settings/profile.cljs index e07c536548..7024e42f66 100644 --- a/frontend/src/app/main/ui/settings/profile.cljs +++ b/frontend/src/app/main/ui/settings/profile.cljs @@ -23,7 +23,8 @@ [app.util.i18n :as i18n :refer [tr t]] [cljs.spec.alpha :as s] [cuerdas.core :as str] - [rumext.alpha :as mf])) + [rumext.alpha :as mf] + [app.config :as cfg])) (s/def ::fullname ::us/not-empty-string) (s/def ::email ::us/email) @@ -90,10 +91,10 @@ [{:keys [locale] :as props}] (let [file-input (mf/use-ref nil) profile (mf/deref refs/profile) - photo (:photo-uri profile) + photo (:photo profile) photo (if (or (str/empty? photo) (nil? photo)) "images/avatar.jpg" - photo) + (cfg/resolve-media-path photo)) on-image-click #(dom/click (mf/ref-val file-input)) From 6af382429305751d28c8f6da117667a63c6b66a6 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 23 Dec 2020 10:16:46 +0100 Subject: [PATCH 06/10] :bug: Fixed avatar on sessions in workspace --- frontend/src/app/main/data/workspace/notifications.cljs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/main/data/workspace/notifications.cljs b/frontend/src/app/main/data/workspace/notifications.cljs index 28008bdfc5..300ec4dd71 100644 --- a/frontend/src/app/main/data/workspace/notifications.cljs +++ b/frontend/src/app/main/data/workspace/notifications.cljs @@ -13,6 +13,7 @@ [app.common.geom.point :as gpt] [app.common.pages :as cp] [app.common.spec :as us] + [app.config :as cfg] [app.main.data.workspace.common :as dwc] [app.main.data.workspace.persistence :as dwp] [app.main.data.workspace.libraries :as dwl] @@ -146,7 +147,7 @@ (let [session {:id id :fullname (:fullname profile) :updated-at (dt/now) - :photo-uri (or (:photo-uri profile) + :photo-uri (or (and (:photo profile) (cfg/resolve-media-path (:photo profile))) (avatars/generate {:name (:fullname profile)}))} session (assign-color sessions session)] (assoc sessions id session))) From 33b6df01ba3f50226860fb8910e35af1db61af06 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 23 Dec 2020 10:22:52 +0100 Subject: [PATCH 07/10] :bug: Fixes when blocking an object deselects it --- frontend/src/app/main/ui/workspace/sidebar/layers.cljs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs index 9ac44acf47..6fa7ecfadf 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs @@ -120,7 +120,8 @@ (dom/stop-propagation event) (if (:blocked item) (st/emit! (dw/update-shape-flags id {:blocked false})) - (st/emit! (dw/update-shape-flags id {:blocked true})))) + (st/emit! (dw/update-shape-flags id {:blocked true}) + (dw/select-shape id true)))) toggle-visibility (fn [event] From 9ae9da8256f608801969ffeb9325ce81d03cd986 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 23 Dec 2020 10:44:04 +0100 Subject: [PATCH 08/10] :bug: Fixes problems with handoff and text shapes --- frontend/src/app/main/ui/shapes/text.cljs | 5 ++--- frontend/src/app/main/ui/workspace/shapes/text.cljs | 8 +++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/frontend/src/app/main/ui/shapes/text.cljs b/frontend/src/app/main/ui/shapes/text.cljs index 05c0afda49..6124f45759 100644 --- a/frontend/src/app/main/ui/shapes/text.cljs +++ b/frontend/src/app/main/ui/shapes/text.cljs @@ -88,7 +88,7 @@ [props ref] (let [shape (unchecked-get props "shape") selected? (unchecked-get props "selected?") - grow-type (:grow-type shape) + grow-type (unchecked-get props "grow-type") {:keys [id x y width height content]} shape] [:foreignObject {:x x :y y @@ -97,7 +97,6 @@ :transform (geom/transform-matrix shape) :width (if (#{:auto-width} grow-type) 10000 width) :height (if (#{:auto-height :auto-width} grow-type) 10000 height) - :ref ref - :pointer-events "none"} + :ref ref} [:& text-content {:shape shape :content (:content shape)}]])) diff --git a/frontend/src/app/main/ui/workspace/shapes/text.cljs b/frontend/src/app/main/ui/workspace/shapes/text.cljs index d122c694d9..47ce0fc571 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text.cljs @@ -110,10 +110,12 @@ [:& text/text-shape {:key (str "text-shape" (:id shape)) :ref text-ref-cb :shape shape - :selected? selected?}]] + :selected? selected? + :grow-type (:grow-type shape)}]] (when edition? - [:& editor/text-shape-edit {:key (str "editor" (:id shape)) - :shape shape}]) + [:g {:pointer-events "none"} + [:& editor/text-shape-edit {:key (str "editor" (:id shape)) + :shape shape}]]) (when-not edition? [:rect.text-actions From 3f887f20e9f90e3130828d2cf68a881ced1ca479 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 23 Dec 2020 12:29:36 +0100 Subject: [PATCH 09/10] :bug: When creating a frame moves the top-level shapes inside --- common/app/common/pages/helpers.cljc | 20 ++++--------- .../src/app/main/data/workspace/common.cljs | 30 +++++++++++++++++-- .../main/data/workspace/drawing/common.cljs | 15 ++++++++-- 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/common/app/common/pages/helpers.cljc b/common/app/common/pages/helpers.cljc index b0cc1b468f..53787ac473 100644 --- a/common/app/common/pages/helpers.cljc +++ b/common/app/common/pages/helpers.cljc @@ -175,21 +175,11 @@ ([objects {:keys [include-frames?] :or {include-frames? false}}] (let [lookup #(get objects %) root (lookup uuid/zero) - childs (:shapes root)] - (loop [id (first childs) - ids (rest childs) - res []] - (if (nil? id) - res - (let [obj (lookup id) - typ (:type obj)] - (recur (first ids) - (rest ids) - (if (= :frame typ) - (if include-frames? - (d/concat res [obj] (map lookup (:shapes obj))) - (d/concat res (map lookup (:shapes obj)))) - (conj res obj))))))))) + childs (:shapes root) + shapes (->> childs + (mapv lookup))] + (cond->> shapes + include-frames? (filterv #(not= :frame (:type %))))))) (defn select-frames [objects] diff --git a/frontend/src/app/main/data/workspace/common.cljs b/frontend/src/app/main/data/workspace/common.cljs index 278255c526..45ab3be451 100644 --- a/frontend/src/app/main/data/workspace/common.cljs +++ b/frontend/src/app/main/data/workspace/common.cljs @@ -538,8 +538,6 @@ unames (retrieve-used-names objects) name (generate-unique-name unames (:name shape)) - - frame-id (if (= :frame (:type attrs)) uuid/zero (or (:frame-id attrs) @@ -568,3 +566,31 @@ (when (= :text (:type attrs)) (->> (rx/of (start-edition-mode id)) (rx/observe-on :async)))))))) + +(defn move-shapes-into-frame [frame-id shapes] + (ptk/reify ::move-shapes-into-frame + ptk/WatchEvent + (watch [_ state stream] + (let [page-id (:current-page-id state) + objects (lookup-page-objects state page-id) + to-move-shapes (->> (cp/select-toplevel-shapes objects {:include-frames? false}) + (mapv :id) + (d/enumerate) + (filterv (comp shapes second))) + + rchanges [{:type :mov-objects + :parent-id frame-id + :frame-id frame-id + :page-id page-id + :index 0 + :shapes (mapv second to-move-shapes)}] + + uchanges (->> to-move-shapes + (mapv (fn [[index shape-id]] + {:type :mov-objects + :parent-id uuid/zero + :frame-id uuid/zero + :page-id page-id + :index index + :shapes [shape-id]})))] + (rx/of (commit-changes rchanges uchanges {:commit-local? true})))))) diff --git a/frontend/src/app/main/data/workspace/drawing/common.cljs b/frontend/src/app/main/data/workspace/drawing/common.cljs index c5a19c32c3..fef13e2450 100644 --- a/frontend/src/app/main/data/workspace/drawing/common.cljs +++ b/frontend/src/app/main/data/workspace/drawing/common.cljs @@ -15,7 +15,8 @@ [app.common.geom.shapes :as gsh] [app.main.data.workspace.common :as dwc] [app.main.data.workspace.selection :as dws] - [app.main.streams :as ms])) + [app.main.streams :as ms] + [app.main.worker :as uw])) (def clear-drawing (ptk/reify ::clear-drawing @@ -31,7 +32,8 @@ (rx/concat (rx/of clear-drawing) (when (:initialized? shape) - (let [shape-click-width (case (:type shape) + (let [page-id (:current-page-id state) + shape-click-width (case (:type shape) :text 3 20) shape-click-height (case (:type shape) @@ -59,4 +61,11 @@ (rx/empty)) (rx/of (dws/deselect-all) - (dwc/add-shape shape)))))))))) + (dwc/add-shape shape)) + + (if (= :frame (:type shape)) + (->> (uw/ask! {:cmd :selection/query + :page-id page-id + :rect (:selrect shape)}) + (rx/map #(dwc/move-shapes-into-frame (:id shape) %))) + (rx/empty)))))))))) From 6d328e852d1b5841fec8b1ff8d3016e2c644fc74 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 23 Dec 2020 12:33:20 +0100 Subject: [PATCH 10/10] :bug: Selection tool not selected when editing shapes --- frontend/src/app/main/ui/workspace/left_toolbar.cljs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/left_toolbar.cljs b/frontend/src/app/main/ui/workspace/left_toolbar.cljs index fe606453b6..edebacf8db 100644 --- a/frontend/src/app/main/ui/workspace/left_toolbar.cljs +++ b/frontend/src/app/main/ui/workspace/left_toolbar.cljs @@ -69,13 +69,15 @@ [props] (let [layout (obj/get props "layout") selected-drawtool (mf/deref refs/selected-drawing-tool) - select-drawtool #(st/emit! :interrupt (dw/select-for-drawing %))] + select-drawtool #(st/emit! :interrupt (dw/select-for-drawing %)) + edition (mf/deref refs/selected-edition)] [:aside.left-toolbar [:div.left-toolbar-inside [:ul.left-toolbar-options [:li.tooltip.tooltip-right {:alt (tr "workspace.toolbar.move") - :class (when (nil? selected-drawtool) "selected") + :class (when (and (nil? selected-drawtool) + (not edition)) "selected") :on-click (st/emitf :interrupt)} i/pointer-inner] [:li.tooltip.tooltip-right