Grids und Graphen
Beispielmodul: hellogrid.
Ein Graph ist kein eigenständiger Mechanismus: er ist eine Visualisierung eines bestehenden Grids. Alles beginnt also beim Grid.
Der Grundmechanismus: ein wiederholter Snapshot
Ein Grid ist nichts anderes als ein wiederholter Snapshot der Basiselemente seiner eigenen Property — es gibt keine API, um direkt “eine Zeile mit diesen Werten hinzuzufügen”:
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()setzt das Grid zurück.gridLimit(JSON-Schlüssel) begrenzt die Anzahl der Zeilen: darüber hinaus wird die älteste stillschweigend entfernt (FIFO).
"mesures": {
"hasGrid": true,
"showGrid": true,
"showElts": false,
"gridLimit": 30,
"e": {
"t": { "type": "int" },
"valeur": { "type": "float" }
}
}showGrid: zeigt das Grid selbst an.showElts: zeigt das Formular der Basiselemente (der “Entwurf” vorpush()). Normalerweise ausgeblendet (false), wenn es das Modul ist, das die Zeilen pusht.
Generisches CRUD, ohne jeglichen Code
Mit permission:2 (lesen/schreiben) auf einer Property mit Grid erhält der Client kostenlos Steuerelemente zum Erstellen/Ändern/Löschen/Neuordnen von Zeilen — vollständig vom Framework verwaltet, ohne dass auf Modulseite Code nötig wäre:
| Ereignis | Aufgerufene PropertyMulti-Methode | Effekt |
|---|---|---|
GC | newLine(valeurs) | Fügt eine Zeile hinzu |
GU | updateLine(index, valeurs) | Ändert eine bestehende Zeile |
GD | deleteLine(index) | Löscht eine Zeile |
GF | fetchLine(index) | Kopiert die Werte der Zeile in die Basiselemente zurück — “zum Bearbeiten laden” |
GH | swapLines(index, index-1) | Rückt eine Zeile einen Rang nach oben |
GB | swapLines(index, index+1) | Rückt eine Zeile einen Rang nach unten |
GR | clearGrid() | Leert das Grid |
Der typische Client (die ostcore-Oberfläche) zeigt für jede nicht auf nur-lesbar gesperrte Property mit Grid bereits an: einen Bearbeiten-Button (löst GF aus), Hoch/Runter (GH/GB), Löschen (GD), und ein Hinzufügen-/Bearbeiten-Formular (GC/GU) — bedingungslos, sobald showGrid und die Permission es erlauben. Mit zusätzlich showElts:true löst das Klicken einer Zeile (außerhalb der Aktions-Buttons) ebenfalls GF aus und lädt ihre Werte in das Formular der Basiselemente. Genau das demonstriert bereits gridvisible im Beispielmodul — kein zusätzlicher Code nötig, um davon zu profitieren.
Ein Grid kann vom Modul gepusht werden (nur lesbar auf Client-Seite, der Server pusht die Zeilen fortlaufend — zum Beispiel ein Messverlauf) oder vom Client verwaltet werden (lesen/schreiben, das generische CRUD oben — eine Aufgabenliste, Zielliste, Filterliste…). Beide Muster leben in derselben Mechanik nebeneinander, nur die permission ändert sich.
autoSelect / autoUpDown: reserviert, noch nicht angebunden
PropertyMulti stellt auch autoSelect()/setAutoSelect() und autoUpDown()/setAutoUpDown() bereit (JSON-Schlüssel "autoselect"/"autoupdown"). Ihr vorgesehener Zweck: dem Modul die Kontrolle darüber zu geben, was passieren soll, wenn der Benutzer eine Zeile auswählt oder neu ordnet — keine Darstellungsfrage auf Client-Seite, der Client zeigt seine Grid-Steuerelemente in jedem Fall gleich an.
Diese beiden Einstellungen werden gespeichert und wieder eingelesen, aber nichts im Framework fragt sie derzeit tatsächlich ab — es gibt heute keinen Einstiegspunkt (virtuelle Methode, Ereignis), über den ein Modul auf eine Zeilenauswahl oder -umordnung reagieren könnte. Verfolgt in ost/ostserver#270.
Ein Graph ist ein visualisiertes Grid
graphType/graphParams erfordern hasGrid:true — ohne Grid kein Graph.
XY: eine Kurve oder eine Punktwolke
"courbe": {
"hasGrid": true, "showGrid": false, "showElts": false,
"gridLimit": 30,
"graphType": "XY",
"graphParams": { "X": "t", "Y": "valeur" }
}X/Y benennen die als Achsen zu verwendenden Elemente des Grids. Die Punkte werden standardmäßig durch eine Linie verbunden — für eine Punktwolke ohne Ordnungsbeziehung (zum Beispiel nicht sequenzielle Messungen) deaktiviert das Hinzufügen von "scatter": true in graphParams das Zeichnen der Linie, die Punkte selbst werden weiterhin angezeigt.
SDY: mehrere Serien, auf mehreren Achsen
"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" }
}Ein einziges Grid, mehrere verschachtelte benannte Serien — jede Zeile hat ihren eigenen Serienwert (S), einen Zeitstempel (D) und einen Wert (Y). Um zwei Serien bei jedem Sample zu befüllen, wird pro Serie eine Zeile gepusht:
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 erlauben es zwei Serien mit sehr unterschiedlichen Skalen, sich visuell nicht gegenseitig zu überdecken, jede auf ihrer eigenen Achse.