com.openbravo.pos.sales.JTicketLines.java Source code

Java tutorial

Introduction

Here is the source code for com.openbravo.pos.sales.JTicketLines.java

Source

//    Openbravo POS is a point of sales application designed for touch screens.
//    Copyright (C) 2008-2009 Openbravo, S.L.
//    http://www.openbravo.com/product/pos
//
//    This file is part of Openbravo POS.
//
//    Openbravo POS is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    Openbravo POS 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 General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with Openbravo POS.  If not, see <http://www.gnu.org/licenses/>.

package com.openbravo.pos.sales;

import com.openbravo.data.loader.LocalRes;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Map;

import javax.accessibility.Accessible;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.Scrollable;
import javax.swing.SwingUtilities;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.RowSorterListener;
import javax.swing.event.TableColumnModelListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.swing.text.html.parser.*;
import javax.swing.text.html.*;
import com.openbravo.pos.scripting.ScriptEngine;
import com.openbravo.pos.scripting.ScriptException;
import com.openbravo.pos.scripting.ScriptFactory;
import com.openbravo.pos.forms.AppLocal;
import com.openbravo.pos.forms.AppView;
import com.openbravo.pos.ticket.TicketLineInfo;
import com.openbravo.pos.util.PropertyUtil;

import javafx.scene.layout.Border;
import javafx.scene.layout.BorderStrokeStyle;

