Grillas y gráficos

Módulo de ejemplo: hellogrid.

Un gráfico no es un mecanismo aparte: es una visualización de una grilla existente. Todo empieza, por tanto, con la grilla.

El mecanismo básico: una instantánea repetida

Una grilla no es más que una instantánea repetida de los elementos base de su propia propiedad — no existe ninguna API para “añadir una línea con estos valores” directamente:

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() reinicia la grilla.
  • gridLimit (clave JSON) limita el número de líneas: más allá de ese límite, la más antigua se retira silenciosamente (FIFO).
"mesures": {
  "hasGrid": true,
  "showGrid": true,
  "showElts": false,
  "gridLimit": 30,
  "e": {
    "t": { "type": "int" },
    "valeur": { "type": "float" }
  }
}
  • showGrid: muestra la grilla misma.
  • showElts: muestra el formulario de los elementos base (el “borrador” antes de push()). Generalmente oculto (false) cuando es el módulo el que empuja las líneas.

CRUD genérico, sin ningún código

Con permission:2 (lectura/escritura) en una propiedad con grilla, el cliente gana gratuitamente controles de creación/modificación/eliminación/reordenamiento de las líneas — gestionados enteramente por el framework, sin que se necesite ningún código del lado del módulo:

EventoMétodo PropertyMulti llamadoEfecto
GCnewLine(valeurs)Añade una línea
GUupdateLine(index, valeurs)Modifica una línea existente
GDdeleteLine(index)Elimina una línea
GFfetchLine(index)Copia los valores de la línea a los elementos base — “cargar para editar”
GHswapLines(index, index-1)Hace subir una línea un puesto
GBswapLines(index, index+1)Hace bajar una línea un puesto
GRclearGrid()Vacía la grilla

El cliente típico (interfaz ostcore) ya muestra, para toda propiedad con grilla no bloqueada en solo lectura: un botón editar (dispara GF), subir/bajar (GH/GB), eliminar (GD), y un formulario de añadir/editar (GC/GU) — incondicionalmente, en cuanto showGrid y el permiso lo permiten. Con showElts:true además, hacer clic en una línea (fuera de los botones de acción) también dispara GF y carga sus valores en el formulario de elementos base. Es exactamente lo que ya demuestra gridvisible en el módulo de ejemplo — ningún código adicional que escribir para beneficiarse de todo esto.

Dos usos bien distintos

Una grilla puede ser empujada por el módulo (solo lectura del lado del cliente, el servidor empuja las líneas sobre la marcha — un historial de mediciones, por ejemplo) o gestionada por el cliente (lectura/escritura, el CRUD genérico anterior — una lista de tareas, de objetivos, de filtros…). Ambos patrones coexisten en la misma mecánica, solo cambia el permission.

autoSelect / autoUpDown: reservados, aún no cableados

PropertyMulti también expone autoSelect()/setAutoSelect() y autoUpDown()/setAutoUpDown() (claves JSON "autoselect"/"autoupdown"). Su rol previsto: dejar que el módulo tome el control de lo que debe ocurrir cuando el usuario selecciona una línea o la reordena — no es asunto de presentación del lado del cliente, el cliente muestra sus controles de grilla de la misma forma en todos los casos.

Aún no implementado

Estos dos ajustes se guardan y se vuelven a leer, pero nada en el framework los consulta todavía de verdad — hoy no existe ningún punto de entrada (método virtual, evento) que permita a un módulo reaccionar a una selección o un reordenamiento de línea. Seguimiento en ost/ostserver#270.

Un gráfico es una grilla, visualizada

graphType/graphParams requieren hasGrid:true — sin grilla, no hay gráfico.

XY: una curva, o una nube de puntos

"courbe": {
  "hasGrid": true, "showGrid": false, "showElts": false,
  "gridLimit": 30,
  "graphType": "XY",
  "graphParams": { "X": "t", "Y": "valeur" }
}

X/Y nombran los elementos de la grilla a usar como ejes. Los puntos se conectan por defecto con una línea — para una nube de puntos sin relación de orden (mediciones no secuenciales, por ejemplo), añadir "scatter": true en graphParams desactiva el trazado de la línea, los puntos en sí se siguen mostrando.

SDY: varias series, en varios ejes

"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 grilla, varias series con nombre entrelazadas — cada línea tiene su propio valor de serie (S), una marca de tiempo (D) y un valor (Y). Para alimentar dos series en cada muestra, empujar una línea por 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 permiten que dos series de escalas muy diferentes no se aplasten visualmente entre sí, cada una en su propio eje.