35c1b6f0452b9a4ba74af090068c539024110437
[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 <Standard_Type.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   myDraw ( (Standard_Address)&di ),
35   myShown ( Standard_False ),
36   myBreak ( Standard_False ),
37   myUpdateThreshold ( 0.01 * theUpdateThreshold ),
38   myLastPosition ( -1. ),
39   myStartTime ( 0 )
40 {
41 }
42
43 //=======================================================================
44 //function : ~Draw_ProgressIndicator
45 //purpose  : 
46 //=======================================================================
47
48 Draw_ProgressIndicator::~Draw_ProgressIndicator()
49 {
50   Reset();
51 }
52
53 //=======================================================================
54 //function : Reset
55 //purpose  : 
56 //=======================================================================
57
58 void Draw_ProgressIndicator::Reset()
59 {
60   Message_ProgressIndicator::Reset();
61   if ( myShown ) {
62     ((Draw_Interpretor*)myDraw)->Eval ( "destroy .xprogress" );
63     myShown = Standard_False;
64   }
65   myBreak = Standard_False;
66   myLastPosition = -1.;
67   myStartTime = 0;
68 }
69
70 //=======================================================================
71 //function : Show
72 //purpose  : 
73 //=======================================================================
74
75 Standard_Boolean Draw_ProgressIndicator::Show(const Standard_Boolean force)
76 {
77   if ( ! myGraphMode && ! myTextMode )
78     return Standard_False;
79
80   // remember time of the first call to Show as process start time
81   if ( ! myStartTime )
82   {
83     time_t aTimeT;
84     time ( &aTimeT );
85     myStartTime = (Standard_Size)aTimeT;
86   }
87
88   // unless show is forced, show updated state only if at least 1% progress has been reached since the last update
89   Standard_Real aPosition = GetPosition();
90   if ( ! force && aPosition < 1. && Abs (aPosition - myLastPosition) < myUpdateThreshold)
91     return Standard_False; // return if update interval has not elapsed
92   myLastPosition = aPosition;
93   
94   // Prepare textual progress info
95   char text[2048];
96   Standard_Integer n = 0;
97   n += Sprintf ( &text[n], "Progress: %.0f%%", 100. * GetPosition() );
98   for ( Standard_Integer i=GetNbScopes(); i >=1; i-- ) {
99     const Message_ProgressScale &scale = GetScope ( i );
100     if ( scale.GetName().IsNull() ) continue; // skip unnamed scopes
101     // if scope has subscopes, print end of subscope as its current position
102     Standard_Real locPos = ( i >1 ? GetScope ( i-1 ).GetLast() : GetPosition() );
103     // print progress info differently for finite and infinite scopes
104     if ( scale.GetInfinite() )
105       n += Sprintf ( &text[n], " %s: %.0f", scale.GetName()->ToCString(), 
106                      scale.BaseToLocal ( locPos ) );
107     else 
108       n += Sprintf ( &text[n], " %s: %.0f / %.0f", scale.GetName()->ToCString(), 
109                      scale.BaseToLocal ( locPos ), scale.GetMax() );
110   }
111
112   // Show graphic progress bar
113   if ( myGraphMode ) {
114
115     // In addition, write elapsed/estimated/remaining time
116     if ( GetPosition() > 0.01 ) { 
117       time_t aTimeT;
118       time ( &aTimeT );
119       Standard_Size aTime = (Standard_Size)aTimeT;
120       n += Sprintf ( &text[n], "\nElapsed/estimated time: %ld/%.0f sec", 
121                      (long)(aTime - myStartTime), ( aTime - myStartTime ) / GetPosition() );
122     }
123   
124     if ( ! myShown ) {
125       char command[1024];
126       Sprintf ( command, "toplevel .xprogress -height 100 -width 410;"
127                          "wm title .xprogress \"Progress\";"
128                          "set xprogress_stop 0;"
129                          "canvas .xprogress.bar -width 402 -height 22;"
130                          ".xprogress.bar create rectangle 2 2 2 21 -fill blue -tags progress;"
131                          ".xprogress.bar create rectangle 2 2 2 21 -outline black -tags progress_next;"
132                          "message .xprogress.text -width 400 -text \"Progress 0%%\";"
133                          "button .xprogress.stop -text \"Break\" -relief groove -width 9 -command {XProgress -stop %p};"
134                          "pack .xprogress.bar .xprogress.text .xprogress.stop -side top;", this );
135       ((Draw_Interpretor*)myDraw)->Eval ( command );
136       myShown = Standard_True;
137     }
138     char command[1024];
139     Standard_Integer num = 0;
140     num += Sprintf ( &command[num], ".xprogress.bar coords progress 2 2 %.0f 21;", 
141                   1+400*GetPosition() );
142     num += Sprintf ( &command[num], ".xprogress.bar coords progress_next 2 2 %.0f 21;", 
143                   1+400*GetScope(1).GetLast() );
144     num += Sprintf ( &command[num], ".xprogress.text configure -text \"%s\";", text );
145     num += Sprintf ( &command[num], "update" );
146     ((Draw_Interpretor*)myDraw)->Eval ( command );
147   }
148
149   // Print textual progress info
150   if ( myTextMode )
151     Message::DefaultMessenger()->Send (text, Message_Info);
152   
153   return Standard_True;
154 }
155        
156 //=======================================================================
157 //function : UserBreak
158 //purpose  : 
159 //=======================================================================
160
161 Standard_Boolean Draw_ProgressIndicator::UserBreak()
162 {
163   if ( StopIndicator() == this ) {
164 //    std::cout << "Progress Indicator - User Break: " << StopIndicator() << ", " << (void*)this << std::endl;
165     myBreak = Standard_True;
166     ((Draw_Interpretor*)myDraw)->Eval ( "XProgress -stop 0" );
167   }
168   return myBreak;
169 }
170        
171 //=======================================================================
172 //function : SetTextMode
173 //purpose  : Sets text output mode (on/off)
174 //=======================================================================
175
176 void Draw_ProgressIndicator::SetTextMode(const Standard_Boolean theTextMode)
177 {
178   myTextMode = theTextMode;
179 }
180
181 //=======================================================================
182 //function : GetTextMode
183 //purpose  : Returns text output mode (on/off)
184 //=======================================================================
185
186 Standard_Boolean Draw_ProgressIndicator::GetTextMode() const
187 {
188   return myTextMode;
189 }
190
191 //=======================================================================
192 //function : SetGraphMode
193 //purpose  : Sets graphical output mode (on/off)
194 //=======================================================================
195
196 void Draw_ProgressIndicator::SetGraphMode(const Standard_Boolean theGraphMode)
197 {
198   myGraphMode = theGraphMode;
199 }
200
201 //=======================================================================
202 //function : GetGraphMode
203 //purpose  : Returns graphical output mode (on/off)
204 //=======================================================================
205
206 Standard_Boolean Draw_ProgressIndicator::GetGraphMode() const
207 {
208   return myGraphMode;
209 }
210
211 //=======================================================================
212 //function : DefaultTextMode
213 //purpose  : 
214 //=======================================================================
215
216 Standard_Boolean &Draw_ProgressIndicator::DefaultTextMode () 
217 {
218   static Standard_Boolean defTextMode = Standard_False;
219   return defTextMode;
220 }
221     
222 //=======================================================================
223 //function : DefaultGraphMode
224 //purpose  : 
225 //=======================================================================
226
227 Standard_Boolean &Draw_ProgressIndicator::DefaultGraphMode () 
228 {
229   static Standard_Boolean defGraphMode = Standard_False;
230   return defGraphMode;
231 }
232     
233 //=======================================================================
234 //function : StopIndicator
235 //purpose  : 
236 //=======================================================================
237
238 Standard_Address &Draw_ProgressIndicator::StopIndicator ()
239 {
240   static Standard_Address stopIndicator = 0;
241   return stopIndicator;
242 }
243
244