Alright, I've got it working - so for those following along, here's a working filter at a LineSeries not LineChart level....but hit another framework show-stopper and need your expertise Ely (sorry for bugging ya directly Ely, thought ya missed my reply earlier and getting slammed with a deadline - I promise I'll share my Gantt when its finished :).
Anyways, below is my FilteredLineSeries (which works) and my mxml file I'm using to test it. My problem is the horizontalAxis/categoryAxis isn't smart when it filters data - if you change the dataprovider of the categoryAxis back between the hAxisData and the alteredData, you will see what the problem is. In a nut shell, the categoryAxis is filtering the data completely meaning that once it sees a value for the x-axis, it clips/skips the other instances of it - aka, even though I have a number:1 for blue and red, I only see blue. How do I get around this? I need to show both lines for red/blue starting at 1. If you uncomment the basic LineSeries addition, you can see it easier. In pure basic terms: If I have in my dataProvider: name="1" amount="200" brand="blue" name="1" amount="400" brand="red" how do I get 2 lines starting at name="1" and not two entries for "1" in the x-axis? I'm assuming this is a change on CategoryAxis, not the FilteredLineSeries I'll need to mess with. **Also** Side note: Printing of Charts, usually with PrintJobs you have to create a sprite and do an addChild - but a problem in the FlexFramework, is that if I do an addChild of something I'm displaying, I'll lose it because of parenting problems. Is there some nice way to print charts ala cacheAsBitmap or something similar? I'd rather not recreate charts via actionscript for each print job. I know there's some way to say "take what I see and make it a bitmap" but I'm not savy to that and I'm guessing Ely you know how to print charts :) Some advice? ====FilteredLineSeries==== package com.NoTouchie.chart { import mx.charts.series.LineSeries; import mx.charts.ChartItem; import mx.charts.series.items.LineSeriesSegment; import mx.graphics.IStroke; import mx.charts.series.renderData.LineSeriesRenderData; public class FilteredLineSeries extends LineSeries{ public function FilteredLineSeries(customFilters:Array = null) { super(); this._customFilters = customFilters; } public function set customFilters(newFilterSet:Array):void { _customFilters = newFilterSet; invalidateData(); } override protected function updateFilter():void { super.updateFilter(); // No customFilters, then don't run if(_customFilters.length > 0) { var validSegments :Array = new Array(); var validFrom :int = 0; var validTo :int = -1; var getLastValid :Boolean = false; var newCache :Array = new Array(); // For every point in the line... for(var i:int = 0; i < renderData.filteredCache.length; i++) { var currentItem:ChartItem = renderData.filteredCache[i]; // For every custom filter... var currentItemPassed:Boolean = true; for(var j:int = 0; j < _customFilters.length; j++) { var customFieldName:String = _customFilters[j].name; // Considered using FilterVO.equals, but wouldn't work with dynamic name as is // and wasn't sure if it is used elsewhere so I left it. Possible Fix Needed if(currentItem.item[customFieldName] != _customFilters[j].value) { // Only add segments that are lines (*NOT* dots) if(validFrom < validTo) { validSegments.push({validF:validFrom,validT:validTo}); } validFrom = i+1; validTo = i; getLastValid = false; // Filter causes failure, reject value currentItemPassed = false; } else { validTo++; getLastValid = true; } } if(currentItemPassed) { newCache.push(renderData.filteredCache[i]); } } // Add last segment if it wasn't added yet if(getLastValid && (validFrom < validTo)) { validSegments.push({validF:validFrom,validT:validTo}); } // Clear all Segments renderData.segments = []; if(interpolateValues == false) { for(var i:int=0; i < validSegments.length; i++) { // Push segments on that meet our customFilters var newLine:LineSeriesSegment = new LineSeriesSegment(this,i,renderData.filteredCache,validSegments[i].validF,validSegments[i].validT); renderData.segments.push(newLine); } } else { renderData.filteredCache = newCache; // Only push if it's a line if(renderData.filteredCache.length > 1 ) { var newLine:LineSeriesSegment = new LineSeriesSegment(this,0,renderData.filteredCache,0,renderData.filteredCache.length-1); renderData.segments.push(newLine); } } renderData.validPoints = renderData.filteredCache.length; } } private var _customFilters:Array = []; } } =====testChart.mxml===== <?xml version="1.0" encoding="utf-8"?> <mx:Application layout="vertical" verticalGap="100" creationComplete="initApp()" xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:view="*"> <mx:Script> <![CDATA[ import mx.charts.series.LineSeries; import mx.charts.chartClasses.Series; import mx.graphics.Stroke; private function initApp():void { var myFilters:Array=[ [{name:"brand",value:"blue"}], [{name:"brand",value:"red"}]]; var mySeries:Array=new Array(); for(var i:int=0; i<2 ; i++) { var newLineSeries:FilteredLineSeries = new FilteredLineSeries(myFilters[i]); newLineSeries.filterData = true; newLineSeries.interpolateValues = true; newLineSeries.yField = "amount"; newLineSeries.form = "curve"; //var newStroke:Stroke = new Stroke(0x000000,3,1,false); //newLineSeries.setStyle("lineStroke",newStroke); mySeries.push(newLineSeries); } /*var newBasicSeries:LineSeries = new LineSeries(); newBasicSeries.filterData = true; newBasicSeries.interpolateValues = true; newBasicSeries.yField = "amount"; newBasicSeries.form = "curve"; mySeries.push(newBasicSeries); */ myLineChart.series = mySeries; } private var __alteredData : Array = [{name:1,amount:"100",brand:"red",category:"soap"}, {name:2,amount:"20",brand:"red",category:"soap"}, {name:3,amount:"350",brand:"red",category:"food"}, {name:4,amount:"220",brand:"red",category:"soap"}, {name:5,amount:"578",brand:"red",category:"soap"}, {name:6,amount:"900",brand:"red",category:"food"}, {name:7,amount:"89",brand:"red",category:"soap"}, {name:8,amount:"198",brand:"red",category:"food"}, {name:9,amount:"287",brand:"red",category:"soap"}, {name:10,amount:"568",brand:"red",category:"soap"}, {name:11,amount:"013",brand:"red",category:"food"}, {name:12,amount:"298",brand:"red",category:"food"}, {name:1,amount:"1000",brand:"blue",category:"soap"}, {name:2,amount:"200",brand:"blue",category:"soap"}, {name:3,amount:"3500",brand:"blue",category:"food"}, {name:4,amount:"2200",brand:"blue",category:"soap"}, {name:5,amount:"5780",brand:"blue",category:"soap"}, {name:6,amount:"9000",brand:"blue",category:"food"}, {name:7,amount:"890",brand:"blue",category:"soap"}, {name:8,amount:"1980",brand:"blue",category:"food"}, {name:9,amount:"2870",brand:"blue",category:"soap"}, {name:10,amount:"5680",brand:"blue",category:"soap"}, {name:11,amount:"0130",brand:"blue",category:"food"}, {name:12,amount:"2980",brand:"blue",category:"food"}]; private var __hAxisData : Array = [{name:1}, {name:2}, {name:3}, {name:4}, {name:5}, {name:6}, {name:7}, {name:8}, {name:9}, {name:10}, {name:11}, {name:12}]; ]]> </mx:Script> <mx:LineChart id="myLineChart" dataProvider="{__alteredData}" width="100%" height="100%" showDataTips="true"> <mx:horizontalAxis> <mx:CategoryAxis dataProvider="{__alteredData}" categoryField="name"/> </mx:horizontalAxis> <mx:verticalAxis> <mx:LinearAxis maximum="10000"/> </mx:verticalAxis> </mx:LineChart> </mx:Application> -- Flexcoders Mailing List FAQ: http://groups.yahoo.com/group/flexcoders/files/flexcodersFAQ.txt Search Archives: http://www.mail-archive.com/flexcoders%40yahoogroups.com Yahoo! Groups Links <*> To visit your group on the web, go to: http://groups.yahoo.com/group/flexcoders/ <*> Your email settings: Individual Email | Traditional <*> To change settings online go to: http://groups.yahoo.com/group/flexcoders/join (Yahoo! ID required) <*> To change settings via email: mailto:[EMAIL PROTECTED] mailto:[EMAIL PROTECTED] <*> To unsubscribe from this group, send an email to: [EMAIL PROTECTED] <*> Your use of Yahoo! Groups is subject to: http://docs.yahoo.com/info/terms/