{**********************************************}
{   TeeChart Gallery Panel                     }
{   Copyright (c) 1996-2020 by Steema Software }
{**********************************************}
unit TeeGalleryPanel;
{$I TeeDefs.inc}

interface

Uses {$IFNDEF FMX}
     {$IFNDEF LINUX}
     Windows,
     Messages,
     {$ENDIF}
     {$ENDIF}

     {$IFDEF D16}
     System.UIConsts, System.UITypes,
     {$ENDIF}

     {$IFDEF D18}
     System.Generics.Collections,
     {$ENDIF}
     
     {$IFDEF FMX}
     FMX.Types, FMX.Forms, FMX.Platform, FMX.Layouts,
       {$IFDEF D18}
       FMX.Controls,
       {$ENDIF}
     {$ELSE}
     Controls, ExtCtrls, Forms, Graphics,
     {$ENDIF}

     {$IFNDEF FMX}

     {$IFDEF D6}
     Types,
     {$ENDIF}

     {$IFDEF USETHEMES}
     Themes, UxTheme,
     {$ENDIF}

     {$ENDIF}

     Classes,

     {$IFDEF FMX}
     System.Types,
     FMXTee.Canvas, FMXTee.Procs, FMXTee.Engine, FMXTee.Chart, FMXTee.Series
     {$ELSE}
     TeCanvas, TeeProcs, TeEngine, Chart
     {$ENDIF}
     ;

Const TeeGalleryNumRows=0; // Automatic number of rows
      TeeGalleryNumCols=4;
      TeeCursorDisabled={$IFDEF FMX}crNo{$ELSE}crNoDrop{$ENDIF};
      TeeMsg_GalleryRender='GalleryRender'; // Do not localize

var
  clTeeGallery:TColor={$IFDEF FMX}TAlphaColors.White{$ELSE}clWhite{$ENDIF};

  TeeGalleryCheckMaximize:Boolean=True;

