blob: 0acaf8779e1f60fcde1733961141c2f35f2b2c21 [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.debugger.ui;
import com.intellij.CommonBundle;
import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.DebuggerManagerEx;
import com.intellij.debugger.actions.DebuggerActions;
import com.intellij.debugger.engine.evaluation.CodeFragmentFactory;
import com.intellij.debugger.engine.evaluation.DefaultCodeFragmentFactory;
import com.intellij.debugger.engine.evaluation.TextWithImports;
import com.intellij.debugger.impl.DebuggerContextImpl;
import com.intellij.debugger.impl.DebuggerContextListener;
import com.intellij.debugger.impl.DebuggerSession;
import com.intellij.debugger.impl.PositionUtil;
import com.intellij.debugger.ui.impl.ValueNodeDnD;
import com.intellij.debugger.ui.impl.WatchDebuggerTree;
import com.intellij.debugger.ui.impl.WatchPanel;
import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeImpl;
import com.intellij.debugger.ui.impl.watch.NodeDescriptorImpl;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.psi.PsiElement;
import com.intellij.xdebugger.XDebuggerBundle;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.tree.TreeModel;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
public abstract class EvaluationDialog extends DialogWrapper {
private final MyEvaluationPanel myEvaluationPanel;
private final Project myProject;
private final DebuggerContextListener myContextListener;
private final DebuggerEditorImpl myEditor;
private final List<Runnable> myDisposeRunnables = new ArrayList<Runnable>();
public EvaluationDialog(Project project, TextWithImports text) {
super(project, true);
myProject = project;
setModal(false);
setCancelButtonText(CommonBundle.message("button.close"));
setOKButtonText(DebuggerBundle.message("button.evaluate"));
myEvaluationPanel = new MyEvaluationPanel(myProject);
myEditor = createEditor(DefaultCodeFragmentFactory.getInstance());
setDebuggerContext(getDebuggerContext());
initDialogData(text);
myContextListener = new DebuggerContextListener() {
public void changeEvent(DebuggerContextImpl newContext, int event) {
boolean close = true;
for (DebuggerSession session : DebuggerManagerEx.getInstanceEx(myProject).getSessions()) {
if (!session.isStopped()) {
close = false;
break;
}
}
if(close) {
close(CANCEL_EXIT_CODE);
}
else {
setDebuggerContext(newContext);
}
}
};
DebuggerManagerEx.getInstanceEx(myProject).getContextManager().addListener(myContextListener);
setHorizontalStretch(1f);
setVerticalStretch(1f);
}
protected void doOKAction() {
if (isOKActionEnabled()) {
doEvaluate();
}
}
protected void doEvaluate() {
if (myEditor == null || myEvaluationPanel == null) {
return;
}
myEvaluationPanel.clear();
TextWithImports codeToEvaluate = getCodeToEvaluate();
if (codeToEvaluate == null) {
return;
}
try {
setOKActionEnabled(false);
NodeDescriptorImpl descriptor = myEvaluationPanel.getWatchTree().addWatch(codeToEvaluate, "result").getDescriptor();
//if (descriptor instanceof EvaluationDescriptor) {
// final EvaluationDescriptor evalDescriptor = (EvaluationDescriptor)descriptor;
// evalDescriptor.setCodeFragmentFactory(myEditor.getCurrentFactory());
//}
myEvaluationPanel.getWatchTree().rebuild(getDebuggerContext());
descriptor.myIsExpanded = true;
}
finally {
setOKActionEnabled(true);
}
getEditor().addRecent(getCodeToEvaluate());
final DebuggerSession session = myEvaluationPanel.getContextManager().getContext().getDebuggerSession();
if (session != null) {
session.refresh(true);
}
}
@Nullable
protected TextWithImports getCodeToEvaluate() {
TextWithImports text = getEditor().getText();
String s = text.getText();
if (s != null) {
s = s.trim();
}
if ("".equals(s)) {
return null;
}
return text;
}
public JComponent getPreferredFocusedComponent() {
return myEditor.getPreferredFocusedComponent();
}
protected String getDimensionServiceKey() {
return "#com.intellij.debugger.ui.EvaluationDialog2";
}
protected void addDisposeRunnable (Runnable runnable) {
myDisposeRunnables.add(runnable);
}
public void dispose() {
for (Runnable runnable : myDisposeRunnables) {
runnable.run();
}
myDisposeRunnables.clear();
myEditor.dispose();
DebuggerManagerEx.getInstanceEx(myProject).getContextManager().removeListener(myContextListener);
myEvaluationPanel.dispose();
super.dispose();
}
protected class MyEvaluationPanel extends WatchPanel {
public MyEvaluationPanel(final Project project) {
super(project, (DebuggerManagerEx.getInstanceEx(project)).getContextManager());
final WatchDebuggerTree watchTree = getWatchTree();
final AnAction setValueAction = ActionManager.getInstance().getAction(DebuggerActions.SET_VALUE);
setValueAction.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0)), watchTree);
registerDisposable(new Disposable() {
public void dispose() {
setValueAction.unregisterCustomShortcutSet(watchTree);
}
});
setUpdateEnabled(true);
getTree().getEmptyText().setText(XDebuggerBundle.message("debugger.no.results"));
new ValueNodeDnD(myTree, project);
}
protected ActionPopupMenu createPopupMenu() {
ActionGroup group = (ActionGroup)ActionManager.getInstance().getAction(DebuggerActions.EVALUATION_DIALOG_POPUP);
return ActionManager.getInstance().createActionPopupMenu(DebuggerActions.EVALUATION_DIALOG_POPUP, group);
}
protected void changeEvent(DebuggerContextImpl newContext, int event) {
if (event == DebuggerSession.EVENT_REFRESH || event == DebuggerSession.EVENT_REFRESH_VIEWS_ONLY) {
// in order not to spoil the evaluation result do not re-evaluate the tree
final TreeModel treeModel = getTree().getModel();
updateTree(treeModel, (DebuggerTreeNodeImpl)treeModel.getRoot());
}
}
private void updateTree(final TreeModel model, final DebuggerTreeNodeImpl node) {
if (node == null) {
return;
}
if (node.getDescriptor().myIsExpanded) {
final int count = model.getChildCount(node);
for (int idx = 0; idx < count; idx++) {
final DebuggerTreeNodeImpl child = (DebuggerTreeNodeImpl)model.getChild(node, idx);
updateTree(model, child);
}
}
node.labelChanged();
}
}
protected void setDebuggerContext(DebuggerContextImpl context) {
final PsiElement contextElement = PositionUtil.getContextElement(context);
myEditor.setContext(contextElement);
}
protected PsiElement getContext() {
return myEditor.getContext();
}
protected void initDialogData(TextWithImports text) {
getEditor().setText(text);
myEvaluationPanel.clear();
}
public DebuggerContextImpl getDebuggerContext() {
return DebuggerManagerEx.getInstanceEx(myProject).getContext();
}
public DebuggerEditorImpl getEditor() {
return myEditor;
}
protected abstract DebuggerEditorImpl createEditor(final CodeFragmentFactory factory);
protected MyEvaluationPanel getEvaluationPanel() {
return myEvaluationPanel;
}
public Project getProject() {
return myProject;
}
}