Presentación de instancias XFA dinámicas

Unidad: HPDFXFAPresentation

TXFAInstancePresentation posee un TXFAWidgetRuntime independiente y añade un perfil acotado de presentación de instancias para documentos de paquete XDP con un único registro datasets

Usa SetPresence('row[1]', 'hidden') para sacar una ocurrencia del flujo, invisible para retener su espacio ocultando sus widgets y visible para restaurarla; los índices son posiciones basadas en cero entre las ocurrencias de datos, incluidas las ocultas

El resolver de disposición mide cada ocurrencia por separado, compacta los offsets verticales supervivientes y reserva la extensión repetida completa antes de colocar el contenido posterior; las filas de altura fija, de altura derivada del contenido y de tabla participan en el reflow

Identidad estable y persistencia

Los IDs de widget combinan identidades opacas de template y datasets y permanecen estables cuando se ocultan o eliminan filas precedentes, tras guardar y recargar, y mientras los campos supervivientes retienen el foco o ediciones pendientes

El helper guarda los atributos de identidad con namespace cualificado y los overrides de instancia en una extensión de namespace ajeno dentro del paquete de formulario, usando urn:hotpdf:xfa:instance-presentation:1; las filas recién añadidas reciben identidades nuevas y valores por defecto del template, y las filas eliminadas no pueden transferir ediciones pendientes a filas de reemplazo

SaveToBytes devuelve el XDP completo, incluidos los datasets actualizados, las identidades y los estados de presentación; usa THotPDF.SetXFADocument para persistirlo en un PDF y pon XFANeedsRendering := True al escribir un formulario dinámico

Tras recargar el PDF, obtén el XDP completo con THotPDF.CreateLoadedXFAWidgetRuntime.SaveToBytes y después construye TXFAInstancePresentation a partir de esos bytes para restaurar este perfil

La extensión de namespace la interpreta este helper; el HPDFXFAFlatten nativo, la factoría por defecto del runtime cargado y los visores XFA externos no aplican automáticamente sus overrides por instancia, de modo que persistir el perfil no afirma un rendering idéntico en otros lectores

Binding explícito y operaciones de instancia

Los subforms repetidos pueden vincularse a un grupo de datos con otro nombre mediante <bind match="dataRef" ref="$record.lines.entry[*]"/>; las raíces absolutas $record y $data y las rutas relativas soportan grupos padre sin indexar y un grupo repetido final

Los campos dentro de cada ocurrencia usan el resolver nativo de valores vinculados, incluidos los bindings relativos explícitos de campos como ref="label"

AddInstance y RemoveInstance actualizan el grupo de datos seleccionado, imponen el mínimo y máximo de occur, aplican límites de creación y hacen reflow antes de publicar; la fila nueva recibe los valores de campo del template en lugar de copiar los valores introducidos en la fila anterior

Los selectores usan un nombre de template único con un índice de ocurrencia opcional, como row[1]; los nombres de template duplicados, los grupos ausentes, los índices inválidos y las mutaciones bajo un padre repetido ambiguo rechazan la transacción

SetAccess soporta open, readOnly, protected y nonInteractive; las restricciones de instancia las heredan los descendientes e impiden editar a través del runtime propio

Eventos condicionales

DispatchConditionalEvent localiza un evento de campo coincidente con content type JavaScript y analiza el perfil acotado directamente; Execute ejecuta un script explícito contra un ID de widget existente

if(this.rawValue=="hide"){
  row[1].presence="hidden";
}else{
  row[1].presence="visible";
}
row.instanceManager.addInstance();
row.instanceManager.removeInstance(0);

Las condiciones aceptan igualdad o desigualdad entre this.rawValue y un literal entrecomillado sin escapar; los bloques if anidados entre llaves y los else opcionales quedan acotados por MaxDepth

Las asignaciones soportan presence y access; todas las ramas pasan la comprobación de sintaxis, incluidas las que no se ejecutan, y las operaciones no soportadas rechazan el lote entero

this.rawValue lee el valor confirmado del widget; confirma las ediciones pendientes mediante Runtime.CommitEdit antes de despachar un evento que deba observarlas

El Runtime.DispatchEvent original conserva su comportamiento restringido de operaciones literales y rechaza la sintaxis condicional y de instancias indexadas; este helper no aporta un intérprete general de JavaScript o FormCalc, ni APIs de navegador, ni acceso a red, ni despacho automático del ciclo de vida XFA