type
  TChartGalleryPanel=class;

  TGalleryChart=class(TCustomChart)
  private
    FSmooth         : Boolean;
    ICreatingBitmap : Boolean;

    IMouseInside    : Boolean;
    DisabledSeries  : Boolean;

    SeriesType      : TTeeSeriesType;

    Procedure AfterDraw(Sender:TObject);
    Function ArrowRect:TRect;
    procedure CreateSeriesType(const AGallery:TChartGalleryPanel);
    function DoFocusRotation:Boolean;

    {$IFNDEF FMX}
    {$IFNDEF LCL}
    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
    {$ENDIF}
    {$ENDIF}

    procedure DrawSmoothChart;
    procedure DrawSubGalleryArrow;
    function ParentGallery:TChartGalleryPanel;
    procedure SetTitleFontSize(AOffset:Integer=0);
    procedure SetSmooth(Value:Boolean);
  protected
    CanSetFocus : Boolean;
  public
    Constructor Create(AOwner:TComponent); override;

    Procedure Focus(Is3D:Boolean);
    Procedure SetMargins;
    Procedure UnFocus(Is3D:Boolean);

    property Smooth:Boolean read FSmooth write SetSmooth default False;
  end;

  TChartList=class({$IFDEF D18}TObjectList<TGalleryChart>{$ELSE}TList{$ENDIF})
  private
    IGallery : TChartGalleryPanel;

    {$IFNDEF D18}
    Function GetChart(Index:Integer):TGalleryChart;
    {$ENDIF}
  public
    procedure FreeAll;

    {$IFNDEF D18}
    Procedure Clear; override;
    property Items[Index:Integer]:TGalleryChart read GetChart; default;
    {$ENDIF}
  end;

  {$IFDEF LCL}
  {$DEFINE TEEBEVELS}
  {$ENDIF}

  {$IFDEF D16}
  [ComponentPlatformsAttribute(TeeAllComponentPlatformIDs)]
  {$ENDIF}
  TChartGalleryPanel=class({$IFDEF FMX}TVertScrollBox{$ELSE}TScrollBox{$ENDIF})
  private
    FAspectRatio     : Single;  // Width vs. Height, default 1
    FCharts          : TChartList;
    FColWidth        : Integer;
    FDisplaySub      : Boolean;
    FFocusRotation   : Boolean;
    FNumRows         : Integer;
    FNumCols         : Integer;
    FRowHeight       : Integer;
    FSmooth          : Boolean;
    FView3D          : Boolean;
    FOnChangeChart   : TNotifyEvent;
    FOnSelectedChart : TNotifyEvent;
    FOnSubSelected   : TNotifyEvent;
    FOnSubShow       : TNotifyEvent;

    {$IFDEF TEEBEVELS}
    FBevelInner : TPanelBevel;
    FBevelOuter : TPanelBevel;
    FBevelWidth : Integer;
    {$ENDIF}

    ISubGallery       : Boolean;
    ISelectedChart    : TGalleryChart;
    FOldSmooth        : Boolean;
    IRemoving         : Boolean;
    IResizing         : Boolean;
    ICreating         : Boolean;

    {$IFDEF LCL}
    IResizingLCL      : Boolean;
    {$ENDIF}

    function CalcNumCols:Integer;
    procedure ChartKeyDown(Sender: TObject; var Key: Word;
                          {$IFDEF FMX}var KeyChar:System.WideChar;{$ENDIF} Shift: TShiftState);
    function ClickedArrow(const P:TPoint):Boolean;
    Procedure DoRealignCharts;
    function GetChart(Index:Integer):TGalleryChart;

    procedure SetAspectRatio(const Value:Single);
    Procedure SetNumCols(Value:Integer);
    Procedure SetNumRows(Value:Integer);
    procedure SetSmooth(Value:Boolean);
    Procedure SetView3D(Value:Boolean);
    procedure ShowSubGallery;

    Function ValidSeries(Const ASeriesType:TTeeSeriesType; Const APage:String):Boolean;

    {$IFNDEF FMX}
    {$IFDEF MSWINDOWS}
    procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
    {$ENDIF}
    {$ENDIF}

  protected
    tmpG      : TChartGalleryPanel;
    tmpSeries : TChartSeries;
    tmpType   : TTeeSeriesType;

    CanSetFocus : Boolean;
    CanvasClass : TTeeCanvasClass;

    Procedure CalcChartWidthHeight;
    Procedure ChartEvent(Sender: TObject);

    // problem: double-clicking gallery ends-up calling MouseUp for the wrong chart
    // procedure ChartMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: TCoordinate);

    procedure ChartOnDblClick(Sender: TObject);
    Function CreateSubChart(const ATitle:String):TCustomAxisPanel;
    Procedure CreateSubGallery(const AGallery:TChartGalleryPanel; AClass:TChartSeriesClass);

    {$IFDEF FMX}
    {$IFDEF D17}
    procedure DoRealign; override;
    {$ENDIF}
    {$ELSE}
    function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean; override;
    {$ENDIF}

    Procedure GetChartXY(const AChart:TGalleryChart; out x,y:Integer);
    procedure KeyDown(var Key: Word; {$IFDEF FMX}var KeyChar: System.WideChar;{$ENDIF}
                      Shift: TShiftState); override;
    procedure Loaded; override;
    procedure Resize; override;
    Procedure ResizeChart(const AChart:TGalleryChart; TopOffset:Integer=0);

    Procedure AddSubCharts(AGallery:TChartGalleryPanel);
    procedure FindSelectedChart;
    Procedure ShowSelectedChart;
  public
    CheckSeries      : Boolean;
    FunctionsVisible : Boolean;
    SelectedSeries   : TChartSeries;

    Constructor Create(AOwner:TComponent); override;
    Destructor Destroy; override;

    procedure SelectSeries(const Series: TChartSeries);
    procedure SelectChart(const Chart: TGalleryChart); virtual;

    Function CreateChart(Const AType:TTeeSeriesType):TCustomAxisPanel;
    Procedure CreateChartList(ASeriesList:Array of TChartSeriesClass);  // BCB does not allow "const"
    Procedure CreateGalleryPage(Const PageName:String);
    property ColWidth:Integer read FColWidth;

    class Function DefaultMode:Integer;
    class Function DefaultSmooth:Boolean;

    Function GetSeriesClass(out AClass:TChartSeriesClass;
                            out AFunctionClass:TTeeFunctionClass;
                            out ASubIndex:Integer):Boolean; // deprecated

    procedure FinishAdd(const Chart:TGalleryChart; IsDisabled:Boolean=False);
    procedure FreeAllCharts;

    {$IFDEF FMX}
    procedure MouseWheel(Shift: TShiftState; WheelDelta: Integer; var Handled: Boolean); override;
    {$ENDIF}

    Procedure ResizeCharts;

    class Procedure SaveMode(Value:Integer);
    class Procedure SaveSmooth(Value:Boolean);

    // Returns class type of first series in selected chart
    function SelectedSeriesClass:TChartSeriesClass;

    procedure UseTheme(const Theme: TChartThemeClass);

    property AspectRatio:Single read FAspectRatio write SetAspectRatio; // default 1
    property Chart[Index:Integer]:TGalleryChart read GetChart; default;
    property Charts:TChartList read FCharts;
    property RowHeight:Integer read FRowHeight;
    property SelectedChart:TGalleryChart read ISelectedChart write SelectChart;
  published
    property DisplaySub:Boolean read FDisplaySub write FDisplaySub default False;
    property FocusRotation:Boolean read FFocusRotation write FFocusRotation default True;
    property NumRows:Integer read FNumRows write SetNumRows default TeeGalleryNumRows;
    property NumCols:Integer read FNumCols write SetNumCols default TeeGalleryNumCols;
    property Smooth:Boolean read FSmooth write SetSmooth default False;
    property View3D:Boolean read FView3D write SetView3D default True;

    { events }
    property OnSelectedChart:TNotifyEvent read FOnSelectedChart write FOnSelectedChart;
    property OnChangeChart:TNotifyEvent read FOnChangeChart write FOnChangeChart;
    property OnShowSubGallery:TNotifyEvent read FOnSubShow write FOnSubShow;
    property OnSubSelected:TNotifyEvent read FOnSubSelected write FOnSubSelected;

    { TPanel properties }

    {$IFDEF FMX}
    {$IFDEF D17}
    property Action;
    {$ENDIF}
    {$ENDIF}

    property Align;

    {$IFDEF FMX}

    {$IFDEF D23}
    property ParentShowHint;
    {$ENDIF}

    {$ELSE}

    property BevelInner{$IFDEF TEEBEVELS}:TPanelBevel read FBevelInner write FBevelInner default bvNone{$ENDIF};
    property BevelOuter{$IFDEF TEEBEVELS}:TPanelBevel read FBevelOuter write FBevelOuter default bvNone{$ENDIF};
    property BevelWidth{$IFDEF TEEBEVELS}:Integer read FBevelWidth write FBevelWidth default 0{$ENDIF};

    property BorderWidth;
    property BorderStyle;
    property DragCursor;
    property ParentColor;
    property ParentShowHint;
    property TabStop;
    property AutoSize;
    property Constraints;
    {$ENDIF}

    property ShowHint;
    
    {$IFNDEF FMX}
    property Color;
    {$ENDIF}

    property DragMode;
    property Enabled;
    property PopupMenu;
    property TabOrder;
    property Visible;
    property Anchors;

    {$IFNDEF FMX}
    property DragKind;
    {$ENDIF}

    { TPanel events }
    property OnClick;

    {$IFNDEF FMX}
    property OnContextPopup;
    {$ENDIF}

    property OnDblClick;

    property OnDragDrop;
    property OnDragOver;

    {$IFNDEF FMX}
    property OnEndDrag;
    property OnStartDrag;
    {$ENDIF}

    property OnEnter;
    property OnExit;
    property OnMouseDown;

    {$IFDEF D10}
    property OnMouseEnter;
    property OnMouseLeave;
    {$ENDIF}

    property OnMouseMove;
    property OnMouseUp;
    property OnResize;

    {$IFNDEF FMX}
    property OnConstrainedResize;

    {$IFNDEF LCL}
    property OnCanResize;
    {$ENDIF}
    property OnDockDrop;
    property OnDockOver;
    property OnEndDock;
    property OnStartDock;
    property OnUnDock;
    {$ENDIF}
  end;

implementation

Uses Math, SysUtils,

     {$IFDEF FMX}
     {$IFDEF D19}
     FMX.Graphics,
     {$ENDIF}
     FMXTee.Constants, FMX.Effects
     {$ELSE}
     TeeConst, Series, TeeFilters,

     {$IFDEF LCL}
     GraphType
     {$ELSE}
     TeePenDlg
     {$ENDIF}
     {$ENDIF}
     ;

const
  clTeeSelected = {$IFDEF FMX}TAlphaColors.Silver{$ELSE}clSilver{$ENDIF}; // $0080FFFF;   { <-- color use to select charts }

{ TChartList }

