git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.DevExpressVCL@38 05c56307-c608-d34a-929d-697000501d7a
3418 lines
111 KiB
ObjectPascal
3418 lines
111 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 cxSchedulerDayView;
|
|
|
|
{$I cxVer.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF DELPHI6}
|
|
Types, DateUtils,
|
|
{$ENDIF}
|
|
Windows, Forms, Classes, SysUtils, Math, StdCtrls, Graphics, Controls,
|
|
ExtCtrls, cxControls, cxGraphics, cxStyles, cxGeometry, Menus,
|
|
cxLookAndFeelPainters, cxSchedulerCustomControls, cxSchedulerCustomResourceView,
|
|
cxSchedulerUtils, cxSchedulerStorage, cxSchedulerStrs, cxEdit;
|
|
|
|
const
|
|
|
|
cxcsHeaderContainer = 0;
|
|
cxcsSelectedHeaderContainer = 1;
|
|
cxcsTimeLine = 2;
|
|
cxcsTimeRuler = 3;
|
|
cxcsMaxDayViewValue = cxcsTimeRuler;
|
|
//for PS
|
|
cxcsDayViewStyleFirst = cxcsHeaderContainer;
|
|
cxcsDayViewStyleLast = cxcsMaxDayViewValue;
|
|
|
|
cxSchedulerAllDayEventContainerMaxLineCount: Integer = 0;
|
|
|
|
type
|
|
TcxSchedulerDayViewViewInfo = class;
|
|
TcxEventLayoutInfo = class;
|
|
TcxCalculateEventLayout = class;
|
|
TcxSchedulerDayViewHitTest = class;
|
|
TcxSchedulerDayViewController = class;
|
|
TcxSchedulerTimeRulerPopupMenu = class;
|
|
|
|
IcxSchedulerTimeRulerParams = interface
|
|
['{FEAA09ED-8FE1-4968-9BCB-0FC26B13A391}']
|
|
function GetTimeRulerParams: TcxViewParams;
|
|
end;
|
|
|
|
{ TcxSchedulerDayViewStyles }
|
|
|
|
TcxSchedulerDayViewStyles = class(TcxStyles)
|
|
private
|
|
FScheduler: TcxCustomScheduler;
|
|
function GetPainter: TcxCustomLookAndFeelPainterClass;
|
|
protected
|
|
procedure Changed(AIndex: Integer); override;
|
|
procedure GetDefaultViewParams(Index: Integer; AData: TObject; out AParams: TcxViewParams); override;
|
|
property Painter: TcxCustomLookAndFeelPainterClass read GetPainter;
|
|
public
|
|
constructor Create(AOwner: TPersistent); override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
function GetHeaderContainerParams(const ADate: TDateTime;
|
|
AResource: TcxSchedulerStorageResourceItem; ASelected: Boolean): TcxViewParams;
|
|
function GetTimeRulerParams: TcxViewParams;
|
|
function GetTimeLineParams: TcxViewParams;
|
|
// define colors functions
|
|
property Scheduler: TcxCustomScheduler read FScheduler;
|
|
published
|
|
property HeaderContainer: TcxStyle index cxcsHeaderContainer read GetValue write SetValue;
|
|
property SelectedHeaderContainer: TcxStyle index cxcsSelectedHeaderContainer read GetValue write SetValue;
|
|
property TimeLine: TcxStyle index cxcsTimeLine read GetValue write SetValue;
|
|
property TimeRuler: TcxStyle index cxcsTimeRuler read GetValue write SetValue;
|
|
end;
|
|
|
|
{ TcxSchedulerDayView }
|
|
|
|
TcxSchedulerCustomDrawContainerEvent = procedure(Sender: TObject;
|
|
ACanvas: TcxCanvas; AViewInfo: TcxSchedulerContainerCellViewInfo; var ADone: Boolean) of object;
|
|
TcxSchedulerCustomDrawTimeRulerEvent = procedure(Sender: TObject;
|
|
ACanvas: TcxCanvas; AViewInfo: TcxSchedulerTimeRulerCellViewInfo; var ADone: Boolean) of object;
|
|
|
|
TcxSchedulerDayView = class(TcxSchedulerCustomResourceView)
|
|
private
|
|
FAlwaysShowEventTime: Boolean;
|
|
FAutoContentHeight: Boolean;
|
|
FEventShadows: Boolean;
|
|
FHeaderContainer: Boolean;
|
|
FStyles: TcxSchedulerDayViewStyles;
|
|
FTimeRulerMinutes: Boolean;
|
|
FTimeRulerPopupMenu: TcxSchedulerTimeRulerPopupMenu;
|
|
FTimeScale: Integer;
|
|
FWorkTimeOnly: Boolean;
|
|
FOnCustomDrawContainer: TcxSchedulerCustomDrawContainerEvent;
|
|
FOnCustomDrawTimeRuler: TcxSchedulerCustomDrawTimeRulerEvent;
|
|
function GetHitTest: TcxSchedulerDayViewHitTest;
|
|
function GetViewInfo: TcxSchedulerDayViewViewInfo;
|
|
procedure SetAlwaysShowEventTime(AValue: Boolean);
|
|
procedure SetAutoContentHeight(AValue: Boolean);
|
|
procedure SetEventShadows(AValue: Boolean);
|
|
procedure SetHeaderContainer(AValue: Boolean);
|
|
procedure SetStyles(AValue: TcxSchedulerDayViewStyles);
|
|
procedure SetTimeRulerMinutes(AValue: Boolean);
|
|
procedure SetTimeRulerPopupMenu(AValue: TcxSchedulerTimeRulerPopupMenu);
|
|
procedure SetTimeScale(AValue: Integer);
|
|
procedure SetWorkTimeOnly(AValue: Boolean);
|
|
protected
|
|
// store interface
|
|
procedure GetProperties(AProperties: TStrings); override;
|
|
procedure GetPropertyValue(const AName: string; var AValue: Variant); override;
|
|
procedure SetPropertyValue(const AName: string; const AValue: Variant); override;
|
|
//
|
|
procedure CreateSubClasses; override;
|
|
procedure DestroySubClasses; override;
|
|
function CreateController: TcxSchedulerSubControlController; override;
|
|
function CreateHitTest: TcxSchedulerSubControlHitTest; override;
|
|
function CreatePainter: TcxSchedulerSubControlPainter; override;
|
|
function CreateStyles: TcxSchedulerDayViewStyles; virtual;
|
|
function CreateTimeRulerPopupMenu: TcxSchedulerTimeRulerPopupMenu; virtual;
|
|
function CreateViewAdapter: TcxCustomResourceViewAdapter; override;
|
|
function CreateViewInfo: TcxSchedulerSubControlViewInfo; override;
|
|
procedure DoCustomDrawContainer(ACell: TcxSchedulerContainerCellViewInfo; var ADone: Boolean); virtual;
|
|
procedure DoCustomDrawTimeRuler(ACell: TcxSchedulerTimeRulerCellViewInfo; var ADone: Boolean); virtual;
|
|
function DoShowPopupMenu(X, Y: Integer): Boolean; override;
|
|
function EventContentSelected(AEvent: TcxSchedulerControlEvent): Boolean; override;
|
|
function GetEditWithSingleLineEditor(AEvent: TcxSchedulerControlEvent): Boolean; override;
|
|
function GetTimeIncrement: TDateTime; override;
|
|
function GetViewContentRect: TRect; override;
|
|
function IsDayView: Boolean; override;
|
|
procedure MakeEventVisible(AEvent: TcxSchedulerControlEvent; const ADate: TDateTime;
|
|
AResource: TcxSchedulerStorageResourceItem); override;
|
|
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
|
procedure ScrollVisibleDays(AScrollUp: Boolean); override;
|
|
procedure TimeChanged; override;
|
|
procedure VisibleChanged; override;
|
|
|
|
property ViewInfo: TcxSchedulerDayViewViewInfo read GetViewInfo;
|
|
public
|
|
constructor Create(AOwner: TcxCustomScheduler); override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
procedure MakeWorkTimeVisible;
|
|
|
|
property HitTest: TcxSchedulerDayViewHitTest read GetHitTest;
|
|
property Scheduler;
|
|
property WorkDays;
|
|
property WorkStart;
|
|
property WorkFinish;
|
|
published
|
|
property CanShow; //before active
|
|
property Active;
|
|
property AlwaysShowEventTime: Boolean read FAlwaysShowEventTime write SetAlwaysShowEventTime default False;
|
|
property AutoContentHeight: Boolean read FAutoContentHeight write SetAutoContentHeight default False;
|
|
property EventImagesLayout default eilAuto;
|
|
property EventShadows: Boolean read FEventShadows write SetEventShadows default True;
|
|
property GroupingKind;
|
|
property HeaderContainer: Boolean read FHeaderContainer write SetHeaderContainer default True;
|
|
property Styles: TcxSchedulerDayViewStyles read FStyles write SetStyles;
|
|
property TimeRulerMinutes: Boolean read FTimeRulerMinutes write SetTimeRulerMinutes default False;
|
|
property TimeRulerPopupMenu: TcxSchedulerTimeRulerPopupMenu read FTimeRulerPopupMenu write SetTimeRulerPopupMenu;
|
|
property TimeScale: Integer read FTimeScale write SetTimeScale default cxDefaultTimeScale;
|
|
property WorkTimeOnly: Boolean read FWorkTimeOnly write SetWorkTimeOnly default False;
|
|
property OnCustomDrawContainer: TcxSchedulerCustomDrawContainerEvent read FOnCustomDrawContainer write FOnCustomDrawContainer;
|
|
property OnCustomDrawTimeRuler: TcxSchedulerCustomDrawTimeRulerEvent read FOnCustomDrawTimeRuler write FOnCustomDrawTimeRuler;
|
|
end;
|
|
|
|
{ TcxSchedulerDayViewAdapter }
|
|
|
|
TcxSchedulerDayViewAdapter = class(TcxCustomResourceViewAdapter)
|
|
protected
|
|
FTopIndex: Integer;
|
|
function GetPrintRange(Index: Integer): TDateTime; override;
|
|
procedure Store; override;
|
|
procedure Restore; override;
|
|
end;
|
|
|
|
{ TcxSchedulerDayViewEventCellViewInfo }
|
|
|
|
TcxSchedulerDayViewEventCellViewInfo = class(TcxSchedulerEventCellViewInfo)
|
|
protected
|
|
procedure CalculateCaptions; override;
|
|
procedure CalculateEventTimeVisibility; override;
|
|
procedure CalculateItemsLayout; override;
|
|
procedure CalculateTimeLineParams;
|
|
procedure DrawContent; override;
|
|
procedure DrawSelection;
|
|
procedure DrawShadow;
|
|
procedure DrawState; overload;
|
|
function GetEditingRect: TRect; override;
|
|
procedure InitHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest); override;
|
|
function IsHorzSizing: Boolean; override;
|
|
function IsNeedDrawTime: Boolean; override;
|
|
function IsTimeLineVisible: Boolean; override;
|
|
end;
|
|
|
|
{ TcxSchedulerDayViewViewInfo }
|
|
|
|
TcxSchedulerDayViewViewInfo = class(TcxSchedulerCustomResourceViewViewInfo)
|
|
private
|
|
function GetAutoHeight: Boolean;
|
|
function GetColumnInGroup: Integer;
|
|
function GetContentHeight: Integer;
|
|
function GetController: TcxSchedulerDayViewController;
|
|
function GetDayView: TcxSchedulerDayView;
|
|
function GetGroupCount: Integer;
|
|
function GetHeaderContainer: Boolean;
|
|
function GetPrintRowCount: Integer;
|
|
function GetLinePerHour: Integer;
|
|
procedure SetLargeFont(AFont: TFont);
|
|
protected
|
|
Builder: TcxSchedulerEventLayoutBuilder;
|
|
FAdditionalTimeZone: Integer;
|
|
FBackground: TcxSchedulerBackgroundCellViewInfo;
|
|
FColCount: Integer;
|
|
FContentOffset: Integer;
|
|
FCurrentTimeZone: Integer;
|
|
FDayRowCount: Integer;
|
|
FEventLayout: TcxCalculateEventLayout;
|
|
FHeaderLineCount: Integer;
|
|
FHeaderLineHeight: Integer;
|
|
FHeaderOffsetLeft: Integer;
|
|
FIsContainerSelected: Boolean;
|
|
FIsPrinting: Boolean;
|
|
FLargeFont: TFont;
|
|
FPrintStartRow: Integer;
|
|
FPrintFinishRow: Integer;
|
|
FRowCount: Integer;
|
|
FTimeRulerCells: TcxSchedulerViewInfoCellList;
|
|
FTopIndex: Integer;
|
|
FTimeScale: Integer;
|
|
FUnusedRowCount: Integer;
|
|
FVisibleRowCount: Integer;
|
|
function AddContentCell(const ARect: TRect; const AStart, AFinish: TDateTime;
|
|
AResourceIndex: Integer): TcxSchedulerContentCellViewInfo; override;
|
|
procedure AddContainerCell(AColumn: Integer; const ABounds: TRect);
|
|
procedure AddHeaderContainerEvent(APlace: TcxSchedulerEventPlace);
|
|
procedure AddHeaderContainerEventPlace(AEvent: TcxSchedulerControlEvent; var AColIndex: Integer);
|
|
procedure AddMoreEventsButton(const AIndex, ARowIndex: Integer; AIsTop: Boolean);
|
|
procedure CalculateBackground; virtual;
|
|
procedure CalculateContent; virtual;
|
|
procedure CalculateEvents; virtual;
|
|
procedure CalculateEventsForColumn(AIndex: Integer;
|
|
AContainer: TcxSchedulerContainerCellViewInfo; AEvents: TcxSchedulerEventList); virtual;
|
|
procedure CalculateHeaderEvents; virtual;
|
|
procedure CalculateHeaderEventsPlace;
|
|
procedure CalculateHeaderLineCount;
|
|
procedure CalculateHeaders; virtual;
|
|
procedure CalculateMetrics; override;
|
|
procedure CalculateMetricsForPrinting;
|
|
procedure CalculateDisplayRows;
|
|
procedure CalculateTimeLine; virtual;
|
|
procedure CalculateVisibleRows;
|
|
procedure CalculateUnusedRowCount;
|
|
function CheckDisplayRows(var AStartRow, AFinishRow: Integer): Boolean;
|
|
procedure CheckEventRowsVisibility(AEvent: TcxSchedulerControlEvent;
|
|
AStartRow, AFinishRow: Integer);
|
|
procedure Clear; override;
|
|
function CreateContentEventViewData(AEventInfo: TcxEventLayoutInfo;
|
|
AResource: TcxSchedulerResourceViewInfo): TcxSchedulerEventViewData;
|
|
function CreateHeaderEventViewData(AEvent: TcxSchedulerControlEvent; const ABounds: TRect;
|
|
const AStart, AFinish: TDateTime; AResource: TcxSchedulerResourceViewInfo): TcxSchedulerEventViewData;
|
|
function CreateEventCellViewInfo(AViewData: TcxSchedulerEventViewData): TcxSchedulerEventCellViewInfo; override;
|
|
function CreateEventLayout: TcxCalculateEventLayout; virtual;
|
|
procedure DoCalculate; override;
|
|
procedure DoMoreEventsButtonClick(Sender: TcxSchedulerMoreEventsButtonViewInfo); override;
|
|
procedure ExtractEvents(ASource, ADest: TcxSchedulerEventList; AIndex: Integer);
|
|
function GetContentParams(const ATime: TDateTime;
|
|
AResource: TcxSchedulerResourceViewInfo): TcxViewParams; override;
|
|
function GetColumnDate(AIndex: Integer): Integer;
|
|
function GetColumnResource(AIndex: Integer): TcxSchedulerResourceViewInfo;
|
|
function GetColumnResourceIndex(AIndex: Integer): Integer;
|
|
function GetContainer(AIndex: Integer): TcxSchedulerContainerCellViewInfo; virtual;
|
|
function GetContainerCount: Integer; virtual;
|
|
function GetDayHeaderHeight: Integer; override;
|
|
procedure GetHeaderEventInfo(AColStart, AColFinish: Integer;
|
|
out ALeft, ARight: Integer; out AStart, AFinish: TDateTime);
|
|
function GetEventColumnRow(const ATime: TDateTime; AColIndex: Integer; AStart: Boolean): Integer;
|
|
function GetEventSlotDisplayText(AEvent: TcxSchedulerControlEvent): string;
|
|
function GetTimeLineParams: TcxViewParams; override;
|
|
function GetTimeRulerParams: TcxViewParams;
|
|
function GetTimeRow(const ATime: TDateTime; AIsStart: Boolean): Integer;
|
|
function GetResourcesContentWidth: Integer; override;
|
|
function GetRowTime(AColumn, ARow: Integer): TDateTime;
|
|
function GetSeparatorCount: Integer; override;
|
|
function IsColumnEvent(AEvent: TcxSchedulerEvent; AIndex: Integer; IsHeaderEvent: Boolean): Boolean;
|
|
function IsContainerSelected(AResource: TcxSchedulerStorageResourceItem; ADate: TDateTime): Boolean;
|
|
function IsEventVisible(AEvent: TcxSchedulerEvent): Boolean; overload;
|
|
function IsEventVisible(var AStartRow, AStopRow: Integer): Boolean; overload;
|
|
function IsHourVisible(AIndex: Integer): Boolean;
|
|
function IsRowVisible(AIndex: Integer): Boolean;
|
|
procedure MakeTimeVisible(const ATime: TDateTime); override;
|
|
procedure SetColumnTimeLineStyle(AViewInfo: TcxSchedulerEventCellViewInfo; AColIndex: Integer);
|
|
|
|
property ColCount: Integer read FColCount;
|
|
property ColumnInGroup: Integer read GetColumnInGroup;
|
|
property ContainerCount: Integer read GetContainerCount;
|
|
property Containers[AIndex: Integer]: TcxSchedulerContainerCellViewInfo read GetContainer;
|
|
property Controller: TcxSchedulerDayViewController read GetController;
|
|
property GroupCount: Integer read GetGroupCount;
|
|
public
|
|
constructor Create(AOwner: TcxSchedulerSubControl); override;
|
|
destructor Destroy; override;
|
|
procedure CalculateHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest); override;
|
|
procedure InitScrollBarsParameters; override;
|
|
procedure ScrollVertical(AScrollCode: TScrollCode; var AScrollPos: Integer); override;
|
|
|
|
property AutoHeight: Boolean read GetAutoHeight;
|
|
property Background: TcxSchedulerBackgroundCellViewInfo read FBackground;
|
|
property ContentHeight: Integer read GetContentHeight;
|
|
property DayView: TcxSchedulerDayView read GetDayView;
|
|
property HeaderContainer: Boolean read GetHeaderContainer;
|
|
property HeaderContainerCells: TcxSchedulerViewInfoCellList read FHeaderContainerCells;
|
|
property HeaderLineHeight: Integer read FHeaderLineHeight;
|
|
property IsPrinting: Boolean read FIsPrinting;
|
|
property LargeFont: TFont read FLargeFont write SetLargeFont;
|
|
property LinePerHour: Integer read GetLinePerHour;
|
|
property PrintRowCount: Integer read GetPrintRowCount;
|
|
property PrintFinishRow: Integer read FPrintFinishRow;
|
|
property PrintStartRow: Integer read FPrintStartRow;
|
|
property TimeScale: Integer read FTimeScale;
|
|
property TimeRulerCells: TcxSchedulerViewInfoCellList read FTimeRulerCells;
|
|
property TopIndex: Integer read FTopIndex;
|
|
property UnusedRowCount: Integer read FUnusedRowCount;
|
|
property VisibleRowCount: Integer read FVisibleRowCount;
|
|
end;
|
|
|
|
{ TcxSchedulerDayViewHitTest }
|
|
|
|
TcxSchedulerDayViewHitTest = class(TcxSchedulerCustomResourceViewHitTest)
|
|
private
|
|
function GetContainerCell: TcxSchedulerContainerCellViewInfo;
|
|
function GetTimeRulerCell: TcxSchedulerTimeRulerCellViewInfo;
|
|
public
|
|
property ContainerCell: TcxSchedulerContainerCellViewInfo read GetContainerCell;
|
|
property HitAtContainer: Boolean index htcContainer read GetBitState;
|
|
property HitAtTimeRuler: Boolean index htcTimeRuler read GetBitState;
|
|
property TimeRulerCell: TcxSchedulerTimeRulerCellViewInfo read GetTimeRulerCell;
|
|
property HitAtTimeZoneLabel;
|
|
property TimeZone;
|
|
end;
|
|
|
|
{ TcxDayViewDragEventHelper }
|
|
|
|
TcxDayViewDragEventHelper = class(TcxDragEventHelper)
|
|
private
|
|
FStartInHeader: Boolean;
|
|
function GetController: TcxSchedulerDayViewController;
|
|
function GetHitTest: TcxSchedulerDayViewHitTest;
|
|
function GetShowHeaderContainer: Boolean;
|
|
protected
|
|
function GetOriginHitTestMask: Int64; override;
|
|
procedure GetOriginState; override;
|
|
function IsAtOrigin: Boolean; override;
|
|
function InHeader: Boolean; virtual;
|
|
procedure SetCloneEventsTimeDelta(AStart, ACurrent: TDateTime; AInHeader: Boolean);
|
|
procedure UpdateViewClonesTime; override;
|
|
procedure UpdateEventStates;
|
|
|
|
property Controller: TcxSchedulerDayViewController read GetController;
|
|
property HitTest: TcxSchedulerDayViewHitTest read GetHitTest;
|
|
property ShowHeaderContainer: Boolean read GetShowHeaderContainer;
|
|
end;
|
|
|
|
{ TcxDayViewEventSizing }
|
|
|
|
TcxDayViewEventSizing = class(TcxEventSizingHelper)
|
|
private
|
|
FFixedBoundTime: TDateTime;
|
|
function GetController: TcxSchedulerDayViewController;
|
|
function GetHitTest: TcxSchedulerDayViewHitTest;
|
|
protected
|
|
function GetDragCursor(Accepted: Boolean): TCursor; override;
|
|
function GetOriginHitTestMask: Int64; override;
|
|
// Event handling
|
|
procedure CalcAllDayEvent; override;
|
|
function GetFinishTime: TDateTime; override;
|
|
procedure GetOriginState; override;
|
|
function GetSizingTime: TDateTime;
|
|
function GetStartTime: TDateTime; override;
|
|
|
|
property Controller: TcxSchedulerDayViewController read GetController;
|
|
property HitTest: TcxSchedulerDayViewHitTest read GetHitTest;
|
|
end;
|
|
|
|
{ TcxSchedulerDayNavigation }
|
|
|
|
TcxSchedulerDayNavigation = class(TcxSchedulerCustomResourceViewNavigation)
|
|
private
|
|
function GetDayView: TcxSchedulerDayView;
|
|
function GetSelectedDays: TcxSchedulerDateList;
|
|
function GetViewInfo: TcxSchedulerDayViewViewInfo;
|
|
protected
|
|
FSelRow: Integer;
|
|
function ColCount: Integer;
|
|
procedure DoNextColumn(AGoToNext: Boolean; AColumn: Integer;
|
|
const ATime: TDateTime; AResource: TcxSchedulerStorageResourceItem); virtual;
|
|
function DoNextPage(AGoForward: Boolean; var ATime: TDateTime;
|
|
var AResource: TcxSchedulerStorageResourceItem): Boolean; virtual;
|
|
function GetColumnByDate(const ADate: TDateTime; AResource: TObject): Integer;
|
|
function GetColumnDate(AColumn: Integer): TDateTime;
|
|
function GetColumnResource(AColumn: Integer): TcxSchedulerStorageResourceItem;
|
|
function GetRowTime(const ARow: Integer; AFinish: Boolean = False): TDateTime;
|
|
function GetTimeRow(const ATime: TDateTime): Integer;
|
|
function IsResourceNavigation(AGoToNext: Boolean;
|
|
AColumn: Integer; const ATime: TDateTime): Boolean;
|
|
public
|
|
procedure KeyDown(var AKey: Word; AShift: TShiftState); override;
|
|
procedure ValidateSelection(var ASelStart, ASelFinish: TDateTime;
|
|
var AResource: TcxSchedulerStorageResourceItem); override;
|
|
function ValidateTimeVisibility(var ADateTime: TDateTime): TDateTime;
|
|
|
|
property DayView: TcxSchedulerDayView read GetDayView;
|
|
property SelectedDays: TcxSchedulerDateList read GetSelectedDays;
|
|
property ViewInfo: TcxSchedulerDayViewViewInfo read GetViewInfo;
|
|
end;
|
|
|
|
{ TcxSchedulerDayViewController }
|
|
|
|
TcxSchedulerDayViewController = class(TcxSchedulerCustomResourceViewController)
|
|
private
|
|
FLockScrolling: Boolean;
|
|
FTimer: TTimer;
|
|
function GetHitTest: TcxSchedulerDayViewHitTest;
|
|
function GetTimeRulerTime: TDateTime;
|
|
function GetViewInfo: TcxSchedulerDayViewViewInfo;
|
|
protected
|
|
FIsEditingBeforeMouseDown: Boolean;
|
|
FScrollAreaRects: TList;
|
|
procedure BeforeMouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure CancelScroll; override;
|
|
procedure CheckScrolling(const APos: TPoint); override;
|
|
procedure CheckTimeRulerTime;
|
|
function CreateDragEventHelper: TcxDragEventHelper; override;
|
|
function CreateNavigation: TcxSchedulerViewNavigation; override;
|
|
function CreateResizeEventHelper: TcxEventSizingHelper; 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 OnTimer(Sender: TObject); virtual;
|
|
//
|
|
procedure CheckNavigatorScrollArea(const APoint: TPoint); override;
|
|
procedure DoneNavigatorScrollArea; override;
|
|
procedure InitNavigatorScrollArea; override;
|
|
|
|
property HitTest: TcxSchedulerDayViewHitTest read GetHitTest;
|
|
property ViewInfo: TcxSchedulerDayViewViewInfo read GetViewInfo;
|
|
public
|
|
constructor Create(AOwner: TcxSchedulerSubControl); override;
|
|
destructor Destroy; override;
|
|
end;
|
|
|
|
{ TcxSchedulerDayViewPainter }
|
|
|
|
TcxSchedulerDayViewPainter = class(TcxSchedulerCustomViewPainter)
|
|
private
|
|
function GetView: TcxSchedulerDayView;
|
|
function GetViewInfo: TcxSchedulerDayViewViewInfo;
|
|
protected
|
|
procedure DrawContainerCell(AItem: TcxSchedulerCustomViewInfoItem; var ADone: Boolean); virtual;
|
|
procedure DrawDayViewEventCell(AItem: TcxSchedulerCustomViewInfoItem; var ADone: Boolean); virtual;
|
|
procedure DrawTimeRulerCell(AItem: TcxSchedulerCustomViewInfoItem; var ADone: Boolean); virtual;
|
|
public
|
|
procedure Paint; override;
|
|
|
|
property View: TcxSchedulerDayView read GetView;
|
|
property ViewInfo: TcxSchedulerDayViewViewInfo read GetViewInfo;
|
|
end;
|
|
|
|
{ TcxEventLayoutInfo }
|
|
|
|
TcxEventLayoutInfo = class
|
|
private
|
|
protected
|
|
ColStart, ColEnd, ColCount: Integer;
|
|
Event: TcxSchedulerControlEvent;
|
|
FDisplayRect: TRect;
|
|
FFinishTime: TDateTime;
|
|
FStartTime: TDateTime;
|
|
IsBreakEvent: Boolean;
|
|
RowCount: Integer;
|
|
StartRow, StopRow: Integer;
|
|
function ShadowSize: Integer;
|
|
procedure CalculateDisplayRect(AWidth, ARowHeight: Integer);
|
|
procedure CalculateTimes(const ADate: TDateTime; AScale, AOfs: Integer);
|
|
public
|
|
constructor Create(AEvent: TcxSchedulerControlEvent;
|
|
const ADate: TDateTime; AScale: Integer); virtual;
|
|
|
|
property DisplayRect: TRect read FDisplayRect;
|
|
property Finish: TDateTime read FFinishTime;
|
|
property Start: TDateTime read FStartTime;
|
|
end;
|
|
|
|
{ TcxCalculateEventLayout }
|
|
|
|
TcxCalculateEventLayout = class(TList)
|
|
private
|
|
FDate: TDateTime;
|
|
FLeft: Integer;
|
|
FRowHeight: Integer;
|
|
FTimeScale: Integer;
|
|
FTop: Integer;
|
|
FWidth: Integer;
|
|
function GetInfo(AIndex: Integer): TcxEventLayoutInfo;
|
|
protected
|
|
FViewInfo: TcxSchedulerDayViewViewInfo;
|
|
procedure CalculateColCount(AInfo: TcxEventLayoutInfo); virtual;
|
|
procedure CalculateColEnd(AInfo: TcxEventLayoutInfo); virtual;
|
|
procedure CalculateColStart(AInfo: TcxEventLayoutInfo; AIndex: Integer); virtual;
|
|
function CreateEventInfo(AEvent: TcxSchedulerControlEvent): TcxEventLayoutInfo;
|
|
function Intersect(AInfo1, AInfo2: TcxEventLayoutInfo): Boolean;
|
|
procedure SetColCount(AInfo: TcxEventLayoutInfo);
|
|
public
|
|
procedure Add(AEvent: TcxSchedulerControlEvent);
|
|
procedure Calculate;
|
|
procedure Clear; override;
|
|
procedure SetParams(const ADate: TDateTime; ATimeScale, ARowHeight: Integer;
|
|
ALeft, ATop, AWidth: Integer);
|
|
|
|
property Date: TDateTime read FDate write FDate;
|
|
property Infos[Index: Integer]: TcxEventLayoutInfo read GetInfo;
|
|
property Left: Integer read FLeft;
|
|
property RowHeight: Integer read FRowHeight;
|
|
property TimeScale: Integer read FTimeScale;
|
|
property Top: Integer read FTop;
|
|
property Width: Integer read FWidth;
|
|
end;
|
|
|
|
{ TcxSchedulerTimeRulerPopupMenu }
|
|
|
|
TcxSchedulerTimeRulerPopupMenuItem = (rpmiNewEvent, rpmiNewAllDayEvent,
|
|
rpmiNewReccuringEvent, rpmi60min, rpmi30min, rpmi15min, rpmi10min,
|
|
rpmi6min, rpmi5min);
|
|
TcxSchedulerTimeRulerPopupMenuItems = set of TcxSchedulerTimeRulerPopupMenuItem;
|
|
|
|
TcxSchedulerTimeRulerPopupMenuPopupEvent = procedure (
|
|
Sender: TcxSchedulerTimeRulerPopupMenu; ABuiltInMenu: TPopupMenu;
|
|
var AHandled: Boolean) of object;
|
|
TcxSchedulerTimeRulerPopupMenuClickEvent = procedure (
|
|
Sender: TcxSchedulerTimeRulerPopupMenu;
|
|
AItem: TcxSchedulerTimeRulerPopupMenuItem; var AHandled: Boolean) of object;
|
|
|
|
TcxSchedulerTimeRulerPopupMenu = class(TcxSchedulerCustomContentPopupMenu)
|
|
private
|
|
FItems: TcxSchedulerTimeRulerPopupMenuItems;
|
|
FOnPopup: TcxSchedulerTimeRulerPopupMenuPopupEvent;
|
|
FOnClick: TcxSchedulerTimeRulerPopupMenuClickEvent;
|
|
function GetDayView: TcxSchedulerDayView;
|
|
protected
|
|
procedure CreateItems; override;
|
|
procedure DoExecute(ACommand: Integer); override;
|
|
function DoOnClick(ACommand: Integer): Boolean; override;
|
|
function DoOnPopup: Boolean; override;
|
|
function IsValidCommand(ACommand: Integer): Boolean; override;
|
|
|
|
property DayView: TcxSchedulerDayView read GetDayView;
|
|
public
|
|
constructor Create(AScheduler: TcxCustomScheduler); override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
procedure Execute(AItem: TcxSchedulerTimeRulerPopupMenuItem);
|
|
function GetMenuItem(AItem: TcxSchedulerTimeRulerPopupMenuItem): TMenuItem;
|
|
published
|
|
property Items: TcxSchedulerTimeRulerPopupMenuItems
|
|
read FItems write FItems default [rpmiNewEvent, rpmiNewAllDayEvent,
|
|
rpmiNewReccuringEvent, rpmi60min, rpmi30min, rpmi15min, rpmi10min,
|
|
rpmi6min, rpmi5min];
|
|
property PopupMenu;
|
|
property UseBuiltInPopupMenu;
|
|
|
|
property OnClick: TcxSchedulerTimeRulerPopupMenuClickEvent read FOnClick write FOnClick;
|
|
property OnPopup: TcxSchedulerTimeRulerPopupMenuPopupEvent read FOnPopup write FOnPopup;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
cxDateUtils, cxClasses, cxLibraryConsts;
|
|
|
|
const
|
|
cxMinutesPerDay = 24 * 60;
|
|
RulerScales: array[0..5] of Integer = (60, 30, 15, 10, 6, 5);
|
|
|
|
function GetTimeMinutes(const ATime: TDateTime): Integer;
|
|
var
|
|
H, M, S, MS: Word;
|
|
begin
|
|
DecodeTime(ATime, H, M, S, MS);
|
|
Result := H * 60 + M;
|
|
end;
|
|
|
|
{ TcxSchedulerDayViewStyles }
|
|
|
|
constructor TcxSchedulerDayViewStyles.Create(AOwner: TPersistent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FScheduler := TcxSchedulerDayView(GetOwner).Scheduler;
|
|
BitmapInViewParams := True;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewStyles.Assign(Source: TPersistent);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if Source is TcxSchedulerDayViewStyles then
|
|
begin
|
|
for I := 0 to cxcsMaxDayViewValue do
|
|
SetValue(I, TcxSchedulerDayViewStyles(Source).GetValue(I))
|
|
end;
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewStyles.Changed(AIndex: Integer);
|
|
begin
|
|
TcxSchedulerDayView(GetOwner).Refresh;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewStyles.GetDefaultViewParams(Index: Integer;
|
|
AData: TObject; out AParams: TcxViewParams);
|
|
begin
|
|
AParams.Bitmap := nil;
|
|
AParams.Font := Scheduler.Font;
|
|
AParams.TextColor := clBlack;
|
|
AParams.Color := Scheduler.Color;
|
|
case Index of
|
|
cxcsHeaderContainer:
|
|
begin
|
|
AParams.Color := Painter.DefaultHeaderBackgroundColor;
|
|
AParams.TextColor := Painter.DefaultHeaderBackgroundTextColor;
|
|
end;
|
|
cxcsSelectedHeaderContainer:
|
|
begin
|
|
AParams.Color := Painter.DefaultContentColor;
|
|
AParams.TextColor := Painter.DefaultContentTextColor;
|
|
end;
|
|
cxcsTimeLine:
|
|
begin
|
|
AParams.Color := clWhite;
|
|
AParams.TextColor := Scheduler.OptionsView.DayBorderColor;
|
|
if AParams.TextColor = clDefault then
|
|
AParams.TextColor := clWindowText;
|
|
end;
|
|
cxcsTimeRuler:
|
|
begin
|
|
AParams.Color := Painter.DefaultHeaderColor;
|
|
AParams.TextColor := Painter.DefaultHeaderTextColor;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewStyles.GetHeaderContainerParams(
|
|
const ADate: TDateTime; AResource: TcxSchedulerStorageResourceItem;
|
|
ASelected: Boolean): TcxViewParams;
|
|
begin
|
|
GetViewParams(cxcsHeaderContainer + Byte(ASelected), nil, nil, Result);
|
|
end;
|
|
|
|
function TcxSchedulerDayViewStyles.GetTimeLineParams: TcxViewParams;
|
|
begin
|
|
GetViewParams(cxcsTimeLine, nil, nil, Result);
|
|
end;
|
|
|
|
function TcxSchedulerDayViewStyles.GetTimeRulerParams: TcxViewParams;
|
|
begin
|
|
GetViewParams(cxcsTimeRuler, nil, nil, Result);
|
|
end;
|
|
|
|
function TcxSchedulerDayViewStyles.GetPainter: TcxCustomLookAndFeelPainterClass;
|
|
begin
|
|
Result := TcxSchedulerDayView(GetOwner).LookAndFeelPainter;
|
|
end;
|
|
|
|
//procedures
|
|
function cxCompareTime(const ATime1, ATime2: TDateTime): Integer;
|
|
begin
|
|
Result := 0;
|
|
if ATime1 < ATime2 then
|
|
Result := -1
|
|
else
|
|
if ATime1 > ATime2 then
|
|
Result := 1;
|
|
end;
|
|
|
|
function cxCompareButtons(AItem1, AItem2: TcxSchedulerMoreEventsButtonViewInfo): Integer;
|
|
begin
|
|
Result := Byte(AItem1 <> nil) - Byte(AItem2 <> nil);
|
|
if Result = 0 then
|
|
Result := Byte(not AItem1.IsDown) - Byte(not AItem2.IsDown);
|
|
if Result = 0 then
|
|
begin
|
|
if AItem1.IsDown then
|
|
Result := cxCompareTime(AItem1.DateTime, AItem2.DateTime)
|
|
else
|
|
Result := cxCompareTime(AItem2.DateTime, AItem1.DateTime)
|
|
end;
|
|
end;
|
|
|
|
function cxCompareEventViewInfoOrders(
|
|
AInfo1, AInfo2: TcxSchedulerEventCellViewInfo): Integer;
|
|
var
|
|
AAllDay1, AAllDay2: Boolean;
|
|
AEvent1, AEvent2: TcxSchedulerEvent;
|
|
begin
|
|
Result := Byte(AInfo2.Visible) - Byte(AInfo1.Visible);
|
|
if Result = 0 then
|
|
Result := Byte(AInfo1.Selected) - Byte(AInfo2.Selected);
|
|
if Result = 0 then
|
|
Result := Byte(AInfo2.Hidden) - Byte(AInfo1.Hidden);
|
|
if Result = 0 then
|
|
begin
|
|
AEvent1 := AInfo1.Event;
|
|
AEvent2 := AInfo2.Event;
|
|
AAllDay1 := AEvent1.AllDayEvent or (AEvent1.Duration >= 1);
|
|
AAllDay2 := AEvent2.AllDayEvent or (AEvent2.Duration >= 1);
|
|
Result := Byte(AAllDay2) - Byte(AAllDay1);
|
|
if Result <> 0 then Exit;
|
|
if AEvent1.Start < AEvent2.Start then
|
|
Result := -1
|
|
else
|
|
if AEvent1.Start > AEvent2.Start then
|
|
Result := 1
|
|
else
|
|
if AEvent1.Finish > AEvent2.Finish then
|
|
Result := -1
|
|
else
|
|
if AEvent1.Finish < AEvent2.Finish then
|
|
Result := 1
|
|
else
|
|
Result := 0;
|
|
end;
|
|
end;
|
|
|
|
{ TcxEventLayoutInfo }
|
|
|
|
constructor TcxEventLayoutInfo.Create(AEvent: TcxSchedulerControlEvent;
|
|
const ADate: TDateTime; AScale: Integer);
|
|
var
|
|
AFinish: Integer;
|
|
begin
|
|
Event := AEvent;
|
|
AFinish := Round(TimeOf(Event.Finish) / MinuteToTime);
|
|
StartRow := Round(TimeOf(AEvent.Start) / MinuteToTime) div AScale;
|
|
StopRow := AFinish div AScale;
|
|
if (StopRow <> StartRow) and (AFinish mod AScale = 0) then
|
|
Dec(StopRow);
|
|
|
|
if DateOf(Event.Start) <> DateOf(Event.Finish) then
|
|
begin
|
|
if DateOf(ADate) = DateOf(Event.Start) then
|
|
StopRow := cxMinutesPerDay div AScale - 1
|
|
else
|
|
StartRow := 0;
|
|
end;
|
|
IsBreakEvent := (StopRow = cxMinutesPerDay div AScale - 1);
|
|
end;
|
|
|
|
function TcxEventLayoutInfo.ShadowSize: Integer;
|
|
begin
|
|
Result := TcxSchedulerPainterHelper.ShadowSize;
|
|
end;
|
|
|
|
procedure TcxEventLayoutInfo.CalculateDisplayRect(
|
|
AWidth, ARowHeight: Integer);
|
|
begin
|
|
FDisplayRect := Rect(MulDiv(AWidth, ColStart, ColCount), StartRow * ARowHeight,
|
|
MulDiv(AWidth, ColEnd, ColCount) - ShadowSize, (StopRow + 1) * ARowHeight + Byte(IsBreakEvent));
|
|
end;
|
|
|
|
procedure TcxEventLayoutInfo.CalculateTimes(
|
|
const ADate: TDateTime; AScale, AOfs: Integer);
|
|
begin
|
|
FFinishTime := ADate + (StopRow + 1 + AOfs) * AScale * MinuteToTime;
|
|
FStartTime := ADate + (StartRow + AOfs)* AScale * MinuteToTime;
|
|
end;
|
|
|
|
{ TcxCalculateEventLayout }
|
|
|
|
procedure TcxCalculateEventLayout.Add(AEvent: TcxSchedulerControlEvent);
|
|
var
|
|
AEventInfo: TcxEventLayoutInfo;
|
|
begin
|
|
AEventInfo := CreateEventInfo(AEvent);
|
|
if AEventInfo <> nil then
|
|
inherited Add(AEventInfo);
|
|
end;
|
|
|
|
procedure TcxCalculateEventLayout.Calculate;
|
|
var
|
|
I: Integer;
|
|
AInfo: TcxEventLayoutInfo;
|
|
begin
|
|
for I := 0 to Count - 1 do
|
|
begin
|
|
AInfo := Infos[I];
|
|
CalculateColCount(AInfo);
|
|
CalculateColStart(AInfo, I);
|
|
SetColCount(AInfo);
|
|
end;
|
|
// Find ColEnd for events
|
|
for I := 0 to Count - 1 do
|
|
CalculateColEnd(Infos[I]);
|
|
for I := 0 to Count - 1 do
|
|
begin
|
|
AInfo := Infos[I];
|
|
AInfo.StartRow := Max(0, AInfo.StartRow - FViewInfo.PrintStartRow);
|
|
AInfo.StopRow := Min(FViewInfo.FRowCount, AInfo.StopRow - FViewInfo.PrintStartRow);
|
|
AInfo.CalculateDisplayRect(FWidth, FRowHeight);
|
|
OffsetRect(AInfo.FDisplayRect, Left, Top - Byte(FViewInfo.IsPrinting));
|
|
AInfo.CalculateTimes(FDate, FTimeScale, FViewInfo.PrintStartRow);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCalculateEventLayout.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := Count - 1 downto 0 do
|
|
Infos[I].Free;
|
|
inherited Clear;
|
|
end;
|
|
|
|
procedure TcxCalculateEventLayout.SetParams(const ADate: TDateTime;
|
|
ATimeScale, ARowHeight: Integer; ALeft, ATop, AWidth: Integer);
|
|
begin
|
|
FDate := ADate;
|
|
FTimeScale := ATimeScale;
|
|
FRowHeight := ARowHeight;
|
|
FLeft := ALeft;
|
|
FTop := ATop;
|
|
FWidth := AWidth;
|
|
end;
|
|
|
|
procedure TcxCalculateEventLayout.CalculateColCount(
|
|
AInfo: TcxEventLayoutInfo);
|
|
var
|
|
I, J: Integer;
|
|
begin
|
|
for I := AInfo.StartRow to AInfo.StopRow do
|
|
begin
|
|
AInfo.ColEnd := 0;
|
|
for J := 0 to Count - 1 do
|
|
if (I >= Infos[J].StartRow) and (I <= Infos[J].StopRow) then
|
|
Inc(AInfo.ColEnd);
|
|
if AInfo.ColCount < AInfo.ColEnd then
|
|
AInfo.ColCount := AInfo.ColEnd;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCalculateEventLayout.CalculateColEnd(
|
|
AInfo: TcxEventLayoutInfo);
|
|
var
|
|
I: Integer;
|
|
AEventInfo: TcxEventLayoutInfo;
|
|
begin
|
|
AInfo.ColEnd := AInfo.ColCount;
|
|
for I := 0 to Count - 1 do
|
|
begin
|
|
AEventInfo := Infos[I];
|
|
if (AEventInfo.ColStart > AInfo.ColStart) and
|
|
(AEventInfo.ColStart < AInfo.ColEnd) and Intersect(AInfo, AEventInfo) then
|
|
begin
|
|
AInfo.ColEnd := AEventInfo.ColStart;
|
|
if AInfo.ColEnd = AInfo.ColStart + 1 then Break;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCalculateEventLayout.CalculateColStart(
|
|
AInfo: TcxEventLayoutInfo; AIndex: Integer);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
repeat
|
|
AInfo.ColEnd := AInfo.ColStart;
|
|
for I := AIndex - 1 downto 0 do
|
|
if (Infos[I].ColStart = AInfo.ColStart) and Intersect(Infos[I], AInfo) then
|
|
begin
|
|
Inc(AInfo.ColStart);
|
|
Break;
|
|
end;
|
|
until (AInfo.ColStart = AInfo.ColEnd) or (AInfo.ColStart = (AInfo.ColCount - 1));
|
|
end;
|
|
|
|
function TcxCalculateEventLayout.CreateEventInfo(
|
|
AEvent: TcxSchedulerControlEvent): TcxEventLayoutInfo;
|
|
begin
|
|
Result := TcxEventLayoutInfo.Create(AEvent, FDate, FTimeScale);
|
|
with FViewInfo do
|
|
if HasVisibleBounds and not IsEventVisible(Result.StartRow, Result.StopRow) then
|
|
FreeAndNil(Result);
|
|
end;
|
|
|
|
function TcxCalculateEventLayout.Intersect(
|
|
AInfo1, AInfo2: TcxEventLayoutInfo): Boolean;
|
|
begin
|
|
Result := (AInfo1.StartRow <= AInfo2.StopRow) and
|
|
(AInfo2.StartRow <= AInfo1.StopRow);
|
|
end;
|
|
|
|
procedure TcxCalculateEventLayout.SetColCount(
|
|
AInfo: TcxEventLayoutInfo);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to Count - 1 do
|
|
begin
|
|
if (Infos[I].ColCount < AInfo.ColCount) and Intersect(Infos[I], AInfo) then
|
|
begin
|
|
Infos[I].ColCount := AInfo.ColCount;
|
|
SetColCount(Infos[I]);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxCalculateEventLayout.GetInfo(
|
|
AIndex: Integer): TcxEventLayoutInfo;
|
|
begin
|
|
Result := TcxEventLayoutInfo(List^[AIndex]);
|
|
end;
|
|
|
|
{ TcxSchedulerDayView }
|
|
|
|
constructor TcxSchedulerDayView.Create(AOwner: TcxCustomScheduler);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FTimeScale := cxDefaultTimeScale;
|
|
FHeaderContainer := True;
|
|
EventImagesLayout := eilAuto;
|
|
FEventShadows := True;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TcxSchedulerDayView then
|
|
begin
|
|
FAlwaysShowEventTime := TcxSchedulerDayView(Source).FAlwaysShowEventTime;
|
|
FHeaderContainer := TcxSchedulerDayView(Source).FHeaderContainer;
|
|
FTimeRulerMinutes := TcxSchedulerDayView(Source).FTimeRulerMinutes;
|
|
FEventShadows := TcxSchedulerDayView(Source).FEventShadows;
|
|
FTimeScale := TcxSchedulerDayView(Source).FTimeScale;
|
|
TimeRulerPopupMenu := TcxSchedulerDayView(Source).TimeRulerPopupMenu;
|
|
FWorkTimeOnly := TcxSchedulerDayView(Source).FWorkTimeOnly;
|
|
end;
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.MakeWorkTimeVisible;
|
|
begin
|
|
if Visible then
|
|
begin
|
|
if WorkTimeOnly then
|
|
ViewInfo.FTopIndex := 0
|
|
else
|
|
ViewInfo.FTopIndex := Round(WorkStart / MinuteToTime) div TimeScale;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.GetProperties(AProperties: TStrings);
|
|
begin
|
|
inherited GetProperties(AProperties);
|
|
AProperties.Add('TimeScale')
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.GetPropertyValue(const AName: string;
|
|
var AValue: Variant);
|
|
begin
|
|
inherited GetPropertyValue(AName, AValue);
|
|
if AName = 'TimeScale' then
|
|
AValue := TimeScale;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.SetPropertyValue(const AName: string;
|
|
const AValue: Variant);
|
|
begin
|
|
inherited SetPropertyValue(AName, AValue);
|
|
if AName = 'TimeScale' then
|
|
TimeScale := AValue;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.CreateSubClasses;
|
|
begin
|
|
FStyles := CreateStyles;
|
|
inherited CreateSubClasses;
|
|
FTimeRulerPopupMenu := CreateTimeRulerPopupMenu;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.DestroySubClasses;
|
|
begin
|
|
FTimeRulerPopupMenu.Free;
|
|
inherited DestroySubClasses;
|
|
FStyles.Free;
|
|
end;
|
|
|
|
function TcxSchedulerDayView.CreateController: TcxSchedulerSubControlController;
|
|
begin
|
|
Result := TcxSchedulerDayViewController.Create(Self);
|
|
end;
|
|
|
|
function TcxSchedulerDayView.CreateHitTest: TcxSchedulerSubControlHitTest;
|
|
begin
|
|
Result := TcxSchedulerDayViewHitTest.Create(Self);
|
|
end;
|
|
|
|
function TcxSchedulerDayView.CreatePainter: TcxSchedulerSubControlPainter;
|
|
begin
|
|
Result := TcxSchedulerDayViewPainter.Create(Self);
|
|
end;
|
|
|
|
function TcxSchedulerDayView.CreateStyles: TcxSchedulerDayViewStyles;
|
|
begin
|
|
Result := TcxSchedulerDayViewStyles.Create(Self);
|
|
end;
|
|
|
|
function TcxSchedulerDayView.CreateTimeRulerPopupMenu: TcxSchedulerTimeRulerPopupMenu;
|
|
begin
|
|
Result := TcxSchedulerTimeRulerPopupMenu.Create(Scheduler);
|
|
end;
|
|
|
|
function TcxSchedulerDayView.CreateViewAdapter: TcxCustomResourceViewAdapter;
|
|
begin
|
|
Result := TcxSchedulerDayViewAdapter.Create(Self);
|
|
end;
|
|
|
|
function TcxSchedulerDayView.CreateViewInfo: TcxSchedulerSubControlViewInfo;
|
|
begin
|
|
Result := TcxSchedulerDayViewViewInfo.Create(Self);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.DoCustomDrawContainer(
|
|
ACell: TcxSchedulerContainerCellViewInfo; var ADone: Boolean);
|
|
begin
|
|
if Assigned(FOnCustomDrawContainer) then
|
|
FOnCustomDrawContainer(Self, Canvas, ACell, ADone);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.DoCustomDrawTimeRuler(
|
|
ACell: TcxSchedulerTimeRulerCellViewInfo; var ADone: Boolean);
|
|
begin
|
|
if Assigned(FOnCustomDrawTimeRuler) then
|
|
FOnCustomDrawTimeRuler(Self, Canvas, ACell, ADone);
|
|
end;
|
|
|
|
function TcxSchedulerDayView.DoShowPopupMenu(X, Y: Integer): Boolean;
|
|
begin
|
|
if HitTest.HitAtTimeRuler then
|
|
Result := TimeRulerPopupMenu.Popup(X, Y)
|
|
else
|
|
Result := inherited DoShowPopupMenu(X, Y);
|
|
end;
|
|
|
|
function TcxSchedulerDayView.EventContentSelected(
|
|
AEvent: TcxSchedulerControlEvent): Boolean;
|
|
begin
|
|
Result := AEvent.AllDayEvent or (AEvent.Duration >= 1);
|
|
end;
|
|
|
|
function TcxSchedulerDayView.GetEditWithSingleLineEditor(
|
|
AEvent: TcxSchedulerControlEvent): Boolean;
|
|
begin
|
|
Result := IsHeaderEvent(AEvent);
|
|
end;
|
|
|
|
function TcxSchedulerDayView.GetTimeIncrement: TDateTime;
|
|
begin
|
|
Result := TimeOf(TimeScale * MinuteToTime);
|
|
end;
|
|
|
|
function TcxSchedulerDayView.GetViewContentRect: TRect;
|
|
begin
|
|
Result := inherited GetViewContentRect;
|
|
Result.Left := ViewInfo.FHeaderOffsetLeft;
|
|
end;
|
|
|
|
function TcxSchedulerDayView.IsDayView: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.MakeEventVisible(AEvent: TcxSchedulerControlEvent;
|
|
const ADate: TDateTime; AResource: TcxSchedulerStorageResourceItem);
|
|
var
|
|
I, DH: Integer;
|
|
R, R1: TRect;
|
|
AViewInfo: TcxSchedulerEventCellViewInfo;
|
|
begin
|
|
if Visible and AEvent.AllDayEvent or (AEvent.Duration >= 1) then Exit;
|
|
for I := 0 to 1 do
|
|
begin
|
|
if FindEventViewInfo(AEvent, ADate, AResource, AViewInfo) and
|
|
not AViewInfo.Hidden then
|
|
begin
|
|
if not AViewInfo.Visible then
|
|
DH := ViewInfo.GetTimeRow(AViewInfo.ContentStart, True)
|
|
else
|
|
begin
|
|
DH := 0;
|
|
R := AViewInfo.Bounds;
|
|
R1 := AViewInfo.ClipRect;
|
|
if cxRectIsEqual(R, R1) then Exit;
|
|
if R.Top < R1.Top then
|
|
DH := (R.Top - R1.Top) div ViewInfo.FContentLineHeight
|
|
else
|
|
if (I = 0) and (R.Bottom > R1.Bottom) then
|
|
DH := (R.Bottom - R1.Bottom) div ViewInfo.FContentLineHeight;
|
|
Inc(DH, ViewInfo.FTopIndex);
|
|
end;
|
|
if ViewInfo.FTopIndex <> DH then
|
|
begin
|
|
ViewInfo.FTopIndex := DH;
|
|
LayoutChanged;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
ViewInfo.FTopIndex := ViewInfo.GetTimeRow(AEvent.Start, True);
|
|
LayoutChanged;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.Notification(AComponent: TComponent;
|
|
Operation: TOperation);
|
|
begin
|
|
TimeRulerPopupMenu.Notification(AComponent, Operation);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.ScrollVisibleDays(AScrollUp: Boolean);
|
|
begin
|
|
ScrollSelectedDays(Byte(AScrollUp) * 2 - 1);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.TimeChanged;
|
|
begin
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.VisibleChanged;
|
|
begin
|
|
MakeWorkTimeVisible;
|
|
inherited VisibleChanged;
|
|
end;
|
|
|
|
function TcxSchedulerDayView.GetHitTest: TcxSchedulerDayViewHitTest;
|
|
begin
|
|
Result := TcxSchedulerDayViewHitTest(inherited HitTest);
|
|
end;
|
|
|
|
function TcxSchedulerDayView.GetViewInfo: TcxSchedulerDayViewViewInfo;
|
|
begin
|
|
Result := TcxSchedulerDayViewViewInfo(inherited ViewInfo)
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.SetAlwaysShowEventTime(AValue: Boolean);
|
|
begin
|
|
if AValue <> FAlwaysShowEventTime then
|
|
begin
|
|
FAlwaysShowEventTime := AValue;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.SetAutoContentHeight(AValue: Boolean);
|
|
begin
|
|
if AValue <> FAutoContentHeight then
|
|
begin
|
|
FAutoContentHeight := AValue;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.SetEventShadows(AValue: Boolean);
|
|
begin
|
|
if AValue <> FEventShadows then
|
|
begin
|
|
FEventShadows := AValue;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.SetHeaderContainer(AValue: Boolean);
|
|
begin
|
|
if AValue <> FHeaderContainer then
|
|
begin
|
|
FHeaderContainer := AValue;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.SetTimeRulerMinutes(AValue: Boolean);
|
|
begin
|
|
if AValue <> FTimeRulerMinutes then
|
|
begin
|
|
FTimeRulerMinutes := AValue;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.SetStyles(AValue: TcxSchedulerDayViewStyles);
|
|
begin
|
|
FStyles.Assign(AValue);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.SetTimeRulerPopupMenu(
|
|
AValue: TcxSchedulerTimeRulerPopupMenu);
|
|
begin
|
|
FTimeRulerPopupMenu.Assign(AValue);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.SetTimeScale(
|
|
AValue: Integer);
|
|
begin
|
|
AValue := Min(60, Max(5, AValue));
|
|
AValue := 60 div Max(1, 60 div AValue);
|
|
if AValue <> FTimeScale then
|
|
begin
|
|
while 60 mod AValue <> 0 do Inc(AValue);
|
|
FTimeScale := AValue;
|
|
MakeWorkTimeVisible;
|
|
Refresh;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayView.SetWorkTimeOnly(AValue: Boolean);
|
|
begin
|
|
if AValue <> FWorkTimeOnly then
|
|
begin
|
|
FWorkTimeOnly := AValue;
|
|
if (ViewInfo <> nil) then
|
|
ViewInfo.FTopIndex := 0;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
{ TcxSchedulerDayViewAdapter }
|
|
|
|
function TcxSchedulerDayViewAdapter.GetPrintRange(Index: Integer): TDateTime;
|
|
begin
|
|
with TcxSchedulerDayView(View) do
|
|
begin
|
|
if not WorkTimeOnly then
|
|
Result := inherited GetPrintRange(Index)
|
|
else
|
|
begin
|
|
if Index = 0 then
|
|
Result := TimeOf(WorkStart)
|
|
else
|
|
Result := TimeOf(WorkFinish);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewAdapter.Store;
|
|
begin
|
|
FTopIndex := TcxSchedulerDayViewViewInfo(ViewInfo).FTopIndex;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewAdapter.Restore;
|
|
begin
|
|
TcxSchedulerDayViewViewInfo(ViewInfo).FTopIndex := FTopIndex;
|
|
end;
|
|
|
|
{ TcxSchedulerDayViewEventCellViewInfo }
|
|
|
|
procedure TcxSchedulerDayViewEventCellViewInfo.CalculateCaptions;
|
|
begin
|
|
if IsDetailInfo and ShowStartTime then
|
|
begin
|
|
inherited CalculateCaptions; //todo: optimization - check with PS
|
|
if EventStart <> EventFinish then
|
|
ViewData.Caption := StartText + '-' + FinishText + ' ' + ViewData.Caption
|
|
else
|
|
ViewData.Caption := StartText + ' ' + ViewData.Caption;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewEventCellViewInfo.CalculateEventTimeVisibility;
|
|
begin
|
|
inherited CalculateEventTimeVisibility;
|
|
if ShowTimeAsClock and ViewData.ShowFinishTime then
|
|
ViewData.ShowFinishTime := ViewData.ContentFinish > EventFinish;
|
|
if ShowTimeAsClock and ViewData.ShowStartTime then
|
|
ViewData.ShowStartTime := ViewData.ContentStart < EventStart;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewEventCellViewInfo.CalculateItemsLayout;
|
|
begin
|
|
if ViewData.ShowTimeLine then Inc(FBounds.Left, cxTimeLineWidth);
|
|
inherited CalculateItemsLayout;
|
|
if ViewData.ShowTimeLine then
|
|
begin
|
|
CalculateTimeLineParams;
|
|
Exclude(FBorders, bLeft);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewEventCellViewInfo.CalculateTimeLineParams;
|
|
var
|
|
LTime: Double;
|
|
AStart, AFinish: TDateTime;
|
|
ATop, AHeight: Integer;
|
|
begin
|
|
AStart := Max(Event.Start, ContentStart);
|
|
AFinish := Min(Event.Finish, ContentFinish);
|
|
if (ContentFinish - ContentStart) <= 0 then
|
|
begin
|
|
AHeight := 0;
|
|
ATop := 0;
|
|
end
|
|
else
|
|
begin
|
|
LTime := (cxRectHeight(FBounds) - 2) / (ContentFinish - ContentStart);
|
|
ATop := Round((AStart - ContentStart) * LTime) + 1;
|
|
AHeight := Round((AFinish - ContentStart) * LTime + 1) - ATop;
|
|
end;
|
|
Inc(ATop, FBounds.Top);
|
|
FTimeLineRect := cxRectSetRight(FBounds, FBounds.Left, cxTimeLineWidth);
|
|
FEventTimeRect := cxRectBounds(FTimeLineRect.Left, ATop, cxTimeLineWidth, AHeight);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewEventCellViewInfo.DrawContent;
|
|
begin
|
|
inherited DrawContent;
|
|
if ShowTimeLine then
|
|
begin
|
|
if not cxRectIsEmpty(TimeLineRect) then
|
|
DrawState;
|
|
DrawShadow;
|
|
DrawSelection;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewEventCellViewInfo.DrawSelection;
|
|
var
|
|
R: TRect;
|
|
begin
|
|
if ShowTimeLine and Selected and FExternalPainter.NeedDrawSelection then
|
|
begin
|
|
R := cxRectSetTop(Bounds, Bounds.Top - cxTimeLineWidth + 1, cxTimeLineWidth);
|
|
Dec(R.Left, cxTimeLineWidth);
|
|
PainterHelper.DrawState(Canvas, R, Event.State, cxBordersAll, ViewData.BorderColor);
|
|
R := cxRectSetTop(R, Bounds.Bottom - 1);
|
|
PainterHelper.DrawState(Canvas, R, Event.State, cxBordersAll, ViewData.BorderColor);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewEventCellViewInfo.DrawShadow;
|
|
var
|
|
R: TRect;
|
|
begin
|
|
if (ViewData.DrawShadows) and (ViewData.Bitmap <> nil) and
|
|
not Hidden and not Selected and ShowTimeLine then
|
|
begin
|
|
R := Bounds;
|
|
Dec(R.Left, cxTimeLineWidth);
|
|
with ViewData do
|
|
ExternalPainter.DrawShadow(Canvas, R, VisibleRect, Bitmap);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewEventCellViewInfo.DrawState;
|
|
begin
|
|
Canvas.FillRect(FTimeLineRect, ViewData.TimeLineParams, cxBordersAll,
|
|
ViewData.BorderColor);
|
|
PainterHelper.DrawState(Canvas, FEventTimeRect, Event.State, [bLeft, bRight],
|
|
ViewData.BorderColor);
|
|
end;
|
|
|
|
function TcxSchedulerDayViewEventCellViewInfo.GetEditingRect: TRect;
|
|
begin
|
|
Result := inherited GetEditingRect;
|
|
if IsDetailCaption then
|
|
Inc(Result.Top);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewEventCellViewInfo.InitHitTest(
|
|
AHitTest: TcxSchedulerCustomResourceViewHitTest);
|
|
begin
|
|
inherited InitHitTest(AHitTest);
|
|
if IsDetailInfo then
|
|
begin
|
|
if ShowTimeLine and PtInRect(FTimeLineRect, AHitTest.HitPoint) then
|
|
AHitTest.SetDragKind(edkEventDragRect)
|
|
else
|
|
begin
|
|
if (AHitTest.HitY - Bounds.Top) <= cxHitDelta then
|
|
AHitTest.SetDragKind(edkResizeStart)
|
|
else
|
|
if (Bounds.Bottom - AHitTest.HitY) <= cxHitDelta then
|
|
AHitTest.SetDragKind(edkResizeEnd);
|
|
end;
|
|
end
|
|
else
|
|
if IsHeaderEvent then
|
|
begin
|
|
if (bLeft in Borders) and ((AHitTest.HitX - Bounds.Left) <= cxHitDelta) then
|
|
AHitTest.SetDragKind(edkResizeStart)
|
|
else
|
|
if (bRight in Borders) and ((Bounds.Right - AHitTest.HitX) <= cxHitDelta) then
|
|
AHitTest.SetDragKind(edkResizeEnd);
|
|
end;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewEventCellViewInfo.IsHorzSizing: Boolean;
|
|
begin
|
|
Result := IsHeaderEvent;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewEventCellViewInfo.IsNeedDrawTime: Boolean;
|
|
begin
|
|
if IsDetailInfo then
|
|
Result := False
|
|
else
|
|
Result := inherited IsNeedDrawTime;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewEventCellViewInfo.IsTimeLineVisible: Boolean;
|
|
begin
|
|
Result := not IsHeaderEvent;
|
|
end;
|
|
|
|
{ TcxSchedulerDayViewViewInfo }
|
|
|
|
constructor TcxSchedulerDayViewViewInfo.Create(
|
|
AOwner: TcxSchedulerSubControl);
|
|
begin
|
|
inherited Create(AOwner);
|
|
Builder := TcxSchedulerEventLayoutBuilder.Create;
|
|
FLargeFont := TFont.Create;
|
|
FTimeRulerCells := TcxSchedulerViewInfoCellList.Create;
|
|
FCells.Insert(1, FTimeRulerCells);
|
|
end;
|
|
|
|
destructor TcxSchedulerDayViewViewInfo.Destroy;
|
|
begin
|
|
Builder.Free;
|
|
FBackground.Free;
|
|
FLargeFont.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.CalculateHitTest(
|
|
AHitTest: TcxSchedulerCustomResourceViewHitTest);
|
|
begin
|
|
inherited CalculateHitTest(AHitTest);
|
|
TimeRulerCells.CalculateHitTest(AHitTest);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.InitScrollBarsParameters;
|
|
begin
|
|
if (FVisibleRowCount = 0) or (FVisibleRowCount >= FRowCount) or
|
|
(cxRectWidth(Bounds) <= 0) then
|
|
DayView.SetScrollBarInfo(sbVertical, 0, 2, 1, 1, 0, False, True)
|
|
else
|
|
DayView.SetScrollBarInfo(sbVertical, 0, FRowCount - 1, 1,
|
|
FVisibleRowCount, TopIndex, True, True);
|
|
inherited InitScrollBarsParameters;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.ScrollVertical(
|
|
AScrollCode: TScrollCode; var AScrollPos: Integer);
|
|
begin
|
|
if not (AScrollCode in [scPosition, scTrack]) then
|
|
AScrollPos := TopIndex;
|
|
case AScrollCode of
|
|
scLineUp:
|
|
Dec(AScrollPos, 1);
|
|
scLineDown:
|
|
Inc(AScrollPos, 1);
|
|
scPageUp:
|
|
Dec(AScrollPos, VisibleRowCount);
|
|
scPageDown:
|
|
Inc(AScrollPos, VisibleRowCount);
|
|
scTop:
|
|
AScrollPos := 0;
|
|
scBottom:
|
|
AScrollPos := FRowCount;
|
|
end;
|
|
if AScrollPos + VisibleRowCount > (FRowCount - 1) then
|
|
AScrollPos := FRowCount - VisibleRowCount;
|
|
if AScrollPos < 0 then
|
|
AScrollPos := 0;
|
|
if FTopIndex <> AScrollPos then
|
|
begin
|
|
FTopIndex := AScrollPos;
|
|
DayView.LayoutChanged;
|
|
AScrollPos := FTopIndex;
|
|
end;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.AddContentCell(
|
|
const ARect: TRect; const AStart, AFinish: TDateTime;
|
|
AResourceIndex: Integer): TcxSchedulerContentCellViewInfo;
|
|
var
|
|
R: TRect;
|
|
P: TcxViewParams;
|
|
begin
|
|
R := Bounds;
|
|
R.Top := FContentOffset;
|
|
if cxRectIntersect(R, ARect) then
|
|
P := GetContentParams(AStart, Resources[AResourceIndex])
|
|
else
|
|
FillChar(P, SizeOf(P), 0);
|
|
CreateCellInstance(ContentCellClass, ARect, R, P, Result);
|
|
Result.SetTime(AStart, AFinish);
|
|
AssignResourceID(Result, AResourceIndex);
|
|
ContentCells.Add(Result);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.AddContainerCell(
|
|
AColumn: Integer; const ABounds: TRect);
|
|
var
|
|
ACell: TcxSchedulerContainerCellViewInfo;
|
|
AParams: TcxViewParams;
|
|
ASelected: Boolean;
|
|
AResource: TcxSchedulerStorageResourceItem;
|
|
ADate: TDateTime;
|
|
begin
|
|
ADate := GetColumnDate(AColumn);
|
|
AResource := GetResourceItemByIndex(GetColumnResourceIndex(AColumn));
|
|
ASelected := IsContainerSelected(AResource, ADate);
|
|
AParams := DayView.Styles.GetHeaderContainerParams(ADate, AResource, ASelected);
|
|
CreateCellInstance(TcxSchedulerContainerCellViewInfo, ABounds, AParams, ACell);
|
|
ACell.DateTime := ADate;
|
|
ACell.Selected := ASelected;
|
|
AssignResourceID(ACell, GetColumnResourceIndex(AColumn));
|
|
Inc(AColumn);
|
|
if (AColumn = FColCount) or (HasSeparator and (GroupingKind <> gkNone) and
|
|
(AColumn mod ColumnInGroup = 0)) then
|
|
ACell.Borders := [bBottom]
|
|
else
|
|
ACell.Borders := [bBottom, bRight];
|
|
if HasVisibleBounds and (AColumn = FColCount) then
|
|
ACell.Borders := [bBottom, bRight];
|
|
FHeaderContainerCells.Add(ACell);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.AddHeaderContainerEvent(
|
|
APlace: TcxSchedulerEventPlace);
|
|
var
|
|
I, ATop: Integer;
|
|
ABounds: TRect;
|
|
AStart, AFinish: TDateTime;
|
|
ACell: TcxSchedulerEventCellViewInfo;
|
|
begin
|
|
if APlace.LineStart >= FHeaderLineCount then Exit;
|
|
ATop := Bounds.Top + DayHeaderHeight + FResourceHeaderHeight * Byte(GroupingKind <> gkNone);
|
|
GetHeaderEventInfo(APlace.ColStart, APlace.ColFinish,
|
|
ABounds.Left, ABounds.Right, AStart, AFinish);
|
|
ABounds.Top := ATop + cxTextOffset;
|
|
ABounds.Bottom := ATop + FHeaderLineHeight + cxTextOffset;
|
|
OffsetRect(ABounds, 0, APlace.LineStart * (FHeaderLineHeight + cxTextOffset));
|
|
ACell := AddEventCell(CreateHeaderEventViewData(
|
|
TcxSchedulerControlEvent(APlace.Event), ABounds,
|
|
AStart, AFinish, GetColumnResource(APlace.ColStart)));
|
|
if not ACell.Event.IsClone then
|
|
for I := APlace.ColStart to APlace.ColFinish do
|
|
SetColumnTimeLineStyle(ACell, I);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.AddHeaderContainerEventPlace(
|
|
AEvent: TcxSchedulerControlEvent; var AColIndex: Integer);
|
|
var
|
|
I, J: Integer;
|
|
ADate: TDateTime;
|
|
begin
|
|
J := AColIndex;
|
|
ADate := GetColumnDate(J);
|
|
for I := AColIndex + 1 to FColCount - 1 do
|
|
if IsColumnEvent(AEvent, I, True) and (GetColumnDate(I) > ADate) then
|
|
J := I
|
|
else
|
|
Break;
|
|
Builder.AddEventPlace(AEvent, AColIndex, J);
|
|
AColIndex := J + 1;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.AddMoreEventsButton(
|
|
const AIndex, ARowIndex: Integer; AIsTop: Boolean);
|
|
var
|
|
R: TRect;
|
|
begin
|
|
R := Bounds;
|
|
R.Top := FContentOffset;
|
|
R.Right := FHeaderOffsetLeft;
|
|
AddButton(R, ARowIndex / FRowCount, AIndex, not AIsTop)
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.CalculateBackground;
|
|
|
|
procedure CreateBackgroundCell(const ABounds: TRect);
|
|
begin
|
|
if ABounds.Top < ABounds.Bottom then
|
|
begin
|
|
CreateCellInstance(TcxSchedulerBackgroundCellViewInfo, ABounds,
|
|
Styles.GetBackgroundParams, FBackground);
|
|
FBackground.Borders := [bTop];
|
|
end;
|
|
end;
|
|
|
|
procedure CreateBackgroundCellSlots(const ABounds: TRect);
|
|
var
|
|
R: TRect;
|
|
AEventIndex, I, J, K: Integer;
|
|
AEvent: TcxSchedulerControlEvent;
|
|
ASlot: TcxSchedulerBackgroundSlotCellViewInfo;
|
|
const
|
|
ABorders: array[Boolean] of TcxBorders = ([bRight, bTop], [bTop]);
|
|
begin
|
|
if ABounds.Top >= ABounds.Bottom then Exit;
|
|
TcxSchedulerTimeRulerCellViewInfo(
|
|
TimeRulerCells[TimeRulerCells.Count - 1]).SetBottom(ABounds.Top);
|
|
for J := -1 to ColCount - 1 do
|
|
begin
|
|
for I := 0 to UnusedRowCount - 1 do
|
|
begin
|
|
R := cxRectSetTop(ABounds, ABounds.Top +
|
|
I * FContentLineHeight, FContentLineHeight);
|
|
if J = -1 then
|
|
R.Right := FHeaderOffsetLeft
|
|
else
|
|
with GetContainer(J) do
|
|
R := cxRectSetLeft(R, Bounds.Left, cxRectWidth(Bounds));
|
|
if J = ColCount - 1 then Dec(R.Right);
|
|
ASlot := AddBackgroundSlot(R, ABorders[J = ColCount - 1], IntToStr(I));
|
|
if J >= 0 then
|
|
begin
|
|
AEventIndex := 0;
|
|
for K := 0 to Events.Count - 1 do
|
|
begin
|
|
AEvent := Events[K];
|
|
if IsColumnEvent(AEvent, J, False) and not IsEventVisible(AEvent) then
|
|
begin
|
|
if AEventIndex = I then
|
|
begin
|
|
ASlot.DisplayText := GetEventSlotDisplayText(AEvent);
|
|
Break;
|
|
end;
|
|
Inc(AEventIndex);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
R: TRect;
|
|
begin
|
|
FreeAndNil(FBackground);
|
|
if AutoHeight and not HasVisibleBounds then Exit;
|
|
R := Bounds;
|
|
if IsPrinting then
|
|
begin
|
|
R.Top := FContentOffset + (PrintFinishRow - PrintStartRow + 1) * FContentLineHeight;
|
|
CreateBackgroundCellSlots(R);
|
|
end
|
|
else
|
|
begin
|
|
R.Top := FContentOffset + FRowCount * FContentLineHeight;
|
|
CreateBackgroundCell(R);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.CalculateContent;
|
|
var
|
|
I, J: Integer;
|
|
ACell: TcxSchedulerContentCellViewInfo;
|
|
AColor: TColor;
|
|
ARect, ABounds: TRect;
|
|
AIndex: Integer;
|
|
AResource: TcxSchedulerStorageResourceItem;
|
|
begin
|
|
ABounds := Bounds;
|
|
ABounds.TopLeft := Point(FHeaderOffsetLeft, FContentOffset);
|
|
for I := 0 to FColCount - 1 do
|
|
begin
|
|
AIndex := GetColumnResourceIndex(I);
|
|
AResource := GetResourceItemByIndex(AIndex);
|
|
AColor := StylesAdapter.GetContentParams(GetColumnDate(I), True, AResource).Color;
|
|
ARect := cxRectSetTop(Containers[I].Bounds, ABounds.Top, ContentLineHeight);
|
|
if HasVisibleBounds and not IsPrinting then
|
|
OffsetRect(ARect, 0, -FTopIndex * ContentLineHeight);
|
|
if not IsPrinting then
|
|
begin
|
|
if (ColumnInGroup > 1) or ((ColumnInGroup = 1) and (DayView.OptionsView.GroupSeparatorWidth = 0)) then
|
|
begin
|
|
if (I + 1) mod ColumnInGroup <> 0 then
|
|
Dec(ARect.Right, 1);
|
|
if ((I mod ColumnInGroup > 0) or not HasSeparator) then
|
|
Dec(ARect.Left);
|
|
end;
|
|
end;
|
|
for J := 0 to FDayRowCount - 1 do
|
|
if IsRowVisible(J) then
|
|
begin
|
|
ACell := AddContentCell(ARect, GetRowTime(I, J), GetRowTime(I, J + 1), AIndex);
|
|
ACell.Borders := [];
|
|
if I = 0 then
|
|
ACell.TimeLineBorders := [bRight];
|
|
if HasSeparator and (I mod ColumnInGroup = 0) then
|
|
ACell.TimeLineBorders := ACell.TimeLineBorders *
|
|
LookAndFeelPainter.HeaderBorders([nLeft]);
|
|
ACell.ShowTimeLine := True;
|
|
if IsPrinting and (I < (FColCount - 1)) then
|
|
ACell.Borders := [bRight];
|
|
if not IsPrinting or (J <> PrintFinishRow) then
|
|
ACell.Borders := ACell.Borders + [bBottom];
|
|
ACell.BorderColor := PainterHelper.GetSeparatorColor(
|
|
AColor, (J + 1) mod LinePerHour = 0, DayView.IsWorkTime(AResource, ACell.TimeStart));
|
|
ACell.TimeLineParams := DayView.Styles.GetTimeLineParams;
|
|
OffsetRect(ARect, 0, FContentLineHeight);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.CalculateEvents;
|
|
var
|
|
I: Integer;
|
|
AList: TcxSchedulerEventList;
|
|
AContainer: TcxSchedulerContainerCellViewInfo;
|
|
begin
|
|
AList := TcxSchedulerEventList.Create;
|
|
try
|
|
for I := 0 to ContainerCount - 1 do
|
|
begin
|
|
AContainer := Containers[I];
|
|
// for source events
|
|
AList.Clear;
|
|
ExtractEvents(Events, AList, I);
|
|
CalculateEventsForColumn(I, AContainer, AList);
|
|
// for clones
|
|
AList.Clear;
|
|
ExtractEvents(Events.Clones, AList, I);
|
|
CalculateEventsForColumn(I, AContainer, AList);
|
|
end;
|
|
finally
|
|
AList.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.CalculateEventsForColumn(AIndex: Integer;
|
|
AContainer: TcxSchedulerContainerCellViewInfo; AEvents: TcxSchedulerEventList);
|
|
var
|
|
ATop, I: Integer;
|
|
AViewData: TcxSchedulerEventViewData;
|
|
AInfo: TcxEventLayoutInfo;
|
|
begin
|
|
if AEvents.Count = 0 then Exit;
|
|
FEventLayout.Clear;
|
|
I := Byte(((AIndex mod ColumnInGroup <> 0) or not HasSeparator) and not (ColCount = 1));
|
|
ATop := FContentOffset;
|
|
if not IsPrinting then
|
|
Dec(ATop, TopIndex * FContentLineHeight);
|
|
FEventLayout.SetParams(DateOf(AContainer.DateTime), TimeScale,
|
|
FContentLineHeight, AContainer.Bounds.Left - I, ATop, cxRectWidth(AContainer.Bounds));
|
|
for I := 0 to AEvents.Count - 1 do
|
|
FEventLayout.Add(TcxSchedulerControlEvent(AEvents[I]));
|
|
FEventLayout.Calculate;
|
|
for I := 0 to FEventLayout.Count - 1 do
|
|
begin
|
|
AInfo := FEventLayout.Infos[I];
|
|
CheckEventRowsVisibility(AInfo.Event, AInfo.StartRow, AInfo.StopRow + 1);
|
|
AViewData := CreateContentEventViewData(AInfo, AContainer.Resource);
|
|
if AViewData <> nil then
|
|
begin
|
|
if IsPrinting and (FColCount > 1) then
|
|
if (AIndex mod ColumnInGroup > 0) or ((ColumnInGroup = 1) and
|
|
(DayView.OptionsView.GroupSeparatorWidth = 0)) then
|
|
OffsetRect(AViewData.Bounds, 1, 0);
|
|
AViewData.DrawShadows := DayView.EventShadows;
|
|
AddEventCell(AViewData);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.CalculateHeaderEvents;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to Builder.EventPlaceCount - 1 do
|
|
AddHeaderContainerEvent(Builder.EventPlaces[I]);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.CalculateHeaderEventsPlace;
|
|
var
|
|
I, J: Integer;
|
|
begin
|
|
if not HeaderContainer then Exit;
|
|
for I := 0 to Events.AbsoluteCount - 1 do
|
|
begin
|
|
J := 0;
|
|
while J < FColCount do
|
|
begin
|
|
if IsColumnEvent(Events.AbsoluteItems[I], J, True) then
|
|
AddHeaderContainerEventPlace(Events.AbsoluteItems[I], J)
|
|
else
|
|
Inc(J)
|
|
end;
|
|
end;
|
|
Builder.Calculate;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.CalculateHeaderLineCount;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if not HeaderContainer then
|
|
begin
|
|
FHeaderLineCount := 0;
|
|
Exit;
|
|
end;
|
|
FHeaderLineCount := 1;
|
|
CalculateHeaderEventsPlace;
|
|
for I := 0 to Builder.EventPlaceCount - 1 do
|
|
FHeaderLineCount := Max(Builder.EventPlaces[I].LineFinish + 1, FHeaderLineCount);
|
|
if cxSchedulerAllDayEventContainerMaxLineCount = 0 then
|
|
I := (Bounds.Bottom - Bounds.Top - FDayHeaderHeight -
|
|
FResourceHeaderHeight) div FContentLineHeight div 2
|
|
else
|
|
I := cxSchedulerAllDayEventContainerMaxLineCount;
|
|
FHeaderLineCount := Min(FHeaderLineCount, Max(1, I));
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.CalculateHeaders;
|
|
var
|
|
I, J, W: Integer;
|
|
AHeaderBounds, AGroupBounds: TRect;
|
|
const
|
|
ANeighbors: array[TcxSchedulerGroupingKind, 0..1] of TcxNeighbors =
|
|
(([], []), ([], []), ([nTop], []), ([], [nTop]));
|
|
begin
|
|
AGroupBounds := cxRectSetHeight(Bounds, Byte(GroupByResource) * FResourceHeaderHeight +
|
|
Byte(GroupByDate) * DayHeaderHeight);
|
|
AHeaderBounds := cxRectSetTop(Bounds, AGroupBounds.Bottom,
|
|
Byte(GroupByDate) * FResourceHeaderHeight + Byte(not GroupByDate) * DayHeaderHeight);
|
|
W := Bounds.Right - FHeaderOffsetLeft - (GroupCount - 1) * SeparatorWidth;
|
|
for I := 0 to GroupCount - 1 do
|
|
begin
|
|
AGroupBounds.Left := MulDiv(W, I, GroupCount) + FHeaderOffsetLeft + SeparatorWidth * I;
|
|
AGroupBounds.Right := MulDiv(W, I + 1, GroupCount) + FHeaderOffsetLeft + SeparatorWidth * I;
|
|
for J := 0 to ColumnInGroup - 1 do
|
|
begin
|
|
AHeaderBounds.Left := AGroupBounds.Left +
|
|
MulDiv(cxRectWidth(AGroupBounds), J, ColumnInGroup);
|
|
AHeaderBounds.Right := AGroupBounds.Left +
|
|
MulDiv(cxRectWidth(AGroupBounds), J + 1, ColumnInGroup);
|
|
if GroupByDate then
|
|
AddResourceHeader(J, AHeaderBounds).DateTime :=
|
|
GetColumnDate(I * ColumnInGroup + J)
|
|
else
|
|
AddDayHeader(GetColumnDate(I * ColumnInGroup + J), AHeaderBounds,
|
|
GetColumnResourceIndex(I * ColumnInGroup + J));
|
|
AddContainerCell(I * ColumnInGroup + J,
|
|
cxRectSetTop(AHeaderBounds, Bounds.Top, FContentOffset - Bounds.Top));
|
|
end;
|
|
if GroupByResource then
|
|
AddResourceHeader(I, AGroupBounds)
|
|
else
|
|
if GroupByDate then
|
|
AddDayHeader(Days[I], AGroupBounds, -1);
|
|
if HasSeparator then AddGroupVertSeparator(AGroupBounds.Right);
|
|
end;
|
|
ProcessCheckBorders(ResourceHeaderCells, False, ANeighbors[GroupingKind, 0]);
|
|
ProcessDateToDisplayText(True);
|
|
ProcessCheckBorders(DayHeaderCells, False, ANeighbors[GroupingKind, 1]);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.CalculateMetrics;
|
|
|
|
function GetExtraContentOffset: Integer;
|
|
begin
|
|
if HeaderContainer then
|
|
Result := cxTextOffset + FHeaderLineCount * (FHeaderLineHeight + cxTextOffset)
|
|
else
|
|
Result := 0;
|
|
end;
|
|
|
|
begin
|
|
inherited CalculateMetrics;
|
|
FHeaderLineHeight := FContentLineHeight;
|
|
FAdditionalTimeZone := -1;
|
|
FCurrentTimeZone := DayView.OptionsView.CurrentTimeZone;
|
|
if FCurrentTimeZone = -1 then
|
|
FCurrentTimeZone := DayView.DateTimeHelper.CurrentTimeZone;
|
|
if DayView.OptionsView.ShowAdditionalTimeZone then
|
|
begin
|
|
FAdditionalTimeZone := DayView.OptionsView.AdditionalTimeZone;
|
|
if FAdditionalTimeZone = -1 then
|
|
FAdditionalTimeZone := DayView.DateTimeHelper.CurrentTimeZone;
|
|
end;
|
|
FColCount := DayCount;
|
|
if GroupingKind <> gkNone then
|
|
FColCount := FColCount * ResourceCount;
|
|
LargeFont := GetTimeRulerParams.Font;
|
|
CalculateHeaderLineCount;
|
|
CalculateVisibleRows;
|
|
FVisibleRowCount := Max(1, ContentHeight div FContentLineHeight);
|
|
if not IsPrinting then
|
|
begin
|
|
if AutoHeight and (FVisibleRowCount > (FRowCount + FHeaderLineCount)) then
|
|
FContentLineHeight := (ContentHeight - GetExtraContentOffset) div FRowCount;
|
|
|
|
FContentOffset := FContentOffset + GetExtraContentOffset;
|
|
FVisibleRowCount := Min(FRowCount, Max(1, ContentHeight div FContentLineHeight));
|
|
if AutoHeight or (ContentHeight div FContentLineHeight < FRowCount) then
|
|
Inc(FContentOffset, ContentHeight - FContentLineHeight * FVisibleRowCount);
|
|
end;
|
|
if not HeaderContainer then
|
|
FDayHeaderHeight := FContentOffset - Byte(GroupingKind <> gkNone) * FResourceHeaderHeight;
|
|
while (FTopIndex > 0) and ((FTopIndex + FVisibleRowCount) > FRowCount) do
|
|
Dec(FTopIndex);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.CalculateMetricsForPrinting;
|
|
var
|
|
AContentHeight: Integer;
|
|
HeightAdjusted: Boolean;
|
|
begin
|
|
FContentOffset := Byte(GroupingKind <> gkNone) *
|
|
FResourceHeaderHeight * Byte(ResourceCount >= 1) +
|
|
FHeaderLineCount * (FHeaderLineHeight + cxTextOffset) + cxTextOffset;
|
|
if (GroupingKind = gkByResource) or (SelectedDays.Count > 1) then
|
|
Inc(FContentOffset, DayHeaderHeight);
|
|
CalculateUnusedRowCount;
|
|
FTimeScale := DayView.TimeScale;
|
|
AContentHeight := Bounds.Bottom - Bounds.Top - FContentOffset;
|
|
HeightAdjusted := AContentHeight < FContentLineHeight;
|
|
while not HeightAdjusted do
|
|
begin
|
|
CalculateDisplayRows;
|
|
FTopIndex := PrintStartRow;
|
|
HeightAdjusted := AContentHeight >= FContentLineHeight * PrintRowCount;
|
|
if not HeightAdjusted then
|
|
begin
|
|
if FTimeScale < 60 then
|
|
begin
|
|
FTimeScale := FTimeScale * 2;
|
|
while 60 mod FTimeScale <> 0 do Inc(FTimeScale);
|
|
end
|
|
else
|
|
if UnusedRowCount > 0 then
|
|
Dec(FUnusedRowCount)
|
|
else
|
|
Break;
|
|
end;
|
|
end;
|
|
CalculateDisplayRows;
|
|
if HeightAdjusted then
|
|
begin
|
|
FContentLineHeight := AContentHeight div PrintRowCount;
|
|
Inc(FContentOffset, AContentHeight - FContentLineHeight * PrintRowCount);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.CalculateDisplayRows;
|
|
|
|
function GetTimeRow(ATime: TDateTime; IsFinish: Boolean): Integer;
|
|
begin
|
|
Result := Round(ATime / MinuteToTime);
|
|
Result := Result div FTimeScale - Byte(IsFinish) +
|
|
Byte(IsFinish and (Result mod FTimeScale <> 0))
|
|
end;
|
|
|
|
begin
|
|
FDayRowCount := cxMinutesPerDay div TimeScale;
|
|
if HasVisibleBounds then
|
|
begin
|
|
FPrintStartRow := GetTimeRow(PrintFrom, False);
|
|
FPrintFinishRow := Max(FPrintStartRow, GetTimeRow(PrintTo, True));
|
|
end
|
|
else
|
|
begin
|
|
FPrintStartRow := 0;
|
|
FPrintFinishRow := FDayRowCount - 1;
|
|
end;
|
|
FRowCount := FPrintFinishRow - FPrintStartRow + 1;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.CalculateTimeLine;
|
|
var
|
|
ABounds, R: TRect;
|
|
AOfs, I, AHour: Integer;
|
|
AViewParams: TcxViewParams;
|
|
ACommonCell, ARulerCell: TcxSchedulerTimeRulerCellViewInfo;
|
|
begin
|
|
R := cxRectSetTop(Bounds, FContentOffset);
|
|
AViewParams := GetTimeRulerParams;
|
|
FHeaderOffsetLeft := R.Left + TcxSchedulerTimeRulerCellViewInfo.CalculateWidth(
|
|
1 + Byte(FAdditionalTimeZone >= 0), LinePerHour, AViewParams.Font, LargeFont);
|
|
R.Right := FHeaderOffsetLeft;
|
|
// add common area
|
|
CreateCellInstance(TcxSchedulerTimeRulerCellViewInfo,
|
|
cxRectSetTop(R, 0, R.Top), AViewParams, ACommonCell);
|
|
ACommonCell.Calculate(DayView.OptionsView.CurrentTimeZoneLabel,
|
|
DayView.OptionsView.AdditionalTimeZoneLabel, FCurrentTimeZone, FAdditionalTimeZone);
|
|
// add ruler cells
|
|
AOfs := FPrintStartRow * FContentLineHeight - FContentOffset;
|
|
if not IsPrinting then
|
|
Inc(AOfs, TopIndex * FContentLineHeight);
|
|
R := cxRectSetTop(R, 0, LinePerHour * FContentLineHeight);
|
|
ABounds := Bounds;
|
|
ABounds.Top := FContentOffset;
|
|
ABounds.Bottom := Min(FContentOffset + FRowCount * FContentLineHeight, Bounds.Bottom);
|
|
FTimeRulerCells.Add(ACommonCell);
|
|
I := 0;
|
|
while I < FDayRowCount do
|
|
begin
|
|
if IsRowVisible(I) then
|
|
begin
|
|
AHour := I div LinePerHour;
|
|
CreateCellInstance(TcxSchedulerTimeRulerCellViewInfo,
|
|
cxRectSetTop(R, R.Bottom * AHour - AOfs), ABounds, AViewParams, ARulerCell);
|
|
ARulerCell.ShowMinutes := DayView.TimeRulerMinutes;
|
|
ARulerCell.Calculate(AHour, LinePerHour, FCurrentTimeZone,
|
|
FAdditionalTimeZone, LargeFont);
|
|
ARulerCell.LastVisibleHour := not IsHourVisible(AHour + 1);
|
|
FTimeRulerCells.Add(ARulerCell);
|
|
I := (AHour + 1) * LinePerHour;
|
|
end
|
|
else
|
|
Inc(I);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.CalculateVisibleRows;
|
|
begin
|
|
if not IsPrinting then
|
|
begin
|
|
FTimeScale := DayView.TimeScale;
|
|
CalculateDisplayRows;
|
|
FContentOffset := DayHeaderHeight + Byte(GroupingKind <> gkNone) * FResourceHeaderHeight;
|
|
if HeaderContainer then
|
|
Inc(FContentOffset, cxTextOffset);
|
|
end
|
|
else
|
|
CalculateMetricsForPrinting;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.CalculateUnusedRowCount;
|
|
var
|
|
I, J: Integer;
|
|
AEvent: TcxSchedulerEvent;
|
|
AColRowCount: Integer;
|
|
begin
|
|
FUnusedRowCount := 3;
|
|
for I := 0 to ColCount - 1 do
|
|
begin
|
|
AColRowCount := 0;
|
|
for J := 0 to Events.Count - 1 do
|
|
begin
|
|
AEvent := Events[J];
|
|
if IsColumnEvent(AEvent, I, False) and not IsEventVisible(AEvent) then
|
|
Inc(AColRowCount);
|
|
end;
|
|
FUnusedRowCount := Max(FUnusedRowCount, AColRowCount);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.Clear;
|
|
begin
|
|
inherited Clear;
|
|
FTimeRulerCells.Clear;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.CheckDisplayRows(
|
|
var AStartRow, AFinishRow: Integer): Boolean;
|
|
begin
|
|
Result := not HasVisibleBounds or ((AStartRow <= PrintFinishRow) and
|
|
(PrintStartRow <= AFinishRow));
|
|
if Result then
|
|
begin
|
|
AStartRow := Max(AStartRow, PrintStartRow);
|
|
AFinishRow := Min(AFinishRow, PrintFinishRow);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.CheckEventRowsVisibility(
|
|
AEvent: TcxSchedulerControlEvent; AStartRow, AFinishRow: Integer);
|
|
begin
|
|
if IsPrinting then Exit;
|
|
if AStartRow < FTopIndex then
|
|
AddMoreEventsButton(-1, AStartRow, True);
|
|
if (AFinishRow > (FTopIndex + VisibleRowCount)) then
|
|
begin
|
|
if AFinishRow <= FRowCount then
|
|
AddMoreEventsButton(-1, AFinishRow, False)
|
|
else
|
|
if AStartRow > (FTopIndex + VisibleRowCount) then
|
|
AddMoreEventsButton(-1, AStartRow, False);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.DoCalculate;
|
|
begin
|
|
Builder.Clear;
|
|
if IsPrinting then
|
|
Inc(FBounds.Right);
|
|
FEventLayout := CreateEventLayout;
|
|
FIsPrinting := Adapter <> DayView.Adapter;
|
|
inherited DoCalculate;
|
|
with DayView.Scheduler do
|
|
begin
|
|
FIsContainerSelected := (GetTimeMinutes(SelFinish) = 0) and
|
|
(GetTimeMinutes(SelStart) = 0);
|
|
end;
|
|
try
|
|
CalculateTimeLine;
|
|
CalculateHeaders;
|
|
CalculateContent;
|
|
CalculateEvents;
|
|
CalculateHeaderEvents;
|
|
CalculateBackground;
|
|
finally
|
|
FEventLayout.Free;
|
|
FButtons.Sort(TListSortCompare(@cxCompareButtons));
|
|
if FEventCells.Count > 1 then
|
|
FEventCells.Sort(TListSortCompare(@cxCompareEventViewInfoOrders));
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.DoMoreEventsButtonClick(
|
|
Sender: TcxSchedulerMoreEventsButtonViewInfo);
|
|
var
|
|
ARow: Integer;
|
|
ADateTime: TDateTime;
|
|
begin
|
|
ARow := Min(FRowCount, Max(0, Round(Sender.DateTime * FRowCount)));
|
|
if not Sender.IsDown then
|
|
FTopIndex := ARow
|
|
else
|
|
FTopIndex := Max(0, ARow - VisibleRowCount);
|
|
with Controller.Navigation do
|
|
begin
|
|
ADateTime := DateOf(SelStart) + TimeOf(Sender.DateTime);
|
|
ReplaceSelParams(ADateTime, ADateTime);
|
|
end;
|
|
View.LayoutChanged;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.CreateContentEventViewData(
|
|
AEventInfo: TcxEventLayoutInfo; AResource: TcxSchedulerResourceViewInfo): TcxSchedulerEventViewData;
|
|
begin
|
|
if (AEventInfo.DisplayRect.Bottom <= FContentOffset) or
|
|
(AEventInfo.DisplayRect.Top >= Bounds.Bottom) then
|
|
Result := nil
|
|
else
|
|
begin
|
|
Result := CreateEventViewData(AEventInfo.Event,
|
|
AEventInfo.DisplayRect, AEventInfo.Start, AEventInfo.Finish, AResource);
|
|
Result.AlwaysShowTime := DayView.AlwaysShowEventTime;
|
|
Result.VisibleRect.TopLeft := Point(FHeaderOffsetLeft, FContentOffset);
|
|
Result.ShowTimeLine := True;
|
|
end;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.CreateHeaderEventViewData(
|
|
AEvent: TcxSchedulerControlEvent; const ABounds: TRect;
|
|
const AStart, AFinish: TDateTime; AResource: TcxSchedulerResourceViewInfo): TcxSchedulerEventViewData;
|
|
begin
|
|
Result := CreateEventViewData(AEvent, ABounds, AStart, AFinish, AResource);
|
|
Result.VisibleRect := cxRect(FHeaderOffsetLeft, DayHeaderHeight,
|
|
Bounds.Right, FContentOffset);
|
|
Result.ShowTimeLine := False;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.CreateEventCellViewInfo(
|
|
AViewData: TcxSchedulerEventViewData): TcxSchedulerEventCellViewInfo;
|
|
begin
|
|
Result := TcxSchedulerDayViewEventCellViewInfo.Create(AViewData);
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.CreateEventLayout: TcxCalculateEventLayout;
|
|
begin
|
|
Result := TcxCalculateEventLayout.Create;
|
|
Result.FViewInfo := Self;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.ExtractEvents(
|
|
ASource, ADest: TcxSchedulerEventList; AIndex: Integer);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to ASource.Count - 1 do
|
|
if IsColumnEvent(ASource[I], AIndex, False) then
|
|
ADest.Add(ASource[I]);
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetContentParams(const ATime: TDateTime;
|
|
AResource: TcxSchedulerResourceViewInfo): TcxViewParams;
|
|
begin
|
|
Result := inherited GetContentParams(ATime, AResource);
|
|
if not HiddenSelection and not FIsContainerSelected and IsTimeSelected(ATime, AResource) then
|
|
Result := GetSelectionParams(Result);
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetColumnDate(
|
|
AIndex: Integer): Integer;
|
|
begin
|
|
if GroupingKind = gkByDate then
|
|
AIndex := AIndex div ResourceCount
|
|
else
|
|
if GroupingKind = gkByResource then
|
|
AIndex := AIndex mod DayCount;
|
|
Result := Integer(SelectedDays.List^[AIndex])
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetColumnResource(
|
|
AIndex: Integer): TcxSchedulerResourceViewInfo;
|
|
begin
|
|
Result := Resources[GetColumnResourceIndex(AIndex)];
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetColumnResourceIndex(
|
|
AIndex: Integer): Integer;
|
|
begin
|
|
Result := -1;
|
|
if ResourceCount > 0 then
|
|
begin
|
|
if GroupingKind = gkByDate then
|
|
Result := AIndex mod ResourceCount
|
|
else
|
|
if GroupingKind = gkByResource then
|
|
Result := AIndex div DayCount;
|
|
end;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetContainer(
|
|
AIndex: Integer): TcxSchedulerContainerCellViewInfo;
|
|
begin
|
|
Result := TcxSchedulerContainerCellViewInfo(HeaderContainerCells[AIndex]);
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetContainerCount: Integer;
|
|
begin
|
|
Result := HeaderContainerCells.Count;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetDayHeaderHeight: Integer;
|
|
begin
|
|
Result := inherited GetDayHeaderHeight;
|
|
if (SelectedDays.Count = 1) and IsPrinting and (GroupingKind <> gkByResource) then
|
|
Result := 0;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetEventSlotDisplayText(
|
|
AEvent: TcxSchedulerControlEvent): string;
|
|
begin
|
|
Result := DoGetEventDisplayText(AEvent);
|
|
with DateTimeHelper do
|
|
begin
|
|
Result := TimeToStr(AEvent.Start) + '-' + TimeToStr(AEvent.Finish) + ' ' + Result;
|
|
end;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetEventColumnRow(
|
|
const ATime: TDateTime; AColIndex: Integer; AStart: Boolean): Integer;
|
|
|
|
function GetTimeRowEx: Integer;
|
|
var
|
|
ARow: Integer;
|
|
begin
|
|
ARow := Round(TimeOf(ATime) / MinuteToTime);
|
|
Result := ARow div TimeScale;
|
|
if not AStart then
|
|
Result := Result - Byte((ARow mod TimeScale) <= (TimeScale / 2));
|
|
Result := Max(0, Min(FRowCount - 1, Result - FPrintStartRow));
|
|
end;
|
|
|
|
begin
|
|
if AStart and (ATime <= GetColumnDate(AColIndex)) then
|
|
Result := 0
|
|
else
|
|
if not AStart and (ATime >= GetColumnDate(AColIndex)) then
|
|
begin
|
|
if HasVisibleBounds then
|
|
Result := FRowCount - 1
|
|
else
|
|
Result := VisibleRowCount - 1
|
|
end
|
|
else
|
|
begin
|
|
if HasVisibleBounds then
|
|
Result := GetTimeRowEx
|
|
else
|
|
Result := Min(VisibleRowCount, GetTimeRowEx - TopIndex);
|
|
if AStart then
|
|
Result := Max(0, Result);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.GetHeaderEventInfo(AColStart, AColFinish: Integer;
|
|
out ALeft, ARight: Integer; out AStart, AFinish: TDateTime);
|
|
begin
|
|
with Containers[AColStart] do
|
|
begin
|
|
ALeft := Bounds.Left + cxTextOffset;
|
|
AStart := DateTime;
|
|
end;
|
|
with Containers[AColFinish] do
|
|
begin
|
|
ARight := Bounds.Right - cxTextOffset - 1;
|
|
AFinish := DateTime + 1;
|
|
end;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetTimeLineParams: TcxViewParams;
|
|
begin
|
|
Result := DayView.Styles.GetTimeLineParams;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetTimeRulerParams: TcxViewParams;
|
|
var
|
|
AIntf: IcxSchedulerTimeRulerParams;
|
|
begin
|
|
if Supports(StylesAdapter, IcxSchedulerTimeRulerParams, AIntf) then
|
|
Result := AIntf.GetTimeRulerParams
|
|
else
|
|
Result := DayView.Styles.GetTimeRulerParams;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetTimeRow(
|
|
const ATime: TDateTime; AIsStart: Boolean): Integer;
|
|
var
|
|
ACount: Double;
|
|
begin
|
|
ACount := Min(FRowCount - 1,
|
|
TimeOf(ATime) / MinuteToTime / TimeScale - FPrintStartRow);
|
|
Result := Round(ACount);
|
|
if not AIsStart and (TimeOf(ACount) = 0) then
|
|
Dec(Result);
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetResourcesContentWidth: Integer;
|
|
var
|
|
AFont: TFont;
|
|
begin
|
|
AFont := GetTimeRulerParams.Font;
|
|
LargeFont := AFont;
|
|
Result := (Bounds.Right - Bounds.Top) - TcxSchedulerTimeRulerCellViewInfo.CalculateWidth(
|
|
1 + Byte(FAdditionalTimeZone >= 0), 60 div DayView.TimeScale, AFont, LargeFont);
|
|
if GroupByDate then
|
|
Result := Result div DayCount;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetRowTime(
|
|
AColumn, ARow: Integer): TDateTime;
|
|
begin
|
|
Result := GetColumnDate(AColumn) + (ARow * TimeScale) * MinuteToTime;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetSeparatorCount: Integer;
|
|
begin
|
|
Result := inherited GetSeparatorCount;
|
|
if GroupByDate then
|
|
Result := DayCount - 1;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.IsColumnEvent(AEvent: TcxSchedulerEvent;
|
|
AIndex: Integer; IsHeaderEvent: Boolean): Boolean;
|
|
begin
|
|
Result := AEvent.IsDayEvent(GetColumnDate(AIndex)) and
|
|
(IsHeaderEvent = (AEvent.AllDayEvent or (AEvent.Duration >= 1)));
|
|
if Result then
|
|
Result := AEvent.IsResourceEvent(GetResourceItemByIndex(
|
|
GetColumnResourceIndex(AIndex)), ShowEventsWithoutResource);
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.IsContainerSelected(
|
|
AResource: TcxSchedulerStorageResourceItem; ADate: TDateTime): Boolean;
|
|
begin
|
|
Result := False;
|
|
with DayView.Scheduler do
|
|
begin
|
|
if SelectedEventCount > 0 then Exit;
|
|
if (AResource = SelResource) and (DateOf(ADate + 1) <= DateOf(SelFinish)) then
|
|
begin
|
|
if DateOf(ADate) > DateOf(SelStart) then
|
|
Result := True
|
|
else
|
|
Result := (DateOf(ADate) = DateOf(SelStart)) and
|
|
(GetTimeMinutes(SelStart) = 0);
|
|
end;
|
|
end;
|
|
Result := Result and CanSelected;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.IsEventVisible(
|
|
AEvent: TcxSchedulerEvent): Boolean;
|
|
begin
|
|
Result := (TimeOf(AEvent.Start) <= PrintTo) and (TimeOf(AEvent.Finish) >= PrintFrom);
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.IsEventVisible(
|
|
var AStartRow, AStopRow: Integer): Boolean;
|
|
begin
|
|
Result := (AStopRow >= PrintStartRow) and (AStartRow <= PrintFinishRow);
|
|
if Result then
|
|
begin
|
|
AStopRow := Min(PrintFinishRow, AStopRow);
|
|
AStartRow := Max(PrintStartRow, AStartRow);
|
|
end;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.IsHourVisible(AIndex: Integer): Boolean;
|
|
begin
|
|
Result := not HasVisibleBounds or ((PrintStartRow div LinePerHour <= AIndex) and
|
|
(AIndex <= PrintFinishRow div LinePerHour));
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.IsRowVisible(AIndex: Integer): Boolean;
|
|
begin
|
|
if not HasVisibleBounds then
|
|
Result := (AIndex >= FTopIndex) and (AIndex <= FTopIndex + FVisibleRowCount)
|
|
else
|
|
Result := (AIndex >= PrintStartRow) and (AIndex <= PrintFinishRow);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.MakeTimeVisible(
|
|
const ATime: TDateTime);
|
|
var
|
|
ARow: Integer;
|
|
begin
|
|
ARow := GetTimeRow(ATime, True);
|
|
if (ARow < FTopIndex) or (ARow >= (FTopIndex + VisibleRowCount)) then
|
|
begin
|
|
if ARow < FTopIndex then
|
|
FTopIndex := ARow
|
|
else
|
|
FTopIndex := Max(0, (ARow + 1) - VisibleRowCount);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.SetColumnTimeLineStyle(
|
|
AViewInfo: TcxSchedulerEventCellViewInfo; AColIndex: Integer);
|
|
var
|
|
ACell: TcxSchedulerContentCellViewInfo;
|
|
I, AOfs, StartRow, StopRow: Integer;
|
|
begin
|
|
AOfs := (ContentCells.Count div ColCount) * AColIndex;
|
|
StartRow := GetEventColumnRow(AViewInfo.Event.Start, AColIndex, True) + AOfs;
|
|
StopRow := GetEventColumnRow(AViewInfo.Event.Finish - 1, AColIndex, False) + AOfs;
|
|
for I := StartRow to StopRow do
|
|
if I < ContentCells.Count then
|
|
begin
|
|
ACell := TcxSchedulerContentCellViewInfo(ContentCells[I]);
|
|
if ACell.TimeEvent = nil then
|
|
ACell.TimeEvent := AViewInfo;
|
|
end;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetAutoHeight: Boolean;
|
|
begin
|
|
Result := DayView.AutoContentHeight or IsPrinting;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetColumnInGroup: Integer;
|
|
begin
|
|
Result := DayCount;
|
|
if GroupingKind = gkByDate then
|
|
Result := ResourceCount;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetContentHeight: Integer;
|
|
begin
|
|
Result := Bounds.Bottom - FContentOffset;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetController: TcxSchedulerDayViewController;
|
|
begin
|
|
Result := TcxSchedulerDayViewController(DayView.Controller);
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetDayView: TcxSchedulerDayView;
|
|
begin
|
|
Result := TcxSchedulerDayView(Owner);
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetGroupCount: Integer;
|
|
begin
|
|
if GroupingKind = gkByDate then
|
|
Result := DayCount
|
|
else
|
|
if GroupingKind = gkByResource then
|
|
Result := ResourceCount
|
|
else
|
|
Result := 1;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetHeaderContainer: Boolean;
|
|
begin
|
|
Result := DayView.HeaderContainer;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetPrintRowCount: Integer;
|
|
begin
|
|
Result := FPrintFinishRow - FPrintStartRow + UnusedRowCount + 1;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewViewInfo.GetLinePerHour: Integer;
|
|
begin
|
|
Result := 60 div TimeScale;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewViewInfo.SetLargeFont(AFont: TFont);
|
|
begin
|
|
FLargeFont.Assign(AFont);
|
|
FLargeFont.Size := AFont.Size * 2;
|
|
end;
|
|
|
|
{ TcxSchedulerDayViewHitTest }
|
|
|
|
function TcxSchedulerDayViewHitTest.GetContainerCell: TcxSchedulerContainerCellViewInfo;
|
|
begin
|
|
if HitAtContainer then
|
|
Result := TcxSchedulerContainerCellViewInfo(FHitObject)
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewHitTest.GetTimeRulerCell: TcxSchedulerTimeRulerCellViewInfo;
|
|
begin
|
|
if HitAtTimeRuler then
|
|
Result := TcxSchedulerTimeRulerCellViewInfo(FHitObject)
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
{ TcxDayViewDragEventHelper }
|
|
|
|
function TcxDayViewDragEventHelper.GetOriginHitTestMask: Int64;
|
|
const
|
|
Mask = (1 shl htcControl) or (1 shl htcDayHeader) or (1 shl htcTimeRuler)
|
|
or (1 shl htcContainer) or (1 shl htcContent);
|
|
begin
|
|
Result := Mask;
|
|
end;
|
|
|
|
procedure TcxDayViewDragEventHelper.GetOriginState;
|
|
begin
|
|
inherited GetOriginState;
|
|
FStartInHeader := FStartHitFlags and (1 shl htcContainer) <> 0;
|
|
end;
|
|
|
|
function TcxDayViewDragEventHelper.IsAtOrigin: Boolean;
|
|
begin
|
|
Result := inherited IsAtOrigin or
|
|
(((not ShowHeaderContainer and HitTest.HitAtDayHeader) or (FStartInHeader and InHeader)) and
|
|
(Controller.StartDragHitTime = HitTest.Time) and
|
|
((FStartResource = nil) or (FStartResource = HitTest.Resource)));
|
|
|
|
end;
|
|
|
|
function TcxDayViewDragEventHelper.InHeader: Boolean;
|
|
begin
|
|
with HitTest do
|
|
Result := ShowHeaderContainer and (HitAtDayHeader or HitAtContainer);
|
|
end;
|
|
|
|
procedure TcxDayViewDragEventHelper.SetCloneEventsTimeDelta(AStart, ACurrent: TDateTime;
|
|
AInHeader: Boolean);
|
|
var
|
|
I: Integer;
|
|
ADelta: TDateTime;
|
|
begin
|
|
for I := 0 to Clones.Count - 1 do
|
|
begin
|
|
with Clones[I] do
|
|
begin
|
|
AllDayEvent := AInHeader and (Source.AllDayEvent or (Source.Duration < 1));
|
|
if AInHeader then
|
|
begin
|
|
ADelta := DateOf(AStart) - DateOf(ACurrent);
|
|
if not IsHeaderEvent(Source) then
|
|
begin
|
|
Duration := 1;
|
|
MoveTo(DateOf(Source.Start) - ADelta);
|
|
end
|
|
else
|
|
begin
|
|
Duration := Source.Duration;
|
|
MoveTo(Source.Start - ADelta);
|
|
end;
|
|
end
|
|
else
|
|
if not IsHeaderEvent(Source) then
|
|
begin
|
|
Duration := Source.Duration;
|
|
MoveTo(Source.Start - (AStart - ACurrent));
|
|
end
|
|
else
|
|
begin
|
|
Duration := cxHalfHour;
|
|
MoveTo(ACurrent);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxDayViewDragEventHelper.UpdateViewClonesTime;
|
|
begin
|
|
with HitTest do
|
|
begin
|
|
if HitAtTimeRuler then
|
|
// correct event's times
|
|
SetCloneEventsTimeDelta(Controller.StartDragHitTime,
|
|
DateOf(Controller.StartDragHitTime) + Time, False)
|
|
else
|
|
SetCloneEventsTimeDelta(Controller.StartDragHitTime, Time, InHeader);
|
|
end;
|
|
UpdateEventStates;
|
|
end;
|
|
|
|
procedure TcxDayViewDragEventHelper.UpdateEventStates;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to Clones.Count - 1 do
|
|
CheckEventState(Clones[I]);
|
|
end;
|
|
|
|
function TcxDayViewDragEventHelper.GetController: TcxSchedulerDayViewController;
|
|
begin
|
|
Result := TcxSchedulerDayViewController(inherited Controller);
|
|
end;
|
|
|
|
function TcxDayViewDragEventHelper.GetHitTest: TcxSchedulerDayViewHitTest;
|
|
begin
|
|
Result := TcxSchedulerDayViewHitTest(inherited HitTest);
|
|
end;
|
|
|
|
function TcxDayViewDragEventHelper.GetShowHeaderContainer: Boolean;
|
|
begin
|
|
Result := TcxSchedulerDayView(HitTest.View).HeaderContainer;
|
|
end;
|
|
|
|
{ TcxDayViewEventSizing }
|
|
|
|
function TcxDayViewEventSizing.GetDragCursor(Accepted: Boolean): TCursor;
|
|
const
|
|
Cursors: array[Boolean] of TCursor = (crSchedulerVertResize,
|
|
crSchedulerHorzResize);
|
|
begin
|
|
if HasConflicts then
|
|
Result := crNoDrop
|
|
else
|
|
Result := Cursors[IsHeaderEvent(Event) and HitTest.HitAtContainer];
|
|
end;
|
|
|
|
function TcxDayViewEventSizing.GetOriginHitTestMask: Int64;
|
|
const
|
|
Mask = (1 shl htcControl) or (1 shl htcDayHeader) or (1 shl htcTimeRuler)
|
|
or (1 shl htcContainer) or (1 shl htcContent);
|
|
begin
|
|
Result := Mask;
|
|
end;
|
|
|
|
procedure TcxDayViewEventSizing.CalcAllDayEvent;
|
|
begin
|
|
with Event do
|
|
begin
|
|
AllDayEvent := (HitTest.HitAtContainer or (TimeOf(GetSizingTime) = 0)) and
|
|
(Source.AllDayEvent or (TimeOf(FFixedBoundTime) = 0));
|
|
if Controller.DragKind = edkResizeStart then
|
|
Finish := FFixedBoundTime
|
|
else
|
|
Start := FFixedBoundTime;
|
|
end;
|
|
end;
|
|
|
|
function TcxDayViewEventSizing.GetFinishTime: TDateTime;
|
|
begin
|
|
Result := HitTest.Time;
|
|
if HitTest.HitAtTimeRuler then
|
|
Result := Result + DateOf(Event.Finish)
|
|
else
|
|
if HitTest.HitAtContent then
|
|
Result := Result +
|
|
TcxSchedulerDayView(Scheduler.CurrentView).TimeScale * MinuteToTime
|
|
else
|
|
if (Controller.DragKind = edkResizeEnd) and not Event.AllDayEvent and
|
|
HitTest.HitAtContainer and (TimeOf(Result) = 0) then Result := Result + 1;
|
|
end;
|
|
|
|
procedure TcxDayViewEventSizing.GetOriginState;
|
|
begin
|
|
inherited GetOriginState;
|
|
with Event do
|
|
begin
|
|
if Controller.DragKind = edkResizeStart then
|
|
FFixedBoundTime := Finish
|
|
else
|
|
FFixedBoundTime := Start;
|
|
end;
|
|
end;
|
|
|
|
function TcxDayViewEventSizing.GetSizingTime: TDateTime;
|
|
begin
|
|
if Controller.DragKind = edkResizeStart then
|
|
Result := GetStartTime
|
|
else
|
|
Result := GetFinishTime;
|
|
end;
|
|
|
|
function TcxDayViewEventSizing.GetStartTime: TDateTime;
|
|
begin
|
|
Result := HitTest.Time;
|
|
if HitTest.HitAtTimeRuler then
|
|
Result := Result + DateOf(Event.Start);
|
|
end;
|
|
|
|
function TcxDayViewEventSizing.GetController: TcxSchedulerDayViewController;
|
|
begin
|
|
Result := TcxSchedulerDayViewController(inherited Controller);
|
|
end;
|
|
|
|
function TcxDayViewEventSizing.GetHitTest: TcxSchedulerDayViewHitTest;
|
|
begin
|
|
Result := TcxSchedulerDayViewHitTest(inherited HitTest);
|
|
end;
|
|
|
|
{ TcxSchedulerDayNavigation }
|
|
|
|
procedure TcxSchedulerDayNavigation.KeyDown(
|
|
var AKey: Word; AShift: TShiftState);
|
|
var
|
|
ATime, ATimeDelta: TDateTime;
|
|
begin
|
|
FSelRow := GetTimeRow(FCurrentAnchor);
|
|
ATime := DateOf(FCurrentAnchor);
|
|
ATimeDelta := 0;
|
|
case AKey of
|
|
VK_UP:
|
|
begin
|
|
if FSelRow = 0 then
|
|
Exit
|
|
else
|
|
ATimeDelta := GetRowTime(FSelRow - 1);
|
|
end;
|
|
VK_DOWN:
|
|
begin
|
|
if FSelRow >= ViewInfo.FRowCount - 1 then
|
|
Exit
|
|
else
|
|
ATimeDelta := GetRowTime(FSelRow + 1);
|
|
end;
|
|
VK_HOME:
|
|
if not (ssCtrl in AShift) or DayView.WorkTimeOnly then
|
|
ATimeDelta := TimeOf(DayView.WorkStart);
|
|
VK_END:
|
|
begin
|
|
if (ssCtrl in AShift) and not DayView.WorkTimeOnly then
|
|
ATimeDelta := 1 - DayView.GetTimeIncrement
|
|
else
|
|
ATimeDelta := TimeOf(DayView.WorkFinish) - DayView.GetTimeIncrement;
|
|
end;
|
|
VK_LEFT, VK_RIGHT:
|
|
begin
|
|
DoNextColumn(AKey = VK_RIGHT, GetColumnByDate(ATime, ResourceObject),
|
|
ATime, FCurrentResource);
|
|
Exit;
|
|
end;
|
|
VK_NEXT, VK_PRIOR:
|
|
if not DoNextPage(AKey = VK_NEXT, ATime, FCurrentResource) then Exit;
|
|
end;
|
|
ATime := ATime + ATimeDelta;
|
|
ViewInfo.MakeTimeVisible(ATime);
|
|
SetSelAnchor(ATime, AShift, FCurrentResource);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayNavigation.ValidateSelection(var ASelStart,
|
|
ASelFinish: TDateTime; var AResource: TcxSchedulerStorageResourceItem);
|
|
var
|
|
I: Integer;
|
|
AStart, AFinish, ADate: TDateTime;
|
|
begin
|
|
inherited ValidateSelection(ASelStart, ASelFinish, AResource);
|
|
if DayView.WorkTimeOnly and ((TimeOf(ASelStart) <> 0) or
|
|
(TimeOf(ASelFinish + ViewInfo.DayView.GetTimeIncrement) <> 0)) then
|
|
begin
|
|
ASelStart := ValidateTimeVisibility(ASelStart);
|
|
ASelFinish := ValidateTimeVisibility(ASelFinish);
|
|
end;
|
|
AStart := DateOf(Min(ASelFinish, ASelStart));
|
|
AFinish := DateOf(Max(ASelFinish, ASelStart));
|
|
for I := 0 to ViewInfo.DayCount - 1 do
|
|
begin
|
|
ADate := ViewInfo.Days[I];
|
|
if (ADate >= AStart) and (ADate <= AFinish) then Exit
|
|
end;
|
|
ASelFinish := GetColumnDate(0) + TimeOf(ASelFinish);
|
|
ASelStart := ASelFinish;
|
|
end;
|
|
|
|
function TcxSchedulerDayNavigation.ValidateTimeVisibility(
|
|
var ADateTime: TDateTime): TDateTime;
|
|
begin
|
|
Result := DateOf(ADateTime) + Min(DayView.WorkFinish,
|
|
Max(DayView.WorkStart, TimeOf(ADateTime)));
|
|
end;
|
|
|
|
function TcxSchedulerDayNavigation.ColCount: Integer;
|
|
begin
|
|
Result := ViewInfo.ColCount;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayNavigation.DoNextColumn(AGoToNext: Boolean; AColumn: Integer;
|
|
const ATime: TDateTime; AResource: TcxSchedulerStorageResourceItem);
|
|
const
|
|
AColInc: array[Boolean] of Integer = (-1, 1);
|
|
begin
|
|
if IsResourceNavigation(AGoToNext, AColumn, ATime) then Exit;
|
|
if ((AGoToNext and (AColumn = ColCount - 1)) or (not AGoToNext and (AColumn = 0))) then
|
|
begin
|
|
DayView.ScrollVisibleDays(not AGoToNext);
|
|
ReplaceDate(ATime + AColInc[AGoToNext], GetColumnResource(AColumn));
|
|
end
|
|
else
|
|
begin
|
|
Inc(AColumn, AColInc[AGoToNext]);
|
|
if (AResource <> GetColumnResource(AColumn)) then
|
|
ReplaceDate(GetColumnDate(AColumn), GetColumnResource(AColumn))
|
|
else
|
|
if not (ssShift in FShift) then
|
|
ReplaceDate(GetColumnDate(AColumn), GetColumnResource(AColumn))
|
|
else
|
|
SetSelAnchor(GetColumnDate(AColumn) + TimeOf(FCurrentAnchor), FShift, AResource);
|
|
end;
|
|
end;
|
|
|
|
function TcxSchedulerDayNavigation.DoNextPage(AGoForward: Boolean;
|
|
var ATime: TDateTime; var AResource: TcxSchedulerStorageResourceItem): Boolean;
|
|
var
|
|
ARow: Integer;
|
|
begin
|
|
if AGoForward then
|
|
Result := FSelRow < (ViewInfo.FRowCount - 1)
|
|
else
|
|
Result := FSelRow > 0;
|
|
if Result then
|
|
begin
|
|
if AGoForward then
|
|
begin
|
|
ARow := Min(FSelRow + ViewInfo.VisibleRowCount, ViewInfo.FRowCount - 1);
|
|
ViewInfo.FTopIndex := Min(ViewInfo.FTopIndex + ViewInfo.VisibleRowCount,
|
|
ViewInfo.FRowCount - 1)
|
|
end
|
|
else
|
|
begin
|
|
ARow := Max(0, FSelRow - ViewInfo.VisibleRowCount);
|
|
ViewInfo.FTopIndex := Max(0, ViewInfo.FTopIndex - ViewInfo.VisibleRowCount);
|
|
end;
|
|
ATime := ATime + GetRowTime(ARow);
|
|
end;
|
|
end;
|
|
|
|
function TcxSchedulerDayNavigation.GetColumnByDate(
|
|
const ADate: TDateTime; AResource: TObject): Integer;
|
|
begin
|
|
for Result := 0 to ViewInfo.ColCount - 1 do
|
|
with ViewInfo do
|
|
begin
|
|
if (GetColumnDate(Result) >= DateOf(ADate)) and
|
|
(GetColumnResource(Result) = AResource) then Exit;
|
|
end;
|
|
Result := 0;
|
|
end;
|
|
|
|
function TcxSchedulerDayNavigation.GetColumnDate(AColumn: Integer): TDateTime;
|
|
begin
|
|
Result := ViewInfo.GetColumnDate(AColumn);
|
|
end;
|
|
|
|
function TcxSchedulerDayNavigation.GetColumnResource(
|
|
AColumn: Integer): TcxSchedulerStorageResourceItem;
|
|
begin
|
|
Result := GetResourceFromViewInfo(ViewInfo.Containers[AColumn].Resource);
|
|
end;
|
|
|
|
function TcxSchedulerDayNavigation.GetRowTime(
|
|
const ARow: Integer; AFinish: Boolean = False): TDateTime;
|
|
begin
|
|
Result := RoundTime((ARow + ViewInfo.PrintStartRow +
|
|
Byte(AFinish)) * DayView.TimeScale * MinuteToTime);
|
|
end;
|
|
|
|
function TcxSchedulerDayNavigation.GetTimeRow(const ATime: TDateTime): Integer;
|
|
begin
|
|
Result := ViewInfo.GetTimeRow(ATime, True);
|
|
end;
|
|
|
|
function TcxSchedulerDayNavigation.IsResourceNavigation(AGoToNext: Boolean;
|
|
AColumn: Integer; const ATime: TDateTime): Boolean;
|
|
|
|
function GetActualDate(AIsFirst: Boolean): TDateTime;
|
|
begin
|
|
if AIsFirst then
|
|
Result := Integer(ViewInfo.SelectedDays.First)
|
|
else
|
|
Result := Integer(ViewInfo.SelectedDays.Last);
|
|
end;
|
|
|
|
var
|
|
AResource: TcxSchedulerStorageResourceItem;
|
|
begin
|
|
Result := True;
|
|
if ViewInfo.GroupByResource and ((AGoToNext and (AColumn = ColCount - 1)) or
|
|
(not AGoToNext and (AColumn = 0))) then
|
|
begin
|
|
if ScrollResourcesEx(AGoToNext, AResource) then
|
|
begin
|
|
ReplaceDate(GetActualDate(AGoToNext), AResource);
|
|
Exit;
|
|
end;
|
|
end
|
|
else
|
|
if ViewInfo.GroupByDate and ((IsLastResource and AGoToNext) or
|
|
(IsFirstResource and not AGotoNext)) then
|
|
begin
|
|
if ScrollResourcesEx(AGoToNext, AResource) then
|
|
begin
|
|
ReplaceSelParams(AResource);
|
|
Exit;
|
|
end
|
|
else
|
|
if not ((AGoToNext and (AColumn = ColCount - 1)) or
|
|
(not AGoToNext and (AColumn = 0))) and ScrollResourcesCycled(AGoToNext, AResource) then
|
|
ReplaceSelParams(AResource);
|
|
end;
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxSchedulerDayNavigation.GetDayView: TcxSchedulerDayView;
|
|
begin
|
|
Result := ViewInfo.DayView;
|
|
end;
|
|
|
|
function TcxSchedulerDayNavigation.GetSelectedDays: TcxSchedulerDateList;
|
|
begin
|
|
Result := ViewInfo.SelectedDays;
|
|
end;
|
|
|
|
function TcxSchedulerDayNavigation.GetViewInfo: TcxSchedulerDayViewViewInfo;
|
|
begin
|
|
Result := TcxSchedulerDayViewViewInfo(inherited ViewInfo);
|
|
end;
|
|
|
|
{ TcxSchedulerDayViewController }
|
|
|
|
constructor TcxSchedulerDayViewController.Create(
|
|
AOwner: TcxSchedulerSubControl);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FTimer := TTimer.Create(nil);
|
|
FScrollAreaRects := TList.Create;
|
|
end;
|
|
|
|
destructor TcxSchedulerDayViewController.Destroy;
|
|
begin
|
|
FScrollAreaRects.Free;
|
|
FTimer.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewController.BeforeMouseDown(
|
|
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
FIsEditingBeforeMouseDown := IsEditing;
|
|
inherited BeforeMouseDown(Button, Shift, X, Y);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewController.CancelScroll;
|
|
begin
|
|
InitTimer(False, scEndScroll);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewController.CheckScrolling(const APos: TPoint);
|
|
var
|
|
ACanScroll: Boolean;
|
|
AScrollCode: TScrollCode;
|
|
R: TRect;
|
|
begin
|
|
if FLockScrolling then Exit;
|
|
R := ViewInfo.Bounds;
|
|
R.Top := ViewInfo.FContentOffset;
|
|
ACanScroll := cxRectPtIn(R, APos);
|
|
AScrollCode := TScrollCode(FTimer.Tag);
|
|
if (APos.Y >= R.Top) and (APos.Y < (R.Top + cxScrollZoneSize)) then
|
|
AScrollCode := scLineUp
|
|
else
|
|
if (APos.Y < R.Bottom) and (APos.Y >= (R.Bottom - cxScrollZoneSize)) then
|
|
AScrollCode := scLineDown
|
|
else
|
|
ACanScroll := False;
|
|
if (ACanScroll <> FTimer.Enabled) or (Integer(AScrollCode) <> FTimer.Tag) then
|
|
InitTimer(ACanScroll, AScrollCode);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewController.CheckTimeRulerTime;
|
|
begin
|
|
if HitTest.HitAtTime and HitTest.HitAtTimeRuler and (DragEventHelper = nil) then
|
|
HitTest.SetHitTime(htcTime, DateOf(Navigation.SelAnchor) + TimeOf(HitTest.Time));
|
|
end;
|
|
|
|
function TcxSchedulerDayViewController.CreateDragEventHelper: TcxDragEventHelper;
|
|
begin
|
|
Result := TcxDayViewDragEventHelper.Create(Scheduler);
|
|
end;
|
|
|
|
function TcxSchedulerDayViewController.CreateNavigation: TcxSchedulerViewNavigation;
|
|
begin
|
|
Result := TcxSchedulerDayNavigation.Create(View);
|
|
end;
|
|
|
|
function TcxSchedulerDayViewController.CreateResizeEventHelper: TcxEventSizingHelper;
|
|
begin
|
|
Result := TcxDayViewEventSizing.Create(Scheduler);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewController.InitTimer(
|
|
AllowStart: Boolean; AScrollCode: TScrollCode);
|
|
begin
|
|
if AllowStart and FIsEditingBeforeMouseDown then
|
|
begin
|
|
FIsEditingBeforeMouseDown := False;
|
|
AllowStart := False;
|
|
end;
|
|
if not AllowStart then
|
|
FTimer.OnTimer := nil
|
|
else
|
|
FTimer.OnTimer := OnTimer;
|
|
FTimer.Enabled := AllowStart;
|
|
FTimer.Interval := cxScrollInterval;
|
|
FTimer.Tag := Integer(AScrollCode);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewController.MouseDown(
|
|
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
if (Button = mbLeft) and (DragKind = edkNone) and not HitTest.HitAtEvent then
|
|
begin
|
|
FLockScrolling := False;
|
|
CloseInplaceEdit;
|
|
UnselectEvents;
|
|
if HitTest.HitAtContainer and not HitTest.HitAtDayHeader then
|
|
begin
|
|
FLockScrolling := True;
|
|
with HitTest.ContainerCell do
|
|
begin
|
|
Navigation.ReplaceSelParams(DateTime, DateTime + 1 - Navigation.TimeIncrement, HitTest.Resource);
|
|
FStartSelAnchor := DateTime - Navigation.TimeIncrement;
|
|
end;
|
|
if (Shift = [ssLeft, ssDouble]) and CanCreateEventUsingDialog then
|
|
Scheduler.CreateEventUsingDialog
|
|
else
|
|
View.Refresh;
|
|
Exit;
|
|
end
|
|
else
|
|
if HitTest.HitAtTimeRuler then
|
|
begin
|
|
HitTest.SetHitTime(htcTime, GetTimeRulerTime);
|
|
FLockScrolling := HitTest.HitAtButton;
|
|
end;
|
|
end;
|
|
inherited MouseDown(Button, Shift, X, Y);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewController.MouseMove(
|
|
Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
AStart, AFinish: TDateTime;
|
|
begin
|
|
CheckTimeRulerTime;
|
|
if CanProcessMouseMove and (ssLeft in Shift) and (DragKind = edkNone) then
|
|
begin
|
|
if HitTest.HitAtContainer and not HitTest.HitAtDayHeader then
|
|
begin
|
|
InitTimer(False, scEndScroll);
|
|
AStart := DateOf(Navigation.SelRealStart);
|
|
AFinish := HitTest.ContainerCell.DateTime;
|
|
HitTest.SetBitState(htcTime, False);
|
|
HitTest.SetBitState(htcContainer, False);
|
|
if Navigation.SelResource = HitTest.Resource then
|
|
begin
|
|
if AFinish >= AStart then
|
|
Navigation.ReplaceSelParams(AStart, AFinish + 1 - Navigation.TimeIncrement)
|
|
else
|
|
Navigation.ReplaceSelParams(AStart + 1 - Navigation.TimeIncrement, AFinish);
|
|
end
|
|
else
|
|
Navigation.ReplaceSelParams(AStart, AStart + 1 - Navigation.TimeIncrement,
|
|
Navigation.SelResource);
|
|
View.Refresh;
|
|
Exit;
|
|
end
|
|
else
|
|
if HitTest.HitAtTimeRuler then
|
|
begin
|
|
Navigation.SetSelAnchor(GetTimeRulerTime, [ssShift] + Shift);
|
|
CheckScrolling(cxPoint(X, Y));
|
|
Exit;
|
|
end;
|
|
end;
|
|
inherited MouseMove(Shift, X, Y);
|
|
if CanProcessMouseMove and (ssLeft in Shift) then
|
|
CheckScrolling(cxPoint(X, Y));
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewController.MouseUp(
|
|
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
FLockScrolling := False;
|
|
CancelScroll;
|
|
inherited MouseUp(Button, Shift, X, Y);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewController.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;
|
|
AMousePos: TPoint;
|
|
AShift: TShiftState;
|
|
begin
|
|
AShift := GetShiftState;
|
|
if not (ssLeft in AShift) then
|
|
begin
|
|
CancelScroll;
|
|
SetCaptureControl(nil);
|
|
end
|
|
else
|
|
begin
|
|
APos := ViewInfo.FTopIndex;
|
|
ViewInfo.ScrollVertical(TScrollCode(FTimer.Tag), APos);
|
|
AMousePos := View.ScreenToClient(GetMouseCursorPos);
|
|
MouseMove(AShift, AMousePos.X, AMousePos.Y);
|
|
if (DragKind in [edkResizeStart, edkResizeEnd]) then
|
|
CheckUpdateEventBounds;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewController.CheckNavigatorScrollArea(
|
|
const APoint: TPoint);
|
|
|
|
function CheckArea(const ARect: TRect; AIsUpArea: Boolean): Boolean;
|
|
var
|
|
R: TRect;
|
|
DW, I: Integer;
|
|
begin
|
|
Result := PtInArea(ARect, APoint, AIsUpArea);
|
|
if not Result and (FScrollAreaRects.Count > 0) then
|
|
begin
|
|
DW := ViewInfo.DayView.OptionsView.GroupSeparatorWidth div 2;
|
|
for I := 0 to FScrollAreaRects.Count - 1 do
|
|
begin
|
|
if I mod 2 <> Byte(AIsUpArea) then Continue;
|
|
if not AIsUpArea then
|
|
R := cxRectSetLeft(ARect, Integer(FScrollAreaRects[I]) - DW, cxScrollZoneSize)
|
|
else
|
|
R := cxRectSetRight(ARect, Integer(FScrollAreaRects[I]) + DW + 1, cxScrollZoneSize);
|
|
Result := PtInRect(R, APoint);
|
|
if Result then Break;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
ACode: TScrollCode;
|
|
begin
|
|
if CheckArea(FUpScrollArea, False) then
|
|
ACode := scLineDown
|
|
else
|
|
if CheckArea(FDownScrollArea, True) then
|
|
ACode := scLineUp
|
|
else
|
|
ACode := scEndScroll;
|
|
NavigatorTimer.Tag := Byte(ACode);
|
|
if not NavigatorTimer.Enabled then
|
|
NavigatorTimer.Interval := cxNavigatorStartTimer;
|
|
NavigatorTimer.Enabled := ACode <> scEndScroll;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewController.DoneNavigatorScrollArea;
|
|
begin
|
|
FScrollAreaRects.Clear;
|
|
inherited DoneNavigatorScrollArea;
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewController.InitNavigatorScrollArea;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
FScrollAreaRects.Clear;
|
|
if ViewInfo.GroupingKind = gkByDate then
|
|
begin
|
|
for I := 0 to ViewInfo.GroupSeparatorCells.Count - 1 do
|
|
with ViewInfo.GroupSeparatorCells[I] do
|
|
begin
|
|
FScrollAreaRects.Add(Pointer(Bounds.Left));
|
|
FScrollAreaRects.Add(Pointer(Bounds.Right));
|
|
end;
|
|
end;
|
|
inherited InitNavigatorScrollArea;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewController.GetHitTest: TcxSchedulerDayViewHitTest;
|
|
begin
|
|
Result := TcxSchedulerDayView(View).HitTest;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewController.GetTimeRulerTime: TDateTime;
|
|
begin
|
|
Result := TimeOf(HitTest.Time) + DateOf(Navigation.SelAnchor);
|
|
end;
|
|
|
|
function TcxSchedulerDayViewController.GetViewInfo: TcxSchedulerDayViewViewInfo;
|
|
begin
|
|
Result := TcxSchedulerDayView(View).ViewInfo;
|
|
end;
|
|
|
|
{ TcxSchedulerDayViewPainter }
|
|
|
|
procedure TcxSchedulerDayViewPainter.Paint;
|
|
begin
|
|
inherited Paint;
|
|
ViewInfo.ContentCells.Draw(Canvas, DrawContentCell);
|
|
ViewInfo.HeaderContainerCells.Draw(Canvas, DrawContainerCell);
|
|
ViewInfo.EventCells.Draw(Canvas, DrawDayViewEventCell);
|
|
ViewInfo.ResourceHeaderCells.Draw(Canvas, DrawResourceHeaderCell);
|
|
ViewInfo.GroupSeparatorCells.Draw(Canvas, DrawGroupSeparatorCell);
|
|
ViewInfo.DayHeaderCells.Draw(Canvas, DrawHeaderCell);
|
|
ViewInfo.TimeRulerCells.Draw(Canvas, DrawTimeRulerCell);
|
|
ViewInfo.Buttons.Draw(Canvas, DrawButtonCell);
|
|
DrawBackgroundCell(ViewInfo.Background);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewPainter.DrawContainerCell(
|
|
AItem: TcxSchedulerCustomViewInfoItem; var ADone: Boolean);
|
|
begin
|
|
View.DoCustomDrawContainer(
|
|
TcxSchedulerContainerCellViewInfo(AItem), ADone);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewPainter.DrawDayViewEventCell(
|
|
AItem: TcxSchedulerCustomViewInfoItem; var ADone: Boolean);
|
|
begin
|
|
DrawEventCell(AItem, ADone);
|
|
end;
|
|
|
|
procedure TcxSchedulerDayViewPainter.DrawTimeRulerCell(
|
|
AItem: TcxSchedulerCustomViewInfoItem; var ADone: Boolean);
|
|
begin
|
|
View.DoCustomDrawTimeRuler(
|
|
TcxSchedulerTimeRulerCellViewInfo(AItem), ADone);
|
|
end;
|
|
|
|
function TcxSchedulerDayViewPainter.GetView: TcxSchedulerDayView;
|
|
begin
|
|
Result := ViewInfo.DayView;
|
|
end;
|
|
|
|
function TcxSchedulerDayViewPainter.GetViewInfo: TcxSchedulerDayViewViewInfo;
|
|
begin
|
|
Result := TcxSchedulerDayViewViewInfo(inherited ViewInfo);
|
|
end;
|
|
|
|
{ TcxSchedulerTimeRulerPopupMenu }
|
|
|
|
constructor TcxSchedulerTimeRulerPopupMenu.Create(
|
|
AScheduler: TcxCustomScheduler);
|
|
begin
|
|
inherited Create(AScheduler);
|
|
FItems := [rpmiNewEvent, rpmiNewAllDayEvent, rpmiNewReccuringEvent, rpmi60min,
|
|
rpmi30min, rpmi15min, rpmi10min, rpmi6min, rpmi5min];
|
|
end;
|
|
|
|
procedure TcxSchedulerTimeRulerPopupMenu.Assign(Source: TPersistent);
|
|
begin
|
|
inherited Assign(Source);
|
|
if Source is TcxSchedulerTimeRulerPopupMenu then
|
|
begin
|
|
Items := TcxSchedulerTimeRulerPopupMenu(Source).Items;
|
|
OnClick := TcxSchedulerTimeRulerPopupMenu(Source).OnClick;
|
|
OnPopup := TcxSchedulerTimeRulerPopupMenu(Source).OnPopup;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerTimeRulerPopupMenu.Execute(
|
|
AItem: TcxSchedulerTimeRulerPopupMenuItem);
|
|
begin
|
|
ExecuteCommand(Ord(AItem));
|
|
end;
|
|
|
|
function TcxSchedulerTimeRulerPopupMenu.GetMenuItem(
|
|
AItem: TcxSchedulerTimeRulerPopupMenuItem): TMenuItem;
|
|
begin
|
|
Result := FindItemByCommand(Root, Ord(AItem));
|
|
end;
|
|
|
|
procedure TcxSchedulerTimeRulerPopupMenu.CreateItems;
|
|
|
|
function GetChecked(ACommand: Integer): Boolean;
|
|
var
|
|
AIndex: Integer;
|
|
begin
|
|
Result := False;
|
|
AIndex := ACommand - Ord(rpmi60min);
|
|
if (AIndex < 0) or (AIndex > 5) then Exit;
|
|
Result := DayView.TimeScale = RulerScales[AIndex];
|
|
end;
|
|
|
|
procedure CreateRulerItem(const ACaption: string;
|
|
AItem: TcxSchedulerTimeRulerPopupMenuItem);
|
|
var
|
|
ACommand: Integer;
|
|
begin
|
|
if AItem in Items then
|
|
begin
|
|
ACommand := Ord(AItem);
|
|
CreateSubItem(Root, ACaption, ACommand, -1, True, GetChecked(ACommand));
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
CreateNewEventItems(rpmiNewEvent in FItems, rpmiNewAllDayEvent in FItems,
|
|
rpmiNewReccuringEvent in FItems, Ord(rpmiNewEvent), Ord(rpmiNewAllDayEvent),
|
|
Ord(rpmiNewReccuringEvent));
|
|
if Items * [rpmi60min, rpmi30min, rpmi15min, rpmi10min, rpmi6min, rpmi5min] <> [] then
|
|
begin
|
|
AddValidSeparator(Root);
|
|
CreateRulerItem(cxGetResourceString(@scxpm60Minutes), rpmi60min);
|
|
CreateRulerItem(cxGetResourceString(@scxpm30Minutes), rpmi30min);
|
|
CreateRulerItem(cxGetResourceString(@scxpm15Minutes), rpmi15min);
|
|
CreateRulerItem(cxGetResourceString(@scxpm10Minutes), rpmi10min);
|
|
CreateRulerItem(cxGetResourceString(@scxpm6Minutes), rpmi6min);
|
|
CreateRulerItem(cxGetResourceString(@scxpm5Minutes), rpmi5min);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSchedulerTimeRulerPopupMenu.DoExecute(ACommand: Integer);
|
|
var
|
|
AIndex: Integer;
|
|
begin
|
|
if ACommand in [Ord(rpmiNewEvent), Ord(rpmiNewAllDayEvent), Ord(rpmiNewReccuringEvent)] then
|
|
inherited DoExecute(ACommand)
|
|
else
|
|
begin
|
|
AIndex := ACommand - Ord(rpmi60min);
|
|
if AIndex in [0..5] then
|
|
DayView.TimeScale := RulerScales[AIndex];
|
|
end;
|
|
end;
|
|
|
|
function TcxSchedulerTimeRulerPopupMenu.DoOnClick(
|
|
ACommand: Integer): Boolean;
|
|
begin
|
|
Result := False;
|
|
if Assigned(FOnClick) then
|
|
FOnClick(Self, TcxSchedulerTimeRulerPopupMenuItem(ACommand), Result);
|
|
end;
|
|
|
|
function TcxSchedulerTimeRulerPopupMenu.DoOnPopup: Boolean;
|
|
begin
|
|
Result := False;
|
|
if Assigned(FOnPopup) then
|
|
FOnPopup(Self, InternalMenu, Result);
|
|
end;
|
|
|
|
function TcxSchedulerTimeRulerPopupMenu.IsValidCommand(
|
|
ACommand: Integer): Boolean;
|
|
begin
|
|
Result := (ACommand >= Ord(rpmiNewEvent)) and (ACommand <= Ord(rpmi5min));
|
|
end;
|
|
|
|
function TcxSchedulerTimeRulerPopupMenu.GetDayView: TcxSchedulerDayView;
|
|
begin
|
|
Result := Scheduler.CurrentView as TcxSchedulerDayView;
|
|
end;
|
|
|
|
end.
|
|
|