unit UFormList;

{$mode delphi}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ComCtrls,
  ActnList, Menus, fgl, UItemList;

type
  { TFormList }

  TFormList = class(TForm)
    AAdd: TAction;
    ASelectAll: TAction;
    AModify: TAction;
    ARemove: TAction;
    AClone: TAction;
    ActionList1: TActionList;
    ListView1: TListView;
    MenuItem1: TMenuItem;
    MenuItem2: TMenuItem;
    MenuItem3: TMenuItem;
    MenuItem4: TMenuItem;
    MenuItem5: TMenuItem;
    PopupMenu1: TPopupMenu;
    ToolBar1: TToolBar;
    ToolButton1: TToolButton;
    ToolButton2: TToolButton;
    ToolButton3: TToolButton;
    ToolButton4: TToolButton;
    procedure AAddExecute(Sender: TObject);
    procedure ACloneExecute(Sender: TObject);
    procedure AModifyExecute(Sender: TObject);
    procedure ARemoveExecute(Sender: TObject);
    procedure ASelectAllExecute(Sender: TObject);
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure ListView1CustomDrawSubItem(Sender: TCustomListView;
      Item: TListItem; SubItem: Integer; State: TCustomDrawState;
      var DefaultDraw: Boolean);
    procedure ListView1Data(Sender: TObject; Item: TListItem);
    procedure ListView1KeyPress(Sender: TObject; var Key: char);
    procedure ListView1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState
      );
    procedure ListView1SelectItem(Sender: TObject; Item: TListItem;
      Selected: Boolean);
  private
    FList: TItemList;
    procedure SetList(AValue: TItemList);
    procedure UpdateListViewColumns;
  public
    MinItemCount: Integer;
    MaxItemCount: Integer;
    procedure UpdateInterface;
    procedure UpdateList;
    property List: TItemList read FList write SetList;
  end;

var
  FormList: TFormList;


implementation

{$R *.lfm}

uses
  UCore, UFormItem;

resourcestring
  SRemoveItems = 'Remove items';
  SRemoveItemsQuery = 'Do you want to remove selected items?';
  SNew = 'New';

{ TFormList }

procedure TFormList.ARemoveExecute(Sender: TObject);
var
  I: Integer;
begin
  if Assigned(ListView1.Selected) then begin
    if MessageDlg(SRemoveItems, SRemoveItemsQuery,
    TMsgDlgType.mtConfirmation, [mbCancel, mbOk], 0) = mrOk then begin
      for I := ListView1.Items.Count - 1 downto 0 do
        if ListView1.Items[I].Selected then begin
          if List.Count <= MinItemCount then Break;
          ListView1.Items[I].Selected := False;
          List.Remove(TItem(ListView1.Items[I].Data));
        end;
      UpdateList;
      UpdateInterface;
    end;
  end;
end;

procedure TFormList.AModifyExecute(Sender: TObject);
var
  TempEntry: TItem;
  FormItem: TFormItem;
begin
  if Assigned(ListView1.Selected) then
  with TItem(ListView1.Selected.Data) do begin
    TempEntry := List.CreateItem;
    TempEntry.Assign(TItem(ListView1.Selected.Data));
    FormItem := TFormItem.Create(Self);
    try
      FormItem.Item := TempEntry;
      if FormItem.ShowModal = mrOk then begin
        TItem(ListView1.Selected.Data).Assign(TempEntry);
        UpdateList;
        UpdateInterface;
      end;
    finally
      FreeAndNil(FormItem);
      FreeAndNil(TempEntry);
    end;
  end;
end;

procedure TFormList.AAddExecute(Sender: TObject);
var
  TempEntry: TItem;
  FormItem: TFormItem;
begin
  if (MaxItemCount <> -1) and (List.Count >= MaxItemCount) then Exit;

  TempEntry := List.CreateItem;
  FormItem := TFormItem.Create(Self);
  try
    TempEntry.Name := List.GetNextAvailableName(SNew + ' ' + LowerCase(List.GetItemClass.GetClassName));
    FormItem.Item := TempEntry;
    if FormItem.ShowModal = mrOk then begin
      List.Add(TempEntry);
      TempEntry := nil;
      UpdateList;
      UpdateInterface;
    end;
  finally
    FreeAndNil(FormItem);
  end;
  TempEntry.Free;
end;

procedure TFormList.ACloneExecute(Sender: TObject);
var
  TempEntry: TItem;
  FormItem: TFormItem;
begin
  if (MaxItemCount <> -1) and (List.Count >= MaxItemCount) then Exit;

  TempEntry := List.CreateItem;
  TempEntry.Assign(TItem(ListView1.Selected.Data));
  FormItem := TFormItem.Create(Self);
  try
    TempEntry.Name := List.GetNextAvailableName(TempEntry.Name);
    FormItem.Item := TempEntry;
    if FormItem.ShowModal = mrOk then begin
      List.Add(TempEntry);
      TempEntry := nil;
      UpdateList;
      UpdateInterface;
    end;
  finally
    FreeAndNil(FormItem);
  end;
  TempEntry.Free;
