unit BPlusF;
//*******************************************************
// Example program demonstrating B+trees.
//*******************************************************
// 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,
  BPlusC, BPlusSF;

type
  TBPlusForm = class(TForm)
    GroupBox1: TGroupBox;
    Label1: TLabel;
    Label2: TLabel;
    SearchLastNameText: TEdit;
    SearchFirstNameText: TEdit;
    CmdSearch: TButton;
    GroupBox2: TGroupBox;
    Label3: TLabel;
    Label4: TLabel;
    RecFirstNameText: TEdit;
    RecLastNameText: TEdit;
    Label5: TLabel;
    Label6: TLabel;
    Label7: TLabel;
    Label8: TLabel;
    Label9: TLabel;
    Label10: TLabel;
    RecCityText: TEdit;
    RecAddressText: TEdit;
    RecZipText: TEdit;
    RecStateText: TEdit;
    RecPhoneText: TEdit;
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    mnuExit: TMenuItem;
    Help1: TMenuItem;
    mnuAbout: TMenuItem;
    CmdAdd: TButton;
    CmdRemove: TButton;
    RecNumLabel: TLabel;
    AccessesLabel: TLabel;
    Label11: TLabel;
    GroupBox3: TGroupBox;
    Label12: TLabel;
    Label13: TLabel;
    Label14: TLabel;
    HeightLabel: TLabel;
    RecordsLabel: TLabel;
    BucketsLabel: TLabel;
    Data1: TMenuItem;
    Display1: TMenuItem;
    mnuCreateData: TMenuItem;
    mnuInternalNodes: TMenuItem;
    mnuCompleteTree: TMenuItem;
    procedure mnuExitClick(Sender: TObject);
    procedure mnuAboutClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure OpenFiles;
    procedure ShowStats;
    procedure ShowCurrent;
    procedure CmdAddClick(Sender: TObject);
    procedure CmdSearchClick(Sender: TObject);
    procedure CmdRemoveClick(Sender: TObject);
    procedure mnuCreateDataClick(Sender: TObject);
    procedure mnuInternalNodesClick(Sender: TObject);
    procedure mnuCompleteTreeClick(Sender: TObject);
    procedure ShowStructure(show_leaves : Boolean);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  BPlusForm: TBPlusForm;

implementation

var
    tree : TBPlusTree;

{$R *.DFM}

procedure TBPlusForm.mnuExitClick(Sender: TObject);
begin
    Application.Terminate;
end;

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


    MessageDlg(
        'Niniejszy program ilustruje funkcjonowanie B+drzewa.' + break +
        'W celu dodania klienta wprowadź jego dane w środkowej części formularza' + CR +
        'i kliknij w przycisk "Dodaj"; wymagane jest podanie imienia i nazwiska.' + break +
        'W celu znalezienia klienta wprowadź jego nazwisko i imię w górnej części formularza i kliknij w przycisk "Szukaj".' + break +
        'Rekord właśnie dodany lub znaleziony jest rekordem bieżącym;' + CR +
        'kliknięcie w przycisk "Usuń" spowoduje jego usunięcie.'
        , mtInformation, [mbOK], 0);





end;

procedure TBPlusForm.FormCreate(Sender: TObject);
begin
    tree := TBPlusTree.Create;
    OpenFiles;
    ShowStats;
end;

// Make the B+tree open files Custs.dat and Custs.idx.
procedure TBPlusForm.OpenFiles;
var
    dir_name : String;
