unit TriangF;
//*******************************************************
// Example program demonstrating triangular arrays.
//*******************************************************
// Copyright (C) 1998 John Wiley & Sons, Inc.
// All rights reserved. See additional copyright
// information in Readme.txt.
//*******************************************************

interface

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

type
  TTriangForm = class(TForm)
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    mnuExit: TMenuItem;
    Help1: TMenuItem;
    mnuAbout: TMenuItem;
    ArrayTypeGroup: TRadioGroup;
    procedure mnuAboutClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure mnuExitClick(Sender: TObject);
    procedure ArrayTypeGroupClick(Sender: TObject);
    procedure FormPaint(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  TriangForm: TTriangForm;

implementation

const
    NUM_ROWS = 8;
    MAX_ROW = NUM_ROWS - 1;
var
    the_array : TTriangularArray;

{$R *.DFM}

procedure TTriangForm.mnuAboutClick(Sender: TObject);
const
    CRCR = #13#10#13#10;
begin
    MessageDlg(
        'This program packs a triangular array into a one-dimensional array.' + CRCR +
        'Use the option buttons to determine whether the array should include diagonal entries.'
        , mtInformation, [mbOK], 0);
end;

procedure TTriangForm.FormCreate(Sender: TObject);
begin
    ArrayTypeGroup.ItemIndex := 0;
end;

procedure TTriangForm.mnuExitClick(Sender: TObject);
begin
     Close;
end;

procedure TTriangForm.ArrayTypeGroupClick(Sender: TObject);
var
    use_diagonals : Boolean;
    i, j          : Integer;
begin
    // Delete the old array if there is one.
    the_array.Free;

    // Create the array.
    use_diagonals := (ArrayTypeGroup.ItemIndex = 0);
    if (use_diagonals) then
        the_array := TTriangularArray.Create(NUM_ROWS, True)
    else
        the_array := TTriangularArray.Create(NUM_ROWS, False);

    // Set values in the array.
    for j := 0 to MAX_ROW do
    begin
        for i := j to MAX_ROW do
        begin
            if ((use_diagonals) or (i <> j)) then
                the_array.SetValue(i, j,
                    Format('A(%d, %d)', [i, j]));
        end;
    end;

    Refresh;
end;

// Draw the items in the array.
procedure TTriangForm.FormPaint(Sender: TObject);
var
    use_diagonals   : Boolean;
    i, j, x, y      : Integer;
    l, t, h, w      : Integer;
    value           : String;
    text_size       : TSize;
    grid_area       : TRect;
begin
    if (the_array = nil) then exit;

    // Get positioning information.
    t := 10;
    l := ArrayTypeGroup.Left + ArrayTypeGroup.Width + t;
    text_size := Canvas.TextExtent('A(9, 9)');
    w := Round(text_size.cx * 1.3);
    h := Round(text_size.cy * 1.3);

    // Erase the area behind the grid.
    grid_area.Left   := l;
    grid_area.Top    := t;
    grid_area.Right  := l + NUM_ROWS * w;
    grid_area.Bottom := t + NUM_ROWS * h;
    Canvas.FillRect(grid_area);

    // Draw the grid.
    for i := 0 to NUM_ROWS do
    begin
        Canvas.MoveTo(l + i * w, t);
        Canvas.LineTo(l + i * w, t + NUM_ROWS * h);
        Canvas.MoveTo(l, t + i * h);
        Canvas.LineTo(l + NUM_ROWS * w, t + i * h);
    end;

    // Draw the real values.
    use_diagonals := (ArrayTypeGroup.ItemIndex = 0);
    for j := 0 to MAX_ROW do
    begin
        for i := 0 to MAX_ROW do
        begin
            if ((not use_diagonals) and (i = j)) then
                value := '-'
            else if (i > j) then
                value := the_array.GetValue(i, j)
            else
                value := the_array.GetValue(j, i);
            // See how big the text is.
            text_size := Canvas.TextExtent(value);

            // Center the text in this position.
            if (i >= j) then
                Canvas.Font.Color := clBlack
            else
                Canvas.Font.Color := clGray;
            x := l + Round((j + 0.5) * w - text_size.cx / 2);
            y := t + Round((i + 0.5) * h - text_size.cy / 2);
            Canvas.TextOut(x, y, value);
        end;
    end;
end;

end.
