////////////////////////////////////////////////////////////////////////////////
//
// Name: DynCol.pas
// Creator: C. Aaangel
// Description: This unit will add an easy to use dynamic column wrapper into
//              a Tlistview. System is embedded in TlplListView.
// Version: 1.0
//
// Copyright (C) 2005 - C. Aaangel
////////////////////////////////////////////////////////////////////////////////
unit DynCol;

interface

Uses Classes, ComCtrls, SysUtils;

Type
 TColumnInfo = Record
  Name: String;
  ScreenName: String;
  Description: String;
  Width: Integer;
  Alignment: TAlignment;
  Position: ShortInt;
 end;
 TColumnInfoList = Class(TObject)
 private
  fList: Array of TColumnInfo;
  function GET_COUNT: Integer;
  function GetColumnInfo(Index: Integer): TColumnInfo;
  procedure SetColumnInfo(Index: Integer; const Value: TColumnInfo);
 public
  Function Add(Name: String; ScreenName: String; Description: String; Width: Integer; Alignment: TAlignment; Position: ShortInt = -1): Integer;
  Procedure Delete(Index: Integer);
  Property Count: Integer read GET_COUNT;
  Property ColumnInfo[Index: Integer]: TColumnInfo read GetColumnInfo write SetColumnInfo; default;
  Procedure BuildColumns(IntoListview: TListview);
  procedure AddToList(IntoListView: TListView; ItemIndex: Integer; AtColumn: String; Str: String); overload;
  procedure AddToList(IntoListView: TListView; ItemName: String; AtColumn: String; Str: String); overload;
 end;

implementation

{ TColumnInfoList }

function TColumnInfoList.Add(Name: String; ScreenName: String; Description: String; Width: Integer; Alignment: TAlignment; Position: ShortInt = -1): Integer;
begin
 SetLength(fList, length(fList) + 1);
 Result := Length(fList)-1;
 fList[Result].Name := Name;
 fList[Result].ScreenName := ScreenName;
 fList[Result].Description := Description;
 fList[Result].Width := Width;
 fList[Result].Alignment := Alignment;
 fList[Result].Position := Position;
end;

procedure TColumnInfoList.Delete(Index: Integer);
Var
 I: Integer;
begin
 For I := Index to count - 2 do begin
  fList[I] := fList[I+1];
 end;
 SetLength(fList, length(fList) - 1);
end;

function TColumnInfoList.GET_COUNT: Integer;
begin
 Result := Length(fList);
end;

function TColumnInfoList.GetColumnInfo(Index: Integer): TColumnInfo;
begin
 Result := fList[Index];
end;

procedure TColumnInfoList.SetColumnInfo(Index: Integer;
  const Value: TColumnInfo);
begin
 fList[Index] := Value;
end;

procedure TColumnInfoList.BuildColumns(IntoListview: TListview);
Var
 Cnt, C, I: Integer;
begin
 // First figure out how many columns is showing
 Cnt := 0;
 For I := 0 to count - 1 do begin
  If fList[I].Position > -1 then Inc(Cnt);
 End;

 // Adjust the columns count to the required number
 // Clear followed by Add could also be used but this approach is faster
 If cnt > IntoListView.Columns.Count then begin
  For I := IntoListView.Columns.Count to cnt-1 do begin
   IntoListView.Columns.Add;
  end;
 end;
 If cnt < IntoListView.Columns.Count then begin
  For I := cnt downto IntoListView.Columns.Count-1 do begin
   IntoListView.Columns.Delete(IntoListView.Columns.Count - 1);
  end;
 end;
 For C := 0 to Count - 1 do begin
  For I := 0 to count - 1 do begin
   If fList[I].Position = C then begin
    With IntoListView.Columns[C] do begin
     Caption := fList[I].ScreenName;
     Alignment := fList[I].Alignment;
     Width := fList[I].Width;
    end;
   end;
  end;
 end;
end;

procedure TColumnInfoList.AddToList(IntoListView: TListView; ItemIndex: Integer; AtColumn: String; Str: String);
Var
 I: Integer;
 ColumnIndex: ShortInt;
begin
 ColumnIndex := -1;
 For I := 0 to count - 1 do begin
  If uppercase(fList[I].Name) = (uppercase(AtColumn)) Then begin
   ColumnIndex := fList[I].Position;
  end;
 end;
 If ColumnIndex = -1 then exit;
 If ColumnIndex = 0 then begin
  IntoListView.Items[ItemIndex].Caption := Str;
 end
  else
 begin
  Dec(ColumnIndex);
  IntoListView.Items[ItemIndex].SubItems[ColumnIndex] := Str;
 end;
end;

procedure TColumnInfoList.AddToList(IntoListView: TListView; ItemName,
  AtColumn, Str: String);
Var
 I: Integer;
begin
 For I := 0 to IntoListView.Items.Count - 1 do begin
  If uppercase(ItemName) = Uppercase(Intolistview.Items[I].Caption) then begin
   AddToList(IntoListView, I, AtColumn, Str);
   break;
  end;
 end;
end;

end.
