package gutenberg.itext.pegdown;
import com.google.common.base.Optional;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfPTableEvent;
import gutenberg.pegdown.TreeNavigation;
import gutenberg.pegdown.plugin.AttributesNode;
import gutenberg.util.Attributes;
import gutenberg.util.Dimension;
import gutenberg.util.DimensionFormatException;
import gutenberg.util.KeyValues;
import org.pegdown.ast.Node;
import org.pegdown.ast.TableColumnNode;
import org.pegdown.ast.TableNode;
import java.util.List;
import static gutenberg.pegdown.TreeNavigation.*;
/**
* @author <a href="http://twitter.com/aloyer">@aloyer</a>
*/
public class TableNodeProcessor extends Processor {
public static final Object TABLE_SPACING_BEFORE = "table-spacing-before";
public static final Object TABLE_SPACING_AFTER = "table-spacing-after";
private final PdfPTableEvent[] tableEvents;
public TableNodeProcessor(PdfPTableEvent... tableEvents) {
this.tableEvents = tableEvents;
}
@Override
public void process(int level, Node node, InvocationContext context) {
TableNode tableNode = (TableNode) node;
List<TableColumnNode> tableNodeColumns = tableNode.getColumns();
PdfPTable table = new PdfPTable(tableNodeColumns.size());
for (PdfPTableEvent tableEvent : tableEvents) {
table.setTableEvent(tableEvent);
}
context.pushTable(new TableInfos(table, tableNodeColumns));
context.processChildren(level, node);
context.popTable();
KeyValues kvs = context.iTextContext().keyValues();
Float spacingBefore = kvs.<Float>getNullable(TABLE_SPACING_BEFORE).or(5f);
Float spacingAfter = kvs.<Float>getNullable(TABLE_SPACING_AFTER).or(5f);
table.setSpacingBefore(spacingBefore);
table.setSpacingAfter(spacingAfter);
applyAttributes(context, table);
context.append(table);
}
private void applyAttributes(InvocationContext context, PdfPTable table) {
Attributes attributes = lookupAttributes(context);
Dimension width = readWidth(attributes);
if (width != null) {
switch (width.unit()) {
case Percent:
table.setWidthPercentage(width.amount());
break;
case Px:
default:
table.setTotalWidth(width.amount());
break;
}
}
}
private Attributes lookupAttributes(InvocationContext context) {
TreeNavigation nav = context.treeNavigation();
Optional<TreeNavigation> attrNode =
firstAncestorOfType(TableNode.class)
.then(siblingBefore())
.then(ofType(AttributesNode.class))
.query(nav);
Attributes attributes;
if (attrNode.isPresent()) {
attributes = attrNode.get().peek(AttributesNode.class).asAttributes();
} else {
attributes = new Attributes();
}
return attributes;
}
private Dimension readWidth(Attributes attributes) {
try {
return attributes.getDimension("width");
} catch (DimensionFormatException e) {
log.warn("Unreadable width {}", attributes.getString("width"));
return null;
}
}
}