/* * Copyright 2000-2012 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.actions; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.SmartList; import com.intellij.xdebugger.frame.XFullValueEvaluator; import com.intellij.xdebugger.impl.ui.XValueTextProvider; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import com.intellij.xdebugger.impl.ui.tree.nodes.HeadlessValueEvaluationCallback; import com.intellij.xdebugger.impl.ui.tree.nodes.WatchMessageNode; import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.tree.TreePath; import java.util.List; public abstract class XFetchValueActionBase extends AnAction { @Nullable private static TreePath[] getSelectedNodes(DataContext dataContext) { XDebuggerTree tree = XDebuggerTree.getTree(dataContext); return tree == null ? null : tree.getSelectionPaths(); } @Override public void update(AnActionEvent e) { TreePath[] paths = getSelectedNodes(e.getDataContext()); if (paths != null) { for (TreePath path : paths) { Object node = path.getLastPathComponent(); if (node instanceof XValueNodeImpl) { if (((XValueNodeImpl)node).isComputed()) { e.getPresentation().setEnabled(true); return; } } else if (node instanceof WatchMessageNode) { e.getPresentation().setEnabled(true); return; } } } e.getPresentation().setEnabled(false); } @Override public void actionPerformed(final AnActionEvent e) { TreePath[] paths = getSelectedNodes(e.getDataContext()); if (paths == null) { return; } ValueCollector valueCollector = new ValueCollector(); for (TreePath path : paths) { Object node = path.getLastPathComponent(); if (node instanceof XValueNodeImpl) { XValueNodeImpl valueNode = (XValueNodeImpl)node; XFullValueEvaluator fullValueEvaluator = valueNode.getFullValueEvaluator(); if (fullValueEvaluator == null) { String rawValue; if (valueNode.getValueContainer() instanceof XValueTextProvider) { rawValue = ((XValueTextProvider)valueNode.getValueContainer()).getValueText(); } else { rawValue = valueNode.getRawValue(); } valueCollector.add(StringUtil.notNullize(rawValue)); } else { new CopyValueEvaluationCallback(valueNode, valueCollector).startFetchingValue(fullValueEvaluator); } } else if (node instanceof WatchMessageNode) { valueCollector.add(((WatchMessageNode)node).getExpression().getExpression()); } } valueCollector.processed = true; valueCollector.finish(e.getProject()); } private final class ValueCollector { private final List values = new SmartList(); private volatile boolean processed; public void add(@NotNull String value) { values.add(value); } public void finish(Project project) { if (processed && !values.contains(null) && !project.isDisposed()) { handle(project, StringUtil.join(values, "\n")); } } public int acquire() { int index = values.size(); values.add(null); return index; } public void evaluationComplete(int index, @NotNull String value, Project project) { values.set(index, value); finish(project); } } protected abstract void handle(final Project project, final String value); private static final class CopyValueEvaluationCallback extends HeadlessValueEvaluationCallback { private final int myValueIndex; private final ValueCollector myValueCollector; public CopyValueEvaluationCallback(@NotNull XValueNodeImpl node, @NotNull ValueCollector valueCollector) { super(node); myValueCollector = valueCollector; myValueIndex = valueCollector.acquire(); } @Override protected void evaluationComplete(@NotNull String value, @NotNull Project project) { myValueCollector.evaluationComplete(myValueIndex, value, project); } } }