Skip to content

Instantly share code, notes, and snippets.

@selfsame
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save selfsame/9031240 to your computer and use it in GitHub Desktop.
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…
;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