#include <progress.h>
Public Member Functions | |
Progress () | |
Constructs an instance of a Progress object. This starts the hourglass running. Destruct the object to stop the hourglass. | |
Progress (StringBase *Description, INT32 FinalCount=-1, BOOL Delay=TRUE, BOOL bEnable=TRUE) | |
Constructs an instance of a Progress object. This starts the hourglass (and optional progress bar) running. Destruct the object to stop the hourglass. | |
Progress (UINT32 DescriptionID, INT32 FinalCount=-1, BOOL Delay=TRUE, BOOL bEnable=TRUE) | |
~Progress () | |
Destructs an instance of a Progress object. This stops the hourglass (and optional progress bar) which the constructor started going. | |
INT32 | GetCount (INT32 n=0) |
Gets the current progress count, and add 'n' to it. 'n' is added before the current count is returned. | |
void | ResetCount (INT32 n=0) |
Resets the progress count to n. | |
Static Public Member Functions | |
static BOOL | Init (void) |
Initialise the progress display system. Call once on startup (see main3.cpp). | |
static BOOL | Deinit (void) |
De-initialise the progress display system. Call once on shutdown (see main.cpp). | |
static void | Start (BOOL Delay=FALSE, StringBase *Description=NULL, INT32 FinalCount=-1) |
static void | Start (BOOL Delay, UINT32 DescriptionID, INT32 FinalCount=-1) |
[NOTE that to show a progress display, the easiest system is to construct a Progress object - this will automatically turn the hourglass off when the object is destructed. Only use this call if you need lower level control or it is a lot more convenient than a simple instance of the class] | |
static BOOL | Update (INT32 CurrentCount=0, BOOL FreqEscChecks=FALSE) |
Updates progress indications. This serves 3 purposes: a) To show the progress indications if a delayed-start was specified in your call to Start(). This is the default action. b) To check for the user pressing escape to abort the job c) To change the displayed percentage on the progress bar and animated cursor. | |
static void | Stop (void) |
Stops a progress indication started with a call to Start() The hourglass and progress bar etc will only be removed once all calls to Start() have been countermanded by calls to Stop(). | |
static void | Smash (BOOL ForceSmash=FALSE) |
Smashes the hourglass and other progress displays. This kills all active progress indications immediately, as if Progress::Stop() had been called enough times to cancel all active displays. | |
static void | SetFinalCount (INT32 n) |
Allows you to set this value after construction of a Progress object. You should call this value before you make any calls to Update(). | |
static BOOL | SetDescription (const StringBase *const Description) |
Gives the user some textual description of what's going on when the hourglass is blocking the view. | |
static void | RalphAbortJob () |
static void | ClearRalphAbortJob () |
static BOOL | IsRalphAbort () |
static void | ThreadCallback (void) |
This method is called by our delay thread to show any delayed progress displays that we wish to display. It should not be called from elsewhere. | |
Protected Attributes | |
INT32 | ProgressCount |
Static Protected Attributes | |
static INT32 | ActiveDisplays = 0 |
static BOOL | JobCancelled = FALSE |
static BOOL | JobDelayed = FALSE |
static INT32 | FinalCount = 0 |
static INT32 | CurrentPercent = 0 |
static BOOL | HourglassShown = FALSE |
static String_64 | JobDescription = TEXT("") |
static BOOL | HaveJobDescription = FALSE |
static MonotonicTime | StartTime |
static BOOL | AbortJob = FALSE |
static INT32 | DisplayBar = TRUE |
If TRUE, a progress bar will be displayed while Camelot is busy processing. |
Definition at line 137 of file progress.h.
|
Constructs an instance of a Progress object. This starts the hourglass running. Destruct the object to stop the hourglass.
Notes: IMPORTANT! Only use this constructor for small, deep-down functions which you can't supply a useful operation description for. Whenever we're busy we must endeavour to show a useful description to the user.
Definition at line 377 of file progress.cpp. 00378 { 00379 ProgressCount = 0; 00380 00381 Progress::Start(TRUE, (StringBase *)NULL, -1); 00382 }
|
|
Constructs an instance of a Progress object. This starts the hourglass (and optional progress bar) running. Destruct the object to stop the hourglass.
Delay - TRUE if you want the hourglass to appear after a short delay FALSE for it to appear immediately See Progress::Start() for more details on the progress system
Definition at line 414 of file progress.cpp. 00415 { 00416 if (bEnable) 00417 { 00418 ProgressCount = 0; 00419 ERROR3IF(Description == NULL, "Progress constructor - Illegal NULL parameter"); 00420 Progress::Start(Delay, Description, FinalCount); 00421 } 00422 }
|
|
Definition at line 425 of file progress.cpp. 00426 { 00427 if (bEnable) 00428 { 00429 ProgressCount = 0; 00430 ERROR3IF(!DescriptionID, "Progress constructor - Illegal NULL parameter"); 00431 Progress::Start(Delay, DescriptionID, FinalCount); 00432 } 00433 }
|
|
Destructs an instance of a Progress object. This stops the hourglass (and optional progress bar) which the constructor started going.
Definition at line 452 of file progress.cpp. 00453 { 00454 Progress::Stop(); 00455 }
|
|
Definition at line 186 of file progress.h.
|
|
De-initialise the progress display system. Call once on shutdown (see main.cpp).
Definition at line 991 of file progress.cpp. 00992 { 00993 return(TRUE); 00994 }
|
|
Gets the current progress count, and add 'n' to it. 'n' is added before the current count is returned.
If the final count var (as supplied to the constructor or SetFinalCount()) is less that 1, the counter is not incremented AND 0 is always returned.
Definition at line 1042 of file progress.cpp. 01043 { 01044 if (FinalCount > 0) 01045 { 01046 ProgressCount += n; 01047 return ProgressCount; 01048 } 01049 else 01050 return 0; 01051 }
|
|
Initialise the progress display system. Call once on startup (see main3.cpp).
Definition at line 965 of file progress.cpp. 00966 { 00967 Camelot.DeclareSection(TEXT("Displays"), 8); 00968 Camelot.DeclarePref(TEXT("Displays"), TEXT("ProgressBar"), &DisplayBar); 00969 00970 return(TRUE); // We successfully initialised 00971 }
|
|
Definition at line 187 of file progress.h. 00187 {return AbortJob;};
|
|
Definition at line 185 of file progress.h.
|
|
Resets the progress count to n.
Definition at line 1067 of file progress.cpp. 01068 { 01069 ProgressCount = n; 01070 }
|
|
Gives the user some textual description of what's going on when the hourglass is blocking the view.
Definition at line 471 of file progress.cpp. 00472 { 00473 Description->Left(&JobDescription, 63); 00474 HaveJobDescription = TRUE; 00475 00476 return TRUE; 00477 }
|
|
Allows you to set this value after construction of a Progress object. You should call this value before you make any calls to Update().
Definition at line 1013 of file progress.cpp. 01014 { 01015 // if (ActiveDisplays <= 1) 01016 // { 01017 // --- We're starting a brand new progress indication - so set it up 01018 FinalCount = n; 01019 // } 01020 }
|
|
Smashes the hourglass and other progress displays. This kills all active progress indications immediately, as if Progress::Stop() had been called enough times to cancel all active displays.
This is called on each idle event to ensure that spurious hourglasses are removed.
Definition at line 910 of file progress.cpp. 00911 { 00912 if (ActiveDisplays > 0 || ForceSmash) 00913 { 00914 #if DELAY_THREAD 00915 ThreadAlive = FALSE; // Stop the delay thread (if any) 00916 #endif 00917 00918 // --- Tell the node subsystem that we're turning off the hourglass 00919 Node::StopHourglass(); 00920 00921 // --- Blank the status line text 00922 String_256 Blank(""); 00923 GetApplication()->UpdateStatusBarText(&Blank); 00924 00925 // --- Remove any active progress bar 00926 if (StatusLine::Get()) 00927 { 00928 StatusLine::Get()->ShowProgress(FALSE); 00929 } 00930 00931 // --- And reset all variables to suitable defaults 00932 ActiveDisplays = 0; 00933 JobCancelled = FALSE; 00934 00935 JobDelayed = TRUE; 00936 FinalCount = 0; 00937 CurrentPercent = 0; 00938 HourglassShown = FALSE; 00939 00940 JobDescription.MakeMsg(_R(IDS_BUSYMSG)); 00941 } 00942 00943 // --- And ensure no busy cursors are left active 00944 SmashBusyCursor(); 00945 }
|
|
[NOTE that to show a progress display, the easiest system is to construct a Progress object - this will automatically turn the hourglass off when the object is destructed. Only use this call if you need lower level control or it is a lot more convenient than a simple instance of the class]
FinalCount - -1 if you want no progress bar (percentage) indication, else the number you expect to count up to (e.g. number of lines in the file you're reading, number of nodes you're changing, etc) Starts a progress (hourglass and optional progress bar) indication. Call this when you start doing something that could take a significant amount of time (more than half a second delay should show an hourglass under all circumstances) Notes: The delay parameter specifies whether the hourglass should be shown immediately or if its appearance should be put off for a short time in case you don't take as long as you thought you might. NOTE however, that you *must* call Progress::Update at frequent intervals or the delayed hourglass may never appear! Note that Progress::Update is very efficient, so may be called very often (it only updates 6 times a second at the most). IMPORTANT - The description should be filled in with an appropriate string. We must avoid use of the default generic description whenever possible. Multiple progress indications may be active at any time. In this case, the calls to Start and Stop are "stacked" so the hourglass will only go away when all Start calls have been countermanded by Stops. Preferably, the outermost Start/Stop will provide a progress percentage, while the inner ones will simply use Start() with the default parameters, merely to ensure that an hourglass is shown while they are busy. Don't rely upon your caller to show the hourglass for you! The start/stop/update calls have all been designed to be called often without introducing noticable performance overheads.
Definition at line 532 of file progress.cpp. 00533 { 00534 if (!DescriptionID) 00535 Progress::Start(Delay, (StringBase *)NULL, IntendedFinalCount); 00536 else 00537 { 00538 String_256 Description(DescriptionID); 00539 00540 Progress::Start(Delay, (StringBase *)&Description, IntendedFinalCount); 00541 } 00542 }
|
|
Definition at line 546 of file progress.cpp. 00547 { 00548 #if DEBUG_OUTPUT 00549 TRACE( _T("Progress::Start ActiveDisplays = %d IntendedFinalCount = %d\n"),ActiveDisplays,IntendedFinalCount); 00550 #endif 00551 00552 // Ensure the ActiveDisplays value is valid 00553 if (ActiveDisplays < 0) 00554 ActiveDisplays = 0; 00555 00556 ActiveDisplays++; 00557 if (ActiveDisplays <= 1) 00558 { 00559 // --- We're starting a brand new progress indication - set everything up 00560 JobDelayed = Delay; 00561 JobCancelled = FALSE; 00562 CurrentPercent = 0; 00563 FinalCount = IntendedFinalCount; 00564 HourglassShown = FALSE; 00565 00566 // Remember when we started and when we last updated the screen displays 00567 StartTime.Sample(); 00568 00569 if (Description != NULL) 00570 { 00571 SetDescription(Description); 00572 } 00573 else 00574 { 00575 JobDescription.MakeMsg(_R(IDS_BUSYMSG)); 00576 HaveJobDescription = FALSE; 00577 } 00578 00579 // Inform the Node subsystem that we're putting up an hourglass 00580 Node::StartHourglass(); 00581 00582 // Update the status line text 00583 GetApplication()->UpdateStatusBarText((String_256 *)&JobDescription, FALSE); 00584 00585 #if DELAY_THREAD 00586 // Attempt to start a thread to show the hourglass after a delay 00587 if (JobDelayed) 00588 ::AfxBeginThread(ThreadProc, NULL); 00589 #endif 00590 } 00591 else 00592 { 00593 // --- We're starting a progress indication while another one is already active. 00594 // If they've got a better idea about what the final count should be, use their estimate 00595 00596 // If an "inner" job wants the hourglass to _not_ be delayed, we override the 00597 // current JobDelayed state to make sure it definitely shows an hourglass 00598 if (!Delay) 00599 JobDelayed = FALSE; 00600 00601 // Removed by Jason, 22/1/96. This causes ensures to go off and bad progress 00602 // displays when you have a case like the following: 00603 // Start (-1) 00604 // Start(100) 00605 // End 00606 // Start(200) 00607 // End 00608 // End 00609 // ...In the 2nd progress bar, the FinalCount remains at 100, so Update error3's 00610 // This occurs in saving/exporting and other multi-part busy processes 00611 // A proper fix for this problem requires proper nesting of hourglasses, 00612 // which is not feasible at this stage (a *lot* of conversion work on 00613 // existing code would be necessary). 00614 // This still won't work if progress bars are nested, but should work 00615 // reasonably well otherwise. 00616 // if (FinalCount <= 0) 00617 // FinalCount = IntendedFinalCount; 00618 // The replacement code for the above now occurs below, after we get the JobDescription 00619 00620 00621 // Similarly, if we have only a generic job desc and they've supplied one, then we'll 00622 // use the one that they supplied. 00623 if (!HaveJobDescription && Description != NULL) 00624 { 00625 SetDescription(Description); 00626 } 00627 00628 // Check if we're starting a new progress-bar job, in which case it overrides 00629 // any previous settings for FinalCount and the description string 00630 if (IntendedFinalCount > 0) 00631 { 00632 FinalCount = IntendedFinalCount; 00633 00634 // And reset the current percentage and job description fields 00635 CurrentPercent = 0; 00636 if (Description != NULL) 00637 { 00638 SetDescription(Description); 00639 } 00640 00641 // And reset/redraw the progress bar display to make sure it starts from 0 again 00642 // and shows the new job description (if any). 00643 if (StatusLine::Get()) 00644 { 00645 StatusLine::Get()->SetPercent(0, TRUE, (HaveJobDescription) ? &JobDescription : NULL); 00646 } 00647 } 00648 } 00649 00650 // And finally, update to show the current state. This will show the progress displays 00651 // if appropriate at this time, etc. 00652 Progress::Update(0); 00653 }
|
|
Stops a progress indication started with a call to Start() The hourglass and progress bar etc will only be removed once all calls to Start() have been countermanded by calls to Stop().
It is recommended that you do not call Start() and Stop() directly, but instead construct a local instance of the Progress class in your function. This will automatically start and stop the hourglass for you, and also ensures that Start() and Stop() calls are correctly nested/balanced.
Definition at line 841 of file progress.cpp. 00842 { 00843 #if DEBUG_OUTPUT 00844 TRACE( _T("Progress::Stop ActiveDisplays = %d \n"),ActiveDisplays); 00845 #endif 00846 00847 // Decrement the usage count. The progress display remains until the count returns to zero 00848 ActiveDisplays--; 00849 00850 if (ActiveDisplays <0) 00851 { 00852 // This should never happen but does as Op::End() calls EndSlowJob despite 00853 // BeginSlowJob() not being called first. We return immediately because Progress::Smash() is 00854 // expensive and not a great thing to do on every Op. 00855 ActiveDisplays = 0; 00856 return; 00857 } 00858 00859 // Return if there are active displays left 00860 if (ActiveDisplays > 0) 00861 return; 00862 00863 // We have zero active displays, and before the call, had a positive number, so smash the 00864 // hourglass and delete the progress bar 00865 00866 if (StatusLine::Get() && StatusLine::Get()->IsProgressShown() && CurrentPercent < 97) 00867 { 00868 // We are showing a progress bar, but have not shown "completion" of the job (99%) 00869 // Briefly jump to 99% on the progress bar so the user can't see how bad our estimate 00870 // of when we'd finish really was. 00871 00872 StatusLine::Get()->SetPercent(99); 00873 00874 ::wxMilliSleep(150); /* wait */ 00875 } 00876 00877 // Make sure everything is reset properly 00878 Progress::Smash(TRUE); 00879 }
|
|
This method is called by our delay thread to show any delayed progress displays that we wish to display. It should not be called from elsewhere.
NOTE also that if you change this method do anything more than this, you must be very careful - generally the thread can introduce instability that causes random access violations and stuff. Scope: public, but don't let that fool you. It'd be private but for a technical hitch.
Definition at line 294 of file progress.cpp. 00295 { 00296 #if DELAY_THREAD 00297 //-- This does not work. The SetCursor call is executed, but the cursor stubbornly 00298 //-- refuses to change shape - I suspect this is because the window under the cursor 00299 //-- belongs to the main process thread, not us... 00300 00301 // Tell the thread that it can exit now 00302 ThreadAlive = FALSE; 00303 00304 // And change the cursor shape to an hourglass 00305 // NOTE that I don't call BeginBusyCursor here, to avoid the cursor stack 00306 // doing anything - that way the busy pointer will happily go away as soon as anyone 00307 // tries to do anything with the Camelot cursor stack. 00308 HCURSOR Busy = ::LoadCursor(NULL, _R(IDC_WAIT)); 00309 ::SetCursor(Busy); 00310 #endif 00311 }
|
|
Updates progress indications. This serves 3 purposes: a) To show the progress indications if a delayed-start was specified in your call to Start(). This is the default action. b) To check for the user pressing escape to abort the job c) To change the displayed percentage on the progress bar and animated cursor.
In fact, if it is not called often, a) Delayed start won't work, and you may not get an hourglass at all! b) The user won't be able to abort part way through a job WHEN IN DOUBT, CALL THIS ROUTINE. IT IS BETTER TO CALL IT TOO OFTEN THAN TO NOT CALL IT OFTEN ENOUGH. It is safe to call this function at ANY time, even if no progress indication is active, so if your function can take more than 1/3rd of a second to execute, it really should call Update occasionally just to ensure smooth operation. You need not check the return value on every call. Once the user has pressed escape, this function will always return FALSE until someone takes note. Thus, routines which cannot cope with abortion can possibly leave abortion to their callers. The percentage is only updated if it has become greater than the currently displayed percentage value. The FreqEscChecks parameter (markn) - this param will control the frequency with which the escape key is checked when this function is called. If it is TRUE, it is checked once, guaranteed. If it is FALSE, it is only checked if the percentage displayed increases. You should only call with FreqEscChecks = FALSE if you can detect a performance hit due to too many escape key checks. NOTE: If you call with FreqEscChecks = FALSE, and you never display a percentage, the user will not be able to abort the op part way through.
Definition at line 720 of file progress.cpp. 00721 { 00722 #if DEBUG_OUTPUT 00723 TRACE( _T("Progress::Update ActiveDisplays = %d CurrentCount = %d FinalCount=%d\n"),ActiveDisplays,CurrentCount, FinalCount); 00724 #endif 00725 00726 // --- If no active progress display is on, then return immediately 00727 if (ActiveDisplays <= 0) 00728 { 00729 ActiveDisplays = 0; 00730 return(TRUE); 00731 } 00732 00733 // --- If the job has been cancelled, then return FALSE to indicate user intervention 00734 if (JobCancelled) 00735 return(FALSE); 00736 00737 // If FreqEscChecks is TRUE, ensure we check the escape key, no matter what percentage is displayed 00738 if (FreqEscChecks) 00739 { 00740 // Has the user cancelled the job via the Escape key? 00741 if (KeyPress::IsEscapePressed()) 00742 { 00743 JobCancelled = TRUE; 00744 Beep(); 00745 return(FALSE); 00746 } 00747 } 00748 00749 // --- If the startup delay (if any) has not expired, we do nothing just yet 00750 if (JobDelayed && !StartTime.Elapsed(STARTDELAY)) 00751 return(TRUE); 00752 00753 // --- Check that the parameter passed in was vaguely sensible 00754 ERROR3IF(CurrentCount < 0, "Progress::Update called with out of range parameter"); 00755 00756 // --- If we haven't yet shown the hourglass cursor, do it now 00757 if (!HourglassShown) 00758 { 00759 #if DELAY_THREAD 00760 ThreadAlive = FALSE; // Stop the delay thread (if any) because it's not needed now 00761 #endif 00762 BeginBusyCursor(); 00763 HourglassShown = TRUE; 00764 00765 } 00766 00767 // --- Calculate the new percentage to display. This is limited to lie between 00768 // the last displayed percentage and 99 inclusive. 00769 INT32 NewPercent = CurrentPercent; 00770 if (FinalCount > 0) 00771 { 00772 NewPercent = (100 * CurrentCount) / FinalCount; 00773 00774 if (NewPercent > 99) 00775 NewPercent = 99; 00776 00777 if (NewPercent < CurrentPercent) 00778 NewPercent = CurrentPercent; 00779 } 00780 00781 // --- Now, update the percentage display if it has changed, or if it is a while since 00782 // our last update. NOTE: Updates occur periodically for (a) checking the escape key state 00783 // occasionally, so we can be called often without a huge performance hit, and (b) to 00784 // update frames of our animated hourglass pointer. 00785 if (NewPercent > CurrentPercent) 00786 { 00787 // If FreqEscChecks is FALSE, we only check the escape key when the percentage increases 00788 if (!FreqEscChecks) 00789 { 00790 // Has the user cancelled the job via the Escape key? 00791 if (KeyPress::IsEscapePressed()) 00792 { 00793 JobCancelled = TRUE; 00794 Beep(); 00795 return(FALSE); 00796 } 00797 } 00798 00799 // (Create if necessary) and update the progress bar, if it is needed 00800 if (DisplayBar && FinalCount > 0) 00801 { 00802 if (StatusLine::Get()) 00803 { 00804 StatusLine::Get()->ShowProgress(TRUE, &JobDescription); 00805 StatusLine::Get()->SetPercent(NewPercent); 00806 } 00807 } 00808 00809 // Remember the last displayed percentage 00810 CurrentPercent = NewPercent; 00811 } 00812 00813 return(TRUE); 00814 }
|
|
Definition at line 212 of file progress.h. |
|
Definition at line 195 of file progress.h. |
|
Definition at line 201 of file progress.h. |
|
If TRUE, a progress bar will be displayed while Camelot is busy processing. Preference: ProgressBar Section: Displays Range: TRUE or FALSE
Definition at line 214 of file progress.h. |
|
Definition at line 200 of file progress.h. |
|
Definition at line 206 of file progress.h. |
|
Definition at line 203 of file progress.h. |
|
Definition at line 196 of file progress.h. |
|
Definition at line 198 of file progress.h. |
|
Definition at line 205 of file progress.h. |
|
Definition at line 217 of file progress.h. |
|
Definition at line 208 of file progress.h. |