Solved

For Meikl

Posted on 2001-07-09
15
373 Views
Last Modified: 2010-04-06
Hi, Meikl.

You helped me last week with my question titled "Records" by providing me with a sample program.

I am thinking of adapting the program sample you gave so that i can add the parent nodes in myself when required instead of having them fixed inside the program.

I am hoping that you can help me by showing me how i can adapt the program so as to allow for this.

can you help?
0
Comment
Question by:mi6agent
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 7
15 Comments
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6264157
well, i would help you, but i don't know yet, what exactly you mean?

do you mean variable parents?

if so, then just add a secondary file with a structure like
ID : Integer;
Name : String[50];

which is read in the inittree-method?

well, could post this evening a sample,
if you mean this

meikl ;-)
0
 

Author Comment

by:mi6agent
ID: 6264179
Hi Meikl

What i am looking to do is to start with no parents in the treeview and be able to add/delete a parent node to the treeview when i want.  Then i will be able to add a record under the new parent.

I just can't work out a way to be able to do that and be able to save and reload it all back in when i restart the program.

Hope this explains it better for you

0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6264226
well,

sounds like
it could be done,
as i mentioned above

sample follows in ~9 hours

meikl ;-)
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:mi6agent
ID: 6264235
thanks Meikl - i shall wait till it suits you.  

speak to you later.
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6266498
sorry, got not the time today
(during week is too much todo)

if you are not in hurry, then i post it hopefully tomorrow
otherwise open another q for all

meikl ;-)
0
 

Author Comment

by:mi6agent
ID: 6267028
That's ok Meikl, i can wait.  I know you will help if you can so i shall wait for you.
0
 

Author Comment

by:mi6agent
ID: 6271000
thought i would increase the points for you since you are kind enough to help me on this one again.
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6271797
you do not need to raise the points for me,
have begun yesterday, but not ready yet

this evening it comes :-)

meikl ;-)
0
 

Author Comment

by:mi6agent
ID: 6271924
Thanks Meikl.  As for the points, your help is worth it.
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6273793
well, here it comes

well, its already a one file based app,
i've the typ-field in the record to string,
also the combobox is now at the style-property so adjusted,
that u can type in or select an entry->style csDropDown

the inittree method is canceled,
a new method findparent is introduced,
this method looks up, if a given typ alredady exists in the tree,
and returns the node if found.

the insertnode is changed,
it calls now the findparent-method,
if findparent nothing found,
a root node is ceated with given typ
and the comboboxlist is expanded with the new typ-entry.

so it should be now very dynamic,
the root entrys now depends on that what
you type in the combobox

empty rootnodes will disappear after next appstart

unit r_file_tree3_u;

interface

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

Type TheRec = Record  //a record
                LastName  : String[100];
                FirstName : String[100];
                //more attributes could stand here
                Typ      : String[100];
                Deleted  : Boolean;
              end;


type
  TForm1 = class(TForm)
    TreeView1: TTreeView;
    Panel1: TPanel;
    Edit1: TEdit;
    Edit2: TEdit;
    BInsert: TButton;
    BUpdate: TButton;
    BDelete: TButton;
    ComboBox1: TComboBox;
    procedure FormCreate(Sender: TObject);
    procedure BInsertClick(Sender: TObject);
    procedure BUpdateClick(Sender: TObject);
    procedure BDeleteClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure TreeView1Change(Sender: TObject; Node: TTreeNode);
    procedure FormDestroy(Sender: TObject);
  private
    NodeList : TList;      //Never used
    f : file of TheRec;    // file of this record
    rec : TheRec;   {Buffer} // a memorybuffer for this record
    Currentrecord : LongInt; {FileCursor}  //Points to the current record in the file
    RecordCount : LongInt; {RecordCount} //Holds the amount of records in the file
    Procedure PopulateEdits;
    Procedure PopulateRecord;
    Procedure CleanUpFile_at_Back;  //looks at the last record, if this is deleted, and deletes it
    Procedure CleanUpFile;          //Deletes all records, which are marked for deletion
    Procedure LoadTree;             //adds the level two nodes from files
    Procedure GetRecord(ARecNo : LongInt);  //gets a record
    Procedure UpdateRecord;         //Upsate a Record
    Procedure MarkToDeleteRecord;   //Marks a record for delete
    Procedure InsertNode(AName : String; AType : String; ARecNo : LongInt; DoSelect : Boolean);  //Inserts a Node into the tree
    Procedure AdJustControls(Switch : Boolean);  //Dis-/Enables Buttons
    Procedure InsertRecord;         //Insert a Record
    Function Findparent(AType : String) : TTreeNode;  //Find the Parent by Typ
  public
    { Public-Deklarationen }
  end;



