From b74e1cfb86e4fd25f011e7daad64ec1baa07c0cd Mon Sep 17 00:00:00 2001 From: Egor Ushakov Date: Sun, 5 Oct 2014 13:25:55 +0400 Subject: [PATCH] IDEA-123114 Debugger: render awt.Image and swing.Icon in Variables/Watches/Evaluate views --- .../engine/FullValueEvaluatorProvider.java | 28 +++++ .../intellij/debugger/engine/JavaValue.java | 5 +- .../settings/ColorObjectRenderer.java | 69 +++++++++++ .../CustomPopupFullValueEvaluator.java | 72 +++++++++++ .../debugger/settings/IconObjectRenderer.java | 72 +++++++++++ .../settings/ImageObjectRenderer.java | 114 ++++++++++++++++++ .../settings/NodeRendererSettings.java | 49 ++------ .../render/CompoundReferenceRenderer.java | 13 ++ .../intellij/rt/debugger/ImageSerializer.java | 59 +++++++++ .../xdebugger/impl/ui/DebuggerUIUtil.java | 33 +++-- 10 files changed, 460 insertions(+), 54 deletions(-) create mode 100644 java/debugger/impl/src/com/intellij/debugger/engine/FullValueEvaluatorProvider.java create mode 100644 java/debugger/impl/src/com/intellij/debugger/settings/ColorObjectRenderer.java create mode 100644 java/debugger/impl/src/com/intellij/debugger/settings/CustomPopupFullValueEvaluator.java create mode 100644 java/debugger/impl/src/com/intellij/debugger/settings/IconObjectRenderer.java create mode 100644 java/debugger/impl/src/com/intellij/debugger/settings/ImageObjectRenderer.java create mode 100644 java/java-runtime/src/com/intellij/rt/debugger/ImageSerializer.java diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/FullValueEvaluatorProvider.java b/java/debugger/impl/src/com/intellij/debugger/engine/FullValueEvaluatorProvider.java new file mode 100644 index 000000000000..3d03d68750db --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/engine/FullValueEvaluatorProvider.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2014 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.debugger.engine; + +import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; +import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl; +import com.intellij.xdebugger.frame.XFullValueEvaluator; +import org.jetbrains.annotations.NotNull; + +/** + * Created by Egor on 04.10.2014. + */ +public interface FullValueEvaluatorProvider { + @NotNull XFullValueEvaluator getFullValueEvaluator(EvaluationContextImpl evaluationContext, ValueDescriptorImpl valueDescriptor); +} diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java index 0a5b37fcd5bf..5dc61a146a0b 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java @@ -146,7 +146,10 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV presentation = new JavaValuePresentation(value, type, exception != null ? exception.getMessage() : null); } } - if (value.length() > XValueNode.MAX_VALUE_LENGTH) { + if (myValueDescriptor.getLastRenderer() instanceof FullValueEvaluatorProvider) { + node.setFullValueEvaluator(((FullValueEvaluatorProvider)myValueDescriptor.getLastRenderer()).getFullValueEvaluator(myEvaluationContext, myValueDescriptor)); + } + else if (value.length() > XValueNode.MAX_VALUE_LENGTH) { node.setFullValueEvaluator(new XFullValueEvaluator() { @Override public void startEvaluation(@NotNull final XFullValueEvaluationCallback callback) { diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/ColorObjectRenderer.java b/java/debugger/impl/src/com/intellij/debugger/settings/ColorObjectRenderer.java new file mode 100644 index 000000000000..b5596ceb3559 --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/settings/ColorObjectRenderer.java @@ -0,0 +1,69 @@ +/* + * Copyright 2000-2014 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.debugger.settings; + +import com.intellij.debugger.engine.evaluation.EvaluateException; +import com.intellij.debugger.engine.evaluation.EvaluationContext; +import com.intellij.debugger.ui.tree.ValueDescriptor; +import com.intellij.debugger.ui.tree.render.CompoundReferenceRenderer; +import com.intellij.debugger.ui.tree.render.DescriptorLabelListener; +import com.intellij.util.ui.ColorIcon; +import com.sun.jdi.*; + +import javax.swing.*; +import java.awt.*; + +/** +* Created by Egor on 04.10.2014. +*/ +class ColorObjectRenderer extends CompoundReferenceRenderer { + + public ColorObjectRenderer(final NodeRendererSettings rendererSettings) { + super(rendererSettings, "Color", null, null); + setClassName("java.awt.Color"); + } + + public String calcLabel(ValueDescriptor descriptor, EvaluationContext evaluationContext, DescriptorLabelListener listener) throws + EvaluateException { + String res = calcToStringLabel(descriptor, evaluationContext, listener); + if (res != null) { + return res; + } + return super.calcLabel(descriptor, evaluationContext, listener); + } + + public Icon calcValueIcon(ValueDescriptor descriptor, EvaluationContext evaluationContext, DescriptorLabelListener listener) throws EvaluateException { + final Value value = descriptor.getValue(); + if (value instanceof ObjectReference) { + try { + final ObjectReference objRef = (ObjectReference)value; + final ReferenceType refType = objRef.referenceType(); + final Field valueField = refType.fieldByName("value"); + if (valueField != null) { + final Value rgbValue = objRef.getValue(valueField); + if (rgbValue instanceof IntegerValue) { + final Color color = new Color(((IntegerValue)rgbValue).value(), true); + return new ColorIcon(16, 12, color, true); + } + } + } + catch (Exception e) { + throw new EvaluateException(e.getMessage(), e); + } + } + return null; + } +} diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/CustomPopupFullValueEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/settings/CustomPopupFullValueEvaluator.java new file mode 100644 index 000000000000..084efd170c19 --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/settings/CustomPopupFullValueEvaluator.java @@ -0,0 +1,72 @@ +/* + * Copyright 2000-2014 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.debugger.settings; + +import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; +import com.intellij.debugger.engine.events.SuspendContextCommandImpl; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.wm.WindowManager; +import com.intellij.ui.awt.RelativePoint; +import com.intellij.xdebugger.frame.XFullValueEvaluator; +import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.*; + +/** + * Created by Egor on 04.10.2014. + */ +public abstract class CustomPopupFullValueEvaluator extends XFullValueEvaluator { + protected final EvaluationContextImpl myEvaluationContext; + + public CustomPopupFullValueEvaluator(@NotNull String linkText, EvaluationContextImpl evaluationContext) { + super(linkText); + myEvaluationContext = evaluationContext; + setShowValuePopup(false); + } + + protected abstract JComponent createComponent(); + + @Override + public void startEvaluation(@NotNull final XFullValueEvaluationCallback callback) { + myEvaluationContext.getDebugProcess().getManagerThread().schedule(new SuspendContextCommandImpl(myEvaluationContext.getSuspendContext()) { + @Override + public Priority getPriority() { + return Priority.NORMAL; + } + + @Override + public void contextAction() throws Exception { + final JComponent comp = createComponent(); + DebuggerUIUtil.invokeLater(new Runnable() { + @Override + public void run() { + Project project = myEvaluationContext.getProject(); + JBPopup popup = DebuggerUIUtil.createValuePopup(project, comp, null); + JFrame frame = WindowManager.getInstance().getFrame(project); + Dimension frameSize = frame.getSize(); + Dimension size = new Dimension(frameSize.width / 2, frameSize.height / 2); + popup.setSize(size); + callback.evaluated(""); + popup.show(new RelativePoint(frame, new Point((int)size.getWidth() / 2, (int)size.getHeight() / 2))); + } + }); + } + }); + } +} diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/IconObjectRenderer.java b/java/debugger/impl/src/com/intellij/debugger/settings/IconObjectRenderer.java new file mode 100644 index 000000000000..02fa84ef4f2c --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/settings/IconObjectRenderer.java @@ -0,0 +1,72 @@ +/* + * Copyright 2000-2014 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.debugger.settings; + +import com.intellij.debugger.engine.FullValueEvaluatorProvider; +import com.intellij.debugger.engine.evaluation.EvaluateException; +import com.intellij.debugger.engine.evaluation.EvaluationContext; +import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; +import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl; +import com.intellij.debugger.ui.tree.ValueDescriptor; +import com.intellij.debugger.ui.tree.render.CompoundReferenceRenderer; +import com.intellij.debugger.ui.tree.render.DescriptorLabelListener; +import com.intellij.ui.components.JBLabel; +import com.intellij.util.IconUtil; +import com.intellij.xdebugger.frame.XFullValueEvaluator; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; + +/** +* Created by Egor on 04.10.2014. +*/ +class IconObjectRenderer extends CompoundReferenceRenderer implements FullValueEvaluatorProvider { + + public IconObjectRenderer(final NodeRendererSettings rendererSettings) { + super(rendererSettings, "Icon", null, null); + setClassName("javax.swing.Icon"); + } + + public String calcLabel(ValueDescriptor descriptor, EvaluationContext evaluationContext, DescriptorLabelListener listener) throws + EvaluateException { + String res = calcToStringLabel(descriptor, evaluationContext, listener); + if (res != null) { + return res; + } + return super.calcLabel(descriptor, evaluationContext, listener); + } + + @Override + public Icon calcValueIcon(ValueDescriptor descriptor, EvaluationContext evaluationContext, DescriptorLabelListener listener) + throws EvaluateException { + ImageIcon icon = ImageObjectRenderer.getIcon(evaluationContext, descriptor.getValue(), "iconToBytes"); + if (icon != null) { + return IconUtil.cropIcon(icon, 16, 16); + } + return null; + } + + @NotNull + @Override + public XFullValueEvaluator getFullValueEvaluator(final EvaluationContextImpl evaluationContext, final ValueDescriptorImpl valueDescriptor) { + return new CustomPopupFullValueEvaluator(" (Show icon)", evaluationContext) { + @Override + protected JComponent createComponent() { + return new JBLabel(ImageObjectRenderer.getIcon(myEvaluationContext, valueDescriptor.getValue(), "iconToBytes")); + } + }; + } +} diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/ImageObjectRenderer.java b/java/debugger/impl/src/com/intellij/debugger/settings/ImageObjectRenderer.java new file mode 100644 index 000000000000..8f48ae93b995 --- /dev/null +++ b/java/debugger/impl/src/com/intellij/debugger/settings/ImageObjectRenderer.java @@ -0,0 +1,114 @@ +/* + * Copyright 2000-2014 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.debugger.settings; + +import com.intellij.debugger.engine.DebugProcess; +import com.intellij.debugger.engine.FullValueEvaluatorProvider; +import com.intellij.debugger.engine.evaluation.EvaluateException; +import com.intellij.debugger.engine.evaluation.EvaluationContext; +import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; +import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl; +import com.intellij.debugger.ui.tree.ValueDescriptor; +import com.intellij.debugger.ui.tree.render.CompoundReferenceRenderer; +import com.intellij.debugger.ui.tree.render.DescriptorLabelListener; +import com.intellij.rt.debugger.ImageSerializer; +import com.intellij.ui.components.JBLabel; +import com.intellij.xdebugger.frame.XFullValueEvaluator; +import com.sun.jdi.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.util.Arrays; +import java.util.List; + +/** +* Created by Egor on 04.10.2014. +*/ +class ImageObjectRenderer extends CompoundReferenceRenderer implements FullValueEvaluatorProvider { + public ImageObjectRenderer(final NodeRendererSettings rendererSettings) { + super(rendererSettings, "Image", null, null); + setClassName("java.awt.Image"); + } + + public String calcLabel(ValueDescriptor descriptor, EvaluationContext evaluationContext, DescriptorLabelListener listener) throws + EvaluateException { + String res = calcToStringLabel(descriptor, evaluationContext, listener); + if (res != null) { + return res; + } + return super.calcLabel(descriptor, evaluationContext, listener); + } + + @NotNull + @Override + public XFullValueEvaluator getFullValueEvaluator(final EvaluationContextImpl evaluationContext, final ValueDescriptorImpl valueDescriptor) { + return new CustomPopupFullValueEvaluator(" (Show image)", evaluationContext) { + @Override + protected JComponent createComponent() { + return new JBLabel(getIcon(myEvaluationContext, valueDescriptor.getValue(), "imageToBytes")); + } + }; + } + + @Nullable + static ImageIcon getIcon(EvaluationContext evaluationContext, Value obj, String methodName) { + try { + Value bytes = getImageBytes(evaluationContext, obj, methodName); + byte[] data = readBytes(bytes); + if (data != null) { + return new ImageIcon(data); + } + } + catch (Exception e) { + return null; + } + return null; + } + + private static Value getImageBytes(EvaluationContext evaluationContext, Value obj, String methodName) + throws EvaluateException, ClassNotLoadedException, InvalidTypeException { + DebugProcess process = evaluationContext.getDebugProcess(); + ClassType cls = (ClassType)process.findClass(evaluationContext, ImageSerializer.class.getName(), + evaluationContext.getClassLoader()); + + if (cls != null) { + List methods = cls.methodsByName(methodName); + if (!methods.isEmpty()) { + return process.invokeMethod(evaluationContext, cls, methods.get(0), Arrays.asList(obj)); + } + } + return null; + } + + private static byte[] readBytes(Value bytes) { + if (bytes instanceof ArrayReference) { + List values = ((ArrayReference)bytes).getValues(); + byte[] res = new byte[values.size()]; + int idx = 0; + for (Value value : values) { + if (value instanceof ByteValue) { + res[idx++] = ((ByteValue)value).value(); + } + else { + return null; + } + } + return res; + } + return null; + } +} diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/NodeRendererSettings.java b/java/debugger/impl/src/com/intellij/debugger/settings/NodeRendererSettings.java index e1d80414f0e6..5d5bd7681336 100644 --- a/java/debugger/impl/src/com/intellij/debugger/settings/NodeRendererSettings.java +++ b/java/debugger/impl/src/com/intellij/debugger/settings/NodeRendererSettings.java @@ -17,7 +17,6 @@ package com.intellij.debugger.settings; import com.intellij.debugger.DebuggerBundle; import com.intellij.debugger.DebuggerContext; -import com.intellij.debugger.DebuggerManagerEx; import com.intellij.debugger.engine.DebugProcess; import com.intellij.debugger.engine.evaluation.*; import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator; @@ -41,7 +40,6 @@ import com.intellij.psi.PsiExpression; import com.intellij.util.EventDispatcher; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.InternalIterator; -import com.intellij.util.ui.ColorIcon; import com.sun.jdi.*; import org.jdom.Element; import org.jetbrains.annotations.NonNls; @@ -49,7 +47,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.awt.*; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -82,6 +79,8 @@ public class NodeRendererSettings implements PersistentStateComponent { private final HexRenderer myHexRenderer = new HexRenderer(); private final ToStringRenderer myToStringRenderer = new ToStringRenderer(); private final CompoundReferenceRenderer myColorRenderer; + private final CompoundReferenceRenderer myImageRenderer; + private final CompoundReferenceRenderer myIconRenderer; // alternate collections private final NodeRenderer[] myAlternateCollectionRenderers = new NodeRenderer[]{ createCompoundReferenceRenderer( @@ -111,11 +110,15 @@ public class NodeRendererSettings implements PersistentStateComponent { public NodeRendererSettings() { myColorRenderer = new ColorObjectRenderer(this); + myImageRenderer = new ImageObjectRenderer(this); + myIconRenderer = new IconObjectRenderer(this); // default configuration myHexRenderer.setEnabled(false); myToStringRenderer.setEnabled(true); setAlternateCollectionViewsEnabled(true); myColorRenderer.setEnabled(true); + myImageRenderer.setEnabled(true); + myIconRenderer.setEnabled(true); } public static NodeRendererSettings getInstance() { @@ -282,6 +285,8 @@ public class NodeRendererSettings implements PersistentStateComponent { }); Collections.addAll(allRenderers, myAlternateCollectionRenderers); allRenderers.add(myColorRenderer); + allRenderers.add(myImageRenderer); + allRenderers.add(myIconRenderer); allRenderers.add(myToStringRenderer); allRenderers.add(myArrayRenderer); allRenderers.add(myClassRenderer); @@ -559,42 +564,4 @@ public class NodeRendererSettings implements PersistentStateComponent { return keyDescriptor == null? "null" : keyDescriptor.getValueLabel(); } } - - private static class ColorObjectRenderer extends CompoundReferenceRenderer { - - public ColorObjectRenderer(final NodeRendererSettings rendererSettings) { - super(rendererSettings, "Color", null, null); - setClassName("java.awt.Color"); - } - - public String calcLabel(ValueDescriptor descriptor, EvaluationContext evaluationContext, DescriptorLabelListener listener) throws EvaluateException { - final ToStringRenderer toStringRenderer = myRendererSettings.getToStringRenderer(); - if (toStringRenderer.isEnabled() && DebuggerManagerEx.getInstanceEx(evaluationContext.getProject()).getContext().isEvaluationPossible()) { - return toStringRenderer.calcLabel(descriptor, evaluationContext, listener); - } - return super.calcLabel(descriptor, evaluationContext, listener); - } - - public Icon calcValueIcon(ValueDescriptor descriptor, EvaluationContext evaluationContext, DescriptorLabelListener listener) throws EvaluateException { - final Value value = descriptor.getValue(); - if (value instanceof ObjectReference) { - try { - final ObjectReference objRef = (ObjectReference)value; - final ReferenceType refType = objRef.referenceType(); - final Field valueField = refType.fieldByName("value"); - if (valueField != null) { - final Value rgbValue = objRef.getValue(valueField); - if (rgbValue instanceof IntegerValue) { - final Color color = new Color(((IntegerValue)rgbValue).value(), true); - return new ColorIcon(16, 12, color, true); - } - } - } - catch (Exception e) { - throw new EvaluateException(e.getMessage(), e); - } - } - return null; - } - } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/CompoundReferenceRenderer.java b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/CompoundReferenceRenderer.java index c3e20f60d398..9522e7150f4b 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/CompoundReferenceRenderer.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/CompoundReferenceRenderer.java @@ -15,8 +15,12 @@ */ package com.intellij.debugger.ui.tree.render; +import com.intellij.debugger.DebuggerManagerEx; import com.intellij.debugger.engine.DebuggerUtils; +import com.intellij.debugger.engine.evaluation.EvaluateException; +import com.intellij.debugger.engine.evaluation.EvaluationContext; import com.intellij.debugger.settings.NodeRendererSettings; +import com.intellij.debugger.ui.tree.ValueDescriptor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.CommonClassNames; import com.sun.jdi.ReferenceType; @@ -106,6 +110,15 @@ public class CompoundReferenceRenderer extends CompoundNodeRenderer{ } } + protected String calcToStringLabel(ValueDescriptor descriptor, EvaluationContext evaluationContext, DescriptorLabelListener listener) + throws EvaluateException { + final ToStringRenderer toStringRenderer = myRendererSettings.getToStringRenderer(); + if (toStringRenderer.isEnabled() && DebuggerManagerEx.getInstanceEx(evaluationContext.getProject()).getContext().isEvaluationPossible()) { + return toStringRenderer.calcLabel(descriptor, evaluationContext, listener); + } + return null; + } + public @NotNull String getClassName() { return myProperties.getClassName(); } diff --git a/java/java-runtime/src/com/intellij/rt/debugger/ImageSerializer.java b/java/java-runtime/src/com/intellij/rt/debugger/ImageSerializer.java new file mode 100644 index 000000000000..c6e509904777 --- /dev/null +++ b/java/java-runtime/src/com/intellij/rt/debugger/ImageSerializer.java @@ -0,0 +1,59 @@ +/* + * Copyright 2000-2014 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.rt.debugger; + +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +/** + * Created by Egor on 04.10.2014. + */ +public class ImageSerializer { + public static byte[] imageToBytes(Image image) throws IOException { + BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB); + Graphics2D g = bi.createGraphics(); + g.drawImage(image, 0, 0, null); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageIO.write(bi, "png", baos); + return baos.toByteArray(); + } + + public static byte[] iconToBytes(Icon icon) throws IOException { + return imageToBytes(toImage(icon)); + } + + // copied from IconUtils + private static Image toImage(Icon icon) { + if (icon instanceof ImageIcon) { + return ((ImageIcon)icon).getImage(); + } + else { + final int w = icon.getIconWidth(); + final int h = icon.getIconHeight(); + final BufferedImage image = GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage(w, h, Transparency.TRANSLUCENT); + final Graphics2D g = image.createGraphics(); + icon.paintIcon(null, g, 0, 0); + g.dispose(); + return image; + } + } + +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java index d9a1fdbcf0af..9baa5a85bda4 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java @@ -114,18 +114,7 @@ public class DebuggerUIUtil { textArea.setPreferredSize(size); - JBPopup popup = JBPopupFactory.getInstance().createComponentPopupBuilder(textArea, null) - .setResizable(true) - .setMovable(true) - .setDimensionServiceKey(project, FULL_VALUE_POPUP_DIMENSION_KEY, false) - .setRequestFocus(false) - .setCancelCallback(new Computable() { - @Override - public Boolean compute() { - callback.setObsolete(); - return true; - } - }).createPopup(); + JBPopup popup = createValuePopup(project, textArea, callback); if (editor == null) { popup.show(new RelativePoint(event.getComponent(), new Point(event.getX() - size.width, event.getY() - size.height))); } @@ -134,6 +123,26 @@ public class DebuggerUIUtil { } } + public static JBPopup createValuePopup(Project project, + JComponent component, + @Nullable final FullValueEvaluationCallbackImpl callback) { + ComponentPopupBuilder builder = JBPopupFactory.getInstance().createComponentPopupBuilder(component, null); + builder.setResizable(true) + .setMovable(true) + .setDimensionServiceKey(project, FULL_VALUE_POPUP_DIMENSION_KEY, false) + .setRequestFocus(false); + if (callback != null) { + builder.setCancelCallback(new Computable() { + @Override + public Boolean compute() { + callback.setObsolete(); + return true; + } + }); + } + return builder.createPopup(); + } + public static void showXBreakpointEditorBalloon(final Project project, @Nullable final Point point, final JComponent component,