Guest User

Untitled

a guest
Aug 17th, 2018
131
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.  
  2.  
  3.  
  4. package com.xxxx.charts {
  5.     import com.xxxx.charts.chartClasses.GanttConfig;
  6.     import com.xxxx.charts.chartClasses.Snapping;
  7.     import com.xxxx.charts.renderers.DateAxisRenderer;
  8.  
  9.     import flash.events.Event;
  10.     import flash.geom.Rectangle;
  11.  
  12.     import mx.charts.DateTimeAxis;
  13.     import mx.collections.IList;
  14.     import mx.core.ClassFactory;
  15.     import mx.events.CollectionEvent;
  16.     import mx.events.CollectionEventKind;
  17.  
  18.     import org.as3commons.lang.DateUtils;
  19.  
  20.     import spark.components.DataGroup;
  21.     import spark.components.ResizeMode;
  22.     import spark.formatters.DateTimeFormatter;
  23.     import spark.layouts.HorizontalLayout;
  24.  
  25.     // jjh - event metadata
  26.     public class DateAxis extends DataGroup implements IList {
  27.  
  28.         public static const RENDERER_WIDTH:int = 30;
  29.         /**
  30.          * MajorTick Days
  31.          */
  32.         public static const DAYS:String = "days";
  33.         /**
  34.          * Major Tick Months
  35.          */
  36.         public static const MONTHS:String = "months";
  37.  
  38.         /**
  39.          * Major Ticks weeks
  40.          */
  41.         public static const WEEKS:String = "weeks"
  42.         private static const DEBUG:Boolean = GanttConfig.DEBUG;
  43.  
  44.  
  45.         private static const GAP:int = 0;
  46.  
  47.  
  48.         private static const PADDING_LEFT:Number = 8;
  49.         private var logger:GanttLogger = GanttLogger.get();
  50.  
  51.         /**
  52.          *
  53.          *
  54.          */
  55.         public function DateAxis() {
  56.             super();
  57.             dateFormatter = new DateTimeFormatter()
  58.             dateFormatter.dateTimePattern = "MMM. dd";
  59.  
  60.             // set the dataGroup dataProvider to this(DateAxis) instance
  61.             // since the DateAxis implements IList we can do this
  62.             // and supply working logic for getItemIndex and any other
  63.             // IList methods we may need for an "virtual" dataProvider
  64.             dataProvider = this;
  65.             itemRenderer = new ClassFactory(DateAxisRenderer);
  66.  
  67.             var layout:HorizontalLayout = new HorizontalLayout();
  68.             layout.paddingLeft = PADDING_LEFT;
  69.             layout.columnWidth = _tickWidth;
  70.             layout.variableColumnWidth = false;
  71.             layout.gap = _gap;
  72.             layout.useVirtualLayout = true;
  73.             minWidth = 600;
  74.  
  75.             this.layout = layout;
  76.             this.clipAndEnableScrolling = true;
  77.         }
  78.  
  79.         public function get dateTimePattern():String {
  80.             return dateFormatter.dateTimePattern;
  81.         }
  82.  
  83.         /**
  84.          * Set the date pattern to use when formatting the dateAxis labels
  85.          * @param value Format to use
  86.          * @see spark.formatters.DateTimeFormatter
  87.          *
  88.          */
  89.         public function set dateTimePattern(value:String):void {
  90.             if (value != dateFormatter.dateTimePattern) {
  91.                 dateFormatter.dateTimePattern = value
  92.                 invalidateDisplayList();
  93.             }
  94.         }
  95.  
  96.         private var _endDate:Number
  97.  
  98.         /**
  99.          * Returns the axis end date
  100.          * @return
  101.          *
  102.          */
  103.         public function get endDate():Number {
  104.             return _endDate;
  105.         }
  106.  
  107.         /**
  108.          * Sets the axis end date
  109.          * @param value Date since epoch
  110.          *
  111.          */
  112.         public function set endDate(value:Number):void {
  113.             if (_endDate != value) {
  114.                 _endDate = value;
  115.  
  116.                 invalidateCache("endDate");
  117.  
  118.             }
  119.         }
  120.  
  121.         private var _gap:Number = GAP;
  122.  
  123.         /**
  124.          * Returns the gap between each tick
  125.          * @return
  126.          *
  127.          */
  128.         public function get gap():Number {
  129.             return _gap;
  130.         }
  131.  
  132.         /**
  133.          * Sets the gap between each gap
  134.          * @param value
  135.          *
  136.          */
  137.         public function set gap(value:Number):void {
  138.             if (value != _gap) {
  139.                 _gap = value;
  140.  
  141.             }
  142.         }
  143.         private var _hourInterval:int = 12;
  144.  
  145.  
  146.         private var dataProviderChanged:Boolean
  147.  
  148.         /**
  149.          * Return the hour interval
  150.          * @return
  151.          *
  152.          */
  153.         public function get hourInterval():int {
  154.             return _hourInterval;
  155.         }
  156.  
  157.         /**
  158.          * Sets the hour interval
  159.          * @param value A interval of 8,12 or 24
  160.          * @default 12
  161.          *
  162.          */
  163.         public function set hourInterval(value:int):void {
  164.             if (value != _hourInterval) {
  165.                 _hourInterval = value;
  166.                 dataProviderChanged = true;
  167.                 invalidateCache();
  168.             }
  169.  
  170.         }
  171.  
  172.         /**
  173.          *
  174.          *  @inheritDoc
  175.          *
  176.          */
  177.         public function get length():int {
  178.  
  179.             return _totalTicks;
  180.         }
  181.  
  182.         private var _majorTickUnits:String = WEEKS;
  183.  
  184.         /**
  185.          * Returns the units used for the major ticks
  186.          * @return
  187.          *
  188.          */
  189.         public function get majorTickUnits():String {
  190.             return _majorTickUnits;
  191.         }
  192.  
  193.         /**
  194.          * Sets the major tick units
  195.          * @param value
  196.          *
  197.          */
  198.  
  199.         public function set majorTickUnits(value:String):void {
  200.             if (_majorTickUnits != value) {
  201.                 _majorTickUnits = value;
  202.                 dataProviderChanged = true;
  203.                 invalidateCache("majorTickUnits");
  204.             }
  205.         }
  206.  
  207.         private var _showMinorTicks:Boolean = true;
  208.  
  209.         /**
  210.          * Wether or not we are showing the minor tick parts
  211.          * @return
  212.          *
  213.          */
  214.         public function get showMinorTicks():Boolean {
  215.             return _showMinorTicks;
  216.         }
  217.  
  218.         /**
  219.          * Wether or not to show minor ticks when drawing
  220.          * @param value To show minor ticks or not
  221.          *
  222.          */
  223.         public function set showMinorTicks(value:Boolean):void {
  224.             if (_showMinorTicks != value) {
  225.                 _showMinorTicks = value
  226.                 invalidateDisplayList();
  227.             }
  228.         }
  229.         private var _startDate:Number
  230.  
  231.         /**
  232.          * Returns the axis start date
  233.          * @return
  234.          *
  235.          */
  236.         public function get startDate():Number {
  237.             return _startDate;
  238.         }
  239.  
  240.  
  241.         public function get axisStartDate():Number {
  242.             return actualStartDate.time;
  243.         }
  244.  
  245.         /**
  246.          * Sets the start date of the axis
  247.          * @param value Start date since epoch
  248.          *
  249.          */
  250.         public function set startDate(value:Number):void {
  251.             if (_startDate != value) {
  252.                 _startDate = value;
  253.  
  254.                 invalidateCache("startDate");
  255.  
  256.  
  257.             }
  258.         }
  259.         private var _tickWidth:Number = RENDERER_WIDTH;
  260.  
  261.         /**
  262.          * Returns the width of the tick
  263.          * @return
  264.          *
  265.          */
  266.         public function get tickWidth():Number {
  267.             return _tickWidth;
  268.         }
  269.  
  270.         /**
  271.          * Set the tick width
  272.          * @param value
  273.          *
  274.          */
  275.         public function set tickWidth(value:Number):void {
  276.             if (value != tickWidth) {
  277.                 _tickWidth = value;
  278.             }
  279.  
  280.         }
  281.         private var _timeZoneOffset:Number = localTimeZoneOffset;
  282.  
  283.  
  284.  
  285.  
  286.  
  287.  
  288.         private var _weekInterval:int = 5;
  289.  
  290.         /**
  291.          * Retuns the week interval
  292.          * @return
  293.          *
  294.          */
  295.         public function get weekInterval():int {
  296.             return _weekInterval;
  297.         }
  298.  
  299.         [Inspectable(category = "Other", enumeration = "5,7", defaultValue = "5")]
  300.         /**
  301.          * Sets the week interval
  302.          * @param value Days in a week to show 5 or 7
  303.          * @default 5
  304.          *
  305.          */
  306.         public function set weekInterval(value:int):void {
  307.             if (value != _weekInterval) {
  308.                 _weekInterval = value;
  309.                 dataProviderChanged = true;
  310.                 invalidateCache();
  311.             }
  312.         }
  313.  
  314.         /**
  315.          *
  316.          * @inheritDoc
  317.          *
  318.          */
  319.         override public function set width(value:Number):void {
  320.             if (width != value) {
  321.  
  322.                 invalidateCache()
  323.  
  324.  
  325.                 super.width = value;
  326.             }
  327.  
  328.         }
  329.  
  330.  
  331.  
  332.         private var _totalTicks:int
  333.  
  334.         private var actualEndDate:Date = new Date();
  335.  
  336.  
  337.         private var actualStartDate:Date = new Date();
  338.  
  339.         private var adjustedEndDate:Date
  340.  
  341.         private var adjustedStartDate:Date
  342.         private var adjustedStartDateEpoch:Number
  343.  
  344.         private var adjustedEndDateEpoch:Number
  345.  
  346.  
  347.         private var cacheIsDirty:Boolean
  348.         /**
  349.          * Cached date objected used  for caculation
  350.          * */
  351.         private var cachedDate:Date = new Date();
  352.  
  353.  
  354.  
  355.  
  356.         //private var dateCache:Vector.<Number> = new Vector.<Number>();
  357.         // TODO : switch back to an optomized vector
  358.         private var dateCache:Object = {};
  359.  
  360.         private var dateFormatter:DateTimeFormatter
  361.  
  362.  
  363.         private var inCommitPropertiesAsDirty:Boolean
  364.  
  365.  
  366.         private var localTimeZoneOffset:Number = new Date().timezoneOffset;
  367.  
  368.         private var minorSingleUnitMilliseconds:Number
  369.  
  370.         private var minorTickInterval:int
  371.  
  372.  
  373.         private var majorTickValue:Number
  374.         private var minorTickValue:Number
  375.  
  376.         /**
  377.          *
  378.          *  @inheritDoc
  379.          *
  380.          */
  381.         public function addItem(item:Object):void {
  382.  
  383.  
  384.         }
  385.  
  386.         /**
  387.          *
  388.          * @inheritDoc
  389.          *
  390.          */
  391.         public function addItemAt(item:Object, index:int):void {
  392.  
  393.  
  394.         }
  395.  
  396.         public function containsDate(date:Number):Boolean {
  397.  
  398.             return date >= adjustedStartDateEpoch && date <= adjustedEndDateEpoch;
  399.         }
  400.  
  401.         /**
  402.          * Formats the date
  403.          * @param value Can be an Number or Date object
  404.          * @return
  405.          *
  406.          */
  407.         public function formatDate(value:Object):String {
  408.  
  409.             // jjh - should talk about how to handle the date format since only some formats will work for
  410.             // the major/minor tick settings. Might want to make this a non-settable, compile-time thing.
  411.  
  412.             // jjh - also, need to see how DateTimeFormatter handles localization.
  413.             return dateFormatter.format(value);
  414.         }
  415.  
  416.         /**
  417.          * Returns the date found at a given index
  418.          * @param index Zero based index
  419.          * @return Date in epoch value
  420.          *
  421.          */
  422.         public function getDateAt(index:Number):Number {
  423.             return calculateDateByIndex(index);
  424.  
  425.  
  426.         }
  427.  
  428.         /**
  429.          * Returns the date denoted by the change, if 2 is passed, then the return value
  430.          * will be 2 dates after the passed <code>date</code>, if -2 is passed then the return
  431.          * value will be 2 days before the passed <code>date</code>
  432.          * @param date The based date
  433.          * @param change Change factor
  434.          * @param snap snapping type
  435.          * @param includeDifference If set to false the hours,seconds,milliseconds and minutes
  436.          * will not be carried over to the computed date, thus using what caculateDateByIndex rounding
  437.          * which defaults to an actual tick mark.
  438.          * @return
  439.          *
  440.          */
  441.         public function getDateBeforeOrAfter(date:Number, change:int, snap:String = "snapDown"
  442.                                              , includeDifference:Boolean = true):Number {
  443.             var index:int = getDateIndex(date, snap)
  444.             index += change;
  445.             if (index < 0)
  446.                 index = 0;
  447.             var current:Date = new Date(date);
  448.             var result:Date = new Date(calculateDateByIndex(index, false, true));
  449.             if (includeDifference) {
  450.                 result.hours = current.hours;
  451.                 result.seconds = current.seconds;
  452.                 result.milliseconds = current.milliseconds;
  453.                 result.minutes = current.minutes;
  454.             }
  455.             return result.time;
  456.         }
  457.  
  458.         /**
  459.          * Returns the milliseconds difference between 1 tick
  460.          * @return
  461.          *
  462.          */
  463.  
  464.         public function get singleTickDifference():int {
  465.             return minorSingleUnitMilliseconds;
  466.         }
  467.  
  468.  
  469.         /**
  470.          * Returns the date value from a giving X
  471.          * @param x The x value to evaluate
  472.          * @param snap
  473.          * @param calculateAhead
  474.          * @return Returns the date value for the x position passed, if caculateAhead is false then NaN is
  475.          * returned if the date index isn't in the current endDate - startDate range
  476.          *
  477.          */
  478.         public function getDateFromX(x:Number, snap:String = "snapDown", calculateAhead:Boolean = false):Number {
  479.  
  480.             var index:Number = getXIndex(x, snap, calculateAhead);
  481.  
  482.  
  483.             var date:Number
  484.                 = (index < 0 || (index > length - 1 && !calculateAhead)) ? NaN : calculateDateByIndex(index
  485.                                                                                                       , snap == Snapping.SNAP_NONE ? false : true);
  486.  
  487.             return date;
  488.  
  489.         }
  490.  
  491.         /**
  492.          * Returns the index of the date based on the snapping provided
  493.          * @param date Date to find index of
  494.          * @param snap Snapping rule
  495.          * @return
  496.          *
  497.          */
  498.         public function getDateIndex(date:Number, snap:String = "snapDown"):Number {
  499.             return applySnap(itemIndex(date), snap);
  500.  
  501.  
  502.  
  503.         }
  504.  
  505.  
  506.  
  507.         /**
  508.          *
  509.          *  @inheritDoc
  510.          *
  511.          */
  512.         public function getItemAt(index:int, prefetch:int = 0):Object {
  513.  
  514.             return inCommitPropertiesAsDirty ? null : calculateDateByIndex(index);
  515.         }
  516.  
  517.         /**
  518.          *
  519.          *  @inheritDoc
  520.          *
  521.          */
  522.         public function getItemIndex(item:Object):int {
  523.  
  524.  
  525.             return applySnap(itemIndex(item));
  526.  
  527.         }
  528.  
  529.         /**
  530.          * Return the x position based by the date
  531.          * @param date Can either be a Number or an Date object
  532.          * @return
  533.          *
  534.          */
  535.         public function getXFromDate(date:Object, snap:String = "snapDown"):Number {
  536.             var index:Number = applySnap(itemIndex(date), snap);
  537.  
  538.  
  539.  
  540.             return PADDING_LEFT + (RENDERER_WIDTH * index) + (RENDERER_WIDTH >> 1);
  541.  
  542.         }
  543.  
  544.         public static var MONTHS_DAYS:Array = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];
  545.  
  546.         private var cachedMonthFirstMondays:Object = {}
  547.  
  548.         /**
  549.          * Checks to see if the passed date value is a major or minor tick
  550.          * @param value Can be either an Date or Number object
  551.          * @return
  552.          *
  553.          */
  554.         public function isMajorTick(date:Number):Boolean {
  555.  
  556.  
  557.             cachedDate.setTime(date);
  558.  
  559.  
  560.             var matches:Boolean = true;
  561.             switch (majorTickUnits) {
  562.                 case WEEKS:
  563.                     // sunday
  564.                     return minorTickInterval == 7 ? cachedDate.day == 0 : cachedDate.day == 1;
  565.                     break;
  566.                 case DAYS:
  567.                     // 8 am, 8pm
  568.                     // 9 am
  569.                     if ((minorTickInterval == 12 && cachedDate.hours == 8)
  570.                         || (minorTickInterval == 8 && cachedDate.hours == 9)
  571.                         || (minorTickInterval == 24 && cachedDate.hours == 8)) {
  572.  
  573.  
  574.                         return cachedDate.seconds == 0 && cachedDate.minutes == 0 && cachedDate.milliseconds == 0;
  575.  
  576.                     }
  577.  
  578.                     break;
  579.                 case MONTHS:
  580.                     var cacheKey:String = cachedDate.fullYear + "_" + cachedDate.month;
  581.                     logger.debug(this, "isMajorTick {0}", cachedDate);
  582.                     var firstMondayDate:Number = cachedMonthFirstMondays[cacheKey]
  583.                     if (isNaN(firstMondayDate)) {
  584.  
  585.  
  586.                         var firstMonday:Date = new Date(cachedDate.fullYear, cachedDate.month, 1);
  587.                         if (firstMonday.day != 1) {
  588.                             firstMonday.dateUTC += firstMonday.day == 0 ? 1 : (7 - firstMonday.day) + 1;
  589.  
  590.                         }
  591.                         firstMondayDate = firstMonday.date;
  592.                         cachedMonthFirstMondays[cacheKey] = firstMondayDate;
  593.                     }
  594.  
  595.  
  596.  
  597.                     return firstMondayDate == cachedDate.date;
  598.  
  599.  
  600.  
  601.  
  602.  
  603.             }
  604.             return false;
  605.         }
  606.  
  607.         /**
  608.          *
  609.          *  @inheritDoc
  610.          *
  611.          */
  612.         public function itemUpdated(item:Object, property:Object = null, oldValue:Object = null
  613.                                     , newValue:Object = null):void {
  614.  
  615.  
  616.         }
  617.  
  618.  
  619.         /**
  620.          *
  621.          * @inheritDoc
  622.          *
  623.          */
  624.         public function removeAll():void {
  625.  
  626.  
  627.         }
  628.  
  629.         /**
  630.          *
  631.          *  @inheritDoc
  632.          *
  633.          */
  634.         public function removeItemAt(index:int):Object {
  635.  
  636.             return null;
  637.         }
  638.  
  639.         /**
  640.          *
  641.          *  @inheritDoc
  642.          *
  643.          */
  644.         public function setItemAt(item:Object, index:int):Object {
  645.  
  646.             return null;
  647.         }
  648.  
  649.         /**
  650.          *
  651.          *  @inheritDoc
  652.          *
  653.          */
  654.         public function toArray():Array {
  655.  
  656.             return null;
  657.         }
  658.  
  659.  
  660.  
  661.  
  662.         override protected function commitProperties():void {
  663.  
  664.  
  665.             if (cacheIsDirty) {
  666.                 ensureMinorTickInterval();
  667.  
  668.                 resizeCache();
  669.                 cacheIsDirty = false;
  670.                 inCommitPropertiesAsDirty = true;
  671.  
  672.             }
  673.  
  674.  
  675.  
  676.             super.commitProperties();
  677.  
  678.  
  679.             inCommitPropertiesAsDirty = false;
  680.         }
  681.  
  682.  
  683.  
  684.         protected function itemIndex(item:Object):Number {
  685.  
  686.             var dateValue:Number = Number(item);
  687.             if (isNaN(dateValue))
  688.                 return -1;
  689.  
  690.  
  691.  
  692.             dateValue = offsetDate(dateValue);
  693.  
  694.             var index:Number;
  695.  
  696.             var len:int = length;
  697.             const cache:Object = dateCache;
  698.             var date:Number
  699.  
  700.             var start:Number
  701.             var end:Number
  702.             var i:int
  703.             do {
  704.                 date = cache[i];
  705.                 if (!date) {
  706.                     date = calculateDateByIndex(i);
  707.                 }
  708.                 if (date > dateValue) {
  709.                     if (i == 0)
  710.                         i += 1;
  711.                     start = cache[i - 1];
  712.                     end = date;
  713.                     index = i - 1;
  714.  
  715.                     break;
  716.                 }
  717.                 i++;
  718.  
  719.             } while (true);
  720.             if (dateValue == start)
  721.                 return index;
  722.  
  723.             cachedDate.setTime(dateValue);
  724.  
  725.  
  726.             // caculate themillisecond difference
  727.             var mills:Number = cachedDate.seconds * DateUtils.MILLIS_PER_SECOND + cachedDate.milliseconds
  728.             if (majorTickUnits != DAYS)
  729.                 mills += cachedDate.hours * DateUtils.MILLIS_PER_HOUR;
  730.  
  731.            
  732.             return index + (mills / minorSingleUnitMilliseconds);
  733.  
  734.  
  735.             return index;
  736.         }
  737.  
  738.  
  739.  
  740.         override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
  741.             var oldTotalTicks:int = length;
  742.             if (oldTotalTicks) {
  743.                 // check if we need to draw more ticks from a resize
  744.                 var newTotalTicks:int = caculateTotalTicks(adjustedStartDateEpoch, caculateMaxEndDate())
  745.  
  746.  
  747.                 if (newTotalTicks > oldTotalTicks) {
  748.                     dispatchDataProviderChangeEvent(oldTotalTicks, newTotalTicks);
  749.  
  750.  
  751.                 }
  752.  
  753.             }
  754.  
  755.             super.updateDisplayList(unscaledWidth, unscaledHeight);
  756.  
  757.  
  758.  
  759.         }
  760.  
  761.         private function handleDaylightSavings(oldEpoch:Number, newEpoch:Number):Number {
  762.  
  763.             cachedDate.setTime(oldEpoch);
  764.             var result:Date = new Date(newEpoch);
  765.             var originalHours:int = cachedDate.hours;
  766.             if (originalHours != result.hours) {
  767.  
  768.                 if (result.hours > 0) { // spring back
  769.                     result.hoursUTC -= result.hours;
  770.                 } else { // fall back
  771.                     result.hoursUTC += (24 - (result.hours - originalHours))
  772.                 }
  773.             }
  774.             var originalMinutes:int = cachedDate.minutes;
  775.             if (originalMinutes != result.minutes)
  776.                 result.minutesUTC -= (result.minutes - originalMinutes);
  777.             /*var originalOffset:int = cachedDate.getTimezoneOffset()
  778.             if (originalOffset != result.getTimezoneOffset())
  779.                 result.minutesUTC -= (result.getTimezoneOffset() - originalOffset);*/
  780.  
  781.             return result.time
  782.         }
  783.  
  784.         private function addToDateInContext(lastComputedIndex:int, amount:Number, withOffset:Boolean = true):Number {
  785.  
  786.             lastComputedIndex = lastComputedIndex < 0 ? 0 : lastComputedIndex;
  787.             var lastComputedDate:Number = dateCache[lastComputedIndex];
  788.             //lastComputedDate = offsetDate(lastComputedDate);
  789.             var property:String
  790.             var interval:int;
  791.             var checkForDST:Boolean = true;
  792.  
  793.  
  794.  
  795.             switch (_majorTickUnits) {
  796.                 case WEEKS:
  797.                     property = "dateUTC";
  798.                     interval = 1;
  799.                     break;
  800.                 case DAYS:
  801.  
  802.                     property = "hoursUTC";
  803.                     checkForDST = false;
  804.                     interval = 1;
  805.                     break;
  806.                 case MONTHS:
  807.                     property = "dateUTC";
  808.                     interval = 7;
  809.                     break;
  810.             }
  811.  
  812.             // do on the fly computing, this happens when
  813.             // we resize the viewing range and the virtualLayout only picks
  814.             // up the items in view
  815.             var cacheLength:int = length;
  816.  
  817.             var cacheIndex:int = lastComputedIndex;
  818.             var oldDay:int
  819.             for (var i:int; i < amount; i++) {
  820.  
  821.                 cachedDate.setTime(lastComputedDate);
  822.  
  823.  
  824.                 oldDay = cachedDate.date;
  825.  
  826.  
  827.  
  828.  
  829.                 cachedDate[property] += interval;
  830.  
  831.                 if (withOffset) {
  832.                     if (checkForDST) {
  833.                         lastComputedDate = handleDaylightSavings(lastComputedDate, offsetDate(cachedDate.time));
  834.                     } else {
  835.                         lastComputedDate = offsetDate(cachedDate.time);
  836.                     }
  837.                 } else if (checkForDST) {
  838.                     lastComputedDate = handleDaylightSavings(lastComputedDate, cachedDate.time);
  839.                 } else {
  840.                     lastComputedDate = cachedDate.time;
  841.                 }
  842.  
  843.  
  844.                 cacheIndex += 1;
  845.  
  846.                 if (withOffset && !cachedDate[cacheIndex]) {
  847.                     dateCache[cacheIndex] = lastComputedDate;
  848.                     /*if(cacheIndex+1 >dateCache.length)
  849.                         dateCache.length = _totalTicks=cacheIndex*/
  850.                 }
  851.             }
  852.  
  853.             return lastComputedDate;
  854.  
  855.  
  856.         }
  857.  
  858.  
  859.  
  860.         private function caculateMaxEndDate():Number {
  861.             var maxWidthEndDate:Number = getDateFromX(width, Snapping.SNAP_UP, true);
  862.             actualEndDate.setTime(maxWidthEndDate > _endDate ? maxWidthEndDate : _endDate);
  863.  
  864.  
  865.             if (actualEndDate.hours != 0) {
  866.                 adjustedEndDate = DateUtils.getEndOfDay(DateUtils.addDays(actualEndDate, 1));
  867.  
  868.             } else {
  869.                 adjustedEndDate = DateUtils.getEndOfDay(actualEndDate);
  870.             }
  871.  
  872.             return adjustedEndDate.time;
  873.         }
  874.  
  875.         private function caculateTotalTicks(start:Number, end:Number):int {
  876.             var totalTime:Number = (end - start);
  877.  
  878.  
  879.             return Math.ceil((totalTime / majorTickValue) * minorTickValue);
  880.         }
  881.  
  882.  
  883.  
  884.         /**
  885.          * The main function of the DateAxis, this function is called upon many other functions
  886.          * @param index The index to caculate
  887.          * @param snap The snapping rule
  888.          * @param caculateAhead Should we allow to caculate ahead
  889.          * @param withOffset When set to true we will call the offsetDate method to apply any
  890.          *  offet rules
  891.          * @return
  892.          *
  893.          */
  894.         private function calculateDateByIndex(index:Number, snap:Boolean = true, caculateAhead:Boolean = true
  895.                                               , withOffset:Boolean = true):Number {
  896.  
  897.  
  898.             const clampedIndex:int = int(index);
  899.             const inRange:Boolean = clampedIndex >= 0 && clampedIndex < length;
  900.  
  901.             if (inRange && snap && dateCache[clampedIndex]) {
  902.  
  903.                 return dateCache[clampedIndex];
  904.             }
  905.  
  906.             var date:Number
  907.  
  908.  
  909.             var maxCached:int = length;
  910.             var lastComputedIndex:int;
  911.  
  912.  
  913.             // try to find the last computed index so we dont have to compute from the start
  914.             //in most cases this is index-1, but allows us to compute ahead by an x factor
  915.             for (lastComputedIndex = clampedIndex - 1; lastComputedIndex > 0; lastComputedIndex--) {
  916.                 if (lastComputedIndex < maxCached && dateCache[lastComputedIndex]) {
  917.                     break;
  918.                 }
  919.             }
  920.  
  921.             if (lastComputedIndex == -1)
  922.                 lastComputedIndex = 0;
  923.  
  924.             var indexDifference:Number = index - lastComputedIndex;
  925.  
  926.  
  927.             var multipler:int
  928.             var remainder:Number
  929.             var clampedDate:Number
  930.             if (snap) {
  931.  
  932.  
  933.                 clampedDate = date = addToDateInContext(lastComputedIndex, indexDifference)
  934.  
  935.  
  936.  
  937.             } else {
  938.                 // snap since we can have index difference of .<value>
  939.                 multipler = int(indexDifference);
  940.  
  941.                 remainder = indexDifference - multipler;
  942.  
  943.  
  944.  
  945.                 clampedDate = date = addToDateInContext(lastComputedIndex, multipler, withOffset)
  946.  
  947.  
  948.                 date += (minorSingleUnitMilliseconds * remainder);
  949.  
  950.             }
  951.  
  952.  
  953.             return date;
  954.         }
  955.  
  956.  
  957.         private function ensureMinorTickInterval():void {
  958.  
  959.  
  960.             switch (_majorTickUnits) {
  961.                 case WEEKS:
  962.                     switch (_weekInterval) {
  963.                         case 5:
  964.                         case 7:
  965.                             break;
  966.                         default:
  967.                             weekInterval = 5;
  968.                     }
  969.  
  970.                     break;
  971.                 case DAYS:
  972.                     switch (_hourInterval) {
  973.                         case 8:
  974.                         case 12:
  975.                         case 24:
  976.  
  977.                             break;
  978.                         default:
  979.                             hourInterval = 24;
  980.                     }
  981.             }
  982.  
  983.  
  984.         }
  985.  
  986.         private function applySnap(value:Number, snap:String = "snapDown"):Number {
  987.             if (snap == Snapping.SNAP_DOWN) {
  988.                 value = Math.floor(value);
  989.             } else if (snap == Snapping.SNAP_UP) {
  990.                 value = Math.ceil(value)
  991.             } else if (snap == Snapping.SNAP_CLOSEST) {
  992.                 value = Math.round(value);
  993.             }
  994.             return value;
  995.  
  996.         }
  997.  
  998.         private function getXIndex(x:Number, snap:String = "snapDown", calculateAhead:Boolean = false):Number {
  999.  
  1000.  
  1001.  
  1002.             // ensure that the index is witin the range        
  1003.             var index:Number = ((x - PADDING_LEFT) - (RENDERER_WIDTH >> 1)) / RENDERER_WIDTH;
  1004.             if (index < 0)
  1005.                 index = 0;
  1006.  
  1007.             return applySnap(index, snap);
  1008.  
  1009.  
  1010.         }
  1011.  
  1012.  
  1013.         private function invalidateCache(causedBy:String = null):void {
  1014.             cacheIsDirty = true;
  1015.             invalidateProperties();
  1016.             invalidateSize();
  1017.             invalidateDisplayList();
  1018.             if (causedBy) {
  1019.                 // majorTick, startDate, endDate
  1020.                 var eventType:String = causedBy + "Changed";
  1021.                 if (hasEventListener(eventType))
  1022.                     dispatchEvent(new Event(eventType))
  1023.             }
  1024.             dispatchEvent(new Event("dateAxisInvalidated"));
  1025.         }
  1026.  
  1027.  
  1028.         private function offsetDate(date:Number, resizing:Boolean = false):Number {
  1029.  
  1030.  
  1031.             cachedDate.setTime(date);
  1032.  
  1033.  
  1034.             var oldDate:Number = date;
  1035.             var offsetApplied:Boolean
  1036.  
  1037.  
  1038.             if (majorTickUnits == WEEKS && minorTickInterval == 5) {
  1039.  
  1040.                 var oldDay:int = cachedDate.date;
  1041.                 if (cachedDate.day == 0) {
  1042.                     offsetApplied = true;
  1043.  
  1044.                     // sunday
  1045.                     cachedDate.dateUTC += 1;
  1046.                     date = cachedDate.time;
  1047.  
  1048.                 } else if (cachedDate.day == 6) {
  1049.                     offsetApplied = true;
  1050.                     // saturday
  1051.                     cachedDate.dateUTC += 2
  1052.                     date = cachedDate.time;
  1053.                 }
  1054.                 if (offsetApplied) {
  1055.                     while (cachedDate.day != 1) {
  1056.                         cachedDate.dateUTC += 1;
  1057.                         cachedDate.hours = 0;
  1058.                     }
  1059.                     date = cachedDate.time;
  1060.  
  1061.  
  1062.                 }
  1063.  
  1064.  
  1065.  
  1066.             }
  1067.             if (majorTickUnits == DAYS) {
  1068.                 if (minorTickInterval == 8) {
  1069.                     if (cachedDate.hours > 17) { // later then 5pm
  1070.                         // if the date is the startDate then we need apply a special case, so we have some room to include the real start date
  1071.                         cachedDate.dateUTC += resizing ? -1 : 1;
  1072.                         offsetApplied = true;
  1073.                     } else if (cachedDate.hours < 9) {
  1074.                         offsetApplied = true;
  1075.                     }
  1076.                     if (offsetApplied) {
  1077.                         cachedDate.hours = 9;
  1078.                         cachedDate.milliseconds = 0;
  1079.                         cachedDate.seconds = 0;
  1080.                         cachedDate.minutes = 0;
  1081.                         date = cachedDate.time;
  1082.                     }
  1083.                 }
  1084.                 if (minorTickInterval == 12) {
  1085.                     if (cachedDate.hours > 19) { // later then 8pm go to next day
  1086.                         // if the date is the startDate then we need apply a special case, so we have some room to include the real start date
  1087.                         //
  1088.                         cachedDate.dateUTC += resizing ? -1 : 1;
  1089.                         offsetApplied = true;
  1090.  
  1091.                     } else if (cachedDate.hours < 8) {
  1092.  
  1093.                         offsetApplied = true;
  1094.                     }
  1095.                     if (offsetApplied) {
  1096.                         cachedDate.hours = 8;
  1097.                         cachedDate.milliseconds = 0;
  1098.                         cachedDate.seconds = 0;
  1099.                         cachedDate.minutes = 0;
  1100.                         date = cachedDate.time;
  1101.                     }
  1102.  
  1103.                 }
  1104.             }
  1105.  
  1106.             return date;
  1107.         }
  1108.  
  1109.  
  1110.  
  1111.         private function resizeCache():void {
  1112.  
  1113.  
  1114.             if (isNaN(_startDate) || isNaN(_endDate))
  1115.                 return;
  1116.  
  1117.  
  1118.             actualStartDate.setTime(_startDate);
  1119.             switch (majorTickUnits) {
  1120.                 case WEEKS:
  1121.  
  1122.                     minorSingleUnitMilliseconds = DateUtils.MILLIS_PER_DAY
  1123.                     minorTickValue = 7;
  1124.                     minorTickInterval = _weekInterval; // seven days in a week
  1125.                     actualStartDate.hours = 0;
  1126.                     actualStartDate.milliseconds = 0;
  1127.                     actualStartDate.seconds = 0;
  1128.                     actualStartDate.minutes = 0;
  1129.  
  1130.  
  1131.                     break;
  1132.                 case DAYS:
  1133.                     minorSingleUnitMilliseconds = DateUtils.MILLIS_PER_HOUR;
  1134.                     minorTickValue = 24; // 24 hours in a day
  1135.                     minorTickInterval = _hourInterval;
  1136.                     actualStartDate.setTime(offsetDate(_startDate, true));
  1137.                     actualStartDate.milliseconds = 0;
  1138.                     actualStartDate.minutes = 0;
  1139.                     actualStartDate.seconds = 0;
  1140.  
  1141.  
  1142.  
  1143.                     break;
  1144.                 case MONTHS:
  1145.                     minorSingleUnitMilliseconds = DateUtils.MILLIS_PER_DAY * 7;
  1146.                     minorTickValue = 4 // in most cases 4 weeks in a month
  1147.                     if (actualStartDate.day != 1) {
  1148.                         if (actualStartDate.day > 1) {
  1149.                             actualStartDate.dateUTC -= (actualStartDate.day - 1);
  1150.                         } else if (actualStartDate.day) {
  1151.                             actualStartDate.dateUTC -= 5;
  1152.                         }
  1153.                     }
  1154.                     actualStartDate.hours = 0;
  1155.                     actualStartDate.milliseconds = 0;
  1156.                     actualStartDate.minutes = 0;
  1157.                     actualStartDate.seconds = 0;
  1158.  
  1159.  
  1160.                     break;
  1161.             }
  1162.  
  1163.  
  1164.             cachedMonthFirstMondays = {};
  1165.             dateCache = {};
  1166.  
  1167.             adjustedStartDateEpoch = offsetDate(actualStartDate.time);
  1168.  
  1169.             dateCache[0] = adjustedStartDateEpoch;
  1170.  
  1171.             var oldTotalTicks:int = _totalTicks;
  1172.             _totalTicks = 0;
  1173.  
  1174.  
  1175.             // always ensure that ticks fill up atleast 600pixels
  1176.             var mesureWidth:Number = width < 600 ? 600 : width;
  1177.             var hl:HorizontalLayout = HorizontalLayout(layout);
  1178.             hl.requestedMinColumnCount = Math.round(600 / (RENDERER_WIDTH + GAP));
  1179.             hl.requestedMaxColumnCount = mesureWidth / (RENDERER_WIDTH + GAP)
  1180.  
  1181.  
  1182.             majorTickValue = minorSingleUnitMilliseconds * minorTickValue;
  1183.  
  1184.  
  1185.             var currentTotalTicks:int = caculateTotalTicks(adjustedStartDateEpoch, caculateMaxEndDate())
  1186.             dispatchDataProviderChangeEvent(oldTotalTicks, currentTotalTicks);
  1187.  
  1188.  
  1189.         }
  1190.  
  1191.         private function dispatchDataProviderChangeEvent(old:int, current:int):void {
  1192.             var event:CollectionEvent = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
  1193.             if (dataProviderChanged) {
  1194.                 event.kind = CollectionEventKind.REFRESH;
  1195.                 dataProviderChanged = false;
  1196.             } else {
  1197.                 if (old > current) {
  1198.                     event.kind = CollectionEventKind.REMOVE;
  1199.                     event.items = new Array(old - current);
  1200.                     event.location = current;
  1201.                 } else if (old < current) {
  1202.                     event.kind = CollectionEventKind.ADD;
  1203.                     event.items = new Array(current - old);
  1204.                     event.location = old;
  1205.                 }
  1206.             }
  1207.  
  1208.  
  1209.             if (event.kind) {
  1210.  
  1211.  
  1212.  
  1213.  
  1214.                 dispatchEvent(event);
  1215.             }
  1216.             _totalTicks = current;
  1217.             dateCache.length = current;
  1218.  
  1219.         }
  1220.     }
  1221. }
Add Comment
Please, Sign In to add comment