/* * 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 myDisposeRunnables = new ArrayList(); 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; } }