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

2920 lines
100 KiB
ObjectPascal

{********************************************************************}
{ }
{ Developer Express Visual Component Library }
{ ExpressScheduler }
{ }
{ Copyright (c) 2003-2009 Developer Express Inc. }
{ ALL RIGHTS RESERVED }
{ }
{ The entire contents of this file is protected by U.S. and }
{ International Copyright Laws. Unauthorized reproduction, }
{ reverse-engineering, and distribution of all or any portion of }
{ the code contained in this file is strictly prohibited and may }
{ result in severe civil and criminal penalties and will be }
{ prosecuted to the maximum extent possible under the law. }
{ }
{ RESTRICTIONS }
{ }
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
{ LICENSED TO DISTRIBUTE THE EXPRESSSCHEDULER AND ALL ACCOMPANYING }
{ VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY. }
{ }
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
{ }
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
{ ADDITIONAL RESTRICTIONS. }
{ }
{********************************************************************}
unit cxSchedulerTimeGridView;
{$I cxVer.inc}
interface
uses
{$IFDEF DELPHI6}
Types, DateUtils,
{$ENDIF}
Windows, Forms, Classes, Math, StdCtrls, Graphics, Controls, ExtCtrls,
cxControls, cxEdit, cxGraphics, cxStyles, cxGeometry, Menus, dxCore,
cxLookAndFeelPainters, cxSchedulerCustomControls, cxSchedulerCustomResourceView,
cxSchedulerUtils, cxSchedulerStorage, cxSchedulerStrs, cxDateUtils, cxClasses,
cxDrawTextUtils, SysUtils;
const
htcMajorScale = $11;
htcMajorSeparator = $12;
htcMinorScale = $13;
htcSelectionBar = $14;
cxHorzEventIndent = 2;
cxMinutesPerDay = 60 * 24;
cxMinHourScale = 5;
cxMaxHourScale = 60;
cxMinColumnWidth = 15;
cxDefaultMinorUnitWidth = 50;
cxMinSelectionBarHeight = 5;
// TimeGrid styles
cxcsMajorScale = 0;
cxcsMajorScaleUnitSeparator = 1;
cxcsMinorScale = 3;
cxcsSelectionBar = 2;
cxcsMaxTimeGridStyle = cxcsSelectionBar;
type
TcxSchedulerTimeGridView = class;
TcxSchedulerTimeGridViewViewInfo = class;
TcxSchedulerTimeGridSelectionBarCell = class;
TcxSchedulerTimeGridMinorScaleCell = class;
TcxSchedulerTimeGridMajorScaleCell = class;
TcxSchedulerTimeBuilder = class;
TcxSchedulerTimeGridViewHitTest = class;
//
TcxSchedulerTimeGridScaleUnit = (suHour, suDay, suWeek, suMonth, suQuarter, suYear);
TcxSchedulerTimeGridScaleUnits = set of TcxSchedulerTimeGridScaleUnit;
TcxSchedulerTimeGridScaleTextType = (sttUnknown, sttShort, sttMiddle, sttLong);
{ TcxCustomWeekViewDragEventHelper }
TcxTimeGridDragEventHelper = class(TcxDragEventHelper)
private
function GetHitTest: TcxSchedulerTimeGridViewHitTest;
protected
procedure CorrectAllDayEventProperty;
function IsValidTime: Boolean; override;
procedure UpdateViewClonesTime; override;
property HitTest: TcxSchedulerTimeGridViewHitTest read GetHitTest;
end;
{ TcxTimeGridEventSizing }
TcxTimeGridEventSizing = class(TcxEventSizingHelper)
private
function GetTimeBuilder: TcxSchedulerTimeBuilder;
function GetHitTest: TcxSchedulerTimeGridViewHitTest;
protected
function IsValidTime: Boolean; override;
procedure UpdateEventBounds; override;
property HitTest: TcxSchedulerTimeGridViewHitTest read GetHitTest;
property TimeBuilder: TcxSchedulerTimeBuilder read GetTimeBuilder;
end;
{ TcxSchedulerTimeGridViewController }
TcxSchedulerTimeGridViewController = class(TcxSchedulerCustomResourceViewController)
private
FTimer: TTimer;
function GetHitTest: TcxSchedulerTimeGridViewHitTest;
function GetView: TcxSchedulerTimeGridView;
function GetViewInfo: TcxSchedulerTimeGridViewViewInfo;
protected
FPos: TPoint;
FIsEditingBeforeMouseDown: Boolean;
function CreateDragEventHelper: TcxDragEventHelper; override;
function CreateNavigation: TcxSchedulerViewNavigation; override;
function CreateResizeEventHelper: TcxEventSizingHelper; override;
// todo: scrolling timer (need move to CustomResourceView), and optimize day view
procedure BeforeMouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure CancelScroll; override;
procedure CheckScrolling(const APos: TPoint); override;
procedure InitTimer(AllowStart: Boolean; AScrollCode: TScrollCode);
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
procedure SyncEventSelection(AEvent: TcxSchedulerControlEvent); override;
procedure OnTimer(Sender: TObject);
property HitTest: TcxSchedulerTimeGridViewHitTest read GetHitTest;
property Timer: TTimer read FTimer;
property View: TcxSchedulerTimeGridView read GetView;
property ViewInfo: TcxSchedulerTimeGridViewViewInfo read GetViewInfo;
public
constructor Create(AOwner: TcxSchedulerSubControl); override;
destructor Destroy; override;
end;
{ TcxSchedulerTimeGridViewNavigation }
TcxSchedulerTimeGridViewNavigation = class(TcxSchedulerCustomResourceViewNavigation)
private
function GetTimeBuilder: TcxSchedulerTimeBuilder;
function GetView: TcxSchedulerTimeGridView;
function GetViewInfo: TcxSchedulerTimeGridViewViewInfo;
protected
property TimeBuilder: TcxSchedulerTimeBuilder read GetTimeBuilder;
property View: TcxSchedulerTimeGridView read GetView;
property ViewInfo: TcxSchedulerTimeGridViewViewInfo read GetViewInfo;
public
procedure KeyDown(var AKey: Word; AShift: TShiftState); override;
procedure ValidateSelection(var ASelStart, ASelFinish: TDateTime;
var AResource: TcxSchedulerStorageResourceItem); override;
end;
{ TcxSchedulerTimeGridViewStyles }
TcxSchedulerGetScaleItemStyleEvent = procedure(Sender: TObject;
const ADateTime: TDateTime; var AStyle: TcxStyle) of object;
TcxSchedulerTimeGridViewStyles = class(TcxStyles)
private
FScheduler: TcxCustomScheduler;
FOnGetMajorScaleParams: TcxSchedulerGetScaleItemStyleEvent;
FOnGetMinorScaleParams: TcxSchedulerGetScaleItemStyleEvent;
FOnGetSelectionBarParams: TcxSchedulerGetScaleItemStyleEvent;
function GetTimeGrid: TcxSchedulerTimeGridView;
protected
procedure Changed(AIndex: Integer); override;
procedure GetDefaultViewParams(Index: Integer; AData: TObject; out AParams: TcxViewParams); override;
function GetSelectionBarParamsEx(const ADateTime: TDateTime; ASelected: Boolean): TcxViewParams; virtual;
function IsTimeSelected(const ADateTime: TDateTime): Boolean;
public
constructor Create(AOwner: TPersistent); override;
procedure Assign(Source: TPersistent); override;
// time grid visual parameters
function GetMajorScaleParams(const ADateTime: TDateTime): TcxViewParams;
function GetMajorScaleUnitSeparatorParams: TcxViewParams;
function GetMinorScaleParams(const ADateTime: TDateTime): TcxViewParams;
function GetSelectionBarParams(const ADateTime: TDateTime): TcxViewParams;
property Scheduler: TcxCustomScheduler read FScheduler;
property TimeGrid: TcxSchedulerTimeGridView read GetTimeGrid;
published
property MajorScale: TcxStyle index cxcsMajorScale read GetValue write SetValue;
property MajorScaleUnitSeparator: TcxStyle index cxcsMajorScaleUnitSeparator read GetValue write SetValue;
property MinorScale: TcxStyle index cxcsMinorScale read GetValue write SetValue;
property SelectionBar: TcxStyle index cxcsSelectionBar read GetValue write SetValue;
property OnGetMajorScaleParams: TcxSchedulerGetScaleItemStyleEvent read FOnGetMajorScaleParams write FOnGetMajorScaleParams;
property OnGetMinorScaleParams: TcxSchedulerGetScaleItemStyleEvent read FOnGetMinorScaleParams write FOnGetMinorScaleParams;
property OnGetSelectionBarParams: TcxSchedulerGetScaleItemStyleEvent read FOnGetSelectionBarParams write FOnGetSelectionBarParams;
end;
{ TcxSchedulerTimeGridViewScales }
TcxSchedulerTimeGridViewScales = class(TPersistent)
private
FMajor: Boolean;
FMajorUnit: TcxSchedulerTimeGridScaleUnit;
FMajorUnitSeparatorWidth: Integer;
FMinor: Boolean;
FMinorUnit: TcxSchedulerTimeGridScaleUnit;
FMinorUnitWidth: Integer;
FOwner: TcxSchedulerTimeGridView;
FTimeStep: Integer;
function GetScheduler: TcxCustomScheduler;
procedure SetMajor(AValue: Boolean);
procedure SetMajorUnit(AValue: TcxSchedulerTimeGridScaleUnit);
procedure SetMajorUnitSeparatorWidth(AValue: Integer);
procedure SetMinor(AValue: Boolean);
procedure SetMinorUnit(AValue: TcxSchedulerTimeGridScaleUnit);
procedure SetMinorUnitWidth(AValue: Integer);
procedure SetTimeStep(AValue: Integer);
protected
procedure Changed; virtual;
function GetOwner: TPersistent; override;
public
constructor Create(AOwner: TcxSchedulerTimeGridView); virtual;
procedure Assign(Source: TPersistent); override;
property Scheduler: TcxCustomScheduler read GetScheduler;
property TimeGrid: TcxSchedulerTimeGridView read FOwner;
published
property Major: Boolean read FMajor write SetMajor default True;
property MajorUnit: TcxSchedulerTimeGridScaleUnit read FMajorUnit write SetMajorUnit default suDay;
property MajorUnitSeparatorWidth: Integer read FMajorUnitSeparatorWidth write SetMajorUnitSeparatorWidth default cxDefaultSplitterWidth;
property Minor: Boolean read FMinor write SetMinor default True;
property MinorUnit: TcxSchedulerTimeGridScaleUnit read FMinorUnit write SetMinorUnit default suHour;
property MinorUnitWidth: Integer read FMinorUnitWidth write SetMinorUnitWidth default cxDefaultMinorUnitWidth;
property TimeStep: Integer read FTimeStep write SetTimeStep default 30;
end;
{ TcxSchedulerTimeGridViewHitTest }
TcxSchedulerTimeGridViewHitTest = class(TcxSchedulerCustomResourceViewHitTest)
protected
function HitAtScale: Boolean;
public
property HitAtMajorScale: Boolean index htcMajorScale read GetBitState;
property HitAtMajorSeparator: Boolean index htcMajorSeparator read GetBitState;
property HitAtMinorScale: Boolean index htcMinorScale read GetBitState;
property HitAtSelectionBar: Boolean index htcSelectionBar read GetBitState;
end;
{ TcxSchedulerTimeGridView }
TcxSchedulerCustomDrawMajorUnitEvent = procedure(Sender: TObject; ACanvas: TcxCanvas;
AViewInfo: TcxSchedulerTimeGridMajorScaleCell; var ADone: Boolean) of object;
TcxSchedulerCustomDrawMinorUnitEvent = procedure(Sender: TObject; ACanvas: TcxCanvas;
AViewInfo: TcxSchedulerTimeGridMinorScaleCell; var ADone: Boolean) of object;
TcxSchedulerCustomDrawSelectionBarEvent = procedure(Sender: TObject; ACanvas: TcxCanvas;
AViewInfo: TcxSchedulerTimeGridSelectionBarCell; var ADone: Boolean) of object;
TcxSchedulerTimeGridViewGetUnitDisplayTextEvent = procedure(Sender: TcxSchedulerTimeGridView;
const AStart, AFinish: TDateTime; ATextType: TcxSchedulerTimeGridScaleTextType; var AText: string) of object;
TcxSchedulerTimeGridView = class(TcxSchedulerCustomResourceView)
private
FEventMaxLineCount: Integer;
FScales: TcxSchedulerTimeGridViewScales;
FEventDetailInfo: Boolean;
FStyles: TcxSchedulerTimeGridViewStyles;
FVisibleFinish: TDateTime;
FVisibleStart: TDateTime;
FWorkDaysOnly: Boolean;
FWorkTimeOnly: Boolean;
FOnCustomDrawMajorUnit: TcxSchedulerCustomDrawMajorUnitEvent;
FOnCustomDrawMinorUnit: TcxSchedulerCustomDrawMinorUnitEvent;
FOnCustomDrawSelectionBar: TcxSchedulerCustomDrawSelectionBarEvent;
FOnGetMajorUnitDisplayText: TcxSchedulerTimeGridViewGetUnitDisplayTextEvent;
FOnGetMinorUnitDisplayText: TcxSchedulerTimeGridViewGetUnitDisplayTextEvent;
function GetHitTest: TcxSchedulerTimeGridViewHitTest;
function GetViewInfo: TcxSchedulerTimeGridViewViewInfo;
procedure SetEventMaxLineCount(AValue: Integer);
procedure SetScales(AValue: TcxSchedulerTimeGridViewScales);
procedure SetEventDetailInfo(AValue: Boolean);
procedure SetStyles(AValue: TcxSchedulerTimeGridViewStyles);
procedure SetVisibleStart(AValue: TDateTime);
procedure SetWorkDaysOnly(AValue: Boolean);
procedure SetWorkTimeOnly(AValue: Boolean);
protected
FLockSelectionUpdate: Boolean;
FScrollPosition: Integer;
FScrollUpdateLocked: Boolean;
ScaleTextType: TcxSchedulerTimeGridScaleTextType;
function CanDeactivateOnDateNavigatorSelectionChange: Boolean; override;
function CanSelectPeriod: Boolean; override;
procedure Changed; override;
procedure CheckRefresh;
function CreateController: TcxSchedulerSubControlController; override;
function CreateHitTest: TcxSchedulerSubControlHitTest; override;
function CreatePainter: TcxSchedulerSubControlPainter; override;
function CreateScales: TcxSchedulerTimeGridViewScales; virtual;
function CreateStyles: TcxSchedulerTimeGridViewStyles; virtual;
function CreateViewInfo: TcxSchedulerSubControlViewInfo; override;
procedure DoDrawSelectionBarCell(AItem: TcxSchedulerTimeGridSelectionBarCell; var ADone: Boolean); virtual;
procedure DoDrawTimeLineCell(AItem: TcxSchedulerTimeGridMinorScaleCell; var ADone: Boolean); virtual;
procedure DoDrawTimeLineHeaderCell(AItem: TcxSchedulerTimeGridMajorScaleCell; var ADone: Boolean); virtual;
procedure DoGetMajorUnitDisplayText(const AStart, AFinish: TDateTime;
ATextType: TcxSchedulerTimeGridScaleTextType; var AText: string); virtual;
procedure DoGetMinorUnitDisplayText(const AStart, AFinish: TDateTime;
ATextType: TcxSchedulerTimeGridScaleTextType; var AText: string); virtual;
function GetCompressWeekEnd: Boolean; override;
function GetEditWithSingleLineEditor(AEvent: TcxSchedulerControlEvent): Boolean; override;
function GetFirstVisibleDate: TDateTime; override;
function GetLastVisibleDate: TDateTime; override;
function GetTimeIncrement: TDateTime; override;
function GetViewContentRect: TRect; override;
procedure InitScrollBarsParameters; override;
procedure MakeEventVisible(AEvent: TcxSchedulerControlEvent;
const ADate: TDateTime; AResource: TcxSchedulerStorageResourceItem); override;
procedure ScaleChanged; virtual;
procedure Scroll(AScrollBarKind: TScrollBarKind;
AScrollCode: TScrollCode; var AScrollPos: Integer); override;
procedure SelectedDaysChanged; override;
procedure UpdateDateNavigatorSelection;
procedure ValidateSelectionFinishTime(var ADateTime: TDateTime); override;
procedure VisibleChanged; override;
//
property ViewInfo: TcxSchedulerTimeGridViewViewInfo read GetViewInfo;
public
constructor Create(AOwner: TcxCustomScheduler); override;
destructor Destroy; override;
procedure Assign(Source: TPersistent); override;
function GetMajorUnitDisplayText(const AStart, AFinish: TDateTime;
ATextType: TcxSchedulerTimeGridScaleTextType): string;
function GetMinorUnitDisplayText(const AStart, AFinish: TDateTime;
ATextType: TcxSchedulerTimeGridScaleTextType): string;
property HitTest: TcxSchedulerTimeGridViewHitTest read GetHitTest;
property VisibleFinish: TDateTime read FVisibleFinish;
property VisibleStart: TDateTime read FVisibleStart write SetVisibleStart;
published
property Active;
property EventImagesLayout default eilAuto;
property EventMaxLineCount: Integer read FEventMaxLineCount write SetEventMaxLineCount default 0;
property Scales: TcxSchedulerTimeGridViewScales read FScales write SetScales;
property Styles: TcxSchedulerTimeGridViewStyles read FStyles write SetStyles;
property EventDetailInfo: Boolean read FEventDetailInfo write SetEventDetailInfo default False;
property ShowTimeAsClock;
property WorkDaysOnly: Boolean read FWorkDaysOnly write SetWorkDaysOnly default False;
property WorkTimeOnly: Boolean read FWorkTimeOnly write SetWorkTimeOnly default False;
property OnCustomDrawMajorUnit: TcxSchedulerCustomDrawMajorUnitEvent read FOnCustomDrawMajorUnit write FOnCustomDrawMajorUnit;
property OnCustomDrawMinorUnit: TcxSchedulerCustomDrawMinorUnitEvent read FOnCustomDrawMinorUnit write FOnCustomDrawMinorUnit;
property OnCustomDrawSelectionBar: TcxSchedulerCustomDrawSelectionBarEvent read FOnCustomDrawSelectionBar write FOnCustomDrawSelectionBar;
property OnGetMajorUnitDisplayText: TcxSchedulerTimeGridViewGetUnitDisplayTextEvent read FOnGetMajorUnitDisplayText write FOnGetMajorUnitDisplayText;
property OnGetMinorUnitDisplayText: TcxSchedulerTimeGridViewGetUnitDisplayTextEvent read FOnGetMinorUnitDisplayText write FOnGetMinorUnitDisplayText;
end;
{ TcxSchedulerTimeBuilder }
TcxSchedulerTimeBuilder = class
protected
CheckTime: Boolean;
CheckDays: Boolean;
MajorUnit: TcxSchedulerTimeGridScaleUnit;
MinorUnit: TcxSchedulerTimeGridScaleUnit;
TimeScale: Integer;
ScaleUnit: TDateTime;
WorkDays: TDays;
WorkFinish: TDateTime;
WorkStart: TDateTime;
function CalculateDateTime(const ADateTime: TDateTime; AInc: Integer): TDateTime;
function CalculateScaleUnit(const AScaleUnit: Integer): Integer;
procedure CalculateWorkTime(AIsWorkTimeOnly: Boolean; var AWorkStart, AWorkFinish: TDateTime);
procedure CalculateWorkDays(AIsWorkDaysOnly: Boolean; var AWorkDays: TDays);
function RoundTime(const ADateTime: TDateTime): TDateTime;
procedure ValidateTime(var ADateTime: TDateTime; AGoForward: Boolean; AInc: Integer = 1);
procedure ValidateUnits(var AMajorUnit, AMinorUnit: TcxSchedulerTimeGridScaleUnit);
procedure ValidateVisibleStart(var ADateTime: TDateTime);
public
procedure Assign(AView: TcxSchedulerTimeGridView); virtual;
procedure CalculateActualStart(var ActualStart, AVisibleStart: TDateTime;
var AStartIndex: Integer);
procedure CheckWorkDays(var ADateTime: TDateTime; AGoForward: Boolean);
function Dec(const ADateTime: TDateTime): TDateTime;
function Inc(const ADateTime: TDateTime): TDateTime;
function IsPeriodChanged(const AFirst, ANext: TDateTime): Boolean;
function TimeCorrected(var AStart, AFinish: TDateTime; AGoForward: Boolean = True): Boolean;
function TimeMode: Boolean;
end;
{ TcxSchedulerTimeGridViewEventCellViewInfo }
TcxSchedulerTimeGridViewEventCellViewInfo = class(TcxSchedulerEventCellViewInfo)
protected
procedure CalculateCaptions; override;
procedure CalculateDetailInfo; override;
procedure CalculateEventTimeAsClockLayout(const ABounds: TRect;
const ACaptionWidth, AImagesWidth: Integer; var ALeft: Integer); override;
procedure CalculateEventTimeVisibility; override;
function CalculateNonDetailEventImages(const ACaptionWidth: Integer;
out AImagesWidth: Integer): TRect; override;
procedure CalculateItemsLayout; override;
procedure CalculateShowTimeAsClock; override;
function GetEditingRect: TRect; override;
procedure InitHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest); override;
end;
{ TcxSchedulerTimeGridViewViewInfo }
TcxSchedulerTimeGridViewViewInfo = class(TcxSchedulerCustomResourceViewViewInfo)
private
function GetTimeGridView: TcxSchedulerTimeGridView;
// calculate scales items
procedure CalculateMajorScale;
procedure CalculateMinorScale;
procedure CalculateSelectionBar;
protected
FActualStartTime: TDateTime;
FColumnCount: Integer;
FColumnsInMinorUnit: Integer;
FColumnWidth: Integer;
FEventRowHeight: Integer;
FFirstVisibleIndex: Integer;
FLastVisibleTime: TDateTime;
FMajorScaleHeight: Integer;
FMajorTextType: TcxSchedulerTimeGridScaleTextType;
FMinorScaleHeight: Integer;
FMinorTextType: TcxSchedulerTimeGridScaleTextType;
FResourceHeaderWidth: Integer;
FScales: TcxSchedulerTimeGridViewScales;
FScalesBounds: TRect;
FScalesHeight: Integer;
FScaleUnit: TDateTime;
FSelectionBarHeight: Integer;
FSeparatorWidth: Integer;
FTimeBuilder: TcxSchedulerTimeBuilder;
FTimeLineCells: TcxSchedulerViewInfoCellList;
FVisibleColumnCount: Integer;
procedure AddEventForCalculation(ABuilder: TcxSchedulerEventLayoutBuilder;
AEvent: TcxSchedulerControlEvent; AResourceIndex: Integer);
function AddEventViewInfo(APlace: TcxSchedulerEventPlace; AResourceIndex: Integer;
const AStart, AFinish: TDateTime): TcxSchedulerEventCellViewInfo;
procedure AddMajorScaleCell(ABounds: TRect; const AStart, AFinish: TDateTime); virtual;
procedure AddMajorSeparator(var ALeft: Integer);
procedure AddMinorScaleCell(const ABounds: TRect; const AStart, AFinish: TDateTime); virtual;
function AddSelectionBarCell(const ABounds: TRect;
const AStart, AFinish: TDateTime): TcxSchedulerTimeGridSelectionBarCell; virtual;
procedure AddTimeLineItem(AClass: TcxSchedulerCustomViewInfoItemClass; const ABounds: TRect;
AType: Byte; const AStart, AFinish: TDateTime; const AViewParams: TcxViewParams; var Instance);
procedure AdjustTextType;
procedure CalculateContentCells; virtual;
procedure CalculateEventPosition(AEvent: TcxSchedulerControlEvent;
AColIndex: Integer; out AStartX, AFinishX: Integer; out AStart, AFinish: TDateTime);
procedure CalculateEvents; virtual;
procedure CalculateMetrics; override;
procedure CalculateResourceHeaderCells; virtual;
procedure CalculateResourceHeadersAutoHeight(AWidth: Integer); override;
procedure CalculateScales; virtual;
procedure CalculateScalesHeight;
procedure CheckEventVisibility(ACell: TcxSchedulerEventCellViewInfo; AIndex: Integer);
function CheckFinishTime(const ATime: TDateTime; AUnit: TcxSchedulerTimeGridScaleUnit): TDateTime; virtual;
procedure Clear; override;
function CreateEventCellViewInfo(AViewData: TcxSchedulerEventViewData): TcxSchedulerEventCellViewInfo; override;
procedure DoCalculate; override;
function IsColumnEvent(AEvent: TcxSchedulerControlEvent; AColumnIndex: Integer): Boolean;
function GetContentParams(const ATime: TDateTime;
AResource: TcxSchedulerResourceViewInfo): TcxViewParams; override;
procedure GetItemInfo(AIndex1, AIndex2, ATop, AHeight: Integer;
var ABounds: TRect; var AStart, AFinish: TDateTime);
function GetResourceImagesSize: TSize; override;
function GetResourcesContentWidth: Integer; override;
function GetResourceScrollBarKind: TScrollBarKind; override;
function GetStyleFont(AStyle: TcxStyle): TFont;
procedure MakeTimeVisible(const ATime: TDateTime); override;
function MeasureFontHeight(AStyle: TcxStyle; AHeight: Integer; Borders: TcxBorders): Integer;
procedure Realign(APlace: TcxSchedulerEventPlace);
procedure ValidateStartTime;
public
constructor Create(AOwner: TcxSchedulerSubControl); override;
destructor Destroy; override;
procedure CalculateHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest); override;
property ActualStartTime: TDateTime read FActualStartTime;
property ColumnCount: Integer read FColumnCount;
property FirstVisibleIndex: Integer read FFirstVisibleIndex;
property MajorTextType: TcxSchedulerTimeGridScaleTextType read FMajorTextType;
property MinorTextType: TcxSchedulerTimeGridScaleTextType read FMinorTextType;
property Scales: TcxSchedulerTimeGridViewScales read FScales;
property ScalesHeight: Integer read FScalesHeight;
property ScaleUnit: TDateTime read FScaleUnit;
property TimeBuilder: TcxSchedulerTimeBuilder read FTimeBuilder;
property TimeLineCells: TcxSchedulerViewInfoCellList read FTimeLineCells;
property ResourceHeaderWidth: Integer read FResourceHeaderWidth;
property VisibleColumnCount: Integer read FVisibleColumnCount;
property View: TcxSchedulerTimeGridView read GetTimeGridView;
end;
{ TcxSchedulerTimeGridScaleCell }
TcxSchedulerTimeGridScaleCell = class(TcxSchedulerCustomViewInfoItem)
private
FAlignHorz: TAlignment;
FAlignVert: TcxAlignmentVert;
FBorderColor: TColor;
protected
FTimeFinish: TDateTime;
ItemType: Integer;
property AlignHorz: TAlignment read FAlignHorz write FAlignHorz;
property AlignVert: TcxAlignmentVert read FAlignVert write FAlignVert;
property BorderColor: TColor read FBorderColor write FBorderColor;
property TimeFinish: TDateTime read FTimeFinish;
property TimeStart: TDateTime read FDateTime;
public
constructor Create(APainter: TcxCustomLookAndFeelPainterClass;
const ABounds, AVisibleRect: TRect; const AViewParams: TcxViewParams); override;
end;
{ TcxSchedulerTimeGridMinorScaleCell }
TcxSchedulerTimeGridMinorScaleCell = class(TcxSchedulerTimeGridScaleCell)
protected
FHideDisplayText: Boolean;
FTextBounds: TRect;
procedure Calculate; virtual;
procedure DoDraw; override;
procedure DrawContent;
procedure InitHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest); override;
public
property AlignHorz;
property AlignVert;
property BorderColor;
property DisplayText;
property TimeFinish;
property TimeStart;
end;
{ TcxSchedulerTimeGridMajorScaleCell }
TcxSchedulerTimeGridMajorScaleCell = class(TcxSchedulerTimeGridMinorScaleCell)
protected
FRightIndent: Integer;
procedure Calculate; override;
procedure DoDraw; override;
procedure InitHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest); override;
public
property DisplayText;
property HideDisplayText: Boolean read FHideDisplayText write FHideDisplayText;
property RightIndent: Integer read FRightIndent;
end;
{ TcxSchedulerTimeGridSelectionBarCell }
TcxSchedulerTimeGridSelectionBarCell = class(TcxSchedulerTimeGridMinorScaleCell)
protected
FSelected: Boolean;
procedure Calculate; override;
procedure DoDraw; override;
procedure InitHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest); override;
public
property Selected: Boolean read FSelected;
end;
{ TcxSchedulerMajorSeparatorCellViewInfo }
TcxSchedulerMajorSeparatorCellViewInfo = class(TcxSchedulerGroupSeparatorCellViewInfo)
protected
FContentBounds: TRect;
procedure DoDraw; override;
procedure InitHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest); override;
public
property ContentBounds: TRect read FContentBounds;
end;
{ TcxSchedulerTimeGridViewPainter }
TcxSchedulerTimeGridViewPainter = class(TcxSchedulerCustomViewPainter)
private
FView: TcxSchedulerTimeGridView;
function GetViewInfo: TcxSchedulerTimeGridViewViewInfo;
protected
procedure DrawTimeLineCellItem(AItem: TcxSchedulerCustomViewInfoItem; var ADone: Boolean); virtual;
//
public
procedure Paint; override;
property View: TcxSchedulerTimeGridView read FView;
property ViewInfo: TcxSchedulerTimeGridViewViewInfo read GetViewInfo;
end;
const
ValidMinorUnits: array[TcxSchedulerTimeGridScaleUnit] of TcxSchedulerTimeGridScaleUnits =
([], [suHour], [suDay], [suDay], [suDay, suMonth], [suDay, suMonth, suQuarter]);
// unit caption text formats
WeekTextFormats: array[TcxSchedulerTimeGridScaleTextType] of string =
('mmmm dd, yyyy', 'mmm dd, yy', 'mmmm dd, yy', 'mmmm dd, yyyy');
MonthTextFormats: array[TcxSchedulerTimeGridScaleTextType] of string =
('mmmm, yyyy', 'mm, yy', 'mmm, yy', 'mmmm, yyyy');
QuarterTextFormats: array[TcxSchedulerTimeGridScaleTextType, 0..3] of string =
(('Q1{ ''yy}', 'Q2{ ''yy}', 'Q3{ ''yy}', 'Q4{ ''yy}'),
('Q1{ ''yy}', 'Q2{ ''yy}', 'Q3{ ''yy}', 'Q4{ ''yy}'),
('Q1{ ''yyyy}', 'Q2{ ''yyyy}', 'Q3 ''{yyyy}', 'Q4{ ''yyyy}'),
('1st Quarter{, yyyy}', '2nd Quarter{, yyyy}',
'3rd Quarter{, yyyy}', '4th Quarter{, yyyy}'));
YearTextFormats: array[0..1] of string = ('yyyy', 'yy');
implementation
const
DefaultBorders = [bRight, bBottom];
Direction: array[Boolean] of Integer = (-1, 1);
ScrollMaxPos: Integer = 50;
ScrollPage: Integer = 5;
function cxTimeLineCellsCompare(ACell1, ACell2: TcxSchedulerTimeGridMinorScaleCell): Integer;
begin
Result := ACell2.Bounds.Top - ACell1.Bounds.Top;
if Result = 0 then
Result := ACell2.Bounds.Left - ACell1.Bounds.Left;
end;
function GetQuarterAsText(ATextType: TcxSchedulerTimeGridScaleTextType;
const ADateTime: TDateTime; AIncludeYear: Boolean = False): string;
var
I, J, K: Integer;
AYear: string;
ValidYearFormat: Boolean;
const
UnusedChars = [' ', '''', ',', '_'];
begin
Result := QuarterTextFormats[ATextType, (MonthOf(ADateTime) - 1) div 3];
I := Pos('{', Result);
J := Pos('}', Result);
ValidYearFormat := (I > 0) and (J > 0) and (J > I);
if ValidYearFormat then
begin
if AIncludeYear then
begin
Delete(Result, J, 1);
Delete(Result, I, 1);
for K := 0 to High(YearTextFormats) do
begin
I := Pos(YearTextFormats[K], Result);
if I = 0 then Continue;
AYear := FormatDateTime(YearTextFormats[K], ADateTime);
Delete(Result, I, Length(YearTextFormats[K]));
Insert(AYear, Result, I);
Break;
end
end
else
Delete(Result, I, J - I + 1);
end;
end;
function GetMinorCellDisplayText(ATextType: TcxSchedulerTimeGridScaleTextType;
AScale, AMajorScale: TcxSchedulerTimeGridScaleUnit; const AStart, AFinish: TDateTime): string;
begin
case AScale of
suHour:
Result := DateTimeHelper.HourToStr(TimeOf(AStart));
suDay:
begin
if ATextType in [sttLong, sttUnknown] then
Result := DateTimeHelper.DateToLongDateStr(AStart)
else
if AMajorScale <= suMonth then
Result := FormatDateTime('d ddd', AStart)
else
Result := FormatDateTime('d/m', AStart);
end;
suWeek:
Result := GetMinorCellDisplayText(ATextType, suDay, AMajorScale, AStart, AStart) + '-'
+ GetMinorCellDisplayText(ATextType, suDay, AMajorScale, AFinish, AFinish);
suMonth:
Result := LongMonthNames[MonthOf(AStart)];//
suQuarter:
Result := GetQuarterAsText(ATextType, AStart);
suYear:
Result := IntToStr(YearOf(AStart));
else
Result := '';
end;
end;
function GetMajorCellDisplayText(ATextType: TcxSchedulerTimeGridScaleTextType;
AScale: TcxSchedulerTimeGridScaleUnit; const AStart, AFinish: TDateTime): string;
begin
case AScale of
suDay:
if ATextType = sttLong then
Result := DateTimeHelper.DateToLongDateStr(AStart)
else
Result := DateTimeHelper.DateToLongDateStr(AStart);
suWeek:
Result := FormatDateTime(WeekTextFormats[ATextType], AStart) +
' - ' + FormatDateTime(WeekTextFormats[ATextType], AFinish);
suMonth:
Result := FormatDateTime(MonthTextFormats[ATextType], AStart);
suQuarter:
Result := GetQuarterAsText(ATextType, AStart, True);
suYear:
Result := GetMinorCellDisplayText(ATextType, suYear, suYear, AStart, AFinish);
else
Result := '';
end;
end;
{ TcxTimeGridDragEventHelper }
procedure TcxTimeGridDragEventHelper.CorrectAllDayEventProperty;
var
I: Integer;
AEvent: TcxSchedulerControlEvent;
ASaveStart, ASaveFinish: TDateTime;
AllDay: Boolean;
begin
for I := 0 to Clones.Count - 1 do
begin
AEvent := Clones[I];
with AEvent do
begin
AllDay := (TimeOf(Start) = 0) and (TimeOf(Finish) = 0) and (Duration >= 1);
if AllDay <> AllDayEvent then
begin
if AllDayEvent then
begin
ASaveStart := Start;
ASaveFinish := Finish;
AllDayEvent := False;
Start := ASaveStart;
Finish := ASaveFinish;
end
else
AllDayEvent := True;
CheckEventState(AEvent);
end;
end;
end;
end;
function TcxTimeGridDragEventHelper.GetHitTest: TcxSchedulerTimeGridViewHitTest;
begin
Result := TcxSchedulerTimeGridViewHitTest(inherited HitTest);
end;
function TcxTimeGridDragEventHelper.IsValidTime: Boolean;
begin
Result := not HitTest.HitAtMajorScale and inherited IsValidTime;
end;
procedure TcxTimeGridDragEventHelper.UpdateViewClonesTime;
var
I: Integer;
ADelta: TDateTime;
begin
ADelta := Controller.StartDragHitTime - HitTest.Time;
for I := 0 to Clones.Count - 1 do
with Clones[I] do
MoveTo(Source.Start - ADelta);
CorrectAllDayEventProperty;
end;
{ TcxTimeGridEventSizing }
function TcxTimeGridEventSizing.IsValidTime: Boolean;
begin
Result := not HitTest.HitAtMajorScale and inherited IsValidTime;
end;
procedure TcxTimeGridEventSizing.UpdateEventBounds;
var
AllDayEvent: Boolean;
ATime, ASaveTime: TDateTime;
begin
ATime := HitTest.Time;
if Controller.DragKind = edkResizeStart then
begin
ATime := Min(ATime, Event.Finish);
AllDayEvent := (TimeOf(Event.Finish) = 0) and (TimeOf(ATime) = 0) and
(Event.Duration >= 1);
if AllDayEvent <> Event.AllDayEvent then
begin
if Event.AllDayEvent then
begin
ASaveTime := Event.Finish;
Event.AllDayEvent := AllDayEvent;
Event.Finish := ASaveTime;
end
else
Event.AllDayEvent := True;
CheckEventState(Event);
end;
Event.Start := ATime;
end
else
begin
ATime := Max(Event.Start, TimeBuilder.Inc(ATime));
AllDayEvent := (TimeOf(Event.Start) = 0) and (TimeOf(ATime) = 0) and
(Event.Duration >= 1);
if AllDayEvent <> Event.AllDayEvent then
begin
if Event.AllDayEvent then
begin
ASaveTime := Event.Start;
Event.AllDayEvent := AllDayEvent;
Event.Start := ASaveTime;
end
else
Event.AllDayEvent := True;
CheckEventState(Event);
end;
Event.Finish := ATime;
end;
RefreshCurrentView;
end;
function TcxTimeGridEventSizing.GetHitTest: TcxSchedulerTimeGridViewHitTest;
begin
Result := TcxSchedulerTimeGridViewHitTest(inherited HitTest);
end;
function TcxTimeGridEventSizing.GetTimeBuilder: TcxSchedulerTimeBuilder;
begin
Result := TcxSchedulerTimeGridView(Scheduler.CurrentView).ViewInfo.TimeBuilder;
end;
{ TcxSchedulerTimeGridViewController }
constructor TcxSchedulerTimeGridViewController.Create(AOwner: TcxSchedulerSubControl);
begin
inherited Create(AOwner);
FTimer := TTimer.Create(nil);
FTimer.Enabled := False;
end;
destructor TcxSchedulerTimeGridViewController.Destroy;
begin
FTimer.Free;
inherited Destroy;
end;
function TcxSchedulerTimeGridViewController.CreateDragEventHelper: TcxDragEventHelper;
begin
Result := TcxTimeGridDragEventHelper.Create(Scheduler);
end;
function TcxSchedulerTimeGridViewController.CreateNavigation: TcxSchedulerViewNavigation;
begin
Result := TcxSchedulerTimeGridViewNavigation.Create(View);
end;
function TcxSchedulerTimeGridViewController.CreateResizeEventHelper: TcxEventSizingHelper;
begin
Result := TcxTimeGridEventSizing.Create(Scheduler);
end;
procedure TcxSchedulerTimeGridViewController.BeforeMouseDown(
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
FIsEditingBeforeMouseDown := IsEditing;
inherited BeforeMouseDown(Button, Shift, X, Y);
end;
procedure TcxSchedulerTimeGridViewController.CancelScroll;
begin
InitTimer(False, scEndScroll);
end;
procedure TcxSchedulerTimeGridViewController.CheckScrolling(const APos: TPoint);
var
ACanScroll: Boolean;
AScrollCode: TScrollCode;
R: TRect;
begin
R := ViewInfo.Bounds;
Inc(R.Top, ViewInfo.FScalesHeight);
Inc(R.Left, ViewInfo.FResourceHeaderWidth);
FPos := APos;
ACanScroll := cxRectPtIn(R, APos);
AScrollCode := TScrollCode(Timer.Tag);
if APos.X < (R.Left + cxScrollZoneSize) then
AScrollCode := scLineUp
else
if APos.X >= (R.Right - cxScrollZoneSize) then
AScrollCode := scLineDown
else
ACanScroll := False;
if (ACanScroll <> Timer.Enabled) or (Integer(AScrollCode) <> Timer.Tag) then
InitTimer(ACanScroll, AScrollCode);
end;
procedure TcxSchedulerTimeGridViewController.InitTimer(
AllowStart: Boolean; AScrollCode: TScrollCode);
begin
if AllowStart and FIsEditingBeforeMouseDown then
begin
FIsEditingBeforeMouseDown := False;
AllowStart := False;
end;
if not AllowStart then
Timer.OnTimer := nil
else
Timer.OnTimer := OnTimer;
Timer.Enabled := AllowStart;
Timer.Interval := cxScrollInterval;
Timer.Tag := Integer(AScrollCode);
end;
procedure TcxSchedulerTimeGridViewController.MouseDown(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
inherited MouseDown(Button, Shift, X, Y);
if CanProcessMouseMove and (Button = mbLeft) then
CheckScrolling(cxPoint(X, Y))
end;
procedure TcxSchedulerTimeGridViewController.MouseMove(
Shift: TShiftState; X, Y: Integer);
begin
if (DragKind = edkNone) and HitTest.HitAtScale and HitTest.HitAtTime then
HitTest.FResource := Scheduler.SelResource;
inherited MouseMove(Shift, X, Y);
if CanProcessMouseMove and (ssLeft in Shift) then
CheckScrolling(cxPoint(X, Y))
end;
procedure TcxSchedulerTimeGridViewController.SyncEventSelection(
AEvent: TcxSchedulerControlEvent);
var
AStart, AFinish: TDateTime;
AViewInfo: tcxSchedulerEventCellViewInfo;
AResourceItem: TcxSchedulerStorageResourceItem;
begin
AResourceItem := nil;
if HitTest.HitAtResource then
AResourceItem := HitTest.Resource;
if HitTest.HitAtEvent and (HitTest.EventCell <> nil) and (HitTest.Event = AEvent) then
AViewInfo := HitTest.EventCell
else
if not View.FindEventViewInfo(AEvent.Source, AEvent.Start, AEvent.GetResourceItem, AViewInfo) then
AViewInfo := nil;
if AViewInfo <> nil then
begin
AStart := AViewInfo.ContentStart;
AFinish := AViewInfo.ContentFinish - View.GetTimeIncrement;
if View.WorkDaysOnly then
ViewInfo.TimeBuilder.CheckWorkDays(AFinish, False);
if AResourceItem = nil then
AResourceItem := AEvent.GetResourceItem;
TcxSchedulerTimeGridViewNavigation(Navigation).ReplaceSelParams(
AStart, AFinish, AResourceItem);
end
else
inherited SyncEventSelection(AEvent);
end;
procedure TcxSchedulerTimeGridViewController.OnTimer(Sender: TObject);
function GetShiftState: TShiftState;
const
Buttons: array[Boolean] of Integer = (VK_LBUTTON, VK_RBUTTON);
begin
Result := [];
if GetAsyncKeyState(Buttons[GetSystemMetrics(SM_SWAPBUTTON) <> 0]) < 0 then
Include(Result, ssLeft);
if GetAsyncKeyState(VK_CONTROL) < 0 then
Include(Result, ssCtrl);
end;
var
APos: Integer;
AShift: TShiftState;
begin
AShift := GetShiftState;
if not (ssLeft in AShift) then
begin
CancelScroll;
SetCaptureControl(nil);
end
else
begin
APos := View.FScrollPosition;
View.Scroll(sbHorizontal, TScrollCode(Timer.Tag), APos);
MouseMove(AShift, FPos.X, FPos.Y);
if (DragKind in [edkResizeStart, edkResizeEnd]) then
CheckUpdateEventBounds;
end;
end;
function TcxSchedulerTimeGridViewController.GetHitTest: TcxSchedulerTimeGridViewHitTest;
begin
Result := TcxSchedulerTimeGridViewHitTest(inherited HitTest);
end;
function TcxSchedulerTimeGridViewController.GetView: TcxSchedulerTimeGridView;
begin
Result := TcxSchedulerTimeGridView(inherited View);
end;
function TcxSchedulerTimeGridViewController.GetViewInfo: TcxSchedulerTimeGridViewViewInfo;
begin
Result := View.ViewInfo;
end;
{ TcxSchedulerTimeGridViewNavigation }
procedure TcxSchedulerTimeGridViewNavigation.KeyDown(
var AKey: Word; AShift: TShiftState);
var
AFinish: TDateTime;
begin
case AKey of
VK_LEFT, VK_RIGHT:
with TimeBuilder do
begin
AFinish := CalculateDateTime(FCurrentAnchor, Direction[AKey = VK_RIGHT]);
if CheckTime and (((AFinish > SelAnchor) and (RoundTime(TimeOf(AFinish)) = WorkFinish)) or
IsPeriodChanged(AFinish, FCurrentAnchor)) then
AFinish := CalculateDateTime(AFinish, Direction[AKey = VK_RIGHT]);
TimeBuilder.CheckWorkDays(AFinish, AKey = VK_RIGHT);
ViewInfo.MakeTimeVisible(AFinish);
SetSelAnchor(AFinish, AShift, FCurrentResource);
end;
VK_HOME:
SetSelAnchor(View.VisibleStart, AShift, FCurrentResource);
VK_END:
SetSelAnchor(View.VisibleFinish, AShift, FCurrentResource);
VK_UP, VK_DOWN:
if not (ssShift in AShift) and (GetNextResource(AKey = VK_DOWN) <> FCurrentResource) then
SetSelAnchor(FCurrentAnchor, AShift, GetNextResource(AKey = VK_DOWN))
else
if ScrollResourcesEx(AKey = VK_DOWN, FCurrentResource) then
ReplaceSelParams(FCurrentResource);
end;
View.CheckRefresh;
end;
procedure TcxSchedulerTimeGridViewNavigation.ValidateSelection(
var ASelStart, ASelFinish: TDateTime;
var AResource: TcxSchedulerStorageResourceItem);
begin
if ASelStart = NullDate then
begin
ASelStart := View.VisibleStart;
ASelFinish := ASelStart;
end;
TimeBuilder.ValidateTime(ASelStart, True, 0);
TimeBuilder.ValidateTime(ASelFinish, True, 0);
TimeBuilder.CheckWorkDays(ASelStart, True);
TimeBuilder.CheckWorkDays(ASelFinish, True);
end;
function TcxSchedulerTimeGridViewNavigation.GetTimeBuilder: TcxSchedulerTimeBuilder;
begin
Result := ViewInfo.TimeBuilder;
end;
function TcxSchedulerTimeGridViewNavigation.GetView: TcxSchedulerTimeGridView;
begin
Result := TcxSchedulerTimeGridView(inherited View);
end;
function TcxSchedulerTimeGridViewNavigation.GetViewInfo: TcxSchedulerTimeGridViewViewInfo;
begin
Result := View.ViewInfo;
end;
{ TcxSchedulerTimeGridViewStyles }
constructor TcxSchedulerTimeGridViewStyles.Create(AOwner: TPersistent);
begin
inherited Create(AOwner);
FScheduler := TimeGrid.Scheduler;
BitmapInViewParams := True;
end;
procedure TcxSchedulerTimeGridViewStyles.Assign(Source: TPersistent);
var
I: Integer;
begin
if Source is TcxSchedulerTimeGridViewStyles then
for I := 0 to cxcsMaxTimeGridStyle do
SetValue(I, TcxSchedulerTimeGridViewStyles(Source).GetValue(I));
inherited Assign(Source);
end;
function TcxSchedulerTimeGridViewStyles.GetMajorScaleParams(
const ADateTime: TDateTime): TcxViewParams;
var
AStyle: TcxStyle;
begin
AStyle := nil;
if Assigned(FOnGetMajorScaleParams) then
FOnGetMajorScaleParams(TimeGrid, ADateTime, AStyle);
GetViewParams(cxcsMajorScale, nil, AStyle, Result);
end;
function TcxSchedulerTimeGridViewStyles.GetMajorScaleUnitSeparatorParams: TcxViewParams;
begin
GetViewParams(cxcsMajorScaleUnitSeparator, nil, nil, Result);
end;
function TcxSchedulerTimeGridViewStyles.GetMinorScaleParams(
const ADateTime: TDateTime): TcxViewParams;
var
AStyle: TcxStyle;
begin
AStyle := nil;
if Assigned(FOnGetMinorScaleParams) then
FOnGetMinorScaleParams(TimeGrid, ADateTime, AStyle);
GetViewParams(cxcsMinorScale, nil, AStyle, Result);
end;
function TcxSchedulerTimeGridViewStyles.GetSelectionBarParams(
const ADateTime: TDateTime): TcxViewParams;
begin
Result := GetSelectionBarParamsEx(ADateTime, IsTimeSelected(ADateTime));
end;
procedure TcxSchedulerTimeGridViewStyles.Changed(AIndex: Integer);
begin
inherited Changed(AIndex);
TimeGrid.ScaleChanged;
end;
procedure TcxSchedulerTimeGridViewStyles.GetDefaultViewParams(
Index: Integer; AData: TObject; out AParams: TcxViewParams);
var
APainter: TcxCustomLookAndFeelPainterClass;
begin
AParams.Bitmap := nil;
AParams.Font := Scheduler.Font;
AParams.TextColor := clBlack;
APainter := TimeGrid.LookAndFeelPainter;
case Index of
cxcsSelectionBar:
begin
if Boolean(AData) then
AParams.Color := Scheduler.Styles.GetSelectionParams.Color
else
AParams.Color := APainter.DefaultTimeGridSelectionBarColor;
end;
cxcsMajorScaleUnitSeparator, cxcsMajorScale:
begin
AParams.Color := APainter.DefaultTimeGridMajorScaleColor;
AParams.TextColor := APainter.DefaultTimeGridMajorScaleTextColor;
end;
cxcsMinorScale:
begin
AParams.Color := APainter.DefaultTimeGridMinorScaleColor;
AParams.TextColor := APainter.DefaultTimeGridMinorScaleTextColor;
end;
end;
end;
function TcxSchedulerTimeGridViewStyles.GetSelectionBarParamsEx(
const ADateTime: TDateTime; ASelected: Boolean): TcxViewParams;
var
AStyle: TcxStyle;
begin
AStyle := nil;
if Assigned(FOnGetSelectionBarParams) then
FOnGetSelectionBarParams(TimeGrid, ADateTime, AStyle);
GetViewParams(cxcsSelectionBar, TObject(ASelected), AStyle, Result);
end;
function TcxSchedulerTimeGridViewStyles.IsTimeSelected(
const ADateTime: TDateTime): Boolean;
begin
with TimeGrid.ViewInfo do
Result := IsTimeSelected(ADateTime, FSelResource);
end;
function TcxSchedulerTimeGridViewStyles.GetTimeGrid: TcxSchedulerTimeGridView;
begin
Result := TcxSchedulerTimeGridView(inherited GetOwner);
end;
{ TcxSchedulerTimeGridViewScales }
constructor TcxSchedulerTimeGridViewScales.Create(
AOwner: TcxSchedulerTimeGridView);
begin
FOwner := AOwner;
Major := True;
MajorUnitSeparatorWidth := cxDefaultSplitterWidth;
MajorUnit := suDay;
Minor := True;
MinorUnit := suHour;
MinorUnitWidth := cxDefaultMinorUnitWidth;
TimeStep := 30;
end;
procedure TcxSchedulerTimeGridViewScales.Assign(Source: TPersistent);
begin
if Source is TcxSchedulerTimeGridViewScales then
with TcxSchedulerTimeGridViewScales(Source) do
begin
Self.FMajor := FMajor;
Self.FMajorUnitSeparatorWidth := FMajorUnitSeparatorWidth;
Self.FMajorUnit := FMajorUnit;
Self.FMinor := FMinor;
Self.FMinorUnit := FMinorUnit;
Self.FMinorUnitWidth := FMinorUnitWidth;
Self.FTimeStep := FTimeStep;
end
else
inherited Assign(Source);
end;
procedure TcxSchedulerTimeGridViewScales.Changed;
begin
TimeGrid.ScaleChanged;
end;
function TcxSchedulerTimeGridViewScales.GetOwner: TPersistent;
begin
Result := FOwner;
end;
function TcxSchedulerTimeGridViewScales.GetScheduler: TcxCustomScheduler;
begin
Result := FOwner.Scheduler;
end;
procedure TcxSchedulerTimeGridViewScales.SetMajor(AValue: Boolean);
begin
if AValue <> FMajor then
begin
FMajor := AValue;
Changed;
end;
end;
procedure TcxSchedulerTimeGridViewScales.SetMajorUnitSeparatorWidth(AValue: Integer);
begin
AValue := Max(0, AValue);
if AValue <> FMajorUnitSeparatorWidth then
begin
FMajorUnitSeparatorWidth := AValue;
Changed;
end;
end;
procedure TcxSchedulerTimeGridViewScales.SetMajorUnit(AValue: TcxSchedulerTimeGridScaleUnit);
begin
if AValue <> FMajorUnit then
begin
FMajorUnit := AValue;
Changed;
end;
end;
procedure TcxSchedulerTimeGridViewScales.SetMinor(AValue: Boolean);
begin
if AValue <> FMinor then
begin
FMinor := AValue;
Changed;
end;
end;
procedure TcxSchedulerTimeGridViewScales.SetMinorUnit(AValue: TcxSchedulerTimeGridScaleUnit);
begin
if AValue <> FMinorUnit then
begin
FMinorUnit := AValue;
Changed;
end;
end;
procedure TcxSchedulerTimeGridViewScales.SetMinorUnitWidth(AValue: Integer);
begin
AValue := Max(cxMinColumnWidth, AValue);
if AValue <> FMinorUnitWidth then
begin
FMinorUnitWidth := AValue;
Changed;
end;
end;
procedure TcxSchedulerTimeGridViewScales.SetTimeStep(AValue: Integer);
begin
if AValue <> FTimeStep then
begin
FTimeStep := Max(cxMinHourScale, Min(cxMaxHourScale, AValue));
while cxMaxHourScale mod FTimeStep <> 0 do Inc(FTimeStep);
Changed;
end;
end;
{ TcxSchedulerTimeGridViewHitTest }
function TcxSchedulerTimeGridViewHitTest.HitAtScale: Boolean;
begin
Result := HitAtMajorScale or HitAtSelectionBar or HitAtMinorScale;
end;
{ TcxSchedulerTimeGridView }
constructor TcxSchedulerTimeGridView.Create(AOwner: TcxCustomScheduler);
begin
inherited Create(AOwner);
FVisibleStart := NullDate;
FScales := CreateScales;
FStyles := CreateStyles;
EventImagesLayout := eilAuto;
FScrollPosition := (ScrollMaxPos - ScrollPage) div 2;
end;
destructor TcxSchedulerTimeGridView.Destroy;
begin
FScales.Free;
FStyles.Free;
inherited Destroy;
end;
procedure TcxSchedulerTimeGridView.Assign(Source: TPersistent);
begin
if Source is TcxSchedulerTimeGridView then
with TcxSchedulerTimeGridView(Source) do
begin
Self.FScales.Assign(FScales);
Self.FStyles.Assign(FStyles);
Self.FWorkDaysOnly := FWorkDaysOnly;
Self.FWorkTimeOnly := FWorkTimeOnly;
end;
inherited Assign(Source);
end;
function TcxSchedulerTimeGridView.GetMajorUnitDisplayText(
const AStart, AFinish: TDateTime; ATextType: TcxSchedulerTimeGridScaleTextType): string;
begin
Result := GetMajorCellDisplayText(ATextType, Scales.MajorUnit, AStart, AFinish);
DoGetMajorUnitDisplayText(AStart, AFinish, ATextType, Result);
end;
function TcxSchedulerTimeGridView.GetMinorUnitDisplayText(
const AStart, AFinish: TDateTime; ATextType: TcxSchedulerTimeGridScaleTextType): string;
begin
Result := GetMinorCellDisplayText(ATextType, Scales.MinorUnit,
Scales.MajorUnit, AStart, AFinish);
DoGetMinorUnitDisplayText(AStart, AFinish, ATextType, Result);
end;
function TcxSchedulerTimeGridView.CanDeactivateOnDateNavigatorSelectionChange: Boolean;
begin
Result := False;
end;
function TcxSchedulerTimeGridView.CanSelectPeriod: Boolean;
begin
Result := False;
end;
procedure TcxSchedulerTimeGridView.Changed;
begin
inherited Changed;
end;
procedure TcxSchedulerTimeGridView.CheckRefresh;
begin
if (FirstVisibleDate < EventList.SelStart) or (LastVisibleDate >= EventList.SelFinish) then
Scheduler.FullRefresh;
end;
function TcxSchedulerTimeGridView.CreateController: TcxSchedulerSubControlController;
begin
Result := TcxSchedulerTimeGridViewController.Create(Self);
end;
function TcxSchedulerTimeGridView.CreateHitTest: TcxSchedulerSubControlHitTest;
begin
Result := TcxSchedulerTimeGridViewHitTest.Create(Self);
end;
function TcxSchedulerTimeGridView.CreatePainter: TcxSchedulerSubControlPainter;
begin
Result := TcxSchedulerTimeGridViewPainter.Create(Self);
end;
function TcxSchedulerTimeGridView.CreateScales: TcxSchedulerTimeGridViewScales;
begin
Result := TcxSchedulerTimeGridViewScales.Create(Self);
end;
function TcxSchedulerTimeGridView.CreateStyles: TcxSchedulerTimeGridViewStyles;
begin
Result := TcxSchedulerTimeGridViewStyles.Create(Self);
end;
function TcxSchedulerTimeGridView.CreateViewInfo: TcxSchedulerSubControlViewInfo;
begin
Result := TcxSchedulerTimeGridViewViewInfo.Create(Self);
end;
procedure TcxSchedulerTimeGridView.DoDrawSelectionBarCell(
AItem: TcxSchedulerTimeGridSelectionBarCell; var ADone: Boolean);
begin
if Assigned(FOnCustomDrawSelectionBar) then
OnCustomDrawSelectionBar(Self, Canvas, AItem, ADone);
end;
procedure TcxSchedulerTimeGridView.DoDrawTimeLineCell(
AItem: TcxSchedulerTimeGridMinorScaleCell; var ADone: Boolean);
begin
if Assigned(FOnCustomDrawMinorUnit) then
FOnCustomDrawMinorUnit(Self, Canvas, AItem, ADone);
end;
procedure TcxSchedulerTimeGridView.DoDrawTimeLineHeaderCell(
AItem: TcxSchedulerTimeGridMajorScaleCell; var ADone: Boolean);
begin
if Assigned(FOnCustomDrawMajorUnit) then
FOnCustomDrawMajorUnit(Self, Canvas, AItem, ADone);
end;
procedure TcxSchedulerTimeGridView.DoGetMajorUnitDisplayText(
const AStart, AFinish: TDateTime;
ATextType: TcxSchedulerTimeGridScaleTextType; var AText: string);
begin
if Assigned(FOnGetMajorUnitDisplayText) then
FOnGetMajorUnitDisplayText(Self, AStart, AFinish, ATextType, AText);
end;
procedure TcxSchedulerTimeGridView.DoGetMinorUnitDisplayText(
const AStart, AFinish: TDateTime;
ATextType: TcxSchedulerTimeGridScaleTextType; var AText: string);
begin
if Assigned(FOnGetMinorUnitDisplayText) then
FOnGetMinorUnitDisplayText(Self, AStart, AFinish, ATextType, AText);
end;
function TcxSchedulerTimeGridView.GetCompressWeekEnd: Boolean;
begin
Result := False;
end;
function TcxSchedulerTimeGridView.GetEditWithSingleLineEditor(
AEvent: TcxSchedulerControlEvent): Boolean;
begin
Result := not EventDetailInfo;
end;
function TcxSchedulerTimeGridView.GetFirstVisibleDate: TDateTime;
begin
Result := DateOf(VisibleStart);
if (VisibleStart = NullDate) and (SelectedDays.Count > 0) then
Result := SelectedDays[0] - 7;
end;
function TcxSchedulerTimeGridView.GetLastVisibleDate: TDateTime;
begin
if (FVisibleFinish = 0) and (VisibleStart > 0) then
Result := VisibleStart + GetTimeIncrement
else
Result := DateOf(VisibleFinish);
if (VisibleStart = NullDate) and (SelectedDays.Count > 0) then
Result := SelectedDays[0] + 7;
end;
function TcxSchedulerTimeGridView.GetTimeIncrement: TDateTime;
begin
Result := inherited GetTimeIncrement;
if Scales.MinorUnit = suHour then
Result := Scales.TimeStep * MinuteToTime;
end;
function TcxSchedulerTimeGridView.GetViewContentRect: TRect;
begin
Result := inherited GetViewContentRect;
end;
procedure TcxSchedulerTimeGridView.InitScrollBarsParameters;
var
Position: Integer;
begin
inherited InitScrollBarsParameters;
Position := Min(Max(FScrollPosition, 0), ScrollMaxPos - 1);
SetScrollBarInfo(sbHorizontal, 0, ScrollMaxPos, 1, ScrollPage, Position, True, True);
end;
procedure TcxSchedulerTimeGridView.MakeEventVisible(
AEvent: TcxSchedulerControlEvent; const ADate: TDateTime;
AResource: TcxSchedulerStorageResourceItem);
begin
ViewInfo.MakeTimeVisible(AEvent.Start);
LayoutChanged;
end;
procedure TcxSchedulerTimeGridView.ScaleChanged;
var
AStart: TDateTime;
begin
if (Scales = nil) or (ViewInfo = nil) then Exit;
ScaleTextType := sttUnknown;
if VisibleStart <> NullDate then
begin
AStart := Scheduler.SelStart;
ViewInfo.TimeBuilder.Assign(Self);
ViewInfo.TimeBuilder.ValidateVisibleStart(AStart);
ViewInfo.TimeBuilder.ValidateTime(AStart, False);
Controller.Navigation.ReplaceSelParams(AStart, AStart, Scheduler.SelResource);
end;
Changed;
end;
procedure TcxSchedulerTimeGridView.Scroll(AScrollBarKind: TScrollBarKind;
AScrollCode: TScrollCode; var AScrollPos: Integer);
var
AStartTime: TDateTime;
begin
if FVisibleStart = NullDate then
FVisibleStart := SelectedDays[0];
AStartTime := VisibleStart;
FScrollUpdateLocked := AScrollCode <> scEndScroll;
case AScrollCode of
scLineDown, scLineUp:
with ViewInfo.TimeBuilder do
begin
System.Inc(FScrollPosition, Direction[AScrollCode = scLineDown]);
AStartTime := CalculateDateTime(AStartTime, Direction[AScrollCode = scLineDown]);
if CheckTime and (RoundTime(TimeOf(AStartTime)) = WorkFinish) then
AStartTime := CalculateDateTime(AStartTime, Direction[AScrollCode = scLineDown]);
end;
scPageUp, scPageDown:
begin
AStartTime := ViewInfo.TimeBuilder.CalculateDateTime(AStartTime,
Direction[AScrollCode = scPageDown] * ViewInfo.VisibleColumnCount);
System.Inc(FScrollPosition, Direction[AScrollCode = scLineDown] * ViewInfo.VisibleColumnCount);
end;
scBottom, scTop, scPosition, scTrack:
if AScrollPos <> FScrollPosition then
begin
AStartTime := ViewInfo.TimeBuilder.CalculateDateTime(AStartTime,
AScrollPos - FScrollPosition);
with ViewInfo.TimeBuilder do
begin
if CheckTime and (RoundTime(TimeOf(AStartTime)) = WorkFinish) then
AStartTime := CalculateDateTime(AStartTime, Direction[AScrollPos - FScrollPosition > 0]);
end;
FScrollPosition := AScrollPos;
end;
end;
VisibleStart := DateTimeHelper.RoundTime(AStartTime);
if IsScrollingContent or (AScrollCode = scEndScroll) then
AScrollPos := Max(Min(FScrollPosition, ScrollMaxPos - (ScrollPage * 2 - 1)), ScrollPage);
if IsScrollingContent then
GetScrollBar(sbHorizontal).Position := AScrollPos;
FScrollPosition := AScrollPos;
CheckRefresh;
end;
procedure TcxSchedulerTimeGridView.SelectedDaysChanged;
var
ADate: TDateTime;
begin
if SelectedDays.Count > 0 then
begin
ADate := SelectedDays[0];
ViewInfo.TimeBuilder.ValidateTime(ADate, True, 0);
ViewInfo.TimeBuilder.CheckWorkDays(ADate, True);
VisibleStart := ADate;
if not FLockSelectionUpdate then
Controller.Navigation.ReplaceSelParams(
NullDate, NullDate, Scheduler.SelResource);
Changed;
end;
end;
procedure TcxSchedulerTimeGridView.UpdateDateNavigatorSelection;
var
AStart: TDateTime;
begin
AStart := FVisibleStart;
inherited UpdateDateNavigatorSelection;
VisibleStart := AStart;
end;
procedure TcxSchedulerTimeGridView.ValidateSelectionFinishTime(
var ADateTime: TDateTime);
var
Y, M, D: Word;
begin
if Scales.MinorUnit < suDay then Exit;
DecodeDate(ADateTime, Y, M, D);
case Scales.MinorUnit of
suDay:
ADateTime := EncodeDate(Y, M, D);
suWeek:
ADateTime := Trunc(ADateTime) - (DayOfTheWeek(ADateTime) - 1) + 6;
suMonth:
ADateTime := EncodeDate(Y, M, DaysPerMonth(Y, M));
suQuarter:
begin
M := ((M - 1) div 3 + 1) * 3;
ADateTime := EncodeDate(Y, M, DaysPerMonth(Y, M));
end;
suYear:
ADateTime := EncodeDate(Y, 12, 31);
end;
if Scales.MinorUnit > suDay then
ADateTime := ADateTime + 1;
end;
procedure TcxSchedulerTimeGridView.VisibleChanged;
begin
inherited;
if not Visible then
FVisibleStart := NullDate;
end;
function TcxSchedulerTimeGridView.GetHitTest: TcxSchedulerTimeGridViewHitTest;
begin
Result := TcxSchedulerTimeGridViewHitTest(inherited HitTest);
end;
function TcxSchedulerTimeGridView.GetViewInfo: TcxSchedulerTimeGridViewViewInfo;
begin
Result := TcxSchedulerTimeGridViewViewInfo(inherited ViewInfo);
end;
procedure TcxSchedulerTimeGridView.SetEventMaxLineCount(AValue: Integer);
begin
AValue := Max(0, AValue);
if AValue <> FEventMaxLineCount then
begin
FEventMaxLineCount := AValue;
Changed;
end;
end;
procedure TcxSchedulerTimeGridView.SetScales(
AValue: TcxSchedulerTimeGridViewScales);
begin
FScales.Assign(AValue);
Changed;
end;
procedure TcxSchedulerTimeGridView.SetEventDetailInfo(AValue: Boolean);
begin
if AValue <> FEventDetailInfo then
begin
FEventDetailInfo := AValue;
Changed;
end;
end;
procedure TcxSchedulerTimeGridView.SetStyles(
AValue: TcxSchedulerTimeGridViewStyles);
begin
FStyles.Assign(AValue);
Changed;
end;
procedure TcxSchedulerTimeGridView.SetVisibleStart(AValue: TDateTime);
begin
if AValue <> FVisibleStart then
begin
Scheduler.DateNavigator.BeginUpdate;
try
FVisibleStart := AValue;
if Controller.Navigation.SelStart = 0 then
Controller.Navigation.ReplaceSelParams(NullDate, NullDate, Scheduler.SelResource);
UpdateDateNavigatorSelection;
Changed;
finally
Scheduler.DateNavigator.EndUpdate;
end;
end;
end;
procedure TcxSchedulerTimeGridView.SetWorkDaysOnly(AValue: Boolean);
begin
if AValue <> FWorkDaysOnly then
begin
FWorkDaysOnly := AValue;
Changed;
end;
end;
procedure TcxSchedulerTimeGridView.SetWorkTimeOnly(AValue: Boolean);
begin
if AValue <> FWorkTimeOnly then
begin
FWorkTimeOnly := AValue;
Changed;
end;
end;
{ TcxSchedulerTimeGridViewEventCellViewInfo }
procedure TcxSchedulerTimeGridViewEventCellViewInfo.CalculateCaptions;
begin
if (ShowFinishTime or ShowStartTime) and ViewData.AutoHeight then
begin
inherited CalculateCaptions;
if EventStart <> EventFinish then
ViewData.Caption := StartText + '-' + FinishText + ' ' + ViewData.Caption
else
ViewData.Caption := StartText + ' ' + ViewData.Caption;
end
else
if not ShowTimeAsClock then
inherited CalculateCaptions;
end;
procedure TcxSchedulerTimeGridViewEventCellViewInfo.CalculateDetailInfo;
begin
FIsDetailInfo := ViewData.AutoHeight;
FIsDetailCaption := FIsDetailInfo;
FShowMessage := IsDetailInfo and (Length(Message) > 0);
end;
procedure TcxSchedulerTimeGridViewEventCellViewInfo.CalculateEventTimeAsClockLayout(
const ABounds: TRect; const ACaptionWidth, AImagesWidth: Integer; var ALeft: Integer);
var
ASpaceWidth, AIconsWidth, AVertOffset: Integer;
R: TRect;
begin
AIconsWidth := TcxSchedulerPainterHelper.IconsWidth;
R := cxRectBounds(0, 0, AIconsWidth, TcxSchedulerPainterHelper.IconsHeight);
AVertOffset := GetImagesVerticalOffset(R.Bottom, True);
ASpaceWidth := cxRectWidth(CaptionRect) - (ACaptionWidth + AImagesWidth + cxEventImagesOffset);
if ASpaceWidth > AIconsWidth then
begin
FStartRect := SetItemRect(ShowStartTime, R, AVertOffset, ALeft);
Dec(ASpaceWidth, AIconsWidth + cxEventImagesGap);
if ASpaceWidth > AIconsWidth then
FFinishRect := SetItemRect(ShowFinishTime, R, AVertOffset, ALeft);
Inc(ALeft);
end;
end;
procedure TcxSchedulerTimeGridViewEventCellViewInfo.CalculateEventTimeVisibility;
begin
if Event.AllDayEvent then
begin
ViewData.ShowFinishTime := False;
ViewData.ShowStartTime := False;
end
else
if IsHeaderEvent then
begin
ViewData.ShowFinishTime := (TimeOf(EventFinish) <> 0) and (ContentFinish <> EventFinish);
ViewData.ShowStartTime := (TimeOf(EventStart) <> 0) and (ContentStart <> EventStart);
end
else
begin
ViewData.ShowFinishTime := (ContentFinish <> EventFinish) or (ContentStart <> EventStart);
ViewData.ShowStartTime := ViewData.ShowFinishTime;
end;
end;
function TcxSchedulerTimeGridViewEventCellViewInfo.CalculateNonDetailEventImages(
const ACaptionWidth: Integer; out AImagesWidth: Integer): TRect;
begin
Result := cxRectInflate(Bounds, -cxEventBorderWidth, 0);
Inc(Result.Left, cxEventImagesOffset);
Inc(Result.Top, cxEventImagesOffset);
Result.Right := Result.Right - ACaptionWidth;
AImagesWidth := CalculateSingleLineImages(Result, CaptionRect.Right);
end;
procedure TcxSchedulerTimeGridViewEventCellViewInfo.CalculateItemsLayout;
begin
if not ViewData.AutoHeight then
begin
if Event.AllDayEvent then
CalculateHeaderEventLayout
else
CalculateNonDetailEventLayout;
end;
end;
procedure TcxSchedulerTimeGridViewEventCellViewInfo.CalculateShowTimeAsClock;
begin
ViewData.ShowTimeAsClock := ViewData.ShowTimeAsClock and not ViewData.AutoHeight;
end;
function TcxSchedulerTimeGridViewEventCellViewInfo.GetEditingRect: TRect;
begin
Result := inherited GetEditingRect;
Inc(Result.Top, Byte(ViewData.AutoHeight));
end;
procedure TcxSchedulerTimeGridViewEventCellViewInfo.InitHitTest(
AHitTest: TcxSchedulerCustomResourceViewHitTest);
begin
inherited InitHitTest(AHitTest);
InitHitTestForHorzEvent(AHitTest);
end;
{ TcxSchedulerTimeGridViewViewInfo }
constructor TcxSchedulerTimeGridViewViewInfo.Create(AOwner: TcxSchedulerSubControl);
begin
inherited Create(AOwner);
FTimeLineCells := TcxSchedulerViewInfoCellList.Create();
FCells.Add(FTimeLineCells);
FTimeBuilder := TcxSchedulerTimeBuilder.Create();
end;
destructor TcxSchedulerTimeGridViewViewInfo.Destroy;
begin
FreeAndNil(FTimeBuilder);
inherited Destroy;
end;
procedure TcxSchedulerTimeGridViewViewInfo.CalculateHitTest(
AHitTest: TcxSchedulerCustomResourceViewHitTest);
begin
if not FTimeLineCells.CalculateHitTest(AHitTest) then
inherited CalculateHitTest(AHitTest);
end;
procedure TcxSchedulerTimeGridViewViewInfo.AddEventForCalculation(
ABuilder: TcxSchedulerEventLayoutBuilder; AEvent: TcxSchedulerControlEvent;
AResourceIndex: Integer);
var
I: Integer;
AItem: TcxSchedulerStorageResourceItem;
APlace: TcxSchedulerEventPlace;
AStart, AFinish: TDateTime;
AStartCol, AFinishCol: Integer;
begin
AItem := nil;
if AResourceIndex < ResourceCount then
AItem := GetResourceItemByIndex(AResourceIndex);
if not AEvent.IsResourceEvent(AItem, ShowEventsWithoutResource) or
(AEvent.Finish < View.VisibleStart) or (AEvent.Start >= FLastVisibleTime) then Exit;
I := FirstVisibleIndex;
while I < FColumnCount do
begin
if IsColumnEvent(AEvent, I) then
begin
CalculateEventPosition(AEvent, I, AStartCol, AFinishCol, AStart, AFinish);
APlace := ABuilder.AddEventPlace(AEvent, AStartCol, AFinishCol, 1, TObject(AResourceIndex));
APlace.Data := AddEventViewInfo(APlace, AResourceIndex, AStart, AFinish);
Break;
end;
Inc(I);
end;
end;
function TcxSchedulerTimeGridViewViewInfo.AddEventViewInfo(
APlace: TcxSchedulerEventPlace; AResourceIndex: Integer;
const AStart, AFinish: TDateTime): TcxSchedulerEventCellViewInfo;
var
I: Integer;
ABounds, AVisibleBounds: TRect;
AResource: TcxSchedulerResourceViewInfo;
AViewData: TcxSchedulerEventViewData;
begin
AVisibleBounds := Rect(ResourceHeaderWidth, ScalesHeight,
Bounds.Right, Bounds.Bottom);
if Integer(APlace.Resource) < ResourceCount then
begin
AResource := Resources[Integer(APlace.Resource)];
with ResourceHeaderCells[1 + Integer(APlace.Resource)] do
begin
AVisibleBounds.Top := Bounds.Top;
AVisibleBounds.Bottom := Bounds.Bottom;
end;
end
else
AResource := nil;
ABounds := cxRect(APlace.ColStart, AVisibleBounds.Top + cxTextOffset,
APlace.ColFinish, AVisibleBounds.Top + cxTextOffset + FContentLineHeight);
AViewData := CreateEventViewData(TcxSchedulerControlEvent(APlace.Event),
ABounds, AStart, AFinish, AResource);
AViewData.VisibleRect := AVisibleBounds;
AViewData.AutoHeight := View.EventDetailInfo;
Result := AddEventCell(AViewData, not AViewData.AutoHeight);
if View.EventDetailInfo then
begin
I := Result.MeasureHeight(View.Canvas);
APlace.LineFinish := (I div ContentLineHeight) - 1;
if (I mod ContentLineHeight > 0) then Inc(APlace.LineFinish);
if View.EventMaxLineCount > 0 then
APlace.LineFinish := Min(View.EventMaxLineCount, APlace.LineFinish + 1) - 1;
end;
end;
procedure TcxSchedulerTimeGridViewViewInfo.AddMajorScaleCell(
ABounds: TRect; const AStart, AFinish: TDateTime);
var
AItem: TcxSchedulerTimeGridMajorScaleCell;
begin
if ABounds.Left > ResourceHeaderWidth then
Dec(ABounds.Left);
Inc(ABounds.Right, FSeparatorWidth);
AddTimeLineItem(TcxSchedulerTimeGridMajorScaleCell, ABounds, 0,
AStart, AFinish, View.Styles.GetMajorScaleParams(AStart), AItem);
AItem.FDisplayText := View.GetMajorUnitDisplayText(AStart,
CheckFinishTime(AFinish, Scales.MajorUnit), FMajorTextType);
AItem.FBorders := [bBottom];
AItem.FRightIndent := FSeparatorWidth;
end;
procedure TcxSchedulerTimeGridViewViewInfo.AddMajorSeparator(
var ALeft: Integer);
var
ARect: TRect;
ACell: TcxSchedulerMajorSeparatorCellViewInfo;
begin
Dec(ALeft);
ARect := Rect(ALeft, Bounds.Top,
ALeft + FSeparatorWidth, Bounds.Bottom);
CreateCellInstance(TcxSchedulerMajorSeparatorCellViewInfo,
cxRectInflate(ARect, -1, 0), Bounds, View.Styles.GetMajorScaleUnitSeparatorParams, ACell);
Inc(ARect.Top, FMajorScaleHeight);
ACell.FContentBounds := ARect;
Inc(ALeft, FSeparatorWidth);
FGroupSeparatorCells.Insert(0, ACell);
end;
procedure TcxSchedulerTimeGridViewViewInfo.AddMinorScaleCell(const ABounds: TRect;
const AStart, AFinish: TDateTime);
var
AItem: TcxSchedulerTimeGridMinorScaleCell;
begin
AddTimeLineItem(TcxSchedulerTimeGridMinorScaleCell, ABounds, 1, AStart, AFinish,
View.Styles.GetMinorScaleParams(AStart), AItem);
AItem.Borders := [bBottom];
if (Scales.MajorUnitSeparatorWidth = 0) and (Scales.MajorUnit = suDay) then
begin
if TimeBuilder.IsPeriodChanged(AFinish, TimeBuilder.CalculateDateTime(AFinish, 2)) then
AItem.Borders := [bBottom, bRight];
end;
AItem.FDisplayText := View.GetMinorUnitDisplayText(AStart,
CheckFinishTime(AFinish, Scales.MinorUnit), FMajorTextType);
end;
function TcxSchedulerTimeGridViewViewInfo.AddSelectionBarCell(const ABounds: TRect;
const AStart, AFinish: TDateTime): TcxSchedulerTimeGridSelectionBarCell;
begin
AddTimeLineItem(TcxSchedulerTimeGridSelectionBarCell, ABounds, 2, AStart, AFinish,
View.Styles.GetSelectionBarParams(AStart), Result);
Result.FSelected := View.Styles.IsTimeSelected(AStart);
Result.Borders := DefaultBorders;
end;
procedure TcxSchedulerTimeGridViewViewInfo.AddTimeLineItem(
AClass: TcxSchedulerCustomViewInfoItemClass; const ABounds: TRect; AType: Byte;
const AStart, AFinish: TDateTime; const AViewParams: TcxViewParams; var Instance);
var
ACell: TcxSchedulerTimeGridMinorScaleCell;
begin
CreateCellInstance(AClass, ABounds, FScalesBounds, AViewParams, Instance);
ACell := TcxSchedulerTimeGridMinorScaleCell(Instance);
ACell.ItemType := AType;
ACell.FTimeFinish := AFinish;
if AStart = AFinish then
ACell.FTimeFinish := TimeBuilder.Inc(AStart);
ACell.FDateTime := AStart;
ACell.FVisible := ACell.FVisible and (ABounds.Bottom > ABounds.Top);
FTimeLineCells.Add(TcxSchedulerTimeGridMinorScaleCell(Instance));
end;
procedure TcxSchedulerTimeGridViewViewInfo.AdjustTextType;
var
I: Integer;
ATextAdjusted: Boolean;
ACell: TcxSchedulerTimeGridMinorScaleCell;
procedure CheckScale(var ATextType: TcxSchedulerTimeGridScaleTextType);
const
RevertTypes: array[TcxSchedulerTimeGridScaleTextType] of TcxSchedulerTimeGridScaleTextType =
(sttLong, sttUnknown, sttShort, sttMiddle);
var
S: string;
begin
if ACell.ItemType = 0 then
S := View.GetMajorUnitDisplayText(ACell.TimeStart,
CheckFinishTime(ACell.TimeFinish, Scales.MajorUnit), ATextType)
else
S := View.GetMinorUnitDisplayText(ACell.TimeStart,
CheckFinishTime(ACell.TimeFinish, Scales.MinorUnit), ATextType);
ACell.DisplayText := S;
if (ATextType <> sttShort) and
(cxTextWidth(ACell.Font, S) > (cxRectWidth(ACell.Bounds) - cxTextOffset * 2)) then
begin
ATextType := RevertTypes[ATextType];
ATextAdjusted := False;
end;
end;
begin
FMajorTextType := sttUnknown;
FMinorTextType := sttUnknown;
repeat
ATextAdjusted := True;
for I := 0 to TimeLineCells.Count - 1 do
begin
ACell := TcxSchedulerTimeGridMinorScaleCell(TimeLineCells.List^[I]);
case ACell.ItemType of
0:
CheckScale(FMajorTextType);
1:
CheckScale(FMinorTextType);
end;
if not ATextAdjusted then Break;
end;
until ATextAdjusted;
end;
procedure TcxSchedulerTimeGridViewViewInfo.CalculateContentCells;
var
R: TRect;
I, J, ID: Integer;
AColor: TColor;
ACell: TcxSchedulerTimeGridSelectionBarCell;
AContentCell: TcxSchedulerContentCellViewInfo;
AResource: TcxSchedulerStorageResourceItem;
begin
R := Bounds;
for I := 0 to Max(ResourceCount - 1, 0) do
begin
AResource := nil;
if I <= (ResourceCount - 1) then
begin
ID := I;
AResource := Resources[I].ResourceItem;
R := ResourceHeaderCells[I + 1].Bounds
end
else
begin
R.Top := FScalesHeight;
ID := -1;
end;
for J := 0 to ColumnCount - 1 do
begin
ACell := TcxSchedulerTimeGridSelectionBarCell(TimeLineCells.List^[J]);
if not ACell.Visible then Continue;
AColor := StylesAdapter.GetContentParams(ACell.TimeStart, True, AResource).Color;
R.Left := ACell.Bounds.Left;
R.Right := ACell.Bounds.Right;
AContentCell := AddContentCell(R, ACell.TimeStart, ACell.TimeFinish, ID);
AContentCell.Borders := [bRight];
if FColumnsInMinorUnit > 1 then
AContentCell.BorderColor := PainterHelper.GetSeparatorColor(AColor,
(J + 1) mod FColumnsInMinorUnit = 0, View.IsWorkTime(AResource, ACell.TimeFinish))
else
AContentCell.BorderColor := PainterHelper.GetSeparatorColor(AColor, True,
View.IsWorkTime(AResource, ACell.TimeStart))
end;
end;
end;
procedure TcxSchedulerTimeGridViewViewInfo.CalculateEventPosition(
AEvent: TcxSchedulerControlEvent; AColIndex: Integer;
out AStartX, AFinishX: Integer; out AStart, AFinish: TDateTime);
var
EventStart, EventFinish, AFirst, ALast: TDateTime;
procedure CalculateForward;
begin
ALast := AFinish;
while AEvent.Finish > ALast do
begin
AFirst := ALast;
TimeBuilder.ValidateTime(AFirst, True);
ALast := TimeBuilder.Inc(AFirst);
if TimeBuilder.CheckTime and TimeBuilder.IsPeriodChanged(AFirst, ALast) and
(EventFinish > ALast) then Inc(AFinishX, FSeparatorWidth - 1);
TimeBuilder.TimeCorrected(AFirst, ALast);
if (EventFinish >= AFirst) then
begin
AFinish := ALast;
AFinishX := AFinishX + FColumnWidth;
end;
if TimeBuilder.IsPeriodChanged(AFirst, ALast) and (EventFinish > ALast) then
Inc(AFinishX, FSeparatorWidth - 1);
end;
end;
procedure CalculateBackward;
begin
AFirst := AStart;
ALast := AFirst;
while AEvent.Start < AFirst do
begin
ALast := AFirst;
TimeBuilder.ValidateTime(ALast, False);
AFirst := TimeBuilder.Dec(ALast);
TimeBuilder.TimeCorrected(AFirst, ALast, False);
if (EventStart <= AFirst) or ((EventStart > AFirst) and (EventStart < ALast)) then
begin
AStart := AFirst;
AStartX := AStartX - FColumnWidth;
end;
if TimeBuilder.IsPeriodChanged(AFirst, ALast) and (EventStart <= AFirst) then
Dec(AStartX, FSeparatorWidth);
end;
end;
begin
with TcxSchedulerTimeGridSelectionBarCell(FTimeLineCells.List^[AColIndex]) do
begin
AStartX := Bounds.Left;
AFinishX := Bounds.Left;
AStart := TimeStart;
AFinish := TimeStart;
if AEvent.Duration < 1*MinuteToTime then
begin
AFinishX := Bounds.Right;
AFinish := TimeFinish;
end;
end;
EventStart := DateTimeHelper.RoundTime(AEvent.Start);
EventFinish := DateTimeHelper.RoundTime(AEvent.Finish);
CalculateForward;
CalculateBackward;
// correct bounds by indent
Inc(AStartX, cxHorzEventIndent - 1);
Dec(AFinishX, cxHorzEventIndent);
end;
procedure TcxSchedulerTimeGridViewViewInfo.CalculateEvents;
var
AEventIndex, AResourceIndex: Integer;
ABuilder: TcxSchedulerEventLayoutBuilder;
begin
ABuilder := TcxSchedulerEventLayoutBuilder.Create;
try
ABuilder.Clear;
for AResourceIndex := 0 to Max(ResourceCount - 1, 0) do
for AEventIndex := 0 to Events.AbsoluteCount - 1 do
AddEventForCalculation(ABuilder, Events.AbsoluteItems[AEventIndex], AResourceIndex);
ABuilder.Calculate;
for AEventIndex := 0 to ABuilder.EventPlaceCount - 1 do
Realign(ABuilder.EventPlaces[AEventIndex]);
for AEventIndex := EventCells.Count - 1 downto 0 do
CheckEventVisibility(TcxSchedulerEventCellViewInfo(
EventCells.List^[AEventIndex]), AEventIndex);
finally
ABuilder.Free;
end;
end;
procedure TcxSchedulerTimeGridViewViewInfo.CalculateMetrics;
begin
inherited CalculateMetrics;
if Scales.FMajorUnitSeparatorWidth = 0 then
FSeparatorWidth := 1
else
FSeparatorWidth := Scales.FMajorUnitSeparatorWidth + 2;
if ResourceCount > 0 then
FResourceHeaderWidth := FResourceHeaderHeight
else
FResourceHeaderWidth := 0;
ValidateStartTime;
CalculateScalesHeight;
if TimeBuilder.MinorUnit = suHour then
FColumnsInMinorUnit := 60 div Scales.TimeStep
else
FColumnsInMinorUnit := 1;
FColumnWidth := Max(Scales.MinorUnitWidth div FColumnsInMinorUnit, 1);
with Bounds do
FScalesBounds := Rect(Left + FResourceHeaderWidth, Top, Right, Top + FScalesHeight);
end;
procedure TcxSchedulerTimeGridViewViewInfo.CalculateResourceHeaderCells;
var
R: TRect;
I, H: Integer;
AHeader: TcxSchedulerHeaderCellViewInfo;
begin
if ResourceCount = 0 then Exit;
R := cxRectSetWidth(FBounds, ResourceHeaderWidth);
H := FBounds.Bottom - FBounds.Top - SeparatorWidth * (ResourceCount - 1) - FScalesHeight;
AddResourceHeader(-1, cxRectSetSize(Bounds, ResourceHeaderWidth, FScalesHeight));
for I := 0 to ResourceCount - 1 do
begin
R.Top := MulDiv(H, I, ResourceCount);
R.Bottom := MulDiv(H, I + 1, ResourceCount);
OffsetRect(R, 0, SeparatorWidth * I + FScalesHeight);
AHeader := AddResourceHeader(I, R);
AHeader.RotateText := View.Scheduler.OptionsView.RotateResourceCaptions;
AHeader.RotateHeader := True;
if I < ResourceCount - 1 then
AddGroupHorzSeparator(R.Bottom);
end;
ProcessCheckBorders(ResourceHeaderCells, True, [], []);
end;
procedure TcxSchedulerTimeGridViewViewInfo.CalculateResourceHeadersAutoHeight(
AWidth: Integer);
begin
if not ResourceHeaders.RotateCaptions then
FResourceHeaderHeight := CalculateResourceHeaderWidth
else
inherited CalculateResourceHeadersAutoHeight(AWidth);
FResourceHeaderWidth := FResourceHeaderHeight;
end;
procedure TcxSchedulerTimeGridViewViewInfo.CalculateScales;
var
I: Integer;
begin
CalculateSelectionBar;
CalculateMinorScale;
CalculateMajorScale;
FEventRowHeight := FContentLineHeight + cxTextOffset;
if View.ScaleTextType = sttUnknown then
begin
AdjustTextType;
View.ScaleTextType := FMajorTextType;
end;
for I := 0 to TimeLineCells.Count - 1 do
TcxSchedulerTimeGridMinorScaleCell(TimeLineCells[I]).Calculate;
end;
procedure TcxSchedulerTimeGridViewViewInfo.CalculateScalesHeight;
begin
FMajorScaleHeight := MeasureFontHeight(View.Styles.MajorScale, -1, [bBottom]);
if not Scales.Major then
FMajorScaleHeight := 0;
FMinorScaleHeight := MeasureFontHeight(View.Styles.MinorScale, -1, [bBottom]);
if not Scales.Minor then
FMinorScaleHeight := 0;
FSelectionBarHeight := MeasureFontHeight(View.Styles.SelectionBar, -1, [bBottom]);
FSelectionBarHeight := Max(cxMinSelectionBarHeight, Round(FSelectionBarHeight / 1.5));
FScalesHeight := FMajorScaleHeight + FMinorScaleHeight + FSelectionBarHeight;
end;
procedure TcxSchedulerTimeGridViewViewInfo.CheckEventVisibility(
ACell: TcxSchedulerEventCellViewInfo; AIndex: Integer);
begin
if ACell.Hidden then
begin
ACell.Free;
FEventCells.Delete(AIndex);
end;
end;
function TcxSchedulerTimeGridViewViewInfo.CheckFinishTime(
const ATime: TDateTime; AUnit: TcxSchedulerTimeGridScaleUnit): TDateTime;
begin
Result := ATime;
{ if not View.WorkDaysOnly and (AUnit in [suWeek]) then
Result := Result - 1;}
end;
procedure TcxSchedulerTimeGridViewViewInfo.Clear;
begin
inherited Clear;
FTimeLineCells.Clear;
end;
function TcxSchedulerTimeGridViewViewInfo.CreateEventCellViewInfo(
AViewData: TcxSchedulerEventViewData): TcxSchedulerEventCellViewInfo;
begin
Result := TcxSchedulerTimeGridViewEventCellViewInfo.Create(AViewData);
end;
procedure TcxSchedulerTimeGridViewViewInfo.DoCalculate;
begin
FTimeBuilder.Assign(View);
FScales := View.Scales;
inherited DoCalculate;
CalculateResourceHeaderCells;
CalculateScales;
CalculateContentCells;
CalculateEvents;
View.FLockSelectionUpdate := True;
try
View.UpdateDateNavigatorSelection;
finally
View.FLockSelectionUpdate := False;
end;
end;
function TcxSchedulerTimeGridViewViewInfo.IsColumnEvent(
AEvent: TcxSchedulerControlEvent; AColumnIndex: Integer): Boolean;
var
AFinish, AStart: TDateTime;
begin
Result := False;
AStart := TcxSchedulerTimeGridSelectionBarCell(FTimeLineCells.List^[AColumnIndex]).TimeStart;
AFinish := TcxSchedulerTimeGridSelectionBarCell(FTimeLineCells.List^[AColumnIndex]).TimeFinish;
if Scales.MinorUnit = suDay then
Result := AEvent.IsDayEvent(AStart)
else
if Scales.MinorUnit > suDay then
Result := (AEvent.Finish > AStart) and (AEvent.Start < AFinish)
else
if AEvent.Finish = AEvent.Start then
Result := (AEvent.Start >= AStart) and (AEvent.Start < AFinish)
else
begin
if AEvent.Finish > AStart then
Result := {(AEvent.Start <= AStart) or
(AEvent.Finish <= AFinish) } AEvent.Start < AFinish
else
if AEvent.Finish = AStart then
Result := AEvent.Start = AStart;
end;
end;
function TcxSchedulerTimeGridViewViewInfo.GetContentParams(const ATime: TDateTime;
AResource: TcxSchedulerResourceViewInfo): TcxViewParams;
begin
Result := inherited GetContentParams(ATime, AResource);
if not HiddenSelection and IsTimeSelected(ATime, AResource) then
Result := GetSelectionParams(Result);
end;
procedure TcxSchedulerTimeGridViewViewInfo.GetItemInfo(AIndex1, AIndex2,
ATop, AHeight: Integer; var ABounds: TRect; var AStart, AFinish: TDateTime);
begin
AIndex2 := Min(ColumnCount - 1, AIndex2);
AIndex1 := Min(ColumnCount - 1, AIndex1);
with TcxSchedulerTimeGridSelectionBarCell(FTimeLineCells[AIndex1]) do
begin
ABounds.Left := Bounds.Left;
AStart := TimeStart;
end;
ABounds.Top := ATop;
ABounds.Bottom := ATop + AHeight;
with TcxSchedulerTimeGridSelectionBarCell(FTimeLineCells[AIndex2]) do
begin
ABounds.Right := Bounds.Right;
AFinish := TimeStart{Finish}; // todo: !!!!!!!!!!!!!!!!
end;
end;
function TcxSchedulerTimeGridViewViewInfo.GetResourceImagesSize: TSize;
begin
if ResourceImages = nil then
Result := TSize(cxNullSize)
else
Result := cxSize(ResourceImages.Height, ResourceImages.Width);
end;
function TcxSchedulerTimeGridViewViewInfo.GetResourcesContentWidth: Integer;
begin
CalculateScalesHeight;
Result := (Bounds.Bottom - Bounds.Top) - FScalesHeight;
end;
function TcxSchedulerTimeGridViewViewInfo.GetResourceScrollBarKind: TScrollBarKind;
begin
Result := sbVertical;
end;
function TcxSchedulerTimeGridViewViewInfo.GetStyleFont(AStyle: TcxStyle): TFont;
begin
if (AStyle <> nil) and (cxStyles.svFont in AStyle.AssignedValues) then
Result := AStyle.Font
else
Result := View.Scheduler.Font;
end;
procedure TcxSchedulerTimeGridViewViewInfo.MakeTimeVisible(
const ATime: TDateTime);
var
APos: Integer;
AFinish: TDateTime;
begin
if ATime < View.VisibleStart then
View.FVisibleStart := ATime
else
if ATime > View.VisibleFinish then
begin
APos := Bounds.Right - FResourceHeaderWidth;
View.FVisibleStart := ATime;
while APos > Bounds.Left do
begin
TimeBuilder.CheckWorkDays(View.FVisibleStart, False);
AFinish := View.FVisibleStart;
Dec(APos, FColumnWidth);
if TimeBuilder.IsPeriodChanged(View.FVisibleStart, AFinish) then
if (APos - FColumnWidth) >= (Bounds.Left + FSeparatorWidth) then
Dec(APos, FSeparatorWidth);
if (APos - FColumnWidth) > Bounds.Left then
begin
View.FVisibleStart := TimeBuilder.Dec(AFinish);
TimeBuilder.TimeCorrected(View.FVisibleStart, AFinish, False);
end
else
Break;
end;
end;
end;
function TcxSchedulerTimeGridViewViewInfo.MeasureFontHeight(
AStyle: TcxStyle; AHeight: Integer; Borders: TcxBorders): Integer;
begin
Result := AHeight;
if Result = -1 then
Result := cxTextHeight(GetStyleFont(AStyle)) + cxTextOffset * 2;
if bTop in Borders then Inc(Result);
if bBottom in Borders then Inc(Result);
end;
procedure TcxSchedulerTimeGridViewViewInfo.Realign(APlace: TcxSchedulerEventPlace);
var
R: TRect;
I: Integer;
ACell: TcxSchedulerTimeGridViewEventCellViewInfo;
AColStart, AColFinish: Integer;
AViewData: TcxSchedulerEventViewData;
AResourceIndex: Integer;
begin
ACell := TcxSchedulerTimeGridViewEventCellViewInfo(APlace.Data);
AViewData := ACell.EventViewData;
AViewData.Bounds.Bottom := AViewData.VisibleRect.Top +
(APlace.LineFinish - APlace.LineStart + 1) * FEventRowHeight;
if cxRectIntersect(R, AViewData.Bounds, AViewData.VisibleRect) and
(R.Bottom < AViewData.Bounds.Bottom) and
((AViewData.VisibleRect.Bottom - AViewData.Bounds.Top) div FEventRowHeight > 1)
then
AViewData.Bounds.Bottom := AViewData.VisibleRect.Bottom - cxTextOffset;
ACell.MoveTo(0, APlace.LineStart * FEventRowHeight);
if cxRectIntersect(R, AViewData.Bounds, AViewData.VisibleRect) and
(R.Bottom < AViewData.Bounds.Bottom) then
begin
AResourceIndex := -1;
AColStart := R.Left div FColumnWidth;
AColFinish := R.Right div FColumnWidth;
R.Right := R.Left + FColumnWidth;
for I := AColStart to AColFinish - 1 do
begin
AddButton(R, ACell.Event.Start, AResourceIndex, True);
OffsetRect(R, FColumnWidth, 0);
end;
ACell.Hidden := True;
end;
end;
procedure TcxSchedulerTimeGridViewViewInfo.ValidateStartTime;
begin
if View.FVisibleStart = NullDate then
begin
View.FVisibleStart := Days[0];
View.Controller.Navigation.ReplaceSelParams(
NullDate, NullDate, View.Scheduler.SelResource);
end;
FTimeBuilder.CalculateActualStart(FActualStartTime,
View.FVisibleStart, FFirstVisibleIndex);
SelectedDays.Clear;
SelectedDays.Add(View.FVisibleStart);
end;
function TcxSchedulerTimeGridViewViewInfo.GetTimeGridView: TcxSchedulerTimeGridView;
begin
Result := TcxSchedulerTimeGridView(inherited View);
end;
procedure TcxSchedulerTimeGridViewViewInfo.CalculateMajorScale;
var
R: TRect;
AIndex, I: Integer;
AStart, AFinish, APrevFinish: TDateTime;
ACell: TcxSchedulerTimeGridMajorScaleCell;
begin
AIndex := 0;
AStart := ActualStartTime;
ACell := nil;
for I := 1 to ColumnCount do
begin
AFinish := TcxSchedulerTimeGridSelectionBarCell(FTimeLineCells[I]).TimeStart;
if TimeBuilder.IsPeriodChanged(AStart, AFinish) or (I = ColumnCount) then
begin
APrevFinish := AFinish;
GetItemInfo(AIndex, I - 1, FBounds.Top, FMajorScaleHeight, R, AStart, AFinish);
AddMajorScaleCell(R, AStart, AFinish);
ACell := TcxSchedulerTimeGridMajorScaleCell(FTimeLineCells.Last);
AStart := APrevFinish;
AIndex := I;
end;
end;
if ACell <> nil then
Inc(ACell.FBounds.Right, Bounds.Right - Bounds.Left);
end;
procedure TcxSchedulerTimeGridViewViewInfo.CalculateMinorScale;
var
R: TRect;
AIndex, ATop, I: Integer;
AStart, AFinish: TDateTime;
begin
AIndex := 0;
ATop := FBounds.Top + FMajorScaleHeight;
for I := 1 to ColumnCount do
if (I mod FColumnsInMinorUnit = 0) or (I = ColumnCount) then
begin
GetItemInfo(AIndex, I - 1, ATop, FMinorScaleHeight, R, AStart, AFinish);
AddMinorScaleCell(R, AStart, AFinish);
AIndex := I;
end;
end;
procedure TcxSchedulerTimeGridViewViewInfo.CalculateSelectionBar;
var
ASelBounds: TRect;
ALeft, AIndex: Integer;
AActualFinish, AStart, AFinish: TDateTime;
begin
AIndex := 0;
AStart := ActualStartTime;
ALeft := Bounds.Left + FResourceHeaderWidth - FColumnWidth * FirstVisibleIndex;
ASelBounds := cxRectSetBottom(Bounds, Bounds.Top + FScalesHeight, FSelectionBarHeight);
FVisibleColumnCount := 0;
repeat
AFinish := TimeBuilder.Inc(AStart);
AActualFinish := AFinish;
if TimeBuilder.MinorUnit = suHour then
AActualFinish := TimeBuilder.RoundTime(AStart + View.GetTimeIncrement);
if TimeBuilder.TimeCorrected(AStart, AFinish) then
AddMajorSeparator(ALeft);
ASelBounds := cxRectSetLeft(ASelBounds, ALeft, FColumnWidth);
if (FVisibleColumnCount = 0) and (Bounds.Right > ALeft) then
View.FVisibleStart := AStart;
AddSelectionBarCell(ASelBounds, AStart, AActualFinish);
if (AIndex >= FirstVisibleIndex) and ((ALeft + FColumnWidth) <= Bounds.Right) then
Inc(FVisibleColumnCount);
if (FVisibleColumnCount = 1) or (ASelBounds.Right <= Bounds.Right) then
View.FVisibleFinish := AStart;
FLastVisibleTime := AFinish;
Inc(ALeft, FColumnWidth);
Inc(AIndex);
if (AIndex > FirstVisibleIndex) and TimeBuilder.IsPeriodChanged(AStart, AFinish) then
AddMajorSeparator(ALeft);
AStart := AFinish;
until (ALeft >= Bounds.Right) and (AIndex mod FColumnsInMinorUnit = 0);
FColumnCount := FTimeLineCells.Count;
FVisibleColumnCount := Max(FVisibleColumnCount, 1);
end;
{ TcxSchedulerTimeGridScaleCell }
constructor TcxSchedulerTimeGridScaleCell.Create(
APainter: TcxCustomLookAndFeelPainterClass;
const ABounds, AVisibleRect: TRect; const AViewParams: TcxViewParams);
begin
inherited Create(APainter, ABounds, AVisibleRect, AViewParams);
FBorderColor := clBtnShadow;
end;
{ TcxSchedulerTimeGridMinorScaleCell }
procedure TcxSchedulerTimeGridMinorScaleCell.Calculate;
begin
FTextBounds := Bounds;
end;
procedure TcxSchedulerTimeGridMinorScaleCell.DoDraw;
begin
DrawContent;
if (MinuteOf(TimeFinish) = 0) or (bRight in Borders) then
Canvas.FrameRect(Bounds, clBtnShadow, 1, [bRight])
else
begin
Canvas.FrameRect(Rect(Bounds.Left, Bounds.Bottom - cxTextOffset * 2,
Bounds.Right, Bounds.Bottom - 1), clBtnShadow, 1, [bRight])
end;
end;
procedure TcxSchedulerTimeGridMinorScaleCell.DrawContent;
const
Horz: array[TAlignment] of Integer =
(CXTO_LEFT, CXTO_RIGHT, CXTO_CENTER_HORIZONTALLY);
Vert: array[TcxAlignmentVert] of Integer =
(CXTO_TOP, CXTO_BOTTOM, CXTO_CENTER_VERTICALLY);
var
R: TRect;
AFlags: Integer;
ASelected: Boolean;
begin
if Self is TcxSchedulerTimeGridSelectionBarCell then
ASelected := TcxSchedulerTimeGridSelectionBarCell(Self).Selected
else
ASelected := False;
FExternalPainter.DrawTimeGridHeader(Canvas, BorderColor, Self, Borders, ASelected);
if not FHideDisplayText and (DisplayText <> '') then
begin
R := cxTextRect(PainterHelper.ExcludeBorders(FTextBounds, Borders));
AFlags := Horz[AlignHorz] or Vert[AlignVert];
SetBkMode(Canvas.Handle, Windows.Transparent);
cxTextOut(Canvas.Handle, PChar(DisplayText), R, AFlags);
end;
end;
procedure TcxSchedulerTimeGridMinorScaleCell.InitHitTest(
AHitTest: TcxSchedulerCustomResourceViewHitTest);
begin
inherited InitHitTest(AHitTest);
TcxSchedulerTimeGridViewHitTest(AHitTest).SetHitTime(htcMinorScale, TimeStart);
end;
{ TcxSchedulerTimeGridMajorScaleCell }
procedure TcxSchedulerTimeGridMajorScaleCell.Calculate;
var
W: Integer;
begin
inherited Calculate;
Dec(FTextBounds.Right, RightIndent);
FTextBounds.Left := Max(Bounds.Left, ClipRect.Left);
W := cxTextWidth(Font, FDisplayText) + cxTextOffset;
if (Bounds.Left < ClipRect.Left) and (W >= cxRectWidth(FTextBounds)) then
begin
FAlignHorz := taRightJustify;
FHideDisplayText := (cxRectWidth(FTextBounds) / W) < 0.5;
end;
end;
procedure TcxSchedulerTimeGridMajorScaleCell.DoDraw;
begin
DrawContent;
end;
procedure TcxSchedulerTimeGridMajorScaleCell.InitHitTest(
AHitTest: TcxSchedulerCustomResourceViewHitTest);
begin
inherited InitHitTest(AHitTest);
TcxSchedulerTimeGridViewHitTest(AHitTest).SetHitTime(htcMajorScale, TimeStart);
end;
{ TcxSchedulerTimeGridSelectionBarCell }
procedure TcxSchedulerTimeGridSelectionBarCell.Calculate;
begin
end;
procedure TcxSchedulerTimeGridSelectionBarCell.DoDraw;
begin
DrawContent;
end;
procedure TcxSchedulerTimeGridSelectionBarCell.InitHitTest(
AHitTest: TcxSchedulerCustomResourceViewHitTest);
begin
inherited InitHitTest(AHitTest);
TcxSchedulerTimeGridViewHitTest(AHitTest).SetHitTime(htcSelectionBar, TimeStart);
end;
{ TcxSchedulerMajorSeparatorCellViewInfo }
procedure TcxSchedulerMajorSeparatorCellViewInfo.DoDraw;
begin
Canvas.FillRect(Bounds, ViewParams);
Canvas.FrameRect(ContentBounds, Painter.DefaultSchedulerBorderColor,
1, [bLeft, bRight]);
end;
procedure TcxSchedulerMajorSeparatorCellViewInfo.InitHitTest(
AHitTest: TcxSchedulerCustomResourceViewHitTest);
begin
inherited InitHitTest(AHitTest);
TcxSchedulerTimeGridViewHitTest(AHitTest).SetBitState(htcMajorSeparator, True);
end;
{ TcxSchedulerTimeGridViewPainter }
procedure TcxSchedulerTimeGridViewPainter.Paint;
begin
FView := inherited View as TcxSchedulerTimeGridView;
ViewInfo.ContentCells.Draw(Canvas, DrawContentCell);
ViewInfo.DayHeaderCells.Draw(Canvas, DrawHeaderCell);
ViewInfo.TimeLineCells.Draw(Canvas, DrawTimeLineCellItem);
ViewInfo.ResourceHeaderCells.Draw(Canvas, DrawResourceHeaderCell);
ViewInfo.GroupSeparatorCells.Draw(Canvas, DrawGroupSeparatorCell);
ViewInfo.EventCells.Draw(Canvas, DrawEventCell);
ViewInfo.Buttons.Draw(Canvas, DrawButtonCell);
end;
procedure TcxSchedulerTimeGridViewPainter.DrawTimeLineCellItem(
AItem: TcxSchedulerCustomViewInfoItem; var ADone: Boolean);
begin
case TcxSchedulerTimeGridMinorScaleCell(AItem).ItemType of
0:
View.DoDrawTimeLineHeaderCell(TcxSchedulerTimeGridMajorScaleCell(AItem), ADone);
1:
View.DoDrawTimeLineCell(TcxSchedulerTimeGridMinorScaleCell(AItem), ADone);
2:
View.DoDrawSelectionBarCell(TcxSchedulerTimeGridSelectionBarCell(AItem), ADone);
end;
end;
function TcxSchedulerTimeGridViewPainter.GetViewInfo: TcxSchedulerTimeGridViewViewInfo;
begin
Result := TcxSchedulerTimeGridViewViewInfo(inherited ViewInfo);
end;
{ TcxSchedulerTimeBuilder }
procedure TcxSchedulerTimeBuilder.Assign(AView: TcxSchedulerTimeGridView);
begin
ValidateUnits(AView.Scales.FMajorUnit, AView.Scales.FMinorUnit);
MajorUnit := AView.Scales.MajorUnit;
MinorUnit := AView.Scales.MinorUnit;
TimeScale := CalculateScaleUnit(AView.Scales.TimeStep);
WorkFinish := AView.WorkFinish;
WorkStart := AView.WorkStart;
WorkDays := AView.WorkDays;
CalculateWorkTime(AView.WorkTimeOnly, WorkStart, WorkFinish);
CalculateWorkDays(AView.WorkDaysOnly, WorkDays);
end;
procedure TcxSchedulerTimeBuilder.CalculateActualStart(
var ActualStart, AVisibleStart: TDateTime; var AStartIndex: Integer);
begin
if CheckTime then
begin
if (RoundTime(TimeOf(AVisibleStart)) > WorkFinish) then
AVisibleStart := Trunc(AVisibleStart) + WorkFinish
else
if (RoundTime(TimeOf(AVisibleStart)) < WorkStart) then
AVisibleStart := Trunc(AVisibleStart) + WorkStart
end;
ValidateVisibleStart(AVisibleStart);
ActualStart := AVisibleStart;
AStartIndex := 0;
while not IsPeriodChanged(Dec(ActualStart), AVisibleStart) do
begin
ActualStart := Dec(ActualStart);
AStartIndex := AStartIndex + 1;
end;
end;
procedure TcxSchedulerTimeBuilder.CheckWorkDays(var ADateTime: TDateTime; AGoForward: Boolean);
begin
if MinorUnit > suDay then Exit;
while CheckDays and not (TDay(DayOfWeek(ADateTime) - 1) in WorkDays) do
ADateTime := ADateTime + Byte(AGoForward) * 2 - 1;
end;
function TcxSchedulerTimeBuilder.Dec(const ADateTime: TDateTime): TDateTime;
begin
Result := CalculateDateTime(ADateTime, -1);
end;
function TcxSchedulerTimeBuilder.Inc(const ADateTime: TDateTime): TDateTime;
begin
Result := CalculateDateTime(ADateTime, 1);
end;
function TcxSchedulerTimeBuilder.IsPeriodChanged(
const AFirst, ANext: TDateTime): Boolean;
begin
Result := False;
case MajorUnit of
suDay:
Result := DayOf(AFirst) - DayOf(ANext) <> 0;
suWeek:
Result := WeekOf(AFirst) - WeekOf(ANext) <> 0;
suMonth:
Result := MonthOf(AFirst) - MonthOf(ANext) <> 0;
suQuarter:
Result := (MonthOf(AFirst) - 1) div 3 - (MonthOf(ANext) - 1) div 3 <> 0;
suYear:
Result := YearOf(AFirst) - YearOf(ANext) <> 0;
end;
end;
function TcxSchedulerTimeBuilder.TimeCorrected(
var AStart, AFinish: TDateTime; AGoForward: Boolean = True): Boolean;
begin
Result := CheckTime and IsPeriodChanged(AStart, AFinish);
if Result then
begin
if AGoForward then
begin
AStart := AFinish;
AFinish := Inc(AStart)
end
else
begin
AStart := Dec(AStart);
AFinish := AStart;
end;
end;
end;
function TcxSchedulerTimeBuilder.TimeMode: Boolean;
begin
Result := (MajorUnit = suDay) and (MinorUnit = suHour)
end;
function TcxSchedulerTimeBuilder.CalculateDateTime(
const ADateTime: TDateTime; AInc: Integer): TDateTime;
var
ATimeInc: Integer;
begin
Result := ADateTime;
ATimeInc := 1;
if MinorUnit = suHour then
begin
Result := Result + AInc * TimeScale * MinuteToTime;
if (ATimeInc = 1) and CheckTime and (Abs(Trunc(ADateTime) - Trunc(Result)) >= 1) then
ATimeInc := 0;
end
else
if MinorUnit <= suWeek then
Result := IncDay(Result, AInc * TimeScale)
else
if MinorUnit > suWeek then
Result := StartOfTheMonth(IncMonth(Result, AInc * TimeScale));
ValidateTime(Result, AInc > 0, ATimeInc);
CheckWorkDays(Result, AInc > 0);
Result := RoundTime(Result);
end;
function TcxSchedulerTimeBuilder.CalculateScaleUnit(const AScaleUnit: Integer): Integer;
const
TimeScales: array[TcxSchedulerTimeGridScaleUnit] of Integer =
(1, 1, 7, 1, 3, 12);
begin
Result := AScaleUnit;
if not TimeMode then
Result := TimeScales[MinorUnit];
end;
procedure TcxSchedulerTimeBuilder.CalculateWorkTime(AIsWorkTimeOnly: Boolean;
var AWorkStart, AWorkFinish: TDateTime);
begin
if not AIsWorkTimeOnly or not TimeMode then
begin
WorkFinish := EncodeTime(23, 59, 59, 0);
WorkStart := 0;
end;
CheckTime := (TimeOf(WorkStart) > 0) or
(TimeOf(WorkFinish) < EncodeTime(23, 59, 59, 0)) and (MinorUnit = suHour);
WorkFinish := RoundTime(WorkFinish);
WorkStart := RoundTime(WorkStart);
end;
procedure TcxSchedulerTimeBuilder.CalculateWorkDays(
AIsWorkDaysOnly: Boolean; var AWorkDays: TDays);
const
FullWeek = [dSunday..dSaturday];
begin
if not AIsWorkDaysOnly then
WorkDays := FullWeek;
CheckDays := FullWeek * WorkDays <> FullWeek;
end;
function TcxSchedulerTimeBuilder.RoundTime(const ADateTime: TDateTime): TDateTime;
begin
Result := DateTimeHelper.RoundTime(ADateTime);
end;
procedure TcxSchedulerTimeBuilder.ValidateTime(
var ADateTime: TDateTime; AGoForward: Boolean; AInc: Integer = 1);
begin
if CheckTime and ((RoundTime(TimeOf(ADateTime)) > WorkFinish) or
(RoundTime(TimeOf(ADateTime)) < WorkStart)) then
begin
if (AInc = 0) and AGoForward and (RoundTime(TimeOf(ADateTime)) > WorkFinish) then
AInc := 1;
if AGoForward then
ADateTime := RoundTime(Trunc(ADateTime) + AInc + WorkStart)
else
ADateTime := RoundTime(Trunc(ADateTime) - AInc + WorkFinish);
end;
end;
procedure TcxSchedulerTimeBuilder.ValidateUnits(
var AMajorUnit, AMinorUnit: TcxSchedulerTimeGridScaleUnit);
var
AUnit: TcxSchedulerTimeGridScaleUnit;
AValidUnits: TcxSchedulerTimeGridScaleUnits;
begin
if AMajorUnit = suHour then
AMajorUnit := suDay;
AValidUnits := ValidMinorUnits[AMajorUnit];
if not (AMinorUnit in AValidUnits) then
begin
for AUnit := suHour to suYear do
if AUnit in AValidUnits then
begin
AMinorUnit := AUnit;
Break;
end;
end;
end;
procedure TcxSchedulerTimeBuilder.ValidateVisibleStart(
var ADateTime: TDateTime);
begin
case MinorUnit of
suHour:
begin
ADateTime := Trunc(ADateTime) + (Round(TimeOf(ADateTime) /
MinuteToTime) div TimeScale * TimeScale) * MinuteToTime;
end;
suDay:
ADateTime := Trunc(ADateTime);
suWeek:
begin
ADateTime := Trunc(ADateTime);
while Byte(DayOfWeek(ADateTime)) <> 1 do ADateTime := ADateTime - 1;
end;
suMonth:
ADateTime := StartOfTheMonth(ADateTime);
suQuarter:
begin
ADateTime := StartOfTheMonth(ADateTime);
while (MonthOf(ADateTime) - 1) mod 3 <> 0 do
ADateTime := IncMonth(ADateTime, -1);
end;
suYear:
ADateTime := StartOfTheYear(ADateTime);
end;
end;
end.