1 /*
   2  * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /*
  27   test
  28   @bug 8023392
  29   @summary Swing text components printed with spaces between chars
  30   @author Anton Nashatyrev
  31   @run applet/manual=yesno bug8023392.html
  32 */
  33 
  34 import javax.swing.*;
  35 import javax.swing.border.LineBorder;
  36 import java.applet.Applet;
  37 import java.awt.*;
  38 import java.awt.event.ActionEvent;
  39 import java.awt.event.ActionListener;
  40 import java.awt.font.TextAttribute;
  41 import java.awt.print.PageFormat;
  42 import java.awt.print.Printable;
  43 import java.awt.print.PrinterException;
  44 import java.awt.print.PrinterJob;
  45 import java.text.AttributedCharacterIterator;
  46 import java.text.AttributedString;
  47 
  48 
  49 public class bug8023392 extends Applet {
  50     static final String[] instructions = {
  51         "A Frame containing several pairs of labels ((a) and (b)) is displayed.",
  52         "Labels of each pair look the same and are left-aligned (with spaces ",
  53         "between chars).",
  54         "1. Hit the print button.",
  55         "2. Select any available printer (printing to file is also fine).",
  56         "3. Look at the printing result (paper, PDF, PS, etc.):",
  57         "   The (a) and (b) labels should look almost the same and the (a) labels",
  58         "   shouldn't appear as if they are stretched along X axis."};
  59 
  60     public void init() {
  61         this.setLayout(new BorderLayout());
  62         add(new SimplePrint2(), BorderLayout.CENTER);
  63 
  64         Sysout.createDialogWithInstructions(instructions);
  65 
  66     }
  67 
  68     public static class SimplePrint2 extends JPanel
  69             implements ActionListener, Printable {
  70         JLabel label1;
  71         JLabel label2;
  72         JButton printButton;
  73 
  74 
  75         public SimplePrint2() {
  76             setLayout(new BorderLayout());
  77             label1 = new JLabel("2a) a b c d e" +
  78                     "                         ");
  79             label2 = new JLabel("2b) a b c d e");
  80 
  81             Box p1 = new Box(BoxLayout.Y_AXIS);
  82             p1.add(label1);
  83             p1.add(label2);
  84             p1.add(new JLabel("wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww") {
  85                 String s = "3a) a b c d e                                     ";
  86                 @Override
  87                 protected void paintComponent(Graphics g) {
  88                     sun.swing.SwingUtilities2.drawChars(this, g, s.toCharArray(),
  89                             0, s.length(), 0, 15);
  90                 }
  91             });
  92             p1.add(new JLabel("wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww") {
  93                 String s = "3b) a b c d e";
  94                 @Override
  95                 protected void paintComponent(Graphics g) {
  96                     sun.swing.SwingUtilities2.drawChars(this, g, s.toCharArray(),
  97                             0, s.length(), 0, 15);
  98                 }
  99             });
 100             p1.add(new JLabel("wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww") {
 101                 String s = "4a) a b c d e                                     ";
 102                 AttributedCharacterIterator it;
 103                 {
 104                     AttributedString as = new AttributedString(s);
 105                     as.addAttribute(TextAttribute.FONT, getFont());
 106                     as.addAttribute(TextAttribute.FOREGROUND, Color.RED, 3, 8);
 107                     it = as.getIterator();
 108                 }
 109                 @Override
 110                 protected void paintComponent(Graphics g) {
 111                     sun.swing.SwingUtilities2.drawString(this, g, it, 0, 15);
 112                 }
 113             });
 114 
 115             p1.add(new JLabel("wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww") {
 116                 String s = "4b) a b c d e";
 117                 AttributedCharacterIterator it;
 118                 {
 119                     AttributedString as = new AttributedString(s);
 120                     as.addAttribute(TextAttribute.FONT, getFont());
 121                     as.addAttribute(TextAttribute.FOREGROUND, Color.RED, 3, 8);
 122                     it = as.getIterator();
 123                 }
 124                 @Override
 125                 protected void paintComponent(Graphics g) {
 126                     sun.swing.SwingUtilities2.drawString(this, g, it, 0, 15);
 127                 }
 128             });
 129 
 130             JPanel p2 = new JPanel();
 131             printButton = new JButton("Print");
 132             printButton.addActionListener(this);
 133             p2.add(printButton);
 134 
 135             Container c = this;
 136             c.add(p1, BorderLayout.CENTER);
 137             c.add(p2, BorderLayout.SOUTH);
 138 
 139             String[] data = {
 140                     "1a) \u30aa\u30f3\u30e9\u30a4\u30f3\u6d88\u8fbc" +
 141                     "                                              ",
 142                     "1b) \u30aa\u30f3\u30e9\u30a4\u30f3\u6d88\u8fbc"
 143             };
 144             JList l0 = new JList(data);
 145             l0.setVisibleRowCount(l0.getModel().getSize());
 146             JScrollPane jsp = new JScrollPane(l0);
 147             l0.setBorder(new LineBorder(Color.GRAY));
 148             c.add(jsp, BorderLayout.NORTH);
 149 
 150             for (Component comp : new Component[]{label1, label2, printButton}) {
 151                 comp.setFont(new Font("Monospaced", 0, 16));
 152             }
 153         }
 154 
 155         public void actionPerformed(ActionEvent e) {
 156             PrinterJob job = PrinterJob.getPrinterJob();
 157             job.setPrintable(this);
 158             if (job.printDialog()) {
 159                 try {
 160                     job.print();
 161                 } catch (PrinterException ex) {
 162                     ex.printStackTrace();
 163                 }
 164             }
 165         }
 166 
 167         public int print(Graphics graphics,
 168                          PageFormat pageFormat,
 169                          int pageIndex)
 170                 throws PrinterException {
 171             if (pageIndex >= 1) {
 172                 return Printable.NO_SUCH_PAGE;
 173             }
 174 
 175             this.paint(graphics);
 176             return Printable.PAGE_EXISTS;
 177         }
 178     }
 179 }
 180 
 181 
 182 /**
 183  * *************************************************
 184  * Standard Test Machinery
 185  * DO NOT modify anything below -- it's a standard
 186  * chunk of code whose purpose is to make user
 187  * interaction uniform, and thereby make it simpler
 188  * to read and understand someone else's test.
 189  * **************************************************
 190  */
 191 class Sysout {
 192     private static TestDialog dialog;
 193 
 194     public static void createDialogWithInstructions(String[] instructions) {
 195         dialog = new TestDialog(new Frame(), "Instructions");
 196         dialog.printInstructions(instructions);
 197         dialog.show();
 198         println("Any messages for the tester will display here.");
 199     }
 200 
 201     public static void createDialog() {
 202         dialog = new TestDialog(new Frame(), "Instructions");
 203         String[] defInstr = {"Instructions will appear here. ", ""};
 204         dialog.printInstructions(defInstr);
 205         dialog.show();
 206         println("Any messages for the tester will display here.");
 207     }
 208 
 209 
 210     public static void printInstructions(String[] instructions) {
 211         dialog.printInstructions(instructions);
 212     }
 213 
 214 
 215     public static void println(String messageIn) {
 216         dialog.displayMessage(messageIn);
 217     }
 218 
 219 }// Sysout  class
 220 
 221 
 222 class TestDialog extends Dialog {
 223 
 224     TextArea instructionsText;
 225     TextArea messageText;
 226     int maxStringLength = 80;
 227 
 228     //DO NOT call this directly, go through Sysout
 229     public TestDialog(Frame frame, String name) {
 230         super(frame, name);
 231         int scrollBoth = TextArea.SCROLLBARS_BOTH;
 232         instructionsText = new TextArea("", 15, maxStringLength, scrollBoth);
 233         add("North", instructionsText);
 234 
 235         messageText = new TextArea("", 5, maxStringLength, scrollBoth);
 236         add("South", messageText);
 237 
 238         pack();
 239 
 240         show();
 241     }// TestDialog()
 242 
 243     //DO NOT call this directly, go through Sysout
 244     public void printInstructions(String[] instructions) {
 245         //Clear out any current instructions
 246         instructionsText.setText("");
 247 
 248         //Go down array of instruction strings
 249 
 250         String printStr, remainingStr;
 251         for (int i = 0; i < instructions.length; i++) {
 252             //chop up each into pieces maxSringLength long
 253             remainingStr = instructions[i];
 254             while (remainingStr.length() > 0) {
 255                 //if longer than max then chop off first max chars to print
 256                 if (remainingStr.length() >= maxStringLength) {
 257                     //Try to chop on a word boundary
 258                     int posOfSpace = remainingStr.
 259                             lastIndexOf(' ', maxStringLength - 1);
 260 
 261                     if (posOfSpace <= 0) posOfSpace = maxStringLength - 1;
 262 
 263                     printStr = remainingStr.substring(0, posOfSpace + 1);
 264                     remainingStr = remainingStr.substring(posOfSpace + 1);
 265                 }
 266                 //else just print
 267                 else {
 268                     printStr = remainingStr;
 269                     remainingStr = "";
 270                 }
 271 
 272                 instructionsText.append(printStr + "\n");
 273 
 274             }// while
 275 
 276         }// for
 277 
 278     }//printInstructions()
 279 
 280     //DO NOT call this directly, go through Sysout
 281     public void displayMessage(String messageIn) {
 282         messageText.append(messageIn + "\n");
 283     }
 284 
 285 }// TestDialog  class
 286