opennurbs_progress_reporter.h
1 /* $NoKeywords: $ */
2 /*
3 //
4 // Copyright (c) 1993-2013 Robert McNeel & Associates. All rights reserved.
5 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
6 // McNeel & Associates.
7 //
8 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
9 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
10 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
11 //
12 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
13 //
14 ////////////////////////////////////////////////////////////////
15 */
16 
17 #if !defined(OPENNURBS_PROGRESS_REPORTER_INC_)
18 #define OPENNURBS_PROGRESS_REPORTER_INC_
19 
20 /////////////////////////////////////////////////////////////
21 //
22 // Calculation use ON_ProgressReporter to
23 // report progress to the calling code.
24 //
25 class ON_CLASS ON_ProgressReporter
26 {
27 public:
30 
31  /*
32  Description:
33  Set the function that is called when a calculation calls ReportProgress().
34  Parameters:
35  callback_function - [in]
36  * This function is called when the calculation reports progress.
37  * The calculation thread calls in this callback function.
38  * The callback function should do something that is fast and simple,
39  like post a message to a user interface control and return
40  immediately.
41  Paramters passed to the callback function:
42  context - [in]
43  the value of callback_context.
44  fraction_complete - [in]
45  A value between 0.0 and 1.0 indicating how much of the
46  calculation is compete.
47  Example:
48 
49  struct MyWindowsMessage
50  {
51  HWND m_hWnd;
52  UINT m_Msg,
53  WPARAM m_wParam
54  };
55 
56  ...
57 
58  void MyProgressCallback(
59  ON__UINT_PTR context,
60  double fraction_complete
61  )
62  {
63  if ( 0 != context )
64  {
65  MyWindowsMessage* msg = (MyWindowsMessage*)context;
66  LPARAM lParam = (UINT)ceil(100.0*fraction_complete); // 0 to 100.
67  PostWindowsMessage(msg.m_hWnd,msg.m_Msg,msg.m_wParam,lParam);
68  }
69  }
70 
71  ...
72 
73  struct MyWindowsMessage my_msg;
74  my_msg.m_hWnd = my progress bar window
75  my_msg.m_Msg = RegisterWindowMessage(L"MyProgressBarWindowsMessage");
76  my_msg.m_wParam = ...;
77 
78  ON_ProgressReporter pr;
79  pr.SetSynchronousProgressCallbackFunction(MyProgressCallback,&my_msg);
80  ...
81  Pass &pr to a calculation function. The calcuation will generally be running
82  in a different thread or allowing Windows messages to be pumped.
83  */
84  void SetSynchronousProgressCallbackFunction(
85  void (*callback_function)(ON__UINT_PTR context,double fraction_complete),
86  ON__UINT_PTR callback_context
87  );
88 
89  /*
90  Description:
91  The caclulation calls ON_ProgressReporter::ReportProgress to report
92  its current progress. If it is the first call to ReportProgress,
93  or the faction_complete is 1.0, or the fraction_complete has
94  increased a reasonable amount, then the callback function is called.
95  Parameters:
96  progress_reporter - [in]
97  A pointer to an ON_ProgressReporter or null pointer.
98  fraction_complete - [in]
99  a value between 0.0 and 1.0 where 0.0 indicates the calcuation
100  is beginning and 1.0 indicates the calculation is complete.
101  Example:
102  void MyLongCalculation( ..., ON_ProgressReporter* pr, ...)
103  {
104  ...
105  for ( i = 0; i < count; i++ )
106  {
107  ON_ProgressReporter::ReportProgress(pr,i/((double)count));
108  ...
109  }
110  ON_ProgressReporter::ReportProgress(pr,1.0); // finished
111  ...
112  }
113  */
114  static void ReportProgress(
115  ON_ProgressReporter* progress_reporter,
116  double fraction_complete
117  );
118 
119  /*
120  Description:
121  The caclulation calls ON_ProgressReporter::ReportProgress to report
122  its current progress. If it is the first call to ReportProgress,
123  or the faction_complete is 1.0, or the fraction_complete has
124  increased a reasonable amount, then the callback function is called.
125  Parameters:
126  progress_reporter - [in]
127  A pointer to an ON_ProgressReporter or null pointer.
128  fraction_complete - [in]
129  a value between 0.0 and 1.0 where 0.0 indicates the calcuation
130  is beginning and 1.0 indicates the calculation is complete.
131  Example:
132  void MyLongCalculation( ..., ON_ProgressReporter* pr, ...)
133  {
134  ...
135  for ( i = 0; i < count; i++ )
136  {
137  ON_ProgressReporter::ReportProgress(pr,i,count);
138  ...
139  }
140  ON_ProgressReporter::ReportProgress(pr,1.0); // finished
141  ...
142  }
143  */
144  static void ReportProgress(
145  ON_ProgressReporter* progress_reporter,
146  int i,
147  int max_i
148  );
149 
150  /*
151  Description:
152  The caclulation calls ON_ProgressReporter::ReportProgress to report
153  its current progress. If it is the first call to ReportProgress,
154  or the faction_complete is 1.0, or the fraction_complete has
155  increased a reasonable amount, then the callback function is called.
156  Parameters:
157  progress_reporter - [in]
158  A pointer to an ON_ProgressReporter or null pointer.
159  fraction_complete - [in]
160  a value between 0.0 and 1.0 where 0.0 indicates the calcuation
161  is beginning and 1.0 indicates the calculation is complete.
162  Example:
163  void MyLongCalculation( ..., ON_ProgressReporter* pr, ...)
164  {
165  ...
166  for ( i = 0; i < count; i++ )
167  {
168  ON_ProgressReporter::ReportProgress(pr,i,count);
169  ...
170  }
171  ON_ProgressReporter::ReportProgress(pr,1.0); // finished
172  ...
173  }
174  */
175  static void ReportProgress(
176  ON_ProgressReporter* progress_reporter,
177  unsigned int i,
178  unsigned int max_i
179  );
180 
181  /*
182  Description:
183  The calculation may call ON_ProgressReporter::FractionComplete to get
184  the current fraction completed.
185  Parameters:
186  progress_reporter - [in]
187  A pointer to an ON_ProgressReporter or null pointer.
188  Returns:
189  ON_UNSET_VALUE is returned when progress_reporter is nullptr.
190  Otherwise, a value between 0.0 and 1.0 is returned where 0.0 indicates
191  the calcuation is beginning and 1.0 indicates the calculation is complete.
192  */
193  static double FractionComplete(
194  ON_ProgressReporter* progress_reporter
195  );
196 
197 private:
198  void (*m_callback_function)(ON__UINT_PTR,double);
199  ON__UINT_PTR m_callback_context;
200  double m_fraction_complete;
201 
202  // Information for the previous call to callbackFunction
203  double m_previous_callback_fraction_complete;
204  ON__UINT64 m_reserved[4];
205 };
206 
207 class ON_CLASS ON_ProgressStepCounter
208 {
209 public:
210 
211  // This class makes it easy for functions to use a progress reporter.
212  ON_ProgressStepCounter() = default;
213  ~ON_ProgressStepCounter() = default;
214  ON_ProgressStepCounter(const ON_ProgressStepCounter&) = default;
215  ON_ProgressStepCounter& operator=(const ON_ProgressStepCounter&) = default;
216 
217  /*
218  Description:
219  When you have a process that needs to call a ON_ProgressReporter::ReportProgress()
220  a reasonable number of times and you can calculate the number of steps your process
221  takes, then ON_ProgressStepCounter will handle all the details.
222  Parameters:
223  progress_reporter - [in]
224  Parameter passed to ON_ProgressReporter::ReportProgress().
225  step_count - [in]
226  Number of steps.
227  Remarks:
228  This will create a ON_ProgressStepCounter that will call
229  ON_ProgressReporter::ReportProgress(progress_reporter) at most 101 times.
230  The first call reports progress 0.0.
231  The last call reports progress 1.0.
232  */
233  static ON_ProgressStepCounter Create(
234  ON_ProgressReporter* progress_reporter,
235  unsigned int step_count
236  );
237 
238  /*
239  Description:
240  When you have a process that needs to call a ON_ProgressReporter::ReportProgress()
241  a reasonable number of times and you can calculate the number of steps your process
242  takes, then ON_ProgressStepCounter will handle all the details.
243  Parameters:
244  progress_reporter - [in]
245  Parameter passed to ON_ProgressReporter::ReportProgress().
246  step_count - [in]
247  Number of steps.
248  progress_interval_start - [in]
249  progress_interval_finish - [in]
250  0.0 <= progress_interval_start < progress_interval_finish <= 1.0
251  maximum_progress_reports - [in]
252  Maximum number of times to call ON_ProgressReporter::ReportProgress()
253  after the initial call reporting progress of progress_interval_start.
254  10 to 100 are good values.
255  */
256  static ON_ProgressStepCounter Create(
257  ON_ProgressReporter* progress_reporter,
258  unsigned int step_count,
259  double progress_interval_start,
260  double progress_interval_finish,
261  unsigned int maximum_progress_reports
262  );
263 
264  static const ON_ProgressStepCounter Empty;
266  /*
267  Description:
268  Call IncrementStep() after you complete each step.
269  */
270  void IncrementStep();
271 
272  /*
273  Description:
274  Call Finished() after you complete the process.
275  */
276  void Finished();
277 
278  double Progress() const;
279 
280  unsigned int Step() const;
281 
282  unsigned int StepCount() const;
283 private:
284  ON_ProgressReporter* m_progress_reporter = nullptr;
285  unsigned int m_step_index = 0;
286  unsigned int m_step_count = 0;
287  unsigned int m_step_interval = 0;
288  double m_progress_interval_start = 0.0;
289  double m_progress_interval_finish = 0.0;
290 };
291 
292 #endif
Definition: opennurbs_progress_reporter.h:25