Click here to Skip to main content
Click here to Skip to main content

Collapsing Multiple Progress Bars

, 15 Nov 2007
Rate this:
Please Sign up or sign in to vote.
An article on how to collapse the progress feedback given by multiple routines in a single progress bar
Screenshot - Article.gif

Introduction

Everybody knows the frustration caused by a new progress bar popping up and starting from 0% just after the previous one reached 100%. This annoyance is caused by several consecutive subroutines providing independent progress feedback. Collapsing these isolated progress bars into one bar running from 0 to 100% can be a nasty problem. In this article, an object-oriented approach is presented that provides an elegant and transparent solution to this problem.

Background

In complex software packages, there are often multiple lengthy tasks that provide progress feedback. A single user action could lead to a number of such tasks being executed, typically resulting in several consecutive instances of progress running from 0 to 100%. It is desirable to collapse the isolated instances of progress feedback into one overall instance of feedback running from 0 to 100%. This willl give the user a good notion of how much of the overall task has been finished and how much is left.

It is possible to solve this problem by hard-coding the progress range into every function or by passing the current progress as parameters to each function. However, the first solution is not very flexible (consider calling the same subroutines in a different order or different context) and the latter poses constraints to your code. Therefore this article presents a transparent and flexible solution to the above-described problem.

We introduce a CProgress class that subscribes itself to a linked list containing all active progress feedback in the application. This subscription mechanism, however, is completely hidden from a programmer using the CProgress class, which makes it very easy to use.

Using the Code

Consider a simple traditional class for progress feedback, CTraditionalProgress, which could be used in the following way:

void A()
{
   CTraditionalProgress myProgress;
   myProgress.Set(0);
   B(); //call function B
   myProgress.Set(60);
   C(); //call function C
   myProgress.Set(100);
}

It is very simple to imagine how the code of CTraditionalProgress could look. The Set() function simply sets the progress bar to the number that is passed.

Now suppose that functions B() and C() have their own progress bars and suppose that we also want to capture that progress in the progress bar of function A(). In other words, we want to collapse the progress feedback of functions B() and C() into the progress bar of function A(). Well, that is exactly what the CProgress class does for us. The beauty of it is that we hardly need to change any code. Most especially, we do not need to pass any additional parameters to the B() and C() subroutines.

One small adjustment to our code concerns replacing the Set() member function with the SetRange() function. Rather than indicating what percentage of the progress has already finished, this function indicates the fraction of the total time that the next block of code is expected to demand. The example code now looks like this:

void A()
{
   CProgress myProgress;
   myProgress.SetRange(0.60);
   B(); //call function B
   myProgress.SetRange(0.40);
   C(); //call function C
}

void B()
{
   CProgress myProgress;
   myProgress.SetRange(0.20);
   // Do something, estimated duration 20% of time for function B()

   for (int n=0; n < 80; n++) {
      myProgress.SetRange(0.01);
      // Do something, estimated duration 1%
   }
}

The progress feedback of function B() is automatically mapped on the range of 0.60, which was specified in function A(). If function B() calls any routines that provide feedback regarding their progress, then that is again collapsed to the range that was specified in function B(). This process of collapsing is illustrated in the figure below.

Screenshot - Collapse.gif

Points of Interest

If you are interested in the inner workings of the collapsing mechanism, have a look at the sample code and at the PDF article that is attached in the ZIP file. The main trick is the fact that each CProgress instance registers itself to a chained list. Since this chained list does not have an explicit owner or parent, it was decided to call it an "orphaned chained list." It is not hard to understand the CProgress source code. The class consists of less than 50 lines of code. That degree of efficiency could be reached because the traversal of the parent progress nodes is done by simple recursive calls.

History

  • 7 November, 2007 -- Version 1.0
  • 15 November, 2007 -- Downloads updated

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Danny Ruijters
Software Developer (Senior)
Netherlands Netherlands
As a 3D Imaging Scientist, I build clinical prototype software, mainly in the domain of 3D cardio-vascular x-ray. The value of the prototypes is evaluated in hospitals by physicians, who use them in cardio-vascular interventions. Further it is my task to stay in touch with the scientific developments in 3D medical imaging.
 
I have been writing software for about 20 years now. The past 6 years I concerned myself mainly with 3D medical image processing, visualization and GPU programming.

Comments and Discussions

 
GeneralNice, simple approach to the problem Pinmemberwtwhite12-Nov-07 16:29 
GeneralRe: Nice, simple approach to the problem PinmemberDanny Ruijters12-Nov-07 21:28 
GeneralRe: Nice, simple approach to the problem PinmemberVattila13-Nov-07 1:08 
GeneralRe: Nice, simple approach to the problem PinmemberDanny Ruijters16-Nov-07 3:09 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140709.1 | Last Updated 15 Nov 2007
Article Copyright 2007 by Danny Ruijters
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid