001 /*
002 * Copyright (c) 1995-2010, The University of Sheffield. See the file
003 * COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
004 *
005 * This file is part of GATE (see http://gate.ac.uk/), and is free
006 * software, licenced under the GNU Library General Public License,
007 * Version 2, June 1991 (in the distribution as file licence.html,
008 * and also available at http://gate.ac.uk/gate/licence.html).
009 *
010 * Valentin Tablan 07/12/2001
011 *
012 * $Id: JComponentPrinter.java 12950 2010-08-11 18:58:56Z bensonmargulies $
013 *
014 */
015 package gate.print;
016
017 import java.awt.*;
018 import java.awt.print.*;
019
020 import javax.swing.JComponent;
021 import javax.swing.text.BadLocationException;
022 import javax.swing.text.JTextComponent;
023
024 import gate.Gate;
025 import gate.event.StatusListener;
026 import gate.util.Err;
027
028
029 /**
030 * Will scale the component so it fits on a page horizontally
031 */
032 public class JComponentPrinter implements Pageable{
033
034 public JComponentPrinter(JComponent component, PageFormat format){
035 this.component = component;
036 this.pageFormat = format;
037 //find the scale factor; we will not enlarge as it would look ugly
038 Rectangle componentBounds = component.getBounds(null);
039 scaleFactor = Math.min(format.getImageableWidth() /componentBounds.width,
040 1);
041
042 //calculate the pages count
043 pageCount = (int)((componentBounds.height * scaleFactor +
044 pageFormat.getImageableHeight() - 1) /
045 pageFormat.getImageableHeight());
046 }
047
048 /**
049 * Returns the number of pages over which the canvas
050 * will be drawn.
051 */
052 public int getNumberOfPages() {
053 return pageCount;
054 }
055
056
057 /**
058 * Returns the PageFormat of the page specified by
059 * pageIndex. The PageFormat is the same for all pages.
060 *
061 * @param pageIndex the zero based index of the page whose
062 * PageFormat is being requested
063 * @return the PageFormat describing the size and
064 * orientation.
065 * @exception IndexOutOfBoundsException
066 * the Pageable does not contain the requested
067 * page.
068 */
069 public PageFormat getPageFormat(int pageIndex)
070 throws IndexOutOfBoundsException {
071 if (pageIndex >= pageCount) throw new IndexOutOfBoundsException();
072 return pageFormat;
073 }
074
075
076 /**
077 * Returns the <code>Printable</code> instance responsible for
078 * rendering the page specified by <code>pageIndex</code>.
079 *
080 * @param pageIndex the zero based index of the page whose
081 * Printable is being requested
082 * @return the Printable that renders the page.
083 * @exception IndexOutOfBoundsException
084 * the Pageable does not contain the requested
085 * page.
086 */
087 public Printable getPrintable(int pageIndex)
088 throws IndexOutOfBoundsException {
089 if (pageIndex >= pageCount)throw new IndexOutOfBoundsException();
090
091 double originY = pageIndex * pageFormat.getImageableHeight() / scaleFactor;
092 if(component instanceof JTextComponent){
093 JTextComponent tComp = (JTextComponent)component;
094 //move the origin up towards the first inter-row space
095 int location = tComp.viewToModel(new Point(0, (int)originY));
096 try{
097 Rectangle rect = tComp.modelToView(location);
098 originY = rect.y + rect.height - 1;
099 }catch(BadLocationException ble){
100 ble.printStackTrace(Err.getPrintWriter());
101 }
102 }
103
104 return new TranslatedPrintable(originY);
105 }
106
107
108 /**
109 * This inner class's sole responsibility is to translate
110 * the coordinate system before invoking a canvas's
111 * painter. The coordinate system is translated in order
112 * to get the desired portion of a canvas to line up with
113 * the top of a page.
114 */
115 public class TranslatedPrintable implements Printable {
116 public TranslatedPrintable(double originY){
117 this.originY = originY;
118 }
119
120 /**
121 * Prints the page at the specified index into the specified
122 * {@link Graphics} context in the specified
123 * format. A PrinterJob calls the
124 * Printableinterface to request that a page be
125 * rendered into the context specified by
126 * graphics. The format of the page to be drawn is
127 * specified by pageFormat. The zero based index
128 * of the requested page is specified by pageIndex.
129 * If the requested page does not exist then this method returns
130 * NO_SUCH_PAGE; otherwise PAGE_EXISTS is returned.
131 * The Graphics class or subclass implements the
132 * {@link PrinterGraphics} interface to provide additional
133 * information. If the Printable object
134 * aborts the print job then it throws a {@link PrinterException}.
135 * @param graphics the context into which the page is drawn
136 * @param pageFormat the size and orientation of the page being drawn
137 * @param pageIndex the zero based index of the page to be drawn
138 * @return PAGE_EXISTS if the page is rendered successfully
139 * or NO_SUCH_PAGE if pageIndex specifies a
140 * non-existent page.
141 * @exception java.awt.print.PrinterException
142 * thrown when the print job is terminated.
143 */
144 public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
145 throws PrinterException {
146
147 Rectangle componentBounds = component.getBounds(null);
148 Graphics2D g2 = (Graphics2D) graphics;
149 g2.translate(pageFormat.getImageableX() - componentBounds.x,
150 pageFormat.getImageableY() - originY - componentBounds.y);
151 g2.scale(scaleFactor, scaleFactor);
152
153 if(component instanceof JTextComponent){
154 JTextComponent tComp = (JTextComponent)component;
155 double nextOriginY = (pageIndex + 1) * pageFormat.getImageableHeight() /
156 scaleFactor;
157 int location = tComp.viewToModel(new Point(0, (int)nextOriginY));
158 try{
159 Rectangle rect = tComp.modelToView(location);
160 nextOriginY = rect.y;
161 }catch(BadLocationException ble){
162 ble.printStackTrace(Err.getPrintWriter());
163 }
164 Rectangle clip = g2.getClip().getBounds();
165 clip.setSize((int)clip.getWidth(), (int)(nextOriginY - originY) - 1);
166 g2.setClip(clip);
167 }
168
169 boolean wasBuffered = component.isDoubleBuffered();
170 component.paint(g2);
171 component.setDoubleBuffered(wasBuffered);
172
173 //fire the events
174 StatusListener sListener = (StatusListener)Gate.getListeners().
175 get("gate.event.StatusListener");
176 if(sListener != null){
177 sListener.statusChanged("Printing page " + (pageIndex + 1) +
178 "/" + pageCount);
179 }
180
181 return PAGE_EXISTS;
182 }
183
184 double originY;
185 }
186
187
188 JComponent component;
189 PageFormat pageFormat;
190 int pageCount;
191 double scaleFactor;
192 }
|