Skip to content

Instantly share code, notes, and snippets.

@mlb-
Created June 17, 2016 06:57
Show Gist options
  • Save mlb-/50b559aff7a877b9f6037331fdbf6b9a to your computer and use it in GitHub Desktop.
Save mlb-/50b559aff7a877b9f6037331fdbf6b9a to your computer and use it in GitHub Desktop.
;; This buffer is for notes you don't want to save, and for Lisp evaluation.
;; If you want to create a file, visit that file with C-x C-f,
;; then enter the text in that file's own buffer.
(defn get-that-thing
"Bind the event handler for clicks and have it `put!` into a
channel."
[]
;; The implementation of this is left to the reader. Who will
;; probably skim swannodette's blog.
nil)
(def double-click-timeout-duration
"Length of time we wait to call a second click a double-click."
some-value-in-ms)
(let [;; Our raw input channel
raw-click-chan (get-that-thing)
;; Channels used in double-click detection
first-click (chan)
second-click (chan)
;; A channel that provides either `first-click`, or
;; `second-click`.
next-click-chan-provider (doto (chan)
;; Initialize!
(put! first-click))
;; The processed clicks from `raw-click-channel` go through
;; `first-click` or `second-click` and end up here for
;; consumption later on.
processed-click-events (chan)]
(go
(while true
;; Put the `raw-click-event` on the correct channel. The very
;; first click cannot be a "double-click", hence
;; `next-click-chan-provider` being initialized with
;; `first-click` above.
(let [raw-click-event (<! raw-click-chan)
next-click-chan (<! next-click-chan-provider)]
(>! next-click-chan raw-click-event))))
(go
(while true
;; Once we receive a first click, we start a timer to see if a
;; second click arrives before it expires. If so, it's a
;; double-click. Otherwise, we "reset" and provide `first-click`
;; to `next-click-chan-provider`.
(let [raw-click-event (<! first-click)
t (timeout double-click-timeout-duration)]
(alt! [t
;; If the timeout expires, then no additional click
;; happened in time. It's not a double-click. It's a
;; single-click.
(put! processed-click-events {:single-click raw-click-event})
;; If we succeed placing a value on
;; `next-click-chan-provider`, it's because another
;; `raw-click-event` arrived on `raw-click-chan` before
;; the timeout window closed. It must be a double
;; click!
[next-click-chan-provider second-click]
(put! processed-click-events {:double-click-part-one raw-click-event})])
;; Whether we got a double-click, or no click, we need to
;; reset `next-click-chan-provider`.
(>! next-click-chan-provider first-click))))
(go
(while true
;; Consume the second click of the double-click event!
(let [raw-click-event (<! second-click)]
(put! processed-click-events {:double-click-part-two raw-click-event}))))
;; Return our processed click/double-click event channel.
processed-click-events)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment