mirror of
https://github.com/penpot/penpot.git
synced 2025-06-11 17:31:37 +02:00
✨ Snap to square grid
This commit is contained in:
parent
3308d762f1
commit
d2229f43c7
12 changed files with 159 additions and 171 deletions
|
@ -66,7 +66,8 @@
|
|||
:layers
|
||||
:element-options
|
||||
:rules
|
||||
:dynamic-alignment})
|
||||
:dynamic-alignment
|
||||
:layouts})
|
||||
|
||||
(s/def ::options-mode #{:design :prototype})
|
||||
|
||||
|
@ -1525,6 +1526,17 @@
|
|||
state
|
||||
(assoc-in [:workspace-data pid :objects frame-id :layouts index] data))))))
|
||||
|
||||
(defn set-default-layout [type params]
|
||||
(ptk/reify ::set-default-layout
|
||||
dwc/IBatchedChange
|
||||
|
||||
;; TODO: Save into the backend
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(->
|
||||
state
|
||||
(assoc-in [:workspace-page :options :saved-layouts type] params)))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Exports
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
|
|
@ -42,6 +42,12 @@
|
|||
(def workspace-page
|
||||
(l/derived :workspace-page st/state))
|
||||
|
||||
(def workspace-page-options
|
||||
(l/derived :options workspace-page))
|
||||
|
||||
(def workspace-saved-layouts
|
||||
(l/derived :saved-layouts workspace-page-options))
|
||||
|
||||
(def workspace-page-id
|
||||
(l/derived :id workspace-page))
|
||||
|
||||
|
@ -71,6 +77,9 @@
|
|||
(def workspace-objects
|
||||
(l/derived :objects workspace-data))
|
||||
|
||||
(def workspace-frames
|
||||
(l/derived cp/select-frames workspace-objects))
|
||||
|
||||
(defn object-by-id
|
||||
[id]
|
||||
(letfn [(selector [state]
|
||||
|
|
|
@ -73,7 +73,8 @@
|
|||
[:& viewport {:page page
|
||||
:key (:id page)
|
||||
:file file
|
||||
:local local}]]]
|
||||
:local local
|
||||
:layout layout}]]]
|
||||
|
||||
[:& left-toolbar {:page page :layout layout}]
|
||||
|
||||
|
|
|
@ -11,13 +11,15 @@
|
|||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.common.pages :as cp]
|
||||
[uxbox.util.geom.shapes :as gsh]
|
||||
[uxbox.util.geom.layout :as ula]))
|
||||
|
||||
(mf/defc grid-layout [{:keys [frame zoom layout] :as props}]
|
||||
(let [{:keys [color size] :as params} (-> layout :params)
|
||||
{color-value :value color-opacity :opacity} color
|
||||
{color-value :value color-opacity :opacity} (-> layout :params :color)
|
||||
{frame-width :width frame-height :height :keys [x y]} frame]
|
||||
[:g.grid
|
||||
[:g.layout
|
||||
[:*
|
||||
(for [xs (range size frame-width size)]
|
||||
[:line {:key (str (:id frame) "-y-" xs)
|
||||
|
@ -38,20 +40,20 @@
|
|||
:stroke-opacity color-opacity
|
||||
:stroke-width (str (/ 1 zoom))}}])]]))
|
||||
|
||||
(mf/defc flex-layout [{:keys [frame zoom layout]}]
|
||||
(mf/defc flex-layout [{:keys [key frame zoom layout]}]
|
||||
(let [{color-value :value color-opacity :opacity} (-> layout :params :color)]
|
||||
(for [{:keys [x y width height]} (ula/layout-rects frame layout)]
|
||||
[:rect {:x x
|
||||
:y y
|
||||
:width width
|
||||
:height height
|
||||
:style {:pointer-events "none"
|
||||
:fill color-value
|
||||
:opacity color-opacity}}])))
|
||||
[:g.layout
|
||||
(for [{:keys [x y width height]} (ula/layout-rects frame layout)]
|
||||
[:rect {:key (str key "-" x "-" y)
|
||||
:x x
|
||||
:y y
|
||||
:width width
|
||||
:height height
|
||||
:style {:fill color-value
|
||||
:opacity color-opacity}}])]))
|
||||
|
||||
(mf/defc layout-display [{:keys [frame]}]
|
||||
(let [zoom (mf/deref refs/selected-zoom)
|
||||
layouts (:layouts frame)]
|
||||
(mf/defc layout-display-frame [{:keys [frame zoom]}]
|
||||
(let [layouts (:layouts frame)]
|
||||
(for [[index {:keys [type display] :as layout}] (map-indexed vector layouts)]
|
||||
(let [props #js {:key (str (:id frame) "-layout-" index)
|
||||
:frame frame
|
||||
|
@ -62,3 +64,12 @@
|
|||
:square [:> grid-layout props]
|
||||
:column [:> flex-layout props]
|
||||
:row [:> flex-layout props]))))))
|
||||
|
||||
|
||||
(mf/defc layout-display [{:keys [zoom]}]
|
||||
(let [frames (mf/deref refs/workspace-frames)]
|
||||
[:g.layout-display {:style {:pointer-events "none"}}
|
||||
(for [frame frames]
|
||||
[:& layout-display-frame {:key (str "layout-" (:id frame))
|
||||
:zoom zoom
|
||||
:frame (gsh/transform-shape frame)}])]))
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
;; 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) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
;; Copyright (c) 2015-2019 Andrey Antukh <niwi@niwi.nz>
|
||||
|
||||
(ns uxbox.main.ui.workspace.ruler
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.main.constants :as c]
|
||||
[uxbox.main.data.workspace :as udw]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.math :as mth]))
|
||||
|
||||
(mf/defc ruler-text
|
||||
[{:keys [zoom ruler] :as props}]
|
||||
#_(let [{:keys [start end]} ruler
|
||||
distance (-> (gpt/distance (gpt/divide end zoom)
|
||||
(gpt/divide start zoom))
|
||||
(mth/precision 2))
|
||||
angle (-> (gpt/angle end start)
|
||||
(mth/precision 2))
|
||||
transform1 (str "translate(" (+ (:x end) 35) "," (- (:y end) 10) ")")
|
||||
transform2 (str "translate(" (+ (:x end) 25) "," (- (:y end) 30) ")")]
|
||||
[:g
|
||||
[:rect {:fill "black"
|
||||
:fill-opacity "0.4"
|
||||
:rx "3"
|
||||
:ry "3"
|
||||
:width "90"
|
||||
:height "50"
|
||||
:transform transform2}]
|
||||
[:text {:transform transform1
|
||||
:fill "white"}
|
||||
[:tspan {:x "0"}
|
||||
(str distance " px")]
|
||||
[:tspan {:x "0" :y "20"}
|
||||
(str angle "°")]]]))
|
||||
|
||||
(mf/defc ruler-line
|
||||
[{:keys [zoom ruler] :as props}]
|
||||
#_(let [{:keys [start end]} ruler]
|
||||
[:line {:x1 (:x start)
|
||||
:y1 (:y start)
|
||||
:x2 (:x end)
|
||||
:y2 (:y end)
|
||||
:style {:cursor "cell"}
|
||||
:stroke-width "1"
|
||||
:stroke "red"}]))
|
||||
|
||||
(mf/defc ruler
|
||||
[{:keys [ruler zoom] :as props}]
|
||||
#_(letfn [(on-mouse-down [event]
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! :interrupt
|
||||
(udw/assign-cursor-tooltip nil)
|
||||
(udw/start-ruler)))
|
||||
(on-mouse-up [event]
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! :interrupt))
|
||||
(on-unmount []
|
||||
(st/emit! :interrupt
|
||||
(udw/clear-ruler)))]
|
||||
(mf/use-effect (constantly on-unmount))
|
||||
[:svg {:on-mouse-down on-mouse-down
|
||||
:on-mouse-up on-mouse-up}
|
||||
[:rect {:style {:fill "transparent"
|
||||
:stroke "transparent"
|
||||
:cursor "cell"}
|
||||
:width c/viewport-width
|
||||
:height c/viewport-height}]
|
||||
(when ruler
|
||||
[:g
|
||||
[:& ruler-line {:ruler ruler}]
|
||||
[:& ruler-text {:ruler ruler :zoom zoom}]])]))
|
||||
|
|
@ -22,8 +22,7 @@
|
|||
[uxbox.util.geom.shapes :as geom]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.main.streams :as ms]
|
||||
[uxbox.util.timers :as ts]
|
||||
[uxbox.main.ui.workspace.layout-display :refer [layout-display]]))
|
||||
[uxbox.util.timers :as ts]))
|
||||
|
||||
(defn- frame-wrapper-factory-equals?
|
||||
[np op]
|
||||
|
@ -105,6 +104,5 @@
|
|||
(:name shape)]
|
||||
[:& frame-shape
|
||||
{:shape shape
|
||||
:childs childs}]
|
||||
[:& layout-display {:frame shape}]])))))
|
||||
:childs childs}]])))))
|
||||
|
||||
|
|
|
@ -12,7 +12,9 @@
|
|||
[rumext.alpha :as mf]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.data :as d]
|
||||
[uxbox.common.data :refer [parse-integer]]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.data.workspace :as dw]
|
||||
[uxbox.main.ui.icons :as i]
|
||||
[uxbox.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
|
||||
|
@ -29,27 +31,8 @@
|
|||
[:div.advanced-options {}
|
||||
children]]))
|
||||
|
||||
(defonce ^:private default-params
|
||||
{:square {:size 16
|
||||
:color {:value "#59B9E2"
|
||||
:opacity 0.9}}
|
||||
|
||||
:column {:size 12
|
||||
:type :stretch
|
||||
:item-width nil
|
||||
:gutter 8
|
||||
:margin 0
|
||||
:color {:value "#DE4762"
|
||||
:opacity 0.1}}
|
||||
:row {:size 12
|
||||
:type :stretch
|
||||
:item-height nil
|
||||
:gutter 8
|
||||
:margin 0
|
||||
:color {:value "#DE4762"
|
||||
:opacity 0.1}}})
|
||||
|
||||
(mf/defc layout-options [{:keys [layout on-change on-remove]}]
|
||||
(mf/defc layout-options [{:keys [layout default-layout-params on-change on-remove]}]
|
||||
(prn "(render) layout" layout)
|
||||
(let [state (mf/use-state {:show-advanced-options false
|
||||
:changes {}})
|
||||
{:keys [type display params] :as layout} (d/deep-merge layout (:changes @state))
|
||||
|
@ -61,17 +44,18 @@
|
|||
18 12 10 8 6 4 3 2]
|
||||
|
||||
emit-changes! (fn [update-fn]
|
||||
(swap! state update :changes update-fn)
|
||||
(when on-change (on-change (d/deep-merge layout (-> @state :changes update-fn)))))
|
||||
(swap! state update :changes update-fn)
|
||||
(prn "(event) layout" (d/deep-merge layout (-> @state :changes update-fn)))
|
||||
(when on-change (on-change (d/deep-merge layout (-> @state :changes update-fn)))))
|
||||
|
||||
handle-toggle-visibility (fn [event]
|
||||
(emit-changes! #(update % :display not)))
|
||||
(emit-changes! (fn [changes] (update changes :display #(if (nil? %) false (not %))))))
|
||||
|
||||
handle-remove-layout (fn [event]
|
||||
(when on-remove (on-remove)))
|
||||
|
||||
handle-change-type (fn [type]
|
||||
(let [defaults (type default-params)
|
||||
(let [defaults (type default-layout-params)
|
||||
params (merge
|
||||
defaults
|
||||
(select-keys (keys defaults) (-> @state :changes params)))
|
||||
|
@ -85,7 +69,7 @@
|
|||
handle-change-event (fn [& keys]
|
||||
(fn [event]
|
||||
(let [change-fn (apply handle-change keys)]
|
||||
(-> event dom/get-target dom/get-value change-fn))))
|
||||
(-> event dom/get-target dom/get-value parse-integer change-fn))))
|
||||
]
|
||||
|
||||
[:div.grid-option
|
||||
|
@ -169,20 +153,45 @@
|
|||
[:button.btn-options "Use default"]
|
||||
[:button.btn-options "Set as default"]]]]))
|
||||
|
||||
(defonce ^:private default-layout-params
|
||||
{:square {:size 16
|
||||
:color {:value "#59B9E2"
|
||||
:opacity 0.9}}
|
||||
|
||||
:column {:size 12
|
||||
:type :stretch
|
||||
:item-width nil
|
||||
:gutter 8
|
||||
:margin 0
|
||||
:color {:value "#DE4762"
|
||||
:opacity 0.1}}
|
||||
:row {:size 12
|
||||
:type :stretch
|
||||
:item-height nil
|
||||
:gutter 8
|
||||
:margin 0
|
||||
:color {:value "#DE4762"
|
||||
:opacity 0.1}}})
|
||||
|
||||
(mf/defc frame-layouts [{:keys [shape]}]
|
||||
(let [id (:id shape)
|
||||
default-layout-params (merge default-layout-params (mf/deref refs/workspace-saved-layouts))
|
||||
handle-create-layout #(st/emit! (dw/add-frame-layout id))
|
||||
handle-remove-layout (fn [index] #(st/emit! (dw/remove-frame-layout id index)))
|
||||
handle-edit-layout (fn [index] #(st/emit! (dw/set-frame-layout id index %)))]
|
||||
handle-edit-layout (fn [index] #(st/emit! (dw/set-frame-layout id index %)))
|
||||
handle-save-layout (fn [layout] (st/emit! (dw/set-default-layout (:type layout) (:params layout))))]
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
[:span "Grid & Layout"]
|
||||
[:div.add-page {:on-click handle-create-layout} i/close]]
|
||||
|
||||
[:div.element-set-content
|
||||
(for [[index layout] (map-indexed vector (:layouts shape))]
|
||||
[:& layout-options {:key (str (:id shape) "-" index)
|
||||
:layout layout
|
||||
:on-change (handle-edit-layout index)
|
||||
:on-remove (handle-remove-layout index)}])]]))
|
||||
(when (not (empty? (:layouts shape)))
|
||||
[:div.element-set-content
|
||||
(for [[index layout] (map-indexed vector (:layouts shape))]
|
||||
[:& layout-options {:key (str (:id shape) "-" index)
|
||||
:layout layout
|
||||
:default-layout-params default-layout-params
|
||||
:on-change (handle-edit-layout index)
|
||||
:on-remove (handle-remove-layout index)
|
||||
:on-save-layout handle-save-layout}])])]))
|
||||
|
||||
|
|
|
@ -26,11 +26,10 @@
|
|||
[uxbox.main.ui.workspace.shapes :refer [shape-wrapper frame-wrapper]]
|
||||
[uxbox.main.ui.workspace.shapes.interactions :refer [interactions]]
|
||||
[uxbox.main.ui.workspace.drawarea :refer [draw-area start-drawing]]
|
||||
[uxbox.main.ui.workspace.grid :refer [grid]]
|
||||
[uxbox.main.ui.workspace.ruler :refer [ruler]]
|
||||
[uxbox.main.ui.workspace.selection :refer [selection-handlers]]
|
||||
[uxbox.main.ui.workspace.presence :as presence]
|
||||
[uxbox.main.ui.workspace.snap-feedback :refer [snap-feedback]]
|
||||
[uxbox.main.ui.workspace.layout-display :refer [layout-display]]
|
||||
[uxbox.util.math :as mth]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.object :as obj]
|
||||
|
@ -127,7 +126,7 @@
|
|||
:key (:id item)}]))]))
|
||||
|
||||
(mf/defc viewport
|
||||
[{:keys [page local] :as props}]
|
||||
[{:keys [page local layout] :as props}]
|
||||
(let [{:keys [drawing-tool
|
||||
options-mode
|
||||
zoom
|
||||
|
@ -354,6 +353,7 @@
|
|||
]
|
||||
|
||||
(mf/use-effect on-mount)
|
||||
|
||||
[:svg.viewport
|
||||
{:preserveAspectRatio "xMidYMid meet"
|
||||
:width (:width vport 0)
|
||||
|
@ -381,22 +381,18 @@
|
|||
:zoom zoom
|
||||
:edition edition}])
|
||||
|
||||
|
||||
(when-let [drawing-shape (:drawing local)]
|
||||
[:& draw-area {:shape drawing-shape
|
||||
:zoom zoom
|
||||
:modifiers (:modifiers local)}])
|
||||
|
||||
(when (contains? layout :layouts)
|
||||
[:& layout-display {:zoom zoom}])
|
||||
|
||||
[:& snap-feedback]
|
||||
|
||||
(when (contains? flags :grid)
|
||||
[:& grid])]
|
||||
|
||||
(when tooltip
|
||||
[:& cursor-tooltip {:zoom zoom :tooltip tooltip}])
|
||||
|
||||
(when (contains? flags :ruler)
|
||||
[:& ruler {:zoom zoom :ruler (:ruler local)}])
|
||||
(when tooltip
|
||||
[:& cursor-tooltip {:zoom zoom :tooltip tooltip}])]
|
||||
|
||||
[:& presence/active-cursors {:page page}]
|
||||
[:& selection-rect {:data (:selrect local)}]
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
;;
|
||||
;; Copyright (c) 2020 UXBOX Labs SL
|
||||
|
||||
(ns uxbox.util.geom.layout)
|
||||
(ns uxbox.util.geom.layout
|
||||
(:require
|
||||
[uxbox.util.geom.point :as gpt]))
|
||||
|
||||
(defn calculate-column-layout [{:keys [width height x y] :as frame} {:keys [size gutter margin item-width type] :as params}]
|
||||
(let [parts (/ width size)
|
||||
|
@ -20,7 +22,7 @@
|
|||
gutter (if (= :stretch type) (/ (- width (* item-width size) (* margin 2)) (dec size)) gutter)
|
||||
next-x (fn [cur-val] (+ initial-offset x (* (+ item-width gutter) cur-val)))
|
||||
next-y (fn [cur-val] y)]
|
||||
[item-width item-height next-x next-y]))
|
||||
[size item-width item-height next-x next-y]))
|
||||
|
||||
(defn calculate-row-layout [{:keys [width height x y] :as frame} {:keys [size gutter margin item-height type] :as params}]
|
||||
(let [{:keys [width height x y]} frame
|
||||
|
@ -34,16 +36,51 @@
|
|||
gutter (if (= :stretch type) (/ (- height (* item-height size) (* margin 2)) (dec size)) gutter)
|
||||
next-x (fn [cur-val] x)
|
||||
next-y (fn [cur-val] (+ initial-offset y (* (+ item-height gutter) cur-val)))]
|
||||
[item-width item-height next-x next-y]))
|
||||
[size item-width item-height next-x next-y]))
|
||||
|
||||
(defn calculate-grid-layout [{:keys [width height x y] :as frame} {:keys [size] :as params}]
|
||||
(let [col-size (quot width size)
|
||||
row-size (quot height size)
|
||||
as-row-col (fn [value] [(quot value col-size) (rem value col-size)])
|
||||
next-x (fn [cur-val]
|
||||
(let [[_ col] (as-row-col cur-val)] (+ x (* col size))))
|
||||
next-y (fn [cur-val]
|
||||
(let [[row _] (as-row-col cur-val)] (+ y (* row size))))]
|
||||
[(* col-size row-size) size size next-x next-y]))
|
||||
|
||||
(defn layout-rects [frame layout]
|
||||
(let [[item-width item-height next-x next-y]
|
||||
(case (-> layout :type)
|
||||
:column (calculate-column-layout frame (-> layout :params))
|
||||
:row (calculate-row-layout frame (-> layout :params)))]
|
||||
(let [layout-fn (case (-> layout :type)
|
||||
:column calculate-column-layout
|
||||
:row calculate-row-layout
|
||||
:square calculate-grid-layout)
|
||||
[num-items item-width item-height next-x next-y] (layout-fn frame (-> layout :params))]
|
||||
(->>
|
||||
(range 0 (-> layout :params :size))
|
||||
(range 0 num-items)
|
||||
(map #(hash-map :x (next-x %)
|
||||
:y (next-y %)
|
||||
:width item-width
|
||||
:height item-height)))))
|
||||
|
||||
(defn- layout-rect-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- layout-snap-points
|
||||
([shape coord] (mapcat #(layout-snap-points shape % coord) (:layouts shape)))
|
||||
([shape {:keys [type display params] :as layout} coord]
|
||||
|
||||
(case type
|
||||
:square (let [{:keys [x y width height]} shape
|
||||
size (-> params :size)]
|
||||
(if (= coord :x)
|
||||
(mapcat #(vector (gpt/point (+ x %) y)
|
||||
(gpt/point (+ x %) (+ y height))) (range size width size))
|
||||
(mapcat #(vector (gpt/point x (+ y %))
|
||||
(gpt/point (+ x width) (+ y %))) (range size height size))))
|
||||
:column (when (= coord :x) (->> (layout-rects shape layout)
|
||||
(mapcat layout-rect-points)))
|
||||
|
||||
:row (when (= coord :y) (->> (layout-rects shape layout)
|
||||
(mapcat layout-rect-points))))))
|
||||
|
|
|
@ -12,17 +12,7 @@
|
|||
[cljs.spec.alpha :as s]
|
||||
[clojure.set :as set]
|
||||
[uxbox.util.geom.shapes :as gsh]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.geom.layout :as gla]))
|
||||
|
||||
(defn- layout-rect-snaps [{: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- layout-snap-points [frame {:keys [type] :as layout}]
|
||||
(mapcat layout-rect-snaps (gla/layout-rects frame layout)))
|
||||
[uxbox.util.geom.point :as gpt]))
|
||||
|
||||
(defn- frame-snap-points [{:keys [x y width height layouts] :as frame}]
|
||||
(into #{(gpt/point x y)
|
||||
|
@ -32,11 +22,7 @@
|
|||
(gpt/point (+ x width) (+ y height))
|
||||
(gpt/point (+ x (/ width 2)) (+ y height))
|
||||
(gpt/point x (+ y height))
|
||||
(gpt/point x (+ y (/ height 2)))}
|
||||
(->>
|
||||
layouts
|
||||
(filter #(and (not= :grid (:type %)) (:display %)))
|
||||
(mapcat #(layout-snap-points frame %)))))
|
||||
(gpt/point x (+ y (/ height 2)))}))
|
||||
|
||||
(defn shape-snap-points
|
||||
[shape]
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
[uxbox.common.pages :as cp]
|
||||
[uxbox.worker.impl :as impl]
|
||||
[uxbox.util.range-tree :as rt]
|
||||
[uxbox.util.geom.snap-points :as snap]))
|
||||
[uxbox.util.geom.snap-points :as snap]
|
||||
[uxbox.util.geom.layout :as gla]))
|
||||
|
||||
(defonce state (l/atom {}))
|
||||
|
||||
|
@ -23,8 +24,11 @@
|
|||
[shapes coord]
|
||||
(let [process-shape (fn [coord]
|
||||
(fn [shape]
|
||||
(let [points (snap/shape-snap-points shape)]
|
||||
(map #(vector % (:id shape)) points))))
|
||||
(concat
|
||||
(let [points (snap/shape-snap-points shape)]
|
||||
(map #(vector % (:id shape)) points))
|
||||
(let [points (gla/layout-snap-points shape coord)]
|
||||
(map #(vector % :layout) points)))))
|
||||
into-tree (fn [tree [point _ :as data]]
|
||||
(rt/insert tree (coord point) data))]
|
||||
(->> shapes
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue