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:
parent
f5e8a87ef1
commit
d7354fa6d7
components/fpspreadsheet
examples/visual/fpschart/fpschartlink
source
@ -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 }
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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" ' +
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user