mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-175168 On-demand renderers - implemented on-demand user renderers
This commit is contained in:
@@ -157,8 +157,13 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
|
||||
XValuePresentation presentation = new JavaValuePresentation(
|
||||
value, myValueDescriptor.getIdLabel(), exception != null ? exception.getMessage() : null, myValueDescriptor);
|
||||
|
||||
if (myValueDescriptor.getLastRenderer() instanceof FullValueEvaluatorProvider) {
|
||||
XFullValueEvaluator evaluator = ((FullValueEvaluatorProvider)myValueDescriptor.getLastRenderer())
|
||||
// TODO move inside JavaValuePresentation
|
||||
Renderer lastRenderer = myValueDescriptor.getLastRenderer();
|
||||
if (lastRenderer instanceof CompoundNodeRenderer) {
|
||||
lastRenderer = ((CompoundNodeRenderer)lastRenderer).getLabelRenderer();
|
||||
}
|
||||
if (lastRenderer instanceof FullValueEvaluatorProvider) {
|
||||
XFullValueEvaluator evaluator = ((FullValueEvaluatorProvider)lastRenderer)
|
||||
.getFullValueEvaluator(myEvaluationContext, myValueDescriptor);
|
||||
if (evaluator != null) {
|
||||
node.setFullValueEvaluator(evaluator);
|
||||
@@ -302,13 +307,20 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
|
||||
|
||||
String value = truncateToMaxLength(myValue);
|
||||
Renderer lastRenderer = myValueDescriptor.getLastRenderer();
|
||||
if (lastRenderer instanceof OnDemandRenderer) {
|
||||
OnDemandRenderer onDemandRenderer = (OnDemandRenderer)lastRenderer;
|
||||
if (OnDemandRenderer.isCalculated(myValueDescriptor)) {
|
||||
lastRenderer = onDemandRenderer.getRenderer();
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastRenderer instanceof CompoundTypeRenderer) {
|
||||
lastRenderer = ((CompoundTypeRenderer)lastRenderer).getLabelRenderer();
|
||||
}
|
||||
if (lastRenderer instanceof ToStringRenderer) {
|
||||
if (lastRenderer instanceof LazyToStringRenderer && !((LazyToStringRenderer)lastRenderer).isCalculated(myValueDescriptor)) {
|
||||
return;
|
||||
}
|
||||
value = StringUtil.wrapWithDoubleQuote(value);
|
||||
}
|
||||
renderer.renderValue(value);
|
||||
|
||||
+12
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 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.
|
||||
@@ -59,6 +59,7 @@ class CompoundRendererConfigurable extends JPanel {
|
||||
private final JRadioButton myRbDefaultLabel;
|
||||
private final JRadioButton myRbExpressionLabel;
|
||||
private final JBCheckBox myShowTypeCheckBox;
|
||||
private final JBCheckBox myOnDemandCheckBox;
|
||||
private final JRadioButton myRbDefaultChildrenRenderer;
|
||||
private final JRadioButton myRbExpressionChildrenRenderer;
|
||||
private final JRadioButton myRbListChildrenRenderer;
|
||||
@@ -88,6 +89,7 @@ class CompoundRendererConfigurable extends JPanel {
|
||||
labelButtonsGroup.add(myRbExpressionLabel);
|
||||
|
||||
myShowTypeCheckBox = new JBCheckBox(DebuggerBundle.message("label.compound.renderer.configurable.show.type"));
|
||||
myOnDemandCheckBox = new JBCheckBox(DebuggerBundle.message("label.compound.renderer.configurable.ondemand"));
|
||||
|
||||
myRbDefaultChildrenRenderer = new JRadioButton(DebuggerBundle.message("label.compound.renderer.configurable.use.default.renderer"));
|
||||
myRbExpressionChildrenRenderer = new JRadioButton(DebuggerBundle.message("label.compound.renderer.configurable.use.expression"));
|
||||
@@ -156,6 +158,8 @@ class CompoundRendererConfigurable extends JPanel {
|
||||
JBUI.insetsLeft(10), 0, 0));
|
||||
panel.add(myLabelEditor.getComponent(), new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST,
|
||||
GridBagConstraints.HORIZONTAL, JBUI.insetsLeft(30), 0, 0));
|
||||
panel.add(myOnDemandCheckBox, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST,
|
||||
GridBagConstraints.HORIZONTAL, JBUI.insetsLeft(30), 0, 0));
|
||||
|
||||
panel.add(new JLabel(DebuggerBundle.message("label.compound.renderer.configurable.when.expanding")),
|
||||
new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
|
||||
@@ -218,7 +222,9 @@ class CompoundRendererConfigurable extends JPanel {
|
||||
}
|
||||
|
||||
private void updateEnabledState() {
|
||||
myLabelEditor.setEnabled(myRbExpressionLabel.isSelected());
|
||||
boolean isLabelRenderer = myRbExpressionLabel.isSelected();
|
||||
myLabelEditor.setEnabled(isLabelRenderer);
|
||||
myOnDemandCheckBox.setEnabled(isLabelRenderer);
|
||||
|
||||
final boolean isChildrenExpression = myRbExpressionChildrenRenderer.isSelected();
|
||||
myChildrenExpandedEditor.setEnabled(isChildrenExpression);
|
||||
@@ -321,6 +327,7 @@ class CompoundRendererConfigurable extends JPanel {
|
||||
if (myRbExpressionLabel.isSelected()) {
|
||||
labelRenderer = new LabelRenderer();
|
||||
labelRenderer.setLabelExpression(TextWithImportsImpl.fromXExpression(myLabelEditor.getExpression()));
|
||||
labelRenderer.setOnDemand(myOnDemandCheckBox.isSelected());
|
||||
}
|
||||
renderer.setLabelRenderer(labelRenderer);
|
||||
// children
|
||||
@@ -362,7 +369,9 @@ class CompoundRendererConfigurable extends JPanel {
|
||||
}
|
||||
else {
|
||||
myRbExpressionLabel.setSelected(true);
|
||||
myLabelEditor.setExpression(TextWithImportsImpl.toXExpression(((LabelRenderer)labelRenderer).getLabelExpression()));
|
||||
LabelRenderer lr = (LabelRenderer)labelRenderer;
|
||||
myLabelEditor.setExpression(TextWithImportsImpl.toXExpression(lr.getLabelExpression()));
|
||||
myOnDemandCheckBox.setSelected(lr.isOnDemand());
|
||||
}
|
||||
|
||||
getTableModel().clear();
|
||||
|
||||
@@ -22,7 +22,7 @@ import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
|
||||
import com.intellij.debugger.ui.tree.NodeDescriptor;
|
||||
import com.intellij.debugger.ui.tree.render.DescriptorLabelListener;
|
||||
import com.intellij.debugger.ui.tree.render.LazyToStringRenderer;
|
||||
import com.intellij.debugger.ui.tree.render.OnDemandRenderer;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
@@ -119,7 +119,7 @@ public abstract class NodeDescriptorImpl implements NodeDescriptor {
|
||||
|
||||
// TODO introduce unified way to handle this
|
||||
if (myUserData != null) {
|
||||
myUserData.remove(LazyToStringRenderer.LAZY_CALCULATED); // lazy flag should not be inherited
|
||||
myUserData.remove(OnDemandRenderer.ON_DEMAND_CALCULATED); // calculated flag should not be inherited
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 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.
|
||||
@@ -18,25 +18,25 @@ package com.intellij.debugger.ui.tree.render;
|
||||
import com.intellij.debugger.DebuggerBundle;
|
||||
import com.intellij.debugger.engine.DebugProcess;
|
||||
import com.intellij.debugger.engine.DebuggerUtils;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContext;
|
||||
import com.intellij.debugger.engine.evaluation.TextWithImports;
|
||||
import com.intellij.debugger.engine.FullValueEvaluatorProvider;
|
||||
import com.intellij.debugger.engine.evaluation.*;
|
||||
import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator;
|
||||
import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl;
|
||||
import com.intellij.debugger.ui.tree.ValueDescriptor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.DefaultJDOMExternalizer;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.xdebugger.frame.XFullValueEvaluator;
|
||||
import com.sun.jdi.Value;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class LabelRenderer extends TypeRenderer implements ValueLabelRenderer{
|
||||
public class LabelRenderer extends TypeRenderer implements ValueLabelRenderer, FullValueEvaluatorProvider {
|
||||
public static final @NonNls String UNIQUE_ID = "LabelRenderer";
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.ui.impl.watch.render.ClassLabelRenderer");
|
||||
public boolean myOnDemand;
|
||||
|
||||
private CachedEvaluator myLabelExpression = createCachedEvaluator();
|
||||
|
||||
@@ -62,6 +62,10 @@ public class LabelRenderer extends TypeRenderer implements ValueLabelRenderer{
|
||||
public String calcLabel(ValueDescriptor descriptor, EvaluationContext evaluationContext, DescriptorLabelListener labelListener)
|
||||
throws EvaluateException {
|
||||
|
||||
if (myOnDemand && !OnDemandRenderer.isCalculated(descriptor)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
final Value value = descriptor.getValue();
|
||||
|
||||
String result;
|
||||
@@ -88,6 +92,15 @@ public class LabelRenderer extends TypeRenderer implements ValueLabelRenderer{
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public XFullValueEvaluator getFullValueEvaluator(EvaluationContextImpl evaluationContext, ValueDescriptorImpl valueDescriptor) {
|
||||
if (myOnDemand && !OnDemandRenderer.isCalculated(valueDescriptor)) {
|
||||
return OnDemandRenderer.createFullValueEvaluator("… " + getLabelExpression().getText());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void readExternal(Element element) throws InvalidDataException {
|
||||
super.readExternal(element);
|
||||
DefaultJDOMExternalizer.readExternal(this, element);
|
||||
@@ -111,4 +124,11 @@ public class LabelRenderer extends TypeRenderer implements ValueLabelRenderer{
|
||||
myLabelExpression.setReferenceExpression(expression);
|
||||
}
|
||||
|
||||
public boolean isOnDemand() {
|
||||
return myOnDemand;
|
||||
}
|
||||
|
||||
public void setOnDemand(boolean value) {
|
||||
myOnDemand = value;
|
||||
}
|
||||
}
|
||||
|
||||
+66
-25
@@ -16,64 +16,105 @@
|
||||
package com.intellij.debugger.ui.tree.render
|
||||
|
||||
import com.intellij.debugger.DebuggerBundle
|
||||
import com.intellij.debugger.DebuggerContext
|
||||
import com.intellij.debugger.engine.FullValueEvaluatorProvider
|
||||
import com.intellij.debugger.engine.JavaValue
|
||||
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.DebuggerTreeNode
|
||||
import com.intellij.debugger.ui.tree.NodeDescriptor
|
||||
import com.intellij.debugger.ui.tree.ValueDescriptor
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.xdebugger.frame.XFullValueEvaluator
|
||||
import com.intellij.xdebugger.frame.XValuePlace
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.HeadlessValueEvaluationCallback
|
||||
import com.sun.jdi.Type
|
||||
import com.sun.jdi.Value
|
||||
import javax.swing.Icon
|
||||
|
||||
/**
|
||||
* @author egor
|
||||
*/
|
||||
class LazyToStringRenderer : ToStringRenderer(), FullValueEvaluatorProvider {
|
||||
class OnDemandRenderer(val renderer: NodeRendererImpl) : NodeRendererImpl(), FullValueEvaluatorProvider {
|
||||
init {
|
||||
isEnabled = true
|
||||
}
|
||||
|
||||
override fun getFullValueEvaluator(evaluationContext: EvaluationContextImpl?, valueDescriptor: ValueDescriptorImpl): XFullValueEvaluator? {
|
||||
if (!isCalculated(valueDescriptor)) {
|
||||
return object : XFullValueEvaluator(DebuggerBundle.message("message.node.toString")) {
|
||||
override fun startEvaluation(callback: XFullValueEvaluator.XFullValueEvaluationCallback) {
|
||||
if (callback is HeadlessValueEvaluationCallback) {
|
||||
val node = callback.node
|
||||
node.clearFullValueEvaluator()
|
||||
valueDescriptor.putUserData(LAZY_CALCULATED, true)
|
||||
node.valueContainer.computePresentation(node, XValuePlace.TREE)
|
||||
}
|
||||
callback.evaluated("")
|
||||
}
|
||||
}.setShowValuePopup(false)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
@Throws(EvaluateException::class)
|
||||
override fun calcLabel(descriptor: ValueDescriptor, evaluationContext: EvaluationContext, listener: DescriptorLabelListener): String? {
|
||||
if (!isCalculated(descriptor)) {
|
||||
return ""
|
||||
}
|
||||
return super.calcLabel(descriptor, evaluationContext, listener)
|
||||
return renderer.calcLabel(descriptor, evaluationContext, listener)
|
||||
}
|
||||
|
||||
fun isCalculated(descriptor: ValueDescriptor): Boolean {
|
||||
return LAZY_CALCULATED.get(descriptor, false)
|
||||
override fun getFullValueEvaluator(evaluationContext: EvaluationContextImpl?, valueDescriptor: ValueDescriptorImpl): XFullValueEvaluator? {
|
||||
if (!isCalculated(valueDescriptor)) {
|
||||
return createFullValueEvaluator(DebuggerBundle.message("message.node.toString"))
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun buildChildren(value: Value?, builder: ChildrenBuilder?, evaluationContext: EvaluationContext?) {
|
||||
renderer.buildChildren(value, builder, evaluationContext)
|
||||
}
|
||||
|
||||
override fun getChildValueExpression(node: DebuggerTreeNode?, context: DebuggerContext?): PsiElement {
|
||||
return renderer.getChildValueExpression(node, context)
|
||||
}
|
||||
|
||||
override fun isExpandable(value: Value?, evaluationContext: EvaluationContext?, parentDescriptor: NodeDescriptor?): Boolean {
|
||||
return renderer.isExpandable(value, evaluationContext, parentDescriptor)
|
||||
}
|
||||
|
||||
override fun calcValueIcon(descriptor: ValueDescriptor?,
|
||||
evaluationContext: EvaluationContext?,
|
||||
listener: DescriptorLabelListener?): Icon? {
|
||||
return renderer.calcValueIcon(descriptor, evaluationContext, listener)
|
||||
}
|
||||
|
||||
override fun isApplicable(type: Type?): Boolean {
|
||||
return renderer.isApplicable(type)
|
||||
}
|
||||
|
||||
override fun getName(): String {
|
||||
return "Lazy" + super.getName()
|
||||
return "OnDemand" + renderer.getName()
|
||||
}
|
||||
|
||||
override fun getUniqueId(): String {
|
||||
return "Lazy" + super.getUniqueId()
|
||||
return "OnDemand" + renderer.getUniqueId()
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun createFullValueEvaluator(text: String): XFullValueEvaluator {
|
||||
return object : XFullValueEvaluator(text) {
|
||||
override fun startEvaluation(callback: XFullValueEvaluator.XFullValueEvaluationCallback) {
|
||||
if (callback is HeadlessValueEvaluationCallback) {
|
||||
val node = callback.node
|
||||
node.clearFullValueEvaluator()
|
||||
setCalculated((node.valueContainer as JavaValue).descriptor)
|
||||
node.valueContainer.computePresentation(node, XValuePlace.TREE)
|
||||
}
|
||||
callback.evaluated("")
|
||||
}
|
||||
}.setShowValuePopup(false)
|
||||
}
|
||||
|
||||
@JvmField
|
||||
val LAZY_CALCULATED = Key.create<Boolean>("LAZY_CALCULATED")
|
||||
val ON_DEMAND_CALCULATED = Key.create<Boolean>("ON_DEMAND_CALCULATED")
|
||||
|
||||
@JvmStatic
|
||||
fun isCalculated(descriptor: ValueDescriptor): Boolean {
|
||||
return ON_DEMAND_CALCULATED.get(descriptor, false)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun setCalculated(descriptor: ValueDescriptor) {
|
||||
ON_DEMAND_CALCULATED.set(descriptor, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 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.
|
||||
@@ -52,6 +52,7 @@ public abstract class XFullValueEvaluator {
|
||||
return myShowValuePopup;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public XFullValueEvaluator setShowValuePopup(boolean value) {
|
||||
myShowValuePopup = value;
|
||||
return this;
|
||||
|
||||
@@ -208,6 +208,7 @@ label.base.renderer.configurable.enable.toString=Enable 't&oString()' object vie
|
||||
label.base.renderer.configurable.all.overriding=For all classes that override 'toString()' method
|
||||
label.base.renderer.configurable.classes.from.list=For classes from the list:
|
||||
label.compound.renderer.configurable.show.type=Show type and object id
|
||||
label.compound.renderer.configurable.ondemand=On-demand
|
||||
label.compound.renderer.configurable.use.default.renderer=Use default renderer
|
||||
label.compound.renderer.configurable.use.expression=Use following expression:
|
||||
label.compound.renderer.configurable.use.expression.list=Use list of expressions:
|
||||
|
||||
Reference in New Issue
Block a user