KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > rice > cs > drjava > ui > PreviewFrame


1 /*BEGIN_COPYRIGHT_BLOCK
2  *
3  * This file is part of DrJava. Download the current version of this project from http://www.drjava.org/
4  * or http://sourceforge.net/projects/drjava/
5  *
6  * DrJava Open Source License
7  *
8  * Copyright (C) 2001-2005 JavaPLT group at Rice University (javaplt@rice.edu). All rights reserved.
9  *
10  * Developed by: Java Programming Languages Team, Rice University, http://www.cs.rice.edu/~javaplt/
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
13  * documentation files (the "Software"), to deal with the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
15  * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
16  *
17  * - Redistributions of source code must retain the above copyright notice, this list of conditions and the
18  * following disclaimers.
19  * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
20  * following disclaimers in the documentation and/or other materials provided with the distribution.
21  * - Neither the names of DrJava, the JavaPLT, Rice University, nor the names of its contributors may be used to
22  * endorse or promote products derived from this Software without specific prior written permission.
23  * - Products derived from this software may not be called "DrJava" nor use the term "DrJava" as part of their
24  * names without prior written permission from the JavaPLT group. For permission, write to javaplt@rice.edu.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
27  * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28  * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
29  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30  * WITH THE SOFTWARE.
31  *
32  *END_COPYRIGHT_BLOCK*/

33
34 package edu.rice.cs.drjava.ui;
35
36 import javax.swing.*;
37 import javax.swing.event.*;
38 import javax.swing.border.MatteBorder JavaDoc;
39 import javax.swing.border.EmptyBorder JavaDoc;
40 import java.awt.event.*;
41 import java.awt.*;
42 import java.awt.print.*;
43 import java.awt.image.*;
44 import java.net.*;
45 import java.lang.reflect.Method JavaDoc;
46 import edu.rice.cs.drjava.model.*;
47
48 /** DrJava's print preview window
49  * @version $Id: PreviewFrame.java 4033 2006-11-16 20:16:51Z rcartwright $
50  */

