1//////////////////////////////////////////////////////////////////////////////// 2// 3// ADOBE SYSTEMS INCORPORATED 4// Copyright 2009 Adobe Systems Incorporated 5// All Rights Reserved. 6// 7// NOTICE: Adobe permits you to use, modify, and distribute this file 8// in accordance with the terms of the license agreement accompanying it. 9// 10//////////////////////////////////////////////////////////////////////////////// 11 12package mx.charts 13{ 14 15import flash.display.DisplayObject; 16import flash.filters.DropShadowFilter; 17import flash.system.ApplicationDomain; 18 19import mx.charts.chartClasses.CartesianChart; 20import mx.charts.chartClasses.CartesianTransform; 21import mx.charts.chartClasses.DataTip; 22import mx.charts.chartClasses.DataTransform; 23import mx.charts.chartClasses.IChartElement; 24import mx.charts.chartClasses.NumericAxis; 25import mx.charts.chartClasses.Series; 26import mx.charts.series.BarSeries; 27import mx.charts.series.BarSet; 28import mx.charts.series.items.BarSeriesItem; 29import mx.charts.styles.HaloDefaults; 30import mx.core.IFlexModuleFactory; 31import mx.core.mx_internal; 32import mx.graphics.SolidColor; 33import mx.graphics.SolidColorStroke; 34import mx.graphics.Stroke; 35import mx.styles.CSSStyleDeclaration; 36 37use namespace mx_internal; 38 39//-------------------------------------- 40// Styles 41//-------------------------------------- 42 43/** 44 * Specifies how wide to draw the bars relative to the category width, 45 * as a percentage in the range of 0 to 1. 46 * A value of 1 uses the entire space, while a value of 0.6 47 * uses 60% of the bar's available space. 48 * The actual bar width used is the smaller of the 49 * <code>barWidthRatio</code> property and the 50 * <code>maxbarWidth</code> property 51 * Clustered bars divide this space proportionally 52 * among the bars in each cluster. 53 * The default value is 0.65. 54 * 55 * @langversion 3.0 56 * @playerversion Flash 9 57 * @playerversion AIR 1.1 58 * @productversion Flex 3 59 */ 60[Style(name="barWidthRatio", type="Number", inherit="no")] 61 62/** 63 * Specifies how wide to draw the bars, in pixels. 64 * The actual bar width used is the smaller of this property 65 * and the <code>barWidthRatio</code> property. 66 * Clustered bars divide this space proportionally 67 * among the bars in each cluster. 68 * 69 * @langversion 3.0 70 * @playerversion Flash 9 71 * @playerversion AIR 1.1 72 * @productversion Flex 3 73 */ 74[Style(name="maxBarWidth", type="Number", format="Length", inherit="no")] 75 76/** 77 * The class that is used by this component to render labels. 78 * 79 * <p>It can be set to either the mx.controls.Label class 80 * or the spark.components.Label class.</p> 81 * 82 * @default spark.components.Label 83 * 84 * @langversion 3.0 85 * @playerversion Flash 10.2 86 * @playerversion AIR 2.0 87 * @productversion Flex 4 88 */ 89[Style(name="labelClass", type="Class", inherit="no")] 90 91//-------------------------------------- 92// Other metadata 93//-------------------------------------- 94 95[DefaultBindingProperty(destination="dataProvider")] 96 97[DefaultTriggerEvent("itemClick")] 98 99[IconFile("BarChart.png")] 100 101/** 102 * The BarChart control represents data as a series of horizontal bars 103 * whose length is determined by values in the data. 104 * A BarChart control can represent different chart variations, 105 * including simple bars, clustered bars, stacked, 100% stacked, and high/low. 106 * 107 * <p>The BarChart control expects its <code>series</code> property 108 * to contain an array of BarSeries objects.</p> 109 * 110 * <p>Stacked and 100% bar charts override the <code>minField</code> 111 * property of their BarSeries objects.</p> 112 * 113 * @mxml 114 * 115 * <p>The <code><mx:BarChart></code> tag inherits all the properties 116 * of its parent classes, and adds the following properties:</p> 117 * 118 * <pre> 119 * <mx:BarChart 120 * <strong>Properties</strong> 121 * type="clustered|overlaid|stacked|100%" 122 * 123 * <strong>Styles</strong> 124 * barWidthRatio=".65" 125 * maxBarWidth="<i>No default</i>" 126 * /> 127 * </pre> 128 * 129 * @includeExample examples/Column_BarChartExample.mxml 130 * 131 * @see mx.charts.series.BarSeries 132 * 133 * @langversion 3.0 134 * @playerversion Flash 9 135 * @playerversion AIR 1.1 136 * @productversion Flex 3 137 */ 138public class BarChart extends CartesianChart 139{ 140 include "../core/Version.as"; 141 142 //-------------------------------------------------------------------------- 143 // 144 // Class initialization 145 // 146 //-------------------------------------------------------------------------- 147 148 //-------------------------------------------------------------------------- 149 // 150 // Class constants 151 // 152 //-------------------------------------------------------------------------- 153 154 /** 155 * @private 156 */ 157 private static var INVALIDATING_STYLES:Object = 158 { 159 barWidthRatio: 1, 160 maxBarWidth: 1 161 } 162 163 //-------------------------------------------------------------------------- 164 // 165 // Constructor 166 // 167 //-------------------------------------------------------------------------- 168 169 /** 170 * Constructor. 171 * 172 * @langversion 3.0 173 * @playerversion Flash 9 174 * @playerversion AIR 1.1 175 * @productversion Flex 3 176 */ 177 public function BarChart() 178 { 179 super(); 180 181 LinearAxis(verticalAxis).autoAdjust = false; 182 183 dataTipMode = "single"; 184 185 seriesFilters = [ new DropShadowFilter(2, 45, 0.2 * 0xFFFFFF)]; 186 } 187 188 //-------------------------------------------------------------------------- 189 // 190 // Variables 191 // 192 //-------------------------------------------------------------------------- 193 194 /** 195 * @private 196 */ 197 private var _moduleFactoryInitialized:Boolean = false; 198 199 /** 200 * @private 201 */ 202 private var _perSeriesBarWidthRatio:Number; 203 204 /** 205 * @private 206 */ 207 private var _perSeriesMaxBarWidth:Number; 208 209 /** 210 * @private 211 */ 212 private var _rightOffset:Number; 213 214 /** 215 * @private 216 */ 217 private var _wasStacked:Boolean = false; 218 219 /** 220 * @private 221 */ 222 mx_internal var allLabelsMeasured:Boolean = false; 223 224 /** 225 * @private 226 */ 227 private var _allItems:Array /* of ChartItem */ = []; 228 229 /** 230 * @private 231 */ 232 private var _barSeriesLen:Number; 233 234 /** 235 * @private 236 */ 237 private var _needLabels:Boolean = false; 238 239 /** 240 * @private 241 */ 242 private var _tempField:Object; 243 244 //-------------------------------------------------------------------------- 245 // 246 // Properties 247 // 248 //-------------------------------------------------------------------------- 249 250 //---------------------------------- 251 // type 252 //---------------------------------- 253 254 /** 255 * @private 256 * Storage for the type property. 257 */ 258 private var _type:String = "clustered"; 259 260 [Inspectable(category="General", enumeration="stacked,100%,clustered,overlaid", defaultValue="clustered")] 261 262 /** 263 * The type of bar chart to render. Possible values are: 264 * <ul> 265 * <li><code>"clustered"</code>: 266 * Bars are grouped by category. 267 * This is the default value.</li> 268 * 269 * <li><code>"overlaid"</code>: 270 * Multiple bars are rendered on top of each other by category, 271 * with the last series specified on top.</li> 272 * 273 * <li><code>"stacked"</code>: 274 * Bars are stacked end to end and grouped by category. 275 * Each bar represents the cumulative value of the values beneath it.</li> 276 * 277 * <li><code>"100%"</code>: 278 * Bars are stacked end to end, adding up to 100%. 279 * Each bar represents the percent that it contributes 280 * to the sum of the values for that category.</li> 281 * </ul> 282 * 283 * @langversion 3.0 284 * @playerversion Flash 9 285 * @playerversion AIR 1.1 286 * @productversion Flex 3 287 */ 288 public function get type():String 289 { 290 return _type; 291 } 292 293 /** 294 * @private 295 */ 296 public function set type(value:String):void 297 { 298 _type = value; 299 300 invalidateSeries(); 301 invalidateData(); 302 } 303 304 //-------------------------------------------------------------------------- 305 // 306 // Overridden methods: UIComponent 307 // 308 //-------------------------------------------------------------------------- 309 310 311 /** 312 * @private 313 */ 314 private function initStyles():Boolean 315 { 316 HaloDefaults.init(styleManager); 317 var barChartStyle:CSSStyleDeclaration = styleManager.getStyleDeclaration("mx.charts.BarChart"); 318 barChartStyle.setStyle("chartSeriesStyles", HaloDefaults.chartBaseChartSeriesStyles); 319 barChartStyle.setStyle("fill", new SolidColor(0xFFFFFF, 0)); 320 barChartStyle.setStyle("calloutStroke", new SolidColorStroke(0x888888,2)); 321 barChartStyle.setStyle("horizontalAxisStyleNames", ["blockNumericAxis"]); 322 barChartStyle.setStyle("verticalAxisStyleNames", ["blockCategoryAxis"]); 323 return true; 324 } 325 326 327 /** 328 * A module factory is used as context for using embedded fonts and for finding the style manager that controls the styles for this component. 329 * 330 * @langversion 3.0 331 * @playerversion Flash 9 332 * @playerversion AIR 1.1 333 * @productversion Flex 3 334 */ 335 override public function set moduleFactory(factory:IFlexModuleFactory):void 336 { 337 super.moduleFactory = factory; 338 339 if (_moduleFactoryInitialized) 340 return; 341 342 _moduleFactoryInitialized = true; 343 344 // our style settings 345 initStyles(); 346 } 347 348 /** 349 * @private 350 */ 351 override protected function createChildren():void 352 { 353 super.createChildren(); 354 var labelClass:Class = getLabelClass(); 355 _tempField = new labelClass(); 356 _tempField.visible = false; 357 _tempField.text="W..."; 358 _tempField.toolTip = ""; 359 addChild(_tempField as DisplayObject); 360 _tempField.validateNow(); 361 } 362 363 private function getLabelClass():Class 364 { 365 var labelClass:Class = getStyle("labelClass"); 366 if(labelClass == null) 367 { 368 try{ 369 labelClass = Class(ApplicationDomain.currentDomain. 370 getDefinition("spark.components::Label")); 371 } 372 catch(e:Error) 373 { 374 labelClass = Class(ApplicationDomain.currentDomain. 375 getDefinition("mx.controls::Label")); 376 } 377 } 378 return labelClass; 379 } 380 381 382 /** 383 * @private 384 */ 385 override public function styleChanged(styleProp:String):void 386 { 387 if (styleProp == null || INVALIDATING_STYLES[styleProp] != undefined) 388 invalidateSeries(); 389 390 super.styleChanged(styleProp); 391 } 392 393 //-------------------------------------------------------------------------- 394 // 395 // Overridden methods: ChartBase 396 // 397 //-------------------------------------------------------------------------- 398 399 /** 400 * @private 401 */ 402 override protected function customizeSeries(seriesGlyph:Series, i:uint):void 403 { 404 if ((seriesGlyph is BarSeries) || (seriesGlyph is BarSet)) 405 { 406 var series:Object = seriesGlyph; 407 408 if (!isNaN(_perSeriesBarWidthRatio)) 409 series.barWidthRatio = _perSeriesBarWidthRatio; 410 411 if (!isNaN(_perSeriesMaxBarWidth)) 412 series.maxBarWidth = _perSeriesMaxBarWidth; 413 414 if (_type == "overlaid") 415 series.offset = 0; 416 else 417 series.offset = _rightOffset - i * _perSeriesBarWidthRatio; 418 419 if (series is BarSeries) 420 { 421 series.stacker = null; 422 series.stackTotals = null; 423 } 424 } 425 } 426 427 /** 428 * @private 429 */ 430 override protected function applySeriesSet(seriesSet:Array /* of Series */, 431 transform:DataTransform):Array /* of Series */ 432 { 433 434 var barWidthRatio:Number = getStyle("barWidthRatio"); 435 var maxBarWidth:Number = getStyle("maxBarWidth"); 436 var g:IChartElement; 437 var n:int = seriesSet.length; 438 439 switch (_type) 440 { 441 case "stacked": 442 case "100%": 443 { 444 _wasStacked = true; 445 446 for (var i:int = 0; i < n; i++) 447 { 448 seriesSet[i].offset = 0; 449 } 450 451 var newSeriesGlyph:BarSet = new BarSet(); 452 newSeriesGlyph.series = seriesSet; 453 for (i = 0; i < n; i++) 454 { 455 g = seriesSet[i] as IChartElement; 456 if (!g) 457 continue; 458 if (g.labelContainer) 459 newSeriesGlyph.labelContainer.addChild(seriesSet[i].labelContainer); 460 } 461 462 if (!isNaN(barWidthRatio)) 463 newSeriesGlyph.barWidthRatio = barWidthRatio; 464 465 if (!isNaN(maxBarWidth)) 466 newSeriesGlyph.maxBarWidth = maxBarWidth; 467 468 newSeriesGlyph.type = _type; 469 470 invalidateData(); 471 return [ newSeriesGlyph ]; 472 } 473 474 case "clustered": 475 default: 476 { 477 478 var barSeriesCount:int = 0; 479 for each(var series:Series in seriesSet) { 480 if(series is BarSet || series is BarSeries) 481 barSeriesCount++; 482 } 483 484 _perSeriesBarWidthRatio = barWidthRatio / barSeriesCount; 485 _perSeriesMaxBarWidth = maxBarWidth / barSeriesCount; 486 _rightOffset = barWidthRatio / 2 - _perSeriesBarWidthRatio / 2; 487 n = seriesSet.length; 488 var count:int = 0; 489 for (i = 0; i < n; i++) 490 { 491 var newSeries:IChartElement = seriesSet[i]; 492 if (newSeries is BarSeries || newSeries is BarSet) 493 { 494 customizeSeries(Series(seriesSet[i]), count); 495 count++; 496 } 497 } 498 499 return seriesSet; 500 } 501 502 case "overlaid": 503 { 504 _perSeriesBarWidthRatio = barWidthRatio; 505 _perSeriesMaxBarWidth = maxBarWidth; 506 507 _rightOffset = 0; 508 super.applySeriesSet(seriesSet, transform); 509 break; 510 } 511 } 512 513 return seriesSet; 514 } 515 516 //-------------------------------------------------------------------------- 517 // 518 // Overridden methods: CartesianChart 519 // 520 //-------------------------------------------------------------------------- 521 522 /** 523 * Determines positions and dimensions of labels for all series in the chart 524 * 525 * @langversion 3.0 526 * @playerversion Flash 9 527 * @playerversion AIR 1.1 528 * @productversion Flex 3 529 */ 530 override mx_internal function measureLabels():Object 531 { 532 getSeriesLabelPosSet(); 533 if (!_needLabels) 534 return null; 535 var n:int = series.length; 536 var allSeriesTransform:Boolean = true; 537 538 if (type == "stacked" || type == "overlaid" || type == "100%") 539 allLabelsMeasured = false; 540 541 _allItems = []; 542 _barSeriesLen = 0; 543 for (var i:int = 0; i < n; i++) 544 { 545 findChartItems(series[i]); 546 } 547 _allItems.sort(sortOnY); //sort all items with respect to thier position along Y-axis 548 var itemsLen:Number = _allItems.length; 549 for (i = itemsLen - 1; i >= 0; i--) 550 { 551 var v:BarSeriesItem = _allItems[i]; 552 var barSeries:BarSeries = BarSeries(BarSeriesItem(_allItems[i]).element); 553 var labelPosition:String = barSeries.labelPos; 554 555 if (labelPosition == "inside" || labelPosition == "outside") 556 { 557 558 var base:Number = barSeries.seriesRenderData.renderedBase; 559 var size:Number = barSeries.getStyle('fontSize'); 560 if (barSeries.labelFunction != null) 561 barSeries.measuringField.text = v.labelText = barSeries.labelFunction(v, barSeries); 562 else if (barSeries.labelField != null) 563 barSeries.measuringField.text = v.labelText = v.item[barSeries.labelField]; 564 else if (barSeries.dataFunction != null) 565 barSeries.measuringField.text = v.labelText = barSeries.dataFunction(barSeries, v.item, 'xNumber'); 566 else 567 barSeries.measuringField.text = v.labelText = v.item[barSeries.xField]; 568 569 barSeries.measuringField.validateNow(); 570 571 var labelRotation:Number = barSeries.labelAngle; 572 var labelSizeLimit:Number = barSeries.maxLabelSize; 573 if (labelPosition == "outside" && (type == "stacked" || type == "overlaid" || type == "100%")) 574 { 575 labelPosition = "inside"; 576 barSeries.labelPos = 'inside'; 577 //today, labelPosition = inside is only supported for stacked, 100% and overlaid 578 } 579 580 581 if (labelPosition == 'outside') 582 { 583 v.labelHeight = 2 * barSeries.seriesRenderData.renderedHalfWidth; 584 if (!(isNaN(labelRotation)) && labelRotation != 0 && barSeries.measuringField.embedFonts) 585 { 586 var r:Number = -labelRotation / Math.PI * 180; 587 //for future enhancement 588 //check for type of chart if we need to support labelPosition = outside for all types of charts 589 if (type == "clustered") 590 { 591 if (i > n - 1) 592 v.labelWidth = Math.abs((_allItems[i - i%n - 1].y + BarSeries(_allItems[i - i%n - 1].element).seriesRenderData.renderedYOffset 593 + BarSeries(_allItems[i - i%n - 1].element).seriesRenderData.renderedHalfWidth - 594 (v.y + barSeries.seriesRenderData.renderedYOffset - 595 barSeries.seriesRenderData.renderedHalfWidth))/ Math.cos(r)); 596 else 597 v.labelWidth = Math.abs((_allItems[0].y + BarSeries(_allItems[0].element).seriesRenderData.renderedYOffset 598 - BarSeries(_allItems[0].element).seriesRenderData.renderedHalfWidth - 599 (v.y + barSeries.seriesRenderData.renderedYOffset - 600 barSeries.seriesRenderData.renderedHalfWidth))/ Math.cos(r)); 601 } 602 else 603 { 604 if (i > n - 1) 605 v.labelWidth = Math.abs((_allItems[i - n].y + BarSeries(_allItems[i - n].element).seriesRenderData.renderedYOffset 606 + BarSeries(_allItems[i - n].element).seriesRenderData.renderedHalfWidth - 607 (v.y + barSeries.seriesRenderData.renderedYOffset - 608 barSeries.seriesRenderData.renderedHalfWidth))/ Math.cos(r)); 609 else 610 v.labelWidth = Math.abs((_allItems[0].y + BarSeries(_allItems[0].element).seriesRenderData.renderedYOffset 611 - BarSeries(_allItems[0].element).seriesRenderData.renderedHalfWidth - 612 (v.y + barSeries.seriesRenderData.renderedYOffset - 613 barSeries.seriesRenderData.renderedHalfWidth))/ Math.cos(r)); 614 } 615 v.labelY=v.y + barSeries.seriesRenderData.renderedYOffset + barSeries.seriesRenderData.renderedHalfWidth; 616 } 617 else 618 { 619 if (v.x > (isNaN(v.min) ? base : v.min)) 620 { 621 v.labelWidth = barSeries.dataToLocal(NumericAxis(barSeries.dataTransform.getAxis(CartesianTransform.HORIZONTAL_AXIS)).computedMaximum,0).x - barSeries.dataToLocal(v.xNumber,0).x; 622 v.labelX = v.x; 623 if (v.labelWidth == 0) 624 { 625 v.labelWidth = Math.abs(v.x -(isNaN(v.min) ? base : v.min)); 626 v.labelX = isNaN(v.min) ? base : v.min; 627 } 628 } 629 else 630 { 631 v.labelWidth = barSeries.dataToLocal(v.xNumber,0).x - barSeries.dataToLocal(NumericAxis(barSeries.dataTransform.getAxis(CartesianTransform.HORIZONTAL_AXIS)).computedMinimum,0).x; 632 v.labelX = v.x - v.labelWidth; 633 if (v.labelWidth == 0) 634 { 635 v.labelWidth = Math.abs(v.x -(isNaN(v.min) ? base : v.min)); 636 v.labelX = v.x; 637 } 638 } 639 v.labelY=v.y + barSeries.seriesRenderData.renderedYOffset - barSeries.seriesRenderData.renderedHalfWidth; 640 } 641 var labelScale:Number = 1; 642 if (barSeries.measuringField.textWidth > v.labelWidth || barSeries.measuringField.textHeight > v.labelHeight) 643 { 644 labelScale = v.labelWidth / barSeries.measuringField.textWidth; 645 labelScale = Math.min(labelScale, v.labelHeight / barSeries.measuringField.textHeight); 646 if (size * labelScale > labelSizeLimit) 647 barSeries.seriesRenderData.labelScale = Math.min(labelScale,barSeries.seriesRenderData.labelScale); 648 else 649 { 650 _tempField.setStyle('fontSize',size); 651 _tempField.validateNow(); 652 if (_tempField.measuredWidth > v.labelWidth || _tempField.measuredHeight > v.labelHeight) 653 { 654 labelScale = v.labelWidth / _tempField.measuredWidth; 655 labelScale = Math.min(labelScale, v.labelHeight / _tempField.measuredHeight); 656 if (size * labelScale > labelSizeLimit) 657 barSeries.seriesRenderData.labelScale = Math.min(labelScale,barSeries.seriesRenderData.labelScale); 658 else 659 { 660 v.labelText = ""; 661 v.labelWidth = 1; 662 } 663 } 664 } 665 } 666 667 if (!isNaN(labelRotation) && labelRotation!=0 && barSeries.measuringField.embedFonts) 668 { 669 v.labelHeight = barSeries.measuringField.textHeight + 2; 670 if (v.x > (isNaN(v.min) ? base : v.min)) 671 v.labelX = v.x + v.labelHeight; 672 else 673 v.labelX = v.x - 2 * v.labelHeight; 674 v.labelY = v.labelY - v.labelHeight; 675 v.labelWidth = v.labelWidth - v.labelHeight; 676 } 677 } 678 else if (labelPosition == "inside") 679 { 680 v.labelWidth = Math.abs(v.x -(isNaN(v.min) ? base : v.min)); 681 v.labelHeight = 2 * barSeries.seriesRenderData.renderedHalfWidth; 682 v.labelY=v.y + barSeries.seriesRenderData.renderedYOffset - barSeries.seriesRenderData.renderedHalfWidth; 683 684 if (v.x > (isNaN(v.min) ? base : v.min)) 685 v.labelX = isNaN(v.min) ? base : v.min; 686 else 687 v.labelX = v.x; 688 labelScale = 1; 689 if (barSeries.measuringField.textWidth > v.labelWidth || (barSeries.measuringField.textHeight) > v.labelHeight) 690 { 691 labelScale = v.labelWidth / barSeries.measuringField.textWidth; 692 labelScale = Math.min(labelScale, v.labelHeight / barSeries.measuringField.textHeight); 693 if (size * labelScale > labelSizeLimit) 694 barSeries.seriesRenderData.labelScale = Math.min(labelScale,barSeries.seriesRenderData.labelScale); 695 else 696 { 697 _tempField.setStyle('fontSize',size); 698 _tempField.validateNow(); 699 if (_tempField.measuredWidth > v.labelWidth || _tempField.measuredHeight + 2 > v.labelHeight) 700 { 701 labelScale = v.labelWidth / _tempField.measuredWidth; 702 labelScale = Math.min(labelScale, v.labelHeight / _tempField.measuredHeight); 703 if (size * labelScale > labelSizeLimit) 704 barSeries.seriesRenderData.labelScale = Math.min(labelScale,barSeries.seriesRenderData.labelScale); 705 else 706 { 707 v.labelText = ""; 708 v.labelWidth = 1; 709 } 710 } 711 } 712 } 713 var prevItemsCount:int =_barSeriesLen - 1 - (i % _barSeriesLen); 714 for (var j:int = 1; j <= prevItemsCount; j++) 715 //test for overlaps with previous labels 716 { 717 var tempItem:BarSeriesItem = _allItems[i + j]; 718 if (v.labelY == tempItem.labelY) 719 { 720 if (((v.labelX >= tempItem.labelX) && (v.labelX < (tempItem.labelX + tempItem.labelWidth))) || 721 ((v.labelX <= tempItem.labelX) && ((v.labelX + v.labelWidth) > tempItem.labelX))) 722 { 723 v.labelText = ""; 724 v.labelWidth = 1; 725 } 726 } 727 } 728 } 729 } 730 else 731 { 732 barSeries.seriesRenderData.labelData = null; 733 barSeries.labelCache.count = 0; 734 } 735 } 736 allLabelsMeasured = true; 737 for (i = 0; i < n; i++) 738 { 739 invalidateDisplay(series[i]); 740 } 741 return null; 742 } 743 744 //------------------------------------------------------------------------------------ 745 // 746 // Methods 747 // 748 //------------------------------------------------------------------------------------ 749 750 mx_internal function getSeriesLabelPos(series:Series):void 751 { 752 if (series is BarSeries) 753 { 754 var barSeries:BarSeries = BarSeries(series); 755 var position:String = barSeries.labelPos; 756 if (position == "inside" || position == "outside" || position == "none") 757 _needLabels = true; 758 } 759 else if (series is BarSet) 760 { 761 var setSeries:Array /* of Series */ = BarSet(series).series; 762 var n:int = setSeries.length; 763 for (var i:int = 0; i < n; i++) 764 { 765 getSeriesLabelPos(setSeries[i]); 766 } 767 } 768 } 769 770 mx_internal function getSeriesLabelPosSet():void 771 { 772 var n:int = series.length; 773 _needLabels = false; 774 for (var i:int = 0; i < n; i++) 775 { 776 if (_needLabels) 777 return; 778 getSeriesLabelPos(series[i]); 779 } 780 } 781 782 /** 783 * @private 784 */ 785 private function sortOnY(a:BarSeriesItem,b:BarSeriesItem):int 786 { 787 var offset1:Number = BarSeries(a.element).seriesRenderData.renderedYOffset; 788 var offset2:Number = BarSeries(b.element).seriesRenderData.renderedYOffset; 789 if (a.y + offset1 > b.y + offset2) 790 return 1; 791 else if (a.y + offset1 < b.y + offset2) 792 return -1; 793 else 794 { 795 if (a.xNumber > b.xNumber) 796 return 1; 797 else if (a.xNumber < b.xNumber) 798 return -1; 799 else 800 return 0; 801 } 802 } 803 804 /** 805 * @private 806 */ 807 private function findChartItems(series:Series):void 808 { 809 var n:int; 810 var i:int; 811 if (series is BarSeries) 812 { 813 _barSeriesLen = _barSeriesLen + 1; 814 var barSeries:BarSeries = BarSeries(series); 815 var seriesItems:Array /* of BarSeriesItem */ = barSeries.seriesRenderData.filteredCache; 816 n = seriesItems.length; 817 barSeries.labelCache.count = n; 818 barSeries.seriesRenderData.labelScale = 1; 819 820 for (i = 0; i < n; i++) 821 { 822 _allItems.push(BarSeriesItem(seriesItems[i])); 823 } 824 } 825 else if (series is BarSet) 826 { 827 var setSeries:Array /* of Series */ = BarSet(series).series; 828 n = setSeries.length; 829 for (i = 0; i < n; i++) 830 { 831 findChartItems(setSeries[i]); 832 } 833 } 834 } 835 /** 836 * @private 837 */ 838 private function invalidateDisplay(series:Series):void 839 { 840 if (series is BarSeries) 841 BarSeries(series).updateLabels(); 842 else if (series is BarSet) 843 { 844 var setSeries:Array /* of Series */ = BarSet(series).series; 845 var n:int = setSeries.length; 846 for (var i:int = 0; i < n; i++) 847 { 848 invalidateDisplay(setSeries[i]); 849 } 850 } 851 } 852 853} 854 855} 856