Presentación dinámica de instancias XFA
Unit: HPDFXFAPresentation
TXFAInstancePresentation posee un TXFAWidgetRuntime independiente y agrega un perfil acotado de presentación por instancia para documentos de paquetes XDP con un único record 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 con base cero entre las ocurrencias de datos, incluidas las ocultas
El resolver de layout mide cada ocurrencia por separado, compacta los offsets verticales supervivientes y reserva la extensión repetida completa antes de colocar el contenido siguiente; las filas de altura fija, altura derivada del contenido y de tabla participan en el reflow
Identidad estable y persistencia
Los IDs de widgets combinan identidades opacas de template y datasets y permanecen estables cuando se ocultan o eliminan filas precedentes, después de guardar y recargar, y mientras los campos supervivientes retienen el foco o ediciones pendientes
El helper guarda los atributos de identidad calificados por namespace y las sobrescrituras de instancia en una extensión de namespace externo dentro del paquete del formulario, usando urn:hotpdf:xfa:instance-presentation:1; las filas recién agregadas reciben identidades frescas y defaults de template, y las filas eliminadas no pueden transferir ediciones pendientes a filas de reemplazo
SaveToBytes devuelve el XDP completo, incluidos datasets actualizados, identidades y estados de presentación; usa THotPDF.SetXFADocument para persistirlo en un PDF y fija XFANeedsRendering := True al escribir un formulario dinámico
Tras recargar el PDF, obtén el XDP completo con THotPDF.CreateLoadedXFAWidgetRuntime.SaveToBytes y luego construye TXFAInstancePresentation desde esos bytes para restaurar este perfil
La extensión de namespace la interpreta este helper; el HPDFXFAFlatten nativo, la factory por defecto del runtime cargado y los visores XFA externos no aplican automáticamente sus sobrescrituras 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 bindear a un grupo de datasets con otro nombre mediante <bind match="dataRef" ref="$record.lines.entry[*]"/>; las raíces absolutas $record y $data y los paths relativos soportan grupos padre sin indexar y un grupo repetido final
Los campos dentro de cada ocurrencia usan el resolver nativo de valores bindeados, incluidos bindings de campo relativos explícitos como ref="label"
AddInstance y RemoveInstance actualizan el grupo de datos seleccionado, hacen cumplir 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 ingresados de 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 se heredan por los descendientes y impiden editar a través del runtime propio
Eventos condicionales
DispatchConditionalEvent localiza un evento de campo coincidente con content type JavaScript y parsea el perfil acotado directamente; Execute corre 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 con llaves anidadas y else opcionales quedan acotados por MaxDepth
Las asignaciones soportan presence y access; todas las ramas se verifican sintácticamente, incluidas las que no se ejecutan, y las operaciones no soportadas rechazan el lote completo
this.rawValue lee el valor de widget confirmado; confirma las ediciones pendientes con 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 provee un intérprete general de JavaScript o FormCalc, APIs de browser, acceso a red ni dispatch automático del ciclo de vida XFA
Transacciones y presupuestos
Las mutaciones se ejecutan mediante TXFAWidgetRuntime.UpdateDocument, junto con los cálculos nativos y el 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 conteo de warnings
Los callbacks de foco, layout e invalidación de widgets publican solo tras el éxito; la resolución de rollback suprime el trabajo agotado del helper y las comprobaciones de cancelación mientras retiene el layout nativo y los bounds de widgets para que la cancelación no pueda impedir la restauración
Inicializa TXFAPresentationOptions con Default; los defaults 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 anidación condicional y 5,000 milisegundos
MaxInputBytes también acota un envelope XML escapado conservador antes de cada pasada de layout y publicación, incluidos atributos de identidad, declaraciones de namespace, texto y cambios de datasets; un XML válido puede alcanzar este límite conservador antes de que su conteo serializado de bytes llegue al mismo valor
Cancelled es un callback opcional de método de objeto consultado durante el trabajo acotado; las opciones del Runtime embebido siguen acotando widgets, valores, cálculos, layout, reflow y trabajo de scripts nativo
Pintado del host y accesibilidad
Accessibility devuelve records de widgets visibles con ID estable, role, caption o nombre de campo, descripción de tooltip, valor confirmado, página y bounds, foco, validez, estados read-only y required y etiquetas de choice; los valores password se omiten
PaintPage entrega un snapshot de los widgets visibles y los records de accesibilidad correspondientes a un TXFAHostWidgetPainter; los hosts personalizados pueden implementar sus propios controles o superficie de rendering
TXFACanvasWidgetPainter provee pintado real de canvas VCL y LCL para 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, enrutamiento de eventos, presentación de selección y bridge de accesibilidad a su plataforma
El runtime y el helper son objetos single-thread; los callbacks deben respetar el ownership de threads del host y evitar mutaciones recursivas durante una transacción activa
Los callers de C++Builder deben proveer todos los argumentos del constructor del canvas painter, como new TXFACanvasWidgetPainter(canvas, 1, 0, 0); los headers generados no retienen estos argumentos por defecto de punto flotante
Verificación
La aceptación cubre 106 casos Delphi por arquitectura, compilación FPC fresca en ambas arquitecturas de Windows, compilación de headers públicos en C++Builder Win32 y Win64x y validación independiente del output 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 footer 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 filas de datos XDP reales, identidades persistentes únicas, estado de ocurrencias ocultas, defaults inicializados e identidades tras recargar
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