package nl.fontys.sofa.limo.view.node.property.editor; import java.awt.BorderLayout; import java.awt.Component; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.beans.PropertyEditorSupport; import java.util.Arrays; import java.util.Collections; import java.util.List; import javax.swing.BorderFactory; import javax.swing.DefaultCellEditor; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTable; import javax.swing.UIManager; import javax.swing.border.EtchedBorder; import javax.swing.border.TitledBorder; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableCellRenderer; import nl.fontys.sofa.limo.api.service.distribution.DistributionFactory; import nl.fontys.sofa.limo.domain.component.event.distribution.Distribution; import nl.fontys.sofa.limo.view.util.LIMOResourceBundle; import org.openide.nodes.PropertyEditorRegistration; import org.openide.util.Lookup; /** * * @author Dominik Kaisers {@literal <d.kaisers@student.fontys.nl>} */ @PropertyEditorRegistration(targetType = Distribution.class) public class DistributionPropertyEditor extends PropertyEditorSupport { @Override public boolean supportsCustomEditor() { return true; } @Override public Component getCustomEditor() { return new CustomEditor(); } @Override public String getAsText() { return ((Distribution) getValue()).getClass().getSimpleName(); } /** * Convenience method to get editor value as distribution. * * @return */ protected Distribution getDistribution() { return (Distribution) getValue(); } /** * Private class. Defining the custom distribution property editor. */ private class CustomEditor extends JPanel { private final JLabel distributionTypeLabel; private JComboBox<String> distributionTypeComboBox; private JPanel parametersLabel; private JTable parametersTable; private DistributionFactory distributionFactory; /** * Create editor and init UI. */ public CustomEditor() { // Create layout setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.HORIZONTAL; c.anchor = GridBagConstraints.NORTH; c.insets = new Insets(3, 3, 3, 3); // Create parameter input parametersLabel = new javax.swing.JPanel(); parametersLabel.setBorder(BorderFactory.createTitledBorder( BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), LIMOResourceBundle.getString("PARAMETERS"), TitledBorder.LEFT, TitledBorder.TOP )); parametersLabel.setLayout(new BorderLayout()); parametersTable = new javax.swing.JTable() { @Override public Component prepareRenderer(TableCellRenderer renderer, int row, int column) { // Only select editable cells, not whole row Component c = super.prepareRenderer(renderer, row, column); if (isCellSelected(row, column)) { c.setBackground(getSelectionBackground()); } else if (column == 0) { c.setBackground(UIManager.getColor("Panel.background")); } else { c.setBackground(null); } return c; } }; parametersTable.setModel(new DistributionParameterTableModel()); parametersTable.setShowGrid(true); parametersTable.putClientProperty("terminateEditOnFocusLost", true); DefaultCellEditor singleClick = (DefaultCellEditor) parametersTable.getDefaultEditor(parametersTable.getColumnClass(1)); singleClick.setClickCountToStart(1); parametersTable.setDefaultEditor(parametersTable.getColumnClass(1), singleClick); parametersLabel.add(parametersTable, BorderLayout.CENTER); // Get distributions and add to combo box distributionFactory = Lookup.getDefault().lookup(DistributionFactory.class); List<String> distTypes = Arrays.asList(distributionFactory.getDistributionTypes()); Collections.sort(distTypes); String[] cbModel = distTypes.toArray(new String[distTypes.size()]); distributionTypeLabel = new javax.swing.JLabel(LIMOResourceBundle.getString("DISTRIBUTION_TYPE")); distributionTypeComboBox = new javax.swing.JComboBox<>(cbModel); String nameForDistributionType = distributionFactory.getNameForDistributionType(getDistribution().getClass()); distributionTypeComboBox.getModel().setSelectedItem(nameForDistributionType); distributionTypeComboBox.addActionListener((ActionEvent e) -> { setValue(distributionFactory.getDistributionTypeByName((String) distributionTypeComboBox.getSelectedItem())); ((AbstractTableModel) parametersTable.getModel()).fireTableDataChanged(); }); c.weightx = 0.3; c.gridx = 0; c.gridy = 0; c.gridwidth = 1; add(distributionTypeLabel, c); c.weightx = 0.7; c.gridx = 1; c.gridy = 0; c.gridwidth = 3; add(distributionTypeComboBox, c); c.weightx = 1; c.gridx = 0; c.gridy = 1; c.gridwidth = 4; add(parametersLabel, c); } /** * Table model for distribution property editor. */ private class DistributionParameterTableModel extends AbstractTableModel { @Override public int getRowCount() { return getDistribution() == null ? 0 : getDistribution().getNames().size(); } @Override public int getColumnCount() { return 2; } @Override public Object getValueAt(int rowIndex, int columnIndex) { String inputValueName = getDistribution().getNames().get(rowIndex); if (columnIndex == 0) { return inputValueName; } else { return getDistribution().getValue(inputValueName); } } @Override public Class<?> getColumnClass(int columnIndex) { return String.class; } @Override public String getColumnName(int column) { return column == 0 ? LIMOResourceBundle.getString("NAME") : LIMOResourceBundle.getString("VALUE"); } @Override public boolean isCellEditable(int rowIndex, int columnIndex) { return columnIndex == 1; } @Override public void setValueAt(Object aValue, int rowIndex, int columnIndex) { if (columnIndex == 1) { String inputValueName = getDistribution().getNames().get(rowIndex); Number n; Class<?> inputType = getDistribution().getType(inputValueName); if (inputType.equals(Double.class)) { try { n = Double.parseDouble((String) aValue); } catch (NumberFormatException nfe) { n = null; javax.swing.JOptionPane.showMessageDialog(parametersTable, LIMOResourceBundle.getString("REQUIRES_FLOATING-POINT_VALUE"), LIMOResourceBundle.getString("NOT_FLOATING-POINT"), JOptionPane.WARNING_MESSAGE); } } else if (inputType.equals(Integer.class)) { try { n = Integer.parseInt((String) aValue); } catch (NumberFormatException nfe) { n = null; javax.swing.JOptionPane.showMessageDialog(parametersTable, LIMOResourceBundle.getString("REQUIRES_INTERGER_VALUE"), LIMOResourceBundle.getString("NOT_INTERGER"), JOptionPane.WARNING_MESSAGE); } } else { n = 0; } if (n != null) { getDistribution().setInputValue(inputValueName, n); } Distribution newProp = distributionFactory.getDistributionTypeByName(distributionFactory.getNameForDistributionType(getDistribution().getClass())); newProp.setInputValues(getDistribution().getInputValues()); setValue(newProp); fireTableCellUpdated(rowIndex, columnIndex); } } } } }