Difference between revisions of "FPReport Custom elements"

From Lazarus wiki
(Create a new element class)
(Create a new element class)
Line 26: Line 26:
 
The element itself must only know how to read/write its properties from/to a report streamer, and how to copy properties to another instance.
 
The element itself must only know how to read/write its properties from/to a report streamer, and how to copy properties to another instance.
  
 +
=== Copying properties for cloning ===
 
Copying properties to another instance is done in the usual fashion, using the '''Assign''' method:
 
Copying properties to another instance is done in the usual fashion, using the '''Assign''' method:
 
<syntaxhighlight>
 
<syntaxhighlight>
Line 45: Line 46:
 
end;
 
end;
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
This is important because during layouting, the assign method is used to clone the design elements before layouting them on the page.
  
Writing properties to the  streamer can be done in the WriteElement method, or the DoWriteLocalProperties method:
+
=== Writing properties to a stream ===
 +
When saving a report to file, all elements are written to a stream using a '''TFPReportStreamer''' class. (unit ''fpreportstreamer'')
 +
 
 +
Writing properties to the  streamer must be implemented in the '''WriteElement''' method, or the '''DoWriteLocalProperties''' method:
 
<syntaxhighlight>
 
<syntaxhighlight>
 
procedure TReportPolygon.DoWriteLocalProperties(AWriter: TFPReportStreamer;
 
procedure TReportPolygon.DoWriteLocalProperties(AWriter: TFPReportStreamer;
Line 73: Line 78:
 
end;
 
end;
 
</syntaxhighlight>
 
</syntaxhighlight>
The AOriginal is meant for a rendered element, do be able to write only properties  
+
The WriteElement can be called during layouting. During layouting, a copy is made of each element,
that differ from the original element, to keep the stream minimal in size
+
and the propertie values can differ from the values set during design.
(similar to the default clause in a published property declaration).
+
To minimize the size of the stream, only a diff may be written:
 +
'''AOriginal''' is the element as designed, and
 +
element, do be able to write only properties that have changed.
 +
 
 +
=== Reading properties from a stream ===
 +
When the report design is read from a stream, every element is read from stream.
 +
This happens using the same '''TFPReportStreamer''' class (unit ''fpreportstreamer'') as is used to write the element.
 +
 
 +
The ReadElement method is responsible for reading the element's design from stream:
 +
<syntaxhighlight>
 +
procedure TReportPolygon.ReadElement(AReader: TFPReportStreamer);
 +
begin
 +
  inherited ReadElement(AReader);
 +
  Color:= AReader.ReadInteger('Color', clBlack);
 +
  Corners:=AReader.ReadInteger('Corners',3);
 +
  LineWidth:=AReader.ReadInteger('LineWidth',1);
 +
  RotateAngle:=AReader.ReadFloat('RotateAngle',0);
 +
end;
 +
</syntaxhighlight>

Revision as of 08:37, 26 June 2017

FPReport contains support for 4 basic reporting elements:

  • Memo
  • Shape
  • Image
  • Checkbox

While these will get you a long way, sometimes something extra is needed.

On this page we explain how to create a new element.

We'll take the sample TReportPolygon as an example.

Create a new element class

Any printable element must descend from TFPReportElement. It must expose published properties which allow the user to control behaviour of the element.

TReportPolygon = class(TFPReportElement)
Published
  Property Corners : Cardinal Read FCorners Write SetCorners;
  Property LineWidth : Cardinal Read FLineWidth Write SetCLineWidth;
  Property Color : TFPReportColor Read FColor Write FColor;
  // In degrees
  Property RotateAngle : Double Read FRotateAngle Write FRotateAngle;
end;

The element itself must only know how to read/write its properties from/to a report streamer, and how to copy properties to another instance.

Copying properties for cloning

Copying properties to another instance is done in the usual fashion, using the Assign method:

procedure TReportPolygon.Assign(Source: TPersistent);

Var
  P : TReportPolygon;

begin
  if (Source is TReportPolygon) then
    begin
    P:=Source as TReportPolygon;
    Corners:=P.Corners;
    Color:=P.Color;
    LineWidth:=P.LineWidth;
    RotateAngle:=P.RotateAngle;
    end;
  inherited Assign(Source);
end;

This is important because during layouting, the assign method is used to clone the design elements before layouting them on the page.

Writing properties to a stream

When saving a report to file, all elements are written to a stream using a TFPReportStreamer class. (unit fpreportstreamer)

Writing properties to the streamer must be implemented in the WriteElement method, or the DoWriteLocalProperties method:

procedure TReportPolygon.DoWriteLocalProperties(AWriter: TFPReportStreamer;
  AOriginal: TFPReportElement);

Var
  P : TReportPolygon;

begin
  inherited DoWriteLocalProperties(AWriter, AOriginal);
  if AOriginal is TReportPolygon then
    begin
    P:=AOriginal as TReportPolygon;
    AWriter.WriteIntegerDiff('Color', Color, P.Color);
    AWriter.WriteIntegerDiff('Corners',Corners,P.Color);
    AWriter.WriteIntegerDiff('LineWidth',LineWidth,P.LineWidth);
    AWriter.WriteFloatDiff('RotateAngle',RotateAngle,P.RotateAngle);
    end
  else
    begin
    AWriter.WriteInteger('Color', Color);
    AWriter.WriteInteger('Corners',Corners);
    AWriter.WriteInteger('LineWidth',LineWidth);
    AWriter.WriteFloat('RotateAngle',RotateAngle);
    end;
end;

The WriteElement can be called during layouting. During layouting, a copy is made of each element, and the propertie values can differ from the values set during design. To minimize the size of the stream, only a diff may be written: AOriginal is the element as designed, and element, do be able to write only properties that have changed.

Reading properties from a stream

When the report design is read from a stream, every element is read from stream. This happens using the same TFPReportStreamer class (unit fpreportstreamer) as is used to write the element.

The ReadElement method is responsible for reading the element's design from stream:

procedure TReportPolygon.ReadElement(AReader: TFPReportStreamer);
begin
  inherited ReadElement(AReader);
  Color:= AReader.ReadInteger('Color', clBlack);
  Corners:=AReader.ReadInteger('Corners',3);
  LineWidth:=AReader.ReadInteger('LineWidth',1);
  RotateAngle:=AReader.ReadFloat('RotateAngle',0);
end;