OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

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

package org.jopencalendar.print;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Pageable;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.PrintQuality;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

import org.jopencalendar.LayoutUtils;
import org.jopencalendar.model.Flag;
import org.jopencalendar.model.JCalendarItem;

public class CalendarItemPrinter implements Printable, Pageable {

    private static final int RIGHT_MARGIN = 50;
    public static final Font FONT_NORMAL = new Font("Arial", Font.PLAIN, 11);
    public static final Font FONT_BOLD = FONT_NORMAL.deriveFont(Font.BOLD);

    private List<JCalendarItem> items;
    private List<CalendarItemPage> pages = null;
    private String title;
    private boolean showDuration = true;
    private PageFormat calendarPageFormat;

    public CalendarItemPrinter(String title, List<JCalendarItem> items, PageFormat pf) {
        this.title = title;
        this.items = items;
        this.calendarPageFormat = pf;
    }

    public String getTitle() {
        return title;
    }

    @Override
    public int print(Graphics g, PageFormat pf, int pageIndex) throws PrinterException {
        if (pages == null) {
            computeLayout(g, pf);
        }

        if (pageIndex >= pages.size()) {
            return NO_SUCH_PAGE;
        }

        final Graphics2D g2d = (Graphics2D) g;
        g2d.translate(pf.getImageableX(), pf.getImageableY());
        final CalendarItemPage page = this.pages.get(pageIndex);

        printPage(g, page);

        /* tell the caller that this page is part of the printed document */
        return PAGE_EXISTS;
    }

    public void printPage(Graphics g, final CalendarItemPage page) {
        // We use our own page format to avoid issue between formatting and printing
        PageFormat pf = this.calendarPageFormat;

        final Graphics2D g2d = (Graphics2D) g;
        // Title
        g.setFont(getTitleFont());
        g.setColor(getTitleColor());
        final int xTitle = ((int) pf.getImageableWidth() - (int) g2d.getFontMetrics().getStringBounds(getTitle(), g2d).getWidth()) / 2;
        g.drawString(getTitle(), xTitle, g2d.getFontMetrics().getHeight());
        // Page number
        g.setFont(getPageNumberFont());
        g.setColor(getPageNumberColor());
        int y = getTitleHeight();
        final DateFormat df = DateFormat.getDateInstance(DateFormat.FULL);
        final int size = page.getItems().size();
        final String strPages = (page.getPageIndex() + 1) + " / " + pages.size();
        int xStrPages = (int) pf.getImageableWidth() - (int) g2d.getFontMetrics().getStringBounds(strPages, g2d).getWidth();
        g.drawString(strPages, xStrPages, g2d.getFontMetrics().getHeight());

        final double hourColumnWidth = getHourColumnWidth();
        final double maxWidth = pf.getImageableWidth() - hourColumnWidth - getMarginRight();
        for (int i = 0; i < size; i++) {
            final JCalendarItem item = page.getItems().get(i);
            final double lineHeight = page.getHeights().get(i);
            int lY = y;
            drawBackground(0, lY, (int) pf.getImageableWidth(), (int) lineHeight);
            if (page.getShowDates().get(i)) {
                g2d.setColor(getHourColor(item));
                g.setFont(getHourFont(item));
                int dateHeight = g2d.getFontMetrics().getHeight();
                lY += dateHeight;
                final String format = getDate(df, item);
                g2d.drawString(format, 2, lY);
            }
            // Vertical bar
            g2d.setColor(getVerticalBarColor(item));
            g2d.drawLine((int) hourColumnWidth - 5, lY + 6, (int) hourColumnWidth - 5, (int) (y + lineHeight));

            final Calendar dtStart = item.getDtStart();
            final Calendar dtEnd = item.getDtEnd();
            // Hour
            g.setColor(getHourColor(item));
            g.setFont(getHourFont(item));
            final int hourY = lY + g2d.getFontMetrics().getHeight();
            g2d.drawString(formatTime(dtStart) + " - " + formatTime(dtEnd), 3, hourY);
            // Duration
            if (this.showDuration) {
                g.setColor(getDurationColor(item));
                g.setFont(getDurationFont(item));
                final int durationY = hourY + g2d.getFontMetrics().getHeight();
                g2d.drawString(formatDuration(dtStart, dtEnd), 3, durationY);
            }

            // Summary
            g.setFont(getLine1Font(item));

            final List<String> l1 = LayoutUtils.wrap(getLine1Text(item), g.getFontMetrics(), (int) maxWidth);
            if (item.hasFlag(Flag.getFlag("warning"))) {
                g2d.setColor(new Color(255, 249, 144));
                g2d.fillRect((int) hourColumnWidth - 1, lY + 3, (int) maxWidth, g2d.getFontMetrics().getHeight() * l1.size());
            }
            g.setColor(getLine1Color(item));
            for (String string : l1) {
                lY += g2d.getFontMetrics().getHeight();
                g2d.drawString(string, (int) hourColumnWidth, lY);
            }
            // Description
            g.setFont(getLine2Font(item));
            g.setColor(getLine2Color(item));
            final List<String> l2 = LayoutUtils.wrap(getLine2Text(item), g.getFontMetrics(), (int) maxWidth);
            for (String string : l2) {
                lY += g2d.getFontMetrics().getHeight();
                g2d.drawString(string, (int) hourColumnWidth, lY);
            }
            //
            y += lineHeight;
        }
    }

