unit Vis2D_XYPlotSettings;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, VisCtl2D,
  TextEditor, ColorContainer, Vcl.StdCtrls, ScrollBoxEx, UxPanel, Vcl.ExtCtrls,
  DoublePoint;

type
  TVis2D_XYPlotSettingsFrm = class(TDrawableOptionsFrm)
    pnToolbar: TUxClient;
    btnStyle: TUxButton;
    btnData: TUxButton;
    btnDiagramType: TUxButton;
    pnStyle: TPanel;
    pnData: TPanel;
    pnDiagramType: TPanel;
    btnApply: TUxButton;
    ScrollBox1: TScrollBoxEx;
    btnApplyData: TUxButton;
    eData: TTextEditor;
    cbPoints: TCheckBox;
    Label4: TLabel;
    ePointSize: TTextEditor;
    cbLines: TCheckBox;
    cbArea: TCheckBox;
    procedure CallUpdateDrawable(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure SetPage(Sender: TObject);
    procedure ScrollBox1Enter(Sender: TObject);
    procedure ScrollBox1Exit(Sender: TObject);
    procedure btnApplyDataClick(Sender: TObject);
    procedure cbPointsClick(Sender: TObject);
  strict private
    FPageButtons: TArray<TUxButton>;
    FStyle: TDrawableOptionsFrm;
    FDataLoaded: Boolean;
    procedure LoadData;
    function GetData: TArray<TPointD>;
  strict protected
    procedure Initialize; override;
    procedure UpdateDrawable; override;
  public

  end;

implementation

uses
  Math, Vis2D_ElementSettings, Generics.Collections;

{$R *.dfm}

{ TVis2D_XYPlotSettingsFrm }

procedure TVis2D_XYPlotSettingsFrm.btnApplyDataClick(Sender: TObject);
var
  XYPlot: TXYPlot;
begin

  if Initialized and FDataLoaded then
  begin
    XYPlot := FDrawable as TXYPlot;
    XYPlot.Data := GetData;
    UpdateDrawable;
  end;

end;

procedure TVis2D_XYPlotSettingsFrm.CallUpdateDrawable(Sender: TObject);
begin
  UpdateDrawable;
end;

procedure TVis2D_XYPlotSettingsFrm.cbPointsClick(Sender: TObject);
begin
  ePointSize.Enabled := cbPoints.Checked;
  CallUpdateDrawable(Sender);
end;

procedure TVis2D_XYPlotSettingsFrm.FormCreate(Sender: TObject);
var
  XYPlot: TXYPlot;
begin

  XYPlot := FDrawable as TXYPlot;

  btnStyle.Tag := NativeInt(pnStyle);
  btnData.Tag := NativeInt(pnData);
  btnDiagramType.Tag := NativeInt(pnDiagramType);
  FPageButtons := [btnStyle, btnData, btnDiagramType];

  SetPage(btnStyle);

  FStyle := TVis2D_ElementSettingsFrm.Create(Self, XYPlot.Style);
  FStyle.Parent := pnStyle;
  FStyle.BorderStyle := bsNone;
  FStyle.Align := alClient;
  FStyle.Show;

end;

function StrToPointD(const S: string): TPointD;
var
  p: Integer;
begin
  p := 1;
  while (p <= S.Length) and (S[p] <> ';') do
    Inc(p);
  if p > S.Length then
    raise Exception.CreateFmt('Invalid point: "%s"', [S]);
  Result.X := StrToFloat(Copy(S, 1, p - 1).Trim);
  Result.Y := StrToFloat(Copy(S, p + 1).Trim);
end;

function TVis2D_XYPlotSettingsFrm.GetData: TArray<TPointD>;
var
  List: TList<TPointD>;
  i: Integer;
begin

  List := TList<TPointD>.Create;
  try
    for i := 0 to eData.LineCount - 1 do
      if not eData.TextFile.LineIsEmpty(i) then
        List.Add(StrToPointD(eData.Lines[i]));
    Result := List.ToArray;
  finally
    List.Free;
  end;

end;

procedure TVis2D_XYPlotSettingsFrm.Initialize;
var
  XYPlot: TXYPlot;
begin

  inherited;

  XYPlot := FDrawable as TXYPlot;

  cbPoints.Checked := XYPlot.Points;
  cbLines.Checked := XYPlot.Lines;
  cbArea.Checked := XYPlot.Area;
  ePointSize.PlainText := XYPlot.PointSize.ToString;

end;

procedure TVis2D_XYPlotSettingsFrm.LoadData;
var
  XYPlot: TXYPlot;
  i: Integer;
begin

  XYPlot := FDrawable as TXYPlot;

  eData.BeginVisualUpdate;
  try
    eData.BeginAddLine;
    try
      eData.Clear;
      for i := 0 to High(XYPlot.Data) do
        eData.AddLine(XYPlot.Data[i].X.ToString + '; ' + XYPlot.Data[i].Y.ToString);
    finally
      eData.EndAddLine;
    end;
  finally
    eData.EndVisualUpdate(True);
  end;

  FDataLoaded := True;

end;

procedure TVis2D_XYPlotSettingsFrm.ScrollBox1Enter(Sender: TObject);
begin
  btnApply.Default := True;
end;

procedure TVis2D_XYPlotSettingsFrm.ScrollBox1Exit(Sender: TObject);
begin
  btnApply.Default := False;
end;

procedure TVis2D_XYPlotSettingsFrm.SetPage(Sender: TObject);
var
  B: TUxButton;
  P: TPanel;
begin
  for B in FPageButtons do
  begin
    if B.Tag = 0 then
      Continue;
    P := TObject(B.Tag) as TPanel;
    P.Align := alClient;
    P.Visible := B = Sender;
    B.Down := B = Sender;
    if P = pnData then
      LoadData;
    if (B = Sender) and Visible and P.Visible and P.CanFocus then
      P.SetFocus;
  end;
end;

procedure TVis2D_XYPlotSettingsFrm.UpdateDrawable;
var
  XYPlot: TXYPlot;
begin

  if not Initialized then
    Exit;

  XYPlot := FDrawable as TXYPlot;

  XYPlot.Points := cbPoints.Checked;
  XYPlot.Lines := cbLines.Checked;
  XYPlot.Area := cbArea.Checked;
  XYPlot.PointSize := StrToInt(ePointSize.PlainText);

  inherited;

end;

end.
