All Downloads are FREE. Search and download functionalities are using the official Maven repository.

rwt.widgets.ProgressBar.js Maven / Gradle / Ivy

Go to download

The Rich Ajax Platform lets you build rich, Ajax-enabled Web applications.

There is a newer version: 3.29.0
Show newest version
/*******************************************************************************
 * Copyright (c) 2002, 2012 Innoopract Informationssysteme GmbH and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Innoopract Informationssysteme GmbH - initial API and implementation
 *    EclipseSource - ongoing development
 ******************************************************************************/

rwt.qx.Class.define( "rwt.widgets.ProgressBar", {
  extend : rwt.widgets.base.Parent,

  construct : function() {
    this.base( arguments );
    this.setOverflow( "hidden" );
    this.setAppearance( "progressbar" );
    this.setState( "normal" );
    this._timer = null;
    this._gfxCanvasAppended = false;
    // TODO [tb] : Create a superclass for vector-based widgets (canvas?)
    this._canvas = null;
    this._backgroundShape = null;
    this._indicatorShape = null;
    this._borderShape = null;
    this._useBorderShape = false;
    this._gfxBorderWidth = 0;
    this._indicatorVirtualPosition = 0;
    this._separatorStartShape = null;
    this._separatorEndShape = null;
    this._useSeparator = false;
    this._separatorWidth = 0;
    this._minimum = 0;
    this._maximum = 100;
    this._selection = 0;
  },

  destruct : function() {
    if( this._timer != null ) {
      this._timer.stop();
      this._timer.dispose();
    }
    this._timer = null;
    this._canvas = null;
    this._backgroundShape = null;
    this._indicatorShape = null;
    this._borderShape = null;
    this._separatorStartShape = null;
    this._separatorEndShape = null;
  },

  statics : {
    UNDETERMINED_SIZE : 40
  },

  events : {
    "minimumChanged" : "rwt.event.Event",
    "maximumChanged" : "rwt.event.Event",
    "selectionChanged" : "rwt.event.Event"
  },

  properties : {

    indicatorColor : {
      nullable : true,
      init : null,
      apply : "_applyIndicatorFill",
      themeable : true
    },

    // TODO [tb] : wrong offset in IE when vertical (or undetermined)
    indicatorImage : {
      nullable : true,
      init : null,
      apply : "_applyIndicatorFill",
      themeable : true
    },

    indicatorGradient : {
      nullable : true,
      init : null,
      apply : "_applyIndicatorFill",
      themeable : true
    },

    indicatorOpacity : {
      nullable : true,
      init : 1,
      apply : "_applyIndicatorFill",
      themeable : true
    },

    backgroundImageSized : {
      nullable : true,
      init : null,
      apply : "_applyBackgroundImageSized",
      themeable : true
    },

    separatorBorder : {
      nullable : true,
      init : null,
      apply : "_applySeparatorBorder",
      themeable : true
    }

  },

  members : {

    //////
    // API

    setMinimum : function( minimum ) {
      this._minimum = minimum;
      this.dispatchSimpleEvent( "minimumChanged" );
    },

    setMaximum : function( maximum ) {
      this._maximum = maximum;
      this.dispatchSimpleEvent( "maximumChanged" );
    },

    setSelection : function( selection ) {
      this._selection = selection;
      this.addToQueue( "indicatorSelection" );
      this.dispatchSimpleEvent( "selectionChanged" );
    },

    addState : function( state ) {
      if( state === "rwt_INDETERMINATE" ) {
        this._timer = new rwt.client.Timer( 120 );
        this._timer.addEventListener( "interval", this._onInterval, this );
        this._timer.start();
      }
      this.base( arguments, state );
    },

    setState : function( state ) {
      if( state == "error" ) {
        this.removeState( "normal" );
        this.removeState( "paused" );
        this.addState( "error" );
      } else if( state == "paused" ) {
        this.removeState( "normal" );
        this.removeState( "error" );
        this.addState( "paused" );
      } else {
        this.removeState( "error" );
        this.removeState( "paused" );
        this.addState( "normal" );
      }
    },

    //////////////
    // state-info

    _isIndeterminate : function() {
      return this.hasState( "rwt_INDETERMINATE" );
    },

    _isHorizontal : function() {
      return this.hasState( "rwt_HORIZONTAL" );
    },

    _isVertical : function() {
      return this.hasState( "rwt_VERTICAL" );
    },

    ////////////////
    // apply-methods

    // OVERWRITTEN, called indirectly by _applyBorder in rwt.widgets.base.Widget
    _queueBorder : function( value ) {
      this.addToQueue( "indicatorBorder" );
      if( value && value.getStyle() === "rounded" ) {
        // rounded borders are to be ignored by the qooxdoo-layouting:
        this._cachedBorderTop = 0;
        this._cachedBorderRight = 0;
        this._cachedBorderBottom = 0;
        this._cachedBorderLeft = 0;
        this._invalidateFrameDimensions();
      } else {
        this.base( arguments, value );
      }
    },

    // Overwritten from Widget
    _applyBackgroundColor : function( value ) {
      if( this._gfxCanvasAppended ) {
        this._styleBackgroundFill();
      }
    },

    // OVERWRITTEN FROM rwt.widgets.util.GraphicsMixin
    _applyBackgroundGradient : function( value ) {
      if( this._gfxCanvasAppended ) {
        this._styleBackgroundFill();
      }
    },

    _applyBackgroundImage : function( value ) {
      // nothing to do, uses _applyBackgroundImageSized instead
    },

    _applyBackgroundImageSized : function( value ) {
      if( this._gfxCanvasAppended ) {
        this._styleBackgroundFill();
      }
    },

    _applyIndicatorFill : function( value ) {
      if( this._gfxCanvasAppended ) {
        this._styleIndicatorFill();
      }
    },

    _applySeparatorBorder : function( value ) {
      this.addToQueue( "separatorBorder" );
    },

    ///////////////
    // eventhandler

    _onCanvasAppear : function() {
      rwt.graphics.GraphicsUtil.handleAppear( this._canvas );
    },

    _onInterval : function() {
      if( this.isSeeable() ) {
        this._renderIndicatorSelection();
      }
    },

    ///////
    // core

    _layoutPost : function( changes ) {
      if( !this._gfxCanvasAppended ) {
        this._createCanvas();
      }
      var dimensionChanged =    changes.width
                             || changes.height
                             || changes.frameWidth
                             || changes.frameHeight
                             || changes.initial;
      if( changes.separatorBorder ) {
        this._styleSeparatorBorder();
      }
      if( changes.indicatorBorder ) {
        this._styleIndicatorBorder();
      }
      if( changes.indicatorBorder || dimensionChanged ) {
        this._renderDimension();
        this._renderIndicatorSelection();
      } else if( changes.indicatorSelection || changes.separatorBorder ) {
        this._renderIndicatorSelection();
      }
    },

    _createCanvas : function() {
      var GraphicsUtil = rwt.graphics.GraphicsUtil;
      this._canvas = GraphicsUtil.createCanvas();
      this._getTargetNode().appendChild( GraphicsUtil.getCanvasNode( this._canvas ) );
      this._gfxCanvasAppended = true;
      this.addEventListener( "insertDom", this._onCanvasAppear );
      this._backgroundShape = GraphicsUtil.createShape( "roundrect" );
      this._indicatorShape = GraphicsUtil.createShape( "roundrect" );
      GraphicsUtil.addToCanvas( this._canvas, this._backgroundShape );
      GraphicsUtil.addToCanvas( this._canvas, this._indicatorShape );
      this._styleBackgroundFill();
      this._styleIndicatorFill();
      if( this.isSeeable() ) {
        this._onCanvasAppear();
      }
    },

    ///////////////
    // render style

    _styleIndicatorBorder : function() {
      var GraphicsUtil = rwt.graphics.GraphicsUtil;
      if( this.getBorder() && this.getBorder().getStyle() === "rounded" ) {
        if( !this._useBorderShape ) {
          this._style.border = "";
          if( this._borderShape == null ) {
            this._borderShape = GraphicsUtil.createShape( "roundrect" );
          }
          GraphicsUtil.addToCanvas( this._canvas, this._borderShape );
          this._useBorderShape = true;
        }
        this._gfxBorderWidth = this._getMaxBorderWidth( this.getBorder() );
        var color = this.getBorder().getColor();
        // NOTE : Different widths for different edges are not supported
        GraphicsUtil.setStroke( this._borderShape, color, this._gfxBorderWidth );
      } else {
        if( this._useBorderShape ) {
          GraphicsUtil.removeFromCanvas( this._canvas, this._borderShape );
          this._useBorderShape = true;
          this._gfxBorderWidth = 0;
        }
      }
    },

    _styleSeparatorBorder : function() {
      var GraphicsUtil = rwt.graphics.GraphicsUtil;
      var border = this.getSeparatorBorder();
      if( border != null ) {
        if( !this._useSeparator ) {
          if( this._isIndeterminate() ) {
            if( this._separatorStartShape == null ) {
              this._separatorStartShape = GraphicsUtil.createShape( "rect" );
            }
            GraphicsUtil.addToCanvas( this._canvas, this._separatorStartShape );
          }
          if( this._separatorEndShape == null ) {
            this._separatorEndShape = GraphicsUtil.createShape( "rect" );
          }
          GraphicsUtil.addToCanvas( this._canvas, this._separatorEndShape );
          this._useSeparator = true;
        }
        this._separatorWidth = this._getMaxBorderWidth( border );
        // use one color for all edges:
        var color = border.getColorTop();
        GraphicsUtil.setFillColor( this._separatorEndShape, color );
        if( this._isIndeterminate() ) {
          GraphicsUtil.setFillColor( this._separatorStartShape, color );
        }
      } else if( this._useSeparator ) {
        GraphicsUtil.removeFromCanvas( this._canvas, this._separatorEndShape );
        this._useSeparator = false;
        if( this._isIndeterminate() ) {
          GraphicsUtil.removeFromCanvas( this._canvas, this._separatorStartShape );
        }
        this._separatorWidth = 0;
      }
    },

    // indicator and separator do not support different border-widths
    _getMaxBorderWidth : function( border ) {
      var maxWidth = 0;
      maxWidth = Math.max( maxWidth, border.getWidthTop() );
      maxWidth = Math.max( maxWidth, border.getWidthLeft() );
      maxWidth = Math.max( maxWidth, border.getWidthRight() );
      maxWidth = Math.max( maxWidth, border.getWidthBottom() );
      return maxWidth;
    },

    _styleIndicatorFill : function() {
      var GraphicsUtil = rwt.graphics.GraphicsUtil;
      if(    this.getIndicatorImage() != null
          && this.getIndicatorImage()[ 0 ] != null )
      {
        var image = this.getIndicatorImage();
        GraphicsUtil.setFillPattern( this._indicatorShape,
                                image[ 0 ],
                                image[ 1 ],
                                image[ 2 ] );
      } else if( this.getIndicatorGradient() != null ) {
        GraphicsUtil.setFillGradient( this._indicatorShape,
                                 this.getIndicatorGradient() );
      } else {
        GraphicsUtil.setFillColor( this._indicatorShape, this.getIndicatorColor() );
      }
      GraphicsUtil.setOpacity( this._indicatorShape, this.getIndicatorOpacity() );
    },

    _styleBackgroundFill : function() {
      var GraphicsUtil = rwt.graphics.GraphicsUtil;
      if(    this.getBackgroundImageSized() != null
          && this.getBackgroundImageSized()[ 0 ] != null )
      {
        var image = this.getBackgroundImageSized();
        GraphicsUtil.setFillPattern( this._backgroundShape,
                                image[ 0 ],
                                image[ 1 ],
                                image[ 2 ] );
      } else if( this.getBackgroundGradient() != null ) {
        GraphicsUtil.setFillGradient( this._backgroundShape,
                                 this.getBackgroundGradient() );
      } else {
        GraphicsUtil.setFillColor( this._backgroundShape,
                              this.getBackgroundColor() );
      }
    },

    ////////////////
    // render layout

    _renderDimension : function() {
      var GraphicsUtil = rwt.graphics.GraphicsUtil;
      var radii = [ 0, 0, 0, 0 ];
      var width = this.getInnerWidth();
      var height = this.getInnerHeight();
      if( this._useBorderShape ) {
        radii = this.getBorder().getRadii();
        GraphicsUtil.setRoundRectLayout( this._borderShape,
                                    this._gfxBorderWidth / 2,
                                    this._gfxBorderWidth / 2,
                                    width - this._gfxBorderWidth,
                                    height - this._gfxBorderWidth,
                                    radii );
      }
      GraphicsUtil.setRoundRectLayout( this._backgroundShape,
                                  this._gfxBorderWidth / 2,
                                  this._gfxBorderWidth / 2,
                                  width - this._gfxBorderWidth,
                                  height - this._gfxBorderWidth,
                                  radii );
    },

    _renderIndicatorSelection : function() {
      var GraphicsUtil = rwt.graphics.GraphicsUtil;
      var virtualPosition = this._getIndicatorVirtualPosition();
      var position = Math.max( virtualPosition, 0 );
      var length = this._getIndicatorLength( virtualPosition );
      if( length > 0 ) {
        var radii = this._getIndicatorRadii( position, length );
        // adjust position and length to hide edges under the border
        var displayPosition = position;
        var displayLength = length;
        if( position + length == this._getIndicatorFullLength() ) {
          displayLength += this._gfxBorderWidth / 2;
        } else {
          // this is done to reduce flickering in IE:
          displayLength += this._separatorWidth;
        }
        if( displayPosition === 0 ) {
          displayPosition += this._gfxBorderWidth / 2;
          displayLength += this._gfxBorderWidth / 2;
        } else {
          displayPosition += this._gfxBorderWidth;
        }
        // compute bounds
        var vertical = this._isVertical();
        var width =   vertical
                    ? this.getInnerWidth() - this._gfxBorderWidth
                    : displayLength;
        var height =   vertical
                     ? displayLength
                     : this.getInnerHeight() - this._gfxBorderWidth;
        var top =   vertical
                  ? this.getInnerHeight() - ( displayPosition + displayLength )
                  : this._gfxBorderWidth / 2;
        var left = vertical ? this._gfxBorderWidth / 2 : displayPosition;
        var shape = this._indicatorShape;
        GraphicsUtil.setDisplay( this._indicatorShape, true );
        GraphicsUtil.setRoundRectLayout( shape, left, top, width, height, radii );
      } else {
        GraphicsUtil.setDisplay( this._indicatorShape, false );
      }
      if( this._useSeparator ) {
        this._renderSeparator( position, length );
      }
    },

    _renderSeparator : function( position, length ) {
      var GraphicsUtil = rwt.graphics.GraphicsUtil;
      var full = length + position == this._getIndicatorFullLength();
      if( length === 0 ) {
        GraphicsUtil.setDisplay( this._separatorEndShape, false );
        if( this._isIndeterminate() ) {
          GraphicsUtil.setDisplay( this._separatorStartShape, false );
        }
      } else {
        GraphicsUtil.setDisplay( this._separatorEndShape, !full );
        if( this._isIndeterminate() ) {
          GraphicsUtil.setDisplay( this._separatorStartShape, position !== 0 );
        }
        var displayPosition = position + this._gfxBorderWidth - this._separatorWidth;
        var displayLength = length + 2 * this._separatorWidth;
        if( this._isVertical() ) {
          var left = this._gfxBorderWidth;
          var top = this.getInnerHeight() - ( displayLength + displayPosition );
          var width = this.getInnerWidth() - 2 * this._gfxBorderWidth;
          var height = this._separatorWidth;
          var shape = this._separatorEndShape;
          if( !full ) {
            GraphicsUtil.setRectBounds( shape, left, top, width, height );
          }
          if( position !== 0 ) {
            top = this.getInnerHeight() - displayPosition - this._separatorWidth;
            shape = this._separatorStartShape;
            GraphicsUtil.setRectBounds( shape, left, top, width, height );
          }
        } else {
          var left = displayPosition + displayLength - this._separatorWidth;
          var top = this._gfxBorderWidth;
          var width = this._separatorWidth;
          var height = this.getInnerHeight() - 2 * this._gfxBorderWidth;
          var shape = this._separatorEndShape;
          if( !full ) {
            GraphicsUtil.setRectBounds( shape, left, top, width, height );
          }
          if( position !== 0 ) {
            left = displayPosition;
            shape = this._separatorStartShape;
            GraphicsUtil.setRectBounds( shape, left, top, width, height );
          }
        }
      }
    },

    ////////////////
    // layout helper

    _getIndicatorLength : function( virtualPosition ) {
      var result = this._getIndicatorVirtualLength();
      var fullLength = this._getIndicatorFullLength();
      if( this._isIndeterminate() ) {
        // shorten the length to fit in the bar
        if( virtualPosition < 0 ) {
          result += virtualPosition;
        }
        if( ( virtualPosition + result ) > fullLength ) {
          result = fullLength - virtualPosition;
        }
      } else if( this._useBorderShape ) {
        // round length so it falls into a save area, position is assumed 0
        var minLength = this._getIndicatorMinSafeLength();
        var maxLength = this._getIndicatorMaxSafeLength();
        if( result < minLength ) {
          if( result > 0 ) {
            result = minLength;
          } else {
            result = 0;
          }
        }
        if( result > maxLength && result < fullLength ) {
          result = maxLength;
        }
      }
      return Math.round( result );
    },

    _getIndicatorVirtualLength : function() {
      var result;
      if( this._isIndeterminate() ) {
        result = rwt.widgets.ProgressBar.UNDETERMINED_SIZE;
      } else {
        var fullLength = this._getIndicatorFullLength();
        var selected = this._selection - this._minimum;
        var max = this._maximum - this._minimum;
        result = ( selected / max ) * fullLength;
      }
      return result;
    },

    _getIndicatorVirtualPosition : function() {
      var result = 0;
      if( this._isIndeterminate() ) {
        result = this._computeNextSaveIndicatorPosition();
      }
      return result;
    },

    _computeNextSaveIndicatorPosition : function() {
      var length = rwt.widgets.ProgressBar.UNDETERMINED_SIZE;
      var fullLength = this._getIndicatorFullLength();
      var position = this._indicatorVirtualPosition + 2;
      if( this._useBorderShape ) {
        var minWidth = this._getIndicatorMinSafeLength();
        var maxWidth = this._getIndicatorMaxSafeLength();
        var endPosition = position + length;
        if( endPosition > 0 && endPosition < minWidth ) {
          position = minWidth - length;
        }
        if( position > 0 && position < minWidth ) {
          position = minWidth;
        }
        endPosition = position + length;
        if( endPosition > maxWidth && endPosition < fullLength ) {
          position = fullLength - length;
        }
        if( position > maxWidth ) {
          position = -length;
        }
      } else if( position >= fullLength ) {
          position = -length;
      }
      this._indicatorVirtualPosition = position;
      return position;
    },

    _getIndicatorRadii : function( position, length ) {
      // works under the assumption that positon and length are "radii-save"
      var result = [ 0, 0, 0, 0 ];
      if( this._useBorderShape && length > 0 ) {
        var radii = this.getBorder().getRadii();
        var endPosition = position + length;
        var fullLength = this._getIndicatorFullLength();
        if( this._isVertical() ) {
          if( position === 0 ) {
            result[ 2 ] = radii[ 2 ];
            result[ 3 ] = radii[ 3 ];
          }
          if( endPosition == fullLength ) {
            result[ 0 ] = radii[ 0 ];
            result[ 1 ] = radii[ 1 ];
          }
        } else {
          if( position === 0 ) {
            result[ 0 ] = radii[ 0 ];
            result[ 3 ] = radii[ 3 ];
          }
          if( endPosition == fullLength ) {
            result[ 1 ] = radii[ 1 ];
            result[ 2 ] = radii[ 2 ];
          }
        }
      }
      return result;
    },

    _getIndicatorFullLength : function() {
      return   this._isVertical()
             ? this.getInnerHeight() - 2 * this._gfxBorderWidth
             : this.getInnerWidth() - 2 * this._gfxBorderWidth;
    },

    // minimal indicator-length for the left/lower rounded corners to work
    _getIndicatorMinSafeLength : function() {
      var radii = this.getBorder().getRadii();
      var result =   this._isVertical()
                   ? Math.max( radii[ 2 ], radii[ 3 ] )
                   : Math.max( radii[ 0 ], radii[ 3 ] );
      result += this._separatorWidth;
      result -= Math.floor( this._gfxBorderWidth / 2 );
      return result;
    },

    // maximum indicator-length for the right/upper corners to be rectangular
    _getIndicatorMaxSafeLength : function() {
      var radii = this.getBorder().getRadii();
      var fullLength = this._getIndicatorFullLength();
      var result =   this._isVertical()
                   ? fullLength - Math.max( radii[ 0 ], radii[ 1 ] )
                   : fullLength - Math.max( radii[ 1 ], radii[ 2 ] );
      result -= this._separatorWidth;
      result += Math.floor( this._gfxBorderWidth / 2 );
      return result;
    }

  }
});




© 2015 - 2024 Weber Informatics LLC | Privacy Policy