###########
Page Layout
###########

This section explains how to create and insert entities on a page. Entity types are listed in the section :doc:`Entities <entities>`.

Unless specific situation, the scenario is basically the same for all entities: the entity is created in a first step at a document level, then it is inserted and positioned on the page.

For widgets, the data is usually added on a third step by specific field functions or more generally by using data model (see section :doc:`Data Model </guide/publish/enrich/interactivity_datamodel>`).


Inserting a Text Line
=====================

You can insert a text line in a page. The text should only be one line and cannot contain carriage return. You can parameterize the font for the text, chosen beyond one of the basic standard fonts in Adobe Reader, or chosen from a font installed on the machine running Advanced Publishing. The characters used in the text string are supposed to be supported by the font selected.


Using a Basic Standard Font
---------------------------

Standard fonts are four faces (normal, italic, bold, bold-italic) of three Latin text typefaces: Courier, Helvetica, and Times. They are also two symbol fonts Symbol and ZapfDingbats. These standard fonts are automatically handled by Adobe Reader and don’t require any font installation. The text string content is restricted by the use of these fonts. The supported character set is the "Latin Character Set" with the Standard Encoding described in Annex D.2 in the `PDF reference <http://www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/PDF32000_2008.pdf>`_, and "Symbol Set" described in Annex D.5 and D.6. Standard font is defined using the ``A3DPDFTextData`` data structure.


Using a System Font
-------------------

Arbitrary system fonts can also be used for text lines. The font needs to be available in the system folder (C:\\Windows\\Fonts for Windows system) on the machine where Advanced Publishing is run, or in the 'Font' sub folder of the resource folder specified to A3DPDFInitializePDFLibAndResourceDirectory. A system font is subsetted in the final PDF, to only support the characters used in the page, leaving no need to have the font installed on the computer for the user who will open the document. System font is defined using the ``A3DPDFTextDataEx`` data structure.

The text can be positioned anywhere on the page, specified by a position in page unit, from the bottom left of the page. To create a text line, use ``A3DPDFTextCreate`` or ``A3DPDFTextCreateEx``, then use ``A3DPDFPageInsertText`` to insert it on the page.

.. code-block:: c

    A3DPDFTextData sTextData = A3D_MAKE_DATA(A3DPDFTextData);
    sTextData.m_eFontName = kA3DPDFFontTimesRoman;
    sTextData.m_iFontSize = 12;
    sTextData.m_sColor.m_dRed = 0.4;
    sTextData.m_sColor.m_dGreen = 0.4;
    sTextData.m_sColor.m_dBlue = 0.4;
    sTextData.m_pcTextString = "my text line";
    A3DPDFText* pText = NULL;
    iRet = A3DPDFTextCreate(pDoc, &sTextData, &pText);
    iRet = A3DPDFPageInsertText(pPage, pText, iPosX, iPosY);


Inserting an Image
==================

You can insert an image in a page. Advanced Publishing supports the most popular image formats (BMP, PNG, JPEG, GIF ...). The image can be positioned anywhere on the page, specified by a position in page unit, from the bottom left of the page. To create an image, use ``A3DPDFImageCreate``, then use ``A3DPDFPageInsertImage`` to insert it on the page.

.. code-block:: c

    A3DPDFImageData sImageData = A3D_MAKE_DATA(A3DPDFImageData);
    sImageData.m_pcFileName = "c:\\temp\\myimage.jpg";
    sImageData.m_iHeight = 480;
    sImageData.m_iWidth = 640;
    sImageData.m_eFormat = kA3DPDFImageFormatJpg;
    A3DPDFImage* pImage = NULL;
    iRet = A3DPDFImageCreate(pDoc, &sImageData, &pImage);
    iRet = A3DPDFPageInsertImage(pPage, pImage, iPosX, iPosY);


Inserting a Link
================

You can insert a link in a page. The link can be positioned anywhere on the page, specified by a position in page unit, from the bottom left of the page. To create a link, use ``A3DPDFLinkCreate``, then use ``A3DPDFPageInsertLink`` to insert it on the page.

When clicked, a link will execute an action that you specify. :doc:`Standard Actions </guide/publish/enrich/interactivity>` can be specified using ``A3DPDFLinkAddAction``, or advanced actions can also be coded with JavaScript and specified as argument ``A3DPDFLinkData.m_pcJavascriptString``.

.. code-block:: c

    A3DPDFLinkData sLinkData = A3D_MAKE_DATA(A3DPDFLinkData);
    char* jsactiv = "//activate page 2\n"
        "var a3d = this.getAnnots3D( 1 )[0];\n"
        "a3d.activated=true;\n"
        "c3d = a3d.context3D;\n"
        "c3d.runtime.setView(\"ALL\", true);\n";
    sLinkData.m_eHighlightingMode = eHighlightingMode;
    sLinkData.m_iBorderWidth = iBorderWidth;
    sLinkData.m_sColor.m_dRed = 0.5;
    sLinkData.m_sColor.m_dGreen = 0.0;
    sLinkData.m_sColor.m_dBlue = 1.0;
    sLinkData.m_pcJavascriptString = jsactiv;
    A3DPDFLink* pLink = NULL;
    iRet = A3DPDFLinkCreate(pDoc, &sLinkData, &pLink);
    CHECK_RET;
    // positioning the link in the page
    A3DPDFRectData sPos = A3D_MAKE_DATA(A3DPDFRectData);
    sPos.m_iLeft = iLeft;       // lower left x, from bottom left of the page
    sPos.m_iBottom = iBottom;   // lower left y, from bottom left of the page
    sPos.m_iRight = iRight;     // upper right x, from bottom left of the page
    sPos.m_iTop = iTop;         // upper right y, from bottom left of the page
    iRet = A3DPDFPageInsertLink(pPage, pLink, &sPos);
    CHECK_RET;


.. _layout_table:


Inserting a Table
=================

You can insert a table in a page. Any number of tables can be positioned anywhere on the page.

A table is defined on three levels: the cell, the row, and the table. Obviously a table contains a set of rows, and a row contains a set of cells.

Style can be defined to set properties on text such as font name and font size or text alignements, as well as colors for text, border, and background
We can also define the positionning of the text in a cell with padding (the space between the cell border and the text).

Dimensions of the cells and rows have to be defined with style parameter ``m_iRowHeight`` and ``m_iColumnWidth``.
Cells can be merged horizontally or vertically with the ``m_iRowSpan`` and ``m_iColSpan`` properties on cells. When doing this, be aware to set properly width and height of all rows and cells so that it is consistent.

When drawing the table, Advanced Publishing uses the style of the cell first, if it is not defined then it uses the style of the row, and if not defined the style of the table.
When the size of columns vary depending the column index, it is a good practice to define the styles only at cell level.

To create a table with API functions, use :cpp:func:`A3DPDFTableCreateFromDesc`, then use :cpp:func:`A3DPDFPageInsertTable` to insert it on the page.
The table insertion point is the top left corner of the table.
The coordinate origin (0, 0) is the bottom left of the page.
The unit is point.

More information is available on the :doc:`/api/group__a3d__pdf__table__module`, and particularly an example is provided on :doc:`/api/group__a3d__pdf__tablefromapi__module` to demonstrate the creation functions.



Inserting Field Widgets
=======================

You can create and insert fields in a page using Advanced Publishing API. Supported fields are text fields, buttons, check boxes, radio buttons, list boxes, drop down lists, and signature fields. They are all inserted similarly. The following example demonstrates how to insert a button.

Buttons
-------

Like all fields, buttons are referenced by their name member, which is a string that you specify at creation time. Buttons can use text or images as the button label.

The first thing to do when inserting a button is to define an area on the page where you want it to be displayed. Remember that the coordinate system unit is points, and the origin is the bottom left corner of the page. The following code defines the button's area in the bottom left corner:

.. code-block:: c

    A3DPDFRectData pRectData = A3D_MAKE_DATA(A3DPDFRectData);
    pRectData.m_iTop = 100;
    pRectData.m_iBottom = 0;
    pRectData.m_iLeft = 0;
    pRectData.m_iRight = 200;

Next, define the button's members using ``A3DPDFButtonData``. This structure is not stored and can be used to create additional buttons. The name member m_pcName is required:

.. code-block:: c

    A3DPDFButtonData pButtonData = A3D_MAKE_DATA(A3DPDFButtonData);
    pButtonData.m_pcName = "myButton"; // required!
    pButtonData.m_pcLabel = "Hello Buttons";
    pButtonData.m_pcFontName = "HeBo";
    pButtonData.m_iFontSize = 12;
    pButtonData.m_pcTooltip = "";
    pButtonData.m_bHasBorder = true;
    pButtonData.m_eThicknessBorder = kA3DPDFThin;
    pButtonData.m_eLineStyleBorder = kA3DPDFSolid;
    pButtonData.m_bHasFillColor = true;
    pButtonData.m_sFillColor.m_dRed = 0.5;
    pButtonData.m_sFillColor.m_dGreen = 0.5;
    pButtonData.m_sFillColor.m_dBlue = 0.5;
    pButtonData.m_eLayoutTextIcon = kA3DPDFLabelOnly;

