fpspreadsheet: ods reader and chart link support bitmap fill patterns.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9040 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz 2023-11-23 18:49:41 +00:00
parent f5e8a87ef1
commit d7354fa6d7
5 changed files with 306 additions and 49 deletions
components/fpspreadsheet
examples/visual/fpschart/fpschartlink
source

View File

@ -37,9 +37,10 @@ implementation
const
// FILE_NAME = '../../../other/chart/bars.ods';
// FILE_NAME = '../../../other/chart/area.ods';
FILE_NAME = '../../../other/chart/area-sameImg.ods';
// FILE_NAME = '../../../other/chart/pie.ods';
// FILE_NAME = '../../../other/chart/scatter.ods';
FILE_NAME = '../../../other/chart/regression.ods';
// FILE_NAME = '../../../other/chart/regression.ods';
{ TForm1 }

View File

@ -6,7 +6,7 @@ unit fpsChart;
interface
uses
Classes, SysUtils, Contnrs, fpsTypes, fpsUtils;
Classes, SysUtils, Contnrs, FPImage, fpsTypes, fpsUtils;
const
clsNoLine = -2;
@ -55,6 +55,7 @@ type
CenterX, CenterY: Double; // 0.0 ... 1.0
Angle: Double; // degrees
constructor Create;
destructor Destroy; override;
end;
TsChartGradientList = class(TFPObjectList)
@ -92,7 +93,7 @@ type
LineColor: TsColor;
LineDistance: Double; // mm
LineAngle: Double; // degrees
Filled: Boolean; // filled with background color or not
destructor Destroy; override;
end;
TsChartHatchList = class(TFPObjectList)
@ -101,19 +102,38 @@ type
procedure SetItem(AIndex: Integer; AValue: TsChartHatch);
public
function AddHatch(AName: String; AStyle: TsChartHatchStyle;
ALineColor: TsColor; ALineDistance, ALineAngle: Double; AFilled: Boolean): Integer;
ALineColor: TsColor; ALineDistance, ALineAngle: Double): Integer;
function FindByName(AName: String): TsChartHatch;
function IndexOfName(AName: String): Integer;
property Items[AIndex: Integer]: TsChartHatch read GetItem write SetItem; default;
end;
TsChartFillStyle = (cfsNoFill, cfsSolid, cfsGradient, cfsHatched);
TsChartImage = class
Name: String;
Image: TFPCustomImage;
Width, Height: Double; // mm
destructor Destroy; override;
end;
TsChartImagelist = class(TFPObjectList)
private
function GetItem(AIndex: Integer): TsChartImage;
procedure SetItem(AIndex: Integer; AValue: TsChartImage);
public
function AddImage(AName: String; AImage: TFPCustomImage): Integer;
function FindByName(AName: String): TsChartImage;
function IndexOfName(AName: String): Integer;
property Items[Aindex: Integer]: TsChartImage read GetItem write SetItem; default;
end;
TsChartFillStyle = (cfsNoFill, cfsSolid, cfsGradient, cfsHatched, cfsSolidHatched, cfsImage);
TsChartFill = class
Style: TsChartFillStyle;
Color: TsColor;
Gradient: Integer;
Hatch: Integer;
Image: Integer;
Transparency: Double; // 0.0 ... 1.0
end;
@ -519,6 +539,7 @@ type
FLineStyles: TsChartLineStyleList;
FGradients: TsChartGradientList;
FHatches: TsChartHatchList;
FImages: TsChartImageList;
function GetCategoryLabelRange: TsChartRange;
public
@ -596,6 +617,7 @@ type
property LineStyles: TsChartLineStyleList read FLineStyles;
property Gradients: TsChartGradientList read FGradients;
property Hatches: TsChartHatchList read FHatches;
property Images: TsChartImageList read FImages;
end;
TsChartList = class(TObjectList)
@ -621,6 +643,12 @@ begin
EndIntensity := 1.0;
end;
destructor TsChartGradient.Destroy;
begin
Name := '';
inherited;
end;
{ TsChartGradientList }
@ -729,10 +757,19 @@ begin
end;
{ TsChartHatch }
destructor TsChartHatch.Destroy;
begin
Name := '';
inherited;
end;
{ TsChartHatchList }
function TsChartHatchList.AddHatch(AName: String; AStyle: TsChartHatchStyle;
ALineColor: TsColor; ALineDistance, ALineAngle: Double; AFilled: Boolean): Integer;
ALineColor: TsColor; ALineDistance, ALineAngle: Double): Integer;
var
item: TsChartHatch;
begin
@ -750,7 +787,6 @@ begin
item.LineColor := ALineColor;
item.LineDistance := ALineDistance;
item.LineAngle := ALineAngle;
item.Filled := AFilled;
end;
function TsChartHatchList.FindByName(AName: String): TsChartHatch;
@ -783,6 +819,62 @@ begin
end;
{ TsChartImage }
destructor TsChartImage.Destroy;
begin
Name := '';
Image.Free;
inherited;
end;
{ TsChartImageList }
function TsChartImageList.AddImage(AName: String; AImage: TFPCustomImage): Integer;
var
item: TsChartImage;
begin
Result := IndexOfName(AName);
if Result = -1 then
begin
item := TsChartImage.Create;
item.Name := AName;
Result := inherited Add(item);
end;
Items[Result].Image := AImage;
end;
function TsChartImageList.FindByName(AName: String): TsChartImage;
var
idx: Integer;
begin
idx := IndexOfName(AName);
if idx <> -1 then
Result := Items[idx]
else
Result := nil;
end;
function TsChartImageList.GetItem(AIndex: Integer): TsChartImage;
begin
Result := TsChartImage(inherited Items[AIndex]);
end;
function TsChartImageList.IndexOfName(AName: String): Integer;
begin
for Result := 0 to Count-1 do
if SameText(Items[Result].Name, AName) then
exit;
Result := -1;
end;
procedure TsChartImageList.SetItem(AIndex: Integer; AValue: TsChartImage);
begin
inherited Items[AIndex] := AValue;
end;
{ TsChartLineStyle }
function TsChartLineStyle.GetID: String;
@ -1094,6 +1186,8 @@ end;
destructor TsChartSeries.Destroy;
begin
FLabelBackground.Free;
FLabelBorder.Free;
FLabelFont.Free;
FLine.Free;
FFill.Free;
@ -1511,6 +1605,7 @@ begin
FGradients := TsChartGradientList.Create;
FHatches := TsChartHatchList.Create;
FImages := TsChartImageList.Create;
FSheetIndex := 0;
FRow := 0;
@ -1576,6 +1671,7 @@ begin
FSubtitle.Free;
FFloor.Free;
FPlotArea.Free;
FImages.Free;
FHatches.Free;
FGradients.Free;
FLineStyles.Free;