import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class JTicketLines extends javax.swing.JPanel {

    private static Logger logger = Logger.getLogger("com.openbravo.pos.sales.JTicketLines");

    private static SAXParser m_sp = null;

    private TicketTableModel m_jTableModel;

    private AppView m_App;

    private ListSelectionListener listDoubleClickListener;

    /** Creates new form JLinesTicket */
    public JTicketLines(AppView app, String propertyRowHeight, String propertyFontsize, String ticketline) {
        this.m_App = app;
        initComponents();

        m_jTicketTable.m_App = app;
        m_jTicketTable.propertyRowHeight = propertyRowHeight;

        ColumnTicket[] acolumns = new ColumnTicket[0];

        if (ticketline != null) {
            try {
                if (m_sp == null) {
                    SAXParserFactory spf = SAXParserFactory.newInstance();
                    m_sp = spf.newSAXParser();
                }
                ColumnsHandler columnshandler = new ColumnsHandler();
                m_sp.parse(new InputSource(new StringReader(ticketline)), columnshandler);
                acolumns = columnshandler.getColumns();

            } catch (ParserConfigurationException ePC) {
                logger.log(Level.WARNING, LocalRes.getIntString("exception.parserconfig"), ePC);
            } catch (SAXException eSAX) {
                logger.log(Level.WARNING, LocalRes.getIntString("exception.xmlfile"), eSAX);
            } catch (IOException eIO) {
                logger.log(Level.WARNING, LocalRes.getIntString("exception.iofile"), eIO);
            }
        }

        Map<String, Integer> widths = PropertyUtil.getTicketLineWidths(m_App);
        for (ColumnTicket acolumn : acolumns) {
            Integer width = widths.get(acolumn.name);
            if (width == null) {
                continue;
            }
            acolumn.width = width;
        }

        m_jTableModel = new TicketTableModel(acolumns);
        m_jTicketTable.setModel(m_jTableModel);

        m_jTicketTable.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
        TableColumnModel jColumns = m_jTicketTable.getColumnModel();
        for (int i = 0; i < acolumns.length; i++) {
            jColumns.getColumn(i).setPreferredWidth(acolumns[i].width);
            jColumns.getColumn(i).setResizable(true);
        }

        PropertyUtil.ScaleScrollbar(m_App, m_jScrollTableTicket);

        m_jTicketTable.getTableHeader().setReorderingAllowed(false);
        // m_jTicketTable.setDefaultRenderer(Object.class, new
        // TicketCellRenderer(app, acolumns, propertyFontsize));
        m_jTicketTable.setDefaultRenderer(Object.class,
                new RowHeightCellRenderer(app, acolumns, propertyFontsize, propertyRowHeight));

        PropertyUtil.ScaleTableColumnFontsize(m_App, m_jTicketTable, "sales-tablecolumn-fontsize", "14");

        m_jTicketTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        m_jTicketTable.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent me) {
                JTable table = (JTable) me.getSource();
                Point p = me.getPoint();
                int row = table.rowAtPoint(p);
                if (me.getClickCount() == 2) {
                    // your valueChanged overridden method
                    listDoubleClickListener.valueChanged(new ListSelectionEvent(m_jTicketTable, row, row, false));
                }
            }
        });
        // reseteo la tabla...
        m_jTableModel.clear();
    }

    public void addListDoubleClickListener(ListSelectionListener l) {
        this.listDoubleClickListener = l;
    }

    public void removeListDoubleClickListener(ListSelectionListener l) {
        this.listDoubleClickListener = null;
    }

    public void addListSelectionListener(ListSelectionListener l) {
        m_jTicketTable.getSelectionModel().addListSelectionListener(l);
    }

    public void removeListSelectionListener(ListSelectionListener l) {
        m_jTicketTable.getSelectionModel().removeListSelectionListener(l);
    }

    public void clearTicketLines() {
        m_jTableModel.clear();
    }

    public void setTicketLine(int index, TicketLineInfo oLine) {

        m_jTableModel.setRow(index, oLine);
    }

    public void addTicketLine(TicketLineInfo oLine) {

        m_jTableModel.addRow(oLine);

        // Selecciono la que acabamos de anadir.
        setSelectedIndex(m_jTableModel.getRowCount() - 1);
    }

    public void insertTicketLine(int index, TicketLineInfo oLine) {

        m_jTableModel.insertRow(index, oLine);

        // Selecciono la que acabamos de anadir.
        setSelectedIndex(index);
    }

    public void removeTicketLine(int i) {

        m_jTableModel.removeRow(i);

        // Escojo una a seleccionar
        if (i >= m_jTableModel.getRowCount()) {
            i = m_jTableModel.getRowCount() - 1;
        }

        if ((i >= 0) && (i < m_jTableModel.getRowCount())) {
            // Solo seleccionamos si podemos.
            setSelectedIndex(i);
        }
    }

    public void setSelectedIndex(int i) {

        // Seleccionamos
        m_jTicketTable.getSelectionModel().setSelectionInterval(i, i);

        // Hacemos visible la seleccion.
        Rectangle oRect = m_jTicketTable.getCellRect(i, 0, true);
        m_jTicketTable.scrollRectToVisible(oRect);
    }

    public int getSelectedIndex() {
        return m_jTicketTable.getSelectionModel().getMinSelectionIndex(); // solo
        // sera
        // uno,
        // luego
        // no
        // importa...
    }

    public void selectionDown() {

        int i = m_jTicketTable.getSelectionModel().getMaxSelectionIndex();
        if (i < 0) {
            i = 0; // No hay ninguna seleccionada
        } else {
            i++;
            if (i >= m_jTableModel.getRowCount()) {
                i = m_jTableModel.getRowCount() - 1;
            }
        }

        if ((i >= 0) && (i < m_jTableModel.getRowCount())) {
            // Solo seleccionamos si podemos.

            setSelectedIndex(i);
        }
    }

    public void selectionUp() {

        int i = m_jTicketTable.getSelectionModel().getMinSelectionIndex();
        if (i < 0) {
            i = m_jTableModel.getRowCount() - 1; // No hay ninguna seleccionada
        } else {
            i--;
            if (i < 0) {
                i = 0;
            }
        }

        if ((i >= 0) && (i < m_jTableModel.getRowCount())) {
            // Solo seleccionamos si podemos.
            setSelectedIndex(i);
        }
    }

    public int getTableModelSize() {
        return this.getSelectedIndex();
    }

    private static class RowHeightCellRenderer extends JTextArea implements TableCellRenderer {
        private static final long serialVersionUID = 1L;
        private ColumnTicket[] m_acolumns;
        private AppView m_app;
        private String propertyFontsize;
        private String propertyRowHeight;

        public RowHeightCellRenderer(AppView app, ColumnTicket[] acolumns, String sPropertyFontSize,
                String sPropertyRowHeight) {
            m_acolumns = acolumns;
            m_app = app;
            propertyFontsize = sPropertyFontSize;
            propertyRowHeight = sPropertyRowHeight;
            this.setLineWrap(true);
            this.setWrapStyleWord(true);

            int fontsize = PropertyUtil.ScaleTextAreaFontsize(m_app, this, propertyFontsize, "25");
            int height = PropertyUtil.GetTableRowHeight(m_app, propertyRowHeight, "35");
            int margin = Math.abs(height - fontsize) / 2;
            this.setMargin(new Insets(margin, 0, margin, 0));
        }

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                boolean hasFocus, int row, int column) {

            if (value != null) {

                String textAll = value.toString().replace("<html>", "").replace("<br>", "\\n")
                        .replace("<br/>", "\\n").replace("<i>", "").replace("</i>", "").replace("&nbsp;", " ");
                String[] lines = textAll.split("\\\\n");

                StringBuilder sb = new StringBuilder();
                for (String line : lines) {
                    if (line != null && !line.trim().equals("")) {
                        if (sb.length() > 0)
                            sb.append('\n');

                        sb.append(StringEscapeUtils.unescapeXml(line.trim()));
                    }
                }

                setText(sb.toString());
            } else {
                setText("");
            }

            if (isSelected) {
                this.setBackground(table.getSelectionBackground());
                this.setForeground(table.getSelectionForeground());
            } else {
                this.setBackground(table.getBackground());
                this.setForeground(table.getForeground());
            }

            final int columnWidth = table.getColumnModel().getColumn(column).getWidth();
            final int rowHeight = table.getRowHeight(row);
            this.setSize(columnWidth, rowHeight);

            this.validate();

            return this;
        }
    }

    private static class TicketCellRenderer extends DefaultTableCellRenderer {

        private ColumnTicket[] m_acolumns;
        private AppView m_app;
        private String propertyFontsize;
        private String propertyRowHeight;

        public TicketCellRenderer(AppView app, ColumnTicket[] acolumns, String sPropertyFontSize) {
            m_acolumns = acolumns;
            m_app = app;
            propertyFontsize = sPropertyFontSize;
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                boolean hasFocus, int row, int column) {
            JLabel aux = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row,
                    column);
            aux.setVerticalAlignment(javax.swing.SwingConstants.CENTER);
            aux.setHorizontalAlignment(m_acolumns[column].align);

            PropertyUtil.ScaleTableLabelFontsize(m_app, aux, propertyFontsize, "25");

            return aux;
        }
    }

    private static class TicketTableModel extends AbstractTableModel {

        // private AppView m_App;
        private ColumnTicket[] m_acolumns;
        private ArrayList m_rows = new ArrayList();

        public TicketTableModel(ColumnTicket[] acolumns) {
            m_acolumns = acolumns;
        }

        public ColumnTicket[] getColumnTickets() {
            return this.m_acolumns;
        }

        public int getRowCount() {
            return m_rows.size();
        }

        public int getColumnCount() {
            return m_acolumns.length;
        }

        @Override
        public String getColumnName(int column) {
            return AppLocal.getIntString(m_acolumns[column].name);
            // return m_acolumns[column].name;
        }

        public Object getValueAt(int row, int column) {
            return ((String[]) m_rows.get(row))[column];
        }

        @Override
        public boolean isCellEditable(int row, int column) {
            return false;
        }

        @Override
        public void fireTableRowsInserted(int firstRow, int lastRow) {
            super.fireTableRowsInserted(firstRow, lastRow);
        }

        @Override
        public void fireTableCellUpdated(int row, int column) {
            super.fireTableCellUpdated(row, column);
        }

        @Override
        public void fireTableRowsDeleted(int firstRow, int lastRow) {
            super.fireTableRowsDeleted(firstRow, lastRow);
        }

        public void clear() {
            int old = getRowCount();
            if (old > 0) {
                m_rows.clear();
                fireTableRowsDeleted(0, old - 1);
            }
        }

        public void setRow(int index, TicketLineInfo oLine) {

            String[] row = (String[]) m_rows.get(index);
            for (int i = 0; i < m_acolumns.length; i++) {
                try {
                    ScriptEngine script = ScriptFactory.getScriptEngine(ScriptFactory.VELOCITY);
                    script.put("ticketline", oLine);
                    row[i] = script.eval(m_acolumns[i].value).toString();
                } catch (ScriptException e) {
                    row[i] = null;
                }
                fireTableCellUpdated(index, i);
            }
        }

        public void addRow(TicketLineInfo oLine) {

            insertRow(m_rows.size(), oLine);
        }

        public void insertRow(int index, TicketLineInfo oLine) {

            String[] row = new String[m_acolumns.length];
            for (int i = 0; i < m_acolumns.length; i++) {
                try {
                    ScriptEngine script = ScriptFactory.getScriptEngine(ScriptFactory.VELOCITY);
                    script.put("ticketline", oLine);
                    row[i] = script.eval(m_acolumns[i].value).toString();
                } catch (ScriptException e) {
                    row[i] = null;
                }
            }

            m_rows.add(index, row);
            fireTableRowsInserted(index, index);
        }

        public void removeRow(int row) {
            m_rows.remove(row);
            fireTableRowsDeleted(row, row);
        }
    }

    private static class ColumnsHandler extends DefaultHandler {

        private ArrayList m_columns = null;

        public ColumnTicket[] getColumns() {
            return (ColumnTicket[]) m_columns.toArray(new ColumnTicket[m_columns.size()]);
        }

        @Override
        public void startDocument() throws SAXException {
            m_columns = new ArrayList();
        }

        @Override
        public void endDocument() throws SAXException {
        }

        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes)
                throws SAXException {
            if ("column".equals(qName)) {
                ColumnTicket c = new ColumnTicket();
                c.name = attributes.getValue("name");
                c.width = Integer.parseInt(attributes.getValue("width"));
                String sAlign = attributes.getValue("align");
                if ("right".equals(sAlign)) {
                    c.align = javax.swing.SwingConstants.RIGHT;
                } else if ("center".equals(sAlign)) {
                    c.align = javax.swing.SwingConstants.CENTER;
                } else {
                    c.align = javax.swing.SwingConstants.LEFT;
                }
                c.value = attributes.getValue("value");
                m_columns.add(c);
            }
        }

        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
        }

        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
        }
    }

    private static class ColumnTicket {
        public String name;
        public int width;
        public int align;
        public String value;
    }

    public class JTableEx extends JTable {
        public AppView m_App;
        public String propertyRowHeight;

        @Override
        public void tableChanged(TableModelEvent e) {
            super.tableChanged(e);

            /*
             * if (m_App != null && propertyRowHeight != null && e.getLastRow()
             * >= 0 && (e.getType() == TableModelEvent.UPDATE || e.getType() ==
             * TableModelEvent.INSERT)) {
             * 
             * for (int i = 0; i < this.getModel().getRowCount(); i++) { Object
             * val = this.getModel().getValueAt(i, 0);
             * //PropertyUtil.ScaleTableRowheight(m_App, this, i,
             * getValueLines(val != null ? val.toString() : ""), //
             * propertyRowHeight, "35");
             * 
             * } }
             */

            final int first;
            final int last;
            if (e == null || e.getFirstRow() == TableModelEvent.HEADER_ROW) {
                // assume everything changed
                first = 0;
                last = this.getModel().getRowCount();
            } else {
                first = e.getFirstRow();
                last = e.getLastRow() + 1;
            }
            // GUI-Changes should be done through the EventDispatchThread which
            // ensures all pending events were processed
            // Also this way nobody will change the text of our
            // RowHeightCellRenderer because a cell is to be rendered
            if (SwingUtilities.isEventDispatchThread()) {
                updateRowHeights(first, last);
            } else {
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        updateRowHeights(first, last);
                    }
                });
            }

        }

        private void updateRowHeights(final int first, final int last) {
            /*
             * Auto adjust the height of rows in a JTable. The only way to know
             * the row height for sure is to render each cell to determine the
             * rendered height. After your table is populated with data you can
             * do:
             *
             */
            for (int row = first; row < last; row++) {
                int rowHeight = 20;
                if (this.getRowCount() >= row + 1) {
                    for (int column = 0; column < this.getColumnCount(); column++) {
                        Component comp = this.prepareRenderer(this.getCellRenderer(row, column), row, column);
                        rowHeight = Math.max(rowHeight, comp.getPreferredSize().height);
                    }
                    if (rowHeight != this.getRowHeight(row)) {
                        this.setRowHeight(row, rowHeight);
                    }
                }
            }

        }

        private int getValueLines(String val) {
            int multiply = 1;
            String[] parts = val.split("\n");
            if (parts.length <= 1)
                parts = val.split("<br/>");
            if (parts.length <= 1)
                parts = val.split("<br>");

            if (parts.length > 1) {
                for (int i = 1; i < parts.length; i++) {
                    multiply++;
                }
            }

            return multiply;
        }

    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc=" Generated Code
    // ">//GEN-BEGIN:initComponents
    private void initComponents() {
        m_jScrollTableTicket = new javax.swing.JScrollPane();
        m_jTicketTable = new JTableEx();

        setLayout(new java.awt.BorderLayout());

        m_jScrollTableTicket
                .setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        m_jScrollTableTicket.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        m_jTicketTable.setFocusable(false);
        m_jTicketTable.setIntercellSpacing(new java.awt.Dimension(0, 1));
        m_jTicketTable.setRequestFocusEnabled(false);
        m_jTicketTable.setShowVerticalLines(false);
        m_jScrollTableTicket.setViewportView(m_jTicketTable);

        add(m_jScrollTableTicket, java.awt.BorderLayout.CENTER);

    }// </editor-fold>//GEN-END:initComponents

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JScrollPane m_jScrollTableTicket;
    private JTableEx m_jTicketTable;
    // End of variables declaration//GEN-END:variables

}