mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-11-04 16:59:33 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			226 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			226 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						|
 | 
						|
 *****************************************************************************
 | 
						|
  See the file COPYING.modifiedLGPL.txt, included in this distribution,
 | 
						|
  for details about the license.
 | 
						|
 *****************************************************************************
 | 
						|
 | 
						|
  An ImageList with TCustomChartSeries icons
 | 
						|
 | 
						|
  Authors: Werner Pamler, Alexander Klenin
 | 
						|
 | 
						|
  Notes:
 | 
						|
  - The image list can be used like any other image list.
 | 
						|
  - Assigning the Chart property to a TChart adds the series icons of all
 | 
						|
    series to the image list. Series created at run-time will be added automatically
 | 
						|
    to the end of the list.
 | 
						|
  - Make sure to populate toolbar icons etc. before assigning the chart since the
 | 
						|
    series images are added to the end of the list; otherwise image indices of
 | 
						|
    these icons will change.
 | 
						|
}
 | 
						|
 | 
						|
unit TAChartImageList;
 | 
						|
 | 
						|
{$H+}
 | 
						|
 | 
						|
interface
 | 
						|
 | 
						|
uses
 | 
						|
  Classes, Graphics, Controls,
 | 
						|
  TAChartUtils, TACustomSeries, TAGraph;
 | 
						|
 | 
						|
type
 | 
						|
  TChartImageList = class(TImageList)
 | 
						|
  private
 | 
						|
    FChart: TChart;
 | 
						|
    FFirstSeriesIndex: Integer;
 | 
						|
    FListener: TListener;
 | 
						|
    FOnPopulate: TNotifyEvent;
 | 
						|
    FSeriesCount: Integer;
 | 
						|
    procedure SetChart(AValue: TChart);
 | 
						|
  protected
 | 
						|
    procedure ClearAllSeries;
 | 
						|
    procedure Populate;
 | 
						|
  public
 | 
						|
    procedure ReadData(AStream: TStream); override;
 | 
						|
    procedure WriteData(AStream: TStream); override;
 | 
						|
    procedure ReadAdvData(AStream: TStream); override;
 | 
						|
    procedure WriteAdvData(AStream: TStream); override;
 | 
						|
  public
 | 
						|
    constructor Create(AOwner: TComponent); override;
 | 
						|
    destructor Destroy; override;
 | 
						|
    function GetSeries(AImgIndex: Integer): TCustomChartSeries;
 | 
						|
    function ImageIndexOfSeries(ASeries: TCustomChartSeries): Integer;
 | 
						|
    procedure SeriesChanged(ASender: TObject);
 | 
						|
    property FirstSeriesIndex: Integer read FFirstSeriesIndex;
 | 
						|
    property SeriesCount: Integer read FSeriesCount;
 | 
						|
  published
 | 
						|
    property Chart: TChart read FChart write SetChart;
 | 
						|
    property OnPopulate: TNotifyEvent read FOnPopulate write FOnPopulate;
 | 
						|
  end;
 | 
						|
 | 
						|
procedure Register;
 | 
						|
 | 
						|
implementation
 | 
						|
 | 
						|
uses
 | 
						|
  Math, SysUtils,
 | 
						|
  TADrawUtils, TADrawerCanvas, TAEnumerators, TALegend;
 | 
						|
 | 
						|
 | 
						|
procedure Register;
 | 
						|
begin
 | 
						|
  RegisterComponents(CHART_COMPONENT_IDE_PAGE, [TChartImageList]);
 | 
						|
end;
 | 
						|
 | 
						|
 | 
						|
{ TChartImageList }
 | 
						|
 | 
						|
procedure TChartImageList.ClearAllSeries;
 | 
						|
var
 | 
						|
  i: Integer;
 | 
						|
begin
 | 
						|
  if FFirstSeriesIndex < 0 then exit;
 | 
						|
  for i := FFirstSeriesIndex + FSeriesCount - 1 downto FFirstSeriesIndex do
 | 
						|
    Delete(i);
 | 
						|
  FFirstSeriesIndex := -1;
 | 
						|
  FSeriesCount := 0;
 | 
						|
end;
 | 
						|
 | 
						|
constructor TChartImageList.Create(AOwner: TComponent);
 | 
						|
begin
 | 
						|
  inherited Create(AOwner);
 | 
						|
  FListener := TListener.Create(@FChart, @SeriesChanged);
 | 
						|
  FFirstSeriesIndex := -1;
 | 
						|
  FSeriesCount := 0;
 | 
						|
end;
 | 
						|
 | 
						|
destructor TChartImageList.Destroy;
 | 
						|
begin
 | 
						|
  FreeAndNil(FListener);
 | 
						|
  inherited Destroy;
 | 
						|
end;
 | 
						|
 | 
						|
function TChartImageList.GetSeries(AImgIndex: Integer): TCustomChartSeries;
 | 
						|
