Clover coverage report - DrJava Test Coverage (drjava-20120304-r5456)
Coverage timestamp: Sun Mar 4 2012 03:13:23 CST
file stats: LOC: 504   Methods: 41
NCLOC: 319   Classes: 6
 
 Source file Conditionals Statements Methods TOTAL
PreviewFrame.java 0% 0% 0% 0%
coverage
 1    /*BEGIN_COPYRIGHT_BLOCK
 2    *
 3    * Copyright (c) 2001-2010, JavaPLT group at Rice University (drjava@rice.edu)
 4    * All rights reserved.
 5    *
 6    * Redistribution and use in source and binary forms, with or without
 7    * modification, are permitted provided that the following conditions are met:
 8    * * Redistributions of source code must retain the above copyright
 9    * notice, this list of conditions and the following disclaimer.
 10    * * Redistributions in binary form must reproduce the above copyright
 11    * notice, this list of conditions and the following disclaimer in the
 12    * documentation and/or other materials provided with the distribution.
 13    * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
 14    * names of its contributors may be used to endorse or promote products
 15    * derived from this software without specific prior written permission.
 16    *
 17    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18    * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 19    * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 20    * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 21    * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 22    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 23    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 24    * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 25    * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 26    * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 27    * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28    *
 29    * This software is Open Source Initiative approved Open Source Software.
 30    * Open Source Initative Approved is a trademark of the Open Source Initiative.
 31    *
 32    * This file is part of DrJava. Download the current version of this project
 33    * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
 34    *
 35    * END_COPYRIGHT_BLOCK*/
 36   
 37    package edu.rice.cs.drjava.ui;
 38   
 39    import javax.swing.*;
 40    import javax.swing.event.*;
 41    import javax.swing.border.MatteBorder;
 42    import javax.swing.border.EmptyBorder;
 43    import java.awt.event.*;
 44    import java.awt.*;
 45    import java.awt.print.*;
 46    import java.awt.image.*;
 47    import java.net.*;
 48    import java.lang.reflect.InvocationTargetException;
 49    import java.lang.reflect.Method;
 50   
 51    import edu.rice.cs.drjava.model.*;
 52    import edu.rice.cs.util.swing.SwingFrame;
 53   
 54    /** DrJava's print preview window
 55    * @version $Id: PreviewFrame.java 5436 2011-08-02 06:58:19Z mgricken $
 56    */
 57    public abstract class PreviewFrame extends SwingFrame {
 58   
 59    protected final SingleDisplayModel _model;
 60    protected final MainFrame _mainFrame;
 61    protected final Pageable _print;
 62    protected volatile int _pageNumber;
 63   
 64    //zooming modification
 65    Dimension _screenSize = Toolkit.getDefaultToolkit().getScreenSize();
 66    JSlider _zoomSlider = new JSlider(JSlider.HORIZONTAL, 100, 300, 100);
 67    //zooming modification
 68    private JScrollPane _previewScroll;
 69   
 70    // private JTextField _pageTextField = new JTextField("" + (_pageNumber + 1), 2) {
 71    // public Dimension getMaximumSize() {
 72    // return getPreferredSize();
 73    // }
 74    // };
 75   
 76    private final PageChangerUpdater _pageChanger;
 77   
 78    private static abstract class PageChangerUpdater {
 79    abstract void update(int pageNumber) throws Exception;
 80    abstract JComponent getComponent();
 81    }
 82   
 83    private class JTextFieldChanger extends PageChangerUpdater {
 84    private final JTextField textfield;
 85  0 private JTextFieldChanger(JTextField tf) { textfield = tf; }
 86  0 void update(int pageNumber) throws Exception { textfield.setText(String.valueOf(pageNumber)); }
 87  0 JComponent getComponent() { return textfield; }
 88    }
 89   
 90    private class JSpinnerChanger extends PageChangerUpdater {
 91    private volatile JComponent spinner;
 92    private volatile Method setValueMethod;
 93    private final Object[] args = new Object[1];
 94  0 private JSpinnerChanger(Class<?> spinnerClass, JComponent spinnerObj) throws Exception {
 95  0 spinner = spinnerObj;
 96  0 setValueMethod = spinnerClass.getMethod("setValue", Object.class);
 97    }
 98  0 void update(int pageNumber) throws Exception {
 99  0 args[0] = Integer.valueOf(pageNumber);
 100  0 setValueMethod.invoke(spinner, args);
 101    }
 102  0 JComponent getComponent() { return spinner; }
 103    }
 104   
 105    // Print Preview Dimensions
 106    private final int PREVIEW_WIDTH;
 107    private final int PREVIEW_HEIGHT;
 108    private final int PREVIEW_PAGE_WIDTH;
 109    private final int PREVIEW_PAGE_HEIGHT;
 110   
 111    private static final double PAGE_ZOOM = 0.7;
 112    private static final int PAGE_BORDER = 20;
 113    private static final int TOOLBAR_HEIGHT = 65;
 114    private static final String ICON_PATH = "/edu/rice/cs/drjava/ui/icons/";
 115   
 116    // Components
 117    private JToolBar _toolBar;
 118    private PagePreview _pagePreview;
 119   
 120    // Actions
 121    /** Prints the current document. */
 122    private final ActionListener _printListener = new ActionListener() {
 123  0 public void actionPerformed(ActionEvent ae) {
 124  0 _print();
 125  0 _close();
 126    }
 127    };
 128   
 129    /** Prints the current document. */
 130    private final Action _closeAction = new AbstractAction("Close") {
 131  0 public void actionPerformed(ActionEvent ae) { _close(); }
 132    };
 133   
 134    /** Displays the next page of the document. */
 135    private final Action _nextPageAction = new AbstractAction("Next Page") {
 136  0 public void actionPerformed(ActionEvent ae) { _nextPage(); }
 137    };
 138   
 139    /** Displays the previous page of the document. */
 140    private final Action _prevPageAction = new AbstractAction("Previous Page") {
 141  0 public void actionPerformed(ActionEvent ae) { _previousPage(); }
 142    };
 143   
 144    /** How Preview Pane responds to window events. */
 145    private final WindowListener _windowCloseListener = new WindowAdapter() {
 146  0 public void windowClosing(WindowEvent ev) { _close(); }
 147    };
 148   
 149    /** Contructs a new PreviewFrame using a parent model and a Pageable object print to show. Should only be called in
 150    * event thread.
 151    */
 152  0 public PreviewFrame(SingleDisplayModel model, MainFrame mainFrame, boolean interactions)
 153    throws IllegalStateException {
 154  0 super("Print Preview");
 155  0 mainFrame.hourglassOn();
 156  0 _model = model;
 157  0 _mainFrame = mainFrame;
 158  0 _toolBar = new JToolBar();
 159  0 _print = setUpDocument(model, interactions);
 160  0 _pageChanger = createPageChanger();
 161   
 162    /* Initialize constants. */
 163    //zooming modification
 164  0 PageFormat first = _print.getPageFormat(0);
 165   
 166  0 PREVIEW_PAGE_WIDTH = (int) (PAGE_ZOOM * first.getWidth());
 167  0 PREVIEW_PAGE_HEIGHT = (int) (PAGE_ZOOM * first.getHeight());
 168   
 169  0 PREVIEW_WIDTH = PREVIEW_PAGE_WIDTH + (2 * PAGE_BORDER);
 170  0 PREVIEW_HEIGHT = PREVIEW_PAGE_HEIGHT + (2 * PAGE_BORDER) + TOOLBAR_HEIGHT;
 171   
 172  0 _setUpActions();
 173  0 _setUpToolBar();
 174   
 175  0 _pagePreview = new PagePreview(PREVIEW_PAGE_WIDTH, PREVIEW_PAGE_HEIGHT);
 176  0 _pageNumber = 0;
 177   
 178    //zooming modification
 179    //PagePreviewContainer ppc = new PagePreviewContainer();
 180    //ppc.add(_pagePreview);
 181  0 JPanel previewHolder = new JPanel(new BorderLayout());
 182  0 JPanel tbCont = new JPanel(new BorderLayout());
 183  0 JPanel cp = new JPanel(new BorderLayout());
 184    //zooming modification
 185  0 _previewScroll = new JScrollPane(previewHolder);
 186    //_previewScroll = new JScrollPane(cp);
 187  0 _previewScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
 188  0 _previewScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
 189  0 tbCont.add(_toolBar,BorderLayout.NORTH);
 190  0 tbCont.add(Box.createVerticalStrut(10),BorderLayout.SOUTH);
 191  0 tbCont.setBorder(new EmptyBorder(0,0,5,0));
 192   
 193    //zooming modification
 194  0 previewHolder.add(_pagePreview, BorderLayout.CENTER);
 195  0 cp.add(_previewScroll);
 196   
 197  0 setContentPane(cp);
 198    //setContentPane(_previewScroll);
 199    //cp.add(_pagePreview, BorderLayout.CENTER);
 200  0 cp.setBorder(new EmptyBorder(5,5,5,5));
 201  0 cp.add(tbCont, BorderLayout.NORTH);
 202    //zooming modification
 203    //cp.add(ppc, BorderLayout.SOUTH);
 204  0 addWindowListener(_windowCloseListener);
 205   
 206  0 showPage();
 207  0 _updateActions();
 208    //zooming modification
 209    // setExtendedState(Frame.MAXIMIZED_BOTH);
 210    //setSize(screenSize.width, screenSize.height);
 211  0 setSize(PREVIEW_WIDTH, PREVIEW_HEIGHT);
 212  0 setDefaultCloseOperation(DISPOSE_ON_CLOSE);
 213   
 214  0 initDone(); // call mandated by SwingFrame contract
 215   
 216  0 setVisible(true);
 217    }
 218   
 219    //zooming modification
 220  0 public void setZoom(int percent, boolean fast){
 221  0 int h = (int)((PREVIEW_PAGE_HEIGHT * percent) / 100.0);
 222  0 int w = (int)((PREVIEW_PAGE_WIDTH * percent) / 100.0);
 223  0 _pagePreview.updateScaled(w, h, fast);
 224  0 repaint();
 225  0 if (!fast) {
 226  0 refreshScreen();
 227    }
 228    }
 229   
 230  0 public void refreshScreen() {
 231  0 int previewWidth = _pagePreview.getPreferredSize().width + (2 * PAGE_BORDER);
 232  0 int previewHeight = _pagePreview.getPreferredSize().height + (2 * PAGE_BORDER) + TOOLBAR_HEIGHT;
 233  0 if (previewWidth > _screenSize.width - TOOLBAR_HEIGHT) previewWidth = _screenSize.width - TOOLBAR_HEIGHT;
 234  0 if (previewHeight > _screenSize.height - TOOLBAR_HEIGHT) previewHeight = _screenSize.height - TOOLBAR_HEIGHT;
 235  0 setSize(previewWidth, previewHeight);
 236    }
 237   
 238    /** Prints the document being previewed */
 239    abstract protected void _print();
 240   
 241    /** Sets up the document to be displayed and returns the Pageable object that allows display by pages
 242    * @param model the current display model
 243    * @param interactions whether the document is an interactions document
 244    * @return a Pageable object that allows the document to be displayed by pages
 245    */
 246    abstract protected Pageable setUpDocument(SingleDisplayModel model, boolean interactions);
 247   
 248  0 private void _close() {
 249  0 dispose();
 250  0 _mainFrame.hourglassOff();
 251    }
 252   
 253  0 private void _nextPage() {
 254  0 _pageNumber++;
 255  0 _goToPage(_pageNumber);
 256    }
 257   
 258  0 private void _previousPage() {
 259  0 _pageNumber--;
 260  0 _goToPage(_pageNumber);
 261    }
 262   
 263  0 private void _goToPage(int pi) {
 264  0 _pageNumber = pi;
 265  0 showPage();
 266  0 _updateActions();
 267    }
 268   
 269  0 protected void _showError(Exception e, String title, String message) {
 270  0 JOptionPane.showMessageDialog(this, message + "\n" + e, title, JOptionPane.ERROR_MESSAGE);
 271    }
 272   
 273    /** Updates all of the buttons on the page to reflect the current state of the PreviewWindows. Enables/Disables the
 274    * page buttons, and updates the gotopage field.
 275    */
 276  0 private void _updateActions() {
 277  0 _nextPageAction.setEnabled(_print.getNumberOfPages() > (_pageNumber + 1));
 278  0 _prevPageAction.setEnabled(_pageNumber > 0);
 279  0 try { _pageChanger.update(_pageNumber + 1); }
 280    catch(Exception e) { /* ignore */ }
 281    }
 282   
 283    /** Initializes all action objects. Adds icons and descriptions to several of the actions. */
 284  0 private void _setUpActions() {
 285    //_printAction.putValue(Action.SHORT_DESCRIPTION, "Print");
 286  0 _closeAction.putValue(Action.SHORT_DESCRIPTION, "Close");
 287    //zooming modification
 288    //_zoomInAction.putValue(Action.SHORT_DESCRIPTION, "Zoom In");
 289    //_zoomOutAction.putValue(Action.SHORT_DESCRIPTION, "Zoom Out");
 290    //_zoomOutAction.setEnabled(false);
 291    // _printAction.putValue(Action.SMALL_ICON, _getIcon("Print16.gif"));
 292  0 _nextPageAction.putValue(Action.SMALL_ICON, _getIcon("Forward16.gif"));
 293  0 _nextPageAction.putValue(Action.SHORT_DESCRIPTION, "Next Page");
 294  0 _prevPageAction.putValue(Action.SMALL_ICON, _getIcon("Back16.gif"));
 295  0 _prevPageAction.putValue(Action.SHORT_DESCRIPTION, "Previous Page");
 296    }
 297   
 298  0 private PageChangerUpdater createPageChanger() {
 299    //_pageTextField.setAction(_goToPageAction);
 300    // _goToPageAction.putValue(Action.SHORT_DESCRIPTION, "Goto Page");
 301  0 try {
 302  0 Class<?> spinnerClass = Class.forName("javax.swing.JSpinner");
 303  0 final JComponent spinner = (JComponent) spinnerClass.newInstance();
 304  0 final Method getter = spinnerClass.getMethod("getValue",new Class<?>[0]);
 305  0 Object model = callMethod(spinner, spinnerClass, "getModel",null,null);
 306  0 Class<?> modelClass = model.getClass();
 307  0 Class<?>[] ca = new Class<?>[] {Comparable.class};
 308  0 Object[] aa = new Object[] {Integer.valueOf(1)};
 309  0 callMethod(model,modelClass,"setMinimum",ca,aa);
 310  0 aa[0] = Integer.valueOf(_print.getNumberOfPages());
 311  0 callMethod(model,modelClass,"setMaximum",ca,aa);
 312  0 ca[0] = ChangeListener.class;
 313  0 aa[0] = new ChangeListener() {
 314  0 public void stateChanged(ChangeEvent ev) {
 315  0 int num = _pageNumber;
 316  0 try {
 317  0 num = ((Number) getter.invoke(spinner,new Object[0])).intValue()-1;
 318  0 if ((num >= 0) && (num < _print.getNumberOfPages())) _goToPage(num);
 319  0 else _updateActions();
 320    }
 321  0 catch(IllegalAccessException ex) { _updateActions(); }
 322  0 catch(InvocationTargetException ex) { _updateActions(); }
 323    }
 324    };
 325  0 callMethod(spinner, spinnerClass,"addChangeListener",ca,aa);
 326  0 return new JSpinnerChanger(spinnerClass, spinner);
 327    } catch(Exception e) {
 328    /** Displays the previous page of the document. */
 329  0 final JTextField tf = new JTextField();
 330  0 tf.addActionListener(new ActionListener() {
 331  0 public void actionPerformed(ActionEvent ae) {
 332  0 try {
 333  0 int pageToGoTo = Integer.parseInt(tf.getText()) - 1;
 334  0 if ((pageToGoTo < 0) || (pageToGoTo >= _print.getNumberOfPages())) { _updateActions(); }
 335  0 else _goToPage(pageToGoTo);
 336    }
 337  0 catch (NumberFormatException e) { _updateActions(); }
 338    }
 339    });
 340  0 return new JTextFieldChanger(tf);
 341    }
 342    }
 343   
 344  0 private static Object callMethod(Object rec, Class<?> c, String name, Class<?>[] ca, Object[] args) throws Exception {
 345  0 Method m = c.getMethod(name,ca);
 346  0 return m.invoke(rec,args);
 347    }
 348   
 349    /** Mirrored from MainFrame, will later use the same Icon access code. */
 350  0 private ImageIcon _getIcon(String name) {
 351  0 URL url = PreviewFrame.class.getResource(ICON_PATH + name);
 352  0 if (url != null) return new ImageIcon(url);
 353  0 return null;
 354    }
 355   
 356    /** Sets up the toolbar with all of the necessary buttons. */
 357  0 private void _setUpToolBar() {
 358  0 _toolBar.setFloatable(false);
 359   
 360    // Print and Close buttons
 361  0 JButton printButton = new JButton("Print...",_getIcon("Print16.gif"));
 362  0 printButton.setToolTipText("Print this document");
 363  0 printButton.addActionListener(_printListener);
 364  0 _toolBar.add(printButton);
 365  0 _toolBar.addSeparator();
 366  0 _toolBar.add(_closeAction);
 367   
 368    // Horizontal Gap
 369  0 _toolBar.add(Box.createHorizontalGlue());
 370   
 371    //zooming modification
 372    //_toolBar.add(_zoomOutAction);
 373    //_toolBar.add(_zoomInAction);
 374    //zoomSlider.setMajorTickSpacing(10);
 375    //zoomSlider.setSnapToTicks(true);
 376  0 _zoomSlider.setPaintLabels(true);
 377  0 _zoomSlider.setLabelTable(_zoomSlider.createStandardLabels(100));
 378   
 379  0 _zoomSlider.addChangeListener(new ChangeListener() {
 380  0 public void stateChanged(ChangeEvent evt) {
 381  0 JSlider slider = (JSlider) evt.getSource();
 382  0 setZoom(slider.getValue(), slider.getValueIsAdjusting());
 383    }
 384    });
 385  0 _toolBar.add(_zoomSlider);
 386   
 387    // Navigation components
 388  0 _toolBar.add(_prevPageAction);
 389  0 _toolBar.add(_nextPageAction);
 390  0 _toolBar.addSeparator();
 391   
 392  0 JLabel gotop = new JLabel("Page");
 393   
 394  0 JLabel of = new JLabel(" of " + _print.getNumberOfPages());
 395   
 396  0 _toolBar.add(gotop);
 397  0 _toolBar.addSeparator();
 398  0 JComponent c = _pageChanger.getComponent();
 399  0 Dimension d = c.getPreferredSize();
 400  0 d = new Dimension(100,d.height);
 401  0 c.setMaximumSize(d);
 402  0 c.setPreferredSize(d);
 403  0 c.setMinimumSize(d);
 404  0 c.setToolTipText("Goto Page");
 405  0 _toolBar.add(c);
 406  0 _toolBar.add(of);
 407    }
 408   
 409    /** Generates an Image, prints to it, and then displays the image on the page. */
 410  0 private void showPage() {
 411  0 BufferedImage img = new BufferedImage((int) _model.getPageFormat().getWidth(),
 412    (int) _model.getPageFormat().getHeight(),
 413    BufferedImage.TYPE_INT_RGB);
 414  0 Graphics g = img.getGraphics();
 415  0 g.setColor(Color.white);
 416  0 g.fillRect(0, 0, (int) _model.getPageFormat().getWidth(), (int) _model.getPageFormat().getHeight());
 417   
 418  0 try {
 419  0 _print.getPrintable(_pageNumber).print(g, _model.getPageFormat(), _pageNumber);
 420  0 _pagePreview.setImage(img);
 421    }
 422    catch (PrinterException e) { /* ignore */ }
 423    }
 424   
 425    /** Internal class which holds (and places) the PagePreview object. */
 426    class PagePreviewContainer extends JPanel {
 427  0 public Dimension getPreferredSize() { return getParent().getSize(); }
 428   
 429    /** Places the PagePreview component into the center of this object */
 430  0 public void doLayout() {
 431  0 Component cp = getComponent(0);
 432   
 433  0 Dimension dm = cp.getPreferredSize();
 434  0 int Hindent = (int) (getPreferredSize().getWidth() - dm.getWidth()) / 2;
 435  0 int Vindent = TOOLBAR_HEIGHT + (int) ((getPreferredSize().getHeight() - dm.getHeight() - TOOLBAR_HEIGHT) / 2);
 436  0 _pagePreview.setBounds(Hindent, Vindent, (int) dm.getWidth(), (int) dm.getHeight());
 437    }
 438    }
 439   
 440    /** Static inner class which displays the image on the screen, and holds the Image object. */
 441    static class PagePreview extends JPanel {
 442    // protected final int _width;
 443    // protected final int _height;
 444    //zooming modification
 445    //we need to change the variables from final to non-final because we need to enlarge the page preview area when we zoom in
 446    protected int _width;
 447    protected int _height;
 448    protected volatile Image _source;
 449    protected volatile Image _image;
 450   
 451    /** Constructs a PagePreview object with given width and height. */
 452  0 public PagePreview(int width, int height) {
 453  0 super();
 454  0 _width = width;
 455  0 _height = height;
 456  0 setBorder(new MatteBorder(1, 1, 2, 2, Color.black));
 457  0 setBackground(Color.white);
 458    }
 459   
 460    /** Scales the interal image to the appropriate size. */
 461  0 protected void updateScaled() {
 462  0 _image = _source.getScaledInstance(_width, _height, Image.SCALE_SMOOTH);
 463  0 _image.flush();
 464    }
 465   
 466    //zooming modification
 467  0 protected void updateScaled(int newWidth, int newHeight, boolean fast) {
 468  0 _width = newWidth;
 469  0 _height = newHeight;
 470  0 _image = _source.getScaledInstance(newWidth, newHeight, fast?Image.SCALE_FAST:Image.SCALE_SMOOTH);
 471  0 _image.flush();
 472    }
 473   
 474    /** Updates the image of this PagePreview.
 475    * @param i The Image to place and show.
 476    */
 477  0 public void setImage(Image i) {
 478  0 _source = i;
 479  0 updateScaled();
 480  0 repaint();
 481    }
 482   
 483    //zooming modification
 484  0 public int getHeight() {
 485  0 return _height;
 486    }
 487  0 public int getWidth() {
 488  0 return _width;
 489    }
 490   
 491  0 public Dimension getPreferredSize() { return new Dimension(_width, _height); }
 492   
 493  0 public Dimension getMaximumSize() { return getPreferredSize(); }
 494   
 495  0 public Dimension getMinimumSize() { return getPreferredSize(); }
 496   
 497  0 public void paint(Graphics g) {
 498  0 g.setColor(getBackground());
 499  0 g.fillRect(0, 0, _width, _height);
 500  0 g.drawImage(_image, 0, 0, this);
 501  0 paintBorder(g);
 502    }
 503    }
 504    }