Last active
August 29, 2015 13:56
-
-
Save selfsame/9031240 to your computer and use it in GitHub Desktop.
root component tracks UI state, and builds UI components with a drilled cursor (dummy wrapper for app data), UI changes are handled by root, which compares state and render state for individual components to see if they need :state passed for positioning. Draggable component is using dummy data to get unique cursor path, otherwise it triggers st…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;sug/private is an atomic data store that links the owner path+:react-key to a data map. | |
;it works much like state, but it doesn't trigger any renders and doesn't have pending/rendered versions | |
;it's very helpful here to stash the mouse drag meta info without triggering app updates. | |
(defn unbind-drag [owner] | |
(let [[mouse-up mouse-move] (sug/private owner :event-handlers)] | |
(.unbind (js/$ js/window) "mouseup" mouse-up) | |
(.unbind (js/$ js/window) "mousemove" mouse-move))) | |
(defn drag-stop [e data owner] | |
(let [loc (location e)] | |
(sug/fire! owner (or (om/get-state owner :drag-stop) :drag-stop) | |
(conj {:location loc | |
:start-location (sug/private owner :start-location) | |
:diff-location (map - loc (sug/private owner :last-location))} (om/get-state owner :message))) | |
(unbind-drag owner))) | |
(defn drag [e data owner] | |
(let [loc (location e)] | |
(sug/fire! owner (or (om/get-state owner :drag) :drag) | |
(conj { :location loc | |
:start-location (sug/private owner :start-location) | |
:diff-location (map - loc (sug/private owner :last-location))} (om/get-state owner :message)) ) | |
(sug/private! owner :last-location loc) | |
)) | |
(defn drag-start [e data owner] | |
(let [loc (location e) | |
mouse-up #(drag-stop % @data owner) | |
mouse-move #(drag % @data owner)] | |
(sug/private! owner :event-handlers [mouse-up mouse-move]) | |
(.bind (js/$ js/window) "mouseup" mouse-up) | |
(.bind (js/$ js/window) "mousemove" mouse-move) | |
(sug/private! owner :start-location loc) | |
(sug/private! owner :last-location loc) | |
(sug/fire! owner (or (om/get-state owner :drag-start) :drag-start) | |
(conj {:location loc | |
:start-location loc | |
:diff-location [0 0]} (om/get-state owner :message)) ))) | |
(sug/defcomp draggable | |
[data owner opts] | |
{:will-unmount | |
(fn [_] | |
(unbind-drag owner)) | |
:render-state | |
(fn [_ state] | |
(let [content (:content opts) | |
class-name (or (:className opts) "") | |
style (or (:style opts) #js {})] | |
(dom/div #js {:className class-name :style style | |
:onMouseDown #(drag-start % data owner)} content)))}) | |
(sug/defcomp window | |
[data owner] | |
{:render-state | |
(fn [_ state] | |
(sug/private! owner [:cat] 66) | |
(let [[x y w h] (:xywh state)] | |
(dom/div #js {:style #js {:left x :top y :width w :height h :position "absolute" :border "1px solid red"}} | |
(sug/make draggable data {:opts {:className (str "title" ) | |
:content (prn-str (:view state) " " (rand-int 100) " " (sug/private owner []))} | |
:init-state {:message {:uid (:uid state)} | |
:drag :drag-free}}) | |
(dom/h3 nil (prn-str (:view state))) | |
(dom/p nil (prn-str (:app data) )) | |
)))}) | |
(defn make-window [uid] | |
(let [view (rand-nth [:style :control]) | |
[x y] [(rand-int 800) (rand-int 500)] | |
[w h] (mapv + [(rand-int 200) (rand-int 200)] [100 60])] | |
{uid {:uid uid :view view :xywh [x y w h]}} )) | |
(sug/defcomp router | |
[data owner] | |
{:init-state | |
(fn [_] | |
(let [windows (into {} (map make-window [:w1 :w2 :w3 :w4 :w5 :w6]))] | |
{:windows windows})) | |
:render-state | |
(fn [_ state] | |
(let [render-state (om/get-render-state owner :windows)] | |
(apply dom/div nil | |
(map (fn [w] (sug/make window (:app data) {:react-key (:uid w) | |
:init-state {:uid (:uid w) | |
:view (:view w) | |
:xywh (:xywh w)} | |
:state (if (not= | |
((:uid w)(:windows state)) | |
((:uid w)(:windows render-state))) | |
{:xywh (:xywh w)} | |
{:xywh (:xywh w)}) | |
})) (vals (:windows state)))))) | |
:on {:drag-free | |
(fn [e] | |
(let [uid (:uid e) | |
state (om/get-state owner) | |
window (uid (:windows state)) | |
[dx dy] (:diff-location e) | |
new-xywh (map + (:xywh window) [dx dy 0 0])] | |
(om/set-state! owner [:windows uid :xywh] new-xywh) | |
))}}) | |
(def DAT (atom {:app {:nodes []}})) | |
(om/root DAT router (.getElementById js/document "main")) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment