GUI progress bar for long processes

I am writing a program to crunch some numbers (or, rather, parse some texts and do NLP on them) and it takes some time to run it. I decided to add a progress bar to it in a non-intrusive way. That is, the program would work on its own and the GUI would run in the background showing the state of the computation without slowing down the main computation.

As it turned out, the computations are quite complex and involved, so I needed not one progress bar but a hierarchy of progress bars: every progress bar level shows the progress of a specific computation step.

The result looks like this:

with_progress_display

with_progress_display1

I've made it to be simple. There are two macros:

  • with-progress-bar. This macro wraps the code that makes some work. When starting this work, a progress bar is shown, and it is hidden when the work is completed.
  • with-progress-bar-action. This macro wraps the code that makes some logical part of the work. When it completes, the progress bar is refreshed and the ETA is updated.

In order for this UI not to conflict with the main program, it runs on another thread.

An example use-case:

(defun test-progress ()
  (with-progress-bar ("Snowball" 10)
    (loop
       repeat 10
       do (with-progress-bar-action
            (with-progress-bar ("Texts" 10)
              (loop
                 repeat 10
                 do (with-progress-bar-action (sleep 1))))))))

When I needed to make a similar progress display in C#, it took me a good part of the day. But with Lisp, however, it took me just half an hour. It's the small things that make me more productive in more expressive languages.