package gui.subspacePanel; import gui.bsvComponents.JTextFieldLimited; import gui.main.EventController; import gui.settings.Settings; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.ArrayList; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTabbedPane; import javax.swing.ScrollPaneConstants; import javax.swing.SwingConstants; import controller.Feature; import controller.Subspace; import db.DatabaseAccessException; /** * The dialog shows detailed information about all {@link Feature}s and allows the user to rename them. */ public class FeatureSubspaceDialog extends JDialog { private static final long serialVersionUID = -8762294916340189399L; /** * A list with all existing subspaces. */ private final Subspace[] allSubspaces; /** * A list with the shown single feature panels. */ private final ArrayList<SingleFeature> allFeaturesInUI; /** * Button to accept and change the new values. */ private JButton btnChange; /** * Button to dismiss all changes. */ private JButton btnCancel; /** * The constructor of a new feature-subspace detail dialog. * * @param allSubspaces * a list with all existing subspaces */ public FeatureSubspaceDialog(Subspace[] allSubspaces) { super(EventController.getInstance().getRootFrame(), true); if (allSubspaces == null) { throw new IllegalArgumentException("allSubspaces was null"); } // init the dialog this.allSubspaces = allSubspaces; this.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE); this.setResizable(false); this.setMinimumSize(new Dimension(400, 600)); this.getContentPane().setLayout(new BorderLayout()); // Initialize both panels within the tabs this.allFeaturesInUI = new ArrayList<FeatureSubspaceDialog.SingleFeature>(); // create the panels JPanel outlierPanel = initPanel(true); JPanel featurePanel = initPanel(false); // make them scrollable JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP); JScrollPane scrollPaneFeature = new JScrollPane(featurePanel); scrollPaneFeature.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); JScrollPane scrollPaneOutlier = new JScrollPane(outlierPanel); scrollPaneOutlier.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); tabbedPane.addTab(Settings.getInstance().getResourceBundle().getString("feature"), scrollPaneFeature); tabbedPane.addTab(Settings.getInstance().getResourceBundle().getString("outlierness"), scrollPaneOutlier); this.getContentPane().add(tabbedPane, BorderLayout.CENTER); // Initialize the buttons and add a simple key listener initButtons(); this.addKeyListener(new KeyListener() { @Override public void keyTyped(KeyEvent arg0) { // nothing to do } @Override public void keyReleased(KeyEvent arg0) { // nothing to do } @Override public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER) { btnChange.doClick(); } else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { btnCancel.doClick(); } } }); } /** * Exit and hide the dialog. */ private void exit() { this.setVisible(false); } /** * The method initializes the panels with all features or outlierness. * * @param outlier * true, if you want to build the outlier * @return the new created panel */ private JPanel initPanel(boolean outlier) { JPanel featurePanel = new JPanel(); featurePanel.setLayout(new BoxLayout(featurePanel, BoxLayout.Y_AXIS)); Feature[] allFeatures = new Feature[0]; // get all features try { allFeatures = allSubspaces[0].getFeatures(); } catch (DatabaseAccessException e) { JOptionPane.showMessageDialog(this, Settings.getInstance().getResourceBundle().getString("databaseFeatureReadFailed"), Settings .getInstance().getResourceBundle().getString("databaseExceptionRead"), JOptionPane.ERROR_MESSAGE); e.printStackTrace(); } for (int i = 0; i < allFeatures.length; i++) { // Add all required features to single panels if ((outlier && allFeatures[i].isOutlier() && !allFeatures[i].isVirtual()) || (!outlier && !allFeatures[i].isOutlier() && !allFeatures[i].isVirtual())) { SingleFeature current = new SingleFeature(allFeatures[i]); featurePanel.add(current); this.allFeaturesInUI.add(current); } } return featurePanel; } /** * Initializes the buttons at the bottom of the dialog. */ private void initButtons() { JPanel buttonPanel = new JPanel(new FlowLayout()); buttonPanel.setAlignmentX(SwingConstants.RIGHT); // the button change; use the new entries this.btnChange = new JButton(Settings.getInstance().getResourceBundle().getString("change")); this.btnChange.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { for (SingleFeature current : allFeaturesInUI) { current.update(); } exit(); } }); buttonPanel.add(this.btnChange); // the button cancel; dismiss the entries this.btnCancel = new JButton(Settings.getInstance().getResourceBundle().getString("cancel")); this.btnCancel.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { for (SingleFeature current : allFeaturesInUI) { current.reset(); } exit(); } }); buttonPanel.add(this.btnCancel); this.getContentPane().add(buttonPanel, BorderLayout.SOUTH); } /** * This panel represents one {@link Feature} within the UI. */ class SingleFeature extends JPanel { private static final long serialVersionUID = -4538231871119511998L; /** * The {@link Feature} referring to this {@code SingleFeature}. */ private final Feature feature; /** * The text field to set the name. */ private final JTextFieldLimited featureName; /** * Flag to indicate, that the name has changed and has to be updated. */ private boolean hasChanged; /** * Constructs a new single feature. * * @param feature * the referring {@link Feature} */ public SingleFeature(final Feature feature) { super(); // init the single feature this.feature = feature; this.hasChanged = false; this.setLayout(new FlowLayout()); this.add(new JLabel(Settings.getInstance().getResourceBundle().getString("name") + ": ")); this.featureName = new JTextFieldLimited(feature.maxStringLength()); this.featureName.setColumns(feature.maxStringLength() / 4 * 3); this.featureName.setText(feature.getName()); this.featureName.addFocusListener(new FocusListener() { @Override public void focusLost(FocusEvent arg0) { // nothing to do } @Override public void focusGained(FocusEvent arg0) { // flag, to write only the changed features in database hasChanged = true; } }); this.featureName.addKeyListener(new KeyListener() { @Override public void keyTyped(KeyEvent arg0) { // nothing to do } @Override public void keyReleased(KeyEvent arg0) { String tmp = featureName.getText(); // check for a valid name if (!tmp.matches(".*(\\p{Punct}+|\\p{Space}).*")) { featureName.setForeground(Color.black); btnChange.setEnabled(true); } else { featureName.setForeground(Color.red); btnChange.setEnabled(false); } } @Override public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER) { btnChange.doClick(); } else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { btnCancel.doClick(); } } }); this.add(this.featureName); } /** * The method updates the name of this {@link Feature}, if it has changed. */ public void update() { if (hasChanged) { setFeatureName(featureName.getText()); } hasChanged = false; } /** * This method resets the text field to the old name of the feature. */ public void reset() { if (hasChanged) { featureName.setText(feature.getName()); } } /** * This method updates the name of this feature in the database. * * @param name * the new name */ private void setFeatureName(String name) { if (name == null) { throw new IllegalArgumentException("name may not be null"); } if (name.length() > 0) { try { feature.setName(name.trim()); } catch (DatabaseAccessException e) { JOptionPane.showMessageDialog(this, Settings.getInstance().getResourceBundle().getString("databaseFeatureNameWriteFailed"), Settings.getInstance().getResourceBundle().getString("databaseExceptionWrite"), JOptionPane.ERROR_MESSAGE); e.printStackTrace(); e.printStackTrace(); } } } } }