mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
XDebugger: Merge 'Watches' and 'Variables' views
This commit is contained in:
@@ -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() {
|
||||
|
||||
+3
-3
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+20
-12
@@ -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 {
|
||||
|
||||
+90
-90
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+17
-5
@@ -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)));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -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);
|
||||
|
||||
+5
-4
@@ -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;
|
||||
|
||||
+4
-1
@@ -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() {
|
||||
|
||||
+2
-9
@@ -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
|
||||
|
||||
-79
@@ -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
-2
@@ -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() {
|
||||
|
||||
+131
-80
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-34
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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<>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user