unit NAryF;
//*******************************************************
// Example program demonstrating N-ary trees.
//*******************************************************
// Copyright (C) 1998 John Wiley & Sons, Inc.
// All rights reserved. See additional copyright
// information in Readme.txt.
//
// Revised (C) 1999 Andrzej Grażyński, HELION Publ.
//
//*******************************************************

interface

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

type
  TNAryForm = class(TForm)
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    mnuExit: TMenuItem;
    Help1: TMenuItem;
    mnuAbout: TMenuItem;
    CmdAdd: TButton;
    CmdRemove: TButton;
    procedure mnuExitClick(Sender: TObject);
    procedure mnuAboutClick(Sender: TObject);
    procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormCreate(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure SetButtons;
    procedure SelectNode(new_selection : TNAryNode);
    procedure CmdAddClick(Sender: TObject);
    procedure CmdRemoveClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  NAryForm: TNAryForm;

implementation

var
    root, selected  : TNAryNode;
    x0, y0, node_id : Integer;

{$R *.DFM}

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

procedure TNAryForm.mnuAboutClick(Sender: TObject);
const
    CRCR = #13#10#13#10;
    CR = #13#10;
begin

    MessageDlg(
        'Niniejszy program ilustruje manipulowanie węzłami drzewa dowolnego stopnia.' + CRCR +
        'Kliknij w dowolny węzeł, a następnie w przycisk "Dodaj potomka"' + CR +
        ' - spowoduje to dodanie węzła potomnego do wyróżnionego węzła.' + CRCR +
        'Kliknięcie w przycisk "Usuń poddrzewo" spowoduje usunięcie wyróżnionego węzła' + CR +
        'i wszystkich jego potomków.'
        , mtInformation, [mbOK], 0);

end;

procedure TNAryForm.FormMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
    // Select the node at the given point.
    SelectNode(
        root.NodeAtPoint(X, Y));
end;

// Create the root node.
procedure TNAryForm.FormCreate(Sender: TObject);
var
    xmin : Integer;
begin
    // Create a one node tree.
    root := TNAryNode.Create;
    root.Id := 'Root';
    node_id := 0;

    // Save the coordinates where we will start drawing.
    x0 := 3;
    y0 := CmdAdd.Top + CmdAdd.Height + 3;

    // Use bold text.
    Canvas.Font.Style := [fsBold];

    // Position the initial one node tree.
    xmin := x0;
    root.SetPosition(xmin, y0);
end;

// Draw the tree.
procedure TNAryForm.FormPaint(Sender: TObject);
var
    rect : TRect;
begin
    // Erase the canvas.
    rect.Left := 0;
    rect.Right := Width;
    rect.Top := 0;
    rect.Bottom := Height;
    Canvas.Brush.Color := clLtGray;
    Canvas.FillRect(rect);

    // Draw the tree.
    root.DrawSubtree(Canvas, selected);
end;

// Enable the correct buttons for the selected node.
procedure TNAryForm.SetButtons;
begin
    if (selected = nil) then
    begin
        CmdAdd.Enabled    := False;
        CmdRemove.Enabled := False;
    end else begin
        CmdAdd.Enabled    := True;
        CmdRemove.Enabled := (selected <> root);
    end;
end;

procedure TNAryForm.SelectNode(new_selection : TNAryNode);
begin
    // Unselect the previously selected node.
    if (selected <> nil) then
        selected.DrawNode(Canvas, nil);

    // Select the new node.
    selected := new_selection;
    // Highlight the selected node.
    if (selected <> nil) then
        selected.DrawNode(Canvas, selected);
    SetButtons;
end;

// Add a left child to the selected node.
procedure TNAryForm.CmdAddClick(Sender: TObject);
var
    xmin : Integer;
begin
    node_id := node_id + 1;
    selected.AddChild(selected, IntToStr(node_id));

    // Reposition the nodes.
    xmin := x0;
    root.SetPosition(xmin, y0);

    // Enable the correct buttons.
    SetButtons;

    Refresh;
end;

// Remove the selected node and its descendants.
procedure TNAryForm.CmdRemoveClick(Sender: TObject);
var
    xmin   : Integer;
    target : TNAryNode;
begin
    // Unselect the node.
    target := selected;
    SelectNode(nil);

    // Remove the selected node from the tree.
    target.ParentNode.RemoveChild(target);

    // Reposition the remaining nodes.
    xmin := x0;
    root.SetPosition(xmin, y0);

    Refresh;
end;

end.
