/*
* Copyright 2003-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jetbrains.mps.ide.projectPane.logicalview.highlighting.listeners;
import jetbrains.mps.classloading.ClassLoaderManager;
import jetbrains.mps.classloading.MPSClassesListenerAdapter;
import jetbrains.mps.ide.projectPane.logicalview.highlighting.visitor.TreeUpdateVisitor;
import jetbrains.mps.ide.ui.tree.module.ProjectModuleTreeNode;
import jetbrains.mps.module.ReloadableModuleBase;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Semaphore;
/**
* Control listeners that track changes to module node.
* Use {@link #startListening()}/{@link #startListening()} to turn change tracking on and off.
* Use {@link #attach(jetbrains.mps.ide.ui.tree.module.ProjectModuleTreeNode)} and {@link #detach(jetbrains.mps.ide.ui.tree.module.ProjectModuleTreeNode)}
* to include/exclude given node from update.
*/
public final class ModuleNodeListeners {
private final List<ProjectModuleTreeNode> myNodes = new ArrayList<ProjectModuleTreeNode>();
private final Semaphore myListAccess;
private final TreeUpdateVisitor myChecker;
private final MyReloadAdapter myHandler = new MyReloadAdapter();
public ModuleNodeListeners(@NotNull TreeUpdateVisitor errorChecker) {
myChecker = errorChecker;
myListAccess = new Semaphore(1);
}
public void startListening() {
ClassLoaderManager.getInstance().addClassesHandler(myHandler);
}
public void stopListening() {
ClassLoaderManager.getInstance().removeClassesHandler(myHandler);
}
public void attach(@NotNull ProjectModuleTreeNode node) {
myListAccess.acquireUninterruptibly();
try {
myNodes.add(node);
} finally {
myListAccess.release();
}
node.accept(myChecker);
}
public void detach(@NotNull ProjectModuleTreeNode node) {
myListAccess.acquireUninterruptibly();
try {
myNodes.remove(node);
} finally {
myListAccess.release();
}
}
void refreshTreeNodes() {
List<ProjectModuleTreeNode> a = Collections.emptyList();
myListAccess.acquireUninterruptibly();
try {
a = new ArrayList<ProjectModuleTreeNode>(myNodes);
} finally {
myListAccess.release();
}
for (ProjectModuleTreeNode n : a) {
n.accept(myChecker);
}
}
private class MyReloadAdapter extends MPSClassesListenerAdapter {
@Override
public void afterClassesLoaded(Set<? extends ReloadableModuleBase> loadedModules) {
refreshTreeNodes();
}
}
}