unit FMXTee.Editor.General;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes,
  System.Variants, FMX.Types, FMX.Controls, FMX.Forms,
  FMX.Edit, FMX.ListBox, FMX.Dialogs, FMX.Layouts, FMX.TabControl,
  FMXTee.Chart, FMXTee.RadioGroup, FMXTee.Editor.Font, FMXTee.Canvas,
  FMX.Objects;

type
  TGeneralEditor = class(TForm)
    PageControl1: TTabControl;
    TabZoom: TTabItem;
    LSteps: TLabel;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    CBAllowZoom: TCheckBox;
    CBAnimatedZoom: TCheckBox;
    UDAniZoomSteps: TSpinBox;
    BZoomPen: TButton;
    BZoomColor: TButton;
    UDMinPix: TSpinBox;
    CBDir: TComboBox;
    CBZoomMouse: TComboBox;
    CBUpLeft: TCheckBox;
    CBHistory: TCheckBox;
    CBZoomAspect: TCheckBox;
    TabScroll: TTabItem;
    Label4: TLabel;
    CBScrollMouse: TComboBox;
    CBInsideBounds: TCheckBox;
    TabCursor: TTabItem;
    TabFont: TTabItem;
    Splitter1: TSplitter;
    LBFonts: TListBox;
    Panel1: TPanel;
    PanelFont: TPanel;
    Panel2: TPanel;
    LTextSize: TLabel;
    Label5: TLabel;
    CBAllFonts: TCheckBox;
    UDTextSize: TSpinBox;
    CBZoomText: TComboBox;
    TabPalette: TTabItem;
    Label6: TLabel;
    LBPalette: TListBox;
    RGScroll: TRadioGroup;
    Label7: TLabel;
    LBCursor: TListBox;
    PaintBox1: TPaintBox;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure PageControl1Change(Sender: TObject);
    procedure BZoomColorClick(Sender: TObject);
    procedure CBDirChange(Sender: TObject);
    procedure CBZoomMouseChange(Sender: TObject);
    procedure CBScrollMouseChange(Sender: TObject);
    procedure LBFontsKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState);
    procedure ETextSizeChange(Sender: TObject);
    procedure CBZoomTextChange(Sender: TObject);
    procedure CBAllowZoomChange(Sender: TObject);
    procedure CBAnimatedZoomChange(Sender: TObject);
    procedure UDAniZoomStepsChangeTracking(Sender: TObject);
    procedure UDMinPixChangeTracking(Sender: TObject);
    procedure CBUpLeftChange(Sender: TObject);
    procedure CBHistoryChange(Sender: TObject);
    procedure CBZoomAspectChange(Sender: TObject);
    procedure CBInsideBoundsChange(Sender: TObject);
    procedure BZoomPenClick(Sender: TObject);
    procedure CBAllFontsChange(Sender: TObject);
    procedure LBPaletteChange(Sender: TObject);
    procedure RGScrollChange(Sender: TObject);
    procedure UDTextSizeChangeTracking(Sender: TObject);
    procedure LBFontsChange(Sender: TObject);
    procedure LBCursorChange(Sender: TObject);
    procedure PaintBox1Paint(Sender: TObject; const Canvas: TCanvas);
  private
   { Private declarations }
    Chart : TCustomChart;
    IFont : TTeeFont;
    IBackup : TTeeFont;
    IFontEditor : TFontEditor;
    OldChange   : TNotifyEvent;

    procedure AddCursors;
    procedure ChangedFont(Sender: TObject);
    procedure FillFonts;
    class procedure GetChartObjects(AChart:TCustomChart;
                              AList:TCustomListBox; WithFonts:Boolean=False);
    function IndexOfCursor(ACursor:TCursor):Integer;
    procedure RefreshChart(AChart:TCustomChart);
    procedure ResetIFont;
    function SelectedFont(Index:Integer):TTeeFont;
  public
   { Public declarations }
    class function CreateEditor(AOwner:TComponent; AChart:TCustomChart):TForm;
  end;

