XDebugger: Merge 'Watches' and 'Variables' views

This commit is contained in:
Gregory.Shrago
2016-03-10 21:07:33 +03:00
parent a86989f51b
commit 55029007ad
17 changed files with 323 additions and 348 deletions
@@ -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() {
@@ -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);
}
@@ -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<InlineVariablesInfo> DEBUG_VARIABLES = Key.create("debug.variables");
public static final Key<ObjectLongHashMap<VirtualFile>> 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<Pair<VirtualFile, Integer>, Set<Entry>> myData
= new THashMap<Pair<VirtualFile, Integer>, Set<Entry>>();
@@ -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;
}
}
}
@@ -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<VirtualFile>());
@@ -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 {
@@ -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<? extends WatchNode> 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<? extends WatchNode> current = root instanceof WatchesRootNode
? ((WatchesRootNode)tree.getRoot()).getWatchChildren() : Collections.emptyList();
List<XExpression> 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<? extends XDebuggerTreeNode> nodes) {
List<? extends WatchNode> children = myRootNode.getAllChildren();
List<? extends WatchNode> children = myRootNode.getWatchChildren();
int minIndex = Integer.MAX_VALUE;
List<XDebuggerTreeNode> toRemove = new ArrayList<XDebuggerTreeNode>();
if (children != null) {
@@ -376,10 +399,10 @@ public class XWatchesViewImpl extends XDebugView implements DnDNativeTarget, XWa
}
myRootNode.removeChildren(toRemove);
List<? extends WatchNode> newChildren = myRootNode.getAllChildren();
List<? extends WatchNode> 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<XExpression> watchExpressions = new ArrayList<XExpression>();
final List<? extends WatchNode> children = myRootNode.getAllChildren();
if (children != null) {
for (WatchNode child : children) {
watchExpressions.add(child.getExpression());
}
List<XExpression> watchExpressions = ContainerUtil.newArrayList();
List<? extends WatchNode> 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;
}
}
}
@@ -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<? extends WatchNode> nodes = getSelectedNodes(tree, WatchNode.class);
for (WatchNode node : nodes) {
List<? extends XValueNodeImpl> 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)));
}
}
}
@@ -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<? extends WatchNode> watchNodes = getSelectedNodes(tree, WatchNode.class);
List<? extends WatchNodeImpl> 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);
@@ -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<? extends XDebuggerTreeNode> nodes = getSelectedNodes(tree, XDebuggerTreeNode.class);
List<? extends WatchNodeImpl>nodes = getSelectedNodes(tree, WatchNodeImpl.class);
watchesView.removeWatches(nodes);
}
}
@@ -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<XDebugSessionTab> TAB_KEY = DataKey.create("XDebugSessionTab");
private XWatchesViewImpl myWatchesView;
private final List<XDebugView> myViews = new ArrayList<XDebugView>();
private final List<XDebugView> 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;
@@ -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() {
@@ -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
@@ -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;
}
}
@@ -23,6 +23,8 @@ import javax.swing.tree.TreeNode;
/**
* @author nik
*
* @deprecated to be removed
*/
public interface WatchNode extends TreeNode, Obsolescent {
@NotNull
@@ -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() {
@@ -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<XValueContainer> {
private final XWatchesView myWatchesView;
private List<WatchNode> myChildren;
private List<XDebuggerTreeNode> myLoadedChildren;
private XDebuggerEvaluator myCurrentEvaluator;
private final List<WatchNodeImpl> 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<WatchNode>();
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<WatchNode> newChildren = new ArrayList<WatchNode>();
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<? extends XValueContainerNode<?>> getLoadedChildren() {
List<? extends XValueContainerNode<?>> empty = Collections.<XValueGroupNodeImpl>emptyList();
return ContainerUtil.concat(myChildren, ObjectUtils.notNull(super.getLoadedChildren(), empty));
}
@NotNull
@Override
public List<? extends TreeNode> getChildren() {
return myChildren;
List<? extends TreeNode> children = super.getChildren();
return ContainerUtil.concat(myChildren, children);
}
@Nullable
public List<? extends WatchNode> getAllChildren() {
@NotNull
public List<? extends WatchNode> getWatchChildren() {
return myChildren;
}
@Override
public List<? extends XDebuggerTreeNode> getLoadedChildren() {
if (myLoadedChildren == null) {
myLoadedChildren = new ArrayList<XDebuggerTreeNode>();
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.<XValueContainerNode<?>>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<? extends XDebuggerTreeNode> 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);
}
}
@@ -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<XStackFrame> {
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();
}
}
@@ -104,7 +104,7 @@ public abstract class XValueContainerNode<ValueContainer extends XValueContainer
else {
newChildren = new SmartList<>();
if (myValueChildren == null) {
myValueChildren = last ? Collections.emptyList() : new SmartList<>();
myValueChildren = new SmartList<>();
}
}