0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-09 00:10:11 -05:00

Add initial approach for grid alignment.

A little bit buggy because the main algorithm
does not works well.
This commit is contained in:
Andrey Antukh 2016-04-10 18:45:20 +03:00
parent 051163c3ae
commit 935bafd512
No known key found for this signature in database
GPG key ID: 4DFEBCB8316A8B95
6 changed files with 245 additions and 19 deletions

View file

@ -0,0 +1,32 @@
;; 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) 2016 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.data.worker
"Worker related api and initialization events."
(:require [beicon.core :as rx]
[uxbox.rstore :as rs]
[uxbox.constants :as c]
[uxbox.util.workers :as uw]))
(defonce worker (uw/init "/js/worker.js"))
;; --- Worker Initialization
(defrecord InitializeWorker [id]
rs/EffectEvent
(-apply-effect [_ state]
(let [page (get-in state [:pages-by-id id])
opts (:options page)
message {:cmd :grid/init
:width c/viewport-width
:height c/viewport-height
:x-axis (:grid/x-axis opts c/grid-x-axis)
:y-axis (:grid/y-axis opts c/grid-y-axis)}]
(uw/send! worker message))))
(defn initialize
[id]
(InitializeWorker. id))

View file

@ -14,31 +14,41 @@
[uxbox.schema :as sc]
[uxbox.data.pages :as udp]
[uxbox.data.shapes :as uds]
;; [uxbox.data.worker :as wrk]
[uxbox.data.worker :as wrk]
[uxbox.util.datetime :as dt]
[uxbox.util.geom.point :as gpt]))
;; --- Workspace Initialization
(defrecord InitializeWorkspace [project page]
rs/UpdateEvent
(-apply-update [_ state]
(if (:workspace state)
(update state :workspace merge
{:project project
:page page
:selected #{}
:drawing nil})
(assoc state :workspace
{:project project
:zoom 1
:page page
:flags #{:layers :element-options}
:selected #{}
:drawing nil})))
rs/WatchEvent
(-apply-watch [_ state s]
(if (get-in state [:pages-by-id page])
(rx/of (wrk/initialize page))
(->> (rx/filter udp/pages-fetched? s)
(rx/take 1)
(rx/map #(wrk/initialize page))))))
(defn initialize
"Initialize the workspace state."
[project page]
(reify
rs/UpdateEvent
(-apply-update [_ state]
(if (:workspace state)
(update state :workspace merge
{:project project
:page page
:selected #{}
:drawing nil})
(assoc state :workspace
{:project project
:zoom 1
:page page
:flags #{:layers :element-options}
:selected #{}
:drawing nil})))))
(InitializeWorkspace. project page))
(defn toggle-flag
"Toggle the enabled flag of the specified tool."

View file

@ -0,0 +1,37 @@
;; 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) 2016 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.ui.workspace.align
"Shape alignmen impl."
(:require [beicon.core :as rx]
[lentes.core :as l]
[uxbox.state :as st]
[uxbox.shapes :as sh]
[uxbox.data.worker :refer (worker)]
[uxbox.ui.workspace.base :as wb]
[uxbox.util.geom.point :as gpt]
[uxbox.util.workers :as uw]))
(defn- move
[shape p1]
(let [dx (- (:x2 shape) (:x1 shape))
dy (- (:y2 shape) (:y1 shape))
p2 (gpt/add p1 [dx dy])]
(assoc shape
:x1 (:x p1)
:y1 (:y p1)
:x2 (:x p2)
:y2 (:y p2))))
(defn translate
[{:keys [x1 y1] :as shape}]
(let [message {:cmd :grid/align
:point (gpt/point x1 y1)}]
(->> (uw/ask! worker message)
(rx/map (fn [{:keys [point]}]
(if point
(move shape point)
shape))))))

View file

@ -9,6 +9,7 @@
"Shape movement in workspace logic."
(:require [beicon.core :as rx]
[lentes.core :as l]
[uxbox.constants :as c]
[uxbox.rstore :as rs]
[uxbox.state :as st]
[uxbox.shapes :as sh]
@ -23,16 +24,24 @@
;; --- Lenses
(declare translate-to-viewport)
(defn- resolve-selected
[state]
(let [selected (get-in state [:workspace :selected])
xf (map #(get-in state [:shapes-by-id %]))]
xf (comp
(map #(get-in state [:shapes-by-id %]))
(map translate-to-viewport))]
(into #{} xf selected)))
(def ^:const ^:private selected-shapes-l
(-> (l/getter resolve-selected)
(l/focus-atom st/state)))
(def ^:const ^:privae page-options-l
(-> (l/key :options)
(l/focus-atom wb/page-l)))
;; --- Public Api
(defn watch-move-actions
@ -43,9 +52,40 @@
;; --- Implementation
(def coords
(gpt/point c/canvas-start-x
c/canvas-start-y))
(defn- translate-to-viewport
[shape]
(let [dx (- (:x2 shape) (:x1 shape))
dy (- (:y2 shape) (:y1 shape))
p1 (gpt/point (:x1 shape) (:y1 shape))
p2 (gpt/add p1 coords)
p3 (gpt/add p2 [dx dy])]
(assoc shape
:x1 (:x p2)
:y1 (:y p2)
:x2 (:x p3)
:y2 (:y p3))))
(defn- translate-to-canvas
[shape]
(let [dx (- (:x2 shape) (:x1 shape))
dy (- (:y2 shape) (:y1 shape))
p1 (gpt/point (:x1 shape) (:y1 shape))
p2 (gpt/subtract p1 coords)
p3 (gpt/add p2 [dx dy])]
(assoc shape
:x1 (:x p2)
:y1 (:y p2)
:x2 (:x p3)
:y2 (:y p3))))
(defn- initialize
[]
(let [shapes @selected-shapes-l
options @page-options-l
stoper (->> uuc/actions-s
(rx/map :type)
(rx/filter empty?)
@ -53,7 +93,17 @@
(as-> wb/mouse-delta-s $
(rx/take-until stoper $)
(rx/scan (fn [acc delta]
(mapv #(sh/move % delta) acc)) shapes $)
(let [xf (map #(sh/move % delta))]
(into [] xf acc))) shapes $)
(rx/mapcat (fn [items]
(if (:grid/align options)
(->> (apply rx/of items)
(rx/mapcat align/translate)
(rx/reduce conj []))
(rx/of items))) $)
(rx/map (fn [items]
(mapv translate-to-canvas items)) $)
(rx/subscribe $ handle-movement))))
(defn- handle-movement
@ -61,3 +111,4 @@
(doseq [shape delta]
(rs/emit! (uds/update-shape shape))))

View file

@ -0,0 +1,62 @@
;; 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) 2016 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.util.workers
"A lightweight layer on top of webworkers api."
(:require [beicon.core :as rx]
[uxbox.util.transit :as t]))
;; --- Implementation
(defprotocol IWorker
(-ask [_ msg] "Send and receive message as rx stream.")
(-send [_ msg] "Send message and forget."))
(deftype WebWorker [stream wrk]
IWorker
(-ask [this message]
(let [sender (random-uuid)
data (assoc message :sender sender)
data (t/encode data)]
(.postMessage wrk data)
(->> stream
(rx/filter #(= (:reply-to %) sender))
(rx/take 1))))
(-send [this message]
(let [sender (random-uuid)
data (assoc message :sender sender)
data (t/encode data)]
(.postMessage wrk data)
(->> stream
(rx/filter #(= (:reply-to %) sender))))))
;; --- Public Api
(defn init
"Return a initialized webworker instance."
[path]
(let [wrk (js/Worker. path)
bus (rx/bus)]
(.addEventListener wrk "message"
(fn [event]
(let [data (.-data event)
data (t/decode data)]
(rx/push! bus data))))
(.addEventListener wrk "error"
(fn [event]
(rx/error! bus event)))
(WebWorker. (rx/map identity bus) wrk)))
(defn ask!
[wrk message]
(-ask wrk message))
(defn send!
[wrk message]
(-send wrk message))

View file

@ -0,0 +1,34 @@
;; 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) 2016 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.worker.align
"Workspace aligment indexes worker."
(:require [beicon.core :as rx]
[kdtree :as kd]
[uxbox.worker.core :as wrk]
[uxbox.util.geom.point :as gpt]))
(defonce state (volatile! nil))
(defmethod wrk/handler :grid/init
[{:keys [width height x-axis y-axis] :as opts}]
(println ":grid/init" opts)
(let [points (into-array
(for [x (range 0 width (or x-axis 10))
y (range 0 height (or y-axis 10))]
#js [x y]))
tree (kd/create2d points)]
(vreset! state tree)))
(defmethod wrk/handler :grid/align
[{:keys [sender point] :as message}]
(println "request" point)
(let [point #js [(:x point) (:y point)]
results (js->clj (.nearest @state point 1))
[[x y] d] (first results)
result (gpt/point x y)]
(println "result:" result)
(wrk/reply! sender {:point (gpt/point x y)})))