{ *************************************************************************** }
{                                                                             }
{ EControl Syntax Editor SDK                                                  }
{                                                                             }
{ Copyright (c) 2004 - 2008 EControl Ltd., Zaharov Michael                    }
{     www.econtrol.ru                                                         }
{     support@econtrol.ru                                                     }
{                                                                             }
{ *************************************************************************** }
{$I ecSyntEdit.INC}

unit ecMacroEditDlg;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ActnList, ecSyntMemo, ecMacroRec, ComCtrls;

type
  TMacrosEditDlg = class(TForm)
    GroupBox1: TGroupBox;
    MacrosList: TListBox;
    GroupBox2: TGroupBox;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Button5: TButton;
    Button6: TButton;
    Button7: TButton;
    Button8: TButton;
    Button9: TButton;
    ActionList1: TActionList;
    MacrosPlay: TAction;
    MacrosRename: TAction;
    MacrosDelete: TAction;
    Recorder: TecMacroRecorder;
    CommandChange: TAction;
    CommandInsert: TAction;
    CommandDelete: TAction;
    CommandClear: TAction;
    FileImport: TAction;
    FileExport: TAction;
    Button10: TButton;
    Button11: TButton;
    OpenDialog1: TOpenDialog;
    SaveDialog1: TSaveDialog;
    CmdList: TListView;
    Button12: TButton;
    MacrosAdd: TAction;
    procedure FormCreate(Sender: TObject);
    procedure MacrosUpdate(Sender: TObject);
    procedure FileImportExecute(Sender: TObject);
    procedure FileExportExecute(Sender: TObject);
    procedure MacrosPlayUpdate(Sender: TObject);
    procedure MacrosPlayExecute(Sender: TObject);
    procedure MacrosRenameExecute(Sender: TObject);
    procedure MacrosDeleteExecute(Sender: TObject);
    procedure CommandChangeUpdate(Sender: TObject);
    procedure CommandDeleteUpdate(Sender: TObject);
    procedure CommandDeleteExecute(Sender: TObject);
    procedure CommandClearUpdate(Sender: TObject);
    procedure CommandClearExecute(Sender: TObject);
    procedure MacrosListClick(Sender: TObject);
    procedure CommandChangeExecute(Sender: TObject);
    procedure MacrosListDblClick(Sender: TObject);
    procedure CmdListDblClick(Sender: TObject);
    procedure CommandInsertExecute(Sender: TObject);
    procedure CmdListDragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    procedure CmdListDragDrop(Sender, Source: TObject; X, Y: Integer);
    procedure MacrosListDragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    procedure MacrosListDragDrop(Sender, Source: TObject; X, Y: Integer);
    procedure MacrosAddExecute(Sender: TObject);
  private
    FPlayIdx: integer;
    FCanPlay: Boolean;
    procedure SetMacroRecorder(const Value: TecMacroRecorder);
  protected
    procedure FillMacrosList;
    procedure FillCommands;
    procedure FillCmdItem(li: TListItem; MacroCmd: TMacroEvent);
  public
    property MacroRecorder: TecMacroRecorder read Recorder write SetMacroRecorder;
    property PlayIdx: integer read FPlayIdx;
  end;

function EditMacro(Macros: TecMacroRecorder; CanPlay: Boolean = True): Boolean;

implementation

uses {$IFDEF EC_DOTNET}Types,{$ENDIF} ecKeyMap, ecMacroCmdEditDlg, ecStrUtils;

{$R *.dfm}

function EditMacro(Macros: TecMacroRecorder; CanPlay: Boolean): Boolean;
begin
  Result := False;
  if Macros <> nil then
  with TMacrosEditDlg.Create(nil) do
    try
      MacroRecorder := Macros;
      FCanPlay := FCanPlay and CanPlay;
      if ShowModal = mrOK then
        begin
          Macros.Assign(MacroRecorder);
          if PlayIdx <> -1 then
            Macros.Play(PlayIdx);
          Result := True;
        end;
    finally
      Free;
    end;
end;

procedure TMacrosEditDlg.FormCreate(Sender: TObject);
begin
  FPlayIdx := -1;
