Obligement - L'Amiga au maximum

Vendredi 06 juin 2025 - 12:18  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

Actualité (récente)
Actualité (archive)
Comparatifs
Dossiers
Entrevues
Matériel (tests)
Matériel (bidouilles)
Points de vue
En pratique
Programmation
Reportages
Quizz
Tests de jeux
Tests de logiciels
Tests de compilations
Trucs et astuces
Articles divers

Articles in English


Réseaux sociaux

Suivez-nous sur X




Liste des jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z,
ALL


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Galeries

Menu des galeries

BD d'Amiga Spécial
Caricatures Dudai
Caricatures Jet d'ail
Diagrammes de Jay Miner
Images insolites
Fin de jeux (de A à E)
Fin de Jeux (de F à O)
Fin de jeux (de P à Z)
Galerie de Mike Dafunk
Logos d'Obligement
Pubs pour matériels
Systèmes d'exploitation
Trombinoscope Alchimie 7
Vidéos


Téléchargement

Documents
Jeux
Logiciels
Magazines
Divers


Liens

Associations
Jeux
Logiciels
Matériel
Magazines et médias
Pages personnelles
Réparateurs
Revendeurs
Scène démo
Sites de téléchargement
Divers


Partenaires

Annuaire Amiga

Amedia Computer

Relec


A Propos

A propos d'Obligement

A Propos


Contact

David Brunet

Courriel

 


