For a Seesaw (Swing) app I'm writing, I need to be able to flash a component for a certain duration. Here's the basic function I came up with that accomplishes this:

; Note, this isn't what I want reviewed. See below. 
(defn flash-property [component prop-key flash-value duration]
  (let [old-value (sc/config component prop-key)]
    (sc/config! component prop-key flash-value)

    (sc/timer (fn [_]
                (sc/config! component prop-key old-value))
              :initial-delay duration, :repeats? false)))

It reads the current property value into old-value, sets the new value, then in a timer reverts the old value after duration many milliseconds. If I wanted to create a button that flashes for half a second when pressed, I could write:

(let [btn (sc/button :text "Button")]
  (sc/listen btn
     :action (fn [_] (flash-property btn :background :red 500)))


I had a problem that if you start a new flash before the old one has finished, old-value becomes the flash color from the previous flash, and the component gets stuck as the flash color.

To get around this, I had to rely on a "static variable" that keeps track of what is currently being flashed. I tried to extract as much as I could out of the decider function, but I'm still unhappy with it. The atom, while in a restricted scope, still feels like a hack to cover up a bad design. I've never used a let at the top level before, and it feels kind of dirty.

Of course, I could create some kind of a "flash handler" that gets passed back and forth and keeps track of what's being flashed, but that would be it's own flavour of mess. Then the caller would need to maintain it somehow. Considering the flash gets triggered in a button handler, I'd probably have to maintain an atom there anyways.

Can anyone see how to cleanly avoid the "static variable" flashing?-atom?

(ns pet-redo.full-ui.helpers
  (:require [seesaw.core :as sc]))

(defn flash-property
  "Alters the property at prop-key to flash-value for duration-many milliseconds,
    then reverts the property back to the original value.

  Will break if a new flash is started before a previous one ends."
  [component prop-key flash-value duration component-done-callback]
  (let [old-value (sc/config component prop-key)]
    (sc/config! component prop-key flash-value)

    (sc/timer (fn [_]
                (sc/config! component prop-key old-value)
              :initial-delay duration, :repeats? false)))

(let [flashing?-atom (atom #{})]
  (defn maybe-flash-background!
    "Alters the property at prop-key to flash-value for duration-many milliseconds,
      then reverts the property back to the original value.

    Does nothing if the element is already being flashed.

    Returns whether or not a flash was triggered."
    [component flash-color duration]
    (when-not (@flashing?-atom component)
      (swap! flashing?-atom conj component)

      (flash-property component :background flash-color duration
                      #(swap! flashing?-atom disj component))

  • \$\begingroup\$ Calling people numb-nuts and incapable of reading does not help anyone. \$\endgroup\$ – Simon Forsberg Jul 1 '18 at 13:33
  • \$\begingroup\$ @SimonForsberg The "numbnuts" wasn't nice, I'll admit. It was out of frustration though of posting here being progressively less useful every time. Rarely do I even get a good review anymore, and then this time people vote to close because they misunderstand the question. I had to vent, but you're right, it was wrong. I added a note in the code in question, and removed the comment. My apologies. \$\endgroup\$ – Carcigenicate Jul 1 '18 at 14:33
  • \$\begingroup\$ The reason for you not getting a review is probably that few people know Clojure. And getting an answer here for non-popular languages can take a lot of time. If you know any people yourself who knows Clojure, maybe try getting them here to review your code? \$\endgroup\$ – Simon Forsberg Jul 1 '18 at 14:46
  • 2
    \$\begingroup\$ @SimonForsberg Ya, unfortunately I'm one of the only reviewers, and I don't know of any others. I seemed to get good reviews when I first started the language, but those were probably easy ones that most people could comment on. I'll just be patient. \$\endgroup\$ – Carcigenicate Jul 1 '18 at 15:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.