Transacciones y presupuestos

Las mutaciones se ejecutan mediante TXFAWidgetRuntime.UpdateDocument, junto con los cálculos nativos y un reflow estable acotado; un fallo restaura el XDP serializado, el foco, las ediciones pendientes, el estado de validación, los contadores de cálculo y reflow y el recuento de avisos

Los callbacks de foco, disposición e invalidación de widgets publican solo tras el éxito; la resolución del rollback suprime el trabajo de helper agotado y las comprobaciones de cancelación mientras retiene la disposición nativa y los bounds de widgets, para que la cancelación no pueda impedir la restauración

Inicializa TXFAPresentationOptions con Default; los valores por defecto son 200 000 operaciones, 4 096 estados de presentación, 10 000 instancias creadas por grupo, 32 MiB de envelope de entrada y documento, 65 536 bytes de script, 32 niveles de anidamiento condicional y 5 000 milisegundos

MaxInputBytes acota también un envelope XML conservador con escapes antes de cada pasada de disposición y publicación, incluidos los atributos de identidad, las declaraciones de namespace, el texto y los cambios de datasets; un XML válido puede alcanzar este límite conservador antes de que su recuento de bytes serializado llegue al mismo valor

Cancelled es un callback opcional de método de objeto que se comprueba durante el trabajo acotado; las opciones del Runtime incrustado siguen acotando los widgets, valores, cálculos, disposición, reflow y trabajo de script nativo

Pintado por el host y accesibilidad

Accessibility devuelve los registros de widgets visibles con ID estable, rol, caption o nombre de campo, descripción de tooltip, valor confirmado, página y bounds, foco, validez, estados de solo lectura y obligatorio y etiquetas de choice; los valores de password se omiten

PaintPage entrega un snapshot de los widgets visibles y los registros de accesibilidad correspondientes a un TXFAHostWidgetPainter; los hosts personalizados pueden implementar sus propios controles o superficie de rendering

TXFACanvasWidgetPainter aporta pintado real en canvas VCL y LCL para los bordes de widgets, texto, enmascaramiento de password, marcas de checkbox y radio, indicadores de choice, botones y foco, con escala positiva y offsets opcionales; recorta cada widget y restaura los estilos del canvas

El adaptador de canvas pinta widgets y no pinta el árbol completo de gráficos estáticos XFA; el host aporta su propio fondo de página, gráficos estáticos, enrutado de eventos, presentación de selección y bridge de accesibilidad hacia su plataforma

El runtime y el helper son objetos de un solo hilo; los callbacks deben respetar la propiedad de hilos del host y evitar mutaciones recursivas durante una transacción activa

Los llamadores de C++Builder deben aportar todos los argumentos del constructor del canvas painter, como new TXFACanvasWidgetPainter(canvas, 1, 0, 0); los headers generados no retienen esos argumentos por defecto de coma flotante

Verificación

La aceptación cubre 106 casos Delphi por arquitectura, compilación FPC limpia en ambas arquitecturas Windows, compilación de headers públicos con C++Builder en Win32 y Win64x y validación independiente de la salida real PDF/XDP

Tests/Fixtures/XFAInstancePresentation/explicit-invoice.xdp contiene nombres de datos independientes, tres líneas de factura repetidas, un evento condicional, metadatos de accesibilidad y un pie de página posterior

Run-XFAInstancePresentationTests.ps1 ejecuta las comprobaciones del helper y los fixtures existentes de regresión de eventos XFA, runtime, scripting, SOM, DOM y resolución, sin GUI ni lectores PDF externos

El verify_saved_invoice.py independiente lee el PDF generado con pypdf y comprueba las filas de datos XDP reales, las identidades persistentes únicas, el estado de las ocurrencias ocultas, los valores por defecto inicializados y las identidades tras la recarga

powershell -File Tests/Delphi/Run-XFAInstancePresentationTests.ps1 -Platform Win32 -CheckCppHeaders
powershell -File Tests/Delphi/Run-XFAInstancePresentationTests.ps1 -Platform Win64 -CheckCppHeaders
python Tests/Fixtures/XFAInstancePresentation/verify_saved_invoice.py

Consulta Interactive XFA Widget Runtime para el runtime base compatible y el contrato nativo de edición