1package com.yahoo.astra.fl.charts.axes
2{
3	import com.yahoo.astra.display.BitmapText;
4	import com.yahoo.astra.utils.DynamicRegistration;
5	import flash.geom.Point;
6
7	/**
8	 * The default horizontal axis renderer for a cartesian chart.
9	 *
10	 * @see com.yahoo.astra.fl.charts.CartesianChart
11	 * @author Tripp Bridges
12	 */
13	public class HorizontalAxisRenderer extends DefaultAxisRenderer implements ICartesianAxisRenderer
14	{
15
16	//--------------------------------------
17	//  Constructor
18	//--------------------------------------
19
20		/**
21		 * Constructor
22		 */
23		public function HorizontalAxisRenderer()
24		{
25			super();
26			this.orientation = AxisOrientation.HORIZONTAL
27		}
28
29	//--------------------------------------
30	// Properties
31	//--------------------------------------
32		/**
33	 	 * @private
34	 	 * Placeholder for position.
35	 	 */
36		private var _position:String = "left";
37
38	//--------------------------------------
39	//  Protected Methods
40	//--------------------------------------
41
42		/**
43 		 * @private
44		 * Positions the title along the axis.
45		 */
46		override protected function positionTitle():void
47		{
48			var showTitle:Boolean = this.getStyleValue("showTitle") as Boolean;
49			this.titleTextField.visible = showTitle;
50			if(showTitle)
51			{
52				var titleRotation:Number = this.getStyleValue("titleRotation") as Number;
53				titleRotation = Math.max(-90, Math.min(titleRotation, 90));
54
55				this.titleTextField.rotation = titleRotation;
56				this.titleTextField.x = this.contentBounds.x + (this.contentBounds.width/2);
57
58				if(this.position != "top")
59				{
60					this.titleTextField.y = this.y + this.height - this.titleTextField.height;
61				}
62				if(titleRotation < 0)
63				{
64					this.titleTextField.y += this.titleTextField.contentWidth * Math.sin(Math.abs(titleRotation)*Math.PI/180);
65				}
66				this.titleTextField.x -= this.titleTextField.width/2;
67			}
68		}
69
70		/**
71		 * @private
72		 * Draws the axis origin line.
73		 */
74		override protected function drawAxis():void
75		{
76			super.drawAxis();
77			var horizontalY:Number = this.position == "top" ? this.contentBounds.y : this.contentBounds.y + this.contentBounds.height;
78			var horizontalStart:Number = this.contentBounds.x;
79			var horizontalEnd:Number = this.contentBounds.x + this.contentBounds.width;
80			this.graphics.moveTo(horizontalStart, horizontalY);
81			this.graphics.lineTo(horizontalEnd, horizontalY);
82		}
83
84		/**
85		 * @private
86		 * Draws a set of ticks on the axis.
87		 */
88		override protected function drawTicks(data:Array, showTicks:Boolean, tickPosition:String,
89			tickLength:Number, tickWeight:Number, tickColor:uint):void
90		{
91			if(!showTicks)
92			{
93				return;
94			}
95
96			this.graphics.lineStyle(tickWeight, tickColor);
97			var dataCount:int = data.length;
98			var axisPosition:Number = this.position == "top" ? this.contentBounds.y : this.contentBounds.y + this.contentBounds.height;
99			if(this.position == "top") tickLength *= -1;
100			for(var i:int = 0; i < dataCount; i++)
101			{
102				var axisData:AxisData = AxisData(data[i]);
103				if(isNaN(axisData.position))
104				{
105					//skip bad positions
106					continue;
107				}
108
109				var position:Number = axisData.position;
110				position += this.contentBounds.x;
111
112				switch(tickPosition)
113				{
114					case TickPosition.OUTSIDE:
115						this.graphics.moveTo(position, axisPosition);
116						this.graphics.lineTo(position, axisPosition + tickLength);
117						break;
118
119					case TickPosition.INSIDE:
120						this.graphics.moveTo(position, axisPosition - tickLength);
121						this.graphics.lineTo(position, axisPosition);
122						break;
123
124					default: //CROSS
125						this.graphics.moveTo(position, axisPosition - tickLength / 2);
126						this.graphics.lineTo(position, axisPosition + tickLength / 2);
127						break;
128				}
129			}
130		}
131
132		/**
133		 * @private
134		 * Positions a set of labels on the axis.
135		 */
136		override protected function positionLabels(labels:Array, showLabels:Boolean, labelDistance:Number, labelRotation:Number, embedFonts:Boolean):void
137		{
138			if(!showLabels)	return;
139			var labelCount:int = this.labelTextFields.length;
140			for(var i:int = 0; i < labelCount; i++)
141			{
142				var label:BitmapText = BitmapText(this.labelTextFields[i]);
143				label.rotation = 0;
144				var axisData:AxisData = AxisData(this.ticks[i]);
145				var position:Number = axisData.position;
146				position += this.contentBounds.x;
147				var absRotation:Number = Math.abs(labelRotation);
148				label.x = position;
149				var xRegistration:Number;
150				var yRegistration:Number = 0;
151				if(this.position == "top")
152				{
153					label.y = this.contentBounds.y - labelDistance - this.outerTickOffset;
154					if(labelRotation > 0)
155					{
156						label.rotation = labelRotation;
157						label.x -= Math.cos(labelRotation * Math.PI/180) * label.contentWidth;
158						label.x += Math.sin(labelRotation * Math.PI/180) * label.contentHeight/2;
159						label.y -= Math.sin(labelRotation * Math.PI/180) * label.contentWidth;
160						label.y -= Math.cos(labelRotation * Math.PI/180) * label.contentHeight * (1 - labelRotation/90);
161					}
162					else if(labelRotation < 0)
163					{
164						label.y -= Math.cos(Math.abs(labelRotation) * Math.PI/180) * label.contentHeight * (1 - absRotation/90);
165						label.x -= Math.sin(Math.abs(labelRotation) * Math.PI/180) * label.contentHeight/2;
166						label.rotation = labelRotation;
167					}
168					else
169					{
170						label.y -= label.height;
171						label.x = position - label.width / 2;
172					}
173				}
174				else
175				{
176					label.y = this.contentBounds.y + this.contentBounds.height + labelDistance + this.outerTickOffset;
177					if(labelRotation > 0)
178					{
179						label.x = position;
180						label.y -= (label.height * labelRotation / 180);
181						DynamicRegistration.rotate(label, new Point(0, label.height / 2), labelRotation);
182					}
183					else if(labelRotation < 0)
184					{
185						label.x = position - label.width;
186						label.y -= (label.height * Math.abs(labelRotation) / 180);
187						DynamicRegistration.rotate(label, new Point(label.width, label.height / 2), labelRotation);
188					}
189					else //labelRotation == 0
190					{
191						label.x = position - label.width / 2;
192					}
193				}
194
195				label.x = Math.round(label.x);
196				label.y = Math.round(label.y);
197				this.handleOverlappingLabels();
198			}
199		}
200		/**
201		 * @private
202		 * If labels overlap, some may need to be hidden.
203		 */
204		override protected function handleOverlappingLabels():void
205		{
206			var showLabels:Boolean = this.getStyleValue("showLabels");
207			var hideOverlappingLabels:Boolean = this.getStyleValue("hideOverlappingLabels");
208			if(!showLabels || !hideOverlappingLabels)
209			{
210				return;
211			}
212			var labelRotation:Number = this.getStyleValue("labelRotation") as Number;
213			var lastVisibleLabel:BitmapText;
214 			var labelCount:int = this.labelTextFields.length;
215			for(var i:int = 0; i < labelCount; i++)
216			{
217				var idealDistance:Number;
218				var index:int = labelRotation >= 0 ? i : (labelCount - i - 1);
219				var label:BitmapText = BitmapText(this.labelTextFields[index]);
220				label.visible = true;
221				if(lastVisibleLabel)
222				{
223					var diff:Number;
224					var maxWidth:Number;
225					if(labelRotation >= 0)
226					{
227						diff = Math.abs(label.x - lastVisibleLabel.x);
228						maxWidth = lastVisibleLabel.rotationWidth;
229						if(labelRotation == 90)
230						{
231							idealDistance = lastVisibleLabel.textField.textHeight;
232						}
233						else if(labelRotation == 0)
234						{
235							idealDistance = lastVisibleLabel.textField.textWidth;
236						}
237						else
238						{
239							idealDistance = lastVisibleLabel.textField.textHeight / (Math.sin((Math.abs(labelRotation))*Math.PI/180));
240							idealDistance = Math.min(idealDistance, lastVisibleLabel.width);
241						}
242					}
243					else
244					{
245						diff = (lastVisibleLabel.x + lastVisibleLabel.width) - (label.x + label.width);
246						maxWidth = label.rotationWidth;
247						if(labelRotation == 90)
248						{
249							idealDistance = label.textField.textHeight;
250						}
251						else if(labelRotation == 0)
252						{
253							idealDistance = label.textField.textWidth;
254						}
255						else
256						{
257							idealDistance = label.textField.textHeight / (Math.sin((Math.abs(labelRotation))*Math.PI/180));
258							idealDistance = Math.min(idealDistance, label.width);
259						}
260					}
261					if(idealDistance > diff)
262					{
263						label.visible = false;
264					}
265				}
266				if(label.visible)
267				{
268					lastVisibleLabel = label;
269				}
270			}
271		}
272
273
274
275	}
276}