Revenir au plan du site

Gestion de plusieurs checkBox avec les prémices de fonctions réflexes...


Cette fois, nous allons utiliser la routine de gestion associée à notre structure, ainsi que les champs 'précédent' et 'suivant'. Et comme c'est susceptible de nous servir dans d'autres objets, on va encapsuler ces champs communs dans une autre structure.
struct s_gui
gestion defw ; routine de gestion
selectionne defb ; objet sélectionné ou non
suivant defw ; champ suivant
precedent defw ; champ precedent
endstruct

struct s_checkbox
struct s_gui gui ; commun à tous les objets de la GUI
adresse_ecran defw ; position écran
valeur defb ; cochée ou pas cochée
libelle defs 20
endstruct

On va déclarer 4 checkbox, ça ressemble à ce qu'on a déjà vu dans la création d'une [ petite gestion de menu ] avec les structures.
struct s_checkbox Check1,1,GUICheckBoxGestion,1,Check2,Check4,#C000+80*0,0,'Première coche' ; première sélectionnée
struct s_checkbox Check2,1,GUICheckBoxGestion,0,Check3,Check1,#C000+80*3,0,'Deuxième coche'
struct s_checkbox Check3,1,GUICheckBoxGestion,0,Check4,Check2,#C000+80*6,0,'Troisième coche'
struct s_checkbox Check4,1,GUICheckBoxGestion,0,Check1,Check3,#C000+80*9,0,'Quatrième coche'

Notre boucle principale de gestion va ressembler à ça, quel que soit le nombre de champs à gérer. À tout instant, on a l'adresse du champ courant et on appelle sans réfléchir la routine de gestion associée au champ en question.
Ainsi, quand on ajoutera d'autres types de champs, tout sera déjà géré par cette boucle.
laBoucle
halt 6 : call gererClavier
cp CODE_MORT : jr z,laBoucle
ld hl,laBoucle : push hl ; adresse de retour
ld ix,(GUIStructureCourante) : ld hl,(ix+s_checkbox.gui.gestion) : jp (hl)

Il reste à écrire quelques fonctions, notamment celle de la GUI qui va parcourir tous les champs et les afficher un à un. Pour notre checkBox, on va devoir ajouter la fonction qui passe au champ suivant.

Enfin, on compilera avec RASM et l'option -utf8 qui permet de compiler avec les caractères spéciaux de la fonte CPC Azerty.
buildsna : bankset 0
org #38 : ei : ret
org #100 : run #100 : ld sp,#100 : ei

MACRO expandNextLineDE
ld a,d : add 8 : ld d,a : and #38 : jr nz,@termine
ld a,80 : add e : ld e,a : ld a,#C0 : adc d : ld d,a : res 3,d
@termine
MEND

struct s_gui
gestion defw ; routine de gestion
selectionne defb ; objet sélectionné ou non
suivant defw ; champ suivant
precedent defw ; champ precedent
endstruct

struct s_checkbox
struct s_gui gui ; commun à tous les objets de la GUI
adresse_ecran defw ; position écran
valeur defb ; cochée ou pas cochée
libelle defs 20
endstruct

ld bc,#7F10 : out (c),c : ld a,#54 : out (c),a
ld bc,#7F00 : out (c),c : ld a,#54 : out (c),a
ld bc,#7F01 : out (c),c : ld a,#44 : out (c),a
ld bc,#7F02 : out (c),c : ld a,#5B : out (c),a
ld bc,#7F03 : out (c),c : ld a,#4B : out (c),a

call GUIInitialisation

laBoucle
halt 6 : call gererClavier
cp CODE_MORT : jr z,laBoucle
ld hl,laBoucle : push hl ; adresse de retour
ld ix,(GUIStructureCourante) : ld hl,(ix+s_gui.gestion) : jp (hl)

;------------------------------------------------------------------------------------------
; gestion de la checkBox
;------------------------------------------------------------------------------------------
GUICheckBoxGestion cp CODE_MORT : ret z
cp CODE_INIT : jr z,GUICheckBoxAffiche
cp ' ' : jr z,GUICheckBoxFlip ; on a une entrée clavier et c'est Espace, alors on permute la coche
cp CODE_TAB : jp z,GUIObjetSuivant
ret
GUICheckBoxFlip push af : ld a,(ix+s_checkbox.valeur) : inc a : and 1 : ld (ix+s_checkbox.valeur),a : call GUICheckBoxAffiche : pop af : ret

