Runtime de widget XFA dinâmico interativo

TXFAWidgetRuntime oferece um modelo de interação neutro em relação ao host para formulários XFA dinâmicos, sem convertê-los em campos AcroForm nem achatar seu conteúdo

O runtime expõe limites e estado de widgets de forma determinística, para que um desktop, um serviço ou um renderer customizado forneça a própria entrada, pintura, acessibilidade e event loop dele

Criar um runtime

Crie o runtime diretamente a partir de bytes XDP ou chame THotPDF.CreateLoadedXFAWidgetRuntime depois de carregar um PDF cujo AcroForm contenha uma entrada /XFA de stream único ou array de pacotes

var
  Runtime: TXFAWidgetRuntime;
  State: TXFAWidgetState;
begin
  Runtime := PDF.CreateLoadedXFAWidgetRuntime;
  try
    if (Runtime <> nil) and (Runtime.WidgetCount > 0) then
    begin
      State := Runtime.Widgets[0];
      Runtime.FocusWidget(State.ID);
      Runtime.BeginEdit(State.ID);
      Runtime.ReplaceSelection(0, Length(State.Value), 'Updated value');
      if not Runtime.CommitEdit then
        raise Exception.Create(Runtime.LastDiagnostic);
    end;
  finally
    Runtime.Free;
  end;
end;

A factory de documento carregado é somente leitura em relação ao grafo de objetos do PDF e aos XFAFlattenWarnings existentes; salvar o documento mantém as entradas originais /XFA e /NeedsRendering

Modelo de interação

Commits interativos sincronizam valores scalar nativos existentes em aliases hidden e invisible, incluindo escopos reais de dados repetidos e rollback exato em bytes

Validação e cálculo atômicos

Um commit resolve vínculos SOM explícitos e o contexto de dados atual de linhas repetidas antes de executar os scripts de validate e calculate

O valor editado, os valores calculados, os nodes de dados, o modelo de widget, o estado de foco e edição, os avisos e os contadores de passagens são publicados em conjunto somente depois que a validação e o layout se estabilizam

Scripts rejeitados, orçamentos esgotados, limites de seleção UTF-16 inválidos e exceções de layout ou de medição do host restauram o estado anterior completo e definem LastDiagnostic

Orçamentos

TXFAWidgetRuntimeOptions limita a contagem de widgets, o comprimento do valor editado, as passagens de cálculo, as passagens de reflow, as operações de layout, as operações de script, o tempo decorrido de script e outros recursos de FormCalc ou JavaScript

O teto de widgets se aplica enquanto itens de layout e fragmentos de paginação são acrescentados, enquanto a descompressão do XFA carregado e a montagem de packets param no limite de entrada do XFA DOM antes da análise

MaxLayoutOperations tem padrão 200000 e limita tanto o percurso do documento quanto o trabalho de layout; a profundidade de layout é limitada a 128, a profundidade de alvo de evento e de inicialização de instância a 64, e o despacho recursivo de eventos é rejeitado

Eventos dinâmicos literais default

DispatchEvent aceita operações literais separadas por ponto e vírgula em scripts de eventos de campo correspondentes, com content types FormCalc ou JavaScript; essas operações são analisadas diretamente e não exigem uma DLL de JavaScript

row.instanceManager.addInstance(true);
row.instanceManager.removeInstance(0);
target.presence = "hidden";

addInstance anexa uma instância e aceita true, false, 1 ou 0 como argumento de merge; um argumento omitido usa true, e a forma abreviada _row.addInstance(1) também é aceita

O modelo suportado vincula todo data group de mesmo nome existente, então uma instância nova recebe um data group novo inicializado com os defaults do template para qualquer argumento de merge; a criação de instância não clona os valores digitados da linha anterior

removeInstance usa um índice inteiro de base zero entre os data groups de mesmo nome do subform selecionado; o subform precisa ter um element occur com máximo repetível, e ambas as operações impõem o mínimo e o máximo dele, incluindo max="-1"

A mutação de instâncias exige binding implícito de dataset nomeado e nomes de dados ASCII no XML; binding explícito por referência de dados e contextos de parent ambíguos são rejeitados antes de publicar a transação

