📄 calendardisplay.as
字号:
package qs.controls
{
import flash.display.Shape;
import flash.display.DisplayObject;
import flash.events.Event;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import flash.utils.Dictionary;
import mx.containers.Canvas;
import mx.controls.Button;
import mx.controls.Label;
import mx.controls.VScrollBar;
import mx.core.ClassFactory;
import mx.core.Container;
import mx.core.EdgeMetrics;
import mx.core.IDataRenderer;
import mx.core.UIComponent;
import mx.events.ScrollEvent;
import qs.context.ContextData;
import qs.context.ContextManager;
import qs.controls.calendarDisplayClasses.CalendarDay;
import qs.controls.calendarDisplayClasses.CalendarEventRenderer;
import qs.controls.calendarDisplayClasses.CalendarHeader;
import qs.controls.calendarDisplayClasses.ICalendarEventRenderer;
import qs.calendar.CalendarSet;
import qs.calendar.CalendarEvent;
import qs.utils.DateRange;
import qs.utils.DateUtils;
import qs.utils.InstanceCache;
import qs.utils.ReservationAgent;
import qs.controls.calendarDisplayClasses.CalendarHours;
import flash.events.MouseEvent;
import flash.geom.Point;
import qs.controls.calendarDisplayClasses.CalendarDisplayEvent;
import flash.utils.getTimer;
import mx.skins.RectangularBorder;
import mx.skins.halo.HaloBorder;
import mx.core.IFlexDisplayObject;
import qs.controls.calendarDisplayClasses.CalendarAllDayRegion;
import flash.filters.DropShadowFilter;
import mx.core.DragSource;
import mx.managers.DragManager;
import mx.events.DragEvent;
import qs.utils.TimeZone;
[Event("change")]
[Event(name="displayModeChange", type="qs.controls.calendarDisplayClasses.CalendarDisplayEvent")]
[Event(name="headerClick",type="qs.controls.calendarDisplayClasses.CalendarDisplayEvent")]
[Event(name="dayClick",type="qs.controls.calendarDisplayClasses.CalendarDisplayEvent")]
[Event(name="itemClick",type="qs.controls.calendarDisplayClasses.CalendarDisplayEvent")]
[Style(name="hourDividerColor", type="uint", format="Color", inherit="no")]
[Style(name="hourDividerThickness", type="Number", format="Length", inherit="no")]
[Style(name="allDayDividerColor", type="uint", format="Color", inherit="no")]
[Style(name="allDayDividerThickness", type="Number", format="Length", inherit="no")]
[Style(name="allDayColor", type="uint", format="Color", inherit="no")]
[Style(name="hourColor", type="uint", format="Color", inherit="no")]
[Style(name="hourThickness", type="Number", format="Length", inherit="no")]
[Style(name="hourBackgroundColor", type="uint", format="Color", inherit="no")]
[Style(name="hourStyleName", type="String", inherit="no")]
[Style(name="dayStyleName", type="String", inherit="no")]
[Style(name="dayHeaderStyleName", type="String", inherit="no")]
[Style(name="eventStyleName", type="String", inherit="no")]
public class CalendarDisplay extends UIComponent
{
private const ROW_LENGTH:int = 7;
private const EVENT_INSET:int = 3;
private const MIN_HOUR_HEIGHT:Number = 40;
private var _animator:LayoutAnimator;
private var _dayCache:InstanceCache;
private var _headerCache:InstanceCache;
private var _headerLayer:UIComponent;
private var _dayLayer:UIComponent;
private var _eventLayer:UIComponent;
private var _allDayEventLayer:UIComponent;
private var _allDayEventBorder:IFlexDisplayObject;
private var _eventMask:Shape;
private var _hourGrid:CalendarHours;
private var _removeAllEventsOnUpdate:Boolean;
private var _currentRange:DateRange;
private var _pendingRange:DateRange;
private var _displayMode:String = "month";
private var _userDisplayMode:String = "month";
private var _pendingDisplayMode:String;
private var _removeAllEventData:Boolean;
private var _animated:Boolean = false;
private var _eventData:Dictionary;
private var _dataProvider:CalendarSet;
private var _allDayAreaHeight:Number;
private var _visibleRange:DateRange;
private var _computedRange:DateRange;
private var _columnLength:int;
private var _rowLength:int;
private var _cellWidth:Number;
private var _cellHeight:Number;
private var _visibleEvents:Array;
private var _hourHeight:Number;
private var _dayAreaHeight:Number;
private var _animateRemovingDays:Boolean = false;
// state for drag operations
private var _dragType:String;
private var _dragEventData:EventData;
private var _dragDownPt:Point;
private var _dragRenderer:UIComponent;
private var _dragOffset:Number;
private var _border:EdgeMetrics = new EdgeMetrics();
private var _scroller:VScrollBar;
private var _scrollHour:Number;
private var _dragFilter:DropShadowFilter = new DropShadowFilter();
private var _tz:TimeZone;
public function CalendarDisplay():void
{
var dt:Date = new Date();
_tz = TimeZone.localTimeZone;
range = new DateRange(_tz.startOfMonth(dt),_tz.endOfMonth(dt));
_animator = new LayoutAnimator();
_animator.layoutFunction = generateLayout;
_animator.animationSpeed = .5;
_dayCache = new InstanceCache();
_dayCache.destroyUnusedInstances = false;
_dayCache.createCallback = dayChildCreated;
_dayCache.assignCallback = InstanceCache.showInstance;
_dayCache.releaseCallback = hideInstance;
_dayCache.destroyCallback = InstanceCache.removeInstance;
_dayCache.factory = new ClassFactory(CalendarDay);
_headerCache = new InstanceCache();
_headerCache.destroyUnusedInstances = false;
_headerCache.createCallback = headerChildCreated;
_headerCache.assignCallback = InstanceCache.showInstance;
_headerCache.releaseCallback = hideInstance;
_headerCache.destroyCallback = InstanceCache.removeInstance;
_headerCache.factory = new ClassFactory(CalendarHeader);
_dayLayer = new UIComponent();
addChild(_dayLayer);
_headerLayer = new UIComponent();
addChild(_headerLayer);
_eventLayer = new UIComponent();
addChild(_eventLayer);
_allDayEventLayer = new UIComponent();
addChild(_allDayEventLayer);
_allDayEventBorder = new CalendarAllDayRegion(this);
_allDayEventLayer.addChild(DisplayObject(_allDayEventBorder));
_eventMask = new Shape();
_eventMask.visible = false;
addChild(_eventMask);
_hourGrid = new CalendarHours(this);
_eventLayer.addChild(_hourGrid);
_hourGrid.alpha = 0;
_scroller = new VScrollBar();
_scroller.addEventListener(ScrollEvent.SCROLL,scrollHandler);
addChild(_scroller);
_scroller.alpha = 0;
_visibleRange = new DateRange();
_eventData = new Dictionary();
dataProvider = null;
addEventListener(DragEvent.DRAG_ENTER,dragEnterHandler);
addEventListener(DragEvent.DRAG_OVER,dragOverHandler);
addEventListener(DragEvent.DRAG_EXIT,dragExitHandler);
addEventListener(DragEvent.DRAG_DROP,dragDropHandler);
}
public function set displayMode(value:String):void
{
_userDisplayMode = value;
_pendingDisplayMode = value;
range = _currentRange;
}
public function get displayMode():String
{
return (_pendingDisplayMode == null)? _displayMode:_pendingDisplayMode;
}
public function set animated(value:Boolean):void
{
_animated = value;
}
public function get animated():Boolean { return _animated; }
[Bindable("change")]
public function get currentDate():Date
{
return range.start;
}
public function set range(value:DateRange):void
{
var dayCount:int = _tz.rangeDaySpan(value);
if(_userDisplayMode == "auto")
{
if(dayCount <= 7)
_pendingDisplayMode = "days";
else
_pendingDisplayMode = "weeks";
dispatchEvent(new CalendarDisplayEvent(CalendarDisplayEvent.DISPLAY_MODE_CHANGE));
}
_pendingRange = value;
// by resetting this to NaN, we'll force the layout to recompute an appropriate hour to
// make sure values are visible.
_scrollHour = NaN;
dispatchEvent(new Event("change"));
var dm:String = (_pendingDisplayMode == null)? _pendingDisplayMode:_displayMode;
_removeAllEventData = (dm == "weeks" || dm == "week" || dm == "month");
invalidateProperties();
}
[Bindable("change")]
public function get range():DateRange
{
var result:DateRange = _computedRange;
var bRecompute:Boolean = false;
var pr:DateRange = _currentRange;
var mode:String = _displayMode;
if(_pendingRange != null)
{
bRecompute = true;
pr = _pendingRange;
}
if(_pendingDisplayMode != null)
{
bRecompute = true;
mode = _pendingDisplayMode;
}
if(bRecompute)
{
var ranges:Object = computeRanges(pr,mode);
result = ranges._computedRange;
}
return result;
}
public function set currentDate(value:Date):void
{
range = new DateRange(value,value);
}
private function hideInstance(child:UIComponent):void
{
if(_animated == false)
child.visible = false;
_animator.releaseTarget(child).animate = _animateRemovingDays;
}
public function set dataProvider(value:CalendarSet):void
{
if(_dataProvider != null)
_dataProvider.removeEventListener("change",eventsChanged);
if(value == null)
value = new CalendarSet();
if(_dataProvider == value)
return;
_dataProvider = value;
if(_dataProvider != null)
_dataProvider.addEventListener("change",eventsChanged);
_removeAllEventData = true;
invalidateProperties();
}
public function get dataProvider():CalendarSet
{
return _dataProvider;
}
private function indexForDate(value:Date):int
{
return Math.floor((value.getTime() - _visibleRange.start.getTime())/DateUtils.MILLI_IN_DAY);
}
private function dateForIndex(index:int):Date
{
var result:Date = new Date(_visibleRange.start.getTime());
result.date = result.date + index;
return result;
}
private function eventsChanged(event:Event):void
{
_removeAllEventData = false;
invalidateProperties();
}
//----------------------------------------------------------------------------------------------------
// Navigation
//----------------------------------------------------------------------------------------------------
public function next():void
{
var r:DateRange = _currentRange.clone();
switch(_userDisplayMode)
{
case "day":
r.start.date += 1;
r.end.date += 1;
break;
case "week":
r.start.date += 7;
r.end.date += 7;
break;
case "auto":
r = _currentRange.clone();
r.start = r.end;
r.start.date += 1;
r.end = new Date(r.start);
r.end.date += _tz.daySpan(_currentRange.start,_currentRange.end)-1;
break;
case "month":
default:
r.start.month++;
r.end.month++;
break;
}
range = r;
}
public function previous():void
{
var r:DateRange = _currentRange.clone();
switch(_userDisplayMode)
{
case "day":
r.start.date -= 1;
r.end.date -= 1;
break;
case "week":
r.start.date -= 7;
r.end.date -= 7;
break;
case "auto":
r = _currentRange.clone();
r.end = r.start;
r.end.date -= 1;
r.start = new Date(r.end);
r.start.date += _tz.daySpan(_currentRange.start,_currentRange.end)-1;
break;
case "month":
default:
r.start.month--;
r.end.month--;
break;
}
range = r;
}
//----------------------------------------------------------------------------------------------------
// Property Management
//----------------------------------------------------------------------------------------------------
override protected function commitProperties():void
{
var prevDM:String = _displayMode;
var prevFirstDate:Date = new Date(_visibleRange.start);
var startIndex:int;
var endIndex:int;
if(_pendingRange != null)
{
_currentRange = _pendingRange;
_pendingRange = null;
}
var oldVisible:DateRange = _visibleRange.clone();
if(_pendingDisplayMode != null)
{
_displayMode = _pendingDisplayMode;
_pendingDisplayMode = null;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -