1
2
3
4
5
6
7
8
9
10
11 package de.jaret.util.ui.table;
12
13 import org.eclipse.swt.SWT;
14 import org.eclipse.swt.graphics.Font;
15 import org.eclipse.swt.graphics.FontData;
16 import org.eclipse.swt.graphics.GC;
17 import org.eclipse.swt.graphics.Point;
18 import org.eclipse.swt.graphics.Rectangle;
19 import org.eclipse.swt.printing.Printer;
20
21 import de.jaret.util.ui.table.model.IColumn;
22 import de.jaret.util.ui.table.model.IRow;
23 import de.jaret.util.ui.table.print.JaretTablePrintConfiguration;
24 import de.jaret.util.ui.table.renderer.ICellRenderer;
25 import de.jaret.util.ui.table.renderer.ICellStyle;
26 import de.jaret.util.ui.table.renderer.ITableHeaderRenderer;
27
28 /***
29 * <p>
30 * Print utility for the jaret table. The table printer depends on implemented print functionality in the configured
31 * renderers. It "connects" directly to the jaret table thus no headless printing is possible.
32 * </p>
33 * <p>
34 * The Table printer should be disposed after using!
35 * </p>
36 * TODO this is a first hack.
37 *
38 * @author Peter Kliem
39 * @version $Id: JaretTablePrinter.java 179 2007-01-07 17:37:50Z olk $
40 */
41 public class JaretTablePrinter {
42 /*** borders in cm. */
43 protected double _borderTop = 1;
44
45 protected double _borderBottom = 1;
46
47 protected double _borderLeft = 1;
48
49 protected double _borderRight = 1;
50
51 protected Rectangle _printingRect;
52
53 protected Printer _printer;
54
55 protected double _scaleX;
56
57 protected double _scaleY;
58
59 protected ITableHeaderRenderer _headerRenderer;
60
61 protected JaretTable _table;
62
63 protected int _pageHeight;
64
65 protected int _pageWidth;
66
67 protected int _footerHeight;
68
69 protected double _scale = 1.0;
70
71 public JaretTablePrinter(Printer printer, JaretTable table) {
72 _table = table;
73 setPrinter(printer);
74 }
75
76 public void setPrinter(Printer printer) {
77 if (_printer != null) {
78 _printer.dispose();
79 }
80 _printer = printer;
81 if (printer != null) {
82 Point dpi = _printer.getDPI();
83 _scaleX = (double) dpi.x / 96.0;
84 _scaleY = (double) dpi.y / 96.0;
85 }
86
87 }
88
89 public int scaleX(int in) {
90 return (int) Math.round(_scaleX * (double) in * _scale);
91 }
92
93 public double getScaleX() {
94 return _scaleX;
95 }
96
97 public int scaleY(int in) {
98 return (int) Math.round(_scaleY * (double) in * _scale);
99 }
100
101 public Printer getPrinter() {
102 return _printer;
103 }
104
105 protected int pixelForCmX(double cm) {
106 Point dpi = _printer.getDPI();
107 double inch = cm / 2.54;
108 return (int) (dpi.x * inch);
109 }
110
111 protected int pixelForCmY(double cm) {
112 Point dpi = _printer.getDPI();
113 double inch = cm / 2.54;
114 return (int) (dpi.y * inch);
115 }
116
117 /***
118 * Calculate the number of pages generated when printing.
119 *
120 * @param configuration
121 * @return
122 */
123 public Point calculatePageCount(JaretTablePrintConfiguration configuration) {
124 _scale = configuration.getScale();
125 _pageHeight = _printer.getClientArea().height - pixelForCmY(_borderTop + _borderBottom);
126 _pageWidth = _printer.getClientArea().width - pixelForCmX(_borderLeft + _borderRight);
127
128 int tHeight;
129 if (configuration.getRowLimit() == -1) {
130 tHeight = _table.getTotalHeight();
131 } else {
132 tHeight = _table.getTotalHeight(configuration.getRowLimit());
133 }
134 int tWidth;
135 if (configuration.getColLimit() == -1) {
136 tWidth = _table.getTotalWidth();
137 } else {
138 tWidth = _table.getTotalWidth(configuration.getColLimit());
139 }
140
141 int pagesx = (scaleX(tWidth) / _pageWidth) + 1;
142 int pagesy = (scaleY(tHeight) / (_pageHeight - _footerHeight)) + 1;
143
144 int headerheight = _table.getDrawHeader() ? _table.getHeaderHeight() : 0;
145 headerheight = configuration.getRepeatHeader() ? headerheight + headerheight * (pagesy - 1) : headerheight;
146
147
148 pagesy = (scaleY(tHeight + headerheight) / (_pageHeight - _footerHeight)) + 1;
149
150 return new Point(pagesx, pagesy);
151
152 }
153
154 public void print(JaretTablePrintConfiguration configuration) {
155 _printingRect = new Rectangle(pixelForCmX(_borderLeft), pixelForCmY(_borderTop), _pageWidth, _pageHeight);
156
157 _headerRenderer = _table.getHeaderRenderer().getPrintRenderer(_printer);
158 Point pages = calculatePageCount(configuration);
159 int pagesx = pages.x;
160 int pagesy = pages.y;
161
162 _printer.startJob(configuration.getName() != null ? configuration.getName() : "jarettable");
163
164 GC gc = new GC(_printer);
165 Font oldfont = gc.getFont();
166 FontData fontdata = new FontData("Arial", (int) (8.0 * _scale), SWT.NULL);
167 Font printerFont = new Font(_printer, fontdata);
168 gc.setFont(printerFont);
169
170 for (int px = 0; px < pagesx; px++) {
171 int startx = (int) ((px * _pageWidth) / (_scaleX * _scale));
172 IColumn column = _table.getColumnForAbsX(startx);
173 int offx = startx - _table.getAbsBeginXForColumn(column);
174 int beginColIdx = _table.getColIdxForAbsX(startx);
175
176 int rIdx = 0;
177 for (int py = 0; py < pagesy; py++) {
178 int y = 0;
179 String footerText = configuration.getFooterText() != null ? configuration.getFooterText() : "";
180 footerText += "(" + (px + 1) + "/" + pagesx + "," + (py + 1) + "/" + pagesy + ")";
181 _printer.startPage();
182
183 int starty = (int) (py * ((_pageHeight - _footerHeight - (configuration.getRepeatHeader() ? scaleY(_table
184 .getHeaderHeight())
185 : 0)) / (_scaleY * _scale)));
186 rIdx = py == 0 ? 0 : rIdx;
187 Rectangle clipSave = gc.getClipping();
188
189 if (starty == 0 || configuration.getRepeatHeader()) {
190
191
192 int x = -offx;
193 int cIdx = beginColIdx;
194 while (scaleX(x) < _pageWidth && cIdx < _table.getColumnCount()
195 && (configuration.getColLimit() == -1 || cIdx <= configuration.getColLimit())) {
196 IColumn col = _table.getColumn(cIdx);
197 int colwidth = _table.getTableViewState().getColumnWidth(col);
198 int xx = x > 0 ? x : 0;
199 int clipWidth = x > 0 ? colwidth : colwidth - offx;
200 if (!_headerRenderer.disableClipping()) {
201 gc.setClipping(scaleX(xx) + pixelForCmX(_borderLeft), pixelForCmY(_borderTop),
202 scaleX(clipWidth), scaleY(_table.getHeaderHeight()));
203 gc.setClipping(gc.getClipping().intersection(_printingRect));
204 }
205
206 drawHeader(gc, scaleX(x) + pixelForCmX(_borderLeft), scaleX(colwidth), col);
207
208 x += colwidth;
209 cIdx++;
210 }
211 y += _table.getHeaderHeight();
212 gc.setClipping(clipSave);
213 }
214
215
216
217 gc.setClipping(_printingRect);
218
219 while (scaleY(y) < _pageHeight && rIdx < _table.getRowCount()
220 && (configuration.getRowLimit() == -1 || rIdx <= configuration.getRowLimit())) {
221 IRow row = _table.getRow(rIdx);
222 int rHeight = _table.getTableViewState().getRowHeight(row);
223
224 if (scaleY(y) + scaleY(rHeight) > _pageHeight) {
225 break;
226 }
227 int x = -offx;
228 int cIdx = beginColIdx;
229 while (scaleX(x) < _pageWidth && cIdx < _table.getColumnCount()
230 && (configuration.getColLimit() == -1 || cIdx <= configuration.getColLimit())) {
231 IColumn col = _table.getColumn(cIdx);
232 int colwidth = _table.getTableViewState().getColumnWidth(col);
233 Rectangle area = new Rectangle(scaleX(x) + pixelForCmX(_borderLeft), scaleY(y)
234 + pixelForCmY(_borderTop), scaleX(colwidth), scaleY(rHeight));
235 drawCell(gc, area, row, col);
236 x += colwidth;
237 cIdx++;
238 }
239 y += rHeight;
240 rIdx++;
241 }
242
243 gc.setClipping(clipSave);
244 drawFooter(gc, footerText);
245 _printer.endPage();
246 }
247 }
248 _printer.endJob();
249 printerFont.dispose();
250 gc.setFont(oldfont);
251 gc.dispose();
252 }
253
254 /***
255 * TODO creation and disposal of the cell renderers for printing is ... well should be changed!
256 *
257 * @param gc
258 * @param area
259 * @param row
260 * @param col
261 */
262 private void drawCell(GC gc, Rectangle area, IRow row, IColumn col) {
263 ICellStyle bc = _table.getTableViewState().getCellStyle(row, col);
264 ICellRenderer cellRenderer = _table.getCellRenderer(row, col).createPrintRenderer(_printer);
265 if (cellRenderer != null) {
266 cellRenderer.draw(gc, _table, bc, area, row, col, false, false, true);
267 }
268 cellRenderer.dispose();
269 }
270
271 private void drawFooter(GC gc, String footer) {
272 Point extent = gc.textExtent(footer);
273 int y = _printer.getClientArea().height - _footerHeight - pixelForCmY(_borderBottom);
274
275
276 gc.drawString(footer, pixelForCmX(_borderLeft), y);
277
278 }
279
280 private void drawHeader(GC gc, int x, int colwidth, IColumn col) {
281 Rectangle area = new Rectangle(x, pixelForCmY(_borderTop), colwidth, scaleY(_table.getHeaderHeight()));
282 int sortingPos = _table.getTableViewState().getColumnSortingPosition(col);
283 boolean sortingDir = _table.getTableViewState().getColumnSortingDirection(col);
284 _headerRenderer.draw(gc, area, col, sortingPos, sortingDir, true);
285 }
286
287 public void dispose() {
288 if (_headerRenderer != null) {
289 _headerRenderer.dispose();
290 }
291 }
292 }