/* * 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; import jetbrains.mps.ide.ui.smodel.SModelEventsDispatcher; import jetbrains.mps.ide.ui.tree.MPSTree; import jetbrains.mps.ide.ui.tree.MPSTreeNode; import jetbrains.mps.ide.ui.tree.MPSTreeNodeListener; import jetbrains.mps.ide.ui.tree.smodel.SModelTreeNode; import jetbrains.mps.project.Project; import jetbrains.mps.smodel.event.SModelEvent; import org.jetbrains.annotations.NotNull; import org.jetbrains.mps.openapi.model.EditableSModel; import org.jetbrains.mps.openapi.model.SModel; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Tracks SModelTreeNodes and updates (with ModelStructureUpdate help) tree structure according to model changes. * @author Artem Tikhomirov */ class TreeStructureUpdate implements MPSTreeNodeListener { private final ProjectTree myProjectTree; private final SModelEventsDispatcher myEventsListener = new SModelEventsDispatcher(); private final Map<SModelTreeNode, ModelChangeListener> myListeners = new HashMap<SModelTreeNode, ModelChangeListener>(); public TreeStructureUpdate(ProjectTree projectTree) { myProjectTree = projectTree; } public void init() { myProjectTree.addTreeNodeListener(this); } public void dispose() { myProjectTree.removeTreeNodeListener(this); myEventsListener.dispose(); } @Override public void treeNodeAdded(MPSTreeNode treeNode, MPSTree tree) { if (treeNode instanceof SModelTreeNode) { final SModelTreeNode mn = (SModelTreeNode) treeNode; if (mn.getModel() instanceof EditableSModel) { assert !myListeners.containsKey(mn); final ModelChangeListener l = new ModelChangeListener(myProjectTree.getProject(), mn); myEventsListener.registerListener(l); myListeners.put(mn, l); } } } @Override public void treeNodeRemoved(MPSTreeNode treeNode, MPSTree tree) { if (treeNode instanceof SModelTreeNode) { final ModelChangeListener l = myListeners.remove(treeNode); // might be SModelTreeNode for a !EditableSModel if (l != null) { myEventsListener.unregisterListener(l); } } } @Override public void treeNodeUpdated(MPSTreeNode treeNode, MPSTree tree) {} @Override public void beforeTreeDisposed(MPSTree tree) {} private static class ModelChangeListener implements SModelEventsDispatcher.SModelEventsListener { private final Project myProject; private final SModelTreeNode myTreeNode; private ModelStructureUpdate myUpdater; public ModelChangeListener(@NotNull Project project, @NotNull SModelTreeNode treeNode) { myProject = project; myTreeNode = treeNode; } @NotNull @Override public SModel getModelDescriptor() { return myTreeNode.getModel(); } @Override public void eventsHappened(List<SModelEvent> events) { if (myUpdater == null) { myUpdater = new ModelStructureUpdate(myProject, myTreeNode); myUpdater.setDependencyRecorder(myTreeNode.getDependencyRecorder()); } myUpdater.eventsHappenedInCommand(events); } } }