{********************************************************************} { } { 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 cxSchedulerCustomResourceView; {$I cxVer.inc} interface uses {$IFDEF DELPHI6} Types, {$ENDIF} Windows, Graphics, SysUtils, StdCtrls, Classes, Forms, Controls, Contnrs, cxClasses, cxGraphics, {$IFDEF DELPHI6} DateUtils, Variants, {$ENDIF} cxGeometry, Math, cxControls, cxStyles, cxEdit, cxContainer, cxSchedulerStorage, cxSchedulerUtils, cxSchedulerCustomControls, cxLookAndFeelPainters, cxDateUtils, ImgList, cxEditUtils, cxSchedulerStrs, cxLookAndFeels; const // default values cxTimeLineWidth: Integer = 7; cxEventImagesOffset = 1; cxEventBorderWidth = 1; cxHitDelta: Integer = 4; // hittest constants htcButton = $3; htcContainer = $4; htcTimeRuler = $5; htcTimeZoneLabel = $6; htcContent = $7; htcDayHeader = $8; htcGroupSeparator = $9; htcResourceHeader = $10; htcNavigationButton = $16; type TcxSchedulerCustomViewInfoItem = class; TcxSchedulerCustomResourceViewViewInfo = class; TcxSchedulerCustomResourceViewHitTest = class; TcxSchedulerBackgroundCellViewInfo = class; TcxSchedulerContentCellViewInfo = class; TcxSchedulerDayHeaderCellViewInfo = class; TcxSchedulerEventCellViewInfo = class; TcxSchedulerExternalPainter = class; TcxSchedulerGroupSeparatorCellViewInfo = class; TcxSchedulerHeaderCellViewInfo = class; TcxSchedulerMoreEventsButtonViewInfo = class; TcxSchedulerResourceViewInfo = class; TcxCustomResourceViewAdapter = class; TcxSchedulerEventLayoutBuilder = class; TcxSchedulerEventImages = class; TcxSchedulerContentNavigationButtonViewInfo = class; TcxSchedulerCachedImage = class; TcxSchedulerContentNavigationButtonKind = (nbkPrevious, nbkNext); TcxSchedulerColumnPositionInResource = (cprIndefinite, cprFirst, cprLast, cprSingle); // custom draw event types definition TcxSchedulerCustomDrawBackgroundEvent = procedure(Sender: TObject; ACanvas: TcxCanvas; AViewInfo: TcxSchedulerBackgroundCellViewInfo; var ADone: Boolean) of object; TcxSchedulerCustomDrawButtonEvent = procedure(Sender: TObject; ACanvas: TcxCanvas; AViewInfo: TcxSchedulerMoreEventsButtonViewInfo; var ADone: Boolean) of object; TcxSchedulerCustomDrawDayHeaderEvent = procedure(Sender: TObject; ACanvas: TcxCanvas; AViewInfo: TcxSchedulerDayHeaderCellViewInfo; var ADone: Boolean) of object; TcxSchedulerCustomDrawNavigationButtonEvent = procedure(Sender: TObject; ACanvas: TcxCanvas; AViewInfo: TcxSchedulerContentNavigationButtonViewInfo; var ADone: Boolean) of object; TcxSchedulerCustomDrawResourceHeaderEvent = procedure(Sender: TObject; ACanvas: TcxCanvas; AViewInfo: TcxSchedulerHeaderCellViewInfo; var ADone: Boolean) of object; TcxSchedulerCustomDrawContentEvent = procedure(Sender: TObject; ACanvas: TcxCanvas; AViewInfo: TcxSchedulerContentCellViewInfo; var ADone: Boolean) of object; TcxSchedulerCustomDrawEventEvent = procedure(Sender: TObject; ACanvas: TcxCanvas; AViewInfo: TcxSchedulerEventCellViewInfo; var ADone: Boolean) of object; TcxSchedulerCustomDrawGroupSeparatorEvent = procedure(Sender: TObject; ACanvas: TcxCanvas; AViewInfo: TcxSchedulerGroupSeparatorCellViewInfo; var ADone: Boolean) of object; { IcxSchedulerCommonViewItemsPainter } IcxSchedulerCommonViewItemsPainter = interface ['{0702AB17-C2F1-479D-B809-C3B972F8A334}'] procedure DoCustomDrawBackground( AViewInfo: TcxSchedulerBackgroundCellViewInfo; var ADone: Boolean); procedure DoCustomDrawButton( AViewInfo: TcxSchedulerMoreEventsButtonViewInfo; var ADone: Boolean); procedure DoCustomDrawContent( AViewInfo: TcxSchedulerContentCellViewInfo; var ADone: Boolean); procedure DoCustomDrawDayHeader( AViewInfo: TcxSchedulerDayHeaderCellViewInfo; var ADone: Boolean); procedure DoCustomDrawEvent( AViewInfo: TcxSchedulerEventCellViewInfo; var ADone: Boolean); procedure DoCustomDrawGroupSeparator( AViewInfo: TcxSchedulerGroupSeparatorCellViewInfo; var ADone: Boolean); procedure DoCustomDrawNavigationButton( AViewInfo: TcxSchedulerContentNavigationButtonViewInfo; var ADone: Boolean); procedure DoCustomDrawResourceHeader( AViewInfo: TcxSchedulerHeaderCellViewInfo; var ADone: Boolean); //cached paint function HasCustomDrawGroupSeparator: Boolean; function HasCustomDrawResourceHeader: Boolean; end; { IcxSchedulerEventImages } IcxSchedulerEventImages = interface ['{4C5A8F8B-5356-4D2B-9972-507A7D60954A}'] procedure DoInitEventImages(AEvent: TcxSchedulerControlEvent; AImages: TcxSchedulerEventImages); function GetImages: TCustomImageList; function SupportEventImages: Boolean; end; { TcxSchedulerViewInfoCellList } TcxSchedulerCustomDrawItemProc = procedure( AItem: TcxSchedulerCustomViewInfoItem; var ADone: Boolean) of object; TcxSchedulerViewInfoCellList = class(TList) private function GetItem(AIndex: Integer): TcxSchedulerCustomViewInfoItem; public function CalculateHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest): Boolean; procedure Clear; override; procedure Draw(ACanvas: TcxCanvas; ADrawItemProc: TcxSchedulerCustomDrawItemProc); property Items[Index: Integer]: TcxSchedulerCustomViewInfoItem read GetItem; default; end; { TcxSchedulerCustomViewInfoItem } TcxSchedulerCustomViewInfoItem = class private FCache: TcxSchedulerCachedImage; function GetBitmap: TBitmap; function GetColor: TColor; function GetDateTimeHelper: TcxSchedulerDateTimeHelperClass; function GetHeight: Integer; function GetPainterHelper: TcxSchedulerPainterHelperClass; function GetTextColor: TColor; function GetWidth: Integer; procedure SetBitmap(AValue: TBitmap); procedure SetColor(AValue: TColor); procedure SetTextColor(AValue: TColor); protected FBackgroundDrawing: Boolean; FBorders: TcxBorders; FBounds: TRect; FCanvas: TcxCanvas; FClipRect: TRect; FClipRgn: TcxRegion; FClipRef: Integer; FDateTime: TDateTime; FDayBorderColor: TColor; FDisplayText: string; FExternalPainter: TcxSchedulerExternalPainter; FHasClipping: Boolean; FPainter: TcxCustomLookAndFeelPainterClass; FSavedClipRgn: TcxRegion; FTransparent: Boolean; FViewParams: TcxViewParams; FVisible: Boolean; procedure CalculateCellBounds(const ABounds, AVisibleRect: TRect); procedure ClippingCreate(AHasClipping: Boolean); virtual; procedure ClippingRestore; procedure DoDraw; virtual; abstract; function DrawBackground(ACanvas: TcxCanvas; const ABounds: TRect): Boolean; virtual; procedure DrawFrame(const ARect: TRect; ABorders: TcxBorders = []; ABorderColor: TColor = clDefault; ALineWidth: Integer = 1); procedure DrawRect(const ARect: TRect; ABorders: TcxBorders = []; ABorderColor: TColor = clDefault; ALineWidth: Integer = 1); procedure DrawText(const ARect: TRect; const AText: string; AFlags: Integer; AFont: TFont = nil; AColor: TColor = clDefault); function GetFont: TFont; virtual; function GetHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest; var ABreak: Boolean): Boolean; virtual; procedure InitHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest); virtual; // custom draw support procedure AfterCustomDraw(ACanvas: TcxCanvas); virtual; procedure BeforeCustomDraw(ACanvas: TcxCanvas); virtual; procedure UpdateCachedImage(const AViewParams: TcxViewParams); virtual; property Cache: TcxSchedulerCachedImage read FCache write FCache; // class item settings property DateTimeHelper: TcxSchedulerDateTimeHelperClass read GetDateTimeHelper; property DisplayText: string read FDisplayText write FDisplayText; property PainterHelper: TcxSchedulerPainterHelperClass read GetPainterHelper; property ExternalPainter: TcxSchedulerExternalPainter read FExternalPainter; public constructor Create(APainter: TcxCustomLookAndFeelPainterClass; const ABounds, AVisibleRect: TRect; const AViewParams: TcxViewParams); virtual; destructor Destroy; override; procedure Draw(ACanvas: TcxCanvas); virtual; property Borders: TcxBorders read FBorders write FBorders; property Bounds: TRect read FBounds; property Bitmap: TBitmap read GetBitmap write SetBitmap; property Canvas: TcxCanvas read FCanvas; property ClipRect: TRect read FClipRect; property Color: TColor read GetColor write SetColor; property Font: TFont read GetFont; property Height: Integer read GetHeight; property Painter: TcxCustomLookAndFeelPainterClass read FPainter; property TextColor: TColor read GetTextColor write SetTextColor; property Transparent: Boolean read FTransparent write FTransparent; property ViewParams: TcxViewParams read FViewParams; property Visible: Boolean read FVisible; property Width: Integer read GetWidth; end; { TcxSchedulerBackgroundCellViewInfo } TcxSchedulerBackgroundCellViewInfo = class(TcxSchedulerCustomViewInfoItem) protected procedure DoDraw; override; end; TcxSchedulerCustomViewInfoItemClass = class of TcxSchedulerCustomViewInfoItem; { TcxSchedulerCustomResourceViewInfoItem } TcxSchedulerCustomResourceViewInfoItem = class(TcxSchedulerCustomViewInfoItem) private FIsResourceAssigned: Boolean; FTimeFinish: TDateTime; FResource: TcxSchedulerResourceViewInfo; protected procedure InitHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest); override; property DateTime: TDateTime read FDateTime write FDateTime; property IsResourceAssigned: Boolean read FIsResourceAssigned; property Resource: TcxSchedulerResourceViewInfo read FResource write FResource; property TimeFinish: TDateTime read FTimeFinish; end; { TcxSchedulerHeaderCellViewInfo } TcxSchedulerHeaderCellViewInfo = class(TcxSchedulerCustomResourceViewInfoItem) protected DisplayBounds: TRect; FAlignHorz: TAlignment; FAlignVert: TcxAlignmentVert; FAutoHeight: Boolean; FButtonState: TcxButtonState; FDrawRotatedBackground: Boolean; FImageIndex: Integer; FImagePosition: TcxSchedulerHeaderImagePosition; FImages: TCustomImageList; FImageRectAssigned: Boolean; FImageRect: TRect; FIsResourceHeader: Boolean; FMultiLine: Boolean; FNeighbors: TcxNeighbors; FRotateBitmap: TcxBitmap; FRotateHeader: Boolean; FRotateText: Boolean; FSelected: Boolean; FSelectionBitmap: TcxBitmap; FSelectionColor: TColor; FSelectionRect: TRect; FSelectionTextColor: TColor; FShowEndEllipsis: Boolean; FTextRect: TRect; procedure CheckNeighbor(APrevCell: TcxSchedulerHeaderCellViewInfo); function CheckSelection: Boolean; virtual; procedure DoDraw; override; procedure DrawCaption(ACanvas: TcxCanvas = nil); procedure DrawHorizontalHeader; virtual; function DrawRotateBackground(ACanvas: TcxCanvas; const ABounds: TRect): Boolean; virtual; procedure DrawSelection; virtual; procedure DrawVerticalHeader; virtual; function GetTextOutcxFlags: Integer; function GetTextOutFlags: Integer; function HasImage: Boolean; procedure InitHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest); override; procedure TextOut(ACanvas: TcxCanvas; const AText: string; R: TRect); procedure ValidateSelection; public constructor Create(APainter: TcxCustomLookAndFeelPainterClass; const ABounds, AVisibleRect: TRect; const AViewParams: TcxViewParams); override; destructor Destroy; override; procedure Calculate(const AText: string); virtual; procedure CalculateImageLayout; property AlignHorz: TAlignment read FAlignHorz write FAlignHorz; property AlignVert: TcxAlignmentVert read FAlignVert write FAlignVert; property AutoHeight: Boolean read FAutoHeight; property DateTime: TDateTime read FDateTime write FDateTime; property ImageIndex: Integer read FImageIndex; property ImagePosition: TcxSchedulerHeaderImagePosition read FImagePosition; property ImageRect: TRect read FImageRect; property Images: TCustomImageList read FImages; property IsResourceHeader: Boolean read FIsResourceHeader; property MultiLine: Boolean read FMultiLine write FMultiLine; property Neighbors: TcxNeighbors read FNeighbors write FNeighbors; property RotateHeader: Boolean read FRotateHeader write FRotateHeader; property RotateText: Boolean read FRotateText write FRotateText; property Selected: Boolean read FSelected write FSelected; property SelectionColor: TColor read FSelectionColor write FSelectionColor; property SelectionTextColor: TColor read FSelectionTextColor write FSelectionTextColor; property ShowEndEllipsis: Boolean read FShowEndEllipsis write FShowEndEllipsis; property TextRect: TRect read FTextRect; property Bounds; property DisplayText; property Painter; property Resource; end; { TcxSchedulerDayHeaderCellViewInfo } TcxSchedulerDayHeaderCellViewInfo = class(TcxSchedulerHeaderCellViewInfo) private FCompressed: Boolean; protected function CheckSelection: Boolean; override; function DrawBackground(ACanvas: TcxCanvas; const ABounds: TRect): Boolean; override; procedure DrawHorizontalHeader; override; public function ConvertDateToDisplayText(AType: Integer = 0): Integer; virtual; property Compressed: Boolean read FCompressed write FCompressed; end; { TcxSchedulerWeekDayHeaderCellViewInfo } TcxSchedulerWeekDayHeaderCellViewInfo = class(TcxSchedulerDayHeaderCellViewInfo) protected function GetDayText(AType: Integer): string; procedure InitHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest); override; public function ConvertDateToDisplayText(AType: Integer = 0): Integer; override; end; { TcxSchedulerContainerCellViewInfo } TcxSchedulerContainerCellViewInfo = class(TcxSchedulerCustomResourceViewInfoItem) protected FLineCount: Integer; FSelected: Boolean; procedure DoDraw; override; procedure InitHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest); override; public property LineCount: Integer read FLineCount write FLineCount; property DateTime; property Resource; property Selected: Boolean read FSelected write FSelected; end; { TcxSchedulerTimeRulerCellViewInfo } TcxSchedulerTimeRulerCellViewInfo = class(TcxSchedulerCustomViewInfoItem) private FLastVisibleHour: Boolean; function GetBoundsRect(AType: Boolean): TRect; function GetDisplayText(AType: Boolean): string; function GetHasAdditionalTimeZone: Boolean; protected FAdditionalTimeZone: Integer; FAdditionalTimeZoneBiasDelta: Integer; FBounds: array[Boolean] of TRect; FDisplayTexts: array[Boolean] of string; FHour: Integer; FLargeFont: TFont; FLineCount: Integer; FShowMinutes: Boolean; FTimeZone: Integer; procedure CalculateDisplayInfo; procedure DoDraw; override; procedure DrawTimeZone(const ABounds: TRect; const AText: string; AIsCurrent: Boolean); virtual; procedure DrawTimeZoneLabel(const ABounds: TRect; const AText: string; ABorders: TcxBorders); virtual; procedure DrawCurrentTime(const AStart: TDateTime; ABounds: TRect); function GetAdditionalTime: TDateTime; function GetTimeDisplayText(const ATime: TDateTime): string; procedure InitHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest); override; // procedure AfterCustomDraw(ACanvas: TcxCanvas); override; public class function CalculateWidth(ATimeZoneCount, ALineCount: Integer; AFont1, AFont2: TFont): Integer; procedure Calculate(const ALabel1, ALabel2: string; ATimeZone, AAdditionalTimeZone: Integer; AAdditionalTimeZoneBiasDelta: Integer); overload; virtual; procedure Calculate(AHour, ALineCount: Integer; ATimeZone, AAdditionalTimeZone: Integer; ALargeFont: TFont; AAdditionalTimeZoneBiasDelta: Integer); overload; virtual; procedure SetBottom(AValue: Integer); property AdditionalTimeZone: Integer read FAdditionalTimeZone; property Bounds[ACurrentTimeZone: Boolean]: TRect read GetBoundsRect; property DisplayTexts[ACurrentTimeZone: Boolean]: string read GetDisplayText; property HasAdditionalTimeZone: Boolean read GetHasAdditionalTimeZone; property Hour: Integer read FHour; property LargeFont: TFont read FLargeFont; property LastVisibleHour: Boolean read FLastVisibleHour write FLastVisibleHour; property LineCount: Integer read FLineCount; property ShowMinutes: Boolean read FShowMinutes write FShowMinutes; property TimeZone: Integer read FTimeZone; end; { TcxSchedulerContentCellViewInfo } TcxSchedulerContentCellViewInfo = class(TcxSchedulerCustomResourceViewInfoItem) protected FBorderColor: TColor; FDontPrint: Boolean; FLineCount: Integer; FShowTimeLine: Boolean; FTimeEvent: TcxSchedulerEventCellViewInfo; FTimeLineBorders: TcxBorders; FTimeLineParams: TcxViewParams; procedure DoDraw; override; procedure InitHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest); override; public constructor Create(APainter: TcxCustomLookAndFeelPainterClass; const ABounds, AVisibleRect: TRect; const AViewParams: TcxViewParams); override; procedure SetTime(const ATimeStart, ATimeFinish: TDateTime); property BorderColor: TColor read FBorderColor write FBorderColor; property DontPrint: Boolean read FDontPrint write FDontPrint; property LineCount: Integer read FLineCount write FLineCount; property ShowTimeLine: Boolean read FShowTimeLine write FShowTimeLine; property TimeEvent: TcxSchedulerEventCellViewInfo read FTimeEvent write FTimeEvent; property TimeLineBorders: TcxBorders read FTimeLineBorders write FTimeLineBorders; property TimeLineParams: TcxViewParams read FTimeLineParams write FTimeLineParams; property TimeStart: TDateTime read FDateTime; property TimeFinish; property Resource; end; TcxSchedulerContentCellViewInfoClass = class of TcxSchedulerContentCellViewInfo; { TcxSchedulerBackgroundSlotCellViewInfo } TcxSchedulerBackgroundSlotCellViewInfo = class(TcxSchedulerContentCellViewInfo) protected procedure DoDraw; override; public property DisplayText; end; { TcxSchedulerMonthDayContentCellViewInfo } TcxSchedulerMonthDayContentCellViewInfo = class(TcxSchedulerContentCellViewInfo) private FSelected: Boolean; FSelectionColor: TColor; FSelectionTextColor: TColor; function GetIsToday: Boolean; procedure SetSmallTextFont(AFont: TFont); protected FTextRect: TRect; FSmallFont: Boolean; FSmallFontCreated: Boolean; FSmallTextFont: TFont; procedure DoDraw; override; function GetLongDisplayText: string; virtual; property IsToday: Boolean read GetIsToday; public destructor Destroy; override; procedure SetContentState(AsDayOfMonth: Boolean; ASelected: Boolean; ATextHeight: Integer; const ASelectionParams: TcxViewParams); function UpdateSelection(ASelected: Boolean): Boolean; property DisplayText; property SmallFont: Boolean read FSmallFont; property SmallTextFont: TFont read FSmallTextFont write SetSmallTextFont; property Selected: Boolean read FSelected; property SelectionColor: TColor read FSelectionColor write FSelectionColor; property SelectionTextColor: TColor read FSelectionTextColor write FSelectionTextColor; end; TcxSchedulerEventImagesLayout = (eilAuto, eilHorizontal, eilVertical); { TcxSchedulerEventViewData } TcxSchedulerEventViewData = class public AlwaysShowTime: Boolean; AutoHeight: Boolean; Bitmap: TBitmap; BorderColor: TColor; Bounds: TRect; Canvas: TcxCanvas; Caption: string; ContentFinish: TDateTime; ContentStart: TDateTime; DrawAsProgress: Boolean; DrawShadows: Boolean; EditProperties: TcxCustomEditProperties; EditStyle: TcxCustomEditStyle; Event: TcxSchedulerControlEvent; ExternalPainter: TcxSchedulerExternalPainter; GetEventHint: function(AEvent: TcxSchedulerControlEvent): string of object; ImagesLayout: TcxSchedulerEventImagesLayout; LineHeight: Integer; MaxHeight: Integer; Painter: TcxCustomLookAndFeelPainterClass; Resource: TcxSchedulerResourceViewInfo; ShowAllDayEventsInContentArea: Boolean; ShowFinishTime: Boolean; ShowStartTime: Boolean; ShowTimeAsClock: Boolean; ShowTimeLine: Boolean; StartLine: Integer; TaskComplete: Integer; TaskStatus: TcxSchedulerEventTaskStatus; TimeLineParams: TcxViewParams; ViewParams: TcxViewParams; VisibleRect: TRect; end; { TcxSchedulerEventCellViewInfo } TcxSchedulerEventCellViewInfo = class(TcxSchedulerCustomViewInfoItem) private FEventFinish: TDateTime; FEventStart: TDateTime; FIsHeaderEvent: Boolean; function CalculateMessageHeight(const R: TRect): Integer; function GetBorderColor: TColor; function GetCaption: string; function GetCaptionBounds(const R: TRect): TRect; function GetContentFinish: TDateTime; function GetContentStart: TDateTime; function GetEvent: TcxSchedulerControlEvent; function GetHint: string; function GetIsHeaderEvent: Boolean; function GetMessage: string; function GetResourceInfo: TcxSchedulerResourceViewInfo; function GetResourceItem: TcxSchedulerStorageResourceItem; function GetSelected: Boolean; function GetShowingState(AIndex: Integer): Boolean; procedure SetBorderColor(AValue: TColor); protected FCaptionRect: TRect; FEditViewInfo: TcxCustomEditViewInfo; FFinishRect: TRect; FFinishText: string; FHidden: Boolean; FImages: TcxSchedulerEventImages; FMessageRect: TRect; FHint: string; FHintAssigned: Boolean; FHintNeeded: Boolean; FHintNeededCalculated: Boolean; FSeparatorColor: TColor; FShowMessage: Boolean; FStartRect: TRect; FStartText: string; FEventTimeRect: TRect; FTimeLineRect: TRect; FIsDetailCaption: Boolean; FIsDetailInfo: Boolean; ViewData: TcxSchedulerEventViewData; procedure AssignEditStyle(AEditStyle: TcxCustomEditStyle); procedure BeforeCustomDraw(ACanvas: TcxCanvas); override; procedure Calculate; procedure CalculateBorders; virtual; procedure CalculateCaptions; virtual; procedure CalculateDetailInfo; virtual; procedure CalculateNeedHint; procedure CalculateEditViewInfo; procedure CalculateShowTimeAsClock; virtual; //items layout function CalculateAutoLayoutImagesAutoHeight(AVisibleImages: TList): Integer; function CalculateHorizontalImagesAutoHeight: Integer; procedure CalculateMessageAutoLayout(var AHeight: Integer); function CalculateVerticalImagesAutoHeight: Integer; procedure CalculateItemsLayout; virtual; procedure CalculateDetailViewEventLayout; procedure CalculateHeaderEventLayout; procedure CalculateNonDetailEventLayout; procedure CalculateEventTimeAsClockLayout(const ABounds: TRect; const ACaptionWidth, AImagesWidth: Integer; var ALeft: Integer); virtual; procedure CalculateEventTimeAsTextLayout(const ABounds: TRect; const ACaptionWidth, AImagesWidth: Integer; var ALeft: Integer); virtual; function CalculateNonDetailEventImages(const ACaptionWidth: Integer; out AImagesWidth: Integer): TRect; virtual; function CalculateSingleLineImages(const ABounds: TRect; ARightLimit: Integer = 0): Integer; function SetItemRect(AShowItem: Boolean; const ABounds: TRect; AVertOffset: Integer; var APos: Integer): TRect; //time visibility procedure CalculateEventTimeVisibility; virtual; procedure CalculateDetailEventTimeVisibility; virtual; procedure CalculateNonDetailEventTimeVisibility; virtual; procedure CalculateVisibility; virtual; function CanAutoHideStandardImages: Boolean; virtual; function CanShowHint: Boolean; virtual; procedure DoDraw; override; procedure DrawCaption; procedure DrawContent; virtual; procedure DrawImages; procedure DrawMessageSeparator; procedure DrawTime; function GetCaptionAutoHeight(const R: TRect): Integer; function GetEditingRect: TRect; virtual; function GetForceShowClockInHeaderEvent: Boolean; virtual; function GetHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest; var ABreak: Boolean): Boolean; override; function GetImagesBounds: TRect; function GetImagesVerticalOffset(AImageHeight: Integer; AIsAbsolute: Boolean): Integer; function GetMessageRect(const ACaptionRect: TRect; AHasImages: Boolean): TRect; function HasReminder: Boolean; virtual; procedure Initialize; virtual; //hittest procedure InitHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest); override; procedure InitHitTestForHorzEvent(AHitTest: TcxSchedulerCustomResourceViewHitTest); procedure InitStandardEventImages; function IsHorzSizing: Boolean; virtual; function IsNeedDrawTime: Boolean; virtual; function IsTimeLineVisible: Boolean; virtual; function TruncTime(const ATime: TDateTime): TDateTime; property EventFinish: TDateTime read FEventFinish; property EventStart: TDateTime read FEventStart; property IsHeaderEvent: Boolean read FIsHeaderEvent; property IsDetailCaption: Boolean read FIsDetailCaption; public constructor Create(AViewData: TcxSchedulerEventViewData); reintroduce; virtual; destructor Destroy; override; procedure Draw(ACanvas: TcxCanvas; ABitmap: TBitmap); reintroduce; overload; procedure DrawState(ACanvas: TcxCanvas; const ARect: TRect; ABorders: TcxBorders; ABorderColor: TColor); overload; function MeasureHeight(ACanvas: TcxCanvas): Integer; virtual; procedure MoveTo(X, Y: Integer); virtual; property BorderColor: TColor read GetBorderColor write SetBorderColor; property Caption: string read GetCaption; property CaptionRect: TRect read FCaptionRect; property ClipRect: TRect read FClipRect; property ClipRgn: TcxRegion read FClipRgn write FClipRgn; property ContentFinish: TDateTime read GetContentFinish; property ContentStart: TDateTime read GetContentStart; property EditingRect: TRect read GetEditingRect; property EditViewInfo: TcxCustomEditViewInfo read FEditViewInfo; property Event: TcxSchedulerControlEvent read GetEvent; property EventTimeRect: TRect read FEventTimeRect; property EventViewData: TcxSchedulerEventViewData read ViewData; property FinishRect: TRect read FFinishRect; property FinishText: string read FFinishText; property Hidden: Boolean read FHidden write FHidden; property Hint: string read GetHint; property Images: TcxSchedulerEventImages read FImages; property IsDetailInfo: Boolean read FIsDetailInfo; property Message: string read GetMessage; property MessageRect: TRect read FMessageRect; property ResourceInfo: TcxSchedulerResourceViewInfo read GetResourceInfo; property ResourceItem: TcxSchedulerStorageResourceItem read GetResourceItem; property Selected: Boolean read GetSelected; property SeparatorColor: TColor read FSeparatorColor write FSeparatorColor; property ShowFinishTime: Boolean index 0 read GetShowingState; property ShowMessage: Boolean read FShowMessage; property ShowStartTime: Boolean index 1 read GetShowingState; property ShowTimeAsClock: Boolean index 2 read GetShowingState; property ShowTimeLine: Boolean index 3 read GetShowingState; property StartRect: TRect read FStartRect; property StartText: string read FStartText; property TimeLineRect: TRect read FTimeLineRect write FTimeLineRect; property Visible: Boolean read FVisible; end; { TcxSchedulerMoreEventsButtonViewInfo } TcxSchedulerMoreEventsButtonClick = procedure (Sender: TcxSchedulerMoreEventsButtonViewInfo) of object; TcxSchedulerMoreEventsButtonViewInfoClass = class of TcxSchedulerMoreEventsButtonViewInfo; TcxSchedulerMoreEventsButtonViewInfo = class(TcxSchedulerCustomResourceViewInfoItem) protected FEvent: TcxSchedulerEvent; FIsDown: Boolean; FOnClick: TcxSchedulerMoreEventsButtonClick; procedure DoDraw; override; procedure InitHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest); override; property OnClick: TcxSchedulerMoreEventsButtonClick read FOnClick write FOnClick; public procedure Click; virtual; property Event: TcxSchedulerEvent read FEvent write FEvent; property IsDown: Boolean read FIsDown; property DateTime; property Resource; end; { TcxSchedulerContentNavigationButtonViewInfo } TcxSchedulerContentNavigationButtonClick = procedure (Sender: TcxSchedulerContentNavigationButtonViewInfo) of object; TcxSchedulerContentNavigationButtonViewInfo = class(TcxSchedulerCustomResourceViewInfoItem) private FArrowRect: TRect; FCaption: string; FHitTest: TcxSchedulerCustomResourceViewHitTest; FInterval: TDateTime; FKind: TcxSchedulerContentNavigationButtonKind; FOnClick: TcxSchedulerContentNavigationButtonClick; FTextRect: TRect; function GetEnabled: Boolean; protected procedure DoDraw; override; procedure InitHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest); override; property Enabled: Boolean read GetEnabled; property OnClick: TcxSchedulerContentNavigationButtonClick read FOnClick write FOnClick; public procedure Click; virtual; property ArrowRect: TRect read FArrowRect; property Caption: string read FCaption write FCaption; property Interval: TDateTime read FInterval write FInterval; property Kind: TcxSchedulerContentNavigationButtonKind read FKind write FKind; property TextRect: TRect read FTextRect; end; { TcxSchedulerGroupSeparatorCellViewInfo } TcxSchedulerGroupSeparatorCellViewInfo = class(TcxSchedulerCustomViewInfoItem) private FDrawRotatedBackground: Boolean; FRotated: Boolean; function DrawRotateBackground(ACanvas: TcxCanvas; const ABounds: TRect): Boolean; protected FRotateBitmap: TcxBitmap; procedure DoDraw; override; procedure InitHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest); override; public destructor Destroy; override; property Rotated: Boolean read FRotated write FRotated; end; { TcxSchedulerResourceViewInfo } TcxSchedulerResourceViewInfo = class protected FCaption: string; FColor: TColor; FImageIndex: Integer; FImagePosition: TcxSchedulerHeaderImagePosition; FImages: TCustomImageList; FResourceID: Variant; FResourceItem: TcxSchedulerStorageResourceItem; FTextRect: TRect; FVisibleEventCount: Integer; public constructor Create(AResource: TcxSchedulerStorageResourceItem); virtual; property Caption: string read FCaption; property Color: TColor read FColor; property ImageIndex: Integer read FImageIndex; property ImagePosition: TcxSchedulerHeaderImagePosition read FImagePosition; property Images: TCustomImageList read FImages; property ResourceID: Variant read FResourceID; property ResourceItem: TcxSchedulerStorageResourceItem read FResourceItem; property TextRect: TRect read FTextRect write FTextRect; property VisibleEventCount: Integer read FVisibleEventCount write FVisibleEventCount; end; { TcxSchedulerExternalPainter } TcxSchedulerExternalPainter = class(TInterfacedObject, IcxSchedulerCommonViewItemsPainter) private FCommonPainter: IcxSchedulerCommonViewItemsPainter; FPainter: TcxCustomLookAndFeelPainterClass; function GetPainterHelper: TcxSchedulerPainterHelperClass; protected property PainterHelper: TcxSchedulerPainterHelperClass read GetPainterHelper; public // IcxSchedulerCommonViewItemsPainter procedure DoCustomDrawBackground( AViewInfo: TcxSchedulerBackgroundCellViewInfo; var ADone: Boolean); virtual; procedure DoCustomDrawButton( AViewInfo: TcxSchedulerMoreEventsButtonViewInfo; var ADone: Boolean); virtual; procedure DoCustomDrawContent( AViewInfo: TcxSchedulerContentCellViewInfo; var ADone: Boolean); virtual; procedure DoCustomDrawDayHeader( AViewInfo: TcxSchedulerDayHeaderCellViewInfo; var ADone: Boolean); virtual; procedure DoCustomDrawEvent( AViewInfo: TcxSchedulerEventCellViewInfo; var ADone: Boolean); virtual; procedure DoCustomDrawGroupSeparator( AViewInfo: TcxSchedulerGroupSeparatorCellViewInfo; var ADone: Boolean); virtual; procedure DoCustomDrawNavigationButton( AViewInfo: TcxSchedulerContentNavigationButtonViewInfo; var ADone: Boolean); virtual; procedure DoCustomDrawResourceHeader( AViewInfo: TcxSchedulerHeaderCellViewInfo; var ADone: Boolean); virtual; function HasCustomDrawGroupSeparator: Boolean; function HasCustomDrawResourceHeader: Boolean; // function NeedDrawSelection: Boolean; virtual; function DrawCurrentTimeFirst: Boolean; virtual; // procedure DrawAllDayArea(ACanvas: TcxCanvas; const ARect: TRect; ABorderColor: TColor; ABorders: TcxBorders; AViewParams: TcxViewParams; ASelected: Boolean; ATransparent: Boolean); virtual; procedure DrawCurrentTime(ACanvas: TcxCanvas; AColor: TColor; AStart: TDateTime; ABounds: TRect); virtual; procedure DrawEvent(AViewInfo: TcxSchedulerEventCellViewInfo); virtual; procedure DrawEventAsProgress(AViewInfo: TcxSchedulerEventCellViewInfo); virtual; procedure DrawEventAsProgressText(AViewInfo: TcxSchedulerEventCellViewInfo; AContent: TRect; AProgressRect: TRect; const AText: string); virtual; procedure DrawTimeGridCurrentTime(ACanvas: TcxCanvas; AColor: TColor; const ATimeLineRect: TRect); virtual; procedure DrawTimeGridHeader(ACanvas: TcxCanvas; ABorderColor: TColor; AViewInfo: TcxSchedulerCustomViewInfoItem; ABorders: TcxBorders; ASelected: Boolean); virtual; procedure DrawTimeLine(ACanvas: TcxCanvas; const ARect: TRect; AViewParams: TcxViewParams; ABorders: TcxBorders; ABorderColor: TColor); virtual; procedure DrawTimeRulerBackground(ACanvas: TcxCanvas; const ARect: TRect; ABorders: TcxBorders; AViewParams: TcxViewParams; ATransparent: Boolean); virtual; procedure DrawShadow(ACanvas: TcxCanvas; const ARect, AVisibleRect: TRect; ABuffer: TBitmap); virtual; function MoreButtonSize(ASize: TSize): TSize; virtual; property Painter: TcxCustomLookAndFeelPainterClass read FPainter write FPainter; property CommonPainter: IcxSchedulerCommonViewItemsPainter read FCommonPainter write FCommonPainter; end; TcxSchedulerExternalPainterClass = class of TcxSchedulerExternalPainter; { TcxSchedulerCustomResourceView } TcxSchedulerCustomResourceView = class(TcxSchedulerCustomView) private FAdapter: TcxCustomResourceViewAdapter; FExternalPainter: TcxSchedulerExternalPainter; FGroupingKind: TcxSchedulerGroupingKind; FEventImagesLayout: TcxSchedulerEventImagesLayout; FShowEndTime: Boolean; FShowTimeAsClock: Boolean; FOnCustomDrawBackground: TcxSchedulerCustomDrawBackgroundEvent; FOnCustomDrawButton: TcxSchedulerCustomDrawButtonEvent; FOnCustomDrawContent: TcxSchedulerCustomDrawContentEvent; FOnCustomDrawDayHeader: TcxSchedulerCustomDrawDayHeaderEvent; FOnCustomDrawEvent: TcxSchedulerCustomDrawEventEvent; FOnCustomDrawGroupSeparator: TcxSchedulerCustomDrawGroupSeparatorEvent; FOnCustomDrawNavigationButton: TcxSchedulerCustomDrawNavigationButtonEvent; FOnCustomDrawResourceHeader: TcxSchedulerCustomDrawResourceHeaderEvent; procedure CheckSelectOnRightClick; function GetViewInfo: TcxSchedulerCustomResourceViewViewInfo; function IsRelevantSelection(out ATime: TDateTime; out AResource: TcxSchedulerStorageResourceItem): Boolean; procedure SetEventImagesLayout(const AValue: TcxSchedulerEventImagesLayout); procedure SetShowEndTime(const AValue: Boolean); procedure SetShowTimeAsClock(const AValue: Boolean); protected procedure CalculateViewInfo; override; procedure CheckGroupingKind(AStyle: TcxSchedulerGroupingKind; var ActuallyStyle: TcxSchedulerGroupingKind); virtual; procedure ClearCachedData; override; function CreateController: TcxSchedulerSubControlController; override; function CreateHitTest: TcxSchedulerSubControlHitTest; override; function CreateViewAdapter: TcxCustomResourceViewAdapter; virtual; procedure CreateSubClasses; override; procedure DestroySubClasses; override; procedure DoCustomDrawBackground( AViewInfo: TcxSchedulerBackgroundCellViewInfo; var ADone: Boolean); virtual; procedure DoCustomDrawButton( AViewInfo: TcxSchedulerMoreEventsButtonViewInfo; var ADone: Boolean); virtual; procedure DoCustomDrawContent( AViewInfo: TcxSchedulerContentCellViewInfo; var ADone: Boolean); virtual; procedure DoCustomDrawDayHeader( AViewInfo: TcxSchedulerDayHeaderCellViewInfo; var ADone: Boolean); virtual; procedure DoCustomDrawEvent( AViewInfo: TcxSchedulerEventCellViewInfo; var ADone: Boolean); virtual; procedure DoCustomDrawGroupSeparator( AViewInfo: TcxSchedulerGroupSeparatorCellViewInfo; var ADone: Boolean); virtual; procedure DoCustomDrawNavigationButton( AViewInfo: TcxSchedulerContentNavigationButtonViewInfo; var ADone: Boolean); virtual; procedure DoCustomDrawResourceHeader( AViewInfo: TcxSchedulerHeaderCellViewInfo; var ADone: Boolean); virtual; procedure DoLayoutChanged; override; procedure DoMouseDown(AButton: TMouseButton; AShift: TShiftState; X, Y: Integer); override; function DoShowPopupMenu(X, Y: Integer): Boolean; override; function FindEventViewInfo(AEvent: TcxSchedulerEvent; const ADate: TDateTime; AResource: TcxSchedulerStorageResourceItem; var AViewInfo: TcxSchedulerEventCellViewInfo): Boolean; function GetCommonViewItemsPainter: IcxSchedulerCommonViewItemsPainter; virtual; function GetCompressWeekEnd: Boolean; virtual; function GetEditRectForEvent(AEvent: TcxSchedulerControlEvent; const ADate: TDateTime; AResource: TcxSchedulerStorageResourceItem): TRect; override; function GetEventHintText(AEvent: TcxSchedulerControlEvent): string; override; function GetEventVisibility(AEvent: TcxSchedulerControlEvent): Boolean; override; function GetGroupingKind: TcxSchedulerGroupingKind; override; function HasCustomDrawGroupSeparator: Boolean; function HasCustomDrawResourceHeader: Boolean; procedure InitScrollBarsParameters; override; function IsShowResources: Boolean; override; procedure LookAndFeelChanged(Sender: TcxLookAndFeel; AChangedValues: TcxLookAndFeelValues); override; procedure Scroll(AScrollBarKind: TScrollBarKind; AScrollCode: TScrollCode; var AScrollPos: Integer); override; procedure SetGroupingKind(AValue: TcxSchedulerGroupingKind); virtual; property Adapter: TcxCustomResourceViewAdapter read FAdapter write FAdapter; property EventImagesLayout: TcxSchedulerEventImagesLayout read FEventImagesLayout write SetEventImagesLayout; property ExternalPainter: TcxSchedulerExternalPainter read FExternalPainter; property ShowEndTime: Boolean read FShowEndTime write SetShowEndTime default True; property ShowTimeAsClock: Boolean read FShowTimeAsClock write SetShowTimeAsClock default False; property ViewInfo: TcxSchedulerCustomResourceViewViewInfo read GetViewInfo; property OnCustomDrawBackground: TcxSchedulerCustomDrawBackgroundEvent read FOnCustomDrawBackground write FOnCustomDrawBackground; property OnCustomDrawButton: TcxSchedulerCustomDrawButtonEvent read FOnCustomDrawButton write FOnCustomDrawButton; property OnCustomDrawContent: TcxSchedulerCustomDrawContentEvent read FOnCustomDrawContent write FOnCustomDrawContent; property OnCustomDrawDayHeader: TcxSchedulerCustomDrawDayHeaderEvent read FOnCustomDrawDayHeader write FOnCustomDrawDayHeader; property OnCustomDrawEvent: TcxSchedulerCustomDrawEventEvent read FOnCustomDrawEvent write FOnCustomDrawEvent; property OnCustomDrawGroupSeparator: TcxSchedulerCustomDrawGroupSeparatorEvent read FOnCustomDrawGroupSeparator write FOnCustomDrawGroupSeparator; property OnCustomDrawNavigationButton: TcxSchedulerCustomDrawNavigationButtonEvent read FOnCustomDrawNavigationButton write FOnCustomDrawNavigationButton; property OnCustomDrawResourceHeader: TcxSchedulerCustomDrawResourceHeaderEvent read FOnCustomDrawResourceHeader write FOnCustomDrawResourceHeader; public constructor Create(AOwner: TcxCustomScheduler); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; procedure InitializePainter; virtual; procedure FinilizePainter; virtual; property GroupingKind: TcxSchedulerGroupingKind read FGroupingKind write SetGroupingKind default gkDefault; end; { TcxCustomResourceViewAdapter } TcxCustomResourceViewAdapter = class(TcxIUnknownObject) private FView: TcxSchedulerCustomResourceView; function GetCells: TcxObjectList; function GetContentLineHeight: Integer; function GetPainterHelper: TcxSchedulerPainterHelperClass; function GetResourceNavigator: TcxSchedulerResourceNavigator; function GetResources: TcxSchedulerStorageResourceItems; function GetScheduler: TcxCustomScheduler; function GetViewInfo: TcxSchedulerCustomResourceViewViewInfo; protected function CanCalculate: Boolean; virtual; function GetActualStart: TDateTime; virtual; function GetActualFinish: TDateTime; virtual; function GetCompressWeekends: Boolean; virtual; function GetDontPrintFreeTime: Boolean; virtual; function GetDontPrintWeekEnds: Boolean; virtual; function GetHideSelection: Boolean; virtual; function GetIsPrinting: Boolean; virtual; function GetPageBounds: TRect; virtual; function GetPagesPerWeek: Byte; virtual; function GetPrimaryPage: Boolean; virtual; function GetPrintExactlyOneMonth: Boolean; virtual; function GetPrintRange(Index: Integer): TDateTime; virtual; function GetStylesAdapter: IcxSchedulerStylesAdapter; virtual; function GetView: TcxSchedulerCustomResourceView; virtual; procedure AfterCalculatePage; virtual; procedure BeforeCalculatePage; virtual; procedure DoInitialize(var ASelectedDays: TcxSchedulerDateList; var AEvents: TcxSchedulerCachedEventList); virtual; function GetPageHeaderText: string; virtual; procedure Store; virtual; procedure Restore; virtual; property Scheduler: TcxCustomScheduler read GetScheduler; property PainterHelper: TcxSchedulerPainterHelperClass read GetPainterHelper; property ResourceNavigator: TcxSchedulerResourceNavigator read GetResourceNavigator; property ViewInfo: TcxSchedulerCustomResourceViewViewInfo read GetViewInfo; public constructor Create(AView: TcxSchedulerCustomResourceView); virtual; procedure Calculate; overload; procedure GetPageResources(AResources: TcxObjectList); virtual; procedure GetPageDays(APageIndex: Integer; ADays: TcxSchedulerDateList); procedure Invalidate; virtual; property ActualStart: TDateTime read GetActualStart; property ActualFinish: TDateTime read GetActualFinish; property Cells: TcxObjectList read GetCells; property ContentLineHeight: Integer read GetContentLineHeight; property DontPrintFreeTime: Boolean read GetDontPrintFreeTime; property DontPrintWeekEnd: Boolean read GetDontPrintWeekEnds; property IsPrinting: Boolean read GetIsPrinting; property PagesPerWeek: Byte read GetPagesPerWeek; property PrintExactlyOneMonth: Boolean read GetPrintExactlyOneMonth; property PrintFrom: TDateTime index 0 read GetPrintRange; property PrintTo: TDateTime index 1 read GetPrintRange; property Resources: TcxSchedulerStorageResourceItems read GetResources; property StylesAdapter: IcxSchedulerStylesAdapter read GetStylesAdapter; property View: TcxSchedulerCustomResourceView read GetView write FView; end; TcxCustomResourceViewAdapterClass = class of TcxCustomResourceViewAdapter; { TcxSchedulerEventImages } TcxSchedulerEventImageType = (eitReminder, eitRecurrence, eitCustomOccurrence, eitCustom); { TcxSchedulerEventImageItem } TcxSchedulerEventImageItem = class(TCollectionItem) private FAutoHide: Boolean; FImageType: TcxSchedulerEventImageType; FImageIndex: Integer; FImages: TCustomImageList; FVisible: Boolean; function GetHeight: Integer; function GetWidth: Integer; protected FBounds: TRect; FHidden: Boolean; public constructor Create(Collection: TCollection); override; property AutoHide: Boolean read FAutoHide write FAutoHide; property Bounds: TRect read FBounds; property Height: Integer read GetHeight; property ImageIndex: Integer read FImageIndex; property ImageType: TcxSchedulerEventImageType read FImageType; property Images: TCustomImageList read FImages; property Visible: Boolean read FVisible write FVisible; property Width: Integer read GetWidth; end; { TcxSchedulerEventImages } TcxSchedulerEventImages = class(TCollection) private FForceVisibleHeight: Integer; FForceVisibleWidth: Integer; FImages: TCustomImageList; FLayout: TcxSchedulerEventImagesLayout; FItemHeight: Integer; FItemWidth: Integer; FTotalVisibleHeight: Integer; FTotalVisibleWidth: Integer; FTotalVisibleImageCount: Integer; FVisibleImageCount: Integer; function GetImageItem(AIndex: Integer): TcxSchedulerEventImageItem; protected function Calculate(const R: TRect): Integer; procedure CalculateForCols(AVisibleImages: TList; const ATopLeft: TPoint; AColCount: Integer); function CalculateImages(const R: TRect): Integer; function CalculateSingleColumnImages(const R: TRect): Integer; function CalculateSingleLineImages(const R: TRect; ARightLimit: Integer = 0): Integer; function Offset(ADeltaX, ADeltaY: Integer): Integer; function CreateVisibleList: TList; procedure Init(AImages: TCustomImageList); procedure SetItemBounds(AItem: TcxSchedulerEventImageItem; ALeft, ATop: Integer); property ItemHeight: Integer read FItemHeight; property ItemWidth: Integer read FItemWidth; property ForceVisibleHeight: Integer read FForceVisibleHeight; property ForceVisibleWidth: Integer read FForceVisibleWidth; property TotalVisibleHeight: Integer read FTotalVisibleHeight; property TotalVisibleWidth: Integer read FTotalVisibleWidth; property TotalVisibleImageCount: Integer read FTotalVisibleImageCount; property VisibleImageCount: Integer read FVisibleImageCount; public constructor Create(ALayout: TcxSchedulerEventImagesLayout); function Add(AImageIndex: Integer; AutoHide: Boolean = True): TcxSchedulerEventImageItem; function AddStandardImage(AImageType: TcxSchedulerEventImageType; AutoHide: Boolean = True): TcxSchedulerEventImageItem; property Items[Index: Integer]: TcxSchedulerEventImageItem read GetImageItem; default; property Layout: TcxSchedulerEventImagesLayout read FLayout write FLayout; end; { TcxSchedulerCachedImage } TcxSchedulerCachedImage = class private FImage: TcxBitmap; public constructor Create; destructor Destroy; override; procedure Invalidate; function IsValid(AItem: TcxSchedulerCustomViewInfoItem): Boolean; virtual; procedure Update(AItem: TcxSchedulerCustomViewInfoItem); virtual; property Image: TcxBitmap read FImage; end; { TcxSchedulerResourceHeaderCachedImage } TcxSchedulerResourceHeaderCachedImage = class(TcxSchedulerCachedImage) private FDisplayText: string; FDateTime: TDateTime; FResourceItem: TcxSchedulerStorageResourceItem; public function IsValid(AItem: TcxSchedulerCustomViewInfoItem): Boolean; override; procedure Update(AItem: TcxSchedulerCustomViewInfoItem); override; end; { TcxSchedulerResourceHeaderCachedImageList } TcxSchedulerResourceHeaderCachedImageList = class(TcxObjectList) public function Add(AItem: TcxSchedulerHeaderCellViewInfo): TcxSchedulerResourceHeaderCachedImage; function GetCacheForItem(AItem: TcxSchedulerHeaderCellViewInfo): TcxSchedulerResourceHeaderCachedImage; end; { TcxSchedulerImageCacheManager } TcxSchedulerImageCacheManager = class private FResourceHeaders: TcxSchedulerResourceHeaderCachedImageList; FSeparator: TcxSchedulerCachedImage; public constructor Create; virtual; destructor Destroy; override; procedure Invalidate; virtual; property ResourceHeaders: TcxSchedulerResourceHeaderCachedImageList read FResourceHeaders; property Separator: TcxSchedulerCachedImage read FSeparator; end; { TcxSchedulerCustomResourceViewViewInfo } TcxSchedulerCustomResourceViewViewInfo = class(TcxSchedulerCustomViewViewInfo, IcxMouseTrackingCaller ) private FButtonBounds: TRect; FButtonTextRect: TRect; FButtonArrowRect: TRect; FContentNavigationIntervals: TObjectList; FContentNavigationWithoutResources: Boolean; FEventWithoutResourceCount: Integer; FImageCacheManager: TcxSchedulerImageCacheManager; FHotContentNavigationButton: TcxSchedulerContentNavigationButtonViewInfo; procedure AddContentNavigationIntervalItem(AResourceIndex: Variant); procedure ClearContentNavigationIntervals; function GetClones: TcxSchedulerEventList; function GetCorrectColumnHeight(AColumnRect: TRect): Integer; function GetDay(AIndex: Integer): TDateTime; function GetDayCount: Integer; function GetShowEventsWithoutResource: Boolean; function GetGroupByDate: Boolean; function GetGroupByResource: Boolean; function GetGroupingKind: TcxSchedulerGroupingKind; function GetHasSeparator: Boolean; function GetHasVisibleBounds: Boolean; function GetHiddenSelection: Boolean; function GetMinResourceHeight: Integer; function GetMoreEventsButtonCount(AResourceIndex: Integer): Integer; function GetResource(AIndex: Integer): TcxSchedulerResourceViewInfo; function GetResourceCaption(AIndex: Integer): string; function GetResourceCount: Integer; function GetResourceHeaders: TcxSchedulerResourceHeaders; function GetPrintRange(Index: Integer): TDateTime; function GetSeparatorWidth: Integer; function GetView: TcxSchedulerCustomResourceView; function IsDrawContentNavigationButtons: Boolean; procedure SetContentNavigationButtonsIntervals; procedure SetHitContentNavigationButton(AButton: TcxSchedulerContentNavigationButtonViewInfo; AHitTest: TcxSchedulerCustomResourceViewHitTest); procedure SetHotContentNavigationButton(AButton: TcxSchedulerContentNavigationButtonViewInfo); protected FAdapter: TcxCustomResourceViewAdapter; FButtons: TcxSchedulerViewInfoCellList; FCanSelected: Boolean; FCells: TcxObjectList; FContentCells: TcxSchedulerViewInfoCellList; FContentFontHeight: Integer; FContentLineHeight: Integer; FDayBorderColor: TColor; FDayHeaderCells: TcxSchedulerViewInfoCellList; FDayHeaderHeight: Integer; FEventCells: TcxSchedulerViewInfoCellList; FEventImages: IcxSchedulerEventImages; FGroupSeparatorCells: TcxSchedulerViewInfoCellList; FGroupSeparatorParams: TcxViewParams; FGroupingKind: TcxSchedulerGroupingKind; FHasVisibleBounds: Boolean; FHeaderContainerCells: TcxSchedulerViewInfoCellList; FHideClones: Boolean; FHideSelection: Boolean; FHideSource: Boolean; FNavigationButtons: TcxSchedulerViewInfoCellList; FResources: TcxObjectList; FResourceBounds: array of TRect; FResourceHeaderCells: TcxSchedulerViewInfoCellList; FResourceHeaderHeight: Integer; FResourceImages: TCustomImageList; FSelectionParams: TcxViewParams; FSelStart: TDateTime; FSelFinish: TDateTime; FSelResource: TcxSchedulerResourceViewInfo; FStylesAdapter: IcxSchedulerStylesAdapter; FTimeLineParams: TcxViewParams; // for page splitting FPageBounds: TRect; FPagesPerWeek: Byte; FPrimaryPage: Boolean; FPrintWeekEnds: Boolean; FUseResourceImages: Boolean; ScreenCanvas: TcxCanvas; // IcxMouseTrackingCaller procedure MouseLeave; virtual; function AddBackgroundSlot(const ABounds: TRect; ABorders: TcxBorders; const AText: string = ''): TcxSchedulerBackgroundSlotCellViewInfo; virtual; function AddButton(ABounds: TRect; const ADateTime: TDateTime; AIsDown: Boolean; AEvent: TcxSchedulerEvent): TcxSchedulerMoreEventsButtonViewInfo; virtual; function AddContentCell(const ARect: TRect; const AStart, AFinish: TDateTime; AResourceIndex: Integer): TcxSchedulerContentCellViewInfo; virtual; procedure AddContentNavigationButton(const AColumnRect: TRect; AResourceIndex: Integer; AColumnPositionInResource: TcxSchedulerColumnPositionInResource); function AddDayHeader(const ADate: TDateTime; const ABounds: TRect; AResourceIndex: Integer): TcxSchedulerDayHeaderCellViewInfo; overload; virtual; function AddDayHeader(const ADate: TDateTime; ATop, ALeft, ARight: Integer; AResourceIndex: Integer): TcxSchedulerDayHeaderCellViewInfo; overload; function AddEventCell( AViewData: TcxSchedulerEventViewData; AImmediateCalculate: Boolean = True): TcxSchedulerEventCellViewInfo; virtual; function AddGroupHorzSeparator(APos: Integer): TcxSchedulerGroupSeparatorCellViewInfo; virtual; function AddGroupSeparator(const ABounds: TRect): TcxSchedulerGroupSeparatorCellViewInfo; virtual; function AddGroupVertSeparator(APos: Integer): TcxSchedulerGroupSeparatorCellViewInfo; virtual; procedure AddResourceBounds(AResourceIndex: Integer; const ABounds: TRect); function AddResourceHeader(const AIndex: Integer; const ABounds: TRect): TcxSchedulerHeaderCellViewInfo; virtual; procedure AfterCalculate; override; function AreThereEventsInVisibleInterval(AResourceIndex: Integer): Boolean; procedure AssignResourceID(ACell: TcxSchedulerCustomResourceViewInfoItem; AIndex: Integer); procedure CalculateContentNavigationButtons; virtual; procedure CalculateMetrics; virtual; procedure CalculateNavigationButtonParams(AColumnRect: TRect; AKind: TcxSchedulerContentNavigationButtonKind; out AButtonWidth: Integer); procedure CalculateResourceHeadersAutoHeight(AWidth: Integer); virtual; function CalculateResourceHeaderWidth: Integer; virtual; function CanCalculateNavigationButtons: Boolean; virtual; function CanCacheGroupSeparator(AItem: TcxSchedulerGroupSeparatorCellViewInfo): Boolean; virtual; function CanCacheResourceHeader(AItem: TcxSchedulerHeaderCellViewInfo): Boolean; virtual; procedure Clear; override; procedure ClearResourceBounds; function ContentCellClass: TcxSchedulerContentCellViewInfoClass; virtual; procedure CreateCellInstance(AClass: TcxSchedulerCustomViewInfoItemClass; const ABounds: TRect; const AViewParams: TcxViewParams; var Instance); overload; procedure CreateCellInstance(AClass: TcxSchedulerCustomViewInfoItemClass; const ABounds, AVisibleBounds: TRect; const AViewParams: TcxViewParams; var Instance); overload; function CreateEventViewData(AEvent: TcxSchedulerControlEvent; const ABounds: TRect; const AStart, AFinish: TDateTime; AResource: TcxSchedulerResourceViewInfo): TcxSchedulerEventViewData; virtual; function CreateEventCellViewInfo(AViewData: TcxSchedulerEventViewData): TcxSchedulerEventCellViewInfo; virtual; function CreateImageCacheManager: TcxSchedulerImageCacheManager; virtual; procedure DoCalculate; override; procedure DoContentNavigationButtonClick(Sender: TcxSchedulerContentNavigationButtonViewInfo); virtual; procedure DoMoreEventsButtonClick(Sender: TcxSchedulerMoreEventsButtonViewInfo); virtual; procedure ExtractResources; virtual; function GetBounds: TRect; override; function GetContentNavigationInterval(AContentNavigationButton: TcxSchedulerContentNavigationButtonViewInfo): TDateTime; function GetContentParams(const ATime: TDateTime; AResource: TcxSchedulerResourceViewInfo): TcxViewParams; virtual; function GetDayHeaderHeight: Integer; virtual; function GetEventForResourceCount(AResourceIndex: Integer; out AResourceID: Variant): Integer; virtual; function GetEventWithoutResourceCount: Integer; virtual; function GetMoreEventButtonClass: TcxSchedulerMoreEventsButtonViewInfoClass; virtual; function GetResourceHeaderWidth: Integer; function GetResourceImagesSize: TSize; virtual; function GetResourcesContentWidth: Integer; virtual; function GetSelectionParams(const AParams: TcxViewParams): TcxViewParams; function GetSeparatorCount: Integer; virtual; function GetTimeLineParams: TcxViewParams; virtual; function GetFontHeight(AStyle: TcxStyle): Integer; overload; function GetFontHeight(const AParams: TcxViewParams): Integer; overload; function GetPageHeaderText: string; virtual; function GetResourceItemByIndex(AIndex: Integer): TcxSchedulerStorageResourceItem; function GetResourceViewInfoByItem(AItem: TcxSchedulerStorageResourceItem; var ResourceViewInfoIndex: Integer): TcxSchedulerResourceViewInfo; function GetStartDate(Index: Integer): TDateTime; virtual; function HasStorage: Boolean; function HasVisibleEvents: Boolean; virtual; procedure HideCloneEventsOnDragDrop; procedure HideSourceEventsOnDragDrop; procedure HotTrackNavigationButtons(AHitTest: TcxSchedulerCustomResourceViewHitTest); function IsTimeSelected(ATime: TDateTime; AResource: TObject): Boolean; virtual; function IsValidNavigationButtonsPlace(const AResourceRect: TRect): Boolean; procedure MakeTimeVisible(const ATime: TDateTime); virtual; function NavigationButtonOffset(AKind: TcxSchedulerContentNavigationButtonKind; AResourceIndex: Integer): Integer; virtual; procedure OnContentNavigationButtonClick(Sender: TcxSchedulerContentNavigationButtonViewInfo); procedure OnMoreEventsButtonClick(Sender: TcxSchedulerMoreEventsButtonViewInfo); procedure ProcessDateToDisplayText(ArrangeByType: Boolean = False); virtual; procedure ProcessCheckBorders(AList: TcxSchedulerViewInfoCellList; AHasCommonArea: Boolean; ANeighbors: TcxNeighbors = []; AExcludeBorders: TcxBorders = []; AAddBorders: TcxBorders = []); procedure ReturnVisibleInterval(var AStart, AEnd: TDateTime); virtual; function SetAdapter(Adapter: TcxCustomResourceViewAdapter): TcxCustomResourceViewAdapter; procedure SetResourceHasVisibleEvent(AEvent: TcxSchedulerControlEvent); procedure SetResourceTextRect(AResource: TcxSchedulerStorageResourceItem; const ARect: TRect); property HotContentNavigationButton: TcxSchedulerContentNavigationButtonViewInfo read FHotContentNavigationButton write SetHotContentNavigationButton; property ImageCacheManager: TcxSchedulerImageCacheManager read FImageCacheManager; property StartDates[AnIndex: Integer]: TDateTime read GetStartDate; property View: TcxSchedulerCustomResourceView read GetView; public constructor Create(AOwner: TcxSchedulerSubControl); override; destructor Destroy; override; procedure Calculate; override; procedure CalculateHitTest(AHitTest: TcxSchedulerCustomResourceViewHitTest); virtual; procedure InitScrollBarsParameters; virtual; procedure ScrollHorizontal(AScrollCode: TScrollCode; var AScrollPos: Integer); virtual; procedure ScrollVertical(AScrollCode: TScrollCode; var AScrollPos: Integer); virtual; procedure SetEventsVisibility(AShowSources, AShowClones: Boolean; AForceRepaint: Boolean = False); override; property Adapter: TcxCustomResourceViewAdapter read FAdapter; property Buttons: TcxSchedulerViewInfoCellList read FButtons; property CanSelected: Boolean read FCanSelected; property Clones: TcxSchedulerEventList read GetClones; property ContentCells: TcxSchedulerViewInfoCellList read FContentCells; property ContentLineHeight: Integer read FContentLineHeight; property DayCount: Integer read GetDayCount; property DayHeaderCells: TcxSchedulerViewInfoCellList read FDayHeaderCells; property DayHeaderHeight: Integer read GetDayHeaderHeight; property Days[Index: Integer]: TDateTime read GetDay; property EventCells: TcxSchedulerViewInfoCellList read FEventCells; property ShowEventsWithoutResource: Boolean read GetShowEventsWithoutResource; property GroupByDate: Boolean read GetGroupByDate; property GroupByResource: Boolean read GetGroupByResource; property GroupSeparatorCells: TcxSchedulerViewInfoCellList read FGroupSeparatorCells; property GroupSeparatorParams: TcxViewParams read FGroupSeparatorParams; property GroupingKind: TcxSchedulerGroupingKind read FGroupingKind; property HasSeparator: Boolean read GetHasSeparator; property HasVisibleBounds: Boolean read FHasVisibleBounds; property HeaderContainerCells: TcxSchedulerViewInfoCellList read FHeaderContainerCells; property HideSelection: Boolean read FHideSelection; property NavigationButtons: TcxSchedulerViewInfoCellList read FNavigationButtons; property PagesPerWeek: Byte read FPagesPerWeek; property PrimaryPage: Boolean read FPrimaryPage; property PrintFrom: TDateTime index 0 read GetPrintRange; property PrintTo: TDateTime index 1 read GetPrintRange; property PrintWeekEnds: Boolean read FPrintWeekEnds; property Resources[AIndex: Integer]: TcxSchedulerResourceViewInfo read GetResource; property ResourceCaptions[AIndex: Integer]: string read GetResourceCaption; property ResourceCount: Integer read GetResourceCount; property ResourceHeaders: TcxSchedulerResourceHeaders read GetResourceHeaders; property ResourceHeaderCells: TcxSchedulerViewInfoCellList read FResourceHeaderCells; property ResourceHeaderHeight: Integer read FResourceHeaderHeight; property ResourceImages: TCustomImageList read FResourceImages; property SelFinish: TDateTime read FSelFinish; property SelResource: TcxSchedulerResourceViewInfo read FSelResource; property SelStart: TDateTime read FSelStart; property SeparatorWidth: Integer read GetSeparatorWidth; property StylesAdapter: IcxSchedulerStylesAdapter read FStylesAdapter; property HiddenSelection: Boolean read GetHiddenSelection; property UseResourceImages: Boolean read FUseResourceImages; end; { TcxSchedulerCustomResourceViewNavigation } TcxSchedulerCustomResourceViewNavigation = class(TcxSchedulerViewNavigation) private function GetIsFirstResource: Boolean; function GetIsLastResource: Boolean; function GetGroupingKind: TcxSchedulerGroupingKind; function GetResourceObject: TcxSchedulerResourceViewinfo; function GetViewInfo: TcxSchedulerCustomResourceViewViewInfo; protected function GetNextResource(AGoToForward: Boolean): TcxSchedulerStorageResourceItem; function GetResourceItem: TcxSchedulerStorageResourceItem; override; function GetResourceFromViewInfo(AInfo: TcxSchedulerResourceViewInfo): TcxSchedulerStorageResourceItem; function RoundTime(const ADateTime: TDateTime): TDateTime; public procedure ValidateSelection(var ASelStart, ASelFinish: TDateTime; var AResource: TcxSchedulerStorageResourceItem); override; property IsFirstResource: Boolean read GetIsFirstResource; property IsLastResource: Boolean read GetIsLastResource; property GroupingKind: TcxSchedulerGroupingKind read GetGroupingKind; property ResourceItem: TcxSchedulerStorageResourceItem read GetResourceItem; property ResourceObject: TcxSchedulerResourceViewInfo read GetResourceObject; property ViewInfo: TcxSchedulerCustomResourceViewViewInfo read GetViewInfo; end; { TcxSchedulerCustomResourceViewController } TcxSchedulerCustomResourceViewController = class(TcxSchedulerViewController) private FCalculatedHintBounds: Boolean; FHintText: string; FNavigationButtonClicked: Boolean; function GetHintController: TcxSchedulerHintController; function GetHitTest: TcxSchedulerCustomResourceViewHitTest; function GetView: TcxSchedulerCustomResourceView; protected function CreateNavigation: TcxSchedulerViewNavigation; 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; // hint function GetDayHeaderDate: TDateTime; virtual; procedure InternalHideHint; procedure InternalShowHint(P: TPoint; const AHintText: string); function NeedShowDayHeaderHint: Boolean; virtual; function ShowHint: Boolean; virtual; procedure ShowDayHeaderHint; virtual; property HintController: TcxSchedulerHintController read GetHintController; property HitTest: TcxSchedulerCustomResourceViewHitTest read GetHitTest; property NavigationButtonClicked: Boolean read FNavigationButtonClicked write FNavigationButtonClicked; property View: TcxSchedulerCustomResourceView read GetView; end; { TcxSchedulerCustomResourceViewHitTest } TcxSchedulerCustomResourceViewHitTest = class(TcxSchedulerViewHitTest) private function GetContentCell: TcxSchedulerContentCellViewInfo; function GetHitContentNavigationButton: TcxSchedulerContentNavigationButtonViewInfo; function GetHeaderCell: TcxSchedulerHeaderCellViewInfo; function GetView: TcxSchedulerCustomResourceView; protected FButton: TcxSchedulerMoreEventsButtonViewInfo; FContentNavigationButton: TcxSchedulerContentNavigationButtonViewInfo; FDragKind: TcxEventDragKind; FEventCell: TcxSchedulerEventCellViewInfo; FHitObject: TObject; FTimeZone: Integer; function CanMoveEvent(AEvent: TcxSchedulerControlEvent): Boolean; virtual; function CanResizeEvent(AEvent: TcxSchedulerControlEvent): Boolean; virtual; procedure Clear; override; procedure DoCalculate; override; function GetHitEvent: TcxSchedulerControlEvent; override; procedure SetHitTime(AItemFlag: Integer; const ATime: TDateTime); virtual; procedure SetResource(AResource: TcxSchedulerResourceViewInfo); procedure ValidateDragKind; virtual; property View: TcxSchedulerCustomResourceView read GetView; property HitAtTimeZoneLabel: Boolean index htcTimeZoneLabel read GetBitState; property HitContentNavigationButton: TcxSchedulerContentNavigationButtonViewInfo read GetHitContentNavigationButton; property TimeZone: Integer read FTimeZone; public function GetDragKind: TcxEventDragKind; override; procedure SetDragKind(AValue: TcxEventDragKind); property Button: TcxSchedulerMoreEventsButtonViewInfo read FButton; property ContentCell: TcxSchedulerContentCellViewInfo read GetContentCell; property ContentNavigationButton: TcxSchedulerContentNavigationButtonViewInfo read FContentNavigationButton; property EventCell: TcxSchedulerEventCellViewInfo read FEventCell; property HeaderCell: TcxSchedulerHeaderCellViewInfo read GetHeaderCell; property HitAtButton: Boolean index htcButton read GetBitState; property HitAtContent: Boolean index htcContent read GetBitState; property HitAtContentNavigationButton: Boolean index htcNavigationButton read GetBitState; property HitAtDayHeader: Boolean index htcDayHeader read GetBitState; property HitAtGroupSeparator: Boolean index htcGroupSeparator read GetBitState; property HitAtResourceHeader: Boolean index htcResourceHeader read GetBitState; end; { TcxSchedulerCustomViewPainter } TcxSchedulerCustomViewPainter = class(TcxSchedulerSubControlPainter) private function GetView: TcxSchedulerCustomResourceView; protected FPainter: IcxSchedulerCommonViewItemsPainter; procedure DrawBackgroundCell(AItem: TcxSchedulerBackgroundCellViewInfo); virtual; procedure DrawButtonCell(AItem: TcxSchedulerCustomViewInfoItem; var ADone: Boolean); virtual; procedure DrawContentCell(AItem: TcxSchedulerCustomViewInfoItem; var ADone: Boolean); virtual; procedure DrawEventCell(AItem: TcxSchedulerCustomViewInfoItem; var ADone: Boolean); virtual; procedure DrawGroupSeparatorCell(AItem: TcxSchedulerCustomViewInfoItem; var ADone: Boolean); virtual; procedure DrawHeaderCell(AItem: TcxSchedulerCustomViewInfoItem; var ADone: Boolean); virtual; procedure DrawResourceHeaderCell(AItem: TcxSchedulerCustomViewInfoItem; var ADone: Boolean); virtual; public constructor Create(AOwner: TcxSchedulerSubControl); override; procedure InitializePainter; override; procedure Paint; override; property Painter: IcxSchedulerCommonViewItemsPainter read FPainter; property View: TcxSchedulerCustomResourceView read GetView; end; { TcxSchedulerEventPlace } TcxSchedulerEventPlace = class public ColFinish: Integer; ColStart: Integer; Resource: TObject; Data: TObject; Event: TcxSchedulerEvent; LineFinish: Integer; LineStart: Integer; procedure AlignPosition(APlace: TcxSchedulerEventPlace); function IntersectHorz(APlace: TcxSchedulerEventPlace): Boolean; function IntersectVert(APlace: TcxSchedulerEventPlace): Boolean; procedure LineStartToEvent; procedure ResetPosition; end; { TcxSchedulerEventLayoutBuilder } TcxSchedulerEventLayoutBuilderGetEventPlaceProc = function(Sender: TcxSchedulerEventLayoutBuilder; AEvent: TcxSchedulerControlEvent; out AStartCol, AFinishCol: Integer; out ALineCount: Integer): Boolean of object; TcxSchedulerEventLayoutBuilder = class private FEventPlaces: TcxObjectList; function GetEventPlace(AIndex: Integer): TcxSchedulerEventPlace; function GetEventPlaceCount: Integer; public constructor Create; virtual; destructor Destroy; override; function AddEventPlace(AEvent: TcxSchedulerEvent; AStartCol, AFinishCol: Integer; ALineCount: Integer = 1; AResource: TObject = nil): TcxSchedulerEventPlace; procedure Clear; procedure Calculate; virtual; procedure CalculateEx(AEventsList: TcxSchedulerFilteredEventList; APlaceInfoProc: TcxSchedulerEventLayoutBuilderGetEventPlaceProc); property EventPlaceCount: Integer read GetEventPlaceCount; property EventPlaces[Index: Integer]: TcxSchedulerEventPlace read GetEventPlace; property EventPlacesList: TcxObjectList read FEventPlaces; end; var ExternalPainterClass: TcxSchedulerExternalPainterClass = TcxSchedulerExternalPainter; function MakeTextOutcxFlags(AlignHorz: TAlignment; AlignVert: TcxAlignmentVert; AMultiline: Boolean = False): Integer; implementation uses cxDrawTextUtils, cxLibraryConsts, cxVariants, cxSchedulerDateNavigator, dxCore; type TcxCustomEditStyleAccess = class(TcxCustomEditStyle); TcxCustomSchedulerAccess = class(TcxCustomScheduler); TcxDateNavigatorAccess = class(TcxSchedulerDateNavigator); TcxSchedulerControlEventAccess = class(TcxSchedulerControlEvent); const ContentNavigationButtonWidth = 24; ContentNavigationButtonHeight = 172; ContentNavigationButtonReducedHeight = 32; MultiLines: array[Boolean] of Integer = (0, cxWordBreak or cxNoFullWidthCharBreak); cxDrawTextFlags: array[Boolean] of Cardinal = ( cxAlignLeft or cxAlignVCenter or cxSingleLine, cxAlignLeft or cxAlignTop or cxWordBreak or cxDontBreakChars or cxNoFullWidthCharBreak); function MakeTextOutcxFlags(AlignHorz: TAlignment; AlignVert: TcxAlignmentVert; AMultiline: Boolean = False): Integer; begin Result := cxAlignmentsHorz[AlignHorz] or cxDontBreakChars or cxAlignmentsVert[AlignVert] or MultiLines[AMultiline]; end; function MakeRect(ALeft, ATop: Integer; ASize: TSize): TRect; begin Result.Left := ALeft; Result.Top := ATop; Result.Right := ALeft + ASize.cx; Result.Bottom := ATop + ASize.cy; end; function GetTrueMultilineTextHeight(ACanvas: TcxCanvas; const S: string; ABounds: TRect): Integer; var ARowCount: Integer; ATextFlags: Cardinal; ATextParams: TcxTextParams; ATextRows: TcxTextRows; begin ABounds.Bottom := 30000; ATextFlags := CXTO_CALCROWCOUNT or CXTO_LEFT or CXTO_TOP or CXTO_WORDBREAK or CXTO_EDITCONTROL; ATextParams := cxCalcTextParams(ACanvas.Canvas, ATextFlags); cxMakeTextRows(ACanvas.Canvas, PChar(S), Length(S), ABounds, ATextParams, ATextRows, ARowCount); Result := ATextParams.RowHeight * Max(ARowCount, 1); cxResetTextRows(ATextRows); end; { TcxSchedulerViewInfoCellList } function TcxSchedulerViewInfoCellList.CalculateHitTest( AHitTest: TcxSchedulerCustomResourceViewHitTest): Boolean; var I: Integer; begin Result := False; for I := 0 to Count - 1 do if Items[I].GetHitTest(AHitTest, Result) and Result then Exit; end; procedure TcxSchedulerViewInfoCellList.Clear; var I: Integer; begin for I := Count - 1 downto 0 do Items[I].Free; inherited Clear; end; procedure TcxSchedulerViewInfoCellList.Draw( ACanvas: TcxCanvas; ADrawItemProc: TcxSchedulerCustomDrawItemProc); var I: Integer; ADone: Boolean; AItem: TcxSchedulerCustomViewInfoItem; ASavedFont: TFont; begin for I := 0 to Count - 1 do begin AItem := Items[I]; if AItem.FVisible and not cxRectIsEmpty(AItem.Bounds) then begin ASavedFont := AItem.FViewParams.Font; AItem.BeforeCustomDraw(ACanvas); ADone := False; AItem.FCanvas := ACanvas; if AItem.FHasClipping then begin AItem.ClippingCreate(AItem.FHasClipping); ADrawItemProc(AItem, ADone); AItem.ClippingRestore; end else ADrawItemProc(AItem, ADone); AItem.AfterCustomDraw(ACanvas); if not ADone then AItem.Draw(ACanvas); AItem.FViewParams.Font := ASavedFont; end; end; // need Optimize if custom draw not supported do not need // custom draw canvas preparation // SelectClipRgn(ACanvas.Handle, 0); // TODO: draw and custom draw events end; function TcxSchedulerViewInfoCellList.GetItem( AIndex: Integer): TcxSchedulerCustomViewInfoItem; begin Result := List^[AIndex]; end; { TcxSchedulerCustomViewInfoItem } constructor TcxSchedulerCustomViewInfoItem.Create( APainter: TcxCustomLookAndFeelPainterClass; const ABounds, AVisibleRect: TRect; const AViewParams: TcxViewParams); begin FPainter := APainter; FDateTime := NullDate; FViewParams := AViewParams; CalculateCellBounds(ABounds, AVisibleRect); end; destructor TcxSchedulerCustomViewInfoItem.Destroy; begin FClipRgn.Free; inherited Destroy; end; procedure TcxSchedulerCustomViewInfoItem.Draw(ACanvas: TcxCanvas); var ATransparent: Boolean; APrevCanvas: TcxCanvas; APrevParams: TcxViewParams; begin if not FVisible then Exit; ATransparent := Transparent; APrevCanvas := FCanvas; ACanvas.GetParams(APrevParams); if Cache <> nil then begin if not Cache.IsValid(Self) then begin Cache.Update(Self); UpdateCachedImage(APrevParams); end; ACanvas.Draw(Bounds.Left, Bounds.Top, Cache.Image); end else begin FCanvas := ACanvas; DoDraw; end; ACanvas.SetParams(APrevParams); FCanvas := APrevCanvas; Transparent := ATransparent; end; procedure TcxSchedulerCustomViewInfoItem.CalculateCellBounds( const ABounds, AVisibleRect: TRect); begin FBounds := ABounds; FVisible := cxRectIntersect(FClipRect, ABounds, AVisibleRect); FHasClipping := FVisible and not cxRectIsEqual(FClipRect, ABounds); end; procedure TcxSchedulerCustomViewInfoItem.ClippingCreate(AHasClipping: Boolean); begin Inc(FClipRef); if not AHasClipping or (FClipRef > 1) then Exit; if FClipRgn = nil then FClipRgn := TcxRegion.Create(FClipRect); FSavedClipRgn := Canvas.GetClipRegion; Canvas.SetClipRegion(FClipRgn, roSet, False); end; procedure TcxSchedulerCustomViewInfoItem.ClippingRestore; begin Dec(FClipRef); if (FClipRef = 0) and (FSavedClipRgn <> nil) then begin Canvas.SetClipRegion(FSavedClipRgn, roSet, True); FSavedClipRgn := nil; end; end; function TcxSchedulerCustomViewInfoItem.DrawBackground( ACanvas: TcxCanvas; const ABounds: TRect): Boolean; begin Result := Transparent or Assigned(Bitmap) and not Bitmap.Empty; if Result and not Transparent then ACanvas.FillRect(ABounds, Bitmap); end; procedure TcxSchedulerCustomViewInfoItem.DrawFrame( const ARect: TRect; ABorders: TcxBorders = []; ABorderColor: TColor = clDefault; ALineWidth: Integer = 1); begin Canvas.FrameRect(ARect, ABorderColor, ALineWidth, ABorders); end; procedure TcxSchedulerCustomViewInfoItem.DrawRect( const ARect: TRect; ABorders: TcxBorders = []; ABorderColor: TColor = clDefault; ALineWidth: Integer = 1); begin if Transparent then Canvas.FrameRect(ARect, ABorderColor, ALineWidth, ABorders) else Canvas.FillRect(ARect, FViewParams, ABorders, ABorderColor, ALineWidth); end; procedure TcxSchedulerCustomViewInfoItem.DrawText( const ARect: TRect; const AText: string; AFlags: Integer; AFont: TFont = nil; AColor: TColor = clDefault); begin if AFont = nil then Canvas.Font := FViewParams.Font else Canvas.Font := AFont; if AColor <> clDefault then Canvas.Font.Color := AColor; Canvas.Brush.Style := bsClear; Canvas.DrawTexT(AText, ARect, AFlags); end; function TcxSchedulerCustomViewInfoItem.GetFont: TFont; begin Result := FViewParams.Font; end; function TcxSchedulerCustomViewInfoItem.GetHitTest( AHitTest: TcxSchedulerCustomResourceViewHitTest; var ABreak: Boolean): Boolean; begin Result := FVisible and PtInRect(FClipRect, AHitTest.HitPoint); ABreak := Result; if Result then InitHitTest(AHitTest); end; procedure TcxSchedulerCustomViewInfoItem.InitHitTest( AHitTest: TcxSchedulerCustomResourceViewHitTest); begin AHitTest.FHitObject := Self; end; // custom draw support procedure TcxSchedulerCustomViewInfoItem.AfterCustomDraw(ACanvas: TcxCanvas); begin ACanvas.GetParams(FViewParams); end; procedure TcxSchedulerCustomViewInfoItem.BeforeCustomDraw(ACanvas: TcxCanvas); begin ACanvas.SetParams(FViewParams); end; procedure TcxSchedulerCustomViewInfoItem.UpdateCachedImage( const AViewParams: TcxViewParams); begin if Transparent then BitBlt(Cache.Image.Canvas.Handle, 0, 0, Width, Height, Canvas.Handle, Bounds.Left, Bounds.Top, srcCopy); FCanvas := Cache.Image.cxCanvas; Canvas.SetParams(AViewParams); Canvas.WindowOrg := Bounds.TopLeft; DoDraw; Canvas.WindowOrg := cxNullPoint; end; function TcxSchedulerCustomViewInfoItem.GetBitmap: TBitmap; begin Result := FViewParams.Bitmap; end; function TcxSchedulerCustomViewInfoItem.GetColor: TColor; begin Result := FViewParams.Color; end; function TcxSchedulerCustomViewInfoItem.GetDateTimeHelper: TcxSchedulerDateTimeHelperClass; begin Result := cxSchedulerUtils.DateTimeHelper; end; function TcxSchedulerCustomViewInfoItem.GetHeight: Integer; begin Result := Bounds.Bottom - Bounds.Top; end; function TcxSchedulerCustomViewInfoItem.GetPainterHelper: TcxSchedulerPainterHelperClass; begin Result := TcxSchedulerHelpersFactory.PainterHelperClass; end; function TcxSchedulerCustomViewInfoItem.GetTextColor: TColor; begin Result := FViewParams.TextColor; end; function TcxSchedulerCustomViewInfoItem.GetWidth: Integer; begin Result := Bounds.Right - Bounds.Left; end; procedure TcxSchedulerCustomViewInfoItem.SetBitmap( AValue: TBitmap); begin FViewParams.Bitmap := AValue; end; procedure TcxSchedulerCustomViewInfoItem.SetColor( AValue: TColor); begin FViewParams.Color := AValue; end; procedure TcxSchedulerCustomViewInfoItem.SetTextColor( AValue: TColor); begin FViewParams.TextColor := AValue; end; { TcxSchedulerBackgroundCellViewInfo } procedure TcxSchedulerBackgroundCellViewInfo.DoDraw; begin DrawRect(Bounds, Borders, clBtnShadow); end; { TcxSchedulerCustomResourceViewInfoItem } procedure TcxSchedulerCustomResourceViewInfoItem.InitHitTest( AHitTest: TcxSchedulerCustomResourceViewHitTest); begin if IsResourceAssigned then begin AHitTest.SetResource(FResource); AHitTest.SetBitState(htcResource, True); end; end; { TcxSchedulerHeaderCellViewInfo } constructor TcxSchedulerHeaderCellViewInfo.Create( APainter: TcxCustomLookAndFeelPainterClass; const ABounds, AVisibleRect: TRect; const AViewParams: TcxViewParams); begin inherited Create(APainter, ABounds, AVisibleRect, AViewParams); FImageIndex := -1; FButtonState := cxbsDefault; FAlignHorz := taCenter; FAlignVert := vaCenter; FBorders := cxBordersAll; FTextRect := cxRectInflate(FBounds, -cxTextOffset, 0); end; destructor TcxSchedulerHeaderCellViewInfo.Destroy; begin FreeAndNil(FSelectionBitmap); FreeAndNil(FRotateBitmap); inherited Destroy; end; procedure TcxSchedulerHeaderCellViewInfo.Calculate(const AText: string); begin FDisplayText := AText; end; procedure TcxSchedulerHeaderCellViewInfo.CalculateImageLayout; const Alignments: array[TcxSchedulerHeaderImagePosition] of TAlignment = (taLeftJustify, taCenter, taRightJustify, taCenter); var ATopLeft: TPoint; ATextSize, AImageSize: TSize; ABounds: TRect; begin FImageRectAssigned := HasImage; if not FImageRectAssigned then begin FTextRect := cxRectInflate(PainterHelper.ExcludeBorders(Bounds, Borders), -cxTextOffset, 0); if not HasImage and RotateHeader then begin if RotateText then FTextRect := MakeRect(0, 0, cxSize(Height, Width)) else FTextRect := MakeRect(0, 0, cxSize(Width, Height)); InflateRect(FTextRect, -(cxTextOffset + 1), -(cxTextOffset + 1)); end; DisplayBounds := FTextRect; Exit; end; FTextRect := cxTextRect(PainterHelper.ExcludeBorders(Bounds, Borders)); FAlignHorz := Alignments[ImagePosition]; FAlignVert := vaTop; MultiLine := AutoHeight; // calculate text and image extents AImageSize := cxSize(Images.Width, Images.Height); if RotateHeader and RotateText then begin AImageSize := cxSize(Images.Height, Images.Width); ABounds := MakeRect(0, 0, cxSize(Height - 2, Width - 2)); FTextRect := cxTextRect(ABounds); end else begin ABounds := Bounds; if RotateHeader then begin OffsetRect(ABounds, -ABounds.Left, -ABounds.Top); FTextRect := cxTextRect(ABounds); end; end; DisplayBounds := cxRectInflate(ABounds, -1, -1); if AutoHeight and (ImagePosition in [ipLeft, ipRight]) then Dec(FTextRect.Right, AImageSize.cx + cxTextOffset * 2); if Length(DisplayText) > 0 then begin // Canvas.Font.Assign(Font); // Canvas.TextExtent(DisplayText, FTextRect, GetTextOutcxFlags); FTextRect.Right := FTextRect.Left + cxRectWidth(Resource.FTextRect); FTextRect.Bottom := FTextRect.Top + cxRectHeight(Resource.FTextRect); end else FTextRect := cxNullRect; ATextSize := cxRectSize(FTextRect); ATopLeft := cxPointOffset(cxRectCenter(ABounds), 1, -1 + Byte(RotateHeader)); if ImagePosition in [ipLeft, ipRight] then begin Dec(ATopLeft.X, (AImageSize.cx + ATextSize.cx + cxTextOffset) div 2); FTextRect := MakeRect(ATopLeft.X, ATopLeft.y - ATextSize.cy div 2, ATextSize); FImageRect := MakeRect(ATopLeft.X, ATopLeft.y - AImageSize.cy div 2, AImageSize); end else begin Dec(ATopLeft.Y, (AImageSize.cy + ATextSize.cy + cxTextOffset) div 2); FTextRect := MakeRect(ATopLeft.x - ATextSize.cx div 2, ATopLeft.y, ATextSize); FImageRect := MakeRect(ATopLeft.x - AImageSize.cx div 2, ATopLeft.y, AImageSize); end; // calculate text bounds if Length(DisplayText) > 0 then begin case ImagePosition of ipLeft: OffsetRect(FTextRect, AImageSize.cx + cxTextOffset, 0); ipTop: OffsetRect(FTextRect, 0, AImageSize.cy + cxTextOffset); ipRight: OffsetRect(FImageRect, ATextSize.cx + cxTextOffset, 0); ipBottom: OffsetRect(FImageRect, 0, ATextSize.cy + cxTextOffset); end; end; end; procedure TcxSchedulerHeaderCellViewInfo.CheckNeighbor( APrevCell: TcxSchedulerHeaderCellViewInfo); begin if (APrevCell = nil) or (APrevCell.RotateHeader <> RotateHeader) then Exit; if (RotateHeader and (APrevCell.Bounds.Bottom <> Bounds.Top)) or (not RotateHeader and (APrevCell.Bounds.Right <> Bounds.Left)) then Exclude(APrevCell.FBorders, bRight); end; function TcxSchedulerHeaderCellViewInfo.CheckSelection: Boolean; begin Result := False; end; procedure TcxSchedulerHeaderCellViewInfo.DoDraw; begin ValidateSelection; CalculateImageLayout; FBackgroundDrawing := False; if RotateText or RotateHeader then DrawVerticalHeader else DrawHorizontalHeader; end; procedure TcxSchedulerHeaderCellViewInfo.DrawCaption(ACanvas: TcxCanvas = nil); var ABitmap: TcxBitmap; begin if ACanvas = nil then ACanvas := Canvas; ACanvas.SaveClipRegion; try ACanvas.Brush.Style := bsClear; ACanvas.IntersectClipRect(DisplayBounds); ACanvas.Font := Font; ACanvas.Font.Color := TextColor; ACanvas.DrawTexT(DisplayText, TextRect, GetTextOutcxFlags); if FImageRectAssigned and HasImage then begin if not RotateText then ACanvas.DrawImage(Images, FImageRect.Left, FImageRect.Top, ImageIndex) else begin //todo: ABitmap := TcxBitmap.CreateSize(Images.Width, Images.Height, pf32bit); try ABitmap.Rotate(raMinus90); cxBitBlt(ABitmap.Canvas.Handle, ACanvas.Handle, ABitmap.ClientRect, FImageRect.TopLeft, SRCCOPY); ABitmap.Rotate(raPlus90); Images.Draw(ABitmap.Canvas, 0, 0, ImageIndex); ABitmap.Rotate(raMinus90); ACanvas.Draw(FImageRect.Left, FImageRect.Top, ABitmap); finally ABitmap.Free; end; end; end; finally ACanvas.RestoreClipRegion; end; end; procedure TcxSchedulerHeaderCellViewInfo.DrawHorizontalHeader; begin if not Transparent then Painter.DrawHeader(Canvas, Bounds, TextRect, Neighbors, Borders, FButtonState, AlignHorz, AlignVert, MultiLine, ShowEndEllipsis, '', Font, TextColor, Color, DrawBackground, not (nRight in Neighbors)); if not FBackgroundDrawing and Selected then DrawSelection; if DisplayText <> '' then DrawCaption; end; function TcxSchedulerHeaderCellViewInfo.DrawRotateBackground( ACanvas: TcxCanvas; const ABounds: TRect): Boolean; begin Result := FDrawRotatedBackground; end; procedure TcxSchedulerHeaderCellViewInfo.DrawSelection; begin if FSelectionBitmap = nil then FSelectionBitmap := TcxBitmap.CreateSize(Bounds, pf32bit) else FSelectionBitmap.SetSize(Width, Height); cxBitBlt(FSelectionBitmap.Canvas.Handle, Canvas.Handle, FSelectionBitmap.ClientRect, Bounds.TopLeft, SRCCOPY); cxAlphaBlend(FSelectionBitmap, cxRectOffset(FSelectionRect, -Bounds.Left, -Bounds.Top), ColorToRgb(SelectionColor)); cxBitBlt(Canvas.Handle, FSelectionBitmap.Canvas.Handle, Bounds, cxNullPoint, SRCCOPY); end; procedure TcxSchedulerHeaderCellViewInfo.DrawVerticalHeader; procedure CreateRotatedBitmap; begin FRotateBitmap := TcxBitmap.CreateSize(Bounds, pf32bit); FRotateBitmap.Canvas.Lock; if Transparent then cxBitBlt(FRotateBitmap.Canvas.Handle, Canvas.Handle, FRotateBitmap.ClientRect, Bounds.TopLeft, SRCCOPY); FRotateBitmap.cxCanvas.WindowOrg := Bounds.TopLeft; end; var R: TRect; begin if FRotateBitmap = nil then begin CreateRotatedBitmap; FDrawRotatedBackground := DrawBackground(FRotateBitmap.cxCanvas, Bounds); FRotateBitmap.Rotate(raPlus90); R := FRotateBitmap.ClientRect; if not Transparent then Painter.DrawHeader(FRotateBitmap.cxCanvas, R, cxRectInflate(R, -cxTextOffset, -cxTextOffset), Neighbors, Borders, cxbsNormal, taCenter, vaCenter, False, False, '', Font, TextColor, Color, DrawRotateBackground); if RotateText then begin DrawCaption(FRotateBitmap.cxCanvas); FRotateBitmap.Rotate(raPlus90); end else begin FRotateBitmap.Rotate(raPlus90); DrawCaption(FRotateBitmap.cxCanvas); end; end; Canvas.Draw(Bounds.Left, Bounds.Top, FRotateBitmap); end; function TcxSchedulerHeaderCellViewInfo.GetTextOutcxFlags: Integer; begin Result := MakeTextOutcxFlags(AlignHorz, AlignVert, AutoHeight); end; function TcxSchedulerHeaderCellViewInfo.GetTextOutFlags: Integer; const Horz: array[TAlignment] of Integer = (CXTO_LEFT, CXTO_RIGHT, CXTO_CENTER_HORIZONTALLY); Vert: array[TcxAlignmentVert] of Integer = (CXTO_TOP, CXTO_BOTTOM, CXTO_CENTER_VERTICALLY); begin Result := CXTO_PREVENT_LEFT_EXCEED or CXTO_PREVENT_TOP_EXCEED or Horz[AlignHorz] or Vert[AlignVert] + CXTO_SINGLELINE; if AutoHeight then begin Result := CXTO_PREVENT_LEFT_EXCEED or CXTO_PREVENT_TOP_EXCEED or Horz[AlignHorz] or Vert[AlignVert] or CXTO_WORDBREAK; end; end; function TcxSchedulerHeaderCellViewInfo.HasImage: Boolean; begin Result := ImageIndex >=0 end; procedure TcxSchedulerHeaderCellViewInfo.InitHitTest( AHitTest: TcxSchedulerCustomResourceViewHitTest); begin inherited InitHitTest(AHitTest); if IsResourceAssigned then AHitTest.SetBitState(htcResourceHeader, True); if DateTime <> NullDate then AHitTest.SetHitTime(htcDayHeader, DateTime); end; procedure TcxSchedulerHeaderCellViewInfo.TextOut(ACanvas: TcxCanvas; const AText: string; R: TRect); begin if Length(AText) = 0 then Exit; if not FImageRectAssigned then R := cxRectInflate(R, -1, -(cxTextOffset + 1)); with ACanvas.Canvas do begin Font := FViewParams.Font; Font.Color := FViewParams.TextColor; cxTextOut(Handle, AText, R, GetTextOutFlags); end; end; procedure TcxSchedulerHeaderCellViewInfo.ValidateSelection; begin if CheckSelection and (Date = DateOf(FDateTime)) then FButtonState := cxbsHot; if Selected then begin if Selected then TextColor := FSelectionTextColor; FSelectionRect := PainterHelper.ExcludeBorders(Bounds, Borders); if FButtonState = cxbsHot then begin FSelectionRect.Left := Max(FSelectionRect.Left, FSelectionRect.Right - PainterHelper.TextWidth(Font, DisplayText) - cxTextOffset * 2); end; end; end; { TcxSchedulerDayHeaderCellViewInfo } function TcxSchedulerDayHeaderCellViewInfo.ConvertDateToDisplayText( AType: Integer = 0): Integer; begin Result := AType - 1; repeat Inc(Result); if cxRectWidth(FTextRect) <= 0 then Exit; FDisplayText := DateTimeHelper.DayToStr(FDateTime, Result, Compressed); until (Result = DateTimeHelper.DayToStrFormatCount - 1) or (cxTextWidth(Font, DisplayText) <= cxRectWidth(FTextRect) - cxTextOffset); end; function TcxSchedulerDayHeaderCellViewInfo.CheckSelection: Boolean; begin Result := True; end; function TcxSchedulerDayHeaderCellViewInfo.DrawBackground( ACanvas: TcxCanvas; const ABounds: TRect): Boolean; var R: TRect; begin FBackgroundDrawing := True; Result := inherited DrawBackground(ACanvas, ABounds); if Result then Exit; R := PainterHelper.ExcludeBorders(Bounds, Borders); if FButtonState = cxbsHot then PainterHelper.DrawGradientRect(Canvas, Color, R); if Selected then Canvas.FillRect(FSelectionRect, SelectionColor); Result := (FButtonState = cxbsHot) or Selected; end; procedure TcxSchedulerDayHeaderCellViewInfo.DrawHorizontalHeader; begin if Selected and not (FButtonState = cxbsHot) then begin Color := FSelectionColor; TextColor := FSelectionTextColor; end; inherited DrawHorizontalHeader; end; { TcxSchedulerWeekDayHeaderCellViewInfo } function TcxSchedulerWeekDayHeaderCellViewInfo.ConvertDateToDisplayText( AType: Integer = 0): Integer; begin Result := AType - 1; repeat Inc(Result); FDisplayText := GetDayText(Result); until (Result = 3) or (cxTextWidth(Font, DisplayText) <= cxRectWidth(FTextRect)); if (DateOf(FDateTime) + 1) > 7 then Result := 0; end; procedure TcxSchedulerWeekDayHeaderCellViewInfo.InitHitTest( AHitTest: TcxSchedulerCustomResourceViewHitTest); begin inherited InitHitTest(AHitTest); AHitTest.SetBitState(htcTime, False); end; function TcxSchedulerWeekDayHeaderCellViewInfo.GetDayText( AType: Integer): string; var ADay: Integer; begin //DELPHI8! check Trunc() ADay := Trunc(FDateTime) + 1; if ADay > 7 then begin case AType of 0: Result := LongDayNames[7]+ '/' + LongDayNames[1]; 1: Result := ShortDayNames[7]+ '/' + ShortDayNames[1]; else Result := AnsiUpperCase(LongDayNames[7][1]+ '/' + LongDayNames[1][1]); end; end else case AType of 0: Result := LongDayNames[ADay]; 1: Result := ShortDayNames[ADay]; else Result := AnsiUpperCase(LongDayNames[ADay][1]); end; end; { TcxSchedulerContainerCellViewInfo } procedure TcxSchedulerContainerCellViewInfo.DoDraw; begin FExternalPainter.DrawAllDayArea(Canvas, Bounds, FDayBorderColor, Borders, ViewParams, Selected, Transparent); end; procedure TcxSchedulerContainerCellViewInfo.InitHitTest( AHitTest: TcxSchedulerCustomResourceViewHitTest); begin inherited InitHitTest(AHitTest); AHitTest.FHitObject := Self; AHitTest.SetHitTime(htcContainer, DateTime); end; { TcxSchedulerTimeRulerCellViewInfo } procedure TcxSchedulerTimeRulerCellViewInfo.Calculate( const ALabel1, ALabel2: string; ATimeZone, AAdditionalTimeZone: Integer; AAdditionalTimeZoneBiasDelta: Integer); begin Calculate(-1, 1, ATimeZone, AAdditionalTimeZone, nil, AAdditionalTimeZoneBiasDelta); FDisplayTexts[True] := ALabel1; FDisplayTexts[False] := ALabel2; end; procedure TcxSchedulerTimeRulerCellViewInfo.Calculate(AHour, ALineCount: Integer; ATimeZone, AAdditionalTimeZone: Integer; ALargeFont: TFont; AAdditionalTimeZoneBiasDelta: Integer); begin FHour := AHour; FLineCount := ALineCount; FAdditionalTimeZone := AAdditionalTimeZone; FAdditionalTimeZoneBiasDelta := AAdditionalTimeZoneBiasDelta; FTimeZone := ATimeZone; FLargeFont := ALargeFont; if FVisible then CalculateDisplayInfo; end; procedure TcxSchedulerTimeRulerCellViewInfo.SetBottom(AValue: Integer); begin FClipRect.Bottom := AValue; end; class function TcxSchedulerTimeRulerCellViewInfo.CalculateWidth( ATimeZoneCount, ALineCount: Integer; AFont1, AFont2: TFont): Integer; begin if ALineCount = 1 then Result := TcxSchedulerPainterHelper.TextWidth(AFont1, ' 24:PM') else begin Result := TcxSchedulerPainterHelper.TextWidth(AFont1, ' 24') + cxTextWidth(AFont2, 'pm') + cxTextOffset; end; Inc(Result, cxTextOffset shl 2); if ATimeZoneCount > 1 then Result := Result shl 1; end; procedure TcxSchedulerTimeRulerCellViewInfo.CalculateDisplayInfo; begin FBounds[True] := inherited Bounds; FDateTime := Hour * HourToTime; if Hour >= 0 then FDisplayTexts[True] := GetTimeDisplayText(FDateTime); FBounds[False] := inherited Bounds; if HasAdditionalTimeZone then begin FBounds[True].Left := cxRectCenter(inherited Bounds).X; FBounds[False].Right := FBounds[True].Left; if Hour >= 0 then FDisplayTexts[False] := GetTimeDisplayText(GetAdditionalTime); end; end; procedure TcxSchedulerTimeRulerCellViewInfo.DoDraw; var ACurrentTimeZone: Boolean; const ABorders: array[Boolean] of TcxBorders = ([bBottom], [bBottom, bRight]); begin ClippingCreate(FHasClipping); for ACurrentTimeZone := not HasAdditionalTimeZone to True do begin if Hour >= 0 then DrawTimeZone(Bounds[ACurrentTimeZone], DisplayTexts[ACurrentTimeZone], ACurrentTimeZone) else DrawTimeZoneLabel(Bounds[ACurrentTimeZone], DisplayTexts[ACurrentTimeZone], ABorders[ACurrentTimeZone]); end; ClippingRestore; end; procedure TcxSchedulerTimeRulerCellViewInfo.DrawTimeZoneLabel( const ABounds: TRect; const AText: string; ABorders: TcxBorders); begin FExternalPainter.DrawTimeRulerBackground(Canvas, ABounds, ABorders, ViewParams, Transparent); DrawText(cxTextRect(ABounds), AText, cxAlignBottom or cxAlignLeft, Font, TextColor); end; procedure TcxSchedulerTimeRulerCellViewInfo.DrawTimeZone( const ABounds: TRect; const AText: string; AIsCurrent: Boolean); var J, LH: Integer; S: string; R, R1, TextR: TRect; const cxRightCenterAlign: Integer = cxAlignVCenter or cxAlignRight or cxDontClip; cxRightTopAlign: Integer = cxAlignTop or cxAlignRight or cxDontClip; begin LH := cxRectHeight(inherited Bounds) div LineCount; FExternalPainter.DrawTimeRulerBackground(Canvas, ABounds, [bRight], ViewParams, Transparent); R := cxRectSetHeight(ABounds, LH); R.Left := (R.Left + R.Right) div 2 + cxTextOffset shl 1; Dec(R.Right, 6); for J := 0 to LineCount - 2 do begin Canvas.FrameRect(R, clBtnShadow, 1, [bBottom]); OffsetRect(R, 0, LH); end; Canvas.Brush.Style := bsClear; TextR := cxRectInflate(PainterHelper.ExcludeBorders(ABounds, [bRight, bBottom]), -5, -cxTextOffset); if AIsCurrent and FExternalPainter.DrawCurrentTimeFirst then DrawCurrentTime(FDateTime, ABounds); if LineCount > 1 then begin J := Length(AText); DrawText(Rect(TextR.Left, TextR.Top, R.Left - cxTextOffset, TextR.Bottom), Copy(AText, 1, J - 3), cxRightTopAlign, LargeFont, TextColor); R1 := Rect(R.Left, TextR.Top, TextR.Right, TextR.Top + LH - 3); DrawText(R1, Copy(AText, J - 1, 2), cxAlignCenter, Font, TextColor); if ShowMinutes and AIsCurrent then for J := 1 to LineCount - 1 do begin OffsetRect(R1, 0, LH); S := IntToStr(MulDiv(60, J, LineCount)); if Length(S) < 2 then S := '0' + S; DrawText(R1, S, cxAlignCenter, Font, TextColor); end; end else DrawText(TextR, AText, cxRightCenterAlign, Font, TextColor); if AIsCurrent and not FExternalPainter.DrawCurrentTimeFirst then DrawCurrentTime(FDateTime, ABounds); R.Left := ABounds.Left + 5; if (Hour <> 23) and not LastVisibleHour then DrawFrame(R, [bBottom], clBtnShadow) else DrawFrame(ABounds, [bBottom], clBtnShadow); end; procedure TcxSchedulerTimeRulerCellViewInfo.DrawCurrentTime( const AStart: TDateTime; ABounds: TRect); begin FExternalPainter.DrawCurrentTime(Canvas, Color, AStart, ABounds); Canvas.Brush.Style := bsClear; end; function TcxSchedulerTimeRulerCellViewInfo.GetAdditionalTime: TDateTime; begin Result := DateTimeHelper.ConvertToAnotherTimeZone( (Hour + FAdditionalTimeZoneBiasDelta / MinsPerHour) * HourToTime + Date, TimeZone, AdditionalTimeZone); end; function TcxSchedulerTimeRulerCellViewInfo.GetTimeDisplayText( const ATime: TDateTime): string; var APos: Integer; begin Result := DateTimeHelper.HourToStr(ATime); if LineCount > 1 then begin APos := Pos(TimeSeparator, Result); if APos = 0 then APos := Pos(' ', Result); if APos = 0 then APos := Length(Result) - 2; Result := Copy(Result, 1, APos - 1) + ' ' + AnsiLowerCase(Copy(Result, APos + 1, 2)); end; end; procedure TcxSchedulerTimeRulerCellViewInfo.InitHitTest( AHitTest: TcxSchedulerCustomResourceViewHitTest); var LH: Integer; ACurrentTimeZone: Boolean; ATime, ATimePerLine: TDateTime; begin inherited InitHitTest(AHitTest); if Hour >= 0 then begin LH := cxRectHeight(inherited Bounds) div FLineCount; ATimePerLine := 60 / FLineCount * MinuteToTime; ATime := (AHitTest.HitY - inherited Bounds.Top) div LH * ATimePerLine + FHour * HourToTime; AHitTest.SetHitTime(htcTimeRuler, ATime); end else AHitTest.SetBitState(htcTimeZoneLabel, True); for ACurrentTimeZone := not HasAdditionalTimeZone to True do if PtInRect(Bounds[ACurrentTimeZone], AHitTest.HitPoint) then begin if ACurrentTimeZone then AHitTest.FTimeZone := TimeZone else AHitTest.FTimeZone := AdditionalTimeZone; end; end; procedure TcxSchedulerTimeRulerCellViewInfo.AfterCustomDraw(ACanvas: TcxCanvas); begin FViewParams.TextColor := ACanvas.Font.Color; FViewParams.Color := ACanvas.Brush.Color; end; function TcxSchedulerTimeRulerCellViewInfo.GetBoundsRect( AType: Boolean): TRect; begin Result := FBounds[AType]; end; function TcxSchedulerTimeRulerCellViewInfo.GetDisplayText( AType: Boolean): string; begin Result := FDisplayTexts[AType]; end; function TcxSchedulerTimeRulerCellViewInfo.GetHasAdditionalTimeZone: Boolean; begin Result := AdditionalTimeZone >= 0; end; { TcxSchedulerContentCellViewInfo } constructor TcxSchedulerContentCellViewInfo.Create( APainter: TcxCustomLookAndFeelPainterClass; const ABounds, AVisibleRect: TRect; const AViewParams: TcxViewParams); begin inherited Create(APainter, ABounds, AVisibleRect, AViewParams); FTimeLineBorders := [bLeft, bRight]; BorderColor := clDefault; end; procedure TcxSchedulerContentCellViewInfo.SetTime( const ATimeStart, ATimeFinish: TDateTime); begin FDateTime := ATimeStart; FTimeFinish := ATimeFinish; end; procedure TcxSchedulerContentCellViewInfo.DoDraw; var R: TRect; begin if BorderColor = clDefault then BorderColor := FDayBorderColor; if FShowTimeLine then begin R := Bounds; Inc(R.Left, cxTimeLineWidth); DrawRect(R, Borders, BorderColor); R := cxRectSetRight(R, R.Left, cxTimeLineWidth); if FTimeEvent = nil then FExternalPainter.DrawTimeLine(Canvas, R, FTimeLineParams, FTimeLineBorders, FTimeLineParams.TextColor) else FTimeEvent.DrawState(Canvas, R, FTimeLineBorders, FTimeLineParams.TextColor); end else DrawRect(Bounds, Borders, BorderColor); end; procedure TcxSchedulerContentCellViewInfo.InitHitTest( AHitTest: TcxSchedulerCustomResourceViewHitTest); begin inherited InitHitTest(AHitTest); AHitTest.SetHitTime(htcContent, FDateTime); AHitTest.FHitObject := Self; end; { TcxSchedulerBackgroundSlotCellViewInfo } procedure TcxSchedulerBackgroundSlotCellViewInfo.DoDraw; begin inherited DoDraw; end; { TcxSchedulerMonthDayContentCellViewInfo } destructor TcxSchedulerMonthDayContentCellViewInfo.Destroy; begin if FSmallFontCreated then FreeAndNil(FSmallTextFont); inherited Destroy; end; procedure TcxSchedulerMonthDayContentCellViewInfo.SetContentState( AsDayOfMonth: Boolean; ASelected: Boolean; ATextHeight: Integer; const ASelectionParams: TcxViewParams); begin FSelectionColor := ASelectionParams.Color; FSelectionTextColor := ASelectionParams.TextColor; FTextRect := PainterHelper.ExcludeBorders(Bounds, Borders); if AsDayOfMonth then FDisplayText := IntToStr(DayOf(TimeStart)) else FDisplayText := GetLongDisplayText; FSelected := ASelected; FTextRect.Bottom := Min(FTextRect.Bottom, FTextRect.Top + ATextHeight); if not SmallFont then FTextRect.Left := Max(FTextRect.Left, FTextRect.Right - PainterHelper.TextWidth(Font, DisplayText)) - cxTextOffset * 2 else begin if FSmallTextFont = nil then begin SmallTextFont := TFont.Create; FSmallFontCreated := True; FSmallTextFont.Assign(Font); FSmallTextFont.Size := Round(Font.Size * 2 / 3); end; FTextRect.Left := Max(FTextRect.Left, FTextRect.Right - PainterHelper.TextWidth(FSmallTextFont, DisplayText)) - cxTextOffset; end; end; function TcxSchedulerMonthDayContentCellViewInfo.UpdateSelection(ASelected: Boolean): Boolean; begin Result := FSelected <> ASelected; if Result then FSelected := ASelected; end; procedure TcxSchedulerMonthDayContentCellViewInfo.DoDraw; const TextFlags = CXTO_PREVENT_LEFT_EXCEED or CXTO_PREVENT_TOP_EXCEED or CXTO_CENTER_VERTICALLY or CXTO_RIGHT; var R: TRect; AColor: Integer; begin inherited DoDraw; if DisplayText <> '' then begin R := PainterHelper.ExcludeBorders(Bounds, Borders); R.Bottom := FTextRect.Bottom; if not Transparent and IsToday then PainterHelper.DrawGradientRect(Canvas, Color, R); if Selected then begin Inc(R.Top); InflateRect(R, -1, 0); Canvas.SetBrushColor(SelectionColor); if not IsToday then Canvas.FillRect(R) else begin R := FTextRect; R.Left := Max(Bounds.Left, (R.Left - cxTextOffset * 2)); Inc(R.Bottom); InflateRect(R, -1, -1); Canvas.FillRect(R); end; end; if SmallFont then Canvas.Font := SmallTextFont else Canvas.Font := Font; if Selected then AColor := SelectionTextColor else AColor := TextColor; Canvas.Brush.Style := bsClear; cxTextOut(Canvas.Handle, DisplayText, FTextRect, TextFlags, nil, 0, 0, cxTextOffset + 1, AColor); end; end; function TcxSchedulerMonthDayContentCellViewInfo.GetLongDisplayText: string; begin Result := LongMonthNames[MonthOf(TimeStart)] + ', ' + IntToStr(DayOf(TimeStart)); if cxTextWidth(Font, Result) >= (cxRectWidth(FTextRect) div 2) then Result := ShortMonthNames[MonthOf(TimeStart)] + ' ' + IntToStr(DayOf(TimeStart)); end; function TcxSchedulerMonthDayContentCellViewInfo.GetIsToday: Boolean; begin Result := Date = TimeStart; end; procedure TcxSchedulerMonthDayContentCellViewInfo.SetSmallTextFont(AFont: TFont); begin if FSmallFontCreated then FreeAndNil(FSmallFont); FSmallTextFont := AFont; end; { TcxSchedulerEventCellViewInfo } constructor TcxSchedulerEventCellViewInfo.Create( AViewData: TcxSchedulerEventViewData); begin inherited Create(AViewData.Painter, AViewData.Bounds, AViewData.VisibleRect, AViewData.ViewParams); FExternalPainter := AViewData.ExternalPainter; ViewData := AViewData; FSeparatorColor := clBtnShadow; FCanvas := AViewData.Canvas; FImages := TcxSchedulerEventImages.Create(AViewData.ImagesLayout); Initialize; end; destructor TcxSchedulerEventCellViewInfo.Destroy; begin ViewData.Free; FImages.Free; FEditViewInfo.Free; inherited Destroy; end; procedure TcxSchedulerEventCellViewInfo.Draw( ACanvas: TcxCanvas; ABitmap: TBitmap); begin ViewData.Bitmap := ABitmap; inherited Draw(ACanvas); end; procedure TcxSchedulerEventCellViewInfo.DrawState(ACanvas: TcxCanvas; const ARect: TRect; ABorders: TcxBorders; ABorderColor: TColor); begin PainterHelper.DrawState(ACanvas, ARect, Event.State, ABorders, ABorderColor); end; function TcxSchedulerEventCellViewInfo.MeasureHeight(ACanvas: TcxCanvas): Integer; var L: TList; begin Canvas.Font := Font; FIsHeaderEvent := GetIsHeaderEvent; CalculateVisibility; FCaptionRect := cxRectInflate(Bounds, -(cxTextOffset + 1), -(cxTextOffset + 1)); L := Images.CreateVisibleList; try case Images.Layout of eilHorizontal: Result := CalculateHorizontalImagesAutoHeight; eilVertical: Result := CalculateVerticalImagesAutoHeight; else //eilAuto:; Result := CalculateAutoLayoutImagesAutoHeight(L); end; finally L.Free; end; Result := Max(ViewData.LineHeight, Result); end; procedure TcxSchedulerEventCellViewInfo.MoveTo(X, Y: Integer); procedure ShiftRect(var R: TRect); begin if not cxRectIsEmpty(R) then OffsetRect(R, X, Y); end; var I: Integer; begin ShiftRect(ViewData.Bounds); CalculateCellBounds(ViewData.Bounds, ViewData.VisibleRect); if not Visible or Hidden then Exit; ShiftRect(FCaptionRect); ShiftRect(FFinishRect); ShiftRect(FMessageRect); ShiftRect(FStartRect); ShiftRect(FEventTimeRect); ShiftRect(FTimeLineRect); if FShowMessage then CalculateEditViewInfo; for I := 0 to Images.Count - 1 do ShiftRect(Images[0].FBounds); end; procedure TcxSchedulerEventCellViewInfo.AssignEditStyle( AEditStyle: TcxCustomEditStyle); var AStyle: TcxCustomEditStyleAccess; begin AStyle := TcxCustomEditStyleAccess(AEditStyle); AStyle.FAssignedValues := AStyle.FAssignedValues - [svFont] + [svColor, svButtonTransparency]; AStyle.StyleData.Font := Font; AStyle.StyleData.Color := Color; AStyle.StyleData.FontColor := TextColor; AStyle.ButtonTransparency := ebtHideInactive; AStyle.Changed; end; procedure TcxSchedulerEventCellViewInfo.BeforeCustomDraw(ACanvas: TcxCanvas); begin FViewParams := ViewData.ViewParams; inherited BeforeCustomDraw(ACanvas); end; procedure TcxSchedulerEventCellViewInfo.Calculate; begin Canvas.Font := Font; CalculateItemsLayout; end; procedure TcxSchedulerEventCellViewInfo.CalculateBorders; begin end; procedure TcxSchedulerEventCellViewInfo.CalculateCaptions; begin FStartText := DateTimeHelper.TimeToStr(EventStart); FFinishText := DateTimeHelper.TimeToStr(EventFinish); end; procedure TcxSchedulerEventCellViewInfo.CalculateDetailInfo; begin FIsDetailInfo := ViewData.AutoHeight or (not IsHeaderEvent and ((TimeOf(ContentFinish) <> 0) or (TimeOf(ContentStart) <> 0))); FIsDetailCaption := FIsDetailInfo and not IsHeaderEvent; FShowMessage := IsDetailInfo and (Length(Message) > 0); end; procedure TcxSchedulerEventCellViewInfo.CalculateNeedHint; var R: TRect; begin if FHintNeededCalculated then Exit; FHintNeeded := CanShowHint; if not FHintNeeded then begin R := FCaptionRect; Canvas.TextExtent(Hint, R, cxDrawTextFlags[IsDetailCaption]); FHintNeeded := (FCaptionRect.Right < R.Right) or (FCaptionRect.Bottom < R.Bottom); end; FHintNeededCalculated := True; end; procedure TcxSchedulerEventCellViewInfo.CalculateEditViewInfo; var AProperties: TcxCustomEditProperties; AEditViewData: TcxCustomEditViewData; begin if not ViewData.AutoHeight then begin FMessageRect := GetMessageRect(CaptionRect, Images.VisibleImageCount > 0); FCaptionRect.Bottom := Min(FMessageRect.Top, Bounds.Bottom - cxTextOffset); end; if cxRectIsEmpty(FMessageRect) then begin FShowMessage := False; Exit; end; if FEditViewInfo = nil then FEditViewInfo := TcxCustomEditViewInfo(ViewData.EditProperties.GetViewInfoClass.Create); AProperties := ViewData.EditProperties; AEditViewData := AProperties.CreateViewData(ViewData.EditStyle, True); try Include(AEditViewData.PaintOptions, epoAutoHeight); AssignEditStyle(ViewData.EditStyle); AEditViewData.ContentOffset := cxSimpleRect; AEditViewData.EditValueToDrawValue(Canvas, Message, FEditViewInfo); AEditViewData.CalculateEx(Canvas, FMessageRect, cxInvalidPoint, cxmbNone, [], FEditViewInfo, False); finally AEditViewData.Free; end; end; procedure TcxSchedulerEventCellViewInfo.CalculateShowTimeAsClock; begin ViewData.ShowTimeAsClock := IsHeaderEvent or (ViewData.ShowTimeAsClock and not IsDetailInfo); end; function TcxSchedulerEventCellViewInfo.CalculateAutoLayoutImagesAutoHeight( AVisibleImages: TList): Integer; function GetEventTextsHeight(const AWidth: Integer): Integer; var R: TRect; begin R := cxRect(0, 0, AWidth, MaxInt); Result := GetCaptionAutoHeight(R) + 2 * cxTextOffset; if ShowMessage then begin Inc(R.Right, 3); Inc(Result, CalculateMessageHeight(R) + 1); end; end; function GetColCountForRowCount(ARowCount: Integer): Integer; begin Result := Images.TotalVisibleImageCount div ARowCount; if (Images.TotalVisibleImageCount mod ARowCount) > 0 then Inc(Result); Result := Max(1, Result); end; var I, ANewColCount, ACaptionWidth, ASpaceWidth, AImagesHeight, AImagesWidth, AImagesColCount, AImagesRowCount, ATextsHeight: Integer; begin ASpaceWidth := cxRectWidth(Bounds) - 2 * cxTextOffset; ACaptionWidth := Canvas.TextWidth(Caption); if (Images.TotalVisibleImageCount < 2) or (ASpaceWidth >= Images.TotalVisibleWidth + cxEventImagesGap + ACaptionWidth) then begin Result := CalculateHorizontalImagesAutoHeight; Exit; end; AImagesWidth := 0; AImagesRowCount := 1; AImagesColCount := 0; for I := 1 to Images.TotalVisibleImageCount do begin AImagesRowCount := I; AImagesHeight := Min(Images.TotalVisibleImageCount, (AImagesRowCount + 1)) * (Images.ItemHeight + cxEventImagesGap) + 4; ANewColCount := GetColCountForRowCount(AImagesRowCount); if ANewColCount <> AImagesColCount then begin AImagesColCount := ANewColCount; AImagesWidth := AImagesColCount * (Images.ItemWidth + cxEventImagesGap) + 1; if ASpaceWidth <= AImagesWidth then Continue; ATextsHeight := GetEventTextsHeight(ASpaceWidth - AImagesWidth); if ATextsHeight < AImagesHeight then Break; end else Continue; end; Result := AImagesRowCount * (Images.ItemHeight + cxEventImagesGap) + 1; Images.CalculateForCols(AVisibleImages, cxPointOffset(Bounds.TopLeft, cxEventImagesOffset + cxEventBorderWidth, cxEventImagesOffset + cxEventBorderWidth), AImagesColCount); Inc(FCaptionRect.Left, AImagesWidth); CalculateMessageAutoLayout(Result); end; function TcxSchedulerEventCellViewInfo.CalculateHorizontalImagesAutoHeight: Integer; var ARightLimit, ACaptionWidth, ACaptionHeight, AMessageHeight, ASpaceWidth, AMessageTop, AImagesWidth: Integer; AImagesRect, R: TRect; begin Result := Images.ItemHeight + cxTextOffset; ASpaceWidth := cxRectWidth(Bounds) - 2 * cxTextOffset; ACaptionWidth := Canvas.TextWidth(Caption); AImagesRect := cxRectInflate(Bounds, -cxTextOffset, -cxTextOffset); if Images.ForceVisibleWidth + cxEventImagesGap >= ASpaceWidth then begin FCaptionRect := cxNullRect; Images.CalculateSingleLineImages(AImagesRect); AMessageTop := Bounds.Top + cxTextOffset + Result + cxEventImagesGap; end else begin ARightLimit := 0; if not (Images.TotalVisibleWidth + cxEventImagesGap + ACaptionWidth <= ASpaceWidth) then begin R := FCaptionRect; R.Left := Min(AImagesRect.Left + Images.TotalVisibleWidth, R.Right - 1); Canvas.TextExtent(Caption, R, cxWordBreak or cxDontBreakChars); if R.Right > FCaptionRect.Right then begin ACaptionWidth := cxRectWidth(R); Dec(AImagesRect.Right, ACaptionWidth); ARightLimit := Bounds.Right - cxTextOffset - cxRectWidth(R); end; end; AImagesWidth := Images.CalculateSingleLineImages(AImagesRect, ARightLimit); if AImagesWidth > 0 then Inc(AImagesWidth); Inc(FCaptionRect.Left, AImagesWidth); ACaptionHeight := GetCaptionAutoHeight(CaptionRect); FCaptionRect.Bottom := FCaptionRect.Top + ACaptionHeight; Result := Max(Result, ACaptionHeight + 2 * cxTextOffset); AMessageTop := FCaptionRect.Top + Result; end; if FShowMessage then begin FMessageRect := cxRect(Bounds.Left + cxEventImagesGap, AMessageTop - 1, Bounds.Right - 1, 0); AMessageHeight := CalculateMessageHeight(FMessageRect); FMessageRect.Bottom := FMessageRect.Top + AMessageHeight; Inc(Result, AMessageHeight + 1); CalculateEditViewInfo; end; end; procedure TcxSchedulerEventCellViewInfo.CalculateMessageAutoLayout(var AHeight: Integer); var ACaptionHeight, AMessageHeight, AMessageTop: Integer; begin if not cxRectIsEmpty(CaptionRect) then begin ACaptionHeight := GetCaptionAutoHeight(CaptionRect); FCaptionRect.Bottom := CaptionRect.Top + ACaptionHeight; Inc(ACaptionHeight, 2 * cxTextOffset); AHeight := Max(AHeight, ACaptionHeight); if FShowMessage then begin AMessageTop := FCaptionRect.Top + ACaptionHeight - 1; FMessageRect := cxRect(FCaptionRect.Left - 2, AMessageTop, Bounds.Right - 1, 0); AMessageHeight := CalculateMessageHeight(FMessageRect); FMessageRect.Bottom := FMessageRect.Top + AMessageHeight; AHeight := Max(AHeight, ACaptionHeight + AMessageHeight); CalculateEditViewInfo; end; end else FShowMessage := False; end; function TcxSchedulerEventCellViewInfo.CalculateVerticalImagesAutoHeight: Integer; var AImagesRect: TRect; begin Result := Images.ItemHeight + cxTextOffset; if Images.TotalVisibleHeight > 0 then begin AImagesRect := cxRectInflate(Bounds, -cxTextOffset, -cxTextOffset); AImagesRect.Bottom := AImagesRect.Top + Images.TotalVisibleHeight; if (cxRectWidth(AImagesRect) > Images.ItemWidth + cxEventImagesGap) or (Images.ForceVisibleHeight > 0) then begin Inc(FCaptionRect.Left, Images.ItemWidth + cxTextOffset); Result := Images.TotalVisibleHeight + cxEventImagesGap; end; Images.CalculateSingleColumnImages(AImagesRect); end; CalculateMessageAutoLayout(Result); end; procedure TcxSchedulerEventCellViewInfo.CalculateItemsLayout; begin if IsDetailInfo then CalculateDetailViewEventLayout else CalculateHeaderEventLayout; end; procedure TcxSchedulerEventCellViewInfo.CalculateDetailViewEventLayout; var AImagesWidth: Integer; begin FCaptionRect := cxRectInflate(Bounds, -cxTextOffset, -(cxTextOffset + 1)); AImagesWidth := Images.Calculate(GetImagesBounds); Images.Offset(0, GetImagesVerticalOffset(Images.ItemHeight, False)); Inc(FCaptionRect.Left, AImagesWidth + cxEventImagesGap); if FShowMessage then CalculateEditViewInfo; end; procedure TcxSchedulerEventCellViewInfo.CalculateHeaderEventLayout; var ACaptionRect: TRect; ALeft, AWidth, AImagesWidth, ACaptionWidth, AVertOffset: Integer; ACanShowClock: Boolean; R: TRect; procedure CalculateCaption; var R: TRect; begin InflateRect(ACaptionRect, -cxTextOffset, 0); R := cxRectSetLeft(cxRectInflate(Bounds, -1, -1), 0, cxRectWidth(ACaptionRect) - (ACaptionWidth + cxTextOffset)); AImagesWidth := Images.CalculateSingleLineImages(R); if AImagesWidth <> 0 then Inc(AImagesWidth, cxTextOffset); AWidth := AImagesWidth + ACaptionWidth; end; begin FCaptionRect := cxRectInflate(Bounds, -cxTextOffset, -1); R := cxRect(0, 0, EventImages.Width, EventImages.Height); AVertOffset := GetImagesVerticalOffset(R.Bottom, True); ACaptionWidth := Canvas.TextWidth(ViewData.Caption); ACaptionRect := FCaptionRect; ACanShowClock := cxRectWidth(ACaptionRect) >= EventImages.Width + cxEventImagesGap; if ShowStartTime and ACanShowClock then begin FStartRect := cxRectOffset(R, Bounds.Left + (cxEventBorderWidth + cxEventImagesOffset), AVertOffset); ACaptionRect.Left := FStartRect.Right; end; if ShowFinishTime and ACanShowClock then begin FFinishRect := cxRectOffset(R, Bounds.Right - R.Right - (cxEventBorderWidth + cxEventImagesOffset), AVertOffset); ACaptionRect.Right := FFinishRect.Left; end; CalculateCaption; if (ShowStartTime or ShowFinishTime) and (ACaptionWidth + Images.TotalVisibleWidth > cxRectWidth(ACaptionRect)) and not GetForceShowClockInHeaderEvent then begin FStartRect := cxEmptyRect; FFinishRect := cxEmptyRect; ViewData.ShowStartTime := False; ViewData.ShowFinishTime := False; ACaptionRect := FCaptionRect; CalculateCaption; end; with ACaptionRect do ALeft := Max(Left + ((Right - Left - AWidth) div 2), ACaptionRect.Left); Images.Offset(ALeft, GetImagesVerticalOffset(Images.ItemHeight, False)); ACaptionRect.Left := ALeft + AImagesWidth; FCaptionRect := ACaptionRect; end; procedure TcxSchedulerEventCellViewInfo.CalculateNonDetailEventLayout; var R: TRect; ALeft, ACaptionWidth, AImagesWidth: Integer; begin FCaptionRect := cxRectInflate(Bounds, -cxTextOffset, -1); ALeft := CaptionRect.Left; ACaptionWidth := Canvas.TextWidth(ViewData.Caption); R := CalculateNonDetailEventImages(ACaptionWidth, AImagesWidth); if ShowFinishTime or ShowStartTime then begin if ShowTimeAsClock then CalculateEventTimeAsClockLayout(R, ACaptionWidth, AImagesWidth, ALeft) else CalculateEventTimeAsTextLayout(R, ACaptionWidth, AImagesWidth, ALeft); end; AImagesWidth := Images.Offset(ALeft - FCaptionRect.Left, GetImagesVerticalOffset(Images.ItemHeight, False)); if AImagesWidth > 0 then Inc(AImagesWidth); Inc(ALeft, AImagesWidth + cxEventImagesOffset); FCaptionRect.Left := ALeft; end; procedure TcxSchedulerEventCellViewInfo.CalculateEventTimeAsClockLayout( const ABounds: TRect; const ACaptionWidth, AImagesWidth: Integer; var ALeft: Integer); var R: TRect; AVertOffset: Integer; begin R := cxRectBounds(0, 0, TcxSchedulerPainterHelper.IconsWidth, TcxSchedulerPainterHelper.IconsHeight); AVertOffset := GetImagesVerticalOffset(R.Bottom, True); FStartRect := SetItemRect(ShowStartTime, R, AVertOffset, ALeft); FFinishRect := SetItemRect(ShowFinishTime, R, AVertOffset, ALeft); Inc(ALeft); end; procedure TcxSchedulerEventCellViewInfo.CalculateEventTimeAsTextLayout( const ABounds: TRect; const ACaptionWidth, AImagesWidth: Integer; var ALeft: Integer); var ASpaceWidth, AWidth: Integer; R: TRect; begin ASpaceWidth := cxRectWidth(ABounds) - AImagesWidth; with Canvas.TextExtent('00:00') do R := cxRectBounds(ABounds.Left, 0, CX, CY); if not Is24HourTimeFormat then R := cxRectSetWidth(R, Max(Canvas.TextWidth('00:00' + TimeAMString), Canvas.TextWidth('00:00' + TimePMString))); AWidth := cxRectWidth(R); if ASpaceWidth >= AWidth then begin FStartRect := cxRect(ALeft, FCaptionRect.Top, ALeft + AWidth, FCaptionRect.Bottom); Inc(AWidth, Canvas.TextWidth('0') div 2); Inc(ALeft, AWidth); Dec(ASpaceWidth, AWidth); if ShowFinishTime and (ASpaceWidth >= AWidth) then begin FFinishRect := cxRectOffset(FStartRect, AWidth, 0); Inc(ALeft, AWidth); end; end; end; function TcxSchedulerEventCellViewInfo.CalculateNonDetailEventImages( const ACaptionWidth: Integer; out AImagesWidth: Integer): TRect; begin Result := GetImagesBounds; AImagesWidth := CalculateSingleLineImages(Result); end; function TcxSchedulerEventCellViewInfo.CalculateSingleLineImages( const ABounds: TRect; ARightLimit: Integer = 0): Integer; begin Result := Images.CalculateSingleLineImages(ABounds, ARightLimit); end; function TcxSchedulerEventCellViewInfo.SetItemRect(AShowItem: Boolean; const ABounds: TRect; AVertOffset: Integer; var APos: Integer): TRect; begin Result := cxNullRect; if AShowItem then begin if ((APos + cxRectWidth(ABounds)) <= cxRectCenter(FBounds).X) then begin Result := cxRectOffset(ABounds, APos, AVertOffset); APos := Result.Right + cxTextOffset; end; end end; procedure TcxSchedulerEventCellViewInfo.CalculateEventTimeVisibility; begin if IsDetailInfo then CalculateDetailEventTimeVisibility else CalculateNonDetailEventTimeVisibility; end; procedure TcxSchedulerEventCellViewInfo.CalculateDetailEventTimeVisibility; begin ViewData.ShowFinishTime := (IsDetailCaption and ViewData.AlwaysShowTime) or ((ViewData.ContentFinish > EventFinish) and (ViewData.ContentStart <> EventFinish)) or (ViewData.ContentStart < EventStart); ViewData.ShowStartTime := ViewData.ShowFinishTime; end; procedure TcxSchedulerEventCellViewInfo.CalculateNonDetailEventTimeVisibility; begin if Event.AllDayEvent then begin ViewData.ShowFinishTime := False; ViewData.ShowStartTime := False; end else begin ViewData.ShowFinishTime := (ViewData.ContentFinish >= EventFinish) and (ViewData.ShowFinishTime or (Event.Duration >= 1)); ViewData.ShowStartTime := (ContentStart <= EventStart); end; end; procedure TcxSchedulerEventCellViewInfo.CalculateVisibility; begin if ViewData.ShowTimeLine then begin if Selected then FVisible := cxRectIntersect(FClipRect, cxRectInflate(Bounds, 0, cxTimeLineWidth), ViewData.VisibleRect); end else FVisible := FVisible and (FClipRect.Bottom = FBounds.Bottom); CalculateDetailInfo; CalculateShowTimeAsClock; CalculateEventTimeVisibility; CalculateBorders; end; function TcxSchedulerEventCellViewInfo.CanAutoHideStandardImages: Boolean; begin Result := False; end; function TcxSchedulerEventCellViewInfo.CanShowHint: Boolean; begin Result := not Event.AllDayEvent and not IsDetailInfo and (cxRectIsEmpty(FinishRect) or cxRectIsEmpty(StartRect)); end; procedure TcxSchedulerEventCellViewInfo.DoDraw; begin if FHidden then Exit; ClippingCreate(True); DrawContent; ClippingRestore; end; procedure TcxSchedulerEventCellViewInfo.DrawCaption; begin if cxRectIsEmpty(FCaptionRect) or (ViewData.Caption = '') then Exit; Canvas.Brush.Style := bsClear; Canvas.DrawText(ViewData.Caption, FCaptionRect, cxDrawTextFlags[IsDetailCaption]); Canvas.Brush.Style := bsSolid; end; procedure TcxSchedulerEventCellViewInfo.DrawContent; begin if ViewData.DrawAsProgress then ExternalPainter.DrawEventAsProgress(Self) else begin ExternalPainter.DrawEvent(Self); if not Event.IsEditing then DrawImages; if IsNeedDrawTime then DrawTime; DrawCaption; if FShowMessage then begin FEditViewInfo.Transparent := True; FEditViewInfo.TextColor := TextColor; FEditViewInfo.PaintEx(Canvas); DrawMessageSeparator; end; end; end; procedure TcxSchedulerEventCellViewInfo.DrawImages; var I: Integer; ASaveRgn: TcxRegion; begin with Images do begin if Count = 0 then Exit; ASaveRgn := Canvas.GetClipRegion; Canvas.IntersectClipRect(cxRectInflate(Bounds, -1, -1)); for I := 0 to Count - 1 do with Items[I] do if Visible and not FHidden then PainterHelper.DrawTransparentImage(Canvas, Images, Bounds.Left, Bounds.Top, ImageIndex); Canvas.SetClipRegion(ASaveRgn, roSet); end; end; procedure TcxSchedulerEventCellViewInfo.DrawMessageSeparator; var R: TRect; begin R := cxRectInflate(MessageRect, -(1 + Byte(not ShowTimeLine)), 1, -2, 0); Canvas.FrameRect(R, SeparatorColor, 1, [bTop]); end; procedure TcxSchedulerEventCellViewInfo.DrawTime; const RightJustify = cxAlignRight or cxAlignVCenter or cxSingleLine; begin if ShowTimeAsClock then begin if ShowStartTime then PainterHelper.DrawClock(Canvas, FStartRect, Event.Start, FViewParams); if ShowFinishTime then PainterHelper.DrawClock(Canvas, FFinishRect, Event.Finish, FViewParams); end else begin DrawText(FStartRect, FStartText, RightJustify); DrawText(FFinishRect, FFinishText, RightJustify); end; end; function TcxSchedulerEventCellViewInfo.GetCaptionAutoHeight(const R: TRect): Integer; begin if (Caption <> '') and not cxRectIsEmpty(CaptionRect) then Result := GetTrueMultilineTextHeight(Canvas, ViewData.Caption, R) else Result := Canvas.FontHeight(Font); end; function TcxSchedulerEventCellViewInfo.GetEditingRect: TRect; begin cxRectIntersect(Result, PainterHelper.ExcludeBorders(Bounds, Borders), FClipRect); with Result do begin if IsDetailCaption then begin Inc(Left, cxTextOffset - Byte(bLeft in Borders)); Dec(Right); end else Inc(Left); end; end; function TcxSchedulerEventCellViewInfo.GetForceShowClockInHeaderEvent: Boolean; begin Result := True; end; function TcxSchedulerEventCellViewInfo.GetHitTest( AHitTest: TcxSchedulerCustomResourceViewHitTest; var ABreak: Boolean): Boolean; begin Result := inherited GetHittest(AHitTest, ABreak); Result := Result and not Hidden; if Result and not Hidden and ShowTimeLine and Selected then ABreak := not PtInRect(CaptionRect, AHitTest.HitPoint) and not PtInRect(MessageRect, AHitTest.HitPoint) else ABreak := False; end; function TcxSchedulerEventCellViewInfo.GetImagesBounds: TRect; begin with Bounds do Result := cxRect(Left + cxEventBorderWidth + cxEventImagesOffset - Byte(ViewData.ShowTimeLine), Top + cxEventBorderWidth, (Left + Right - cxTextOffset) div 2, Bottom - (cxEventBorderWidth + cxEventImagesOffset)); end; function TcxSchedulerEventCellViewInfo.GetImagesVerticalOffset( AImageHeight: Integer; AIsAbsolute: Boolean): Integer; begin Result := cxEventImagesOffset; if not FIsDetailCaption then Result := Max(Result, (cxRectHeight(Bounds) - 2 * cxEventBorderWidth - AImageHeight) div 2); if AIsAbsolute then Inc(Result, Bounds.Top + cxEventBorderWidth); end; function TcxSchedulerEventCellViewInfo.GetMessageRect(const ACaptionRect: TRect; AHasImages: Boolean): TRect; var ACaptionBottom: Integer; R: TRect; begin if not cxRectIsEmpty(ACaptionRect) then begin R := GetCaptionBounds(ACaptionRect); ACaptionBottom := R.Bottom + cxTextOffset; //bottom text offset end else ACaptionBottom := Bounds.Top + cxTextOffset; if AHasImages then ACaptionBottom := Max(ACaptionBottom, Bounds.Top + Images.ItemHeight); Inc(ACaptionBottom); //horz line Result.Top := ACaptionBottom; Result.Bottom := Bounds.Bottom; Result.Right := Bounds.Right - 1; if Images.Layout = eilHorizontal then Result.Left := Bounds.Left + cxEventBorderWidth else Result.Left := R.Left - cxTextOffset; end; function TcxSchedulerEventCellViewInfo.HasReminder: Boolean; begin with Event do begin Result := Storage.Reminders.Active and Storage.IsReminderAvailable and Reminder; if Result and (ResourceItem <> nil) and Storage.IsReminderByResourceAvailable then Result := HasReminderForResourceID(ResourceItem.ResourceID); end; end; procedure TcxSchedulerEventCellViewInfo.Initialize; begin FBorders := cxBordersAll; FEventStart := TruncTime(Event.Start); FEventFinish := TruncTime(Event.Finish); FIsHeaderEvent := GetIsHeaderEvent; FStartRect := cxNullRect; FFinishRect := cxNullRect; FTimeLineRect := cxNullRect; ViewData.ShowTimeLine := ViewData.ShowTimeLine and IsTimeLineVisible; InitStandardEventImages; CalculateVisibility; CalculateCaptions; end; procedure TcxSchedulerEventCellViewInfo.InitHitTest( AHitTest: TcxSchedulerCustomResourceViewHitTest); begin AHitTest.FEventCell := Self; AHitTest.FEventBounds := FClipRect; AHitTest.FDragKind := edkMoveEvent; CalculateNeedHint; AHitTest.FNeedShowHint := FHintNeeded; end; procedure TcxSchedulerEventCellViewInfo.InitHitTestForHorzEvent( AHitTest: TcxSchedulerCustomResourceViewHitTest); begin if (bLeft in Borders) and ((AHitTest.HitX - Bounds.Left) <= cxHitDelta) then AHitTest.FDragKind := edkResizeStart else if (bRight in Borders) and ((Bounds.Right - AHitTest.HitX) <= cxHitDelta) then AHitTest.FDragKind := edkResizeEnd; end; procedure TcxSchedulerEventCellViewInfo.InitStandardEventImages; var AutoHide: Boolean; begin AutoHide := CanAutoHideStandardImages; with Event do begin if HasReminder then Images.AddStandardImage(eitReminder, AutoHide); case EventType of etOccurrence: Images.AddStandardImage(eitRecurrence, AutoHide); etCustom: Images.AddStandardImage(eitCustomOccurrence, AutoHide); end; end; end; function TcxSchedulerEventCellViewInfo.IsHorzSizing: Boolean; begin Result := True; end; function TcxSchedulerEventCellViewInfo.IsNeedDrawTime: Boolean; begin Result := ViewData.ShowFinishTime or ViewData.ShowStartTime; end; function TcxSchedulerEventCellViewInfo.IsTimeLineVisible: Boolean; begin Result := False; end; function TcxSchedulerEventCellViewInfo.TruncTime( const ATime: TDateTime): TDateTime; begin Result := DateTimeHelper.RoundTime(ATime); end; function TcxSchedulerEventCellViewInfo.GetContentFinish: TDateTime; begin Result := ViewData.ContentFinish; end; function TcxSchedulerEventCellViewInfo.CalculateMessageHeight(const R: TRect): Integer; function CreateEditViewData: TcxCustomEditViewData; begin with ViewData do Result := EditProperties.CreateViewData(EditStyle, True); end; var AEditViewData: TcxCustomEditViewData; ASize: TcxEditSizeProperties; begin AEditViewData := CreateEditViewData; try AssignEditStyle(ViewData.EditStyle); AEditViewData.ContentOffset := cxSimpleRect; ASize.MaxLineCount := 0; ASize.Height := -1; ASize.Width := cxRectWidth(R); Result := AEditViewData.GetEditSize(Canvas, Message, ASize).cy; finally AEditViewData.Free; end; end; function TcxSchedulerEventCellViewInfo.GetBorderColor: TColor; begin Result := ViewData.BorderColor; end; function TcxSchedulerEventCellViewInfo.GetCaption: string; begin Result := ViewData.Caption; end; function TcxSchedulerEventCellViewInfo.GetCaptionBounds(const R: TRect): TRect; begin Result := R; if Length(ViewData.Caption) > 0 then Canvas.TextExtent(ViewData.Caption, Result, cxDrawTextFlags[IsDetailCaption]) else Canvas.TextExtent('Wg', Result, cxDrawTextFlags[IsDetailCaption]); end; function TcxSchedulerEventCellViewInfo.GetContentStart: TDateTime; begin Result := ViewData.ContentStart; end; function TcxSchedulerEventCellViewInfo.GetEvent: TcxSchedulerControlEvent; begin Result := ViewData.Event; end; function TcxSchedulerEventCellViewInfo.GetHint: string; begin if not FHintAssigned then FHint := ViewData.GetEventHint(Event); FHintAssigned := True; Result := FHint; end; function TcxSchedulerEventCellViewInfo.GetIsHeaderEvent: Boolean; begin Result := Event.AllDayEvent or ((Event.Finish - Event.Start) >= 1); end; function TcxSchedulerEventCellViewInfo.GetMessage: string; begin Result := Event.Message; end; function TcxSchedulerEventCellViewInfo.GetResourceInfo: TcxSchedulerResourceViewInfo; begin Result := ViewData.Resource; end; function TcxSchedulerEventCellViewInfo.GetResourceItem: TcxSchedulerStorageResourceItem; begin Result := nil; if ResourceInfo <> nil then Result := ResourceInfo.ResourceItem; end; function TcxSchedulerEventCellViewInfo.GetSelected: Boolean; begin Result := Event.Selected; end; function TcxSchedulerEventCellViewInfo.GetShowingState( AIndex: Integer): Boolean; begin case AIndex of 0: Result := ViewData.ShowFinishTime; 1: Result := ViewData.ShowStartTime; 2: Result := ViewData.ShowTimeAsClock; 3: Result := ViewData.ShowTimeLine; else Result := False; end; end; procedure TcxSchedulerEventCellViewInfo.SetBorderColor(AValue: TColor); begin ViewData.BorderColor := AValue; end; { TcxSchedulerMoreEventsButtonViewInfo } procedure TcxSchedulerMoreEventsButtonViewInfo.Click; begin if Assigned(FOnClick) then FOnClick(Self); end; procedure TcxSchedulerMoreEventsButtonViewInfo.DoDraw; begin PainterHelper.DrawTransparentImage(Canvas, MoreEventButtonGlyphs, Bounds.Left, Bounds.Top, Byte(not IsDown)); end; procedure TcxSchedulerMoreEventsButtonViewInfo.InitHitTest( AHitTest: TcxSchedulerCustomResourceViewHitTest); begin inherited InitHitTest(AHitTest); AHitTest.SetBitState(htcButton, True); AHitTest.FButton := Self; if Int(DateTime) > 0 then AHitTest.SetHitTime(htcTime, Int(DateTime)); end; { TcxSchedulerContentNavigationButtonViewInfo } procedure TcxSchedulerContentNavigationButtonViewInfo.Click; begin if Enabled and Assigned(FOnClick) then FOnClick(Self); end; procedure TcxSchedulerContentNavigationButtonViewInfo.DoDraw; var AState: TcxButtonState; begin if Enabled then begin if (FHitTest <> nil) and (FHitTest.FContentNavigationButton = Self) then AState := cxbsHot else AState := cxbsNormal; end else AState := cxbsDisabled; Painter.DrawSchedulerNavigationButton(Canvas, Bounds, Kind = nbkNext, AState, Caption, TextRect, ArrowRect); end; procedure TcxSchedulerContentNavigationButtonViewInfo.InitHitTest( AHitTest: TcxSchedulerCustomResourceViewHitTest); begin FHitTest := AHitTest; inherited InitHitTest(AHitTest); AHitTest.SetBitState(htcNavigationButton, True); AHitTest.FContentNavigationButton := Self; end; function TcxSchedulerContentNavigationButtonViewInfo.GetEnabled: Boolean; begin Result := Abs(Interval) < cxMaxDateTime; end; { TcxSchedulerGroupSeparatorCellViewInfo } destructor TcxSchedulerGroupSeparatorCellViewInfo.Destroy; begin FreeAndNil(FRotateBitmap); inherited Destroy; end; procedure TcxSchedulerGroupSeparatorCellViewInfo.DoDraw; procedure CreateRotatedBitmap; begin FRotateBitmap := TcxBitmap.CreateSize(Bounds, pf32bit); FRotateBitmap.Canvas.Lock; FRotateBitmap.cxCanvas.WindowOrg := Bounds.TopLeft; end; begin if not Rotated then Painter.DrawHeader(Canvas, Bounds, Bounds, [nRight, nLeft], cxBordersAll, cxbsNormal, taLeftJustify, vaCenter, False, False, '', nil, clNone, Color, DrawBackground) else begin if FRotateBitmap = nil then begin CreateRotatedBitmap; FDrawRotatedBackground := DrawBackground(FRotateBitmap.cxCanvas, Bounds); FRotateBitmap.Rotate(raPlus90); Painter.DrawHeader(FRotateBitmap.cxCanvas, Rect(0, 0, FRotateBitmap.Width, FRotateBitmap.Height), cxNullRect, [nRight, nLeft], cxBordersAll, cxbsNormal, taCenter, vaCenter, False, False, '', nil, clNone, Color, DrawRotateBackground); FRotateBitmap.Rotate(raPlus90); end; Canvas.Draw(Bounds.Left, Bounds.Top, FRotateBitmap); end; end; procedure TcxSchedulerGroupSeparatorCellViewInfo.InitHitTest( AHitTest: TcxSchedulerCustomResourceViewHitTest); begin AHitTest.SetBitState(htcGroupSeparator, True); end; function TcxSchedulerGroupSeparatorCellViewInfo.DrawRotateBackground( ACanvas: TcxCanvas; const ABounds: TRect): Boolean; begin Result := FDrawRotatedBackground; end; { TcxSchedulerResourceViewInfo } constructor TcxSchedulerResourceViewInfo.Create( AResource: TcxSchedulerStorageResourceItem); begin FResourceItem := AResource; FColor := AResource.Color; FResourceID := AResource.ResourceID; FCaption := AResource.Resources.GetResourceName(FResourceItem); FImages := AResource.Resources.Images; FImageIndex := AResource.ActualImageIndex; end; { TcxSchedulerExternalPainter } procedure TcxSchedulerExternalPainter.DoCustomDrawBackground( AViewInfo: TcxSchedulerBackgroundCellViewInfo; var ADone: Boolean); begin if FCommonPainter <> nil then FCommonPainter.DoCustomDrawBackground(AViewInfo, ADone); end; procedure TcxSchedulerExternalPainter.DoCustomDrawButton( AViewInfo: TcxSchedulerMoreEventsButtonViewInfo; var ADone: Boolean); begin if FCommonPainter <> nil then FCommonPainter.DoCustomDrawButton(AViewInfo, ADone); end; procedure TcxSchedulerExternalPainter.DoCustomDrawContent( AViewInfo: TcxSchedulerContentCellViewInfo; var ADone: Boolean); begin if FCommonPainter <> nil then FCommonPainter.DoCustomDrawContent(AViewInfo, ADone); end; procedure TcxSchedulerExternalPainter.DoCustomDrawDayHeader( AViewInfo: TcxSchedulerDayHeaderCellViewInfo; var ADone: Boolean); begin if FCommonPainter <> nil then FCommonPainter.DoCustomDrawDayHeader(AViewInfo, ADone); end; procedure TcxSchedulerExternalPainter.DoCustomDrawEvent( AViewInfo: TcxSchedulerEventCellViewInfo; var ADone: Boolean); begin if FCommonPainter <> nil then FCommonPainter.DoCustomDrawEvent(AViewInfo, ADone); end; procedure TcxSchedulerExternalPainter.DoCustomDrawGroupSeparator( AViewInfo: TcxSchedulerGroupSeparatorCellViewInfo; var ADone: Boolean); begin if FCommonPainter <> nil then FCommonPainter.DoCustomDrawGroupSeparator(AViewInfo, ADone); end; procedure TcxSchedulerExternalPainter.DoCustomDrawNavigationButton( AViewInfo: TcxSchedulerContentNavigationButtonViewInfo; var ADone: Boolean); begin if FCommonPainter <> nil then FCommonPainter.DoCustomDrawNavigationButton(AViewInfo, ADone); end; procedure TcxSchedulerExternalPainter.DoCustomDrawResourceHeader( AViewInfo: TcxSchedulerHeaderCellViewInfo; var ADone: Boolean); begin if FCommonPainter <> nil then FCommonPainter.DoCustomDrawResourceHeader(AViewInfo, ADone); end; function TcxSchedulerExternalPainter.HasCustomDrawGroupSeparator: Boolean; begin Result := (FCommonPainter <> nil) and FCommonPainter.HasCustomDrawGroupSeparator; end; function TcxSchedulerExternalPainter.HasCustomDrawResourceHeader: Boolean; begin Result := (FCommonPainter <> nil) and FCommonPainter.HasCustomDrawResourceHeader; end; procedure TcxSchedulerExternalPainter.DrawAllDayArea(ACanvas: TcxCanvas; const ARect: TRect; ABorderColor: TColor; ABorders: TcxBorders; AViewParams: TcxViewParams; ASelected: Boolean; ATransparent: Boolean); begin if ATransparent then ACanvas.FrameRect(ARect, ABorderColor, 1, ABorders) else ACanvas.FillRect(ARect, AViewParams, ABorders, ABorderColor, 1); end; procedure TcxSchedulerExternalPainter.DrawCurrentTime(ACanvas: TcxCanvas; AColor: TColor; AStart: TDateTime; ABounds: TRect); var Y: Integer; ANow: TDateTime; begin ANow := TimeOf(Now) - TimeOf(AStart); if (ANow < 0) or (ANow >= HourToTime) then Exit; Y := Round(ABounds.Top + (ANow * cxRectHeight(ABounds)) / HourToTime); Dec(Y, 3); Dec(ABounds.Right); if Y < ABounds.Top then Y := ABounds.Top; PainterHelper.DrawGradientRect(ACanvas, AColor, cxRectSetTop(ABounds, Y - 6, 6)); end; function TcxSchedulerExternalPainter.NeedDrawSelection: Boolean; begin Result := True; end; function TcxSchedulerExternalPainter.DrawCurrentTimeFirst: Boolean; begin Result := True; end; procedure TcxSchedulerExternalPainter.DrawEvent( AViewInfo: TcxSchedulerEventCellViewInfo); begin with AViewInfo do DrawRect(Bounds, Borders, ViewData.BorderColor); end; procedure TcxSchedulerExternalPainter.DrawEventAsProgress( AViewInfo: TcxSchedulerEventCellViewInfo); var AContent: TRect; AProgressRect: TRect; begin with AViewInfo do begin AContent := cxRectContent(Bounds, Painter.SchedulerEventProgressOffsets); AProgressRect := AContent; AProgressRect.Right := AProgressRect.Left + Trunc(ViewData.TaskComplete / 100 * cxRectWidth(AProgressRect)); Painter.DrawSchedulerEventProgress(Canvas, Bounds, AProgressRect, ViewParams, Transparent); Canvas.Brush.Style := bsClear; Canvas.Font.Color := Painter.ProgressBarTextColor; DrawEventAsProgressText(AViewInfo, AContent, AProgressRect, IntToStr(ViewData.TaskComplete) + '%'); end; end; procedure TcxSchedulerExternalPainter.DrawEventAsProgressText( AViewInfo: TcxSchedulerEventCellViewInfo; AContent: TRect; AProgressRect: TRect; const AText: string); begin Painter.DrawProgressBarText(AViewInfo.Canvas, False, False, AText, cxRectCenter(AContent, AViewInfo.Canvas.TextExtent(AText)), AContent, AProgressRect); end; procedure TcxSchedulerExternalPainter.DrawTimeGridCurrentTime(ACanvas: TcxCanvas; AColor: TColor; const ATimeLineRect: TRect); begin ACanvas.FillRect(ATimeLineRect, AColor); end; procedure TcxSchedulerExternalPainter.DrawTimeGridHeader(ACanvas: TcxCanvas; ABorderColor: TColor; AViewInfo: TcxSchedulerCustomViewInfoItem; ABorders: TcxBorders; ASelected: Boolean); begin with AViewInfo do DrawRect(Bounds, Borders, ABorderColor); end; procedure TcxSchedulerExternalPainter.DrawTimeLine(ACanvas: TcxCanvas; const ARect: TRect; AViewParams: TcxViewParams; ABorders: TcxBorders; ABorderColor: TColor); begin ACanvas.FillRect(ARect, AViewParams, ABorders, ABorderColor); end; procedure TcxSchedulerExternalPainter.DrawTimeRulerBackground(ACanvas: TcxCanvas; const ARect: TRect; ABorders: TcxBorders; AViewParams: TcxViewParams; ATransparent: Boolean); begin if ATransparent then ACanvas.FrameRect(ARect, clBtnShadow, 1, ABorders) else ACanvas.FillRect(ARect, AViewParams, ABorders, clBtnShadow, 1); end; procedure TcxSchedulerExternalPainter.DrawShadow(ACanvas: TcxCanvas; const ARect, AVisibleRect: TRect; ABuffer: TBitmap); begin PainterHelper.DrawShadow(ACanvas, ARect, AVisibleRect, ABuffer); end; function TcxSchedulerExternalPainter.GetPainterHelper: TcxSchedulerPainterHelperClass; begin Result := SchedulerHelpersFactory.PainterHelperClass; end; function TcxSchedulerExternalPainter.MoreButtonSize(ASize: TSize): TSize; begin Result := ASize; end; { TcxSchedulerCustomResourceView } constructor TcxSchedulerCustomResourceView.Create( AOwner: TcxCustomScheduler); begin inherited Create(AOwner); FShowEndTime := True; InitializePainter; end; destructor TcxSchedulerCustomResourceView.Destroy; begin FinilizePainter; inherited Destroy; end; procedure TcxSchedulerCustomResourceView.Assign(Source: TPersistent); begin if Source is TcxSchedulerCustomResourceView then begin ShowEndTime := TcxSchedulerCustomResourceView(Source).ShowEndTime; ShowTimeAsClock := TcxSchedulerCustomResourceView(Source).ShowTimeAsClock; FGroupingKind := TcxSchedulerCustomResourceView(Source).GroupingKind; end; inherited Assign(Source); end; procedure TcxSchedulerCustomResourceView.InitializePainter; begin if FExternalPainter = nil then FExternalPainter := ExternalPainterClass.Create; end; procedure TcxSchedulerCustomResourceView.FinilizePainter; begin FExternalPainter := nil; end; procedure TcxSchedulerCustomResourceView.CalculateViewInfo; begin Adapter.Calculate; end; procedure TcxSchedulerCustomResourceView.CheckGroupingKind( AStyle: TcxSchedulerGroupingKind; var ActuallyStyle: TcxSchedulerGroupingKind); begin ActuallyStyle := AStyle; end; procedure TcxSchedulerCustomResourceView.ClearCachedData; begin ViewInfo.ImageCacheManager.Invalidate; end; function TcxSchedulerCustomResourceView.CreateController: TcxSchedulerSubControlController; begin Result := TcxSchedulerCustomResourceViewController.Create(Self); end; function TcxSchedulerCustomResourceView.CreateHitTest: TcxSchedulerSubControlHitTest; begin Result := TcxSchedulerCustomResourceViewHitTest.Create(Self); end; function TcxSchedulerCustomResourceView.CreateViewAdapter: TcxCustomResourceViewAdapter; begin Result := TcxCustomResourceViewAdapter.Create(Self); end; procedure TcxSchedulerCustomResourceView.CreateSubClasses; begin inherited CreateSubClasses; FAdapter := CreateViewAdapter; ViewInfo.FAdapter := FAdapter; end; procedure TcxSchedulerCustomResourceView.DestroySubClasses; var Adapter: TObject; begin Adapter := ViewInfo.FAdapter; inherited DestroySubClasses; Adapter.Free; end; procedure TcxSchedulerCustomResourceView.DoCustomDrawBackground( AViewInfo: TcxSchedulerBackgroundCellViewInfo; var ADone: Boolean); begin if Assigned(FOnCustomDrawBackground) then FOnCustomDrawBackground(Self, Canvas, AViewInfo, ADone); end; procedure TcxSchedulerCustomResourceView.DoCustomDrawButton( AViewInfo: TcxSchedulerMoreEventsButtonViewInfo; var ADone: Boolean); begin if Assigned(FOnCustomDrawButton) then FOnCustomDrawButton(Self, Canvas, AViewInfo, ADone); end; procedure TcxSchedulerCustomResourceView.DoCustomDrawContent( AViewInfo: TcxSchedulerContentCellViewInfo; var ADone: Boolean); begin if Assigned(FOnCustomDrawContent) then FOnCustomDrawContent(Self, Canvas, AViewInfo, ADone); end; procedure TcxSchedulerCustomResourceView.DoCustomDrawDayHeader( AViewInfo: TcxSchedulerDayHeaderCellViewInfo; var ADone: Boolean); begin if Assigned(FOnCustomDrawDayHeader) then FOnCustomDrawDayHeader(Self, Canvas, AViewInfo, ADone); end; procedure TcxSchedulerCustomResourceView.DoCustomDrawEvent( AViewInfo: TcxSchedulerEventCellViewInfo; var ADone: Boolean); begin if Assigned(FOnCustomDrawEvent) then FOnCustomDrawEvent(Self, Canvas, AViewInfo, ADone); end; procedure TcxSchedulerCustomResourceView.DoCustomDrawGroupSeparator( AViewInfo: TcxSchedulerGroupSeparatorCellViewInfo; var ADone: Boolean); begin if Assigned(FOnCustomDrawGroupSeparator) then FOnCustomDrawGroupSeparator(Self, Canvas, AViewInfo, ADone); end; procedure TcxSchedulerCustomResourceView.DoCustomDrawNavigationButton( AViewInfo: TcxSchedulerContentNavigationButtonViewInfo; var ADone: Boolean); begin if Assigned(FOnCustomDrawNavigationButton) then FOnCustomDrawNavigationButton(Self, Canvas, AViewInfo, ADone); end; procedure TcxSchedulerCustomResourceView.DoCustomDrawResourceHeader( AViewInfo: TcxSchedulerHeaderCellViewInfo; var ADone: Boolean); begin if Assigned(FOnCustomDrawResourceHeader) then FOnCustomDrawResourceHeader(Self, Canvas, AViewInfo, ADone); end; procedure TcxSchedulerCustomResourceView.DoLayoutChanged; begin inherited DoLayoutChanged; if Active then begin if (ViewInfo.GroupingKind = gkNone) and (Scheduler.SelResource <> nil) then with Controller.Navigation do ReplaceSelParams(SelStart, SelFinish, nil) else if (ViewInfo.GroupingKind <> gkNone) and (Scheduler.SelResource = nil) then with Controller.Navigation do ReplaceSelParams(SelStart, SelFinish, VisibleResources[0]); end; end; procedure TcxSchedulerCustomResourceView.DoMouseDown(AButton: TMouseButton; AShift: TShiftState; X, Y: Integer); begin inherited DoMouseDown(AButton, AShift, X, Y); if AButton = mbRight then CheckSelectOnRightClick; end; function TcxSchedulerCustomResourceView.DoShowPopupMenu(X, Y: Integer): Boolean; var ATime: TDateTime; AResource: TcxSchedulerStorageResourceItem; ASelectOnRightClick: Boolean; begin Result := False; if HitTest.HitAtEvent then Result := not Controller.IsEditing and Scheduler.EventPopupMenu.Popup(X, Y) else begin ASelectOnRightClick := Scheduler.OptionsBehavior.SelectOnRightClick; if not ASelectOnRightClick or (IsRelevantSelection(ATime, AResource) and ASelectOnRightClick) then Result := Scheduler.ContentPopupMenu.Popup(X, Y); end; end; function TcxSchedulerCustomResourceView.FindEventViewInfo(AEvent: TcxSchedulerEvent; const ADate: TDateTime; AResource: TcxSchedulerStorageResourceItem; var AViewInfo: TcxSchedulerEventCellViewInfo): Boolean; var I: Integer; begin Result := False; for I := 0 to ViewInfo.EventCells.Count - 1 do begin AViewInfo := TcxSchedulerEventCellViewInfo(ViewInfo.EventCells[I]); if AViewInfo.Event = AEvent then begin Result := True; with AViewInfo do begin if (AResource = nil) or (ResourceItem = AResource) then if (ADate = NullDate) or ((DateOf(ContentStart) = ADate) or (IsHeaderEvent and (ADate >= DateOf(ContentStart)) and (ADate < DateOf(ContentFinish)))) then Break; end; end; end; end; function TcxSchedulerCustomResourceView.GetCommonViewItemsPainter: IcxSchedulerCommonViewItemsPainter; var ACustomPainter: IcxSchedulerCommonViewItemsPainter; begin if not Supports(TObject(Scheduler), IcxSchedulerCommonViewItemsPainter, ACustomPainter) then ACustomPainter := nil; InitializePainter; ExternalPainter.Painter := LookAndFeelPainter; ExternalPainter.CommonPainter := ACustomPainter; Result := ExternalPainter; end; function TcxSchedulerCustomResourceView.GetCompressWeekEnd: Boolean; begin Result := False; end; function TcxSchedulerCustomResourceView.GetEditRectForEvent( AEvent: TcxSchedulerControlEvent; const ADate: TDateTime; AResource: TcxSchedulerStorageResourceItem): TRect; var AViewInfo: TcxSchedulerEventCellViewInfo; begin if FindEventViewInfo(AEvent, ADate, AResource, AViewInfo) then Result := AViewInfo.EditingRect else Result := inherited GetEditRectForEvent(AEvent, ADate, AResource); end; procedure TcxSchedulerCustomResourceView.InitScrollBarsParameters; begin ViewInfo.InitScrollBarsParameters; end; function TcxSchedulerCustomResourceView.GetEventHintText(AEvent: TcxSchedulerControlEvent): string; var AViewInfo: TcxSchedulerEventCellViewInfo; begin if FindEventViewInfo(AEvent, NullDate, nil, AViewInfo) then Result := AViewInfo.Hint else Result := inherited GetEventHintText(AEvent); end; function TcxSchedulerCustomResourceView.GetEventVisibility( AEvent: TcxSchedulerControlEvent): Boolean; var AViewInfo: TcxSchedulerEventCellViewInfo; begin Result := FindEventViewInfo(AEvent, NullDate, nil, AViewInfo) end; function TcxSchedulerCustomResourceView.GetGroupingKind: TcxSchedulerGroupingKind; begin Result := GroupingKind; if Result = gkDefault then Result := OptionsView.GroupingKind; end; function TcxSchedulerCustomResourceView.HasCustomDrawGroupSeparator: Boolean; begin Result := Assigned(FOnCustomDrawGroupSeparator) or ExternalPainter.HasCustomDrawGroupSeparator; end; function TcxSchedulerCustomResourceView.HasCustomDrawResourceHeader: Boolean; begin Result := Assigned(FOnCustomDrawResourceHeader) or ExternalPainter.HasCustomDrawResourceHeader; end; function TcxSchedulerCustomResourceView.IsShowResources: Boolean; var AKind: TcxSchedulerGroupingKind; begin Result := inherited IsShowResources; if Result then begin AKind := GroupingKind; if AKind = gkDefault then AKind := OptionsView.GroupingKind; Result := AKind <> gkNone; end; end; procedure TcxSchedulerCustomResourceView.LookAndFeelChanged( Sender: TcxLookAndFeel; AChangedValues: TcxLookAndFeelValues); begin ViewInfo.ImageCacheManager.Invalidate; end; procedure TcxSchedulerCustomResourceView.Scroll(AScrollBarKind: TScrollBarKind; AScrollCode: TScrollCode; var AScrollPos: Integer); begin if AScrollBarKind = sbHorizontal then ViewInfo.ScrollHorizontal(AScrollCode, AScrollPos) else ViewInfo.ScrollVertical(AScrollCode, AScrollPos); inherited Scroll(AScrollBarKind, AScrollCode, AScrollPos); end; procedure TcxSchedulerCustomResourceView.SetGroupingKind( AValue: TcxSchedulerGroupingKind); begin CheckGroupingKind(AValue, AValue); if (FGroupingKind <> AValue) then begin FGroupingKind := AValue; LayoutChanged; end; end; procedure TcxSchedulerCustomResourceView.CheckSelectOnRightClick; var ATime: TDateTime; AResource: TcxSchedulerStorageResourceItem; begin if Scheduler.OptionsBehavior.SelectOnRightClick and not IsRelevantSelection(ATime, AResource) then begin if AResource <> nil then Scheduler.SelectTime(ATime, ATime, AResource) else Scheduler.SelectTime(ATime, ATime, Scheduler.SelResource) end; end; function TcxSchedulerCustomResourceView.GetViewInfo: TcxSchedulerCustomResourceViewViewInfo; begin Result := TcxSchedulerCustomResourceViewViewInfo(inherited ViewInfo); end; function TcxSchedulerCustomResourceView.IsRelevantSelection(out ATime: TDateTime; out AResource: TcxSchedulerStorageResourceItem): Boolean; begin ATime := HitTest.Time; if ATime < 1 then ATime := ATime + DateOf(Scheduler.SelStart); AResource := HitTest.Resource; Result := ((ATime >= Scheduler.SelStart) and (ATime < Scheduler.SelFinish)) and ((Scheduler.SelResource = AResource) or (AResource = nil)); end; procedure TcxSchedulerCustomResourceView.SetEventImagesLayout( const AValue: TcxSchedulerEventImagesLayout); begin if FEventImagesLayout <> AValue then begin FEventImagesLayout := AValue; LayoutChanged; end; end; procedure TcxSchedulerCustomResourceView.SetShowEndTime( const AValue: Boolean); begin if FShowEndTime <> AValue then begin FShowEndTime := AValue; LayoutChanged; end; end; procedure TcxSchedulerCustomResourceView.SetShowTimeAsClock( const AValue: Boolean); begin if FShowTimeAsClock <> AValue then begin FShowTimeAsClock := AValue; LayoutChanged; end; end; { TcxCustomResourceViewAdapter } constructor TcxCustomResourceViewAdapter.Create( AView: TcxSchedulerCustomResourceView); begin FView := AView; end; procedure TcxCustomResourceViewAdapter.Calculate; var FPrevAdapter: TcxCustomResourceViewAdapter; begin FPrevAdapter := FView.ViewInfo.SetAdapter(Self); FPrevAdapter.Store; try BeforeCalculatePage; FView.ViewInfo.Calculate; AfterCalculatePage; finally FView.ViewInfo.SetAdapter(FPrevAdapter); if (FPrevAdapter <> Self) and FView.Active then begin FPrevAdapter.Restore; FView.ViewInfo.Calculate; end; FView.ViewInfo.FStylesAdapter := nil; end; end; procedure TcxCustomResourceViewAdapter.GetPageResources( AResources: TcxObjectList); var ACount, I: Integer; AResourceViewInfo: TcxSchedulerResourceViewInfo; begin if Resources = nil then Exit; Scheduler.ValidateFirstVisibleResourceIndex; ACount := Resources.VisibleResourceCount; with Scheduler.OptionsView do begin if (ResourcesPerPage > 0) and (ACount > ResourcesPerPage) then ACount := ResourcesPerPage; end; for I := 0 to ACount - 1 do begin AResourceViewInfo := TcxSchedulerResourceViewInfo.Create( Resources.VisibleResources[Scheduler.FirstVisibleResourceIndex + I]); AResources.Add(AResourceViewInfo); end; end; procedure TcxCustomResourceViewAdapter.GetPageDays( APageIndex: Integer; ADays: TcxSchedulerDateList); begin end; procedure TcxCustomResourceViewAdapter.Invalidate; begin end; function TcxCustomResourceViewAdapter.CanCalculate: Boolean; begin Result := View.Active; end; function TcxCustomResourceViewAdapter.GetActualStart: TDateTime; begin Result := PrintFrom; end; function TcxCustomResourceViewAdapter.GetActualFinish: TDateTime; begin Result := PrintTo; end; function TcxCustomResourceViewAdapter.GetCompressWeekends: Boolean; begin Result := View.GetCompressWeekEnd; end; function TcxCustomResourceViewAdapter.GetDontPrintFreeTime: Boolean; begin Result := False; end; function TcxCustomResourceViewAdapter.GetDontPrintWeekEnds: Boolean; begin Result := False; end; function TcxCustomResourceViewAdapter.GetHideSelection: Boolean; begin Result := View.OptionsView.HideSelection and not View.Scheduler.IsFocused; end; function TcxCustomResourceViewAdapter.GetIsPrinting: Boolean; begin Result := False; end; function TcxCustomResourceViewAdapter.GetPageBounds: TRect; begin Result := View.ClientRect; end; function TcxCustomResourceViewAdapter.GetPagesPerWeek: Byte; begin Result := 1; end; function TcxCustomResourceViewAdapter.GetPrimaryPage: Boolean; begin Result := True; end; function TcxCustomResourceViewAdapter.GetPrintExactlyOneMonth: Boolean; begin Result := False; end; function TcxCustomResourceViewAdapter.GetPrintRange( Index: Integer): TDateTime; begin Result := NullDate; end; function TcxCustomResourceViewAdapter.GetStylesAdapter: IcxSchedulerStylesAdapter; begin Result := FView.Styles; end; function TcxCustomResourceViewAdapter.GetView: TcxSchedulerCustomResourceView; begin Result := FView; end; procedure TcxCustomResourceViewAdapter.AfterCalculatePage; begin end; procedure TcxCustomResourceViewAdapter.BeforeCalculatePage; begin end; procedure TcxCustomResourceViewAdapter.DoInitialize( var ASelectedDays: TcxSchedulerDateList; var AEvents: TcxSchedulerCachedEventList); begin ASelectedDays := View.Scheduler.SelectedDays; AEvents := ViewInfo.GetSchedulerEventsList; end; function TcxCustomResourceViewAdapter.GetPageHeaderText: string; begin Result := ViewInfo.GetPageHeaderText; end; procedure TcxCustomResourceViewAdapter.Store; begin end; procedure TcxCustomResourceViewAdapter.Restore; begin end; function TcxCustomResourceViewAdapter.GetCells: TcxObjectList; begin Result := ViewInfo.FCells; end; function TcxCustomResourceViewAdapter.GetContentLineHeight: Integer; var AEventHeight, AIconHeight: Integer; AImages: TCustomImageList; begin with View do begin AEventHeight := OptionsView.EventHeight; AImages := Scheduler.EventImages; end; with ViewInfo do begin Result := GetFontHeight(StylesAdapter.GetEventParams(nil)) + 2 * cxTextOffset; if AEventHeight = 0 then begin if AImages <> nil then AIconHeight := Max(PainterHelper.IconsHeight, AImages.Height) else AIconHeight := PainterHelper.IconsHeight; Result := Max(AIconHeight + cxTextOffset + 2 * cxEventImagesOffset, Result); end else Result := Max(AEventHeight, Result); end; end; function TcxCustomResourceViewAdapter.GetPainterHelper: TcxSchedulerPainterHelperClass; begin Result := TcxSchedulerHelpersFactory.PainterHelperClass; end; function TcxCustomResourceViewAdapter.GetResourceNavigator: TcxSchedulerResourceNavigator; begin Result := View.Scheduler.ResourceNavigator; end; function TcxCustomResourceViewAdapter.GetResources: TcxSchedulerStorageResourceItems; begin Result := View.Resources; end; function TcxCustomResourceViewAdapter.GetScheduler: TcxCustomScheduler; begin Result := View.Scheduler; end; function TcxCustomResourceViewAdapter.GetViewInfo: TcxSchedulerCustomResourceViewViewInfo; begin Result := View.ViewInfo; end; { TcxSchedulerEventImageItem } constructor TcxSchedulerEventImageItem.Create(Collection: TCollection); begin inherited Create(Collection); FAutoHide := True; FImageIndex := -1; FVisible := True; end; function TcxSchedulerEventImageItem.GetHeight: Integer; begin Result := Images.Height; end; function TcxSchedulerEventImageItem.GetWidth: Integer; begin Result := Images.Width; end; { TcxSchedulerEventImages } constructor TcxSchedulerEventImages.Create( ALayout: TcxSchedulerEventImagesLayout); begin inherited Create(TcxSchedulerEventImageItem); FLayout := ALayout; FItemHeight := EventImages.Height; FItemWidth := EventImages.Width; end; function TcxSchedulerEventImages.Add(AImageIndex: Integer; AutoHide: Boolean = True): TcxSchedulerEventImageItem; begin if (FImages = nil) or ((AImageIndex < 0) or (AImageIndex >= FImages.Count)) then begin Result := nil; Exit; end; Result := TcxSchedulerEventImageItem(inherited Add); Result.FImageIndex := AImageIndex; Result.AutoHide := AutoHide; Result.FImageType := eitCustom; Result.FImages := FImages; end; function TcxSchedulerEventImages.AddStandardImage( AImageType: TcxSchedulerEventImageType; AutoHide: Boolean = True): TcxSchedulerEventImageItem; const Indexes: array[TcxSchedulerEventImageType] of TImageIndex = (4, 2, 3, -1); begin Result := TcxSchedulerEventImageItem(inherited Add); Result.AutoHide := AutoHide; Result.FImageType := AImageType; Result.FImages := EventImages; Result.FImageIndex := Indexes[AImageType]; end; function TcxSchedulerEventImages.Calculate(const R: TRect): Integer; begin case FLayout of eilAuto: Result := CalculateImages(R); eilHorizontal: Result := CalculateSingleLineImages(R); else Result := CalculateSingleColumnImages(R); end; end; procedure TcxSchedulerEventImages.CalculateForCols(AVisibleImages: TList; const ATopLeft: TPoint; AColCount: Integer); var ARow, ACol, AIndex: Integer; begin AIndex := 0; ACol := 0; ARow := 0; while AIndex < TotalVisibleImageCount do begin SetItemBounds(TcxSchedulerEventImageItem(AVisibleImages[AIndex]), ATopLeft.X + ACol * (ItemWidth + cxEventImagesGap), ATopLeft.Y + ARow * (ItemHeight + cxEventImagesGap)); if ACol = AColCount - 1 then begin ACol := 0; Inc(ARow); end else Inc(ACol); Inc(AIndex); end; end; function TcxSchedulerEventImages.CalculateImages(const R: TRect): Integer; var I, AWidth, AHeight, ACount, ARows, AColIndex, ARowIndex: Integer; L: TList; RS: TSize; procedure CheckAutoHideItems; var I: Integer; AItem: TcxSchedulerEventImageItem; begin if ACount >= L.Count then Exit; for I := L.Count - 1 downto 0 do begin AItem := TcxSchedulerEventImageItem(L[I]); if AItem.AutoHide then begin AItem.FHidden := True; L.Delete(I); if ACount >= L.Count then break; end; end; end; begin AHeight := ItemHeight + cxEventImagesGap; RS := cxRectSize(R); ARows := Max(1, RS.cy div AHeight); if ARows = 1 then begin Result := CalculateSingleLineImages(R); Exit; end; Result := 0; L := CreateVisibleList; try if L.Count = 0 then Exit; AWidth := ItemWidth + cxEventImagesGap; ACount := Max(1, RS.cx div AWidth) * ARows; CheckAutoHideItems; AColIndex := 0; ARowIndex := 0; for I := 0 to L.Count - 1 do begin SetItemBounds(TcxSchedulerEventImageItem(L[I]), R.Left + AColIndex * AWidth, R.Top + ARowIndex * AHeight); Result := Max(Result, (AColIndex + 1) * AWidth); Inc(ARowIndex); if ARowIndex = ARows then begin Inc(AColIndex); ARowIndex := 0; end; end; FVisibleImageCount := L.Count; finally L.Free; end; end; function TcxSchedulerEventImages.CalculateSingleLineImages(const R: TRect; ARightLimit: Integer = 0): Integer; var I, ALeft, AImageWidth, ATotalWidth, ARectWidth: Integer; L: TList; AItem: TcxSchedulerEventImageItem; procedure CheckAutoHideItems; var I: Integer; AItem: TcxSchedulerEventImageItem; begin if ARectWidth >= ATotalWidth then Exit; if ARightLimit > 0 then ARectWidth := Min(ARightLimit, Max(ARectWidth, ForceVisibleWidth)); for I := L.Count - 1 downto 0 do begin AItem := TcxSchedulerEventImageItem(L.List^[I]); if AItem.AutoHide then begin AItem.FHidden := True; Dec(ATotalWidth, AImageWidth); L.Delete(I); if ARectWidth >= ATotalWidth then break; end; end; end; begin Result := 0; L := CreateVisibleList; try if L.Count = 0 then Exit; ATotalWidth := TotalVisibleWidth; ARectWidth := R.Right - R.Left; AImageWidth := ItemWidth + cxEventImagesGap; CheckAutoHideItems; ALeft := R.Left; for I := 0 to L.Count - 1 do begin AItem := TcxSchedulerEventImageItem(L.List^[I]); SetItemBounds(AItem, ALeft, R.Top); Inc(ALeft, AImageWidth); Inc(Result, AImageWidth); end; FVisibleImageCount := L.Count; finally L.Free; end; end; function TcxSchedulerEventImages.CalculateSingleColumnImages(const R: TRect): Integer; var I, ATop, AWidth, AHeight, ATotalHeight: Integer; RS: TSize; L: TList; procedure CheckAutoHideItems; var I: Integer; AItem: TcxSchedulerEventImageItem; begin if RS.cy + cxEventImagesGap >= ATotalHeight then Exit; for I := L.Count - 1 downto 0 do begin AItem := TcxSchedulerEventImageItem(L.List^[I]); if AItem.AutoHide then begin AItem.FHidden := True; Dec(ATotalHeight, AHeight); L.Delete(I); if RS.cy + cxEventImagesGap >= ATotalHeight then break; end; end; end; function CanAutoHideAllItems: Boolean; var I: Integer; begin Result := True; for I := 0 to L.Count - 1 do if not TcxSchedulerEventImageItem(L.List^[I]).AutoHide then begin Result := False; break; end; end; begin Result := 0; L := CreateVisibleList; try if L.Count = 0 then Exit; ATotalHeight := TotalVisibleHeight; RS := cxRectSize(R); AWidth := ItemWidth + cxEventImagesGap; if (RS.cx < AWidth) and CanAutoHideAllItems then Exit; AHeight := ItemHeight + cxEventImagesGap; CheckAutoHideItems; if L.Count = 0 then Exit; Result := AWidth; ATop := R.Top; for I := 0 to L.Count - 1 do begin SetItemBounds(TcxSchedulerEventImageItem(L.List^[I]), R.Left, ATop); Inc(ATop, AHeight); end; FVisibleImageCount := L.Count; finally L.Free; end; end; function TcxSchedulerEventImages.CreateVisibleList: TList; var I: Integer; AItem: TcxSchedulerEventImageItem; begin FVisibleImageCount := 0; FForceVisibleHeight := 0; FForceVisibleWidth := 0; FTotalVisibleImageCount := 0; Result := TList.Create; for I := 0 to Count - 1 do begin AItem := Items[I]; if AItem.Visible then begin Inc(FTotalVisibleImageCount); if not AItem.AutoHide then begin Inc(FForceVisibleHeight, ItemHeight + cxEventImagesGap); Inc(FForceVisibleWidth, ItemWidth + cxEventImagesGap); end; AItem.FHidden := False; Result.Add(AItem); end else AItem.FHidden := True; end; FTotalVisibleWidth := (ItemWidth + cxEventImagesGap) * Result.Count; FTotalVisibleHeight := (ItemHeight + cxEventImagesGap) * Result.Count; end; procedure TcxSchedulerEventImages.Init(AImages: TCustomImageList); begin FVisibleImageCount := 0; FImages := AImages; if (FImages <> nil) then begin if FImages.Height > FItemHeight then FItemHeight := FImages.Height; if FImages.Width > FItemWidth then FItemWidth := FImages.Width; end; end; function TcxSchedulerEventImages.Offset(ADeltaX, ADeltaY: Integer): Integer; var I: Integer; begin Result := 0; for I := 0 to Count - 1 do with Items[I] do begin if not FHidden then begin FBounds := cxRectOffset(FBounds, ADeltaX, ADeltaY); Inc(Result, ItemWidth + cxEventImagesGap); end; end; end; procedure TcxSchedulerEventImages.SetItemBounds( AItem: TcxSchedulerEventImageItem; ALeft, ATop: Integer); begin Inc(ALeft, Max(0, (ItemWidth - AItem.Width) div 2)); Inc(ATop, Max(0, (ItemHeight - AItem.Height) div 2)); AItem.FBounds := cxRectBounds(ALeft, ATop, AItem.Width, AItem.Height); end; function TcxSchedulerEventImages.GetImageItem( AIndex: Integer): TcxSchedulerEventImageItem; begin Result := TcxSchedulerEventImageItem(inherited Items[AIndex]); end; { TcxSchedulerCachedImage } constructor TcxSchedulerCachedImage.Create; begin inherited; FImage := TcxBitmap.CreateSize(0, 0, pf32bit); end; destructor TcxSchedulerCachedImage.Destroy; begin FreeAndNil(FImage); inherited Destroy; end; procedure TcxSchedulerCachedImage.Invalidate; begin Image.SetSize(0, 0); end; function TcxSchedulerCachedImage.IsValid(AItem: TcxSchedulerCustomViewInfoItem): Boolean; begin Result := (Image.Width = AItem.Width) and (Image.Height = AItem.Height); end; procedure TcxSchedulerCachedImage.Update(AItem: TcxSchedulerCustomViewInfoItem); begin if not cxRectIsEmpty(AItem.Bounds) then begin Image.SetSize(AItem.Width, AItem.Height); Image.cxCanvas.Canvas.Lock; end; end; { TcxSchedulerResourceHeaderCachedImage } function TcxSchedulerResourceHeaderCachedImage.IsValid(AItem: TcxSchedulerCustomViewInfoItem): Boolean; begin Result := inherited IsValid(AItem); if Result then begin Result := (TcxSchedulerHeaderCellViewInfo(AItem).DisplayText = FDisplayText) and (TcxSchedulerHeaderCellViewInfo(AItem).DateTime = FDateTime); end; end; procedure TcxSchedulerResourceHeaderCachedImage.Update(AItem: TcxSchedulerCustomViewInfoItem); begin inherited Update(AItem); FDisplayText := TcxSchedulerHeaderCellViewInfo(AItem).DisplayText; FDateTime := TcxSchedulerHeaderCellViewInfo(AItem).DateTime; end; { TcxSchedulerResourceHeaderCachedImageList } function TcxSchedulerResourceHeaderCachedImageList.Add(AItem: TcxSchedulerHeaderCellViewInfo): TcxSchedulerResourceHeaderCachedImage; begin Result := TcxSchedulerResourceHeaderCachedImage.Create; if AItem.Resource <> nil then Result.FResourceItem := AItem.Resource.ResourceItem; inherited Add(Result); end; function TcxSchedulerResourceHeaderCachedImageList.GetCacheForItem( AItem: TcxSchedulerHeaderCellViewInfo): TcxSchedulerResourceHeaderCachedImage; function GetResourceItem(AItem: TcxSchedulerHeaderCellViewInfo): TcxSchedulerStorageResourceItem; begin if AItem.Resource = nil then Result := nil else Result := AItem.Resource.ResourceItem; end; var I: Integer; ACachedItem: TcxSchedulerResourceHeaderCachedImage; begin Result := nil; for I := 0 to Count - 1 do begin ACachedItem := TcxSchedulerResourceHeaderCachedImage(Items[I]); if ACachedItem.FResourceItem = GetResourceItem(AItem) then begin Result := ACachedItem; Break; end; end; if Result = nil then Result := Add(AItem); end; { TcxSchedulerImageCacheManager } constructor TcxSchedulerImageCacheManager.Create; begin FResourceHeaders := TcxSchedulerResourceHeaderCachedImageList.Create; FSeparator := TcxSchedulerCachedImage.Create; end; destructor TcxSchedulerImageCacheManager.Destroy; begin FResourceHeaders.Free; FSeparator.Free; inherited Destroy; end; procedure TcxSchedulerImageCacheManager.Invalidate; begin ResourceHeaders.Clear; Separator.Invalidate; end; { TcxSchedulerCustomResourceViewViewInfo } constructor TcxSchedulerCustomResourceViewViewInfo.Create( AOwner: TcxSchedulerSubControl); begin inherited Create(AOwner); FCells := TcxObjectList.Create; FResources := TcxObjectList.Create; FGroupSeparatorCells := TcxSchedulerViewInfoCellList.Create; FButtons := TcxSchedulerViewInfoCellList.Create; FNavigationButtons := TcxSchedulerViewInfoCellList.Create; FContentCells := TcxSchedulerViewInfoCellList.Create; FEventCells := TcxSchedulerViewInfoCellList.Create; FDayHeaderCells := TcxSchedulerViewInfoCellList.Create; FResourceHeaderCells := TcxSchedulerViewInfoCellList.Create; FHeaderContainerCells := TcxSchedulerViewInfoCellList.Create; FCells.Add(FEventCells); FCells.Add(FGroupSeparatorCells); FCells.Add(FDayHeaderCells); FCells.Add(FResourceHeaderCells); FCells.Add(FContentCells); FCells.Add(FHeaderContainerCells); // cache FImageCacheManager := CreateImageCacheManager; end; destructor TcxSchedulerCustomResourceViewViewInfo.Destroy; begin FreeAndNil(FImageCacheManager); FEventImages := nil; FResources.Free; FButtons.Free; FNavigationButtons.Free; FCells.Free; FreeAndNil(FContentNavigationIntervals); inherited Destroy; end; procedure TcxSchedulerCustomResourceViewViewInfo.Calculate; begin if ScreenCanvas = nil then ScreenCanvas := TcxScreenCanvas.Create; try Supports(TObject(View.Scheduler), IcxSchedulerEventImages, FEventImages); FPrimaryPage := Adapter.GetPrimaryPage; Adapter.DoInitialize(FSelectedDays, FEvents); FHasVisibleBounds := GetHasVisibleBounds; FPrintWeekEnds := not Adapter.DontPrintWeekEnd; FPagesPerWeek := Adapter.PagesPerWeek; FPageBounds := Adapter.GetPageBounds; FCanSelected := not Adapter.GetHideSelection; inherited Calculate; finally FreeAndNil(ScreenCanvas); end; end; procedure TcxSchedulerCustomResourceViewViewInfo.CalculateHitTest( AHitTest: TcxSchedulerCustomResourceViewHitTest); begin FEventCells.CalculateHitTest(AHitTest); if not FNavigationButtons.CalculateHitTest(AHitTest) then if not FDayHeaderCells.CalculateHitTest(AHitTest) then if not FResourceHeaderCells.CalculateHitTest(AHitTest) then if not FHeaderContainerCells.CalculateHitTest(AHitTest) then if not FButtons.CalculateHitTest(AHitTest) then if not FContentCells.CalculateHitTest(AHitTest) then FGroupSeparatorCells.CalculateHitTest(AHitTest); if AHitTest.HitAtButton and AHitTest.HitAtEvent then begin AHitTest.FHitObject := nil; AHitTest.FEventCell := nil; end; HotTrackNavigationButtons(AHitTest); end; procedure TcxSchedulerCustomResourceViewViewInfo.InitScrollBarsParameters; begin CheckResourceNavigator; end; procedure TcxSchedulerCustomResourceViewViewInfo.ScrollHorizontal( AScrollCode: TScrollCode; var AScrollPos: Integer); begin end; procedure TcxSchedulerCustomResourceViewViewInfo.ScrollVertical( AScrollCode: TScrollCode; var AScrollPos: Integer); begin end; procedure TcxSchedulerCustomResourceViewViewInfo.SetEventsVisibility( AShowSources, AShowClones: Boolean; AForceRepaint: Boolean = False); var ARepaint: Boolean; begin ARepaint := AForceRepaint or (FHideSource <> not AShowSources) or (FHideClones <> not AShowClones); FHideSource := not AShowSources; FHideClones := not AShowClones; if ARepaint then View.Refresh; end; procedure TcxSchedulerCustomResourceViewViewInfo.MouseLeave; begin if View.HitTest is TcxSchedulerCustomResourceViewHitTest then SetHitContentNavigationButton(nil, TcxSchedulerCustomResourceViewHitTest(View.HitTest)); end; function TcxSchedulerCustomResourceViewViewInfo.AddButton( ABounds: TRect; const ADateTime: TDateTime; AIsDown: Boolean; AEvent: TcxSchedulerEvent): TcxSchedulerMoreEventsButtonViewInfo; var AMoreButtonSize: TSize; begin ABounds := cxRectInflate(ABounds, -cxTextOffset, -cxTextOffset); AMoreButtonSize := View.ExternalPainter.MoreButtonSize( Size(PainterHelper.MoreButtonWidth, PainterHelper.MoreButtonHeight)); ABounds.Left := ABounds.Right - AMoreButtonSize.cx; if AIsDown then ABounds.Top := ABounds.Bottom - AMoreButtonSize.cy else ABounds.Bottom := ABounds.Top + AMoreButtonSize.cy; if DateOf(ADateTime) = 0 then CreateCellInstance(GetMoreEventButtonClass, ABounds, Styles.GetBackgroundParams, Result) else CreateCellInstance(GetMoreEventButtonClass, ABounds, GetContentParams(ADateTime, nil), Result); Result.FIsDown := AIsDown; Result.FDateTime := ADateTime; Result.FOnClick := OnMoreEventsButtonClick; Result.Event := AEvent; FButtons.Add(Result); end; function TcxSchedulerCustomResourceViewViewInfo.AddBackgroundSlot(const ABounds: TRect; ABorders: TcxBorders; const AText: string = ''): TcxSchedulerBackgroundSlotCellViewInfo; begin CreateCellInstance(TcxSchedulerBackgroundSlotCellViewInfo, ABounds, Styles.GetBackgroundParams, Result); Result.FBorders := ABorders; AssignResourceID(Result, -1); ContentCells.Add(Result); end; function TcxSchedulerCustomResourceViewViewInfo.AddContentCell(const ARect: TRect; const AStart, AFinish: TDateTime; AResourceIndex: Integer): TcxSchedulerContentCellViewInfo; begin CreateCellInstance(ContentCellClass, ARect, GetContentParams(AStart, Resources[AResourceIndex]), Result); Result.SetTime(AStart, AFinish); AssignResourceID(Result, AResourceIndex); ContentCells.Add(Result); end; procedure TcxSchedulerCustomResourceViewViewInfo.AddContentNavigationButton( const AColumnRect: TRect; AResourceIndex: Integer; AColumnPositionInResource: TcxSchedulerColumnPositionInResource); procedure AddAppointedButton(AKind: TcxSchedulerContentNavigationButtonKind); const AButtonTexts: array[TcxSchedulerContentNavigationButtonKind] of pointer = (@scxPrevAppointment, @scxNextAppointment); var AButton: TcxSchedulerContentNavigationButtonViewInfo; AWidth, AButtonOffset: Integer; begin CalculateNavigationButtonParams(AColumnRect, AKind, AWidth); AButtonOffset := NavigationButtonOffset(AKind, AResourceIndex); OffsetRect(FButtonBounds, AButtonOffset, 0); CreateCellInstance(TcxSchedulerContentNavigationButtonViewInfo, FButtonBounds, Styles.GetBackgroundParams, AButton); AButton.FOnClick := OnContentNavigationButtonClick; AssignResourceID(AButton, AResourceIndex); AButton.FKind := AKind; OffsetRect(FButtonTextRect, AButtonOffset, 0); AButton.FTextRect := FButtonTextRect; OffsetRect(FButtonArrowRect, AButtonOffset, 0); AButton.FArrowRect := FButtonArrowRect; AButton.Caption := cxGetResourceString(AButtonTexts[AKind]); FNavigationButtons.Add(AButton); AddContentNavigationIntervalItem(AResourceIndex); end; var AColumnHeight: Integer; begin if Adapter.IsPrinting then Exit; AColumnHeight := GetCorrectColumnHeight(AColumnRect); if Scheduler.OptionsView.ShowNavigationButtons and not AreThereEventsInVisibleInterval(AResourceIndex) and (AColumnPositionInResource <> cprIndefinite) and (AColumnHeight > ContentNavigationButtonReducedHeight) then begin case AColumnPositionInResource of cprFirst: AddAppointedButton(nbkPrevious); cprLast: AddAppointedButton(nbkNext); cprSingle: begin AddAppointedButton(nbkPrevious); AddAppointedButton(nbkNext); end; end; end; end; function TcxSchedulerCustomResourceViewViewInfo.AddDayHeader( const ADate: TDateTime; const ABounds: TRect; AResourceIndex: Integer): TcxSchedulerDayHeaderCellViewInfo; begin CreateCellInstance(TcxSchedulerDayHeaderCellViewInfo, ABounds, StylesAdapter.GetDayHeaderParams(ADate), Result); Result.DateTime := ADate; AssignResourceID(Result, AResourceIndex); FDayHeaderCells.Add(Result); end; function TcxSchedulerCustomResourceViewViewInfo.AddDayHeader( const ADate: TDateTime; ATop, ALeft, ARight: Integer; AResourceIndex: Integer): TcxSchedulerDayHeaderCellViewInfo; begin Result := AddDayHeader(ADate, cxRect(ALeft, ATop, ARight, ATop + FDayHeaderHeight), AResourceIndex); end; function TcxSchedulerCustomResourceViewViewInfo.AddEventCell( AViewData: TcxSchedulerEventViewData; AImmediateCalculate: Boolean = True): TcxSchedulerEventCellViewInfo; begin Result := CreateEventCellViewInfo(AViewData); if (FEventImages <> nil) and FEventImages.SupportEventImages then begin Result.Images.Init(FEventImages.GetImages); FEventImages.DoInitEventImages(AViewData.Event, Result.Images); end; if AImmediateCalculate then Result.Calculate; EventCells.Add(Result); SetResourceHasVisibleEvent(AViewData.Event); end; function TcxSchedulerCustomResourceViewViewInfo.AddGroupHorzSeparator( APos: Integer): TcxSchedulerGroupSeparatorCellViewInfo; begin Result := AddGroupSeparator(cxRectSetTop(Bounds, APos, SeparatorWidth)); if Result = nil then Exit; Result.Rotated := True; if CanCacheGroupSeparator(Result) then Result.Cache := ImageCacheManager.Separator; end; function TcxSchedulerCustomResourceViewViewInfo.AddGroupSeparator( const ABounds: TRect): TcxSchedulerGroupSeparatorCellViewInfo; begin Result := nil; if not HasSeparator then Exit; CreateCellInstance(TcxSchedulerGroupSeparatorCellViewInfo, ABounds, FGroupSeparatorParams, Result); GroupSeparatorCells.Add(Result); end; function TcxSchedulerCustomResourceViewViewInfo.AddGroupVertSeparator( APos: Integer): TcxSchedulerGroupSeparatorCellViewInfo; begin Result := AddGroupSeparator(cxRectSetLeft(Bounds, APos, SeparatorWidth)); end; procedure TcxSchedulerCustomResourceViewViewInfo.AddResourceBounds( AResourceIndex: Integer; const ABounds: TRect); begin if Length(FResourceBounds) <> ResourceCount then SetLength(FResourceBounds, ResourceCount); FResourceBounds[AResourceIndex] := ABounds; end; function TcxSchedulerCustomResourceViewViewInfo.AddResourceHeader( const AIndex: Integer; const ABounds: TRect): TcxSchedulerHeaderCellViewInfo; begin CreateCellInstance(TcxSchedulerHeaderCellViewInfo, ABounds, StylesAdapter.GetResourceHeaderParams(GetResourceItemByIndex(AIndex)), Result); Result.FIsResourceHeader := AIndex >= 0; if Result.IsResourceHeader then begin Result.FDisplayText := ResourceCaptions[AIndex]; AssignResourceID(Result, AIndex); with Resources[AIndex] do begin Result.FAutoHeight := ResourceHeaders.MultilineCaptions; Result.FImageIndex := ImageIndex; Result.FImagePosition := ImagePosition; Result.FImages := Images; end; end; ResourceHeaderCells.Add(Result); if CanCacheResourceHeader(Result) then Result.Cache := ImageCacheManager.ResourceHeaders.GetCacheForItem(Result); end; procedure TcxSchedulerCustomResourceViewViewInfo.AfterCalculate; begin inherited AfterCalculate; if FHideClones then HideCloneEventsOnDragDrop; if FHideSource then HideSourceEventsOnDragDrop; SetContentNavigationButtonsIntervals; end; function TcxSchedulerCustomResourceViewViewInfo.AreThereEventsInVisibleInterval( AResourceIndex: Integer): Boolean; var AResourceID: Variant; begin Result := (((GetGroupingKind = gkNone) or (AResourceIndex < 0)) and (HasVisibleEvents or (GetMoreEventsButtonCount(-1) <> 0))) or ((GetGroupingKind <> gkNone) and (AResourceIndex >= 0) and ((GetEventForResourceCount(AResourceIndex, AResourceID) <> 0) or (GetEventWithoutResourceCount <> 0))); end; procedure TcxSchedulerCustomResourceViewViewInfo.AssignResourceID( ACell: TcxSchedulerCustomResourceViewInfoItem; AIndex: Integer); begin if AIndex >= 0 then ACell.Resource := Resources[AIndex]; ACell.FIsResourceAssigned := AIndex >= 0; end; procedure TcxSchedulerCustomResourceViewViewInfo.CalculateContentNavigationButtons; var AResourceIndex: Integer; begin if IsDrawContentNavigationButtons then begin if ResourceCount > 0 then for AResourceIndex := 0 to ResourceCount - 1 do AddContentNavigationButton(FResourceBounds[AResourceIndex], AResourceIndex, cprSingle) else AddContentNavigationButton(Bounds, -1, cprSingle); end; end; procedure TcxSchedulerCustomResourceViewViewInfo.CalculateMetrics; begin FHideSelection := View.OptionsView.HideSelection and not View.Scheduler.IsFocused; FGroupSeparatorParams := Styles.GetGroupSeparatorParams; FTimeLineParams := GetTimeLineParams; FSelectionParams := Styles.GetSelectionParams; FContentLineHeight := Adapter.GetContentLineHeight; FContentFontHeight := cxTextHeight(StylesAdapter.GetContentParams(Now, nil).Font) + cxTextOffset * 2; FDayHeaderHeight := LookAndFeelPainter.HeaderHeight(GetFontHeight(StylesAdapter.GetDayHeaderStyle)); FResourceHeaderHeight := LookAndFeelPainter.HeaderHeight(GetFontHeight(StylesAdapter.GetResourceHeaderStyle)); FUseResourceImages := HasStorage and View.Scheduler.Storage.Resources.AreImagesUsed; if HasStorage then FResourceImages := View.Scheduler.Storage.Resources.Images else FResourceImages := nil; if HasStorage then begin if ResourceHeaders.Height <> 0 then FResourceHeaderHeight := ResourceHeaders.Height; CalculateResourceHeadersAutoHeight(GetResourceHeaderWidth - cxTextOffset * 3); if ResourceHeaders.Height <> 0 then FResourceHeaderHeight := ResourceHeaders.Height; end; end; procedure TcxSchedulerCustomResourceViewViewInfo.CalculateNavigationButtonParams( AColumnRect: TRect; AKind: TcxSchedulerContentNavigationButtonKind; out AButtonWidth: Integer); var AHeight, AMiddle: Integer; AIsCollapsed: Boolean; begin AIsCollapsed := Round(ContentNavigationButtonHeight * 1.5) >= GetCorrectColumnHeight(AColumnRect); if AIsCollapsed then AHeight := ContentNavigationButtonReducedHeight else AHeight := ContentNavigationButtonHeight; AMiddle := (AColumnRect.Top + AColumnRect.Bottom) div 2; case AKind of nbkPrevious: FButtonBounds := Rect(AColumnRect.Left, AMiddle - AHeight div 2, AColumnRect.Left + ContentNavigationButtonWidth, AMiddle + AHeight div 2); nbkNext: FButtonBounds := Rect(AColumnRect.Right - ContentNavigationButtonWidth, AMiddle - AHeight div 2, AColumnRect.Right, AMiddle + AHeight div 2); else FButtonBounds := cxNullRect; end; with ScreenCanvas do begin SetParams(Styles.GetBackgroundParams); LookAndFeelPainter.CalculateSchedulerNavigationButtonRects( AKind = nbkNext, AIsCollapsed, TextExtent(cxGetResourceString(@scxPrevAppointment)), TextExtent(cxGetResourceString(@scxNextAppointment)), FButtonBounds, FButtonTextRect, FButtonArrowRect); end; AButtonWidth := FButtonBounds.Right - FButtonBounds.Left; end; procedure TcxSchedulerCustomResourceViewViewInfo.CalculateResourceHeadersAutoHeight( AWidth: Integer); function CalculateResourceHeight(AResource: TcxSchedulerStorageResourceItem; AWidth: Integer): Integer; var R: TRect; AFont: TFont; AText: string; AHasImage: Boolean; begin AFont := Styles.GetResourceHeaderParams(AResource).Font; AHasImage := UseResourceImages and (AResource.ActualImageIndex >= 0); if AHasImage and (ResourceHeaders.ImagePosition in [ipLeft, ipRight]) then AWidth := Max(0, AWidth - (GetResourceImagesSize.cx + cxTextOffset * 2)); R := Rect(0, 0, Max(AWidth, 2), 0); AText := AResource.Resources.GetResourceName(AResource); ScreenCanvas.Font.Assign(AFont); ScreenCanvas.TextExtent(AText, R, MakeTextOutcxFlags(taLeftJustify, vaCenter, ResourceHeaders.MultilineCaptions)); Result := R.Bottom - R.Top + cxTextOffset * 3; SetResourceTextRect(AResource, R); if AHasImage then begin if (ResourceHeaders.ImagePosition in [ipTop, ipBottom]) then Inc(Result, GetResourceImagesSize.cy + cxTextOffset * 4) else Result := Max(Result, GetResourceImagesSize.cy + cxTextOffset * 3); end; end; var I: Integer; begin AWidth := Max(0, AWidth); for I := 0 to Adapter.Resources.VisibleResourceCount - 1 do FResourceHeaderHeight := Max(FResourceHeaderHeight, CalculateResourceHeight( Adapter.Resources.VisibleResources[I], AWidth)); end; function TcxSchedulerCustomResourceViewViewInfo.CalculateResourceHeaderWidth: Integer; var I: Integer; AWidth: Integer; function CalculateWidth(AResource: TcxSchedulerStorageResourceItem): Integer; var R: TRect; AText: string; AHasImage: Boolean; AViewParams: TcxViewParams; begin AViewParams := StylesAdapter.GetResourceHeaderParams(AResource); Result := 0; AHasImage := AResource.ActualImageIndex >= 0; AText := AResource.Resources.GetResourceName(AResource); if Length(AText) > 0 then begin R := Rect(0, 0, FResourceHeaderHeight, AWidth); if AHasImage and (ResourceHeaders.ImagePosition in [ipTop, ipBottom]) then Dec(R.Bottom, ResourceImages.Height + cxTextOffset * 3); ScreenCanvas.Font.Assign(AViewParams.Font); ScreenCanvas.TextExtent(AText, R, MakeTextOutcxFlags(taLeftJustify, vaCenter, ResourceHeaders.MultilineCaptions)); Result := R.Right - R.Left + cxTextOffset * 3; SetResourceTextRect(AResource, R); if AHasImage and (ResourceHeaders.ImagePosition in [ipTop, ipBottom]) then Result := Max(Result, ResourceImages.Width + cxTextOffset * 4); end; if AHasImage and (ResourceHeaders.ImagePosition in [ipLeft, ipRight]) then Inc(Result, ResourceImages.Width + cxTextOffset * 4); end; begin AWidth := GetResourceHeaderWidth - cxTextOffset * 3; Result := FResourceHeaderHeight; for I := 0 to Adapter.Resources.VisibleResourceCount - 1 do Result := Max(Result, CalculateWidth(Adapter.Resources.VisibleResources[I])); end; function TcxSchedulerCustomResourceViewViewInfo.CanCalculateNavigationButtons: Boolean; begin Result := Scheduler.OptionsView.ShowNavigationButtons and not Adapter.IsPrinting; end; function TcxSchedulerCustomResourceViewViewInfo.CanCacheGroupSeparator( AItem: TcxSchedulerGroupSeparatorCellViewInfo): Boolean; begin Result := AItem.Rotated and (AItem.Bitmap = nil) and not View.HasCustomDrawGroupSeparator; end; function TcxSchedulerCustomResourceViewViewInfo.CanCacheResourceHeader( AItem: TcxSchedulerHeaderCellViewInfo): Boolean; begin Result := (AItem.Bitmap = nil) and not View.HasCustomDrawResourceHeader; end; procedure TcxSchedulerCustomResourceViewViewInfo.Clear; begin FResources.Clear; GroupSeparatorCells.Clear; Buttons.Clear; NavigationButtons.Clear; ContentCells.Clear; EventCells.Clear; DayHeaderCells.Clear; ResourceHeaderCells.Clear; HeaderContainerCells.Clear; ClearResourceBounds; ClearContentNavigationIntervals; end; procedure TcxSchedulerCustomResourceViewViewInfo.ClearResourceBounds; var I: Integer; begin for I := 0 to Length(FResourceBounds) - 1 do FResourceBounds[I] := cxNullRect; end; function TcxSchedulerCustomResourceViewViewInfo.ContentCellClass: TcxSchedulerContentCellViewInfoClass; begin Result := TcxSchedulerContentCellViewInfo end; procedure TcxSchedulerCustomResourceViewViewInfo.CreateCellInstance( AClass: TcxSchedulerCustomViewInfoItemClass; const ABounds: TRect; const AViewParams: TcxViewParams; var Instance); begin CreateCellInstance(AClass, ABounds, Bounds, AViewParams, Instance); end; procedure TcxSchedulerCustomResourceViewViewInfo.CreateCellInstance( AClass: TcxSchedulerCustomViewInfoItemClass; const ABounds, AVisibleBounds: TRect; const AViewParams: TcxViewParams; var Instance); begin Pointer(Instance) := AClass.Create(LookAndFeelPainter, ABounds, AVisibleBounds, AViewParams); TcxSchedulerCustomViewInfoItem(Instance).FDayBorderColor := FDayBorderColor; TcxSchedulerCustomViewInfoItem(Instance).FExternalPainter := View.ExternalPainter; end; function TcxSchedulerCustomResourceViewViewInfo.CreateEventViewData( AEvent: TcxSchedulerControlEvent; const ABounds: TRect; const AStart, AFinish: TDateTime; AResource: TcxSchedulerResourceViewInfo): TcxSchedulerEventViewData; var ALocation: string; begin Result := TcxSchedulerEventViewData.Create; Result.Bounds := ABounds; Result.VisibleRect := Bounds; Result.Canvas := View.Canvas; Result.ContentStart := DateTimeHelper.RoundTime(AStart); Result.ExternalPainter := View.ExternalPainter; {$IFNDEF DEBUGPAINT} Result.Bitmap := View.Bitmap; {$ENDIF} Result.GetEventHint := GetEventHint; Result.BorderColor := View.OptionsView.EventBorderColor; Result.ContentFinish := DateTimeHelper.RoundTime(AFinish); Result.Event := AEvent; Result.ShowTimeAsClock := View.ShowTimeAsClock; Result.TimeLineParams := FTimeLineParams; Result.ShowFinishTime := View.ShowEndTime; Result.Painter := LookAndFeelPainter; Result.ViewParams := StylesAdapter.GetEventParams(AEvent); Result.EditProperties := View.GetEditProperties(AEvent); Result.EditStyle := View.GetEditStyle(AEvent); Result.Resource := AResource; if (AEvent <> nil) and AEvent.Shared and (AResource <> nil) then AEvent.LockResource(AResource.ResourceID); Result.Caption := DoGetEventDisplayText(AEvent); AEvent.UnlockResource; Result.ImagesLayout := View.EventImagesLayout; Result.DrawAsProgress := False; Result.TaskComplete := AEvent.TaskComplete; Result.TaskStatus := AEvent.TaskStatus; ALocation := Trim(AEvent.Location); if ALocation <> '' then Result.Caption := Result.Caption + ' (' + ALocation + ')'; Result.LineHeight := FContentLineHeight; end; function TcxSchedulerCustomResourceViewViewInfo.CreateEventCellViewInfo( AViewData: TcxSchedulerEventViewData): TcxSchedulerEventCellViewInfo; begin Result := TcxSchedulerEventCellViewInfo.Create(AViewData); end; function TcxSchedulerCustomResourceViewViewInfo.CreateImageCacheManager: TcxSchedulerImageCacheManager; begin Result := TcxSchedulerImageCacheManager.Create; end; procedure TcxSchedulerCustomResourceViewViewInfo.DoCalculate; var Temp: Integer; begin FDayBorderColor := View.OptionsView.DayBorderColor; if FDayBorderColor = clDefault then FDayBorderColor := clWindowText; FEventWithoutResourceCount := 0; ExtractResources; FGroupingKind := GetGroupingKind; if FGroupingKind = gkNone then FResources.Clear; if SelectedDays.Count = 0 then SelectedDays.Add(Date); with View.Controller.Navigation do Self.FSelResource := GetResourceViewInfoByItem(SelResource, Temp); if (FSelResource = nil) and (ResourceCount > 0) then FSelResource := Resources[0]; CalculateMetrics; View.Controller.Navigation.CheckSelection; with View.Controller.Navigation do begin Self.FSelStart := DateTimeHelper.RoundTime(Min(SelStart, SelFinish)); Self.FSelFinish := DateTimeHelper.RoundTime(Max(SelStart, SelFinish)); end; end; procedure TcxSchedulerCustomResourceViewViewInfo.DoContentNavigationButtonClick( Sender: TcxSchedulerContentNavigationButtonViewInfo); begin TcxCustomSchedulerAccess(Scheduler).PeriodChanged; TcxDateNavigatorAccess(Scheduler.DateNavigator).MakeSelectionVisible; end; procedure TcxSchedulerCustomResourceViewViewInfo.DoMoreEventsButtonClick( Sender: TcxSchedulerMoreEventsButtonViewInfo); begin end; procedure TcxSchedulerCustomResourceViewViewInfo.ExtractResources; var I: Integer; begin Adapter.GetPageResources(FResources); for I := 0 to FResources.Count - 1 do Resources[I].FImagePosition := ResourceHeaders.ImagePosition; end; function TcxSchedulerCustomResourceViewViewInfo.GetBounds: TRect; begin Result := FPageBounds; end; function TcxSchedulerCustomResourceViewViewInfo.GetContentNavigationInterval( AContentNavigationButton: TcxSchedulerContentNavigationButtonViewInfo): TDateTime; function GetContentNavigationInfo(AIndex: Integer): TcxSchedulerContentNavigationInfo; begin Result := TcxSchedulerContentNavigationInfo(FContentNavigationIntervals[AIndex]); end; function GetInterval(AIndex: Integer): TDateTime; begin if AContentNavigationButton.Kind = nbkPrevious then Result := - GetContentNavigationInfo(AIndex).FIntervalBefore else Result := GetContentNavigationInfo(AIndex).FIntervalAfter; end; var I: Integer; begin Result := cxMaxDateTime; if AContentNavigationButton.Resource = nil then Result := GetInterval(0) else for I := 0 to FContentNavigationIntervals.Count - 1 do if VarEqualsSoft(GetContentNavigationInfo(I).FResourceID, AContentNavigationButton.Resource.ResourceID) then begin Result := GetInterval(I); Break; end; end; function TcxSchedulerCustomResourceViewViewInfo.GetContentParams( const ATime: TDateTime; AResource: TcxSchedulerResourceViewInfo): TcxViewParams; begin if AResource = nil then Result := StylesAdapter.GetContentParams(ATime, nil) else Result := StylesAdapter.GetContentParams(ATime, AResource.ResourceItem) end; function TcxSchedulerCustomResourceViewViewInfo.GetDayHeaderHeight: Integer; begin Result := FDayHeaderHeight; end; function TcxSchedulerCustomResourceViewViewInfo.GetEventForResourceCount( AResourceIndex: Integer; out AResourceID: Variant): Integer; begin Result := Resources[AResourceIndex].VisibleEventCount + GetMoreEventsButtonCount(AResourceIndex); AResourceID := Resources[AResourceIndex].ResourceID; end; function TcxSchedulerCustomResourceViewViewInfo.GetEventWithoutResourceCount: Integer; begin Result := FEventWithoutResourceCount; end; function TcxSchedulerCustomResourceViewViewInfo.GetMoreEventButtonClass: TcxSchedulerMoreEventsButtonViewInfoClass; begin Result := TcxSchedulerMoreEventsButtonViewInfo; end; function TcxSchedulerCustomResourceViewViewInfo.GetResourceHeaderWidth: Integer; begin Result := GetResourcesContentWidth; if ResourceCount > 0 then Result := Max(0, (Result - SeparatorWidth * GetSeparatorCount) div ResourceCount); end; function TcxSchedulerCustomResourceViewViewInfo.GetResourceImagesSize: TSize; begin if ResourceImages = nil then Result := TSize(cxNullSize) else Result := cxSize(ResourceImages.Width, ResourceImages.Height); end; function TcxSchedulerCustomResourceViewViewInfo.GetResourcesContentWidth: Integer; begin Result := FBounds.Bottom - FBounds.Top - FDayHeaderHeight; end; function TcxSchedulerCustomResourceViewViewInfo.GetTimeLineParams: TcxViewParams; begin Result := StylesAdapter.GetContentParams(NullDate, nil) end; function TcxSchedulerCustomResourceViewViewInfo.GetSelectionParams( const AParams: TcxViewParams): TcxViewParams; begin Result := AParams; if View.Scheduler.Focused or not HideSelection then begin Result := FSelectionParams; Result.Bitmap := nil; end; end; function TcxSchedulerCustomResourceViewViewInfo.GetSeparatorCount: Integer; begin Result := ResourceCount - 1; end; function TcxSchedulerCustomResourceViewViewInfo.GetFontHeight( AStyle: TcxStyle): Integer; begin if (AStyle = nil) or not (cxStyles.svFont in AStyle.AssignedValues) then Result := PainterHelper.TextHeight(DefaultFont) else Result := PainterHelper.TextHeight(AStyle.Font); end; function TcxSchedulerCustomResourceViewViewInfo.GetFontHeight( const AParams: TcxViewParams): Integer; begin Result := PainterHelper.TextHeight(AParams.Font); end; function TcxSchedulerCustomResourceViewViewInfo.GetPageHeaderText: string; begin Result := FormatDateTime(LongDateFormat, Days[0]); if Days[0] <> Days[DayCount - 1] then Result := Result + ' - ' + FormatDateTime(LongDateFormat, Days[DayCount - 1]); end; function TcxSchedulerCustomResourceViewViewInfo.GetResourceItemByIndex( AIndex: Integer): TcxSchedulerStorageResourceItem; begin Result := nil; if AIndex >= 0 then Result := Resources[AIndex].ResourceItem; end; function TcxSchedulerCustomResourceViewViewInfo.GetResourceViewInfoByItem( AItem: TcxSchedulerStorageResourceItem; var ResourceViewInfoIndex: Integer): TcxSchedulerResourceViewInfo; var I: Integer; begin Result := nil; for I := 0 to ResourceCount - 1 do if Resources[I].ResourceItem = AItem then begin Result := Resources[I]; ResourceViewInfoIndex := I; end; end; function TcxSchedulerCustomResourceViewViewInfo.GetStartDate( Index: Integer): TDateTime; begin Result := SelectedDays[0]; end; function TcxSchedulerCustomResourceViewViewInfo.HasStorage: Boolean; begin Result := View.Scheduler.Storage <> nil; end; function TcxSchedulerCustomResourceViewViewInfo.HasVisibleEvents: Boolean; begin Result := EventCells.Count <> 0; end; procedure TcxSchedulerCustomResourceViewViewInfo.ProcessCheckBorders( AList: TcxSchedulerViewInfoCellList; AHasCommonArea: Boolean; ANeighbors: TcxNeighbors = []; AExcludeBorders: TcxBorders = []; AAddBorders: TcxBorders = []); var I: Integer; DrawCommonBorders: Boolean; ACell, APrevCell: TcxSchedulerHeaderCellViewInfo; begin DrawCommonBorders := LookAndFeelPainter.HeaderBorders([nLeft..nBottom]) = cxBordersAll; APrevCell := nil; for I := 0 to AList.Count - 1 do begin ACell := TcxSchedulerHeaderCellViewInfo(AList[I]); ACell.FNeighbors := [nLeft, nRight]; if (I = 0) and not ACell.RotateHeader then begin Exclude(ACell.FNeighbors, nLeft); if AHasCommonArea then Include(ACell.FNeighbors, nBottom); end; ACell.FNeighbors := ACell.FNeighbors + ANeighbors; ACell.FBorders := LookAndFeelPainter.HeaderBorders(ACell.FNeighbors); if not DrawCommonBorders then begin ACell.CheckNeighbor(APrevCell); ACell.FBorders := ACell.FBorders - AExcludeBorders + AAddBorders; end; if I = (AList.Count - 1) then begin Exclude(ACell.FBorders, bRight); Exclude(ACell.FNeighbors, nRight); end; APrevCell := ACell; end; end; procedure TcxSchedulerCustomResourceViewViewInfo.ReturnVisibleInterval( var AStart, AEnd: TDateTime); function IsDescreteSelection: Boolean; var I: Integer; begin Result := False; I := 0; while not Result and (I < SelectedDays.Count - 1) do begin Result := SelectedDays[I] + 1 <> SelectedDays[I + 1]; Inc(I); end; end; begin AStart := StartDates[0]; if IsDescreteSelection then AEnd := AStart else AEnd := AStart + SelectedDays.Count - 1; end; function TcxSchedulerCustomResourceViewViewInfo.SetAdapter( Adapter: TcxCustomResourceViewAdapter): TcxCustomResourceViewAdapter; begin Result := FAdapter; FAdapter := Adapter; FStylesAdapter := FAdapter.GetStylesAdapter; end; procedure TcxSchedulerCustomResourceViewViewInfo.SetResourceHasVisibleEvent( AEvent: TcxSchedulerControlEvent); var AResourceIndex: Integer; AResourceFound: Boolean; begin AResourceFound := False; for AResourceIndex := 0 to ResourceCount - 1 do if AEvent.IsSharedWithResource(Resources[AResourceIndex].ResourceID) then begin Resources[AResourceIndex].VisibleEventCount := Resources[AResourceIndex].VisibleEventCount + 1; AResourceFound := True; end; if not AResourceFound then Inc(FEventWithoutResourceCount); end; procedure TcxSchedulerCustomResourceViewViewInfo.SetResourceTextRect( AResource: TcxSchedulerStorageResourceItem; const ARect: TRect); var I: Integer; begin for I := 0 to ResourceCount - 1 do if Resources[I].ResourceItem = AResource then begin Resources[I].FTextRect := ARect; Break; end; end; procedure TcxSchedulerCustomResourceViewViewInfo.ProcessDateToDisplayText( ArrangeByType: Boolean = False); var I: Integer; AType: Integer; begin AType := 0; for I := 0 to FDayHeaderCells.Count - 1 do AType := Max(TcxSchedulerDayHeaderCellViewInfo( FDayHeaderCells[I]).ConvertDateToDisplayText, AType); if ArrangeByType and (AType > 0) then begin for I := 0 to FDayHeaderCells.Count - 1 do TcxSchedulerDayHeaderCellViewInfo( FDayHeaderCells[I]).ConvertDateToDisplayText(AType); end; end; procedure TcxSchedulerCustomResourceViewViewInfo.HideCloneEventsOnDragDrop; var I: Integer; AEventCell: TcxSchedulerEventCellViewInfo; begin for I := 0 to EventCells.Count - 1 do begin AEventCell := TcxSchedulerEventCellViewInfo(EventCells[I]); if Events.Clones.IndexOf(AEventCell.Event) <> -1 then AEventCell.Hidden := True; end; end; procedure TcxSchedulerCustomResourceViewViewInfo.HideSourceEventsOnDragDrop; var I, J: Integer; AEventCell: TcxSchedulerEventCellViewInfo; begin for I := 0 to EventCells.Count - 1 do begin AEventCell := TcxSchedulerEventCellViewInfo(EventCells[I]); for J := 0 to Events.Clones.Count - 1 do if TcxSchedulerControlEvent(Events.Clones[J]).Source = AEventCell.Event then begin AEventCell.Hidden := True; Break; end; end; end; procedure TcxSchedulerCustomResourceViewViewInfo.HotTrackNavigationButtons( AHitTest: TcxSchedulerCustomResourceViewHitTest); var ANavigationButton: TcxSchedulerContentNavigationButtonViewInfo; begin if not CanCalculateNavigationButtons then Exit; if Scheduler.OptionsBehavior.HotTrack then ANavigationButton := AHitTest.HitContentNavigationButton else ANavigationButton := nil; SetHitContentNavigationButton(ANavigationButton, AHitTest); end; function TcxSchedulerCustomResourceViewViewInfo.IsTimeSelected( ATime: TDateTime; AResource: TObject): Boolean; begin ATime := DateTimeHelper.RoundTime(ATime); Result := not HideSelection and ((AResource = FSelResource) and (ATime >= SelStart) and (ATime <= SelFinish)); Result := Result and CanSelected; end; function TcxSchedulerCustomResourceViewViewInfo.IsValidNavigationButtonsPlace( const AResourceRect: TRect): Boolean; var AButtonWidth1, AButtonWidth2: Integer; begin CalculateNavigationButtonParams(AResourceRect, nbkPrevious, AButtonWidth1); CalculateNavigationButtonParams(AResourceRect, nbkNext, AButtonWidth2); Result := AButtonWidth1 + AButtonWidth2 <= AResourceRect.Right - AResourceRect.Left; end; procedure TcxSchedulerCustomResourceViewViewInfo.MakeTimeVisible( const ATime: TDateTime); begin end; function TcxSchedulerCustomResourceViewViewInfo.NavigationButtonOffset( AKind: TcxSchedulerContentNavigationButtonKind; AResourceIndex: Integer): Integer; begin Result := 0; end; procedure TcxSchedulerCustomResourceViewViewInfo.OnContentNavigationButtonClick( Sender: TcxSchedulerContentNavigationButtonViewInfo); var AResource: TcxSchedulerStorageResourceItem; begin if Sender.Resource <> nil then AResource := Sender.Resource.ResourceItem else AResource := nil; if not DoSchedulerNavigationButtonClick(Sender.Interval, AResource) then DoContentNavigationButtonClick(Sender); end; procedure TcxSchedulerCustomResourceViewViewInfo.OnMoreEventsButtonClick( Sender: TcxSchedulerMoreEventsButtonViewInfo); begin if not DoSchedulerMoreEventsButtonClick then DoMoreEventsButtonClick(Sender); end; procedure TcxSchedulerCustomResourceViewViewInfo.AddContentNavigationIntervalItem( AResourceIndex: Variant); var AResourceID: Variant; I: Integer; AnAlreadyExists: Boolean; begin if AResourceIndex > -1 then AResourceID := Resources[AResourceIndex].ResourceID else begin AResourceID := 0; FContentNavigationWithoutResources := True; end; AnAlreadyExists := False; I := 0; while not AnAlreadyExists and (I < FContentNavigationIntervals.Count) do begin AnAlreadyExists := VarEqualsSoft(TcxSchedulerContentNavigationInfo( FContentNavigationIntervals[I]).FResourceID, AResourceID); Inc(I); end; if not AnAlreadyExists then FContentNavigationIntervals.Add(TcxSchedulerContentNavigationInfo.Create(AResourceID)); end; procedure TcxSchedulerCustomResourceViewViewInfo.ClearContentNavigationIntervals; begin if FContentNavigationIntervals = nil then FContentNavigationIntervals := TObjectList.Create else FContentNavigationIntervals.Clear; FContentNavigationWithoutResources := False; end; function TcxSchedulerCustomResourceViewViewInfo.GetClones: TcxSchedulerEventList; begin Result := View.EventList.Clones; end; function TcxSchedulerCustomResourceViewViewInfo.GetCorrectColumnHeight( AColumnRect: TRect): Integer; begin Result := Min(AColumnRect.Bottom - AColumnRect.Top, GetMinResourceHeight); end; function TcxSchedulerCustomResourceViewViewInfo.GetDay(AIndex: Integer): TDateTime; begin Result := Integer(SelectedDays.List^[AIndex]); end; function TcxSchedulerCustomResourceViewViewInfo.GetDayCount: Integer; begin Result := SelectedDays.Count; end; function TcxSchedulerCustomResourceViewViewInfo.GetShowEventsWithoutResource: Boolean; begin Result := View.OptionsView.ShowEventsWithoutResource or (FGroupingKind = gkNone); end; function TcxSchedulerCustomResourceViewViewInfo.GetGroupByDate: Boolean; begin Result := GroupingKind = gkByDate; end; function TcxSchedulerCustomResourceViewViewInfo.GetGroupByResource: Boolean; begin Result := GroupingKind = gkByResource; end; function TcxSchedulerCustomResourceViewViewInfo.GetGroupingKind: TcxSchedulerGroupingKind; begin Result := View.GroupingKind; if Result = gkDefault then Result := View.OptionsView.GroupingKind; if ResourceCount = 0 then Result := gkNone else if Result = gkDefault then Result := gkByResource; end; function TcxSchedulerCustomResourceViewViewInfo.GetHasSeparator: Boolean; begin Result := (SeparatorWidth > 0) and (GroupingKind <> gkNone); end; function TcxSchedulerCustomResourceViewViewInfo.GetHasVisibleBounds: Boolean; begin Result := (PrintFrom <> NullDate) and (PrintTo <> NullDate) end; function TcxSchedulerCustomResourceViewViewInfo.GetHiddenSelection: Boolean; begin Result := View.Controller.IsEditing or (Events.Selection.Count > 0); end; function TcxSchedulerCustomResourceViewViewInfo.GetMinResourceHeight: Integer; var I, AResourceHeight: Integer; begin Result := MaxInt; if Length(FResourceBounds) = ResourceCount then for I := 0 to ResourceCount - 1 do begin AResourceHeight := FResourceBounds[I].Bottom - FResourceBounds[I].Top; if (AResourceHeight <> 0) and (Result > AResourceHeight) then Result := AResourceHeight; end; end; function TcxSchedulerCustomResourceViewViewInfo.GetMoreEventsButtonCount( AResourceIndex: Integer): Integer; function IsButtonWithoutResources( AButton: TcxSchedulerMoreEventsButtonViewInfo): Boolean; var I: Integer; begin Result := True; I := 0; while (I < ResourceCount) and Result do begin if AButton.Event.IsSharedWithResource(Resources[I].ResourceID) then Result := False; Inc(I); end; end; var I: Integer; begin Result := 0; for I := 0 to Buttons.Count - 1 do if (Buttons[I] is TcxSchedulerMoreEventsButtonViewInfo) and ((AResourceIndex = -1) or TcxSchedulerMoreEventsButtonViewInfo(Buttons[I]).Event.IsSharedWithResource( Resources[AResourceIndex].ResourceID) or IsButtonWithoutResources(TcxSchedulerMoreEventsButtonViewInfo(Buttons[I]))) then Inc(Result); end; function TcxSchedulerCustomResourceViewViewInfo.GetResource( AIndex: Integer): TcxSchedulerResourceViewInfo; begin if AIndex < 0 then Result := nil else Result := TcxSchedulerResourceViewInfo(FResources[AIndex]); end; function TcxSchedulerCustomResourceViewViewInfo.GetResourceCaption( AIndex: Integer): string; begin Result := Resources[AIndex].Caption; end; function TcxSchedulerCustomResourceViewViewInfo.GetResourceCount: Integer; begin Result := FResources.Count; end; function TcxSchedulerCustomResourceViewViewInfo.GetResourceHeaders: TcxSchedulerResourceHeaders; begin Result := View.OptionsView.ResourceHeaders; end; function TcxSchedulerCustomResourceViewViewInfo.GetPrintRange( Index: Integer): TDateTime; begin Result := Adapter.GetPrintRange(Index) end; function TcxSchedulerCustomResourceViewViewInfo.GetSeparatorWidth: Integer; begin Result := View.OptionsView.GroupSeparatorWidth; end; function TcxSchedulerCustomResourceViewViewInfo.GetView: TcxSchedulerCustomResourceView; begin Result := TcxSchedulerCustomResourceView(Owner); end; function TcxSchedulerCustomResourceViewViewInfo.IsDrawContentNavigationButtons: Boolean; var I: Integer; begin Result := CanCalculateNavigationButtons; if Result then begin I := 0; if ResourceCount > 0 then while (I < ResourceCount) and Result do begin Result := IsValidNavigationButtonsPlace(FResourceBounds[I]); Inc(I); end else Result := IsValidNavigationButtonsPlace(Bounds); end; end; procedure TcxSchedulerCustomResourceViewViewInfo.SetContentNavigationButtonsIntervals; procedure FillContentNavigationIntervals; var ACalculator: TcxSchedulerContentNavigationCalculator; AStart, AFinish: TDateTime; begin ReturnVisibleInterval(AStart, AFinish); ACalculator := TcxSchedulerContentNavigationCalculator.Create; try ACalculator.FindNavigationIntervals(Scheduler.Storage, FContentNavigationIntervals, AStart, AFinish, FContentNavigationWithoutResources, ShowEventsWithoutResource); finally ACalculator.Free; end; end; var I: Integer; AContentNavigationButton: TcxSchedulerContentNavigationButtonViewInfo; begin FillContentNavigationIntervals; for I := 0 to FNavigationButtons.Count - 1 do begin AContentNavigationButton := TcxSchedulerContentNavigationButtonViewInfo(FNavigationButtons[I]); AContentNavigationButton.Interval := GetContentNavigationInterval(AContentNavigationButton); end; end; procedure TcxSchedulerCustomResourceViewViewInfo.SetHitContentNavigationButton( AButton: TcxSchedulerContentNavigationButtonViewInfo; AHitTest: TcxSchedulerCustomResourceViewHitTest); begin AHitTest.FContentNavigationButton := AButton; HotContentNavigationButton := AButton; end; procedure TcxSchedulerCustomResourceViewViewInfo.SetHotContentNavigationButton( AButton: TcxSchedulerContentNavigationButtonViewInfo); begin if FHotContentNavigationButton <> AButton then begin if FHotContentNavigationButton <> nil then begin EndMouseTracking(Self); View.RepaintRect(FHotContentNavigationButton.Bounds); end; FHotContentNavigationButton := AButton; if FHotContentNavigationButton <> nil then begin View.RepaintRect(FHotContentNavigationButton.Bounds); BeginMouseTracking(Scheduler, cxRectOffset(FHotContentNavigationButton.Bounds, View.Left, View.Top), Self); end; end; end; { TcxSchedulerCustomResourceViewNavigation } procedure TcxSchedulerCustomResourceViewNavigation.ValidateSelection( var ASelStart, ASelFinish: TDateTime; var AResource: TcxSchedulerStorageResourceItem); begin AResource := ResourceItem; end; function TcxSchedulerCustomResourceViewNavigation.GetNextResource( AGoToForward: Boolean): TcxSchedulerStorageResourceItem; var AIndex: Integer; begin Result := ResourceItem; AIndex := ViewInfo.FResources.IndexOf(ResourceObject) + Byte(AGoToForward) * 2 - 1; if (AIndex < 0) or (AIndex >= ViewInfo.FResources.Count) then Exit; Result := ViewInfo.GetResourceItemByIndex(AIndex); end; function TcxSchedulerCustomResourceViewNavigation.GetResourceItem: TcxSchedulerStorageResourceItem; begin Result := nil; if ResourceObject <> nil then Result := ResourceObject.ResourceItem; end; function TcxSchedulerCustomResourceViewNavigation.GetResourceFromViewInfo( AInfo: TcxSchedulerResourceViewInfo): TcxSchedulerStorageResourceItem; begin Result := nil; if AInfo <> nil then Result := AInfo.ResourceItem; end; function TcxSchedulerCustomResourceViewNavigation.RoundTime( const ADateTime: TDateTime): TDateTime; begin Result := DateTimeHelper.RoundTime(ADateTime); end; function TcxSchedulerCustomResourceViewNavigation.GetIsFirstResource: Boolean; begin Result := ViewInfo.FResources.IndexOf(ResourceObject) <= 0; end; function TcxSchedulerCustomResourceViewNavigation.GetIsLastResource: Boolean; begin Result := ViewInfo.FResources.IndexOf(ResourceObject) = (ViewInfo.FResources.Count - 1); end; function TcxSchedulerCustomResourceViewNavigation.GetGroupingKind: TcxSchedulerGroupingKind; begin Result := ViewInfo.FGroupingKind; end; function TcxSchedulerCustomResourceViewNavigation.GetResourceObject: TcxSchedulerResourceViewinfo; begin Result := ViewInfo.FSelResource; end; function TcxSchedulerCustomResourceViewNavigation.GetViewInfo: TcxSchedulerCustomResourceViewViewInfo; begin Result := TcxSchedulerCustomResourceView(View).ViewInfo; end; { TcxSchedulerCustomResourceViewController } function TcxSchedulerCustomResourceViewController.CreateNavigation: TcxSchedulerViewNavigation; begin Result := TcxSchedulerCustomResourceViewNavigation.Create(View); end; function TcxSchedulerCustomResourceViewController.GetCursor(X, Y: Integer): TCursor; const Cursors: array[Boolean] of TCursor = (crSchedulerVertResize, crSchedulerHorzResize); begin with HitTest do case GetDragKind of edkEventDragRect: Result := crSchedulerSplitAll; edkResizeStart, edkResizeEnd: Result := Cursors[EventCell.IsHorzSizing]; else Result := inherited GetCursor(X, Y); end; end; procedure TcxSchedulerCustomResourceViewController.MouseDown( Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin NavigationButtonClicked := HitTest.HitAtContentNavigationButton; if HitTest.HitAtButton then Exclude(Shift, ssDouble); inherited MouseDown(Button, Shift, X, Y); if HitTest.HitAtButton then HitTest.Button.Click; InternalHideHint; end; procedure TcxSchedulerCustomResourceViewController.MouseLeave; begin inherited MouseLeave; InternalHideHint; NavigationButtonClicked := False; end; procedure TcxSchedulerCustomResourceViewController.MouseMove(Shift: TShiftState; X, Y: Integer); begin if not NavigationButtonClicked then inherited MouseMove(Shift, X, Y); ShowHint; end; procedure TcxSchedulerCustomResourceViewController.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin inherited MouseUp(Button, Shift, X, Y); if (HitTest.HitAtContentNavigationButton) and (Button = mbLeft) then HitTest.ContentNavigationButton.Click; InternalHideHint; NavigationButtonClicked := False; end; function TcxSchedulerCustomResourceViewController.GetDayHeaderDate: TDateTime; begin Result := HitTest.Time; end; procedure TcxSchedulerCustomResourceViewController.InternalHideHint; begin HintController.Hide; FCalculatedHintBounds := False; end; procedure TcxSchedulerCustomResourceViewController.InternalShowHint(P: TPoint; const AHintText: string); var R: TRect; begin if (not FCalculatedHintBounds) then begin FHintText := AHintText; R := HintController.CalcHintRect(cxscMinHintWidth, AHintText, cxAlignRight); OffsetRect(R, P.X, P.Y + cxGetCursorSize.cy); HintController.Activate(R, AHintText, True, False); FCalculatedHintBounds := True; end; end; function TcxSchedulerCustomResourceViewController.NeedShowDayHeaderHint: Boolean; var AGroupingKind: TcxSchedulerGroupingKind; AGroupByDate: Boolean; begin AGroupingKind := View.GetGroupingKind; AGroupByDate := AGroupingKind in [gkByDate, gkDefault]; Result := Scheduler.OptionsView.ShowHints and HitTest.HitAtDayHeader and (HitTest.HitAtTime) and ((AGroupByDate and not HitTest.HitAtResourceHeader) or not AGroupByDate); end; function TcxSchedulerCustomResourceViewController.ShowHint: Boolean; begin Result := NeedShowDayHeaderHint; if Result then ShowDayHeaderHint else begin Result := HitTest.NeedShowHint; if not Result then InternalHideHint; end; end; procedure TcxSchedulerCustomResourceViewController.ShowDayHeaderHint; var AHintText: string; ADate: TDateTime; begin AHintText := ''; ADate := GetDayHeaderDate; if TcxCustomSchedulerAccess(Scheduler).DoShowDateHint(ADate, AHintText) then begin if AnsiCompareText(AHintText, FHintText) <> 0 then InternalHideHint; InternalShowHint(GetMouseCursorPos, AHintText); end else InternalHideHint; end; function TcxSchedulerCustomResourceViewController.GetHintController: TcxSchedulerHintController; begin Result := TcxCustomSchedulerAccess(Scheduler).HintController; end; function TcxSchedulerCustomResourceViewController.GetHitTest: TcxSchedulerCustomResourceViewHitTest; begin Result := TcxSchedulerCustomResourceViewHitTest(inherited HitTest); end; function TcxSchedulerCustomResourceViewController.GetView: TcxSchedulerCustomResourceView; begin Result := TcxSchedulerCustomResourceView(inherited View); end; { TcxSchedulerCustomResourceViewHitTest } function TcxSchedulerCustomResourceViewHitTest.GetDragKind: TcxEventDragKind; begin ValidateDragKind; Result := FDragKind; end; procedure TcxSchedulerCustomResourceViewHitTest.SetDragKind( AValue: TcxEventDragKind); begin FDragKind := AValue; ValidateDragKind; end; function TcxSchedulerCustomResourceViewHitTest.CanMoveEvent( AEvent: TcxSchedulerControlEvent): Boolean; var AResource: TcxSchedulerStorageResourceItem; begin Result := Scheduler.EventOperations.Moving; if Result then begin AResource := AEvent.GetResourceItem; Result := (AResource = nil) or not AResource.ReadOnly; end; end; function TcxSchedulerCustomResourceViewHitTest.CanResizeEvent( AEvent: TcxSchedulerControlEvent): Boolean; var AResource: TcxSchedulerStorageResourceItem; begin Result := Scheduler.EventOperations.Sizing; if Result then begin AResource := AEvent.GetResourceItem; Result := (AResource = nil) or not AResource.ReadOnly; end; end; procedure TcxSchedulerCustomResourceViewHitTest.Clear; begin FDragKind := edkNone; FEventCell := nil; FResource := nil; FHitObject := nil; FContentNavigationButton := nil; inherited Clear; end; procedure TcxSchedulerCustomResourceViewHitTest.DoCalculate; begin inherited DoCalculate; if HitAtControl then View.ViewInfo.CalculateHitTest(Self); end; function TcxSchedulerCustomResourceViewHitTest.GetHitEvent: TcxSchedulerControlEvent; begin Result := inherited GetHitEvent; if FEventCell <> nil then Result := FEventCell.Event; end; procedure TcxSchedulerCustomResourceViewHitTest.SetHitTime( AItemFlag: Integer; const ATime: TDateTime); begin SetBitState(AItemFlag, True); SetBitState(htcTime, True); FTime := ATime; end; procedure TcxSchedulerCustomResourceViewHitTest.SetResource( AResource: TcxSchedulerResourceViewInfo); begin if AResource = nil then FResource := nil else FResource := AResource.ResourceItem; end; procedure TcxSchedulerCustomResourceViewHitTest.ValidateDragKind; begin if (Event = nil) or ((FDragKind in [edkEventDragRect, edkMoveEvent]) and not CanMoveEvent(Event)) or ((FDragKind in [edkResizeStart, edkResizeEnd]) and not CanResizeEvent(Event)) then FDragKind := edkNone; end; function TcxSchedulerCustomResourceViewHitTest.GetContentCell: TcxSchedulerContentCellViewInfo; begin if HitAtContent then Result := TcxSchedulerContentCellViewInfo(FHitObject) else Result := nil; end; function TcxSchedulerCustomResourceViewHitTest.GetHitContentNavigationButton: TcxSchedulerContentNavigationButtonViewInfo; begin if GetBitState(htcNavigationButton) then Result := FContentNavigationButton else Result := nil; end; function TcxSchedulerCustomResourceViewHitTest.GetHeaderCell: TcxSchedulerHeaderCellViewInfo; begin if HitAtDayHeader or HitAtResourceHeader then Result := TcxSchedulerHeaderCellViewInfo(FHitObject) else Result := nil; end; function TcxSchedulerCustomResourceViewHitTest.GetView: TcxSchedulerCustomResourceView; begin Result := TcxSchedulerCustomResourceView(inherited Owner); end; { TcxSchedulerCustomViewPainter } constructor TcxSchedulerCustomViewPainter.Create( AOwner: TcxSchedulerSubControl); begin inherited Create(AOwner); FPainter := View.GetCommonViewItemsPainter; end; procedure TcxSchedulerCustomViewPainter.InitializePainter; begin FPainter := View.GetCommonViewItemsPainter; end; procedure TcxSchedulerCustomViewPainter.Paint; begin end; procedure TcxSchedulerCustomViewPainter.DrawBackgroundCell( AItem: TcxSchedulerBackgroundCellViewInfo); var ADone: Boolean; begin if AItem = nil then Exit; ADone := False; AItem.BeforeCustomDraw(Canvas); if Painter <> nil then Painter.DoCustomDrawBackground(AItem, ADone); if not ADone then View.DoCustomDrawBackground(AItem, ADone); AItem.AfterCustomDraw(Canvas); if not ADone then AItem.Draw(Canvas); end; procedure TcxSchedulerCustomViewPainter.DrawButtonCell( AItem: TcxSchedulerCustomViewInfoItem; var ADone: Boolean); begin if AItem is TcxSchedulerMoreEventsButtonViewInfo then begin if Painter <> nil then Painter.DoCustomDrawButton(TcxSchedulerMoreEventsButtonViewInfo(AItem), ADone); if not ADone then View.DoCustomDrawButton(TcxSchedulerMoreEventsButtonViewInfo(AItem), ADone); end else begin if Painter <> nil then Painter.DoCustomDrawNavigationButton(TcxSchedulerContentNavigationButtonViewInfo(AItem), ADone); if not ADone then View.DoCustomDrawNavigationButton(TcxSchedulerContentNavigationButtonViewInfo(AItem), ADone); end; end; procedure TcxSchedulerCustomViewPainter.DrawContentCell( AItem: TcxSchedulerCustomViewInfoItem; var ADone: Boolean); begin if Painter <> nil then Painter.DoCustomDrawContent(TcxSchedulerContentCellViewInfo(AItem), ADone); if not ADone then View.DoCustomDrawContent(TcxSchedulerContentCellViewInfo(AItem), ADone); end; procedure TcxSchedulerCustomViewPainter.DrawEventCell( AItem: TcxSchedulerCustomViewInfoItem; var ADone: Boolean); begin with TcxSchedulerEventCellViewInfo(AItem) do if Hidden or not Visible then Exit; if Painter <> nil then Painter.DoCustomDrawEvent(TcxSchedulerEventCellViewInfo(AItem), ADone); if not ADone then View.DoCustomDrawEvent(TcxSchedulerEventCellViewInfo(AItem), ADone); end; procedure TcxSchedulerCustomViewPainter.DrawHeaderCell( AItem: TcxSchedulerCustomViewInfoItem; var ADone: Boolean); begin if Painter <> nil then Painter.DoCustomDrawDayHeader(TcxSchedulerDayHeaderCellViewInfo(AItem), ADone); if not ADone then View.DoCustomDrawDayHeader(TcxSchedulerDayHeaderCellViewInfo(AItem), ADone); end; procedure TcxSchedulerCustomViewPainter.DrawGroupSeparatorCell( AItem: TcxSchedulerCustomViewInfoItem; var ADone: Boolean); begin if Painter <> nil then Painter.DoCustomDrawGroupSeparator(TcxSchedulerGroupSeparatorCellViewInfo(AItem), ADone); if not ADone then View.DoCustomDrawGroupSeparator(TcxSchedulerGroupSeparatorCellViewInfo(AItem), ADone); end; procedure TcxSchedulerCustomViewPainter.DrawResourceHeaderCell( AItem: TcxSchedulerCustomViewInfoItem; var ADone: Boolean); begin if Painter <> nil then Painter.DoCustomDrawResourceHeader(TcxSchedulerHeaderCellViewInfo(AItem), ADone); if not ADone then View.DoCustomDrawResourceHeader(TcxSchedulerHeaderCellViewInfo(AItem), ADone); end; function TcxSchedulerCustomViewPainter.GetView: TcxSchedulerCustomResourceView; begin Result := TcxSchedulerCustomResourceView(Owner); end; { TcxSchedulerEventPlace } procedure TcxSchedulerEventPlace.AlignPosition(APlace: TcxSchedulerEventPlace); begin LineFinish := APlace.LineFinish + 1 + (LineFinish - LineStart); LineStart := APlace.LineFinish + 1; end; function TcxSchedulerEventPlace.IntersectHorz(APlace: TcxSchedulerEventPlace): Boolean; begin Result := (APlace.Resource = Resource) and (APlace.ColFinish >= ColStart) and (APlace.ColStart <= ColFinish); end; function TcxSchedulerEventPlace.IntersectVert(APlace: TcxSchedulerEventPlace): Boolean; begin Result := (APlace.Resource = Resource) and (APlace.LineFinish >= LineStart) and (APlace.LineStart <= LineFinish); end; procedure TcxSchedulerEventPlace.LineStartToEvent; begin TcxSchedulerControlEventAccess(Event).LineStart := LineStart; end; procedure TcxSchedulerEventPlace.ResetPosition; begin LineFinish := LineFinish - LineStart; LineStart := 0; end; function cxCompareEventPlaces(AEventPlace1, AEventPlace2: TcxSchedulerEventPlace): Integer; var AAllDay1, AAllDay2: Boolean; AEvent1, AEvent2: TcxSchedulerEvent; begin Result := Integer(AEventPlace1.Resource) - Integer(AEventPlace2.Resource); if Result <> 0 then Exit; AEvent1 := AEventPlace1.Event; AEvent2 := AEventPlace2.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 AEventPlace1.ColStart < AEventPlace2.ColStart then Result := -1 else if AEventPlace1.ColStart > AEventPlace2.ColStart then Result := 1 else if AEventPlace1.ColFinish > AEventPlace2.ColFinish then Result := -1 else if AEventPlace1.ColFinish < AEventPlace2.ColFinish then Result := 1 else 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 if AEvent1.RecordIndex < AEvent2.RecordIndex then Result := -1 else if AEvent1.RecordIndex > AEvent2.RecordIndex then Result := 1 else Result := 0; end; { TcxSchedulerEventLayoutBuilder } constructor TcxSchedulerEventLayoutBuilder.Create; begin FEventPlaces := TcxObjectList.Create; end; destructor TcxSchedulerEventLayoutBuilder.Destroy; begin FreeAndNil(FEventPlaces); inherited Destroy; end; function TcxSchedulerEventLayoutBuilder.AddEventPlace(AEvent: TcxSchedulerEvent; AStartCol, AFinishCol: Integer; ALineCount: Integer = 1; AResource: TObject = nil): TcxSchedulerEventPlace; begin Result := TcxSchedulerEventPlace.Create; Result.ColStart := AStartCol; Result.ColFinish := AFinishCol; Result.Event := AEvent; Result.LineFinish := ALineCount - 1; Result.Resource := AResource; FEventPlaces.Add(Result); end; procedure TcxSchedulerEventLayoutBuilder.Clear; begin FEventPlaces.Clear; end; procedure TcxSchedulerEventLayoutBuilder.Calculate; var I, J, K: Integer; ACurPlace: TcxSchedulerEventPlace; begin FEventPlaces.Sort(TListSortCompare(@cxCompareEventPlaces)); for I := 1 to EventPlaceCount - 1 do begin J := I; K := I; ACurPlace := EventPlaces[I]; repeat Dec(J); if ACurPlace.IntersectHorz(EventPlaces[J]) then K := J; until J = 0; ACurPlace.ResetPosition; J := K; while J < I do begin if ACurPlace.IntersectHorz(EventPlaces[J]) and ACurPlace.IntersectVert(EventPlaces[J]) then begin ACurPlace.AlignPosition(EventPlaces[J]); J := K; end else Inc(J); end; end; end; procedure TcxSchedulerEventLayoutBuilder.CalculateEx(AEventsList: TcxSchedulerFilteredEventList; APlaceInfoProc: TcxSchedulerEventLayoutBuilderGetEventPlaceProc); var AEvent: TcxSchedulerControlEvent; I, AStartCol, AFinishCol, ALineCount: Integer; begin Clear; for I := 0 to AEventsList.Count - 1 do begin AEvent := AEventsList[I]; ALineCount := 1; if APlaceInfoProc(Self, AEventsList[I], AStartCol, AFinishCol, ALineCount) then AddEventPlace(AEvent, AStartCol, AFinishCol, ALineCount); end; Calculate; end; function TcxSchedulerEventLayoutBuilder.GetEventPlace(AIndex: Integer): TcxSchedulerEventPlace; begin Result := TcxSchedulerEventPlace(FEventPlaces.List^[AIndex]); end; function TcxSchedulerEventLayoutBuilder.GetEventPlaceCount: Integer; begin Result := FEventPlaces.Count; end; end.