Skip to content

TList. To improve array management

Well... we are on the final rush, so the project's code follows:

unit Unit1; 

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
  StdCtrls;

//Definition of Employee type (Record) : Here we define TEmployee type of a generic Employee
type
  pEmployee = ^TEmployee; //Define a poiner of TEmployee

  TEmployee = Record
    Id : integer;
    Name  : string;
    Surname  : string;
  end;
//End of employee type

type

  { TForm1 }

  TForm1 = class(TForm)
    ButtonAdd: TButton;
    ButtonModify: TButton;
    ButtonDelete: TButton;
    ButtonShow: TButton;
    EditNameNew: TEdit;
    EditSurnameNew: TEdit;
    EditIdModify: TEdit;
    EditNameModify: TEdit;
    EditSurnameModify: TEdit;
    EditIdDelete: TEdit;
    GroupBox1: TGroupBox;
    GroupBox2: TGroupBox;
    GroupBox3: TGroupBox;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    LabelNameDelete: TLabel;
    LabelSurnameDelete: TLabel;
    Memo: TMemo;

    procedure ButtonAddClick(Sender: TObject);
    procedure ButtonDeleteClick(Sender: TObject);
    procedure ButtonModifyClick(Sender: TObject);
    procedure ButtonShowClick(Sender: TObject);
    procedure EditIdDeleteChange(Sender: TObject);
    procedure EditIdModifyChange(Sender: TObject);
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure FormCreate(Sender: TObject);

  private
    { private declarations }
    EmployeeList  : TList; //list of pointers of employees (list of pEmployee)
    function findNumberOfEmployees(): integer;
    function findNextFreeId(): integer;
    procedure addEmployee(pEmp:pEmployee);
    procedure modifyEmployee(id:integer; pEmpnew:pEmployee);
    procedure deleteEmployee(id:integer);
    function getEmployee(id:integer): pEmployee; //get the pointer of an employee
    function printEmployeeWithId(id:integer): string;
    function printEmployeeWithIndex(index:integer): string;
  public
    { public declarations }
  end; 

var
  Form1: TForm1;

implementation

{ TForm1 }

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
////////////////////////PRIVATE FUNCTIONS////////////////////////////////////

function TForm1.findNumberOfEmployees(): integer;
begin
 result := EmployeeList.Count;
end;

function TForm1.findNextFreeId(): integer;
var imax :integer;
    pEmpTemp:pEmployee;
begin
  imax:=self.findNumberOfEmployees-1; //TList starts from a[0] etc...
  if imax <> -1 then begin
    pEmpTemp := self.EmployeeList[imax]; //Casting : pEmployee = generic pointer of a TList

    result :=pEmpTemp^.Id +1;
  end else result := 1;
end;

procedure TForm1.addEmployee(pEmp:pEmployee);
begin

  self.EmployeeList.Add(pEmp);

end;

procedure TForm1.modifyEmployee(id:integer; pEmpnew:pEmployee);
var i,imax :integer;
    pEmpTemp:pEmployee;
begin

  imax:=self.findNumberOfEmployees-1;//TList starts from a[0] etc...
  for i:=0 to imax do begin
    pEmpTemp := self.EmployeeList[i]; //Casting : pEmployee = generic pointer of a TList
    if pEmpTemp^.id = id then begin
      pEmpTemp^:=pEmpnew^; //copy by value !!
      break;
    end;
  end;

end;

procedure TForm1.deleteEmployee(id:integer);
var i,imax :integer;
    pEmpTemp:pEmployee;
begin

  imax:=self.findNumberOfEmployees-1;

  for i:=0 to imax do begin
    pEmpTemp:= self.EmployeeList[i];  //CASTING
    if pEmpTemp^.id = id then begin   //if pEmployee(self.EmployeeList[i])^.id = id then ....
      dispose(pEmpTemp); //FREE the created pointer which was related to list's item i
      self.EmployeeList.Delete(i); //delete the list's item i
      break;
    end;
  end;

end;

function TForm1.getEmployee(id:integer): pEmployee;
var i,imax :integer;
    pEmpTemp:pEmployee;
begin

  result:=nil;
  imax:=self.findNumberOfEmployees-1;
  for i:=0 to imax do begin
    pEmpTemp:=self.EmployeeList[i];
    if pEmpTemp^.id = id then begin
      result:= pEmpTemp;
      break;
    end;
  end;

end;

function TForm1.printEmployeeWithId(id:integer): string;
var i,imax :integer;
    pEmpTemp:pEmployee;
begin
  imax:=self.findNumberOfEmployees-1;
  for i:=0 to imax do begin
    pEmpTemp:=self.EmployeeList[i]; //Casting : pEmployee = generic pointer of a TList
    if pEmpTemp^.id = id then begin
      result:= 'Id : ' + inttostr(pEmpTemp^.Id)  + '; Name : ' + pEmpTemp^.Name  + '; Surname : ' + pEmpTemp^.Surname;
      break;
    end;
  end;