    private int getMarginRight() {
        return RIGHT_MARGIN;
    }

    public String getDate(final DateFormat df, final JCalendarItem item) {
        return LayoutUtils.firstUp(df.format(item.getDtStart().getTime()));
    }

    public String formatDuration(Calendar dtStart, Calendar dtEnd) {
        long t2 = dtEnd.getTimeInMillis();
        long t1 = dtStart.getTimeInMillis();
        long seconds = (t2 - t1) / 1000;

        final long minutes = seconds / 60;

        String l = String.valueOf(minutes % 60);
        if (l.length() < 2) {
            l = "0" + l;
        }
        return "(" + minutes / 60 + "h" + l + ")";
    }

    public void drawBackground(int x, int y, int w, int h) {
        // for subclass to add some background
    }

    public Color getPageNumberColor() {
        return Color.BLACK;
    }

    public Font getPageNumberFont() {
        return FONT_NORMAL;
    }

    // Title
    public Color getTitleColor() {
        return Color.BLACK;
    }

    public Font getTitleFont() {
        return FONT_NORMAL;
    }

    // Hour
    public Color getHourColor(JCalendarItem item) {
        return Color.BLACK;
    }

    public Font getHourFont(JCalendarItem item) {
        return FONT_BOLD;
    }

    // Duration
    public Color getDurationColor(JCalendarItem item) {
        return Color.BLACK;
    }

    public Font getDurationFont(JCalendarItem item) {
        return FONT_NORMAL;
    }

    // Line 1
    public Color getLine1Color(final JCalendarItem item) {
        return Color.BLACK;
    }

    public String getLine1Text(final JCalendarItem item) {
        return item.getSummary();
    }

    public Font getLine1Font(final JCalendarItem item) {
        return FONT_NORMAL;
    }

    // Line 2
    public Color getLine2Color(final JCalendarItem item) {
        return Color.BLACK;
    }

    public String getLine2Text(final JCalendarItem item) {
        return item.getDescription();
    }

    public Font getLine2Font(final JCalendarItem item) {
        return FONT_NORMAL;
    }

    public Color getVerticalBarColor(final JCalendarItem item) {
        return new Color(0, 68, 128);
    }

    public void setShowDuration(boolean showDuration) {
        this.showDuration = showDuration;
    }

    public String formatTime(final Calendar dtStart) {
        String h = String.valueOf(dtStart.get(Calendar.HOUR_OF_DAY));
        String m = String.valueOf(dtStart.get(Calendar.MINUTE));
        if (h.length() < 2) {
            h = " " + h;
        }
        if (m.length() < 2) {
            m = "0" + m;
        }
        return h + ":" + m;
    }

    private void computeLayout(Graphics g, PageFormat pf) {
        int pageIndex = 0;
        pages = new ArrayList<CalendarItemPage>();
        CalendarItemPage page = new CalendarItemPage();
        page.setPageIndex(pageIndex);
        this.pages.add(page);
        pageIndex++;
        if (items.isEmpty()) {
            return;
        }
        double remainingHeight = pf.getImageableHeight() - getTitleHeight();
        boolean showDate = true;
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(this.items.get(0).getDtStart().getTimeInMillis());
        for (int i = 0; i < this.items.size(); i++) {
            JCalendarItem item = this.items.get(i);
            if (i > 0) {
                showDate = (item.getDtStart().get(Calendar.YEAR) != c.get(Calendar.YEAR) || item.getDtStart().get(Calendar.DAY_OF_YEAR) != c.get(Calendar.DAY_OF_YEAR));
            }
            c = item.getDtStart();
            double h = getPrintHeight(g, pf, item);
            double secureMargin = 20D;
            if (remainingHeight < h + secureMargin) {
                page = new CalendarItemPage();
                page.setPageIndex(pageIndex);
                showDate = true;
                remainingHeight = pf.getImageableHeight() - getTitleHeight();
                this.pages.add(page);
                pageIndex++;

            }
            if (showDate) {
                g.setFont(getHourFont(item));
                h += g.getFontMetrics().getHeight();
            }
            remainingHeight -= h;

            page.add(item);
            page.addHeight(Double.valueOf(h));
            page.addShowDate(showDate);
        }

    }