procedure TChartList.FreeAll;
var t : Integer;
begin
  IGallery.IRemoving:=True;
  try
    for t:=0 to Count-1 do
        Items[t].{$IFDEF D18}DisposeOf{$ELSE}Free{$ENDIF};

    {$IFDEF D18}
    Clear;
    {$ENDIF}

  finally
    IGallery.IRemoving:=False;
  end;
end;

{$IFNDEF D18}
Procedure TChartList.Clear;
begin
  FreeAll;
  inherited;
end;

{$IFNDEF D16}
{$DEFINE TEELISTARRAY}
{$ENDIF}

Function TChartList.GetChart(Index:Integer):TGalleryChart;
begin
  result:=TGalleryChart(List{$IFDEF TEELISTARRAY}^{$ENDIF}[Index]);
end;
{$ENDIF}

{ TGalleryChart }

Constructor TGalleryChart.Create(AOwner:TComponent);
begin
  inherited;

  CanSetFocus:=True;
  
  AutoRepaint:=False;

  Legend.Hide;

  LeftAxis.LabelStyle:=talValue;
  LeftAxis.Grid.Color:=$DDDDDD;
  LeftAxis.LabelsFont.Size:=7;
  LeftAxis.LabelsFont.Color:=clDkGray;

  BottomAxis.LabelStyle:=talValue;
  BottomAxis.Grid.Color:=$DDDDDD;
  BottomAxis.LabelsFont.Size:=7;
  BottomAxis.LabelsFont.Color:=clDkGray;

  Title.Font.Color:={$IFDEF FMX}TAlphaColors.Navy{$ELSE}clNavy{$ENDIF};

  Zoom.Animated:=True;

  With View3DOptions do
  begin
    Orthogonal:=False;
    Zoom       :=90;
    Perspective:=55;

    if Assigned(AOwner) and TChartGalleryPanel(AOwner).FocusRotation then
    begin
      Rotation   :=335;
      Elevation  :=350;
    end;
  end;

  Chart3DPercent:=100;
  ClipPoints:=False;

  Frame.Hide;
  BevelWidth:=2;
  BevelOuter:={$IFDEF LCL}TPanelBevel.{$ENDIF}bvNone;

  With LeftWall do
  begin
    Color:=clTeeGallery;
    Size:=4;
    Pen.Color:=clDkGray;
    Gradient.Visible:=True;
    Gradient.StartColor:=clDkGray;
    Gradient.EndColor:=clTeeSelected;
  end;

  With BottomWall do
  begin
    Color:=clTeeGallery;
    Size:=4;
    Pen.Color:=clDkGray;
    Gradient.Visible:=True;
    Gradient.StartColor:=clDkGray;
    Gradient.EndColor:=clTeeSelected;
  end;

  OnAfterDraw:=AfterDraw;

  AllowPanning:=pmNone;

  Color:=clTeeGallery;

  {$IFDEF FMX}
  CanFocus:=True;
  {$ENDIF}

  AutoRepaint:=True;
end;

Procedure TGalleryChart.SetMargins;
var tmp : Integer;
begin
  if View3D then tmp:=4 else tmp:=5;

  MarginTop    :=tmp;
  MarginBottom :=tmp;
  MarginLeft   :=tmp;
  MarginRight  :=tmp;
end;

function TGalleryChart.ParentGallery:TChartGalleryPanel;
begin
  if Assigned(Parent) then
     result:=TChartGalleryPanel(Parent{$IFDEF FMX}.Parent{$ENDIF})
  else
     result:=nil;
end;

function TGalleryChart.DoFocusRotation:Boolean;
var tmp : TChartGalleryPanel;
begin
  tmp:=ParentGallery;
  result:=Assigned(tmp) and tmp.FocusRotation;
end;

type
  TSeriesAccess=class(TChartSeries);

Procedure TGalleryChart.Focus(Is3D:Boolean);
begin
  AutoRepaint:=False;

  with Gradient do
  begin
    Visible:=True;
    Direction:=gdFromTopLeft;
    StartColor:=clTeeSelected;
    EndColor:=clTeeGallery;
  end;

  if DoFocusRotation then
  begin
    View3DOptions.Rotation:=345;

    if SeriesCount>0 then
       TSeriesAccess(Series[0]).GalleryChanged3D(Is3D);
  end;

  With Title.Font do
  begin
    Style:=[{$IFDEF FMX}TFontStyle.{$ENDIF}fsBold];
    Color:={$IFDEF FMX}TAlphaColors.Black{$ELSE}clBlack{$ENDIF};
  end;

  SetTitleFontSize(2);

  with Title.Font.Shadow do
  begin
    Visible:=True;

    Size:=1;
    Color:={$IFDEF FMX}TAlphaColors.LightGray{$ELSE}clDkGray{$ENDIF};

    SmoothBlur:=2;
  end;

  BevelOuter:={$IFDEF LCL}TPanelBevel.{$ENDIF}bvRaised;

  {$IFNDEF FMX} // TODO
  if CanSetFocus then
     if {$IFNDEF FMX}Showing and{$ENDIF} CanFocus then
        {$IFDEF FMX}if Assigned(Root) then{$ENDIF}
        SetFocus;
  {$ENDIF}

  AutoRepaint:=True;
  Invalidate;
end;

Procedure TGalleryChart.UnFocus(Is3D:Boolean);
begin
  if Gradient.Visible then
  begin
    Gradient.Visible:=False;
    BevelOuter:=bvNone;

    with Title.Font do
    begin
      Style:=[];
      Color:={$IFDEF FMX}TAlphaColors.Navy{$ELSE}clNavy{$ENDIF};
    end;

    SetTitleFontSize;

    Title.Font.Shadow.Visible:=False;

    if DoFocusRotation then
    begin
      View3DOptions.Rotation:=335;

      if SeriesCount>0 then
         TSeriesAccess(Series[0]).GalleryChanged3D(Is3D);
    end;
  end;
end;

{$IFNDEF FMX}
{$IFNDEF LCL}

procedure TGalleryChart.CMMouseEnter(var Message: TMessage);
begin
  IMouseInside:=True;
  Invalidate;
  inherited;
end;

procedure TGalleryChart.CMMouseLeave(var Message: TMessage);
begin
  IMouseInside:=False;
  Invalidate;
  inherited;
end;
{$ENDIF}
{$ENDIF}

procedure TGalleryChart.SetSmooth(Value:Boolean);
begin
  SetBooleanProperty(FSmooth,Value);
end;

Function TGalleryChart.ArrowRect:TRect;
{$IFDEF FMX}
const
  OneDiv12=1.0/12;
{$ENDIF}

var tmpHeight,
    tmp  : TCoordinate;
