Componentes.Terceros.DevExp.../official/x.44/ExpressScheduler/Sources/cxSchedulerDayView.pas

2861 lines
94 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
Windows, Forms, Classes, SysUtils, Math, StdCtrls, Graphics, {$IFDEF DELPHI6}DateUtils, {$ENDIF}
Controls, ExtCtrls, cxControls, cxGraphics, cxStyles, cxGeometry, Menus,
cxLookAndFeelPainters, cxSchedulerCustomControls, cxSchedulerCustomResourceView,
cxSchedulerUtils, cxSchedulerStorage, cxSchedulerStrs;
const
cxDefaultTimeScale = 30;
cxScrollInterval = 25;
cxScrollZoneSize = 10;
cxcsHeaderContainer = 0;
cxcsSelectedHeaderContainer = 1;
cxcsTimeLine = 2;
cxcsTimeRuler = 3;
cxcsMaxDayViewValue = cxcsTimeRuler;
//for PS
cxcsDayViewStyleFirst = cxcsHeaderContainer;
cxcsDayViewStyleLast = cxcsMaxDayViewValue;
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
FAutoContentHeight: Boolean;
FEventShadows: Boolean;
FStyles: TcxSchedulerDayViewStyles;
FTimeRulerPopupMenu: TcxSchedulerTimeRulerPopupMenu;
FTimeScale: Integer;
FOnCustomDrawContainer: TcxSchedulerCustomDrawContainerEvent;
FOnCustomDrawTimeRuler: TcxSchedulerCustomDrawTimeRulerEvent;
function GetHitTest: TcxSchedulerDayViewHitTest;
function GetViewInfo: TcxSchedulerDayViewViewInfo;
procedure SetAutoContentHeight(AValue: Boolean);
procedure SetEventShadows(AValue: Boolean);
procedure SetStyles(AValue: TcxSchedulerDayViewStyles);
procedure SetTimeRulerPopupMenu(AValue: TcxSchedulerTimeRulerPopupMenu);
procedure SetTimeScale(AValue: Integer);
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 GetTimeIncrement: TDateTime; 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 AutoContentHeight: Boolean read FAutoContentHeight write SetAutoContentHeight default False;
property EventShadows: Boolean read FEventShadows write SetEventShadows default True;
property GroupingKind;
property Styles: TcxSchedulerDayViewStyles read FStyles write SetStyles;
property TimeRulerPopupMenu: TcxSchedulerTimeRulerPopupMenu read FTimeRulerPopupMenu write SetTimeRulerPopupMenu;
property TimeScale: Integer read FTimeScale write SetTimeScale default cxDefaultTimeScale;
property OnCustomDrawContainer: TcxSchedulerCustomDrawContainerEvent read FOnCustomDrawContainer write FOnCustomDrawContainer;
property OnCustomDrawTimeRuler: TcxSchedulerCustomDrawTimeRulerEvent read FOnCustomDrawTimeRuler write FOnCustomDrawTimeRuler;
end;
{ TcxSchedulerDayViewAdapter }
TcxSchedulerDayViewAdapter = class(TcxCustomResourceViewAdapter)
protected
FTopIndex: Integer;
procedure Store; override;
procedure Restore; override;
end;
{ TcxSchedulerDayViewViewInfo }
TcxSchedulerDayViewViewInfo = class(TcxSchedulerCustomResourceViewViewInfo)
private
function GetAutoHeight: Boolean;
function GetColumnInGroup: Integer;
function GetContentHeight: Integer;
function GetDayView: TcxSchedulerDayView;
function GetGroupCount: Integer;
function GetPrintRowCount: Integer;
function GetLinePerHour: Integer;
procedure SetLargeFont(AFont: TFont);
protected
FAdditionalTimeZone: Integer;
FBackground: TcxSchedulerBackgroundCellViewInfo;
FColCount: Integer;
FContentOffset: Integer;
FCurrentTimeZone: Integer;
FEventLayout: TcxCalculateEventLayout;
FHeaderLineCount: Integer;
FHeaderLineHeight: Integer;
FHeaderOffsetLeft: Integer;
FIsContainerSelected: 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(AEvent: TcxSchedulerControlEvent;
AContainer: TcxSchedulerContainerCellViewInfo; 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 CalculateHeaderLineCount;
procedure CalculateHeaders; virtual;
procedure CalculateMetrics; override;
procedure CalculateMetricsForPrinting;
procedure CalculatePrintRows;
procedure CalculateTimeLine; virtual;
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 CreateEventLayout: TcxCalculateEventLayout; virtual;
procedure DoCalculate; override;
procedure ExtractEvents(ASource, ADest: TcxSchedulerEventList; AIndex: Integer);
function GetContentParams(const ATime: TDateTime;
AResource: TcxSchedulerResourceViewInfo): TcxViewParams; override;
function GetColumnDate(AIndex: Integer): TDateTime;
function GetColumnResource(AIndex: Integer): TcxSchedulerResourceViewInfo;
function GetColumnResourceIndex(AIndex: Integer): Integer;
function GetContainer(AIndex: Integer): TcxSchedulerContainerCellViewInfo; virtual;
function GetContainerCount: Integer; virtual;
function GetDayHeaderHeight: Integer; override;
function GetEventSlotDisplayText(AEvent: TcxSchedulerControlEvent): string;
function GetTimeLineParams: TcxViewParams; override;
function GetTimeRulerParams: TcxViewParams;
function GetTimeRow(const ATime: TDateTime; AIsStart: Boolean): Integer;
function GetRowTime(AColumn, ARow: Integer): TDateTime;
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 OnClickMoreButton(Sender: TcxSchedulerMoreEventsButtonViewInfo); 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 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 HeaderContainerCells: TcxSchedulerViewInfoCellList read FHeaderContainerCells;
property HeaderLineHeight: Integer read FHeaderLineHeight;
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;
protected
function GetOriginHitTestMask: Int64; override;
procedure GetOriginState; override;
function InHeader: Boolean; virtual;
function IsAtOrigin: Boolean; override;
procedure SetCloneEventsTimeDelta(AStart, ACurrent: TDateTime; AInHeader: Boolean);
procedure UpdateClonesTime; override;
procedure UpdateEventProperties; override;
procedure UpdateEventStates;
property Controller: TcxSchedulerDayViewController read GetController;
property HitTest: TcxSchedulerDayViewHitTest read GetHitTest;
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;
public
procedure KeyDown(var AKey: Word; AShift: TShiftState); override;
procedure ValidateSelection(var ASelStart, ASelFinish: TDateTime;
var AResource: TcxSchedulerStorageResourceItem); override;
property DayView: TcxSchedulerDayView read GetDayView;
property SelectedDays: TcxSchedulerDateList read GetSelectedDays;
property ViewInfo: TcxSchedulerDayViewViewInfo read GetViewInfo;
end;
{ TcxSchedulerDayViewController }
TcxSchedulerDayViewController = class(TcxSchedulerCustomResourceViewController)
private
FPos: TPoint;
FTimer: TTimer;
procedure CheckUpdateEventBounds;
function GetHitTest: TcxSchedulerDayViewHitTest;
function GetViewInfo: TcxSchedulerDayViewViewInfo;
protected
FIsEditingBeforeMouseDown: Boolean;
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;
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: 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
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;
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 := clBtnText;
end;
cxcsTimeRuler:
begin
AParams.Color := Painter.DefaultSchedulerControlColor;
AParams.TextColor := Painter.DefaultHeaderTextColor;
end;
end;
end;
function TcxSchedulerDayViewStyles.GetHeaderContainerParams(
const ADate: TDateTime; AResource: TcxSchedulerStorageResourceItem;
ASelected: Boolean): TcxViewParams;
begin
GetDefaultViewParams(cxcsHeaderContainer + Byte(ASelected), nil, Result);
CombineParamsWithStyle(GetValue(cxcsHeaderContainer + Byte(ASelected)), [], Result);
end;
function TcxSchedulerDayViewStyles.GetTimeLineParams: TcxViewParams;
begin
GetDefaultViewParams(cxcsTimeLine, nil, Result);
CombineParamsWithStyle(TimeLine, [], Result);
Result.TextColor := Scheduler.OptionsView.DayBorderColor;
if Result.TextColor = clDefault then
Result.TextColor := clWindowText;
end;
function TcxSchedulerDayViewStyles.GetTimeRulerParams: TcxViewParams;
begin
GetDefaultViewParams(cxcsTimeRuler, nil, Result);
CombineParamsWithStyle(TimeRuler, [], 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 := 24 * 60 div AScale - 1
else
StartRow := 0;
end;
IsBreakEvent := (StopRow = 24 * 60 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: Integer);
begin
FFinishTime := ADate + (StopRow + 1) * AScale * MinuteToTime;
FStartTime := ADate + StartRow * 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.CalculateDisplayRect(FWidth, FRowHeight);
OffsetRect(AInfo.FDisplayRect, Left, Top - Byte(not FViewInfo.HasVisibleBounds));
AInfo.CalculateTimes(FDate, FTimeScale);
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;
FEventShadows := True;
end;
procedure TcxSchedulerDayView.Assign(Source: TPersistent);
begin
if Source is TcxSchedulerDayView then
begin
FEventShadows := TcxSchedulerDayView(Source).FEventShadows;
FTimeScale := TcxSchedulerDayView(Source).FTimeScale;
TimeRulerPopupMenu := TcxSchedulerDayView(Source).TimeRulerPopupMenu;
end;
inherited Assign(Source);
end;
procedure TcxSchedulerDayView.MakeWorkTimeVisible;
begin
if Visible then
ViewInfo.FTopIndex := (HourOf(WorkStart) * 60 + MinuteOf(WorkStart)) div TimeScale;
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.GetTimeIncrement: TDateTime;
begin
Result := TimeOf(TimeScale * MinuteToTime);
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 Event date out of bounds then need scroll
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;
end;
end;
procedure TcxSchedulerDayView.Notification(AComponent: TComponent;
Operation: TOperation);
begin
if (Operation = opRemove) and (AComponent = TimeRulerPopupMenu.PopupMenu) then
TimeRulerPopupMenu.PopupMenu := nil;
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.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.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
FTimeScale := AValue;
MakeWorkTimeVisible;
Refresh;
end;
end;
{ TcxSchedulerDayViewAdapter }
procedure TcxSchedulerDayViewAdapter.Store;
begin
FTopIndex := TcxSchedulerDayViewViewInfo(ViewInfo).FTopIndex;
end;
procedure TcxSchedulerDayViewAdapter.Restore;
begin
TcxSchedulerDayViewViewInfo(ViewInfo).FTopIndex := FTopIndex;
end;
{ TcxSchedulerDayViewViewInfo }
constructor TcxSchedulerDayViewViewInfo.Create(
AOwner: TcxSchedulerSubControl);
begin
inherited Create(AOwner);
FLargeFont := TFont.Create;
FTimeRulerCells := TcxSchedulerViewInfoCellList.Create;
FCells.Insert(1, FTimeRulerCells);
end;
destructor TcxSchedulerDayViewViewInfo.Destroy;
begin
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 - 2, 1,
FVisibleRowCount, TopIndex, True, True);
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 - 1;
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(
AEvent: TcxSchedulerControlEvent;
AContainer: TcxSchedulerContainerCellViewInfo; AColIndex: Integer);
var
AHeight, I, J, ATop, ALine: Integer;
ABounds: TRect;
ACell: TcxSchedulerEventCellViewInfo;
ANextContainer: TcxSchedulerContainerCellViewInfo;
begin
ANextContainer := AContainer;
ALine := AContainer.LineCount + 1;
J := AColIndex;
for I := AColIndex + 1 to ContainerCount - 1 do
if IsColumnEvent(AEvent, I, True) and (AContainer.Resource = GetColumnResource(I)) then
begin
J := I;
ANextContainer := Containers[I];
ANextContainer.LineCount := ALine;
end
else
Break;
AHeight := FHeaderLineHeight + cxTextOffset;
ATop := Bounds.Top + DayHeaderHeight + FResourceHeaderHeight * Byte(GroupingKind <> gkNone);
ABounds := Rect(AContainer.Bounds.Left + cxTextOffset * 2,
ATop + cxTextOffset + AContainer.LineCount * AHeight,
ANextContainer.Bounds.Right - cxTextOffset * 2 - Byte(bRight in ANextContainer.Borders),
ATop + (AContainer.LineCount + 1) * AHeight );
AContainer.LineCount := ALine;
ACell := AddEventCell(CreateHeaderEventViewData(AEvent, ABounds,
AContainer.DateTime, ANextContainer.DateTime + 1, AContainer.Resource));
if not (AEvent.AllDayEvent and AEvent.IsClone) then
for I := AColIndex to J do
SetColumnTimeLineStyle(ACell, I);
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 HasVisibleBounds 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 - TopIndex * ContentLineHeight, ContentLineHeight);
if not HasVisibleBounds 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 FRowCount - 1 do
begin
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 HasVisibleBounds and (I < (FColCount - 1)) then
ACell.Borders := [bRight];
if not HasVisibleBounds 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;
end;
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
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));
FEventLayout.SetParams(DateOf(AContainer.DateTime), TimeScale,
FContentLineHeight, AContainer.Bounds.Left - I, FContentOffset -
TopIndex * FContentLineHeight, 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 HasVisibleBounds 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;
procedure TcxSchedulerDayViewViewInfo.CalculateHeaderEvents;
var
I, J: Integer;
begin
for I := 0 to ContainerCount - 1 do
for J := 0 to Events.AbsoluteCount - 1 do
begin
if IsColumnEvent(Events.AbsoluteItems[J], I, True) and ((I = 0) or
(GetColumnResourceIndex(I) <> GetColumnResourceIndex(I - 1)) or
not IsColumnEvent(Events.AbsoluteItems[J], I - 1, True)) then
AddHeaderContainerEvent(Events.AbsoluteItems[J], Containers[I], I);
end;
end;
procedure TcxSchedulerDayViewViewInfo.CalculateHeaderLineCount;
var
I, J, ALineCount, ANextLineCount: Integer;
AEvent: TcxSchedulerControlEvent;
begin
FHeaderLineCount := 1;
ANextLineCount := 0;
for I := 0 to FColCount - 1 do
begin
ALineCount := ANextLineCount;
ANextLineCount := 0;
for J := 0 to Events.AbsoluteCount - 1 do
begin
AEvent := Events.AbsoluteItems[J];
if IsColumnEvent(AEvent, I, True) then
begin
if FHideClones and AEvent.IsClone then
Continue
else
begin
if (I = 0) or not IsColumnEvent(AEvent, I - 1, True) then
Inc(ALineCount);
if (I < (FColCount - 1)) and IsColumnEvent(AEvent, I + 1, True) then
ANextLineCount := ALineCount;
end;
end;
end;
FHeaderLineCount := Max(FHeaderLineCount, ALineCount);
end;
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
Result := FHeaderLineCount * (FContentLineHeight + cxTextOffset) + 1;
if AutoHeight or (FVisibleRowCount < FRowCount + FHeaderLineCount) then
Inc(Result, ContentHeight - FVisibleRowCount * FContentLineHeight);
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;
CalculateHeaderLineCount;
LargeFont := GetTimeRulerParams.Font;
CalculateHeaderLineCount;
if not HasVisibleBounds then
begin
FTimeScale := DayView.TimeScale;
FRowCount := 24 * 60 div TimeScale;
FContentOffset := DayHeaderHeight + cxTextOffset +
Byte(GroupingKind <> gkNone) * FResourceHeaderHeight;
end
else
CalculateMetricsForPrinting;
FVisibleRowCount := Max(1, ContentHeight div FContentLineHeight);
if HasVisibleBounds then Exit;
if AutoHeight and (FVisibleRowCount > (FRowCount + FHeaderLineCount)) then
begin
FContentLineHeight := ContentHeight div (FRowCount + FHeaderLineCount);
FVisibleRowCount := FRowCount + FHeaderLineCount;
end;
Inc(FContentOffset, GetExtraContentOffset);
FVisibleRowCount := Min(FRowCount, Max(1, ContentHeight div FContentLineHeight));
while (FTopIndex > 0) and ((FTopIndex + FVisibleRowCount) > (FRowCount - 1)) 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
CalculatePrintRows;
FTopIndex := PrintStartRow;
HeightAdjusted := AContentHeight >= FContentLineHeight * PrintRowCount;
if not HeightAdjusted then
begin
if FTimeScale < 60 then
FTimeScale := FTimeScale * 2
else
if UnusedRowCount > 0 then
Dec(FUnusedRowCount)
else
Break;
end;
end;
CalculatePrintRows;
if HeightAdjusted then
begin
FContentLineHeight := AContentHeight div PrintRowCount;
Inc(FContentOffset, AContentHeight - FContentLineHeight * PrintRowCount);
end;
end;
procedure TcxSchedulerDayViewViewInfo.CalculatePrintRows;
function GetTimeRow(ATime: TDateTime; IsFinish: Boolean): Integer;
begin
Result := HourOf(ATime) * 60 + MinuteOf(ATime);
if IsFinish and (Result mod FTimeScale <> 0) then
Result := Result div FTimeScale + 1
else
Result := Result div FTimeScale - Byte(IsFinish);
end;
begin
FRowCount := 24 * 60 div FTimeScale;
FPrintStartRow := GetTimeRow(PrintFrom, False);
FPrintFinishRow := GetTimeRow(PrintTo, True);
end;
procedure TcxSchedulerDayViewViewInfo.CalculateTimeLine;
var
ABounds, R: TRect;
I: 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
R := cxRectSetTop(R, R.Top - TopIndex * FContentLineHeight,
LinePerHour * FContentLineHeight);
ABounds := Bounds;
ABounds.Top := FContentOffset;
FTimeRulerCells.Add(ACommonCell);
for I := 0 to 23 do
begin
if IsHourVisible(I) then
begin
CreateCellInstance(TcxSchedulerTimeRulerCellViewInfo, R,
ABounds, AViewParams, ARulerCell);
ARulerCell.Calculate(I, LinePerHour, FCurrentTimeZone,
FAdditionalTimeZone, LargeFont);
FTimeRulerCells.Add(ARulerCell);
end;
R := cxRectSetTop(R, R.Bottom);
end;
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 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
if HasVisibleBounds then Inc(FBounds.Right);
FEventLayout := CreateEventLayout;
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));
FEventCells.Sort(TListSortCompare(@cxCompareEventViewInfoOrders));
end;
end;
function TcxSchedulerDayViewViewInfo.CreateContentEventViewData(
AEventInfo: TcxEventLayoutInfo; AResource: TcxSchedulerResourceViewInfo): TcxSchedulerEventViewData;
begin
Result := CreateEventViewData(AEventInfo.Event,
AEventInfo.DisplayRect, AEventInfo.Start, AEventInfo.Finish, AResource);
Result.VisibleRect.TopLeft := Point(FHeaderOffsetLeft, FContentOffset);
Result.ShowTimeLine := True;
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.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): TDateTime;
begin
if GroupingKind = gkByDate then
AIndex := AIndex div ResourceCount
else
if GroupingKind = gkByResource then
AIndex := AIndex mod DayCount;
Result := Days[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 HasVisibleBounds 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.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);
Result := Round(ACount);
if not AIsStart and (TimeOf(ACount) = 0) then
Dec(Result);
end;
function TcxSchedulerDayViewViewInfo.GetRowTime(
AColumn, ARow: Integer): TDateTime;
begin
Result := GetColumnDate(AColumn) + (ARow * TimeScale) * MinuteToTime;
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
Result := not HasVisibleBounds or
((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.OnClickMoreButton(
Sender: TcxSchedulerMoreEventsButtonViewInfo);
var
ARow: Integer;
begin
ARow := Min(FRowCount, Max(0, Round(Sender.DateTime * FRowCount)));
if not Sender.IsDown then
FTopIndex := ARow
else
FTopIndex := Max(0, ARow - VisibleRowCount);
View.LayoutChanged;
end;
procedure TcxSchedulerDayViewViewInfo.SetColumnTimeLineStyle(
AViewInfo: TcxSchedulerEventCellViewInfo; AColIndex: Integer);
var
ACell: TcxSchedulerContentCellViewInfo;
I, AOffset, StartRow, StopRow, ACount: Integer;
begin
if AViewInfo.Event.Start <= GetColumnDate(AColIndex) then
StartRow := 0
else
StartRow := GetTimeRow(AViewInfo.Event.Start, True);
if (AViewInfo.Event.Finish - 1) >= GetColumnDate(AColIndex) then
StopRow := FRowCount - 1
else
StopRow := GetTimeRow(AViewInfo.Event.Finish, False);
AOffset := 0;
if HasVisibleBounds then
begin
ACount := PrintFinishRow - PrintStartRow + 1;
if (StartRow > PrintFinishRow) or (StopRow < PrintStartRow) then Exit;
StartRow := Max(0, StartRow - PrintStartRow);
StopRow := Min(PrintFinishRow - StartRow, StopRow - PrintStartRow);
AOffset := PrintStartRow;
end
else
ACount := FRowCount;
Inc(StartRow, AColIndex * ACount);
Inc(StopRow, AColIndex * ACount);
Dec(AOffset, AColIndex * ACount);
for I := StartRow to StopRow do
begin
if not IsRowVisible(I + AOffset) then Continue;
ACell := TcxSchedulerContentCellViewInfo(ContentCells[I]);
if ACell.TimeEvent = nil then
ACell.TimeEvent := AViewInfo;
end;
end;
function TcxSchedulerDayViewViewInfo.GetAutoHeight: Boolean;
begin
Result := DayView.AutoContentHeight or HasVisibleBounds;
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.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.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.InHeader: Boolean;
begin
with HitTest do
Result := HitAtDayHeader or HitAtContainer;
end;
function TcxDayViewDragEventHelper.IsAtOrigin: Boolean;
begin
Result := inherited IsAtOrigin or
((FStartInHeader and InHeader) and (Controller.StartDragHitTime = HitTest.Time) and
((FStartResource = nil) or (FStartResource = HitTest.Resource)));
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;
if AInHeader then
begin
ADelta := DateOf(AStart) - DateOf(ACurrent);
if not IsHeaderEvent(Source) then
Duration := 1
else
Duration := Source.Duration;
MoveTo(DateOf(Source.Start) - ADelta);
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.UpdateClonesTime;
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;
end;
procedure TcxDayViewDragEventHelper.UpdateEventProperties;
begin
inherited UpdateEventProperties;
UpdateEventStates;
end;
procedure TcxDayViewDragEventHelper.UpdateEventStates;
const
States: array[Boolean] of Byte = (tlsBusy, tlsFree);
var
I: Integer;
AEvent: TcxSchedulerControlEvent;
begin
for I := 0 to Clones.Count - 1 do
begin
AEvent := Clones[I];
if (AEvent.AllDayEvent <> AEvent.Source.AllDayEvent) and
((AEvent.AllDayEvent and (AEvent.Source.State = tlsBusy)) or
(not AEvent.AllDayEvent and (AEvent.Source.State = tlsFree))) then
AEvent.State := States[AEvent.AllDayEvent];
end;
end;
function TcxDayViewDragEventHelper.GetController: TcxSchedulerDayViewController;
begin
Result := TcxSchedulerDayViewController(inherited Controller);
end;
function TcxDayViewDragEventHelper.GetHitTest: TcxSchedulerDayViewHitTest;
begin
Result := TcxSchedulerDayViewHitTest(inherited HitTest);
end;
{ TcxDayViewEventSizing }
function TcxDayViewEventSizing.GetDragCursor(Accepted: Boolean): TCursor;
const
Cursors: array[Boolean] of TCursor = (crSchedulerVertResize,
crSchedulerHorzResize);
begin
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) then
ATimeDelta := TimeOf(DayView.WorkStart);
VK_END:
begin
if ssCtrl in AShift 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);
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.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 (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 + Byte(AFinish)) * DayView.TimeScale * MinuteToTime);
end;
function TcxSchedulerDayNavigation.GetTimeRow(const ATime: TDateTime): Integer;
begin
Result := ViewInfo.GetTimeRow(ATime, True);
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);
end;
destructor TcxSchedulerDayViewController.Destroy;
begin
FTimer.Free;
inherited Destroy;
end;
procedure TcxSchedulerDayViewController.BeforeMouseDown(
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
FIsEditingBeforeMouseDown := IsEditing;
inherited BeforeMouseDown(Button, Shift, X, Y);
if HitTest.HitAtTimeRuler then
HitTest.SetHitTime(htcTime, TimeOf(HitTest.Time) + DateOf(DateOf(Navigation.SelAnchor)));
end;
procedure TcxSchedulerDayViewController.CancelScroll;
begin
InitTimer(False, scEndScroll);
end;
procedure TcxSchedulerDayViewController.CheckScrolling(const APos: TPoint);
var
ACanScroll: Boolean;
AScrollCode: TScrollCode;
R: TRect;
begin
R := ViewInfo.Bounds;
R.Top := ViewInfo.FContentOffset;
FPos := APos;
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 in [edkNone]) and HitTest.HitAtContainer and
not HitTest.HitAtDayHeader and not HitTest.HitAtEvent then
begin
CloseInplaceEdit;
UnselectEvents;
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;
end
else
begin
if HitTest.HitAtTimeRuler then
HitTest.SetHitTime(htcTime, TimeOf(HitTest.Time) + DateOf(DateOf(Navigation.SelAnchor)));
inherited MouseDown(Button, Shift, X, Y);
end;
end;
procedure TcxSchedulerDayViewController.MouseMove(
Shift: TShiftState; X, Y: Integer);
var
AStart, AFinish: TDateTime;
begin
CheckTimeRulerTime;
if (ssLeft in Shift) and (DragKind in [edkNone]) and 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;
inherited MouseMove(Shift, X, Y);
if not (ssLeft in Shift) then Exit;
if ssLeft in Shift then
CheckScrolling(cxPoint(X, Y))
else
CancelScroll;
end;
procedure TcxSchedulerDayViewController.MouseUp(
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
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;
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);
MouseMove(AShift, FPos.X, FPos.Y);
if (DragKind in [edkResizeStart, edkResizeEnd]) then
CheckUpdateEventBounds;
end;
end;
procedure TcxSchedulerDayViewController.CheckUpdateEventBounds;
var
ASizingHelper: TcxEventSizingHelper;
begin
if (Scheduler.DragAndDropState = ddsInProcess) and
(Scheduler.DragAndDropObject is TcxSchedulerDragAndDropObject) then
begin
ASizingHelper := TcxSchedulerDragAndDropObject(Scheduler.DragAndDropObject).SizingHelper;
if ASizingHelper is TcxDayViewEventSizing then
TcxDayViewEventSizing(ASizingHelper).UpdateEventBounds;
end;
end;
function TcxSchedulerDayViewController.GetHitTest: TcxSchedulerDayViewHitTest;
begin
Result := TcxSchedulerDayView(View).HitTest;
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.