mirror of
https://github.com/penpot/penpot.git
synced 2025-06-14 17:41:39 +02:00
✨ Snap to square grid
This commit is contained in:
parent
3308d762f1
commit
d2229f43c7
12 changed files with 159 additions and 171 deletions
|
@ -575,6 +575,10 @@
|
||||||
height: 1rem;
|
height: 1rem;
|
||||||
fill: $color-gray-20;
|
fill: $color-gray-20;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:hover svg, &.is-active svg {
|
||||||
|
fill: $color-primary;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.element-set-content .input-row {
|
.element-set-content .input-row {
|
||||||
|
|
|
@ -66,7 +66,8 @@
|
||||||
:layers
|
:layers
|
||||||
:element-options
|
:element-options
|
||||||
:rules
|
:rules
|
||||||
:dynamic-alignment})
|
:dynamic-alignment
|
||||||
|
:layouts})
|
||||||
|
|
||||||
(s/def ::options-mode #{:design :prototype})
|
(s/def ::options-mode #{:design :prototype})
|
||||||
|
|
||||||
|
@ -1525,6 +1526,17 @@
|
||||||
state
|
state
|
||||||
(assoc-in [:workspace-data pid :objects frame-id :layouts index] data))))))
|
(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
|
;; Exports
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
|
@ -42,6 +42,12 @@
|
||||||
(def workspace-page
|
(def workspace-page
|
||||||
(l/derived :workspace-page st/state))
|
(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
|
(def workspace-page-id
|
||||||
(l/derived :id workspace-page))
|
(l/derived :id workspace-page))
|
||||||
|
|
||||||
|
@ -71,6 +77,9 @@
|
||||||
(def workspace-objects
|
(def workspace-objects
|
||||||
(l/derived :objects workspace-data))
|
(l/derived :objects workspace-data))
|
||||||
|
|
||||||
|
(def workspace-frames
|
||||||
|
(l/derived cp/select-frames workspace-objects))
|
||||||
|
|
||||||
(defn object-by-id
|
(defn object-by-id
|
||||||
[id]
|
[id]
|
||||||
(letfn [(selector [state]
|
(letfn [(selector [state]
|
||||||
|
|
|
@ -73,7 +73,8 @@
|
||||||
[:& viewport {:page page
|
[:& viewport {:page page
|
||||||
:key (:id page)
|
:key (:id page)
|
||||||
:file file
|
:file file
|
||||||
:local local}]]]
|
:local local
|
||||||
|
:layout layout}]]]
|
||||||
|
|
||||||
[:& left-toolbar {:page page :layout layout}]
|
[:& left-toolbar {:page page :layout layout}]
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,15 @@
|
||||||
(:require
|
(:require
|
||||||
[rumext.alpha :as mf]
|
[rumext.alpha :as mf]
|
||||||
[uxbox.main.refs :as refs]
|
[uxbox.main.refs :as refs]
|
||||||
|
[uxbox.common.pages :as cp]
|
||||||
|
[uxbox.util.geom.shapes :as gsh]
|
||||||
[uxbox.util.geom.layout :as ula]))
|
[uxbox.util.geom.layout :as ula]))
|
||||||
|
|
||||||
(mf/defc grid-layout [{:keys [frame zoom layout] :as props}]
|
(mf/defc grid-layout [{:keys [frame zoom layout] :as props}]
|
||||||
(let [{:keys [color size] :as params} (-> layout :params)
|
(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]
|
{frame-width :width frame-height :height :keys [x y]} frame]
|
||||||
[:g.grid
|
[:g.layout
|
||||||
[:*
|
[:*
|
||||||
(for [xs (range size frame-width size)]
|
(for [xs (range size frame-width size)]
|
||||||
[:line {:key (str (:id frame) "-y-" xs)
|
[:line {:key (str (:id frame) "-y-" xs)
|
||||||
|
@ -38,20 +40,20 @@
|
||||||
:stroke-opacity color-opacity
|
:stroke-opacity color-opacity
|
||||||
:stroke-width (str (/ 1 zoom))}}])]]))
|
: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)]
|
(let [{color-value :value color-opacity :opacity} (-> layout :params :color)]
|
||||||
(for [{:keys [x y width height]} (ula/layout-rects frame layout)]
|
[:g.layout
|
||||||
[:rect {:x x
|
(for [{:keys [x y width height]} (ula/layout-rects frame layout)]
|
||||||
:y y
|
[:rect {:key (str key "-" x "-" y)
|
||||||
:width width
|
:x x
|
||||||
:height height
|
:y y
|
||||||
:style {:pointer-events "none"
|
:width width
|
||||||
:fill color-value
|
:height height
|
||||||
:opacity color-opacity}}])))
|
:style {:fill color-value
|
||||||
|
:opacity color-opacity}}])]))
|
||||||
|
|
||||||
(mf/defc layout-display [{:keys [frame]}]
|
(mf/defc layout-display-frame [{:keys [frame zoom]}]
|
||||||
(let [zoom (mf/deref refs/selected-zoom)
|
(let [layouts (:layouts frame)]
|
||||||
layouts (:layouts frame)]
|
|
||||||
(for [[index {:keys [type display] :as layout}] (map-indexed vector layouts)]
|
(for [[index {:keys [type display] :as layout}] (map-indexed vector layouts)]
|
||||||
(let [props #js {:key (str (:id frame) "-layout-" index)
|
(let [props #js {:key (str (:id frame) "-layout-" index)
|
||||||
:frame frame
|
:frame frame
|
||||||
|
@ -62,3 +64,12 @@
|
||||||
:square [:> grid-layout props]
|
:square [:> grid-layout props]
|
||||||
:column [:> flex-layout props]
|
:column [:> flex-layout props]
|
||||||
:row [:> 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.geom.shapes :as geom]
|
||||||
[uxbox.util.dom :as dom]
|
[uxbox.util.dom :as dom]
|
||||||
[uxbox.main.streams :as ms]
|
[uxbox.main.streams :as ms]
|
||||||
[uxbox.util.timers :as ts]
|
[uxbox.util.timers :as ts]))
|
||||||
[uxbox.main.ui.workspace.layout-display :refer [layout-display]]))
|
|
||||||
|
|
||||||
(defn- frame-wrapper-factory-equals?
|
(defn- frame-wrapper-factory-equals?
|
||||||
[np op]
|
[np op]
|
||||||
|
@ -105,6 +104,5 @@
|
||||||
(:name shape)]
|
(:name shape)]
|
||||||
[:& frame-shape
|
[:& frame-shape
|
||||||
{:shape shape
|
{:shape shape
|
||||||
:childs childs}]
|
:childs childs}]])))))
|
||||||
[:& layout-display {:frame shape}]])))))
|
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,9 @@
|
||||||
[rumext.alpha :as mf]
|
[rumext.alpha :as mf]
|
||||||
[uxbox.util.dom :as dom]
|
[uxbox.util.dom :as dom]
|
||||||
[uxbox.util.data :as d]
|
[uxbox.util.data :as d]
|
||||||
|
[uxbox.common.data :refer [parse-integer]]
|
||||||
[uxbox.main.store :as st]
|
[uxbox.main.store :as st]
|
||||||
|
[uxbox.main.refs :as refs]
|
||||||
[uxbox.main.data.workspace :as dw]
|
[uxbox.main.data.workspace :as dw]
|
||||||
[uxbox.main.ui.icons :as i]
|
[uxbox.main.ui.icons :as i]
|
||||||
[uxbox.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
|
[uxbox.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
|
||||||
|
@ -29,27 +31,8 @@
|
||||||
[:div.advanced-options {}
|
[:div.advanced-options {}
|
||||||
children]]))
|
children]]))
|
||||||
|
|
||||||
(defonce ^:private default-params
|
(mf/defc layout-options [{:keys [layout default-layout-params on-change on-remove]}]
|
||||||
{:square {:size 16
|
(prn "(render) layout" layout)
|
||||||
: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]}]
|
|
||||||
(let [state (mf/use-state {:show-advanced-options false
|
(let [state (mf/use-state {:show-advanced-options false
|
||||||
:changes {}})
|
:changes {}})
|
||||||
{:keys [type display params] :as layout} (d/deep-merge layout (:changes @state))
|
{:keys [type display params] :as layout} (d/deep-merge layout (:changes @state))
|
||||||
|
@ -61,17 +44,18 @@
|
||||||
18 12 10 8 6 4 3 2]
|
18 12 10 8 6 4 3 2]
|
||||||
|
|
||||||
emit-changes! (fn [update-fn]
|
emit-changes! (fn [update-fn]
|
||||||
(swap! state update :changes update-fn)
|
(swap! state update :changes update-fn)
|
||||||
(when on-change (on-change (d/deep-merge layout (-> @state :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]
|
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]
|
handle-remove-layout (fn [event]
|
||||||
(when on-remove (on-remove)))
|
(when on-remove (on-remove)))
|
||||||
|
|
||||||
handle-change-type (fn [type]
|
handle-change-type (fn [type]
|
||||||
(let [defaults (type default-params)
|
(let [defaults (type default-layout-params)
|
||||||
params (merge
|
params (merge
|
||||||
defaults
|
defaults
|
||||||
(select-keys (keys defaults) (-> @state :changes params)))
|
(select-keys (keys defaults) (-> @state :changes params)))
|
||||||
|
@ -85,7 +69,7 @@
|
||||||
handle-change-event (fn [& keys]
|
handle-change-event (fn [& keys]
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [change-fn (apply handle-change keys)]
|
(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
|
[:div.grid-option
|
||||||
|
@ -169,20 +153,45 @@
|
||||||
[:button.btn-options "Use default"]
|
[:button.btn-options "Use default"]
|
||||||
[:button.btn-options "Set as 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]}]
|
(mf/defc frame-layouts [{:keys [shape]}]
|
||||||
(let [id (:id 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-create-layout #(st/emit! (dw/add-frame-layout id))
|
||||||
handle-remove-layout (fn [index] #(st/emit! (dw/remove-frame-layout id index)))
|
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
|
||||||
[:div.element-set-title
|
[:div.element-set-title
|
||||||
[:span "Grid & Layout"]
|
[:span "Grid & Layout"]
|
||||||
[:div.add-page {:on-click handle-create-layout} i/close]]
|
[:div.add-page {:on-click handle-create-layout} i/close]]
|
||||||
|
|
||||||
[:div.element-set-content
|
(when (not (empty? (:layouts shape)))
|
||||||
(for [[index layout] (map-indexed vector (:layouts shape))]
|
[:div.element-set-content
|
||||||
[:& layout-options {:key (str (:id shape) "-" index)
|
(for [[index layout] (map-indexed vector (:layouts shape))]
|
||||||
:layout layout
|
[:& layout-options {:key (str (:id shape) "-" index)
|
||||||
:on-change (handle-edit-layout index)
|
:layout layout
|
||||||
:on-remove (handle-remove-layout index)}])]]))
|
: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 :refer [shape-wrapper frame-wrapper]]
|
||||||
[uxbox.main.ui.workspace.shapes.interactions :refer [interactions]]
|
[uxbox.main.ui.workspace.shapes.interactions :refer [interactions]]
|
||||||
[uxbox.main.ui.workspace.drawarea :refer [draw-area start-drawing]]
|
[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.selection :refer [selection-handlers]]
|
||||||
[uxbox.main.ui.workspace.presence :as presence]
|
[uxbox.main.ui.workspace.presence :as presence]
|
||||||
[uxbox.main.ui.workspace.snap-feedback :refer [snap-feedback]]
|
[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.math :as mth]
|
||||||
[uxbox.util.dom :as dom]
|
[uxbox.util.dom :as dom]
|
||||||
[uxbox.util.object :as obj]
|
[uxbox.util.object :as obj]
|
||||||
|
@ -127,7 +126,7 @@
|
||||||
:key (:id item)}]))]))
|
:key (:id item)}]))]))
|
||||||
|
|
||||||
(mf/defc viewport
|
(mf/defc viewport
|
||||||
[{:keys [page local] :as props}]
|
[{:keys [page local layout] :as props}]
|
||||||
(let [{:keys [drawing-tool
|
(let [{:keys [drawing-tool
|
||||||
options-mode
|
options-mode
|
||||||
zoom
|
zoom
|
||||||
|
@ -354,6 +353,7 @@
|
||||||
]
|
]
|
||||||
|
|
||||||
(mf/use-effect on-mount)
|
(mf/use-effect on-mount)
|
||||||
|
|
||||||
[:svg.viewport
|
[:svg.viewport
|
||||||
{:preserveAspectRatio "xMidYMid meet"
|
{:preserveAspectRatio "xMidYMid meet"
|
||||||
:width (:width vport 0)
|
:width (:width vport 0)
|
||||||
|
@ -381,22 +381,18 @@
|
||||||
:zoom zoom
|
:zoom zoom
|
||||||
:edition edition}])
|
:edition edition}])
|
||||||
|
|
||||||
|
|
||||||
(when-let [drawing-shape (:drawing local)]
|
(when-let [drawing-shape (:drawing local)]
|
||||||
[:& draw-area {:shape drawing-shape
|
[:& draw-area {:shape drawing-shape
|
||||||
:zoom zoom
|
:zoom zoom
|
||||||
:modifiers (:modifiers local)}])
|
:modifiers (:modifiers local)}])
|
||||||
|
|
||||||
|
(when (contains? layout :layouts)
|
||||||
|
[:& layout-display {:zoom zoom}])
|
||||||
|
|
||||||
[:& snap-feedback]
|
[:& snap-feedback]
|
||||||
|
|
||||||
(when (contains? flags :grid)
|
(when tooltip
|
||||||
[:& grid])]
|
[:& cursor-tooltip {:zoom zoom :tooltip tooltip}])]
|
||||||
|
|
||||||
(when tooltip
|
|
||||||
[:& cursor-tooltip {:zoom zoom :tooltip tooltip}])
|
|
||||||
|
|
||||||
(when (contains? flags :ruler)
|
|
||||||
[:& ruler {:zoom zoom :ruler (:ruler local)}])
|
|
||||||
|
|
||||||
[:& presence/active-cursors {:page page}]
|
[:& presence/active-cursors {:page page}]
|
||||||
[:& selection-rect {:data (:selrect local)}]
|
[:& selection-rect {:data (:selrect local)}]
|
||||||
|
|
|
@ -7,7 +7,9 @@
|
||||||
;;
|
;;
|
||||||
;; Copyright (c) 2020 UXBOX Labs SL
|
;; 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}]
|
(defn calculate-column-layout [{:keys [width height x y] :as frame} {:keys [size gutter margin item-width type] :as params}]
|
||||||
(let [parts (/ width size)
|
(let [parts (/ width size)
|
||||||
|
@ -20,7 +22,7 @@
|
||||||
gutter (if (= :stretch type) (/ (- width (* item-width size) (* margin 2)) (dec size)) gutter)
|
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-x (fn [cur-val] (+ initial-offset x (* (+ item-width gutter) cur-val)))
|
||||||
next-y (fn [cur-val] y)]
|
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}]
|
(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
|
(let [{:keys [width height x y]} frame
|
||||||
|
@ -34,16 +36,51 @@
|
||||||
gutter (if (= :stretch type) (/ (- height (* item-height size) (* margin 2)) (dec size)) gutter)
|
gutter (if (= :stretch type) (/ (- height (* item-height size) (* margin 2)) (dec size)) gutter)
|
||||||
next-x (fn [cur-val] x)
|
next-x (fn [cur-val] x)
|
||||||
next-y (fn [cur-val] (+ initial-offset y (* (+ item-height gutter) cur-val)))]
|
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]
|
(defn layout-rects [frame layout]
|
||||||
(let [[item-width item-height next-x next-y]
|
(let [layout-fn (case (-> layout :type)
|
||||||
(case (-> layout :type)
|
:column calculate-column-layout
|
||||||
:column (calculate-column-layout frame (-> layout :params))
|
:row calculate-row-layout
|
||||||
:row (calculate-row-layout frame (-> layout :params)))]
|
: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 %)
|
(map #(hash-map :x (next-x %)
|
||||||
:y (next-y %)
|
:y (next-y %)
|
||||||
:width item-width
|
:width item-width
|
||||||
:height item-height)))))
|
: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]
|
[cljs.spec.alpha :as s]
|
||||||
[clojure.set :as set]
|
[clojure.set :as set]
|
||||||
[uxbox.util.geom.shapes :as gsh]
|
[uxbox.util.geom.shapes :as gsh]
|
||||||
[uxbox.util.geom.point :as gpt]
|
[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)))
|
|
||||||
|
|
||||||
(defn- frame-snap-points [{:keys [x y width height layouts] :as frame}]
|
(defn- frame-snap-points [{:keys [x y width height layouts] :as frame}]
|
||||||
(into #{(gpt/point x y)
|
(into #{(gpt/point x y)
|
||||||
|
@ -32,11 +22,7 @@
|
||||||
(gpt/point (+ x width) (+ y height))
|
(gpt/point (+ x width) (+ y height))
|
||||||
(gpt/point (+ x (/ width 2)) (+ y height))
|
(gpt/point (+ x (/ width 2)) (+ y height))
|
||||||
(gpt/point x (+ y height))
|
(gpt/point x (+ y height))
|
||||||
(gpt/point x (+ y (/ height 2)))}
|
(gpt/point x (+ y (/ height 2)))}))
|
||||||
(->>
|
|
||||||
layouts
|
|
||||||
(filter #(and (not= :grid (:type %)) (:display %)))
|
|
||||||
(mapcat #(layout-snap-points frame %)))))
|
|
||||||
|
|
||||||
(defn shape-snap-points
|
(defn shape-snap-points
|
||||||
[shape]
|
[shape]
|
||||||
|
|
|
@ -14,7 +14,8 @@
|
||||||
[uxbox.common.pages :as cp]
|
[uxbox.common.pages :as cp]
|
||||||
[uxbox.worker.impl :as impl]
|
[uxbox.worker.impl :as impl]
|
||||||
[uxbox.util.range-tree :as rt]
|
[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 {}))
|
(defonce state (l/atom {}))
|
||||||
|
|
||||||
|
@ -23,8 +24,11 @@
|
||||||
[shapes coord]
|
[shapes coord]
|
||||||
(let [process-shape (fn [coord]
|
(let [process-shape (fn [coord]
|
||||||
(fn [shape]
|
(fn [shape]
|
||||||
(let [points (snap/shape-snap-points shape)]
|
(concat
|
||||||
(map #(vector % (:id shape)) points))))
|
(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]]
|
into-tree (fn [tree [point _ :as data]]
|
||||||
(rt/insert tree (coord point) data))]
|
(rt/insert tree (coord point) data))]
|
||||||
(->> shapes
|
(->> shapes
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue