You've already forked lazarus-ccr
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@5890 8e941d3f-bd1b-0410-a28a-d453659cc2b4
814 lines
26 KiB
ObjectPascal
814 lines
26 KiB
ObjectPascal
{$I vp.inc}
|
|
|
|
unit VpMonthViewPainter;
|
|
|
|
interface
|
|
|
|
uses
|
|
SysUtils, LCLType, LCLIntf, Types, Classes, Graphics,
|
|
VpConst, VPBase, VpData, VpMonthView, VpBasePainter;
|
|
|
|
type
|
|
TVpMonthViewPainter = class(TVpBasePainter)
|
|
private
|
|
FMonthView: TVpMonthView;
|
|
// local parameters of the old TVpMonthView method
|
|
DisplayDate: TDateTime;
|
|
DisplayMonth: Word;
|
|
RealColor: TColor;
|
|
BevelHighlight: TColor;
|
|
BevelShadow: TColor;
|
|
BevelDarkShadow: TColor;
|
|
BevelFace: TColor;
|
|
DayHeadAttrColor: TColor;
|
|
HeadAttrColor: TColor;
|
|
RealLineColor: TColor;
|
|
RealOffDayColor: TColor;
|
|
RealSelDayColor: TColor;
|
|
EventFontColor: TColor;
|
|
TodayFontColor: TColor;
|
|
TodayAttrColor: TColor;
|
|
DotDotDotColor: TColor;
|
|
FCurrHoliday: String;
|
|
|
|
// protected variables of the original monthview needed only for painting
|
|
mvEventTextHeight: Integer;
|
|
mvDayNumberHeight: Integer;
|
|
mvRowHeight: Integer;
|
|
mvColWidth: Integer;
|
|
mvLineHeight: Integer;
|
|
|
|
protected
|
|
procedure Clear;
|
|
procedure DrawBorders;
|
|
procedure DrawDayCell(ADate: TDate; ACol, ARow: Integer;
|
|
var AIndex, ADayNumber: Integer; var ATextRect: TRect);
|
|
procedure DrawDayHead;
|
|
procedure DrawDays;
|
|
procedure DrawEvents;
|
|
procedure DrawFocusRect(ARect: TRect; FixRight: Boolean = false);
|
|
procedure DrawHeader;
|
|
procedure FixFontHeights;
|
|
procedure InitColors;
|
|
procedure SetMeasurements; override;
|
|
|
|
public
|
|
constructor Create(AMonthView: TVpMonthView; ARenderCanvas: TCanvas);
|
|
procedure RenderToCanvas(ARenderIn: TRect; AAngle: TVpRotationAngle;
|
|
AScale: Extended; ARenderDate: TDateTime; AStartLine, AStopLine: Integer;
|
|
AUseGran: TVpGranularity; ADisplayOnly: Boolean); override;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
LazUtf8, Math,
|
|
VpCanvasUtils, VpMisc;
|
|
|
|
type
|
|
TVpMonthViewOpener = class(TVpMonthView);
|
|
|
|
constructor TVpMonthViewPainter.Create(AMonthView: TVpMonthView;
|
|
ARenderCanvas: TCanvas);
|
|
begin
|
|
inherited Create(ARenderCanvas);
|
|
FMonthView := AMonthView;
|
|
end;
|
|
|
|
procedure TVpMonthViewPainter.Clear;
|
|
begin
|
|
RenderCanvas.Brush.Color := RealColor;
|
|
RenderCanvas.FillRect(RenderIn);
|
|
end;
|
|
|
|
procedure TVpMonthViewPainter.DrawBorders;
|
|
var
|
|
R: TRect;
|
|
begin
|
|
R := Rect(RealLeft, RealTop, RealRight - 1, RealBottom - 1);
|
|
if FMonthView.DrawingStyle = dsFlat then begin
|
|
{ draw a simple rectangular border }
|
|
DrawBevelRect(
|
|
RenderCanvas,
|
|
TPSRotateRectangle(Angle, RenderIn, R),
|
|
BevelShadow,
|
|
BevelShadow
|
|
);
|
|
end else
|
|
if FMonthView.DrawingStyle = ds3d then begin
|
|
{ draw a 3d bevel }
|
|
DrawBevelRect(
|
|
RenderCanvas,
|
|
TPSRotateRectangle(Angle, RenderIn, R),
|
|
BevelShadow,
|
|
BevelHighlight
|
|
);
|
|
InflateRect(R, -1, -1);
|
|
DrawBevelRect(
|
|
RenderCanvas,
|
|
TPSRotateRectangle(Angle, RenderIn, R),
|
|
BevelDarkShadow,
|
|
BevelFace
|
|
);
|
|
end;
|
|
end;
|
|
|
|
procedure TVpMonthViewPainter.DrawDayCell(ADate: TDate; ACol, ARow: Integer;
|
|
var AIndex, ADayNumber: Integer; var ATextRect: TRect);
|
|
var
|
|
tmpRect: TRect;
|
|
Y, M, D: Word;
|
|
Str: String;
|
|
todayDate: TDate;
|
|
fontStyle: TFontStyles;
|
|
textAdjust: Integer;
|
|
textHeight: Integer;
|
|
begin
|
|
todayDate := Date();
|
|
DecodeDate(ADate, Y, M, D);
|
|
|
|
if (ACol = 6) then begin
|
|
ATextRect.Right := ATextRect.Right + 8;
|
|
tmpRect := ATextRect;
|
|
if ATextRect.Bottom > RealBottom then
|
|
tmpRect.Bottom := RealBottom;
|
|
end else
|
|
tmpRect := ATextRect;
|
|
if ARow = 0 then
|
|
inc(tmpRect.Top);
|
|
|
|
if FCurrHoliday <> '' then begin
|
|
RenderCanvas.Brush.Color := FMonthView.HolidayAttributes.Color;
|
|
TPSFillRect(RenderCanvas, Angle, RenderIn, tmpRect);
|
|
end else if DisplayMonth <> M then begin
|
|
RenderCanvas.Brush.Color := RealOffDayColor;
|
|
TPSFillRect(RenderCanvas, Angle, RenderIn, tmpRect);
|
|
end else if DayOfWeek(ADate) in [1, 7] then begin
|
|
RenderCanvas.Brush.Color := FMonthView.WeekendAttributes.Color;
|
|
TPSFillRect(RenderCanvas, Angle, RenderIn, tmpRect);
|
|
end else
|
|
RenderCanvas.Brush.Color := RealColor;
|
|
|
|
if ACol = 6 then begin
|
|
{ draw bottom line }
|
|
TPSMoveTo(RenderCanvas, Angle, RenderIn, ATextRect.Left, ATextRect.Bottom);
|
|
TPSLineTo(RenderCanvas, Angle, RenderIn, RealRight - 2, ATextRect.Bottom);
|
|
end else begin
|
|
{ draw right side and bottom lines }
|
|
TPSMoveTo(RenderCanvas, Angle, RenderIn, ATextRect.Right, ATextRect.top);
|
|
if ATextRect.Bottom > RealBottom then begin
|
|
TPSLineTo(RenderCanvas, Angle, RenderIn, ATextRect.Right, RealBottom);
|
|
TPSLineTo(RenderCanvas, Angle, RenderIn, ATextRect.Left - 1, RealBottom);
|
|
end else begin
|
|
TPSLineTo(RenderCanvas, Angle, RenderIn, ATextRect.Right, ATextRect.Bottom);
|
|
TPSLineTo(RenderCanvas, Angle, RenderIn, ATextRect.Left - 1, ATextRect.Bottom);
|
|
end;
|
|
end;
|
|
|
|
{ Prepare the day number as string}
|
|
Str := FormatDateTime('d', ADate);
|
|
|
|
{ Set the proper font and style }
|
|
if ADate = todayDate then
|
|
RenderCanvas.Font.Assign(FMonthView.TodayAttributes.Font)
|
|
else
|
|
RenderCanvas.Font.Assign(FMonthView.DayNumberFont);
|
|
{$IF VP_LCL_SCALING = 0}
|
|
RenderCanvas.Font.Size := ScaleY(RenderCanvas.Font.Size, DesignTimeDPI);
|
|
{$ENDIF}
|
|
fontstyle := RenderCanvas.Font.style;
|
|
|
|
if (DisplayDate = ADate) then begin
|
|
if FMonthView.Focused then begin
|
|
if ACol = 6 then begin
|
|
tmpRect := ATextRect;
|
|
dec(tmpRect.Right, 4);
|
|
DrawFocusRect(tmpRect, true);
|
|
end else
|
|
DrawFocusRect(ATextRect);
|
|
end;
|
|
RenderCanvas.Font.Color := RealSelDayColor;
|
|
RenderCanvas.Font.Style := FMonthView.DayNumberFont.Style + [fsBold];
|
|
if (FMonthView.EventDayStyle <> []) and (FMonthView.Datastore <> nil) and
|
|
(FMonthView.DataStore.Resource <> nil) and
|
|
(FMonthView.DataStore.Resource.Schedule.EventCountByDay(ADate) > 0)
|
|
then
|
|
RenderCanvas.Font.Style := RenderCanvas.Font.Style + FMonthView.EventDayStyle;
|
|
end else begin
|
|
{ Set the font style for days which have events. }
|
|
if (FMonthView.EventDayStyle <> []) and (FMonthview.Datastore <> nil) and
|
|
(FMonthView.DataStore.Resource <> nil) and
|
|
(FMonthView.DataStore.Resource.Schedule.EventCountByDay(ADate) > 0)
|
|
then
|
|
RenderCanvas.Font.Style := RenderCanvas.Font.Style + FMonthView.EventDayStyle
|
|
else begin
|
|
RenderCanvas.Font.Color := EventFontColor;
|
|
RenderCanvas.Font.Style := FMonthView.DayNumberFont.Style;
|
|
end;
|
|
end;
|
|
|
|
FontStyle := RenderCanvas.Font.Style;
|
|
RenderCanvas.Font.Style := [fsBold, fsItalic];
|
|
textAdjust := RenderCanvas.TextWidth(Str);
|
|
textHeight := RenderCanvas.TextHeight(Str);
|
|
RenderCanvas.Font.Style := FontStyle;
|
|
if DisplayMonth <> M then
|
|
RenderCanvas.Font.Color := FMonthView.OffDayFontColor;
|
|
if FCurrHoliday <> '' then
|
|
RenderCanvas.Font.Assign(FMonthView.HolidayAttributes.Font);
|
|
|
|
{ Calculate size of rect for the day number at the top of the TextRect. }
|
|
if ACol = 6 then
|
|
tmpRect.Left := ATextRect.Left + mvColWidth - TextAdjust - TextMargin
|
|
else
|
|
tmpRect.Left := ATextRect.Right - TextAdjust - TextMargin;
|
|
if fsItalic in RenderCanvas.Font.Style then
|
|
dec(tmpRect.Left, 2);
|
|
tmpRect.Top := ATextRect.Top + TextMargin div 2;
|
|
tmpRect.Right := tmpRect.Left + textAdjust;
|
|
tmpRect.Bottom := tmpRect.Top + textHeight;
|
|
|
|
{ Highlight today by a border }
|
|
if ADate = todayDate then begin
|
|
InflateRect(tmpRect, 3, 3);
|
|
RenderCanvas.Pen.Assign(FMonthView.TodayAttributes.BorderPen);
|
|
RenderCanvas.Brush.Color := FMonthView.TodayAttributes.Color;
|
|
RenderCanvas.Brush.Style := bsSolid;
|
|
RenderCanvas.Rectangle(tmpRect);
|
|
InflateRect(tmpRect, -3, -3);
|
|
RenderCanvas.Font.Color := FMonthView.TodayAttributes.Font.Color;
|
|
end;
|
|
|
|
{ Write the day number at the top of the TextRect. }
|
|
TPSTextOut(RenderCanvas, Angle, RenderIn, tmpRect.Left, tmpRect.Top, Str);
|
|
|
|
{ Update MonthDayArray }
|
|
with TVpMonthViewOpener(FMonthView) do begin
|
|
mvMonthDayArray[AIndex].Rec := ATextRect;
|
|
mvMonthDayArray[AIndex].Date := ADate;
|
|
mvMonthDayArray[AIndex].OffDay := DisplayMonth <> M;
|
|
end;
|
|
Inc(ADayNumber);
|
|
Inc(AIndex);
|
|
|
|
if ACol = 6 then begin
|
|
{ drop rect down one row and all the way to the left }
|
|
ATextRect.TopLeft := Point(RealLeft + 1, ATextRect.Bottom + 1);
|
|
ATextRect.BottomRight := Point(ATextRect.Left + mvColWidth, ATextRect.Top + mvRowHeight);
|
|
end else begin
|
|
{ slide rect one column to the right }
|
|
ATextRect.Left := ATextRect.Right + 1;
|
|
ATextRect.Right := ATextRect.Right + mvColWidth;
|
|
end;
|
|
end;
|
|
|
|
procedure TVpMonthViewPainter.DrawDayHead;
|
|
var
|
|
dhRect, R: TRect;
|
|
P: TPoint;
|
|
I: Integer;
|
|
DayTAG: Integer;
|
|
Str: string;
|
|
StrLen: Integer;
|
|
begin
|
|
{ clear day head area }
|
|
RenderCanvas.Font.Assign(FMonthView.DayHeadAttributes.Font);
|
|
{$IF VP_LCL_SCALING = 0}
|
|
RenderCanvas.Font.Size := ScaleY(RenderCanvas.Font.Size, DesignTimeDPI);
|
|
{$ENDIF}
|
|
RenderCanvas.Brush.Color := DayHeadAttrColor;
|
|
|
|
{ build rect }
|
|
dhRect.Left := RealLeft;
|
|
dhRect.Top := RealTop + TVpMonthViewOpener(FMonthView).mvDayHeadHeight;
|
|
dhRect.Right := RealRight;
|
|
dhRect.Bottom := dhRect.Top + TVpMonthViewOpener(FMonthView).mvDayHeadHeight;
|
|
if FMonthView.DrawingStyle = ds3d then begin
|
|
inc(dhRect.Left, 2);
|
|
inc(dhRect.Top, 3);
|
|
dec(dhRect.Right, 3);
|
|
dhRect.Bottom := dhRect.Top + TVpMonthViewOpener(FMonthView).mvDayHeadHeight;
|
|
TPSFillRect(RenderCanvas, Angle, RenderIn, dhRect);
|
|
R := TPSRotateRectangle(Angle, RenderIn, dhRect);
|
|
DrawBevelRect(RenderCanvas, R, BevelHighlight, BevelDarkShadow);
|
|
end else
|
|
if FMonthView.DrawingStyle = dsFlat then begin
|
|
dhRect.Left := RealLeft;
|
|
dhRect.Top := RealTop + TVpMonthViewOpener(FMonthView).mvDayHeadHeight;
|
|
dhRect.Right := RealRight;
|
|
dhRect.Bottom := dhRect.Top + TVpMonthViewOpener(FMonthView).mvDayHeadHeight;
|
|
TPSFillRect(RenderCanvas, Angle, RenderIn, dhRect);
|
|
R := TPSRotateRectangle(Angle, RenderIn, dhRect);
|
|
DrawBevelRect(RenderCanvas, R, BevelShadow, BevelShadow);
|
|
end else
|
|
begin
|
|
dhRect.Left := RealLeft;
|
|
TPSFillRect(RenderCanvas, Angle, RenderIn, dhRect);
|
|
end;
|
|
|
|
DayTAG := Ord(FMonthView.WeekStartsOn);
|
|
dhRect.Right := dhRect.Left + mvColWidth;
|
|
|
|
for I := 0 to 6 do begin
|
|
{ draw the little vertical lines between each day }
|
|
if I < 6 then begin
|
|
if FMonthView.DrawingStyle = ds3d then
|
|
begin
|
|
R := Rect(dhRect.Right-1, dhRect.Top + 3, dhRect.Right, dhRect.Bottom - 3);
|
|
R := TPSRotateRectangle(Angle, RenderIn, R);
|
|
DrawBevelRect(RenderCanvas, TPSRotateRectangle(Angle, RenderIn, R), BevelShadow, BevelHighlight);
|
|
end else
|
|
begin
|
|
TPSMoveTo(RenderCanvas, Angle, RenderIn, dhRect.Right + 1, dhRect.Top + 4);
|
|
TPSLineTo(RenderCanvas, Angle, RenderIn, dhRect.Right + 1, dhRect.Bottom - 3);
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF LCL}
|
|
case FMonthView.DayNameStyle of
|
|
dsLong : { Draw each day's full caption... }
|
|
str := FormatSettings.LongDayNames[DayTAG+1];
|
|
dsShort: { Draw each day's abbreviated caption... }
|
|
str := FormatSettings.ShortDayNames[DayTAG+1];
|
|
dsLetter: { Draw each day's first letter only }
|
|
str := FormatSettings.ShortDayNames[DayTAG+1, 1];
|
|
end;
|
|
{$ELSE}
|
|
case FMontheView.DayNameStyle of
|
|
dsLong: { Draw each day's full caption... }
|
|
case DayTAG of
|
|
0: str := RSSunday;
|
|
1: str := RSMonday;
|
|
2: str := RSTuesday;
|
|
3: str := RSWednesday;
|
|
4: str := RSThursday;
|
|
5: str := RSFriday;
|
|
6: str := RSSaturday;
|
|
end
|
|
dsShort: { Draw each day's abbreviated caption... }
|
|
case DayTAG of
|
|
0: str := RSASunday;
|
|
1: str := RSAMonday;
|
|
2: str := RSATuesday;
|
|
3: str := RSAWednesday;
|
|
4: str := RSAThursday;
|
|
5: str := RSAFriday;
|
|
6: str := RSASaturday;
|
|
end
|
|
dsLetter: { Draw each day's first letter only }
|
|
case DayTAG of
|
|
0: str := RSLSunday;
|
|
1: str := RSLMonday;
|
|
2: str := RSLTuesday;
|
|
3: str := RSLWednesday;
|
|
4: str := RSLThursday;
|
|
5: str := RSLFriday;
|
|
6: str := RSLSaturday;
|
|
end;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
{ Fix header string }
|
|
StrLen := RenderCanvas.TextWidth(Str);
|
|
if (StrLen > mvColWidth - TextMargin * 2) then
|
|
Str := GetDisplayString(RenderCanvas, Str, 0, mvColWidth - TextMargin * 2);
|
|
StrLen := RenderCanvas.TextWidth(Str);
|
|
|
|
{ Draw header text }
|
|
P := Point((dhRect.Left + dhRect.Right - StrLen) div 2, dhRect.Top + TextMargin - 1);
|
|
TPSTextOut(RenderCanvas, Angle, RenderIn, P.X, P.Y, Str);
|
|
|
|
DayTAG := (DayTAG + 1) mod 7;
|
|
|
|
dhRect.Left := dhRect.Right;
|
|
dhRect.Right := dhRect.Left + mvColWidth;
|
|
end; // for I ...
|
|
end;
|
|
|
|
procedure TVpMonthViewPainter.DrawDays;
|
|
var
|
|
TextRect: TRect;
|
|
Col, Row: Integer;
|
|
DayNumber: Integer;
|
|
M, D, Y: Word;
|
|
MonthStartsOn: Integer;
|
|
DayTag: Integer;
|
|
DayOffset: Integer;
|
|
StartingDate: TDateTime;
|
|
ThisDate: TDateTime;
|
|
I: Integer;
|
|
Drawn: Boolean;
|
|
OldBrush: TBrush;
|
|
OldPen: TPen;
|
|
OldFont: TFont;
|
|
hDayHead: Integer;
|
|
begin
|
|
{ initialize the MonthDayArray }
|
|
with TVpMonthViewOpener(FMonthView) do begin
|
|
for I := 0 to Pred(Length(mvMonthDayArray)) do begin
|
|
mvMonthDayArray[I].Rec := Rect(-1, -1, -1, -1);
|
|
mvMonthDayArray[I].Date := 0.0;
|
|
end;
|
|
hDayHead := mvDayHeadHeight;
|
|
end;
|
|
|
|
RenderCanvas.Pen.Color := RealLineColor;
|
|
RenderCanvas.Brush.Color := RealColor;
|
|
|
|
if FMonthView.DrawingStyle = ds3d then
|
|
begin
|
|
mvRowHeight := (RealHeight - hDayHead * 2 - 4) div 6;
|
|
TextRect.TopLeft := Point(RealLeft + 1, RealTop + hDayHead * 2 + 4);
|
|
end else
|
|
begin
|
|
mvRowHeight := (RealHeight - hDayHead * 2) div 6;
|
|
TextRect.TopLeft := Point(RealLeft + 1, RealTop + hDayHead * 2);
|
|
end;
|
|
TextRect.BottomRight := Point(TextRect.Left + mvColWidth, TextRect.Top + mvRowHeight);
|
|
|
|
{ Determine the starting date and offset }
|
|
DecodeDate(DisplayDate, Y, DisplayMonth, D);
|
|
StartingDate := EncodeDate(Y, DisplayMonth, 1);
|
|
MonthStartsOn := DayOfWeek(StartingDate);
|
|
DayTag := Ord(FMonthView.WeekStartsOn);
|
|
DayOffset := DayTag - MonthStartsOn;
|
|
if DayOffset = 0 then
|
|
DayOffset := -7;
|
|
|
|
I := 0;
|
|
DayNumber := DayOffset + 1;
|
|
|
|
// iterate through each column row by row, drawing each day in numerical order.
|
|
OldBrush := TBrush.Create;
|
|
try
|
|
OldPen := TPen.Create;
|
|
try
|
|
OldFont := TFont.Create;
|
|
try
|
|
for Row := 0 to 5 do begin
|
|
for Col := 0 to 6 do begin
|
|
ThisDate := Trunc(StartingDate + DayNumber);
|
|
|
|
{ Check and store if the this date is a holiday }
|
|
FMonthView.IsHoliday(ThisDate, FCurrHoliday);
|
|
|
|
OldBrush.Assign(RenderCanvas.Brush);
|
|
OldPen.Assign(RenderCanvas.Pen);
|
|
OldFont.Assign(RenderCanvas.Font);
|
|
try
|
|
{ Allow the user to draw the day }
|
|
if Assigned(FMonthView.OwnerDrawCells) then begin
|
|
Drawn := false;
|
|
DecodeDate(ThisDate, Y,M,D);
|
|
FMonthView.OwnerDrawCells(self, RenderCanvas, TextRect, D, Drawn);
|
|
if Drawn then
|
|
Continue;
|
|
end else
|
|
DrawDayCell(ThisDate, Col, Row, I, DayNumber, TextRect);
|
|
finally
|
|
RenderCanvas.Brush.Assign(OldBrush);
|
|
RenderCanvas.Pen.Assign(OldPen);
|
|
RenderCanvas.Font.Assign(OldFont);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
finally
|
|
OldFont.Free;
|
|
end;
|
|
finally
|
|
OldPen.Free;
|
|
end;
|
|
finally
|
|
OldBrush.Free;
|
|
end;
|
|
|
|
DrawEvents;
|
|
end;
|
|
|
|
procedure TVpMonthViewPainter.DrawEvents;
|
|
var
|
|
I, J: Integer;
|
|
EventList: TList;
|
|
dayRect: TRect;
|
|
TextRect: TRect;
|
|
Str: String;
|
|
StrLen: Integer;
|
|
P: TPoint;
|
|
visibleEvents: Integer;
|
|
begin
|
|
RenderCanvas.Pen.Color := RealLineColor;
|
|
RenderCanvas.Pen.Style := psSolid;
|
|
RenderCanvas.Brush.Color := RealColor;
|
|
|
|
{ write the events }
|
|
if (FMonthView.DataStore <> nil) and FMonthView.ShowEvents and
|
|
(FMonthView.DataStore.Resource <> nil) and
|
|
(FMonthView.DataStore.Resource.Schedule.EventCount <> 0)
|
|
then begin
|
|
visibleEvents := 0;
|
|
EventList := TList.Create;
|
|
try
|
|
for I := 0 to 43 do begin
|
|
EventList.Clear;
|
|
FMonthView.DataStore.Resource.Schedule.EventsByDate(TVpMonthViewOpener(FMonthView).mvMonthDayArray[I].Date, EventList);
|
|
if EventList.Count > 0 then begin
|
|
{ there are events scheduled for this day }
|
|
|
|
dayRect := TVpMonthViewOpener(FMonthView).mvMonthDayArray[I].Rec;
|
|
|
|
{ initialize TextRect for this day }
|
|
TextRect.TopLeft := Point(dayRect.Left, dayRect.Top);
|
|
TextRect.BottomRight := Point(
|
|
TextRect.Left + mvColWidth,
|
|
TextRect.Top + mvEventTextHeight + TextMargin div 2
|
|
);
|
|
|
|
{ set canvas color }
|
|
if TVpMonthViewOpener(FMonthView).mvMonthDayArray[I].OffDay
|
|
then RenderCanvas.Brush.Color := RealOffDayColor
|
|
else RenderCanvas.Brush.Color := RealColor;
|
|
|
|
{ spin through the events and paint them }
|
|
for J := 0 to Pred(EventList.Count) do begin
|
|
if (TextRect.Bottom > dayRect.Bottom) and (J <= Pred(EventList.Count)) then
|
|
begin
|
|
{ draw a little red square with a (...) at the bottom right }
|
|
{ corner of the day to indicate that there are more events }
|
|
{ than can be listed in the available space. }
|
|
DrawDotDotDot(dayRect, DotDotDotColor);
|
|
Break;
|
|
end;
|
|
|
|
{ shorten events that are next to the day number, in order }
|
|
{ to give the day number enough room }
|
|
if (TextRect.Top < dayRect.Top + mvDayNumberHeight + TextMargin div 2)
|
|
then
|
|
TextRect.Right := TextRect.Left + mvColWidth - mvDayNumberHeight - TextMargin
|
|
else
|
|
TextRect.Right := TextRect.Left + mvColWidth;
|
|
|
|
{ Construct the display text }
|
|
Str := FMonthView.BuildEventString(TVpEvent(EventList[j]), FMonthView.ShowEventTime, true);
|
|
|
|
{ set the event font }
|
|
RenderCanvas.Font.Assign(FMonthView.EventFont);
|
|
{$IF VP_LCL_SCALING = 0}
|
|
RenderCanvas.Font.Size := ScaleY(RenderCanvas.Font.Size, DesignTimeDPI);
|
|
{$ENDIF}
|
|
if TVpMonthViewOpener(FMonthView).mvMonthDayArray[I].OffDay then
|
|
RenderCanvas.Font.Color := FMonthView.OffDayFontColor;
|
|
|
|
StrLen := RenderCanvas.TextWidth(Str);
|
|
if StrLen > WidthOf(TextRect) - TextMargin * 2 then
|
|
Str := GetDisplayString(RenderCanvas, Str, 0, WidthOf(TextRect) - TextMargin * 2);
|
|
|
|
{ write the event text }
|
|
P := Point(TextRect.Left + TextMargin div 2, TextRect.Top + TextMargin div 2);
|
|
TPSTextOut(RenderCanvas, Angle, RenderIn, P.X, P.Y, Str);
|
|
|
|
{ Store TextRect and Event in EventArray }
|
|
with TVpMonthViewOpener(FMonthView) do begin
|
|
Inc(visibleEvents);
|
|
mvEventArray[visibleEvents - 1].Rec := TextRect;
|
|
mvEventArray[visibleEvents - 1].Event := TVpEvent(EventList.List^[j]);
|
|
end;
|
|
|
|
{ Move TextRect down one line for the next item... }
|
|
TextRect.Top := TextRect.Bottom + 1;
|
|
TextRect.Bottom := TextRect.Top + mvLineHeight;
|
|
end;
|
|
end;
|
|
end;
|
|
finally
|
|
EventList.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TVpMonthViewPainter.DrawFocusRect(ARect: TRect; FixRight: Boolean = false);
|
|
var
|
|
tmpRect: TRect;
|
|
begin
|
|
tmpRect := ARect;
|
|
InflateRect(tmpRect, 2, 2);
|
|
TPSDrawFocusRect(RenderCanvas, Angle, RenderIn, tmpRect);
|
|
|
|
tmpRect := ARect;
|
|
InflateRect(tmpRect, -2, -2);
|
|
if FixRight then
|
|
inc(tmpRect.Right);
|
|
TPSDrawFocusRect(RenderCanvas, Angle, RenderIn, tmpRect);
|
|
end;
|
|
|
|
procedure TVpMonthViewPainter.DrawHeader;
|
|
var
|
|
HeadRect: TRect;
|
|
HeadTextRect: TRect;
|
|
HeadStr: string;
|
|
HeadStrLen : Integer;
|
|
dayHeadHeight: Integer;
|
|
R: TRect;
|
|
begin
|
|
RenderCanvas.Brush.Color := HeadAttrColor;
|
|
dayHeadHeight := TVpMonthViewOpener(FMonthView).mvDayHeadHeight;
|
|
|
|
HeadRect := Rect(RealLeft, RealTop, RealRight, RealTop + dayHeadHeight);
|
|
|
|
{ Draw the header cell and borders }
|
|
if FMonthView.DrawingStyle = dsFlat then begin
|
|
// draw a flat rectanbular border
|
|
TPSFillRect(RenderCanvas, Angle, RenderIn, HeadRect);
|
|
R := TPSRotateRectangle(Angle, RenderIn, HeadRect);
|
|
DrawBevelRect(RenderCanvas, R, BevelShadow, BevelShadow);
|
|
end else
|
|
if FMonthView.DrawingStyle = ds3d then begin
|
|
// draw a 3d bevel
|
|
InflateRect(HeadRect, -2, -2);
|
|
dec(HeadRect.Right);
|
|
HeadRect.Bottom := HeadRect.Top + dayHeadHeight;
|
|
TPSFillRect(RenderCanvas, Angle, RenderIn, HeadRect);
|
|
R := TPSRotateRectangle(Angle, RenderIn, HeadRect);
|
|
DrawBevelRect(RenderCanvas, R, BevelHighlight, BevelDarkShadow);
|
|
end else
|
|
TPSFillRect(RenderCanvas, Angle, RenderIn, HeadRect);
|
|
|
|
{ Position the spinner }
|
|
with TVpMonthViewOpener(FMonthView) do begin
|
|
mvSpinButtons.Height := dayHeadHeight - 3;
|
|
mvSpinButtons.Width := mvSpinButtons.Height * 2;
|
|
mvSpinButtons.Left := TextMargin;
|
|
mvSpinButtons.Top := HeadRect.Top + (dayHeadHeight - mvSpinButtons.Height) div 2 + 1;
|
|
end;
|
|
|
|
{ Acquire startdate and end date }
|
|
HeadStr := FormatDateTime(FMonthView.DateLabelFormat, DisplayDate);
|
|
{$IFDEF FPC}{$IF FPC_FULLVERSION < 30000}
|
|
HeadStr := SysToUTF8(HeadStr);
|
|
{$ENDIF}{$ENDIF}
|
|
|
|
{ Calculate the text rectangle }
|
|
RenderCanvas.Font.Assign(FMonthView.HeadAttributes.Font);
|
|
{$IF VP_LCL_SCALING = 0}
|
|
RenderCanvas.Font.Size := ScaleY(RenderCanvas.Font.Size, DesignTimeDPI);
|
|
{$ENDIF}
|
|
if DisplayOnly and (RenderCanvas.TextWidth(HeadStr) >= RealWidth) then
|
|
HeadTextRect.Left:= RealLeft + TextMargin * 2
|
|
else
|
|
if DisplayOnly then
|
|
HeadTextRect.Left := RealLeft + (RealWidth - RenderCanvas.TextWidth(HeadStr)) div 2
|
|
else
|
|
HeadTextRect.Left := RealLeft + 30 + TextMargin * 2;
|
|
HeadTextRect.Top := (HeadRect.Top + HeadRect.Bottom - RenderCanvas.TextHeight('Tg')) div 2;
|
|
HeadTextRect.BottomRight := HeadRect.BottomRight;
|
|
|
|
{ Fix Header String }
|
|
HeadStrLen := RenderCanvas.TextWidth(HeadStr);
|
|
|
|
if HeadStrLen > HeadTextRect.Right - HeadTextRect.Left then begin
|
|
HeadStr := GetDisplayString(
|
|
RenderCanvas,
|
|
HeadStr,
|
|
0,
|
|
HeadTextRect.Right - HeadTextRect.Left - TextMargin
|
|
);
|
|
end;
|
|
|
|
// Draw the text
|
|
RenderCanvas.Font.Assign(FMonthView.HeadAttributes.Font);
|
|
{$IF VP_LCL_SCALING = 0}
|
|
RenderCanvas.Font.Size := ScaleY(RenderCanvas.Font.Size, DesignTimeDPI);
|
|
{$ENDIF}
|
|
TPSTextOut(
|
|
RenderCanvas,
|
|
Angle,
|
|
RenderIn,
|
|
RealLeft + TVpMonthViewOpener(FMonthView).mvSpinButtons.Width + TextMargin * 2,
|
|
HeadTextRect.Top, // this vertical position is already centered
|
|
HeadStr
|
|
);
|
|
end;
|
|
|
|
procedure TVpMonthViewPainter.FixFontHeights;
|
|
begin
|
|
with FMonthView do begin
|
|
HeadAttributes.Font.Height := GetRealFontHeight(HeadAttributes.Font);
|
|
DayHeadAttributes.Font.Height := GetRealFontHeight(DayHeadAttributes.Font);
|
|
DayNumberFont.Height := GetRealFontHeight(DayNumberFont);
|
|
EventFont.Height := GetRealFontHeight(EventFont);
|
|
Font.Height := GetRealFontHeight(Font);
|
|
end;
|
|
end;
|
|
|
|
procedure TVpMonthViewPainter.InitColors;
|
|
begin
|
|
if DisplayOnly then begin
|
|
BevelHighlight := clBlack;
|
|
BevelShadow := clBlack;
|
|
BevelDarkShadow := clBlack;
|
|
BevelFace := clBlack;
|
|
RealColor := clWhite;
|
|
DayHeadAttrColor := clSilver;
|
|
HeadAttrColor := clSilver;
|
|
RealLineColor := clBlack;
|
|
RealOffDayColor := clSilver;
|
|
RealSelDayColor := clWhite;
|
|
EventFontColor := clBlack;
|
|
TodayFontColor := clBlack;
|
|
TodayAttrColor := clWhite;
|
|
end else begin
|
|
BevelHighlight := clBtnHighlight;
|
|
BevelShadow := clBtnShadow;
|
|
BevelDarkShadow := cl3DDkShadow;
|
|
BevelFace := clBtnFace;
|
|
RealColor := FMonthView.Color;
|
|
HeadAttrColor := FMonthView.HeadAttributes.Color;
|
|
DayHeadAttrColor := FMonthView.DayHeadAttributes.Color;
|
|
RealLineColor := FMonthView.LineColor;
|
|
RealOffDayColor := FMonthView.OffDayColor;
|
|
RealSelDayColor := FMonthView.SelectedDayColor;
|
|
EventFontColor := FMonthView.DayNumberFont.Color;
|
|
TodayFontColor := FMonthView.TodayAttributes.Font.Color;
|
|
TodayAttrColor := FMonthView.TodayAttributes.Color;
|
|
end;
|
|
DotDotDotColor := clBlack;
|
|
end;
|
|
|
|
procedure TVpMonthViewPainter.RenderToCanvas(ARenderIn: TRect;
|
|
AAngle: TVpRotationAngle; AScale: Extended; ARenderDate: TDateTime;
|
|
AStartLine, AStopLine: Integer; AUseGran: TVpGranularity; ADisplayOnly: Boolean);
|
|
begin
|
|
inherited;
|
|
|
|
InitColors;
|
|
SavePenBrush;
|
|
InitPenBrush;
|
|
if ADisplayOnly then
|
|
FixFontHeights;
|
|
|
|
Rgn := CreateRectRgn(RenderIn.Left, RenderIn.Top, RenderIn.Right, RenderIn.Bottom);
|
|
try
|
|
SelectClipRgn(RenderCanvas.Handle, Rgn);
|
|
|
|
{ clear client area }
|
|
Clear;
|
|
|
|
{ measure the row heights }
|
|
SetMeasurements;
|
|
|
|
{ draw headers }
|
|
DrawHeader;
|
|
DrawDayHead;
|
|
|
|
{ draw days }
|
|
DrawDays;
|
|
|
|
{ draw the borders }
|
|
DrawBorders;
|
|
|
|
finally
|
|
SelectClipRgn(RenderCanvas.Handle, 0);
|
|
DeleteObject(Rgn);
|
|
end;
|
|
|
|
{ reinstate canvas settings}
|
|
RestorePenBrush;
|
|
end;
|
|
|
|
procedure TVpMonthViewPainter.SetMeasurements;
|
|
begin
|
|
inherited;
|
|
|
|
DisplayDate := IfThen(RenderDate = 0, Date, RenderDate);
|
|
|
|
{ we use the VpProductName because is is a good representation of some }
|
|
{ generic text }
|
|
RenderCanvas.Font.Assign(FMonthView.DayHeadAttributes.Font);
|
|
{$IF VP_LCL_SCALING = 0}
|
|
RenderCanvas.Font.Size := ScaleY(RenderCanvas.Font.Size, DesignTimeDPI);
|
|
{$ENDIF}
|
|
with TVpMonthViewOpener(FMonthView) do
|
|
mvDayHeadHeight := RenderCanvas.TextHeight(VpProductName) + TextMargin + 2;
|
|
|
|
RenderCanvas.Font.Assign(FMonthView.DayNumberFont);
|
|
{$IF VP_LCL_SCALING = 0}
|
|
RenderCanvas.Font.Size := ScaleY(RenderCanvas.Font.Size, DesignTimeDPI);
|
|
{$ENDIF}
|
|
mvDayNumberHeight := RenderCanvas.TextHeight('00');
|
|
|
|
RenderCanvas.Font.Assign(FMonthView.EventFont);
|
|
{$IF VP_LCL_SCALING = 0}
|
|
RenderCanvas.Font.Size := ScaleY(RenderCanvas.Font.Size, DesignTimeDPI);
|
|
{$ENDIF}
|
|
mvEventTextHeight := RenderCanvas.TextHeight(VpProductName);
|
|
|
|
RenderCanvas.Font.Assign(FMonthView.Font);
|
|
{$IF VP_LCL_SCALING = 0}
|
|
RenderCanvas.Font.Size := ScaleY(RenderCanvas.Font.Size, DesignTimeDPI);
|
|
{$ENDIF}
|
|
mvLineHeight := RenderCanvas.TextHeight(VpProductName) + 2;
|
|
mvColWidth := (RealWidth - 4) div 7;
|
|
end;
|
|
|
|
end.
|