begin
    // Get the executable directory's name.
    dir_name := Application.ExeName;
    while (dir_name[Length(dir_name)] <> '\') do
        dir_name := Copy(dir_name, 0, Length(dir_name) - 1);

    // Get the data directory name.
    if (not InputQuery('Katalog', 'Katalog danych',
        dir_name)) then
    begin
        Application.Terminate;
        exit;
    end;

    // Make the tree open its data files.
    tree.OpenFiles(dir_name);
end;

// Show the B+tree's current statistics.
procedure TBPlusForm.ShowStats;
begin
    HeightLabel.Caption  := IntToStr(tree.Header.Height);
    RecordsLabel.Caption := IntToStr(tree.Header.NumRecords);
    BucketsLabel.Caption := IntToStr(tree.Header.NumBuckets);
    AccessesLabel.Caption := IntToStr(tree.DiskAccesses);
end;

// Show the B+tree's current record.
procedure TBPlusForm.ShowCurrent;
begin
    if (tree.CurrentIndex = NIL_RECORD) then
    begin
        // There is no current record.
        RecLastNameText.Text := '';
        RecFirstNameText.Text := '';
        RecAddressText.Text := '';
        RecCityText.Text := '';
        RecStateText.Text := '';
        RecZipText.Text := '';
        RecPhoneText.Text := '';
        RecNumLabel.Caption := '';
    end else begin
        with tree.CurrentRecord do
        begin
            RecLastNameText.Text := LastName;
            RecFirstNameText.Text := FirstName;
            RecAddressText.Text := Address;
            RecCityText.Text := City;
            RecStateText.Text := Voivodship;
            RecZipText.Text := Zip;
            RecPhoneText.Text := Phone;
            RecNumLabel.Caption := IntToStr(tree.CurrentIndex);
        end;
    end;
end;

// Add a new record to the tree.
procedure TBPlusForm.CmdAddClick(Sender: TObject);
begin
    // Make sure the first and last names are non-blank.
    if (RecLastNameText.Text = '') then
    begin
        ShowMessage('Wprowadź nazwisko.');
        RecLastNameText.SetFocus;
        exit;
    end;
    if (RecFirstNameText.Text = '') then
    begin
        ShowMessage('Wprowadź imię.');
        RecFirstNameText.SetFocus;
        exit;
    end;

    // Read the entered field values.
    with tree.CurrentRecord do
    begin
        LastName := RecLastNameText.Text;
        FirstName := RecFirstNameText.Text;
        Address := RecAddressText.Text;
        City := RecCityText.Text;
        Voivodship := RecStateText.Text;
        Zip := RecZipText.Text;
        Phone := RecPhoneText.Text;
    end;

    tree.Add; // Add the new customer record.

    ShowStats;
    RecNumLabel.Caption := IntToStr(tree.CurrentIndex);
    AccessesLabel.Caption := IntToStr(tree.DiskAccesses);
    ShowMessage('Rekord dodany.');
end;

// Find the indicated LastName,FirstName in the tree.
procedure TBPlusForm.CmdSearchClick(Sender: TObject);
var
    found_it : Boolean;
begin
    // Find the record.
    tree.FindRecord(
        SearchLastNameText.Text + ',' +
        SearchFirstNameText.Text,
        found_it);

    // Display the record.
    ShowCurrent;
    ShowStats;

    if (found_it) then
        CmdRemove.Enabled := True
    else begin
        CmdRemove.Enabled := False;
        ShowMessage('Nie znaleziono rekordu.');
    end;
end;

// Remove the current item from the B+tree.
procedure TBPlusForm.CmdRemoveClick(Sender: TObject);
begin
    // Make the user confirm the deletion.
    if (MessageDlg('Czy usunąć rekord ''' +
        tree.CurrentRecord.LastName + ',' +
        tree.CurrentRecord.FirstName + '''?',
        mtConfirmation, [mbYes, mbNo], 0) = mrNo) then
            exit;

    // Remove the record.
    tree.Remove;

    // Blank the record information display.
    ShowCurrent;
    ShowStats;
end;

// Allow the user to create a bunch of records.
procedure TBPlusForm.mnuCreateDataClick(Sender: TObject);
var
    num, first, i : Longint;
    numstr        : String;
begin
    // Ask the user how many items we should create.
    numstr := '1000';
    if (not InputQuery('Liczba rekordów',
        'Liczba tworzonych rekordów',
        numstr)) then
            exit;
    num := StrToInt(numstr);

    // Ask the user what item number to use first.
    numstr := IntToStr(tree.Header.NumRecords);
    if (not InputQuery('Pierwszy numer',
        'Numer pierwszego rekordu',
        numstr)) then
            exit;
    first := StrToInt(numstr);

    // Create the items.
    Screen.Cursor := crHourglass;

    with tree.CurrentRecord do
    begin
        Voivodship := '';
        Zip := '';
        Phone := '';
        for i := first to first + num do
        begin
            numstr := IntToStr(i);
            LastName := 'Last_' + numstr;
            FirstName := 'First_' + numstr;
            Address := 'Addr_' + numstr;
            City := 'City_' + numstr;
            tree.Add;
        end;
    end; // End with CurrentRecord...

    ShowStats;
    Screen.Cursor := crDefault;
end;

// Display the tree's internal structure.
procedure TBPlusForm.mnuInternalNodesClick(Sender: TObject);
begin
    ShowStructure(False);
end;

// Display the tree's complete structure.
procedure TBPlusForm.mnuCompleteTreeClick(Sender: TObject);
begin
    ShowStructure(True);
end;

// Display the tree's structure.
procedure TBPlusForm.ShowStructure(show_leaves : Boolean);
var
    frm : TStructForm;
begin
    frm := TStructForm.Create(Self);
    if (tree.Header.Height < 1) then
        frm.StructLabel.Caption := '<Puste drzewo>'
    else
        frm.StructLabel.Caption :=
            tree.TreeStructure('', 1, 0, show_leaves);
    frm.ShowModal;
    frm.Free;
end;

end.
