OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 137 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
137 ilm 1
package org.jopencalendar.print;
2
 
3
import java.awt.Color;
4
import java.awt.Font;
5
import java.awt.Graphics;
6
import java.awt.Graphics2D;
7
import java.awt.event.ActionEvent;
8
import java.awt.event.ActionListener;
9
import java.awt.image.BufferedImage;
10
import java.awt.print.PageFormat;
11
import java.awt.print.Pageable;
12
import java.awt.print.Printable;
13
import java.awt.print.PrinterException;
14
import java.awt.print.PrinterJob;
15
import java.text.DateFormat;
16
import java.util.ArrayList;
17
import java.util.Calendar;
18
import java.util.List;
19
 
20
import javax.print.attribute.HashPrintRequestAttributeSet;
21
import javax.print.attribute.PrintRequestAttributeSet;
22
import javax.print.attribute.standard.PrintQuality;
23
import javax.swing.JButton;
24
import javax.swing.JFrame;
25
import javax.swing.SwingUtilities;
26
import javax.swing.UIManager;
27
 
28
import org.jopencalendar.LayoutUtils;
29
import org.jopencalendar.model.Flag;
30
import org.jopencalendar.model.JCalendarItem;
31
 
32
public class CalendarItemPrinter implements Printable, Pageable {
33
 
168 ilm 34
    private static final int RIGHT_MARGIN = 50;
35
    public static final Font FONT_NORMAL = new Font("Arial", Font.PLAIN, 11);
36
    public static final Font FONT_BOLD = FONT_NORMAL.deriveFont(Font.BOLD);
37
 
137 ilm 38
    private List<JCalendarItem> items;
39
    private List<CalendarItemPage> pages = null;
40
    private String title;
41
    private boolean showDuration = true;
168 ilm 42
    private PageFormat calendarPageFormat;
137 ilm 43
 
44
    public CalendarItemPrinter(String title, List<JCalendarItem> items, PageFormat pf) {
45
        this.title = title;
46
        this.items = items;
168 ilm 47
        this.calendarPageFormat = pf;
137 ilm 48
    }
49
 
50
    public String getTitle() {
51
        return title;
52
    }
53
 
168 ilm 54
    @Override
137 ilm 55
    public int print(Graphics g, PageFormat pf, int pageIndex) throws PrinterException {
56
        if (pages == null) {
57
            computeLayout(g, pf);
58
        }
59
 
60
        if (pageIndex >= pages.size()) {
61
            return NO_SUCH_PAGE;
62
        }
63
 
64
        final Graphics2D g2d = (Graphics2D) g;
65
        g2d.translate(pf.getImageableX(), pf.getImageableY());
66
        final CalendarItemPage page = this.pages.get(pageIndex);
67
 
168 ilm 68
        printPage(g, page);
137 ilm 69
 
70
        /* tell the caller that this page is part of the printed document */
71
        return PAGE_EXISTS;
72
    }
73
 
168 ilm 74
    public void printPage(Graphics g, final CalendarItemPage page) {
75
        // We use our own page format to avoid issue between formatting and printing
76
        PageFormat pf = this.calendarPageFormat;
77
 
137 ilm 78
        final Graphics2D g2d = (Graphics2D) g;
79
        // Title
80
        g.setFont(getTitleFont());
81
        g.setColor(getTitleColor());
82
        final int xTitle = ((int) pf.getImageableWidth() - (int) g2d.getFontMetrics().getStringBounds(getTitle(), g2d).getWidth()) / 2;
83
        g.drawString(getTitle(), xTitle, g2d.getFontMetrics().getHeight());
84
        // Page number
85
        g.setFont(getPageNumberFont());
86
        g.setColor(getPageNumberColor());
87
        int y = getTitleHeight();
88
        final DateFormat df = DateFormat.getDateInstance(DateFormat.FULL);
89
        final int size = page.getItems().size();
90
        final String strPages = (page.getPageIndex() + 1) + " / " + pages.size();
91
        int xStrPages = (int) pf.getImageableWidth() - (int) g2d.getFontMetrics().getStringBounds(strPages, g2d).getWidth();
92
        g.drawString(strPages, xStrPages, g2d.getFontMetrics().getHeight());
93
 
94
        final double hourColumnWidth = getHourColumnWidth();
168 ilm 95
        final double maxWidth = pf.getImageableWidth() - hourColumnWidth - getMarginRight();
137 ilm 96
        for (int i = 0; i < size; i++) {
97
            final JCalendarItem item = page.getItems().get(i);
98
            final double lineHeight = page.getHeights().get(i);
99
            int lY = y;
100
            drawBackground(0, lY, (int) pf.getImageableWidth(), (int) lineHeight);
101
            if (page.getShowDates().get(i)) {
102
                g2d.setColor(getHourColor(item));
103
                g.setFont(getHourFont(item));
104
                int dateHeight = g2d.getFontMetrics().getHeight();
105
                lY += dateHeight;
106
                final String format = getDate(df, item);
107
                g2d.drawString(format, 2, lY);
108
            }
109
            // Vertical bar
110
            g2d.setColor(getVerticalBarColor(item));
111
            g2d.drawLine((int) hourColumnWidth - 5, lY + 6, (int) hourColumnWidth - 5, (int) (y + lineHeight));
112
 
113
            final Calendar dtStart = item.getDtStart();
114
            final Calendar dtEnd = item.getDtEnd();
115
            // Hour
116
            g.setColor(getHourColor(item));
117
            g.setFont(getHourFont(item));
118
            final int hourY = lY + g2d.getFontMetrics().getHeight();
119
            g2d.drawString(formatTime(dtStart) + " - " + formatTime(dtEnd), 3, hourY);
120
            // Duration
121
            if (this.showDuration) {
122
                g.setColor(getDurationColor(item));
123
                g.setFont(getDurationFont(item));
124
                final int durationY = hourY + g2d.getFontMetrics().getHeight();
125
                g2d.drawString(formatDuration(dtStart, dtEnd), 3, durationY);
126
            }
127
 
128
            // Summary
129
            g.setFont(getLine1Font(item));
130
 
131
            final List<String> l1 = LayoutUtils.wrap(getLine1Text(item), g.getFontMetrics(), (int) maxWidth);
132
            if (item.hasFlag(Flag.getFlag("warning"))) {
133
                g2d.setColor(new Color(255, 249, 144));
168 ilm 134
                g2d.fillRect((int) hourColumnWidth - 1, lY + 3, (int) maxWidth, g2d.getFontMetrics().getHeight() * l1.size());
137 ilm 135
            }
136
            g.setColor(getLine1Color(item));
137
            for (String string : l1) {
138
                lY += g2d.getFontMetrics().getHeight();
139
                g2d.drawString(string, (int) hourColumnWidth, lY);
140
            }
141
            // Description
142
            g.setFont(getLine2Font(item));
143
            g.setColor(getLine2Color(item));
144
            final List<String> l2 = LayoutUtils.wrap(getLine2Text(item), g.getFontMetrics(), (int) maxWidth);
145
            for (String string : l2) {
146
                lY += g2d.getFontMetrics().getHeight();
147
                g2d.drawString(string, (int) hourColumnWidth, lY);
148
            }
149
            //
150
            y += lineHeight;
151
        }
152
    }
153
 
168 ilm 154
    private int getMarginRight() {
155
        return RIGHT_MARGIN;
156
    }
157
 
137 ilm 158
    public String getDate(final DateFormat df, final JCalendarItem item) {
159
        return LayoutUtils.firstUp(df.format(item.getDtStart().getTime()));
160
    }
161
 
162
    public String formatDuration(Calendar dtStart, Calendar dtEnd) {
163
        long t2 = dtEnd.getTimeInMillis();
164
        long t1 = dtStart.getTimeInMillis();
165
        long seconds = (t2 - t1) / 1000;
166
 
167
        final long minutes = seconds / 60;
168
 
169
        String l = String.valueOf(minutes % 60);
170
        if (l.length() < 2) {
171
            l = "0" + l;
172
        }
173
        return "(" + minutes / 60 + "h" + l + ")";
174
    }
175
 
176
    public void drawBackground(int x, int y, int w, int h) {
177
        // for subclass to add some background
178
    }
179
 
180
    public Color getPageNumberColor() {
181
        return Color.BLACK;
182
    }
183
 
184
    public Font getPageNumberFont() {
185
        return FONT_NORMAL;
186
    }
187
 
188
    // Title
189
    public Color getTitleColor() {
190
        return Color.BLACK;
191
    }
192
 
193
    public Font getTitleFont() {
194
        return FONT_NORMAL;
195
    }
196
 
197
    // Hour
198
    public Color getHourColor(JCalendarItem item) {
199
        return Color.BLACK;
200
    }
201
 
202
    public Font getHourFont(JCalendarItem item) {
203
        return FONT_BOLD;
204
    }
205
 
206
    // Duration
207
    public Color getDurationColor(JCalendarItem item) {
208
        return Color.BLACK;
209
    }
210
 
211
    public Font getDurationFont(JCalendarItem item) {
212
        return FONT_NORMAL;
213
    }
214
 
215
    // Line 1
216
    public Color getLine1Color(final JCalendarItem item) {
217
        return Color.BLACK;
218
    }
219
 
220
    public String getLine1Text(final JCalendarItem item) {
221
        return item.getSummary();
222
    }
223
 
224
    public Font getLine1Font(final JCalendarItem item) {
225
        return FONT_NORMAL;
226
    }
227
 
228
    // Line 2
229
    public Color getLine2Color(final JCalendarItem item) {
230
        return Color.BLACK;
231
    }
232
 
233
    public String getLine2Text(final JCalendarItem item) {
234
        return item.getDescription();
235
    }
236
 
237
    public Font getLine2Font(final JCalendarItem item) {
238
        return FONT_NORMAL;
239
    }
240
 
241
    public Color getVerticalBarColor(final JCalendarItem item) {
242
        return new Color(0, 68, 128);
243
    }
244
 
245
    public void setShowDuration(boolean showDuration) {
246
        this.showDuration = showDuration;
247
    }
248
 
249
    public String formatTime(final Calendar dtStart) {
250
        String h = String.valueOf(dtStart.get(Calendar.HOUR_OF_DAY));
251
        String m = String.valueOf(dtStart.get(Calendar.MINUTE));
252
        if (h.length() < 2) {
253
            h = " " + h;
254
        }
255
        if (m.length() < 2) {
256
            m = "0" + m;
257
        }
258
        return h + ":" + m;
259
    }
260
 
261
    private void computeLayout(Graphics g, PageFormat pf) {
168 ilm 262
        int pageIndex = 0;
137 ilm 263
        pages = new ArrayList<CalendarItemPage>();
264
        CalendarItemPage page = new CalendarItemPage();
168 ilm 265
        page.setPageIndex(pageIndex);
137 ilm 266
        this.pages.add(page);
168 ilm 267
        pageIndex++;
137 ilm 268
        if (items.isEmpty()) {
269
            return;
270
        }
271
        double remainingHeight = pf.getImageableHeight() - getTitleHeight();
272
        boolean showDate = true;
273
        Calendar c = Calendar.getInstance();
274
        c.setTimeInMillis(this.items.get(0).getDtStart().getTimeInMillis());
275
        for (int i = 0; i < this.items.size(); i++) {
276
            JCalendarItem item = this.items.get(i);
277
            if (i > 0) {
278
                showDate = (item.getDtStart().get(Calendar.YEAR) != c.get(Calendar.YEAR) || item.getDtStart().get(Calendar.DAY_OF_YEAR) != c.get(Calendar.DAY_OF_YEAR));
279
            }
280
            c = item.getDtStart();
281
            double h = getPrintHeight(g, pf, item);
282
            double secureMargin = 20D;
283
            if (remainingHeight < h + secureMargin) {
284
                page = new CalendarItemPage();
168 ilm 285
                page.setPageIndex(pageIndex);
137 ilm 286
                showDate = true;
287
                remainingHeight = pf.getImageableHeight() - getTitleHeight();
288
                this.pages.add(page);
168 ilm 289
                pageIndex++;
290
 
137 ilm 291
            }
292
            if (showDate) {
293
                g.setFont(getHourFont(item));
294
                h += g.getFontMetrics().getHeight();
295
            }
296
            remainingHeight -= h;
297
 
298
            page.add(item);
299
            page.addHeight(Double.valueOf(h));
300
            page.addShowDate(showDate);
301
        }
302
 
303
    }
304
 
305
    public int getHourColumnWidth() {
306
        return 90;
307
    }
308
 
309
    public int getTitleHeight() {
310
        return 40;
311
    }
312
 
313
    private double getPrintHeight(Graphics g, PageFormat pf, JCalendarItem item) {
168 ilm 314
        double heigth = 0;
315
        int maxWidth = (int) pf.getImageableWidth() - getHourColumnWidth() - getMarginRight();
316
        // Line 1
137 ilm 317
        g.setFont(this.getLine1Font(item));
168 ilm 318
        int l1 = LayoutUtils.wrap(getLine1Text(item), g.getFontMetrics(), maxWidth).size();
319
        heigth += l1 * g.getFontMetrics().getHeight();
320
        // Line 2
137 ilm 321
        g.setFont(this.getLine2Font(item));
168 ilm 322
        int l2 = LayoutUtils.wrap(getLine2Text(item), g.getFontMetrics(), maxWidth).size();
323
        heigth += l2 * g.getFontMetrics().getHeight();
324
        return heigth;
137 ilm 325
    }
326
 
327
    public List<CalendarItemPage> getPages() {
328
        return pages;
329
    }
330
 
168 ilm 331
    public static void main(String[] args) {
137 ilm 332
        SwingUtilities.invokeLater(new Runnable() {
333
 
334
            @Override
335
            public void run() {
336
                try {
337
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
338
                } catch (Exception ex) {
339
                    ex.printStackTrace();
340
                }
341
                final JFrame f = new JFrame("Printing Pagination Example");
342
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
343
                final JButton printButton = new JButton("Print test pages");
344
                printButton.addActionListener(new ActionListener() {
345
 
346
                    @Override
347
                    public void actionPerformed(ActionEvent e) {
348
                        PrinterJob job = PrinterJob.getPrinterJob();
168 ilm 349
                        List<JCalendarItem> cItems = new ArrayList<JCalendarItem>();
137 ilm 350
                        Calendar c = Calendar.getInstance();
351
                        Flag.register(new Flag("warning", null, "Warning", "A default warning"));
352
                        for (int i = 0; i < 50; i++) {
353
                            JCalendarItem item = new JCalendarItem();
354
                            item.setSummary("Item " + i);
355
                            StringBuilder d = new StringBuilder();
356
                            d.append("Description");
357
                            for (int j = 0; j < i; j++) {
358
                                if (i % 2 == 0)
359
                                    d.append(" Hello");
360
                                else
168 ilm 361
                                    d.append(" Wo");
137 ilm 362
                            }
363
                            d.append("END");
364
                            if (i % 6 == 0) {
365
                                item.addFlag(Flag.getFlag("warning"));
366
                            }
168 ilm 367
                            if (i != 5) {
368
                                item.setDescription(d.toString());
369
                            } else {
370
                                item.setDescription(
371
                                        "Escalier Ménage Complet - 2 escaliers : Interrupteurs, poignées portes, mains courantes côté route, traces de doigts sur vitres et ascenseur, aspiration moquettes et carrelage, lavage des halls.");
372
                            }
137 ilm 373
                            item.setDtStart(c);
374
                            c.add(Calendar.HOUR_OF_DAY, 1);
375
                            item.setDtEnd(c);
376
                            c.add(Calendar.HOUR_OF_DAY, 1);
168 ilm 377
                            cItems.add(item);
137 ilm 378
                        }
379
                        final PrintRequestAttributeSet printAttributes = new HashPrintRequestAttributeSet();
380
                        printAttributes.add(PrintQuality.HIGH);
168 ilm 381
                        job.setPrintable(new CalendarItemPrinter("OpenConcerto", cItems, job.getPageFormat(printAttributes)));
137 ilm 382
                        boolean ok = job.printDialog();
383
                        if (ok) {
384
                            try {
385
                                job.print();
386
                            } catch (PrinterException ex) {
387
                                /* The job did not successfully complete */
388
                                ex.printStackTrace();
389
                            }
390
                        }
391
 
392
                    }
393
                });
394
                f.add("Center", printButton);
395
                f.pack();
396
                f.setLocationRelativeTo(null);
397
                f.setVisible(true);
398
            }
399
        });
400
    }
401
 
402
    public List<JCalendarItem> getItems() {
403
        return this.items;
404
    }
405
 
406
    @Override
407
    public int getNumberOfPages() {
408
        if (this.pages == null) {
168 ilm 409
            BufferedImage offImage = new BufferedImage((int) calendarPageFormat.getHeight(), (int) calendarPageFormat.getWidth(), BufferedImage.TYPE_INT_ARGB);
410
            Graphics2D g2 = offImage.createGraphics();
411
            computeLayout(g2, calendarPageFormat);
137 ilm 412
        }
413
        return this.pages.size();
414
    }
415
 
416
    @Override
168 ilm 417
    public PageFormat getPageFormat(int pageIndex) {
418
        return this.calendarPageFormat;
137 ilm 419
    }
420
 
421
    @Override
168 ilm 422
    public Printable getPrintable(int pageIndex) {
137 ilm 423
        final CalendarItemPage page = this.pages.get(pageIndex);
424
        return new Printable() {
425
 
426
            @Override
427
            public int print(Graphics graphics, PageFormat pageFormat, int i) throws PrinterException {
428
                final Graphics2D g2d = (Graphics2D) graphics;
168 ilm 429
                g2d.translate(calendarPageFormat.getImageableX(), calendarPageFormat.getImageableY());
430
                printPage(graphics, page);
137 ilm 431
                return PAGE_EXISTS;
432
            }
433
        };
434
    }
435
}