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

514 lines
18 KiB
ObjectPascal

{********************************************************************}
{ }
{ Developer Express Visual Component Library }
{ ExpressSkins Library }
{ }
{ Copyright (c) 2006-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 EXPRESSSKINS 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 dxSkinscxSchedulerPainter;
interface
uses
Windows, SysUtils, Classes, cxSchedulerCustomResourceView, cxDateUtils,
cxSchedulerCustomControls, dxSkinsCore, dxSkinsLookAndFeelPainter,
cxLookAndFeels, cxLookAndFeelPainters, cxGraphics, Graphics, cxGeometry,
cxSchedulerUtils, Math, cxScheduler, cxClasses;
type
{ TcxSchedulerSkinViewItemsPainter }
TcxSchedulerSkinViewItemsPainter = class(TcxSchedulerExternalPainter)
private
procedure DrawCaption(ACanvas: TcxCanvas; const ATextAreaBounds: TRect;
AAlignmentHorz: TAlignment; AAlignmentVert: TcxAlignmentVert;
AMultiLine, AShowEndEllipsis: Boolean; const AText: string;
AFont: TFont; ATextColor: TColor);
procedure DrawClippedElement(ACanvas: TcxCanvas; AElement: TdxSkinElement;
ABorders: TcxBorders; R: TRect);
function IsSkinAvalaible: Boolean;
function SkinInfo: TdxSkinLookAndFeelPainterInfo;
// Headers
procedure DrawHorizontalHeader(AViewInfo: TcxSchedulerDayHeaderCellViewInfo);
procedure DrawVerticalHeader(AViewInfo: TcxSchedulerDayHeaderCellViewInfo);
public
procedure DoCustomDrawButton(AViewInfo: TcxSchedulerMoreEventsButtonViewInfo;
var ADone: Boolean); override;
procedure DoCustomDrawDayHeader(AViewInfo: TcxSchedulerDayHeaderCellViewInfo;
var ADone: Boolean); override;
//
function NeedDrawSelection: Boolean; override;
function DrawCurrentTimeFirst: Boolean; override;
//
procedure DrawAllDayArea(ACanvas: TcxCanvas; const ARect: TRect;
ABorderColor: TColor; ABorders: TcxBorders; AViewParams: TcxViewParams;
ASelected: Boolean; ATransparent: Boolean); override;
procedure DrawCurrentTime(ACanvas: TcxCanvas; AColor: TColor; AStart: TDateTime;
ABounds: TRect); override;
procedure DrawEvent(AViewInfo: TcxSchedulerEventCellViewInfo); override;
procedure DrawTimeGridHeader(ACanvas: TcxCanvas; ABorderColor: TColor;
AViewInfo: TcxSchedulerCustomViewInfoItem; ABorders: TcxBorders;
ASelected: Boolean); override;
procedure DrawTimeLine(ACanvas: TcxCanvas; const ARect: TRect;
AViewParams: TcxViewParams; ABorders: TcxBorders;
ABorderColor: TColor); override;
procedure DrawTimeRulerBackground(ACanvas: TcxCanvas; const ARect: TRect;
ABorders: TcxBorders; AViewParams: TcxViewParams; ATransparent: Boolean); override;
procedure DrawShadow(ACanvas: TcxCanvas; const ARect, AVisibleRect: TRect;
ABuffer: TBitmap); override;
function MoreButtonSize(ASize: TSize): TSize; override;
end;
implementation
uses Types;
type
TcxCustomSchedulerAccess = class(TcxCustomScheduler);
const
cxHeaderStateToButtonState: array[Boolean] of TcxButtonState =
(cxbsNormal, cxbsHot);
{ TcxSchedulerSkinViewItemsPainter }
procedure TcxSchedulerSkinViewItemsPainter.DrawClippedElement(ACanvas: TcxCanvas;
AElement: TdxSkinElement; ABorders: TcxBorders; R: TRect);
begin
ACanvas.SaveClipRegion;
ACanvas.SetClipRegion(TcxRegion.Create(R), roIntersect);
try
with AElement.Image.Margins.Rect do
begin
if not (bLeft in ABorders) then
Dec(R.Left, Left);
if not (bTop in ABorders) then
Dec(R.Top, Top);
if not (bRight in ABorders) then
Inc(R.Right, Right);
if not (bBottom in ABorders) then
Inc(R.Bottom, Bottom);
end;
AElement.Draw(ACanvas.Handle, R);
finally
ACanvas.RestoreClipRegion;
end;
end;
function TcxSchedulerSkinViewItemsPainter.IsSkinAvalaible: Boolean;
begin
Result := Painter.InheritsFrom(TdxSkinLookAndFeelPainter);
end;
function TcxSchedulerSkinViewItemsPainter.SkinInfo: TdxSkinLookAndFeelPainterInfo;
begin
GetExtendedStylePainters.GetPainterData(Painter, Result);
end;
function TcxSchedulerSkinViewItemsPainter.MoreButtonSize(ASize: TSize): TSize;
begin
if IsSkinAvalaible and (SkinInfo.SchedulerMoreButton <> nil) then
Result := SkinInfo.SchedulerMoreButton.Size
else
Result := ASize;
end;
procedure TcxSchedulerSkinViewItemsPainter.DoCustomDrawButton(
AViewInfo: TcxSchedulerMoreEventsButtonViewInfo; var ADone: Boolean);
begin
inherited DoCustomDrawButton(AViewInfo, ADone);
if not ADone and IsSkinAvalaible then
begin
ADone := SkinInfo.SchedulerMoreButton <> nil;
if ADone then
begin
with AViewInfo do
SkinInfo.SchedulerMoreButton.Draw(Canvas.Handle, Bounds, Byte(IsDown));
end;
end;
end;
procedure TcxSchedulerSkinViewItemsPainter.DrawCaption(ACanvas: TcxCanvas;
const ATextAreaBounds: TRect; AAlignmentHorz: TAlignment;
AAlignmentVert: TcxAlignmentVert; AMultiLine, AShowEndEllipsis: Boolean;
const AText: string; AFont: TFont; ATextColor: TColor);
const
AlignmentsHorz: array[TAlignment] of Integer =
(cxAlignLeft, cxAlignRight, cxAlignHCenter);
AlignmentsVert: array[TcxAlignmentVert] of Integer =
(cxAlignTop, cxAlignBottom, cxAlignVCenter);
MultiLines: array[Boolean] of Integer = (cxSingleLine, cxWordBreak);
ShowEndEllipsises: array[Boolean] of Integer = (0, cxShowEndEllipsis);
begin
with ACanvas do
if AText <> '' then
begin
Brush.Style := bsClear;
Font := AFont;
Font.Color := ATextColor;
DrawText(AText, ATextAreaBounds, AlignmentsHorz[AAlignmentHorz] or
AlignmentsVert[AAlignmentVert] or MultiLines[AMultiLine] or
ShowEndEllipsises[AShowEndEllipsis]);
end;
end;
procedure TcxSchedulerSkinViewItemsPainter.DrawHorizontalHeader(
AViewInfo: TcxSchedulerDayHeaderCellViewInfo);
begin
with AViewInfo do
begin
Painter.DrawHeader(Canvas, Bounds, TextRect, Neighbors, Borders,
cxHeaderStateToButtonState[Selected], AlignHorz, AlignVert, MultiLine,
ShowEndEllipsis, '', Font, TextColor, 0, nil);
DrawCaption(Canvas, TextRect, AlignHorz, AlignVert, MultiLine,
ShowEndEllipsis, DisplayText, Font, TextColor);
end;
end;
procedure TcxSchedulerSkinViewItemsPainter.DrawVerticalHeader(
AViewInfo: TcxSchedulerDayHeaderCellViewInfo);
var
ABitmap: TcxBitmap;
R: TRect;
begin
with AViewInfo do
begin
ABitmap := TcxBitmap.CreateSize(Bounds);
try
ABitmap.cxCanvas.WindowOrg := Bounds.TopLeft;
cxBitBlt(ABitmap.Canvas.Handle, Canvas.Handle, ABitmap.ClientRect, Bounds.TopLeft, SRCCOPY);
ABitmap.Rotate(raPlus90, True);
R := ABitmap.ClientRect;
Painter.DrawHeader(ABitmap.cxCanvas, R, R, Neighbors, Borders, cxbsNormal,
taCenter, vaCenter, False, False, '', Font, TextColor, Color, nil);
if RotateText then
begin
ABitmap.Rotate(ra0, True);
DrawCaption(ABitmap.cxCanvas, R, AlignHorz, AlignVert, MultiLine,
ShowEndEllipsis, DisplayText, Font, TextColor);
ABitmap.Rotate(raPlus90);
end
else
begin
ABitmap.Rotate(raPlus90, True);
R.BottomRight := cxPoint(R.Bottom, R.Right);
DrawCaption(ABitmap.cxCanvas, R, AlignHorz, AlignVert, MultiLine,
ShowEndEllipsis, DisplayText, Font, TextColor);
end;
cxBitBlt(Canvas.Handle, ABitmap.Canvas.Handle, Bounds, cxNullPoint, SRCCOPY);
finally
ABitmap.Free;
end;
end;
end;
procedure TcxSchedulerSkinViewItemsPainter.DoCustomDrawDayHeader(
AViewInfo: TcxSchedulerDayHeaderCellViewInfo; var ADone: Boolean);
begin
inherited DoCustomDrawDayHeader(AViewInfo, ADone);
ADone := IsSkinAvalaible;
if ADone then
with AViewInfo do
if RotateHeader or RotateText then
DrawVerticalHeader(AViewInfo)
else
DrawHorizontalHeader(AViewInfo);
end;
procedure TcxSchedulerSkinViewItemsPainter.DrawAllDayArea(ACanvas: TcxCanvas;
const ARect: TRect; ABorderColor: TColor; ABorders: TcxBorders;
AViewParams: TcxViewParams; ASelected: Boolean; ATransparent: Boolean);
var
ADoCustomDraw: Boolean;
AElement: TdxSkinElement;
begin
if IsSkinAvalaible then
begin
AElement := SkinInfo.SchedulerAllDayArea[ASelected];
ADoCustomDraw := AElement = nil;
if not ADoCustomDraw then
DrawClippedElement(ACanvas, AElement, ABorders, ARect);
end
else
ADoCustomDraw := True;
if ADoCustomDraw then
inherited DrawAllDayArea(ACanvas, ARect, ABorderColor, ABorders, AViewParams,
ASelected, ATransparent);
end;
procedure TcxSchedulerSkinViewItemsPainter.DrawCurrentTime(ACanvas: TcxCanvas;
AColor: TColor; AStart: TDateTime; ABounds: TRect);
var
ADoCustomDraw: Boolean;
AElement: TdxSkinElement;
ANow: TDateTime;
Y, I: Integer;
begin
if IsSkinAvalaible then
begin
AElement := SkinInfo.SchedulerCurrentTimeIndicator;
ADoCustomDraw := AElement = nil;
if not ADoCustomDraw then
begin
ANow := TimeOf(Now) - TimeOf(AStart);
if (ANow < 0) or (ANow >= HourToTime) then Exit;
Y := Trunc(ABounds.Top + (ANow * cxRectHeight(ABounds)) / HourToTime);
Dec(ABounds.Right);
Inc(ABounds.Left, 5);
with AElement.Image.Size do
ABounds := cxRectSetTop(ABounds, Y - cy div 2, cy);
for I := 0 to 1 do
AElement.Draw(ACanvas.Handle, ABounds, I);
end;
end
else
ADoCustomDraw := True;
if ADoCustomDraw then
inherited DrawCurrentTime(ACanvas, AColor, AStart, ABounds);
end;
function TcxSchedulerSkinViewItemsPainter.NeedDrawSelection: Boolean;
begin
Result := not IsSkinAvalaible;
end;
function TcxSchedulerSkinViewItemsPainter.DrawCurrentTimeFirst: Boolean;
begin
Result := True;
end;
procedure TcxSchedulerSkinViewItemsPainter.DrawEvent(
AViewInfo: TcxSchedulerEventCellViewInfo);
const
AShadowSize = 4;
ASelectedFlags: array[Boolean] of TdxSkinElementState = (esNormal, esHot);
var
ADone: Boolean;
AElement: TdxSkinElement;
AMask: TdxSkinElement;
ASkinInfo: TdxSkinLookAndFeelPainterInfo;
function CheckRect(const ARect: TRect): TRect;
begin
if AViewInfo.Selected and (ASkinInfo.SchedulerAppointmentBorderSize <> nil) then
begin
with ASkinInfo.SchedulerAppointmentBorderSize do
begin
Result := Rect(ARect.Left, ARect.Top - Value, ARect.Right + Value,
ARect.Bottom + Value);
if IsRectEmpty(AViewInfo.TimeLineRect) then
Dec(Result.Left, Value)
else
Dec(Result.Left, cxTimeLineWidth);
end;
end
else
Result := ARect;
end;
procedure DrawShadowLine(const AShadow: TdxSkinElement; const ARect: TRect);
begin
if AShadow <> nil then
AShadow.Draw(AViewInfo.Canvas.Handle, ARect);
end;
procedure DrawShadows(ASkinInfo: TdxSkinLookAndFeelPainterInfo);
begin
with AViewInfo do
if EventViewData.DrawShadows and (EventViewData.Bitmap <> nil) and
not Hidden and not Selected and ShowTimeLine then
begin
DrawShadowLine(ASkinInfo.SchedulerAppointmentShadow[False],
Rect(Bounds.Left + AShadowSize, Bounds.Bottom - AShadowSize,
Bounds.Right + AShadowSize, Bounds.Bottom + AShadowSize));
DrawShadowLine(ASkinInfo.SchedulerAppointmentShadow[True],
Rect(Bounds.Right - AShadowSize, Bounds.Top + AShadowSize,
Bounds.Right + AShadowSize, Bounds.Bottom - AShadowSize));
end;
end;
procedure DrawLabeledEvent(ALabelColor: TColor);
const
AImageIndexs: array[Boolean] of Integer = (1, 0);
var
ABitmap, AMaskBmp, ASourceBmp: TcxBitmap;
R: TRect;
begin
if AMask = nil then Exit;
R := AViewInfo.Bounds;
OffsetRect(R, -R.Left, -R.Top);
AMaskBmp := TcxBitmap.CreateSize(R, pf32bit);
ASourceBmp := TcxBitmap.CreateSize(R, pf32bit);
try
ASourceBmp.Canvas.Brush.Color := ALabelColor;
ASourceBmp.Canvas.FillRect(R);
AMask.Draw(AMaskBmp.Canvas.Handle, R, AImageIndexs[IsRectEmpty(AViewInfo.TimeLineRect)]);
ABitmap := TcxBitmap.CreateSize(R, pf32bit);
try
cxBitBlt(AMaskBmp.Canvas.Handle, AMaskBmp.Canvas.Handle, AMaskBmp.ClientRect, cxNullPoint, NOTSRCCOPY);
cxBitBlt(ABitmap.Canvas.Handle, AMaskBmp.Canvas.Handle, ABitmap.ClientRect, cxNullPoint, SRCCOPY);
cxBitBlt(ABitmap.Canvas.Handle, ASourceBmp.Canvas.Handle, ABitmap.ClientRect, cxNullPoint, SRCERASE);
cxBitBlt(AViewInfo.Canvas.Handle, AMaskBmp.Canvas.Handle, AViewInfo.Bounds, cxNullPoint, SRCAND);
cxBitBlt(AViewInfo.Canvas.Handle, ABitmap.Canvas.Handle, AViewInfo.Bounds, cxNullPoint, SRCINVERT);
finally
ABitmap.Free;
end;
finally
AMaskBmp.Free;
ASourceBmp.Free;
end;
end;
function GetSeparatorColor(ABorderColor: TdxSkinColor): TColor;
begin
Result := clDefault;
if ABorderColor <> nil then
Result := ABorderColor.Value;
if (Result = clNone) or (Result = clDefault) then
Result := AViewInfo.SeparatorColor;
end;
begin
ASkinInfo := SkinInfo;
ADone := ASkinInfo <> nil;
if ADone then
begin
with ASkinInfo do
begin
AElement := SchedulerAppointment[IsRectEmpty(AViewInfo.TimeLineRect)];
AMask := SchedulerAppointmentMask;
end;
ADone := (AElement <> nil) and (AMask <> nil);
if ADone then
with AViewInfo do
begin
Canvas.SaveClipRegion;
try
Canvas.SetClipRegion(TcxRegion.Create(
cxRectInflate(CheckRect(ClipRect), 0, 0, AShadowSize, AShadowSize)),
roSet);
Canvas.ExcludeClipRect(TimeLineRect);
DrawShadows(ASkinInfo);
SeparatorColor := GetSeparatorColor(ASkinInfo.SchedulerAppointmentBorder);
AElement.Draw(Canvas.Handle, CheckRect(Bounds), 0, ASelectedFlags[Selected]);
if Event.LabelColor <> clDefault then
DrawLabeledEvent(Event.LabelColor);
Transparent := True;
finally
Canvas.RestoreClipRegion;
end;
end;
end;
if not ADone then
inherited DrawEvent(AViewInfo);
end;
procedure TcxSchedulerSkinViewItemsPainter.DrawTimeGridHeader(ACanvas: TcxCanvas;
ABorderColor: TColor; AViewInfo: TcxSchedulerCustomViewInfoItem;
ABorders: TcxBorders; ASelected: Boolean);
var
ADoCustomDraw: Boolean;
AElement: TdxSkinElement;
begin
ADoCustomDraw := True;
if IsSkinAvalaible then
begin
AElement := SkinInfo.SchedulerTimeGridHeader[ASelected];
ADoCustomDraw := AElement = nil;
if not ADoCustomDraw then
with AViewInfo do
DrawClippedElement(ACanvas, AElement, ABorders, Bounds);
end;
if ADoCustomDraw then
inherited DrawTimeGridHeader(ACanvas, ABorderColor, AViewInfo, ABorders,
ASelected);
end;
procedure TcxSchedulerSkinViewItemsPainter.DrawTimeLine(ACanvas: TcxCanvas;
const ARect: TRect; AViewParams: TcxViewParams; ABorders: TcxBorders;
ABorderColor: TColor);
var
ADoCustomDraw: Boolean;
AElement: TdxSkinElement;
begin
ADoCustomDraw := True;
if IsSkinAvalaible then
begin
AElement := SkinInfo.SchedulerTimeLine;
ADoCustomDraw := AElement = nil;
if not ADoCustomDraw then
DrawClippedElement(ACanvas, AElement, ABorders, ARect);
end;
if ADoCustomDraw then
inherited DrawTimeLine(ACanvas, ARect, AViewParams, ABorders, ABorderColor);
end;
procedure TcxSchedulerSkinViewItemsPainter.DrawTimeRulerBackground(
ACanvas: TcxCanvas; const ARect: TRect; ABorders: TcxBorders;
AViewParams: TcxViewParams; ATransparent: Boolean);
var
ADoCustomDraw: Boolean;
AElement: TdxSkinElement;
begin
ADoCustomDraw := True;
if IsSkinAvalaible then
begin
AElement := SkinInfo.SchedulerTimeRuler;
ADoCustomDraw := AElement = nil;
if not ADoCustomDraw then
DrawClippedElement(ACanvas, AElement, ABorders, ARect);
end;
if ADoCustomDraw then
inherited DrawTimeRulerBackground(ACanvas, ARect, ABorders, AViewParams,
ATransparent);
end;
procedure TcxSchedulerSkinViewItemsPainter.DrawShadow(ACanvas: TcxCanvas;
const ARect, AVisibleRect: TRect; ABuffer: TBitmap);
begin
if not IsSkinAvalaible then
inherited DrawShadow(ACanvas, ARect, AVisibleRect, ABuffer);
end;
initialization
ExternalPainterClass := TcxSchedulerSkinViewItemsPainter;
finalization
ExternalPainterClass := TcxSchedulerExternalPainter;
end.