diff options
author | Vincent Hennebert <vhennebert@apache.org> | 2012-09-26 11:31:40 +0000 |
---|---|---|
committer | Vincent Hennebert <vhennebert@apache.org> | 2012-09-26 11:31:40 +0000 |
commit | a1af0b2481adf1d4bdb1279972a9d4e51e381f6a (patch) | |
tree | 00f0840c0593e48cc1c49878a6e2a1a78e20a9e9 /src | |
parent | 182bbad662b45ecc15e2cc3d3de6cde7bdc77bea (diff) | |
download | xmlgraphics-fop-a1af0b2481adf1d4bdb1279972a9d4e51e381f6a.tar.gz xmlgraphics-fop-a1af0b2481adf1d4bdb1279972a9d4e51e381f6a.zip |
Bugzilla #53902: Added possibility to define 'header' table columns (the same way as fo:table-header allows to define header rows).
When accessibility is enabled, this allows to set the appropriate Scope attribute on the corresponding TH cells.
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1390412 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src')
7 files changed, 71 insertions, 18 deletions
diff --git a/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java b/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java index 93b815d30..09a814ef5 100644 --- a/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java +++ b/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java @@ -20,6 +20,7 @@ package org.apache.fop.accessibility.fo; import java.util.Locale; +import java.util.Stack; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; @@ -30,6 +31,7 @@ import org.apache.fop.fo.FOEventHandler; import org.apache.fop.fo.FONode; import org.apache.fop.fo.FOText; import org.apache.fop.fo.extensions.ExtensionElementMapping; +import org.apache.fop.fo.extensions.InternalElementMapping; import org.apache.fop.fo.flow.AbstractGraphics; import org.apache.fop.fo.flow.BasicLink; import org.apache.fop.fo.flow.Block; @@ -70,6 +72,10 @@ class StructureTreeEventTrigger extends FOEventHandler { private LayoutMasterSet layoutMasterSet; + private final Stack<Table> tables = new Stack<Table>(); + + private final Stack<Boolean> inTableHeader = new Stack<Boolean>(); + public StructureTreeEventTrigger(StructureTreeEventHandler structureTreeEventHandler) { this.structureTreeEventHandler = structureTreeEventHandler; } @@ -195,42 +201,51 @@ class StructureTreeEventTrigger extends FOEventHandler { @Override public void startTable(Table tbl) { + tables.push(tbl); startElement(tbl); } @Override public void endTable(Table tbl) { endElement(tbl); + tables.pop(); } @Override public void startHeader(TableHeader header) { + inTableHeader.push(Boolean.TRUE); startElement(header); } @Override public void endHeader(TableHeader header) { endElement(header); + inTableHeader.pop(); } @Override public void startFooter(TableFooter footer) { + // TODO Shouldn't it be true? + inTableHeader.push(Boolean.FALSE); startElement(footer); } @Override public void endFooter(TableFooter footer) { endElement(footer); + inTableHeader.pop(); } @Override public void startBody(TableBody body) { + inTableHeader.push(Boolean.FALSE); startElement(body); } @Override public void endBody(TableBody body) { endElement(body); + inTableHeader.pop(); } @Override @@ -248,6 +263,24 @@ class StructureTreeEventTrigger extends FOEventHandler { AttributesImpl attributes = new AttributesImpl(); addSpanAttribute(attributes, "number-columns-spanned", tc.getNumberColumnsSpanned()); addSpanAttribute(attributes, "number-rows-spanned", tc.getNumberRowsSpanned()); + boolean rowHeader = inTableHeader.peek(); + boolean columnHeader = tables.peek().getColumn(tc.getColumnNumber() - 1).isHeader(); + if (rowHeader || columnHeader) { + final String th = "TH"; + String role = tc.getCommonAccessibility().getRole(); + /* Do not override a custom role */ + if (role == null) { + role = th; + addNoNamespaceAttribute(attributes, "role", th); + } + if (role.equals(th)) { + if (columnHeader) { + String scope = rowHeader ? "Both" : "Row"; + addAttribute(attributes, InternalElementMapping.URI, InternalElementMapping.SCOPE, + InternalElementMapping.STANDARD_PREFIX, scope); + } + } + } startElement(tc, attributes); } diff --git a/src/java/org/apache/fop/fo/Constants.java b/src/java/org/apache/fop/fo/Constants.java index 2d10dcdd9..6688042e2 100644 --- a/src/java/org/apache/fop/fo/Constants.java +++ b/src/java/org/apache/fop/fo/Constants.java @@ -785,8 +785,11 @@ public interface Constants { */ int PR_X_NUMBER_CONVERSION_FEATURES = 276; + /** Scope for table header */ + int PR_X_HEADER_COLUMN = 277; + /** Number of property constants defined */ - int PROPERTY_COUNT = 276; + int PROPERTY_COUNT = 277; // compound property constants diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java index d0d13fc17..a92b71ef9 100644 --- a/src/java/org/apache/fop/fo/FOPropertyMapping.java +++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java @@ -2513,6 +2513,12 @@ public final class FOPropertyMapping implements Constants { m.setInherited(false); m.setDefault("false"); addPropertyMaker("table-omit-header-at-break", m); + + // fox:scope + m = new EnumProperty.Maker(PR_X_HEADER_COLUMN); + m.useGeneric(genericBoolean); + m.setDefault("false"); + addPropertyMaker("fox:header", m); } private void createWritingModeProperties() { diff --git a/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java b/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java index f0e03399f..a040edf1a 100644 --- a/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java +++ b/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java @@ -52,6 +52,7 @@ public class ExtensionElementMapping extends ElementMapping { PROPERTY_ATTRIBUTES.add("disable-column-balancing"); //These are FOP's extension properties for accessibility PROPERTY_ATTRIBUTES.add("alt-text"); + PROPERTY_ATTRIBUTES.add("header"); } /** diff --git a/src/java/org/apache/fop/fo/extensions/InternalElementMapping.java b/src/java/org/apache/fop/fo/extensions/InternalElementMapping.java index 687952d25..f257dd79d 100644 --- a/src/java/org/apache/fop/fo/extensions/InternalElementMapping.java +++ b/src/java/org/apache/fop/fo/extensions/InternalElementMapping.java @@ -43,12 +43,15 @@ public class InternalElementMapping extends ElementMapping { /** The "struct-ref" attribute, to refer to a structure tree element. */ public static final String STRUCT_REF = "struct-ref"; + public static final String SCOPE = "scope"; + private static final Set<String> PROPERTY_ATTRIBUTES = new java.util.HashSet<String>(); static { //These are FOP's extension properties for accessibility PROPERTY_ATTRIBUTES.add(STRUCT_ID); PROPERTY_ATTRIBUTES.add(STRUCT_REF); + PROPERTY_ATTRIBUTES.add(SCOPE); } /** diff --git a/src/java/org/apache/fop/fo/flow/table/TableColumn.java b/src/java/org/apache/fop/fo/flow/table/TableColumn.java index 5047822da..33cbff884 100644 --- a/src/java/org/apache/fop/fo/flow/table/TableColumn.java +++ b/src/java/org/apache/fop/fo/flow/table/TableColumn.java @@ -24,6 +24,7 @@ import org.xml.sax.Locator; import org.apache.fop.apps.FOPException; import org.apache.fop.datatypes.Length; +import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.ValidationException; @@ -44,6 +45,7 @@ public class TableColumn extends TableFObj { private Length columnWidth; private int numberColumnsRepeated; private int numberColumnsSpanned; + private boolean isHeader; // Unused but valid items, commented out for performance: // private int visibility; // End of property values @@ -120,6 +122,7 @@ public class TableColumn extends TableFObj { if (!this.implicitColumn) { this.pList = pList; } + isHeader = (pList.get(Constants.PR_X_HEADER_COLUMN).getEnum() == Constants.EN_TRUE); } /** {@inheritDoc} */ @@ -263,4 +266,13 @@ public class TableColumn extends TableFObj { this.pList = null; } + /** + * Returns {@code true} if this column is made of header cells. + * + * @return {@code true} if cells in this column are like TH cells in HTML + */ + public boolean isHeader() { + return isHeader; + } + } diff --git a/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java b/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java index 0d4a6b7fb..031224ffb 100644 --- a/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java +++ b/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java @@ -30,6 +30,7 @@ import org.apache.fop.accessibility.StructureTreeElement; import org.apache.fop.accessibility.StructureTreeEventHandler; import org.apache.fop.events.EventBroadcaster; import org.apache.fop.fo.extensions.ExtensionElementMapping; +import org.apache.fop.fo.extensions.InternalElementMapping; import org.apache.fop.fo.pagination.Flow; import org.apache.fop.pdf.PDFFactory; import org.apache.fop.pdf.PDFParentTree; @@ -138,7 +139,7 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler { PDFStructElem structElem = createStructureElement(parent, structureType); setAttributes(structElem, attributes); addKidToParent(structElem, parent, attributes); - registerStructureElement(structElem, pdfFactory); + registerStructureElement(structElem, pdfFactory, attributes); return structElem; } @@ -155,7 +156,8 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler { parent.addKid(kid); } - protected void registerStructureElement(PDFStructElem structureElement, PDFFactory pdfFactory) { + protected void registerStructureElement(PDFStructElem structureElement, PDFFactory pdfFactory, + Attributes attributes) { pdfFactory.getDocument().registerStructureElement(structureElement); } @@ -240,22 +242,15 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler { } @Override - protected PDFStructElem createStructureElement(StructureHierarchyMember parent, - StructureType structureType) { - PDFStructElem grandParent = ((PDFStructElem) parent).getParentStructElem(); - //TODO What to do with cells from table-footer? Currently they are mapped on TD. - if (grandParent.getStructureType() == StandardStructureTypes.Table.THEAD) { - structureType = StandardStructureTypes.Table.TH; - } else { - structureType = StandardStructureTypes.Table.TD; - } - return super.createStructureElement(parent, structureType); - } - - @Override - protected void registerStructureElement(PDFStructElem structureElement, PDFFactory pdfFactory) { + protected void registerStructureElement(PDFStructElem structureElement, PDFFactory pdfFactory, + Attributes attributes) { if (structureElement.getStructureType() == Table.TH) { - pdfFactory.getDocument().registerStructureElement(structureElement, Scope.COLUMN); + String scopeAttribute = attributes.getValue(InternalElementMapping.URI, + InternalElementMapping.SCOPE); + Scope scope = (scopeAttribute == null) + ? Scope.COLUMN + : Scope.valueOf(scopeAttribute.toUpperCase(Locale.ENGLISH)); + pdfFactory.getDocument().registerStructureElement(structureElement, scope); } else { pdfFactory.getDocument().registerStructureElement(structureElement); } |