begin
  tmp:=0;
  if Border.Visible then tmp:=tmp+Border.Width;
  if Smooth then tmp:=tmp {$IFDEF FMX}*0.5{$ELSE}div 2{$ENDIF};

  result.Left:=4+tmp;
  result.Right:=result.Left+(Width {$IFDEF FMX}*OneDiv12{$ELSE}div 12{$ENDIF})+1;

  tmpHeight:=tmp+(Width {$IFDEF FMX}*OneDiv12{$ELSE}div 12{$ENDIF});
  if Shadow.Size>0 then tmpHeight:=tmpHeight+Shadow.Size;

  result.Bottom:=Height-4;
  result.Top:=result.Bottom-tmpHeight+2;
end;

procedure TGalleryChart.DrawSubGalleryArrow;
var R : TRect;
begin
  R:=ArrowRect;

  with Canvas do
  begin
    Brush.Style:=bsSolid;
    Brush.Color:={$IFDEF FMX}TAlphaColors.Black{$ELSE}clBlack{$ENDIF};
    Pen.Style:=psClear;

    Polygon([R.TopLeft,TeePoint(R.Right,R.Top),TeePoint((R.Left+R.Right) {$IFDEF FMX}*0.5{$ELSE}div 2{$ENDIF},R.Bottom)]);

    Pen.Mode:=pmCopy;
    Pen.Style:=psSolid;
  end;
end;

procedure TGalleryChart.SetTitleFontSize(AOffset:Integer=0);
var tmp : Integer;
begin
  tmp:=Round(Width*0.108)+AOffset; // Adequate text size proportion for both VCL and FMX

  if Title.Font.Size<>tmp then
     Title.Font.Size:=tmp;

  if (Width>0) and Assigned(Canvas.ReferenceCanvas) then
  repeat
    TryAssignFont(Title.Font);

    if Canvas.TextWidth(Title.Caption)>Round(0.5*Width) then
       {$IFDEF FMX}
       Title.Font.Size:=Title.Font.Size-1
       {$ELSE}
       Title.Font.SizeFloat:=Title.Font.SizeFloat-1
       {$ENDIF}
    else
       break;

  until False or (Title.Font.Size<1);
end;

procedure TGalleryChart.DrawSmoothChart;
const
  ScaleFactor=2;

var tmp  : TBitmap;
    tmpR : TRect;
    Old  : Boolean;
    TextFactor : Integer;
begin
  if (Width>=ScaleFactor) and (Height>=ScaleFactor) then
  begin
    ICreatingBitmap:=True;

    LeftAxis.Labels:=True;
    BottomAxis.Labels:=True;

    TextFactor:=ScaleFactor div 2;

    with LeftAxis.LabelsFont do Size:=Size*TextFactor;
    with BottomAxis.LabelsFont do Size:=Size*TextFactor;

    tmpR:=Title.ShapeBounds;
    Old:=Title.Visible;
    Title.Hide;
    MarginTop:=30;

    tmp:=TeeCreateBitmap(Color,TeeRect(ScaleFactor*Width,ScaleFactor*Height),TeePixelFormat);
    try
      Canvas.InitWindow(Canvas.ReferenceCanvas,View3DOptions,Color,View3D,BoundsRect);
      SmoothStretch(tmp,TTeeCanvas3D(Canvas).Bitmap,ssBestPerformance);
    finally
      tmp.Free;
      Title.Visible:=Old;
      Title.ShapeBounds:=tmpR;
      Title.CustomPosition:=True;

      if Canvas.ClassType<>TTeeCanvas3D then
         Canvas.InitWindow(Canvas.ReferenceCanvas,View3DOptions,Color,View3D,BoundsRect);

      Title.DrawTitle;

      Title.CustomPosition:=False;
      SetMargins;
      ICreatingBitmap:=False;
    end;

    with LeftAxis.LabelsFont do Size:=Size {$IFDEF FMX}/{$ELSE}div{$ENDIF} TextFactor;
    with BottomAxis.LabelsFont do Size:=Size {$IFDEF FMX}/{$ELSE}div{$ENDIF} TextFactor;
  end;
end;

procedure TGalleryChart.AfterDraw(Sender: TObject);

  function ShouldDisplaySub:Boolean;
  var tmp : TChartGalleryPanel;
  begin
    tmp:=ParentGallery;
    result:=Assigned(tmp) and tmp.DisplaySub;
  end;

{$IFNDEF FMX}
var f : TGrayScaleFilter;
{$ENDIF}
var tmp : TColor;
    tmpR : TRect;
begin
  if FSmooth and (not ICreatingBitmap) then
     DrawSmoothChart;

  if not ICreatingBitmap then
    if Gradient.Visible then
       if ShouldDisplaySub then
          DrawSubGalleryArrow;

  {$IFNDEF FMX} // Pending
  if DisabledSeries then
  begin
    f:=TGrayScaleFilter.Create(nil);
    try
      f.Apply(TTeeCanvas3D(Canvas).Bitmap);
    finally
      f.Free;
    end;
  end;
  {$ENDIF}

  if IMouseInside and (Cursor<>TeeCursorDisabled) then
  begin
    if Color=clWhite then
       tmp:=clTeeSelected
    else
       tmp:=clWhite;

    tmpR:=Canvas.Bounds;
    Canvas.Frame3D(tmpR,tmp,clDkGray,1);
  end;
end;

type
   TFunctionAccess=class(TTeeFunction);

procedure TGalleryChart.CreateSeriesType(const AGallery:TChartGalleryPanel);

  Procedure CreateSeries(const AClass:TChartSeriesClass);
  var tmp       : Integer;
      tmpSeries : TChartSeries;
  begin
    for tmp:=1 to Math.Max(1,SeriesType.NumGallerySeries) do
    begin
      tmpSeries:=CreateNewSeries(nil,Self,AClass,SeriesType.FunctionClass);

      if SeriesType.SubIndex<>0 then
         TSeriesAccess(tmpSeries).SetSubGallery(tmpSeries,SeriesType.SubIndex);
    end;
  end;

var tmpClass : TChartSeriesClass;
    tmpFunc : TTeeFunction;
    t : Integer;
    tmpNum   : Integer;
    tmpDesc  : String;
