Modificar uma página XPS em eventos | Java

Compreender a abordagem baseada em eventos na programação

A abordagem baseada em eventos na programação é um paradigma focado nos eventos e no seu tratamento. Neste modelo, o fluxo do programa é ditado por eventos, que podem incluir ações do utilizador (como cliques do rato ou pressionamentos de teclas), notificações geradas pelo sistema ou mensagens de outras aplicações. Abaixo estão alguns aspetos-chave da abordagem baseada em eventos:

De um modo geral, a abordagem baseada em eventos é um método eficaz para gerir interações e fluxos de trabalho dentro de um programa, tornando-a especialmente adequada para aplicações que requerem capacidade de resposta e interações do utilizador.

Conversão e eventos de documentos XPS

Quando necessita de modificar uma página específica de um documento XPS utilizando a API Aspose.Page, normalmente seleciona o documento ativo (se existirem vários documentos no ficheiro XPS), seleciona a página ativa e aplica as alterações.

Agora, digamos que precisa de implementar alterações repetidas em todas as páginas de um ficheiro XPS e, posteriormente, converter o resultado para PDF ou um formato de imagem. Exemplos destas alterações podem incluir a adição de uma marca de água às páginas ou a inserção de hiperligações de navegação. O método simples para fazer estas alterações implica percorrer os documentos no pacote XPS, percorrer as páginas do documento activo actual e, finalmente, aplicar as alterações. Assim sendo, o código para realizar esta tarefa seria o seguinte:

 1for (int i = 1; i <= document.getDocumentCount(); i++)
 2{
 3    document.selectActiveDocument(i);
 4    for (j = 1; j <= document.getPageCount(); j++)
 5    {
 6        document.selectActivePage(j);
 7        // Your changes ...
 8    }
 9}
10document.saveAsPdf("file-name.pdf", saveOptions);

Se também precisar de fazer algumas alterações irregulares antes de aplicar as repetidas, esta abordagem pode causar confusão ou percorrer excessivamente documentos e páginas. Além disso, estes loops podem parecer algo trabalhosos.

Ao converter um documento XPS em PDF ou imagem, o processo ocorre uma página de cada vez. À medida que a tarefa de conversão se prepara para processar a página seguinte, desencadeia um evento “before-page”. O utilizador pode definir o comportamento (manipulação de eventos) nestes eventos estendendo a classe BeforePageSavingEventHandler, aproveitando assim algumas das vantagens discutidas na secção introdutória deste artigo.

Exemplo de adição de hiperligações de navegação

Nesta secção, apresentaremos um exemplo que envolve hiperligações de navegação. E para complicar um pouco a tarefa, apenas converteremos um subconjunto de todas as páginas para PDF, tal como definido pelo método PdfSaveOptions.setPageNumbers().

A classe manipuladora de eventos

Abaixo está a extensão da classe BeforePageSavingEventHandler:

 1/**
 2 * The class to handle the before-page event while converting an XPS document.
 3 */
 4public static class NavigationInjector extends BeforePageSavingEventHandler
 5{
 6    private final XpsFont _font;
 7    private List<Integer> _pageNumbers;
 8
 9    public NavigationInjector(XpsFont font, int[] pageNumbers)
10    {
11        _font = font;
12        if (pageNumbers == null || pageNumbers.length == 0)
13            return;
14
15        // Turn the page number array into a sorted collection of unique values.
16        SortedMap<Integer, Integer> map = new TreeMap<Integer, Integer>();
17        for (int pn : pageNumbers)
18            map.put(pn, 0);
19        _pageNumbers = new ArrayList<Integer>(map.keySet());
20    }
21
22    /**
23     * The action itself to be triggered on a before-page event.
24     * @param args The even arguments.
25     */
26    @Override
27    public void handle(BeforeSavingEventArgs<PageAPI> args)
28    {
29        PageAPI api = args.getElementAPI();
30
31        XpsGlyphs glyphs;
32        // For all pages in the output PDF except the first one...
33        if (args.getOutputPageNumber() > 1)
34        {
35          // ...insert a hyperlink to the first page...
36            glyphs = api.createGlyphs(_font, 15f, 5f, api.getHeight() - 10f, "[First]");
37            glyphs.setFill(api.createSolidColorBrush(Color.BLUE));
38            glyphs.setHyperlinkTarget(new XpsPageLinkTarget(_pageNumbers == null ? 1 : _pageNumbers.get(0)));
39            api.add(glyphs);
40
41            // ...and to the previous page.
42            glyphs = api.createGlyphs(_font, 15f, 60f, api.getHeight() - 10f, "[Prev]");
43            glyphs.setFill(api.createSolidColorBrush(Color.BLUE));
44            glyphs.setHyperlinkTarget(new XpsPageLinkTarget(
45                _pageNumbers == null ? args.getAbsolutePageNumber() - 1 : _pageNumbers.get(args.getOutputPageNumber() - 2)));
46            api.add(glyphs);
47        }
48
49        // For all pages in the output PDF except the last one...
50        if ((_pageNumbers != null && args.getOutputPageNumber() < _pageNumbers.size()) ||
51            (_pageNumbers == null && args.getOutputPageNumber() < api.getTotalPageCount()))
52        {
53          // ...insert a hyperlink to the next page...
54            glyphs = api.createGlyphs(_font, 15f, 110f, api.getHeight() - 10f, "[Next]");
55            glyphs.setFill(api.createSolidColorBrush(Color.BLUE));
56            glyphs.setHyperlinkTarget(new XpsPageLinkTarget(
57                _pageNumbers == null ? args.getAbsolutePageNumber() + 1 : _pageNumbers.get(args.getOutputPageNumber())));
58            api.add(glyphs);
59
60            // ...and to the last page.
61            glyphs = api.createGlyphs(_font, 15f, 160f, api.getHeight() - 10f, "[Last]");
62            glyphs.setFill(api.createSolidColorBrush(Color.BLUE));
63            glyphs.setHyperlinkTarget(new XpsPageLinkTarget(
64                _pageNumbers == null ? api.getTotalPageCount() : _pageNumbers.get(_pageNumbers.size() - 1)));
65            api.add(glyphs);
66        }
67
68        // Insert a page number in the bottom-right corner.
69        glyphs = api.createGlyphs(_font, 15f, api.getWidth() - 20f, api.getHeight() - 10f, Integer.toString(args.getOutputPageNumber()));
70        glyphs.setFill(api.createSolidColorBrush(Color.BLACK));
71        api.add(glyphs);
72
73        // Add an outline entry to display the links to the converted pages in the navigation pane of a PDF viewer.
74        api.addOutlineEntry(MessageFormat.format("Page {0}", args.getOutputPageNumber()), 1, args.getAbsolutePageNumber());
75    }
76}

