Use the proper license header for the progress bar implementation.
[pithos] / src / gr / ebs / gss / client / ProgressBar.java
1 /*
2  * Copyright 2006 Robert Hanson <iamroberthanson AT gmail.com>
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *    http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package gr.ebs.gss.client;
18
19 import com.google.gwt.user.client.ui.FlexTable;
20 import com.google.gwt.user.client.ui.Grid;
21 import com.google.gwt.user.client.ui.Label;
22 import com.google.gwt.user.client.ui.VerticalPanel;
23
24 /**
25  * <P>
26  * A simple progress bar that uses table elements to show progress and with a
27  * basic time remaining calculation built in.
28  * <P>
29  * You can optionally display some text above the progress bar and/or display
30  * time remaining underneath the progress bar. To control the display of those
31  * features, set the options in the constructor as shown in the following usage
32  * example:
33  *
34  * <PRE>
35  * final ProgressBar progressBar = new ProgressBar(20, ProgressBar.SHOW_TIME_REMAINING + ProgressBar.SHOW_TEXT);
36  * progressBar.setText(&quot;Doing something...&quot;);
37  * RootPanel.get().add(progressBar);
38  * Timer t = new Timer() {
39  *
40  *      public void run() {
41  *              int progress = progressBar.getProgress() + 4;
42  *              if (progress &gt; 100)
43  *                      cancel();
44  *              progressBar.setProgress(progress);
45  *      }
46  * };
47  * t.scheduleRepeating(1000);
48  * </PRE>
49  * <P>
50  * How the time remaining is displayed can be controlled by setting the relevant
51  * messages using the language of your choice.
52  * <P>
53  * The default setting for the messages are as follows:
54  *
55  * <PRE>
56  * setSecondsMessage(&quot;Time remaining: {0} Seconds&quot;);
57  * setMinutesMessage(&quot;Time remaining: {0} Minutes&quot;);
58  * setHoursMessage(&quot;Time remaining: {0} Hours&quot;);
59  * </PRE>
60  * <P>
61  * To reset the time remaining/set the start time, simply set the progress to
62  * zero.
63  * <P>
64  * Some basic CSS styling is available to control the text, border around the
65  * progress bar itself and the colour of the progress bar elements.
66  *
67  * <PRE>
68  * .progressbar-text {
69  *     font-weight: bold;
70  * }
71  * .progressbar-remaining {
72  *     font-size: 12px;
73  *     font-style: italic;
74  * }
75  * .progressbar-outer {
76  *     border: 1px solid black;
77  * }
78  * .progressbar-inner {
79  *     border: 1px solid black;
80  *     margin: 1px;
81  * }
82  * .progressbar-bar {
83  *     width: 5px;
84  *     height: 15px;
85  *     margin: 1px;
86  * }
87  * .progressbar-fullbar {
88  *     background: blue;
89  * }
90  * .progressbar-blankbar {
91  *     background: #eee;
92  * }
93  *</PRE>
94  * <P>
95  * You can take advantage of the default style by adding the following to the
96  * head of your HTML page.
97  * <P>
98  * &lt;link rel="stylesheet" type="text/css" href="style/gwl-progressBar.css">
99  * <P>
100  * This style sheet also has two additional styles which you can use by adding
101  * the stye name to the widget. You can use either one of these, or use both
102  * combined.
103  *
104  * <PRE>
105  * ProgressBar progressBar = new ProgressBar(20);
106  * progressBar.addStyleName(&quot;progressbar-solid&quot;);
107  * progressBar.addStyleName(&quot;progressbar-noborder&quot;);
108  * </PRE>
109  *
110  * @author Bjarne Matzen - Bjarne[dot]Matzen[at]gmail[dot]com
111  */
112
113 public class ProgressBar extends VerticalPanel {
114
115         /**
116          * Option to show text label above progress bar
117          */
118         public static final int SHOW_TEXT = 2;
119
120         /**
121          * Option to show time remaining
122          */
123         public static final int SHOW_TIME_REMAINING = 1;
124
125         /**
126          * The time the progress bar was started
127          */
128         private long startTime = System.currentTimeMillis();
129
130         /**
131          * The number of bar elements to show
132          */
133         private int elements = 20;
134
135         /**
136          * Time element text
137          */
138         private String secondsMessage = "Estimated time remaining: {0} Seconds";
139
140         private String minutesMessage = "Estimated time remaining: {0} Minutes";
141
142         private String hoursMessage = "Estimated time remaining: {0} Hours";
143
144         /**
145          * Current progress (as a percentage)
146          */
147         private int progress = 0;
148
149         /**
150          * This is the frame around the progress bar
151          */
152         private FlexTable barFrame = new FlexTable();
153
154         /**
155          * This is the grid used to show the elements
156          */
157         private Grid elementGrid;
158
159         /**
160          * This is the current text label below the progress bar
161          */
162         private Label remainLabel = new Label();
163
164         /**
165          * This is the current text label above the progress bar
166          */
167         private Label textLabel = new Label();
168
169         /**
170          * internal flags for options
171          */
172         private boolean showRemaining = false;
173
174         private boolean showText = false;
175
176         /**
177          * Base constructor for this widget
178          *
179          * @param elements The number of elements (bars) to show on the progress bar
180          * @param options The display options for the progress bar
181          */
182         public ProgressBar(int elements, int options) {
183                 // Read the options and set convenience variables
184                 if ((options & SHOW_TIME_REMAINING) == SHOW_TIME_REMAINING)
185                         showRemaining = true;
186                 if ((options & SHOW_TEXT) == SHOW_TEXT)
187                         showText = true;
188
189                 // Set element count
190                 this.elements = elements;
191
192                 // Styling
193                 remainLabel.setStyleName("progressbar-remaining");
194                 textLabel.setStyleName("progressbar-text");
195
196                 // Initialize the progress elements
197                 elementGrid = new Grid(1, elements);
198                 elementGrid.setStyleName("progressbar-inner");
199                 elementGrid.setCellPadding(0);
200                 elementGrid.setCellSpacing(0);
201
202                 for (int loop = 0; loop < elements; loop++) {
203                         Grid elm = new Grid(1, 1);
204                         // elm.setHTML(0, 0, "&nbsp;");
205                         elm.setHTML(0, 0, "");
206                         elm.setStyleName("progressbar-blankbar");
207                         elm.addStyleName("progressbar-bar");
208                         elementGrid.setWidget(0, loop, elm);
209                 }
210
211                 // Create the container around the elements
212                 Grid containerGrid = new Grid(1, 1);
213                 containerGrid.setCellPadding(0);
214                 containerGrid.setCellSpacing(0);
215                 containerGrid.setWidget(0, 0, elementGrid);
216                 containerGrid.setStyleName("progressbar-outer");
217                 // containerGrid.setBorderWidth(1);
218
219                 // Set up the surrounding flex table based on the options
220                 int row = 0;
221                 if (showText)
222                         barFrame.setWidget(row++, 0, textLabel);
223                 barFrame.setWidget(row++, 0, containerGrid);
224                 if (showRemaining)
225                         barFrame.setWidget(row++, 0, remainLabel);
226
227                 barFrame.setWidth("100%");
228
229                 // Add the frame to the panel
230                 this.add(barFrame);
231
232                 // Initialize progress bar
233                 setProgress(0);
234         }
235
236         /**
237          * Constructor without options
238          *
239          * @param elements The number of elements (bars) to show on the progress bar
240          */
241         public ProgressBar(int elements) {
242                 this(elements, 0);
243         }
244
245         /**
246          * Set the current progress as a percentage
247          *
248          * @param percentage Set current percentage for the progress bar
249          */
250         public void setProgress(int percentage) {
251                 // Make sure we are error-tolerant
252                 if (percentage > 100)
253                         percentage = 100;
254                 if (percentage < 0)
255                         percentage = 0;
256
257                 // Set the internal variable
258                 progress = percentage;
259
260                 // Update the elements in the progress grid to
261                 // reflect the status
262                 int completed = elements * percentage / 100;
263                 for (int loop = 0; loop < elements; loop++) {
264                         Grid elm = (Grid) elementGrid.getWidget(0, loop);
265                         if (loop < completed) {
266                                 elm.setStyleName("progressbar-fullbar");
267                                 elm.addStyleName("progressbar-bar");
268                         } else {
269                                 elm.setStyleName("progressbar-blankbar");
270                                 elm.addStyleName("progressbar-bar");
271                         }
272                 }
273
274                 if (percentage > 0) {
275                         // Calculate the new time remaining
276                         long soFar = (System.currentTimeMillis() - startTime) / 1000;
277                         long remaining = soFar * (100 - percentage) / percentage;
278                         // Select the best UOM
279                         String remainText = secondsMessage;
280                         if (remaining > 120) {
281                                 remaining = remaining / 60;
282                                 remainText = minutesMessage;
283                                 if (remaining > 120) {
284                                         remaining = remaining / 60;
285                                         remainText = hoursMessage;
286                                 }
287                         }
288                         // Locate the position to insert out time remaining
289                         int pos = remainText.indexOf("{0}");
290                         if (pos >= 0) {
291                                 String trail = "";
292                                 if (pos + 3 < remainText.length())
293                                         trail = remainText.substring(pos + 3);
294                                 remainText = remainText.substring(0, pos) + remaining + trail;
295                         }
296                         // Set the label
297                         remainLabel.setText(remainText);
298                 } else
299                         // If progress is 0, reset the start time
300                         startTime = System.currentTimeMillis();
301         }
302
303         /**
304          * Get the current progress as a percentage
305          *
306          * @return Current percentage for the progress bar
307          */
308         public int getProgress() {
309                 return progress;
310         }
311
312         /**
313          * Get the text displayed above the progress bar
314          *
315          * @return the text
316          */
317         public String getText() {
318                 return textLabel.getText();
319         }
320
321         /**
322          * Set the text displayed above the progress bar
323          *
324          * @param text the text to set
325          */
326         public void setText(String text) {
327                 textLabel.setText(text);
328         }
329
330         /**
331          * Get the message used to format the time remaining text for hours
332          *
333          * @return the hours message
334          */
335         public String getHoursMessage() {
336                 return hoursMessage;
337         }
338
339         /**
340          * Set the message used to format the time remaining text below the progress
341          * bar. There are 3 messages used for hours, minutes and seconds
342          * respectively. The message must contain a placeholder for the value. The
343          * placeholder must be {0}. For example, the following is a valid message:
344          * "Hours remaining: {0}"
345          *
346          * @param hoursMessage the hours message to set
347          */
348         public void setHoursMessage(String hoursMessage) {
349                 this.hoursMessage = hoursMessage;
350         }
351
352         /**
353          * Get the message used to format the time remaining text for minutes
354          *
355          * @return the minutesMessage
356          */
357         public String getMinutesMessage() {
358                 return minutesMessage;
359         }
360
361         /**
362          * Set the message used to format the time remaining text below the progress
363          * bar. There are 3 messages used for hours, minutes and seconds
364          * respectively. The message must contain a placeholder for the value. The
365          * placeholder must be {0}. For example, the following is a valid message:
366          * "Minutes remaining: {0}"
367          *
368          * @param minutesMessage the minutes message to set
369          */
370         public void setMinutesMessage(String minutesMessage) {
371                 this.minutesMessage = minutesMessage;
372         }
373
374         /**
375          * Get the message used to format the time remaining text for seconds
376          *
377          * @return the secondsMessage
378          */
379         public String getSecondsMessage() {
380                 return secondsMessage;
381         }
382
383         /**
384          * Set the message used to format the time remaining text below the progress
385          * bar. There are 3 messages used for hours, minutes and seconds
386          * respectively. The message must contain a placeholder for the value. The
387          * placeholder must be {0}. For example, the following is a valid message:
388          * "Seconds remaining: {0}"
389          *
390          * @param secondsMessage the secondsMessage to set
391          */
392         public void setSecondsMessage(String secondsMessage) {
393                 this.secondsMessage = secondsMessage;
394         }
395
396 }