EOS 2  1.1.0
Einfache Objektbasierte Sprache
PrintPanel.java
gehe zur Dokumentation dieser Datei
1 package de.lathanda.eos.common.gui;
2 
3 import java.awt.Color;
4 import java.awt.Dimension;
5 import java.awt.Font;
6 import java.awt.FontMetrics;
7 import java.awt.Graphics;
8 import java.awt.geom.Rectangle2D;
9 import java.awt.print.PageFormat;
10 import java.awt.print.Pageable;
11 import java.awt.print.Paper;
12 import java.awt.print.Printable;
13 import java.awt.print.PrinterException;
14 import java.awt.print.PrinterJob;
15 import java.util.ArrayList;
16 import java.util.LinkedList;
17 import javax.swing.JOptionPane;
18 
19 import de.lathanda.eos.baseparser.AbstractProgram;
20 import de.lathanda.eos.baseparser.Format;
21 import de.lathanda.eos.baseparser.InfoToken;
22 
29 public class PrintPanel extends javax.swing.JPanel implements Printable, Pageable {
30 
34  private static final long serialVersionUID = -6226144081255555607L;
35  private PageFormat pageFormat;
36  private int pageIndex = 0;
37  private boolean linenumbers = false;
38  private AbstractProgram program;
39  // ******** layout *******
40  private final ArrayList<LinkedList<PrintPart>> pages = new ArrayList<>();
41  // ******** fonts ********
42  private final Font fontLiteral = new Font("monospaced", Font.PLAIN, 12);
43  private final Font fontComment = fontLiteral.deriveFont(Font.ITALIC);
44  private final Font fontKeyword = fontLiteral.deriveFont(Font.BOLD);
45  private final Font fontLinenumber = fontLiteral;
46  private final Font fontHeader = new Font("sans", Font.PLAIN, 10);
47  private final Font fontFooter = new Font("sans", Font.PLAIN, 8);
48  private final static String TAB = " ";
49  private static final double PAPER_BORDER_X = 56.69; // 2cm in 1/72 inches
50  private static final double PAPER_BORDER_Y = 28.34; // 1cm in 1/72 inches
51  private String header = "";
52 
56  public PrintPanel() {
57  try {
58  if (PrinterJob.lookupPrintServices().length > 0) {
59  PrinterJob job = PrinterJob.getPrinterJob();
60  pageFormat = job.defaultPage();
61  } else {
62  pageFormat = new PageFormat();
63  }
64  } catch (Throwable t) {
65  JOptionPane.showMessageDialog(this, Messages.getString("Print.Error.Title"), t.getLocalizedMessage(),
66  JOptionPane.ERROR_MESSAGE);
67  pageFormat = new PageFormat();
68  }
69 
70  Paper paper = pageFormat.getPaper();
71  paper.setImageableArea(PAPER_BORDER_X, PAPER_BORDER_Y, paper.getWidth() - 2 * PAPER_BORDER_X,
72  paper.getHeight() - 2 * PAPER_BORDER_Y);
73  pageFormat.setPaper(paper);
74 
75  setBackground(Color.WHITE);
76  setPreferredSize(new Dimension(400, 300));
77  }
78 
79  @Override
80  protected void paintComponent(Graphics g) {
81  super.paintComponent(g);
82  try {
83  print(g, pageFormat, pageIndex);
84  } catch (PrinterException ex) {
85  JOptionPane.showMessageDialog(this, Messages.getString("Print.Error.Title"), ex.getLocalizedMessage(),
86  JOptionPane.ERROR_MESSAGE);
87  }
88  }
89 
90  @Override
91  public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
92  this.pageFormat = pageFormat;
93  if (pageIndex < 0 || pageIndex >= pages.size()) {
94  return NO_SUCH_PAGE;
95  }
96 
97  pages.get(pageIndex).stream().forEachOrdered(t -> t.print(graphics));
98 
99  return PAGE_EXISTS;
100  }
101 
102  void previousPage() {
103  pageIndex = (pageIndex - 1 + pages.size()) % pages.size();
104  repaint();
105  }
106 
107  void nextPage() {
108  pageIndex = (pageIndex + 1) % pages.size();
109  repaint();
110  }
111 
112  public void setLinenumberVisible(boolean visible) {
113  linenumbers = visible;
114  repaint();
115  }
116 
117  public void setHeader(String header) {
118  this.header = header;
119  parse(getGraphics());
120  }
121 
122  void init(AbstractProgram abstractProgram, String header) {
123  this.program = abstractProgram;
124  this.header = header;
125  parse(getGraphics());
126  }
127 
128  private void parse(Graphics g) {
129  LinkedList<PrintPart> page = new LinkedList<>();
130  pages.clear();
131  pages.add(page);
132 
133  int sourceIndex = 0; // sourcecode index
134  int tokenIndexBegin; // token index
135  int tokenIndexEnd; // token index
136  double lineheight = g.getFontMetrics(fontLiteral).getHeight() * 1.0;
137  double lineNrOffset = g.getFontMetrics(fontLinenumber).stringWidth("XX: ");
138  double headerHeight = lineheight;
139  double footerHeight = lineheight;
140 
141  double x = 0; // x within actual page
142  double y = g.getFontMetrics(fontLiteral).getHeight(); // y within actual
143  // page
144 
145  double linewidth = pageFormat.getImageableWidth() - lineNrOffset;
146  double pageheight = pageFormat.getImageableHeight() - headerHeight - footerHeight;
147  double offsetX = pageFormat.getImageableX() + lineNrOffset;
148  double offsetY = pageFormat.getImageableY() + headerHeight;
149 
150  if (program == null) {
151  return;
152  }
153 
154  String source = program.getSource();
155  int linenumber = 0;
156 
157  for (InfoToken st : program.getTokenList()) {
158  if (st.getFormat() == Format.IGNORE)
159  continue;
160  String token = source.substring(sourceIndex, st.getBegin() + st.getLength());
161  tokenIndexBegin = 0;
162 
163  boolean realline = true;
164  while (tokenIndexBegin < token.length()) {
165  Text text = null;
166  String part;
167  boolean newline;
168  Rectangle2D r = null;
169  tokenIndexEnd = token.indexOf('\n', tokenIndexBegin);
170  if (tokenIndexEnd != -1) {
171  newline = true;
172  if (realline) {
173  linenumber++;
174  Text linenr = new Text(linenumber + ": ", fontLinenumber, Color.BLACK, true);
175  Rectangle2D bounds = linenr.getMetrics(g);
176  linenr.move(offsetX - bounds.getWidth(), offsetY + y);
177  page.add(linenr);
178  }
179  } else {
180  tokenIndexEnd = token.length();
181  newline = false;
182  }
183  int skip = 1;
184  boolean fitting = false;
185  do {
186  if (r != null) {
187  tokenIndexEnd--;
188  skip = 0;
189  }
190  part = token.substring(tokenIndexBegin, tokenIndexEnd);
191  switch (st.getFormat()) {
192  case COMMENT:
193  text = new Text(part, fontComment, new Color(0, 160, 0), false);
194  break;
195  case LITERAL:
196  text = new Text(part, fontLiteral, Color.BLACK, false);
197  break;
198  case KEYWORD:
199  text = new Text(part, fontKeyword, Color.BLACK, false);
200  break;
201  default:
202  text = new Text(part, fontLiteral, Color.BLACK, false);
203  }
204  r = text.getMetrics(g);
205  if (fitting || r.getWidth() >= linewidth) {
206  if (x + r.getWidth() > linewidth) {
207  fitting = true;
208  } else {
209  fitting = false;
210  }
211  skip = 0;
212  realline = false;
213  } else {
214  skip = 1;
215  realline = true;
216  }
217  } while (fitting);
218  tokenIndexBegin = tokenIndexEnd + skip;
219  if (x + r.getWidth() > linewidth) {
220  x = 0;
221  y += lineheight;
222  if (y > pageheight) {
223  y = g.getFontMetrics(fontLiteral).getHeight();
224  page = new LinkedList<>();
225  pages.add(page);
226  }
227  }
228  text.move(offsetX + x, offsetY + y);
229  x += r.getWidth();
230  page.add(text);
231 
232  if (newline) {
233  x = 0;
234  y += lineheight;
235  if (y > pageheight) {
236  y = g.getFontMetrics(fontLiteral).getHeight();
237  page = new LinkedList<>();
238  pages.add(page);
239  }
240  }
241  }
242  sourceIndex = st.getBegin() + st.getLength();
243  }
244  // add linenumber for last line
245  linenumber++;
246  Text linenr = new Text(linenumber + ": ", fontLinenumber, Color.BLACK, true);
247  Rectangle2D bounds = linenr.getMetrics(g);
248  linenr.move(offsetX - bounds.getWidth(), offsetY + y);
249  page.add(linenr);
250 
251  // add headers
252  Text headerText = new Text(header, fontHeader, Color.BLACK, false);
253  headerText.move(offsetX + (linewidth - headerText.getMetrics(g).getWidth()) / 2, offsetY - 1);
254  Line headerLine = new Line(Color.BLACK, offsetX, offsetY, offsetX + linewidth, offsetY);
255  Line footerLine = new Line(Color.BLACK, offsetX, offsetY + pageheight, offsetX + linewidth,
256  offsetY + pageheight);
257  int pageNr = 1;
258  for (LinkedList<PrintPart> p : pages) {
259  Text footerText = new Text(pageNr + "/" + pages.size(), fontFooter, Color.BLACK, false);
260  footerText.move(offsetX + (linewidth - footerText.getMetrics(g).getWidth()) / 2,
261  offsetY + pageheight + footerHeight);
262  pageNr++;
263  p.add(headerLine);
264  p.add(footerLine);
265  p.add(footerText);
266  p.add(headerText);
267  }
268  }
269 
270  @Override
271  public Dimension getPreferredSize() {
272  return new Dimension((int) pageFormat.getWidth(), (int) pageFormat.getHeight());
273  }
274 
275  @Override
276  public int getNumberOfPages() {
277  return pages.size();
278  }
279 
280  @Override
281  public PageFormat getPageFormat(int pageIndex) throws IndexOutOfBoundsException {
282  return pageFormat;
283  }
284 
285  @Override
286  public Printable getPrintable(int pageIndex) throws IndexOutOfBoundsException {
287  return this;
288  }
289 
290  private static interface PrintPart {
291  public void print(Graphics g);
292  }
293 
294  private class Text implements PrintPart {
295 
296  private final String text;
297  private final Font font;
298  private final Color color;
299  private int x;
300  private int y;
301  private boolean linenumber;
302 
303  public Text(String text, Font font, Color color, boolean linenumber) {
304  this.text = text.replace("\t", TAB);
305  this.font = font;
306  this.color = color;
307  this.linenumber = linenumber;
308  }
309 
310  public void move(double x, double y) {
311  this.x = (int) x;
312  this.y = (int) y;
313  }
314 
315  public void print(Graphics g) {
316  if (!linenumber || linenumbers) {
317  g.setColor(color);
318  g.setFont(font);
319  g.drawString(text, x, y);
320  }
321  }
322 
323  public Rectangle2D getMetrics(Graphics g) {
324  FontMetrics fm = g.getFontMetrics(font);
325  return fm.getStringBounds(text, g);
326  }
327  }
328 
329  private static class Line implements PrintPart {
330  private final Color color;
331  private int x1;
332  private int y1;
333  private int x2;
334  private int y2;
335 
336  public Line(Color color, double x1, double y1, double x2, double y2) {
337  this.color = color;
338  this.x1 = (int) x1;
339  this.y1 = (int) y1;
340  this.x2 = (int) x2;
341  this.y2 = (int) y2;
342  }
343 
344  public void print(Graphics g) {
345  g.setColor(color);
346  g.drawLine(x1, y1, x2, y2);
347  }
348  }
349 }
static String getString(String id)
Definition: Messages.java:29
Printable getPrintable(int pageIndex)
void setLinenumberVisible(boolean visible)
int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
Definition: PrintPanel.java:91
PageFormat getPageFormat(int pageIndex)
LinkedList< InfoToken > getTokenList()
Impressum