Hexagon Geospatial
MENU

WebGIS Tutorials

WebGIS enables powerful geospatial web applications and services that securely share your organization’s rich geospatial data, and provides tools to deeply examine spatial data and create value added products, on demand.
Showing results for 
Search instead for 
Do you mean 

How to customize printing templates used by external printing service

by Technical Evangelist ‎05-12-2017 06:58 AM - edited ‎05-12-2017 07:00 AM (3,459 Views)

Table Of Contents

Introduction

The external printing service uses XAML templates to generate print output. Server-sided printing is performed using a Snapshot Page that is opened in the server-side printing engine. After the snapshot page is fully loaded, the printing engine captures a bitmap. Bitmap is then applied to the template with other controls such as scale bar, legend and custom texts or images. See more on the internal mechanism here:

http://community.hexagongeospatial.com/t5/Developers-Knowledge-Base/Custom-Snapshot-Page-for-Printin...

XAML Language and WPF

  • XAML, an Extensible Application Markup Language, is a XML-based markup design language developed by Microsoft and used by Windows Presentation Foundation (WPF) controls.
  • WPF is an interface for building modern, vector-oriented GUIs on Windows systems. WPF replaced the aging .NET Windows Forms. XAML shares principles of both XML and .NET.

WPF design advantages

  • WPF uses device independent pixels approach. Those are abstractly defined points that scale with DPI changes automatically. In effect, the controls and fonts behave like vectors. Correctly designed forms will look the same on different resolutions and DPIs, fonts or other content will not overflow its parent content.
  • Controls are positioned relatively to their parent containers and sibblings. You can simply compare this behavior to HTML/CSS design.
  • Control containers can define rotation and orientation of their content. Example:
<StackPanel>
   <StackPanel.LayoutTransform>
      <RotateTransform Angle="-90"></RotateTransform>
   </StackPanel.LayoutTransform>
</StackPanel>

WPF controls positioning

Take a look at the brief summary of positioning options for any elements placed in a parent container.

Alignment

Dimension

Result

HorizontalAlignment="Stretch" (default)

Width="Auto" (default)

Element will stretch to full width of its parent.
Both attributes don’t need to be set explicitly.

HorizontalAlignment="Left"

Width="Auto" (default)

Element will snap to left border of its parent. Width will be set by its content.

HorizontalAlignment="Center"

Width="100"

Element will center horizontally to its parent. Width is exactly 100.

HorizontalAlignment="Stretch"

Width="100"

Illogical state, control cannot stretch and have an absolute width at the same time.

VerticalAlignment="Stretch" (default)

Height="Auto" (default)

Element will stretch to full height of its parent
Both attributes don’t need to be set explicitly.

VerticalAlignment="Top"

Height="50"

Elemement will snap to top border of its parent and will have absolute height of 50.

VerticalAlignment="Stretch" (default)

Height="50"

Illogical state, control cannot stretch and have an absolute height at the same time.

 

You can also use margin and padding same way as in to HTML/CSS defitions.

  • Margin - defines outer edges of the element
  • Padding - defines inner space of the element

WPFpositioning.png

XML namespaces

Namespaces are used for clear definition (resolution) of classes and other types. Without a namespaces there would be many conflicts and each class would have to have unique name in the whole project scope, incl. external libraries. Every element therefore must use a namespace. If no namespace is explicitly specified, default will be used. Namespaces in XAML reference .NET assemblies. Examples:

Custom namespace definition:

xmlns:tm="clr-namespace:Intergraph.MapPrinting.Templates;assembly=PrintEngine"

Usage of namespace delivered with WPF:

<x:Window xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" />

Note: It is a common practice to define all namespaces in the root element of XML document, the namespace shortcuts are then accessible through whole document.

Properties and Attributes

Each XAML element comes with set of properties. Some of them are simple in-line properties but some of them can be structured.

Example of simple property:

<Grid Background="Gray" ... />

Example of structured property:

<Grid Background="Gray">
   <Grid.RowDefinitions>
      <RowDefinition Height="59*" />
      <RowDefinition Height="88*" />
   </Grid.RowDefinitions>
</Grid>

Some attributes are default, such as "Text" in the following example:

<Label Text="Hello" />
<Label>Hello!</Label>

WPF Controls Examples

Grid

<Grid>
   <Grid.RowDefinitions>
        <RowDefinition Height="50" />
        <RowDefinition Height="*" MinHeight="20" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="2*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
</Grid>
  • There will be two rows, one will be exactly 50 points high and the second will use the rest of the box model. If empty, it will be still 20pts high.
  • There will be three columns, where the first one will use 25% of the box, second 50% and third 25%.

Use inherited complex properties inside Grid.Row & Grid.Column to position the controls within a Grid. If those properties are not specified the content will be automatically placed to the first row / column. Example

