Trying to clear a project's tasks leads to an exception. The reason is the destructor of TTMSFNCGanttTask. It should first call FOwnerProject.RemoveDependentTaks(Self) and then free the task's members.
Thank you for letting us know, although we weren't able to reproduce this issue, we made the changes as advised.
Ths will be fixed in the next release of the TMS FNC Gantt Chart.
Actually, TTMSFNCGanttTask.Destroy should look something like this (we renamed the misspelled method RemoveDependentTaks to RemoveDependentTask):
destructor TTMSFNCGanttTask.Destroy;
begin
FSubTasks.Clear;
FTaskDependencies.Clear;
if (Assigned(FOwnerProject) and not FOwnerProject.IsDestroying) then
FOwnerProject.RemoveDependentTask(Self);
FreeAndNil(FTaskAppearance);
FreeAndNil(FSubTasks);
FreeAndNil(FTaskDependencies);
FreeAndNil(FPlannedDuration);
inherited;
if Assigned(FOwnerProject) then
FOwnerProject.DoInternalUpdate;
end;
Furthermore, a method is missing which clears the Gantt Chart. We found, that the following extension does the job:
TTMSFNCCustomGanttChart = class(TTMSFNCCustomControl)
...
public
...
procedure Clear;
...
end;
procedure TTMSFNCCustomGanttChart.Clear;
begin
BeginUpdate;
Project.ClearTasks;
FTimeLine.Items.Clear;
FTaskList.Clear;
EndUpdate;
end;
Finally, it would be nice, if the WBS property of a task could be set. At the moment, it's a read-only property.
Thank you for adding the Clear method to FNC Gantt Chart 1.2.3.3.
Unfortunately, the Clear method is not yet completely correct.
Since Project.ClearTasks actually frees the tasks, the lists that reference these tasks should be cleared first. Furthermore, FTimeline.Items.Clear misses a surrounding FTimeline.BeginUpdate/FTimeline.EndUpdate (it would be cleaner, if the TimeLine component itself would have a Clear method which does the BeginUpdate/EndUpdate just as the TaskList.Clear method):
procedure TTMSFNCCustomGanttChart.Clear;
begin
BeginUpdate;
FTimeline.BeginUpdate;
FTimeline.Items.Clear;
FTimeline.EndUpdate;
FTaskList.Clear;
Project.ClearTasks;
EndUpdate;
end;
or
procedure TTMSFNCCustomGanttChart.Clear;
begin
BeginUpdate;
FTimeline.Clear;
FTaskList.Clear;
Project.ClearTasks;
EndUpdate;
end;
Do you get an access violation or error in this order?
As I'm not able to reproduce any problem.
I got an error in the drawing routines where a task that has already been freed was referenced. Accessing the task's subtasks.count (line 2635 in WEBLib.TMSFNCGanttChart.pas) lead to an undefined error, since the task's subtasks have already been set to nil. To reproduce this error, you have to first select a row in the Gantt chart and then call Clear. Here is a stack trace:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'GetCount')
at Object.DoOnBeforeDrawItem (WEBLib.TMSFNCGanttChart.pas:2635:19)
at Object.cb [as FOnBeforeDrawItem] (rtl.js:250:1)
at Object.DoBeforeDrawItem (WEBLib.TMSFNCGanttTimeline.pas:3538:5)
at Object.DrawItem (WEBLib.TMSFNCGanttTimeline.pas:10458:3)
at Object.DrawDisplay (WEBLib.TMSFNCGanttTimeline.pas:9585:7)
at Object.DrawItems (WEBLib.TMSFNCGanttTimeline.pas:11574:3)
at Object.Draw (WEBLib.TMSFNCGanttTimeline.pas:16180:3)
at Object.DrawControl (WEBLib.TMSFNCCustomControl.pas:2552:7)
at Object.Paint (WEBLib.TMSFNCCustomControl.pas:2601:3)
at Object.Invalidate (WEBLib.Controls.pas:6205:3)
Line 2635 in WEBLib.TMSFNCGanttChart.pas:
if (t.SubTasks.Count > 0) then