View File

@ -5,7 +5,7 @@ unit fpsOpenDocumentChart;
interface
uses
Classes, SysUtils, StrUtils,
Classes, SysUtils, StrUtils, Contnrs, FPImage,
{$IF FPC_FULLVERSION >= 20701}
zipper,
{$ELSE}
@ -24,6 +24,7 @@ type
FPointSeparatorSettings: TFormatSettings;
FNumberFormatList: TStrings;
FPieSeriesStartAngle: Integer;
FStreamList: TFPObjectList;
function FindStyleNode(AStyleNodes: TDOMNode; AStyleName: String): TDOMNode;
procedure GetChartFillProps(ANode: TDOMNode; AChart: TsChart; AFill: TsChartFill);
procedure GetChartLineProps(ANode: TDOMNode; AChart: TsChart; ALine: TsChartLine);
@ -48,13 +49,15 @@ type
procedure ReadChartTitleProps(ANode, AStyleNode: TDOMNode; AChart: TsChart; ATitle: TsChartText);
procedure ReadChartTitleStyle(AStyleNode: TDOMNode; AChart: TsChart; ATitle: TsChartText);
procedure ReadObjectFillImages(ANode: TDOMNode; AChart: TsChart; ARoot: String);
procedure ReadObjectGradientStyles(ANode: TDOMNode; AChart: TsChart);
procedure ReadObjectHatchStyles(ANode: TDOMNode; AChart: TsChart);
procedure ReadObjectLineStyles(ANode: TDOMNode; AChart: TsChart);
protected
procedure ReadChartFiles(AStream: TStream; AFileList: String);
procedure ReadChart(AChartNode, AStyleNode: TDOMNode; AChart: TsChart);
procedure ReadObjectStyles(ANode: TDOMNode; AChart: TsChart);
procedure ReadObjectStyles(ANode: TDOMNode; AChart: TsChart; ARoot: String);
procedure ReadPictureFile(AStream: TStream; AFileName: String);
public
constructor Create(AReader: TsBasicSpreadReader); override;
destructor Destroy; override;
@ -303,6 +306,42 @@ begin
end;
{------------------------------------------------------------------------------}
{ internal picture storage }
{------------------------------------------------------------------------------}
type
TStreamItem = class
Name: String;
Stream: TStream;
destructor Destroy; override;
end;
destructor TStreamItem.Destroy;
begin
Stream.Free;
inherited;
end;
type
TStreamList = class(TFPObjectList)
public
function FindByName(AName: String): TStream;
end;
function TStreamList.FindByName(AName: String): TStream;
var
i: Integer;
begin
for i := 0 to Count-1 do
if TStreamItem(Items[i]).Name = AName then
begin
Result := TStreamItem(Items[i]).Stream;
exit;
end;
Result := nil;
end;
{------------------------------------------------------------------------------}
{ TsSpreadOpenDocChartReader }
{------------------------------------------------------------------------------}
@ -317,12 +356,14 @@ begin
FChartFiles := TStringList.Create;
FNumberFormatList := TsChartNumberFormatList.Create;
FNumberFormatList.NameValueSeparator := ':';
FStreamList := TStreamList.Create;
FPieSeriesStartAngle := 999;
end;
destructor TsSpreadOpenDocChartReader.Destroy;
begin
FStreamList.Free;
FNumberFormatList.Free;
FChartFiles.Free;
inherited;
@ -367,6 +408,9 @@ var
sc: String;
sn: String;
opacity: Double;
img: TsChartImage;
value: Double;
rel: Boolean;
begin
nodeName := ANode.NodeName;
@ -390,17 +434,41 @@ begin
end;
'hatch':
begin
AFill.Style := cfsHatched;
sc := GetAttrValue(ANode, 'draw:fill-hatch-solid');
if sc = 'true' then
AFill.Style := cfsSolidHatched
else
AFill.Style := cfsHatched;
sn := GetAttrValue(ANode, 'draw:fill-hatch-name');
if sn <> '' then
AFill.Hatch := AChart.Hatches.IndexOfName(UnASCIIName(sn));
sc := GetAttrValue(ANode, 'draw:fill-color');
if sc <> '' then
AFill.Color := HTMLColorStrToColor(sc);
sc := GetAttrValue(ANode, 'draw:fill-hatch-solid');
// AFill.Hatch.Filled := (sc = 'true'); // !!!! FIX ME: Filled should not be part of the style
end;
'bitmap':
begin
sn := GetAttrValue(ANode, 'draw:fill-image-name');
if sn <> '' then
begin
AFill.Style := cfsImage;
AFill.Image := AChart.Images.IndexOfName(UnASCIIName(sn));
img := AChart.Images[AFill.Image];
sc := GetAttrValue(ANode, 'draw:fill-image-width');
if (sc <> '') and EvalLengthStr(sc, value, rel) then
img.Width := value
else
img.Width := -1;
sc := GetAttrValue(ANode, 'draw:fill-image-height');
if (sc <> '') and EvalLengthStr(sc, value, rel) then
img.Height := value
else
img.Height := -1;
end else
AFill.Style := cfsSolid;
end;
end;
s := GetAttrValue(ANode, 'draw:opacity');
if (s <> '') and TryPercentStrToFloat(s, opacity) then
AFill.Transparency := 1.0 - opacity;
@ -770,8 +838,8 @@ procedure TsSpreadOpenDocChartReader.ReadChartFiles(AStream: TStream;
AFileList: String);
var
sa: TStringArray;
i: Integer;
fn: String;
i, p: Integer;
root, fn: String;
contentFile: String = '';
stylesFile: String = '';
XMLStream: TStream;
@ -789,7 +857,9 @@ begin
if fn = 'content.xml' then
contentFile := sa[i]
else if fn = 'styles.xml' then
stylesFile := sa[i];
stylesFile := sa[i]
else if pos('/Pictures/', sa[i]) > 0 then
ReadPictureFile(AStream, sa[i]);
end;
for i := 0 to TsWorkbook(Reader.Workbook).GetChartCount-1 do
@ -822,7 +892,9 @@ begin
if not ok then
raise Exception.Create('ODS chart reader: error reading styles file "' + stylesFile + '"');
ReadObjectStyles(doc.DocumentElement.FindNode('office:styles'), chart);
p := pos('/', stylesFile);
root := copy(stylesFile, 1, p);
ReadObjectStyles(doc.DocumentElement.FindNode('office:styles'), chart, root);
FreeAndNil(doc);
end;
@ -1421,7 +1493,7 @@ end;
{ Reads the styles stored in the Object files. }
procedure TsSpreadOpenDocChartReader.ReadObjectStyles(ANode: TDOMNode;
AChart: TsChart);
AChart: TsChart; ARoot: String);
var
nodeName: String;
begin
@ -1437,11 +1509,38 @@ begin
ReadObjectHatchStyles(ANode, AChart);
'draw:gradient': // gradient definition
ReadObjectGradientStyles(ANode, AChart);
'draw:fill-image':
ReadObjectFillImages(ANode, AChart, ARoot);
end;
ANode := ANode.NextSibling;
end;
end;
procedure TsSpreadOpenDocChartReader.ReadObjectFillImages(ANode: TDOMNode;
AChart: TsChart; ARoot: String);
var
styleName: String;
imgFileName: string;
imgStream: TStream;
img: TFPCustomImage;
begin
styleName := GetAttrValue(ANode, 'draw:display-name');
if styleName = '' then
styleName := GetAttrValue(ANode, 'draw:name');
imgFileName := GetAttrValue(ANode, 'xlink:href');
if imgFileName = '' then
exit;
imgStream := TStreamList(FStreamList).FindByName(ARoot + imgFileName);
if imgStream <> nil then
begin
img := TFPMemoryImage.Create(0, 0); // do not destroy this image here!
img.LoadFromStream(imgStream);
AChart.Images.AddImage(styleName, img);
end;
end;
procedure TsSpreadOpenDocChartReader.ReadObjectGradientStyles(ANode: TDOMNode;
AChart: TsChart);
var
@ -1547,8 +1646,7 @@ begin
else
hatchAngle := 0;
AChart.Hatches.AddHatch(styleName, hatchStyle, hatchColor, hatchDist, hatchAngle, false);
AChart.Hatches.AddHatch(styleName+' filled', hatchStyle, hatchColor, hatchDist, hatchAngle, true);
AChart.Hatches.AddHatch(styleName, hatchStyle, hatchColor, hatchDist, hatchAngle);
end;
{ Reads the line styles stored as "draw:stroke-dash" nodes in the chart's
@ -1591,6 +1689,31 @@ begin
AChart.LineStyles.Add(styleName, dots1Length, dots1, dots2Length, dots2, distance, rel1 or rel2 or relDist);
end;
procedure TsSpreadOpenDocChartReader.ReadPictureFile(AStream: TStream;
AFileName: String);
var
memStream: TMemoryStream;
img: TFPCustomImage;
item: TStreamItem;
begin
memStream := TMemoryStream.Create;
try
if UnzipToStream(AStream, AFileName, memStream) then
begin
memstream.Position := 0;
item := TStreamItem.Create;
item.Name := AFileName;
item.Stream := TMemoryStream.Create;
item.Stream.CopyFrom(memStream, memStream.Size);
item.Stream.Position := 0;
FStreamList.Add(item);
end;
finally
memstream.Free;
end;
end;
{------------------------------------------------------------------------------}
{ TsSpreadOpenDocChartWriter }
{------------------------------------------------------------------------------}
@ -1879,10 +2002,10 @@ begin
[ ASCIIName(gradient.Name) ]
);
end;
cfsHatched:
cfsHatched, cfsSolidHatched:
begin
hatch := AChart.Hatches[AFill.Hatch];
if hatch.Filled then
if AFill.Style = cfsSolidHatched then
fillStr := 'draw:fill-hatch-solid="true" ';
Result := Format(
'draw:fill="hatch" draw:fill-color="%s" ' +

View File

@ -123,8 +123,8 @@ function GetCellRangeString_R1C1(ASheet1, ASheet2: String;
function SheetNameNeedsQuotes(ASheet: String): Boolean;
// OpenDocument Syntax
function TryStrToCellRange_ODS(const AStr: String; out ASheet1, ASheet2: String;
out ARow1, ACol1, ARow2, ACol2: Cardinal; out AFlags: TsRelFlags): Boolean;
function TryStrToCellRange_ODS(const AStr: String; var ASheet1, ASheet2: String;
var ARow1, ACol1, ARow2, ACol2: Cardinal; var AFlags: TsRelFlags): Boolean;
function GetCellRangeString_ODS(ASheet1, ASheet2: String; ARow1, ACol1, ARow2, ACol2: Cardinal;
AFlags: TsRelFlags = rfAllRel; WithBrackets: Boolean = true): String; overload;
@ -1345,8 +1345,8 @@ end;
Extracts sheets names and cell coordinates from a cell range string in
OpenDocument syntax, e.g. "Table1.A1:Table2.B4"
-------------------------------------------------------------------------------}
function TryStrToCellRange_ODS(const AStr: String; out ASheet1, ASheet2: String;
out ARow1, ACol1, ARow2, ACol2: Cardinal; out AFlags: TsRelFlags): Boolean;
function TryStrToCellRange_ODS(const AStr: String; var ASheet1, ASheet2: String;
var ARow1, ACol1, ARow2, ACol2: Cardinal; var AFlags: TsRelFlags): Boolean;
var
p: Integer;
cell1Str, cell2Str: String;

View File

@ -18,9 +18,9 @@ interface
uses
// RTL/FCL
Classes, SysUtils, Types,
Classes, Contnrs, SysUtils, Types,
// LCL
LCLVersion, Forms, Controls, Graphics, Dialogs,
LCLVersion, Forms, Controls, Graphics, GraphUtil, Dialogs,
// TAChart
TATypes, TATextElements, TAChartUtils, TALegend, TACustomSource,
TACustomSeries, TASeries, TARadialSeries, TAFitUtils, TAFuncSeries,
@ -102,6 +102,7 @@ type
FWorkbookSource: TsWorkbookSource;
FWorkbook: TsWorkbook;
FWorkbookChartIndex: Integer;
FBrushBitmaps: TFPObjectList;
procedure SetChart(AValue: TChart);
procedure SetWorkbookChartIndex(AValue: Integer);
procedure SetWorkbookSource(AValue: TsWorkbookSource);
@ -120,12 +121,14 @@ type
procedure UpdateChartAxisLabels(AWorkbookChart: TsChart);
procedure UpdateChartBackground(AWorkbookChart: TsChart);
procedure UpdateBarSeries(AWorkbookChart: TsChart);
procedure UpdateChartBrush(AWorkbookFill: TsChartFill; ABrush: TBrush);
procedure UpdateChartBrush(AWorkbookChart: TsChart; AWorkbookFill: TsChartFill; ABrush: TBrush);
procedure UpdateChartLegend(AWorkbookLegend: TsChartLegend; ALegend: TChartLegend);
procedure UpdateChartPen(AWorkbookLine: TsChartLine; APen: TPen);
procedure UpdateChartSeriesMarks(AWorkbookSeries: TsChartSeries; AChartSeries: TChartSeries);
procedure UpdateChartTitle(AWorkbookTitle: TsChartText; AChartTitle: TChartTitle);
procedure UpdateAreaSeries(AWorkbookSeries: TsAreaSeries; AChartSeries: TAreaSeries);
procedure UpdateBarSeries(AWorkbookSeries: TsBarSeries; AChartSeries: TBarSeries);
procedure UpdateLineSeries(AWorkbookSeries: TsLineSeries; AChartSeries: TLineSeries);
procedure UpdatePieSeries(AWorkbookSeries: TsPieSeries; AChartSeries: TPieSeries);
procedure UpdateScatterSeries(AWorkbookSeries: TsScatterSeries; AChartSeries: TLineSeries);
@ -622,6 +625,7 @@ end;
constructor TsWorkbookChartLink.Create(AOwner: TComponent);
begin
inherited;
FBrushBitmaps := TFPObjectList.Create;
FWorkbookChartIndex := -1;
end;
@ -632,6 +636,7 @@ end;
destructor TsWorkbookChartLink.Destroy;
begin
if FWorkbookSource <> nil then FWorkbookSource.RemoveListener(self);
FBrushBitmaps.Free;
inherited;
end;
@ -668,16 +673,9 @@ begin
case ASeries.ChartType of
ctArea:
begin
UpdateChartBrush(ASeries.Fill, TAreaSeries(ser).AreaBrush);
UpdateChartPen(ASeries.Line, TAreaSeries(ser).AreaContourPen);
TAreaSeries(ser).AreaLinesPen.Style := psClear;
end;
UpdateAreaSeries(TsAreaSeries(ASeries), TAreaSeries(ser));
ctBar:
begin
UpdateChartBrush(ASeries.Fill, TBarSeries(ser).BarBrush);
UpdateChartPen(ASeries.Line, TBarSeries(ser).BarPen);
end;
UpdateBarSeries(TsBarSeries(ASeries), TBarSeries(ser));
ctLine:
UpdateLineSeries(TsLineSeries(ASeries), TLineSeries(ser));
ctScatter:
@ -863,6 +861,21 @@ begin
UpdateChart;
end;
procedure TsWorkbookChartLink.UpdateAreaSeries(AWorkbookSeries: TsAreaSeries;
AChartSeries: TAreaSeries);
begin
UpdateChartBrush(AWorkbookSeries.Chart, AWorkbookSeries.Fill, AChartSeries.AreaBrush);
UpdateChartPen(AWorkbookSeries.Line, AChartSeries.AreaContourPen);
AChartSeries.AreaLinesPen.Style := psClear;
end;
procedure TsWorkbookChartLink.UpdateBarSeries(AWorkbookSeries: TsBarSeries;
AChartSeries: TBarSeries);
begin
UpdateChartBrush(AWorkbookSeries.Chart, AWorkbookSeries.Fill, AChartSeries.BarBrush);
UpdateChartPen(AWorkbookSeries.Line, AChartSeries.BarPen);
end;
procedure TsWorkbookChartLink.UpdateChart;
var
ch: TsChart;
@ -1036,18 +1049,42 @@ begin
end;
end;
procedure TsWorkbookChartLink.UpdateChartBrush(AWorkbookFill: TsChartFill;
ABrush: TBrush);
procedure TsWorkbookChartLink.UpdateChartBrush(AWorkbookChart: TsChart;
AWorkbookFill: TsChartFill; ABrush: TBrush);
var
img: TsChartImage;
png: TCustomBitmap;
w, h, ppi: Integer;
begin
if (AWorkbookFill <> nil) and (ABrush <> nil) then
begin
ABrush.Color := Convert_sColor_to_Color(AWorkbookFill.Color);
if AWorkbookFill.Style = cfsNoFill then
ABrush.Style := bsClear
else
ABrush.Style := bsSolid;
// NOTE: TAChart will ignore gradient.
// To be completed: hatched filles.
case AWorkbookFill.Style of
cfsNoFill:
ABrush.Style := bsClear;
cfsSolid:
ABrush.Style := bsSolid;
cfsGradient:
ABrush.Style := bsSolid; // NOTE: TAChart cannot display gradients
cfsHatched, cfsSolidHatched:
ABrush.Style := bsSolid;
cfsImage:
begin
img := AWorkbookChart.Images[AWorkbookFill.Image];
if img <> nil then
begin
ppi := GetParentForm(FChart).PixelsPerInch;
w := mmToPx(img.Width, ppi);
h := mmToPx(img.Height, ppi);
png := TPortableNetworkGraphic.Create;
png.Assign(img.Image);
ScaleImg(png, w, h);
FBrushBitmaps.Add(png);
ABrush.Bitmap := png;
end else
ABrush.Style := bsSolid;
end;
end;
end;
end;
@ -1065,7 +1102,7 @@ begin
begin
Convert_sFont_to_Font(AWorkbookLegend.Font, ALegend.Font);
UpdateChartPen(AWorkbookLegend.Border, ALegend.Frame);
UpdateChartBrush(AWorkbookLegend.Background, ALegend.BackgroundBrush);
UpdateChartBrush(AWorkbookLegend.Chart, AWorkbookLegend.Background, ALegend.BackgroundBrush);
ALegend.Frame.Visible := (ALegend.Frame.Style <> psClear);
ALegend.Alignment := LEG_POS[AWorkbookLegend.Position];
ALegend.UseSidebar := not AWorkbookLegend.CanOverlapPlotArea;
@ -1137,7 +1174,7 @@ begin
end;
UpdateChartPen(AWorkbookSeries.LabelBorder, AChartSeries.Marks.Frame);
UpdateChartBrush(AWorkbookSeries.LabelBackground, AChartSeries.Marks.LabelBrush);
UpdateChartBrush(AWorkbookSeries.Chart, AWorkbookSeries.LabelBackground, AChartSeries.Marks.LabelBrush);
end;
{@@ Updates title and footer of the linked TAChart.
@ -1153,7 +1190,7 @@ begin
AChartTitle.WordWrap := true;
Convert_sFont_to_Font(AWorkbookTitle.Font, AChartTitle.Font);
UpdateChartPen(AWorkbookTitle.Border, AChartTitle.Frame);
UpdateChartBrush(AWorkbookTitle.Background, AChartTitle.Brush);
UpdateChartBrush(AWorkbookTitle.Chart, AWorkbookTitle.Background, AChartTitle.Brush);
AChartTitle.Font.Orientation := round(AWorkbookTitle.RotationAngle * 10);
AChartTitle.Frame.Visible := (AChartTitle.Frame.Style <> psClear);
end;
@ -1185,7 +1222,7 @@ begin
AChartSeries.ShowPoints := AWorkbookSeries.ShowSymbols;
if AChartSeries.ShowPoints then
begin
UpdateChartBrush(AWorkbookSeries.Fill, AChartSeries.Pointer.Brush);
UpdateChartBrush(AWorkbookSeries.Chart, AWorkbookSeries.Fill, AChartSeries.Pointer.Brush);
AChartSeries.Pointer.Pen.Color := AChartSeries.LinePen.Color;
AChartSeries.Pointer.Style := POINTER_STYLES[AWorkbookSeries.Symbol];
AChartSeries.Pointer.HorizSize := mmToPx(AWorkbookSeries.SymbolWidth, ppi);