{*********************************************}
{  TeeChart Charting Library for FireMonkey   }
{  Copyright (c) 2012-2020 by Steema Software }
{  All Rights Reserved                        }
{*********************************************}
unit FMXTee.Editor.Series.Grid;
{$I TeeDefs.inc}

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs, FMXTee.RadioGroup,
  {$IFNDEF UPTOXE3}
  FMX.StdCtrls,
  {$ENDIF}
  {$IFDEF D21}
  FMX.SpinBox,
  {$ENDIF}
  FMX.TabControl, FMXTee.Series.Surface, FMX.Edit, FMX.ListBox, FMX.Colors,
  FMXTee.Engine, FMXTee.Procs, FMX.Grid, FMX.Layouts, FMXTee.Chart.Grid;

type
  TGrid3DSeriesEditor = class(TForm,ITeeEventListener)
    TabControl1: TTabControl;
    TabSingle: TTabItem;
    TabRange: TTabItem;
    TabPalette: TTabItem;
    Panel1: TPanel;
    GroupBox1: TGroupBox;
    UDXGrid: TSpinBox;
    Label6: TLabel;
    UDZGrid: TSpinBox;
    Label7: TLabel;
    UDDepth: TSpinBox;
    Label8: TLabel;
    CBIrreg: TCheckBox;
    BColor: TComboColorBox;
    BRemove: TButton;
    Label4: TLabel;
    BFromColor: TComboColorBox;
    Label5: TLabel;
    BMidColor: TComboColorBox;
    Label3: TLabel;
    BToColor: TComboColorBox;
    Label9: TLabel;
    CBNoMiddle: TCheckBox;
    BSwap: TButton;
    BGallery: TButton;
    TabControl2: TTabControl;
    TabSteps: TTabItem;
    TabColors: TTabItem;
    UDPalette: TSpinBox;
    Label2: TLabel;
    CBUseMin: TCheckBox;
    Label10: TLabel;
    EPaletteMin: TEdit;
    EPaletteStep: TEdit;
    Label11: TLabel;
    UDLegendEvery: TSpinBox;
    Label12: TLabel;
    Panel2: TPanel;
    CBPalStyle: TComboBox;
    ListBoxItem1: TListBoxItem;
    ListBoxItem2: TListBoxItem;
    ListBoxItem3: TListBoxItem;
    ListBoxItem4: TListBoxItem;
    ListBoxItem5: TListBoxItem;
    ListBoxItem6: TListBoxItem;
    Label1: TLabel;
    Label13: TLabel;
    CBPalettes: TComboBox;
    BInvert: TButton;
    CBColorEach: TCheckBox;
    procedure FormActivate(Sender: TObject);
    procedure CBPalStyleChange(Sender: TObject);
    procedure BInvertClick(Sender: TObject);
    procedure BColorChange(Sender: TObject);
    procedure BFromColorChange(Sender: TObject);
    procedure BMidColorChange(Sender: TObject);
    procedure BToColorChange(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure UDZGridChange(Sender: TObject);
    procedure UDDepthChange(Sender: TObject);
    procedure UDPaletteChange(Sender: TObject);
    procedure CBIrregChange(Sender: TObject);
    procedure CBPalettesChange(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure TabControl1Change(Sender: TObject);
    procedure CBUseMinChange(Sender: TObject);
    procedure EPaletteMinChange(Sender: TObject);
    procedure EPaletteStepChange(Sender: TObject);
    procedure BSwapClick(Sender: TObject);
    procedure CBNoMiddleChange(Sender: TObject);
    procedure UDLegendEveryChange(Sender: TObject);
    procedure BRemoveClick(Sender: TObject);
    procedure BGalleryClick(Sender: TObject);
    procedure CBColorEachChange(Sender: TObject);
  private
    { Private declarations }
    FChartGrid    : TChartGrid;
    PaletteSeries : TChartSeries;
    Grid3D        : TCustom3DPaletteSeries;

    IChangingColor : Boolean;

    procedure CheckMidColor;
    procedure SetCustomPalette;
    procedure UpdatePalette;
    function EditGradientColors(var AStart,AMid,AEnd:TAlphaColor;
                                HideTabColors:Boolean):Boolean;

    procedure ChartGridEditingCell(Sender: TCustomChartGrid;
      ACol, ARow: Integer; var Allow: Boolean);
    procedure ChartGridChangeColor(Sender: TObject);
  protected
    Creating : Boolean;

    procedure TeeEvent(Event: TTeeEvent);
  public
    { Public declarations }
    class procedure ApplyPalette(const Series:TCustom3DPaletteSeries; Index:Integer);
    class function CreateEmbedd(const AOwner: TComponent;
                                const AGrid3D: TCustom3DPaletteSeries;
                                const AParent: TFmxObject): TForm;
    Procedure RefreshControls(const AGrid:TCustom3DPaletteSeries);
  end;

implementation

{$R *.fmx}

uses
  FMXTee.Canvas, FMXTee.Chart, FMXTee.ProConstants, FMXTee.Editor.Gradient,
  FMXTee.Editor.Stroke;

type
  TCustom3DGridSeriesAccess=class(TCustom3DGridSeries);
  TTeePanelAccess=class(TCustomTeePanel);

class function TGrid3DSeriesEditor.CreateEmbedd(const AOwner: TComponent;
                                const AGrid3D: TCustom3DPaletteSeries;
                                const AParent: TFmxObject): TForm;
begin
  result:=TGrid3DSeriesEditor.Create(AOwner);
  result.Name:=AOwner.ClassName+AParent.Name;
  TGrid3DSeriesEditor(result).RefreshControls(AGrid3D);
  EmbeddForm(result, AParent);
end;

class procedure TGrid3DSeriesEditor.ApplyPalette(const Series:TCustom3DPaletteSeries;
                                                 Index:Integer);
var tmp : TColorArray;
begin
  TColorPalettes.GetPalette(Index,tmp);
  Series.AddPalette(tmp);
end;

function TGrid3DSeriesEditor.EditGradientColors(var AStart,AMid,AEnd:TAlphaColor;
                                                HideTabColors:Boolean):Boolean;
var tmp : TTeeGradient;

//  Function EditedGradient:Boolean;
//  var tmpEd : TGradientEditor;
//  begin
//    tmpEd:=TGradientEditor.Create(Self);
//    with tmpEd do
//    try
//      RefreshGradient(tmp);
//
//      Panel1.Visible:=False;;
//
//      if HideTabColors then
//         TabSheet1.TabVisible:=False;
//
//      TabSheet2.TabVisible:=False;
//      TabDirections.TabVisible:=False;
//      TabSheet5.TabVisible:=False;
//
//      result:=ShowModal=mrOk;
//    finally
//      Free;
//    end;
//
//    tmpEd:=TTeeGradientEditor.Create(Self);
//    with tmpEd do  // 7.0
//    try
//
//    finally
//      Free;
//    end;
//  end;

begin
  result:=False;

  tmp:=TTeeGradient.Create(nil);
  try
    tmp.Visible:=True;
    tmp.StartColor:=AStart;
    tmp.MidColor:=AMid;
    tmp.EndColor:=AEnd;

    if TGradientEditor.Edit(Self, tmp) then
    begin
      AStart:=tmp.StartColor;
      AMid:=tmp.MidColor;
      AEnd:=tmp.EndColor;
      result:=True;
    end;
  finally
    tmp.Free;
  end;
end;

procedure TGrid3DSeriesEditor.CBColorEachChange(Sender: TObject);
begin
  if Assigned(Grid3D) then
  begin
    Grid3D.ColorEachPoint:=CBColorEach.IsChecked;
    BColor.Enabled:=not CBColorEach.IsChecked;
  end;
end;

procedure TGrid3DSeriesEditor.CBIrregChange(Sender: TObject);
begin
  if Assigned(Grid3D) then
    TCustom3DGridSeries(Grid3D).IrregularGrid:=CBIrreg.IsChecked
end;

procedure TGrid3DSeriesEditor.CBNoMiddleChange(Sender: TObject);
begin
  if Assigned(Grid3D) then
  begin
    if CBNoMiddle.IsChecked then
    begin
      Grid3D.MidColor:=clNone;
      BMidColor.Color:=clNone;
    end;

    CBNoMiddle.Enabled:=not CBNoMiddle.IsChecked;
  end;
end;

procedure TGrid3DSeriesEditor.CBPalettesChange(Sender: TObject);
begin
  if Assigned(Grid3D) then
  begin
    ApplyPalette(Grid3D,CBPalettes.ItemIndex);
    UpdatePalette;
  end;
end;

procedure TGrid3DSeriesEditor.CBPalStyleChange(Sender: TObject);
begin
  if Assigned(Grid3D) then
  begin
    Grid3D.PaletteStyle:=TTeePaletteStyle(CBPalStyle.ItemIndex);
    UpdatePalette;
  end;
end;

procedure TGrid3DSeriesEditor.CBUseMinChange(Sender: TObject);
begin
  if Assigned(Grid3D) then
  begin
    Grid3D.UsePaletteMin:=CBUseMin.IsChecked;
    EPaletteMin.Enabled:=Grid3D.UsePaletteMin;
  end;
end;

procedure TGrid3DSeriesEditor.BColorChange(Sender: TObject);
begin
  if Assigned(Grid3D) and (not IChangingColor) then
    Grid3D.SeriesColor:=BColor.Color;
end;

procedure TGrid3DSeriesEditor.BFromColorChange(Sender: TObject);
begin
  if Assigned(Grid3D) then
    Grid3D.StartColor:=BFromColor.Color;
end;

procedure TGrid3DSeriesEditor.BGalleryClick(Sender: TObject);
var tmpS : TAlphaColor;
    tmpM : TAlphaColor;
    tmpE : TAlphaColor;
begin
  tmpS:=Grid3D.StartColor;
  tmpM:=Grid3D.MidColor;
  tmpE:=Grid3D.EndColor;

  if EditGradientColors(tmpS,tmpM,tmpE,True) then
  begin
    Grid3D.StartColor:=tmpS;
    Grid3D.MidColor:=tmpM;
    Grid3D.EndColor:=tmpE;

    BFromColor.Color:=tmpS;
    BMidColor.Color:=tmpM;
    BToColor.Color:=tmpE;
    CheckMidColor;
  end;
end;

procedure TGrid3DSeriesEditor.BInvertClick(Sender: TObject);
begin
  if Assigned(Grid3D) then
  begin
    Grid3D.InvertPalette;
    SetCustomPalette;
  end;
end;

procedure TGrid3DSeriesEditor.BMidColorChange(Sender: TObject);
begin
  if Assigned(Grid3D) then
  begin
    Grid3D.MidColor:=BMidColor.Color;
    CheckMidColor;
  end;
end;

procedure TGrid3DSeriesEditor.BRemoveClick(Sender: TObject);
  var t : Integer;
begin
  if Assigned(Grid3D) then
  begin
    with Grid3D do
      for t:=0 to Count-1 do ValueColor[t]:=clTeeColor;
    BRemove.Enabled:=False;
  end;
end;

procedure TGrid3DSeriesEditor.BSwapClick(Sender: TObject);
var tmp : TColor;
begin
  if Assigned(Grid3D) then
  with Grid3D do
  begin
    tmp:=StartColor;
    StartColor:=EndColor;
    EndColor:=tmp;

    BFromColor.Color:=StartColor;
    BToColor.Color:=EndColor;
  end;
end;

procedure TGrid3DSeriesEditor.BToColorChange(Sender: TObject);
begin
  if Assigned(Grid3D) then
    Grid3D.EndColor:=BToColor.Color;
end;

procedure TGrid3DSeriesEditor.ChartGridChangeColor(Sender: TObject);
var Index : Integer;
begin
  Index:=FChartGrid.Selected-FChartGrid.FirstRowNum;
  Grid3D.Palette[Index].Color:=PaletteSeries.ValueColor[Index];
  Grid3D.Repaint;
end;

procedure TGrid3DSeriesEditor.ChartGridEditingCell(
  Sender: TCustomChartGrid; ACol, ARow: Integer; var Allow: Boolean);
begin
  Allow:=ACol=Sender.ColorsColumn;
end;

procedure TGrid3DSeriesEditor.FormActivate(Sender: TObject);
begin
  Grid3D:=TCustom3DPaletteSeries(TagObject);

  if Assigned(Grid3D) then
     RefreshControls(Grid3D);
end;

procedure TGrid3DSeriesEditor.FormCreate(Sender: TObject);
begin
  Creating:=True;

  FChartGrid:=TChartGrid.Create(Self);
  FChartGrid.Align:=TAlignLayout.{$IFDEF D20}Client{$ELSE}alClient{$ENDIF};
  FChartGrid.OnEditingCell:=ChartGridEditingCell;
  FChartGrid.OnChangeColor:=ChartGridChangeColor;
  TabColors.AddObject(FChartGrid);

  ColorPalettes.AddTo(CBPalettes.Items);

  PaletteSeries:=TChartSeries.Create(nil);
  PaletteSeries.MandatoryValueList.Name:=TeeMsg_UpToValue;

  FChartGrid.Series:=PaletteSeries;
  FChartGrid.ShowFields:=False;
  //FChartGrid.EditorMode:=False;
  FChartGrid.AllowAppend:=False;
  FChartGrid.Columns[2].Width:=90;
end;

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

  if Assigned(Grid3D) and Assigned(Grid3D.ParentChart) then
     TTeePanelAccess(Grid3D.ParentChart).RemoveListener(Self);
end;

procedure TGrid3DSeriesEditor.CheckMidColor;
begin
  CBNoMiddle.IsChecked:=Grid3D.MidColor=clNone;
  CBNoMiddle.Enabled:=not CBNoMiddle.IsChecked;
end;

procedure TGrid3DSeriesEditor.EPaletteMinChange(Sender: TObject);
begin
  if not Creating and Assigned(Grid3D) then
     with Grid3D do PaletteMin:=StrToFloatDef(EPaletteMin.Text,PaletteMin);
end;

procedure TGrid3DSeriesEditor.EPaletteStepChange(Sender: TObject);
begin
  if not Creating and Assigned(Grid3D) then
     with Grid3D do PaletteStep:=StrToFloatDef(EPaletteStep.Text,PaletteStep);
end;

procedure TGrid3DSeriesEditor.RefreshControls(const AGrid:TCustom3DPaletteSeries);
begin
  Creating:=True;

  Grid3D:=AGrid;

  if Grid3D is TCustom3DGridSeries then
  With TCustom3DGridSeriesAccess(Grid3D) do
  begin
    UDXGrid.Value:=NumXValues;
    UDZGrid.Value:=NumZValues;
    CBIrreg.IsChecked :=IrregularGrid;

    EnableControls(CanCreateValues,[UDXGrid,UDZGrid]);
  end
  else
  begin
    EnableControls(False,[UDXGrid,UDZGrid]);
    CBIrreg.Visible:=False;
  end;

  if Assigned(Grid3D) then
  begin
    With Grid3D do
    begin
      UDDepth.Value:=TimesZOrder;
      UDPalette.Value:=PaletteSteps;
      CBPalStyle.ItemIndex:=Ord(PaletteStyle);
      UpdatePalette;

      if UseColorRange then
         TabControl1.ActiveTab:=TabRange
      else
      if UsePalette then
      begin
        TabControl1.ActiveTab:=TabPalette;
        TabControl2.ActiveTab:=TabSteps;
      end
      else
         TabControl1.ActiveTab:=TabSingle;

      CBUseMin.IsChecked:=UsePaletteMin;
      EPaletteMin.Text:=FloatToStr(PaletteMin);
      EPaletteMin.Enabled:=UsePaletteMin;
      EPaletteStep.Text:=FloatToStr(PaletteStep);

      UDLegendEvery.Value:=LegendEvery;

      CheckMidColor;

      BColor.Color:=SeriesColor;
      BFromColor.Color:=StartColor;
      BMidColor.Color:=MidColor;
      BToColor.Color:=EndColor;
    end;

    BRemove.Enabled:=HasColors(Grid3D);

    if Assigned(Grid3D.ParentChart) then
       TTeePanelAccess(Grid3D.ParentChart).Listeners.Add(Self);
  end;

  Creating:=False;
end;

procedure TGrid3DSeriesEditor.SetCustomPalette;
begin
  Grid3D.PaletteStyle:=psCustom;
  CBPalStyle.ItemIndex:=Ord(Grid3D.PaletteStyle);
  CBPalettes.ItemIndex:=-1;
  UpdatePalette;
end;

procedure TGrid3DSeriesEditor.TabControl1Change(Sender: TObject);
begin
  if (not Creating) and Assigned(Grid3D) then
  begin
    if TabControl1.ActiveTab=TabSingle then
    begin
      With Grid3D do
      begin
        UseColorRange:=False;
        UsePalette:=False;
      end;
    end
    else
    if TabControl1.ActiveTab=TabRange then
    begin
      Grid3D.UseColorRange:=True;
      Grid3D.UsePalette:=False;
    end
    else
    begin
      Grid3D.UseColorRange:=False;
      Grid3D.UsePalette:=True;

      if Grid3D.PaletteStyle<>psCustom then
         Grid3D.ClearPalette;

      UpdatePalette;
    end;
  end;
end;

procedure TGrid3DSeriesEditor.TeeEvent(Event: TTeeEvent);
begin
  if not (csDestroying in ComponentState) then
     if Event is TTeeSeriesEvent then
     with TTeeSeriesEvent(Event) do
          if Event=seChangeColor then
          begin
            IChangingColor:=True;
            try
              BColor.Color:=Grid3D.SeriesColor;
            finally
              IChangingColor:=False;
            end;
          end;
end;

procedure TGrid3DSeriesEditor.UDDepthChange(Sender: TObject);
begin
  if not Creating and Assigned(Grid3D) then
    Grid3D.TimesZOrder:=Round(UDDepth.Value);
end;

procedure TGrid3DSeriesEditor.UDLegendEveryChange(Sender: TObject);
begin
  if not Creating and Assigned(Grid3D) then
     with Grid3D do LegendEvery:=Round(UDLegendEvery.Value);
end;

procedure TGrid3DSeriesEditor.UDPaletteChange(Sender: TObject);
begin
  if (not Creating) and Assigned(Grid3D) then
  begin
    Grid3D.PaletteSteps:=Round(UDPalette.Value);
    UpdatePalette;
  end;
end;

procedure TGrid3DSeriesEditor.UDZGridChange(Sender: TObject);
begin
  if not Creating then
  if Assigned(Grid3D) and (Grid3D is TCustom3DGridSeries) then
  With TCustom3DGridSeries(Grid3D) do
     if (Round(UDXGrid.Value)<>NumXValues) or (Round(UDZGrid.Value)<>NumZValues) then
        CreateValues(Round(UDXGrid.Value),Round(UDZGrid.Value));
end;

procedure TGrid3DSeriesEditor.UpdatePalette;
var t : Integer;
begin
  CBPalettes.Enabled:=Grid3D.PaletteStyle=psCustom;
  FChartGrid.ReadOnly:=not CBPalettes.Enabled;

  if (Grid3D.PaletteStyle<>psCustom) and (Length(Grid3D.Palette)=0) then
     Grid3D.CreateDefaultPalette;

  PaletteSeries.Clear;
  for t:=0 to Length(Grid3D.Palette)-1 do
      PaletteSeries.Add(Grid3D.Palette[t].UpToValue,'',Grid3D.Palette[t].Color);

  FChartGrid.RecalcDimensions;
  FChartGrid.Repaint;
end;

initialization
  RegisterSeriesEditor(TGrid3DSeriesEditor);
end.
