0031763: Foundation Classes - reporting of progress within parallel algorithms
[occt.git] / src / Draw / Draw_ProgressIndicator.cxx
CommitLineData
973c2be1 1// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 2//
973c2be1 3// This file is part of Open CASCADE Technology software library.
b311480e 4//
d5f74e42 5// This library is free software; you can redistribute it and/or modify it under
6// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 7// by the Free Software Foundation, with special exception defined in the file
8// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9// distribution for complete text of the license and disclaimer of any warranty.
b311480e 10//
973c2be1 11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
b311480e 13
42cf5bc1 14
7fd59977 15#include <Draw.hxx>
42cf5bc1 16#include <Draw_Interpretor.hxx>
17#include <Draw_ProgressIndicator.hxx>
7fd59977 18#include <Message.hxx>
42cf5bc1 19#include <Message_Messenger.hxx>
7e785937 20#include <Message_ProgressScope.hxx>
21#include <NCollection_List.hxx>
53d770b3 22#include <Precision.hxx>
7e785937 23#include <OSD.hxx>
24#include <OSD_Exception_CTRL_BREAK.hxx>
25#include <OSD_Thread.hxx>
b311480e 26
7fd59977 27#include <stdio.h>
42cf5bc1 28#include <time.h>
92efcf78 29IMPLEMENT_STANDARD_RTTIEXT(Draw_ProgressIndicator,Message_ProgressIndicator)
30
7fd59977 31//=======================================================================
32//function : Draw_ProgressIndicator
33//purpose :
34//=======================================================================
6b55f8e3 35Draw_ProgressIndicator::Draw_ProgressIndicator (const Draw_Interpretor &di, Standard_Real theUpdateThreshold)
7e785937 36: myTclMode ( DefaultTclMode() ),
37 myConsoleMode ( DefaultConsoleMode() ),
6b55f8e3 38 myGraphMode ( DefaultGraphMode() ),
caee80f3 39 myDraw ( (Draw_Interpretor*)&di ),
6b55f8e3 40 myShown ( Standard_False ),
41 myBreak ( Standard_False ),
42 myUpdateThreshold ( 0.01 * theUpdateThreshold ),
43 myLastPosition ( -1. ),
7e785937 44 myStartTime ( 0 ),
45 myGuiThreadId (OSD_Thread::Current())
7fd59977 46{
47}
48
49//=======================================================================
6b55f8e3 50//function : ~Draw_ProgressIndicator
7fd59977 51//purpose :
52//=======================================================================
53
6b55f8e3 54Draw_ProgressIndicator::~Draw_ProgressIndicator()
7fd59977 55{
56 Reset();
57}
58
59//=======================================================================
60//function : Reset
61//purpose :
62//=======================================================================
63
64void Draw_ProgressIndicator::Reset()
65{
66 Message_ProgressIndicator::Reset();
67 if ( myShown ) {
caee80f3 68 myDraw->Eval ( "destroy .xprogress" );
7fd59977 69 myShown = Standard_False;
70 }
71 myBreak = Standard_False;
6b55f8e3 72 myLastPosition = -1.;
73 myStartTime = 0;
7fd59977 74}
75
76//=======================================================================
77//function : Show
78//purpose :
79//=======================================================================
80
7e785937 81void Draw_ProgressIndicator::Show (const Message_ProgressScope& theScope, const Standard_Boolean force)
7fd59977 82{
7e785937 83 if (!myGraphMode && !myTclMode && !myConsoleMode)
84 return;
6b55f8e3 85
86 // remember time of the first call to Show as process start time
87 if ( ! myStartTime )
88 {
7e785937 89 if (!myStartTime)
90 {
91 time_t aTimeT;
92 time(&aTimeT);
93 myStartTime = (Standard_Size)aTimeT;
94 }
6b55f8e3 95 }
96
97 // unless show is forced, show updated state only if at least 1% progress has been reached since the last update
98 Standard_Real aPosition = GetPosition();
99 if ( ! force && aPosition < 1. && Abs (aPosition - myLastPosition) < myUpdateThreshold)
7e785937 100 return; // return if update interval has not elapsed
101
6b55f8e3 102 myLastPosition = aPosition;
7fd59977 103
104 // Prepare textual progress info
53d770b3 105 std::stringstream aText;
106 aText.setf (std::ios::fixed, std:: ios::floatfield);
107 aText.precision(0);
108 aText << "Progress: " << 100. * GetPosition() << "%";
7e785937 109 NCollection_List<const Message_ProgressScope*> aScopes;
110 for (const Message_ProgressScope* aPS = &theScope; aPS; aPS = aPS->Parent())
111 aScopes.Prepend(aPS);
112 for (NCollection_List<const Message_ProgressScope*>::Iterator it(aScopes); it.More(); it.Next())
113 {
114 const Message_ProgressScope* aPS = it.Value();
115 if (!aPS->Name()) continue; // skip unnamed scopes
116 aText << " " << aPS->Name() << ": ";
53d770b3 117
7fd59977 118 // print progress info differently for finite and infinite scopes
7e785937 119 Standard_Real aVal = aPS->Value();
120 if (aPS->IsInfinite())
53d770b3 121 {
53d770b3 122 if (Precision::IsInfinite(aVal))
123 {
124 aText << "finished";
125 }
126 else
127 {
128 aText << aVal;
129 }
130 }
131 else
132 {
7e785937 133 aText << aVal << " / " << aPS->MaxValue();
53d770b3 134 }
7fd59977 135 }
136
7e785937 137 // Show graphic progress bar.
138 // It will be updated only within GUI thread.
139 if (myGraphMode && myGuiThreadId == OSD_Thread::Current())
140 {
6b55f8e3 141 // In addition, write elapsed/estimated/remaining time
142 if ( GetPosition() > 0.01 ) {
143 time_t aTimeT;
144 time ( &aTimeT );
145 Standard_Size aTime = (Standard_Size)aTimeT;
53d770b3 146 aText << "\nElapsed/estimated time: " << (long)(aTime - myStartTime) <<
147 "/" << ( aTime - myStartTime ) / GetPosition() << " sec";
6b55f8e3 148 }
149
7fd59977 150 if ( ! myShown ) {
151 char command[1024];
91322f44 152 Sprintf ( command, "toplevel .xprogress -height 100 -width 410;"
7fd59977 153 "wm title .xprogress \"Progress\";"
154 "set xprogress_stop 0;"
155 "canvas .xprogress.bar -width 402 -height 22;"
156 ".xprogress.bar create rectangle 2 2 2 21 -fill blue -tags progress;"
157 ".xprogress.bar create rectangle 2 2 2 21 -outline black -tags progress_next;"
158 "message .xprogress.text -width 400 -text \"Progress 0%%\";"
68299304 159 "button .xprogress.stop -text \"Break\" -relief groove -width 9 -command {XProgress -stop %p};"
160 "pack .xprogress.bar .xprogress.text .xprogress.stop -side top;", this );
caee80f3 161 myDraw->Eval ( command );
7fd59977 162 myShown = Standard_True;
163 }
53d770b3 164 std::stringstream aCommand;
165 aCommand.setf(std::ios::fixed, std::ios::floatfield);
166 aCommand.precision(0);
167 aCommand << ".xprogress.bar coords progress 2 2 " << (1 + 400 * GetPosition()) << " 21;";
7e785937 168 aCommand << ".xprogress.bar coords progress_next 2 2 " << (1 + 400 * theScope.GetPortion()) << " 21;";
53d770b3 169 aCommand << ".xprogress.text configure -text \"" << aText.str() << "\";";
170 aCommand << "update";
caee80f3 171 myDraw->Eval (aCommand.str().c_str());
7fd59977 172 }
173
174 // Print textual progress info
7e785937 175 if (myTclMode && myDraw)
caee80f3 176 {
7e785937 177 *myDraw << aText.str().c_str() << "\n";
178 }
179 if (myConsoleMode)
180 {
181 std::cout << aText.str().c_str() << "\n";
caee80f3 182 }
7fd59977 183}
caee80f3 184
7fd59977 185//=======================================================================
186//function : UserBreak
187//purpose :
188//=======================================================================
189
190Standard_Boolean Draw_ProgressIndicator::UserBreak()
191{
7e785937 192 if ( StopIndicator() == this )
193 {
04232180 194// std::cout << "Progress Indicator - User Break: " << StopIndicator() << ", " << (void*)this << std::endl;
7fd59977 195 myBreak = Standard_True;
caee80f3 196 myDraw->Eval ( "XProgress -stop 0" );
7fd59977 197 }
7e785937 198 else
199 {
200 // treatment of Ctrl-Break signal
201 try
202 {
203 OSD::ControlBreak();
204 }
7a3e8aad 205 catch (const OSD_Exception_CTRL_BREAK&)
7e785937 206 {
207 myBreak = Standard_True;
208 }
209 }
7fd59977 210 return myBreak;
211}
212
213//=======================================================================
7e785937 214//function : SetTclMode
215//purpose : Sets Tcl output mode (on/off)
7fd59977 216//=======================================================================
217
7e785937 218void Draw_ProgressIndicator::SetTclMode(const Standard_Boolean theTclMode)
7fd59977 219{
7e785937 220 myTclMode = theTclMode;
7fd59977 221}
222
223//=======================================================================
7e785937 224//function : GetTclMode
225//purpose : Returns Tcl output mode (on/off)
7fd59977 226//=======================================================================
227
7e785937 228Standard_Boolean Draw_ProgressIndicator::GetTclMode() const
7fd59977 229{
7e785937 230 return myTclMode;
231}
232
233//=======================================================================
234//function : SetConsoleMode
235//purpose : Sets Console output mode (on/off)
236//=======================================================================
237
238void Draw_ProgressIndicator::SetConsoleMode(const Standard_Boolean theMode)
239{
240 myConsoleMode = theMode;
241}
242
243//=======================================================================
244//function : GetConsoleMode
245//purpose : Returns Console output mode (on/off)
246//=======================================================================
247
248Standard_Boolean Draw_ProgressIndicator::GetConsoleMode() const
249{
250 return myConsoleMode;
7fd59977 251}
252
253//=======================================================================
254//function : SetGraphMode
255//purpose : Sets graphical output mode (on/off)
256//=======================================================================
257
258void Draw_ProgressIndicator::SetGraphMode(const Standard_Boolean theGraphMode)
259{
260 myGraphMode = theGraphMode;
261}
262
263//=======================================================================
264//function : GetGraphMode
265//purpose : Returns graphical output mode (on/off)
266//=======================================================================
267
268Standard_Boolean Draw_ProgressIndicator::GetGraphMode() const
269{
270 return myGraphMode;
271}
272
273//=======================================================================
7e785937 274//function : DefaultTclMode
7fd59977 275//purpose :
276//=======================================================================
277
7e785937 278Standard_Boolean &Draw_ProgressIndicator::DefaultTclMode()
7fd59977 279{
7e785937 280 static Standard_Boolean defTclMode = Standard_False;
281 return defTclMode;
7fd59977 282}
caee80f3 283
7fd59977 284//=======================================================================
7e785937 285//function : DefaultConsoleMode
7fd59977 286//purpose :
287//=======================================================================
288
7e785937 289Standard_Boolean &Draw_ProgressIndicator::DefaultConsoleMode()
7fd59977 290{
7e785937 291 static Standard_Boolean defConsoleMode = Standard_False;
292 return defConsoleMode;
7fd59977 293}
caee80f3 294
295//=======================================================================
7e785937 296//function : DefaultGraphMode
297//purpose :
caee80f3 298//=======================================================================
299
7e785937 300Standard_Boolean &Draw_ProgressIndicator::DefaultGraphMode()
caee80f3 301{
7e785937 302 static Standard_Boolean defGraphMode = Standard_False;
303 return defGraphMode;
caee80f3 304}
305
7fd59977 306//=======================================================================
307//function : StopIndicator
308//purpose :
309//=======================================================================
310
caee80f3 311Standard_Address &Draw_ProgressIndicator::StopIndicator()
7fd59977 312{
68299304 313 static Standard_Address stopIndicator = 0;
7fd59977 314 return stopIndicator;
315}
316
317