1  /*
     2   Copyright aswing.org, see the LICENCE.txt.
     3  */
     4  import org.aswing.ASWingConstants;
     5  import org.aswing.BoundedRangeModel;
     6  import org.aswing.Component;
     7  import org.aswing.DefaultBoundedRangeModel;
     8  import org.aswing.Icon;
     9  import org.aswing.plaf.ProgressBarUI;
    10  import org.aswing.UIManager;
    11  import org.aswing.utils.Timer;
    12  
    13  /**
    14   * @author iiley
    15   */
    16  class org.aswing.JProgressBar extends Component {
    17  	/**
    18  	 * When the progressBar's progress state changed.
    19  	 *<br>
    20  	 * onStateChanged Event{source:JProgressBar}
    21  	 * @see org.aswing.BoundedRangeModel#addChangeListener()
    22  	 */	
    23  	public static var ON_STATE_CHANGED:String = Component.ON_STATE_CHANGED;	
    24  		
    25      /** 
    26       * Horizontal orientation.
    27       */
    28      public static var HORIZONTAL:Number = ASWingConstants.HORIZONTAL;
    29      /** 
    30       * Vertical orientation.
    31       */
    32      public static var VERTICAL:Number   = ASWingConstants.VERTICAL;
    33  	
    34  	private var orientation:Number;
    35  	private var indeterminate:Boolean;
    36  	private var icon:Icon;
    37  	private var string:String;
    38  	private var model:BoundedRangeModel;
    39  	private var indeterminatePaintTimer:Timer;
    40  	private var modelListener:Object;
    41  	
    42  	/**
    43  	 * JProgressBar(orient:Number, min:Number, max:Number)<br>
    44  	 * JProgressBar(orient:Number)<br>
    45  	 * JProgressBar()
    46  	 * <p>
    47  	 * @param orient (optional)the desired orientation of the progress bar, 
    48  	 *  just can be <code>JProgressBar.HORIZONTAL</code> or <code>JProgressBar.VERTICAL</code>,
    49  	 *  default is <code>JProgressBar.HORIZONTAL</code>
    50  	 * @param min (optional)the minimum value of the progress bar, default is 0
    51  	 * @param max (optional)the maximum value of the progress bar, default is 100
    52  	 */
    53  	public function JProgressBar(orient:Number, min:Number, max:Number) {
    54  		super();
    55  		setName("ProgressBar");
    56  		
    57  		if(orient == undefined) orient = HORIZONTAL;
    58  		if(min == undefined) min = 0;
    59  		if(max == undefined) max = 100;
    60  		
    61  		orientation = orient;
    62  		model = new DefaultBoundedRangeModel(min, 0, min, max);
    63  		addListenerToModel();
    64  		
    65  		indeterminate = false;
    66  		string = null;
    67  		icon = undefined; //Pluginable from UI
    68  		
    69  		indeterminatePaintTimer = new Timer(50);
    70  		indeterminatePaintTimer.addActionListener(__indeterminateInterval, this);
    71  		
    72  		addEventListener(ON_CREATED, __validateIndeterminateIntervalIfNecessary, this);
    73  		addEventListener(ON_DESTROY, __validateIndeterminateIntervalIfNecessary, this);
    74  		
    75  		updateUI();
    76  	}
    77  	
    78      public function updateUI():Void{
    79      	setUI(ProgressBarUI(UIManager.getUI(this)));
    80      }
    81      
    82      public function setUI(newUI:ProgressBarUI):Void{
    83      	super.setUI(newUI);
    84      }
    85  	
    86  	public function getUIClassID():String{
    87  		return "ProgressBarUI";
    88  	} 
    89  	    
    90  	/**
    91       * Returns the data model used by this progress bar.
    92       *
    93       * @return the <code>BoundedRangeModel</code> currently in use
    94       * @see    org.aswing.BoundedRangeModel
    95       */
    96  	public function getModel():BoundedRangeModel {
    97  		return model;
    98  	}
    99  	
   100      /**
   101       * Sets the data model used by the <code>JProgressBar</code>.
   102       *
   103       * @param  newModel the <code>BoundedRangeModel</code> to use
   104       */
   105  	public function setModel(newModel:BoundedRangeModel):Void {
   106  		var oldModel:BoundedRangeModel = model;
   107  		if (model != null){
   108  			model.removeEventListener(modelListener);
   109  		}
   110  		model = newModel;
   111  		if (model != null){
   112  			model.setExtent(0);
   113  			addListenerToModel();
   114  		}
   115  	}
   116  	
   117  	/**
   118  	 * Returns the icon used by this progress bar.
   119  	 * 
   120  	 * @return the <code>Icon</code> currently in use
   121  	 */
   122  	public function getIcon():Icon {
   123  		return icon;
   124  	}
   125  	
   126  	/**
   127  	 * Sets the icon used by the <code>JProgressBar</code>.
   128  	 * Genarally the LookAndFeel UI for <code>JProgressBar</code> will set 
   129  	 * a icon to paint the progress, if you want a custom icon, you can 
   130  	 * set a new icon by this method, and your custom icon should paint the 
   131  	 * progress by the model data or indeterminate property.
   132  	 * 
   133  	 * @param icon the <code>Icon</code> to paint the progress.
   134  	 * @see #getModel()
   135  	 * @see #isIndeterminate()
   136  	 */
   137  	public function setIcon(icon:Icon):Void {
   138  		if(this.icon != icon){
   139  			if(this.icon != null){
   140  				uninstallIconWhenNextPaint(this.icon);
   141  			}
   142  			this.icon = icon;
   143  			repaint();
   144  		}
   145  	}
   146  	
   147      /**
   148       * Returns the current value of the progress string.
   149       * @return the value of the progress string
   150       * @see    #setString
   151       */
   152  	public function getString():String {
   153  		return string;
   154  	}
   155  
   156      /**
   157       * Sets the value of the progress string. By default,
   158       * this string is <code>null</code>, will paint nothing text.
   159       * @param  s the value of the progress string
   160       * @see    #getString()
   161       */
   162  	public function setString(s:String):Void {
   163  		if(string != s){
   164  			string = s;
   165  			repaint();
   166  		}
   167  	}
   168  
   169      /**
   170       * Returns <code>JProgressBar.VERTICAL</code> or 
   171       * <code>JProgressBar.HORIZONTAL</code>, depending on the orientation
   172       * of the progress bar. The default orientation is 
   173       * <code>HORIZONTAL</code>.
   174       *
   175       * @return <code>HORIZONTAL</code> or <code>VERTICAL</code>
   176       * @see #setOrientation()
   177       */
   178  	public function getOrientation():Number {
   179  		return orientation;
   180  	}
   181  	
   182      /**
   183       * Sets the progress bar's orientation to <code>newOrientation</code>, 
   184       * which must be <code>JProgressBar.VERTICAL</code> or 
   185       * <code>JProgressBar.HORIZONTAL</code>. The default orientation 
   186       * is <code>HORIZONTAL</code>.
   187       * <p>
   188       * Note that If the orientation is set to <code>VERTICAL</code>,
   189       *  the progress string can only be displayable when the progress bar's font 
   190       *  is a embedFonts.
   191       * 
   192       * @param  newOrientation  <code>HORIZONTAL</code> or <code>VERTICAL</code>
   193       * @see #getOrientation()
   194       * @see org.aswing.ASFont#getEmbedFonts()
   195       */
   196  	public function setOrientation(newOrientation:Number):Void {
   197  		if(newOrientation != HORIZONTAL && newOrientation!= VERTICAL){
   198  			newOrientation = HORIZONTAL;
   199  		}
   200  		if(orientation != newOrientation){
   201  			orientation = newOrientation;
   202  			revalidate();
   203  			repaint();
   204  		}
   205  	}
   206  	
   207      /**
   208       * Returns the percent complete for the progress bar.
   209       * Note that this number is between 0.0 and 1.0.
   210       *
   211       * @return the percent complete for this progress bar
   212       */
   213      public function getPercentComplete():Number {
   214  		var span:Number = model.getMaximum() - model.getMinimum();
   215  		var currentValue:Number = model.getValue();
   216  		var pc:Number = (currentValue - model.getMinimum()) / span;
   217  		return pc;
   218      }
   219      
   220      /**
   221       * Returns the progress bar's current value,
   222       * which is stored in the progress bar's <code>BoundedRangeModel</code>.
   223       * The value is always between the 
   224       * minimum and maximum values, inclusive. By default, the 
   225       * value is initialized to be equal to the minimum value.
   226       *
   227       * @return  the current value of the progress bar
   228       * @see     #setValue()
   229       * @see     org.aswing.BoundedRangeModel#getValue()
   230       */
   231  	public function getValue():Number{
   232  		return getModel().getValue();
   233  	}
   234      /**
   235       * Returns the progress bar's minimum value,
   236       * which is stored in the progress bar's <code>BoundedRangeModel</code>.
   237       * By default, the minimum value is <code>0</code>.
   238       *
   239       * @return  the progress bar's minimum value
   240       * @see     #setMinimum()
   241       * @see     org.aswing.BoundedRangeModel#getMinimum()
   242       */	
   243  	public function getMinimum():Number{
   244  		return getModel().getMinimum();
   245  	}
   246  	/**
   247       * Returns the progress bar's maximum value,
   248       * which is stored in the progress bar's <code>BoundedRangeModel</code>.
   249       * By default, the maximum value is <code>100</code>.
   250       *
   251       * @return  the progress bar's maximum value
   252       * @see     #setMaximum()
   253       * @see     org.aswing.BoundedRangeModel#getMaximum()
   254       */
   255  	public function getMaximum():Number{
   256  		return getModel().getMaximum();
   257  	}
   258      /**
   259       * Sets the progress bar's current value 
   260       * (stored in the progress bar's data model) to <code>n</code>.
   261       * The data model (a <code>BoundedRangeModel</code> instance)
   262       * handles any mathematical
   263       * issues arising from assigning faulty values.
   264       * <p>
   265       * If the new value is different from the previous value,
   266       * all change listeners are notified.
   267       *
   268       * @param   n       the new value
   269       * @see     #getValue()
   270       * @see    #addChangeListener()
   271       * @see     org.aswing.BoundedRangeModel#setValue()
   272       */	
   273  	public function setValue(n:Number):Void{
   274  		getModel().setValue(n);
   275  	}
   276      /**
   277       * Sets the progress bar's minimum value 
   278       * (stored in the progress bar's data model) to <code>n</code>.
   279       * The data model (a <code>BoundedRangeModel</code> instance)
   280       * handles any mathematical
   281       * issues arising from assigning faulty values.
   282       * <p>
   283       * If the minimum value is different from the previous minimum,
   284       * all change listeners are notified.
   285       *
   286       * @param  n       the new minimum
   287       * @see    #getMinimum()
   288       * @see    #addChangeListener()
   289       * @see    org.aswing.BoundedRangeModel#setMinimum()
   290       */	
   291  	public function setMinimum(n:Number):Void{
   292  		getModel().setMinimum(n);
   293  	}
   294      /**
   295       * Sets the progress bar's maximum value
   296       * (stored in the progress bar's data model) to <code>n</code>.
   297       * The underlying <code>BoundedRangeModel</code> handles any mathematical
   298       * issues arising from assigning faulty values.
   299       * <p>
   300       * If the maximum value is different from the previous maximum,
   301       * all change listeners are notified.
   302       *
   303       * @param  n       the new maximum
   304       * @see    #getMaximum()
   305       * @see    #addChangeListener()
   306       * @see    org.aswing.BoundedRangeModel#setMaximum()
   307       */	
   308  	public function setMaximum(n:Number):Void{
   309  		getModel().setMaximum(n);
   310  	}
   311      /**
   312       * Sets the <code>indeterminate</code> property of the progress bar,
   313       * which determines whether the progress bar is in determinate
   314       * or indeterminate mode.
   315       * An indeterminate progress bar continuously displays animation
   316       * indicating that an operation of unknown length is occurring.
   317       * By default, this property is <code>false</code>.
   318       * <p>
   319       * An indeterminate progress bar will start a <code>Timer</code> to 
   320       * call repaint continuously when it is displayable, it make the progress can paint continuously.
   321       * Make sure the current <code>Icon</code> for this bar support indeterminate 
   322       * if you set indeterminate to true.
   323       * <p>
   324       * @param newValue	<code>true</code> if the progress bar
   325       * 			should change to indeterminate mode;
   326       * 			<code>false</code> if it should revert to normal.
   327       *
   328       * @see #isIndeterminate()
   329       */	
   330  	public function setIndeterminate(newValue:Boolean):Void{
   331  		indeterminate = newValue;
   332  		__validateIndeterminateIntervalIfNecessary();
   333  	}
   334      /**
   335       * Returns the value of the <code>indeterminate</code> property.
   336       *
   337       * @return the value of the <code>indeterminate</code> property
   338       * @see    #setIndeterminate()
   339       */	
   340  	public function isIndeterminate():Boolean{
   341  		return indeterminate;
   342  	}
   343  	
   344  	/**
   345  	 * @see #ON_STATE_CHANGED
   346  	 */
   347  	public function addChangeListener(func:Function, obj:Object):Object{
   348  		return addEventListener(ON_STATE_CHANGED, func, obj);
   349  	}
   350  	
   351  	//------------------
   352  	    
   353  	private function addListenerToModel():Void{
   354  		modelListener = model.addChangeListener(__onModelStateChanged, this);		
   355  	}
   356  	
   357  	private function __onModelStateChanged():Void{
   358  		fireStateChanged();
   359  	}
   360  	
   361  	private function __indeterminateInterval():Void{
   362  		repaint();
   363  	}
   364  	private function __validateIndeterminateIntervalIfNecessary():Void{
   365  		if(isDisplayable() && isIndeterminate()){
   366  			if(!indeterminatePaintTimer.isRunning()){
   367  				indeterminatePaintTimer.start();
   368  			}
   369  		}else{
   370  			if(indeterminatePaintTimer.isRunning()){
   371  				indeterminatePaintTimer.stop();
   372  			}
   373  		}
   374  	}
   375  }
   376