{*********************************************}
{  TeeChart Pro Charting Library              }
{  Themes Editor Dialog                       }
{  Copyright (c) 2003-2020 by Steema Software }
{  All Rights Reserved                        }
{*********************************************}
unit TeeThemeEditor;
{$I TeeDefs.inc}

interface

uses {$IFNDEF LINUX}
     Windows, Messages,
     {$ENDIF}

     Classes, SysUtils,

     {$IFDEF D17}
     System.UITypes, System.Types,
     {$ENDIF}

     Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, ExtCtrls, Buttons,
     Grids,

     {$IFNDEF D15}
     FileCtrl,
     {$ENDIF}

     Menus,

     {$IFDEF MSWINDOWS}
     TeeGDIPlus,
     {$ENDIF}

     TeeProcs, TeEngine, Chart, TeeThemes, TeeTools, TeCanvas, TeeDraw3D,
     TeeChartGrid, TeeGalleryPanel;

type
  TChartThemeSelector = class(TForm)
    Panel1: TPanel;
    PageControl1: TPageControl;
    TabPreview: TTabSheet;
    PreviewChart: TChart;
    PageControl2: TPageControl;
    TabSheet2: TTabSheet;
    PanelBottom: TPanel;
    Panel3: TPanel;
    BOK: TButton;
    Button2: TButton;
    ChartTool1: TRotateTool;
    ScaledChart: TDraw3D;
    TabPalette: TTabSheet;
    ChartGrid1: TChartGrid;
    BSaveAs: TButton;
    SpeedView: TSpeedButton;
    PopupView: TPopupMenu;
    CBView3D: TMenuItem;
    CBScale: TMenuItem;
    Panel5: TPanel;
    TabGallery: TTabSheet;
    Splitter1: TSplitter;
    ChartGalleryPanel1: TChartGalleryPanel;
    LBThemes: TTreeView;
    Panel2: TPanel;
    Label1: TLabel;
    LBPalette: TListBox;
    Splitter2: TSplitter;
    TabFonts: TTabSheet;
    Panel4: TPanel;
    Label2: TLabel;
    LBFonts: TListBox;
    Panel6: TPanel;
    Label3: TLabel;
    TabColors: TTabSheet;
    Panel7: TPanel;
    Panel8: TPanel;
    LBColors: TListBox;
    SBFontUp: TSpeedButton;
    SBFontDown: TSpeedButton;
    Panel9: TPanel;
    Label5: TLabel;
    Panel10: TPanel;
    Label4: TLabel;
    TBOffset: TTrackBar;
    Panel11: TPanel;
    procedure LBThemesClick(Sender: TObject);
    procedure BOKClick(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure ScaledChartAfterDraw(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure PageControl1Change(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure ChartGrid1ChangeColor(Sender: TObject);
    procedure BSaveAsClick(Sender: TObject);
    procedure SpeedViewMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure CBScaleClick(Sender: TObject);
    procedure CBView3DClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure ChartGalleryPanel1ChangeChart(Sender: TObject);
    procedure ChartGalleryPanel1SelectedChart(Sender: TObject);
    procedure LBPaletteClick(Sender: TObject);
    procedure LBFontsClick(Sender: TObject);
    procedure LBColorsClick(Sender: TObject);
    procedure LBColorsDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure LBFontsDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure LBFontsMeasureItem(Control: TWinControl; Index: Integer;
      var Height: Integer);
    procedure SBFontUpClick(Sender: TObject);
    procedure SBFontDownClick(Sender: TObject);
    procedure LBColorsDblClick(Sender: TObject);
    procedure TBOffsetChange(Sender: TObject);
  private
    { Private declarations }
    IBasic,
    ICustom : TTreeNode;
    PaletteSeries : TChartSeries;

    ICurrentColors : TColorArray;
    
    IChangingColors,
    IChangingFonts,
    ISelecting : Boolean;

    procedure AddToGallery(const AItem:TTreeNode);
    procedure ApplyScheme(const AColors:TColorArray);
    procedure ApplyThemeTo(const AItem:TTreeNode; const AChart:TCustomChart);
    procedure CheckScale;
    procedure CreatePreview(const AChart:TCustomChart; const AItem:TTreeNode=nil);
    procedure InitPreviewChart;

    {$IFDEF MSWINDOWS}
    procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED;
    {$ENDIF}

    procedure RecreateGallery;
    procedure RefreshColorGrid;
    procedure SelectAtGallery;
  public
    { Public declarations }
    Chart : TCustomChart;
    AutoApply : Boolean;

    class function CreateEditor(const AOwner:TComponent;
                   const APanel:TCustomTeePanel):TChartThemeSelector;

    Function SelectedTheme:TChartThemeClass;
  end;

// Shows the Chart Theme editor. Returns the selected Theme class or nil.
Function ChartThemeSelector(const AChart:TCustomChart):TChartThemeClass;

// Adds all available registered Chart Themes to "Items"
Procedure AddChartThemes(const Items:TStrings);

Procedure ShowThemesEditor(Value:Boolean);

implementation

{$IFNDEF LCL}
{$R *.DFM}
{$ELSE}
{$R *.lfm}
{$ENDIF}

uses Math,
     TeePenDlg, TeeEditCha, TeeConst, TeeProCo, TeeStore;

const
  Tee_CurrentNode=5555;

Procedure AddChartThemes(const Items:TStrings);
var t : Integer;
    tmp : TChartTheme;
    tmpPath : String;
    tmpSt : TStrings;
begin
  for t:=0 to ChartThemes.Count-1 do
  begin
    tmp:=ChartThemes[t].Create(nil);
    try
      Items.AddObject(tmp.Description,TObject(ChartThemes[t]));
    finally
      tmp.Free;
    end;
  end;

  tmpPath:=TThemesList.ThemesPath;

  if tmpPath<>'' then
  begin
    tmpSt:=TeeGetFilesFromDir(tmpPath+'\*.'+TeeMsg_TeeExtension);
    try
      for t:=0 to tmpSt.Count-1 do
          Items.Add(RemoveFileExtension(tmpSt[t]));
    finally
      tmpSt.Free;
    end;
  end;
end;

Procedure AddChartThemesTree(const Basic,Custom:TTreeNode);
var t : Integer;
    tmp : TChartTheme;
    tmpPath : String;
    tmpSt : TStrings;
    tmpNodes : TTreeNodes;
begin
  tmpNodes:=TTreeView(Basic.TreeView).Items;

  for t:=0 to ChartThemes.Count-1 do
  begin
    tmp:=ChartThemes[t].Create(nil);
    try
      tmpNodes.AddChildObject(Basic,tmp.Description,TObject(ChartThemes[t])).ImageIndex:=t;
    finally
      tmp.Free;
    end;
  end;

  tmpPath:=TThemesList.ThemesPath;

  if tmpPath<>'' then
  begin
    tmpSt:=TeeGetFilesFromDir(tmpPath+'\*.'+TeeMsg_TeeExtension);
    try
      for t:=0 to tmpSt.Count-1 do
          tmpNodes.AddChild(Custom,RemoveFileExtension(tmpSt[t])).ImageIndex:=t+Basic.Count;
    finally
      tmpSt.Free;
    end;
  end;
end;

Function ChartThemeSelector(const AChart:TCustomChart):TChartThemeClass;
begin
  with TChartThemeSelector.Create(nil) do
  try
    Chart:=AChart;
    if ShowModal=mrOk then
       result:=SelectedTheme
    else
       result:=nil;
  finally
    Free;
  end;
end;

procedure TChartThemeSelector.ApplyThemeTo(const AItem:TTreeNode; const AChart:TCustomChart);
var tmp : TChartThemeClass;
begin
  tmp:=TChartThemeClass(AItem.Data);

  if Assigned(tmp) then
  begin
    if LBPalette.ItemIndex=0 then
       ApplyChartTheme(tmp,AChart)
    else
       ApplyChartTheme(tmp,AChart,LBPalette.ItemIndex-1);
  end
  else
    TThemesList.Apply(AChart,TThemesList.ThemesPath+'\'+AItem.Text+'.'+TeeMsg_TeeExtension);
end;

procedure TChartThemeSelector.LBThemesClick(Sender: TObject);
var tmp : TTreeNode;
begin
  tmp:=LBThemes.Selected;
  BOK.Enabled:=False;

  if Assigned(tmp) and (tmp.Count=0) and (tmp<>IBasic) and (tmp<>ICustom) then
  begin
    if tmp.ImageIndex<>Tee_CurrentNode then
    begin
      ApplyThemeTo(tmp,PreviewChart);
      BOK.Enabled:=True;
    end
    else
      InitPreviewChart;

    // Enable saving theme only for "default" (current) chart theme:
    BSaveAs.Enabled:=tmp.ImageIndex=Tee_CurrentNode;

    RefreshColorGrid;

    if CBScale.Checked then
       ScaledChart.Invalidate;

    ISelecting:=True;
    try
      SelectAtGallery;
    finally
      ISelecting:=False;
    end;

    if AutoApply then
       BOKClick(Self);
  end;
end;

Function TChartThemeSelector.SelectedTheme:TChartThemeClass;
begin
  if Assigned(LBThemes.Selected) and (LBThemes.Selected.Count=0) and
     (LBThemes.Selected.ImageIndex<>Tee_CurrentNode) then

     result:=TChartThemeClass(LBThemes.Selected.Data)
  else
     result:=nil;
end;

procedure TChartThemeSelector.InitPreviewChart;
begin
  PreviewChart.FreeAllSeries;

  if Assigned(Chart) then
  begin
    CloneChart(PreviewChart,Chart,PreviewChart,True);

    CheckScale;

    CBView3D.Checked:=Chart.View3D;
  end;
end;

procedure TChartThemeSelector.BOKClick(Sender: TObject);
begin
  Chart.View3D:=CBView3D.Checked;

  if LBThemes.Selected.ImageIndex<>Tee_CurrentNode then
     ApplyThemeTo(LBThemes.Selected,Chart);

  BOK.Enabled:=False;
end;

procedure TChartThemeSelector.FormShow(Sender: TObject);
var tmpCurrent : TTreeNode;
begin
  // Force recreating all treenode items, this might fail if we're coming
  // from a repeated FormShow call from Chart Editor changing tabs and parents:
  if not LBThemes.HandleAllocated then
     LBThemes.HandleNeeded;

  // Fill registered Themes...
  LBThemes.Items.Clear;

  tmpCurrent:=LBThemes.Items.Add(nil,TeeMsg_Current);
  tmpCurrent.ImageIndex:=Tee_CurrentNode;

  IBasic:=LBThemes.Items.Add(nil,TeeMsg_GalleryStandard);
  ICustom:=LBThemes.Items.Add(nil,'Custom');

  IBasic.Expanded:=True;
  LBThemes.Selected:=tmpCurrent;
  LBThemesClick(Self);

  BOk.Enabled:=False;

  AddChartThemesTree(IBasic,ICustom);

  TeeTranslateControl(Self);
end;

// Returns tab inside APage with ACaption title. Or nil if none.
function FindTab(const APage:TPageControl; const ACaption:String):TTabSheet;
var t : Integer;
begin
  for t:=0 to APage.PageCount-1 do
  if APage.Pages[t].Caption=ACaption then
  begin
    result:=APage.Pages[t];
    exit;
  end;

  result:=nil;
end;

Procedure TeeThemeShowEditor(AOwner:TComponent; APanel:TCustomTeePanel;
                             ATab:TTabSheet; APageControl:TPageControl);
var tmpForm : TChartThemeSelector;
    tmpActive : TTabSheet;
begin
  if APanel is TCustomChart then
  begin
    tmpActive:=APageControl.ActivePage;

    if not Assigned(ATab) then
       ATab:=FindTab(APageControl,TeeMsg_Themes);

    if not Assigned(ATab) then
    begin
      ATab:=TTabSheet.Create(AOwner);
      ATab.Caption:=TeeMsg_Themes;
      ATab.PageControl:=APageControl;
    end
    else
    if (ATab.ControlCount=0) and (ATab.Caption=TeeMsg_Themes) then
    begin
      tmpForm:=TChartThemeSelector.CreateEditor(AOwner,APanel);

      AddFormTo(tmpForm,ATab);

      tmpForm.RequestAlign;
    end;

    APageControl.ActivePage:=tmpActive;
  end;
end;

procedure TChartThemeSelector.RefreshColorGrid;
var t : Integer;
    p : TColorArray;
begin
  {$IFNDEF D7}
  p:=nil; // Avoid warning in D5 and D6
  {$ENDIF}
  
  if Assigned(PaletteSeries) then
  begin
    PaletteSeries.Clear;

    p:=PreviewChart.ColorPalette;

    if Length(p)=0 then
       p:=TeeColorPalette;

    for t:=0 to Length(p)-1 do
        PaletteSeries.Add(t,'',p[t]);

    ChartGrid1.RecalcDimensions;
    ChartGrid1.Invalidate;
  end;
end;

procedure TChartThemeSelector.CheckScale;
begin
  if CBScale.Checked then
  begin
    PreviewChart.Align:=alNone;
    PreviewChart.Width:=Chart.Width;
    PreviewChart.Height:=Chart.Height;
    PreviewChart.Hide;
    ScaledChart.Show;
  end
  else
  begin
    PreviewChart.Align:=alClient;
    PreviewChart.Show;
    ScaledChart.Hide;
  end;
end;

procedure TChartThemeSelector.ScaledChartAfterDraw(Sender: TObject);
var tmp : TBitmap;
begin
  if CBScale.Checked then
  begin
    if not PreviewChart.Canvas.ReDrawBitmap then
       PreviewChart.Draw;

    tmp:=TTeeCanvas3D(PreviewChart.Canvas).Bitmap;
    if Assigned(tmp) then
       SmoothStretch(tmp,TTeeCanvas3D(ScaledChart.Canvas).Bitmap);
  end;
end;

procedure TChartThemeSelector.FormCloseQuery(Sender: TObject;
  var CanClose: Boolean);
begin
  if BOk.Enabled then
  Case MessageDlg(TeeMsg_SureToApply,mtConfirmation,[mbYes,mbNo,mbCancel],0) of
    mrYes: begin
             BOkClick(Self);
             CanClose:=not BOk.Enabled;
           end;
    mrNo: begin
            BOk.Enabled:=False;
            CanClose:=True;
          end;
    mrCancel: CanClose:=False;
  end;
end;

{$IFDEF MSWINDOWS}
procedure TChartThemeSelector.CMShowingChanged(var Message: TMessage);
begin
  inherited;

  {$IFNDEF LCL}
  if Assigned(Parent) then
     Parent.UpdateControlState;
  {$ENDIF}
end;
{$ENDIF}

procedure InstallHook;
begin
  TeeOnShowEditor.Add(@TeeThemeShowEditor);
end;

procedure RemoveHook;
begin
  TeeOnShowEditor.Remove(@TeeThemeShowEditor);
end;

procedure ShowThemesEditor(Value:Boolean);
begin
  if Value then
  begin
    if Not Assigned(TeeThemeSelectorHook) then
    begin
      InstallHook;
      TeeThemeSelectorHook:=ChartThemeSelector;
    end;
  end
  else
  begin
    TeeThemeSelectorHook := nil;
    RemoveHook;
  end;
end;

procedure TChartThemeSelector.SelectAtGallery;
begin
  if ChartGalleryPanel1.Charts.Count>0 then
     if Assigned(LBThemes.Selected) and (LBThemes.Selected.Count=0) then
        if LBThemes.Selected.ImageIndex=Tee_CurrentNode then
           ChartGalleryPanel1.SelectChart(ChartGalleryPanel1.Chart[0])
        else
           ChartGalleryPanel1.SelectChart(ChartGalleryPanel1.Chart[LBThemes.Selected.ImageIndex]);
end;

procedure TChartThemeSelector.RecreateGallery;
var t : Integer;
begin
  // Theme Gallery should be recreated all the time, because the Chart
  // might have changed:
  ChartGalleryPanel1.FreeAllCharts;

  for t:=0 to IBasic.Count-1 do
      AddToGallery(IBasic.{$IFDEF LCL}Items{$ELSE}Item{$ENDIF}[t]);

  for t:=0 to ICustom.Count-1 do
      AddToGallery(ICustom.{$IFDEF LCL}Items{$ELSE}Item{$ENDIF}[t]);

  ChartGalleryPanel1.ResizeCharts;

  SelectAtGallery;
end;

procedure TChartThemeSelector.PageControl1Change(Sender: TObject);

  procedure InitColorGrid;
  begin
    PaletteSeries:=TChartSeries.Create(nil);
    PaletteSeries.MandatoryValueList.Name:=TeeMsg_Index;

    ChartGrid1.Series:=PaletteSeries;
    ChartGrid1.ShowFields:=False;
    ChartGrid1.EditorMode:=False;
    ChartGrid1.AllowAppend:=False;

    ChartGrid1.ColWidths[2]:=90;
  end;

  procedure FillColors;
  var t : Integer;
  begin
    LBColors.Items.Clear;

    LBColors.Items.Add('');

    for t:=Low(TeeColorSchemes) to High(TeeColorSchemes) do
        LBColors.Items.Add('');
  end;

  function FindCurrentColors:Integer;

    function EqualColors(const AColors:TColorArray):Boolean;
    var tmpLow,
        t : Integer;
    begin
      result:=Length(ICurrentColors)<=Length(AColors);

      if result then
      begin
        tmpLow:=Low(AColors);

        for t:=0 to High(ICurrentColors) do
            if ICurrentColors[t]<>AColors[tmpLow+t] then
            begin
              result:=False;
              break;
            end;
      end;
    end;

  var t : Integer;
  begin
    result:=0;

    SetLength(ICurrentColors,5);

    ICurrentColors[0]:=Chart.Legend.Color;
    ICurrentColors[1]:=Chart.Legend.Pen.Color;
    ICurrentColors[2]:=Chart.Legend.Font.Color;

    ICurrentColors[3]:=Chart.Walls.Back.Color;
    ICurrentColors[4]:=Chart.Walls.Bottom.Color;

    for t:=Low(TeeColorSchemes) to High(TeeColorSchemes) do
        if EqualColors(TeeColorSchemes[t]) then
        begin
          result:=t+1;

          ICurrentColors:=TeeColorSchemes[t];

          break;
        end;
  end;

begin
  if PageControl1.ActivePage=TabPalette then
  begin
    if LBPalette.Items.Count=0 then
    begin
      // Fill Color Palette combo...
      TColorPalettes.AddTo(LBPalette.Items,True);
      LBPalette.ItemIndex:=0;
    end;

    if ChartGrid1.Series=nil then
       InitColorGrid;

    RefreshColorGrid;
  end
  else
  if PageControl1.ActivePage=TabPreview then
     InitPreviewChart
  else
  if PageControl1.ActivePage=TabGallery then
     RecreateGallery
  else
  if PageControl1.ActivePage=TabFonts then
  begin
    IChangingFonts:=True;
    try
      if LBFonts.Items.Count=0 then
         LBFonts.Items:=Screen.Fonts;

      LBFonts.ItemIndex:=LBFonts.Items.IndexOf(Chart.Legend.Font.Name);
    finally
      IChangingFonts:=False;
    end;
  end
  else
  if PageControl1.ActivePage=TabColors then
  begin
    IChangingColors:=True;
    try
      if LBColors.Items.Count=0 then
         FillColors;

      LBColors.ItemIndex:=FindCurrentColors;
    finally
      IChangingColors:=False;
    end;
  end
end;

procedure TChartThemeSelector.AddToGallery(const AItem:TTreeNode);
var tmp : TGalleryChart;
begin
  tmp:=TGalleryChart.Create(Self);
  ChartGalleryPanel1.Charts.Add(tmp);
  ChartGalleryPanel1.FinishAdd(tmp);

  tmp.Tag:=AItem.ImageIndex;

  tmp.Title.Caption:=AItem.Text;
  tmp.Axes.Hide;
  tmp.TabStop:=False;
  tmp.View3D:=False;

  CreatePreview(tmp,AItem);

  tmp.Parent:=ChartGalleryPanel1;

  //tmp.OnEnter:=nil;
  //tmp.Title.Visible:=True;
end;

procedure TChartThemeSelector.CreatePreview(const AChart:TCustomChart; const AItem:TTreeNode=nil);
var tmpP : TChart;
begin
  // Create preview
  tmpP:=TChart.Create(nil);
  try
    CloneChart(tmpP,Chart,tmpP,True);

    if (tmpP.SeriesCount>0) and (tmpP[0].Count=0) then
       tmpP[0].FillSampleValues;

    if Assigned(AItem) and (AItem.ImageIndex<>Tee_CurrentNode) then
       ApplyThemeTo(AItem,tmpP);

    tmpP.View3D:=CBView3D.Checked;
    
    AChart.BackImage.Graphic:=tmpP.TeeCreateBitmap; // leak?
    AChart.BackImageInside:=True;
  finally
    tmpP.Free;
  end;
end;

procedure TChartThemeSelector.FormDestroy(Sender: TObject);
begin
  PaletteSeries.Free;
end;

procedure TChartThemeSelector.ChartGrid1ChangeColor(Sender: TObject);
var Index : Integer;
begin
  Index:=ChartGrid1.Row-ChartGrid1.FirstRowNum;
  PreviewChart.ColorPalette[Index]:=PaletteSeries.ValueColor[Index];
  PreviewChart.Invalidate;

  if CBScale.Checked then
     ScaledChart.Invalidate;
end;

procedure TChartThemeSelector.BSaveAsClick(Sender: TObject);

  function UniqueThemeName(const Path,Prefix:String):String;
  var t : Integer;
  begin
    result:=Prefix;

    t:=1;

    while FileExists(Path+'\'+result+'.'+TeeMsg_TeeExtension) do
    begin
      result:=Prefix+' '+IntToStr(t);
      Inc(t);
    end;
  end;

var tmp : String;
    tmpPath : String;
begin
  tmpPath:=TThemesList.ThemesPath;

  if tmpPath='' then
     if TeeSelectFolder(TeeMsg_SelectFolder,'',tmpPath) then
        TeeSaveStringOption(TeeMsg_ThemesPath,tmpPath)
     else
        Exit;

  if {$IFDEF D15}SysUtils.{$ENDIF}DirectoryExists(tmpPath) then
  begin
    tmp:=UniqueThemeName(tmpPath,'My Theme');

    if InputQuery(TeeMsg_NewChart,TeeMsg_ChartName,tmp) then
    begin
      SaveChartToFile(Chart,tmpPath+'\'+tmp,False);
      LBThemes.Items.Add(ICustom,tmp);
    end;
  end;
end;

procedure TChartThemeSelector.SpeedViewMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var P : TPoint;
begin
  P.X:=0;
  P.Y:=SpeedView.BoundsRect.Bottom;
  P:=SpeedView.ClientToScreen(P);
  PopupView.Popup(P.X,P.Y);
end;

procedure TChartThemeSelector.CBScaleClick(Sender: TObject);
begin
  CBScale.Checked:=not CBScale.Checked;
  CheckScale;
  SpeedView.Down:=False;
end;

procedure TChartThemeSelector.CBView3DClick(Sender: TObject);
begin
  CBView3D.Checked:=not CBView3D.Checked;

  PreviewChart.View3D:=CBView3D.Checked;
  if CBScale.Checked then ScaledChart.Invalidate;

  if PageControl1.ActivePage=TabGallery then
     RecreateGallery;

  BOk.Enabled:=True;
  SpeedView.Down:=False;
end;

procedure TChartThemeSelector.FormCreate(Sender: TObject);
begin
  IChangingFonts:=True;
  PageControl1.ActivePage:=TabPreview;
end;

procedure TChartThemeSelector.ChartGalleryPanel1ChangeChart(
  Sender: TObject);

  function FindNodeImageIndex(AIndex:Integer):TTreeNode;
  var t : Integer;
  begin
    result:=nil;

    for t:=0 to LBThemes.Items.Count-1 do
        if (LBThemes.Items[t].Count=0) and (LBThemes.Items[t].ImageIndex=AIndex) then
        begin
          result:=LBThemes.Items[t];
          exit;
        end;
  end;

begin
  BSaveAs.Enabled:=ChartGalleryPanel1.SelectedChart.Tag=Tee_CurrentNode;

  if not ISelecting then
  begin
    LBThemes.Selected:=FindNodeImageIndex(ChartGalleryPanel1.SelectedChart.Tag);
    LBThemesClick(Self);
  end;
end;

procedure TChartThemeSelector.ChartGalleryPanel1SelectedChart(Sender: TObject);
begin
  PageControl1.ActivePage:=TabPreview;
end;

procedure TChartThemeSelector.LBPaletteClick(Sender: TObject);
begin
  if LBPalette.ItemIndex=0 then
     LBThemesClick(Self)
  else
     PreviewChart.ColorPaletteIndex:=LBPalette.ItemIndex-1;

  if CBScale.Checked then
     ScaledChart.Invalidate;

  RefreshColorGrid;

  BOK.Enabled:=True;

  if (LBPalette.ItemIndex>0) and AutoApply then
     Chart.ColorPaletteIndex:=LBPalette.ItemIndex-1;
end;

class function TChartThemeSelector.CreateEditor(const AOwner: TComponent;
  const APanel: TCustomTeePanel): TChartThemeSelector;
begin
  result:=TChartThemeSelector.Create(AOwner);

  with result do
  begin
    Chart:=APanel as TCustomChart;

    Button2.Visible:=False;
    BOK.Left:=Button2.Left;
    BOK.ModalResult:=mrNone;
    BOK.Caption:=TeeMsg_Apply;
    Align:=alClient;

    PageControl2.Width:=100;
  end;
end;

procedure TChartThemeSelector.LBFontsClick(Sender: TObject);
begin
  if not IChangingFonts then
  begin
    TThemesList.ApplyFont(Chart,LBFonts.Items[LBFonts.ItemIndex]);

    if CBScale.Checked then
       ScaledChart.Invalidate;
  end;
end;

procedure TChartThemeSelector.ApplyScheme(const AColors:TColorArray);
begin
  TThemesList.ApplyColors(Chart,AColors,TBOffset.Position);
end;

procedure TChartThemeSelector.LBColorsClick(Sender: TObject);
begin
  if not IChangingColors then
  begin
    if LBColors.ItemIndex=0 then
       ApplyScheme(ICurrentColors)
    else
       ApplyScheme(TeeColorSchemes[LBColors.ItemIndex-1]);

    if CBScale.Checked then
       ScaledChart.Invalidate;
  end;
end;

procedure TChartThemeSelector.LBColorsDrawItem(Control: TWinControl;
  Index: Integer; Rect: TRect; State: TOwnerDrawState);
var tmp : TColorArray;
    t,x,y,
    w,h : Integer;
begin
  {$IFNDEF D7}
  tmp:=nil; // skip warning
  {$ENDIF}

  LBColors.Canvas.FillRect(Rect);

  if Index<>-1 then
  begin
    if Index=0 then
       tmp:=ICurrentColors
    else
       tmp:=TeeColorSchemes[Index-1];

    LBColors.Canvas.Brush.Style:=bsSolid;
    LBColors.Canvas.Pen.Style:=psSolid;
    LBColors.Canvas.Pen.Color:=clBlack;

    if Length(tmp)>0 then
    begin
      w:=((Rect.Right-Rect.Left-2) div Length(tmp))-2;
      h:=Rect.Bottom-Rect.Top-4;

      for t:=Low(tmp) to High(tmp) do
      begin
        LBColors.Canvas.Brush.Color:=tmp[t];

        x:=2+Rect.Left+(w+2)*t;
        y:=2+Rect.Top;

        LBColors.Canvas.Rectangle(x,y,x+w,y+h);
      end;
    end;
  end;
end;

procedure TChartThemeSelector.LBFontsDrawItem(Control: TWinControl;
  Index: Integer; Rect: TRect; State: TOwnerDrawState);
var s : String;
begin
  LBFonts.Canvas.FillRect(Rect);

  if Index<>-1 then
  begin
    s:=LBFonts.Items[Index];
    LBFonts.Canvas.Font.Name:=s;
    LBFonts.Canvas.TextOut(Rect.Left,Rect.Top,s);
  end;
end;

procedure TChartThemeSelector.LBFontsMeasureItem(Control: TWinControl;
  Index: Integer; var Height: Integer);
var s : String;
begin
  if Index<>-1 then
  begin
    s:=LBFonts.Items[Index];
    LBFonts.Canvas.Font.Name:=s;
    Height:=LBFonts.Canvas.TextHeight(s);
  end;
end;

procedure TChartThemeSelector.SBFontUpClick(Sender: TObject);
begin
  if not IChangingFonts then
  begin
    TThemesList.ApplyFontSizeDelta(Chart,1);

    if CBScale.Checked then
       ScaledChart.Invalidate;
  end;
end;

procedure TChartThemeSelector.SBFontDownClick(Sender: TObject);
begin
  if not IChangingFonts then
     TThemesList.ApplyFontSizeDelta(Chart,-1);
end;

procedure TChartThemeSelector.LBColorsDblClick(Sender: TObject);
var P : TPoint;
    w,x,tmp: Integer;
    tmpColors : TColorArray;
begin
  {$IFNDEF D7}
  tmpColors:=nil; // skip warning
  {$ENDIF}

  P:=LBColors.ScreenToClient(Mouse.CursorPos);
  tmp:=LBColors.ItemAtPos(P,True);

  if tmp<>-1 then
  begin
    if tmp=0 then
       tmpColors:=ICurrentColors
    else
       tmpColors:=TeeColorSchemes[tmp-1];

    w:=((LBColors.ClientWidth-2) div Length(tmpColors))-2;
    x:=P.X div w;

    if EditColorDialog(Self,tmpColors[x]) then
    begin
      ApplyScheme(tmpColors);
      LBColors.Invalidate;
    end;
  end;
end;

procedure TChartThemeSelector.TBOffsetChange(Sender: TObject);
begin
  LBColorsClick(Self);
end;

initialization
  InstallHook;
  TeeThemeSelectorHook:=ChartThemeSelector;
finalization
  TeeThemeSelectorHook:=nil;
  RemoveHook;
end.


