IDEA-23075 Debugger "Set Value" TextBox should be a TextArea - implemented editable...
authorEgor.Ushakov <egor.ushakov@jetbrains.com>
Tue, 26 Apr 2016 14:47:44 +0000 (17:47 +0300)
committerEgor.Ushakov <egor.ushakov@jetbrains.com>
Tue, 26 Apr 2016 14:49:33 +0000 (17:49 +0300)
java/debugger/impl/src/com/intellij/debugger/actions/ViewTextAction.java
platform/platform-resources-en/src/messages/ActionsBundle.properties
platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerUIUtil.java
platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/TextViewer.java
platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/SetValueInplaceEditor.java

index bf63f833b23eb22ecab4dcc95992413cccb43b03..22573df059afd540a5ad2df3e5c6ea8196f8801e 100644 (file)
  */
 package com.intellij.debugger.actions;
 
+import com.intellij.debugger.engine.DebuggerUtils;
+import com.intellij.debugger.engine.JavaValue;
+import com.intellij.idea.ActionsBundle;
 import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.editor.event.DocumentAdapter;
+import com.intellij.openapi.editor.event.DocumentEvent;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.ui.EditorTextField;
 import com.intellij.util.ui.JBUI;
+import com.intellij.util.ui.components.BorderLayoutPanel;
+import com.intellij.xdebugger.frame.XValue;
+import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
 import com.intellij.xdebugger.impl.ui.TextViewer;
 import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
+import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase;
 import com.intellij.xdebugger.impl.ui.tree.actions.XFetchValueActionBase;
