/*
* @(#)ActivityManager.java
*
* Copyright (c) 2011 The authors and contributors of JHotDraw.
*
* You may not use, copy or modify this file, except in compliance with the
* license agreement you entered into with the copyright holders. For details
* see accompanying license terms.
*/
package org.jhotdraw.gui;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import javax.swing.SwingUtilities;
import org.jhotdraw.gui.event.ActivityManagerEvent;
import org.jhotdraw.gui.event.ActivityManagerListener;
/**
* The activity manager keeps track of all active {@code ActivityModel} objects.
*
* <hr>
* <b>Design Patterns</b>
*
* <p><em>Framework</em><br>
* The interfaces and classes listed below define a framework for progress
* management.<br>
* Contract: {@link ActivityManager}, {@link ActivityModel},
* {@link JActivityWindow}, {@link JActivityIndicator}.
*
*
* @author Werner Randelshofer
* @version 1.0 2011-09-07 Created.
*/
public class ActivityManager {
private static ActivityManager instance;
public synchronized static ActivityManager getInstance() {
if (instance == null) {
instance = new ActivityManager();
}
return instance;
}
private ArrayList<ActivityModel> models = new ArrayList<>();
private ArrayList<ActivityManagerListener> listeners = new ArrayList<>();
/** Adds a listener to the progress manager. */
public synchronized void addActivityManagerListener(ActivityManagerListener l) {
listeners.add(l);
}
/** Removes a listener from the progress manager. */
public synchronized void removeActivityManagerListener(ActivityManagerListener l) {
listeners.remove(l);
}
/** Adds a progress model to the manager. This method is thread safe. */
public void add(final ActivityModel pm) {
invokeAndWait(new Runnable() {
@Override @SuppressWarnings("unchecked")
public void run() {
if (models.add(pm)) {
ArrayList<ActivityManagerListener> ls;
synchronized (ActivityManager.this) {
ls = (ArrayList<ActivityManagerListener>) listeners.clone();
}
ActivityManagerEvent evt = new ActivityManagerEvent(ActivityManager.this, pm);
for (ActivityManagerListener l : ls) {
l.activityModelAdded(evt);
}
}
}
});
}
/** Removes a progress model from the manager. This method is thread safe. */
public void remove(final ActivityModel pm) {
invokeAndWait(new Runnable() {
@Override @SuppressWarnings("unchecked")
public void run() {
if (models.remove(pm)) {
ArrayList<ActivityManagerListener> ls;
synchronized (ActivityManager.this) {
ls = (ArrayList<ActivityManagerListener>) listeners.clone();
}
ActivityManagerEvent evt = new ActivityManagerEvent(ActivityManager.this, pm);
for (ActivityManagerListener l : ls) {
l.activityModelRemoved(evt);
}
}
}
});
}
@SuppressWarnings("unchecked")
public ArrayList<ActivityModel> getActivityModels() {
return (ArrayList<ActivityModel>) models.clone();
}
/** Invokes a runnable on the EDT and wait until it is finished.
* FIXME - Maybe move this into a utility class?
*/
protected static void invokeAndWait(Runnable r) {
if (SwingUtilities.isEventDispatchThread()) {
r.run();
} else {
try {
SwingUtilities.invokeAndWait(r);
} catch (InterruptedException | InvocationTargetException ex) {
ex.printStackTrace();
}
}
}
}