Configuring a Table Column Width Provider
In a custom framework, the table
element as well as the table columns can
have specified widths. For these widths to be considered by Author
mode we need to provide the means to determine them. As explained in Configuring Tables, if you use the
table element attribute width
Oxygen XML Editor plugin can determine the table width automatically. In this example the
table has col
elements with width attributes that are not recognized
by default. You will need to implement a Java extension class to determine the column
widths.
- Create the class
simple.documentation.framework.TableColumnWidthProvider
. This class must implement thero.sync.ecss.extensions.api.AuthorTableColumnWidthProvider
interface.import ro.sync.ecss.extensions.api.AuthorAccess; import ro.sync.ecss.extensions.api.AuthorOperationException; import ro.sync.ecss.extensions.api.AuthorTableColumnWidthProvider; import ro.sync.ecss.extensions.api.WidthRepresentation; import ro.sync.ecss.extensions.api.node.AuthorElement; public class TableColumnWidthProvider implements AuthorTableColumnWidthProvider {
- Method
init
is taking as argument anro.sync.ecss.extensions.api.node.AuthorElement
that represents the XMLtable
element. In our case the column widths are specified incol
elements from thetable
element. In such cases you must collect the span information by analyzing thetable
element.public void init(AuthorElement tableElement) { this.tableElement = tableElement; AuthorElement[] colChildren = tableElement.getElementsByLocalName("customcol"); if (colChildren != null && colChildren.length > 0) { for (int i = 0; i < colChildren.length; i++) { AuthorElement colChild = colChildren[i]; if (i == 0) { colsStartOffset = colChild.getStartOffset(); } if (i == colChildren.length - 1) { colsEndOffset = colChild.getEndOffset(); } // Determine the 'width' for this col. AttrValue colWidthAttribute = colChild.getAttribute("width"); String colWidth = null; if (colWidthAttribute != null) { colWidth = colWidthAttribute.getValue(); // Add WidthRepresentation objects for the columns this 'customcol' // specification spans over. colWidthSpecs.add(new WidthRepresentation(colWidth, true)); } } } }
- The method
isTableAcceptingWidth
should check if the table cells aretd
.public boolean isTableAcceptingWidth(String tableCellsTagName) { return "td".equals(tableCellsTagName); }
- The method
isTableAndColumnsResizable
should check if the table cells aretd
. This method determines if the table and its columns can be resized by dragging the edge of a column.public boolean isTableAndColumnsResizable(String tableCellsTagName) { return "td".equals(tableCellsTagName); }
- Methods
getTableWidth
andgetCellWidth
are used to determine the table and column width. The table layout engine will ask thisro.sync.ecss.extensions.api.AuthorTableColumnWidthProvider
implementation what is the table width for each table element and the cell width for each cell element from the table that was marked as cell in the CSS using the propertydisplay:table-cell
. The implementation is simple and just parses the value of the width attribute. The methods must returnnull
for the tables / cells that do not have a specified width.public WidthRepresentation getTableWidth(String tableCellsTagName) { WidthRepresentation toReturn = null; if (tableElement != null && "td".equals(tableCellsTagName)) { AttrValue widthAttr = tableElement.getAttribute("width"); if (widthAttr != null) { String width = widthAttr.getValue(); if (width != null) { toReturn = new WidthRepresentation(width, true); } } } return toReturn; }
public List<WidthRepresentation> getCellWidth(AuthorElement cellElement, int colNumberStart, int colSpan) { List<WidthRepresentation> toReturn = null; int size = colWidthSpecs.size(); if (size >= colNumberStart && size >= colNumberStart + colSpan) { toReturn = new ArrayList<WidthRepresentation>(colSpan); for (int i = colNumberStart; i < colNumberStart + colSpan; i ++) { // Add the column widths toReturn.add(colWidthSpecs.get(i)); } } return toReturn; }
- Methods
commitTableWidthModification
andcommitColumnWidthModifications
are used to commit changes made to the width of the table or its columns when using the mouse drag gestures.public void commitTableWidthModification (AuthorDocumentController authorDocumentController, int newTableWidth, String tableCellsTagName) throws AuthorOperationException { if ("td".equals(tableCellsTagName)) { if (newTableWidth > 0) { if (tableElement != null) { String newWidth = String.valueOf(newTableWidth); authorDocumentController.setAttribute( "width", new AttrValue(newWidth), tableElement); } else { throw new AuthorOperationException("Cannot find the table element."); } } } }
public void commitColumnWidthModifications (AuthorDocumentController authorDocumentController, WidthRepresentation[] colWidths, String tableCellsTagName) throws AuthorOperationException { if ("td".equals(tableCellsTagName)) { if (colWidths != null && tableElement != null) { if (colsStartOffset >= 0 && colsEndOffset >= 0 && colsStartOffset < colsEndOffset) { authorDocumentController.delete(colsStartOffset, colsEndOffset); } String xmlFragment = createXMLFragment(colWidths); int offset = -1; AuthorElement[] header = tableElement.getElementsByLocalName("header"); if (header != null && header.length > 0) { // Insert the cols elements before the 'header' element offset = header[0].getStartOffset(); } if (offset == -1) { throw new AuthorOperationException("No valid offset to insert column width"); } authorDocumentController.insertXMLFragment(xmlFragment, offset); } } } private String createXMLFragment(WidthRepresentation[] widthRepresentations) { StringBuffer fragment = new StringBuffer(); String ns = tableElement.getNamespace(); for (int i = 0; i < widthRepresentations.length; i++) { WidthRepresentation width = widthRepresentations[i]; fragment.append("<customcol"); String strRepresentation = width.getWidthRepresentation(); if (strRepresentation != null) { fragment.append(" width=\"" + width.getWidthRepresentation() + "\""); } if (ns != null && ns.length() > 0) { fragment.append(" xmlns=\"" + ns + "\""); } fragment.append("/>"); } return fragment.toString(); }
- The following three methods are used to determine what type of column width
specifications the table column width provider support. In our case all types of
specifications are allowed:
public boolean isAcceptingFixedColumnWidths(String tableCellsTagName) { return true; } public boolean isAcceptingPercentageColumnWidths(String tableCellsTagName) { return true; } public boolean isAcceptingProportionalColumnWidths(String tableCellsTagName) { return true; }
Note
The complete source code for the examples can be found in the Simple Documentation Framework project, included in the oxygen-sample-framework module of the Oxygen SDK , available as a Maven archetype on the Oxygen XML Editor plugin website.
In the listing below, the XML document contains the table element:
<table width="300"> <customcol width="50.0px"/> <customcol width="1*"/> <customcol width="2*"/> <customcol width="20%"/> <header> <td>C1</td> <td>C2</td> <td>C3</td> <td>C4</td> </header> <tr> <td>cs=1, rs=1</td> <td>cs=1, rs=1</td> <td row_span="2">cs=1, rs=2</td> <td row_span="3">cs=1, rs=3</td> </tr> <tr> <td>cs=1, rs=1</td> <td>cs=1, rs=1</td> </tr> <tr> <td column_span="3">cs=3, rs=1</td> </tr> </table>
When no table column width provider is specified, the table has the following layout:
Table layout when no column width provider is specified
When the above implementation is configured, the table has the correct layout: