0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-15 03:28:25 -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 (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.geom.shapes.path :as gsp] [app.common.geom.shapes.path :as gsp]
[app.common.geom.shapes.rect :as gpr]
[app.common.geom.shapes.transforms :as gtr] [app.common.geom.shapes.transforms :as gtr]
[app.common.path.bool :as pb] [app.common.path.bool :as pb]
[app.common.path.shapes-to-path :as stp])) [app.common.path.shapes-to-path :as stp]))

View file

@ -6,10 +6,10 @@
(ns app.main.data.workspace.drawing.common (ns app.main.data.workspace.drawing.common
(:require (:require
[app.common.pages :as cp]
[app.common.geom.matrix :as gmt] [app.common.geom.matrix :as gmt]
[app.common.geom.shapes :as gsh] [app.common.geom.shapes :as gsh]
[app.common.math :as mth] [app.common.math :as mth]
[app.common.pages :as cp]
[app.main.data.workspace.common :as dwc] [app.main.data.workspace.common :as dwc]
[app.main.data.workspace.undo :as dwu] [app.main.data.workspace.undo :as dwu]
[app.main.worker :as uw] [app.main.worker :as uw]

View file

@ -51,18 +51,21 @@
:fill "none"}}]))) :fill "none"}}])))
(defn- handlers-for-selection [{:keys [x y width height]} {:keys [type]} zoom] (defn- handlers-for-selection [{:keys [x y width height]} {:keys [type]} zoom]
(let [zoom-width (* width zoom) (let [threshold-small (/ 25 zoom)
zoom-height (* height zoom) threshold-tiny (/ 10 zoom)
align (when (or (<= zoom-width small-selrect-side) small-width? (<= width threshold-small)
(<= zoom-height small-selrect-side)) tiny-width? (<= width threshold-tiny)
:outside)
show-resize-point? (or (not= type :path) small-height? (<= height threshold-small)
(and tiny-height? (<= height threshold-tiny)
(> zoom-width min-selrect-side)
(> zoom-height min-selrect-side))) vertical-line? (and (= type :path) tiny-width?)
min-side-top? (or (not= type :path) (> zoom-height min-selrect-side)) horizontal-line? (and (= type :path) tiny-height?)
min-side-side? (or (not= type :path) (> zoom-width min-selrect-side))]
align (if (or small-width? small-height?)
:outside
:inside)]
(->> (->>
[ ;; TOP-LEFT [ ;; TOP-LEFT
{:type :rotation {:type :rotation
@ -81,42 +84,66 @@
:position :bottom-left :position :bottom-left
:props {:cx x :cy (+ y height)}} :props {:cx x :cy (+ y height)}}
(when min-side-top? (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 {:type :resize-side
:position :top :position :top
:props {:x x :y y :length width :angle 0 :align align}}) :props {:x x
:y y
:length length
:angle 0
:align align}}))
(when min-side-side? (when-not horizontal-line?
{:type :resize-side (let [x (if small-width? (+ x (/ (+ width threshold-small) 2)) (+ x width))
:position :right length (if small-width? threshold-small width)]
:props {:x (+ x width) :y y :length height :angle 90 :align align}})
(when min-side-top?
{:type :resize-side {:type :resize-side
:position :bottom :position :bottom
:props {:x (+ x width) :y (+ y height) :length width :angle 180 :align align}}) :props {:x x
:y (+ y height)
:length length
:angle 180
:align align}}))
(when min-side-side? (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-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 {:type :resize-side
:position :left :position :left
:props {:x x :y (+ y height) :length height :angle 270 :align align}}) :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 {:type :resize-point
:position :top-left :position :top-left
:props {:cx x :cy y :align align}}) :props {:cx x :cy y :align align}})
(when show-resize-point? (when (and (not tiny-width?) (not tiny-height?))
{:type :resize-point {:type :resize-point
:position :top-right :position :top-right
:props {:cx (+ x width) :cy y :align align}}) :props {:cx (+ x width) :cy y :align align}})
(when show-resize-point? (when (and (not tiny-width?) (not tiny-height?))
{:type :resize-point {:type :resize-point
:position :bottom-right :position :bottom-right
:props {:cx (+ x width) :cy (+ y height) :align align}}) :props {:cx (+ x width) :cy (+ y height) :align align}})
(when show-resize-point? (when (and (not tiny-width?) (not tiny-height?))
{:type :resize-point {:type :resize-point
:position :bottom-left :position :bottom-left
:props {:cx x :cy (+ y height) :align align}})] :props {:cx x :cy (+ y height) :align align}})]
@ -137,8 +164,7 @@
:y y :y y
:width size :width size
:height size :height size
:fill (if (debug? :rotation-handler) "blue" "none") :fill (if (debug? :handlers) "blue" "none")
:stroke (if (debug? :rotation-handler) "blue" "none")
:stroke-width 0 :stroke-width 0
:transform transform :transform transform
:on-mouse-down on-rotate}])) :on-mouse-down on-rotate}]))
@ -171,8 +197,7 @@
:width resize-point-circle-radius :width resize-point-circle-radius
:height resize-point-circle-radius :height resize-point-circle-radius
:transform (when rotation (str/fmt "rotate(%s, %s, %s)" rotation cx' cy')) :transform (when rotation (str/fmt "rotate(%s, %s, %s)" rotation cx' cy'))
:style {:fill (if (debug? :resize-handler) "red" "none") :style {:fill (if (debug? :handlers) "red" "none")
:stroke (if (debug? :resize-handler) "red" "none")
:stroke-width 0 :stroke-width 0
:cursor cursor} :cursor cursor}
:on-mouse-down #(on-resize {:x cx' :y cy'} %)}]) :on-mouse-down #(on-resize {:x cx' :y cy'} %)}])
@ -181,8 +206,7 @@
:r (/ resize-point-circle-radius zoom) :r (/ resize-point-circle-radius zoom)
:cx cx' :cx cx'
:cy cy' :cy cy'
:style {:fill (if (debug? :resize-handler) "red" "none") :style {:fill (if (debug? :handlers) "red" "none")
:stroke (if (debug? :resize-handler) "red" "none")
:stroke-width 0 :stroke-width 0
:cursor cursor}}])])) :cursor cursor}}])]))
@ -192,25 +216,18 @@
(let [res-point (if (#{:top :bottom} position) (let [res-point (if (#{:top :bottom} position)
{:y y} {:y y}
{:x x}) {: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) height (/ resize-side-height zoom)
offset-x (/ (- length width) 2)
offset-y (if (= align :outside) (- height) (- (/ height 2))) offset-y (if (= align :outside) (- height) (- (/ height 2)))
target-x (+ x offset-x)
target-y (+ y offset-y)] target-y (+ y offset-y)]
[:rect {:x target-x [:rect {:x x
:y target-y :y target-y
:width width :width length
:height height :height height
:transform (gmt/multiply transform :transform (gmt/multiply transform
(gmt/rotate-matrix angle (gpt/point x y))) (gmt/rotate-matrix angle (gpt/point x y)))
:on-mouse-down #(on-resize res-point %) :on-mouse-down #(on-resize res-point %)
:style {:fill (if (debug? :resize-handler) "yellow" "none") :style {:fill (if (debug? :handlers) "yellow" "none")
:stroke (if (debug? :resize-handler) "yellow" "none")
:stroke-width 0 :stroke-width 0
:cursor (if (#{:left :right} position) :cursor (if (#{:left :right} position)
(cur/resize-ew rotation) (cur/resize-ew rotation)

View file

@ -9,13 +9,13 @@
[app.common.geom.point :as gpt] [app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh])) [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 y)
(gpt/point (+ x width) y) (gpt/point (+ x width) y)
(gpt/point (+ x width) (+ y height)) (gpt/point (+ x width) (+ y height))
(gpt/point x (+ 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) (into (selrect-snap-points selrect)
#{(gpt/point (+ x (/ width 2)) y) #{(gpt/point (+ x (/ width 2)) y)
(gpt/point (+ x width) (+ y (/ height 2))) (gpt/point (+ x width) (+ y (/ height 2)))

View file

@ -31,11 +31,8 @@
;; Displays in the console log the events through the application ;; Displays in the console log the events through the application
:events :events
;; Display the boxes that represent the rotation handlers ;; Display the boxes that represent the rotation and resize handlers
:rotation-handler :handlers
;; Display the boxes that represent the resize handlers
:resize-handler
;; Displays the center of a selection ;; Displays the center of a selection
:selection-center :selection-center