Java tutorial
/* * @(#)InvoiceView.java 2.15.0 13/09/17 * * Copyright (c) 1999-2017 Musiques Tangentes. All Rights Reserved. * * This file is part of Algem. * Algem is free software: you can redistribute it and/or modify it * under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Algem is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Algem. If not, see <http://www.gnu.org/licenses/>. * */ package net.algem.billing; import com.itextpdf.text.Document; import com.itextpdf.text.DocumentException; import com.itextpdf.text.PageSize; import com.itextpdf.text.pdf.PdfContentByte; import com.itextpdf.text.pdf.PdfWriter; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GridBagLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.print.PageFormat; import java.awt.print.Printable; import java.awt.print.PrinterException; import java.awt.print.PrinterJob; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.sql.SQLException; import java.text.NumberFormat; import java.text.ParseException; import java.util.Collection; import java.util.List; import java.util.Vector; import javax.print.attribute.standard.MediaSizeName; import javax.print.attribute.standard.OrientationRequested; import javax.swing.JFormattedTextField; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import net.algem.accounting.AccountUtil; import net.algem.accounting.OrderLine; import net.algem.config.PageTemplate; import net.algem.config.PageTemplateIO; import net.algem.contact.Address; import net.algem.contact.Contact; import net.algem.contact.ContactIO; import net.algem.contact.Person; import net.algem.edition.*; import net.algem.planning.DateFr; import net.algem.planning.DateFrField; import net.algem.room.EstabChoice; import net.algem.room.Establishment; import net.algem.room.EstablishmentIO; import net.algem.util.*; import net.algem.util.event.CancelEvent; import net.algem.util.event.GemEvent; import net.algem.util.event.GemEventListener; import net.algem.util.model.Model; import net.algem.util.module.GemDesktop; import net.algem.util.ui.*; /** * Invoice / quotation view. * * @author <a href="mailto:jmg@musiques-tangentes.asso.fr">Jean-Marc Gobat</a> * @version 2.15.0 * @since 2.3.a 07/02/12 */ public class InvoiceView extends GemPanel implements ActionListener, GemEventListener, Printable { public static final int MARGIN = ImageUtil.mmToPoints(15); private final static Font sans = new Font(Font.SANS_SERIF, Font.PLAIN, 8); private final static Font serif = new Font(Font.SERIF, Font.PLAIN, 9); private GemField invoiceId; private GemField invoiceLabel; private DateFrField date; private GemField ref; private EstabChoice estab; private GemField payerName; private GemNumericField payerId; private GemField memberName; private GemNumericField issuerId; private GemField issuerName; private JFormattedTextField downPayment; private JFormattedTextField totalET; private JFormattedTextField totalATI; private JFormattedTextField net; private ItemListCtrl itemList; private Quote invoice; private final DataCache dataCache; private final DataConnection dc; private final GemDesktop desktop; private GemButton btAdd; private GemButton btModify; private GemButton btDelete; private InvoiceItemSearchCtrl browser; private NumberFormat nf; private final BillingService service; private Collection<OrderLine> orderLines; private boolean isInvoice; private PdfHandler pdfHandler; public InvoiceView(GemDesktop desktop, BillingService service) { this.desktop = desktop; this.dataCache = desktop.getDataCache(); this.dc = DataCache.getDataConnection(); this.service = service; pdfHandler = new PdfHandler(new PageTemplateIO(dc)); init(); } private void init() { GemPanel head = new GemPanel(new GridBagLayout()); GridBagHelper gb = new GridBagHelper(head); invoiceId = new GemField(6); invoiceId.setMinimumSize(new Dimension(65, invoiceId.getPreferredSize().height)); invoiceId.setCaretPosition(0); invoiceId.setEditable(false); invoiceLabel = new GemField(25); invoiceLabel.setMinimumSize(new Dimension(250, invoiceLabel.getPreferredSize().height)); date = new DateFrField(); ref = new GemField(15); ref.setMinimumSize(new Dimension(150, ref.getPreferredSize().height)); estab = new EstabChoice(dataCache.getList(Model.Establishment)); payerId = new GemNumericField(5); payerId.setMinimumSize(new Dimension(50, payerId.getPreferredSize().height)); payerId.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try { int id = Integer.parseInt(payerId.getText()); Person p = (Person) DataCache.findId(id, Model.Person); String org = p.getOrganization() != null ? p.getOrganization().getCompanyName() : null; payerName.setText(org != null && org.length() > 0 ? org : p.getFirstnameName()); } catch (Exception ex) { GemLogger.log(ex.getMessage()); } } }); payerName = new GemField(20); payerName.setMinimumSize(new Dimension(200, payerName.getPreferredSize().height)); payerName.setEditable(false); memberName = new GemField(20); memberName.setMinimumSize(new Dimension(200, memberName.getPreferredSize().height)); memberName.setEditable(false); nf = AccountUtil.getDefaultCurrencyFormat(); downPayment = new JFormattedTextField(nf); downPayment.setColumns(10); downPayment.getDocument().addDocumentListener(new DownPaymentListener()); totalET = new JFormattedTextField(nf); totalET.setColumns(10); totalET.setEditable(false); totalATI = new JFormattedTextField(nf); totalATI.setColumns(10); totalATI.setFont(getFont().deriveFont(Font.BOLD)); totalATI.setEditable(false); net = new JFormattedTextField(nf); net.setColumns(10); net.setFont(getFont().deriveFont(Font.BOLD)); net.setEditable(false); itemList = new ItemListCtrl(new InvoiceItemTableModel(), false); gb.add(new GemLabel(BundleUtil.getLabel("Number.abbrev.label")), 0, 0, 1, 1, GridBagHelper.WEST); gb.add(invoiceId, 1, 0, 1, 1); gb.add(new GemLabel(BundleUtil.getLabel("Invoice.description.label")), 2, 0, 1, 1, GridBagHelper.WEST); gb.add(invoiceLabel, 3, 0, 1, 1); gb.add(new GemLabel(BundleUtil.getLabel("Date.label")), 4, 0, 1, 1, GridBagHelper.WEST); gb.add(date, 5, 0, 1, 1); gb.add(new GemLabel(BundleUtil.getLabel("Invoice.reference.label")), 6, 0, 1, 1, GridBagHelper.WEST); gb.add(ref, 7, 0, 1, 1); gb.add(new GemLabel(BundleUtil.getLabel("Payer.label")), 0, 1, 1, 1, GridBagHelper.WEST); gb.add(payerId, 1, 1, 1, 1, GridBagHelper.WEST); gb.add(payerName, 2, 1, 2, 1, GridBagHelper.WEST); gb.add(new GemLabel(BundleUtil.getLabel("Member.label")), 4, 1, 1, 1, GridBagHelper.WEST); gb.add(memberName, 5, 1, 3, 1, GridBagHelper.WEST); issuerId = new GemNumericField(5); issuerId.setMinimumSize(new Dimension(50, issuerId.getPreferredSize().height)); issuerId.setEditable(false); issuerName = new GemField(20); issuerName.setMinimumSize(new Dimension(200, issuerName.getPreferredSize().height)); issuerName.setEditable(false); gb.add(new GemLabel(BundleUtil.getLabel("Issuer.label")), 0, 2, 1, 1, GridBagHelper.WEST); gb.add(issuerId, 1, 2, 2, 1, GridBagHelper.WEST); gb.add(issuerName, 2, 2, 2, 1, GridBagHelper.WEST); gb.add(new GemLabel(BundleUtil.getLabel("Establishment.label").substring(0, 5)), 4, 2, 1, 1, GridBagHelper.WEST); gb.add(estab, 5, 2, 3, 1, GridBagHelper.WEST); GemPanel buttons = new GemPanel(new GridLayout(1, 3)); btDelete = new GemButton(GemCommand.DELETE_CMD); btDelete.setToolTipText(BundleUtil.getLabel("Invoice.item.delete.tip")); btDelete.addActionListener(this); btModify = new GemButton(GemCommand.MODIFY_CMD); btModify.setToolTipText(BundleUtil.getLabel("Invoice.item.modify.tip")); btModify.addActionListener(this); btAdd = new GemButton(GemCommand.ADD_CMD); btAdd.setToolTipText(BundleUtil.getLabel("Invoice.item.add.tip")); btAdd.addActionListener(this); buttons.add(btDelete); buttons.add(btModify); buttons.add(btAdd); GemPanel body = new GemPanel(new BorderLayout()); body.add(itemList, BorderLayout.CENTER); GemPanel footer = new GemPanel(new BorderLayout()); GemPanel total = new GemPanel(); total.add(new GemLabel(BundleUtil.getLabel("Invoice.down.payment.label"))); total.add(downPayment); total.add(new GemLabel(BundleUtil.getLabel("Invoice.et.label"))); total.add(totalET); total.add(new GemLabel(BundleUtil.getLabel("Invoice.ati.label"))); total.add(totalATI); total.add(new GemLabel(BundleUtil.getLabel("Invoice.net.label"))); total.add(net); footer.add(buttons, BorderLayout.NORTH); footer.add(total, BorderLayout.SOUTH); setLayout(new BorderLayout()); add(head, BorderLayout.NORTH); add(body, BorderLayout.CENTER); add(footer, BorderLayout.SOUTH); } public void setId(String n) { invoiceId.setText(n); invoiceId.setCaretPosition(0); if (invoice != null) { invoice.setNumber(n); } } /** * Sets the different field values. * * @param <Q> * @param quote * @param m member name * @param p payer name * @param i issuer name */ <Q extends Quote> void set(Q quote, String m, String p, String i) { if (quote == null) { return; } invoice = quote; isInvoice = quote.isInvoice(); invoiceId.setText(quote.getNumber()); invoiceId.setCaretPosition(0); invoiceLabel.setText(quote.getDescription()); invoiceLabel.setCaretPosition(0); date.setText(quote.getDate().toString()); ref.setText(quote.getReference()); estab.setKey(quote.getEstablishment()); payerId.setText(String.valueOf(quote.getPayer())); payerName.setText(p); memberName.setText(m); issuerId.setText(String.valueOf(quote.getIssuer())); issuerName.setText(i); if (quote.getItems() != null) { itemList.loadResult(new Vector<InvoiceItem>(quote.getItems())); } if (!isInvoice) { downPayment.setEditable(false); // TODO set payer editable } downPayment.setValue(quote.getDownPayment()); totalET.setValue(quote.getTotalET()); double ttc = quote.getTotalATI(); totalATI.setValue(ttc); net.setValue(Double.valueOf(ttc - quote.getDownPayment())); orderLines = quote.getOrderLines(); if (!isInvoice && !quote.isEditable()) { btDelete.setEnabled(false); btModify.setEnabled(false); btAdd.setEnabled(false); } else { btDelete.setEnabled(true); btModify.setEnabled(true); btAdd.setEnabled(true); } } /** * Retrieves the current quote/invoice (possibly updated). * * @return a quote/invoice */ Quote get() { Quote q; try { q = invoice.getClass().newInstance(); q.setNumber(invoiceId.getText()); //Quote inv = new Invoice(invoiceId.getText()); } catch (ReflectiveOperationException ex) { GemLogger.log(ex.getMessage()); q = new Invoice(invoiceId.getText()); } q.setDescription(invoiceLabel.getText()); q.setDate(new DateFr(date.getText())); q.setReference(ref.getText()); q.setEstablishment(estab.getKey()); try { q.setPayer(Integer.parseInt(payerId.getText())); } catch (NumberFormatException ex) { GemLogger.log(ex.getMessage()); } double a = ((Number) downPayment.getValue()).doubleValue(); q.setDownPayment(Math.abs(a)); q.setItems(getItems()); q.setOrderLines(orderLines); if (invoice != null) { // inv.setPayer(invoice.getPayer()); q.setMember(invoice.getMember()); q.setEstablishment(invoice.getEstablishment()); q.setIssuer(invoice.getIssuer()); q.setUser(invoice.getUser()); q.setCreditNote(invoice.isCreditNote()); } return q; } /** * Retrieves the different items (possibly updated). * * @return a collection of invoice items */ Collection<InvoiceItem> getItems() { return itemList.getData(); } @Override public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); try { if (GemCommand.ADD_CMD.equals(cmd)) { browser = new InvoiceItemSearchCtrl(desktop); browser.init(); browser.addGemEventListener(this); browser.addActionListener(this);// pour le bouton abandon du browser if (!desktop.hasModule(InvoiceItemSearchCtrl.INVOICE_ITEM_BROWSER_KEY)) { desktop.addPanel(InvoiceItemSearchCtrl.INVOICE_ITEM_BROWSER_KEY, browser); } } else if (GemCommand.MODIFY_CMD.equals(cmd)) { InvoiceItem selectedItem = itemList.getSelectedItem(); InvoiceItemEditor dlg = new InvoiceItemEditor(desktop, selectedItem, service); dlg.setVisible(true); if (dlg.hasChanged()) { OrderLine ol = selectedItem.getOrderLine(); InvoiceItem updatedItem = dlg.get(); // l'article modifier pourrait tre rfrenc dans un devis (on aurait cr une facture partir de ce devis) try { if (isInvoice && updatedItem.getItem() != null && QuoteIO.isQuotationItem(updatedItem.getItem().getId(), dc)) { if (!MessagePopup.confirm(this, MessageUtil.getMessage("existing.estimate.item"), BundleUtil.getLabel("Warning.label"))) { return; } } } catch (SQLException ex) { System.err.println(ex.getMessage()); } if (ol != null && ol.getId() > 0) { // if (ol != null && !AccountUtil.isRevenueAccount(ol.getAccount()) // && updatedItem.getQuantity() > 0.0f // && Math.abs(ol.getDoubleAmount()) != updatedItem.getTotal(true)) { MessagePopup.warning(this, MessageUtil.getMessage("invoice.item.modification.warning")); // modification des items dj pays if (ol.isPaid()) { if (!MessagePopup.confirm(this, MessageUtil.getMessage("invoice.item.modification.confirmation"), "")) { return; } } } update(updatedItem); postEvent(new CancelEvent()); } } else if (GemCommand.DELETE_CMD.equals(cmd)) { InvoiceItem item = itemList.getSelectedItem(); itemList.deleteRow(item); if (isInvoice) { MessagePopup.warning(this, MessageUtil.getMessage("invoice.item.suppression.warning")); // ((Invoice) invoice).getOrderLines().remove(item.getOrderLine()); orderLines.remove(item.getOrderLine()); } updateTotal(); } else if (GemCommand.CANCEL_CMD.equals(cmd)) { postEvent(new CancelEvent()); } } catch (IndexOutOfBoundsException ix) { MessagePopup.warning(this, MessageUtil.getMessage("no.line.selected")); } } @Override public void postEvent(GemEvent evt) { if (evt instanceof InvoiceItemCreateEvent) { add(((InvoiceItemCreateEvent) evt).getArticleFacture()); } else if (evt instanceof CancelEvent) { if (browser != null) { desktop.removeGemEventListener((GemEventListener) browser); } desktop.removeModule(InvoiceItemSearchCtrl.INVOICE_ITEM_BROWSER_KEY); } } /** * Reset the fields. */ void reset() { invoice = null; itemList = null; invoiceLabel.setText(null); date.set(new DateFr()); estab.setSelectedIndex(0); totalET.setValue(null); totalATI.setValue(null); memberName.setText(null); payerName.setText(null); issuerName.setText(null); downPayment.setValue(null); ref.setText(null); } /** * Invoice item modification. * * @param a the item */ private void update(InvoiceItem a) { if (a == null) { return; } itemList.updateRow(a); updateTotal(); } /** * Adds an item. * * @param a the item */ private void add(InvoiceItem a) { if (a == null) { return; } itemList.addRow(a); updateTotal(); } /** * Updates total in the main view. */ private void updateTotal() { invoice.setItems(getItems()); totalET.setValue(invoice.getTotalET()); double ttc = invoice.getTotalATI(); totalATI.setValue(ttc); net.setValue(ttc - ((Number) downPayment.getValue()).doubleValue()); } @Override public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException { if (pageIndex > 1) { // We have only 2 pages, and 'page' is zero-based return NO_SUCH_PAGE; } Quote quote = get(); String genericLabel = invoice.getClass() == Quote.class ? BundleUtil.getLabel("Quotation.label") : BundleUtil.getLabel("Invoice.label"); int left = ImageUtil.mmToPoints(110); int top = ImageUtil.mmToPoints(50); int bottom = ImageUtil.mmToPoints(297 - 20);// hauteur de page - 20 mm de marge int margin = ImageUtil.mmToPoints(15); Font defaultFont = g.getFont(); g.setFont(serif); int itemsHeight = ((g.getFontMetrics().getHeight() * 2) * (quote.getItems().size() - 1)); // average int footerHeight = InvoiceFooterEditor.getFooter().size() * 10; int maxHeight = top + 160 + 20 + itemsHeight + ImageUtil.mmToPoints(50); if (pageIndex == 1) { if (maxHeight > (bottom - footerHeight)) { g.setFont(serif.deriveFont(Font.ITALIC)); g.drawString("(page 2)", margin, top + 90); g.setFont(serif); g.drawString(genericLabel + " : " + quote.getNumber(), margin, top + 100); // description g.drawString(BundleUtil.getLabel("Invoice.description.label") + " : " + quote.getDescription(), margin, top + 140); // pied tableau new InvoiceFooterElement(margin, top + 160, quote).draw(g); // infos lgales drawFooter(g, margin, bottom); return PAGE_EXISTS; } else { return NO_SUCH_PAGE; } } drawHeader(g, defaultFont, quote, genericLabel, top, left, margin); int tablebottom = drawContent(g, quote, top, margin); if (maxHeight > (bottom - footerHeight)) { g.setFont(sans.deriveFont(Font.ITALIC)); g.drawString(MessageUtil.getMessage("see.back.page.label"), margin, tablebottom + 10); drawFooter(g, margin, bottom); return PAGE_EXISTS; } // pied tableau new InvoiceFooterElement(margin, tablebottom + 20, quote).draw(g); // infos lgales drawFooter(g, margin, bottom); return PAGE_EXISTS; } private void drawPdf(Document document, PdfWriter writer) { PdfContentByte cb = writer.getDirectContent(); Graphics2D g = cb.createGraphics(document.getPageSize().getWidth(), document.getPageSize().getHeight()); Quote quote = get(); String genericLabel = invoice.getClass() == Quote.class ? BundleUtil.getLabel("Quotation.label") : BundleUtil.getLabel("Invoice.label"); int left = ImageUtil.mmToPoints(110); int top = ImageUtil.mmToPoints(50); int bottom = ImageUtil.mmToPoints(297 - 20);// hauteur de page - 20 mm de marge int margin = ImageUtil.mmToPoints(15); Font defaultFont = g.getFont(); g.setFont(serif); int itemsHeight = ((g.getFontMetrics().getHeight() * 2) * (quote.getItems().size() - 1)); // average int footerHeight = InvoiceFooterEditor.getFooter().size() * 10; int maxHeight = top + 160 + 20 + itemsHeight + ImageUtil.mmToPoints(50); drawHeader(g, defaultFont, quote, genericLabel, top, left, margin); int tablebottom = drawContent(g, quote, top, margin); if (maxHeight > (bottom - footerHeight)) { g.setFont(serif.deriveFont(Font.ITALIC)); g.drawString(MessageUtil.getMessage("see.back.page.label"), margin, tablebottom + 10); drawFooter(g, margin, bottom); //IMPORTANT g.dispose(); document.newPage(); g = cb.createGraphics(document.getPageSize().getWidth(), document.getPageSize().getHeight()); g.setFont(serif.deriveFont(Font.ITALIC)); g.drawString("(page 2)", margin, top + 90); g.setFont(serif); g.drawString(genericLabel + " : " + quote.getNumber(), margin, top + 100); // description g.drawString(BundleUtil.getLabel("Invoice.description.label") + " : " + quote.getDescription(), margin, top + 140); // pied tableau new InvoiceFooterElement(margin, top + 160, quote).draw(g); // infos lgales drawFooter(g, margin, bottom); g.dispose(); } else { // pied tableau new InvoiceFooterElement(margin, tablebottom + 20, quote).draw(g); // infos lgales drawFooter(g, margin, bottom); g.dispose(); } } /** * Prints the invoice. */ void print() { if (invoice.getClass() != Quote.class && (invoice.getNumber() == null || invoice.getNumber().isEmpty())) { MessagePopup.warning(this, MessageUtil.getMessage("invoice.printing.warning")); return; } PrinterJob job = PrinterJob.getPrinterJob(); job.setPrintable(this); try { if (job.printDialog()) { job.print(FileUtil.getAttributeSet(MediaSizeName.ISO_A4, OrientationRequested.PORTRAIT)); } } catch (PrinterException e) { GemLogger.logException(e); } } void preview() { if (isNotSaved()) { MessagePopup.warning(this, MessageUtil.getMessage("invoice.printing.warning")); } else { try { createPdf(); } catch (IOException | DocumentException ex) { GemLogger.logException(ex); } } } private <Q extends Quote> boolean isNotSaved() { return invoice.getClass() != Quote.class && (invoice.getNumber() == null || invoice.getNumber().isEmpty()); } private void createPdf() throws IOException, DocumentException { Document document = new Document(PageSize.A4); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); PdfWriter writer = PdfWriter.getInstance(document, outputStream); document.open(); drawPdf(document, writer); document.close(); String prefix = invoice.getClass() == Quote.class ? BundleUtil.getLabel("Quotation.label") : BundleUtil.getLabel("Invoice.label"); String tmpFileName = prefix.toLowerCase() + "-" + invoice.getNumber() + "_"; pdfHandler.createPdf(tmpFileName, outputStream, PageTemplate.QUOTE_PAGE_MODEL); } /** * Search establishment name. * * @param q quote/invoice * @return a name or null */ private String getEstabName(Quote q) { try { Establishment e = EstablishmentIO.findId(q.getEstablishment(), dc); return e == null ? "" : e.getName(); } catch (SQLException ex) { GemLogger.logException(ex); return ""; } } private void drawContactName(Graphics g, Contact c, int x, int y) { g.setFont(new Font(Font.SERIF, Font.PLAIN, 10)); if (c != null) { String org = c.getCompanyName(); if (org != null) { g.drawString(org, x, y - 10); } else { g.drawString(c.toString(), x, y); } } } private void drawHeader(Graphics g, Font font, Quote quote, String label, int top, int left, int margin) { Contact c = ContactIO.findId(quote.getPayer(), dc); Address a = null; if (c != null) { a = c.getAddress(); } //IdentityElement name = new IdentityElement(c, left, top + 10); AddressElement address = new InvoiceAddressElement(a, left, top + 30); // nom et adresse g.setFont(font); //name.draw(g); drawContactName(g, c, left, top + 10); address.draw(g); g.setFont(serif); // numro invoice g.drawString(label + " : " + quote.getNumber(), margin, top + 100); // nom tablissement g.drawString(getEstabName(quote) + ", le " + quote.getDate(), left, top + 85); // rfrence g.drawString(BundleUtil.getLabel("Reference.abbreviation.label") + " : " + quote.getReference(), left, top + 100); // description g.drawString(BundleUtil.getLabel("Invoice.description.label") + " : " + quote.getDescription(), margin, top + 140); } private int drawContent(Graphics g, Quote quote, int top, int margin) { int tableY = top + 160; int tabletop = tableY; //int end = margin + InvoiceItemElement.TABLE_WIDTH; // entete tableau new InvoiceHeaderElement(margin, tableY).draw(g); g.drawLine(margin, tableY + 20, margin + InvoiceItemElement.TABLE_WIDTH, tableY + 20); // items tableY += 5; for (InvoiceItem invoiceItem : quote.getItems()) { InvoiceItemElement item = new InvoiceItemElement(margin, tableY + 20, invoiceItem); item.draw(g); tableY = tableY + 20 + item.getOffset(); } tableY += 5; int tablebottom = tableY + 20; // encadrement du tableau d'items g.drawRect(margin, tabletop, InvoiceItemElement.TABLE_WIDTH, tablebottom - tabletop); // lignes sparatrices verticales des colonnes g.drawLine(InvoiceItemElement.xColPrice, tabletop, InvoiceItemElement.xColPrice, tablebottom); // colonne prix g.drawLine(InvoiceItemElement.xColVAT, tabletop, InvoiceItemElement.xColVAT, tablebottom); // colonne tva g.drawLine(InvoiceItemElement.xColQty, tabletop, InvoiceItemElement.xColQty, tablebottom); // colonne quantit g.drawLine(InvoiceItemElement.xColHT, tabletop, InvoiceItemElement.xColHT, tablebottom); // colonne total HT return tablebottom; } /** * Prints footer. * * @param g graphics * @param x horizontal position * @param y vertical position */ private void drawFooter(Graphics g, int x, int y) { int yPos = y; List<String> lines = InvoiceFooterEditor.getFooter(); g.setFont(sans); // on commence par la dernire ligne afin de partir de la marge infrieure for (int i = lines.size() - 1; i >= 0; i--) { g.drawString(lines.get(i), x, yPos); yPos -= 10; } } class DownPaymentListener implements DocumentListener { @Override public void insertUpdate(DocumentEvent e) { this.changedUpdate(e); } @Override public void removeUpdate(DocumentEvent e) { this.changedUpdate(e); } @Override public void changedUpdate(DocumentEvent e) { String a = downPayment.getText(); double ac = 0.0; if (invoice != null && a != null && !a.isEmpty()) { try { ac = nf.parse(a).doubleValue(); } catch (ParseException ex) { System.err.println(ex.getMessage()); } net.setValue(invoice.getTotalATI() - Math.abs(ac)); } } } }