package org.signalml.app.view.common.dialogs; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Window; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import javax.swing.JComponent; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.ListCellRenderer; import javax.swing.ListSelectionModel; import javax.swing.border.CompoundBorder; import javax.swing.border.EmptyBorder; import javax.swing.border.TitledBorder; import org.signalml.app.view.common.components.ProgressState; /** * Dialog that shows progress of some time consuming operation. * It's a Property Change Listener, the only property it reacts to is * progressState, it's value is a {@link ProgressState} object. * * @author Tomasz Sawicki */ public class ProgressDialog extends AbstractDialog implements PropertyChangeListener { public static final String PROGRESS_STATE = "progressState"; public final int DIALOG_WIDTH = 400; public final int DIALOG_HEIGHT = 280; /** * The text area. */ private ProgressStateList progressStateList = null; /** * The progress bar. */ private JProgressBar progressBar = null; /** * If there was an error. */ private boolean error; /** * If there was a success. */ private boolean success; /** * Default constructor. * * @param w parent window * @param isModal if this window is modal * @param caption window's caption */ public ProgressDialog(Window w, boolean isModal, String title) { super(w, isModal); setTitle(title); setPreferredSize(new Dimension(DIALOG_WIDTH, DIALOG_HEIGHT)); } /** * Creates the interface. * * @return the interfacesize */ @Override protected JComponent createInterface() { JPanel interfacePanel = new JPanel(new BorderLayout(10, 10)); CompoundBorder panelBorder = new CompoundBorder(new TitledBorder(""), new EmptyBorder(3, 3, 3, 3)); interfacePanel.setBorder(panelBorder); interfacePanel.add(new JScrollPane(getProgressStateList()), BorderLayout.CENTER); interfacePanel.add(getProgressBar(), BorderLayout.PAGE_END); return interfacePanel; } /** * Gets the text area. * * @return the text area */ private ProgressStateList getProgressStateList() { if (progressStateList == null) { progressStateList = new ProgressStateList(); } return progressStateList; } /** * Gets the progress bar. * * @return the progress bar */ private JProgressBar getProgressBar() { if (progressBar == null) { progressBar = new JProgressBar(); } return progressBar; } /** * Only supported model is {@link ProgressState}. * * @param clazz class * @return true if clazz can be assigned to a ProgressState object */ @Override public boolean supportsModelClass(Class<?> clazz) { return ProgressState.class.isAssignableFrom(clazz); } /** * Fills all components from a {@link ProgressState} object. * * @param model a {@link ProgressState} object */ @Override public void fillDialogFromModel(Object model) { ProgressState state = (ProgressState) model; error = (state.getCurrentProgress() < 0); success = (state.getCurrentProgress() == state.getMaxProgress()); getProgressStateList().add(state); getProgressBar().setValue(state.getCurrentProgress()); getProgressBar().setMaximum(state.getMaxProgress()); if (error || success) { getOkButton().setEnabled(true); getCancelButton().setEnabled(false); } else { getOkButton().setEnabled(false); getCancelButton().setEnabled(true); } } /** * Dialog is read only. * * @param model not used */ @Override public void fillModelFromDialog(Object model) { } /** * Only supported property is progressState. * * @param evt property change event */ @Override public void propertyChange(PropertyChangeEvent evt) { if (PROGRESS_STATE.equals(evt.getPropertyName())) { fillDialogFromModel(evt.getNewValue()); } } /** * No cancel on escape. * * @return false */ @Override public boolean isCancelOnEscape() { return false; } /** * Shows an empty dialog. */ public boolean showDialog() { return showDialog(new ProgressState(), true); } /** * Resets dialog. */ @Override protected void resetDialog() { super.resetDialog(); getProgressStateList().removeAll(); } /** * Returns true if the window was cancelled. * * @return true if the window was cancelled */ public boolean wasCancelled() { return (!(error || success)); } /** * Returns true if there was a success. * * @return true if there was a success */ public boolean wasSuccess() { return success; } } /** * Class responsible for showing the progress. * * @author Tomasz Sawicki */ class ProgressStateList extends JList { /** * Default constructor */ public ProgressStateList() { setCellRenderer(new ProgressStateListCellRenderer()); setSelectionMode(ListSelectionModel.SINGLE_SELECTION); } /** * Adds an element to the list. * * @param state progress state */ public void add(ProgressState state) { if (state.getProgressMsg().equals("")) { return; } Dimension size = getSize(); ArrayList<ProgressState> list = new ArrayList<ProgressState>(); for (int i = 0; i < getModel().getSize(); i++) { list.add((ProgressState) getModel().getElementAt(i)); } list.add(state); setListData(list.toArray()); setSize(size); } } /** * Renderer for {@link ProgressStateList} * * @author Tomasz Sawicki */ class ProgressStateListCellRenderer implements ListCellRenderer { @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { ProgressState state = (ProgressState) value; JTextArea textArea = new JTextArea(state.getProgressMsg()); textArea.setBackground(Color.WHITE); if (state.getCurrentProgress() < 0) { textArea.setForeground(Color.RED); } else if (state.getCurrentProgress() == state.getMaxProgress()) { textArea.setForeground(Color.GREEN); } else { textArea.setForeground(Color.BLACK); } return textArea; } }