0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-26 08:45:34 -05:00

🎉 Changed the user origin for shapes to their corner

This commit is contained in:
alonso.torres 2020-04-29 09:59:12 +02:00
parent db4e0fc314
commit 7ab3d86bc6
19 changed files with 195 additions and 182 deletions

View file

@ -88,7 +88,3 @@
(when (= "main" (unchecked-get js/window app-sym)) (when (= "main" (unchecked-get js/window app-sym))
(reinit))) (reinit)))
(defn ^:export toggle-debug
[]
(swap! st/*debug* not))

View file

@ -70,7 +70,6 @@
(let [frame (get objects (:frame-id shape)) (let [frame (get objects (:frame-id shape))
{:keys [width height rotation]} shape {:keys [width height rotation]} shape
center (gpt/center shape)
shapev (-> (gpt/point width height)) shapev (-> (gpt/point width height))
;; Vector modifiers depending on the handler ;; Vector modifiers depending on the handler
@ -140,7 +139,7 @@
(watch [_ state stream] (watch [_ state stream]
(let [stoper (rx/filter ms/mouse-up? stream) (let [stoper (rx/filter ms/mouse-up? stream)
group (gsh/selection-rect shapes) group (gsh/selection-rect shapes)
group-center (gpt/center group) group-center (gsh/center group)
initial-angle (gpt/angle (apply-zoom @ms/mouse-position) group-center) initial-angle (gpt/angle (apply-zoom @ms/mouse-position) group-center)
calculate-angle (fn [pos ctrl?] calculate-angle (fn [pos ctrl?]
(let [angle (- (gpt/angle pos group-center) initial-angle) (let [angle (- (gpt/angle pos group-center) initial-angle)
@ -161,7 +160,7 @@
(rx/with-latest vector ms/mouse-position-ctrl) (rx/with-latest vector ms/mouse-position-ctrl)
(rx/map (fn [[pos ctrl?]] (rx/map (fn [[pos ctrl?]]
(let [delta-angle (calculate-angle pos ctrl?)] (let [delta-angle (calculate-angle pos ctrl?)]
(set-rotation delta-angle shapes)))) (set-rotation delta-angle shapes group-center))))
(rx/take-until stoper)) (rx/take-until stoper))
(rx/of (apply-modifiers (map :id shapes)))))))) (rx/of (apply-modifiers (map :id shapes))))))))
@ -275,7 +274,7 @@
;; Set-rotation is custom because applies different modifiers to each shape adjusting their position ;; Set-rotation is custom because applies different modifiers to each shape adjusting their position
(defn set-rotation (defn set-rotation
[delta-rotation shapes] [delta-rotation shapes center]
(ptk/reify ::set-rotation (ptk/reify ::set-rotation
IUpdateGroup IUpdateGroup
(get-ids [_] (map :id shapes)) (get-ids [_] (map :id shapes))
@ -293,8 +292,7 @@
(rotate-around-center [state angle center shapes] (rotate-around-center [state angle center shapes]
(reduce #(rotate-shape %1 angle %2 center) state shapes))] (reduce #(rotate-shape %1 angle %2 center) state shapes))]
(let [center (-> shapes gsh/selection-rect gpt/center) (let [objects (get-in state [:workspace-data page-id :objects])
objects (get-in state [:workspace-data page-id :objects])
id->obj #(get objects %) id->obj #(get objects %)
get-children (fn [shape] (map id->obj (helpers/get-children (:id shape) objects))) get-children (fn [shape] (map id->obj (helpers/get-children (:id shape) objects)))
shapes (concat shapes (mapcat get-children shapes))] shapes (concat shapes (mapcat get-children shapes))]

View file

@ -57,6 +57,14 @@
(get-in % [:workspace-data page-id])) (get-in % [:workspace-data page-id]))
(l/derived st/state))) (l/derived st/state)))
(defn object-by-id
[id]
(letfn [(selector [state]
(let [page-id (get-in state [:workspace-page :id])
objects (get-in state [:workspace-data page-id :objects])]
(->> (get objects id))))]
(l/derived selector st/state =)))
(defn objects-by-id (defn objects-by-id
[ids] [ids]
(letfn [(selector [state] (letfn [(selector [state]

View file

@ -23,11 +23,10 @@
(when (debug? :bounding-boxes) (when (debug? :bounding-boxes)
(let [shape (unchecked-get props "shape") (let [shape (unchecked-get props "shape")
frame (unchecked-get props "frame") frame (unchecked-get props "frame")
selrect (geom/transform-selrect frame shape) selrect (-> shape
shape-path (-> shape (geom/selection-rect-shape)
(geom/transform-apply-modifiers) (geom/translate-to-frame frame))
(geom/translate-to-frame frame)) shape-center (geom/center selrect)]
shape-center (geom/center shape-path)]
[:g [:g
[:text {:x (:x selrect) [:text {:x (:x selrect)
:y (- (:y selrect) 5) :y (- (:y selrect) 5)
@ -37,10 +36,12 @@
:stroke-width 0.1} :stroke-width 0.1}
(str/format "%s - (%s, %s)" (str/slice (str (:id shape)) 0 8) (fix (:x shape)) (fix (:y shape)))] (str/format "%s - (%s, %s)" (str/slice (str (:id shape)) 0 8) (fix (:x shape)) (fix (:y shape)))]
[:circle {:cx (:x shape-center) :cy (:y shape-center) :r 5 :fill "yellow"}]
[:rect {:x (:x selrect) [:rect {:x (:x selrect)
:y (:y selrect) :y (:y selrect)
:width (:width selrect) :width (:width selrect)
:height (:height selrect) :height (:height selrect)
:style {:stroke "red" :fill "transparent" :stroke-width "1px" :stroke-opacity 0.5}}]]))) :style {:stroke "red"
:fill "transparent"
:stroke-width "1px"
:stroke-opacity 0.5
:pointer-events "none"}}]])))

View file

@ -22,7 +22,7 @@
(declare circle-shape) (declare circle-shape)
(mf/defc circle-wrapper (mf/defc circle-wrapper
[{:keys [shape frame] :as props}] [{:keys [shape] :as props}]
(let [selected (mf/deref refs/selected-shapes) (let [selected (mf/deref refs/selected-shapes)
selected? (contains? selected (:id shape)) selected? (contains? selected (:id shape))
on-mouse-down #(common/on-mouse-down % shape) on-mouse-down #(common/on-mouse-down % shape)
@ -30,8 +30,7 @@
[:g.shape {:class (when selected? "selected") [:g.shape {:class (when selected? "selected")
:on-mouse-down on-mouse-down :on-mouse-down on-mouse-down
:on-context-menu on-context-menu} :on-context-menu on-context-menu}
[:& circle-shape {:shape (geom/transform-shape frame shape)}] [:& circle-shape {:shape shape}]]))
[:& bounding-box {:shape shape :frame frame}]]))
;; --- Circle Shape ;; --- Circle Shape

View file

@ -75,7 +75,7 @@
inv-zoom (/ 1 zoom) inv-zoom (/ 1 zoom)
childs (mapv #(get objects %) (:shapes shape)) childs (mapv #(get objects %) (:shapes shape))
ds-modifier (:displacement-modifier shape) ds-modifier (get-in shape [:modifiers :displacement])
label-pos (cond-> (gpt/point x (- y 10)) label-pos (cond-> (gpt/point x (- y 10))
(gmt/matrix? ds-modifier) (gpt/transform ds-modifier)) (gmt/matrix? ds-modifier) (gpt/transform ds-modifier))

View file

@ -73,11 +73,9 @@
[:& group-shape [:& group-shape
{:frame frame {:frame frame
:shape (geom/transform-shape frame shape) :shape shape
:children children :children children
:is-child-selected? is-child-selected?}] :is-child-selected? is-child-selected?}]]))))
(when (not is-child-selected?)
[:& bounding-box {:shape shape :frame frame}])]))))
(defn group-shape (defn group-shape
[shape-wrapper] [shape-wrapper]

View file

@ -15,15 +15,14 @@
[uxbox.main.ui.shapes.attrs :as attrs] [uxbox.main.ui.shapes.attrs :as attrs]
[uxbox.main.ui.shapes.common :as common] [uxbox.main.ui.shapes.common :as common]
[uxbox.util.interop :as itr] [uxbox.util.interop :as itr]
[uxbox.util.geom.matrix :as gmt] [uxbox.util.geom.matrix :as gmt]))
[uxbox.main.ui.shapes.bounding-box :refer [bounding-box]]))
;; --- Image Wrapper ;; --- Image Wrapper
(declare image-shape) (declare image-shape)
(mf/defc image-wrapper (mf/defc image-wrapper
[{:keys [shape frame] :as props}] [{:keys [shape] :as props}]
(let [selected (mf/deref refs/selected-shapes) (let [selected (mf/deref refs/selected-shapes)
selected? (contains? selected (:id shape)) selected? (contains? selected (:id shape))
on-mouse-down (mf/use-callback on-mouse-down (mf/use-callback
@ -37,8 +36,7 @@
[:g.shape {:class (when selected? "selected") [:g.shape {:class (when selected? "selected")
:on-mouse-down on-mouse-down :on-mouse-down on-mouse-down
:on-context-menu on-context-menu} :on-context-menu on-context-menu}
[:& image-shape {:shape (geom/transform-shape frame shape)}] [:& image-shape {:shape shape}]]))
[:& bounding-box {:shape shape :frame frame}]]))
;; --- Image Shape ;; --- Image Shape

View file

@ -24,7 +24,7 @@
(declare path-shape) (declare path-shape)
(mf/defc path-wrapper (mf/defc path-wrapper
[{:keys [shape frame] :as props}] [{:keys [shape] :as props}]
(let [selected (mf/deref refs/selected-shapes) (let [selected (mf/deref refs/selected-shapes)
selected? (contains? selected (:id shape)) selected? (contains? selected (:id shape))
on-mouse-down (mf/use-callback on-mouse-down (mf/use-callback
@ -42,8 +42,7 @@
[:g.shape {:on-double-click on-double-click [:g.shape {:on-double-click on-double-click
:on-mouse-down on-mouse-down :on-mouse-down on-mouse-down
:on-context-menu on-context-menu} :on-context-menu on-context-menu}
[:& path-shape {:shape (geom/transform-shape frame shape) :background? true}] [:& path-shape {:shape shape :background? true}]]))
[:& bounding-box {:shape shape :frame frame}]]))
;; --- Path Shape ;; --- Path Shape

View file

@ -15,7 +15,6 @@
[uxbox.main.ui.shapes.attrs :as attrs] [uxbox.main.ui.shapes.attrs :as attrs]
[uxbox.main.ui.shapes.common :as common] [uxbox.main.ui.shapes.common :as common]
[uxbox.util.interop :as itr] [uxbox.util.interop :as itr]
[uxbox.main.ui.shapes.bounding-box :refer [bounding-box]]
[uxbox.main.ui.shapes.custom-stroke :refer [shape-custom-stroke]])) [uxbox.main.ui.shapes.custom-stroke :refer [shape-custom-stroke]]))
;; --- Rect Wrapper ;; --- Rect Wrapper
@ -26,7 +25,6 @@
{::mf/wrap-props false} {::mf/wrap-props false}
[props] [props]
(let [shape (unchecked-get props "shape") (let [shape (unchecked-get props "shape")
frame (unchecked-get props "frame")
on-mouse-down (mf/use-callback on-mouse-down (mf/use-callback
(mf/deps shape) (mf/deps shape)
#(common/on-mouse-down % shape)) #(common/on-mouse-down % shape))
@ -35,8 +33,7 @@
#(common/on-context-menu % shape))] #(common/on-context-menu % shape))]
[:g.shape {:on-mouse-down on-mouse-down [:g.shape {:on-mouse-down on-mouse-down
:on-context-menu on-context-menu} :on-context-menu on-context-menu}
[:& rect-shape {:shape (geom/transform-shape frame shape) }] [:& rect-shape {:shape shape}]]))
[:& bounding-box {:shape shape :frame frame}]]))
;; --- Rect Shape ;; --- Rect Shape

View file

@ -19,6 +19,8 @@
[uxbox.main.ui.shapes.text :as text] [uxbox.main.ui.shapes.text :as text]
[uxbox.main.ui.shapes.group :as group] [uxbox.main.ui.shapes.group :as group]
[uxbox.main.ui.shapes.frame :as frame] [uxbox.main.ui.shapes.frame :as frame]
[uxbox.main.ui.shapes.bounding-box :refer [bounding-box]]
[uxbox.util.geom.shapes :as gsh]
[uxbox.main.refs :as refs])) [uxbox.main.refs :as refs]))
(defn- shape-wrapper-memo-equals? (defn- shape-wrapper-memo-equals?
@ -42,21 +44,24 @@
[props] [props]
(let [shape (unchecked-get props "shape") (let [shape (unchecked-get props "shape")
frame (unchecked-get props "frame") frame (unchecked-get props "frame")
opts #js {:shape shape :frame frame}] opts #js {:shape (->> shape (gsh/transform-shape frame))
:frame frame}]
(when (and shape (not (:hidden shape))) (when (and shape (not (:hidden shape)))
(case (:type shape) [:*
:group [:> group-wrapper opts] (case (:type shape)
:curve [:> path/path-wrapper opts] :group [:> group-wrapper opts]
:text [:> text/text-wrapper opts] :curve [:> path/path-wrapper opts]
:icon [:> icon/icon-wrapper opts] :text [:> text/text-wrapper opts]
:rect [:> rect/rect-wrapper opts] :icon [:> icon/icon-wrapper opts]
:path [:> path/path-wrapper opts] :rect [:> rect/rect-wrapper opts]
:image [:> image/image-wrapper opts] :path [:> path/path-wrapper opts]
:circle [:> circle/circle-wrapper opts] :image [:> image/image-wrapper opts]
:circle [:> circle/circle-wrapper opts]
;; Only used when drawing a new frame. ;; Only used when drawing a new frame.
:frame [:> frame-wrapper opts] :frame [:> frame-wrapper {:shape shape}]
nil)))) nil)
[:& bounding-box {:shape shape :frame frame}]])))
(def group-wrapper (group/group-wrapper shape-wrapper)) (def group-wrapper (group/group-wrapper shape-wrapper))
(def frame-wrapper (frame/frame-wrapper shape-wrapper)) (def frame-wrapper (frame/frame-wrapper shape-wrapper))

View file

@ -46,7 +46,7 @@
(declare text-shape) (declare text-shape)
(mf/defc text-wrapper (mf/defc text-wrapper
[{:keys [shape frame] :as props}] [{:keys [shape] :as props}]
(let [{:keys [id x1 y1 content group]} shape (let [{:keys [id x1 y1 content group]} shape
selected (mf/deref refs/selected-shapes) selected (mf/deref refs/selected-shapes)
edition (mf/deref refs/selected-edition) edition (mf/deref refs/selected-edition)
@ -67,8 +67,8 @@
:on-mouse-down on-mouse-down :on-mouse-down on-mouse-down
:on-context-menu on-context-menu} :on-context-menu on-context-menu}
(if edition? (if edition?
[:& text-shape-edit {:shape (geom/transform-shape frame shape)}] [:& text-shape-edit {:shape shape}]
[:& text-shape {:shape (geom/transform-shape frame shape) [:& text-shape {:shape shape
:selected? selected?}])])) :selected? selected?}])]))
;; --- Text Rendering ;; --- Text Rendering
@ -284,7 +284,8 @@
(mf/use-effect on-mount) (mf/use-effect on-mount)
[:foreignObject {:x x :y y :width width :height height :ref self-ref} [:foreignObject {:transform (geom/transform-matrix shape)
:x x :y y :width width :height height :ref self-ref}
[:> rslate/Slate {:editor editor [:> rslate/Slate {:editor editor
:value @state :value @state
:on-change on-change} :on-change on-change}
@ -305,13 +306,7 @@
(mf/defc text-shape (mf/defc text-shape
[{:keys [shape selected?] :as props}] [{:keys [shape selected?] :as props}]
(let [{:keys [id x y width height rotation content]} shape (let [{:keys [id x y width height content]} shape
transform (when (and rotation (pos? rotation))
(str/format "rotate(%s %s %s)"
rotation
(+ x (/ width 2))
(+ y (/ height 2))))
content (parse-content content) content (parse-content content)
editor (mf/use-memo #(rslate/withReact (slate/createEditor))) editor (mf/use-memo #(rslate/withReact (slate/createEditor)))
@ -334,7 +329,7 @@
[:foreignObject {:x x [:foreignObject {:x x
:y y :y y
:transform transform :transform (geom/transform-matrix shape)
:id (str id) :id (str id)
:width width :width width
:height height} :height height}

View file

@ -83,7 +83,7 @@
(let [modifier (-> (gpt/point (:x frame) (:y frame)) (let [modifier (-> (gpt/point (:x frame) (:y frame))
(gpt/negate) (gpt/negate)
(gmt/translate-matrix)) (gmt/translate-matrix))
frame (assoc frame :displacement-modifier modifier) frame (assoc-in frame [:modifiers :displacement] modifier )
width (* (:width frame) zoom) width (* (:width frame) zoom)
height (* (:height frame) zoom) height (* (:height frame) zoom)

View file

@ -305,7 +305,7 @@
(mf/defc generic-draw-area (mf/defc generic-draw-area
[{:keys [shape zoom]}] [{:keys [shape zoom]}]
(let [{:keys [x y width height]} (geom/transform-selrect nil shape)] (let [{:keys [x y width height]} (geom/selection-rect-shape shape)]
(when (and x y) (when (and x y)
[:g [:g
[:& shapes/shape-wrapper {:shape shape}] [:& shapes/shape-wrapper {:shape shape}]

View file

@ -72,6 +72,7 @@
[{:keys [shape zoom on-resize on-rotate] :as props}] [{:keys [shape zoom on-resize on-rotate] :as props}]
(let [{:keys [x y width height rotation] :as shape} (geom/shape->rect-shape shape) (let [{:keys [x y width height rotation] :as shape} (geom/shape->rect-shape shape)
radius (if (> (max width height) handler-size-threshold) 4.0 4.0) radius (if (> (max width height) handler-size-threshold) 4.0 4.0)
transform (geom/transform-matrix shape) transform (geom/transform-matrix shape)
resize-handlers {:top [(+ x (/ width 2 )) y] resize-handlers {:top [(+ x (/ width 2 )) y]
@ -85,14 +86,12 @@
[:g.controls [:g.controls
[:rect.main {:transform transform [:rect.main {:transform transform
:x x :y y :x (- x 1) :y (- y 1)
:width width :width (+ width 2)
:height height :height (+ height 2)
;;:stroke-dasharray (str (/ 8.0 zoom) "," (/ 5 zoom))
:vector-effect "non-scaling-stroke"
:style {:stroke "#1FDEA7" :style {:stroke "#1FDEA7"
:fill "transparent" :stroke-width "1"
:stroke-opacity "1"}}] :fill "transparent"}}]
(for [[position [cx cy]] resize-handlers] (for [[position [cx cy]] resize-handlers]
(let [tp (gpt/transform (gpt/point cx cy) transform)] (let [tp (gpt/transform (gpt/point cx cy) transform)]
@ -156,12 +155,12 @@
(mf/defc text-edition-selection-handlers (mf/defc text-edition-selection-handlers
[{:keys [shape zoom] :as props}] [{:keys [shape zoom] :as props}]
(let [{:keys [x y width height] :as shape} shape] (let [{:keys [x y width height]} shape]
[:g.controls [:g.controls
[:rect.main {:x x :y y [:rect.main {:x x :y y
:transform (geom/transform-matrix shape)
:width width :width width
:height height :height height
;; :stroke-dasharray (str (/ 5.0 zoom) "," (/ 5 zoom))
:style {:stroke "#1FDEA7" :style {:stroke "#1FDEA7"
:stroke-width "0.5" :stroke-width "0.5"
:stroke-opacity "1" :stroke-opacity "1"
@ -170,16 +169,20 @@
(mf/defc multiple-selection-handlers (mf/defc multiple-selection-handlers
[{:keys [shapes selected zoom objects] :as props}] [{:keys [shapes selected zoom objects] :as props}]
(let [shape (geom/selection-rect shapes) (let [shape (geom/selection-rect shapes)
shape-center (geom/center shape)
on-resize #(do (dom/stop-propagation %2) on-resize #(do (dom/stop-propagation %2)
(st/emit! (dw/start-resize %1 selected shape objects))) (st/emit! (dw/start-resize %1 selected shape objects)))
on-rotate #(do (dom/stop-propagation %) on-rotate #(do (dom/stop-propagation %)
(st/emit! (dw/start-rotate shapes)))] (st/emit! (dw/start-rotate shapes)))]
[:& controls {:shape shape [:*
:zoom zoom [:& controls {:shape shape
:on-resize on-resize :zoom zoom
:on-rotate on-rotate}])) :on-resize on-resize
:on-rotate on-rotate}]
(when (debug? :selection-center)
[:circle {:cx (:x shape-center) :cy (:y shape-center) :r 5 :fill "yellow"}])]))
(mf/defc single-selection-handlers (mf/defc single-selection-handlers
[{:keys [shape zoom objects] :as props}] [{:keys [shape zoom objects] :as props}]

View file

@ -15,25 +15,43 @@
[uxbox.main.refs :as refs] [uxbox.main.refs :as refs]
[uxbox.common.data :as d] [uxbox.common.data :as d]
[uxbox.util.dom :as dom] [uxbox.util.dom :as dom]
[uxbox.util.geom.shapes :as gsh]
[uxbox.util.geom.point :as gpt]
[uxbox.main.data.workspace :as udw] [uxbox.main.data.workspace :as udw]
[uxbox.util.math :as math] [uxbox.util.math :as math]
[uxbox.util.i18n :refer [t] :as i18n])) [uxbox.util.i18n :refer [t] :as i18n]))
;; -- User/drawing coords
(defn user-coords-vector [shape]
(let [{sel-x :x sel-y :y :as selrect}
(-> shape
gsh/shape->path
(gsh/center-transform (:transform shape))
gsh/shape->rect-shape)
{rec-x :x rec-y :y} (-> shape gsh/shape->rect-shape)
dx (- rec-x sel-x)
dy (- rec-y sel-y)]
(gpt/point dx dy)))
(defn user->draw [{:keys [x y width height] :as shape}]
(let [dv (user-coords-vector shape)]
(-> shape (gsh/move dv))))
(defn draw->user [{:keys [x y width height] :as shape}]
(let [dv (user-coords-vector shape)]
(-> shape (gsh/move (gpt/negate dv)))))
(mf/defc measures-menu (mf/defc measures-menu
[{:keys [shape options] :as props}] [{:keys [shape options] :as props}]
(let [options (or options #{:size :position :rotation :radius}) (let [options (or options #{:size :position :rotation :radius})
locale (i18n/use-locale) locale (i18n/use-locale)
frame (deref (refs/object-by-id (:frame-id shape)))
data (deref refs/workspace-data) shape (->> shape
parent (get-in data [:objects (:frame-id shape)]) (gsh/transform-shape frame)
(draw->user))
x (cond
(:x shape) :x
(:cx shape) :cx)
y (cond
(:y shape) :y
(:cy shape) :cy)
on-size-change on-size-change
(fn [event attr] (fn [event attr]
@ -58,9 +76,12 @@
(fn [event attr] (fn [event attr]
(let [value (-> (dom/get-target event) (let [value (-> (dom/get-target event)
(dom/get-value) (dom/get-value)
(d/parse-integer 0) (d/parse-integer 0))
(+ (attr parent)))] ; Convert back to absolute position before update new-shape (-> shape
(st/emit! (udw/update-position (:id shape) {attr value})))) (assoc attr value)
(gsh/translate-from-frame frame)
(user->draw))]
(st/emit! (udw/update-position (:id shape) (select-keys new-shape [attr])))))
on-rotation-change on-rotation-change
(fn [event] (fn [event]
@ -89,31 +110,31 @@
;; WIDTH & HEIGHT ;; WIDTH & HEIGHT
(when (options :size) (when (options :size)
[:div.row-flex [:div.row-flex
[:span.element-set-subtitle (t locale "workspace.options.size")] [:span.element-set-subtitle (t locale "workspace.options.size")]
[:div.lock-size {:class (when (:proportion-lock shape) "selected") [:div.lock-size {:class (when (:proportion-lock shape) "selected")
:on-click on-proportion-lock-change} :on-click on-proportion-lock-change}
(if (:proportion-lock shape) (if (:proportion-lock shape)
i/lock i/lock
i/unlock)] i/unlock)]
[:div.input-element.pixels [:div.input-element.pixels
[:input.input-text {:type "number" [:input.input-text {:type "number"
:min "0" :min "0"
:no-validate true :no-validate true
:on-change on-width-change :on-change on-width-change
:value (str (-> (:width shape) :value (str (-> (:width shape)
(d/coalesce 0) (d/coalesce 0)
(math/round)))}]] (math/round)))}]]
[:div.input-element.pixels [:div.input-element.pixels
[:input.input-text {:type "number" [:input.input-text {:type "number"
:min "0" :min "0"
:no-validate true :no-validate true
:on-change on-height-change :on-change on-height-change
:value (str (-> (:height shape) :value (str (-> (:height shape)
(d/coalesce 0) (d/coalesce 0)
(math/round)))}]]]) (math/round)))}]]])
;; Circle RX RY ;; Circle RX RY
(when (options :circle-size) (when (options :circle-size)
@ -142,57 +163,61 @@
;; POSITION ;; POSITION
(when (options :position) (when (options :position)
[:div.row-flex [:div.row-flex
[:span.element-set-subtitle (t locale "workspace.options.position")] [:span.element-set-subtitle (t locale "workspace.options.position")]
[:div.input-element.pixels [:div.input-element.pixels
[:input.input-text {:placeholder "x" [:input.input-text {:placeholder "x"
:type "number" :type "number"
:no-validate true :no-validate true
:on-change on-pos-x-change :on-change on-pos-x-change
:value (str (-> (- (x shape) (:x parent)) ; Show to user position relative to frame :value (:x shape)
(d/coalesce 0) ;;:value (str (-> (- (x shape) (:x parent)) ; Show to user position relative to frame
(math/round)))}]] ;; (d/coalesce 0)
[:div.input-element.pixels ;; (math/round)))
[:input.input-text {:placeholder "y" }]]
:type "number" [:div.input-element.pixels
:no-validate true [:input.input-text {:placeholder "y"
:on-change on-pos-y-change :type "number"
:value (str (-> (- (y shape) (:y parent)) :no-validate true
(d/coalesce 0) :on-change on-pos-y-change
(math/round)))}]]]) :value (:y shape)
;;:value (str (-> (- (y shape) (:y parent))
;; (d/coalesce 0)
;; (math/round)))
}]]])
(when (options :rotation) (when (options :rotation)
[:div.row-flex [:div.row-flex
[:span.element-set-subtitle (t locale "workspace.options.rotation")] [:span.element-set-subtitle (t locale "workspace.options.rotation")]
[:div.input-element.degrees [:div.input-element.degrees
[:input.input-text [:input.input-text
{:placeholder "" {:placeholder ""
:type "number" :type "number"
:no-validate true :no-validate true
:min "0"
:max "360"
:on-change on-rotation-change
:value (str (-> (:rotation shape)
(d/coalesce 0)
(math/round)))}]]
[:input.slidebar
{:type "range"
:min "0" :min "0"
:max "360" :max "360"
:step "1"
:no-validate true
:on-change on-rotation-change :on-change on-rotation-change
:value (str (-> (:rotation shape) :value (str (-> (:rotation shape)
(d/coalesce 0) (d/coalesce 0)))}]])
(math/round)))}]]
[:input.slidebar
{:type "range"
:min "0"
:max "360"
:step "1"
:no-validate true
:on-change on-rotation-change
:value (str (-> (:rotation shape)
(d/coalesce 0)))}]])
(when (options :radius) (when (options :radius)
[:div.row-flex [:div.row-flex
[:span.element-set-subtitle (t locale "workspace.options.radius")] [:span.element-set-subtitle (t locale "workspace.options.radius")]
[:div.input-element.pixels [:div.input-element.pixels
[:input.input-text [:input.input-text
{:placeholder "rx" {:placeholder "rx"
:type "number" :type "number"
:on-change on-radius-change :on-change on-radius-change
:value (str (-> (:rx shape) :value (str (-> (:rx shape)
(d/coalesce 0) (d/coalesce 0)
(math/round)))}]] (math/round)))}]]
[:div.input-element]])]])) [:div.input-element]])]]))

View file

@ -1,9 +1,7 @@
(ns uxbox.util.debug (ns uxbox.util.debug
"Debugging utils" "Debugging utils")
(:require
[uxbox.main.store :as store]))
(def debug-options #{:bounding-boxes :group :events :rotation-handler #_:simple-selection }) (def debug-options #{:bounding-boxes :group :events :rotation-handler :selection-center #_:simple-selection })
(defonce ^:dynamic *debug* (atom #{})) (defonce ^:dynamic *debug* (atom #{}))
@ -13,6 +11,13 @@
(defn -debug! [option] (swap! *debug* disj option)) (defn -debug! [option] (swap! *debug* disj option))
(defn debug? [option] (@*debug* option)) (defn debug? [option] (@*debug* option))
(defn ^:export toggle-debug [name] (let [option (keyword name)]
(if (debug? option)
(-debug! option)
(debug! option))))
(defn ^:export debug-all [name] (debug-all!))
(defn tap (defn tap
"Transducer function that can execute a side-effect `effect-fn` per input" "Transducer function that can execute a side-effect `effect-fn` per input"
[effect-fn] [effect-fn]
@ -31,9 +36,4 @@
(js/console.log str (clj->js val)) (js/console.log str (clj->js val))
val)) val))
(defn dump-state []
(logjs "state" @store/state))
(defn dump-objects []
(let [page-id (get @store/state :current-page-id)]
(logjs "state" (get-in @store/state [:workspace-data page-id :objects]))))

View file

@ -40,11 +40,6 @@
(throw (ex-info "Invalid arguments" {:v v})))) (throw (ex-info "Invalid arguments" {:v v}))))
([x y] (Point. x y))) ([x y] (Point. x y)))
(defn center
[{:keys [x y width height]}]
(point (+ x (/ width 2))
(+ y (/ height 2))))
(defn add (defn add
"Returns the addition of the supplied value to both "Returns the addition of the supplied value to both
coordinates of the point as a new point." coordinates of the point as a new point."

View file

@ -376,6 +376,7 @@
maxx (transduce (map :x) max segments) maxx (transduce (map :x) max segments)
maxy (transduce (map :y) max segments)] maxy (transduce (map :y) max segments)]
(assoc shape (assoc shape
:type :rect
:x1 minx :x1 minx
:y1 miny :y1 miny
:x2 maxx :x2 maxx
@ -495,7 +496,7 @@
(defn translate-from-frame (defn translate-from-frame
[shape {:keys [x y] :as frame}] [shape {:keys [x y] :as frame}]
(move shape (gpt/point (+ x) (+ y)))) (move shape (gpt/point x y)))
;; --- Alignment ;; --- Alignment
@ -736,13 +737,6 @@
(gpt/divide (gpt/point (:width shape-path-temp-rec) (:height shape-path-temp-rec)) (gpt/divide (gpt/point (:width shape-path-temp-rec) (:height shape-path-temp-rec))
(gpt/point (:width shape-path-temp-dim) (:height shape-path-temp-dim))))) (gpt/point (:width shape-path-temp-dim) (:height shape-path-temp-dim)))))
(defn transform-selrect
[frame shape]
(-> shape
(transform-apply-modifiers)
(translate-to-frame frame)
(shape->rect-shape)))
(defn transform-rect-shape (defn transform-rect-shape
[shape] [shape]
(let [;; Apply modifiers to the rect as a path so we have the end shape expected (let [;; Apply modifiers to the rect as a path so we have the end shape expected
@ -788,6 +782,8 @@
new-shape (-> shape new-shape (-> shape
(merge rec) (merge rec)
(update :x #(mth/precision % 2))
(update :y #(mth/precision % 2))
(update :transform #(gmt/multiply (or % (gmt/matrix)) stretch-matrix)) (update :transform #(gmt/multiply (or % (gmt/matrix)) stretch-matrix))
(update :transform-inverse #(gmt/multiply stretch-matrix-inverse (or % (gmt/matrix)))))] (update :transform-inverse #(gmt/multiply stretch-matrix-inverse (or % (gmt/matrix)))))]