A classe manipuladora necessita de estar ciente das páginas que pretendemos guardar como PDF para estabelecer os alvos corretos da hiperligação. Consequentemente, o construtor deve receber como argumento a propriedade getPageNumbers() do array options. Se a matriz de números de página for fornecida, criamos uma coleção ordenada dos mesmos, excluindo os duplicados ao mesmo tempo. Além disso, a classe necessita de um objeto XpsFont que contém os dados da fonte para o texto da hiperligação.

O método handle() sobrescrito é onde tudo acontece. O argumento do método é um objeto que contém a API de modificação para a página atual, o número do documento dentro do pacote XPS, o número absoluto da página em todos os documentos, o número relativo da página dentro do documento atual (que é igual ao número anterior se existir apenas um documento no pacote) e o número da página de saída (que é igual ao número absoluto da página quando convertemos o pacote inteiro).

A lógica dos dois blocos if seguintes é bastante simples. Analisa o argumento do evento getOutputPageNumber() para omitir alguns dos links quando apropriado: os links [First] e [Prev] não serão adicionados à primeira página, enquanto os links [Next] e [Last] não aparecerão na última página. A lógica também foi concebida para acomodar ambos os cenários, independentemente de os números de página serem ou não especificados.

Após os blocos if, existe um código que adiciona um número de página no canto inferior direito da página.

A última linha adiciona a entrada de estrutura de tópicos da página, que é o item que será apresentado no painel de navegação de um visualizador de PDF (se compatível).

Código para conversão

Agora que o manipulador de eventos “before-page” está definido, podemos escrever o código para a conversão do documento:

 1// For complete examples and data files, please go to https://github.com/aspose-page/Aspose.Page-for-Java
 2// The path to the documents directory.
 3String dataDir = Utils.getDataDir();
 4String fontDir = dataDir + "necessary_fonts/";
 5// Open an XPS Document
 6final XpsDocument doc = new XpsDocument(dataDir + "Sample3.xps");
 7try {
 8  // Create a font
 9  final InputStream fontStream = new FileInputStream(fontDir + "arialbd.ttf");
10  try {
11    // Create options for conversion to PDF
12    PdfSaveOptions options = new PdfSaveOptions();
13    // Set the filter for the pages that need conversion
14    options.setPageNumbers(new int[] { 2, 6, 7, 13 });
15    // Add the event handler that will execute right before the conversion of each page
16    options.getBeforePageSavingEventHandlers().add(new NavigationInjector(doc.createFont(fontStream), options.getPageNumbers()));
17    // Save resultant XPS document
18    doc.saveAsPdf(dataDir + "ModifyPageOnConversion_out.pdf", options);
19  } finally {
20    if (fontStream != null)
21      fontStream.close();
22  }
23} finally {
24  if (doc != null)
25    doc.close();
26}

Abrimos um ficheiro XPS e criamos um objeto de fluxo com o ficheiro de dados da fonte. De seguida, instanciamos a classe PdfSaveOptions e especificamos os números de página que precisamos de converter. A linha seguinte “liga” o manipulador de eventos “before-page” à tarefa de conversão através da coleção getBeforePageSavingEventHandlers().

Agora, basta executar a conversão para PDF utilizando o método saveAsPdf() do documento.

Conclusão

Neste artigo, abordamos os aspetos fundamentais da abordagem baseada em eventos em programação, examinamos o método direto para modificar páginas de um documento XPS e exploramos uma técnica mais avançada para fazer alterações repetidas em todas as páginas de saída durante o processo de conversão, utilizando a inserção de hiperligações de navegação como exemplo.

Para os exemplos completos, explore o nosso projeto de exemplo.

Have any questions about Aspose.Page?



Subscribe to Aspose Product Updates

Get monthly newsletters & offers directly delivered to your mailbox.