// Openbravo POS is a point of sales application designed for touch screens.
// Copyright (C) 2007-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.catalog;
import com.openbravo.basic.BasicException;
import com.openbravo.data.gui.JMessageDialog;
import com.openbravo.data.gui.MessageInf;
import com.openbravo.format.Formats;
import com.openbravo.pos.forms.AppLocal;
import com.openbravo.pos.forms.AppView;
import com.openbravo.pos.forms.DataLogicSales;
import com.openbravo.pos.sales.PropertiesConfig;
import com.openbravo.pos.sales.TaxesLogic;
import com.openbravo.pos.ticket.CategoryInfo;
import com.openbravo.pos.ticket.ProductInfoExt;
import com.openbravo.pos.ticket.TaxInfo;
import com.openbravo.pos.util.ThumbNailBuilder;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import javax.swing.event.EventListenerList;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
/**
*
* @author adrianromero
* @author Andrey Svininykh <svininykh@gmail.com>
*/
public class JCatalog extends JPanel implements ListSelectionListener, CatalogSelector {
protected EventListenerList listeners = new EventListenerList();
private DataLogicSales m_dlSales;
private TaxesLogic taxeslogic;
private boolean pricevisible;
private boolean taxesincluded;
private boolean refvisible;
private boolean namevisible;
private boolean stockvisible;
// Set of Products panels
private Map<String, ProductInfoExt> m_productsset = new HashMap<String, ProductInfoExt>();
// Set of Categoriespanels
private Set<String> m_categoriesset = new HashSet<String>();
private ThumbNailBuilder tnbbutton;
private CategoryInfo showingcategory = null;
private LinkedList<CategoryInfo> subcategories;
private String s_DefProdCat;
private final int iTextFontSize;
private String s_DefLocation;
public JCatalog(DataLogicSales dlSales, PropertiesConfig panelconfig) {
m_dlSales = dlSales;
this.pricevisible = "true".equals(panelconfig.getProperty("pricevisible", "true"));
this.taxesincluded = "true".equals(panelconfig.getProperty("taxesincluded", "false"));
this.refvisible = "true".equals(panelconfig.getProperty("refvisible", "false"));
this.namevisible = "true".equals(panelconfig.getProperty("namevisible", "true"));
this.stockvisible = "true".equals(panelconfig.getProperty("stockvisible", "false"));
initComponents();
m_jPanelImageViewer.setVisible("true".equals(panelconfig.getProperty("imageviewer", "true")));
iTextFontSize = Integer.parseInt(panelconfig.getProperty("font-size", "12"));
tnbbutton = new ThumbNailBuilder(Integer.parseInt(panelconfig.getProperty("img-width", "64")),
Integer.parseInt(panelconfig.getProperty("img-height", "54")),
iTextFontSize,
"com/openbravo/images/package.png");
}
public Component getComponent() {
return this;
}
public void showCatalogPanel(String id) {
if (id == null) {
showRootCategoriesPanel();
} else {
showProductPanel(id);
}
}
@Override
public void loadCatalog(AppView app) throws BasicException {
// delete all categories panel
m_jProducts.removeAll();
m_productsset.clear();
m_categoriesset.clear();
showingcategory = null;
subcategories = new LinkedList();
// Load the taxes logic
taxeslogic = new TaxesLogic(m_dlSales.getTaxList().list());
s_DefProdCat = app.getDefaultProductCategory();
s_DefLocation = app.getInventoryLocation();
// Display catalog panel
showRootCategoriesPanel();
}
public void setComponentEnabled(boolean value) {
m_btnBackRoot.setEnabled(value);
m_jProducts.setEnabled(value);
synchronized (m_jProducts.getTreeLock()) {
int compCount = m_jProducts.getComponentCount();
for (int i = 0; i < compCount; i++) {
m_jProducts.getComponent(i).setEnabled(value);
}
}
this.setEnabled(value);
}
public void addActionListener(ActionListener l) {
listeners.add(ActionListener.class, l);
}
public void removeActionListener(ActionListener l) {
listeners.remove(ActionListener.class, l);
}
public void valueChanged(ListSelectionEvent evt) {
if (!evt.getValueIsAdjusting()) {
}
}
protected void fireSelectedProduct(ProductInfoExt prod) {
EventListener[] l = listeners.getListeners(ActionListener.class);
ActionEvent e = null;
for (int i = 0; i < l.length; i++) {
if (e == null) {
e = new ActionEvent(prod, ActionEvent.ACTION_PERFORMED, prod.getID());
}
((ActionListener) l[i]).actionPerformed(e);
}
if (prod.getImage() != null) {
m_jImage.setImage(prod.getImage());
} else {
m_jImage.setImage(null);
}
}
private void selectCategoryPanel(String catid) {
try {
// Load categories panel if not exists
if (!m_categoriesset.contains(catid)) {
JCatalogTab jcurrTab = new JCatalogTab();
jcurrTab.applyComponentOrientation(getComponentOrientation());
m_jProducts.add(jcurrTab, catid);
m_categoriesset.add(catid);
// Add subcategories
java.util.List<CategoryInfo> categories = new LinkedList<CategoryInfo>();
if (catid.isEmpty()) {
categories = m_dlSales.getRootCategories();
} else {
categories = m_dlSales.getSubcategories(catid);
}
for (CategoryInfo cat : categories) {
jcurrTab.addButton(new ImageIcon(tnbbutton.getThumbNailText(cat.getImage(), "<p align=\"center\">" + cat.getName() + "</p>")), new SelectedCategory(cat));
}
// Add products
java.util.List<ProductInfoExt> products = m_dlSales.getProductCatalog(catid);
for (ProductInfoExt prod : products) {
jcurrTab.addButton(new ImageIcon(tnbbutton.getThumbNailText(prod.getImage(), getProductLabel(prod))), new SelectedAction(prod));
}
}
// Show categories panel
CardLayout cl = (CardLayout) (m_jProducts.getLayout());
cl.show(m_jProducts, catid);
} catch (BasicException e) {
JMessageDialog.showMessage(this, new MessageInf(MessageInf.SGN_WARNING, AppLocal.getIntString("message.notactive"), e));
}
}
private String getProductLabel(ProductInfoExt product) {
String sProductText = "<p align=\"center\">";
Double dProductStock = 0.0;
if (namevisible) {
sProductText = sProductText.concat(product.getName());
}
if (refvisible) {
sProductText = sProductText.concat("<br>#" + product.getReference());
}
if (pricevisible) {
if (taxesincluded) {
TaxInfo tax = taxeslogic.getTaxInfo(product.getTaxCategoryID(), new Date());
sProductText = sProductText.concat("<br>" + product.printPriceSellTax(tax));
} else {
sProductText = sProductText.concat("<br>" + product.printPriceSell());
}
}
if (stockvisible) {
try {
dProductStock = m_dlSales.findProductStock(s_DefLocation, product.getID(), null);
} catch (BasicException ex) {
Logger.getLogger(JCatalog.class.getName()).log(Level.SEVERE, null, ex);
}
sProductText = sProductText.concat("<br>[" + Formats.DOUBLE.formatValue(dProductStock) + "]");
}
return sProductText.concat("</p>");
}
private void showRootCategoriesPanel() {
subcategories = new LinkedList();
if (s_DefProdCat != null && !s_DefProdCat.isEmpty()) {
try {
showingcategory = m_dlSales.getCategoryInfoById(s_DefProdCat);
} catch (BasicException ex) {
Logger.getLogger(JCatalog.class.getName()).log(Level.SEVERE, null, ex);
}
subcategories.add(null);
if (showingcategory != null) {
selectCategoryPanel(showingcategory.getID());
}
} else {
showingcategory = null;
showSubcategoryPanel(showingcategory);
}
}
private void showSubcategoryPanel(CategoryInfo category) {
if (category != null) {
selectCategoryPanel(category.getID());
} else {
selectCategoryPanel("");
}
showingcategory = category;
}
private void showProductPanel(String id) {
ProductInfoExt product = m_productsset.get(id);
if (product == null) {
if (m_productsset.containsKey(id)) {
// It is an empty panel
if (showingcategory == null) {
showRootCategoriesPanel();
} else {
showSubcategoryPanel(showingcategory);
}
} else {
try {
// Create products panel
java.util.List<ProductInfoExt> products = m_dlSales.getProductComments(id);
if (products.isEmpty()) {
// no hay productos por tanto lo anado a la de vacios y muestro el panel principal.
m_productsset.put(id, null);
if (showingcategory == null) {
showRootCategoriesPanel();
} else {
showSubcategoryPanel(showingcategory);
}
} else {
// Load product panel
product = m_dlSales.getProductInfo(id);
m_productsset.put(id, product);
JCatalogTab jcurrTab = new JCatalogTab();
jcurrTab.applyComponentOrientation(getComponentOrientation());
m_jProducts.add(jcurrTab, "PRODUCT." + id);
// Add products
for (ProductInfoExt prod : products) {
jcurrTab.addButton(new ImageIcon(tnbbutton.getThumbNailText(prod.getImage(), getProductLabel(prod))), new SelectedAction(prod));
}
CardLayout cl = (CardLayout) (m_jProducts.getLayout());
cl.show(m_jProducts, "PRODUCT." + id);
}
} catch (BasicException eb) {
m_productsset.put(id, null);
if (showingcategory == null) {
showRootCategoriesPanel();
} else {
showSubcategoryPanel(showingcategory);
}
}
}
} else {
// already exists
CardLayout cl = (CardLayout) (m_jProducts.getLayout());
cl.show(m_jProducts, "PRODUCT." + id);
}
}
private class SelectedAction implements ActionListener {
private ProductInfoExt prod;
public SelectedAction(ProductInfoExt prod) {
this.prod = prod;
}
public void actionPerformed(ActionEvent e) {
fireSelectedProduct(prod);
}
}
private class SelectedCategory implements ActionListener {
private CategoryInfo category;
public SelectedCategory(CategoryInfo category) {
this.category = category;
}
public void actionPerformed(ActionEvent e) {
subcategories.add(showingcategory);
showSubcategoryPanel(category);
}
}
/**
* 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_jProducts = new javax.swing.JPanel();
jPanel1 = new javax.swing.JPanel();
m_jCategories = new javax.swing.JPanel();
jPanel5 = new javax.swing.JPanel();
m_btnBackRoot = new javax.swing.JButton();
m_btnBackSub = new javax.swing.JButton();
m_jPanelImageViewer = new javax.swing.JPanel();
m_jImage = new com.openbravo.data.gui.JImageViewer();
setLayout(new java.awt.BorderLayout());
m_jProducts.setLayout(new java.awt.CardLayout());
add(m_jProducts, java.awt.BorderLayout.CENTER);
jPanel1.setLayout(new java.awt.BorderLayout());
m_jCategories.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 5, 0, 5));
m_jCategories.setMinimumSize(new java.awt.Dimension(72, 275));
m_jCategories.setPreferredSize(new java.awt.Dimension(82, 275));
m_jCategories.setLayout(new java.awt.BorderLayout());
jPanel5.setLayout(new java.awt.GridLayout(0, 1, 0, 2));
m_btnBackRoot.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/openbravo/images/3uparrow2.png"))); // NOI18N
m_btnBackRoot.setFocusPainted(false);
m_btnBackRoot.setFocusable(false);
m_btnBackRoot.setRequestFocusEnabled(false);
m_btnBackRoot.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
m_btnBackRootActionPerformed(evt);
}
});
jPanel5.add(m_btnBackRoot);
m_btnBackSub.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/openbravo/images/3uparrow.png"))); // NOI18N
m_btnBackSub.setFocusPainted(false);
m_btnBackSub.setFocusable(false);
m_btnBackSub.setRequestFocusEnabled(false);
m_btnBackSub.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
m_btnBackSubActionPerformed(evt);
}
});
jPanel5.add(m_btnBackSub);
m_jCategories.add(jPanel5, java.awt.BorderLayout.NORTH);
jPanel1.add(m_jCategories, java.awt.BorderLayout.LINE_START);
m_jPanelImageViewer.setPreferredSize(new java.awt.Dimension(240, 275));
m_jPanelImageViewer.setLayout(new java.awt.BorderLayout());
m_jImage.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
m_jPanelImageViewer.add(m_jImage, java.awt.BorderLayout.CENTER);
jPanel1.add(m_jPanelImageViewer, java.awt.BorderLayout.LINE_END);
add(jPanel1, java.awt.BorderLayout.LINE_END);
}// </editor-fold>//GEN-END:initComponents
private void m_btnBackRootActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_m_btnBackRootActionPerformed
showRootCategoriesPanel();
}//GEN-LAST:event_m_btnBackRootActionPerformed
private void m_btnBackSubActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_m_btnBackSubActionPerformed
if (!subcategories.isEmpty()) {
showSubcategoryPanel(subcategories.getLast());
subcategories.removeLast();
}
}//GEN-LAST:event_m_btnBackSubActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel5;
private javax.swing.JButton m_btnBackRoot;
private javax.swing.JButton m_btnBackSub;
private javax.swing.JPanel m_jCategories;
private com.openbravo.data.gui.JImageViewer m_jImage;
private javax.swing.JPanel m_jPanelImageViewer;
private javax.swing.JPanel m_jProducts;
// End of variables declaration//GEN-END:variables
}