/jEdit/tags/jedit-4-2-pre4/org/gjt/sp/jedit/print/BufferPrintable.java
Java | 360 lines | 259 code | 52 blank | 49 comment | 29 complexity | 0ac8e251a8b3116b9bc5e102d72ec3ef MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
1/*
2 * BufferPrintable.java - Printable implementation
3 * :tabSize=8:indentSize=8:noTabs=false:
4 * :folding=explicit:collapseFolds=1:
5 *
6 * Copyright (C) 2001, 2003 Slava Pestov
7 * Portions copyright (C) 2002 Thomas Dilts
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24package org.gjt.sp.jedit.print;
25
26//{{{ Imports
27import javax.swing.text.Segment;
28import javax.swing.text.TabExpander;
29import javax.swing.SwingUtilities;
30import java.awt.font.*;
31import java.awt.geom.*;
32import java.awt.print.*;
33import java.awt.*;
34import java.lang.reflect.Method;
35import java.util.*;
36import org.gjt.sp.jedit.syntax.*;
37import org.gjt.sp.jedit.*;
38import org.gjt.sp.util.*;
39//}}}
40
41class BufferPrintable implements Printable
42{
43 //{{{ BufferPrintable constructor
44 BufferPrintable(PrinterJob job, Object format,
45 View view, Buffer buffer, Font font, boolean header,
46 boolean footer, boolean lineNumbers, boolean color)
47 {
48 this.job = job;
49 this.format = format;
50 this.view = view;
51 this.buffer = buffer;
52 this.font = font;
53 this.header = header;
54 this.footer = footer;
55 this.lineNumbers = lineNumbers;
56
57 styles = GUIUtilities.loadStyles(jEdit.getProperty("print.font"),
58 jEdit.getIntegerProperty("print.fontsize",10),color);
59 styles[Token.NULL] = new SyntaxStyle(textColor,null,font);
60
61 lineList = new ArrayList();
62
63 tokenHandler = new DisplayTokenHandler();
64 } //}}}
65
66 //{{{ print() method
67 public void print()
68 {
69 try
70 {
71 //buffer.readLock();
72
73 if(format == null)
74 job.print();
75 else
76 {
77 Method method = PrinterJob.class.getMethod(
78 "print",new Class[] { Class.forName(
79 "javax.print.attribute.PrintRequestAttributeSet") });
80 method.invoke(job,new Object[] { format });
81 }
82 }
83 catch(PrinterAbortException ae)
84 {
85 Log.log(Log.DEBUG,this,ae);
86 }
87 catch(Exception e)
88 {
89 Log.log(Log.ERROR,this,e);
90 final String[] args = { e.toString() };
91 SwingUtilities.invokeLater(new Runnable()
92 {
93 public void run()
94 {
95 GUIUtilities.error(view,"print-error",args);
96 }
97 });
98 }
99 finally
100 {
101 //buffer.readUnlock();
102 }
103 } //}}}
104
105 //{{{ print() method
106 public int print(Graphics _gfx, PageFormat pageFormat, int pageIndex)
107 throws PrinterException
108 {
109 if(pageIndex > currentPage)
110 {
111 for(int i = currentPage; i < pageIndex; i++)
112 {
113 currentPhysicalLine = currentPageStart;
114 printPage(_gfx,pageFormat,i,true);
115 }
116
117 currentPage = pageIndex - 1;
118 }
119
120 if(pageIndex == currentPage + 1)
121 {
122 if(end)
123 return NO_SUCH_PAGE;
124
125 currentPageStart = currentPhysicalLine;
126 currentPage = pageIndex;
127 }
128 else if(pageIndex == currentPage)
129 {
130 currentPhysicalLine = currentPageStart;
131 }
132
133 printPage(_gfx,pageFormat,pageIndex,true);
134
135 return PAGE_EXISTS;
136 } //}}}
137
138 //{{{ Private members
139
140 //{{{ Static variables
141 private static Color headerColor = Color.lightGray;
142 private static Color headerTextColor = Color.black;
143 private static Color footerColor = Color.lightGray;
144 private static Color footerTextColor = Color.black;
145 private static Color lineNumberColor = Color.gray;
146 private static Color textColor = Color.black;
147 //}}}
148
149 //{{{ Instance variables
150 private PrinterJob job;
151 private Object format;
152
153 private View view;
154 private Buffer buffer;
155 private Font font;
156 private SyntaxStyle[] styles;
157 private boolean header;
158 private boolean footer;
159 private boolean lineNumbers;
160
161 private int currentPage;
162 private int currentPageStart;
163 private int currentPhysicalLine;
164 private boolean end;
165
166 private LineMetrics lm;
167 private ArrayList lineList;
168
169 private DisplayTokenHandler tokenHandler;
170 //}}}
171
172 //{{{ printPage() method
173 private void printPage(Graphics _gfx, PageFormat pageFormat, int pageIndex,
174 boolean actuallyPaint)
175 {
176 Graphics2D gfx = (Graphics2D)_gfx;
177 gfx.setFont(font);
178
179 double pageX = pageFormat.getImageableX();
180 double pageY = pageFormat.getImageableY();
181 double pageWidth = pageFormat.getImageableWidth();
182 double pageHeight = pageFormat.getImageableHeight();
183
184 if(header)
185 {
186 double headerHeight = paintHeader(gfx,pageX,pageY,pageWidth,
187 actuallyPaint);
188 pageY += headerHeight;
189 pageHeight -= headerHeight;
190 }
191
192 if(footer)
193 {
194 double footerHeight = paintFooter(gfx,pageX,pageY,pageWidth,
195 pageHeight,pageIndex,actuallyPaint);
196 pageHeight -= footerHeight;
197 }
198
199 FontRenderContext frc = gfx.getFontRenderContext();
200
201 boolean glyphVector = jEdit.getBooleanProperty("print.glyphVector");
202 double lineNumberWidth;
203
204 //{{{ determine line number width
205 if(lineNumbers)
206 {
207 // the +1's ensure that 99 gets 3 digits, 103 gets 4 digits,
208 // and so on.
209 int lineNumberDigits = (int)Math.ceil(Math.log(buffer.getLineCount() + 1)
210 / Math.log(10)) + 1;
211
212 // now that we know how many chars there are, get the width.
213 char[] chars = new char[lineNumberDigits];
214 for(int i = 0; i < chars.length; i++)
215 chars[i] = ' ';
216 lineNumberWidth = font.getStringBounds(chars,
217 0,lineNumberDigits,frc).getWidth();
218 }
219 else
220 lineNumberWidth = 0.0;
221 //}}}
222
223 //{{{ calculate tab size
224 int tabSize = jEdit.getIntegerProperty("print.tabSize",8);
225 char[] chars = new char[tabSize];
226 for(int i = 0; i < chars.length; i++)
227 chars[i] = ' ';
228 double tabWidth = font.getStringBounds(chars,
229 0,tabSize,frc).getWidth();
230 PrintTabExpander e = new PrintTabExpander(tabWidth);
231 //}}}
232
233 double y = 0.0;
234
235 lm = font.getLineMetrics("gGyYX",frc);
236
237print_loop: for(;;)
238 {
239 if(currentPhysicalLine == buffer.getLineCount())
240 {
241 end = true;
242 break print_loop;
243 }
244
245 lineList.clear();
246
247 tokenHandler.init(styles,frc,e,lineList,
248 (float)(pageWidth - lineNumberWidth));
249
250 buffer.markTokens(currentPhysicalLine,tokenHandler);
251 if(lineList.size() == 0)
252 lineList.add(null);
253
254 if(y + (lm.getHeight() * lineList.size()) >= pageHeight)
255 break print_loop;
256
257 if(lineNumbers && actuallyPaint)
258 {
259 gfx.setFont(font);
260 gfx.setColor(lineNumberColor);
261 gfx.drawString(String.valueOf(currentPhysicalLine + 1),
262 (float)pageX,(float)(pageY + y + lm.getHeight()));
263 }
264
265 for(int i = 0; i < lineList.size(); i++)
266 {
267 y += lm.getHeight();
268 Chunk chunks = (Chunk)lineList.get(i);
269 if(chunks != null && actuallyPaint)
270 {
271 Chunk.paintChunkBackgrounds(chunks,gfx,
272 (float)(pageX + lineNumberWidth),
273 (float)(pageY + y));
274 Chunk.paintChunkList(chunks,gfx,
275 (float)(pageX + lineNumberWidth),
276 (float)(pageY + y),glyphVector);
277 }
278 }
279
280 currentPhysicalLine++;
281 }
282 } //}}}
283
284 //{{{ paintHeader() method
285 private double paintHeader(Graphics2D gfx, double pageX, double pageY,
286 double pageWidth, boolean actuallyPaint)
287 {
288 String headerText = jEdit.getProperty("print.headerText",
289 new String[] { buffer.getName() });
290 FontRenderContext frc = gfx.getFontRenderContext();
291 lm = font.getLineMetrics(headerText,frc);
292
293 Rectangle2D bounds = font.getStringBounds(headerText,frc);
294 Rectangle2D headerBounds = new Rectangle2D.Double(
295 pageX,pageY,pageWidth,bounds.getHeight());
296
297 if(actuallyPaint)
298 {
299 gfx.setColor(headerColor);
300 gfx.fill(headerBounds);
301 gfx.setColor(headerTextColor);
302 gfx.drawString(headerText,
303 (float)(pageX + (pageWidth - bounds.getWidth()) / 2),
304 (float)(pageY + lm.getAscent()));
305 }
306
307 return headerBounds.getHeight();
308 }
309 //}}}
310
311 //{{{ paintFooter() method
312 private double paintFooter(Graphics2D gfx, double pageX, double pageY,
313 double pageWidth, double pageHeight, int pageIndex,
314 boolean actuallyPaint)
315 {
316 String footerText = jEdit.getProperty("print.footerText",
317 new Object[] { new Date(), new Integer(pageIndex + 1) });
318 FontRenderContext frc = gfx.getFontRenderContext();
319 lm = font.getLineMetrics(footerText,frc);
320
321 Rectangle2D bounds = font.getStringBounds(footerText,frc);
322 Rectangle2D footerBounds = new Rectangle2D.Double(
323 pageX,pageY + pageHeight - bounds.getHeight(),
324 pageWidth,bounds.getHeight());
325
326 if(actuallyPaint)
327 {
328 gfx.setColor(footerColor);
329 gfx.fill(footerBounds);
330 gfx.setColor(footerTextColor);
331 gfx.drawString(footerText,
332 (float)(pageX + (pageWidth - bounds.getWidth()) / 2),
333 (float)(pageY + pageHeight - bounds.getHeight()
334 + lm.getAscent()));
335 }
336
337 return footerBounds.getHeight();
338 } //}}}
339
340 //}}}
341
342 //{{{ PrintTabExpander class
343 static class PrintTabExpander implements TabExpander
344 {
345 private double tabWidth;
346
347 //{{{ PrintTabExpander constructor
348 public PrintTabExpander(double tabWidth)
349 {
350 this.tabWidth = tabWidth;
351 } //}}}
352
353 //{{{ nextTabStop() method
354 public float nextTabStop(float x, int tabOffset)
355 {
356 int ntabs = (int)((x + 1) / tabWidth);
357 return (float)((ntabs + 1) * tabWidth);
358 } //}}}
359 } //}}}
360}