begin
  tmpDesc:=SeriesType.Description^;

  tmpNum:=TeeNumFields(tmpDesc,TeeLineSeparator);

  for t:=1 to tmpNum do
      Title.Text.Add(TeeExtractField(tmpDesc,t,TeeLineSeparator){$IFDEF FMX}+' '{$ENDIF});

  tmpClass:=SeriesType.SeriesClass;

  if SeriesType.FunctionClass=nil then
  begin
    tmpFunc:=nil;

    if not Assigned(tmpClass) then
       tmpClass:=TLineSeries;
  end
  else
  begin
    tmpFunc:=SeriesType.FunctionClass.Create(nil);

    if not Assigned(tmpClass) then
    begin
      tmpClass:=TFunctionAccess(tmpFunc).GallerySource;

      if not Assigned(tmpClass) then
         tmpClass:=TFastLineSeries;
    end;
  end;

  CreateSeries(tmpClass);

  DisabledSeries:=AGallery.CheckSeries and
                  Assigned(AGallery.SelectedSeries) and
                  ( not Series[0].IsValidSourceOf(AGallery.SelectedSeries) );

  // Note: Call SetMargins before GalleryChanged3D, to allow TDoubleHorizBar
  // series customize the MarginLeft.
  SetMargins;

  TSeriesAccess(Series[0]).GalleryChanged3D(AGallery.FView3D);

  if Assigned(tmpFunc) then
  begin
    TFunctionAccess(tmpFunc).PrepareForGallery(Self);
    tmpFunc.Free;
  end
  else
    for t:=0 to SeriesCount-1 do
        TSeriesAccess(Series[t]).PrepareForGallery;
end;

{ TChartGalleryPanel }

Constructor TChartGalleryPanel.Create(AOwner:TComponent);

  function SelectCanvas(const ACanvas:String):Boolean;
  var t : Integer;
  begin
    result:=False;

    for t:=0 to TeeRenderClasses.Count-1 do
    if TTeeCanvasClass(TeeRenderClasses[t]).ClassName=ACanvas then
    begin
      CanvasClass:=TTeeCanvasClass(TeeRenderClasses[t]);
      result:=CanvasClass.IsAvailable;
      break;
    end;
  end;

  procedure SetRender;
  var tmp : TChart;
  begin
    // Default is 1 = TGDIPlusCanvas
    case TeeReadIntegerOption(TeeMsg_GalleryRender,1) of
      0: SelectCanvas('TTeeCanvas3D');
    else
      begin
        // Trick:
        // Try to startup GDI+ dll, by creating a dummy Chart:
        tmp:=TChart.Create(nil);
        tmp.Free;

        // Verify GDI+ is available, and can be activated:
        if not SelectCanvas('TGDIPlusCanvas') then
           SelectCanvas('TTeeCanvas3D');
      end;
    end;
  end;

begin
  inherited;

  CanSetFocus:=True;

  FunctionsVisible:=False;
  ISelectedChart:=nil;
  SelectedSeries:=nil;
  FOnSelectedChart:=nil;
  FOnChangeChart:=nil;

  FCharts:=TChartList.Create{$IFDEF D18}(False){$ENDIF};
  FCharts.IGallery:=Self;

  FView3D:=True;

  FAspectRatio:=1;

  FFocusRotation:=True;
  FNumRows:=TeeGalleryNumRows;
  FNumCols:=TeeGalleryNumCols;

  {$IFNDEF FMX}
  {$IFNDEF LCL}
  {$IFDEF D7}
  if not (csDesigning in ComponentState) then  // <-- breaks < D7 DFMs
     ParentBackground:=True;
  {$ENDIF}
  {$ENDIF}

  Color:=clTeeGallery;
  {$ENDIF}

  FSmooth:=DefaultSmooth;
  FOldSmooth:=FSmooth;

  SetRender;

  Smooth:=False;

  {$IFNDEF FMX}
  VertScrollBar.Tracking:=True;
  HorzScrollBar.Visible:=False;

  // D7 bug (TControlScrollBar.FDelay is not Cardinal)
  VertScrollBar.Smooth:={$IFNDEF D12}False{$ELSE}True{$ENDIF};
  {$ENDIF}
end;

Destructor TChartGalleryPanel.Destroy;
begin
  if FSmooth<>FOldSmooth then
     SaveSmooth(FSmooth);

  FCharts.Free;

  inherited;
end;

procedure TChartGalleryPanel.FreeAllCharts;
begin
  IRemoving:=True;
  try
    ISelectedChart:=nil;

    {$IFDEF D18}
    Charts.FreeAll;
    {$ELSE}
    Charts.Clear;
    {$ENDIF}
  finally
    IRemoving:=False;
  end;
end;

class Function TChartGalleryPanel.DefaultSmooth:Boolean;
begin
  result:=TeeReadBoolOption('SmoothGallery',False); // Do not localize
end;

class Function TChartGalleryPanel.DefaultMode:Integer;
begin
  result:=TeeReadIntegerOption('GalleryMode',0); // Do not localize
end;

class Procedure TChartGalleryPanel.SaveSmooth(Value:Boolean);
begin
  TeeSaveBoolOption('SmoothGallery',Value); // Do not localize
end;

class Procedure TChartGalleryPanel.SaveMode(Value:Integer);
begin
  TeeSaveIntegerOption('GalleryMode',Value); // Do not localize
end;

Procedure TChartGalleryPanel.SetNumCols(Value:Integer);
begin
  FNumCols:=Value;
  ResizeCharts;
end;

Procedure TChartGalleryPanel.SetNumRows(Value:Integer);
begin
  FNumRows:=Value;
  ResizeCharts;
end;

Procedure TChartGalleryPanel.SetAspectRatio(const Value:Single);
begin
  FAspectRatio:=Value;
  ResizeCharts;
end;

Procedure TChartGalleryPanel.Loaded;
begin
  inherited;

  {$IFNDEF FMX}
  {$IFDEF D7}
  // D7 bug (TControlScrollBar.FDelay is not Cardinal)
  VertScrollBar.Smooth:=False;
  {$ENDIF}
  {$ENDIF}
end;

{$IFDEF FMX}
procedure TChartGalleryPanel.MouseWheel(Shift: TShiftState; WheelDelta: Integer; var Handled: Boolean);
begin
  inherited;
end;
{$ELSE}
function TChartGalleryPanel.DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
                      MousePos: TPoint): Boolean;
begin
  result:=inherited DoMouseWheel(Shift,WheelDelta,MousePos);
  VertScrollBar.Position:=VertScrollBar.Position-(WheelDelta div 5);
end;
{$ENDIF}

Procedure TChartGalleryPanel.GetChartXY(const AChart:TGalleryChart; out x,y:Integer);
var tmp : Integer;
    t   : Integer;
    tmpCols : Integer;
