{********************************************************************} { } { 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 cxSchedulerCustomControls; {$I cxVer.inc} interface uses {$IFDEF DELPHI6} Types, {$ENDIF} Classes, SysUtils, Windows, Messages, Forms, StdCtrls, Controls, Graphics, cxControls, Math, cxGraphics, cxGeometry, cxLookAndFeels, cxLookAndFeelPainters, cxFormats, cxSchedulerUtils, cxSchedulerStorage, cxStyles, cxClasses, cxEdit, cxDateUtils, ExtCtrls, Menus, cxStorage, cxTextEdit; const // resize bitmap capacity cxSizeDelta = 32; //hittest codes //base class htcControl = $0; htcTime = $1; //custom viewinfo htcResource = $2; // style indexes cxcsBackground = 0; cxcsContent = 1; cxcsEvent = 2; cxcsGroupSeparator = 3; cxcsDayHeader = 4; cxcsSelection = 5; cxcsHSplitter = 6; cxcsVSplitter = 7; cxcsResourceHeader = 8; cxcsMaxValue = cxcsResourceHeader; // for PS cxcsSchedulerStyleFirst = cxcsBackground; cxcsSchedulerStyleLast = cxcsMaxValue; // default property values cxDefaultSchedulerHeight = 250; cxDefaultSchedulerWidth = 350; cxDefaultSplitterWidth = 5; cxDefaultGroupSeparatorWidth = 11; // minimal property values cxMinSplitterWidth = 3; // hint timings cxscWaitForHideHint: Integer = 5000; cxscWaitForShowHint: Integer = 1000; cxscMinHintWindth: Integer = 150; type TcxCustomScheduler = class; TcxSchedulerSubControl = class; TcxSchedulerSubControlController = class; TcxSchedulerSubControlHitTest = class; TcxSchedulerSubControlPainter = class; TcxSchedulerSubControlViewInfo = class; TcxSchedulerSplitter = class; TcxSchedulerStyles = class; // popup menus TcxSchedulerContentPopupMenu = class; TcxSchedulerEventPopupMenu = class; TcxSchedulerViewController = class; TcxSchedulerCustomView = class; TcxSchedulerCustomViewClass = class of TcxSchedulerCustomView; TcxSchedulerCustomViewViewInfo = class; TcxDragHelper = class; TcxDragEventHelper = class; TcxEventSizingHelper = class; TcxSchedulerCustomDateNavigator = class; TcxControlFlag = (cfInvalidLayout, cfLocked, cfImageValid, cfViewValid); TcxControlFlags = set of TcxControlFlag; TcxSchedulerSplitterKind = (skHorizontal, skVertical); TcxSchedulerViewPosition = (vpRight, vpLeft); TcxSchedulerGroupingKind = (gkDefault, gkNone, gkByDate, gkByResource); TcxSchedulerViewMode = (vmDay, vmWeek, vmMonth, vmWorkWeek); TcxOnDeleteEventFunc = function (AEvent: TcxSchedulerControlEvent): Boolean of object; { TcxSchedulerSubControl } TcxSchedulerSubControl = class(TPersistent) private FCanvas: TcxCanvas; FController: TcxSchedulerSubControlController; FCursor: TCursor; FHeight: Integer; FHitTest: TcxSchedulerSubControlHitTest; FLeft: Integer; FPainter: TcxSchedulerSubControlPainter; FScheduler: TcxCustomScheduler; FTop: Integer; FViewInfo: TcxSchedulerSubControlViewInfo; FVisible: Boolean; FWidth: Integer; {$IFNDEF DEBUGPAINT} function GetBitmap: TBitmap; {$ENDIF} function GetBottom: Integer; function GetBounds: TRect; function GetDateTimeHelperClass: TcxSchedulerDateTimeHelperClass; function GetLookAndFeelPainter: TcxCustomLookAndFeelPainterClass; function GetPainterHelperClass: TcxSchedulerPainterHelperClass; function GetRight: Integer; function GetStyles: TcxSchedulerStyles; procedure InternalSetBounds(const AValue: TRect); procedure SetBottom(const Value: Integer); procedure SetHeight(AValue: Integer); procedure SetLeft(AValue: Integer); procedure SetRight(Value: Integer); procedure SetTop(AValue: Integer); procedure SetVisible(AValue: Boolean); procedure SetWidth(AValue: Integer); protected // store interface procedure GetProperties(AProperties: TStrings); virtual; procedure GetPropertyValue(const AName: string; var AValue: Variant); virtual; procedure SetPropertyValue(const AName: string; const AValue: Variant); virtual; // function AllowDesignHitTest(X, Y: Integer; AShift: TShiftState): Boolean; virtual; procedure BoundsChanged; virtual; procedure CalculateViewInfo; virtual; function CanCapture(const APoint: TPoint): Boolean; virtual; procedure Changed; virtual; function CreateController: TcxSchedulerSubControlController; virtual; function CreateHitTest: TcxSchedulerSubControlHitTest; virtual; function CreatePainter: TcxSchedulerSubControlPainter; virtual; function CreateViewInfo: TcxSchedulerSubControlViewInfo; virtual; procedure CreateSubClasses; virtual; procedure DestroySubClasses; virtual; procedure DoBeforeMouseDown(AButton: TMouseButton; AShift: TShiftState; X, Y: Integer); procedure DoCancelMode; virtual; procedure DoLayoutChanged; virtual; procedure DoMouseDown(AButton: TMouseButton; AShift: TShiftState; X, Y: Integer); procedure DoMouseMove(AShift: TShiftState; X, Y: Integer); procedure DoMouseUp(AButton: TMouseButton; AShift: TShiftState; X, Y: Integer); procedure DoPaint; virtual; procedure FormatChanged; virtual; function GetClientRect: TRect; virtual; function GetOwner: TPersistent; override; function GetHScrollBarBounds: TRect; virtual; function GetSizeGripBounds: TRect; virtual; function GetStartOfWeek: TDay; virtual; function GetVScrollBarBounds: TRect; virtual; procedure InitScrollBarsParameters; virtual; procedure MousePositionChanged(var X, Y: Integer); procedure Notification(AComponent: TComponent; Operation: TOperation); virtual; procedure Paint; procedure PeriodChanged; virtual; procedure SetScrollBarInfo(AScrollBarKind: TScrollBarKind; AMin, AMax, AStep, APage, APos: Integer; AAllowShow, AAllowHide: Boolean); procedure VisibleChanged; virtual; property Canvas: TcxCanvas read FCanvas; {$IFNDEF DEBUGPAINT} property Bitmap: TBitmap read GetBitmap; {$ENDIF} property Bottom: Integer read GetBottom write SetBottom; property ClientRect: TRect read GetClientRect; property Controller: TcxSchedulerSubControlController read FController; property Cursor: TCursor read FCursor write FCursor; property DateTimeHelper: TcxSchedulerDateTimeHelperClass read GetDateTimeHelperClass; property HitTest: TcxSchedulerSubControlHitTest read FHitTest; property Left: Integer read FLeft write SetLeft; property LookAndFeelPainter: TcxCustomLookAndFeelPainterClass read GetLookAndFeelPainter; property Painter: TcxSchedulerSubControlPainter read FPainter; property PainterHelper: TcxSchedulerPainterHelperClass read GetPainterHelperClass; property Right: Integer read GetRight write SetRight; property Scheduler: TcxCustomScheduler read FScheduler; property StartOfWeek: TDay read GetStartOfWeek; property Styles: TcxSchedulerStyles read GetStyles; property Top: Integer read FTop write SetTop; property ViewInfo: TcxSchedulerSubControlViewInfo read FViewInfo; property Visible: Boolean read FVisible write SetVisible; public constructor Create(AOwner: TcxCustomScheduler); virtual; destructor Destroy; override; procedure Invalidate; procedure InvalidateRect(const ARect: TRect); procedure LayoutChanged; procedure Refresh; procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); property Bounds: TRect read GetBounds write InternalSetBounds; property Height: Integer read FHeight write SetHeight; property Width: Integer read FWidth write SetWidth; end; { TcxSchedulerSubControlController } TcxSchedulerSubControlController = class(TcxIUnknownObject) private FOwner: TcxSchedulerSubControl; function GetHitTest: TcxSchedulerSubControlHitTest; function GetStartOfWeek: TDay; protected // drag'n'drop procedure BeginDragAndDrop; virtual; function CanDrag(X, Y: Integer): Boolean; virtual; procedure DragAndDrop(const P: TPoint; var Accepted: Boolean); virtual; procedure DragDrop(Source: TObject; X, Y: Integer); virtual; procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); virtual; procedure EndDrag(Target: TObject; X, Y: Integer); virtual; procedure EndDragAndDrop(Accepted: Boolean); virtual; function GetDragAndDropObjectClass: TcxDragAndDropObjectClass; virtual; procedure StartDrag(var DragObject: TDragObject); virtual; function StartDragAndDrop(const P: TPoint): Boolean; virtual; // virtuals procedure BeforeMouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); virtual; procedure DoCancelMode; virtual; function GetCursor(X, Y: Integer): TCursor; virtual; procedure KeyDown(var Key: Word; Shift: TShiftState); virtual; procedure KeyPress(var Key: Char); virtual; procedure KeyUp(var Key: Word; Shift: TShiftState); virtual; procedure MouseEnter; virtual; procedure MouseLeave; virtual; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); virtual; procedure MouseMove(Shift: TShiftState; X, Y: Integer); virtual; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); virtual; procedure Reset; virtual; public constructor Create(AOwner: TcxSchedulerSubControl); virtual; property HitTest: TcxSchedulerSubControlHitTest read GetHitTest; property Owner: TcxSchedulerSubControl read FOwner; property StartOfWeek: TDay read GetStartOfWeek; end; { TcxSchedulerSubControlHitTest } TcxSchedulerSubControlHitTest = class private FOwner: TcxSchedulerSubControl; FHitPoint: TPoint; function GetPosValue(AIndex: Integer): Integer; function GetScheduler: TcxCustomScheduler; procedure SetHitPoint(const APoint: TPoint); procedure SetPosValue(AIndex, AValue: Integer); protected FTime: TDateTime; Flags: Int64; procedure Clear; virtual; procedure DoCalculate; virtual; function GetBitState(AIndex: Integer): Boolean; function GetMaskState(AMask: Integer): Boolean; function GetMaskStateEx(AMask: Integer): Boolean; procedure SetBitState(AIndex: Integer; AValue: Boolean); procedure SetMaskState(AMask: Integer; AValue: Boolean); property Owner: TcxSchedulerSubControl read FOwner; property Scheduler: TcxCustomScheduler read GetScheduler; public constructor Create(AOwner: TcxSchedulerSubControl); virtual; destructor Destroy; override; procedure Recalculate; property HitPoint: TPoint read FHitPoint write SetHitPoint; property HitX: Integer index 0 read GetPosValue write SetPosValue; property HitY: Integer index 1 read GetPosValue write SetPosValue; property HitAtControl: Boolean index htcControl read GetBitState; property HitAtTime: Boolean index htcTime read GetBitState; property Time: TDateTime read FTime; end; { TcxSchedulerSubControlPainter } TcxSchedulerSubControlPainter = class private FOwner: TcxSchedulerSubControl; {$IFNDEF DEBUGPAINT} function GetBitmap: TBitmap; {$ENDIF} function GetCanvas: TcxCanvas; function GetViewInfo: TcxSchedulerSubControlViewInfo; protected property Owner: TcxSchedulerSubControl read FOwner; property ViewInfo: TcxSchedulerSubControlViewInfo read GetViewInfo; public constructor Create(AOwner: TcxSchedulerSubControl); virtual; procedure Paint; virtual; property Canvas: TcxCanvas read GetCanvas; {$IFNDEF DEBUGPAINT} property Bitmap: TBitmap read GetBitmap; {$ENDIF} end; { TcxSchedulerSubControlViewInfo } TcxSchedulerSubControlViewInfo = class private FOwner: TcxSchedulerSubControl; function GetDateTimeHelperClass: TcxSchedulerDateTimeHelperClass; function GetDefaultFont: TFont; function GetIsSchedulerCreated: Boolean; function GetLookAndFeelPainter: TcxCustomLookAndFeelPainterClass; function GetPainterHelperClass: TcxSchedulerPainterHelperClass; function GetStyles: TcxSchedulerStyles; protected FBounds: TRect; procedure AfterCalculate; virtual; procedure Clear; virtual; procedure DoCalculate; virtual; function GetBounds: TRect; virtual; property DateTimeHelper: TcxSchedulerDateTimeHelperClass read GetDateTimeHelperClass; property DefaultFont: TFont read GetDefaultFont; property IsSchedulerCreated: Boolean read GetIsSchedulerCreated; property LookAndFeelPainter: TcxCustomLookAndFeelPainterClass read GetLookAndFeelPainter; property Bounds: TRect read FBounds; property Owner: TcxSchedulerSubControl read FOwner; property PainterHelper: TcxSchedulerPainterHelperClass read GetPainterHelperClass; property Styles: TcxSchedulerStyles read GetStyles; public constructor Create(AOwner: TcxSchedulerSubControl); virtual; procedure Calculate; virtual; end; { TcxSchedulerControlBox } TcxSchedulerControlBox = class(TcxSchedulerSubControl) private FContainer: TWinControl; FControlAlign: TAlign; FControlParent: TWinControl; FControlRect: TRect; FControl: TControl; FViewParams: TcxViewParams; procedure RestorePosition; procedure SetControl(AValue: TControl); procedure StorePosition; protected // store interface procedure GetProperties(AProperties: TStrings); override; procedure GetPropertyValue(const AName: string; var AValue: Variant); override; procedure SetPropertyValue(const AName: string; const AValue: Variant); override; // procedure BoundsChanged; override; function CreateWndContainerControl: TWinControl; virtual; procedure DoPaint; override; procedure DoLayoutChanged; override; function HasAsParent(AValue: TControl): Boolean; procedure VisibleChanged; override; property ViewParams: TcxViewParams read FViewParams; public constructor Create(AOwner: TcxCustomScheduler); override; procedure Assign(Source: TPersistent); override; property Container: TWinControl read FContainer; property Height; property Width; published property Control: TControl read FControl write SetControl; property Visible default True; end; { TcxSchedulerSplitterController } TcxSchedulerSplitterController = class(TcxSchedulerSubControlController) private FHitPoint: TPoint; FPrevInvertRect: TRect; FPrevRect: TRect; FSaveKeyboardListener: TcxSchedulerSubControl; FSizingBoundsRect: TRect; FStartBounds: TRect; FScreenCanvasClipRect: TRect; function GetDrawClipRect: TRect; function GetHorzSizingRect(const P: TPoint): TRect; function GetScheduler: TcxCustomScheduler; function GetScreenOffset: TPoint; function GetSplitter: TcxSchedulerSplitter; function GetVertSizingRect(const P: TPoint): TRect; procedure SetHorzBounds(var R: TRect); procedure SetHorzDelta(ADelta: Integer); procedure SetVertBounds(var R: TRect); procedure SetVertDelta(ADelta: Integer); protected // override procedure DoCancelMode; override; procedure KeyDown(var Key: Word; Shift: TShiftState); override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; // methods procedure DrawInvertRect(const R: TRect); procedure EraseInvertRect; function GetMonthSize: TSize; function GetOwnerMousePos(X, Y: Integer): TPoint; function GetSizingBoundsRect: TRect; function GetSizingIncrement: Integer; function GetSizingRect(const P: TPoint): TRect; procedure InvertRect(ACanvas: TcxCanvas; R: TRect); function IsIntegralSizing: Boolean; function IsDynamicUpdate: Boolean; procedure SetSizeDelta(ADelta: Integer); procedure UpdateSizing(const R: TRect); property Scheduler: TcxCustomScheduler read GetScheduler; property ScreenCanvasClipRect: TRect read FScreenCanvasClipRect; property ScreenOffset: TPoint read GetScreenOffset; property SizingBoundsRect: TRect read FSizingBoundsRect; property Splitter: TcxSchedulerSplitter read GetSplitter; end; { TcxSchedulerSplitter } TcxSchedulerSplitter = class(TcxSchedulerSubControl) private FKind: TcxSchedulerSplitterKind; FViewParams: TcxViewParams; protected function AllowDesignHitTest(X, Y: Integer; AShift: TShiftState): Boolean; override; function CreateController: TcxSchedulerSubControlController; override; procedure DoLayoutChanged; override; procedure DoPaint; override; procedure SetKind(AKind: TcxSchedulerSplitterKind); virtual; procedure UpdateCursor; property ViewParams: TcxViewParams read FViewParams; public property Kind: TcxSchedulerSplitterKind read FKind; end; { TcxSchedulerOptionsData } TcxSchedulerEventOperations = class(TPersistent) private FScheduler: TcxCustomScheduler; FCreating: Boolean; FDeleting: Boolean; FDialogEditing: Boolean; FDialogShowing: Boolean; FInplaceEditing: Boolean; FMoving: Boolean; FMovingBetweenResources: Boolean; FReadOnly: Boolean; FRecurrence: Boolean; FSizing: Boolean; function GetCreating: Boolean; function GetCreatingStored: Boolean; function GetDeleting: Boolean; function GetDeletingStored: Boolean; function GetDialogEditing: Boolean; function GetDialogEditingStored: Boolean; function GetInplaceEditing: Boolean; function GetInplaceEditingStored: Boolean; function GetMoving: Boolean; function GetMovingBetweenResources: Boolean; function GetMovingBetweenResourcesStored: Boolean; function GetMovingStored: Boolean; function GetSizing: Boolean; function GetSizingStored: Boolean; protected function GetOwner: TPersistent; override; property Scheduler: TcxCustomScheduler read FScheduler; public constructor Create(AOwner: TcxCustomScheduler); virtual; procedure Assign(Source: TPersistent); override; published property Creating: Boolean read GetCreating write FCreating stored GetCreatingStored; property Deleting: Boolean read GetDeleting write FDeleting stored GetDeletingStored; property DialogEditing: Boolean read GetDialogEditing write FDialogEditing stored GetDialogEditingStored; property DialogShowing: Boolean read FDialogShowing write FDialogShowing default True; property InplaceEditing: Boolean read GetInplaceEditing write FInplaceEditing stored GetInplaceEditingStored; property MovingBetweenResources: Boolean read GetMovingBetweenResources write FMovingBetweenResources stored GetMovingBetweenResourcesStored; property Moving: Boolean read GetMoving write FMoving stored GetMovingStored; property ReadOnly: Boolean read FReadOnly write FReadOnly default False; property Recurrence: Boolean read FRecurrence write FRecurrence default True; property Sizing: Boolean read GetSizing write FSizing stored GetSizingStored; end; { TcxSchedulerOptionsCustomize } TcxSchedulerOptionsCustomize = class(TPersistent) private FControlsSizing: Boolean; FDynamicSizing: Boolean; FIntegralSizing: Boolean; FScheduler: TcxCustomScheduler; procedure SetControlsSizing(AValue: Boolean); procedure SetIntegralSizing(AValue: Boolean); protected procedure Changed; virtual; function GetOwner: TPersistent; override; public constructor Create(AOwner: TcxCustomScheduler); virtual; procedure Assign(Source: TPersistent); override; property Scheduler: TcxCustomScheduler read FScheduler; published property ControlsSizing: Boolean read FControlsSizing write SetControlsSizing default True; property DynamicSizing: Boolean read FDynamicSizing write FDynamicSizing default False; property IntegralSizing: Boolean read FIntegralSizing write SetIntegralSizing default True; end; { TcxSchedulerOptionsView } TcxSchedulerOptionsView = class(TPersistent) private FActualStartOfWeek: TDay; FDayBorderColor: TColor; FShowEventsWithoutResource: Boolean; FGroupSeparatorWidth: Integer; FGroupingKind: TcxSchedulerGroupingKind; FHideSelection: Boolean; FHorzSplitterWidth: Integer; FHotTrack: Boolean; FRotateResourceCaptions: Boolean; FScheduler: TcxCustomScheduler; FShowAdditionalTimeZone: Boolean; FShowHints: Boolean; FStartOfWeek: TcxStartOfWeek; FTimeZoneLabels: array[0..1] of string; FTimeZones: array[0..1] of Integer; FVertSplitterWidth: Integer; FViewPosition: TcxSchedulerViewPosition; FWorkDays: TDays; FWorkFinish: TTime; FWorkStart: TTime; function GetDateTimeHelperClass: TcxSchedulerDateTimeHelperClass; function GetTimeZone(AIndex: Integer): Integer; function GetTimeZoneLabel(AIndex: Integer): string; procedure SetDayBorderColor(AValue: TColor); procedure SetShowEventsWithoutResource(AValue: Boolean); procedure SetGroupSeparatorWidth(AValue: Integer); procedure SetGroupingKind(AValue: TcxSchedulerGroupingKind); procedure SetHideSelection(AValue: Boolean); procedure SetHorzSplitterWidth(AValue: Integer); procedure SetRotateResourceCaptions(AValue: Boolean); procedure SetShowAdditionalTimeZone(AValue: Boolean); procedure SetSplitterWidth(AValue: Integer; var AWidth: Integer); procedure SetStartOfWeek(AValue: TcxStartOfWeek); procedure SetTimeZone(AIndex, AValue: Integer); procedure SetTimeZoneLabel(AIndex: Integer; const AValue: string); procedure SetVertSplitterWidth(AValue: Integer); procedure SetViewPosition(AValue: TcxSchedulerViewPosition); procedure SetWorkDays(AValue: TDays); procedure SetWorkFinish(AValue: TTime); procedure SetWorkStart(AValue: TTime); function IsTimeZoneLabelStored(AIndex: Integer): Boolean; protected procedure CalculateActualStartOfWeek; procedure Changed; virtual; function GetOwner: TPersistent; override; function IsWorkDaysStored: Boolean; function IsWorkFinishStored: Boolean; function IsWorkStartStored: Boolean; function IsWorkTime(const ADateTime: TDateTime): Boolean; property DateTimeHelper: TcxSchedulerDateTimeHelperClass read GetDateTimeHelperClass; property HotTrack: Boolean read FHotTrack write FHotTrack default False;//True; public constructor Create(AOwner: TcxCustomScheduler); virtual; procedure Assign(Source: TPersistent); override; property ActualStartOfWeek: TDay read FActualStartOfWeek; property Scheduler: TcxCustomScheduler read FScheduler; published property AdditionalTimeZone: Integer index 0 read GetTimeZone write SetTimeZone default -1; property AdditionalTimeZoneLabel: string index 0 read GetTimeZoneLabel write SetTimeZoneLabel stored IsTimeZoneLabelStored; property CurrentTimeZone: Integer index 1 read GetTimeZone write SetTimeZone default -1; property CurrentTimeZoneLabel: string index 1 read GetTimeZoneLabel write SetTimeZoneLabel stored IsTimeZoneLabelStored; property DayBorderColor: TColor read FDayBorderColor write SetDayBorderColor default clDefault; property ShowEventsWithoutResource: Boolean read FShowEventsWithoutResource write SetShowEventsWithoutResource default False; property GroupSeparatorWidth: Integer read FGroupSeparatorWidth write SetGroupSeparatorWidth default cxDefaultGroupSeparatorWidth; property GroupingKind: TcxSchedulerGroupingKind read FGroupingKind write SetGroupingKind default gkDefault; property HideSelection: Boolean read FHideSelection write SetHideSelection default False; property HorzSplitterWidth: Integer read FHorzSplitterWidth write SetHorzSplitterWidth default cxDefaultSplitterWidth; property RotateResourceCaptions: Boolean read FRotateResourceCaptions write SetRotateResourceCaptions default True; property ShowAdditionalTimeZone: Boolean read FShowAdditionalTimeZone write SetShowAdditionalTimeZone default False; property ShowHints: Boolean read FShowHints write FShowHints default True; property StartOfWeek: TcxStartOfWeek read FStartOfWeek write SetStartOfWeek default swSystem; property VertSplitterWidth: Integer read FVertSplitterWidth write SetVertSplitterWidth default cxDefaultSplitterWidth; property ViewPosition: TcxSchedulerViewPosition read FViewPosition write SetViewPosition default vpLeft; property WorkDays: TDays read FWorkDays write SetWorkDays stored IsWorkDaysStored; property WorkFinish: TTime read FWorkFinish write SetWorkFinish stored IsWorkFinishStored; property WorkStart: TTime read FWorkStart write SetWorkStart stored IsWorkStartStored; end; { TcxSchedulerViewHitTest } TcxEventDragKind = (edkNone, edkEventDragRect, edkMoveEvent, edkResizeStart, edkResizeEnd); TcxSchedulerViewHitTest = class(TcxSchedulerSubControlHitTest) private function GetHitAtEvent: Boolean; protected FNeedShowHint: Boolean; FEventBounds: TRect; FResource: TcxSchedulerStorageResourceItem; procedure Clear; override; function GetHitEvent: TcxSchedulerControlEvent; virtual; property NeedShowHint: Boolean read FNeedShowHint; public function GetDragKind: TcxEventDragKind; virtual; property HitAtEvent: Boolean read GetHitAtEvent; property HitAtResource: Boolean index htcResource read GetBitState; property Event: TcxSchedulerControlEvent read GetHitEvent; property Resource: TcxSchedulerStorageResourceItem read FResource; end; { TcxSchedulerEditController } TcxSchedulerEditController = class private FEdit: TcxCustomEdit; FEditData: TcxCustomEditData; FEditDate: TDateTime; FEditList: TcxInplaceEditList; FEditProperties: TcxCustomEditProperties; FEditResource: TcxSchedulerStorageResourceItem; FEvent: TcxSchedulerControlEvent; FFocused: Boolean; FIsEditing: Boolean; FIsNewEvent: Boolean; FOwner: TcxCustomScheduler; function CanAccept: Boolean; function GetController: TcxSchedulerViewController; function GetEditVisible: Boolean; function GetView: TcxSchedulerCustomView; procedure SetEditVisible(Value: Boolean); protected function GetEditRect(var R: TRect; const ADate: TDateTime; AResource: TcxSchedulerStorageResourceItem; AMakeVisible: Boolean = False): Boolean; virtual; procedure EditAfterKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); virtual; procedure EditExit(Sender: TObject); virtual; procedure EditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); virtual; procedure EditKeyPress(Sender: TObject; var Key: Char); virtual; procedure EditKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); virtual; procedure EditPostEditValue(Sender: TObject); virtual; function InitEdit(AEvent: TcxSchedulerControlEvent): Boolean; virtual; function IsKeyForControl(var AKey: Word; Shift: TShiftState): Boolean; virtual; procedure PrepareEdit(AEdit: TcxCustomEdit); virtual; property EditProperties: TcxCustomEditProperties read FEditProperties; property EditData: TcxCustomEditData read FEditData; property Event: TcxSchedulerControlEvent read FEvent; public constructor Create(AOwner: TcxCustomScheduler); virtual; destructor Destroy; override; procedure Activate(AEvent: TcxSchedulerControlEvent); overload; procedure Activate(AEvent: TcxSchedulerControlEvent; const APos: TPoint; AShift: TShiftState); overload; procedure Activate(AEvent: TcxSchedulerControlEvent; Key: Char); overload; procedure CloseEdit(Accepted: Boolean); virtual; procedure Init(const AEditDate: TDateTime; AResource: TcxSchedulerStorageResourceItem; AIsNewEvent: Boolean = False); procedure UpdateEdit; virtual; procedure UpdateValue; virtual; property Controller: TcxSchedulerViewController read GetController; property Edit: TcxCustomEdit read FEdit; property EditVisible: Boolean read GetEditVisible write SetEditVisible; property Focused: Boolean read FFocused write FFocused; property IsEditing: Boolean read FIsEditing; property Scheduler: TcxCustomScheduler read FOwner; property View: TcxSchedulerCustomView read GetView; end; { TcxSchedulerViewNavigation } TcxSchedulerViewNavigation = class private FView: TcxSchedulerCustomView; function GetScheduler: TcxCustomScheduler; function GetSelAnchor: TDateTime; function GetSelRealStart: TDateTime; function GetSelFinish: TDateTime; function GetSelResource: TcxSchedulerStorageResourceItem; function GetSelStart: TDateTime; function GetTimeIncrement: TDateTime; protected FCurrentAnchor: TDateTime; FCurrentResource: TcxSchedulerStorageResourceItem; FShift: TShiftState; procedure DoKeyDown(var AKey: Word; AShift: TShiftState); virtual; function IsKeyNavigation(var AKey: Word; AShift: TShiftState): Boolean; virtual; function IsSingleLine: Boolean; function GetResourceItem: TcxSchedulerStorageResourceItem; virtual; procedure KeyDown(var AKey: Word; AShift: TShiftState); virtual; procedure ReplaceDate(ADate: TDateTime; AResource: TcxSchedulerStorageResourceItem = nil); public constructor Create(AView: TcxSchedulerCustomView); procedure CheckSelection; procedure ReplaceSelParams(const ASelStart, ASelFinish: TDateTime); overload; procedure ReplaceSelParams(const ASelStart, ASelFinish: TDateTime; AResource: TcxSchedulerStorageResourceItem); overload; procedure SetSelAnchor(const Anchor: TDateTime; AShift: TShiftState); overload; procedure SetSelAnchor(const Anchor: TDateTime; AShift: TShiftState; AResource: TcxSchedulerStorageResourceItem); overload; procedure ValidateSelection(var ASelStart, ASelFinish: TDateTime; var AResource: TcxSchedulerStorageResourceItem); virtual; property SelAnchor: TDateTime read GetSelAnchor; property SelFinish: TDateTime read GetSelFinish; property SelRealStart: TDateTime read GetSelRealStart; property SelResource: TcxSchedulerStorageResourceItem read GetSelResource; property SelStart: TDateTime read GetSelStart; property Scheduler: TcxCustomScheduler read GetScheduler; property TimeIncrement: TDateTime read GetTimeIncrement; property View: TcxSchedulerCustomView read FView; end; { TcxSchedulerViewController } TcxSchedulerViewController = class(TcxSchedulerSubControlController) private FEditShowingTimer: TTimer; FEditShowingTimerItem: TcxSchedulerControlEvent; FDragEventHelper: TcxDragEventHelper; FDragEvent: TcxSchedulerControlEvent; FDragKind: TcxEventDragKind; FLockShowEditorOnMouseClick: Boolean; FNavigation: TcxSchedulerViewNavigation; FStartDragFlags: Int64; FStartDragHitTime: TDateTime; FStartDragResource: TcxSchedulerStorageResourceItem; procedure EditShowingTimerHandler(Sender: TObject); function GetHitTest: TcxSchedulerViewHitTest; // function GetHotTrackController: TcxSchedulerHotTrackController; function GetEditController: TcxSchedulerEditController; function GetIsEditing: Boolean; function GetScheduler: TcxCustomScheduler; function GetView: TcxSchedulerCustomView; procedure ShowEventEditor(AEvent: TcxSchedulerControlEvent); procedure StartEditShowingTimer(AEvent: TcxSchedulerControlEvent); procedure StopEditShowingTimer; protected FStartSelAnchor: TDateTime; FBeforeFocusedEvent: TcxSchedulerControlEvent; procedure BeforeMouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure CancelScroll; virtual; function CanDrag(X, Y: Integer): Boolean; override; procedure CheckOpenInplaceEditorOnMouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); virtual; procedure CheckScrolling(const APos: TPoint); virtual; procedure CloseInplaceEdit; function CreateDragEventHelper: TcxDragEventHelper; virtual; function CreateNavigation: TcxSchedulerViewNavigation; virtual; function CreateResizeEventHelper: TcxEventSizingHelper; virtual; procedure DoCancelMode; override; procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); override; procedure EndDrag(Target: TObject; X, Y: Integer); override; function GetDragAndDropObjectClass: TcxDragAndDropObjectClass; override; function GetResourceReadOnly: Boolean; function IsCaptionAvailable: Boolean; function IsDragOperation: Boolean; procedure KeyDown(var Key: Word; Shift: TShiftState); override; procedure KeyPress(var Key: Char); override; // procedure KeyUp(var Key: Word; Shift: TShiftState); override; // procedure MouseEnter; override; // procedure MouseLeave; override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure RecreateNavigation; procedure StartDrag(var DragObject: TDragObject); override; function StartDragAndDrop(const P: TPoint): Boolean; override; procedure SyncEventSelection(AEvent: TcxSchedulerControlEvent); virtual; procedure UnselectEvents; procedure UpdateEventSelection(AEvent: TcxSchedulerControlEvent; Button: TMouseButton; Shift: TShiftState); property EditController: TcxSchedulerEditController read GetEditController; property DragEventHelper: TcxDragEventHelper read FDragEventHelper; property HitTest: TcxSchedulerViewHitTest read GetHitTest; // property HotTrackController: TcxSchedulerHotTrackController read GetHotTrackController; property View: TcxSchedulerCustomView read GetView; public constructor Create(AOwner: TcxSchedulerSubControl); override; destructor Destroy; override; function CanCreateEventUsingDialog: Boolean; virtual; function CanCreateEventUsingInplaceEdit: Boolean; virtual; function CanEditEvent(AEvent: TcxSchedulerControlEvent; AInplace: Boolean): Boolean; virtual; function CanShowEventDialog: Boolean; virtual; procedure DeleteSelectedEvents; function IsEventEditing(AEvent: TcxSchedulerControlEvent; AResource: TcxSchedulerStorageResourceItem): Boolean; procedure SelectSingleEvent(AEvent: TcxSchedulerControlEvent; ADate: TDateTime; AMakeVisible: Boolean = True); property DragEvent: TcxSchedulerControlEvent read FDragEvent; property DragKind: TcxEventDragKind read FDragKind; property IsEditing: Boolean read GetIsEditing; property Navigation: TcxSchedulerViewNavigation read FNavigation; property Scheduler: TcxCustomScheduler read GetScheduler; property StartDragFlags: Int64 read FStartDragFlags; property StartDragHitTime: TDateTime read FStartDragHitTime; property StartDragResource: TcxSchedulerStorageResourceItem read FStartDragResource; end; { TcxDragHelper } TcxDragHelper = class private FScheduler: TcxCustomScheduler; function GetController: TcxSchedulerViewController; function GetEvents: TcxSchedulerCachedEventList; function GetHitTest: TcxSchedulerViewHitTest; protected FPrevHitFlags: Int64; FPrevHitTime: TDateTime; FPrevHitResource: TcxSchedulerStorageResourceItem; FStartHitTime: TDateTime; FStartHitFlags: Int64; FStartResource: TcxSchedulerStorageResourceItem; // virtuals procedure BeginDrag; virtual; procedure DragOver(const P: TPoint; State: TDragState; var Accepted: Boolean); virtual; procedure EndDrag(Accepted: Boolean); virtual; function GetOriginHitTestMask: Int64; virtual; procedure GetOriginState; virtual; function HasChangedState: Boolean; virtual; function IsAtOrigin: Boolean; virtual; function IsShowResources: Boolean; function IsValidTime: Boolean; virtual; procedure RefreshCurrentView; virtual; procedure SetSelection; virtual; procedure UpdateState; virtual; property Controller: TcxSchedulerViewController read GetController; property Events: TcxSchedulerCachedEventList read GetEvents; property HitTest: TcxSchedulerViewHitTest read GetHitTest; property Scheduler: TcxCustomScheduler read FScheduler; public constructor Create(AScheduler: TcxCustomScheduler); virtual; end; { TcxDragEventHelper } TcxSchedulerDragObject = class(TcxDragControlObject) private FUseInternalCursors: Boolean; protected function GetDragCursor(Accepted: Boolean; X, Y: Integer): TCursor; override; public constructor Create(AControl: TControl); override; end; TcxDragEventHelper = class(TcxDragHelper) private FDragObject: TDragObject; FInNavigator: Boolean; FSaveCursor: TCursor; function GetClones: TcxSchedulerFilteredEventList; function GetDateNavigator: TcxSchedulerCustomDateNavigator; function GetViewInfo: TcxSchedulerCustomViewViewInfo; protected FPrevIsDragCopy: Boolean; procedure ApplyChanges; virtual; procedure BeginDrag; override; procedure CheckAccepted(var Accepted: Boolean); virtual; procedure CheckVisibility(Accepted: Boolean); procedure CorrectAllDayEventProperty; virtual; procedure DragOver(const P: TPoint; State: TDragState; var Accepted: Boolean); override; procedure EndDrag(Accepted: Boolean); override; function GetClonesVisible(Accepted: Boolean): Boolean; virtual; function GetIsDragCopy: Boolean; virtual; procedure GetOriginState; override; function GetSourcesVisible(Accepted: Boolean): Boolean; virtual; function HasChangedState: Boolean; override; function IsValidNavigatorDate: Boolean; virtual; function IsValidTime: Boolean; override; procedure PrepareClones; procedure ProcessDateNavigator; procedure RestoreAllDayProperties; procedure SetSelection; override; procedure UpdateClones; virtual; procedure UpdateClonesTime; virtual; procedure UpdateDateNavigator(var Accepted: Boolean); virtual; procedure UpdateEventProperties; virtual; procedure UpdateState; override; property Clones: TcxSchedulerFilteredEventList read GetClones; property DateNavigator: TcxSchedulerCustomDateNavigator read GetDateNavigator; property DragObject: TDragObject read FDragObject; property InNavigator: Boolean read FInNavigator; property IsDragCopy: Boolean read GetIsDragCopy; property ViewInfo: TcxSchedulerCustomViewViewInfo read GetViewInfo; end; { TcxEventSizingHelper } TcxEventSizingHelper = class(TcxDragHelper) private function GetEvent: TcxSchedulerControlEvent; function GetHitTest: TcxSchedulerViewHitTest; protected procedure BeginDrag; override; procedure DragOver(const P: TPoint; State: TDragState; var Accepted: Boolean); override; procedure EndDrag(Accepted: Boolean); override; function GetDragCursor(Accepted: Boolean): TCursor; virtual; function IsValidTime: Boolean; override; // Event handling procedure CalcAllDayEvent; virtual; function GetFinishTime: TDateTime; virtual; function GetStartTime: TDateTime; virtual; procedure UpdateEventBounds; virtual; property Event: TcxSchedulerControlEvent read GetEvent; property HitTest: TcxSchedulerViewHitTest read GetHitTest; end; { TcxSchedulerDragAndDropObject } TcxSchedulerDragAndDropObject = class(TcxDragAndDropObject) private FSizingHelper: TcxEventSizingHelper; FScheduler: TcxCustomScheduler; function GetController: TcxSchedulerViewController; function GetHitTest: TcxSchedulerViewHitTest; protected procedure BeginDragAndDrop; override; procedure DragAndDrop(const P: TPoint; var Accepted: Boolean); override; procedure EndDragAndDrop(Accepted: Boolean); override; function GetDragAndDropCursor(Accepted: Boolean): TCursor; override; public constructor Create(AControl: TcxControl); override; property Controller: TcxSchedulerViewController read GetController; property SizingHelper: TcxEventSizingHelper read FSizingHelper; property HitTest: TcxSchedulerViewHitTest read GetHitTest; property Scheduler: TcxCustomScheduler read FScheduler; end; { TcxSchedulerHintController } TcxSchedulerHintController = class protected FAutoHide: Boolean; FHintWindow: THintWindow; FOwner: TcxCustomScheduler; FHintFlags: Integer; FHintRect: TRect; FHintText: string; FTimer: TTimer; procedure CheckHintClass; procedure HideHint; virtual; procedure ShowHint; virtual; procedure StartHideHintTimer; procedure StartShowHintTimer; procedure StopTimer; procedure TimerHandler(Sender: TObject); public constructor Create(AOwner: TcxCustomScheduler); virtual; destructor Destroy; override; procedure Activate(const AHintRect: TRect; const AHintText: string; AImmediateHint: Boolean = False); virtual; function CalcHintRect(AMaxWidth: Integer; const AHintText: string; AFlags: Integer): TRect; procedure Hide; procedure Reset; property Scheduler: TcxCustomScheduler read FOwner; end; { TcxSchedulerEventHitTestController } TcxSchedulerEventHitTestController = class private function GetHintController: TcxSchedulerHintController; function GetHitTest: TcxSchedulerViewHitTest; protected FOwner: TcxCustomScheduler; FPrevHintEvent: TcxSchedulerControlEvent; public constructor Create(AOwner: TcxCustomScheduler); virtual; procedure MouseMove(X, Y: Integer; AShift: TShiftState); virtual; property HitTest: TcxSchedulerViewHitTest read GetHitTest; property HintController: TcxSchedulerHintController read GetHintController; property Scheduler: TcxCustomScheduler read FOwner; end; { TcxSchedulerCustomView } TcxSchedulerCustomView = class(TcxSchedulerSubControl) private FCanShow: Boolean; function GetActive: Boolean; function GetCanShow: Boolean; function GetController: TcxSchedulerViewController; function GetDragCloneEventList: TcxSchedulerFilteredEventList; function GetEventList: TcxSchedulerCachedEventList; function GetHitTest: TcxSchedulerViewHitTest; function GetOptionsView: TcxSchedulerOptionsView; function GetResources: TcxSchedulerStorageResourceItems; function GetSelectedDays: TcxSchedulerDateList; function GetWorkDays: TDays; function GetWorkFinish: TDateTime; function GetWorkStart: TDateTime; procedure SetActive(AValue: Boolean); procedure SetCanShow(AValue: Boolean); protected function CreateController: TcxSchedulerSubControlController; override; function CreateHitTest: TcxSchedulerSubControlHitTest; override; procedure DateChanged; virtual; procedure DoLayoutChanged; override; function DoShowPopupMenu(X, Y: Integer): Boolean; virtual; function EventContentSelected(AEvent: TcxSchedulerControlEvent): Boolean; virtual; function GetClientRect: TRect; override; function GetDateOffset: Integer; function GetGroupingKind: TcxSchedulerGroupingKind; virtual; function GetHScrollBarBounds: TRect; override; function GetEditRectForEvent(AEvent: TcxSchedulerControlEvent; const ADate: TDateTime; AResource: TcxSchedulerStorageResourceItem): TRect; virtual; function GetEditStyle(AEvent: TcxSchedulerControlEvent): TcxCustomEditStyle; virtual; function GetEditProperties(AEvent: TcxSchedulerControlEvent): TcxCustomEditProperties; virtual; function GetEventVisibility(AEvent: TcxSchedulerControlEvent): Boolean; virtual; function GetFirstVisibleDate: TDateTime; virtual; function GetLastVisibleDate: TDateTime; virtual; function GetSizeGripBounds: TRect; override; function GetTimeIncrement: TDateTime; virtual; function GetVScrollBarBounds: TRect; override; function GetVisibleDaysRange: Integer; virtual; procedure InitEventBySelectedPeriod(AEvent: TcxSchedulerEvent; AllDay: Boolean; ARecurrence: Boolean; AInplaceEditing: Boolean); virtual; function IsAllDaySelection: Boolean; function IsDayView: Boolean; virtual; function IsShowResources: Boolean; virtual; function IsWorkTime(AResourceItem: TcxSchedulerStorageResourceItem; const ADateTime: TDateTime): Boolean; procedure MakeEventVisible(AEvent: TcxSchedulerControlEvent; const ADate: TDateTime; AResource: TcxSchedulerStorageResourceItem); virtual; procedure PeriodChanged; override; procedure Scroll(AScrollBarKind: TScrollBarKind; AScrollCode: TScrollCode; var AScrollPos: Integer); virtual; procedure ScrollSelectedDays(AScrollDelta: Integer); overload; virtual; procedure ScrollSelectedDays(AForward: Boolean; ANeedDate: TDateTime; AIsByPage: Boolean); overload; virtual; procedure ScrollVisibleDays(AScrollUp: Boolean); virtual; procedure TimeChanged; virtual; procedure VisibleChanged; override; // hint procedure HideHintOnScroll; virtual; procedure ShowHintOnScroll(const ADate: TDateTime); virtual; property Controller: TcxSchedulerViewController read GetController; property EventList: TcxSchedulerCachedEventList read GetEventList; property OptionsView: TcxSchedulerOptionsView read GetOptionsView; property Resources: TcxSchedulerStorageResourceItems read GetResources; property WorkDays: TDays read GetWorkDays; property WorkStart: TDateTime read GetWorkStart; property WorkFinish: TDateTime read GetWorkFinish; public constructor Create(AOwner: TcxCustomScheduler); override; procedure Assign(Source: TPersistent); override; property Active: Boolean read GetActive write SetActive default False; property CanShow: Boolean read GetCanShow write SetCanShow default True; property DragCloneEventList: TcxSchedulerFilteredEventList read GetDragCloneEventList; property FirstVisibleDate: TDateTime read GetFirstVisibleDate; property HitTest: TcxSchedulerViewHitTest read GetHitTest; property LastVisibleDate: TDateTime read GetLastVisibleDate; property SelectedDays: TcxSchedulerDateList read GetSelectedDays; property StartOfWeek; end; { TcxSchedulerCustomViewViewInfo } TcxSchedulerCustomViewViewInfo = class(TcxSchedulerSubControlViewInfo) protected FEvents: TcxSchedulerCachedEventList; FSelectedDays: TcxSchedulerDateList; function GetSchedulerEventsList: TcxSchedulerCachedEventList; function DoGetEventDisplayText(AEvent: TcxSchedulerControlEvent): string; virtual; procedure SetEventsVisibility(AShowSources, AShowClones: Boolean; AForceRepaint: Boolean = False); virtual; property Events: TcxSchedulerCachedEventList read FEvents; property SelectedDays: TcxSchedulerDateList read FSelectedDays; end; { TcxSchedulerCustomDataNavigator } TcxSchedulerCustomDateNavigator = class(TcxSchedulerSubControl) private FLockCount: Integer; FSaveRealFirstDate: TDateTime; FSaveRealLastDate: TDateTime; FSaveSelectionList: TcxSchedulerDateList; function GetEventDays: TcxSchedulerDateList; protected FSavedSize: TSize; procedure CheckSizes; virtual; abstract; procedure CheckChanges; virtual; procedure DoPeriodChangedEvent; virtual; abstract; procedure DoSelectionChangedEvent; virtual; abstract; procedure DoScrollSelection(AForward: Boolean; ANeedDate: TDateTime; AIsByPage: Boolean); overload; virtual; abstract; procedure DoScrollSelection(AScrollDelta: Integer); overload; virtual; abstract; function GetMonthSize: TSize; virtual; function GetSelection: TcxSchedulerDateList; virtual; function GetShowDatesContainingEventsInBold: Boolean; virtual; abstract; function GetRealFirstDate: TDateTime; virtual; abstract; function GetRealLastDate: TDateTime; virtual; abstract; procedure PeriodChanged; override; procedure SaveSize; procedure SaveState; virtual; procedure ScrollSelection(AForward: Boolean; ANeedDate: TDateTime; AIsByPage: Boolean); overload; procedure ScrollSelection(AScrollDelta: Integer); overload; procedure SetIntegralSizes; virtual; abstract; procedure UpdateDragging; virtual; abstract; procedure UpdateSelection; virtual; abstract; property EventDays: TcxSchedulerDateList read GetEventDays; public constructor Create(AOwner: TcxCustomScheduler); override; destructor Destroy; override; procedure BeginUpdate; procedure CancelUpdates; procedure EndUpdate; end; { IcxSchedulerStylesAdapter } IcxSchedulerStylesAdapter = interface ['{0BFEA90D-0CE8-4ED1-88E8-71A3396186F3}'] function GetContentParams(const ADateTime: TDateTime; AResource: TcxSchedulerStorageResourceItem): TcxViewParams; overload; function GetContentParams(const ADateTime: TDateTime; ALightColor: Boolean; AResource: TcxSchedulerStorageResourceItem): TcxViewParams; overload; function GetDayHeaderParams(const ADateTime: TDateTime): TcxViewParams; function GetEventParams(AEvent: TcxSchedulerEvent): TcxViewParams; function GetResourceHeaderParams(AResource: TcxSchedulerStorageResourceItem): TcxViewParams; // hard style function GetDayHeaderStyle: TcxStyle; function GetResourceHeaderStyle: TcxStyle; end; { TcxSchedulerStyles } TcxSchedulerOnGetDayHeaderStyleEvent = procedure(Sender: TObject; const ADate: TDateTime; var AStyle: TcxStyle) of object; TcxSchedulerOnGetResourceHeaderStyleEvent = procedure(Sender: TObject; AResource: TcxSchedulerStorageResourceItem; var AStyle: TcxStyle) of object; TcxSchedulerOnGetContentStyleEvent = procedure(Sender: TObject; AResource: TcxSchedulerStorageResourceItem; const ADateTime: TDateTime; var AStyle: TcxStyle) of object; TcxSchedulerOnGetEventStyleEvent = procedure(Sender: TObject; AEvent: TcxSchedulerEvent; var AStyle: TcxStyle) of object; TcxSchedulerStyles = class(TcxStyles, IcxSchedulerStylesAdapter) private FScheduler: TcxCustomScheduler; FOnGetContentStyle: TcxSchedulerOnGetContentStyleEvent; FOnGetDayHeaderStyle: TcxSchedulerOnGetDayHeaderStyleEvent; FOnGetEventStyle: TcxSchedulerOnGetEventStyleEvent; FOnGetResourceHeaderStyle: TcxSchedulerOnGetResourceHeaderStyleEvent; function GetPainter: TcxCustomLookAndFeelPainterClass; function GetPainterHelperClass: TcxSchedulerPainterHelperClass; function GetResources: TcxSchedulerStorageResourceItems; protected procedure Changed(AIndex: Integer); override; function EventContentSelected(AEvent: TcxSchedulerControlEvent): Boolean; procedure GetDefaultViewParams(Index: Integer; AData: TObject; out AParams: TcxViewParams); override; // IcxSchedulerStylesAdapter function GetDayHeaderStyle: TcxStyle; function GetEventParams(AEvent: TcxSchedulerEvent): TcxViewParams; function GetResourceHeaderStyle: TcxStyle; property Painter: TcxCustomLookAndFeelPainterClass read GetPainter; property PainterHelper: TcxSchedulerPainterHelperClass read GetPainterHelperClass; property Resources: TcxSchedulerStorageResourceItems read GetResources; public constructor Create(AOwner: TPersistent); override; procedure Assign(Source: TPersistent); override; function GetBackgroundParams: TcxViewParams; function GetContentParams(const ADateTime: TDateTime; AResource: TcxSchedulerStorageResourceItem = nil): TcxViewParams; overload; function GetContentParams(const ADateTime: TDateTime; ALightColor: Boolean; AResource: TcxSchedulerStorageResourceItem = nil): TcxViewParams; overload; function GetDayHeaderParams(const ADate: TDateTime): TcxViewParams; function GetGroupSeparatorParams: TcxViewParams; function GetResourceHeaderParams(AResource: TcxSchedulerStorageResourceItem): TcxViewParams; function GetSelectionParams: TcxViewParams; function GetSplitterParams(AKind: TcxSchedulerSplitterKind): TcxViewParams; function GetEventContentParams(AEvent: TcxSchedulerEvent): TcxViewParams; function IsEventStyleAssigned(AEvent: TcxSchedulerEvent): Boolean; // define colors functions property Scheduler: TcxCustomScheduler read FScheduler; published property Background: TcxStyle index cxcsBackground read GetValue write SetValue; property Content: TcxStyle index cxcsContent read GetValue write SetValue; property Event: TcxStyle index cxcsEvent read GetValue write SetValue; property GroupSeparator: TcxStyle index cxcsGroupSeparator read GetValue write SetValue; property DayHeader: TcxStyle index cxcsDayHeader read GetValue write SetValue; property HorzSplitter: TcxStyle index cxcsHSplitter read GetValue write SetValue; property ResourceHeader: TcxStyle index cxcsResourceHeader read GetValue write SetValue; property Selection: TcxStyle index cxcsSelection read GetValue write SetValue; property VertSplitter: TcxStyle index cxcsVSplitter read GetValue write SetValue; property OnGetContentStyle: TcxSchedulerOnGetContentStyleEvent read FOnGetContentStyle write FOnGetContentStyle; property OnGetDayHeaderStyle: TcxSchedulerOnGetDayHeaderStyleEvent read FOnGetDayHeaderStyle write FOnGetDayHeaderStyle; property OnGetEventStyle: TcxSchedulerOnGetEventStyleEvent read FOnGetEventStyle write FOnGetEventStyle; property OnGetResourceHeaderStyle: TcxSchedulerOnGetResourceHeaderStyleEvent read FOnGetResourceHeaderStyle write FOnGetResourceHeaderStyle; end; { TcxCustomScheduler } TcxSchedulerCanShowViewEvent = procedure(Sender: TObject; AView: TcxSchedulerCustomView; var Allow: Boolean) of object; TcxSchedulerGetEventEditPropertiesEvent = procedure(Sender: TObject; AEvent: TcxSchedulerControlEvent; var AProperties: TcxCustomEditProperties) of object; TcxSchedulerGetEventText = procedure(Sender: TObject; AEvent: TcxSchedulerControlEvent; var AText: string) of object; TcxSchedulerInitEditEvent = procedure(Sender: TObject; AEdit: TcxCustomEdit) of object; TcxSchedulerViewTypeChangedEvent = procedure(Sender: TObject; APrevView, ANewView: TcxSchedulerCustomView) of object; TcxSchedulerIsWorkTimeEvent = procedure(Sender: TObject; AResource: TcxSchedulerStorageResourceItem; const ATime: TDateTime; var AIsWork: Boolean) of object; TcxSchedulerBeforeDeleting = procedure (Sender: TcxCustomScheduler; AEvent: TcxSchedulerControlEvent; var Allow: Boolean) of object; TcxSchedulerBeforeDragEvent = procedure (Sender: TcxCustomScheduler; AEvent: TcxSchedulerControlEvent; X, Y: Integer; var Allow: Boolean) of object; TcxSchedulerBeforeEditing = procedure (Sender: TcxCustomScheduler; AEvent: TcxSchedulerControlEvent; AInplace: Boolean; var Allow: Boolean) of object; TcxSchedulerAfterDragEvent = procedure (Sender: TcxCustomScheduler; Target: TObject; X, Y: Integer; var Accept: Boolean) of object; TcxSchedulerBeforeSizingEvent = procedure (Sender: TcxCustomScheduler; AEvent: TcxSchedulerControlEvent; X, Y: Integer; var Allow: Boolean) of object; TcxSchedulerAfterSizingEvent = procedure (Sender: TcxCustomScheduler; X, Y: Integer; var Accept: Boolean) of object; TcxSchedulerAfterEditing = procedure (Sender: TcxCustomScheduler; AEvent: TcxSchedulerControlEvent) of object; TcxSchedulerEventSelectionChangedEvent = procedure (Sender: TcxCustomScheduler; AEvent: TcxSchedulerControlEvent) of object; TcxCustomScheduler = class(TcxControl, IcxSchedulerStorageListener, IcxFormatControllerListener, IcxFormatControllerListener2, IcxStoredObject) private FActiveControl: TcxSchedulerSubControl; FAligningSubControls: Boolean; FBackground: TcxSchedulerSubControl; {$IFNDEF DEBUGPAINT} FBitmap: TBitmap; FBitmapCanvas: TcxCanvas; {$ENDIF} FBoundsChanging: Boolean; FCanModified: Boolean; FCanvas: TcxCanvas; FCaptureControl: TcxSchedulerSubControl; FContentPopupMenu: TcxSchedulerContentPopupMenu; FContentPopupMenuEvents: TNotifyEvent; FControlBox: TcxSchedulerControlBox; FControlFlags: TcxControlFlags; FCurrentView: TcxSchedulerCustomView; FDateNavigator: TcxSchedulerCustomDateNavigator; FDefaultProperties: TcxCustomEditProperties; FEditController: TcxSchedulerEditController; FEditStyle: TcxCustomEditStyle; FEventDays: TcxSchedulerDateList; FEventHitTestController: TcxSchedulerEventHitTestController; FEventList: TcxSchedulerCachedEventList; FEventOperations: TcxSchedulerEventOperations; FEventPopupMenu: TcxSchedulerEventPopupMenu; FEventPopupMenuEvents: TNotifyEvent; FHintController: TcxSchedulerHintController; FHorzSplitter: TcxSchedulerSplitter; FHorzSplitterShowing: Boolean; FIsDragCanceled: Boolean; FKeyboardListener: TcxSchedulerSubControl; FLockCount: Integer; FLockRefresh: Integer; FOnInitEdit: TcxSchedulerInitEditEvent; FOptionsCustomize: TcxSchedulerOptionsCustomize; FOptionsView: TcxSchedulerOptionsView; FPrevBounds: TRect; FPrevCopyDragDrop: Boolean; FPrevMousePos: TPoint; FSelectedDays: TcxSchedulerDateList; FSelFinish: TDateTime; FSelResource: TcxSchedulerStorageResourceItem; FSelStart: TDateTime; FStorage: TcxCustomSchedulerStorage; FStoringName: string; FStyles: TcxSchedulerStyles; FStylesEvents: TNotifyEvent; FSubControls: TList; FSubControlsCreated: Boolean; FTextEditProperties: TcxTextEditProperties; FVertSplitter: TcxSchedulerSplitter; FVertSplitterShowing: Boolean; FVisibleChangedCount: Integer; FUpdateTimeTimer: TTimer; FOnAfterDragEvent: TcxSchedulerAfterDragEvent; FOnAfterEditing: TcxSchedulerAfterEditing; FOnAfterSizingEvent: TcxSchedulerAfterSizingEvent; FOnBeforeDeleting: TcxSchedulerBeforeDeleting; FOnBeforeDragEvent: TcxSchedulerBeforeDragEvent; FOnBeforeEditing: TcxSchedulerBeforeEditing; FOnBeforeSizingEvent: TcxSchedulerBeforeSizingEvent; FOnCanShowView: TcxSchedulerCanShowViewEvent; FOnGetEventDisplayText: TcxSchedulerGetEventText; FOnEventSelectionChanged: TcxSchedulerEventSelectionChangedEvent; FOnGetEventEditProperties: TcxSchedulerGetEventEditPropertiesEvent; FOnGetEventHintText: TcxSchedulerGetEventText; FOnIsWorkTime: TcxSchedulerIsWorkTimeEvent; FOnLayoutChanged: TNotifyEvent; FOnSelectionChanged: TNotifyEvent; FOnViewTypeChanged: TcxSchedulerViewTypeChangedEvent; procedure CalcHorzSplitterBounds(AByDateNavigator: Boolean); procedure CalcVertSplitterBounds; procedure CheckHorzSplitterBounds; procedure CheckSplittersVisibilityChanging; procedure CreateUpdateTimeTimer; function GetActiveHitTest: TcxSchedulerSubControlHitTest; function GetCaptureControl: TcxSchedulerSubControl; function GetCaptureController: TcxSchedulerSubControlController; function GetSelectedEventCount: Integer; function GetSelectedEvent(AIndex: Integer): TcxSchedulerControlEvent; function GetSelFinish: TDateTime; function GetSelStart: TDateTime; function GetIsDynamicUpdate: Boolean; function GetStartOfWeek: TDay; function GetStorageActive: Boolean; function GetStorageValid: Boolean; function GetSubControl(AIndex: Integer): TcxSchedulerSubControl; function GetSubControlCount: Integer; function GetVisibleEventCount: Integer; function GetVisibleEvent(AIndex: Integer): TcxSchedulerControlEvent; procedure InitEventBySelection(AEvent: TcxSchedulerEvent; AllDay: Boolean; ARecurrence: Boolean; AInplaceEditing: Boolean); function IsHorzSplitterVisible: Boolean; function IsVertSplitterVisible: Boolean; procedure SetCaptureControl(AValue: TcxSchedulerSubControl); procedure SetContentPopupMenu(AValue: TcxSchedulerContentPopupMenu); procedure SetControlBox(AValue: TcxSchedulerControlBox); procedure SetEventOperations(AValue: TcxSchedulerEventOperations); procedure SetEventPopupMenu(AValue: TcxSchedulerEventPopupMenu); procedure SetOptionsCustomize(AValue: TcxSchedulerOptionsCustomize); procedure SetOptionsView(AValue: TcxSchedulerOptionsView); procedure SetStyles(AValue: TcxSchedulerStyles); procedure SetStorage(AValue: TcxCustomSchedulerStorage); procedure UpdateAlignByDateNavigatorOrControlBox(AByDateNavigator: Boolean); procedure UpdateAlignByView; procedure UpdateControlsBoundsOnHorzSplitterShowing; procedure UpdateControlsBoundsOnVertSplitterShowing; procedure UpdateCurrentViewBounds; procedure UpdateInvisibleSplitterBounds; procedure UpdateTimeHandler(Sender: TObject); procedure WMCancelMode(var Message: TWMCancelMode); message WM_CANCELMODE; procedure WMSetCursor(var Message: TWMSetCursor); message WM_SETCURSOR; procedure WMTimeChange(var Message: TWMTimeChange); message WM_TIMECHANGE; procedure ReadSelectionData(AReader: TReader); procedure ReadSplittersData(AStream: TStream); procedure WriteSelectionData(AWriter: TWriter); procedure WriteSplittersData(AStream: TStream); protected // IcxSchedulerStorageListener procedure StorageChanged(Sender: TObject); procedure StorageRemoved(Sender: TObject); // IcxFormatControllerListener procedure DoStartOfWeekChanged(AOldStartOfWeek, ANewStartOfWeek: TDay); virtual; procedure FormatChanged; virtual; // IcxFormatControllerListener2 procedure TimeChanged; // IcxStoredObject function GetObjectName: string; virtual; function GetProperties(AProperties: TStrings): Boolean; virtual; procedure GetPropertyValue(const AName: string; var AValue: Variant); virtual; procedure SetPropertyValue(const AName: string; const AValue: Variant); virtual; // from TControl procedure AlignControls(AControl: TControl; var Rect: TRect); override; procedure DefineProperties(Filer: TFiler); override; procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; procedure Notification(AComponent: TComponent; Operation: TOperation); override; // methods procedure AlignSubControls(Sender: TcxSchedulerSubControl = nil); virtual; procedure BoundsChanged; override; function CanModified: Boolean; virtual; function CanShowEventDialog: Boolean; function CreateBackground: TcxSchedulerSubControl; virtual; function CreateContentPopupMenu: TcxSchedulerContentPopupMenu; virtual; function CreateControlBox: TcxSchedulerControlBox; virtual; function CreateDateNavigator: TcxSchedulerCustomDateNavigator; virtual; function CreateDefaultView: TcxSchedulerCustomView; virtual; function CreateDefaultEditProperties: TcxCustomEditProperties; virtual; function CreateEditController: TcxSchedulerEditController; virtual; function CreateEventHitTestController: TcxSchedulerEventHitTestController; virtual; function CreateEventList: TcxSchedulerCachedEventList; virtual; function CreateEventOperations: TcxSchedulerEventOperations; virtual; function CreateEventPopupMenu: TcxSchedulerEventPopupMenu; virtual; function CreateHintController: TcxSchedulerHintController; virtual; function CreateOptionsCustomize: TcxSchedulerOptionsCustomize; virtual; function CreateOptionsView: TcxSchedulerOptionsView; virtual; function CreateSplitter(AKind: TcxSchedulerSplitterKind): TcxSchedulerSplitter; virtual; function CreateStyles: TcxSchedulerStyles; virtual; procedure CreateSubClasses; virtual; procedure DateNavigatorSelectionChanged; virtual; procedure DblClick; override; procedure DestroySubClasses; virtual; procedure DoAfterDragEvent(Target: TObject; X, Y: Integer; var Accept: Boolean); virtual; procedure DoAfterEditing(AEvent: TcxSchedulerControlEvent); virtual; procedure DoAfterSizingEvent(X, Y: Integer; var Accept: Boolean); virtual; function DoBeforeDeleting(AEvent: TcxSchedulerControlEvent): Boolean; virtual; function DoBeforeDragEvent(AEvent: TcxSchedulerControlEvent; X, Y: Integer): Boolean; virtual; function DoBeforeEditing(AEvent: TcxSchedulerControlEvent; AInplace: Boolean): Boolean; virtual; function DoBeforeSizingEvent(AEvent: TcxSchedulerControlEvent; X, Y: Integer): Boolean; virtual; procedure DoCalculateLayout(AControl: TcxSchedulerSubControl); virtual; procedure DoCancelMode; override; procedure DoControllerReset(AControl: TcxSchedulerSubControl); virtual; procedure DoCreateEventUsingInplaceEdit(AKey: Char = #0); virtual; procedure DoEventSelectionChanged(AEvent: TcxSchedulerControlEvent); procedure DoGetEventDisplayText(AEvent: TcxSchedulerControlEvent; var AText: string); virtual; procedure DoGetEventEditProperties(AEvent: TcxSchedulerControlEvent; var AProperties: TcxCustomEditProperties); virtual; procedure DoHitTestRecalculate(AControl: TcxSchedulerSubControl); virtual; procedure DoInitEdit(AEdit: TcxCustomEdit); virtual; function DoIsWorkTime(AResourceItem: TcxSchedulerStorageResourceItem; const ADateTime: TDateTime): Boolean; procedure DoCanShowView(AView: TcxSchedulerCustomView; var Allow: Boolean); virtual; procedure DoLayoutChanged; virtual; procedure DoLayoutChangedEvent; virtual; procedure DoSelectionChanged; virtual; function DoShowPopupMenu(AMenu: TComponent; X, Y: Integer): Boolean; override; procedure DoViewTypeChanged(ANewView: TcxSchedulerCustomView); virtual; procedure DoUpdateTime; virtual; procedure DragCanceled; override; procedure FontChanged; override; procedure FocusChanged; override; function GetClientBounds: TRect; override; function GetControlCanvas: TcxCanvas; function GetControlFromPoint(const APoint: TPoint): TcxSchedulerSubControl; virtual; function GetCursor(X, Y: Integer): TCursor; override; function GetDateTimeHelper: TcxSchedulerDateTimeHelperClass; virtual; function GetDesignHitTest(X, Y: Integer; Shift: TShiftState): Boolean; override; function GetEventHintText(AEvent: TcxSchedulerControlEvent): string; virtual; function GetHScrollBarBounds: TRect; override; function GetIsLocked: Boolean; virtual; function GetNextView(AView: TcxSchedulerCustomView): TcxSchedulerCustomView; virtual; function GetPainterHelper: TcxSchedulerPainterHelperClass; virtual; function GetSizeGripBounds: TRect; override; function GetTimeBias: Double; virtual; function GetVScrollBarBounds: TRect; override; function HasResources: Boolean; procedure InitControl; override; procedure InitScrollBarsParameters; override; procedure InternalDeleteEvent(AEvent: TcxSchedulerControlEvent; AIgnoreRecurring: Boolean); procedure InternalDeleteSelectedEvents(AForceDelete, ACheckReadOnly: Boolean); function IsViewAtLeft: Boolean; procedure KeyDown(var Key: Word; Shift: TShiftState); override; procedure KeyPress(var Key: Char); override; procedure KeyUp(var Key: Word; Shift: TShiftState); override; procedure Loaded; override; procedure LookAndFeelChanged(Sender: TcxLookAndFeel; AChangedValues: TcxLookAndFeelValues); override; procedure LockUpdateChanged(ALocking: Boolean); virtual; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure MouseLeave(AControl: TControl); override; procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure Paint; override; procedure PeriodChanged; virtual; procedure RemoveSubControl(AControl: TcxSchedulerSubControl); procedure ReplaceSelParams(ASelStart, ASelFinish: TDateTime; AResource: TcxSchedulerStorageResourceItem); virtual; procedure Scroll(AScrollBarKind: TScrollBarKind; AScrollCode: TScrollCode; var AScrollPos: Integer); override; procedure SetCurrentView(AView: TcxSchedulerCustomView); virtual; procedure SubControlAdd(AControl: TcxSchedulerSubControl); procedure SubControlRemove(AControl: TcxSchedulerSubControl); procedure SynchronizeVisibleDays; virtual; procedure UpdateEventsCache(ACheckDaysInterval: Boolean); virtual; procedure ValidateSelection(ASelection: TcxSchedulerDateList); virtual; procedure ValidateState; procedure ViewVisibleChanged(AView: TcxSchedulerCustomView); virtual; function VisibleGroupingKind: TcxSchedulerGroupingKind; // drag'n'drop support function CanDrag(X, Y: Integer): Boolean; override; procedure DoEndDrag(Target: TObject; X, Y: Integer); override; procedure DoStartDrag(var DragObject: TDragObject); override; procedure DragAndDrop(const P: TPoint; var Accepted: Boolean); override; procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); override; procedure EndDragAndDrop(Accepted: Boolean); override; function GetDragAndDropObjectClass: TcxDragAndDropObjectClass; override; function GetDragObjectClass: TDragControlObjectClass; override; function StartDragAndDrop(const P: TPoint): Boolean; override; property Background: TcxSchedulerSubControl read FBackground; {$IFNDEF DEBUGPAINT} property Bitmap: TBitmap read FBitmap; property BitmapCanvas: TcxCanvas read FBitmapCanvas; {$ENDIF} property Canvas: TcxCanvas read FCanvas; property Capture: TcxSchedulerSubControl read GetCaptureControl write SetCaptureControl; property CaptureController: TcxSchedulerSubControlController read GetCaptureController; property ControlFlags: TcxControlFlags read FControlFlags write FControlFlags; property DefaultProperties: TcxCustomEditProperties read FDefaultProperties; property EditController: TcxSchedulerEditController read FEditController; property EditStyle: TcxCustomEditStyle read FEditStyle; //remove to EditingController property EventHitTestController: TcxSchedulerEventHitTestController read FEventHitTestController write FEventHitTestController; property EventList: TcxSchedulerCachedEventList read FEventList; property HintController: TcxSchedulerHintController read FHintController; property HorzSplitter: TcxSchedulerSplitter read FHorzSplitter; property IsDragCanceled: Boolean read FIsDragCanceled; property IsDynamicUpdate: Boolean read GetIsDynamicUpdate; property IsLocked: Boolean read GetIsLocked; property KeyboardListener: TcxSchedulerSubControl read FKeyboardListener write FKeyboardListener; property LockCount: Integer read FLockCount; property PainterHelper: TcxSchedulerPainterHelperClass read GetPainterHelper; property ParentFont default False; property StartOfWeek: TDay read GetStartOfWeek; property StorageActive: Boolean read GetStorageActive; property StorageValid: Boolean read GetStorageValid; property SubControlCount: Integer read GetSubControlCount; property SubControls[Index: Integer]: TcxSchedulerSubControl read GetSubControl; property VertSplitter: TcxSchedulerSplitter read FVertSplitter; property DragMode default dmAutomatic; property BorderStyle default cxcbsDefault; property OnAfterDragEvent: TcxSchedulerAfterDragEvent read FOnAfterDragEvent write FOnAfterDragEvent; property OnAfterEditing: TcxSchedulerAfterEditing read FOnAfterEditing write FOnAfterEditing; property OnAfterSizingEvent: TcxSchedulerAfterSizingEvent read FOnAfterSizingEvent write FOnAfterSizingEvent; property OnBeforeDeleting: TcxSchedulerBeforeDeleting read FOnBeforeDeleting write FOnBeforeDeleting; property OnBeforeDragEvent: TcxSchedulerBeforeDragEvent read FOnBeforeDragEvent write FOnBeforeDragEvent; property OnBeforeEditing: TcxSchedulerBeforeEditing read FOnBeforeEditing write FOnBeforeEditing; property OnBeforeSizingEvent: TcxSchedulerBeforeSizingEvent read FOnBeforeSizingEvent write FOnBeforeSizingEvent; property OnCanShowView: TcxSchedulerCanShowViewEvent read FOnCanShowView write FOnCanShowView; property OnEventSelectionChanged: TcxSchedulerEventSelectionChangedEvent read FOnEventSelectionChanged write FOnEventSelectionChanged; property OnGetEventDisplayText: TcxSchedulerGetEventText read FOnGetEventDisplayText write FOnGetEventDisplayText; property OnGetEventHintText: TcxSchedulerGetEventText read FOnGetEventHintText write FOnGetEventHintText; property OnGetEventEditProperties: TcxSchedulerGetEventEditPropertiesEvent read FOnGetEventEditProperties write FOnGetEventEditProperties; property OnInitEdit: TcxSchedulerInitEditEvent read FOnInitEdit write FOnInitEdit; property OnIsWorkTime: TcxSchedulerIsWorkTimeEvent read FOnIsWorkTime write FOnIsWorkTime; property OnLayoutChanged: TNotifyEvent read FOnLayoutChanged write FOnLayoutChanged; property OnSelectionChanged: TNotifyEvent read FOnSelectionChanged write FOnSelectionChanged; property OnViewTypeChanged: TcxSchedulerViewTypeChangedEvent read FOnViewTypeChanged write FOnViewTypeChanged; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure BeginUpdate; procedure CreateEventUsingDialog(AllDay: Boolean = False; ARecurrence: Boolean = False); virtual; procedure CreateEventUsingInplaceEdit; procedure DeleteEvent(AEvent: TcxSchedulerControlEvent); virtual; procedure DeleteSelectedEvents(ACheckReadOnly: Boolean = True); procedure EditEventUsingDialog(AEvent: TcxSchedulerControlEvent; ACheckReadOnly: Boolean = True; AForcePatternEditing: Boolean = False); procedure EditEventUsingInplaceEdit(AEvent: TcxSchedulerControlEvent); procedure DragDrop(Source: TObject; X, Y: Integer); override; procedure EndUpdate; function GoToDate(ADate: TDateTime; AViewMode: TcxSchedulerViewMode = vmDay): Boolean; virtual; procedure FullRefresh; virtual; procedure LayoutChanged; procedure MakeEventVisible(AEvent: TcxSchedulerControlEvent; const ADate: TDateTime = NullDate; AResource: TcxSchedulerStorageResourceItem = nil); procedure SelectEvent(AEvent: TcxSchedulerControlEvent; AShift: TShiftState = []); procedure SelectTime(const ASelStart, ASelFinish: TDateTime; AResource: TcxSchedulerStorageResourceItem); procedure UnselectEvents; // store/load procedure RestoreFromIniFile(const AStorageName: string; ARestoreResources: Boolean = True); procedure RestoreFromRegistry(const AStorageName: string; ARestoreResources: Boolean = True); procedure RestoreFromStream(AStream: TStream; ARestoreResources: Boolean = True); procedure StoreToIniFile(const AStorageName: string; AReCreate: Boolean = True; AStoreResources: Boolean = True); procedure StoreToRegistry(const AStorageName: string; AReCreate: Boolean = True; AStoreResources: Boolean = True); procedure StoreToStream(AStream: TStream; AStoreResources: Boolean = True); property ActiveHitTest: TcxSchedulerSubControlHitTest read GetActiveHitTest; property Color; property ContentPopupMenu: TcxSchedulerContentPopupMenu read FContentPopupMenu write SetContentPopupMenu; property ControlBox: TcxSchedulerControlBox read FControlBox write SetControlBox; property CurrentView: TcxSchedulerCustomView read FCurrentView write SetCurrentView; property DateNavigator: TcxSchedulerCustomDateNavigator read FDateNavigator; property DateTimeHelper: TcxSchedulerDateTimeHelperClass read GetDateTimeHelper; property EventDays: TcxSchedulerDateList read FEventDays; property EventOperations: TcxSchedulerEventOperations read FEventOperations write SetEventOperations; property EventPopupMenu: TcxSchedulerEventPopupMenu read FEventPopupMenu write SetEventPopupMenu; property OptionsCustomize: TcxSchedulerOptionsCustomize read FOptionsCustomize write SetOptionsCustomize; property OptionsView: TcxSchedulerOptionsView read FOptionsView write SetOptionsView; property SelectedDays: TcxSchedulerDateList read FSelectedDays; property SelectedEventCount: Integer read GetSelectedEventCount; property SelectedEvents[Index: Integer]: TcxSchedulerControlEvent read GetSelectedEvent; property SelFinish: TDateTime read GetSelFinish; property SelResource: TcxSchedulerStorageResourceItem read FSelResource; property SelStart: TDateTime read GetSelStart; property Storage: TcxCustomSchedulerStorage read FStorage write SetStorage; property StoringName: string read FStoringName write FStoringName; property Styles: TcxSchedulerStyles read FStyles write SetStyles; property VisibleEventCount: Integer read GetVisibleEventCount; property VisibleEvents[AIndex: Integer]: TcxSchedulerControlEvent read GetVisibleEvent; property TabStop default True; property Font; published property StylesEvents: TNotifyEvent read FStylesEvents write FStylesEvents; property ContentPopupMenuEvents: TNotifyEvent read FContentPopupMenuEvents write FContentPopupMenuEvents; property EventPopupMenuEvents: TNotifyEvent read FEventPopupMenuEvents write FEventPopupMenuEvents; end; { TcxSchedulerPopupMenu } TcxSchedulerPopupMenu = class(TPersistent) private FScheduler: TcxCustomScheduler; FPopupMenu: TComponent; FInternalMenu: TPopupMenu; FUseBuiltInPopupMenu: Boolean; function GetRoot: TMenuItem; procedure SetPopupMenu(const Value: TComponent); protected function AddValidSeparator(AOwner: TMenuItem): TMenuItem; procedure CreateInternalMenu; procedure CreateItems; virtual; function CreateSeparator(AOwner: TMenuItem): TMenuItem; function CreateSubItem(AOwner: TMenuItem; const ACaption: string; ACommand: Integer = -1; AImageIndex: Integer = -1; AEnabled: Boolean = True; AChecked: Boolean = False): TMenuItem; procedure DoExecute(ACommand: Integer); virtual; function DoOnClick(ACommand: Integer): Boolean; virtual; function DoOnPopup: Boolean; virtual; procedure ExecuteCommand(ACommand: Integer); function FindItemByCommand(AOwnerItem: TMenuItem; ACommand: Integer): TMenuItem; function IsValidCommand(ACommand: Integer): Boolean; virtual; procedure OnItemClickHandler(Sender: TObject); function Storage: TcxCustomSchedulerStorage; property InternalMenu: TPopupMenu read FInternalMenu; property Root: TMenuItem read GetRoot; public constructor Create(AScheduler: TcxCustomScheduler); virtual; destructor Destroy; override; procedure Assign(Source: TPersistent); override; function Popup(X, Y: Integer): Boolean; virtual; property Scheduler: TcxCustomScheduler read FScheduler; published property PopupMenu: TComponent read FPopupMenu write SetPopupMenu; property UseBuiltInPopupMenu: Boolean read FUseBuiltInPopupMenu write FUseBuiltInPopupMenu default True; end; { TcxSchedulerCustomContentPopupMenu } TcxSchedulerCustomContentPopupMenu = class(TcxSchedulerPopupMenu) private FNewID: Integer; FAllDayID: Integer; FReccurenceID: Integer; protected function CanCreateEvent: Boolean; procedure CreateNewEventItems(ANew, AllDay, AReccurence: Boolean; ANewID, AllDayID, AReccurenceID: Integer); procedure DoExecute(ACommand: Integer); override; public constructor Create(AScheduler: TcxCustomScheduler); override; end; { TcxSchedulerContentPopupMenu } TcxSchedulerContentPopupMenuItem = (cpmiNewEvent, cpmiNewAllDayEvent, cpmiNewReccuringEvent, cpmiToday, cpmiGoToDate, cpmiGoToThisDay, cpmiResourcesLayout); TcxSchedulerContentPopupMenuItems = set of TcxSchedulerContentPopupMenuItem; TcxSchedulerContentPopupMenuPopupEvent = procedure (Sender: TcxSchedulerContentPopupMenu; ABuiltInMenu: TPopupMenu; var AHandled: Boolean) of object; TcxSchedulerContentPopupMenuClickEvent = procedure (Sender: TcxSchedulerContentPopupMenu; AItem: TcxSchedulerContentPopupMenuItem; var AHandled: Boolean) of object; TcxSchedulerContentPopupMenu = class(TcxSchedulerCustomContentPopupMenu) private FItems: TcxSchedulerContentPopupMenuItems; FSavedDate: TDateTime; FOnPopup: TcxSchedulerContentPopupMenuPopupEvent; FOnClick: TcxSchedulerContentPopupMenuClickEvent; procedure CreateGoToThisDayItem; protected procedure CreateItems; override; procedure DoExecute(ACommand: Integer); override; function DoOnClick(ACommand: Integer): Boolean; override; function DoOnPopup: Boolean; override; function IsValidCommand(ACommand: Integer): Boolean; override; public constructor Create(AScheduler: TcxCustomScheduler); override; procedure Assign(Source: TPersistent); override; procedure Execute(AItem: TcxSchedulerContentPopupMenuItem); function GetMenuItem(AItem: TcxSchedulerContentPopupMenuItem): TMenuItem; published property Items: TcxSchedulerContentPopupMenuItems read FItems write FItems default [cpmiNewEvent, cpmiNewAllDayEvent, cpmiNewReccuringEvent, cpmiToday, cpmiGoToDate, cpmiGoToThisDay, cpmiResourcesLayout]; property PopupMenu; property UseBuiltInPopupMenu; property OnClick: TcxSchedulerContentPopupMenuClickEvent read FOnClick write FOnClick; property OnPopup: TcxSchedulerContentPopupMenuPopupEvent read FOnPopup write FOnPopup; end; { TcxSchedulerEventPopupMenu } TcxSchedulerEventPopupMenuItem = (epmiOpen, epmiEditSeries, epmiShowTimeAs, epmiLabel, epmiDelete); TcxSchedulerEventPopupMenuItems = set of TcxSchedulerEventPopupMenuItem; TcxSchedulerEventPopupMenuPopupEvent = procedure (Sender: TcxSchedulerEventPopupMenu; ABuiltInMenu: TPopupMenu; var AHandled: Boolean) of object; TcxSchedulerEventPopupMenuClickEvent = procedure (Sender: TcxSchedulerEventPopupMenu; AItem: TcxSchedulerEventPopupMenuItem; ASubItemIndex: Integer; var AHandled: Boolean) of object; TcxSchedulerEventPopupMenu = class(TcxSchedulerPopupMenu) private FEvent: TcxSchedulerControlEvent; FItems: TcxSchedulerEventPopupMenuItems; FOnPopup: TcxSchedulerEventPopupMenuPopupEvent; FOnClick: TcxSchedulerEventPopupMenuClickEvent; procedure CreateDeleteItem; procedure CreateLabelItems; procedure CreateTimeItems; function GetCommand(AItem: TcxSchedulerEventPopupMenuItem; ASubItemIndex: Integer): Integer; function CanEdit: Boolean; function GetEvent: TcxSchedulerControlEvent; procedure UnpackCommand(ACommand: Integer; out AItem: TcxSchedulerEventPopupMenuItem; out ASubItemIndex: Integer); protected procedure CreateItems; override; procedure DoExecute(ACommand: Integer); override; function DoOnClick(ACommand: Integer): Boolean; override; function DoOnPopup: Boolean; override; function IsValidCommand(ACommand: Integer): Boolean; override; procedure SetEventLabelColor(AColor: Integer); procedure SetEventState(AState: Integer); public constructor Create(AScheduler: TcxCustomScheduler); override; procedure Assign(Source: TPersistent); override; function GetMenuItem(AItem: TcxSchedulerEventPopupMenuItem; ASubItemIndex: Integer = -1): TMenuItem; property Event: TcxSchedulerControlEvent read FEvent; published property Items: TcxSchedulerEventPopupMenuItems read FItems write FItems default [epmiOpen, epmiEditSeries, epmiShowTimeAs, epmiLabel, epmiDelete]; property PopupMenu; property UseBuiltInPopupMenu; property OnClick: TcxSchedulerEventPopupMenuClickEvent read FOnClick write FOnClick; property OnPopup: TcxSchedulerEventPopupMenuPopupEvent read FOnPopup write FOnPopup; end; function IsHeaderEvent(AEvent: TcxSchedulerEvent): Boolean; implementation uses {$IFDEF DELPHI6} DateUtils, Variants, {$ENDIF} cxLibraryConsts, cxVariants, cxSchedulerDialogs, cxMemo, cxSchedulerStrs, cxSchedulerRecurrenceSelectionDialog; const EventContentColors: array[Boolean] of TColor = (clWindow, clWhite); EditStartChars = [#8, #13, ^V, ^X, #32..#255]; type TcxCustomEditAccess = class(TcxCustomEdit); function IsHeaderEvent(AEvent: TcxSchedulerEvent): Boolean; begin Result := AEvent.AllDayEvent or (AEvent.Duration >= 1); end; { TcxSchedulerSubControl } constructor TcxSchedulerSubControl.Create( AOwner: TcxCustomScheduler); begin FScheduler := AOwner; FVisible := True; CreateSubClasses; FCursor := crDefault; Scheduler.SubControlAdd(Self); end; destructor TcxSchedulerSubControl.Destroy; begin DestroySubClasses; Scheduler.SubControlRemove(Self); inherited Destroy; end; procedure TcxSchedulerSubControl.Invalidate; begin InvalidateRect(ClientRect); end; procedure TcxSchedulerSubControl.InvalidateRect( const ARect: TRect); begin Scheduler.InvalidateRect(cxRectOffset(ARect, Left, Top), False); Exclude(Scheduler.FControlFlags, cfImageValid); end; procedure TcxSchedulerSubControl.LayoutChanged; begin FCanvas := Scheduler.FCanvas; if not Visible then ViewInfo.Clear; if not Visible or (Controller = nil) then Exit; Exclude(Scheduler.FControlFlags, cfImageValid); Controller.Reset; DoLayoutChanged; HitTest.Recalculate; Invalidate; end; procedure TcxSchedulerSubControl.Refresh; begin LayoutChanged; end; procedure TcxSchedulerSubControl.SetBounds( ALeft, ATop, AWidth, AHeight: Integer); begin if (ALeft <> FLeft) or (ATop <> FTop) or (AWidth <> FWidth) or (AHeight <> FHeight) then begin FLeft := ALeft; FTop := ATop; FWidth := AWidth; FHeight := AHeight; BoundsChanged; end; end; procedure TcxSchedulerSubControl.GetProperties(AProperties: TStrings); begin end; procedure TcxSchedulerSubControl.GetPropertyValue(const AName: string; var AValue: Variant); begin end; procedure TcxSchedulerSubControl.SetPropertyValue(const AName: string; const AValue: Variant); begin end; function TcxSchedulerSubControl.AllowDesignHitTest( X, Y: Integer; AShift: TShiftState): Boolean; begin MousePositionChanged(X, Y); Result := False; end; procedure TcxSchedulerSubControl.BoundsChanged; begin Scheduler.AlignSubControls(Self); Changed; end; procedure TcxSchedulerSubControl.CalculateViewInfo; begin ViewInfo.Calculate; end; function TcxSchedulerSubControl.CanCapture( const APoint: TPoint): Boolean; begin Result := Visible and cxRectPtIn(Bounds, APoint); end; procedure TcxSchedulerSubControl.Changed; begin Scheduler.LayoutChanged; end; function TcxSchedulerSubControl.CreateController: TcxSchedulerSubControlController; begin Result := TcxSchedulerSubControlController.Create(Self); end; function TcxSchedulerSubControl.CreateHitTest: TcxSchedulerSubControlHitTest; begin Result := TcxSchedulerSubControlHitTest.Create(Self); end; function TcxSchedulerSubControl.CreatePainter: TcxSchedulerSubControlPainter; begin Result := TcxSchedulerSubControlPainter.Create(Self); end; function TcxSchedulerSubControl.CreateViewInfo: TcxSchedulerSubControlViewInfo; begin Result := TcxSchedulerSubControlViewInfo.Create(Self); end; procedure TcxSchedulerSubControl.CreateSubClasses; begin FViewInfo := CreateViewInfo; FHitTest := CreateHitTest; FController := CreateController; FPainter := CreatePainter; end; procedure TcxSchedulerSubControl.DestroySubClasses; begin FPainter.Free; FHitTest.Free; FController.Free; FViewInfo.Free; end; procedure TcxSchedulerSubControl.DoBeforeMouseDown(AButton: TMouseButton; AShift: TShiftState; X, Y: Integer); begin MousePositionChanged(X, Y); Controller.BeforeMouseDown(AButton, AShift, X, Y); end; procedure TcxSchedulerSubControl.DoCancelMode; begin Mouse.Capture := 0; end; procedure TcxSchedulerSubControl.DoLayoutChanged; begin CalculateViewInfo; end; procedure TcxSchedulerSubControl.DoMouseDown( AButton: TMouseButton; AShift: TShiftState; X, Y: Integer); begin MousePositionChanged(X, Y); Controller.MouseDown(AButton, AShift, X, Y); end; procedure TcxSchedulerSubControl.DoMouseMove( AShift: TShiftState; X, Y: Integer); begin MousePositionChanged(X, Y); Controller.MouseMove(AShift, X, Y); end; procedure TcxSchedulerSubControl.DoMouseUp( AButton: TMouseButton; AShift: TShiftState; X, Y: Integer); begin MousePositionChanged(X, Y); Controller.MouseUp(AButton, AShift, X, Y); end; procedure TcxSchedulerSubControl.DoPaint; var AClipRgn: TcxRegion; begin AClipRgn := Canvas.GetClipRegion; Canvas.IntersectClipRect(ClientRect); Painter.Paint; Canvas.SetClipRegion(AClipRgn, roSet); end; procedure TcxSchedulerSubControl.FormatChanged; begin end; function TcxSchedulerSubControl.GetClientRect: TRect; begin Result := cxRectBounds(0, 0, FWidth, FHeight); end; function TcxSchedulerSubControl.GetOwner: TPersistent; begin Result := FScheduler; end; function TcxSchedulerSubControl.GetHScrollBarBounds: TRect; begin Result := cxNullRect; end; function TcxSchedulerSubControl.GetSizeGripBounds: TRect; begin Result := cxNullRect; end; function TcxSchedulerSubControl.GetStartOfWeek: TDay; begin Result := Scheduler.OptionsView.ActualStartOfWeek; end; function TcxSchedulerSubControl.GetVScrollBarBounds: TRect; begin Result := cxNullRect; end; procedure TcxSchedulerSubControl.InitScrollBarsParameters; begin end; procedure TcxSchedulerSubControl.MousePositionChanged( var X, Y: Integer); begin Dec(X, FLeft); Dec(Y, FTop); HitTest.HitPoint := cxPoint(X, Y); end; procedure TcxSchedulerSubControl.Notification(AComponent: TComponent; Operation: TOperation); begin end; procedure TcxSchedulerSubControl.Paint; var ASavePos: TPoint; begin if not Visible or cxRectIsEmpty(Bounds) then Exit; ASavePos := Canvas.WindowOrg; Canvas.WindowOrg := cxPoint(-Left, -Top); try DoPaint; finally Canvas.WindowOrg := ASavePos; end; end; procedure TcxSchedulerSubControl.PeriodChanged; begin Scheduler.PeriodChanged; end; procedure TcxSchedulerSubControl.SetScrollBarInfo( AScrollBarKind: TScrollBarKind; AMin, AMax, AStep, APage, APos: Integer; AAllowShow, AAllowHide: Boolean); begin Scheduler.SetScrollBarInfo(AScrollBarKind, AMin, AMax, AStep, APage, APos, AAllowShow and Visible, AAllowHide); end; procedure TcxSchedulerSubControl.VisibleChanged; begin Scheduler.AlignSubControls(Self); Changed; end; function TcxSchedulerSubControl.GetBottom: Integer; begin Result := FTop + FHeight; end; {$IFNDEF DEBUGPAINT} function TcxSchedulerSubControl.GetBitmap: TBitmap; begin Result := Scheduler.FBitmap; end; {$ENDIF} function TcxSchedulerSubControl.GetBounds: TRect; begin Result := cxRectBounds(FLeft, FTop, FWidth, FHeight); end; function TcxSchedulerSubControl.GetDateTimeHelperClass: TcxSchedulerDateTimeHelperClass; begin Result := Scheduler.DateTimeHelper; end; function TcxSchedulerSubControl.GetLookAndFeelPainter: TcxCustomLookAndFeelPainterClass; begin Result := Scheduler.LookAndFeelPainter; end; function TcxSchedulerSubControl.GetPainterHelperClass: TcxSchedulerPainterHelperClass; begin Result := Scheduler.PainterHelper; end; function TcxSchedulerSubControl.GetRight: Integer; begin Result := FLeft + FWidth; end; function TcxSchedulerSubControl.GetStyles: TcxSchedulerStyles; begin Result := Scheduler.Styles; end; procedure TcxSchedulerSubControl.InternalSetBounds(const AValue: TRect); begin SetBounds(AValue.Left, AValue.Top, AValue.Right - AValue.Left, AValue.Bottom - AValue.Top); end; procedure TcxSchedulerSubControl.SetBottom(const Value: Integer); begin InternalSetBounds(cxRectSetBottom(Bounds, Value)); end; procedure TcxSchedulerSubControl.SetHeight(AValue: Integer); begin SetBounds(FLeft, FTop, FWidth, AValue); end; procedure TcxSchedulerSubControl.SetLeft(AValue: Integer); begin SetBounds(AValue, FTop, FWidth, FHeight); end; procedure TcxSchedulerSubControl.SetRight(Value: Integer); begin InternalSetBounds(cxRectSetRight(Bounds, Value)); end; procedure TcxSchedulerSubControl.SetTop(AValue: Integer); begin SetBounds(FLeft, AValue, FWidth, FHeight); end; procedure TcxSchedulerSubControl.SetVisible( AValue: Boolean); begin if AValue <> FVisible then begin FVisible := AValue; VisibleChanged; end; end; procedure TcxSchedulerSubControl.SetWidth(AValue: Integer); begin SetBounds(FLeft, FTop, AValue, FHeight); end; { TcxSchedulerSubControlController } constructor TcxSchedulerSubControlController.Create( AOwner: TcxSchedulerSubControl); begin FOwner := AOwner; end; procedure TcxSchedulerSubControlController.BeginDragAndDrop; begin end; function TcxSchedulerSubControlController.CanDrag( X, Y: Integer): Boolean; begin Result := False; end; procedure TcxSchedulerSubControlController.DragAndDrop( const P: TPoint; var Accepted: Boolean); begin end; procedure TcxSchedulerSubControlController.DragDrop( Source: TObject; X, Y: Integer); begin end; procedure TcxSchedulerSubControlController.DragOver( Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin Accept := False; end; procedure TcxSchedulerSubControlController.EndDrag( Target: TObject; X, Y: Integer); begin end; procedure TcxSchedulerSubControlController.EndDragAndDrop( Accepted: Boolean); begin end; function TcxSchedulerSubControlController.GetDragAndDropObjectClass: TcxDragAndDropObjectClass; begin Result := nil; end; procedure TcxSchedulerSubControlController.StartDrag( var DragObject: TDragObject); begin end; function TcxSchedulerSubControlController.StartDragAndDrop( const P: TPoint): Boolean; begin Result := False; end; procedure TcxSchedulerSubControlController.BeforeMouseDown( Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin end; procedure TcxSchedulerSubControlController.DoCancelMode; begin end; function TcxSchedulerSubControlController.GetCursor( X, Y: Integer): TCursor; begin Result := Owner.Cursor; end; procedure TcxSchedulerSubControlController.KeyDown( var Key: Word; Shift: TShiftState); begin end; procedure TcxSchedulerSubControlController.KeyPress( var Key: Char); begin end; procedure TcxSchedulerSubControlController.KeyUp( var Key: Word; Shift: TShiftState); begin end; procedure TcxSchedulerSubControlController.MouseEnter; begin end; procedure TcxSchedulerSubControlController.MouseLeave; begin end; procedure TcxSchedulerSubControlController.MouseDown( Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin end; procedure TcxSchedulerSubControlController.MouseMove( Shift: TShiftState; X, Y: Integer); begin end; procedure TcxSchedulerSubControlController.MouseUp( Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin end; procedure TcxSchedulerSubControlController.Reset; begin end; function TcxSchedulerSubControlController.GetHitTest: TcxSchedulerSubControlHitTest; begin Result := Owner.HitTest; end; function TcxSchedulerSubControlController.GetStartOfWeek: TDay; begin Result := Owner.StartOfWeek; end; { TcxSchedulerSubControlHitTest } constructor TcxSchedulerSubControlHitTest.Create( AOwner: TcxSchedulerSubControl); begin FOwner := AOwner; end; destructor TcxSchedulerSubControlHitTest.Destroy; begin inherited Destroy; end; procedure TcxSchedulerSubControlHitTest.Recalculate; begin DoCalculate; end; procedure TcxSchedulerSubControlHitTest.Clear; begin Flags := 0; FTime := NullDate; end; procedure TcxSchedulerSubControlHitTest.DoCalculate; begin Clear; SetBitState(htcControl, cxRectPtIn(Owner.Bounds, cxPointOffset(HitPoint, Owner.Left, Owner.Top))); end; function TcxSchedulerSubControlHitTest.GetBitState( AIndex: Integer): Boolean; begin Result := (Flags and (1 shl AIndex)) <> 0 end; function TcxSchedulerSubControlHitTest.GetMaskState( AMask: Integer): Boolean; begin Result := Flags and AMask = AMask; end; function TcxSchedulerSubControlHitTest.GetMaskStateEx( AMask: Integer): Boolean; begin Result := Flags and AMask <> 0; end; procedure TcxSchedulerSubControlHitTest.SetBitState( AIndex: Integer; AValue: Boolean); begin if AValue then Flags := Flags or (1 shl AIndex) else Flags := Flags and not (1 shl AIndex); end; procedure TcxSchedulerSubControlHitTest.SetMaskState( AMask: Integer; AValue: Boolean); begin if AValue then Flags := Flags or AMask else Flags := Flags and not AMask; end; function TcxSchedulerSubControlHitTest.GetPosValue( AIndex: Integer): Integer; begin Result := cxPointGetItem(FHitPoint, AIndex); end; function TcxSchedulerSubControlHitTest.GetScheduler: TcxCustomScheduler; begin Result := FOwner.FScheduler; end; procedure TcxSchedulerSubControlHitTest.SetHitPoint( const APoint: TPoint); begin FHitPoint := APoint; Recalculate; end; procedure TcxSchedulerSubControlHitTest.SetPosValue( AIndex, AValue: Integer); begin FHitPoint := cxPointReplaceItem(FHitPoint, AIndex, AValue); Recalculate; end; { TcxSchedulerSubControlPainter } constructor TcxSchedulerSubControlPainter.Create( AOwner: TcxSchedulerSubControl); begin FOwner := AOwner; end; procedure TcxSchedulerSubControlPainter.Paint; begin end; {$IFNDEF DEBUGPAINT} function TcxSchedulerSubControlPainter.GetBitmap: TBitmap; begin Result := FOwner.Bitmap; end; {$ENDIF} function TcxSchedulerSubControlPainter.GetCanvas: TcxCanvas; begin Result := FOwner.FCanvas; end; function TcxSchedulerSubControlPainter.GetViewInfo: TcxSchedulerSubControlViewInfo; begin Result := Owner.ViewInfo; end; { TcxSchedulerSubControlViewInfo } constructor TcxSchedulerSubControlViewInfo.Create( AOwner: TcxSchedulerSubControl); begin FOwner := AOwner; end; procedure TcxSchedulerSubControlViewInfo.Calculate; begin if not IsSchedulerCreated then Exit; FBounds := GetBounds; Clear; DoCalculate; AfterCalculate; end; procedure TcxSchedulerSubControlViewInfo.AfterCalculate; begin end; procedure TcxSchedulerSubControlViewInfo.Clear; begin end; procedure TcxSchedulerSubControlViewInfo.DoCalculate; begin end; function TcxSchedulerSubControlViewInfo.GetBounds: TRect; begin Result := Owner.ClientRect; end; function TcxSchedulerSubControlViewInfo.GetDateTimeHelperClass: TcxSchedulerDateTimeHelperClass; begin Result := Owner.DateTimeHelper; end; function TcxSchedulerSubControlViewInfo.GetDefaultFont: TFont; begin Result := Owner.Scheduler.Font; end; function TcxSchedulerSubControlViewInfo.GetIsSchedulerCreated: Boolean; begin Result := Owner.Scheduler.FSubControlsCreated; end; function TcxSchedulerSubControlViewInfo.GetLookAndFeelPainter: TcxCustomLookAndFeelPainterClass; begin Result := Owner.Scheduler.LookAndFeelPainter; end; function TcxSchedulerSubControlViewInfo.GetPainterHelperClass: TcxSchedulerPainterHelperClass; begin Result := Owner.PainterHelper; end; function TcxSchedulerSubControlViewInfo.GetStyles: TcxSchedulerStyles; begin Result := Owner.Styles; end; type TContainer = class(TWinControl) protected procedure CreateParams(var Params: TCreateParams); override; public constructor Create(AOwner: TComponent); override; end; { TcxSchedulerControlBox } constructor TcxSchedulerControlBox.Create(AOwner: TcxCustomScheduler); begin inherited Create(AOwner); FContainer := CreateWndContainerControl; end; procedure TcxSchedulerControlBox.Assign(Source: TPersistent); begin if Source is TcxSchedulerControlBox then with TcxSchedulerControlBox(Source) do begin Self.Control := Control; Self.Visible := Visible; end else inherited Assign(Source); end; function TcxSchedulerControlBox.HasAsParent( AValue: TControl): Boolean; var AParent: TWinControl; begin Result := False; AParent := Scheduler; while not Result and (AParent <> nil) do begin Result := AValue = AParent; AParent := AParent.Parent; end; end; procedure TcxSchedulerControlBox.VisibleChanged; begin FContainer.Visible := Visible; inherited VisibleChanged; end; procedure TcxSchedulerControlBox.DoLayoutChanged; begin FViewParams := Styles.GetBackgroundParams; inherited DoLayoutChanged; end; procedure TcxSchedulerControlBox.GetProperties(AProperties: TStrings); begin if Scheduler.DateNavigator.Visible then Exit; AProperties.Add('DNWidth'); end; procedure TcxSchedulerControlBox.GetPropertyValue(const AName: string; var AValue: Variant); begin if Scheduler.DateNavigator.Visible then Exit; if AName = 'DNWidth' then AValue := Width end; procedure TcxSchedulerControlBox.SetPropertyValue(const AName: string; const AValue: Variant); begin if Scheduler.DateNavigator.Visible then Exit; if AName = 'DNWidth' then begin Scheduler.DateNavigator.Width := AValue; Scheduler.DateNavigator.DoLayoutChanged; Width := AValue; end; end; procedure TcxSchedulerControlBox.BoundsChanged; begin FContainer.BoundsRect := Bounds; inherited BoundsChanged; FContainer.Update; end; function TcxSchedulerControlBox.CreateWndContainerControl: TWinControl; begin Result := TContainer.Create(Scheduler); Result.Parent := Scheduler; end; procedure TcxSchedulerControlBox.DoPaint; begin Canvas.FillRect(ClientRect, ViewParams); end; procedure TcxSchedulerControlBox.RestorePosition; begin if (FControl = nil) or (csDestroying in Control.ComponentState) then Exit; Control.RemoveFreeNotification(Scheduler); Control.Align := FControlAlign; Control.Parent := FControlParent; Control.BoundsRect := FControlRect; end; procedure TcxSchedulerControlBox.SetControl( AValue: TControl); begin if HasAsParent(AValue) then Exit; if FControl <> AValue then begin RestorePosition; FControl := AValue; StorePosition; FContainer.BoundsRect := Bounds; FContainer.Visible := Visible and (Control <> nil); Changed; end else FContainer.Visible := False; end; procedure TcxSchedulerControlBox.StorePosition; begin if Control = nil then Exit; FControlAlign := Control.Align; FControlParent := Control.Parent; FControlRect := Control.BoundsRect; Control.FreeNotification(Scheduler); Control.Parent := FContainer; Control.Align := alClient; end; { TcxDragHelper } constructor TcxDragHelper.Create(AScheduler: TcxCustomScheduler); begin FScheduler := AScheduler; BeginDrag; end; procedure TcxDragHelper.BeginDrag; begin //FLockShowEditorOnMouseClick := DragKind = edkMoveEvent; GetOriginState; end; procedure TcxDragHelper.DragOver(const P: TPoint; State: TDragState; var Accepted: Boolean); begin end; procedure TcxDragHelper.EndDrag(Accepted: Boolean); begin end; function TcxDragHelper.GetOriginHitTestMask: Int64; const Mask = 1 shl htcControl; begin Result := Mask; end; procedure TcxDragHelper.GetOriginState; begin with Controller do begin FStartHitFlags := StartDragFlags and GetOriginHitTestMask; FStartHitTime := StartDragHitTime; FStartResource := StartDragResource; end; FPrevHitTime := FStartHitTime; FPrevHitFlags := FStartHitFlags; FPrevHitResource := FStartResource; end; function TcxDragHelper.HasChangedState: Boolean; begin with HitTest do Result := (FPrevHitFlags <> (Flags and GetOriginHitTestMask)) or (HitAtTime and (FPrevHitTime <> Time)) or (HitAtResource and (FPrevHitResource <> Resource)); end; function TcxDragHelper.IsAtOrigin: Boolean; begin with HitTest do begin Result := (FStartHitFlags = (Flags and GetOriginHitTestMask)) and (Controller.StartDragHitTime = Time); if Result and IsShowResources then Result := HitAtResource and (FStartResource = Resource); end; end; function TcxDragHelper.IsShowResources: Boolean; begin Result := Scheduler.CurrentView.IsShowResources; end; function TcxDragHelper.IsValidTime: Boolean; begin Result := HitTest.HitAtTime; end; procedure TcxDragHelper.RefreshCurrentView; begin Scheduler.CurrentView.Refresh; end; procedure TcxDragHelper.SetSelection; begin Controller.SyncEventSelection(Controller.DragEvent); end; procedure TcxDragHelper.UpdateState; begin with HitTest do begin FPrevHitFlags := Flags and GetOriginHitTestMask; FPrevHitTime := Time; FPrevHitResource := Resource; end; end; function TcxDragHelper.GetController: TcxSchedulerViewController; begin Result := Scheduler.CurrentView.Controller; end; function TcxDragHelper.GetEvents: TcxSchedulerCachedEventList; begin Result := Scheduler.EventList; end; function TcxDragHelper.GetHitTest: TcxSchedulerViewHitTest; begin Result := Scheduler.CurrentView.HitTest; end; { TcxSchedulerDragObject} constructor TcxSchedulerDragObject.Create(AControl: TControl); begin inherited Create(AControl); FUseInternalCursors := (Control is TcxCustomScheduler) and (TcxCustomScheduler(Control).DragCursor = crDrag); end; function TcxSchedulerDragObject.GetDragCursor(Accepted: Boolean; X, Y: Integer): TCursor; begin if Accepted and FUseInternalCursors then begin if TcxCustomScheduler(Control).IsCopyDragDrop then Result := crSchedulerCopyEvent else Result := crSchedulerMoveEvent; end else Result := inherited GetDragCursor(Accepted, X, Y); end; { TcxDragEventHelper } procedure TcxDragEventHelper.ApplyChanges; begin UpdateEventProperties; if IsValidNavigatorDate then ProcessDateNavigator; SetSelection; Events.PostClones(IsDragCopy) end; procedure TcxDragEventHelper.BeginDrag; begin inherited BeginDrag; FSaveCursor := Scheduler.DragCursor; PrepareClones; Events.AlwaysShowSelectedEvent := False; CheckVisibility(True); end; procedure TcxDragEventHelper.CheckVisibility(Accepted: Boolean); begin Inc(Scheduler.FLockRefresh); try Events.AlwaysShowSelectedEvent := not Accepted or not HitTest.HitAtTime; ViewInfo.SetEventsVisibility(GetSourcesVisible(Accepted), GetClonesVisible(Accepted), True); finally Dec(Scheduler.FLockRefresh); end; end; procedure TcxDragEventHelper.CheckAccepted(var Accepted: Boolean); function CanMoveBetweenResources: Boolean; var AResource: TcxSchedulerStorageResourceItem; begin AResource := HitTest.Resource; Result := (FStartResource = AResource) or (Scheduler.EventOperations.MovingBetweenResources and ((AResource = nil) or not AResource.ReadOnly)); end; var P: TPoint; begin if not Accepted then Exit; P := Scheduler.ScreenToClient(GetMouseCursorPos); if Scheduler.ControlBox.Visible and cxRectPtIn(Scheduler.ControlBox.Bounds, P) then Exit; Accepted := False; if cxRectPtIn(Scheduler.CurrentView.Bounds, P) then begin Accepted := HitTest.HitAtTime; if Accepted and IsShowResources and HitTest.HitAtResource and not CanMoveBetweenResources then Accepted := False; end; UpdateDateNavigator(Accepted); end; procedure TcxDragEventHelper.CorrectAllDayEventProperty; var I: Integer; begin if IsValidNavigatorDate then RestoreAllDayProperties else for I := 0 to Clones.Count - 1 do with Clones[I] do begin AllDayEvent := AllDayEvent and (not IsHeaderEvent(Source) or Source.AllDayEvent); if not AllDayEvent and (Duration > 1) then MoveTo(DateOf(Start) + TimeOf(Source.Start)); end; end; procedure TcxDragEventHelper.DragOver(const P: TPoint; State: TDragState; var Accepted: Boolean); begin CheckAccepted(Accepted); if Accepted and (HasChangedState or (State in [dsDragLeave, dsDragEnter])) then begin Accepted := IsValidTime and ({$IFDEF DELPHI6}DragObject.Dropped{$ELSE}DragObject.Cancelling{$ENDIF} or (State <> dsDragLeave)); if Accepted then UpdateClones; end; CheckVisibility(Accepted); if State <> dsDragLeave then Controller.CheckScrolling(P) else Controller.CancelScroll; end; procedure TcxDragEventHelper.EndDrag(Accepted: Boolean); begin Controller.CancelScroll; Scheduler.DragCursor := FSaveCursor; with Scheduler do begin Accepted := Accepted and IsValidTime and not (IsAtOrigin and not IsDragCopy); if Accepted and (IsValidNavigatorDate or HitTest.HitAtControl) then begin UpdateClones; ApplyChanges; end else FullRefresh; DateNavigator.Controller.DoCancelMode; end; RefreshCurrentView; end; function TcxDragEventHelper.GetClonesVisible(Accepted: Boolean): Boolean; begin if FInNavigator and Accepted then Result := False else Result := Accepted and not (IsAtOrigin and not IsDragCopy); end; function TcxDragEventHelper.GetIsDragCopy: Boolean; begin Result := Scheduler.IsCopyDragDrop; end; procedure TcxDragEventHelper.GetOriginState; begin inherited GetOriginState; FInNavigator := False; FPrevIsDragCopy := IsDragCopy; end; function TcxDragEventHelper.GetSourcesVisible(Accepted: Boolean): Boolean; begin Result := not Accepted or (FInNavigator or IsAtOrigin or IsDragCopy); end; function TcxDragEventHelper.HasChangedState: Boolean; begin Result := inherited HasChangedState or (FPrevIsDragCopy <> IsDragCopy); end; function TcxDragEventHelper.IsValidNavigatorDate: Boolean; begin Result := FInNavigator and DateNavigator.HitTest.HitAtTime; end; function TcxDragEventHelper.IsValidTime: Boolean; begin Result := HitTest.HitAtTime or IsValidNavigatorDate; end; procedure TcxDragEventHelper.PrepareClones; var I: Integer; AEvent: TcxSchedulerControlEvent; AResource, ADragEventResource: TcxSchedulerStorageResourceItem; begin ADragEventResource := Controller.DragEvent.GetResourceItem; for I := Events.Selection.Count - 1 downto 0 do begin AEvent := Events.Selection.Items[I]; AResource := AEvent.GetResourceItem; if IsShowResources and (AResource <> nil) and (AResource <> ADragEventResource) then Events.Selection.Add(AEvent, [ssCtrl]); end; Events.CreateClones; end; procedure TcxDragEventHelper.ProcessDateNavigator; var I: Integer; AEvent: TcxSchedulerControlEvent; ADate: TDateTime; begin ADate := DateNavigator.HitTest.Time; for I := 0 to Clones.Count - 1 do begin AEvent := Clones[I]; AEvent.MoveTo(TimeOf(AEvent.Source.Start) + ADate); end; end; procedure TcxDragEventHelper.RestoreAllDayProperties; var I: Integer; begin for I := 0 to Clones.Count - 1 do with Clones[I] do AllDayEvent := Source.AllDayEvent; end; procedure TcxDragEventHelper.SetSelection; var I: Integer; AEvent: TcxSchedulerControlEvent; begin for I := 0 to Clones.Count - 1 do begin AEvent := Clones[I]; if AEvent.Source = Controller.DragEvent then Controller.SyncEventSelection(AEvent); end; end; procedure TcxDragEventHelper.UpdateClones; var I: Integer; AResource: TcxSchedulerStorageResourceItem; begin with HitTest do if HitAtResource then AResource := Resource else AResource := FStartResource; for I := 0 to Clones.Count - 1 do if not VarIsNull(Clones[I].ResourceID) and (AResource <> nil) then Clones[I].ResourceID := AResource.ResourceID; if HitTest.HitAtTime and not FInNavigator then UpdateClonesTime; end; procedure TcxDragEventHelper.UpdateClonesTime; begin end; procedure TcxDragEventHelper.UpdateDateNavigator(var Accepted: Boolean); begin with DateNavigator do begin if not Visible then Exit; HitTest.HitPoint := cxPointOffset(Scheduler.ScreenToClient(GetMouseCursorPos), -Left, -Top); FInNavigator := HitTest.HitAtControl; if FInNavigator then Accepted := HitTest.HitAtTime; UpdateDragging; end; end; procedure TcxDragEventHelper.UpdateEventProperties; begin CorrectAllDayEventProperty; end; procedure TcxDragEventHelper.UpdateState; begin inherited UpdateState; FPrevIsDragCopy := IsDragCopy; end; function TcxDragEventHelper.GetClones: TcxSchedulerFilteredEventList; begin Result := Scheduler.EventList.Clones; end; function TcxDragEventHelper.GetDateNavigator: TcxSchedulerCustomDateNavigator; begin Result := Scheduler.DateNavigator; end; function TcxDragEventHelper.GetViewInfo: TcxSchedulerCustomViewViewInfo; begin Result := TcxSchedulerCustomViewViewInfo(Scheduler.CurrentView.ViewInfo); end; { TcxSchedulerCustomView } constructor TcxSchedulerCustomView.Create(AOwner: TcxCustomScheduler); begin inherited Create(AOwner); FVisible := False; FCanShow := True; end; procedure TcxSchedulerCustomView.Assign(Source: TPersistent); begin if Source is TcxSchedulerCustomView then with TcxSchedulerCustomView(Source) do begin Self.CanShow := CanShow; Self.Active := Active; end; inherited Assign(Source); end; function TcxSchedulerCustomView.CreateController: TcxSchedulerSubControlController; begin Result := TcxSchedulerViewController.Create(Self); end; function TcxSchedulerCustomView.CreateHitTest: TcxSchedulerSubControlHitTest; begin Result := TcxSchedulerViewHitTest.Create(Self); end; procedure TcxSchedulerCustomView.DateChanged; begin Refresh; end; procedure TcxSchedulerCustomView.DoLayoutChanged; begin TcxSchedulerCustomViewViewInfo(ViewInfo).FSelectedDays := Scheduler.SelectedDays; TcxSchedulerCustomViewViewInfo(ViewInfo).FEvents := Scheduler.EventList; inherited DoLayoutChanged; Scheduler.UpdateScrollBars; end; function TcxSchedulerCustomView.DoShowPopupMenu(X, Y: Integer): Boolean; begin Result := False; end; function TcxSchedulerCustomView.EventContentSelected( AEvent: TcxSchedulerControlEvent): Boolean; begin Result := True; end; function TcxSchedulerCustomView.GetClientRect: TRect; begin Result := inherited GetClientRect; if Scheduler.HScrollBarVisible then Dec(Result.Bottom, Scheduler.HScrollBar.Height); if Scheduler.VScrollBarVisible then Dec(Result.Right, Scheduler.VScrollBar.Width); end; function TcxSchedulerCustomView.GetDateOffset: Integer; begin Result := 1 - Ord(OptionsView.ActualStartOfWeek); end; function TcxSchedulerCustomView.GetGroupingKind: TcxSchedulerGroupingKind; begin Result := gkNone; end; function TcxSchedulerCustomView.GetHScrollBarBounds: TRect; begin Result := ClientRect; Result.Top := Result.Bottom; Result.Bottom := Result.Top + Scheduler.HScrollBar.Height; OffsetRect(Result, Bounds.Left, Bounds.Top); end; function TcxSchedulerCustomView.GetEditRectForEvent( AEvent: TcxSchedulerControlEvent; const ADate: TDateTime; AResource: TcxSchedulerStorageResourceItem): TRect; begin Result := cxNullRect; end; function TcxSchedulerCustomView.GetEditStyle( AEvent: TcxSchedulerControlEvent): TcxCustomEditStyle; begin Result := Scheduler.EditStyle; end; function TcxSchedulerCustomView.GetEditProperties( AEvent: TcxSchedulerControlEvent): TcxCustomEditProperties; begin Scheduler.DoGetEventEditProperties(AEvent, Result); end; function TcxSchedulerCustomView.GetEventVisibility( AEvent: TcxSchedulerControlEvent): Boolean; begin Result := False; end; function TcxSchedulerCustomView.GetFirstVisibleDate: TDateTime; begin if SelectedDays.Count = 0 then Result := Date else Result := Integer(SelectedDays.First) end; function TcxSchedulerCustomView.GetLastVisibleDate: TDateTime; begin if SelectedDays.Count = 0 then Result := Date else Result := Integer(SelectedDays.Last) end; function TcxSchedulerCustomView.GetSizeGripBounds: TRect; begin with Result do begin Left := Scheduler.VScrollBar.Left; Right := Left + Scheduler.VScrollBar.Width; Top := Scheduler.HScrollBar.Top; Bottom := Top + Scheduler.HScrollBar.Height; end; OffsetRect(Result, Bounds.Left, Bounds.Top); end; function TcxSchedulerCustomView.GetTimeIncrement: TDateTime; begin Result := 1; end; function TcxSchedulerCustomView.GetVScrollBarBounds: TRect; begin Result := ClientRect; Result.Left := Result.Right; Result.Right := Result.Left + Scheduler.VScrollBar.Width; OffsetRect(Result, Bounds.Left, Bounds.Top); end; function TcxSchedulerCustomView.GetVisibleDaysRange: Integer; begin Result := 31; end; procedure TcxSchedulerCustomView.InitEventBySelectedPeriod( AEvent: TcxSchedulerEvent; AllDay: Boolean; ARecurrence: Boolean; AInplaceEditing: Boolean); var AIsAllDaySelection: Boolean; begin AIsAllDaySelection := IsAllDaySelection; AEvent.Start := Scheduler.SelStart; AEvent.AllDayEvent := AllDay or AIsAllDaySelection; if AllDay and not AIsAllDaySelection then AEvent.Finish := DateOf(Scheduler.SelFinish) + 1 else AEvent.Finish := Scheduler.SelFinish; end; function TcxSchedulerCustomView.IsAllDaySelection: Boolean; var AStart, AFinish, H, M, S, MS: Word; begin if DateOf(Scheduler.SelFinish - Scheduler.SelStart) >= 1 then begin DecodeTime(Scheduler.SelStart, H, M, S, MS); AStart := H * 60 + M; DecodeTime(Scheduler.SelFinish, H, M, S, MS); AFinish := H * 60 + M; Result := (AStart = 0) and (AFinish = 0); end else Result := False; end; function TcxSchedulerCustomView.IsDayView: Boolean; begin Result := False; end; function TcxSchedulerCustomView.IsShowResources: Boolean; begin Result := Scheduler.HasResources; end; function TcxSchedulerCustomView.IsWorkTime( AResourceItem: TcxSchedulerStorageResourceItem; const ADateTime: TDateTime): Boolean; begin Result := Scheduler.DoIsWorkTime(AResourceItem, ADateTime); end; procedure TcxSchedulerCustomView.MakeEventVisible( AEvent: TcxSchedulerControlEvent; const ADate: TDateTime; AResource: TcxSchedulerStorageResourceItem); begin end; procedure TcxSchedulerCustomView.PeriodChanged; begin Scheduler.ValidateSelection(SelectedDays); end; procedure TcxSchedulerCustomView.Scroll(AScrollBarKind: TScrollBarKind; AScrollCode: TScrollCode; var AScrollPos: Integer); begin if AScrollBarKind = sbHorizontal then Scheduler.HScrollBar.Position := AScrollPos else Scheduler.VScrollBar.Position := AScrollPos; end; procedure TcxSchedulerCustomView.ScrollSelectedDays(AScrollDelta: Integer); begin Scheduler.DateNavigator.ScrollSelection(AScrollDelta); end; procedure TcxSchedulerCustomView.ScrollSelectedDays(AForward: Boolean; ANeedDate: TDateTime; AIsByPage: Boolean); begin Scheduler.DateNavigator.ScrollSelection(AForward, ANeedDate, AIsByPage); end; procedure TcxSchedulerCustomView.ScrollVisibleDays( AScrollUp: Boolean); begin end; procedure TcxSchedulerCustomView.TimeChanged; begin end; procedure TcxSchedulerCustomView.VisibleChanged; begin if Visible and not CanShow then Visible := False else Scheduler.ViewVisibleChanged(Self) end; procedure TcxSchedulerCustomView.HideHintOnScroll; begin Scheduler.HintController.HideHint; end; procedure TcxSchedulerCustomView.ShowHintOnScroll(const ADate: TDateTime); var R: TRect; AHintText: string; begin AHintText := DateTimeToStr(ADate); R := Scheduler.HintController.CalcHintRect(cxscMinHintWindth, AHintText, cxAlignRight); with Scheduler.ClientToScreen(Point(Scheduler.VScrollBar.Left, 0)) do begin R := cxRectSetRight(R, X - 5); R := cxRectSetTop(R, GetMouseCursorPos.Y - cxGetCursorSize.cy div 2 - 1); end; Scheduler.HintController.Activate(R, AHintText, True); end; function TcxSchedulerCustomView.GetActive: Boolean; begin Result := Visible; end; function TcxSchedulerCustomView.GetCanShow: Boolean; begin Result := FCanShow; Scheduler.DoCanShowView(Self, Result); end; function TcxSchedulerCustomView.GetController: TcxSchedulerViewController; begin Result := TcxSchedulerViewController(inherited Controller); end; function TcxSchedulerCustomView.GetDragCloneEventList: TcxSchedulerFilteredEventList; begin if Assigned(Controller.DragEventHelper) then Result := Scheduler.EventList.Clones else Result := nil; end; function TcxSchedulerCustomView.GetEventList: TcxSchedulerCachedEventList; begin Result := Scheduler.EventList; end; function TcxSchedulerCustomView.GetHitTest: TcxSchedulerViewHitTest; begin Result := TcxSchedulerViewHitTest(inherited HitTest); end; function TcxSchedulerCustomView.GetSelectedDays: TcxSchedulerDateList; begin Result := Scheduler.SelectedDays end; function TcxSchedulerCustomView.GetOptionsView: TcxSchedulerOptionsView; begin Result := Scheduler.OptionsView; end; function TcxSchedulerCustomView.GetResources: TcxSchedulerStorageResourceItems; begin if Scheduler.StorageValid then Result := Scheduler.Storage.Resources.ResourceItems else Result := nil; end; function TcxSchedulerCustomView.GetWorkDays: TDays; begin Result := OptionsView.WorkDays; end; function TcxSchedulerCustomView.GetWorkFinish: TDateTime; begin Result := OptionsView.WorkFinish; end; function TcxSchedulerCustomView.GetWorkStart: TDateTime; begin Result := OptionsView.WorkStart; end; procedure TcxSchedulerCustomView.SetActive(AValue: Boolean); begin Visible := FCanShow and AValue; end; procedure TcxSchedulerCustomView.SetCanShow(AValue: Boolean); begin if FCanShow <> AValue then begin FCanShow := AValue; if not AValue then Visible := False else begin if not Scheduler.CurrentView.Visible then Visible := True; Changed; end; end; end; { TcxSchedulerCustomViewViewInfo } function TcxSchedulerCustomViewViewInfo.DoGetEventDisplayText( AEvent: TcxSchedulerControlEvent): string; begin Owner.Scheduler.DoGetEventDisplayText(AEvent, Result); end; function TcxSchedulerCustomViewViewInfo.GetSchedulerEventsList: TcxSchedulerCachedEventList; begin Result := Owner.Scheduler.EventList; end; procedure TcxSchedulerCustomViewViewInfo.SetEventsVisibility( AShowSources, AShowClones: Boolean; AForceRepaint: Boolean = False); begin end; { TcxSchedulerStyles } constructor TcxSchedulerStyles.Create(AOwner: TPersistent); begin if AOwner is TcxCustomScheduler then FScheduler := TcxCustomScheduler(AOwner); inherited Create(AOwner); end; procedure TcxSchedulerStyles.Assign(Source: TPersistent); var I: Integer; begin if Source is TcxSchedulerStyles then begin for I := 0 to cxcsMaxValue do SetValue(I, TcxSchedulerStyles(Source).GetValue(I)) end; inherited Assign(Source); end; function TcxSchedulerStyles.GetBackgroundParams: TcxViewParams; begin GetDefaultViewParams(cxcsBackground, nil, Result); CombineParamsWithStyle(Background, [], Result); end; function TcxSchedulerStyles.GetContentParams(const ADateTime: TDateTime; AResource: TcxSchedulerStorageResourceItem = nil): TcxViewParams; begin Result := GetContentParams( ADateTime, Scheduler.DoIsWorkTime(AResource, ADateTime), AResource); end; function TcxSchedulerStyles.GetContentParams(const ADateTime: TDateTime; ALightColor: Boolean; AResource: TcxSchedulerStorageResourceItem = nil): TcxViewParams; var AStyle: TcxStyle; begin GetDefaultViewParams(cxcsContent, AResource, Result); CombineParamsWithStyle(Content, [], Result); if Assigned(FOnGetContentStyle) then begin AStyle := nil; FOnGetContentStyle(Scheduler, AResource, ADateTime, AStyle); if AStyle <> nil then CombineParamsWithStyle(AStyle, [], Result); end; Result.Color := PainterHelper.GetContentColor(Result.Color, ALightColor); end; function TcxSchedulerStyles.GetEventContentParams( AEvent: TcxSchedulerEvent): TcxViewParams; var AStyle: TcxStyle; begin GetDefaultViewParams(cxcsEvent, AEvent, Result); CombineParamsWithStyle(Content, [cxStyles.svColor], Result); CombineParamsWithStyle(Event, [], Result); if (AEvent <> nil) and EventContentSelected(TcxSchedulerControlEvent(AEvent)) then CombineParamsWithStyle(Selection, [], Result); if Assigned(OnGetEventStyle) then begin AStyle := nil; OnGetEventStyle(Scheduler, AEvent, AStyle); CombineParamsWithStyle(AStyle, [], Result); end; end; function TcxSchedulerStyles.IsEventStyleAssigned( AEvent: TcxSchedulerEvent): Boolean; var AStyle: TcxStyle; begin Result := (AEvent.LabelColor <> clDefault) or (Event <> nil); if not Result and Assigned(FOnGetEventStyle) then begin AStyle := nil; FOnGetEventStyle(Scheduler, AEvent, AStyle); Result := AStyle <> nil; end; end; function TcxSchedulerStyles.GetDayHeaderParams( const ADate: TDateTime): TcxViewParams; var AStyle: TcxStyle; begin //DELPHI8! check Trunc(ADate) GetDefaultViewParams(cxcsDayHeader, Pointer(Trunc(ADate)), Result); CombineParamsWithStyle(DayHeader, [], Result); if Assigned(FOnGetDayHeaderStyle) then begin AStyle := nil; FOnGetDayHeaderStyle(Scheduler, ADate, AStyle); CombineParamsWithStyle(AStyle, [], Result) end; end; function TcxSchedulerStyles.GetGroupSeparatorParams: TcxViewParams; begin GetDefaultViewParams(cxcsGroupSeparator, nil, Result); CombineParamsWithStyle(GroupSeparator, [], Result); end; function TcxSchedulerStyles.GetResourceHeaderParams( AResource: TcxSchedulerStorageResourceItem): TcxViewParams; var AStyle: TcxStyle; begin GetDefaultViewParams(cxcsResourceHeader, AResource, Result); CombineParamsWithStyle(ResourceHeader, [], Result); if Assigned(FOnGetResourceHeaderStyle) then begin AStyle := nil; FOnGetResourceHeaderStyle(Scheduler, AResource, AStyle); CombineParamsWithStyle(AStyle, [], Result); end; end; function TcxSchedulerStyles.GetSplitterParams( AKind: TcxSchedulerSplitterKind): TcxViewParams; var AIndex: Integer; begin AIndex := cxcsHSplitter + Byte(AKind); GetDefaultViewParams(AIndex, nil, Result); CombineParamsWithStyle(GetValue(AIndex), [], Result); end; function TcxSchedulerStyles.GetSelectionParams: TcxViewParams; begin GetDefaultViewParams(cxcsSelection, nil, Result); CombineParamsWithStyle(Selection, [], Result); end; procedure TcxSchedulerStyles.Changed(AIndex: Integer); begin inherited Changed(AIndex); if GetOwner is TcxCustomScheduler then begin Scheduler.DateNavigator.CheckSizes; Scheduler.LayoutChanged; end; end; function TcxSchedulerStyles.EventContentSelected( AEvent: TcxSchedulerControlEvent): Boolean; begin Result := AEvent.Selected and not (Scheduler.EditController.Event = AEvent) and Scheduler.CurrentView.EventContentSelected(AEvent); end; procedure TcxSchedulerStyles.GetDefaultViewParams( Index: Integer; AData: TObject; out AParams: TcxViewParams); var AEvent: TcxSchedulerControlEvent; ASelected: Boolean; begin AParams.Bitmap := nil; AParams.Font := Scheduler.Font; AParams.TextColor := AParams.Font.Color; AParams.Color := Scheduler.Color; case Index of cxcsDayHeader, cxcsResourceHeader: begin AParams.Color := Painter.DefaultHeaderColor; AParams.TextColor := Painter.DefaultHeaderTextColor; end; cxcsBackground: begin AParams.Color := Painter.DefaultSchedulerBackgroundColor; AParams.TextColor := Painter.DefaultSchedulerTextColor; end; cxcsContent: begin AParams.Color := Painter.DefaultSchedulerViewContentColor; if AData <> nil then begin AParams.Color := Resources[TcxSchedulerStorageResourceItem(AData).Index].Color; if AParams.Color = clDefault then AParams.Color := PainterHelper.GetResourceContentColor( TcxSchedulerStorageResourceItem(AData).Index); end; AParams.TextColor := Painter.DefaultSchedulerViewTextColor; end; cxcsSelection: begin AParams.Color := clHighLight; AParams.TextColor := clHighLightText; end; cxcsHSplitter, cxcsVSplitter, cxcsGroupSeparator: AParams.Color := Painter.DefaultSchedulerControlColor; cxcsEvent: if AData <> nil then begin AEvent := TcxSchedulerControlEvent(AData); ASelected := EventContentSelected(AEvent); if (AEvent.LabelColor = clDefault) or ASelected then begin if ASelected then begin AParams.Color := GetSelectionParams.Color; AParams.TextColor := GetSelectionParams.TextColor; end else AParams.Color := EventContentColors[AEvent.AllDayEvent or (AEvent.Duration >= 1)]; end else AParams.Color := AEvent.LabelColor; end; end; end; function TcxSchedulerStyles.GetDayHeaderStyle: TcxStyle; begin Result := DayHeader; end; function TcxSchedulerStyles.GetEventParams(AEvent: TcxSchedulerEvent): TcxViewParams; begin Result := GetEventContentParams(AEvent); end; function TcxSchedulerStyles.GetResourceHeaderStyle: TcxStyle; begin Result := ResourceHeader; end; function TcxSchedulerStyles.GetPainter: TcxCustomLookAndFeelPainterClass; begin Result := Scheduler.LookAndFeelPainter; end; function TcxSchedulerStyles.GetPainterHelperClass: TcxSchedulerPainterHelperClass; begin Result := Scheduler.PainterHelper end; function TcxSchedulerStyles.GetResources: TcxSchedulerStorageResourceItems; begin Result := Scheduler.CurrentView.Resources; end; { TcxSchedulerHintController } constructor TcxSchedulerHintController.Create(AOwner: TcxCustomScheduler); begin FOwner := AOwner; FTimer := TTimer.Create(nil); FTimer.Enabled := False; FTimer.OnTimer := TimerHandler; FHintWindow := HintWindowClass.Create(nil); end; destructor TcxSchedulerHintController.Destroy; begin Hide; FreeAndNil(FTimer); FreeAndNil(FHintWindow); inherited Destroy; end; procedure TcxSchedulerHintController.Activate(const AHintRect: TRect; const AHintText: string; AImmediateHint: Boolean = False); begin Hide; FHintText := AHintText; FHintRect := AHintRect; FAutoHide := not AImmediateHint; if AImmediateHint then ShowHint else StartShowHintTimer; end; function TcxSchedulerHintController.CalcHintRect(AMaxWidth: Integer; const AHintText: string; AFlags: Integer): TRect; begin CheckHintClass; FHintFlags := AFlags; Result := FHintWindow.CalcHintRect(AMaxWidth, AHintText, nil); end; procedure TcxSchedulerHintController.Hide; begin HideHint; end; procedure TcxSchedulerHintController.Reset; begin Hide; end; procedure TcxSchedulerHintController.CheckHintClass; begin if FHintWindow.ClassType <> HintWindowClass then begin FHintWindow.Free; FHintWindow := HintWindowClass.Create(nil); end; end; procedure TcxSchedulerHintController.HideHint; begin StopTimer; FHintWindow.Hide; ShowWindow(FHintWindow.Handle, SW_HIDE); //MUST USE ShowWindow - WIN32 BUG end; procedure TcxSchedulerHintController.ShowHint; begin HideHint; if not Scheduler.OptionsView.ShowHints then Exit; CheckHintClass; FHintWindow.Color := clInfoBk; with GetMouseCursorPos do begin if FAutoHide then begin FHintRect := cxRectOffset(FHintRect, X, Y); if FHintFlags and cxAlignRight = cxAlignRight then FHintRect := cxRectSetRight(FHintRect, X); if FHintFlags and cxAlignBottom = cxAlignBottom then FHintRect := cxRectSetTop(FHintRect, Y + cxGetCursorSize.cy); end; end; FHintWindow.ActivateHint(FHintRect, FHintText); if FAutoHide then StartHideHintTimer; end; procedure TcxSchedulerHintController.StartHideHintTimer; begin FTimer.Tag := 0; FTimer.Interval := cxscWaitForHideHint; FTimer.Enabled := True; end; procedure TcxSchedulerHintController.StartShowHintTimer; begin FTimer.Tag := 1; FTimer.Interval := cxscWaitForShowHint; FTimer.Enabled := True; end; procedure TcxSchedulerHintController.StopTimer; begin FTimer.Enabled := False; end; procedure TcxSchedulerHintController.TimerHandler(Sender: TObject); begin if FTimer.Tag = 0 then HideHint else ShowHint; end; { TcxSchedulerEventHitTestController } constructor TcxSchedulerEventHitTestController.Create( AOwner: TcxCustomScheduler); begin FOwner := AOwner; end; procedure TcxSchedulerEventHitTestController.MouseMove( X, Y: Integer; AShift: TShiftState); var R: TRect; AHintText: string; begin if Scheduler.IsDesigning then Exit; if (ssLeft in AShift) or not HitTest.HitAtEvent then begin HintController.HideHint; if not HitTest.HitAtEvent then FPrevHintEvent := nil; end; if HitTest.HitAtEvent and (FPrevHintEvent <> HitTest.Event) then begin if HitTest.NeedShowHint then begin FPrevHintEvent := HitTest.Event; AHintText := Scheduler.GetEventHintText(FPrevHintEvent); R := HintController.CalcHintRect(Max(cxscMinHintWindth, cxRectWidth(HitTest.FEventBounds)), AHintText, cxAlignBottom); HintController.Activate(R, AHintText); end; if Scheduler.OptionsView.HotTrack then Scheduler.CurrentView.InvalidateRect(HitTest.FEventBounds); end; end; function TcxSchedulerEventHitTestController.GetHintController: TcxSchedulerHintController; begin Result := Scheduler.HintController; end; function TcxSchedulerEventHitTestController.GetHitTest: TcxSchedulerViewHitTest; begin Result := Scheduler.CurrentView.HitTest; end; { TcxSchedulerSplitterController } procedure TcxSchedulerSplitterController.DoCancelMode; begin EraseInvertRect; Scheduler.FCaptureControl := nil; Scheduler.FKeyboardListener := FSaveKeyboardListener; end; procedure TcxSchedulerSplitterController.KeyDown(var Key: Word; Shift: TShiftState); begin if Scheduler.OptionsCustomize.ControlsSizing and Scheduler.IsDragCanceled then begin DoCancelMode; Mouse.Capture := 0; end; end; procedure TcxSchedulerSplitterController.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if Scheduler.OptionsCustomize.ControlsSizing and (ssLeft in Shift) then begin FSaveKeyboardListener := Scheduler.KeyboardListener; Scheduler.KeyboardListener := Splitter; FHitPoint := GetOwnerMousePos(X, Y); FStartBounds := Splitter.Bounds; FSizingBoundsRect := GetSizingBoundsRect; FScreenCanvasClipRect := GetDrawClipRect; if not IsDynamicUpdate then begin Scheduler.Update; //force repaint before on-screen drawing DrawInvertRect(FStartBounds); end; FPrevRect := FStartBounds; end; end; procedure TcxSchedulerSplitterController.MouseMove(Shift: TShiftState; X, Y: Integer); var R: TRect; begin if not Scheduler.OptionsCustomize.ControlsSizing or (Scheduler.CaptureController <> Self) or Scheduler.IsLocked then Exit; R := GetSizingRect(GetOwnerMousePos(X, Y)); if not cxRectIsEqual(R, FPrevRect) then begin if IsDynamicUpdate then UpdateSizing(R) else DrawInvertRect(R); FPrevRect := R; end; end; procedure TcxSchedulerSplitterController.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if not Scheduler.OptionsCustomize.ControlsSizing then Exit; Scheduler.KeyboardListener := FSaveKeyboardListener; EraseInvertRect; UpdateSizing(GetSizingRect(GetOwnerMousePos(X, Y))); end; procedure TcxSchedulerSplitterController.DrawInvertRect(const R: TRect); var Temp: TRect; AOffset: TPoint; ACanvas: TcxCanvas; begin if not cxRectIsEmpty(FPrevInvertRect) and cxRectIntersect(Temp, R, FPrevInvertRect) then begin SubtractRect(FPrevInvertRect, FPrevInvertRect, Temp); SubtractRect(Temp, R, Temp); end else Temp := R; AOffset := ScreenOffset; ACanvas := TcxScreenCanvas.Create; InvertRect(ACanvas, cxRectOffset(FPrevInvertRect, AOffset)); InvertRect(ACanvas, cxRectOffset(Temp, AOffset)); ACanvas.Free; FPrevInvertRect := R; end; procedure TcxSchedulerSplitterController.EraseInvertRect; var ACanvas: TcxCanvas; begin if cxRectIsEmpty(FPrevInvertRect) then Exit; ACanvas := TcxScreenCanvas.Create; InvertRect(ACanvas, cxRectOffset(FPrevInvertRect, ScreenOffset)); FPrevInvertRect := cxNullRect; ACanvas.Free; end; function TcxSchedulerSplitterController.GetMonthSize: TSize; begin Result := Scheduler.DateNavigator.GetMonthSize; end; function TcxSchedulerSplitterController.GetOwnerMousePos(X, Y: Integer): TPoint; begin Result := cxPoint(X + Owner.Bounds.Left, Y + Owner.Bounds.Top); end; function TcxSchedulerSplitterController.GetSizingBoundsRect: TRect; begin Result := Scheduler.ClientBounds; if Splitter.Kind = skHorizontal then SetVertBounds(Result) else SetHorzBounds(Result); end; function TcxSchedulerSplitterController.GetSizingIncrement: Integer; begin if not IsIntegralSizing then Result := 1 else if Splitter.Kind = skVertical then Result := GetMonthSize.cx else Result := GetMonthSize.cy; end; function TcxSchedulerSplitterController.GetSizingRect(const P: TPoint): TRect; begin if Splitter.Kind = skHorizontal then Result := GetVertSizingRect(P) else Result := GetHorzSizingRect(P); with SizingBoundsRect do begin if Result.Left < Left then Result := cxRectSetLeft(Result, Left); if Result.Top < Top then Result := cxRectSetTop(Result, Top); if Result.Right > Right then Result := cxRectSetRight(Result, Right); if Result.Bottom > Bottom then Result := cxRectSetBottom(Result, Bottom); end; end; procedure TcxSchedulerSplitterController.InvertRect(ACanvas: TcxCanvas; R: TRect); begin if cxRectIsEmpty(R) then Exit; if Splitter.Kind = skHorizontal then begin R.Left := Max(R.Left, ScreenCanvasClipRect.Left); R.Right := Min(R.Right, ScreenCanvasClipRect.Right); end else begin R.Top := Max(R.Top, ScreenCanvasClipRect.Top); R.Bottom := Min(R.Bottom, ScreenCanvasClipRect.Bottom); end; if not cxRectIsEmpty(R) then ACanvas.InvertRect(R); end; function TcxSchedulerSplitterController.IsIntegralSizing: Boolean; begin Result := Scheduler.OptionsCustomize.IntegralSizing; end; function TcxSchedulerSplitterController.IsDynamicUpdate: Boolean; begin Result := Scheduler.IsDynamicUpdate; end; procedure TcxSchedulerSplitterController.SetSizeDelta(ADelta: Integer); begin if Splitter.Kind = skHorizontal then SetVertDelta(ADelta) else SetHorzDelta(ADelta); end; procedure TcxSchedulerSplitterController.UpdateSizing(const R: TRect); function GetDelta: Integer; begin if Splitter.Kind = skHorizontal then Result := Splitter.Top - R.Top else Result := Splitter.Left - R.Left; end; var ADelta: Integer; begin ADelta := GetDelta; if ADelta <> 0 then begin SetSizeDelta(ADelta); if IsDynamicUpdate then Scheduler.Update; Scheduler.DateNavigator.SaveSize; end; end; function TcxSchedulerSplitterController.GetDrawClipRect: TRect; var AParent: TControl; R: TRect; begin with Scheduler do begin Result := cxRectOffset(ClientBounds, ClientToScreen(cxNullPoint)); AParent := Parent; end; while AParent <> nil do begin R := cxRectOffset(AParent.ClientRect, AParent.ClientOrigin); if AParent.Parent <> nil then cxRectOffset(R, AParent.ClientToScreen(cxNullPoint)); cxRectIntersect(Result, Result, R); AParent := AParent.Parent; end; end; function TcxSchedulerSplitterController.GetHorzSizingRect( const P: TPoint): TRect; var AStep, ANewPos: Integer; begin AStep := GetSizingIncrement; ANewPos := FStartBounds.Left - Round((FHitPoint.X - P.X) / AStep) * AStep; Result := cxRectSetLeft(FStartBounds, ANewPos); end; function TcxSchedulerSplitterController.GetScheduler: TcxCustomScheduler; begin Result := Owner.Scheduler; end; function TcxSchedulerSplitterController.GetScreenOffset: TPoint; begin Result := Scheduler.ClientToScreen(cxNullPoint); end; function TcxSchedulerSplitterController.GetSplitter: TcxSchedulerSplitter; begin Result := TcxSchedulerSplitter(inherited Owner); end; function TcxSchedulerSplitterController.GetVertSizingRect( const P: TPoint): TRect; var AStep, ANewPos: Integer; begin AStep := GetSizingIncrement; ANewPos := FStartBounds.Top - Round((FHitPoint.Y - P.Y) / AStep) * AStep; Result := cxRectSetTop(FStartBounds, ANewPos); end; procedure TcxSchedulerSplitterController.SetHorzBounds(var R: TRect); var W: Integer; begin W := ((R.Right - R.Left - Splitter.Width) div GetMonthSize.cx) * GetMonthSize.cx + Splitter.Width; if Scheduler.IsViewAtLeft then begin if IsIntegralSizing then R.Left := R.Right - W; Dec(R.Right, GetMonthSize.cx); end else begin if IsIntegralSizing then R.Right := R.Left + W; Inc(R.Left, GetMonthSize.cx); end; end; procedure TcxSchedulerSplitterController.SetHorzDelta(ADelta: Integer); begin with Scheduler do begin if IsViewAtLeft then CurrentView.Width := CurrentView.Width - ADelta else DateNavigator.Width := DateNavigator.Width - ADelta; end; end; procedure TcxSchedulerSplitterController.SetVertBounds(var R: TRect); begin if IsIntegralSizing then R.Bottom := R.Top + ((R.Bottom - R.Top - Splitter.Height) div GetMonthSize.cy) * GetMonthSize.cy + Splitter.Height; Inc(R.Top, GetMonthSize.cy); end; procedure TcxSchedulerSplitterController.SetVertDelta(ADelta: Integer); begin with Scheduler.DateNavigator do Height := Height - ADelta; end; { TcxSchedulerCustomDataNavigator } constructor TcxSchedulerCustomDateNavigator.Create( AOwner: TcxCustomScheduler); begin inherited Create(AOwner); FSaveSelectionList := TcxSchedulerDateList.Create; end; destructor TcxSchedulerCustomDateNavigator.Destroy; begin FSaveSelectionList.Free; inherited Destroy; end; procedure TcxSchedulerCustomDateNavigator.BeginUpdate; begin if FLockCount = 0 then SaveState; Inc(FLockCount); end; procedure TcxSchedulerCustomDateNavigator.CancelUpdates; begin FLockCount := 0; end; procedure TcxSchedulerCustomDateNavigator.EndUpdate; begin Dec(FLockCount); if FLockCount <= 0 then begin FLockCount := 0; CheckChanges; end; end; procedure TcxSchedulerCustomDateNavigator.CheckChanges; var I: Integer; ACallEvent: Boolean; begin if (FSaveRealFirstDate <> GetRealFirstDate) or (FSaveRealLastDate <> GetRealLastDate) then DoPeriodChangedEvent; GetSelection.Changed := False; ACallEvent := GetSelection.Count <> FSaveSelectionList.Count; if not ACallEvent then for I := 0 to FSaveSelectionList.Count - 1 do if FSaveSelectionList[I] <> GetSelection[I] then begin ACallEvent := True; break; end; if ACallEvent then DoSelectionChangedEvent; SaveState; end; function TcxSchedulerCustomDateNavigator.GetMonthSize: TSize; begin Result := cxNullSize; end; function TcxSchedulerCustomDateNavigator.GetSelection: TcxSchedulerDateList; begin Result := Scheduler.SelectedDays; end; procedure TcxSchedulerCustomDateNavigator.PeriodChanged; begin Scheduler.DateNavigatorSelectionChanged; end; procedure TcxSchedulerCustomDateNavigator.SaveSize; begin FSavedSize := cxSize(Width, Height); end; procedure TcxSchedulerCustomDateNavigator.SaveState; begin FSaveSelectionList.Assign(GetSelection); FSaveRealFirstDate := GetRealFirstDate; FSaveRealLastDate := GetRealLastDate; end; procedure TcxSchedulerCustomDateNavigator.ScrollSelection(AForward: Boolean; ANeedDate: TDateTime; AIsByPage: Boolean); begin BeginUpdate; try DoScrollSelection(AForward, ANeedDate, AIsByPage); finally EndUpdate; end; end; procedure TcxSchedulerCustomDateNavigator.ScrollSelection(AScrollDelta: Integer); begin BeginUpdate; try DoScrollSelection(AScrollDelta); finally EndUpdate; end; end; function TcxSchedulerCustomDateNavigator.GetEventDays: TcxSchedulerDateList; begin Result := Scheduler.EventDays; end; { TcxSchedulerSplitter } function TcxSchedulerSplitter.AllowDesignHitTest( X, Y: Integer; AShift: TShiftState): Boolean; begin Result := True; end; function TcxSchedulerSplitter.CreateController: TcxSchedulerSubControlController; begin Result := TcxSchedulerSplitterController.Create(Self); end; procedure TcxSchedulerSplitter.DoLayoutChanged; begin FViewParams := Styles.GetSplitterParams(Kind); inherited DoLayoutChanged; end; procedure TcxSchedulerSplitter.DoPaint; begin LookAndFeelPainter.DrawSchedulerSplitterBorder(Canvas, ClientRect, ViewParams, Kind = skHorizontal); end; procedure TcxSchedulerSplitter.UpdateCursor; const Cursors: array[TcxSchedulerSplitterKind] of TCursor = ( crSchedulerVertSplit, crSchedulerHorzSplit); begin if Scheduler.OptionsCustomize.ControlsSizing then Cursor := Cursors[Kind] else Cursor := crDefault; end; procedure TcxSchedulerSplitter.SetKind(AKind: TcxSchedulerSplitterKind); begin FKind := AKind; UpdateCursor; end; { TContainer } constructor TContainer.Create(AOwner: TComponent); begin inherited Create(AOwner); ControlStyle := ControlStyle + [csAcceptsControls] + [csNoDesignVisible]; Visible := False; TabStop := False; end; procedure TContainer.CreateParams(var Params: TCreateParams); begin inherited CreateParams(Params); with Params do begin Style := WS_CHILD or WS_CLIPCHILDREN or WS_CLIPSIBLINGS; ExStyle := WS_EX_CONTROLPARENT; WindowClass.Style := CS_DBLCLKS; end; end; { TcxSchedulerEventOperations } constructor TcxSchedulerEventOperations.Create( AOwner: TcxCustomScheduler); begin FScheduler := AOwner; FCreating := True; FDeleting := True; FDialogEditing := True; FDialogShowing := True; FInplaceEditing := True; FMoving := True; FMovingBetweenResources := True; FReadOnly := False; FRecurrence := True; FSizing := True; end; procedure TcxSchedulerEventOperations.Assign(Source: TPersistent); begin if Source is TcxSchedulerEventOperations then with TcxSchedulerEventOperations(Source) do begin Self.FCreating := FCreating; Self.FDeleting := FDeleting; Self.FDialogEditing := FDialogEditing; Self.FDialogShowing := FDialogShowing; Self.FInplaceEditing := FInplaceEditing; Self.FMoving := FMoving; Self.FMovingBetweenResources := FMovingBetweenResources; Self.FReadOnly := FReadOnly; Self.FRecurrence := FRecurrence; Self.FSizing := FSizing; end else inherited Assign(Source); end; function TcxSchedulerEventOperations.GetOwner: TPersistent; begin Result := FScheduler; end; function TcxSchedulerEventOperations.GetCreating: Boolean; begin Result := not FReadOnly and FCreating; end; function TcxSchedulerEventOperations.GetCreatingStored: Boolean; begin Result := not (FReadOnly or FCreating); end; function TcxSchedulerEventOperations.GetDeleting: Boolean; begin Result := not FReadOnly and FDeleting; end; function TcxSchedulerEventOperations.GetDeletingStored: Boolean; begin Result := not (FReadOnly or FDeleting); end; function TcxSchedulerEventOperations.GetDialogEditing: Boolean; begin Result := not FReadOnly and FDialogEditing; end; function TcxSchedulerEventOperations.GetDialogEditingStored: Boolean; begin Result := not (FReadOnly or FDialogEditing); end; function TcxSchedulerEventOperations.GetInplaceEditing: Boolean; begin Result := not FReadOnly and FInplaceEditing; end; function TcxSchedulerEventOperations.GetInplaceEditingStored: Boolean; begin Result := not (FReadOnly or FInplaceEditing); end; function TcxSchedulerEventOperations.GetMoving: Boolean; begin Result := not FReadOnly and FMoving; end; function TcxSchedulerEventOperations.GetMovingBetweenResources: Boolean; begin Result := not FReadOnly and FMovingBetweenResources; end; function TcxSchedulerEventOperations.GetMovingBetweenResourcesStored: Boolean; begin Result := not (FReadOnly or FMovingBetweenResources); end; function TcxSchedulerEventOperations.GetMovingStored: Boolean; begin Result := not (FReadOnly or FMoving); end; function TcxSchedulerEventOperations.GetSizing: Boolean; begin Result := not FReadOnly and FSizing; end; function TcxSchedulerEventOperations.GetSizingStored: Boolean; begin Result := not (FReadOnly or FSizing); end; { TcxSchedulerViewNavigation } constructor TcxSchedulerViewNavigation.Create( AView: TcxSchedulerCustomView); begin FView := AView; end; procedure TcxSchedulerViewNavigation.CheckSelection; begin with Scheduler do Self.ValidateSelection(FSelStart, FSelFinish, FSelResource); end; procedure TcxSchedulerViewNavigation.ReplaceSelParams( const ASelStart, ASelFinish: TDateTime); begin ReplaceSelParams(ASelStart, ASelFinish, GetResourceItem); end; procedure TcxSchedulerViewNavigation.ReplaceSelParams( const ASelStart, ASelFinish: TDateTime; AResource: TcxSchedulerStorageResourceItem); begin Scheduler.ReplaceSelParams(ASelStart, ASelFinish, AResource); end; procedure TcxSchedulerViewNavigation.SetSelAnchor( const Anchor: TDateTime; AShift: TShiftState); begin SetSelAnchor(Anchor, AShift, SelResource); end; procedure TcxSchedulerViewNavigation.SetSelAnchor( const Anchor: TDateTime; AShift: TShiftState; AResource: TcxSchedulerStorageResourceItem); var APrevSelResource: TObject; APrevSelStart, APrevSelFinish: TDateTime; procedure StoreSelection; begin with Scheduler do begin APrevSelResource := SelResource; APrevSelStart := SelStart; APrevSelFinish := SelFinish; end; end; function NeedUpdateOnMouseAction: Boolean; begin with Scheduler do Result := (ssLeft in AShift) and ((SelResource <> APrevSelResource) or (SelStart <> APrevSelStart) or (SelFinish <> APrevSelFinish)); end; begin StoreSelection; if not (ssShift in AShift) or (AResource <> SelResource) then Scheduler.ReplaceSelParams(Anchor, Anchor, AResource) else Scheduler.ReplaceSelParams(Scheduler.FSelStart, Anchor, AResource); if NeedUpdateOnMouseAction then View.LayoutChanged; end; procedure TcxSchedulerViewNavigation.ValidateSelection(var ASelStart, ASelFinish: TDateTime; var AResource: TcxSchedulerStorageResourceItem); begin end; procedure TcxSchedulerViewNavigation.DoKeyDown( var AKey: Word; AShift: TShiftState); begin Scheduler.BeginUpdate; try FCurrentAnchor := SelAnchor; FCurrentResource := SelResource; FShift := AShift; KeyDown(AKey, AShift); Scheduler.LayoutChanged; finally Scheduler.EndUpdate; end; end; function TcxSchedulerViewNavigation.IsKeyNavigation( var AKey: Word; AShift: TShiftState): Boolean; begin Result := (AKey = VK_UP) or (AKey = VK_DOWN) or (AKey = VK_Next) or (AKey = VK_Prior) or (AKey = VK_Left) or (AKey = VK_Right) or (AKey = VK_Home) or (AKey = VK_End); end; function TcxSchedulerViewNavigation.IsSingleLine: Boolean; begin Result := TimeOf(Abs(Scheduler.FSelStart - Scheduler.FSelFinish)) <= View.GetTimeIncrement; end; function TcxSchedulerViewNavigation.GetResourceItem: TcxSchedulerStorageResourceItem; begin Result := nil; end; procedure TcxSchedulerViewNavigation.KeyDown(var AKey: Word; AShift: TShiftState); begin end; procedure TcxSchedulerViewNavigation.ReplaceDate( ADate: TDateTime; AResource: TcxSchedulerStorageResourceItem); begin if AResource = nil then AResource := SelResource; with Scheduler do begin ADate := ADate - DateOf(FSelFinish); ReplaceSelParams(FSelStart + ADate, FSelFinish + ADate, AResource); end; end; function TcxSchedulerViewNavigation.GetScheduler: TcxCustomScheduler; begin Result := View.Scheduler; end; function TcxSchedulerViewNavigation.GetSelAnchor: TDateTime; begin Result := Scheduler.FSelFinish end; function TcxSchedulerViewNavigation.GetSelRealStart: TDateTime; begin Result := Scheduler.FSelStart; end; function TcxSchedulerViewNavigation.GetSelFinish: TDateTime; begin Result := Max(Scheduler.FSelFinish, Scheduler.FSelStart); end; function TcxSchedulerViewNavigation.GetSelResource: TcxSchedulerStorageResourceItem; begin Result := Scheduler.SelResource; end; function TcxSchedulerViewNavigation.GetSelStart: TDateTime; begin Result := Min(Scheduler.FSelFinish, Scheduler.FSelStart); end; function TcxSchedulerViewNavigation.GetTimeIncrement: TDateTime; begin Result := View.GetTimeIncrement; end; { TcxSchedulerViewController } constructor TcxSchedulerViewController.Create(AOwner: TcxSchedulerSubControl); begin inherited Create(AOwner); FNavigation := CreateNavigation; end; destructor TcxSchedulerViewController.Destroy; begin FNavigation.Free; inherited Destroy; end; function TcxSchedulerViewController.CanCreateEventUsingDialog: Boolean; begin with Scheduler.EventOperations do Result := Scheduler.StorageActive and CanShowEventDialog and Creating and DialogEditing and not GetResourceReadOnly; end; function TcxSchedulerViewController.CanCreateEventUsingInplaceEdit: Boolean; begin with Scheduler.EventOperations do Result := Scheduler.StorageActive and Creating and InplaceEditing and not GetResourceReadOnly and IsCaptionAvailable and (Scheduler.SelectedEventCount = 0); end; function TcxSchedulerViewController.CanEditEvent( AEvent: TcxSchedulerControlEvent; AInplace: Boolean): Boolean; begin with Scheduler.EventOperations do begin if AInplace then Result := InplaceEditing and IsCaptionAvailable else Result := DialogEditing and DialogShowing; end; Result := Result and (AEvent <> nil); if AInplace and Result then Result := not AEvent.ReadOnly; end; function TcxSchedulerViewController.CanShowEventDialog: Boolean; begin Result := Scheduler.EventOperations.DialogShowing and Assigned(cxEventEditorClass); end; procedure TcxSchedulerViewController.DeleteSelectedEvents; begin Scheduler.InternalDeleteSelectedEvents(False, True); end; function TcxSchedulerViewController.IsEventEditing( AEvent: TcxSchedulerControlEvent; AResource: TcxSchedulerStorageResourceItem): Boolean; begin Result := IsEditing and (EditController.Event = AEvent) and (EditController.FEditResource = AResource); end; procedure TcxSchedulerViewController.SelectSingleEvent( AEvent: TcxSchedulerControlEvent; ADate: TDateTime; AMakeVisible: Boolean = True); begin if AMakeVisible then View.MakeEventVisible(AEvent, ADate, nil); Scheduler.EventList.Selection.Add(AEvent, []); end; procedure TcxSchedulerViewController.BeforeMouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin StopEditShowingTimer; Scheduler.HintController.Hide; if Button <> mbLeft then Exit; FDragKind := HitTest.GetDragKind; if DragKind <> edkNone then begin CloseInplaceEdit; FDragEvent := HitTest.Event; FStartDragHitTime := HitTest.Time; FStartDragFlags := HitTest.Flags; FStartDragResource := HitTest.Resource; end; end; procedure TcxSchedulerViewController.CancelScroll; begin end; function TcxSchedulerViewController.CanDrag(X, Y: Integer): Boolean; begin Result := (DragKind in [edkEventDragRect, edkMoveEvent]); if Result then begin if Scheduler.EventList.Selection.IsSelected(DragEvent) then Result := Scheduler.DoBeforeDragEvent(DragEvent, X, Y) else begin Result := False; SendMessage(Scheduler.Handle, WM_CANCELMODE, 0, 0); end; end; end; procedure TcxSchedulerViewController.CheckOpenInplaceEditorOnMouseUp( Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var AEvent: TcxSchedulerControlEvent; begin if FLockShowEditorOnMouseClick then Exit; if (HitTest.HitAtEvent and (HitTest.Event = FBeforeFocusedEvent)) and (Button = mbLeft) and ([ssShift, ssCtrl] * Shift = []) and not (FDragKind in [edkResizeStart, edkResizeEnd]) then begin AEvent := HitTest.Event; if cxRectPtIn(View.GetEditRectForEvent(AEvent, DateOf(HitTest.Time), HitTest.Resource), X, Y) and CanEditEvent(AEvent, True) then begin EditController.Init(HitTest.Time, HitTest.Resource); StartEditShowingTimer(AEvent); end; end; FLockShowEditorOnMouseClick := False; FBeforeFocusedEvent := nil; end; procedure TcxSchedulerViewController.CheckScrolling( const APos: TPoint); begin end; procedure TcxSchedulerViewController.CloseInplaceEdit; begin if EditController.IsEditing then begin EditController.CloseEdit(True); HitTest.Recalculate; end; end; function TcxSchedulerViewController.CreateResizeEventHelper: TcxEventSizingHelper; begin Result := TcxEventSizingHelper.Create(Scheduler); end; function TcxSchedulerViewController.CreateDragEventHelper: TcxDragEventHelper; begin Result := TcxDragEventHelper.Create(Scheduler); end; function TcxSchedulerViewController.CreateNavigation: TcxSchedulerViewNavigation; begin Result := TcxSchedulerViewNavigation.Create(View); end; procedure TcxSchedulerViewController.DoCancelMode; begin inherited DoCancelMode; // HotTrackController.SetViewInfo(cxInvalidPoint, nil); FLockShowEditorOnMouseClick := False; end; procedure TcxSchedulerViewController.DragOver(Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); var P: TPoint; begin if Assigned(DragEventHelper) and Accept then begin Owner.MousePositionChanged(X, Y); P := cxPoint(X, Y); HitTest.HitPoint := P; DragEventHelper.DragOver(P, State, Accept); DragEventHelper.UpdateState; end; end; procedure TcxSchedulerViewController.EndDrag(Target: TObject; X, Y: Integer); var Accepted: Boolean; APos: TPoint; begin if Assigned(DragEventHelper) then try APos := Scheduler.ScreenToClient(GetMouseCursorPos); Owner.MousePositionChanged(APos.X, APos.Y); HitTest.HitPoint := APos; Accepted := not Scheduler.IsDragCanceled; if Accepted then Scheduler.DoAfterDragEvent(Target, APos.X, APos.Y, Accepted); FDragEventHelper.EndDrag(Accepted); finally FreeAndNil(FDragEventHelper); end; end; function TcxSchedulerViewController.GetDragAndDropObjectClass: TcxDragAndDropObjectClass; begin Result := TcxSchedulerDragAndDropObject; end; function TcxSchedulerViewController.GetResourceReadOnly: Boolean; begin with Scheduler do Result := not StorageValid or ((SelResource <> nil) and SelResource.ReadOnly) or ((Storage.ResourceCount > 0) and ((SelResource = nil) and not OptionsView.ShowEventsWithoutResource)); end; function TcxSchedulerViewController.IsCaptionAvailable: Boolean; begin Result := Scheduler.StorageValid and Scheduler.Storage.IsCaptionAvailable; end; function TcxSchedulerViewController.IsDragOperation: Boolean; begin Result := Scheduler.Dragging or (Scheduler.DragAndDropState <> ddsNone); end; procedure TcxSchedulerViewController.KeyDown( var Key: Word; Shift: TShiftState); var I, SelectedIndex: Integer; begin if View.Active and not EditController.IsEditing then begin if Navigation.IsKeyNavigation(Key, Shift) then begin Scheduler.BeginUpdate; try UnselectEvents; Navigation.DoKeyDown(Key, Shift); finally Scheduler.EndUpdate; end; end; case Key of VK_ESCAPE: if Scheduler.CaptureController = Self then UnselectEvents; VK_DELETE: DeleteSelectedEvents; VK_TAB: with Scheduler do begin if EventList.Count <> 0 then begin SelectedIndex := -1; for I := 0 to EventList.Count - 1 do if EventList[I].Selected then SelectedIndex := I; Inc(SelectedIndex); while (SelectedIndex < EventList.Count) and not CurrentView.GetEventVisibility(EventList[SelectedIndex]) do Inc(SelectedIndex); if SelectedIndex < EventList.Count then SelectSingleEvent(EventList[SelectedIndex], NullDate) else UnselectEvents; CurrentView.Refresh; end; end; end; end; inherited KeyDown(Key, Shift); end; procedure TcxSchedulerViewController.KeyPress(var Key: Char); var AEvent: TcxSchedulerControlEvent; begin with Scheduler do begin if IsLocked or not StorageActive or GetResourceReadOnly then Exit; if Key in EditStartChars then begin if Key = #13 then begin if SelectedEventCount > 0 then begin AEvent := SelectedEvents[SelectedEventCount - 1]; if CanShowEventDialog then EditEventUsingDialog(AEvent); end else begin if CanCreateEventUsingInplaceEdit then CreateEventUsingInplaceEdit else if CanCreateEventUsingDialog then CreateEventUsingDialog; end; end else if CanCreateEventUsingInplaceEdit then DoCreateEventUsingInplaceEdit(Key); end; end; end; procedure TcxSchedulerViewController.MouseDown( Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var AEvent: TcxSchedulerControlEvent; begin CloseInplaceEdit; if HitTest.HitAtEvent then begin AEvent := HitTest.Event; FBeforeFocusedEvent := AEvent; UpdateEventSelection(AEvent, Button, Shift); if Shift = [ssLeft, ssDouble] then ShowEventEditor(AEvent) else View.Refresh; end else if Button = mbLeft then begin UnselectEvents; if HitTest.HitAtTime then begin FStartSelAnchor := HitTest.Time; Navigation.SetSelAnchor(HitTest.Time, Shift, HitTest.Resource); if (Shift = [ssLeft, ssDouble]) and CanCreateEventUsingDialog then Scheduler.CreateEventUsingDialog; end; end; inherited MouseDown(Button, Shift, X, Y); end; procedure TcxSchedulerViewController.MouseMove(Shift: TShiftState; X, Y: Integer); var Accepted: Boolean; P: TPoint; begin inherited MouseMove(Shift, X, Y); if DragEventHelper <> nil then begin P := cxPoint(X, Y); Accepted := cxRectPtIn(View.Bounds, P); DragEventHelper.DragOver(P, dsDragMove, Accepted); DragEventHelper.UpdateState; end; if (ssLeft in Shift) and not EditController.IsEditing then begin if (DragKind in [edkNone]) and HitTest.HitAtTime then begin if Navigation.SelResource = HitTest.Resource then begin if FStartSelAnchor <> NullDate then Scheduler.FSelStart := FStartSelAnchor; Navigation.SetSelAnchor(HitTest.Time, [ssShift] + Shift) end else Navigation.SetSelAnchor(Scheduler.FSelStart, [ssShift] + Shift); end; end; end; procedure TcxSchedulerViewController.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin inherited MouseUp(Button, Shift, X, Y); CheckOpenInplaceEditorOnMouseUp(Button, Shift, X, Y); FStartSelAnchor := NullDate; FDragKind := edkNone; end; procedure TcxSchedulerViewController.RecreateNavigation; begin FNavigation.Free; FNavigation := CreateNavigation; FNavigation.CheckSelection; end; procedure TcxSchedulerViewController.StartDrag(var DragObject: TDragObject); begin FDragEventHelper := CreateDragEventHelper; if FDragEventHelper <> nil then FDragEventHelper.FDragObject := DragObject; end; function TcxSchedulerViewController.StartDragAndDrop(const P: TPoint): Boolean; begin Result := (DragKind in [edkResizeStart, edkResizeEnd]) and Scheduler.DoBeforeSizingEvent(DragEvent, P.X, P.Y); end; procedure TcxSchedulerViewController.SyncEventSelection( AEvent: TcxSchedulerControlEvent); begin if View.GetTimeIncrement = 1 then Scheduler.ReplaceSelParams(DateOf(AEvent.Start), DateOf(AEvent.Finish) - Byte(AEvent.AllDayEvent or (TimeOf(AEvent.Finish) = 0)) * View.GetTimeIncrement, AEvent.GetResourceItem) else Scheduler.ReplaceSelParams(AEvent.Start, AEvent.Finish - View.GetTimeIncrement, AEvent.GetResourceItem); end; procedure TcxSchedulerViewController.UnselectEvents; begin Scheduler.UnselectEvents end; procedure TcxSchedulerViewController.UpdateEventSelection( AEvent: TcxSchedulerControlEvent; Button: TMouseButton; Shift: TShiftState); begin if AEvent = nil then Exit; with Scheduler.EventList.Selection do if (Button = mbRight) and (Shift * [ssCtrl, ssShift] <> [])then begin if not IsSelected(AEvent) then Add(AEvent, [ssCtrl]); end else Add(AEvent, Shift); SyncEventSelection(AEvent); end; procedure TcxSchedulerViewController.EditShowingTimerHandler(Sender: TObject); begin StopEditShowingTimer; EditController.Activate(FEditShowingTimerItem); end; function TcxSchedulerViewController.GetHitTest: TcxSchedulerViewHitTest; begin Result := View.HitTest; end; function TcxSchedulerViewController.GetEditController: TcxSchedulerEditController; begin Result := Scheduler.EditController; end; function TcxSchedulerViewController.GetIsEditing: Boolean; begin Result := EditController.IsEditing; end; function TcxSchedulerViewController.GetScheduler: TcxCustomScheduler; begin Result := Owner.Scheduler; end; function TcxSchedulerViewController.GetView: TcxSchedulerCustomView; begin Result := TcxSchedulerCustomView(inherited Owner); end; procedure TcxSchedulerViewController.ShowEventEditor( AEvent: TcxSchedulerControlEvent); begin StopEditShowingTimer; if CanShowEventDialog then Scheduler.EditEventUsingDialog(AEvent); end; procedure TcxSchedulerViewController.StartEditShowingTimer( AEvent: TcxSchedulerControlEvent); begin StopEditShowingTimer; FEditShowingTimerItem := AEvent; FEditShowingTimer := TTimer.Create(nil); FEditShowingTimer.Interval := GetDblClickInterval; FEditShowingTimer.OnTimer := EditShowingTimerHandler; end; procedure TcxSchedulerViewController.StopEditShowingTimer; begin FreeAndNil(FEditShowingTimer); end; { TcxSchedulerPopupMenu } constructor TcxSchedulerPopupMenu.Create( AScheduler: TcxCustomScheduler); begin FScheduler := AScheduler; FUseBuiltInPopupMenu := True; end; destructor TcxSchedulerPopupMenu.Destroy; begin PopupMenu := nil; FreeAndNil(FInternalMenu); inherited Destroy; end; procedure TcxSchedulerPopupMenu.Assign(Source: TPersistent); begin if Source is TcxSchedulerPopupMenu then begin PopupMenu := TcxSchedulerPopupMenu(Source).PopupMenu; UseBuiltInPopupMenu := TcxSchedulerPopupMenu(Source).UseBuiltInPopupMenu; end; end; function TcxSchedulerPopupMenu.AddValidSeparator(AOwner: TMenuItem): TMenuItem; begin if AOwner.Count > 0 then Result := CreateSeparator(AOwner) else Result := nil end; procedure TcxSchedulerPopupMenu.CreateInternalMenu; begin FreeAndNil(FInternalMenu); FInternalMenu := TPopupMenu.Create(nil); FInternalMenu.Images := MenuImages; CreateItems; end; procedure TcxSchedulerPopupMenu.CreateItems; begin end; function TcxSchedulerPopupMenu.CreateSeparator(AOwner: TMenuItem): TMenuItem; begin Result := CreateSubItem(AOwner, '-'); end; function TcxSchedulerPopupMenu.CreateSubItem( AOwner: TMenuItem; const ACaption: string; ACommand: Integer = -1; AImageIndex: Integer = -1; AEnabled: Boolean = True; AChecked: Boolean = False): TMenuItem; begin Result := TMenuItem.Create(nil); Result.Caption := ACaption; Result.Enabled := AEnabled; Result.ImageIndex := AImageIndex; Result.Checked := AChecked; Result.Tag := ACommand; Result.OnClick := OnItemClickHandler; AOwner.Add(Result); end; procedure TcxSchedulerPopupMenu.DoExecute(ACommand: Integer); begin end; function TcxSchedulerPopupMenu.DoOnClick(ACommand: Integer): Boolean; begin Result := False; end; function TcxSchedulerPopupMenu.DoOnPopup: Boolean; begin Result := False; end; procedure TcxSchedulerPopupMenu.ExecuteCommand(ACommand: Integer); begin if IsValidCommand(ACommand) and not DoOnClick(ACommand) then DoExecute(ACommand); end; function TcxSchedulerPopupMenu.FindItemByCommand(AOwnerItem: TMenuItem; ACommand: Integer): TMenuItem; var I: Integer; begin Result := nil; if (InternalMenu = nil) or (AOwnerItem = nil) then Exit; with AOwnerItem do for I := 0 to Count - 1 do if (Items[I].Tag = Ord(ACommand)) and (Items[I].Caption <> '-') then begin Result := Items[I]; system.Break; end; end; function TcxSchedulerPopupMenu.IsValidCommand(ACommand: Integer): Boolean; begin Result := True; end; function TcxSchedulerPopupMenu.Popup(X, Y: Integer): Boolean; begin CreateInternalMenu; Result := DoOnPopup; if not Result then begin if UseBuiltInPopupMenu then Result := ShowPopupMenu(Scheduler, FInternalMenu, X, Y) else Result := ShowPopupMenu(Scheduler, FPopupMenu, X, Y); end; end; procedure TcxSchedulerPopupMenu.OnItemClickHandler(Sender: TObject); begin if Sender is TComponent then ExecuteCommand(TComponent(Sender).Tag); end; function TcxSchedulerPopupMenu.Storage: TcxCustomSchedulerStorage; begin Result := Scheduler.Storage; end; function TcxSchedulerPopupMenu.GetRoot: TMenuItem; begin Result := FInternalMenu.Items; end; procedure TcxSchedulerPopupMenu.SetPopupMenu(const Value: TComponent); begin if FPopupMenu <> Value then begin if (FPopupMenu <> nil) and not (csDestroying in FPopupMenu.ComponentState) then FPopupMenu.RemoveFreeNotification(Scheduler); FPopupMenu := Value; if FPopupMenu <> nil then FPopupMenu.FreeNotification(Scheduler); end; end; { TcxSchedulerCustomContentPopupMenu } constructor TcxSchedulerCustomContentPopupMenu.Create( AScheduler: TcxCustomScheduler); begin inherited Create(AScheduler); FNewID := -1; FAllDayID := -1; FReccurenceID := -1; end; function TcxSchedulerCustomContentPopupMenu.CanCreateEvent: Boolean; begin Result := Scheduler.CurrentView.Controller.CanCreateEventUsingDialog; end; procedure TcxSchedulerCustomContentPopupMenu.CreateNewEventItems(ANew, AllDay, AReccurence: Boolean; ANewID, AllDayID, AReccurenceID: Integer); var AEnabled: Boolean; begin AEnabled := CanCreateEvent; if ANew then begin CreateSubItem(Root, cxGetResourceString(@scxpmNewEvent), ANewID, 2, AEnabled); FNewID := ANewID; end; if AllDay then begin CreateSubItem(Root, cxGetResourceString(@scxpmNewAllDayEvent), AllDayID, -1, AEnabled); FAllDayID := AllDayID; end; if Scheduler.StorageActive and Storage.IsRecurrenceAvailable and AReccurence and Scheduler.EventOperations.Recurrence then begin CreateSubItem(Root, cxGetResourceString(@scxpmNewRecurringEvent), AReccurenceID, 3, AEnabled); FReccurenceID := AReccurenceID; end; AddValidSeparator(Root); end; procedure TcxSchedulerCustomContentPopupMenu.DoExecute(ACommand: Integer); begin if ACommand <> -1 then begin if ACommand = FNewID then Scheduler.CreateEventUsingDialog else if ACommand = FAllDayID then Scheduler.CreateEventUsingDialog(True) else if ACommand = FReccurenceID then Scheduler.CreateEventUsingDialog(False, True); end; end; { TcxSchedulerContentPopupMenu } constructor TcxSchedulerContentPopupMenu.Create( AScheduler: TcxCustomScheduler); begin inherited Create(AScheduler); FItems := [cpmiNewEvent, cpmiNewAllDayEvent, cpmiNewReccuringEvent, cpmiToday, cpmiGoToDate, cpmiGoToThisDay, cpmiResourcesLayout]; end; procedure TcxSchedulerContentPopupMenu.Assign(Source: TPersistent); begin inherited Assign(Source); if Source is TcxSchedulerContentPopupMenu then begin Items := TcxSchedulerContentPopupMenu(Source).Items; OnClick := TcxSchedulerContentPopupMenu(Source).OnClick; OnPopup := TcxSchedulerContentPopupMenu(Source).OnPopup; end; end; procedure TcxSchedulerContentPopupMenu.Execute( AItem: TcxSchedulerContentPopupMenuItem); begin ExecuteCommand(Ord(AItem)); end; function TcxSchedulerContentPopupMenu.GetMenuItem( AItem: TcxSchedulerContentPopupMenuItem): TMenuItem; begin Result := FindItemByCommand(Root, Ord(AItem)); end; procedure TcxSchedulerContentPopupMenu.CreateItems; begin CreateNewEventItems(cpmiNewEvent in FItems, cpmiNewAllDayEvent in FItems, cpmiNewReccuringEvent in FItems, Ord(cpmiNewEvent), Ord(cpmiNewAllDayEvent), Ord(cpmiNewReccuringEvent)); CreateGoToThisDayItem; if cpmiToday in FItems then CreateSubItem(Root, cxGetResourceString(@scxpmToday), Ord(cpmiToday)); if cpmiGoToDate in FItems then CreateSubItem(Root, cxGetResourceString(@scxpmGoToDate), Ord(cpmiGoToDate)); if (cpmiResourcesLayout in FItems) and Scheduler.CurrentView.IsShowResources then begin AddValidSeparator(Root); CreateSubItem(Root, cxGetResourceString(@scxpmResourcesLayout), Ord(cpmiResourcesLayout)); end; end; procedure TcxSchedulerContentPopupMenu.DoExecute(ACommand: Integer); var ADate: TDateTime; AViewMode: TcxSchedulerViewMode; begin case ACommand of Ord(cpmiNewEvent), Ord(cpmiNewAllDayEvent), Ord(cpmiNewReccuringEvent): inherited DoExecute(ACommand); Ord(cpmiResourcesLayout): cxShowResourcesLayoutEditor(Scheduler.Storage, Scheduler.LookAndFeel); Ord(cpmiGoToThisDay): Scheduler.GoToDate(FSavedDate); Ord(cpmiToday): Scheduler.GoToDate(Date); Ord(cpmiGoToDate): begin if Scheduler.SelectedDays.Count > 0 then ADate := Scheduler.SelectedDays[0] else ADate := Date; if cxShowGoToDateDialog(Scheduler, Scheduler.LookAndFeel, ADate, AViewMode) then Scheduler.GoToDate(ADate, AViewMode); end; end; end; function TcxSchedulerContentPopupMenu.DoOnClick(ACommand: Integer): Boolean; begin Result := False; if Assigned(FOnClick) then FOnClick(Self, TcxSchedulerContentPopupMenuItem(ACommand), Result); end; function TcxSchedulerContentPopupMenu.DoOnPopup: Boolean; begin Result := False; if Assigned(FOnPopup) then FOnPopup(Self, InternalMenu, Result); end; function TcxSchedulerContentPopupMenu.IsValidCommand( ACommand: Integer): Boolean; begin Result := (ACommand >= Ord(cpmiNewEvent)) and (ACommand <= Ord(cpmiResourcesLayout)); end; procedure TcxSchedulerContentPopupMenu.CreateGoToThisDayItem; var AItem: TMenuItem; begin if (cpmiGoToThisDay in FItems) and not Scheduler.CurrentView.IsDayView then begin AItem := CreateSubItem(Root, cxGetResourceString(@scxpmGotoThisDay), Ord(cpmiGoToThisDay)); AItem.Enabled := Scheduler.ActiveHitTest.HitAtTime; if AItem.Enabled then FSavedDate := Scheduler.ActiveHitTest.Time; end; end; { TcxSchedulerEventPopupMenu } constructor TcxSchedulerEventPopupMenu.Create( AScheduler: TcxCustomScheduler); begin inherited Create(AScheduler); FItems := [epmiOpen, epmiEditSeries, epmiShowTimeAs, epmiLabel, epmiDelete]; end; procedure TcxSchedulerEventPopupMenu.Assign(Source: TPersistent); begin inherited Assign(Source); if Source is TcxSchedulerEventPopupMenu then begin Items := TcxSchedulerEventPopupMenu(Source).Items; OnClick := TcxSchedulerEventPopupMenu(Source).OnClick; OnPopup := TcxSchedulerEventPopupMenu(Source).OnPopup; end; end; procedure TcxSchedulerEventPopupMenu.CreateItems; function GetEditEnabled: Boolean; begin Result := (Event <> nil) and Scheduler.CanShowEventDialog; end; begin FEvent := GetEvent; if epmiOpen in Items then CreateSubItem(Root, cxGetResourceString(@scxpmOpen), Ord(epmiOpen)).Enabled := GetEditEnabled; if (epmiEditSeries in Items) and (Event <> nil) and (Event.EventType <> etNone) then CreateSubItem(Root, cxGetResourceString(@scxpmEditSeries), Ord(epmiEditSeries), 8).Enabled := GetEditEnabled; if Items * [epmiLabel, epmiShowTimeAs] <> [] then AddValidSeparator(Root); CreateTimeItems; CreateLabelItems; CreateDeleteItem; end; procedure TcxSchedulerEventPopupMenu.DoExecute(ACommand: Integer); begin case ACommand of Ord(epmiOpen): Scheduler.EditEventUsingDialog(Event); Ord(epmiEditSeries): Scheduler.EditEventUsingDialog(Event, True, True); Ord(epmiDelete): Scheduler.InternalDeleteSelectedEvents(False, True); 10..13: SetEventState(ACommand - 10); 20..30: SetEventLabelColor(EventLabelColors[ACommand - 20]); end; end; function TcxSchedulerEventPopupMenu.DoOnClick(ACommand: Integer): Boolean; var AItem: TcxSchedulerEventPopupMenuItem; ASubItemIndex: Integer; begin Result := False; UnpackCommand(ACommand, AItem, ASubItemIndex); if Assigned(FOnClick) then FOnClick(Self, AItem, ASubItemIndex, Result); end; function TcxSchedulerEventPopupMenu.DoOnPopup: Boolean; begin Result := False; if Assigned(FOnPopup) then FOnPopup(Self, InternalMenu, Result); end; function TcxSchedulerEventPopupMenu.GetMenuItem( AItem: TcxSchedulerEventPopupMenuItem; ASubItemIndex: Integer = -1): TMenuItem; begin Result := FindItemByCommand(Root, Ord(AItem)); if Result <> nil then begin if (AItem = epmiLabel) and (ASubItemIndex in [0..10]) then Result := FindItemByCommand(Result, ASubItemIndex + 20) else if (AItem = epmiShowTimeAs) and (ASubItemIndex in [0..3]) then Result := FindItemByCommand(Result, ASubItemIndex + 10) end; end; function TcxSchedulerEventPopupMenu.IsValidCommand( ACommand: Integer): Boolean; begin Result := (ACommand >= Ord(epmiOpen)) and (ACommand <= Ord(epmiDelete)) or (ACommand in [20..30]) or //Label (ACommand in [10..13]); //TimeLine end; procedure TcxSchedulerEventPopupMenu.SetEventLabelColor(AColor: Integer); begin if Event = nil then Exit; if Event.EventType = etOccurrence then Event.Pattern.LabelColor := AColor else Event.Source.LabelColor := AColor; end; procedure TcxSchedulerEventPopupMenu.SetEventState(AState: Integer); begin if Event = nil then Exit; Event.State := AState; Scheduler.EventList.PostEvent(Event); end; procedure TcxSchedulerEventPopupMenu.CreateDeleteItem; function CanDelete: Boolean; var I: Integer; begin with Scheduler do begin Result := EventOperations.Deleting; if Result then begin for I := 0 to SelectedEventCount - 1 do if not SelectedEvents[I].ReadOnly then Exit; Result := False; end; end; end; begin if epmiDelete in Items then begin AddValidSeparator(Root); CreateSubItem(Root, cxGetResourceString(@scxpmDelete), Ord(epmiDelete), 10).Enabled := CanDelete; end; end; procedure TcxSchedulerEventPopupMenu.CreateLabelItems; var AOwner: TMenuItem; I: Integer; function GetColorChecked(AIndex: Integer): Boolean; begin if Event = nil then Result := False else Result := Event.LabelColor = EventLabelColors[AIndex]; end; procedure CreateEventColorItem(const ACaption: string; AIndex: Integer); var AChecked: Boolean; begin AChecked := GetColorChecked(AIndex); CreateSubItem(AOwner, ACaption, GetCommand(epmiLabel, AIndex), AIndex + 11, CanEdit, AChecked).Default := AChecked; end; begin if not (epmiLabel in Items) or not Scheduler.StorageActive or not Storage.IsLabelColorAvailable then Exit; AOwner := CreateSubItem(Root, cxGetResourceString(@scxpmLabel), Ord(epmiLabel)); //label colors CreateEventColorItem(cxGetResourceString(@scxEventLabelNone), 0); CreateSeparator(AOwner); for I := 1 to 10 do CreateEventColorItem(cxGetResourceString(sEventLabelCaptions[I]), I); end; procedure TcxSchedulerEventPopupMenu.CreateTimeItems; var AOwner: TMenuItem; function GetTimeLineChecked(AIndex: Integer): Boolean; begin if Event = nil then Result := False else Result := Integer(Event.State) = AIndex; end; procedure CreateTimeLineItem(const ACaption: string; AIndex: Integer); var AChecked: Boolean; begin AChecked := GetTimeLineChecked(AIndex); CreateSubItem(AOwner, ACaption, GetCommand(epmiShowTimeAs, AIndex), AIndex, CanEdit, AChecked).Default := AChecked; end; begin if not (epmiShowTimeAs in Items) or not Scheduler.StorageActive or not Storage.IsStateAvailable then Exit; AOwner := CreateSubItem(Root, cxGetResourceString(@scxpmShowTimeAs), Ord(epmiShowTimeAs)); AOwner.SubMenuImages := TimeLinePatterns; // TimeLine styles CreateTimeLineItem(cxGetResourceString(@scxpmFree), 0); CreateTimeLineItem(cxGetResourceString(@scxpmTentative), 1); CreateTimeLineItem(cxGetResourceString(@scxpmBusy), 2); CreateTimeLineItem(cxGetResourceString(@scxpmOutOfOffice), 3); end; function TcxSchedulerEventPopupMenu.GetCommand( AItem: TcxSchedulerEventPopupMenuItem; ASubItemIndex: Integer): Integer; begin Result := Ord(AItem); case AItem of epmiShowTimeAs: if (ASubItemIndex >= 0) and (ASubItemIndex <= 3) then Result := 10 + ASubItemIndex; epmiLabel: if (ASubItemIndex >= 0) and (ASubItemIndex <= 10) then Result := 20 + ASubItemIndex; end; end; function TcxSchedulerEventPopupMenu.CanEdit: Boolean; begin Result := (Event <> nil) and not Event.ReadOnly; end; function TcxSchedulerEventPopupMenu.GetEvent: TcxSchedulerControlEvent; begin with Scheduler.EventList.Selection do begin if Count = 1 then Result := Items[0] else Result := nil; end; end; procedure TcxSchedulerEventPopupMenu.UnpackCommand(ACommand: Integer; out AItem: TcxSchedulerEventPopupMenuItem; out ASubItemIndex: Integer); begin AItem := epmiOpen; ASubItemIndex := -1; if not IsValidCommand(ACommand) then Exit; if ACommand in [20..30] then begin AItem := epmiLabel; ASubItemIndex := ACommand - 20; end else if ACommand in [10..13] then begin AItem := epmiShowTimeAs; ASubItemIndex := ACommand - 10; end else AItem := TcxSchedulerEventPopupMenuItem(ACommand); end; { TcxSchedulerEditController } constructor TcxSchedulerEditController.Create(AOwner: TcxCustomScheduler); begin FOwner := AOwner; FEditList := TcxInplaceEditList.Create(AOwner); end; destructor TcxSchedulerEditController.Destroy; begin CloseEdit(False); FEditList.Free; inherited Destroy; end; procedure TcxSchedulerEditController.Activate( AEvent: TcxSchedulerControlEvent); begin if InitEdit(AEvent) then FEdit.Activate(FEditData); end; procedure TcxSchedulerEditController.Activate( AEvent: TcxSchedulerControlEvent; const APos: TPoint; AShift: TShiftState); begin if InitEdit(AEvent) then FEdit.ActivateByMouse(AShift, APos.X, APos.Y, FEditData); end; procedure TcxSchedulerEditController.Activate( AEvent: TcxSchedulerControlEvent; Key: Char); begin if InitEdit(AEvent) then FEdit.ActivateByKey(Key, FEditData); end; procedure TcxSchedulerEditController.CloseEdit(Accepted: Boolean); function IsDataRefreshing: Boolean; begin Result := Scheduler.FLockRefresh > 0; end; begin if not IsEditing then Exit; FIsEditing := False; FFocused := False; try if not IsDataRefreshing then if Accepted and CanAccept then begin if not FEdit.Deactivate then raise EAbort.Create(''); UpdateValue; Scheduler.EventList.PostEvent(Event); Scheduler.SetFocus; end else begin if FIsNewEvent then begin Event.Source.Delete; FEvent := nil; end; Scheduler.FullRefresh; end; finally FEdit.Parent := nil; FEdit := nil; FreeAndNil(FEditData); Scheduler.DoAfterEditing(Event); FIsNewEvent := False; FEvent := nil; if not IsDataRefreshing then Scheduler.CurrentView.Refresh; end; end; procedure TcxSchedulerEditController.Init(const AEditDate: TDateTime; AResource: TcxSchedulerStorageResourceItem; AIsNewEvent: Boolean = False); begin FEditDate := DateOf(AEditDate); FEditResource := AResource; FIsNewEvent := AIsNewEvent; end; procedure TcxSchedulerEditController.UpdateEdit; var R: TRect; begin if not IsEditing then Exit; if GetEditRect(R, FEditDate, FEditResource) then begin FEdit.BoundsRect := R; FEdit.Visible := True; end else FEdit.Visible := False; FEdit.EditValue := FEvent.Caption; end; procedure TcxSchedulerEditController.UpdateValue; begin if (FEdit <> nil) and FEdit.EditModified then begin FEdit.ValidateEdit(True); FEvent.Caption := FEdit.EditValue; end; end; function TcxSchedulerEditController.GetEditRect(var R: TRect; const ADate: TDateTime; AResource: TcxSchedulerStorageResourceItem; AMakeVisible: Boolean = False): Boolean; begin Scheduler.MakeEventVisible(Event, ADate, AResource); with Scheduler.CurrentView do R := cxRectOffset(GetEditRectForEvent(Event, ADate, AResource), Bounds.TopLeft); Result := not cxRectIsEmpty(R); end; procedure TcxSchedulerEditController.EditAfterKeyDown( Sender: TObject; var Key: Word; Shift: TShiftState); begin if IsKeyForControl(Key, Shift) then begin Scheduler.SetFocus; CloseEdit(True); end; end; procedure TcxSchedulerEditController.EditExit(Sender: TObject); begin if IsEditing then CloseEdit(True); end; procedure TcxSchedulerEditController.EditKeyDown( Sender: TObject; var Key: Word; Shift: TShiftState); begin if IsKeyForControl(Key, Shift) then begin CloseEdit(Key <> VK_ESCAPE); Scheduler.SetFocus; end; if Assigned(Scheduler.OnKeyDown) then Scheduler.OnKeyDown(Scheduler, Key, Shift); end; procedure TcxSchedulerEditController.EditKeyPress( Sender: TObject; var Key: Char); begin if Assigned(Scheduler.OnKeyPress) then Scheduler.OnKeyPress(Scheduler, Key); end; procedure TcxSchedulerEditController.EditKeyUp( Sender: TObject; var Key: Word; Shift: TShiftState); begin if Assigned(Scheduler.OnKeyUp) then Scheduler.OnKeyUp(Scheduler, Key, Shift); end; procedure TcxSchedulerEditController.EditPostEditValue(Sender: TObject); begin UpdateValue; end; function TcxSchedulerEditController.InitEdit( AEvent: TcxSchedulerControlEvent): Boolean; var R: TRect; begin Result := False; if AEvent = nil then Exit; if IsEditing then begin if FEvent = AEvent then begin UpdateValue; UpdateEdit; end else CloseEdit(True); Exit; end; FIsEditing := False; FEvent := AEvent; Controller.SelectSingleEvent(AEvent, NullDate, False); if not (Scheduler.DoBeforeEditing(AEvent, True) and GetEditRect(R, FEditDate, FEditResource, True)) then Exit; Scheduler.DoGetEventEditProperties(Event, FEditProperties); FEdit := FEditList.GetEdit(EditProperties); Result := FEdit <> nil; if not Result then Exit; FIsEditing := True; PrepareEdit(FEdit); if FIsEditing then Scheduler.CurrentView.Refresh; end; function TcxSchedulerEditController.IsKeyForControl( var AKey: Word; Shift: TShiftState): Boolean; begin Result := (AKey = VK_TAB) or (AKey = VK_ESCAPE) or (AKey = VK_RETURN); end; procedure TcxSchedulerEditController.PrepareEdit(AEdit: TcxCustomEdit); var R: TRect; AParams: TcxViewParams; begin FFocused := True; FEdit.Visible := GetEditRect(R, FEditDate, FEditResource); FEdit.BoundsRect := R; FEdit.Parent := Scheduler; FEdit.EditValue := FEvent.Caption; with TcxCustomEditAccess(FEdit) do begin OnAfterKeyDown := EditAfterKeyDown; OnExit := EditExit; OnKeyDown := EditKeyDown; OnKeyPress := EditKeyPress; OnKeyUp := EditKeyUp; OnPostEditValue := EditPostEditValue; AParams := Scheduler.Styles.GetEventContentParams(Event); Color := AParams.Color; Font := AParams.Font; Font.Color := AParams.TextColor; end; Scheduler.DoInitEdit(FEdit); end; function TcxSchedulerEditController.CanAccept: Boolean; begin Result := not Scheduler.IsDestroying and (FEdit.EditModified or FIsNewEvent); end; function TcxSchedulerEditController.GetController: TcxSchedulerViewController; begin Result := View.Controller; end; function TcxSchedulerEditController.GetEditVisible: Boolean; begin Result := IsEditing and FEdit.Visible; end; function TcxSchedulerEditController.GetView: TcxSchedulerCustomView; begin Result := Scheduler.CurrentView; end; procedure TcxSchedulerEditController.SetEditVisible(Value: Boolean); begin if not IsEditing then Exit; if Value <> EditVisible then begin FEdit.Visible := Value; UpdateEdit; end; end; { TcxCustomScheduler } constructor TcxCustomScheduler.Create(AOwner: TComponent); begin inherited Create(AOwner); Color := clBtnFace; ParentFont := False; Font.Name := 'Tahoma'; Keys := [kAll, kArrows, kChars, kTab]; BeginUpdate; SetBounds(0, 0, cxDefaultSchedulerWidth, cxDefaultSchedulerHeight); FSubControls := TList.Create; {$IFNDEF DEBUGPAINT} FBitmap := TBitmap.Create; FBitmap.PixelFormat := pf24Bit; FBitmapCanvas := TcxCanvas.Create(FBitmap.Canvas); {$ENDIF} CreateSubClasses; FBackground := CreateBackground; FSubControlsCreated := True; BorderStyle := cxcbsDefault; EndUpdate; DragMode := dmAutomatic; cxFormatController.AddListener(Self); end; destructor TcxCustomScheduler.Destroy; begin cxFormatController.RemoveListener(Self); FSubControlsCreated := False; Storage := nil; DestroySubClasses; while SubControlCount > 0 do SubControls[0].Free; FSubControls.Free; {$IFNDEF DEBUGPAINT} FBitmapCanvas.Free; FBitmap.Free; {$ENDIF} inherited Destroy; end; procedure TcxCustomScheduler.BeginUpdate; begin Inc(FLockCount); Include(FControlFlags, cfLocked); LockUpdateChanged(True); end; procedure TcxCustomScheduler.CreateEventUsingDialog(AllDay: Boolean = False; ARecurrence: Boolean = False); var AModified: Boolean; AEvent: TcxSchedulerControlEvent; begin if not StorageActive then Exit; AEvent := TcxSchedulerControlEvent.Create(Storage); EditController.FFocused := True; try InitEventBySelection(AEvent, AllDay, ARecurrence, False); if DoBeforeEditing(AEvent, False) then begin if cxShowEventEditor(AEvent, LookAndFeel, ARecurrence, AModified, False, False, EventOperations.Recurrence, nil, ARecurrence, GetTimeBias) then DoAfterEditing(nil); end finally AEvent.Free; EditController.FFocused := False; end; end; procedure TcxCustomScheduler.CreateEventUsingInplaceEdit; begin DoCreateEventUsingInplaceEdit; end; procedure TcxCustomScheduler.DeleteEvent(AEvent: TcxSchedulerControlEvent); begin if not StorageActive or (AEvent = nil) or not EventOperations.Deleting or AEvent.ReadOnly then Exit; InternalDeleteEvent(AEvent, False); end; procedure TcxCustomScheduler.DeleteSelectedEvents( ACheckReadOnly: Boolean = True); begin if StorageActive then InternalDeleteSelectedEvents(True, ACheckReadOnly); end; procedure TcxCustomScheduler.EditEventUsingDialog( AEvent: TcxSchedulerControlEvent; ACheckReadOnly: Boolean = True; AForcePatternEditing: Boolean = False); var AReadOnly, AModified: Boolean; begin if (AEvent = nil) or not StorageActive or (cxEventEditorClass = nil) or not DoBeforeEditing(AEvent, False) then Exit; AReadOnly := ACheckReadOnly and (not CurrentView.Controller.CanEditEvent(AEvent, False) or AEvent.ReadOnly); EditController.FFocused := True; try if cxShowEventEditor(AEvent, LookAndFeel, False, AModified, AReadOnly, EventOperations.Deleting, EventOperations.Recurrence, DoBeforeDeleting, AForcePatternEditing, GetTimeBias) and AModified then DoAfterEditing(AEvent); finally EditController.FFocused := False; end; end; procedure TcxCustomScheduler.EditEventUsingInplaceEdit( AEvent: TcxSchedulerControlEvent); begin if (AEvent = nil) or not StorageActive then Exit; if CanFocusEx then begin SetFocus; EditController.Activate(AEvent); end; end; procedure TcxCustomScheduler.DragDrop( Source: TObject; X, Y: Integer); begin inherited DragDrop(Source, X, Y); CaptureController.DragDrop(Source, X, Y); end; procedure TcxCustomScheduler.EndUpdate; begin LockUpdateChanged(False); Dec(FLockCount); if FLockCount = 0 then begin Exclude(FControlFlags, cfLocked); if cfInvalidLayout in FControlFlags then begin Exclude(FControlFlags, cfInvalidLayout); LayoutChanged; end; end; end; function TcxCustomScheduler.GoToDate(ADate: TDateTime; AViewMode: TcxSchedulerViewMode = vmDay): Boolean; begin if ADate = NullDate then Result := False else begin FSelectedDays.Clear; FSelectedDays.Add(ADate); CurrentView.PeriodChanged; Result := True; end; end; procedure TcxCustomScheduler.FullRefresh; begin Inc(FLockRefresh); try UpdateEventsCache(FLockRefresh <> 1); LayoutChanged; finally Dec(FLockRefresh); end; end; procedure TcxCustomScheduler.LayoutChanged; begin if IsLocked or IsLoading or IsDestroying or not HandleAllocated then Include(FControlFlags, cfInvalidLayout) else begin Exclude(FControlFlags, cfImageValid); if CurrentView.Visible and not CurrentView.CanShow then CurrentView.Visible := False; AlignSubControls; if not (cfViewValid in FControlFlags) then SynchronizeVisibleDays; DoLayoutChanged; Exclude(FControlFlags, cfInvalidLayout); UpdateScrollBars; end; if not FBoundsChanging and CanModified then Modified; Invalidate; end; procedure TcxCustomScheduler.MakeEventVisible( AEvent: TcxSchedulerControlEvent; const ADate: TDateTime = NullDate; AResource: TcxSchedulerStorageResourceItem = nil); begin CurrentView.MakeEventVisible(AEvent, ADate, AResource); end; procedure TcxCustomScheduler.SelectEvent( AEvent: TcxSchedulerControlEvent; AShift: TShiftState = []); begin EventList.Selection.Add(AEvent, AShift); if not IsLocked then CurrentView.Refresh; end; procedure TcxCustomScheduler.SelectTime(const ASelStart, ASelFinish: TDateTime; AResource: TcxSchedulerStorageResourceItem); begin if DateTimeHelper.RoundTime(Abs(ASelStart - ASelFinish)) <= CurrentView.GetTimeIncrement then ReplaceSelParams(ASelStart, ASelStart, AResource) else ReplaceSelParams(ASelStart, (ASelFinish - CurrentView.GetTimeIncrement), AResource); LayoutChanged; end; procedure TcxCustomScheduler.UnselectEvents; begin if EventList.Selection.Count = 0 then Exit; EventList.Selection.Clear; CurrentView.LayoutChanged; end; procedure TcxCustomScheduler.RestoreFromIniFile(const AStorageName: string; ARestoreResources: Boolean = True); var AStorage: TcxStorage; begin AStorage := TcxStorage.Create(AStorageName); try BeginUpdate; try AStorage.RestoreFromIni(Self); if ARestoreResources and HasResources then AStorage.RestoreFromIni(Storage.Resources); finally EndUpdate; end; finally AStorage.Free; end; end; procedure TcxCustomScheduler.RestoreFromRegistry(const AStorageName: string; ARestoreResources: Boolean = True); var AStorage: TcxStorage; begin AStorage := TcxStorage.Create(AStorageName); try BeginUpdate; try AStorage.RestoreFromRegistry(Self); if ARestoreResources and HasResources then AStorage.RestoreFromRegistry(Storage.Resources); finally EndUpdate; end; finally AStorage.Free; end; end; procedure TcxCustomScheduler.RestoreFromStream(AStream: TStream; ARestoreResources: Boolean = True); var AStorage: TcxStorage; begin AStorage := TcxStorage.Create(AStream); try BeginUpdate; try AStorage.RestoreFromStream(Self); if ARestoreResources and HasResources then AStorage.RestoreFromStream(Storage.Resources); finally EndUpdate; end; finally AStorage.Free; end; end; procedure TcxCustomScheduler.StoreToIniFile(const AStorageName: string; AReCreate: Boolean = True; AStoreResources: Boolean = True); var AStorage: TcxStorage; begin AStorage := TcxStorage.Create(AStorageName); try BeginUpdate; try AStorage.ReCreate := ARecreate; AStorage.StoreToIni(Self); AStorage.ReCreate := False; if AStoreResources and HasResources then AStorage.StoreToIni(Storage.Resources); finally EndUpdate; end; finally AStorage.Free; end; end; procedure TcxCustomScheduler.StoreToRegistry(const AStorageName: string; AReCreate: Boolean = True; AStoreResources: Boolean = True); var AStorage: TcxStorage; begin AStorage := TcxStorage.Create(AStorageName); try BeginUpdate; try AStorage.ReCreate := ARecreate; AStorage.StoreToRegistry(Self); AStorage.ReCreate := False; if AStoreResources and HasResources then AStorage.StoreToRegistry(Storage.Resources); finally EndUpdate; end; finally AStorage.Free; end; end; procedure TcxCustomScheduler.StoreToStream(AStream: TStream; AStoreResources: Boolean = True); var AStorage: TcxStorage; begin AStorage := TcxStorage.Create(AStream); try BeginUpdate; try AStorage.StoreToStream(Self); AStorage.ReCreate := False; if AStoreResources and HasResources then AStorage.StoreToStream(Storage.Resources); finally EndUpdate; end; finally AStorage.Free; end; end; procedure TcxCustomScheduler.AlignControls(AControl: TControl; var Rect: TRect); begin end; procedure TcxCustomScheduler.DefineProperties(Filer: TFiler); begin inherited DefineProperties(Filer); Filer.DefineBinaryProperty('Splitters', ReadSplittersData, WriteSplittersData, True); Filer.DefineProperty('Selection', ReadSelectionData, WriteSelectionData, (FSelectedDays.Count > 1) or (SelectedDays[0] <> Date)); end; procedure TcxCustomScheduler.GetChildren( Proc: TGetChildProc; Root: TComponent); begin inherited GetChildren(Proc, Root); if ControlBox.Control <> nil then Proc(ControlBox.Control); end; procedure TcxCustomScheduler.Notification( AComponent: TComponent; Operation: TOperation); var I: Integer; begin inherited Notification(AComponent, Operation); if not IsDestroying and FSubControlsCreated then begin if Operation = opRemove then begin if AComponent = ControlBox.Control then ControlBox.Control := nil; if AComponent = ContentPopupMenu.PopupMenu then ContentPopupMenu.PopupMenu := nil; if AComponent = EventPopupMenu.PopupMenu then EventPopupMenu.PopupMenu := nil; end; for I := 0 to SubControlCount - 1 do SubControls[I].Notification(AComponent, Operation); end; end; procedure TcxCustomScheduler.AlignSubControls( Sender: TcxSchedulerSubControl = nil); begin if FAligningSubControls or IsLoading or not FSubControlsCreated then Exit; FAligningSubControls := True; try CheckSplittersVisibilityChanging; if (Sender = DateNavigator) or (Sender = ControlBox) then UpdateAlignByDateNavigatorOrControlBox(Sender = DateNavigator) else if Sender = CurrentView then UpdateAlignByView else begin if DateNavigator.Visible then UpdateAlignByDateNavigatorOrControlBox(True) else if ControlBox.Visible then UpdateAlignByDateNavigatorOrControlBox(False) else UpdateAlignByView; end; FullRefresh; finally FAligningSubControls := False; end; end; procedure TcxCustomScheduler.BoundsChanged; begin FBoundsChanging := True; Include(FControlFlags, cfLocked); try {$IFNDEF DEBUGPAINT} if ((FBitmap.Width < Width) or ((FBitmap.Width - Width) > cxSizeDelta)) or ((FBitmap.Height < Height) or ((FBitmap.Height - Height) > cxSizeDelta)) then begin FBitmap.Width := (Width div cxSizeDelta + 1) * cxSizeDelta; FBitmap.Height := (Height div cxSizeDelta + 1) * cxSizeDelta; end; {$ENDIF} if not (IsLoading or IsDestroying) and EditController.IsEditing then CurrentView.Controller.CloseInplaceEdit; inherited BoundsChanged; AlignSubControls; UpdateInvisibleSplitterBounds; FPrevBounds := ClientBounds; finally Exclude(FControlFlags, cfLocked); LayoutChanged; FBoundsChanging := False; end; end; function TcxCustomScheduler.CanShowEventDialog: Boolean; begin Result := CurrentView.Controller.CanShowEventDialog; end; function TcxCustomScheduler.CanModified: Boolean; begin Result := FCanModified; end; function TcxCustomScheduler.CreateBackground: TcxSchedulerSubControl; begin Result := TcxSchedulerSubControl.Create(Self); end; function TcxCustomScheduler.CreateContentPopupMenu: TcxSchedulerContentPopupMenu; begin Result := TcxSchedulerContentPopupMenu.Create(Self); end; function TcxCustomScheduler.CreateControlBox: TcxSchedulerControlBox; begin Result := TcxSchedulerControlBox.Create(Self) end; function TcxCustomScheduler.CreateDateNavigator: TcxSchedulerCustomDateNavigator; begin Result := nil; end; function TcxCustomScheduler.CreateDefaultView: TcxSchedulerCustomView; begin Result := nil; end; function TcxCustomScheduler.CreateDefaultEditProperties: TcxCustomEditProperties; begin Result := TcxMemoProperties.Create(Self); end; function TcxCustomScheduler.CreateEditController: TcxSchedulerEditController; begin Result := TcxSchedulerEditController.Create(Self); end; function TcxCustomScheduler.CreateEventHitTestController: TcxSchedulerEventHitTestController; begin Result := TcxSchedulerEventHitTestController.Create(Self); end; function TcxCustomScheduler.CreateEventList: TcxSchedulerCachedEventList; begin Result := TcxSchedulerCachedEventList.Create; Result.Selection.OnEventSelectionChanged := DoEventSelectionChanged; end; function TcxCustomScheduler.CreateEventOperations: TcxSchedulerEventOperations; begin Result := TcxSchedulerEventOperations.Create(Self); end; function TcxCustomScheduler.CreateEventPopupMenu: TcxSchedulerEventPopupMenu; begin Result := TcxSchedulerEventPopupMenu.Create(Self); end; function TcxCustomScheduler.CreateHintController: TcxSchedulerHintController; begin Result := TcxSchedulerHintController.Create(Self); end; function TcxCustomScheduler.CreateOptionsCustomize: TcxSchedulerOptionsCustomize; begin Result := TcxSchedulerOptionsCustomize.Create(Self); end; function TcxCustomScheduler.CreateOptionsView: TcxSchedulerOptionsView; begin Result := TcxSchedulerOptionsView.Create(Self); end; function TcxCustomScheduler.CreateSplitter( AKind: TcxSchedulerSplitterKind): TcxSchedulerSplitter; begin Result := TcxSchedulerSplitter.Create(Self); Result.SetKind(AKind); end; function TcxCustomScheduler.CreateStyles: TcxSchedulerStyles; begin Result := TcxSchedulerStyles.Create(Self); end; procedure TcxCustomScheduler.CreateSubClasses; begin FTextEditProperties := TcxTextEditProperties.Create(Self); FEventHitTestController := CreateEventHitTestController; FHintController := CreateHintController; FEditController := CreateEditController; FEditStyle := TcxCustomEditStyle.Create(Self, True); FDefaultProperties := TcxMemoProperties.Create(Self); FEventList := CreateEventList; FEventDays := TcxSchedulerDateList.Create; FSelectedDays := TcxSchedulerDateList.Create; FSelectedDays.Add(Date); FStyles := CreateStyles; FEventOperations := CreateEventOperations; FOptionsCustomize := CreateOptionsCustomize; FOptionsView := CreateOptionsView; // subcontrols FControlBox := CreateControlBox; FDateNavigator := CreateDateNavigator; // this order FVertSplitter := CreateSplitter(skVertical); FHorzSplitter := CreateSplitter(skHorizontal); // view FCurrentView := CreateDefaultView; FCurrentView.Visible := True; // popups FContentPopupMenu := CreateContentPopupMenu; FEventPopupMenu := CreateEventPopupMenu; CreateUpdateTimeTimer; end; procedure TcxCustomScheduler.DateNavigatorSelectionChanged; begin if not (cfViewValid in FControlFlags) then Exit; Exclude(FControlFlags, cfViewValid); PeriodChanged; end; procedure TcxCustomScheduler.DblClick; var P: TPoint; begin P := ScreenToClient(GetMouseCursorPos); if FActiveControl <> nil then FActiveControl.MousePositionChanged(P.X, P.Y); inherited DblClick; end; procedure TcxCustomScheduler.DestroySubClasses; begin FEditController.Free; FEventHitTestController.Free; FUpdateTimeTimer.Free; FContentPopupMenu.Free; FEventPopupMenu.Free; FEventOperations.Free; FEventList.Free; FEventDays.Free; FOptionsCustomize.Free; FOptionsView.Free; FStyles.Free; FSelectedDays.Free; FEditStyle.Free; FDefaultProperties.Free; FTextEditProperties.Free; FHintController.Free; end; procedure TcxCustomScheduler.DoAfterDragEvent(Target: TObject; X, Y: Integer; var Accept: Boolean); begin if Assigned(FOnAfterDragEvent) then FOnAfterDragEvent(Self, Target, X, Y, Accept); end; procedure TcxCustomScheduler.DoAfterEditing(AEvent: TcxSchedulerControlEvent); begin if Assigned(FOnAfterEditing) then FOnAfterEditing(Self, AEvent); end; procedure TcxCustomScheduler.DoAfterSizingEvent(X, Y: Integer; var Accept: Boolean); begin if Assigned(FOnAfterSizingEvent) then FOnAfterSizingEvent(Self, X, Y, Accept); end; function TcxCustomScheduler.DoBeforeDeleting( AEvent: TcxSchedulerControlEvent): Boolean; begin Result := True; if Assigned(FOnBeforeDeleting) then FOnBeforeDeleting(Self, AEvent, Result); end; function TcxCustomScheduler.DoBeforeDragEvent( AEvent: TcxSchedulerControlEvent; X, Y: Integer): Boolean; begin Result := True; if Assigned(FOnBeforeDragEvent) then FOnBeforeDragEvent(Self, AEvent, X, Y, Result); end; function TcxCustomScheduler.DoBeforeEditing( AEvent: TcxSchedulerControlEvent; AInplace: Boolean): Boolean; begin Result := True; if Assigned(FOnBeforeEditing) then FOnBeforeEditing(Self, AEvent, AInplace, Result); end; function TcxCustomScheduler.DoBeforeSizingEvent( AEvent: TcxSchedulerControlEvent; X, Y: Integer): Boolean; begin Result := True; if Assigned(FOnBeforeSizingEvent) then FOnBeforeSizingEvent(Self, AEvent, X, Y, Result); end; procedure TcxCustomScheduler.DoCalculateLayout( AControl: TcxSchedulerSubControl); begin AControl.LayoutChanged; end; procedure TcxCustomScheduler.DoCancelMode; begin if FCaptureControl <> nil then FCaptureControl.Controller.DoCancelMode; FCaptureControl := nil; end; procedure TcxCustomScheduler.DoControllerReset( AControl: TcxSchedulerSubControl); begin AControl.Controller.Reset; end; procedure TcxCustomScheduler.DoCreateEventUsingInplaceEdit( AKey: Char = #0); var I: Integer; AEvent: TcxSchedulerEvent; AControlEvent: TcxSchedulerControlEvent; begin if not StorageActive then Exit; AEvent := Storage.CreateEvent; InitEventBySelection(AEvent, False, False, True); AEvent.MoveTo(AEvent.Start + GetTimeBias); AEvent.Post; for I := 0 to EventList.Count - 1 do begin AControlEvent := EventList[I]; if AControlEvent.Source = AEvent then begin EditController.Init(SelStart, SelResource, True); if AKey = #0 then EditController.Activate(AControlEvent) else EditController.Activate(AControlEvent, AKey); if not EditController.IsEditing then AEvent.Delete; Exit; end; end; end; procedure TcxCustomScheduler.DoEventSelectionChanged( AEvent: TcxSchedulerControlEvent); begin if Assigned(FOnEventSelectionChanged) then FOnEventSelectionChanged(Self, AEvent); end; procedure TcxCustomScheduler.DoGetEventDisplayText( AEvent: TcxSchedulerControlEvent; var AText: string); begin AText := AEvent.Caption; if Assigned(FOnGetEventDisplayText) then FOnGetEventDisplayText(Self, AEvent, AText); end; procedure TcxCustomScheduler.DoGetEventEditProperties( AEvent: TcxSchedulerControlEvent; var AProperties: TcxCustomEditProperties); begin if not CurrentView.IsDayView or (AEvent.Duration >= 1) or AEvent.AllDayEvent then AProperties := FTextEditProperties else AProperties := DefaultProperties; if Assigned(OnGetEventEditProperties) then begin OnGetEventEditProperties(Self, AEvent, AProperties); if AProperties = nil then AProperties := DefaultProperties; end; end; procedure TcxCustomScheduler.DoHitTestRecalculate( AControl: TcxSchedulerSubControl); begin AControl.Controller.HitTest.Recalculate; end; procedure TcxCustomScheduler.DoInitEdit(AEdit: TcxCustomEdit); begin if Assigned(FOnInitEdit) then FOnInitEdit(Self, AEdit); end; function TcxCustomScheduler.DoIsWorkTime( AResourceItem: TcxSchedulerStorageResourceItem; const ADateTime: TDateTime): Boolean; begin Result := OptionsView.IsWorkTime(ADateTime); if Assigned(FOnIsWorkTime) then FOnIsWorkTime(Self, AResourceItem, ADateTime, Result); end; procedure TcxCustomScheduler.DoLayoutChanged; var I: Integer; begin FCanvas := GetControlCanvas; for I := 0 to FSubControls.Count - 1 do SubControls[I].LayoutChanged; UpdateScrollBars; DoLayoutChangedEvent; end; procedure TcxCustomScheduler.DoLayoutChangedEvent; begin if Assigned(FOnLayoutChanged) then FOnLayoutChanged(Self); end; procedure TcxCustomScheduler.DoCanShowView( AView: TcxSchedulerCustomView; var Allow: Boolean); begin if Assigned(FOnCanShowView) then FOnCanShowView(Self, AView, Allow); end; procedure TcxCustomScheduler.DoSelectionChanged; begin if Assigned(FOnSelectionChanged) then FOnSelectionChanged(Self); end; function TcxCustomScheduler.DoShowPopupMenu(AMenu: TComponent; X, Y: Integer): Boolean; begin with CurrentView do Result := Visible and cxRectPtIn(Bounds, ScreenToClient(cxPoint(X, Y))) and DoShowPopupMenu(X, Y); if not Result then Result := inherited DoShowPopupMenu(AMenu, X, Y); end; procedure TcxCustomScheduler.DoViewTypeChanged( ANewView: TcxSchedulerCustomView); begin if Assigned(FOnViewTypeChanged) then FOnViewTypeChanged(Self, FCurrentView, ANewView); end; procedure TcxCustomScheduler.DoUpdateTime; begin if not FSubControlsCreated or not HandleAllocated then Exit; if CurrentView.Visible then CurrentView.DateChanged; if DateNavigator.Visible then DateNavigator.Refresh; end; procedure TcxCustomScheduler.DragCanceled; begin FIsDragCanceled := True; end; procedure TcxCustomScheduler.FontChanged; begin BeginUpdate; if not IsLoading and FSubControlsCreated then DateNavigator.SetIntegralSizes; inherited FontChanged; LayoutChanged; EndUpdate; end; function TcxCustomScheduler.GetClientBounds: TRect; begin Result := GetBounds; InflateRect(Result, -BorderSize, -BorderSize); end; procedure TcxCustomScheduler.FocusChanged; begin if OptionsView.HideSelection and not EditController.Focused then begin if (CurrentView <> nil) and CurrentView.Visible then CurrentView.Refresh; if DateNavigator.Visible then DateNavigator.Refresh; end; inherited FocusChanged; end; function TcxCustomScheduler.GetControlCanvas: TcxCanvas; begin {$IFDEF DEBUGPAINT} Result := inherited Canvas {$ELSE} Result := FBitmapCanvas; {$ENDIF} end; function TcxCustomScheduler.GetControlFromPoint( const APoint: TPoint): TcxSchedulerSubControl; var I: Integer; begin Result := Background; for I := 0 to SubControlCount - 1 do if SubControls[I].CanCapture(APoint) then begin Result := SubControls[I]; Break; end; end; function TcxCustomScheduler.GetCursor( X, Y: Integer): TCursor; begin Result := crDefault; if not IsDesigning then Result := GetControlFromPoint(cxPoint(X, Y)).Controller.GetCursor(X, Y); if Result = crDefault then Result := inherited GetCursor(X, Y); end; function TcxCustomScheduler.GetDateTimeHelper: TcxSchedulerDateTimeHelperClass; begin Result := cxSchedulerUtils.DateTimeHelper; end; function TcxCustomScheduler.GetDesignHitTest( X, Y: Integer; Shift: TShiftState): Boolean; begin Result := inherited GetDesignHitTest(X, Y, Shift); if not Result then begin Result := Capture.AllowDesignHitTest(X, Y, Shift); if not Result then Result := GetControlFromPoint(cxPoint(X, Y)).AllowDesignHitTest(X, Y, Shift); end; end; function TcxCustomScheduler.GetEventHintText( AEvent: TcxSchedulerControlEvent): string; begin Result := AEvent.Caption; with DateTimeHelper do Result := TimeToStr(AEvent.Start) + '-' + TimeToStr(AEvent.Finish) + ' ' + Result; if Assigned(FOnGetEventHintText) then FOnGetEventHintText(Self, AEvent, Result); end; function TcxCustomScheduler.GetHScrollBarBounds: TRect; begin Result := CurrentView.GetHScrollBarBounds; end; function TcxCustomScheduler.GetIsLocked: Boolean; begin Result := cfLocked in FControlFlags; end; function TcxCustomScheduler.GetNextView( AView: TcxSchedulerCustomView): TcxSchedulerCustomView; begin Result := AView; end; function TcxCustomScheduler.GetPainterHelper: TcxSchedulerPainterHelperClass; begin Result := TcxSchedulerPainterHelper; end; function TcxCustomScheduler.GetSizeGripBounds: TRect; begin Result := CurrentView.GetSizeGripBounds; end; function TcxCustomScheduler.GetTimeBias: Double; begin Result := 0; if StorageValid then begin with DateTimeHelper do begin Result := TimeZoneBias(CurrentTimeZone); if not Storage.StoreUsingGlobalTime then; Result := TimeZoneBias(OptionsView.CurrentTimeZone) - Result; end; end; end; function TcxCustomScheduler.GetVScrollBarBounds: TRect; begin Result := CurrentView.GetVScrollBarBounds; end; function TcxCustomScheduler.HasResources: Boolean; begin Result := (Storage <> nil) and (Storage.ResourceCount > 0); end; procedure TcxCustomScheduler.InitControl; begin inherited InitControl; if not IsLoading and OptionsCustomize.IntegralSizing then DateNavigator.SetIntegralSizes; end; procedure TcxCustomScheduler.InitScrollBarsParameters; begin CurrentView.InitScrollBarsParameters; end; procedure TcxCustomScheduler.InternalDeleteEvent(AEvent: TcxSchedulerControlEvent; AIgnoreRecurring: Boolean); var ADeleteOccurrence: Boolean; begin if not DoBeforeDeleting(AEvent) then Exit; if not AIgnoreRecurring and AEvent.IsRecurring then begin if cxShowRecurrenceSelectionDialog(AEvent, rsmDeleting, LookAndFeel, ADeleteOccurrence) then if ADeleteOccurrence then AEvent.Delete else AEvent.Pattern.Delete; end else AEvent.Delete; end; procedure TcxCustomScheduler.InternalDeleteSelectedEvents(AForceDelete, ACheckReadOnly: Boolean); var I, AIndex, ACount: Integer; AEvent: TcxSchedulerControlEvent; ASelectedIDs: array of Variant; procedure GetSelection; var I: Integer; begin SetLength(ASelectedIDs, SelectedEventCount); for I := 0 to SelectedEventCount - 1 do ASelectedIDs[I] := SelectedEvents[I].ID; end; function GetIndexOfID(const AID: Variant): Integer; begin for Result := 0 to High(ASelectedIDs) do if VarEquals(AID, ASelectedIDs[Result]) then Exit; Result := -1; end; procedure DeleteIDByIndex(AIndex: Integer); var I: Integer; begin for I := AIndex + 1 to High(ASelectedIDs) do ASelectedIDs[I - 1] := ASelectedIDs[I]; SetLength(ASelectedIDs, Length(ASelectedIDs) - 1); end; begin GetSelection; if AForceDelete then BeginUpdate; ACount := 0; try while ACount <> SelectedEventCount do begin ACount := SelectedEventCount; for I := 0 to ACount - 1 do begin AEvent := SelectedEvents[I]; AIndex := GetIndexOfID(AEvent.ID); if AIndex >= 0 then begin DeleteIDByIndex(AIndex); if not AForceDelete then DeleteEvent(AEvent) else if not (ACheckReadOnly and AEvent.ReadOnly) then InternalDeleteEvent(AEvent, True); if ACount <> SelectedEventCount then break; end; end; end; finally SetLength(ASelectedIDs, 0); if AForceDelete then EndUpdate; end; end; function TcxCustomScheduler.IsViewAtLeft: Boolean; begin Result := OptionsView.ViewPosition = vpLeft; end; procedure TcxCustomScheduler.KeyDown( var Key: Word; Shift: TShiftState); begin if KeyboardListener <> nil then KeyboardListener.Controller.KeyDown(Key, Shift) else CurrentView.Controller.KeyDown(Key, Shift); inherited KeyDown(Key, Shift); end; procedure TcxCustomScheduler.KeyPress(var Key: Char); begin if KeyboardListener <> nil then KeyboardListener.Controller.KeyPress(Key) else CurrentView.Controller.KeyPress(Key); inherited KeyPress(Key); end; procedure TcxCustomScheduler.KeyUp( var Key: Word; Shift: TShiftState); begin if KeyboardListener <> nil then KeyboardListener.Controller.KeyUp(Key, Shift) else CurrentView.Controller.KeyUp(Key, Shift); inherited KeyUp(Key, Shift); end; procedure TcxCustomScheduler.Loaded; begin inherited Loaded; if not OptionsCustomize.IntegralSizing then begin if IsViewAtLeft then DateNavigator.FSavedSize.cx := ClientBounds.Right - VertSplitter.Right else DateNavigator.FSavedSize.cx := VertSplitter.Left - ClientBounds.Left; DateNavigator.FSavedSize.cy := HorzSplitter.Top - ClientBounds.Top; end; DateNavigator.CheckSizes; FullRefresh; end; procedure TcxCustomScheduler.LockUpdateChanged( ALocking: Boolean); begin end; procedure TcxCustomScheduler.LookAndFeelChanged( Sender: TcxLookAndFeel; AChangedValues: TcxLookAndFeelValues); begin inherited LookAndFeelChanged(Sender, AChangedValues); LayoutChanged; end; procedure TcxCustomScheduler.MouseDown( Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin FPrevMousePos := cxInvalidPoint; FActiveControl := GetControlFromPoint(cxPoint(X, Y)); Capture := FActiveControl; Capture.DoBeforeMouseDown(Button, Shift, X, Y); inherited MouseDown(Button, Shift, X, Y); Capture.DoMouseDown(Button, Shift, X, Y); end; procedure TcxCustomScheduler.MouseLeave(AControl: TControl); begin inherited MouseLeave(AControl); FActiveControl := nil; end; procedure TcxCustomScheduler.MouseMove( Shift: TShiftState; X, Y: Integer); begin if (FPrevMousePos.X = X) and (FPrevMousePos.Y = Y) then Exit; FPrevMousePos := cxPoint(X, Y); FActiveControl := FCaptureControl; if FActiveControl = nil then FActiveControl := GetControlFromPoint(cxPoint(X, Y)); FActiveControl.DoMouseMove(Shift, X, Y); inherited MouseMove(Shift, X, Y); if OptionsView.HotTrack or OptionsView.ShowHints then begin CurrentView.MousePositionChanged(X, Y); if (ssLeft in Shift) and not CurrentView.HitTest.HitAtControl and (FSelStart <> FSelFinish) then begin ReplaceSelParams(FSelStart, FSelStart, FSelResource); CurrentView.Refresh; end; EventHitTestController.MouseMove(X, Y, Shift); end; end; procedure TcxCustomScheduler.MouseUp( Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin inherited MouseUp(Button, Shift, X, Y); Capture.DoMouseUp(Button, Shift, X, Y); Capture := nil; end; procedure TcxCustomScheduler.Paint; var I: Integer; begin if IsLoading then Exit; {$IFNDEF DEBUGPAINT} if not (cfImageValid in FControlFlags) then {$ELSE} GdiSetBatchLimit(1); {$ENDIF} begin Canvas.Canvas.Lock; try SelectClipRgn(GetControlCanvas.Handle, 0); if BorderStyle = cxcbsDefault then begin LookAndFeelPainter.DrawSchedulerBorder(GetControlCanvas, Bounds); GetControlCanvas.IntersectClipRect(ClientBounds); end; for I := 0 to SubControlCount - 1 do if SubControls[I] <> FBackground then SubControls[I].Paint; Include(FControlFlags, cfImageValid); finally Canvas.Canvas.Unlock; end; end; {$IFNDEF DEBUGPAINT} BitBlt(inherited Canvas.Handle, 0, 0, Width, Height, BitmapCanvas.Handle, 0, 0, SRCCOPY); {$ENDIF} FCanModified := True; end; procedure TcxCustomScheduler.PeriodChanged; begin FullRefresh; DateNavigator.DoPeriodChangedEvent; end; procedure TcxCustomScheduler.RemoveSubControl( AControl: TcxSchedulerSubControl); begin if (FSubControls.Remove(AControl) <> -1) and not IsDestroying then begin LayoutChanged; if Capture = AControl then Capture := nil; end; end; procedure TcxCustomScheduler.ReplaceSelParams(ASelStart, ASelFinish: TDateTime; AResource: TcxSchedulerStorageResourceItem); begin with DateTimeHelper do begin if (FSelResource <> AResource) or (FSelStart <> RoundTime(ASelStart)) or (FSelFinish <> RoundTime(ASelFinish)) then begin FSelResource := AResource; FSelStart := RoundTime(ASelStart); FSelFinish := RoundTime(ASelFinish); DoSelectionChanged; end; end; end; procedure TcxCustomScheduler.Scroll(AScrollBarKind: TScrollBarKind; AScrollCode: TScrollCode; var AScrollPos: Integer); begin if EditController.IsEditing then Exit; CurrentView.Scroll(AScrollBarKind, AScrollCode, AScrollPos); end; procedure TcxCustomScheduler.SetCurrentView( AView: TcxSchedulerCustomView); begin if (AView <> nil) and (AView.Scheduler = Self) then FCurrentView := AView; end; procedure TcxCustomScheduler.SubControlAdd( AControl: TcxSchedulerSubControl); begin FSubControls.Add(AControl); LayoutChanged; end; procedure TcxCustomScheduler.SubControlRemove( AControl: TcxSchedulerSubControl); begin FSubControls.Remove(AControl); LayoutChanged; end; procedure TcxCustomScheduler.SynchronizeVisibleDays; begin Include(FControlFlags, cfViewValid); end; procedure TcxCustomScheduler.UpdateEventsCache( ACheckDaysInterval: Boolean); var AStart, AFinish: TDateTime; begin CurrentView.Controller.CloseInplaceEdit; if not StorageValid then begin FreeAndNil(FEventList); FEventList := CreateEventList; end; FEventList.TimeZone := OptionsView.CurrentTimeZone; FEventList.ShowEventsWithoutResource := OptionsView.ShowEventsWithoutResource or (VisibleGroupingKind = gkNone); AStart := Min(CurrentView.FirstVisibleDate, DateNavigator.GetRealFirstDate) - CurrentView.GetVisibleDaysRange; AFinish := Max(CurrentView.LastVisibleDate, DateNavigator.GetRealLastDate) + CurrentView.GetVisibleDaysRange; if ACheckDaysInterval and (AStart >= EventList.Start) and (AFinish <= EventList.Finish) then Exit; FEventList.SelStart := SelectedDays[0] - 7; FEventList.SelFinish := SelectedDays[SelectedDays.Count - 1] + 7; if StorageValid then Storage.GetEvents(FEventList, AStart, AFinish); FEventDays.Clear; if DateNavigator.GetShowDatesContainingEventsInBold then FEventList.ExtractUsedDays(FEventDays); end; procedure TcxCustomScheduler.ValidateSelection( ASelection: TcxSchedulerDateList); begin DateNavigator.UpdateSelection; end; procedure TcxCustomScheduler.ValidateState; var AIsLocked: Boolean; begin AIsLocked := cfLocked in FControlFlags; if cfInvalidLayout in FControlFlags then try LayoutChanged; finally FControlFlags := []; if AIsLocked then FControlFlags := [cfLocked]; end; end; procedure TcxCustomScheduler.ViewVisibleChanged( AView: TcxSchedulerCustomView); begin Exclude(FControlFlags, cfViewValid); if FVisibleChangedCount = 0 then DateNavigator.BeginUpdate; Inc(FVisibleChangedCount); try if AView.Visible and (CurrentView <> AView) then begin CurrentView.Visible := False; DoViewTypeChanged(AView); CurrentView := AView; end else if not FCurrentView.Visible and (FVisibleChangedCount = 1) then GetNextView(FCurrentView).Visible := True; finally Dec(FVisibleChangedCount); if FVisibleChangedCount = 0 then begin AlignSubControls; LayoutChanged; DateNavigator.EndUpdate; end; end; end; function TcxCustomScheduler.VisibleGroupingKind: TcxSchedulerGroupingKind; var I, C: Integer; begin Result := CurrentView.GetGroupingKind; C := 0; if HasResources then begin for I := 0 to Storage.ResourceCount - 1 do if Storage.Resources.ResourceItems[I].Visible then Inc(C); end; if C = 0 then Result := gkNone else if Result = gkDefault then Result := gkByResource; end; function TcxCustomScheduler.CanDrag(X, Y: Integer): Boolean; begin Result := inherited CanDrag(X, Y) and not IsDesigning and CaptureController.CanDrag(X, Y); end; procedure TcxCustomScheduler.DoEndDrag( Target: TObject; X, Y: Integer); begin CaptureController.EndDrag(Target, X, Y); inherited DoEndDrag(Target, X, Y); Capture := nil; end; procedure TcxCustomScheduler.DoStartDrag( var DragObject: TDragObject); begin FIsDragCanceled := False; inherited DoStartDrag(DragObject); CaptureController.StartDrag(DragObject); end; procedure TcxCustomScheduler.DragAndDrop( const P: TPoint; var Accepted: Boolean); begin inherited DragAndDrop(P, Accepted); CaptureController.DragAndDrop(P, Accepted); end; procedure TcxCustomScheduler.DragOver( Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); var AAccept, ACopyDragDrop: Boolean; AControl: TcxSchedulerSubControl; begin ACopyDragDrop := IsCopyDragDrop; if State <> dsDragMove then FPrevMousePos := cxInvalidPoint else if (FPrevMousePos.X = X) and (FPrevMousePos.Y = Y) and (FPrevCopyDragDrop = ACopyDragDrop) then Exit else FPrevMousePos := cxPoint(X, Y); if not Dragging then begin AControl := GetControlFromPoint(Point(X, Y)); if AControl <> nil then begin SetCaptureControl(AControl); AControl.MousePositionChanged(X, Y); end; end; AAccept := Accept and (DragMode = dmAutomatic); inherited DragOver(Source, X, Y, State, Accept); if not Assigned(OnDragOver) then Accept := AAccept; CaptureController.DragOver(Source, X, Y, State, Accept); FPrevCopyDragDrop := ACopyDragDrop; end; procedure TcxCustomScheduler.EndDragAndDrop( Accepted: Boolean); begin inherited EndDragAndDrop(Accepted); CaptureController.EndDragAndDrop(Accepted); end; function TcxCustomScheduler.GetDragAndDropObjectClass: TcxDragAndDropObjectClass; begin Result := CaptureController.GetDragAndDropObjectClass; end; function TcxCustomScheduler.GetDragObjectClass: TDragControlObjectClass; begin Result := TcxSchedulerDragObject; end; function TcxCustomScheduler.StartDragAndDrop( const P: TPoint): Boolean; begin Result := CaptureController.StartDragAndDrop(P) end; // IcxSchedulerStorageListener procedure TcxCustomScheduler.StorageChanged(Sender: TObject); begin FullRefresh; end; procedure TcxCustomScheduler.StorageRemoved(Sender: TObject); begin CurrentView.Controller.CloseInplaceEdit; FStorage.RemoveListener(Self); FStorage := nil; LayoutChanged; end; // IcxFormatControllerListener procedure TcxCustomScheduler.DoStartOfWeekChanged( AOldStartOfWeek, ANewStartOfWeek: TDay); var I, ADelta: Integer; begin ADelta := Ord(ANewStartOfWeek) - Ord(AOldStartOfWeek); if (ADelta <> 0) and not CurrentView.IsDayView then begin for I := 0 to SelectedDays.Count - 1 do SelectedDays[I] := SelectedDays[I] + ADelta; end; OptionsView.CalculateActualStartOfWeek; FullRefresh; end; procedure TcxCustomScheduler.FormatChanged; var I: Integer; begin if DateTimeHelper <> nil then DateTimeHelper.Refresh; if OptionsView.StartOfWeek = swSystem then DoStartOfWeekChanged(OptionsView.ActualStartOfWeek, TDay(DateTimeHelper.StartOfWeek)) else begin for I := 0 to SubControlCount - 1 do SubControls[I].FormatChanged; FullRefresh; end; end; // IcxFormatControllerListener2 procedure TcxCustomScheduler.TimeChanged; begin DoUpdateTime; end; // IcxStoredObject function TcxCustomScheduler.GetObjectName: string; begin if FStoringName <> '' then Result := FStoringName else Result := Name; end; function TcxCustomScheduler.GetProperties(AProperties: TStrings): Boolean; var I: Integer; begin AProperties.Add('SelectedDayCount'); for I := 0 to SubControlCount - 1 do SubControls[I].GetProperties(AProperties); Result := True; end; procedure TcxCustomScheduler.GetPropertyValue(const AName: string; var AValue: Variant); var I: Integer; begin if AName = 'SelectedDayCount' then AValue := SelectedDays.Count else for I := 0 to SubControlCount - 1 do SubControls[I].GetPropertyValue(AName, AValue); end; procedure TcxCustomScheduler.SetPropertyValue(const AName: string; const AValue: Variant); var I: Integer; ADate: TDateTime; begin if AName = 'SelectedDayCount' then begin SelectedDays.Clear; ADate := Date; for I := 0 to Min(Max(AValue - 1, 0), 41) do SelectedDays.Add(ADate + I); end else for I := 0 to SubControlCount - 1 do SubControls[I].SetPropertyValue(AName, AValue); end; procedure TcxCustomScheduler.CalcHorzSplitterBounds( AByDateNavigator: Boolean); begin if not FHorzSplitter.Visible or FHorzSplitterShowing then Exit; if AByDateNavigator then FHorzSplitter.Bounds := cxRectSetTop(DateNavigator.Bounds, DateNavigator.Bottom, OptionsView.HorzSplitterWidth) else FHorzSplitter.Bounds := cxRectSetBottom(ControlBox.Bounds, ControlBox.Top, OptionsView.HorzSplitterWidth); end; procedure TcxCustomScheduler.CalcVertSplitterBounds; var R: TRect; begin if not FVertSplitter.Visible or FVertSplitterShowing then Exit; if DateNavigator.Visible then R := DateNavigator.Bounds else R := ControlBox.Bounds; if IsViewAtLeft then R := cxRectSetRight(ClientBounds, R.Left, OptionsView.VertSplitterWidth) else R := cxRectSetLeft(ClientBounds, R.Right, OptionsView.VertSplitterWidth); FVertSplitter.Bounds := R; end; procedure TcxCustomScheduler.CheckHorzSplitterBounds; var R: TRect; begin R := FHorzSplitter.Bounds; if IsVertSplitterVisible then begin if IsViewAtLeft then begin R.Left := FVertSplitter.Right; R.Right := ClientBounds.Right; end else begin R.Left := ClientBounds.Left; R.Right := FVertSplitter.Left; end end else begin R.Left := ClientBounds.Left; R.Right := ClientBounds.Right; end; FHorzSplitter.Bounds := cxRectSetHeight(R, OptionsView.HorzSplitterWidth); end; procedure TcxCustomScheduler.CheckSplittersVisibilityChanging; begin FVertSplitterShowing := not FVertSplitter.Visible and IsVertSplitterVisible; if FVertSplitterShowing then UpdateControlsBoundsOnVertSplitterShowing; FVertSplitter.Visible := IsVertSplitterVisible; FHorzSplitterShowing := not FHorzSplitter.Visible and IsHorzSplitterVisible; if FHorzSplitterShowing then UpdateControlsBoundsOnHorzSplitterShowing; FHorzSplitter.Visible := IsHorzSplitterVisible; end; procedure TcxCustomScheduler.CreateUpdateTimeTimer; begin FUpdateTimeTimer := TTimer.Create(nil); FUpdateTimeTimer.Interval := 60 * 1000; //one minute FUpdateTimeTimer.OnTimer := UpdateTimeHandler; end; function TcxCustomScheduler.GetActiveHitTest: TcxSchedulerSubControlHitTest; var AControl: TcxSchedulerSubControl; APos: TPoint; begin if (FActiveControl <> nil) and (FCaptureControl = nil) then Result := FActiveControl.HitTest else begin APos := ScreenToClient(GetMouseCursorPos); AControl := GetControlFromPoint(APos); if AControl = Background then Result := nil else begin AControl.MousePositionChanged(APos.X, APos.Y); Result := AControl.HitTest; end; end; end; function TcxCustomScheduler.GetCaptureControl: TcxSchedulerSubControl; begin Result := FCaptureControl; if FCaptureControl = nil then Result := Background; end; function TcxCustomScheduler.GetCaptureController: TcxSchedulerSubControlController; begin Result := Capture.Controller; end; function TcxCustomScheduler.GetSelectedEventCount: Integer; begin Result := EventList.Selection.Count; end; function TcxCustomScheduler.GetSelectedEvent( AIndex: Integer): TcxSchedulerControlEvent; begin Result := EventList.Selection[AIndex] end; function TcxCustomScheduler.GetSelFinish: TDateTime; begin Result := Max(FSelStart, FSelFinish); Result := DateTimeHelper.RoundTime(Result + CurrentView.GetTimeIncrement); end; function TcxCustomScheduler.GetSelStart: TDateTime; begin Result := Min(FSelStart, FSelFinish); end; function TcxCustomScheduler.GetIsDynamicUpdate: Boolean; begin Result := OptionsCustomize.DynamicSizing and not IsDesigning; end; function TcxCustomScheduler.GetStartOfWeek: TDay; begin Result := OptionsView.ActualStartOfWeek; end; function TcxCustomScheduler.GetStorageActive: Boolean; begin Result := (FStorage <> nil) and FStorage.IsActive; end; function TcxCustomScheduler.GetStorageValid: Boolean; begin Result := FStorage <> nil; end; function TcxCustomScheduler.GetSubControl( AIndex: Integer): TcxSchedulerSubControl; begin Result := TcxSchedulerSubControl(FSubControls[AIndex]) end; function TcxCustomScheduler.GetSubControlCount: Integer; begin Result := FSubControls.Count; end; function TcxCustomScheduler.GetVisibleEventCount: Integer; begin Result := EventList.Count; end; function TcxCustomScheduler.GetVisibleEvent( AIndex: Integer): TcxSchedulerControlEvent; begin Result := EventList[AIndex]; end; procedure TcxCustomScheduler.InitEventBySelection( AEvent: TcxSchedulerEvent; AllDay: Boolean; ARecurrence: Boolean; AInplaceEditing: Boolean); const States: array[Boolean] of Byte = (tlsBusy, tlsFree); begin if SelResource <> nil then AEvent.ResourceID := SelResource.ResourceID; CurrentView.InitEventBySelectedPeriod(AEvent, AllDay, ARecurrence, AInplaceEditing); AEvent.State := States[AEvent.AllDayEvent]; end; function TcxCustomScheduler.IsHorzSplitterVisible: Boolean; begin Result := DateNavigator.Visible and ControlBox.Visible; end; function TcxCustomScheduler.IsVertSplitterVisible: Boolean; begin Result := CurrentView.Visible and (DateNavigator.Visible or ControlBox.Visible); end; procedure TcxCustomScheduler.SetCaptureControl( AValue: TcxSchedulerSubControl); begin if FCaptureControl <> AValue then begin CaptureController.DoCancelMode; FCaptureControl := AValue; end; end; procedure TcxCustomScheduler.SetContentPopupMenu( AValue: TcxSchedulerContentPopupMenu); begin FContentPopupMenu.Assign(AValue); end; procedure TcxCustomScheduler.SetControlBox( AValue: TcxSchedulerControlBox); begin FControlBox.Assign(AValue); end; procedure TcxCustomScheduler.SetEventOperations( AValue: TcxSchedulerEventOperations); begin FEventOperations.Assign(AValue); end; procedure TcxCustomScheduler.SetEventPopupMenu( AValue: TcxSchedulerEventPopupMenu); begin FEventPopupMenu.Assign(AValue); end; procedure TcxCustomScheduler.SetOptionsCustomize( AValue: TcxSchedulerOptionsCustomize); begin FOptionsCustomize.Assign(AValue); end; procedure TcxCustomScheduler.SetOptionsView( AValue: TcxSchedulerOptionsView); begin FOptionsView.Assign(AValue); end; procedure TcxCustomScheduler.SetStorage( AValue: TcxCustomSchedulerStorage); begin if FStorage <> AValue then begin if FStorage <> nil then FStorage.RemoveListener(Self); FStorage := AValue; if FStorage <> nil then FStorage.AddListener(Self); FullRefresh; end; end; procedure TcxCustomScheduler.SetStyles( AValue: TcxSchedulerStyles); begin FStyles.Assign(AValue); end; procedure TcxCustomScheduler.UpdateAlignByDateNavigatorOrControlBox( AByDateNavigator: Boolean); procedure CalcSlaveControlBounds(ASlave, AMaster: TcxSchedulerSubControl); var R: TRect; begin if not ASlave.Visible then Exit; R := ClientBounds; R.Left := AMaster.Left; R.Right := AMaster.Right; if IsHorzSplitterVisible then if ASlave = DateNavigator then R.Bottom := FHorzSplitter.Top else R.Top := FHorzSplitter.Bottom; ASlave.Bounds := R; end; procedure CalcMasterControlBounds(AMaster: TcxSchedulerSubControl); var R: TRect; begin if not AMaster.Visible then Exit; R := AMaster.Bounds; if not IsVertSplitterVisible then begin R.Left := ClientBounds.Left; R.Right := ClientBounds.Right; end else if IsViewAtLeft then R := cxRectSetRight(R, ClientBounds.Right) else R := cxRectSetLeft(R, ClientBounds.Left); if not IsHorzSplitterVisible then if AMaster = DateNavigator then R.Bottom := ClientBounds.Bottom else R.Top := ClientBounds.Top; if AMaster = DateNavigator then R := cxRectSetTop(R, ClientBounds.Top) else R := cxRectSetBottom(R, ClientBounds.Bottom); AMaster.Bounds := R; end; var ASlave, AMaster: TcxSchedulerSubControl; begin if AByDateNavigator then begin AMaster := DateNavigator; ASlave := ControlBox; end else begin AMaster := ControlBox; ASlave := DateNavigator; end; CalcMasterControlBounds(AMaster); if AMaster.Visible then CalcHorzSplitterBounds(AByDateNavigator); CalcSlaveControlBounds(ASlave, AMaster); CalcVertSplitterBounds; UpdateCurrentViewBounds; end; procedure TcxCustomScheduler.UpdateAlignByView; procedure CalcControlBounds(AControl: TcxSchedulerSubControl); var R: TRect; begin if not AControl.Visible then Exit; R := ClientBounds; if IsHorzSplitterVisible then if AControl = DateNavigator then R.Bottom := FHorzSplitter.Top else R.Top := FHorzSplitter.Bottom; if IsVertSplitterVisible then if IsViewAtLeft then R.Left := FVertSplitter.Right else R.Right := FVertSplitter.Left; AControl.Bounds := R; end; procedure CheckVertSplitterBounds; var R: TRect; begin if not IsVertSplitterVisible then Exit; R := CurrentView.Bounds; if IsViewAtLeft then R := cxRectSetLeft(R, R.Right, OptionsView.VertSplitterWidth) else R := cxRectSetRight(R, R.Left, OptionsView.VertSplitterWidth); FVertSplitter.Bounds := R; end; procedure CheckCurrentViewBounds; begin if not IsVertSplitterVisible then UpdateCurrentViewBounds; if not IsViewAtLeft then CurrentView.Right := ClientBounds.Right; end; begin CheckCurrentViewBounds; CheckVertSplitterBounds; CalcControlBounds(DateNavigator); CalcControlBounds(ControlBox); CalcHorzSplitterBounds(DateNavigator.Visible); end; procedure TcxCustomScheduler.UpdateControlsBoundsOnHorzSplitterShowing; var R: TRect; begin CheckHorzSplitterBounds; R := DateNavigator.Bounds; R.Top := ClientBounds.Top; R.Bottom := FHorzSplitter.Top; DateNavigator.Bounds := R; R.Top := FHorzSplitter.Bottom; R.Bottom := ClientBounds.Bottom; ControlBox.Bounds := R; end; procedure TcxCustomScheduler.UpdateControlsBoundsOnVertSplitterShowing; var R: TRect; begin CheckHorzSplitterBounds; FVertSplitter.Width := OptionsView.VertSplitterWidth; R := ClientBounds; if IsViewAtLeft then begin R.Right := FVertSplitter.Left; CurrentView.Bounds := R; R := DateNavigator.Bounds; R.Left := FVertSplitter.Right; R.Right := ClientBounds.Right; end else begin R.Left := FVertSplitter.Right; CurrentView.Bounds := R; R := DateNavigator.Bounds; R.Left := ClientBounds.Left; R.Right := FVertSplitter.Left; end; DateNavigator.Bounds := R; R.Top := ControlBox.Bounds.Top; R.Bottom := ClientBounds.Bottom; ControlBox.Bounds := R; end; procedure TcxCustomScheduler.UpdateCurrentViewBounds; var R: TRect; begin if not CurrentView.Visible then Exit; R := ClientBounds; if IsViewAtLeft and IsVertSplitterVisible then R.Right := FVertSplitter.Left; if not IsViewAtLeft and IsVertSplitterVisible then R.Left := FVertSplitter.Right; CurrentView.Bounds := R; end; procedure TcxCustomScheduler.UpdateInvisibleSplitterBounds; begin if not (FSubControlsCreated and HandleAllocated) then Exit; FAligningSubControls := True; try if not HorzSplitter.Visible and IsViewAtLeft then HorzSplitter.Right := ClientBounds.Right; if not VertSplitter.Visible then begin if IsViewAtLeft then VertSplitter.Left := VertSplitter.Left + (ClientBounds.Right - FPrevBounds.Right); VertSplitter.Height := ClientHeight; end; finally FAligningSubControls := False; end; end; procedure TcxCustomScheduler.UpdateTimeHandler(Sender: TObject); begin CurrentView.TimeChanged; end; procedure TcxCustomScheduler.WMCancelMode(var Message: TWMCancelMode); begin FIsDragCanceled := True; try inherited; finally FIsDragCanceled := False; end; end; procedure TcxCustomScheduler.WMSetCursor(var Message: TWMSetCursor); var P: TPoint; ACursor: TCursor; begin ACursor := crDefault; P := ScreenToClient(GetMouseCursorPos); if IsDesigning and (DragAndDropState = ddsNone) and GetDesignHitTest(P.X, P.Y, [ssLeft]) then ACursor := GetControlFromPoint(P).Controller.GetCursor(P.X, P.Y); if ACursor <> crDefault then SetCursor(Screen.Cursors[ACursor]) else inherited; end; procedure TcxCustomScheduler.WMTimeChange(var Message: TWMTimeChange); begin DoUpdateTime; Message.Result := 0; end; procedure TcxCustomScheduler.ReadSelectionData(AReader: TReader); var I: Integer; begin FSelectedDays.Count := AReader.ReadInteger and $FF; for I := 0 to FSelectedDays.Count - 1 do FSelectedDays[I] := Date + I; end; procedure TcxCustomScheduler.ReadSplittersData(AStream: TStream); var R: TRect; begin BeginUpdate; try AStream.Read(R, SizeOf(R)); HorzSplitter.Bounds := R; AStream.Read(R, SizeOf(R)); VertSplitter.Bounds := R; LayoutChanged; finally EndUpdate; end; end; procedure TcxCustomScheduler.WriteSelectionData(AWriter: TWriter); begin AWriter.WriteInteger(FSelectedDays.Count); end; procedure TcxCustomScheduler.WriteSplittersData(AStream: TStream); var R: TRect; begin R := HorzSplitter.Bounds; AStream.Write(R, SizeOf(R)); R := VertSplitter.Bounds; AStream.Write(R, SizeOf(R)); end; { TcxSchedulerDragAndDropObject } constructor TcxSchedulerDragAndDropObject.Create(AControl: TcxControl); begin inherited Create(AControl); FScheduler := AControl as TcxCustomScheduler; end; procedure TcxSchedulerDragAndDropObject.BeginDragAndDrop; begin inherited BeginDragAndDrop; FSizingHelper := Controller.CreateResizeEventHelper; end; procedure TcxSchedulerDragAndDropObject.DragAndDrop(const P: TPoint; var Accepted: Boolean); var AP: TPoint; begin if Assigned(FSizingHelper) then begin AP := P; Controller.Owner.MousePositionChanged(AP.X, AP.Y); HitTest.HitPoint := AP; SizingHelper.DragOver(AP, dsDragMove, Accepted); SizingHelper.UpdateState; end; inherited DragAndDrop(P, Accepted); end; procedure TcxSchedulerDragAndDropObject.EndDragAndDrop(Accepted: Boolean); var AP: TPoint; begin if Assigned(SizingHelper) then try AP := CurMousePos; Controller.Owner.MousePositionChanged(AP.X, AP.Y); HitTest.HitPoint := AP; if Accepted then Scheduler.DoAfterSizingEvent(AP.X, AP.Y, Accepted); SizingHelper.EndDrag(Accepted); finally FreeAndNil(FSizingHelper); end; inherited EndDragAndDrop(Accepted); end; function TcxSchedulerDragAndDropObject.GetController: TcxSchedulerViewController; begin Result := FScheduler.CurrentView.Controller; end; function TcxSchedulerDragAndDropObject.GetDragAndDropCursor( Accepted: Boolean): TCursor; begin if Assigned(FSizingHelper) then Result := SizingHelper.GetDragCursor(Accepted) else Result := inherited GetDragAndDropCursor(Accepted); end; function TcxSchedulerDragAndDropObject.GetHitTest: TcxSchedulerViewHitTest; begin Result := FScheduler.CurrentView.HitTest; end; { TcxSchedulerOptionsCustomize } constructor TcxSchedulerOptionsCustomize.Create( AOwner: TcxCustomScheduler); begin FScheduler := AOwner; FControlsSizing := True; FIntegralSizing := True; end; procedure TcxSchedulerOptionsCustomize.Assign(Source: TPersistent); var ASourceOptionsCustomize: TcxSchedulerOptionsCustomize; begin if Source is TcxSchedulerOptionsCustomize then begin ASourceOptionsCustomize := TcxSchedulerOptionsCustomize(Source); FControlsSizing := ASourceOptionsCustomize.ControlsSizing; FDynamicSizing := ASourceOptionsCustomize.DynamicSizing; IntegralSizing := ASourceOptionsCustomize.IntegralSizing; end else inherited Assign(Source); end; procedure TcxSchedulerOptionsCustomize.Changed; begin FScheduler.LayoutChanged; end; function TcxSchedulerOptionsCustomize.GetOwner: TPersistent; begin Result := FScheduler; end; procedure TcxSchedulerOptionsCustomize.SetControlsSizing(AValue: Boolean); begin FControlsSizing := AValue; Scheduler.HorzSplitter.UpdateCursor; Scheduler.VertSplitter.UpdateCursor; end; procedure TcxSchedulerOptionsCustomize.SetIntegralSizing(AValue: Boolean); begin if AValue <> FIntegralSizing then begin FIntegralSizing := AValue; if AValue then Scheduler.DateNavigator.SetIntegralSizes; Changed; end; end; { TcxSchedulerOptionsView } constructor TcxSchedulerOptionsView.Create( AOwner: TcxCustomScheduler); begin FTimeZones[0] := -1; FTimeZones[1] := -1; FDayBorderColor := clDefault; FGroupSeparatorWidth := cxDefaultGroupSeparatorWidth; FScheduler := AOwner; FHorzSplitterWidth := cxDefaultSplitterWidth; FVertSplitterWidth := cxDefaultSplitterWidth; FHideSelection := False; FHotTrack := False; //for the next version True; FRotateResourceCaptions := True; FWorkDays := DateTimeHelper.WorkDays; FStartOfWeek := swSystem; CalculateActualStartOfWeek; FWorkFinish := DateTimeHelper.WorkFinish; FWorkStart := DateTimeHelper.WorkStart; FViewPosition := vpLeft; ShowHints := True; end; procedure TcxSchedulerOptionsView.Assign( Source: TPersistent); var AItem: Integer; ASourceOptionsView: TcxSchedulerOptionsView; begin if Source is TcxSchedulerOptionsView then begin ASourceOptionsView := TcxSchedulerOptionsView(Source); for AItem := 0 to 1 do begin FTimeZones[AItem] := ASourceOptionsView.FTimeZones[AItem]; FTimeZoneLabels[AItem] := ASourceOptionsView.FTimeZoneLabels[AItem]; end; FDayBorderColor := ASourceOptionsView.DayBorderColor; FGroupingKind := ASourceOptionsView.FGroupingKind; FGroupSeparatorWidth := ASourceOptionsView.FGroupSeparatorWidth; FHideSelection := ASourceOptionsView.HideSelection; FHorzSplitterWidth := ASourceOptionsView.FHorzSplitterWidth; FHotTrack := ASourceOptionsView.HotTrack; FRotateResourceCaptions := ASourceOptionsView.RotateResourceCaptions; FShowHints := ASourceOptionsView.ShowHints; FVertSplitterWidth := ASourceOptionsView.FVertSplitterWidth; FViewPosition := ASourceOptionsView.ViewPosition; FWorkDays := ASourceOptionsView.WorkDays; FWorkFinish := ASourceOptionsView.WorkFinish; FWorkStart := ASourceOptionsView.WorkStart; end else inherited Assign(Source); end; procedure TcxSchedulerOptionsView.CalculateActualStartOfWeek; begin if FStartOfWeek = swSystem then FActualStartOfWeek := TDay(DateTimeHelper.StartOfWeek) else FActualStartOfWeek := TDay(Pred(FStartOfWeek)); end; procedure TcxSchedulerOptionsView.Changed; begin Scheduler.LayoutChanged; end; function TcxSchedulerOptionsView.GetOwner: TPersistent; begin Result := FScheduler; end; function TcxSchedulerOptionsView.IsWorkDaysStored: Boolean; begin Result := FWorkDays <> DateTimeHelper.WorkDays; end; function TcxSchedulerOptionsView.IsWorkFinishStored: Boolean; begin Result := FWorkFinish <> DateTimeHelper.WorkFinish; end; function TcxSchedulerOptionsView.IsWorkStartStored: Boolean; begin Result := FWorkStart <> DateTimeHelper.WorkStart; end; function TcxSchedulerOptionsView.IsWorkTime( const ADateTime: TDateTime): Boolean; begin Result := (TDay(DayOfWeek(ADateTime) - 1) in WorkDays) and ((DateTimeHelper.RoundTime(TimeOf(ADateTime)) >= WorkStart) and (DateTimeHelper.RoundTime(TimeOf(ADateTime)) < WorkFinish)); end; function TcxSchedulerOptionsView.GetDateTimeHelperClass: TcxSchedulerDateTimeHelperClass; begin Result := Scheduler.DateTimeHelper; end; function TcxSchedulerOptionsView.GetTimeZone( AIndex: Integer): Integer; begin Result := FTimeZones[AIndex]; if (Result < 0) or (Result >= DateTimeHelper.TimeZoneCount) then Result := -1; end; function TcxSchedulerOptionsView.GetTimeZoneLabel( AIndex: Integer): string; begin Result := FTimeZoneLabels[AIndex]; end; procedure TcxSchedulerOptionsView.SetDayBorderColor(AValue: TColor); begin if AValue <> FDayBorderColor then begin FDayBorderColor := AValue; Changed; end; end; procedure TcxSchedulerOptionsView.SetShowEventsWithoutResource( AValue: Boolean); begin if AValue <> FShowEventsWithoutResource then begin FShowEventsWithoutResource := AValue; Scheduler.FullRefresh; end; end; procedure TcxSchedulerOptionsView.SetGroupSeparatorWidth( AValue: Integer); begin FGroupSeparatorWidth := Max(0, AValue); Changed; end; procedure TcxSchedulerOptionsView.SetGroupingKind( AValue: TcxSchedulerGroupingKind); begin if FGroupingKind <> AValue then begin FGroupingKind := AValue; Changed; end; end; procedure TcxSchedulerOptionsView.SetHideSelection(AValue: Boolean); begin if FHideSelection <> AValue then begin FHideSelection := AValue; Changed; end; end; procedure TcxSchedulerOptionsView.SetHorzSplitterWidth(AValue: Integer); begin SetSplitterWidth(AValue, FHorzSplitterWidth); end; procedure TcxSchedulerOptionsView.SetRotateResourceCaptions(AValue: Boolean); begin if AValue <> FRotateResourceCaptions then begin FRotateResourceCaptions := AValue; Changed; end; end; procedure TcxSchedulerOptionsView.SetShowAdditionalTimeZone(AValue: Boolean); begin if FShowAdditionalTimeZone <> AValue then begin FShowAdditionalTimeZone := AValue; Changed; end; end; procedure TcxSchedulerOptionsView.SetSplitterWidth( AValue: Integer; var AWidth: Integer); begin AValue := Max(AValue, cxMinSplitterWidth); if AValue <> AWidth then begin AWidth := AValue; Changed; end; end; procedure TcxSchedulerOptionsView.SetStartOfWeek(AValue: TcxStartOfWeek); var AOldActualValue: TDay; begin if AValue <> FStartOfWeek then begin FStartOfWeek := AValue; AOldActualValue := ActualStartOfWeek; CalculateActualStartOfWeek; if not Scheduler.IsLoading then Scheduler.DoStartOfWeekChanged(AOldActualValue, ActualStartOfWeek); end; end; procedure TcxSchedulerOptionsView.SetTimeZone( AIndex, AValue: Integer); begin AValue := Max(Min(AValue, DateTimeHelper.TimeZoneCount - 1), -1); if AValue <> FTimeZones[AIndex] then begin FTimeZones[AIndex] := AValue; Scheduler.FullRefresh; end; end; procedure TcxSchedulerOptionsView.SetTimeZoneLabel( AIndex: Integer; const AValue: string); begin if AValue <> FTimeZoneLabels[AIndex] then begin FTimeZoneLabels[AIndex] := AValue; Changed; end; end; procedure TcxSchedulerOptionsView.SetVertSplitterWidth(AValue: Integer); begin SetSplitterWidth(AValue, FVertSplitterWidth); end; procedure TcxSchedulerOptionsView.SetViewPosition( AValue: TcxSchedulerViewPosition); begin if AValue <> FViewPosition then begin FViewPosition := AValue; Changed; end; end; procedure TcxSchedulerOptionsView.SetWorkDays(AValue: TDays); begin if AValue <> FWorkDays then begin FWorkDays := AValue; Scheduler.PeriodChanged; end; end; procedure TcxSchedulerOptionsView.SetWorkFinish(AValue: TTime); begin if AValue <> FWorkFinish then begin FWorkFinish := DateTimeHelper.RoundTime(AValue); Scheduler.PeriodChanged; end; end; procedure TcxSchedulerOptionsView.SetWorkStart(AValue: TTime); begin if AValue <> FWorkStart then begin FWorkStart := DateTimeHelper.RoundTime(AValue); Scheduler.PeriodChanged; end; end; function TcxSchedulerOptionsView.IsTimeZoneLabelStored( AIndex: Integer): Boolean; begin Result := FTimeZoneLabels[AIndex] <> ''; end; { TcxSchedulerViewHitTest } function TcxSchedulerViewHitTest.GetDragKind: TcxEventDragKind; begin Result := edkNone; end; procedure TcxSchedulerViewHitTest.Clear; begin inherited Clear; FNeedShowHint := False; FTime := NullDate; end; function TcxSchedulerViewHitTest.GetHitEvent: TcxSchedulerControlEvent; begin Result := nil; end; function TcxSchedulerViewHitTest.GetHitAtEvent: Boolean; begin Result := Event <> nil; end; { TcxEventSizingHelper } procedure TcxEventSizingHelper.BeginDrag; begin inherited BeginDrag; if IsValidTime then UpdateEventBounds; end; procedure TcxEventSizingHelper.DragOver(const P: TPoint; State: TDragState; var Accepted: Boolean); begin Accepted := IsValidTime; if HasChangedState and Accepted then UpdateEventBounds; Controller.CheckScrolling(P); end; procedure TcxEventSizingHelper.EndDrag(Accepted: Boolean); begin if Accepted then begin SetSelection; Events.PostEvent(Event); end else Scheduler.FullRefresh; end; function TcxEventSizingHelper.GetDragCursor(Accepted: Boolean): TCursor; //const // Cursors: array[Boolean] of TCursor = (crNoDrop, crSchedulerHorzResize); begin Result := crSchedulerHorzResize; // Result := Cursors[Accepted]; end; function TcxEventSizingHelper.IsValidTime: Boolean; begin with HitTest do Result := HitAtTime and (not HitAtResource or (FStartResource = Resource)); end; procedure TcxEventSizingHelper.CalcAllDayEvent; begin end; function TcxEventSizingHelper.GetFinishTime: TDateTime; begin Result := HitTest.Time; end; function TcxEventSizingHelper.GetStartTime: TDateTime; begin Result := HitTest.Time; end; procedure TcxEventSizingHelper.UpdateEventBounds; var AValue: TDateTime; begin CalcAllDayEvent; case Controller.DragKind of edkResizeStart: begin AValue := GetStartTime; if AValue > Event.Finish - Ord(Event.AllDayEvent) then AValue := Event.Finish - Ord(Event.AllDayEvent); Event.Start := AValue; end; edkResizeEnd: begin AValue := GetFinishTime; if AValue < Event.Start then AValue := Event.Start; Event.Finish := AValue + Ord(Event.AllDayEvent); end; end; RefreshCurrentView; end; function TcxEventSizingHelper.GetEvent: TcxSchedulerControlEvent; begin Result := TcxSchedulerViewController(Controller).DragEvent; end; function TcxEventSizingHelper.GetHitTest: TcxSchedulerViewHitTest; begin Result := TcxSchedulerViewHitTest(inherited HitTest); end; end.