0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-15 17:21:17 -05:00

Many performance improvements on workspace.

This commit is contained in:
Andrey Antukh 2017-01-31 17:02:33 +01:00
parent 3fdce853d0
commit 6c1955c0d9
No known key found for this signature in database
GPG key ID: 4DFEBCB8316A8B95
12 changed files with 120 additions and 127 deletions

View file

@ -53,6 +53,7 @@
:page page :page page
:selected #{} :selected #{}
:drawing nil :drawing nil
:drawing-tool nil
:tooltip nil}) :tooltip nil})
(assoc state :workspace (assoc state :workspace
{:project project {:project project
@ -61,6 +62,7 @@
:flags #{:sitemap :drawtools :layers :element-options} :flags #{:sitemap :drawtools :layers :element-options}
:selected #{} :selected #{}
:drawing nil :drawing nil
:drawing-tool nil
:tooltip nil}))) :tooltip nil})))
ptk/WatchEvent ptk/WatchEvent

View file

@ -33,8 +33,10 @@
(let [current (l/focus ul/selected-drawing state)] (let [current (l/focus ul/selected-drawing state)]
(if (or (nil? shape) (if (or (nil? shape)
(= shape current)) (= shape current))
(update state :workspace dissoc :drawing) (update state :workspace dissoc :drawing :drawing-tool)
(assoc-in state [:workspace :drawing] shape))))) (update state :workspace assoc
:drawing shape
:drawing-tool shape)))))
(defn select-for-drawing (defn select-for-drawing
[shape] [shape]
@ -105,9 +107,8 @@
(deftype FinishDrawing [] (deftype FinishDrawing []
ptk/WatchEvent ptk/WatchEvent
(watch [_ state stream] (watch [_ state stream]
(println "finish-drawing" (get-in state [:workspace :drawing]))
(if-let [shape (get-in state [:workspace :drawing])] (if-let [shape (get-in state [:workspace :drawing])]
(rx/of #(update % :workspace dissoc :drawing) (rx/of #(update % :workspace dissoc :drawing :drawing-tool)
(uds/add-shape shape) (uds/add-shape shape)
(uds/select-first-shape) (uds/select-first-shape)
::uev/interrupt) ::uev/interrupt)
@ -197,11 +198,9 @@
(defn- translate-to-canvas (defn- translate-to-canvas
[point] [point]
(let [zoom @refs/selected-zoom (-> point
ccords (gpt/multiply canvas-coords zoom)] (gpt/subtract (gpt/multiply canvas-coords @refs/selected-zoom))
(-> point (gpt/divide @refs/selected-zoom)))
(gpt/subtract ccords)
(gpt/divide zoom))))
(declare on-init-draw-icon) (declare on-init-draw-icon)
(declare on-init-draw-path) (declare on-init-draw-path)
@ -302,7 +301,7 @@
(defn- on-init-draw-free-path (defn- on-init-draw-free-path
[shape stoper] [shape stoper]
(let [stoper (get-path-stoper-stream stoper true) (let [stoper (get-path-stoper-stream stoper true)
mouse (->> (rx/sample 10 streams/viewport-mouse-position) mouse (->> streams/viewport-mouse-position
(rx/mapcat conditional-align) (rx/mapcat conditional-align)
(rx/map translate-to-canvas)) (rx/map translate-to-canvas))

View file

@ -64,6 +64,9 @@
(defn render-page (defn render-page
[id] [id]
(let [page (get-in @*state* [:pages id])] (try
(when (:shapes page) (let [page (get-in @*state* [:pages id])]
(mx/render-static-html (page-svg page))))) (when (:shapes page)
(mx/render-static-html (page-svg page))))
(catch :default e
nil)))

View file

@ -62,6 +62,14 @@
(-> (l/key :zoom) (-> (l/key :zoom)
(l/derive workspace))) (l/derive workspace)))
(def selected-tooltip
(-> (l/key :tooltip)
(l/derive workspace)))
(def selected-drawing-tool
(-> (l/key :drawing-tool)
(l/derive workspace)))
(defn alignment-activated? (defn alignment-activated?
[state] [state]
(let [flags (l/focus ul/workspace-flags state)] (let [flags (l/focus ul/workspace-flags state)]

View file

@ -52,6 +52,7 @@
"A default error handler." "A default error handler."
[{:keys [status] :as error}] [{:keys [status] :as error}]
(js/console.log "on-error:" (pr-str error)) (js/console.log "on-error:" (pr-str error))
(js/console.log "stack:" (.-stack error))
(reset! st/loader false) (reset! st/loader false)
(cond (cond
;; Unauthorized or Auth timeout ;; Unauthorized or Auth timeout

View file

@ -21,12 +21,13 @@
;; --- Refs ;; --- Refs
(def edition-ref (def edition-ref
(-> (l/in [:workspace :edition]) (-> (l/in [:edition])
(l/derive st/state))) (l/derive refs/workspace)))
;; TODO: replace with refs/selected-drawing-tool
(def drawing-state-ref (def drawing-state-ref
(-> (l/in [:workspace :drawing]) (-> (l/key :drawing-tool)
(l/derive st/state))) (l/derive refs/workspace)))
(def selected-ref (def selected-ref
(-> (l/in [:selected]) (-> (l/in [:selected])

View file

@ -8,6 +8,7 @@
(ns uxbox.main.ui.workspace (ns uxbox.main.ui.workspace
(:require [beicon.core :as rx] (:require [beicon.core :as rx]
[potok.core :as ptk] [potok.core :as ptk]
[lentes.core :as l]
[uxbox.main.store :as st] [uxbox.main.store :as st]
[uxbox.main.constants :as c] [uxbox.main.constants :as c]
[uxbox.main.refs :as refs] [uxbox.main.refs :as refs]
@ -97,6 +98,10 @@
(st/emit! (dw/decrease-zoom))) (st/emit! (dw/decrease-zoom)))
(scroll/scroll-to-point dom mouse-point scroll-position)))) (scroll/scroll-to-point dom mouse-point scroll-position))))
(def ^:private workspace-page-ref
(-> (l/key :page)
(l/derive refs/workspace)))
(mx/defcs workspace (mx/defcs workspace
{:did-remount workspace-did-remount {:did-remount workspace-did-remount
:will-mount workspace-will-mount :will-mount workspace-will-mount
@ -104,15 +109,15 @@
:did-mount workspace-did-mount :did-mount workspace-did-mount
:mixins [mx/static :mixins [mx/static
mx/reactive mx/reactive
shortcuts-mixin shortcuts-mixin]}
(mx/local)]}
[own] [own]
(let [{:keys [flags zoom page] :as workspace} (mx/react refs/workspace) (let [flags (mx/react refs/flags)
page (mx/react workspace-page-ref)
left-sidebar? (not (empty? (keep flags [:layers :sitemap left-sidebar? (not (empty? (keep flags [:layers :sitemap
:document-history]))) :document-history])))
right-sidebar? (not (empty? (keep flags [:icons :drawtools right-sidebar? (not (empty? (keep flags [:icons :drawtools
:element-options]))) :element-options])))
local (:rum/local own)
classes (classnames classes (classnames
:no-tool-bar-right (not right-sidebar?) :no-tool-bar-right (not right-sidebar?)
:no-tool-bar-left (not left-sidebar?) :no-tool-bar-left (not left-sidebar?)
@ -123,7 +128,6 @@
(colorpalette) (colorpalette)
[:main.main-content [:main.main-content
[:section.workspace-content [:section.workspace-content
{:class classes {:class classes
:on-scroll on-scroll :on-scroll on-scroll
@ -133,8 +137,8 @@
(history-dialog page) (history-dialog page)
;; Rules ;; Rules
(horizontal-rule zoom) (horizontal-rule)
(vertical-rule zoom) (vertical-rule)
;; Canvas ;; Canvas
[:section.workspace-canvas [:section.workspace-canvas

View file

@ -103,11 +103,9 @@
;; --- Canvas ;; --- Canvas
(mx/defc canvas (mx/defc canvas
{:mixins [mx/reactive]} {:mixins [mx/static mx/reactive]}
[{:keys [metadata id] :as page}] [{:keys [metadata id] :as page}]
(let [workspace (mx/react refs/workspace) (let [width (:width metadata)
flags (:flags workspace)
width (:width metadata)
height (:height metadata)] height (:height metadata)]
[:svg.page-canvas {:x c/canvas-start-x [:svg.page-canvas {:x c/canvas-start-x
:y c/canvas-start-y :y c/canvas-start-y
@ -201,14 +199,12 @@
:will-unmount viewport-will-unmount :will-unmount viewport-will-unmount
:mixins [mx/reactive]} :mixins [mx/reactive]}
[] []
(let [workspace (mx/react refs/workspace) (let [page (mx/react refs/selected-page)
page (mx/react refs/selected-page) flags (mx/react refs/flags)
flags (:flags workspace) drawing (mx/react refs/selected-drawing-tool)
drawing? (:drawing workspace) tooltip (or (mx/react refs/selected-tooltip)
tooltip (if (:tooltip workspace) (get-shape-tooltip drawing))
(:tooltip workspace) zoom (or (mx/react refs/selected-zoom) 1)]
(get-shape-tooltip drawing?))
zoom (or (:zoom workspace) 1)]
(letfn [(on-mouse-down [event] (letfn [(on-mouse-down [event]
(dom/stop-propagation event) (dom/stop-propagation event)
(let [ctrl? (kbd/ctrl? event) (let [ctrl? (kbd/ctrl? event)
@ -216,8 +212,8 @@
opts {:shift? shift? opts {:shift? shift?
:ctrl? ctrl?}] :ctrl? ctrl?}]
(st/emit! (uev/mouse-event :down ctrl? shift?))) (st/emit! (uev/mouse-event :down ctrl? shift?)))
(if-let [object (:drawing workspace)] (if drawing
(st/emit! (udw/start-drawing object)) (st/emit! (udw/start-drawing drawing))
(st/emit! (udw/start-selrect)))) (st/emit! (udw/start-selrect))))
(on-context-menu [event] (on-context-menu [event]
(dom/prevent-default event) (dom/prevent-default event)
@ -255,7 +251,7 @@
[:svg.viewport {:width (* c/viewport-width zoom) [:svg.viewport {:width (* c/viewport-width zoom)
:height (* c/viewport-height zoom) :height (* c/viewport-height zoom)
:ref "viewport" :ref "viewport"
:class (when drawing? "drawing") :class (when drawing "drawing")
:on-context-menu on-context-menu :on-context-menu on-context-menu
:on-click on-click :on-click on-click
:on-double-click on-double-click :on-double-click on-double-click

View file

@ -6,8 +6,7 @@
;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com> ;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
(ns uxbox.main.ui.workspace.rules (ns uxbox.main.ui.workspace.rules
(:require [sablono.core :as html :refer-macros [html]] (:require [sablono.core :refer-macros [html]]
[rum.core :as rum]
[cuerdas.core :as str] [cuerdas.core :as str]
[beicon.core :as rx] [beicon.core :as rx]
[uxbox.main.store :as s] [uxbox.main.store :as s]
@ -104,84 +103,62 @@
;; --- Horizontal Rule Ticks (Component) ;; --- Horizontal Rule Ticks (Component)
(defn- horizontal-rule-ticks-render (mx/defc horizontal-rule-ticks
[own zoom] {:mixins [mx/static]}
[zoom]
(let [zoom (or zoom 1) (let [zoom (or zoom 1)
path (reduce (partial make-vertical-tick zoom) [] +ticks+) path (reduce (partial make-vertical-tick zoom) [] +ticks+)
labels (->> (map (partial horizontal-text-label zoom) +ticks+) labels (->> (map (partial horizontal-text-label zoom) +ticks+)
(filterv identity))] (filterv identity))]
(html [:g
[:g [:path {:d (str/join " " path) :stroke "#9da2a6"}]
[:path {:d (str/join " " path) :stroke "#9da2a6"}] labels]))
labels])))
(def ^:private horizontal-rule-ticks
(mx/component
{:render horizontal-rule-ticks-render
:name "horizontal-rule-ticks"
:mixins [mx/static]}))
;; --- Vertical Rule Ticks (Component) ;; --- Vertical Rule Ticks (Component)
(defn- vertical-rule-ticks-render (mx/defc vertical-rule-ticks
[own zoom] {:mixins [mx/static]}
[zoom]
(let [zoom (or zoom 1) (let [zoom (or zoom 1)
path (reduce (partial make-horizontal-tick zoom) [] +ticks+) path (reduce (partial make-horizontal-tick zoom) [] +ticks+)
labels (->> (map (partial vertical-text-label zoom) +ticks+) labels (->> (map (partial vertical-text-label zoom) +ticks+)
(filterv identity))] (filterv identity))]
(html [:g
[:g [:path {:d (str/join " " path) :stroke "#9da2a6"}]
[:path {:d (str/join " " path) :stroke "#9da2a6"}] labels]))
labels])))
(def ^:private vertical-rule-ticks
(mx/component
{:render vertical-rule-ticks-render
:name "vertical-rule-ticks"
:mixins [mx/static]}))
;; --- Horizontal Rule (Component) ;; --- Horizontal Rule (Component)
(defn horizontal-rule-render (mx/defc horizontal-rule
[own zoom] {:mixins [mx/static mx/reactive]}
[]
(let [scroll (mx/react refs/workspace-scroll) (let [scroll (mx/react refs/workspace-scroll)
zoom (mx/react refs/selected-zoom)
scroll-x (:x scroll) scroll-x (:x scroll)
translate-x (- (- c/canvas-scroll-padding) (:x scroll))] translate-x (- (- c/canvas-scroll-padding) (:x scroll))]
(html [:svg.horizontal-rule
[:svg.horizontal-rule {:width c/viewport-width
{:width c/viewport-width :height 20}
:height 20} [:g {:transform (str "translate(" translate-x ", 0)")}
[:g {:transform (str "translate(" translate-x ", 0)")} (horizontal-rule-ticks zoom)]]))
(horizontal-rule-ticks zoom)]])))
(def horizontal-rule
(mx/component
{:render horizontal-rule-render
:name "horizontal-rule"
:mixins [mx/static mx/reactive]}))
;; --- Vertical Rule (Component) ;; --- Vertical Rule (Component)
(defn vertical-rule-render (mx/defc vertical-rule
[own zoom] {:mixins [mx/static mx/reactive]}
[]
(let [scroll (mx/react refs/workspace-scroll) (let [scroll (mx/react refs/workspace-scroll)
zoom (mx/react refs/selected-zoom)
scroll-y (:y scroll) scroll-y (:y scroll)
translate-y (- (- c/canvas-scroll-padding) (:y scroll))] translate-y (- (- c/canvas-scroll-padding) (:y scroll))]
(html [:svg.vertical-rule
[:svg.vertical-rule {:width 20
{:width 20 :height c/viewport-height}
:height c/viewport-height}
[:g {:transform (str "translate(0, " translate-y ")")} [:g {:transform (str "translate(0, " translate-y ")")}
(vertical-rule-ticks zoom)] (vertical-rule-ticks zoom)]
[:rect {:x 0 [:rect {:x 0
:y 0 :y 0
:height 20 :height 20
:width 20 :width 20
:fill "rgb(233, 234, 235)"}]]))) :fill "rgb(233, 234, 235)"}]]))
(def vertical-rule
(mx/component
{:render vertical-rule-render
:name "vertical-rule"
:mixins [mx/static mx/reactive]}))

View file

@ -14,6 +14,7 @@
[uxbox.main.data.workspace :as dw] [uxbox.main.data.workspace :as dw]
[uxbox.main.user-events :as uev] [uxbox.main.user-events :as uev]
[uxbox.builtins.icons :as i] [uxbox.builtins.icons :as i]
[uxbox.util.uuid :as uuid]
[uxbox.util.i18n :refer (tr)] [uxbox.util.i18n :refer (tr)]
[uxbox.util.router :as r] [uxbox.util.router :as r]
[uxbox.util.data :refer (read-string)] [uxbox.util.data :refer (read-string)]
@ -22,27 +23,30 @@
;; --- Refs ;; --- Refs
(def ^:private drawing-shape (def ^:private drawing-shape-id-ref
"A focused vision of the drawing property "A focused vision of the drawing property
of the workspace status. This avoids of the workspace status. This avoids
rerender the whole toolbox on each workspace rerender the whole toolbox on each workspace
change." change."
(-> (l/in [:workspace :drawing]) (-> (l/key :drawing-tool)
(l/derive st/state))) (l/derive refs/workspace)))
;; --- Constants ;; --- Constants
(def +draw-tool-rect+ (def +draw-tool-rect+
{:type :rect {:type :rect
:id (uuid/random)
:name "Rect" :name "Rect"
:stroke-color "#000000"}) :stroke-color "#000000"})
(def +draw-tool-circle+ (def +draw-tool-circle+
{:type :circle {:type :circle
:id (uuid/random)
:name "Circle"}) :name "Circle"})
(def +draw-tool-path+ (def +draw-tool-path+
{:type :path {:type :path
:id (uuid/random)
:name "Path" :name "Path"
:stroke-style :solid :stroke-style :solid
:stroke-color "#000000" :stroke-color "#000000"
@ -52,8 +56,14 @@
;; :close? true ;; :close? true
:points []}) :points []})
(def +draw-tool-curve+
(assoc +draw-tool-path+
:id (uuid/random)
:free true))
(def +draw-tool-text+ (def +draw-tool-text+
{:type :text {:type :text
:id (uuid/random)
:name "Text" :name "Text"
:content "Hello world"}) :content "Hello world"})
@ -76,7 +86,7 @@
:priority 5} :priority 5}
{:icon i/pencil {:icon i/pencil
:help (tr "ds.help.path") :help (tr "ds.help.path")
:shape (assoc +draw-tool-path+ :free true) :shape +draw-tool-curve+
:priority 6}]) :priority 6}])
;; --- Draw Toolbox (Component) ;; --- Draw Toolbox (Component)
@ -88,9 +98,8 @@
(mx/defc draw-toolbox (mx/defc draw-toolbox
{:mixins [mx/static mx/reactive]} {:mixins [mx/static mx/reactive]}
[own] []
(let [workspace (mx/react refs/workspace) (let [drawing-tool (mx/react refs/selected-drawing-tool)
drawing (mx/react drawing-shape)
close #(st/emit! (dw/toggle-flag :drawtools)) close #(st/emit! (dw/toggle-flag :drawtools))
tools (->> (into [] +draw-tools+) tools (->> (into [] +draw-tools+)
(sort-by (comp :priority second)))] (sort-by (comp :priority second)))]
@ -101,7 +110,7 @@
[:div.tool-window-close {:on-click close} i/close]] [:div.tool-window-close {:on-click close} i/close]]
[:div.tool-window-content [:div.tool-window-content
(for [[i props] (map-indexed vector tools) (for [[i props] (map-indexed vector tools)
:let [selected? (= drawing (:shape props))]] :let [selected? (= drawing-tool (:shape props))]]
[:div.tool-btn.tooltip.tooltip-hover [:div.tool-btn.tooltip.tooltip-hover
{:alt (:help props) {:alt (:help props)
:class (when selected? "selected") :class (when selected? "selected")

View file

@ -151,24 +151,17 @@
;; --- History Dialog ;; --- History Dialog
(defn history-dialog-render (mx/defc history-dialog
[own page] {:mixins [mx/static mx/reactive]}
[page]
(let [history (mx/react history-ref) (let [history (mx/react history-ref)
version (:selected history) version (:selected history)
on-accept #(st/emit! (udh/apply-selected-history page)) on-accept #(st/emit! (udh/apply-selected-history page))
on-cancel #(st/emit! (udh/deselect-page-history page))] on-cancel #(st/emit! (udh/deselect-page-history page))]
(when (or version (:deselecting history)) (when (or version (:deselecting history))
(html [:div.message-version
[:div.message-version {:class (when (:deselecting history) "hide-message")}
{:class (when (:deselecting history) "hide-message")} [:span (tr "history.alert-message" (or version "00"))
[:span (tr "history.alert-message" (or version "00")) [:div.message-action
[:div.message-action [:a.btn-transparent {:on-click on-accept} "Accept"]
[:a.btn-transparent {:on-click on-accept} "Accept"] [:a.btn-transparent {:on-click on-cancel} "Cancel"]]]])))
[:a.btn-transparent {:on-click on-cancel} "Cancel"]]]]))))
(def history-dialog
(mx/component
{:render history-dialog-render
:name "history-dialog"
:mixins [mx/static mx/reactive]}))

View file

@ -288,13 +288,13 @@
;; --- Layers Toolbox (Component) ;; --- Layers Toolbox (Component)
(mx/defc layers-toolbox (mx/defc layers-toolbox
{:mixins [mx/reactive]} {:mixins [mx/static mx/reactive]}
[] []
(let [workspace (mx/react refs/workspace) (let [selected (mx/react refs/selected-shapes)
selected (:selected workspace) page (mx/react refs/selected-page)
;; TODO: dont react to the while shapes-by-id
;; TODO: dont react to the whole shapes-by-id
shapes-map (mx/react refs/shapes-by-id) shapes-map (mx/react refs/shapes-by-id)
page (mx/react (focus-page (:page workspace)))
close #(st/emit! (udw/toggle-flag :layers)) close #(st/emit! (udw/toggle-flag :layers))
duplicate #(st/emit! (uds/duplicate-selected)) duplicate #(st/emit! (uds/duplicate-selected))
group #(st/emit! (uds/group-selected)) group #(st/emit! (uds/group-selected))