diff options
author | Dirk Fauth | 2016-10-22 17:33:25 +0000 |
---|---|---|
committer | Dirk Fauth | 2016-10-22 17:39:45 +0000 |
commit | a79d4ecceaf62701615a0901b6b2760d3063c0db (patch) | |
tree | e1bcc3d9b4828f635e33b6d7ae03f23aeed8ba9a | |
parent | 7235a973636fc28c6832ce6aed4a4c01ad4cc79f (diff) | |
download | org.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>
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; |