0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-10 09:08:31 -05:00

Add naive impl for transfer/move shapes (in drag and drop).

This commit is contained in:
Andrey Antukh 2016-02-01 19:48:04 +02:00
parent 45caf5cdda
commit 811f47f929
3 changed files with 195 additions and 27 deletions

View file

@ -8,7 +8,8 @@
[uxbox.schema :as sc] [uxbox.schema :as sc]
[uxbox.time :as time] [uxbox.time :as time]
[uxbox.xforms :as xf] [uxbox.xforms :as xf]
[uxbox.shapes :as sh])) [uxbox.shapes :as sh]
[uxbox.util.data :refer (index-of)]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Schemas ;; Schemas
@ -376,6 +377,40 @@
(rx/from-coll (rx/from-coll
(map unlock-shape (:items shape)))))))) (map unlock-shape (:items shape))))))))
(defn transfer-after
"Event used in drag and drop for transfer shape
from one position to an other."
[sid tid]
(reify
rs/UpdateEvent
(-apply-update [_ state]
(let [sitem (get-in state [:shapes-by-id sid])
titem (get-in state [:shapes-by-id tid])
page (get-in state [:pages-by-id (:page titem)])
index (index-of (:shapes page) tid)
[fst snd] (split-at (inc index) (:shapes page))
fst (remove #(= % sid) fst)
snd (remove #(= % sid) snd)
items (concat fst [sid] snd)]
(assoc-in state [:pages-by-id (:page titem) :shapes] items)))))
(defn transfer-before
[sid tid]
(reify
rs/UpdateEvent
(-apply-update [_ state]
(let [sitem (get-in state [:shapes-by-id sid])
titem (get-in state [:shapes-by-id tid])
page (get-in state [:pages-by-id (:page titem)])
index (index-of (:shapes page) tid)
[fst snd] (split-at index (:shapes page))
fst (remove #(= % sid) fst)
snd (remove #(= % sid) snd)
items (concat fst [sid] snd)]
(assoc-in state [:pages-by-id (:page titem) :shapes] items)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Events (for selected) ;; Events (for selected)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View file

@ -1,18 +1,21 @@
(ns uxbox.ui.workspace.toolboxes.layers (ns uxbox.ui.workspace.toolboxes.layers
(:require-macros [uxbox.util.syntax :refer (defer)])
(:require [sablono.core :as html :refer-macros [html]] (:require [sablono.core :as html :refer-macros [html]]
[rum.core :as rum] [rum.core :as rum]
[cats.labs.lens :as l] [cats.labs.lens :as l]
[goog.events :as events]
[uxbox.router :as r] [uxbox.router :as r]
[uxbox.rstore :as rs] [uxbox.rstore :as rs]
[uxbox.state :as st] [uxbox.state :as st]
[uxbox.shapes :as shapes] [uxbox.shapes :as shapes]
[uxbox.library :as library] [uxbox.library :as library]
[uxbox.util.data :refer (read-string)] [uxbox.util.data :refer (read-string classnames)]
[uxbox.data.workspace :as dw] [uxbox.data.workspace :as dw]
[uxbox.ui.workspace.base :as wb] [uxbox.ui.workspace.base :as wb]
[uxbox.ui.icons :as i] [uxbox.ui.icons :as i]
[uxbox.ui.mixins :as mx] [uxbox.ui.mixins :as mx]
[uxbox.ui.dom :as dom])) [uxbox.ui.dom :as dom])
(:import goog.events.EventType))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Lenses ;; Lenses
@ -88,37 +91,98 @@
:builtin/rect i/box :builtin/rect i/box
:builtin/group i/folder)) :builtin/group i/folder))
(defn- get-hover-position
[event group?]
(let [target (.-currentTarget event)
brect (.getBoundingClientRect target)
width (.-offsetHeight target)
y (- (.-clientY event) (.-top brect))
part (/ (* 30 width) 100)]
(if group?
(cond
(> part y) :top
(< (- width part) y) :bottom
:else :middle)
(if (>= y (/ width 2))
:bottom
:top))))
(defn- layer-element-render (defn- layer-element-render
[own item selected] [own item selected]
(let [selected? (contains? selected (:id item)) (let [selected? (contains? selected (:id item))
select #(select-shape selected item %) select #(select-shape selected item %)
toggle-visibility #(toggle-visibility selected item %) toggle-visibility #(toggle-visibility selected item %)
toggle-blocking #(toggle-blocking item %)] toggle-blocking #(toggle-blocking item %)
(html local (:rum/local own)
[:li {:key (str (:id item))
:on-click select classes (classnames
:class (when selected? "selected")} :selected selected?
[:div.element-list-body :drag-top (= :top (:over @local))
{:class (when selected? "selected")} :drag-bottom (= :bottom (:over @local))
[:div.element-actions :drag-inside (= :middle (:over @local)))]
[:div.toggle-element (letfn [(on-drag-start [event]
{:class (when-not (:hidden item) "selected") (let [target (.-target event)
:on-click toggle-visibility} style (.-style target)
i/eye] dt (.-dataTransfer event)]
[:div.block-element (set! (.-effectAllowed dt) "move")
{:class (when (:blocked item) "selected") (.setData dt "item/uuid" (pr-str (:id item)))
:on-click toggle-blocking} (swap! local assoc :dragging true)))
i/lock]] (on-drag-end [event]
(if (:group item) (swap! local assoc :dragging false :over nil))
[:div.sublevel-element i/sublevel]) (on-drop [event]
[:div.element-icon (element-icon item)] (let [dt (.-dataTransfer event)
[:span (:name item "Unnamed")]]]))) id (read-string (.getData dt "item/uuid"))
over (:over @local)]
(case (:over @local)
:top (rs/emit! (dw/transfer-before id (:id item)))
:bottom (rs/emit! (dw/transfer-after id (:id item)))
;; :middle (rs/emit! (dw/transfer-inside id (:id item)))
)
(swap! local assoc :dragging false :over nil)))
(on-drag-over [event]
(dom/prevent-default event)
(let [dt (.-dataTransfer event)
over (get-hover-position event (:group item))]
(set! (.-dropEffect dt) "move")
(swap! local assoc :over over)))
(on-drag-enter [event]
(swap! local assoc :over true))
(on-drag-leave [event]
(swap! local assoc :over false))]
(html
[:li {:key (str (:id item))
:on-click select
:on-drag-start on-drag-start
:on-drag-enter on-drag-enter
:on-drag-leave on-drag-leave
:on-drag-over on-drag-over
:on-drag-end on-drag-end
:on-drop on-drop
:data-over (str (:over @local))
:draggable true
:class (when selected? "selected")}
[:div.element-list-body
{:class classes}
[:div.element-actions
[:div.toggle-element
{:class (when-not (:hidden item) "selected")
:on-click toggle-visibility}
i/eye]
[:div.block-element
{:class (when (:blocked item) "selected")
:on-click toggle-blocking}
i/lock]]
(if (:group item)
[:div.sublevel-element i/sublevel])
[:div.element-icon (element-icon item)]
[:span (:name item "Unnamed")]]]))))
(def ^:static ^:private layer-element (def ^:static ^:private layer-element
(mx/component (mx/component
{:render layer-element-render {:render layer-element-render
:name "layer-element" :name "layer-element"
:mixins [mx/static]})) :mixins [mx/static (mx/local)]}))
(declare layer-group) (declare layer-group)
@ -136,7 +200,7 @@
(swap! local assoc :open (not open?))) (swap! local assoc :open (not open?)))
shapes-by-id (rum/react wb/shapes-by-id-l)] shapes-by-id (rum/react wb/shapes-by-id-l)]
(html (html
[:li.group {:class (when open? "open")} [:li.group {:class (when open? "open") :draggable true}
[:div.element-list-body [:div.element-list-body
{:class (when selected? "selected") {:class (when selected? "selected")
:on-click select} :on-click select}
@ -175,6 +239,63 @@
:name "layer-group" :name "layer-group"
:mixins [mx/static rum/reactive (mx/local)]})) :mixins [mx/static rum/reactive (mx/local)]}))
;; (defn layers-did-mount
;; [own local]
;; (let [rootel (mx/get-ref-dom own "rootel")
;; dragel (volatile! nil)]
;; (letfn [(on-drag-start [event]
;; (println "on-drag-start")
;; (js/console.log (.getBrowserEvent event))
;; (let [event (.getBrowserEvent event)
;; target (.-target event)
;; dt (.-dataTransfer event)]
;; (vreset! dragel target)
;; (set! (.-effectAllowed dt) "move")
;; (events/listen rootel EventType.DRAGOVER on-drag-over)
;; (events/listen rootel EventType.DRAGEND on-drag-end)
;; (.setData dt "Text" (.-textContent target))
;; (defer
;; (let [clist (.-classList target)]
;; (.add clist "ghost")))))
;; (on-drag-over [event]
;; (dom/prevent-default event)
;; (let [event (.getBrowserEvent event)
;; dt (.-dataTransfer event)
;; target (.-target event)]
;; (set! (.-dropEffect dt) "move")
;; (println "kaka" (.-nodeName target))
;; (when (and target (not= target @dragel))
;; (.insertBefore rootel @dragel (or (.-nextSibling target)
;; target)))))
;; (on-drag-end [event]
;; (println "drag end")
;; (dom/prevent-default event)
;; (events/unlisten rootel EventType.DRAGEND on-drag-end)
;; (events/unlisten rootel EventType.DRAGOVER on-drag-over)
;; (let [cl (.-classList @dragel)]
;; (.remove cl "ghost")
;; (println "on-drag-end")))]
;; (assoc own ::key
;; (events/listen rootel EventType.DRAGSTART on-drag-start)))))
;; (defn layers-will-unmount
;; [own local]
;; (let [key (::key own)]
;; (events/unlistenByKey key)
;; (dissoc own ::key)))
;; (defn layers-transfer-state
;; [old-own own]
;; (let [key (::key old-own)]
;; (assoc own ::key key)))
(defn layers-render (defn layers-render
[own] [own]
(let [workspace (rum/react wb/workspace-l) (let [workspace (rum/react wb/workspace-l)
@ -184,7 +305,8 @@
close #(rs/emit! (dw/toggle-toolbox :layers)) close #(rs/emit! (dw/toggle-toolbox :layers))
;; copy #(rs/emit! (dw/copy-selected)) ;; copy #(rs/emit! (dw/copy-selected))
group #(rs/emit! (dw/group-selected)) group #(rs/emit! (dw/group-selected))
delete #(rs/emit! (dw/delete-selected))] delete #(rs/emit! (dw/delete-selected))
dragel (volatile! nil)]
(html (html
[:div#layers.tool-window [:div#layers.tool-window
[:div.tool-window-bar [:div.tool-window-bar
@ -192,7 +314,10 @@
[:span "Layers"] [:span "Layers"]
[: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
[:ul.element-list [:ul.element-list {;;:onDragStart on-drag-start
;;:onDragOver on-drag-over
;;:onDragEnd on-drag-end
:ref "rootel"}
(for [shape (map #(get shapes-by-id %) (:shapes page)) (for [shape (map #(get shapes-by-id %) (:shapes page))
:let [key (str (:id shape))]] :let [key (str (:id shape))]]
(if (= (:type shape) :builtin/group) (if (= (:type shape) :builtin/group)
@ -209,6 +334,9 @@
(def ^:static layers-toolbox (def ^:static layers-toolbox
(mx/component (mx/component
{:render layers-render {:render layers-render
;; :did-mount layers-did-mount
;; :will-unmount layers-will-unmount
;; :transfer-state layers-transfer-state
:name "layers" :name "layers"
:mixins [rum/reactive]})) :mixins [rum/reactive]}))

View file

@ -6,3 +6,8 @@
(let [sym (symbol (str (namespace name') "-" (name name')))] (let [sym (symbol (str (namespace name') "-" (name name')))]
`(cljs.core/defonce ~sym `(cljs.core/defonce ~sym
(do ~@body nil)))) (do ~@body nil))))
(defmacro defer
[& body]
`(let [func# (fn [] ~@body)]
(js/setTimeout func# 0)))