From b5248bf52066af7f75ec4d36113cc41904e40969 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 20 Dec 2016 16:54:53 +0100 Subject: [PATCH 01/11] Remove whitespaces on constants. --- frontend/src/uxbox/main/constants.cljs | 3 --- 1 file changed, 3 deletions(-) diff --git a/frontend/src/uxbox/main/constants.cljs b/frontend/src/uxbox/main/constants.cljs index 94aadee87b..076f827a55 100644 --- a/frontend/src/uxbox/main/constants.cljs +++ b/frontend/src/uxbox/main/constants.cljs @@ -3,7 +3,6 @@ ;; file, You can obtain one at http://mozilla.org/MPL/2.0/. ;; ;; Copyright (c) 2015-2016 Andrey Antukh -;; Copyright (c) 2015-2016 Juan de la Cruz (ns uxbox.main.constants) @@ -18,5 +17,3 @@ (def canvas-scroll-padding 50) (def canvas-start-scroll-x (- canvas-start-x canvas-scroll-padding)) (def canvas-start-scroll-y (- canvas-start-y canvas-scroll-padding)) - - From 0a5f4e310ca7b9a5157b40b0b0d65a5040de1c32 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 20 Dec 2016 16:55:51 +0100 Subject: [PATCH 02/11] Prevent page persistence when shape is resizing. --- frontend/src/uxbox/main/data/pages.cljs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/frontend/src/uxbox/main/data/pages.cljs b/frontend/src/uxbox/main/data/pages.cljs index 481b33f91f..9ac75a5294 100644 --- a/frontend/src/uxbox/main/data/pages.cljs +++ b/frontend/src/uxbox/main/data/pages.cljs @@ -9,10 +9,11 @@ [cuerdas.core :as str] [beicon.core :as rx] [lentes.core :as l] - [uxbox.main.repo :as rp] - [uxbox.store :as st] - [uxbox.util.spec :as us] [potok.core :as ptk] + [uxbox.store :as st] + [uxbox.main.repo :as rp] + [uxbox.util.rlocks :as rlocks] + [uxbox.util.spec :as us] [uxbox.util.router :as r] [uxbox.util.i18n :refer (tr)] [uxbox.util.forms :as sc] @@ -308,6 +309,7 @@ (rx/merge (->> stream (rx/take-until stopper) + (rx/filter #(not= @rlocks/lock :shape/resize)) (rx/filter #(satisfies? IPageUpdate %)) (rx/debounce 1000) (rx/map #(persist-page id))) From 8ca15771d5025300cff32979d7d87f40506a573b Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 20 Dec 2016 16:57:01 +0100 Subject: [PATCH 03/11] Make geom/size as shape transformation instead simple calculation. --- frontend/src/uxbox/main/geom.cljs | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/frontend/src/uxbox/main/geom.cljs b/frontend/src/uxbox/main/geom.cljs index 39962143a7..9f9cef3acc 100644 --- a/frontend/src/uxbox/main/geom.cljs +++ b/frontend/src/uxbox/main/geom.cljs @@ -12,6 +12,7 @@ ;; --- Relative Movement +;; TODO: revisit, maybe dead code (declare move-rect) (declare move-path) (declare move-circle) @@ -118,31 +119,47 @@ (declare size-rect) (declare size-circle) +(declare size-path) (defn size "Calculate the size of the shape." [shape] (case (:type shape) + :group (assoc shape :width 100 :height 100) :circle (size-circle shape) :text (size-rect shape) :rect (size-rect shape) :icon (size-rect shape) :image (size-rect shape) - :path (size-rect shape))) + :path (size-path shape))) + +(defn- size-path + [{:keys [points x1 y1 x2 y2] :as shape}] + (if (and x1 y1 x2 y2) + (assoc shape + :width (- x2 x1) + :height (- y2 y1)) + (let [minx (apply min (map :x points)) + miny (apply min (map :y points)) + maxx (apply max (map :x points)) + maxy (apply max (map :y points))] + (assoc shape + :width (- maxx minx) + :height (- maxy miny))))) (defn- size-rect "A specialized function for calculate size for rect-like shapes." [{:keys [x1 y1 x2 y2] :as shape}] - {:width (- x2 x1) - :height (- y2 y1)}) + (merge shape {:width (- x2 x1) + :height (- y2 y1)})) (defn- size-circle "A specialized function for calculate size for circle shape." - [{:keys [rx ry]}] - {:width (* rx 2) - :height (* ry 2)}) + [{:keys [rx ry] :as shape}] + (merge shape {:width (* rx 2) + :height (* ry 2)})) ;; --- Vertex Access From 747c07af00f938f3a54ce3dbe959226b7fdd3380 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 20 Dec 2016 16:57:35 +0100 Subject: [PATCH 04/11] Add geom helpers for apply a transformation matrix to shape. --- frontend/src/uxbox/main/geom.cljs | 160 ++++++++++++++++++++---------- 1 file changed, 109 insertions(+), 51 deletions(-) diff --git a/frontend/src/uxbox/main/geom.cljs b/frontend/src/uxbox/main/geom.cljs index 9f9cef3acc..2e70bf9c1e 100644 --- a/frontend/src/uxbox/main/geom.cljs +++ b/frontend/src/uxbox/main/geom.cljs @@ -213,7 +213,7 @@ "A specialized function for vertex movement for rect-like shapes." [shape vid {dx :x dy :y lock? :lock}] - (letfn [(handle-positioning [{:keys [x1 x2 y1 y2 proportion] :as shape}] + (letfn [(handle-positioning [{:keys [x1 x2 y1 y2] :as shape}] (case vid :top-left (assoc shape :x1 (min x2 (+ x1 dx)) @@ -482,66 +482,124 @@ :proportion (/ width height) :proportion-lock true))) -;; --- Inner Rect +;; --- Coerce to Rect-like shape. -(declare apply-rotation-transformation) -(declare inner-rect-circle) -(declare inner-rect-group) -(declare inner-rect-path) -(declare inner-rect-generic) +(declare circle->rect-shape) +(declare path->rect-shape) +(declare group->rect-shape) -(defn inner-rect - ([shape] (inner-rect @st/state shape)) - ([state shape] - (case (:type shape) - :circle (inner-rect-circle state shape) - :group (inner-rect-group state shape) - :path (inner-rect-path state shape) - (inner-rect-generic state shape)))) +(defn shape->rect-shape + "Coerce shape to rect like shape." + ([shape] (shape->rect-shape @st/state shape)) + ([state {:keys [type] :as shape}] + (case type + :circle (circle->rect-shape state shape) + :path (path->rect-shape state shape) + :group (group->rect-shape state shape) + shape))) -(defn- inner-rect-generic - [state {:keys [x1 y1] :as shape}] - (-> (assoc shape :x x1 :y y1) - (merge (size shape)) - (apply-rotation-transformation))) +(defn shapes->rect-shape + ([shapes] (shapes->rect-shape @st/state shapes)) + ([state shapes] + {:pre [(seq shapes)]} + (let [shapes (map shape->rect-shape shapes) + minx (apply min (map :x1 shapes)) + miny (apply min (map :y1 shapes)) + maxx (apply max (map :x2 shapes)) + maxy (apply max (map :y2 shapes))] + {:x1 minx + :y1 miny + :x2 maxx + :y2 maxy + ::shapes shapes}))) -(defn- inner-rect-path +(defn- group->rect-shape + [state {:keys [items] :as group}] + (let [shapes (map #(get-in state [:shapes %]) items)] + (shapes->rect-shape state shapes))) + +(defn- path->rect-shape [state {:keys [points] :as shape}] (let [minx (apply min (map :x points)) miny (apply min (map :y points)) maxx (apply max (map :x points)) - maxy (apply max (map :y points)) - props {:x minx - :y miny - :width (- maxx minx) - :height (- maxy miny)}] - (-> (merge shape props) - (apply-rotation-transformation)))) + maxy (apply max (map :y points))] + (assoc shape + :x1 minx + :y1 miny + :x2 maxx + :y2 maxy))) -(defn- inner-rect-circle - [state {:keys [cx cy rx ry group] :as shape}] - (let [props {:x (- cx rx) - :y (- cy ry) - :width (* rx 2) - :height (* ry 2)}] - (-> (merge shape props) - (apply-rotation-transformation)))) +(defn- circle->rect-shape + [state {:keys [cx cy rx ry] :as shape}] + (let [width (* rx 2) + height (* ry 2) + x1 (- cx rx) + y1 (- cy ry)] + (assoc shape + :x1 x1 + :y1 y1 + :x2 (+ x1 width) + :y2 (+ y1 height)))) -(defn- inner-rect-group - [state {:keys [id group rotation dx dy] :as shape}] - (let [shapes (->> (:items shape) - (map #(get-in state [:shapes %])) - (map #(inner-rect state %))) - x (apply min (map :x shapes)) - y (apply min (map :y shapes)) - x' (apply max (map (fn [{:keys [x width]}] (+ x width)) shapes)) - y' (apply max (map (fn [{:keys [y height]}] (+ y height)) shapes)) - width (- x' x) - height (- y' y) - x (+ x dx) - y (+ y dy)] - (-> (merge shape {:width width :height height :x x :y y}) - (apply-rotation-transformation)))) +;; --- Transform Shape + +(declare transform-rect) +(declare transform-circle) +(declare transform-path) + +(defn transform + "Apply the matrix transformation to shape." + ([shape xfmt] (transform @st/state shape xfmt)) + ([state {:keys [type] :as shape} xfmt] + (case type + :rect (transform-rect shape xfmt) + :icon (transform-rect shape xfmt) + :image (transform-rect shape xfmt) + :path (transform-path shape xfmt) + :circle (transform-circle shape xfmt)))) + +(defn- transform-rect + [{:keys [x1 y1] :as shape} mx] + (let [{:keys [width height]} (size shape) + tl (gpt/transform [x1 y1] mx) + tr (gpt/transform [(+ x1 width) y1] mx) + bl (gpt/transform [x1 (+ y1 height)] mx) + br (gpt/transform [(+ x1 width) (+ y1 height)] mx) + minx (apply min (map :x [tl tr bl br])) + maxx (apply max (map :x [tl tr bl br])) + miny (apply min (map :y [tl tr bl br])) + maxy (apply max (map :y [tl tr bl br]))] + (assoc shape + :x1 minx + :y1 miny + :x2 (+ minx (- maxx minx)) + :y2 (+ miny (- maxy miny))))) + +(defn- transform-circle + [{:keys [cx cy rx ry] :as shape} xfmt] + (let [{:keys [x1 y1 x2 y2]} (shape->rect-shape shape) + tl (gpt/transform [x1 y1] xfmt) + tr (gpt/transform [x2 y1] xfmt) + bl (gpt/transform [x1 y2] xfmt) + br (gpt/transform [x2 y2] xfmt) + + x (apply min (map :x [tl tr bl br])) + y (apply min (map :y [tl tr bl br])) + maxx (apply max (map :x [tl tr bl br])) + maxy (apply max (map :y [tl tr bl br])) + width (- maxx x) + height (- maxy y) + cx (+ x (/ width 2)) + cy (+ y (/ height 2)) + rx (/ width 2) + ry (/ height 2)] + (assoc shape :cx cx :cy cy :rx rx :ry ry))) + +(defn- transform-path + [{:keys [points] :as shape} xfmt] + (let [points (map #(gpt/transform % xfmt) points)] + (assoc shape :points points))) ;; --- Outer Rect From f7f05c4dbbbe39ff3fe8d3287b56eaa5ee369219 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 20 Dec 2016 16:58:28 +0100 Subject: [PATCH 05/11] Remove unused code from geom ns. --- frontend/src/uxbox/main/geom.cljs | 94 ------------------------------- 1 file changed, 94 deletions(-) diff --git a/frontend/src/uxbox/main/geom.cljs b/frontend/src/uxbox/main/geom.cljs index 2e70bf9c1e..c764df03e4 100644 --- a/frontend/src/uxbox/main/geom.cljs +++ b/frontend/src/uxbox/main/geom.cljs @@ -746,100 +746,6 @@ :x x :y y})) -;; --- Transformation Matrix - -(declare transformation-matrix-rect) -(declare transformation-matrix-text) -(declare transformation-matrix-circle) -(declare transformation-matrix-icon) -(declare transformation-matrix-path) -(declare transformation-matrix-group) - -(defn transformation-matrix - ([shape] - (transformation-matrix @st/state shape)) - ([state shape] - (case (:type shape) - :rect (transformation-matrix-rect state shape) - :text (transformation-matrix-text state shape) - :circle (transformation-matrix-circle state shape) - :icon (transformation-matrix-icon state shape) - :image (transformation-matrix-icon state shape) - :path (transformation-matrix-path state shape) - :group (transformation-matrix-group state shape)))) - -(defn- transformation-matrix-rect - [state {:keys [x1 y1 rotation] :or {rotation 0} :as shape}] - (let [{:keys [width height]} (size shape) - center-x (+ x1 (/ width 2)) - center-y (+ y1 (/ height 2))] - (-> (gmt/matrix) - (gmt/translate center-x center-y) - (gmt/rotate rotation) - (gmt/translate (- center-x) (- center-y))))) - -(defn- transformation-matrix-text - [state {:keys [x1 y1 rotation] :or {rotation 0} :as shape}] - (let [{:keys [width height]} (size shape) - center-x (+ x1 (/ width 2)) - center-y (+ y1 (/ height 2))] - (-> (gmt/matrix) - (gmt/translate center-x center-y) - (gmt/rotate rotation) - (gmt/translate (- center-x) (- center-y))))) - -(defn- transformation-matrix-icon - [state {:keys [x1 y1 rotation view-box] :or {rotation 0} :as shape}] - (let [{:keys [width height]} (size shape) - orig-width (nth view-box 2) - orig-height (nth view-box 3) - scale-x (/ width orig-width) - scale-y (/ height orig-height) - center-x (- width (/ width 2)) - center-y (- height (/ height 2))] - (-> (gmt/matrix) - (gmt/translate x1 y1) - (gmt/translate center-x center-y) - (gmt/rotate rotation) - (gmt/translate (- center-x) (- center-y)) - (gmt/scale scale-x scale-y)))) - -(defn- transformation-matrix-path - [state {:keys [x1 y1 rotation view-box] :or {rotation 0} :as shape}] - (let [{:keys [width height]} (size shape) - orig-width (nth view-box 2) - orig-height (nth view-box 3) - scale-x (/ width orig-width) - scale-y (/ height orig-height) - center-x (- width (/ width 2)) - center-y (- height (/ height 2))] - (-> (gmt/matrix) - (gmt/translate x1 y1) - (gmt/translate center-x center-y) - (gmt/rotate rotation) - (gmt/translate (- center-x) (- center-y)) - (gmt/scale scale-x scale-y)))) - -(defn- transformation-matrix-circle - [state {:keys [cx cy rx ry rotation] :or {rotation 0} :as shape}] - (-> (gmt/matrix) - (gmt/translate cx cy) - (gmt/rotate rotation) - (gmt/translate (- cx) (- cy)))) - -(defn- transformation-matrix-group - [state {:keys [dx dy rotation items] :or {rotation 0} :as shape}] - (let [shapes-by-id (get state :shapes) - shapes (map #(get shapes-by-id %) items) - {:keys [x y width height]} (outer-rect-coll shapes) - center-x (+ x (/ width 2)) - center-y (+ y (/ height 2))] - (-> (gmt/matrix) - (gmt/translate (or dx 0) (or dy 0)) - (gmt/translate center-x center-y) - (gmt/rotate rotation) - (gmt/translate (- center-x) (- center-y))))) - ;; --- Helpers (defn apply-rotation From 5acb69995550dff7c53842efd066dc5ca52c4a12 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 20 Dec 2016 16:58:53 +0100 Subject: [PATCH 06/11] Remove and reorganize imports on login ns. --- frontend/src/uxbox/main/ui/auth/login.cljs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/src/uxbox/main/ui/auth/login.cljs b/frontend/src/uxbox/main/ui/auth/login.cljs index 98e57505af..a1d638ee34 100644 --- a/frontend/src/uxbox/main/ui/auth/login.cljs +++ b/frontend/src/uxbox/main/ui/auth/login.cljs @@ -7,17 +7,17 @@ (ns uxbox.main.ui.auth.login (:require [lentes.core :as l] [cuerdas.core :as str] - [uxbox.util.router :as rt] - [uxbox.util.dom :as dom] [potok.core :as ptk] - [uxbox.util.forms :as forms] - [uxbox.util.mixins :as mx :include-macros true] [uxbox.store :as st] [uxbox.main.data.auth :as da] [uxbox.main.data.messages :as udm] [uxbox.main.ui.icons :as i] [uxbox.main.ui.messages :as uum] - [uxbox.main.ui.navigation :as nav])) + [uxbox.main.ui.navigation :as nav] + [uxbox.util.mixins :as mx :include-macros true] + [uxbox.util.router :as rt] + [uxbox.util.dom :as dom] + [uxbox.util.forms :as forms])) (def form-data (forms/focus-data :login st/state)) (def set-value! (partial forms/set-value! :login)) From aed1b8cd26ffe7875b8961bbf2469fe4741d5a86 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 20 Dec 2016 17:03:40 +0100 Subject: [PATCH 07/11] Improve matrix transformation helpers. --- frontend/src/uxbox/util/geom/matrix.cljs | 154 ++++++++++++++--------- 1 file changed, 96 insertions(+), 58 deletions(-) diff --git a/frontend/src/uxbox/util/geom/matrix.cljs b/frontend/src/uxbox/util/geom/matrix.cljs index 9306d19b21..c3586db331 100644 --- a/frontend/src/uxbox/util/geom/matrix.cljs +++ b/frontend/src/uxbox/util/geom/matrix.cljs @@ -44,63 +44,7 @@ (let [[a b c d tx ty] v] (Matrix. a b c d tx ty)))) -(defn ^boolean matrix? - "Return true if `v` is Matrix instance." - [v] - (instance? Matrix v)) - -(defn matrix - "Create a new matrix instance." - ([] - (Matrix. 1 0 0 1 0 0)) - ([v] - (-matrix v)) - ([a b c d tx ty] - (Matrix. a b c d tx ty))) - -(defn rotate - "Apply rotation transformation to the matrix." - ([m angle] - (let [center (gpt/point 0 0)] - (rotate m angle center))) - ([m angle center] - (let [angle (mth/radians angle) - x (:x center) - y (:y center) - cos (mth/cos angle) - sin (mth/sin angle) - nsin (- sin) - tx (- x (+ (* x cos)) (* y sin)) - ty (- y (- (* x sin)) (* y cos)) - a (+ (* cos (:a m)) (* sin (:b m))) - b (+ (* nsin (:a m)) (* cos (:b m))) - c (+ (* cos (:c m)) (* sin (:d m))) - d (+ (* nsin (:c m)) (* cos (:d m))) - tx' (+ (:tx m) (* tx (:a m)) (* ty (:b m))) - ty' (+ (:ty m) (* tx (:c m)) (* ty (:d m)))] - (Matrix. a b c d tx' ty')))) - -(defn scale - "Apply scale transformation to the matrix." - ([m v] (scale m v v)) - ([m x y] - (assoc m - :a (* (:a m) x) - :c (* (:c m) x) - :b (* (:b m) y) - :d (* (:d m) y)))) - -(defn translate - "Apply translate transformation to the matrix." - ([m pt] - (let [pt (gpt/-point pt)] - (assoc m - :tx (+ (:tx m) (* (:x pt) (:a m)) (* (:y pt) (:b m))) - :ty (+ (:ty m) (* (:x pt) (:c m)) (* (:y pt) (:d m)))))) - ([m x y] - (translate m (gpt/point x y)))) - -(defn append +(defn multiply ([m om] (let [a1 (:a m) b1 (:b m) @@ -122,7 +66,101 @@ (+ tx1 (* tx2 a1) (* ty2 b1)) (+ ty1 (* tx2 c1) (* ty2 d1))))) ([m om & others] - (reduce append (append m om) others))) + (reduce multiply (multiply m om) others))) + +(defn ^boolean matrix? + "Return true if `v` is Matrix instance." + [v] + (instance? Matrix v)) + +(defn matrix + "Create a new matrix instance." + ([] + (Matrix. 1 0 0 1 0 0)) + ([v] + (-matrix v)) + ([a b c d tx ty] + (Matrix. a b c d tx ty))) + +(defn translate-matrix + ([pt] + (let [pt (gpt/-point pt)] + (Matrix. 1 0 0 1 (:x pt) (:y pt)))) + ([x y] + (translate-matrix (gpt/point x y)))) + +(defn scale-matrix + ([s] + (Matrix. s 0 0 s 0 0)) + ([sx sy] + (Matrix. sx 0 0 sy 0 0))) + +(defn rotate-matrix + [a] + (let [a (mth/radians a)] + (Matrix. (mth/cos a) + (mth/sin a) + (- (mth/sin a)) + (mth/cos a) + 0 0))) + +(defn rotate + "Apply rotation transformation to the matrix." + ([m angle] + (multiply m (rotate-matrix angle))) + ([m angle center] + (multiply m + (translate-matrix center) + (rotate-matrix angle) + (translate-matrix (gpt/negate center))))) + + ;; ([m angle] + ;; (let [center (gpt/point 0 0)] + ;; (rotate m angle center))) + ;; ([m angle center] + ;; (let [angle (mth/radians angle) + ;; x (:x center) + ;; y (:y center) + ;; cos (mth/cos angle) + ;; sin (mth/sin angle) + ;; nsin (- sin) + ;; tx (- x (+ (* x cos)) (* y sin)) + ;; ty (- y (- (* x sin)) (* y cos)) + ;; a (+ (* cos (:a m)) (* sin (:b m))) + ;; b (+ (* nsin (:a m)) (* cos (:b m))) + ;; c (+ (* cos (:c m)) (* sin (:d m))) + ;; d (+ (* nsin (:c m)) (* cos (:d m))) + ;; tx' (+ (:tx m) (* tx (:a m)) (* ty (:b m))) + ;; ty' (+ (:ty m) (* tx (:c m)) (* ty (:d m)))] + ;; (Matrix. a b c d tx' ty')))) + +(defn scale + "Apply scale transformation to the matrix." + ([m v] (scale m v v)) + ([m vx vy] (multiply m (scale-matrix vx vy)))) + + ;; ([m v] (scale m v v)) + ;; ([m x y] + ;; (assoc m + ;; :a (* (:a m) x) + ;; :c (* (:c m) x) + ;; :b (* (:b m) y) + ;; :d (* (:d m) y)))) + +(defn translate + "Apply translate transformation to the matrix." + ([m pt] + (multiply m (translate-matrix pt))) + ([m x y] + (translate m (gpt/point x y)))) + + ;; ([m pt] + ;; (let [pt (gpt/-point pt)] + ;; (assoc m + ;; :tx (+ (:tx m) (* (:x pt) (:a m)) (* (:y pt) (:b m))) + ;; :ty (+ (:ty m) (* (:x pt) (:c m)) (* (:y pt) (:d m)))))) + ;; ([m x y] + ;; (translate m (gpt/point x y)))) (defn ^boolean invertible? [{:keys [a b c d tx ty] :as m}] From 462f37e601cabe4ce3b513ea3519944a25a964e0 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 20 Dec 2016 17:04:18 +0100 Subject: [PATCH 08/11] Improve point transformation helpers. --- frontend/src/uxbox/util/geom/point.cljs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/frontend/src/uxbox/util/geom/point.cljs b/frontend/src/uxbox/util/geom/point.cljs index f5258bbf71..b2c05325ec 100644 --- a/frontend/src/uxbox/util/geom/point.cljs +++ b/frontend/src/uxbox/util/geom/point.cljs @@ -94,6 +94,12 @@ (Point. (/ (:x p) (:x other)) (/ (:y p) (:y other))))) +(defn negate + [p] + {:pre [(point? p)]} + (let [{:keys [x y]} (-point p)] + (Point. (- x) (- y)))) + (defn distance "Calculate the distance between two points." [p other] @@ -161,7 +167,7 @@ (defn transform "Transform a point applying a matrix transfomation." - [{:keys [x y] :as p} {:keys [a b c d tx ty] :as m}] - (Point. (+ (* x a) (* y c) tx) - (+ (* x b) (* y d) ty))) - + [pt {:keys [a b c d tx ty] :as m}] + (let [{:keys [x y]} (point pt)] + (Point. (+ (* x a) (* y c) tx) + (+ (* x b) (* y d) ty)))) From a28a6978fecbee1657d73ec7590c31c9f2acc627 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 20 Dec 2016 17:04:38 +0100 Subject: [PATCH 09/11] Add matrix type to transit handlers. --- frontend/src/uxbox/util/transit.cljs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/frontend/src/uxbox/util/transit.cljs b/frontend/src/uxbox/util/transit.cljs index 70a94272e3..534c97f4dc 100644 --- a/frontend/src/uxbox/util/transit.cljs +++ b/frontend/src/uxbox/util/transit.cljs @@ -10,6 +10,7 @@ [com.cognitect.transit :as tr] [uxbox.util.data :refer (parse-int)] [uxbox.util.geom.point :as gpt] + [uxbox.util.geom.matrix :as gmt] [uxbox.util.datetime :as dt])) ;; --- Transit Handlers @@ -34,13 +35,25 @@ (gpt/point (vec value)) (gpt/map->Point value))))) +(def matrix-write-handler + (t/write-handler + (constantly "matrix") + (fn [v] (into {} v)))) + +(def matrix-read-handler + (t/read-handler + (fn [value] + (gmt/map->Matrix value)))) + (def ^:privare +read-handlers+ {"u" uuid "m" datetime-read-handler + "matrix" matrix-read-handler "point" point-read-handler}) (def ^:privare +write-handlers+ {dt/DateTime datetime-write-handler + gmt/Matrix matrix-write-handler gpt/Point point-write-handler}) ;; --- Public Api From 23dbc77da909ccb65f047d4a63e6f6eb871fd484 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 20 Dec 2016 21:08:12 +0100 Subject: [PATCH 10/11] Fix copyright headers on some files. --- frontend/src/uxbox/main/data/dashboard.cljs | 1 - frontend/src/uxbox/main/data/projects.cljs | 1 - frontend/src/uxbox/main/data/shapes.cljs | 1 - frontend/src/uxbox/main/ui/auth/login.cljs | 3 ++- frontend/src/uxbox/main/ui/auth/recovery.cljs | 3 ++- frontend/src/uxbox/main/ui/auth/recovery_request.cljs | 3 ++- frontend/src/uxbox/main/ui/auth/register.cljs | 3 ++- 7 files changed, 8 insertions(+), 7 deletions(-) diff --git a/frontend/src/uxbox/main/data/dashboard.cljs b/frontend/src/uxbox/main/data/dashboard.cljs index aeae181799..93ce7ad395 100644 --- a/frontend/src/uxbox/main/data/dashboard.cljs +++ b/frontend/src/uxbox/main/data/dashboard.cljs @@ -3,7 +3,6 @@ ;; file, You can obtain one at http://mozilla.org/MPL/2.0/. ;; ;; Copyright (c) 2015-2016 Andrey Antukh -;; Copyright (c) 2015-2016 Juan de la Cruz (ns uxbox.main.data.dashboard (:require [beicon.core :as rx] diff --git a/frontend/src/uxbox/main/data/projects.cljs b/frontend/src/uxbox/main/data/projects.cljs index 5568565cf7..1ffbb6aa76 100644 --- a/frontend/src/uxbox/main/data/projects.cljs +++ b/frontend/src/uxbox/main/data/projects.cljs @@ -3,7 +3,6 @@ ;; file, You can obtain one at http://mozilla.org/MPL/2.0/. ;; ;; Copyright (c) 2015-2016 Andrey Antukh -;; Copyright (c) 2015-2016 Juan de la Cruz (ns uxbox.main.data.projects (:require [cuerdas.core :as str] diff --git a/frontend/src/uxbox/main/data/shapes.cljs b/frontend/src/uxbox/main/data/shapes.cljs index a164f3ea89..4c2ae4359b 100644 --- a/frontend/src/uxbox/main/data/shapes.cljs +++ b/frontend/src/uxbox/main/data/shapes.cljs @@ -3,7 +3,6 @@ ;; file, You can obtain one at http://mozilla.org/MPL/2.0/. ;; ;; Copyright (c) 2015-2016 Andrey Antukh -;; Copyright (c) 2015-2016 Juan de la Cruz (ns uxbox.main.data.shapes (:require [beicon.core :as rx] diff --git a/frontend/src/uxbox/main/ui/auth/login.cljs b/frontend/src/uxbox/main/ui/auth/login.cljs index a1d638ee34..006ee21a1a 100644 --- a/frontend/src/uxbox/main/ui/auth/login.cljs +++ b/frontend/src/uxbox/main/ui/auth/login.cljs @@ -2,7 +2,8 @@ ;; 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) 2016 Andrey Antukh +;; Copyright (c) 2015-2016 Andrey Antukh +;; Copyright (c) 2015-2016 Juan de la Cruz (ns uxbox.main.ui.auth.login (:require [lentes.core :as l] diff --git a/frontend/src/uxbox/main/ui/auth/recovery.cljs b/frontend/src/uxbox/main/ui/auth/recovery.cljs index 19092e63d3..4c416e984c 100644 --- a/frontend/src/uxbox/main/ui/auth/recovery.cljs +++ b/frontend/src/uxbox/main/ui/auth/recovery.cljs @@ -2,7 +2,8 @@ ;; 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) 2016 Andrey Antukh +;; Copyright (c) 2015-2016 Andrey Antukh +;; Copyright (c) 2015-2016 Juan de la Cruz (ns uxbox.main.ui.auth.recovery (:require [lentes.core :as l] diff --git a/frontend/src/uxbox/main/ui/auth/recovery_request.cljs b/frontend/src/uxbox/main/ui/auth/recovery_request.cljs index 60e402363b..0e6d29cd3f 100644 --- a/frontend/src/uxbox/main/ui/auth/recovery_request.cljs +++ b/frontend/src/uxbox/main/ui/auth/recovery_request.cljs @@ -2,7 +2,8 @@ ;; 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) 2016 Andrey Antukh +;; Copyright (c) 2015-2016 Andrey Antukh +;; Copyright (c) 2015-2016 Juan de la Cruz (ns uxbox.main.ui.auth.recovery-request (:require [lentes.core :as l] diff --git a/frontend/src/uxbox/main/ui/auth/register.cljs b/frontend/src/uxbox/main/ui/auth/register.cljs index e49ce49f56..718c38245c 100644 --- a/frontend/src/uxbox/main/ui/auth/register.cljs +++ b/frontend/src/uxbox/main/ui/auth/register.cljs @@ -2,7 +2,8 @@ ;; 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) 2016 Andrey Antukh +;; Copyright (c) 2015-2016 Andrey Antukh +;; Copyright (c) 2015-2016 Juan de la Cruz (ns uxbox.main.ui.auth.register (:require [lentes.core :as l] From af57d8b449a987eba298a3fb101cc6f779e8ee6f Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 20 Dec 2016 17:05:42 +0100 Subject: [PATCH 11/11] Refactor shape resize and displacement. --- frontend/src/uxbox/main/data/shapes.cljs | 134 +++++- frontend/src/uxbox/main/geom.cljs | 1 + frontend/src/uxbox/main/ui/shapes/circle.cljs | 53 +-- frontend/src/uxbox/main/ui/shapes/common.cljs | 17 +- frontend/src/uxbox/main/ui/shapes/group.cljs | 20 +- frontend/src/uxbox/main/ui/shapes/icon.cljs | 46 +- frontend/src/uxbox/main/ui/shapes/image.cljs | 31 +- frontend/src/uxbox/main/ui/shapes/path.cljs | 21 +- frontend/src/uxbox/main/ui/shapes/rect.cljs | 28 +- .../src/uxbox/main/ui/shapes/selection.cljs | 401 +++++++++++++----- frontend/src/uxbox/main/ui/shapes/text.cljs | 58 ++- frontend/src/uxbox/util/transit.cljs | 9 +- .../uxbox/view/ui/viewer/interactions.cljs | 4 +- frontend/src/uxbox/view/ui/viewer/shapes.cljs | 6 +- 14 files changed, 577 insertions(+), 252 deletions(-) diff --git a/frontend/src/uxbox/main/data/shapes.cljs b/frontend/src/uxbox/main/data/shapes.cljs index 4c2ae4359b..cd9a0e791f 100644 --- a/frontend/src/uxbox/main/data/shapes.cljs +++ b/frontend/src/uxbox/main/data/shapes.cljs @@ -8,17 +8,18 @@ (:require [beicon.core :as rx] [uxbox.util.uuid :as uuid] [potok.core :as ptk] - [uxbox.util.router :as r] + [uxbox.store :as st] [uxbox.util.forms :as sc] + [uxbox.util.geom.point :as gpt] + [uxbox.util.geom.matrix :as gmt] + [uxbox.util.router :as r] + [uxbox.util.rlocks :as rlocks] [uxbox.util.workers :as uw] [uxbox.main.constants :as c] [uxbox.main.geom :as geom] - [uxbox.store :as st] [uxbox.main.data.core :refer (worker)] [uxbox.main.data.shapes-impl :as impl] - [uxbox.main.data.pages :as udp] - [uxbox.util.rlocks :as rlocks] - [uxbox.util.geom.point :as gpt])) + [uxbox.main.data.pages :as udp])) ;; --- Shapes CRUD @@ -70,18 +71,21 @@ (gpt/point c/canvas-start-x c/canvas-start-y)) +(declare apply-temporal-displacement) + (defn initial-align-shape [id] (reify ptk/WatchEvent (watch [_ state s] - (let [shape (get-in state [:shapes id]) - shape (geom/outer-rect state shape) - point (gpt/point (:x shape) (:y shape)) - point (gpt/add point canvas-coords)] - (->> (align-point point) - (rx/map #(gpt/subtract % point)) - (rx/map #(move-shape id %))))))) + (let [{:keys [x1 y1] :as shape} (->> (get-in state [:shapes id]) + (geom/shape->rect-shape state)) + point1 (gpt/point x1 y1) + point2 (gpt/add point1 canvas-coords)] + (->> (align-point point2) + (rx/map #(gpt/subtract % canvas-coords)) + (rx/map (fn [{:keys [x y] :as pt}] + (apply-temporal-displacement id (gpt/subtract pt point1))))))))) (defn update-line-attrs [sid {:keys [x1 y1 x2 y2] :as opts}] @@ -119,6 +123,92 @@ (update [_ state] (update-in state [:shapes sid] geom/resize-dim opts)))) +;; --- Apply Temporal Displacement + +(deftype ApplyTemporalDisplacement [id delta] + ptk/UpdateEvent + (update [_ state] + (let [current-delta (get-in state [:shapes id :tmp-displacement] (gpt/point 0 0)) + delta (gpt/add current-delta delta)] + (assoc-in state [:shapes id :tmp-displacement] delta)))) + +(defn apply-temporal-displacement + [id pt] + {:pre [(uuid? id) (gpt/point? pt)]} + (ApplyTemporalDisplacement. id pt)) + +;; --- Apply Displacement + +(deftype ApplyDisplacement [id] + ptk/UpdateEvent + (update [_ state] + (let [{:keys [tmp-displacement type] :as shape} (get-in state [:shapes id]) + xfmt (gmt/translate-matrix tmp-displacement)] + + (if (= type :group) + (letfn [(update-item [state id] + (let [{:keys [type items] :as shape} (get-in state [:shapes id])] + (if (= type :group) + (reduce update-item state items) + (update-in state [:shapes id] + (fn [shape] + (as-> (dissoc shape :tmp-displacement) $ + (geom/transform state $ xfmt)))))))] + (-> (reduce update-item state (:items shape)) + (update-in [:shapes id] dissoc :tmp-displacement))) + + (update-in state [:shapes id] (fn [shape] + (as-> (dissoc shape :tmp-displacement) $ + (geom/transform state $ xfmt)))))))) + +(defn apply-displacement + [id] + {:pre [(uuid? id)]} + (ApplyDisplacement. id)) + +;; --- Apply Temporal Resize Matrix + +(deftype ApplyTemporalResizeMatrix [id mx] + ptk/UpdateEvent + (update [_ state] + (assoc-in state [:shapes id :tmp-resize-xform] mx))) + +(defn apply-temporal-resize-matrix + "Attach temporal resize matrix transformation to the shape." + [id mx] + (ApplyTemporalResizeMatrix. id mx)) + +;; --- Apply Resize Matrix + +(declare apply-resize-matrix) + +(deftype ApplyResizeMatrix [id] + ptk/UpdateEvent + (update [_ state] + (let [{:keys [type tmp-resize-xform] + :or {tmp-resize-xform (gmt/matrix)} + :as shape} (get-in state [:shapes id])] + (if (= type :group) + (letfn [(update-item [state id] + (let [{:keys [type items] :as shape} (get-in state [:shapes id])] + (if (= type :group) + (reduce update-item state items) + (update-in state [:shapes id] + (fn [shape] + (as-> (dissoc shape :tmp-resize-xform) $ + (geom/transform state $ tmp-resize-xform)))))))] + (-> (reduce update-item state (:items shape)) + (update-in [:shapes id] dissoc :tmp-resize-xform))) + (update-in state [:shapes id] (fn [shape] + (as-> (dissoc shape :tmp-resize-xform) $ + (geom/transform state $ tmp-resize-xform)))))))) + +(defn apply-resize-matrix + "Apply definitivelly the resize matrix transformation to the shape." + [id] + {:pre [(uuid? id)]} + (ApplyResizeMatrix. id)) + (defn update-vertex-position [id {:keys [vid delta]}] (reify @@ -208,7 +298,6 @@ (when rx {:rx rx}) (when ry {:ry ry}))))) - ;; --- Shape Proportions (defn lock-proportions @@ -378,17 +467,20 @@ id (first (get-in state [:pages page :shapes]))] (assoc-in state [:workspace :selected] #{id}))))) + +(deftype SelectShape [id] + ptk/UpdateEvent + (update [_ state] + (let [selected (get-in state [:workspace :selected]) + state (if (contains? selected id) + (update-in state [:workspace :selected] disj id) + (update-in state [:workspace :selected] conj id))] + (update-in state [:workspace :flags] conj :element-options)))) + (defn select-shape "Mark a shape selected for drawing in the canvas." [id] - (reify - ptk/UpdateEvent - (update [_ state] - (let [selected (get-in state [:workspace :selected]) - state (if (contains? selected id) - (update-in state [:workspace :selected] disj id) - (update-in state [:workspace :selected] conj id))] - (update-in state [:workspace :flags] conj :element-options))))) + (SelectShape. id)) ;; --- Select Shapes diff --git a/frontend/src/uxbox/main/geom.cljs b/frontend/src/uxbox/main/geom.cljs index c764df03e4..ffec054636 100644 --- a/frontend/src/uxbox/main/geom.cljs +++ b/frontend/src/uxbox/main/geom.cljs @@ -555,6 +555,7 @@ (case type :rect (transform-rect shape xfmt) :icon (transform-rect shape xfmt) + :text (transform-rect shape xfmt) :image (transform-rect shape xfmt) :path (transform-path shape xfmt) :circle (transform-circle shape xfmt)))) diff --git a/frontend/src/uxbox/main/ui/shapes/circle.cljs b/frontend/src/uxbox/main/ui/shapes/circle.cljs index 8f334fe16e..7c4e3e7e40 100644 --- a/frontend/src/uxbox/main/ui/shapes/circle.cljs +++ b/frontend/src/uxbox/main/ui/shapes/circle.cljs @@ -5,50 +5,39 @@ ;; Copyright (c) 2016 Andrey Antukh (ns uxbox.main.ui.shapes.circle - (:require [sablono.core :refer-macros [html]] - [rum.core :as rum] - [lentes.core :as l] - [uxbox.util.mixins :as mx :include-macros true] + (:require [lentes.core :as l] [uxbox.main.ui.shapes.common :as common] [uxbox.main.ui.shapes.attrs :as attrs] - [uxbox.main.geom :as geom])) + [uxbox.main.geom :as geom] + [uxbox.util.geom.matrix :as gmt] + [uxbox.util.geom.point :as gpt] + [uxbox.util.mixins :as mx :include-macros true])) ;; --- Circle Component (declare circle-shape) -(defn- circle-component-render - [own shape] +(mx/defc circle-component + {:mixins [mx/reactive mx/static]} + [shape] (let [{:keys [id x y width height group]} shape selected (mx/react common/selected-ref) selected? (contains? selected id) on-mouse-down #(common/on-mouse-down % shape selected)] - (html - [:g.shape {:class (when selected? "selected") - :on-mouse-down on-mouse-down} - (circle-shape shape identity)]))) - -(def circle-component - (mx/component - {:render circle-component-render - :name "circle-component" - :mixins [mx/static mx/reactive]})) + [:g.shape {:class (when selected? "selected") + :on-mouse-down on-mouse-down} + (circle-shape shape identity)])) ;; --- Circle Shape -(defn- circle-shape-render - [own {:keys [id] :as shape}] - (let [key (str "shape-" id) - rfm (geom/transformation-matrix shape) - props (select-keys shape [:cx :cy :rx :ry]) - attrs (-> (attrs/extract-style-attrs shape) - (merge {:id key :key key :transform (str rfm)}) - (merge props))] - (html - [:ellipse attrs]))) +(mx/defc circle-shape + {:mixins [mx/static]} + [{:keys [id tmp-resize-xform tmp-displacement] :as shape}] + (let [xfmt (cond-> (or tmp-resize-xform (gmt/matrix)) + tmp-displacement (gmt/translate tmp-displacement)) -(def circle-shape - (mx/component - {:render circle-shape-render - :name "circle-shape" - :mixins [mx/static]})) + props {:transform (str xfmt) :id (str id)} + attrs (merge props + (attrs/extract-style-attrs shape) + (select-keys shape [:cx :cy :rx :ry]))] + [:ellipse attrs])) diff --git a/frontend/src/uxbox/main/ui/shapes/common.cljs b/frontend/src/uxbox/main/ui/shapes/common.cljs index a84755b0e1..b807c89b90 100644 --- a/frontend/src/uxbox/main/ui/shapes/common.cljs +++ b/frontend/src/uxbox/main/ui/shapes/common.cljs @@ -10,11 +10,12 @@ [beicon.core :as rx] [potok.core :as ptk] [uxbox.store :as st] + [uxbox.main.geom :as geom] [uxbox.main.data.shapes :as uds] [uxbox.main.ui.keyboard :as kbd] [uxbox.main.ui.workspace.base :as wb] + [uxbox.util.geom.point :as gpt] [uxbox.util.rlocks :as rlocks] - [uxbox.main.geom :as geom] [uxbox.util.dom :as dom])) ;; --- Refs @@ -36,13 +37,19 @@ (defn start-move [] - (letfn [(on-start [shape] + (letfn [(on-move [shape delta] + (st/emit! (uds/apply-temporal-displacement shape delta))) + (on-stop [{:keys [id] :as shape}] + (rlocks/release! :shape/move) + (st/emit! (uds/apply-displacement shape))) + (on-start [shape] (let [stoper (->> (rx/map first wb/events-s) (rx/filter #(= % :mouse/up)) (rx/take 1)) - stream (rx/take-until stoper wb/mouse-delta-s) - on-move #(st/emit! (uds/move-shape shape %)) - on-stop #(rlocks/release! :shape/move)] + stream (->> wb/mouse-delta-s + (rx/take-until stoper)) + on-move (partial on-move shape) + on-stop (partial on-stop shape)] (when @wb/alignment-ref (st/emit! (uds/initial-align-shape shape))) (rx/subscribe stream on-move nil on-stop)))] diff --git a/frontend/src/uxbox/main/ui/shapes/group.cljs b/frontend/src/uxbox/main/ui/shapes/group.cljs index 172b02ec06..8c873add78 100644 --- a/frontend/src/uxbox/main/ui/shapes/group.cljs +++ b/frontend/src/uxbox/main/ui/shapes/group.cljs @@ -7,7 +7,7 @@ (ns uxbox.main.ui.shapes.group (:require [lentes.core :as l] [uxbox.store :as st] - [uxbox.util.mixins :as mx :include-macros true] + [uxbox.main.geom :as geom] [uxbox.main.ui.shapes.common :as common] [uxbox.main.ui.shapes.attrs :as attrs] [uxbox.main.ui.shapes.icon :as icon] @@ -16,7 +16,9 @@ [uxbox.main.ui.shapes.text :as text] [uxbox.main.ui.shapes.path :as path] [uxbox.main.ui.shapes.image :as image] - [uxbox.main.geom :as geom])) + [uxbox.util.geom.matrix :as gmt] + [uxbox.util.mixins :as mx :include-macros true])) + ;; --- Helpers @@ -64,12 +66,14 @@ (mx/defc group-shape {:mixins [mx/static mx/reactive]} - [{:keys [items id dx dy rotation] :as shape} factory] - (let [key (str "shape-" id) - rfm (geom/transformation-matrix shape) - attrs (merge {:id key :key key :transform (str rfm)} - (attrs/extract-style-attrs shape) - (attrs/make-debug-attrs shape))] + [{:keys [id items tmp-resize-xform tmp-displacement] :as shape} factory] + (let [xfmt (cond-> (or tmp-resize-xform (gmt/matrix)) + tmp-displacement (gmt/translate tmp-displacement)) + + props {:id (str id) + :transform (str xfmt)} + + attrs (merge props (attrs/extract-style-attrs shape))] [:g attrs (for [item (reverse items) :let [key (str item)]] diff --git a/frontend/src/uxbox/main/ui/shapes/icon.cljs b/frontend/src/uxbox/main/ui/shapes/icon.cljs index 64208eda70..cd161d0e24 100644 --- a/frontend/src/uxbox/main/ui/shapes/icon.cljs +++ b/frontend/src/uxbox/main/ui/shapes/icon.cljs @@ -5,10 +5,11 @@ ;; Copyright (c) 2016 Andrey Antukh (ns uxbox.main.ui.shapes.icon - (:require [uxbox.util.mixins :as mx :include-macros true] - [uxbox.main.ui.shapes.common :as common] + (:require [uxbox.main.ui.shapes.common :as common] [uxbox.main.ui.shapes.attrs :as attrs] - [uxbox.main.geom :as geom])) + [uxbox.main.geom :as geom] + [uxbox.util.mixins :as mx :include-macros true] + [uxbox.util.geom.matrix :as gmt])) ;; --- Icon Component @@ -28,19 +29,30 @@ (mx/defc icon-shape {:mixins [mx/static]} - [{:keys [x1 y1 content id metadata] :as shape} factory] - (let [key (str "shape-" id) - ;; rfm (geom/transformation-matrix shape) + [shape] + (let [{:keys [x1 y1 content id metadata + width height + tmp-resize-xform + tmp-displacement]} (geom/size shape) + + [_ _ orw orh] (:view-box metadata) + scalex (/ width orw) + scaley (/ height orh) + view-box (apply str (interpose " " (:view-box metadata))) - size (geom/size shape) - attrs (merge {:id key :key key ;; :transform (str rfm) - :x x1 :y y1 :view-box view-box - :preserve-aspect-ratio "none" - :dangerouslySetInnerHTML {:__html content}} - size - (attrs/extract-style-attrs shape) - (attrs/make-debug-attrs shape))] - [:svg attrs])) + + xfmt (cond-> (or tmp-resize-xform (gmt/matrix)) + tmp-displacement (gmt/translate tmp-displacement) + true (gmt/translate x1 y1) + true (gmt/scale scalex scaley)) + + props {:id (str id) + :preserve-aspect-ratio "none" + :dangerouslySetInnerHTML {:__html content} + :transform (str xfmt)} + + attrs (merge props (attrs/extract-style-attrs shape))] + [:g attrs])) ;; --- Icon SVG @@ -48,7 +60,7 @@ {:mixins [mx/static]} [{:keys [content id metadata] :as shape}] (let [view-box (apply str (interpose " " (:view-box metadata))) - id (str "icon-svg-" id) - props {:view-box view-box :id id + props {:view-box view-box + :id (str id) :dangerouslySetInnerHTML {:__html content}}] [:svg props])) diff --git a/frontend/src/uxbox/main/ui/shapes/image.cljs b/frontend/src/uxbox/main/ui/shapes/image.cljs index f1c60c3a10..9478d54982 100644 --- a/frontend/src/uxbox/main/ui/shapes/image.cljs +++ b/frontend/src/uxbox/main/ui/shapes/image.cljs @@ -7,14 +7,14 @@ (ns uxbox.main.ui.shapes.image (:require [beicon.core :as rx] [lentes.core :as l] - [uxbox.util.mixins :as mx :include-macros true] - [uxbox.util.http :as http] [potok.core :as ptk] [uxbox.store :as st] [uxbox.main.ui.shapes.common :as common] [uxbox.main.ui.shapes.attrs :as attrs] [uxbox.main.data.images :as udi] - [uxbox.main.geom :as geom])) + [uxbox.main.geom :as geom] + [uxbox.util.mixins :as mx :include-macros true] + [uxbox.util.geom.matrix :as gmt])) ;; --- Refs @@ -51,13 +51,22 @@ (mx/defc image-shape {:mixins [mx/static]} - [{:keys [id x1 y1 image] :as shape}] - (let [key (str "shape-" id) - ;; rfm (geom/transformation-matrix shape) - size (geom/size shape) - props {:x x1 :y y1 :id key :key key + [shape] + (let [{:keys [id x1 y1 image + width height + tmp-resize-xform + tmp-displacement]} (geom/size shape) + + xfmt (cond-> (or tmp-resize-xform (gmt/matrix)) + tmp-displacement (gmt/translate tmp-displacement)) + + props {:x x1 :y y1 + :id (str id) :preserve-aspect-ratio "none" - :xlink-href (:url image)} - attrs (-> (attrs/extract-style-attrs shape) - (merge props size))] + :xlink-href (:url image) + :transform (str xfmt) + :width width + :height height} + + attrs (merge props (attrs/extract-style-attrs shape))] [:image attrs])) diff --git a/frontend/src/uxbox/main/ui/shapes/path.cljs b/frontend/src/uxbox/main/ui/shapes/path.cljs index 91ca3cfcdf..4143c4b89d 100644 --- a/frontend/src/uxbox/main/ui/shapes/path.cljs +++ b/frontend/src/uxbox/main/ui/shapes/path.cljs @@ -5,13 +5,14 @@ ;; Copyright (c) 2016 Andrey Antukh (ns uxbox.main.ui.shapes.path - (:require [uxbox.util.mixins :as mx :include-macros true] - [potok.core :as ptk] + (:require [potok.core :as ptk] [uxbox.store :as st] [uxbox.main.ui.shapes.common :as common] [uxbox.main.ui.shapes.attrs :as attrs] [uxbox.main.data.shapes :as uds] - [uxbox.main.geom :as geom])) + [uxbox.main.geom :as geom] + [uxbox.util.geom.matrix :as gmt] + [uxbox.util.mixins :as mx :include-macros true])) ;; --- Path Component @@ -45,11 +46,11 @@ (mx/defc path-shape {:mixins [mx/static]} - [{:keys [id drawing?] :as shape}] - (let [key (str "shape-" id) - rfm (geom/transformation-matrix shape) - attrs (-> (attrs/extract-style-attrs shape) - (merge {:id key :key key :d (render-path shape)}) - (merge (when-not drawing? - #_{:transform (str rfm)})))] + [{:keys [id tmp-resize-xform tmp-displacement] :as shape}] + (let [xfmt (cond-> (or tmp-resize-xform (gmt/matrix)) + tmp-displacement (gmt/translate tmp-displacement)) + props {:transform (str xfmt) + :id (str id) + :d (render-path shape)} + attrs (merge props (attrs/extract-style-attrs shape))] [:path attrs])) diff --git a/frontend/src/uxbox/main/ui/shapes/rect.cljs b/frontend/src/uxbox/main/ui/shapes/rect.cljs index 2ce55e0ef8..598d85ced9 100644 --- a/frontend/src/uxbox/main/ui/shapes/rect.cljs +++ b/frontend/src/uxbox/main/ui/shapes/rect.cljs @@ -7,8 +7,10 @@ (ns uxbox.main.ui.shapes.rect (:require [uxbox.main.ui.shapes.common :as common] [uxbox.main.ui.shapes.attrs :as attrs] - [uxbox.util.mixins :as mx :include-macros true] [uxbox.main.geom :as geom] + [uxbox.util.geom.matrix :as gmt] + [uxbox.util.geom.point :as gpt] + [uxbox.util.mixins :as mx :include-macros true] [uxbox.util.dom :as dom])) ;; --- Rect Component @@ -23,18 +25,26 @@ selected? (contains? selected id) on-mouse-down #(common/on-mouse-down % shape selected)] [:g.shape {:class (when selected? "selected") - :on-mouse-down on-mouse-down} + :on-mouse-down on-mouse-down + } (rect-shape shape identity)])) ;; --- Rect Shape (mx/defc rect-shape {:mixins [mx/static]} - [{:keys [id x1 y1] :as shape}] - (let [key (str "shape-" id) - rfm (geom/transformation-matrix shape) - size (geom/size shape) - props {:x x1 :y y1 :id key :key key :transform (str rfm)} - attrs (-> (attrs/extract-style-attrs shape) - (merge props size))] + [shape] + (let [{:keys [id x1 y1 width height + tmp-resize-xform + tmp-displacement]} (geom/size shape) + + xfmt (cond-> (or tmp-resize-xform (gmt/matrix)) + tmp-displacement (gmt/translate tmp-displacement)) + + props {:x x1 :y y1 :id id + :width width + :height height + :transform (str xfmt)} + + attrs (merge (attrs/extract-style-attrs shape) props)] [:rect attrs])) diff --git a/frontend/src/uxbox/main/ui/shapes/selection.cljs b/frontend/src/uxbox/main/ui/shapes/selection.cljs index e4035ab1bf..cd4d5b7232 100644 --- a/frontend/src/uxbox/main/ui/shapes/selection.cljs +++ b/frontend/src/uxbox/main/ui/shapes/selection.cljs @@ -9,14 +9,16 @@ "Multiple selection handlers component." (:require [lentes.core :as l] [beicon.core :as rx] - [uxbox.store :as st] - [uxbox.util.mixins :as mx :include-macros true] [potok.core :as ptk] + [uxbox.store :as st] + [uxbox.main.constants :as c] [uxbox.main.data.shapes :as uds] [uxbox.main.ui.workspace.base :as wb] - [uxbox.util.rlocks :as rlocks] [uxbox.main.ui.shapes.common :as scommon] [uxbox.main.geom :as geom] + [uxbox.util.mixins :as mx :include-macros true] + [uxbox.util.rlocks :as rlocks] + [uxbox.util.geom.matrix :as gmt] [uxbox.util.geom.point :as gpt] [uxbox.util.dom :as dom])) @@ -41,115 +43,257 @@ (def edition-ref scommon/edition-ref) +(defn transform-rect + [{:keys [x1 y1 x2 y2] :as shape} xfmt] + (if xfmt + (let [tl (gpt/transform [x1 y1] xfmt) + tr (gpt/transform [x2 y1] xfmt) + bl (gpt/transform [x1 y2] xfmt) + br (gpt/transform [x2 y2] xfmt) + minx (apply min (map :x [tl tr bl br])) + maxx (apply max (map :x [tl tr bl br])) + miny (apply min (map :y [tl tr bl br])) + maxy (apply max (map :y [tl tr bl br]))] + (assoc shape + :x1 minx + :y1 miny + :x2 maxx + :y2 maxy)) + shape)) + ;; --- Resize Implementation (defn- start-resize - [vid sid] - (letfn [(on-resize [[delta ctrl?]] - (let [params {:vid vid :delta (assoc delta :lock ctrl?)}] - (st/emit! (uds/update-vertex-position sid params)))) + [vid ids shape] + (letfn [(gen-matrix [shape {scalex :x scaley :y}] + (case vid + :top-left + (-> (gmt/matrix) + (gmt/translate (+ (:x2 shape)) + (+ (:y2 shape))) + (gmt/scale scalex scaley) + (gmt/translate (- (:x2 shape)) + (- (:y2 shape)))) + + :top-right + (-> (gmt/matrix) + (gmt/translate (+ (:x1 shape)) + (+ (:y2 shape))) + (gmt/scale scalex scaley) + (gmt/translate (- (:x1 shape)) + (- (:y2 shape)))) + + :top + (-> (gmt/matrix) + (gmt/translate (+ (:x1 shape)) + (+ (:y2 shape))) + (gmt/scale scalex scaley) + (gmt/translate (- (:x1 shape)) + (- (:y2 shape)))) + + :bottom-left + (-> (gmt/matrix) + (gmt/translate (+ (:x2 shape)) + (+ (:y1 shape))) + (gmt/scale scalex scaley) + (gmt/translate (- (:x2 shape)) + (- (:y1 shape)))) + + :bottom-right + (-> (gmt/matrix) + (gmt/translate (+ (:x1 shape)) + (+ (:y1 shape))) + (gmt/scale scalex scaley) + (gmt/translate (- (:x1 shape)) + (- (:y1 shape)))) + + :bottom + (-> (gmt/matrix) + (gmt/translate (+ (:x1 shape)) + (+ (:y1 shape))) + (gmt/scale scalex scaley) + (gmt/translate (- (:x1 shape)) + (- (:y1 shape)))) + + :right + (-> (gmt/matrix) + (gmt/translate (+ (:x1 shape)) + (+ (:y1 shape))) + (gmt/scale scalex scaley) + (gmt/translate (- (:x1 shape)) + (- (:y1 shape)))) + + :left + (-> (gmt/matrix) + (gmt/translate (+ (:x2 shape)) + (+ (:y1 shape))) + (gmt/scale scalex scaley) + (gmt/translate (- (:x2 shape)) + (- (:y1 shape)))) + )) + + (on-resize [shape scale] + (let [mt (gen-matrix shape scale) + xf (map #(uds/apply-temporal-resize-matrix % mt))] + (apply st/emit! (sequence xf ids)))) + (on-end [] - (rlocks/release! :shape/resize))] + (apply st/emit! (map uds/apply-resize-matrix ids)) + (rlocks/release! :shape/resize)) + (calculate-ratio [orig-shape {:keys [width height] :as shape}] + {:x (/ width (:width orig-shape)) + :y (/ height (:height orig-shape))}) + (apply-delta [shape [{:keys [x y] :as point} ctrl?]] + (case vid + :top-left + (let [width (- (:x2 shape) x) + height (- (:y2 shape) y) + proportion (:proportion shape)] + (assoc shape + :width width + :height (if ctrl? (/ width proportion) height))) + + :top-right + (let [width (- x (:x1 shape)) + height (- (:y2 shape) y) + proportion (:proportion shape)] + (assoc shape + :width width + :height (if ctrl? (/ width proportion) height))) + + :top + (let [width (- (:x2 shape) (:x1 shape)) + height (- (:y2 shape) y) + proportion (:proportion shape)] + (assoc shape + :width width + :height (if ctrl? (/ width proportion) height))) + + :bottom-left + (let [width (- (:x2 shape) x) + height (- y (:y1 shape)) + proportion (:proportion shape)] + (assoc shape + :width width + :height (if ctrl? (/ width proportion) height))) + + :bottom-right + (let [width (- x (:x1 shape)) + height (- y (:y1 shape)) + proportion (:proportion shape)] + (assoc shape + :width width + :height (if ctrl? (/ width proportion) height))) + + :bottom + (let [width (- (:x2 shape) (:x1 shape)) + height (- y (:y1 shape)) + proportion (:proportion shape)] + (assoc shape + :width width + :height (if ctrl? (/ width proportion) height))) + + :left + (let [width (- (:x2 shape) x) + height (- (:y2 shape) (:y1 shape)) + proportion (:proportion shape)] + (assoc shape + :width width + :height (if ctrl? (/ width proportion) height))) + + :right + (let [width (- x (:x1 shape)) + height (- (:y2 shape) (:y1 shape)) + proportion (:proportion shape)] + (assoc shape + :width width + :height (if ctrl? (/ width proportion) height))) + + ))] + (let [stoper (->> wb/events-s (rx/map first) (rx/filter #(= % :mouse/up)) (rx/take 1)) - stream (->> wb/mouse-delta-s + stream (->> wb/mouse-canvas-s + (rx/map #(gpt/divide % @wb/zoom-ref)) + (rx/mapcat (fn [point] + (if @wb/alignment-ref + (uds/align-point point) + (rx/of point)))) (rx/take-until stoper) - (rx/with-latest-from vector wb/mouse-ctrl-s))] + (rx/with-latest-from vector wb/mouse-ctrl-s) + (rx/scan apply-delta shape) + (rx/map (partial calculate-ratio shape)))] (rlocks/acquire! :shape/resize) - (when @wb/alignment-ref - (st/emit! (uds/initial-vertext-align sid vid))) - (rx/subscribe stream on-resize nil on-end)))) + (rx/subscribe stream + (partial on-resize shape) + nil + on-end)))) + +;; --- Controls (Component) + +(mx/defc controls + {:mixins [mx/static]} + [{:keys [width height x1 y1]} zoom on-mouse-down] + [:g.controls + [:rect.main {:x x1 :y y1 + :width width + :height height + :stroke-dasharray (str (/ 5.0 zoom) "," (/ 5 zoom)) + :style {:stroke "#333" :fill "transparent" + :stroke-opacity "1"}}] + [:circle.top + (merge +circle-props+ + {:on-mouse-down #(on-mouse-down :top %) + :r (/ 6.0 zoom) + :cx (+ x1 (/ width 2)) + :cy (- y1 2)})] + [:circle.right + (merge +circle-props+ + {:on-mouse-down #(on-mouse-down :right %) + :r (/ 6.0 zoom) + :cy (+ y1 (/ height 2)) + :cx (+ x1 width 1)})] + [:circle.bottom + (merge +circle-props+ + {:on-mouse-down #(on-mouse-down :bottom %) + :r (/ 6.0 zoom) + :cx (+ x1 (/ width 2)) + :cy (+ y1 height 2)})] + [:circle.left + (merge +circle-props+ + {:on-mouse-down #(on-mouse-down :left %) + :r (/ 6.0 zoom) + :cy (+ y1 (/ height 2)) + :cx (- x1 3)})] + [:circle.top-left + (merge +circle-props+ + {:on-mouse-down #(on-mouse-down :top-left %) + :r (/ 6.0 zoom) + :cx x1 + :cy y1})] + [:circle.top-right + (merge +circle-props+ + {:on-mouse-down #(on-mouse-down :top-right %) + :r (/ 6.0 zoom) + :cx (+ x1 width) + :cy y1})] + [:circle.bottom-left + (merge +circle-props+ + {:on-mouse-down #(on-mouse-down :bottom-left %) + :r (/ 6.0 zoom) + :cx x1 + :cy (+ y1 height)})] + [:circle.bottom-right + (merge +circle-props+ + {:on-mouse-down #(on-mouse-down :bottom-right %) + :r (/ 6.0 zoom) + :cx (+ x1 width) + :cy (+ y1 height)})]]) ;; --- Selection Handlers (Component) -(mx/defc multiple-selection-handlers - [shapes] - (let [{:keys [width height x y]} (geom/outer-rect-coll shapes)] - [:g.controls - [:rect.main {:x x :y y - :width width - :height height - :stroke-dasharray "5,5" - :style {:stroke "#333" :fill "transparent" - :stroke-opacity "1"}}]])) - -(mx/defc single-not-editable-selection-handlers - [{:keys [id] :as shape} zoom] - (let [{:keys [width height x y]} (geom/outer-rect shape)] - [:g.controls - [:rect.main {:x x :y y - :width width - :height height - :stroke-dasharray (str (/ 5.0 zoom) "," (/ 5.0 zoom)) - :style {:stroke "#333" - :fill "transparent" - :stroke-opacity "1"}}]])) - -(mx/defc single-selection-handlers - [{:keys [id] :as shape} zoom] - (letfn [(on-mouse-down [vid event] - (dom/stop-propagation event) - (start-resize vid id))] - (let [{:keys [x y width height]} (geom/outer-rect shape)] - [:g.controls - [:rect.main {:x x :y y - :width width - :height height - :stroke-dasharray (str (/ 5.0 zoom) "," (/ 5.0 zoom)) - :style {:stroke "#333" - :fill "transparent" - :stroke-opacity "1"}}] - [:circle.top - (merge +circle-props+ - {:on-mouse-down #(on-mouse-down :top %) - :r (/ 6.0 zoom) - :cx (+ x (/ width 2)) - :cy (- y 2)})] - [:circle.right - (merge +circle-props+ - {:on-mouse-down #(on-mouse-down :right %) - :r (/ 6.0 zoom) - :cy (+ y (/ height 2)) - :cx (+ x width 1)})] - [:circle.bottom - (merge +circle-props+ - {:on-mouse-down #(on-mouse-down :bottom %) - :r (/ 6.0 zoom) - :cx (+ x (/ width 2)) - :cy (+ y height 2)})] - [:circle.left - (merge +circle-props+ - {:on-mouse-down #(on-mouse-down :left %) - :r (/ 6.0 zoom) - :cy (+ y (/ height 2)) - :cx (- x 3)})] - [:circle.top-left - (merge +circle-props+ - {:on-mouse-down #(on-mouse-down :top-left %) - :r (/ 6.0 zoom) - :cx x - :cy y})] - [:circle.top-right - (merge +circle-props+ - {:on-mouse-down #(on-mouse-down :top-right %) - :r (/ 6.0 zoom) - :cx (+ x width) - :cy y})] - [:circle.bottom-left - (merge +circle-props+ - {:on-mouse-down #(on-mouse-down :bottom-left %) - :r (/ 6.0 zoom) - :cx x - :cy (+ y height)})] - [:circle.bottom-right - (merge +circle-props+ - {:on-mouse-down #(on-mouse-down :bottom-right %) - :r (/ 6.0 zoom) - :cx (+ x width) - :cy (+ y height)})]]))) - (defn start-path-edition [shape-id index] (letfn [(on-move [delta] @@ -181,6 +325,43 @@ :stroke "#28c4d4" :style {:cursor "pointer"}}])])) +(mx/defc multiple-selection-handlers + {:mixins [mx/static]} + [[shape & rest :as shapes] zoom] + (let [resize-xf (:tmp-resize-xform shape (gmt/matrix)) + displc-xf (-> (:tmp-displacement shape (gpt/point 0 0)) + (gmt/translate-matrix)) + selection (-> (geom/shapes->rect-shape shapes) + (assoc :type :rect) + (geom/transform resize-xf) + (geom/transform displc-xf) + (geom/size)) + on-click #(do (dom/stop-propagation %2) + (start-resize %1 (map :id shapes) selection))] + ;; (println "single-selection-handlers" displc-xf) + ;; (println "single-selection-handlers" (select-keys selection [:x1 :y1 :x2 :y2])) + ;; (println "single-selection-handlers" (select-keys selection [:x1 :y1 :width :height])) + (controls selection zoom on-click))) + +(mx/defc single-selection-handlers + {:mixins [mx/static]} + [{:keys [id] :as shape} zoom] + (let [resize-xf (:tmp-resize-xform shape (gmt/matrix)) + displc-xf (-> (:tmp-displacement shape (gpt/point 0 0)) + (gmt/translate-matrix)) + selection (-> (geom/shape->rect-shape shape) + ;; (transform-rect resize-xf) + (assoc :type :rect) + (geom/transform resize-xf) + (geom/transform displc-xf) + (geom/size)) + on-click #(do (dom/stop-propagation %2) + (start-resize %1 #{id} selection))] + ;; (println "single-selection-handlers" displc-xf) + ;; (println "single-selection-handlers" (select-keys selection [:x1 :y1 :x2 :y2])) + ;; (println "single-selection-handlers" (select-keys selection [:x1 :y1 :width :height])) + (controls selection zoom on-click))) + (mx/defc selection-handlers {:mixins [mx/reactive mx/static]} [] @@ -196,20 +377,10 @@ (> shapes-num 1) (multiple-selection-handlers shapes zoom) + (= :path (:type shape)) + (if (= @edition-ref (:id shape)) + (path-edition-selection-handlers shape zoom) + (single-selection-handlers shape zoom)) + :else - (cond - (= :path (:type shape)) - (if (= @edition-ref (:id shape)) - (path-edition-selection-handlers shape zoom) - (single-not-editable-selection-handlers shape zoom)) - - (= :text (:type shape)) - (if (= @edition-ref (:id shape)) - (single-not-editable-selection-handlers shape zoom) - (single-selection-handlers (first shapes) zoom)) - - (= :group (:type shape)) - (single-not-editable-selection-handlers shape zoom) - - :else - (single-selection-handlers (first shapes) zoom))))) + (single-selection-handlers shape zoom)))) diff --git a/frontend/src/uxbox/main/ui/shapes/text.cljs b/frontend/src/uxbox/main/ui/shapes/text.cljs index 8acd4e75d2..584e5df060 100644 --- a/frontend/src/uxbox/main/ui/shapes/text.cljs +++ b/frontend/src/uxbox/main/ui/shapes/text.cljs @@ -9,15 +9,16 @@ [lentes.core :as l] [goog.events :as events] [potok.core :as ptk] - [uxbox.util.mixins :as mx :include-macros true] - [uxbox.util.color :as color] - [uxbox.util.dom :as dom] [uxbox.store :as st] + [uxbox.main.geom :as geom] [uxbox.main.data.shapes :as uds] [uxbox.main.ui.shapes.common :as common] [uxbox.main.ui.shapes.attrs :as attrs] + [uxbox.util.color :as color] + [uxbox.util.dom :as dom] + [uxbox.util.geom.matrix :as gmt] [uxbox.util.rlocks :as rlocks] - [uxbox.main.geom :as geom]) + [uxbox.util.mixins :as mx :include-macros true]) (:import goog.events.EventType)) ;; --- Events @@ -106,8 +107,8 @@ [{:keys [id x1 y1 content] :as shape}] (let [size (geom/size shape) style (make-style shape) - rfm (geom/transformation-matrix shape) - props {:x x1 :y y1 :transform (str rfm)} + ;; rfm (geom/transformation-matrix shape) + props {:x x1 :y y1} ;; :transform (str rfm)} props (merge props size)] (letfn [#_(on-blur [ev] (rlocks/release! :ui/text-edit) @@ -126,15 +127,38 @@ ;; --- Text Shape +;; NOTE: this is a hack for the browser rendering. +;; +;; Without forcing rerender, when the shape is displaced +;; and only x and y attrs are updated in dom, the whole content +;; of the foreignObject becomes sometimes partially or +;; completelly invisible. The complete dom rerender fixes that +;; problem. + +(defn- text-shape-did-update + [own] + (let [pref (mx/ref-node own "fo") + html (.-innerHTML pref)] + (set! (.-innerHTML pref) html) + own)) + (mx/defc text-shape - {:mixins [mx/static]} - [{:keys [id x1 y1 content] :as shape}] - (let [key (str "shape-" id) - rfm (geom/transformation-matrix shape) - size (geom/size shape) - props {:x x1 :y y1 - :transform (str rfm)} - attrs (merge props size) - style (make-style shape)] - [:foreignObject attrs - [:p {:style style} content]])) + {:mixins [mx/static] + :did-update text-shape-did-update} + [{:keys [tmp-resize-xform] :as shape}] + (let [shape (cond-> (geom/size shape) + tmp-resize-xform (geom/transform shape tmp-resize-xform)) + + {:keys [id x1 y1 content + width height + tmp-displacement]} (geom/size shape) + + xfmt (cond-> (gmt/matrix) + tmp-displacement (gmt/translate tmp-displacement)) + + style (make-style shape) + props {:x x1 :y y1 :id (str id) :ref "fo" + :width width :height height + :transform (str xfmt)}] + [:foreignObject props + [:p {:ref "p" :style style} content]])) diff --git a/frontend/src/uxbox/util/transit.cljs b/frontend/src/uxbox/util/transit.cljs index 534c97f4dc..47d2fb752b 100644 --- a/frontend/src/uxbox/util/transit.cljs +++ b/frontend/src/uxbox/util/transit.cljs @@ -65,5 +65,10 @@ (defn encode [data] - (let [w (t/writer :json {:handlers +write-handlers+})] - (t/write w data))) + (try + (let [w (t/writer :json {:handlers +write-handlers+})] + (t/write w data)) + (catch :default e + (println "data:" data) + (throw e)))) + diff --git a/frontend/src/uxbox/view/ui/viewer/interactions.cljs b/frontend/src/uxbox/view/ui/viewer/interactions.cljs index 2bddaa1bf3..2cfa213f75 100644 --- a/frontend/src/uxbox/view/ui/viewer/interactions.cljs +++ b/frontend/src/uxbox/view/ui/viewer/interactions.cljs @@ -116,7 +116,7 @@ [{:keys [x1 y1 rotation] :as shape} {:keys [resize-width resize-height easing element delay duration direction] :as opts}] - (if (= direction :reverse) + #_(if (= direction :reverse) (let [end (geom/transformation-matrix shape)] (animate :targets [(str "#shape-" element)] :transform (str end) @@ -165,7 +165,7 @@ (defn- run-rotate-interaction [{:keys [element rotation direction easing delay duration] :as opts}] - (let [shape (get-in @st/state [:shapes element]) + #_(let [shape (get-in @st/state [:shapes element]) dom (dom/get-element (str "shape-" element)) mtx1 (geom/transformation-matrix (update shape :rotation + rotation)) mtx2 (geom/transformation-matrix shape)] diff --git a/frontend/src/uxbox/view/ui/viewer/shapes.cljs b/frontend/src/uxbox/view/ui/viewer/shapes.cljs index 8f76d4e731..7623f651d6 100644 --- a/frontend/src/uxbox/view/ui/viewer/shapes.cljs +++ b/frontend/src/uxbox/view/ui/viewer/shapes.cljs @@ -52,15 +52,15 @@ {:pre [(map? shape)]} (let [show-itx? (and (mx/react itx-flag-ref) (not (empty? (:interactions shape)))) - rect (geom/inner-rect shape)] + rect (geom/shape->rect-shape shape)] [:g {:id (str "itx-" (:id shape)) :style (when show-itx? {:cursor "pointer"})} (factory shape) (when show-itx? [:circle {:fill "#78dbbe" - :cx (:x rect) - :cy (:y rect) + :cx (:x1 rect) + :cy (:y1 rect) :r 5}])])) ;; --- Shapes