PageRenderTime 40ms CodeModel.GetById 9ms app.highlight 26ms RepoModel.GetById 1ms app.codeStats 0ms

/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
  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}