From 55029007ad9364dfced92e67b3e8873f0cbb5fdd Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Thu, 10 Mar 2016 14:30:13 +0300 Subject: [PATCH] XDebugger: Merge 'Watches' and 'Variables' views --- .../xdebugger/impl/XDebugSessionImpl.java | 4 - .../impl/frame/WatchInplaceEditor.java | 6 +- .../xdebugger/impl/frame/XVariablesView.java | 30 +-- .../impl/frame/XVariablesViewBase.java | 32 ++- .../impl/frame/XWatchesViewImpl.java | 180 +++++++-------- .../impl/frame/actions/XCopyWatchAction.java | 22 +- .../impl/frame/actions/XEditWatchAction.java | 8 +- .../frame/actions/XRemoveWatchAction.java | 9 +- .../xdebugger/impl/ui/XDebugSessionTab.java | 18 +- .../impl/ui/tree/TreeInplaceEditor.java | 5 +- .../tree/actions/XFetchValueActionBase.java | 11 +- .../impl/ui/tree/nodes/WatchMessageNode.java | 79 ------- .../impl/ui/tree/nodes/WatchNode.java | 2 + .../impl/ui/tree/nodes/WatchNodeImpl.java | 17 +- .../impl/ui/tree/nodes/WatchesRootNode.java | 211 +++++++++++------- .../impl/ui/tree/nodes/XStackFrameNode.java | 35 +-- .../ui/tree/nodes/XValueContainerNode.java | 2 +- 17 files changed, 323 insertions(+), 348 deletions(-) delete mode 100644 platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchMessageNode.java diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java index 33fd6d1ddb37..585f9960e5b3 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java @@ -43,7 +43,6 @@ import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.ToolWindowId; import com.intellij.ui.AppUIUtil; @@ -968,9 +967,6 @@ public class XDebugSessionImpl implements XDebugSession { public void setWatchExpressions(@NotNull XExpression[] watchExpressions) { mySessionData.setWatchExpressions(watchExpressions); myDebuggerManager.getWatchesManager().setWatches(getConfigurationName(), watchExpressions); - if (Registry.is("debugger.watches.in.variables")) { - rebuildViews(); - } } XExpression[] getWatchExpressions() { 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 3eaf44e8d9e1..62392df9eb30 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 @@ -62,9 +62,9 @@ public class WatchInplaceEditor extends XDebuggerTreeInplaceEditor { public void cancelEditing() { if (!isShown()) return; super.cancelEditing(); - int index = myRootNode.removeChildNode(getNode()); - if (myOldNode != null && index != -1) { - myWatchesView.addWatchExpression(myOldNode.getExpression(), index, false); + int index = myRootNode.getIndex(getNode()); + if (myOldNode == null && index != -1) { + myRootNode.removeChildNode(getNode()); } getTree().setSelectionRow(index); } 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 77b95edada70..857bd9fc3f06 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 @@ -15,6 +15,7 @@ */ package com.intellij.xdebugger.impl.frame; +import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataProvider; import com.intellij.openapi.util.Comparing; @@ -49,19 +50,20 @@ import static com.intellij.xdebugger.impl.ui.tree.nodes.MessageTreeNode.createIn /** * @author nik */ -public class XVariablesView extends XVariablesViewBase { +public class XVariablesView extends XVariablesViewBase implements DataProvider { public static final Key DEBUG_VARIABLES = Key.create("debug.variables"); public static final Key> DEBUG_VARIABLES_TIMESTAMPS = Key.create("debug.variables.timestamps"); - private final JComponent myComponent; + private final JPanel myComponent; public XVariablesView(@NotNull XDebugSessionImpl session) { super(session.getProject(), session.getDebugProcess().getEditorsProvider(), session.getValueMarkers()); - myComponent = new MyPanel(); + myComponent = new BorderLayoutPanel(); myComponent.add(super.getPanel()); + DataManager.registerDataProvider(myComponent, this); } @Override - public JComponent getPanel() { + public JPanel getPanel() { return myComponent; } @@ -119,6 +121,15 @@ public class XVariablesView extends XVariablesViewBase { super.clear(); } + @Nullable + @Override + public Object getData(@NonNls String dataId) { + if (CommonDataKeys.VIRTUAL_FILE.is(dataId)) { + return getCurrentFile(getTree()); + } + return null; + } + public static class InlineVariablesInfo { private final Map, Set> myData = new THashMap, Set>(); @@ -186,15 +197,4 @@ public class XVariablesView extends XVariablesViewBase { } } } - - private class MyPanel extends BorderLayoutPanel implements DataProvider { - @Nullable - @Override - public Object getData(@NonNls String dataId) { - if (CommonDataKeys.VIRTUAL_FILE.is(dataId)) { - return getCurrentFile(getTree()); - } - return null; - } - } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesViewBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesViewBase.java index 767a5fb8a124..ef2390e44a16 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesViewBase.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesViewBase.java @@ -43,6 +43,7 @@ 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.XDebuggerTreeNode; import com.intellij.xdebugger.impl.ui.tree.nodes.XStackFrameNode; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -54,23 +55,25 @@ import java.awt.*; * @author nik */ public abstract class XVariablesViewBase extends XDebugView { - protected final XDebuggerTreePanel myDebuggerTreePanel; + private final XDebuggerTreePanel myTreePanel; private XDebuggerTreeState myTreeState; - private Object myFrameEqualityObject; private XDebuggerTreeRestorer myTreeRestorer; + + private Object myFrameEqualityObject; private MySelectionListener mySelectionListener; protected XVariablesViewBase(@NotNull Project project, @NotNull XDebuggerEditorsProvider editorsProvider, @Nullable XValueMarkers markers) { - myDebuggerTreePanel = new XDebuggerTreePanel(project, 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()); + myTreePanel = new XDebuggerTreePanel( + project, editorsProvider, this, null, this instanceof XWatchesView ? XDebuggerActions.WATCHES_TREE_POPUP_GROUP : XDebuggerActions.VARIABLES_TREE_POPUP_GROUP, markers); + myTreePanel.getTree().getEmptyText().setText(XDebuggerBundle.message("debugger.variables.not.available")); + DnDManager.getInstance().registerSource(myTreePanel, myTreePanel.getTree()); } protected void buildTreeAndRestoreState(@NotNull final XStackFrame stackFrame) { - XDebuggerTree tree = myDebuggerTreePanel.getTree(); - final XSourcePosition position = stackFrame.getSourcePosition(); + XSourcePosition position = stackFrame.getSourcePosition(); + XDebuggerTree tree = getTree(); tree.setSourcePosition(position); - tree.setRoot(new XStackFrameNode(tree, stackFrame), false); + tree.setRoot(buildRootNode(stackFrame), false); final Project project = tree.getProject(); project.putUserData(XVariablesView.DEBUG_VARIABLES, new XVariablesView.InlineVariablesInfo()); project.putUserData(XVariablesView.DEBUG_VARIABLES_TIMESTAMPS, new ObjectLongHashMap()); @@ -85,6 +88,11 @@ public abstract class XVariablesViewBase extends XDebugView { } } + @NotNull + protected XDebuggerTreeNode buildRootNode(@NotNull XStackFrame stackFrame) { + return new XStackFrameNode(getTree(), stackFrame); + } + private void registerInlineEvaluator(final XStackFrame stackFrame, final XSourcePosition position, final Project project) { @@ -102,7 +110,7 @@ public abstract class XVariablesViewBase extends XDebugView { disposeTreeRestorer(); removeSelectionListener(); myFrameEqualityObject = stackFrame != null ? stackFrame.getEqualityObject() : null; - myTreeState = XDebuggerTreeState.saveState(myDebuggerTreePanel.getTree()); + myTreeState = XDebuggerTreeState.saveState(myTreePanel.getTree()); } private void removeSelectionListener() { @@ -125,18 +133,18 @@ public abstract class XVariablesViewBase extends XDebugView { } public XDebuggerTree getTree() { - return myDebuggerTreePanel.getTree(); + return myTreePanel.getTree(); } public JComponent getPanel() { - return myDebuggerTreePanel.getMainPanel(); + return myTreePanel.getMainPanel(); } @Override public void dispose() { disposeTreeRestorer(); removeSelectionListener(); - DnDManager.getInstance().unregisterSource(myDebuggerTreePanel, myDebuggerTreePanel.getTree()); + DnDManager.getInstance().unregisterSource(myTreePanel, myTreePanel.getTree()); } private class MySelectionListener implements SelectionListener { 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 index 88a7d5bbe3ca..608c71d08e66 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java @@ -29,10 +29,12 @@ import com.intellij.openapi.ide.CopyPasteManager; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.EmptyRunnable; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.registry.Registry; import com.intellij.ui.*; import com.intellij.ui.border.CustomLineBorder; import com.intellij.util.Alarm; import com.intellij.util.Consumer; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.tree.TreeUtil; import com.intellij.xdebugger.XDebugSession; @@ -46,9 +48,6 @@ import com.intellij.xdebugger.impl.frame.actions.XWatchesTreeActionBase; import com.intellij.xdebugger.impl.ui.XDebugSessionData; import com.intellij.xdebugger.impl.ui.XDebugSessionTab; 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.actions.XWatchTransferable; import com.intellij.xdebugger.impl.ui.tree.nodes.WatchNode; import com.intellij.xdebugger.impl.ui.tree.nodes.WatchesRootNode; @@ -65,40 +64,40 @@ import java.awt.*; import java.awt.datatransfer.DataFlavor; import java.awt.event.*; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** * @author nik */ -public class XWatchesViewImpl extends XDebugView implements DnDNativeTarget, XWatchesView { - private final XDebuggerTreePanel myTreePanel; - private XDebuggerTreeState myTreeState; - private XDebuggerTreeRestorer myTreeRestorer; - private final WatchesRootNode myRootNode; - private final JPanel myDecoratedPanel; +public class XWatchesViewImpl extends XVariablesView implements DnDNativeTarget, XWatchesView { + private WatchesRootNode myRootNode; + private final CompositeDisposable myDisposables = new CompositeDisposable(); private boolean myRebuildNeeded; public XWatchesViewImpl(@NotNull XDebugSessionImpl session) { - myTreePanel = new XDebuggerTreePanel(session.getProject(), session.getDebugProcess().getEditorsProvider(), this, null, - XDebuggerActions.WATCHES_TREE_POPUP_GROUP, session.getValueMarkers()); + super(session); ActionManager actionManager = ActionManager.getInstance(); - XDebuggerTree tree = myTreePanel.getTree(); - actionManager.getAction(XDebuggerActions.XNEW_WATCH).registerCustomShortcutSet(CommonShortcuts.INSERT, tree, myDisposables); - actionManager.getAction(XDebuggerActions.XREMOVE_WATCH).registerCustomShortcutSet(CommonShortcuts.getDelete(), tree, myDisposables); + XDebuggerTree tree = getTree(); + tree.setRoot(buildRootNode(null), false); + AnAction newWatchAction = actionManager.getAction(XDebuggerActions.XNEW_WATCH); + AnAction removeWatchAction = actionManager.getAction(XDebuggerActions.XREMOVE_WATCH); + AnAction copyAction = actionManager.getAction(XDebuggerActions.XCOPY_WATCH); + AnAction editWatchAction = actionManager.getAction(XDebuggerActions.XEDIT_WATCH); + + newWatchAction.registerCustomShortcutSet(CommonShortcuts.INSERT, tree, myDisposables); + removeWatchAction.registerCustomShortcutSet(CommonShortcuts.getDelete(), tree, myDisposables); CustomShortcutSet f2Shortcut = new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0)); - actionManager.getAction(XDebuggerActions.XEDIT_WATCH).registerCustomShortcutSet(f2Shortcut, tree, myDisposables); + editWatchAction.registerCustomShortcutSet(f2Shortcut, tree, myDisposables); - AnAction copyAction = actionManager.getAction(XDebuggerActions.XCOPY_WATCH); copyAction.registerCustomShortcutSet( ActionManager.getInstance().getAction(IdeActions.ACTION_EDITOR_DUPLICATE).getShortcutSet(), tree, myDisposables); DnDManager.getInstance().registerTarget(this, tree); - myRootNode = new WatchesRootNode(tree, this, session.getSessionData().getWatchExpressions()); - tree.setRoot(myRootNode, false); new AnAction() { @Override @@ -114,7 +113,7 @@ public class XWatchesViewImpl extends XDebugView implements DnDNativeTarget, XWa } }.registerCustomShortcutSet(CommonShortcuts.getPaste(), tree, myDisposables); - final ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myTreePanel.getTree()).disableUpDownActions(); + final ToolbarDecorator decorator = ToolbarDecorator.createDecorator(getTree()).disableUpDownActions(); decorator.setAddAction(new AnActionButtonRunnable() { @Override public void run(AnActionButton button) { @@ -127,6 +126,13 @@ public class XWatchesViewImpl extends XDebugView implements DnDNativeTarget, XWa executeAction(XDebuggerActions.XREMOVE_WATCH); } }); + decorator.setRemoveActionUpdater(new AnActionButtonUpdater() { + @Override + public boolean isEnabled(AnActionEvent e) { + removeWatchAction.update(e); + return e.getPresentation().isEnabled(); + } + }); decorator.addExtraAction(AnActionButton.fromAction(copyAction)); decorator.setMoveUpAction(new AnActionButtonRunnable() { @Override @@ -159,23 +165,28 @@ public class XWatchesViewImpl extends XDebugView implements DnDNativeTarget, XWa public boolean isEnabled(AnActionEvent e) { List nodes = XWatchesTreeActionBase.getSelectedNodes(getTree(), WatchNode.class); if (nodes.size() != 1) return false; - return myRootNode.getIndex(nodes.get(0)) < myRootNode.getChildCount() - 1; + return myRootNode.getIndex(nodes.get(0)) < myRootNode.getWatchChildren().size() - 1; } }); CustomLineBorder border = new CustomLineBorder(CaptionPanel.CNT_ACTIVE_BORDER_COLOR, SystemInfo.isMac ? 1 : 0, 0, SystemInfo.isMac ? 0 : 1, 0); decorator.setToolbarBorder(border); - myDecoratedPanel = new MyPanel(decorator.createPanel()); - myDecoratedPanel.setBorder(null); - - myTreePanel.getTree().getEmptyText().setText(XDebuggerBundle.message("debugger.no.watches")); + decorator.setPanelBorder(BorderFactory.createEmptyBorder()); + getPanel().removeAll(); + getPanel().add(decorator.createPanel()); + if (Registry.is("debugger.watches.in.variables")) { + decorator.getActionsPanel().setVisible(false); + } + else { + getTree().getEmptyText().setText(XDebuggerBundle.message("debugger.no.watches")); + } installEditListeners(); } private void installEditListeners() { - final XDebuggerTree watchTree = myTreePanel.getTree(); + final XDebuggerTree watchTree = getTree(); final Alarm quitePeriod = new Alarm(); final Alarm editAlarm = new Alarm(); final ClickListener mouseListener = new ClickListener() { @@ -255,7 +266,18 @@ public class XWatchesViewImpl extends XDebugView implements DnDNativeTarget, XWa @Override public void dispose() { Disposer.dispose(myDisposables); - DnDManager.getInstance().unregisterTarget(this, myTreePanel.getTree()); + DnDManager.getInstance().unregisterTarget(this, getTree()); + } + + @Override + protected void clear() { + XDebuggerTree tree = getTree(); + XExpression[] expressions = getExpressions(); + super.clear(); + if (expressions.length > 0) { + myRootNode = new WatchesRootNode(tree, this, expressions, null); + tree.setRoot(myRootNode, false); + } } private static boolean isAboveSelectedItem(MouseEvent event, XDebuggerTree watchTree) { @@ -272,7 +294,7 @@ public class XWatchesViewImpl extends XDebugView implements DnDNativeTarget, XWa private void executeAction(@NotNull String watch) { AnAction action = ActionManager.getInstance().getAction(watch); Presentation presentation = action.getTemplatePresentation().clone(); - DataContext context = DataManager.getInstance().getDataContext(myTreePanel.getTree()); + DataContext context = DataManager.getInstance().getDataContext(getTree()); AnActionEvent actionEvent = new AnActionEvent(null, context, ActionPlaces.DEBUGGER_TOOLBAR, presentation, ActionManager.getInstance(), 0); @@ -310,58 +332,59 @@ public class XWatchesViewImpl extends XDebugView implements DnDNativeTarget, XWa @Override public void processSessionEvent(@NotNull final SessionEvent event) { - if (getMainPanel().isShowing() || ApplicationManager.getApplication().isUnitTestMode()) { + if (Registry.is("debugger.watches.in.variables") || + getPanel().isShowing() || + ApplicationManager.getApplication().isUnitTestMode()) { myRebuildNeeded = false; } else { myRebuildNeeded = true; return; } + super.processSessionEvent(event); + } - XDebuggerTree tree = myTreePanel.getTree(); + @NotNull + @Override + protected XDebuggerTreeNode buildRootNode(@Nullable XStackFrame stackFrame) { + WatchesRootNode node = new WatchesRootNode(getTree(), this, getExpressions(), stackFrame); + myRootNode = node; + return node; + } - if (event == SessionEvent.BEFORE_RESUME || event == SessionEvent.SETTINGS_CHANGED) { - if (myTreeRestorer != null) { - myTreeRestorer.dispose(); - } - myTreeState = XDebuggerTreeState.saveState(tree); - if (event == SessionEvent.BEFORE_RESUME) { - return; - } - } - - XDebugSession session = getSession(getMainPanel()); - XStackFrame stackFrame = session == null ? null : session.getCurrentStackFrame(); - if (stackFrame != null) { - cancelClear(); - tree.setSourcePosition(stackFrame.getSourcePosition()); - myRootNode.updateWatches(stackFrame.getEvaluator()); - if (myTreeState != null) { - myTreeRestorer = myTreeState.restoreState(tree); - } + @NotNull + private XExpression[] getExpressions() { + XDebuggerTree tree = getTree(); + XDebugSession session = getSession(tree); + XExpression[] expressions; + if (session != null) { + expressions = ((XDebugSessionImpl)session).getSessionData().getWatchExpressions(); } else { - requestClear(); + XDebuggerTreeNode root = tree.getRoot(); + List current = root instanceof WatchesRootNode + ? ((WatchesRootNode)tree.getRoot()).getWatchChildren() : Collections.emptyList(); + List list = ContainerUtil.newArrayList(); + for (WatchNode child : current) { + list.add(child.getExpression()); + } + expressions = list.toArray(new XExpression[list.size()]); } + return expressions; } + @Nullable @Override - protected void clear() { - getTree().setSourcePosition(null); - myRootNode.updateWatches(null); - } - - public XDebuggerTree getTree() { - return myTreePanel.getTree(); - } - - public JPanel getMainPanel() { - return myDecoratedPanel; + public Object getData(@NonNls String dataId) { + if (XWatchesView.DATA_KEY.is(dataId)) { + return this; + } + return super.getData(dataId); } @Override public void removeWatches(List nodes) { - List children = myRootNode.getAllChildren(); + List children = myRootNode.getWatchChildren(); int minIndex = Integer.MAX_VALUE; List toRemove = new ArrayList(); if (children != null) { @@ -376,10 +399,10 @@ public class XWatchesViewImpl extends XDebugView implements DnDNativeTarget, XWa } myRootNode.removeChildren(toRemove); - List newChildren = myRootNode.getAllChildren(); + List newChildren = myRootNode.getWatchChildren(); if (newChildren != null && !newChildren.isEmpty()) { WatchNode node = minIndex < newChildren.size() ? newChildren.get(minIndex) : newChildren.get(newChildren.size() - 1); - TreeUtil.selectNode(myTreePanel.getTree(), node); + TreeUtil.selectNode(getTree(), node); } updateSessionData(); } @@ -391,14 +414,11 @@ public class XWatchesViewImpl extends XDebugView implements DnDNativeTarget, XWa } public void updateSessionData() { - List watchExpressions = new ArrayList(); - final List children = myRootNode.getAllChildren(); - if (children != null) { - for (WatchNode child : children) { - watchExpressions.add(child.getExpression()); - } + List watchExpressions = ContainerUtil.newArrayList(); + List children = myRootNode.getWatchChildren(); + for (WatchNode child : children) { + watchExpressions.add(child.getExpression()); } - XDebugSession session = getSession(getTree()); XExpression[] expressions = watchExpressions.toArray(new XExpression[watchExpressions.size()]); if (session != null) { @@ -461,24 +481,4 @@ public class XWatchesViewImpl extends XDebugView implements DnDNativeTarget, XWa @Override public void updateDraggedImage(final Image image, final Point dropPoint, final Point imageOffset) { } - - private class MyPanel extends JPanel implements DataProvider { - public MyPanel(JPanel panel) { - setLayout(new BorderLayout()); - add(panel); - panel.setBorder(null); - } - - @Nullable - @Override - public Object getData(@NonNls String dataId) { - if (XWatchesView.DATA_KEY.is(dataId)) { - return XWatchesViewImpl.this; - } - else if (CommonDataKeys.VIRTUAL_FILE.is(dataId)) { - return getCurrentFile(getTree()); - } - return null; - } - } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XCopyWatchAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XCopyWatchAction.java index 3dc175b60b3e..8de9515e8ee0 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XCopyWatchAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/actions/XCopyWatchAction.java @@ -16,10 +16,15 @@ package com.intellij.xdebugger.impl.frame.actions; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.util.ObjectUtils; +import com.intellij.xdebugger.XExpression; +import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl; import com.intellij.xdebugger.impl.frame.XWatchesView; +import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; 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.XDebuggerTreeNode; +import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -29,17 +34,24 @@ import java.util.List; */ public class XCopyWatchAction extends XWatchesTreeActionBase { - protected boolean isEnabled(@NotNull final AnActionEvent e, @NotNull XDebuggerTree tree) { - return !getSelectedNodes(tree, WatchNode.class).isEmpty(); + protected boolean isEnabled(@NotNull AnActionEvent e, @NotNull XDebuggerTree tree) { + return !getSelectedNodes(tree, XValueNodeImpl.class).isEmpty(); } @Override protected void perform(@NotNull AnActionEvent e, @NotNull XDebuggerTree tree, @NotNull XWatchesView watchesView) { XDebuggerTreeNode root = tree.getRoot(); - List nodes = getSelectedNodes(tree, WatchNode.class); - for (WatchNode node : nodes) { + List nodes = getSelectedNodes(tree, XValueNodeImpl.class); + for (XValueNodeImpl node : nodes) { int index = root.getIndex(node); - watchesView.addWatchExpression(node.getExpression(), index + 1, true); + boolean isWatch = node instanceof WatchNode; + XExpression expression = isWatch ? ((WatchNode)node).getExpression() : + XExpressionImpl.fromText(node.getName()); + if (expression == null) continue; + node.getValueContainer().calculateEvaluationExpression().done( + expr -> DebuggerUIUtil.invokeLater( + () -> watchesView.addWatchExpression(ObjectUtils.notNull(expr, expression), isWatch ? index + 1 : -1, true))); + } } } 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 422c469cfd27..fad170270088 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 @@ -18,7 +18,7 @@ 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.WatchNodeImpl; import com.intellij.xdebugger.impl.ui.tree.nodes.WatchesRootNode; import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode; import org.jetbrains.annotations.NotNull; @@ -32,16 +32,16 @@ public class XEditWatchAction extends XWatchesTreeActionBase { @Override public void update(final AnActionEvent e) { XDebuggerTree tree = XDebuggerTree.getTree(e); - e.getPresentation().setVisible(tree != null && getSelectedNodes(tree, WatchNode.class).size() == 1); + e.getPresentation().setVisible(tree != null && getSelectedNodes(tree, WatchNodeImpl.class).size() == 1); super.update(e); } @Override protected void perform(@NotNull AnActionEvent e, @NotNull XDebuggerTree tree, @NotNull XWatchesView watchesView) { - List watchNodes = getSelectedNodes(tree, WatchNode.class); + List watchNodes = getSelectedNodes(tree, WatchNodeImpl.class); if (watchNodes.size() != 1) return; - WatchNode node = watchNodes.get(0); + WatchNodeImpl node = watchNodes.get(0); XDebuggerTreeNode root = tree.getRoot(); if (root instanceof WatchesRootNode) { ((WatchesRootNode)root).editWatch(node); 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 4ed9b476e174..5852f7f1dc72 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 @@ -18,7 +18,7 @@ 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.XDebuggerTreeNode; +import com.intellij.xdebugger.impl.ui.tree.nodes.WatchNodeImpl; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -27,13 +27,14 @@ import java.util.List; * @author nik */ public class XRemoveWatchAction extends XWatchesTreeActionBase { - protected boolean isEnabled(@NotNull final AnActionEvent e, @NotNull XDebuggerTree tree) { - return !getSelectedNodes(tree, XDebuggerTreeNode.class).isEmpty(); + + protected boolean isEnabled(@NotNull AnActionEvent e, @NotNull XDebuggerTree tree) { + return !getSelectedNodes(tree, WatchNodeImpl.class).isEmpty(); } @Override protected void perform(@NotNull AnActionEvent e, @NotNull XDebuggerTree tree, @NotNull XWatchesView watchesView) { - List nodes = getSelectedNodes(tree, XDebuggerTreeNode.class); + Listnodes = getSelectedNodes(tree, WatchNodeImpl.class); watchesView.removeWatches(nodes); } } 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 ce698b4d4511..7cd529a767b1 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 @@ -32,6 +32,7 @@ import com.intellij.idea.ActionsBundle; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.registry.Registry; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.ui.AppUIUtil; import com.intellij.ui.content.Content; @@ -52,14 +53,13 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.util.ArrayList; import java.util.List; public class XDebugSessionTab extends DebuggerSessionTabBase { public static final DataKey TAB_KEY = DataKey.create("XDebugSessionTab"); private XWatchesViewImpl myWatchesView; - private final List myViews = new ArrayList(); + private final List myViews = ContainerUtil.newArrayList(); @Nullable private XDebugSessionImpl mySession; @@ -107,7 +107,9 @@ public class XDebugSessionTab extends DebuggerSessionTabBase { myUi.addContent(createFramesContent(), 0, PlaceInGrid.left, false); myUi.addContent(createVariablesContent(session), 0, PlaceInGrid.center, false); - myUi.addContent(createWatchesContent(session), 0, PlaceInGrid.right, false); + if (!Registry.is("debugger.watches.in.variables")) { + myUi.addContent(createWatchesContent(session), 0, PlaceInGrid.right, false); + } for (XDebugView view : myViews) { Disposer.register(myRunContentDescriptor, view); @@ -180,7 +182,13 @@ public class XDebugSessionTab extends DebuggerSessionTabBase { } private Content createVariablesContent(@NotNull XDebugSessionImpl session) { - final XVariablesView variablesView = new XVariablesView(session); + XVariablesView variablesView; + if (Registry.is("debugger.watches.in.variables")) { + variablesView = myWatchesView = new XWatchesViewImpl(session); + } + else { + variablesView = new XVariablesView(session); + } myViews.add(variablesView); Content result = myUi.createContent(DebuggerContentInfo.VARIABLES_CONTENT, variablesView.getPanel(), XDebuggerBundle.message("debugger.session.tab.variables.title"), @@ -195,7 +203,7 @@ public class XDebugSessionTab extends DebuggerSessionTabBase { private Content createWatchesContent(@NotNull XDebugSessionImpl session) { myWatchesView = new XWatchesViewImpl(session); myViews.add(myWatchesView); - Content watchesContent = myUi.createContent(DebuggerContentInfo.WATCHES_CONTENT, myWatchesView.getMainPanel(), + Content watchesContent = myUi.createContent(DebuggerContentInfo.WATCHES_CONTENT, myWatchesView.getPanel(), XDebuggerBundle.message("debugger.session.tab.watches.title"), AllIcons.Debugger.Watches, null); watchesContent.setCloseable(false); return watchesContent; diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java index b95cf4c485db..dfc755541dea 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java @@ -94,7 +94,10 @@ public abstract class TreeInplaceEditor implements AWTEventListener { protected abstract Project getProject(); private static void setInplaceEditorBounds(JComponent component, int x, int y, int width, int height) { - component.setBounds(x, y, width, Math.max(height, component.getPreferredSize().height)); + int preferredHeight = component.getPreferredSize().height; + int h = Math.max(height, preferredHeight); + int delta = Math.max(0, h - height) / 2; + component.setBounds(x, y - delta, width, Math.max(height, preferredHeight)); } public final void show() { 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 e7c840a1b662..5378d3bf37c2 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 @@ -27,7 +27,7 @@ import com.intellij.xdebugger.frame.XFullValueEvaluator; import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; 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.WatchNodeImpl; import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -58,15 +58,11 @@ public abstract class XFetchValueActionBase extends AnAction { protected boolean isEnabled(@NotNull AnActionEvent event, @NotNull Object node) { if (node instanceof XValueNodeImpl) { - if (((XValueNodeImpl)node).isComputed()) { + if (node instanceof WatchNodeImpl || ((XValueNodeImpl)node).isComputed()) { event.getPresentation().setEnabled(true); return true; } } - else if (node instanceof WatchMessageNode) { - event.getPresentation().setEnabled(true); - return true; - } return false; } @@ -101,9 +97,6 @@ public abstract class XFetchValueActionBase extends AnAction { } } } - else if (node instanceof WatchMessageNode) { - valueCollector.add(((WatchMessageNode)node).getExpression().getExpression()); - } } @NotNull diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchMessageNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchMessageNode.java deleted file mode 100644 index 53115cd36a7b..000000000000 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchMessageNode.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2000-2015 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.nodes; - -import com.intellij.icons.AllIcons; -import com.intellij.ui.SimpleTextAttributes; -import com.intellij.xdebugger.XExpression; -import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants; -import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; -import org.jetbrains.annotations.NotNull; - -import javax.swing.*; - -/** - * @author nik - */ -public class WatchMessageNode extends MessageTreeNode implements WatchNode { - private final XExpression myExpression; - private volatile boolean myObsolete; - - private WatchMessageNode(XDebuggerTree tree, XDebuggerTreeNode parent, @NotNull XExpression expression, final Icon icon) { - super(tree, parent, true); - myExpression = expression; - setIcon(icon); - } - - @Override - @NotNull - public XExpression getExpression() { - return myExpression; - } - - public static WatchMessageNode createMessageNode(XDebuggerTree tree, XDebuggerTreeNode parent, XExpression expression) { - final WatchMessageNode node = new WatchMessageNode(tree, parent, expression, AllIcons.Debugger.Watch); - node.myText.append(expression.getExpression(), SimpleTextAttributes.REGULAR_ATTRIBUTES); - return node; - } - - public static WatchMessageNode createEvaluatingNode(XDebuggerTree tree, XDebuggerTreeNode parent, XExpression expression) { - final WatchMessageNode node = new WatchMessageNode(tree, parent, expression, AllIcons.Debugger.Watch); - node.myText.append(expression + " = ...", XDebuggerUIConstants.EVALUATING_EXPRESSION_HIGHLIGHT_ATTRIBUTES); - return node; - } - - public static WatchMessageNode createErrorNode(XDebuggerTree tree, XDebuggerTreeNode parent, @NotNull XExpression expression, @NotNull String errorMessage) { - final WatchMessageNode node = new WatchMessageNode(tree, parent, expression, XDebuggerUIConstants.ERROR_MESSAGE_ICON); - node.myText.append(expression + " = ", SimpleTextAttributes.REGULAR_ATTRIBUTES); - node.myText.append(errorMessage, SimpleTextAttributes.ERROR_ATTRIBUTES); - return node; - } - - @Override - public String toString() { - return myExpression.getExpression(); - } - - @Override - public void setObsolete() { - myObsolete = true; - } - - @Override - public boolean isObsolete() { - return myObsolete; - } -} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchNode.java index 54a84ac6f967..771cb798b231 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchNode.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchNode.java @@ -23,6 +23,8 @@ import javax.swing.tree.TreeNode; /** * @author nik + * + * @deprecated to be removed */ public interface WatchNode extends TreeNode, Obsolescent { @NotNull diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchNodeImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchNodeImpl.java index 73bc05646b8e..af43106354d9 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchNodeImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchNodeImpl.java @@ -15,10 +15,16 @@ */ package com.intellij.xdebugger.impl.ui.tree.nodes; +import com.intellij.icons.AllIcons; import com.intellij.xdebugger.XExpression; import com.intellij.xdebugger.frame.XValue; +import com.intellij.xdebugger.frame.presentation.XErrorValuePresentation; +import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; /** * @author nik @@ -26,12 +32,19 @@ import org.jetbrains.annotations.NotNull; public class WatchNodeImpl extends XValueNodeImpl implements WatchNode { private final XExpression myExpression; - public WatchNodeImpl(final @NotNull XDebuggerTree tree, final @NotNull WatchesRootNode parent, final @NotNull XValue result, - final @NotNull XExpression expression) { + public WatchNodeImpl(@NotNull XDebuggerTree tree, @NotNull WatchesRootNode parent, + @NotNull XValue result, @NotNull XExpression expression) { super(tree, parent, expression.getExpression(), result); myExpression = expression; } + @Nullable + @Override + public Icon getIcon() { + return getValuePresentation() instanceof XErrorValuePresentation? + XDebuggerUIConstants.ERROR_MESSAGE_ICON : AllIcons.Debugger.Watch; + } + @Override @NotNull public XExpression getExpression() { 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 78172bba8c72..4c70dacda133 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,115 +15,115 @@ */ package com.intellij.xdebugger.impl.ui.tree.nodes; +import com.intellij.icons.AllIcons; +import com.intellij.openapi.util.registry.Registry; +import com.intellij.util.ArrayUtil; +import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.tree.TreeUtil; import com.intellij.xdebugger.Obsolescent; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XExpression; import com.intellij.xdebugger.evaluation.XDebuggerEvaluator; -import com.intellij.xdebugger.frame.XValue; +import com.intellij.xdebugger.frame.*; +import com.intellij.xdebugger.frame.presentation.XErrorValuePresentation; +import com.intellij.xdebugger.frame.presentation.XValuePresentation; import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl; import com.intellij.xdebugger.impl.frame.WatchInplaceEditor; -import com.intellij.xdebugger.impl.frame.XDebugView; import com.intellij.xdebugger.impl.frame.XWatchesView; import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; +import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.tree.TreeNode; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; +import static com.intellij.xdebugger.impl.frame.XDebugView.getSession; + /** * @author nik */ -public class WatchesRootNode extends XDebuggerTreeNode { +public class WatchesRootNode extends XValueContainerNode { private final XWatchesView myWatchesView; - private List myChildren; - private List myLoadedChildren; - private XDebuggerEvaluator myCurrentEvaluator; + private final List myChildren; public WatchesRootNode(@NotNull XDebuggerTree tree, @NotNull XWatchesView watchesView, - @NotNull XExpression[] watchExpressions) { - super(tree, null, false); + @NotNull XExpression[] expressions) { + this(tree, watchesView, expressions, null); + } + + public WatchesRootNode(@NotNull XDebuggerTree tree, + @NotNull XWatchesView watchesView, + @NotNull XExpression[] expressions, + @Nullable XStackFrame stackFrame) { + super(tree, null, new XValueContainer() { + @Override + public void computeChildren(@NotNull XCompositeNode node) { + if (stackFrame != null && Registry.is("debugger.watches.in.variables")) { + stackFrame.computeChildren(node); + } + else { + node.addChildren(XValueChildrenList.EMPTY, true); + } + XDebuggerEvaluator evaluator = stackFrame == null ? null : stackFrame.getEvaluator(); + WatchesRootNode thisNode = (WatchesRootNode)node; + for (WatchNodeImpl child : thisNode.myChildren) { + MyEvaluationCallback callback = new MyEvaluationCallback(child); + if (evaluator != null) { + evaluator.evaluate(child.getExpression(), callback, stackFrame.getSourcePosition()); + } + else { + callback.noSession(); + } + } + } + }); + setLeaf(false); myWatchesView = watchesView; - myChildren = new ArrayList(); - for (XExpression watchExpression : watchExpressions) { - myChildren.add(WatchMessageNode.createMessageNode(tree, this, watchExpression)); + myChildren = ContainerUtil.newArrayList(); + for (XExpression watchExpression : expressions) { + myChildren.add(createEvaluatingNode(myTree, this, watchExpression)); } } - public void updateWatches(@Nullable XDebuggerEvaluator evaluator) { - myCurrentEvaluator = evaluator; - List newChildren = new ArrayList(); - for (WatchNode child : myChildren) { - child.setObsolete(); - } - if (evaluator != null) { - for (WatchNode child : myChildren) { - final XExpression expression = child.getExpression(); - final WatchMessageNode evaluatingNode = WatchMessageNode.createEvaluatingNode(myTree, this, expression); - newChildren.add(evaluatingNode); - evaluator.evaluate(expression, new MyEvaluationCallback(evaluatingNode), null); - } - } - else { - for (WatchNode child : myChildren) { - final XExpression expression = child.getExpression(); - newChildren.add(WatchMessageNode.createMessageNode(myTree, this, expression)); - } - } - myChildren = newChildren; - myLoadedChildren = null; - fireNodeStructureChanged(); + @Nullable + @Override + public List> getLoadedChildren() { + List> empty = Collections.emptyList(); + return ContainerUtil.concat(myChildren, ObjectUtils.notNull(super.getLoadedChildren(), empty)); } @NotNull @Override public List getChildren() { - return myChildren; + List children = super.getChildren(); + return ContainerUtil.concat(myChildren, children); } - @Nullable - public List getAllChildren() { + @NotNull + public List getWatchChildren() { return myChildren; } - @Override - public List getLoadedChildren() { - if (myLoadedChildren == null) { - myLoadedChildren = new ArrayList(); - for (WatchNode child : myChildren) { - if (child instanceof WatchNodeImpl) { - myLoadedChildren.add((WatchNodeImpl)child); - } - } - } - return myLoadedChildren; - } - @Override public void clearChildren() { - updateWatches(myCurrentEvaluator); + super.clearChildren(); + myChildren.clear(); } - private void replaceNode(final WatchNode oldNode, final WatchNode newNode) { + private void replaceNode(WatchNodeImpl oldNode, WatchNodeImpl newNode) { int[] selectedRows = getTree().getSelectionRows(); for (int i = 0; i < myChildren.size(); i++) { - WatchNode child = myChildren.get(i); + WatchNodeImpl child = myChildren.get(i); if (child == oldNode) { myChildren.set(i, newNode); - if (newNode instanceof XValueContainerNode) { - myLoadedChildren = null; - fireNodeStructureChanged(newNode); - myTree.childrenLoaded(this, Collections.>singletonList((XValueContainerNode)newNode), false); - } - else { - fireNodeStructureChanged(newNode); - } + fireNodeStructureChanged(newNode); + myTree.childrenLoaded(this, Collections.singletonList((XValueContainerNode)newNode), false); getTree().setSelectionRows(selectedRows); return; } @@ -133,7 +133,8 @@ public class WatchesRootNode extends XDebuggerTreeNode { public void addWatchExpression(final @Nullable XDebuggerEvaluator evaluator, final @NotNull XExpression expression, int index, final boolean navigateToWatchNode) { - WatchMessageNode message = evaluator != null ? WatchMessageNode.createEvaluatingNode(myTree, this, expression) : WatchMessageNode.createMessageNode(myTree, this, expression); + WatchNodeImpl message = evaluator != null ? createEvaluatingNode(myTree, this, expression) : + createMessageNode(myTree, this, expression); if (index == -1) { myChildren.add(message); index = myChildren.size() - 1; @@ -142,6 +143,7 @@ public class WatchesRootNode extends XDebuggerTreeNode { myChildren.add(index, message); } fireNodeInserted(index); + TreeUtil.selectNode(myTree, message); if (navigateToWatchNode) { myTree.scrollPathToVisible(message.getPath()); } @@ -159,23 +161,20 @@ public class WatchesRootNode extends XDebuggerTreeNode { int index = myChildren.indexOf(node); if (index != -1) { myChildren.remove(node); - myLoadedChildren = null; fireNodesRemoved(new int[]{index}, new TreeNode[]{node}); } return index; } public void removeChildren(Collection nodes) { - final int[] indices = getNodesIndices(nodes); - final TreeNode[] removed = getChildNodes(indices); + int[] indices = getNodesIndices(nodes); + TreeNode[] removed = getChildNodes(indices); myChildren.removeAll(nodes); - myLoadedChildren = null; fireNodesRemoved(indices, removed); } public void removeAllChildren() { myChildren.clear(); - myLoadedChildren = null; fireNodeStructureChanged(); } @@ -201,25 +200,28 @@ public class WatchesRootNode extends XDebuggerTreeNode { editWatch(null); } - public void editWatch(@Nullable WatchNode node) { - WatchNode messageNode = WatchMessageNode.createMessageNode(myTree, this, XExpressionImpl.EMPTY_EXPRESSION); + public void editWatch(@Nullable WatchNodeImpl node) { + WatchNodeImpl messageNode; int index = node != null ? myChildren.indexOf(node) : -1; if (index == -1) { - myChildren.add(messageNode); - fireNodeInserted(myChildren.size() - 1); + int selectedIndex = myChildren.indexOf(ArrayUtil.getFirstElement(myTree.getSelectedNodes(WatchNodeImpl.class, null))); + int targetIndex = selectedIndex == - 1 ? myChildren.size() : selectedIndex + 1; + messageNode = createMessageNode(myTree, this, XExpressionImpl.EMPTY_EXPRESSION); + myChildren.add(targetIndex, messageNode); + fireNodeInserted(targetIndex); + getTree().setSelectionRows(ArrayUtil.EMPTY_INT_ARRAY); } else { - myChildren.set(index, messageNode); - fireNodeStructureChanged(messageNode); + messageNode = node; } - XDebugSession session = XDebugView.getSession(myTree); + XDebugSession session = getSession(myTree); new WatchInplaceEditor(this, session, myWatchesView, messageNode, "watch", node).show(); } - private class MyEvaluationCallback extends XEvaluationCallbackBase implements Obsolescent { - private final WatchNode myResultPlace; + private static class MyEvaluationCallback extends XEvaluationCallbackBase implements Obsolescent { + private final WatchNodeImpl myResultPlace; - public MyEvaluationCallback(final @NotNull WatchNode resultPlace) { + public MyEvaluationCallback(@NotNull WatchNodeImpl resultPlace) { myResultPlace = resultPlace; } @@ -233,7 +235,8 @@ public class WatchesRootNode extends XDebuggerTreeNode { DebuggerUIUtil.invokeLater(new Runnable() { @Override public void run() { - replaceNode(myResultPlace, new WatchNodeImpl(myTree, WatchesRootNode.this, result, myResultPlace.getExpression())); + WatchesRootNode root = (WatchesRootNode)myResultPlace.getParent(); + root.replaceNode(myResultPlace, new WatchNodeImpl(root.myTree, root, result, myResultPlace.getExpression())); } }); } @@ -243,9 +246,57 @@ public class WatchesRootNode extends XDebuggerTreeNode { DebuggerUIUtil.invokeLater(new Runnable() { @Override public void run() { - replaceNode(myResultPlace, WatchMessageNode.createErrorNode(myTree, WatchesRootNode.this, myResultPlace.getExpression(), errorMessage)); + WatchesRootNode root = (WatchesRootNode)myResultPlace.getParent(); + root.replaceNode(myResultPlace, createErrorNode(root.myTree, root, myResultPlace.getExpression(), errorMessage)); + } + }); + } + + public void noSession() { + DebuggerUIUtil.invokeLater(new Runnable() { + @Override + public void run() { + WatchesRootNode root = (WatchesRootNode)myResultPlace.getParent(); + root.replaceNode(myResultPlace, createMessageNode(root.myTree, root, myResultPlace.getExpression())); } }); } } + + private static WatchNodeImpl createMessageNode(XDebuggerTree tree, WatchesRootNode parent, XExpression expression) { + return new WatchNodeImpl(tree, parent, new XValue() { + @Override + public void computePresentation(@NotNull XValueNode node, @NotNull XValuePlace place) { + node.setPresentation(AllIcons.Debugger.Watch, new XValuePresentation() { + @NotNull + @Override + public String getSeparator() { + return ""; + } + + @Override + public void renderValue(@NotNull XValueTextRenderer renderer) { + } + }, false); + } + }, expression); + } + + private static WatchNodeImpl createEvaluatingNode(XDebuggerTree tree, WatchesRootNode parent, XExpression expression) { + return new WatchNodeImpl(tree, parent, new XValue() { + @Override + public void computePresentation(@NotNull XValueNode node1, @NotNull XValuePlace place) { + } + }, expression); + } + + private static WatchNodeImpl createErrorNode(XDebuggerTree tree, WatchesRootNode parent, + @NotNull XExpression expression, @NotNull String errorMessage) { + return new WatchNodeImpl(tree, parent, new XValue() { + @Override + public void computePresentation(@NotNull XValueNode node, @NotNull XValuePlace place) { + node.setPresentation(XDebuggerUIConstants.ERROR_MESSAGE_ICON, new XErrorValuePresentation(errorMessage), false); + } + }, expression); + } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XStackFrameNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XStackFrameNode.java index eee3a99c2acc..dd018f945dc5 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XStackFrameNode.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XStackFrameNode.java @@ -15,16 +15,7 @@ */ package com.intellij.xdebugger.impl.ui.tree.nodes; -import com.intellij.openapi.util.registry.Registry; -import com.intellij.xdebugger.XDebugSession; -import com.intellij.xdebugger.XExpression; -import com.intellij.xdebugger.evaluation.XDebuggerEvaluator; import com.intellij.xdebugger.frame.XStackFrame; -import com.intellij.xdebugger.frame.XValue; -import com.intellij.xdebugger.frame.XValueChildrenList; -import com.intellij.xdebugger.impl.XDebugSessionImpl; -import com.intellij.xdebugger.impl.frame.XDebugView; -import com.intellij.xdebugger.impl.ui.XDebugSessionData; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import org.jetbrains.annotations.NotNull; @@ -32,34 +23,10 @@ import org.jetbrains.annotations.NotNull; * @author nik */ public class XStackFrameNode extends XValueContainerNode { + public XStackFrameNode(final @NotNull XDebuggerTree tree, final @NotNull XStackFrame xStackFrame) { super(tree, null, xStackFrame); setLeaf(false); } - @Override - public void startComputingChildren() { - if (Registry.is("debugger.watches.in.variables")) { - XDebugSession session = XDebugView.getSession(getTree()); - XDebuggerEvaluator evaluator = getValueContainer().getEvaluator(); - if (session != null && evaluator != null) { - XDebugSessionData data = ((XDebugSessionImpl)session).getSessionData(); - XExpression[] expressions = data.getWatchExpressions(); - for (final XExpression expression : expressions) { - evaluator.evaluate(expression, new XDebuggerEvaluator.XEvaluationCallback() { - @Override - public void evaluated(@NotNull XValue result) { - addChildren(XValueChildrenList.singleton(expression.getExpression(), result), false); - } - - @Override - public void errorOccurred(@NotNull String errorMessage) { - // do not add anything - } - }, getValueContainer().getSourcePosition()); - } - } - } - super.startComputingChildren(); - } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueContainerNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueContainerNode.java index 01cdc4c9f7e8..2148fb4c2b3a 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueContainerNode.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueContainerNode.java @@ -104,7 +104,7 @@ public abstract class XValueContainerNode(); if (myValueChildren == null) { - myValueChildren = last ? Collections.emptyList() : new SmartList<>(); + myValueChildren = new SmartList<>(); } }