Alvos resolvem por meio de filhos nomeados do template nos escopos que envolvem o evento, incluindo paths com pontos e this.parent; um manager aninhado em um escopo repetido usa o próprio data group do evento

presence aceita visible, hidden e invisible em fields, draws, subforms e exclusion groups do template; conteúdo hidden não ocupa espaço de fluxo, enquanto conteúdo invisible retém o espaço dele e é omitido dos widgets e da saída do flatten

Com o parser literal default, mudanças de presence se aplicam ao node de template selecionado e, portanto, a todas as ocorrências repetidas dele; presence indexada por instância, inactive, expressões arbitrárias, variáveis, condicionais, loops e outras operações de script de evento exigem um event host adicional

Um lote de eventos publica mudanças de dados, cálculos, layout, foco e estado de edição juntos depois que o reflow se estabiliza; qualquer operação rejeitada ou orçamento esgotado de entrada, operações, instâncias, valores, widgets, layout ou tempo decorrido restaura o estado completo anterior do documento e da interação

Remover uma linha preserva o foco e as edições pendentes dos data groups sobreviventes mesmo quando os índices de widget deles mudam; remover ou ocultar o widget em foco limpa o foco e publica o callback de foco correspondente depois do sucesso

Execução de eventos gerais em JavaScript e FormCalc

Defina TXFAWidgetRuntimeOptions.ScriptOptions.EnableJavaScript para habilitar a ponte QuickJS limitada embarcada na execução de eventos; eventos JavaScript então suportam funções, closures, arrays, condições, loops e exceções em vez da gramática literal default

Options := TXFAWidgetRuntimeOptions.Default;
Options.ScriptOptions.EnableJavaScript := True;
Runtime := TXFAWidgetRuntime.Create(XDPBytes, 595, 842, Options);

O event host expõe this, fields e subforms nomeados envolventes, parent, rawValue gravável, presence e access, instanceManager.count/min/max, addInstance, removeInstance, insertInstance, moveInstance e setInstances, xfa.resolveNode, xfa.resolveNodes, resolução por node e xfa.layout.relayout

Listas de nodes suportam indexação numérica, length e item; valores de campos repetidos retêm os próprios alvos de dataset, e paths SOM aceitam filhos nomeados com índices numéricos ou wildcard para nodes vivos do host

const values = xfa.resolveNodes("main.row[*].amount[*]");
let total = 0;
for (const field of values) total += Number(field.rawValue);
xfa.resolveNode("main.total").rawValue = total;
if (total > 100) this.parent.warning.presence = "visible";

Cada subform repetido tem o próprio objeto vivo e os campos filhos dele; index, getters de filhos do parent e queries SOM subsequentes seguem operações de insert, move e remove imediatamente dentro do script

addInstance e insertInstance retornam uma subárvore viva inicializada com os defaults do template, de modo que o script pode escrever os valores de campos dela antes de o evento publicar; handles removidos rejeitam leituras ou escritas subsequentes

Mudanças gerais de presence e access de scripts persistem no packet form XFA padrão por ocorrência, enquanto valores de campos e operações de repetição persistem em datasets; insert, move e remove mantêm o estado de form correspondente alinhado com os data groups

Com o mesmo opt-in, scripts de eventos FormCalc compilam para a engine limitada e suportam var, if/elseif/else, for com upto ou downto, while, foreach, func com resultados implícitos, aritmética e comparações, concatenação de strings, agregação de nodes wildcard e atribuição implícita de valores de campos

A biblioteca de funções de eventos inclui Sum, Count, Avg, Min, Max, Round, funções matemáticas comuns, fatiamento de strings, conversão de caixa, trimming, substituição, HasValue, Exists, Within, Oneof e Choose; nomes built-in não diferenciam maiúsculas, At(source, search) segue a ordem de argumentos do XFA incluindo o comportamento de busca vazia, funções financeiras seguem a ordem de parâmetros do XFA, e os catálogos de datas e finanças são descritos em FormCalc Functions

Mutações de scripts são gravadas dentro da engine, validadas e reproduzidas dentro da transação do runtime; exceções, interrupção, Unicode inválido, operações de host inválidas e orçamentos esgotados não publicam mudanças parciais no documento

