mirror of
https://github.com/penpot/penpot.git
synced 2025-02-15 11:38:24 -05:00
✨ Improved text selection
This commit is contained in:
parent
618d22d214
commit
bbf91a8957
6 changed files with 82 additions and 27 deletions
|
@ -70,9 +70,11 @@
|
||||||
([points matrix]
|
([points matrix]
|
||||||
(transform-points points nil matrix))
|
(transform-points points nil matrix))
|
||||||
([points center matrix]
|
([points center matrix]
|
||||||
(let [prev (if center (gmt/translate-matrix center) (gmt/matrix))
|
(if (some? matrix)
|
||||||
post (if center (gmt/translate-matrix (gpt/negate center)) (gmt/matrix))
|
(let [prev (if center (gmt/translate-matrix center) (gmt/matrix))
|
||||||
|
post (if center (gmt/translate-matrix (gpt/negate center)) (gmt/matrix))
|
||||||
|
|
||||||
tr-point (fn [point]
|
tr-point (fn [point]
|
||||||
(gpt/transform point (gmt/multiply prev matrix post)))]
|
(gpt/transform point (gmt/multiply prev matrix post)))]
|
||||||
(mapv tr-point points))))
|
(mapv tr-point points))
|
||||||
|
points)))
|
||||||
|
|
|
@ -9,8 +9,10 @@
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.geom.matrix :as gmt]
|
[app.common.geom.matrix :as gmt]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
|
[app.common.geom.shapes.common :as gco]
|
||||||
[app.common.geom.shapes.path :as gpp]
|
[app.common.geom.shapes.path :as gpp]
|
||||||
[app.common.geom.shapes.rect :as gpr]
|
[app.common.geom.shapes.rect :as gpr]
|
||||||
|
[app.common.geom.shapes.text :as gte]
|
||||||
[app.common.math :as mth]))
|
[app.common.math :as mth]))
|
||||||
|
|
||||||
(defn orientation
|
(defn orientation
|
||||||
|
@ -283,6 +285,23 @@
|
||||||
(is-point-inside-ellipse? (first rect-points) ellipse-data)
|
(is-point-inside-ellipse? (first rect-points) ellipse-data)
|
||||||
(intersects-lines-ellipse? rect-lines ellipse-data))))
|
(intersects-lines-ellipse? rect-lines ellipse-data))))
|
||||||
|
|
||||||
|
(defn overlaps-text?
|
||||||
|
[{:keys [position-data] :as shape} rect]
|
||||||
|
|
||||||
|
(if (and (some? position-data) (d/not-empty? position-data))
|
||||||
|
(let [center (gco/center-shape shape)
|
||||||
|
|
||||||
|
transform-rect
|
||||||
|
(fn [rect-points]
|
||||||
|
(gco/transform-points rect-points center (:transform shape)))]
|
||||||
|
|
||||||
|
(->> position-data
|
||||||
|
(map (comp transform-rect
|
||||||
|
gpr/rect->points
|
||||||
|
gte/position-data->rect))
|
||||||
|
(some #(overlaps-rect-points? rect %))))
|
||||||
|
(overlaps-rect-points? rect (:points shape))))
|
||||||
|
|
||||||
(defn overlaps?
|
(defn overlaps?
|
||||||
"General case to check for overlapping between shapes and a rectangle"
|
"General case to check for overlapping between shapes and a rectangle"
|
||||||
[shape rect]
|
[shape rect]
|
||||||
|
@ -291,14 +310,25 @@
|
||||||
(update :x - stroke-width)
|
(update :x - stroke-width)
|
||||||
(update :y - stroke-width)
|
(update :y - stroke-width)
|
||||||
(update :width + (* 2 stroke-width))
|
(update :width + (* 2 stroke-width))
|
||||||
(update :height + (* 2 stroke-width))
|
(update :height + (* 2 stroke-width)))]
|
||||||
)]
|
|
||||||
(or (not shape)
|
(or (not shape)
|
||||||
(let [path? (= :path (:type shape))
|
(let [path? (= :path (:type shape))
|
||||||
circle? (= :circle (:type shape))]
|
circle? (= :circle (:type shape))
|
||||||
(and (overlaps-rect-points? rect (:points shape))
|
text? (= :text (:type shape))]
|
||||||
(or (not path?) (overlaps-path? shape rect))
|
(cond
|
||||||
(or (not circle?) (overlaps-ellipse? shape rect)))))))
|
path?
|
||||||
|
(and (overlaps-rect-points? rect (:points shape))
|
||||||
|
(overlaps-path? shape rect))
|
||||||
|
|
||||||
|
circle?
|
||||||
|
(and (overlaps-rect-points? rect (:points shape))
|
||||||
|
(overlaps-ellipse? shape rect))
|
||||||
|
|
||||||
|
text?
|
||||||
|
(overlaps-text? shape rect)
|
||||||
|
|
||||||
|
:else
|
||||||
|
(overlaps-rect-points? rect (:points shape)))))))
|
||||||
|
|
||||||
(defn has-point-rect?
|
(defn has-point-rect?
|
||||||
[rect point]
|
[rect point]
|
||||||
|
|
27
common/src/app/common/geom/shapes/text.cljc
Normal file
27
common/src/app/common/geom/shapes/text.cljc
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; 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) UXBOX Labs SL
|
||||||
|
|
||||||
|
(ns app.common.geom.shapes.text
|
||||||
|
(:require
|
||||||
|
[app.common.geom.shapes.common :as gco]
|
||||||
|
[app.common.geom.shapes.rect :as gpr]
|
||||||
|
[app.common.geom.shapes.transforms :as gtr]))
|
||||||
|
|
||||||
|
(defn position-data->rect
|
||||||
|
[{:keys [x y width height]}]
|
||||||
|
{:x x
|
||||||
|
:y (- y height)
|
||||||
|
:width width
|
||||||
|
:height height})
|
||||||
|
|
||||||
|
(defn position-data-bounding-box
|
||||||
|
[{:keys [position-data] :as shape}]
|
||||||
|
(let [points (->> position-data
|
||||||
|
(mapcat (comp gpr/rect->points position-data->rect)))
|
||||||
|
transform (gtr/transform-matrix shape)
|
||||||
|
points (gco/transform-points points transform)]
|
||||||
|
(gpr/points->selrect points)))
|
||||||
|
|
|
@ -82,7 +82,7 @@
|
||||||
|
|
||||||
(defn add-fill
|
(defn add-fill
|
||||||
([attrs shape render-id]
|
([attrs shape render-id]
|
||||||
(add-fill attrs shape render-id 0))
|
(add-fill attrs shape render-id nil))
|
||||||
|
|
||||||
([attrs shape render-id index]
|
([attrs shape render-id index]
|
||||||
(let [fill-attrs
|
(let [fill-attrs
|
||||||
|
@ -92,7 +92,7 @@
|
||||||
{:fill (str/format "url(#%s)" fill-image-id)})
|
{:fill (str/format "url(#%s)" fill-image-id)})
|
||||||
|
|
||||||
(contains? shape :fill-color-gradient)
|
(contains? shape :fill-color-gradient)
|
||||||
(let [fill-color-gradient-id (str "fill-color-gradient_" render-id "_" index)]
|
(let [fill-color-gradient-id (str "fill-color-gradient_" render-id (if index (str "_" index) ""))]
|
||||||
{:fill (str/format "url(#%s)" fill-color-gradient-id)})
|
{:fill (str/format "url(#%s)" fill-color-gradient-id)})
|
||||||
|
|
||||||
(contains? shape :fill-color)
|
(contains? shape :fill-color)
|
||||||
|
|
|
@ -98,16 +98,6 @@
|
||||||
(some #(cph/is-parent? objects % group-id))
|
(some #(cph/is-parent? objects % group-id))
|
||||||
(not))))
|
(not))))
|
||||||
|
|
||||||
(defn check-text-collision?
|
|
||||||
"Checks if he current position `pos` overlaps any of the text-nodes for the given `text-id`"
|
|
||||||
[objects pos text-id]
|
|
||||||
(and (= :text (get-in objects [text-id :type]))
|
|
||||||
(let [collisions
|
|
||||||
(->> (dom/query-all (str "#shape-" text-id " .text-node"))
|
|
||||||
(map dom/get-bounding-rect)
|
|
||||||
(map dom/bounding-rect->rect))]
|
|
||||||
(not (some #(gshr/contains-point? % pos) collisions)))))
|
|
||||||
|
|
||||||
(defn setup-hover-shapes [page-id move-stream raw-position-ref objects transform selected ctrl? hover hover-ids hover-disabled? zoom]
|
(defn setup-hover-shapes [page-id move-stream raw-position-ref objects transform selected ctrl? hover hover-ids hover-disabled? zoom]
|
||||||
(let [;; We use ref so we don't recreate the stream on a change
|
(let [;; We use ref so we don't recreate the stream on a change
|
||||||
zoom-ref (mf/use-ref zoom)
|
zoom-ref (mf/use-ref zoom)
|
||||||
|
@ -180,9 +170,6 @@
|
||||||
|
|
||||||
remove-xfm (mapcat #(cph/get-parent-ids objects %))
|
remove-xfm (mapcat #(cph/get-parent-ids objects %))
|
||||||
remove-id? (cond-> (into #{} remove-xfm selected)
|
remove-id? (cond-> (into #{} remove-xfm selected)
|
||||||
:always
|
|
||||||
(into (filter #(check-text-collision? objects (mf/ref-val raw-position-ref) %)) ids)
|
|
||||||
|
|
||||||
(not @ctrl?)
|
(not @ctrl?)
|
||||||
(into (filter #(group-empty-space? % objects ids)) ids)
|
(into (filter #(group-empty-space? % objects ids)) ids)
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
|
[app.common.geom.shapes.text :as gte]
|
||||||
[app.common.pages :as cp]
|
[app.common.pages :as cp]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
|
@ -23,7 +24,15 @@
|
||||||
(defn index-shape
|
(defn index-shape
|
||||||
[objects parents-index clip-parents-index]
|
[objects parents-index clip-parents-index]
|
||||||
(fn [index shape]
|
(fn [index shape]
|
||||||
(let [{:keys [x y width height]} (gsh/points->selrect (:points shape))
|
(let [{:keys [x y width height]}
|
||||||
|
(cond
|
||||||
|
(and (= :text (:type shape))
|
||||||
|
(some? (:position-data shape))
|
||||||
|
(d/not-empty? (:position-data shape)))
|
||||||
|
(gte/position-data-bounding-box shape)
|
||||||
|
|
||||||
|
:else
|
||||||
|
(gsh/points->selrect (:points shape)))
|
||||||
shape-bound #js {:x x :y y :width width :height height}
|
shape-bound #js {:x x :y y :width width :height height}
|
||||||
|
|
||||||
parents (get parents-index (:id shape))
|
parents (get parents-index (:id shape))
|
||||||
|
|
Loading…
Add table
Reference in a new issue