Finally, the button is created and inserted. It is not shown here, but you should always remember to handle potential errors by checking return values for all A3D* functions:

.. code-block:: c

    A3DPDFButton* pButton;
    A3DPDFButtonCreate(pDoc, &pButtonData, &pButton);
    A3DPDFPageInsertButton(pPage, pButton, &pRectData);

When clicked, a button will execute an action that you specify. :doc:`Standard Actions </guide/publish/enrich/interactivity>` can be specified using ``A3DPDFButtonAddAction``, or advanced actions can also be coded with :doc:`Javascript </guide/publish/enrich/javascript>` and specified using ``A3DPDFPageFieldSetActionJavascriptFromString``.


Other Fields
------------

Each field type has its own data structure that is used for defining the field. Many structure members are common, but each field type has a few special members.

Follow the above pattern to insert other fields - corresponding data structures are noted below:

.. csv-table::
   :header: "Field", "Data Structure", "Creation Function", "Insertion Function", "Supporting Function"

    "Button", "A3DPDFButtonData", "A3DPDFButtonCreate", "A3DPDFPageInsertButton"
    "Check box", "A3DPDFCheckBoxData", "A3DPDFCheckBoxCreate", "A3DPDFPageInsertCheckBox"
    "Drop down list", "A3DPDFDropDownListData", "A3DPDFDropDownListCreate",	"A3DPDFPageInsertDropDownList", "A3DPDFPageFieldListAddItem"
    "List box", "A3DPDFListBoxData", "A3DPDFListBoxCreate", "A3DPDFPageInsertListBox", "A3DPDFPageFieldListAddItem"
    "Signature field", "A3DPDFDigitalSignatureData", "A3DPDFDigitalSignatureCreate", A3DPDFPageInsertDigitalSignature"
    "Radio button", "A3DPDFRadioButtonData", "A3DPDFRadioButtonCreate", "A3DPDFPageInsertRadioButton"
    "Text field", "A3DPDFTextFieldData", "A3DPDFTextFieldCreate", "A3DPDFPageInsertTextField"

If you need more information on the fields themselves, including their members and functions, consult Adobe's documentation.


Specifying Font for Field
-------------------------

You can parameterize the font used for a field. The font specified must be installed on the machine running Advanced Publishing. Unfortunately, embedding a font is not completely possible for fields, as the text is theorically subject to change dynamically. Consequently, the font selected must also be installed on the machine used by the final user of the PDF document. If the font is not found by Adobe Reader, then a replacement font is tentatively selected by Adobe Reader that can display the characters used. Finally, note that an Asian font selected for text field requires the Adobe Asian font package to be installed on the machine used by the final user.


Inserting Rich Text
===================

Text field allows to define certain rich text attributes. For example, text color, alignment, and font, among others. To define a text field as rich text, you have to set the Boolean ``A3DPDFTextFieldData.m_bAllowRichText`` to true. Then, define a rich text value with ``A3DPDFTextFieldData.m_pcRichTextValue``:

.. code-block:: c

    sTextFieldData.m_bAllowRichText = TRUE;
    sTextFieldData.m_pcRichTextValue = "<?xml version=\"1.0\"?>  \
          <body xfa:APIVersion=\"Acroform:2.7.0.0\"  \
          xfa:spec=\"2.1\" xmlns=\"http://www.w3.org/1999/xhtml\"  \
          xmlns:xfa=\"http://www.xfa.org/schema/xfa-data/1.0/\"><p style=\"margin-top:0pt;margin-bottom:0pt;text-align:center;  \
            text-valign:middle;font-family:Arial;font-size:18pt;  \
            color:#0000ff\"><i><b>Hello italic bold  \
            centered</b></i></p></body>";

The above example gives us the following results:

.. raw:: html

    <p style="margin-top:0pt;margin-bottom:0pt;text-align:center;       text-valign:middle;font-family:Arial;font-size:18pt;color:#0000ff;"><i><b>Hello italic bold centered</b></i></p><br>

Please note that the header is mandatory. Rich text strings are XHTML elements with a limited set of CSS2 style attributes:

