Search code examples
clojureseesaw

How do I make seesaw listbox react to double-click?


Okay, so this may be a silly one, but I am at such a loss that I created a SOF account for that. Here's a thing that does almost what I want:

(let [lb (listbox :model ["a" "b" "c"])]
  (listen lb :selection
    (fn [e] (alert (selection lb))))
(-> (frame :content lb)
  pack! show!))

If you run this code you'll see a listbox with three entries (a, b, c). If you click on any one of them an alert pops up with that entry in it. What I want to do is make the listbox react in this way to DOUBLE-clicks, not single-clicks. How should I go about it?

Extra kudos to those who tell me how to make the number of the double-clicked item appear in the popup (0 for a, 1 for b, 2 for c).


Solution

  • Seesaw's listbox function returns a JList. A JList's ListSelectionModel does not provide a way to determine whether the ListSelectionEvent was the result of a double-click. So a :selection listener won't help here.

    On the other-hand, MouseEvent does provide getClickCount, which can be used to detect a double-click. So you can use a :mouse-clicked listener instead, and filter for double-clicks. Then all you need to do is find the ListItem that corresponds with the click location. Fortunately, JList provides a locationToIndex method that can be used for this purpose. This answer to "Double-click event on JList element" puts those pieces together for Java. A translation to Clojure/Seesaw would look something like this:

    (listen lb :mouse-clicked
            (fn [ev]
              (when (= 2 (. ev getClickCount))
                (let [index (. list locationToIndex (. ev getPoint))]
                  <... do something with the index / list item ...>))))