PageRenderTime 85ms CodeModel.GetById 20ms app.highlight 39ms RepoModel.GetById 21ms app.codeStats 0ms

/jEdit/tags/jedit-4-1-pre5/org/gjt/sp/jedit/print/BufferPrintable.java

#
Java | 370 lines | 264 code | 53 blank | 53 comment | 29 complexity | a4d235bd7fdcc85ed1588f0d9d252dbc 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, 2002 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 extends WorkRequest 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		softWrap = new SoftWrapTokenHandler();
 64	} //}}}
 65
 66	//{{{ run() method
 67	public void run()
 68	{
 69		try
 70		{
 71			// can't use a read lock here since Buffer.markTokens()
 72			// grabs a write lock
 73			//buffer.readLock();
 74
 75			if(format == null)
 76				job.print();
 77			else
 78			{
 79				Method method = PrinterJob.class.getMethod(
 80					"print",new Class[] { Class.forName(
 81					"javax.print.attribute.PrintRequestAttributeSet") });
 82				method.invoke(job,new Object[] { format });
 83			}
 84		}
 85		catch(PrinterAbortException ae)
 86		{
 87			Log.log(Log.DEBUG,this,ae);
 88		}
 89		catch(Exception e)
 90		{
 91			Log.log(Log.ERROR,this,e);
 92			final String[] args = { e.toString() };
 93			SwingUtilities.invokeLater(new Runnable()
 94			{
 95				public void run()
 96				{
 97					GUIUtilities.error(view,"print-error",args);
 98				}
 99			});
100		}
101		finally
102		{
103			//buffer.readUnlock();
104		}
105	} //}}}
106
107	//{{{ print() method
108	public int print(Graphics _gfx, PageFormat pageFormat, int pageIndex)
109		throws PrinterException
110	{
111		if(pageIndex > currentPage + 1)
112		{
113			for(int i = currentPage; i < pageIndex; i++)
114			{
115				printPage(_gfx,pageFormat,i,true);
116			}
117
118			currentPage = pageIndex - 1;
119		}
120
121		if(pageIndex == currentPage + 1)
122		{
123			if(end)
124			{
125				view.getStatus().setMessage(null);
126				return NO_SUCH_PAGE;
127			}
128
129			currentPageStart = currentPhysicalLine;
130			currentPage = pageIndex;
131		}
132		else if(pageIndex == currentPage)
133		{
134			currentPhysicalLine = currentPageStart;
135
136			// show the message in both the view's status bar, and the
137			// I/O progress monitor
138			Object[] args = new Object[] { new Integer(pageIndex + 1) };
139			String message = jEdit.getProperty("view.status.print",args);
140			view.getStatus().setMessage(message);
141			setStatus(message);
142		}
143
144		printPage(_gfx,pageFormat,pageIndex,true);
145
146		return PAGE_EXISTS;
147	} //}}}
148
149	//{{{ Private members
150
151	//{{{ Static variables
152	private static Color headerColor = Color.lightGray;
153	private static Color headerTextColor = Color.black;
154	private static Color footerColor = Color.lightGray;
155	private static Color footerTextColor = Color.black;
156	private static Color lineNumberColor = Color.gray;
157	private static Color textColor = Color.black;
158	//}}}
159
160	//{{{ Instance variables
161	private PrinterJob job;
162	private Object format;
163
164	private View view;
165	private Buffer buffer;
166	private Font font;
167	private SyntaxStyle[] styles;
168	private boolean header;
169	private boolean footer;
170	private boolean lineNumbers;
171
172	private int currentPage;
173	private int currentPageStart;
174	private int currentPhysicalLine;
175	private boolean end;
176
177	private LineMetrics lm;
178	private ArrayList lineList;
179
180	private SoftWrapTokenHandler softWrap;
181	//}}}
182
183	//{{{ printPage() method
184	private void printPage(Graphics _gfx, PageFormat pageFormat, int pageIndex,
185		boolean actuallyPaint)
186	{
187		Graphics2D gfx = (Graphics2D)_gfx;
188		gfx.setFont(font);
189
190		double pageX = pageFormat.getImageableX();
191		double pageY = pageFormat.getImageableY();
192		double pageWidth = pageFormat.getImageableWidth();
193		double pageHeight = pageFormat.getImageableHeight();
194
195		if(header)
196		{
197			double headerHeight = paintHeader(gfx,pageX,pageY,pageWidth,
198				actuallyPaint);
199			pageY += headerHeight * 2;
200			pageHeight -= headerHeight * 2;
201		}
202
203		if(footer)
204		{
205			double footerHeight = paintFooter(gfx,pageX,pageY,pageWidth,
206				pageHeight,pageIndex,actuallyPaint);
207			pageHeight -= footerHeight * 2;
208		}
209
210		FontRenderContext frc = gfx.getFontRenderContext();
211
212		double lineNumberWidth;
213
214		//{{{ determine line number width
215		if(lineNumbers)
216		{
217			// the +1's ensure that 99 gets 3 digits, 103 gets 4 digits,
218			// and so on.
219			int lineNumberDigits = (int)Math.ceil(Math.log(buffer.getLineCount() + 1)
220				/ Math.log(10)) + 1;
221
222			// now that we know how many chars there are, get the width.
223			char[] chars = new char[lineNumberDigits];
224			for(int i = 0; i < chars.length; i++)
225				chars[i] = ' ';
226			lineNumberWidth = font.getStringBounds(chars,
227				0,lineNumberDigits,frc).getWidth();
228		}
229		else
230			lineNumberWidth = 0.0;
231		//}}}
232
233		//{{{ calculate tab size
234		int tabSize = jEdit.getIntegerProperty("print.tabSize",8);
235		char[] chars = new char[tabSize];
236		for(int i = 0; i < chars.length; i++)
237			chars[i] = ' ';
238		double tabWidth = font.getStringBounds(chars,
239			0,tabSize,frc).getWidth();
240		PrintTabExpander e = new PrintTabExpander(tabWidth);
241		//}}}
242
243		Segment seg = new Segment();
244		double y = 0.0;
245
246		lm = font.getLineMetrics("gGyYX",frc);
247
248print_loop:	for(;;)
249		{
250			if(currentPhysicalLine == buffer.getLineCount())
251			{
252				end = true;
253				break print_loop;
254			}
255
256			lineList.clear();
257
258			buffer.getLineText(currentPhysicalLine,seg);
259			softWrap.init(seg,styles,frc,e,lineList,
260				(float)(pageWidth - lineNumberWidth));
261
262			buffer.markTokens(currentPhysicalLine,softWrap);
263			if(lineList.size() == 0)
264				lineList.add(null);
265
266			if(y + (lm.getHeight() * lineList.size()) >= pageHeight)
267				break print_loop;
268
269			if(lineNumbers && actuallyPaint)
270			{
271				gfx.setFont(font);
272				gfx.setColor(lineNumberColor);
273				gfx.drawString(String.valueOf(currentPhysicalLine + 1),
274					(float)pageX,(float)(pageY + y));
275			}
276
277			for(int i = 0; i < lineList.size(); i++)
278			{
279				Chunk chunks = (Chunk)lineList.get(i);
280				if(chunks != null && actuallyPaint)
281				{
282					Chunk.paintChunkList(seg,chunks,gfx,
283						(float)(pageX + lineNumberWidth),
284						(float)(pageY + y),
285						Color.white,false);
286				}
287				y += lm.getHeight();
288			}
289
290			currentPhysicalLine++;
291		}
292	} //}}}
293
294	//{{{ paintHeader() method
295	private double paintHeader(Graphics2D gfx, double pageX, double pageY,
296		double pageWidth, boolean actuallyPaint)
297	{
298		String headerText = jEdit.getProperty("print.headerText",
299			new String[] { buffer.getPath() });
300		FontRenderContext frc = gfx.getFontRenderContext();
301		lm = font.getLineMetrics(headerText,frc);
302
303		Rectangle2D bounds = font.getStringBounds(headerText,frc);
304		Rectangle2D headerBounds = new Rectangle2D.Double(
305			pageX,pageY,pageWidth,bounds.getHeight());
306
307		if(actuallyPaint)
308		{
309			gfx.setColor(headerColor);
310			gfx.fill(headerBounds);
311			gfx.setColor(headerTextColor);
312			gfx.drawString(headerText,
313				(float)(pageX + (pageWidth - bounds.getWidth()) / 2),
314				(float)(pageY + lm.getAscent()));
315		}
316
317		return headerBounds.getHeight();
318	}
319	//}}}
320
321	//{{{ paintFooter() method
322	private double paintFooter(Graphics2D gfx, double pageX, double pageY,
323		double pageWidth, double pageHeight, int pageIndex,
324		boolean actuallyPaint)
325	{
326		String footerText = jEdit.getProperty("print.footerText",
327			new Object[] { new Date(), new Integer(pageIndex + 1) });
328		FontRenderContext frc = gfx.getFontRenderContext();
329		lm = font.getLineMetrics(footerText,frc);
330
331		Rectangle2D bounds = font.getStringBounds(footerText,frc);
332		Rectangle2D footerBounds = new Rectangle2D.Double(
333			pageX,pageY + pageHeight - bounds.getHeight(),
334			pageWidth,bounds.getHeight());
335
336		if(actuallyPaint)
337		{
338			gfx.setColor(footerColor);
339			gfx.fill(footerBounds);
340			gfx.setColor(footerTextColor);
341			gfx.drawString(footerText,
342				(float)(pageX + (pageWidth - bounds.getWidth()) / 2),
343				(float)(pageY + pageHeight - bounds.getHeight()
344				+ lm.getAscent()));
345		}
346
347		return footerBounds.getHeight();
348	} //}}}
349
350	//}}}
351
352	//{{{ PrintTabExpander class
353	static class PrintTabExpander implements TabExpander
354	{
355		private double tabWidth;
356
357		//{{{ PrintTabExpander constructor
358		public PrintTabExpander(double tabWidth)
359		{
360			this.tabWidth = tabWidth;
361		} //}}}
362
363		//{{{ nextTabStop() method
364		public float nextTabStop(float x, int tabOffset)
365		{
366			int ntabs = (int)((x + 1) / tabWidth);
367			return (float)((ntabs + 1) * tabWidth);
368		} //}}}
369	} //}}}
370}