A execução geral de scripts permanece desligada por default, não usa browser nem processo externo e não expõe APIs de filesystem, rede ou aplicação; o chamador pode fornecer JavaScriptEvaluator em vez da ponte

Script objects persistentes

Objetos script JavaScript dentro do element variables de um subform expõem as variáveis e funções deles pelo nome do script; variáveis lexicais, estado de objetos e closures aninhadas permanecem vivos pela sessão do runtime, com shadowing lexical normal e diretivas strict preservados

<variables>
  <script name="Helpers" contentType="application/x-javascript"><![CDATA[
    let count = 0;
    const nextPrivate = (() => { let value = 0; return () => ++value; })();
    function next() { return ++count + ":" + nextPrivate(); }
  ]]></script>
</variables>

Código de eventos pode chamar Helpers.next(); ocorrências repetidas de subforms têm script objects independentes, e funções resolvem campos nomeados contra o contexto vivo atual do formulário

Nodes de campos e managers capturados seguem identidade estável de dados entre movimentos e a publicação de instâncias recém-criadas; acessar um node removido rejeita o evento e desfaz o estado do módulo dele

Scripts gerais de calculate e validate compartilham a sessão e os script objects; JavaScript suporta completion values implícitos e return explícito, enquanto FormCalc retorna a expressão final dele

Transações que falham restauram o estado lexical e de closures reproduzindo o journal virtual commitado, com tempo e entradas aleatórias gravados; replay e execução atual compartilham o prazo da transação, e os limites default do journal são 64 MiB de scripts/resultados e 8192 entradas

O estado de script objects vive na sessão do runtime e é inicializado de novo depois do reload do XDP; valores padrão do documento e overrides de formulário continuam persistindo por meio de SaveToBytes

Callbacks customizados de JavaScriptEvaluator retêm o envelope nativo existente de calculate/validate; a sessão persistente é fornecida pela engine embarcada

Configurar host transport explícito

Defina HostTransport e o OnHostTransactionCompleted opcional em TXFAWidgetRuntimeOptions para executar dialogs de host, impressão, navegação, submission e transferência de dados por meio de callbacks da aplicação

Explicit XFA Host Transport fornece xfa.host.messageBox, response, beep, print, gotoURL, submitForm, importData, exportData e FormCalc Get, Post e Put; a aplicação retorna resultados tipados e controla os efeitos externos

Retries e replay de sessão usam responses gravadas, de modo que callbacks executam uma vez por request despachada; a conclusão de falha permite à aplicação descartar efeitos preparados ou compensar operações reversíveis

HostTransportLimits positivos limitam a contagem de requests, a contagem de argumentos e os bytes agregados de request/response dentro da transação envolvente do runtime

Execução de locales e pictures

Eventos FormCalc gerais e scripts de calculate e validate suportam funções de locale e picture, incluindo Format, Parse, conversões localizadas de data/hora, unidades, encoding, UUIDs e palavras de números em inglês

Dynamic FormCalc Eval executa cálculos fornecidos dinamicamente com variáveis e funções isoladas, acesso relativo a campos, compilação nativa, responses gravadas e rollback transacional

Referências FormCalc explícitas suportam atribuição write-through, rebind, desanexação de null, argumentos de funções e handles estáveis retidos por script objects entre movimentos de instâncias repetidas

Live SOM paths suportam índices de ocorrência inferidos, absolutos e relativos, selectors de class e de descendentes, contêineres transparentes, predicates de candidates e atribuição indexada direta em FormCalc

O Data DOM nativo expõe datasets por meio de $data e $record, sincroniza leituras e escritas de formulários vinculados imediatamente, espelha instâncias repetidas e preserva referências de dados retidas por meio da publicação nativa de identidade

O Property DOM nativo expõe filhos declarados de value, fonte, UI e outras propriedades, sincroniza valores tipados de campos e persiste atributos por instância usados pela medição de fontes e pelo styling de flatten suportado