<Image Grid.Row="2" Grid.Column="2" Stretch="Fill" Source="/images/pic1.png" />
<TextBlock Grid.Row="3" Grid.Column="2">Image Caption</TextBlock>

Canvas

Used for positioning the elements in absolute coordinates related to canvas corners.

<Canvas Height="400" Width="400" >
    <Button Canvas.Top="10" Canvas.Left="10" Content="Button 1" />
    <Button Canvas.Top="40" Canvas.Left="20" Content="Button 2" />
</Canvas>

Result:

WPFCanvas.png

StackPanel

Used for stacking elements one-after-another horizontally or vertically. Useful e.g. when too many Grid.RowDefinitions would be confusing.

<StackPanel Grid.Column="0" Orientation="Horizontal" Width="30">
   <Button Content="Button 1" Margin="2" />
   <Button Content="Button 2" Margin="2" />
</StackPanel>

Result:

WPFStackPanel.png

WrapPanel

Similar to StackPanel but wraps element to a new line or column if a corner is reached.

<WrapPanel Background="LightBlue" Width="200" Height="100">
    <Button Width="200">Button 1</Button>
    <Button>Button 2</Button>
    <Button>Button 3</Button>
    <Button>Button 4</Button>
</WrapPanel>

Result:

WPFWrapPanel.png

TextBlock

For text descriptions, map coordinate display, disclaimers or additional information. Uses document “inlines” like <Bold>, <Italic>, etc.

<TextBlock>This is <Bold>bolded</Bold> text <LineBreak />
   and <Italic>Italic text</Italic> goes to a new line</TextBlock>

textblock.png

Image

Inserting custom logos & other bitmaps onto printing output.

<Image Height="70" Width="606" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" 
   Margin="0.2cm,0.2cm,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Name="myImage" Stretch="Fill"
   Source="C:\Temp\Images\img.png" />

Border

Creates and emphasizes actual content borders.

<Border BorderThickness="2" BorderBrush="Gray" 
   Grid.ColumnSpan="4" Grid.RowSpan="6" Grid.Column="1"
   HorizontalAlignment="Center" Width="717">   
     <Image ... />
</Border>

Custom template controls

The printing engine assemblies come with several custom controls that are essential for the actual print. Those are:

LegendControl

Use this control to place a legend that was available to the user issuing print in Portal application. This control comes with property LegendImageSize, a complex property containing Size element with Height and Width values:

<LegendControl LegendImageSize="10,10" … >

VerticalLegendControl

Same as above but positioned vertically. VerticalLegendControl adds additional property LegendClipMessage that allows to define a message displayed in situation when legend does not fit the window and was clipped.

MapControl

Basic control for placing a map. Has no specific properties.

ScaleControl

Control for placing an additional scalebar. Usable properties are

  • Segments - number of black-white segments on the scale bar
  • Units - if used, automatically converts between "Metric" or "Miles"

NOTE: One scalebar is automatically rendered inside the map control but can be removed if custom snapshot page is developed.

Using custom controls in Visual Studio

Microsoft Visual Studio 2013 and later is recommended development environment when working with printing template files. It comes with WYSIWYG editor for XAML files, IntelliSense and validators. You can add the printing service custom controls to the Toolbox and simply drag and drop them onto the designer view.

  1. Launch Visual Studio and create a new WPF project.
  2. Open the XAML file in designer view and activate Toolbox.
  3. Create Printing Template Controls group and right click into an empty space.
  4. Add new controls using Choose Items...
    VS101.png
  5. Locate PrintEngine.DLL assembly delivered with the printing service. It is usually located at:
    C:\Program Files\Common Files\Hexagon\Services\Supporting Services\PrintingService\bin
    VS1.png
  6. Click Open.
  7. The custom controls available in this WPF library will be selected for you.
  8. Click OK.VS2.png
  9. Now you can drag and drop these controls to the designer view.
    VS3.png

Basic Template Structure

The printing templates are specific when it comes to the default structure. Each XAML template should have this basic structure as a starting point. Note the custom namespaces definitions such as con, el and tm.

<tm:TemplateControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:con="clr-namespace:Intergraph.MapPrinting.Converters;assembly=PrintEngine"
                    xmlns:el="clr-namespace:Intergraph.MapPrinting.Elements;assembly=PrintEngine"
                    xmlns:sys="clr-namespace:System;assembly=mscorlib"
                    xmlns:tm="clr-namespace:Intergraph.MapPrinting.Templates;assembly=PrintEngine"
                    Height="29.7cm"
                    Width="21cm"
                    Background="{x:Null}"
                    TemplateDescription="Custom portrait template"
                    TemplateName="My Portrait Template"
                    TemplateOrientation="Portrait"
                    >
    <tm:TemplateControl.TemplateScales>
        <sys:Int32>500</sys:Int32>
		  <sys:Int32>1000</sys:Int32>
        <sys:Int32>2000</sys:Int32>
        <sys:Int32>5000</sys:Int32>
    </tm:TemplateControl.TemplateScales>
    <!-- Grid is not mandatory but recommended as the main container -->
    <Grid Margin="1cm,1cm,1cm,1cm">
    </Grid>