begin
 | 
						|
  Result := nil;
 | 
						|
  AImgIndex -= FFirstSeriesIndex;
 | 
						|
  if
 | 
						|
    (FFirstSeriesIndex > -1) and (FChart <> nil) and
 | 
						|
    InRange(AImgIndex, 0, FSeriesCount - 1)
 | 
						|
  then
 | 
						|
    Result := FChart.Series[AImgIndex] as TCustomChartSeries;
 | 
						|
end;
 | 
						|
 | 
						|
function TChartImageList.ImageIndexOfSeries(ASeries: TCustomChartSeries): Integer;
 | 
						|
begin
 | 
						|
  Result := -1;
 | 
						|
  if ASeries = nil then exit;
 | 
						|
  for Result := 0 to Count - 1 do
 | 
						|
    if GetSeries(Result) = ASeries then exit;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TChartImageList.Populate;
 | 
						|
var
 | 
						|
  legendItems: TChartLegendItems = nil;
 | 
						|
  bmp: TBitmap;
 | 
						|
  r: TRect;
 | 
						|
  s: TCustomChartSeries;
 | 
						|
  id: IChartDrawer;
 | 
						|
  li: TLegendItem;
 | 
						|
begin
 | 
						|
  ClearAllSeries;
 | 
						|
  if FChart = nil then exit;
 | 
						|
 | 
						|
  FFirstSeriesIndex := Count;
 | 
						|
  FSeriesCount := 0;
 | 
						|
 | 
						|
  legendItems := TChartLegendItems.Create;
 | 
						|
  bmp := TBitmap.Create;
 | 
						|
  try
 | 
						|
    bmp.Width := Width;
 | 
						|
    bmp.Height := Height;
 | 
						|
    bmp.Canvas.Brush.Style := bsSolid;
 | 
						|
    bmp.Canvas.Pen.Style := psSolid;
 | 
						|
    bmp.Canvas.Pen.Width := 1;
 | 
						|
    bmp.Transparent := true;
 | 
						|
    bmp.TransparentMode := tmAuto;
 | 
						|
    r := Rect(0, 0, Width, Height);
 | 
						|
    id := TCanvasDrawer.Create(bmp.Canvas);
 | 
						|
    id.Pen := FChart.Legend.SymbolFrame;
 | 
						|
    for s in CustomSeries(FChart) do
 | 
						|
      s.GetSingleLegendItem(legendItems);
 | 
						|
    for li in legendItems do begin
 | 
						|
      bmp.Canvas.Brush.Color := BkColor;
 | 
						|
      bmp.Canvas.FillRect(r);
 | 
						|
      li.Draw(id, R);
 | 
						|
      AddMasked(bmp, bmp.TransparentColor);
 | 
						|
      FSeriesCount += 1;
 | 
						|
    end;
 | 
						|
    if Assigned(FOnPopulate) then FOnPopulate(Self);
 | 
						|
  finally
 | 
						|
    FreeAndNil(legendItems);
 | 
						|
    FreeAndNil(bmp);
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TChartImageList.ReadAdvData(AStream: TStream);
 | 
						|
begin
 | 
						|
  Unused(AStream);
 | 
						|
end;
 | 
						|
 | 
						|
procedure TChartImageList.ReadData(AStream: TStream);
 | 
						|
var
 | 
						|
  ch: TChart;
 | 
						|
begin
 | 
						|
  ch := Chart;
 | 
						|
  Chart := nil;
 | 
						|
  Clear;
 | 
						|
  inherited ReadData(AStream);
 | 
						|
  Chart := ch;
 | 
						|
end;
 | 
						|
 | 
						|
// Notification procedure of the listener. Responds to chart broadcasts
 | 
						|
// by populating the imagelist with the chart's series icons.
 | 
						|
procedure TChartImageList.SeriesChanged(ASender:TObject);
 | 
						|
begin
 | 
						|
  Unused(ASender);
 | 
						|
  Populate;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TChartImageList.SetChart(AValue:TChart);
 | 
						|
begin
 | 
						|
  if FChart = AValue then exit;
 | 
						|
 | 
						|
  if FListener.IsListening then
 | 
						|
    FChart.Broadcaster.Unsubscribe(FListener);
 | 
						|
  FChart := AValue;
 | 
						|
  if FChart <> nil then
 | 
						|
    FChart.Broadcaster.Subscribe(FListener);
 | 
						|
 | 
						|
  SeriesChanged(Self);
 | 
						|
end;
 | 
						|
 | 
						|
procedure TChartImageList.WriteAdvData(AStream: TStream);
 | 
						|
begin
 | 
						|
  Unused(AStream);
 | 
						|
end;
 | 
						|
 | 
						|
procedure TChartImageList.WriteData(AStream: TStream);
 | 
						|
var
 | 
						|
  ch: TChart;
 | 
						|
begin
 | 
						|
  ch := Chart;
 | 
						|
  Chart := nil;
 | 
						|
  inherited WriteData(AStream);
 | 
						|
  Chart := ch;{
 | 
						|
 | 
						|
  // Don't write the series images to stream.
 | 
						|
  // They will be recreated automatically when the chart is assigned on loading.
 | 
						|
  Unused(AStream);
 | 
						|
  }
 | 
						|
end;
 | 
						|
 | 
						|
end.
 | 
						|
 |