end;

function TForm1.printEmployeeWithIndex(index:integer): string;
var pEmpTemp:pEmployee;
begin
   pEmpTemp:=self.EmployeeList[index]; //Casting : pEmployee = generic pointer of a TList
   result:= 'Id : ' + inttostr(pEmpTemp^.Id)  + '; Name : ' + pEmpTemp^.Name  + '; Surname : ' + pEmpTemp^.Surname;
end;

//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
///////////////////////////EVENTS/////////////////////////////////////////////

//add employee event
procedure TForm1.ButtonAddClick(Sender: TObject);
var pEmpTemp : pEmployee;
begin

    //new : Create a new pointer type variable
    new(pEmpTemp); //SOS TRY DISABLING THIS STRING AND SEE WHAT HAPPENS ! (pEmpTemp^.Id := .. cannot be assigned i need to create the object)

   pEmpTemp^.Id := self.findNextFreeId;
   pEmpTemp^.Name := EditNameNew.Text;
   pEmpTemp^.Surname := EditSurnameNew.Text;

   self.addEmployee(pEmpTemp);

   showmessage('Employee with this info : ' + self.printEmployeeWithId(pEmpTemp^.Id) + ' added into TList.');

   //dispose(pEmpTemp); //FREE the created pointer  What happens if i enable this string here? when i call ButtonShowClick the TList has no values!!!

end;

//modify employe event
procedure TForm1.ButtonModifyClick(Sender: TObject);
var pEmpTemp: pEmployee;
begin
   //i do not create anything the pointer is created at the ADD section and i get it via getEmployee
   pEmpTemp:=self.getEmployee(strtoint(EditIdModify.Text));

   pEmpTemp^.Id := strtoint(EditIdModify.Text);
   pEmpTemp^.Name := EditNameModify.Text;
   pEmpTemp^.Surname := EditSurnameModify.Text;

   self.modifyEmployee(pEmpTemp^.Id,pEmpTemp);

   showmessage('Employee with this info : ' + self.printEmployeeWithId(pEmpTemp^.id) + ' modifided.');

end;

//delete employee event
procedure TForm1.ButtonDeleteClick(Sender: TObject);
begin
   self.deleteEmployee(strtoint(EditIdDelete.Text)) ;
   showmessage('Employee deleted');
end;

//Show all employees event
procedure TForm1.ButtonShowClick(Sender: TObject);
var i,imax:integer;
begin
  memo.Clear;
  imax:=self.findNumberOfEmployees-1;

  for i:=0 to imax do begin
    Memo.Lines.Add(self.printEmployeeWithIndex(i));
  end;

end;

//on modify change
procedure TForm1.EditIdModifyChange(Sender: TObject);
var pTempEmployee : pEmployee;
begin
    pTempEmployee := getEmployee(strtoint(EditIdModify.Text));
    if pTempEmployee <> nil then begin
      EditNameModify.text := pTempEmployee^.Name;
      EditSurnameModify.text := pTempEmployee^.Surname;
      ButtonModify.Enabled := true;
    end else begin
      EditNameModify.text := 'N/A';
      EditSurnameModify.text := 'N/A';
      ButtonModify.Enabled := false;
    end;
    pTempEmployee:=nil;
end;

//on delete change
procedure TForm1.EditIdDeleteChange(Sender: TObject);
var pTempEmployee : pEmployee;
begin
    pTempEmployee := getEmployee(strtoint(EditIdDelete.Text));
    if pTempEmployee <> nil then begin
      LabelNameDelete.Caption := pTempEmployee^.Name;
      LabelSurnameDelete.Caption := pTempEmployee^.Surname;
      ButtonDelete.Enabled := true;
    end else begin
      LabelNameDelete.Caption := 'N/A';
      LabelSurnameDelete.Caption := 'N/A';
      ButtonDelete.Enabled := false;
    end;
    pTempEmployee:=nil;
end;

//On create form
procedure TForm1.FormCreate(Sender: TObject);
begin
  EmployeeList := TList.Create; //Create the list !!!
end;

//On Exit form
procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
var i,imax:integer;
begin
  imax:=self.findNumberOfEmployees-1;

  //for i:=imax downto 0 do begin
  for i:=0 to imax do begin
      dispose( pEmployee(EmployeeList[i]) ); //delete both TEmployee record and pointer
      EmployeeList.Delete(i);    // delete list's item at index i
  end;

  EmployeeList.Free;  //Destroy the list !!!
end;

initialization
  {$I unit1.lrs}

end.

Have fun!
See you on next article!