<?xml version="1.0" encoding="utf-8"?>
<!--
	 Copyright (c) 2009 Team Axiis

	 Permission is hereby granted, free of charge, to any person
	 obtaining a copy of this software and associated documentation
	 files (the "Software"), to deal in the Software without
	 restriction, including without limitation the rights to use,
	 copy, modify, merge, publish, distribute, sublicense, and/or sell
	 copies of the Software, and to permit persons to whom the
	 Software is furnished to do so, subject to the following
	 conditions:

	 The above copyright notice and this permission notice shall be
	 included in all copies or substantial portions of the Software.

	 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
	 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
	 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
	 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
	 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
	 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
	 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
	 OTHER DEALINGS IN THE SOFTWARE.
-->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
	xmlns:charts="org.axiis.charts.*"
	layout="absolute"
	backgroundGradientColors="[0xDDDDDD,0xF5F5F5]"
	creationComplete="start();"
	xmlns:axiis="http://www.axiis.org/2009"
	xmlns:series="org.axiis.charts.series.*"
	xmlns:groupings="org.axiis.charts.groupings.*"
	xmlns:degrafa="http://www.degrafa.com/2007"
	xmlns:states="org.axiis.states.*"
	xmlns:paint="org.axiis.paint.*"
	xmlns:Examples="com.webappsolution.datavisualization.examples.*"
	xmlns:axis="org.axiis.charts.axis.*"
	xmlns:labels="org.axiis.charts.labels.*"
	xmlns:utils="org.axiis.utils.*">

	<!--<mx:Style source="styles/Axiis_Examples.css"/>-->
	
	<mx:Script>
		<![CDATA[
			import org.axiis.data.DataSet;

			private var ds:DataSet = new DataSet();

			public function start():void
			{
				//ds.processCsvAsTable(payload, false);
				
				//LineSeriesGroup expects each unique series as a row
				//Since our data has the time entries on each row (a common format for temporal data) we want to pivot the data
				//This then makes a column for each unique time entrie and a row for each unique column.
				ds.pivotTable(0);
				dataProvider = ds.data.pivot.rows;
				// Set the intial dp to the intial setting of the %data slider
				hScale.dataProvider=ds.data.pivot.header.slice(1,dataSlice.value+1);
				hAxis.invalidateDataProvider();
				// Has to be called any time the dataCanvas dp is changed
				dc.invalidateDisplayList();
			}
			
			/**
			 * This function is called when the % data slider changes.
			 * It's merely using the current slider value to slice the underlying array
			 */ 
			private function sliceData():void {
				hScale.dataProvider=ds.data.pivot.header.slice(1,dataSlice.value+1);
				hAxis.invalidateDataProvider();
				myLineGroup.invalidateDataProvider();
				dc.invalidateDisplayList(); 
			}

			/**
			 * The labelFunction property of the LineSeriesGroup, and other components, allow you to 
			 * to determine how each to format each label the component displays
			 */
			private function axisLabel(obj:Object):String
			{
				return formatter.format(Number(obj) / 1000);
			}

			/**
			 * This function determines whether or not a point in the plotCollection should be graphed
			 * This particular one looks at the index property of the obj to see if it should be included. This assumes there's an index property
			 * These functions are usefull if you have not specifically massaged the data so that the extraneouse data has been removed.
			 * The axiis dataset will provide the index value and it will indicate a column in the data set. Here you can specify 
			 * columns to not include. 
			 * If you do massage your data, the plotFilterFunction will not need to be used.
			 */
			private function filterColumns(obj:Object):Boolean
			{
				//Don't want filter fields, trim columns
				if (obj.index < 1 || obj.index > dataSlice.value)
					return false;
				else
					return true;
			}

			/**
			 * The dataFilterFunction property of a LineSeriesGroup allows you to specify a filter such as this that allows you to decide
			 * on the fly, which lines to include in rendering so you don't need to manipulate the underlying data set
			 */
			private function filterRows(obj:Object):Boolean
			{
				//Trim our rows
				if (obj.pivotName == "Apples")
					return false;
				else
					return true;
			}
		]]>
	</mx:Script>
	
	<!-- places a convenient background on the chart -->
	<Examples:ExampleBackground width="100%" height="100%" title="Horizontal Chart" subTitle="Lines and Areas"/>
	
	<!--<mx:String id="payload" source="data/LineSeriesData.csv"/>-->

	<mx:CurrencyFormatter currencySymbol="k"
		precision="0"
		id="formatter"
		alignSymbol="right"
		useThousandsSeparator="true"/>

	<!--  GLOBAL VARIABLES -->
	<mx:Object id="dataProvider"/>
	<mx:String id="verticalField"/>
	<mx:Number id="percentGap">.02</mx:Number>

	<!--   
	NumericExpression provides a convenient place to store the results of numeric calculations used in multiple places within an MXML document. 
	By binding the results of a complex numeric computation to a NumericExpression's value property, you allow other objects to bind on that 
	value without the overhead of re-running the original computation.
	-->
	<utils:NumericExpression id="tension" value="{slider.value/210}" valueChanged="{if (myLineGroup) dc.invalidateDisplayList();}"/>

	<!--
	BooleanExpression provides a convenient place to store the results of boolean calculations used in multiple places within an MXML document. 
	By binding the results of a complex boolean expression to a BooleanExpression's value property, you allow other objects to bind on that 
	value without the overhead of re-running the original expression.
	
	For example, this markup will populate two labels with the text "true" but (a || b || c || d || e || true) will only have been evaluated once.
	                 
	<BooleanExpression id="be0" value="{a || b || c || d || e || true}" />
	<mx:Label text="{be0.value}" />
	<mx:Label text="{be0.value}" />
	-->
	              

	<!--  
	A scale that deals with linear numeric data.
	-->
	<axiis:LinearScale id="vScale"
		dataProvider="{dataProvider}"
		minLayout="0"
		maxLayout="{myLineGroup.height}"
		/>
	
	<!--
	A scale that converts categorical (String) data into layout space. The categories are assumed to be sorted alphabetically. 
	-->
	<axiis:CategoricalScale id="hScale"
		minLayout="0"
		maxLayout="{myLineGroup.width}"
	 />

	<!--
	DataCanvas manages the placement and the rendering of layouts.
	They can have backgroundGeometries, foregroundGeometries, and layouts.
	They inherit from Canvas
	-->
	<axiis:DataCanvas width="80%"
		id="dc"
		top="120"
		bottom="100"
		horizontalCenter="0"
		strokes="{strokes}"
		fills="{fills}"
		palettes="{palettes}"
		showDataTips="true">

		<!-- Background -->
		<!-- backgrounds appear behind the graph. There are also foregroundGeometries for doing annotations on top of the graph 
			verticalScale="{vScale}"			The vertical scale used for scaling data to actual screen units		
			tickStroke="{axisStroke}"			The stroke used to put the hash or tick marks on an axis
			width="{dc.width}"
			height="{myLineGroup.height}"
			showDataTips="false"				A flag that indicates to DataCanvas that it should listen for mouse events that signal the need to create a data tip.
			showGridArea="false"				Whether or not the grid cells are displayed
			showGridLine="false"				Whether or not lines are drawn between grid cells
			showLabels="false"					Whether or not to show labels on the axis
			fontFamily="Myriad Pro"
			fontColor="0"
			fontSize="14"
			tickGap="5"
			majorTickSpacing="50"				The space between successive major tick marks. There is also a minorTickSpacing. Length of marks can be adjusted as well majorTickLength
			labelFunction="{axisLabel}"			A function that is used to determine how each item in the dataProvider should be labeled along the axis.
		-->
		<axiis:backgroundGeometries>
			<!--
			VAxis renders values from bottom to top between a minimum and maximum value, and is intended to be rendered to the left of other layouts to provide a point of reference for those visualizations.
			VAxis can optionally label each major tick mark or render gridlines aligned to the axis itself. 
			-->
			<axis:VAxis id="vAxis"
				verticalScale="{vScale}"
				tickStroke="{axisStroke}"
				width="{dc.width}"
				height="{myLineGroup.height}"
				showDataTips="false"
				fontFamily="Myriad Pro"
				fontColor="0"
				fontSize="14"
				tickGap="5"
				majorTickSpacing="50"
				labelFunction="{axisLabel}"/>
			<!--
			HCategoryAxis renders values from left to right between a indexed collection of string values and is intended to be rendered beneath other layouts to provide a point of reference for those visualizations.
			HCategory Axis trys to optmize its layout based on the maximum widht/length of all labels in collection 
			-->
			<axiis:HCategoryAxis id="hAxis"
				x="{myLineGroup.x}"
				categoryScale="{this.hScale}"
				width="{myLineGroup.width}"
				dataProvider="{hScale.dataProvider}"
				height="50"
				y="{myLineGroup.height}"/>
			<!-- this is the actual x axis line -->
			<degrafa:Line x="0"
				x1="{myLineGroup.x+myLineGroup.width}"
				y="{myLineGroup.height}"
				y1="{myLineGroup.height}"
				stroke="{axisStroke}"/>
		</axiis:backgroundGeometries>

		<!-- Layouts -->
		<!--
				Layouts are composite components consisting of ReferenceRepeaters (the
				loop that defines a repeated bounding pattern)  DrawingGeometries
				(what you are going to draw) and Layouts (child layouts) 
		-->
		<axiis:layouts>
		
			<!-- LineSeriesGroup
				 Line series group renders multiple lines for a series of data points. This can be used to create visualizations that use curved surfaces such as stream graphs and line charts.
				 
					x="12"											x-location relative to paren
					y="0"											y-location relative to parent
					height="{dc.height-70}"							height of display essentially
					width="{dc.width}"								width
					tension="{tension.value}"						The tension used to render the curves in this chart. A value of 0 results in straight lines while a value of 1 results in exaggerated Bezier curves.
					markerColor="{areaPalette.currentColor}"		The color at the center of the markers.		
					dataFilterFunction="{filterRows}"				This provides a way to further refine a layouts dataProvider by providing access to a custom filter data filter function. 
																	This allows developers to easily visualize subsets of the data without having to change the underlying data structure. 
					showArea="{area.selected}"						Whether the area beneath the lines should be filled.
					plotFilterFunction="{filterColumns}"			A filter function that will be used to determine whether a given data point should be included in the rendering.			
					markerSize="8"									The diameter in pixels of the markers shown at each data point.			
					showMarker="{showMarker.selected}"				Whether or not markers should be displayed at each data point
					mode="{int(layoutGroup.selectedValue)}"			The layout mode used to render the lines. One of {MODE_BASELINE,MODE_STACK_ZERO,MODE_STACK_FLOW}.	
					dataProvider="{dataProvider}"					EG: var myLines is an ArrayCollection || Array of Line
																		Line is an object that has a name property, a plotPointsCollection property of PlotPoint, and an optional index which would be it's order in myLines
																		PlotPoint is an object with an index property, an xvalue property used for display of text or the x-value, and a yvalue property which is the y-value
					plotCollection="columns"						The name of the property on the objects in the dataProvider that contains the data to plot 
																	It is expected that the plot collection is a collection of objects - like Array or ArrayCollection and contains the series of data to be plotted. 
																	i.e. dataProvider=myLines is Array || ArrayCollection myLines[0].myPlotCollection is Array || ArrayCollection
					dataField="value"								The property within each item in the dataProvider that contains the field used to determine the value of the item. (essentially the y value)							
					labelField="pivotName"							The property within each item in the dataProvider that contains the field used to determine the label for the item.
					xDataField="name"								The property within each item in the dataProvider that contains the field used to determine the value of the item on the horizontal axis.
					plotLabelField="name"							The property on the items in the dataProvider that contains the label field for the entire plot.				
					verticalScale="{vScale}"						The vertical scale, IScale, used to scale data values to chart values 
					horizontalScale="{hScale}"						The horizontal scale, IScale, used to scale data values to chart values
					stroke="{myStroke}"								The stroke used to render lines
					fill="{areaFill}"								The fill used to render the area beneath the lines if area rendering is enabled.
					enableRollOver="true"							Turns on/off the default roll-over state
					currentDatum									The item in the dataProvider that the layout is currently rendering.
					currentIndex									The index of the item in the dataProvider that the layout is currently rendering.
					currentLabel									The label of the item in the dataProvider that the layout is currently rendering, as determine by taking currentDatum[labelField], if a labelField is defined.
					currentReference								The geometry that is being used to render the current data item as it appears after the necessary iterations of the referenceRepeater have been executed.
					currentValue									The value of the item in the dataProvider that the layout is currently rendering, as determined by taking currentDatum[dataField], if a dataField is defined.								
			-->
			<groupings:LineSeriesGroup id="myLineGroup"
				x="12"
				y="0"
				height="{dc.height-70}"
				width="{dc.width}"
				tension="{tension.value}"
				markerColor="{areaPalette.currentColor}"		
				dataFilterFunction="{filterRows}"
				showArea="{area.selected}"
				plotFilterFunction="{filterColumns}"
				markerSize="8"
				showMarker="{showMarker.selected}"
				mode="{int(layoutGroup.selectedValue)}"
				dataProvider="{dataProvider}"
				plotCollection="columns"
				dataField="value"
				labelField="pivotName"
				xDataField="name"
				plotLabelField="name"
				verticalScale="{vScale}"
				horizontalScale="{hScale}"
				stroke="{myStroke}"
				fill="{areaFill}"
				 enableRollOver="true"/>
				 
		</axiis:layouts>
		
	</axiis:DataCanvas>

	<!--  FILLS & STROKES -->

	<!--
	LayoutPalette will generate an Array of colors based on a Layout. The produced colors will be equally distributed between two given anchor colors 
	and will contain x values where x is the number of objects in the Layout's dataProvider. As the Layout renders and its currentIndex property is incremented, 
	the LayoutPalette's currentColor will be incremented as well. Binding on the currentColor allows you vary the color of a fill or stroke used 
	in the Layout's drawingGeometries  as the Layout renders. Very cool.
	-->
	<mx:Array id="palettes">
		<paint:LayoutAutoPalette id="outerPalette" layout="{myLineGroup}" colorFrom="0xCC3333" colorTo="0x3333CC"/>
		<paint:LayoutAutoPalette id="clusterPalette" layout="{myLineGroup}" colorFrom="{outerPalette.currentColor}" colorTo="{outerPalette.currentColor | 0x337f00}"/>
		<paint:LayoutAutoPalette id="areaPalette" layout="{myLineGroup}" colorFrom="0x3333CC" colorTo="0xCC3333"/>
	</mx:Array>
	
	<!--
	A LinearGradientFill lets you specify a gradient fill
	angle defines the transition across the content
	A GradientStop defines the objects that control a transition as part of a gradient fill. Stops will be equally spaced unless ratio is specified
	-->
	<mx:Array id="fills">
		<degrafa:LinearGradientFill id="areaFill" angle="90" enableEvents="false">
			<degrafa:GradientStop color="{areaPalette.currentColor}" alpha=".95"/>
			<degrafa:GradientStop color="{areaPalette.currentColor | 0x999933}" alpha=".65"/>
		</degrafa:LinearGradientFill>
		<degrafa:LinearGradientFill id="clusterFill" angle="45" enableEvents="false">
			<degrafa:GradientStop color="{clusterPalette.currentColor}"/>
			<degrafa:GradientStop color="{clusterPalette.currentColor | 0xFFFFFF}" alpha=".85"/>
		</degrafa:LinearGradientFill>
	</mx:Array>
	
	<!--
	LinearGradientStroke is gradient filled stroke as opposed to just one color. pixelHinting is used to hint strokes to full pixels.
	SolidStroke is typicaly solid stroke. caps define line ends and can put additional lenght on a line. Useful where lines overlap
	-->
	<mx:Array id="strokes">
		<degrafa:LinearGradientStroke id="colStroke" pixelHinting="true" angle="45" enableEvents="false">
			<degrafa:GradientStop color="0xFFFFFF" alpha=".7"/>
			<degrafa:GradientStop color="0xFFFFFF" alpha=".3"/>
		</degrafa:LinearGradientStroke>
		<degrafa:SolidStroke color="0xFFFFFF" alpha=".3"/>
		<degrafa:SolidStroke color="0x222222" id="axisStroke" pixelHinting="true"/>
		<degrafa:SolidStroke color="{areaPalette.currentColor}"
			id="myStroke"
			weight="1"
			alpha="1"
			caps="none"
			pixelHinting="true"/>
	</mx:Array>

	<!-- DISPLAY OBJECTS -->

	<mx:HBox id="myBox" bottom="50" horizontalCenter="0">
		<mx:HBox>
			<mx:Label text="Line Curve" textAlign="right" verticalCenter="0"/>
			<mx:HSlider width="80"
				id="slider"
				minimum="1"
				maximum="80"
				value="35"
				liveDragging="true"
				showTrackHighlight="false"
				verticalCenter="-5"/>
		</mx:HBox>
		<mx:Label text="|"/>
		<mx:HBox>
			<mx:Label text="% Data" textAlign="right" verticalCenter="0"/>
			<mx:HSlider width="80"
				id="dataSlice"
				minimum="3"
				maximum="220"
				value="30"
				snapInterval="1"
				change="{sliceData();}"
				showTrackHighlight="false"
				verticalCenter="-5"/>
		</mx:HBox>
		<mx:HBox>
		<mx:Label text="Label Rotation" textAlign="right" verticalCenter="0"/>
			<mx:HSlider width="80"
				id="labelRotate"
				minimum="0"
				maximum="90"
				value="0"
				snapInterval="1"
				change="{hAxis.labelRotation=labelRotate.value;dc.invalidateDisplayList();}"
				showTrackHighlight="false"
				verticalCenter="-5"/>
		</mx:HBox>
		<mx:Label text="|"/>
		<mx:HBox>
			<mx:Label text="Area" textAlign="right" verticalCenter="0"/>
			<mx:CheckBox id="area" change="{dc.invalidateDisplayList();}" selected="true"/>
		</mx:HBox>
		<mx:Label text="|"/>
		<mx:HBox>
			<mx:Label text="Marker" textAlign="right" verticalCenter="0"/>
			<mx:CheckBox id="showMarker" change="{dc.invalidateDisplayList();}"/>
		</mx:HBox>
		<mx:Label text="|"/>
		<mx:Spacer width="20"/>
		<mx:HBox>
			<mx:RadioButtonGroup id="layoutGroup" change="{dc.invalidateDisplayList();}"/>
			<mx:RadioButton label="Overlay" group="{layoutGroup}" value="{LineSeriesGroup.MODE_BASELINE}" selected="true"/>
			<mx:RadioButton label="Stack" group="{layoutGroup}" value="{LineSeriesGroup.MODE_STACK_ZERO}"/>
			<mx:RadioButton label="Flow" group="{layoutGroup}" value="{LineSeriesGroup.MODE_STACK_FLOW}"/>
		</mx:HBox>
	</mx:HBox>

</mx:Application>