end;

procedure TFormList.ASelectAllExecute(Sender: TObject);
var
  I: Integer;
begin
  for I := 0 to ListView1.Items.Count - 1 do
    ListView1.Items[I].Selected := True;
end;

procedure TFormList.FormClose(Sender: TObject;
  var CloseAction: TCloseAction);
begin
  Core.PersistentForm.Save(Self);
end;

procedure TFormList.FormCreate(Sender: TObject);
var
  I: Integer;
begin
  Core.CoolTranslator1.TranslateComponentRecursive(Self);
  Core.ThemeManager1.UseTheme(Self);
  for I := 0 to ToolBar1.ButtonCount - 1 do
    ToolBar1.Buttons[I].Hint := ToolBar1.Buttons[I].Caption;
  MinItemCount := 0;
  MaxItemCount := -1;
end;

procedure TFormList.FormShow(Sender: TObject);
begin
  Core.PersistentForm.Load(Self);
  UpdateListViewColumns;
  UpdateList;
  UpdateInterface;
end;

procedure TFormList.ListView1CustomDrawSubItem(Sender: TCustomListView;
  Item: TListItem; SubItem: Integer; State: TCustomDrawState;
  var DefaultDraw: Boolean);
var
  ItemFields: TItemFields;
  ItemField: TItemField;
begin
  ItemFields := TItem(Item.Data).GetFields;
  try
    ItemField := ItemFields[SubItem];
    if ItemField.DataType = dtColor then
    with ListView1.Canvas do begin
      Brush.Color := TItem(Item.Data).GetValueColor(ItemField.Index);
      Brush.Style := bsSolid;
      FillRect(Item.DisplayRectSubItem(SubItem, drBounds));
    end;
  finally
    ItemFields.Free;
  end;
end;

procedure TFormList.ListView1Data(Sender: TObject; Item: TListItem);
var
  I: Integer;
  Fields: TItemFields;
begin
  if Item.Index < ListView1.Items.Count then
  with TItem(List[Item.Index]) do begin
    //Item.Caption := GetName;
    Item.Data := List[Item.Index];
    Fields := List.GetItemClass.GetFields;
    try
      for I := 0 to Fields.Count - 1 do begin
        if I = 0 then Item.Caption := GetValueAsText(Fields[I].Index)
          else Item.SubItems.Add(GetValueAsText(Fields[I].Index));
      end;
    finally
      Fields.Free;
    end;
  end;
end;

procedure TFormList.ListView1KeyPress(Sender: TObject; var Key: char);
begin
  if Key = #13 then AModify.Execute;
  if Key = #27 then Close;
end;

procedure TFormList.ListView1KeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if Key = 45 then AAdd.Execute;
  if Key = 46 then ARemove.Execute;
end;

procedure TFormList.ListView1SelectItem(Sender: TObject;
  Item: TListItem; Selected: Boolean);
begin
  UpdateInterface;
end;

procedure TFormList.SetList(AValue: TItemList);
begin
  if FList = AValue then Exit;
  FList := AValue;
end;

procedure TFormList.UpdateListViewColumns;
var
  I: Integer;
  Fields: TItemFields;
begin
  Fields := List.GetItemClass.GetFields;
  ListView1.Columns.BeginUpdate;
  try
    while ListView1.Columns.Count < Fields.Count do
      ListView1.Columns.Add;
    while ListView1.Columns.Count > Fields.Count do
      ListView1.Columns.Delete(ListView1.Columns.Count - 1);
    for I := 0 to ListView1.Columns.Count - 1 do begin
      ListView1.Columns[I].Caption := Fields[I].Name;
      ListView1.Columns[I].Width := Scale96ToScreen(100);
    end;
  finally
    ListView1.Columns.EndUpdate;
  end;
  Fields.Free;
end;

procedure TFormList.UpdateInterface;
begin
  ARemove.Enabled := Assigned(FList) and Assigned(ListView1.Selected) and (List.Count > MinItemCount);
  AModify.Enabled := Assigned(FList) and Assigned(ListView1.Selected);
  AAdd.Enabled := Assigned(FList) and ((MaxItemCount = -1) or ((MaxItemCount <> -1) and (List.Count < MaxItemCount)));
  AClone.Enabled := Assigned(FList) and ((MaxItemCount = -1) or ((MaxItemCount <> -1) and (List.Count < MaxItemCount)));
  ASelectAll.Enabled := ListView1.Items.Count > 0;
end;

procedure TFormList.UpdateList;
begin
  if Assigned(List) then ListView1.Items.Count := List.Count
    else ListView1.Items.Count := 0;
  ListView1.Refresh;
end;

end.

