diff --git a/components/fpspreadsheet/examples/other/chart/write_chart_demo.lpr b/components/fpspreadsheet/examples/other/chart/write_chart_demo.lpr
index 1bd9d870c..90d7ce8e9 100644
--- a/components/fpspreadsheet/examples/other/chart/write_chart_demo.lpr
+++ b/components/fpspreadsheet/examples/other/chart/write_chart_demo.lpr
@@ -22,37 +22,32 @@ begin
sh1.WriteNumber(i, 1, sin(i-1));
end;
- ch := b.AddChart(sh1, 4, 4, 125, 95);
+ ch := b.AddChart(sh1, 4, 4, 160, 100);
ser := TsLineSeries.Create(ch);
ser.SetTitleAddr(0, 1);
ser.SetLabelRange(1, 0, 7, 0);
ser.SetYRange(1, 1, 7, 1);
+ ch.Background.Style := fsSolidFill;
+ ch.Border.Style := clsSolid;
+ ch.PlotArea.Background.Style := fsSolidFill;
{$IFDEF DARK_MODE}
ch.Background.FgColor := scBlack;
- ch.Background.Style := fsSolidFill;
-
ch.Border.Color := scWhite;
- ch.Border.Style := clsSolid;
-
- ch.PlotArea.Background.Style := fsSolidFill;
ch.PlotArea.Background.FgColor := $1F1F1F;
{$ELSE}
ch.Background.FgColor := scWhite;
- ch.Background.Style := fsSolidFill;
-
ch.Border.Color := scBlack;
- ch.Border.Style := clsSolid;
-
- ch.PlotArea.Background.Style := fsSolidFill;
ch.PlotArea.Background.FgColor := $F0F0F0;
{$ENDIF}
ch.XAxis.ShowLabels := true;
ch.XAxis.LabelFont.Size := 8;
ch.XAxis.LabelFont.Color := scRed;
+ ch.XAxis.LabelFont.Style := [fssStrikeout];
ch.XAxis.AxisLine.Color := scRed;
ch.XAxis.CaptionFont.Color := scRed;
ch.XAxis.CaptionFont.Size := 12;
+ ch.XAxis.Inverted := true;
ch.YAxis.ShowLabels := true;
ch.YAxis.LabelFont.Size := 8;
@@ -72,6 +67,13 @@ begin
ch.YAxis.MajorGridLines.Style := clsSolid;
ch.YAxis.MinorGridLines.Style := clsSolid;
+ ch.Legend.Font.Size := 20;
+ ch.Legend.Font.Color := scGreen;
+ ch.Legend.Border.Width := 3;
+ ch.Legend.Border.Color := scRed;
+ ch.Legend.Background.FgColor := scYellow;
+ ch.Legend.Background.Style := fsSolidFill;
+
// 2nd sheet
sh2 := b.AddWorksheet('test2');
diff --git a/components/fpspreadsheet/source/common/fpschart.pas b/components/fpspreadsheet/source/common/fpschart.pas
index b9090f256..bce6a56f4 100644
--- a/components/fpspreadsheet/source/common/fpschart.pas
+++ b/components/fpspreadsheet/source/common/fpschart.pas
@@ -1,4 +1,4 @@
-unit fpschart;
+unit fpsChart;
{$mode objfpc}{$H+}
{$modeswitch advancedrecords}
@@ -24,6 +24,10 @@ var
clsLongDashDot: Integer = -1;
clsLongDashDotDot: Integer = -1;
+const
+ DEFAULT_CHART_LINEWIDTH = 0.75; // pts
+ DEFAULT_CHART_FONT = 'Arial';
+
type
TsChart = class;
@@ -160,7 +164,13 @@ type
property ShowLabels: Boolean read FShowLabels write FShowLabels;
end;
- TsChartLegend = class(TsChartText)
+ TsChartLegend = class(TsChartFillElement)
+ private
+ FFont: TsFont;
+ public
+ constructor Create(AChart: TsChart);
+ destructor Destroy; override;
+ property Font: TsFont read FFont write FFont;
end;
TsChartAxisLink = (alPrimary, alSecondary);
@@ -329,10 +339,6 @@ type
implementation
-const
- DEFAULT_LINE_WIDTH = 0.75; // pts
- DEFAULT_FONT = 'Arial';
-
{ TsChartLineStyle }
function TsChartLineStyle.GetID: String;
@@ -398,7 +404,7 @@ begin
FBackground.FgColor := scWhite;
FBorder := TsChartLine.Create;
FBorder.Style := clsSolid;
- FBorder.Width := PtsToMM(DEFAULT_LINE_WIDTH);
+ FBorder.Width := PtsToMM(DEFAULT_CHART_LINEWIDTH);
FBorder.Color := scBlack;
end;
@@ -417,7 +423,6 @@ begin
inherited Create(AChart);
FShowCaption := true;
FFont := TsFont.Create;
- FFont.FontName := DEFAULT_FONT;
FFont.Size := 10;
FFont.Style := [];
FFont.Color := scBlack;
@@ -440,13 +445,11 @@ begin
FAutomaticMinorSteps := true;
FCaptionFont := TsFont.Create;
- FCaptionFont.FontName := DEFAULT_FONT;
FCaptionFont.Size := 10;
FCaptionFont.Style := [];
FCaptionFont.Color := scBlack;
FLabelFont := TsFont.Create;
- FLabelFont.FontName := DEFAULT_FONT;
FLabelFont.Size := 9;
FLabelFont.Style := [];
FLabelFont.Color := scBlack;
@@ -460,27 +463,27 @@ begin
FAxisLine := TsChartLine.Create;
FAxisLine.Color := scBlack;
FAxisLine.Style := clsSolid;
- FAxisLine.Width := PtsToMM(DEFAULT_LINE_WIDTH);
+ FAxisLine.Width := PtsToMM(DEFAULT_CHART_LINEWIDTH);
FMajorTickLines := TsChartLine.Create;
FMajorTickLines.Color := scBlack;
FMajorTickLines.Style := clsSolid;
- FMajorTickLines.Width := PtsToMM(DEFAULT_LINE_WIDTH);
+ FMajorTickLines.Width := PtsToMM(DEFAULT_CHART_LINEWIDTH);
FMinorTickLines := TsChartLine.Create;
FMinorTickLines.Color := scBlack;
FMinorTickLines.Style := clsSolid;
- FMinorTickLines.Width := PtsToMM(DEFAULT_LINE_WIDTH);
+ FMinorTickLines.Width := PtsToMM(DEFAULT_CHART_LINEWIDTH);
FMajorGridLines := TsChartLine.Create;
FMajorGridLines.Color := scSilver;
FMajorGridLines.Style := clsSolid;
- FMajorGridLines.Width := PtsToMM(DEFAULT_LINE_WIDTH);
+ FMajorGridLines.Width := PtsToMM(DEFAULT_CHART_LINEWIDTH);
FMinorGridLines := TsChartLine.Create;
FMinorGridLines.Color := scSilver;
FMinorGridLines.Style := clsDot;
- FMinorGridLines.Width := PtsToMM(DEFAULT_LINE_WIDTH);
+ FMinorGridLines.Width := PtsToMM(DEFAULT_CHART_LINEWIDTH);
end;
destructor TsChartAxis.Destroy;
@@ -496,6 +499,23 @@ begin
end;
+{ TsChartLegend }
+
+constructor TsChartLegend.Create(AChart: TsChart);
+begin
+ inherited Create(AChart);
+ FFont := TsFont.Create;
+ FFont.Size := 9;
+ FVisible := true;
+end;
+
+destructor TsChartLegend.Destroy;
+begin
+ FFont.Free;
+ inherited;
+end;
+
+
{ TsChartSeries }
constructor TsChartSeries.Create(AChart: TsChart);
@@ -619,12 +639,12 @@ begin
FLine := TsChartLine.Create;
FLine.Color := scBlack;
FLine.Style := clsSolid;
- FLine.Width := PtsToMM(DEFAULT_LINE_WIDTH);
+ FLine.Width := PtsToMM(DEFAULT_CHART_LINEWIDTH);
FSymbolBorder := TsChartline.Create;
FSymbolBorder.Color := scBlack;
FSymbolBorder.Style := clsSolid;
- FSymbolBorder.Width := PtsToMM(DEFAULT_LINE_WIDTH);
+ FSymbolBorder.Width := PtsToMM(DEFAULT_CHART_LINEWIDTH);
FSymbolFill := TsChartFill.Create;
FSymbolFill.FgColor := scWhite;
diff --git a/components/fpspreadsheet/source/common/fpschartstyles.pas b/components/fpspreadsheet/source/common/fpschartstyles.pas
index 4fd107944..3b77421c5 100644
--- a/components/fpspreadsheet/source/common/fpschartstyles.pas
+++ b/components/fpspreadsheet/source/common/fpschartstyles.pas
@@ -82,6 +82,16 @@ type
class operator = (A, B: TsChartCaptionRec): Boolean;
end;
+ TsChartLegendRec = record
+ Font: TsChartFontRec;
+ Border: TsChartLineRec;
+ Fill: TsChartFillRec;
+ Visible: Boolean;
+ procedure FromChart(AChart: TsChart);
+ procedure ToChart(AChart: TsChart);
+ class operator = (A, B: TsChartLegendRec): Boolean;
+ end;
+
{----------------------------------------------------------------------------}
TsChartStyle = class
@@ -131,6 +141,15 @@ type
property CaptionType: TsChartCaptionType read FCaptionType write FCaptionType;
end;
+ TsChartLegendStyle = class(TsChartStyle)
+ private
+ FLegend: TsChartLegendRec;
+ public
+ procedure ApplyToChart(AChart: TsChart);
+ procedure ExtractFromChart(AChart: TsChart);
+ property Legend: TsChartLegendRec read FLegend write FLegend;
+ end;
+
{ ---------------------------------------------------------------------------}
TsChartStyleList = class(TFPList)
@@ -141,10 +160,12 @@ type
procedure AddChartAxisStyle(AChart: TsChart; AType: TsChartAxisType);
procedure AddChartBackgroundStyle(AChart: TsChart; AType: TsChartBackgroundType);
procedure AddChartCaptionStyle(AChart: TsChart; AType: TsChartCaptionType);
+ procedure AddChartLegendStyle(AChart: TsChart);
procedure Clear;
function FindChartAxisStyle(AChart: TsChart; AType: TsChartAxisType): Integer;
function FindChartBackgroundStyle(AChart: TsChart; AType: TsChartBackgroundType): Integer;
function FindChartCaptionStyle(AChart: TsChart; AType: TsChartCaptionType): Integer;
+ function FindChartLegendStyle(AChart: TsChart): Integer;
end;
implementation
@@ -376,6 +397,33 @@ begin
Result := (A.Font = B.Font) and (A.Visible = B.Visible);
end;
+{ TsChartLegendRec }
+procedure TsChartLegendRec.FromChart(AChart: TsChart);
+begin
+ Font.FromFont(AChart.Legend.Font);
+ Border.FromLine(AChart.Legend.Border);
+ Fill.FromFill(AChart.Legend.Background);
+ Visible := AChart.Legend.Visible;
+end;
+
+procedure TsChartLegendRec.ToChart(AChart: TsChart);
+begin
+ Font.ToFont(AChart.Legend.Font);
+ Border.ToLine(AChart.Legend.Border);
+ Fill.ToFill(AChart.Legend.Background);
+ AChart.Legend.Visible := Visible;
+end;
+
+class operator TsChartLegendRec.= (A, B: TsChartLegendRec): Boolean;
+begin
+ Result := (A.Font = B.Font) and (A.Border = B.Border) and (A.Fill = B.Fill) and
+ (A.Visible = B.Visible);
+end;
+
+
+{==============================================================================}
+{ Style classes to be listed in ChartStyleList }
+{==============================================================================}
{ TsChartBackgroundstyle }
@@ -477,6 +525,19 @@ begin
end;
+{ TsChartLegendStyle }
+
+procedure TsChartLegendStyle.ApplyToChart(AChart: TsChart);
+begin
+ FLegend.ToChart(AChart);
+end;
+
+procedure TsChartLegendStyle.ExtractFromChart(AChart: TsChart);
+begin
+ FLegend.FromChart(AChart);
+end;
+
+
{ TsChartStyleList }
destructor TsChartStyleList.Destroy;
@@ -493,6 +554,14 @@ begin
FindChartAxisStyle(AChart, AType);
end;
+{ Adds the style of the specified type in the given chart as new style to the
+ style list. But only if the same style does not yet exist. }
+procedure TsChartStyleList.AddChartBackgroundStyle(AChart: TsChart;
+ AType: TsChartBackgroundType);
+begin
+ FindChartBackgroundStyle(AChart, AType);
+end;
+
{ Adds the style of the specified caption in the given chart as new style to
the style list. But only if the same style does not yet exist. }
procedure TsChartStyleList.AddChartCaptionStyle(AChart: TsChart;
@@ -501,12 +570,11 @@ begin
FindChartCaptionStyle(AChart, AType);
end;
-{ Adds the style of the specified type in the given chart as new style to the
- style list. But only if the same style does not yet exist. }
-procedure TsChartStyleList.AddChartBackgroundStyle(AChart: TsChart;
- AType: TsChartBackgroundType);
+{ Adds the style of the legend of the given chart chart as new style to
+ the style list. But only if the same style does not yet exist. }
+procedure TsChartStyleList.AddChartLegendStyle(AChart: TsChart);
begin
- FindChartBackgroundStyle(AChart, AType);
+ FindChartLegendStyle(AChart);
end;
procedure TsChartStyleList.Clear;
@@ -611,6 +679,35 @@ begin
newStyle.Free;
end;
+{ Searches whether the legend style of the given chart is already in the
+ list. If not, a new style is created and added.
+ The type of the requested axis must be provided as parameter.
+ Returns the index of the style. }
+function TsChartStyleList.FindChartLegendStyle(AChart: TsChart): Integer;
+var
+ newStyle, style: TsChartLegendStyle;
+ i: Integer;
+begin
+ Result := -1;
+ newStyle := TsChartLegendStyle.Create;
+ newStyle.ExtractFromChart(AChart);
+ for i := 0 to Count-1 do
+ begin
+ if (TsChartStyle(Items[i]) is TsChartLegendStyle) then
+ begin
+ style := TsChartLegendStyle(Items[i]);
+ if (style.Legend = newStyle.Legend) then
+ begin
+ Result := i;
+ break;
+ end;
+ end;
+ end;
+ if Result = -1 then
+ Result := Add(newStyle)
+ else
+ newStyle.Free;
+end;
end.
diff --git a/components/fpspreadsheet/source/common/fpsopendocument.pas b/components/fpspreadsheet/source/common/fpsopendocument.pas
index 001a37a0f..f7c716a9e 100644
--- a/components/fpspreadsheet/source/common/fpsopendocument.pas
+++ b/components/fpspreadsheet/source/common/fpsopendocument.pas
@@ -289,6 +289,7 @@ type
function GetChartAxisStyleAsXML(AChart: TsChart; AStyleIndex: Integer; AIndent: Integer): String;
function GetChartBackgroundStyleAsXML(AChart: TsChart; AStyleIndex: Integer; AIndent: Integer): String;
function GetChartCaptionStyleAsXML(AChart: TsChart; AStyleIndex: Integer; AIndent: Integer): String;
+ function GetChartLegendStyleAsXML(AChart: TsChart; AStyleIndex: Integer; AIndent: Integer): String;
procedure PrepareChartTable(AChart: TsChart; AWorksheet: TsBasicWorksheet);
procedure WriteChart(AStream: TStream; AChart: TsChart);
@@ -5905,6 +5906,8 @@ begin
styles.AddChartCaptionStyle(chart, cctSecondaryY);
styles.AddChartCaptionStyle(chart, cctTitle);
styles.AddChartCaptionStyle(chart, cctSubTitle);
+
+ styles.AddChartLegendStyle(chart);
end;
end;
@@ -6913,17 +6916,19 @@ procedure TsSpreadOpenDocWriter.WriteChartLegend(AStream: TStream; AChart: TsCha
AIndent: Integer);
var
ind: String;
- legendStyleID: Integer = 400;
+ legendStyleIdx: Integer = 400;
begin
if (not AChart.Legend.Visible) then
exit;
+ legendStyleIdx := TsChartStyleList(FChartStyleList).FindChartLegendStyle(AChart);
+
ind := DupeString(' ', AIndent);
AppendToStream(AStream, Format(
ind + '' + LE,
- [ legendStyleID ]
+ [ legendStyleIdx + 1 ]
));
end;
@@ -7011,12 +7016,10 @@ function TsSpreadOpenDocWriter.GetChartAxisStyleAsXML(
var
ind: String;
style: TsChartAxisStyle;
- displayLabels: string = '';
- logarithmic: String = '';
- strokeColor: String = '';
- styleRotationAngle: String = '';
- fontSize: String = '';
- fontColor: String = '';
+ font: TsFont;
+ textProps: String = '';
+ graphProps: String = '';
+ chartProps: String = '';
begin
if AStyleIndex = -1 then
begin
@@ -7030,54 +7033,35 @@ begin
exit;
if style.Axis.ShowLabels then
- displayLabels := 'chart:display-label="true" '
- else
- displayLabels := '';
+ chartProps := chartProps + 'chart:display-label="true" ';
if style.Axis.Logarithmic then
- logarithmic := 'logarithmic="true" '
- else
- logarithmic := '';
+ chartProps := chartProps + 'chart:logarithmic="true" ';
+
+ if style.Axis.Inverted then
+ chartProps := chartProps + 'chart:reverse-direction="true" ';
if style.Axis.LabelRotation <> 0 then
- styleRotationAngle := 'style:rotation-ange="' + IntToStr(style.Axis.LabelRotation) + '" ';
+ chartProps := chartProps + Format('style:rotation-angle="%d" ', [style.Axis.LabelRotation]);
- strokeColor := 'svg:stroke-color="' + ColorToHTMLColorStr(style.Axis.AxisLine.Color) + '" ';
+ graphProps := 'svg:stroke-color="' + ColorToHTMLColorStr(style.Axis.AxisLine.Color) + '" ';
- fontSize := Format('fo:font-size="%.1fpt" style:font-size-asian="%.1fpt" style:font-size-complex="%.1fpt" ',
- [style.Axis.LabelFont.Size, style.Axis.LabelFont.Size, style.Axis.LabelFont.Size],
- FPointSeparatorSettings
- );
- fontColor := 'fo:color="' + ColorToHTMLColorStr(style.Axis.LabelFont.Color) + '" ';
+ font := TsFont.Create;
+ try
+ style.Axis.LabelFont.ToFont(font);
+ textProps := WriteFontStyleXMLAsString(font);
+ finally
+ font.Free;
+ end;
- (*
-
-
-
-
- *)
ind := DupeString(' ', AIndent);
Result := Format(
ind + '' + LE +
- ind + ' ' + LE +
+ ind + ' ' + LE +
ind + ' ' + LE +
- ind + ' ' + LE +
+ ind + ' ' + LE +
ind + '' + LE,
- [ AStyleIndex + 1,
- // chart-properties
- displayLabels, logarithmic, styleRotationAngle,
- // graphic-properties
- strokeColor,
- // text-properties
- fontSize, fontColor
- ]
+ [ AStyleIndex + 1, chartProps, graphProps, textProps ]
);
end;
@@ -7135,9 +7119,9 @@ function TsSpreadOpenDocWriter.GetChartCaptionStyleAsXML(AChart: TsChart;
var
style: TsChartCaptionStyle;
ind: String;
- fontSize: String = '';
- fontColor: String = '';
- styleRotationAngle: String = '';
+ font: TsFont;
+ chartProps: String = '';
+ textProps: String = '';
begin
Result := '';
@@ -7150,28 +7134,94 @@ begin
exit;
if style.Caption.Rotation <> 0 then
- styleRotationAngle := Format('style:rotation-angle="%d" ', [style.Caption.Rotation]);
+ chartProps := chartProps + Format('style:rotation-angle="%d" ', [style.Caption.Rotation]);
- fontSize := Format('fo:font-size="%.1fpt" style:font-size-asian="%.1fpt" style:font-size-complex="%.1fpt" ',
- [ style.Caption.Font.Size, style.Caption.Font.Size, style.Caption.Font.Size ],
- FPointSeparatorSettings
- );
- fontColor := Format('fo:color="%s" ', [ColorToHTMLColorStr(style.Caption.Font.Color)]);
+ font := TsFont.Create;
+ try
+ style.Caption.Font.ToFont(font);
+ textProps := WriteFontStyleXMLAsString(font);
+ finally
+ font.Free;
+ end;
ind := DupeString(' ', AIndent);
Result := Format(
ind + '' + LE +
ind + ' ' + LE +
- ind + ' ' + LE +
+ ind + ' ' + LE +
ind + '' + LE,
- [AStyleIndex + 1,
- // chart-properties
- styleRotationAngle,
- // text-properties
- fontSize, fontColor ]
+ [ AStyleIndex + 1, chartProps, textProps ]
);
end;
+{
+
+
+
+
+
+}
+function TsSpreadOpenDocWriter.GetChartLegendStyleAsXML(AChart: TsChart;
+ AStyleIndex: Integer; AIndent: Integer): String;
+var
+ ind: String;
+ style: TsChartLegendStyle;
+ font: TsFont;
+ textProps: String = '';
+ graphProps: String = '';
+begin
+ Result := '';
+
+ if AStyleIndex = -1 then
+ exit;
+
+ style := TsChartLegendStyle(FChartStyleList[AStyleIndex]);
+
+ if not style.Legend.Visible then
+ exit;
+
+ if style.Legend.Border.Style = clsNoLine then
+ graphProps := 'draw:stroke="none" '
+ else
+ graphProps := Format('svg:stroke-color="%s" svg:stroke-width="%.1fmm" ',
+ [ColorToHTMLColorStr(style.Legend.Border.Color), style.Legend.Border.Width],
+ FPointSeparatorSettings);
+ if style.Legend.Fill.Style = fsNoFill then
+ graphProps := graphProps + 'draw:fill="none" '
+ else
+ graphProps := graphProps + Format('draw:fill="solid" draw:fill-color="%s" ',
+ [ColorToHTMLColorStr(style.Legend.Fill.FgColor)]);;
+
+ font := TsFont.Create;
+ try
+ style.Legend.Font.ToFont(font);
+ textProps := WriteFontStyleXMLAsString(font);
+ finally
+ font.Free;
+ end;
+
+ ind := DupeString(' ', AIndent);
+ Result := Format(
+ ind + '' + LE +
+ ind + ' ' + LE +
+ ind + ' ' + LE +
+ ind + ' ' + LE +
+ ind + '' + LE,
+ [
+ AStyleIndex + 1,
+ // chart-properties
+ //...
+ // graphic-properties
+ graphProps,
+ // text-properties
+ textProps
+ ]);
+end;
+
{ To do: The list of styles must be updated to the real chart element settings. }
procedure TsSpreadOpenDocWriter.WriteChartStyles(AStream: TStream;
AChart: TsChart; AIndent: Integer);
@@ -7190,6 +7240,7 @@ var
y2AxisCaptionStyleIdx: Integer;
titleCaptionStyleIdx: Integer;
subtitleCaptionStyleIdx: Integer;
+ legendStyleIdx: Integer;
begin
backGrStyleIdx := TsChartStyleList(FChartStyleList).FindChartBackgroundStyle(AChart, cbtBackground);
wallStyleIdx := TsChartStyleList(FChartStyleList).FindChartBackgroundStyle(AChart, cbtWall);
@@ -7207,6 +7258,8 @@ begin
titleCaptionStyleIdx := TsChartStyleList(FChartStyleList).FindChartCaptionStyle(AChart, cctTitle);
subtitleCaptionStyleIdx := TsChartStyleList(FChartStyleList).FindChartCaptionStyle(AChart, cctSubtitle);
+ legendStyleIdx := TsChartStyleList(FChartStyleList).FindChartLegendStyle(AChart);
+
ind := DupeString(' ', AIndent);
AppendToStream(AStream,
@@ -7235,12 +7288,15 @@ begin
ind + ' ' + LE +
// ch 4: style for element
+ GetChartLegendStyleAsXML(AChart, legendStyleIdx, AIndent + 2) +
+ {
ind + ' ' + LE +
ind + ' ' + LE +
ind + ' ' + LE +
ind + ' ' + LE +
ind + ' ' + LE +
+ }
// ch5: style for element
ind + ' ' + LE +