|
u_c_display - John COLIBRI.
|
- mots clé:display - mise au point - affichage de texte - Write
- logiciel utilisé: Windows 98, Delphi 5.0
- matériel utilisé: Pentium 500Mhz, 128 M de mémoire
- champ d'application: Delphi 1 à 6 sur Windows, Kylix
- niveau: débutant en Pascal et Delphi
- uses: u_c_basic_object, u_c_log, u_loaded, u_strings,
(u_types_constants, u_c_basic_file, u_c_file_name,
u_dir)
- plan:
1 - Introduction
Depuis le Pascal de l'Apple ][, je passe mon temps à afficher du texte pour
mettre au point mes programmes.
Lors de l'arrivé du Pascal UCSD 1.3 (vers 1981 de mémoire) j'avais même
commencé à mettre au point un débugger symbolique qui synchronise l'adresse
dans le code exécutable et la ligne dans un fichier source. Puis est venu
Turbo, et bien longtemps après son fabuleux débugger.
Fini les Writeln qu'il faillait péniblement insérer ici ou là et dont la
triste vocation était d'être un jour virés comme des malpropres.
Eh bien Que Nenni. Vingt ans plus tard, je continue à afficher du texte plutôt
que d'utiliser le débugger.
Comme les discussions sur C++ vs Pascal, ou d'autres batailles entre Gnome vs
Qt, ce genre de bataille frise la guerre de religion. Je donnerai simplement
ici mes raisons, sachant que ceux qui ont remplacé les Writeln par le débugger
seront convaincus d'avoir raison. Pour ceux qui n'auront pas ici quitté la
présentation, mes arguments sont les suivants:
- les Writeln peuvent être insérés en tenant compte de toute la puissance de
Pascal. Un IF bien concocté est bien plus spécifique que toutes les
conditions ajoutées au débugger
- l'affichage me permet de garder une trace de l'historique. Le débugger
m'oblige à mémoriser par où je suis passé
- l'affichage peut être formatté à volonté
- l'affichage est souvent couplé à un Log sur disque qui est facilement
consultable (chaque ligne est purgée sur disque) en cas de problème grave
- ces logs peuvent d'ailleurs être multiples et hiérarchiques (liste des
fichiers traités, valeurs lors de l'un des traitements etc)
1.2 - Historique
Historiquement, dans le livre 'Delphi Applis Windows Rapides', j'avais commencé
à utiliser des tListbox (car elles étaient présentées avant les tMemo).
Depuis, j'utilise des tMemo, qui peuvent en outre être édités avant d'être
envoyés sur disque.
L'utilisation de tMemo explique l'affichage ligne à ligne utilisé dans la
première version de u_display. De plus l'affichage de la ligne provoquait
l'écriture dans le log disque, ce qui explique que je ne souhaitais pas
tamponner les textes partiels (Write).
Pris par le temps, l'ensemble de ces procédures a été placé dans une unité
u_display, qui a naturellement grossi à travers les ages (ajout de
display_bug_stop, display_bug_halt, stop_display, restart_display etc.)
Comme je souhaite publier des articles sur mes programmes récents, la plupart
utilisent ces affichages (pour la mise au point, mais pourraient aussi être
utiles pour présenter le fonctionnement du programme).
Deux choix: soit virer touts les appels display, soit publier cette unité.
Je ne la publierai pas dans l'état actuel car:
- elle n'est pas toilettée
- elle n'est pas objet, ce qui empêche la création de plusieurs affichages
J'ai donc choisi:
- d'en fournir une version allégé
- cette version est "objet": l'utilisateur peut avoir autant de display qu'il
veut.
De plus pour conserver la compatibilité avec mes anciens programmes, les
primitives essentielles (display, display_line, clear_display) sont
maintenue comme procédures globales et non objet, en appelant une objet
c_display global. Ceci évite d'avoir à corriger la tonne de programmes
actuels en remplaçant:
display('ok');
par
mon_c_display.display('ok');
Bref, le meilleur des deux mondes.
- la nouvelle mécanique permet l'écriture tamponnée (Write) en ajoutant
c_display.write (c_display.WriteLn étant l'affichage d'une ligne
complète).
Notez que cette notation Write est un peu abusive, car nous n'avons de loin
pas les fonctionalités de Write:
- redirection vers des fichiers quelconques (disque, imprimante)
Write(PRINTER, 'j''imprime');
- paramètres multiples
Write('le total est ', montant* taux);
- formattage par :
Write('résultat: ', total: 12: 2, ' quantité ', quantité: 5);
Peut-être Delphi permet-il de rediriger Write comme le faisait Pascal (cf
l'article de Daniel GAVARIN dans Pascalissime).
Faute de temps, et comme l'affichage de mise au point ne nécessite pas ces
ajouts, j'ai fait l'impasse.
1.3 - L'affichage indenté
display(p_text) est la procédure fondamentale:
- l'indentation est décrémentée si la chaîne commence par <
- la chaîne est calculée à pâtir de l'indentation, la chaîne courante et le
paramètre
- s'il y a un fichier log, les données y sont envoyées
- si la chaîne commence par >, l'indentation est incrémentée
2 - Utilisation
2.1 - L'interface est la suivante:
type c_display= class(c_basic_object)
public
m_do_display: Boolean;
m_indentation: Integer;
m_current_string: String;
m_c_strings: tStrings;
m_c_log: c_log;
Constructor create_display(p_name: String; p_c_strings: tStrings;
p_c_log: c_log); Virtual;
procedure clear_display;
procedure display_string(p_text: String);
procedure display(p_text: String);
procedure display_line;
function f_save_display: Boolean;
procedure restore_display(p_display: Boolean);
procedure stop(p_text: String);
procedure display_bug(p_text: String);
procedure display_bug_stop(p_text: String);
procedure display_bug_halt(p_text: String);
Destructor Destroy; Override;
end;
|
Pour les données:
- m_do_display: permet de bloquer l'affichage
- m_indentation: l'indentation. Gérée essentiellement en fournissant des
lignes commençant par > ou <
- m_current_string: permet la construction progressive de la chaîne
- m_c_strings: le descendant de tStrings dans lequel aboutira la chaîne (en
général un tMemo)
- m_c_log: le fichier dans lequel seront écrites les chaînes
Et pour les méthodes:
- create_display: créé c_display, en indiquant dans quelle tStrings envoyer
les chaînes et le nom du log
- pour l'affichage:
- clear_display: purge les tStrings
- display_string: ajoute une chaîne à la chaîne courante
- display: envoie la chaîne courante dans la tStrings et le log
- display_line: envoie une ligne vide dans la tStrings et le log
- l'affichage peut être temporairement désactivé:
- f_save_display: retourne la valeur de m_do_display
- restore_display: restore la valeur de m_do_display
- quelques procédures facilitent l'affichage des bugs:
- stop bloque l'exécution par un ShowMessage
- display_bug: affiche le texte avec '***' au début
- display_bug_stop: affiche le texte en bloquant l'exécution
- display_bug_halt: affiche le texte et interrompt le programme
2.2 - Répertoires
L'unité est prévue pour être placée dans:
C:
programs
colibri_helpers
classes
Vous pouvez naturellement changer cette organisation par Projet | Options |
Directories
2.3 - Directives de compilation
Les directives de compilation sont:
- R+ (vérification des intervalles)
- S+ (vérification de la pile)
- pas d'optimisation
3 - Programmation
Cette classe utilise essentiellement le fait que les tMemo.Lines sont des
descendants de tStrings: en ajoutant une ligne au tStrings de u_c_display,
nous affichons dans le tMemo.
L'affichage fonctionne ainsi:
- l'utilisateur appelle initialize_display qui stocke dans un pointeur privé
de c_display l'adresse de mon_memo.Lines.
- toutes les unités qui utilisent par USES u_c_display peuvent ainsi
afficher dans mon_memo, sans avoir à importer la tForm qui contient le
tMemo
4 - Améliorations
La syntaxe actuelle est historique:
- display affiche une ligne, et display_strings une chaîne.
- une autre solution aurait été d'utiliser "display" pour une chaîne et
display_line pour une ligne
Une autre possiblité aurait été de détourner les sorties des fichiers ASCII, ce
qui aurait permis les possibilités de conversion et de formatage de Write.
Mentionnons aussi que les unités telles que WinCrt, ou autre dérivées de CRT
offrent aussi ces possibilités d'affichage de mise au point. L'inconvénient à
mes yeux est qu'une autre fenêtre est utilisée pour l'affichage, alors que
u_c_display permet l'affichage dans la fenêtre principale.
5 - Télécharger
Vous pouvez télécharger:
Avec les mentions d'usage:
- j'apprécie tous les commentaires, remarques ou critiques
- signalez-moi les bugs que vous trouverez.
L'auteur
John COLIBRI est passionné par le développement
Delphi et les applications de Bases de Données. Il a écrit de nombreux livres
et articles, et partage son temps entre la
développement de projets pour
ses clients, le conseil et la formation. Son site contient des articles
avec code source, ainsi que le programme et le calendrier des
stages
de formation Delphi, base de données, Ado.Net, Asp.Net et UML qu'il
anime personellement tous les mois, à Paris, en province ou sur site client.
|