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

4424 lines
132 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 cxSchedulerStorage;
{$I cxVer.inc}
interface
uses
Classes, SysUtils,
Windows, Forms,
{$IFDEF DELPHI6}
Variants,
{$ENDIF}
Math, Graphics, {$IFDEF DELPHI6} DateUtils, {$ENDIF} cxClasses, cxCustomData, cxDataStorage,
cxDateUtils, cxDataUtils, cxSchedulerUtils, cxVariants, cxStorage;
type
TcxCustomSchedulerStorage = class;
TcxSchedulerStorage = class;
TcxSchedulerEvent = class;
TcxSchedulerEventRecurrenceInfo = class;
TcxSchedulerControlEvent = class;
TcxSchedulerCachedEventList = class;
TcxSchedulerOccurrenceCalculator = class;
TcxSchedulerEventList = class;
TcxSchedulerFilteredEventList = class;
TcxSchedulerStorageResources = class;
TcxSchedulerStorageResourceItem = class;
TcxCustomSchedulerStorageClass = class of TcxCustomSchedulerStorage;
TcxSchedulerCachedEventListClass = class of TcxSchedulerCachedEventList;
TcxSchedulerStorageResourcesClass = class of TcxSchedulerStorageResources;
TcxSchedulerStorageResourceItemClass = class of TcxSchedulerStorageResourceItem;
TcxEventType = (etNone, etPattern, etOccurrence, etException, etCustom);
TcxRecurrence = (cxreDaily, cxreWeekly, cxreMonthly, cxreYearly);
TcxRecurrenceValidStatus = (rvsValid, rvsReplaceOccurrenceDate, rvsInvalidPattern,
rvsInvalidDuration);
TcxDayType = (cxdtDay, cxdtEveryDay, cxdtWeekDay, cxdtWeekEndDay, cxdtSunday,
cxdtMonday, cxdtTuesday, cxdtWednesday, cxdtThursday, cxdtFriday, cxdtSaturday);
TcxCompareEventsProc = function(AEvent1, AEvent2: TcxSchedulerEvent): Integer;
TcxGetRecurrenceDescriptionStringProc = function(
ARecurrenceInfo: TcxSchedulerEventRecurrenceInfo): string;
{ IcxSchedulerStorageListener }
IcxSchedulerStorageListener = interface
['{87E0EBF3-F68A-4A51-8EA3-850D3819FBAB}']
procedure StorageChanged(Sender: TObject);
procedure StorageRemoved(Sender: TObject);
end;
{ IcxSchedulerSelectionAdapter }
IcxSchedulerSelectionAdapter = interface
['{68B007E5-1057-40DE-BDA4-0D72F3780CC7}']
procedure Add(AEvent: TcxSchedulerControlEvent; Shift: TShiftState);
procedure Clear;
function IsSelected(AEvent: TcxSchedulerControlEvent): Boolean;
procedure Update;
end;
{ TcxSchedulerStorageDataController }
TcxSchedulerStorageDataController = class(TcxCustomDataController)
private
function GetStorage: TcxCustomSchedulerStorage;
protected
procedure UpdateControl(AInfo: TcxUpdateControlInfo); override;
function UseRecordID: Boolean; override;
property Storage: TcxCustomSchedulerStorage read GetStorage;
public
function GetItem(Index: Integer): TObject; override;
function GetItemValueSource(AItemIndex: Integer): TcxDataEditValueSource; override;
function GetItemID(AItem: TObject): Integer; override;
procedure UpdateData; override;
procedure UpdateItemIndexes; override;
end;
TcxSchedulerStorageDataControllerClass = class of TcxCustomDataController;
{ TcxCustomSchedulerStorageField }
TcxCustomSchedulerStorageField = class(TCollectionItem)
private
FIndex: Integer;
FName: string;
function IsValueTypeStored: Boolean;
function GetDataController: TcxCustomDataController;
function GetStorage: TcxCustomSchedulerStorage;
function GetValue(AIndex: Integer): Variant;
function GetValueCount: Integer;
function GetValueType: string;
function GetValueTypeClass: TcxValueTypeClass;
procedure SetName(const AValue: string);
procedure SetValue(AIndex: Integer; const AValue: Variant);
procedure SetValueType(const AValue: string);
procedure SetValueTypeClass(AValue: TcxValueTypeClass); virtual;
protected
function GetDisplayName: string; override;
property DataController: TcxCustomDataController read GetDataController;
property Name: string read FName write SetName;
property Storage: TcxCustomSchedulerStorage read GetStorage;
property ValueCount: Integer read GetValueCount;
property Values[ARecordIndex: Integer]: Variant read GetValue write SetValue;
property ValueType: string read GetValueType write SetValueType stored IsValueTypeStored;
property ValueTypeClass: TcxValueTypeClass read GetValueTypeClass write SetValueTypeClass;
public
constructor Create(Collection: TCollection); override;
destructor Destroy; override;
procedure Assign(Source: TPersistent); override;
property Index: Integer read FIndex;
end;
TcxSchedulerStorageFieldClass = class of TcxCustomSchedulerStorageField;
{ TcxSchedulerStorageField }
TcxSchedulerStorageField = class(TcxCustomSchedulerStorageField)
public
property ValueCount;
property Values;
property ValueTypeClass;
published
property Index;
property Name;
property ValueType;
end;
{ TcxCustomSchedulerStorageFields }
TcxCustomSchedulerStorageFields = class(TCollection)
private
FOwner: TPersistent;
function GetStorage: TcxCustomSchedulerStorage;
protected
function FindFieldByName(const AName: string): TcxCustomSchedulerStorageField; virtual;
function GetOwner: TPersistent; override;
procedure Update(Item: TCollectionItem); override;
public
property Storage: TcxCustomSchedulerStorage read GetStorage;
end;
TcxSchedulerStorageFieldsClass = class of TcxCustomSchedulerStorageFields;
{ TcxSchedulerStorageFields }
TcxSchedulerStorageFields = class(TcxCustomSchedulerStorageFields)
private
function GetItem(AIndex: Integer): TcxSchedulerStorageField;
procedure SetItem(AIndex: Integer; AValue: TcxSchedulerStorageField);
public
function Add: TcxSchedulerStorageField;
function ItemByName(const AName: string): TcxSchedulerStorageField;
property Items[Index: Integer]: TcxSchedulerStorageField read GetItem write SetItem;
property Storage;
end;
{ TcxSchedulerEventRecurrenceInfo }
TcxSchedulerEventRecurrenceInfoData = packed record
Count: Integer;
DayNumber: Integer;
DayType: TcxDayType;
Finish: TDateTime;
OccurDays: TDays;
Periodicity: Integer;
Recurrence: TcxRecurrence;
Start: TDateTime;
YearPeriodicity: Integer;
Reserved1: Byte;
Reserved2: Integer;
end;
TcxSchedulerEventRecurrenceInfo = class(TPersistent)
private
FOwner: TcxSchedulerEvent;
function GetCount: Integer;
function GetDayNumber: Integer;
function GetDayType: TcxDayType;
function GetFinish: TDateTime;
function GetOccurDays: TDays;
function GetPeriodicity: Integer;
function GetRecurrence: TcxRecurrence;
function GetStart: TDateTime;
function GetStorage: TcxCustomSchedulerStorage;
function GetYearPeriodicity: Integer;
procedure SetCount(const AValue: Integer);
procedure SetDayNumber(const AValue: Integer);
procedure SetDayType(const AValue: TcxDayType);
procedure SetFinish(AValue: TDateTime);
procedure SetOccurDays(const AValue: TDays);
procedure SetPeriodicity(const AValue: Integer);
procedure SetRecurrence(const AValue: TcxRecurrence);
procedure SetStart(const AValue: TDateTime);
procedure SetYearPeriodicity(const AValue: Integer);
protected
procedure AssignDefaultValues; virtual;
function GetData: TcxSchedulerEventRecurrenceInfoData;
function GetOwner: TPersistent; override;
function GetValue(var AValue: string): Boolean;
procedure SetDataItem(AOffset: Pointer; ASize: Integer; const AValue);
procedure SetValue(const AValue: string);
// validate
function GetDailyPatternStatus: TcxRecurrenceValidStatus;
function GetMonthlyPatternStatus: TcxRecurrenceValidStatus;
function GetWeeklyPatternStatus: TcxRecurrenceValidStatus;
function GetYearlyPatternStatus: TcxRecurrenceValidStatus;
property Storage: TcxCustomSchedulerStorage read GetStorage;
public
constructor Create(AOwner: TcxSchedulerEvent); virtual;
procedure Assign(Source: TPersistent); override;
function GetValidStatus: TcxRecurrenceValidStatus;
procedure Validate;
property Count: Integer read GetCount write SetCount;
property DayNumber: Integer read GetDayNumber write SetDayNumber;
property DayType: TcxDayType read GetDayType write SetDayType;
property Event: TcxSchedulerEvent read FOwner;
property Finish: TDateTime read GetFinish write SetFinish;
property OccurDays: TDays read GetOccurDays write SetOccurDays;
property Periodicity: Integer read GetPeriodicity write SetPeriodicity;
property Recurrence: TcxRecurrence read GetRecurrence write SetRecurrence;
property Start: TDateTime read GetStart write SetStart;
property YearPeriodicity: Integer read GetYearPeriodicity write SetYearPeriodicity;
end;
TcxSchedulerEventRecurrenceInfoClass = class of TcxSchedulerEventRecurrenceInfo;
{ TcxSchedulerEvent }
TcxSchedulerEvent = class(TPersistent)
private
FIsModified: Boolean;
FLink: TcxSchedulerEvent;
FStorage: TcxCustomSchedulerStorage;
FRecurrenceInfo: TcxSchedulerEventRecurrenceInfo;
function GetAllDayEvent: Boolean;
function GetCaption: string;
function GetDuration: TDateTime;
function GetEditValue(AIndex: Integer): Variant;
function GetEnabled: Boolean;
function GetEventType: TcxEventType;
function GetFinish: TDateTime;
function GetID: Variant;
function GetIsEditing: Boolean;
function GetIsNewEvent: Boolean;
function GetLabelColor: Integer;
function GetLocation: string;
function Getmessage: string; {GetMessage conflicts with C++ macro}
function GetOptionsFlag: Integer;
function GetParentID: Variant;
function GetReadOnly: Boolean;
function GetRecurrenceIndex: Integer;
function GetReminder: Boolean;
function GetReminderTime: Integer;
function GetResourceID: Variant;
function GetStart: TDateTime;
function GetState: Integer;
function GetValueCount: Integer;
procedure SetAllDayEvent(const AValue: Boolean);
procedure SetCaption(const AValue: string);
procedure SetDuration(const AValue: TDateTime);
procedure SetEditValue(AIndex: Integer; const AValue: Variant);
procedure SetEnabled(const AValue: Boolean);
procedure SetEventType(AValue: TcxEventType);
procedure SetFinish(const AValue: TDateTime);
procedure SetLabelColor(const AValue: Integer);
procedure SetLocation(const AValue: string);
procedure SetMessage(const AValue: string);
function SetOptionsFlag(const AMask: Integer; AValue: Boolean): Boolean;
procedure SetParentID(const AValue: Variant);
procedure SetRecurrenceIndex(const AValue: Integer);
procedure SetRecurrenceInfo(AValue: TcxSchedulerEventRecurrenceInfo);
procedure SetReminder(const AValue: Boolean);
procedure SetReminderTime(const AValue: Integer);
procedure SetResourceID(const AValue: Variant);
procedure SetStart(const AValue: TDateTime);
procedure SetState(const AValue: Integer);
protected
FEditCount: Integer;
FEditValues: array of Variant;
FPattern: TcxSchedulerEvent;
FRecordIndex: Integer;
FIsDataValid: Boolean;
FFinish, FStart: Double;
FOptions: Integer;
FSavedID: Variant;
FSkipModified: Boolean;
procedure AssignDefaultValues; virtual;
procedure CheckRecurrenceLink(AEvent: TcxSchedulerEvent);
function CreateRecurrenceInfo: TcxSchedulerEventRecurrenceInfo; virtual;
function GetOccurrenceByIndex(AIndex: Integer; var AOccurrence: TcxSchedulerEvent): Boolean;
function GetOwner: TPersistent; override;
function GetRecurrenceInfoValue(var AValue: string): Boolean; virtual;
function GetValueByIndex(AIndex: Integer): Variant; virtual;
function GetValueDef(AField: TcxCustomSchedulerStorageField; const ADefValue: Variant): Variant;
procedure Modified;
procedure PostEditingData;
procedure SetRecordIndex(const AIndex: Integer);
procedure SetRecurrenceInfoValue(const AValue: string); virtual;
procedure SetValue(AField: TcxCustomSchedulerStorageField; const AValue: Variant);
procedure SetValueByIndex(AIndex: Integer; const AValue: Variant); virtual;
function TimeBias: Double; virtual;
procedure UpdateTemporaryData;
property IsNewEvent: Boolean read GetIsNewEvent;
property IsModified: Boolean read FIsModified write FIsModified;
property Link: TcxSchedulerEvent read FLink;
property Reminder: Boolean read GetReminder write SetReminder;
property ReminderTime: Integer read GetReminderTime write SetReminderTime;
public
constructor Create(AStorage: TcxCustomSchedulerStorage); overload; virtual;
constructor Create(AStorage: TcxCustomSchedulerStorage; ARecordIndex: Integer); overload; virtual;
destructor Destroy; override;
procedure Assign(Source: TPersistent); override;
procedure BeginEditing; virtual;
procedure Cancel;
procedure EndEditing; virtual;
procedure Delete; virtual;
procedure DeleteExceptions;
function HasExceptions: Boolean;
//custom fields routines
function GetCustomFieldValueByIndex(AIndex: Integer): Variant;
function GetCustomFieldValueByName(const AName: String): Variant;
function GetCustomFieldValue(ACustomField: TcxCustomSchedulerStorageField): Variant;
procedure SetCustomFieldValueByIndex(AIndex: Integer; const AValue: Variant);
procedure SetCustomFieldValueByName(const AName: string; const AValue: Variant);
procedure SetCustomFieldValue(ACustomField: TcxCustomSchedulerStorageField; const AValue: Variant);
//
function GetResourceItem: TcxSchedulerStorageResourceItem;
function GetRecurrenceChain: TcxSchedulerEventList;
function IsDayEvent(ADate: TDateTime): Boolean;
function IsRecurring: Boolean;
function IsResourceEvent(AResource: TcxSchedulerStorageResourceItem;
AllowUnassigned: Boolean): Boolean;
procedure MoveTo(const AStartTime: TDateTime);
procedure Post;
property AllDayEvent: Boolean read GetAllDayEvent write SetAllDayEvent;
property Caption: string read GetCaption write SetCaption;
property Duration: TDateTime read GetDuration write SetDuration;
property EditValues[Index: Integer]: Variant read GetEditValue write SetEditValue;
property Enabled: Boolean read GetEnabled write SetEnabled;
property EventType: TcxEventType read GetEventType write SetEventType;
property Finish: TDateTime read GetFinish write SetFinish;
property ID: Variant read GetID;
property IsEditing: Boolean read GetIsEditing;
property LabelColor: Integer read GetLabelColor write SetLabelColor;
property Location: string read GetLocation write SetLocation;
property Message: string read Getmessage write SetMessage;
property ParentID: Variant read GetParentID write SetParentID;
property Pattern: TcxSchedulerEvent read FPattern;
property ReadOnly: Boolean read GetReadOnly;
property RecordIndex: Integer read FRecordIndex;
property RecurrenceIndex: Integer read GetRecurrenceIndex write SetRecurrenceIndex;
property RecurrenceInfo: TcxSchedulerEventRecurrenceInfo read FRecurrenceInfo write SetRecurrenceInfo;
property ResourceID: Variant read GetResourceID write SetResourceID;
property Start: TDateTime read GetStart write SetStart;
property State: Integer read GetState write SetState;
property Storage: TcxCustomSchedulerStorage read FStorage;
property ValueCount: Integer read GetValueCount;
property Values[Index: Integer]: Variant read GetValueByIndex write SetValueByIndex;
end;
{ TcxSchedulerControlEvent }
TcxSchedulerControlEvent = class(TcxSchedulerEvent)
private
FIsClone: Boolean;
FIsSource: Boolean;
FSelectionAdapter: IcxSchedulerSelectionAdapter;
FSource: TcxSchedulerEvent;
FTimeBias: Double;
FValues: array of Variant;
function GetSelected: Boolean;
procedure SetSelected(AValue: Boolean);
protected
procedure ClearValues;
function GetValueByIndex(AIndex: Integer): Variant; override;
procedure SetValueByIndex(AIndex: Integer; const AValue: Variant); override;
function TimeBias: Double; override;
property SelectionAdapter: IcxSchedulerSelectionAdapter read FSelectionAdapter write FSelectionAdapter;
public
constructor Create(AStorage: TcxCustomSchedulerStorage); overload; override;
constructor Create(ASource: TcxSchedulerEvent); reintroduce; overload;
constructor Create(ASource: TcxSchedulerEvent; const AStart, AFinish: TDateTime); reintroduce; overload;
destructor Destroy; override;
procedure Assign(Source: TPersistent); override;
procedure BeginEditing; override;
procedure Delete; override;
procedure EndEditing; override;
property Selected: Boolean read GetSelected write SetSelected;
property Source: TcxSchedulerEvent read FSource;
property IsClone: Boolean read FIsClone;
property IsSource: Boolean read FIsSource;
end;
TcxSchedulerEventClass = class of TcxSchedulerEvent;
TcxSchedulerGetResourceNameEvent = procedure(Sender: TObject;
AResource: TcxSchedulerStorageResourceItem; var AResourceName: string) of object;
{ TcxSchedulerStorageResourceItems }
TcxSchedulerStorageResourceItems = class(TCollection)
private
FOwner: TcxSchedulerStorageResources;
function GetItem(AIndex: Integer): TcxSchedulerStorageResourceItem;
function GetStorage: TcxCustomSchedulerStorage;
procedure SetItem(AIndex: Integer; AValue: TcxSchedulerStorageResourceItem);
function GetVisibleResource(AIndex: Integer): TcxSchedulerStorageResourceItem;
function GetVisibleResourceCount: Integer;
protected
function GetOwner: TPersistent; override;
procedure Update(Item: TCollectionItem); override;
property Resources: TcxSchedulerStorageResources read FOwner;
property Storage: TcxCustomSchedulerStorage read GetStorage;
public
constructor Create(AOwner: TcxSchedulerStorageResources; AItemClass: TcxSchedulerStorageResourceItemClass); virtual;
function Add: TcxSchedulerStorageResourceItem;
property Items[Index: Integer]: TcxSchedulerStorageResourceItem read GetItem write SetItem; default;
property VisibleResourceCount: Integer read GetVisibleResourceCount;
property VisibleResources[Index: Integer]: TcxSchedulerStorageResourceItem read GetVisibleResource;
end;
{ TcxSchedulerStorageResourceItem }
TcxSchedulerStorageResourceItem = class(TCollectionItem)
private
FColor: TColor;
FName: string;
FReadOnly: Boolean;
FResourceID: Variant;
FVisible: Boolean;
function GetResources: TcxSchedulerStorageResources;
protected
// methods TList.Sort
function GetDisplayName: string; override;
procedure SetColor(const AValue: TColor); virtual;
procedure SetName(const AValue: string); virtual;
procedure SetResourceID(const AValue: Variant); virtual;
procedure SetVisible(const AValue: Boolean); virtual;
public
constructor Create(Collection: TCollection); override;
procedure Assign(Source: TPersistent); override;
property Resources: TcxSchedulerStorageResources read GetResources;
published
property Name: string read FName write SetName;
property Color: TColor read FColor write SetColor default clDefault;
property ResourceID: Variant read FResourceID write SetResourceID;
property ReadOnly: Boolean read FReadOnly write FReadOnly default False;
property Visible: Boolean read FVisible write SetVisible default True;
end;
{ TcxSchedulerStorageResources }
TcxSchedulerStorageResources = class(TcxInterfacedPersistent, IcxStoredObject)
private
FItems: TcxSchedulerStorageResourceItems;
FOwner: TcxCustomSchedulerStorage;
FOnGetResourceName: TcxSchedulerGetResourceNameEvent;
procedure SetItems(AValue: TcxSchedulerStorageResourceItems);
protected
// IcxStoredObject
function GetObjectName: string;
function GetProperties(AProperties: TStrings): Boolean;
procedure GetPropertyValue(const AName: string; var AValue: Variant);
procedure SetPropertyValue(const AName: string; const AValue: Variant);
// methods
procedure Changed; virtual;
function CreateItems: TcxSchedulerStorageResourceItems; virtual;
function DoGetResourceName(AItem: TcxSchedulerStorageResourceItem): string; virtual;
function GetOwner: TPersistent; override;
function GetResourceItems: TcxSchedulerStorageResourceItems; virtual;
property Storage: TcxCustomSchedulerStorage read FOwner;
public
constructor Create(AOwner: TcxCustomSchedulerStorage); reintroduce; virtual;
destructor Destroy; override;
procedure Assign(Source: TPersistent); override;
function GetResourceName(AResource: TcxSchedulerStorageResourceItem): string;
property ResourceItems: TcxSchedulerStorageResourceItems read GetResourceItems;
published
property Items: TcxSchedulerStorageResourceItems read FItems write SetItems;
property OnGetResourceName: TcxSchedulerGetResourceNameEvent read FOnGetResourceName write FOnGetResourceName;
end;
TcxSchedulerNotificationEvent = procedure(Sender: TObject;
AEvent: TcxSchedulerEvent; var AHandled: Boolean) of object;
{ TcxCustomSchedulerStorage }
TcxCustomSchedulerStorage = class(TComponent)
private
FDataController: TcxCustomDataController;
FEditor: TForm;
FInternalFields: TcxCustomSchedulerStorageFields;
FIsLoading: Boolean;
FIsModified: Boolean;
FIsDeletion: Boolean;
FListeners: TInterfaceList;
FResources: TcxSchedulerStorageResources;
FResourcesEvents: TNotifyEvent;
FStoreUsingGlobalTime: Boolean;
FStoringName: string;
FUserFields: TcxCustomSchedulerStorageFields;
FOnEventDeleted: TcxSchedulerNotificationEvent;
FOnEventInserted: TcxSchedulerNotificationEvent;
FOnEventModified: TcxSchedulerNotificationEvent;
function GetEvent(AIndex: Integer): TcxSchedulerEvent;
function GetEventCount: Integer;
function GetFieldCount: Integer;
function GetIsDestroying: Boolean;
function GetIsLoading: Boolean;
function GetIsLocked: Boolean;
function GetIsUpdatingMode: Boolean;
function GetResourceCount: Integer;
function GetResourceID(AIndex: Integer): Variant;
function GetResourceName(AIndex: Integer): string;
procedure SetEvent(AIndex: Integer; AValue: TcxSchedulerEvent);
procedure SetResources(AValue: TcxSchedulerStorageResources);
procedure SetStoreUsingGlobalTime(AValue: Boolean);
protected
EventsIndex: TList;
FFields: TList;
FNewEvents: TcxSchedulerEventList;
FEventsList: TcxSchedulerEventList;
FDeletedRecords: TList;
// internal fields
FCaptionField: TcxCustomSchedulerStorageField;
FEventTypeField: TcxCustomSchedulerStorageField;
FFinishField: TcxCustomSchedulerStorageField;
FLabelColorField: TcxCustomSchedulerStorageField;
FLocationField: TcxCustomSchedulerStorageField;
FMessageField: TcxCustomSchedulerStorageField;
FOptionsField: TcxCustomSchedulerStorageField;
FParentIDField: TcxCustomSchedulerStorageField;
FRecurrenceIndexField: TcxCustomSchedulerStorageField;
FRecurrenceInfoField: TcxCustomSchedulerStorageField;
FReminderTimeField: TcxCustomSchedulerStorageField;
FResourceIDField: TcxCustomSchedulerStorageField;
FStartField: TcxCustomSchedulerStorageField;
FStateField: TcxCustomSchedulerStorageField;
TimeBias: Double;
procedure AddInternalField(var AField: TcxCustomSchedulerStorageField;
AValueType: TcxValueTypeClass);
procedure AddRecord; virtual;
procedure CancelEvent(AEvent: TcxSchedulerEvent); virtual;
function CanGetValueFromPattern(AIndex: Integer): Boolean; virtual;
procedure Changed; virtual;
procedure CreateDefaultFields; virtual;
function CreateFields: TcxCustomSchedulerStorageFields; virtual;
function CreateResources: TcxSchedulerStorageResources; virtual;
procedure CreateSubClasses; virtual;
procedure DestroySubClasses; virtual;
procedure DoDeleteEvent(const ARecordIndex: Integer); virtual;
procedure DoDestroyEvent(AEvent: TcxSchedulerEvent); virtual;
function DoEventDeleted(AEvent: TcxSchedulerEvent): Boolean; virtual;
function DoEventInserted(AEvent: TcxSchedulerEvent): Boolean; virtual;
function DoEventModified(AEvent: TcxSchedulerEvent): Boolean; virtual;
procedure DoRefresh; virtual;
function GetDataControllerClass: TcxCustomDataControllerClass; virtual;
function GetEventClass: TcxSchedulerEventClass; virtual;
function GetEventStoredID(AEvent: TcxSchedulerEvent): Variant;
function GetFieldValueBeforePost(ARecordIndex, AFieldIndex: Integer): Variant; virtual;
function GetFocusedRecordID(ARecordIndex: Integer): Variant; virtual;
function GetParentForm: TForm;
function GetRecordID(const ARecordIndex: Integer): Variant; virtual;
function GetValue(ARecordIndex, AItemIndex: Integer): Variant; virtual;
procedure ItemAdded(AItem: TcxCustomSchedulerStorageField);
procedure ItemRemoved(AItem: TcxCustomSchedulerStorageField);
function IsDataSettingsValid: Boolean; virtual;
procedure LayoutChanged; virtual;
procedure Loaded; override;
procedure PostEvent(AEvent: TcxSchedulerEvent); virtual;
procedure PostEditingData(AEvent: TcxSchedulerEvent); virtual;
procedure SendNotification(
AIsRemoved: Boolean = False); virtual;
procedure SetEventRecordInfo(AEvent: TcxSchedulerEvent; ARecordIndex: Integer; const AEventID: Variant); virtual;
procedure SetFieldValueBeforePost(ARecordIndex, AFieldIndex: Integer; const AValue: Variant); virtual;
procedure SetPostFieldValue(AEvent: TcxSchedulerEvent; AFieldIndex: Integer); virtual;
procedure SetValue(ARecordIndex, AItemIndex: Integer; const AValue: Variant); virtual;
procedure UpdateControl(AInfo: TcxUpdateControlInfo); virtual;
procedure UpdateData; virtual;
procedure UpdateItemIndexes;
function IsReminderAvailable: Boolean; virtual;
procedure AfterUpdate; virtual;
procedure BeforeUpdate; virtual;
property DataController: TcxCustomDataController read FDataController;
property Editor: TForm read FEditor write FEditor;
property Fields: TcxCustomSchedulerStorageFields read FUserFields;
property InternalFields: TcxCustomSchedulerStorageFields read FInternalFields;
property IsDeletion: Boolean read FIsDeletion write FIsDeletion;
property IsDestroying: Boolean read GetIsDestroying;
property IsLoading: Boolean read GetIsLoading;
property IsLocked: Boolean read GetIsLocked;
property IsModified: Boolean read FIsModified;
property IsUpdatingMode: Boolean read GetIsUpdatingMode;
property Listeners: TInterfaceList read FListeners;
property OnEventDeleted: TcxSchedulerNotificationEvent read FOnEventDeleted write FOnEventDeleted;
property OnEventInserted: TcxSchedulerNotificationEvent read FOnEventInserted write FOnEventInserted;
property OnEventModified: TcxSchedulerNotificationEvent read FOnEventModified write FOnEventModified;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Assign(Source: TPersistent); override;
procedure AddListener(AListener: IcxSchedulerStorageListener);
procedure BeginUpdate;
function CheckRequiredFields: Boolean; virtual;
function createEvent: TcxSchedulerEvent; {CreateEvent conflicts with C++ macro}
function CreateOccurrence(APattern: TcxSchedulerEvent; const ADate: TDateTime;
AType: TcxEventType): TcxSchedulerEvent;
procedure Clear; virtual;
procedure EndUpdate;
procedure FullRefresh;
function GetEventByID(const AID: Variant): TcxSchedulerEvent;
function GetEvents(AList: TcxSchedulerFilteredEventList;
const AStart, AFinish: TDateTime): Boolean; overload;
function GetEvents(AList: TcxSchedulerFilteredEventList;
const AStart, AFinish: TDateTime; const AResourceID: Variant): Boolean; overload;
function IsActive: Boolean; virtual;
function IsCaptionAvailable: Boolean; virtual;
function IsLabelColorAvailable: Boolean; virtual;
function IsLocationAvailable: Boolean; virtual;
function IsMessageAvailable: Boolean; virtual;
function IsRecurrenceAvailable: Boolean; virtual;
function IsStateAvailable: Boolean; virtual;
procedure PostEvents;
procedure RemoveListener(AListener: IcxSchedulerStorageListener);
property EventCount: Integer read GetEventCount;
property Events[Index: Integer]: TcxSchedulerEvent read GetEvent write SetEvent;
property FieldCount: Integer read GetFieldCount;
property ResourceCount: Integer read GetResourceCount;
property ResourceIDs[Index: Integer]: Variant read GetResourceID;
property ResourceNames[Index: Integer]: string read GetResourceName;
property Resources: TcxSchedulerStorageResources read FResources write SetResources;
property StoringName: string read FStoringName write FStoringName;
property Values[ARecordIndex, AFieldIndex: Integer]: Variant read GetValue write SetValue;
published
property StoreUsingGlobalTime: Boolean read FStoreUsingGlobalTime write SetStoreUsingGlobalTime default False;
property ResourcesEvents: TNotifyEvent read FResourcesEvents write FResourcesEvents;
end;
{ TcxSchedulerStorage }
TcxSchedulerStorage = class(TcxCustomSchedulerStorage)
private
function GetFields: TcxSchedulerStorageFields;
procedure SetFields(const AValue: TcxSchedulerStorageFields);
protected
procedure DefineProperties(Filer: TFiler); override;
public
procedure Assign(Source: TPersistent); override;
procedure SaveToFile(const AFileName: string);
procedure SaveToStream(AStream: TStream); virtual;
procedure LoadFromFile(const AFileName: string);
procedure LoadFromStream(AStream: TStream); virtual;
published
property CustomFields: TcxSchedulerStorageFields read GetFields write SetFields;
property Resources;
property OnEventDeleted;
property OnEventInserted;
property OnEventModified;
end;
{ TcxSchedulerEventSelection }
TcxSelectedItemData = class
public
ID, ParentID: Variant;
RecurrenceIndex: Integer;
constructor Create(AEvent: TcxSchedulerEvent);
end;
TcxEventSelectionChangedEvent = procedure (AEvent: TcxSchedulerControlEvent) of object;
TcxSchedulerEventSelection = class(TcxIUnknownObject, IcxSchedulerSelectionAdapter)
private
FOnEventSelectionChanged: TcxEventSelectionChangedEvent;
function GetCount: Integer;
function GetItem(AIndex: Integer): TcxSchedulerControlEvent;
function GetKey(AIndex: Integer): TcxSelectedItemData;
function GetKeyCount: Integer;
protected
FKeys: TList;
FEvents: TList;
FSourceEvents: TcxSchedulerEventList;
procedure ClearKeys;
function CreateItem(AEvent: TcxSchedulerControlEvent): TcxSelectedItemData;
procedure DoEventSelectionChanged(AEvent: TcxSchedulerControlEvent);
function KeyIndexOf(AEvent: TcxSchedulerControlEvent): Integer;
function IndexOf(AEvent: TcxSchedulerControlEvent): Integer;
procedure InternalClear;
procedure ReplaceSelection;
property KeyCount: Integer read GetKeyCount;
property Keys[Index: Integer]: TcxSelectedItemData read GetKey;
public
constructor Create(ASourceEvents: TcxSchedulerEventList); virtual;
destructor Destroy; override;
procedure Add(AEvent: TcxSchedulerControlEvent; AShift: TShiftState);
procedure Clear;
function IsSelected(AEvent: TcxSchedulerControlEvent): Boolean;
procedure Update;
property Count: Integer read GetCount;
property Items[Index: Integer]: TcxSchedulerControlEvent read GetItem; default;
property OnEventSelectionChanged: TcxEventSelectionChangedEvent
read FOnEventSelectionChanged write FOnEventSelectionChanged;
end;
{ TcxSchedulerEventList }
TcxSchedulerEventList = class
private
FItems: TList;
function GetCount: Integer;
function GetFirst: TcxSchedulerEvent;
function GetEvent(AIndex: Integer): TcxSchedulerEvent;
function GetLast: TcxSchedulerEvent;
protected
procedure EventAdded(AEvent: TcxSchedulerEvent); virtual;
procedure DoClear(AFreeItems: Boolean); virtual;
public
constructor Create; virtual;
destructor Destroy; override;
procedure Assign(ASource: TcxSchedulerEventList{$IFDEF DELPHI6};
AOperator: TListAssignOp = laCopy {$ENDIF}); virtual;
function Add(AEvent: TcxSchedulerEvent): Integer; virtual;
procedure Clear;
procedure Delete(AIndex: Integer);
procedure DestroyItems;
function Remove(AEvent: TcxSchedulerEvent): Integer;
function IndexOf(AEvent: TcxSchedulerEvent): Integer;
procedure Sort(ACompare: TcxCompareEventsProc); virtual;
property Count: Integer read GetCount;
property First: TcxSchedulerEvent read GetFirst;
property Items[Index: Integer]: TcxSchedulerEvent read GetEvent; default;
property Last: TcxSchedulerEvent read GetLast;
end;
{ TcxSchedulerFilteredEventList }
TcxSchedulerFilteredEventList = class(TcxSchedulerEventList)
private
FFinish: TDateTime;
FStart: TDateTime;
FStorage: TcxCustomSchedulerStorage;
function GetEvent(AIndex: Integer): TcxSchedulerControlEvent;
protected
function AddEvent(AEvent: TcxSchedulerEvent): TcxSchedulerControlEvent;
function AddOccurrence(ACalculator: TcxSchedulerOccurrenceCalculator): TcxSchedulerControlEvent;
procedure Changed; virtual;
procedure CheckEvent(AEvent: TcxSchedulerEvent; const AResourceID: Variant); virtual;
procedure CheckRecurrenceEvent(AEvent: TcxSchedulerEvent; const AResourceID: Variant);
procedure CheckSimpleEvent(AEvent: TcxSchedulerEvent; const AResourceID: Variant);
function CreateControlEvent(AEvent: TcxSchedulerEvent): TcxSchedulerControlEvent; virtual;
procedure Init(const AStart, AFinish: TDateTime; AStorage: TcxCustomSchedulerStorage); virtual;
public
destructor Destroy; override;
property Finish: TDateTime read FFinish;
property Start: TDateTime read FStart;
property Storage: TcxCustomSchedulerStorage read FStorage;
property Items[AIndex: Integer]: TcxSchedulerControlEvent read GetEvent; default;
property Count;
end;
{ TcxSchedulerCachedEventList }
TcxSchedulerCachedEventList = class(TcxSchedulerFilteredEventList, IUnknown, IcxSchedulerSelectionAdapter)
private
FAbsoluteItems: TList;
FAlwaysShowSelectedEvent: Boolean;
FClones: TcxSchedulerFilteredEventList;
FSelStart: TDateTime;
FShowEventsWithoutResource: Boolean;
FSelFinish: TDateTime;
FSelection: TcxSchedulerEventSelection;
FTimeBias: Double;
FTimeZone: Integer;
function GetAbsoluteCount: Integer;
function GetAbsoluteItem(AIndex: Integer): TcxSchedulerControlEvent;
function GetAbsoluteCountInternal: Integer;
function GetAbsoluteItemInternal(AIndex: Integer): TcxSchedulerControlEvent;
function GetItem(AIndex: Integer): TcxSchedulerControlEvent;
// IcxSchedulerSelectionAdapter
procedure IcxSchedulerSelectionAdapter.Add = SelectionAdd;
procedure IcxSchedulerSelectionAdapter.Clear = SelectionClear;
procedure IcxSchedulerSelectionAdapter.Update = SelectionUpdate;
protected
procedure Changed; override;
procedure CheckEvent(AEvent: TcxSchedulerEvent; const AResourceID: Variant); override;
function CheckEventVisibility(AEvent: TcxSchedulerEvent; AIncludeUnassigned: Boolean): Boolean;
function CreateControlEvent(AEvent: TcxSchedulerEvent): TcxSchedulerControlEvent; override;
function CreateCloneList: TcxSchedulerFilteredEventList; virtual;
function CreateSelection: TcxSchedulerEventSelection; virtual;
procedure DoClear(AFreeItems: Boolean); override;
procedure EventAdded(AEvent: TcxSchedulerEvent); override;
procedure Init(const AStart, AFinish: TDateTime; AStorage: TcxCustomSchedulerStorage); override;
procedure InternalPost(AEvent: TcxSchedulerControlEvent; ACopy: Boolean);
function IsDayNoneEmpty(ADay: Integer): Boolean;
function IsSelected(AEvent: TcxSchedulerControlEvent): Boolean; virtual;
procedure PostCloneForRecurrenceEvent(AEvent: TcxSchedulerControlEvent; ACopy: Boolean); virtual;
procedure PostCloneForSimpleEvent(AEvent: TcxSchedulerControlEvent;
ACopy: Boolean; AType: TcxEventType); virtual;
procedure SelectionAdd(AEvent: TcxSchedulerControlEvent; Shift: TShiftState); virtual;
procedure SelectionClear; virtual;
procedure SelectionUpdate; virtual;
// IUnknown
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
public
constructor Create; override;
destructor Destroy; override;
procedure CancelClones;
function CreateClones: TcxSchedulerEventList;
procedure ExtractEvents(const ADate: TDateTime; AList: TcxSchedulerEventList);
procedure ExtractUsedDays(AList: TcxSchedulerDateList);
procedure PostClones(ACopy: Boolean);
procedure PostEvent(AEvent: TcxSchedulerControlEvent);
procedure Sort(ACompare: TcxCompareEventsProc); override;
property AbsoluteCount: Integer read GetAbsoluteCount;
property AbsoluteItems[Index: Integer]: TcxSchedulerControlEvent read GetAbsoluteItem;
property AlwaysShowSelectedEvent: Boolean read FAlwaysShowSelectedEvent write FAlwaysShowSelectedEvent;
property TimeZone: Integer read FTimeZone write FTimeZone;
property Clones: TcxSchedulerFilteredEventList read FClones;
property ShowEventsWithoutResource: Boolean read FShowEventsWithoutResource write FShowEventsWithoutResource;
property SelStart: TDateTime read FSelStart write FSelStart;
property SelFinish: TDateTime read FSelFinish write FSelFinish;
property Selection: TcxSchedulerEventSelection read FSelection;
property Items[Index: Integer]: TcxSchedulerControlEvent read GetItem; default;
end;
{ TcxSchedulerOccuranceCalculator }
TcxSchedulerOccurrenceCalculator = class
protected
FDate: Integer;
FDay: Word;
FDayNumber: Integer;
FDayType: TcxDayType;
FEvent: TcxSchedulerEvent;
FFinishDate: TDateTime;
FIndex: Integer;
FMonth: Word;
FOccurDays: TDays;
FOccurrenceFinish: TDateTime;
FOccurrenceStart: TDateTime;
FPeriodicity: Integer;
FRecurCount: Integer;
FRecurrence: TcxRecurrence;
FStartOfWeek: Integer;
FVisibleFinish: TDateTime;
FVisibleStart: TDateTime;
FWeekStart: Integer;
FWorkDays: TDays;
FYear: Word;
FYearPeriodicity: Integer;
procedure CalcFirstDate;
procedure CalcNextDate;
function GetCertainDay(const ADate, ANumber: Integer; ADayType: TcxDayType): Integer;
function GetDayForMonth: Integer; virtual;
function GetDayFromOccurDays(const APrevDate, APeriodicity: Integer): Integer;
function GetSomeDay(const ADate, ANumber: Integer; AWeekEnd: Boolean): Integer;
function IsValidOccurrence: Boolean;
public
constructor Create(AEvent: TcxSchedulerEvent; const AStart, AFinish: TDateTime);
procedure CalcOccurrence(AIndex: Integer);
function GetNextOccurrence: Boolean; virtual;
function GetOccurrenceCount(AEndDate: TDateTime): Integer;
property Event: TcxSchedulerEvent read FEvent;
property Index: Integer read FIndex;
property OccurrenceFinish: TDateTime read FOccurrenceFinish;
property OccurrenceStart: TDateTime read FOccurrenceStart;
property StartOfWeek: Integer read FStartOfWeek;
property VisibleFinish: TDateTime read FVisibleFinish;
property VisibleStart: TDateTime read FVisibleStart;
property WorkDays: TDays read FWorkDays write FWorkDays;
end;
procedure cxCheckDaysList(AList: TList; var AStartDay, AFinishDay: Integer);
function cxGetRecurrenceDescriptionString(ARecurrenceInfo: TcxSchedulerEventRecurrenceInfo): string;
function cxRecurrenceInfoDataToString(const AData: TcxSchedulerEventRecurrenceInfoData): string;
function cxStringToRecurrenceInfoData(const S: string): TcxSchedulerEventRecurrenceInfoData;
const
// Options flag masks
omAllDayEvent = $0001;
omEnabled = $0002;
omReminder = $0004;
// Time line state
tlsFree = 0;
tlsTentative = 1;
tlsBusy = 2;
tlsOutOfOffice = 3;
cxDefaultEventDuration: TDateTime = 0.0034722222222;
cxMaxDate = 767010; //Dec 31 3999
cxGetRecurrenceDescriptionStringProc: TcxGetRecurrenceDescriptionStringProc =
cxGetRecurrenceDescriptionString;
implementation
uses
cxSchedulerStrs;
const
cxInvalidRecordIndex = -MaxInt;
DefInfoData: TcxSchedulerEventRecurrenceInfoData =
(Count: 10; DayNumber: 1; DayType: cxdtDay; Finish: -1;
OccurDays: []; Periodicity: 1; Recurrence: cxreDaily;
Start: 0; YearPeriodicity: 1);
PatternValidStatus: array[Boolean] of TcxRecurrenceValidStatus =
(rvsInvalidPattern, rvsValid);
function cxCompareEventsByID(AEvent1, AEvent2: TcxSchedulerEvent): Integer;
begin
Result := VarCompare(AEvent1.FSavedID, AEvent2.FSavedID);
end;
function cxIntSortProc(P1, P2: Pointer): Integer;
begin
Result := Integer(P1) - Integer(P2);
end;
function cxCompareSelectionKeys(AItem1, AItem2: TcxSelectedItemData): Integer;
begin
Result := VarCompare(AItem1.ID, AItem2.ID);
if Result = 0 then
Result := VarCompare(AItem1.ParentID, AItem2.ParentID);
if Result = 0 then
Result := AItem1.RecurrenceIndex - AItem2.RecurrenceIndex;
end;
procedure cxCheckDaysList(AList: TList; var AStartDay, AFinishDay: Integer);
begin
AList.Sort(cxIntSortProc);
AStartDay := Integer(AList[0]);
AFinishDay := Integer(AList[AList.Count - 1]);
end;
function cxGetRecurrenceDescriptionString(ARecurrenceInfo: TcxSchedulerEventRecurrenceInfo): string;
const
Weeks: array[1..5] of string = ('first', 'second', 'third', 'fourth', 'last');
Days: array[cxdtEveryDay..cxdtWeekEndDay] of string = ('day', 'weekday', 'weekend day');
EveryDays: array[Boolean] of string = ('every %d days', 'every day');
EveryMonths1: array[Boolean] of string = ('day %d of every %d months', 'day %d of every month');
EveryMonths2: array[Boolean] of string = ('the %s %s of every %d months', 'the %s %s of every month');
procedure GetDateParts(out ADayStr, AWeekStr: string);
begin
with ARecurrenceInfo do
begin
if DayNumber in [1..5] then AWeekStr := Weeks[DayNumber] else AWeekStr := '';
if DayType in [cxdtEveryDay..cxdtWeekEndDay] then
ADayStr := Days[DayType]
else
ADayStr := LongDayNames[Ord(DayType) - Ord(cxdtSunday) + 1];
end;
end;
function OccurDaysToString: string;
var
ADay: TDay;
ACount, ASaveCount: Integer;
begin
Result := '';
ACount := 0;
for ADay := Low(TDay) to High(TDay) do
if ADay in ARecurrenceInfo.OccurDays then Inc(ACount);
ASaveCount := ACount;
for ADay := Low(TDay) to High(TDay) do
if ADay in ARecurrenceInfo.OccurDays then
if ASaveCount = 1 then
begin
Result := LongDayNames[Ord(ADay) + 1];
Exit;
end
else
begin
Dec(ACount);
if ACount > 1 then
Result := Result + LongDayNames[Ord(ADay) + 1] + ', '
else if ACount = 1 then
Result := Result + LongDayNames[Ord(ADay) + 1] + ' '
else
Result := Result + 'and ' + LongDayNames[Ord(ADay) + 1];
end;
end;
var
ADayStr, AWeekStr, AMonthStr: string;
begin
Result := '';
if not Assigned(ARecurrenceInfo) or not ARecurrenceInfo.Event.IsRecurring then Exit;
with ARecurrenceInfo do
begin
case Recurrence of
cxreDaily:
if DayType = cxdtWeekDay then
Result := 'every weekday'
else
Result := Format(EveryDays[Periodicity = 1], [Periodicity]);
cxreWeekly:
if Periodicity = 1 then
Result := 'every ' + OccurDaysToString
else
Result := Format('every %d weeks on %s', [Periodicity, OccurDaysToString]);
cxreMonthly:
if DayType = cxdtDay then
Result := Format(EveryMonths1[Periodicity = 1], [DayNumber, Periodicity])
else
begin
GetDateParts(ADayStr, AWeekStr);
Result := Format(EveryMonths2[Periodicity = 1], [AWeekStr, ADayStr, Periodicity]);
end;
cxreYearly:
begin
if Periodicity in [1..12] then
AMonthStr := LongMonthNames[Periodicity]
else
AMonthStr := '';
if DayType = cxdtDay then
Result := Format('every %s %d', [AMonthStr, DayNumber])
else
begin
GetDateParts(ADayStr, AWeekStr);
Result := Format('the %s %s of %s', [AWeekStr, ADayStr, AMonthStr]);
end;
end;
end;
Result := Result + ' from ' + FormatDateTime('t', Event.Pattern.Start) +
' to ' + FormatDateTime('t', Event.Pattern.Finish);
end;
end;
function cxRecurrenceInfoDataToString(const AData: TcxSchedulerEventRecurrenceInfoData): string;
begin
SetLength(Result, SizeOf(AData));
Move(AData, Result[1], SizeOf(AData));
end;
function cxStringToRecurrenceInfoData(const S: string): TcxSchedulerEventRecurrenceInfoData;
begin
if Length(S) = SizeOf(TcxSchedulerEventRecurrenceInfoData) then
Move(S[1], Result, SizeOf(TcxSchedulerEventRecurrenceInfoData))
else
Result := DefInfoData;
end;
function cxFindEvent(AList: TList; const ID: Variant; var AEvent: TcxSchedulerEvent): Boolean;
var
L, H, I, C: Integer;
begin
Result := False;
L := 0;
H := AList.Count - 1;
while L <= H do
begin
I := (L + H) shr 1;
AEvent := TcxSchedulerEvent(AList.List^[I]);
C := VarCompare(AEvent.FSavedID, ID);
if C < 0 then
L := I + 1
else
begin
H := I - 1;
if C = 0 then
begin
Result := True;
AList.Delete(I);
Break;
end;
end;
end;
end;
{ TcxSchedulerStorageDataController }
function TcxSchedulerStorageDataController.GetItem(Index: Integer): TObject;
begin
Result := Storage.FFields.List^[Index];
end;
function TcxSchedulerStorageDataController.GetItemValueSource(
AItemIndex: Integer): TcxDataEditValueSource;
begin
Result := evsValue;
end;
function TcxSchedulerStorageDataController.GetItemID(AItem: TObject): Integer;
begin
if AItem is TcxCustomSchedulerStorageField then
Result := TcxCustomSchedulerStorageField(AItem).FIndex
else
Result := -1;
end;
procedure TcxSchedulerStorageDataController.UpdateData;
begin
Storage.UpdateData;
end;
procedure TcxSchedulerStorageDataController.UpdateItemIndexes;
begin
Storage.UpdateItemIndexes;
inherited UpdateItemIndexes;
end;
procedure TcxSchedulerStorageDataController.UpdateControl(
AInfo: TcxUpdateControlInfo);
begin
Storage.UpdateControl(AInfo);
end;
function TcxSchedulerStorageDataController.UseRecordID: Boolean;
begin
Result := True;
end;
function TcxSchedulerStorageDataController.GetStorage: TcxCustomSchedulerStorage;
begin
Result := TcxCustomSchedulerStorage(GetOwner)
end;
{ TcxCustomSchedulerStorageField }
constructor TcxCustomSchedulerStorageField.Create(Collection: TCollection);
begin
inherited Create(Collection);
Storage.ItemAdded(Self);
ValueTypeClass := TcxStringValueType;
end;
destructor TcxCustomSchedulerStorageField.Destroy;
var
AStorage: TcxCustomSchedulerStorage;
begin
AStorage := Storage;
Collection := nil;
AStorage.ItemRemoved(Self);
inherited Destroy;
end;
procedure TcxCustomSchedulerStorageField.Assign(Source: TPersistent);
begin
if Source is TcxCustomSchedulerStorageField then
ValueTypeClass := TcxCustomSchedulerStorageField(Source).ValueTypeClass
else
inherited Assign(Source);
end;
function TcxCustomSchedulerStorageField.GetDisplayName: string;
begin
Result := FName;
if Result = '' then
Result := inherited GetDisplayName;
end;
function TcxCustomSchedulerStorageField.IsValueTypeStored: Boolean;
begin
Result := ValueTypeClass <> TcxStringValueType;
end;
function TcxCustomSchedulerStorageField.GetDataController: TcxCustomDataController;
begin
Result := Storage.DataController;
end;
function TcxCustomSchedulerStorageField.GetStorage: TcxCustomSchedulerStorage;
begin
Result := TcxCustomSchedulerStorageFields(Collection).Storage;
end;
function TcxCustomSchedulerStorageField.GetValue(
AIndex: Integer): Variant;
begin
Result := Storage.Values[AIndex, FIndex];
end;
function TcxCustomSchedulerStorageField.GetValueCount: Integer;
begin
Result := Storage.EventCount;
end;
function TcxCustomSchedulerStorageField.GetValueType: string;
begin
if ValueTypeClass = nil then
Result := ''
else
Result := ValueTypeClass.Caption;
end;
function TcxCustomSchedulerStorageField.GetValueTypeClass: TcxValueTypeClass;
begin
Result := Storage.DataController.GetItemValueTypeClass(Index);
end;
procedure TcxCustomSchedulerStorageField.SetName(
const AValue: string);
begin
if FName <> AValue then
begin
FName := AValue;
Changed(True);
end;
end;
procedure TcxCustomSchedulerStorageField.SetValue(
AIndex: Integer; const AValue: Variant);
begin
Storage.Values[AIndex, FIndex] := AValue;
end;
procedure TcxCustomSchedulerStorageField.SetValueType(
const AValue: string);
begin
if ValueType <> AValue then
ValueTypeClass := cxValueTypeClassList.ItemByCaption(AValue);
end;
procedure TcxCustomSchedulerStorageField.SetValueTypeClass(
AValue: TcxValueTypeClass);
begin
Storage.DataController.ChangeValueTypeClass(Index, AValue);
end;
{ TcxCustomSchedulerStorageFields }
function TcxCustomSchedulerStorageFields.FindFieldByName(const AName: string): TcxCustomSchedulerStorageField;
var
I: Integer;
begin
for I := 0 to Count - 1 do
begin
Result := TcxCustomSchedulerStorageField(inherited Items[I]);
if AnsiSameText(AName, Result.Name) then Exit;
end;
Result := nil;
end;
function TcxCustomSchedulerStorageFields.GetOwner: TPersistent;
begin
Result := FOwner;
end;
procedure TcxCustomSchedulerStorageFields.Update(Item: TCollectionItem);
begin
inherited Update(Item);
Storage.Changed;
end;
function TcxCustomSchedulerStorageFields.GetStorage: TcxCustomSchedulerStorage;
begin
Result := TcxCustomSchedulerStorage(GetOwner);
end;
{ TcxSchedulerStorageFields }
function TcxSchedulerStorageFields.Add: TcxSchedulerStorageField;
begin
Result := TcxSchedulerStorageField(inherited Add);
end;
function TcxSchedulerStorageFields.ItemByName(
const AName: string): TcxSchedulerStorageField;
begin
Result := TcxSchedulerStorageField(FindFieldByName(AName));
end;
function TcxSchedulerStorageFields.GetItem(
AIndex: Integer): TcxSchedulerStorageField;
begin
Result := TcxSchedulerStorageField(inherited Items[AIndex]);
end;
procedure TcxSchedulerStorageFields.SetItem(
AIndex: Integer; AValue: TcxSchedulerStorageField);
begin
inherited Items[AIndex].Assign(AValue);
end;
{ TcxSchedulerEventRecurrenceInfo }
constructor TcxSchedulerEventRecurrenceInfo.Create(
AOwner: TcxSchedulerEvent);
begin
FOwner := AOwner;
end;
procedure TcxSchedulerEventRecurrenceInfo.Assign(Source: TPersistent);
var
S: string;
begin
if Source is TcxSchedulerEventRecurrenceInfo then
begin
if GetValue(S) then
SetValue(S)
else
SetValue('');
end
else
inherited Assign(Source);
end;
function TcxSchedulerEventRecurrenceInfo.GetValidStatus: TcxRecurrenceValidStatus;
function IntersectOccurrences(APrevFinish, AStart: TDateTime): Boolean;
begin
if FOwner.AllDayEvent then
Result := DateOf(AStart) < DateOf(APrevFinish)
else
Result := DateOf(AStart) <= DateOf(APrevFinish);
end;
var
AFinish: TDateTime;
begin
if not FOwner.IsRecurring then
begin
Result := rvsValid;
Exit;
end;
case Recurrence of
cxreDaily: Result := GetDailyPatternStatus;
cxreWeekly: Result := GetWeeklyPatternStatus;
cxreMonthly: Result := GetMonthlyPatternStatus;
else Result := GetYearlyPatternStatus;
end;
if Result = rvsInvalidPattern then Exit;
with TcxSchedulerOccurrenceCalculator.Create(FOwner,
FOwner.RecurrenceInfo.Start, cxMaxDate) do
try
// find a first occurrence
if GetNextOccurrence then
begin
AFinish := OccurrenceFinish;
if not (FOwner.RecurrenceInfo.Count in [0, 1]) then
begin
if not GetNextOccurrence then
begin
Result := rvsInvalidDuration;
Exit;
end;
end;
if (Index > 0) and IntersectOccurrences(AFinish, OccurrenceStart) then
Result := rvsInvalidDuration;
end
else
Result := rvsInvalidDuration;
finally
Free;
end;
end;
procedure TcxSchedulerEventRecurrenceInfo.Validate;
begin
with TcxSchedulerOccurrenceCalculator.Create(FOwner,
FOwner.RecurrenceInfo.Start, cxMaxDate) do
try
if GetNextOccurrence then
FOwner.MoveTo(OccurrenceStart)
else
cxSchedulerError(cxGetResourceString(@scxWrongPattern));
finally
Free;
end;
end;
procedure TcxSchedulerEventRecurrenceInfo.AssignDefaultValues;
begin
Count := -1;
DayNumber := 1;
DayType := cxdtDay;
Finish := -1;
OccurDays := [TDay(DayOfWeek(Event.Start) - 1)];
Periodicity := 1;
Recurrence := cxreWeekly;
YearPeriodicity := 1;
end;
function TcxSchedulerEventRecurrenceInfo.GetData: TcxSchedulerEventRecurrenceInfoData;
var
S: string;
begin
if GetValue(S) then
Result := cxStringToRecurrenceInfoData(S)
else
Result := DefInfoData;
end;
function TcxSchedulerEventRecurrenceInfo.GetOwner: TPersistent;
begin
Result := FOwner;
end;
function TcxSchedulerEventRecurrenceInfo.GetValue(
var AValue: string): Boolean;
begin
Result := FOwner.GetRecurrenceInfoValue(AValue);
end;
procedure TcxSchedulerEventRecurrenceInfo.SetDataItem(
AOffset: Pointer; ASize: Integer; const AValue);
var
S: string;
begin
Dec(Integer(AOffset), Integer(@DefInfoData));
if not GetValue(S) then
S := cxRecurrenceInfoDataToString(DefInfoData);
Move(AValue, S[1 + Integer(AOffset)], ASize);
SetValue(S);
end;
procedure TcxSchedulerEventRecurrenceInfo.SetValue(
const AValue: string);
begin
FOwner.SetRecurrenceInfoValue(AValue);
end;
function TcxSchedulerEventRecurrenceInfo.GetDailyPatternStatus: TcxRecurrenceValidStatus;
begin
if DayType = cxdtEveryDay then
Result := PatternValidStatus[Periodicity > 0]
else
Result := PatternValidStatus[(DayType = cxdtWeekDay) and (Periodicity = 1)]
end;
function TcxSchedulerEventRecurrenceInfo.GetMonthlyPatternStatus: TcxRecurrenceValidStatus;
begin
if DayType = cxdtDay then
begin
Result := PatternValidStatus[(Periodicity > 0) and (DayNumber in [1..31])];
if (Result = rvsValid) and (DayNumber in [29..31]) then
Result := rvsReplaceOccurrenceDate;
end
else
Result := PatternValidStatus[Periodicity > 0];
end;
function TcxSchedulerEventRecurrenceInfo.GetWeeklyPatternStatus: TcxRecurrenceValidStatus;
begin
Result := PatternValidStatus[(Periodicity > 0) and (OccurDays <> [])]
end;
function TcxSchedulerEventRecurrenceInfo.GetYearlyPatternStatus: TcxRecurrenceValidStatus;
begin
if DayType = cxdtDay then
Result := PatternValidStatus[(Periodicity in [1..12]) and
(DayNumber >=1) and (DayNumber <= DaysPerMonth(2000, Periodicity))]
else
Result := PatternValidStatus[(Periodicity in [1..12])];
end;
function TcxSchedulerEventRecurrenceInfo.GetCount: Integer;
begin
Result := GetData.Count;
end;
function TcxSchedulerEventRecurrenceInfo.GetDayNumber: Integer;
begin
Result := GetData.DayNumber;
end;
function TcxSchedulerEventRecurrenceInfo.GetDayType: TcxDayType;
begin
Result := GetData.DayType;
end;
function TcxSchedulerEventRecurrenceInfo.GetFinish: TDateTime;
begin
Result := GetData.Finish - FOwner.TimeBias;
end;
function TcxSchedulerEventRecurrenceInfo.GetOccurDays: TDays;
begin
Result := GetData.OccurDays;
end;
function TcxSchedulerEventRecurrenceInfo.GetPeriodicity: Integer;
begin
Result := GetData.Periodicity;
end;
function TcxSchedulerEventRecurrenceInfo.GetRecurrence: TcxRecurrence;
begin
Result := GetData.Recurrence;
end;
function TcxSchedulerEventRecurrenceInfo.GetStart: TDateTime;
begin
Result := DateOf(FOwner.Start);
end;
function TcxSchedulerEventRecurrenceInfo.GetStorage: TcxCustomSchedulerStorage;
begin
Result := FOwner.Storage;
end;
function TcxSchedulerEventRecurrenceInfo.GetYearPeriodicity: Integer;
begin
Result := GetData.YearPeriodicity;
end;
procedure TcxSchedulerEventRecurrenceInfo.SetCount(
const AValue: Integer);
begin
SetDataItem(@DefInfoData.Count, SizeOf(Integer), AValue);;
end;
procedure TcxSchedulerEventRecurrenceInfo.SetDayNumber(
const AValue: Integer);
begin
SetDataItem(@DefInfoData.DayNumber, SizeOf(Integer), AValue);;
end;
procedure TcxSchedulerEventRecurrenceInfo.SetDayType(
const AValue: TcxDayType);
begin
SetDataItem(@DefInfoData.DayType, SizeOf(TcxDayType), AValue);;
end;
procedure TcxSchedulerEventRecurrenceInfo.SetFinish(
AValue: TDateTime);
begin
AValue := TcxSchedulerDateTimeHelper.RoundTime(AValue) + FOwner.TimeBias;
SetDataItem(@DefInfoData.Finish, SizeOf(AValue), AValue);
end;
procedure TcxSchedulerEventRecurrenceInfo.SetOccurDays(
const AValue: TDays);
begin
SetDataItem(@DefInfoData.OccurDays, SizeOf(TDays), AValue);;
end;
procedure TcxSchedulerEventRecurrenceInfo.SetPeriodicity(
const AValue: Integer);
begin
SetDataItem(@DefInfoData.Periodicity, SizeOf(Integer), AValue);
end;
procedure TcxSchedulerEventRecurrenceInfo.SetRecurrence(
const AValue: TcxRecurrence);
begin
SetDataItem(@DefInfoData.Recurrence, SizeOf(TcxRecurrence), AValue);
end;
procedure TcxSchedulerEventRecurrenceInfo.SetStart(
const AValue: TDateTime);
begin
FOwner.MoveTo(AValue);
end;
procedure TcxSchedulerEventRecurrenceInfo.SetYearPeriodicity(
const AValue: Integer);
begin
SetDataItem(@DefInfoData.YearPeriodicity, SizeOf(Integer), AValue);
end;
{ TcxSchedulerEvent }
constructor TcxSchedulerEvent.Create(
AStorage: TcxCustomSchedulerStorage);
begin
Create(AStorage, -1);
BeginEditing;
AssignDefaultValues;
end;
constructor TcxSchedulerEvent.Create(
AStorage: TcxCustomSchedulerStorage; ARecordIndex: Integer);
begin
FStorage := AStorage;
FRecordIndex := ARecordIndex;
FRecurrenceInfo := CreateRecurrenceInfo;
FRecurrenceInfo.FOwner := Self;
end;
destructor TcxSchedulerEvent.Destroy;
begin
FStorage.DoDestroyEvent(Self);
FRecurrenceInfo.Free;
inherited Destroy;
end;
procedure TcxSchedulerEvent.Assign(Source: TPersistent);
var
I: Integer;
begin
if Source is TcxSchedulerEvent then
begin
BeginEditing;
FSkipModified := True;
try
for I := 0 to ValueCount - 1 do
SetValueByIndex(I, TcxSchedulerEvent(Source).GetValueByIndex(I));
Start := TcxSchedulerEvent(Source).Start;
Finish := TcxSchedulerEvent(Source).Finish;
finally
FIsDataValid := False;
EndEditing;
FSkipModified := False;
end;
end;
end;
procedure TcxSchedulerEvent.BeginEditing;
var
I: Integer;
begin
if not IsEditing then
begin
SetLength(FEditValues, ValueCount);
for I := 0 to ValueCount - 1 do
FEditValues[I] := GetValueByIndex(I);
end;
Inc(FEditCount);
end;
procedure TcxSchedulerEvent.Cancel;
begin
IsModified := False;
if FEditCount = 1 then
begin
Dec(FEditCount);
if FEditCount = 0 then
SetLength(FEditValues, 0);
Storage.CancelEvent(Self);
end;
end;
procedure TcxSchedulerEvent.EndEditing;
begin
if FEditCount = 0 then Exit;
try
if (FEditCount = 1) and not IsNewEvent then
PostEditingData;
finally
Dec(FEditCount);
if FEditCount = 0 then
SetLength(FEditValues, 0);
end;
end;
procedure TcxSchedulerEvent.Delete;
begin
if Self = nil then Exit;
case EventType of
etCustom:
EventType := etException;
etOccurrence:
begin
Storage.BeginUpdate;
try
with Storage.CreateEvent do
begin
Assign(Self);
ParentID := Self.ID;
EventType := etException;
end;
finally
Storage.EndUpdate;
end;
end;
else
Storage.DoDeleteEvent(RecordIndex);
end;
end;
procedure TcxSchedulerEvent.DeleteExceptions;
begin
if not HasExceptions then Exit;
Storage.BeginUpdate;
try
while FLink <> nil do
begin
Storage.DoDeleteEvent(FLink.RecordIndex);
FLink := FLink.FLink
end;
finally
Storage.EndUpdate;
end;
end;
function TcxSchedulerEvent.HasExceptions: Boolean;
begin
Result := (EventType = etPattern) and (Link <> nil);
end;
function TcxSchedulerEvent.GetCustomFieldValueByIndex(AIndex: Integer): Variant;
begin
Result := GetValueByIndex(TcxCustomSchedulerStorageField(Storage.Fields.Items[AIndex]).Index);
end;
function TcxSchedulerEvent.GetCustomFieldValueByName(
const AName: String): Variant;
var
AField: TcxCustomSchedulerStorageField;
begin
AField := Storage.Fields.FindFieldByName(AName);
if AField <> nil then
Result := GetValueByIndex(AField.Index)
else
cxSchedulerError(scxInvalidFieldName);
end;
function TcxSchedulerEvent.GetCustomFieldValue(
ACustomField: TcxCustomSchedulerStorageField): Variant;
begin
if (ACustomField <> nil) and (ACustomField.Storage = Storage) then
Result := GetValueByIndex(ACustomField.Index)
else
cxSchedulerError(scxInvalidCustomField);
end;
procedure TcxSchedulerEvent.SetCustomFieldValueByIndex(AIndex: Integer;
const AValue: Variant);
begin
SetValueByIndex(TcxCustomSchedulerStorageField(Storage.Fields.Items[AIndex]).Index, AValue);
end;
procedure TcxSchedulerEvent.SetCustomFieldValueByName(const AName: string;
const AValue: Variant);
var
AField: TcxCustomSchedulerStorageField;
begin
AField := Storage.Fields.FindFieldByName(AName);
if AField <> nil then
SetValueByIndex(AField.Index, AValue)
else
cxSchedulerError(scxInvalidFieldName);
end;
procedure TcxSchedulerEvent.SetCustomFieldValue(
ACustomField: TcxCustomSchedulerStorageField; const AValue: Variant);
begin
if (ACustomField <> nil) and (ACustomField.Storage = Storage) then
SetValueByIndex(ACustomField.Index, AValue)
else
cxSchedulerError(scxInvalidCustomField);
end;
function TcxSchedulerEvent.GetResourceItem: TcxSchedulerStorageResourceItem;
var
I: Integer;
begin
for I := 0 to Storage.ResourceCount - 1 do
begin
Result := Storage.Resources.ResourceItems[I];
if IsResourceEvent(Result, False) then
Exit;
end;
Result := nil;
end;
function TcxSchedulerEvent.GetRecurrenceChain: TcxSchedulerEventList;
var
ALink: TcxSchedulerEvent;
begin
Result := TcxSchedulerEventList.Create;
if EventType = etPattern then
begin
ALink := Link;
while ALink <> nil do
begin
Result.Add(ALink);
ALink := ALink.Link;
end;
end;
end;
function TcxSchedulerEvent.IsDayEvent(ADate: TDateTime): Boolean;
begin
Result := False;
if not FIsDataValid then
UpdateTemporaryData;
ADate := DateOf(ADate);
if FFinish > ADate then
Result := (DateOf(FStart) <= ADate)
else
if FFinish = ADate then
Result := DateOf(FStart) = ADate;
end;
function TcxSchedulerEvent.IsRecurring: Boolean;
begin
Result := EventType in [etPattern..etCustom];
end;
function TcxSchedulerEvent.IsResourceEvent(
AResource: TcxSchedulerStorageResourceItem; AllowUnassigned: Boolean): Boolean;
begin
Result := (AResource = nil) or (AllowUnassigned and VarIsNull(ResourceID)) or
(VarCompare(AResource.ResourceID, ResourceID) = 0);
end;
procedure TcxSchedulerEvent.MoveTo(const AStartTime: TDateTime);
var
ADuration: Double;
begin
BeginEditing;
try
ADuration := Duration;
Start := AStartTime;
Duration := ADuration;
finally
EndEditing;
end;
end;
procedure TcxSchedulerEvent.Post;
begin
if (FEditCount = 1) and IsNewEvent then
FStorage.PostEvent(Self);
end;
procedure TcxSchedulerEvent.AssignDefaultValues;
begin
AllDayEvent := False;
Caption := '';
Enabled := True;
EventType := etNone;
LabelColor := clDefault;
Location := '';
Message := '';
RecurrenceIndex := -1;
Reminder := False; //not implemented yet
ReminderTime := 15; //not implemented yet
Start := Now;
Finish := Start + cxDefaultEventDuration;
State := tlsBusy;
RecurrenceInfo.AssignDefaultValues;
end;
procedure TcxSchedulerEvent.CheckRecurrenceLink(AEvent: TcxSchedulerEvent);
begin
if (AEvent.EventType in [etCustom, etException]) and VarEquals(ID, AEvent.ParentID) then
begin
AEvent.FPattern := Self;
AEvent.FLink := FLink;
FLink := AEvent;
end;
end;
function TcxSchedulerEvent.CreateRecurrenceInfo: TcxSchedulerEventRecurrenceInfo;
begin
Result := TcxSchedulerEventRecurrenceInfo.Create(Self);
end;
function TcxSchedulerEvent.GetOccurrenceByIndex(
AIndex: Integer; var AOccurrence: TcxSchedulerEvent): Boolean;
begin
Result := False;
if FLink = nil then Exit;
AOccurrence := FLink;
while (AOccurrence <> nil) and (AOccurrence.RecurrenceIndex <> AIndex) do
AOccurrence := AOccurrence.FLink;
Result := (AOccurrence <> nil) and (AOccurrence.RecurrenceIndex = AIndex);
end;
function TcxSchedulerEvent.GetOwner: TPersistent;
begin
Result := FStorage;
end;
function TcxSchedulerEvent.GetRecurrenceInfoValue(
var AValue: string): Boolean;
begin
AValue := GetValueDef(FStorage.FRecurrenceInfoField, '');
Result := AValue <> '';
end;
function TcxSchedulerEvent.GetValueByIndex(AIndex: Integer): Variant;
begin
if FRecordIndex = cxInvalidRecordIndex then
Result := Null
else
Result := FStorage.GetValue(RecordIndex, AIndex);
end;
function TcxSchedulerEvent.GetValueDef(
AField: TcxCustomSchedulerStorageField; const ADefValue: Variant): Variant;
begin
if not IsEditing then
Result := GetValueByIndex(AField.Index)
else
Result := FEditValues[AField.Index];
if VarType(Result) in [varNull, varEmpty] then
Result := ADefValue;
end;
procedure TcxSchedulerEvent.Modified;
begin
FIsModified := True;
end;
procedure TcxSchedulerEvent.PostEditingData;
var
ACount: Integer;
begin
ACount := Storage.DataController.RecordCount;
if IsModified then
begin
Storage.BeginUpdate;
try
FStorage.PostEditingData(Self);
finally
Storage.EndUpdate;
end;
end;
if Storage.DataController.RecordCount < ACount then
FRecordIndex := cxInvalidRecordIndex;
end;
procedure TcxSchedulerEvent.SetRecordIndex(
const AIndex: Integer);
begin
if AIndex <> -1 then
FSavedID := FStorage.DataController.GetRecordID(AIndex)
else
FSavedID := Null;
FIsDataValid := False;
FRecordIndex := AIndex;
FLink := nil;
end;
procedure TcxSchedulerEvent.SetRecurrenceInfoValue(
const AValue: string);
begin
SetValue(FStorage.FRecurrenceInfoField, AValue);
end;
procedure TcxSchedulerEvent.SetValue(
AField: TcxCustomSchedulerStorageField; const AValue: Variant);
begin
SetValueByIndex(AField.Index, AValue);
end;
procedure TcxSchedulerEvent.SetValueByIndex(
AIndex: Integer; const AValue: Variant);
begin
if (FRecordIndex = cxInvalidRecordIndex) or
(IsEditing and VarEquals(FEditValues[AIndex], AValue)) or
VarEquals(GetValueByIndex(AIndex), AValue) then Exit;
Modified;
BeginEditing;
try
FEditValues[AIndex] := AValue
finally
EndEditing;
end;
end;
function TcxSchedulerEvent.TimeBias: Double;
begin
Result := Storage.TimeBias;
end;
procedure TcxSchedulerEvent.UpdateTemporaryData;
begin
FStart := TDateTime(GetValueDef(FStorage.FStartField, 0)) - TimeBias;
FFinish := TDateTime(GetValueDef(FStorage.FFinishField, 0)) - TimeBias;
FOptions := GetValueDef(FStorage.FOptionsField, 0);
FIsDataValid := True;
end;
function TcxSchedulerEvent.GetAllDayEvent: Boolean;
begin
Result := (GetOptionsFlag and omAllDayEvent) <> 0;
end;
function TcxSchedulerEvent.GetCaption: string;
begin
Result := GetValueDef(FStorage.FCaptionField, '');
end;
function TcxSchedulerEvent.GetDuration: TDateTime;
begin
Result := TcxSchedulerDateTimeHelper.RoundTime(Finish - Start);
end;
function TcxSchedulerEvent.GetEditValue(AIndex: Integer): Variant;
begin
if IsEditing then
Result := FEditValues[AIndex]
else
Result := Null;
end;
function TcxSchedulerEvent.GetEnabled: Boolean;
begin
Result := (GetOptionsFlag and omEnabled) <> 0;
end;
function TcxSchedulerEvent.GetEventType: TcxEventType;
begin
Result := GetValueDef(FStorage.FEventTypeField, etNone);
end;
function TcxSchedulerEvent.GetFinish: TDateTime;
begin
if not FIsDataValid then
UpdateTemporaryData;
Result := FFinish;
end;
function TcxSchedulerEvent.GetID: Variant;
begin
Result := FStorage.GetRecordId(RecordIndex);
end;
function TcxSchedulerEvent.GetIsNewEvent: Boolean;
begin
Result := (FRecordIndex = -1) and
(FStorage.FNewEvents.IndexOf(Self) <> - 1);
end;
function TcxSchedulerEvent.GetIsEditing: Boolean;
begin
Result := FEditCount > 0;
end;
function TcxSchedulerEvent.GetLabelColor: Integer;
begin
Result := GetValueDef(FStorage.FLabelColorField, clDefault);
end;
function TcxSchedulerEvent.GetLocation: string;
begin
Result := GetValueDef(FStorage.FLocationField, '');
end;
function TcxSchedulerEvent.Getmessage: string;
begin
Result := GetValueDef(FStorage.FMessageField, '');
end;
function TcxSchedulerEvent.GetOptionsFlag: Integer;
begin
if not FIsDataValid then
UpdateTemporaryData;
Result := FOptions;
end;
function TcxSchedulerEvent.GetParentID: Variant;
begin
Result := GetValueDef(FStorage.FParentIDField, Integer(-2));
end;
function TcxSchedulerEvent.GetReadOnly: Boolean;
begin
Result := (GetResourceItem <> nil) and GetResourceItem.ReadOnly;
end;
function TcxSchedulerEvent.GetRecurrenceIndex: Integer;
begin
Result := GetValueDef(FStorage.FRecurrenceIndexField, 0)
end;
function TcxSchedulerEvent.GetReminder: Boolean;
begin
Result := (GetOptionsFlag and omReminder) <> 0;
end;
function TcxSchedulerEvent.GetReminderTime: Integer;
begin
Result := GetValueDef(FStorage.FReminderTimeField, Integer(-2));
end;
function TcxSchedulerEvent.GetResourceID: Variant;
begin
Result := GetValueDef(FStorage.FResourceIDField, Null);
end;
function TcxSchedulerEvent.GetStart: TDateTime;
begin
if not FIsDataValid then
UpdateTemporaryData;
Result := FStart;
end;
function TcxSchedulerEvent.GetState: Integer;
begin
Result := GetValueDef(FStorage.FStateField, 0);
end;
function TcxSchedulerEvent.GetValueCount: Integer;
begin
Result := FStorage.FieldCount;
end;
procedure TcxSchedulerEvent.SetAllDayEvent(const AValue: Boolean);
begin
if SetOptionsFlag(omAllDayEvent, AValue) then
begin
if AValue then
begin
Start := DateOf(Start);
if DateOf(Finish) <= Start then
Finish := Start + 1
else
Finish := DateOf(Finish)
end
else
begin
Start := DateOf(Start) + cxTime8AM;
Finish := DateOf(Finish) + cxTime8AM + cxHalfHour;
end;
end;
end;
procedure TcxSchedulerEvent.SetCaption(const AValue: string);
begin
SetValue(FStorage.FCaptionField, AValue);
end;
procedure TcxSchedulerEvent.SetDuration(const AValue: TDateTime);
begin
Finish := Start + TcxSchedulerDateTimeHelper.RoundTime(AValue);
end;
procedure TcxSchedulerEvent.SetEditValue(AIndex: Integer;
const AValue: Variant);
begin
if not IsEditing then Exit;
FEditValues[AIndex] := AValue;
end;
procedure TcxSchedulerEvent.SetEnabled(const AValue: Boolean);
begin
SetOptionsFlag(omEnabled, AValue);
end;
procedure TcxSchedulerEvent.SetEventType(AValue: TcxEventType);
var
AResetRecurrence: Boolean;
begin
AResetRecurrence := FStorage.IsRecurrenceAvailable;
if not AResetRecurrence then
AValue := etNone;
AResetRecurrence := AResetRecurrence and (AValue = etNone) and
(AValue <> EventType);
SetValue(FStorage.FEventTypeField, AValue);
if AResetRecurrence then
RecurrenceInfo.AssignDefaultValues;
end;
procedure TcxSchedulerEvent.SetFinish(const AValue: TDateTime);
begin
FFinish := TcxSchedulerDateTimeHelper.RoundTime(AValue);
SetValue(FStorage.FFinishField, FFinish + TimeBias);
end;
procedure TcxSchedulerEvent.SetLabelColor(const AValue: Integer);
begin
SetValue(FStorage.FLabelColorField, AValue);
end;
procedure TcxSchedulerEvent.SetLocation(const AValue: string);
begin
SetValue(FStorage.FLocationField, AValue);
end;
procedure TcxSchedulerEvent.SetMessage(const AValue: string);
begin
SetValue(FStorage.FMessageField, AValue);
end;
function TcxSchedulerEvent.SetOptionsFlag(const AMask: Integer;
AValue: Boolean): Boolean;
begin
if not FIsDataValid then
UpdateTemporaryData;
Result := (FOptions and AMask = AMask) <> AValue;
if AValue then
FOptions := FOptions or AMask
else
FOptions := FOptions and not AMask;
SetValue(FStorage.FOptionsField, FOptions);
end;
procedure TcxSchedulerEvent.SetParentID(const AValue: Variant);
begin
SetValue(FStorage.FParentIDField, AValue);
end;
procedure TcxSchedulerEvent.SetRecurrenceIndex(const AValue: Integer);
begin
SetValue(FStorage.FRecurrenceIndexField, AValue);
end;
procedure TcxSchedulerEvent.SetRecurrenceInfo(
AValue: TcxSchedulerEventRecurrenceInfo);
begin
FRecurrenceInfo.Assign(AValue);
end;
procedure TcxSchedulerEvent.SetReminder(const AValue: Boolean);
begin
SetOptionsFlag(omReminder, AValue);
end;
procedure TcxSchedulerEvent.SetReminderTime(const AValue: Integer);
begin
SetValue(FStorage.FReminderTimeField, AValue);
end;
procedure TcxSchedulerEvent.SetResourceID(const AValue: Variant);
begin
SetValue(FStorage.FResourceIDField, AValue);
end;
procedure TcxSchedulerEvent.SetStart(const AValue: TDateTime);
begin
FStart := TcxSchedulerDateTimeHelper.RoundTime(AValue);
SetValue(FStorage.FStartField, FStart + TimeBias);
end;
procedure TcxSchedulerEvent.SetState(const AValue: Integer);
begin
SetValue(FStorage.FStateField, AValue);
end;
{ TcxSchedulerControlEvent }
constructor TcxSchedulerControlEvent.Create(
AStorage: TcxCustomSchedulerStorage);
begin
FStorage := AStorage;
SetLength(FValues, AStorage.FieldCount);
ClearValues;
SetRecordIndex(-1);
FRecurrenceInfo := CreateRecurrenceInfo;
FRecurrenceInfo.FOwner := Self;
AssignDefaultValues;
end;
constructor TcxSchedulerControlEvent.Create(ASource: TcxSchedulerEvent);
begin
SetLength(FValues, ASource.ValueCount);
ClearValues;
inherited Create(ASource.FStorage);
FIsClone := ASource is TcxSchedulerControlEvent;
SetRecordIndex(ASource.RecordIndex);
FSource := ASource;
Assign(ASource);
end;
constructor TcxSchedulerControlEvent.Create(
ASource: TcxSchedulerEvent; const AStart, AFinish: TDateTime);
begin
Create(ASource);
Start := AStart;
Finish := AFinish;
end;
destructor TcxSchedulerControlEvent.Destroy;
begin
if FIsClone and (Source is TcxSchedulerControlEvent) then
TcxSchedulerControlEvent(Source).FIsSource := False;
inherited Destroy;
end;
procedure TcxSchedulerControlEvent.Assign(Source: TPersistent);
function GetPattern: TcxSchedulerEvent;
begin
if IsClone then
Result := TcxSchedulerEvent(Source).FPattern
else
if TcxSchedulerEvent(Source).EventType = etPattern then
Result := TcxSchedulerEvent(Source)
else
Result := nil;
end;
var
I: Integer;
begin
if Source is TcxSchedulerEvent then
begin
for I := 0 to ValueCount - 1 do
FValues[I] := TcxSchedulerEvent(Source).GetValueByIndex(I);
FIsDataValid := False;
FPattern := GetPattern;
end;
end;
procedure TcxSchedulerControlEvent.BeginEditing;
begin
// do nothing for
end;
procedure TcxSchedulerControlEvent.Delete;
begin
Selected := False;
if EventType = etOccurrence then
inherited Delete
else
Source.Delete;
end;
procedure TcxSchedulerControlEvent.EndEditing;
begin
end;
function TcxSchedulerControlEvent.GetValueByIndex(
AIndex: Integer): Variant;
begin
Result := FValues[AIndex];
if (Pattern <> nil) and VarIsNull(Result) and Storage.CanGetValueFromPattern(AIndex) then
Result := Pattern.GetValueByIndex(AIndex);
end;
procedure TcxSchedulerControlEvent.ClearValues;
var
I: Integer;
begin
for I := 0 to Length(FValues) - 1 do
FValues[I] := Null;
end;
procedure TcxSchedulerControlEvent.SetValueByIndex(
AIndex: Integer; const AValue: Variant);
begin
Modified;
FValues[AIndex] := AValue;
end;
function TcxSchedulerControlEvent.TimeBias: Double;
begin
Result := FTimeBias;
end;
function TcxSchedulerControlEvent.GetSelected: Boolean;
begin
if SelectionAdapter <> nil then
Result := SelectionAdapter.IsSelected(Self)
else
Result := FIsClone;
end;
procedure TcxSchedulerControlEvent.SetSelected(AValue: Boolean);
begin
if (AValue <> GetSelected) and (SelectionAdapter <> nil) then
SelectionAdapter.Add(Self, [ssCtrl]);
end;
{ TcxSchedulerStorageResourceItems }
constructor TcxSchedulerStorageResourceItems.Create(
AOwner: TcxSchedulerStorageResources;
AItemClass: TcxSchedulerStorageResourceItemClass);
begin
FOwner := AOwner;
inherited Create(AItemClass);
end;
function TcxSchedulerStorageResourceItems.Add: TcxSchedulerStorageResourceItem;
begin
Result := TcxSchedulerStorageResourceItem(inherited Add);
end;
function TcxSchedulerStorageResourceItems.GetOwner: TPersistent;
begin
Result := FOwner;
end;
procedure TcxSchedulerStorageResourceItems.Update(Item: TCollectionItem);
begin
inherited Update(Item);
Storage.Changed;
end;
function TcxSchedulerStorageResourceItems.GetItem(
AIndex: Integer): TcxSchedulerStorageResourceItem;
begin
Result := TcxSchedulerStorageResourceItem(inherited Items[AIndex]);
end;
function TcxSchedulerStorageResourceItems.GetStorage: TcxCustomSchedulerStorage;
begin
Result := FOwner.Storage;
end;
procedure TcxSchedulerStorageResourceItems.SetItem(
AIndex: Integer; AValue: TcxSchedulerStorageResourceItem);
begin
Items[AIndex].Assign(AValue);
end;
function TcxSchedulerStorageResourceItems.GetVisibleResource(
AIndex: Integer): TcxSchedulerStorageResourceItem;
var
I: Integer;
begin
Result := nil;
for I := 0 to Count - 1 do
if GetItem(I).Visible then
begin
if AIndex = 0 then
begin
Result := GetItem(I);
Break;
end;
Dec(AIndex);
end;
end;
function TcxSchedulerStorageResourceItems.GetVisibleResourceCount: Integer;
var
I: Integer;
begin
Result := 0;
for I := 0 to Count - 1 do
if GetItem(I).Visible then Inc(Result);
end;
{ TcxSchedulerStorageResourceItem }
constructor TcxSchedulerStorageResourceItem.Create(Collection: TCollection);
begin
FColor := clDefault;
FVisible := True;
FReadOnly := False;
inherited Create(Collection);
end;
procedure TcxSchedulerStorageResourceItem.Assign(Source: TPersistent);
begin
if Source is TcxSchedulerStorageResourceItem then
begin
FColor := TcxSchedulerStorageResourceItem(Source).FColor;
FName := TcxSchedulerStorageResourceItem(Source).FName;
FReadOnly := TcxSchedulerStorageResourceItem(Source).FReadOnly;
FResourceID := TcxSchedulerStorageResourceItem(Source).FResourceID;
FVisible := TcxSchedulerStorageResourceItem(Source).FVisible;
end
else
inherited Assign(Source);
end;
function TcxSchedulerStorageResourceItem.GetDisplayName: string;
begin
Result := TcxSchedulerStorageResourceItems(Collection).
Resources.DoGetResourceName(Self);
end;
procedure TcxSchedulerStorageResourceItem.SetName(
const AValue: string);
begin
if AValue = FName then Exit;
FName := AValue;
Changed(True);
end;
procedure TcxSchedulerStorageResourceItem.SetColor(
const AValue: TColor);
begin
FColor := AValue;
Changed(True);
end;
procedure TcxSchedulerStorageResourceItem.SetResourceID(
const AValue: Variant);
begin
FResourceID := AValue;
Changed(True);
end;
procedure TcxSchedulerStorageResourceItem.SetVisible(const AValue: Boolean);
begin
FVisible := AValue;
Changed(True);
end;
function TcxSchedulerStorageResourceItem.GetResources: TcxSchedulerStorageResources;
begin
Result := TcxSchedulerStorageResourceItems(Collection).Resources;
end;
{ TcxSchedulerStorageResources }
constructor TcxSchedulerStorageResources.Create(
AOwner: TcxCustomSchedulerStorage);
begin
FOwner := AOwner;
inherited Create(AOwner);
FItems := CreateItems;
end;
destructor TcxSchedulerStorageResources.Destroy;
begin
FItems.Free;
inherited Destroy;
end;
procedure TcxSchedulerStorageResources.Assign(
Source: TPersistent);
begin
if Source is TcxSchedulerStorageResources then
FItems.Assign(TcxSchedulerStorageResources(Source).Items);
end;
function TcxSchedulerStorageResources.GetResourceName(
AResource: TcxSchedulerStorageResourceItem): string;
begin
Result := DoGetResourceName(AResource);
end;
function TcxSchedulerStorageResources.GetObjectName: string;
begin
if Storage.StoringName <> '' then
Result := Storage.StoringName
else
Result := Storage.Name;
end;
function TcxSchedulerStorageResources.GetProperties(
AProperties: TStrings): Boolean;
var
I: Integer;
begin
Result := ResourceItems.Count > 0;
for I := 0 to ResourceItems.Count - 1 do
with ResourceItems[I] do
AProperties.Add('Resource' + IntToHex(I, 8));
end;
procedure TcxSchedulerStorageResources.GetPropertyValue(const AName: string;
var AValue: Variant);
var
AID: Integer;
AItem: TcxSchedulerStorageResourceItem;
begin
if ResourceItems.Count = 0 then Exit;
if Pos('Resource', AName) = 1 then
begin
AID := StrToIntDef('$' + Copy(AName, 9, 8), -1);
AItem := TcxSchedulerStorageResourceItem(ResourceItems.FindItemID(AID));
if AItem <> nil then
AValue := ((AItem.Index and $FFFF) shl 1) or Ord(AItem.Visible);
end;
end;
procedure TcxSchedulerStorageResources.SetPropertyValue(const AName: string;
const AValue: Variant);
var
AID, AIndex: Integer;
AItem: TcxSchedulerStorageResourceItem;
begin
if ResourceItems.Count = 0 then Exit;
if Pos('Resource', AName) = 1 then
begin
AID := StrToIntDef('$' + Copy(AName, 9, 8), -1);
AItem := TcxSchedulerStorageResourceItem(ResourceItems.FindItemID(AID));
if AItem <> nil then
begin
AIndex := (AValue shr 1) and $FFFFFFF;
if (AIndex >= 0) and (AIndex < ResourceItems.Count) then
begin
AItem.Index := AIndex;
AItem.Visible := Boolean(AValue and 1);
end;
end;
end;
end;
procedure TcxSchedulerStorageResources.Changed;
begin
Storage.Changed;
end;
function TcxSchedulerStorageResources.CreateItems: TcxSchedulerStorageResourceItems;
begin
Result := TcxSchedulerStorageResourceItems.Create(
Self, TcxSchedulerStorageResourceItem);
end;
function TcxSchedulerStorageResources.DoGetResourceName(
AItem: TcxSchedulerStorageResourceItem): string;
begin
Result := '';
if AItem <> nil then
Result := AItem.Name;
if Assigned(FOnGetResourceName) then
FOnGetResourceName(Storage, AItem, Result);
end;
function TcxSchedulerStorageResources.GetOwner: TPersistent;
begin
Result := FOwner;
end;
function TcxSchedulerStorageResources.GetResourceItems: TcxSchedulerStorageResourceItems;
begin
Result := Items;
end;
procedure TcxSchedulerStorageResources.SetItems(
AValue: TcxSchedulerStorageResourceItems);
begin
FItems.Assign(AValue);
end;
{ TcxCustomSchedulerStorage }
constructor TcxCustomSchedulerStorage.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
EventsIndex := TList.Create;
FIsLoading := True;
CreateSubClasses;
FIsLoading := False;
end;
destructor TcxCustomSchedulerStorage.Destroy;
begin
EventsIndex.Free;
SendNotification(True);
DestroySubClasses;
inherited Destroy;
end;
procedure TcxCustomSchedulerStorage.Assign(
Source: TPersistent);
begin
if Source is TcxCustomSchedulerStorage then
begin
Resources := TcxCustomSchedulerStorage(Source).Resources;
Fields.Assign(TcxCustomSchedulerStorage(Source).Fields);
InternalFields.Assign(TcxCustomSchedulerStorage(Source).InternalFields);
end;
end;
procedure TcxCustomSchedulerStorage.AddListener(
AListener: IcxSchedulerStorageListener);
begin
if FListeners.IndexOf(AListener) = -1 then
FListeners.Add(AListener);
end;
procedure TcxCustomSchedulerStorage.BeginUpdate;
begin
DataController.BeginUpdate;
end;
procedure TcxCustomSchedulerStorage.Clear;
begin
DataController.RecordCount := 0;
DataController.Post;
end;
function TcxCustomSchedulerStorage.CheckRequiredFields: Boolean;
begin
Result := True;
end;
function TcxCustomSchedulerStorage.CreateEvent: TcxSchedulerEvent;
begin
Result := GetEventClass.Create(Self);
FNewEvents.Add(Result);
end;
function TcxCustomSchedulerStorage.CreateOccurrence(APattern: TcxSchedulerEvent;
const ADate: TDateTime; AType: TcxEventType): TcxSchedulerEvent;
var
ACalculator: TcxSchedulerOccurrenceCalculator;
AOccurrence: TcxSchedulerEvent;
begin
Result := nil;
if not (AType in [etCustom, etException]) or (APattern.EventType <> etPattern) then Exit;
ACalculator := TcxSchedulerOccurrenceCalculator.Create(APattern, APattern.Start, ADate + 7);
try
while ACalculator.GetNextOccurrence do
begin
if APattern.GetOccurrenceByIndex(ACalculator.Index, AOccurrence) then
Continue
else
if DateOf(ACalculator.OccurrenceStart) > DateOf(ADate) then
Break
else
if DateOf(ACalculator.OccurrenceStart) = DateOf(ADate) then
begin
Result := CreateEvent;
Result.Assign(APattern);
Result.Start := ACalculator.OccurrenceStart;
Result.Finish := ACalculator.OccurrenceFinish;
Result.RecurrenceIndex := ACalculator.Index;
Result.EventType := AType;
Result.ParentID := APattern.ID;
Result.FPattern := APattern;
Break;
end;
end;
finally
ACalculator.Free;
end;
end;
procedure TcxCustomSchedulerStorage.EndUpdate;
begin
if DataController.LockCount = 1 then
begin
BeforeUpdate;
try
PostEvents;
if FDeletedRecords.Count > 0 then
TcxSchedulerStorageDataController(DataController).DeleteRecords(FDeletedRecords);
FDeletedRecords.Count := 0;
finally
AfterUpdate;
end;
end;
DataController.EndUpdate;
end;
procedure TcxCustomSchedulerStorage.FullRefresh;
begin
if IsUpdatingMode then Exit;
FIsLoading := True;
try
DoRefresh;
finally
FIsLoading := False;
SendNotification;
end;
end;
function TcxCustomSchedulerStorage.GetEventByID(const AID: Variant): TcxSchedulerEvent;
var
I: Integer;
begin
Result := nil;
for I := 0 to EventCount - 1 do
if VarEquals(AID, Events[I].ID) then
begin
Result := Events[I];
break;
end;
end;
function TcxCustomSchedulerStorage.GetEvents(
AList: TcxSchedulerFilteredEventList;
const AStart, AFinish: TDateTime): Boolean;
begin
Result := GetEvents(AList, AStart, AFinish, Null);
end;
function TcxCustomSchedulerStorage.GetEvents(
AList: TcxSchedulerFilteredEventList; const AStart, AFinish: TDateTime;
const AResourceID: Variant): Boolean;
var
I: Integer;
begin
AList.Init(AStart, AFinish, Self);
for I := 0 to EventCount - 1 do
AList.CheckEvent(Events[I], AResourceID);
AList.Changed;
Result := AList.Count > 0;
end;
procedure TcxCustomSchedulerStorage.PostEvents;
begin
if not IsActive or (FNewEvents.Count = 0) then Exit;
BeginUpdate;
try
while FNewEvents.Count <> 0 do FNewEvents.Last.Post;
finally
EndUpdate;
end;
end;
function TcxCustomSchedulerStorage.IsActive: Boolean;
begin
Result := True;
end;
function TcxCustomSchedulerStorage.IsCaptionAvailable: Boolean;
begin
Result := True;
end;
function TcxCustomSchedulerStorage.IsLabelColorAvailable: Boolean;
begin
Result := True;
end;
function TcxCustomSchedulerStorage.IsLocationAvailable: Boolean;
begin
Result := True;
end;
function TcxCustomSchedulerStorage.IsMessageAvailable: Boolean;
begin
Result := True;
end;
function TcxCustomSchedulerStorage.IsRecurrenceAvailable: Boolean;
begin
Result := True;
end;
function TcxCustomSchedulerStorage.IsStateAvailable: Boolean;
begin
Result := True;
end;
function TcxCustomSchedulerStorage.IsReminderAvailable: Boolean;
begin
Result := True;
end;
procedure TcxCustomSchedulerStorage.AfterUpdate;
begin
end;
procedure TcxCustomSchedulerStorage.BeforeUpdate;
begin
end;
procedure TcxCustomSchedulerStorage.RemoveListener(
AListener: IcxSchedulerStorageListener);
begin
FListeners.Remove(AListener);
end;
procedure TcxCustomSchedulerStorage.AddInternalField(
var AField: TcxCustomSchedulerStorageField; AValueType: TcxValueTypeClass);
begin
AField := TcxCustomSchedulerStorageField(InternalFields.Add);
AField.ValueTypeClass := AValueType;
end;
procedure TcxCustomSchedulerStorage.AddRecord;
begin
DataController.AppendRecord;
end;
procedure TcxCustomSchedulerStorage.CancelEvent(AEvent: TcxSchedulerEvent);
begin
Dec(AEvent.FEditCount);
if AEvent.FEditCount = 0 then
AEvent.Free;
Changed;
end;
function TcxCustomSchedulerStorage.CanGetValueFromPattern(
AIndex: Integer): Boolean;
begin
Result := AIndex in [
FCaptionField.Index,
FLabelColorField.Index,
FLocationField.Index,
FMessageField.Index,
FOptionsField.Index,
FReminderTimeField.Index,
FStateField.Index
];
Result := Result or (AIndex > FStateField.Index);
end;
procedure TcxCustomSchedulerStorage.Changed;
begin
if not IsLocked then SendNotification;
end;
procedure TcxCustomSchedulerStorage.CreateDefaultFields;
begin
AddInternalField(FCaptionField, TcxStringValueType);
AddInternalField(FEventTypeField, TcxIntegerValueType);
AddInternalField(FFinishField, TcxDateTimeValueType);
AddInternalField(FLabelColorField, TcxIntegerValueType);
AddInternalField(FLocationField, TcxStringValueType);
AddInternalField(FMessageField, TcxStringValueType);
AddInternalField(FOptionsField, TcxIntegerValueType);
AddInternalField(FParentIDField, TcxIntegerValueType);
AddInternalField(FRecurrenceIndexField, TcxIntegerValueType);
AddInternalField(FRecurrenceInfoField, TcxVariantValueType);
AddInternalField(FReminderTimeField, TcxIntegerValueType);
AddInternalField(FResourceIDField, TcxVariantValueType);
AddInternalField(FStartField, TcxDateTimeValueType);
AddInternalField(FStateField, TcxIntegerValueType);
end;
function TcxCustomSchedulerStorage.CreateFields: TcxCustomSchedulerStorageFields;
begin
Result := TcxSchedulerStorageFields.Create(TcxSchedulerStorageField);
end;
function TcxCustomSchedulerStorage.CreateResources: TcxSchedulerStorageResources;
begin
Result := TcxSchedulerStorageResources.Create(Self);
end;
procedure TcxCustomSchedulerStorage.CreateSubClasses;
begin
FDeletedRecords := TList.Create;
FResources := CreateResources;
FInternalFields := CreateFields;
FInternalFields.FOwner := Self;
FUserFields := CreateFields;
FUserFields.FOwner := Self;
FFields := TList.Create;
FNewEvents := TcxSchedulerEventList.Create;
FEventsList := TcxSchedulerEventList.Create;
FListeners := TInterfaceList.Create();
FDataController := GetDataControllerClass.Create(Self);
CreateDefaultFields;
end;
procedure TcxCustomSchedulerStorage.DestroySubClasses;
begin
try
FUserFields.Clear;
FInternalFields.Clear;
FEventsList.DestroyItems;
FNewEvents.DestroyItems;
FDeletedRecords.Free;
finally
FDataController.Free;
FNewEvents.Free;
FEventsList.Free;
FUserFields.Free;
FInternalFields.Free;
FFields.Free;
FResources.Free;
FreeAndNil(FEditor);
FListeners.Free;
end;
end;
procedure TcxCustomSchedulerStorage.DoDeleteEvent(
const ARecordIndex: Integer);
var
I: Integer;
AParentEvent, AChildEvent: TcxSchedulerEvent;
AEventsChain: TcxSchedulerEventList;
begin
AParentEvent := FEventsList[ARecordIndex];
if IsUpdatingMode or IsDeletion or DoEventDeleted(AParentEvent) then Exit;
IsDeletion := True;
BeginUpdate;
FDeletedRecords.Add(Pointer(AParentEvent.RecordIndex));
try
AEventsChain := AParentEvent.GetRecurrenceChain;
try
for I := 0 to AEventsChain.Count - 1 do
begin
AChildEvent := AEventsChain[I];
DoEventDeleted(AChildEvent); //ignore Allow parameter for the database integrity
FDeletedRecords.Add(Pointer(AChildEvent.RecordIndex));
AChildEvent.Free;
end;
AParentEvent.Free;
finally
AEventsChain.Destroy;
end;
finally
IsDeletion := False;
EndUpdate;
end;
end;
procedure TcxCustomSchedulerStorage.DoDestroyEvent(
AEvent: TcxSchedulerEvent);
begin
FEventsList.Remove(AEvent);
FNewEvents.Remove(AEvent);
end;
function TcxCustomSchedulerStorage.DoEventDeleted(
AEvent: TcxSchedulerEvent): Boolean;
begin
Result := False;
if Assigned(FOnEventDeleted) then
FOnEventDeleted(Self, AEvent, Result);
end;
function TcxCustomSchedulerStorage.DoEventInserted(
AEvent: TcxSchedulerEvent): Boolean;
begin
Result := False;
if Assigned(FOnEventInserted) then
FOnEventInserted(Self, AEvent, Result);
end;
function TcxCustomSchedulerStorage.DoEventModified(
AEvent: TcxSchedulerEvent): Boolean;
begin
Result := False;
with AEvent do
begin
if not FSkipModified and IsModified and Assigned(FOnEventModified) then
FOnEventModified(Self, AEvent, Result);
end;
end;
procedure TcxCustomSchedulerStorage.DoRefresh;
var
ID: Variant;
AEvent: TcxSchedulerEvent;
IndexList, DestList: TList;
I, J, ACount: Integer;
begin
ACount := DataController.RecordCount;
if not IsDataSettingsValid then
ACount := 0;
IndexList := FEventsList.FItems;
IndexList.Sort(TListSortCompare(@cxCompareEventsByID));
DestList := TList.Create;
try
FEventsList.FItems := DestList;
DestList.Count := ACount;
for I := 0 to ACount - 1 do
begin
ID := DataController.GetRecordID(I);
if not cxFindEvent(IndexList, ID, AEvent) then
AEvent := GetEventClass.Create(Self, I);
AEvent.SetRecordIndex(I);
AEvent.FPattern := nil;
DestList[I] := AEvent;
end;
for I := 0 to IndexList.Count - 1 do
TObject(IndexList.List^[I]).Free;
finally
IndexList.Free;
end;
for I := 0 to ACount - 1 do
if Events[I].EventType = etPattern then
begin
for J := 0 to ACount - 1 do
if J <> I then
Events[I].CheckRecurrenceLink(Events[J]);
end;
end;
function TcxCustomSchedulerStorage.GetDataControllerClass: TcxCustomDataControllerClass;
begin
Result := TcxSchedulerStorageDataController;
end;
function TcxCustomSchedulerStorage.GetEventStoredID(AEvent: TcxSchedulerEvent): Variant;
begin
Result := AEvent.FSavedID;
end;
function TcxCustomSchedulerStorage.GetFieldValueBeforePost(
ARecordIndex, AFieldIndex: Integer): Variant;
begin
Result := Values[ARecordIndex, AFieldIndex];
end;
function TcxCustomSchedulerStorage.GetFocusedRecordID(ARecordIndex: Integer): Variant;
begin
Result := DataController.GetRecordId(ARecordIndex);
end;
function TcxCustomSchedulerStorage.GetEventClass: TcxSchedulerEventClass;
begin
Result := TcxSchedulerEvent;
end;
function TcxCustomSchedulerStorage.GetParentForm: TForm;
var
AOwner: TComponent;
begin
AOwner := Owner;
while not (AOwner is TForm) and (AOwner <> nil) do
AOwner := AOwner.Owner;
Result := TForm(AOwner);
end;
function TcxCustomSchedulerStorage.GetRecordID(
const ARecordIndex: Integer): Variant;
begin
Result := DataController.GetRecordID(ARecordIndex);
end;
function TcxCustomSchedulerStorage.GetValue(
ARecordIndex, AItemIndex: Integer): Variant;
begin
if DataController.IsEditing and (ARecordIndex = DataController.EditingRecordIndex) then
Result := DataController.GetEditValue(AItemIndex, evsValue)
else
Result := DataController.Values[ARecordIndex, AItemIndex];
end;
procedure TcxCustomSchedulerStorage.ItemAdded(
AItem: TcxCustomSchedulerStorageField);
begin
if FFields.IndexOf(AItem) = -1 then
try
AItem.FIndex := FFields.Add(AItem);
DataController.AddItem(AItem);
finally
DataController.UpdateItemIndexes;
LayoutChanged;
end;
end;
procedure TcxCustomSchedulerStorage.ItemRemoved(
AItem: TcxCustomSchedulerStorageField);
begin
if FFields.Remove(AItem) <> -1 then
try
DataController.RemoveItem(AItem);
finally
UpdateItemIndexes;
LayoutChanged;
end;
end;
function TcxCustomSchedulerStorage.IsDataSettingsValid: Boolean;
begin
Result := True;
end;
procedure TcxCustomSchedulerStorage.LayoutChanged;
begin
SendNotification;
end;
procedure TcxCustomSchedulerStorage.Loaded;
begin
inherited Loaded;
DataController.Loaded;
FullRefresh;
end;
procedure TcxCustomSchedulerStorage.PostEvent(
AEvent: TcxSchedulerEvent);
var
ARecordIndex: Integer;
begin
BeginUpdate;
try
if AEvent.IsNewEvent then
begin
FNewEvents.Remove(AEvent);
FEventsList.Add(AEvent);
if DoEventInserted(AEvent) then Exit;
if CheckRequiredFields then
begin
ARecordIndex := DataController.RecordCount;
AddRecord;
if ARecordIndex < DataController.RecordCount then
begin
AEvent.SetRecordIndex(ARecordIndex);
AEvent.EndEditing;
AEvent.FSavedID := GetFocusedRecordID(ARecordIndex);
end;
end
else
AEvent.Free;
end;
finally
EndUpdate;
end;
end;
procedure TcxCustomSchedulerStorage.PostEditingData(
AEvent: TcxSchedulerEvent);
var
AFieldIndex: Integer;
begin
if DoEventModified(AEvent) then Exit;
DataController.BeginUpdate;
try
for AFieldIndex := 0 to AEvent.ValueCount - 1 do
SetPostFieldValue(AEvent, AFieldIndex);
finally
DataController.EndUpdate;
end;
end;
procedure TcxCustomSchedulerStorage.SendNotification(
AIsRemoved: Boolean = False);
var
I: Integer;
AIntf: IcxSchedulerStorageListener;
begin
for I := Listeners.Count - 1 downto 0 do
if Supports(Listeners[I], IcxSchedulerStorageListener, AIntf) then
begin
if AIsRemoved then
AIntf.StorageRemoved(Self)
else
if not IsUpdatingMode then
AIntf.StorageChanged(Self);
end;
end;
procedure TcxCustomSchedulerStorage.SetEventRecordInfo(AEvent: TcxSchedulerEvent;
ARecordIndex: Integer; const AEventID: Variant);
begin
AEvent.SetRecordIndex(ARecordIndex);
AEvent.FSavedID := AEventID;
end;
procedure TcxCustomSchedulerStorage.SetFieldValueBeforePost(
ARecordIndex, AFieldIndex: Integer; const AValue: Variant);
begin
Values[ARecordIndex, AFieldIndex] := AValue;
end;
procedure TcxCustomSchedulerStorage.SetPostFieldValue(AEvent: TcxSchedulerEvent;
AFieldIndex: Integer);
var
AEventValue, APatternValue, AStoredValue: Variant;
begin
AEventValue := AEvent.FEditValues[AFieldIndex];
if (AEvent.Pattern <> nil) and (AEvent.EventType = etCustom) and CanGetValueFromPattern(AFieldIndex) then
begin
APatternValue := Values[AEvent.Pattern.RecordIndex, AFieldIndex];
AStoredValue := GetFieldValueBeforePost(AEvent.RecordIndex, AFieldIndex);
if not VarEquals(AEventValue, APatternValue) or
(not VarEquals(AEventValue, AStoredValue) and not VarIsNull(AStoredValue)) then
SetFieldValueBeforePost(AEvent.RecordIndex, AFieldIndex, AEventValue);
end
else
SetFieldValueBeforePost(AEvent.RecordIndex, AFieldIndex, AEventValue);
end;
procedure TcxCustomSchedulerStorage.SetValue(
ARecordIndex, AItemIndex: Integer;
const AValue: Variant);
begin
DataController.Values[ARecordIndex, AItemIndex] := AValue;
end;
procedure TcxCustomSchedulerStorage.UpdateControl(
AInfo: TcxUpdateControlInfo);
begin
if (AInfo is TcxDataChangedInfo) or (AInfo is TcxUpdateRecordInfo) then
FullRefresh;
end;
procedure TcxCustomSchedulerStorage.UpdateData;
begin
end;
procedure TcxCustomSchedulerStorage.UpdateItemIndexes;
var
I: Integer;
begin
for I := 0 to FieldCount - 1 do
TcxCustomSchedulerStorageField(FFields[I]).FIndex := I;
SendNotification;
end;
function TcxCustomSchedulerStorage.GetEvent(
AIndex: Integer): TcxSchedulerEvent;
begin
Result := FEventsList[AIndex];
end;
function TcxCustomSchedulerStorage.GetEventCount: Integer;
begin
Result := FEventsList.Count;
end;
function TcxCustomSchedulerStorage.GetFieldCount: Integer;
begin
Result := FFields.Count
end;
function TcxCustomSchedulerStorage.GetIsDestroying: Boolean;
begin
Result := csDestroying in ComponentState;
end;
function TcxCustomSchedulerStorage.GetIsLoading: Boolean;
begin
Result := csLoading in ComponentState;
end;
function TcxCustomSchedulerStorage.GetIsLocked: Boolean;
begin
Result := DataController.LockCount > 0
end;
function TcxCustomSchedulerStorage.GetIsUpdatingMode: Boolean;
begin
Result := FIsLoading or IsLoading or IsDestroying;
end;
function TcxCustomSchedulerStorage.GetResourceCount: Integer;
begin
Result := Resources.ResourceItems.Count;
end;
function TcxCustomSchedulerStorage.GetResourceID(AIndex: Integer): Variant;
begin
Result := Resources.ResourceItems[AIndex].ResourceID;
end;
function TcxCustomSchedulerStorage.GetResourceName(AIndex: Integer): string;
begin
Result := Resources.ResourceItems[AIndex].DisplayName;
end;
procedure TcxCustomSchedulerStorage.SetEvent(
AIndex: Integer; AValue: TcxSchedulerEvent);
begin
Events[AIndex].Assign(AValue);
end;
procedure TcxCustomSchedulerStorage.SetResources(
AValue: TcxSchedulerStorageResources);
begin
FResources.Assign(AValue);
end;
procedure TcxCustomSchedulerStorage.SetStoreUsingGlobalTime(AValue: Boolean);
begin
if StoreUsingGlobalTime <> AValue then
begin
FStoreUsingGlobalTime := AValue;
if AValue then
begin
with TcxSchedulerDateTimeHelper do
TimeBias := TimeZoneBias(CurrentTimeZone)
end
else
TimeBias := 0;
Changed;
end;
end;
{ TcxSchedulerStorage }
procedure TcxSchedulerStorage.Assign(Source: TPersistent);
var
AMemStream: TMemoryStream;
begin
if Source is TcxSchedulerStorage then
begin
AMemStream := TMemoryStream.Create;
try
TcxSchedulerStorage(Source).SaveToStream(AMemStream);
AMemStream.Position := 0;
LoadFromStream(AMemStream);
finally
AMemStream.Free;
end;
end
else
inherited Assign(Source);
end;
procedure TcxSchedulerStorage.SaveToFile(
const AFileName: string);
var
AStream: TFileStream;
begin
AStream := TFileStream.Create(AFileName, fmCreate);
try
SaveToStream(AStream);
finally
AStream.Free;
end;
end;
procedure TcxSchedulerStorage.SaveToStream(AStream: TStream);
begin
DataController.SaveToStream(AStream);
end;
procedure TcxSchedulerStorage.LoadFromFile(const AFileName: string);
var
AStream: TFileStream;
begin
AStream := TFileStream.Create(AFileName, fmOpenRead);
try
LoadFromStream(AStream);
finally
AStream.Free;
end;
end;
procedure TcxSchedulerStorage.LoadFromStream(
AStream: TStream);
var
AMemStream: TMemoryStream;
begin
AMemStream := TMemoryStream.Create;
BeginUpdate;
try
SaveToStream(AMemStream);
try
Clear;
DataController.LoadFromStream(AStream);
except
Clear;
DataController.LoadFromStream(AMemStream);
raise;
end;
finally
AMemStream.Free;
if IsUpdatingMode then
DoRefresh;
EndUpdate;
end;
end;
procedure TcxSchedulerStorage.DefineProperties(
Filer: TFiler);
begin
inherited DefineProperties(Filer);
Filer.DefineBinaryProperty('BinaryData', LoadFromStream,
SaveToStream, DataController.RecordCount > 0);
end;
function TcxSchedulerStorage.GetFields: TcxSchedulerStorageFields;
begin
Result := TcxSchedulerStorageFields(inherited Fields)
end;
procedure TcxSchedulerStorage.SetFields(
const AValue: TcxSchedulerStorageFields);
begin
Fields.Assign(AValue);
end;
{ TcxSelectedItemData }
constructor TcxSelectedItemData.Create(AEvent: TcxSchedulerEvent);
begin
ID := AEvent.ID;
ParentID := AEvent.ParentID;
RecurrenceIndex := AEvent.RecurrenceIndex
end;
{ TcxSchedulerEventSelection }
constructor TcxSchedulerEventSelection.Create(
ASourceEvents: TcxSchedulerEventList);
begin
FKeys := TList.Create;
FEvents := TList.Create;
FSourceEvents := ASourceEvents;
end;
destructor TcxSchedulerEventSelection.Destroy;
begin
InternalClear;
FEvents.Free;
FKeys.Free;
inherited Destroy;
end;
procedure TcxSchedulerEventSelection.Add(
AEvent: TcxSchedulerControlEvent; AShift: TShiftState);
var
AIndex: Integer;
ASelected: Boolean;
begin
ASelected := (AEvent <> nil) and AEvent.Selected;
if (AEvent = nil) or ([ssShift, ssCtrl] * AShift = []) then
InternalClear;
if AEvent <> nil then
try
AIndex := KeyIndexOf(AEvent);
if (ssCtrl in AShift) and (AIndex >= 0) then
begin
Keys[AIndex].Free;
FKeys.Delete(AIndex);
end
else
if AIndex < 0 then
FKeys.Add(CreateItem(AEvent));
finally
Update;
if ASelected <> AEvent.Selected then
DoEventSelectionChanged(AEvent);
end;
end;
procedure TcxSchedulerEventSelection.Clear;
begin
if Count = 0 then Exit;
InternalClear;
DoEventSelectionChanged(nil);
end;
function TcxSchedulerEventSelection.IsSelected(
AEvent: TcxSchedulerControlEvent): Boolean;
begin
Result := KeyIndexOf(AEvent) >= 0;
end;
procedure TcxSchedulerEventSelection.Update;
begin
FKeys.Sort(TListSortCompare(@cxCompareSelectionKeys));
ReplaceSelection;
end;
procedure TcxSchedulerEventSelection.ClearKeys;
var
I: Integer;
begin
for I := FKeys.Count - 1 downto 0 do
TObject(FKeys.List^[I]).Free;
FKeys.Clear;
end;
function TcxSchedulerEventSelection.CreateItem(
AEvent: TcxSchedulerControlEvent): TcxSelectedItemData;
begin
Result := TcxSelectedItemData.Create(AEvent);
Result.ID := AEvent.ID;
Result.ParentID := AEvent.ParentID;
Result.RecurrenceIndex := AEvent.RecurrenceIndex;
end;
procedure TcxSchedulerEventSelection.DoEventSelectionChanged(
AEvent: TcxSchedulerControlEvent);
begin
if Assigned(FOnEventSelectionChanged) then
FOnEventSelectionChanged(AEvent);
end;
function TcxSchedulerEventSelection.KeyIndexOf(
AEvent: TcxSchedulerControlEvent): Integer;
var
I, L, R, C: Integer;
AItemForSearch: TcxSelectedItemData;
begin
Result := -1;
L := 0;
R := KeyCount - 1;
if R < L then Exit;
AItemForSearch := CreateItem(AEvent);
try
while L <= R do
begin
I := (L + R) shr 1;
C := cxCompareSelectionKeys(Keys[I], AItemForSearch);
if C < 0 then
L := I + 1
else
begin
R := I - 1;
if C = 0 then
begin
Result := I;
Break;
end;
end;
end;
finally
AItemForSearch.Free;
end;
end;
function TcxSchedulerEventSelection.IndexOf(
AEvent: TcxSchedulerControlEvent): Integer;
begin
Result := FEvents.IndexOf(AEvent);
end;
procedure TcxSchedulerEventSelection.InternalClear;
begin
ClearKeys;
FEvents.Clear;
end;
procedure TcxSchedulerEventSelection.ReplaceSelection;
var
AIndex, I: Integer;
begin
FEvents.Clear;
for I := 0 to FSourceEvents.Count - 1 do
begin
AIndex := KeyIndexOf(TcxSchedulerControlEvent(FSourceEvents[I]));
if AIndex <> -1 then FEvents.Add(FSourceEvents[I]);
end;
ClearKeys;
for I := 0 to FEvents.Count - 1 do
FKeys.Add(CreateItem(TcxSchedulerControlEvent(FEvents[I])));
FKeys.Sort(TListSortCompare(@cxCompareSelectionKeys));
end;
function TcxSchedulerEventSelection.GetCount: Integer;
begin
Result := FEvents.Count;
end;
function TcxSchedulerEventSelection.GetItem(
AIndex: Integer): TcxSchedulerControlEvent;
begin
Result := TcxSchedulerControlEvent(FEvents.List^[AIndex])
end;
function TcxSchedulerEventSelection.GetKey(
AIndex: Integer): TcxSelectedItemData;
begin
Result := FKeys.List^[AIndex];
end;
function TcxSchedulerEventSelection.GetKeyCount: Integer;
begin
Result := FKeys.Count;
end;
{ TcxSchedulerEventList }
constructor TcxSchedulerEventList.Create;
begin
FItems := TList.Create;
end;
destructor TcxSchedulerEventList.Destroy;
begin
FItems.Free;
inherited Destroy;
end;
procedure TcxSchedulerEventList.Assign(ASource: TcxSchedulerEventList{$IFDEF DELPHI6};
AOperator: TListAssignOp = laCopy {$ENDIF});
{$IFNDEF DELPHI6}
var
I: Integer;
{$ENDIF}
begin
if ASource = nil then Exit;
{$IFDEF DELPHI6}
FItems.Assign(ASource.FItems, AOperator, nil);
{$ELSE}
FItems.Clear;
FItems.Capacity := ASource.FItems.Capacity;
for I := 0 to ASource.FItems.Count - 1 do
FItems.Add(ASource.FItems.List^[I]);
{$ENDIF}
end;
function TcxSchedulerEventList.Add(
AEvent: TcxSchedulerEvent): Integer;
begin
Result := FItems.Add(AEvent);
EventAdded(AEvent);
end;
procedure TcxSchedulerEventList.Clear;
begin
DoClear(False);
end;
procedure TcxSchedulerEventList.Delete(AIndex: Integer);
begin
FItems.Delete(AIndex);
end;
procedure TcxSchedulerEventList.DestroyItems;
begin
DoClear(True);
end;
function TcxSchedulerEventList.Remove(
AEvent: TcxSchedulerEvent): Integer;
begin
Result := FItems.Remove(AEvent);
end;
function TcxSchedulerEventList.IndexOf(
AEvent: TcxSchedulerEvent): Integer;
begin
Result := FItems.IndexOf(AEvent);
end;
procedure TcxSchedulerEventList.Sort(
ACompare: TcxCompareEventsProc);
begin
FItems.Sort(@ACompare);
end;
procedure TcxSchedulerEventList.EventAdded(
AEvent: TcxSchedulerEvent);
begin
end;
procedure TcxSchedulerEventList.DoClear(AFreeItems: Boolean);
var
I: Integer;
begin
if AFreeItems then
for I := FItems.Count - 1 downto 0 do Items[I].Free;
FItems.Clear;
end;
function TcxSchedulerEventList.GetCount: Integer;
begin
Result := FItems.Count;
end;
function TcxSchedulerEventList.GetFirst: TcxSchedulerEvent;
begin
Result := TcxSchedulerEvent(FItems.First);
end;
function TcxSchedulerEventList.GetEvent(
AIndex: Integer): TcxSchedulerEvent;
begin
Result := TcxSchedulerEvent(FItems.List^[AIndex]);
end;
function TcxSchedulerEventList.GetLast: TcxSchedulerEvent;
begin
Result := TcxSchedulerEvent(FItems.Last);
end;
{ TcxSchedulerFilteredEventList }
destructor TcxSchedulerFilteredEventList.Destroy;
begin
DestroyItems;
inherited Destroy;
end;
function TcxSchedulerFilteredEventList.AddEvent(
AEvent: TcxSchedulerEvent): TcxSchedulerControlEvent;
begin
Result := CreateControlEvent(AEvent);
Add(Result);
end;
function TcxSchedulerFilteredEventList.AddOccurrence(
ACalculator: TcxSchedulerOccurrenceCalculator): TcxSchedulerControlEvent;
begin
Result := nil;
with ACalculator do
begin
if (DateOf(OccurrenceStart) <= Finish) and (DateOf(OccurrenceFinish) >= Start) then
Result := AddEvent(Event)
else
Exit;
Result.Start := OccurrenceStart - Result.TimeBias + Storage.TimeBias;
Result.Finish := OccurrenceFinish - Result.TimeBias + Storage.TimeBias;
Result.RecurrenceIndex := Index;
Result.EventType := etOccurrence;
Result.FPattern := Event;
Result.FOptions := Event.FOptions;
end;
end;
procedure TcxSchedulerFilteredEventList.Changed;
begin
end;
procedure TcxSchedulerFilteredEventList.CheckEvent(
AEvent: TcxSchedulerEvent; const AResourceID: Variant);
begin
if AEvent.EventType = etNone then
CheckSimpleEvent(AEvent, AResourceID)
else
if AEvent.EventType = etPattern then
CheckRecurrenceEvent(AEvent, AResourceID);
end;
procedure TcxSchedulerFilteredEventList.CheckRecurrenceEvent(
AEvent: TcxSchedulerEvent; const AResourceID: Variant);
var
AOccurrence: TcxSchedulerEvent;
ACalculator: TcxSchedulerOccurrenceCalculator;
begin
ACalculator := TcxSchedulerOccurrenceCalculator.Create(AEvent, FStart, FFinish);
try
while ACalculator.GetNextOccurrence do
begin
if AEvent.GetOccurrenceByIndex(ACalculator.Index, AOccurrence) then
begin
if AOccurrence.EventType = etCustom then
CheckSimpleEvent(AOccurrence, AResourceID)
end
else
if VarIsNull(AResourceID) or VarEquals(AEvent.ResourceID, AResourceID) then
AddOccurrence(ACalculator);
end;
finally
ACalculator.Free;
end;
end;
procedure TcxSchedulerFilteredEventList.CheckSimpleEvent(
AEvent: TcxSchedulerEvent; const AResourceID: Variant);
begin
if (VarIsNull(AResourceID) or VarEquals(AResourceID, AEvent.ResourceID)) and
((AEvent.Start <= Finish) and (AEvent.Finish >= Start)) then
AddEvent(AEvent).FPattern := AEvent.FPattern;
end;
function TcxSchedulerFilteredEventList.CreateControlEvent(
AEvent: TcxSchedulerEvent): TcxSchedulerControlEvent;
begin
Result := TcxSchedulerControlEvent.Create(AEvent);
Result.FTimeBias := AEvent.TimeBias;
end;
procedure TcxSchedulerFilteredEventList.Init(
const AStart, AFinish: TDateTime; AStorage: TcxCustomSchedulerStorage);
begin
DestroyItems;
FStart := AStart;
FFinish := AFinish;
FStorage := AStorage;
end;
function TcxSchedulerFilteredEventList.GetEvent(
AIndex: Integer): TcxSchedulerControlEvent;
begin
Result := TcxSchedulerControlEvent(FItems.List^[AIndex])
end;
{ TcxSchedulerCachedEventList }
constructor TcxSchedulerCachedEventList.Create;
begin
inherited Create;
FAbsoluteItems := TList.Create;
FSelection := CreateSelection;
FClones := CreateCloneList;
FShowEventsWithoutResource := True;
FTimeZone := -1;
end;
destructor TcxSchedulerCachedEventList.Destroy;
begin
FreeAndNil(FClones);
FreeAndNil(FSelection);
FreeAndNil(FAbsoluteItems);
inherited Destroy;
end;
procedure TcxSchedulerCachedEventList.CancelClones;
begin
FClones.DestroyItems;
Changed;
end;
function TcxSchedulerCachedEventList.CreateClones: TcxSchedulerEventList;
var
I: Integer;
AEvent: TcxSchedulerControlEvent;
begin
FClones.DestroyItems;
for I := 0 to Selection.Count - 1 do
begin
AEvent := CreateControlEvent(Selection.Items[I]);
Selection.Items[I].FIsSource := True;
AEvent.FIsClone := True;
AEvent.FPattern := AEvent.Source.FPattern;
FClones.Add(AEvent);
end;
Result := FClones;
Changed;
end;
procedure TcxSchedulerCachedEventList.ExtractEvents(
const ADate: TDateTime; AList: TcxSchedulerEventList);
var
I: Integer;
AEvent: TcxSchedulerEvent;
begin
AList.Clear;
for I := 0 to AbsoluteCount - 1 do
begin
AEvent := AbsoluteItems[I];
if AEvent.IsDayEvent(ADate) and (AList.IndexOf(AEvent) = -1) then
AList.Add(AEvent);
end;
end;
procedure TcxSchedulerCachedEventList.ExtractUsedDays(AList: TcxSchedulerDateList);
var
I: Integer;
begin
AList.Count := 0;
//DELPHI8! check Trunc()
for I := Trunc(FStart) to Trunc(FFinish) do
if IsDayNoneEmpty(I) then AList.Add(I);
end;
procedure TcxSchedulerCachedEventList.PostClones(ACopy: Boolean);
var
I: Integer;
begin
Storage.BeginUpdate;
try
for I := 0 to FClones.Count - 1 do
InternalPost(TcxSchedulerControlEvent(FClones[I]), ACopy);
finally
Storage.EndUpdate;
end;
Selection.Clear;
CancelClones;
end;
procedure TcxSchedulerCachedEventList.PostEvent(
AEvent: TcxSchedulerControlEvent);
begin
if AEvent.EventType in [etNone, etCustom] then
PostCloneForSimpleEvent(AEvent, False, AEvent.EventType)
else
if AEvent.EventType = etOccurrence then
PostCloneForSimpleEvent(AEvent, True, etCustom)
end;
procedure TcxSchedulerCachedEventList.Sort(ACompare: TcxCompareEventsProc);
begin
inherited Sort(ACompare);
FAbsoluteItems.Sort(TListSortCompare(@ACompare));
end;
procedure TcxSchedulerCachedEventList.Changed;
var
I: Integer;
AEvent: TcxSchedulerEvent;
begin
FAbsoluteItems.Count := 0;
FAbsoluteItems.Capacity := GetAbsoluteCountInternal;
for I := 0 to GetAbsoluteCountInternal - 1 do
begin
AEvent := GetAbsoluteItemInternal(I);
if (AEvent.Start <= SelFinish) and (SelStart <= AEvent.Finish) then
FAbsoluteItems.Add(GetAbsoluteItemInternal(I));
end;
Selection.Update;
inherited Changed;
end;
procedure TcxSchedulerCachedEventList.CheckEvent(
AEvent: TcxSchedulerEvent; const AResourceID: Variant);
begin
if CheckEventVisibility(AEvent, ShowEventsWithoutResource) then
inherited CheckEvent(AEvent, AResourceID);
end;
function TcxSchedulerCachedEventList.CheckEventVisibility(
AEvent: TcxSchedulerEvent; AIncludeUnassigned: Boolean): Boolean;
var
I: Integer;
AItems: TcxSchedulerStorageResourceItems;
begin
Result := VarIsNull(AEvent.ResourceID);
if Result and AIncludeUnassigned then
Exit
else
begin
AItems := Storage.Resources.ResourceItems;
Result := AItems.Count = 0;
for I := 0 to AItems.Count - 1 do
if AItems[I].Visible and AEvent.IsResourceEvent(AItems[I], False) then
begin
Result := True;
Exit;
end;
end;
end;
function TcxSchedulerCachedEventList.CreateControlEvent(
AEvent: TcxSchedulerEvent): TcxSchedulerControlEvent;
begin
Result := inherited CreateControlEvent(AEvent);
Result.FTimeBias := FTimeBias;
end;
function TcxSchedulerCachedEventList.CreateCloneList: TcxSchedulerFilteredEventList;
begin
Result := TcxSchedulerFilteredEventList.Create;
end;
function TcxSchedulerCachedEventList.CreateSelection: TcxSchedulerEventSelection;
begin
Result := TcxSchedulerEventSelection.Create(Self);
end;
procedure TcxSchedulerCachedEventList.DoClear(AFreeItems: Boolean);
begin
if FClones <> nil then
FClones.DestroyItems;
inherited DoClear(True);
end;
procedure TcxSchedulerCachedEventList.EventAdded(
AEvent: TcxSchedulerEvent);
begin
TcxSchedulerControlEvent(AEvent).SelectionAdapter := Self;
inherited EventAdded(AEvent);
end;
procedure TcxSchedulerCachedEventList.Init(
const AStart, AFinish: TDateTime; AStorage: TcxCustomSchedulerStorage);
begin
inherited Init(AStart, AFinish, AStorage);
with TcxSchedulerDateTimeHelper do
begin
if Storage.StoreUsingGlobalTime then
FTimeBias := TimeZoneBias(FTimeZone)
else
FTimeBias := TimeZoneBias(FTimeZone) - TimeZoneBias(CurrentTimeZone);
end;
end;
procedure TcxSchedulerCachedEventList.InternalPost(
AEvent: TcxSchedulerControlEvent; ACopy: Boolean);
begin
if AEvent.EventType = etNone then
PostCloneForSimpleEvent(AEvent, ACopy, etNone)
else
PostCloneForRecurrenceEvent(AEvent, ACopy);
end;
function TcxSchedulerCachedEventList.IsDayNoneEmpty(ADay: Integer): Boolean;
var
I: Integer;
begin
Result := False;
for I := 0 to Count - 1 do
begin
Result := Items[I].IsDayEvent(ADay);
if Result then Break;
end;
end;
function TcxSchedulerCachedEventList.IsSelected(
AEvent: TcxSchedulerControlEvent): Boolean;
begin
Result := AEvent.IsClone or (Selection.IsSelected(AEvent) and
(AlwaysShowSelectedEvent or (FClones.Count = 0)));
end;
procedure TcxSchedulerCachedEventList.PostCloneForRecurrenceEvent(
AEvent: TcxSchedulerControlEvent; ACopy: Boolean);
const
ANewType: array[Boolean] of TcxEventType = (etCustom, etNone);
begin
if not ACopy and (AEvent.EventType = etOccurrence) then
PostCloneForSimpleEvent(AEvent, True, etCustom)
else
PostCloneForSimpleEvent(AEvent, ACopy, ANewType[ACopy]);
end;
procedure TcxSchedulerCachedEventList.PostCloneForSimpleEvent(
AEvent: TcxSchedulerControlEvent; ACopy: Boolean; AType: TcxEventType);
var
AStorageEvent: TcxSchedulerEvent;
begin
AEvent.Storage.BeginUpdate;
try
AEvent.EventType := AType;
if ACopy then
begin
if AEvent.IsClone then
TcxSchedulerControlEvent(AEvent.Source).FSource := Storage.CreateEvent
else
AEvent.FSource := Storage.CreateEvent;
end;
if AEvent.IsClone then
AStorageEvent := TcxSchedulerControlEvent(AEvent.Source).Source
else
AStorageEvent := AEvent.Source;
AStorageEvent.FPattern := AEvent.FPattern;
AStorageEvent.BeginEditing;
try
AStorageEvent.Assign(AEvent);
AStorageEvent.MoveTo(AEvent.Start + AEvent.TimeBias - Storage.TimeBias);
if AType <> etNone then
AStorageEvent.ParentID := AEvent.Pattern.ID;
finally
AStorageEvent.EndEditing;
AStorageEvent.Post;
end;
finally
AEvent.Storage.EndUpdate;
end;
end;
procedure TcxSchedulerCachedEventList.SelectionAdd(
AEvent: TcxSchedulerControlEvent; Shift: TShiftState);
begin
Selection.Add(AEvent, Shift);
end;
procedure TcxSchedulerCachedEventList.SelectionClear;
begin
Selection.Clear;
end;
procedure TcxSchedulerCachedEventList.SelectionUpdate;
begin
Selection.Update;
end;
function TcxSchedulerCachedEventList._AddRef: Integer;
begin
Result := -1;
end;
function TcxSchedulerCachedEventList._Release: Integer;
begin
Result := -1;
end;
function TcxSchedulerCachedEventList.QueryInterface(
const IID: TGUID; out Obj): HResult;
const
E_NOINTERFACE = HResult($80004002);
begin
if GetInterface(IID, Obj) then
Result := 0
else
Result := E_NOINTERFACE;
end;
function TcxSchedulerCachedEventList.GetAbsoluteCount: Integer;
begin
Result := FAbsoluteItems.Count;
end;
function TcxSchedulerCachedEventList.GetAbsoluteItem(
AIndex: Integer): TcxSchedulerControlEvent;
begin
Result := TcxSchedulerControlEvent(FAbsoluteItems.List^[AIndex])
end;
function TcxSchedulerCachedEventList.GetAbsoluteCountInternal: Integer;
begin
Result := Count + FClones.Count;
end;
function TcxSchedulerCachedEventList.GetAbsoluteItemInternal(
AIndex: Integer): TcxSchedulerControlEvent;
begin
if AIndex >= Count then
Result := TcxSchedulerControlEvent(FClones.Items[AIndex - Count])
else
Result := Items[AIndex];
end;
function TcxSchedulerCachedEventList.GetItem(
AIndex: Integer): TcxSchedulerControlEvent;
begin
Result := TcxSchedulerControlEvent(FItems.List^[AIndex])
end;
{ TcxSchedulerOccurrenceCalculator }
constructor TcxSchedulerOccurrenceCalculator.Create(
AEvent: TcxSchedulerEvent; const AStart, AFinish: TDateTime);
begin
FWorkDays := TcxSchedulerDateTimeHelper.WorkDays;
FStartOfWeek := TcxSchedulerDateTimeHelper.StartOfWeek;
FEvent := AEvent;
FIndex := -1;
FVisibleStart := AStart;
FVisibleFinish := AFinish;
FRecurCount := FEvent.RecurrenceInfo.Count;
if FRecurCount = 0 then
FFinishDate := FEvent.RecurrenceInfo.Finish
else
FFinishDate := VisibleFinish;
FOccurrenceStart := FEvent.Start;
FOccurrenceFinish := FEvent.Finish;
FDayNumber := FEvent.RecurrenceInfo.DayNumber;
FDayType := FEvent.RecurrenceInfo.DayType;
FOccurDays := FEvent.RecurrenceInfo.OccurDays;
FPeriodicity := FEvent.RecurrenceInfo.Periodicity;
FRecurrence := Event.RecurrenceInfo.Recurrence;
FYearPeriodicity := Event.RecurrenceInfo.YearPeriodicity;
Dec(FRecurCount);
end;
procedure TcxSchedulerOccurrenceCalculator.CalcOccurrence(AIndex: Integer);
begin
FIndex := -1;
FFinishDate := cxMaxDate;
FRecurCount := -1;
while (AIndex > 0) and GetNextOccurrence do
Dec(AIndex);
end;
function TcxSchedulerOccurrenceCalculator.GetNextOccurrence: Boolean;
var
AOccurrenceStartBeforeEventStart: Boolean;
begin
Result := False;
AOccurrenceStartBeforeEventStart := False;
if not IsValidOccurrence then Exit;
repeat
//DELPHI8! check Trunc()
FDate := Trunc(FOccurrenceStart);
case FRecurrence of
cxreWeekly:
begin
FWeekStart := FDate - (DayOfWeek(FDate) - 1) + StartOfWeek;
if FWeekStart > FDate then Dec(FWeekStart, 7);
end;
cxreMonthly:
DecodeDate(FDate, FYear, FMonth, FDay);
cxreYearly:
begin
DecodeDate(FDate, FYear, FMonth, FDay);
FMonth := FPeriodicity;
end;
end;
if (FIndex = - 1) and not AOccurrenceStartBeforeEventStart then
CalcFirstDate
else
CalcNextDate;
AOccurrenceStartBeforeEventStart := True;
FOccurrenceFinish := FDate + (FOccurrenceFinish - DateOf(FOccurrenceStart));
FOccurrenceStart := FDate + TimeOf(FOccurrenceStart);
until DateOf(FOccurrenceStart) >= DateOf(FEvent.Start);
Result := IsValidOccurrence;
Inc(FIndex);
end;
function TcxSchedulerOccurrenceCalculator.GetOccurrenceCount(
AEndDate: TDateTime): Integer;
begin
Result := 0;
FFinishDate := AEndDate;
FIndex := -1;
FRecurCount := -1;
while GetNextOccurrence do
Inc(Result);
end;
procedure TcxSchedulerOccurrenceCalculator.CalcFirstDate;
begin
//DELPHI8! check Trunc()
FDate := Trunc(FOccurrenceStart);
case FRecurrence of
cxreDaily:
if FDayType in [cxdtWeekDay, cxdtWeekEndDay] then
FDate := GetSomeDay(FDate, 1, FDayType = cxdtWeekEndDay);
cxreWeekly:
begin
FWeekStart := FDate - (DayOfWeek(FDate) - 1) + StartOfWeek;
if FWeekStart > FDate then Dec(FWeekStart, 7);
FDate := GetDayFromOccurDays(FDate - 1, 1);
end;
cxreMonthly:
begin
DecodeDate(FDate, FYear, FMonth, FDay);
FDate := GetDayForMonth;
end;
cxreYearly:
begin
DecodeDate(FDate, FYear, FMonth, FDay);
FMonth := FPeriodicity;
FDate := GetDayForMonth;
if FDate < DateOf(FOccurrenceStart) then
begin
Inc(FYear);
FDate := GetDayForMonth;
end;
end;
end;
end;
procedure TcxSchedulerOccurrenceCalculator.CalcNextDate;
var
ADay: Word;
begin
case FRecurrence of
cxreDaily:
if FDayType = cxdtEveryDay then
Inc(FDate, FPeriodicity)
else
FDate := GetSomeDay(FDate + 1, 1, FDayType = cxdtWeekEndDay);
cxreWeekly:
FDate := GetDayFromOccurDays(FDate, FPeriodicity);
cxreMonthly:
begin
IncAMonth(FYear, FMonth, ADay, FPeriodicity);
FDate := GetDayForMonth;
end;
cxreYearly:
begin
Inc(FYear, FYearPeriodicity);
FDate := GetDayForMonth;
end;
end;
end;
function TcxSchedulerOccurrenceCalculator.GetCertainDay(
const ADate, ANumber: Integer; ADayType: TcxDayType): Integer;
var
AYear, AMonth, ADay: Word;
AOffset: Integer;
begin
DecodeDate(ADate, AYear, AMonth, ADay);
AOffset := Ord(ADayType) - Ord(cxdtSunDay) - (DayOfWeek(ADate - ADay + 1) - 1);
if AOffset < 0 then Inc(AOffset, 7);
Inc(AOffset, (ANumber - 1) * 7);
if AOffset > DaysInAMonth(AYear, AMonth) - 1 then Dec(AOffset, 7);
Result := ADate - ADay + 1 + AOffset;
end;
function TcxSchedulerOccurrenceCalculator.GetDayForMonth: Integer;
function GetADay(const ADate: Integer; ACondition: Boolean): Integer;
begin
if ACondition then
Result := ADate + DaysInAMonth(FYear, FMonth)
else
Result := ADate + FDayNumber;
end;
begin
Result := Trunc(EncodeDate(FYear, FMonth, 1)) - 1;
case FDayType of
cxdtDay:
Result := GetADay(Result, FDayNumber > DaysInAMonth(FYear, FMonth));
cxdtEveryDay:
Result := GetADay(Result, FDayNumber = 5);
cxdtWeekDay, cxdtWeekEndDay:
Result := GetSomeDay(Result + 1, FDayNumber, FDayType = cxdtWeekEndDay);
cxdtSunday..cxdtSaturday:
Result := GetCertainDay(Result + 1, FDayNumber, FDayType);
end;
end;
function TcxSchedulerOccurrenceCalculator.GetDayFromOccurDays(
const APrevDate, APeriodicity: Integer): Integer;
var
ADelta: Integer;
ADay: TDay;
begin
repeat
for ADelta := 0 to 6 do
begin
ADay := TDay(StartOfWeek + ADelta - 7 * Byte(StartOfWeek + ADelta > 6));
if ADay in FOccurDays then
begin
Result := FWeekStart + ADelta;
if Result > APrevDate then Exit;
end;
end;
Inc(FWeekStart, 7 * APeriodicity);
until False;
end;
function TcxSchedulerOccurrenceCalculator.GetSomeDay(
const ADate, ANumber: Integer; AWeekEnd: Boolean): Integer;
var
AYear, AMonth, ADay: Word;
I: Integer;
begin
if ANumber = 5 then
begin
DecodeDate(ADate, AYear, AMonth, ADay);
Result := ADate - ADay + DaysInAMonth(AYear, AMonth);
while not (AWeekEnd xor (TDay(DayOfWeek(Result) - 1) in WorkDays)) do
Dec(Result);
end
else
begin
Result := ADate;
I := 1;
repeat
while not (AWeekEnd xor (TDay(DayOfWeek(Result) - 1) in WorkDays)) do
Inc(Result);
if ANumber = I then Break;
Inc(Result);
Inc(I);
until False;
end;
end;
function TcxSchedulerOccurrenceCalculator.IsValidOccurrence: Boolean;
begin
Result := ((FRecurCount >= 0) and (FIndex < FRecurCount)) or
((FRecurCount < 0) and (DateOf(FOccurrenceStart) <= FFinishDate));
end;
end.