PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 1ms 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
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, 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. package org.gjt.sp.jedit.print;
  24. //{{{ Imports
  25. import javax.swing.text.Segment;
  26. import javax.swing.text.TabExpander;
  27. import javax.swing.SwingUtilities;
  28. import java.awt.font.*;
  29. import java.awt.geom.*;
  30. import java.awt.print.*;
  31. import java.awt.*;
  32. import java.lang.reflect.Method;
  33. import java.util.*;
  34. import org.gjt.sp.jedit.syntax.*;
  35. import org.gjt.sp.jedit.*;
  36. import org.gjt.sp.util.*;
  37. //}}}
  38. class BufferPrintable extends WorkRequest implements Printable
  39. {
  40. //{{{ BufferPrintable constructor
  41. BufferPrintable(PrinterJob job, Object format,
  42. View view, Buffer buffer, Font font, boolean header,
  43. boolean footer, boolean lineNumbers, boolean color)
  44. {
  45. this.job = job;
  46. this.format = format;
  47. this.view = view;
  48. this.buffer = buffer;
  49. this.font = font;
  50. this.header = header;
  51. this.footer = footer;
  52. this.lineNumbers = lineNumbers;
  53. styles = GUIUtilities.loadStyles(jEdit.getProperty("print.font"),
  54. jEdit.getIntegerProperty("print.fontsize",10),color);
  55. styles[Token.NULL] = new SyntaxStyle(textColor,null,font);
  56. lineList = new ArrayList();
  57. softWrap = new SoftWrapTokenHandler();
  58. } //}}}
  59. //{{{ run() method
  60. public void run()
  61. {
  62. try
  63. {
  64. // can't use a read lock here since Buffer.markTokens()
  65. // grabs a write lock
  66. //buffer.readLock();
  67. if(format == null)
  68. job.print();
  69. else
  70. {
  71. Method method = PrinterJob.class.getMethod(
  72. "print",new Class[] { Class.forName(
  73. "javax.print.attribute.PrintRequestAttributeSet") });
  74. method.invoke(job,new Object[] { format });
  75. }
  76. }
  77. catch(PrinterAbortException ae)
  78. {
  79. Log.log(Log.DEBUG,this,ae);
  80. }
  81. catch(Exception e)
  82. {
  83. Log.log(Log.ERROR,this,e);
  84. final String[] args = { e.toString() };
  85. SwingUtilities.invokeLater(new Runnable()
  86. {
  87. public void run()
  88. {
  89. GUIUtilities.error(view,"print-error",args);
  90. }
  91. });
  92. }
  93. finally
  94. {
  95. //buffer.readUnlock();
  96. }
  97. } //}}}
  98. //{{{ print() method
  99. public int print(Graphics _gfx, PageFormat pageFormat, int pageIndex)
  100. throws PrinterException
  101. {
  102. if(pageIndex > currentPage + 1)
  103. {
  104. for(int i = currentPage; i < pageIndex; i++)
  105. {
  106. printPage(_gfx,pageFormat,i,true);
  107. }
  108. currentPage = pageIndex - 1;
  109. }
  110. if(pageIndex == currentPage + 1)
  111. {
  112. if(end)
  113. {
  114. view.getStatus().setMessage(null);
  115. return NO_SUCH_PAGE;
  116. }
  117. currentPageStart = currentPhysicalLine;
  118. currentPage = pageIndex;
  119. }
  120. else if(pageIndex == currentPage)
  121. {
  122. currentPhysicalLine = currentPageStart;
  123. // show the message in both the view's status bar, and the
  124. // I/O progress monitor
  125. Object[] args = new Object[] { new Integer(pageIndex + 1) };
  126. String message = jEdit.getProperty("view.status.print",args);
  127. view.getStatus().setMessage(message);
  128. setStatus(message);
  129. }
  130. printPage(_gfx,pageFormat,pageIndex,true);
  131. return PAGE_EXISTS;
  132. } //}}}
  133. //{{{ Private members
  134. //{{{ Static variables
  135. private static Color headerColor = Color.lightGray;
  136. private static Color headerTextColor = Color.black;
  137. private static Color footerColor = Color.lightGray;
  138. private static Color footerTextColor = Color.black;
  139. private static Color lineNumberColor = Color.gray;
  140. private static Color textColor = Color.black;
  141. //}}}
  142. //{{{ Instance variables
  143. private PrinterJob job;
  144. private Object format;
  145. private View view;
  146. private Buffer buffer;
  147. private Font font;
  148. private SyntaxStyle[] styles;
  149. private boolean header;
  150. private boolean footer;
  151. private boolean lineNumbers;
  152. private int currentPage;
  153. private int currentPageStart;
  154. private int currentPhysicalLine;
  155. private boolean end;
  156. private LineMetrics lm;
  157. private ArrayList lineList;
  158. private SoftWrapTokenHandler softWrap;
  159. //}}}
  160. //{{{ printPage() method
  161. private void printPage(Graphics _gfx, PageFormat pageFormat, int pageIndex,
  162. boolean actuallyPaint)
  163. {
  164. Graphics2D gfx = (Graphics2D)_gfx;
  165. gfx.setFont(font);
  166. double pageX = pageFormat.getImageableX();
  167. double pageY = pageFormat.getImageableY();
  168. double pageWidth = pageFormat.getImageableWidth();
  169. double pageHeight = pageFormat.getImageableHeight();
  170. if(header)
  171. {
  172. double headerHeight = paintHeader(gfx,pageX,pageY,pageWidth,
  173. actuallyPaint);
  174. pageY += headerHeight * 2;
  175. pageHeight -= headerHeight * 2;
  176. }
  177. if(footer)
  178. {
  179. double footerHeight = paintFooter(gfx,pageX,pageY,pageWidth,
  180. pageHeight,pageIndex,actuallyPaint);
  181. pageHeight -= footerHeight * 2;
  182. }
  183. FontRenderContext frc = gfx.getFontRenderContext();
  184. double lineNumberWidth;
  185. //{{{ determine line number width
  186. if(lineNumbers)
  187. {
  188. // the +1's ensure that 99 gets 3 digits, 103 gets 4 digits,
  189. // and so on.
  190. int lineNumberDigits = (int)Math.ceil(Math.log(buffer.getLineCount() + 1)
  191. / Math.log(10)) + 1;
  192. // now that we know how many chars there are, get the width.
  193. char[] chars = new char[lineNumberDigits];
  194. for(int i = 0; i < chars.length; i++)
  195. chars[i] = ' ';
  196. lineNumberWidth = font.getStringBounds(chars,
  197. 0,lineNumberDigits,frc).getWidth();
  198. }
  199. else
  200. lineNumberWidth = 0.0;
  201. //}}}
  202. //{{{ calculate tab size
  203. int tabSize = jEdit.getIntegerProperty("print.tabSize",8);
  204. char[] chars = new char[tabSize];
  205. for(int i = 0; i < chars.length; i++)
  206. chars[i] = ' ';
  207. double tabWidth = font.getStringBounds(chars,
  208. 0,tabSize,frc).getWidth();
  209. PrintTabExpander e = new PrintTabExpander(tabWidth);
  210. //}}}
  211. Segment seg = new Segment();
  212. double y = 0.0;
  213. lm = font.getLineMetrics("gGyYX",frc);
  214. print_loop: for(;;)
  215. {
  216. if(currentPhysicalLine == buffer.getLineCount())
  217. {
  218. end = true;
  219. break print_loop;
  220. }
  221. lineList.clear();
  222. buffer.getLineText(currentPhysicalLine,seg);
  223. softWrap.init(seg,styles,frc,e,lineList,
  224. (float)(pageWidth - lineNumberWidth));
  225. buffer.markTokens(currentPhysicalLine,softWrap);
  226. if(lineList.size() == 0)
  227. lineList.add(null);
  228. if(y + (lm.getHeight() * lineList.size()) >= pageHeight)
  229. break print_loop;
  230. if(lineNumbers && actuallyPaint)
  231. {
  232. gfx.setFont(font);
  233. gfx.setColor(lineNumberColor);
  234. gfx.drawString(String.valueOf(currentPhysicalLine + 1),
  235. (float)pageX,(float)(pageY + y));
  236. }
  237. for(int i = 0; i < lineList.size(); i++)
  238. {
  239. Chunk chunks = (Chunk)lineList.get(i);
  240. if(chunks != null && actuallyPaint)
  241. {
  242. Chunk.paintChunkList(seg,chunks,gfx,
  243. (float)(pageX + lineNumberWidth),
  244. (float)(pageY + y),
  245. Color.white,false);
  246. }
  247. y += lm.getHeight();
  248. }
  249. currentPhysicalLine++;
  250. }
  251. } //}}}
  252. //{{{ paintHeader() method
  253. private double paintHeader(Graphics2D gfx, double pageX, double pageY,
  254. double pageWidth, boolean actuallyPaint)
  255. {
  256. String headerText = jEdit.getProperty("print.headerText",
  257. new String[] { buffer.getPath() });
  258. FontRenderContext frc = gfx.getFontRenderContext();
  259. lm = font.getLineMetrics(headerText,frc);
  260. Rectangle2D bounds = font.getStringBounds(headerText,frc);
  261. Rectangle2D headerBounds = new Rectangle2D.Double(
  262. pageX,pageY,pageWidth,bounds.getHeight());
  263. if(actuallyPaint)
  264. {
  265. gfx.setColor(headerColor);
  266. gfx.fill(headerBounds);
  267. gfx.setColor(headerTextColor);
  268. gfx.drawString(headerText,
  269. (float)(pageX + (pageWidth - bounds.getWidth()) / 2),
  270. (float)(pageY + lm.getAscent()));
  271. }
  272. return headerBounds.getHeight();
  273. }
  274. //}}}
  275. //{{{ paintFooter() method
  276. private double paintFooter(Graphics2D gfx, double pageX, double pageY,
  277. double pageWidth, double pageHeight, int pageIndex,
  278. boolean actuallyPaint)
  279. {
  280. String footerText = jEdit.getProperty("print.footerText",
  281. new Object[] { new Date(), new Integer(pageIndex + 1) });
  282. FontRenderContext frc = gfx.getFontRenderContext();
  283. lm = font.getLineMetrics(footerText,frc);
  284. Rectangle2D bounds = font.getStringBounds(footerText,frc);
  285. Rectangle2D footerBounds = new Rectangle2D.Double(
  286. pageX,pageY + pageHeight - bounds.getHeight(),
  287. pageWidth,bounds.getHeight());
  288. if(actuallyPaint)
  289. {
  290. gfx.setColor(footerColor);
  291. gfx.fill(footerBounds);
  292. gfx.setColor(footerTextColor);
  293. gfx.drawString(footerText,
  294. (float)(pageX + (pageWidth - bounds.getWidth()) / 2),
  295. (float)(pageY + pageHeight - bounds.getHeight()
  296. + lm.getAscent()));
  297. }
  298. return footerBounds.getHeight();
  299. } //}}}
  300. //}}}
  301. //{{{ PrintTabExpander class
  302. static class PrintTabExpander implements TabExpander
  303. {
  304. private double tabWidth;
  305. //{{{ PrintTabExpander constructor
  306. public PrintTabExpander(double tabWidth)
  307. {
  308. this.tabWidth = tabWidth;
  309. } //}}}
  310. //{{{ nextTabStop() method
  311. public float nextTabStop(float x, int tabOffset)
  312. {
  313. int ntabs = (int)((x + 1) / tabWidth);
  314. return (float)((ntabs + 1) * tabWidth);
  315. } //}}}
  316. } //}}}
  317. }