{ Apophysis AV "Phoenix Edition" Copyright (C) 2021 Alice V. Koryagina }

unit Chaos;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Grids, Vcl.ComCtrls, Editor, Translation,
  Vcl.StdCtrls, Math;

type
  TChaosForm = class(TForm)
    PageControl1: TPageControl;
    TabMatrix: TTabSheet;
    ChaosMatrix: TStringGrid;
    btnClose: TButton;
    TabDiagram: TTabSheet;
    chkPercents: TCheckBox;
    WeightVector: TStringGrid;
    procedure ChaosMatrixDrawCell(Sender: TObject; ACol, ARow: Integer;
      Rect: TRect; State: TGridDrawState);
    procedure FormActivate(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure btnCloseClick(Sender: TObject);
    procedure chkPercentsClick(Sender: TObject);
    procedure FormResize(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  ChaosForm: TChaosForm;

implementation

{$R *.dfm}


procedure TChaosForm.btnCloseClick(Sender: TObject);
begin
  Close;
end;

procedure TChaosForm.ChaosMatrixDrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
    h, ax, ay, bx, by: integer;
    val: double;
    trgColor : TColor;
    newRect: TRect;
  begin
  if (ARow = 0) and (ACol = 0) then exit;
  if not (gdFixed in	State) then
  begin
     trgColor := EditForm.GetTriangleColor(ACol - 1);
     with TStringGrid(Sender).Canvas do begin
        Brush.Color := trgColor;
        FillRect(Rect);
        Font.Color := clBlack; //clWindowText;
        if Sender = ChaosMatrix then
        begin
          val := EditForm.cp.xform[ACol - 1].modWeights[ARow - 1];
          if not chkPercents.Checked then
            TextOut(Rect.Left + 4, Rect.Top + 4, FloatToStr(RoundTo(val, -4)))
          else begin
            if ChaosMatrix.Cells[ACol, 1] = '0' then
              TextOut(Rect.Left + 4, Rect.Top + 4, '0%')
            else
              TextOut(Rect.Left + 4, Rect.Top + 4, Format('%g%%',
              [RoundTo(val / StrToFloat(ChaosMatrix.Cells[ACol, 1]), -4)]));
          end;
        end else  // if Sender = WeightVector then
        begin
          val := EditForm.cp.xform[ACol - 1].density;
          if not chkPercents.Checked then
            TextOut(Rect.Left + 4, Rect.Top + 4, FloatToStr(RoundTo(val, -4)))
          else   // weight sum is always not zero
            TextOut(Rect.Left + 4, Rect.Top + 4, Format('%g%%',
              [RoundTo(val / StrToFloat(WeightVector.Cells[1,1]), -4)]));
        end;
     end;
  end else
  begin
      if (ACol = 0) then
        trgColor := EditForm.GetTriangleColor(ARow - 1)
      else
        trgColor := EditForm.GetTriangleColor(ACol - 1);
      if (Sender = WeightVector) and (ARow = 1) then exit;
      with TStringGrid(Sender).Canvas do begin
        h := Rect.Bottom - Rect.Top - 2;
        ax := Rect.Right - 3;
        ay := Rect.Top + 2;
        bx := Rect.Right - h;
        by := Rect.Bottom - 3;

        pen.Color := clBlack;
        Polyline([Point(ax+1, ay-2), Point(ax+1, by+1), Point(bx-2, by+1), Point(ax+1, ay-2)]);

        pen.Color := trgColor;
        brush.Color := pen.Color shr 1 and $7f7f7f;
        Polygon([Point(ax, ay), Point(ax, by), Point(bx, by)]);
      end;
  end;
end;

procedure TChaosForm.chkPercentsClick(Sender: TObject);
begin
  WeightVector.Invalidate;
  ChaosMatrix.Invalidate;
end;

procedure TChaosForm.FormActivate(Sender: TObject);
var
    i, j, n: integer;
    sum: double;
begin
  n := EditForm.cp.NumXForms + 1;
  sum := 0;
  with WeightVector do begin
    ColCount := n;
    for i := 1 to n do
      Cells[i,0] := '   ' + IntToStr(i);
    for j := 0 to n-2 do
      sum := sum + EditForm.cp.xform[j].density;
    Cells[1, 1] := FloatToStr(sum * 0.01);
  end;
  with ChaosMatrix do begin
    ColCount := n;
    RowCount := n;
    for i := 1 to n do
    begin
       Cells[0,i] := Format(TextByKey('editor-common-toprefix'), [i]);
       Cells[i,0] := Format(TextByKey('editor-common-fromprefix'), [i]);
       sum := 0;
       for j := 0 to n-2 do
          sum := sum + EditForm.cp.xform[i-1].modWeights[j];
       Cells[i, 1] := FloatToStr(sum * 0.01);
    end;
    Height := TabMatrix.Height - Top - 24;
    Invalidate;
  end;
  chkPercents.Top := TabMatrix.Height - 20;
end;

procedure TChaosForm.FormCreate(Sender: TObject);
begin
  self.Caption := TextByKey('transitions-title');
  TabMatrix.Caption := TextByKey('transitions-matrix');
  btnClose.Caption := TextByKey('common-close');
  ChaosMatrix.Cells[0,0] := TextByKey('editor-tab-chaos-path');
  chkPercents.Caption := TextByKey('transitions-inpercents');
  WeightVector.Cells[0,0] := TextByKey('transitions-transform');
  WeightVector.Cells[0,1] := TextByKey('editor-common-weight');
  // AV: TODO: visualize Markov chain transitions using arrows
  // TabDiagram.Caption := TextByKey('transitions-diagram');
end;

procedure TChaosForm.FormResize(Sender: TObject);
begin
  ChaosMatrix.Height := TabMatrix.Height - ChaosMatrix.Top - 24;
  chkPercents.Top := TabMatrix.Height - 20;
  TabMatrix.Invalidate;
end;

end.
