Revenir au plan du site
Gestion d'un champ texte
On conserve notre structure
s_gui commune et on voit ce dont nous allons avoir besoin pour gérer un champ texte.
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_saisietexte
struct s_gui gui ; commun à tous les objets de la GUI
adresse_ecran defw ; position écran
contenu defs 20 ; contenu texte
terminateur defb 0 ; terminateur du contenu
longueur defb 20
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
checkboxchar defb ; caractère réservé pour afficher la checkbox
libelle defs 20
endstruct
|
Contrairement à la checkbox, la gestion d'une saisie texte va évidemment être plus complexe. On change le contenu de notre objet! Il va
falloir gérer un curseur (simple) pour l'édition, pouvoir effacer, limiter à la taille du contenu... Par contre, la gestion du curseur, du moins
ses coordonnées peuvent être mutualisées entre tous les objets ayant besoin d'un curseur, on le placera dans le code de gestion générale.
Pour la récupération du curseur, j'ai fait un truc qui me plait moyen pour le moment, à voir avec la suite de la GUI si on va le garder en l'état :
- Le curseur donne l'emplacement du caractère à venir, qui n'est pas encore tapé sauf...
- Sauf si le curseur est au maximum de la chaine, alors il vaut 1 de moins, pour écraser le dernier et ne pas déborder.
On a donc deux curseurs, le premier qui est celui des caractères à venir et celui réel, dont on a besoin pour effacer.
GUISaisieTexteGestion cp CODE_MORT : ret z
cp CODE_INIT : jr z,GUIsaisieTexteAffiche
cp CODE_DEL : jp z,.suppressionChar
cp CODE_TAB : jp z,GUIObjetSuivant
; si c'est un caractère on essaie de l'ajouter
cp 32 : ret c ; c'est un autre code de contrôle
; c'est un caractère, on l'ajoute (ou pas)
.ajouteChar
exa : call .recupereCurseur
cp (ix+s_saisieTexte.longueur) : ret z ; contenu déjà rempli au maximum
ld de,ix : ld hl,s_saisieTexte.contenu : add hl,de : add l : ld l,a : ld a,h : adc 0 : ld h,a : exa : ld (hl),a : inc hl : ld (hl),0
jp GUIsaisieTexteAffiche
.suppressionChar
call .recupereCurseur : ld a,(GUIcurseurDel)
or a : ret z ; déjà plus rien dans le contenu
dec a : ld de,ix : ld hl,s_saisieTexte.contenu : add hl,de : add l : ld l,a : ld a,h : adc 0 : ld h,a : ld (hl),' ' : push hl : call GUIsaisieTexteAffiche : pop hl : ld (hl),0 : jp GUIsaisieTexteAffiche
ret
; s'assurer que le curseur n'est pas en dehors des clous en le maximisant à la position du dernier char
.recupereCurseur ld hl,s_saisietexte.contenu : ld de,ix : add hl,de : call strlen ; longueur de chaine dans HL
ld a,(ix+s_saisietexte.longueur) : cp l : ld a,l : ld (GUIcurseurDel),a : jr nz,.forceCurseur : dec l : .forceCurseur ld a,l : ld (GUIcurseur),a
ret
GUIsaisieTexteAffiche
ld hl,(ix+s_saisieTexte.adresse_ecran) : ld de,80 : add hl,de ; ligne du dessous pour le surlignage
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)
jp GUIDisplayString
|
La gestion globale est un peu remaniée (nouvelle fonte, système d'activation/désactivation lors de changement de champ)
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 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 ld de,(ix+s_gui.suivant) : ld ix,de : ld (ix+s_gui.selectionne),1 : ld (GUIStructureCourante),ix
ld a,CODE_INIT : ld hl,(ix+s_gui.gestion) : jp (hl) ; active le suivant
GUIStructureCourante defw Check1
GUIStructureTemp defw #1234
GUICurseur defb 0 ; curseur visible (avec saturation)
GUICurseurDel defb 0 ; curseur réel
GUICheckTMP defb 0,0
;------------------------------------------------------------------------------------------
; affichage des chaines de caractères
;------------------------------------------------------------------------------------------
; HL' libelle
; DE destination écran sur une adresse paire!
GUIDisplayString
exx : ld a,(hl) : or a : ret z : inc hl : exx ; A=caractère pseudo-ASCII
sub 32 : add a : ld l,a : ld a,0 : adc a : ld h,a : add hl,hl : add hl,hl : add hl,hl ; x16
ld bc,fonte_data : add hl,bc ; données du caractère
push de
ld b,8
.spriteLine
push de : ld a,(hl) : ld (de),a : inc l : inc e : ld a,(hl) : inc l : ld (de),a : pop de : expandNextLineDE (void)
djnz .spriteLine
pop de : inc de : inc de
jp GUIDisplayString
align 16
fonte_data incbin 'guiFonte.bin'
caractere_etendu='}'+1 ; les caractères étendus commencent après le dernier caractère ASCII standard
utf8remap 'â',caractere_etendu : caractere_etendu+=1 ; et on incrémente pour le suivant
utf8remap 'à',caractere_etendu : caractere_etendu+=1 ; etc.
utf8remap 'é',caractere_etendu : caractere_etendu+=1
utf8remap 'è',caractere_etendu : caractere_etendu+=1
utf8remap 'ê',caractere_etendu : caractere_etendu+=1
utf8remap 'ë',caractere_etendu : caractere_etendu+=1
utf8remap 'ô',caractere_etendu : caractere_etendu+=1
utf8remap 'ö',caractere_etendu : caractere_etendu+=1
utf8remap 'œ',caractere_etendu : caractere_etendu+=1
utf8remap 'æ',caractere_etendu : caractere_etendu+=1
utf8remap 'î',caractere_etendu : caractere_etendu+=1
utf8remap 'ï',caractere_etendu : caractere_etendu+=1
utf8remap 'ü',caractere_etendu : caractere_etendu+=1
utf8remap 'ù',caractere_etendu : caractere_etendu+=1
utf8remap 'û',caractere_etendu : caractere_etendu+=1
utf8remap 'Ç',caractere_etendu : caractere_etendu+=1
utf8remap '«',caractere_etendu : caractere_etendu+=1
utf8remap '»',caractere_etendu : caractere_etendu+=1
utf8remap '£',caractere_etendu : caractere_etendu+=1
utf8remap 'Æ',caractere_etendu : caractere_etendu+=1
utf8remap 'Œ',caractere_etendu : caractere_etendu+=1
checkBoxsprites=caractere_etendu : caractere_etendu+=4 ; 4 checkboxes
|
On vient de définir tout ce dont nous aurons besoin pour notre nouveau type d'objet et ce qui va être "magique", c'est que notre
programme principal ne va pas changer. On a notre boucle qui gère le clavier et appelle une routine de gestion. C'est tout.
Avant d'assembler ce source, vous devrez télécharger les fichiers
[ guiStructure.asm ],
[ guiGlobal.asm ],
[ guiCheckBox.asm ],
[ guiSaisieTexte.asm ],
[ libChaines.asm ]
dans lesquels j'ai mis nos structures, les fonctions communes et la gestion par objet. Et puis la
[ fonte ] bien sûr!
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
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)
include 'guiStructure.asm'
include 'guiCheckBox.asm'
include 'guiSaisieTexte.asm'
include 'guiGlobal.asm'
include 'guiKeyboard.asm'
include 'libChaines.asm'
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,Text3,Check1,#C000+80*1,0,'Deuxième coche'
struct s_checkbox Text3 ,1,GUISaisieTexteGestion,0,Check4,Check2,#C000+80*2,0,0,20 ; champ vide et longueur 20
struct s_checkbox Check4,1,GUICheckBoxGestion ,0,Check1,Text3,#C000+80*3,0,'Quatrième coche'
|
Et voilà notre interface qui fonctionne "toute seule", avec la gestion des champes, la bascule d'un champ à l'autre quel que soit son type, le surlignage, etc.