0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-09 00:28:20 -05:00

Improved resize/rotation handlers for shapes with tiny height/width

This commit is contained in:
alonso.torres 2022-03-09 12:55:21 +01:00
parent f4be3aa9de
commit 9332d6f36c
5 changed files with 69 additions and 56 deletions

View file

@ -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]))

View file

@ -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]

View file

@ -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)

View file

@ -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)))

View file

@ -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