.. code-block:: html

    <?xml version=\"1.0\"?>
    <body xfa:APIVersion=\"Acroform:2.7.0.0\"
          xfa:spec=\"2.1\" xmlns=\"http://www.w3.org/1999/xhtml\"
          xmlns:xfa=\"http://www.xfa.org/schema/xfa-data/1.0/\">

The following piece of code is to create a text field in RTF format:

.. code-block:: c

    A3DPDFTextFieldData sTextFieldData = A3D_MAKE_DATA(A3DPDFTextFieldData);
    sTextFieldData.m_pcDefaultValue="mon second RTF text field est rose";
    sTextFieldData.m_pcName="textfield";
    sTextFieldData.m_pcTooltip="tooltip!!";
    sTextFieldData.m_sBorderColor.m_dRed=1.0;
    sTextFieldData.m_sBorderColor.m_dGreen=0.0;
    sTextFieldData.m_sBorderColor.m_dRed=0.0;
    sTextFieldData.m_sFillColor.m_dRed=0.5;
    sTextFieldData.m_sFillColor.m_dGreen=0.5;
    sTextFieldData.m_sFillColor.m_dBlue=0.5;
    sTextFieldData.m_eFormField=kA3DPDFVisible;
    sTextFieldData.m_eTextOrientation=kA3DPDFNormal;
    sTextFieldData.m_bIsLocked=false;
    sTextFieldData.m_bHasBorder=true;
    sTextFieldData.m_eThicknessBorder=kA3DPDFThick;
    sTextFieldData.m_eLineStyleBorder=kA3DPDFBeveled;
    sTextFieldData.m_pcFontName="Times,BoldItalic";
    sTextFieldData.m_iFontSize=18;
    sTextFieldData.m_sTextColor.m_dRed=0.1;
    sTextFieldData.m_sTextColor.m_dGreen=0.0;
    sTextFieldData.m_sTextColor.m_dBlue=0.1;
    sTextFieldData.m_bAllowRichText=true;
    sTextFieldData.m_pcRichTextValue="<?xml version=\"1.0\"?><body   \
        xfa:APIVersion=\"Acroform:2.7.0.0\" xfa:spec=\"2.1\"   \
        xmlns=\"http://www.w3.org/1999/xhtml\"   \
        xmlns:xfa=\"http://www.xfa.org/schema/xfa-data/1.0/\"><p   \
        style=\"margin-top:0pt;margin-bottom:0pt;text-align:center;  \
        text-valign:middle;font-family:Arial;font-size:18pt;color:#0000ff\">  \
        <i><b>Hello world?</b></i></p></body>";

Rich text strings are defined in the PDF specification (see 12.7.3.4, "Rich Text Strings" in the section "Document management — Portable document format — Part 1: PDF 1.7").


Inserting a View Carousel
=========================

Advanced Publishing facilitates the creation of a view carousel. This is a component which becomes useful when you have many defined views and would like a way for the end user to browse them. The carousel, outlined in red in the image below, is scrolled by a set of buttons that you have previously defined.

.. image:: view_carousel.png
    :align: center

The view carousel renders button icons based on the views you specify. Then, it will apply the icons to the buttons automatically. As an example, let's say you have ten views, and would like to show four buttons at a time in the carousel. Only four (not ten) buttons need to be provided in m_ppcButtonsNames. The carousel will alternate the button icons automatically as it is scrolled. Simply click on a button to activate that view.

If you want to scroll one page of views at a time, set the scroll step to the number of views in your carousel. For example, if you have a 2x2 carousel, set the scroll step to 4. To scroll half a page at a time, set the scroll step to 2.

View carousel is a high level widget. The widget is first created and inserted on a page as other entities, then the data and interactivity is defined following :doc:`data model </guide/publish/enrich/interactivity_datamodel>` rules. A view carousel is specifically bound to a A3DPDFDataTable3DViews data table built from a A3DPDF3DArtwork and a A3DAsmModelFile. Different options exist to specify the view list and posters when the data table is created. Finally, the interaction of the view carousel with the 3D annotation must be explicitly set with function ``A3DPDFWidgetSetTargetBehaviour``.

For a complete example, see the *samples/publishing/PDFWithBOMAndCarousel.cpp* sample included with the Advanced Publishing package. The function of interest is stAddViewCarousel.