+import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
-import java.awt.*;
+import java.util.List;
 
 /*
  * @author Jeka
@@ -45,16 +55,38 @@ public class ViewTextAction extends XFetchValueActionBase {
 
       @Override
       public void handleInCollector(Project project, String value, XDebuggerTree tree) {
+        String text = StringUtil.unquoteString(value);
         if (dialog == null) {
-          dialog = new MyDialog(project);
-          dialog.setTitle("View Text");
+          XValueNodeImpl node = getStringNode(e);
+          dialog = new MyDialog(project, text, node);
+          dialog.setTitle(ActionsBundle.message(node != null ? "action.Debugger.ViewEditText.text" : "action.Debugger.ViewText.text"));
           dialog.show();
         }
-        dialog.setText(StringUtil.unquoteString(value));
+        dialog.setText(text);
       }
     };
   }
 
+  @Override
+  public void update(@NotNull AnActionEvent e) {
+    super.update(e);
+    if (getStringNode(e) != null) {
+      e.getPresentation().setText(ActionsBundle.message("action.Debugger.ViewEditText.text"));
+    }
+  }
+
+  private static XValueNodeImpl getStringNode(@NotNull AnActionEvent e) {
+    List<XValueNodeImpl> selectedNodes = XDebuggerTreeActionBase.getSelectedNodes(e.getDataContext());
+    if (selectedNodes.size() == 1) {
+      XValueNodeImpl node = selectedNodes.get(0);
+      XValue container = node.getValueContainer();
+      if (container instanceof JavaValue && ((JavaValue)container).getDescriptor().isString() && container.getModifier() != null) {
+        return node;
+      }
+    }
+    return null;
+  }
+
   //@Override
   //protected void processText(final Project project, final String text, DebuggerTreeNodeImpl node, DebuggerContextImpl debuggerContext) {
   //  final NodeDescriptorImpl descriptor = node.getDescriptor();
@@ -66,15 +98,27 @@ public class ViewTextAction extends XFetchValueActionBase {
   //}
 
   private static class MyDialog extends DialogWrapper {
-    private final EditorTextField myTextViewer;
+    private final TextViewer myTextViewer;
+    private final XValueNodeImpl myStringNode;
 
-    private MyDialog(Project project) {
+    private MyDialog(Project project, String initialValue, XValueNodeImpl stringNode) {
       super(project, false);
+      myStringNode = stringNode;
       setModal(false);
       setCancelButtonText("Close");
+      setOKButtonText("Set");
+      getOKAction().setEnabled(false);
       setCrossClosesWindow(true);
 
-      myTextViewer = new TextViewer(project, true, true);
+      myTextViewer = new TextViewer(initialValue, project, myStringNode == null);
+      myTextViewer.addDocumentListener(new DocumentAdapter() {
+        @Override
+        public void documentChanged(DocumentEvent e) {
+          if (e.getNewLength() + e.getOldLength() > 0) {
+            getOKAction().setEnabled(true);
+          }
+        }
+      });
       init();
     }
 
@@ -82,10 +126,20 @@ public class ViewTextAction extends XFetchValueActionBase {
       myTextViewer.setText(text);
     }
 
+    @Override
+    protected void doOKAction() {
+      if (myStringNode != null) {
+        DebuggerUIUtil.setTreeNodeValue(myStringNode,
+                                        StringUtil.wrapWithDoubleQuote(DebuggerUtils.translateStringValue(myTextViewer.getText())),
+                                        errorMessage -> Messages.showErrorDialog(myStringNode.getTree(), errorMessage));
+      }
+      super.doOKAction();
+    }
+
     @Override
     @NotNull
     protected Action[] createActions() {
-      return new Action[] {getCancelAction()};
+      return myStringNode != null ? new Action[]{getOKAction(), getCancelAction()} : new Action[]{getCancelAction()};
     }
 
     @Nullable
@@ -101,8 +155,7 @@ public class ViewTextAction extends XFetchValueActionBase {
 
     @Override
     protected JComponent createCenterPanel() {
-      final JPanel panel = new JPanel(new BorderLayout());
-      panel.add(myTextViewer, BorderLayout.CENTER);
+      BorderLayoutPanel panel = JBUI.Panels.simplePanel(myTextViewer);
       panel.setPreferredSize(JBUI.size(300, 200));
       return panel;
     }
index 3e94ee271249820bb87171e60b6cfba5761ede7b..ae6d3f2747f7d2f98cba00c67d7931cf2477bf50 100644 (file)
@@ -1027,6 +1027,7 @@ group.XDebugger.settings.text=Settings
 action.Debugger.AdjustArrayRange.text=Adjust Range...
 action.Debugger.Inspect.text=Inspect
 action.Debugger.CopyValue.text=Copy Value
+action.Debugger.ViewEditText.text=View/Edit Text
 action.Debugger.ViewText.text=View Text
 action.Debugger.ViewText.description=View text value of selected node in a separate pane
 action.Debugger.ShowReferring.text=Show Referring Objects
index 4764e4047bc7398bfb393d7d23770925707470c4..f9728611db035ff908eeef411ac0483716ce7dfc 100644 (file)
@@ -16,6 +16,7 @@
 package com.intellij.xdebugger.impl.ui;
 
 import com.intellij.codeInsight.hint.HintUtil;
+import com.intellij.ide.DataManager;
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.actionSystem.ActionManager;
 import com.intellij.openapi.actionSystem.AnAction;
@@ -38,6 +39,7 @@ import com.intellij.ui.EditorTextField;
 import com.intellij.ui.ScreenUtil;
 import com.intellij.ui.awt.RelativePoint;
 import com.intellij.ui.popup.list.ListPopupImpl;
+import com.intellij.util.Consumer;
 import com.intellij.xdebugger.Obsolescent;
 import com.intellij.xdebugger.XDebuggerBundle;
 import com.intellij.xdebugger.XDebuggerManager;
@@ -48,9 +50,13 @@ import com.intellij.xdebugger.breakpoints.XBreakpointListener;
 import com.intellij.xdebugger.breakpoints.XBreakpointManager;
 import com.intellij.xdebugger.frame.XFullValueEvaluator;
 import com.intellij.xdebugger.frame.XValue;
+import com.intellij.xdebugger.frame.XValueModifier;
+import com.intellij.xdebugger.impl.XDebuggerUtilImpl;
 import com.intellij.xdebugger.impl.breakpoints.XBreakpointBase;
 import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointsDialogFactory;
 import com.intellij.xdebugger.impl.breakpoints.ui.XLightBreakpointPropertiesPanel;
+import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
+import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeState;
 import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -406,4 +412,35 @@ public class DebuggerUIUtil {
   public static boolean isObsolete(Object object) {
     return object instanceof Obsolescent && ((Obsolescent)object).isObsolete();
   }
+
+  public static void setTreeNodeValue(XValueNodeImpl valueNode, String text, Consumer<String> errorConsumer) {
+    XDebuggerTree tree = valueNode.getTree();
+    Project project = tree.getProject();
+    XValueModifier modifier = valueNode.getValueContainer().getModifier();
+    if (modifier == null) return;
+    XDebuggerTreeState treeState = XDebuggerTreeState.saveState(tree);
+    valueNode.setValueModificationStarted();
+    modifier.setValue(text, new XValueModifier.XModificationCallback() {
+      @Override
+      public void valueModified() {
+        if (isDetachedTree(tree)) {
+          AppUIUtil.invokeOnEdt(() -> tree.rebuildAndRestore(treeState));
+        }
+        XDebuggerUtilImpl.rebuildAllSessionsViews(project);
+      }
+
+      @Override
+      public void errorOccurred(@NotNull final String errorMessage) {
+        AppUIUtil.invokeOnEdt(() -> {
+          tree.rebuildAndRestore(treeState);
+          errorConsumer.consume(errorMessage);
+        });
+        XDebuggerUtilImpl.rebuildAllSessionsViews(project);
+      }
+
+      boolean isDetachedTree(XDebuggerTree tree) {
+        return XDebugSessionTab.TAB_KEY.getData(DataManager.getInstance().getDataContext(tree)) == null;
+      }
+    });
+  }
 }
index 112425d6b84d1de58cbe8b1101d61c2ddce833ac..bd32c766e0d8cfc6d2b8aaeaa3f5318600a3b48c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2015 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -29,26 +29,24 @@ import javax.swing.*;
 
 public final class TextViewer extends EditorTextField {
   private final boolean myEmbeddedIntoDialogWrapper;
-  private final boolean myUseSoftWraps;
 
-  public TextViewer(@NotNull Project project, boolean embeddedIntoDialogWrapper, boolean useSoftWraps) {
-    this(createDocument(""), project, embeddedIntoDialogWrapper, useSoftWraps);
+  public TextViewer(@NotNull String initialText, @NotNull Project project, boolean viewer) {
+    this(createDocument(initialText), project, true, viewer);
   }
 
   public TextViewer(@NotNull String initialText, @NotNull Project project) {
-    this(createDocument(initialText), project, false, true);
+    this(initialText, project, true);
   }
 
-  public TextViewer(@NotNull Document document, @NotNull Project project, boolean embeddedIntoDialogWrapper, boolean useSoftWraps) {
-    super(document, project, FileTypes.PLAIN_TEXT, true, false);
+  public TextViewer(@NotNull Document document, @NotNull Project project, boolean embeddedIntoDialogWrapper, boolean viewer) {
+    super(document, project, FileTypes.PLAIN_TEXT, viewer, false);
 
     myEmbeddedIntoDialogWrapper = embeddedIntoDialogWrapper;
-    myUseSoftWraps = useSoftWraps;
     setFontInheritedFromLAF(false);
   }
 
   private static Document createDocument(@NotNull String initialText) {
-    final Document document = EditorFactory.getInstance().createDocument(initialText);
+    final Document document = EditorFactory.getInstance().createDocument(StringUtil.convertLineSeparators(initialText));
     //if (document instanceof DocumentImpl) {
     //  ((DocumentImpl)document).setAcceptSlashR(true);
     //}
@@ -68,7 +66,7 @@ public final class TextViewer extends EditorTextField {
     editor.getScrollPane().setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
     editor.setEmbeddedIntoDialogWrapper(myEmbeddedIntoDialogWrapper);
     editor.getComponent().setPreferredSize(null);
-    editor.getSettings().setUseSoftWraps(myUseSoftWraps);
+    editor.getSettings().setUseSoftWraps(true);
 
     editor.setColorsScheme(DebuggerUIUtil.getColorScheme());
     return editor;
index 9352e3f9db0794c55e73e7ec7d79ad0c8c91cd40..c353e01488562cd0717676da72a00a617fb1fa97 100644 (file)
 package com.intellij.xdebugger.impl.ui.tree;
 
 import com.intellij.codeInsight.hint.HintManager;
-import com.intellij.ide.DataManager;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.ui.Messages;
 import com.intellij.ui.AppUIUtil;
 import com.intellij.ui.SimpleColoredComponent;
 import com.intellij.xdebugger.frame.XValueModifier;
 import com.intellij.xdebugger.frame.presentation.XValuePresentation;
-import com.intellij.xdebugger.impl.XDebuggerUtilImpl;
 import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl;
-import com.intellij.xdebugger.impl.ui.XDebugSessionTab;
+import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
 import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants;
 import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
 import com.intellij.xdebugger.impl.ui.tree.nodes.XValuePresentationUtil;
@@ -93,37 +91,17 @@ public class SetValueInplaceEditor extends XDebuggerTreeInplaceEditor {
     if (myModifier == null) return;
 
     myExpressionEditor.saveTextInHistory();
-    final XDebuggerTreeState treeState = XDebuggerTreeState.saveState(myTree);
-    myValueNode.setValueModificationStarted();
-    myModifier.setValue(myExpressionEditor.getExpression().getExpression(), new XValueModifier.XModificationCallback() {
-      @Override
-      public void valueModified() {
-        if (isDetachedTree(myTree)) {
-          AppUIUtil.invokeOnEdt(() -> myTree.rebuildAndRestore(treeState));
-        }
-        XDebuggerUtilImpl.rebuildAllSessionsViews(getProject());
-      }
-
-      @Override
-      public void errorOccurred(@NotNull final String errorMessage) {
-        AppUIUtil.invokeOnEdt(() -> {
-          myTree.rebuildAndRestore(treeState);
 
-          Editor editor = myExpressionEditor.getEditor();
-          if (editor != null) {
-            HintManager.getInstance().showErrorHint(editor, errorMessage);
-          }
-          else {
-            Messages.showErrorDialog(myTree, errorMessage);
-          }
-        });
-        XDebuggerUtilImpl.rebuildAllSessionsViews(getProject());
+    DebuggerUIUtil.setTreeNodeValue(myValueNode, myExpressionEditor.getExpression().getExpression(), errorMessage -> {
+      Editor editor = myExpressionEditor.getEditor();
+      if (editor != null) {
+        HintManager.getInstance().showErrorHint(editor, errorMessage);
       }
-
-      boolean isDetachedTree(XDebuggerTree tree) {
-        return XDebugSessionTab.TAB_KEY.getData(DataManager.getInstance().getDataContext(tree)) == null;
+      else {
+        Messages.showErrorDialog(myTree, errorMessage);
       }
     });
+
     super.doOKAction();
   }
 }