En pratique : CanDo - Les documents, les variables définies par l'utilisateur et les bases de données
(Article écrit par Randy Finch et extrait du Randy Finch's Web Site - octobre 1993)


Bienvenue dans la deuxième partie d'une série d'articles sur CanDo. J'espère que vous avez apprécié la première partie qui comparait CanDo 2.0 avec Visual Basic 2.0 (version Windows). Je viens de recevoir Visual Basic 3.0 et j'ai hâte de l'installer et de l'essayer. Je crois également savoir qu'INOVAtronics va bientôt sortir CanDo 2.5. Je ne connais pas les nouvelles fonctionnalités qu'il offrira, à l'exception de la gestion d'AmigaDOS 3.0 et des graphismes AGA. Comme je l'ai promis, cet article traite de l'utilisation des documents CanDo en conjonction avec des variables définies par l'utilisateur, ainsi que de l'initiation à la programmation de bases de données.

Tout d'abord, permettez-moi de dire que mon intention n'est pas de présenter un tutoriel détaillé du langage de programmation CanDo dans cet article. Je vous montrerai plutôt comment combiner diverses fonctionnalités de CanDo pour effectuer des tâches intéressantes et utiles. Si vous avez des questions sur la syntaxe de l'une des déclarations de mes programmes, je vous renvoie au manuel CanDo ou au système d'aide en ligne disponible dans le logiciel CanDo.

Je vais vous présenter deux programmes. Le premier vous montre comment les documents et les variables définies par l'utilisateur peuvent être combinés de façon utile. La technique présentée peut être utilisée dans de nombreuses applications différentes. Le deuxième programme montre à quel point il est facile de développer des applications de base de données avec CanDo.

Extraits d'un budget simple

Le premier programme que je vais présenter est un extrait d'une application que je suis en train d'écrire, intitulée "SimpleBudget". Comme vous l'avez peut-être deviné, il s'agit d'une application de budget familial. En écrivant SimpleBudget, j'ai dû faire un usage intensif de documents et de variables définies par l'utilisateur. L'extrait de programme dont je vais vous parler est centré sur l'une de plusieurs cartes et ses routines de gestion. L'objectif de cette carte est de permettre à l'utilisateur d'entrer les noms des comptes financiers qu'il possède et les noms des différentes catégories dans lesquelles chaque compte est divisé. Par exemple, l'utilisateur peut avoir un compte appelé "Checking" qui est divisé en catégories telles que "Car Payment" (factures de la voiture), "Mortgage" (hypothèque), "Food" (alimentation), "Clothes" (vêtements), etc. et un autre compte appelé "Savings" (économies) avec les catégories "Johnny's Education" (éducation de John) et "Sue's Summer Trip" (voyage d'été de Sue). Chacun de ces comptes représente un compte réel dans une banque, une coopérative de crédit ou une autre institution financière. Les catégories ne sont que des divisions artificielles des comptes créées par l'utilisateur à des fins de budgétisation.

La carte illustrée à la figure 1 s'appelle "Create_Accounts". Sur cette carte se trouvent plusieurs objets CanDo. Il y a deux objets TextField appelés "Field_Account" et "Field_Category". Il s'agit des deux rectangles biseautés situés en haut de l'écran, qui servent à saisir les nouveaux noms de compte et de catégorie. Directement sous ces objets se trouvent deux grandes boîtes biseautées qui sont des objets List nommés "Document_Accounts" et "Document_Categories". Elles sont utilisées pour afficher des listes de noms de comptes et de catégories. Enfin, il y a six objets TextButton. Les deux situés à gauche de l'objet List Document_Accounts sont nommés "DeleteAccount" et "SortAccount". Le premier permet à l'utilisateur de supprimer un seul compte sélectionné, tandis que le second permet au programme de trier la liste des noms de comptes. Les deux boutons de texte situés à gauche de Document_Categories sont appelés "DeleteCategory" et "SortCategory". Ils effectuent la suppression et le tri des noms de catégories. Les deux derniers boutons de texte sont situés dans le coin inférieur droit de l'écran et s'appellent "OK" et "Cancel". Le premier permet à l'utilisateur d'accepter les modifications apportées aux noms de compte et de catégorie, tandis que le second permet d'annuler les modifications.

CanDo 2.0
Figure 1 - carte "Create_Accounts"

La carte Create_Accounts contient également quatre chaînes de texte : "Enter Accounts:", "Enter Categories:", et deux chaînes "000". Ces deux dernières chaînes seront continuellement mises à jour par le programme pour tenir l'utilisateur informé du nombre actuel de comptes et de catégories dans les deux objets List. La figure 2 montre à quoi peut ressembler la carte après l'ajout de quelques comptes et catégories. Remarquez que le compte nommé "Checking" a été sélectionné par l'utilisateur. Cinq catégories sont associées à ce compte : "Car Payment" (factures de la voiture), "Church" (église), "Clothes" (vêtements), "Food" (alimentation) et "House Payment" (factures de la maison).

CanDo 2.0
Figure 2 - carte "Create_Accounts" avec catégories

Le travail sur papier

Maintenant que l'interface utilisateur a été conçue et que nous savons comment elle doit fonctionner, il est temps de faire un peu de travail administratif. Nous devons décider comment gérer les données de l'utilisateur. C'est là que les variables flexibles définies par l'utilisateur de CanDo deviennent extrêmement utiles. Tout d'abord, il faut choisir un nom de variable primaire. J'utilise le nom "Budget", qui est controversé, mais qui donne à réfléchir. Plusieurs niveaux de noms secondaires seront suspendus à ce nom de variable primaire. La variable Budget ressemble à ceci :

Budget.NumAccounts
Budget.Account[].Name
Budget.Account[].Numcategories
Budget.Account[].Category[].Name
Budget.Account[].Category[].BeginBalance.Dollars
Budget.Account[].Category[].BeginBalance.Cents
Budget.Account[].Category[].EndBalance.Dollars
Budget.Account[].Category[].EndBalance.Cents
Budget.Transactions[].Type
Budget.Transactions[].DollarsTotal
Budget.Transactions[].CentsTotal
.
.
.

Remarquez que Budget gère un tableau dynamique (représenté par les parenthèses) de noms de comptes et un tableau dynamique de noms de catégories pour chaque compte, ainsi que d'autres types d'informations. La structure de données de Budget est assez longue et n'est pas présentée dans son intégralité. La carte Create_Accounts n'utilise que les huit premiers éléments de la structure. Les autres éléments de la structure de données du budget sont utilisés par d'autres cartes de SimpleBudget et ne sont pas abordés dans cet article.

L'avantage de stocker toutes les données dans une structure définie par l'utilisateur, telle que présentée ci-dessus, est qu'il est très simple de sauvegarder et de récupérer les données dans un fichier disque. Par exemple, si vous voulez sauvegarder la structure de données Budget, vous pouvez lancer la commande suivante dans le code CanDo :

SaveVariable Budget, Filename

Vous pouvez tout aussi facilement récupérer ces données dans la variable Budget avec cette commande :

Budget=LoadVariable(Filename)

Cette fonctionnalité rend CanDo extrêmement utile pour le développement d'applications. Il n'est pas nécessaire d'avoir des boucles dans des boucles dans des boucles autour d'une commande PRINT ou WRITE comme c'est le cas en BASIC.

Plus d'informations sur l'interface utilisateur

Le Listing 1 présente toutes les informations relatives à la carte Create_Accounts. Le listing a été généré par un utilitaire fourni avec CanDo, et les numéros de ligne ont été ajoutés à l'aide de la commande Shell "TYPE filename OPT N". Lorsque vous créez l'interface utilisateur dont nous avons parlé plus haut, vous pouvez utiliser les informations de ce listing pour vous aider à mettre en page l'interface exactement comme elle apparaît sur la figure 1. Les informations relatives à la fenêtre de la carte sont indiquées aux lignes 64 à 77. Toutes les informations nécessaires à la disposition des différents objets sont présentées dans les sections Définition du listing. Remarquez aux lignes 270-299 qu'il y a deux objets TextMenu attachés à la carte. Il s'agit de menus déroulants. Vous n'avez pas besoin d'ajouter ces objets si vous ne le souhaitez pas. Ils offrent simplement une alternative aux boutons textuels "OK" et "Cancel".

Listing 1. Routines d'interface d'information et d'événement
                   pour Create_Accounts Card dans CanDo 2.0

    1 *************
    2 * Deck "CanDo-Part2-Program"
    3 * Time 13:19:34
    4 * Date 06/27/93
    5 *************
    6 
    7 *************
    8 * Card(s) in deck.
    9 *  Card "Create_Accounts"
   10 *************
   11 * 1 Card(s), 1 were printed.
   12 *************
   13 
   14 *************
   15 * Natural order of Cards
   16 *  Card "Create_Accounts"
   17 *************
   18 
   19 *************
   20 * Global Routine(s) in deck.
   21 *  Routine "Cancel Accounts" (was not printed)
   22 *  Routine "Display Categories" (was not printed)
   23 *  Routine "OK Accounts" (was not printed)
   24 *  Routine "Print Num Accts" (was not printed)
   25 *  Routine "Print Num Cats" (was not printed)
   26 *  Routine "Sort the Document" (was not printed)
   27 *  Routine "Update Categories" (was not printed)
   28 *************
   29 * 7 Global routines(s), 0 were printed.
   30 *************
   31 
   32 *************
   33 * Card "Create_Accounts"
   34   BeforeAttachment ; used to be OnStartup
   35     WorkWithDocument "Accounts"
   36     Clear DOCUMENT 
   37     Let NumAccounts = Budget.NumAccounts
   38     Let I = 1
   39     While I <= NumAccounts
   40        Type Budget.Account[I].Name,NEWLINE 
   41        WorkWithDocument "Categories."||Budget.Account[I].Name
   42        Clear DOCUMENT 
   43        Let NumCategories = Budget.Account[I].NumCategories
   44        Let J = 1
   45        While J <= NumCategories
   46           Type Budget.Account[I].Category[J].Name,NEWLINE 
   47           Let J = J+1
   48        EndLoop
   49        WorkWithDocument "Accounts"
   50        Let I = I+1
   51     EndLoop
   52   EndScript
   53   AfterAttachment ; used to be AfterStartup
   54     SetPrintFont "topaz",9
   55     SetPrintStyle BOLD ,2,3
   56     SetPen 1,0
   57     SetDrawMode JAM1 
   58     PrintText "Enter Accounts:",102,18
   59     PrintText "Enter Categories:",410,18
   60     Do "Print Num Accts"
   61     Do "Print Num Cats"
   62     SetObjectState "Field_Account",ON
   63   EndScript
   64   Window "UserWindow"
   65     Definition
   66        Origin 0,0
   67        Size 640,200
   68        Title "SimpleBudget v1.00  ©1992 RKA Productions          ACCOUNTS and CATEGORIES"
   69        NumberOfColors 4
   70        WindowColors 3,1,0 ; Detail, Block, Background
   71        WindowObjects CLOSEBUTTON 
   72        WindowFlags ACTIVATE SEPARATESCREEN TOFRONT 
   73     EndScript
   74     OnCloseButton
   75        Quit
   76     EndScript
   77   EndObject
   78   List "Document_Accounts"
   79     Definition
   80        Origin 106,45
   81        Size 209,120
   82        Font "topaz",8 ; FontName, PointSize
   83        PrintStyle PLAIN ,2,3 ; Style, Pen1, Pen2
   84        TextColors 1,0,JAM2  ; PenA, PenB, DrawMode
   85        Border DOUBLEBEVEL ,2,1 ; BorderStyle, MainPen, ExtraPen
   86        Document "Accounts" ; where the text comes from
   87     EndScript
   88     OnClick
   89        Do "Update Categories"
   90        Do "Display Categories"
   91        Do "Print Num Cats"
   92     EndScript
   93     OnRelease
   94        SetObjectState "Field_Category",ON
   95     EndScript
   96   EndObject
   97   TextField "Field_Account"
   98     Definition
   99        Origin 106,32
  100        Size 185,8
  101        Justification LEFT 
  102        MaxFieldLength 22
  103        InitialText ""
  104        Border DOUBLEBEVEL ,2,1 ; BorderStyle, MainPen, ExtraPen
  105     EndScript
  106     OnRelease
  107        Let AcctName = TextFrom("Field_Account")
  108        Type AcctName,NEWLINE 
  109        SetText "Field_Account",""
  110        SetObjectState "Field_Account",ON
  111        Do "Print Num Accts"
  112     EndScript
  113     OnClick
  114        WorkWithDocument "Accounts"
  115        MoveCursorTo ENDOF DOCUMENT 
  116        Do "Update Categories"
  117        Do "Display Categories"
  118        Do "Print Num Cats"
  119     EndScript
  120   EndObject
  121   TextButton "OK"
  122     Definition
  123        Origin 463,181
  124        Font "topaz",8 ; FontName, PointSize
  125        PrintStyle PLAIN ,2,3 ; Style, Pen1, Pen2
  126        TextColors 1,0,NORMAL  ; PenA, PenB, DrawMode
  127        Text "   OK   "
  128        Border EMBOSSED ,2,1 ; BorderStyle, MainPen, ExtraPen
  129        Highlight OUTLINE 
  130        ButtonFlags NONE 
  131     EndScript
  132     OnRelease
  133        Do "OK Accounts"
  134     EndScript
  135   EndObject
  136   TextButton "Cancel"
  137     Definition
  138        Origin 557,181
  139        Font "topaz",8 ; FontName, PointSize
  140        PrintStyle PLAIN ,2,3 ; Style, Pen1, Pen2
  141        TextColors 1,0,NORMAL  ; PenA, PenB, DrawMode
  142        Text " CANCEL "
  143        Border EMBOSSED ,2,1 ; BorderStyle, MainPen, ExtraPen
  144        Highlight OUTLINE 
  145        ButtonFlags NONE 
  146     EndScript
  147     OnRelease
  148        Nop ;Change nairy a thing!!
  149        GotoCard "Intro"
  150     EndScript
  151   EndObject
  152   TextButton "DeleteAccount"
  153     Definition
  154        Origin 19,54
  155        Font "topaz",8 ; FontName, PointSize
  156        PrintStyle PLAIN ,2,3 ; Style, Pen1, Pen2
  157        TextColors 1,0,NORMAL  ; PenA, PenB, DrawMode
  158        Text "Delete->"
  159        Border EMBOSSED ,2,1 ; BorderStyle, MainPen, ExtraPen
  160        Highlight OUTLINE 
  161        ButtonFlags NONE 
  162     EndScript
  163     OnRelease
  164        WorkWithDocument "Accounts"
  165        Let DeletedAccount = TheLine
  166        Delete LINE 
  167        Do "Print Num Accts"
  168        Nop ;Clear the document associated with the deleted account
  169        WorkWithDocument "Categories."||DeletedAccount
  170        Clear DOCUMENT 
  171        Do "Display Categories"
  172        Do "Print Num Cats"
  173        WorkWithDocument "Accounts"
  174     EndScript
  175   EndObject
  176   TextButton "SortAccount"
  177     Definition
  178        Origin 19,74
  179        Font "topaz",8 ; FontName, PointSize
  180        PrintStyle PLAIN ,2,3 ; Style, Pen1, Pen2
  181        TextColors 1,0,NORMAL  ; PenA, PenB, DrawMode
  182        Text " Sort-> "
  183        Border EMBOSSED ,2,1 ; BorderStyle, MainPen, ExtraPen
  184        Highlight OUTLINE 
  185        ButtonFlags NONE 
  186     EndScript
  187     OnRelease
  188        Do "Update Categories"
  189        WorkWithDocument "Accounts"
  190        Do "Sort the Document"
  191        SetObjectState "Field_Account",ON
  192     EndScript
  193   EndObject
  194   List "Document_Categories"
  195     Definition
  196        Origin 414,45
  197        Size 209,120
  198        Font "topaz",8 ; FontName, PointSize
  199        PrintStyle PLAIN ,2,3 ; Style, Pen1, Pen2
  200        TextColors 1,0,JAM2  ; PenA, PenB, DrawMode
  201        Border DOUBLEBEVEL ,2,1 ; BorderStyle, MainPen, ExtraPen
  202        Document "Categories" ; where the text comes from
  203     EndScript
  204     OnClick
  205        WorkWithDocument "Categories"
  206     EndScript
  207   EndObject
  208   TextButton "DeleteCategory"
  209     Definition
  210        Origin 333,54
  211        Font "topaz",8 ; FontName, PointSize
  212        PrintStyle PLAIN ,2,3 ; Style, Pen1, Pen2
  213        TextColors 1,0,NORMAL  ; PenA, PenB, DrawMode
  214        Text "Delete->"
  215        Border EMBOSSED ,2,1 ; BorderStyle, MainPen, ExtraPen
  216        Highlight OUTLINE 
  217        ButtonFlags NONE 
  218     EndScript
  219     OnRelease
  220        WorkWithDocument "Categories"
  221        Delete LINE 
  222        Let ChangedCategories = TRUE
  223        Do "Print Num Cats"
  224        Do "Update Categories"
  225        SetObjectState "Field_Category",ON
  226     EndScript
  227   EndObject
  228   TextButton "SortCategory"
  229     Definition
  230        Origin 333,74
  231        Font "topaz",8 ; FontName, PointSize
  232        PrintStyle PLAIN ,2,3 ; Style, Pen1, Pen2
  233        TextColors 1,0,NORMAL  ; PenA, PenB, DrawMode
  234        Text " Sort-> "
  235        Border EMBOSSED ,2,1 ; BorderStyle, MainPen, ExtraPen
  236        Highlight OUTLINE 
  237        ButtonFlags NONE 
  238     EndScript
  239     OnRelease
  240        WorkWithDocument "Categories"
  241        Do "Sort the Document"
  242        Let ChangedCategories = TRUE
  243        Do "Update Categories"
  244        SetObjectState "Field_Category",ON
  245     EndScript
  246   EndObject
  247   TextField "Field_Category"
  248     Definition
  249        Origin 414,32
  250        Size 185,8
  251        Justification LEFT 
  252        MaxFieldLength 22
  253        InitialText ""
  254        Border DOUBLEBEVEL ,2,1 ; BorderStyle, MainPen, ExtraPen
  255     EndScript
  256     OnRelease
  257        Let CatName = TextFrom("Field_Category")
  258        Type CatName,NEWLINE 
  259        Let ChangedCategories = TRUE
  260        SetText "Field_Category",""
  261        SetObjectState "Field_Category",ON
  262        Do "Print Num Cats"
  263        Do "Update Categories"
  264     EndScript
  265     OnClick
  266        WorkWithDocument "Categories"
  267        MoveCursorTo ENDOF DOCUMENT 
  268     EndScript
  269   EndObject
  270   TextMenu "Okay   "
  271     Definition
  272        AttachTo MENU ,"Options"
  273        Font "topaz",8 ; FontName, PointSize
  274        PrintStyle PLAIN ,2,3 ; Style, Pen1, Pen2
  275        TextColors 0,1,NORMAL  ; PenA, PenB, DrawMode
  276        Text "Okay   "
  277        MenuFlags NONE 
  278        Highlight COMPLEMENT 
  279        ShortCutKey ""
  280     EndScript
  281     Occurred
  282        Do "OK Accounts"
  283     EndScript
  284   EndObject
  285   TextMenu "Cancel "
  286     Definition
  287        AttachTo MENU ,"Options"
  288        Font "topaz",8 ; FontName, PointSize
  289        PrintStyle PLAIN ,2,3 ; Style, Pen1, Pen2
  290        TextColors 0,1,NORMAL  ; PenA, PenB, DrawMode
  291        Text "Cancel "
  292        MenuFlags NONE 
  293        Highlight COMPLEMENT 
  294        ShortCutKey ""
  295     EndScript
  296     Occurred
  297        Do "Cancel Accounts"
  298     EndScript
  299   EndObject
  300 * End of Card "Create_Accounts"
  301 *************

Ajout de fonctionnalités

Une fois l'interface définie dans CanDo, il est temps d'y ajouter des fonctionnalités en ajoutant du code. Le code peut être ajouté sous forme de routines d'événements ou de routines globales. Les routines d'événement sont exécutées lorsqu'un événement survient sur un objet ou une carte. Les routines globales sont des sous-programmes qui peuvent être appelés à partir de routines d'événement ou d'autres routines globales et sont généralement utilisées lorsque certaines tâches doivent être accomplies à partir de plus d'une routine. Si le programmeur n'ajoute aucun code à une routine d'événement, rien ne se passe lorsque l'événement se produit.

Commençons par la carte Create_Accounts. Elle possède deux routines d'événement : BeforeAttachment et AfterAttachment (lignes 34-52 et 53-63). La première est exécutée juste avant l'affichage d'une carte à l'écran et est normalement utilisée pour attribuer des valeurs aux variables utilisées par la carte. La seconde est exécutée après l'affichage de la carte et sert normalement à imprimer du texte et des graphismes sur la carte.

La routine BeforeAttachment est extrêmement importante pour la carte Create_Accounts. Elle transfère les informations stockées dans la variable Budget vers plusieurs documents. Dans CanDo, les documents sont comme des chaînes de caractères de longueur variable, sauf que des opérations sophistiquées peuvent être effectuées sur les documents. De plus, un document peut être attaché à un objet List de sorte que lorsque le document change, l'objet List est automatiquement mis à jour. L'objet List Document_Accounts a le document Accounts attaché à lui (ligne 86) ; l'objet List Document_Categories a le document Categories attaché à lui (ligne 202). Ces affectations d'attachement sont effectuées lors de la conception des objets List.

Comme il existe un tableau de noms de catégories pour chaque compte, un mécanisme est nécessaire pour créer une multitude de documents avec des noms différents, un pour chaque compte. Une fois ces documents créés, le texte de ces documents peut être déplacé dans le document Categories lorsque l'utilisateur sélectionne différents comptes. Ceci est nécessaire car le nom du document attaché à un objet List ne peut pas changer, mais le texte du document attaché peut être modifié. Par conséquent, j'ai décidé de créer, en substance, un tableau de documents. Les documents ne peuvent pas réellement faire partie d'un tableau ; il faut donc faire preuve d'un peu d'ingéniosité. Comme les documents sont référencés par des variables de type chaîne, il est possible d'utiliser l'opérateur de concaténation de chaînes pour créer le tableau de documents. Chaque document du tableau aura un nom de la forme "Categories.AccountName" où "AccountName" peut être n'importe quel nom de compte utilisateur. Ainsi, si l'utilisateur possède trois comptes nommés "Checking" (compte de chèques), "Savings" (économies) et "MutualFund" (fonds communs), trois documents seront créés sous les noms "Categories.Checking", "Categories.Savings" et "Categories.MutualFund" pour stocker les trois listes de noms de catégories pour les comptes.

La routine BeforeAttachment de la carte Create_Accounts est utilisée pour déplacer les noms actuels des comptes et des catégories dans la variable Budget vers des documents nommés de manière appropriée. L'utilisateur peut ensuite manipuler les documents à sa guise. Une fois que l'utilisateur a terminé de modifier les comptes et les catégories, il peut sélectionner le bouton de texte "OK" ou le menu de texte "OK", auquel cas les informations contenues dans les documents modifiés seront replacées dans la variable Budget pour être enregistrées ultérieurement à l'aide de la commande "SaveVariable". Cependant, si l'utilisateur sélectionne le bouton de texte "Annuler" ou le menu de texte "Annuler", le contenu du document n'est pas transféré dans la variable Budget, laissant ainsi les valeurs originales intactes. Par conséquent, les documents servent de zones de stockage temporaire pour les nouvelles entrées.

Le code de BeforeAttachment est assez simple. Il définit le document de travail comme Accounts, l'efface, détermine le nombre de comptes dans la variable Budget, puis utilise une boucle intégrée pour construire le document Accounts et chacun des documents Categories.AccountName. Chaque nom est inséré dans le document approprié à l'aide de la commande "Type" (lignes 40 et 46). Remarquez le paramètre "NEWLINE" à la fin de cette commande. Il permet au pointeur du document d'avancer à la ligne suivante. Sans ce paramètre, tous les noms apparaîtraient sur la même ligne.

Routines globales

Avant d'examiner le code du reste des routines d'événement de la carte Create_Accounts, jetons un coup d'oeil aux sept routines de gestion globales des listes 2 à 8. Cela vous aidera à mieux comprendre ce que font les routines d'événements lorsqu'elles appellent l'une de ces routines globales.

Le Listing 2 est la routine d'annulation des comptes. Elle n'est appelée que lorsque l'élément de menu "Annuler" est sélectionné (le bouton "Annuler" a le même code que la routine d'événement elle-même. C'est juste pour vous montrer qu'il existe différentes façons d'accomplir la même tâche). Cette routine globale dirige simplement le programme vers une carte appelée "Intro". Il s'agit d'une autre carte de l'application SimpleBudget qui n'est pas abordée dans cet article. Jetez un coup d'oeil à la ligne 3. CanDo ne permet pas à un commentaire de résider seul sur une ligne ; il doit suivre une commande. Par conséquent, la commande "Nop" (qui signifie "No Operation") est utilisée pour précéder le commentaire. C'est quelque chose que j'aimerais voir corrigé dans une prochaine version de CanDo.

Listing 2.  Routine globale "Cancel Accounts"

    1 *************
    2 * Global routine "Cancel Accounts"
    3   Nop ;Change nairy a thing!!
    4   GotoCard "Intro"
    5 * End of routine "Cancel Accounts"
    6 *************

Le Listing 3 est la routine "Display Categories". Elle est utilisée pour déplacer le document Categories.AccountName approprié dans le document Categories afin qu'il soit affiché dans l'objet List Document_Categories. En général, cette routine est appelée lorsque l'utilisateur sélectionne un nom de compte dans l'objet Document_Accounts avec le bouton gauche de la souris. Comme il ne peut y avoir qu'un seul document de travail à la fois, cette routine affecte d'abord le nom du document de travail actuel, stocké dans la variable système DocumentName, à la variable CurrentDocument. Ensuite, le document de travail est changé en Accounts et le nom qui est stocké dans la ligne actuellement sélectionnée de Document_Comptes est affecté à la variable ChosenAccount. La Ligne est une variable système utilisée pour stocker le texte de la ligne actuellement sélectionnée du document de travail en cours. Si la valeur de ChosenAccount n'est pas NULL, le document de travail est modifié en fonction du Categories.AccountName approprié à l'aide de la commande "WorkWithDocument". Cette commande créera le document s'il n'existe pas déjà.

Listing 3. Routine globale "Display Categories"

    1 *************
    2 * Global routine "Display Categories"
    3   Let CurrentDocument = DocumentName
    4   WorkWithDocument "Accounts"
    5   Let ChosenAccount = TheLine
    6   If ChosenAccount <> NULL
    7     WorkWithDocument "Categories."||ChosenAccount  ;Create if nonexistant
    8     Let NewCategoryDocument = TextFromDocument("Categories."||ChosenAccount)
    9     WorkWithDocument "Categories"
   10     Clear DOCUMENT 
   11     Type NewCategoryDocument
   12   Else
   13     WorkWithDocument "Categories"
   14     Clear DOCUMENT 
   15   EndIf
   16   WorkWithDocument CurrentDocument
   17 * End of routine "Display Categories"
   18 *************

Ensuite, le texte de ce document, s'il y en a un, est attribué à la variable chaîne NewCategoryDocument. Le document de travail est changé en Categories (celui qui est attaché à l'objet Document_Categories), vidé de son texte actuel, puis le texte de NewCategoryDocument lui est attribué. À ce stade, les catégories du compte sélectionné seront affichées. Étant donné que les documents Accounts et Categories ont toujours une ligne vide comme dernière ligne du document (utilisée comme point d'insertion pour un nom nouvellement saisi), il est possible que ChosenAccount soit NULL. Si c'est le cas, le document Categories est effacé car il n'y a pas de catégories pour ce nom de compte vide. Enfin, le document de travail original est réinitialisé.

Le Listing 4 est la routine "OK Accounts". Elle est exécutée lorsque le bouton "OK" ou l'élément de menu "OK" est sélectionné par l'utilisateur. Elle est très similaire à la routine BeforeAttachment discutée précédemment, sauf qu'elle déplace toutes les informations des documents vers la variable Budget plutôt que l'inverse. Le nombre de comptes et de catégories dans chaque document est déterminé en prenant le nombre de lignes dans le document et en soustrayant un (lignes 5 et 13). L'unité est soustraite parce qu'il y a toujours une ligne blanche à la fin du document. La variable système LinesInDocument contient toujours le nombre de lignes du document de travail actuel. Les noms de compte et de catégorie sont extraits du document en déplaçant le curseur au début du document approprié (lignes 4 et 12) et en utilisant la variable système "TheLine" comme décrit précédemment. Le curseur du document est ensuite déplacé dans le document, une ligne à la fois (lignes 23 et 27), en extrayant les noms au fur et à mesure.

Listing 4. Routine globale "OK Accounts"

    1 *************
    2 * Global routine "OK Accounts"
    3   WorkWithDocument "Accounts"
    4   MoveCursorTo STARTOF DOCUMENT 
    5   Let NumAccounts = LinesInDocument-1
    6   Let Budget.NumAccounts = NumAccounts
    7   Let I = 1
    8   While I <= NumAccounts
    9     Let AccountName = TheLine
   10     Let Budget.Account[I].Name = AccountName
   11     WorkWithDocument "Categories."||AccountName
   12     MoveCursorTo STARTOF DOCUMENT 
   13     Let NumCategories = LinesInDocument-1
   14     Let Budget.Account[I].NumCategories = NumCategories
   15     Let J = 1
   16     While J <= NumCategories
   17        Let CategoryName = TheLine
   18        Let Budget.Account[I].Category[J].Name = CategoryName
   19        Let Budget.Account[I].Category[J].BegBal.Dollars = 0
   20        Let Budget.Account[I].Category[J].BegBal.Cents = 0
   21        Let Budget.Account[I].Category[J].EndBal.Dollars = 0
   22        Let Budget.Account[I].Category[J].EndBal.Cents = 0
   23        MoveCursor DOWN 
   24        Let J = J+1
   25     EndLoop
   26     WorkWithDocument "Accounts"
   27     MoveCursor DOWN 
   28     Let I = I+1
   29   EndLoop
   30   GotoCard "Intro"
   31 * End of routine "OK Accounts"
   32 *************

Le Listing 5 est la routine "Print Num Accounts". Elle met à jour l'affichage situé en haut de la carte Create_Accounts qui indique le nombre de comptes dans l'objet Document_Accounts. Pour ce faire, elle efface le nombre actuel sur la carte et affiche le nouveau nombre.

Listing 5. Routine globale "Print Num Accts"

    1 *************
    2 * Global routine "Print Num Accts"
    3   Let CurrentDocument = DocumentName
    4   WorkWithDocument "Accounts"
    5   SetPrintFont "topaz",9
    6   SetPen 1,0
    7   SetPrintStyle BOLD ,2,3
    8   SetDrawMode JAM2 
    9   PrintText "   ",268,18  ;clear the previous number
   10   SetDrawMode JAM1 
   11   PrintText FormatValue(LinesInDocument-1,"000"),268,18
   12   WorkWithDocument CurrentDocument
   13 * End of routine "Print Num Accts"
   14 *************

Le Listing 6 est la routine "Print Num Cats". Elle est identique à Print Num Accounts sauf qu'elle met à jour le nombre de catégories affichées dans l'objet Document_Categories.

Listing 6. Routine globale "Print Num Cats"

    1 *************
    2 * Global routine "Print Num Cats"
    3   Let CurrentDocument = DocumentName
    4   WorkWithDocument "Categories"
    5   SetPrintFont "topaz",9
    6   SetPrintStyle BOLD ,2,3
    7   SetPen 1,0
    8   SetDrawMode JAM1 
    9   PrintText "   ",595,18
   10   SetDrawMode JAM2 
   11   PrintText FormatValue(LinesInDocument-1,"000"),595,18
   12   WorkWithDocument CurrentDocument
   13 * End of routine "Print Num Cats"
   14 *************

Le Listing 7 est la routine "Sort the Document". Elle trie le document de travail actuel ; par conséquent, le document de travail doit être défini avant d'appeler cette routine. Le corps principal de la routine de tri (lignes 5 à 9) n'est exécuté que si le document contient au moins une ligne non vierge. La commande SortDocument est utilisée pour effectuer le tri et l'option "NOCASE" est utilisée pour rendre le tri non sensible à la casse. Une fois le tri terminé, la première ligne sera toujours la ligne d'insertion vide qui se trouve normalement à la fin du document. Le curseur du document doit donc être déplacé jusqu'à la première ligne du document et cette ligne doit être supprimée. Le curseur est ensuite déplacé à la fin du document et la commande NewLine est émise afin de laisser le document avec une ligne vierge à la fin.

Listing 7. Routine globale "Sort the Document"

    1 *************
    2 * Global routine "Sort the Document"
    3   Nop ;The current document should be set in calling routine
    4   If LinesInDocument > 1
    5     SortDocument NOCASE 
    6     MoveCursorTo STARTOF DOCUMENT 
    7     Delete LINE 
    8     MoveCursorTo ENDOF DOCUMENT 
    9     NewLine
   10   EndIf
   11 * End of routine "Sort the Document"
   12 *************

Le Listing 8 est la routine "Update Categories". Elle déplace le contenu du document Categories dans le document Categories.AccountName approprié. Cette opération est normalement effectuée chaque fois que l'utilisateur sélectionne un nom de compte différent afin de s'assurer que les modifications apportées aux catégories du compte précédemment sélectionné sont correctement enregistrées. Cette routine est très similaire à la routine Display Categories.

Listing 8. Routine globale "Update Categories"

    1 *************
    2 * Global routine "Update Categories"
    3   Let CurrentDocument = DocumentName
    4   Nop ;If "Categories" was changed, update appropriate document
    5   If ChangedCategories = TRUE
    6     Let NewCategoryDocument = TextFromDocument("Categories")
    7     WorkWithDocument "Categories."||ChosenAccount
    8     Clear DOCUMENT 
    9     Type NewCategoryDocument
   10     Let ChangedCategories = FALSE
   11   EndIf
   12   WorkWithDocument CurrentDocument
   13 * End of routine "Update Categories"
   14 *************

Routines d'événements

Il est maintenant temps d'examiner les autres routines d'événements de la carte Create_Accounts présentée dans le Listing 1. J'ai déjà parlé de la routine BeforeAttachment ; examinons maintenant la routine AfterAttachment (lignes 53-63). Cette routine affiche un texte à l'écran et imprime le nombre de comptes et de catégories via des routines globales. Enfin, elle active l'objet Field_Account, anticipant que la première chose que l'utilisateur voudra faire sera d'ajouter un nom de compte. À ce stade, l'application attendra simplement que l'utilisateur fasse quelque chose. Le code qui est exécuté dépend de l'action de l'utilisateur. Jetons un coup d'oeil à ces possibilités.

L'objet Field_Account est associé à deux événements : OnClick (lignes 113-119) et OnRelease (lignes 106-112). La routine OnClick s'exécute lorsque l'utilisateur déplace le pointeur de la souris sur le champ et clique sur le bouton gauche de la souris. Cette routine définit le document de travail sur Accounts, déplace le curseur sur la dernière ligne de ce document, puis met à jour les catégories. La routine OnRelease s'exécute lorsque l'utilisateur appuie sur la touche "Entrée" alors qu'il se trouve dans le champ. Elle récupère le texte du champ, l'insère dans le document de travail, qui a été défini comme Comptes dans la routine OnClick, efface le champ, le réactive, puis met à jour le nombre d'Accounts. À ce stade, le nouveau nom de compte saisi par l'utilisateur sera affiché dans la liste des comptes de l'objet liste Document_Accounts.

L'objet Field_Category possède également une routine d'événement OnClick (lignes 265-268) et une routine d'événement OnRelease (lignes 256-264). Ces routines exécutent des fonctions similaires aux routines OnClick et OnRelease de l'objet Field_Account.

L'objet Document_Accounts est également associé aux routines OnClick (lignes 88-92) et OnRelease (lignes 93-95). Lorsque l'utilisateur clique sur un nom de compte dans cet objet, les catégories actuelles sont mises à jour, les catégories du compte choisi sont affichées et le nombre de catégories est mis à jour. La routine OnRelease active simplement l'objet Field_Category en anticipant que l'utilisateur voudra ajouter de nouvelles catégories au compte choisi.

L'objet Document_Categories ne possède qu'une routine OnClick (lignes 204-206). Elle définit le document de travail à Categories.

Le bouton DeleteAccount n'est associé qu'à une routine OnRelease (lignes 163-174). Lorsque l'utilisateur appuie et relâche le bouton gauche de la souris alors que le pointeur se trouve sur cet objet, cette routine s'exécute. Le fait d'en faire une routine OnRelease plutôt qu'une routine OnClick permet à l'utilisateur de changer d'avis sur la sélection après avoir cliqué sur le bouton de la souris en déplaçant le pointeur hors de l'objet avant de relâcher le bouton de la souris. La routine définit le document de travail approprié, affecte la variable DeletedAccount au nom du compte choisi, supprime le nom du compte, puis met à jour le nombre de comptes. Comme les catégories associées au compte supprimé ne sont plus valides, la routine efface le document Categories.AccountName associé au compte supprimé. Enfin, les informations relatives à la catégorie sont mises à jour. Le bouton DeleteCategory possède également une routine OnRelease (lignes 219-226). Elle supprime la catégorie choisie et met à jour les informations sur la catégorie, laissant Field_Category activé.

Le bouton SortAccount possède une routine OnRelease (lignes 187-192) qui met à jour la liste des catégories actuelles, fait de Accounts le document de travail, puis appelle la routine globale "Sort the Document". N'oubliez pas que le document de travail doit être défini avant d'appeler la routine de tri. Enfin, l'objet Field_Account est activé.

Le bouton SortCategory possède une routine OnRelease (lignes 239-245) qui fonctionne de manière similaire à la routine SortAccount OnRelease.

Enfin, la routine OnRelease (lignes 132-134) pour le bouton "OK" et la routine Occurred (lignes 281-283) pour l'élément de menu "OK" appellent simplement la routine globale "OK Accounts" décrite précédemment. Les routines équivalentes pour le bouton "Cancel" (lignes 147-150) et l'élément de menu "Cancel" (lignes 296-298) vont dans une autre carte nommée "Intro" (non traitée dans cet article).

J'espère que cet extrait de programme CanDo vous a permis de voir à quel point les variables définies par l'utilisateur, associées à des pseudo-tableaux de documents, peuvent être utiles pour la programmation d'applications. De nombreux types d'applications différentes pourraient bénéficier des techniques discutées.

Tournons maintenant notre attention vers certaines des caractéristiques de CanDo qui facilitent la programmation des bases de données.

Programmation de la base de données

La figure 3 montre l'interface utilisateur d'une application de base de données simple. Le nom de la carte sur laquelle l'interface a été créée est "DataEntry" ; le programme est présenté dans le Listing 9.

CanDo 2.0
Figure 3 - carte "DataEntry"

L'interface se compose de cinq objets TextField et de six objets TextButton. Les objets TextField sont utilisés pour saisir les noms et les adresses. Chaque combinaison nom/adresse est appelée un enregistrement. Les objets TextButton sont utilisés pour ajouter un nouvel enregistrement, supprimer un enregistrement existant, afficher l'enregistrement précédent, afficher l'enregistrement suivant, charger la base de données depuis le disque et enregistrer la base de données sur le disque.

Listing 9. Routines d'interface d'information et d'événements
                pour la carte DataEntry dans CanDo 2.0

    1 *************
    2 * Deck "CanDo-Part2-Program2"
    3 * Time 18:48:16
    4 * Date 06/27/93
    5 *************
    6 
    7 *************
    8 * Card(s) in deck.
    9 *  Card "DataEntry"
   10 *************
   11 * 1 Card(s), 1 were printed.
   12 *************
   13 
   14 *************
   15 * Natural order of Cards
   16 *  Card "DataEntry"
   17 *************
   18 
   19 *************
   20 * Global Routine(s) in deck.
   21 *  Routine "Show Record" (was not printed)
   22 *************
   23 * 1 Global routines(s), 0 were printed.
   24 *************
   25 
   26 *************
   27 * Card "DataEntry"
   28   AfterAttachment ; used to be AfterStartup
   29     SetPrintFont "ruby",12
   30     SetPrintStyle BOLD SHADOW ,2,3
   31     SetPen 1,0
   32     SetDrawMode JAM1 
   33     PrintText "   Name:",119,39
   34     PrintText "Address:",124,59
   35     PrintText "   City:",124,79
   36     PrintText "  State:",119,99
   37     PrintText "    Zip:",130,119
   38   EndScript
   39   Window "UserWindow"
   40     Definition
   41        Origin 0,0
   42        Size 640,200
   43        Title "Database Demo"
   44        NumberOfColors 4
   45        WindowColors 0,1,0 ; Detail, Block, Background
   46        WindowObjects CLOSEBUTTON 
   47        WindowFlags ACTIVATE SEPARATESCREEN TOFRONT 
   48     EndScript
   49     OnCloseButton
   50        Quit
   51     EndScript
   52   EndObject
   53   TextField ".Name"
   54     Definition
   55        Origin 214,40
   56        Size 221,8
   57        Justification LEFT 
   58        MaxFieldLength 32
   59        InitialText ""
   60        Border DOUBLEBEVEL ,2,1 ; BorderStyle, MainPen, ExtraPen
   61     EndScript
   62     OnRelease
   63        SetObjectState ".Address",ON
   64     EndScript
   65   EndObject
   66   TextField ".Address"
   67     Definition
   68        Origin 214,60
   69        Size 221,8
   70        Justification LEFT 
   71        MaxFieldLength 32
   72        InitialText ""
   73        Border DOUBLEBEVEL ,2,1 ; BorderStyle, MainPen, ExtraPen
   74     EndScript
   75     OnRelease
   76        SetObjectState ".City",ON
   77     EndScript
   78   EndObject
   79   TextField ".City"
   80     Definition
   81        Origin 214,80
   82        Size 221,8
   83        Justification LEFT 
   84        MaxFieldLength 32
   85        InitialText ""
   86        Border DOUBLEBEVEL ,2,1 ; BorderStyle, MainPen, ExtraPen
   87     EndScript
   88     OnRelease
   89        SetObjectState ".State",ON
   90     EndScript
   91   EndObject
   92   TextField ".State"
   93     Definition
   94        Origin 214,100
   95        Size 221,8
   96        Justification LEFT 
   97        MaxFieldLength 32
   98        InitialText ""
   99        Border DOUBLEBEVEL ,2,1 ; BorderStyle, MainPen, ExtraPen
  100     EndScript
  101     OnRelease
  102        SetObjectState ".ZipCode",ON
  103     EndScript
  104   EndObject
  105   TextField ".ZipCode"
  106     Definition
  107        Origin 214,120
  108        Size 221,8
  109        Justification LEFT 
  110        MaxFieldLength 32
  111        InitialText ""
  112        Border DOUBLEBEVEL ,2,1 ; BorderStyle, MainPen, ExtraPen
  113     EndScript
  114     OnRelease
  115        SetObjectState ".Name",ON
  116     EndScript
  117   EndObject
  118   TextButton "Add"
  119     Definition
  120        Origin 107,155
  121        Font "System",8 ; FontName, PointSize
  122        PrintStyle SHADOW ,2,3 ; Style, Pen1, Pen2
  123        TextColors 1,0,NORMAL  ; PenA, PenB, DrawMode
  124        Text " Add "
  125        Border BEVEL ,2,1 ; BorderStyle, MainPen, ExtraPen
  126        Highlight COMPLEMENT 
  127        ButtonFlags NONE 
  128     EndScript
  129     OnRelease
  130        Let Address[CurIndex]=GetDBObjects  ;store current entry
  131        Let CurIndex=CurIndex+1             ;get next index number
  132        InsertArrayEntry Address,CurIndex   ;insert new index in array
  133        Do "Show Record"                    ;show a blank record
  134     EndScript
  135   EndObject
  136   TextButton "Delete"
  137     Definition
  138        Origin 177,155
  139        Font "System",8 ; FontName, PointSize
  140        PrintStyle SHADOW ,2,3 ; Style, Pen1, Pen2
  141        TextColors 1,0,NORMAL  ; PenA, PenB, DrawMode
  142        Text " Del "
  143        Border BEVEL ,2,1 ; BorderStyle, MainPen, ExtraPen
  144        Highlight COMPLEMENT 
  145        ButtonFlags NONE 
  146     EndScript
  147     OnRelease
  148        DeleteArrayEntry Address,CurIndex        ;delete record
  149        If VarType(Address[CurIndex])="Nothing"  ;see if last
  150           Let CurIndex=LastArrayIndex(Address)  ;find new last
  151        EndIf
  152        Do "Show Record"
  153     EndScript
  154   EndObject
  155   TextButton "Prev"
  156     Definition
  157        Origin 247,155
  158        Font "System",8 ; FontName, PointSize
  159        PrintStyle SHADOW ,2,3 ; Style, Pen1, Pen2
  160        TextColors 1,0,NORMAL  ; PenA, PenB, DrawMode
  161        Text " Prev "
  162        Border BEVEL ,2,1 ; BorderStyle, MainPen, ExtraPen
  163        Highlight COMPLEMENT 
  164        ButtonFlags NONE 
  165     EndScript
  166     OnRelease
  167        Let Address[CurIndex]=GetDBObjects                 ;save current record
  168        Let CurIndex=PreviousArrayIndex(Address,CurIndex)  ;get previous record
  169        If Not SearchFound                                 ;if no previous record
  170           Let CurIndex=LastArrayIndex(Address)            ;go to last record
  171        EndIf
  172        Do "Show Record"
  173     EndScript
  174   EndObject
  175   TextButton "Next"
  176     Definition
  177        Origin 327,155
  178        Font "System",8 ; FontName, PointSize
  179        PrintStyle SHADOW ,2,3 ; Style, Pen1, Pen2
  180        TextColors 1,0,NORMAL  ; PenA, PenB, DrawMode
  181        Text " Next "
  182        Border BEVEL ,2,1 ; BorderStyle, MainPen, ExtraPen
  183        Highlight COMPLEMENT 
  184        ButtonFlags NONE 
  185     EndScript
  186     OnRelease
  187        Let Address[CurIndex]=GetDBObjects            ;save current record
  188        Let CurIndex=NextArrayIndex(Address,CurIndex) ;get next record
  189        If Not SearchFound                            ;if no next record
  190           Let CurIndex=FirstArrayIndex(Address)      ;go to first record
  191        EndIf
  192        Do "Show Record"
  193     EndScript
  194   EndObject
  195   TextButton "Load"
  196     Definition
  197        Origin 407,155
  198        Font "System",8 ; FontName, PointSize
  199        PrintStyle SHADOW ,2,3 ; Style, Pen1, Pen2
  200        TextColors 1,0,NORMAL  ; PenA, PenB, DrawMode
  201        Text " Load "
  202        Border BEVEL ,2,1 ; BorderStyle, MainPen, ExtraPen
  203        Highlight COMPLEMENT 
  204        ButtonFlags NONE 
  205     EndScript
  206     OnRelease
  207        Dispose Address                                    ;delete current database
  208        Let FN=AskForFileName("","Load an Address File")   ;get a filename
  209        If Exists(FN)                                      ;if file exists
  210           Let Address=LoadVariable(FN)                    ;load it
  211        EndIf
  212        Let CurIndex=FirstArrayIndex(Address)              ;go to first record
  213        Do "Show Record"
  214     EndScript
  215   EndObject
  216   TextButton "Save"
  217     Definition
  218        Origin 487,155
  219        Font "System",8 ; FontName, PointSize
  220        PrintStyle SHADOW ,2,3 ; Style, Pen1, Pen2
  221        TextColors 1,0,NORMAL  ; PenA, PenB, DrawMode
  222        Text " Save "
  223        Border BEVEL ,2,1 ; BorderStyle, MainPen, ExtraPen
  224        Highlight COMPLEMENT 
  225        ButtonFlags NONE 
  226     EndScript
  227     OnRelease
  228        Let Address[CurIndex]=GetDBObjects                 ;store current record
  229        Let FN=AskForFileName("","Save an Address File")   ;get a filename
  230        SaveVariable Address,FN                            ;save it
  231     EndScript
  232   EndObject
  233 * End of Card "DataEntry"
  234 *************

Remarquez dans le Listing 9 que les noms de tous les objets TextField ont quelque chose en commun : ils commencent tous par un point. Ils sont nommés ".Name" (.nom), ".Address" (.adresse), ".City" (.ville), ".State" (.état) et ".ZipCode" (.codepostal). Lorsque les noms de ces champs commencent par un point, certaines commandes spéciales sont disponibles pour déplacer les données des champs vers des variables définies par l'utilisateur et vice versa. Le principal nom de variable utilisé dans le programme est "Address". Sa structure est la suivante :

Address[].Name
Address[].Address
Address[].City
Address[].State
Address[].ZipCode

Il s'agit d'un tableau dynamique d'adresses. Remarquez que tous les noms des extensions correspondent aux noms des objets TextField de la carte DataEntry. Cela est nécessaire pour que les commandes spéciales de la base de données fonctionnent correctement (cependant, c'est essentiellement un point discutable puisque les variables définies par l'utilisateur ne doivent pas être prédéfinies).

Chaque objet TextField possède une routine OnRelease qui active simplement le champ suivant à l'écran. Ainsi, si l'utilisateur tape un nom dans le champ ".Name" et appuie sur "Entrée", le champ ".Address" sera activé et ainsi de suite. Cela permet à l'utilisateur de saisir facilement les données d'un enregistrement sans avoir à activer chaque champ par un clic de souris. Lorsque l'utilisateur appuie sur la touche "Entrée" dans le champ ".ZipCode", le champ ".Name" est réactivé. Les six objets TextButton sont également associés à des routines OnRelease. Examinons-les dans l'ordre.

Le bouton "Add" est utilisé pour ajouter un autre enregistrement à la variable "Address". La routine OnRelease (lignes 129 à 134) utilise la variable système GetDBObjects. Cette variable, lorsqu'elle est affectée à l'enregistrement actuel de la variable "Address", qui est numérotée "CurIndex", déplace les valeurs de tous les champs spécialement nommés de la carte DataEntry dans la variable "Address" (sympa, non ?). Cela permet, en substance, de stocker l'enregistrement actuellement affiché. Ensuite, CurIndex est incrémenté, un nouvel enregistrement vide est inséré dans le tableau "Address" à l'aide de la commande "InsertArrayEntry", et la routine globale "Show Record" est appelée pour afficher à l'écran cet enregistrement vide nouvellement inséré, prêt à être saisi par l'utilisateur.

Le Listing 10 présente la routine globale "Show Record". Elle utilise la commande SetDBObjects. Cette commande extrait l'enregistrement actuel de la variable "Address" et affiche les composants de l'enregistrement dans les champs appropriés de la carte. Ensuite, le titre de la fenêtre de la carte est modifié pour refléter le nouveau numéro d'enregistrement, et le champ ".Name" est activé, dans l'attente d'une saisie supplémentaire de l'utilisateur.

Listing 10. Routine globale "Show Record"

    1 *************
    2 * Global routine "Show Record"
    3   SetDBObjects Address[CurIndex]                     ;show the record
    4   SetWindowTitle "Database Demo:  Record #"||CurIndex     ;show record number
    5   SetObjectState ".Name",ON                          ;put cursor in Name Field
    6 * End of routine "Show Record"
    7 *************

Revenons maintenant au Listing 9 et au bouton "Delete" (supprimer). La routine OnRelease (lignes 147-153) de ce bouton supprime d'abord l'enregistrement en cours à l'aide de la commande DeleteArrayIndex. Si l'enregistrement supprimé est le dernier de la base de données, alors le type de variable (obtenu avec la fonction VarType) de Address[CurIndex] sera désormais égal à "Nothing" (rien) puisqu'il n'existe pas. Si c'est le cas, la fonction LastArrayIndex est utilisée pour déterminer l'indice réel du dernier enregistrement dans la variable "Address". Cette valeur est affectée à CurIndex. Enfin, cet enregistrement est affiché.

La routine OnRelease du bouton "Prev" (lignes 166-173) stocke l'enregistrement actuel, détermine le numéro de l'enregistrement précédent à l'aide de la fonction PreviousArrayIndex, et affiche cet enregistrement. S'il n'y a pas d'enregistrement précédent, ce qui signifie que l'enregistrement actuellement affiché est le premier du tableau, la variable système SearchFound aura la valeur "FALSE" (FAUX) lorsque la fonction PreviousArrayIndex sera exécutée. Dans ce cas, l'enregistrement actuel est défini comme le dernier enregistrement de la base de données.

La routine OnRelease du bouton "Next" (lignes 186-193) fonctionne de la même manière que la routine du bouton "Prev", sauf qu'elle effectue une recherche en avant dans le tableau en utilisant la fonction NextArrayIndex. S'il n'y a pas d'enregistrement suivant, alors le premier enregistrement est affiché. Ceci, en combinaison avec le bouclage du premier au dernier du bouton "Prev", rend la base de données circulaire plutôt que linéaire. C'est comme autoriser un écart Roi-As-Deux au rami.

La routine OnRelease du bouton "Load" (lignes 206-214) supprime toutes les données de la variable "Address" à l'aide de la commande Dispose. Elle utilise ensuite la fonction AskForFilename pour afficher une requête de fichier à l'écran. Une fois que l'utilisateur a sélectionné un nom de fichier et fermé la requête, le nom du fichier est renvoyé à la variable "FN". Si ce fichier existe, il est chargé dans la variable "Address" à l'aide de la fonction LoadVariable, et le premier enregistrement est affiché.

Enfin, la routine OnRelease du bouton "Save" (lignes 227-231) stocke l'enregistrement actuellement affiché, obtient un nom de fichier de la part de l'utilisateur, puis utilise la commande SaveVariable pour enregistrer les données de la variable "Address" dans le fichier.

Bien entendu, ce programme de base de données est très simple et d'autres codes doivent être ajoutés pour en faire un programme utilisable. Cependant, mon intention est de vous aider à vous familiariser avec l'utilisation des commandes et fonctions spéciales de la base de données.

Commentaires de conclusion

Eh bien, c'est suffisant, vous ne pensez pas ? Vous êtes probablement fatigué de lire, et je sais que je suis fatigué de taper sur ces fichues touches de clavier de mon ordinateur. J'espère que cet article vous a aidé à apprécier les outils inestimables disponibles dans CanDo pour écrire des logiciels pour Amiga.


[Retour en haut] / [Retour aux articles]