Griglie e grafici
Modulo di esempio: hellogrid.
Un grafico non è un meccanismo separato: è una visualizzazione di una griglia esistente. Tutto parte quindi dalla griglia.
Il meccanismo di base: un’istantanea ripetuta
Una griglia è solo un’istantanea ripetuta degli elementi di base della propria proprietà — non esiste alcuna API per “aggiungere una riga con questi valori” direttamente:
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()reinizializza la griglia.gridLimit(chiave JSON) imposta un tetto al numero di righe: oltre, la più vecchia viene rimossa silenziosamente (FIFO).
"mesures": {
"hasGrid": true,
"showGrid": true,
"showElts": false,
"gridLimit": 30,
"e": {
"t": { "type": "int" },
"valeur": { "type": "float" }
}
}showGrid: mostra la griglia stessa.showElts: mostra il form degli elementi di base (la “bozza” prima dipush()). Generalmente nascosto (false) quando è il modulo a spingere le righe.
CRUD generico, senza alcun codice
Con permission:2 (lettura/scrittura) su una proprietà con griglia, il client guadagna gratuitamente controlli di creazione/modifica/eliminazione/riordinamento delle righe — interamente gestiti dal framework, senza che sia necessario alcun codice lato modulo:
| Evento | Metodo PropertyMulti chiamato | Effetto |
|---|---|---|
GC | newLine(valeurs) | Aggiunge una riga |
GU | updateLine(index, valeurs) | Modifica una riga esistente |
GD | deleteLine(index) | Elimina una riga |
GF | fetchLine(index) | Ricopia i valori della riga negli elementi di base — “carica per modificare” |
GH | swapLines(index, index-1) | Fa risalire una riga di un rango |
GB | swapLines(index, index+1) | Fa scendere una riga di un rango |
GR | clearGrid() | Svuota la griglia |
Il client tipico (interfaccia ostcore) mostra già, per qualsiasi proprietà con griglia non bloccata in sola lettura: un pulsante modifica (attiva GF), sali/scendi (GH/GB), elimina (GD), e un form di aggiunta/modifica (GC/GU) — incondizionatamente, non appena showGrid e il permesso lo consentono. Con showElts:true in più, cliccare una riga (fuori dai pulsanti di azione) attiva anche GF e carica i suoi valori nel form degli elementi di base. È esattamente ciò che dimostra già gridvisible nel modulo di esempio — nessun codice supplementare da scrivere per beneficiarne.
Una griglia può essere spinta dal modulo (sola lettura lato client, il server spinge le righe col passare del tempo — una cronologia di misure, per esempio) oppure gestita dal client (lettura/scrittura, il CRUD generico sopra — una lista di task, di target, di filtri…). I due pattern convivono nella stessa meccanica, solo la permission cambia.
autoSelect / autoUpDown: riservati, non ancora cablati
PropertyMulti espone anche autoSelect()/setAutoSelect() e autoUpDown()/setAutoUpDown() (chiavi JSON "autoselect"/"autoupdown"). Il loro ruolo previsto: lasciare che il modulo prenda il controllo di ciò che deve accadere quando l’utente seleziona una riga o la riordina — non una questione di presentazione lato client, il client mostra i suoi controlli di griglia nello stesso modo in tutti i casi.
Queste due impostazioni si memorizzano e si rileggono, ma nulla nel framework le consulta ancora per davvero — non esiste oggi alcun punto di ingresso (metodo virtuale, evento) che permetta a un modulo di reagire a una selezione o a un riordinamento di riga. Monitorato in ost/ostserver#270.
Un grafico è una griglia, visualizzata
graphType/graphParams richiedono hasGrid:true — senza griglia, nessun grafico.
XY: una curva, o una nuvola di punti
"courbe": {
"hasGrid": true, "showGrid": false, "showElts": false,
"gridLimit": 30,
"graphType": "XY",
"graphParams": { "X": "t", "Y": "valeur" }
}X/Y nominano gli elementi della griglia da usare come assi. I punti sono per default collegati da una linea — per una nuvola di punti senza relazione d’ordine (misure non sequenziali, per esempio), aggiungere "scatter": true in graphParams disabilita il tracciamento della linea, i punti stessi restano visualizzati.
SDY: più serie, su più assi
"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" }
}Una sola griglia, più serie con nome intrecciate — ogni riga ha il proprio valore di serie (S), un timestamp (D) e un valore (Y). Per alimentare due serie a ogni campione, spingere una riga per serie:
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 permettono a due serie di scale molto diverse di non schiacciarsi visivamente l’una l’altra, ciascuna sul proprio asse.