72e694453d856a393395040fd38ce120c928d2ce
[occt.git] / src / Draw / Draw_ProgressIndicator.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
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
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.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14
15 #include <Draw.hxx>
16 #include <Draw_Interpretor.hxx>
17 #include <Draw_ProgressIndicator.hxx>
18 #include <Message.hxx>
19 #include <Message_Messenger.hxx>
20 #include <Message_ProgressScale.hxx>
21 #include <Precision.hxx>
22
23 #include <stdio.h>
24 #include <time.h>
25 IMPLEMENT_STANDARD_RTTIEXT(Draw_ProgressIndicator,Message_ProgressIndicator)
26
27 //=======================================================================
28 //function : Draw_ProgressIndicator
29 //purpose  : 
30 //=======================================================================
31 Draw_ProgressIndicator::Draw_ProgressIndicator (const Draw_Interpretor &di, Standard_Real theUpdateThreshold)
32 : myTextMode ( DefaultTextMode() ),
33   myGraphMode ( DefaultGraphMode() ),
34   myTclOutput ( DefaultTclOutput() ),
35   myDraw ( (Draw_Interpretor*)&di ),
36   myShown ( Standard_False ),
37   myBreak ( Standard_False ),
38   myUpdateThreshold ( 0.01 * theUpdateThreshold ),
39   myLastPosition ( -1. ),
40   myStartTime ( 0 )
41 {
42 }
43
44 //=======================================================================
45 //function : ~Draw_ProgressIndicator
46 //purpose  : 
47 //=======================================================================
48
49 Draw_ProgressIndicator::~Draw_ProgressIndicator()
50 {
51   Reset();
52 }
53
54 //=======================================================================
55 //function : Reset
56 //purpose  : 
57 //=======================================================================
58
59 void Draw_ProgressIndicator::Reset()
60 {
61   Message_ProgressIndicator::Reset();
62   if ( myShown ) {
63     myDraw->Eval ( "destroy .xprogress" );
64     myShown = Standard_False;
65   }
66   myBreak = Standard_False;
67   myLastPosition = -1.;
68   myStartTime = 0;
69 }
70
71 //=======================================================================
72 //function : Show
73 //purpose  : 
74 //=======================================================================
75
76 Standard_Boolean Draw_ProgressIndicator::Show(const Standard_Boolean force)
77 {
78   if ( ! myGraphMode && ! myTextMode )
79     return Standard_False;
80
81   // remember time of the first call to Show as process start time
82   if ( ! myStartTime )
83   {
84     time_t aTimeT;
85     time ( &aTimeT );
86     myStartTime = (Standard_Size)aTimeT;
87   }
88
89   // unless show is forced, show updated state only if at least 1% progress has been reached since the last update
90   Standard_Real aPosition = GetPosition();
91   if ( ! force && aPosition < 1. && Abs (aPosition - myLastPosition) < myUpdateThreshold)
92     return Standard_False; // return if update interval has not elapsed
93   myLastPosition = aPosition;
94   
95   // Prepare textual progress info
96   std::stringstream aText;
97   aText.setf (std::ios::fixed, std:: ios::floatfield);
98   aText.precision(0);
99   aText << "Progress: " << 100. * GetPosition() << "%";
100   for ( Standard_Integer i=GetNbScopes(); i >=1; i-- ) {
101     const Message_ProgressScale &scale = GetScope ( i );
102     if ( scale.GetName().IsNull() ) continue; // skip unnamed scopes
103     aText << " " << scale.GetName()->ToCString() << ": ";
104
105     // if scope has subscopes, print end of subscope as it s current position
106     Standard_Real locPos = ( (i >1 && GetPosition()!=0) ? GetScope ( i-1 ).GetLast() : GetPosition() );
107     // print progress info differently for finite and infinite scopes
108     if ( scale.GetInfinite() )
109     {
110       Standard_Real aVal = scale.BaseToLocal(locPos);
111       if (Precision::IsInfinite(aVal))
112       {
113         aText << "finished";
114       }
115       else
116       {
117         aText << aVal;
118       }
119     }
120     else
121     {
122       aText << scale.BaseToLocal ( locPos ) << " / " << scale.GetMax();
123     }
124   }
125
126   // Show graphic progress bar
127   if ( myGraphMode ) {
128
129     // In addition, write elapsed/estimated/remaining time
130     if ( GetPosition() > 0.01 ) { 
131       time_t aTimeT;
132       time ( &aTimeT );
133       Standard_Size aTime = (Standard_Size)aTimeT;
134       aText << "\nElapsed/estimated time: " << (long)(aTime - myStartTime) <<
135                "/" << ( aTime - myStartTime ) / GetPosition() << " sec";
136     }
137   
138     if ( ! myShown ) {
139       char command[1024];
140       Sprintf ( command, "toplevel .xprogress -height 100 -width 410;"
141                          "wm title .xprogress \"Progress\";"
142                          "set xprogress_stop 0;"
143                          "canvas .xprogress.bar -width 402 -height 22;"
144                          ".xprogress.bar create rectangle 2 2 2 21 -fill blue -tags progress;"
145                          ".xprogress.bar create rectangle 2 2 2 21 -outline black -tags progress_next;"
146                          "message .xprogress.text -width 400 -text \"Progress 0%%\";"
147                          "button .xprogress.stop -text \"Break\" -relief groove -width 9 -command {XProgress -stop %p};"
148                          "pack .xprogress.bar .xprogress.text .xprogress.stop -side top;", this );
149       myDraw->Eval ( command );
150       myShown = Standard_True;
151     }
152     std::stringstream aCommand;
153     aCommand.setf(std::ios::fixed, std::ios::floatfield);
154     aCommand.precision(0);
155     aCommand << ".xprogress.bar coords progress 2 2 " << (1 + 400 * GetPosition()) << " 21;";
156     aCommand << ".xprogress.bar coords progress_next 2 2 " << (1 + 400 * GetScope(1).GetLast()) << " 21;";
157     aCommand << ".xprogress.text configure -text \"" << aText.str() << "\";";
158     aCommand << "update";
159     myDraw->Eval (aCommand.str().c_str());
160   }
161
162   // Print textual progress info
163   if (myTextMode)
164   {
165     if (myTclOutput && myDraw)
166     {
167       *myDraw << aText.str().c_str() << "\n";
168     }
169     else
170     {
171       std::cout << aText.str().c_str() << "\n";
172     }
173   }
174   return Standard_True;
175 }
176
177 //=======================================================================
178 //function : UserBreak
179 //purpose  : 
180 //=======================================================================
181
182 Standard_Boolean Draw_ProgressIndicator::UserBreak()
183 {
184   if ( StopIndicator() == this ) {
185 //    std::cout << "Progress Indicator - User Break: " << StopIndicator() << ", " << (void*)this << std::endl;
186     myBreak = Standard_True;
187     myDraw->Eval ( "XProgress -stop 0" );
188   }
189   return myBreak;
190 }
191        
192 //=======================================================================
193 //function : SetTextMode
194 //purpose  : Sets text output mode (on/off)
195 //=======================================================================
196
197 void Draw_ProgressIndicator::SetTextMode(const Standard_Boolean theTextMode)
198 {
199   myTextMode = theTextMode;
200 }
201
202 //=======================================================================
203 //function : GetTextMode
204 //purpose  : Returns text output mode (on/off)
205 //=======================================================================
206
207 Standard_Boolean Draw_ProgressIndicator::GetTextMode() const
208 {
209   return myTextMode;
210 }
211
212 //=======================================================================
213 //function : SetGraphMode
214 //purpose  : Sets graphical output mode (on/off)
215 //=======================================================================
216
217 void Draw_ProgressIndicator::SetGraphMode(const Standard_Boolean theGraphMode)
218 {
219   myGraphMode = theGraphMode;
220 }
221
222 //=======================================================================
223 //function : GetGraphMode
224 //purpose  : Returns graphical output mode (on/off)
225 //=======================================================================
226
227 Standard_Boolean Draw_ProgressIndicator::GetGraphMode() const
228 {
229   return myGraphMode;
230 }
231
232 //=======================================================================
233 //function : DefaultTextMode
234 //purpose  : 
235 //=======================================================================
236
237 Standard_Boolean &Draw_ProgressIndicator::DefaultTextMode()
238 {
239   static Standard_Boolean defTextMode = Standard_False;
240   return defTextMode;
241 }
242
243 //=======================================================================
244 //function : DefaultGraphMode
245 //purpose  : 
246 //=======================================================================
247
248 Standard_Boolean &Draw_ProgressIndicator::DefaultGraphMode()
249 {
250   static Standard_Boolean defGraphMode = Standard_False;
251   return defGraphMode;
252 }
253
254 //=======================================================================
255 //function : DefaultTclOutput
256 //purpose  :
257 //=======================================================================
258
259 Standard_Boolean &Draw_ProgressIndicator::DefaultTclOutput()
260 {
261   static Standard_Boolean defTclOutput = Standard_False;
262   return defTclOutput;
263 }
264
265 //=======================================================================
266 //function : StopIndicator
267 //purpose  : 
268 //=======================================================================
269
270 Standard_Address &Draw_ProgressIndicator::StopIndicator()
271 {
272   static Standard_Address stopIndicator = 0;
273   return stopIndicator;
274 }
275
276