/* * codjo.net * * Common Apache License 2.0 */ package net.codjo.gui.operation; import net.codjo.gui.toolkit.swing.SwingWorker; import net.codjo.gui.toolkit.util.ErrorDialog; import net.codjo.gui.treatment.SleeveAuditHelper; import net.codjo.operation.OperationFailureException; import net.codjo.persistent.PersistenceException; import net.codjo.utils.JukeBox; import java.awt.Component; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyVetoException; import java.beans.VetoableChangeListener; import java.sql.SQLException; import javax.swing.JInternalFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.ProgressMonitor; import javax.swing.Timer; import org.apache.log4j.Logger; /** * Effectue une operation, avec affichage de sa progression. * * @author $Author: acharif $ * @version $Revision: 1.7 $ */ public class OperationProgress extends MouseAdapter implements Runnable { private static final int ONE_SECOND = 1000; private boolean calculatingLengthOfTask = true; private JPanel glassPanel; private JukeBox jukeBox; private JInternalFrame managerWindow; private ProgressData operation; private boolean operationDone; private ProgressMonitor progressMonitor; private Thread thread; private Timer timer; private ModalVetoableChangeListener vcl = new ModalVetoableChangeListener(); private SwingWorker worker; private WaitingWindowManager waitingWindowManager; // Log private static final Logger APP = Logger.getLogger(OperationProgress.class); /** * Constructeur. * * @param op L'operation a effectuer (interface permettant d'adapter le code en fonction * de l'application). * @param jb Le JukeBox des sons * @param waitingWindowManager Le gestionnaire d'affichage de la waitingWindow */ public OperationProgress(ProgressData op, JukeBox jb, WaitingWindowManager waitingWindowManager) { operation = op; jukeBox = jb; this.waitingWindowManager = waitingWindowManager; } /** * Lance l'operation. Le composant <code>gui</code> sera <code>repaint</code> a la fin du traitement. * * @param firstLaunch Traitement complet (sinon Reprise du traitement) * @param gui Le composant lancant l'operation. * @param endOperationListener Runner dont la methode run sera appelee en fin de tache (dans le thread * Event) * * @throws PersistenceException Impossible de charger le behavior * @throws OperationFailureException Impossible de determiner la longueur de la tache. * @throws SQLException Erreur d'acc�s base * @throws IllegalArgumentException TODO */ public void go(boolean firstLaunch, JInternalFrame gui, Runnable endOperationListener) throws PersistenceException, OperationFailureException, SQLException { if (gui == null || endOperationListener == null) { throw new IllegalArgumentException(); } managerWindow = gui; operation.prepareProceed(firstLaunch); thread = new Thread(this); thread.start(); progressMonitor = new ProgressMonitor(gui, operation.getProgressMessage(), "", 0, 100); timer = new Timer(ONE_SECOND, new OperationListener()); worker = new OperationWorker(gui, endOperationListener, waitingWindowManager); operationDone = false; addModalRestriction(); try { worker.start(); timer.start(); } catch (RuntimeException ex) { removeModalRestriction(); throw ex; } catch (Error er) { removeModalRestriction(); throw er; } } /** * Overview. * * <p> Description </p> * * @param e Description of Parameter */ @Override public void mouseClicked(MouseEvent e) { Toolkit.getDefaultToolkit().beep(); } /** * Main processing method for the OperationProgress object */ public void run() { try { operation.determineLengthOfTask(); } catch (OperationFailureException ex) { ex.printStackTrace(); } this.calculatingLengthOfTask = false; } /** * DOCUMENT ME! * * @return The CurrentOfTask value */ private int getCurrentOfTask() { return operation.getCurrentOfTask() * 100; } /** * DOCUMENT ME! * * @return The LengthOfTask value */ private int getLengthOfTask() { int length = operation.getLengthOfTask(); if (length == 0) { length = 1; } return length * 100; } /** * Gets the Message attribute of the OperationProgress object * * @return The Message value */ private String getStateMessage() { return "Enregistrement " + getCurrentOfTask() / 100 + " / " + getLengthOfTask() / 100 + "."; } /** * Empeche la selection de la fen�tre managerWindow. */ private void addModalRestriction() { glassPanel = new JPanel(); glassPanel.setOpaque(false); glassPanel.addMouseListener(this); managerWindow.setGlassPane(glassPanel); managerWindow.addVetoableChangeListener(vcl); try { managerWindow.setSelected(false); } catch (Exception ex) { ex.printStackTrace(); } } /** * Redonne la possibilite de selectionner la fen�tre managerWindow. */ private void removeModalRestriction() { managerWindow.removeVetoableChangeListener(vcl); managerWindow.remove(glassPanel); try { managerWindow.setSelected(true); } catch (Exception ex) { ex.printStackTrace(); } } /** * Evite la selection de la fen�tre managerWindow. * * @author $Author: acharif $ * @version $Revision: 1.7 $ */ static class ModalVetoableChangeListener implements VetoableChangeListener { /** * DOCUMENT ME! * * @param evt Changement de propri�t� de la fen�tre source. * * @throws PropertyVetoException Exception sur le changement. */ public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException { if ("selected".equals(evt.getPropertyName()) && Boolean.TRUE.equals(evt.getNewValue())) { throw new PropertyVetoException("En cours d'edition", evt); } } } /** * Rafraichit le ProgressMonitor en fonction de l'etat de l'operation. * * @author $Author: acharif $ * @version $Revision: 1.7 $ */ private class OperationListener implements ActionListener { /** * DOCUMENT ME! * * @param evt Description of Parameter */ public void actionPerformed(ActionEvent evt) { if (operationDone) { Toolkit.getDefaultToolkit().beep(); timer.stop(); progressMonitor.close(); thread.interrupt(); removeModalRestriction(); } else if ((progressMonitor.isCanceled()) && (!thread.isInterrupted())) { timer.stop(); Object[] choix = {"Non je continue", "Oui je veux arr�ter"}; int answer = -1; while (answer == -1) { answer = JOptionPane.showOptionDialog(null, "Etes-vous s�r(e) de vouloir annuler l'op�ration en cours ?", "Arr�t de l'op�ration", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, choix, null); } if (answer == 1) { worker.interrupt(); thread.interrupt(); removeModalRestriction(); } else { progressMonitor = new ProgressMonitor(managerWindow, operation.getOperationType() + " de " + operation.getSourceTable().getTableName() + " vers " + operation.getDestTable().getTableName() + " en cours ...", "", 0, 100); timer.start(); } } else { // APP.debug("--> Memory : " + Runtime.getRuntime().totalMemory()); // APP.debug("--> Time : " + System.currentTimeMillis() / 1000); if (calculatingLengthOfTask) { progressMonitor.setNote("Enregistrement " + getCurrentOfTask() / 100 + " / ...calcul en cours"); progressMonitor.setProgress(1); } else { double progress = getCurrentOfTask() / (getLengthOfTask() / 100); progressMonitor.setNote(getStateMessage()); progressMonitor.setProgress((int)progress); } } } } /** * Execute l'operation dans un thread de type SwingWorker. * * @author $Author: acharif $ * @version $Revision: 1.7 $ */ private class OperationWorker extends SwingWorker { private Runnable endOperationListener; private Component gui; private WaitingWindowManager waitingWindowManager; /** * Constructor for the OperationWorker object * * @param endOperationListener Runner appele en fin de tache * @param waitingWindowManager Le gestionnaire d'affichage de la waitingWindow */ private OperationWorker(Component gui, Runnable endOperationListener, WaitingWindowManager waitingWindowManager) { this.gui = gui; this.endOperationListener = endOperationListener; this.waitingWindowManager = waitingWindowManager; } /** * Execute l'operation. * * @return l'operation executee. */ @Override public Object construct() { try { operation.proceed(); operationDone = true; jukeBox.playSuccessSound(); } catch (OperationFailureException ex) { if (operation instanceof OperationProgressData) { OperationFailureHelper.getInstance().addError(((OperationProgressData)operation) .getOperationId(), ex.getLocalizedMessage()); } else { SleeveAuditHelper.getInstance().setErrorMsg(ex.getLocalizedMessage()); } ex.printStackTrace(); operationDone = true; jukeBox.playFailureSound(); ErrorDialog.show(gui, "Erreur pendant l'op�ration!", ex.getLocalizedMessage()); waitingWindowManager.disposeWaitingWindow(); } return operation; } /** * Enregistre l'operation et previent l'IHM. */ @Override public void finished() { waitingWindowManager.disposeWaitingWindow(); endOperationListener.run(); } } }