package co.smartreceipts.android.workers.reports.pdf.renderer.grid; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import com.google.common.base.Preconditions; import com.tom_roush.pdfbox.util.awt.AWTColor; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import co.smartreceipts.android.workers.reports.pdf.pdfbox.PdfBoxWriter; import co.smartreceipts.android.workers.reports.pdf.renderer.Renderer; import co.smartreceipts.android.workers.reports.pdf.renderer.constraints.HeightConstraint; import co.smartreceipts.android.workers.reports.pdf.renderer.constraints.WidthConstraint; import co.smartreceipts.android.workers.reports.pdf.renderer.constraints.XPositionConstraint; import co.smartreceipts.android.workers.reports.pdf.renderer.constraints.YPositionConstraint; import co.smartreceipts.android.workers.reports.pdf.renderer.formatting.Alignment; import co.smartreceipts.android.workers.reports.pdf.renderer.formatting.BackgroundColor; import co.smartreceipts.android.workers.reports.pdf.renderer.formatting.Padding; public class GridRowRenderer extends Renderer { private final List<? extends Renderer> columns; private GridRowRenderer header; public GridRowRenderer(@NonNull Renderer renderer) { this(Collections.singletonList(Preconditions.checkNotNull(renderer))); } public GridRowRenderer(@NonNull List<? extends Renderer> columns) { this.columns = new ArrayList<>(Preconditions.checkNotNull(columns)); this.width = MATCH_PARENT; float layoutHeight = WRAP_CONTENT; for (final Renderer column : columns) { // We'll use match parent if any of them are set to that if (column.getHeight() == MATCH_PARENT) { layoutHeight = MATCH_PARENT; break; } } this.height = layoutHeight; } public void associateHeaderRow(@Nullable GridRowRenderer header) { this.header = header; } @Nullable public GridRowRenderer getAssociatedHeader() { return header; } @NonNull @Override public Renderer copy() { final List<Renderer> renderers = new ArrayList<>(); for (final Renderer renderer : this.columns) { renderers.add(renderer.copy()); } final GridRowRenderer copy = new GridRowRenderer(renderers); copy.header = this.header; copy.height = this.height; copy.width = this.width; copy.getRenderingConstraints().setConstraints(this.getRenderingConstraints()); copy.getRenderingFormatting().setFormatting(this.getRenderingFormatting()); return copy; } @Override public void measure() throws IOException { final float x = Preconditions.checkNotNull(getRenderingConstraints().getConstraint(XPositionConstraint.class, 0f)); final float y = Preconditions.checkNotNull(getRenderingConstraints().getConstraint(YPositionConstraint.class, 0f)); final float widthConstraint = Preconditions.checkNotNull(getRenderingConstraints().getConstraint(WidthConstraint.class)); final Float heightConstraint = getRenderingConstraints().getConstraint(HeightConstraint.class); final Float padding = getRenderingFormatting().getFormatting(Padding.class); if (padding != null) { for (final Renderer renderer : columns) { renderer.getRenderingFormatting().addFormatting(new Padding(padding)); } } final AWTColor backgroundColor = getRenderingFormatting().getFormatting(BackgroundColor.class); if (backgroundColor != null) { for (final Renderer renderer : columns) { renderer.getRenderingFormatting().addFormatting(new BackgroundColor(backgroundColor)); } } final Alignment.Type alignment = getRenderingFormatting().getFormatting(Alignment.class); if (alignment != null) { for (final Renderer renderer : columns) { renderer.getRenderingFormatting().addFormatting(new Alignment(alignment)); } } float unconstrainedWidth = widthConstraint; int constrainedByWidthColumnCount = 0; for (int i = 0; i < columns.size(); i++) { final Float columnWidthConstraint = columns.get(i).getRenderingConstraints().getConstraint(WidthConstraint.class); if (columnWidthConstraint != null) { unconstrainedWidth -= columnWidthConstraint; constrainedByWidthColumnCount++; } } final WidthConstraint remainingColumnsWidthConstraint; if (constrainedByWidthColumnCount != columns.size()) { final float unconstrainedPerColumnWidthConstraint = unconstrainedWidth / (columns.size() - constrainedByWidthColumnCount); remainingColumnsWidthConstraint = new WidthConstraint(unconstrainedPerColumnWidthConstraint); } else { remainingColumnsWidthConstraint = null; } // First - measure out all our widths float measuredHeight = -1; float currentXPosition = x; for (int i = 0; i < columns.size(); i++) { final Renderer column = columns.get(i); // TODO: Refactor this if we use dynamic formatting for the first tables if (heightConstraint != null) { column.getRenderingConstraints().addConstraint(new HeightConstraint(heightConstraint)); } if (!column.getRenderingConstraints().hasConstraint(WidthConstraint.class)) { column.getRenderingConstraints().addConstraint(remainingColumnsWidthConstraint); } column.getRenderingConstraints().addConstraint(new XPositionConstraint(currentXPosition)); column.getRenderingConstraints().addConstraint(new YPositionConstraint(y)); column.measure(); final Float columnWidthConstraint = column.getRenderingConstraints().getConstraint(WidthConstraint.class); currentXPosition += columnWidthConstraint; measuredHeight = Math.max(measuredHeight, column.getHeight()); } this.width = widthConstraint; this.height = measuredHeight; } @Override public void render(@NonNull PdfBoxWriter writer) throws IOException { final AWTColor backgroundColor = getRenderingFormatting().getFormatting(BackgroundColor.class); if (backgroundColor != null) { float x = Preconditions.checkNotNull(getRenderingConstraints().getConstraint(XPositionConstraint.class)); float y = Preconditions.checkNotNull(getRenderingConstraints().getConstraint(YPositionConstraint.class)); writer.printRectangle(backgroundColor, x, y, width, height); } for (final Renderer column : columns) { column.render(writer); } } }