{**********************************************}
{  TCustomChart (or derived) Editor Dialog     }
{  Copyright (c) 1996-2020 by Steema Software  }
{**********************************************}
unit TeeEdiGene;
{$I TeeDefs.inc}

interface

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

     {$IFDEF D6}
     Types,
     {$ENDIF}

     {$IFDEF D17}
     System.UITypes,
     {$ENDIF}
     
     Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls, Buttons,

     TeCanvas, TeeProcs, TeEngine, TeeNavigator, TeeEdiFont, TeeMouseCursor, TeePenDlg,
     Chart, TeePrevi, TeeLisB, TeeDraw3D;

type
  TFormTeeGeneral = class(TForm)
    PageControl1: TPageControl;
    TabZoom: TTabSheet;
    TabScroll: TTabSheet;
    RGPanning: TRadioGroup;
    Label4: TLabel;
    CBScrollMouse: TComboFlat;
    TabCursor: TTabSheet;
    TabFont: TTabSheet;
    LBFonts: TListBox;
    Panel1: TPanel;
    PanelFont: TPanel;
    Splitter1: TSplitter;
    Panel2: TPanel;
    CBAllFonts: TCheckBox;
    CBInsideBounds: TCheckBox;
    LTextSize: TLabel;
    ETextSize: TEdit;
    UDTextSize: TUpDown;
    CBZoomText: TComboFlat;
    Label5: TLabel;
    TabPalette: TTabSheet;
    TabMouse: TTabSheet;
    GroupBox1: TGroupBox;
    Label6: TLabel;
    CBLeftButton: TComboFlat;
    Label7: TLabel;
    CBMidButton: TComboFlat;
    Label8: TLabel;
    CBRightButton: TComboFlat;
    GroupBox2: TGroupBox;
    GroupColors: TGroupBox;
    Label10: TLabel;
    SBLum: TScrollBar;
    Label11: TLabel;
    SBHue: TScrollBar;
    Label12: TLabel;
    SBSat: TScrollBar;
    OpenDialog1: TOpenDialog;
    SaveDialog1: TSaveDialog;
    PanelColors: TPanel;
    LPalette: TLabel;
    SBAddColor: TSpeedButton;
    SBDeleteColor: TSpeedButton;
    SBEditColor: TSpeedButton;
    LColor: TLabel;
    LBPalette: TListBox;
    LBColors: TListBox;
    CBCustom: TCheckBox;
    SBLoad: TSpeedButton;
    SBSave: TSpeedButton;
    PageControl2: TPageControl;
    TabSheet1: TTabSheet;
    TabZoomBorder: TTabSheet;
    LSteps: TLabel;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    CBAllowZoom: TCheckBox;
    CBAnimatedZoom: TCheckBox;
    SEAniZoomSteps: TEdit;
    UDAniZoomSteps: TUpDown;
    EMinPix: TEdit;
    UDMinPix: TUpDown;
    CBDir: TComboFlat;
    CBZoomMouse: TComboFlat;
    CBUpLeft: TCheckBox;
    CBHistory: TCheckBox;
    CBZoomAspect: TCheckBox;
    RGWheelScroll: TRadioButton;
    RGWheelData: TRadioButton;
    RGWheelChart: TRadioButton;
    CBInvWheel: TCheckBox;
    RBWheelNone: TRadioButton;
    TabZoomPattern: TTabSheet;
    CBFullRepaint: TCheckBox;
    BMoveUP: TSpeedButton;
    BMoveDown: TSpeedButton;
    TabHover: TTabSheet;
    CBHover: TCheckBox;
    procedure CBAllowZoomClick(Sender: TObject);
    procedure CBAnimatedZoomClick(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure RGPanningClick(Sender: TObject);
    procedure SEAniZoomStepsChange(Sender: TObject);
    procedure EMinPixChange(Sender: TObject);
    procedure CBDirChange(Sender: TObject);
    procedure CBZoomMouseChange(Sender: TObject);
    procedure CBScrollMouseChange(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure CBUpLeftClick(Sender: TObject);
    procedure LBFontsClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormDeactivate(Sender: TObject);
    procedure LBFontsKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure PageControl1Change(Sender: TObject);
    procedure CBHistoryClick(Sender: TObject);
    procedure CBAllFontsClick(Sender: TObject);
    procedure CBZoomAspectClick(Sender: TObject);
    procedure CBInsideBoundsClick(Sender: TObject);
    procedure CBZoomTextChange(Sender: TObject);
    procedure ETextSizeChange(Sender: TObject);
    procedure CBPaletteChange(Sender: TObject);
    procedure CBLeftButtonChange(Sender: TObject);
    procedure CBRightButtonChange(Sender: TObject);
    procedure CBMidButtonChange(Sender: TObject);
    procedure LBColorsDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure SBDeleteColorClick(Sender: TObject);
    procedure SBAddColorClick(Sender: TObject);
    procedure LBColorsClick(Sender: TObject);
    procedure LBColorsDblClick(Sender: TObject);
    procedure CBCustomClick(Sender: TObject);
    procedure SBEditColorClick(Sender: TObject);
    procedure LBColorsDragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    procedure LBColorsDragDrop(Sender, Source: TObject; X, Y: Integer);
    procedure SBLumChange(Sender: TObject);
    procedure SBSaveClick(Sender: TObject);
    procedure SBLoadClick(Sender: TObject);
    procedure PanelColorsResize(Sender: TObject);
    procedure PageControl2Change(Sender: TObject);
    procedure CBInvWheelClick(Sender: TObject);
    procedure RGWheelScrollClick(Sender: TObject);
    procedure CBFullRepaintClick(Sender: TObject);
    procedure BMoveUPClick(Sender: TObject);
    procedure BMoveDownClick(Sender: TObject);
    procedure CBHoverClick(Sender: TObject);
  private
    { Private declarations }
    Changing    : Boolean;
    IBackup     : TTeeFont;
    ICursorEdit : TMouseCursorEdit;
    IFont       : TTeeFont;
    IFontEditor : TTeeFontEditor;
    OldChange   : TNotifyEvent;
    ISaved      : TColorArray;

    procedure AlterPalette;
    procedure ChangedCustomPalette;
    procedure ChangedFont(Sender: TObject);
    procedure CheckCustomPalette;
    procedure CheckMouseButton(const Combo1,Combo2:TComboBox;
                               const Button1,Button2:TMouseButton);
    function CurrentColor(out AColor:TColor):Boolean;
    procedure CursorChange(Sender: TObject);
    procedure DoSelectAllFonts;
    procedure EnablePaletteButtons;
    Procedure EnableZoomControls;

    {$IFDEF D6}
    procedure FillFonts;
    procedure SelectTitleFont;
    {$ENDIF}

    procedure FillPalette;
    function FindPalette:TColorArray;
    procedure FlagCustomPalette;

    procedure RefreshLabelColor;
    procedure ResetIFont;
    procedure SavePalette;
    function SelectedFont(Index:Integer):TTeeFont;
    procedure SwapColor(const AFrom,Delta:Integer);
  protected
    function CheckCursorEdit:TMouseCursorEdit;
  public
    { Public declarations }
    TheChart : TCustomChart;

    {$IFDEF D6}
    class procedure GetChartObjects(const AChart:TCustomChart;
                        const AList:TStrings; WithFonts:Boolean=False);
    {$ENDIF}

    Constructor CreateChart(const Owner:TComponent; const AChart:TCustomChart);
  end;

  {$IFDEF D16}
  [ComponentPlatformsAttribute(pidWin32 or pidWin64)]
  {$ENDIF}
  TChartPageNavigator=class(TCustomTeeNavigator)
  private
    function GetChart: TCustomChart;
    procedure SetChart(const Value: TCustomChart);
  protected
    procedure BtnClick(Index: TTeeNavigateBtn); override;
    procedure DoTeeEvent(Event: TTeeEvent); override;
    procedure SetPanel(const Value: TCustomTeePanel); override;
  public
    procedure EnableButtons; override;
    Function PageCount:Integer; override;
    procedure Print; override;
  published
    property Chart:TCustomChart read GetChart write SetChart;
    property OnButtonClicked;
  end;

Procedure ChartPreview(const AOwner:TComponent; const TeePanel:TCustomTeePanel);

var
  TeeEditToolProc:procedure(AOwner:TComponent; const ATool:TTeeCustomTool)=nil;

implementation

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

uses
  {$IFDEF D6}
  TypInfo,
  {$ENDIF}
  TeeConst, TeeStore, TeeBrushDlg, TeeFilters, Math;

Procedure ChartPreview(const AOwner:TComponent; const TeePanel:TCustomTeePanel);
Begin
  with TChartPreview.Create(AOwner) do
  try
    PageNavigatorClass:=TChartPageNavigator;
    TeePreviewPanel1.Panel:=TeePanel;
    ShowModal;
  finally
    Free;
    TeePanel.Repaint;
  end;
end;

{ TChartPageNavigator }
procedure TChartPageNavigator.BtnClick(Index: TTeeNavigateBtn);
var tmp : TChartPage;
begin
  tmp:=Chart.Pages;

  if Assigned(tmp) then
  with tmp do
  case Index of
    nbPrior : PreviousPage;
    nbNext  : NextPage;
    nbFirst : Current:=1;
    nbLast  : Current:=Count;
  end;

  EnableButtons;

  inherited;
end;

procedure TChartPageNavigator.SetPanel(const Value: TCustomTeePanel);
begin
  if Value is TCustomAxisPanel then inherited
                               else inherited SetPanel(nil);
end;

procedure TChartPageNavigator.EnableButtons;
var tmp : TChartPage;
begin
  inherited;

  if Assigned(Chart) then
  begin
    tmp:=Chart.Pages;

    if Assigned(tmp) then
    begin
      Buttons[nbFirst].Enabled:=tmp.Current>1;
      Buttons[nbPrior].Enabled:=Buttons[nbFirst].Enabled;
      Buttons[nbNext].Enabled:=tmp.Current<tmp.Count;
      Buttons[nbLast].Enabled:=Buttons[nbNext].Enabled;
    end;
  end;
end;

procedure TChartPageNavigator.DoTeeEvent(Event: TTeeEvent);
begin
  if (Event is TChartChangePage) or
     ( (Event is TTeeSeriesEvent) and
       (TTeeSeriesEvent(Event).Event=seDataChanged)
      ) then
        EnableButtons;
end;

function TChartPageNavigator.GetChart: TCustomChart;
begin
  result:=TCustomChart(Panel);
end;

procedure TChartPageNavigator.SetChart(const Value: TCustomChart);
begin
  Panel:=Value;
end;

Function TChartPageNavigator.PageCount:Integer;
begin
  result:=Chart.NumPages;
end;

procedure TChartPageNavigator.Print;
begin
  {$IFNDEF LCL}  // Pending Lazarus TPrintDialog
  if PageCount>1 then
  With TPrintDialog.Create(Self) do
  try
    Options:=[poPageNums];
    PrintRange:=prPageNums;

    FromPage:=1;
    MinPage:=FromPage;
    ToPage:=Chart.NumPages;
    MaxPage:=ToPage;
    if Execute then Chart.PrintPages(FromPage,ToPage);
  finally
    Free;
  end
  else Chart.PrintPages(1,1);
  {$ENDIF}
end;

{ Chart General Editor }
Constructor TFormTeeGeneral.CreateChart(const Owner:TComponent; const AChart:TCustomChart);
begin
  inherited Create(Owner);
  TheChart:=AChart;
end;

procedure TFormTeeGeneral.EnablePaletteButtons;
begin
  SBDeleteColor.Enabled:=LBColors.ItemIndex<>-1;
  SBEditColor.Enabled:=SBDeleteColor.Enabled;

  BMoveUP.Enabled:=CBCustom.Checked and (LBColors.ItemIndex>0);
  BMoveDown.Enabled:=CBCustom.Checked and (LBColors.ItemIndex<LBColors.Items.Count-1)
      and (LBColors.ItemIndex<>-1);
end;

Procedure TFormTeeGeneral.EnableZoomControls;
begin
  EnableControls(TheChart.Zoom.Allow,[ CBAnimatedZoom, UDAniZoomSteps,
                                       SEAniZoomSteps,EMinPix,UDMinPix,
                                       CBDir,CBZoomMouse,CBUpLeft]);
end;

procedure TFormTeeGeneral.CBAllowZoomClick(Sender: TObject);
begin
  TheChart.Zoom.Allow:=CBAllowZoom.Checked;
  EnableZoomControls;
end;

procedure TFormTeeGeneral.CBAnimatedZoomClick(Sender: TObject);
begin
  TheChart.Zoom.Animated:=CBAnimatedZoom.Checked;
end;

procedure TFormTeeGeneral.FormShow(Sender: TObject);

  procedure CheckButtons(AMouseButton:TMouseButton; AIndex:Integer);
  begin
    if AMouseButton=mbLeft then
       CBLeftButton.ItemIndex:=AIndex
    else
    if AMouseButton=mbMiddle then
       CBMidButton.ItemIndex:=AIndex
    else
    if AMouseButton=mbRight then
       CBRightButton.ItemIndex:=AIndex;
  end;

begin
  TeeLoadArrowBitmaps(BMoveUp.Glyph,BMoveDown.Glyph);

  if Assigned(TheChart) then
  With TheChart do
  begin
    RGPanning.ItemIndex    :=Ord(AllowPanning);
    CBInsideBounds.Checked :=Panning.InsideBounds;

    CBHover.Checked:=Hover.Visible;

    if Panning.MouseWheel<>pmwNone then
    begin
      RGWheelScroll.Checked:=True;
      CBInvWheel.Checked:=Panning.MouseWheel=pmwInverted;
    end
    else
    if Zoom.MouseWheel<>pmwNone then
    begin
      RGWheelData.Checked:=True;
      CBInvWheel.Checked:=Zoom.MouseWheel=pmwInverted;
    end
    else
    if ZoomWheel<>pmwNone then
    begin
      RGWheelChart.Checked:=True;
      CBInvWheel.Checked:=ZoomWheel=pmwInverted;
    end
    else
      RBWheelNone.Checked:=True;

    CBInvWheel.Enabled:=not RBWheelNone.Checked;

    CBLeftButton.ItemIndex:=2;
    CBMidButton.ItemIndex:=2;
    CBRightButton.ItemIndex:=2;

    With Zoom do
    begin
      CBAllowZoom.Checked    :=Allow;
      CBAnimatedZoom.Checked :=Animated;
      UDAniZoomSteps.Position:=AnimatedSteps;
      EnableZoomControls;
      UDMinPix.Position      :=MinimumPixels;
      CBDir.ItemIndex        :=Ord(Direction);
      CBZoomMouse.ItemIndex  :=Ord(MouseButton);
      CBUpLeft.Checked       :=UpLeftZooms;
      CBHistory.Checked      :=History;
      CBZoomAspect.Checked   :=KeepAspectRatio;

      if Allow then
         CheckButtons(MouseButton,0);

      CBFullRepaint.Checked  :=FullRepaint;
    end;

    CBScrollMouse.ItemIndex  :=Ord(ScrollMouseButton);
    CBScrollMouse.Enabled    :=AllowPanning<>pmNone;

    if CBScrollMouse.Enabled then
       CheckButtons(ScrollMouseButton,1);

    CBZoomText.ItemIndex:=Ord(View3DOptions.ZoomText);
    CBZoomTextChange(Self);
    UDTextSize.Position:=View3DOptions.FontZoom;

    LBPalette.Clear;
    TColorPalettes.AddTo(LBPalette.Items,True);

    if ColorPaletteIndex=0 then
       LBPalette.ItemIndex:=0
    else
       LBPalette.ItemIndex:=ColorPaletteIndex+1;

    FillPalette;

    CheckCustomPalette;

    if CBCustom.Checked then
       SavePalette;
  end;

  Changing:=False;
end;

procedure TFormTeeGeneral.CheckCustomPalette;
begin
  CBCustom.Checked:=TheChart.ColorPaletteIndex=-2;
  LBPalette.Enabled:=not CBCustom.Checked;
  EnablePaletteButtons;

  GroupColors.Enabled:=CBCustom.Checked;

  SBLum.Enabled:=CBCustom.Checked;
  SBHue.Enabled:=SBLum.Enabled;
  SBSat.Enabled:=SBLum.Enabled;

  SBLum.Position:=0;
  SBHue.Position:=0;
  SBSat.Position:=0;

  if CBCustom.Checked then
     SavePalette;
end;

{$IFDEF D6}
function FontOfPersistent(Instance:TPersistent; FilterOut:TPersistent=nil):TTeeFont;
var t : Integer;
    n : Integer;
    tmpProps : PPropList;
    tmpProp  : TObject;
begin
  result:=nil;

  n:=GetPropList(Instance,tmpProps);

  if n>0 then
  try
    for t:=0 to n-1 do
    with tmpProps[t]^ do
    if (PropType^.Kind=tkClass) and Assigned(GetProc) then
    begin
      tmpProp:=GetObjectProp(Instance,tmpProps[t]);

      if tmpProp is TTeeFont then
      begin
        if tmpProp<>FilterOut then
        begin
          result:=TTeeFont(tmpProp);
          break;
        end;
      end
      else
      if tmpProp is TPersistent then
         if not (tmpProp is TComponent) then
         begin
           result:=FontOfPersistent(TPersistent(tmpProp),FilterOut);

           if Assigned(result) then
              break;
         end;
    end;

  finally
    FreeMemory(tmpProps);
  end;
end;

class procedure TFormTeeGeneral.GetChartObjects(const AChart:TCustomChart;
                     const AList:TStrings; WithFonts:Boolean=False);

  procedure AddAxis(const Description:String; const Axis:TChartAxis);
  begin
    with AList do
    begin
      AddObject(Description,Axis);
      AddObject(Description+' ('+TeeMsg_AxisTitle+')',Axis.Title);
    end;
  end;

var t : Integer;
    tmpTitle : String;
begin
  with AList do
  begin
    AddObject(TeeMsg_Legend,AChart.Legend);
    AddObject(TeeMsg_LegendTitle,AChart.Legend.Title);
    AddObject(TeeMsg_Title,AChart.Title);
    AddObject(TeeMsg_Foot,AChart.Foot);
    AddObject(TeeMsg_SubTitle,AChart.SubTitle);
    AddObject(TeeMsg_SubFoot,AChart.SubFoot);

    for t:=0 to AChart.SeriesCount-1 do
    begin
      tmpTitle:=SeriesTitleOrName(AChart[t],True);

      if (not WithFonts) or
         Assigned(FontOfPersistent(AChart[t],AChart[t].Marks.Font)) then
            AddObject(tmpTitle,AChart[t]);

      AddObject(tmpTitle+' ('+TeeMsg_Marks+')',AChart[t].Marks);
    end;

    for t:=0 to AChart.Tools.Count-1 do
      if (not WithFonts) or Assigned(FontOfPersistent(AChart.Tools[t])) then
      begin
        tmpTitle:=AChart.Tools[t].Name;

        if tmpTitle='' then
           tmpTitle:=AChart.Tools[t].Description;

        AddObject(tmpTitle,AChart.Tools[t]);
      end;
  end;

  // Do not translate string constants

  AddAxis(TeeMsg_LeftAxis,AChart.Axes.Left);
  AddAxis(TeeMsg_RightAxis,AChart.Axes.Right);
  AddAxis(TeeMsg_TopAxis,AChart.Axes.Top);
  AddAxis(TeeMsg_BottomAxis,AChart.Axes.Bottom);
  AddAxis(TeeMsg_DepthTopAxis,AChart.Axes.DepthTop);
  AddAxis(TeeMsg_DepthAxis,AChart.Axes.Depth);

  for t:=0 to AChart.CustomAxes.Count-1 do
      AddAxis(TeeTranslateString('Custom axis')+' '+IntToStr(t),AChart.CustomAxes[t]);
end;

procedure TFormTeeGeneral.FillFonts;
begin
  LBFonts.Items.Clear;

  GetChartObjects(TheChart,LBFonts.Items,True);

  SelectTitleFont;
end;
{$ENDIF}

procedure TFormTeeGeneral.RGPanningClick(Sender: TObject);
begin
  TheChart.AllowPanning:=TPanningMode(RGPanning.ItemIndex);
  CBScrollMouse.Enabled:=TheChart.AllowPanning<>pmNone;
end;

procedure TFormTeeGeneral.SEAniZoomStepsChange(Sender: TObject);
begin
  if Showing then
     TheChart.Zoom.AnimatedSteps:=UDAniZoomSteps.Position;
end;

procedure TFormTeeGeneral.EMinPixChange(Sender: TObject);
begin
  if Showing then
     TheChart.Zoom.MinimumPixels:=UDMinPix.Position
end;

procedure TFormTeeGeneral.CBDirChange(Sender: TObject);
begin
  TheChart.Zoom.Direction:=TTeeZoomDirection(CBDir.ItemIndex);
end;

procedure TFormTeeGeneral.CBZoomMouseChange(Sender: TObject);
begin
  TheChart.Zoom.MouseButton:=TMouseButton(CBZoomMouse.ItemIndex)
end;

procedure TFormTeeGeneral.CBScrollMouseChange(Sender: TObject);
begin
  TheChart.ScrollMouseButton:=TMouseButton(CBScrollMouse.ItemIndex)
end;

procedure TFormTeeGeneral.FormCreate(Sender: TObject);
begin
  {$IFDEF D7}
  PageControl1.DoubleBuffered:=True;
  PageControl2.DoubleBuffered:=True;
  {$ENDIF}

  Changing:=True;
  Align:=alClient;
  PageControl1.ActivePage:=TabMouse;

  {$IFNDEF D6}
  TabFont.TabVisible:=False;
  {$ENDIF}

end;

procedure TFormTeeGeneral.CBUpLeftClick(Sender: TObject);
begin
  TheChart.Zoom.UpLeftZooms:=CBUpLeft.Checked;
end;

function TFormTeeGeneral.SelectedFont(Index:Integer):TTeeFont;
var tmp : TObject;
begin
  tmp:=LBFonts.Items.Objects[Index];

  if tmp is TTeeCustomShape then
     result:=TTeeCustomShape(tmp).Font
  else
  if tmp is TChartAxis then
     result:=TChartAxis(tmp).LabelsFont
  {$IFDEF D6}
  else
  if tmp is TChartSeries then
     result:=FontOfPersistent(tmp as TPersistent,TChartSeries(tmp).Marks.Font)
  else
     result:=FontOfPersistent(tmp as TPersistent);
  {$ELSE}
  else
     result:=nil;
  {$ENDIF}
end;

procedure TFormTeeGeneral.ResetIFont;
begin
  if Assigned(IFont) then
  begin
    IFont.OnChange:=OldChange;
    IFont:=nil;
  end;

  FreeAndNil(IBackup);
end;

procedure TFormTeeGeneral.LBFontsClick(Sender: TObject);
begin
  ResetIFont;

  if LBFonts.ItemIndex<>-1 then
  begin
    IFont:=SelectedFont(LBFonts.ItemIndex);
    IBackup:=TTeeFont.Create(nil);
    IBackup.Assign(IFont);

    if not Assigned(IFontEditor) then
    begin
      IFontEditor:=TTeeFontEditor.Create(nil);
      IFontEditor.Align:=alClient;
      AddFormTo(IFontEditor,PanelFont);
    end;

    IFontEditor.RefreshControls(IFont);

    OldChange:=IFont.OnChange;
    IFont.OnChange:=ChangedFont;
  end;
end;

procedure TFormTeeGeneral.ChangedFont(Sender: TObject);
var t   : Integer;
    tmp : TTeeFont;
begin
  if Assigned(IFont) then
    if Showing then
    begin
      for t:=0 to LBFonts.Items.Count-1 do
      if LBFonts.Selected[t] then
      begin
        tmp:=SelectedFont(t);

        if tmp<>IFont then
        begin
          if IFont.Name<>IBackup.Name then
             tmp.Name:=IFont.Name;

          if IFont.Size<>IBackup.Size then
             tmp.Size:=IFont.Size;

          if IFont.Style<>IBackup.Style then
             tmp.Style:=IFont.Style;

          if IFont.Color<>IBackup.Color then
             tmp.Color:=IFont.Color;

          if IFont.InterCharSize<>IBackup.InterCharSize then
             tmp.InterCharSize:=IFont.InterCharSize;

          if IFont.Shadow.HorizSize<>IBackup.Shadow.HorizSize then
             tmp.Shadow.HorizSize:=IFont.Shadow.HorizSize;

          if IFont.Shadow.VertSize<>IBackup.Shadow.VertSize then
             tmp.Shadow.VertSize:=IFont.Shadow.VertSize;

          if IFont.Shadow.Color<>IBackup.Shadow.Color then
             tmp.Shadow.Color:=IFont.Shadow.Color;

          if IFont.Shadow.Visible<>IBackup.Shadow.Visible then
             tmp.Shadow.Visible:=IFont.Shadow.Visible;

          if IFont.Shadow.Transparency<>IBackup.Shadow.Transparency then
             tmp.Shadow.Transparency:=IFont.Shadow.Transparency;

          if IFont.Shadow.Smooth<>IBackup.Shadow.Smooth then
             tmp.Shadow.Smooth:=IFont.Shadow.Smooth;

          if IFont.Gradient.Visible<>IBackup.Gradient.Visible then
             tmp.Gradient.Visible:=IFont.Gradient.Visible;

          //tmp.Assign(IFont); // everything?
        end;
      end;

      IBackup.Assign(IFont);

      if Assigned(OldChange) then
         OldChange(IFont);
    end
    else
       ResetIFont;
end;

procedure TFormTeeGeneral.FormDestroy(Sender: TObject);
begin
  ResetIFont;
end;

procedure TFormTeeGeneral.FormDeactivate(Sender: TObject);
begin
  ResetIFont;
end;

{$IFNDEF D6}
{$DEFINE SELECTALLFONTS}
{$ENDIF}

procedure TFormTeeGeneral.LBFontsKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if ssCtrl in Shift then
     if Key=Ord('A') then
        DoSelectAllFonts;
end;

function TFormTeeGeneral.CheckCursorEdit:TMouseCursorEdit;
begin
  if not Assigned(ICursorEdit) then
  begin
    ICursorEdit:=TMouseCursorEdit.Create(Self);
    ICursorEdit.TheCursor:=TheChart.Cursor;
    ICursorEdit.TheComponent:=TheChart;
    ICursorEdit.OnChange:=CursorChange;

    AddFormTo(ICursorEdit,TabCursor);
  end;

  result:=ICursorEdit;
end;

procedure TFormTeeGeneral.PageControl1Change(Sender: TObject);
begin
  if PageControl1.ActivePage=TabFont then
  begin
    {$IFDEF D6}
    if LBFonts.Items.Count=0 then
    begin
      FillFonts;
      TeeTranslateControl(LBFonts);
    end;
    {$ENDIF}

    if LBFonts.CanFocus then
       LBFonts.SetFocus;
  end
  else
  if PageControl1.ActivePage=TabCursor then
     CheckCursorEdit;
end;

procedure TFormTeeGeneral.CursorChange(Sender: TObject);
begin
  TheChart.Cursor:=TMouseCursorEdit(Sender).TheCursor;
  TheChart.OriginalCursor:=TheChart.Cursor;
end;

procedure TFormTeeGeneral.CBHistoryClick(Sender: TObject);
begin
  TheChart.Zoom.History:=CBHistory.Checked;
end;

{$IFDEF D6}
procedure TFormTeeGeneral.SelectTitleFont;
begin
  LBFonts.ClearSelection;

  LBFonts.ItemIndex:=LBFonts.Items.IndexOfObject(TheChart.Title);
  LBFonts.Selected[LBFonts.ItemIndex]:=True;

  LBFontsClick(LBFonts);
end;
{$ENDIF}

procedure TFormTeeGeneral.CBAllFontsClick(Sender: TObject);
begin
  {$IFDEF D6}
  if CBAllFonts.Checked then
     DoSelectAllFonts
  else
     SelectTitleFont;
  {$ENDIF}
end;

procedure TFormTeeGeneral.DoSelectAllFonts;
{$IFDEF SELECTALLFONTS}
var t : Integer;
{$ENDIF}
begin
  {$IFDEF SELECTALLFONTS}
  with LBFonts do
  for t:=0 to Items.Count-1 do
      Selected[t]:=True;

  {$ELSE}
  LBFonts.SelectAll;
  {$ENDIF}
end;

procedure TFormTeeGeneral.CBZoomAspectClick(Sender: TObject);
begin
  TheChart.Zoom.KeepAspectRatio:=CBZoomAspect.Checked;
end;

procedure TFormTeeGeneral.CBInsideBoundsClick(Sender: TObject);
begin
  TheChart.Panning.InsideBounds:=CBInsideBounds.Checked;
end;

procedure TFormTeeGeneral.CBZoomTextChange(Sender: TObject);
begin
  TheChart.View3DOptions.ZoomText:=TCanvasZoomText(CBZoomText.ItemIndex);
  ETextSize.Enabled:=TheChart.View3DOptions.ZoomText=ztManual;
  UDTextSize.Enabled:=ETextSize.Enabled;
end;

procedure TFormTeeGeneral.ETextSizeChange(Sender: TObject);
begin
  if Showing and (not Changing) then
     TheChart.View3DOptions.FontZoom:=UDTextSize.Position;
end;

procedure TFormTeeGeneral.CBPaletteChange(Sender: TObject);
begin
  TheChart.ColorPaletteIndex:=LBPalette.ItemIndex-1;
  FillPalette;
  EnablePaletteButtons;
end;

function TFormTeeGeneral.FindPalette:TColorArray;
begin
  result:=TheChart.ColorPalette;

  if not Assigned(result) then
     result:=TeeColorPalette;
end;

procedure TFormTeeGeneral.FillPalette;
var t,
    tmpL : Integer;
    tmpP : TColorArray;
begin
  tmpP:=FindPalette;
  tmpL:=Length(tmpP);

  LBColors.Items.BeginUpdate;
  try
    LBColors.Items.Clear;

    for t:=0 to tmpL-1 do
        LBColors.Items.Add('');
  finally
    LBColors.Items.EndUpdate;
  end;
end;

procedure TFormTeeGeneral.CheckMouseButton(const Combo1,Combo2:TComboBox;
                                           const Button1,Button2:TMouseButton);
begin
  if Combo1.ItemIndex=0 then
  begin
    TheChart.Zoom.Allow:=True;
    TheChart.Zoom.MouseButton:=Button1;

    if TheChart.ScrollMouseButton=Button1 then
    begin
      TheChart.ScrollMouseButton:=Button2;
      if TheChart.AllowPanning<>pmNone then
         Combo2.ItemIndex:=1;
    end;
  end
  else
  if Combo1.ItemIndex=1 then
  begin
    if TheChart.AllowPanning=pmNone then
       TheChart.AllowPanning:=pmBoth;

    TheChart.ScrollMouseButton:=Button1;

    if TheChart.Zoom.MouseButton=Button1 then
    begin
      TheChart.Zoom.MouseButton:=Button2;
      if TheChart.Zoom.Allow then
         Combo2.ItemIndex:=0;
    end;
  end
  else
  begin
    if TheChart.Zoom.Allow and (TheChart.Zoom.MouseButton=Button1) then
       TheChart.Zoom.Allow:=False;

    if TheChart.ScrollMouseButton=Button1 then
       if TheChart.AllowPanning<>pmNone then
          TheChart.AllowPanning:=pmNone;
  end;
end;

procedure TFormTeeGeneral.CBLeftButtonChange(Sender: TObject);
begin
  CheckMouseButton(CBLeftButton,CBRightButton,mbLeft,mbRight);
end;

procedure TFormTeeGeneral.CBRightButtonChange(Sender: TObject);
begin
  CheckMouseButton(CBRightButton,CBLeftButton,mbRight,mbLeft);
end;

procedure TFormTeeGeneral.CBMidButtonChange(Sender: TObject);
begin
  CheckMouseButton(CBMidButton,CBRightButton,mbMiddle,mbRight);
end;

procedure TFormTeeGeneral.LBColorsDrawItem(Control: TWinControl;
  Index: Integer; Rect: TRect; State: TOwnerDrawState);
var tmpP : TColorArray;
begin
  tmpP:=FindPalette;

  if Length(tmpP)>Index then
  begin
    LBColors.Canvas.Brush.Color:=tmpP[Index];
    LBColors.Canvas.FillRect(Rect);

//    if odSelected in State then
  end;
end;

type
  TCustomChartAccess=class(TCustomChart);

procedure TFormTeeGeneral.ChangedCustomPalette;
begin
  SavePalette;
  TCustomChartAccess(TheChart).ColorPaletteChanged;
  TheChart.Invalidate;
end;

procedure TFormTeeGeneral.SBDeleteColorClick(Sender: TObject);
var L, t,
    Old : Integer;
begin
  FlagCustomPalette;

  Old:=LBColors.ItemIndex;

  // Remove color from ColorPalette:
  L:=Length(TheChart.ColorPalette);

  if Old<L then
  begin
    for t:=Old to L-2 do
        TheChart.ColorPalette[t]:=TheChart.ColorPalette[t+1];

    SetLength(TheChart.ColorPalette,L-1);
  end;

  // Remove listbox item:
  LBColors.Items.Delete(Old);

  // Set new listbox itemindex:
  if LBColors.ItemIndex=-1 then
     if Old<LBColors.Items.Count then
        LBColors.ItemIndex:=Old
     else
        LBColors.ItemIndex:=LBColors.Items.Count-1;

  // Tell chart to repaint:
  ChangedCustomPalette;

  // Re-enable buttons:
  EnablePaletteButtons;
end;

procedure TFormTeeGeneral.SBAddColorClick(Sender: TObject);
var tmp : TColor;
    L   : Integer;
begin
  tmp:=clWhite;

  if EditColorDialog(Self,tmp,[]) then
  begin
    L:=Length(TheChart.ColorPalette);
    SetLength(TheChart.ColorPalette,L+1);
    TheChart.ColorPalette[L]:=tmp;

    LBColors.Items.Add('');
    LBColors.ItemIndex:=LBColors.Items.Count-1;

    ChangedCustomPalette;

    FlagCustomPalette;
    EnablePaletteButtons;
  end;
end;

procedure TFormTeeGeneral.RefreshLabelColor;
var tmp : TColor;
begin
  if CurrentColor(tmp) then
     LColor.Caption:=IntToHex({ColorToRGB}(tmp),6);
end;

procedure TFormTeeGeneral.LBColorsClick(Sender: TObject);
begin
  EnablePaletteButtons;
  RefreshLabelColor;
end;

function TFormTeeGeneral.CurrentColor(out AColor:TColor):Boolean;
var tmpIndex : Integer;
    tmpP : TColorArray;
begin
  tmpP:=FindPalette;
  tmpIndex:=LBColors.ItemIndex;

  result:=tmpIndex<Length(tmpP);

  if result then
     AColor:=tmpP[tmpIndex]
  else
     AColor:=clNone;
end;

procedure TFormTeeGeneral.LBColorsDblClick(Sender: TObject);
var Old : Integer;
    tmp : TColor;
begin
  Old:=LBColors.ItemIndex;

  if CurrentColor(tmp) then
    if EditColorDialog(Self,tmp,[]) then
    begin
      FlagCustomPalette;

      TheChart.ColorPalette[Old]:=tmp;

      LColor.Caption:=IntToHex({ColorToRGB}(tmp),6);

      LBColors.Repaint;
      ChangedCustomPalette;
    end;
end;

procedure TFormTeeGeneral.SavePalette;
var tmpP : TColorArray;
    L,t  : Integer;
begin
  tmpP:=FindPalette;
  L:=Length(tmpP);
  SetLength(ISaved,L);

  for t:=0 to L-1 do
      ISaved[t]:=tmpP[t];
end;

procedure TFormTeeGeneral.FlagCustomPalette;
begin
  if TheChart.ColorPaletteIndex<>-2 then
  begin
    TheChart.ColorPaletteIndex:=-2;
    CBCustom.Checked:=True;

    CheckCustomPalette;
  end;
end;

procedure TFormTeeGeneral.CBCustomClick(Sender: TObject);
var tmp : Integer;
begin
  if CBCustom.Checked then
  begin
    FlagCustomPalette;
    FillPalette;
  end
  else
  begin
    tmp:=LBPalette.ItemIndex;
    if tmp=-1 then
       tmp:=0;

    TheChart.ColorPaletteIndex:=tmp-1;

    if LBPalette.ItemIndex=-1 then
       LBPalette.ItemIndex:=0;

    LBColors.Repaint;
    TheChart.Invalidate;

    CheckCustomPalette;
  end;
end;

procedure TFormTeeGeneral.SBEditColorClick(Sender: TObject);
begin
  LBColorsDblClick(Self);
end;

procedure TFormTeeGeneral.LBColorsDragOver(Sender, Source: TObject; X,
  Y: Integer; State: TDragState; var Accept: Boolean);
begin
  Accept:=(LBColors.ItemIndex<>-1) and (Sender=Source);
end;

procedure TFormTeeGeneral.LBColorsDragDrop(Sender, Source: TObject; X,
  Y: Integer);
var tmp : Integer;
    Old : TColor;
    tmpIndex : Integer;
begin
  tmpIndex:=LBColors.ItemIndex;
  tmp:=LBColors.ItemAtPos(Point(X,Y),True);

  if (tmpIndex<>-1) and (tmp<>tmpIndex) then
  begin
    FlagCustomPalette;

    // Swap color
    Old:=TheChart.ColorPalette[tmpIndex];
    TheChart.ColorPalette[tmpIndex]:=TheChart.ColorPalette[tmp];
    TheChart.ColorPalette[tmp]:=Old;

    LBColors.ItemIndex:=tmp;

    LBColors.Repaint;
    ChangedCustomPalette;
  end;
end;

{$IFNDEF D7}
function EnsureRange(const AValue, AMin, AMax: Integer): Integer;
begin
  if AValue<AMin then
     result:=AMin
  else
  if AValue>AMax then
     result:=AMax
  else
     result:=AValue;
end;
{$ENDIF}

procedure TFormTeeGeneral.AlterPalette;

  function AlterColor(const AColor:TColor):TColor;
  var H,L,S : Word;
  begin
    ColorToHLS(AColor,H,L,S);

    H:=EnsureRange(H+SBHue.Position,0,240);
    L:=EnsureRange(L+SBLum.Position,0,240);
    S:=EnsureRange(S+SBSat.Position,0,240);

    result:=HLSToColor(H,L,S);
  end;

var Current,
    tmpP : TColorArray;
    t    : Integer;
begin
  tmpP:=ISaved;
  Current:=FindPalette;

  for t:=0 to Length(tmpP)-1 do
      Current[t]:=AlterColor(tmpP[t]);
end;

procedure TFormTeeGeneral.SBLumChange(Sender: TObject);
begin
  AlterPalette;
  LBColors.Repaint;

  RefreshLabelColor;
  TCustomChartAccess(TheChart).ColorPaletteChanged;
  TheChart.Invalidate;
end;

procedure TFormTeeGeneral.SBSaveClick(Sender: TObject);
var t,
    tmpL : Integer;
    tmp  : TStringList;
    tmpP : TColorArray;
begin
  {$IFNDEF D7}
  tmpP:=nil;
  {$ENDIF}

  if SaveDialog1.Execute then
  begin
    tmp:=TStringList.Create;
    try
      tmpP:=FindPalette;
      tmpL:=Length(tmpP);

      for t:=0 to tmpL-1 do
          tmp.Add(Format('%s%.8x', [HexDisplayPrefix, tmpP[t]]));

      tmp.SaveToFile(SaveDialog1.FileName);
    finally
      tmp.Free;
    end;
  end;
end;

procedure TFormTeeGeneral.SBLoadClick(Sender: TObject);
var tmp : TStringList;
    l,t : Integer;
begin
  if OpenDialog1.Execute then
  begin
    tmp:=TStringList.Create;
    try
      tmp.LoadFromFile(OpenDialog1.FileName);

      FlagCustomPalette;

      TheChart.ColorPalette:=nil;

      for t:=0 to tmp.Count-1 do
      if (tmp[t]<>'') and (Copy(Trim(tmp[t]),1,2)<>'//') then
      begin
        l:=Length(TheChart.ColorPalette);
        SetLength(TheChart.ColorPalette,l+1);
        TheChart.ColorPalette[l]:=StrToInt(tmp[t]);
      end;

      FillPalette;
    finally
      tmp.Free;
    end;
  end;
end;

procedure TFormTeeGeneral.PanelColorsResize(Sender: TObject);
var tmp : Integer;
begin
  tmp:=PanelColors.Height-30;
  LBPalette.Height:=tmp;
  LBColors.Height:=tmp;
end;

procedure TFormTeeGeneral.PageControl2Change(Sender: TObject);
begin
  if (PageControl2.ActivePage=TabZoomBorder) and (TabZoomBorder.ControlCount=0) then
     TPenDialog.InsertForm(TheChart.Zoom.Pen, TabZoomBorder)
  else
  if (PageControl2.ActivePage=TabZoomPattern) and (TabZoomPattern.ControlCount=0) then
     TBrushDialog.AddDialog(TheChart.Zoom.Brush, TabZoomPattern);
end;

procedure TFormTeeGeneral.CBInvWheelClick(Sender: TObject);
var tmp : TMouseWheelStyle;
begin
  if Changing then
     Exit;

  if CBInvWheel.Checked then
     tmp:=pmwInverted
  else
     tmp:=pmwNormal;

  if RGWheelScroll.Checked then
     TheChart.Panning.MouseWheel:=tmp
  else
  if RGWheelData.Checked then
     TheChart.Zoom.MouseWheel:=tmp
  else
  if RGWheelChart.Checked then
     TheChart.ZoomWheel:=tmp;
end;

procedure TFormTeeGeneral.RGWheelScrollClick(Sender: TObject);
var tmp : TMouseWheelStyle;
begin
  if Changing then
     Exit;

  RBWheelNone.Checked:=Sender=RBWheelNone;
  RGWheelScroll.Checked:=Sender=RGWheelScroll;
  RGWheelData.Checked:=Sender=RGWheelData;
  RGWheelChart.Checked:=Sender=RGWheelChart;

  TheChart.Panning.MouseWheel:=pmwNone;
  TheChart.Zoom.MouseWheel:=pmwNone;
  TheChart.ZoomWheel:=pmwNone;

  if CBInvWheel.Checked then
     tmp:=pmwInverted
  else
     tmp:=pmwNormal;

  if RGWheelScroll.Checked then
     TheChart.Panning.MouseWheel:=tmp
  else
  if RGWheelData.Checked then
     TheChart.Zoom.MouseWheel:=tmp
  else
  if RGWheelChart.Checked then
     TheChart.ZoomWheel:=tmp;
end;

procedure TFormTeeGeneral.CBFullRepaintClick(Sender: TObject);
begin
  TheChart.Zoom.FullRepaint:=CBFullRepaint.Checked;
end;

procedure TFormTeeGeneral.SwapColor(const AFrom,Delta:Integer);
var tmpP : TColorArray;
    tmp  : TColor;
begin
  tmpP:=FindPalette;

  tmp:=tmpP[AFrom];
  tmpP[AFrom]:=tmpP[AFrom+Delta];
  tmpP[AFrom+Delta]:=tmp;

  LBColors.ItemIndex:=LBColors.ItemIndex+Delta;
  EnablePaletteButtons;

  TCustomChartAccess(TheChart).ColorPaletteChanged;
  TheChart.Invalidate;

  LBColors.Invalidate;
end;

procedure TFormTeeGeneral.BMoveUPClick(Sender: TObject);
begin
  SwapColor(LBColors.ItemIndex,-1);
end;

procedure TFormTeeGeneral.BMoveDownClick(Sender: TObject);
begin
  SwapColor(LBColors.ItemIndex,1);
end;

procedure TFormTeeGeneral.CBHoverClick(Sender: TObject);
begin
  TheChart.Hover.Visible:=CBHover.Checked;
end;

end.
