blob: 73724b1d3957838260b031d367e0c6ddf826fe6a [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package mx.charts.chartClasses
{
import flash.events.Event;
import flash.events.EventDispatcher;
import mx.charts.LinearAxis;
import mx.core.mx_internal;
import mx.events.FlexEvent;
use namespace mx_internal;
//--------------------------------------
// Events
//--------------------------------------
/**
* Dispatched when the transformation from data space to screen space
* has changed, typically either because the axes that make up
* the transformation have changed in some way,
* or the data transform itself has size.
*
* @eventType mx.events.FlexEvent.TRANSFORM_CHANGE
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="transformChange", type="mx.events.FlexEvent")]
/**
* The DataTransform object represents a portion of a chart
* that contains glyphs and can transform values
* to screen coordinates and vice versa.
* Each DataTransform object has a horizontal axis, a vertical axis,
* and a set of glyphs (background, data, and overlay) to render.
*
* <p>In theory, a chart can contain multiple overlaid DataTransform objects.
* This allows you to display a chart with multiple data sets
* rendered in the same area but with different ranges.
* For example, you might want to show monthly revenues
* compared to the number of units sold.
* If revenue was typically in millions while units was typically
* in the thousands, it would be difficult to render these effectively
* along the same range.
* Overlaying them in different DataTransform objects allows
* the end user to compare trends in the values
* when they are rendered with different ranges.</p>
*
* <p>Charts can only contain one set of DataTransform.</p>
*
* <p>Most of the time, you will use the ChartBase object,
* which hides the existance of the DataTransform object
* between the chart and its contained glyphs and axis objects.
* If you create your own ChartElement objects, you must understand
* the methods of the DataTransform class to correctly implement their element.</p>
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public class DataTransform extends EventDispatcher
{
include "../../core/Version.as";
//--------------------------------------------------------------------------
//
// Constructor
//
//--------------------------------------------------------------------------
/**
* Constructor.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function DataTransform()
{
super();
}
//--------------------------------------------------------------------------
//
// Properties
//
//--------------------------------------------------------------------------
//----------------------------------
// axes
//----------------------------------
/**
* @private
* Storage for the axes property.
*/
private var _axes:Object = {};
[Inspectable(environment="none")]
/**
* The set of axes associated with this transform.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get axes():Object
{
return _axes;
}
//----------------------------------
// elements
//----------------------------------
/**
* @private
*/
private var _elements:Array /* of ChartElement */ = [];
[Inspectable(environment="none")]
/**
* The elements that are associated with this transform.
* This Array includes background, series, and overlay elements
* associated with the transform.
* This value is assigned by the enclosing chart object.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get elements():Array /* of ChartElement */
{
return _elements;
}
/**
* @private
*/
public function set elements(value:Array /* of ChartElement */):void
{
_elements = value;
}
//--------------------------------------------------------------------------
//
// Methods
//
//--------------------------------------------------------------------------
/**
* Maps a set of numeric values representing data to screen coordinates.
* This method assumes the values are all numbers,
* so any non-numeric values must have been previously converted
* with the <code>mapCache()</code> method.
*
* @param cache An array of objects containing the data values
* in their fields. This is also where this function
* will store the converted numeric values.
*
* @param xField The field where the data values for the x axis
* can be found.
*
* @param xConvertedField The field where the mapped x screen coordinate
* will be stored.
*
* @param yField The field where the data values for the y axis
* can be found.
*
* @param yConvertedField The field where the mapped y screen coordinate
* will be stored.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function transformCache(cache:Array /* of Object */,
xField:String, xConvertedField:String,
yField:String, yConvertedField:String):void
{
}
/**
* Transforms x and y coordinates relative to the DataTransform
* coordinate system into a two-dimensional value in data space.
*
* @param ...values The x and y positions (in that order).
*
* @return An Array containing the transformed values.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function invertTransform(...values):Array
{
return null;
}
/**
* Informs the DataTransform that some of the underlying data
* being represented on the chart has changed.
* The DataTransform generally has no knowledge of the source
* of the underlying data being represented by the chart,
* so glyphs should call this when their data changes
* so that the DataTransform can recalculate range scales
* based on their data.
* This does <b>not</b> invalidate the DataTransform,
* because there is no guarantee the data has changed.
* The axis objects (or range objects) must trigger an invalidate event.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function dataChanged():void
{
for (var p:String in _axes)
{
if (_axes[p])
_axes[p].dataChanged();
}
}
/**
* Collects important displayed values for all elements
* associated with this data transform.
* Axis instances call this method to collect the values
* they need to consider when auto-generating appropriate ranges.
* This method returns an Array of BoundedValue objects.
*
* <p>To collect important values for the horizontal axis
* of a CartesianTransform, pass 0.
* To collect values for the vertical axis, pass 1.</p>
*
* @param dimension The dimension to collect values for.
*
* @param requiredFields Defines the data that are required
* by this transform.
*
* @return A Array of BoundedValue objects.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function describeData(dimension:String, requiredFields:uint):Array /* of BoundedValue */
{
var results:Array /* of BoundedValue */ = [];
var n:int = elements.length;
for (var i:int = 0; i < n; i++)
{
var dataGlyph:IChartElement = (elements[i] as IChartElement);
if (!dataGlyph)
continue;
results = results.concat(
dataGlyph.describeData(dimension, requiredFields));
}
return results;
}
/**
* Retrieves the axis instance responsible for transforming
* the data dimension specified by the <code>dimension</code> parameter.
* If no axis has been previously assigned, a default axis is created.
* The default axis for all dimensions is a LinearAxis
* with the <code>autoAdjust</code> property set to <code>false</code>.
*
* @param dimension The dimension whose axis is responsible
* for transforming the data.
*
* @return The axis instance.
*
* @see mx.charts.LinearAxis
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function getAxis(dimension:String):IAxis
{
if (!(_axes[dimension]))
{
var newAxis:LinearAxis = new LinearAxis();
newAxis.autoAdjust = false;
setAxisNoEvent(dimension,newAxis);
}
return _axes[dimension];
}
/**
* Assigns an axis instance to a particular dimension of the transform.
* Axis objects are assigned by the enclosing chart object.
*
* @param dimension The dimension of the transform.
* @param v The target axis instance.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function setAxis(dimension:String, v:IAxis):void
{
if(setAxisNoEvent(dimension, v))
mappingChangeHandler();
}
/**
* @private
*/
private function setAxisNoEvent(dimension:String, v:IAxis):Boolean
{
var oldV:IAxis = _axes[dimension];
if(oldV != v)
{
if (oldV)
{
oldV.unregisterDataTransform(this);
oldV.removeEventListener("mappingChange", mappingChangeHandler);
}
_axes[dimension] = v;
{
v.registerDataTransform(this, dimension);
v.addEventListener("mappingChange", mappingChangeHandler, false, 0, true);
}
return true;
}
return false;
}
//--------------------------------------------------------------------------
//
// Event handlers
//
//--------------------------------------------------------------------------
/**
* @private
*/
private function mappingChangeHandler(event:Event = null):void
{
var n:int = elements.length;
for (var i:int = 0; i < n; i++)
{
var g:IChartElement = elements[i] as IChartElement;
if (g)
g.mappingChanged();
}
}
}
}