var
  Form1: TForm1;


implementation

{$R *.DFM}

//open the file
procedure TForm1.FormCreate(Sender: TObject);
var I : Integer;
begin
  assignfile(f,'MyFile3.Dat');  //we will work with this file
  if not(fileexists('MyFile3.Dat')) then  //if this file not exists
    rewrite(f)  //create this file
  else
    reset(f);   //open this file
  CurrentRecord := 0;      //
  RecordCount := fileSize(f);
  LoadTree;
end;

Procedure TForm1.InsertRecord;
begin
  PopulateRecord;
  rec.Deleted := False;
  seek(f,RecordCount);  //goto last record
  write(f,rec);
  inc(RecordCount);
  CurrentRecord := RecordCount;
  InsertNode(rec.LastName,rec.typ,CurrentRecord,True);
end;

procedure TForm1.BInsertClick(Sender: TObject);
begin
  InsertRecord;
end;

procedure TForm1.BUpdateClick(Sender: TObject);
begin
  UpdateRecord;
end;

procedure TForm1.UpdateRecord;
var
  ParentSwap : Boolean;
begin
  if CurrentRecord > 0 then
  begin
    //must we Move the ChildeNode
    ParentSwap := rec.typ <> combobox1.Text;
    PopulateRecord;
    seek(f,CurrentRecord-1);
    write(f,rec);
    If ParentSwap then
    begin
      TreeView1.Selected.Delete;
      InsertNode(rec.LastName,rec.typ,CurrentRecord,True);
    end
    else
      TreeView1.Selected.Text := rec.LastName; //Update NodeText
  end;
end;

Procedure TForm1.MarkToDeleteRecord;
Begin
  rec.deleted := true;
  seek(f,CurrentRecord-1);
  write(f,rec);
  treeview1.selected.Delete;
End;


procedure TForm1.BDeleteClick(Sender: TObject);
begin
  MarkToDeleteRecord;
end;


procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  closefile(f);
end;

Procedure TForm1.AdJustControls(Switch : Boolean);
var I : integer;
begin
  BUpdate.Enabled := Switch;
  BDelete.Enabled := Switch;
  If Not(Switch) then
  begin
    combobox1.ItemIndex := -1;
    edit1.text := '';
    edit2.text := '';
  end;
end;

procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
begin

  If Node.Level > 0 then
  begin
    GetRecord(Integer(node.Data));
    PopulateEdits;
  End;
  AdjustControls(Node.Level > 0);
end;

Procedure TForm1.GetRecord(ARecNo : LongInt);
begin
  If (ARecNo > 0) and (ARecNo <= RecordCount) then
  begin
    try
      seek(f,ARecNo-1);
      read(f,rec);
      CurrentRecord := ARecNo;
    except
      raise;
    end;
  End
  else
    raise exception.create('GetRecord : Recno Out of Bounds');
end;

procedure TForm1.PopulateEdits;
begin
  edit1.text := rec.FirstName;
  edit2.text := rec.LastName;
  //maybe more attributes
  ComboBox1.Text := rec.typ;
end;

procedure TForm1.PopulateRecord;
Begin
  rec.FirstName := edit1.text;
  rec.LastName := edit2.text;
  if comboBox1.Text <> '' then
    rec.Typ := ComboBox1.Text
  else
    raise exception.create('Typ must be set!');
  //maybe more attributes
End;

Procedure TForm1.CleanUpFile_at_Back;
var
  endloop : Boolean;
begin
  if RecordCount > 0 then
  begin
    endloop := False;
    while (not endloop) and (RecordCount > 0) do
    begin
      getrecord(RecordCount);
      if rec.Deleted then
      begin
        seek(f,RecordCount-1);
        truncate(f);
        dec(RecordCount);
      end
      else endloop := true;
    end;
  end;
