package nl.fontys.sofa.limo.view.custom.procedure;
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BoxLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import static javax.swing.WindowConstants.DISPOSE_ON_CLOSE;
import javax.swing.table.DefaultTableCellRenderer;
import nl.fontys.sofa.limo.api.dao.ProcedureCategoryDAO;
import nl.fontys.sofa.limo.api.service.provider.ProcedureService;
import nl.fontys.sofa.limo.domain.component.procedure.Procedure;
import nl.fontys.sofa.limo.domain.component.procedure.ProcedureCategory;
import nl.fontys.sofa.limo.domain.component.procedure.TimeType;
import nl.fontys.sofa.limo.domain.component.procedure.value.Value;
import nl.fontys.sofa.limo.view.custom.table.ProcedureTableModel;
import nl.fontys.sofa.limo.view.util.IconUtil;
import nl.fontys.sofa.limo.view.util.LIMOResourceBundle;
import org.openide.util.Lookup;
/**
* This Panel handles everything about a procedure component. It shows you a
* given list of procedures, you can edit them, add new ones and delete some
* from the list.
*
* @author Matthias Brück
*/
public class ProcedureComponent extends JPanel implements ActionListener, MouseListener {
protected JTable table;
protected ProcedureTableModel model;
protected JButton addButton, newButton, deleteButton;
protected ProcedureCategoryDAO procedureCategoryDao;
protected Value changedValue;
protected JComboBox procedureCategoryCheckbox, timeTypesCheckbox;
protected DefaultComboBoxModel procedureComboBoxModel;
protected JComboBox<Procedure> proceduresComboBox;
protected ProcedureService service;
protected List<Procedure> allProcedures;
protected List<Procedure> tableProcedures;
/**
* Creates a new ProcedureComponent with an empty table.
*/
public ProcedureComponent() {
this(new ArrayList<>());
}
/**
* Creates a new ProcedureComponent with a given list of procedures.
*
* @param procedures The procedures that have to be displayed in the table.
*/
public ProcedureComponent(List<Procedure> procedures) {
procedureCategoryDao = Lookup.getDefault().lookup(ProcedureCategoryDAO.class);
tableProcedures = procedures;
initProcedureService();
proceduresComboBox = new JComboBox();
setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 0.2;
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 1;
add(new JLabel(LIMOResourceBundle.getString("PROCEDURE")), c);
c.weightx = 0.7;
c.gridx = 1;
c.gridy = 0;
add(proceduresComboBox, c);
ProcedureTableModel tableModel;
JPanel panel = new JPanel(new BorderLayout());
tableModel = new ProcedureTableModel(procedures);
table = new JTable(tableModel);
initProceduresTable(procedures);
JScrollPane scrollPane = new JScrollPane(table);
panel.add(scrollPane, BorderLayout.CENTER);
addButton = new JButton(new ImageIcon(IconUtil.getIcon(IconUtil.UI_ICON.VALID)));
newButton = new JButton(new ImageIcon(IconUtil.getIcon(IconUtil.UI_ICON.ADD)));
deleteButton = new JButton(new ImageIcon(IconUtil.getIcon(IconUtil.UI_ICON.TRASH)));
JPanel panelLeft = new JPanel();
panelLeft.setLayout(new BoxLayout(panelLeft, BoxLayout.Y_AXIS));
panelLeft.add(addButton);
panelLeft.add(newButton);
panelLeft.add(deleteButton);
panel.add(panelLeft, BorderLayout.EAST);
c.weightx = 1;
c.gridx = 0;
c.gridy = 1;
c.gridwidth = 5;
add(panel, c);
addButton.addActionListener(this);
newButton.addActionListener(this);
deleteButton.addActionListener(this);
table.addMouseListener(this);
setVisible(true);
setProcedureComboBox();
checkButtonsState();
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(deleteButton)) {
int rowToDelete = table.getSelectedRow();
if (rowToDelete > -1) {
deleteProcedure(rowToDelete);
}
} else if (e.getSource().equals(addButton)) {
addClicked();
setProcedureComboBox();
checkButtonsState();
}
}
@Override
public void mouseClicked(MouseEvent e) {
if (e.getSource().equals(table)) {
if (e.getClickCount() > 1) {
editProcedure();
}
}
checkButtonsState();
}
/**
* Returns a list with all procedures present in the table.
*
* @return A list with all procedures that are in the table at the moment.
*/
public List<Procedure> getActiveTableState() {
return model.getProcedures();
}
/**
* Sets the table to a new procedure list.
*
* @param procedures The new list of procedures that has to be used.
*/
public void setProcedureTable(List<Procedure> procedures) {
tableProcedures = procedures;
initProceduresTable(procedures);
model.fireTableDataChanged();
revalidate();
repaint();
}
/**
* Handles the adding of a procedure via a dialog.
*/
protected void addProcedure() {
AddProcedureDialog addProcedureDialog = new AddProcedureDialog(procedureCategoryDao, table);
addProcedureDialog.setListener((Procedure procedure) -> {
deleteButton.setEnabled(true);
tableProcedures.add(procedure);
});
addProcedureDialog.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
addProcedureDialog.setVisible(true);
initProcedureService();
setProcedureComboBox();
checkButtonsState();
}
/**
* Deletes the specified row. Does nothing if the row is out of scope.
*
* @param row The row that has to be deleted.
*/
protected void deleteProcedure(int row) {
model.removeProcedue(row);
}
/**
* Handles the editing of the specified row.
*/
protected void editProcedure() {
if (table.getSelectedColumn() == 2 || table.getSelectedColumn() == 4 || table.getSelectedColumn() == 5) {
changedValue = (Value) table.getValueAt(table.getSelectedRow(), table.getSelectedColumn());
Object valueAt = table.getValueAt(table.getSelectedRow(), table.getSelectedColumn());
EditValueDialog editValueDialog = new EditValueDialog((Value) valueAt, (Value value) -> {
changedValue = value;
table.setValueAt(value, table.getSelectedRow(), table.getSelectedColumn());
ProcedureComponent.this.revalidate();
ProcedureComponent.this.repaint();
});
editValueDialog.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
editValueDialog.setVisible(true);
}
}
// <editor-fold desc="UNUSED LISTENER METHODS" defaultstate="collapsed">
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
//</editor-fold>
/**
* Initializes the procedure table with the given list of procedures.
*
* @param procedures The list of procedures that has to be used in the
* table.
*/
private void initProceduresTable(List<Procedure> procedures) {
tableProcedures = procedures;
model = new ProcedureTableModel(procedures);
table.setModel(model);
DefaultTableCellRenderer rightRenderer = new DefaultTableCellRenderer();
rightRenderer.setHorizontalAlignment(SwingConstants.RIGHT);
table.getColumnModel().getColumn(2).setCellRenderer(rightRenderer);
table.getColumnModel().getColumn(4).setCellRenderer(rightRenderer);
table.getColumnModel().getColumn(5).setCellRenderer(rightRenderer);
DefaultTableCellRenderer middleRenderer = new DefaultTableCellRenderer();
middleRenderer.setHorizontalAlignment(SwingConstants.CENTER);
table.getColumnModel().getColumn(3).setCellRenderer(middleRenderer);
try {
procedureCategoryCheckbox = new JComboBox(procedureCategoryDao.findAll().toArray());
table.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(procedureCategoryCheckbox));
} catch (Exception e) {
procedureCategoryCheckbox = new JComboBox(new ProcedureCategory[]{});
table.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(procedureCategoryCheckbox));
}
timeTypesCheckbox = new JComboBox(TimeType.values());
table.getColumnModel().getColumn(3).setCellEditor(new DefaultCellEditor(timeTypesCheckbox));
}
protected void checkButtonsState() {
addButton.setEnabled(proceduresComboBox.getModel().getSize() > 0);
deleteButton.setEnabled(tableProcedures.size() > 1 && table.getSelectedRow() != -1);
}
private void initProcedureService() {
service = Lookup.getDefault().lookup(ProcedureService.class);
allProcedures = service.findAll();
}
protected void setProcedureComboBox() {
ArrayList<String> allProcedureNames = new ArrayList<>();
List<String> usedProcedures = new ArrayList<>();
for (int row = 0; row < table.getRowCount(); row++) {
usedProcedures.add((String) table.getValueAt(row, 0));
}
if (allProcedures != null) {
for (Procedure procedure : allProcedures) {
boolean valid = true;
for (String used : usedProcedures) {
if (procedure.getName() != null && used != null) {
valid = !procedure.getName().equals(used);
}
if (!valid) {
break;
}
}
if (valid) {
allProcedureNames.add(procedure.getName());
}
}
addButton.setEnabled(!allProcedures.isEmpty());
proceduresComboBox.setModel(new DefaultComboBoxModel(allProcedureNames.toArray()));
} else {
allProcedures = new ArrayList<>();
proceduresComboBox.setModel(new DefaultComboBoxModel(new String[]{}));
}
}
protected void addClicked() {
Procedure selected = null;
for (Procedure procedure : allProcedures) {
if (((String) proceduresComboBox.getSelectedItem()).equals(procedure.getName())) {
selected = service.findById(procedure.getId());
break;
}
}
if (selected != null) {
List<Procedure> procedures = new ArrayList<>(tableProcedures);
selected.setId(null);
procedures.add(selected);
model.fireTableDataChanged();
setProcedureTable(procedures);
}
}
}