OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Rev 174 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 2011-2019 OpenConcerto, by ILM Informatique. All rights reserved.
 * 
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each file.
 */
 
 package org.openconcerto.erp.core.sales.pos.ui;

import org.openconcerto.erp.core.sales.pos.model.Article;
import org.openconcerto.erp.core.sales.pos.model.Categorie;
import org.openconcerto.ui.touch.ScrollableList;
import org.openconcerto.utils.QuickOrderedMap;
import org.openconcerto.utils.StringUtils;

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.math.BigDecimal;
import java.math.RoundingMode;

import javax.swing.JPanel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

public class ArticleSelector extends JPanel implements CaisseListener {
    private ArticleModel model;
    private ScrollableList list;
    private StatusBar comp;
    private CaisseControler controller;

    ArticleSelector(final CaisseControler controller) {
        this.controller = controller;
        this.controller.addCaisseListener(this);

        this.setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.gridx = 0;
        c.gridy = 0;
        c.weightx = 1;
        c.fill = GridBagConstraints.BOTH;
        this.comp = new StatusBar();
        this.comp.setLayout(new FlowLayout(FlowLayout.LEFT));
        this.comp.setTitle("Articles");
        final POSButton bSwitch = new POSButton("-");
        bSwitch.setForeground(Color.WHITE);
        bSwitch.setBackground(CaissePanel.DARK_BLUE);
        this.comp.add(bSwitch);
        this.add(this.comp, c);

        c.weighty = 1;
        c.gridy++;
        this.model = new ArticleModel();
        this.model.setCategorie(null);

        final Font f;
        if (controller.getPOSConf().getScreenWidth() < 1280) {
            f = new Font("Arial", Font.PLAIN, 18);
        } else {
            f = new Font("Arial", Font.PLAIN, 21);
        }

        this.list = new ScrollableList(this.model) {
            int maxStringWidth = 0;

            @Override
            public void paint(Graphics g) {

                if (this.maxStringWidth == 0) {
                    g.setFont(f);
                    int w = this.getWidth();
                    int priceWidth = (int) g.getFontMetrics(f).getStringBounds(getPrice(BigDecimal.valueOf(999)), g).getWidth();
                    int maxW = w - priceWidth - getLeftMargin();
                    String str = "a";
                    int strW;
                    do {
                        strW = (int) g.getFontMetrics(f).getStringBounds(str, g).getWidth();
                        str += "a";
                    } while (strW < maxW);

                    this.maxStringWidth = Math.max(1, str.length() - 1);

                }
                super.paint(g);
                g.setColor(Color.GRAY);
                g.drawLine(0, 0, 0, this.getHeight());
            }

            @Override
            public void paintCell(Graphics g, Object object, int index, boolean isSelected, int posY) {
                Article article = (Article) object;
                paintArticle(f, g, article, isSelected, posY, this.getWidth(), this.getCellHeight(), this.maxStringWidth, getLeftMargin(), false);

            }
        };

        this.list.setFixedCellHeight(64);
        this.list.setOpaque(true);
        this.add(this.list, c);
        this.list.addListSelectionListener(new ListSelectionListener() {

            @Override
            public void valueChanged(ListSelectionEvent e) {
                Object sel = ArticleSelector.this.list.getSelectedValue();
                if (sel != null && !e.getValueIsAdjusting()) {
                    Article article = (Article) sel;
                    controller.setArticleSelected(article);
                }

            }
        });

        this.list.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {

                Object sel = ArticleSelector.this.list.getSelectedValue();
                if (sel != null) {
                    int nb = e.getClickCount();
                    if (nb == 1) {
                        Article article = (Article) sel;
                        controller.addArticle(article);
                    } else if (nb > 1) {
                        Article article = (Article) sel;
                        controller.incrementArticle(article);
                        controller.setArticleSelected(article);
                    }
                }
            }
        });

        bSwitch.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                controller.switchListMode();

            }
        });
        this.comp.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                ArticleSelector.this.list.scrollToOffset(0);
            }
        });
    }

    public ArticleModel getModel() {
        return this.model;
    }

    @Override
    public void caisseStateChanged() {

        final Article articleSelected = this.controller.getArticleSelected();
        if (articleSelected == null) {
            this.list.clearSelection();
            return;
        }

        Object selectedValue = null;
        try {
            selectedValue = this.list.getSelectedValue();
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (!articleSelected.equals(selectedValue)) {
            Categorie c = articleSelected.getCategorie();
            this.model.setCategorie(c);
            this.list.setSelectedValue(articleSelected, true);
        }

    }

    public static void paintArticle(final Font f, Graphics g, Article article, boolean isSelected, int posY, int cellWidth, int cellHeight, int maxWidth, int leftMargin, boolean showCode) {

        g.setFont(f);

        if (isSelected) {
            g.setColor(new Color(232, 242, 254));
        } else {
            g.setColor(Color.WHITE);
        }
        g.fillRect(0, posY, cellWidth, cellHeight);

        //
        g.setColor(Color.GRAY);
        g.drawLine(0, posY + cellHeight - 1, cellWidth, posY + cellHeight - 1);

        if (isSelected) {
            g.setColor(Color.BLACK);
        } else {
            g.setColor(Color.GRAY);
        }
        ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        String label = article.getName();
        if (showCode && article.getCode() != null && !article.getCode().isEmpty()) {
            label += " [" + article.getCode() + "]";
        }
        StringBuilder declinaisons = null;
        QuickOrderedMap<String, String> decls = article.getDeclinaisons();
        if (decls != null && !decls.isEmpty()) {
            declinaisons = new StringBuilder();
            for (int i = 0; i < decls.size(); i++) {
                declinaisons.append(StringUtils.firstUpThenLow(decls.getKey(i)));
                declinaisons.append(": ");
                declinaisons.append(decls.getValue(i));
                declinaisons.append("  ");
            }
        }

        if (label.length() > maxWidth * 2) {
            label = label.substring(0, maxWidth * 2) + "...";
        }
        String label2 = null;
        if (label.length() > maxWidth) {
            String t = label.substring(0, maxWidth).trim();
            int lastSpace = t.lastIndexOf(' ');
            if (lastSpace <= 0) {
                lastSpace = maxWidth;
            }
            label2 = label.substring(lastSpace).trim();
            label = label.substring(0, lastSpace).trim();
            if (label2.length() > maxWidth) {
                label2 = label2.substring(0, maxWidth) + "...";
            }
        }
        if (declinaisons != null) {
            String textDeclinaisons = declinaisons.toString();
            if (label2 == null) {
                label2 = textDeclinaisons;
            } else {
                if (label2.length() + textDeclinaisons.length() > maxWidth) {
                    label2 = label2.substring(0, maxWidth - textDeclinaisons.length()) + "...";
                }
                label2 = label2 + " " + textDeclinaisons;
            }

        }

        final BigDecimal priceInCents = article.getPriceWithTax(BigDecimal.ONE);
        String euro = getPrice(priceInCents);

        int wEuro = (int) g.getFontMetrics().getStringBounds(euro, g).getWidth();
        if (label2 == null) {
            g.drawString(label, leftMargin, posY + 39);
        } else {
            g.drawString(label, leftMargin, posY + 26);
            g.drawString(label2, leftMargin, posY + 52);
        }

        if (isSelected) {
            g.setColor(new Color(232, 242, 254));
        } else {
            g.setColor(Color.WHITE);
        }
        g.fillRect(cellWidth - wEuro - 12, posY + 1, wEuro + 12, cellHeight - 2);

        // Price
        if (isSelected) {
            g.setColor(Color.BLACK);
        } else {
            g.setColor(Color.GRAY);
        }
        if (article.getSalesUnit() != null) {
            String unit = "/" + article.getSalesUnit();
            int wUnit = (int) g.getFontMetrics().getStringBounds(unit, g).getWidth();
            g.drawString(euro, cellWidth - 5 - wEuro, posY + 28);
            g.drawString(unit, cellWidth - 5 - wUnit, posY + 50);
        } else {
            g.drawString(euro, cellWidth - 5 - wEuro, posY + 39);
        }

    }

    public int getLeftMargin() {
        if (this.controller.getPOSConf().getScreenWidth() < 1280) {
            return 3;
        }
        return 10;
    }

    public static String getPrice(final BigDecimal price) {
        return TicketCellRenderer.centsToString(price.movePointRight(2).setScale(0, RoundingMode.HALF_UP).intValue()) + "€";
    }

}