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;

  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;
    procedure RecreateList;
    procedure LoadFileNames;
    procedure SelectFileName(filename: String);
    procedure SelectFileID(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);
  private
    FSortBy: TSortType;
    FOnNewFileSelected: TNewFileSelectedEvent;
    FAllowedExts: String;
    FAllowMultiSelect: Boolean;
    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 AllowedExts: String read FAllowedExts write SetAllowedExts;
    property AllowMultiSelect: Boolean read FAllowMultiSelect write SetMultiSelect;
  end;

var
  ToolList: TToolList;
procedure AddToolListEntry(context, name, exts: String);

implementation
{$R *.dfm}
uses Main, Exporters;


procedure TForm_ToolTemplate.RecreateList;
var
  i:    LongWord;
  exts: TStringArray;
begin
  combo_extension.Items.Clear;
  combo_extension.Items.Add('_All files_ (' +
    IntToStr(OniDataConnection.GetFilesCount) + ')');
  exts := OniDataConnection.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;




procedure TForm_ToolTemplate.LoadFileNames;
var
  Extension: String;
  no_zero_bytes: Boolean;
  pattern: String;
  files: TStringArray;
  i: LongWord;
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 := OniDataConnection.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;


procedure TForm_ToolTemplate.popup_exportClick(Sender: TObject);
var
  id: Integer;
  ext: String;
begin
  id := OniDataConnection.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(id, exportd.FileName);
end;

procedure TForm_ToolTemplate.popup_importClick(Sender: TObject);
var
  id: Integer;
  finfo: TFileInfo;
  fs: TFileStream;
  data: TData;
begin
  id := OniDataConnection.ExtractFileID(filelist.Items.Strings[filelist.ItemIndex]);
  finfo := OniDataConnection.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);
      OniDataConnection.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 := OniDataConnection.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, id);
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;
  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 := OniDataConnection.ExtractFileID(
          filelist.Items.Strings[filelist.ItemIndex]);
    if Assigned(FOnNewFileSelected) then
      FOnNewFileSelected(OniDataConnection.GetFileInfo(fileid));
  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(id: Integer);
var
  i: Integer;
begin
  filelist.ItemIndex := -1;
  if filelist.Items.Count > 0 then
    for i := 0 to filelist.Items.Count - 1 do
      if OniDataConnection.ExtractFileID(filelist.Items.Strings[i]) = id then
      begin
        filelist.ItemIndex := i;
        Break;
      end;
  Self.listClick(Self);
end;

procedure TForm_ToolTemplate.SelectFileName(filename: String);
var
  i: Integer;
begin
  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;
  RecreateList;
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;
  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.