Matérialiser l'enregistrement courant dans un cadre de table

Il est relativement commun d'avoir à saisir des données relatives à un enregistrement pointé dans un cadre de table, en dehors du cadre de table lui-même. Par exemple, les champ Mémo sont souvent déportés hors du cadre de table pour des raisons de lisibilité. Un modèle relationnel 1,n, représenté par deux cadres de tables, contraint l'utilisateur à sortir du cadre représentant l'enregistrement maître, pour saisir des informations dans la table enfant. Dans cette situation, on perd visuellement la position de l'enregistrement dont dépendent les données en cours de saisie ou de consultation. Paradox ne propose pas d'outils naturels permettant de remédier à cette gêne. Il est évidemment possible de sortir - ou de rappeler - l'identifiant de l'enregistrement maître hors du cadre de table.

Nous proposons deux autres solutions permettant de pointer visuellement l'enregistrement courant d'un cadre de table. La première solution est la plus performante en terme de rapidité d'exécution : elle est moins visuelle mais plus facile à mettre en place. La seconde solution est plus facilement paramétrable et permet d'agir sur chacun des objets inclus dans l'enregistrement (champs, boutons \'85).

 

La première solution consiste à déplacer un objet sur un bord du cadre, en lui assignant la même position verticale que l'enregistrement lui-même. C'est la proposition standard d'Access. Pour cela, il suffit de grouper l'objet et le cadre de table, d'ouvrir deux variables de type UIObject, sur l'objet à déplacer et sur l'objet enregistrement. Lors de l'arrivée sur le cadre de table, on récupère alors la position relative verticale et la taille de l'enregistrement pour les assigner à l'objet à déplacer.

Un cadre de table posé directement dans une fiche donne un nom particulier à chaque enregistrement du cadre de table. Pour fixer l'Uiobject enregistrement, il est donc nécessaire de renommer l'objet enregistrement.

 

Dans notre exemple, l'objet à déplacer est un bouton nommé " BOUTON ". L'objet enregistrement du cadre de table est renommé " ENREGISTREMENT ".

 

Dans l'objet groupe, plus petit conteneur de OBJET et ENREGISTREMENT, sont déclarés deux variables de types UIObject, BTUI pour le BOUTON et EnrUI pour l'ENREGISTREMENT. Elles sont pointées à l'ouverture de l'objet groupe:


Method Open(var eventInfo Event)
BTUI.attach(BOUTON)
EnrUI.attach(ENREGISTREMENT)
Endmethod

Une méthode BTLigne est crée dans le cadre de table :


method BTligne()
VAR
BTPosPT, BTTaillePT,
EnrPosPT, EnrTaillePT
Point
ENDVAR

BTPosPT = BTUI.position;Récupération de la position initiale du bouton
BTTaillePT = BTUI.size;Récupération de la position initiale du bouton
EnrPosPT = EnrUI.position;Récupération de la position de l'enregistrement
EnrTaillePT = EnrUI.size;Récupération de la taille de l'enregistrement
BTPosPT = point(BTPosPT.x(), EnrPosPT.y());Assignation de la positionhorizontale du bouton et verticale de l'enregistrement dans une variable
BTTaillePT = point(BTTaillePT.x(), EnrTaillePT.y());Assignation de lalargeur du bouton et de la hauteur de l'enregistrement dans une variable
BTUI.position  = BTPosPT;Le bouton prend sa nouvelle position verticale et garde sa position horizontale
BTUI.Size  = BTTaillePT;Le bouton prend la même hauteur que l'enregistrement et garde sa largeur.
Endmethod

Pour synchroniser la position du bouton et celle de l'enregistrement courant, il ne suffit plus que de déclencher la méthode Btligne sur les actions de mouvement du cadre de table :


method action(var eventInfo ActionEvent)
If eventInfo.id() = DataArriveRecord then
   btligne()
endif
EndMethod

Notre seconde proposition est un peu plus lourde à mettre en place, et également un peu moins efficace en terme de rapidité d'exécution. Ce dernier point ne sera cependant pas pris en compte lors du choix de la mise place de l'une ou l'autre solution, les temps de réponse étant dans les deux cas négligeables par rapport au temps de rafraîchissement d'un cadre de table.

Cette solution, beaucoup plus visuelle, permet en outre d'agir sur tous les objets contenus dans le cadre de table. Elle consiste à forcer un nom distinct à chaque ligne (objet " Enregistrement ") du cadre de table et à lui assigner des propriétés visuelles dans le cas d'un DataArriveRecord().

