8170349: The printed content is beyond the borders
authorpsadhukhan
Thu, 22 Dec 2016 18:30:27 +0530
changeset 43077 785bbcd9812a
parent 43076 a2d90fcf0a70
child 43078 1d242b27f9e2
8170349: The printed content is beyond the borders Reviewed-by: alexsch, aniyogi
jdk/src/java.desktop/share/classes/javax/swing/TablePrintable.java
jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java
jdk/test/javax/swing/JTable/PrintManualTest_FitWidthMultiple.java
--- a/jdk/src/java.desktop/share/classes/javax/swing/TablePrintable.java	Thu Dec 22 12:17:56 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/TablePrintable.java	Thu Dec 22 18:30:27 2016 +0530
@@ -380,6 +380,12 @@
         // print the current section of the table
         g2d.translate(-clip.x, -clip.y);
         g2d.clip(clip);
+
+        // set a property so that BasicTableUI#paint can know JTable printMode
+        // is FIT_WIDTH since TablePrintable.printMode is not accessible from BasicTableUI
+        if (printMode == JTable.PrintMode.FIT_WIDTH) {
+            table.putClientProperty("Table.printMode", JTable.PrintMode.FIT_WIDTH);
+        }
         table.print(g2d);
 
         // restore the original transform and clip
@@ -407,8 +413,18 @@
         for(int visrow = rMin; visrow < rMax; visrow++) {
             rowHeight += table.getRowHeight(visrow);
         }
-        g2d.drawRect(0, 0, visibleBounds.width, hclip.height + rowHeight);
+        // If PrintMode is FIT_WIDTH, then draw rect for entire column width while
+        // printing irrespective of how many columns are visible in console
+        if (printMode == JTable.PrintMode.FIT_WIDTH) {
+            g2d.drawRect(0, 0, clip.width, hclip.height + rowHeight);
+        } else {
+            g2d.drawRect(0, 0, visibleBounds.width, hclip.height + rowHeight);
+        }
 
+        // clear the property
+        if (printMode == JTable.PrintMode.FIT_WIDTH) {
+            table.putClientProperty("Table.printMode", null);
+        }
         // dispose the graphics copy
         g2d.dispose();
 
@@ -534,5 +550,4 @@
         } while (clip.width + colWidth <= pw);
 
     }
-
 }
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java	Thu Dec 22 12:17:56 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTableUI.java	Thu Dec 22 18:30:27 2016 +0530
@@ -1812,12 +1812,12 @@
         }
 
         boolean ltr = table.getComponentOrientation().isLeftToRight();
-
+        Point upperLeft, lowerRight;
         // compute the visible part of table which needs to be painted
         Rectangle visibleBounds = clip.intersection(bounds);
-        Point upperLeft = visibleBounds.getLocation();
-        Point lowerRight = new Point(visibleBounds.x + visibleBounds.width - 1,
-                                     visibleBounds.y + visibleBounds.height - 1);
+        upperLeft = visibleBounds.getLocation();
+        lowerRight = new Point(visibleBounds.x + visibleBounds.width - 1,
+                               visibleBounds.y + visibleBounds.height - 1);
 
         int rMin = table.rowAtPoint(upperLeft);
         int rMax = table.rowAtPoint(lowerRight);
@@ -1834,6 +1834,18 @@
             rMax = table.getRowCount()-1;
         }
 
