001/* 002 * $RCSfile$ 003 * 004 * $Author: crawl $ 005 * $Date: 2014-08-26 00:46:48 +0000 (Tue, 26 Aug 2014) $ 006 * $Revision: 32920 $ 007 * 008 * For Details: http://kepler-project.org 009 * 010 * Copyright (c) 2007 The Regents of the University of California. 011 * All rights reserved. 012 * 013 * Permission is hereby granted, without written agreement and without 014 * license or royalty fees, to use, copy, modify, and distribute this 015 * software and its documentation for any purpose, provided that the 016 * above copyright notice and the following two paragraphs appear in 017 * all copies of this software. 018 * 019 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 020 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 021 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 022 * IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY 023 * OF SUCH DAMAGE. 024 * 025 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 026 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 027 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 028 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY 029 * OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 030 * UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 031 */ 032package org.kepler.monitor.figure; 033 034import java.awt.Color; 035import java.awt.event.ActionEvent; 036import java.awt.event.ActionListener; 037import java.awt.geom.RectangularShape; 038 039import javax.swing.Timer; 040 041import diva.canvas.toolbox.BasicFigure; 042 043/** 044 * A "progress bar" monitor figure. 045 * 046 * This figure has some similar functionality as that of 047 * {@link javax.swing.JProgressBar}. 048 * 049 * <p> 050 * By default, the progress bar will be indeterminate. In this case, an 051 * animation is set up to show a bouncing box within the given displayable area. 052 * 053 * @see org.kepler.monitor.test.ActorWithProgressBar 054 * 055 * @author Carlos Rueda 056 * @version $Id: ProgressBarFigure.java 32920 2014-08-26 00:46:48Z crawl $ 057 */ 058public class ProgressBarFigure extends BaseFigure { 059 060 /** 061 * Creates an horizontal and indeterminate progress bar figure. 062 * 063 * @param shape 064 * Rectangular shape for the progress bar. 065 */ 066 public ProgressBarFigure(RectangularShape shape) { 067 super(shape); 068 069 _orientation = Orientation.HORIZONTAL; 070 _indeterminate = true; 071 072 // _figs[0]: background; _figs[1]: foreground 073 074 _figs = new BasicFigure[2]; 075 _figs[0] = new BasicFigure(shape); 076 _figs[0].setFillPaint(_backgroundColor); 077 this.add(_figs[0]); 078 079 _figs[1] = new BasicFigure(shape); 080 _figs[1].setFillPaint(_foregroundColor); 081 this.add(_figs[1]); 082 } 083 084 /** 085 * Sets the orientation and calls {@link #update()} if the orientation 086 * changes. 087 * 088 * @param orientation 089 * the orientation. 090 */ 091 @Override 092 public void setOrientation(Orientation orientation) { 093 Orientation old = this._orientation; 094 this._orientation = orientation; 095 if (old != orientation) { 096 update(); 097 } 098 } 099 100 /** 101 * Set the indeterminate flag of this progress bar figure. 102 * 103 * @param indeterminate 104 * true for indeterminate, false for determinate. 105 */ 106 public void setIndeterminate(boolean indeterminate) { 107 boolean old = this._indeterminate; 108 this._indeterminate = indeterminate; 109 if (old != indeterminate) { 110 if (_started) { 111 if (_indeterminate) { 112 startTimer(); 113 } else { 114 stopTimer(); 115 } 116 } 117 update(); 118 } 119 } 120 121 /** 122 * Sets the maximum value, which is meaningful only for a determinate 123 * progress bar. 124 * 125 * @param n 126 * the maximum value. 127 */ 128 public void setMaximum(int n) { 129 _range.max = n; 130 if (!_indeterminate) { 131 update(); 132 } 133 } 134 135 /** 136 * Sets the minimum value, which is meaningful only for a determinate 137 * progress bar. 138 * 139 * @param n 140 * the minimum value. 141 */ 142 public void setMinimum(int n) { 143 _range.min = n; 144 if (!_indeterminate) { 145 update(); 146 } 147 } 148 149 /** 150 * Sets the current value, which is meaningful only for a determinate 151 * progress bar. 152 * 153 * @param n 154 * the current value. 155 */ 156 public void setValue(int n) { 157 int old = _range.cur; 158 _range.cur = n; 159 if (old != n && !_indeterminate) { 160 update(); 161 } 162 } 163 164 /** 165 * Tells if this progress bar is indeterminate. 166 * 167 * @return true iff this progress bar is indeterminate. 168 */ 169 public boolean isIndeterminate() { 170 return _indeterminate; 171 } 172 173 /** 174 * Gets the current value associated for a determinate progress bar. 175 * 176 * @return current value. 177 */ 178 public int getCurrentValue() { 179 return _range.cur; 180 } 181 182 /** 183 * Gets the maximum value in the range associated for a determinate progress 184 * bar. 185 * 186 * @return maximum value in range. 187 */ 188 public int getMaximum() { 189 return _range.max; 190 } 191 192 /** 193 * Gets the minimum value in the range associated for a determinate progress 194 * bar. 195 * 196 * @return minimum value in range. 197 */ 198 public int getMinimum() { 199 return _range.min; 200 } 201 202 /** 203 * @return the backgroundColor 204 */ 205 public Color getBackgroundColor() { 206 return _backgroundColor; 207 } 208 209 /** 210 * @param backgroundColor 211 * the backgroundColor to set 212 */ 213 public void setBackgroundColor(Color backgroundColor) { 214 this._backgroundColor = backgroundColor; 215 _figs[0].setFillPaint(backgroundColor); 216 update(); 217 } 218 219 /** 220 * @return the foregroundColor 221 */ 222 public Color getForegroundColor() { 223 return _foregroundColor; 224 } 225 226 /** 227 * @param foregroundColor 228 * the foregroundColor to set 229 */ 230 public void setForegroundColor(Color foregroundColor) { 231 this._foregroundColor = foregroundColor; 232 _figs[1].setFillPaint(foregroundColor); 233 update(); 234 } 235 236 /** 237 * Sets the rectangular shape for this figure. 238 * 239 * @param shape 240 */ 241 public void setShape(RectangularShape shape) { 242 this._shape = (RectangularShape) shape.clone(); 243 _figs[0].setShape(this._shape); 244 update(); 245 } 246 247 public void setStarted(boolean started) { 248 log.debug(Boolean.valueOf(started)); 249 _started = started; 250 if (_started) { 251 _figs[1].setFillPaint(_foregroundColor); 252 if (_indeterminate) { 253 startTimer(); 254 } 255 } else { 256 stopTimer(); 257 setValue(getMinimum() - 1); 258 update(); 259 } 260 } 261 262 // ///////////////////////////////////////////////////////////////// 263 // // protected members //// 264 265 /** 266 * Updates the appearance of this progress bar. 267 */ 268 @Override 269 protected void _update() { 270 double x = _shape.getX(); 271 double y = _shape.getY(); 272 double h = _shape.getHeight(); 273 double w = _shape.getWidth(); 274 275 RectangularShape rect1 = (RectangularShape) _figs[1].getShape(); 276 277 if (!_started) { 278 // a trick to "only" show the background 279 _figs[1].setFillPaint(_backgroundColor); 280 rect1.setFrame(x, y, w, h); 281 _figs[1].setShape(rect1); 282 return; 283 } 284 285 if (_orientation == Orientation.HORIZONTAL) { 286 if (_indeterminate) { 287 double xx = x + _indet.shift * w; 288 double ww = _indet.bbSize * w; 289 if (xx < x) { 290 ww -= x - xx; 291 xx = x; 292 } else if (xx + ww > x + w) { 293 ww = x + w - xx; 294 } 295 rect1.setFrame(xx, y, ww, h); 296 } else { 297 // always, left to right: 298 double ww = _range.fraction() * w; 299 rect1.setFrame(x, y, ww, h); 300 } 301 } else { 302 if (_indeterminate) { 303 double yy = y + _indet.shift * h; 304 double hh = _indet.bbSize * h; 305 if (yy < y) { 306 hh -= y - yy; 307 yy = y; 308 } else if (yy + hh > y + h) { 309 hh = y + h - yy; 310 } 311 rect1.setFrame(x, yy, w, hh); 312 } else { 313 // always, bottom to top: 314 double hh = _range.fraction() * h; 315 rect1.setFrame(x, y + h - hh, w, hh); 316 } 317 } 318 _figs[0].setShape(_shape); 319 _figs[1].setShape(rect1); 320 } 321 322 // ///////////////////////////////////////////////////////////////// 323 // // private members //// 324 325 /** 326 * Starts a timer for animating this indeterminate progress bar. Does 327 * nothing if <code>!this.isIndeterminate()</code>. 328 */ 329 private void startTimer() { 330 if (_timer == null && _indeterminate) { 331 _timer = new Timer(_indet.delay, new ActionListener() { 332 @Override 333 public void actionPerformed(ActionEvent ev) { 334 _indet.update(); 335 // we can call _update() directly because this runs on the 336 // event thread: 337 _lastUpdate = System.currentTimeMillis(); 338 _update(); 339 } 340 }); 341 _timer.start(); 342 if (isDebugging) { 343 log.debug("Started timer"); 344 } 345 } 346 } 347 348 /** 349 * Stops the timer for animating this indeterminate progress bar. Does 350 * nothing if no such timer has been created. 351 */ 352 private void stopTimer() { 353 if (_timer != null) { 354 _timer.stop(); 355 _timer = null; 356 if (isDebugging) { 357 log.debug("Stopped timer"); 358 } 359 } 360 } 361 362 /** to update an indeterminate progress bar */ 363 private Timer _timer; 364 365 private boolean _started; 366 367 private Color _backgroundColor = new Color(185, 185, 255); 368 private Color _foregroundColor = Color.CYAN; 369 private BasicFigure[] _figs; 370 371 private boolean _indeterminate; 372 373 /** Range in case of a determinate progress bar */ 374 private Range _range = new Range(0, 100); 375 376 /** Info in case of an indeterminate progress bar */ 377 private Indet _indet = new Indet(); 378 379 /** Range info for a determinate progress bar. */ 380 private final static class Range { 381 Range(int min, int max) { 382 this.min = min; 383 this.max = max; 384 this.cur = min - 1; 385 } 386 387 double fraction() { 388 return cur < min ? 0.0 : min >= max ? 1.0 : (double) (cur - min) 389 / (max - min); 390 } 391 392 int min; 393 int max; 394 int cur; 395 } 396 397 /** Info for an indeterminate progress bar. */ 398 private final static class Indet { 399 /** To repaint */ 400 final int delay = 55; 401 402 /** bouncing box size */ 403 final double bbSize = 0.3; 404 405 /** increment to update shift; should be < bbSize */ 406 double delta = 0.1; 407 408 /** we allow the bouncing box to "hide" by at most this fraction */ 409 final double hideSize = delta; 410 411 /** current position of bouncing box */ 412 double shift = Math.random(); // -hideSize; 413 414 /** updates position of bouncing box */ 415 void update() { 416 shift += delta; 417 if (shift < -hideSize) { 418 shift = -hideSize; 419 delta *= -1; 420 } else if (shift > 1.0 - (bbSize - hideSize)) { 421 shift = 1.0 - (bbSize - hideSize); 422 delta *= -1; 423 } 424 } 425 } 426 427}