diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/MarkObjectAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/MarkObjectAction.java index 50766230db76..6f93f6601978 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/MarkObjectAction.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/MarkObjectAction.java @@ -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 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> result = new Ref>(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 pair = result.get(); + if (pair != null) { + valueDescriptor.setMarkup(debugProcess, pair.first); + if (pair.second) { + final Map map = NodeDescriptorImpl.getMarkupMap(debugProcess); + if (map != null) { + for (Map.Entry 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 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 result = new HashMap(); + 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 getReferringObjects(ObjectReference value) { + // invoke the following method using Reflection in order to remain compilable on jdk 1.5 + // java.util.List referringObjects(long l); + try { + final java.lang.reflect.Method apiMethod = ObjectReference.class.getMethod("referringObjects", long.class); + return (List)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("
").append(refType.name()).append(".").append(fieldName).append("").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); } -} \ No newline at end of file +} diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ObjectMarkupPropertiesDialog.java b/java/debugger/impl/src/com/intellij/debugger/actions/ObjectMarkupPropertiesDialog.java index a04f478cdfa8..c6851571e0cf 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/ObjectMarkupPropertiesDialog.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/ObjectMarkupPropertiesDialog.java @@ -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 myAdditional; + private static Boolean ourMarkCbSavedState; - public ObjectMarkupPropertiesDialog(final String suggestedName) { + public ObjectMarkupPropertiesDialog(@NotNull final ValueMarkup suggestion, @NotNull Map 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 chooseMarkup(ValueMarkup suggestion, Map 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(new ValueMarkup(text, color, suggestion.getToolTipText()), dialog.myCbMarkAdditionalFields.isSelected()) : null; } return null; } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreeBase.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreeBase.java index 386e36a523a7..839eaaf8ce93 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreeBase.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreeBase.java @@ -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("
"); + if (tipText.length() > 0) { + tipBuilder.append("

").append("Value="); + + final StringTokenizer tokenizer = new StringTokenizer(tipText, "\n"); + + while (tokenizer.hasMoreElements()) { + final String each = tokenizer.nextElement(); + tipBuilder.append(JDOMUtil.legalizeText(each)); + tipBuilder.append("
"); + } } 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 diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreeRenderer.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreeRenderer.java index 6572b49d22bb..db2212cd9959 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreeRenderer.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/DebuggerTreeRenderer.java @@ -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())); } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/DebuggerTreeNodeImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/DebuggerTreeNodeImpl.java index d03700fb69f1..571cc707ab38 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/DebuggerTreeNodeImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/DebuggerTreeNodeImpl.java @@ -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; diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeDescriptorImpl.java index 40447a003738..565251f7165e 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeDescriptorImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeDescriptorImpl.java @@ -139,7 +139,7 @@ public abstract class NodeDescriptorImpl implements NodeDescriptor { } @Nullable - protected static Map getMarkupMap(final DebugProcess process) { + public static Map getMarkupMap(final DebugProcess process) { if (process == null) { return null; } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java index 67f14ed807d3..aeed5bda7f0a 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java @@ -407,7 +407,12 @@ public abstract class ValueDescriptorImpl extends NodeDescriptorImpl implements final Map 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); + } } } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/ValueMarkup.java b/java/debugger/impl/src/com/intellij/debugger/ui/tree/ValueMarkup.java index 4c236df1f3cf..63eaf61cf193 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/ValueMarkup.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/ValueMarkup.java @@ -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(); + } }