Dynamic XFA Instance Presentation
Unit: HPDFXFAPresentation
TXFAInstancePresentation owns an independent TXFAWidgetRuntime and adds a bounded instance presentation profile for XDP packet documents with one datasets record
Use SetPresence('row[1]', 'hidden') to remove one occurrence from flow, invisible to retain its space while concealing its widgets, and visible to restore it; indices are zero-based positions among data occurrences, including concealed occurrences
The layout resolver measures each occurrence separately, compacts surviving vertical offsets, and reserves the complete repeated extent before placing following content; fixed-height, content-derived height, and table rows participate in reflow
Stable identity and persistence
Widget IDs combine opaque template and datasets identities and remain stable when preceding rows are hidden or removed, after save and reload, and while surviving fields retain focus or pending edits
The helper stores namespace-qualified identity attributes and instance overrides in a foreign-namespace extension inside the form packet, using urn:hotpdf:xfa:instance-presentation:1; newly added rows receive fresh identities and template defaults, and removed rows cannot transfer pending edits to replacement rows
SaveToBytes returns the complete XDP, including updated datasets, identities, and presentation states; use THotPDF.SetXFADocument to persist it in a PDF and set XFANeedsRendering := True when writing a dynamic form
After PDF reload, obtain the complete XDP with THotPDF.CreateLoadedXFAWidgetRuntime.SaveToBytes, then construct TXFAInstancePresentation from those bytes to restore this profile
The namespace extension is interpreted by this helper; native HPDFXFAFlatten, the default loaded runtime factory, and external XFA viewers do not automatically apply its per-instance overrides, so persistently storing the profile does not assert identical rendering in other readers
Explicit binding and instance operations
Repeated subforms can bind to a differently named dataset group with <bind match="dataRef" ref="$record.lines.entry[*]"/>; absolute $record and $data roots and relative paths support unindexed parent groups and a final repeated group
Fields inside each occurrence use the native bound-value resolver, including explicit relative field bindings such as ref="label"
AddInstance and RemoveInstance update the selected data group, enforce occur minimum and maximum, apply creation limits, and reflow before publication; the new row receives field values from the template instead of copying entered values from the previous row
Selectors use a unique template name with an optional occurrence index, such as row[1]; duplicate template names, missing groups, invalid indices, and mutations beneath an ambiguous repeated parent reject the transaction
SetAccess supports open, readOnly, protected, and nonInteractive; instance restrictions are inherited by descendants and prevent editing through the owned runtime
Conditional events
DispatchConditionalEvent locates a matching field event with JavaScript content type and parses the bounded profile directly; Execute runs an explicit script against an existing widget ID
if(this.rawValue=="hide"){
row[1].presence="hidden";
}else{
row[1].presence="visible";
}
row.instanceManager.addInstance();
row.instanceManager.removeInstance(0);
Conditions accept equality or inequality between this.rawValue and an unescaped quoted literal; nested braced if and optional else blocks are bounded by MaxDepth
Assignments support presence and access; all branches are syntax checked, including branches that are not taken, and unsupported operations reject the entire batch
this.rawValue reads the committed widget value; commit pending edits through Runtime.CommitEdit before dispatching an event that should observe them
The original Runtime.DispatchEvent retains its restricted literal-operation behavior and rejects conditional and indexed-instance syntax; this helper does not provide a general JavaScript or FormCalc interpreter, browser APIs, network access, or automatic XFA lifecycle dispatch
Transactions and budgets
Mutations execute through TXFAWidgetRuntime.UpdateDocument, together with native calculations and bounded stable reflow; failure restores serialized XDP, focus, pending edits, validation state, calculation and reflow counters, and warning count
Focus, layout, and widget invalidation callbacks publish only after success; rollback resolution suppresses exhausted helper work and cancellation checks while retaining native layout and widget bounds so cancellation cannot prevent restoration
Initialize TXFAPresentationOptions with Default; defaults are 200,000 operations, 4,096 presentation states, 10,000 created instances per group, 32 MiB input and document envelope, 65,536 script bytes, 32 conditional nesting levels, and 5,000 milliseconds
MaxInputBytes also bounds a conservative escaped XML envelope before each layout and publication pass, including identity attributes, namespace declarations, text, and datasets changes; valid XML may reach this conservative limit before its serialized byte count reaches the same value
Cancelled is an optional object-method callback checked during bounded work; the embedded Runtime options continue to bound widgets, values, calculations, layout, reflow, and native script work
Host painting and accessibility
Accessibility returns visible widget records with stable ID, role, caption or field name, tooltip description, committed value, page and bounds, focus, validity, read-only and required states, and choice labels; password values are omitted
PaintPage delivers a snapshot of visible widgets and corresponding accessibility records to a TXFAHostWidgetPainter; custom hosts can implement their own controls or rendering surface
TXFACanvasWidgetPainter provides actual VCL and LCL canvas painting for widget borders, text, password masking, checkbox and radio marks, choice indicators, buttons, and focus, with positive scale and optional offsets; it clips each widget and restores canvas styles
The canvas adapter paints widgets and does not paint the full static XFA graphics tree; the host supplies its own page background, static graphics, event routing, selection presentation, and accessibility bridge to its platform
The runtime and helper are single-thread objects; callbacks must follow the host's thread ownership and avoid recursive mutations during an active transaction
C++Builder callers must provide all canvas painter constructor arguments, such as new TXFACanvasWidgetPainter(canvas, 1, 0, 0); the generated headers do not retain these floating-point default arguments
Verification
Acceptance covers 106 Delphi cases per architecture, fresh FPC compilation on both Windows architectures, C++Builder public-header compilation on Win32 and Win64x, and independent validation of the actual PDF/XDP output
Tests/Fixtures/XFAInstancePresentation/explicit-invoice.xdp contains independent data names, three repeated invoice lines, a conditional event, metadata for accessibility, and a following footer
Run-XFAInstancePresentationTests.ps1 runs the helper checks and existing XFA event, runtime, scripting, SOM, DOM, and resolution regression fixtures without GUI or external PDF readers
The independent verify_saved_invoice.py reads the generated PDF with pypdf and checks real XDP data rows, unique persistent identities, hidden occurrence state, initialized defaults, and reload identities
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
See Interactive XFA Widget Runtime for the compatible base runtime and native editing contract