| /* |
| * 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. |
| */ |
| |
| /* |
| * Class DebuggerTreeNodeImpl |
| * @author Jeka |
| */ |
| package com.intellij.debugger.ui.impl.watch; |
| |
| import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; |
| import com.intellij.debugger.engine.events.DebuggerContextCommandImpl; |
| import com.intellij.debugger.impl.DebuggerContextImpl; |
| import com.intellij.debugger.ui.impl.DebuggerTreeRenderer; |
| import com.intellij.debugger.ui.impl.tree.TreeBuilder; |
| import com.intellij.debugger.ui.impl.tree.TreeBuilderNode; |
| import com.intellij.debugger.ui.tree.DebuggerTreeNode; |
| import com.intellij.debugger.ui.tree.NodeDescriptor; |
| import com.intellij.debugger.ui.tree.ValueDescriptor; |
| import com.intellij.debugger.ui.tree.render.DescriptorLabelListener; |
| import com.intellij.debugger.ui.tree.render.NodeRenderer; |
| import com.intellij.openapi.application.ApplicationManager; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.util.Key; |
| import com.intellij.ui.SimpleColoredText; |
| import com.intellij.util.containers.HashMap; |
| import com.intellij.xdebugger.impl.ui.tree.ValueMarkup; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import java.util.Map; |
| |
| public class DebuggerTreeNodeImpl extends TreeBuilderNode implements DebuggerTreeNode{ |
| private Icon myIcon; |
| private SimpleColoredText myText; |
| private String myMarkupTooltipText; |
| private final DebuggerTree myTree; |
| private final Map myProperties = new HashMap(); |
| |
| private DebuggerTreeNodeImpl(DebuggerTree tree, NodeDescriptor descriptor) { |
| super(descriptor); |
| myTree = tree; |
| } |
| |
| @Override |
| public DebuggerTreeNodeImpl getParent() { |
| return (DebuggerTreeNodeImpl) super.getParent(); |
| } |
| |
| @Override |
| protected TreeBuilder getTreeBuilder() { |
| return myTree.getMutableModel(); |
| } |
| |
| public DebuggerTree getTree() { |
| return myTree; |
| } |
| |
| public String toString() { |
| return myText != null? myText.toString() : ""; |
| } |
| |
| @Override |
| public NodeDescriptorImpl getDescriptor() { |
| return (NodeDescriptorImpl)getUserObject(); |
| } |
| |
| @Override |
| public Project getProject() { |
| return getTree().getProject(); |
| } |
| |
| @Override |
| public void setRenderer(NodeRenderer renderer) { |
| ((ValueDescriptorImpl) getDescriptor()).setRenderer(renderer); |
| calcRepresentation(); |
| } |
| |
| private void updateCaches() { |
| final NodeDescriptorImpl descriptor = getDescriptor(); |
| myIcon = DebuggerTreeRenderer.getDescriptorIcon(descriptor); |
| final DebuggerContextImpl context = getTree().getDebuggerContext(); |
| myText = DebuggerTreeRenderer.getDescriptorText(context, descriptor, DebuggerTreeRenderer.getColorScheme(myTree), false); |
| if (descriptor instanceof ValueDescriptor) { |
| final ValueMarkup markup = ((ValueDescriptor)descriptor).getMarkup(context.getDebugProcess()); |
| myMarkupTooltipText = markup != null? markup.getToolTipText() : null; |
| } |
| else { |
| myMarkupTooltipText = null; |
| } |
| } |
| |
| public Icon getIcon() { |
| return myIcon; |
| } |
| |
| public SimpleColoredText getText() { |
| return myText; |
| } |
| |
| @Nullable |
| public String getMarkupTooltipText() { |
| return myMarkupTooltipText; |
| } |
| |
| @Override |
| public void clear() { |
| removeAllChildren(); |
| myIcon = null; |
| myText = null; |
| super.clear(); |
| } |
| |
| private void update(final DebuggerContextImpl context, final Runnable runnable, boolean labelOnly) { |
| if(!labelOnly) { |
| clear(); |
| } |
| |
| if(context != null && context.getDebugProcess() != null) { |
| getTree().saveState(this); |
| |
| myIcon = DebuggerTreeRenderer.getDescriptorIcon(MessageDescriptor.EVALUATING); |
| myText = DebuggerTreeRenderer.getDescriptorText(context, MessageDescriptor.EVALUATING, false); |
| |
| context.getDebugProcess().getManagerThread().invoke(new DebuggerContextCommandImpl(context) { |
| @Override |
| public void threadAction() { |
| runnable.run(); |
| } |
| |
| @Override |
| protected void commandCancelled() { |
| clear(); |
| getDescriptor().clear(); |
| updateCaches(); |
| |
| labelChanged(); |
| childrenChanged(true); |
| } |
| @Override |
| public Priority getPriority() { |
| return Priority.NORMAL; |
| } |
| |
| }); |
| } |
| |
| labelChanged(); |
| if(!labelOnly) { |
| childrenChanged(true); |
| } |
| } |
| |
| public void calcLabel() { |
| final DebuggerContextImpl context = getTree().getDebuggerContext(); |
| update(context, new Runnable() { |
| @Override |
| public void run() { |
| getDescriptor().updateRepresentation(context.createEvaluationContext(), new DescriptorLabelListener() { |
| @Override |
| public void labelChanged() { |
| updateCaches(); |
| DebuggerTreeNodeImpl.this.labelChanged(); |
| } |
| }); |
| } |
| }, true); |
| } |
| |
| public void calcRepresentation() { |
| final DebuggerContextImpl context = getTree().getDebuggerContext(); |
| update(context, new Runnable() { |
| @Override |
| public void run() { |
| getDescriptor().updateRepresentation(context.createEvaluationContext(), new DescriptorLabelListener() { |
| @Override |
| public void labelChanged() { |
| updateCaches(); |
| DebuggerTreeNodeImpl.this.labelChanged(); |
| } |
| }); |
| } |
| }, false); |
| } |
| |
| public void calcValue() { |
| final DebuggerContextImpl context = getTree().getDebuggerContext(); |
| update( |
| context, |
| new Runnable() { |
| @Override |
| public void run() { |
| EvaluationContextImpl evaluationContext = context.createEvaluationContext(); |
| getDescriptor().setContext(evaluationContext); |
| getDescriptor().updateRepresentation(evaluationContext, new DescriptorLabelListener() { |
| @Override |
| public void labelChanged() { |
| updateCaches(); |
| DebuggerTreeNodeImpl.this.labelChanged(); |
| } |
| }); |
| childrenChanged(true); |
| } |
| }, false); |
| } |
| |
| private static void invoke(Runnable r) { |
| if(ApplicationManager.getApplication().isDispatchThread()) { |
| r.run(); |
| } |
| else { |
| SwingUtilities.invokeLater(r); |
| } |
| } |
| |
| public void labelChanged() { |
| invoke(new Runnable() { |
| @Override |
| public void run() { |
| updateCaches(); |
| getTree().getMutableModel().nodeChanged(DebuggerTreeNodeImpl.this); |
| } |
| }); |
| } |
| |
| public void childrenChanged(final boolean scrollToVisible) { |
| invoke(new Runnable() { |
| @Override |
| public void run() { |
| getTree().getMutableModel().nodeStructureChanged(DebuggerTreeNodeImpl.this); |
| getTree().restoreState(DebuggerTreeNodeImpl.this); |
| } |
| }); |
| } |
| |
| public DebuggerTreeNodeImpl add(MessageDescriptor message) { |
| DebuggerTreeNodeImpl node = getNodeFactory().createMessageNode(message); |
| add(node); |
| return node; |
| } |
| |
| public NodeManagerImpl getNodeFactory() { |
| return myTree.getNodeFactory(); |
| } |
| |
| public Object getProperty(Key key) { |
| return myProperties.get(key); |
| } |
| |
| public void putProperty(Key key, Object data) { |
| myProperties.put(key, data); |
| } |
| |
| public static DebuggerTreeNodeImpl createNodeNoUpdate(DebuggerTree tree, NodeDescriptor descriptor) { |
| DebuggerTreeNodeImpl node = new DebuggerTreeNodeImpl(tree, descriptor); |
| node.updateCaches(); |
| return node; |
| } |
| |
| protected static DebuggerTreeNodeImpl createNode(DebuggerTree tree, NodeDescriptorImpl descriptor, EvaluationContextImpl evaluationContext) { |
| final DebuggerTreeNodeImpl node = new DebuggerTreeNodeImpl(tree, descriptor); |
| descriptor.updateRepresentationNoNotify(evaluationContext, new DescriptorLabelListener() { |
| @Override |
| public void labelChanged() { |
| node.updateCaches(); |
| node.labelChanged(); |
| } |
| }); |
| node.updateCaches(); |
| return node; |
| } |
| } |