PageRenderTime 38ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-2-pre14/org/gjt/sp/jedit/print/BufferPrintable.java

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