mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
funcTests + macro playbacl: selected ui activities watching - 2
This commit is contained in:
@@ -43,6 +43,11 @@ public class UiActivity implements ComparableObject{
|
||||
return new Object[] {myElements};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UiActivity: " + myElements;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return ComparableObjectCheck.hashCode(this, super.hashCode());
|
||||
|
||||
@@ -31,16 +31,29 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
public class UiActivityMonitorImpl extends UiActivityMonitor implements ModalityStateListener, Disposable {
|
||||
private final Map<Object, BusyImpl> myObjects = new HashMap<Object, BusyImpl>();
|
||||
private final Map<Object, BusyContainer> myObjects = new HashMap<Object, BusyContainer>();
|
||||
|
||||
public UiActivityMonitorImpl(Application application) {
|
||||
myObjects.put(null, new BusyObjectGlobalImpl());
|
||||
myObjects.put(null, new BusyContainer() {
|
||||
@Override
|
||||
protected BusyImpl createBusyImpl(HashSet<UiActivity> key) {
|
||||
return new BusyImpl(key, this) {
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
for (Map.Entry<Object, BusyContainer> entry : myObjects.entrySet()) {
|
||||
final BusyContainer eachContainer = entry.getValue();
|
||||
final BusyImpl busy = eachContainer.getOrCreateBusy(myToWatchArray);
|
||||
if (busy == this) continue;
|
||||
if (!busy.isOwnReady()) return false;
|
||||
}
|
||||
return isOwnReady();
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
application.getMessageBus().connect().subscribe(ProjectLifecycleListener.TOPIC, new ProjectLifecycleListener() {
|
||||
@Override
|
||||
public void projectComponentsInitialized(Project project) {
|
||||
@@ -85,19 +98,20 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
|
||||
}
|
||||
|
||||
public void maybeReady() {
|
||||
for (Map.Entry<Object, BusyImpl> entry : myObjects.entrySet()) {
|
||||
entry.getValue().onReady();
|
||||
final Collection<BusyContainer> values = myObjects.values();
|
||||
for (BusyContainer each : values) {
|
||||
each.onReady();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BusyObject getBusy(@NotNull Project project, UiActivity ... toWatch) {
|
||||
return _getBusy(project);
|
||||
public BusyObject getBusy(@NotNull Project project, UiActivity... toWatch) {
|
||||
return _getBusy(project, toWatch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BusyObject getBusy(UiActivity ... toWatch) {
|
||||
return _getBusy(null);
|
||||
public BusyObject getBusy(UiActivity... toWatch) {
|
||||
return _getBusy(null, toWatch);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -106,7 +120,9 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addActivity(@NotNull final Project project, @NotNull final UiActivity activity, @NotNull final ModalityState effectiveModalityState) {
|
||||
public void addActivity(@NotNull final Project project,
|
||||
@NotNull final UiActivity activity,
|
||||
@NotNull final ModalityState effectiveModalityState) {
|
||||
invokeLaterIfNeeded(new MyRunnable() {
|
||||
@Override
|
||||
public void run(Throwable allocation) {
|
||||
@@ -120,7 +136,7 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
|
||||
}
|
||||
}
|
||||
|
||||
_getBusy(project).addActivity(activity, allocation, effectiveModalityState);
|
||||
getBusyContainer(project).addActivity(activity, allocation, effectiveModalityState);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -149,7 +165,7 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
|
||||
invokeLaterIfNeeded(new MyRunnable() {
|
||||
@Override
|
||||
public void run(Throwable allocation) {
|
||||
_getBusy(null).addActivity(activity, allocation, effectiveModalityState);
|
||||
getBusyContainer(null).addActivity(activity, allocation, effectiveModalityState);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -164,13 +180,17 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
|
||||
});
|
||||
}
|
||||
|
||||
private BusyImpl _getBusy(@Nullable Object key) {
|
||||
BusyImpl object = myObjects.get(key);
|
||||
return object != null ? object : getGlobalBusy();
|
||||
private BusyImpl _getBusy(@Nullable Object key, UiActivity... toWatch) {
|
||||
return getBusyContainer(key).getOrCreateBusy(toWatch);
|
||||
}
|
||||
|
||||
private BusyContainer getBusyContainer(@Nullable Object key) {
|
||||
BusyContainer container = myObjects.get(key);
|
||||
return container != null ? container : getGlobalBusy();
|
||||
}
|
||||
|
||||
void initBusyObjectFor(@Nullable Object key) {
|
||||
BusyImpl object = new BusyImpl();
|
||||
BusyContainer object = new BusyContainer();
|
||||
myObjects.put(key, object);
|
||||
}
|
||||
|
||||
@@ -178,18 +198,19 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
|
||||
return myObjects.containsKey(project);
|
||||
}
|
||||
|
||||
private BusyObjectGlobalImpl getGlobalBusy() {
|
||||
return (BusyObjectGlobalImpl)myObjects.get(null);
|
||||
private BusyContainer getGlobalBusy() {
|
||||
return myObjects.get(null);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
for (Map.Entry<Object, BusyImpl> entry : myObjects.entrySet()) {
|
||||
entry.getValue().clear();
|
||||
final Set<Object> keys = myObjects.keySet();
|
||||
for (Iterator<Object> iterator = keys.iterator(); iterator.hasNext(); ) {
|
||||
Object each = iterator.next();
|
||||
myObjects.get(each).clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void disposeComponent() {
|
||||
myObjects.clear();
|
||||
@@ -227,20 +248,49 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
|
||||
|
||||
private class BusyImpl extends BusyObject.Impl {
|
||||
|
||||
private final Map<Object, ActivityInfo> myActivities = new HashMap<Object, ActivityInfo>();
|
||||
private final Map<UiActivity, ActivityInfo> myActivities = new HashMap<UiActivity, ActivityInfo>();
|
||||
|
||||
private final Set<Object> myQueuedToRemove = new HashSet<Object>();
|
||||
private final Set<UiActivity> myQueuedToRemove = new HashSet<UiActivity>();
|
||||
|
||||
protected final Set<UiActivity> myToWatch;
|
||||
protected final UiActivity[] myToWatchArray;
|
||||
private UiActivityMonitorImpl.BusyContainer myContainer;
|
||||
|
||||
private BusyImpl(Set<UiActivity> toWatch, BusyContainer container) {
|
||||
myToWatch = toWatch;
|
||||
myToWatchArray = toWatch.toArray(new UiActivity[toWatch.size()]);
|
||||
myContainer = container;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return isOwnReady() && getGlobalBusy().isOwnReady();
|
||||
return isOwnReady() && getGlobalBusy().getOrCreateBusy(myToWatchArray).isOwnReady();
|
||||
}
|
||||
|
||||
boolean isOwnReady() {
|
||||
if (myActivities.isEmpty()) return true;
|
||||
Map<UiActivity, ActivityInfo> infoToCheck = new HashMap<UiActivity, ActivityInfo>();
|
||||
|
||||
final Iterator<Set<UiActivity>> activitySets = myContainer.myActivities2Object.keySet().iterator();
|
||||
while (activitySets.hasNext()) {
|
||||
Set<UiActivity> eachActivitySet = activitySets.next();
|
||||
final BusyImpl eachBusyObject = myContainer.myActivities2Object.get(eachActivitySet);
|
||||
if (eachBusyObject == this) continue;
|
||||
|
||||
for (UiActivity eachOtherActivity : eachActivitySet) {
|
||||
for (UiActivity eachToWatch : myToWatch) {
|
||||
if (eachToWatch.isSameOrGeneralFor(eachOtherActivity) && eachBusyObject.myActivities.containsKey(eachOtherActivity)) {
|
||||
infoToCheck.put(eachOtherActivity, eachBusyObject.myActivities.get(eachOtherActivity));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
infoToCheck.putAll(myActivities);
|
||||
|
||||
if (infoToCheck.isEmpty()) return true;
|
||||
|
||||
final ModalityState current = getCurrentState();
|
||||
for (Map.Entry<Object, ActivityInfo> entry : myActivities.entrySet()) {
|
||||
for (Map.Entry<UiActivity, ActivityInfo> entry : infoToCheck.entrySet()) {
|
||||
final ActivityInfo info = entry.getValue();
|
||||
if (!current.dominates(info.getEffectiveState())) {
|
||||
return false;
|
||||
@@ -251,12 +301,18 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
|
||||
}
|
||||
|
||||
|
||||
public void addActivity(Object activity, Throwable allocation, ModalityState effectiveModalityState) {
|
||||
public void addActivity(UiActivity activity, Throwable allocation, ModalityState effectiveModalityState) {
|
||||
if (!myToWatch.isEmpty()) {
|
||||
if (!myToWatch.contains(activity)) return;
|
||||
}
|
||||
|
||||
myActivities.put(activity, new ActivityInfo(allocation, effectiveModalityState));
|
||||
myQueuedToRemove.remove(activity);
|
||||
|
||||
myContainer.onActivityAdded(this, activity);
|
||||
}
|
||||
|
||||
public void removeActivity(final Object activity) {
|
||||
public void removeActivity(final UiActivity activity) {
|
||||
if (!myActivities.containsKey(activity)) return;
|
||||
|
||||
myQueuedToRemove.add(activity);
|
||||
@@ -268,44 +324,34 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
|
||||
|
||||
myQueuedToRemove.remove(activity);
|
||||
myActivities.remove(activity);
|
||||
myContainer.onActivityRemoved(BusyImpl.this, activity);
|
||||
|
||||
onReady();
|
||||
}
|
||||
};
|
||||
if (isUnitTestMode()) {
|
||||
runnable.run();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
SwingUtilities.invokeLater(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
Object[] activities = myActivities.keySet().toArray(new Object[myActivities.size()]);
|
||||
for (Object each : activities) {
|
||||
UiActivity[] activities = myActivities.keySet().toArray(new UiActivity[myActivities.size()]);
|
||||
for (UiActivity each : activities) {
|
||||
removeActivity(each);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class BusyObjectGlobalImpl extends BusyImpl {
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
for (Map.Entry<Object, BusyImpl> entry : myObjects.entrySet()) {
|
||||
BusyImpl busy = entry.getValue();
|
||||
if (busy == this) continue;
|
||||
if (!busy.isOwnReady()) return false;
|
||||
}
|
||||
|
||||
return isOwnReady();
|
||||
}
|
||||
}
|
||||
|
||||
private static void invokeLaterIfNeeded(final MyRunnable runnable) {
|
||||
final Throwable allocation = Registry.is("ide.debugMode") ? new Exception() : null;
|
||||
|
||||
if (isUnitTestMode()) {
|
||||
runnable.run(allocation);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -320,8 +366,110 @@ public class UiActivityMonitorImpl extends UiActivityMonitor implements Modality
|
||||
}
|
||||
|
||||
private static boolean isUnitTestMode() {
|
||||
Application app = ApplicationManager.getApplication();
|
||||
return app == null || app.isUnitTestMode();
|
||||
Application app = ApplicationManager.getApplication();
|
||||
return app == null || app.isUnitTestMode();
|
||||
}
|
||||
|
||||
public class BusyContainer {
|
||||
|
||||
private Map<Set<UiActivity>, BusyImpl> myActivities2Object = new HashMap<Set<UiActivity>, BusyImpl>();
|
||||
private Map<BusyImpl, Set<UiActivity>> myObject2Activities = new HashMap<BusyImpl, Set<UiActivity>>();
|
||||
|
||||
private Set<UiActivity> myActivities = new HashSet<UiActivity>();
|
||||
|
||||
private BusyImpl myDefault;
|
||||
|
||||
private boolean myRemovingActivityNow;
|
||||
|
||||
public BusyContainer() {
|
||||
myDefault = registerBusyObject(new HashSet<UiActivity>());
|
||||
}
|
||||
|
||||
public BusyImpl getOrCreateBusy(UiActivity... activities) {
|
||||
final HashSet<UiActivity> key = new HashSet<UiActivity>();
|
||||
key.addAll(Arrays.asList(activities));
|
||||
|
||||
if (myActivities2Object.containsKey(key)) {
|
||||
return myActivities2Object.get(key);
|
||||
}
|
||||
else {
|
||||
final BusyImpl busy = registerBusyObject(key);
|
||||
return busy;
|
||||
}
|
||||
}
|
||||
|
||||
private BusyImpl registerBusyObject(HashSet<UiActivity> key) {
|
||||
final BusyImpl busy = createBusyImpl(key);
|
||||
myActivities2Object.put(key, busy);
|
||||
myObject2Activities.put(busy, key);
|
||||
return busy;
|
||||
}
|
||||
|
||||
protected BusyImpl createBusyImpl(HashSet<UiActivity> key) {
|
||||
return new BusyImpl(key, this);
|
||||
}
|
||||
|
||||
public void onReady() {
|
||||
final Iterator<Set<UiActivity>> keyIterator = myActivities2Object.keySet().iterator();
|
||||
while (keyIterator.hasNext()) {
|
||||
Set<UiActivity> eachKey = keyIterator.next();
|
||||
final BusyImpl busy = myActivities2Object.get(eachKey);
|
||||
busy.onReady();
|
||||
if (busy.isReady()) {
|
||||
keyIterator.remove();
|
||||
myObject2Activities.remove(busy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
final UiActivity[] activities = (UiActivity[])myActivities.toArray();
|
||||
for (UiActivity each : activities) {
|
||||
removeActivity(each);
|
||||
}
|
||||
}
|
||||
|
||||
public void onActivityAdded(BusyImpl busy, UiActivity activity) {
|
||||
myActivities.add(activity);
|
||||
}
|
||||
|
||||
public void onActivityRemoved(BusyImpl busy, UiActivity activity) {
|
||||
if (myRemovingActivityNow) return;
|
||||
|
||||
final Map<BusyImpl, Set<UiActivity>> toRemove = new HashMap<BusyImpl, Set<UiActivity>>();
|
||||
|
||||
try {
|
||||
myRemovingActivityNow = true;
|
||||
|
||||
myActivities.remove(activity);
|
||||
final Iterator<BusyImpl> objects = myObject2Activities.keySet().iterator();
|
||||
while (objects.hasNext()) {
|
||||
BusyImpl each = objects.next();
|
||||
if (each != busy) {
|
||||
each.removeActivity(activity);
|
||||
}
|
||||
if (each.isReady()) {
|
||||
final Set<UiActivity> activities = myObject2Activities.get(busy);
|
||||
toRemove.put(busy, activities);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
for (BusyImpl each : toRemove.keySet()) {
|
||||
final Set<UiActivity> activities = myObject2Activities.remove(each);
|
||||
myActivities2Object.remove(activities);
|
||||
}
|
||||
|
||||
myRemovingActivityNow = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void addActivity(UiActivity activity, Throwable allocation, ModalityState state) {
|
||||
getOrCreateBusy(activity);
|
||||
final Set<BusyImpl> busies = myObject2Activities.keySet();
|
||||
for (BusyImpl each : busies) {
|
||||
each.addActivity(activity, allocation, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +117,32 @@ public class ActivityMonitorTest extends UsefulTestCase {
|
||||
}
|
||||
|
||||
public void testReadyWithWatchActivities() throws Exception {
|
||||
final UiActivity root = new UiActivity("root");
|
||||
|
||||
final UiActivity op1 = new UiActivity("root", "operation1");
|
||||
final UiActivity op2 = new UiActivity("root", "operation2");
|
||||
|
||||
final UiActivity op12 = new UiActivity("root", "operation1", "operation12");
|
||||
final UiActivity op121 = new UiActivity("root", "operation1", "operation12", "operation121");
|
||||
|
||||
|
||||
myMonitor.addActivity(op1);
|
||||
assertBusy(null);
|
||||
assertReady(null, op2);
|
||||
assertBusy(null, op1);
|
||||
assertBusy(null, root);
|
||||
|
||||
myMonitor.removeActivity(op1);
|
||||
assertReady(null);
|
||||
assertReady(null, op2);
|
||||
assertReady(null, op1);
|
||||
assertReady(null, root);
|
||||
|
||||
myMonitor.addActivity(op12);
|
||||
assertBusy(null);
|
||||
assertBusy(null, root);
|
||||
assertBusy(null, op12);
|
||||
assertReady(null, op121);
|
||||
}
|
||||
|
||||
public void testModalityState() {
|
||||
@@ -159,9 +184,9 @@ public class ActivityMonitorTest extends UsefulTestCase {
|
||||
assertFalse(new UiActivity("root", "folder2").isSameOrGeneralFor(new UiActivity("anotherRoot")));
|
||||
}
|
||||
|
||||
private void assertReady(@Nullable Project key) {
|
||||
BusyObject.Impl busy = (BusyObject.Impl)(key != null ? myMonitor.getBusy(key) : myMonitor.getBusy());
|
||||
assertTrue(busy.isReady());
|
||||
private void assertReady(@Nullable Project key, UiActivity ... activities) {
|
||||
BusyObject.Impl busy = (BusyObject.Impl)(key != null ? myMonitor.getBusy(key, activities) : myMonitor.getBusy(activities));
|
||||
assertTrue("Must be READY, but was: BUSY", busy.isReady());
|
||||
|
||||
final boolean[] done = new boolean[] {false};
|
||||
busy.getReady(this).doWhenDone(new Runnable() {
|
||||
@@ -174,9 +199,9 @@ public class ActivityMonitorTest extends UsefulTestCase {
|
||||
assertTrue(done[0]);
|
||||
}
|
||||
|
||||
private void assertBusy(@Nullable Project key) {
|
||||
BusyObject.Impl busy = (BusyObject.Impl)(key != null ? myMonitor.getBusy(key) : myMonitor.getBusy());
|
||||
assertFalse(busy.isReady());
|
||||
private void assertBusy(@Nullable Project key, UiActivity ... activities) {
|
||||
BusyObject.Impl busy = (BusyObject.Impl)(key != null ? myMonitor.getBusy(key, activities) : myMonitor.getBusy(activities));
|
||||
assertFalse("Must be BUSY, but was: READY", busy.isReady());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user