📄 fisheyebase.as
字号:
package qs.controls.fisheyeClasses
{
import mx.containers.VBox;
import mx.core.UIComponent;
import mx.controls.Text;
import flash.text.TextLineMetrics;
import mx.core.UITextField;
import flash.events.MouseEvent;
import mx.core.UIComponent;
import Infinity;
import mx.core.IDataRenderer;
import flash.geom.Matrix;
import mx.core.IFactory;
import mx.core.ClassFactory;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.geom.Point;
import flash.display.Scene;
import flash.events.Event;
import flash.display.Sprite;
import flash.display.Shape;
import flash.display.DisplayObject;
import mx.charts.chartClasses.RenderData;
import qs.controls.LayoutAnimator;
import qs.controls.LayoutTarget;
import qs.controls.fisheyeClasses.FisheyeAxis;
import qs.controls.fisheyeClasses.FisheyeParameters;
import mx.core.UIComponent;
import flash.net.FileFilter;
import qs.controls.CachedLabel;
/** the horizontal alignment. */
[Style(name="horizontalAlign", type="String", enumeration="left,center,right,justified", inherit="no")]
/** the vertical alignment */
[Style(name="verticalAlign", type="String", enumeration="top,center,bottom,justified", inherit="no")]
/** the amount of space, in pixels, between invidual items */
[Style(name="defaultSpacing", type="Number", inherit="no")]
/** the amount of space, in pixels, between invidual items when hilighted*/
[Style(name="hilightSpacing", type="Number", inherit="no")]
/** the property on the item renderer to assign to when the renderer' state changes */
[Style(name="stateProperty", type="String", inherit="no")]
/** the value to assign to 'stateProperty' on the renderer when the item is hilighted */
[Style(name="rolloverValue", type="String", inherit="no")]
/** the value to assign to 'stateProperty' on the renderer when the item is selected */
[Style(name="selectedValue", type="String", inherit="no")]
/** the value to assign to 'stateProperty' on the renderer when some other item is selected */
[Style(name="unselectedValue", type="String", inherit="no")]
/** the value to assign to 'stateProperty' on the renderer when the item is in its default state */
[Style(name="defaultValue", type="String", inherit="no")]
/** the scale factor assigned to renderers when no item is hilighted or selected */
[Style(name="defaultScale", type="Number", inherit="no")]
/** the minimum scale factor assigned to renderers on screen. The actual scale factor assigned to
* an item will range between minScale and hilightMaxScale based on its distance from the hilighted or selected item */
[Style(name="hilightMinScale", type="Number", inherit="no")]
/** the maximum scale factor assigned to renderers on screen. The actual scale factor assigned to
* an item will range between minScale and hilightMaxScale based on its distance from the hilighted or selected item */
[Style(name="hilightMaxScale", type="Number", inherit="no")]
/** how quickly or slowly items scale down from the hilightMaxScale value to minScale value. A value of 1 will scale linearly down from the hilighted item out to the item at scaleRadius.
* A value higher than wone will descend slowly from the hilight, then drop off quicker at the edge. A value lower than one will drop off quickly from the hilight Should be greater than 0*/
[Style(name="hilightScaleSlope", type="Number", inherit="no")]
/** The radius, in items, around the hilighted item that are affected by the hilight. A value of 1 means only the hilighted item will scale. A value of three means the hilighted item plus the two items
* to either side will scale up. How much each item scales is affected by the scaleSlope style.*/
[Style(name="hilightScaleRadius", type="Number", inherit="no")]
/** how quickly items animate to their target location when the layout of the renderers change. A value of 1 will
* snap instantly to the new value, while a value of 0 will never change */
[Style(name="animationSpeed", type="Number", inherit="no")]
[Event("change")]
[DefaultProperty("dataProvider")]
public class FisheyeBase extends UIComponent
{
/** the data items driving the component
*/
private var _items:Array = [];
/** when a new dataprovider is assigned, we keep it in reserve until we have a chance
* to generate new renderers for it. This is the temporary holding pen for those new items
*/
private var _pendingItems:Array;
protected var itemsChanged:Boolean = false;
/** true if the renderers need to be regenerated */
protected var renderersDirty:Boolean = true;
/** the renderers representing the data items, one for each item */
protected var renderers:Array = [];
/** the currently hilighted item
*/
protected var hilightedItemIndex:Number = NaN;
/** the currently selected item
*/
protected var selectedItemIndex:Number = NaN;
/** @private */
private var _selectionEnabled:Boolean = true;
/** the factory that generates item renderers
*/
private var _itemRendererFactory:IFactory;
/**
* the object that manages animating the children layout
*/
protected var animator:LayoutAnimator;
/** Constructor */
public function FisheyeBase()
{
super();
_itemRendererFactory= new ClassFactory(CachedLabel);
addEventListener(MouseEvent.MOUSE_MOVE,updateHilight);
addEventListener(MouseEvent.ROLL_OUT,removeHilight);
addEventListener(MouseEvent.MOUSE_DOWN,updateSelection);
var maskShape:Sprite = new Sprite();
addChild(maskShape);
mask = maskShape;
maskShape.graphics.beginFill(0);
maskShape.graphics.drawRect(0,0,10,10);
maskShape.graphics.endFill();
animator = new LayoutAnimator();
animator.layoutFunction = generateLayout;
}
//-----------------------------------------------------------------
/** the data source
*/
public function set dataProvider(value:Array):void
{
_pendingItems= value;
renderersDirty = true;
itemsChanged = true;
invalidateProperties();
}
public function get dataProvider():Array
{
return _items;
}
//-----------------------------------------------------------------
public function set selectionEnabled(value:Boolean):void
{
if(_selectionEnabled == value)
return;
_selectionEnabled = value;
selectedIndex = selectedIndex;
}
public function get selectionEnabled():Boolean
{
return _selectionEnabled;
}
[Bindable("change")]
public function get selectedItem():Object
{
return (isNaN(selectedItemIndex)? null:_items[selectedItemIndex]);
}
public function set selectedItem(value:Object):void
{
var newIndex:Number;
for(var i:int = 0;i<_items.length;i++)
{
if(value == _items[i])
{
newIndex = i;
break;
}
}
selectedIndex = newIndex;
}
[Bindable("change")]
public function get selectedIndex():int
{
return (isNaN(selectedItemIndex)? -1:selectedItemIndex);
}
public function set selectedIndex(value:int):void
{
var v:Number = (value < 0 || value >= _items.length)? NaN:value;
if(v != selectedItemIndex)
{
selectedItemIndex = v;
updateState();
animator.invalidateLayout();
dispatchEvent(new Event("change"));
}
}
//-----------------------------------------------------------------
/* These private get properties are wrappers around styles that return defaults if unset.
* It saves me from having to write a CSS selector, which
* I really should do at some point */
protected function get defaultSpacingWithDefault():Number
{
var result:Number= getStyle("defaultSpacing");
if(isNaN(result))
result = 0;
return result;
}
protected function get maxScaleWithDefault():Number
{
var result:Number= getStyle("hilightMaxScale");
if(isNaN(result))
result = 1;
return result;
}
//-----------------------------------------------------------------
/**
* by making the itemRenderer be of type IFactory,
* developers can define it inline using the <Component> tag
*/
public function get itemRenderer():IFactory
{
return _itemRendererFactory;
}
public function set itemRenderer(value:IFactory):void
{
_itemRendererFactory = value;
renderersDirty = true;
invalidateProperties();
}
//-----------------------------------------------------------------
override protected function commitProperties():void
{
// its now safe to switch over new dataProviders.
if(_pendingItems != null)
{
_items = _pendingItems;
_pendingItems = null;
}
itemsChanged = false;
if(renderersDirty)
{
// something has forced us to reallocate our renderers. start by throwing out the old ones.
renderersDirty = false;
var mask:DisplayObject = mask;
for(var i:int=numChildren-1;i>= 0;i--)
removeChildAt(i);
addChild(mask);
renderers = [];
// allocate new renderers, assign the data.
for(var i:int = 0;i<_items.length;i++)
{
var renderer:UIComponent = _itemRendererFactory.newInstance();
IDataRenderer(renderer).data = _items[i];
renderers[i] = renderer;
addChild(renderer);
}
animator.items = renderers;
}
invalidateSize();
}
private function removeHilight(e:MouseEvent):void
{
// called on rollout. Clear out any hilight, and reset our layout.
hilightedItemIndex = NaN;
updateState();
animator.invalidateLayout();
}
/** finds the item that would be closest to the x/y position if it were hilighted
*/
protected function findItemForPosition(xPos:Number,yPos:Number):Number
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -