-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprogressbar.m
319 lines (286 loc) · 10.8 KB
/
progressbar.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
%this m-file modified by Quan Quach on 12/12/07
%email: [email protected]
%Original Author: Steve Hoelzer
function [stopBar] = progressbar(fractiondone, position)
if(~exist('fractiondone'))
return
end
% Description:
% progressbar(fractiondone,position) provides an indication of the progress of
% some task using graphics and text. Calling progressbar repeatedly will update
% the figure and automatically estimate the amount of time remaining.
% This implementation of progressbar is intended to be extremely simple to use
% while providing a high quality user experience.
%
% Features:
% - Can add progressbar to existing m-files with a single line of code.
% - The figure closes automatically when the task is complete.
% - Only one progressbar can exist so old figures don't clutter the desktop.
% - Remaining time estimate is accurate even if the figure gets closed.
% - Minimal execution time. Won't slow down code.
% - Random color and position options. When a programmer gets bored....
%
% Usage:
% fractiondone specifies what fraction (0.0 - 1.0) of the task is complete.
% Typically, the figure will be updated according to that value. However, if
% fractiondone == 0.0, a new figure is created (an existing figure would be
% closed first). If fractiondone == 1.0, the progressbar figure will close.
% position determines where the progressbar figure appears on screen. This
% argument only has an effect when a progress bar is first created or is reset
% by calling with fractiondone = 0. The progress bar's position can be specifed
% as follows:
% [x, y] - Position of lower left corner in normalized units (0.0 - 1.0)
% 0 - Centered (Default)
% 1 - Upper right
% 2 - Upper left
% 3 - Lower left
% 4 - Lower right
% 5 - Random [x, y] position
% The color of the progressbar is choosen randomly when it is created or
% reset. Clicking inside the figure will cause a random color change.
% For best results, call progressbar(0) (or just progressbar) before starting
% a task. This sets the proper starting time to calculate time remaining.
%
% Example Function Calls:
% progressbar(fractiondone,position)
% progressbar % Initialize/reset
% progressbar(0) % Initialize/reset
% progressbar(0,4) % Initialize/reset and specify position
% progressbar(0,[0.2 0.7]) % Initialize/reset and specify position
% progressbar(0.5) % Update
% progressbar(1) % Close
%
% Demo:
% n = 1000;
% progressbar % Create figure and set starting time
% for i = 1:n
% pause(0.01) % Do something important
% progressbar(i/n) % Update figure
% end
%
% Author: Steve Hoelzer
%
% Revisions:
% 2002-Feb-27 Created function
% 2002-Mar-19 Updated title text order
% 2002-Apr-11 Use floor instead of round for percentdone
% 2002-Jun-06 Updated for speed using patch (Thanks to waitbar.m)
% 2002-Jun-19 Choose random patch color when a new figure is created
% 2002-Jun-24 Click on bar or axes to choose new random color
% 2002-Jun-27 Calc time left, reset progress bar when fractiondone == 0
% 2002-Jun-28 Remove extraText var, add position var
% 2002-Jul-18 fractiondone input is optional
% 2002-Jul-19 Allow position to specify screen coordinates
% 2002-Jul-22 Clear vars used in color change callback routine
% 2002-Jul-29 Position input is always specified in pixels
% 2002-Sep-09 Change order of title bar text
% 2003-Jun-13 Change 'min' to 'm' because of built in function 'min'
% 2003-Sep-08 Use callback for changing color instead of string
% 2003-Sep-10 Use persistent vars for speed, modify titlebarstr
% 2003-Sep-25 Correct titlebarstr for 0% case
% 2003-Nov-25 Clear all persistent vars when percentdone = 100
% 2004-Jan-22 Cleaner reset process, don't create figure if percentdone = 100
% 2004-Jan-27 Handle incorrect position input
% 2004-Feb-16 Minimum time interval between updates
% 2004-Apr-01 Cleaner process of enforcing minimum time interval
% 2004-Oct-08 Seperate function for timeleftstr, expand to include days
% 2004-Oct-20 Efficient if-else structure for sec2timestr
%
stopBar = 0;
persistent progfig progpatch starttime lastupdate firstIteration
% Set defaults for variables not passed in
if nargin < 1
fractiondone = 0;
end
if nargin < 2
position = 0;
end
try
% Access progfig to see if it exists ('try' will fail if it doesn't)
dummy = get(progfig,'UserData');
% If progress bar needs to be reset, close figure and set handle to empty
if fractiondone == 0
delete(progfig) % Close progress bar
progfig = []; % Set to empty so a new progress bar is created
end
catch
progfig = []; % Set to empty so a new progress bar is created
end
percentdone = floor(100*fractiondone);
% Create new progress bar if needed
if (isempty(progfig) && (isempty(firstIteration)))
firstIteration = 1;
% Calculate position of progress bar in normalized units
scrsz = [0 0 1 1];
width = scrsz(3)/4;
height = scrsz(4)/50;
if (length(position) == 1)
hpad = scrsz(3)/64; % Padding from left or right edge of screen
vpad = scrsz(4)/24; % Padding from top or bottom edge of screen
left = scrsz(3)/2 - width/2; % Default
bottom = scrsz(4)/2 - height/2; % Default
switch position
case 0 % Center
% Do nothing (default)
case 1 % Top-right
left = scrsz(3) - width - hpad;
bottom = scrsz(4) - height - vpad;
case 2 % Top-left
left = hpad;
bottom = scrsz(4) - height - vpad;
case 3 % Bottom-left
left = hpad;
bottom = vpad;
case 4 % Bottom-right
left = scrsz(3) - width - hpad;
bottom = vpad;
case 5 % Random
left = rand * (scrsz(3)-width);
bottom = rand * (scrsz(4)-height);
otherwise
warning('position must be (0-5). Reset to 0.')
end
position = [left bottom];
elseif length(position) == 2
% Error checking on position
if (position(1) < 0) || (scrsz(3)-width < position(1))
position(1) = max(min(position(1),scrsz(3)-width),0);
warning('Horizontal position adjusted to fit on screen.')
end
if (position(2) < 0) || (scrsz(4)-height < position(2))
position(2) = max(min(position(2),scrsz(4)-height),0);
warning('Vertical position adjusted to fit on screen.')
end
else
error('position is not formatted correctly')
end
% Initialize progress bar
progfig = figure(...
'Units', 'normalized',...
'Position', [position width height],...
'NumberTitle', 'off',...
'Resize', 'off',...
'MenuBar', 'none',...
'BackingStore', 'off' );
progaxes = axes(...
'Position', [0.02 0.15 0.96 0.70],...
'XLim', [0 1],...
'YLim', [0 1],...
'Box', 'on',...
'ytick', [],...
'xtick', [] );
progpatch = patch(...
'XData', [0 0 0 0],...
'YData', [0 0 1 1],...
'EraseMode', 'none' );
% enable this code if you want the bar to change colors when the
% user clicks on the progress bar
% set(progfig, 'ButtonDownFcn',{@changecolor,progpatch});
% set(progaxes, 'ButtonDownFcn',{@changecolor,progpatch});
% set(progpatch,'ButtonDownFcn',{@changecolor,progpatch});
% changecolor(0,0,progpatch)
set(progpatch,'FaceColor',[.1 1 .1]);
% Set time of last update to ensure a redraw
lastupdate = clock - 1;
% Task starting time reference
if isempty(starttime) || (fractiondone == 0)
starttime = clock;
end
set(progfig,'CloseRequestFcn',@closeBar);
end
%if the user closes the progress bar during the data processing
%then this will erase all the variables are return 1 to the output
if (isempty(progfig) && ~(fractiondone==0))
delete(progfig) % Close progress bar
% Clear persistent vars
clear progfig progpatch starttime lastupdate firstIteration
stopBar = 1;
return
end
%Enforce a minimum time interval between updates
%but allows for the case when the bar reaches 100% so that the user can see
%it
if (etime(clock,lastupdate) < 0.01 && ~(percentdone == 100))
return
end
% Update progress patch
set(progpatch,'XData',[0 fractiondone fractiondone 0])
% Update progress figure title bar
if (fractiondone == 0)
titlebarstr = ' 0%';
else
titlebarstr = sprintf(' %2d%% complete',percentdone);
end
set(progfig,'Name',titlebarstr)
% Force redraw to show changes
drawnow
% If task completed, close figure and clear vars, then exit
if percentdone == 100 % Task completed
delete(progfig) % Close progress bar
%change the close request function back to normal
%set(progfig,'CloseRequestFcn','closereq');
% Clear persistent vars
clear progfig progpatch starttime lastupdate firstIteration
return
end
% Record time of this update
% lastupdate = clock;
%%
% ------------------------------------------------------------------------------
% function changecolor(h,e,progpatch)
% % Change the color of the progress bar patch
%
% colorlim = 2.8; % Must be <= 3.0 - This keeps the color from being too light
% thiscolor = rand(1,3);
% while sum(thiscolor) > colorlim
% thiscolor = rand(1,3);
% end
% set(progpatch,'FaceColor',thiscolor);
%%
% ------------------------------------------------------------------------------
% function timestr = sec2timestr(sec)
% % Convert a time measurement from seconds into a human readable string.
%
% % Convert seconds to other units
% d = floor(sec/86400); % Days
% sec = sec - d*86400;
% h = floor(sec/3600); % Hours
% sec = sec - h*3600;
% m = floor(sec/60); % Minutes
% sec = sec - m*60;
% s = floor(sec); % Seconds
%
% % Create time string
% if d > 0
% if d > 9
% timestr = sprintf('%d day',d);
% else
% timestr = sprintf('%d day, %d hr',d,h);
% end
% elseif h > 0
% if h > 9
% timestr = sprintf('%d hr',h);
% else
% timestr = sprintf('%d hr, %d min',h,m);
% end
% elseif m > 0
% if m > 9
% timestr = sprintf('%d min',m);
% else
% timestr = sprintf('%d min, %d sec',m,s);
% end
% else
% timestr = sprintf('%d sec',s);
% end
% function closeBar(src,evnt)
%
% selection = questdlg('Do you want to stop this process?',...
% 'Stop process',...
% 'Yes','No','Yes');
% switch selection,
% case 'Yes',
% delete(gcf)
% case 'No'
% return
% end
function closeBar(src,evnt)