unit Plotu;

interface
uses TVType, UlanType, MyLib, Classes, SysUtils, Graphics;

const
{plot commands:}
  pcMoveTo = 1;
  pcLineTo = 2;
  pcTextOut = 3;
  pcClearTextOut = 4;

type
  TPlotCommand = word;

{  PPlotRecord = ^TPlotRecord;}
  TPlotRecord = class(TObject)
    pc: TPlotCommand;
    X: TScreenX;
    Y: TScreenY;
    Info: pointer;{PString for pc = pcTextOut}
    constructor Create(APC: TPlotCommand; AX: TScreenX; AY: TScreenY; AInfo: pointer);
    destructor Destroy; override;
  end;

{  PPlotting = ^TPlotting;}
  TPlotting = class(TList){of Pplotcommandrecs}
    CurRec:integer;
    CurX:TScreenX;
    CurY:TScreenY;
    {FCharHeight:TScreenY;
    FCharWidth:TScreenX; }
    FCanvas: TCanvas;
    constructor Create(ACanvas: TCanvas; ALimit: integer);
      { ACanvas just for finding out TextWidth, TextHeight. No output
        is going to FCanvas using Move.., Line..., .. commands.
        Only by method CopyToCanvas. }
    function Reset: boolean;
    function Read(var APlotRecord: TPlotRecord): boolean;

    {adding records:}
    function ClearTextOut(AX: TScreenX; AY: TScreenY; AText: string): boolean;
    function MoveTo(AX: TScreenX; AY: TScreenY): boolean;
    function LineTo(AX: TScreenX; AY: TScreenY): boolean;
    function TextOut(AX: TScreenX; AY: TScreenY; AText: string): boolean;
    function GetX: TScreenX;
    function GetY: TScreenY;
    function TextWidth(AText: string): TScreenX;
    function TextHeight(AText: string): TScreenY;
    function Line(X1: TScreenX; Y1: TScreenY; X2: TScreenX; Y2: TScreenY): boolean;
    function SetLineStyle(a, b, c: integer): boolean;
      {?see dos graph}
    function Rectangle(X1: TScreenX; Y1: TScreenY; X2: TScreenX; Y2: TScreenY): boolean;
    procedure Clear; override;{tlist reset, then free all}
    {procedure SetCharHeight(AHeight: TScreenY);
    procedure SetCharWidth(AWidth: TScreenX);}
    property Canvas: TCanvas read FCanvas write FCanvas;
  end;

implementation

constructor TPlotRecord.Create(APC:TPlotCommand; AX:TScreenX; AY:TScreenY; AInfo:pointer);
begin
  inherited Create;
  pc := APC;
  X := AX;
  Y := AY;
  Info := AInfo;
end;

destructor TPlotRecord.Destroy;
begin
  if (pc in [pcTextOut, pcClearTextOut]) then
   {mylib}FreePString(@PString(Info));
  inherited Destroy;
end;


constructor TPlotting.Create(ACanvas: TCanvas; ALimit:integer);
begin
  inherited Create;
  Capacity := ALimit;
  CurRec := 0;
  CurX := 0;
  CurY := 0;
  FCanvas := ACanvas;
{  FCharHeight := 12;
  FCharWidth := 8;}
end;

function TPlotting.Reset:boolean;
begin
  Reset := false;
  CurRec := 0;
  if Count = 0 then
    exit;
  Reset := true;
end;

function TPlotting.Read(var APlotRecord:TPlotRecord):boolean;
begin
  Read := false;
  if CurRec >= Count then
    exit;
  APlotRecord := Items[CurRec];
  case APlotRecord.pc of
    pcLineTo, pcMoveTo: begin
      CurX := APlotRecord.X;
      CurY := APlotRecord.Y;
    end;
  end;
  inc(CurRec);
  Read := true;
end;

function TPlotting.ClearTextOut(AX:TScreenX; AY:TScreenY ;AText:string):boolean;
begin
  ClearTextOut := TextOut(AX, AY, AText);
end;

function TPlotting.MoveTo(AX:TScreenX;AY:TScreenY):boolean;
begin
  MoveTo := true;
  Add(TPlotRecord.Create(pcMoveTo, AX, AY, nil));
  CurX := AX;
  CurY := AY;
end;

function TPlotting.LineTo(AX:TScreenX;AY:TScreenY):boolean;
begin
  LineTo := true;
  Add(TPlotRecord.Create(pcLineTo, AX, AY, nil));
  CurX := AX;
  CurY := AY;
end;

function TPlotting.TextOut(AX:TScreenX; AY:TScreenY; AText:string):boolean;

begin
  TextOut := true;
  Add(TPlotRecord.Create(pcTextOut, AX, AY, NewStr(AText)));
  {CurX := AX;
  CurY := AY;}
end;

function TPlotting.GetX:TScreenX;
begin
  GetX := CurX;
end;

function TPlotting.GetY:TScreenY;
begin
  GetY := CurY;
end;

function TPlotting.TextWidth(AText:String):TScreenX;
begin
  TextWidth := FCanvas.TextWidth(AText);{length(AText) * FCharWidth;}
end;

function TPlotting.TextHeight(AText:string):TScreenY;
begin
  TextHeight := FCanvas.TextHeight(AText);{FCharHeight;}
end;

function TPlotting.Line(X1:TScreenX; Y1:TScreenY; X2:TScreenX; Y2:TScreenY):boolean;
begin
  Line := false;
  if not MoveTo(X1, Y1) then
    exit;
  if not LineTo(X2, Y2) then
    exit;
  Line := true;
end;

function TPlotting.Rectangle(X1:TScreenX; Y1:TScreenY; X2:TScreenX; Y2:TScreenY):boolean;
begin
  Rectangle := false;
  if not MoveTo(X1, Y1) then
    exit;
  if not LineTo(X1, Y2) then
    exit;
  if not LineTo(X2, Y2) then
    exit;
  if not LineTo(X2, Y1) then
    exit;
  if not LineTo(X1, Y1) then
    exit;
  Rectangle := true;
end;

function TPlotting.SetLineStyle(a,b,c:integer):boolean;{?see dos graph}
begin
  SetLineStyle := false;
end;

procedure TPlotting.Clear;{free all}
var i:integer;
begin
  Reset;
  if Count > 0 then begin
    for i := 0 to Count - 1 do
      TObject(Items[i]).Free;
  end;
  inherited Clear;
{  FreeAll;}
end;

{procedure TPlotting.SetCharHeight(AHeight:TScreenY);
begin
  FCharHeight := AHeight;
end;

procedure TPlotting.SetCharWidth(AWidth:TScreenX);
begin
  FCharWidth := AWidth;
end;
 }
end.
