La fiche principale, le code associé dans la unit.
Etape de construction
n°2 ( la classe).
Etape de
construction
n°3 (le composant).
Exécuter le programme
Classe mère dont on dérive :
Le composant visuel ToutLine déposé:
La fiche principale du projet :
Le code de la Unit fiche principale :
unit Ucompo00;
{Etape 0 : programme Delphi classique}
interface // voir la classe dans l'étape suivante plus bas.
uses
SysUtils, Messages, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, ExtCtrls, Grids, Outline;
type
TForm1 = class(TForm)
Outline1: TOutline;
RadioGrouplevel: TRadioGroup;
procedure RadioGrouplevelClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Déclarations private }
public
{ Déclarations public }
end;
var
Form1: TForm1;
app_path:string;
implementation
{$R *.DFM}
{------------ procédures d'actions
nouvelles sur le Toutline -----------}
procedure affiche_racine(tree:TOutline);
{remonte à la racine d'où que l'on soit}
var num_lev:integer;
begin
if tree.Itemcount<>0 then
// voir la classe dans
l'étape suivante plus bas.
begin
num_lev:=tree.items[tree.selecteditem].topItem;
tree.SelectedItem:=tree.items[num_lev].parent.index;
tree.items[1].expanded:=false;
end
end;
procedure lire_un_niveau(rac:Toutline;indice:integer;niveau:integer);
{descente recursive en préordre sur
un outline}
var node:ToutlineNode; {pour simplifier les manipulations}
indice_node_fils,indice_node_pere:integer;
begin
if (indice<>-1)and(rac.ItemCount<>0) then
begin
node:=rac.items[indice];
indice_node_pere:=rac.items[indice].parent.index;
indice_node_fils:=indice;
if node.HasItems then {il
y a des descendants}
begin
if node.level<=niveau then {uniquement
si le niveau est correct}
begin
node.expand;
{visualiser les descendants à level+1}
indice_node_pere:= rac.SelectedItem; {le
noeud est le père}
rac.SelectedItem:=rac.Items[rac.SelectedItem].GetFirstChild;
{le
1er à gauche}
indice_node_fils:=rac.SelectedItem; {indice
du noeud fils gauche}
if indice_node_fils<>-1 then
begin
lire_un_niveau(rac,indice_node_fils,niveau);
indice:=rac.Items[indice_node_pere].GetNextChild(indice_node_fils);{indice
du frère suivant}
end;
while indice<>-1 do {examen
de tous les frères de indice_node_fils}
begin
rac.SelectedItem:=indice;
{le frère suivant}
indice_node_fils:=rac.SelectedItem; {le
frère suivant est le nouveau fils}
lire_un_niveau(rac,indice_node_fils,niveau);
indice:=rac.Items[indice_node_pere].GetNextChild(indice_node_fils);
{indice
du frère suivant}
end
end
end
end
end;
procedure affiche_un_niveau(le_niveau:integer);
{pour visualiser tout le niveau choisi par
l'utilisateur}
var
indice_noeud:integer;
begin
affiche_racine(form1.Outline1);
if le_niveau<>0 then
begin
indice_noeud:= form1.Outline1.selecteditem;
lire_un_niveau(form1.Outline1,indice_noeud,le_niveau);
if form1.Outline1.Itemcount<>0 then
begin
indice_noeud:=form1.Outline1.Items[1].GetNextChild(indice_noeud);
while indice_noeud<>-1 do
begin
form1.Outline1.selecteditem:=indice_noeud;
lire_un_niveau(form1.Outline1,indice_noeud,le_niveau);
indice_noeud:=form1.Outline1.Items[1].GetNextChild(indice_noeud);
end
end
end
end;
{------------------------------------------------------------------------}
{////////////////////// Gestionnaires d'événements
//////////////////////}
procedure TForm1.RadioGrouplevelClick(Sender: TObject);
var
level_click:integer;
begin
level_click:=RadioGrouplevel.Itemindex;
Form1.caption:=' Structure abstraite générale -
Profondeur choisie : '+inttostr(level_click);
affiche_un_niveau(level_click); {appel
de la procédure d'action}
end;
procedure TForm1.FormCreate(Sender:
TObject);
begin //
voir la classe dans
l'étape suivante plus bas.
app_path:=ExtractFilePath(Application.ExeName);
Outline1.lines.LoadFromfile(app_path+'lines.txt'); {arbre
chargé}
end;
end.
Remonter
Création d'une classe à partir de l'étape précédente n°0, avec un programme d'utilisation d'une instance de cette classe afin de la tester.
unit Ucompo01;
{Etape 1 : programme Delphi avec une classe}
interface
uses
SysUtils, Messages, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, ExtCtrls, Grids, Outline;
type
TTree1 = class(TOutline)
{la nouvelle classe TTree1 dérivée de Toutline}
private
Fniveau:integer;
function Getmaxniveau:integer;
{méthode interne}
procedure affiche_un_niveau(le_niveau:integer);
{méthode
interne}
public
{ Déclarations public }
property profondeur:integer
readGetmaxniveau;
property show_niveau:integer
read
Fniveau write affiche_un_niveau;
end;
TForm1 = class(TForm)
RadioGrouplevel: TRadioGroup;
procedure FormCreate(Sender: TObject);
procedure RadioGrouplevelClick(Sender: TObject);
private
{ Déclarations private }
public
{ Déclarations public }
end;
var
Form1: TForm1;
app_path:string;
new_compos:TTree1; {objet TTree1 instancié}
{$R *.DFM}
{------------ procédures d'actions
sur le TTree1 -----------}
procedure affiche_racine(tree:TTree1);
{remonte à la racine d'où que
l'on soit.
Code identique à l'étape
0 }
var num_lev:integer;
begin
if tree.Itemcount<>0 then
begin
num_lev:=tree.items[tree.selecteditem].topItem;
tree.SelectedItem:=tree.items[num_lev].parent.index;
tree.items[1].expanded:=false;
end
end;
procedure lire_un_niveau(rac:TTree1;indice:integer;niveau:integer);
{descente recursive en préordre sur
un outline.
Code identique à l'étape
0 }
var
node:ToutlineNode; {pour
simplifier les manipulations}
indice_node_fils,indice_node_pere:integer;
begin
if (indice<>-1)and(rac.Itemcount<>0) then
begin
node:=rac.items[indice];
indice_node_pere:=rac.items[indice].parent.index;
indice_node_fils:=indice;
if node.HasItems then {il
y a des descendants}
begin
if node.level<=niveau then {uniquement
si le niveau est correct}
begin
node.expand;
{visualiser les descendants à level+1}
indice_node_pere:= rac.SelectedItem; {le
noeud est le père}
rac.SelectedItem:=rac.Items[rac.SelectedItem].GetFirstChild;
{le
1er à gauche}
indice_node_fils:=rac.SelectedItem; {indice
du noeud fils gauche}
if indice_node_fils<>-1 then
begin
lire_un_niveau(rac,indice_node_fils,niveau);
indice:=rac.Items[indice_node_pere].GetNextChild(indice_node_fils);{indice
du frère suivant}
end;
while indice<>-1 do {examen
de tous les frères de indice_node_fils}
begin
rac.SelectedItem:=indice;
{le frère suivant}
indice_node_fils:=rac.SelectedItem; {le
frère suivant est le nouveau fils}
lire_un_niveau(rac,indice_node_fils,niveau);
indice:=rac.Items[indice_node_pere].GetNextChild(indice_node_fils);
{indice
du frère suivant}
end
end
end
end
end;
{----------------
Méthodes internes de la classe TTree1 -----------------}
procedure TTree1.affiche_un_niveau(le_niveau:integer);
{pour visualiser tout le niveau choisi par
l'utilisateur.
On reprende le code de l'étape
1 de l'exemple "Methode.Tree",
le form1.outline1 est remplacé par
"self"}
var
indice_noeud:integer;
begin
affiche_racine(self);
if le_niveau<>0 then
begin
indice_noeud:= self.selecteditem;
lire_un_niveau(self,indice_noeud,le_niveau);
if self.Itemcount<>0 then
begin
indice_noeud:=self.Items[1].GetNextChild(indice_noeud);
while indice_noeud<>-1 do
begin
self.selecteditem:=indice_noeud;
lire_un_niveau(self,indice_noeud,le_niveau);
indice_noeud:=self.Items[1].GetNextChild(indice_noeud);
end
end
end
end;
function TTree1.Getmaxniveau:integer;
{donne la profondeur maximum de l'arbre
profondeur racine=0}
var i,max:integer;
begin
if self.Itemcount<>0 then
begin
max:=1;
for i:=1 to self.Itemcount do
if max<self.Items[i].level then
max:=self.Items[i].level;
Getmaxniveau:=max-1;
end
else Getmaxniveau:=0
end;
{------------------------------------------------------------------------}
{/////////////////// Gestionnaires d'événements
//////////////////////}
procedure TForm1.FormCreate(Sender:
TObject);
{Les différences avec l'étape
0 portent essentiellement
sur l'instanciation d'un objet de la classe
TTree1 et
son positionnement sur la fiche.}
begin
app_path:=ExtractFilePath(Application.ExeName);
new_compos:=TTree1.create(self);
{objet TTree1 créé}
new_compos.parent:=self;
{objet TTree1 affichable}
new_compos.setbounds(8,8,233,233); {position
: left,top,width,height}
new_compos.lines.loadfromfile(app_path+'lines.txt'); {arbre
chargé}
RadioGrouplevel.caption:='Prof.= '+Inttostr(new_compos.profondeur)
end;
procedure TForm1.RadioGrouplevelClick(Sender:
TObject);
{tester et visualiser tout le niveau choisi
par l'utilisateur}
var
level_click:integer;
begin
level_click:=RadioGrouplevel.Itemindex;
Form1.caption:=' Structure abstraite générale -
Profondeur choisie : '+inttostr(level_click);
new_compos.show_niveau:=level_click; {modification
de propriété de l'objet}
end;
La classe TTree1 dérive
du Toutline et contient deux propriétés
nouvelles profondeur et show_niveau.
La unit contenant le composant :
unit Utree1;
{Etape 2 : un composant à partir de la classe}
interface
uses
SysUtils, Messages, Classes, Graphics, Controls,
Forms, StdCtrls, ExtCtrls, Outline;
type
TTree1 = class(TOutline) {la
nouvelle classe TTree1 dérivée de Toutline}
private
Fniveau:integer;
function Getmaxniveau:integer;
{méthode interne}
procedure affiche_un_niveau(le_niveau:integer);
{méthode
interne}
public
constructor
Create(Aowner:Tcomponent);override;
property profondeur:integer
readGetmaxniveau;
property show_niveau:integer read
Fniveau write affiche_un_niveau;
end;
implementation
procedure register;
begin
RegisterComponents('Perso',[TTree1])
end;
{//////////////////////////////////////////////////////////////////////////////////////////////////////////////////}
{--------------------- procédures internes
au TTree1 ------------------------}
procedure affiche_racine(tree:TTree1);
{remonte à la racine d'où que
l'on soit
Code identique à l'étape 1}
var num_lev:integer;
begin
if tree.Itemcount<>0 then
begin
num_lev:=tree.items[tree.selecteditem].topItem;
tree.SelectedItem:=tree.items[num_lev].parent.index;
tree.items[1].expanded:=false;
end
end;
procedure lire_un_niveau(rac:TTree1;indice:integer;le_niveau:integer);
{descente recursive en préordre sur
un outline
Code identique à l'étape 1}
var
node:ToutlineNode; {pour
simplifier les manipulations}
indice_node_fils,indice_node_pere:integer;
begin
if (indice<>-1)and(rac.Itemcount<>0) then
begin
node:=rac.items[indice];
indice_node_pere:=rac.items[indice].parent.index;
indice_node_fils:=indice;
if node.HasItems then {il
y a des descendants}
begin
if node.level<=le_niveau then {uniquement
si le niveau est correct}
begin
node.expand;
{visualiser les descendants à level+1}
indice_node_pere:= rac.SelectedItem; {le
noeud est le père}
rac.SelectedItem:=rac.Items[rac.SelectedItem].GetFirstChild;
{le
1er à gauche}
indice_node_fils:=rac.SelectedItem; {indice
du noeud fils gauche}
if indice_node_fils<>-1 then
begin
lire_un_niveau(rac,indice_node_fils,le_niveau);
indice:=rac.Items[indice_node_pere].GetNextChild(indice_node_fils);{indice
du frère suivant}
end;
while indice<>-1 do {examen
de tous les frères de indice_node_fils}
begin
rac.SelectedItem:=indice;
{le frère suivant}
indice_node_fils:=rac.SelectedItem; {le
frère suivant est le nouveau fils}
lire_un_niveau(rac,indice_node_fils,le_niveau);
indice:=rac.Items[indice_node_pere].GetNextChild(indice_node_fils);
{indice
du frère suivant}
end
end
end
end;
end;
{////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////}
{-------------------- Méthodes
internes de la classe TTree1 ---------------------}
procedure TTree1.affiche_un_niveau(le_niveau:integer);
{pour visualiser tout le niveau choisi par
l'utilisateur}
var
indice_noeud:integer;
begin
affiche_racine(self);
if le_niveau<>0 then
begin
indice_noeud:= self.selecteditem;
lire_un_niveau(self,indice_noeud,le_niveau);
if self.Itemcount<>0 then
begin
indice_noeud:=self.Items[1].GetNextChild(indice_noeud);
while indice_noeud<>-1 do
begin
self.selecteditem:=indice_noeud;
lire_un_niveau(self,indice_noeud,le_niveau);
indice_noeud:=self.Items[1].GetNextChild(indice_noeud);
end
end
end
end;
function TTree1.Getmaxniveau:integer;
{renvoie la profondeur maximum de l'arbre
profondeur de la racine=0}
var i,max:integer;
begin
if self.Itemcount<>0 then
begin
max:=1;
for i:=1 to self.Itemcount do
if max<self.Items[i].level then
max:=self.Items[i].level;
Getmaxniveau:=max-1;
end
else Getmaxniveau:=0
end;
{------------------------------------------------------------------------------------}
{////////////////////////////// CONSTRUCTEUR
////////////////////////////////////////}
constructor TTree1.Create(Aowner:Tcomponent);
begin
inherited create(Aowner);
self.setbounds(8,8,233,233); {position
: left,top,width,height}
end;