Toutes les variables sont définies dans l'objet Cadre de table :


Var
NumSI
Smallint
NomAR
Array[] string
OrigineST
String
RSI,
GSI,
BSI
smallint
RgbLI
Longint
Namest
string
ObjAR
Array[] string
debLO
Logical
endvar

Lors de l'ouverture de chaque enregistrement, on donne un nom distincts à tous les objets " Enregistrement " :


method open(var eventInfo Event) ;
Var
ChampUI
UIobject
ST
String
endvar

Dans le cas du premier enregistrement, on récupère les objets dans un tableau et on ne change pas le nom de l'enregistrement :


If not NumSI.isassigned() then
OrigineST=Self.name
NumSI=1
ChampUI.attach(self)
ChampUI.enumObjectNames(ObjAR)
For n from 2 to ObjAR.size()
ObjAR[n].Match(ChampUI.fullname+"..",ST)
ObjAR[n]=ST.substr(2,st.size())
If ObjAR[n].Match("#",ST) then
ObjAR[n]=ST
endif
endfor
debLO=False
endif
; définition de noms définis pour chaque enregistrement et stockage de ces noms dans un tableau
If NumSI<>1 then
Self.name=self.name+strval(NumSI)
getrgb(Self.Color,RSI,GSI,BSI)
endif
NomAR.grow(1)
NomAR[NumSI] = Self.FullName
NumSI=NumSI+1
EndMethod

La méthode action du cadre de table déclenche l'appel de la procédure de coloration s'il s'agit d'un déplacement dans le tableau :


method action(var eventInfo ActionEvent)
If eventInfo.id() = DataArriveRecord Then
ColLignes(Self.RowNo);La ligne est passée en paramètre à la methode ColLigne
Endif
EndMethod()

Enfin, la methode ColLignes colore et décolore les objets du tableFrame :


Proc color(var cUI UIobject)
var
ui
UIobject
endvar

ui.attach(cUI)
;Enregistrement courant en Bleu
ui.color=DarkBlue
;Coloration des objets présents dans le cadre de table en fonction de paramètres modifiables.
;Ici, les champs en lecture seule apparaissent en blanc sur fond bleu.
for n from 2 to ObjAR.size()
ui.attach(ObjAR[n])
If UI.Class<> "Field" then loop endif
If UI.DisplayType<>"EditField" then loop endif
If ui.ReadOnly<>False then
ui.font.color=White
ui.Translucent=True
endif
endfor
endproc

Proc decolor(var cUI UIobject)
var
ui
UIobject
st
string
endvar
;Récupération de la couleur initiale de l'enregistrement \'85
ui.attach(cUI)
ui.color=rgb(RSI,GSI,BSI)
;\'85 et des objets dépendants
for n from 2 to ObjAR.size()
ui.attach(Cui.name+"."+ObjAR[n])
If UI.Class<> "Field" then loop endif
If UI.DisplayType<>"EditField" then loop endif
If ui.ReadOnly<>False then
ui.font.color=Black
ui.Translucent=False
endif
endfor
endproc

method ColLignes(RowSI SmallInt)
VAR
PriorUI, EnrUI UIObject
ENDVAR
try
If NomAR.size() = 0 Then
Return
EndIf
EnrUI.attach(NomAR[RowSI]);Récupération de l'enregistrement à colorer
If nameST.isAssigned() then
PriorUI.attach(nameST); Si un autre objet est coloré, décoloration
Decolor(PriorUI)
endif
Color(EnrUI)
Switch
case NomAR[RowSI]=NomAR[NomAR.size()]:;Gestion des premiers et derniers
PriorUI.attach(NomAR[NomAR.size()-1]);Gestion des premiers et derniers
decolor(PriorUI) ;
Case NomAR[RowSI]=NomAR[1]:
PriorUI.attach(NomAR[2])
decolor(PriorUI);
Otherwise:
Endswitch
nameST=NomAR[RowSI];Prochaine ligne à décolorer
;En cas d'erreur (suppression des enregistrements par empty() par exemple), on perd l'enregistrement courant.
;Il faut alors décolorer tous les enregistrements, ils seront recolorés dans la methode action.
onfail
For n from 1 to NomAR.size()
EnrUI.attach(NomAR[n])
Decolor(EnrUI)
endfor
endtry