unit Template;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls, StrUtils,
  OniDataClass, Functions, Data, Menus, Buttons;

type
  TNewFileSelectedEvent = procedure(fileinfo: TFileInfo) of object;
  TNewConnectionEvent = procedure(connection: TOniData) of object;

  TForm_ToolTemplate = class(TForm)
    panel_files: TPanel;
    filelist: TListBox;
    panel_extension: TPanel;
    label_ext: TLabel;
    combo_extension: TComboBox;
    check_zerobyte: TCheckBox;
    edit_filtername: TEdit;
    check_filtername: TCheckBox;
    Splitter1: TSplitter;
    content: TPanel;
    filepopup: TPopupMenu;
    popup_import: TMenuItem;
    popup_export: TMenuItem;
    popup_separator: TMenuItem;
    importd: TOpenDialog;
    exportd: TSaveDialog;
    btn_sort_id_asc: TSpeedButton;
    btn_sort_id_desc: TSpeedButton;
    btn_sort_name_asc: TSpeedButton;
    btn_sort_name_desc: TSpeedButton;
    btn_sort_ext_asc: TSpeedButton;
    btn_sort_ext_desc: TSpeedButton;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    combo_connection: TComboBox;
    Bevel1: TBevel;
    procedure RecreateList;
    procedure UpdateList;
    procedure RecreateExtList;
    procedure LoadFileNames;
    procedure SelectFileName(connection: TOniData; filename: String);
    procedure SelectFileID(connection: TOniData; id: Integer);
    procedure check_filternameClick(Sender: TObject);
    procedure check_zerobyteClick(Sender: TObject);
    procedure combo_extensionClick(Sender: TObject);
    procedure listClick(Sender: TObject);
    procedure listMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);

    procedure FormResize(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure popup_importClick(Sender: TObject);
    procedure popup_exportClick(Sender: TObject);
    procedure popup_opentool(Sender: TObject);
    procedure filepopupPopup(Sender: TObject);
    procedure btn_sortClick(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure combo_connectionChange(Sender: TObject);
  private
    FSortBy: TSortType;
    FOnNewFileSelected: TNewFileSelectedEvent;
    FOnNewConnection: TNewConnectionEvent;
    FAllowedExts: String;
    FAllowMultiSelect: Boolean;
    FSelectedFile: TFileInfo;
    FConnection: TOniData;
    procedure SetAllowedExts(exts: String);
    procedure SetMultiSelect(allow: Boolean);
  public
    constructor Create(AOwner: TComponent); override;
    procedure SetFileFilters(pattern, extension: String; zerobytes: Boolean);
  published
    property OnNewFileSelected: TNewFileSelectedEvent read FOnNewFileSelected write FOnNewFileSelected;
    property OnNewConnection: TNewConnectionEvent read FOnNewConnection write FOnNewConnection;
    property AllowedExts: String read FAllowedExts write SetAllowedExts;
    property AllowMultiSelect: Boolean read FAllowMultiSelect write SetMultiSelect;
    property SelectedFile: TFileInfo read FSelectedFile;
    property Connection: TOniData read FConnection;
  end;

var
  ToolList: TToolList;
procedure AddToolListEntry(context, name, exts: String);

implementation
{$R *.dfm}
uses Main, Exporters;


procedure TForm_ToolTemplate.UpdateList;
var
  i: Integer;
  fn, datatype, boxstring: String;
  level: Integer;
  oldcon: String;
begin
  oldcon := combo_connection.Items.Strings[combo_connection.ItemIndex];
  combo_connection.ItemIndex := -1;
  combo_connection.Items.Clear;
  if Length(DataConnections) > 0 then
  begin
    for i := 0 to High(DataConnections) do
    begin
      level := DataConnections[i].LevelInfo.LevelNumber;
      fn := ExtractFileName(DataConnections[i].FileName);
      if DataConnections[i].Backend = ODB_Dat then
        datatype := 'ONI-.dat: '
      else if DataConnections[i].Backend = ODB_ADB then
        datatype := 'OUP-DB: '
      else
        datatype := 'Unknown: ';
      boxstring := datatype + fn + ' (Level: ' + IntToStr(level) + ')';
      combo_connection.Items.Add(boxstring);
      if oldcon = boxstring then
        combo_connection.ItemIndex := combo_connection.Items.Count - 1;
    end;
    if combo_connection.ItemIndex = -1 then
    begin
      combo_connection.ItemIndex := 0;
      combo_connectionChange(Self);
    end;
  end
  else
  begin
    FConnection := nil;
    filelist.Items.Clear;
    combo_extension.Items.Clear;
    combo_connectionChange(Self);
    FSelectedFile := GetEmptyFileInfo;
    if Assigned(FOnNewFileSelected) then
      FOnNewFileSelected(FSelectedFile);
  end;
end;

procedure TForm_ToolTemplate.RecreateList;
var
  i: Integer;
  fn, datatype: String;
  level: Integer;
begin
  combo_connection.Items.Clear;
  if Length(DataConnections) > 0 then
  begin
    for i := 0 to High(DataConnections) do
    begin
      level := DataConnections[i].LevelInfo.LevelNumber;
      fn := ExtractFileName(DataConnections[i].FileName);
      if DataConnections[i].Backend = ODB_Dat then
        datatype := 'ONI-.dat: '
      else if DataConnections[i].Backend = ODB_ADB then
        datatype := 'OUP-DB: '
      else
        datatype := 'Unknown: ';
      combo_connection.Items.Add(datatype + fn + ' (Level: ' + IntToStr(level) + ')');
    end;
    FConnection := DataConnections[0];
    combo_connection.ItemIndex := 0;
    combo_connectionChange(Self);
  end
  else
  begin
    FConnection := nil;
    filelist.Items.Clear;
    combo_extension.Items.Clear;
    combo_connectionChange(Self);
  end;
end;

procedure TForm_ToolTemplate.RecreateExtList;
var
  i:    LongWord;
  exts: TStringArray;
begin
  combo_extension.Items.Clear;
  if FConnection <> nil then
  begin
    combo_extension.Items.Add('_All files_ (' +
      IntToStr(FConnection.GetFilesCount) + ')');
    exts := FConnection.GetExtensionsList;
    for i := 0 to High(exts) do
      if Length(FAllowedExts) > 0 then
      begin
        if Pos(MidStr(exts[i],1,4), FAllowedExts) > 0 then
        begin
          combo_extension.Items.Add(exts[i]);
        end;
      end else
        combo_extension.Items.Add(exts[i]);
    combo_extension.ItemIndex := 0;
    combo_extensionClick(Self);
  end;
end;




procedure TForm_ToolTemplate.LoadFileNames;
var
  Extension: String;
  no_zero_bytes: Boolean;
  pattern: String;
  files: TStringArray;
  i: LongWord;
begin
  if FConnection <> nil then
  begin
    Extension := MidStr(combo_extension.Items.Strings[combo_extension.ItemIndex], 1, 4);
    no_zero_bytes := not check_zerobyte.Checked;
    pattern := '';
    if check_filtername.Checked then
      pattern := edit_filtername.Text;
    if Extension = '_All' then
      if Length(FAllowedExts) > 0 then
        Extension := FAllowedExts
      else
        Extension := '';

    files := FConnection.GetFilesList(extension, pattern, no_zero_bytes, FSortBy);

    filelist.Visible := False;
    filelist.Items.Clear;
    if Length(files) > 0 then
      for i := 0 to High(files) do
        filelist.Items.Add(files[i]);
    filelist.Visible := True;
  end;
end;


procedure TForm_ToolTemplate.popup_exportClick(Sender: TObject);
var
  id: Integer;
  ext: String;
begin
  id := FConnection.ExtractFileID(filelist.Items.Strings[filelist.ItemIndex]);
  ext := RightStr(filelist.Items.Strings[filelist.ItemIndex], 4);
  exportd.Filter := 'Files of matching extension (*.' + ext + ')|*.' + ext + '|All files|*.*';
  exportd.DefaultExt := ext;
  if exportd.Execute then
    ExportDatFile(FConnection, id, exportd.FileName);
end;

procedure TForm_ToolTemplate.popup_importClick(Sender: TObject);
var
  id: Integer;
  finfo: TFileInfo;
  fs: TFileStream;
  data: TData;
begin
  id := FConnection.ExtractFileID(filelist.Items.Strings[filelist.ItemIndex]);
  finfo := FConnection.GetFileInfo(id);

  importd.Filter := 'Files of matching extension (*.' + finfo.Extension + ')|*.' +
        finfo.Extension + '|All files|*.*';
  if importd.Execute then
  begin
    fs := TFileStream.Create(importd.FileName, fmOpenRead);
    if fs.Size <> finfo.Size then
      ShowMessage('Can''t import ' + ExtractFilename(importd.FileName) +
        ', file has to have same size as file in .dat.' + CrLf +
        'Size of file in .dat: ' + FormatFileSize(finfo.Size) + CrLf +
        'Size of chosen file: ' + FormatFileSize(fs.Size))
    else begin
      SetLength(data, fs.Size);
      fs.Read(data[0], fs.Size);
      FConnection.UpdateDatFile(id, data);
      Self.listClick(Self);
    end;
    fs.Free;
  end;
end;

procedure TForm_ToolTemplate.popup_opentool(Sender: TObject);
var
  sender_name, context: String;
  id: Integer;
begin
  sender_name := TComponent(Sender).Name;
  id := FConnection.ExtractFileID(filelist.Items.Strings[filelist.ItemIndex]);
  context := MidStr(sender_name, Pos('_', sender_name) + 1, Length(sender_name) - Pos('_', sender_name));
  Form_Main.open_child(context, FConnection, id);
end;

procedure TForm_ToolTemplate.combo_connectionChange(Sender: TObject);
var
  name: String;
  nstart, nend: Integer;
  i: Integer;
begin
  if combo_connection.ItemIndex >= 0 then
  begin
    name := combo_connection.Items.Strings[combo_connection.ItemIndex];
    nstart := Pos(' ', name) + 1;
    nend := Pos('(', name) - 1;
    name := MidStr(name, nstart, nend - nstart);

    for i := 0 to High(DataConnections) do
    begin
      if ExtractFileName(DataConnections[i].FileName) = name then
      begin
        FConnection := DataConnections[i];
        Break;
      end;
    end;
    if i = Length(DataConnections) then
      FConnection := nil;

    RecreateExtList;
    if Assigned(FOnNewConnection) then
      FOnNewConnection(FConnection);
  end;
end;

procedure TForm_ToolTemplate.combo_extensionClick(Sender: TObject);
begin
  LoadFileNames;
end;


constructor TForm_ToolTemplate.Create(AOwner: TComponent);
var
  i: Integer;
  item: TMenuItem;
begin
  inherited;
  RecreateList;
  FSelectedFile := GetEmptyFileInfo;
  if Length(ToolList) > 0 then
  begin
    for i := 0 to High(ToolList) do
    begin
      item := TMenuItem.Create(filepopup);
      item.Name := 'popup_' + ToolList[i].context;
      item.Caption := 'Open with ' + ToolList[i].name;
      item.OnClick := Self.popup_opentool;
      filepopup.Items.Insert(i, item);
    end;
  end;
end;

procedure TForm_ToolTemplate.filepopupPopup(Sender: TObject);
var
  ext: String;
  i: Integer;
begin
  ext := RightStr(filelist.Items.Strings[filelist.ItemIndex], 4);
  for i := 0 to High(ToolList) do
  begin
    filepopup.Items.Items[i].Enabled := True;
    if Length(ToolList[i].exts) > 0 then
      if Pos(ext, ToolList[i].exts) = 0 then
        filepopup.Items.Items[i].Enabled := False;
  end;
end;

procedure TForm_ToolTemplate.check_zerobyteClick(Sender: TObject);
begin
  LoadFileNames;
end;

procedure TForm_ToolTemplate.btn_sortClick(Sender: TObject);
begin
  if btn_sort_id_asc.Down then
    FSortBy := stIDAsc
  else if btn_sort_id_desc.Down then
    FSortBy := stIDDesc
  else if btn_sort_name_asc.Down then
    FSortBy := stNameAsc
  else if btn_sort_name_desc.Down then
    FSortBy := stNameDesc
  else if btn_sort_ext_asc.Down then
    FSortBy := stExtAsc
  else if btn_sort_ext_desc.Down then
    FSortBy := stExtDesc;
  LoadFileNames;
end;

procedure TForm_ToolTemplate.check_filternameClick(Sender: TObject);
begin
  edit_filtername.Enabled := not check_filtername.Checked;
  LoadFileNames;
end;

procedure TForm_ToolTemplate.listClick(Sender: TObject);
var
  fileid: Integer;
begin
  if filelist.ItemIndex > -1 then
  begin
    fileid := FConnection.ExtractFileID(
          filelist.Items.Strings[filelist.ItemIndex]);
    FSelectedFile := FConnection.GetFileInfo(fileid);
    if Assigned(FOnNewFileSelected) then
      FOnNewFileSelected(FSelectedFile);
  end;
end;

procedure TForm_ToolTemplate.listMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  pt: TPoint;
begin
  pt.X := x;
  pt.Y := y;
//  filelist.ItemIndex := filelist.ItemAtPos(pt, true);
//  Self.listClick(Self);
end;



procedure TForm_ToolTemplate.SelectFileID(connection: TOniData; id: Integer);
var
  i: Integer;
  name: String;
  nstart, nend: Integer;
begin
  for i := 0 to combo_connection.Items.Count - 1 do
  begin
    name := combo_connection.Items.Strings[i];
    nstart := Pos(' ', name) + 1;
    nend := Pos('(', name) - 1;
    name := MidStr(name, nstart, nend - nstart);

    if ExtractFileName(connection.FileName) = name then
    begin
      combo_connection.ItemIndex := i;
      combo_connectionChange(Self);
    end;
  end;

  filelist.ItemIndex := -1;
  if filelist.Items.Count > 0 then
    for i := 0 to filelist.Items.Count - 1 do
      if FConnection.ExtractFileID(filelist.Items.Strings[i]) = id then
      begin
        filelist.ItemIndex := i;
        Break;
      end;
  Self.listClick(Self);
end;

procedure TForm_ToolTemplate.SelectFileName(connection: TOniData; filename: String);
var
  i: Integer;
  name: String;
  nstart, nend: Integer;
begin
  for i := 0 to combo_connection.Items.Count - 1 do
  begin
    name := combo_connection.Items.Strings[i];
    nstart := Pos(' ', name) + 1;
    nend := Pos('(', name) - 1;
    name := MidStr(name, nstart, nend - nstart);

    if ExtractFileName(connection.FileName) = name then
    begin
      combo_connection.ItemIndex := i;
      combo_connectionChange(Self);
    end;
  end;

  filelist.ItemIndex := -1;
  if filelist.Items.Count > 0 then
    for i := 0 to filelist.Items.Count - 1 do
      if filelist.Items.Strings[i] = filename then
        filelist.ItemIndex := i;
  Self.listClick(Self);
end;

procedure TForm_ToolTemplate.SetAllowedExts(exts: String);
begin
  FAllowedExts := exts;
  RecreateExtList;
end;

procedure TForm_ToolTemplate.SetFileFilters(pattern, extension: String;
  zerobytes: Boolean);
var
  i: Integer;
begin
  if Length(pattern) > 0 then
    Self.edit_filtername.Text := pattern;
  Self.check_filtername.Checked := Length(pattern) > 0;
  if Length(extension) > 0 then
  begin
    for i := 0 to Self.combo_extension.Items.Count - 1 do
      if Pos(extension, Self.combo_extension.Items.Strings[i]) > 0 then
        Break;
    if i < Self.combo_extension.Items.Count then
      Self.combo_extension.ItemIndex := i
    else
      Self.combo_extension.ItemIndex := -1;
  end;
  Self.check_zerobyte.Checked := zerobytes;
  Self.LoadFileNames;
end;

procedure TForm_ToolTemplate.SetMultiSelect(allow: Boolean);
begin
  FAllowMultiSelect := allow;
  filelist.MultiSelect := allow;
end;


procedure TForm_ToolTemplate.FormResize(Sender: TObject);
begin
  if Self.Width < 300 then
    Self.Width := 300;
  if Self.Height < 200 then
    Self.Height := 200;
end;



procedure TForm_ToolTemplate.FormCreate(Sender: TObject);
begin
  Self.Width  := 260;
  Self.Height := 300;
  FOnNewFileSelected := nil;
  FOnNewConnection := nil;
  FAllowedExts := '';
  FAllowMultiSelect := False;
end;

procedure TForm_ToolTemplate.FormActivate(Sender: TObject);
begin
  if edit_filtername.CanFocus then
    edit_filtername.SetFocus
  else
    if content.CanFocus then
      content.SetFocus;
end;

procedure TForm_ToolTemplate.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;


procedure AddToolListEntryExt(context, ext: String);
var
  i: Integer;
begin
  for i := 0 to High(ToolList) do
    if ToolList[i].context = context then
    begin
      if Pos(ext, ToolList[i].exts) = 0 then
      begin
        if Length(ToolList[i].exts) = 0 then
          ToolList[i].exts := ext
        else
          ToolList[i].exts := ToolList[i].exts + ',' + ext;
      end;
      Exit;
    end;
end;

procedure AddToolListEntry(context, name, exts: String);
var
  i: Integer;
begin
  if Length(ToolList) > 0 then
  begin
    for i := 0 to High(ToolList) do
      if ToolList[i].context = context then
      begin
        if (Length(ToolList[i].name) = 0) and (Length(name) > 0) then
          ToolList[i].name := name;
        if Length(exts) > 0 then
          AddToolListEntryExt(context, exts);
        Exit;
      end;
  end;
  SetLength(ToolList, Length(ToolList) + 1);
  for i := High(ToolList) downto 1 do
    if ToolList[i - 1].name > name then
      ToolList[i] := ToolList[i - 1]
    else
      Break;
  ToolList[i].context := context;
  ToolList[i].name := name;
  ToolList[i].exts := exts;
end;

end.