Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDirk Fauth2016-10-22 17:33:25 +0000
committerDirk Fauth2016-10-22 17:39:45 +0000
commita79d4ecceaf62701615a0901b6b2760d3063c0db (patch)
treee1bcc3d9b4828f635e33b6d7ae03f23aeed8ba9a
parent7235a973636fc28c6832ce6aed4a4c01ad4cc79f (diff)
downloadorg.eclipse.nebula.widgets.nattable-a79d4ecceaf62701615a0901b6b2760d3063c0db.tar.gz
org.eclipse.nebula.widgets.nattable-a79d4ecceaf62701615a0901b6b2760d3063c0db.tar.xz
org.eclipse.nebula.widgets.nattable-a79d4ecceaf62701615a0901b6b2760d3063c0db.zip
Bug 506392 - [Print] Support stretching with fit-to-page
Change-Id: Ib1d5875734e9aadf4da2d8108263a94d4bd394b6 Signed-off-by: Dirk Fauth <dirk.fauth@googlemail.com>
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/print/LayerPrinter.java74
-rw-r--r--org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/print/config/PrintConfigAttributes.java13
-rw-r--r--org.eclipse.nebula.widgets.nattable.examples/src/org/eclipse/nebula/widgets/nattable/examples/_700_AdditionalFunctions/_762_MultiPrintExample.java117
3 files changed, 172 insertions, 32 deletions
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 08218bb3..3d2f4b62 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
@@ -85,6 +85,7 @@ public class LayerPrinter {
protected boolean preRender = true;
private final Direction fittingMode;
+ private final boolean stretch;
private int headerHeight = 0;
@@ -152,6 +153,11 @@ public class LayerPrinter {
PrintConfigAttributes.FITTING_MODE,
DisplayMode.NORMAL);
this.fittingMode = (configuredFittingMode != null) ? configuredFittingMode : Direction.NONE;
+
+ Boolean configureStretching = configRegistry.getConfigAttribute(
+ PrintConfigAttributes.STRETCH,
+ DisplayMode.NORMAL);
+ this.stretch = (configureStretching != null) ? configureStretching : false;
}
/**
@@ -228,6 +234,22 @@ public class LayerPrinter {
}
/**
+ * @param printer
+ * The printer that will be used for printing.
+ * @return The scale factor used for the scaling of the repeat print target
+ * or [0, 0] of there is no print target configured for repeating.
+ */
+ private float[] getRepeatPrintTargetScaleFactor(Printer printer) {
+ float[] result = new float[] { 0, 0 };
+ // currently we only support repeating the first of the configured multi
+ // print targets
+ if (this.printTargets.get(0).repeat) {
+ result = computeLayerScaleFactor(this.printTargets.get(0).layer, printer);
+ }
+ return result;
+ }
+
+ /**
* Computes the scale factor to match the printer resolution.
*
* @param layer
@@ -267,7 +289,7 @@ public class LayerPrinter {
// stretching could cause serious issues, e.g. vertical
// stretching for one row could cause a really long running
// operation because the width gets really really big
- if (pixelX > sfX) {
+ if (pixelX > sfX && !this.stretch) {
pixelX = sfX;
}
if (pixelY > sfY) {
@@ -302,7 +324,8 @@ public class LayerPrinter {
private float[] computeLayerScaleFactor(ILayer layer, Printer printer) {
float[] scaleFactor = null;
if (this.fittingMode == Direction.NONE
- || (!this.join && !this.printTargets.get(0).repeat)) {
+ || (!this.join && !this.printTargets.get(0).repeat)
+ || this.stretch) {
scaleFactor = computeScaleFactor(layer, printer, false);
} else {
// search for the common scaling factor
@@ -339,9 +362,10 @@ public class LayerPrinter {
private int getPageCount(Printer printer) {
int result = 0;
int available = -1;
+ float[] prevScaleFactor = null;
for (PrintTarget target : this.printTargets) {
if (!target.repeat) {
- int[] layerResult = getPageCount(target, printer, available);
+ int[] layerResult = getPageCount(target, printer, available, prevScaleFactor);
result += (layerResult[0] * layerResult[1]);
// as the print targets should be joined and the print was
@@ -351,6 +375,9 @@ public class LayerPrinter {
}
available = layerResult[2];
+ if (available >= 0) {
+ prevScaleFactor = computeLayerScaleFactor(target.layer, printer);
+ }
}
}
@@ -366,14 +393,18 @@ public class LayerPrinter {
* @param printer
* The printer that will be used.
* @param available
- * The remaining available space on a page after the target is
- * printed in case the print targets should be glued, -1
- * otherwise.
+ * The remaining available space in pixel on a page after the
+ * target is printed in case the print targets should be glued,
+ * -1 otherwise.
+ * @param prevScaleFactor
+ * The scale factor of the previous table in case the tables
+ * should be joined. Needed to calculate the available space
+ * correctly
* @return The number of horizontal and vertical pages that are needed to
* print the layer of the given print target and the remaining space
* on a page if the print targets should be glued.
*/
- private int[] getPageCount(PrintTarget target, Printer printer, int available) {
+ private int[] getPageCount(PrintTarget target, Printer printer, int available, float[] prevScaleFactor) {
Rectangle printArea = computePrintArea(printer);
float[] scaleFactor = computeLayerScaleFactor(target.layer, printer);
@@ -403,14 +434,14 @@ public class LayerPrinter {
}
int numOfVerticalPages = 0;
- int repeatPrintTargetHeightInDpi = Math.round(Float.valueOf(getRepeatPrintTargetHeight() * scaleFactor[1]));
+ int repeatPrintTargetHeightInDpi = Math.round(Float.valueOf(getRepeatPrintTargetHeight() * getRepeatPrintTargetScaleFactor(printer)[1]));
int headerHeightInDpi = (this.headerHeight != 0 && this.repeatHeaderLayer != null)
? Math.round(Float.valueOf((this.headerHeight * scaleFactor[1]))) : 0;
int pageHeight = Math.round(Float.valueOf(
(printArea.height - repeatPrintTargetHeightInDpi - headerHeightInDpi - getFooterHeightInPrinterDPI()) / scaleFactor[1]));
int firstPageHeight = (available < 0)
? Math.round(Float.valueOf((printArea.height - repeatPrintTargetHeightInDpi - getFooterHeightInPrinterDPI()) / scaleFactor[1]))
- : available;
+ : Math.round(Float.valueOf(Math.round(Float.valueOf(available * prevScaleFactor[1])) / scaleFactor[1]));
int endY = 0;
int added = 0;
int remaining = -1;
@@ -680,8 +711,11 @@ public class LayerPrinter {
int totalPageCount = getPageCount(this.printer);
Integer[] repeatHeaderGridLineWidth = null;
+ float[] repeatScaleFactor = null;
int available = -1;
+ float[] prevScaleFactor = null;
+
boolean newPage = true;
boolean pageStarted = false;
for (PrintTarget target : LayerPrinter.this.printTargets) {
@@ -689,6 +723,7 @@ public class LayerPrinter {
// we do not render the repeat print target directly
// as it is handled on every page while printing
repeatHeaderGridLineWidth = getGridLineWidth(target.configRegistry);
+ repeatScaleFactor = computeLayerScaleFactor(target.layer, this.printer);
continue;
}
@@ -712,6 +747,12 @@ public class LayerPrinter {
float[] scaleFactor = computeLayerScaleFactor(target.layer, this.printer);
float[] dpiFactor = computeScaleFactor(target.layer, this.printer, true);
+ int availablePixel = available;
+ if (available > 0) {
+ int prevDPI = Math.round(Float.valueOf(available * prevScaleFactor[1]));
+ availablePixel = Math.round(Float.valueOf(prevDPI / scaleFactor[1]));
+ }
+
Integer[] gridLineWidth = getGridLineWidth(target.configRegistry);
try {
@@ -730,15 +771,15 @@ public class LayerPrinter {
final Rectangle printerClientArea = computePrintArea(this.printer);
final int printBoundsWidth = Math.round(Float.valueOf(printerClientArea.width / scaleFactor[0]));
int repeatPrintTargetHeight = getRepeatPrintTargetHeight();
- int repeatPrintTargetHeightInDpi = Math.round(Float.valueOf(repeatPrintTargetHeight * scaleFactor[1]));
+ int repeatPrintTargetHeightInDpi = Math.round(Float.valueOf(repeatPrintTargetHeight * ((repeatScaleFactor != null) ? repeatScaleFactor[1] : 0)));
int headerHeightDPI = Math.round(Float.valueOf((LayerPrinter.this.headerHeight * scaleFactor[1])));
int printBoundsHeight = Math.round(Float.valueOf((printerClientArea.height - repeatPrintTargetHeightInDpi - headerHeightDPI - getFooterHeightInPrinterDPI()) / scaleFactor[1]));
int firstPagePrintBoundsHeight = (available < 0)
? Math.round(Float.valueOf((printerClientArea.height - repeatPrintTargetHeightInDpi - getFooterHeightInPrinterDPI()) / scaleFactor[1]))
- : available;
+ : availablePixel;
- final int[] pageCount = getPageCount(target, this.printer, available);
+ final int[] pageCount = getPageCount(target, this.printer, available, prevScaleFactor);
// Print pages Left to Right and then Top to Down
int startY = 0;
@@ -826,7 +867,7 @@ public class LayerPrinter {
intersect = printBounds.intersection(intersect);
configureScalingTransform(printerTransform, scaleFactor, printerClientArea, intersect);
- configureScalingTransform(repeatTransform, scaleFactor, printerClientArea, intersect);
+ configureScalingTransform(repeatTransform, (repeatScaleFactor != null ? repeatScaleFactor : scaleFactor), printerClientArea, intersect);
configureScalingTransform(headerTransform, scaleFactor, printerClientArea, intersect);
if (repeatPrintTargetHeight > 0) {
@@ -842,11 +883,11 @@ public class LayerPrinter {
repeatIntersect = printBounds.intersection(repeatIntersect);
printLayer(LayerPrinter.this.printTargets.get(0), gc, new Rectangle(repeatIntersect.x, 0, repeatIntersect.width, repeatPrintTargetHeight));
- printerTransform.translate(0, repeatPrintTargetHeight);
+ printerTransform.translate(0, Math.round(Float.valueOf(Math.round(Float.valueOf(repeatPrintTargetHeight * repeatScaleFactor[1])) / scaleFactor[1])));
}
if (LayerPrinter.this.repeatHeaderLayer != null && verticalPageNumber != 0) {
- headerTransform.translate(0, startY + repeatPrintTargetHeight);
+ headerTransform.translate(0, startY + Math.round(Float.valueOf(Math.round(Float.valueOf(repeatPrintTargetHeight * ((repeatScaleFactor != null) ? repeatScaleFactor[1] : 0))) / scaleFactor[1])));
gc.setTransform(headerTransform);
printLayer(target, gc, new Rectangle(printBounds.x, 0, intersect.width, LayerPrinter.this.headerHeight));
printerTransform.translate(0, LayerPrinter.this.headerHeight);
@@ -857,7 +898,7 @@ public class LayerPrinter {
// page on the same page as the previous
// target
if (LayerPrinter.this.join && available > 0 && verticalPageNumber == 0) {
- printerTransform.translate(0, (printBoundsHeight + LayerPrinter.this.headerHeight) - available);
+ printerTransform.translate(0, (printBoundsHeight + LayerPrinter.this.headerHeight) - availablePixel);
}
gc.setTransform(printerTransform);
@@ -878,6 +919,7 @@ public class LayerPrinter {
}
startY += pbh;
available = pageCount[2];
+ prevScaleFactor = scaleFactor;
}
if (LayerPrinter.this.join && available > 0) {
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/print/config/PrintConfigAttributes.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/print/config/PrintConfigAttributes.java
index 2903334a..5d3b21d0 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/print/config/PrintConfigAttributes.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/print/config/PrintConfigAttributes.java
@@ -40,6 +40,19 @@ public interface PrintConfigAttributes {
ConfigAttribute<Direction> FITTING_MODE = new ConfigAttribute<Direction>();
/**
+ * Configuration attribute to configure a scaling option in case
+ * {@link #FITTING_MODE} is set. By default only downscaling is supported on
+ * enabling the fit-to-page scaling. By setting {@link #STRETCH} to
+ * <code>true</code> also upscaling will be performed to make the most out
+ * of the available space.
+ * <p>
+ * <b>Note:</b> stretching is only supported for fitting mode
+ * {@link Direction#HORIZONTAL}.
+ * </p>
+ */
+ ConfigAttribute<Boolean> STRETCH = new ConfigAttribute<Boolean>();
+
+ /**
* Configuration attribute to configure the date format that is used for
* rendering the print date in the footer region. If not specified the
* default value <i>EEE, d MMM yyyy HH:mm a</i> will be used.
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
index 07f869a4..488215ec 100644
--- 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
@@ -17,6 +17,8 @@ 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.config.Direction;
+import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
import org.eclipse.nebula.widgets.nattable.data.ExtendedReflectiveColumnPropertyAccessor;
import org.eclipse.nebula.widgets.nattable.data.IColumnPropertyAccessor;
import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
@@ -39,10 +41,12 @@ 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.painter.NatTableBorderOverlayPainter;
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.print.config.PrintConfigAttributes;
import org.eclipse.nebula.widgets.nattable.reorder.ColumnReorderLayer;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;
@@ -50,12 +54,17 @@ 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.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
public class _762_MultiPrintExample extends AbstractNatExample {
+ Button joinTablesButton;
+ Button repeatHeaderTableButton;
+ Button repeatColumnHeaderButton;
+
public static void main(String[] args) throws Exception {
StandaloneNatExampleRunner.run(new _762_MultiPrintExample());
}
@@ -79,47 +88,110 @@ public class _762_MultiPrintExample extends AbstractNatExample {
GridDataFactory.fillDefaults().grab(true, true).applyTo(gridPanel);
Composite buttonPanel = new Composite(panel, SWT.NONE);
- buttonPanel.setLayout(new GridLayout());
+ buttonPanel.setLayout(new GridLayout(4, false));
GridDataFactory.fillDefaults().grab(true, false).applyTo(buttonPanel);
- NatTable natTable = createSmallTable(gridPanel);
- NatTable grid = createGrid(gridPanel);
+ NatTable headerTable = createSmallTable(gridPanel);
+ NatTable bodyTable = createGrid(gridPanel);
// create a custom command handler for printing of multiple NatTable
// instances
- PrintCommandHandler handler = new PrintCommandHandler(natTable.getLayer()) {
+ PrintCommandHandler handler = new PrintCommandHandler(headerTable.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());
+ LayerPrinter printer = new LayerPrinter(headerTable, headerTable.getConfigRegistry(), _762_MultiPrintExample.this.repeatHeaderTableButton.getSelection());
+ printer.addPrintTarget(bodyTable, bodyTable.getConfigRegistry());
+ printer.joinPrintTargets(_762_MultiPrintExample.this.joinTablesButton.getSelection());
+ if (_762_MultiPrintExample.this.repeatColumnHeaderButton.getSelection()) {
+ printer.repeatHeaderLayer(((GridLayer) bodyTable.getLayer()).getColumnHeaderLayer());
+ }
+ printer.print(headerTable.getShell());
return true;
};
};
// register the handler to both NatTable instances
- natTable.getLayer().registerCommandHandler(handler);
- grid.getLayer().registerCommandHandler(handler);
+ headerTable.getLayer().registerCommandHandler(handler);
+ bodyTable.getLayer().registerCommandHandler(handler);
+
+ Composite multiTableConfigPanel = new Composite(buttonPanel, SWT.NONE);
+ multiTableConfigPanel.setLayout(new RowLayout(SWT.VERTICAL));
+ this.joinTablesButton = new Button(multiTableConfigPanel, SWT.CHECK);
+ this.joinTablesButton.setText("Join Tables");
+ this.repeatHeaderTableButton = new Button(multiTableConfigPanel, SWT.CHECK);
+ this.repeatHeaderTableButton.setText("Repeat Header Table");
+ this.repeatColumnHeaderButton = new Button(multiTableConfigPanel, SWT.CHECK);
+ this.repeatColumnHeaderButton.setText("Repeat Column Header");
+
+ Composite fittingConfigPanel = new Composite(buttonPanel, SWT.NONE);
+ fittingConfigPanel.setLayout(new RowLayout(SWT.VERTICAL));
+ Button fitHorizontalButton = new Button(fittingConfigPanel, SWT.CHECK);
+ fitHorizontalButton.setText("Fit Horizontally");
+ Button fitVerticalButton = new Button(fittingConfigPanel, SWT.CHECK);
+ fitVerticalButton.setText("Fit Vertically");
+ Button stretchButton = new Button(fittingConfigPanel, SWT.CHECK);
+ stretchButton.setText("Stretch");
+ stretchButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ headerTable.getConfigRegistry().registerConfigAttribute(
+ PrintConfigAttributes.STRETCH,
+ stretchButton.getSelection());
+ }
+ });
+
+ fitHorizontalButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ updateFittingConfig(
+ headerTable.getConfigRegistry(),
+ fitHorizontalButton.getSelection(),
+ fitVerticalButton.getSelection());
+ }
+ });
+
+ fitVerticalButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ updateFittingConfig(
+ headerTable.getConfigRegistry(),
+ fitHorizontalButton.getSelection(),
+ fitVerticalButton.getSelection());
+ }
+ });
Button addColumnButton = new Button(buttonPanel, SWT.PUSH);
addColumnButton.setText("Print");
addColumnButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
- natTable.doCommand(
+ headerTable.doCommand(
new PrintCommand(
- natTable.getConfigRegistry(),
- natTable.getShell()));
+ headerTable.getConfigRegistry(),
+ headerTable.getShell()));
}
});
return panel;
}
+ private void updateFittingConfig(IConfigRegistry configRegistry, boolean fitHorizontally, boolean fitVertically) {
+ Direction dir = Direction.NONE;
+ if (fitHorizontally && fitVertically) {
+ dir = Direction.BOTH;
+ } else if (fitHorizontally && !fitVertically) {
+ dir = Direction.HORIZONTAL;
+ } else if (!fitHorizontally && fitVertically) {
+ dir = Direction.VERTICAL;
+ }
+ configRegistry.registerConfigAttribute(
+ PrintConfigAttributes.FITTING_MODE,
+ dir);
+ }
+
private NatTable createSmallTable(Composite parent) {
// property names of the Person class
- String[] propertyNames = { "firstName", "lastName", "gender",
- "married", "birthday" };
+ 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>();
@@ -131,7 +203,7 @@ public class _762_MultiPrintExample extends AbstractNatExample {
IDataProvider bodyDataProvider =
new DefaultBodyDataProvider<Person>(
- PersonService.getPersons(150), propertyNames);
+ PersonService.getPersons(3), propertyNames);
DataLayer bodyDataLayer = new DataLayer(bodyDataProvider);
SelectionLayer selectionLayer = new SelectionLayer(bodyDataLayer);
ViewportLayer viewportLayer = new ViewportLayer(selectionLayer);
@@ -140,10 +212,21 @@ public class _762_MultiPrintExample extends AbstractNatExample {
// adding this configuration adds the styles and the painters to use
natTable.addConfiguration(new DefaultNatTableStyleConfiguration());
- natTable.addConfiguration(new DefaultPrintBindings());
+ natTable.addConfiguration(new DefaultPrintBindings() {
+ @Override
+ public void configureRegistry(IConfigRegistry configRegistry) {
+ super.configureRegistry(configRegistry);
+
+ configRegistry.registerConfigAttribute(
+ PrintConfigAttributes.FOOTER_PAGE_PATTERN,
+ "Page {0} of {1}");
+ }
+ });
natTable.configure();
+ natTable.addOverlayPainter(new NatTableBorderOverlayPainter());
+
GridDataFactory.fillDefaults().grab(true, true).applyTo(natTable);
return natTable;
@@ -215,6 +298,8 @@ public class _762_MultiPrintExample extends AbstractNatExample {
NatTable natTable = new NatTable(parent, gridLayer);
+ natTable.addOverlayPainter(new NatTableBorderOverlayPainter());
+
GridDataFactory.fillDefaults().grab(true, true).applyTo(natTable);
return natTable;

Back to the top