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

unit ecLexLibDlg;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, StdCtrls, Buttons, ActnList, ImgList, ToolWin,
  ecSyntAnal;

type
  TLexerLibraryDlg = class(TForm)
    LV: TListView;
    ToolBar1: TToolBar;
    ImageList1: TImageList;
    ActionList1: TActionList;
    actOpenLib: TAction;
    actSaveLib: TAction;
    actLexerProps: TAction;
    actImportLexer: TAction;
    actExportLexer: TAction;
    actDeleteLexer: TAction;
    actNewLexer: TAction;
    ToolButton1: TToolButton;
    ToolButton2: TToolButton;
    ToolButton3: TToolButton;
    ToolButton4: TToolButton;
    ToolButton5: TToolButton;
    ToolButton6: TToolButton;
    ToolButton7: TToolButton;
    ToolButton8: TToolButton;
    ToolButton9: TToolButton;
    ToolButton10: TToolButton;
    ToolButton11: TToolButton;
    actClose: TAction;
    ToolButton12: TToolButton;
    ToolButton13: TToolButton;
    ToolButton14: TToolButton;
    OD1: TOpenDialog;
    SD1: TSaveDialog;
    OD: TOpenDialog;
    SD: TSaveDialog;
    ToolButton15: TToolButton;
    ToolButton16: TToolButton;
    actCopy: TAction;
    actClear: TAction;
    ToolButton17: TToolButton;
    procedure actLexerPropsUpdate(Sender: TObject);
    procedure actOpenLibExecute(Sender: TObject);
    procedure actSaveLibExecute(Sender: TObject);
    procedure actImportLexerExecute(Sender: TObject);
    procedure actLexerPropsExecute(Sender: TObject);
    procedure actExportLexerExecute(Sender: TObject);
    procedure actNewLexerExecute(Sender: TObject);
    procedure actDeleteLexerExecute(Sender: TObject);
    procedure actCloseExecute(Sender: TObject);
    procedure LVDragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    procedure LVDragDrop(Sender, Source: TObject; X, Y: Integer);
    procedure actCopyExecute(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure LVKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure actClearUpdate(Sender: TObject);
    procedure actClearExecute(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure LVChange(Sender: TObject; Item: TListItem;
      Change: TItemChange);
  private
    FLexLib: TSyntaxManager;
    procedure FillList;
    procedure FillItem(li: TListItem; FSynt: TSyntAnalyzer);
  protected
    procedure ReadState(Reader: TReader); override;
  public
  end;

function CustomizeLexerLib(LexerLib: TSyntaxManager): Boolean;

implementation

uses Clipbrd;

{$R *.dfm}

function CustomizeLexerLib(LexerLib: TSyntaxManager): Boolean;
begin
 with TLexerLibraryDlg.Create(nil) do
  try
    FLexLib := LexerLib;
    ShowModal;
    Result := True;
  finally
    Free;
  end;
end;

{ TLexerLibraryDlg }

procedure TLexerLibraryDlg.FormShow(Sender: TObject);
begin
  FillList;
end;

procedure TLexerLibraryDlg.actCloseExecute(Sender: TObject);
begin
  Close;
end;

procedure TLexerLibraryDlg.actLexerPropsUpdate(Sender: TObject);
begin
  (Sender as TAction).Enabled := LV.Selected <> nil;
end;

procedure TLexerLibraryDlg.FillItem(li: TListItem; FSynt: TSyntAnalyzer);
begin
  li.Caption := FSynt.LexerName;
  li.Checked := not FSynt.Internal;
  li.SubItems.Clear;
  li.SubItems.Add(FSynt.Extentions);
  li.SubItems.Add(IntToStr(FSynt.Formats.Count));
  li.SubItems.Add(IntToStr(FSynt.TokenRules.Count));
  li.SubItems.Add(IntToStr(FSynt.BlockRules.Count));
  li.SubItems.Add(IntToStr(FSynt.SubAnalyzers.Count));
  li.Data := FSynt;
end;

procedure TLexerLibraryDlg.FillList;
var i: integer;
    cur: TObject;
    li: TListItem;
begin
  if LV.Selected <> nil then cur := LV.Selected.Data
    else cur := nil;
  LV.Items.BeginUpdate;
  try
    LV.Items.Clear;
    for i := 0 to FLexLib.AnalyzerCount - 1 do
     begin
      li := LV.Items.Add;
      FillItem(li, FLexLib.Analyzers[i]);
      if li.Data = cur then li.Selected := True;
     end;
  finally
    LV.Items.EndUpdate;
  end;
end;

procedure TLexerLibraryDlg.actOpenLibExecute(Sender: TObject);
begin
  if FLexLib.FileName <> '' then
   begin
    OD1.InitialDir := ExtractFileDir(FLexLib.FileName);
    OD1.FileName := ExtractFileName(FLexLib.FileName);
   end;
  if OD1.Execute then
   begin
    FLexLib.LoadFromFile(OD1.FileName);
    FillList;
   end;
end;

procedure TLexerLibraryDlg.actSaveLibExecute(Sender: TObject);
begin
  if FLexLib.FileName <> '' then
   begin
    SD1.InitialDir := ExtractFileDir(FLexLib.FileName);
    SD1.FileName := ExtractFileName(FLexLib.FileName);
   end;
  if SD1.Execute then
    FLexLib.SaveToFile(SD1.FileName);
end;

procedure TLexerLibraryDlg.actImportLexerExecute(Sender: TObject);
var FSynt: TSyntAnalyzer;
    li: TListItem;
begin
  if OD.Execute then
   begin
    FSynt := FLexLib.AddAnalyzer;
    try
     FSynt.LoadFromFile(OD.FileName);
     li := LV.Items.Add;
     FillItem(li, FSynt);
     li.Selected := True;
    except
     FSynt.Free;
    end;
   end;
end;

procedure TLexerLibraryDlg.actLexerPropsExecute(Sender: TObject);
var FSynt: TSyntAnalyzer;
begin
  if LV.Selected <> nil then
   begin
    FSynt := TSyntAnalyzer(LV.Selected.Data);
    if FSynt.CustomizeLexer then
     begin
      FillItem(LV.Selected, FSynt);
      FLexLib.Modified := True;
     end;
   end;
end;

procedure TLexerLibraryDlg.actExportLexerExecute(Sender: TObject);
begin
  if (LV.Selected <> nil) and SD.Execute then
   TSyntAnalyzer(LV.Selected.Data).SaveToFile(SD.FileName);
end;

procedure TLexerLibraryDlg.actNewLexerExecute(Sender: TObject);
var FSynt: TSyntAnalyzer;
    li: TListItem;
begin
  FSynt := FLexLib.AddAnalyzer;
  if FSynt.CustomizeLexer then
   begin
    li := LV.Items.Add;
    FillItem(li, FSynt);
    li.Selected := True;
   end else FSynt.Free;
end;

procedure TLexerLibraryDlg.actDeleteLexerExecute(Sender: TObject);
begin
  if (LV.Selected <> nil) and
     (MessageBox(Handle, 'Do you really want to Delete this Lexer?', 'Confirmation',
               MB_YESNO or MB_ICONWARNING) = IDYES) then
   begin
    TComponent(LV.Selected.Data).Free;
    LV.Selected.Delete;
    FLexLib.Modified := True;
   end;
end;

procedure TLexerLibraryDlg.LVDragOver(Sender, Source: TObject; X,
  Y: Integer; State: TDragState; var Accept: Boolean);
var nd: TListItem;
begin
  nd := LV.GetItemAt(X, Y);
  Accept := (Sender = Source) and (nd <> LV.Selected) and (LV.Selected <> nil) and (nd <> nil);
end;

procedure TLexerLibraryDlg.LVDragDrop(Sender, Source: TObject; X,
  Y: Integer);
var nd: TListItem;
begin
  nd := LV.GetItemAt(X, Y);
  if nd = nil then Exit;
  FLexLib.Move(LV.Selected.Index, nd.Index);
  FillList;
end;

procedure TLexerLibraryDlg.actCopyExecute(Sender: TObject);
var FSynt: TSyntAnalyzer;
    li: TListItem;
begin
  FSynt := FLexLib.AddAnalyzer;
  FSynt.Assign(TSyntAnalyzer(LV.Selected.Data));
  li := LV.Items.Add;
  FillItem(li, FSynt);
  li.Selected := True;
end;

procedure TLexerLibraryDlg.FormActivate(Sender: TObject);
begin
 Width := Width + 1; // for auto resize columns in LV
end;

// for web site (private use)
procedure TLexerLibraryDlg.LVKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var i,j: integer;
    S: string;
    st: TStringList;
begin
  if (Key = Ord('K')) and (ssCtrl in Shift) then
   begin
    st:= TStringList.Create;
    for i := 0 to LV.Items.Count - 1 do
     begin
       s := Format('<td>%s</td>', [LV.Items[i].Caption]);
       for j := 0 to 4 do
         s := s + Format('<td>%s</td>', [LV.Items[i].SubItems[j]]);
       s := s + Format('<td>%s</td>', [DateToStr(Now)]);
       st.Add('<tr>' + s + '</tr>');
     end;
    Clipboard.AsText := st.Text;
    st.Free;
   end;
end;

procedure TLexerLibraryDlg.actClearUpdate(Sender: TObject);
begin
  actClear.Enabled := FLexLib.AnalyzerCount > 0;
end;

procedure TLexerLibraryDlg.actClearExecute(Sender: TObject);
begin
  if MessageDlg('Do you really want to remove all lexers from th library?', mtConfirmation, [mbYes, mbNo], 0) = idYes then
   begin
     LV.Items.Clear;
     FLexLib.Clear;
   end;
end;

procedure TLexerLibraryDlg.LVChange(Sender: TObject; Item: TListItem;
  Change: TItemChange);
begin
  if (Change = ctState) and Assigned(Item.Data) then
   TSyntAnalyzer(Item.Data).Internal := not Item.Checked;
end;

procedure TLexerLibraryDlg.ReadState(Reader: TReader);
begin
  inherited;
  BorderStyle := bsSizeable;
end;

end.