begin
  tmp:=0;

  for t:=0 to Charts.Count-1 do
  if Charts[t]=AChart then
     break
  else
  if Charts[t].Visible then
     Inc(tmp);

  tmpCols:=CalcNumCols;

  if tmpCols>0 then
     y:=tmp div tmpCols
  else
     y:=0;

  x:=tmp mod tmpCols;
end;

procedure TChartGalleryPanel.ChartOnDblClick(Sender: TObject);
begin
  ISelectedChart:=TGalleryChart(Sender);

  if Assigned(FOnSelectedChart) then
     OnSelectedChart(Self);
end;

function TChartGalleryPanel.CalcNumCols:Integer;
var tmp : Integer;
begin
  result:=NumCols;

  if (result=0) and (NumRows>0) then
  begin
    tmp:=({$IFDEF FMX}Round{$ENDIF}(Height) div NumRows);

    if tmp>0 then
       result:={$IFDEF FMX}Round{$ENDIF}(Width) div tmp;
  end;
end;

Procedure TChartGalleryPanel.CalcChartWidthHeight;

  procedure CalcWidthHeight(AWidth,ANumCols:Integer);
  var tmp : Integer;
  begin
    {$IFDEF FMX}
    tmp:=0;
    {$ELSE}
    if BorderStyle=bsSingle then
       tmp:=BorderWidth
    else
       tmp:=0;

    {$IFNDEF LCL}
    if BevelInner<>bvNone then
       Inc(tmp,BevelWidth);

    if BevelOuter<>bvNone then
       Inc(tmp,BevelWidth);
    {$ENDIF}

    {$ENDIF}

    FColWidth:={$IFDEF FMX}Trunc{$ENDIF}(AWidth-tmp-1) div ANumCols;
    FRowHeight:=Round(FColWidth*FAspectRatio);
  end;

  function ScrollBarSize:Integer;
  begin
    {$IFDEF FMX}
    if VScrollBar=nil then
       result:=0
    else
    {$ENDIF}

      {$IFDEF FMX}
      result:=Round(VScrollBar.Width);
      {$ELSE}
      {$IFDEF MSWINDOWS}
      result:=GetSystemMetrics(SM_CXVSCROLL);
      {$ELSE}
      result:=Round(VertScrollBar.Size);
      {$ENDIF}
      {$ENDIF}
  end;

var tmp : Integer;
    tmpW,
    tmpH : Integer;
    tmpCols : Integer;
begin
  if NumRows=0 then
  begin
    if NumCols<1 then
       NumCols:=TeeGalleryNumCols;

    tmp:=Charts.Count;

    if tmp>((NumRows-1)*NumCols) then
       FNumRows:=1+((tmp-1) div NumCols)
    else
       FNumRows:=TeeGalleryNumRows;
  end;

  tmpCols:=CalcNumCols;

  if tmpCols>0 then
  begin
    {$IFDEF FMX}
    tmpW:=Round(Width);
    tmpH:=Round(Height);
    {$ELSE}
    tmpW:=Width;
    tmpH:=Height;
    {$ENDIF}

    // FMX bug: ClientWidth/ClientHeight aren't updated at OnResize event !
    // QC119329

    CalcWidthHeight(tmpW,tmpCols);

    // Vertical scrollbar necessary?
    if FRowHeight*FNumRows>tmpH then
       CalcWidthHeight(tmpW-ScrollBarSize,tmpCols);

    // VCL Problem:
    // Sometimes the Height / ClientHeight is incorrect (it seems its subtracting the non-visible
    // horizontal scrollbar height), and so our calculation fails, and the vertical scrollbar
    // appears when it shouldn't.
  end
  else
  begin
    FRowHeight:=0;
    FColWidth:=0;
  end;
end;

Function TChartGalleryPanel.CreateChart(Const AType:TTeeSeriesType):TCustomAxisPanel;
begin
  ICreating:=True;

  result:=TGalleryChart.Create(Self);
  result.Tag:=AType.SubIndex;

  result.Zoom.Allow:=False;

  result.AutoRepaint:=False;

  Charts.Add(TGalleryChart(result));

  with TGalleryChart(result) do
  begin
    Parent:=Self;

    Name:=TeeGetUniqueName(Owner,TeeMsg_GalleryChartName);
    ResizeChart(TGalleryChart(result));

    SeriesType:=AType;

    CreateSeriesType(Self);

    Smooth:=Self.Smooth;
    CanSetFocus:=Self.CanSetFocus;
  end;

  FinishAdd(TGalleryChart(result),TGalleryChart(result).DisabledSeries);

  result.AutoRepaint:=True;

  ICreating:=False;
end;

procedure TChartGalleryPanel.FinishAdd(const Chart:TGalleryChart; IsDisabled:Boolean=False);
{$IFDEF FMX}
var tmpGlow : TEffect;
{$ENDIF}
{$IFDEF USETHEMES}
var tmpColor  : Cardinal;
    tmpPColor : Cardinal;
{$ENDIF}
begin
  {$IFDEF FMX}
  tmpGlow:=TInnerGlowEffect.Create(Self);
  tmpGlow.Enabled:=False;

  tmpGlow.Trigger:='IsMouseOver=true';

  Chart.AddObject(tmpGlow);
  {$ENDIF}

  Chart.View3D:=View3D;
  
  if not ISubGallery then
     TGalleryChart(Chart).OnKeyDown:=ChartKeyDown;

  {$IFDEF USETHEMES}
  if ThemeServices.ThemesEnabled then
  begin
    tmpColor:=0;
    tmpPColor:=Integer(@tmpColor);
    GetThemeColor(ThemeServices.Theme[teTab],TABP_BODY,TIS_NORMAL,TMT_FILLCOLOR,tmpPColor);
    Color:=tmpPColor;
  end;
  {$ENDIF}

  with Chart do
  if IsDisabled then
  begin
    Cursor:=TeeCursorDisabled;
    OriginalCursor:=Cursor;
    OnClick:=nil;
    OnDblClick:=nil;
    OnMouseUp:=nil;
  end
  else
  begin
    Cursor:=crHandPoint;
    OriginalCursor:=Cursor;
    OnDblClick:=ChartOnDblClick;
    OnClick:=ChartEvent; // problem double-clicking: ChartMouseUp;
  end;

  // Change Canvas, only when different, and available (supported):
  if Assigned(CanvasClass) then
     if Chart.Canvas.ClassName<>CanvasClass.ClassName then
        if CanvasClass.IsAvailable then
           Chart.Canvas:=CanvasClass.Create;
end;