</tm:TemplateControl>

Templates Default Location

The template XAML files must be stored in
C:\Program Files\Common Files\Hexagon\Services\Supporting Services\PrintingService\App_Data\Resources\Templates

The printing service automatically reads those file and compiles them into resulting printout image. Should any problems occur while reading the XAML file you find related error message in the service's log file:

C:\Program Files\Common Files\Hexagon\Services\Supporting Services\PrintingService\App_Data\Resources\Logs

Template Parameters

There are two types of parametrs usable in printing templates. One of them are predefined system parameters while others are custom defined by the template developers. The system parameters have their values set during the print page generation or by user input. You can reference and display those values usually using Textblock elements. Binding mechanism is used to dynamically access the parameters during run time.

System Parameters - initialized by the Printing Engine

  • Map Extents: [xMin], [xMax], [yMin], [yMax]
  • CRS information: [crsId], [crsName]
  • Zoom level: ScaleSource

Example usage:

<TextBlock FontSize="8pt" Text="{Binding Path=Parameters.[yMax]}" ... />
<TextBlock FontSize="10pt" Text="{Binding Path=ScaleSource}" ... />

System Parameters - set by the user in the Common Options tab

Example:

TControl.png

Available parameters list:

  • TemplateDescription – description of the template, not visible anywhere else
  • TemplateName – custom template name
  • TemplateOrientation – Landscape or Portrait, or both
  • TemplatePageSizeNames – refine the actual page names (in case of non-standard template sizes
  • TemplateScales – refine list of available template scales

Custom Parameters - defined by template developer

Template developers can define their custom parameters that will appear in the Template Options tab. It is done through specifying custom attributes for user Textblock user control that can appear as:

  • Text input box
  • Checkbox
  • Date picker
  • Selection list
  • Multiline text area

Here's a list of the custom attributes available through tm namespace:

  • ParameterCategory - System or User - used to identify if this field bounds to a system predefined parameter or of it’s a custom defined paramater
  • ParameterDefault - Default value (e.g. preset text in the text box)
  • ParameterDescription - Label displayed in the printing dialog
  • ParameterType - Text by default; other options are Checkbox, Date, List and Textarea
  • ParameterValues - list of values for lists

Following example shows a parameters definition:

CustomParam.png

Sample Template

Please find attached below a sample template that should render as following.

SampleOutput.png

Comments
by Technical Evangelist
on ‎04-12-2018 11:54 PM

Of course, you can use GraphicsMagick as long as you use the Printing Service.

by
on ‎04-12-2018 05:02 AM

 

The "Custom custom snapshot page for printing" article at https://community.hexagongeospatial.com/t5/Developers-Knowledge-Base/Custom-Snapshot-Page-for-Printi...  has a code change to use PhantomJS engine

<printing tileSize="2000" mapSizeLimit="5000" timeout="00:02" defaultService="FirstExternal" precisionGeographic="7" precisionProjected="0" printingEngine="phantomJS" phantomJSProgramLocation="c:\intergraph\Geospatial Portal\Program\PhantomJS\phantomjs.exe" />

and sounded like it was only for local printing

WebGIS
Geospatial Portal Printing Workflow
Portal performs local printing on the server using one of two engines
Internet Explorer
PhantomJS
Server-Side printing is performed using a „Snapshot Page” that is opened in the server-side printing engine
After the snapshot page is fully loaded, the printing engine captures a bitmap
EP05 introduces customization of the snapshot page allowing developer to load additional scripts
Local printout may be then piped to the printing service for further processing
Custom snapshot page
With EP05 it is possible to implement custom snapshot page that generates image used for the printout
Custom snapshot page may use API.js
Custom snapshot page may inject custom script tags
For example custom script tags may handle dynamic predicate based styles

so i will just leave out that change (which switches to PhantomJS printing) and try it. Thanks....

by Anthony
‎05-14-2018 01:33 PM - edited ‎05-14-2018 01:37 PM

I'm using custom page sizes defined in web.config. When I use the default page sizes (A0-A5), the scale bar appears on the map as it should. However, when I change the page size to using custom sizes, the scale bar gets truncated. Here is what the page sizes in my web.config look like below. I didn't see how to use the PageNames defined on the template themselves, I did notice that with the following page sizes, it sometimes seems off in that even though it's in landscape, the larger page sizes act give a portrait like map selection

 

webconfig.PNGtruncatedscalebar.PNG

Contributors