+        // For FIT_WIDTH, all columns should be printed irrespective of
+        // how many columns are visible. So, we used clip which is already set to
+        // total col width instead of visible region
+        // Since JTable.PrintMode is not accessible
+        // from here, we aet "Table.printMode" in TablePrintable#print and
+        // access from here.
+        Object printMode = table.getClientProperty("Table.printMode");
+        if ((printMode == JTable.PrintMode.FIT_WIDTH)) {
+            upperLeft = clip.getLocation();
+            lowerRight = new Point(clip.x + clip.width - 1,
+                                   clip.y + clip.height - 1);
+        }
         int cMin = table.columnAtPoint(ltr ? upperLeft : lowerRight);
         int cMax = table.columnAtPoint(ltr ? lowerRight : upperLeft);
         // This should never happen.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JTable/PrintManualTest_FitWidthMultiple.java	Thu Dec 22 18:30:27 2016 +0530
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * @test
+ * @bug 8170349
+ * @summary  Verify if printed content is within border and all columns are
+ *           printed for PrintMode.FIT_WIDTH
+ * @run main/manual PrintManualTest_FitWidthMultiple
+ */
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.text.MessageFormat;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import javax.print.attribute.HashPrintRequestAttributeSet;
+import javax.print.attribute.PrintRequestAttributeSet;
+import javax.swing.AbstractAction;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JTextArea;
+import javax.swing.KeyStroke;
+import javax.swing.SwingUtilities;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableModel;
+
+public class PrintManualTest_FitWidthMultiple extends JTable implements Runnable {
+
+    static boolean testPassed;
+    static JFrame fr = null;
+    static JFrame instructFrame = null;
+    private final CountDownLatch latch;
+
+    public PrintManualTest_FitWidthMultiple(CountDownLatch latch){
+        this.latch = latch;
+    }
+
+    @Override
+    public void run() {
+        try {
+            createUIandTest();
+        } catch (Exception ex) {
+            dispose();
+            latch.countDown();
+            throw new RuntimeException(ex.getMessage());
+        }
+    }
+
+    private void createUIandTest() throws Exception {
+        /*Message Format Header and Footer */
+        final MessageFormat header=new MessageFormat("JTable Printing Header {0}");
+        final MessageFormat footer = new MessageFormat("JTable Printing Footer {0}");
+
+        SwingUtilities.invokeAndWait(new Runnable() {
+            @Override
+            public void run() {
+                /* Instructions Section */
+                String info =
+                    " \nThis test case brings up JTable with more Columns and Rows \n"+
+                    "Press the Print Button. It Prints in PRINT_MODE_FIT_WIDTH \n" +
+                    "It Pops up the Print Dialog. Check if Job/Print Attributes in the\n" +
+                    "Print Dialog are configurable. Default Print out will be in Landscape \n"+
+                    "The Print out should have JTable Centered on the Print out with thin borders \n"+
+                    "Prints out with Header and Footer. \n"+
+                    "The JTable should have all columns printed within border";
+
+                instructFrame=new JFrame("PrintManualTest_NormalSingle");
+                JPanel panel=new JPanel(new BorderLayout());
+                JButton button1 = new JButton("Pass");
+                JButton button2 = new JButton("Fail");
+                button1.addActionListener((e) -> {
+                    testPassed = true;
+                    dispose();
+                    latch.countDown();
+                });
+                button2.addActionListener((e) -> {
+                    testPassed = false;
+                    dispose();
+                    latch.countDown();
+                });
+                JPanel btnpanel1 = new JPanel();
+                btnpanel1.add(button1);
+                btnpanel1.add(button2);
+                panel.add(addInfo(info),BorderLayout.CENTER);
+                panel.add(btnpanel1, BorderLayout.SOUTH);
+                instructFrame.getContentPane().add(panel);
+                instructFrame.setBounds(600,100,350,350);
+
+                /* Print Button */
+                final JButton printButton=new JButton("Print");
+
+                /* Table Model */
+                final TableModel datamodel=new AbstractTableModel(){
+                    @Override
+                    public int getColumnCount() { return 50;}
+                    @Override
+                    public int getRowCount() { return 50; }
+                    @Override
+                    public Object getValueAt(int row, int column){ return new Integer(row*column);}
+                };
+
+                /* Constructing the JTable */
+                final JTable table=new JTable(datamodel);
+
+                /* Putting the JTable in ScrollPane and Frame Container */
+                JScrollPane scrollpane=new JScrollPane(table);
+                fr = new JFrame("PrintManualTest_FitWidthMultiple");
+                fr.getContentPane().add(scrollpane);
+
+                /* Light Weight Panel for holding Print and other buttons */
+                JPanel btnpanel=new JPanel();
+                btnpanel.add(printButton);
+                fr.getContentPane().add(btnpanel,BorderLayout.SOUTH);
+                fr.setBounds(0,0,400,400);
+                fr.setSize(500,500);
+
+                /* Binding the KeyStroke to Print Button Action */
+                fr.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ctrl P"), "printButton");
+                fr.getRootPane().getActionMap().put("printButton", new AbstractAction(){
+                    @Override
+                    public void actionPerformed(ActionEvent e){
+                        printButton.doClick();
+                    }
+                });
+
+                /* Container and Component Listeners */
+                fr.addWindowListener(new WindowAdapter() {
+                    @Override
+                    public void windowClosing(WindowEvent e) {
+                        dispose();
+                        if (testPassed == false) {
+                            throw new RuntimeException(" User has not executed the test");
+                        }
+                    }
+                });
+
+                final PrintRequestAttributeSet prattr=new HashPrintRequestAttributeSet();
+                prattr.add(javax.print.attribute.standard.OrientationRequested.LANDSCAPE);
+
+                printButton.addActionListener(new ActionListener(){
+                    @Override
+                    public void actionPerformed(ActionEvent ae){
+                        try{
+                            table.print(JTable.PrintMode.FIT_WIDTH, header,footer,true,prattr,true);
+                        } catch(Exception e){}
+                    }
+                });
+                instructFrame.setVisible(true);
+                fr.setVisible(true);
+            }
+        });
+    }
+
+    public void dispose() {
+        instructFrame.dispose();
+        fr.dispose();
+    }
+
+    public JScrollPane addInfo(String info) {
+        JTextArea jta = new JTextArea(info,8,20);
+        jta.setEditable(false);
+        jta.setLineWrap(true);
+        JScrollPane sp = new JScrollPane(jta);
+        return sp;
+
+    }
+
+    /* Main Method */
+
+    public static void main(String[] argv) throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
+        PrintManualTest_FitWidthMultiple test = new PrintManualTest_FitWidthMultiple(latch);
+        Thread T1 = new Thread(test);
+        T1.start();
+
+        // wait for latch to complete
+        boolean ret = false;
+        try {
+            ret = latch.await(60, TimeUnit.SECONDS);
+        } catch (InterruptedException ie) {
+            throw ie;
+        }
+        if (!ret) {
+            test.dispose();
+            throw new RuntimeException(" User has not executed the test");
+        }
+        if (test.testPassed == false) {
+            throw new RuntimeException("printed contents is beyond borders");
+        }
+    }
+}