mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
enhanced object markup in debugger, initial version
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
package com.intellij.debugger.actions;
|
||||
|
||||
import com.intellij.debugger.engine.DebugProcessImpl;
|
||||
import com.intellij.debugger.engine.events.DebuggerContextCommandImpl;
|
||||
import com.intellij.debugger.impl.DebuggerContextImpl;
|
||||
import com.intellij.debugger.impl.DebuggerSession;
|
||||
import com.intellij.debugger.ui.impl.watch.DebuggerTree;
|
||||
@@ -11,12 +13,25 @@ import com.intellij.debugger.ui.tree.ValueMarkup;
|
||||
import com.intellij.idea.ActionsBundle;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.sun.jdi.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/*
|
||||
* Class SetValueAction
|
||||
* @author Jeka
|
||||
*/
|
||||
public class MarkObjectAction extends DebuggerAction {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.actions.MarkObjectAction");
|
||||
private final String MARK_TEXT = ActionsBundle.message("action.Debugger.MarkObject.text");
|
||||
private final String UNMARK_TEXT = ActionsBundle.message("action.Debugger.MarkObject.unmark.text");
|
||||
|
||||
@@ -35,32 +50,160 @@ public class MarkObjectAction extends DebuggerAction {
|
||||
|
||||
final ValueDescriptorImpl valueDescriptor = ((ValueDescriptorImpl)descriptor);
|
||||
final DebuggerContextImpl debuggerContext = tree.getDebuggerContext();
|
||||
final ValueMarkup markup = valueDescriptor.getMarkup(debuggerContext.getDebugProcess());
|
||||
try {
|
||||
if (markup != null) {
|
||||
valueDescriptor.setMarkup(debuggerContext.getDebugProcess(), null);
|
||||
final DebugProcessImpl debugProcess = debuggerContext.getDebugProcess();
|
||||
final ValueMarkup markup = valueDescriptor.getMarkup(debugProcess);
|
||||
debugProcess.getManagerThread().invoke(new DebuggerContextCommandImpl(debuggerContext) {
|
||||
public Priority getPriority() {
|
||||
return Priority.HIGH;
|
||||
}
|
||||
else {
|
||||
final ValueMarkup valueMarkup = ObjectMarkupPropertiesDialog.chooseMarkup(valueDescriptor.getName());
|
||||
if (valueMarkup != null) {
|
||||
valueDescriptor.setMarkup(debuggerContext.getDebugProcess(), valueMarkup);
|
||||
public void threadAction() {
|
||||
boolean sessionRefreshNeeded = true;
|
||||
try {
|
||||
if (markup != null) {
|
||||
valueDescriptor.setMarkup(debugProcess, null);
|
||||
}
|
||||
else {
|
||||
final Value value = valueDescriptor.getValue();
|
||||
final Map<Long, ValueMarkup> additionalMarkup = suggestMarkup(debugProcess, value);
|
||||
ValueMarkup valueMarkup = null;
|
||||
if (value instanceof ObjectReference) {
|
||||
valueMarkup = additionalMarkup.get(((ObjectReference)value).uniqueID());
|
||||
}
|
||||
if (valueMarkup == null) {
|
||||
valueMarkup = new ValueMarkup(valueDescriptor.getName(), Color.RED);
|
||||
}
|
||||
final Ref<Pair<ValueMarkup,Boolean>> result = new Ref<Pair<ValueMarkup, Boolean>>(null);
|
||||
try {
|
||||
final ValueMarkup _suggestion = valueMarkup;
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
result.set(ObjectMarkupPropertiesDialog.chooseMarkup(_suggestion, additionalMarkup));
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (InterruptedException ignored) {
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
final Pair<ValueMarkup, Boolean> pair = result.get();
|
||||
if (pair != null) {
|
||||
valueDescriptor.setMarkup(debugProcess, pair.first);
|
||||
if (pair.second) {
|
||||
final Map<Long, ValueMarkup> map = NodeDescriptorImpl.getMarkupMap(debugProcess);
|
||||
if (map != null) {
|
||||
for (Map.Entry<Long,ValueMarkup> entry : additionalMarkup.entrySet()) {
|
||||
final Long key = entry.getKey();
|
||||
if (!map.containsKey(key)) {
|
||||
map.put(key, entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
sessionRefreshNeeded = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return;
|
||||
finally {
|
||||
final boolean _sessionRefreshNeeded = sessionRefreshNeeded;
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
tree.restoreState(node);
|
||||
node.labelChanged();
|
||||
if (_sessionRefreshNeeded) {
|
||||
final DebuggerSession session = debuggerContext.getDebuggerSession();
|
||||
if (session != null) {
|
||||
session.refresh(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
tree.restoreState(node);
|
||||
node.labelChanged();
|
||||
}
|
||||
|
||||
final DebuggerSession session = debuggerContext.getDebuggerSession();
|
||||
if (session != null) {
|
||||
session.refresh(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static Map<Long, ValueMarkup> suggestMarkup(DebugProcessImpl debugProcess, Value value) {
|
||||
if (!(value instanceof ObjectReference)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
final ObjectReference objRef = (ObjectReference)value;
|
||||
if (objRef instanceof ArrayReference || objRef instanceof ClassObjectReference || objRef instanceof ThreadReference || objRef instanceof ThreadGroupReference || objRef instanceof ClassLoaderReference) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
final Map<Long, ValueMarkup> result = new HashMap<Long, ValueMarkup>();
|
||||
if (debugProcess.getVirtualMachineProxy().canGetInstanceInfo()) {
|
||||
for (ObjectReference ref : getReferringObjects(objRef)) {
|
||||
if (!(ref instanceof ClassObjectReference)) {
|
||||
// consider references from statisc fields only
|
||||
continue;
|
||||
}
|
||||
final ReferenceType refType = ((ClassObjectReference)ref).reflectedType();
|
||||
if (!refType.isAbstract()) {
|
||||
continue;
|
||||
}
|
||||
for (Field field : refType.fields()) {
|
||||
if (!(field.isStatic() && field.isFinal())) {
|
||||
continue;
|
||||
}
|
||||
final Value fieldValue = refType.getValue(field);
|
||||
if (!(fieldValue instanceof ObjectReference)) {
|
||||
continue;
|
||||
}
|
||||
final long id = ((ObjectReference)fieldValue).uniqueID();
|
||||
final ValueMarkup markup = result.get(id);
|
||||
|
||||
final String fieldName = field.name();
|
||||
final Color autoMarkupColor = ValueMarkup.getAutoMarkupColor();
|
||||
if (markup == null) {
|
||||
result.put(id, new ValueMarkup(fieldName, autoMarkupColor, createMarkupTooltipText(null, refType, fieldName)));
|
||||
}
|
||||
else {
|
||||
final String currentText = markup.getText();
|
||||
if (!currentText.contains(fieldName)) {
|
||||
final String currentTooltip = markup.getToolTipText();
|
||||
final String tooltip = createMarkupTooltipText(currentTooltip, refType, fieldName);
|
||||
result.put(id, new ValueMarkup(currentText + ", " + fieldName, autoMarkupColor, tooltip));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<ObjectReference> getReferringObjects(ObjectReference value) {
|
||||
// invoke the following method using Reflection in order to remain compilable on jdk 1.5
|
||||
// java.util.List<com.sun.jdi.ObjectReference> referringObjects(long l);
|
||||
try {
|
||||
final java.lang.reflect.Method apiMethod = ObjectReference.class.getMethod("referringObjects", long.class);
|
||||
return (List<ObjectReference>)apiMethod.invoke(value, ValueMarkup.AUTO_MARKUP_REFERRING_OBJECTS_LIMIT);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
LOG.error(e); // should not happen
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
catch (NoSuchMethodException ignored) {
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private static String createMarkupTooltipText(String prefix, ReferenceType refType, String fieldName) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
if (prefix == null) {
|
||||
builder.append("Value referenced from:");
|
||||
}
|
||||
else {
|
||||
builder.append(prefix);
|
||||
}
|
||||
return builder.append("<br><b>").append(refType.name()).append(".").append(fieldName).append("</b>").toString();
|
||||
}
|
||||
|
||||
|
||||
public void update(AnActionEvent e) {
|
||||
boolean enable = false;
|
||||
String text = MARK_TEXT;
|
||||
@@ -79,4 +222,4 @@ public class MarkObjectAction extends DebuggerAction {
|
||||
presentation.setVisible(enable);
|
||||
presentation.setText(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+43
-19
@@ -7,11 +7,14 @@ package com.intellij.debugger.actions;
|
||||
import com.intellij.debugger.ui.tree.ValueMarkup;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.FixedSizeButton;
|
||||
import com.intellij.openapi.ui.ex.MultiLineLabel;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.ui.ColorChooser;
|
||||
import com.intellij.ui.DocumentAdapter;
|
||||
import com.intellij.ui.SimpleColoredComponent;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.util.Alarm;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -19,6 +22,9 @@ import javax.swing.event.DocumentEvent;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
@@ -26,27 +32,35 @@ import java.awt.event.ActionListener;
|
||||
*/
|
||||
public class ObjectMarkupPropertiesDialog extends DialogWrapper {
|
||||
private final JTextField myTextMarkupField;
|
||||
private final JCheckBox myCbMarkAdditionalFields;
|
||||
private final SimpleColoredComponent myColorSample;
|
||||
private SimpleTextAttributes myAttributes;
|
||||
private final Alarm myUpdateAlarm;
|
||||
private static final int UPDATE_DELAY = 200;
|
||||
private final Map<Long, ValueMarkup> myAdditional;
|
||||
private static Boolean ourMarkCbSavedState;
|
||||
|
||||
public ObjectMarkupPropertiesDialog(final String suggestedName) {
|
||||
public ObjectMarkupPropertiesDialog(@NotNull final ValueMarkup suggestion, @NotNull Map<Long, ValueMarkup> additional) {
|
||||
super(true);
|
||||
myAdditional = additional;
|
||||
setTitle("Select object label");
|
||||
setModal(true);
|
||||
myTextMarkupField = new JTextField(30);
|
||||
myCbMarkAdditionalFields = new JCheckBox("Mark values referenced from constant fields", ourMarkCbSavedState == null? additional.size() > 0 : ourMarkCbSavedState);
|
||||
myCbMarkAdditionalFields.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
ourMarkCbSavedState = myCbMarkAdditionalFields.isSelected();
|
||||
}
|
||||
});
|
||||
myColorSample = new SimpleColoredComponent();
|
||||
myAttributes = createAttributes(Color.RED);
|
||||
myUpdateAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
|
||||
if (suggestedName != null) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
myTextMarkupField.setText(suggestedName.trim());
|
||||
updateLabelSample(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
myAttributes = createAttributes(suggestion.getColor());
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
myTextMarkupField.setText(suggestion.getText().trim());
|
||||
updateLabelSample(0);
|
||||
}
|
||||
});
|
||||
init();
|
||||
}
|
||||
|
||||
@@ -62,20 +76,30 @@ public class ObjectMarkupPropertiesDialog extends DialogWrapper {
|
||||
|
||||
@Nullable
|
||||
protected JComponent createCenterPanel() {
|
||||
|
||||
final JPanel mainPanel = new JPanel(new GridBagLayout());
|
||||
mainPanel.add(new JLabel("Label:"), new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
|
||||
mainPanel.add(new JLabel("Label:"), new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
|
||||
mainPanel.add(myTextMarkupField, new GridBagConstraints(1, GridBagConstraints.RELATIVE, 2, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
|
||||
|
||||
|
||||
final JPanel samplePanel = new JPanel(new BorderLayout());
|
||||
samplePanel.add(myColorSample, BorderLayout.CENTER);
|
||||
samplePanel.setBorder(BorderFactory.createEtchedBorder());
|
||||
final FixedSizeButton chooseColorButton = new FixedSizeButton(samplePanel);
|
||||
|
||||
mainPanel.add(new JLabel("Preview: "), new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 0.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 0, 0, 0), 0, 0));
|
||||
mainPanel.add(samplePanel, new GridBagConstraints(1, GridBagConstraints.RELATIVE, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 0, 0), 0, 0));
|
||||
mainPanel.add(chooseColorButton, new GridBagConstraints(2, GridBagConstraints.RELATIVE, 1, 1, 0.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 0, 0, 0), 0, 0));
|
||||
final boolean shouldShowCheckbox = myAdditional.size() > 0;
|
||||
double weighty = shouldShowCheckbox? 0.0 : 1.0;
|
||||
mainPanel.add(new JLabel("Preview: "), new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 0.0, weighty, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 0, 0, 0), 0, 0));
|
||||
mainPanel.add(samplePanel, new GridBagConstraints(1, GridBagConstraints.RELATIVE, 1, 1, 1.0, weighty, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 0, 0, 0), 0, 0));
|
||||
mainPanel.add(chooseColorButton, new GridBagConstraints(2, GridBagConstraints.RELATIVE, 1, 1, 0.0, weighty, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(5, 0, 0, 0), 0, 0));
|
||||
|
||||
if (shouldShowCheckbox) {
|
||||
final JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.add(new MultiLineLabel(
|
||||
"The value is referenced by a constant field of an abstract class.\nIDEA could mark values referenced from this class with the names of referencing fields."
|
||||
), BorderLayout.CENTER);
|
||||
panel.add(myCbMarkAdditionalFields, BorderLayout.SOUTH);
|
||||
|
||||
mainPanel.add(panel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 3, 1, 0.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10, 0, 0, 0), 0, 0));
|
||||
}
|
||||
|
||||
myTextMarkupField.getDocument().addDocumentListener(new DocumentAdapter() {
|
||||
protected void textChanged(final DocumentEvent e) {
|
||||
@@ -103,13 +127,13 @@ public class ObjectMarkupPropertiesDialog extends DialogWrapper {
|
||||
}, updateDelay);
|
||||
}
|
||||
|
||||
public static ValueMarkup chooseMarkup(final String suggestedName) {
|
||||
final ObjectMarkupPropertiesDialog dialog = new ObjectMarkupPropertiesDialog(suggestedName);
|
||||
public static Pair<ValueMarkup,Boolean> chooseMarkup(ValueMarkup suggestion, Map<Long, ValueMarkup> additionalMarkup) {
|
||||
final ObjectMarkupPropertiesDialog dialog = new ObjectMarkupPropertiesDialog(suggestion, additionalMarkup);
|
||||
dialog.show();
|
||||
if (dialog.isOK()) {
|
||||
final String text = dialog.myTextMarkupField.getText().trim();
|
||||
final Color color = dialog.myAttributes.getFgColor();
|
||||
return text.length() > 0? new ValueMarkup(text, color) : null;
|
||||
return text.length() > 0? new Pair<ValueMarkup, Boolean>(new ValueMarkup(text, color, suggestion.getToolTipText()), dialog.myCbMarkAdditionalFields.isSelected()) : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ public class DebuggerTreeBase extends DnDAwareTree implements Disposable {
|
||||
return minChar;
|
||||
}
|
||||
|
||||
private JComponent createTipContent(String tipText) {
|
||||
private JComponent createTipContent(String tipText, DebuggerTreeNodeImpl node) {
|
||||
final JToolTip tooltip = new JToolTip();
|
||||
|
||||
if (tipText == null) {
|
||||
@@ -98,12 +98,21 @@ public class DebuggerTreeBase extends DnDAwareTree implements Disposable {
|
||||
//noinspection HardCodedStringLiteral
|
||||
final StringBuffer tipBuilder = new StringBuffer();
|
||||
try {
|
||||
final StringTokenizer tokenizer = new StringTokenizer(tipText, "\n");
|
||||
final String markupText = node.getMarkupTooltipText();
|
||||
if (markupText != null) {
|
||||
tipBuilder.append(markupText);
|
||||
}
|
||||
|
||||
while (tokenizer.hasMoreElements()) {
|
||||
final String each = tokenizer.nextElement();
|
||||
tipBuilder.append(JDOMUtil.legalizeText(each));
|
||||
tipBuilder.append("<br>");
|
||||
if (tipText.length() > 0) {
|
||||
tipBuilder.append("<br><br>").append("Value=");
|
||||
|
||||
final StringTokenizer tokenizer = new StringTokenizer(tipText, "\n");
|
||||
|
||||
while (tokenizer.hasMoreElements()) {
|
||||
final String each = tokenizer.nextElement();
|
||||
tipBuilder.append(JDOMUtil.legalizeText(each));
|
||||
tipBuilder.append("<br>");
|
||||
}
|
||||
}
|
||||
|
||||
tooltip.setTipText(UIUtil.toHtml(tipBuilder.toString(), 0));
|
||||
@@ -162,7 +171,7 @@ public class DebuggerTreeBase extends DnDAwareTree implements Disposable {
|
||||
return null;
|
||||
}
|
||||
|
||||
final JComponent tipContent = createTipContent(toolTipText);
|
||||
final JComponent tipContent = createTipContent(toolTipText, node);
|
||||
final JScrollPane scrollPane = new JScrollPane(tipContent);
|
||||
scrollPane.setBorder(null);
|
||||
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||
@@ -260,7 +269,7 @@ public class DebuggerTreeBase extends DnDAwareTree implements Disposable {
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return node.getMarkupTooltipText() != null? "" : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -12,8 +12,8 @@ import com.intellij.ui.ColoredTreeCellRenderer;
|
||||
import com.intellij.ui.SimpleColoredText;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.util.Icons;
|
||||
import com.intellij.xdebugger.ui.DebuggerIcons;
|
||||
import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants;
|
||||
import com.intellij.xdebugger.ui.DebuggerIcons;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -125,7 +125,7 @@ public class DebuggerTreeRenderer extends ColoredTreeCellRenderer {
|
||||
if (descriptor instanceof ValueDescriptor) {
|
||||
final ValueMarkup markup = ((ValueDescriptor)descriptor).getMarkup(debuggerContext.getDebugProcess());
|
||||
if (markup != null) {
|
||||
descriptorText.append(markup.getText(), new SimpleTextAttributes(SimpleTextAttributes.STYLE_BOLD, markup.getColor()));
|
||||
descriptorText.append("[" + markup.getText() + "] ", new SimpleTextAttributes(SimpleTextAttributes.STYLE_BOLD, markup.getColor()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+18
-1
@@ -12,6 +12,8 @@ import com.intellij.debugger.ui.impl.tree.TreeBuilder;
|
||||
import com.intellij.debugger.ui.impl.tree.TreeBuilderNode;
|
||||
import com.intellij.debugger.ui.tree.DebuggerTreeNode;
|
||||
import com.intellij.debugger.ui.tree.NodeDescriptor;
|
||||
import com.intellij.debugger.ui.tree.ValueDescriptor;
|
||||
import com.intellij.debugger.ui.tree.ValueMarkup;
|
||||
import com.intellij.debugger.ui.tree.render.DescriptorLabelListener;
|
||||
import com.intellij.debugger.ui.tree.render.NodeRenderer;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
@@ -19,6 +21,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.ui.SimpleColoredText;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Map;
|
||||
@@ -26,6 +29,7 @@ import java.util.Map;
|
||||
public class DebuggerTreeNodeImpl extends TreeBuilderNode implements DebuggerTreeNode{
|
||||
private Icon myIcon;
|
||||
private SimpleColoredText myText;
|
||||
private String myMarkupTooltipText;
|
||||
private final DebuggerTree myTree;
|
||||
private final Map myProperties = new HashMap();
|
||||
|
||||
@@ -66,7 +70,15 @@ public class DebuggerTreeNodeImpl extends TreeBuilderNode implements DebuggerTre
|
||||
private void updateCaches() {
|
||||
final NodeDescriptorImpl descriptor = getDescriptor();
|
||||
myIcon = DebuggerTreeRenderer.getDescriptorIcon(descriptor);
|
||||
myText = DebuggerTreeRenderer.getDescriptorText(getTree().getDebuggerContext(), descriptor, false);
|
||||
final DebuggerContextImpl context = getTree().getDebuggerContext();
|
||||
myText = DebuggerTreeRenderer.getDescriptorText(context, descriptor, false);
|
||||
if (descriptor instanceof ValueDescriptor) {
|
||||
final ValueMarkup markup = ((ValueDescriptor)descriptor).getMarkup(context.getDebugProcess());
|
||||
myMarkupTooltipText = markup != null? markup.getToolTipText() : null;
|
||||
}
|
||||
else {
|
||||
myMarkupTooltipText = null;
|
||||
}
|
||||
}
|
||||
|
||||
public Icon getIcon() {
|
||||
@@ -77,6 +89,11 @@ public class DebuggerTreeNodeImpl extends TreeBuilderNode implements DebuggerTre
|
||||
return myText;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getMarkupTooltipText() {
|
||||
return myMarkupTooltipText;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
removeAllChildren();
|
||||
myIcon = null;
|
||||
|
||||
@@ -139,7 +139,7 @@ public abstract class NodeDescriptorImpl implements NodeDescriptor {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected static Map<Long, ValueMarkup> getMarkupMap(final DebugProcess process) {
|
||||
public static Map<Long, ValueMarkup> getMarkupMap(final DebugProcess process) {
|
||||
if (process == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -407,7 +407,12 @@ public abstract class ValueDescriptorImpl extends NodeDescriptorImpl implements
|
||||
final Map<Long, ValueMarkup> map = getMarkupMap(debugProcess);
|
||||
if (map != null) {
|
||||
final long id = ((ObjectReference)value).uniqueID();
|
||||
map.put(id, markup);
|
||||
if (markup != null) {
|
||||
map.put(id, markup);
|
||||
}
|
||||
else {
|
||||
map.remove(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
*/
|
||||
package com.intellij.debugger.ui.tree;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
@@ -13,12 +17,21 @@ import java.awt.*;
|
||||
* Date: Jan 27, 2007
|
||||
*/
|
||||
public class ValueMarkup {
|
||||
public static final long AUTO_MARKUP_REFERRING_OBJECTS_LIMIT = 100L; // todo: some reasonable limit
|
||||
|
||||
private final String myText;
|
||||
private final Color myColor;
|
||||
@Nullable
|
||||
private final String myToolTipText;
|
||||
|
||||
public ValueMarkup(final String text, final Color color) {
|
||||
myText = "[" + text + "] ";
|
||||
this(text, color, null);
|
||||
}
|
||||
|
||||
public ValueMarkup(final String text, final Color color, String toolTipText) {
|
||||
myText = text;
|
||||
myColor = color;
|
||||
myToolTipText = toolTipText;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -29,4 +42,15 @@ public class ValueMarkup {
|
||||
public Color getColor() {
|
||||
return myColor;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getToolTipText() {
|
||||
return myToolTipText;
|
||||
}
|
||||
|
||||
public static Color getAutoMarkupColor() {
|
||||
final EditorColorsManager manager = EditorColorsManager.getInstance();
|
||||
final TextAttributes textAttributes = manager.getGlobalScheme().getAttributes(HighlightInfoType.STATIC_FIELD.getAttributesKey());
|
||||
return textAttributes.getForegroundColor();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user