end;

procedure TMacrosEditDlg.SetMacroRecorder(const Value: TecMacroRecorder);
begin
  if Value <> nil then
    begin
      Recorder.Assign(Value);
      FCanPlay := Value.SyntMemo <> nil;
      FillMacrosList;
    end;
end;

procedure TMacrosEditDlg.FillMacrosList;
var i: integer;
begin
  MacrosList.Items.Clear;
  for i := 0 to Recorder.Count - 1 do
    if Recorder[i].Name = '' then
      MacrosList.Items.Add('<Unnamed>')
    else
      MacrosList.Items.Add(Recorder[i].Name);
  if MacrosList.Items.Count > 0 then
    MacrosList.ItemIndex := 0;
  FillCommands;
end;

procedure TMacrosEditDlg.FillCmdItem(li: TListItem; MacroCmd: TMacroEvent);
var cmd: TecCommandItem;
begin
  li.Caption := IntToStr(MacroCmd.Command);
  li.SubItems.Clear;
  li.SubItems.Add(MacroCmd.Data);
  cmd := DefaultKeyMapping.CommandByID(MacroCmd.Command);
  if cmd <> nil then
    li.SubItems.Add(cmd.DisplayName);
end;

procedure TMacrosEditDlg.FillCommands;
var i: integer;
begin
  CmdList.Items.BeginUpdate;
  try
    CmdList.Items.Clear;
    if MacrosList.ItemIndex <> -1 then
     with Recorder[MacrosList.ItemIndex] do
      for i := 0 to Count - 1 do
       FillCmdItem(CmdList.Items.Add, Events[i]);
  finally
    CmdList.Items.EndUpdate;
  end;
end;

procedure TMacrosEditDlg.MacrosListClick(Sender: TObject);
begin
  FillCommands;
end;

procedure TMacrosEditDlg.FileImportExecute(Sender: TObject);
begin
  if OpenDialog1.Execute then
    begin
      Recorder.LoadFromFile(OpenDialog1.FileName);
      FillMacrosList;
    end;
end;

procedure TMacrosEditDlg.FileExportExecute(Sender: TObject);
begin
  if SaveDialog1.Execute then
    Recorder.SaveToFile(SaveDialog1.FileName);
end;

procedure TMacrosEditDlg.MacrosUpdate(Sender: TObject);
begin
  (Sender as TAction).Enabled := MacrosList.ItemIndex <> -1;
end;

procedure TMacrosEditDlg.MacrosPlayUpdate(Sender: TObject);
begin
  MacrosPlay.Enabled := (MacrosList.ItemIndex <> -1) and FCanPlay;
end;

procedure TMacrosEditDlg.MacrosPlayExecute(Sender: TObject);
begin
  FPlayIdx := MacrosList.ItemIndex;
  Close;
  ModalResult := mrOk;
end;

procedure TMacrosEditDlg.MacrosRenameExecute(Sender: TObject);
var S: string;
begin
  S := Recorder[MacrosList.ItemIndex].Name;
  if InputQuery('Macro Name', 'Enter macro name', S) then
    begin
      Recorder[MacrosList.ItemIndex].Name := S;
      if S = '' then S := '<Unnamed>';
      MacrosList.Items[MacrosList.ItemIndex] := S;
    end;
end;

procedure TMacrosEditDlg.MacrosDeleteExecute(Sender: TObject);
var idx: integer;
begin
  idx := MacrosList.ItemIndex;
  Recorder.DeleteMacro(idx);
  MacrosList.Items.Delete(idx);
  if idx >= MacrosList.Items.Count then
    Dec(idx);
  MacrosList.ItemIndex := idx;
  FillCommands;
end;

procedure TMacrosEditDlg.CommandDeleteUpdate(Sender: TObject);
begin
  CommandDelete.Enabled := CmdList.SelCount >= 1;
end;

procedure TMacrosEditDlg.CommandDeleteExecute(Sender: TObject);
var i: integer;
begin
  for i := CmdList.Items.Count - 1 downto 0 do
    if CmdList.Items[i].Selected then
      begin
        Recorder[MacrosList.ItemIndex].Delete(i);
        CmdList.Items.Delete(i);
      end;