.. code-block:: c

    A3DPDF3DViewCarouselData sViewCarouselData = A3D_MAKE_DATA(A3DPDF3DViewCarouselData);
    sViewCarouselData.m_iNbButtons = (int)aViewCarouselButtons.size();
    sViewCarouselData.m_ppcButtonsNames = ppButtonsNames;
    sViewCarouselData.m_pcPreviousButtonName = ppButtonsNamesPrevNext[0];
    sViewCarouselData.m_pcNextButtonName = ppButtonsNamesPrevNext[1];
    sViewCarouselData.m_iScrollStep = 1;
    sViewCarouselData.m_bTransitionActive = TRUE;
    A3DPDF3DViewCarousel* pViewCarousel = NULL;
    iRet = A3DPDF3DViewCarouselCreate(pDoc, &sViewCarouselData, &pViewCarousel);
    iRet = A3DPDFPageInsert3DViewCarousel(pPage, pViewCarousel);
    iRet = A3DPDF3DViewCarouselBindToTable(pViewCarousel, pDataTable_3DViews);
    iRet = A3DPDFWidgetSetTargetBehaviour(pViewCarousel, p3DViewList, kA3DPDFDataSelect);


Inserting a Scroll Table
========================

A scroll table is a table that can be scrolled using a vertical scroll bar. Advanced Publishing has a simplified interface for inserting scroll tables. This function will implement the logic of populating the table rows as the user scrolls the table.

.. image:: slide_table_scroll_bar.png
    :align: center

A scroll table is a high level widget.
The widget is first created and inserted on a page as other entities, then the data and interactivity is defined following :doc:`data model </guide/publish/enrich/interactivity_datamodel>` rules. A scroll table is bound to a A3DPDFDataTable data table. Finally, the interaction of the scroll table with other widgets must be explicitly set with function ``A3DPDFWidgetSetTargetBehaviour``.

For a complete example, see the *samples/publishing/PDFWithBOMAndCarousel.cpp* sample included with the Advanced Publishing package. The function of interest is stAddScrollTable.

.. code-block:: c

    A3DPDFScrollTableData sScrollTableData = A3D_MAKE_DATA(A3DPDFScrollTableData);
    sScrollTableData.m_iGridNbRows = iNbRowsInFrame;
    sScrollTableData.m_iGridNbCols = (int)aiWidthCols.size();
    sScrollTableData.m_iGridHeightCells = iHeightRows;
    sScrollTableData.m_piGridWidthCells = (A3DInt32 *)malloc(sScrollTableData.m_iGridNbCols*sizeof(A3DInt32));
    for (size_t ic=0; ic<aiWidthCols.size(); ic++)
        sScrollTableData.m_piGridWidthCells[ic]=aiWidthCols[ic];
    sScrollTableData.m_iSliderWidth = iSliderWidth;
    A3DPDFScrollTable* pScrollTable = NULL;
    iRet = A3DPDFScrollTableCreate(pDoc, &sScrollTableData, &pScrollTable);
    iRet = A3DPDFPageInsertScrollTable(pPage, pScrollTable, iPosLeft, iPosTop);
    const A3DInt32 piMapColumns[] = { 0, 1, 2 };
    iRet = A3DPDFScrollTableBindToTable(pScrollTable, pDataTable,  sizeof(piMapColumns)/sizeof(A3DInt32), piMapColumns );
    iRet = A3DPDFWidgetSetTargetBehaviour(pScrollTable, p3DNodeScene, kA3DPDFDataHighlight);


Table Colors
------------

To add custom background and border colors to our scroll table, let's use the ``m_pCellFormat`` of the ``sScrollTableData`` object defined in the example above:

.. code-block:: c

    A3DPDFTextFieldData sCellFormatData = A3D_MAKE_DATA(A3DPDFTextFieldData);
    sCellFormatData.m_bHasFillColor = true;
    sCellFormatData.m_sFillColor.m_dBlue = 0.9;
    sCellFormatData.m_sFillColor.m_dGreen = 0.7;
    sCellFormatData.m_sFillColor.m_dRed = 0.7;
    sCellFormatData.m_bHasBorder = true;
    sCellFormatData.m_sBorderColor.m_dBlue = 0.7;
    sCellFormatData.m_sBorderColor.m_dGreen = 0.9;
    sCellFormatData.m_sBorderColor.m_dRed = 0.7;
    sCellFormatData.m_eThicknessBorder = kA3DPDFThin;
    sScrollTableData.m_pCellFormat = &sCellFormatData;

There isn't much to it: Just toggle the border and fill color members to true, set your desired RGB values, select a border thickness, and apply the changes to the ``sScrollTableData`` object.

Color settings can be applied to individual cells as well as to the table as a whole.

