Bug 491864 - Add support for printing multiple NatTable instances in one
job
Change-Id: I613e8644340ad9398890991ca654b5cc541a1f79
Signed-off-by: Dirk Fauth <dirk.fauth@googlemail.com>
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/print/LayerPrinter.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/print/LayerPrinter.java
index 0e285ad..8b0c548 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/print/LayerPrinter.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/print/LayerPrinter.java
@@ -11,7 +11,9 @@
package org.eclipse.nebula.widgets.nattable.print;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.Date;
+import java.util.List;
import org.eclipse.nebula.widgets.nattable.Messages;
import org.eclipse.nebula.widgets.nattable.config.CellConfigAttributes;
@@ -51,9 +53,21 @@
*/
public class LayerPrinter {
- private final IConfigRegistry configRegistry;
- private final ILayer layer;
- private final IClientAreaProvider originalClientAreaProvider;
+ private class PrintTarget {
+
+ private final IConfigRegistry configRegistry;
+ private final ILayer layer;
+ private final IClientAreaProvider originalClientAreaProvider;
+
+ PrintTarget(ILayer layer, IConfigRegistry configRegistry) {
+ this.layer = layer;
+ this.configRegistry = configRegistry;
+ this.originalClientAreaProvider = layer.getClientAreaProvider();
+ }
+ }
+
+ private final List<PrintTarget> printTargets = new ArrayList<PrintTarget>();
+
public static final int FOOTER_HEIGHT_IN_PRINTER_DPI = 300;
final SimpleDateFormat dateFormat;
@@ -79,9 +93,7 @@
* The ConfigRegistry needed for rendering to the print GC.
*/
public LayerPrinter(ILayer layer, IConfigRegistry configRegistry) {
- this.layer = layer;
- this.configRegistry = configRegistry;
- this.originalClientAreaProvider = layer.getClientAreaProvider();
+ this.printTargets.add(new PrintTarget(layer, configRegistry));
// configure the footer height
Integer fh = configRegistry.getConfigAttribute(
@@ -109,8 +121,27 @@
}
/**
+ * Adds the given {@link ILayer} as print target. It can be used to register
+ * multiple NatTable or layer stacks in one print job.
+ *
+ * @param layer
+ * The {@link ILayer} that should be printed together with the
+ * main {@link ILayer} registered via constructor.
+ * @param configRegistry
+ * The {@link IConfigRegistry} that should be used to print the
+ * given {@link ILayer}.
+ *
+ * @since 1.5
+ */
+ public void addPrintTarget(ILayer layer, IConfigRegistry configRegistry) {
+ this.printTargets.add(new PrintTarget(layer, configRegistry));
+ }
+
+ /**
* Computes the scale factor to match the printer resolution.
*
+ * @param layer
+ * The layer for which the scale factor should be calculated.
* @param printer
* The printer that will be used.
* @param dpi
@@ -121,7 +152,7 @@
* @return The amount to scale the screen resolution by, to match the
* printer the resolution.
*/
- private float[] computeScaleFactor(Printer printer, boolean dpi) {
+ private float[] computeScaleFactor(ILayer layer, Printer printer, boolean dpi) {
Point screenDPI = Display.getDefault().getDPI();
Point printerDPI = printer.getDPI();
@@ -129,7 +160,7 @@
float sfY = Float.valueOf(printerDPI.y) / Float.valueOf(screenDPI.y);
if (!dpi && (this.fittingMode != Direction.NONE)) {
- Rectangle total = getTotalArea();
+ Rectangle total = getTotalArea(layer);
Rectangle print = computePrintArea(printer);
float pixelX = Float.valueOf(print.width) / Float.valueOf(total.width);
@@ -149,36 +180,57 @@
}
/**
+ * @param layer
+ * The layer for which the total area is requested.
* @return The size of the layer to fit all the contents.
*/
- private Rectangle getTotalArea() {
- return new Rectangle(0, 0, this.layer.getWidth(), this.layer.getHeight());
+ private Rectangle getTotalArea(ILayer layer) {
+ return new Rectangle(0, 0, layer.getWidth(), layer.getHeight());
+ }
+
+ /**
+ * Calculates number of horizontal and vertical pages needed to print all
+ * registered layers.
+ *
+ * @param printer
+ * The printer that will be used.
+ * @return The number of pages that are needed to print.
+ */
+ private int getPageCount(Printer printer) {
+ int result = 0;
+ for (PrintTarget target : this.printTargets) {
+ Point layerResult = getPageCount(target, printer);
+ result += (layerResult.x * layerResult.y);
+ }
+ return result;
}
/**
* Calculates number of horizontal and vertical pages needed to print the
- * entire layer.
+ * entire layer of the given print target.
*
+ * @param target
+ * The print target to print.
* @param printer
* The printer that will be used.
* @return The number of horizontal and vertical pages that are needed to
- * print the layer.
+ * print the layer of the given print target.
*/
- private Point getPageCount(Printer printer) {
+ private Point getPageCount(PrintTarget target, Printer printer) {
Rectangle printArea = computePrintArea(printer);
- float[] scaleFactor = computeScaleFactor(printer, false);
+ float[] scaleFactor = computeScaleFactor(target.layer, printer, false);
- Integer[] gridLineWidth = getGridLineWidth();
+ Integer[] gridLineWidth = getGridLineWidth(target.configRegistry);
// calculate pages based on non cut off columns/rows
int numOfHorizontalPages = 0;
- int pageWidth = Float.valueOf(printArea.width / scaleFactor[0]).intValue();
+ int pageWidth = Math.round(Float.valueOf(printArea.width / scaleFactor[0]));
int endX = 0;
- while (endX < this.layer.getWidth()) {
+ while (endX < target.layer.getWidth()) {
endX += pageWidth;
- int colPos = this.layer.getColumnPositionByX(endX);
+ int colPos = target.layer.getColumnPositionByX(endX);
if (colPos >= 0) {
- ILayerCell cell = findColumnCellForBounds(colPos);
+ ILayerCell cell = findColumnCellForBounds(target.layer, colPos);
if (cell != null) {
Rectangle cellBounds = cell.getBounds();
if (cellBounds.x < endX) {
@@ -187,20 +239,20 @@
}
}
} else {
- endX = this.layer.getWidth();
+ endX = target.layer.getWidth();
}
numOfHorizontalPages++;
}
int numOfVerticalPages = 0;
- int pageHeight = Float.valueOf((printArea.height - getFooterHeightInPrinterDPI()) / scaleFactor[1]).intValue();
+ int pageHeight = Math.round(Float.valueOf((printArea.height - getFooterHeightInPrinterDPI()) / scaleFactor[1]));
int endY = 0;
- while (endY < this.layer.getHeight()) {
+ while (endY < target.layer.getHeight()) {
endY += pageHeight;
- int rowPos = this.layer.getRowPositionByY(endY);
+ int rowPos = target.layer.getRowPositionByY(endY);
if (rowPos >= 0) {
- ILayerCell cell = findRowCellForBounds(rowPos);
+ ILayerCell cell = findRowCellForBounds(target.layer, rowPos);
if (cell != null) {
Rectangle cellBounds = cell.getBounds();
if (cellBounds.y < endY) {
@@ -209,37 +261,37 @@
}
}
} else {
- endY = this.layer.getHeight();
+ endY = target.layer.getHeight();
}
numOfVerticalPages++;
}
if (gridLineWidth[0] == null) {
- LayerPrinter.this.configRegistry.unregisterConfigAttribute(CellConfigAttributes.GRID_LINE_WIDTH);
+ target.configRegistry.unregisterConfigAttribute(CellConfigAttributes.GRID_LINE_WIDTH);
}
return new Point(numOfHorizontalPages, numOfVerticalPages);
}
- private ILayerCell findColumnCellForBounds(int colPos) {
+ private ILayerCell findColumnCellForBounds(ILayer layer, int colPos) {
int rowPos = 0;
- ILayerCell cell = this.layer.getCellByPosition(colPos, rowPos);
+ ILayerCell cell = layer.getCellByPosition(colPos, rowPos);
while (cell != null && cell.isSpannedCell()) {
// if the cell is spanned, check the cell at the next row
rowPos++;
- cell = this.layer.getCellByPosition(colPos, rowPos);
+ cell = layer.getCellByPosition(colPos, rowPos);
}
return cell;
}
- private ILayerCell findRowCellForBounds(int rowPos) {
+ private ILayerCell findRowCellForBounds(ILayer layer, int rowPos) {
int colPos = 0;
- ILayerCell cell = this.layer.getCellByPosition(colPos, rowPos);
+ ILayerCell cell = layer.getCellByPosition(colPos, rowPos);
while (cell != null && cell.isSpannedCell()) {
// if the cell is spanned, check the cell at the next column
colPos++;
- cell = this.layer.getCellByPosition(colPos, rowPos);
+ cell = layer.getCellByPosition(colPos, rowPos);
}
return cell;
}
@@ -254,20 +306,23 @@
}
/**
+ * @param configRegistry
+ * The {@link IConfigRegistry} to retrieve the grid line width
+ * from.
* @return Integer array that contains the original configured width at
* index 0 and the grid line width to use at index 1.
* @since 1.5
*/
- protected Integer[] getGridLineWidth() {
+ protected Integer[] getGridLineWidth(IConfigRegistry configRegistry) {
// check if a grid line width is configured
- Integer width = LayerPrinter.this.configRegistry.getConfigAttribute(
+ Integer width = configRegistry.getConfigAttribute(
CellConfigAttributes.GRID_LINE_WIDTH,
DisplayMode.NORMAL);
Integer gridLineWidth = width;
// if no explicit width is set, we temporary specify a grid line
// width of 2 for optimized grid line printing
if (width == null) {
- LayerPrinter.this.configRegistry.registerConfigAttribute(
+ configRegistry.registerConfigAttribute(
CellConfigAttributes.GRID_LINE_WIDTH, 2);
gridLineWidth = 2;
}
@@ -284,7 +339,9 @@
public void print(final Shell shell) {
// turn viewport off to ensure calculation of the print pages for the
// whole table
- this.layer.doCommand(new TurnViewportOffCommand());
+ for (PrintTarget target : this.printTargets) {
+ target.layer.doCommand(new TurnViewportOffCommand());
+ }
Printer printer = null;
try {
@@ -294,7 +351,9 @@
}
} finally {
// turn viewport on
- this.layer.doCommand(new TurnViewportOnCommand());
+ for (PrintTarget target : this.printTargets) {
+ target.layer.doCommand(new TurnViewportOnCommand());
+ }
}
// Note: As we are operating on the same layer instance that is shown in
@@ -338,12 +397,12 @@
*/
private Printer setupPrinter(final Shell shell) {
Printer defaultPrinter = new Printer();
- Point pageCount = getPageCount(defaultPrinter);
+ int pageCount = getPageCount(defaultPrinter);
defaultPrinter.dispose();
final PrintDialog printDialog = new PrintDialog(shell);
printDialog.setStartPage(1);
- printDialog.setEndPage(pageCount.x * pageCount.y);
+ printDialog.setEndPage(pageCount);
printDialog.setScope(PrinterData.ALL_PAGES);
PrinterData printerData = printDialog.open();
@@ -432,139 +491,153 @@
@Override
public void run() {
- LayerPrinter.this.layer.doCommand(new TurnViewportOffCommand());
- float[] scaleFactor = null;
- float[] dpiFactor = null;
- try {
- scaleFactor = computeScaleFactor(this.printer, false);
- dpiFactor = computeScaleFactor(this.printer, true);
- } finally {
- LayerPrinter.this.layer.doCommand(new TurnViewportOnCommand());
- }
-
- Integer[] gridLineWidth = getGridLineWidth();
-
- // if pre-rendering is enabled, render in-memory to trigger content
- // based auto-resizing
- if (LayerPrinter.this.preRender) {
- Transform tempTransform = new Transform(this.printer);
- tempTransform.scale(scaleFactor[0], scaleFactor[1]);
- AutoResizeHelper.autoResize(LayerPrinter.this.layer, LayerPrinter.this.configRegistry);
- tempTransform.dispose();
- }
-
if (this.printer.startJob("NatTable")) { //$NON-NLS-1$
+ GC gc = new GC(this.printer);
try {
- // if a SummaryRowLayer is in the layer stack, we need to
- // ensure that the values are calculated
- LayerPrinter.this.layer.doCommand(new CalculateSummaryRowValuesCommand());
-
- // ensure that the viewport is turned off
- LayerPrinter.this.layer.doCommand(new TurnViewportOffCommand());
-
- // ensure that formula processing is performed in the
- // current thread
- LayerPrinter.this.layer.doCommand(new DisableFormulaCachingCommand());
-
- // set the size of the layer according to the print
- // settings made by the user
- setLayerSize(this.printer.getPrinterData());
-
- final Rectangle printerClientArea = computePrintArea(this.printer);
- final int printBoundsWidth = Float.valueOf(printerClientArea.width / scaleFactor[0]).intValue();
- int printBoundsHeight = Float.valueOf((printerClientArea.height - getFooterHeightInPrinterDPI()) / scaleFactor[1]).intValue();
-
- final Point pageCount = getPageCount(this.printer);
- GC gc = new GC(this.printer);
-
- // Print pages Left to Right and then Top to Down
int currentPage = 1;
- int startY = 0;
- for (int verticalPageNumber = 0; verticalPageNumber < pageCount.y; verticalPageNumber++) {
-
- int endY = startY + printBoundsHeight;
- int rowPos = LayerPrinter.this.layer.getRowPositionByY(endY);
- if (rowPos >= 0) {
- ILayerCell cell = findRowCellForBounds(rowPos);
- if (cell != null) {
- Rectangle cellBounds = cell.getBounds();
- if (cellBounds.y < endY) {
- printBoundsHeight -= (endY - cellBounds.y);
- }
- }
+ for (PrintTarget target : LayerPrinter.this.printTargets) {
+ target.layer.doCommand(new TurnViewportOffCommand());
+ float[] scaleFactor = null;
+ float[] dpiFactor = null;
+ try {
+ scaleFactor = computeScaleFactor(target.layer, this.printer, false);
+ dpiFactor = computeScaleFactor(target.layer, this.printer, true);
+ } finally {
+ target.layer.doCommand(new TurnViewportOnCommand());
}
- int startX = 0;
- for (int horizontalPageNumber = 0; horizontalPageNumber < pageCount.x; horizontalPageNumber++) {
+ Integer[] gridLineWidth = getGridLineWidth(target.configRegistry);
- // Calculate bounds for the next page
- Rectangle printBounds = new Rectangle(
- startX,
- startY,
- printBoundsWidth,
- printBoundsHeight);
+ // if pre-rendering is enabled, render in-memory to
+ // trigger content based auto-resizing
+ if (LayerPrinter.this.preRender) {
+ Transform tempTransform = new Transform(this.printer);
+ tempTransform.scale(scaleFactor[0], scaleFactor[1]);
+ AutoResizeHelper.autoResize(target.layer, target.configRegistry);
+ tempTransform.dispose();
+ }
- int endX = startX + printBounds.width;
- int colPos = LayerPrinter.this.layer.getColumnPositionByX(endX);
- if (colPos >= 0) {
- ILayerCell cell = findColumnCellForBounds(colPos);
- if (cell != null) {
- Rectangle cellBounds = cell.getBounds();
- if (cellBounds.x < endX) {
- printBounds.width -= (endX - cellBounds.x);
+ try {
+ // if a SummaryRowLayer is in the layer stack, we
+ // need to ensure that the values are calculated
+ target.layer.doCommand(new CalculateSummaryRowValuesCommand());
+
+ // ensure that the viewport is turned off
+ target.layer.doCommand(new TurnViewportOffCommand());
+
+ // ensure that formula processing is performed in
+ // the current thread
+ target.layer.doCommand(new DisableFormulaCachingCommand());
+
+ // set the size of the layer according to the print
+ // settings made by the user
+ setLayerSize(target, this.printer.getPrinterData());
+
+ final Rectangle printerClientArea = computePrintArea(this.printer);
+ final int printBoundsWidth = Math.round(Float.valueOf(printerClientArea.width / scaleFactor[0]));
+ int printBoundsHeight = Math.round(Float.valueOf((printerClientArea.height - getFooterHeightInPrinterDPI()) / scaleFactor[1]));
+
+ final Point pageCount = getPageCount(target, this.printer);
+
+ // Print pages Left to Right and then Top to Down
+ int startY = 0;
+ for (int verticalPageNumber = 0; verticalPageNumber < pageCount.y; verticalPageNumber++) {
+
+ int endY = startY + printBoundsHeight;
+ // int rowPos =
+ // target.layer.getRowPositionByY(endY);
+ int rowPos = target.layer.getRowPositionByY(endY);
+ if (rowPos >= 0) {
+ ILayerCell cell = findRowCellForBounds(target.layer, rowPos);
+ if (cell != null) {
+ Rectangle cellBounds = cell.getBounds();
+ if (cellBounds.y < endY) {
+ printBoundsHeight -= (endY - cellBounds.y);
+ }
}
}
+
+ int startX = 0;
+ for (int horizontalPageNumber = 0; horizontalPageNumber < pageCount.x; horizontalPageNumber++) {
+
+ // Calculate bounds for the next page
+ Rectangle printBounds = new Rectangle(
+ startX,
+ startY,
+ printBoundsWidth,
+ printBoundsHeight);
+
+ int endX = startX + printBounds.width;
+ int colPos = target.layer.getColumnPositionByX(endX);
+ if (colPos >= 0) {
+ ILayerCell cell = findColumnCellForBounds(target.layer, colPos);
+ if (cell != null) {
+ Rectangle cellBounds = cell.getBounds();
+ if (cellBounds.x < endX) {
+ printBounds.width -= (endX - cellBounds.x);
+ }
+ }
+ }
+
+ Rectangle footerBounds = new Rectangle(
+ Math.round(Float.valueOf((printerClientArea.width / dpiFactor[0]) * horizontalPageNumber)),
+ Math.round(Float.valueOf(((printerClientArea.height - getFooterHeightInPrinterDPI()) / dpiFactor[1]) * verticalPageNumber)),
+ Math.round(Float.valueOf(printerClientArea.width / dpiFactor[0])),
+ Math.round(Float.valueOf((printerClientArea.height - getFooterHeightInPrinterDPI()) / dpiFactor[1])));
+
+ if (shouldPrint(this.printer.getPrinterData(), currentPage)) {
+ this.printer.startPage();
+
+ Transform printerTransform = new Transform(this.printer);
+ Transform footerTransform = new Transform(this.printer);
+
+ // FIXME
+ Rectangle intersect = new Rectangle(
+ 0,
+ 0,
+ target.layer.getWidth(),
+ target.layer.getHeight());
+
+ intersect = printBounds.intersection(intersect);
+
+ configureScalingTransform(printerTransform, scaleFactor, printerClientArea, intersect);
+ configureScalingTransform(footerTransform, dpiFactor, printerClientArea, footerBounds);
+
+ gc.setTransform(printerTransform);
+ printLayer(target, gc, intersect);
+
+ gc.setTransform(footerTransform);
+ printFooter(gc, currentPage, footerBounds, target.configRegistry);
+
+ this.printer.endPage();
+ printerTransform.dispose();
+ footerTransform.dispose();
+ }
+ currentPage++;
+
+ startX += printBounds.width;
+ }
+ startY += printBoundsHeight;
}
- Rectangle footerBounds = new Rectangle(
- Float.valueOf((printerClientArea.width / dpiFactor[0]) * horizontalPageNumber).intValue(),
- Float.valueOf(((printerClientArea.height - getFooterHeightInPrinterDPI()) / dpiFactor[1]) * verticalPageNumber).intValue(),
- Float.valueOf(printerClientArea.width / dpiFactor[0]).intValue(),
- Float.valueOf((printerClientArea.height - getFooterHeightInPrinterDPI()) / dpiFactor[1]).intValue());
-
- if (shouldPrint(this.printer.getPrinterData(), currentPage)) {
- this.printer.startPage();
-
- Transform printerTransform = new Transform(this.printer);
- Transform footerTransform = new Transform(this.printer);
-
- configureScalingTransform(printerTransform, scaleFactor, printerClientArea, printBounds);
- configureScalingTransform(footerTransform, dpiFactor, printerClientArea, footerBounds);
-
- gc.setTransform(printerTransform);
- printLayer(gc, printBounds);
-
- gc.setTransform(footerTransform);
- printFooter(gc, currentPage, footerBounds);
-
- this.printer.endPage();
- printerTransform.dispose();
- footerTransform.dispose();
- }
- currentPage++;
-
- startX += printBounds.width - gridLineWidth[1];
+ } finally {
+ restoreLayerState(target);
}
- startY += printBoundsHeight - gridLineWidth[1];
+
+ // there was no explicit width configured, so we
+ // configured a temporary one for grid line printing.
+ // this configuration needs to be removed again
+ if (gridLineWidth[0] == null) {
+ target.configRegistry.unregisterConfigAttribute(CellConfigAttributes.GRID_LINE_WIDTH);
+ }
}
-
+ } finally {
this.printer.endJob();
-
gc.dispose();
this.printer.dispose();
- } finally {
- restoreLayerState();
}
}
-
- // there was no explicit width configured, so we configured a
- // temporary one for grid line printing. this configuration needs to
- // be removed again
- if (gridLineWidth[0] == null) {
- LayerPrinter.this.configRegistry.unregisterConfigAttribute(CellConfigAttributes.GRID_LINE_WIDTH);
- }
-
}
/**
@@ -606,17 +679,19 @@
* size needs to be extended so that all the contents fit in the
* viewport to ensure that we print the <i>entire</i> table.
*
+ * @param target
+ * The print target to print.
* @param printerData
* The PrinterData that was configured by the user on the
* PrintDialog.
*/
- private void setLayerSize(PrinterData printerData) {
+ private void setLayerSize(PrintTarget target, PrinterData printerData) {
if (printerData != null && printerData.scope == PrinterData.SELECTION) {
- LayerPrinter.this.layer.setClientAreaProvider(LayerPrinter.this.originalClientAreaProvider);
+ target.layer.setClientAreaProvider(target.originalClientAreaProvider);
} else {
- final Rectangle fullLayerSize = getTotalArea();
+ final Rectangle fullLayerSize = getTotalArea(target.layer);
- LayerPrinter.this.layer.setClientAreaProvider(new IClientAreaProvider() {
+ target.layer.setClientAreaProvider(new IClientAreaProvider() {
@Override
public Rectangle getClientArea() {
return fullLayerSize;
@@ -626,21 +701,23 @@
// in case the whole layer should be printed or only the
// selected pages, we need to ensure to set the starting point
// to 0/0
- LayerPrinter.this.layer.doCommand(new PrintEntireGridCommand());
+ target.layer.doCommand(new PrintEntireGridCommand());
}
}
/**
* Print the part of the layer that matches the given print bounds.
*
+ * @param target
+ * The print target to print
* @param gc
* The print GC to render the layer to.
* @param printBounds
* The bounds of the print page.
*/
- private void printLayer(GC gc, Rectangle printBounds) {
- LayerPrinter.this.layer.getLayerPainter().paintLayer(
- LayerPrinter.this.layer, gc, 0, 0, printBounds, LayerPrinter.this.configRegistry);
+ private void printLayer(PrintTarget target, GC gc, Rectangle printBounds) {
+ target.layer.getLayerPainter().paintLayer(
+ target.layer, gc, 0, 0, printBounds, target.configRegistry);
}
/**
@@ -652,8 +729,11 @@
* The total number of pages that are printed.
* @param printBounds
* The bounds of the print page.
+ * @param configRegistry
+ * The {@link IConfigRegistry} needed to retrieve the footer
+ * style.
*/
- private void printFooter(GC gc, int totalPageCount, Rectangle printBounds) {
+ private void printFooter(GC gc, int totalPageCount, Rectangle printBounds, IConfigRegistry configRegistry) {
Color oldForeground = gc.getForeground();
Color oldBackground = gc.getBackground();
Font oldFont = gc.getFont();
@@ -662,7 +742,7 @@
Color footerBackground = null;
Font footerFont = null;
- IStyle style = LayerPrinter.this.configRegistry.getConfigAttribute(
+ IStyle style = configRegistry.getConfigAttribute(
PrintConfigAttributes.FOOTER_STYLE,
DisplayMode.NORMAL);
if (style != null) {
@@ -699,11 +779,14 @@
* Restores the layer state to match the display characteristics again.
* This is done by resetting the client area provider, turning the
* viewport on and enabling formula result caching again.
+ *
+ * @param target
+ * The print target whose state should be restarted.
*/
- private void restoreLayerState() {
- LayerPrinter.this.layer.setClientAreaProvider(LayerPrinter.this.originalClientAreaProvider);
- LayerPrinter.this.layer.doCommand(new TurnViewportOnCommand());
- LayerPrinter.this.layer.doCommand(new EnableFormulaCachingCommand());
+ private void restoreLayerState(PrintTarget target) {
+ target.layer.setClientAreaProvider(target.originalClientAreaProvider);
+ target.layer.doCommand(new TurnViewportOnCommand());
+ target.layer.doCommand(new EnableFormulaCachingCommand());
}
}
diff --git a/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_700_AdditionalFunctions/_762_MultiPrintExample.java b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_700_AdditionalFunctions/_762_MultiPrintExample.java
new file mode 100644
index 0000000..07f869a
--- /dev/null
+++ b/org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_700_AdditionalFunctions/_762_MultiPrintExample.java
@@ -0,0 +1,223 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Dirk Fauth and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Dirk Fauth <dirk.fauth@googlemail.com> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.nebula.widgets.nattable.examples._700_AdditionalFunctions;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.nebula.widgets.nattable.NatTable;
+import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration;
+import org.eclipse.nebula.widgets.nattable.data.ExtendedReflectiveColumnPropertyAccessor;
+import org.eclipse.nebula.widgets.nattable.data.IColumnPropertyAccessor;
+import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
+import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
+import org.eclipse.nebula.widgets.nattable.dataset.person.Person;
+import org.eclipse.nebula.widgets.nattable.dataset.person.PersonService;
+import org.eclipse.nebula.widgets.nattable.dataset.person.PersonWithAddress;
+import org.eclipse.nebula.widgets.nattable.examples.AbstractNatExample;
+import org.eclipse.nebula.widgets.nattable.examples.runner.StandaloneNatExampleRunner;
+import org.eclipse.nebula.widgets.nattable.grid.data.DefaultBodyDataProvider;
+import org.eclipse.nebula.widgets.nattable.grid.data.DefaultColumnHeaderDataProvider;
+import org.eclipse.nebula.widgets.nattable.grid.data.DefaultCornerDataProvider;
+import org.eclipse.nebula.widgets.nattable.grid.data.DefaultRowHeaderDataProvider;
+import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer;
+import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer;
+import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultColumnHeaderDataLayer;
+import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultRowHeaderDataLayer;
+import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer;
+import org.eclipse.nebula.widgets.nattable.grid.layer.RowHeaderLayer;
+import org.eclipse.nebula.widgets.nattable.hideshow.ColumnHideShowLayer;
+import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
+import org.eclipse.nebula.widgets.nattable.layer.ILayer;
+import org.eclipse.nebula.widgets.nattable.print.LayerPrinter;
+import org.eclipse.nebula.widgets.nattable.print.command.PrintCommand;
+import org.eclipse.nebula.widgets.nattable.print.command.PrintCommandHandler;
+import org.eclipse.nebula.widgets.nattable.print.config.DefaultPrintBindings;
+import org.eclipse.nebula.widgets.nattable.reorder.ColumnReorderLayer;
+import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
+import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+public class _762_MultiPrintExample extends AbstractNatExample {
+
+ public static void main(String[] args) throws Exception {
+ StandaloneNatExampleRunner.run(new _762_MultiPrintExample());
+ }
+
+ @Override
+ public String getDescription() {
+ return "This example shows how to trigger printing of multiple NatTable instances in one print job";
+ }
+
+ @Override
+ public Control createExampleControl(Composite parent) {
+ Composite panel = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ panel.setLayout(layout);
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(panel);
+
+ Composite gridPanel = new Composite(panel, SWT.NONE);
+ gridPanel.setLayout(layout);
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(gridPanel);
+
+ Composite buttonPanel = new Composite(panel, SWT.NONE);
+ buttonPanel.setLayout(new GridLayout());
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(buttonPanel);
+
+ NatTable natTable = createSmallTable(gridPanel);
+ NatTable grid = createGrid(gridPanel);
+
+ // create a custom command handler for printing of multiple NatTable
+ // instances
+ PrintCommandHandler handler = new PrintCommandHandler(natTable.getLayer()) {
+ @Override
+ public boolean doCommand(PrintCommand command) {
+ LayerPrinter printer = new LayerPrinter(natTable.getLayer(), natTable.getConfigRegistry());
+ printer.addPrintTarget(grid.getLayer(), grid.getConfigRegistry());
+ printer.print(natTable.getShell());
+ return true;
+ };
+ };
+
+ // register the handler to both NatTable instances
+ natTable.getLayer().registerCommandHandler(handler);
+ grid.getLayer().registerCommandHandler(handler);
+
+ Button addColumnButton = new Button(buttonPanel, SWT.PUSH);
+ addColumnButton.setText("Print");
+ addColumnButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ natTable.doCommand(
+ new PrintCommand(
+ natTable.getConfigRegistry(),
+ natTable.getShell()));
+ }
+ });
+
+ return panel;
+ }
+
+ private NatTable createSmallTable(Composite parent) {
+ // property names of the Person class
+ String[] propertyNames = { "firstName", "lastName", "gender",
+ "married", "birthday" };
+
+ // mapping from property to label, needed for column header labels
+ Map<String, String> propertyToLabelMap = new HashMap<String, String>();
+ propertyToLabelMap.put("firstName", "Firstname");
+ propertyToLabelMap.put("lastName", "Lastname");
+ propertyToLabelMap.put("gender", "Gender");
+ propertyToLabelMap.put("married", "Married");
+ propertyToLabelMap.put("birthday", "Birthday");
+
+ IDataProvider bodyDataProvider =
+ new DefaultBodyDataProvider<Person>(
+ PersonService.getPersons(150), propertyNames);
+ DataLayer bodyDataLayer = new DataLayer(bodyDataProvider);
+ SelectionLayer selectionLayer = new SelectionLayer(bodyDataLayer);
+ ViewportLayer viewportLayer = new ViewportLayer(selectionLayer);
+
+ final NatTable natTable = new NatTable(parent, viewportLayer, false);
+
+ // adding this configuration adds the styles and the painters to use
+ natTable.addConfiguration(new DefaultNatTableStyleConfiguration());
+ natTable.addConfiguration(new DefaultPrintBindings());
+
+ natTable.configure();
+
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(natTable);
+
+ return natTable;
+ }
+
+ private NatTable createGrid(Composite parent) {
+ // property names of the Person class
+ String[] propertyNames = { "firstName", "lastName", "gender",
+ "married", "birthday", "address.street", "address.housenumber",
+ "address.postalCode", "address.city" };
+
+ // mapping from property to label, needed for column header labels
+ Map<String, String> propertyToLabelMap = new HashMap<String, String>();
+ propertyToLabelMap.put("firstName", "Firstname");
+ propertyToLabelMap.put("lastName", "Lastname");
+ propertyToLabelMap.put("gender", "Gender");
+ propertyToLabelMap.put("married", "Married");
+ propertyToLabelMap.put("birthday", "Birthday");
+ propertyToLabelMap.put("address.street", "Street");
+ propertyToLabelMap.put("address.housenumber", "Housenumber");
+ propertyToLabelMap.put("address.postalCode", "Postal Code");
+ propertyToLabelMap.put("address.city", "City");
+
+ // build the body layer stack
+ // Usually you would create a new layer stack by extending
+ // AbstractIndexLayerTransform and
+ // setting the ViewportLayer as underlying layer. But in this case using
+ // the ViewportLayer
+ // directly as body layer is also working.
+ List<PersonWithAddress> data = PersonService.getPersonsWithAddress(100);
+
+ IColumnPropertyAccessor<PersonWithAddress> accessor =
+ new ExtendedReflectiveColumnPropertyAccessor<PersonWithAddress>(propertyNames);
+ IDataProvider bodyDataProvider =
+ new ListDataProvider<PersonWithAddress>(data, accessor);
+ DataLayer bodyDataLayer = new DataLayer(bodyDataProvider);
+ ColumnReorderLayer columnReorderLayer = new ColumnReorderLayer(bodyDataLayer);
+ ColumnHideShowLayer columnHideShowLayer = new ColumnHideShowLayer(columnReorderLayer);
+ SelectionLayer selectionLayer = new SelectionLayer(columnHideShowLayer);
+ ViewportLayer viewportLayer = new ViewportLayer(selectionLayer);
+
+ // build the column header layer
+ IDataProvider columnHeaderDataProvider =
+ new DefaultColumnHeaderDataProvider(propertyNames, propertyToLabelMap);
+ DataLayer columnHeaderDataLayer =
+ new DefaultColumnHeaderDataLayer(columnHeaderDataProvider);
+ ILayer columnHeaderLayer =
+ new ColumnHeaderLayer(columnHeaderDataLayer, viewportLayer, selectionLayer);
+
+ // build the row header layer
+ IDataProvider rowHeaderDataProvider =
+ new DefaultRowHeaderDataProvider(bodyDataProvider);
+ DataLayer rowHeaderDataLayer =
+ new DefaultRowHeaderDataLayer(rowHeaderDataProvider);
+ ILayer rowHeaderLayer =
+ new RowHeaderLayer(rowHeaderDataLayer, viewportLayer, selectionLayer);
+
+ // build the corner layer
+ IDataProvider cornerDataProvider =
+ new DefaultCornerDataProvider(columnHeaderDataProvider, rowHeaderDataProvider);
+ DataLayer cornerDataLayer =
+ new DataLayer(cornerDataProvider);
+ ILayer cornerLayer =
+ new CornerLayer(cornerDataLayer, rowHeaderLayer, columnHeaderLayer);
+
+ // build the grid layer
+ GridLayer gridLayer =
+ new GridLayer(viewportLayer, columnHeaderLayer, rowHeaderLayer, cornerLayer);
+
+ NatTable natTable = new NatTable(parent, gridLayer);
+
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(natTable);
+
+ return natTable;
+
+ }
+}