end;

Procedure TForm1.CleanUpFile;
var
  tmpCurrentRecord : Integer;
Begin
  If RecordCount > 0 then
  begin
    tmpCurrentRecord := 1;
    CleanUpFile_at_Back;  //be sure the last record isn't deleted
    while tmpCurrentRecord < RecordCount do
    begin
      GetRecord(tmpCurrentRecord);
      if rec.Deleted then
      begin
        GetRecord(RecordCount);  //swap records
        seek(f,tmpCurrentRecord-1);
        write(f,rec);
        seek(f,RecordCount-1);
        truncate(f);         //snip
        dec(RecordCount);
        CleanUpFile_at_Back; //be sure the new last record isn't deleted
      end;
      inc(tmpCurrentRecord);
    end;
  end;
  CloseFile(f);  //force physically write
  reset(f);
  CurrentRecord := 0;  //reinit
  If (filesize(f) = RecordCount) then
    RecordCount := FileSize(f)
  else
    raise exception.Create('CleanUp : Something goes wrong');
end;

Function TForm1.Findparent(AType : String) : TTreeNode;
begin
  Result := TreeView1.Items.GetFirstNode;
  While (Result <> NIL) and (Result.Text <> AType) do
    Result := Result.GetNextSibling;
end;


procedure TForm1.InsertNode(AName : String;
                            AType : String;
                            ARecNo : LongInt;
                            DoSelect : Boolean);
var
  ANode : TTreeNode;
  AIndex : Integer;
Begin
  //Search the parentnode
  ANode := FindParent(AType);
  If Anode = Nil then  //Not found
  begin
    Anode := TreeView1.Items.Add(NIL,AType); //Add RootEntry
    ComboBox1.Items.Add(AType);              //Expand Combo
  end;
  ANode := TreeView1.Items.AddChild(ANode,AName); //Create Node
  ANode.Data := Pointer(ARecNo);  //Store recordposition
  If DoSelect Then
  begin
    TreeView1.Selected := ANode;  //Select Node
    ANode.MakeVisible;
  end;
end;

procedure TForm1.LoadTree;
Begin
  CleanUpFile;   //Delete all marked physically
  CurrentRecord := 0;    //load From Beginning
  seek(f,CurrentRecord);
  While not eof(f) do
  begin
    Read(f,rec);
    inc(CurrentRecord);
    InsertNode(rec.LastName,rec.typ,CurrentRecord,False);
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  NodeList.Free; //free the list of RootNodes
end;

end.

hope this helps
ask if something unclear

meikl ;-)
0
 

Author Comment

by:mi6agent
ID: 6274903
Thanks Meikl, you did it again!  I wish i was as good as you at doing all of this.

One question though, what exactly is the purpose of "ParentSwap" i can't seem to figure out what it does.
0
 
LVL 27

Accepted Solution

by:
kretzschmar earned 250 total points
ID: 6275832
hi

well if you change the typ-field of a record, then the record-entry must change to another parentnode

for ex.
you have a record AName, which has the typ friend

friend
|-AName
|-AName2
workers
|-Aname3

you change the type to best friend and update the record,
the result will be then in the tree

friend
|-AName2
best friend
|-AName
workers
|-AName3

parentswap indicates, that the type has changed and introduce a node move to the other parent which matches the changed type via the insertnode-method

meikl ;-)
0
 

Author Comment

by:mi6agent
ID: 6275887
thanks meikl, i think i understand it a bit better now.

as i said, you are a genius and thank you very much for your help in all of this.

0
 

Author Comment

by:mi6agent
ID: 6275894
again, i give and excellent grade for an excellent answer and an excellent guy that took the time to help.

thanks.
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6276302
no no, i'm not a genius

well glad you like it
you a very generous with your points, thnaks :-)

good luck again

meikl ;-)
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
In this video, viewers will be given step by step instructions on adjusting mouse, pointer and cursor visibility in Microsoft Windows 10. The video seeks to educate those who are struggling with the new Windows 10 Graphical User Interface. Change Cu…
Monitoring a network: why having a policy is the best policy? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the enormous benefits of having a policy-based approach when monitoring medium and large networks. Software utilized in this v…

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question