topical media & game development

talk show tell print

actionscript-extra-fisheye-qs-controls-FisheyeTile.ax

actionscript-extra-fisheye-qs-controls-FisheyeTile.ax [swf] flex


  package qs.controls
  {
          import qs.controls.fisheyeClasses.FisheyeBase;
          import qs.controls.fisheyeClasses.FisheyeItem;
          import qs.controls.fisheyeClasses.FisheyeAxis;
          import mx.core.UIComponent;
          import qs.controls.fisheyeClasses.FisheyeParameters;
          import flash.geom.Rectangle;
  
          
the vertical alignment

  
          [Style(name="zoomMode", type="String", enumeration="scale,resize", inherit="no")]
          
          public class @ax-actionscript-extra-fisheye-qs-controls-FisheyeTile extends FisheyeBase
          {
                  
the ideal positional data for the renderers. When the inputs to the layout system change, this array is regenerated to represent the goal positions for each renderer. Over time, the layout system will animate the children towards these positions

  
                  private var _pdata:Array = [];
                  private var _hItems:Array = [];
                  private var _vItems:Array = [];
                  private var _hMouseItems:Array = [];
                  private var _vMouseItems:Array = [];
                  private var _mouseBounds:Rectangle = new Rectangle();
                  private var _rowLength:int = 16;
                  private var _colLength:int;
                  private var _tileWidth:int;
                  private var _tileHeight:int;
                  private var _mouseData:Array = [];
  
                  
the direction this component lays out

  
                  private var _direction:String = "vertical";
  
                  /* abstractions around x/y, width/height. Instead of asking for x/y based properties directly,
  		*  we go through these properties. Switch the properties, and our layout switches axis. Presto! */
                  protected var hAxis:FisheyeAxis = new FisheyeAxis();
                  protected var vAxis:FisheyeAxis = new FisheyeAxis();
  
                  //-----------------------------------------------------------------
  
                  public function @ax-actionscript-extra-fisheye-qs-controls-FisheyeTile()                
                  {
                          hAxis.direction = "horizontal";
                          vAxis.direction = "vertical";                        
                  }
  
                  override protected function measure():void
                  {
                          _tileWidth = 0;
                          _tileHeight = 0;
                          
                          // first, calculate the largest width/height of all the items, since we'll have to make all of the items
                          // that size
                          for(var i:int=0;i<renderers.length;i++)
                          {
                                  var itemRenderer:UIComponent = renderers[i];
                                  _tileWidth = Math.max(_tileWidth,itemRenderer.getExplicitOrMeasuredWidth());
                                  _tileHeight = Math.max(_tileHeight,itemRenderer.getExplicitOrMeasuredHeight());
                          }
                          // square them off
                          _tileWidth = Math.max(_tileWidth,_tileHeight);
                          _tileHeight = _tileWidth;
                                                  
                          for(var i:int=0;i<_rowLength;i++)
                          {
                                  _hItems[i].eomWidth = _hMouseItems[i].eomWidth = _tileWidth;
                                  _hItems[i].eomHeight = _hMouseItems[i].eomHeight = _tileHeight;
                          }
                          for(var i:int=0;i<_colLength;i++)
                          {
                                  _vItems[i].eomWidth = _vMouseItems[i].eomWidth = _tileWidth;
                                  _vItems[i].eomHeight = _vMouseItems[i].eomHeight = _tileHeight;
                          }
                          
                          /* here's where we should actually do some measurement */                                
                          // now that we have newly measured sizes, we'll need to recaculate sizing, and mouse positoins.
                          animator.invalidateLayout();
                  }
                  
                  
                  override protected function commitProperties():void
                  {
                          var itemsChanged:Boolean = this.itemsChanged
                          super.commitProperties();
                          
                          if(itemsChanged)
                          {
                                  _hItems = [];
                                  _vItems = [];
                                  _hMouseItems = []
                                  _vMouseItems = [];
                                  _colLength = Math.ceil(dataProvider.length / _rowLength);                                
                                  for(var i:int = 0;i<_rowLength;i++)
                                  {
                                          _hItems[i] = new FisheyeItem();
                                          _hMouseItems[i] = new FisheyeItem();
                                  }
                                  for(var i:int = 0;i<_colLength;i++)
                                  {
                                          _vItems[i] = new FisheyeItem();
                                          _vMouseItems[i] = new FisheyeItem();
                                  }
                          }
  
                  }
  
                  override protected function generateLayout():void
                  {
                          var itemCount:int = dataProvider.length;
  
                          var targetIndex:Number = (isNaN(hilightedItemIndex)? selectedItemIndex:hilightedItemIndex);
                          
                          if(isNaN(targetIndex))
                          {
                                  populateMajorAxisForDefault(_hItems,hAxis,unscaledWidth);
                                  align(_hItems,hAxis);                        
                                  populateMajorAxisForDefault(_vItems,vAxis,unscaledHeight);
                                  align(_vItems,vAxis);                
                          }
                          else
                          {
                                  var hTargetIndex:Number = targetIndex % _rowLength;
                                  
                                  var hData:FisheyeItem = _hMouseItems[hTargetIndex];
                                  
                                  var hTargetPosition:Number = hData.x + hData.eomWidth*hData.scale - _tileWidth*maxScaleWithDefault/2;
                                  if(hTargetPosition < 0)
                                          hTargetPosition = 0;
                                  if(hTargetPosition + _tileWidth*maxScaleWithDefault > unscaledWidth)
                                          hTargetPosition = unscaledWidth - _tileWidth*maxScaleWithDefault;
                                          
                                  populateMajorAxisFor(_hItems.slice(hTargetIndex),0,unscaledWidth - hTargetPosition,hAxis);
                                  for (var i:int = hTargetIndex;i<_rowLength;i++)
                                          _hItems[i].x += hTargetPosition;
                                  if(hTargetIndex > 0)
                                  {
                                          populateMajorAxisFor(_hItems.slice(0,hTargetIndex),hTargetIndex,hTargetPosition - defaultSpacingWithDefault,hAxis);
                                          hData = _hItems[hTargetIndex - 1];
                                          var offset:Number = hTargetPosition - (hData.x + hData.eomWidth * hData.scale + defaultSpacingWithDefault);
                                          for(var i:int = 0;i<hTargetIndex;i++)
                                                  _hItems[i].x += offset;
                                  }                                
  
                                  var vTargetIndex:Number = Math.floor(targetIndex  / _rowLength);
  
                                  var vData:FisheyeItem = _vMouseItems[vTargetIndex];
                                  
                                  var vTargetPosition:Number = vData.y + vData.eomHeight*vData.scale - _tileHeight*maxScaleWithDefault/2;
                                  if(vTargetPosition < 0)
                                          vTargetPosition = 0;
                                  if(vTargetPosition + _tileHeight*maxScaleWithDefault > unscaledHeight)
                                          vTargetPosition = unscaledHeight - _tileHeight*maxScaleWithDefault;
                                          
                                  populateMajorAxisFor(_vItems.slice(vTargetIndex),0,unscaledHeight - vTargetPosition,vAxis);
                                  for (var i:int = vTargetIndex;i<_colLength;i++)
                                          _vItems[i].y += vTargetPosition;
                                  if(vTargetIndex > 0)
                                  {
                                          populateMajorAxisFor(_vItems.slice(0,vTargetIndex),vTargetIndex,vTargetPosition - defaultSpacingWithDefault,vAxis);
                                          vData = _vItems[vTargetIndex - 1];
                                          var offset:Number = vTargetPosition - (vData.y + vData.eomHeight * vData.scale + defaultSpacingWithDefault);
                                          for(var i:int = 0;i<vTargetIndex;i++)
                                                  _vItems[i].y += offset;
                                  }                                
  
                          }
                          
                          var zoomMode:String = getStyle("zoomMode");
                          var useScale:Boolean = !(zoomMode == "resize");
                          
                          for(var i:int=0;i<itemCount;i++)
                          {
                                  var itemRenderer:UIComponent = renderers[i];
                                  var hData:FisheyeItem = _hItems[ i % _rowLength];
                                  var vData:FisheyeItem = _vItems[Math.floor(i / _rowLength)];
  
                                  var target:LayoutTarget = animator.targetFor(itemRenderer);
                                  
                                  if(useScale)
                                  {
                                  
                                          // now, compare the aspect ratio of the item, compared to the area alloted to it.
                                          var areaAR:Number = (hData.eomWidth * hData.scale) / (vData.eomHeight * vData.scale);
                                          var itemAR:Number = itemRenderer.getExplicitOrMeasuredWidth() / itemRenderer.getExplicitOrMeasuredHeight();
                                          
                                          
                                          if(itemAR/areaAR > 1)
                                          {
                                                  // the item is more horizontal than the area.
                                                  var scale:Number = hData.eomWidth * hData.scale / itemRenderer.getExplicitOrMeasuredWidth();
                                                  target.scaleX = target.scaleY = scale;
                                                  target.x = hData.x;
                                                  target.y = vData.y + vData.eomWidth*vData.scale/2 - itemRenderer.getExplicitOrMeasuredHeight()*scale/2;
                                          }
                                          else
                                          {
                                                  // the item is more vertical than the area.
                                                  var scale:Number = vData.eomHeight * vData.scale / itemRenderer.getExplicitOrMeasuredHeight();
                                                  if(isNaN(scale))
                                                          scale = 0;
                                                  target.scaleX = target.scaleY = scale;
                                                  target.x = hData.x + hData.eomHeight*hData.scale/2 - itemRenderer.getExplicitOrMeasuredWidth()*scale/2;
                                                  target.y = vData.y;
                                          }
                                          target.unscaledWidth = itemRenderer.getExplicitOrMeasuredWidth();
                                          target.unscaledHeight = itemRenderer.getExplicitOrMeasuredHeight();
                                  }
                                  else
                                  {
  
                                          target.x = hData.x;
                                          target.unscaledWidth = hData.eomWidth * hData.scale;
                                          target.y = vData.y;
                                          target.unscaledHeight = vData.eomHeight * vData.scale;
                                          target.scaleX = target.scaleY = 1;
                                  }
                          }
                  }
  
                  override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
                  {
                          populateMajorAxisForDefault(_hMouseItems,hAxis,unscaledWidth);
                          align(_hMouseItems,hAxis);                        
                          populateMajorAxisForDefault(_vMouseItems,vAxis,unscaledHeight);
                          align(_vMouseItems,vAxis);                        
                          
                          var leftItem:FisheyeItem = _hMouseItems[0];
                          var rightItem:FisheyeItem = _hMouseItems[_hMouseItems.length - 1];
                          var topItem:FisheyeItem = _vMouseItems[0];
                          var bottomItem:FisheyeItem = _vMouseItems[_vMouseItems.length - 1];
  
                          _mouseBounds.left = leftItem.x + leftItem.eomWidth*leftItem.scale/2 - leftItem.eomWidth/2;
                          _mouseBounds.top = topItem.y + topItem.eomHeight*topItem.scale/2 - topItem.eomHeight/2;
                          _mouseBounds.right = rightItem.x + rightItem.eomWidth*rightItem.scale/2 + rightItem.eomWidth/2;
                          _mouseBounds.bottom = bottomItem.y + bottomItem.eomHeight*bottomItem.scale/2 + bottomItem.eomHeight/2;
                          
                          super.updateDisplayList(unscaledWidth,unscaledHeight);
                  }
  
                  override protected function findItemForPosition(xPos:Number,yPos:Number):Number
                  {
                          var hIndex:Number;
                          var vIndex:Number;
                          var minDist:Number = Infinity;
  
                          if(dataProvider.length == 0)
                                  return NaN;
                          
                          if(_mouseBounds.contains(xPos,yPos) == false)
                                  return NaN;
                                  
                          for(var i:int = 0; i < _hMouseItems.length; i++)
                          {
                                  var item:FisheyeItem = _hMouseItems[i];
                                  var midPoint:Number = item.x + item.eomWidth * item.scale/2;
                          
                                  var dist:Number = xPos - midPoint;
                                  if (Math.abs(dist) < Math.abs(minDist))                                
                                  {
                                          minDist = dist;
                                          hIndex = i;
                                  }
                                  else
                                  {
                                          break;
                                  }                                
                          }
                          if(isNaN(hIndex))
                                  return NaN;
                          
                          minDist = Infinity;
                          
                          for(var i:int = 0; i < _vMouseItems.length; i++)
                          {
                                  var item:FisheyeItem = _vMouseItems[i];
                                  var midPoint:Number = item.y + item.eomHeight * item.scale/2;
                          
                                  var dist:Number = yPos - midPoint;
                                  if (Math.abs(dist) < Math.abs(minDist))                                
                                  {
                                          minDist = dist;
                                          vIndex = i;
                                  }
                                  else
                                  {
                                          break;
                                  }                                
                          }
                          if(isNaN(vIndex))
                                  return NaN;
                                  
                          return (vIndex)*_rowLength + hIndex;
                  }
          }
  }
  
  


(C) Æliens 27/08/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.