mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-06 18:58:12 +02:00
TAChart: Add a simpler demo for a Gantt chart to the TStateSeries sample project.
This commit is contained in:
parent
99f2947c48
commit
33ef9e8b6a
@ -20,6 +20,9 @@ object MainForm: TMainForm
|
||||
object pgMachineStateChart: TTabSheet
|
||||
Caption = 'State plot'
|
||||
end
|
||||
object pgSimpleGanttChart: TTabSheet
|
||||
Caption = 'Simple Gantt plot'
|
||||
end
|
||||
object pgGanttChart: TTabSheet
|
||||
Caption = 'Gantt plot'
|
||||
end
|
||||
|
@ -6,7 +6,7 @@ interface
|
||||
|
||||
uses
|
||||
SysUtils, Classes, Controls, Forms, ComCtrls,
|
||||
uMachineStateFrame, uGanttFrame;
|
||||
uMachineStateFrame, uSimpleGanttFrame, uGanttFrame;
|
||||
|
||||
type
|
||||
|
||||
@ -16,9 +16,11 @@ type
|
||||
PageControl1: TPageControl;
|
||||
pgMachineStateChart: TTabSheet;
|
||||
pgGanttChart: TTabSheet;
|
||||
pgSimpleGanttChart: TTabSheet;
|
||||
procedure FormCreate(Sender: TObject);
|
||||
private
|
||||
FMachineStateFrame: TMachineStateFrame;
|
||||
FSimpleGanttFrame: TSimpleGanttFrame;
|
||||
FGanttFrame: TGanttFrame;
|
||||
end;
|
||||
|
||||
@ -35,6 +37,10 @@ begin
|
||||
FMachineStateFrame.Parent := pgMachinestateChart;
|
||||
FMachineStateFrame.Align := alClient;
|
||||
|
||||
FSimpleGanttFrame := TSimpleGanttFrame.Create(self);
|
||||
FSimpleGanttFrame.Parent := pgSimpleGanttChart;
|
||||
FSimpleGanttFrame.Align := alClient;
|
||||
|
||||
FGanttFrame := TGanttFrame.Create(self);
|
||||
FGanttFrame.Parent := pgGanttChart;
|
||||
FGanttFrame.Align := alClient;
|
||||
|
@ -65,6 +65,14 @@
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="uGanttData"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="usimpleganttframe.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<ComponentName Value="SimpleGanttFrame"/>
|
||||
<HasResources Value="True"/>
|
||||
<ResourceBaseClass Value="Frame"/>
|
||||
<UnitName Value="uSimpleGanttFrame"/>
|
||||
</Unit>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
|
@ -10,7 +10,7 @@ uses
|
||||
athreads,
|
||||
{$ENDIF}
|
||||
Interfaces, // this includes the LCL widgetset
|
||||
Forms, tachartlazaruspkg, main;
|
||||
Forms, tachartlazaruspkg, main, uSimpleGanttFrame;
|
||||
|
||||
{$R *.res}
|
||||
|
||||
|
119
components/tachart/demo/stateseries/uganttdata.pas
Normal file
119
components/tachart/demo/stateseries/uganttdata.pas
Normal file
@ -0,0 +1,119 @@
|
||||
{ This unit provides a data structure for the Gantt data.
|
||||
Basically Gantt data could be added to the StateSeries directly, but the
|
||||
same data are needed at several places. Therefore, it is better to keep them
|
||||
at a common place. }
|
||||
|
||||
unit uGanttData;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Contnrs;
|
||||
|
||||
type
|
||||
TBasicGanttItem = class
|
||||
protected
|
||||
FTitle: String;
|
||||
FStartDate: TDateTime;
|
||||
FDuration: Double;
|
||||
property Duration: Double read FDuration;
|
||||
public
|
||||
property Title: String read FTitle;
|
||||
end;
|
||||
|
||||
TGanttTask = class(TBasicGanttItem)
|
||||
private
|
||||
FPercentageComplete: Double;
|
||||
function GetEndDate: TDateTime;
|
||||
public
|
||||
constructor Create(ATitle: String; AStartDate: TDateTime;
|
||||
ADuration, APercentageDone: Double);
|
||||
property EndDate: TDateTime read GetEndDate;
|
||||
property PercentageComplete: double read FPercentageComplete write FPercentageComplete;
|
||||
property StartDate: TDateTime read FStartDate;
|
||||
end;
|
||||
|
||||
TGanttMilestone = class(TBasicGanttItem)
|
||||
private
|
||||
FComplete: Boolean;
|
||||
public
|
||||
constructor Create(ATitle: String; ADate: TDateTime; AComplete: Boolean);
|
||||
property Complete: Boolean read FComplete write FComplete;
|
||||
property DateDue: TDateTime read FStartDate;
|
||||
end;
|
||||
|
||||
TGanttTaskList = class(TObjectList)
|
||||
private
|
||||
function GetItem(AIndex: Integer): TBasicGanttItem;
|
||||
procedure SetItem(AIndex: Integer; AValue: TBasicGanttItem);
|
||||
public
|
||||
function AddMilestone(ATitle: String; ADate: TDateTime; AComplete: Boolean): Integer;
|
||||
function AddTask(ATitle: String; AStartDate: TDateTime; ADuration, APercentageDone: Double): Integer;
|
||||
property Items[AIndex: Integer]: TBasicGanttItem read GetItem write SetItem; default;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
constructor TGanttTask.Create(ATitle: String; AStartDate: TDateTime;
|
||||
ADuration, APercentageDone: Double);
|
||||
begin
|
||||
inherited Create;
|
||||
FTitle := ATitle;
|
||||
FStartDate := AStartDate;
|
||||
FDuration := ADuration;
|
||||
FPercentageComplete := APercentageDone;
|
||||
end;
|
||||
|
||||
function TGanttTask.GetEndDate: TDateTime;
|
||||
begin
|
||||
Result := FStartDate + FDuration;
|
||||
end;
|
||||
|
||||
{ TGanttMilestone }
|
||||
|
||||
constructor TGanttMilestone.Create(ATitle: String; ADate: TDateTime;
|
||||
AComplete: Boolean);
|
||||
begin
|
||||
inherited Create;
|
||||
FTitle := ATitle;
|
||||
FStartDate := ADate;
|
||||
FComplete := AComplete;
|
||||
end;
|
||||
|
||||
{ TGanttTaskList }
|
||||
|
||||
function TGanttTaskList.AddMilestone(ATitle: String; ADate: TDateTime;
|
||||
AComplete: Boolean): Integer;
|
||||
var
|
||||
item: TBasicGanttItem;
|
||||
begin
|
||||
item := TGanttMilestone.Create(ATitle, ADate, AComplete);
|
||||
Result := Add(item);
|
||||
end;
|
||||
|
||||
function TGanttTaskList.AddTask(ATitle: String; AStartDate: TDateTime;
|
||||
ADuration, APercentageDone: Double): Integer;
|
||||
var
|
||||
item: TBasicGanttItem;
|
||||
begin
|
||||
item := TGanttTask.Create(ATitle, AStartDate, ADuration, APercentageDone);
|
||||
Result := Add(item);
|
||||
end;
|
||||
|
||||
function TGanttTaskList.GetItem(AIndex: Integer): TBasicGanttItem;
|
||||
begin
|
||||
Result := TBasicGanttItem(inherited Items[AIndex]);
|
||||
end;
|
||||
|
||||
procedure TGanttTaskList.SetItem(AIndex: Integer; AValue: TBasicGanttItem);
|
||||
begin
|
||||
inherited Items[AIndex] := AValue;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
||||
end.
|
||||
|
@ -1,3 +1,14 @@
|
||||
{ Demonstration how a Gantt chart can be constructed out of a TStateSeries.
|
||||
It contains two overlaid StateSeries, one for the planned tasks and one
|
||||
for the achieved tasks.
|
||||
|
||||
Since in this constellation the same data (start/end date, task name) are
|
||||
used at several places, a common data structure is provided in unit uGanttData.
|
||||
|
||||
The StateSeries get their its data from this data structure via
|
||||
UserDefinedChartSources.
|
||||
}
|
||||
|
||||
unit uGanttFrame;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
@ -38,7 +38,7 @@ type
|
||||
procedure TimeAxisGetMarkText(Sender: TObject;
|
||||
var AText: String; AMark: Double);
|
||||
procedure StateSeriesGetMarkText(ASeries: TChartSeries; APointIndex,
|
||||
AXIndex, AYIndex: Integer; var AFormattedMark: String);
|
||||
{%H-}AXIndex, {%H-}AYIndex: Integer; var AFormattedMark: String);
|
||||
procedure tbBarHeightChange(Sender: TObject);
|
||||
private
|
||||
procedure PrepareData;
|
||||
@ -235,6 +235,11 @@ begin
|
||||
// For top-to-bottom order of the machines (or use negative idxMachineXXXX values)
|
||||
Chart.LeftAxis.Inverted := true;
|
||||
Chart.BottomAxis.Inverted := false;
|
||||
|
||||
// Series marks text direction
|
||||
MachineA_Series.Marks.LabelFont.Orientation := 0;
|
||||
MachineB_Series.Marks.LabelFont.Orientation := 0;
|
||||
MachineC_Series.Marks.LabelFont.Orientation := 0;
|
||||
end;
|
||||
|
||||
// Sets axis properties for the case of "rotated" (vertically oriented) state series
|
||||
@ -276,6 +281,11 @@ begin
|
||||
|
||||
// Restore left axis direction
|
||||
Chart.LeftAxis.Inverted := false;
|
||||
|
||||
// Series marks text direction
|
||||
MachineA_Series.Marks.LabelFont.Orientation := 900;
|
||||
MachineB_Series.Marks.LabelFont.Orientation := 900;
|
||||
MachineC_Series.Marks.LabelFont.Orientation := 900;
|
||||
end;
|
||||
|
||||
// Composes the label text from the label value and each data point's
|
||||
|
96
components/tachart/demo/stateseries/usimpleganttframe.lfm
Normal file
96
components/tachart/demo/stateseries/usimpleganttframe.lfm
Normal file
@ -0,0 +1,96 @@
|
||||
object SimpleGanttFrame: TSimpleGanttFrame
|
||||
Left = 0
|
||||
Height = 381
|
||||
Top = 0
|
||||
Width = 935
|
||||
ClientHeight = 381
|
||||
ClientWidth = 935
|
||||
TabOrder = 0
|
||||
DesignLeft = 615
|
||||
DesignTop = 307
|
||||
object GanttChart: TChart
|
||||
Left = 0
|
||||
Height = 350
|
||||
Top = 0
|
||||
Width = 935
|
||||
AxisList = <
|
||||
item
|
||||
Grid.Color = clSilver
|
||||
Grid.Style = psSolid
|
||||
Grid.Visible = False
|
||||
Marks.LabelBrush.Style = bsClear
|
||||
Minors = <>
|
||||
Title.LabelFont.Orientation = 900
|
||||
Title.LabelBrush.Style = bsClear
|
||||
end
|
||||
item
|
||||
Grid.Color = clSilver
|
||||
Grid.Style = psSolid
|
||||
Alignment = calBottom
|
||||
Marks.Format = '%2:s'
|
||||
Marks.LabelBrush.Style = bsClear
|
||||
Marks.Source = DateTimeIntervalChartSource
|
||||
Marks.Style = smsLabel
|
||||
Minors = <>
|
||||
Title.LabelBrush.Style = bsClear
|
||||
end>
|
||||
Margins.Left = 0
|
||||
Margins.Top = 10
|
||||
Margins.Right = 24
|
||||
Margins.Bottom = 24
|
||||
Title.Text.Strings = (
|
||||
'TAChart'
|
||||
)
|
||||
Toolset = GanttChartToolset
|
||||
Align = alClient
|
||||
object GanttSeries: TStateSeries
|
||||
OnGetMarkText = GanttSeriesGetMarkText
|
||||
BarBrush.Color = clSilver
|
||||
BarHeight = 0.7
|
||||
end
|
||||
end
|
||||
object Panel1: TPanel
|
||||
Left = 0
|
||||
Height = 31
|
||||
Top = 350
|
||||
Width = 935
|
||||
Align = alBottom
|
||||
AutoSize = True
|
||||
BevelOuter = bvNone
|
||||
ClientHeight = 31
|
||||
ClientWidth = 935
|
||||
TabOrder = 1
|
||||
object cbRotated: TCheckBox
|
||||
AnchorSideLeft.Control = Panel1
|
||||
AnchorSideTop.Control = Panel1
|
||||
Left = 12
|
||||
Height = 19
|
||||
Top = 6
|
||||
Width = 59
|
||||
BorderSpacing.Left = 6
|
||||
BorderSpacing.Around = 6
|
||||
Caption = 'Rotated'
|
||||
TabOrder = 0
|
||||
OnChange = cbRotatedChange
|
||||
end
|
||||
end
|
||||
object GanttChartToolset: TChartToolset
|
||||
Left = 120
|
||||
Top = 184
|
||||
object GanttZoomDragTool: TZoomDragTool
|
||||
Shift = [ssLeft]
|
||||
Brush.Style = bsClear
|
||||
end
|
||||
object GanttPanDragTool: TPanDragTool
|
||||
Shift = [ssRight]
|
||||
end
|
||||
object GanttDataPointHintTool: TDataPointHintTool
|
||||
end
|
||||
end
|
||||
object DateTimeIntervalChartSource: TDateTimeIntervalChartSource
|
||||
Params.MinLength = 100
|
||||
SuppressPrevUnit = False
|
||||
Left = 120
|
||||
Top = 104
|
||||
end
|
||||
end
|
140
components/tachart/demo/stateseries/usimpleganttframe.pas
Normal file
140
components/tachart/demo/stateseries/usimpleganttframe.pas
Normal file
@ -0,0 +1,140 @@
|
||||
{ A simple demonstration of a GanttChart created by means of a TStateSeries.
|
||||
|
||||
Data are stored in the built-in ListChartSource of the series.
|
||||
}
|
||||
|
||||
unit uSimpleGanttFrame;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
SysUtils, Classes,
|
||||
Graphics, Forms, Controls, StdCtrls, ExtCtrls,
|
||||
TAGraph, TAChartUtils, TACustomSource, TAIntervalSources, TASources,
|
||||
TACustomSeries, TASeries, TAMultiSeries, TATools;
|
||||
|
||||
type
|
||||
TSimpleGanttFrame = class(TFrame)
|
||||
cbRotated: TCheckBox;
|
||||
DateTimeIntervalChartSource: TDateTimeIntervalChartSource;
|
||||
GanttChart: TChart;
|
||||
GanttChartToolset: TChartToolset;
|
||||
GanttDataPointHintTool: TDataPointHintTool;
|
||||
GanttPanDragTool: TPanDragTool;
|
||||
GanttSeries: TStateSeries;
|
||||
GanttZoomDragTool: TZoomDragTool;
|
||||
Panel1: TPanel;
|
||||
procedure cbRotatedChange(Sender: TObject);
|
||||
procedure GanttSeriesGetMarkText({%H-}ASeries: TChartSeries;
|
||||
APointIndex, {%H-}AXIndex, {%H-}AYIndex: Integer; var AFormattedMark: String);
|
||||
private
|
||||
procedure PrepareData;
|
||||
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
{$R *.lfm}
|
||||
|
||||
constructor TSimpleGanttFrame.Create(AOwner: TComponent);
|
||||
begin
|
||||
inherited;
|
||||
PrepareData;
|
||||
end;
|
||||
|
||||
// Checkbox clicked to toggle between "normal" and "rotated" state series
|
||||
// (horizontal or vertical orientation)
|
||||
procedure TSimpleGanttFrame.cbRotatedChange(Sender: TObject);
|
||||
begin
|
||||
if cbRotated.Checked then
|
||||
begin
|
||||
GanttSeries.AxisIndexX := 0;
|
||||
GanttSeries.AxisIndexY := 1;
|
||||
|
||||
// Bottom axis marks
|
||||
GanttChart.BottomAxis.Marks.Source := GanttSeries.ListSource;
|
||||
GanttChart.BottomAxis.Marks.Style := smsLabel;
|
||||
GanttChart.BottomAxis.Marks.SourceExchangeXY := true;
|
||||
GanttChart.BottomAxis.Marks.LabelFont.Orientation := 900;
|
||||
GanttChart.BottomAxis.Grid.Visible := false;
|
||||
|
||||
// Left axis marks
|
||||
GanttChart.LeftAxis.Marks.Source := DateTimeIntervalChartSource;
|
||||
GanttChart.LeftAxis.Marks.Style := smsLabel;
|
||||
GanttChart.LeftAxis.Grid.Visible := true;
|
||||
|
||||
GanttChart.Margins.Top := 0;
|
||||
GanttChart.Margins.Left := 10;
|
||||
end else
|
||||
begin
|
||||
GanttSeries.AxisIndexX := 1;
|
||||
GanttSeries.AxisIndexY := 0;
|
||||
|
||||
// Left axis marks
|
||||
GanttChart.LeftAxis.Marks.Source := GanttSeries.ListSource;
|
||||
GanttChart.LeftAxis.Marks.Style := smsLabel;
|
||||
GanttChart.LeftAxis.Grid.Visible := false;
|
||||
|
||||
// Bottom axis marks
|
||||
GanttChart.BottomAxis.Marks.Source := DateTimeIntervalChartSource;
|
||||
GanttChart.BottomAxis.Marks.Style := smsLabel;
|
||||
GanttChart.BottomAxis.Marks.SourceExchangeXY := false;
|
||||
GanttChart.BottomAxis.Marks.LabelFont.Orientation := 0;
|
||||
GanttChart.BottomAxis.Grid.Visible := true;
|
||||
|
||||
GanttChart.Margins.Left := 0;
|
||||
GanttChart.Margins.Top := 10;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Constructs the Mark text to be used in the popup hint. }
|
||||
procedure TSimpleGanttFrame.GanttSeriesGetMarkText(ASeries: TChartSeries;
|
||||
APointIndex, AXIndex, AYIndex: Integer; var AFormattedMark: String);
|
||||
var
|
||||
tPlan1, tPlan2: Double;
|
||||
txt: String;
|
||||
item: PChartDataItem;
|
||||
begin
|
||||
item := TStateSeries(ASeries).Source.Item[APointIndex];
|
||||
txt := item^.Text;
|
||||
tPlan1 := item^.GetX(0);
|
||||
tPlan2 := item^.GetX(1);
|
||||
if tPlan1 = tPlan2 then
|
||||
AFormattedMark := Format(
|
||||
'"%s"' + LineEnding +
|
||||
'⯄ due %s', [
|
||||
txt, DateToStr(tPlan1)
|
||||
])
|
||||
else
|
||||
AFormattedMark := Format(
|
||||
'Task "%s":' + LineEnding +
|
||||
'⯄ %s - %s', [
|
||||
txt, DateToStr(tPlan1), DateToStr(tPlan2)
|
||||
]);
|
||||
end;
|
||||
|
||||
procedure TSimpleGanttFrame.PrepareData;
|
||||
begin
|
||||
GanttSeries.ListSource.XCount := 2;
|
||||
GanttSeries.AddXY(EncodeDate(2024,2,3), EncodeDate(2024,2,4), 0, 'Kick-off', clGreen);
|
||||
GanttSeries.AddXY(EncodeDate(2024,2,4), EncodeDate(2024,2,8), 1, 'Activity 1', clRed);
|
||||
GanttSeries.AddXY(EncodeDate(2024,2,8), EncodeDate(2024,2,11), 2, 'Activity 2', clYellow);
|
||||
GanttSeries.AddXY(EncodeDate(2024,2,11), EncodeDate(2024,2,21), 3, 'Activity 3', clFuchsia);
|
||||
GanttSeries.AddXY(EncodeDate(2024,2,21), EncodeDate(2024,2,21), 4, 'Intermediate Milestone', clBlack);
|
||||
GanttSeries.AddXY(EncodeDate(2024,2,21), EncodeDate(2024,2,28), 5, 'Activity 4', clSkyBlue);
|
||||
GanttSeries.AddXY(EncodeDate(2024,2,28), EncodeDate(2024,3,7), 6, 'Activity 5', clOlive);
|
||||
GanttSeries.AddXY(EncodeDate(2024,3,7), EncodeDate(2024,3,7), 7, 'Final Milestone', clBlack);
|
||||
|
||||
// Show the task titles as y axis labels
|
||||
GanttChart.LeftAxis.Marks.Source := GanttSeries.ListSource;
|
||||
GanttChart.LeftAxis.Marks.Style := smsLabel;
|
||||
GanttChart.LeftAxis.Inverted := true;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user