From af10749df336a671ef3c06f16da6c83a326fb3c4 Mon Sep 17 00:00:00 2001 From: Kirill Safonov Date: Wed, 1 Aug 2012 21:56:07 +0400 Subject: [PATCH] XDebugger: compare value with clipboard action (IDEA-89243), finish 'Load value' progress if evaluation failed --- .../CompareValueWithClipboardAction.java | 64 +-------- .../actions/ClipboardVsValueContents.java | 86 +++++++++++ .../CompareClipboardWithSelection.java | 17 +-- .../src/messages/ActionsBundle.properties | 3 + .../src/messages/DiffBundle.properties | 2 + .../src/messages/XDebuggerBundle.properties | 4 +- .../src/idea/LangActions.xml | 2 + .../actions/XCompareWithClipboardAction.java | 38 +++++ .../ui/tree/actions/XCopyValueAction.java | 107 +------------- .../tree/actions/XFetchValueActionBase.java | 134 ++++++++++++++++++ .../src/messages/DebuggerBundle.properties | 2 - 11 files changed, 276 insertions(+), 183 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/openapi/diff/actions/ClipboardVsValueContents.java create mode 100644 platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XCompareWithClipboardAction.java create mode 100644 platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XFetchValueActionBase.java diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/CompareValueWithClipboardAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/CompareValueWithClipboardAction.java index 24f5fa0fd12f..0a4f2a366ad2 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/CompareValueWithClipboardAction.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/CompareValueWithClipboardAction.java @@ -15,75 +15,17 @@ */ package com.intellij.debugger.actions; -import com.intellij.debugger.DebuggerBundle; import com.intellij.debugger.impl.DebuggerContextImpl; import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeImpl; -import com.intellij.openapi.diff.*; -import com.intellij.openapi.ide.CopyPasteManager; +import com.intellij.openapi.diff.DiffManager; +import com.intellij.openapi.diff.actions.ClipboardVsValueContents; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.SystemInfo; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.Transferable; /** * @author Jeka */ public class CompareValueWithClipboardAction extends BaseValueAction { protected void processText(final Project project, final String text, DebuggerTreeNodeImpl node, DebuggerContextImpl debuggerContext) { - DiffManager.getInstance().getDiffTool().show(new ClipboardSelectionContents(text, project)); - } - - private static class ClipboardSelectionContents extends DiffRequest { - private DiffContent[] myContents = null; - private final String myValue; - - public ClipboardSelectionContents(String value, Project project) { - super(project); - myValue = value; - } - - public String[] getContentTitles() { - return new String[] { - DiffBundle.message("diff.content.clipboard.content.title"), - DebuggerBundle.message("diff.content.selected.value") - }; - } - - @Override - public boolean isSafeToCallFromUpdate() { - return !SystemInfo.isMac; - } - - @NotNull - public DiffContent[] getContents() { - if (myContents != null) return myContents; - DiffContent clipboardContent = createClipboardContent(); - if (clipboardContent == null) clipboardContent = new SimpleContent(""); - - myContents = new DiffContent[2]; - myContents[0] = clipboardContent; - - myContents[1] = new SimpleContent(myValue); - return myContents; - } - - public String getWindowTitle() { - return DebuggerBundle.message("diff.clipboard.vs.value.dialog.title"); - } - - @Nullable - private static DiffContent createClipboardContent() { - Transferable content = CopyPasteManager.getInstance().getContents(); - if (content != null) { - try { - String text = (String) (content.getTransferData(DataFlavor.stringFlavor)); - return text != null ? new SimpleContent(text) : null; - } catch (Exception ignored) { } - } - return null; - } + DiffManager.getInstance().getDiffTool().show(new ClipboardVsValueContents(text, project)); } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/actions/ClipboardVsValueContents.java b/platform/platform-impl/src/com/intellij/openapi/diff/actions/ClipboardVsValueContents.java new file mode 100644 index 000000000000..966ed4685833 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/diff/actions/ClipboardVsValueContents.java @@ -0,0 +1,86 @@ +/* + * Copyright 2000-2012 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.openapi.diff.actions; + +import com.intellij.openapi.diff.DiffBundle; +import com.intellij.openapi.diff.DiffContent; +import com.intellij.openapi.diff.DiffRequest; +import com.intellij.openapi.diff.SimpleContent; +import com.intellij.openapi.ide.CopyPasteManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.SystemInfo; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; + +/** + * @author Jeka + */ +public class ClipboardVsValueContents extends DiffRequest { + + private DiffContent[] myContents = null; + private final String myValue; + + public ClipboardVsValueContents(String value, Project project) { + super(project); + myValue = value; + } + + public String[] getContentTitles() { + return new String[]{ + DiffBundle.message("diff.content.clipboard.content.title"), + DiffBundle.message("diff.content.selected.value") + }; + } + + @Override + public boolean isSafeToCallFromUpdate() { + return !SystemInfo.isMac; + } + + @NotNull + public DiffContent[] getContents() { + if (myContents != null) return myContents; + DiffContent clipboardContent = createClipboardContent(); + if (clipboardContent == null) clipboardContent = new SimpleContent(""); + + myContents = new DiffContent[2]; + myContents[0] = clipboardContent; + + myContents[1] = new SimpleContent(myValue); + return myContents; + } + + public String getWindowTitle() { + return DiffBundle.message("diff.clipboard.vs.value.dialog.title"); + } + + @Nullable + public static DiffContent createClipboardContent() { + Transferable content = CopyPasteManager.getInstance().getContents(); + if (content != null) { + try { + String text = (String)(content.getTransferData(DataFlavor.stringFlavor)); + return text != null ? new SimpleContent(text) : null; + } + catch (Exception ignored) { + } + } + return null; + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareClipboardWithSelection.java b/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareClipboardWithSelection.java index 230c58b55d50..dfeafd503c68 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareClipboardWithSelection.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareClipboardWithSelection.java @@ -22,16 +22,12 @@ import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.fileEditor.FileEditorManager; -import com.intellij.openapi.ide.CopyPasteManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.TextRange; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.Transferable; - public class CompareClipboardWithSelection extends BaseDiffAction { @Nullable protected DiffRequest getDiffData(DataContext dataContext) { @@ -68,7 +64,7 @@ public class CompareClipboardWithSelection extends BaseDiffAction { @NotNull public DiffContent[] getContents() { if (myContents != null) return myContents; - DiffContent clipboardContent = createClipboardContent(); + DiffContent clipboardContent = ClipboardVsValueContents.createClipboardContent(); if (clipboardContent == null) clipboardContent = new SimpleContent(""); myContents = new DiffContent[2]; myContents[0] = clipboardContent; @@ -97,16 +93,5 @@ public class CompareClipboardWithSelection extends BaseDiffAction { } } - @Nullable - private static DiffContent createClipboardContent() { - Transferable content = CopyPasteManager.getInstance().getContents(); - if (content != null) { - try { - String text = (String) (content.getTransferData(DataFlavor.stringFlavor)); - return text != null ? new SimpleContent(text) : null; - } catch (Exception ignored) { } - } - return null; - } } } diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index b8a4b1a5b3ec..abf46f4cb513 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -857,6 +857,8 @@ action.XDebugger.SetValue.text=Set Value... action.XDebugger.SetValue.description=Modify value of selected node action.XDebugger.CopyValue.text=Copy Value action.XDebugger.CopyValue.description=Copy value of selected node to clipboard +action.XDebugger.CompareValueWithClipboard.text=Compare Value with Clipboard +action.XDebugger.CompareValueWithClipboard.description=Compare value of selected node with clipboard text action.XDebugger.CopyName.text=Copy Name action.XDebugger.CopyName.description=Copy name of selected node to clipboard action.XDebugger.JumpToSource.text=Jump To Source @@ -879,6 +881,7 @@ action.Debugger.CopyValue.text=Copy Value action.Debugger.ViewText.text=View Text action.Debugger.ViewText.description=View text value of selected node in a separate pane action.Debugger.CompareValueWithClipboard.text=Compare Value with Clipboard +action.Debugger.CompareValueWithClipboard.description=Compare value of selected node with clipboard text action.Debugger.CustomizeContextView.text=Customize Data Views... action.Debugger.CustomizeThreadsView.text=Customize Threads View... action.Debugger.NewWatch.text=New Watch... diff --git a/platform/platform-resources-en/src/messages/DiffBundle.properties b/platform/platform-resources-en/src/messages/DiffBundle.properties index cc3d2496e947..511cadb718ad 100644 --- a/platform/platform-resources-en/src/messages/DiffBundle.properties +++ b/platform/platform-resources-en/src/messages/DiffBundle.properties @@ -78,3 +78,5 @@ diff.type.changed.name=Changed diff.type.deleted.name=Deleted diff.type.conflict.name=Conflict diff.type.none.name=None +diff.content.selected.value=Selected Value +diff.clipboard.vs.value.dialog.title=Clipboard vs Selected Value diff --git a/platform/platform-resources-en/src/messages/XDebuggerBundle.properties b/platform/platform-resources-en/src/messages/XDebuggerBundle.properties index 944b88a4bd86..d659517a20fc 100644 --- a/platform/platform-resources-en/src/messages/XDebuggerBundle.properties +++ b/platform/platform-resources-en/src/messages/XDebuggerBundle.properties @@ -93,4 +93,6 @@ debugger.threads.not.available=Threads are not available debugger.variables.not.available=Variables are not available debugger.no.watches=No watches debugger.no.breakpoints=No breakpoints -debugger.no.results=Type an expression and press 'Enter' \ No newline at end of file +debugger.no.results=Type an expression and press 'Enter' +load.value.task.error=Cannot load value\: {0} +load.value.task.text=Loading value \ No newline at end of file diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index fa1c4045d414..63a5238ea992 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -650,6 +650,7 @@ + @@ -690,6 +691,7 @@ + diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XCompareWithClipboardAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XCompareWithClipboardAction.java new file mode 100644 index 000000000000..99d6cf7e2d15 --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XCompareWithClipboardAction.java @@ -0,0 +1,38 @@ +/* + * Copyright 2000-2012 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.xdebugger.impl.ui.tree.actions; + +import com.intellij.openapi.diff.DiffManager; +import com.intellij.openapi.diff.actions.ClipboardVsValueContents; +import com.intellij.openapi.project.Project; +import com.intellij.util.ui.UIUtil; + +/** + * User: ksafonov + */ +public class XCompareWithClipboardAction extends XFetchValueActionBase { + + @Override + protected void handle(final Project project, final String value) { + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + DiffManager.getInstance().getDiffTool().show(new ClipboardVsValueContents(value, project)); + } + }); + } + +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XCopyValueAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XCopyValueAction.java index 7ef5c7963ffe..661371054fcc 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XCopyValueAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XCopyValueAction.java @@ -15,116 +15,17 @@ */ package com.intellij.xdebugger.impl.ui.tree.actions; -import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.ide.CopyPasteManager; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.Task; -import com.intellij.util.Alarm; -import com.intellij.util.concurrency.Semaphore; -import com.intellij.xdebugger.XDebugSession; -import com.intellij.xdebugger.frame.XFullValueEvaluator; -import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import com.intellij.openapi.project.Project; -import java.awt.*; import java.awt.datatransfer.StringSelection; /** * @author nik */ -public class XCopyValueAction extends XDebuggerTreeActionBase { - protected void perform(final XValueNodeImpl node, @NotNull final String nodeName, final AnActionEvent e) { - XFullValueEvaluator fullValueEvaluator = node.getFullValueEvaluator(); - if (fullValueEvaluator == null) { - String value = node.getValue(); - copyToClipboard(value); - return; - } - - final XDebugSession session = node.getTree().getSession(); - startCopying(fullValueEvaluator, session); - } - - private static void startCopying(@NotNull XFullValueEvaluator fullValueEvaluator, final @NotNull XDebugSession session) { - final CopyValueEvaluationCallback callback = new CopyValueEvaluationCallback(session); - fullValueEvaluator.startEvaluation(callback); - new Alarm().addRequest(new Runnable() { - @Override - public void run() { - callback.showProgress(); - } - }, 500); - } - - private static void copyToClipboard(String value) { +public class XCopyValueAction extends XFetchValueActionBase { + @Override + protected void handle(final Project project, final String value) { CopyPasteManager.getInstance().setContents(new StringSelection(value)); } - - protected boolean isEnabled(final XValueNodeImpl node) { - return super.isEnabled(node) && node.getValue() != null; - } - - private static class CopyValueEvaluationCallback implements XFullValueEvaluator.XFullValueEvaluationCallback { - private final XDebugSession mySession; - private volatile boolean myEvaluated; - private volatile boolean myCanceled; - private Semaphore mySemaphore; - - public CopyValueEvaluationCallback(XDebugSession session) { - mySession = session; - mySemaphore = new Semaphore(); - mySemaphore.down(); - } - - @Override - public void evaluated(@NotNull String fullValue) { - copyToClipboard(fullValue); - myEvaluated = true; - mySemaphore.up(); - } - - @Override - public void evaluated(@NotNull String fullValue, @Nullable Font font) { - evaluated(fullValue); - } - - @Override - public void errorOccurred(@NotNull String errorMessage) { - mySession.reportError("Cannot copy value: " + errorMessage); - } - - @Override - public boolean isObsolete() { - return myCanceled; - } - - public void showProgress() { - if (myEvaluated || mySession.isStopped()) return; - - new Task.Backgroundable(mySession.getProject(), "Copying Value") { - @Override - public void run(@NotNull ProgressIndicator indicator) { - indicator.setIndeterminate(true); - indicator.setText("Fetching value..."); - int i = 0; - while (!myCanceled && !myEvaluated) { - indicator.checkCanceled(); - indicator.setFraction(((i++)%100)*0.01); - mySemaphore.waitFor(300); - } - } - - @Override - public boolean shouldStartInBackground() { - return false; - } - - @Override - public void onCancel() { - myCanceled = true; - } - }.queue(); - } - } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XFetchValueActionBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XFetchValueActionBase.java new file mode 100644 index 000000000000..8835d70c73d3 --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XFetchValueActionBase.java @@ -0,0 +1,134 @@ +/* + * Copyright 2000-2012 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.xdebugger.impl.ui.tree.actions; + +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.Project; +import com.intellij.util.Alarm; +import com.intellij.util.concurrency.Semaphore; +import com.intellij.xdebugger.XDebugSession; +import com.intellij.xdebugger.XDebuggerBundle; +import com.intellij.xdebugger.frame.XFullValueEvaluator; +import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.awt.*; + +/** + * User: ksafonov + */ +public abstract class XFetchValueActionBase extends XDebuggerTreeActionBase { + + protected abstract void handle(final Project project, final String value); + + protected void perform(final XValueNodeImpl node, @NotNull final String nodeName, final AnActionEvent e) { + XFullValueEvaluator fullValueEvaluator = node.getFullValueEvaluator(); + if (fullValueEvaluator == null) { + String value = node.getValue(); + handle(node.getTree().getProject(), value); + return; + } + + final XDebugSession session = node.getTree().getSession(); + startFetchingValue(fullValueEvaluator, session); + } + + private void startFetchingValue(@NotNull XFullValueEvaluator fullValueEvaluator, + final @NotNull XDebugSession session) { + final CopyValueEvaluationCallback callback = new CopyValueEvaluationCallback(session); + fullValueEvaluator.startEvaluation(callback); + new Alarm().addRequest(new Runnable() { + @Override + public void run() { + callback.showProgress(); + } + }, 500); + } + + protected boolean isEnabled(final XValueNodeImpl node) { + return super.isEnabled(node) && node.getValue() != null; + } + + private class CopyValueEvaluationCallback implements XFullValueEvaluator.XFullValueEvaluationCallback { + private final XDebugSession mySession; + private volatile boolean myEvaluated; + private volatile boolean myCanceled; + private Semaphore mySemaphore; + + public CopyValueEvaluationCallback(XDebugSession session) { + mySession = session; + mySemaphore = new Semaphore(); + mySemaphore.down(); + } + + @Override + public void evaluated(@NotNull String fullValue) { + handle(mySession.getProject(), fullValue); + evaluationComplete(); + } + + @Override + public void evaluated(@NotNull String fullValue, @Nullable Font font) { + evaluated(fullValue); + } + + @Override + public void errorOccurred(@NotNull String errorMessage) { + mySession.reportError(XDebuggerBundle.message("load.value.task.error", errorMessage)); + evaluationComplete(); + } + + private void evaluationComplete() { + myEvaluated = true; + mySemaphore.up(); + } + + @Override + public boolean isObsolete() { + return myCanceled; + } + + public void showProgress() { + if (myEvaluated || mySession.isStopped()) return; + + new Task.Backgroundable(mySession.getProject(), XDebuggerBundle.message("load.value.task.text")) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + indicator.setIndeterminate(true); + int i = 0; + while (!myCanceled && !myEvaluated) { + indicator.checkCanceled(); + indicator.setFraction(((i++) % 100) * 0.01); + mySemaphore.waitFor(300); + } + } + + @Override + public boolean shouldStartInBackground() { + return false; + } + + @Override + public void onCancel() { + myCanceled = true; + } + }.queue(); + } + } +} diff --git a/resources-en/src/messages/DebuggerBundle.properties b/resources-en/src/messages/DebuggerBundle.properties index 6704cc25f199..1fb3caa7bfd9 100644 --- a/resources-en/src/messages/DebuggerBundle.properties +++ b/resources-en/src/messages/DebuggerBundle.properties @@ -443,6 +443,4 @@ frame.panel.frames.not.available=Frames not available for unsuspended thread error.corrupt.debug.info=Debug info might be corrupt: {0} action.kill.process.text=Kill Process action.kill.process.description=Forcibly terminate debugged application -diff.clipboard.vs.value.dialog.title=Clipboard vs Selected Value -diff.content.selected.value=Selected Value evaluation.error.unknown.method.return.type=Cannot resolve method return type: {0}