YOUSEFUL / DELPHI / COMPONENTS

TAtlasPlot

VCL chart control with line, step, area, bar, point and pie series, zoom, hit testing and PNG, SVG, EMF and CSV export.

Visual control Palette: Atlas Plot Unit Atlas.Plot · Inherits TCustomControl · Product Atlas Plot

Description

The one component of Atlas Plot (palette page Atlas Plot). A chart holds a collection of series (TAtlasPlotSeries) drawn against two axes, ArgumentAxis and ValueAxis (TAtlasPlotAxis), with a title, a footnote and a legend.

Wrap bulk changes in BeginUpdate / EndUpdate; every point added otherwise invalidates the chart and notifies its listeners. The control is a VCL control with no locking: create and change it on the main thread. A chart without a parent (TAtlasPlot.Create(nil)) renders and exports in a console program, as the PlotToPng sample shows.

Not implemented: data-aware series bound to a TDataSet, secondary axes, multiple panes, 3D, gradients, animation, further series kinds (bubble, candle, gauge, polar), a print dialog or preview, keyboard navigation, and FMX or non-Windows platforms. The control runs on VCL for Win32 and Win64.

Members

MemberKindWhat it does
CreateconstructorCreates an empty chart: no series, white background (Color = clWhite), 480 x 320 pixels, legend on the right, zoom and pan allowed, double buffered.
DestroydestructorFrees the series, both axes and the change-listener list.
BeginUpdatemethodStarts a batch.
EndUpdatemethodCloses a batch.
AddChangeListenermethodRegisters a method that is called, with the chart as Sender, after any change to series, points, axes, titles, legend, rotation, stacking, donut size or zoom; once per BeginUpdate / EndUpdate batch.
RemoveChangeListenermethodUnregisters a listener added with AddChangeListener.
AddSeriesmethodAppends a new series to Series and returns it.
ClearmethodRemoves every series and ends any zoom.
SeriesColormethodThe colour series Index is drawn in: its own Color, or when that is clDefault, entry Index mod 10 of a fixed ten-colour palette that starts blue, orange, green, red.
AddTrendLinemethodAdds a straight least-squares line fitted to the values of Source and returns it: a pkLine series titled Source.Title + ' trend' with two points, at the smallest and largest argument of Source.
AddMovingAveragemethodAdds a trailing simple moving average of Source and returns it: a pkLine series titled Format('%s avg(%d)', [Title, Period]).
RendermethodDraws the whole chart (background, title, footnote, legend, axes, series and marks) onto any drawing surface inside Bounds.
RenderTomethodDraws the chart onto any VCL canvas inside Bounds: a bitmap, a metafile canvas, Printer.Canvas, or the canvas of another control.
ZoomTomethodShows exactly the given window, in data units, on both axes (no rounding to whole steps), sets Zoomed, repaints and fires OnZoom.
ResetZoommethodEnds the zoom, returning to the automatic or manual axis ranges, repaints and fires OnZoom.
PanBymethodMoves the visible window as if the content were dragged by DeltaX, DeltaY pixels: a positive DeltaX reveals lower arguments, a positive DeltaY moves the content down.
ZoomAroundmethodScales the visible window by Factor about the pixel X, Y, keeping the data value under that pixel in place: 0.5 halves the window, 2 doubles it.
HitTestmethodReports which point is drawn at pixel X, Y of the most recent render.
ValuesToPixelmethodConverts data values to a pixel of the most recent render, honouring logarithmic, inverted and rotated axes.
PixelToValuesmethodConverts a pixel of the most recent render back to data values (Arg on the argument axis, Val on the value axis); the inverse of ValuesToPixel.
CreateBitmapmethodRenders the chart into a new 24-bit bitmap of the given size and returns it; the caller frees it.
ToSVGmethodRenders the chart as an SVG document of the given size and returns the text (declared UTF-8).
SaveToFilemethodWrites the chart to a file whose extension selects the format: .png, .bmp, .emf (enhanced metafile) and .svg render the chart at AWidth x AHeight pixels (0 means the control's current Width or Height); .csv writes DataToCSV as UTF-8 without BOM and ignores the size.
CopyToClipboardmethodPlaces a bitmap of the chart, at the control's current size, on the clipboard.
DataToCSVmethodReturns every point as CSV text with CRLF line ends.
DataFromCSVmethodReplaces every series with the data in Text, in the format DataToCSV writes.
ZoomedpropertyTrue while a zoom window set by ZoomTo, the mouse, the wheel or PanBy is in effect.
PlotRectpropertyThe rectangle, in pixels of the most recent render, that holds the series (inside the axes).
SeriespropertyThe series collection, drawn in order (later series on top).
ArgumentAxispropertyThe axis of the point arguments (X): horizontal, or vertical when Rotated is True.
ValueAxispropertyThe axis of the point values (Y): vertical, or horizontal when Rotated is True.
TitlepropertyBold heading centred above the chart; empty means no heading and no space reserved.
FootnotepropertyLine of text centred at the bottom of the chart; empty means none.
LegendVisiblepropertyShows the legend.
LegendPositionpropertySide of the chart the legend occupies.
RotatedpropertySwaps the axes: the argument axis runs vertically (bottom to top) and the value axis horizontally, which turns bars into horizontal bars and draws lines sideways.
StackingpropertyStacks bars on bars and areas on areas; lines, steps and points never stack.
DonutPercentpropertySize of the hole in a pie chart, as a percentage of the radius: 0 draws a full pie, 45 a typical donut.
AllowZoompropertyEnables mouse zooming: drag a rectangle with the left button (more than 4 pixels each way), turn the wheel over the plot, double-click to reset.
AllowPanpropertyEnables panning by dragging with the right button inside the plot.
OnPointClickeventFires when the left button is released over a bar, vertex, point or slice (as HitTest sees it) and the press did not become a zoom drag.
OnZoomeventFires after every change of the zoom window: ZoomTo, a mouse zoom, each step of a pan, a wheel step, and ResetZoom when the chart was zoomed.
AlignpropertyStandard VCL alignment, published.
AnchorspropertyStandard VCL anchors, published.
ColorpropertyBackground of the whole chart and the plot area.
ConstraintspropertyStandard VCL size constraints, published.
EnabledpropertyStandard VCL property; a disabled chart still paints but receives no mouse input.
FontpropertyFont of every text.
ParentFontpropertyStandard VCL property: take the parent's font.
ParentShowHintpropertyStandard VCL property, published.
PopupMenupropertyStandard VCL popup menu.
ShowHintpropertyStandard VCL hint display.
TabOrderpropertyStandard VCL tab order.
TabStoppropertyWhen True, clicking the chart gives it the focus, which also makes it the target of wheel messages.
VisiblepropertyStandard VCL visibility.
OnClickeventStandard VCL click: fires when the left button is released inside the control, before OnPointClick, also at the end of a zoom drag.
OnDblClickeventStandard VCL double click.
OnMouseDowneventStandard VCL mouse event; the chart's own zoom and pan handling runs as well.
OnMouseMoveeventStandard VCL mouse event.
OnMouseUpeventStandard VCL mouse event; fires before OnPointClick.
OnResizeeventStandard VCL resize event.

Constructors

Create constructor

constructor Create(AOwner: TComponent); override;

Creates an empty chart: no series, white background (Color = clWhite), 480 x 320 pixels, legend on the right, zoom and pan allowed, double buffered. Pass nil as owner for an off-screen chart that you free yourself; such a chart can still render, export and hit-test.

pascal
Plot := TAtlasPlot.Create(nil);
try
  Plot.AddSeries('Load').AddY(3);
  Plot.SaveToFile('load.png', 640, 400);
finally
  Plot.Free;
end;

Destructors

Destroy destructor

destructor Destroy; override;

Frees the series, both axes and the change-listener list. Listeners are not notified during destruction.

Properties

Zoomed property

property Zoomed: Boolean read FZoomed;

True while a zoom window set by ZoomTo, the mouse, the wheel or PanBy is in effect. ResetZoom, Clear, DataFromCSV and changing Stacking end it.

PlotRect property

property PlotRect: TRect read FPlot;

The rectangle, in pixels of the most recent render, that holds the series (inside the axes). Empty when that render drew no cartesian plot, for example a pie.

pascal
Plot.ZoomAround(Plot.PlotRect.CenterPoint.X, Plot.PlotRect.CenterPoint.Y, 0.5);

Series property

property Series: TAtlasPlotSeriesList read FSeries write SetSeries;

The series collection, drawn in order (later series on top). Editable in the Object Inspector; points persist in the form file. Assigning another list copies its series. See TAtlasPlotSeriesList.

pascal
Plot.Series.Find('Revenue').Visible := False;

ArgumentAxis property

property ArgumentAxis: TAtlasPlotAxis read FArgumentAxis write SetArgumentAxis;

The axis of the point arguments (X): horizontal, or vertical when Rotated is True. Automatic ranges keep the exact data span (plus half a bar slot on each side when there are bars). When the first visible series has point texts and the axis is neither date/time nor logarithmic, those texts replace the numeric ticks. Assigning another axis copies its settings.

pascal
Plot.ArgumentAxis.DateTime := True;

ValueAxis property

property ValueAxis: TAtlasPlotAxis read FValueAxis write SetValueAxis;

The axis of the point values (Y): vertical, or horizontal when Rotated is True. Automatic ranges are rounded outward to whole tick steps (to whole decades when logarithmic). A zero line is drawn when zero lies inside the range. Assigning another axis copies its settings.

pascal
Plot.ValueAxis.SetRange(0, 100);

Title property

property Title: string read FTitle write SetTitle;

Bold heading centred above the chart; empty means no heading and no space reserved.

pascal
Plot.Title := 'Sales 2026';

Footnote property

property Footnote: string read FFootnote write SetFootnote;

Line of text centred at the bottom of the chart; empty means none.

pascal
Plot.Footnote := 'Source: order system';

LegendVisible property

property LegendVisible: Boolean read FLegendVisible write SetLegendVisible default True;

Shows the legend. It lists every visible non-pie series by Title (or "Series N"), or for a pie chart every drawn slice by point Text (or its argument). Captions that do not fit are shortened with "...".

pascal
Plot.LegendVisible := False;

LegendPosition property

property LegendPosition: TAtlasPlotLegendPosition read FLegendPosition write SetLegendPosition default lpRight;

Side of the chart the legend occupies. On the left or right it is one column, at most two fifths of the width, and entries that do not fit the height are left out. At the top or bottom entries flow into at most three centred rows; the rest are left out. See TAtlasPlotLegendPosition.

pascal
Plot.LegendPosition := lpBottom;

Rotated property

property Rotated: Boolean read FRotated write SetRotated default False;

Swaps the axes: the argument axis runs vertically (bottom to top) and the value axis horizontally, which turns bars into horizontal bars and draws lines sideways. Set ArgumentAxis.Inverted as well to list categories from the top down.

pascal
Plot.Rotated := True;
Plot.ArgumentAxis.Inverted := True;

Stacking property

property Stacking: TAtlasPlotStacking read FStacking write SetStacking default psNone;

Stacks bars on bars and areas on areas; lines, steps and points never stack. Points stack when their arguments are equal; positive and negative values build separate stacks from zero. psStacked100 scales each argument's stack to 100 % of the sum of absolute values. Hidden series leave the stack. Changing it ends any zoom. See TAtlasPlotStacking.

pascal
Plot.Stacking := psStacked100;

DonutPercent property

property DonutPercent: Integer read FDonutPercent write SetDonutPercent default 0;

Size of the hole in a pie chart, as a percentage of the radius: 0 draws a full pie, 45 a typical donut. Values are clamped to 0..90. Has no effect on cartesian charts.

pascal
Plot.DonutPercent := 45;

AllowZoom property

property AllowZoom: Boolean read FAllowZoom write FAllowZoom default True;

Enables mouse zooming: drag a rectangle with the left button (more than 4 pixels each way), turn the wheel over the plot, double-click to reset. ZoomTo, ZoomAround and ResetZoom work regardless.

pascal
Plot.AllowZoom := False;

AllowPan property

property AllowPan: Boolean read FAllowPan write FAllowPan default True;

Enables panning by dragging with the right button inside the plot. PanBy works regardless. Consider switching it off when the chart has a PopupMenu, since both use the right button.

pascal
Plot.AllowPan := False;

Align property

property Align;

Standard VCL alignment, published.

Anchors property

property Anchors;

Standard VCL anchors, published.

Color property

property Color default clWhite;

Background of the whole chart and the plot area. It also outlines pie slices and point dots, and area fills are the series colour mixed 55 % toward it. Default clWhite.

pascal
Plot.Color := clBtnFace;

Constraints property

property Constraints;

Standard VCL size constraints, published.

Enabled property

property Enabled;

Standard VCL property; a disabled chart still paints but receives no mouse input.

Font property

property Font;

Font of every text. All spacing derives from its line height, so a larger font gives a roomier layout and the chart follows DPI changes without separate scaling. The title uses it in bold; its colour is the text colour, also in SVG output.

pascal
Plot.Font.Size := 11;

ParentFont property

property ParentFont;

Standard VCL property: take the parent's font.

ParentShowHint property

property ParentShowHint;

Standard VCL property, published.

PopupMenu property

property PopupMenu;

Standard VCL popup menu. The right button also pans when AllowPan is True.

ShowHint property

property ShowHint;

Standard VCL hint display. The chart has no built-in point hints; set the inherited Hint from OnMouseMove with HitTest.

TabOrder property

property TabOrder;

Standard VCL tab order.

TabStop property

property TabStop;

When True, clicking the chart gives it the focus, which also makes it the target of wheel messages. There is no keyboard navigation.

Visible property

property Visible;

Standard VCL visibility. A hidden chart can still render and export.

Events

OnPointClick event

property OnPointClick: TAtlasPlotPointEvent read FOnPointClick write FOnPointClick;

Fires when the left button is released over a bar, vertex, point or slice (as HitTest sees it) and the press did not become a zoom drag. Receives the series and the point index. Fires after OnClick. See TAtlasPlotPointEvent.

pascal
Plot.OnPointClick := PointClicked;

OnZoom event

property OnZoom: TNotifyEvent read FOnZoom write FOnZoom;

Fires after every change of the zoom window: ZoomTo, a mouse zoom, each step of a pan, a wheel step, and ResetZoom when the chart was zoomed. Read Zoomed and the axes' ViewMin/ViewMax (after the next render) to follow it.

pascal
Plot.OnZoom := ZoomChanged;

OnClick event

property OnClick;

Standard VCL click: fires when the left button is released inside the control, before OnPointClick, also at the end of a zoom drag. Use ScreenToClient(Mouse.CursorPos) with PixelToValues or ValuesToPixel to relate it to the data.

OnDblClick event

property OnDblClick;

Standard VCL double click. It fires before the chart resets the zoom (when AllowZoom is True).

OnMouseDown event

property OnMouseDown;

Standard VCL mouse event; the chart's own zoom and pan handling runs as well.

OnMouseMove event

property OnMouseMove;

Standard VCL mouse event. Combine it with PixelToValues and HitTest for a live read-out of the position under the cursor.

OnMouseUp event

property OnMouseUp;

Standard VCL mouse event; fires before OnPointClick.

OnResize event

property OnResize;

Standard VCL resize event. The chart repaints itself at the new size.

Methods

BeginUpdate method

procedure BeginUpdate;

Starts a batch. While at least one batch is open, series, axis and layout changes neither repaint the chart nor notify change listeners. Calls nest; always pair with EndUpdate in a try ... finally block. OnZoom still fires inside a batch.

pascal
Plot.BeginUpdate;
try
  Plot.Title := 'Regions';
  Sales.AddY(42, 'North');
  Sales.AddY(35, 'South');
finally
  Plot.EndUpdate; // one repaint
end;

EndUpdate method

procedure EndUpdate;

Closes a batch. When the outermost batch closes the chart repaints once and every change listener is called once. An EndUpdate without a matching BeginUpdate does nothing.

AddChangeListener method

procedure AddChangeListener(const Listener: TNotifyEvent);

Registers a method that is called, with the chart as Sender, after any change to series, points, axes, titles, legend, rotation, stacking, donut size or zoom; once per BeginUpdate / EndUpdate batch. Font and Color changes repaint without notifying. Adding the same method twice registers it once. Intended for companion controls (a data grid showing the chart, a summary label). A listener may remove itself while being called.

pascal
Plot.AddChangeListener(Watcher.ChartChanged);

RemoveChangeListener method

procedure RemoveChangeListener(const Listener: TNotifyEvent);

Unregisters a listener added with AddChangeListener. Call it before the listening object is freed. Removing a method that is not registered does nothing.

pascal
Plot.RemoveChangeListener(Watcher.ChartChanged);

AddSeries method

function AddSeries(const Title: string; Kind: TAtlasPlotKind = pkLine; Color: TColor = clDefault): TAtlasPlotSeries;

Appends a new series to Series and returns it. Title appears in the legend and in CSV output. Kind selects line, step, area, bar, point or pie drawing (see TAtlasPlotKind). clDefault takes the next colour of the built-in palette (see SeriesColor). The chart owns the series; do not free it yourself unless you mean to remove it.

pascal
Sales := Plot.AddSeries('2026', pkBar);
Orders := Plot.AddSeries('Orders', pkLine, clMaroon);

Clear method

procedure Clear;

Removes every series and ends any zoom. Axis settings, titles, stacking and the other layout properties are kept. References to the removed series become invalid.

pascal
Plot.Clear;

SeriesColor method

function SeriesColor(Index: Integer): TColor;

The colour series Index is drawn in: its own Color, or when that is clDefault, entry Index mod 10 of a fixed ten-colour palette that starts blue, orange, green, red. Pie slices use the same palette by point index instead.

pascal
Swatch.Brush.Color := Plot.SeriesColor(0);

AddTrendLine method

function AddTrendLine(Source: TAtlasPlotSeries): TAtlasPlotSeries;

Adds a straight least-squares line fitted to the values of Source and returns it: a pkLine series titled Source.Title + ' trend' with two points, at the smallest and largest argument of Source. Gaps are ignored. The result is a snapshot: it does not follow later edits of Source; delete it and add it again after changing the data.

Raises EAtlasPlotError when Source is nil or belongs to another chart, has fewer than two values, or all its values share one argument. A failed call adds nothing.

pascal
Plot.AddTrendLine(Sales).LineWidth := 1;

AddMovingAverage method

function AddMovingAverage(Source: TAtlasPlotSeries; Period: Integer): TAtlasPlotSeries;

Adds a trailing simple moving average of Source and returns it: a pkLine series titled Format('%s avg(%d)', [Title, Period]). Each output point sits at the argument of the value that completes its window, so the result has ValueCount - Period + 1 points. Gaps are skipped, not reset: the window runs across them and the average does not break. A snapshot, like AddTrendLine.

Raises EAtlasPlotError when Source is nil or belongs to another chart, or when Period is below 1 or above Source.ValueCount.

pascal
Plot.AddMovingAverage(Daily, 7).LineWidth := 3;

Render method

procedure Render(Surface: TAtlasPlotSurface; const Bounds: TRect);

Draws the whole chart (background, title, footnote, legend, axes, series and marks) onto any drawing surface inside Bounds. This is the single layout path every output uses; implement TAtlasPlotSurface to draw somewhere new, or pass a TAtlasCanvasSurface or TAtlasSvgSurface to place several charts on one page.

Afterwards PlotRect, HitTest, ValuesToPixel, PixelToValues and the axes' ViewMin/ViewMax describe this render. Unlike RenderTo, CreateBitmap, ToSVG and SaveToFile, Render does not restore the on-screen layout afterwards; call Repaint on a visible chart when you are done. Raises EAtlasPlotError when Surface is nil. A target too small for a plot draws only the background, title and footnote.

RenderTo method

procedure RenderTo(Target: TCanvas; const Bounds: TRect);

Draws the chart onto any VCL canvas inside Bounds: a bitmap, a metafile canvas, Printer.Canvas, or the canvas of another control. Text sizes follow the chart's Font as the target canvas measures it. When the chart has a window, its on-screen layout is re-run afterwards so mouse hit testing keeps matching what the user sees.

pascal
Plot.RenderTo(Bitmap.Canvas, Rect(0, 0, Bitmap.Width, Bitmap.Height));

ZoomTo method

procedure ZoomTo(const ArgMin, ArgMax, ValMin, ValMax: Double);

Shows exactly the given window, in data units, on both axes (no rounding to whole steps), sets Zoomed, repaints and fires OnZoom. While zoomed, the window replaces both the data range and any manual axis range.

Raises EAtlasPlotError and changes nothing when a value is not finite or beyond 1E100, when a minimum is not below its maximum, when a logarithmic axis would reach zero or below, or when a span is smaller than about 1E-12 of its magnitude. With psStacked100 the value window is in percent.

pascal
Plot.ZoomTo(2, 6, 0, 40);

ResetZoom method

procedure ResetZoom;

Ends the zoom, returning to the automatic or manual axis ranges, repaints and fires OnZoom. Does nothing, and fires nothing, when the chart is not zoomed. Double-clicking the chart calls it when AllowZoom is True.

pascal
if Plot.Zoomed then Plot.ResetZoom;

PanBy method

procedure PanBy(DeltaX, DeltaY: Integer);

Moves the visible window as if the content were dragged by DeltaX, DeltaY pixels: a positive DeltaX reveals lower arguments, a positive DeltaY moves the content down. Works against the most recent render and leaves the chart zoomed. Does nothing when that render had no cartesian plot (nothing drawn yet, a pie, or a target too small). Can raise EAtlasPlotError at the edge of the supported range; right-drag panning ignores that error.

pascal
Plot.PanBy(Plot.PlotRect.Width div 2, 0);

ZoomAround method

procedure ZoomAround(X, Y: Integer; const Factor: Double);

Scales the visible window by Factor about the pixel X, Y, keeping the data value under that pixel in place: 0.5 halves the window, 2 doubles it. The mouse wheel uses 0.8 (wheel up) and 1.25 (wheel down). Works against the most recent render and does nothing without a cartesian plot. Raises EAtlasPlotError when Factor is not a positive finite number or the resulting window is invalid.

pascal
Plot.ZoomAround(Plot.PlotRect.CenterPoint.X, Plot.PlotRect.CenterPoint.Y, 0.5);

HitTest method

function HitTest(X, Y: Integer; out SeriesIndex, PointIndex: Integer): Boolean;

Reports which point is drawn at pixel X, Y of the most recent render. A bar answers inside its rectangle; a line, step, area or point vertex within 5 pixels (or its dot radius plus 2); a pie or donut slice inside its ring segment. Where regions overlap, the one drawn last wins. Areas answer only at their vertices, not across the fill. Points outside the plot area (beyond a manual range or zoom window) are not hit. Returns False with both indexes -1 when nothing is there.

pascal
if Plot.HitTest(X, Y, SeriesIndex, PointIndex) then
  Caption := Plot.Series[SeriesIndex].Title;

ValuesToPixel method

function ValuesToPixel(const Arg, Val: Double; out Pixel: TPoint): Boolean;

Converts data values to a pixel of the most recent render, honouring logarithmic, inverted and rotated axes. Returns False (and Pixel = (0, 0)) when that render had no cartesian plot, for example before the first paint or for a pie. Values outside the visible range map outside PlotRect. For stacked series pass the stacked total, not the point's own value, to reach the top of its bar or area.

pascal
if Plot.ValuesToPixel(1, 10, Pixel) then
  Caption := Format('%d, %d', [Pixel.X, Pixel.Y]);

PixelToValues method

function PixelToValues(X, Y: Integer; out Arg, Val: Double): Boolean;

Converts a pixel of the most recent render back to data values (Arg on the argument axis, Val on the value axis); the inverse of ValuesToPixel. Returns False, with both values 0, when that render had no cartesian plot. Pixels outside PlotRect are extrapolated. With a date/time axis Arg is a TDateTime.

pascal
if Plot.PixelToValues(X, Y, Arg, Val) then
  Caption := Format('x = %.2f, y = %.2f', [Arg, Val]);

CreateBitmap method

function CreateBitmap(AWidth, AHeight: Integer): Vcl.Graphics.TBitmap;

Renders the chart into a new 24-bit bitmap of the given size and returns it; the caller frees it. Each side must be 1 to 16384 pixels, otherwise EAtlasPlotError is raised. Does not change the on-screen layout.

pascal
Bitmap := Plot.CreateBitmap(800, 500);
try
  Image1.Picture.Assign(Bitmap);
finally
  Bitmap.Free;
end;

ToSVG method

function ToSVG(AWidth, AHeight: Integer): string;

Renders the chart as an SVG document of the given size and returns the text (declared UTF-8). Text is escaped, series are clipped to the plot area with clipPath, fonts are referenced by name, not embedded. Each side must be 1 to 16384 pixels. Does not change the on-screen layout.

pascal
Svg := Plot.ToSVG(800, 500);

SaveToFile method

procedure SaveToFile(const FileName: string; AWidth: Integer = 0; AHeight: Integer = 0);

Writes the chart to a file whose extension selects the format: .png, .bmp, .emf (enhanced metafile) and .svg render the chart at AWidth x AHeight pixels (0 means the control's current Width or Height); .csv writes DataToCSV as UTF-8 without BOM and ignores the size. The file is written to FileName + '.part' and renamed over the target, so a failed export leaves any previous file intact.

Raises EAtlasPlotError for any other extension or an image size outside 1 to 16384; a missing folder or a locked file raises the usual stream or OS exception. Does not change the on-screen layout.

pascal
Plot.SaveToFile('sales.png', 800, 500);
Plot.SaveToFile('sales.svg', 800, 500);
Plot.SaveToFile('sales.csv');

CopyToClipboard method

procedure CopyToClipboard;

Places a bitmap of the chart, at the control's current size, on the clipboard. Clipboard output has not been covered by automated tests.

pascal
Plot.CopyToClipboard;

DataToCSV method

function DataToCSV: string;

Returns every point as CSV text with CRLF line ends. The header is series,kind,x,y,text; kind is line, step, area, bar, point or pie; numbers always use . as decimal separator and keep up to 15 significant digits; a gap has an empty y; fields holding a comma, quote or line break are quoted. Only titles, kinds and points are exported: colours, visibility, marks and line widths are not, and series without points produce no rows.

pascal
Csv := Plot.DataToCSV;

DataFromCSV method

procedure DataFromCSV(const Text: string);

Replaces every series with the data in Text, in the format DataToCSV writes. A leading byte order mark is ignored. Consecutive rows with the same title and kind form one series (two adjacent series sharing both would merge); an empty y becomes a gap. Imported series get default colours, marks and widths, and the zoom is reset.

The whole text is validated first: a missing header, a row without five fields, an unknown kind, a malformed or out-of-range number, a negative pie slice or an unterminated quote raises EAtlasPlotError and leaves the chart unchanged. References to the old series become invalid after a successful import.

pascal
Plot.DataFromCSV(TFile.ReadAllText('sales.csv', TEncoding.UTF8));

Examples

Bar chart on a form, reporting clicks

A form built in code with two grouped bar series whose point texts become category labels. Clicking a bar shows its series, category and value.

pascal
uses
  System.Classes, System.SysUtils, Vcl.Controls, Vcl.Forms, Vcl.StdCtrls,
  Atlas.Plot, Atlas.PlotSeries;

type
  TSalesForm = class(TForm)
  private
    FPlot: TAtlasPlot;
    FStatus: TLabel;
    procedure PointClicked(Sender: TObject; Series: TAtlasPlotSeries; PointIndex: Integer);
  public
    constructor Create(AOwner: TComponent); override;
  end;

constructor TSalesForm.Create(AOwner: TComponent);
var
  Plan, Actual: TAtlasPlotSeries;
begin
  inherited CreateNew(AOwner);
  Caption := 'Sales by region';
  FStatus := TLabel.Create(Self);
  FStatus.Parent := Self;
  FStatus.Align := alBottom;
  FPlot := TAtlasPlot.Create(Self);
  FPlot.Parent := Self;
  FPlot.Align := alClient;
  FPlot.Title := 'Plan and result by region';
  FPlot.OnPointClick := PointClicked;
  FPlot.BeginUpdate;
  try
    Plan := FPlot.AddSeries('Plan', pkBar);
    Actual := FPlot.AddSeries('Result', pkBar);
    Actual.Marks := pmValue;
    Plan.AddY(42, 'North');
    Actual.AddY(45.5, 'North');
    Plan.AddY(35, 'South');
    Actual.AddY(31, 'South');
    Plan.AddY(51, 'East');
    Actual.AddY(56, 'East');
  finally
    FPlot.EndUpdate;
  end;
end;

procedure TSalesForm.PointClicked(Sender: TObject; Series: TAtlasPlotSeries; PointIndex: Integer);
begin
  FStatus.Caption := Format('%s, %s: %g',
    [Series.Title, Series[PointIndex].Text, Series[PointIndex].Y]);
end;

Export without a window

An off-screen chart, created with no owner, rendered to PNG, SVG and CSV files. Works in console programs.

pascal
uses
  System.SysUtils, Atlas.Plot, Atlas.PlotSeries;

procedure ExportVisits(const Folder: string);
var
  Plot: TAtlasPlot;
  Visits: TAtlasPlotSeries;
  Base: string;
begin
  Base := IncludeTrailingPathDelimiter(Folder) + 'visits';
  Plot := TAtlasPlot.Create(nil);
  try
    Plot.Title := 'Visits per day';
    Plot.LegendVisible := False;
    Visits := Plot.AddSeries('Visits', pkArea);
    Visits.AddY(120, 'Mon');
    Visits.AddY(135, 'Tue');
    Visits.AddY(128, 'Wed');
    Visits.AddY(160, 'Thu');
    Visits.AddY(98, 'Fri');
    Plot.SaveToFile(Base + '.png', 800, 450);
    Plot.SaveToFile(Base + '.svg', 800, 450);
    Plot.SaveToFile(Base + '.csv');
  finally
    Plot.Free;
  end;
end;

Print a chart

Draws the chart across the top half of a printed page. There is no print dialog or preview; printing on hardware has not been tested.

pascal
uses
  System.Types, Vcl.Printers, Atlas.Plot;

procedure PrintChart(Plot: TAtlasPlot);
begin
  Printer.BeginDoc;
  try
    Plot.RenderTo(Printer.Canvas, Rect(0, 0, Printer.PageWidth, Printer.PageHeight div 2));
  finally
    Printer.EndDoc;
  end;
end;

Follow changes from another object

A change listener is called once per batch, so a companion object can refresh itself after the chart changes.

pascal
uses
  Atlas.Plot, Atlas.PlotSeries;

type
  TChartWatcher = class
  private
    FChanges: Integer;
    procedure ChartChanged(Sender: TObject);
  public
    property Changes: Integer read FChanges;
  end;

procedure TChartWatcher.ChartChanged(Sender: TObject);
begin
  Inc(FChanges);
end;

procedure RefreshTwice(Plot: TAtlasPlot; Watcher: TChartWatcher);
begin
  Plot.AddChangeListener(Watcher.ChartChanged);
  try
    Plot.BeginUpdate;
    try
      Plot.Title := 'Batch';
      Plot.AddSeries('A').AddY(1);
    finally
      Plot.EndUpdate; // Watcher.Changes grows by one for the whole batch
    end;
    Plot.Footnote := 'Single change'; // and by one more here
  finally
    Plot.RemoveChangeListener(Watcher.ChartChanged);
  end;
end;

TAtlasPlotSeries · TAtlasPlotAxis · TAtlasPlotSeriesList · TAtlasPlotSurface · EAtlasPlotError · TAtlasPlotStacking · TAtlasPlotLegendPosition · TAtlasPlotPointEvent