001    /*
002     * Copyright (C) 2008-2010 by Holger Arndt
003     *
004     * This file is part of the Universal Java Matrix Package (UJMP).
005     * See the NOTICE file distributed with this work for additional
006     * information regarding copyright ownership and licensing.
007     *
008     * UJMP is free software; you can redistribute it and/or modify
009     * it under the terms of the GNU Lesser General Public License as
010     * published by the Free Software Foundation; either version 2
011     * of the License, or (at your option) any later version.
012     *
013     * UJMP is distributed in the hope that it will be useful,
014     * but WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016     * GNU Lesser General Public License for more details.
017     *
018     * You should have received a copy of the GNU Lesser General Public
019     * License along with UJMP; if not, write to the
020     * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
021     * Boston, MA  02110-1301  USA
022     */
023    
024    package org.ujmp.gui.print;
025    
026    import java.awt.BorderLayout;
027    import java.awt.Color;
028    import java.awt.Component;
029    import java.awt.Dimension;
030    import java.awt.Graphics;
031    import java.awt.Graphics2D;
032    import java.awt.GridBagConstraints;
033    import java.awt.GridBagLayout;
034    import java.awt.Image;
035    import java.awt.Insets;
036    import java.awt.event.ActionEvent;
037    import java.awt.event.ActionListener;
038    import java.awt.image.BufferedImage;
039    import java.awt.print.Book;
040    import java.awt.print.PageFormat;
041    import java.awt.print.Paper;
042    import java.awt.print.Printable;
043    import java.awt.print.PrinterException;
044    import java.awt.print.PrinterJob;
045    
046    import javax.swing.BorderFactory;
047    import javax.swing.ButtonGroup;
048    import javax.swing.JButton;
049    import javax.swing.JLabel;
050    import javax.swing.JPanel;
051    import javax.swing.JRadioButton;
052    import javax.swing.JSpinner;
053    import javax.swing.RepaintManager;
054    import javax.swing.SpinnerNumberModel;
055    import javax.swing.event.ChangeEvent;
056    import javax.swing.event.ChangeListener;
057    
058    /*
059     * taken from here:
060     * http://forum.java.sun.com/thread.jspa?threadID=601884&messageID=4215335
061     */
062    
063    public class PrintPreviewPanel extends JPanel implements ActionListener, ChangeListener {
064            private static final long serialVersionUID = -3281742799998775189L;
065    
066            static final double INITIAL_SCALE_FACTOR = 1.0;
067    
068            Component targetComponent;
069    
070            PageFormat pageFormat = new PageFormat();
071    
072            double xScaleFactor = INITIAL_SCALE_FACTOR;
073    
074            double yScaleFactor = INITIAL_SCALE_FACTOR;
075    
076            BufferedImage bufferedImage;
077    
078            JPanel settingsPanel = new JPanel();
079    
080            PreviewPanel previewPanel;
081    
082            ButtonGroup orientationButtonGroup = new ButtonGroup();
083    
084            JRadioButton portraitButton;
085    
086            JRadioButton landscapeButton;
087    
088            JLabel xScaleLabel = new JLabel("X-Scale:", JLabel.LEFT);
089    
090            JLabel yScaleLabel = new JLabel("Y-Scale:", JLabel.LEFT);
091    
092            JButton print = new JButton("Print");
093    
094            JSpinner xsp, ysp;
095    
096            SpinnerNumberModel snmx, snmy;
097    
098            int pcw, pch;
099    
100            double wh, hw;
101    
102            public PrintPreviewPanel(Component pc) {
103                    targetComponent = pc;
104    
105                    setLayout(new BorderLayout());
106    
107                    if (targetComponent.getWidth() < 1)
108                            targetComponent.setSize(600, targetComponent.getHeight());
109                    if (targetComponent.getHeight() < 1)
110                            targetComponent.setSize(targetComponent.getWidth(), 400);
111    
112                    bufferedImage = new BufferedImage(pcw = targetComponent.getWidth(), pch = targetComponent.getHeight(),
113                                    BufferedImage.TYPE_INT_ARGB);
114                    Graphics g = bufferedImage.createGraphics();
115                    targetComponent.paint(g);
116                    g.dispose();
117                    wh = (double) pcw / (double) pch;
118                    hw = (double) pch / (double) pcw;
119    
120                    pageFormat.setPaper(new PaperA4());
121                    pageFormat.setOrientation(PageFormat.PORTRAIT);
122                    previewPanel = new PreviewPanel();
123    
124                    snmx = new SpinnerNumberModel(1.0, 0.1, 10.0, 0.1);
125                    snmy = new SpinnerNumberModel(1.0, 0.1, 10.0, 0.1);
126                    xsp = new JSpinner(snmx);
127                    ysp = new JSpinner(snmy);
128    
129                    xsp.addChangeListener(this);
130                    ysp.addChangeListener(this);
131    
132                    portraitButton = new JRadioButton("Portrait");
133                    portraitButton.setActionCommand("1");
134                    portraitButton.setSelected(true);
135                    portraitButton.addActionListener(this);
136    
137                    landscapeButton = new JRadioButton("Landscape");
138                    landscapeButton.setActionCommand("2");
139                    landscapeButton.addActionListener(this);
140    
141                    orientationButtonGroup.add(portraitButton);
142                    orientationButtonGroup.add(landscapeButton);
143    
144                    print.addActionListener(this);
145    
146                    previewPanel.setBackground(Color.white);
147                    settingsPanel.setBorder(BorderFactory.createTitledBorder("Settings"));
148                    settingsPanel.setLayout(new GridBagLayout());
149    
150                    GridBagConstraints c1 = new GridBagConstraints();
151    
152                    c1.insets = new Insets(15, 45, 0, 5);
153                    c1 = buildConstraints(c1, 0, 0, 2, 1, 0.0, 0.0);
154                    settingsPanel.add(portraitButton, c1);
155    
156                    c1.insets = new Insets(2, 45, 0, 5);
157                    c1 = buildConstraints(c1, 0, 1, 2, 1, 0.0, 0.0);
158                    settingsPanel.add(landscapeButton, c1);
159    
160                    c1.insets = new Insets(25, 5, 0, 5);
161                    c1 = buildConstraints(c1, 0, 2, 1, 1, 0.0, 0.0);
162                    settingsPanel.add(xScaleLabel, c1);
163    
164                    c1.insets = new Insets(25, 5, 0, 35);
165                    c1 = buildConstraints(c1, 1, 2, 1, 1, 0.0, 0.0);
166                    settingsPanel.add(xsp, c1);
167    
168                    c1.insets = new Insets(5, 5, 0, 5);
169                    c1 = buildConstraints(c1, 0, 3, 1, 1, 0.0, 0.0);
170                    settingsPanel.add(yScaleLabel, c1);
171    
172                    c1.insets = new Insets(15, 5, 0, 35);
173                    c1 = buildConstraints(c1, 1, 3, 1, 1, 0.0, 0.0);
174                    settingsPanel.add(ysp, c1);
175    
176                    c1.insets = new Insets(5, 35, 25, 35);
177                    c1 = buildConstraints(c1, 0, 7, 2, 1, 0.0, 0.0);
178                    settingsPanel.add(print, c1);
179    
180                    add(settingsPanel, BorderLayout.WEST);
181                    add(previewPanel, BorderLayout.CENTER);
182            }
183    
184            GridBagConstraints buildConstraints(GridBagConstraints gbc, int gx, int gy, int gw, int gh, double wx, double wy) {
185                    gbc.gridx = gx;
186                    gbc.gridy = gy;
187                    gbc.gridwidth = gw;
188                    gbc.gridheight = gh;
189                    gbc.weightx = wx;
190                    gbc.weighty = wy;
191                    gbc.fill = GridBagConstraints.BOTH;
192                    return gbc;
193            }
194    
195            public class PreviewPanel extends JPanel {
196                    private static final long serialVersionUID = -868466190084572319L;
197    
198                    public PreviewPanel() {
199                            setPreferredSize(new Dimension(640, 640));
200                    }
201    
202                    
203                    public void paintComponent(Graphics g) {
204                            super.paintComponent(g);
205    
206                            Graphics2D g2d = (Graphics2D) g;
207    
208                            int xOffsetPaper = (int) pageFormat.getImageableX();
209                            int yOffsetPaper = (int) pageFormat.getImageableY();
210                            int widthImage = (int) pageFormat.getImageableWidth();
211                            int heightImage = (int) pageFormat.getImageableHeight();
212    
213                            int widthScaledImage = (int) Math.rint(widthImage * xScaleFactor);
214                            int heightScaledImage = (int) Math.rint((widthImage * hw) * yScaleFactor);
215    
216                            g2d.setColor(Color.black);
217                            g2d.drawRect(0, 0, widthImage + 2 * xOffsetPaper, heightImage + 2 * yOffsetPaper);
218                            g2d.setColor(Color.lightGray);
219                            g2d.drawRect(xOffsetPaper, yOffsetPaper, widthImage, heightImage);
220                            Image image = bufferedImage.getScaledInstance(widthScaledImage, heightScaledImage, Image.SCALE_DEFAULT);
221                            g2d.drawImage(image, xOffsetPaper, yOffsetPaper, this);
222                    }
223            }
224    
225            public void actionPerformed(ActionEvent e) {
226                    if (e.getSource() == portraitButton) {
227                            updatePreview();
228                    } else if (e.getSource() == landscapeButton) {
229                            updatePreview();
230                    } else if (e.getSource() == print) {
231                            print();
232                    }
233            }
234    
235            public void updatePreview() {
236                    if (portraitButton.isSelected()) {
237                            pageFormat.setOrientation(PageFormat.PORTRAIT);
238                    } else if (landscapeButton.isSelected()) {
239                            pageFormat.setOrientation(PageFormat.LANDSCAPE);
240                    }
241                    setScales();
242                    previewPanel.repaint();
243            }
244    
245            public void setScales() {
246                    try {
247                            xScaleFactor = ((Double) xsp.getValue()).doubleValue();
248                            yScaleFactor = ((Double) ysp.getValue()).doubleValue();
249                    } catch (NumberFormatException e) {
250                    }
251            }
252    
253            public void print() {
254                    PrinterJob printerJob = PrinterJob.getPrinterJob();
255                    Book book = new Book();
256                    book.append(new PrintPage(), pageFormat);
257                    printerJob.setPageable(book);
258                    boolean doPrint = printerJob.printDialog();
259                    if (doPrint) {
260                            try {
261                                    printerJob.print();
262                            } catch (PrinterException exception) {
263                                    System.err.println("Printing error: " + exception);
264                            }
265                    }
266            }
267    
268            class PrintPage implements Printable {
269    
270                    public int print(Graphics g, PageFormat format, int pageIndex) {
271                            Graphics2D g2d = (Graphics2D) g;
272                            g2d.translate(format.getImageableX(), format.getImageableY());
273    
274                            double dw = format.getImageableWidth();
275                            double dh = format.getImageableHeight();
276                            setScales();
277                            double xScale = dw / (targetComponent.getWidth() * xScaleFactor);
278                            // double yScale = dh / (targetComponent.getHeight() *
279                            // yScaleFactor);
280    
281                            g2d.scale(xScale, xScale);
282                            targetComponent.paint(g2d);
283                            return Printable.PAGE_EXISTS;
284                    }
285    
286                    public void disableDoubleBuffering(Component c) {
287                            RepaintManager currentManager = RepaintManager.currentManager(c);
288                            currentManager.setDoubleBufferingEnabled(false);
289                    }
290    
291                    public void enableDoubleBuffering(Component c) {
292                            RepaintManager currentManager = RepaintManager.currentManager(c);
293                            currentManager.setDoubleBufferingEnabled(true);
294                    }
295            }
296    
297            public void stateChanged(ChangeEvent e) {
298                    updatePreview();
299            }
300    }
301    
302    class PaperA4 extends Paper {
303    
304            private static final int CM = 28;
305    
306            private static final double A4_WIDTH = 21.0 * CM;
307    
308            private static final double A4_HEIGHT = 29.7 * CM;
309    
310            public PaperA4() {
311                    setSize(A4_WIDTH, A4_HEIGHT);
312                    setImageableArea(2 * CM, 2 * CM, A4_WIDTH - 4 * CM, A4_HEIGHT - 4 * CM);
313            }
314    
315    }