O node em execução herda o atributo de locale mais próximo dele; entradas de localeSet do documento sobrepõem símbolos e patterns do sistema, enquanto nomes de locale computados são resolvidos por requests internas limitadas e preservados no journal da sessão

Num2Date sem picture agora usa o pattern default de data ambiente; forneça YYYY-MM-DD explicitamente quando a saída ISO for exigida

Host model com estado

XFA Host Model fornece metadados da aplicação, contagem real de páginas, navegação de páginas, título Unicode, flags de calculation/validation, reset com escopo e foco de campo com lifecycle transacional de enter/exit

TXFAWidgetRuntimeOptions.HostModel configura o estado inicial da aplicação; TXFAWidgetRuntime.HostModel retorna o estado atual, e eventos que falham o restauram junto com os snapshots de documento e de interação

Um movimento de foco sem script enter/exit, edição pendente ou lifecycle inicializado muda o foco sem iniciar cálculo de scripts nem processamento de prazos; foco roteado por scripts e commits de edições pendentes ainda usam orçamentos transacionais, validação e recálculo

Advanced picture clauses executam pelas mesmas transações de runtime, journal de retry de locale e lifecycle de cálculo, com parsing composto limitado

Inicializar e manter o lifecycle

Chame InitializeForm depois de configurar o runtime e os callbacks para executar eventos initialize na ordem do template, depois calculate e validate, eventos form-ready e eventos layout-ready; a chamada é idempotente depois do sucesso

Instâncias novas criadas pela inicialização ou por eventos ready recebem os próprios eventos initialize antes dos handlers ready delas; a execução de layout-ready se repete apenas quando o layout muda, dentro dos orçamentos de reflow e de transação

Depois da inicialização, despacho de eventos bem-sucedido e commit de edição inicializam instâncias recém-criadas e executam calculate, validate e layout-ready; ocorrências existentes retêm o estado de inicialização delas entre movimentos e rollback de transações

Falhas de lifecycle desfazem bytes do documento, interação de widgets e bookkeeping de inicialização juntos, e os callbacks publicam apenas depois que a transação envolvente tem sucesso

Salvar o formulário atualizado

SaveToBytes retorna o XDP completo atualizado do runtime, incluindo datasets modificados e estado padrão de form por instância; mudanças de presence do parser literal continuam sendo atributos de template; use esses bytes com SetXFADocument ao gravar um PDF ou com HPDFXFAFlatten para a saída de flatten atualizada

A factory de documento carregado cria um runtime independente, então eventos do runtime não modificam automaticamente o grafo de objetos do PDF de origem

Profile opcional de instance presentation

Dynamic XFA Instance Presentation adiciona bindings repetidos explícitos, IDs estáveis por instância, presence e acesso indexados, eventos condicionais limitados, pintura em canvas do host e acessibilidade por meio de um helper independente; o runtime default e a gramática de eventos restrita dele permanecem compatíveis

UpdateDocument fornece actions de documentos transacionais; callbacks opcionais de propriedade de runtime, binding-scope, identidade, resolution-started e validação de documentos suportam o helper, enquanto defaults nil preservam os chamadores existentes

APIs de eventos e de formulário de nível mais baixo

HPDFXFACompileFormCalcEvent compila sintaxe de eventos; HPDFXFAExecuteJavaScriptEvent executa o contexto virtual descrito por TXFAEventBinding e TXFAEventBindings

TXFAJavaScriptSession fornece execução persistente e checkpoints limitados para chamadores de nível mais baixo

Valores TXFAEventAction retornados usam TXFAEventActionKind; o replay transacional é fornecido pelo runtime

HPDFXFAResolveFormInstanceNode e HPDFXFAResolveFormInstanceProperty fornecem lookup limitado de form packets padrão

Fronteiras atuais

O runtime é um objeto de host single-thread; GUI e pintura continuam sendo responsabilidade do host ou do helper de presentation opcional

O host state suportado, o form DOM vivo e o lifecycle ainda não cobrem toda propriedade de host do Acrobat, pictures de dígitos de eras alternativas e localizadas, queries síncronas de reflow dinâmico nem todo operador SOM

Veja Bounded XFA FormCalc and JavaScript, XFA Packet DOM e Interactive Document Processing