From 9332d6f36c4d82df036988e79dd18f75895c3baf Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 9 Mar 2022 12:55:21 +0100 Subject: [PATCH] :sparkles: Improved resize/rotation handlers for shapes with tiny height/width --- common/src/app/common/geom/shapes/bool.cljc | 1 - .../main/data/workspace/drawing/common.cljs | 2 +- .../main/ui/workspace/viewport/selection.cljs | 111 ++++++++++-------- frontend/src/app/util/geom/snap_points.cljs | 4 +- frontend/src/debug.cljs | 7 +- 5 files changed, 69 insertions(+), 56 deletions(-) diff --git a/common/src/app/common/geom/shapes/bool.cljc b/common/src/app/common/geom/shapes/bool.cljc index c4646838c..a71fc52c9 100644 --- a/common/src/app/common/geom/shapes/bool.cljc +++ b/common/src/app/common/geom/shapes/bool.cljc @@ -8,7 +8,6 @@ (:require [app.common.data :as d] [app.common.geom.shapes.path :as gsp] - [app.common.geom.shapes.rect :as gpr] [app.common.geom.shapes.transforms :as gtr] [app.common.path.bool :as pb] [app.common.path.shapes-to-path :as stp])) diff --git a/frontend/src/app/main/data/workspace/drawing/common.cljs b/frontend/src/app/main/data/workspace/drawing/common.cljs index 6dc28ac72..047f1c0ff 100644 --- a/frontend/src/app/main/data/workspace/drawing/common.cljs +++ b/frontend/src/app/main/data/workspace/drawing/common.cljs @@ -6,10 +6,10 @@ (ns app.main.data.workspace.drawing.common (:require - [app.common.pages :as cp] [app.common.geom.matrix :as gmt] [app.common.geom.shapes :as gsh] [app.common.math :as mth] + [app.common.pages :as cp] [app.main.data.workspace.common :as dwc] [app.main.data.workspace.undo :as dwu] [app.main.worker :as uw] diff --git a/frontend/src/app/main/ui/workspace/viewport/selection.cljs b/frontend/src/app/main/ui/workspace/viewport/selection.cljs index 814bf4983..df5332ba7 100644 --- a/frontend/src/app/main/ui/workspace/viewport/selection.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/selection.cljs @@ -51,18 +51,21 @@ :fill "none"}}]))) (defn- handlers-for-selection [{:keys [x y width height]} {:keys [type]} zoom] - (let [zoom-width (* width zoom) - zoom-height (* height zoom) + (let [threshold-small (/ 25 zoom) + threshold-tiny (/ 10 zoom) - align (when (or (<= zoom-width small-selrect-side) - (<= zoom-height small-selrect-side)) - :outside) - show-resize-point? (or (not= type :path) - (and - (> zoom-width min-selrect-side) - (> zoom-height min-selrect-side))) - min-side-top? (or (not= type :path) (> zoom-height min-selrect-side)) - min-side-side? (or (not= type :path) (> zoom-width min-selrect-side))] + small-width? (<= width threshold-small) + tiny-width? (<= width threshold-tiny) + + small-height? (<= height threshold-small) + tiny-height? (<= height threshold-tiny) + + vertical-line? (and (= type :path) tiny-width?) + horizontal-line? (and (= type :path) tiny-height?) + + align (if (or small-width? small-height?) + :outside + :inside)] (->> [ ;; TOP-LEFT {:type :rotation @@ -81,42 +84,66 @@ :position :bottom-left :props {:cx x :cy (+ y height)}} - (when min-side-top? - {:type :resize-side - :position :top - :props {:x x :y y :length width :angle 0 :align align}}) + (when-not horizontal-line? + (let [x (if small-width? (+ x (/ (- width threshold-small) 2)) x) + length (if small-width? threshold-small width)] + {:type :resize-side + :position :top + :props {:x x + :y y + :length length + :angle 0 + :align align}})) - (when min-side-side? - {:type :resize-side - :position :right - :props {:x (+ x width) :y y :length height :angle 90 :align align}}) + (when-not horizontal-line? + (let [x (if small-width? (+ x (/ (+ width threshold-small) 2)) (+ x width)) + length (if small-width? threshold-small width)] + {:type :resize-side + :position :bottom + :props {:x x + :y (+ y height) + :length length + :angle 180 + :align align}})) - (when min-side-top? - {:type :resize-side - :position :bottom - :props {:x (+ x width) :y (+ y height) :length width :angle 180 :align align}}) + (when-not vertical-line? + (let [y (if small-height? (+ y (/ (- height threshold-small) 2)) y) + length (if small-height? threshold-small height)] + {:type :resize-side + :position :right + :props {:x (+ x width) + :y y + :length length + :angle 90 + :align align}})) - (when min-side-side? - {:type :resize-side - :position :left - :props {:x x :y (+ y height) :length height :angle 270 :align align}}) + (when-not vertical-line? + (let [y (if small-height? (+ y (/ (+ height threshold-small) 2)) (+ y height)) + length (if small-height? threshold-small height)] + {:type :resize-side + :position :left + :props {:x x + :y y + :length length + :angle 270 + :align align}})) - (when show-resize-point? + (when (and (not tiny-width?) (not tiny-height?)) {:type :resize-point :position :top-left :props {:cx x :cy y :align align}}) - (when show-resize-point? + (when (and (not tiny-width?) (not tiny-height?)) {:type :resize-point :position :top-right :props {:cx (+ x width) :cy y :align align}}) - (when show-resize-point? + (when (and (not tiny-width?) (not tiny-height?)) {:type :resize-point :position :bottom-right :props {:cx (+ x width) :cy (+ y height) :align align}}) - (when show-resize-point? + (when (and (not tiny-width?) (not tiny-height?)) {:type :resize-point :position :bottom-left :props {:cx x :cy (+ y height) :align align}})] @@ -137,8 +164,7 @@ :y y :width size :height size - :fill (if (debug? :rotation-handler) "blue" "none") - :stroke (if (debug? :rotation-handler) "blue" "none") + :fill (if (debug? :handlers) "blue" "none") :stroke-width 0 :transform transform :on-mouse-down on-rotate}])) @@ -171,8 +197,7 @@ :width resize-point-circle-radius :height resize-point-circle-radius :transform (when rotation (str/fmt "rotate(%s, %s, %s)" rotation cx' cy')) - :style {:fill (if (debug? :resize-handler) "red" "none") - :stroke (if (debug? :resize-handler) "red" "none") + :style {:fill (if (debug? :handlers) "red" "none") :stroke-width 0 :cursor cursor} :on-mouse-down #(on-resize {:x cx' :y cy'} %)}]) @@ -181,8 +206,7 @@ :r (/ resize-point-circle-radius zoom) :cx cx' :cy cy' - :style {:fill (if (debug? :resize-handler) "red" "none") - :stroke (if (debug? :resize-handler) "red" "none") + :style {:fill (if (debug? :handlers) "red" "none") :stroke-width 0 :cursor cursor}}])])) @@ -192,25 +216,18 @@ (let [res-point (if (#{:top :bottom} position) {:y y} {:x x}) - target-length (max 0 (- length (/ (* resize-point-rect-size 2) zoom))) - width (if (< target-length 6) length target-length) height (/ resize-side-height zoom) - - offset-x (/ (- length width) 2) offset-y (if (= align :outside) (- height) (- (/ height 2))) - - target-x (+ x offset-x) target-y (+ y offset-y)] - [:rect {:x target-x + [:rect {:x x :y target-y - :width width + :width length :height height :transform (gmt/multiply transform (gmt/rotate-matrix angle (gpt/point x y))) :on-mouse-down #(on-resize res-point %) - :style {:fill (if (debug? :resize-handler) "yellow" "none") - :stroke (if (debug? :resize-handler) "yellow" "none") + :style {:fill (if (debug? :handlers) "yellow" "none") :stroke-width 0 :cursor (if (#{:left :right} position) (cur/resize-ew rotation) diff --git a/frontend/src/app/util/geom/snap_points.cljs b/frontend/src/app/util/geom/snap_points.cljs index 8fccf5bf3..9e8981a44 100644 --- a/frontend/src/app/util/geom/snap_points.cljs +++ b/frontend/src/app/util/geom/snap_points.cljs @@ -9,13 +9,13 @@ [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh])) -(defn- selrect-snap-points [{:keys [x y width height]}] +(defn selrect-snap-points [{:keys [x y width height]}] #{(gpt/point x y) (gpt/point (+ x width) y) (gpt/point (+ x width) (+ y height)) (gpt/point x (+ y height))}) -(defn- frame-snap-points [{:keys [x y width height] :as selrect}] +(defn frame-snap-points [{:keys [x y width height] :as selrect}] (into (selrect-snap-points selrect) #{(gpt/point (+ x (/ width 2)) y) (gpt/point (+ x width) (+ y (/ height 2))) diff --git a/frontend/src/debug.cljs b/frontend/src/debug.cljs index a7153c69c..881971a9f 100644 --- a/frontend/src/debug.cljs +++ b/frontend/src/debug.cljs @@ -31,11 +31,8 @@ ;; Displays in the console log the events through the application :events - ;; Display the boxes that represent the rotation handlers - :rotation-handler - - ;; Display the boxes that represent the resize handlers - :resize-handler + ;; Display the boxes that represent the rotation and resize handlers + :handlers ;; Displays the center of a selection :selection-center