procedure TChartGalleryPanel.KeyDown(var Key: Word;
                          {$IFDEF FMX}var KeyChar:System.WideChar;{$ENDIF} Shift: TShiftState);

    // Returns the gallery Chart in XY position (Column / Row)
    Function FindChartXY(x,y:Integer):TGalleryChart;
    var tmpX : Integer;
        tmpY : Integer;
        t    : Integer;
    begin
      for t:=0 to Charts.Count-1 do
      begin
        result:=Charts[t];
        GetChartXY(result,tmpX,tmpY);
        if (x=tmpx) and (y=tmpy) then Exit;
      end;

      result:=nil;
    end;

var x,y : Integer;
    tmp : TGalleryChart;
begin
  inherited;

  GetChartXY(SelectedChart,x,y);

  Case Key of
    TeeKey_Left  : if x>0 then Dec(x);
    TeeKey_Right : if x<CalcNumCols then Inc(x);
    TeeKey_Up    : if y>0 then Dec(y);
    TeeKey_Down  : if ssAlt in Shift then
                   begin
                     if DisplaySub then ShowSubGallery
                   end
                   else if y<NumRows then Inc(y);

    TeeKey_Return: ChartOnDblClick(SelectedChart);
  end;

  tmp:=FindChartXY(x,y);

  if Assigned(tmp) and (tmp.Cursor=crHandPoint) then
     SelectChart(tmp);
end;

Procedure TChartGalleryPanel.ResizeChart(const AChart:TGalleryChart; TopOffset:Integer=0);
var tmp    : Integer;
    tmpCol : Integer;
    tmpW   : Integer;
    tmpRow : Integer;
    R      : TRect;
begin
  if {$IFDEF LCL}
     (not IResizingLCL) and
     {$ENDIF}
     Assigned(AChart) and (not (csDestroying in AChart.ComponentState)) and (CalcNumCols>0) and (NumRows>0) then
  begin
    GetChartXY(AChart,tmpCol,tmpRow);

    tmp:=0;

    {$IFNDEF FMX}
    if VertScrollBar.Visible then
       Dec(TopOffset,-VertScrollBar.Position);
    {$ENDIF}

    R.Left:=tmp+(tmpCol*ColWidth);
    R.Top:=tmp+(tmpRow*RowHeight)-TopOffset;

    if Assigned(Parent) then
       tmpW:={$IFDEF FMX}Round{$ENDIF}(ClientWidth)
    else
       tmpW:={$IFDEF FMX}Round{$ENDIF}(Width);

    R.Right:=R.Left+Math.Min(ColWidth,tmpW-2*tmp)-1;
    R.Bottom:=R.Top+Math.Min(RowHeight,Height-2*tmp)-1;

    {$IFDEF LCL}
    IResizingLCL:=True;
    try
    {$ENDIF}
      AChart.BoundsRect:=R;
    {$IFDEF LCL}
    finally
      IResizingLCL:=False;
    end;
    {$ENDIF}

    AChart.SetTitleFontSize;
  end;
end;

Procedure TChartGalleryPanel.ShowSelectedChart;
var t : Integer;
begin
  if not Assigned(SelectedChart) then
     for t:=0 to Charts.Count-1 do
         if Charts[t].Cursor<>TeeCursorDisabled then
         begin
           ISelectedChart:=Charts[t];
           break;
         end;

  if Assigned(SelectedChart) then
  begin
    SelectedChart.Focus(FView3D);

    if Assigned(FOnChangeChart) then
       OnChangeChart(Self);
  end;

  for t:=0 to Charts.Count-1 do
      if Charts[t]<>SelectedChart then
         Charts[t].UnFocus(FView3D);
end;

procedure TChartGalleryPanel.FindSelectedChart;
var t : Integer;
begin
  ISelectedChart:=nil;

  if Assigned(SelectedSeries) then
    for t:=0 to Charts.Count-1 do
    with Charts[t].Series[0] do
    if (ClassType=SelectedSeries.ClassType) and (FunctionType=nil) then
    begin
      ISelectedChart:=Charts[t];
      break;
    end;
end;

procedure TChartGalleryPanel.ChartKeyDown(Sender: TObject; var Key: Word;
                          {$IFDEF FMX}var KeyChar:System.WideChar;{$ENDIF} Shift: TShiftState);
begin
  KeyDown(Key,{$IFDEF FMX}KeyChar,{$ENDIF}Shift);
end;

Procedure TChartGalleryPanel.AddSubCharts(AGallery:TChartGalleryPanel);
begin
  tmpG:=AGallery;

  tmpType:=TTeeSeriesType.Create;
  try
    tmpType.SeriesClass:=TChartSeriesClass(tmpSeries.ClassType);
    tmpType.NumGallerySeries:=1;
    tmpType.FunctionClass:=nil;

    AGallery.FreeAllCharts;

    TSeriesAccess(tmpSeries).CreateSubGallery(CreateSubChart);
  finally
    tmpType.Free;
  end;
end;

Procedure TChartGalleryPanel.CreateSubGallery(const AGallery:TChartGalleryPanel; AClass:TChartSeriesClass);
var tmpN : Integer;
    tmpCols : Integer;
begin
  tmpSeries:=AClass.Create(nil);
  try
    AddSubCharts(AGallery);

    { calculate charts width and height }
    AGallery.CalcChartWidthHeight;

    tmpCols:=AGallery.NumCols;

    tmpN:=AGallery.Charts.Count div tmpCols;

    if AGallery.Charts.Count mod tmpCols > 0 then
       Inc(tmpN);

    {$IFDEF FMX}TControl{$ENDIF}(AGallery.Parent).Height:=8+AGallery.FRowHeight*tmpN;
    AGallery.NumRows:=tmpN;
  finally
    tmpSeries.Free;
  end;
end;

procedure TChartGalleryPanel.ShowSubGallery;
begin
  if Assigned(FOnSubShow) then
     FOnSubShow(Self);
end;

procedure TChartGalleryPanel.ChartEvent(Sender: TObject);
begin
  if Sender is TGalleryChart then
     SelectChart(TGalleryChart(Sender));
end;

// problem: double-clicking gallery ends-up calling MouseUp for the wrong chart
{
procedure TChartGalleryPanel.ChartMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: TCoordinate);
begin
  ChartEvent(Sender);
end;
}

function TChartGalleryPanel.ClickedArrow(const P:TPoint):Boolean;
begin
  result:=PointInRect(SelectedChart.ArrowRect, P);
end;

function TChartGalleryPanel.GetChart(Index:Integer):TGalleryChart;
begin
  result:=Charts[Index];
end;

