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

unit VarOrderForm;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, StrUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Forms, Vcl.Dialogs, Vcl.Buttons,
  Vcl.Controls, Vcl.StdCtrls,Vcl.ComCtrls, Vcl.ExtCtrls, Editor;

type
  TVarOrder = class(TForm)
    pnlVarList: TPanel;
    VarListView: TListView;
    btnOK: TButton;
    btnCancel: TButton;
    btnTop: TSpeedButton;
    btnMoveUp: TSpeedButton;
    btnMoveDown: TSpeedButton;
    btnBottom: TSpeedButton;
    btnSort: TSpeedButton;
    btnDefOrder: TSpeedButton;
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure btnMoveUpClick(Sender: TObject);
    procedure VarListViewChange(Sender: TObject; Item: TListItem;
      Change: TItemChange);
    procedure btnMoveDownClick(Sender: TObject);
    procedure btnTopClick(Sender: TObject);
    procedure btnBottomClick(Sender: TObject);
    procedure btnSortClick(Sender: TObject);
    procedure btnDefOrderClick(Sender: TObject);
    procedure VarListViewDragDrop(Sender, Source: TObject; X, Y: Integer);
    procedure VarListViewDragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    procedure VarListViewCustomDrawItem(Sender: TCustomListView;
      Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
     totVars: integer;
     usedVars: TStringList;
     procedure ExchangeVars(const i, j: integer);
     procedure SetVarIcon(const s: string;  ListItem: TListItem);
     procedure ShowSelected(const i: integer);
  public
    { Public declarations }
     Changed: boolean;
  end;

var
  VarOrder: TVarOrder;

implementation

uses
  XFormMan, Global, Translation;  // to get default variation order

{$R *.dfm}

procedure TVarOrder.btnBottomClick(Sender: TObject);
var i: integer;
begin
  if not assigned(VarListView.Selected) then
  begin
    Application.MessageBox(PChar(TextByKey('varorder-noselected')),
      'Apophysis AV', MB_ICONWARNING);
    exit;
  end;

  i := VarListView.Selected.Index;
  ExchangeVars(i, totVars);
  ShowSelected(totVars);
end;

procedure TVarOrder.btnDefOrderClick(Sender: TObject);
var
    i, j: integer;
    s, cap: string;
begin
  VarListView.Items.BeginUpdate;

  if assigned(VarListView.Selected) then
    cap := VarListView.Selected.Caption
  else
    cap := 'linear';
  j := 0;

  for i := 0 to totVars do
  begin
    s := Varnames(i);
    VarListView.Items[i].Caption := s;
    SetVarIcon(s, VarListView.Items[i]);
    if s = cap then j := i;
  end;
  VarListView.Selected := VarListView.Items[j];
  ShowSelected(j);

  VarListView.Items.EndUpdate;
  Changed := True;
end;

procedure TVarOrder.btnMoveDownClick(Sender: TObject);
var i: integer;
begin
  if not assigned(VarListView.Selected) then
  begin
    Application.MessageBox(PChar(TextByKey('varorder-noselected')),
      'Apophysis AV', MB_ICONWARNING);
    exit;
  end;

  i := VarListView.Selected.Index;
  ExchangeVars(i, i + 1);
  ShowSelected(i + 1);
end;

procedure TVarOrder.btnMoveUpClick(Sender: TObject);
var i: integer;
begin
  if not assigned(VarListView.Selected) then
  begin
    Application.MessageBox(PChar(TextByKey('varorder-noselected')),
      'Apophysis AV', MB_ICONWARNING);
    exit;
  end;

  i := VarListView.Selected.Index;
  ExchangeVars(i, i - 1);
  ShowSelected(i - 1);
end;

procedure TVarOrder.btnSortClick(Sender: TObject);
begin
  VarListView.Items.BeginUpdate;
  VarListView.SortType := stText;
  VarListView.SortType := stNone;
  if not assigned(VarListView.Selected) then
    VarListView.Selected := VarListView.Items[0];
  ShowSelected(VarListView.Selected.Index);
  VarListView.Items.EndUpdate;
  Changed := True;
end;

procedure TVarOrder.btnTopClick(Sender: TObject);
var i: integer;
begin
  if not assigned(VarListView.Selected) then
  begin
    Application.MessageBox(PChar(TextByKey('varorder-noselected')),
      'Apophysis AV', MB_ICONWARNING);
    exit;
  end;

  i := VarListView.Selected.Index;
  ExchangeVars(i, 0);
  ShowSelected(0);
end;

procedure TVarOrder.ExchangeVars(const i, j: integer);
var
    tmpVarItem: TListItem;
    n: integer;
begin
  VarListView.Items.BeginUpdate;
  tmpVarItem := TListItem.Create(VarListView.Items);
  try
    if (i < j) then
      for n := i to (j - 1) do
      begin
        tmpVarItem.Assign(VarListView.Items.Item[n]);
        VarListView.Items.Item[n] := VarListView.Items.Item[n + 1];
        VarListView.Items.Item[n + 1] := tmpVarItem;
      end
    else // if (i > j) then
      for n := i downto (j + 1) do
      begin
        tmpVarItem.Assign(VarListView.Items.Item[n]);
        VarListView.Items.Item[n] := VarListView.Items.Item[n - 1];
        VarListView.Items.Item[n - 1] := tmpVarItem;
      end;
    VarListView.Selected := VarListView.Items[j];
    Changed := True;
  finally
    tmpVarItem.Free;
    VarListView.Items.EndUpdate;
  end;
end;

procedure TVarOrder.FormCreate(Sender: TObject);
begin
	btnOK.Caption := TextByKey('common-ok');
	btnCancel.Caption := TextByKey('common-cancel');
	btnMoveUp.Caption := TextByKey('favscripts-moveup');
	btnMoveDown.Caption := TextByKey('favscripts-movedown');
  btnTop.Caption := TextByKey('varorder-totop');
	btnBottom.Caption := TextByKey('varorder-tobottom');
  btnSort.Caption := TextByKey('varorder-byname');
  btnSort.Hint := TextByKey('varorder-bynamehint');
	btnDefOrder.Caption := TextByKey('varorder-byindex');
  btnDefOrder.Hint := TextByKey('varorder-byindexhint');
  self.Caption := TextByKey('varorder-title');
  usedVars := TStringList.Create;
end;

procedure TVarOrder.FormDestroy(Sender: TObject);
begin
  usedVars.Free;
end;

procedure TVarOrder.FormShow(Sender: TObject);
var
  ListItem: TListItem;
  i, SelTX: integer;
  s: string;
begin
  Changed := False;
  SelTX := EditForm.cbTransforms.ItemIndex;
  if SelTX < EditForm.cp.NumXForms then
  begin
    s := TextByKey('editor-common-transform') + '  ' + IntToStr(SelTX + 1);
    //if (EditForm.txtName.Text <> '') then
    //  s := s + ' - ' + EditForm.txtName.Text;
  end else
    s := TextByKey('editor-common-transform') + '  ' +
        TextByKey('editor-common-finalxformlistitem');
  VarListView.Column[0].Caption := s;
  totVars := NrVar - 1;
  VarListView.Items.BeginUpdate;
  VarListView.Items.Clear;
  usedVars.Clear;
  for i := 0 to totVars do
  begin
    ListItem := VarListView.Items.Add;
    s := EditForm.cp.xform[SelTX].ifs[i];
    ListItem.Caption := s;
    SetVarIcon(s, ListItem);
    ListItem.Indent := 1;
    if EditForm.cp.xform[SelTX].GetVariation(i) <> 0 then
      usedVars.Add(Varnames(i));
  end;
  VarListView.Items.EndUpdate;
  VarListView.Selected := VarListView.Items[0];
end;

procedure TVarOrder.SetVarIcon(const s: string; ListItem: TListItem);
begin
    if (LeftStr(s, 4) = 'pre_') or (s = 'flatten') then
      ListItem.ImageIndex := 7 // red
    else if LeftStr(s, 5) = 'post_' then
      ListItem.ImageIndex := 4 // blue
    else if (s = 'trianglecrop') or (s = 'projective')
    or (s = 'affine3D') or (s = 'spherecrop') then
      ListItem.ImageIndex := 6 // violet
    else
      ListItem.ImageIndex := 5 // green;
end;

procedure TVarOrder.ShowSelected(const i: integer);
begin
  try
    VarListView.Items[i].MakeVisible(false);
  finally
    VarListView.SetFocus;
  end;
end;

procedure TVarOrder.VarListViewChange(Sender: TObject; Item: TListItem;
  Change: TItemChange);
begin
  if (Item.Index = totVars) or (Item.Index < 0) then
  begin
    btnMoveDown.Enabled := False;
    btnBottom.Enabled := False;
  end else begin
    btnMoveDown.Enabled := True;
    btnBottom.Enabled := True;
  end;
  if (Item.Index <= 0) then
  begin
    btnMoveUp.Enabled := False;
    btnTop.Enabled := False;
  end else begin
    btnMoveUp.Enabled := True;
    btnTop.Enabled := True;
  end;
end;

procedure TVarOrder.VarListViewCustomDrawItem(Sender: TCustomListView;
  Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
var
  vRect: TRect;
begin
  DefaultDraw := True;
  if (usedVars.Count = 0) then exit;
  vRect := Item.DisplayRect(drLabel);
  if usedVars.IndexOf(Item.Caption) >= 0 then
    with VarListView.Canvas do
    begin
      if (CurrentStyle = 'Windows') then
        Brush.Color := $0002B076
      else
        Brush.Color := BrightColor;
      FillRect(vRect);
      if (CurrentStyle = 'Auric') then   // make the text more visible
        Font.Color := WinColor
      else
        Font.Color := TextColor;
      TextOut(vRect.Left + 2, vRect.Top + 2, Item.Caption);
    end;
end;

procedure TVarOrder.VarListViewDragDrop(Sender, Source: TObject; X, Y: Integer);
var
  i, j: integer;
begin
  if not assigned(VarListView.Selected) then exit;

  if Source = VarListView then
  begin
    try
      i := VarListView.Selected.Index;
      j := VarListView.GetItemAt(X,Y).Index;
      if (j >= 0) and (i >= 0) and (i <> j) then
        ExchangeVars(i, j);
    except
      Beep;
    end;
  end;
end;

procedure TVarOrder.VarListViewDragOver(Sender, Source: TObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
begin
  Accept := (Source = VarListView);
end;

end.
