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

3081 lines
95 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 cxSchedulerDateNavigator;
{$I cxVer.Inc}
interface
uses
{$IFDEF DELPHI6}
Types,
{$ELSE}
MultiMon,
{$ENDIF}
Windows, SysUtils, Classes, Controls, Graphics, ExtCtrls,
cxSchedulerCustomControls, cxSchedulerUtils, cxContainer, cxClasses,
cxGraphics, cxLookAndFeelPainters, cxStyles, cxControls, cxDateUtils;
const
// hit test codes
htcCalendar = 2;
htcDayCaptions = 3;
htcMonthName = 4;
htcNextMonth = 5;
htcPrevMonth = 6;
htcWeekSelectionBar = 7;
// style indexes
cxdnBackground = 0;
cxdnContent = 1;
cxdnHeader = 2;
cxdnSelection = 3;
//for PS
cxcsDateNavigatorFirst = cxdnBackground;
cxcsDateNavigatorLast = cxdnSelection;
cxDaysCalendarMaxColCount = 8;
cxMaxMonthViewInfoDays = 6 * 7;
cxMaxWeekCount = 6;
type
TcxSchedulerDateNavigatorDayNumberViewInfo = class;
TcxSchedulerDateNavigatorMonthHeaderViewInfo = class;
TcxSchedulerDateNavigatorMonthContentViewInfo = class;
TcxSchedulerDateNavigatorMonthViewInfo = class;
TcxSchedulerDateNavigatorViewInfo = class;
TcxSchedulerDateNavigator = class;
TcxSchedulerDateNavigatorViewInfoClass = class of TcxSchedulerDateNavigatorViewInfo;
{ TcxSchedulerDateNavigatorPainter }
TcxSchedulerDateNavigatorPainter = class(TcxSchedulerSubControlPainter)
private
FHeaderParams: TcxViewParams; //for callback procedure
FDateNavigator: TcxSchedulerDateNavigator;
FHeaderTransparent: Boolean;
procedure CheckDrawFrame(const ABounds: TRect; ADate: TDateTime);
function DrawHeaderBackground(ACanvas: TcxCanvas; const ABounds: TRect): Boolean;
protected
procedure DoDrawDayCaptions(AViewInfo: TcxSchedulerDateNavigatorMonthContentViewInfo); virtual;
procedure DoDrawDayNumbers(AViewInfo: TcxSchedulerDateNavigatorMonthContentViewInfo); virtual;
procedure DoDrawMonthContent(AViewInfo: TcxSchedulerDateNavigatorMonthContentViewInfo); virtual;
procedure DoDrawMonthHeader(AViewInfo: TcxSchedulerDateNavigatorMonthHeaderViewInfo); virtual;
procedure DrawBackground; virtual;
procedure DrawDayNumber(ADayInfo: TcxSchedulerDateNavigatorDayNumberViewInfo);
procedure DrawMonthHeader(AViewInfo: TcxSchedulerDateNavigatorMonthHeaderViewInfo); virtual;
procedure DrawSeparators(AViewInfo: TcxSchedulerDateNavigatorMonthContentViewInfo); virtual;
procedure DrawWeekNumbers(AViewInfo: TcxSchedulerDateNavigatorMonthContentViewInfo); virtual;
property DateNavigator: TcxSchedulerDateNavigator read FDateNavigator;
public
constructor Create(AOwner: TcxSchedulerSubControl); override;
procedure Paint; override;
end;
TcxSchedulerDateNavigatorPainterClass = class of TcxSchedulerDateNavigatorPainter;
{ TcxSchedulerDateNavigatorCaptionViewInfo }
TcxSchedulerDateNavigatorCaptionViewInfo = class
private
FBounds: TRect;
FSaveParams: TcxViewParams;
FText: string;
FTransparent: Boolean;
FViewParams: TcxViewParams;
protected
procedure RestoreParams;
procedure SaveParams(ATransparent: Boolean);
property Text: string read FText write FText;
property Transparent: Boolean read FTransparent write FTransparent;
public
property Bounds: TRect read FBounds;
property ViewParams: TcxViewParams read FViewParams write FViewParams;
end;
{ TcxSchedulerDateNavigatorDayNumberViewInfo }
TcxSchedulerDateNavigatorDayNumberViewInfo = class(TcxSchedulerDateNavigatorCaptionViewInfo)
private
FBold: Boolean;
FDate: TDateTime;
FGrayed: Boolean;
FSelected: Boolean;
FSelectionSideBounds: TRect;
public
property Bold: Boolean read FBold write FBold;
property Bounds;
property Date: TDateTime read FDate;
property Grayed: Boolean read FGrayed;
property Selected: Boolean read FSelected;
property SelectionSideBounds: TRect read FSelectionSideBounds;
property Text;
property Transparent;
property ViewParams;
end;
{ TcxSchedulerDateNavigatorDayCaptionViewInfo }
TcxSchedulerDateNavigatorDayCaptionViewInfo = class(TcxSchedulerDateNavigatorCaptionViewInfo)
private
FIndex: Byte;
public
property Bounds;
property Index: Byte read FIndex;
property Text;
property Transparent;
property ViewParams;
end;
{ TcxSchedulerDateNavigatorMonthHeaderViewInfo }
TcxSchedulerDateNavigatorMonthHeaderViewInfo = class(TcxSchedulerDateNavigatorCaptionViewInfo)
private
FArrows: TcxHeaderArrows;
FNeighbors: TcxNeighbors;
FOwner: TcxSchedulerDateNavigatorMonthViewInfo;
FMonthNameBounds: TRect;
function GetMonth: Integer;
function GetMonthNameBounds: TRect;
function GetYear: Integer;
protected
procedure Calculate(const ABounds: TRect); virtual;
public
constructor Create(AOwner: TcxSchedulerDateNavigatorMonthViewInfo);
property Arrows: TcxHeaderArrows read FArrows;
property Bounds;
property Month: Integer read GetMonth;
property Neighbors: TcxNeighbors read FNeighbors;
property MonthNameBounds: TRect read FMonthNameBounds;
property Owner: TcxSchedulerDateNavigatorMonthViewInfo read FOwner;
property Text;
property Transparent;
property ViewParams;
property Year: Integer read GetYear;
end;
{ TcxSchedulerDateNavigatorMonthContentViewInfo }
TcxSchedulerDateNavigatorMonthContentViewInfo = class
private
FBounds: TRect;
FCol: Integer;
FRow: Integer;
FDateNavigator: TcxSchedulerDateNavigator;
FDays: array[0..cxMaxMonthViewInfoDays - 1] of TcxSchedulerDateNavigatorDayNumberViewInfo;
FDayCount: Integer;
FDayCaptions: array[0..6] of TcxSchedulerDateNavigatorDayCaptionViewInfo;
FFont: TFont;
FFontCharset: TFontCharset;
FHorzSeparatorBound: TRect;
FMonth: Integer;
FOwner: TcxSchedulerDateNavigatorMonthViewInfo;
FSaveParams: TcxViewParams;
FSelectedParams: TcxViewParams;
FTransparent: Boolean;
FVertSeparatorBound: TRect;
FViewInfo: TcxSchedulerDateNavigatorViewInfo;
FViewParams: TcxViewParams;
FWeekBounds: array[0..5] of TRect;
FWeekCount: Integer;
FWeekTexts: array[0..5] of string;
FWeekSelectionBarBounds: TRect;
FYear: Integer;
procedure CreateDayInfos;
procedure CreateDayCaptionInfos;
procedure DestroyDayInfos;
procedure DestroyDayCaptionInfos;
function GetDayCaptionInfo(Index: Byte): TcxSchedulerDateNavigatorDayCaptionViewInfo;
function GetDayRectFromColAndRow(ACol, ARow: Integer): TRect;
function GetDayNumberViewInfo(Index: Byte): TcxSchedulerDateNavigatorDayNumberViewInfo;
function GetGrayed(ADate: TDateTime): Boolean;
function GetSelectionSideBounds(const ADayBounds: TRect; ACol: Integer): TRect;
function IsValidDayIndex(Index: Byte): Boolean;
function IsValidDayCaptionIndex(Index: Byte): Boolean;
function IsValidWeekIndex(Index: Byte): Boolean;
procedure SetWeekText(Index: Byte; const Value: string);
protected
procedure CalcAndAddDayInfo(ADate: TDateTime; const ABounds: TRect;
const ASelectionSideBounds: TRect);
procedure Calculate(ACol, ARow, AYear, AMonth: Integer); virtual;
procedure CalcDays; virtual;
procedure CalcDayCaptions; virtual;
procedure CalcParams; virtual;
procedure CalcSeparatorsBound; virtual;
function GetDateViewParams(ADate: TDateTime; ASelected: Boolean): TcxViewParams; virtual;
function GetDayText(ADate: TDateTime): string; virtual;
function GetDayCaptionText(Index: Byte): string; virtual;
function GetWeekBound(Index: Byte): TRect; virtual;
function GetWeekText(Index: Byte): string; virtual;
procedure RestoreParams;
procedure SaveParams;
procedure UpdateElementsAfterCustomDraw(ACanvas: TcxCanvas);
property DateNavigator: TcxSchedulerDateNavigator read FDateNavigator;
property Font: TFont read FFont;
property FontCharset: TFontCharset read FFontCharset;
property Owner: TcxSchedulerDateNavigatorMonthViewInfo read FOwner;
property ViewInfo: TcxSchedulerDateNavigatorViewInfo read FViewInfo;
property WeekSelectionBarBounds: TRect read FWeekSelectionBarBounds;
public
constructor Create(AOwner: TcxSchedulerDateNavigatorMonthViewInfo); virtual;
destructor Destroy; override;
property Bounds: TRect read FBounds;
property Col: Integer read FCol;
property DayCount: Integer read FDayCount;
property Days[Index: Byte]: TcxSchedulerDateNavigatorDayNumberViewInfo read GetDayNumberViewInfo;
property DayCaptions[Index: Byte]: TcxSchedulerDateNavigatorDayCaptionViewInfo read GetDayCaptionInfo;
property HorzSeparatorBound: TRect read FHorzSeparatorBound;
property Month: Integer read FMonth;
property Row: Integer read FRow;
property SelectedParams: TcxViewParams read FSelectedParams;
property Transparent: Boolean read FTransparent write FTransparent;
property VertSeparatorBound: TRect read FVertSeparatorBound;
property ViewParams: TcxViewParams read FViewParams;
property WeekCount: Integer read FWeekCount;
property WeekBounds[Index: Byte]: TRect read GetWeekBound;
property WeekTexts[Index: Byte]: string read GetWeekText write SetWeekText;
property Year: Integer read FYear;
end;
{ TcxSchedulerDateNavigatorMonthViewInfo }
TcxSchedulerDateNavigatorMonthViewInfo = class
private
FBounds: TRect;
FCol: Integer;
FRow: Integer;
FContent: TcxSchedulerDateNavigatorMonthContentViewInfo;
FHeader: TcxSchedulerDateNavigatorMonthHeaderViewInfo;
FMonth: Integer;
FOwner: TcxSchedulerDateNavigatorViewInfo;
FYear: Integer;
protected
procedure Calculate(ACol, ARow, AYear, AMonth: Integer); virtual;
function GetHeaderArrows: TcxHeaderArrows;
function GetHeaderNeighbors: TcxNeighbors;
property Owner: TcxSchedulerDateNavigatorViewInfo read FOwner;
public
constructor Create(AOwner: TcxSchedulerDateNavigatorViewInfo); virtual;
destructor Destroy; override;
property Bounds: TRect read FBounds;
property Col: Integer read FCol;
property Content: TcxSchedulerDateNavigatorMonthContentViewInfo read FContent;
property Header: TcxSchedulerDateNavigatorMonthHeaderViewInfo read FHeader;
property Month: Integer read FMonth;
property Row: Integer read FRow;
property Year: Integer read FYear;
end;
{ TcxSchedulerDateNavigatorViewInfo }
TcxSchedulerDateNavigatorViewInfo = class(TcxSchedulerSubControlViewInfo)
private
FCalendarBounds: TRect;
FColCount: Integer;
FColWidth: Integer;
FContentParams: TcxViewParams;
FDayCaptionsHeight: Integer;
FHeaderBorderSize: Integer;
FHeaderHeight: Integer;
FHeaderParams: TcxViewParams;
FMonthSize: TSize;
FMonthViewInfoList: TList;
FOwner: TcxSchedulerDateNavigator;
FRowCount: Integer;
FRowHeight: Integer;
FSelectedParams: TcxViewParams;
FSideWidth: Integer;
procedure DestroyMonthViewInfoList;
function GetMonthViewInfo(ACol, ARow: Integer): TcxSchedulerDateNavigatorMonthViewInfo;
protected
procedure DoCalculate; override;
procedure CalculateCalendarBounds;
procedure CalculateMonthViewInfos;
procedure CalculateViewParams;
procedure CheckMonthViewInfoCount;
function GetCol(X: Integer): Integer;
function GetHeaderRect(ACol, ARow: Integer): TRect;
function GetInternalRect(ACol, ARow: Integer): TRect;
function GetLeftArrowRect: TRect;
function GetMonthRect(ACol, ARow: Integer): TRect;
function GetRightArrowRect: TRect;
function GetRow(Y: Integer): Integer;
procedure CalcInternalSizes;
property CalendarBounds: TRect read FCalendarBounds;
property ColCount: Integer read FColCount;
property ColWidth: Integer read FColWidth;
property ContentParams: TcxViewParams read FContentParams;
property DayCaptionsHeight: Integer read FDayCaptionsHeight;
property HeaderBorderSize: Integer read FHeaderBorderSize;
property HeaderHeight: Integer read FHeaderHeight;
property HeaderParams: TcxViewParams read FHeaderParams;
property Owner: TcxSchedulerDateNavigator read FOwner;
property RowCount: Integer read FRowCount;
property RowHeight: Integer read FRowHeight;
property SelectedParams: TcxViewParams read FSelectedParams;
property SideWidth: Integer read FSideWidth;
public
constructor Create(AOwner: TcxSchedulerSubControl); override;
destructor Destroy; override;
property MonthSize: TSize read FMonthSize;
property MonthViewInfo[ACol, ARow: Integer]: TcxSchedulerDateNavigatorMonthViewInfo read GetMonthViewInfo;
end;
{ TcxSchedulerDateNavigatorStyles }
TcxSchedulerDateNavigatorStyles = class(TcxStyles)
private
function GetDateNavigator: TcxSchedulerDateNavigator;
protected
procedure Changed(AIndex: Integer); override;
procedure GetDefaultViewParams(Index: Integer; AData: TObject; out AParams: TcxViewParams); override;
public
constructor Create(AOwner: TPersistent); override;
procedure Assign(Source: TPersistent); override;
function GetBackgroundParams: TcxViewParams;
function GetContentParams: TcxViewParams;
function GetHeaderParams: TcxViewParams;
function GetSelectionParams: TcxViewParams;
property DateNavigator: TcxSchedulerDateNavigator read GetDateNavigator;
published
property Background: TcxStyle index cxdnBackground read GetValue write SetValue;
property Content: TcxStyle index cxdnContent read GetValue write SetValue;
property Header: TcxStyle index cxdnHeader read GetValue write SetValue;
property Selection: TcxStyle index cxdnSelection read GetValue write SetValue;
end;
{ TcxSchedulerDateNavigatorHitTest }
TcxSchedulerDateNavigatorHitTest = class(TcxSchedulerSubControlHitTest)
private
FMonthViewInfo: TcxSchedulerDateNavigatorMonthViewInfo;
function GetFirstWeekSelectableDate: TDateTime;
function GetOwner: TcxSchedulerDateNavigator;
function GetViewInfo: TcxSchedulerDateNavigatorViewInfo;
protected
procedure Clear; override;
procedure DoCalculate; override;
procedure CalcMonth; virtual;
function CheckDayCaptions: Boolean;
function CheckMonthHeader: Boolean;
function CheckWeekSelectionBar: Boolean;
property Owner: TcxSchedulerDateNavigator read GetOwner;
property ViewInfo: TcxSchedulerDateNavigatorViewInfo read GetViewInfo;
public
property HitAtCalendar: Boolean index htcCalendar read GetBitState;
property HitAtDayCaptions: Boolean index htcDayCaptions read GetBitState;
property HitAtMonthName: Boolean index htcMonthName read GetBitState;
property HitAtNextMonth: Boolean index htcNextMonth read GetBitState;
property HitAtPrevMonth: Boolean index htcPrevMonth read GetBitState;
property HitAtTime;
property HitAtWeekSelectionBar: Boolean index htcWeekSelectionBar read GetBitState;
property MonthViewInfo: TcxSchedulerDateNavigatorMonthViewInfo read FMonthViewInfo;
property Time;
end;
{ TcxSchedulerDateNavigatorController }
TcxSchedulerDateNavigatorController = class(TcxSchedulerSubControlController)
private
FDragDate: TDateTime;
FExtSelect: Boolean;
FIgnoreMouseMove: Boolean;
FSaveSelectionIsWeeks: Boolean;
FSaveSelectionList: TcxSchedulerDateList;
FSelFinish: TDateTime;
FSelStart: TDateTime;
FSingleSelection: Boolean;
FTimer: TTimer;
FUnselect: Boolean;
function GetHitTest: TcxSchedulerDateNavigatorHitTest;
function GetOwner: TcxSchedulerDateNavigator;
function GetViewInfo: TcxSchedulerDateNavigatorViewInfo;
procedure SetDragDate(const Value: TDateTime);
procedure StartTimer(AFuture: Boolean);
procedure StopTimer;
procedure TimerProc(Sender: TObject);
protected
//overriden
procedure DoCancelMode; override;
procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); override;
function GetCursor(X, Y: Integer): TCursor; override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure MouseLeave; override;
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
//methods
procedure CalculateSelection(AConcatenate: Boolean); virtual;
procedure ProcessSelectionOnMouseDown(AShift: TShiftState);
procedure ProcessSelectionOnMouseMove(AShift: TShiftState);
property HitTest: TcxSchedulerDateNavigatorHitTest read GetHitTest;
property Owner: TcxSchedulerDateNavigator read GetOwner;
property ViewInfo: TcxSchedulerDateNavigatorViewInfo read GetViewInfo;
public
constructor Create(AOwner: TcxSchedulerSubControl); override;
destructor Destroy; override;
property DragDate: TDateTime read FDragDate write SetDragDate;
end;
TcxSchedulerPeriodChangedEvent = procedure(Sender: TObject;
const AStart, AFinish: TDateTime) of object;
TcxSchedulerDateNavigatorCustomDrawBackgroundEvent = procedure (Sender: TObject;
ACanvas: TcxCanvas; const ABounds: TRect; var AViewParams: TcxViewParams;
var ADone: Boolean) of object;
TcxSchedulerDateNavigatorCustomDrawDayNumberEvent = procedure (Sender: TObject;
ACanvas: TcxCanvas; AViewInfo: TcxSchedulerDateNavigatorDayNumberViewInfo;
var ADone: Boolean) of object;
TcxSchedulerDateNavigatorCustomDrawDayCaptionEvent = procedure (Sender: TObject;
ACanvas: TcxCanvas; AViewInfo: TcxSchedulerDateNavigatorDayCaptionViewInfo;
var ADone: Boolean) of object;
TcxSchedulerDateNavigatorCustomDrawContentEvent = procedure (Sender: TObject;
ACanvas: TcxCanvas; AViewInfo: TcxSchedulerDateNavigatorMonthContentViewInfo;
var ADone: Boolean) of object;
TcxSchedulerDateNavigatorCustomDrawHeaderEvent = procedure (Sender: TObject;
ACanvas: TcxCanvas; AViewInfo: TcxSchedulerDateNavigatorMonthHeaderViewInfo;
var ADone: Boolean) of object;
TcxSchedulerDateNavigator = class(TcxSchedulerCustomDateNavigator)
private
FActualFirstWeekOfYear: TcxFirstWeekOfYear;
FColCount: Integer;
FFirstDate: TDateTime;
FFirstWeekOfYear: TcxFirstWeekOfYear;
FLastDate: TDateTime;
FListBox: TcxCustomPopupWindow;
FListBoxDelta: Integer;
FRealFirstDate: TDateTime;
FRealLastDate: TDateTime;
FRowCount: Integer;
FSelectionIsWeeks: Boolean;
FSelectPeriod: Boolean;
FShowDatesContainingEventsInBold: Boolean;
FShowWeekNumbers: Boolean;
FStyles: TcxSchedulerDateNavigatorStyles;
FToday: TDateTime;
// custom draw
FOnCustomDrawBackground: TcxSchedulerDateNavigatorCustomDrawBackgroundEvent;
FOnCustomDrawContent: TcxSchedulerDateNavigatorCustomDrawContentEvent;
FOnCustomDrawDayCaption: TcxSchedulerDateNavigatorCustomDrawDayCaptionEvent;
FOnCustomDrawDayNumber: TcxSchedulerDateNavigatorCustomDrawDayNumberEvent;
FOnCustomDrawHeader: TcxSchedulerDateNavigatorCustomDrawHeaderEvent;
FOnPeriodChanged: TcxSchedulerPeriodChangedEvent;
FOnSelectionChanged: TcxSchedulerPeriodChangedEvent;
function GetActualFirstWeekOfYear: TcxFirstWeekOfYear;
function GetController: TcxSchedulerDateNavigatorController;
function GetDate: TDateTime;
function GetHitTest: TcxSchedulerDateNavigatorHitTest;
function GetLastDate: TDateTime;
function GetViewInfo: TcxSchedulerDateNavigatorViewInfo;
procedure SetColCount(Value: Integer);
procedure SetDate(Value: TDateTime);
procedure SetFirstWeekOfYear(Value: TcxFirstWeekOfYear);
procedure SetRowCount(Value: Integer);
procedure SetSelectPeriod(Value: Boolean);
procedure SetShowDatesContainingEventsInBold(Value: Boolean);
procedure SetShowWeekNumbers(Value: Boolean);
procedure SetStyles(const Value: TcxSchedulerDateNavigatorStyles);
protected
IsLocked: Boolean;
// 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;
//
function AllowDesignHitTest(X, Y: Integer; Shift: TShiftState): Boolean; override;
procedure CheckSizes; override;
procedure CreateSubClasses; override;
function CreateController: TcxSchedulerSubControlController; override;
function CreateHitTest: TcxSchedulerSubControlHitTest; override;
function CreatePainter: TcxSchedulerSubControlPainter; override;
function CreateViewInfo: TcxSchedulerSubControlViewInfo; override;
procedure DestroySubClasses; override;
procedure DoLayoutChanged; override;
//methods
function CanDrawSelectionSide: Boolean;
procedure CheckSelectionBounds; virtual;
procedure DoSelectionChanged; virtual;
procedure DoPeriodChangedEvent; override;
procedure DoSelectionChangedEvent; override;
procedure DoScrollSelection(AScrollDelta: Integer); override;
procedure DoScrollSelection(AForward: Boolean;
ANeedDate: TDateTime; AIsByPage: Boolean); override;
procedure EnsureSelectionVisible;
function IsDateSelected(ADate: TDateTime): Boolean; virtual;
function IsDateHasEvent(ADate: TDateTime): Boolean; virtual;
procedure FormatChanged; override;
function GetMonthSize: TSize; override;
function GetRealFirstDate: TDateTime; override;
function GetRealLastDate: TDateTime; override;
function GetShowDatesContainingEventsInBold: Boolean; override;
procedure RefreshDays;
procedure SetFirstDate(Value: TDateTime); virtual;
procedure ShowMonthPopup(AMonthInfo: TcxSchedulerDateNavigatorMonthViewInfo); virtual;
procedure StepToPast;
procedure StepToFuture;
procedure UpdateCalculatedValues; virtual;
procedure UpdateDragging; override;
procedure UpdateSelection; override;
// support custom draw
procedure AfterCustomDraw(ACanvas: TcxCanvas; var AParams: TcxViewParams); virtual;
procedure BeforeCustomDraw(ACanvas: TcxCanvas; const AParams: TcxViewParams); virtual;
function DoCustomDrawBackground(ACanvas: TcxCanvas;
const ABounds: TRect; var AViewParams: TcxViewParams): Boolean; virtual;
function DoCustomDrawDayNumber(ACanvas: TcxCanvas;
ADayInfo: TcxSchedulerDateNavigatorDayNumberViewInfo): Boolean; virtual;
function DoCustomDrawDayCaption(ACanvas: TcxCanvas;
ADayCaptionInfo: TcxSchedulerDateNavigatorDayCaptionViewInfo): Boolean; virtual;
function DoCustomDrawContent(ACanvas: TcxCanvas;
AViewInfo: TcxSchedulerDateNavigatorMonthContentViewInfo): Boolean; virtual;
function DoCustomDrawHeader(ACanvas: TcxCanvas;
AViewInfo: TcxSchedulerDateNavigatorMonthHeaderViewInfo): Boolean; virtual;
property Controller: TcxSchedulerDateNavigatorController read GetController;
property ViewInfo: TcxSchedulerDateNavigatorViewInfo read GetViewInfo;
public
constructor Create(AOwner: TcxCustomScheduler); override;
procedure SetIntegralSizes; override;
property ActualFirstWeekOfYear: TcxFirstWeekOfYear read FActualFirstWeekOfYear;
property Date: TDateTime read GetDate write SetDate;
property FirstDate: TDateTime read FFirstDate write SetFirstDate;
property HitTest: TcxSchedulerDateNavigatorHitTest read GetHitTest;
property LastDate: TDateTime read FLastDate;
property RealFirstDate: TDateTime read FRealFirstDate;
property RealLastDate: TDateTime read FRealLastDate;
property SelectionIsWeeks: Boolean read FSelectionIsWeeks write FSelectionIsWeeks;
property SelectionList: TcxSchedulerDateList read GetSelection;
property SelectPeriod: Boolean read FSelectPeriod write SetSelectPeriod;
published
property ColCount: Integer read FColCount write SetColCount default 1;
property FirstWeekOfYear: TcxFirstWeekOfYear
read FFirstWeekOfYear write SetFirstWeekOfYear default fwySystem;
property RowCount: Integer read FRowCount write SetRowCount default 1;
property ShowDatesContainingEventsInBold: Boolean
read FShowDatesContainingEventsInBold write SetShowDatesContainingEventsInBold default True;
property ShowWeekNumbers: Boolean read FShowWeekNumbers write SetShowWeekNumbers default True;
property Styles: TcxSchedulerDateNavigatorStyles read FStyles write SetStyles;
property Visible default True;
property OnCustomDrawBackground: TcxSchedulerDateNavigatorCustomDrawBackgroundEvent
read FOnCustomDrawBackground write FOnCustomDrawBackground;
property OnCustomDrawDayCaption: TcxSchedulerDateNavigatorCustomDrawDayCaptionEvent
read FOnCustomDrawDayCaption write FOnCustomDrawDayCaption;
property OnCustomDrawDayNumber: TcxSchedulerDateNavigatorCustomDrawDayNumberEvent
read FOnCustomDrawDayNumber write FOnCustomDrawDayNumber;
property OnCustomDrawContent: TcxSchedulerDateNavigatorCustomDrawContentEvent
read FOnCustomDrawContent write FOnCustomDrawContent;
property OnCustomDrawHeader: TcxSchedulerDateNavigatorCustomDrawHeaderEvent
read FOnCustomDrawHeader write FOnCustomDrawHeader;
property OnPeriodChanged: TcxSchedulerPeriodChangedEvent read FOnPeriodChanged
write FOnPeriodChanged;
property OnSelectionChanged: TcxSchedulerPeriodChangedEvent read FOnSelectionChanged
write FOnSelectionChanged;
end;
implementation
uses
{$IFDEF DELPHI6}
DateUtils,
{$ENDIF}
cxGeometry, Forms, cxFormats, cxLibraryConsts;
const
cxDateStartNavigatorTime = 400;
cxDateNavigatorTime = 200;
cxdnTextFlags = cxSingleLine + cxAlignVCenter + cxAlignRight;
var
DayNames: array[1..7] of string;
procedure GetLocaleSettings;
var
I: Integer;
begin
for I := 1 to 7 do
DayNames[I] := ShortDayNames[I][1];
end;
function Max(A, B: Integer): Integer;
begin
if A > B then Result := A else Result := B;
end;
function Min(A, B: Integer): Integer;
begin
if A < B then Result := A else Result := B;
end;
procedure DecMonth(var AYear, AMonth: Word);
begin
if AMonth = 1 then
begin
Dec(AYear);
AMonth := 12;
end
else Dec(AMonth);
end;
procedure IncMonth(var AYear, AMonth: Word);
begin
if AMonth = 12 then
begin
Inc(AYear);
AMonth := 1;
end
else Inc(AMonth);
end;
procedure ChangeMonth(var AYear, AMonth: Word; Delta: Integer);
var
Month: Integer;
begin
Inc(AYear, Delta div 12);
Month := AMonth;
Inc(Month, Delta mod 12);
if Month < 1 then
begin
Dec(AYear);
Month := 12 + Month;
end;
if Month > 12 then
begin
Inc(AYear);
Month := Month - 12;
end;
AMonth := Month;
end;
function GetDateElement(ADate: TDateTime; Index: Integer): Integer;
var
AYear, AMonth, ADay: Word;
begin
DecodeDate(ADate, AYear, AMonth, ADay);
case Index of
1: Result := AYear;
2: Result := AMonth;
3: Result := ADay;
else Result := -1;
end;
end;
function DaysPerMonth(AYear, AMonth: Integer): Integer;
const
DaysInMonth: array[1..12] of Integer =
(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
begin
Result := DaysInMonth[AMonth];
if (AMonth = 2) and IsLeapYear(AYear) then Inc(Result);
end;
function CheckDay(AYear, AMonth, ADay: Integer): Integer;
begin
if ADay < 1 then Result := 1
else
if ADay > DaysPerMonth(AYear, AMonth) then
Result := DaysPerMonth(AYear, AMonth)
else Result := ADay;
end;
function ColOfDate(ADate: TDateTime; StartOfWeek: TcxDayOfWeek): Integer;
begin
Result := DayOfWeek(ADate) - StartOfWeek - 1;
if Result < 0 then Inc(Result, 7);
end;
type
{ TcxSchedulerMonthListBox }
TcxSchedulerMonthListBox = class(TcxCustomPopupWindow)
private
FOwner: TcxSchedulerDateNavigator;
FOrigin: TPoint;
FTopDate: TDateTime;
FItemHeight: Integer;
FItemIndex: Integer;
FItems: TStrings;
FTimer: TTimer;
FSign: Integer;
function GetDate: TDateTime;
function GetViewInfo: TcxSchedulerDateNavigatorViewInfo;
procedure SetItemIndex(Value: Integer);
procedure SetTopDate(Value: TDateTime);
procedure DoTimer(Sender: TObject);
protected
function CalculatePosition: TPoint; override;
procedure CreateParams(var Params: TCreateParams); override;
procedure DoShowed; override;
procedure FontChanged;
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
procedure Paint; override;
property ItemHeight: Integer read FItemHeight;
property ItemIndex: Integer read FItemIndex write SetItemIndex;
property Items: TStrings read FItems;
property Owner: TcxSchedulerDateNavigator read FOwner;
property TopDate: TDateTime read FTopDate write SetTopDate;
property ViewInfo: TcxSchedulerDateNavigatorViewInfo read GetViewInfo;
public
procedure BeforeDestruction; override;
constructor Create(AOwner: TcxSchedulerDateNavigator); reintroduce;
procedure CloseUp; override;
procedure SetupMonth(R: TRect; ADate: TDateTime);
property Date: TDateTime read GetDate;
end;
function GetDesktopRect: TRect;
begin
{$IFDEF DELPHI6}
Result := Screen.DesktopRect;
{$ELSE}
with Result do
begin
Top := GetSystemMetrics(SM_YVIRTUALSCREEN);
Left := GetSystemMetrics(SM_XVIRTUALSCREEN);
Bottom := Top + GetSystemMetrics(SM_CYVIRTUALSCREEN);
Right := Left + GetSystemMetrics(SM_CXVIRTUALSCREEN);
end;
{$ENDIF}
end;
constructor TcxSchedulerMonthListBox.Create(AOwner: TcxSchedulerDateNavigator);
begin
inherited Create(AOwner.Scheduler);
OwnerParent := AOwner.Scheduler.Parent;
FOwner := AOwner;
IsTopMost := True;
CaptureFocus := False;
ControlStyle := [csCaptureMouse, csOpaque];
FTopDate := NullDate;
FTimer := TTimer.Create(nil);
FTimer.Enabled := False;
FTimer.Interval := 200;
FTimer.OnTimer := DoTimer;
Adjustable := False;
BorderStyle := pbsFlat;
end;
procedure TcxSchedulerMonthListBox.BeforeDestruction;
begin
FTimer.Free;
FTimer := nil;
inherited BeforeDestruction;
end;
procedure TcxSchedulerMonthListBox.CloseUp;
var
ADate: TDateTime;
AYear, AMonth, ADay: Word;
begin
FTimer.Enabled := False;
if GetCaptureControl = Self then SetCaptureControl(nil);
inherited CloseUp;
ADate := GetDate;
with Owner do
begin
if ADate <> NullDate then
begin
DecodeDate(ADate, AYear, AMonth, ADay);
ChangeMonth(AYear, AMonth, -FListBoxDelta);
FirstDate := EncodeDate(AYear, AMonth, 1);
end;
Controller.DoCancelMode;
end;
Owner.EndUpdate;
end;
procedure TcxSchedulerMonthListBox.SetupMonth(R: TRect; ADate: TDateTime);
begin
Font.Assign(ViewInfo.ContentParams.Font);
FontChanged;
R.TopLeft := Owner.Scheduler.ClientToScreen(R.TopLeft);
R.BottomRight := Owner.Scheduler.ClientToScreen(R.BottomRight);
R := cxRectOffset(R, Owner.Bounds.TopLeft);
TopDate := ADate;
FOrigin.X := Max(GetDesktopRect.Left,
(R.Left + R.Right) div 2 - Width div 2);
FOrigin.Y := Max(GetDesktopRect.Top,
(R.Top + R.Bottom) div 2 - Height div 2);
FItemIndex := 3;
end;
function TcxSchedulerMonthListBox.GetDate: TDateTime;
var
Year, Month, Day: Word;
begin
if ItemIndex = -1 then
Result := NullDate
else
begin
DecodeDate(TopDate, Year, Month, Day);
ChangeMonth(Year, Month, ItemIndex);
Result := EncodeDate(Year, Month, 1);
end;
end;
function TcxSchedulerMonthListBox.GetViewInfo: TcxSchedulerDateNavigatorViewInfo;
begin
Result := Owner.ViewInfo;
end;
procedure TcxSchedulerMonthListBox.SetItemIndex(Value: Integer);
var
PrevItemIndex: Integer;
procedure InvalidateItemRect(Index: Integer);
var
R: TRect;
begin
if Index = -1 then Exit;
with R do
begin
Left := BorderWidths[bLeft];
Top := Index * ItemHeight + BorderWidths[bTop];
Right := Width - BorderWidths[bRight];
Bottom := Top + ItemHeight;
end;
InvalidateRect(Handle, @R, False);
end;
begin
if not HandleAllocated then Exit;
if FItemIndex <> Value then
begin
PrevItemIndex := FItemIndex;
FItemIndex := Value;
InvalidateItemRect(PrevItemIndex);
InvalidateItemRect(FItemIndex);
end;
end;
procedure TcxSchedulerMonthListBox.SetTopDate(Value: TDateTime);
begin
if FTopDate <> Value then
begin
FTopDate := Value;
Repaint;
end;
end;
procedure TcxSchedulerMonthListBox.DoTimer(Sender: TObject);
var
Year, Month, Day: Word;
begin
DecodeDate(TopDate, Year, Month, Day);
ChangeMonth(Year, Month, FSign);
TopDate := EncodeDate(Year, Month, 1);
end;
function TcxSchedulerMonthListBox.CalculatePosition: TPoint;
begin
Result.X := Min(cxRectWidth(GetDesktopRect) - Width, FOrigin.X);
Result.Y := Min(cxRectHeight(GetDesktopRect) - Height, FOrigin.Y);
end;
procedure TcxSchedulerMonthListBox.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
with Params do
WindowClass.Style := WindowClass.Style or CS_SAVEBITS;
end;
procedure TcxSchedulerMonthListBox.DoShowed;
begin
SetCaptureControl(Self);
end;
procedure TcxSchedulerMonthListBox.FontChanged;
begin
Canvas.Font.Assign(Font);
FItemHeight := ViewInfo.HeaderHeight - 2;
SetBounds(Left, Top,
BorderWidths[bLeft] + BorderWidths[bRight] + 6 * ViewInfo.ColWidth,
BorderWidths[bTop] + BorderWidths[bBottom] + 7 * FItemHeight);
end;
procedure TcxSchedulerMonthListBox.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
CloseUp;
inherited MouseUp(Button, Shift, X, Y);
end;
procedure TcxSchedulerMonthListBox.MouseMove(Shift: TShiftState; X, Y: Integer);
const
Times: array[0..3] of UINT = (500, 250, 100, 50);
var
Delta: Integer;
Interval: Integer;
begin
if cxRectPtIn(ClientRect, X, Y) then
begin
FTimer.Enabled := False;
ItemIndex := Y div ItemHeight;
end
else
begin
ItemIndex := -1;
if Y < 0 then Delta := Y
else
if Y >= ClientHeight then
Delta := 1 + Y - ClientHeight
else
begin
FTimer.Enabled := False;
Exit;
end;
FSign := Delta div Abs(Delta);
Interval := Abs(Delta) div ItemHeight;
if Interval > 3 then Interval := 3;
if not FTimer.Enabled or (Times[Interval] <> FTimer.Interval) then
begin
FTimer.Interval := Times[Interval];
FTimer.Enabled := True;
end;
end;
end;
procedure TcxSchedulerMonthListBox.Paint;
const
Colors: array[Boolean] of TColor = (clWindow, clWindowText);
var
I: Integer;
Year, Month, Day: Word;
R: TRect;
S: string;
begin
Canvas.FrameRect(ClientRect, clBlack);
DecodeDate(TopDate, Year, Month, Day);
with R do
begin
Left := BorderWidths[bLeft];
Top := BorderWidths[bTop];
Right := Width - BorderWidths[bRight];
Bottom := Top + ItemHeight;
end;
for I := 0 to 6 do
begin
with Canvas do
begin
if I = ItemIndex then
begin
Font.Color := ViewInfo.SelectedParams.TextColor;
Brush.Color := ViewInfo.SelectedParams.Color;
FillRect(R);
end
else
begin
Font.Color := ViewInfo.ContentParams.TextColor;
FillRect(R, ViewInfo.ContentParams);
end;
S := Owner.DateTimeHelper.MonthYearToStr(Month, Year);
Canvas.Brush.Style := bsClear;
Inc(R.Right); // synchronize with header
DrawText(S, R, cxAlignCenter or cxSingleLine, True);
Dec(R.Right);
Canvas.Brush.Style := bsSolid;
end;
IncMonth(Year, Month);
OffsetRect(R, 0, ItemHeight);
end;
end;
{ TcxSchedulerDateNavigatorController }
constructor TcxSchedulerDateNavigatorController.Create(AOwner: TcxSchedulerSubControl);
begin
inherited Create(AOwner);
FSaveSelectionList := TcxSchedulerDateList.Create;
end;
destructor TcxSchedulerDateNavigatorController.Destroy;
begin
StopTimer;
FSaveSelectionList.Free;
inherited Destroy;
end;
procedure TcxSchedulerDateNavigatorController.DoCancelMode;
begin
StopTimer;
FIgnoreMouseMove := False;
FSingleSelection := False;
FDragDate := NullDate;
Screen.Cursor := crDefault;
Owner.RefreshDays;
end;
procedure TcxSchedulerDateNavigatorController.DragOver(
Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
begin
Accept := Accept and HitTest.HitAtTime;
end;
function TcxSchedulerDateNavigatorController.GetCursor(X, Y: Integer): TCursor;
begin
if Owner.SelectPeriod and HitTest.HitAtWeekSelectionBar then
Result := crCalendarMirrorArrow
else
Result := crDefault;
end;
procedure TcxSchedulerDateNavigatorController.MouseDown(
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure ProcessHeader;
begin
with HitTest do
begin
if HitAtPrevMonth then
begin
Owner.StepToPast;
StartTimer(False);
end
else if HitAtNextMonth then
begin
Owner.StepToFuture;
StartTimer(True);
end
else if HitAtMonthName then
Owner.ShowMonthPopup(MonthViewInfo);
end;
end;
begin
FIgnoreMouseMove := False;
FSingleSelection := False;
FSaveSelectionIsWeeks := False;
if Button = mbLeft then
begin
Owner.CancelUpdates; // for a possible changed capture
Owner.BeginUpdate;
FExtSelect := Owner.SelectPeriod and (ssCtrl in Shift);
FUnselect := FExtSelect;
FSaveSelectionList.Assign(Owner.SelectionList);
if not (ssDouble in Shift) then
ProcessSelectionOnMouseDown(Shift);
ProcessHeader;
end;
end;
procedure TcxSchedulerDateNavigatorController.MouseLeave;
begin
inherited MouseLeave;
DoCancelMode;
end;
procedure TcxSchedulerDateNavigatorController.MouseMove(
Shift: TShiftState; X, Y: Integer);
begin
if FIgnoreMouseMove or (FTimer <> nil) then Exit;
if (ssLeft in Shift) and (GetCaptureControl = Owner.Scheduler) then
ProcessSelectionOnMouseMove(Shift);
end;
procedure TcxSchedulerDateNavigatorController.MouseUp(
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
DoCancelMode;
if Button = mbLeft then
begin
if (Owner.SelectionList.Count > 0) and
cxRectPtIn(ViewInfo.GetInternalRect(ViewInfo.GetCol(X), ViewInfo.GetRow(Y)), X, Y) then
begin
if Owner.SelectionList[Owner.SelectionList.Count - 1] < Owner.FirstDate then
Owner.StepToPast;
if Owner.SelectionList[0] > Owner.LastDate then
Owner.StepToFuture;
end;
Owner.DoSelectionChanged;
Owner.EndUpdate;
end;
end;
procedure TcxSchedulerDateNavigatorController.CalculateSelection(AConcatenate: Boolean);
procedure GetBoundParameters(out AStart, AFinish, AMax, AMin: Integer);
begin
//DELPHI8! check Trunc()
AStart := Trunc(FSelStart);
AFinish := Trunc(FSelFinish);
if Owner.SelectionIsWeeks then
begin
if AStart < AFinish then
begin
Dec(AStart, ColOfDate(AStart, Byte(StartOfWeek)));
Inc(AFinish, 6 - ColOfDate(AFinish, Byte(StartOfWeek)));
end
else
begin
Dec(AFinish, ColOfDate(AFinish, Byte(StartOfWeek)));
Inc(AStart, 6 - ColOfDate(AStart, Byte(StartOfWeek)));
end;
AMax := cxMaxWeekCount * 7;
AMin := 7;
end
else
begin
AMax := 14;
AMin := 1;
end;
end;
var
AIndex, ADelta, AStart, AFinish, AMax, AMin: Integer;
begin
GetBoundParameters(AStart, AFinish, AMax, AMin);
if FUnselect and (Owner.SelectionList.Count <= AMin) then Exit;
Owner.SelectionList.Clear;
if AConcatenate then Owner.SelectionList.Assign(FSaveSelectionList);
ADelta := 2 * Byte(AStart < AFinish) - 1;
while (AStart <> AFinish + ADelta) do
begin
AIndex := Owner.SelectionList.IndexOf(AStart);
if AIndex < 0 then
begin
if not FUnselect and (Owner.SelectionList.Count < AMax) then
Owner.SelectionList.Add(AStart);
end
else
if FUnselect and (Owner.SelectionList.Count > AMin) then
Owner.SelectionList.Delete(AIndex);
Inc(AStart, ADelta);
end;
Owner.RefreshDays;
end;
procedure TcxSchedulerDateNavigatorController.ProcessSelectionOnMouseDown(
AShift: TShiftState);
procedure SelectDate(ADate: TDateTime);
begin
with Owner.SelectionList do
begin
if (ExistDate(ADate) and FUnselect and (Count = 1)) or
(FExtSelect and (Count > 14)) then
begin
FIgnoreMouseMove := True;
Exit;
end;
end;
FSelStart := ADate;
FSelFinish := ADate;
Owner.SelectionIsWeeks := False;
CalculateSelection(FExtSelect);
end;
procedure SelectWeek(ADate: TDateTime);
begin
if not Owner.SelectPeriod or (Owner.SelectionIsWeeks and FUnselect and
(Owner.SelectionList.Count = 7)) then Exit;
if not Owner.SelectionIsWeeks then
begin
FUnselect := False;
Owner.SelectionList.Clear;
end;
FSaveSelectionIsWeeks := Owner.SelectionIsWeeks;
FSelStart := ADate;
FSelFinish := FSelStart + 6;
CalculateSelection(FExtSelect and Owner.SelectionIsWeeks);
Owner.SelectionIsWeeks := True;
end;
var
ADate: TDateTime;
begin
ADate := HitTest.Time;
if ADate = NullDate then Exit;
FUnselect := FUnselect and Owner.SelectionList.ExistDate(ADate);
if Owner.SelectPeriod and (ssShift in AShift) then
begin
FSelStart := Owner.SelectionList[0];
FSelFinish := ADate;
Owner.SelectionIsWeeks := HitTest.HitAtWeekSelectionBar or (Owner.SelectionList.Count > 14);
CalculateSelection(not Owner.SelectionIsWeeks);
end
else
if HitTest.HitAtTime then
SelectDate(ADate)
else if HitTest.HitAtWeekSelectionBar then
SelectWeek(ADate)
else if HitTest.HitAtControl and not HitTest.HitAtCalendar then
begin
FSingleSelection := True;
SelectDate(ADate);
end;
if not (ssLeft in AShift) then
Owner.DoSelectionChanged;
end;
procedure TcxSchedulerDateNavigatorController.ProcessSelectionOnMouseMove(
AShift: TShiftState);
procedure ProcessDate(ADate: TDateTime);
begin
if FSingleSelection then
begin
FSelStart := ADate;
FSelFinish := ADate;
CalculateSelection(FExtSelect);
end
else
if ADate <> FSelFinish then
begin
FSelFinish := ADate;
if not Owner.SelectPeriod then FSelStart := FSelFinish;
//DELPHI8! check Trunc()
if not FExtSelect and
(Abs(Trunc(FSelStart) - Trunc(ADate)) + 1 > cxDaysCalendarMaxColCount) then
Owner.SelectionIsWeeks := True;
CalculateSelection(FExtSelect and not Owner.SelectionIsWeeks);
end;
end;
procedure ProcessWeek(ADate: TDateTime);
begin
if Owner.SelectionIsWeeks and Owner.SelectPeriod and (ADate <> FSelFinish) then
begin
FSelFinish := ADate;
CalculateSelection(FExtSelect and FSaveSelectionIsWeeks);
end;
end;
begin
if not HitTest.HitAtControl then
begin
FSelFinish := NullDate;
Owner.SelectionList.Assign(FSaveSelectionList);
Owner.RefreshDays;
end
else if HitTest.HitAtTime then
ProcessDate(HitTest.Time)
else if HitTest.HitAtWeekSelectionBar then
ProcessWeek(HitTest.Time);
end;
function TcxSchedulerDateNavigatorController.GetHitTest: TcxSchedulerDateNavigatorHitTest;
begin
Result := TcxSchedulerDateNavigatorHitTest(inherited HitTest);
end;
function TcxSchedulerDateNavigatorController.GetOwner: TcxSchedulerDateNavigator;
begin
Result := TcxSchedulerDateNavigator(inherited Owner);
end;
function TcxSchedulerDateNavigatorController.GetViewInfo: TcxSchedulerDateNavigatorViewInfo;
begin
Result := Owner.ViewInfo;
end;
procedure TcxSchedulerDateNavigatorController.SetDragDate(const Value: TDateTime);
begin
if FDragDate <> Value then
begin
FDragDate := Value;
Owner.Invalidate;
//Owner.RefreshDays;
end;
end;
procedure TcxSchedulerDateNavigatorController.StartTimer(AFuture: Boolean);
begin
if Assigned(FTimer) then Exit;
FTimer := TTimer.Create(nil);
FTimer.Interval := cxDateStartNavigatorTime;
FTimer.Tag := Ord(AFuture);
FTimer.OnTimer := TimerProc;
end;
procedure TcxSchedulerDateNavigatorController.StopTimer;
begin
FreeAndNil(FTimer);
end;
procedure TcxSchedulerDateNavigatorController.TimerProc(Sender: TObject);
var
P: TPoint;
begin
GetCursorPos(P);
HitTest.HitPoint := Owner.Scheduler.ScreenToClient(P);
case TTimer(Sender).Tag of
0: if HitTest.HitAtPrevMonth then
Owner.StepToPast;
else
if HitTest.HitAtNextMonth then
Owner.StepToFuture;
end;
FTimer.Interval := cxDateNavigatorTime;
end;
{ TcxSchedulerDateNavigator }
constructor TcxSchedulerDateNavigator.Create(AOwner: TcxCustomScheduler);
var
AYear, AMonth, ADay: Word;
begin
inherited Create(AOwner);
FRealFirstDate := NullDate;
FRealLastDate := NullDate;
FToday := SysUtils.Date;
DecodeDate(FToday, AYear, AMonth, ADay);
FFirstDate := EncodeDate(AYear, AMonth, 1);
FFirstWeekOfYear := fwySystem;
FActualFirstWeekOfYear := GetActualFirstWeekOfYear;
FShowDatesContainingEventsInBold := True;
FSelectPeriod := True;
FColCount := 1;
FRowCount := 1;
FShowWeekNumbers := True;
UpdateCalculatedValues;
end;
procedure TcxSchedulerDateNavigator.SetIntegralSizes;
begin
ViewInfo.CalcInternalSizes;
SetBounds(Left, Top,
ColCount * ViewInfo.MonthSize.cx,
RowCount * ViewInfo.MonthSize.cy);
end;
procedure TcxSchedulerDateNavigator.GetProperties(AProperties: TStrings);
begin
if not Visible then Exit;
with AProperties do
begin
if Scheduler.OptionsCustomize.IntegralSizing then
begin
Add('DNColCount');
Add('DNRowCount');
end
else
begin
Add('DNWidth');
Add('DNHeight');
end;
end;
end;
procedure TcxSchedulerDateNavigator.GetPropertyValue(const AName: string;
var AValue: Variant);
begin
if not Visible then Exit;
if AName = 'DNColCount' then
AValue := ColCount
else
if AName = 'DNRowCount' then
AValue := RowCount
else
if AName = 'DNWidth' then
AValue := Width
else
if AName = 'DNHeight' then
AValue := Height
end;
procedure TcxSchedulerDateNavigator.SetPropertyValue(const AName: string;
const AValue: Variant);
begin
if not Visible then Exit;
if Scheduler.OptionsCustomize.IntegralSizing then
begin
if AName = 'DNColCount' then
ColCount := AValue
else
if AName = 'DNRowCount' then
RowCount := AValue
end
else
begin
if AName = 'DNWidth' then
Width := AValue
else
if AName = 'DNHeight' then
Height := AValue;
end;
end;
function TcxSchedulerDateNavigator.AllowDesignHitTest(X, Y: Integer;
Shift: TShiftState): Boolean;
begin
inherited AllowDesignHitTest(X, Y, Shift);
Result := HitTest.HitAtCalendar;
if Result then
begin
Result := HitTest.HitAtTime or HitTest.HitAtWeekSelectionBar or
HitTest.HitAtMonthName or HitTest.HitAtNextMonth or HitTest.HitAtPrevMonth;
end;
end;
procedure TcxSchedulerDateNavigator.CheckSizes;
begin
if Scheduler.OptionsCustomize.IntegralSizing then
SetIntegralSizes
else
begin
ViewInfo.CalcInternalSizes;
SetBounds(Left, Top,
Max(ViewInfo.MonthSize.cx, FSavedSize.cx),
Max(ViewInfo.MonthSize.cy, FSavedSize.cy));
end;
end;
procedure TcxSchedulerDateNavigator.CreateSubClasses;
begin
inherited CreateSubClasses;
FStyles := TcxSchedulerDateNavigatorStyles.Create(Self);
FListBox := TcxSchedulerMonthListBox.Create(Self);
end;
function TcxSchedulerDateNavigator.CreateController: TcxSchedulerSubControlController;
begin
Result := TcxSchedulerDateNavigatorController.Create(Self);
end;
function TcxSchedulerDateNavigator.CreateHitTest: TcxSchedulerSubControlHitTest;
begin
Result := TcxSchedulerDateNavigatorHitTest.Create(Self);
end;
function TcxSchedulerDateNavigator.CreatePainter: TcxSchedulerSubControlPainter;
begin
Result := TcxSchedulerDateNavigatorPainter.Create(Self);
end;
function TcxSchedulerDateNavigator.CreateViewInfo: TcxSchedulerSubControlViewInfo;
begin
Result := TcxSchedulerDateNavigatorViewInfo.Create(Self);
end;
procedure TcxSchedulerDateNavigator.DestroySubClasses;
begin
FreeAndNil(FStyles);
inherited DestroySubClasses;
FreeAndNil(FListBox);
end;
procedure TcxSchedulerDateNavigator.DoLayoutChanged;
begin
BeginUpdate;
try
UpdateCalculatedValues;
ViewInfo.Calculate;
FRowCount := ViewInfo.RowCount;
FColCount := ViewInfo.ColCount;
finally
EndUpdate;
end;
end;
function TcxSchedulerDateNavigator.CanDrawSelectionSide: Boolean;
begin
Result := not ShowWeekNumbers and SelectionIsWeeks;
end;
procedure TcxSchedulerDateNavigator.CheckSelectionBounds;
var
ASelectionCount: Integer;
AFirstSelectedDate: TDateTime;
procedure ShiftSelection(AForward: Boolean);
var
ADate: TDateTime;
AYear, AMonth, ADay: Word;
I: Integer;
begin
if AForward then ADate := LastDate else ADate := FirstDate;
DecodeDate(ADate, AYear, AMonth, ADay);
if SelectionIsWeeks then
ADate := ADate - ColOfDate(ADate, Byte(StartOfWeek))
else
ADate := EncodeDate(AYear, AMonth,
CheckDay(AYear, AMonth, GetDateElement(AFirstSelectedDate, 3)));
SelectionList.Clear;
for I := 0 to ASelectionCount - 1 do
begin
SelectionList.Add(ADate);
ADate := ADate + 1;
end;
end;
begin
ASelectionCount := SelectionList.Count;
if ASelectionCount > 0 then
begin
AFirstSelectedDate := SelectionList[0];
if (AFirstSelectedDate < FirstDate) then
ShiftSelection(False)
else
if AFirstSelectedDate > LastDate then
ShiftSelection(True);
end;
end;
procedure TcxSchedulerDateNavigator.DoSelectionChanged;
begin
if IsLocked then Exit;
IsLocked := True;
try
SelectionList.Changed := False;
PeriodChanged;
finally
IsLocked := False;
end;
end;
procedure TcxSchedulerDateNavigator.DoPeriodChangedEvent;
begin
if Assigned(FOnPeriodChanged) then
FOnPeriodChanged(Self, RealFirstDate, RealLastDate);
end;
procedure TcxSchedulerDateNavigator.DoSelectionChangedEvent;
begin
if Assigned(FOnSelectionChanged) then
FOnSelectionChanged(Self, SelectionList[0], SelectionList[SelectionList.Count - 1]);
end;
procedure TcxSchedulerDateNavigator.DoScrollSelection(AScrollDelta: Integer);
begin
if AScrollDelta = 0 then Exit;
IsLocked := True;
try
while AScrollDelta <> 0 do
begin
ScrollSelection(AScrollDelta < 0, NullDate, False);
Inc(AScrollDelta, Byte(AScrollDelta < 0) * 2 - 1);
end;
finally
IsLocked := False;
DoSelectionChanged;
end;
end;
procedure TcxSchedulerDateNavigator.DoScrollSelection(AForward: Boolean;
ANeedDate: TDateTime; AIsByPage: Boolean);
procedure ScrollWeeks;
var
I, J, ANumPass: Integer;
ADate: TDateTime;
begin
if AIsByPage then
ANumPass := SelectionList.Count div 7
else
ANumPass := 1;
for J := 1 to ANumPass do
if AForward then
begin
ADate := SelectionList[SelectionList.Count - 1] + 1;
for I := 0 to 6 do
begin
SelectionList.Add(ADate + I);
SelectionList.Delete(0);
end
end
else
begin
ADate := SelectionList[0] - 7;
for I := 0 to 6 do
begin
SelectionList.Add(ADate + I);
SelectionList.Delete(SelectionList.Count - 1);
end;
end;
end;
procedure ScrollDays;
begin
if AForward then
begin
SelectionList.Add(SelectionList[SelectionList.Count - 1] + 1);
SelectionList.Delete(0);
end
else
begin
SelectionList.Add(SelectionList[0] - 1);
SelectionList.Delete(SelectionList.Count - 1);
end;
end;
begin
if (SelectionList.Count = 0) or SelectionList.ExistDate(ANeedDate) then Exit;
if SelectionIsWeeks then
ScrollWeeks
else
ScrollDays;
EnsureSelectionVisible;
end;
procedure TcxSchedulerDateNavigator.EnsureSelectionVisible;
var
AMinDate, AMaxDate: TDateTime;
begin
if SelectionList.Count = 0 then Exit;
if SelectionIsWeeks then
begin
AMinDate := RealFirstDate;
AMaxDate := RealLastDate;
end
else
begin
AMinDate := FirstDate;
AMaxDate := LastDate;
end;
if SelectionList[0] > AMaxDate then
FirstDate := RealLastDate
else
if SelectionList[0] < AMinDate then
FirstDate := RealFirstDate
else
DoSelectionChanged;
end;
function TcxSchedulerDateNavigator.IsDateSelected(ADate: TDateTime): Boolean;
begin
Result := SelectionList.ExistDate(ADate);
end;
function TcxSchedulerDateNavigator.IsDateHasEvent(ADate: TDateTime): Boolean;
begin
Result := ShowDatesContainingEventsInBold and EventDays.ExistDate(ADate);
end;
procedure TcxSchedulerDateNavigator.FormatChanged;
begin
FActualFirstWeekOfYear := GetActualFirstWeekOfYear;
GetLocaleSettings;
RefreshDays;
end;
function TcxSchedulerDateNavigator.GetMonthSize: TSize;
begin
Result := ViewInfo.MonthSize;
end;
function TcxSchedulerDateNavigator.GetShowDatesContainingEventsInBold: Boolean;
begin
Result := FShowDatesContainingEventsInBold;
end;
procedure TcxSchedulerDateNavigator.RefreshDays;
begin
ViewInfo.CalculateMonthViewInfos;
Invalidate;
end;
procedure TcxSchedulerDateNavigator.SetFirstDate(Value: TDateTime);
begin
//DELPHI8! check
Value := DateOf(Value) - (GetDateElement(Value, 3) - 1);
if FFirstDate <> Value then
begin
BeginUpdate;
FFirstDate := Value;
UpdateCalculatedValues;
CheckSelectionBounds;
ViewInfo.Calculate;
DoSelectionChanged;
EndUpdate;
end;
end;
procedure TcxSchedulerDateNavigator.ShowMonthPopup(
AMonthInfo: TcxSchedulerDateNavigatorMonthViewInfo);
var
AYear, AMonth, ADay: Word;
begin
if AMonthInfo = nil then Exit;
DecodeDate(FirstDate, AYear, AMonth, ADay);
FListBoxDelta := AMonthInfo.Row * ColCount + AMonthInfo.Col;
ChangeMonth(AYear, AMonth, FListBoxDelta - 3);
TcxSchedulerMonthListBox(FListBox).SetupMonth(
AMonthInfo.Header.MonthNameBounds, EncodeDate(AYear, AMonth, 1));
FListBox.Popup(FListBox)
end;
procedure TcxSchedulerDateNavigator.StepToPast;
var
AYear, AMonth, ADay: Word;
begin
DecodeDate(FirstDate, AYear, AMonth, ADay);
DecMonth(AYear, AMonth);
FirstDate := EncodeDate(AYear, AMonth, 1);
end;
procedure TcxSchedulerDateNavigator.StepToFuture;
var
AYear, AMonth, ADay: Word;
begin
DecodeDate(FirstDate, AYear, AMonth, ADay);
IncMonth(AYear, AMonth);
FirstDate := EncodeDate(AYear, AMonth, 1);
end;
procedure TcxSchedulerDateNavigator.UpdateCalculatedValues;
begin
FToday := SysUtils.Date;
FLastDate := GetLastDate;
FRealFirstDate := GetRealFirstDate;
FRealLastDate := GetRealLastDate;
end;
procedure TcxSchedulerDateNavigator.UpdateDragging;
var
ADate: TDateTime;
begin
with HitTest do
begin
if HitAtTime then ADate := Time else ADate := NullDate;
Controller.DragDate := ADate;
end;
end;
procedure TcxSchedulerDateNavigator.UpdateSelection;
var
ADate: TDateTime;
begin
if SelectionList.Count > 0 then
begin
if SelectionIsWeeks then
ADate := SelectionList[SelectionList.Count div 2]
else
ADate := SelectionList[0]
end
else
begin
ADate := FToday;
SelectionList.Add(FToday)
end;
if (ADate < FirstDate) or (ADate > LastDate) then
FirstDate := ADate;
DoSelectionChanged;
end;
procedure TcxSchedulerDateNavigator.AfterCustomDraw(ACanvas: TcxCanvas;
var AParams: TcxViewParams);
begin
with ACanvas do
begin
AParams.Color := Brush.Color;
AParams.Font := Font;
AParams.TextColor := Font.Color;
end;
end;
procedure TcxSchedulerDateNavigator.BeforeCustomDraw(ACanvas: TcxCanvas;
const AParams: TcxViewParams);
begin
with ACanvas do
begin
Brush.Color := AParams.Color;
Font := AParams.Font;
Font.Color := AParams.TextColor;
end;
end;
function TcxSchedulerDateNavigator.DoCustomDrawBackground(ACanvas: TcxCanvas;
const ABounds: TRect; var AViewParams: TcxViewParams): Boolean;
begin
Result := False;
if Assigned(FOnCustomDrawBackground) then
begin
BeforeCustomDraw(ACanvas, AViewParams);
FOnCustomDrawBackground(Self, ACanvas, ABounds, AViewParams, Result);
if not Result then
AfterCustomDraw(ACanvas, AViewParams);
end;
end;
function TcxSchedulerDateNavigator.DoCustomDrawDayNumber(ACanvas: TcxCanvas; ADayInfo: TcxSchedulerDateNavigatorDayNumberViewInfo): Boolean;
begin
Result := False;
if Assigned(FOnCustomDrawDayNumber) then
begin
BeforeCustomDraw(ACanvas, ADayInfo.FViewParams);
FOnCustomDrawDayNumber(Self, ACanvas, ADayInfo, Result);
if not Result then
AfterCustomDraw(ACanvas, ADayInfo.FViewParams);
end;
end;
function TcxSchedulerDateNavigator.DoCustomDrawDayCaption(ACanvas: TcxCanvas;
ADayCaptionInfo: TcxSchedulerDateNavigatorDayCaptionViewInfo): Boolean;
begin
Result := False;
if Assigned(FOnCustomDrawDayCaption) then
begin
BeforeCustomDraw(ACanvas, ADayCaptionInfo.ViewParams);
FOnCustomDrawDayCaption(Self, ACanvas, ADayCaptionInfo, Result);
if not Result then
AfterCustomDraw(ACanvas, ADayCaptionInfo.FViewParams);
end;
end;
function TcxSchedulerDateNavigator.DoCustomDrawContent(ACanvas: TcxCanvas;
AViewInfo: TcxSchedulerDateNavigatorMonthContentViewInfo): Boolean;
begin
Result := False;
if Assigned(FOnCustomDrawContent) then
begin
BeforeCustomDraw(ACanvas, AViewInfo.ViewParams);
FOnCustomDrawContent(Self, ACanvas, AViewInfo, Result);
if not Result then
begin
AfterCustomDraw(ACanvas, AViewInfo.FViewParams);
AViewInfo.UpdateElementsAfterCustomDraw(ACanvas);
end;
end;
end;
function TcxSchedulerDateNavigator.DoCustomDrawHeader(ACanvas: TcxCanvas;
AViewInfo: TcxSchedulerDateNavigatorMonthHeaderViewInfo): Boolean;
begin
Result := False;
if Assigned(FOnCustomDrawHeader) then
begin
BeforeCustomDraw(ACanvas, AViewInfo.ViewParams);
FOnCustomDrawHeader(Self, ACanvas, AViewInfo, Result);
if not Result then
AfterCustomDraw(ACanvas, AViewInfo.FViewParams);
end;
end;
function TcxSchedulerDateNavigator.GetActualFirstWeekOfYear: TcxFirstWeekOfYear;
begin
if FFirstWeekOfYear = fwySystem then
Result := TcxFirstWeekOfYear(
StrToInt(GetLocaleChar(GetUserDefaultLCID, LOCALE_IFIRSTWEEKOFYEAR, '0')) + 1)
else
Result := FFirstWeekOfYear;
end;
function TcxSchedulerDateNavigator.GetController: TcxSchedulerDateNavigatorController;
begin
Result := TcxSchedulerDateNavigatorController(inherited Controller);
end;
function TcxSchedulerDateNavigator.GetDate: TDateTime;
begin
if SelectionList.Count = 0 then
Result := NullDate
else
Result := SelectionList[0];
end;
function TcxSchedulerDateNavigator.GetHitTest: TcxSchedulerDateNavigatorHitTest;
begin
Result := TcxSchedulerDateNavigatorHitTest(inherited HitTest);
end;
function TcxSchedulerDateNavigator.GetLastDate: TDateTime;
var
Year, Month, Day: Word;
begin
DecodeDate(FirstDate, Year, Month, Day);
ChangeMonth(Year, Month, ColCount * RowCount - 1);
Result := EncodeDate(Year, Month, DaysPerMonth(Year, Month));
end;
function TcxSchedulerDateNavigator.GetRealFirstDate: TDateTime;
var
ACol: Integer;
begin
Result := FFirstDate;
ACol := ColOfDate(FirstDate, Byte(StartOfWeek));
if ACol = 0 then
Result := Result - 7
else
Result := Result - ACol;
end;
function TcxSchedulerDateNavigator.GetRealLastDate: TDateTime;
var
Year, Month, Day: Word;
ACol: Integer;
begin
Result := FLastDate;
DecodeDate(Result, Year, Month, Day);
ACol := ColOfDate(EncodeDate(Year, Month, 1), Byte(StartOfWeek));
Result := Result + 6 * 7 - DaysPerMonth(Year, Month) - ACol;
if (ACol = 0) and (ColCount * RowCount = 1) then Result := Result - 7;
end;
function TcxSchedulerDateNavigator.GetViewInfo: TcxSchedulerDateNavigatorViewInfo;
begin
Result := TcxSchedulerDateNavigatorViewInfo(inherited ViewInfo);
end;
procedure TcxSchedulerDateNavigator.SetColCount(Value: Integer);
begin
if Value < 1 then Value := 1;
if FColCount <> Value then
begin
FColCount := Value;
ViewInfo.CalcInternalSizes;
Width := Value * ViewInfo.MonthSize.cx;
end;
end;
procedure TcxSchedulerDateNavigator.SetDate(Value: TDateTime);
begin
if Value <> NullDate then
begin
SelectionList.Clear;
if (Value < FirstDate) or (Value > LastDate) then
FirstDate := Value;
SelectionIsWeeks := False;
SelectionList.Add(Value);
RefreshDays;
end;
end;
procedure TcxSchedulerDateNavigator.SetFirstWeekOfYear(
Value: TcxFirstWeekOfYear);
begin
if Value <> FFirstWeekOfYear then
begin
FFirstWeekOfYear := Value;
FActualFirstWeekOfYear := GetActualFirstWeekOfYear;
if ShowWeekNumbers then
RefreshDays;
end;
end;
procedure TcxSchedulerDateNavigator.SetRowCount(Value: Integer);
begin
if Value < 1 then Value := 1;
if FRowCount <> Value then
begin
FRowCount := Value;
ViewInfo.CalcInternalSizes;
Height := Value * ViewInfo.MonthSize.cy;
end;
end;
procedure TcxSchedulerDateNavigator.SetSelectPeriod(Value: Boolean);
begin
if FSelectPeriod <> Value then
begin
FSelectPeriod := Value;
if not Value then
Date := Date;
end;
end;
procedure TcxSchedulerDateNavigator.SetShowDatesContainingEventsInBold(Value: Boolean);
begin
if FShowDatesContainingEventsInBold <> Value then
begin
FShowDatesContainingEventsInBold := Value;
RefreshDays;
end;
end;
procedure TcxSchedulerDateNavigator.SetShowWeekNumbers(Value: Boolean);
begin
if FShowWeekNumbers <> Value then
begin
FShowWeekNumbers := Value;
RefreshDays;
end;
end;
procedure TcxSchedulerDateNavigator.SetStyles(
const Value: TcxSchedulerDateNavigatorStyles);
begin
FStyles.Assign(Value);
end;
{ TcxSchedulerDateNavigatorPainter }
constructor TcxSchedulerDateNavigatorPainter.Create(AOwner: TcxSchedulerSubControl);
begin
inherited Create(AOwner);
FDateNavigator := TcxSchedulerDateNavigator(AOwner);
end;
procedure TcxSchedulerDateNavigatorPainter.Paint;
var
I, J: Integer;
AMonthInfo: TcxSchedulerDateNavigatorMonthViewInfo;
begin
Canvas.FillRect(DateNavigator.ViewInfo.CalendarBounds,
DateNavigator.Styles.GetContentParams);
for I := 0 to DateNavigator.ColCount - 1 do
for J := 0 to DateNavigator.RowCount - 1 do
begin
AMonthInfo := DateNavigator.ViewInfo.MonthViewInfo[I, J];
DoDrawMonthContent(AMonthInfo.Content);
DoDrawMonthHeader(AMonthInfo.Header);
DoDrawDayCaptions(AMonthInfo.Content);
DoDrawDayNumbers(AMonthInfo.Content);
DrawSeparators(AMonthInfo.Content);
if DateNavigator.ShowWeekNumbers then
DrawWeekNumbers(AMonthInfo.Content);
end;
Canvas.ExcludeClipRect(DateNavigator.ViewInfo.CalendarBounds);
DrawBackground;
end;
procedure TcxSchedulerDateNavigatorPainter.DoDrawDayCaptions(
AViewInfo: TcxSchedulerDateNavigatorMonthContentViewInfo);
var
I: Integer;
AInfo: TcxSchedulerDateNavigatorDayCaptionViewInfo;
begin
for I := 0 to 6 do
begin
AInfo := AViewInfo.DayCaptions[I];
AInfo.SaveParams(AViewInfo.Transparent);
if not DateNavigator.DoCustomDrawDayCaption(Canvas, AInfo) then
begin
cxApplyViewParams(Canvas, AInfo.ViewParams);
if not AInfo.Transparent then
Canvas.FillRect(AInfo.Bounds, AInfo.ViewParams);
Canvas.Brush.Style := bsClear;
Canvas.DrawText(AInfo.Text, cxRectOffset(AInfo.Bounds, -2, 0), cxdnTextFlags);
Canvas.Brush.Style := bsSolid;
end;
AInfo.RestoreParams;
end;
end;
procedure TcxSchedulerDateNavigatorPainter.DoDrawDayNumbers(
AViewInfo: TcxSchedulerDateNavigatorMonthContentViewInfo);
var
I: Integer;
ADayInfo: TcxSchedulerDateNavigatorDayNumberViewInfo;
begin
for I := 0 to AViewInfo.FDayCount - 1 do
begin
ADayInfo := AViewInfo.FDays[I];
ADayInfo.SaveParams(AViewInfo.Transparent and not ADayInfo.Selected);
if not DateNavigator.DoCustomDrawDayNumber(Canvas, ADayInfo) then
DrawDayNumber(ADayInfo);
ADayInfo.RestoreParams;
end;
end;
procedure TcxSchedulerDateNavigatorPainter.DoDrawMonthContent(
AViewInfo: TcxSchedulerDateNavigatorMonthContentViewInfo);
begin
AViewInfo.SaveParams;
if not DateNavigator.DoCustomDrawContent(Canvas, AViewInfo) then
// use owner's bounds
Canvas.FillRect(AViewInfo.Owner.Bounds, AViewInfo.ViewParams);
AViewInfo.RestoreParams;
end;
procedure TcxSchedulerDateNavigatorPainter.DoDrawMonthHeader(
AViewInfo: TcxSchedulerDateNavigatorMonthHeaderViewInfo);
begin
AViewInfo.SaveParams(False);
if not DateNavigator.DoCustomDrawHeader(Canvas, AViewInfo) then
begin
FHeaderTransparent := AViewInfo.Transparent;
DrawMonthHeader(AViewInfo);
end;
AViewInfo.RestoreParams;
end;
procedure TcxSchedulerDateNavigatorPainter.DrawDayNumber(
ADayInfo: TcxSchedulerDateNavigatorDayNumberViewInfo);
begin
cxApplyViewParams(Canvas, ADayInfo.ViewParams);
with Canvas do
begin
if DateNavigator.ShowDatesContainingEventsInBold then
begin
if ADayInfo.Bold then
Font.Style := Font.Style + [fsBold]
else
Font.Style := Font.Style - [fsBold];
end;
if not ADayInfo.Transparent then
begin
FillRect(ADayInfo.Bounds, ADayInfo.ViewParams);
if not cxRectIsEmpty(ADayInfo.SelectionSideBounds) then
FillRect(ADayInfo.SelectionSideBounds);
end;
CheckDrawFrame(ADayInfo.Bounds, ADayInfo.Date);
Brush.Style := bsClear;
DrawText(ADayInfo.Text, cxRectOffset(ADayInfo.Bounds, -2, 0), cxdnTextFlags);
Brush.Style := bsSolid;
end;
end;
procedure TcxSchedulerDateNavigatorPainter.DrawBackground;
var
AViewParams: TcxViewParams;
begin
with DateNavigator do
begin
AViewParams := Styles.GetBackgroundParams;
if not DoCustomDrawBackground(Canvas, ClientRect, AViewParams) then
Canvas.FillRect(ClientRect, AViewParams);
end;
end;
procedure TcxSchedulerDateNavigatorPainter.DrawMonthHeader(
AViewInfo: TcxSchedulerDateNavigatorMonthHeaderViewInfo);
begin
FHeaderParams := AViewInfo.ViewParams;
DateNavigator.LookAndFeelPainter.DrawMonthHeader(Canvas, AViewInfo.Bounds,
AViewInfo.Text, AViewInfo.Neighbors, FHeaderParams, AViewInfo.Arrows,
DateNavigator.ViewInfo.SideWidth, DrawHeaderBackground);
end;
procedure TcxSchedulerDateNavigatorPainter.DrawSeparators(
AViewInfo: TcxSchedulerDateNavigatorMonthContentViewInfo);
begin
with Canvas do
begin
SetBrushColor(clBtnShadow);
FillRect(AViewInfo.HorzSeparatorBound);
if DateNavigator.ShowWeekNumbers then
begin
FillRect(cxRectSetWidth(AViewInfo.VertSeparatorBound, 1));
SetBrushColor(clBtnHighlight);
FillRect(cxRectSetWidth(AViewInfo.VertSeparatorBound,
AViewInfo.VertSeparatorBound.Left + 1, 1));
end;
end;
end;
procedure TcxSchedulerDateNavigatorPainter.DrawWeekNumbers(
AViewInfo: TcxSchedulerDateNavigatorMonthContentViewInfo);
var
I: Integer;
begin
with Canvas do
begin
Brush.Style := bsClear;
Font := AViewInfo.ViewParams.Font;
Font.Color := AViewInfo.ViewParams.TextColor;
Font.Size := MulDiv(AViewInfo.ViewParams.Font.Size, 2, 3);
with AViewInfo do
for I := 0 to FWeekCount - 1 do
DrawText(FWeekTexts[I], FWeekBounds[I], cxdnTextFlags);
Brush.Style := bsSolid;
Font.Size := AViewInfo.ViewParams.Font.Size;
end;
end;
procedure TcxSchedulerDateNavigatorPainter.CheckDrawFrame(
const ABounds: TRect; ADate: TDateTime);
begin
if ADate = DateNavigator.Controller.DragDate then
Canvas.FrameRect(ABounds, clWindowText, 2)
else
if ADate = DateNavigator.FToday then
begin
Canvas.SetBrushColor(clMaroon);
Canvas.FrameRect(ABounds);
end;
end;
function TcxSchedulerDateNavigatorPainter.DrawHeaderBackground(ACanvas: TcxCanvas;
const ABounds: TRect): Boolean;
begin
Result := True;
if not FHeaderTransparent then
ACanvas.FillRect(ABounds, FHeaderParams);
end;
{ TcxSchedulerDateNavigatorCaptionViewInfo }
procedure TcxSchedulerDateNavigatorCaptionViewInfo.RestoreParams;
begin
FViewParams := FSaveParams;
end;
procedure TcxSchedulerDateNavigatorCaptionViewInfo.SaveParams(ATransparent: Boolean);
begin
FSaveParams := FViewParams;
FTransparent := ATransparent;
end;
{ TcxSchedulerDateNavigatorMonthHeaderViewInfo }
constructor TcxSchedulerDateNavigatorMonthHeaderViewInfo.Create(
AOwner: TcxSchedulerDateNavigatorMonthViewInfo);
begin
inherited Create;
FOwner := AOwner;
end;
procedure TcxSchedulerDateNavigatorMonthHeaderViewInfo.Calculate(const ABounds: TRect);
begin
FBounds := ABounds;
FText := Owner.Owner.DateTimeHelper.MonthYearToStr(Month, Year);
FArrows := Owner.GetHeaderArrows;
FNeighbors := Owner.GetHeaderNeighbors;
FMonthNameBounds := GetMonthNameBounds;
FViewParams := Owner.Owner.HeaderParams;
FTransparent := False;
end;
function TcxSchedulerDateNavigatorMonthHeaderViewInfo.GetMonth: Integer;
begin
Result := Owner.Month;
end;
function TcxSchedulerDateNavigatorMonthHeaderViewInfo.GetMonthNameBounds: TRect;
begin
Result := Bounds;
with Result do
begin
Inc(Left, Owner.Owner.ColWidth);
Dec(Right, Owner.Owner.ColWidth);
Dec(Bottom);
Inc(Top);
end;
end;
function TcxSchedulerDateNavigatorMonthHeaderViewInfo.GetYear: Integer;
begin
Result := Owner.Year;
end;
{ TcxSchedulerDateNavigatorMonthContentViewInfo }
constructor TcxSchedulerDateNavigatorMonthContentViewInfo.Create(
AOwner: TcxSchedulerDateNavigatorMonthViewInfo);
begin
inherited Create;
FOwner := AOwner;
FViewInfo := AOwner.Owner;
FDateNavigator := AOwner.Owner.Owner;
FFont := TFont.Create;
CreateDayInfos;
CreateDayCaptionInfos;
end;
destructor TcxSchedulerDateNavigatorMonthContentViewInfo.Destroy;
begin
DestroyDayCaptionInfos;
DestroyDayInfos;
FFont.Free;
inherited Destroy;
end;
procedure TcxSchedulerDateNavigatorMonthContentViewInfo.CalcAndAddDayInfo(ADate: TDateTime;
const ABounds: TRect; const ASelectionSideBounds: TRect);
var
ASelected: Boolean;
begin
ASelected := DateNavigator.IsDateSelected(ADate);
with FDays[FDayCount] do
begin
FBold := DateNavigator.IsDateHasEvent(ADate);
FBounds := ABounds;
FDate := ADate;
FGrayed := GetGrayed(ADate);
FSelected := ASelected;
if ASelected and DateNavigator.CanDrawSelectionSide then
FSelectionSideBounds := ASelectionSideBounds
else
FSelectionSideBounds := cxNullRect;
FText := IntToStr(GetDateElement(ADate, 3));
FViewParams := GetDateViewParams(ADate, ASelected);
if FGrayed then FViewParams.TextColor := clGrayText;
end;
Inc(FDayCount);
end;
procedure TcxSchedulerDateNavigatorMonthContentViewInfo.Calculate(
ACol, ARow, AYear, AMonth: Integer);
begin
FBounds := ViewInfo.GetInternalRect(ACol, ARow);
FRow := ARow;
FCol := ACol;
FYear := AYear;
FMonth := AMonth;
CalcParams;
CalcDayCaptions;
CalcDays;
with FWeekSelectionBarBounds do
begin
Left := Bounds.Left;
Top := Bounds.Top + ViewInfo.DayCaptionsHeight;
Right := Left + ViewInfo.SideWidth;
Bottom := Top + ViewInfo.RowHeight * FWeekCount;
end;
CalcSeparatorsBound;
end;
procedure TcxSchedulerDateNavigatorMonthContentViewInfo.CalcDays;
var
R: TRect;
I, J, ADayBase, ADaysPerMonth: Integer;
ADate, ADateBase: TDateTime;
AHasDate: Boolean;
procedure CheckCalcWeekNumber(const R: TRect);
begin
if DateNavigator.ShowWeekNumbers then
begin
FWeekBounds[FWeekCount] := cxRect(R.Left - ViewInfo.SideWidth,
R.Top - 1, R.Left - 3, R.Bottom);
FWeekTexts[FWeekCount] := IntToStr(GetWeekNumber(ADate,
DateNavigator.StartOfWeek, DateNavigator.FActualFirstWeekOfYear));
end;
Inc(FWeekCount);
end;
function GetDate(out ADate: TDateTime): Boolean;
var
ACurDay: Integer;
begin
ACurDay := ADayBase + J * 7 + I;
Result := not ((ACurDay < 1) and (FCol + FRow <> 0) or
(ACurDay > ADaysPerMonth) and ((FCol <> ViewInfo.ColCount - 1) or
(FRow <> ViewInfo.RowCount - 1)));
ADate := ADateBase + ACurDay;
end;
begin
FDayCount := 0;
FWeekCount := 0;
ADateBase := EncodeDate(FYear, FMonth, 1) - 1;
ADayBase := 1 - ColOfDate(ADateBase + 1, Byte(DateNavigator.StartOfWeek));
if (ADayBase = 1) and (FCol + FRow = 0) then Dec(ADayBase, 7);
ADaysPerMonth := DaysPerMonth(FYear, FMonth);
for I := 0 to 6 do
for J := 0 to 5 do
begin
AHasDate := GetDate(ADate);
R := GetDayRectFromColAndRow(I, J);
if (I = 0) and not ((J = 5) and not AHasDate) then
CheckCalcWeekNumber(R);
if AHasDate then
CalcAndAddDayInfo(ADate, R, GetSelectionSideBounds(R, I));
end;
end;
procedure TcxSchedulerDateNavigatorMonthContentViewInfo.CalcDayCaptions;
var
I: Integer;
R: TRect;
begin
with R do
begin
Top := Bounds.Top;
Bottom := Top + ViewInfo.DayCaptionsHeight - 2;
Right := Bounds.Left + ViewInfo.SideWidth;
end;
for I := 0 to 6 do
begin
with R do
begin
Left := Right;
Right := Left + ViewInfo.ColWidth;
end;
FDayCaptions[I].FBounds := R;
FDayCaptions[I].FIndex := I;
FDayCaptions[I].FText := GetDayCaptionText(I);
FDayCaptions[I].FViewParams := ViewParams;
end;
end;
procedure TcxSchedulerDateNavigatorMonthContentViewInfo.CalcParams;
begin
FViewParams := ViewInfo.ContentParams;
FSelectedParams := ViewInfo.SelectedParams;
FFontCharset := FViewParams.Font.Charset;
if FFontCharset = DEFAULT_CHARSET then
FFontCharset := GetDefFontCharset;
end;
procedure TcxSchedulerDateNavigatorMonthContentViewInfo.CalcSeparatorsBound;
begin
with FHorzSeparatorBound do
begin
Left := Bounds.Left + ViewInfo.SideWidth;
Right := Bounds.Right - ViewInfo.SideWidth + 1;
Top := Bounds.Top + ViewInfo.DayCaptionsHeight - 2;
Bottom := Top + 1;
end;
if DateNavigator.ShowWeekNumbers then
begin
with FVertSeparatorBound do
begin
Left := WeekSelectionBarBounds.Right;
Right := Left + 2;
Top := WeekSelectionBarBounds.Top - 1;
Bottom := WeekSelectionBarBounds.Bottom;
end
end
else
FVertSeparatorBound := cxNullRect;
end;
function TcxSchedulerDateNavigatorMonthContentViewInfo.GetDateViewParams(ADate: TDateTime;
ASelected: Boolean): TcxViewParams;
begin
if ASelected then
Result := SelectedParams
else
Result := ViewParams;
end;
function TcxSchedulerDateNavigatorMonthContentViewInfo.GetDayCaptionText(Index: Byte): string;
var
ADayIndex: Integer;
begin
if IsValidDayCaptionIndex(Index) then
begin
ADayIndex := Byte(DateNavigator.StartOfWeek) + 1 + Index;
if ADayIndex > 7 then Dec(ADayIndex, 7);
if FFontCharset in [ARABIC_CHARSET, CHINESEBIG5_CHARSET, GB2312_CHARSET] then
Result := AnsiLastChar(ShortDayNames[ADayIndex])
else
Result := WideString(ShortDayNames[ADayIndex])[1];
end
else
Result := '';
end;
function TcxSchedulerDateNavigatorMonthContentViewInfo.GetWeekBound(Index: Byte): TRect;
begin
if IsValidWeekIndex(Index) then
Result := FWeekBounds[Index]
else
Result := cxNullRect;
end;
function TcxSchedulerDateNavigatorMonthContentViewInfo.GetDayText(ADate: TDateTime): string;
begin
if ADate <> NullDate then
Result := IntToStr(GetDateElement(ADate, 3))
else
Result := '';
end;
function TcxSchedulerDateNavigatorMonthContentViewInfo.GetWeekText(Index: Byte): string;
begin
if IsValidWeekIndex(Index) then
Result := FWeekTexts[Index]
else
Result := '';
end;
procedure TcxSchedulerDateNavigatorMonthContentViewInfo.RestoreParams;
begin
FViewParams := FSaveParams;
end;
procedure TcxSchedulerDateNavigatorMonthContentViewInfo.SaveParams;
begin
FTransparent := False;
FSaveParams := FViewParams;
end;
procedure TcxSchedulerDateNavigatorMonthContentViewInfo.UpdateElementsAfterCustomDraw(
ACanvas: TcxCanvas);
var
I: Integer;
begin
FFont.Assign(ACanvas.Font);
for I := 0 to 6 do
with FDayCaptions[I] do
begin
FViewParams.Color := Self.ViewParams.Color;
FViewParams.TextColor := Self.ViewParams.TextColor;
FViewParams.Font := FFont;
end;
for I := 0 to FDayCount - 1 do
with FDays[I] do
if not Selected then
begin
if not Grayed then
FViewParams.TextColor := Self.ViewParams.TextColor;
FViewParams.Color := Self.ViewParams.Color;
FViewParams.Font := FFont;
end;
end;
procedure TcxSchedulerDateNavigatorMonthContentViewInfo.CreateDayInfos;
var
I: Integer;
begin
for I := 0 to cxMaxMonthViewInfoDays - 1 do
FDays[I] := TcxSchedulerDateNavigatorDayNumberViewInfo.Create;
end;
procedure TcxSchedulerDateNavigatorMonthContentViewInfo.CreateDayCaptionInfos;
var
I: Integer;
begin
for I := 0 to 6 do
FDayCaptions[I] := TcxSchedulerDateNavigatorDayCaptionViewInfo.Create;
end;
procedure TcxSchedulerDateNavigatorMonthContentViewInfo.DestroyDayInfos;
var
I: Integer;
begin
for I := 0 to cxMaxMonthViewInfoDays - 1 do
FDays[I].Free;
FDayCount := 0;
end;
procedure TcxSchedulerDateNavigatorMonthContentViewInfo.DestroyDayCaptionInfos;
var
I: Integer;
begin
for I := 0 to 6 do
FDayCaptions[I].Free;
end;
function TcxSchedulerDateNavigatorMonthContentViewInfo.GetDayCaptionInfo(
Index: Byte): TcxSchedulerDateNavigatorDayCaptionViewInfo;
begin
if IsValidDayCaptionIndex(Index) then
Result := FDayCaptions[Index]
else
Result := nil;
end;
function TcxSchedulerDateNavigatorMonthContentViewInfo.GetDayRectFromColAndRow(
ACol, ARow: Integer): TRect;
begin
with Result do
begin
Left := Bounds.Left + ViewInfo.SideWidth + ACol * ViewInfo.ColWidth + 2;
Top := Bounds.Top + ViewInfo.DayCaptionsHeight + ARow * ViewInfo.RowHeight;
Right := Left + ViewInfo.ColWidth;
Bottom := Top + ViewInfo.RowHeight;
end;
end;
function TcxSchedulerDateNavigatorMonthContentViewInfo.GetDayNumberViewInfo(
Index: Byte): TcxSchedulerDateNavigatorDayNumberViewInfo;
begin
if IsValidDayIndex(Index) then
Result := FDays[Index]
else
begin
Result.Text := '';
FillChar(Result, SizeOf(Result), 0);
end;
end;
function TcxSchedulerDateNavigatorMonthContentViewInfo.GetGrayed(ADate: TDateTime): Boolean;
begin
Result := (ADate < DateNavigator.FirstDate) and (FCol + FRow = 0) or
(ADate > DateNavigator.LastDate) and (FCol = ViewInfo.ColCount - 1) and
(FRow = ViewInfo.RowCount - 1);
end;
function TcxSchedulerDateNavigatorMonthContentViewInfo.GetSelectionSideBounds(
const ADayBounds: TRect; ACol: Integer): TRect;
begin
if ((ACol = 0) or (ACol = 6)) and not DateNavigator.ShowWeekNumbers then
begin
Result := ADayBounds;
with Result do
if ACol = 0 then
begin
Right := Left;
Left := Right - ViewInfo.ColWidth div 2;
end
else
begin
Left := Right;
Right := Left + ViewInfo.ColWidth div 2;
end;
end
else Result := cxNullRect;
end;
function TcxSchedulerDateNavigatorMonthContentViewInfo.IsValidDayIndex(Index: Byte): Boolean;
begin
Result := Index < FDayCount;
end;
function TcxSchedulerDateNavigatorMonthContentViewInfo.IsValidDayCaptionIndex(Index: Byte): Boolean;
begin
Result := Index in [0..6];
end;
function TcxSchedulerDateNavigatorMonthContentViewInfo.IsValidWeekIndex(Index: Byte): Boolean;
begin
Result := Index < FWeekCount;
end;
procedure TcxSchedulerDateNavigatorMonthContentViewInfo.SetWeekText(Index: Byte; const Value: string);
begin
if IsValidWeekIndex(Index) then
FWeekTexts[Index] := Value;
end;
{ TcxSchedulerDateNavigatorMonthViewInfo }
constructor TcxSchedulerDateNavigatorMonthViewInfo.Create(
AOwner: TcxSchedulerDateNavigatorViewInfo);
begin
inherited Create;
FOwner := AOwner;
FHeader := TcxSchedulerDateNavigatorMonthHeaderViewInfo.Create(Self);
FContent := TcxSchedulerDateNavigatorMonthContentViewInfo.Create(Self);
end;
destructor TcxSchedulerDateNavigatorMonthViewInfo.Destroy;
begin
FContent.Free;
FHeader.Free;
inherited Destroy;
end;
procedure TcxSchedulerDateNavigatorMonthViewInfo.Calculate(ACol, ARow,
AYear, AMonth: Integer);
begin
FBounds := Owner.GetMonthRect(ACol, ARow);
FRow := ARow;
FCol := ACol;
FYear := AYear;
FMonth := AMonth;
Header.Calculate(Owner.GetHeaderRect(ACol, ARow));
Content.Calculate(ACol, ARow, AYear, AMonth);
end;
function TcxSchedulerDateNavigatorMonthViewInfo.GetHeaderArrows: TcxHeaderArrows;
const
Arrows: array[Boolean, Boolean] of TcxHeaderArrows =
((haNone, haRight), (haLeft, haBoth));
begin
if Row = 0 then
Result := Arrows[Col = 0, Col = Owner.ColCount - 1]
else
Result := haNone;
end;
function TcxSchedulerDateNavigatorMonthViewInfo.GetHeaderNeighbors: TcxNeighbors;
begin
if Owner.ColCount = 1 then
Result := []
else if Col = 0 then
Result := [nRight]
else if Col = Owner.ColCount - 1 then
Result := [nLeft]
else
Result := [nLeft, nRight];
end;
{ TcxSchedulerDateNavigatorStyles }
constructor TcxSchedulerDateNavigatorStyles.Create(AOwner: TPersistent);
begin
inherited Create(AOwner);
BitmapInViewParams := True;
end;
procedure TcxSchedulerDateNavigatorStyles.Assign(Source: TPersistent);
var
I: Integer;
begin
if Source is TcxSchedulerDateNavigatorStyles then
begin
for I := cxdnBackground to cxdnSelection do
SetValue(I, TcxSchedulerDateNavigatorStyles(Source).GetValue(I))
end;
inherited Assign(Source);
end;
procedure TcxSchedulerDateNavigatorStyles.Changed(AIndex: Integer);
begin
DateNavigator.CheckSizes;
DateNavigator.Refresh;
end;
function TcxSchedulerDateNavigatorStyles.GetBackgroundParams: TcxViewParams;
begin
GetViewParams(cxdnBackground, nil, nil, Result);
end;
function TcxSchedulerDateNavigatorStyles.GetContentParams: TcxViewParams;
begin
GetViewParams(cxdnContent, nil, nil, Result);
end;
function TcxSchedulerDateNavigatorStyles.GetHeaderParams: TcxViewParams;
begin
GetViewParams(cxdnHeader, nil, nil, Result);
end;
function TcxSchedulerDateNavigatorStyles.GetSelectionParams: TcxViewParams;
begin
GetViewParams(cxdnSelection, nil, nil, Result);
end;
procedure TcxSchedulerDateNavigatorStyles.GetDefaultViewParams(
Index: Integer; AData: TObject; out AParams: TcxViewParams);
function Painter: TcxCustomLookAndFeelPainterClass;
begin
Result := DateNavigator.LookAndFeelPainter;
end;
begin
AParams.Bitmap := nil;
AParams.Font := DateNavigator.Scheduler.Font;
case Index of
cxdnHeader:
begin
AParams.Color := Painter.DefaultHeaderColor;
AParams.TextColor := Painter.DefaultHeaderTextColor;
end;
cxdnBackground, cxdnContent:
begin
AParams.Color := Painter.DefaultSchedulerBackgroundColor;
AParams.TextColor := Painter.DefaultSchedulerTextColor;
end;
cxdnSelection:
begin
AParams.Font := GetContentParams.Font;
AParams.Color := Painter.DefaultDateNavigatorSelectionColor;
AParams.TextColor := Painter.DefaultDateNavigatorSelectionTextColor;
end;
end;
end;
function TcxSchedulerDateNavigatorStyles.GetDateNavigator: TcxSchedulerDateNavigator;
begin
Result := TcxSchedulerDateNavigator(inherited Owner);
end;
{ TcxSchedulerDateNavigatorHitTest }
procedure TcxSchedulerDateNavigatorHitTest.Clear;
begin
inherited Clear;
FTime := NullDate;
FMonthViewInfo := nil;
end;
procedure TcxSchedulerDateNavigatorHitTest.DoCalculate;
var
ACol, ARow: Integer;
ADay, AYear, AMonth: Word;
begin
inherited DoCalculate;
if cxRectPtIn(ViewInfo.CalendarBounds, HitPoint) then
begin
SetBitState(htcCalendar, True);
ACol := ViewInfo.GetCol(HitX);
ARow := ViewInfo.GetRow(HitY);
DecodeDate(Owner.FirstDate, AYear, AMonth, ADay);
ChangeMonth(AYear, AMonth, ARow * ViewInfo.ColCount + ACol);
FTime := EncodeDate(AYear, AMonth, 1);
FMonthViewInfo := ViewInfo.MonthViewInfo[ACol, ARow];
CalcMonth;
end;
{$IFDEF DEBUG}
if FHitDate <> NullDate then
Application.MainForm.Caption := DateToStr(FHitDate)
else
Application.MainForm.Caption := 'NullDate'
{$ENDIF}
end;
procedure TcxSchedulerDateNavigatorHitTest.CalcMonth;
var
R: TRect;
ADate: TDateTime;
begin
if CheckMonthHeader or CheckWeekSelectionBar or CheckDayCaptions then Exit;
R := MonthViewInfo.Content.Bounds;
with R do
begin
Inc(Top, ViewInfo.DayCaptionsHeight);
Inc(Left, ViewInfo.SideWidth + 2);
Dec(Right, ViewInfo.SideWidth);
end;
if cxRectPtIn(R, HitPoint) then
begin
SetBitState(htcTime, True);
ADate := GetFirstWeekSelectableDate +
((HitY - R.Top) div ViewInfo.RowHeight) * 7 + ((HitX - R.Left) div ViewInfo.ColWidth);
if (ADate < FTime) and (MonthViewInfo.Col + MonthViewInfo.Row > 0) then Exit;
FTime := FTime + DaysPerMonth(MonthViewInfo.Year, MonthViewInfo.Month) - 1;
if (ADate > FTime) and not ((MonthViewInfo.Col = Owner.ColCount - 1) and
(MonthViewInfo.Row = Owner.RowCount - 1)) then Exit;
FTime := ADate;
end;
end;
function TcxSchedulerDateNavigatorHitTest.CheckDayCaptions: Boolean;
var
R: TRect;
begin
R := MonthViewInfo.Bounds;
with R do
begin
Inc(Left, ViewInfo.SideWidth);
Dec(Right, ViewInfo.SideWidth);
Bottom := Top + ViewInfo.DayCaptionsHeight;
end;
Result := cxRectPtIn(R, HitPoint);
if Result then
SetBitState(htcDayCaptions, True);
end;
function TcxSchedulerDateNavigatorHitTest.CheckMonthHeader: Boolean;
begin
Result := False;
if cxRectPtIn(MonthViewInfo.Header.MonthNameBounds, HitPoint) then
begin
SetBitState(htcMonthName, True);
Result := True;
end
else
if cxRectPtIn(ViewInfo.GetLeftArrowRect, HitPoint) then
begin
SetBitState(htcPrevMonth, True);
Result := True;
end
else
if cxRectPtIn(ViewInfo.GetRightArrowRect, HitPoint) then
begin
SetBitState(htcNextMonth, True);
Result := True;
end;
end;
function TcxSchedulerDateNavigatorHitTest.CheckWeekSelectionBar: Boolean;
var
AContent: TcxSchedulerDateNavigatorMonthContentViewInfo;
begin
AContent := MonthViewInfo.Content;
Result := cxRectPtIn(AContent.WeekSelectionBarBounds, HitPoint);
if Result then
begin
SetBitState(htcWeekSelectionBar, True);
FTime := GetFirstWeekSelectableDate +
((HitY - AContent.WeekSelectionBarBounds.Top) div ViewInfo.RowHeight) * 7;
end;
end;
function TcxSchedulerDateNavigatorHitTest.GetFirstWeekSelectableDate: TDateTime;
begin
Result := FTime - ColOfDate(FTime, Byte(Owner.StartOfWeek));
if (MonthViewInfo.Col + MonthViewInfo.Row = 0) and
(ColOfDate(Owner.FirstDate, Byte(Owner.StartOfWeek)) = 0) then
Result := Result - 7;
end;
function TcxSchedulerDateNavigatorHitTest.GetOwner: TcxSchedulerDateNavigator;
begin
Result := TcxSchedulerDateNavigator(inherited Owner);
end;
function TcxSchedulerDateNavigatorHitTest.GetViewInfo: TcxSchedulerDateNavigatorViewInfo;
begin
Result := Owner.ViewInfo;
end;
{ TcxSchedulerDateNavigatorViewInfo }
constructor TcxSchedulerDateNavigatorViewInfo.Create(AOwner: TcxSchedulerSubControl);
begin
inherited Create(AOwner);
FOwner := TcxSchedulerDateNavigator(AOwner);
FMonthViewInfoList := TList.Create;
end;
destructor TcxSchedulerDateNavigatorViewInfo.Destroy;
begin
DestroyMonthViewInfoList;
inherited Destroy;
end;
procedure TcxSchedulerDateNavigatorViewInfo.DoCalculate;
begin
CalcInternalSizes;
CalculateCalendarBounds;
CheckMonthViewInfoCount;
CalculateMonthViewInfos;
end;
procedure TcxSchedulerDateNavigatorViewInfo.CalculateCalendarBounds;
begin
FCalendarBounds := Owner.ClientRect;
FColCount := Max(1, Min(cxDaysCalendarMaxColCount, Owner.Width div MonthSize.cx));
FRowCount := Max(1, Owner.Height div MonthSize.cy);
FCalendarBounds := cxRect(0, 0, ColCount * MonthSize.cx, RowCount * MonthSize.cy);
FCalendarBounds := cxRectOffset(FCalendarBounds,
(Owner.Width - cxRectWidth(CalendarBounds)) div 2,
(Owner.Height - cxRectHeight(CalendarBounds)) div 2);
if FCalendarBounds.Left < 0 then
FCalendarBounds := cxRectSetLeft(FCalendarBounds, 0);
if FCalendarBounds.Top < 0 then
FCalendarBounds := cxRectSetTop(FCalendarBounds, 0);
end;
procedure TcxSchedulerDateNavigatorViewInfo.CalculateMonthViewInfos;
var
I, J: Integer;
AYear, AMonth, ADay: Word;
begin
DecodeDate(Owner.FirstDate, AYear, AMonth, ADay);
for J := 0 to RowCount - 1 do
for I := 0 to ColCount - 1 do
begin
MonthViewInfo[I, J].Calculate(I, J, AYear, AMonth);
ChangeMonth(AYear, AMonth, 1);
end;
end;
procedure TcxSchedulerDateNavigatorViewInfo.CalculateViewParams;
begin
with Owner.Styles do
begin
FContentParams := GetContentParams;
FHeaderParams := GetHeaderParams;
FSelectedParams := GetSelectionParams;
end;
end;
procedure TcxSchedulerDateNavigatorViewInfo.CheckMonthViewInfoCount;
var
I, ACount: Integer;
begin
ACount := RowCount * ColCount;
for I := FMonthViewInfoList.Count - 1 downto ACount do
begin
TcxSchedulerDateNavigatorMonthViewInfo(FMonthViewInfoList[I]).Free;
FMonthViewInfoList.Delete(I);
end;
for I := FMonthViewInfoList.Count to ACount - 1 do
FMonthViewInfoList.Add(TcxSchedulerDateNavigatorMonthViewInfo.Create(Self));
end;
function TcxSchedulerDateNavigatorViewInfo.GetCol(X: Integer): Integer;
begin
Result := (X - CalendarBounds.Left) div MonthSize.cx;
end;
function TcxSchedulerDateNavigatorViewInfo.GetHeaderRect(ACol, ARow: Integer): TRect;
begin
with MonthSize do
Result := cxRectOffset(cxRect(0, 0, cx, FHeaderHeight),
CalendarBounds.Left + ACol * cx, CalendarBounds.Top + ARow * cy);
end;
function TcxSchedulerDateNavigatorViewInfo.GetInternalRect(ACol, ARow: Integer): TRect;
begin
with MonthSize do
Result := cxRectOffset(cxRect(0, FHeaderHeight, cx, cy),
CalendarBounds.Left + ACol * cx, CalendarBounds.Top + ARow * cy);
end;
function TcxSchedulerDateNavigatorViewInfo.GetLeftArrowRect: TRect;
begin
Result := cxRectBounds(CalendarBounds.Left + 1, CalendarBounds.Top + 1,
FColWidth - 2, FHeaderHeight - 2);
end;
function TcxSchedulerDateNavigatorViewInfo.GetMonthRect(
ACol, ARow: Integer): TRect;
begin
with MonthSize do
Result := cxRectOffset(cxRect(0, 0, cx, cy),
CalendarBounds.Left + ACol * cx, CalendarBounds.Top + ARow * cy);
end;
function TcxSchedulerDateNavigatorViewInfo.GetRightArrowRect: TRect;
begin
Result := cxRectBounds(CalendarBounds.Right - FColWidth,
CalendarBounds.Top + HeaderBorderSize, FColWidth - HeaderBorderSize,
FHeaderHeight - HeaderBorderSize);
end;
function TcxSchedulerDateNavigatorViewInfo.GetRow(Y: Integer): Integer;
begin
Result := (Y - CalendarBounds.Top) div MonthSize.cy;
end;
procedure TcxSchedulerDateNavigatorViewInfo.CalcInternalSizes;
var
ASymbolSize: TSize;
begin
CalculateViewParams;
FHeaderBorderSize := LookAndFeelPainter.ButtonBorderSize;
FHeaderBorderSize := 1;
ASymbolSize := cxTextExtent(ContentParams.Font, '0');
FColWidth := 3 * ASymbolSize.cx - 1;
FSideWidth := 2 * ASymbolSize.cx;
FRowHeight := ASymbolSize.cy + 2;
FDayCaptionsHeight := FRowHeight + 1;
FHeaderHeight := cxTextHeight(HeaderParams.Font) + 5;
FMonthSize.cx := (2 * FSideWidth + 7 * FColWidth);
FMonthSize.cy := (FHeaderHeight + FDayCaptionsHeight + 6 * FRowHeight + 1);
end;
procedure TcxSchedulerDateNavigatorViewInfo.DestroyMonthViewInfoList;
var
I: Integer;
begin
for I := 0 to FMonthViewInfoList.Count - 1 do
TcxSchedulerDateNavigatorMonthViewInfo(FMonthViewInfoList[I]).Free;
FreeAndNil(FMonthViewInfoList);
end;
function TcxSchedulerDateNavigatorViewInfo.GetMonthViewInfo(
ACol, ARow: Integer): TcxSchedulerDateNavigatorMonthViewInfo;
begin
if (ARow < 0) or (ARow >= RowCount) or (ACol < 0) or (ACol >= ColCount) then
Result := nil
else
Result := TcxSchedulerDateNavigatorMonthViewInfo(
FMonthViewInfoList[ARow * ColCount + ACol]);
end;
initialization
GetLocaleSettings;
end.