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}