You've already forked lazarus-ccr
tvplanit: Support recurring events in GanttView.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@8543 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -63,6 +63,7 @@ const
|
|||||||
|
|
||||||
NO_DATE = 9999999;
|
NO_DATE = 9999999;
|
||||||
FOREVER_DATE = 999999;
|
FOREVER_DATE = 999999;
|
||||||
|
|
||||||
SecondsInDay = 86400; { Number of seconds in a day }
|
SecondsInDay = 86400; { Number of seconds in a day }
|
||||||
SecondsInHour = 3600; { Number of seconds in an hour }
|
SecondsInHour = 3600; { Number of seconds in an hour }
|
||||||
SecondsInMinute = 60; { Number of seconds in a minute }
|
SecondsInMinute = 60; { Number of seconds in a minute }
|
||||||
@ -72,6 +73,8 @@ const
|
|||||||
OneSecond = 1.0 / SecondsInDay;
|
OneSecond = 1.0 / SecondsInDay;
|
||||||
OneMinute = 1.0 / MinutesInDay;
|
OneMinute = 1.0 / MinutesInDay;
|
||||||
OneHour = 1.0 / HoursInDay;
|
OneHour = 1.0 / HoursInDay;
|
||||||
|
TIME_EPS = 0.1 * OneSecond; // Epsilon for comparing times
|
||||||
|
|
||||||
MaxDateLen = 40; { maximum length of date picture strings }
|
MaxDateLen = 40; { maximum length of date picture strings }
|
||||||
MaxMonthName = 15; { maximum length for month names }
|
MaxMonthName = 15; { maximum length for month names }
|
||||||
MaxDayName = 15; { maximum length for day names }
|
MaxDayName = 15; { maximum length for day names }
|
||||||
|
@ -729,9 +729,6 @@ uses
|
|||||||
VpException, VpConst, VpMisc, VpBaseDS,
|
VpException, VpConst, VpMisc, VpBaseDS,
|
||||||
VpImportPreview_ICalEvent, VpImportPreview_ICalTask, VpImportPreview_VCard;
|
VpImportPreview_ICalEvent, VpImportPreview_ICalTask, VpImportPreview_VCard;
|
||||||
|
|
||||||
const
|
|
||||||
TIME_EPS = 1.0 / SecondsInDay; // Epsilon for comparing times
|
|
||||||
|
|
||||||
{ Compare function for sorting resources: Compares the resource descriptions }
|
{ Compare function for sorting resources: Compares the resource descriptions }
|
||||||
function CompareResources(Item1, Item2: Pointer): Integer;
|
function CompareResources(Item1, Item2: Pointer): Integer;
|
||||||
begin
|
begin
|
||||||
|
@ -28,9 +28,28 @@ type
|
|||||||
TVpGanttEventRec = record
|
TVpGanttEventRec = record
|
||||||
Event: TVpEvent;
|
Event: TVpEvent;
|
||||||
Caption: String;
|
Caption: String;
|
||||||
|
StartTime, EndTime: TDateTime;
|
||||||
HeadRect: TRect;
|
HeadRect: TRect;
|
||||||
EventRect: TRect;
|
EventRect: TRect;
|
||||||
end;
|
end;
|
||||||
|
PVpGanttEventRec = ^TVpGanttEventRec;
|
||||||
|
|
||||||
|
TVpGanttEventList = class(TFPList)
|
||||||
|
private
|
||||||
|
FStartDate, FEndDate: TDateTime;
|
||||||
|
function GetItem(AIndex: Integer): PVpGanttEventRec;
|
||||||
|
procedure SetItem(AIndex: Integer; AItem: PVpGanttEventRec);
|
||||||
|
protected
|
||||||
|
procedure ClipDates(AEventRec: PVpGanttEventRec);
|
||||||
|
public
|
||||||
|
constructor Create(AStartDate, AEndDate: TDateTime);
|
||||||
|
destructor Destroy; override;
|
||||||
|
function AddSingleEvent(AEvent: TVpEvent): PVpGanttEventRec;
|
||||||
|
procedure AddRecurringEvents(AEvent: TVpEvent);
|
||||||
|
procedure Clear;
|
||||||
|
procedure Delete(AIndex: Integer);
|
||||||
|
property Items[AIndex: Integer]: PVpGanttEventRec read GetItem write SetItem; default;
|
||||||
|
end;
|
||||||
|
|
||||||
TVpGanttDayRec = record
|
TVpGanttDayRec = record
|
||||||
Date: TDateTime;
|
Date: TDateTime;
|
||||||
@ -160,7 +179,7 @@ type
|
|||||||
|
|
||||||
function GetDateFormat(AIndex: Integer): String;
|
function GetDateFormat(AIndex: Integer): String;
|
||||||
function GetDayRec(AIndex: Integer): TVpGanttDayRec;
|
function GetDayRec(AIndex: Integer): TVpGanttDayRec;
|
||||||
function GetEventRec(AIndex: Integer): TVpGanttEventRec;
|
function GetEventRec(AIndex: Integer): PVpGanttEventRec;
|
||||||
function GetMonthRec(AIndex: Integer): TVpGanttMonthRec;
|
function GetMonthRec(AIndex: Integer): TVpGanttMonthRec;
|
||||||
function GetNumDays: Integer;
|
function GetNumDays: Integer;
|
||||||
function GetNumEvents: Integer;
|
function GetNumEvents: Integer;
|
||||||
@ -191,7 +210,7 @@ type
|
|||||||
|
|
||||||
protected
|
protected
|
||||||
// Needed by the painter
|
// Needed by the painter
|
||||||
FEventRecords: array of TVpGanttEventRec;
|
FEventRecords: TVpGanttEventList;
|
||||||
FDayRecords: array of TVpGanttDayRec;
|
FDayRecords: array of TVpGanttDayRec;
|
||||||
FWeekRecords: array of TVpGanttWeekRec;
|
FWeekRecords: array of TVpGanttWeekRec;
|
||||||
FMonthRecords: array of TVpGanttMonthRec;
|
FMonthRecords: array of TVpGanttMonthRec;
|
||||||
@ -315,7 +334,7 @@ type
|
|||||||
property TotalColHeaderHeight: Integer read FTotalColHeaderHeight;
|
property TotalColHeaderHeight: Integer read FTotalColHeaderHeight;
|
||||||
|
|
||||||
property DayRecords[AIndex: Integer]: TVpGanttDayRec read GetDayRec;
|
property DayRecords[AIndex: Integer]: TVpGanttDayRec read GetDayRec;
|
||||||
property EventRecords[AIndex: Integer]: TVpGanttEventRec read GetEventRec;
|
property EventRecords[AIndex: Integer]: PVpGanttEventRec read GetEventRec;
|
||||||
property MonthRecords[AIndex: Integer]: TVpGanttMonthRec read GetMonthRec;
|
property MonthRecords[AIndex: Integer]: TVpGanttMonthRec read GetMonthRec;
|
||||||
property WeekRecords[AIndex: Integer]: TVpGanttWeekRec read GetWeekRec;
|
property WeekRecords[AIndex: Integer]: TVpGanttWeekRec read GetWeekRec;
|
||||||
|
|
||||||
@ -372,6 +391,178 @@ const
|
|||||||
DEFAULT_MONTHFORMAT_SHORT = 'mmm yyyy';
|
DEFAULT_MONTHFORMAT_SHORT = 'mmm yyyy';
|
||||||
DEFAULT_COLWIDTH = 20;
|
DEFAULT_COLWIDTH = 20;
|
||||||
|
|
||||||
|
{ Compare function for sorting event records: Compares the start times of two events.
|
||||||
|
If the times are equal (within 1 seconds) then end times are compared.
|
||||||
|
The function is used by TVpGanttEventList.Sort. }
|
||||||
|
function CompareEventRecs(Item1, Item2: Pointer): Integer;
|
||||||
|
var
|
||||||
|
eventRec1, eventRec2: PVpGanttEventRec;
|
||||||
|
begin
|
||||||
|
eventRec1 := PVpGanttEventRec(Item1);
|
||||||
|
eventRec2 := PVpGanttEventRec(Item2);
|
||||||
|
if SameValue(eventRec1^.StartTime, eventRec2^.StartTime, TIME_EPS) then
|
||||||
|
Result := CompareValue(eventRec1^.EndTime, eventRec2^.EndTime)
|
||||||
|
else
|
||||||
|
Result := CompareValue(eventRec1^.StartTime, eventRec2^.StartTime);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{******************************************************************************}
|
||||||
|
{ TVpGanttEventList }
|
||||||
|
{******************************************************************************}
|
||||||
|
constructor TVpGanttEventList.Create(AStartDate, AEndDate: TDateTime);
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
FStartDate := AStartDate;
|
||||||
|
FEndDate := AEndDate;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TVpGanttEventList.Destroy;
|
||||||
|
begin
|
||||||
|
Clear;
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TVpGanttEventList.AddRecurringEvents(AEvent: TVpEvent);
|
||||||
|
var
|
||||||
|
eventRec: PVpGanttEventRec;
|
||||||
|
dt1, dt2: TDateTime;
|
||||||
|
begin
|
||||||
|
if AEvent.AllDayEvent then
|
||||||
|
begin
|
||||||
|
dt1 := DatePart(AEvent.StartTime);
|
||||||
|
dt2 := DatePart(AEvent.EndTime) + 1;
|
||||||
|
if frac(AEvent.EndTime) = 0 then dt2 := dt2 + 1;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
dt1 := AEvent.StartTime;
|
||||||
|
dt2 := AEvent.EndTime;
|
||||||
|
end;
|
||||||
|
|
||||||
|
while (DatePart(dt2) >= FStartDate) or (DatePart(dt1) <= FEndDate) do
|
||||||
|
begin
|
||||||
|
eventRec := AddSingleEvent(AEvent);
|
||||||
|
eventRec^.StartTime := dt1;
|
||||||
|
eventRec^.EndTime := dt2;
|
||||||
|
ClipDates(eventRec);
|
||||||
|
|
||||||
|
// Find date/times of next recurrance.
|
||||||
|
case AEvent.RepeatCode of
|
||||||
|
rtDaily:
|
||||||
|
begin
|
||||||
|
dt1 := dt1 + 1;
|
||||||
|
dt2 := dt2 + 1;
|
||||||
|
end;
|
||||||
|
rtWeekly:
|
||||||
|
begin
|
||||||
|
dt1 := dt1 + 7;
|
||||||
|
dt2 := dt2 + 7;
|
||||||
|
end;
|
||||||
|
rtMonthlyByDay:
|
||||||
|
begin
|
||||||
|
// wp: to do... What does it mean?
|
||||||
|
end;
|
||||||
|
rtMonthlyByDate:
|
||||||
|
begin
|
||||||
|
dt1 := IncMonth(dt1, 1);
|
||||||
|
dt2 := IncMonth(dt2, 1);
|
||||||
|
end;
|
||||||
|
rtYearlyByDay:
|
||||||
|
begin
|
||||||
|
// wp: to do... What does it mean?
|
||||||
|
end;
|
||||||
|
rtYearlyByDate:
|
||||||
|
begin
|
||||||
|
dt1 := IncYear(dt1, 1);
|
||||||
|
dt2 := IncYear(dt2, 1);
|
||||||
|
end;
|
||||||
|
rtCustom:
|
||||||
|
begin
|
||||||
|
dt1 := dt1 + AEvent.CustomInterval;
|
||||||
|
dt2 := dt2 + AEvent.CustomInterval;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if dt2 >= AEvent.RepeatRangeEnd then
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TVpGanttEventList.AddSingleEvent(AEvent: TVpEvent): PVpGanttEventRec;
|
||||||
|
var
|
||||||
|
eventRec: PVpGanttEventRec;
|
||||||
|
dt1, dt2: TDateTime;
|
||||||
|
begin
|
||||||
|
// Handle the start/end times of all-day events correctly.
|
||||||
|
if AEvent.AllDayEvent then
|
||||||
|
begin
|
||||||
|
dt1 := DatePart(AEvent.StartTime);
|
||||||
|
dt2 := DatePart(AEvent.EndTime) + 1;
|
||||||
|
if frac(AEvent.EndTime) = 0 then dt2 := dt2 + 1;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
dt1 := AEvent.StartTime;
|
||||||
|
dt2 := AEvent.EndTime;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Populate the event record
|
||||||
|
New(eventRec);
|
||||||
|
eventRec^ := Default(TVpGanttEventRec);
|
||||||
|
eventRec^.Event := AEvent;
|
||||||
|
eventRec^.Caption := AEvent.Description;
|
||||||
|
eventRec^.StartTime := dt1;
|
||||||
|
eventRec^.EndTime := dt2;
|
||||||
|
eventRec^.HeadRect := Rect(-1, -1, -1, -1);
|
||||||
|
eventRec^.EventRect := Rect(-1, -1, -1, -1);
|
||||||
|
|
||||||
|
ClipDates(eventRec);
|
||||||
|
|
||||||
|
Result := eventRec;
|
||||||
|
|
||||||
|
Add(Result);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TVpGanttEventList.Clear;
|
||||||
|
var
|
||||||
|
eventRec: PVpGanttEventRec;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
for i := 0 to Count-1 do
|
||||||
|
begin
|
||||||
|
eventRec := GetItem(i);
|
||||||
|
Dispose(eventRec);
|
||||||
|
end;
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TVpGanttEventList.ClipDates(AEventRec: PVpGanttEventRec);
|
||||||
|
begin
|
||||||
|
// The time range of events reaching out of the displayed date range
|
||||||
|
// must be clipped at the edges.
|
||||||
|
if AEventRec^.StartTime < FStartDate then
|
||||||
|
AEventRec^.StartTime := FStartDate;
|
||||||
|
if AEventRec^.EndTime > FEndDate + 1 then
|
||||||
|
AEventRec^.EndTime := FEndDate + 1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TVpGanttEventList.Delete(AIndex: Integer);
|
||||||
|
var
|
||||||
|
eventRec: PVpGanttEventRec;
|
||||||
|
begin
|
||||||
|
eventRec := GetItem(AIndex);
|
||||||
|
Dispose(eventRec);
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TVpGanttEventList.GetItem(AIndex: Integer): PVpGanttEventRec;
|
||||||
|
begin
|
||||||
|
Result := PVpGanttEventRec(inherited Items[AIndex]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TVpGanttEventList.SetItem(AIndex: Integer; AItem: PVpGanttEventRec);
|
||||||
|
begin
|
||||||
|
inherited Items[AIndex] := AItem;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{******************************************************************************}
|
{******************************************************************************}
|
||||||
{ TVpGanttHeaderAttributes }
|
{ TVpGanttHeaderAttributes }
|
||||||
{******************************************************************************}
|
{******************************************************************************}
|
||||||
@ -534,6 +725,7 @@ end;
|
|||||||
|
|
||||||
destructor TVpGanttView.Destroy;
|
destructor TVpGanttView.Destroy;
|
||||||
begin
|
begin
|
||||||
|
FEventRecords.Free;
|
||||||
FRowHeaderAttributes.Free;
|
FRowHeaderAttributes.Free;
|
||||||
FColHeaderAttributes.Free;
|
FColHeaderAttributes.Free;
|
||||||
inherited;
|
inherited;
|
||||||
@ -790,10 +982,10 @@ var
|
|||||||
begin
|
begin
|
||||||
inherited;
|
inherited;
|
||||||
|
|
||||||
if (FRowHeight > 0) and (Length(FEventRecords) > 0) then
|
if (FRowHeight > 0) and (FEventRecords.Count > 0) then
|
||||||
begin
|
begin
|
||||||
VisibleRows := CalcVisibleRows(ClientHeight, FTotalColHeaderHeight, FRowHeight);
|
VisibleRows := CalcVisibleRows(ClientHeight, FTotalColHeaderHeight, FRowHeight);
|
||||||
emptyRows := VisibleRows - (Length(FEventRecords) - FTopRow);
|
emptyRows := VisibleRows - (FEventRecords.Count - FTopRow);
|
||||||
if emptyRows > 0 then
|
if emptyRows > 0 then
|
||||||
ScrollVertical(-emptyRows);
|
ScrollVertical(-emptyRows);
|
||||||
|
|
||||||
@ -852,7 +1044,7 @@ end;
|
|||||||
function TVpGanttView.GetEventAtCoord(X, Y: Integer): TVpEvent;
|
function TVpGanttView.GetEventAtCoord(X, Y: Integer): TVpEvent;
|
||||||
var
|
var
|
||||||
idx: Integer;
|
idx: Integer;
|
||||||
eventRec: TVpGanttEventRec;
|
eventRec: PVpGanttEventRec;
|
||||||
dt: TDateTime;
|
dt: TDateTime;
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Result := nil;
|
||||||
@ -863,13 +1055,13 @@ begin
|
|||||||
if (idx >= 0) and (idx < NumEvents) then
|
if (idx >= 0) and (idx < NumEvents) then
|
||||||
begin
|
begin
|
||||||
eventRec := FEventRecords[idx];
|
eventRec := FEventRecords[idx];
|
||||||
Result := eventRec.Event;
|
Result := eventRec^.Event;
|
||||||
if Result.AllDayEvent then
|
if Result.AllDayEvent then
|
||||||
begin
|
begin
|
||||||
if (dt < DatePart(Result.StartTime)) or (dt > DatePart(Result.EndTime) + 1) then
|
if (dt < DatePart(eventRec^.StartTime)) or (dt > DatePart(eventRec^.EndTime) + 1) then
|
||||||
Result := nil;
|
Result := nil;
|
||||||
end else
|
end else
|
||||||
if (dt < Result.StartTime) or (dt > Result.EndTime) then
|
if (dt < eventRec^.StartTime) or (dt > eventRec^.EndTime) then
|
||||||
Result := nil;
|
Result := nil;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -902,10 +1094,10 @@ end;
|
|||||||
|
|
||||||
function TVpGanttView.GetEventOfRow(ARow: Integer): TVpEvent;
|
function TVpGanttView.GetEventOfRow(ARow: Integer): TVpEvent;
|
||||||
begin
|
begin
|
||||||
Result := EventRecords[ARow].Event;
|
Result := EventRecords[ARow]^.Event;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TVpGanttView.GetEventRec(AIndex: Integer): TVpGanttEventRec;
|
function TVpGanttView.GetEventRec(AIndex: Integer): PVpGanttEventRec;
|
||||||
begin
|
begin
|
||||||
Result := FEventRecords[AIndex];
|
Result := FEventRecords[AIndex];
|
||||||
end;
|
end;
|
||||||
@ -931,7 +1123,10 @@ end;
|
|||||||
{ Determines the number of events (= rows) to be displayed in the GanttView. }
|
{ Determines the number of events (= rows) to be displayed in the GanttView. }
|
||||||
function TVpGanttView.GetNumEvents: Integer;
|
function TVpGanttView.GetNumEvents: Integer;
|
||||||
begin
|
begin
|
||||||
Result := Length(FEventRecords);
|
if FEventRecords <> nil then
|
||||||
|
Result := FEventRecords.Count
|
||||||
|
else
|
||||||
|
Result := 0;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Determines the number of months (complete or partial) between the first and
|
{ Determines the number of months (complete or partial) between the first and
|
||||||
@ -1021,8 +1216,8 @@ function TVpGanttView.GetRowOfEvent(AEvent: TVpEvent): Integer;
|
|||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
for i := 0 to High(FEventRecords) do
|
for i := 0 to FEventRecords.Count-1 do
|
||||||
if FEventRecords[i].Event = AEvent then
|
if FEventRecords[i]^.Event = AEvent then
|
||||||
begin
|
begin
|
||||||
Result := i;
|
Result := i;
|
||||||
exit;
|
exit;
|
||||||
@ -1335,34 +1530,39 @@ end;
|
|||||||
procedure TVpGanttView.PopulateEventRecords;
|
procedure TVpGanttView.PopulateEventRecords;
|
||||||
var
|
var
|
||||||
event: TVpEvent;
|
event: TVpEvent;
|
||||||
|
eventRec: PVpGanttEventRec;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
xh1, xh2, y1, xe1, xe2, y2: Integer;
|
xh1, xh2, y1, xe1, xe2, y2: Integer;
|
||||||
t1, t2: TDateTime;
|
t1, t2: TDateTime;
|
||||||
totalWidth: Integer;
|
totalWidth: Integer;
|
||||||
list: TFPList;
|
|
||||||
begin
|
begin
|
||||||
if (Datastore = nil) or (DataStore.Resource = nil) then
|
if (Datastore = nil) or (DataStore.Resource = nil) then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
list := TFPList.Create;
|
// The EventRecords list is supposed to collect all events displayed by the
|
||||||
try
|
// GanttView.
|
||||||
|
FEventRecords.Free;
|
||||||
|
FEventRecords := TVpGanttEventList.Create(FRealStartDate, FRealEndDate);
|
||||||
|
|
||||||
// Consider only events which are, fully or partly, inside the
|
// Consider only events which are, fully or partly, inside the
|
||||||
// displayed date range between FRealStartDate and FRealEndDate
|
// displayed date range between FRealStartDate and FRealEndDate
|
||||||
for i := 0 to Datastore.Resource.Schedule.EventCount-1 do
|
for i := 0 to Datastore.Resource.Schedule.EventCount-1 do
|
||||||
begin
|
begin
|
||||||
event := Datastore.Resource.Schedule.GetEvent(i);
|
event := Datastore.Resource.Schedule.GetEvent(i);
|
||||||
|
if event.RepeatCode <> rtNone then
|
||||||
|
FEventRecords.AddRecurringEvents(event)
|
||||||
|
else
|
||||||
|
begin
|
||||||
if DatePart(event.EndTime) < FRealStartDate then
|
if DatePart(event.EndTime) < FRealStartDate then
|
||||||
continue;
|
continue;
|
||||||
if DatePart(event.StartTime) > FRealEndDate then
|
if DatePart(event.StartTime) > FRealEndDate then
|
||||||
continue;
|
continue;
|
||||||
list.Add(event);
|
FEventRecords.AddSingleEvent(event);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Sort events by date/time - this is a general requirement for Gantt
|
// Sort events by date/time - this is a general requirement for Gantt
|
||||||
list.Sort(@CompareEvents);
|
FEventRecords.Sort(@CompareEventRecs);
|
||||||
|
|
||||||
// Prepare array for the event records simplifying work for the Gantt view
|
|
||||||
SetLength(FEventRecords, list.Count);
|
|
||||||
|
|
||||||
// Iterate over all considered events, fill the event record and store it
|
// Iterate over all considered events, fill the event record and store it
|
||||||
// in the array
|
// in the array
|
||||||
@ -1370,50 +1570,28 @@ begin
|
|||||||
xh2 := FixedColWidth;
|
xh2 := FixedColWidth;
|
||||||
y1 := FTotalColHeaderHeight;
|
y1 := FTotalColHeaderHeight;
|
||||||
totalWidth := GetNumDays * ColWidth;
|
totalWidth := GetNumDays * ColWidth;
|
||||||
for i := 0 to list.Count-1 do
|
for i := 0 to FEventRecords.Count-1 do
|
||||||
begin
|
begin
|
||||||
event := TVpEvent(list[i]);
|
eventRec := FEventRecords[i];
|
||||||
|
t1 := eventRec^.StartTime;
|
||||||
|
t2 := eventRec^.EndTime;
|
||||||
|
|
||||||
// Get start and end time of the event. Handle all-day-events correctly.
|
// Store event rectangle coordinates in the EventRec
|
||||||
if event.AllDayEvent then
|
|
||||||
begin
|
|
||||||
t1 := DatePart(event.StartTime);
|
|
||||||
t2 := DatePart(event.EndTime) + 1;
|
|
||||||
if frac(event.EndTime) = 0 then t2 := t2 + 1;
|
|
||||||
end else
|
|
||||||
begin
|
|
||||||
t1 := event.StartTime;
|
|
||||||
t2 := event.EndTime;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// The time range of events reaching out of the displayed date range
|
|
||||||
// must be clipped at the edges.
|
|
||||||
if t1 < FRealStartDate then
|
|
||||||
t1 := FRealStartDate;
|
|
||||||
if t2 > FRealEndDate + 1 then
|
|
||||||
t2 := FRealEndDate + 1;
|
|
||||||
|
|
||||||
// Store event, caption and its rectangle coordinates in the EventRec
|
|
||||||
y2 := y1 + FRowHeight;
|
y2 := y1 + FRowHeight;
|
||||||
xe1 := round((t1 - FRealStartDate) / numDays * totalWidth) + FixedColWidth;
|
xe1 := round((t1 - FRealStartDate) / numDays * totalWidth) + FixedColWidth;
|
||||||
xe2 := round((t2 - FRealStartDate) / numDays * totalWidth) + FixedColWidth;
|
xe2 := round((t2 - FRealStartDate) / numDays * totalWidth) + FixedColWidth;
|
||||||
if xe1 = xe2 then xe2 := xe1 + 1;
|
if xe1 = xe2 then xe2 := xe1 + 1;
|
||||||
FEventRecords[i].Event := event;
|
|
||||||
FEventRecords[i].Caption := event.Description;
|
eventRec^.HeadRect := Rect(xh1, y1, xh2, y2);
|
||||||
FEventRecords[i].HeadRect := Rect(xh1, y1, xh2, y2);
|
eventRec^.EventRect := Rect(xe1, y1, xe2, y2);
|
||||||
FEventRecords[i].EventRect := Rect(xe1, y1, xe2, y2);
|
|
||||||
|
|
||||||
// Find the active row. This is the row with the active event.
|
// Find the active row. This is the row with the active event.
|
||||||
if event = FActiveEvent then
|
if eventRec^.Event = FActiveEvent then
|
||||||
FActiveRow := i;
|
FActiveRow := i;
|
||||||
|
|
||||||
// Prepare for next row
|
// Prepare for next row
|
||||||
y1 := y2;
|
y1 := y2;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
finally
|
|
||||||
list.Free;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TVpGanttView.PopulateMonthRecords;
|
procedure TVpGanttView.PopulateMonthRecords;
|
||||||
@ -1638,8 +1816,8 @@ begin
|
|||||||
dt := DayRecords[FActiveCol].Date;
|
dt := DayRecords[FActiveCol].Date;
|
||||||
dayRect := DayRecords[FActiveCol].Rect;
|
dayRect := DayRecords[FActiveCol].Rect;
|
||||||
|
|
||||||
event := EventRecords[FActiveRow].Event;
|
event := EventRecords[FActiveRow]^.Event;
|
||||||
eventRect := EventRecords[FActiveRow].EventRect;
|
eventRect := EventRecords[FActiveRow]^.EventRect;
|
||||||
dayRect.Top := eventRect.Top;
|
dayRect.Top := eventRect.Top;
|
||||||
dayRect.Bottom := eventRect.Bottom;
|
dayRect.Bottom := eventRect.Bottom;
|
||||||
|
|
||||||
@ -1696,8 +1874,8 @@ begin
|
|||||||
else
|
else
|
||||||
FActiveRow := AValue;
|
FActiveRow := AValue;
|
||||||
|
|
||||||
event := EventRecords[FActiveRow].Event;
|
event := EventRecords[FActiveRow]^.Event;
|
||||||
eventRect := EventRecords[FActiveRow].EventRect;
|
eventRect := EventRecords[FActiveRow]^.EventRect;
|
||||||
dt := DayRecords[FActiveCol].Date;
|
dt := DayRecords[FActiveCol].Date;
|
||||||
dayRect := DayRecords[FActiveCol].Rect;
|
dayRect := DayRecords[FActiveCol].Rect;
|
||||||
dayRect.Top := eventRect.Top;
|
dayRect.Top := eventRect.Top;
|
||||||
|
@ -83,7 +83,7 @@ procedure TVpGanttViewPainter.DrawActiveDate;
|
|||||||
var
|
var
|
||||||
R: TRect;
|
R: TRect;
|
||||||
dayRec: TVpGanttDayRec;
|
dayRec: TVpGanttDayRec;
|
||||||
eventRec: TVpGanttEventRec;
|
eventRec: PVpGanttEventRec;
|
||||||
dx, dy: Integer;
|
dx, dy: Integer;
|
||||||
bs: TBrushStyle;
|
bs: TBrushStyle;
|
||||||
pw: Integer;
|
pw: Integer;
|
||||||
@ -103,7 +103,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
R := Rect(
|
R := Rect(
|
||||||
dayRec.Rect.Left, eventRec.EventRect.Top, dayRec.Rect.Right, eventRec.EventRect.Bottom
|
dayRec.Rect.Left, eventRec^.EventRect.Top, dayRec.Rect.Right, eventRec^.EventRect.Bottom
|
||||||
);
|
);
|
||||||
OffsetRect(R, -dx, -dy);
|
OffsetRect(R, -dx, -dy);
|
||||||
|
|
||||||
@ -273,7 +273,7 @@ end;
|
|||||||
procedure TVpGanttViewPainter.DrawEvents;
|
procedure TVpGanttViewPainter.DrawEvents;
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
eventRec: TVpGanttEventRec;
|
eventRec: PVpGanttEventRec;
|
||||||
event: TVpEvent;
|
event: TVpEvent;
|
||||||
cat: TVpCategoryInfo;
|
cat: TVpCategoryInfo;
|
||||||
R: TRect;
|
R: TRect;
|
||||||
@ -302,12 +302,12 @@ begin
|
|||||||
for i := 0 to FGanttView.NumEvents-1 do
|
for i := 0 to FGanttView.NumEvents-1 do
|
||||||
begin
|
begin
|
||||||
eventRec := FGanttView.EventRecords[i];
|
eventRec := FGanttView.EventRecords[i];
|
||||||
event := eventRec.Event;
|
event := eventRec^.Event;
|
||||||
if event.EndTime < FGanttView.FirstDate then
|
if eventRec^.EndTime < FGanttView.FirstDate then
|
||||||
Continue;
|
Continue;
|
||||||
if event.StartTime > FGanttView.LastDate + 1then
|
if eventRec^.StartTime > FGanttView.LastDate + 1then
|
||||||
exit;
|
exit;
|
||||||
R := ScaleRect(eventRec.EventRect);
|
R := ScaleRect(eventRec^.EventRect);
|
||||||
OffsetRect(R, -dx, -dy);
|
OffsetRect(R, -dx, -dy);
|
||||||
inc(R.Top, top_margin);
|
inc(R.Top, top_margin);
|
||||||
dec(R.Bottom, bottom_margin);
|
dec(R.Bottom, bottom_margin);
|
||||||
@ -330,7 +330,7 @@ var
|
|||||||
x1, x2, y0, y1, y2: Integer;
|
x1, x2, y0, y1, y2: Integer;
|
||||||
dx, dy: Integer;
|
dx, dy: Integer;
|
||||||
i, n, numEvents: Integer;
|
i, n, numEvents: Integer;
|
||||||
eventRec: TVpGanttEventRec;
|
eventRec: PVpGanttEventRec;
|
||||||
dayRec: TVpGanttDayRec;
|
dayRec: TVpGanttDayRec;
|
||||||
monthRec: TVpGanttMonthRec;
|
monthRec: TVpGanttMonthRec;
|
||||||
R: TRect;
|
R: TRect;
|
||||||
@ -364,7 +364,7 @@ begin
|
|||||||
for i := 0 to numEvents - 1 do
|
for i := 0 to numEvents - 1 do
|
||||||
begin
|
begin
|
||||||
eventRec := FGanttView.EventRecords[i];
|
eventRec := FGanttView.EventRecords[i];
|
||||||
R := ScaleRect(eventRec.EventRect);
|
R := ScaleRect(eventRec^.EventRect);
|
||||||
y1 := y0 + R.Bottom;
|
y1 := y0 + R.Bottom;
|
||||||
if y1 >= FScaledTotalColHeaderHeight then
|
if y1 >= FScaledTotalColHeaderHeight then
|
||||||
begin
|
begin
|
||||||
@ -381,7 +381,7 @@ begin
|
|||||||
if numEvents > 0 then
|
if numEvents > 0 then
|
||||||
begin
|
begin
|
||||||
eventRec := FGanttView.EventRecords[numEvents-1];
|
eventRec := FGanttView.EventRecords[numEvents-1];
|
||||||
R := ScaleRect(eventRec.EventRect);
|
R := ScaleRect(eventRec^.EventRect);
|
||||||
y2 := R.Bottom - dy;
|
y2 := R.Bottom - dy;
|
||||||
n := FGanttView.NumDays;
|
n := FGanttView.NumDays;
|
||||||
for i := 0 to n-1 do
|
for i := 0 to n-1 do
|
||||||
@ -477,7 +477,7 @@ var
|
|||||||
str: String;
|
str: String;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
dy: Integer;
|
dy: Integer;
|
||||||
eventRec: TVpGanttEventRec;
|
eventRec: PVpGanttEventRec;
|
||||||
begin
|
begin
|
||||||
RenderCanvas.Brush.Color := RealRowHeadAttrColor;
|
RenderCanvas.Brush.Color := RealRowHeadAttrColor;
|
||||||
|
|
||||||
@ -511,7 +511,7 @@ begin
|
|||||||
for i := 0 to FGanttView.NumEvents-1 do
|
for i := 0 to FGanttView.NumEvents-1 do
|
||||||
begin
|
begin
|
||||||
eventRec := FGanttView.EventRecords[i];
|
eventRec := FGanttView.EventRecords[i];
|
||||||
R := ScaleRect(eventRec.HeadRect);
|
R := ScaleRect(eventRec^.HeadRect);
|
||||||
OffsetRect(R, 0, -dy);
|
OffsetRect(R, 0, -dy);
|
||||||
if R.Top < FScaledTotalColHeaderHeight then
|
if R.Top < FScaledTotalColHeaderHeight then
|
||||||
Continue;
|
Continue;
|
||||||
@ -537,7 +537,7 @@ begin
|
|||||||
RenderCanvas.ClipRect := R;
|
RenderCanvas.ClipRect := R;
|
||||||
inc(R.Left, FScaledTextMargin + 2);
|
inc(R.Left, FScaledTextMargin + 2);
|
||||||
P := Point(R.Left, (R.Top + R.Bottom - strH) div 2);
|
P := Point(R.Left, (R.Top + R.Bottom - strH) div 2);
|
||||||
str := eventRec.Caption;
|
str := eventRec^.Caption;
|
||||||
TPSTextOut(RenderCanvas, Angle, RenderIn, P.X, P.Y, str);
|
TPSTextOut(RenderCanvas, Angle, RenderIn, P.X, P.Y, str);
|
||||||
finally
|
finally
|
||||||
RenderCanvas.Clipping := false;
|
RenderCanvas.Clipping := false;
|
||||||
@ -568,7 +568,7 @@ begin
|
|||||||
y1 := RealTop + FScaledTotalColHeaderHeight;
|
y1 := RealTop + FScaledTotalColHeaderHeight;
|
||||||
if nEvents > 0 then
|
if nEvents > 0 then
|
||||||
begin
|
begin
|
||||||
R := ScaleRect(EventRecords[nEvents-1].HeadRect);
|
R := ScaleRect(EventRecords[nEvents-1]^.HeadRect);
|
||||||
y2 := R.Bottom - dy;
|
y2 := R.Bottom - dy;
|
||||||
end else
|
end else
|
||||||
y2 := y1;
|
y2 := y1;
|
||||||
|
Reference in New Issue
Block a user