From 8b2612559d02ffce71d91ebf7f7057b098456e40 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 27 Mar 2020 14:42:34 +0100 Subject: [PATCH] :nail_care: drag/drop of element libraries in to canvas --- .../main/partials/workspace-libraries.scss | 9 +++ frontend/src/uxbox/main/geom.cljs | 3 +- .../main/ui/workspace/sidebar/libraries.cljs | 55 +++++++++++-------- .../src/uxbox/main/ui/workspace/viewport.cljs | 24 ++++++-- frontend/src/uxbox/util/dom.cljs | 13 ++++- 5 files changed, 74 insertions(+), 30 deletions(-) diff --git a/frontend/resources/styles/main/partials/workspace-libraries.scss b/frontend/resources/styles/main/partials/workspace-libraries.scss index fe4a8c2f3..8c6b1e281 100644 --- a/frontend/resources/styles/main/partials/workspace-libraries.scss +++ b/frontend/resources/styles/main/partials/workspace-libraries.scss @@ -100,6 +100,15 @@ color: $color-white; padding: $size-2 0; } + + &.is-dragging { + border-radius: 0; + border: none; + + & .library-tab-element-name { + display: none; + } + } } .library-tab-element-name { diff --git a/frontend/src/uxbox/main/geom.cljs b/frontend/src/uxbox/main/geom.cljs index 5939f3a13..2a35ca5c7 100644 --- a/frontend/src/uxbox/main/geom.cljs +++ b/frontend/src/uxbox/main/geom.cljs @@ -31,7 +31,8 @@ :text (move-rect shape dpoint) :curve (move-path shape dpoint) :path (move-path shape dpoint) - :circle (move-circle shape dpoint))) + :circle (move-circle shape dpoint) + nil)) (defn- move-rect "A specialized function for relative movement diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/libraries.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/libraries.cljs index 1cd6f69a2..57a773f8e 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/libraries.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/libraries.cljs @@ -21,6 +21,7 @@ [uxbox.main.ui.shapes.icon :as icon] [uxbox.main.ui.workspace.sortable :refer [use-sortable]] [uxbox.util.dom :as dom] + [uxbox.util.timers :as timers] [uxbox.util.uuid :as uuid] [uxbox.util.i18n :as i18n :refer [tr]] [uxbox.util.data :refer [classnames]] @@ -50,11 +51,27 @@ (-> (comp (l/key :library-filter) (l/key section)) (l/derive st/state))) +(defmulti shape-from-item (fn [type _] type)) + +(defmethod shape-from-item :icons [_ item] + (-> item + (assoc :type :icon) + (assoc :width (-> item :metadata :width)) + (assoc :height (-> item :metadata :height)))) + +(defmethod shape-from-item :images [_ item] + (let [metadata (select-keys item [:width :height :thumb-width + :thumb-height :thumb-uri :uri])] + (-> item + (assoc :type :image) + (assoc :metadata metadata)))) + ;; --- Components (mf/defc library-tab [{:keys [libraries section]}] (when (and libraries (-> libraries count (> 0))) - (let [first-id (-> libraries first :id) + (let [state (mf/use-state {:drag-style false}) + first-id (-> libraries first :id) current-selection (or (mf/deref (selected-library-ref section)) first-id)] ;; Check if the current selection is in the list of libraries @@ -82,33 +99,23 @@ [:div.library-tab-content (let [items (mf/deref (selected-items-ref section current-selection))] (for [item items] - (if (= section :icons) - ;; ICONS - [:div.library-tab-element - {:key (str "icon-" (:id item)) - :on-click #(st/emit! (dw/select-for-drawing :icon item))} - + [:div.library-tab-element + {:draggable true + :class (classnames :is-dragging (:drag-style @state)) + :key (str (:id item)) + :on-drag-start (fn [event] + (swap! state assoc :drag-style true) + (dom/set-data-transfer event (shape-from-item section item)) + ;; This state is so we can give custom css to the dragging + (timers/schedule #(swap! state assoc :drag-style false)))} + (if (= section :icons) [:svg {:view-box (->> item :metadata :view-box (str/join " ")) :width (-> item :metadata :width) :height (-> item :metadat :height) :dangerouslySetInnerHTML {:__html (:content item)}}] - [:span.library-tab-element-name (:name item)]] - - ;; IMAGES - [:div.library-tab-element - {:key (str "image-" (:id item)) - :on-click #(let [shape {:name name - :metadata {:width (:width item) - :height (:height item) - :uri (:uri item) - :thumb-width (:thumb-width item) - :thumb-height (:thumb-height item) - :thumb-uri (:thumb-uri item)}}] - (st/emit! (dw/select-for-drawing :image shape)))} - - [:img {:src (:thumb-uri item)}] - [:span.library-tab-element-name (:name item)]]) - ))]]))) + [:img {:draggable false + :src (:thumb-uri item)}]) + [:span.library-tab-element-name (:name item)]]))]]))) (mf/defc libraries-toolbox [{:keys [key]}] diff --git a/frontend/src/uxbox/main/ui/workspace/viewport.cljs b/frontend/src/uxbox/main/ui/workspace/viewport.cljs index 6b4b77aca..5e98983dd 100644 --- a/frontend/src/uxbox/main/ui/workspace/viewport.cljs +++ b/frontend/src/uxbox/main/ui/workspace/viewport.cljs @@ -234,8 +234,7 @@ on-mouse-move (fn [event] - (let [pt (gpt/point (.-clientX event) - (.-clientY event)) + (let [pt (gpt/point (.-clientX event) (.-clientY event)) pt (translate-point-to-viewport pt)] (st/emit! (ms/->PointerEvent :viewport pt (kbd/ctrl? event) @@ -251,7 +250,22 @@ (events/unlistenByKey key1) (events/unlistenByKey key2) (events/unlistenByKey key3) - )))] + ))) + + on-drag-over + ;; Should prevent only events that we'll handle on-drop + (fn [e] (dom/prevent-default e)) + + on-drop + (fn [event] + (let [shape (dom/get-data-transfer event) + point (gpt/point (.-clientX event) (.-clientY event)) + viewport-coord (translate-point-to-viewport point) + final-x (- (:x viewport-coord) (/ (:width shape) 2)) + final-y (- (:y viewport-coord) (/ (:height shape) 2))] + (st/emit! (dw/add-shape (-> shape + (assoc :x final-x) + (assoc :y final-y))))))] (mf/use-effect on-mount) [:* @@ -264,7 +278,9 @@ :on-click on-click :on-double-click on-double-click :on-mouse-down on-mouse-down - :on-mouse-up on-mouse-up} + :on-mouse-up on-mouse-up + :on-drag-over on-drag-over + :on-drop on-drop} [:g.zoom {:transform (str "scale(" zoom ", " zoom ")")} ;; [:> js/React.Profiler ;; {:id "foobar" diff --git a/frontend/src/uxbox/util/dom.cljs b/frontend/src/uxbox/util/dom.cljs index 3c153c42c..2769dc47e 100644 --- a/frontend/src/uxbox/util/dom.cljs +++ b/frontend/src/uxbox/util/dom.cljs @@ -15,7 +15,8 @@ [beicon.core :as rx] [cuerdas.core :as str] [uxbox.util.geom.point :as gpt] - [uxbox.util.blob :as blob])) + [uxbox.util.blob :as blob] + [uxbox.util.transit :as ts])) ;; --- Deprecated methods @@ -146,3 +147,13 @@ [node] (.focus node)) +(defn set-data-transfer + [event data] + (let [data-string (ts/encode data)] + (-> event .-dataTransfer (.setData "text" data-string)))) + +(defn get-data-transfer + [event] + (let [data-string (-> event .-dataTransfer (.getData "text"))] + (ts/decode data-string))) +