51 public abstract class PreviewFrame extends JFrame {
52
53   protected final SingleDisplayModel _model;
54   protected final MainFrame _mainFrame;
55   protected final Pageable _print;
56   protected volatile int _pageNumber;
57
58 // private JTextField _pageTextField = new JTextField("" + (_pageNumber + 1), 2) {
59
// public Dimension getMaximumSize() {
60
// return getPreferredSize();
61
// }
62
// };
63

64   private final PageChangerUpdater _pageChanger;
65
66   private static abstract class PageChangerUpdater {
67     abstract void update(int pageNumber) throws Exception JavaDoc;
68     abstract JComponent getComponent();
69   }
70
71   private class JTextFieldChanger extends PageChangerUpdater {
72     private final JTextField textfield;
73     private JTextFieldChanger(JTextField tf) { textfield = tf; }
74     void update(int pageNumber) throws Exception JavaDoc { textfield.setText(String.valueOf(pageNumber)); }
75     JComponent getComponent() { return textfield; }
76   }
77
78   private class JSpinnerChanger extends PageChangerUpdater {
79     private volatile JComponent spinner;
80     private volatile Method JavaDoc setValueMethod;
81     private final Object JavaDoc[] args = new Object JavaDoc[1];
82     private JSpinnerChanger(Class JavaDoc<?> spinnerClass, JComponent spinnerObj) throws Exception JavaDoc {
83       spinner = spinnerObj;
84       setValueMethod = spinnerClass.getMethod("setValue", Object JavaDoc.class);
85     }
86     void update(int pageNumber) throws Exception JavaDoc {
87       args[0] = new Integer JavaDoc(pageNumber);
88       setValueMethod.invoke(spinner, args);
89     }
90     JComponent getComponent() { return spinner; }
91   }
92
93   // Print Preview Dimensions
94
private final int PREVIEW_WIDTH;
95   private final int PREVIEW_HEIGHT;
96   private final int PREVIEW_PAGE_WIDTH;
97   private final int PREVIEW_PAGE_HEIGHT;
98   
99   private final double PAGE_ZOOM = 0.7;
100   private final static int PAGE_BORDER = 20;
101   private final int TOOLBAR_HEIGHT = 35;
102   private static final String JavaDoc ICON_PATH = "/edu/rice/cs/drjava/ui/icons/";
103
104   // Components
105
private JToolBar _toolBar;
106   private PagePreview _pagePreview;
107
108   // Actions
109
/** Prints the current document. */
110   private final ActionListener _printListener = new ActionListener() {
111     public void actionPerformed(ActionEvent ae) {
112       _print();
113       _close();
114     }
115   };
116
117   /** Prints the current document. */
118   private final Action _closeAction = new AbstractAction("Close") {
119     public void actionPerformed(ActionEvent ae) { _close(); }
120   };
121
122   /** Displays the next page of the document. */
123   private final Action _nextPageAction = new AbstractAction("Next Page") {
124     public void actionPerformed(ActionEvent ae) { _nextPage(); }
125   };
126
127   /** Displays the previous page of the document. */
128   private final Action _prevPageAction = new AbstractAction("Previous Page") {
129     public void actionPerformed(ActionEvent ae) { _previousPage(); }
130   };
131
132   /** How Preview Pane responds to window events. */
133   private final WindowListener _windowCloseListener = new WindowAdapter() {
134     public void windowClosing(WindowEvent ev) { _close(); }
135   };
136
137   /** Contructs a new PreviewFrame using a parent model and a Pageable object print to show. Should only be called in
138     * event thread.
139     */

140   public PreviewFrame(SingleDisplayModel model, MainFrame mainFrame, boolean interactions)
141     throws IllegalStateException JavaDoc {
142     super("Print Preview");
143     mainFrame.hourglassOn();
144     _model = model;
145     _mainFrame = mainFrame;
146     _toolBar = new JToolBar();
147     _print = setUpDocument(model, interactions);
148     _pageChanger = createPageChanger();
149     
150     /* Initialize constants. */
151     PageFormat first = _print.getPageFormat(0);
152
153     PREVIEW_PAGE_WIDTH = (int) (PAGE_ZOOM * first.getWidth());
154     PREVIEW_PAGE_HEIGHT = (int) (PAGE_ZOOM * first.getHeight());
155
156     PREVIEW_WIDTH = PREVIEW_PAGE_WIDTH + (2 * PAGE_BORDER);
157     PREVIEW_HEIGHT = PREVIEW_PAGE_HEIGHT + (2 * PAGE_BORDER) + TOOLBAR_HEIGHT;
158
159     _setUpActions();
160     _setUpToolBar();
161
162     _pagePreview = new PagePreview(PREVIEW_PAGE_WIDTH, PREVIEW_PAGE_HEIGHT);
163     _pageNumber = 0;
164
165
166     PagePreviewContainer ppc = new PagePreviewContainer();
167     ppc.add(_pagePreview);
168     JPanel tbCont = new JPanel(new BorderLayout());
169     JPanel cp = new JPanel(new BorderLayout());
170     tbCont.add(_toolBar,BorderLayout.NORTH);
171     tbCont.add(Box.createVerticalStrut(10),BorderLayout.SOUTH);
172     tbCont.setBorder(new EmptyBorder JavaDoc(0,0,5,0));
173     setContentPane(cp);
174     cp.setBorder(new EmptyBorder JavaDoc(5,5,5,5));
175     cp.add(tbCont, BorderLayout.NORTH);
176     cp.add(ppc, BorderLayout.SOUTH);
177
178     addWindowListener(_windowCloseListener);
179
180     showPage();
181     _updateActions();
182
183     setSize(PREVIEW_WIDTH, PREVIEW_HEIGHT);
184     setDefaultCloseOperation(DISPOSE_ON_CLOSE);
185     setVisible(true);
186   }
187
188   /** Prints the document being previewed */
189   abstract protected void _print();
190   
191   /** Sets up the document to be displayed and returns the Pageable object that allows display by pages
192    * @param model the current display model
193    * @param interactions whether the document is an interactions document
194    * @return a Pageable object that allows the document to be displayed by pages
195    */

196   abstract protected Pageable setUpDocument(SingleDisplayModel model, boolean interactions);
197
198   private void _close() {
199     dispose();
200     _mainFrame.hourglassOff();
201   }
202
203   private void _nextPage() {
204     _pageNumber++;
205     _goToPage(_pageNumber);
206   }
207
208   private void _previousPage() {
209     _pageNumber--;
210     _goToPage(_pageNumber);
211   }
212
213   private void _goToPage(int pi) {
214     _pageNumber = pi;
215     showPage();
216     _updateActions();
217   }
218
219   protected void _showError(Exception JavaDoc e, String JavaDoc title, String JavaDoc message) {
220     JOptionPane.showMessageDialog(this, message + "\n" + e, title, JOptionPane.ERROR_MESSAGE);
221   }
222
223   /** Updates all of the buttons on the page to reflect the current state of the PreviewWindows. Enables/Disables the
224    * page buttons, and updates the gotopage field.
225    */

226   private void _updateActions() {
227     _nextPageAction.setEnabled(_print.getNumberOfPages() > (_pageNumber + 1));
228     _prevPageAction.setEnabled(_pageNumber > 0);
229     try { _pageChanger.update(_pageNumber + 1); }
230     catch(Exception JavaDoc e) { /* ignore */ }
231   }
232
233   /** Initializes all action objects. Adds icons and descriptions to several of the actions. */
234   private void _setUpActions() {
235     //_printAction.putValue(Action.SHORT_DESCRIPTION, "Print");
236
_closeAction.putValue(Action.SHORT_DESCRIPTION, "Close");
237     // _printAction.putValue(Action.SMALL_ICON, _getIcon("Print16.gif"));
238
_nextPageAction.putValue(Action.SMALL_ICON, _getIcon("Forward16.gif"));
239     _nextPageAction.putValue(Action.SHORT_DESCRIPTION, "Next Page");
240     _prevPageAction.putValue(Action.SMALL_ICON, _getIcon("Back16.gif"));
241     _prevPageAction.putValue(Action.SHORT_DESCRIPTION, "Previous Page");
242   }
243
244   private PageChangerUpdater createPageChanger() {
245     //_pageTextField.setAction(_goToPageAction);
246
// _goToPageAction.putValue(Action.SHORT_DESCRIPTION, "Goto Page");
247
try {
248       Class JavaDoc<?> spinnerClass = Class.forName("javax.swing.JSpinner");
249       final JComponent spinner = (JComponent) spinnerClass.newInstance();
250       final Method JavaDoc getter = spinnerClass.getMethod("getValue",new Class JavaDoc[0]);
251       Object JavaDoc model = callMethod(spinner, spinnerClass, "getModel",null,null);
252       Class JavaDoc<?> modelClass = model.getClass();
253       Class JavaDoc<?>[] ca = new Class JavaDoc<?>[] {Comparable JavaDoc.class};
254       Object JavaDoc[] aa = new Object JavaDoc[] {new Integer JavaDoc(1)};
255       callMethod(model,modelClass,"setMinimum",ca,aa);
256       aa[0] = new Integer JavaDoc(_print.getNumberOfPages());
257       callMethod(model,modelClass,"setMaximum",ca,aa);
258       ca[0] = ChangeListener.class;
259       aa[0] = new ChangeListener() {
260         public void stateChanged(ChangeEvent ev) {
261           int num = _pageNumber;
262           try {
263             num = ((Number JavaDoc) getter.invoke(spinner,new Object JavaDoc[0])).intValue()-1;
264             if ((num >= 0) && (num < _print.getNumberOfPages())) _goToPage(num);
265             else _updateActions();
266           }
267           catch(Exception JavaDoc ex) { _updateActions(); }
268         }
269       };
270       callMethod(spinner, spinnerClass,"addChangeListener",ca,aa);
271       return new JSpinnerChanger(spinnerClass, spinner);
272     } catch(Exception JavaDoc e) {
273       /** Displays the previous page of the document. */
274       final JTextField tf = new JTextField();
275       tf.addActionListener(new ActionListener() {
276         public void actionPerformed(ActionEvent ae) {
277           try {
278             int pageToGoTo = Integer.parseInt(tf.getText()) - 1;
279             if ((pageToGoTo < 0) || (pageToGoTo >= _print.getNumberOfPages())) { _updateActions(); }
280             else _goToPage(pageToGoTo);
281           }
282           catch (NumberFormatException JavaDoc e) { _updateActions(); }
283         }
284       });
285       return new JTextFieldChanger(tf);
286     }
287   }
288
289   private static Object JavaDoc callMethod(Object JavaDoc rec, Class JavaDoc<?> c, String JavaDoc name, Class JavaDoc<?>[] ca, Object JavaDoc[] args) throws Exception JavaDoc {
290     Method JavaDoc m = c.getMethod(name,ca);
291     return m.invoke(rec,args);
292   }
293
294   /** Mirrored from MainFrame, will later use the same Icon access code. */
295   private ImageIcon _getIcon(String JavaDoc name) {
296     URL url = PreviewFrame.class.getResource(ICON_PATH + name);
297     if (url != null) return new ImageIcon(url);
298     return null;
299   }
300
301   /** Sets up the toolbar with all of the necessary buttons. */
302   private void _setUpToolBar() {
303     _toolBar.setFloatable(false);
304
305     // Print and Close buttons
306
JButton printButton = new JButton("Print...",_getIcon("Print16.gif"));
307     printButton.setToolTipText("Print this document");
308     printButton.addActionListener(_printListener);
309     _toolBar.add(printButton);
310     _toolBar.addSeparator();
311     _toolBar.add(_closeAction);
312
313     // Horizontal Gap
314
_toolBar.add(Box.createHorizontalGlue());
315
316     // Navigation components
317
_toolBar.add(_prevPageAction);
318     _toolBar.add(_nextPageAction);
319     _toolBar.addSeparator();
320
321     JLabel gotop = new JLabel("Page");
322
323     JLabel of = new JLabel(" of " + _print.getNumberOfPages());
324
325     _toolBar.add(gotop);
326     _toolBar.addSeparator();
327     JComponent c = _pageChanger.getComponent();
328     Dimension d = c.getPreferredSize();
329     d = new Dimension(100,d.height);
330     c.setMaximumSize(d);
331     c.setPreferredSize(d);
332     c.setMinimumSize(d);
333     c.setToolTipText("Goto Page");
334     _toolBar.add(c);
335     _toolBar.add(of);
336   }
337
338   /** Generates an Image, prints to it, and then displays the image on the page. */
339   private void showPage() {
340     BufferedImage img = new BufferedImage((int) _model.getPageFormat().getWidth(),
341                                           (int) _model.getPageFormat().getHeight(),
342                                           BufferedImage.TYPE_INT_RGB);
343     Graphics g = img.getGraphics();
344     g.setColor(Color.white);
345     g.fillRect(0, 0, (int) _model.getPageFormat().getWidth(), (int) _model.getPageFormat().getHeight());
346
347     try {
348       _print.getPrintable(_pageNumber).print(g, _model.getPageFormat(), _pageNumber);
349       _pagePreview.setImage(img);
350     }
351     catch (PrinterException e) { /* ignore */ }
352   }
353
354   /** Internal class which holds (and places) the PagePreview object. */
355   class PagePreviewContainer extends JPanel {
356     public Dimension getPreferredSize() { return getParent().getSize(); }
357
358     /** Places the PagePreview component into the center of this object */
359     public void doLayout() {
360       Component cp = getComponent(0);
361
362       Dimension dm = cp.getPreferredSize();
363       int Hindent = (int) (getPreferredSize().getWidth() - dm.getWidth()) / 2;
364       int Vindent = TOOLBAR_HEIGHT + (int) ((getPreferredSize().getHeight() - dm.getHeight() - TOOLBAR_HEIGHT) / 2);
365       _pagePreview.setBounds(Hindent, Vindent, (int) dm.getWidth(), (int) dm.getHeight());
366     }
367   }
368
369   /** Static inner class which displays the image on the screen, and holds the Image object. */
370   static class PagePreview extends JPanel {
371     protected final int _width;
372     protected final int _height;
373     protected volatile Image _source;
374     protected volatile Image _image;
375
376     /** Constructs a PagePreview object with given width and height. */
377     public PagePreview(int width, int height) {
378       super();
379       _width = width;
380       _height = height;
381       setBorder(new MatteBorder JavaDoc(1, 1, 2, 2, Color.black));
382       setBackground(Color.white);
383     }
384
385     /** Scales the interal image to the appropriate size. */
386     protected void updateScaled() {
387       _image = _source.getScaledInstance(_width, _height, Image.SCALE_SMOOTH);
388       _image.flush();
389     }
390
391     /** Updates the image of this PagePreview.
392      * @param i The Image to place and show.
393      */

394     public void setImage(Image i) {
395       _source = i;
396       updateScaled();
397       repaint();
398     }
399
400     public Dimension getPreferredSize() { return new Dimension(_width, _height); }
401
402     public Dimension getMaximumSize() { return getPreferredSize(); }
403
404     public Dimension getMinimumSize() { return getPreferredSize(); }
405
406     public void paint(Graphics g) {
407       g.setColor(getBackground());
408       g.fillRect(0, 0, _width, _height);
409       g.drawImage(_image, 0, 0, this);
410       paintBorder(g);
411     }
412   }
413 }
Popular Tags