Revenir au plan du site

Factorisation des actions communes et petites améliorations


Au début de nos deux objets, nous testons plusieurs codes pour les mêmes raisons (et nous allons en ajouter d'autres...). On va alléger notre source en se faisant une macro reprenant les actions communes. Cela permet aussi de faire évoluer ces actions sans devoir revenir dans chacun des objets.

macro GuiObjetActionParDefaut
.gestion
cp CODE_MORT : ret z
cp 32 : jr nc,.texte
cp CODE_INIT : jp z,.affiche
cp CODE_TAB : jp z,GUIObjetSuivant
cp CODE_TAB_INVERSE : jp z,GUIObjetPrecedent
mend

Le TAB_INVERSE nous permettra de passer à l'objet précédent si on fait SHIFT+TAB, pour cela nous allons modifier notre table de touches. Le TAB est sur la 8è ligne.
.shift48 defb 'W',CODE_MORT,'Q',CODE_TAB_INVERSE,'A',CODE_ESC,'21'

Il faudra lui attribuer une valeur libre inférieure à 32 dans guiKeyboard.asm
CODE_TAB_INVERSE equ 14

L'apparition de la fonction GUIObjetPrecedent se passe dans la gestion globale qu'on va légèrement modifier. En fonction de l'action, on charge soit l'objet précédent, soit le suivant et tout le reste du code va suivre.
GUIObjetPrecedent ld hl,(ix+s_gui.precedent) : jr GUIObjet
GUIObjetSuivant ld hl,(ix+s_gui.suivant)
GUIObjet
push hl ; on pousse dans la pile l'objet suivant ou précédent
ld hl,.nouvelObjet : push hl
ld (ix+s_gui.selectionne),0 : ld a,CODE_INIT : ld hl,(ix+s_gui.gestion) : jp (hl) ; déselectionne le courant
.nouvelObjet pop ix /* suivant ou précédent */ : ld (ix+s_gui.selectionne),1 : ld (GUIStructureCourante),ix
ld a,CODE_INIT : ld hl,(ix+s_gui.gestion) : jp (hl) ; active l'objet

Pour le moment, nos objet sont organisés dans une liste chainée circulaire. On pourrait définir un objet neutre qui ne définisse qu'un champ suivant et qui affiche du texte, une image, que sais-je. On organiserait notre liste de façon à ce que les objets neutres (ou non interactifs) soient affichés en début de gestion mais ensuite, ils deviendraient automatiquement hors-liste.

Notre fonction d'initialisation ne change (presque) pas car elle sait se caler sur le premier champ actif. Par contre, nous allons appeler chaque fonction de gestion lors du scan de recherche.
;------------------------------------------------------------------------------------------
; gestion de la GUI
; IX=structure d'initialisation
;------------------------------------------------------------------------------------------
GUIInitialisation
ld hl,.chercheDepart : push hl : ld hl,(ix+s_gui.gestion) : ld a,CODE_INIT : jp (hl) : .chercheDepart
ld a,(ix+s_gui.selectionne) : or a : jr nz,.trouve
ld de,(ix+s_gui.suivant) : ld ix,de : jr GUIInitialisation
.trouve ; on est positionné sur le champ à sélectionner

ld (GUIStructureCourante),ix ; la courante pour la gestion
ld (GUIStructureTemp),ix ; référence
.afficheTout
ld hl,.afficheSuivant : push hl : ld hl,(ix+s_gui.gestion) : ld a,CODE_INIT : jp (hl) : .afficheSuivant

ld de,(ix+s_gui.suivant) : ld hl,(GUIStructureTemp) : xor a : sbc hl,de : ld ix,de
jr nz,.afficheTout
ret

Tant que j'y étais, j'ai embelli la saisie texte pour avoir un petit curseur en surimpression, plus lisible. La suppression d'un char n'affiche plus deux fois de suite avec l'espace mais par contre, on va effacer l'ensemble du champ avant de le rafraichir.
GUIsaisieTexteAffiche
ld hl,(ix+s_saisieTexte.adresse_ecran) : ld a,8 : ld de,8
ld c,(ix+s_saisieTexte.longueur) : sla c
.razLine
ld b,c
push hl : .raz ld (hl),d : inc hl : djnz .raz : pop hl : ld a,h : add 8 : ld h,a
dec e : jr nz,.razLine

ld hl,(ix+s_saisieTexte.adresse_ecran) : ld de,80 : add hl,de ; ligne du dessous
ld a,(ix+s_gui.selectionne) : dec a : cpl : ld b,(ix+s_saisieTexte.longueur) : sla b
.surligne ld (hl),a : inc hl : djnz .surligne

ld de,ix : ld hl,s_saisieTexte.contenu : add hl,de : exx
ld de,(ix+s_saisieTexte.adresse_ecran)
call GUIDisplayString

; curseur
call GUISaisieTexteGestion.recupereCurseur
ld a,(ix+s_gui.selectionne) : or a : ret z
ld hl,(ix+s_saisieTexte.adresse_ecran) : ld d,8*4 : ld a,(GUIcurseur) : add a : ld e,a : add hl,de : ld b,4
.inverse
ld a,(hl) : or #F0 : ld (hl),a : inc l : ld a,(hl) : or #F0 : ld (hl),a : dec l : ld a,h : add 8 : ld h,a : djnz .inverse
ret

Et voilà notre nouveau curseur :)


Nous sommes prêts à ajouter de nouveaux objets, si on s'occupait [ d'un nouveau champ numérique ]?