    public int getHourColumnWidth() {
        return 90;
    }

    public int getTitleHeight() {
        return 40;
    }

    private double getPrintHeight(Graphics g, PageFormat pf, JCalendarItem item) {
        double heigth = 0;
        int maxWidth = (int) pf.getImageableWidth() - getHourColumnWidth() - getMarginRight();
        // Line 1
        g.setFont(this.getLine1Font(item));
        int l1 = LayoutUtils.wrap(getLine1Text(item), g.getFontMetrics(), maxWidth).size();
        heigth += l1 * g.getFontMetrics().getHeight();
        // Line 2
        g.setFont(this.getLine2Font(item));
        int l2 = LayoutUtils.wrap(getLine2Text(item), g.getFontMetrics(), maxWidth).size();
        heigth += l2 * g.getFontMetrics().getHeight();
        return heigth;
    }

    public List<CalendarItemPage> getPages() {
        return pages;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                final JFrame f = new JFrame("Printing Pagination Example");
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                final JButton printButton = new JButton("Print test pages");
                printButton.addActionListener(new ActionListener() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        PrinterJob job = PrinterJob.getPrinterJob();
                        List<JCalendarItem> cItems = new ArrayList<JCalendarItem>();
                        Calendar c = Calendar.getInstance();
                        Flag.register(new Flag("warning", null, "Warning", "A default warning"));
                        for (int i = 0; i < 50; i++) {
                            JCalendarItem item = new JCalendarItem();
                            item.setSummary("Item " + i);
                            StringBuilder d = new StringBuilder();
                            d.append("Description");
                            for (int j = 0; j < i; j++) {
                                if (i % 2 == 0)
                                    d.append(" Hello");
                                else
                                    d.append(" Wo");
                            }
                            d.append("END");
                            if (i % 6 == 0) {
                                item.addFlag(Flag.getFlag("warning"));
                            }
                            if (i != 5) {
                                item.setDescription(d.toString());
                            } else {
                                item.setDescription(
                                        "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.");
                            }
                            item.setDtStart(c);
                            c.add(Calendar.HOUR_OF_DAY, 1);
                            item.setDtEnd(c);
                            c.add(Calendar.HOUR_OF_DAY, 1);
                            cItems.add(item);
                        }
                        final PrintRequestAttributeSet printAttributes = new HashPrintRequestAttributeSet();
                        printAttributes.add(PrintQuality.HIGH);
                        job.setPrintable(new CalendarItemPrinter("OpenConcerto", cItems, job.getPageFormat(printAttributes)));
                        boolean ok = job.printDialog();
                        if (ok) {
                            try {
                                job.print();
                            } catch (PrinterException ex) {
                                /* The job did not successfully complete */
                                ex.printStackTrace();
                            }
                        }

                    }
                });
                f.add("Center", printButton);
                f.pack();
                f.setLocationRelativeTo(null);
                f.setVisible(true);
            }
        });
    }

    public List<JCalendarItem> getItems() {
        return this.items;
    }

    @Override
    public int getNumberOfPages() {
        if (this.pages == null) {
            BufferedImage offImage = new BufferedImage((int) calendarPageFormat.getHeight(), (int) calendarPageFormat.getWidth(), BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2 = offImage.createGraphics();
            computeLayout(g2, calendarPageFormat);
        }
        return this.pages.size();
    }

    @Override
    public PageFormat getPageFormat(int pageIndex) {
        return this.calendarPageFormat;
    }

    @Override
    public Printable getPrintable(int pageIndex) {
        final CalendarItemPage page = this.pages.get(pageIndex);
        return new Printable() {

            @Override
            public int print(Graphics graphics, PageFormat pageFormat, int i) throws PrinterException {
                final Graphics2D g2d = (Graphics2D) graphics;
                g2d.translate(calendarPageFormat.getImageableX(), calendarPageFormat.getImageableY());
                printPage(graphics, page);
                return PAGE_EXISTS;
            }
        };
    }
}