PageRenderTime 50ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

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

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