[squeak-dev] Progress bar design pattern

Bert Freudenberg bert at freudenbergs.de
Fri Apr 1 10:28:09 UTC 2011


On 01.04.2011, at 10:33, Denis Kudriashov wrote:

> We have algorithm:
> 
> MyClass>>algorithm
>        self doA.
>        self doB.
>        self doC.
> 
> And with meta description we can write like:
> 
> Progress for: MyClass>>algorithm when: [:desc |
>     desc for: MyClass>>doB value: 0.33.
>    desc for: MyClass>>doC value: 0.66
> ]
> 
> And doA/B/C can doing some inner loops which we can track with extra meta descriptions.

This is basically how MessageTally works. It's a neat idea and certainly could be done, but seems too "magical" for my taste.

I had to implement progress display for a complex file importer once. It had many different stages, like reading the file, parsing, generating objects, optimizing the structure etc. We wanted a continuous, but optional, progress display.

The main idea was to track progress as fractions. Each subtask would track progress from 0.0 to 1.0, and each higher task would scale that to a proportion of the subtask.

An inner loop would look like

	1 to: total do: [:i |
		... do something ...
		progress ifNotNil: [progress value: i / total] ].

A subtask might do something like

	done := 0.
	total := items size asFloat.
	items do: [:each |
		each processInforming: (progress ifNotNil: [
			[:fraction | progress value: (done + fraction) / total]]).
		done := done + 1].

So it scales each individual fraction to cover part of the total. The cool thing is that these can be arbitrarily nested because each individual progress again goes from 0 to 1.

The outer-most loop looked like

self
	displayProgress: title
	from: 1 to: 4
	during: [:bar |
		bar value: 1.
		X doSomethingInforming: [:fraction | bar value: 1.0 + fraction].
		bar value: 2.
		Y doSomethingElseInforming: [:fraction | bar value: 2.0 + fraction].
		bar value: 3.
		Z doYetMoreInforming: [:fraction | bar value: 3.0 + fraction].
		bar value: 4].

This pattern works well if you can roughly estimate in advance how long each subtask will take. If not, then something more like the project loader's ComplexProgressIndicator might be better suited.

If you don't like passing the progress block explicitly, it can be implemented with Notifications, too. But it would still be the work load reporting its progress, rather than peeking from the outside to guess what's going on.

- Bert -




More information about the Squeak-dev mailing list