r1773 - trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing
Author: tchemit Date: 2010-03-12 01:23:15 +0100 (Fri, 12 Mar 2010) New Revision: 1773 Log: introduce ActionThread reformat code Added: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/AbstractActionThread.java Modified: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/CardLayout2Ext.java Added: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/AbstractActionThread.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/AbstractActionThread.java (rev 0) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/AbstractActionThread.java 2010-03-12 00:23:15 UTC (rev 1773) @@ -0,0 +1,304 @@ +package jaxx.runtime.swing; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +public abstract class AbstractActionThread extends Thread { + + /** Logger */ + private static final Log log = LogFactory.getLog(AbstractActionThread.class); + + /** l'état du thread si annulé */ + private boolean canceled; + + /** + * un lock pour permettre la suspension et la reprise du thread lors du mode + * interactif. + */ + private final Object LOCK = new Object(); + + protected ActionWorker worker; + + protected final PropertyChangeListener workerListener; + + enum ActionStatus { + OK, + CANCEL, + FAIL + } + + public static class ActionWorker extends SwingWorker<Void, Object> { + + protected final String actionLabel; + + protected final Runnable target; + + protected ActionStatus status; + + protected Exception error; + + public ActionWorker(String actionLabel, Runnable target) { + this.target = target; + this.actionLabel = actionLabel; + } + + @Override + protected Void doInBackground() throws Exception { + if (log.isDebugEnabled()) { + log.debug("Action is starting " + getActionLabel()); + } + try { + target.run(); + } catch (Exception e) { + error = e; + } + return null; + } + + public boolean isFailed() { + return (isDone() || isCancelled()) && error != null; + } + + public Exception getError() { + return error; + } + + public ActionStatus getStatus() { + return status; + } + + public String getActionLabel() { + return actionLabel; + } + + @Override + protected void done() { + super.done(); + if (error != null) { + status = ActionStatus.FAIL; + return; + } + + if (isCancelled()) { + status = ActionStatus.CANCEL; + return; + } + status = ActionStatus.OK; + if (log.isDebugEnabled()) { + log.debug("Action is ending " + getActionLabel() + + " with status : " + status); + } + } + } + + protected AbstractActionThread(String name) { + super(name); + workerListener = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (log.isInfoEnabled()) { + log.info("action " + evt.getSource() + " property " + + evt.getPropertyName() + " changed <" + + evt.getOldValue() + " - " + evt.getNewValue() + ">"); + } + + if ("state".equals(evt.getPropertyName())) { + ActionWorker source = (ActionWorker) evt.getSource(); + SwingWorker.StateValue state = + (SwingWorker.StateValue) evt.getNewValue(); + + + if (state == SwingWorker.StateValue.STARTED) { + // starting new action + + onActionStart(source); + return; + } + + if (state == SwingWorker.StateValue.DONE) { + // on rend la main au thread pour qu'il attende une + // prochaine operation + + ActionStatus status = source.getStatus(); + if (log.isInfoEnabled()) { + log.info("status = " + status); + } + try { + switch (status) { + + case OK: + onActionEnd(source); + break; + case CANCEL: + onActionCancel(source); + break; + case FAIL: + onActionFail(source); + break; + } + } finally { + + // release thread + setWaiting(false); + } + } + } + } + }; + } + + + public void cancel() { + log.info("cancel " + this); + canceled = true; + + // on rend la main au thread + setWaiting(false); + } + + public ActionWorker addAction(String actionLabel, Runnable action) { + if (worker != null && !worker.isDone()) { + // on ne peut traiter qu'une seule opération à la fois + throw new IllegalStateException( + "can not add a operation when thread is busy, or has" + + " another operation to be done"); + } + if (action instanceof ActionWorker) { + + worker = (ActionWorker) action; + } else { + worker = new ActionWorker(actionLabel, action); + } + + // on libere le thread pour qu'il execute l'opération + setWaiting(false); + + return worker; + } + + public abstract void onActionStart(ActionWorker source); + + public abstract void onActionFail(ActionWorker source); + + public abstract void onActionCancel(ActionWorker source); + + public abstract void onActionEnd(ActionWorker source); + + @Override + public void run() { + if (log.isInfoEnabled()) { + log.info("starting... " + this); + } + try { + + while (!canceled) { + + if (canceled) { + // une annulation a été demandé + // donc même si une opération est demandée, on ne la traite + // pas + break; + } + + // en attente qu'une opération + // le block est bloqué jusqu'à arrivée d'une opération + // ou une demande d'annulation + setWaiting(true); + + // le thread a repris la main, donc plus en attente + log.trace("no more waiting " + this); + + if (!canceled) { + + // une opération a été demandée + try { + + // le thread écoute les modifications de l'action + worker.addPropertyChangeListener(workerListener); + + // démarrage de l'opération dans un worker + + worker.execute(); + + // le thread est bloqué jusqu'à la fin de l'opération + // ou une demande d'annulation + setWaiting(true); + + // le thread reprend la main des que l'operation + // est terminée ou a été annulée, on passera alors + // dans la méthode onPropertyChanged + + if (canceled) { +// getModel().setOperationState(WizardOperationState.CANCELED); + } else { +// getModel().setOperationState(currentAction.getOperationState()); + } + + } finally { + if (worker != null) { + // le thread n'écoute plus l'action car elle est terminée + // ou annulée + worker.removePropertyChangeListener(workerListener); + + // suppression de l'action + worker = null; + } + } + } + } + + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + unlockThread(); + log.trace(this + " will close..."); + close(); + } + } + + /** La méthode pour nettoyer le thread, a la fermeture. */ + protected void close() { + // par defaut, on ne fait rien + log.info(this); + } + + protected void setWaiting(boolean waiting) { + + if (waiting && !canceled) { + // locking thread + try { + lockThread(); + } catch (InterruptedException ex) { + log.error(ex.getMessage(), ex); + canceled = true; + } + } + + if (!waiting) { + // release lock + unlockThread(); + } + } + + protected void lockThread() throws InterruptedException { + synchronized (LOCK) { + log.trace(this); + // lock + LOCK.wait(); + } + } + + protected void unlockThread() { + synchronized (LOCK) { + log.trace(this); + // unlock + LOCK.notify(); + } + } + +} Property changes on: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/AbstractActionThread.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL Modified: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/CardLayout2Ext.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/CardLayout2Ext.java 2010-03-11 11:27:15 UTC (rev 1772) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/CardLayout2Ext.java 2010-03-12 00:23:15 UTC (rev 1773) @@ -84,8 +84,11 @@ } public void setSelected(String selected) { + String oldSelected = this.selected; this.selected = selected; show(getContainer(), selected); + //TODO-TC20100311 : should propagate the selected ? +// pcs.firePropertyChange(SELECTED_PROPERTY_NAME, oldSelected, selected); } public Container getContainer() { @@ -99,7 +102,8 @@ pcs.addPropertyChangeListener(listener); } - public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) { pcs.addPropertyChangeListener(propertyName, listener); } @@ -107,7 +111,8 @@ pcs.removePropertyChangeListener(listener); } - public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + public void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener) { pcs.removePropertyChangeListener(propertyName, listener); }
participants (1)
-
tchemit@users.nuiton.org