1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package de.jaret.util.ui.timebars.swt;
21
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26
27 import org.eclipse.swt.SWT;
28 import org.eclipse.swt.graphics.Color;
29 import org.eclipse.swt.graphics.Font;
30 import org.eclipse.swt.graphics.FontData;
31 import org.eclipse.swt.graphics.GC;
32 import org.eclipse.swt.graphics.Point;
33 import org.eclipse.swt.printing.Printer;
34
35 import de.jaret.util.date.Interval;
36 import de.jaret.util.date.JaretDate;
37 import de.jaret.util.ui.timebars.TimeBarViewerDelegate;
38 import de.jaret.util.ui.timebars.TimeBarViewerInterface;
39 import de.jaret.util.ui.timebars.ViewConfiguration;
40 import de.jaret.util.ui.timebars.model.TimeBarRow;
41 import de.jaret.util.ui.timebars.strategy.ITickProvider;
42 import de.jaret.util.ui.timebars.swt.renderer.GlobalAssistantRenderer;
43 import de.jaret.util.ui.timebars.swt.renderer.GridRenderer;
44 import de.jaret.util.ui.timebars.swt.renderer.HeaderRenderer;
45 import de.jaret.util.ui.timebars.swt.renderer.HierarchyRenderer;
46 import de.jaret.util.ui.timebars.swt.renderer.IRelationRenderer;
47 import de.jaret.util.ui.timebars.swt.renderer.TimeBarGapRenderer;
48 import de.jaret.util.ui.timebars.swt.renderer.TimeBarMarkerRenderer;
49 import de.jaret.util.ui.timebars.swt.renderer.TimeBarRenderer;
50 import de.jaret.util.ui.timebars.swt.renderer.TimeScaleRenderer;
51 import de.jaret.util.ui.timebars.swt.renderer.TitleRenderer;
52
53
54
55
56
57
58
59 public class TimeBarPrinter {
60
61 private static final double DEFAULT_MARGIN = 1.0;
62
63
64 private static final double DEFAULT_FOOTER_HEIGHT = 0.5;
65
66
67 private static final double SCREEN_DPI_X = 96.0;
68
69 private static final double SCREEN_DPI_Y = 96.0;
70
71
72 private static final double INCH_IN_CM = 2.54;
73
74
75 private static final String PRINTERFONTNAME = "Sans";
76
77 private static final int PRINTERFONTSIZE = 6;
78
79
80 protected Printer _printer;
81
82 protected double _scaleX;
83
84 protected double _scaleY;
85
86
87 protected TimeScaleRenderer _timeScaleRenderer;
88
89 protected HeaderRenderer _headerRenderer;
90
91 protected TimeBarRenderer _renderer;
92
93 protected HierarchyRenderer _hierarchyRenderer;
94
95 protected GridRenderer _gridRenderer;
96
97 protected TimeBarGapRenderer _gapRenderer;
98
99 protected TimeBarMarkerRenderer _markerRenderer;
100
101 protected TitleRenderer _titleRenderer;
102
103 protected GlobalAssistantRenderer _globalAssistantRenderer;
104
105 protected IRelationRenderer _relationRenderer;
106
107
108 protected Map<Class<? extends Interval>, TimeBarRenderer> _printerRendererMap = new HashMap<Class<? extends Interval>, TimeBarRenderer>();
109
110
111 protected TimeBarViewerDelegate _delegate = new TimeBarViewerDelegate(null);
112
113
114 protected double _footerHeight = DEFAULT_FOOTER_HEIGHT;
115
116
117 protected double _marginTop = DEFAULT_MARGIN;
118
119 protected double _marginBottom = DEFAULT_MARGIN;
120
121 protected double _marginLeft = DEFAULT_MARGIN;
122
123 protected double _marginRight = DEFAULT_MARGIN;
124
125
126
127
128
129
130 public TimeBarPrinter(Printer printer) {
131 _printer = printer;
132 Point dpi = _printer.getDPI();
133 _scaleX = (double) dpi.x / SCREEN_DPI_X;
134 _scaleY = (double) dpi.y / SCREEN_DPI_Y;
135 }
136
137
138
139
140
141
142
143 public int scaleX(int in) {
144 return (int) Math.round(_scaleX * (double) in);
145 }
146
147
148
149
150
151
152 public double getScaleX() {
153 return _scaleX;
154 }
155
156
157
158
159
160
161
162 public int scaleY(int in) {
163 return (int) Math.round(_scaleY * (double) in);
164 }
165
166
167
168
169
170
171 public double getScaleY() {
172 return _scaleY;
173 }
174
175
176
177
178
179
180
181 protected int pixelForCmX(double cm) {
182 Point dpi = _printer.getDPI();
183 double inch = cm / INCH_IN_CM;
184 return (int) (dpi.x * inch);
185 }
186
187
188
189
190
191
192
193 protected int pixelForCmY(double cm) {
194 Point dpi = _printer.getDPI();
195 double inch = cm / INCH_IN_CM;
196 return (int) (dpi.y * inch);
197 }
198
199
200
201
202
203
204 public Printer getPrinter() {
205 return _printer;
206 }
207
208
209
210
211
212
213 public TimeBarViewerDelegate getDelegate() {
214 return _delegate;
215 }
216
217
218
219
220
221
222 public void init(TimeBarViewer tbv) {
223
224 _delegate.setOptimizeScrolling(false);
225
226 if (tbv.getTimeScaleRenderer() != null) {
227 _timeScaleRenderer = tbv.getTimeScaleRenderer().createPrintRenderer(_printer);
228 }
229 if (tbv.getHeaderRenderer() != null) {
230 _headerRenderer = tbv.getHeaderRenderer().createPrintRenderer(_printer);
231 }
232 if (tbv.getGridRenderer() != null) {
233 _gridRenderer = tbv.getGridRenderer().createPrintRenderer(_printer);
234 }
235 if (tbv.getHierarchyRenderer() != null) {
236 _hierarchyRenderer = tbv.getHierarchyRenderer().createPrintRenderer(_printer);
237 }
238 if (tbv.getGapRenderer() != null) {
239 _gapRenderer = tbv.getGapRenderer().createPrintRenderer(_printer);
240 }
241 if (tbv.getMarkerRenderer() != null) {
242 _markerRenderer = tbv.getMarkerRenderer().createPrintRenderer(_printer);
243 }
244 if (tbv.getTitleRenderer() != null) {
245 _titleRenderer = tbv.getTitleRenderer().createPrintRenderer(_printer);
246 }
247 if (tbv.getGlobalAssistantRenderer() != null) {
248 _globalAssistantRenderer = tbv.getGlobalAssistantRenderer().createPrintRenderer(_printer);
249 }
250 if (tbv.getRelationRenderer() != null) {
251 _relationRenderer = tbv.getRelationRenderer().createPrintRenderer(_printer);
252 }
253
254
255
256 Map<Class<? extends Interval>, TimeBarRenderer> rendererMap = tbv.getRendererMapping();
257 for (Class<? extends Interval> clazz : rendererMap.keySet()) {
258 TimeBarRenderer displayRenderer = rendererMap.get(clazz);
259 TimeBarRenderer printRenderer = displayRenderer.createPrintrenderer(_printer);
260 _printerRendererMap.put(clazz, printRenderer);
261 }
262
263
264 boolean horizontal = tbv.getTBOrientation().equals(TimeBarViewerInterface.Orientation.HORIZONTAL);
265 _delegate.setOrientation(tbv.getTBOrientation());
266
267
268 _delegate.addMarkers(tbv.getMarkers());
269
270 _delegate.setModel(tbv.getHierarchicalModel());
271 _delegate.setHierarchicalViewState(tbv.getHierarchicalViewState());
272 _delegate.setModel(tbv.getModel());
273
274 _delegate.setXAxisHeight(scaleY(tbv.getXAxisHeight()));
275 if (_timeScaleRenderer.getHeight() > 0) {
276 _delegate.setXAxisHeight(_timeScaleRenderer.getHeight());
277 }
278 _delegate.setTimeScalePosition(tbv.getTimeScalePosition());
279
280 _delegate.setYAxisWidth(scaleX(tbv.getYAxisWidth()));
281 _delegate.setHierarchyWidth(scaleX(tbv.getHierarchyWidth()));
282
283
284 _delegate.setRowHeight(scaleY(tbv.getRowHeight()));
285 if (tbv.getTimeBarViewState().getUseVariableRowHeights()) {
286 _delegate.getTimeBarViewState().setUseVariableRowHeights(true);
287 for (int i = 0; i < tbv.getModel().getRowCount(); i++) {
288 TimeBarRow row = tbv.getModel().getRow(i);
289 int height = tbv.getTimeBarViewState().getRowHeight(row);
290 if (horizontal) {
291 height = scaleY(height);
292 } else {
293 height = scaleX(height);
294 }
295 _delegate.getTimeBarViewState().setRowHeight(row, height);
296 }
297
298 _delegate.getTimeBarViewState().setRowHeightStrategy(tbv.getTimeBarViewState().getRowHeightStrategy());
299 }
300
301 _delegate.setDrawRowGrid(tbv.getDrawRowGrid());
302
303
304 _delegate.setRowSorter(tbv.getRowSorter());
305 _delegate.setRowFilter(tbv.getRowFilter());
306 _delegate.setIntervalFilter(tbv.getIntervalFilter());
307
308 _delegate.setDrawOverlapping(tbv.getDrawOverlapping());
309 _delegate.setTitle(tbv.getTitle());
310 }
311
312
313
314
315
316
317
318 protected TimeBarRenderer getRenderer(Class<? extends Interval> clazz) {
319 TimeBarRenderer result = null;
320 result = _printerRendererMap.get(clazz);
321 if (result != null) {
322 return result;
323 }
324
325
326 Class<?>[] interfaces = clazz.getInterfaces();
327 for (Class<?> c : interfaces) {
328 result = _printerRendererMap.get(c);
329 if (result != null) {
330 return result;
331 }
332 }
333
334
335 Class<?> sc = clazz.getSuperclass();
336
337 while (sc != null) {
338 result = _printerRendererMap.get(sc);
339 if (result != null) {
340 return result;
341 }
342
343 Class<?>[] scinterfaces = sc.getInterfaces();
344 for (Class<?> c : scinterfaces) {
345 result = _printerRendererMap.get(c);
346 if (result != null) {
347 return result;
348 }
349 }
350 sc = sc.getSuperclass();
351 }
352
353 return result;
354 }
355
356
357
358
359
360
361 public void print(ViewConfiguration vc) {
362
363 int marginTop = pixelForCmY(_marginTop);
364 int marginBottom = pixelForCmY(_marginBottom);
365 int marginLeft = pixelForCmX(_marginLeft);
366 int marginRight = pixelForCmX(_marginRight);
367
368 int footerHeight = pixelForCmX(_footerHeight);
369
370 int width = _printer.getClientArea().width - marginLeft - marginRight;
371 int height = _printer.getClientArea().height - marginTop - marginBottom - footerHeight;
372
373 _printer.startJob(vc.getName() != null ? vc.getName() : "timebars_print");
374
375
376 GC gc = new GC(_printer);
377 Font oldfont = gc.getFont();
378 FontData fontdata = new FontData(PRINTERFONTNAME, PRINTERFONTSIZE, SWT.NULL);
379 Font printerFont = new Font(_printer, fontdata);
380 gc.setFont(printerFont);
381
382 int secTotal;
383 if (vc.getEndDate() != null) {
384 secTotal = vc.getEndDate().diffSeconds(vc.getStartDate());
385 } else {
386 secTotal = _delegate.getModel().getMaxDate().diffSeconds(vc.getStartDate());
387 }
388
389 int totalyaxiswidth = _delegate.getHierarchyWidth() + _delegate.getYAxisWidth();
390
391 _delegate.setDrawingOffset(marginLeft, marginTop);
392 _delegate.preparePaint(width, height);
393
394 double pps = (double) _delegate.getDiagramRect().width / (double) vc.getSecondsPerPage();
395 _delegate.setPixelPerSecond(pps);
396
397
398 long totalPixelWidth = (long) ((double) secTotal * pps);
399
400
401 int pagesX;
402 if (vc.getRepeatYAxis()) {
403 pagesX = secTotal / vc.getSecondsPerPage();
404
405 if (secTotal % vc.getSecondsPerPage() > 0) {
406 pagesX += 1;
407 }
408 } else {
409 if (secTotal <= vc.getSecondsPerPage()) {
410 pagesX = 1;
411 } else {
412 long remain = totalPixelWidth;
413 pagesX = 0;
414
415 pagesX++;
416 remain -= _delegate.getDiagramRect().width;
417
418 pagesX += remain / (_delegate.getDiagramRect().width + totalyaxiswidth);
419
420 if (remain % (_delegate.getDiagramRect().width + totalyaxiswidth) > 0) {
421 pagesX++;
422 }
423 }
424 }
425
426
427
428 int pagesY;
429 List<Integer> firstRows = new ArrayList<Integer>();
430 List<Integer> firstRowOffsets = new ArrayList<Integer>();
431
432 int y = 0;
433 int pageIdx = 0;
434 int rowIdx = 0;
435
436 while (rowIdx < _delegate.getRowCount()) {
437 rowIdx = _delegate.getRowIdxForAbsoluteOffset(y);
438 firstRows.add(rowIdx);
439 firstRowOffsets.add(_delegate.getRowPixOffsetForAbsoluteOffset(rowIdx, y));
440 if (vc.getRepeatScale() || pageIdx == 0) {
441 y += _delegate.getDiagramRect().height;
442 } else {
443 y += _delegate.getDiagramRect().height + _delegate.getXAxisHeight();
444 }
445
446 pageIdx++;
447 try {
448 rowIdx = _delegate.getRowIdxForAbsoluteOffset(y);
449 } catch (Exception e) {
450 rowIdx = -1;
451 }
452 if (rowIdx >= _delegate.getRowCount() || rowIdx == -1) {
453 break;
454 }
455 }
456 pagesY = pageIdx;
457
458
459
460 int xaxisheigth = _delegate.getXAxisHeight();
461 int yaxisWidth = _delegate.getYAxisWidth();
462 int hierarchyWidth = _delegate.getHierarchyWidth();
463
464 JaretDate pageStart = vc.getStartDate().copy();
465 for (int px = 0; px < pagesX; px++) {
466 _delegate.setStartDate(pageStart);
467 for (int py = 0; py < pagesY; py++) {
468 String footerText = vc.getFootLine() != null ? vc.getFootLine() : "";
469 footerText += "(" + (px + 1) + "/" + pagesX + "," + (py + 1) + "/" + pagesY + ")";
470 _printer.startPage();
471 if (vc.getRepeatScale()
472 || (py == 0 && _delegate.getTimeScalePosition() == TimeBarViewerInterface.TIMESCALE_POSITION_TOP)
473 || (py == pagesY - 1 && _delegate.getTimeScalePosition() == TimeBarViewerInterface.TIMESCALE_POSITION_BOTTOM)) {
474 _delegate.setXAxisHeight(xaxisheigth);
475 } else {
476 _delegate.setXAxisHeight(0);
477 }
478 if (vc.getRepeatYAxis() || px == 0) {
479 _delegate.setHierarchyWidth(hierarchyWidth);
480 _delegate.setYAxisWidth(yaxisWidth);
481 } else {
482 _delegate.setHierarchyWidth(0);
483 _delegate.setYAxisWidth(0);
484 }
485
486
487 _delegate.preparePaint(width, height);
488
489 print(gc, footerText, firstRows.get(py), firstRowOffsets.get(py), _delegate.getDiagramRect().height,
490 footerHeight);
491 _printer.endPage();
492 }
493
494 pageStart = _delegate.getEndDate().copy();
495
496 }
497 _printer.endJob();
498 gc.setFont(oldfont);
499 printerFont.dispose();
500 gc.dispose();
501 }
502
503
504
505
506
507
508
509
510
511
512
513 private void print(GC gc, String footer, int firstRow, int firstRowOffset, int diagramHeight, int footerHeight) {
514
515 _delegate.setFirstRow(firstRow, firstRowOffset);
516
517
518 RenderDelegate.drawXAxis(_delegate, _timeScaleRenderer, true, gc);
519
520
521 if (_timeScaleRenderer != null && _timeScaleRenderer instanceof ITickProvider) {
522 _gridRenderer.setTickProvider((ITickProvider)_timeScaleRenderer);
523 }
524 RenderDelegate.drawGrid(_delegate, _gridRenderer, true, gc);
525 if (_globalAssistantRenderer != null) {
526 _globalAssistantRenderer.doRenderingBeforeIntervals(_delegate, gc, true);
527 }
528
529 drawRows(gc);
530 RenderDelegate.drawMarkers(_delegate, _markerRenderer, true, gc);
531 if (_delegate.getTitleRect().width > 0 && _delegate.getTitleRect().height > 0) {
532 RenderDelegate.drawTitle(_delegate, _titleRenderer, true, gc);
533 }
534 if (footer != null) {
535 drawFooter(gc, footer, _delegate.getDiagramRect().y + _delegate.getDiagramRect().height, footerHeight);
536 }
537 if (_globalAssistantRenderer != null) {
538 _globalAssistantRenderer.doRenderingLast(_delegate, gc, true);
539 }
540
541
542
543 Color bg = gc.getBackground();
544 gc.fillRectangle(_delegate.getDiagramRect().x + _delegate.getDiagramRect().width, _delegate.getDiagramRect().y,
545 pixelForCmX(_marginLeft), _delegate.getDiagramRect().height);
546 gc.setBackground(bg);
547
548 }
549
550
551
552
553
554
555
556
557
558 private void drawFooter(GC gc, String footer, int footerStartY, int footerHeight) {
559 Point extent = gc.textExtent(footer);
560 int y = footerStartY + (footerHeight - extent.y) / 2;
561 gc.drawString(footer, _delegate.getHierarchyRect().x, y);
562 }
563
564
565
566
567
568
569 private void drawRows(GC gc) {
570
571
572 if (_relationRenderer != null) {
573 _relationRenderer.renderRelations(_delegate, gc, true);
574 }
575
576 int firstRow = _delegate.getFirstRow();
577
578
579 int startY = Math.min(_delegate.getXAxisRect().y, _delegate.getDiagramRect().y);
580 int endY = Math.max(_delegate.getXAxisRect().y + _delegate.getXAxisRect().height, _delegate.getDiagramRect().y
581 + _delegate.getDiagramRect().height);
582
583 if (_delegate.getYAxisWidth() > 0) {
584 gc.drawLine(_delegate.getDiagramRect().x - 1, startY, _delegate.getDiagramRect().x - 1, endY);
585 }
586
587 if (_delegate.getHierarchyWidth() > 0) {
588 gc.drawLine(_delegate.getHierarchyRect().x + _delegate.getHierarchyRect().width - 1, startY, _delegate
589 .getHierarchyRect().x
590 + _delegate.getHierarchyRect().width - 1, endY);
591 }
592 int upperYBound = 0;
593 int lowerYBound = _printer.getClientArea().height;
594 if (gc.isClipped()) {
595 upperYBound = gc.getClipping().y;
596 lowerYBound = upperYBound + gc.getClipping().height;
597 }
598 for (int r = firstRow; r <= firstRow + _delegate.getRowsDisplayed() + 1 && r < _delegate.getRowCount(); r++) {
599 TimeBarRow row = _delegate.getRow(r);
600 int y = _delegate.yForRow(row);
601 if (y == -1) {
602
603 break;
604 }
605
606
607
608
609 int rowHeight = _delegate.getTimeBarViewState().getRowHeight(row);
610 if ((y >= upperYBound && y <= lowerYBound)
611 || (y + rowHeight >= upperYBound && y + rowHeight <= lowerYBound)
612 || (upperYBound > y && upperYBound < y + rowHeight)) {
613 RenderDelegate.drawRowSimple(_delegate, this, _headerRenderer, _hierarchyRenderer, true, gc, _delegate
614 .getRow(r), y, false);
615
616 if (_gapRenderer != null) {
617 RenderDelegate.drawRowGaps(_delegate, _gapRenderer, true, gc, 0, y, _delegate.getRow(r), false);
618 }
619 }
620 }
621 }
622
623
624
625
626 public void dispose() {
627 _delegate.dispose();
628 if (_headerRenderer != null) {
629 _headerRenderer.dispose();
630 }
631 if (_timeScaleRenderer != null) {
632 _timeScaleRenderer.dispose();
633 }
634 if (_renderer != null) {
635 _renderer.dispose();
636 }
637 if (_hierarchyRenderer != null) {
638 _hierarchyRenderer.dispose();
639 }
640 if (_gridRenderer != null) {
641 _gridRenderer.dispose();
642 }
643 if (_markerRenderer != null) {
644 _markerRenderer.dispose();
645 }
646 if (_titleRenderer != null) {
647 _titleRenderer.dispose();
648 }
649 if (_gapRenderer != null) {
650 _gapRenderer.dispose();
651 }
652 if (_globalAssistantRenderer != null) {
653 _globalAssistantRenderer.dispose();
654 }
655 if (_relationRenderer != null) {
656 _relationRenderer.dispose();
657 }
658
659
660 for (TimeBarRenderer renderer : _printerRendererMap.values()) {
661 renderer.dispose();
662 }
663
664 }
665
666
667
668
669 public double getFooterHeight() {
670 return _footerHeight;
671 }
672
673
674
675
676
677 public void setFooterHeight(double footerHeight) {
678 _footerHeight = footerHeight;
679 }
680
681
682
683
684
685
686 public double getMarginTop() {
687 return _marginTop;
688 }
689
690
691
692
693
694
695 public void setMarginTop(double marginTop) {
696 _marginTop = marginTop;
697 }
698
699
700
701
702
703
704 public double getMarginBottom() {
705 return _marginBottom;
706 }
707
708
709
710
711
712
713 public void setMarginBottom(double marginBottom) {
714 _marginBottom = marginBottom;
715 }
716
717
718
719
720
721
722 public double getMarginLeft() {
723 return _marginLeft;
724 }
725
726
727
728
729
730
731 public void setMarginLeft(double marginLeft) {
732 _marginLeft = marginLeft;
733 }
734
735
736
737
738
739
740 public double getMarginRight() {
741 return _marginRight;
742 }
743
744
745
746
747
748
749 public void setMarginRight(double marginRight) {
750 _marginRight = marginRight;
751 }
752 }