Crear propiedades dinámicamente, en C++
Módulo de ejemplo: hellodyn.
loadOstPropertiesFromFile() es solo una comodidad: llama, para cada propiedad y cada elemento del JSON, exactamente a las mismas primitivas que un módulo puede llamar él mismo directamente, en cualquier momento de su vida — en la instanciación, o bien más tarde, en reacción a una acción del usuario.
Construir una propiedad a mano
OST::PropertyMulti *pm = new OST::PropertyMulti(
"hello", "Hello", OST::Permission::ReadOnly,
/* level1 */ "", /* level2 */ "", /* order */ "1",
/* hasProfile */ false, /* hasGrid */ false);
createProperty(pm);
OST::ElementString *message = new OST::ElementString("message", "Message", "1", "");
message->setValue("Hello, world!");
pm->addElt(message);El constructor de PropertyMulti nombra sus dos parámetros de jerarquía level1/level2 (y es también el nombre devuelto al cliente en el dump JSON). Pero la clave JSON de un archivo .json de módulo es devcat/group, no level1/level2 — dos nombres distintos para la misma cosa, según se escriba C++ o JSON. Una confusión fácil de cometer.
Cada tipo de elemento tiene el mismo esquema de constructor: ElementXxx(clave, etiqueta, orden, información-sobre-herramienta). addElt() debe llamarse después de createProperty().
Para ElementInt/ElementFloat, las restricciones numéricas (min/max/step/format — mismas claves que en JSON, ver El catálogo de tipos) se fijan después de la construcción, mediante setters dedicados:
OST::ElementFloat *step = new OST::ElementFloat("step", "Step size", "2", "");
step->setMinMax(1.0, 1000.0, false);
step->setStep(1.0, false);
step->setFormat("%.0f", false);
pm->addElt(step);El último argumento (false aquí) es el mismo emitEvent que setValue() — no vale la pena avisar al cliente de un cambio de metadato en el momento en que el elemento aún no existe en el frontend.
Crear una propiedad a demanda, no al arrancar
Un botón (ElementBool, directedit:true) puede disparar la creación en lugar de hacerla al arrancar:
void HelloDyn::onExternalEvent(OST::ExtEvent event)
{
if (event.ev != OST::ExtEvType::SV || event.prpkey != "actions") return;
if (event.eltkey == "create")
{
if (!getStore().contains("hello"))
{
OST::PropertyMulti *pm = new OST::PropertyMulti("hello", "Hello",
OST::Permission::ReadOnly, "", "", "2", false, false);
createProperty(pm);
OST::ElementString *message = new OST::ElementString("message", "Message", "1", "");
message->setValue("Hello, world! (créé à la demande)");
pm->addElt(message);
}
getEltBool("actions", "create")->setValue(false, true);
}
}Cada rama vuelve a poner su propio botón en false una vez procesada la acción — un botón de acción es un disparador puntual, no un interruptor persistente.
Añadir o quitar un elemento de una propiedad ya existente
if (event.eltkey == "addfield")
{
OST::ElementString *field = new OST::ElementString(key, label, "", "");
field->setValue(value);
getProperty("hello")->addElt(field);
}
if (event.eltkey == "removefield")
{
getProperty("hello")->deleteElt(key);
}addElt()/deleteElt() notifican al cliente de la modificación (aparece un nuevo elemento, o desaparece, sin que sea necesario recargar la página).
PropertyMulti no numera sus elementos por sí misma — le corresponde al módulo generar claves únicas (un contador, por ejemplo) para saber cuáles existen y en qué orden retirarlas.