Grilles et graphes
Module d’exemple : hellogrid.
Un graphe n’est pas un mécanisme à part : c’est une visualisation d’une grille existante. Tout commence donc par la grille.
Le mécanisme de base : un instantané répété
Une grille n’est qu’un instantané répété des éléments de base de sa propre propriété — il n’existe aucune API pour “ajouter une ligne avec ces valeurs-là” directement :
getEltInt("mesures", "t")->setValue(t, false);
getEltFloat("mesures", "valeur")->setValue(v, false);
getProperty("mesures")->push(); // copie l'état courant des éléments en nouvelle ligne
clearGrid()réinitialise la grille.gridLimit(clé JSON) plafonne le nombre de lignes : au-delà, la plus ancienne est retirée silencieusement (FIFO).
"mesures": {
"hasGrid": true,
"showGrid": true,
"showElts": false,
"gridLimit": 30,
"e": {
"t": { "type": "int" },
"valeur": { "type": "float" }
}
}showGrid: affiche la grille elle-même.showElts: affiche le formulaire des éléments de base (le “brouillon” avantpush()). Généralement caché (false) quand c’est le module qui pousse les lignes.
CRUD générique, sans aucun code
Avec permission:2 (lecture/écriture) sur une propriété à grille, le client gagne gratuitement des contrôles de création/modification/suppression/réordonnancement des lignes — entièrement gérés par le framework, sans qu’aucun code ne soit nécessaire côté module :
| Événement | Méthode PropertyMulti appelée | Effet |
|---|---|---|
GC | newLine(valeurs) | Ajoute une ligne |
GU | updateLine(index, valeurs) | Modifie une ligne existante |
GD | deleteLine(index) | Supprime une ligne |
GF | fetchLine(index) | Recopie les valeurs de la ligne dans les éléments de base — “charger pour éditer” |
GH | swapLines(index, index-1) | Fait remonter une ligne d’un rang |
GB | swapLines(index, index+1) | Fait descendre une ligne d’un rang |
GR | clearGrid() | Vide la grille |
Le client type (interface ostcore) affiche déjà, pour toute propriété à grille non verrouillée en lecture seule : un bouton éditer (déclenche GF), monter/descendre (GH/GB), supprimer (GD), et un formulaire d’ajout/édition (GC/GU) — inconditionnellement, dès que showGrid et la permission le permettent. Avec showElts:true en plus, cliquer une ligne (hors des boutons d’action) déclenche aussi GF et charge ses valeurs dans le formulaire des éléments de base. C’est exactement ce que démontre déjà gridvisible dans le module d’exemple — aucun code supplémentaire à écrire pour bénéficier de tout ça.
Une grille peut être poussée par le module (lecture seule côté client, le serveur pousse les lignes au fil de l’eau — un historique de mesures, par exemple) ou gérée par le client (lecture/écriture, le CRUD générique ci-dessus — une liste de tâches, de cibles, de filtres…). Les deux patrons cohabitent dans la même mécanique, seule la permission change.
autoSelect / autoUpDown : réservés, pas encore câblés
PropertyMulti expose aussi autoSelect()/setAutoSelect() et autoUpDown()/setAutoUpDown() (clés JSON "autoselect"/"autoupdown"). Leur rôle visé : laisser le module prendre la main sur ce qui doit se passer quand l’utilisateur sélectionne une ligne ou en réordonne une — pas une affaire de présentation côté client, le client affiche ses contrôles de grille de la même façon dans tous les cas.
Ces deux réglages se stockent et se relisent, mais rien dans le framework ne les consulte encore pour de vrai — il n’existe aujourd’hui aucun point d’entrée (méthode virtuelle, événement) permettant à un module de réagir à une sélection ou un réordonnancement de ligne. Suivi dans ost/ostserver#270.
Un graphe est une grille, visualisée
graphType/graphParams exigent hasGrid:true — sans grille, pas de graphe.
XY : une courbe, ou un nuage de points
"courbe": {
"hasGrid": true, "showGrid": false, "showElts": false,
"gridLimit": 30,
"graphType": "XY",
"graphParams": { "X": "t", "Y": "valeur" }
}X/Y nomment les éléments de la grille à utiliser comme axes. Les points sont par défaut reliés par une ligne — pour un nuage de points sans relation d’ordre (des mesures non séquentielles, par exemple), ajouter "scatter": true dans graphParams désactive le tracé de la ligne, les points eux-mêmes restent affichés.
SDY : plusieurs séries, sur plusieurs axes
"graphType": "SDY",
"graphParams": {
"S": "serie", "D": "date", "Y": "valeur",
"graphColors": {
"temp": { "R": 255, "G": 0, "B": 0 },
"hum": { "R": 0, "G": 0, "B": 255 }
},
"axis": {
"gauche": { "pos": "left", "text": "Température" },
"droite": { "pos": "right", "text": "Humidité" }
},
"mapping": { "temp": "gauche", "hum": "droite" }
}Une seule grille, plusieurs séries nommées entrelacées — chaque ligne a sa propre valeur de série (S), un horodatage (D) et une valeur (Y). Pour alimenter deux séries à chaque échantillon, pousser une ligne par série :
getEltString("historique", "serie")->setValue("temp");
getEltDateTime("historique", "date")->setValue(maintenant, false);
getEltFloat("historique", "valeur")->setValue(temperature, false);
getProperty("historique")->push();
getEltString("historique", "serie")->setValue("hum");
getEltDateTime("historique", "date")->setValue(maintenant, false);
getEltFloat("historique", "valeur")->setValue(humidite, false);
getProperty("historique")->push();graphColors/axis/mapping permettent à deux séries d’échelles très différentes de ne pas s’écraser visuellement l’une l’autre, chacune sur son propre axe.