mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
xdebugger: debugger trees decoupled from XDebugSession
This commit is contained in:
+3
-1
@@ -29,6 +29,7 @@ import com.intellij.xdebugger.XSourcePosition;
|
||||
import com.intellij.xdebugger.evaluation.EvaluationMode;
|
||||
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
|
||||
import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
|
||||
import com.intellij.xdebugger.impl.XDebugSessionImpl;
|
||||
import com.intellij.xdebugger.impl.actions.XDebuggerActions;
|
||||
import com.intellij.xdebugger.impl.ui.XDebuggerEditorBase;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
|
||||
@@ -84,7 +85,8 @@ public class XDebuggerEvaluationDialog extends DialogWrapper {
|
||||
};
|
||||
mySession.addSessionListener(mySessionListener);
|
||||
|
||||
myTreePanel = new XDebuggerTreePanel(session, editorsProvider, myDisposable, sourcePosition, XDebuggerActions.EVALUATE_DIALOG_TREE_POPUP_GROUP);
|
||||
myTreePanel = new XDebuggerTreePanel(session.getProject(), editorsProvider, myDisposable, sourcePosition, XDebuggerActions.EVALUATE_DIALOG_TREE_POPUP_GROUP,
|
||||
((XDebugSessionImpl)session).getValueMarkers());
|
||||
myResultPanel = new JPanel(new BorderLayout());
|
||||
myResultPanel.add(new JLabel(XDebuggerBundle.message("xdebugger.evaluate.label.result")), BorderLayout.NORTH);
|
||||
myResultPanel.add(myTreePanel.getMainPanel(), BorderLayout.CENTER);
|
||||
|
||||
+5
-2
@@ -32,10 +32,12 @@ import com.intellij.xdebugger.frame.XFullValueEvaluator;
|
||||
import com.intellij.xdebugger.frame.XValue;
|
||||
import com.intellij.xdebugger.frame.XValuePlace;
|
||||
import com.intellij.xdebugger.frame.presentation.XValuePresentation;
|
||||
import com.intellij.xdebugger.impl.XDebugSessionImpl;
|
||||
import com.intellij.xdebugger.impl.actions.XDebuggerActions;
|
||||
import com.intellij.xdebugger.impl.actions.handlers.XDebuggerEvaluateActionHandler;
|
||||
import com.intellij.xdebugger.impl.evaluate.quick.common.AbstractValueHint;
|
||||
import com.intellij.xdebugger.impl.evaluate.quick.common.ValueHintType;
|
||||
import com.intellij.xdebugger.impl.frame.XValueMarkers;
|
||||
import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XEvaluationCallbackBase;
|
||||
@@ -128,8 +130,9 @@ public class XValueHint extends AbstractValueHint {
|
||||
}
|
||||
|
||||
private void showTree(final XValue value, final String name) {
|
||||
XDebuggerTree tree = new XDebuggerTree(myDebugSession, myDebugSession.getDebugProcess().getEditorsProvider(),
|
||||
myDebugSession.getCurrentPosition(), XDebuggerActions.INSPECT_TREE_POPUP_GROUP);
|
||||
XValueMarkers<?,?> valueMarkers = ((XDebugSessionImpl)myDebugSession).getValueMarkers();
|
||||
XDebuggerTree tree = new XDebuggerTree(myDebugSession.getProject(), myDebugSession.getDebugProcess().getEditorsProvider(),
|
||||
myDebugSession.getCurrentPosition(), XDebuggerActions.INSPECT_TREE_POPUP_GROUP, valueMarkers);
|
||||
tree.getModel().addTreeModelListener(createTreeListener(tree));
|
||||
XValueHintTreeComponent component = new XValueHintTreeComponent(this, tree, Pair.create(value, name));
|
||||
showTreePopup(component, tree, name);
|
||||
|
||||
+9
-22
@@ -17,16 +17,14 @@ package com.intellij.xdebugger.impl.frame;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.AppUIUtil;
|
||||
import com.intellij.xdebugger.XStackFrameAwareSession;
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import com.intellij.xdebugger.XDebugSessionAdapter;
|
||||
import com.intellij.xdebugger.impl.XDebugSessionImpl;
|
||||
import com.intellij.xdebugger.impl.ui.XDebugSessionTab;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeInplaceEditor;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.WatchNode;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.WatchesRootNode;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -36,20 +34,19 @@ import javax.swing.*;
|
||||
*/
|
||||
public class WatchInplaceEditor extends XDebuggerTreeInplaceEditor {
|
||||
private final WatchesRootNode myRootNode;
|
||||
private final XWatchesView myWatchesView;
|
||||
@Nullable private final WatchNode myOldNode;
|
||||
|
||||
public WatchInplaceEditor(WatchesRootNode rootNode,
|
||||
final WatchNode node,
|
||||
public WatchInplaceEditor(@NotNull WatchesRootNode rootNode,
|
||||
@NotNull XDebugSession session, XWatchesView watchesView, final WatchNode node,
|
||||
@NonNls final String historyId,
|
||||
final @Nullable WatchNode oldNode) {
|
||||
super((XDebuggerTreeNode)node, historyId);
|
||||
myRootNode = rootNode;
|
||||
myWatchesView = watchesView;
|
||||
myOldNode = oldNode;
|
||||
myExpressionEditor.setText(oldNode != null ? oldNode.getExpression() : "");
|
||||
final XStackFrameAwareSession session = rootNode.getTree().getSession();
|
||||
if (session instanceof XDebugSession) {
|
||||
new WatchEditorSessionListener((XDebugSession)session).install();
|
||||
}
|
||||
new WatchEditorSessionListener(session).install();
|
||||
}
|
||||
|
||||
protected JComponent createInplaceEditorComponent() {
|
||||
@@ -61,7 +58,7 @@ public class WatchInplaceEditor extends XDebuggerTreeInplaceEditor {
|
||||
super.cancelEditing();
|
||||
int index = myRootNode.removeChildNode(getNode());
|
||||
if (myOldNode != null && index != -1) {
|
||||
getWatchesView().addWatchExpression(myOldNode.getExpression(), index, false);
|
||||
myWatchesView.addWatchExpression(myOldNode.getExpression(), index, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,24 +68,14 @@ public class WatchInplaceEditor extends XDebuggerTreeInplaceEditor {
|
||||
super.doOKAction();
|
||||
int index = myRootNode.removeChildNode(getNode());
|
||||
if (!StringUtil.isEmpty(expression) && index != -1) {
|
||||
getWatchesView().addWatchExpression(expression, index, false);
|
||||
}
|
||||
}
|
||||
|
||||
private XWatchesView getWatchesView() {
|
||||
if (myRootNode.getTree().getSession() instanceof XDebugSessionImpl) {
|
||||
XDebugSessionTab tab = ((XDebugSessionImpl)myRootNode.getTree().getSession()).getSessionTab();
|
||||
return tab.getWatchesView();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
myWatchesView.addWatchExpression(expression, index, false);
|
||||
}
|
||||
}
|
||||
|
||||
private class WatchEditorSessionListener extends XDebugSessionAdapter {
|
||||
private final XDebugSession mySession;
|
||||
|
||||
public WatchEditorSessionListener(XDebugSession session) {
|
||||
public WatchEditorSessionListener(@NotNull XDebugSession session) {
|
||||
mySession = session;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,12 +17,13 @@ package com.intellij.xdebugger.impl.frame;
|
||||
|
||||
import com.intellij.ide.dnd.DnDManager;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.xdebugger.XStackFrameAwareSession;
|
||||
import com.intellij.xdebugger.XDebugProcess;
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import com.intellij.xdebugger.XDebuggerBundle;
|
||||
import com.intellij.xdebugger.XStackFrameAwareSession;
|
||||
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
|
||||
import com.intellij.xdebugger.frame.XStackFrame;
|
||||
import com.intellij.xdebugger.impl.XDebugSessionImpl;
|
||||
import com.intellij.xdebugger.impl.actions.XDebuggerActions;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreePanel;
|
||||
@@ -49,7 +50,8 @@ public class XVariablesView extends XDebugViewBase {
|
||||
public XVariablesView(@NotNull XStackFrameAwareSession session, @Nullable final Disposable parentDisposable) {
|
||||
super(session, parentDisposable);
|
||||
XDebuggerEditorsProvider editorsProvider = session.getEditorsProvider();
|
||||
myDebuggerTreePanel = new XDebuggerTreePanel(session, editorsProvider, this, null, XDebuggerActions.VARIABLES_TREE_POPUP_GROUP);
|
||||
XValueMarkers<?,?> markers = session instanceof XDebugSessionImpl ? ((XDebugSessionImpl)session).getValueMarkers() : null;
|
||||
myDebuggerTreePanel = new XDebuggerTreePanel(session.getProject(), editorsProvider, this, null, XDebuggerActions.VARIABLES_TREE_POPUP_GROUP, markers);
|
||||
myDebuggerTreePanel.getTree().getEmptyText().setText(XDebuggerBundle.message("debugger.variables.not.available"));
|
||||
DnDManager.getInstance().registerSource(myDebuggerTreePanel, myDebuggerTreePanel.getTree());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,236 +15,21 @@
|
||||
*/
|
||||
package com.intellij.xdebugger.impl.frame;
|
||||
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.dnd.DnDEvent;
|
||||
import com.intellij.ide.dnd.DnDManager;
|
||||
import com.intellij.ide.dnd.DnDNativeTarget;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.ui.AnActionButton;
|
||||
import com.intellij.ui.AnActionButtonRunnable;
|
||||
import com.intellij.ui.CaptionPanel;
|
||||
import com.intellij.ui.ToolbarDecorator;
|
||||
import com.intellij.ui.border.CustomLineBorder;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import com.intellij.xdebugger.XDebuggerBundle;
|
||||
import com.intellij.xdebugger.frame.XStackFrame;
|
||||
import com.intellij.xdebugger.impl.actions.XDebuggerActions;
|
||||
import com.intellij.xdebugger.impl.ui.XDebugSessionData;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreePanel;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeRestorer;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeState;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.WatchNode;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.WatchesRootNode;
|
||||
import com.intellij.openapi.actionSystem.DataKey;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class XWatchesView extends XDebugViewBase implements DnDNativeTarget {
|
||||
private final XDebuggerTreePanel myTreePanel;
|
||||
private XDebuggerTreeState myTreeState;
|
||||
private XDebuggerTreeRestorer myTreeRestorer;
|
||||
private final WatchesRootNode myRootNode;
|
||||
private final XDebugSessionData mySessionData;
|
||||
private final JPanel myDecoratedPanel;
|
||||
public interface XWatchesView {
|
||||
DataKey<XWatchesView> DATA_KEY = DataKey.create("XDEBUGGER_WATCHES_VIEW");
|
||||
|
||||
public XWatchesView(@NotNull final XDebugSession session, @Nullable final Disposable parentDisposable, final XDebugSessionData sessionData) {
|
||||
super(session, parentDisposable);
|
||||
mySessionData = sessionData;
|
||||
myTreePanel = new XDebuggerTreePanel(session, session.getDebugProcess().getEditorsProvider(), this, null,
|
||||
XDebuggerActions.WATCHES_TREE_POPUP_GROUP);
|
||||
void addWatchExpression(@NotNull String expression, int index, boolean navigateToWatchNode);
|
||||
|
||||
ActionManager actionManager = ActionManager.getInstance();
|
||||
void removeWatches(List<? extends XDebuggerTreeNode> nodes);
|
||||
|
||||
XDebuggerTree tree = myTreePanel.getTree();
|
||||
actionManager.getAction(XDebuggerActions.XNEW_WATCH).registerCustomShortcutSet(CommonShortcuts.INSERT, tree);
|
||||
actionManager.getAction(XDebuggerActions.XREMOVE_WATCH).registerCustomShortcutSet(CommonShortcuts.DELETE, tree);
|
||||
|
||||
CustomShortcutSet f2Shortcut = new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0));
|
||||
actionManager.getAction(XDebuggerActions.XEDIT_WATCH).registerCustomShortcutSet(f2Shortcut, tree);
|
||||
|
||||
DnDManager.getInstance().registerTarget(this, tree);
|
||||
myRootNode = new WatchesRootNode(tree, sessionData.getWatchExpressions());
|
||||
tree.setRoot(myRootNode, false);
|
||||
|
||||
final ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myTreePanel.getTree()).disableUpDownActions();
|
||||
decorator.setAddAction(new AnActionButtonRunnable() {
|
||||
@Override
|
||||
public void run(AnActionButton button) {
|
||||
executeAction(XDebuggerActions.XNEW_WATCH);
|
||||
}
|
||||
});
|
||||
decorator.setRemoveAction(new AnActionButtonRunnable() {
|
||||
@Override
|
||||
public void run(AnActionButton button) {
|
||||
executeAction(XDebuggerActions.XREMOVE_WATCH);
|
||||
}
|
||||
});
|
||||
CustomLineBorder border = new CustomLineBorder(CaptionPanel.CNT_ACTIVE_BORDER_COLOR,
|
||||
SystemInfo.isMac ? 1 : 0, 0,
|
||||
SystemInfo.isMac ? 0 : 1, 0);
|
||||
decorator.setToolbarBorder(border);
|
||||
myDecoratedPanel = decorator.createPanel();
|
||||
myDecoratedPanel.setBorder(null);
|
||||
|
||||
myTreePanel.getTree().getEmptyText().setText(XDebuggerBundle.message("debugger.no.watches"));
|
||||
|
||||
}
|
||||
|
||||
private void executeAction(final String watch) {
|
||||
AnAction action = ActionManager.getInstance().getAction(watch);
|
||||
Presentation presentation = action.getTemplatePresentation().clone();
|
||||
DataContext context = DataManager.getInstance().getDataContext(myTreePanel.getTree());
|
||||
|
||||
AnActionEvent actionEvent =
|
||||
new AnActionEvent(null, context, ActionPlaces.DEBUGGER_TOOLBAR, presentation, ActionManager.getInstance(), 0);
|
||||
action.actionPerformed(actionEvent);
|
||||
}
|
||||
|
||||
public void addWatchExpression(@NotNull String expression, int index, final boolean navigateToWatchNode) {
|
||||
XStackFrame stackFrame = mySession.getCurrentStackFrame();
|
||||
myRootNode.addWatchExpression(stackFrame == null ? null : stackFrame.getEvaluator(), expression, index, navigateToWatchNode);
|
||||
updateSessionData();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void rebuildView(final SessionEvent event) {
|
||||
XStackFrame stackFrame = mySession.getCurrentStackFrame();
|
||||
XDebuggerTree tree = myTreePanel.getTree();
|
||||
|
||||
if (event == SessionEvent.BEFORE_RESUME || event == SessionEvent.SETTINGS_CHANGED) {
|
||||
if (myTreeRestorer != null) {
|
||||
myTreeRestorer.dispose();
|
||||
}
|
||||
myTreeState = XDebuggerTreeState.saveState(tree);
|
||||
if (event == SessionEvent.BEFORE_RESUME) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (stackFrame != null) {
|
||||
tree.setSourcePosition(stackFrame.getSourcePosition());
|
||||
myRootNode.updateWatches(stackFrame.getEvaluator());
|
||||
if (myTreeState != null) {
|
||||
myTreeRestorer = myTreeState.restoreState(tree);
|
||||
}
|
||||
}
|
||||
else {
|
||||
tree.setSourcePosition(null);
|
||||
myRootNode.updateWatches(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
DnDManager.getInstance().unregisterTarget(this, myTreePanel.getTree());
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
public XDebuggerTree getTree() {
|
||||
return myTreePanel.getTree();
|
||||
}
|
||||
|
||||
public JPanel getMainPanel() {
|
||||
return myDecoratedPanel;
|
||||
}
|
||||
|
||||
public void removeWatches(final List<? extends XDebuggerTreeNode> nodes) {
|
||||
List<? extends WatchNode> children = myRootNode.getAllChildren();
|
||||
int minIndex = Integer.MAX_VALUE;
|
||||
List<XDebuggerTreeNode> toRemove = new ArrayList<XDebuggerTreeNode>();
|
||||
if (children != null) {
|
||||
for (XDebuggerTreeNode node : nodes) {
|
||||
@SuppressWarnings("SuspiciousMethodCalls")
|
||||
int index = children.indexOf(node);
|
||||
if (index != -1) {
|
||||
toRemove.add(node);
|
||||
minIndex = Math.min(minIndex, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
myRootNode.removeChildren(toRemove);
|
||||
|
||||
List<? extends WatchNode> newChildren = myRootNode.getAllChildren();
|
||||
if (newChildren != null && !newChildren.isEmpty()) {
|
||||
WatchNode node = minIndex < newChildren.size() ? newChildren.get(minIndex) : newChildren.get(newChildren.size() - 1);
|
||||
TreeUtil.selectNode(myTreePanel.getTree(), node);
|
||||
}
|
||||
updateSessionData();
|
||||
}
|
||||
|
||||
public void removeAllWatches() {
|
||||
myRootNode.removeAllChildren();
|
||||
updateSessionData();
|
||||
}
|
||||
|
||||
private void updateSessionData() {
|
||||
List<String> watchExpressions = new ArrayList<String>();
|
||||
final List<? extends WatchNode> children = myRootNode.getAllChildren();
|
||||
if (children != null) {
|
||||
for (WatchNode child : children) {
|
||||
watchExpressions.add(child.getExpression());
|
||||
}
|
||||
}
|
||||
mySessionData.setWatchExpressions(ArrayUtil.toStringArray(watchExpressions));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(final DnDEvent aEvent) {
|
||||
Object object = aEvent.getAttachedObject();
|
||||
boolean possible = false;
|
||||
if (object instanceof XValueNodeImpl[]) {
|
||||
possible = true;
|
||||
}
|
||||
else if (object instanceof EventInfo) {
|
||||
possible = ((EventInfo)object).getTextForFlavor(DataFlavor.stringFlavor) != null;
|
||||
}
|
||||
|
||||
aEvent.setDropPossible(possible, XDebuggerBundle.message("xdebugger.drop.text.add.to.watches"));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drop(final DnDEvent aEvent) {
|
||||
Object object = aEvent.getAttachedObject();
|
||||
if (object instanceof XValueNodeImpl[]) {
|
||||
final XValueNodeImpl[] nodes = (XValueNodeImpl[])object;
|
||||
for (XValueNodeImpl node : nodes) {
|
||||
String expression = node.getValueContainer().getEvaluationExpression();
|
||||
if (expression != null) {
|
||||
addWatchExpression(expression, -1, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (object instanceof EventInfo) {
|
||||
String text = ((EventInfo)object).getTextForFlavor(DataFlavor.stringFlavor);
|
||||
if (text != null) {
|
||||
addWatchExpression(text, -1, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUpOnLeave() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDraggedImage(final Image image, final Point dropPoint, final Point imageOffset) {
|
||||
}
|
||||
void removeAllWatches();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.xdebugger.impl.frame;
|
||||
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.dnd.DnDEvent;
|
||||
import com.intellij.ide.dnd.DnDManager;
|
||||
import com.intellij.ide.dnd.DnDNativeTarget;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.ui.AnActionButton;
|
||||
import com.intellij.ui.AnActionButtonRunnable;
|
||||
import com.intellij.ui.CaptionPanel;
|
||||
import com.intellij.ui.ToolbarDecorator;
|
||||
import com.intellij.ui.border.CustomLineBorder;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import com.intellij.xdebugger.XDebuggerBundle;
|
||||
import com.intellij.xdebugger.frame.XStackFrame;
|
||||
import com.intellij.xdebugger.impl.XDebugSessionImpl;
|
||||
import com.intellij.xdebugger.impl.actions.XDebuggerActions;
|
||||
import com.intellij.xdebugger.impl.ui.XDebugSessionData;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreePanel;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeRestorer;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeState;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.WatchNode;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.WatchesRootNode;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class XWatchesViewImpl extends XDebugViewBase implements DnDNativeTarget, XWatchesView {
|
||||
private final XDebuggerTreePanel myTreePanel;
|
||||
private XDebuggerTreeState myTreeState;
|
||||
private XDebuggerTreeRestorer myTreeRestorer;
|
||||
private final WatchesRootNode myRootNode;
|
||||
private final XDebugSessionData mySessionData;
|
||||
private final JPanel myDecoratedPanel;
|
||||
|
||||
public XWatchesViewImpl(@NotNull final XDebugSession session,
|
||||
@NotNull final Disposable parentDisposable,
|
||||
final XDebugSessionData sessionData) {
|
||||
super(session, parentDisposable);
|
||||
mySessionData = sessionData;
|
||||
myTreePanel = new XDebuggerTreePanel(session.getProject(), session.getDebugProcess().getEditorsProvider(), this, null,
|
||||
XDebuggerActions.WATCHES_TREE_POPUP_GROUP, ((XDebugSessionImpl)session).getValueMarkers());
|
||||
|
||||
ActionManager actionManager = ActionManager.getInstance();
|
||||
|
||||
XDebuggerTree tree = myTreePanel.getTree();
|
||||
actionManager.getAction(XDebuggerActions.XNEW_WATCH).registerCustomShortcutSet(CommonShortcuts.INSERT, tree);
|
||||
actionManager.getAction(XDebuggerActions.XREMOVE_WATCH).registerCustomShortcutSet(CommonShortcuts.DELETE, tree);
|
||||
|
||||
CustomShortcutSet f2Shortcut = new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0));
|
||||
actionManager.getAction(XDebuggerActions.XEDIT_WATCH).registerCustomShortcutSet(f2Shortcut, tree);
|
||||
|
||||
DnDManager.getInstance().registerTarget(this, tree);
|
||||
Disposer.register(parentDisposable, new Disposable() {
|
||||
@Override
|
||||
public void dispose() {
|
||||
DnDManager.getInstance().unregisterTarget(XWatchesViewImpl.this, myTreePanel.getTree());
|
||||
}
|
||||
});
|
||||
myRootNode = new WatchesRootNode(tree, session, this, sessionData.getWatchExpressions());
|
||||
tree.setRoot(myRootNode, false);
|
||||
|
||||
final ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myTreePanel.getTree()).disableUpDownActions();
|
||||
decorator.setAddAction(new AnActionButtonRunnable() {
|
||||
@Override
|
||||
public void run(AnActionButton button) {
|
||||
executeAction(XDebuggerActions.XNEW_WATCH);
|
||||
}
|
||||
});
|
||||
decorator.setRemoveAction(new AnActionButtonRunnable() {
|
||||
@Override
|
||||
public void run(AnActionButton button) {
|
||||
executeAction(XDebuggerActions.XREMOVE_WATCH);
|
||||
}
|
||||
});
|
||||
CustomLineBorder border = new CustomLineBorder(CaptionPanel.CNT_ACTIVE_BORDER_COLOR,
|
||||
SystemInfo.isMac ? 1 : 0, 0,
|
||||
SystemInfo.isMac ? 0 : 1, 0);
|
||||
decorator.setToolbarBorder(border);
|
||||
myDecoratedPanel = decorator.createPanel();
|
||||
myDecoratedPanel.setBorder(null);
|
||||
|
||||
myTreePanel.getTree().getEmptyText().setText(XDebuggerBundle.message("debugger.no.watches"));
|
||||
|
||||
}
|
||||
|
||||
private void executeAction(final String watch) {
|
||||
AnAction action = ActionManager.getInstance().getAction(watch);
|
||||
Presentation presentation = action.getTemplatePresentation().clone();
|
||||
DataContext context = DataManager.getInstance().getDataContext(myTreePanel.getTree());
|
||||
|
||||
AnActionEvent actionEvent =
|
||||
new AnActionEvent(null, context, ActionPlaces.DEBUGGER_TOOLBAR, presentation, ActionManager.getInstance(), 0);
|
||||
action.actionPerformed(actionEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addWatchExpression(@NotNull String expression, int index, final boolean navigateToWatchNode) {
|
||||
XStackFrame stackFrame = mySession.getCurrentStackFrame();
|
||||
myRootNode.addWatchExpression(stackFrame == null ? null : stackFrame.getEvaluator(), expression, index, navigateToWatchNode);
|
||||
updateSessionData();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void rebuildView(final SessionEvent event) {
|
||||
XStackFrame stackFrame = mySession.getCurrentStackFrame();
|
||||
XDebuggerTree tree = myTreePanel.getTree();
|
||||
|
||||
if (event == SessionEvent.BEFORE_RESUME || event == SessionEvent.SETTINGS_CHANGED) {
|
||||
if (myTreeRestorer != null) {
|
||||
myTreeRestorer.dispose();
|
||||
}
|
||||
myTreeState = XDebuggerTreeState.saveState(tree);
|
||||
if (event == SessionEvent.BEFORE_RESUME) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (stackFrame != null) {
|
||||
tree.setSourcePosition(stackFrame.getSourcePosition());
|
||||
myRootNode.updateWatches(stackFrame.getEvaluator());
|
||||
if (myTreeState != null) {
|
||||
myTreeRestorer = myTreeState.restoreState(tree);
|
||||
}
|
||||
}
|
||||
else {
|
||||
tree.setSourcePosition(null);
|
||||
myRootNode.updateWatches(null);
|
||||
}
|
||||
}
|
||||
|
||||
public XDebuggerTree getTree() {
|
||||
return myTreePanel.getTree();
|
||||
}
|
||||
|
||||
public JPanel getMainPanel() {
|
||||
return myDecoratedPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeWatches(final List<? extends XDebuggerTreeNode> nodes) {
|
||||
List<? extends WatchNode> children = myRootNode.getAllChildren();
|
||||
int minIndex = Integer.MAX_VALUE;
|
||||
List<XDebuggerTreeNode> toRemove = new ArrayList<XDebuggerTreeNode>();
|
||||
if (children != null) {
|
||||
for (XDebuggerTreeNode node : nodes) {
|
||||
@SuppressWarnings("SuspiciousMethodCalls")
|
||||
int index = children.indexOf(node);
|
||||
if (index != -1) {
|
||||
toRemove.add(node);
|
||||
minIndex = Math.min(minIndex, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
myRootNode.removeChildren(toRemove);
|
||||
|
||||
List<? extends WatchNode> newChildren = myRootNode.getAllChildren();
|
||||
if (newChildren != null && !newChildren.isEmpty()) {
|
||||
WatchNode node = minIndex < newChildren.size() ? newChildren.get(minIndex) : newChildren.get(newChildren.size() - 1);
|
||||
TreeUtil.selectNode(myTreePanel.getTree(), node);
|
||||
}
|
||||
updateSessionData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllWatches() {
|
||||
myRootNode.removeAllChildren();
|
||||
updateSessionData();
|
||||
}
|
||||
|
||||
private void updateSessionData() {
|
||||
List<String> watchExpressions = new ArrayList<String>();
|
||||
final List<? extends WatchNode> children = myRootNode.getAllChildren();
|
||||
if (children != null) {
|
||||
for (WatchNode child : children) {
|
||||
watchExpressions.add(child.getExpression());
|
||||
}
|
||||
}
|
||||
mySessionData.setWatchExpressions(ArrayUtil.toStringArray(watchExpressions));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(final DnDEvent aEvent) {
|
||||
Object object = aEvent.getAttachedObject();
|
||||
boolean possible = false;
|
||||
if (object instanceof XValueNodeImpl[]) {
|
||||
possible = true;
|
||||
}
|
||||
else if (object instanceof EventInfo) {
|
||||
possible = ((EventInfo)object).getTextForFlavor(DataFlavor.stringFlavor) != null;
|
||||
}
|
||||
|
||||
aEvent.setDropPossible(possible, XDebuggerBundle.message("xdebugger.drop.text.add.to.watches"));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drop(final DnDEvent aEvent) {
|
||||
Object object = aEvent.getAttachedObject();
|
||||
if (object instanceof XValueNodeImpl[]) {
|
||||
final XValueNodeImpl[] nodes = (XValueNodeImpl[])object;
|
||||
for (XValueNodeImpl node : nodes) {
|
||||
String expression = node.getValueContainer().getEvaluationExpression();
|
||||
if (expression != null) {
|
||||
addWatchExpression(expression, -1, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (object instanceof EventInfo) {
|
||||
String text = ((EventInfo)object).getTextForFlavor(DataFlavor.stringFlavor);
|
||||
if (text != null) {
|
||||
addWatchExpression(text, -1, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUpOnLeave() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDraggedImage(final Image image, final Point dropPoint, final Point imageOffset) {
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -16,10 +16,12 @@
|
||||
package com.intellij.xdebugger.impl.frame.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.xdebugger.impl.frame.XWatchesView;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.WatchNode;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.WatchesRootNode;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -35,7 +37,7 @@ public class XEditWatchAction extends XWatchesTreeActionBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void perform(AnActionEvent e, XDebuggerTree tree) {
|
||||
protected void perform(@NotNull AnActionEvent e, @NotNull XDebuggerTree tree, @NotNull XWatchesView watchesView) {
|
||||
List<? extends WatchNode> watchNodes = getSelectedNodes(tree, WatchNode.class);
|
||||
if (watchNodes.size() != 1) return;
|
||||
|
||||
|
||||
+3
-1
@@ -16,16 +16,18 @@
|
||||
package com.intellij.xdebugger.impl.frame.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.xdebugger.impl.frame.XWatchesView;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.WatchesRootNode;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class XNewWatchAction extends XWatchesTreeActionBase {
|
||||
@Override
|
||||
protected void perform(AnActionEvent e, XDebuggerTree tree) {
|
||||
protected void perform(@NotNull AnActionEvent e, @NotNull XDebuggerTree tree, @NotNull XWatchesView watchesView) {
|
||||
XDebuggerTreeNode root = tree.getRoot();
|
||||
if (root instanceof WatchesRootNode) {
|
||||
final WatchesRootNode watchesRoot = (WatchesRootNode)root;
|
||||
|
||||
+5
-9
@@ -16,8 +16,7 @@
|
||||
package com.intellij.xdebugger.impl.frame.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.xdebugger.impl.XDebugSessionImpl;
|
||||
import com.intellij.xdebugger.impl.ui.XDebugSessionTab;
|
||||
import com.intellij.xdebugger.impl.frame.XWatchesView;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -26,15 +25,12 @@ import org.jetbrains.annotations.NotNull;
|
||||
*/
|
||||
public class XRemoveAllWatchesAction extends XWatchesTreeActionBase {
|
||||
@Override
|
||||
protected boolean isEnabled(AnActionEvent e, @NotNull XDebuggerTree tree) {
|
||||
return tree.getRoot().getChildCount() > 0 && (tree.getSession() instanceof XDebugSessionImpl);
|
||||
protected boolean isEnabled(@NotNull AnActionEvent e, @NotNull XDebuggerTree tree) {
|
||||
return tree.getRoot().getChildCount() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void perform(AnActionEvent e, XDebuggerTree tree) {
|
||||
if (tree.getSession() instanceof XDebugSessionImpl) {
|
||||
XDebugSessionTab tab = ((XDebugSessionImpl)tree.getSession()).getSessionTab();
|
||||
tab.getWatchesView().removeAllWatches();
|
||||
}
|
||||
protected void perform(@NotNull AnActionEvent e, @NotNull XDebuggerTree tree, @NotNull XWatchesView watchesView) {
|
||||
watchesView.removeAllWatches();
|
||||
}
|
||||
}
|
||||
|
||||
+5
-9
@@ -16,8 +16,7 @@
|
||||
package com.intellij.xdebugger.impl.frame.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.xdebugger.impl.XDebugSessionImpl;
|
||||
import com.intellij.xdebugger.impl.ui.XDebugSessionTab;
|
||||
import com.intellij.xdebugger.impl.frame.XWatchesView;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -28,16 +27,13 @@ import java.util.List;
|
||||
* @author nik
|
||||
*/
|
||||
public class XRemoveWatchAction extends XWatchesTreeActionBase {
|
||||
protected boolean isEnabled(final AnActionEvent e, @NotNull XDebuggerTree tree) {
|
||||
return !getSelectedNodes(tree, XDebuggerTreeNode.class).isEmpty() && (tree.getSession() instanceof XDebugSessionImpl);
|
||||
protected boolean isEnabled(@NotNull final AnActionEvent e, @NotNull XDebuggerTree tree) {
|
||||
return !getSelectedNodes(tree, XDebuggerTreeNode.class).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void perform(AnActionEvent e, XDebuggerTree tree) {
|
||||
protected void perform(@NotNull AnActionEvent e, @NotNull XDebuggerTree tree, @NotNull XWatchesView watchesView) {
|
||||
List<? extends XDebuggerTreeNode> nodes = getSelectedNodes(tree, XDebuggerTreeNode.class);
|
||||
if (tree.getSession() instanceof XDebugSessionImpl) {
|
||||
XDebugSessionTab tab = ((XDebugSessionImpl)tree.getSession()).getSessionTab();
|
||||
tab.getWatchesView().removeWatches(nodes);
|
||||
}
|
||||
watchesView.removeWatches(nodes);
|
||||
}
|
||||
}
|
||||
|
||||
+8
-5
@@ -17,6 +17,7 @@ package com.intellij.xdebugger.impl.frame.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.xdebugger.impl.frame.XWatchesView;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -45,21 +46,23 @@ public abstract class XWatchesTreeActionBase extends AnAction {
|
||||
|
||||
public void update(final AnActionEvent e) {
|
||||
final XDebuggerTree tree = XDebuggerTree.getTree(e);
|
||||
boolean enabled = tree != null && isEnabled(e, tree);
|
||||
XWatchesView watchesView = e.getData(XWatchesView.DATA_KEY);
|
||||
boolean enabled = tree != null && watchesView != null && isEnabled(e, tree);
|
||||
e.getPresentation().setEnabled(enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final XDebuggerTree tree = XDebuggerTree.getTree(e);
|
||||
if (tree != null) {
|
||||
perform(e, tree);
|
||||
XWatchesView watchesView = e.getData(XWatchesView.DATA_KEY);
|
||||
if (tree != null && watchesView != null) {
|
||||
perform(e, tree, watchesView);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void perform(AnActionEvent e, XDebuggerTree tree);
|
||||
protected abstract void perform(@NotNull AnActionEvent e, @NotNull XDebuggerTree tree, @NotNull XWatchesView watchesView);
|
||||
|
||||
protected boolean isEnabled(AnActionEvent e, @NotNull XDebuggerTree tree) {
|
||||
protected boolean isEnabled(@NotNull AnActionEvent e, @NotNull XDebuggerTree tree) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,12 +41,10 @@ import com.intellij.xdebugger.XDebugSession;
|
||||
import com.intellij.xdebugger.XDebuggerBundle;
|
||||
import com.intellij.xdebugger.impl.XDebugSessionImpl;
|
||||
import com.intellij.xdebugger.impl.actions.XDebuggerActions;
|
||||
import com.intellij.xdebugger.impl.frame.XDebugViewBase;
|
||||
import com.intellij.xdebugger.impl.frame.XFramesView;
|
||||
import com.intellij.xdebugger.impl.frame.XVariablesView;
|
||||
import com.intellij.xdebugger.impl.frame.XWatchesView;
|
||||
import com.intellij.xdebugger.impl.frame.*;
|
||||
import com.intellij.xdebugger.impl.ui.tree.actions.SortValuesToggleAction;
|
||||
import com.intellij.xdebugger.ui.XDebugTabLayouter;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -58,7 +56,7 @@ import java.util.List;
|
||||
* @author spleaner
|
||||
*/
|
||||
public class XDebugSessionTab extends DebuggerSessionTabBase {
|
||||
private XWatchesView myWatchesView;
|
||||
private XWatchesViewImpl myWatchesView;
|
||||
private final List<XDebugViewBase> myViews = new ArrayList<XDebugViewBase>();
|
||||
|
||||
public XDebugSessionTab(@NotNull final Project project, @NotNull final XDebugSessionImpl session, final @Nullable Icon icon,
|
||||
@@ -88,7 +86,7 @@ public class XDebugSessionTab extends DebuggerSessionTabBase {
|
||||
}
|
||||
|
||||
private Content createWatchesContent(final XDebugSession session, final XDebugSessionData sessionData) {
|
||||
myWatchesView = new XWatchesView(session, this, sessionData);
|
||||
myWatchesView = new XWatchesViewImpl(session, this, sessionData);
|
||||
myViews.add(myWatchesView);
|
||||
Content watchesContent = myUi.createContent(DebuggerContentInfo.WATCHES_CONTENT, myWatchesView.getMainPanel(),
|
||||
XDebuggerBundle.message("debugger.session.tab.watches.title"), AllIcons.Debugger.Watches, null);
|
||||
@@ -127,6 +125,16 @@ public class XDebugSessionTab extends DebuggerSessionTabBase {
|
||||
myUi.addContent(createFramesContent(session), 0, PlaceInGrid.left, false);
|
||||
myUi.addContent(createVariablesContent(session), 0, PlaceInGrid.center, false);
|
||||
myUi.addContent(createWatchesContent(session, sessionData), 0, PlaceInGrid.right, false);
|
||||
myUi.getContentManager().addDataProvider(new DataProvider() {
|
||||
@Nullable
|
||||
@Override
|
||||
public Object getData(@NonNls String dataId) {
|
||||
if (XWatchesView.DATA_KEY.is(dataId)) {
|
||||
return myWatchesView;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
XDebugTabLayouter layouter = debugProcess.createTabLayouter();
|
||||
Content consoleContent = layouter.registerConsoleContent(myUi, myConsole);
|
||||
attachNotificationTo(consoleContent);
|
||||
|
||||
@@ -28,10 +28,10 @@ import com.intellij.ui.TreeSpeedSearch;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import com.intellij.xdebugger.XSourcePosition;
|
||||
import com.intellij.xdebugger.XStackFrameAwareSession;
|
||||
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
|
||||
import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink;
|
||||
import com.intellij.xdebugger.impl.actions.XDebuggerActions;
|
||||
import com.intellij.xdebugger.impl.frame.XValueMarkers;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.*;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -73,14 +73,14 @@ public class XDebuggerTree extends DnDAwareTree implements DataProvider, Disposa
|
||||
private final XDebuggerEditorsProvider myEditorsProvider;
|
||||
private XSourcePosition mySourcePosition;
|
||||
private final List<XDebuggerTreeListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
|
||||
private final XStackFrameAwareSession mySession;
|
||||
private final XValueMarkers<?,?> myValueMarkers;
|
||||
|
||||
public XDebuggerTree(final @NotNull XStackFrameAwareSession session,
|
||||
public XDebuggerTree(final @NotNull Project project,
|
||||
final @NotNull XDebuggerEditorsProvider editorsProvider,
|
||||
final @Nullable XSourcePosition sourcePosition,
|
||||
final @NotNull String popupActionGroupId) {
|
||||
mySession = session;
|
||||
myProject = session.getProject();
|
||||
final @NotNull String popupActionGroupId, @Nullable XValueMarkers<?, ?> valueMarkers) {
|
||||
myValueMarkers = valueMarkers;
|
||||
myProject = project;
|
||||
myEditorsProvider = editorsProvider;
|
||||
mySourcePosition = sourcePosition;
|
||||
myTreeModel = new DefaultTreeModel(null);
|
||||
@@ -176,9 +176,9 @@ public class XDebuggerTree extends DnDAwareTree implements DataProvider, Disposa
|
||||
return myProject;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public XStackFrameAwareSession getSession() {
|
||||
return mySession;
|
||||
@Nullable
|
||||
public XValueMarkers<?, ?> getValueMarkers() {
|
||||
return myValueMarkers;
|
||||
}
|
||||
|
||||
public DefaultTreeModel getTreeModel() {
|
||||
|
||||
+5
-4
@@ -20,14 +20,15 @@ import com.intellij.ide.dnd.DnDDragStartBean;
|
||||
import com.intellij.ide.dnd.DnDSource;
|
||||
import com.intellij.ide.dnd.aware.DnDAwareTree;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.ui.ScrollPaneFactory;
|
||||
import com.intellij.ui.treeStructure.Tree;
|
||||
import com.intellij.xdebugger.XDebuggerBundle;
|
||||
import com.intellij.xdebugger.XSourcePosition;
|
||||
import com.intellij.xdebugger.XStackFrameAwareSession;
|
||||
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
|
||||
import com.intellij.xdebugger.impl.frame.XValueMarkers;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -43,10 +44,10 @@ public class XDebuggerTreePanel implements DnDSource {
|
||||
private final XDebuggerTree myTree;
|
||||
private final JPanel myMainPanel;
|
||||
|
||||
public XDebuggerTreePanel(final @NotNull XStackFrameAwareSession session, final @NotNull XDebuggerEditorsProvider editorsProvider,
|
||||
public XDebuggerTreePanel(final @NotNull Project project, final @NotNull XDebuggerEditorsProvider editorsProvider,
|
||||
@NotNull Disposable parentDisposable, final @Nullable XSourcePosition sourcePosition,
|
||||
@NotNull @NonNls final String popupActionGroupId) {
|
||||
myTree = new XDebuggerTree(session, editorsProvider, sourcePosition, popupActionGroupId);
|
||||
@NotNull @NonNls final String popupActionGroupId, @Nullable XValueMarkers<?, ?> markers) {
|
||||
myTree = new XDebuggerTree(project, editorsProvider, sourcePosition, popupActionGroupId, markers);
|
||||
myMainPanel = new JPanel(new BorderLayout());
|
||||
myMainPanel.add(ScrollPaneFactory.createScrollPane(myTree), BorderLayout.CENTER);
|
||||
Disposer.register(parentDisposable, myTree);
|
||||
|
||||
+10
-4
@@ -15,15 +15,16 @@
|
||||
*/
|
||||
package com.intellij.xdebugger.impl.ui.tree;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.xdebugger.XStackFrameAwareSession;
|
||||
import com.intellij.xdebugger.XDebuggerBundle;
|
||||
import com.intellij.xdebugger.XSourcePosition;
|
||||
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
|
||||
import com.intellij.xdebugger.frame.XValue;
|
||||
import com.intellij.xdebugger.impl.actions.XDebuggerActions;
|
||||
import com.intellij.xdebugger.impl.evaluate.quick.XValueHintTreeComponent;
|
||||
import com.intellij.xdebugger.impl.frame.XValueMarkers;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -36,13 +37,18 @@ import javax.swing.*;
|
||||
public class XInspectDialog extends DialogWrapper {
|
||||
private final XValueHintTreeComponent myTreePanel;
|
||||
|
||||
public XInspectDialog(XStackFrameAwareSession session, XDebuggerEditorsProvider editorsProvider, XSourcePosition sourcePosition, @NotNull String name, @NotNull XValue value) {
|
||||
super(session.getProject(), false);
|
||||
public XInspectDialog(@NotNull Project project,
|
||||
XDebuggerEditorsProvider editorsProvider,
|
||||
XSourcePosition sourcePosition,
|
||||
@NotNull String name,
|
||||
@NotNull XValue value,
|
||||
XValueMarkers<?, ?> markers) {
|
||||
super(project, false);
|
||||
|
||||
setTitle(XDebuggerBundle.message("inspect.value.dialog.title", name));
|
||||
setModal(false);
|
||||
|
||||
XDebuggerTree tree = new XDebuggerTree(session, editorsProvider, sourcePosition, XDebuggerActions.INSPECT_TREE_POPUP_GROUP);
|
||||
XDebuggerTree tree = new XDebuggerTree(project, editorsProvider, sourcePosition, XDebuggerActions.INSPECT_TREE_POPUP_GROUP, markers);
|
||||
myTreePanel = new XValueHintTreeComponent(null, tree, Pair.create(value, name));
|
||||
init();
|
||||
}
|
||||
|
||||
+7
-12
@@ -16,9 +16,7 @@
|
||||
package com.intellij.xdebugger.impl.ui.tree.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.xdebugger.XStackFrameAwareSession;
|
||||
import com.intellij.xdebugger.impl.XDebugSessionImpl;
|
||||
import com.intellij.xdebugger.impl.ui.XDebugSessionTab;
|
||||
import com.intellij.xdebugger.impl.frame.XWatchesView;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -27,19 +25,16 @@ import org.jetbrains.annotations.NotNull;
|
||||
*/
|
||||
public class XAddToWatchesAction extends XDebuggerTreeActionBase {
|
||||
@Override
|
||||
protected boolean isEnabled(final XValueNodeImpl node) {
|
||||
return super.isEnabled(node) && node.getValueContainer().getEvaluationExpression() != null && (node.getTree().getSession() instanceof XDebugSessionImpl);
|
||||
protected boolean isEnabled(@NotNull final XValueNodeImpl node, @NotNull AnActionEvent e) {
|
||||
return super.isEnabled(node, e) && node.getValueContainer().getEvaluationExpression() != null && e.getData(XWatchesView.DATA_KEY) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void perform(final XValueNodeImpl node, @NotNull final String nodeName, final AnActionEvent e) {
|
||||
XStackFrameAwareSession session = node.getTree().getSession();
|
||||
if (session instanceof XDebugSessionImpl) {
|
||||
XDebugSessionTab sessionTab = ((XDebugSessionImpl)session).getSessionTab();
|
||||
String expression = node.getValueContainer().getEvaluationExpression();
|
||||
if (expression != null) {
|
||||
sessionTab.getWatchesView().addWatchExpression(expression, -1, true);
|
||||
}
|
||||
XWatchesView watchesView = e.getData(XWatchesView.DATA_KEY);
|
||||
String expression = node.getValueContainer().getEvaluationExpression();
|
||||
if (watchesView != null && expression != null) {
|
||||
watchesView.addWatchExpression(expression, -1, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -46,10 +46,10 @@ public abstract class XDebuggerTreeActionBase extends AnAction {
|
||||
@Override
|
||||
public void update(final AnActionEvent e) {
|
||||
XValueNodeImpl node = getSelectedNode(e.getDataContext());
|
||||
e.getPresentation().setEnabled(node != null && isEnabled(node));
|
||||
e.getPresentation().setEnabled(node != null && isEnabled(node, e));
|
||||
}
|
||||
|
||||
protected boolean isEnabled(final XValueNodeImpl node) {
|
||||
protected boolean isEnabled(final @NotNull XValueNodeImpl node, @NotNull AnActionEvent e) {
|
||||
return node.getName() != null;
|
||||
}
|
||||
|
||||
|
||||
+26
-24
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.xdebugger.impl.ui.tree.actions;
|
||||
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
@@ -26,8 +27,8 @@ import com.intellij.util.Alarm;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.concurrency.Semaphore;
|
||||
import com.intellij.xdebugger.XDebuggerBundle;
|
||||
import com.intellij.xdebugger.XStackFrameAwareSession;
|
||||
import com.intellij.xdebugger.frame.XFullValueEvaluator;
|
||||
import com.intellij.xdebugger.impl.XDebugSessionImpl;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.WatchMessageNode;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
|
||||
@@ -83,7 +84,7 @@ public abstract class XFetchValueActionBase extends AnAction {
|
||||
valueCollector.add(StringUtil.notNullize(valueNode.getRawValue()));
|
||||
}
|
||||
else {
|
||||
startFetchingValue(fullValueEvaluator, new CopyValueEvaluationCallback(valueNode.getTree().getSession(), valueCollector));
|
||||
startFetchingValue(fullValueEvaluator, new CopyValueEvaluationCallback(valueNode, valueCollector));
|
||||
}
|
||||
}
|
||||
else if (node instanceof WatchMessageNode) {
|
||||
@@ -133,21 +134,21 @@ public abstract class XFetchValueActionBase extends AnAction {
|
||||
}
|
||||
|
||||
private static final class CopyValueEvaluationCallback implements XFullValueEvaluator.XFullValueEvaluationCallback {
|
||||
private final XStackFrameAwareSession session;
|
||||
private final XValueNodeImpl myNode;
|
||||
|
||||
private final int valueIndex;
|
||||
private final ValueCollector valueCollector;
|
||||
private final int myValueIndex;
|
||||
private final ValueCollector myValueCollector;
|
||||
|
||||
private volatile boolean evaluated;
|
||||
private volatile boolean canceled;
|
||||
private final Semaphore semaphore;
|
||||
private volatile boolean myEvaluated;
|
||||
private volatile boolean myCanceled;
|
||||
private final Semaphore mySemaphore;
|
||||
|
||||
public CopyValueEvaluationCallback(XStackFrameAwareSession session, ValueCollector valueCollector) {
|
||||
this.session = session;
|
||||
this.valueCollector = valueCollector;
|
||||
valueIndex = valueCollector.acquire();
|
||||
semaphore = new Semaphore();
|
||||
semaphore.down();
|
||||
public CopyValueEvaluationCallback(@NotNull XValueNodeImpl node, ValueCollector valueCollector) {
|
||||
myNode = node;
|
||||
myValueCollector = valueCollector;
|
||||
myValueIndex = valueCollector.acquire();
|
||||
mySemaphore = new Semaphore();
|
||||
mySemaphore.down();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -163,7 +164,8 @@ public abstract class XFetchValueActionBase extends AnAction {
|
||||
@Override
|
||||
public void errorOccurred(@NotNull String errorMessage) {
|
||||
try {
|
||||
session.reportError(XDebuggerBundle.message("load.value.task.error", errorMessage));
|
||||
String message = XDebuggerBundle.message("load.value.task.error", errorMessage);
|
||||
XDebugSessionImpl.NOTIFICATION_GROUP.createNotification(message, NotificationType.ERROR).notify(myNode.getTree().getProject());
|
||||
}
|
||||
finally {
|
||||
evaluationComplete(errorMessage);
|
||||
@@ -172,31 +174,31 @@ public abstract class XFetchValueActionBase extends AnAction {
|
||||
|
||||
private void evaluationComplete(String value) {
|
||||
try {
|
||||
evaluated = true;
|
||||
semaphore.up();
|
||||
myEvaluated = true;
|
||||
mySemaphore.up();
|
||||
}
|
||||
finally {
|
||||
valueCollector.evaluationComplete(valueIndex, value, session.getProject());
|
||||
myValueCollector.evaluationComplete(myValueIndex, value, myNode.getTree().getProject());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isObsolete() {
|
||||
return canceled;
|
||||
return myCanceled;
|
||||
}
|
||||
|
||||
public void showProgress() {
|
||||
if (evaluated || session.isStopped()) return;
|
||||
if (myEvaluated || myNode.isObsolete()) return;
|
||||
|
||||
new Task.Backgroundable(session.getProject(), XDebuggerBundle.message("load.value.task.text")) {
|
||||
new Task.Backgroundable(myNode.getTree().getProject(), XDebuggerBundle.message("load.value.task.text")) {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
indicator.setIndeterminate(true);
|
||||
int i = 0;
|
||||
while (!canceled && !evaluated) {
|
||||
while (!myCanceled && !myEvaluated) {
|
||||
indicator.checkCanceled();
|
||||
indicator.setFraction(((i++) % 100) * 0.01);
|
||||
semaphore.waitFor(300);
|
||||
mySemaphore.waitFor(300);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,7 +209,7 @@ public abstract class XFetchValueActionBase extends AnAction {
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
canceled = true;
|
||||
myCanceled = true;
|
||||
}
|
||||
}.queue();
|
||||
}
|
||||
|
||||
+2
-1
@@ -30,7 +30,8 @@ public class XInspectAction extends XDebuggerTreeActionBase {
|
||||
protected void perform(XValueNodeImpl node, @NotNull final String nodeName, AnActionEvent e) {
|
||||
XDebuggerTree tree = node.getTree();
|
||||
XValue value = node.getValueContainer();
|
||||
XInspectDialog dialog = new XInspectDialog(tree.getSession(), tree.getEditorsProvider(), tree.getSourcePosition(), nodeName, value);
|
||||
XInspectDialog dialog = new XInspectDialog(tree.getProject(), tree.getEditorsProvider(), tree.getSourcePosition(), nodeName, value,
|
||||
tree.getValueMarkers());
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -15,9 +15,11 @@
|
||||
*/
|
||||
package com.intellij.xdebugger.impl.ui.tree.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.xdebugger.frame.XNavigatable;
|
||||
import com.intellij.xdebugger.frame.XValue;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
@@ -29,7 +31,7 @@ public class XJumpToSourceAction extends XJumpToSourceActionBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled(XValueNodeImpl node) {
|
||||
return super.isEnabled(node) && node.getValueContainer().canNavigateToSource();
|
||||
protected boolean isEnabled(@NotNull XValueNodeImpl node, @NotNull AnActionEvent e) {
|
||||
return super.isEnabled(node, e) && node.getValueContainer().canNavigateToSource();
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -15,9 +15,11 @@
|
||||
*/
|
||||
package com.intellij.xdebugger.impl.ui.tree.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.xdebugger.frame.XNavigatable;
|
||||
import com.intellij.xdebugger.frame.XValue;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
@@ -29,7 +31,7 @@ public class XJumpToTypeSourceAction extends XJumpToSourceActionBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled(XValueNodeImpl node) {
|
||||
return super.isEnabled(node) && node.getValueContainer().canNavigateToTypeSource();
|
||||
protected boolean isEnabled(@NotNull XValueNodeImpl node, @NotNull AnActionEvent e) {
|
||||
return super.isEnabled(node, e) && node.getValueContainer().canNavigateToTypeSource();
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -42,8 +42,8 @@ public class XSetValueAction extends XDebuggerTreeActionBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled(XValueNodeImpl node) {
|
||||
return super.isEnabled(node) && node.getValueContainer().getModifier() != null;
|
||||
protected boolean isEnabled(@NotNull XValueNodeImpl node, @NotNull AnActionEvent e) {
|
||||
return super.isEnabled(node, e) && node.getValueContainer().getModifier() != null;
|
||||
}
|
||||
|
||||
protected void perform(final XValueNodeImpl node, @NotNull final String nodeName, final AnActionEvent e) {
|
||||
|
||||
+11
-2
@@ -15,9 +15,11 @@
|
||||
*/
|
||||
package com.intellij.xdebugger.impl.ui.tree.nodes;
|
||||
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
|
||||
import com.intellij.xdebugger.frame.XValue;
|
||||
import com.intellij.xdebugger.impl.frame.WatchInplaceEditor;
|
||||
import com.intellij.xdebugger.impl.frame.XWatchesView;
|
||||
import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -33,12 +35,19 @@ import java.util.List;
|
||||
* @author nik
|
||||
*/
|
||||
public class WatchesRootNode extends XDebuggerTreeNode {
|
||||
private final XDebugSession mySession;
|
||||
private final XWatchesView myWatchesView;
|
||||
private List<WatchNode> myChildren;
|
||||
private List<XDebuggerTreeNode> myLoadedChildren;
|
||||
private XDebuggerEvaluator myCurrentEvaluator;
|
||||
|
||||
public WatchesRootNode(final XDebuggerTree tree, String[] watchExpressions) {
|
||||
public WatchesRootNode(final @NotNull XDebuggerTree tree,
|
||||
@NotNull XDebugSession session,
|
||||
@NotNull XWatchesView watchesView,
|
||||
@NotNull String[] watchExpressions) {
|
||||
super(tree, null, false);
|
||||
mySession = session;
|
||||
myWatchesView = watchesView;
|
||||
myChildren = new ArrayList<WatchNode>();
|
||||
for (String watchExpression : watchExpressions) {
|
||||
myChildren.add(WatchMessageNode.createMessageNode(tree, this, watchExpression));
|
||||
@@ -177,7 +186,7 @@ public class WatchesRootNode extends XDebuggerTreeNode {
|
||||
myChildren.set(index, messageNode);
|
||||
fireNodeStructureChanged(messageNode);
|
||||
}
|
||||
WatchInplaceEditor editor = new WatchInplaceEditor(this, messageNode, "watch", node);
|
||||
WatchInplaceEditor editor = new WatchInplaceEditor(this, mySession, myWatchesView, messageNode, "watch", node);
|
||||
editor.show();
|
||||
}
|
||||
|
||||
|
||||
+1
-4
@@ -23,7 +23,6 @@ import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.util.NotNullFunction;
|
||||
import com.intellij.xdebugger.frame.*;
|
||||
import com.intellij.xdebugger.frame.presentation.XValuePresentation;
|
||||
import com.intellij.xdebugger.impl.XDebugSessionImpl;
|
||||
import com.intellij.xdebugger.impl.frame.XValueMarkers;
|
||||
import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
|
||||
import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants;
|
||||
@@ -133,15 +132,13 @@ public class XValueNodeImpl extends XValueContainerNode<XValue> implements XValu
|
||||
|
||||
private void updateText() {
|
||||
myText.clear();
|
||||
if (myTree.getSession() instanceof XDebugSessionImpl) {
|
||||
XValueMarkers<?,?> markers = ((XDebugSessionImpl)myTree.getSession()).getValueMarkers();
|
||||
XValueMarkers<?, ?> markers = myTree.getValueMarkers();
|
||||
if (markers != null) {
|
||||
ValueMarkup markup = markers.getMarkup(myValueContainer);
|
||||
if (markup != null) {
|
||||
myText.append("[" + markup.getText() + "] ", new SimpleTextAttributes(SimpleTextAttributes.STYLE_BOLD, markup.getColor()));
|
||||
}
|
||||
}
|
||||
}
|
||||
appendName();
|
||||
buildText(myValuePresentation, myText);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user