Componentes.Terceros.DevExp.../internal/x.44/1/ExpressScheduler/Sources/cxScheduler.pas
2009-06-29 12:09:02 +00:00

659 lines
22 KiB
ObjectPascal

{********************************************************************}
{ }
{ Developer Express Visual Component Library }
{ ExpressScheduler }
{ }
{ Copyright (c) 2003-2009 Developer Express Inc. }
{ ALL RIGHTS RESERVED }
{ }
{ The entire contents of this file is protected by U.S. and }
{ International Copyright Laws. Unauthorized reproduction, }
{ reverse-engineering, and distribution of all or any portion of }
{ the code contained in this file is strictly prohibited and may }
{ result in severe civil and criminal penalties and will be }
{ prosecuted to the maximum extent possible under the law. }
{ }
{ RESTRICTIONS }
{ }
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
{ LICENSED TO DISTRIBUTE THE EXPRESSSCHEDULER AND ALL ACCOMPANYING }
{ VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY. }
{ }
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
{ }
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
{ ADDITIONAL RESTRICTIONS. }
{ }
{********************************************************************}
unit cxScheduler;
{$I cxVer.inc}
interface
uses
{$IFDEF DELPHI6} DateUtils, {$ENDIF} cxGraphics, cxDateUtils, cxSchedulerUtils,
cxSchedulerStorage, cxSchedulerCustomControls, cxSchedulerCustomResourceView,
cxSchedulerDayView, cxSchedulerWeekView, cxSchedulerDateNavigator, Classes;
type
{ TcxScheduler }
TcxScheduler = class(TcxCustomScheduler, IUnknown, IcxSchedulerCommonViewItemsPainter)
private
FDateNavigatorEvents: TNotifyEvent;
FIsSelectionValidated: Boolean;
FViewDay: TcxSchedulerDayView;
FViewWeek: TcxSchedulerWeekView;
FViewWeeks: TcxSchedulerWeeksView;
FOnCustomDrawBackground: TcxSchedulerCustomDrawBackgroundEvent;
FOnCustomDrawButton: TcxSchedulerCustomDrawButtonEvent;
FOnCustomDrawContent: TcxSchedulerCustomDrawContentEvent;
FOnCustomDrawDayHeader: TcxSchedulerCustomDrawDayHeaderEvent;
FOnCustomDrawEvent: TcxSchedulerCustomDrawEventEvent;
FOnCustomDrawGroupSeparator: TcxSchedulerCustomDrawGroupSeparatorEvent;
FOnCustomDrawResourceHeader: TcxSchedulerCustomDrawResourceHeaderEvent;
FViewDayEvents: TNotifyEvent;
function GetDateNavigator: TcxSchedulerDateNavigator;
procedure SetDateNavigator(AValue: TcxSchedulerDateNavigator);
procedure SetViewDay(AValue: TcxSchedulerDayView);
procedure SetViewWeek(AValue: TcxSchedulerWeekView);
procedure SetViewWeeks(AValue: TcxSchedulerWeeksView);
protected
// IcxSchedulerCommonViewItemsPainter
procedure DoCustomDrawBackground(
AViewInfo: TcxSchedulerBackgroundCellViewInfo; var ADone: Boolean); virtual;
procedure DoCustomDrawButton(
AViewInfo: TcxSchedulerMoreEventsButtonViewInfo; var ADone: Boolean); virtual;
procedure DoCustomDrawContent(
AViewInfo: TcxSchedulerContentCellViewInfo; var ADone: Boolean); virtual;
procedure DoCustomDrawDayHeader(
AViewInfo: TcxSchedulerDayHeaderCellViewInfo; var ADone: Boolean); virtual;
procedure DoCustomDrawEvent(
AViewInfo: TcxSchedulerEventCellViewInfo; var ADone: Boolean); virtual;
procedure DoCustomDrawGroupSeparator(
AViewInfo: TcxSchedulerGroupSeparatorCellViewInfo; var ADone: Boolean); virtual;
procedure DoCustomDrawResourceHeader(
AViewInfo: TcxSchedulerHeaderCellViewInfo; var ADone: Boolean); virtual;
// layout
function GetProperties(AProperties: TStrings): Boolean; override;
procedure GetPropertyValue(const AName: string; var AValue: Variant); override;
procedure SetPropertyValue(const AName: string; const AValue: Variant); override;
function CreateDateNavigator: TcxSchedulerCustomDateNavigator; override;
function CreateDefaultView: TcxSchedulerCustomView; override;
function CreateViewDay: TcxSchedulerDayView; virtual;
function CreateViewWeek: TcxSchedulerWeekView; virtual;
function CreateViewWeeks: TcxSchedulerWeeksView; virtual;
procedure CreateSubClasses; override;
procedure DateNavigatorSelectionChanged; override;
function GetNextView(AView: TcxSchedulerCustomView): TcxSchedulerCustomView; override;
procedure SetCurrentView(AView: TcxSchedulerCustomView); override;
procedure SynchronizeVisibleDays; override;
procedure UpdateEventsCache(ACheckDaysInterval: Boolean); override;
procedure ValidateSelection(ASelection: TcxSchedulerDateList); override;
procedure ValidateWeekDays(ASaveWeekCount: Boolean = False);
public
function GoToDate(ADate: TDateTime; AViewMode: TcxSchedulerViewMode = vmDay): Boolean; override;
procedure SelectDays(const AStartDay, AFinishDay: TDateTime; AsDays: Boolean = False); overload; virtual;
procedure SelectDays(ASelection: TcxSchedulerDateList; AsDays: Boolean = False); overload; virtual;
procedure SelectDays(const ASelection: array of TDateTime; AsDays: Boolean = False); overload; virtual;
procedure SelectWorkDays(const AWeekDate: TDateTime);
published
property DateNavigator: TcxSchedulerDateNavigator read GetDateNavigator write SetDateNavigator;
property ViewDay: TcxSchedulerDayView read FViewDay write SetViewDay;
property ViewWeek: TcxSchedulerWeekView read FViewWeek write SetViewWeek;
property ViewWeeks: TcxSchedulerWeeksView read FViewWeeks write SetViewWeeks;
property OnCustomDrawBackground: TcxSchedulerCustomDrawBackgroundEvent read FOnCustomDrawBackground write FOnCustomDrawBackground;
property OnCustomDrawButton: TcxSchedulerCustomDrawButtonEvent read FOnCustomDrawButton write FOnCustomDrawButton;
property OnCustomDrawContent: TcxSchedulerCustomDrawContentEvent read FOnCustomDrawContent write FOnCustomDrawContent;
property OnCustomDrawDayHeader: TcxSchedulerCustomDrawDayHeaderEvent read FOnCustomDrawDayHeader write FOnCustomDrawDayHeader;
property OnCustomDrawEvent: TcxSchedulerCustomDrawEventEvent read FOnCustomDrawEvent write FOnCustomDrawEvent;
property OnCustomDrawGroupSeparator: TcxSchedulerCustomDrawGroupSeparatorEvent read FOnCustomDrawGroupSeparator write FOnCustomDrawGroupSeparator;
property OnCustomDrawResourceHeader: TcxSchedulerCustomDrawResourceHeaderEvent read FOnCustomDrawResourceHeader write FOnCustomDrawResourceHeader;
// derived properties and events
property Align;
property Anchors;
{$IFDEF DELPHI6}
property BevelEdges;
property BevelInner;
property BevelOuter;
property BevelKind;
property BevelWidth;
property BorderWidth;
{$ENDIF}
property BorderStyle;
property ContentPopupMenu;
property Constraints;
property ControlBox;
property DragCursor;
property DragKind;
property DragMode;
property Enabled;
property EventOperations;
property EventPopupMenu;
property Font;
property LookAndFeel;
property OptionsCustomize;
property OptionsView;
property ParentFont;
property PopupMenu;
property ShowHint;
property Storage;
property Styles;
property TabOrder;
property TabStop;
property Visible;
//events
property OnAfterDragEvent;
property OnAfterEditing;
property OnAfterSizingEvent;
property OnBeforeDeleting;
property OnBeforeDragEvent;
property OnBeforeEditing;
property OnBeforeSizingEvent;
property OnCanShowView;
property OnClick;
property OnContextPopup;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnEndDock;
property OnEndDrag;
property OnEnter;
property OnExit;
property OnEventSelectionChanged;
property OnGetEventDisplayText;
property OnGetEventEditProperties;
property OnGetEventHintText;
property OnInitEdit;
property OnIsWorkTime;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnLayoutChanged;
property OnMouseDown;
property OnMouseEnter;
property OnMouseLeave;
property OnMouseMove;
property OnMouseUp;
property OnMouseWheel;
property OnMouseWheelDown;
property OnMouseWheelUp;
property OnResize;
property OnStartDock;
property OnStartDrag;
property OnSelectionChanged;
property OnViewTypeChanged;
//nested events
property DateNavigatorEvents: TNotifyEvent read FDateNavigatorEvents write FDateNavigatorEvents;
property ViewDayEvents: TNotifyEvent read FViewDayEvents write FViewDayEvents;
end;
function cxCompareSchedulerControlEvents(
AEvent1, AEvent2: TcxSchedulerControlEvent): Integer;
implementation
uses
SysUtils;
function cxCompareSchedulerControlEvents(
AEvent1, AEvent2: TcxSchedulerControlEvent): Integer;
var
AAllDay1, AAllDay2: Boolean;
begin
AAllDay1 := AEvent1.AllDayEvent or (AEvent1.Duration >= 1);
AAllDay2 := AEvent2.AllDayEvent or (AEvent2.Duration >= 1);
Result := Byte(AAllDay2) - Byte(AAllDay1);
if Result <> 0 then Exit;
if AEvent1.Start < AEvent2.Start then
Result := -1
else
if AEvent1.Start > AEvent2.Start then
Result := 1
else
if AEvent1.Finish > AEvent2.Finish then
Result := -1
else
if AEvent1.Finish < AEvent2.Finish then
Result := 1
else
if AEvent1.RecordIndex < AEvent2.RecordIndex then
Result := -1
else
if AEvent1.RecordIndex > AEvent2.RecordIndex then
Result := 1
else
Result := 0;
end;
{ TcxScheduler }
function TcxScheduler.GoToDate(ADate: TDateTime; AViewMode:
TcxSchedulerViewMode = vmDay): Boolean;
procedure SelectMonth;
var
I, AYear, AMonth, ADay: Word;
AStart: TDateTime;
begin
DecodeDate(ADate, AYear, AMonth, ADay);
AStart := EncodeDate(AYear, AMonth, 1);
for I := 0 to DaysPerMonth(AYear, AMonth) - 1 do
SelectedDays.Add(AStart + I);
ValidateWeekDays;
end;
function UpdateView(AView: TcxSchedulerCustomView): Boolean;
begin
if (ADate < DateNavigator.FirstDate) or (ADate > DateNavigator.LastDate) then
DateNavigator.FirstDate := ADate;
if AView.Active then
AView.Refresh
else
AView.Active := True;
Result := AView.Active;
end;
begin
DateNavigator.BeginUpdate;
try
SelectedDays.Clear;
case AViewMode of
vmDay, vmWeek:
begin
SelectedDays.Add(ADate);
if AViewMode = vmDay then
Result := UpdateView(ViewDay)
else
Result := UpdateView(ViewWeek);
end;
vmMonth:
begin
SelectMonth;
Result := UpdateView(ViewWeeks);
end;
else
SelectWorkDays(ADate);
Result := UpdateView(ViewDay);
end;
finally
SynchronizeVisibleDays;
DateNavigator.Refresh;
DateNavigator.EndUpdate;
end;
end;
procedure TcxScheduler.SelectDays(const AStartDay, AFinishDay: TDateTime;
AsDays: Boolean = False);
var
I: Integer;
begin
SelectedDays.Clear;
//DELPHI8! check Trunc(AStartDay)
for I := Trunc(AStartDay) to Trunc(AFinishDay) do
SelectedDays.Add(I);
SelectDays(SelectedDays, AsDays);
end;
procedure TcxScheduler.SelectDays(
ASelection: TcxSchedulerDateList; AsDays: Boolean = False);
var
I: Integer;
begin
DateNavigator.BeginUpdate;
try
if ASelection <> SelectedDays then
SelectedDays.Assign(ASelection);
SelectedDays.Sort(cxCompareDates);
if SelectedDays.Count = 0 then
SelectedDays.Add(Date);
I := 1;
while I < (ASelection.Count - 1) do
begin
if ASelection[I] = ASelection[I - 1] then
ASelection.Delete(I)
else
Inc(I)
end;
AsDays := AsDays and (ASelection.Count < 14);
if not AsDays then
begin
ValidateWeekDays;
DateNavigator.SelectionIsWeeks := True;
end
else
DateNavigator.SelectionIsWeeks := False;
FIsSelectionValidated := True;
ValidateSelection(SelectedDays);
finally
DateNavigator.EndUpdate;
end;
end;
procedure TcxScheduler.SelectDays(const ASelection: array of TDateTime;
AsDays: Boolean = False);
var
I: Integer;
AList: TcxSchedulerDateList;
begin
AList := TcxSchedulerDateList.Create;
try
for I := Low(ASelection) to High(ASelection) do
AList.Add(ASelection[I]);
if AList.Count = 0 then
AList.Add(Date);
SelectDays(AList, AsDays);
finally
AList.Free;
end;
end;
procedure TcxScheduler.SelectWorkDays(const AWeekDate: TDateTime);
const
ConvertTable: array[1..7] of TDay = (dMonday, dTuesday, dWednesday, dThursday,
dFriday, dSaturday, dSunday);
var
AYear, AWeek, AWeekDay: Word;
ADay: TDay;
I, ADaysDiff: Integer;
AStartWeek: TDateTime;
begin
ViewDay.Active := True;
DecodeDateWeek(AWeekDate, AYear, AWeek, AWeekDay);
ADay := ConvertTable[AWeekDay];
ADaysDiff := Ord(ADay) - Ord(StartOfWeek);
if ADaysDiff >= 0 then
AStartWeek := AWeekDate - ADaysDiff
else
AStartWeek := AWeekDate - (ADaysDiff + 7);
ADay := ConvertTable[DayOfTheWeek(AStartWeek)];
SelectedDays.Clear;
for I := 1 to 7 do
begin
if ADay in OptionsView.WorkDays then
SelectedDays.Add(AStartWeek);
if ADay < dSaturday then
Inc(ADay)
else
ADay := dSunday;
AStartWeek := AStartWeek + 1;
end;
SelectDays(SelectedDays, True)
end;
procedure TcxScheduler.DoCustomDrawBackground(
AViewInfo: TcxSchedulerBackgroundCellViewInfo; var ADone: Boolean);
begin
if Assigned(FOnCustomDrawBackground) then
FOnCustomDrawBackground(CurrentView, Canvas, AViewInfo, ADone);
end;
procedure TcxScheduler.DoCustomDrawButton(
AViewInfo: TcxSchedulerMoreEventsButtonViewInfo; var ADone: Boolean);
begin
if Assigned(FOnCustomDrawButton) then
FOnCustomDrawButton(CurrentView, Canvas, AViewInfo, ADone);
end;
procedure TcxScheduler.DoCustomDrawContent(
AViewInfo: TcxSchedulerContentCellViewInfo; var ADone: Boolean);
begin
if Assigned(FOnCustomDrawContent) then
FOnCustomDrawContent(CurrentView, Canvas, AViewInfo, ADone);
end;
procedure TcxScheduler.DoCustomDrawDayHeader(
AViewInfo: TcxSchedulerDayHeaderCellViewInfo; var ADone: Boolean);
begin
if Assigned(FOnCustomDrawDayHeader) then
FOnCustomDrawDayHeader(CurrentView, Canvas, AViewInfo, ADone);
end;
procedure TcxScheduler.DoCustomDrawEvent(
AViewInfo: TcxSchedulerEventCellViewInfo; var ADone: Boolean);
begin
if Assigned(FOnCustomDrawEvent) and Assigned(AViewInfo.Event) then
FOnCustomDrawEvent(CurrentView, Canvas, AViewInfo, ADone);
end;
procedure TcxScheduler.DoCustomDrawGroupSeparator(
AViewInfo: TcxSchedulerGroupSeparatorCellViewInfo; var ADone: Boolean);
begin
if Assigned(FOnCustomDrawGroupSeparator) then
FOnCustomDrawGroupSeparator(CurrentView, Canvas, AViewInfo, ADone);
end;
procedure TcxScheduler.DoCustomDrawResourceHeader(
AViewInfo: TcxSchedulerHeaderCellViewInfo; var ADone: Boolean);
begin
if Assigned(FOnCustomDrawResourceHeader) then
FOnCustomDrawResourceHeader(CurrentView, Canvas, AViewInfo, ADone);
end;
function TcxScheduler.GetProperties(AProperties: TStrings): Boolean;
begin
Result := inherited GetProperties(AProperties);
if CurrentView.Active then
AProperties.Add('View');
end;
procedure TcxScheduler.GetPropertyValue(const AName: string;
var AValue: Variant);
begin
inherited GetPropertyValue(AName, AValue);
if (AName = 'View') and CurrentView.Active then
begin
if CurrentView = ViewDay then
AValue := 0
else
if CurrentView = ViewWeek then
AValue := 1
else
if CurrentView = ViewWeeks then
AValue := 2
end;
end;
procedure TcxScheduler.SetPropertyValue(const AName: string;
const AValue: Variant);
begin
inherited SetPropertyValue(AName, AValue);
if (AName = 'View') and CurrentView.Active then
begin
DateNavigator.BeginUpdate;
try
if AValue = 0 then
ViewDay.Active := True
else
begin
if AValue = 1 then
ViewWeek.Active := True
else
if AValue = 2 then
ViewWeeks.Active := True;
ValidateWeekDays(True);
end;
finally
DateNavigator.EndUpdate;
end;
end;
end;
function TcxScheduler.CreateDateNavigator: TcxSchedulerCustomDateNavigator;
begin
Result := TcxSchedulerDateNavigator.Create(Self);
end;
function TcxScheduler.CreateDefaultView: TcxSchedulerCustomView;
begin
Result := FViewDay;
end;
function TcxScheduler.CreateViewDay: TcxSchedulerDayView;
begin
Result := TcxSchedulerDayView.Create(Self);
end;
function TcxScheduler.CreateViewWeek: TcxSchedulerWeekView;
begin
Result := TcxSchedulerWeekView.Create(Self);
end;
function TcxScheduler.CreateViewWeeks: TcxSchedulerWeeksView;
begin
Result := TcxSchedulerWeeksView.Create(Self);
end;
procedure TcxScheduler.CreateSubClasses;
begin
FViewDay := CreateViewDay;
FViewWeek := CreateViewWeek;
FViewWeeks := CreateViewWeeks;
inherited CreateSubClasses;
end;
procedure TcxScheduler.DateNavigatorSelectionChanged;
begin
if not (cfViewValid in ControlFlags) then Exit;
if DateNavigator.SelectionIsWeeks then
begin
if SelectedDays.Count >= 14 then
ViewWeeks.Active := True
else
ViewWeek.Active := True
end
else
ViewDay.Active := True;
FullRefresh;
end;
function TcxScheduler.GetNextView(
AView: TcxSchedulerCustomView): TcxSchedulerCustomView;
begin
Result := FViewWeek;
if (AView = FViewWeek) and FViewWeeks.CanShow then
Result := FViewWeeks
else
if not FViewWeek.CanShow or (AView = FViewWeek) then
begin
if AView <> FViewDay then
Result := FViewDay
else
Result := FViewWeeks;
end;
end;
procedure TcxScheduler.SetCurrentView(AView: TcxSchedulerCustomView);
begin
inherited SetCurrentView(AView);
end;
procedure TcxScheduler.SynchronizeVisibleDays;
var
ADate: TDateTime;
begin
if SelectedDays.Count = 0 then
SelectedDays.Add(Date);
if CurrentView = ViewWeek then
begin
ADate := SelectedDays[0];
SelectedDays.Clear;
SelectedDays.Add(ADate);
end;
SelectDays(SelectedDays, CurrentView = ViewDay);
inherited SynchronizeVisibleDays;
end;
procedure TcxScheduler.UpdateEventsCache(ACheckDaysInterval: Boolean);
begin
inherited UpdateEventsCache(ACheckDaysInterval);
EventList.Sort(TcxCompareEventsProc(@cxCompareSchedulerControlEvents));
end;
procedure TcxScheduler.ValidateSelection(ASelection: TcxSchedulerDateList);
begin
if not FIsSelectionValidated then
begin
FIsSelectionValidated := True;
SelectDays(ASelection, (CurrentView = ViewDay) or (SelectedDays.Count = 1));
end
else
begin
FIsSelectionValidated := False;
inherited ValidateSelection(ASelection);
end;
end;
procedure TcxScheduler.ValidateWeekDays(ASaveWeekCount: Boolean = False);
var
I, J, AWeekCount: Integer;
ADate: TDateTime;
AWeeks: TcxSchedulerDateList;
AYear, APrevYear, AWeek, APrevWeek, AWeekDay: Word;
begin
AWeekCount := SelectedDays.Count div 7;
if AWeekCount = 0 then Inc(AWeekCount);
AWeeks := TcxSchedulerDateList.Create;
try
APrevYear := 0;
APrevWeek := 0;
for I := 0 to SelectedDays.Count - 1 do
begin
DecodeDateWeek(SelectedDays[I] + 1 - Byte(StartOfWeek), AYear, AWeek, AWeekDay);
if (AYear <> APrevYear) or (AWeek <> APrevWeek) then
begin
APrevYear := AYear;
APrevWeek := AWeek;
AWeeks.Add(EncodeDateWeek(AYear, AWeek, 1) - 1);
end;
end;
SelectedDays.Clear;
for I := 0 to AWeeks.Count - 1 do
begin
if ASaveWeekCount and (I = AWeekCount) then break;
ADate := AWeeks[I];
for J := 0 to 6 do
SelectedDays.Add(ADate + J + Byte(StartOfWeek));
end;
finally
AWeeks.Free;
end;
end;
function TcxScheduler.GetDateNavigator: TcxSchedulerDateNavigator;
begin
Result := TcxSchedulerDateNavigator(inherited DateNavigator);
end;
procedure TcxScheduler.SetDateNavigator(AValue: TcxSchedulerDateNavigator);
begin
DateNavigator.Assign(AValue);
end;
procedure TcxScheduler.SetViewDay(AValue: TcxSchedulerDayView);
begin
FViewDay.Assign(AValue);
end;
procedure TcxScheduler.SetViewWeek(AValue: TcxSchedulerWeekView);
begin
FViewWeeks.Assign(AValue);
end;
procedure TcxScheduler.SetViewWeeks(AValue: TcxSchedulerWeeksView);
begin
FViewWeek.Assign(AValue);
end;
end.