Componentes.Terceros.DevExp.../internal/x.46/2/ExpressScheduler 3/Sources/cxSchedulerTimeGridView.pas

3906 lines
134 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, Contnrs,
cxControls, cxEdit, cxGraphics, cxStyles, cxGeometry, Menus,
cxLookAndFeelPainters, cxSchedulerCustomControls, cxSchedulerCustomResourceView,
cxSchedulerUtils, cxSchedulerStorage, cxSchedulerStrs, cxDateUtils, cxClasses,
cxDrawTextUtils, SysUtils, dxOffice11, cxScrollBar;
const
htcMajorScale = $11;
htcMajorSeparator = $12;
htcMinorScale = $13;
htcSelectionBar = $14;
cxHorzEventIndent = 2;
cxMinutesPerDay = 60 * 24;
cxMinHourScale = 1;
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;
TcxSchedulerTimeGridMoreEventsButtonViewInfo = class;
TcxSchedulerTimeGridScrollBar = class;
TcxSchedulerTimeGridResourceScroll = 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); virtual;
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 Scrolling(AScrollCode: TScrollCode; var AScrollPos: Integer); virtual;
procedure SyncEventSelection(AEvent: TcxSchedulerControlEvent); override;
procedure OnTimer(Sender: TObject); virtual;
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;
FShowMoreEventsButton: Boolean;
FShowResourceScrollBar: Boolean;
FSnapEventsToTimeSlots: 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 SetShowMoreEventsButton(AValue: Boolean);
procedure SetShowResourceScrollBar(AValue: Boolean);
procedure SetEventDetailInfo(AValue: Boolean);
procedure SetSnapEventsToTimeSlots(AValue: Boolean);
procedure SetStyles(AValue: TcxSchedulerTimeGridViewStyles);
procedure SetVisibleStart(AValue: TDateTime);
procedure SetWorkDaysOnly(AValue: Boolean);
procedure SetWorkTimeOnly(AValue: Boolean);
protected
FLockSelectionCounter: Integer;
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 CreateViewAdapter: TcxCustomResourceViewAdapter; override;
function CreateViewInfo: TcxSchedulerSubControlViewInfo; override;
procedure DeactivateView; 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 GetControlEventLineStart(AEvent: TcxSchedulerControlEvent): Integer;
function GetEditWithSingleLineEditor(AEvent: TcxSchedulerControlEvent): Boolean; override;
function GetFirstVisibleDate: TDateTime; override;
function GetFirstVisibleTime: TDateTime; override;
function GetLastVisibleDate: TDateTime; override;
function GetLastVisibleTime: TDateTime; override;
function GetScrollTimeHint: string; override;
function GetTimeIncrement: TDateTime; override;
function GetViewContentRect: TRect; override;
procedure InitScrollBarsParameters; override;
function IsSnapEventsToTimeSlots: Boolean;
procedure MakeEventVisible(AEvent: TcxSchedulerControlEvent;
const ADate: TDateTime; AResource: TcxSchedulerStorageResourceItem); override;
procedure MakeLineVisible(AResource: TcxSchedulerStorageResourceItem;
AEvent: TcxSchedulerControlEvent); virtual;
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 ShowMoreEventsButton: Boolean read FShowMoreEventsButton write SetShowMoreEventsButton default True;
property ShowResourceScrollBar: Boolean read FShowResourceScrollBar write SetShowResourceScrollBar default True;
property Styles: TcxSchedulerTimeGridViewStyles read FStyles write SetStyles;
property EventDetailInfo: Boolean read FEventDetailInfo write SetEventDetailInfo default False;
property ShowTimeAsClock;
property SnapEventsToTimeSlots: Boolean read FSnapEventsToTimeSlots write SetSnapEventsToTimeSlots default True;
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;
CheckMidnight: Boolean;
MajorUnit: TcxSchedulerTimeGridScaleUnit;
MinorUnit: TcxSchedulerTimeGridScaleUnit;
TimeScale: Integer;
TimeStep : Integer;
ScaleUnit: TDateTime;
WorkDays: TDays;
WorkFinish: TDateTime;
WorkStart: TDateTime;
function CalculateDateTime(const ADateTime: TDateTime; AInc: Integer): TDateTime;
function CalculateDateTimeDateTimeWithoutCheckWorkDays(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 GetScaleStep: TDateTime;
function RoundTime(const ADateTime: TDateTime): TDateTime;
procedure ValidateMidnightForward(var ADateTime: TDateTime);
function ValidateStartTime(const ADateTime: TDateTime): TDateTime;
function ValidateTime(var ADateTime: TDateTime; AGoForward: Boolean; AInc: Integer = 1): Boolean;
procedure ValidateUnits(var AMajorUnit, AMinorUnit: TcxSchedulerTimeGridScaleUnit);
public
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;
procedure Initialize(AView: TcxSchedulerTimeGridView; AWorkTimeOnly, AWorkDaysOnly: Boolean);
function IsPeriodChanged(const AFirst, ANext: TDateTime): Boolean;
function TimeCorrected(var AStart, AFinish: TDateTime; AGoForward: Boolean = True): Boolean;
function TimeMode: Boolean;
procedure ValidateVisibleStart(var ADateTime: TDateTime);
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;
{ IcxSchedulerTimeGridViewAdapter }
IcxSchedulerTimeGridViewAdapter = interface
['{A1808B72-237C-41D0-B864-BE8E24894F22}']
function GetLineOffset: Integer;
function GetShowResourceHeaders: Boolean;
function GetShowLinks: Boolean;
function GetShowScales: Boolean;
function GetWorkDaysOnly: Boolean;
function GetWorkTimeOnly: Boolean;
end;
{ TcxSchedulerTimeGridViewAdapter }
TcxSchedulerTimeGridViewAdapter = class(TcxCustomResourceViewAdapter, IcxSchedulerTimeGridViewAdapter)
protected
FVisibleStart: TDateTime;
function GetLineOffset: Integer;
function GetPrintRange(Index: Integer): TDateTime; override;
function GetShowLinks: Boolean;
function GetShowResourceHeaders: Boolean;
function GetShowScales: Boolean;
function GetWorkDaysOnly: Boolean;
function GetWorkTimeOnly: Boolean;
procedure Store; override;
procedure Restore; override;
end;
{ TcxSchedulerTimeGridViewViewInfo }
TcxSchedulerTimeGridViewViewInfo = class(TcxSchedulerCustomResourceViewViewInfo)
private
FResourceViewShift: TcxObjectList;
procedure CalculateResourceViewShifts(ABuilder: TcxSchedulerEventLayoutBuilder);
procedure ClearMoreEventButtons;
function GetGroupCount: Integer;
function GetGroupLineCount(AIndex: Integer): Integer;
function GetResourceHeight: Integer;
function GetResourceViewShift(Index: Integer): TcxSchedulerTimeGridResourceScroll;
function GetTimeGridView: TcxSchedulerTimeGridView;
function GetVisibleLineCount(AResourceIndex: Integer): Integer;
procedure PrepareMoreEventButtons;
// calculate scales items
procedure CalculateMajorScale;
procedure CalculateMinorScale;
procedure CalculateSelectionBar;
protected
FActualStartTime: TDateTime;
FColumnCount: Integer;
FColumnWidth: Integer;
FEventMinSize: Integer;
FEventRowHeight: Integer;
FFirstVisibleIndex: Integer;
FLastVisibleTime: TDateTime;
FLineOffset: Integer;
FMajorScaleHeight: Integer;
FMajorTextType: TcxSchedulerTimeGridScaleTextType;
FMinorScaleHeight: Integer;
FMinorTextType: TcxSchedulerTimeGridScaleTextType;
FPrintResourceHeaders: Boolean;
FPrintScales: Boolean;
FResourceHeaderWidth: Integer;
FScales: TcxSchedulerTimeGridViewScales;
FScalesBounds: TRect;
FScalesHeight: Integer;
FScaleUnit: TDateTime;
FSelectionBarHeight: Integer;
FSeparatorWidth: Integer;
FShowLinks: Boolean;
FTimeBuilder: TcxSchedulerTimeBuilder;
FTimeLineCells: TcxSchedulerViewInfoCellList;
FVisibleColumnCount: Integer;
FWorkTimeOnly: Boolean;
FWorkDaysOnly: Boolean;
procedure AddEventForCalculation(ABuilder: TcxSchedulerEventLayoutBuilder;
AEvent: TcxSchedulerControlEvent; AResourceIndex: Integer); virtual;
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 CalculateResourceBounds;
procedure CalculateResourceHeaderCells; virtual;
procedure CalculateResourceHeadersAutoHeight(AWidth: Integer); override;
procedure CalculateResourceTopBottom(AResourceIndex: Integer; var ABounds: TRect);
procedure CalculateScales; virtual;
procedure CalculateScalesHeight;
procedure ChangeResourceShift(AResourceIndex, ADelta: Integer);
procedure CheckEventVisibility(ACell: TcxSchedulerEventCellViewInfo; AIndex: Integer); virtual;
function CheckFinishTime(const ATime: TDateTime; AUnit: TcxSchedulerTimeGridScaleUnit): TDateTime; virtual;
procedure Clear; override;
function CreateEventCellViewInfo(AViewData: TcxSchedulerEventViewData): TcxSchedulerEventCellViewInfo; override;
function CreateLayoutBuilder: TcxSchedulerEventLayoutBuilder; virtual;
procedure DoCalculate; override;
procedure DoContentNavigationButtonClick(Sender: TcxSchedulerContentNavigationButtonViewInfo); override;
procedure DoResourceVerticalScroll(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer);
procedure DoTimeGridMoreEventsButtonClick(Sender: TcxSchedulerMoreEventsButtonViewInfo);
function IsColumnEvent(AEvent: TcxSchedulerControlEvent; AColumnIndex: Integer): Boolean;
function IsEventVisible(AEvent: TcxSchedulerControlEvent): Boolean; virtual;
function IsMinorUnitBreak(AColumn: Integer): Boolean;
function GetActualPos(const APos: Integer; const ATime, AStart, AFinish: TDateTime ): Integer; virtual;
function GetContentParams(const ATime: TDateTime;
AResource: TcxSchedulerResourceViewInfo): TcxViewParams; override;
function GetEventClipRect(AEventViewInfo: TcxSchedulerEventCellViewInfo): TRect;
function GetIndentBetweenLines: Integer; virtual;
procedure GetItemInfo(AIndex1, AIndex2, ATop, AHeight: Integer;
var ABounds: TRect; var AStart, AFinish: TDateTime);
function GetNeedShowCurrentTime: Boolean; virtual;
function GetMoreEventButtonClass: TcxSchedulerMoreEventsButtonViewInfoClass; override;
function GetResourceScrollBarMax(I: Integer): Integer;
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 ReturnVisibleInterval(var AStart, AEnd: TDateTime); override;
procedure RestoreScrollInfo;
procedure StoreScrollInfo;
procedure ValidateStartTime;
property ResourceViewShift[Index: Integer]: TcxSchedulerTimeGridResourceScroll read GetResourceViewShift;
property ResourceViewShiftList: TcxObjectList read FResourceViewShift;
property VisibleLineCount[Index: Integer]: Integer read GetVisibleLineCount;
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 ColumnWidth: Integer read FColumnWidth;
property FirstVisibleIndex: Integer read FFirstVisibleIndex;
property IndentBetweenLines: Integer read GetIndentBetweenLines;
property GroupCount: Integer read GetGroupCount;
property GroupLineCount[Index: Integer]: Integer read GetGroupLineCount;
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 View: TcxSchedulerTimeGridView read GetTimeGridView;
property VisibleColumnCount: Integer read FVisibleColumnCount;
property WorkDaysOnly: Boolean read FWorkDaysOnly;
property WorkTimeOnly: Boolean read FWorkTimeOnly;
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;
property TextBounds: TRect read FTextBounds;
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
FIsCurrentTimeCell: Boolean;
FSelected: Boolean;
FShowCurrentTime: Boolean;
FTimeLineRect: TRect;
FViewHeight: Integer;
procedure Calculate; override;
procedure CalculateTimeLineParams(ANeedShowCurrentTime: Boolean);
procedure DoDraw; override;
procedure InitHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest); override;
property ViewHeight: Integer read FViewHeight;
public
property IsCurrentTimeCell: Boolean read FIsCurrentTimeCell;
property Selected: Boolean read FSelected;
property ShowCurrentTime: Boolean read FShowCurrentTime;
property TimeLineRect: TRect read FTimeLineRect;
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;
{ TcxSchedulerTimeGridMoreEventsButton }
TcxSchedulerTimeGridMoreEventsButtonViewInfo = class(TcxSchedulerMoreEventsButtonViewInfo)
private
FDelta: Integer;
FResourceIndex: Integer;
FValidDelta: Boolean;
public
property Delta: Integer read FDelta write FDelta;
property ResourceIndex: Integer read FResourceIndex write FResourceIndex;
property ValidDelta: Boolean read FValidDelta write FValidDelta;
end;
{ TcxSchedulerTimeGridScrollBar }
TcxSchedulerTimeGridScrollBar = class(TcxControlScrollBar)
private
FResourceIndex: Integer;
public
property ResourceIndex: Integer read FResourceIndex;
end;
{ TcxSchedulerTimeGridResourceScroll }
TcxSchedulerTimeGridResourceScroll = class
private
FData: Integer;
FEventMaxLine: Integer;
FMoreEventButtons: array of TcxSchedulerMoreEventsButtonViewInfo;
FScrollBar: TcxSchedulerTimeGridScrollBar;
protected
FShift: Integer;
procedure ClearMoreEventButtons;
procedure SetEventMaxLine(AValue: Integer);
procedure Store(AClear: Boolean);
procedure Restore;
public
destructor Destroy; override;
procedure CreateScrollBar(AResourceBounds: TRect;
ATimeGridView: TcxSchedulerTimeGridView; AResourceIndex, ARange, APosition: Integer);
property ScrollBar: TcxSchedulerTimeGridScrollBar read FScrollBar;
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
uses
dxCore;
const
DefaultBorders = [bRight, bBottom];
Direction: array[Boolean] of Integer = (-1, 1);
ScrollMaxPos: Integer = 50;
ScrollPage: Integer = 5;
type
TcxSchedulerControlEventAccess = class(TcxSchedulerControlEvent);
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.TimeToStr(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) and not NavigationButtonClicked 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) and not NavigationButtonClicked then
CheckScrolling(cxPoint(X, Y))
end;
procedure TcxSchedulerTimeGridViewController.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
inherited MouseUp(Button, Shift, X, Y);
end;
procedure TcxSchedulerTimeGridViewController.Scrolling(AScrollCode: TScrollCode; var AScrollPos: Integer);
begin
View.Scroll(sbHorizontal, AScrollCode, AScrollPos);
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;
Scrolling(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
inherited ValidateSelection(ASelStart, ASelFinish, AResource);
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;
FShowMoreEventsButton := True;
FShowResourceScrollBar := True;
FSnapEventsToTimeSlots := True;
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.FShowMoreEventsButton := FShowMoreEventsButton;
Self.FShowResourceScrollBar := FShowResourceScrollBar;
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.CreateViewAdapter: TcxCustomResourceViewAdapter;
begin
Result := TcxSchedulerTimeGridViewAdapter.Create(Self);
end;
function TcxSchedulerTimeGridView.CreateViewInfo: TcxSchedulerSubControlViewInfo;
begin
Result := TcxSchedulerTimeGridViewViewInfo.Create(Self);
end;
procedure TcxSchedulerTimeGridView.DeactivateView;
begin
inherited DeactivateView;
ViewInfo.ResourceViewShiftList.Clear;
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.GetControlEventLineStart(
AEvent: TcxSchedulerControlEvent): Integer;
var
I: Integer;
begin
Result := TcxSchedulerControlEventAccess(AEvent).LineStart;
if Result = 0 then
begin
for I := 0 to EventList.Count - 1 do
if cxCompareSchedulerControlEvents(AEvent, EventList.Items[I]) = 0 then
begin
Result := TcxSchedulerControlEventAccess(EventList.Items[I]).LineStart;
Break;
end;
end;
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.GetFirstVisibleTime: TDateTime;
begin
Result := TimeOf(VisibleStart);
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.GetLastVisibleTime: TDateTime;
begin
Result := TimeOf(VisibleFinish);
end;
function TcxSchedulerTimeGridView.GetScrollTimeHint: string;
begin
Result := DateTimeToStr(FirstVisibleDate) +
' ' + cxTimeToStr(FirstVisibleTime, ShortTimeFormat);
Result := Result + ' - ';
if LastVisibleDate <> FirstVisibleDate then
Result := Result + #13#10 + DateTimeToStr(LastVisibleDate) + ' ';
Result := Result + cxTimeToStr(LastVisibleTime, ShortTimeFormat);
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;
function TcxSchedulerTimeGridView.IsSnapEventsToTimeSlots: Boolean;
begin
Result := SnapEventsToTimeSlots;
end;
procedure TcxSchedulerTimeGridView.MakeEventVisible(
AEvent: TcxSchedulerControlEvent; const ADate: TDateTime;
AResource: TcxSchedulerStorageResourceItem);
begin
ViewInfo.MakeTimeVisible(AEvent.Start);
LayoutChanged;
if AResource = nil then
AResource := Scheduler.SelResource;
MakeLineVisible(AResource, AEvent);
end;
procedure TcxSchedulerTimeGridView.MakeLineVisible(
AResource: TcxSchedulerStorageResourceItem; AEvent: TcxSchedulerControlEvent);
var
AnEventLineIndex, ADelta, AResourceIndex: Integer;
begin
if Resources.Count > 0 then
ViewInfo.GetResourceViewInfoByItem(AResource, AResourceIndex)
else
AResourceIndex := 0;
AnEventLineIndex := GetControlEventLineStart(AEvent) +
ViewInfo.GetResourceViewShift(AResourceIndex).FShift - ViewInfo.FLineOffset;
ADelta := 0;
if AnEventLineIndex < 0 then
ADelta := -AnEventLineIndex
else
if AnEventLineIndex >= ViewInfo.GetVisibleLineCount(AResourceIndex) - 1 then
ADelta := -(AnEventLineIndex - ViewInfo.GetVisibleLineCount(AResourceIndex) + 1);
if ADelta <> 0 then
ViewInfo.ChangeResourceShift(AResourceIndex, ADelta);
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.Initialize(Self, WorkTimeOnly, WorkDaysOnly);
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;
HideHintOnScroll(AScrollCode);
if AScrollCode = scTrack then
ShowHintOnScroll(GetScrollTimeHint, AScrollBarKind);
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 FLockSelectionCounter = 0 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.SetSnapEventsToTimeSlots(AValue: Boolean);
begin
if FSnapEventsToTimeSlots <> AValue then
begin
FSnapEventsToTimeSlots := AValue;
Changed;
end;
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.SetShowMoreEventsButton(AValue: Boolean);
begin
if FShowMoreEventsButton <> AValue then
begin
FShowMoreEventsButton := AValue;
Changed;
end;
end;
procedure TcxSchedulerTimeGridView.SetShowResourceScrollBar(AValue: Boolean);
begin
if FShowResourceScrollBar <> AValue then
begin
FShowResourceScrollBar := AValue;
Changed;
end;
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;
if (FirstVisibleDate < EventList.SelStart) or (LastVisibleDate >= EventList.SelFinish) then
Scheduler.FullRefresh;
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;
{ TcxSchedulerTimeGridViewAdapter }
function TcxSchedulerTimeGridViewAdapter.GetLineOffset: Integer;
begin
Result := 0;
end;
function TcxSchedulerTimeGridViewAdapter.GetPrintRange(Index: Integer): TDateTime;
begin
Result := TcxSchedulerTimeGridView(View).FVisibleStart;
if Index <> 0 then
Result := TcxSchedulerTimeGridView(View).FVisibleFinish;
end;
function TcxSchedulerTimeGridViewAdapter.GetShowLinks: Boolean;
begin
Result := True;
end;
function TcxSchedulerTimeGridViewAdapter.GetShowResourceHeaders: Boolean;
begin
Result := True;
end;
function TcxSchedulerTimeGridViewAdapter.GetShowScales: Boolean;
begin
Result := True;
end;
function TcxSchedulerTimeGridViewAdapter.GetWorkDaysOnly: Boolean;
begin
Result := TcxSchedulerTimeGridView(View).WorkDaysOnly;
end;
function TcxSchedulerTimeGridViewAdapter.GetWorkTimeOnly: Boolean;
begin
Result := TcxSchedulerTimeGridView(View).WorkTimeOnly;
end;
procedure TcxSchedulerTimeGridViewAdapter.Store;
begin
FVisibleStart := TcxSchedulerTimeGridView(View).FVisibleStart;
TcxSchedulerTimeGridView(View).ViewInfo.StoreScrollInfo;
end;
procedure TcxSchedulerTimeGridViewAdapter.Restore;
begin
TcxSchedulerTimeGridView(View).FVisibleStart := FVisibleStart;
TcxSchedulerTimeGridView(View).ViewInfo.RestoreScrollInfo;
end;
{ TcxSchedulerTimeGridViewViewInfo }
constructor TcxSchedulerTimeGridViewViewInfo.Create(AOwner: TcxSchedulerSubControl);
begin
inherited Create(AOwner);
FTimeLineCells := TcxSchedulerViewInfoCellList.Create();
FCells.Add(FTimeLineCells);
FTimeBuilder := TcxSchedulerTimeBuilder.Create();
FResourceViewShift := TcxObjectList.Create;
end;
destructor TcxSchedulerTimeGridViewViewInfo.Destroy;
begin
FreeAndNil(FTimeBuilder);
FreeAndNil(FResourceViewShift);
inherited Destroy;
end;
procedure TcxSchedulerTimeGridViewViewInfo.CalculateHitTest(
AHitTest: TcxSchedulerCustomResourceViewHitTest);
begin
if not NavigationButtons.CalculateHitTest(AHitTest) then
if not FTimeLineCells.CalculateHitTest(AHitTest) then
inherited CalculateHitTest(AHitTest);
HotTrackNavigationButtons(AHitTest);
end;
procedure TcxSchedulerTimeGridViewViewInfo.AddEventForCalculation(
ABuilder: TcxSchedulerEventLayoutBuilder; AEvent: TcxSchedulerControlEvent;
AResourceIndex: Integer);
procedure AddEventPlace(const AStartCol, AFinishCol: Integer;
const AStart, AFinish: TDateTime);
var
APlace: TcxSchedulerEventPlace;
begin
APlace := ABuilder.AddEventPlace(AEvent,
AStartCol, AFinishCol, 1, TObject(AResourceIndex));
APlace.Data := AddEventViewInfo(APlace, AResourceIndex, AStart, AFinish);
end;
var
I: Integer;
AItem: TcxSchedulerStorageResourceItem;
AStart, AFinish: TDateTime;
AStartCol, AFinishCol: Integer;
const
Delta = 100;
begin
AItem := nil;
if AResourceIndex < ResourceCount then
AItem := GetResourceItemByIndex(AResourceIndex);
if not AEvent.IsResourceEvent(AItem, ShowEventsWithoutResource) or not IsEventVisible(AEvent) then Exit;
if not Adapter.IsPrinting and ((AEvent.Finish <= View.VisibleStart) and not IsColumnEvent(AEvent,
FirstVisibleIndex)) or (AEvent.Start >= FLastVisibleTime) then
begin
if not View.CheckEventsVisibility then
if AEvent.Start >= FLastVisibleTime then
AddEventPlace(Bounds.Right + Delta, Bounds.Right + Delta + 1, AEvent.Start, AEvent.Finish)
else
AddEventPlace(-Delta - 1, -Delta, AEvent.Start, AEvent.Finish);
Exit;
end;
if Adapter.IsPrinting then
I := 0
else
I := FirstVisibleIndex;
while I < FColumnCount do
begin
if IsColumnEvent(AEvent, I) then
begin
CalculateEventPosition(AEvent, I, AStartCol, AFinishCol, AStart, AFinish);
AddEventPlace(AStartCol, AFinishCol, 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 + IndentBetweenLines,
APlace.ColFinish, AVisibleBounds.Top + IndentBetweenLines + FContentLineHeight);
if Adapter.IsPrinting then
Inc(ABounds.Left);
AViewData := CreateEventViewData(TcxSchedulerControlEvent(APlace.Event),
ABounds, AStart, AFinish, AResource);
AViewData.VisibleRect := AVisibleBounds;
AViewData.AutoHeight := View.EventDetailInfo;
AViewData.ShowTimeAsClock := AViewData.ShowTimeAsClock and not Adapter.IsPrinting;
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 Adapter.IsPrinting or (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;
Result.FViewHeight := View.Height;
Result.CalculateTimeLineParams(GetNeedShowCurrentTime);
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));
if not ACell.Visible and Adapter.IsPrinting and (AClass = TcxSchedulerTimeGridSelectionBarCell) then
begin
if cxRectIntersect(cxRectInflate(ABounds, 0, 1), cxRectInflate(FScalesBounds, 0, 1)) then
ACell.FVisible := True;
end;
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 TimeBuilder.MinorUnit = suHour then
AContentCell.BorderColor := PainterHelper.GetSeparatorColor(AColor,
IsMinorUnitBreak(J + 1), 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;
var
AStartValue, AFinishValue: TDateTime;
begin
ALast := AFinish;
AFirst := ALast;
AStartValue := ALast;
while AEvent.Finish > ALast do
begin
AStartValue := ALast;
AFirst := ALast + MinuteToTime;
if not TimeBuilder.ValidateTime(AFirst, True) then
AFirst := AFirst - MinuteToTime;
if AEvent.Finish < AFirst then Break;
AFinishX := AFinishX + FColumnWidth;
ALast := TimeBuilder.CalculateDateTimeDateTimeWithoutCheckWorkDays(AFirst, 1);
AFirst := ALast;
//
TimeBuilder.CheckWorkDays(ALast, True);
ALast := TimeBuilder.RoundTime(ALast);
//
if EventFinish > AFirst then
begin
AFinish := ALast;
if (EventFinish > ALast) and TimeBuilder.IsPeriodChanged(AStartValue, ALast) then
Inc(AFinishX, FSeparatorWidth - 1);
end;
end;
if not View.IsSnapEventsToTimeSlots and (AStartValue < EventFinish) and (EventFinish < AFirst) then
begin
AFinishValue := TimeBuilder.CalculateDateTimeDateTimeWithoutCheckWorkDays(AStartValue, 1);
if TimeBuilder.RoundTime(AFinishValue - AStartValue) =
TimeBuilder.RoundTime(TimeBuilder.GetScaleStep) then
AFinishX := GetActualPos(AFinishX - FColumnWidth, EventFinish, AStartValue, AFinishValue);
end;
end;
procedure CalculateBackward;
var
ACorrected: Boolean;
AIsWorkDays: Boolean;
AFirstWithoutCheckWorkDays: TDateTime;
begin
AFirst := AStart;
ALast := AFirst;
if not View.IsSnapEventsToTimeSlots and (EventStart >= AFirst) then
begin
AStartX := GetActualPos(AStartX, EventStart, AFirst, TimeBuilder.Inc(AFirst));
Exit;
end;
while AEvent.Start < AFirst do
begin
ALast := AFirst;
TimeBuilder.ValidateTime(ALast, False);
AFirst := TimeBuilder.Dec(ALast);
AFirstWithoutCheckWorkDays := TimeBuilder.CalculateDateTimeDateTimeWithoutCheckWorkDays(AFirst, -1);
AIsWorkDays := AFinish <> AFirstWithoutCheckWorkDays;
ACorrected := TimeBuilder.TimeCorrected(AFirst, ALast, False);
if (EventStart <= AFirst) or ((EventStart > AFirst) and (EventStart < ALast) and
not TimeBuilder.IsPeriodChanged(AFirst, EventStart)) then
begin
if AIsWorkDays then
AStart := AFirstWithoutCheckWorkDays
else
AStart := AFirst;
AStartX := AStartX - FColumnWidth;
end;
if not View.IsSnapEventsToTimeSlots and (EventStart >= AFirst) and not AIsWorkDays and not ACorrected then
AStartX := GetActualPos(AStartX, EventStart, AFirst, ALast);
if TimeBuilder.IsPeriodChanged(AFirst, ALast) and (EventStart <= AFirst) and not AIsWorkDays 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
if not View.IsSnapEventsToTimeSlots then
begin
Inc(AStartX);
AFinishX := Max(AFinishX, AStartX + FEventMinSize)
end
else
begin
Inc(AStartX, cxHorzEventIndent - 1);
Dec(AFinishX, cxHorzEventIndent);
end;
end;
procedure TcxSchedulerTimeGridViewViewInfo.CalculateEvents;
procedure SaveEventsLineStart(ABuilder: TcxSchedulerEventLayoutBuilder);
var
I: Integer;
begin
for I := 0 to ABuilder.EventPlaceCount - 1 do
ABuilder.EventPlaces[I].LineStartToEvent;
end;
var
AEventIndex, AResourceIndex: Integer;
ABuilder: TcxSchedulerEventLayoutBuilder;
begin
ABuilder := CreateLayoutBuilder;
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;
CalculateResourceViewShifts(ABuilder);
SaveEventsLineStart(ABuilder);
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 Adapter.IsPrinting or (Scales.FMajorUnitSeparatorWidth = 0) then
FSeparatorWidth := 1
else
FSeparatorWidth := Scales.FMajorUnitSeparatorWidth + 2;
if (ResourceCount > 0) and FPrintResourceHeaders then
FResourceHeaderWidth := FResourceHeaderHeight
else
FResourceHeaderWidth := 0;
ValidateStartTime;
CalculateScalesHeight;
if TimeBuilder.MinorUnit = suHour then
FColumnWidth := Max(Scales.MinorUnitWidth div (60 div Scales.TimeStep), 1)
else
FColumnWidth := Scales.MinorUnitWidth;
with Bounds do
FScalesBounds := Rect(Left + FResourceHeaderWidth, Top, Right, Top + FScalesHeight);
FEventMinSize := cxTextWidth(Scheduler.Font, 'Wg');
end;
procedure TcxSchedulerTimeGridViewViewInfo.CalculateResourceBounds;
var
I: Integer;
R: TRect;
begin
R := FBounds;
R.Left := ResourceHeaderWidth;
for I := 0 to ResourceCount - 1 do
begin
CalculateResourceTopBottom(I, R);
AddResourceBounds(I, R);
end;
end;
procedure TcxSchedulerTimeGridViewViewInfo.CalculateResourceHeaderCells;
var
R: TRect;
I: Integer;
AHeader: TcxSchedulerHeaderCellViewInfo;
begin
if ResourceCount = 0 then Exit;
R := cxRectSetWidth(FBounds, ResourceHeaderWidth);
AddResourceHeader(-1, cxRectSetSize(Bounds, ResourceHeaderWidth, FScalesHeight));
for I := 0 to ResourceCount - 1 do
begin
CalculateResourceTopBottom(I, R);
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.CalculateResourceTopBottom(
AResourceIndex: Integer; var ABounds: TRect);
var
H: Integer;
begin
H := GetResourceHeight;
ABounds.Top := MulDiv(H, AResourceIndex, ResourceCount);
ABounds.Bottom := MulDiv(H, AResourceIndex + 1, ResourceCount);
OffsetRect(ABounds, 0, SeparatorWidth * AResourceIndex + FScalesHeight);
end;
procedure TcxSchedulerTimeGridViewViewInfo.CalculateScales;
var
I: Integer;
begin
CalculateSelectionBar;
CalculateMinorScale;
CalculateMajorScale;
FEventRowHeight := FContentLineHeight + IndentBetweenLines;
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
if not FPrintScales then
begin
FMajorScaleHeight := 0;
FMinorScaleHeight := 0;
FSelectionBarHeight := 0;
end
else
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));
end;
FScalesHeight := FMajorScaleHeight + FMinorScaleHeight + FSelectionBarHeight;
end;
procedure TcxSchedulerTimeGridViewViewInfo.ChangeResourceShift(
AResourceIndex, ADelta: Integer);
begin
Inc(GetResourceViewShift(AResourceIndex).FShift, ADelta);
View.Changed;
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;
function TcxSchedulerTimeGridViewViewInfo.CreateLayoutBuilder: TcxSchedulerEventLayoutBuilder;
begin
Result := TcxSchedulerEventLayoutBuilder.Create;
end;
procedure TcxSchedulerTimeGridViewViewInfo.DoCalculate;
var
AIntf: IcxSchedulerTimeGridViewAdapter;
begin
Supports(Adapter, IcxSchedulerTimeGridViewAdapter, AIntf);
FShowLinks := AIntf.GetShowLinks;
FWorkTimeOnly := AIntf.GetWorkTimeOnly;
FWorkDaysOnly := AIntf.GetWorkDaysOnly;
FPrintResourceHeaders := AIntf.GetShowResourceHeaders;
FPrintScales := AIntf.GetShowScales;
FLineOffset := AIntf.GetLineOffset;
AIntf := nil;
View.FVisibleStart := Adapter.PrintFrom;
FTimeBuilder.Initialize(View, WorkTimeOnly, WorkDaysOnly);
FScales := View.Scales;
inherited DoCalculate;
CalculateResourceHeaderCells;
CalculateScales;
CalculateContentCells;
CalculateEvents;
CalculateResourceBounds;
CalculateContentNavigationButtons;
Inc(View.FLockSelectionCounter);
try
View.UpdateDateNavigatorSelection;
View.Controller.Navigation.CheckSelection;
finally
Dec(View.FLockSelectionCounter);
end;
end;
procedure TcxSchedulerTimeGridViewViewInfo.DoContentNavigationButtonClick(
Sender: TcxSchedulerContentNavigationButtonViewInfo);
begin
View.VisibleStart := View.VisibleStart + Sender.Interval;
inherited DoContentNavigationButtonClick(Sender);
end;
procedure TcxSchedulerTimeGridViewViewInfo.DoResourceVerticalScroll(
Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer);
begin
GetResourceViewShift(TcxSchedulerTimeGridScrollBar(Sender).ResourceIndex).FShift :=
-ScrollPos;
View.Changed;
end;
procedure TcxSchedulerTimeGridViewViewInfo.DoTimeGridMoreEventsButtonClick(
Sender: TcxSchedulerMoreEventsButtonViewInfo);
var
ATimeGridButtonViewInfo: TcxSchedulerTimeGridMoreEventsButtonViewInfo;
begin
ATimeGridButtonViewInfo := TcxSchedulerTimeGridMoreEventsButtonViewInfo(Sender);
ChangeResourceShift(ATimeGridButtonViewInfo.ResourceIndex,
ATimeGridButtonViewInfo.Delta);
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 (AEvent.Duration < 1) and View.WorkTimeOnly and
((TimeOf(AEvent.Finish) < View.WorkStart) and (TimeOf(AEvent.Start) > View.WorkFinish)) then
Exit;
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) todo: } AEvent.Start < AFinish
else
if AEvent.Finish = AStart then
Result := AEvent.Start = AStart;
end;
end;
function TcxSchedulerTimeGridViewViewInfo.IsEventVisible(
AEvent: TcxSchedulerControlEvent): Boolean;
var
I: Integer;
begin
Result := True;
if TcxSchedulerTimeGridViewController(View.Controller).ConsiderHiddenEvents or
(Events.Clones.Count = 0) or (not FHideClones and not FHideSource) then Exit;
if AEvent.IsClone then
Result := not FHideClones
else
if FHideSource then
begin
Result := True;
for I := 0 to Events.Clones.Count - 1 do
if TcxSchedulerControlEvent(Events.Clones[I]).Source = AEvent then
begin
Result := False;
Break;
end;
end;
end;
function TcxSchedulerTimeGridViewViewInfo.IsMinorUnitBreak(AColumn: Integer): Boolean;
function IsHourEqual(const ATime1, ATime2: TDateTime): Boolean;
begin
Result := (Round(ATime1 / MinuteToTime) div 60) =
(Round(ATime2 / MinuteToTime) div 60);
end;
begin
if TimeBuilder.MinorUnit <> suHour then
Result := True
else
begin
Result := AColumn >= ColumnCount;
if not Result then
begin
Result := not IsHourEqual(TcxSchedulerTimeGridSelectionBarCell(FTimeLineCells[AColumn - 1]).TimeStart,
TcxSchedulerTimeGridSelectionBarCell(FTimeLineCells[AColumn]).TimeStart);
end;
end;
end;
function TcxSchedulerTimeGridViewViewInfo.GetActualPos(
const APos: Integer; const ATime, AStart, AFinish: TDateTime): Integer;
begin
Result := APos;
if DateTimeHelper.RoundTime(ATime) >= DateTimeHelper.RoundTime(AFinish) then
Inc(Result, FColumnWidth)
else
if (ATime > AStart) and (ATime < AFinish) then
Result := APos + Round((ATime - AStart) * FColumnWidth / (AFinish - AStart));
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;
function TcxSchedulerTimeGridViewViewInfo.GetEventClipRect(
AEventViewInfo: TcxSchedulerEventCellViewInfo): TRect;
var
I: Integer;
AResourceInfo: TcxSchedulerResourceViewInfo;
begin
AResourceInfo := AEventViewInfo.ResourceInfo;
Result := Rect(ResourceHeaderWidth, ScalesHeight, Bounds.Right, Bounds.Bottom);
if AResourceInfo <> nil then
begin
for I := 0 to ResourceCount - 1 do
if Resources[I].ResourceItem = AResourceInfo.ResourceItem then
begin
with ResourceHeaderCells[I + 1].Bounds do
Result := cxRectSetYPos(Result, Top, Bottom);
Exit;
end;
Result := cxInvalidRect;
end;
end;
function TcxSchedulerTimeGridViewViewInfo.GetIndentBetweenLines: Integer;
begin
Result := cxTextOffset;
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.GetNeedShowCurrentTime: Boolean;
begin
Result := True;
end;
function TcxSchedulerTimeGridViewViewInfo.GetMoreEventButtonClass: TcxSchedulerMoreEventsButtonViewInfoClass;
begin
Result := TcxSchedulerTimeGridMoreEventsButtonViewInfo;
end;
function TcxSchedulerTimeGridViewViewInfo.GetResourceScrollBarMax(I: Integer): Integer;
begin
Result := -1;
if (I < 0) or (I >= FResourceViewShift.Count) then
Exit;
if ResourceViewShift[I].FScrollBar <> nil then
Result := ResourceViewShift[I].FScrollBar.Max
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);
if not TimeBuilder.CheckMidnight then
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);
function GetButton(AColumnIndex: Integer;
IsDown: Boolean): TcxSchedulerMoreEventsButtonViewInfo;
begin
Result := GetResourceViewShift(Integer(
APlace.Resource)).FMoreEventButtons[AColumnIndex * 2 + IfThen(IsDown, 1)];
end;
function GetMoreButtonHeight: Integer;
begin
Result := View.ExternalPainter.MoreButtonSize(
Size(PainterHelper.MoreButtonWidth, PainterHelper.MoreButtonHeight)).cy;
end;
procedure AddMoreEventButton(AnEventLineIndex, ALineCount: Integer; R: TRect;
ADateTime: TDateTime; IsVisible: Boolean);
var
AColumnIndex, ADelta: Integer;
ADownDirection, CanChangeDelta: Boolean;
AButton: TcxSchedulerTimeGridMoreEventsButtonViewInfo;
begin
AColumnIndex := R.Left div FColumnWidth;
if (AColumnIndex < 0) or (AColumnIndex * 2 >=
Length(GetResourceViewShift(Integer(
APlace.Resource)).FMoreEventButtons)) then
Exit;
ADelta := 0;
CanChangeDelta := False;
ADownDirection := False;
if AnEventLineIndex < 0 then
begin
ADelta := -AnEventLineIndex;
R.Bottom := R.Top + GetMoreButtonHeight;
CanChangeDelta := Abs(AnEventLineIndex) <= ALineCount - 1;
end
else
if AnEventLineIndex >= ALineCount then
begin
ADelta := -(AnEventLineIndex - ALineCount + 1);
ADownDirection := True;
R.Top := R.Bottom - GetMoreButtonHeight;
CanChangeDelta := AnEventLineIndex - ALineCount + 1 <= ALineCount - 1;
end;
if ADelta <> 0 then
begin
AButton := GetButton(AColumnIndex, ADownDirection) as TcxSchedulerTimeGridMoreEventsButtonViewInfo;
if AButton = nil then
begin
AButton := AddButton(R, ADateTime, ADownDirection, APlace.Event) as TcxSchedulerTimeGridMoreEventsButtonViewInfo;
AButton.FVisible := IsVisible;
AButton.Delta := ADelta;
AButton.ResourceIndex := Integer(APlace.Resource);
AButton.OnClick :=DoTimeGridMoreEventsButtonClick;
GetResourceViewShift(Integer(
APlace.Resource)).FMoreEventButtons[AColumnIndex * 2 + IfThen(
ADownDirection, 1)] := AButton;
end
else
if CanChangeDelta and ((Abs(AButton.Delta) < Abs(ADelta)) or not AButton.ValidDelta) then
AButton.Delta := ADelta;
AButton.ValidDelta := CanChangeDelta;
end;
end;
var
AEventRect, AButtonRect, AClipRect: TRect;
ACell: TcxSchedulerTimeGridViewEventCellViewInfo;
ALineCount, AnEventLineIndex: Integer;
AViewData: TcxSchedulerEventViewData;
begin
ALineCount := GetVisibleLineCount(Integer(APlace.Resource));
AnEventLineIndex := APlace.LineStart +
GetResourceViewShift(Integer(APlace.Resource)).FShift - FLineOffset;
ACell := TcxSchedulerTimeGridViewEventCellViewInfo(APlace.Data);
AViewData := ACell.EventViewData;
AViewData.Bounds.Bottom := AViewData.VisibleRect.Top +
(APlace.LineFinish - APlace.LineStart + 1) * FEventRowHeight;
if not View.IsSnapEventsToTimeSlots then
Dec(AViewData.Bounds.Left);
ACell.MoveTo(0, AnEventLineIndex * FEventRowHeight);
if ((0 > AnEventLineIndex) or (AnEventLineIndex >= ALineCount)) and
TcxSchedulerTimeGridView(Owner).ShowMoreEventsButton then
begin
AEventRect := AViewData.Bounds;
while AEventRect.Left < 0 do
Inc(AEventRect.Left, FColumnWidth);
AButtonRect := AEventRect;
AButtonRect.Right := AButtonRect.Left + FColumnWidth;
AButtonRect.Bottom := AViewData.VisibleRect.Bottom;
AButtonRect.Top := AViewData.VisibleRect.Top;
AClipRect := GetEventClipRect(ACell);
while AEventRect.Right > AButtonRect.Left do
begin
if (AButtonRect.Left >= AClipRect.Left) and (AButtonRect.Right <= AClipRect.Right) then
begin
AddMoreEventButton(AnEventLineIndex, ALineCount, AButtonRect, ACell.Event.Start,
(AViewData.VisibleRect.Bottom - AViewData.VisibleRect.Top) div 2 >=
GetMoreButtonHeight);
end;
OffsetRect(AButtonRect, FColumnWidth, 0);
end;
ACell.Hidden := True;
end;
end;
procedure TcxSchedulerTimeGridViewViewInfo.ReturnVisibleInterval(
var AStart, AEnd: TDateTime);
begin
AStart := View.VisibleStart;
AEnd := AStart;
end;
procedure TcxSchedulerTimeGridViewViewInfo.RestoreScrollInfo;
var
I: Integer;
begin
for I := 0 to FResourceViewShift.Count - 1 do
ResourceViewShift[I].Restore;
end;
procedure TcxSchedulerTimeGridViewViewInfo.StoreScrollInfo;
var
I: Integer;
begin
if FResourceViewShift = nil then Exit;
for I := 0 to FResourceViewShift.Count - 1 do
ResourceViewShift[I].Store(Adapter.IsPrinting);
end;
procedure TcxSchedulerTimeGridViewViewInfo.ValidateStartTime;
begin
if View.FVisibleStart = NullDate then
begin
View.FVisibleStart := Days[0];
if not Adapter.IsPrinting then
View.Controller.Navigation.ReplaceSelParams(
NullDate, NullDate, View.Scheduler.SelResource)
end;
FActualStartTime := FTimeBuilder.ValidateStartTime(Adapter.ActualStart);
FTimeBuilder.CalculateActualStart(FActualStartTime,
View.FVisibleStart, FFirstVisibleIndex);
if not Adapter.IsPrinting then
begin
SelectedDays.Clear;
SelectedDays.Add(View.FVisibleStart);
TcxSchedulerTimeGridViewAdapter(Adapter).FVisibleStart := View.FVisibleStart;
end;
end;
procedure TcxSchedulerTimeGridViewViewInfo.CalculateResourceViewShifts(
ABuilder: TcxSchedulerEventLayoutBuilder);
function GetResourceBounds(AIndex: Integer): TRect;
var
I, ADimension: Integer;
begin
Result := cxNullRect;
for I := 0 to ABuilder.EventPlaceCount - 1 do
if Integer(ABuilder.EventPlaces[I].Resource) = AIndex then
begin
Result := TcxSchedulerTimeGridViewEventCellViewInfo(
ABuilder.EventPlaces[I].Data).EventViewData.VisibleRect;
ADimension := Result.Right - Result.Left;
Result.Left := View.Left;
Result.Right := Result.Left + ADimension +
IfThen(ResourceHeaderCells.Count > 0, ResourceHeaderHeight, 0);
ADimension := Result.Bottom - Result.Top;
Result.Top := View.Top + Result.Top;
Result.Bottom := Result.Top + ADimension;
Break;
end;
end;
procedure PrepareResourceViewShifts;
var
I: Integer;
begin
if (ResourceCount > 0) and (FResourceViewShift.Count <> ResourceCount) or
(ResourceCount = 0) and (FResourceViewShift.Count <> 1) then
FResourceViewShift.Clear;
for I := FResourceViewShift.Count to Max(0, ResourceCount - 1) do
FResourceViewShift.Add(TcxSchedulerTimeGridResourceScroll.Create)
end;
procedure CalculateEventMaxLines;
var
AResourceIndex, I: Integer;
begin
for I := 0 to FResourceViewShift.Count - 1 do
GetResourceViewShift(I).FEventMaxLine := 0;
for I := 0 to ABuilder.EventPlaceCount - 1 do
begin
AResourceIndex := Integer(ABuilder.EventPlaces[I].Resource);
GetResourceViewShift(AResourceIndex).SetEventMaxLine(
ABuilder.EventPlaces[I].LineStart);
end;
end;
var
I, AVisibleLineCount: Integer;
AResourceViewShift: TcxSchedulerTimeGridResourceScroll;
begin
PrepareResourceViewShifts;
CalculateEventMaxLines;
PrepareMoreEventButtons;
for I := 0 to FResourceViewShift.Count - 1 do
begin
AVisibleLineCount := GetVisibleLineCount(I);
AResourceViewShift := GetResourceViewShift(I);
if AResourceViewShift.FEventMaxLine < AVisibleLineCount then
begin
AResourceViewShift.FShift := 0;
FreeAndNil(GetResourceViewShift(I).FScrollBar);
end
else
if TcxSchedulerTimeGridView(Owner).ShowResourceScrollBar then
AResourceViewShift.CreateScrollBar(GetResourceBounds(I), Self.GetTimeGridView, I,
AResourceViewShift.FEventMaxLine - GetVisibleLineCount(I) + 1, -AResourceViewShift.FShift)
else
FreeAndNil(GetResourceViewShift(I).FScrollBar);
end;
end;
procedure TcxSchedulerTimeGridViewViewInfo.ClearMoreEventButtons;
var
I: Integer;
begin
for I := 0 to FResourceViewShift.Count - 1 do
GetResourceViewShift(I).ClearMoreEventButtons;
end;
function TcxSchedulerTimeGridViewViewInfo.GetGroupCount: Integer;
begin
Result := FResourceViewShift.Count;
end;
function TcxSchedulerTimeGridViewViewInfo.GetGroupLineCount(
AIndex: Integer): Integer;
begin
Result := Max(2, ResourceViewShift[AIndex].FEventMaxLine);
end;
function TcxSchedulerTimeGridViewViewInfo.GetResourceHeight: Integer;
begin
Result := FBounds.Bottom - FBounds.Top -
SeparatorWidth * (ResourceCount - 1) - FScalesHeight;
end;
function TcxSchedulerTimeGridViewViewInfo.GetResourceViewShift(
Index: Integer): TcxSchedulerTimeGridResourceScroll;
begin
if ResourceCount = 0 then
Index := 0;
Result := TcxSchedulerTimeGridResourceScroll(FResourceViewShift[Index]);
end;
function TcxSchedulerTimeGridViewViewInfo.GetTimeGridView: TcxSchedulerTimeGridView;
begin
Result := TcxSchedulerTimeGridView(inherited View);
end;
function TcxSchedulerTimeGridViewViewInfo.GetVisibleLineCount(AResourceIndex: Integer): Integer;
begin
if ResourceHeaderCells.Count > 0 then
with ResourceHeaderCells[1 + AResourceIndex] do
Result := (Bounds.Bottom - Bounds.Top) div FEventRowHeight
else
Result := (Bounds.Bottom - ScalesHeight) div FEventRowHeight;
end;
procedure TcxSchedulerTimeGridViewViewInfo.PrepareMoreEventButtons;
var
I: Integer;
begin
ClearMoreEventButtons;
for I := 0 to FResourceViewShift.Count - 1 do
SetLength(GetResourceViewShift(I).FMoreEventButtons, ColumnCount * 2);
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 IsMinorUnitBreak(I) 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
begin
AddMajorSeparator(ALeft);
AActualFinish := AFinish;
end;
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;
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, 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.CalculateTimeLineParams(
ANeedShowCurrentTime: Boolean);
var
ACurrentTime: TDateTime;
ALeft: Integer;
begin
ACurrentTime := Now;
FIsCurrentTimeCell := (ACurrentTime >= TimeStart) and (ACurrentTime < TimeFinish);
FShowCurrentTime := ANeedShowCurrentTime and IsCurrentTimeCell;
if IsCurrentTimeCell then
begin
ALeft := Bounds.Left + Trunc((Bounds.Right - Bounds.Left) *
(ACurrentTime - TimeStart) / (TimeFinish - TimeStart));
FTimeLineRect := Rect(ALeft - 1, Bounds.Top, ALeft + 1, ViewHeight);
end;
end;
procedure TcxSchedulerTimeGridSelectionBarCell.DoDraw;
begin
DrawContent;
if ShowCurrentTime then
FExternalPainter.DrawTimeGridCurrentTime(Canvas,
dxOffice11SelectedDownColor2, TimeLineRect);
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);
ViewInfo.NavigationButtons.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.CalculateActualStart(
var ActualStart, AVisibleStart: TDateTime; var AStartIndex: Integer);
var
AStart: TDateTime;
begin
AStartIndex := 0;
CheckWorkDays(AVisibleStart, True);
AVisibleStart := ValidateStartTime(AVisibleStart);
AStart := ActualStart;
if (AStart <> 0) or (AStart <> ActualStart) then
begin
while not IsPeriodChanged(Dec(ActualStart), AStart) do
ActualStart := Dec(ActualStart);
end;
AStart := ActualStart;
while AStart < AVisibleStart do
begin
AStart := Inc(AStart);
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;
procedure TcxSchedulerTimeBuilder.Initialize(AView: TcxSchedulerTimeGridView;
AWorkTimeOnly, AWorkDaysOnly: Boolean);
begin
ValidateUnits(AView.Scales.FMajorUnit, AView.Scales.FMinorUnit);
MajorUnit := AView.Scales.MajorUnit;
MinorUnit := AView.Scales.MinorUnit;
TimeStep := AView.Scales.TimeStep;
TimeScale := CalculateScaleUnit(AView.Scales.TimeStep);
WorkFinish := AView.WorkFinish;
WorkStart := AView.WorkStart;
WorkDays := AView.WorkDays;
CalculateWorkTime(AWorkTimeOnly, WorkStart, WorkFinish);
CalculateWorkDays(AWorkDaysOnly, WorkDays);
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;
begin
Result := CalculateDateTimeDateTimeWithoutCheckWorkDays(ADateTime, AInc);
CheckWorkDays(Result, AInc > 0);
Result := RoundTime(Result);
end;
function TcxSchedulerTimeBuilder.CalculateDateTimeDateTimeWithoutCheckWorkDays(
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;
if CheckMidnight then
ValidateMidnightForward(Result);
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);
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);
CheckMidnight := AIsWorkTimeOnly and CheckTime and
(TimeOf(WorkFinish) - EncodeTime(23, 59, 59, 0) <= SecondToTime);
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.GetScaleStep: TDateTime;
begin
if TimeMode then
Result := TimeScale * MinuteToTime
else
Result := TimeScale;
end;
procedure TcxSchedulerTimeBuilder.ValidateMidnightForward(
var ADateTime: TDateTime);
const
MSecToTime = 1 / MSecsPerDay;
begin
if Abs(TimeOf(ADateTime - MSecToTime) - WorkFinish) <= MinuteToTime then
ADateTime := DateOf(ADateTime - MSecToTime) + WorkFinish
end;
function TcxSchedulerTimeBuilder.RoundTime(const ADateTime: TDateTime): TDateTime;
begin
Result := DateTimeHelper.RoundTime(ADateTime);
end;
function TcxSchedulerTimeBuilder.ValidateStartTime(
const ADateTime: TDateTime): TDateTime;
begin
Result := ADateTime;
if CheckTime then
begin
if (RoundTime(TimeOf(Result)) > WorkFinish) then
Result := Trunc(Result) + WorkFinish
else
if (RoundTime(TimeOf(Result)) < WorkStart) then
Result := Trunc(Result) + WorkStart
end;
ValidateVisibleStart(Result);
end;
function TcxSchedulerTimeBuilder.ValidateTime(
var ADateTime: TDateTime; AGoForward: Boolean; AInc: Integer = 1): Boolean;
var
ARoundedDateTime: TDateTime;
AMinorUnitsPerDay: Integer;
begin
ARoundedDateTime := RoundTime(TimeOf(ADateTime));
Result := CheckTime and ((ARoundedDateTime > WorkFinish) or
(ARoundedDateTime < WorkStart));
if Result then
begin
if (AInc = 0) and AGoForward and (ARoundedDateTime > WorkFinish) then
AInc := 1;
if AGoForward then
ADateTime := RoundTime(Trunc(ADateTime) + AInc + WorkStart)
else
begin
if CheckMidnight then
begin
AMinorUnitsPerDay := 24 * 60 div TimeStep;
ADateTime := RoundTime(Trunc(ADateTime) - AInc +
Trunc(WorkFinish * AMinorUnitsPerDay) / AMinorUnitsPerDay)
end
else
ADateTime := RoundTime(Trunc(ADateTime) - AInc + WorkFinish);
end;
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;
ADateTime := RoundTime(ADateTime);
end;
{ TcxSchedulerTimeGridResourceScroll }
destructor TcxSchedulerTimeGridResourceScroll.Destroy;
begin
FScrollBar.Free;
inherited Destroy;
end;
procedure TcxSchedulerTimeGridResourceScroll.CreateScrollBar(
AResourceBounds: TRect; ATimeGridView: TcxSchedulerTimeGridView;
AResourceIndex, ARange, APosition: Integer);
var
AHeight: Integer;
begin
if FScrollBar = nil then
begin
FScrollBar := TcxSchedulerTimeGridScrollBar.Create(nil);
FScrollBar.Kind := sbVertical;
FScrollBar.LookAndFeel.MasterLookAndFeel := ATimeGridView.GetSchedulerLookAndFeel();
end;
FScrollBar.FResourceIndex := AResourceIndex;
FScrollBar.Min := 0;
FScrollBar.Max := ARange;
FScrollBar.Position := APosition;
FScrollBar.LargeChange := ATimeGridView.ViewInfo.GetVisibleLineCount(AResourceIndex);
AHeight := AResourceBounds.Bottom - AResourceBounds.Top - 1;
FScrollBar.SetBounds(AResourceBounds.Right - GetScrollBarSize.cx + 1,
AResourceBounds.Top + 2, GetScrollBarSize.cx, AHeight);
FScrollBar.Visible := AHeight > 0;
FScrollBar.OnScroll := ATimeGridView.ViewInfo.DoResourceVerticalScroll;
FScrollBar.Parent := ATimeGridView.Scheduler;
end;
procedure TcxSchedulerTimeGridResourceScroll.ClearMoreEventButtons;
var
I, ALength: Integer;
begin
ALength := Length(FMoreEventButtons);
for I := 0 to ALength - 1 do
FMoreEventButtons[I] := nil;
end;
procedure TcxSchedulerTimeGridResourceScroll.SetEventMaxLine(AValue: Integer);
begin
FEventMaxLine := Max(FEventMaxLine, AValue);
end;
procedure TcxSchedulerTimeGridResourceScroll.Store(AClear: Boolean);
begin
FData := FShift;
if AClear then
FShift := 0;
end;
procedure TcxSchedulerTimeGridResourceScroll.Restore;
begin
FShift := FData;
end;
end.