unit DDisplayQE;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

// ОПИСАНИЕ КЛАССА ДЛЯ ЭЛЕМЕНТА ОЧЕРЕДИ
type TQItem = class(TObject)
 private
   fPNext  : pointer;  // Указатель на следующий элемент
   fIData  : integer;  // Данные в элементе
   fRData  : double;   // Данные в элементе
   // МЕТОДЫ
   procedure SetPNext(RqPNext : pointer);
   procedure SetIData(RqIData  : integer);
   procedure SetRData(RqRData  : double);
 public
   // СВОЙСТВА
   property PNext : pointer read fPNext write SetPNext;
   property IData : integer read fIData write SetIData;
   property RData : double  read fRData write SetRData;
end;

// ОПИСАНИЕ КЛАССА ДЛЯ ОЧЕРЕДИ НА ОДНОСВЯЗНОМ СПИСКЕ
type TIQueue = class(TQItem)
 protected
   fMaxCount : integer;     // Максимальная длина очереди
   fPHead    : TQItem;      // Указагель элемента головы очереди
   fPTail    : TQItem;      // Указатель элемента хвоста очереди
   fICount   : integer;     // Счетчик элементов в очереди
   fPBuf     : TQItem;      // Буферный указатель элемента очереди
   fDisplay  : TComponent;  // Компонент для дисплея очереди
 private
   procedure SetMaxCount(aMaxCount : integer);
   procedure DeleteItemFromHead();
 protected
   property MaxCount : integer read fMaxCount write SetMaxCount;
 public
   constructor Create(RqDisplay : TComponent);
   procedure Free();
   // Полная очистка очереди
   procedure ClearQueue();
   // ДОБАВИТЬ НОВЫЙ ОБЪЕКТ В ХВОСТ ОЧЕРЕДИ
   procedure AddItemToTail(RqIData : integer; RqRData : double);
   procedure ShowItemQueue(); virtual; abstract;
end;

implementation

// -----------------------------------------------------------------------
// Реализация класса TQItem
// -----------------------------------------------------------------------
procedure TQItem.SetPNext(RqPNext : pointer);
begin fPNext := RqPNext; end;

procedure TQItem.SetIData(RqIData : integer);
begin fIData := RqIData; end;

procedure TQItem.SetRData(RqRData : double);
begin fRData := RqRData; end;

// -----------------------------------------------------------------------
//   Реализация класса TIQueue
// -----------------------------------------------------------------------
// Полная очистка очереди
procedure TIQueue.ClearQueue();
begin
  // Освободить все элементы очереди
  if (fICount > 0) and Assigned(fPHead) and Assigned(fPTail)
  then begin
     repeat
       fPBuf := fPHead;          // Выборка элемента в буфер
       fPHead := fPHead.PNext;   // Новый указатель головы
       fPBuf.Free;               // Освобождение элемента
     until not Assigned(fPHead);
     fICount := 0;               // Очистим счетчик объема очереди
     fPHead := nil;              // Очистим указатель головы очереди
     fPTail := nil;              // Очистим указатель хвоста очереди
  end;
end;

// Обслуживание свойства MaxCount
procedure TIQueue.SetMaxCount(aMaxCount : integer);
begin
  if aMaxCount < fICount
  then begin
     ClearQueue();              // Полная очистка очереди
     fMaxCount := aMaxCount;    // Установка нового предельной длины очереди
  end
  else fMaxCount := aMaxCount;  // Установка нового предельной длины очереди
  ShowItemQueue();              // Отображение очереди с новыми параметрами
end;

// КОНСТРУКТОР
constructor TIQueue.Create (RqDisplay : TComponent);
begin
   inherited Create;
   fMaxCount := 30;             // Максимальная длина очереди по умолчанию
   fDisplay := RqDisplay;       // Компонент для дисплея
end;

// ДЕСТРУКТОР
procedure TIQueue.Free();
begin
  ClearQueue();    // Полная очистка очереди
  inherited Free;  // Освободить объект очередь
end;

// УДАЛИТЬ ОБЪЕКТ ИЗ ГОЛОВЫ ОЧЕРЕДИ С ПОСЛЕДУЮЩЕЙ ЕГО ЛИКВИДАЦИЕЙ
procedure TIQueue.DeleteItemFromHead();
begin
 if (fICount > 0) and Assigned(fPHead)
 then begin
 // Для непустой очереди
   fPBuf  := fPHead;               // Сохраним указатель на элемент головы
   fPHead := fPBuf.PNext;          // Указатель головы на следующий элемент
   fPBuf.Free;                     // Освободим элемент
   fICount := fICount - 1;         // Уменьшим счетчик объема очереди
   if not Assigned(fPHead)
   then begin
      // Если новое состояние очереди пустое
      fICount := 0;               // Очистим счетчик объема очереди
      fPHead := nil;              // Очистим указатель головы очереди
      fPTail := nil;              // Очистим указатель хвоста очереди
   end;
 end;
end;

// ДОБАВИТЬ НОВЫЙ ОБЪЕКТ В ХВОСТ ОЧЕРЕДИ
procedure TIQueue.AddItemToTail(RqIData : integer; RqRData : double);
begin
   if Assigned(fPTail)             // Проверим указатель хвоста очереди
   then begin
      // Оченедь содержит элементы (добавим элемент в очередь)
      fPBuf  := fPTail;            // Старый указатель на хвостовой элемент
      fPTail := TQItem.Create;     // Создадим новый элемент очереди
      fPBuf.PNext := fPTail;       // Свяжем старый и новый элементы
      fICount := fICount + 1;      // Увеличим объем очереди
   end
   else begin
      // Очередь пустая (включем в нее первый элемент)
      fPTail := TQItem.Create;     // Создадим новый элемент очереди
      fPTail.PNext := nil;         // Очистим указатель свяи элементов
      fPHead  := fPTail;           // Установи новый указатель головы
      fICount := 1;                // Объем очереди равен единице
   end;
   fPTail.IData  := RqIData;       // Запишем в элемент данные
   fPTail.fRData := RqRData;
   // Если допустимый объем очереди превышен удалить один элемент из головы
   if (fICount > MaxCount)
   then DeleteItemFromHead();
end;


end.