procedure TChartGalleryPanel.SelectSeries(const Series: TChartSeries);
var t : Integer;
begin
  for t:=0 to Charts.Count-1 do
  if Charts[t].Series[0].SameClass(Series) then
  begin
    SelectChart(Charts[t]);
    break;
  end;
end;

procedure TChartGalleryPanel.SelectChart(const Chart: TGalleryChart);
begin
  if Chart<>ISelectedChart then
  begin
    ISelectedChart:=Chart;
    ShowSelectedChart;
  end;

  if Assigned(Chart) and DisplaySub and
     ClickedArrow(SelectedChart.GetCursorPos) then
        ShowSubGallery;
end;

procedure TChartGalleryPanel.SetView3D(Value:Boolean);
var t : Integer;
begin
  if Value<>FView3D then
  begin
    FView3D:=Value;

    for t:=0 to Charts.Count-1 do
    begin
      // Note: Call SetMargins before GalleryChanged3D, to allow TDoubleHorizBar
      // series customize the MarginLeft.
      Charts[t].SetMargins;

      if Charts[t].SeriesCount>0 then
         TSeriesAccess(Charts[t].Series[0]).GalleryChanged3D(FView3D)
      else
         Charts[t].View3D:=FView3D;
    end;
  end;
end;

procedure TChartGalleryPanel.SetSmooth(Value:Boolean);
var t : Integer;
begin
  if not (csReading in ComponentState) then
  if Value<>FSmooth then
  begin
    FSmooth:=Value;
    for t:=0 to Charts.Count-1 do Charts[t].Smooth:=FSmooth;
  end;
end;

Procedure TChartGalleryPanel.CreateChartList(ASeriesList:Array of TChartSeriesClass);
var t     : Integer;
    AType : TTeeSeriesType;
begin
  FreeAllCharts;

  for t:=Low(ASeriesList) to High(ASeriesList) do
  begin
    AType:=TeeSeriesTypes.Find(ASeriesList[t]);
    if Assigned(AType) then CreateChart(AType);
  end;

  ResizeCharts;

  FindSelectedChart;
  ShowSelectedChart;
end;

Procedure TChartGalleryPanel.DoRealignCharts;
var t : Integer;
begin
  if (not ICreating) and (not IRemoving) and (not IResizing) then
  begin
    if Assigned(Charts) and (Charts.Count>0) then
    begin
      IResizing:=True;

      CalcChartWidthHeight;

      {$IFNDEF LCL}
      {$IFNDEF FMX}
      DisableAutoRange;
      {$ENDIF}
      {$ENDIF}

      for t:=0 to Charts.Count-1 do
          ResizeChart(Charts[t]);

      {$IFNDEF LCL}
      {$IFNDEF FMX}
      EnableAutoRange;
      {$ENDIF}
      {$ENDIF}

      {$IFDEF FMX}
      inherited;
      {$ENDIF}

      IResizing:=False;
    end;
  end;
end;

Procedure TChartGalleryPanel.ResizeCharts;
begin
  {$IFDEF FMX}
  {$IFDEF D18}
  InvalidateContentSize;
  {$ELSE}
  DoRealignCharts;
  {$ENDIF}
  {$ELSE}
  DoRealignCharts;
  {$ENDIF}
end;

{$IFDEF FMX}
{$IFDEF D17}
procedure TChartGalleryPanel.DoRealign;
begin
  inherited;
  DoRealignCharts;
end;
{$ENDIF}
{$ENDIF}

procedure TChartGalleryPanel.Resize;
begin
  inherited;

  if not ICreating then
     ResizeCharts;
end;

Function TChartGalleryPanel.ValidSeries(Const ASeriesType:TTeeSeriesType; Const APage:String):Boolean;
begin
  result:= (ASeriesType.GalleryPage^=APage) and
           (
             (FunctionsVisible and Assigned(ASeriesType.FunctionClass)) or
             ((not FunctionsVisible) and (not Assigned(ASeriesType.FunctionClass)))

           );
end;

Function TChartGalleryPanel.CreateSubChart(Const ATitle:String):TCustomAxisPanel;
var tmp : Integer;
begin
  tmpType.Description:=@ATitle;
  tmp:=tmpG.Charts.Count;
  result:=tmpG.CreateChart(tmpType);
  TSeriesAccess(tmpSeries).SetSubGallery(result[0],tmp);
  result.Tag:=tmp;
end;

Procedure TChartGalleryPanel.CreateGalleryPage(Const PageName:String);
var tmp : TTeeSeriesType;
    t   : Integer;
begin
  FreeAllCharts;

  with TeeSeriesTypes do
  for t:=0 to Count-1 do
  begin
    tmp:=Items[t];

    if ValidSeries(tmp,PageName) then
       CreateChart(tmp);
  end;

  ResizeCharts;
  
  FindSelectedChart;
  ShowSelectedChart;
end;

{$IFNDEF FMX}
{$IFDEF MSWINDOWS}
procedure TChartGalleryPanel.WMGetDlgCode(var Message: TWMGetDlgCode);
begin
  Message.Result := DLGC_WANTARROWS;
end;
{$ENDIF}
{$ENDIF}

function TChartGalleryPanel.SelectedSeriesClass:TChartSeriesClass;
begin
  if Assigned(SelectedChart) then
  begin
    tmpSeries:=SelectedChart.Series[0]; // Keep for later use
    result:=TChartSeriesClass(tmpSeries.ClassType);
  end
  else
    result:=nil;
end;

// Warning: Deprecated / unused AFunctionClass and SubIndex !
function TChartGalleryPanel.GetSeriesClass(out AClass:TChartSeriesClass;
                            out AFunctionClass:TTeeFunctionClass;
                            out ASubIndex:Integer):Boolean;
begin
  result:=Assigned(SelectedChart);

  if result then
  begin
    AClass:=SelectedSeriesClass;
    ASubIndex:=SelectedChart.Tag;
    AFunctionClass:=nil;
  end;
end;

procedure TChartGalleryPanel.UseTheme(const Theme: TChartThemeClass);
var t  : Integer;
    tt : Integer;
    tmp : TChartTheme;
begin
  if Assigned(Theme) then
  begin
    tmp:=Theme.Create(nil);
    try
      for t:=0 to Charts.Count-1 do
      begin
        tmp.Chart:=Charts[t];
        tmp.Apply;
        for tt:=0 to Charts[t].SeriesCount-1 do
            TSeriesAccess(Charts[t][tt]).PrepareForGallery;
      end;
    finally
      tmp.Free;
    end;
  end;
end;

initialization
  RegisterTeeStandardSeries;
end.

