blob: b88a9fcc6d4d2369928e73e083bea020a4b286f0 [file] [log] [blame]
/*
* Copyright 2000-2009 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 com.intellij.xdebugger.impl.ui.tree;
import com.intellij.openapi.util.Comparing;
import com.intellij.xdebugger.impl.ui.tree.nodes.RestorableStateNode;
import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode;
import com.intellij.xdebugger.impl.ui.tree.nodes.XValueContainerNode;
import org.jetbrains.annotations.NotNull;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import java.awt.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author nik
*/
public class XDebuggerTreeRestorer implements XDebuggerTreeListener, TreeSelectionListener {
private final XDebuggerTree myTree;
private final Rectangle myLastVisibleNodeRect;
private final Map<XDebuggerTreeNode, XDebuggerTreeState.NodeInfo> myNode2State = new HashMap<XDebuggerTreeNode, XDebuggerTreeState.NodeInfo>();
private final Map<RestorableStateNode, XDebuggerTreeState.NodeInfo> myNode2ParentState = new HashMap<RestorableStateNode, XDebuggerTreeState.NodeInfo>();
private boolean myStopRestoringSelection;
private boolean myInsideRestoring;
public XDebuggerTreeRestorer(final XDebuggerTree tree, Rectangle lastVisibleNodeRect) {
myTree = tree;
myLastVisibleNodeRect = lastVisibleNodeRect;
tree.addTreeListener(this);
tree.addTreeSelectionListener(this);
}
public void restoreChildren(final XDebuggerTreeNode treeNode, final XDebuggerTreeState.NodeInfo nodeInfo) {
if (nodeInfo.isExpanded()) {
myTree.expandPath(treeNode.getPath());
List<? extends XDebuggerTreeNode> children = treeNode.getLoadedChildren();
if (children != null) {
for (XDebuggerTreeNode child : children) {
restoreNode(child, nodeInfo);
}
}
myNode2State.put(treeNode, nodeInfo);
}
}
private void restoreNode(final XDebuggerTreeNode treeNode, final XDebuggerTreeState.NodeInfo parentInfo) {
if (treeNode instanceof RestorableStateNode) {
RestorableStateNode node = (RestorableStateNode)treeNode;
if (node.isComputed()) {
doRestoreNode(node, parentInfo, node.getName());
}
else {
myNode2ParentState.put(node, parentInfo);
}
}
}
private void doRestoreNode(final RestorableStateNode treeNode, final XDebuggerTreeState.NodeInfo parentInfo, final String nodeName) {
XDebuggerTreeState.NodeInfo childInfo = parentInfo.removeChild(nodeName);
if (childInfo != null) {
if (!Comparing.equal(childInfo.getValue(), treeNode.getRawValue())) {
treeNode.markChanged();
}
if (!myStopRestoringSelection && childInfo.isSelected()) {
try {
myInsideRestoring = true;
myTree.addSelectionPath(treeNode.getPath());
}
finally {
myInsideRestoring = false;
}
}
restoreChildren((XDebuggerTreeNode)treeNode, childInfo);
}
else {
treeNode.markChanged();
}
}
public void nodeLoaded(@NotNull final RestorableStateNode node, final String name) {
XDebuggerTreeState.NodeInfo parentInfo = myNode2ParentState.remove(node);
if (parentInfo != null) {
doRestoreNode(node, parentInfo, name);
}
disposeIfFinished();
}
private void disposeIfFinished() {
if (myNode2ParentState.isEmpty() && myNode2State.isEmpty()) {
if (myLastVisibleNodeRect != null) {
myTree.scrollRectToVisible(myLastVisibleNodeRect);
}
dispose();
}
}
public void childrenLoaded(@NotNull final XDebuggerTreeNode node, @NotNull final List<XValueContainerNode<?>> children, final boolean last) {
XDebuggerTreeState.NodeInfo nodeInfo = myNode2State.get(node);
if (nodeInfo != null) {
for (XDebuggerTreeNode child : children) {
restoreNode(child, nodeInfo);
}
}
if (last) {
myNode2State.remove(node);
disposeIfFinished();
}
}
public void dispose() {
myNode2ParentState.clear();
myNode2State.clear();
myTree.removeTreeListener(this);
myTree.removeTreeSelectionListener(this);
}
public void valueChanged(TreeSelectionEvent e) {
if (!myInsideRestoring) {
myStopRestoringSelection = true;
}
}
}