implementation

{$R *.fmx}

uses
  FMXTee.Constants, FMXTee.Procs, FMXTee.Editor.Stroke,
  FMXTee.Editor.Brush, FMXTee.Engine;

procedure TGeneralEditor.FormCreate(Sender: TObject);

  procedure AddPalette(const AText:String);
  var tmp : TListBoxItem;
  begin
    tmp:=TListBoxItem.Create(Self);
    tmp.Text:=AText;
    LBPalette.AddObject(tmp);
  end;

var t : Integer;
begin
  PageControl1.ActiveTab:=TabZoom;

  AddPalette(TeeMsg_Default);

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

  AddCursors;
end;

procedure TGeneralEditor.AddCursors;

  procedure AddItem(const AText:String; ACursor:Integer);
  var item : TListBoxItem;
  begin
    item:=TListBoxItem.Create(Self);
    item.Text:=AText;
    item.Tag:=ACursor;
    LBCursor.AddObject(item);
  end;

begin
  LBCursor.Clear;

  AddItem('Default     ',0);
  AddItem('None        ',-1);
  AddItem('Arrow       ',-2);
  AddItem('Cross       ',-3);
  AddItem('IBeam       ',-4);
  AddItem('Size        ',-22);
  AddItem('SizeNESW    ',-6);
  AddItem('SizeNS      ',-7);
  AddItem('SizeNWSE    ',-8);
  AddItem('SizeWE      ',-9);
  AddItem('UpArrow     ',-10);
  AddItem('HourGlass   ',-11);
  AddItem('Drag        ',-12);
  AddItem('NoDrop      ',-13);
  AddItem('HSplit      ',-14);
  AddItem('VSplit      ',-15);
  AddItem('MultiDrag   ',-16);
  AddItem('SQLWait     ',-17);
  AddItem('No          ',-18);
  AddItem('AppStart    ',-19);
  AddItem('Help        ',-20);
  AddItem('HandPoint   ',-21);
  AddItem('SizeAll     ',-22);
end;

procedure TGeneralEditor.FormDestroy(Sender: TObject);
begin
  Panel1.Free;  // workaround for : QC112670
  ResetIFont;
end;

function FontOfPersistent(Instance:TPersistent; FilterOut:TPersistent=nil):TTeeFont;
begin
  result:=nil;
end;

class procedure TGeneralEditor.GetChartObjects(AChart:TCustomChart;
                     AList:TCustomListBox; WithFonts:Boolean=False);

  procedure AddItem(const AText:String; AObject:TObject);
  var item : TListBoxItem;
  begin
    item:=TListBoxItem.Create(AList.Owner);
    item.Text:=AText;
    item.Data:=AObject;
    item.Parent:=AList;
  end;

  procedure AddAxis(const Description:String; Axis:TChartAxis);
  begin
    AddItem(Description,Axis);
    AddItem(Description+' ('+TeeMsg_AxisTitle+')',Axis.Title);
  end;

