Created
June 17, 2016 06:57
-
-
Save mlb-/50b559aff7a877b9f6037331fdbf6b9a to your computer and use it in GitHub Desktop.
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
;; 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