From 93a2c9ef22a39fa169ff4af13e55aeb16a7f3557 Mon Sep 17 00:00:00 2001 From: nik Date: Wed, 18 Sep 2013 11:36:58 +0400 Subject: [PATCH] xdebugger: debugger trees decoupled from XDebugSession --- .../evaluate/XDebuggerEvaluationDialog.java | 4 +- .../impl/evaluate/quick/XValueHint.java | 7 +- .../impl/frame/WatchInplaceEditor.java | 31 +-- .../xdebugger/impl/frame/XVariablesView.java | 6 +- .../xdebugger/impl/frame/XWatchesView.java | 229 +--------------- .../impl/frame/XWatchesViewImpl.java | 256 ++++++++++++++++++ .../impl/frame/actions/XEditWatchAction.java | 4 +- .../impl/frame/actions/XNewWatchAction.java | 4 +- .../actions/XRemoveAllWatchesAction.java | 14 +- .../frame/actions/XRemoveWatchAction.java | 14 +- .../frame/actions/XWatchesTreeActionBase.java | 13 +- .../xdebugger/impl/ui/XDebugSessionTab.java | 20 +- .../xdebugger/impl/ui/tree/XDebuggerTree.java | 18 +- .../impl/ui/tree/XDebuggerTreePanel.java | 9 +- .../impl/ui/tree/XInspectDialog.java | 14 +- .../ui/tree/actions/XAddToWatchesAction.java | 19 +- .../tree/actions/XDebuggerTreeActionBase.java | 4 +- .../tree/actions/XFetchValueActionBase.java | 50 ++-- .../impl/ui/tree/actions/XInspectAction.java | 3 +- .../ui/tree/actions/XJumpToSourceAction.java | 6 +- .../tree/actions/XJumpToTypeSourceAction.java | 6 +- .../impl/ui/tree/actions/XSetValueAction.java | 4 +- .../impl/ui/tree/nodes/WatchesRootNode.java | 13 +- .../impl/ui/tree/nodes/XValueNodeImpl.java | 5 +- 24 files changed, 405 insertions(+), 348 deletions(-) create mode 100644 platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java index 61c22c23ad94..badb628d33b1 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java @@ -29,6 +29,7 @@ import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.evaluation.EvaluationMode; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; import com.intellij.xdebugger.evaluation.XDebuggerEvaluator; +import com.intellij.xdebugger.impl.XDebugSessionImpl; import com.intellij.xdebugger.impl.actions.XDebuggerActions; import com.intellij.xdebugger.impl.ui.XDebuggerEditorBase; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; @@ -84,7 +85,8 @@ public class XDebuggerEvaluationDialog extends DialogWrapper { }; mySession.addSessionListener(mySessionListener); - myTreePanel = new XDebuggerTreePanel(session, editorsProvider, myDisposable, sourcePosition, XDebuggerActions.EVALUATE_DIALOG_TREE_POPUP_GROUP); + myTreePanel = new XDebuggerTreePanel(session.getProject(), editorsProvider, myDisposable, sourcePosition, XDebuggerActions.EVALUATE_DIALOG_TREE_POPUP_GROUP, + ((XDebugSessionImpl)session).getValueMarkers()); myResultPanel = new JPanel(new BorderLayout()); myResultPanel.add(new JLabel(XDebuggerBundle.message("xdebugger.evaluate.label.result")), BorderLayout.NORTH); myResultPanel.add(myTreePanel.getMainPanel(), BorderLayout.CENTER); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java index 63ac338674e9..29deaf432f1c 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java @@ -32,10 +32,12 @@ import com.intellij.xdebugger.frame.XFullValueEvaluator; import com.intellij.xdebugger.frame.XValue; import com.intellij.xdebugger.frame.XValuePlace; import com.intellij.xdebugger.frame.presentation.XValuePresentation; +import com.intellij.xdebugger.impl.XDebugSessionImpl; import com.intellij.xdebugger.impl.actions.XDebuggerActions; import com.intellij.xdebugger.impl.actions.handlers.XDebuggerEvaluateActionHandler; import com.intellij.xdebugger.impl.evaluate.quick.common.AbstractValueHint; import com.intellij.xdebugger.impl.evaluate.quick.common.ValueHintType; +import com.intellij.xdebugger.impl.frame.XValueMarkers; import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import com.intellij.xdebugger.impl.ui.tree.nodes.XEvaluationCallbackBase; @@ -128,8 +130,9 @@ public class XValueHint extends AbstractValueHint { } private void showTree(final XValue value, final String name) { - XDebuggerTree tree = new XDebuggerTree(myDebugSession, myDebugSession.getDebugProcess().getEditorsProvider(), - myDebugSession.getCurrentPosition(), XDebuggerActions.INSPECT_TREE_POPUP_GROUP); + XValueMarkers valueMarkers = ((XDebugSessionImpl)myDebugSession).getValueMarkers(); + XDebuggerTree tree = new XDebuggerTree(myDebugSession.getProject(), myDebugSession.getDebugProcess().getEditorsProvider(), + myDebugSession.getCurrentPosition(), XDebuggerActions.INSPECT_TREE_POPUP_GROUP, valueMarkers); tree.getModel().addTreeModelListener(createTreeListener(tree)); XValueHintTreeComponent component = new XValueHintTreeComponent(this, tree, Pair.create(value, name)); showTreePopup(component, tree, name); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/WatchInplaceEditor.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/WatchInplaceEditor.java index abfc06a0e4d9..784908be3613 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/WatchInplaceEditor.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/WatchInplaceEditor.java @@ -17,16 +17,14 @@ package com.intellij.xdebugger.impl.frame; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.AppUIUtil; -import com.intellij.xdebugger.XStackFrameAwareSession; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XDebugSessionAdapter; -import com.intellij.xdebugger.impl.XDebugSessionImpl; -import com.intellij.xdebugger.impl.ui.XDebugSessionTab; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeInplaceEditor; import com.intellij.xdebugger.impl.ui.tree.nodes.WatchNode; import com.intellij.xdebugger.impl.ui.tree.nodes.WatchesRootNode; import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -36,20 +34,19 @@ import javax.swing.*; */ public class WatchInplaceEditor extends XDebuggerTreeInplaceEditor { private final WatchesRootNode myRootNode; + private final XWatchesView myWatchesView; @Nullable private final WatchNode myOldNode; - public WatchInplaceEditor(WatchesRootNode rootNode, - final WatchNode node, + public WatchInplaceEditor(@NotNull WatchesRootNode rootNode, + @NotNull XDebugSession session, XWatchesView watchesView, final WatchNode node, @NonNls final String historyId, final @Nullable WatchNode oldNode) { super((XDebuggerTreeNode)node, historyId); myRootNode = rootNode; + myWatchesView = watchesView; myOldNode = oldNode; myExpressionEditor.setText(oldNode != null ? oldNode.getExpression() : ""); - final XStackFrameAwareSession session = rootNode.getTree().getSession(); - if (session instanceof XDebugSession) { - new WatchEditorSessionListener((XDebugSession)session).install(); - } + new WatchEditorSessionListener(session).install(); } protected JComponent createInplaceEditorComponent() { @@ -61,7 +58,7 @@ public class WatchInplaceEditor extends XDebuggerTreeInplaceEditor { super.cancelEditing(); int index = myRootNode.removeChildNode(getNode()); if (myOldNode != null && index != -1) { - getWatchesView().addWatchExpression(myOldNode.getExpression(), index, false); + myWatchesView.addWatchExpression(myOldNode.getExpression(), index, false); } } @@ -71,24 +68,14 @@ public class WatchInplaceEditor extends XDebuggerTreeInplaceEditor { super.doOKAction(); int index = myRootNode.removeChildNode(getNode()); if (!StringUtil.isEmpty(expression) && index != -1) { - getWatchesView().addWatchExpression(expression, index, false); - } - } - - private XWatchesView getWatchesView() { - if (myRootNode.getTree().getSession() instanceof XDebugSessionImpl) { - XDebugSessionTab tab = ((XDebugSessionImpl)myRootNode.getTree().getSession()).getSessionTab(); - return tab.getWatchesView(); - } - else { - return null; + myWatchesView.addWatchExpression(expression, index, false); } } private class WatchEditorSessionListener extends XDebugSessionAdapter { private final XDebugSession mySession; - public WatchEditorSessionListener(XDebugSession session) { + public WatchEditorSessionListener(@NotNull XDebugSession session) { mySession = session; } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java index eb8ddf6924fa..e2d65b67d8d9 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java @@ -17,12 +17,13 @@ package com.intellij.xdebugger.impl.frame; import com.intellij.ide.dnd.DnDManager; import com.intellij.openapi.Disposable; -import com.intellij.xdebugger.XStackFrameAwareSession; import com.intellij.xdebugger.XDebugProcess; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XDebuggerBundle; +import com.intellij.xdebugger.XStackFrameAwareSession; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; import com.intellij.xdebugger.frame.XStackFrame; +import com.intellij.xdebugger.impl.XDebugSessionImpl; import com.intellij.xdebugger.impl.actions.XDebuggerActions; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreePanel; @@ -49,7 +50,8 @@ public class XVariablesView extends XDebugViewBase { public XVariablesView(@NotNull XStackFrameAwareSession session, @Nullable final Disposable parentDisposable) { super(session, parentDisposable); XDebuggerEditorsProvider editorsProvider = session.getEditorsProvider(); - myDebuggerTreePanel = new XDebuggerTreePanel(session, editorsProvider, this, null, XDebuggerActions.VARIABLES_TREE_POPUP_GROUP); + XValueMarkers markers = session instanceof XDebugSessionImpl ? ((XDebugSessionImpl)session).getValueMarkers() : null; + myDebuggerTreePanel = new XDebuggerTreePanel(session.getProject(), editorsProvider, this, null, XDebuggerActions.VARIABLES_TREE_POPUP_GROUP, markers); myDebuggerTreePanel.getTree().getEmptyText().setText(XDebuggerBundle.message("debugger.variables.not.available")); DnDManager.getInstance().registerSource(myDebuggerTreePanel, myDebuggerTreePanel.getTree()); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesView.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesView.java index c2a0408e280a..9196f5157b6e 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesView.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesView.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -15,236 +15,21 @@ */ package com.intellij.xdebugger.impl.frame; -import com.intellij.ide.DataManager; -import com.intellij.ide.dnd.DnDEvent; -import com.intellij.ide.dnd.DnDManager; -import com.intellij.ide.dnd.DnDNativeTarget; -import com.intellij.openapi.Disposable; -import com.intellij.openapi.actionSystem.*; -import com.intellij.openapi.util.SystemInfo; -import com.intellij.ui.AnActionButton; -import com.intellij.ui.AnActionButtonRunnable; -import com.intellij.ui.CaptionPanel; -import com.intellij.ui.ToolbarDecorator; -import com.intellij.ui.border.CustomLineBorder; -import com.intellij.util.ArrayUtil; -import com.intellij.util.ui.tree.TreeUtil; -import com.intellij.xdebugger.XDebugSession; -import com.intellij.xdebugger.XDebuggerBundle; -import com.intellij.xdebugger.frame.XStackFrame; -import com.intellij.xdebugger.impl.actions.XDebuggerActions; -import com.intellij.xdebugger.impl.ui.XDebugSessionData; -import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; -import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreePanel; -import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeRestorer; -import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeState; -import com.intellij.xdebugger.impl.ui.tree.nodes.WatchNode; -import com.intellij.xdebugger.impl.ui.tree.nodes.WatchesRootNode; +import com.intellij.openapi.actionSystem.DataKey; import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode; -import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import javax.swing.*; -import java.awt.*; -import java.awt.datatransfer.DataFlavor; -import java.awt.event.KeyEvent; -import java.util.ArrayList; import java.util.List; /** * @author nik */ -public class XWatchesView extends XDebugViewBase implements DnDNativeTarget { - private final XDebuggerTreePanel myTreePanel; - private XDebuggerTreeState myTreeState; - private XDebuggerTreeRestorer myTreeRestorer; - private final WatchesRootNode myRootNode; - private final XDebugSessionData mySessionData; - private final JPanel myDecoratedPanel; +public interface XWatchesView { + DataKey DATA_KEY = DataKey.create("XDEBUGGER_WATCHES_VIEW"); - public XWatchesView(@NotNull final XDebugSession session, @Nullable final Disposable parentDisposable, final XDebugSessionData sessionData) { - super(session, parentDisposable); - mySessionData = sessionData; - myTreePanel = new XDebuggerTreePanel(session, session.getDebugProcess().getEditorsProvider(), this, null, - XDebuggerActions.WATCHES_TREE_POPUP_GROUP); + void addWatchExpression(@NotNull String expression, int index, boolean navigateToWatchNode); - ActionManager actionManager = ActionManager.getInstance(); + void removeWatches(List nodes); - XDebuggerTree tree = myTreePanel.getTree(); - actionManager.getAction(XDebuggerActions.XNEW_WATCH).registerCustomShortcutSet(CommonShortcuts.INSERT, tree); - actionManager.getAction(XDebuggerActions.XREMOVE_WATCH).registerCustomShortcutSet(CommonShortcuts.DELETE, tree); - - CustomShortcutSet f2Shortcut = new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0)); - actionManager.getAction(XDebuggerActions.XEDIT_WATCH).registerCustomShortcutSet(f2Shortcut, tree); - - DnDManager.getInstance().registerTarget(this, tree); - myRootNode = new WatchesRootNode(tree, sessionData.getWatchExpressions()); - tree.setRoot(myRootNode, false); - - final ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myTreePanel.getTree()).disableUpDownActions(); - decorator.setAddAction(new AnActionButtonRunnable() { - @Override - public void run(AnActionButton button) { - executeAction(XDebuggerActions.XNEW_WATCH); - } - }); - decorator.setRemoveAction(new AnActionButtonRunnable() { - @Override - public void run(AnActionButton button) { - executeAction(XDebuggerActions.XREMOVE_WATCH); - } - }); - CustomLineBorder border = new CustomLineBorder(CaptionPanel.CNT_ACTIVE_BORDER_COLOR, - SystemInfo.isMac ? 1 : 0, 0, - SystemInfo.isMac ? 0 : 1, 0); - decorator.setToolbarBorder(border); - myDecoratedPanel = decorator.createPanel(); - myDecoratedPanel.setBorder(null); - - myTreePanel.getTree().getEmptyText().setText(XDebuggerBundle.message("debugger.no.watches")); - - } - - private void executeAction(final String watch) { - AnAction action = ActionManager.getInstance().getAction(watch); - Presentation presentation = action.getTemplatePresentation().clone(); - DataContext context = DataManager.getInstance().getDataContext(myTreePanel.getTree()); - - AnActionEvent actionEvent = - new AnActionEvent(null, context, ActionPlaces.DEBUGGER_TOOLBAR, presentation, ActionManager.getInstance(), 0); - action.actionPerformed(actionEvent); - } - - public void addWatchExpression(@NotNull String expression, int index, final boolean navigateToWatchNode) { - XStackFrame stackFrame = mySession.getCurrentStackFrame(); - myRootNode.addWatchExpression(stackFrame == null ? null : stackFrame.getEvaluator(), expression, index, navigateToWatchNode); - updateSessionData(); - } - - @Override - protected void rebuildView(final SessionEvent event) { - XStackFrame stackFrame = mySession.getCurrentStackFrame(); - XDebuggerTree tree = myTreePanel.getTree(); - - if (event == SessionEvent.BEFORE_RESUME || event == SessionEvent.SETTINGS_CHANGED) { - if (myTreeRestorer != null) { - myTreeRestorer.dispose(); - } - myTreeState = XDebuggerTreeState.saveState(tree); - if (event == SessionEvent.BEFORE_RESUME) { - return; - } - } - - if (stackFrame != null) { - tree.setSourcePosition(stackFrame.getSourcePosition()); - myRootNode.updateWatches(stackFrame.getEvaluator()); - if (myTreeState != null) { - myTreeRestorer = myTreeState.restoreState(tree); - } - } - else { - tree.setSourcePosition(null); - myRootNode.updateWatches(null); - } - } - - @Override - public void dispose() { - DnDManager.getInstance().unregisterTarget(this, myTreePanel.getTree()); - super.dispose(); - } - - public XDebuggerTree getTree() { - return myTreePanel.getTree(); - } - - public JPanel getMainPanel() { - return myDecoratedPanel; - } - - public void removeWatches(final List nodes) { - List children = myRootNode.getAllChildren(); - int minIndex = Integer.MAX_VALUE; - List toRemove = new ArrayList(); - if (children != null) { - for (XDebuggerTreeNode node : nodes) { - @SuppressWarnings("SuspiciousMethodCalls") - int index = children.indexOf(node); - if (index != -1) { - toRemove.add(node); - minIndex = Math.min(minIndex, index); - } - } - } - myRootNode.removeChildren(toRemove); - - List newChildren = myRootNode.getAllChildren(); - if (newChildren != null && !newChildren.isEmpty()) { - WatchNode node = minIndex < newChildren.size() ? newChildren.get(minIndex) : newChildren.get(newChildren.size() - 1); - TreeUtil.selectNode(myTreePanel.getTree(), node); - } - updateSessionData(); - } - - public void removeAllWatches() { - myRootNode.removeAllChildren(); - updateSessionData(); - } - - private void updateSessionData() { - List watchExpressions = new ArrayList(); - final List children = myRootNode.getAllChildren(); - if (children != null) { - for (WatchNode child : children) { - watchExpressions.add(child.getExpression()); - } - } - mySessionData.setWatchExpressions(ArrayUtil.toStringArray(watchExpressions)); - } - - @Override - public boolean update(final DnDEvent aEvent) { - Object object = aEvent.getAttachedObject(); - boolean possible = false; - if (object instanceof XValueNodeImpl[]) { - possible = true; - } - else if (object instanceof EventInfo) { - possible = ((EventInfo)object).getTextForFlavor(DataFlavor.stringFlavor) != null; - } - - aEvent.setDropPossible(possible, XDebuggerBundle.message("xdebugger.drop.text.add.to.watches")); - - return true; - } - - @Override - public void drop(final DnDEvent aEvent) { - Object object = aEvent.getAttachedObject(); - if (object instanceof XValueNodeImpl[]) { - final XValueNodeImpl[] nodes = (XValueNodeImpl[])object; - for (XValueNodeImpl node : nodes) { - String expression = node.getValueContainer().getEvaluationExpression(); - if (expression != null) { - addWatchExpression(expression, -1, false); - } - } - } - else if (object instanceof EventInfo) { - String text = ((EventInfo)object).getTextForFlavor(DataFlavor.stringFlavor); - if (text != null) { - addWatchExpression(text, -1, false); - } - } - } - - @Override - public void cleanUpOnLeave() { - } - - @Override - public void updateDraggedImage(final Image image, final Point dropPoint, final Point imageOffset) { - } + void removeAllWatches(); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java new file mode 100644 index 000000000000..557d3fcdff2c --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java @@ -0,0 +1,256 @@ +/* + * 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.frame; + +import com.intellij.ide.DataManager; +import com.intellij.ide.dnd.DnDEvent; +import com.intellij.ide.dnd.DnDManager; +import com.intellij.ide.dnd.DnDNativeTarget; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.ui.AnActionButton; +import com.intellij.ui.AnActionButtonRunnable; +import com.intellij.ui.CaptionPanel; +import com.intellij.ui.ToolbarDecorator; +import com.intellij.ui.border.CustomLineBorder; +import com.intellij.util.ArrayUtil; +import com.intellij.util.ui.tree.TreeUtil; +import com.intellij.xdebugger.XDebugSession; +import com.intellij.xdebugger.XDebuggerBundle; +import com.intellij.xdebugger.frame.XStackFrame; +import com.intellij.xdebugger.impl.XDebugSessionImpl; +import com.intellij.xdebugger.impl.actions.XDebuggerActions; +import com.intellij.xdebugger.impl.ui.XDebugSessionData; +import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; +import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreePanel; +import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeRestorer; +import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeState; +import com.intellij.xdebugger.impl.ui.tree.nodes.WatchNode; +import com.intellij.xdebugger.impl.ui.tree.nodes.WatchesRootNode; +import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode; +import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.*; +import java.awt.datatransfer.DataFlavor; +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.List; + +/** + * @author nik + */ +public class XWatchesViewImpl extends XDebugViewBase implements DnDNativeTarget, XWatchesView { + private final XDebuggerTreePanel myTreePanel; + private XDebuggerTreeState myTreeState; + private XDebuggerTreeRestorer myTreeRestorer; + private final WatchesRootNode myRootNode; + private final XDebugSessionData mySessionData; + private final JPanel myDecoratedPanel; + + public XWatchesViewImpl(@NotNull final XDebugSession session, + @NotNull final Disposable parentDisposable, + final XDebugSessionData sessionData) { + super(session, parentDisposable); + mySessionData = sessionData; + myTreePanel = new XDebuggerTreePanel(session.getProject(), session.getDebugProcess().getEditorsProvider(), this, null, + XDebuggerActions.WATCHES_TREE_POPUP_GROUP, ((XDebugSessionImpl)session).getValueMarkers()); + + ActionManager actionManager = ActionManager.getInstance(); + + XDebuggerTree tree = myTreePanel.getTree(); + actionManager.getAction(XDebuggerActions.XNEW_WATCH).registerCustomShortcutSet(CommonShortcuts.INSERT, tree); + actionManager.getAction(XDebuggerActions.XREMOVE_WATCH).registerCustomShortcutSet(CommonShortcuts.DELETE, tree); + + CustomShortcutSet f2Shortcut = new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0)); + actionManager.getAction(XDebuggerActions.XEDIT_WATCH).registerCustomShortcutSet(f2Shortcut, tree); + + DnDManager.getInstance().registerTarget(this, tree); + Disposer.register(parentDisposable, new Disposable() { + @Override + public void dispose() { + DnDManager.getInstance().unregisterTarget(XWatchesViewImpl.this, myTreePanel.getTree()); + } + }); + myRootNode = new WatchesRootNode(tree, session, this, sessionData.getWatchExpressions()); + tree.setRoot(myRootNode, false); + + final ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myTreePanel.getTree()).disableUpDownActions(); + decorator.setAddAction(new AnActionButtonRunnable() { + @Override + public void run(AnActionButton button) { + executeAction(XDebuggerActions.XNEW_WATCH); + } + }); + decorator.setRemoveAction(new AnActionButtonRunnable() { + @Override + public void run(AnActionButton button) { + executeAction(XDebuggerActions.XREMOVE_WATCH); + } + }); + CustomLineBorder border = new CustomLineBorder(CaptionPanel.CNT_ACTIVE_BORDER_COLOR, + SystemInfo.isMac ? 1 : 0, 0, + SystemInfo.isMac ? 0 : 1, 0); + decorator.setToolbarBorder(border); + myDecoratedPanel = decorator.createPanel(); + myDecoratedPanel.setBorder(null); + + myTreePanel.getTree().getEmptyText().setText(XDebuggerBundle.message("debugger.no.watches")); + + } + + private void executeAction(final String watch) { + AnAction action = ActionManager.getInstance().getAction(watch); + Presentation presentation = action.getTemplatePresentation().clone(); + DataContext context = DataManager.getInstance().getDataContext(myTreePanel.getTree()); + + AnActionEvent actionEvent = + new AnActionEvent(null, context, ActionPlaces.DEBUGGER_TOOLBAR, presentation, ActionManager.getInstance(), 0); + action.actionPerformed(actionEvent); + } + + @Override + public void addWatchExpression(@NotNull String expression, int index, final boolean navigateToWatchNode) { + XStackFrame stackFrame = mySession.getCurrentStackFrame(); + myRootNode.addWatchExpression(stackFrame == null ? null : stackFrame.getEvaluator(), expression, index, navigateToWatchNode); + updateSessionData(); + } + + @Override + protected void rebuildView(final SessionEvent event) { + XStackFrame stackFrame = mySession.getCurrentStackFrame(); + XDebuggerTree tree = myTreePanel.getTree(); + + if (event == SessionEvent.BEFORE_RESUME || event == SessionEvent.SETTINGS_CHANGED) { + if (myTreeRestorer != null) { + myTreeRestorer.dispose(); + } + myTreeState = XDebuggerTreeState.saveState(tree); + if (event == SessionEvent.BEFORE_RESUME) { + return; + } + } + + if (stackFrame != null) { + tree.setSourcePosition(stackFrame.getSourcePosition()); + myRootNode.updateWatches(stackFrame.getEvaluator()); + if (myTreeState != null) { + myTreeRestorer = myTreeState.restoreState(tree); + } + } + else { + tree.setSourcePosition(null); + myRootNode.updateWatches(null); + } + } + + public XDebuggerTree getTree() { + return myTreePanel.getTree(); + } + + public JPanel getMainPanel() { + return myDecoratedPanel; + } + + @Override + public void removeWatches(final List nodes) { + List children = myRootNode.getAllChildren(); + int minIndex = Integer.MAX_VALUE; + List toRemove = new ArrayList(); + if (children != null) { + for (XDebuggerTreeNode node : nodes) { + @SuppressWarnings("SuspiciousMethodCalls") + int index = children.indexOf(node); + if (index != -1) { + toRemove.add(node); + minIndex = Math.min(minIndex, index); + } + } + } + myRootNode.removeChildren(toRemove); + + List newChildren = myRootNode.getAllChildren(); + if (newChildren != null && !newChildren.isEmpty()) { + WatchNode node = minIndex < newChildren.size() ? newChildren.get(minIndex) : newChildren.get(newChildren.size() - 1); + TreeUtil.selectNode(myTreePanel.getTree(), node); + } + updateSessionData(); + } + + @Override + public void removeAllWatches() { + myRootNode.removeAllChildren(); + updateSessionData(); + } + + private void updateSessionData() { + List watchExpressions = new ArrayList(); + final List children = myRootNode.getAllChildren(); + if (children != null) { + for (WatchNode child : children) { + watchExpressions.add(child.getExpression()); + } + } + mySessionData.setWatchExpressions(ArrayUtil.toStringArray(watchExpressions)); + } + + @Override + public boolean update(final DnDEvent aEvent) { + Object object = aEvent.getAttachedObject(); + boolean possible = false; + if (object instanceof XValueNodeImpl[]) { + possible = true; + } + else if (object instanceof EventInfo) { + possible = ((EventInfo)object).getTextForFlavor(DataFlavor.stringFlavor) != null; + } + + aEvent.setDropPossible(possible, XDebuggerBundle.message("xdebugger.drop.text.add.to.watches")); + + return true; + } + + @Override + public void drop(final DnDEvent aEvent) { + Object object = aEvent.getAttachedObject(); + if (object instanceof XValueNodeImpl[]) { + final XValueNodeImpl[] nodes = (XValueNodeImpl[])object; + for (XValueNodeImpl node : nodes) { + String expression = node.getValueContainer().getEvaluationExpression(); + if (expression != null) { + addWatchExpression(expression, -1, false); + } + } + } + else if (object instanceof EventInfo) { + String text = ((EventInfo)object).getTextForFlavor(DataFlavor.stringFlavor); + if (text != null) { + addWatchExpression(text, -1, false); + } + } + } + + @Override + public void cleanUpOnLeave() { + } + + @Override + public void updateDraggedImage(final Image image, final Point dropPoint, final Point imageOffset) { + } +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XEditWatchAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XEditWatchAction.java index ee21e92c5126..422c469cfd27 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XEditWatchAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XEditWatchAction.java @@ -16,10 +16,12 @@ package com.intellij.xdebugger.impl.frame.actions; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.xdebugger.impl.frame.XWatchesView; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import com.intellij.xdebugger.impl.ui.tree.nodes.WatchNode; import com.intellij.xdebugger.impl.ui.tree.nodes.WatchesRootNode; import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode; +import org.jetbrains.annotations.NotNull; import java.util.List; @@ -35,7 +37,7 @@ public class XEditWatchAction extends XWatchesTreeActionBase { } @Override - protected void perform(AnActionEvent e, XDebuggerTree tree) { + protected void perform(@NotNull AnActionEvent e, @NotNull XDebuggerTree tree, @NotNull XWatchesView watchesView) { List watchNodes = getSelectedNodes(tree, WatchNode.class); if (watchNodes.size() != 1) return; diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XNewWatchAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XNewWatchAction.java index 273ff6a1d5b3..e984343be8d5 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XNewWatchAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XNewWatchAction.java @@ -16,16 +16,18 @@ package com.intellij.xdebugger.impl.frame.actions; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.xdebugger.impl.frame.XWatchesView; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import com.intellij.xdebugger.impl.ui.tree.nodes.WatchesRootNode; import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode; +import org.jetbrains.annotations.NotNull; /** * @author nik */ public class XNewWatchAction extends XWatchesTreeActionBase { @Override - protected void perform(AnActionEvent e, XDebuggerTree tree) { + protected void perform(@NotNull AnActionEvent e, @NotNull XDebuggerTree tree, @NotNull XWatchesView watchesView) { XDebuggerTreeNode root = tree.getRoot(); if (root instanceof WatchesRootNode) { final WatchesRootNode watchesRoot = (WatchesRootNode)root; diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XRemoveAllWatchesAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XRemoveAllWatchesAction.java index 7dba10e36d99..678654f5d737 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XRemoveAllWatchesAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XRemoveAllWatchesAction.java @@ -16,8 +16,7 @@ package com.intellij.xdebugger.impl.frame.actions; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.xdebugger.impl.XDebugSessionImpl; -import com.intellij.xdebugger.impl.ui.XDebugSessionTab; +import com.intellij.xdebugger.impl.frame.XWatchesView; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import org.jetbrains.annotations.NotNull; @@ -26,15 +25,12 @@ import org.jetbrains.annotations.NotNull; */ public class XRemoveAllWatchesAction extends XWatchesTreeActionBase { @Override - protected boolean isEnabled(AnActionEvent e, @NotNull XDebuggerTree tree) { - return tree.getRoot().getChildCount() > 0 && (tree.getSession() instanceof XDebugSessionImpl); + protected boolean isEnabled(@NotNull AnActionEvent e, @NotNull XDebuggerTree tree) { + return tree.getRoot().getChildCount() > 0; } @Override - protected void perform(AnActionEvent e, XDebuggerTree tree) { - if (tree.getSession() instanceof XDebugSessionImpl) { - XDebugSessionTab tab = ((XDebugSessionImpl)tree.getSession()).getSessionTab(); - tab.getWatchesView().removeAllWatches(); - } + protected void perform(@NotNull AnActionEvent e, @NotNull XDebuggerTree tree, @NotNull XWatchesView watchesView) { + watchesView.removeAllWatches(); } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XRemoveWatchAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XRemoveWatchAction.java index 0b301ad2fccb..4ed9b476e174 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XRemoveWatchAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XRemoveWatchAction.java @@ -16,8 +16,7 @@ package com.intellij.xdebugger.impl.frame.actions; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.xdebugger.impl.XDebugSessionImpl; -import com.intellij.xdebugger.impl.ui.XDebugSessionTab; +import com.intellij.xdebugger.impl.frame.XWatchesView; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode; import org.jetbrains.annotations.NotNull; @@ -28,16 +27,13 @@ import java.util.List; * @author nik */ public class XRemoveWatchAction extends XWatchesTreeActionBase { - protected boolean isEnabled(final AnActionEvent e, @NotNull XDebuggerTree tree) { - return !getSelectedNodes(tree, XDebuggerTreeNode.class).isEmpty() && (tree.getSession() instanceof XDebugSessionImpl); + protected boolean isEnabled(@NotNull final AnActionEvent e, @NotNull XDebuggerTree tree) { + return !getSelectedNodes(tree, XDebuggerTreeNode.class).isEmpty(); } @Override - protected void perform(AnActionEvent e, XDebuggerTree tree) { + protected void perform(@NotNull AnActionEvent e, @NotNull XDebuggerTree tree, @NotNull XWatchesView watchesView) { List nodes = getSelectedNodes(tree, XDebuggerTreeNode.class); - if (tree.getSession() instanceof XDebugSessionImpl) { - XDebugSessionTab tab = ((XDebugSessionImpl)tree.getSession()).getSessionTab(); - tab.getWatchesView().removeWatches(nodes); - } + watchesView.removeWatches(nodes); } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XWatchesTreeActionBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XWatchesTreeActionBase.java index cfe9e5231c63..e35ab54f1fe5 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XWatchesTreeActionBase.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XWatchesTreeActionBase.java @@ -17,6 +17,7 @@ package com.intellij.xdebugger.impl.frame.actions; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.xdebugger.impl.frame.XWatchesView; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import org.jetbrains.annotations.NotNull; @@ -45,21 +46,23 @@ public abstract class XWatchesTreeActionBase extends AnAction { public void update(final AnActionEvent e) { final XDebuggerTree tree = XDebuggerTree.getTree(e); - boolean enabled = tree != null && isEnabled(e, tree); + XWatchesView watchesView = e.getData(XWatchesView.DATA_KEY); + boolean enabled = tree != null && watchesView != null && isEnabled(e, tree); e.getPresentation().setEnabled(enabled); } @Override public void actionPerformed(AnActionEvent e) { final XDebuggerTree tree = XDebuggerTree.getTree(e); - if (tree != null) { - perform(e, tree); + XWatchesView watchesView = e.getData(XWatchesView.DATA_KEY); + if (tree != null && watchesView != null) { + perform(e, tree, watchesView); } } - protected abstract void perform(AnActionEvent e, XDebuggerTree tree); + protected abstract void perform(@NotNull AnActionEvent e, @NotNull XDebuggerTree tree, @NotNull XWatchesView watchesView); - protected boolean isEnabled(AnActionEvent e, @NotNull XDebuggerTree tree) { + protected boolean isEnabled(@NotNull AnActionEvent e, @NotNull XDebuggerTree tree) { return true; } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java index befd7b7058bd..8779d02295b0 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java @@ -41,12 +41,10 @@ import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XDebuggerBundle; import com.intellij.xdebugger.impl.XDebugSessionImpl; import com.intellij.xdebugger.impl.actions.XDebuggerActions; -import com.intellij.xdebugger.impl.frame.XDebugViewBase; -import com.intellij.xdebugger.impl.frame.XFramesView; -import com.intellij.xdebugger.impl.frame.XVariablesView; -import com.intellij.xdebugger.impl.frame.XWatchesView; +import com.intellij.xdebugger.impl.frame.*; import com.intellij.xdebugger.impl.ui.tree.actions.SortValuesToggleAction; import com.intellij.xdebugger.ui.XDebugTabLayouter; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -58,7 +56,7 @@ import java.util.List; * @author spleaner */ public class XDebugSessionTab extends DebuggerSessionTabBase { - private XWatchesView myWatchesView; + private XWatchesViewImpl myWatchesView; private final List myViews = new ArrayList(); public XDebugSessionTab(@NotNull final Project project, @NotNull final XDebugSessionImpl session, final @Nullable Icon icon, @@ -88,7 +86,7 @@ public class XDebugSessionTab extends DebuggerSessionTabBase { } private Content createWatchesContent(final XDebugSession session, final XDebugSessionData sessionData) { - myWatchesView = new XWatchesView(session, this, sessionData); + myWatchesView = new XWatchesViewImpl(session, this, sessionData); myViews.add(myWatchesView); Content watchesContent = myUi.createContent(DebuggerContentInfo.WATCHES_CONTENT, myWatchesView.getMainPanel(), XDebuggerBundle.message("debugger.session.tab.watches.title"), AllIcons.Debugger.Watches, null); @@ -127,6 +125,16 @@ public class XDebugSessionTab extends DebuggerSessionTabBase { myUi.addContent(createFramesContent(session), 0, PlaceInGrid.left, false); myUi.addContent(createVariablesContent(session), 0, PlaceInGrid.center, false); myUi.addContent(createWatchesContent(session, sessionData), 0, PlaceInGrid.right, false); + myUi.getContentManager().addDataProvider(new DataProvider() { + @Nullable + @Override + public Object getData(@NonNls String dataId) { + if (XWatchesView.DATA_KEY.is(dataId)) { + return myWatchesView; + } + return null; + } + }); XDebugTabLayouter layouter = debugProcess.createTabLayouter(); Content consoleContent = layouter.registerConsoleContent(myUi, myConsole); attachNotificationTo(consoleContent); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java index d2ba91f8ee8d..da91db3cf72b 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java @@ -28,10 +28,10 @@ import com.intellij.ui.TreeSpeedSearch; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Convertor; import com.intellij.xdebugger.XSourcePosition; -import com.intellij.xdebugger.XStackFrameAwareSession; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink; import com.intellij.xdebugger.impl.actions.XDebuggerActions; +import com.intellij.xdebugger.impl.frame.XValueMarkers; import com.intellij.xdebugger.impl.ui.tree.nodes.*; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -73,14 +73,14 @@ public class XDebuggerTree extends DnDAwareTree implements DataProvider, Disposa private final XDebuggerEditorsProvider myEditorsProvider; private XSourcePosition mySourcePosition; private final List myListeners = ContainerUtil.createLockFreeCopyOnWriteList(); - private final XStackFrameAwareSession mySession; + private final XValueMarkers myValueMarkers; - public XDebuggerTree(final @NotNull XStackFrameAwareSession session, + public XDebuggerTree(final @NotNull Project project, final @NotNull XDebuggerEditorsProvider editorsProvider, final @Nullable XSourcePosition sourcePosition, - final @NotNull String popupActionGroupId) { - mySession = session; - myProject = session.getProject(); + final @NotNull String popupActionGroupId, @Nullable XValueMarkers valueMarkers) { + myValueMarkers = valueMarkers; + myProject = project; myEditorsProvider = editorsProvider; mySourcePosition = sourcePosition; myTreeModel = new DefaultTreeModel(null); @@ -176,9 +176,9 @@ public class XDebuggerTree extends DnDAwareTree implements DataProvider, Disposa return myProject; } - @NotNull - public XStackFrameAwareSession getSession() { - return mySession; + @Nullable + public XValueMarkers getValueMarkers() { + return myValueMarkers; } public DefaultTreeModel getTreeModel() { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTreePanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTreePanel.java index c376e3896d14..1a4c5604ed18 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTreePanel.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTreePanel.java @@ -20,14 +20,15 @@ import com.intellij.ide.dnd.DnDDragStartBean; import com.intellij.ide.dnd.DnDSource; import com.intellij.ide.dnd.aware.DnDAwareTree; import com.intellij.openapi.Disposable; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Pair; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.treeStructure.Tree; import com.intellij.xdebugger.XDebuggerBundle; import com.intellij.xdebugger.XSourcePosition; -import com.intellij.xdebugger.XStackFrameAwareSession; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; +import com.intellij.xdebugger.impl.frame.XValueMarkers; import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -43,10 +44,10 @@ public class XDebuggerTreePanel implements DnDSource { private final XDebuggerTree myTree; private final JPanel myMainPanel; - public XDebuggerTreePanel(final @NotNull XStackFrameAwareSession session, final @NotNull XDebuggerEditorsProvider editorsProvider, + public XDebuggerTreePanel(final @NotNull Project project, final @NotNull XDebuggerEditorsProvider editorsProvider, @NotNull Disposable parentDisposable, final @Nullable XSourcePosition sourcePosition, - @NotNull @NonNls final String popupActionGroupId) { - myTree = new XDebuggerTree(session, editorsProvider, sourcePosition, popupActionGroupId); + @NotNull @NonNls final String popupActionGroupId, @Nullable XValueMarkers markers) { + myTree = new XDebuggerTree(project, editorsProvider, sourcePosition, popupActionGroupId, markers); myMainPanel = new JPanel(new BorderLayout()); myMainPanel.add(ScrollPaneFactory.createScrollPane(myTree), BorderLayout.CENTER); Disposer.register(parentDisposable, myTree); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XInspectDialog.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XInspectDialog.java index 8f2ee124a4f4..c9e22b38f05e 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XInspectDialog.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XInspectDialog.java @@ -15,15 +15,16 @@ */ package com.intellij.xdebugger.impl.ui.tree; +import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.Pair; -import com.intellij.xdebugger.XStackFrameAwareSession; import com.intellij.xdebugger.XDebuggerBundle; import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; import com.intellij.xdebugger.frame.XValue; import com.intellij.xdebugger.impl.actions.XDebuggerActions; import com.intellij.xdebugger.impl.evaluate.quick.XValueHintTreeComponent; +import com.intellij.xdebugger.impl.frame.XValueMarkers; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -36,13 +37,18 @@ import javax.swing.*; public class XInspectDialog extends DialogWrapper { private final XValueHintTreeComponent myTreePanel; - public XInspectDialog(XStackFrameAwareSession session, XDebuggerEditorsProvider editorsProvider, XSourcePosition sourcePosition, @NotNull String name, @NotNull XValue value) { - super(session.getProject(), false); + public XInspectDialog(@NotNull Project project, + XDebuggerEditorsProvider editorsProvider, + XSourcePosition sourcePosition, + @NotNull String name, + @NotNull XValue value, + XValueMarkers markers) { + super(project, false); setTitle(XDebuggerBundle.message("inspect.value.dialog.title", name)); setModal(false); - XDebuggerTree tree = new XDebuggerTree(session, editorsProvider, sourcePosition, XDebuggerActions.INSPECT_TREE_POPUP_GROUP); + XDebuggerTree tree = new XDebuggerTree(project, editorsProvider, sourcePosition, XDebuggerActions.INSPECT_TREE_POPUP_GROUP, markers); myTreePanel = new XValueHintTreeComponent(null, tree, Pair.create(value, name)); init(); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XAddToWatchesAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XAddToWatchesAction.java index 805056f0498a..a3621cb1a621 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XAddToWatchesAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XAddToWatchesAction.java @@ -16,9 +16,7 @@ package com.intellij.xdebugger.impl.ui.tree.actions; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.xdebugger.XStackFrameAwareSession; -import com.intellij.xdebugger.impl.XDebugSessionImpl; -import com.intellij.xdebugger.impl.ui.XDebugSessionTab; +import com.intellij.xdebugger.impl.frame.XWatchesView; import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; import org.jetbrains.annotations.NotNull; @@ -27,19 +25,16 @@ import org.jetbrains.annotations.NotNull; */ public class XAddToWatchesAction extends XDebuggerTreeActionBase { @Override - protected boolean isEnabled(final XValueNodeImpl node) { - return super.isEnabled(node) && node.getValueContainer().getEvaluationExpression() != null && (node.getTree().getSession() instanceof XDebugSessionImpl); + protected boolean isEnabled(@NotNull final XValueNodeImpl node, @NotNull AnActionEvent e) { + return super.isEnabled(node, e) && node.getValueContainer().getEvaluationExpression() != null && e.getData(XWatchesView.DATA_KEY) != null; } @Override protected void perform(final XValueNodeImpl node, @NotNull final String nodeName, final AnActionEvent e) { - XStackFrameAwareSession session = node.getTree().getSession(); - if (session instanceof XDebugSessionImpl) { - XDebugSessionTab sessionTab = ((XDebugSessionImpl)session).getSessionTab(); - String expression = node.getValueContainer().getEvaluationExpression(); - if (expression != null) { - sessionTab.getWatchesView().addWatchExpression(expression, -1, true); - } + XWatchesView watchesView = e.getData(XWatchesView.DATA_KEY); + String expression = node.getValueContainer().getEvaluationExpression(); + if (watchesView != null && expression != null) { + watchesView.addWatchExpression(expression, -1, true); } } } \ No newline at end of file diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XDebuggerTreeActionBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XDebuggerTreeActionBase.java index c4ccbbd20128..4ac67113af92 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XDebuggerTreeActionBase.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XDebuggerTreeActionBase.java @@ -46,10 +46,10 @@ public abstract class XDebuggerTreeActionBase extends AnAction { @Override public void update(final AnActionEvent e) { XValueNodeImpl node = getSelectedNode(e.getDataContext()); - e.getPresentation().setEnabled(node != null && isEnabled(node)); + e.getPresentation().setEnabled(node != null && isEnabled(node, e)); } - protected boolean isEnabled(final XValueNodeImpl node) { + protected boolean isEnabled(final @NotNull XValueNodeImpl node, @NotNull AnActionEvent e) { return node.getName() != null; } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XFetchValueActionBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XFetchValueActionBase.java index dd3397d944e2..239509e71475 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XFetchValueActionBase.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XFetchValueActionBase.java @@ -15,6 +15,7 @@ */ package com.intellij.xdebugger.impl.ui.tree.actions; +import com.intellij.notification.NotificationType; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DataContext; @@ -26,8 +27,8 @@ import com.intellij.util.Alarm; import com.intellij.util.SmartList; import com.intellij.util.concurrency.Semaphore; import com.intellij.xdebugger.XDebuggerBundle; -import com.intellij.xdebugger.XStackFrameAwareSession; import com.intellij.xdebugger.frame.XFullValueEvaluator; +import com.intellij.xdebugger.impl.XDebugSessionImpl; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import com.intellij.xdebugger.impl.ui.tree.nodes.WatchMessageNode; import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; @@ -83,7 +84,7 @@ public abstract class XFetchValueActionBase extends AnAction { valueCollector.add(StringUtil.notNullize(valueNode.getRawValue())); } else { - startFetchingValue(fullValueEvaluator, new CopyValueEvaluationCallback(valueNode.getTree().getSession(), valueCollector)); + startFetchingValue(fullValueEvaluator, new CopyValueEvaluationCallback(valueNode, valueCollector)); } } else if (node instanceof WatchMessageNode) { @@ -133,21 +134,21 @@ public abstract class XFetchValueActionBase extends AnAction { } private static final class CopyValueEvaluationCallback implements XFullValueEvaluator.XFullValueEvaluationCallback { - private final XStackFrameAwareSession session; + private final XValueNodeImpl myNode; - private final int valueIndex; - private final ValueCollector valueCollector; + private final int myValueIndex; + private final ValueCollector myValueCollector; - private volatile boolean evaluated; - private volatile boolean canceled; - private final Semaphore semaphore; + private volatile boolean myEvaluated; + private volatile boolean myCanceled; + private final Semaphore mySemaphore; - public CopyValueEvaluationCallback(XStackFrameAwareSession session, ValueCollector valueCollector) { - this.session = session; - this.valueCollector = valueCollector; - valueIndex = valueCollector.acquire(); - semaphore = new Semaphore(); - semaphore.down(); + public CopyValueEvaluationCallback(@NotNull XValueNodeImpl node, ValueCollector valueCollector) { + myNode = node; + myValueCollector = valueCollector; + myValueIndex = valueCollector.acquire(); + mySemaphore = new Semaphore(); + mySemaphore.down(); } @Override @@ -163,7 +164,8 @@ public abstract class XFetchValueActionBase extends AnAction { @Override public void errorOccurred(@NotNull String errorMessage) { try { - session.reportError(XDebuggerBundle.message("load.value.task.error", errorMessage)); + String message = XDebuggerBundle.message("load.value.task.error", errorMessage); + XDebugSessionImpl.NOTIFICATION_GROUP.createNotification(message, NotificationType.ERROR).notify(myNode.getTree().getProject()); } finally { evaluationComplete(errorMessage); @@ -172,31 +174,31 @@ public abstract class XFetchValueActionBase extends AnAction { private void evaluationComplete(String value) { try { - evaluated = true; - semaphore.up(); + myEvaluated = true; + mySemaphore.up(); } finally { - valueCollector.evaluationComplete(valueIndex, value, session.getProject()); + myValueCollector.evaluationComplete(myValueIndex, value, myNode.getTree().getProject()); } } @Override public boolean isObsolete() { - return canceled; + return myCanceled; } public void showProgress() { - if (evaluated || session.isStopped()) return; + if (myEvaluated || myNode.isObsolete()) return; - new Task.Backgroundable(session.getProject(), XDebuggerBundle.message("load.value.task.text")) { + new Task.Backgroundable(myNode.getTree().getProject(), XDebuggerBundle.message("load.value.task.text")) { @Override public void run(@NotNull ProgressIndicator indicator) { indicator.setIndeterminate(true); int i = 0; - while (!canceled && !evaluated) { + while (!myCanceled && !myEvaluated) { indicator.checkCanceled(); indicator.setFraction(((i++) % 100) * 0.01); - semaphore.waitFor(300); + mySemaphore.waitFor(300); } } @@ -207,7 +209,7 @@ public abstract class XFetchValueActionBase extends AnAction { @Override public void onCancel() { - canceled = true; + myCanceled = true; } }.queue(); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XInspectAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XInspectAction.java index fc6062e5dbc5..66751e03eef2 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XInspectAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XInspectAction.java @@ -30,7 +30,8 @@ public class XInspectAction extends XDebuggerTreeActionBase { protected void perform(XValueNodeImpl node, @NotNull final String nodeName, AnActionEvent e) { XDebuggerTree tree = node.getTree(); XValue value = node.getValueContainer(); - XInspectDialog dialog = new XInspectDialog(tree.getSession(), tree.getEditorsProvider(), tree.getSourcePosition(), nodeName, value); + XInspectDialog dialog = new XInspectDialog(tree.getProject(), tree.getEditorsProvider(), tree.getSourcePosition(), nodeName, value, + tree.getValueMarkers()); dialog.show(); } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XJumpToSourceAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XJumpToSourceAction.java index f502354e763c..37248b3b72cb 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XJumpToSourceAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XJumpToSourceAction.java @@ -15,9 +15,11 @@ */ package com.intellij.xdebugger.impl.ui.tree.actions; +import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.xdebugger.frame.XNavigatable; import com.intellij.xdebugger.frame.XValue; import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; +import org.jetbrains.annotations.NotNull; /** * @author nik @@ -29,7 +31,7 @@ public class XJumpToSourceAction extends XJumpToSourceActionBase { } @Override - protected boolean isEnabled(XValueNodeImpl node) { - return super.isEnabled(node) && node.getValueContainer().canNavigateToSource(); + protected boolean isEnabled(@NotNull XValueNodeImpl node, @NotNull AnActionEvent e) { + return super.isEnabled(node, e) && node.getValueContainer().canNavigateToSource(); } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XJumpToTypeSourceAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XJumpToTypeSourceAction.java index b5cb75e9b0b0..7b4483fca602 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XJumpToTypeSourceAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XJumpToTypeSourceAction.java @@ -15,9 +15,11 @@ */ package com.intellij.xdebugger.impl.ui.tree.actions; +import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.xdebugger.frame.XNavigatable; import com.intellij.xdebugger.frame.XValue; import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; +import org.jetbrains.annotations.NotNull; /** * @author nik @@ -29,7 +31,7 @@ public class XJumpToTypeSourceAction extends XJumpToSourceActionBase { } @Override - protected boolean isEnabled(XValueNodeImpl node) { - return super.isEnabled(node) && node.getValueContainer().canNavigateToTypeSource(); + protected boolean isEnabled(@NotNull XValueNodeImpl node, @NotNull AnActionEvent e) { + return super.isEnabled(node, e) && node.getValueContainer().canNavigateToTypeSource(); } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XSetValueAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XSetValueAction.java index 886789ab2c8c..8ca795e925d7 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XSetValueAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XSetValueAction.java @@ -42,8 +42,8 @@ public class XSetValueAction extends XDebuggerTreeActionBase { } @Override - protected boolean isEnabled(XValueNodeImpl node) { - return super.isEnabled(node) && node.getValueContainer().getModifier() != null; + protected boolean isEnabled(@NotNull XValueNodeImpl node, @NotNull AnActionEvent e) { + return super.isEnabled(node, e) && node.getValueContainer().getModifier() != null; } protected void perform(final XValueNodeImpl node, @NotNull final String nodeName, final AnActionEvent e) { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchesRootNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchesRootNode.java index 0f62830c63e8..a7e83931ac2a 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchesRootNode.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchesRootNode.java @@ -15,9 +15,11 @@ */ package com.intellij.xdebugger.impl.ui.tree.nodes; +import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.evaluation.XDebuggerEvaluator; import com.intellij.xdebugger.frame.XValue; import com.intellij.xdebugger.impl.frame.WatchInplaceEditor; +import com.intellij.xdebugger.impl.frame.XWatchesView; import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import org.jetbrains.annotations.NotNull; @@ -33,12 +35,19 @@ import java.util.List; * @author nik */ public class WatchesRootNode extends XDebuggerTreeNode { + private final XDebugSession mySession; + private final XWatchesView myWatchesView; private List myChildren; private List myLoadedChildren; private XDebuggerEvaluator myCurrentEvaluator; - public WatchesRootNode(final XDebuggerTree tree, String[] watchExpressions) { + public WatchesRootNode(final @NotNull XDebuggerTree tree, + @NotNull XDebugSession session, + @NotNull XWatchesView watchesView, + @NotNull String[] watchExpressions) { super(tree, null, false); + mySession = session; + myWatchesView = watchesView; myChildren = new ArrayList(); for (String watchExpression : watchExpressions) { myChildren.add(WatchMessageNode.createMessageNode(tree, this, watchExpression)); @@ -177,7 +186,7 @@ public class WatchesRootNode extends XDebuggerTreeNode { myChildren.set(index, messageNode); fireNodeStructureChanged(messageNode); } - WatchInplaceEditor editor = new WatchInplaceEditor(this, messageNode, "watch", node); + WatchInplaceEditor editor = new WatchInplaceEditor(this, mySession, myWatchesView, messageNode, "watch", node); editor.show(); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java index cfc3782be63e..5ba65e57335f 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java @@ -23,7 +23,6 @@ import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.NotNullFunction; import com.intellij.xdebugger.frame.*; import com.intellij.xdebugger.frame.presentation.XValuePresentation; -import com.intellij.xdebugger.impl.XDebugSessionImpl; import com.intellij.xdebugger.impl.frame.XValueMarkers; import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants; @@ -133,15 +132,13 @@ public class XValueNodeImpl extends XValueContainerNode implements XValu private void updateText() { myText.clear(); - if (myTree.getSession() instanceof XDebugSessionImpl) { - XValueMarkers markers = ((XDebugSessionImpl)myTree.getSession()).getValueMarkers(); + XValueMarkers markers = myTree.getValueMarkers(); if (markers != null) { ValueMarkup markup = markers.getMarkup(myValueContainer); if (markup != null) { myText.append("[" + markup.getText() + "] ", new SimpleTextAttributes(SimpleTextAttributes.STYLE_BOLD, markup.getColor())); } } - } appendName(); buildText(myValuePresentation, myText); }