var t : Integer;
begin
  with AList do
  begin
    AddItem(teeMsg_Legend,AChart.Legend);
    AddItem(teeMsg_LegendTitle,AChart.Legend.Title);
    AddItem(teeMsg_Title,AChart.Title);
    AddItem(teeMsg_Foot,AChart.Foot);
    AddItem(teeMsg_SubTitle,AChart.SubTitle);
    AddItem(teeMsg_SubFoot,AChart.SubFoot);

    for t:=0 to AChart.SeriesCount-1 do
    begin
      if (not WithFonts) or
         Assigned(FontOfPersistent(AChart[t],AChart[t].Marks.Font)) then
            AddItem(SeriesTitleOrName(AChart[t]),AChart[t]);

      AddItem(SeriesTitleOrName(AChart[t])+' ('+TeeTranslateString(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
         AddItem(AChart.Tools[t].Name,AChart.Tools[t]);
  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 TGeneralEditor.FillFonts;
begin
  LBFonts.Clear;
  GetChartObjects(Chart,LBFonts,True);

//  LBFonts.ItemIndex:=IndexOfObject(Chart.Title);
end;

procedure TGeneralEditor.PageControl1Change(Sender: TObject);
begin
  if PageControl1.ActiveTab=TabFont then
     if LBFonts.Count=0 then
        FillFonts;
end;

procedure TGeneralEditor.PaintBox1Paint(Sender: TObject; const Canvas: TCanvas);
var R : TRect;
    t,
    tmpL : Integer;
    tmpP : TColorArray;
    tmpW : Single;
begin
  tmpP:=Chart.ColorPalette;
  if not Assigned(tmpP) then
     tmpP:=TeeColorPalette;

  tmpL:=Length(tmpP);

  R.Left:=PaintBox1.Width*0.25;
  R.Right:=R.Left+(PaintBox1.Width*0.5);

  tmpW:=((PaintBox1.Height-8)/(tmpL));

  for t:=0 to tmpL-1 do
  begin
    R.Top:=4+Round(t*tmpW);
    R.Bottom:=4+Round((t+1)*tmpW);

    PaintBox1.Canvas.Fill.Color:=tmpP[t];
    PaintBox1.Canvas.FillRect(R, 0,0, AllCorners, 1);
  end;
end;

procedure TGeneralEditor.CBAllowZoomChange(Sender: TObject);
begin
  Chart.Zoom.Allow:=CBAllowZoom.IsChecked;
end;

procedure TGeneralEditor.CBAnimatedZoomChange(Sender: TObject);
begin
  Chart.Zoom.Animated:=CBAnimatedZoom.IsChecked;
end;

function TGeneralEditor.SelectedFont(Index: Integer): TTeeFont;
var tmp : TObject;
begin
  tmp:=LBFonts.Selected.Data;

  if tmp is TTeeCustomShape then
     result:=TTeeCustomShape(tmp).Font
  else
  if tmp is TChartAxis then
     result:=TChartAxis(tmp).LabelsFont
  else
  if tmp is TChartSeries then
     result:=FontOfPersistent(tmp as TPersistent,TChartSeries(tmp).Marks.Font)
  else
     result:=FontOfPersistent(tmp as TPersistent);
end;

procedure TGeneralEditor.UDAniZoomStepsChangeTracking(Sender: TObject);
begin
  if Assigned(Chart) then
     Chart.Zoom.AnimatedSteps:=Round(UDAniZoomSteps.Value);
end;

procedure TGeneralEditor.UDMinPixChangeTracking(Sender: TObject);
begin
  if Assigned(Chart) then
     Chart.Zoom.MinimumPixels:=Round(UDMinPix.Value);
end;

procedure TGeneralEditor.UDTextSizeChangeTracking(Sender: TObject);
begin
  if Assigned(Chart) then
     Chart.Canvas.FontZoom:=UDTextSize.Value;
end;

procedure TGeneralEditor.BZoomColorClick(Sender: TObject);
begin
  TBrushEditor.Edit(Self,Chart.Zoom.Brush);
end;

function TGeneralEditor.IndexOfCursor(ACursor:TCursor):Integer;
var
  t: Integer;
begin
  for t := 0 to LBCursor.Count-1 do
    if LBCursor.ListItems[t].Tag=ACursor then
       Exit(t);

  result:=-1;
end;

procedure TGeneralEditor.RefreshChart(AChart:TCustomChart);
begin
  Chart:=AChart;

  CBAllowZoom.IsChecked:=Chart.Zoom.Allow;
  CBAnimatedZoom.IsChecked:=Chart.Zoom.Animated;
  UDAniZoomSteps.Value:=Chart.Zoom.AnimatedSteps;
  UDMinPix.Value:=Chart.Zoom.MinimumPixels;
  CBDir.ItemIndex:=Ord(Chart.Zoom.Direction);
  CBZoomMouse.ItemIndex:=Ord(Chart.Zoom.MouseButton);
  CBUpLeft.IsChecked:=Chart.Zoom.UpLeftZooms;
  CBHistory.IsChecked:=Chart.Zoom.History;
  CBZoomAspect.IsChecked:=Chart.Zoom.KeepAspectRatio;
  CBZoomText.ItemIndex:=Ord(Chart.View3DOptions.ZoomText);

  RGScroll.ItemIndex:=Ord(Chart.AllowPanning);
  CBScrollMouse.ItemIndex:=Ord(Chart.ScrollMouseButton);
  CBInsideBounds.IsChecked:=Chart.Panning.InsideBounds;

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

  LBCursor.ItemIndex:=IndexOfCursor(Chart.Cursor);
end;

class function TGeneralEditor.CreateEditor(AOwner: TComponent; AChart: TCustomChart):TForm;
begin
  result:=TGeneralEditor.Create(AOwner);
  TGeneralEditor(result).RefreshChart(AChart);
end;

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

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

procedure TGeneralEditor.CBUpLeftChange(Sender: TObject);
begin
  Chart.Zoom.UpLeftZooms:=CBUpLeft.IsChecked;
end;

procedure TGeneralEditor.CBHistoryChange(Sender: TObject);
begin
  Chart.Zoom.History:=CBHistory.IsChecked;
end;

procedure TGeneralEditor.CBZoomAspectChange(Sender: TObject);
begin
  Chart.Zoom.KeepAspectRatio:=CBZoomAspect.IsChecked;
end;

procedure TGeneralEditor.RGScrollChange(Sender: TObject);
begin
  Chart.AllowPanning:=TPanningMode(RGScroll.ItemIndex);
end;

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

procedure TGeneralEditor.CBInsideBoundsChange(Sender: TObject);
begin
  Chart.Panning.InsideBounds:=CBInsideBounds.IsChecked;
end;

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

  FreeAndNil(IBackup);
end;

procedure TGeneralEditor.LBCursorChange(Sender: TObject);
begin
  if LBCursor.Selected<>nil then
  begin
    Chart.Cursor:=TCursor(LBCursor.Selected.Tag);
    Chart.OriginalCursor:=Chart.Cursor;
  end;
end;

procedure TGeneralEditor.LBFontsChange(Sender: TObject);
begin
  ResetIFont;

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

    if Assigned(IFontEditor) then
       IFontEditor.RefreshFont(IFont)
    else
       IFontEditor:=TFontEditor.Embedd(nil,IFont,PanelFont);

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

procedure TGeneralEditor.LBFontsKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState);
begin
// TODO
end;

procedure TGeneralEditor.LBPaletteChange(Sender: TObject);
begin
  if not (csDestroying in ComponentState) then
  begin
    Chart.ColorPaletteIndex:=LBPalette.ItemIndex-1;
    PaintBox1.Repaint;
  end;
end;

procedure TGeneralEditor.BZoomPenClick(Sender: TObject);
begin
  TStrokeEditor.Edit(Self,Chart.Zoom.Pen);
end;

procedure TGeneralEditor.CBAllFontsChange(Sender: TObject);
begin
  if CBAllFonts.IsChecked then
     LBFonts.SelectAll
  else
  begin
    LBFonts.ClearSelection;
    LBFonts.ItemIndex:=0;
  end;
end;

procedure TGeneralEditor.ETextSizeChange(Sender: TObject);
begin
// TODO
end;

procedure TGeneralEditor.CBZoomTextChange(Sender: TObject);
begin
  Chart.View3DOptions.ZoomText:=TCanvasZoomText(CBZoomText.ItemIndex);
end;

procedure TGeneralEditor.ChangedFont(Sender: TObject);
var t   : Integer;
    tmp : TTeeFont;
begin
  if Assigned(IFont) then
  begin
    for t:=0 to LBFonts.Count-1 do
    if LBFonts.ListItems[t].IsSelected 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;
end;

end.
