<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
                xmlns:mccune="com.dougmccune.controls.*" viewSourceURL="srcview/index.html"
                creationComplete="chartComplete()" backgroundColor="#FFFFFF">
    
    <mx:CartesianChart id="bigChart" showDataTips="true" dataProvider="{mainData}" width="100%" height="100%">
        
        <mx:horizontalAxis><mx:CategoryAxis categoryField="E"/></mx:horizontalAxis>
        <mx:horizontalAxisRenderer><mx:AxisRenderer visible="false" /></mx:horizontalAxisRenderer>
        
        <mx:verticalAxis><mx:LinearAxis  /></mx:verticalAxis>
        <mx:verticalAxisRenderer><mx:AxisRenderer visible="false" /></mx:verticalAxisRenderer>
        
        <mx:series>
            <mx:AreaSeries name="A" yField="A" areaFill="{new SolidColor(0x0033CC, 0.5)}"  areaStroke="{new Stroke(0x0033CC, 2)}" />
        </mx:series>
        
        <mx:annotationElements>
            <mx:Canvas width="100%" height="100%" buttonMode="true" mouseDown="setMouseDown(bigChart)" />
        </mx:annotationElements>
        
    </mx:CartesianChart>
    
    <mx:VBox verticalGap="0" width="100%" verticalScrollPolicy="off" horizontalAlign="right">
        
        <mx:CartesianChart id="smallChart" dataProvider="{chartData}" width="100%" height="100">
            
            <mx:horizontalAxis><mx:CategoryAxis categoryField="E"/></mx:horizontalAxis>
            <mx:horizontalAxisRenderer><mx:AxisRenderer visible="false" /></mx:horizontalAxisRenderer>
            
            <mx:verticalAxis><mx:LinearAxis  /></mx:verticalAxis>
            <mx:verticalAxisRenderer><mx:AxisRenderer visible="false" /></mx:verticalAxisRenderer>
            <mx:series>
                <mx:AreaSeries name="A" yField="A" areaStroke="{new Stroke(0x0033CC, 2)}" areaFill="{new SolidColor(0x0033CC, 0.5)}" />
            </mx:series>
            
            <mx:annotationElements>
                <mx:HDividedBox id="overlayCanvas" width="100%" alpha="1" dividerAffordance="5" liveDragging="true" horizontalGap="10" verticalGap="0" horizontalScrollPolicy="off" 
                                dividerDrag="updateBoundariesFromDivider(event)" dividerSkin="{blankDividerClass}"
                                mouseOver="overlayCanvas.setStyle('dividerSkin', dividerClass);" mouseOut="overlayCanvas.setStyle('dividerSkin', blankDividerClass);">
                    <mx:Canvas id="leftBox" height="100%"
                               width="{(overlayCanvas.width / chartData.length) * leftBoundary}" 
                               backgroundAlpha="0.8" backgroundColor="#EEEEEE" borderThickness="1" borderColor="#999999" borderStyle="solid" />
                    <mx:Canvas id="visibleBox" width="100%" height="100%" buttonMode="true" mouseDown="setMouseDown(smallChart)" />
                    <mx:Canvas id="rightBox" height="100%" 
                               width="{(overlayCanvas.width / chartData.length) * (chartData.length - rightBoundary)}" 
                               backgroundAlpha="0.8" backgroundColor="#EEEEEE" borderThickness="1" borderColor="#999999" borderStyle="solid"/>
                </mx:HDividedBox>
            </mx:annotationElements>
            
        </mx:CartesianChart>
        <mx:Spacer height="-30" />
        <mccune:HSlider id="slider" width="{overlayCanvas.width}" height="25"
                        trackHighlightSkin="com.dougmccune.skins.SliderThumbHighlightSkin"
                        allowTrackClick="true" allowThumbOverlap="false" 
                        liveDragging="true" change="updateBoundariesFromSlider()"
                        showDataTip="true" dataTipPlacement="bottom" dataTipOffset="3"
                        showTrackHighlight="true"
                        thumbCount="2" snapInterval="1"
                        values="{[leftBoundary, rightBoundary]}"
                        minimum="0" maximum="{chartData.length - 1}"
                        />
    </mx:VBox>
    
    <mx:Script>
        <![CDATA[
            import mx.managers.SystemManager;
            import mx.events.ResizeEvent;
            import mx.graphics.Stroke;
            import mx.graphics.SolidColor;
            import mx.collections.ArrayCollection;
            import mx.events.DividerEvent;
            import mx.managers.SystemManager;
            
            [Embed(source="divider.png")] [Bindable] public var dividerClass:Class;
            [Embed(source="blank.png")] [Bindable] public var blankDividerClass:Class;
            
            
            private var DATA_LENGTH:Number = 500;
            private var LEFT_START:Number = 150;
            private var RIGHT_START:Number = 250;
            [Bindable] public var chartData:ArrayCollection;
            [Bindable] public var mainData:ArrayCollection;
            
            [Bindable] private var leftBoundary:Number;
            [Bindable] private var rightBoundary:Number;
            
            private var staticLeftBoundary:Number;
            private var staticRightBoundary:Number;
            
            public var smallDrag:Boolean = false;
            public var bigDrag:Boolean = false;
            public var mouseXRef:Number;
            
            private function chartComplete():void
            {
                var newData:Array = [];
                var A:Number = Math.random()*100 - 50;
                var B:Number = A - Math.random() * 10;
                var P:Number = Math.random()*100;
                for(var i:int = 0;i<DATA_LENGTH;i++)
                {
                    A = Math.abs(A + Math.random()*10 - 5);
                    B = A - Math.random() * 10;
                    P = Math.random()*100;
                    newData.push( { A: A, B: B, P: P } );
                }
                chartData = new ArrayCollection(newData);        
                mainData = new ArrayCollection(chartData.source);
                leftBoundary = LEFT_START;
                rightBoundary = RIGHT_START;
                updateBoundariesFromSlider();
            }
            
            private function updateBoundariesFromSlider():void
            {
                leftBoundary = slider.values[0];
                rightBoundary = slider.values[1];
                updateMainData();
            }
            
            private function updateBoundariesFromDivider(event:DividerEvent):void
            {
                leftBoundary = Math.abs(HDividedBox(event.target).getChildAt(0).width / (event.target.width / chartData.length));
                rightBoundary = Math.abs(chartData.length - (HDividedBox(event.target).getChildAt(2).width / (event.target.width / chartData.length)));
                updateMainData();
            }
            
            private function updateMainData():void
            {
                mainData.source = chartData.source.slice(leftBoundary, rightBoundary)
            }

            private function setMouseDown(theChart:CartesianChart):void
            {
                mouseXRef = this.mouseX;
                staticLeftBoundary = leftBoundary;
                staticRightBoundary = rightBoundary;
                if(theChart == bigChart) bigDrag = true;
                if(theChart == smallChart) smallDrag = true;
                this.systemManager.addEventListener(MouseEvent.MOUSE_MOVE, moveChart);
                this.systemManager.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
            }
            
            private function stopDragging(event:MouseEvent):void
            {
                smallDrag = false;
                bigDrag = false;
                this.systemManager.removeEventListener(MouseEvent.MOUSE_MOVE, moveChart);
                this.systemManager.removeEventListener(MouseEvent.MOUSE_UP, stopDragging);
            }
            
            private function moveChart(event:MouseEvent):void
            {
                if(bigDrag)
                {
                    leftBoundary = staticLeftBoundary + (mouseXRef - this.mouseX) / (bigChart.width / mainData.length);
                    rightBoundary = staticRightBoundary + (mouseXRef - this.mouseX) / (bigChart.width / mainData.length);
                }
                else if(smallDrag)
                {
                    leftBoundary = staticLeftBoundary - (mouseXRef - this.mouseX) / (smallChart.width / chartData.length);
                    rightBoundary = staticRightBoundary - (mouseXRef - this.mouseX) / (smallChart.width / chartData.length);
                }
            }
        ]]>
    </mx:Script>
</mx:Application>