GUICheckBoxAffiche ld a,(ix+s_gui.selectionne) : add a : add (ix+s_checkbox.valeur) ; numéro de sprite de 0 à 3
add a : add a : ld e,a : add a : add a : add a : add e ; x36 qui est la taille du sprite
ld hl,checkBoxSprites : add l : ld l,a : ld a,h : adc 0 : ld h,a ; adresse du sprite
ld de,(ix+s_checkbox.adresse_ecran) : ld b,4 : .centrage expandNextLineDE (void) : djnz .centrage
ld bc,(12<<8)|#FF
.displayCheck push de : ldi 3 : pop de
expandNextLineDE (void)
djnz .displayCheck
push ix : pop hl : ld a,s_checkbox.libelle : add l : ld l,a : ld a,h : adc 0 : ld h,a : exx
ld hl,(ix+s_checkbox.adresse_ecran) : ld a,4 : add l : ld l,a : ex hl,de
jp GUIDisplayString

checkBoxSprites incbin 'GUICheckboxSprites.bin'

;------------------------------------------------------------------------------------------
; gestion de la GUI
;------------------------------------------------------------------------------------------
GUIInitialisation ld ix,(GUIStructureCourante)
.chercheDepart ld a,(ix+s_gui.selectionne) : or a : jr nz,.trouve
ld de,(ix+s_gui.suivant) : ld ix,de : jr .chercheDepart
.trouve ; on est positionné sur le champ à sélectionner
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

GUIObjetSuivant
ld de,(ix+s_gui.suivant) : ld (ix+s_gui.selectionne),0 : ld ix,de : ld (ix+s_gui.selectionne),1 : ld (GUIStructureCourante),ix : ret

GUIStructureCourante defw Check1
GUIStructureTemp defw #1234
;------------------------------------------------------------------------------------------
; affichage des chaines de caractères
;------------------------------------------------------------------------------------------

; HL' libelle
; DE destination écran
GUIDisplayString
exx : ld a,(hl) : or a : ret z : inc hl : exx ; A=caractère pseudo-ASCII
ld hl,fonte_idx>>2 : sub 32 : add l : ld l,a : add hl,hl : add hl,hl ; pointe dans l'index sur le descripteur de la lettre
push de
ld a,(hl) ; nombre de lignes à 'sauter'
push hl
or a : jr z,.displaySprite
ld b,a : xor a
.razLine
push de : ld (de),a : inc de : ld (de),a : pop de : exa : expandNextLineDE (void) : exa
djnz .razLine
.displaySprite
inc l : ld a,(hl) : or a : jr z,.skipChar ; espace...
ld b,a : inc l : ld a,(hl) : inc l : ld h,(hl) : ld l,a ; B=hauteur
add lo(referenceSprite) : ld l,a : ld a,h : adc hi(referenceSprite) : ld h,a ; HL=sprite du caractère
.spriteLine
push de : ld a,(hl) : ld (de),a : inc l : inc de : ld a,(hl) : inc hl : ld (de),a : pop de : expandNextLineDE (void)
djnz .spriteLine
.skipChar
; compléter le bas si besoin
pop hl : ld a,(hl) : inc l : add (hl) : ld b,a : ld a,21 : sub b : jr z,.dejaComplet
ld b,a : xor a
.razLine2
push de : ld (de),a : inc de : ld (de),a : pop de : exa : expandNextLineDE (void) : exa
djnz .razLine2
.dejaComplet
pop de : inc de : inc de
jp GUIDisplayString

align 2
fonte_data incbin 'FONTE21.DAT'
align 4
fonte_idx incbin 'FONTE21.IDX' ; encodée avec des lettres en #4000 (optimisée pour de la RAM à banker)

referenceSprite=fonte_data-#4000


struct s_checkbox Check1,1,GUICheckBoxGestion,1,Check2,Check4,#C000+80*0,0,'Première coche' ; première sélectionnée
struct s_checkbox Check2,1,GUICheckBoxGestion,0,Check3,Check1,#C000+80*3,0,'Deuxième coche'
struct s_checkbox Check3,1,GUICheckBoxGestion,0,Check4,Check2,#C000+80*6,0,'Troisième coche'
struct s_checkbox Check4,1,GUICheckBoxGestion,0,Check1,Check3,#C000+80*9,0,'Quatrième coche'

include 'GUIkeyboard.asm'

Et voilà, on passe de l'une à l'autre avec la touche TAB, on change la coche avec la touche espace.



La suite par ici avec [ une nouvelle fonte! ]