end;

procedure TMacrosEditDlg.CommandClearUpdate(Sender: TObject);
begin
  CommandClear.Enabled := CmdList.Items.Count > 0;
end;

procedure TMacrosEditDlg.CommandClearExecute(Sender: TObject);
var i: integer;
begin
  with Recorder[MacrosList.ItemIndex] do
    for i := Count - 1 downto 0 do
      Delete(i);
  FillCommands;
end;

procedure TMacrosEditDlg.CommandChangeUpdate(Sender: TObject);
begin
  CommandChange.Enabled := CmdList.SelCount = 1;
end;

procedure TMacrosEditDlg.CommandChangeExecute(Sender: TObject);
var cmd: TMacroEvent;
begin
  cmd := Recorder[MacrosList.ItemIndex][CmdList.Selected.Index];
  with cmd do
    if EditMacroCommand(Command, Data) then
      FillCmdItem(CmdList.Selected, cmd);
end;

procedure TMacrosEditDlg.MacrosListDblClick(Sender: TObject);
begin
  if MacrosRename.Enabled then
    MacrosRename.Execute;
end;

procedure TMacrosEditDlg.CmdListDblClick(Sender: TObject);
begin
  if CommandChange.Enabled then
    CommandChange.Execute;
end;

procedure TMacrosEditDlg.CommandInsertExecute(Sender: TObject);
var cmd: integer;
    data: ecString;
begin
  if EditMacroCommand(cmd, data) then
   begin
    Recorder[MacrosList.ItemIndex].Add(cmd, data);
    FillCommands;
    if CmdList.Items.Count > 0 then
      CmdList.Items[CmdList.Items.Count - 1].Selected := True;
   end;
end;

procedure TMacrosEditDlg.CmdListDragOver(Sender, Source: TObject; X,
  Y: Integer; State: TDragState; var Accept: Boolean);
var li: TListItem;
begin
  if Source = CmdList then
    begin
      li := CmdList.GetItemAt(X, Y);
      Accept := (li <> nil) and (CmdList.SelCount = 1) and
                (CmdList.Selected <> li);
    end else
      Accept := False;
end;

procedure TMacrosEditDlg.CmdListDragDrop(Sender, Source: TObject; X,
  Y: Integer);
var li: TListItem;
    i: integer;
begin
  li := CmdList.GetItemAt(X, Y);
  if (li = nil) or (CmdList.Selected = nil) then Exit;
  if Source = CmdList then
    begin
      Recorder[MacrosList.ItemIndex].Move(CmdList.Selected.Index, li.Index);
      i := li.Index;
      FillCommands;
      if i < CmdList.Items.Count then
        CmdList.Items[i].Selected := True;
    end;
end;

procedure TMacrosEditDlg.MacrosListDragOver(Sender, Source: TObject; X,
  Y: Integer; State: TDragState; var Accept: Boolean);
var Idx: integer;
begin
  if Source = MacrosList then
    begin
      Idx := MacrosList.ItemAtPos(Point(X, Y), True);
      Accept := (Idx <> -1) and (MacrosList.ItemIndex <> -1) and
                (Idx <> MacrosList.ItemIndex);
    end else
      Accept := False;
end;

procedure TMacrosEditDlg.MacrosListDragDrop(Sender, Source: TObject; X,
  Y: Integer);
var Idx, CurIdx: integer;
begin
  if Source = MacrosList then
    begin
      CurIdx := MacrosList.ItemIndex;
      Idx := MacrosList.ItemAtPos(Point(X, Y), True);
      MacrosList.Items.Move(CurIdx, Idx);
      Recorder.MoveMacro(CurIdx, Idx);
    end;
end;

procedure TMacrosEditDlg.MacrosAddExecute(Sender: TObject);
begin
  Recorder.AddMacro(TMacroRecord.Create);
  FillMacrosList;
  MacrosList.ItemIndex := MacrosList.Items.Count - 1;
end;

end.
