diff options
Diffstat (limited to 'platform/xdebugger-impl')
31 files changed, 686 insertions, 321 deletions
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java index 762855510a1e..8ee2f1ee587a 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java @@ -25,7 +25,6 @@ import com.intellij.execution.process.ProcessAdapter; import com.intellij.execution.process.ProcessEvent; import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.runners.ExecutionEnvironment; -import com.intellij.execution.runners.ProgramRunner; import com.intellij.execution.ui.ConsoleView; import com.intellij.execution.ui.ConsoleViewContentType; import com.intellij.execution.ui.RunContentDescriptor; @@ -108,10 +107,9 @@ public class XDebugSessionImpl implements XDebugSession { private final EventDispatcher<XDebugSessionListener> myDispatcher = EventDispatcher.create(XDebugSessionListener.class); private final Project myProject; private final @Nullable ExecutionEnvironment myEnvironment; - private final @Nullable ProgramRunner myRunner; private boolean myStopped; private boolean myPauseActionSupported; - private boolean myShowTabOnSuspend; + private final AtomicBoolean myShowTabOnSuspend; private final List<AnAction> myRestartActions = new SmartList<AnAction>(); private final List<AnAction> myExtraStopActions = new SmartList<AnAction>(); private final List<AnAction> myExtraActions = new SmartList<AnAction>(); @@ -121,23 +119,19 @@ public class XDebugSessionImpl implements XDebugSession { private volatile boolean breakpointsInitialized; private boolean autoInitBreakpoints = true; - public XDebugSessionImpl(@NotNull ExecutionEnvironment environment, - @Nullable ProgramRunner runner, - @NotNull XDebuggerManagerImpl debuggerManager) { - this(environment, runner, debuggerManager, environment.getRunProfile().getName(), environment.getRunProfile().getIcon(), false); + public XDebugSessionImpl(@NotNull ExecutionEnvironment environment, @NotNull XDebuggerManagerImpl debuggerManager) { + this(environment, debuggerManager, environment.getRunProfile().getName(), environment.getRunProfile().getIcon(), false); } public XDebugSessionImpl(@Nullable ExecutionEnvironment environment, - @Nullable ProgramRunner runner, @NotNull XDebuggerManagerImpl debuggerManager, @NotNull String sessionName, @Nullable Icon icon, boolean showTabOnSuspend) { myEnvironment = environment; - myRunner = runner; mySessionName = sessionName; myDebuggerManager = debuggerManager; - myShowTabOnSuspend = showTabOnSuspend; + myShowTabOnSuspend = new AtomicBoolean(showTabOnSuspend); myProject = debuggerManager.getProject(); ValueLookupManager.getInstance(myProject).startListening(); myIcon = icon; @@ -158,7 +152,7 @@ public class XDebugSessionImpl implements XDebugSession { } private void assertSessionTabInitialized() { - if (myShowTabOnSuspend) { + if (myShowTabOnSuspend.get()) { LOG.error("Debug tool window isn't shown yet because debug process isn't suspended"); } else { @@ -176,6 +170,7 @@ public class XDebugSessionImpl implements XDebugSession { myPauseActionSupported = isSupported; } + @NotNull public List<AnAction> getRestartActions() { return myRestartActions; } @@ -186,6 +181,7 @@ public class XDebugSessionImpl implements XDebugSession { } } + @NotNull public List<AnAction> getExtraActions() { return myExtraActions; } @@ -208,7 +204,7 @@ public class XDebugSessionImpl implements XDebugSession { @Override public void rebuildViews() { - if (!myShowTabOnSuspend && mySessionTab != null) { + if (!myShowTabOnSuspend.get() && mySessionTab != null) { mySessionTab.rebuildViews(); } } @@ -262,7 +258,7 @@ public class XDebugSessionImpl implements XDebugSession { return myCurrentPosition; } - public XDebugSessionTab init(final XDebugProcess process, @NotNull final XDebugSessionData sessionData) { + public XDebugSessionTab init(@NotNull XDebugProcess process, @NotNull XDebugSessionData sessionData, @Nullable RunContentDescriptor contentToReuse) { LOG.assertTrue(myDebugProcess == null); myDebugProcess = process; mySessionData = sessionData; @@ -279,8 +275,8 @@ public class XDebugSessionImpl implements XDebugSession { }); //todo[nik] make 'createConsole()' method return ConsoleView myConsoleView = (ConsoleView)myDebugProcess.createConsole(); - if (!myShowTabOnSuspend) { - initSessionTab(); + if (!myShowTabOnSuspend.get()) { + initSessionTab(contentToReuse); } return mySessionTab; @@ -316,11 +312,12 @@ public class XDebugSessionImpl implements XDebugSession { @Override public RunnerLayoutUi getUI() { assertSessionTabInitialized(); + assert mySessionTab != null; return mySessionTab.getUi(); } - private void initSessionTab() { - mySessionTab = new XDebugSessionTab(myProject, this, myIcon, myEnvironment, myRunner); + private void initSessionTab(@Nullable RunContentDescriptor contentToReuse) { + mySessionTab = XDebugSessionTab.create(this, myIcon, myEnvironment, contentToReuse); myDebugProcess.sessionInitialized(); } @@ -536,12 +533,12 @@ public class XDebugSessionImpl implements XDebugSession { private void doResume() { if (!myPaused.getAndSet(false)) return; - final XSourcePosition oldPosition = myCurrentPosition; myDispatcher.getMulticaster().beforeSessionResume(); myDebuggerManager.setActiveSession(this, null, false, null); mySuspendContext = null; myCurrentExecutionStack = null; myCurrentStackFrame = null; + adjustMouseTrackingCounter(myCurrentPosition, -1); myCurrentPosition = null; myActiveNonLineBreakpoint = null; UIUtil.invokeLaterIfNeeded(new Runnable() { @@ -550,9 +547,6 @@ public class XDebugSessionImpl implements XDebugSession { if (mySessionTab != null) { mySessionTab.getUi().clearAttractionBy(XDebuggerUIConstants.LAYOUT_VIEW_BREAKPOINT_CONDITION); } - if (oldPosition != null) { - adjustMouseTrackingCounter(oldPosition, -1); - } } }); myDispatcher.getMulticaster().sessionResumed(); @@ -794,32 +788,37 @@ public class XDebugSessionImpl implements XDebugSession { if (myCurrentPosition != null) { myDebuggerManager.setActiveSession(this, myCurrentPosition, false, getPositionIconRenderer(true)); } - UIUtil.invokeLaterIfNeeded(new Runnable() { - @Override - public void run() { - if (myShowTabOnSuspend) { - myShowTabOnSuspend = false; - initSessionTab(); + adjustMouseTrackingCounter(myCurrentPosition, 1); + + if (myShowTabOnSuspend.compareAndSet(true, false)) { + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + initSessionTab(null); showSessionTab(); } - if (myCurrentPosition != null) { - adjustMouseTrackingCounter(myCurrentPosition, 1); - } - } - }); + }); + } + myDispatcher.getMulticaster().sessionPaused(); } - private void adjustMouseTrackingCounter(@NotNull XSourcePosition position, int increment) { - if (ApplicationManager.getApplication().isUnitTestMode()) return; + private void adjustMouseTrackingCounter(final XSourcePosition position, final int increment) { + if (position == null || ApplicationManager.getApplication().isUnitTestMode()) return; - Editor editor = XDebuggerUtilImpl.createEditor(new OpenFileDescriptor(myProject, position.getFile())); - if (editor != null) { - JComponent component = editor.getComponent(); - Object o = component.getClientProperty(EditorImpl.IGNORE_MOUSE_TRACKING); - Integer value = ((o instanceof Integer) ? (Integer)o : 0) + increment; - component.putClientProperty(EditorImpl.IGNORE_MOUSE_TRACKING, value > 0 ? value : null); - } + // need to always invoke later to maintain order of increment/decrement + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + Editor editor = XDebuggerUtilImpl.createEditor(new OpenFileDescriptor(myProject, position.getFile())); + if (editor != null) { + JComponent component = editor.getComponent(); + Object o = component.getClientProperty(EditorImpl.IGNORE_MOUSE_TRACKING); + Integer value = ((o instanceof Integer) ? (Integer)o : 0) + increment; + component.putClientProperty(EditorImpl.IGNORE_MOUSE_TRACKING, value > 0 ? value : null); + } + } + }); } @Override @@ -851,6 +850,12 @@ public class XDebugSessionImpl implements XDebugSession { if (!myProject.isDisposed()) { myProject.getMessageBus().syncPublisher(XDebuggerManager.TOPIC).processStopped(myDebugProcess); } + + if (mySessionTab != null) { + mySessionTab.detachFromSession(); + } + + adjustMouseTrackingCounter(myCurrentPosition, -1); myCurrentPosition = null; myCurrentExecutionStack = null; myCurrentStackFrame = null; diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java index b974150d2c56..2e6f91d43924 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java @@ -23,10 +23,8 @@ import com.intellij.execution.executors.DefaultDebugExecutor; import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.runners.ProgramRunner; -import com.intellij.execution.ui.ExecutionConsole; -import com.intellij.execution.ui.RunContentDescriptor; -import com.intellij.execution.ui.RunContentManagerImpl; -import com.intellij.execution.ui.RunContentWithExecutorListener; +import com.intellij.execution.runners.RunContentBuilder; +import com.intellij.execution.ui.*; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.*; @@ -119,11 +117,11 @@ public class XDebuggerManagerImpl extends XDebuggerManager } }); - messageBusConnection.subscribe(RunContentManagerImpl.RUN_CONTENT_TOPIC, new RunContentWithExecutorListener() { + messageBusConnection.subscribe(RunContentManager.TOPIC, new RunContentWithExecutorListener() { @Override - public void contentSelected(RunContentDescriptor descriptor, @NotNull Executor executor) { - if (executor.equals(DefaultDebugExecutor.getDebugExecutorInstance())) { - final XDebugSessionImpl session = mySessions.get(descriptor.getProcessHandler()); + public void contentSelected(@Nullable RunContentDescriptor descriptor, @NotNull Executor executor) { + if (descriptor != null && executor.equals(DefaultDebugExecutor.getDebugExecutorInstance())) { + XDebugSessionImpl session = mySessions.get(descriptor.getProcessHandler()); if (session != null) { session.activateSession(); } @@ -134,8 +132,8 @@ public class XDebuggerManagerImpl extends XDebuggerManager } @Override - public void contentRemoved(RunContentDescriptor descriptor, @NotNull Executor executor) { - if (executor.equals(DefaultDebugExecutor.getDebugExecutorInstance())) { + public void contentRemoved(@Nullable RunContentDescriptor descriptor, @NotNull Executor executor) { + if (descriptor != null && executor.equals(DefaultDebugExecutor.getDebugExecutorInstance())) { mySessions.remove(descriptor.getProcessHandler()); mySessionData.remove(descriptor); XDebugSessionTab tab = mySessionTabs.remove(descriptor); @@ -169,11 +167,17 @@ public class XDebuggerManagerImpl extends XDebuggerManager @Override @NotNull - public XDebugSession startSession(@NotNull final ProgramRunner runner, - @NotNull final ExecutionEnvironment environment, - @Nullable final RunContentDescriptor contentToReuse, - @NotNull final XDebugProcessStarter processStarter) throws ExecutionException { - return startSession(contentToReuse, processStarter, new XDebugSessionImpl(environment, runner, this)); + public XDebugSession startSession(@NotNull ProgramRunner runner, + @NotNull ExecutionEnvironment environment, + @Nullable RunContentDescriptor contentToReuse, + @NotNull XDebugProcessStarter processStarter) throws ExecutionException { + return startSession(contentToReuse, processStarter, new XDebugSessionImpl(RunContentBuilder.fix(environment, runner), this)); + } + + @Override + @NotNull + public XDebugSession startSession(@NotNull ExecutionEnvironment environment, @NotNull XDebugProcessStarter processStarter) throws ExecutionException { + return startSession(environment.getContentToReuse(), processStarter, new XDebugSessionImpl(environment, this)); } @Override @@ -193,10 +197,12 @@ public class XDebuggerManagerImpl extends XDebuggerManager @NotNull @Override - public XDebugSession startSessionAndShowTab(@NotNull String sessionName, final Icon icon, @Nullable RunContentDescriptor contentToReuse, + public XDebugSession startSessionAndShowTab(@NotNull String sessionName, + Icon icon, + @Nullable RunContentDescriptor contentToReuse, boolean showToolWindowOnSuspendOnly, @NotNull XDebugProcessStarter starter) throws ExecutionException { - XDebugSessionImpl session = startSession(contentToReuse, starter, new XDebugSessionImpl(null, null, this, sessionName, + XDebugSessionImpl session = startSession(contentToReuse, starter, new XDebugSessionImpl(null, this, sessionName, icon, showToolWindowOnSuspendOnly)); if (!showToolWindowOnSuspendOnly) { session.showSessionTab(); @@ -206,8 +212,9 @@ public class XDebuggerManagerImpl extends XDebuggerManager return session; } - private XDebugSessionImpl startSession(final RunContentDescriptor contentToReuse, final XDebugProcessStarter processStarter, - final XDebugSessionImpl session) throws ExecutionException { + private XDebugSessionImpl startSession(@Nullable RunContentDescriptor contentToReuse, + @NotNull XDebugProcessStarter processStarter, + @NotNull XDebugSessionImpl session) throws ExecutionException { XDebugProcess process = processStarter.start(session); myProject.getMessageBus().syncPublisher(TOPIC).processStarted(process); @@ -222,7 +229,7 @@ public class XDebuggerManagerImpl extends XDebuggerManager ((XDebugProcessConfiguratorStarter)processStarter).configure(oldSessionData); } - session.init(process, oldSessionData); + session.init(process, oldSessionData, contentToReuse); mySessions.put(session.getDebugProcess().getProcessHandler(), session); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerWatchesManager.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerWatchesManager.java index e803453eb662..4bcc6753925e 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerWatchesManager.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerWatchesManager.java @@ -16,6 +16,7 @@ package com.intellij.xdebugger.impl; import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.xmlb.annotations.AbstractCollection; import com.intellij.util.xmlb.annotations.Attribute; @@ -67,11 +68,13 @@ public class XDebuggerWatchesManager implements PersistentStateComponent<XDebugg watches.clear(); if (state != null) { for (ConfigurationState expressionState : state.expressions) { - WatchState[] states = expressionState.myExpressionStates; - XExpression[] expressions = new XExpression[states.length]; - for (int i = 0; i < states.length; i++) { - expressions[i] = states[i].toXExpression(); - } + XExpression[] expressions = ContainerUtil.mapNotNull(expressionState.myExpressionStates, + new Function<WatchState, XExpression>() { + @Override + public XExpression fun(WatchState state) { + return state.toXExpression(); + } + }, new XExpression[0]); watches.put(expressionState.myName, expressions); } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EditBreakpointAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EditBreakpointAction.java index a9f15890bbea..6384629d19a8 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EditBreakpointAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EditBreakpointAction.java @@ -19,13 +19,13 @@ import com.intellij.idea.ActionsBundle; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.markup.GutterIconRenderer; +import com.intellij.openapi.project.DumbAware; import com.intellij.xdebugger.impl.DebuggerSupport; import org.jetbrains.annotations.NotNull; -public class EditBreakpointAction extends XDebuggerActionBase { +public class EditBreakpointAction extends XDebuggerActionBase implements DumbAware { public static class ContextAction extends AnAction { private final GutterIconRenderer myRenderer; diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XExpressionImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XExpressionImpl.java index b966377a47ba..d049356247b4 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XExpressionImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XExpressionImpl.java @@ -18,6 +18,7 @@ package com.intellij.xdebugger.impl.breakpoints; import com.intellij.lang.Language; import com.intellij.xdebugger.XExpression; import com.intellij.xdebugger.evaluation.EvaluationMode; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -65,12 +66,12 @@ public class XExpressionImpl implements XExpression { return myMode; } - @Nullable + @Contract("null -> null; !null -> !null") public static XExpressionImpl fromText(@Nullable String text) { return text != null ? new XExpressionImpl(text, null, null, EvaluationMode.EXPRESSION) : null; } - @Nullable + @Contract("null, _ -> null; !null, _ -> !null") public static XExpressionImpl fromText(@Nullable String text, EvaluationMode mode) { return text != null ? new XExpressionImpl(text, null, null, mode) : null; } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XExpressionState.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XExpressionState.java index 205cc2d9498d..65dc92e97ec1 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XExpressionState.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XExpressionState.java @@ -16,10 +16,12 @@ package com.intellij.xdebugger.impl.breakpoints; import com.intellij.lang.Language; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.xmlb.annotations.Attribute; import com.intellij.util.xmlb.annotations.Text; import com.intellij.xdebugger.XExpression; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author egor @@ -65,8 +67,13 @@ public class XExpressionState { } } + @Nullable public XExpression toXExpression() { checkConverted(); + // old versions may have empty expressions serialized + if (StringUtil.isEmptyOrSpaces(myExpression)) { + return null; + } return new XExpressionImpl(myExpression, Language.findLanguageByID(myLanguage), myCustomInfo); } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java new file mode 100644 index 000000000000..a3aa8ec43fc5 --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java @@ -0,0 +1,75 @@ +/* + * 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.xdebugger.impl.evaluate; + +import com.intellij.openapi.editor.EditorLinePainter; +import com.intellij.openapi.editor.LineExtensionInfo; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.registry.Registry; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.ui.JBColor; +import com.intellij.ui.SimpleColoredText; +import com.intellij.xdebugger.frame.presentation.XValuePresentation; +import com.intellij.xdebugger.impl.frame.XVariablesView; +import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; +import com.intellij.xdebugger.impl.ui.tree.nodes.XValueTextRendererImpl; +import org.jetbrains.annotations.NotNull; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +/** + * @author Konstantin Bulenkov + */ +public class XDebuggerEditorLinePainter extends EditorLinePainter { + @Override + public Collection<LineExtensionInfo> getLineExtensions(@NotNull Project project, @NotNull VirtualFile file, int lineNumber) { + if (!Registry.is("ide.debugger.inline")) { + return null; + } + + Map<Pair<VirtualFile, Integer>, Set<XValueNodeImpl>> map = project.getUserData(XVariablesView.DEBUG_VARIABLES); + if (map != null) { + Set<XValueNodeImpl> values = map.get(Pair.create(file, lineNumber)); + if (values != null && !values.isEmpty()) { + ArrayList<LineExtensionInfo> result = new ArrayList<LineExtensionInfo>(); + for (XValueNodeImpl value : values) { + SimpleColoredText text = new SimpleColoredText(); + XValueTextRendererImpl renderer = new XValueTextRendererImpl(text); + final XValuePresentation presentation = value.getValuePresentation(); + if (presentation == null) continue; + if (presentation instanceof XValueCompactPresentation) { + ((XValueCompactPresentation)presentation).renderValue(renderer, value); + } else { + presentation.renderValue(renderer); + } + final Color color = new JBColor(new Color(61, 128, 101), new Color(61, 128, 101)); + result.add(new LineExtensionInfo(" " + value.getName() + ": ", color, null, null, Font.PLAIN)); + for (String s : text.getTexts()) { + result.add(new LineExtensionInfo(s, color, null, null, Font.PLAIN)); + } + } + return result; + } + } + + return null; + } +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java index bee9b3d91fd7..37da856156ea 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java @@ -129,6 +129,7 @@ public class XDebuggerEvaluationDialog extends DialogWrapper { evaluate(); } + @Override protected void createDefaultActions() { super.createDefaultActions(); myOKAction = new OkAction(){ diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XValueCompactPresentation.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XValueCompactPresentation.java new file mode 100644 index 000000000000..f34b5afe1154 --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XValueCompactPresentation.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.xdebugger.impl.evaluate; + +import com.intellij.xdebugger.frame.presentation.XValuePresentation; +import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Konstantin Bulenkov + */ +public interface XValueCompactPresentation { + void renderValue(@NotNull XValuePresentation.XValueTextRenderer renderer, @Nullable XValueNodeImpl node); +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/AbstractValueHint.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/AbstractValueHint.java index 5a956450952a..7b860b49d255 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/AbstractValueHint.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/AbstractValueHint.java @@ -178,6 +178,9 @@ public abstract class AbstractValueHint { } protected boolean showHint(final JComponent component) { + if (myCurrentHint != null) { + myCurrentHint.hide(); + } myCurrentHint = new LightweightHint(component); myCurrentHint.addHintListener(new HintListener() { @Override diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/DebuggerFramesList.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/DebuggerFramesList.java index 41dd52bcc3b9..18ef7cecd450 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/DebuggerFramesList.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/DebuggerFramesList.java @@ -39,6 +39,7 @@ public abstract class DebuggerFramesList extends JBList implements OccurenceNavi getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); setCellRenderer(createListRenderer()); getSelectionModel().addListSelectionListener(new ListSelectionListener() { + @Override public void valueChanged(final ListSelectionEvent e) { if (!e.getValueIsAdjusting()) { onFrameChanged(getSelectedValue()); @@ -49,6 +50,7 @@ public abstract class DebuggerFramesList extends JBList implements OccurenceNavi getEmptyText().setText(XDebuggerBundle.message("debugger.frames.not.available")); } + @Override public DefaultListModel getModel() { return (DefaultListModel)super.getModel(); } @@ -61,19 +63,23 @@ public abstract class DebuggerFramesList extends JBList implements OccurenceNavi return getModel().getSize(); } + @Override public String getNextOccurenceActionName() { return XDebuggerBundle.message("action.next.frame.text"); } + @Override public String getPreviousOccurenceActionName() { return XDebuggerBundle.message("action.previous.frame.text"); } + @Override public OccurenceInfo goNextOccurence() { setSelectedIndex(getSelectedIndex() + 1); return createInfo(); } + @Override public OccurenceInfo goPreviousOccurence() { setSelectedIndex(getSelectedIndex() - 1); return createInfo(); @@ -83,10 +89,12 @@ public abstract class DebuggerFramesList extends JBList implements OccurenceNavi return OccurenceInfo.position(getSelectedIndex(), getElementCount()); } + @Override public boolean hasNextOccurence() { return getSelectedIndex() < getElementCount() - 1; } + @Override public boolean hasPreviousOccurence() { return getSelectedIndex() > 0; } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebugView.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebugView.java index 85ff7b2c2357..0007ec2f9997 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebugView.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebugView.java @@ -15,14 +15,66 @@ */ package com.intellij.xdebugger.impl.frame; +import com.intellij.execution.ui.layout.ViewContext; +import com.intellij.ide.DataManager; import com.intellij.openapi.Disposable; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.ui.content.ContentManager; +import com.intellij.util.SingleAlarm; +import com.intellij.xdebugger.XDebugSession; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.awt.*; +import java.util.EventObject; /** * @author nik */ -public interface XDebugView extends Disposable { - enum SessionEvent {PAUSED, BEFORE_RESUME, RESUMED, STOPPED, FRAME_CHANGED, SETTINGS_CHANGED} +public abstract class XDebugView implements Disposable { + public enum SessionEvent {PAUSED, BEFORE_RESUME, RESUMED, STOPPED, FRAME_CHANGED, SETTINGS_CHANGED} + + private final SingleAlarm myClearAlarm; + private static final int VIEW_CLEAR_DELAY = 100; //ms + + public XDebugView() { + myClearAlarm = new SingleAlarm(new Runnable() { + @Override + public void run() { + clear(); + } + }, VIEW_CLEAR_DELAY, this); + } + + protected final void requestClear() { + myClearAlarm.cancelAndRequest(); + } + + protected final void cancelClear() { + myClearAlarm.cancel(); + } + + protected abstract void clear(); + + public abstract void processSessionEvent(@NotNull SessionEvent event); + + @Nullable + protected static XDebugSession getSession(@NotNull EventObject e) { + Component component = e.getSource() instanceof Component ? (Component)e.getSource() : null; + return component == null ? null : getSession(component); + } - void processSessionEvent(@NotNull SessionEvent event); + @Nullable + public static XDebugSession getSession(@NotNull Component component) { + DataContext dataContext = DataManager.getInstance().getDataContext(component); + ViewContext viewContext = ViewContext.CONTEXT_KEY.getData(dataContext); + ContentManager contentManager = viewContext == null ? null : viewContext.getContentManager(); + if (contentManager != null) { + XDebugSession session = XDebugSession.DATA_KEY.getData(DataManager.getInstance().getDataContext(contentManager.getComponent())); + if (session != null) { + return session; + } + } + return XDebugSession.DATA_KEY.getData(dataContext); + } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebugViewSessionListener.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebugViewSessionListener.java index d265005d3a34..d790113b1816 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebugViewSessionListener.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebugViewSessionListener.java @@ -15,8 +15,8 @@ */ package com.intellij.xdebugger.impl.frame; -import com.intellij.openapi.project.Project; import com.intellij.ui.AppUIUtil; +import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XDebugSessionAdapter; import org.jetbrains.annotations.NotNull; @@ -25,15 +25,15 @@ import org.jetbrains.annotations.NotNull; */ public class XDebugViewSessionListener extends XDebugSessionAdapter { private final XDebugView myDebugView; - private final Project myProject; + private final XDebugSession session; - public XDebugViewSessionListener(@NotNull XDebugView debugView, @NotNull Project project) { + public XDebugViewSessionListener(@NotNull XDebugView debugView, @NotNull XDebugSession session) { myDebugView = debugView; - myProject = project; + this.session = session; } private void onSessionEvent(final @NotNull XDebugView.SessionEvent event) { - AppUIUtil.invokeLaterIfProjectAlive(myProject, new Runnable() { + AppUIUtil.invokeLaterIfProjectAlive(session.getProject(), new Runnable() { @Override public void run() { myDebugView.processSessionEvent(event); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebuggerFramesList.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebuggerFramesList.java index f4b6c2caee8e..9b39ad63deb8 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebuggerFramesList.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebuggerFramesList.java @@ -27,6 +27,7 @@ import com.intellij.util.ui.UIUtil; import com.intellij.xdebugger.XDebuggerBundle; import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.frame.XStackFrame; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; @@ -84,7 +85,7 @@ public class XDebuggerFramesList extends DebuggerFramesList { private XStackFrame mySelectedFrame; - public XDebuggerFramesList(Project project) { + public XDebuggerFramesList(@NotNull Project project) { super(project); doInit(); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XFramesView.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XFramesView.java index b7c5f4bf9746..b98440b5d69f 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XFramesView.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XFramesView.java @@ -22,6 +22,7 @@ import com.intellij.openapi.actionSystem.ActionPlaces; import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.*; @@ -29,6 +30,7 @@ import com.intellij.ui.border.CustomLineBorder; import com.intellij.ui.components.panels.Wrapper; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; +import com.intellij.util.containers.TransferToEDTQueue; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.frame.XExecutionStack; import com.intellij.xdebugger.frame.XStackFrame; @@ -53,46 +55,47 @@ import java.util.List; /** * @author nik */ -public class XFramesView implements XDebugView { +public class XFramesView extends XDebugView { private final JPanel myMainPanel; private final XDebuggerFramesList myFramesList; private final ComboBox myThreadComboBox; private final Set<XExecutionStack> myExecutionStacks = ContainerUtil.newHashSet(); - @NotNull private final XDebugSession mySession; private XExecutionStack mySelectedStack; private boolean myListenersEnabled; private final Map<XExecutionStack, StackFramesListBuilder> myBuilders = new HashMap<XExecutionStack, StackFramesListBuilder>(); private final ActionToolbarImpl myToolbar; private final Wrapper myThreadsPanel; private boolean myThreadsCalculated = false; + private final TransferToEDTQueue<Runnable> myLaterInvocator = TransferToEDTQueue.createRunnableMerger("XFramesView later invocator", 50); - public XFramesView(@NotNull final XDebugSession session) { - mySession = session; - + public XFramesView(@NotNull Project project) { myMainPanel = new JPanel(new BorderLayout()); - myFramesList = new XDebuggerFramesList(session.getProject()); + myFramesList = new XDebuggerFramesList(project); myFramesList.addListSelectionListener(new ListSelectionListener() { @Override - public void valueChanged(final ListSelectionEvent e) { - if (e.getValueIsAdjusting()) return; - processFrameSelection(); + public void valueChanged(ListSelectionEvent e) { + if (myListenersEnabled && !e.getValueIsAdjusting()) { + processFrameSelection(e); + } } }); myFramesList.addMouseListener(new MouseAdapter() { @Override public void mousePressed(final MouseEvent e) { - int i = myFramesList.locationToIndex(e.getPoint()); - if (i != -1 && myFramesList.isSelectedIndex(i)) { - processFrameSelection(); + if (myListenersEnabled) { + int i = myFramesList.locationToIndex(e.getPoint()); + if (i != -1 && myFramesList.isSelectedIndex(i)) { + processFrameSelection(e); + } } } }); - final ActionManager actionManager = ActionManager.getInstance(); myFramesList.addMouseListener(new PopupHandler() { @Override public void invokePopup(final Component comp, final int x, final int y) { + ActionManager actionManager = ActionManager.getInstance(); ActionGroup group = (ActionGroup)actionManager.getAction(XDebuggerActions.FRAMES_TREE_POPUP_GROUP); actionManager.createActionPopupMenu(ActionPlaces.UNKNOWN, group).getComponent().show(comp, x, y); } @@ -103,13 +106,32 @@ public class XFramesView implements XDebugView { myThreadComboBox = new ComboBox(); //noinspection unchecked myThreadComboBox.setRenderer(new ThreadComboBoxRenderer(myThreadComboBox)); - myThreadComboBox.addItemListener(new MyItemListener()); + myThreadComboBox.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(final ItemEvent e) { + if (!myListenersEnabled) { + return; + } + + if (e.getStateChange() == ItemEvent.SELECTED) { + Object item = e.getItem(); + if (item instanceof XExecutionStack) { + XDebugSession session = getSession(e); + if (session != null) { + updateFrames((XExecutionStack)item, session); + } + } + } + } + }); myThreadComboBox.addPopupMenuListener(new PopupMenuListenerAdapter() { @Override public void popupMenuWillBecomeVisible(PopupMenuEvent e) { - XSuspendContext context = mySession.getSuspendContext(); + XDebugSession session = getSession(e); + XSuspendContext context = session == null ? null : session.getSuspendContext(); if (context != null && !myThreadsCalculated) { myThreadsCalculated = true; + //noinspection unchecked myThreadComboBox.addItem(null); // rendered as "Loading..." context.computeExecutionStacks(new XSuspendContext.XExecutionStackContainer() { @Override @@ -130,7 +152,6 @@ public class XFramesView implements XDebugView { @Override public void errorOccurred(@NotNull String errorMessage) { - } }); } @@ -145,12 +166,9 @@ public class XFramesView implements XDebugView { myToolbar = createToolbar(); myThreadsPanel = new Wrapper(); - CustomLineBorder border = new CustomLineBorder(CaptionPanel.CNT_ACTIVE_BORDER_COLOR, 0, 0, 1, 0); - myThreadsPanel.setBorder(border); + myThreadsPanel.setBorder(new CustomLineBorder(CaptionPanel.CNT_ACTIVE_BORDER_COLOR, 0, 0, 1, 0)); myThreadsPanel.add(myToolbar.getComponent(), BorderLayout.EAST); myMainPanel.add(myThreadsPanel, BorderLayout.NORTH); - - processSessionEvent(SessionEvent.RESUMED); } private ActionToolbarImpl createToolbar() { @@ -181,9 +199,14 @@ public class XFramesView implements XDebugView { @Override public void processSessionEvent(@NotNull final SessionEvent event) { - if (event == SessionEvent.BEFORE_RESUME) return; + if (event == SessionEvent.BEFORE_RESUME) { + return; + } + + XDebugSession session = getSession(getMainPanel()); + if (event == SessionEvent.FRAME_CHANGED) { - XStackFrame currentStackFrame = mySession.getCurrentStackFrame(); + XStackFrame currentStackFrame = session == null ? null : session.getCurrentStackFrame(); if (currentStackFrame != null) { myFramesList.setSelectedValue(currentStackFrame, true); } @@ -196,15 +219,16 @@ public class XFramesView implements XDebugView { } myBuilders.clear(); mySelectedStack = null; - XSuspendContext suspendContext = mySession.getSuspendContext(); - if (suspendContext == null || event == SessionEvent.PAUSED) { - myThreadComboBox.removeAllItems(); - myFramesList.clear(); - myThreadsCalculated = false; - myExecutionStacks.clear(); - if (suspendContext == null) { - return; - } + XSuspendContext suspendContext = session == null ? null : session.getSuspendContext(); + if (suspendContext == null) { + requestClear(); + return; + } + + if (event == SessionEvent.PAUSED) { + // clear immediately + cancelClear(); + clear(); } XExecutionStack[] executionStacks = suspendContext.getExecutionStacks(); @@ -219,10 +243,18 @@ public class XFramesView implements XDebugView { myThreadsPanel.add(myThreadComboBox, BorderLayout.CENTER); } myToolbar.setAddSeparatorFirst(!invisible); - updateFrames(activeExecutionStack); + updateFrames(activeExecutionStack, session); myListenersEnabled = true; } + @Override + protected void clear() { + myThreadComboBox.removeAllItems(); + myFramesList.clear(); + myThreadsCalculated = false; + myExecutionStacks.clear(); + } + private void addExecutionStacks(List<? extends XExecutionStack> executionStacks) { for (XExecutionStack executionStack : executionStacks) { if (!myExecutionStacks.contains(executionStack)) { @@ -233,7 +265,7 @@ public class XFramesView implements XDebugView { } } - private void updateFrames(final XExecutionStack executionStack) { + private void updateFrames(final XExecutionStack executionStack, @NotNull XDebugSession session) { if (mySelectedStack == executionStack) { return; } @@ -249,7 +281,7 @@ public class XFramesView implements XDebugView { XStackFrame topFrame = executionStack.getTopFrame(); if (topFrame != null) { myFramesList.setSelectedValue(topFrame, true); - onFrameSelected(executionStack, topFrame); + session.setCurrentStackFrame(executionStack, topFrame); } } } @@ -262,32 +294,16 @@ public class XFramesView implements XDebugView { return myFramesList; } - private void onFrameSelected(XExecutionStack executionStack, final @NotNull XStackFrame stackFrame) { - mySession.setCurrentStackFrame(executionStack, stackFrame); - } - public JPanel getMainPanel() { return myMainPanel; } - private void processFrameSelection() { - if (!myListenersEnabled) return; + private void processFrameSelection(@NotNull EventObject e) { Object selected = myFramesList.getSelectedValue(); if (selected instanceof XStackFrame) { - onFrameSelected(mySelectedStack, (XStackFrame)selected); - } - } - - private class MyItemListener implements ItemListener { - @Override - public void itemStateChanged(final ItemEvent e) { - if (!myListenersEnabled) return; - - if (e.getStateChange() == ItemEvent.SELECTED) { - Object item = e.getItem(); - if (item instanceof XExecutionStack) { - updateFrames((XExecutionStack)item); - } + XDebugSession session = getSession(e); + if (session != null) { + session.setCurrentStackFrame(mySelectedStack, (XStackFrame)selected); } } } @@ -315,7 +331,7 @@ public class XFramesView implements XDebugView { @Override public void addStackFrames(@NotNull final List<? extends XStackFrame> stackFrames, final boolean last) { - ApplicationManager.getApplication().invokeLater(new Runnable() { + myLaterInvocator.offer(new Runnable() { @Override public void run() { myStackFrames.addAll(stackFrames); @@ -331,7 +347,7 @@ public class XFramesView implements XDebugView { @Override public void errorOccurred(@NotNull final String errorMessage) { - ApplicationManager.getApplication().invokeLater(new Runnable() { + myLaterInvocator.offer(new Runnable() { @Override public void run() { if (myErrorMessage == null) { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XStandaloneVariablesView.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XStandaloneVariablesView.java index f7f32ba86b9c..f91146426878 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XStandaloneVariablesView.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XStandaloneVariablesView.java @@ -42,4 +42,12 @@ public class XStandaloneVariablesView extends XVariablesViewBase { } }); } + + @Override + public void processSessionEvent(@NotNull SessionEvent event) { + } + + @Override + protected void clear() { + } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java index 31b30a8362e3..df43b1147419 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -15,30 +15,37 @@ */ package com.intellij.xdebugger.impl.frame; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.xdebugger.XDebugProcess; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.frame.XStackFrame; import com.intellij.xdebugger.impl.XDebugSessionImpl; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode; +import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; import org.jetbrains.annotations.NotNull; +import java.util.Map; +import java.util.Set; + import static com.intellij.xdebugger.impl.ui.tree.nodes.MessageTreeNode.createInfoMessage; /** * @author nik */ -public class XVariablesView extends XVariablesViewBase implements XDebugView { - @NotNull private final XDebugSession mySession; +public class XVariablesView extends XVariablesViewBase { + public static final Key<Map<Pair<VirtualFile, Integer>, Set<XValueNodeImpl>>> DEBUG_VARIABLES = Key.create("debug.frame"); - public XVariablesView(@NotNull XDebugSession session) { - super(session.getProject(), session.getDebugProcess().getEditorsProvider(), ((XDebugSessionImpl)session).getValueMarkers()); - mySession = session; + public XVariablesView(@NotNull XDebugSessionImpl session) { + super(session.getProject(), session.getDebugProcess().getEditorsProvider(), session.getValueMarkers()); } @Override public void processSessionEvent(@NotNull final SessionEvent event) { - XStackFrame stackFrame = mySession.getCurrentStackFrame(); + XDebugSession session = getSession(getPanel()); + XStackFrame stackFrame = session == null ? null : session.getCurrentStackFrame(); XDebuggerTree tree = getTree(); if (event == SessionEvent.BEFORE_RESUME || event == SessionEvent.SETTINGS_CHANGED) { @@ -50,20 +57,29 @@ public class XVariablesView extends XVariablesViewBase implements XDebugView { tree.markNodesObsolete(); if (stackFrame != null) { + cancelClear(); buildTreeAndRestoreState(stackFrame); } else { - tree.setSourcePosition(null); + requestClear(); + } + } - XDebuggerTreeNode node; - if (!mySession.isStopped() && mySession.isPaused()) { - node = createInfoMessage(tree, "Frame is not available"); - } - else { - XDebugProcess debugProcess = mySession.getDebugProcess(); - node = createInfoMessage(tree, debugProcess.getCurrentStateMessage(), debugProcess.getCurrentStateHyperlinkListener()); - } - tree.setRoot(node, true); + @Override + protected void clear() { + XDebuggerTree tree = getTree(); + tree.getProject().putUserData(DEBUG_VARIABLES, null); + tree.setSourcePosition(null); + + XDebuggerTreeNode node; + XDebugSession session = getSession(getPanel()); + if (session == null || (!session.isStopped() && session.isPaused())) { + node = createInfoMessage(tree, "Frame is not available"); + } + else { + XDebugProcess debugProcess = session.getDebugProcess(); + node = createInfoMessage(tree, debugProcess.getCurrentStateMessage(), debugProcess.getCurrentStateHyperlinkListener()); } + tree.setRoot(node, true); } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesViewBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesViewBase.java index 33a1639ba5d7..ace9938318df 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesViewBase.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesViewBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -16,8 +16,9 @@ package com.intellij.xdebugger.impl.frame; import com.intellij.ide.dnd.DnDManager; -import com.intellij.openapi.Disposable; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.xdebugger.XDebuggerBundle; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; import com.intellij.xdebugger.frame.XStackFrame; @@ -27,15 +28,18 @@ import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreePanel; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeRestorer; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeState; import com.intellij.xdebugger.impl.ui.tree.nodes.XStackFrameNode; +import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.util.HashMap; +import java.util.Set; /** * @author nik */ -public abstract class XVariablesViewBase implements Disposable { +public abstract class XVariablesViewBase extends XDebugView { protected final XDebuggerTreePanel myDebuggerTreePanel; private XDebuggerTreeState myTreeState; private Object myFrameEqualityObject; @@ -51,6 +55,7 @@ public abstract class XVariablesViewBase implements Disposable { XDebuggerTree tree = myDebuggerTreePanel.getTree(); tree.setSourcePosition(stackFrame.getSourcePosition()); tree.setRoot(new XStackFrameNode(tree, stackFrame), false); + tree.getProject().putUserData(XVariablesView.DEBUG_VARIABLES, new HashMap<Pair<VirtualFile, Integer>, Set<XValueNodeImpl>>()); Object newEqualityObject = stackFrame.getEqualityObject(); if (myFrameEqualityObject != null && newEqualityObject != null && myFrameEqualityObject.equals(newEqualityObject) && myTreeState != null) { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java index 6216c1312349..c510cd17c90a 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -33,6 +33,7 @@ import com.intellij.ui.border.CustomLineBorder; import com.intellij.util.Alarm; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.tree.TreeUtil; +import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XDebuggerBundle; import com.intellij.xdebugger.XExpression; import com.intellij.xdebugger.frame.XStackFrame; @@ -64,20 +65,18 @@ import java.util.List; /** * @author nik */ -public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugView { +public class XWatchesViewImpl extends XDebugView implements DnDNativeTarget, XWatchesView { private final XDebuggerTreePanel myTreePanel; private XDebuggerTreeState myTreeState; private XDebuggerTreeRestorer myTreeRestorer; private final WatchesRootNode myRootNode; - @NotNull private final XDebugSessionImpl mySession; private final JPanel myDecoratedPanel; private final CompositeDisposable myDisposables = new CompositeDisposable(); private boolean myRebuildNeeded; - public XWatchesViewImpl(@NotNull final XDebugSessionImpl session) { - mySession = session; + public XWatchesViewImpl(@NotNull XDebugSessionImpl session) { myTreePanel = new XDebuggerTreePanel(session.getProject(), session.getDebugProcess().getEditorsProvider(), this, null, - XDebuggerActions.WATCHES_TREE_POPUP_GROUP, ((XDebugSessionImpl)session).getValueMarkers()); + XDebuggerActions.WATCHES_TREE_POPUP_GROUP, session.getValueMarkers()); ActionManager actionManager = ActionManager.getInstance(); @@ -89,7 +88,7 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi actionManager.getAction(XDebuggerActions.XEDIT_WATCH).registerCustomShortcutSet(f2Shortcut, tree); DnDManager.getInstance().registerTarget(this, tree); - myRootNode = new WatchesRootNode(tree, session, this, session.getSessionData().getWatchExpressions()); + myRootNode = new WatchesRootNode(tree, this, session.getSessionData().getWatchExpressions()); tree.setRoot(myRootNode, false); final ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myTreePanel.getTree()).disableUpDownActions(); @@ -134,6 +133,7 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi DataContext context = DataManager.getInstance().getDataContext(watchTree); final AnActionEvent actionEvent = new AnActionEvent(null, context, "WATCH_TREE", presentation, ActionManager.getInstance(), 0); Runnable runnable = new Runnable() { + @Override public void run() { editWatchAction.actionPerformed(actionEvent); } @@ -161,12 +161,12 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi final FocusListener focusListener = new FocusListener() { @Override - public void focusGained(FocusEvent e) { + public void focusGained(@NotNull FocusEvent e) { quitePeriod.addRequest(EmptyRunnable.getInstance(), UIUtil.getMultiClickInterval()); } @Override - public void focusLost(FocusEvent e) { + public void focusLost(@NotNull FocusEvent e) { editAlarm.cancelAllRequests(); } }; @@ -174,7 +174,7 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi final TreeSelectionListener selectionListener = new TreeSelectionListener() { @Override - public void valueChanged(TreeSelectionEvent e) { + public void valueChanged(@NotNull TreeSelectionEvent e) { quitePeriod.addRequest(EmptyRunnable.getInstance(), UIUtil.getMultiClickInterval()); } }; @@ -219,15 +219,20 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi @Override public void addWatchExpression(@NotNull XExpression expression, int index, final boolean navigateToWatchNode) { - myRootNode.addWatchExpression(mySession.getDebugProcess().getEvaluator(), expression, index, navigateToWatchNode); + XDebugSession session = getSession(getTree()); + if (session == null) { + return; + } + + myRootNode.addWatchExpression(session.getDebugProcess().getEvaluator(), expression, index, navigateToWatchNode); updateSessionData(); if (navigateToWatchNode) { - showWatchesTab(); + showWatchesTab((XDebugSessionImpl)session); } } - private void showWatchesTab() { - XDebugSessionTab tab = mySession.getSessionTab(); + private static void showWatchesTab(@NotNull XDebugSessionImpl session) { + XDebugSessionTab tab = session.getSessionTab(); if (tab != null) { tab.toFront(false); // restore watches tab if minimized @@ -255,7 +260,6 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi return; } - XStackFrame stackFrame = mySession.getCurrentStackFrame(); XDebuggerTree tree = myTreePanel.getTree(); if (event == SessionEvent.BEFORE_RESUME || event == SessionEvent.SETTINGS_CHANGED) { @@ -268,7 +272,10 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi } } + XDebugSession session = getSession(getMainPanel()); + XStackFrame stackFrame = session == null ? null : session.getCurrentStackFrame(); if (stackFrame != null) { + cancelClear(); tree.setSourcePosition(stackFrame.getSourcePosition()); myRootNode.updateWatches(stackFrame.getEvaluator()); if (myTreeState != null) { @@ -276,11 +283,16 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi } } else { - tree.setSourcePosition(null); - myRootNode.updateWatches(null); + requestClear(); } } + @Override + protected void clear() { + getTree().setSourcePosition(null); + myRootNode.updateWatches(null); + } + public XDebuggerTree getTree() { return myTreePanel.getTree(); } @@ -290,7 +302,7 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi } @Override - public void removeWatches(final List<? extends XDebuggerTreeNode> nodes) { + public void removeWatches(List<? extends XDebuggerTreeNode> nodes) { List<? extends WatchNode> children = myRootNode.getAllChildren(); int minIndex = Integer.MAX_VALUE; List<XDebuggerTreeNode> toRemove = new ArrayList<XDebuggerTreeNode>(); @@ -328,7 +340,11 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi watchExpressions.add(child.getExpression()); } } - mySession.setWatchExpressions(watchExpressions.toArray(new XExpression[watchExpressions.size()])); + + XDebugSession session = getSession(getTree()); + if (session != null) { + ((XDebugSessionImpl)session).setWatchExpressions(watchExpressions.toArray(new XExpression[watchExpressions.size()])); + } } @Override @@ -348,13 +364,14 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi } @Override - public void drop(final DnDEvent aEvent) { + public void drop(DnDEvent aEvent) { Object object = aEvent.getAttachedObject(); if (object instanceof XValueNodeImpl[]) { final XValueNodeImpl[] nodes = (XValueNodeImpl[])object; for (XValueNodeImpl node : nodes) { String expression = node.getValueContainer().getEvaluationExpression(); if (expression != null) { + //noinspection ConstantConditions addWatchExpression(XExpressionImpl.fromText(expression), -1, false); } } @@ -362,6 +379,7 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi else if (object instanceof EventInfo) { String text = ((EventInfo)object).getTextForFlavor(DataFlavor.stringFlavor); if (text != null) { + //noinspection ConstantConditions addWatchExpression(XExpressionImpl.fromText(text), -1, false); } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/BreakpointEditor.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/BreakpointEditor.java index f51ce77d3fee..79c8dc49c398 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/BreakpointEditor.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/BreakpointEditor.java @@ -19,6 +19,7 @@ import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.keymap.KeymapUtil; +import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.components.labels.LinkLabel; import com.intellij.ui.components.labels.LinkListener; @@ -79,7 +80,7 @@ public class BreakpointEditor { } }); - final AnAction doneAction = new AnAction() { + final AnAction doneAction = new DumbAwareAction() { @Override public void update(AnActionEvent e) { super.update(e); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerSessionTabBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerSessionTabBase.java index 2134c0c8d4e1..053f18dd14bf 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerSessionTabBase.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerSessionTabBase.java @@ -16,7 +16,8 @@ package com.intellij.xdebugger.impl.ui; import com.intellij.debugger.ui.DebuggerContentInfo; -import com.intellij.diagnostic.logging.*; +import com.intellij.diagnostic.logging.AdditionalTabComponent; +import com.intellij.diagnostic.logging.DebuggerLogConsoleManager; import com.intellij.execution.ExecutionManager; import com.intellij.execution.configurations.RunConfigurationBase; import com.intellij.execution.configurations.RunProfile; @@ -24,6 +25,7 @@ import com.intellij.execution.executors.DefaultDebugExecutor; import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.runners.RunContentBuilder; +import com.intellij.execution.runners.RunTab; import com.intellij.execution.ui.*; import com.intellij.execution.ui.layout.LayoutAttractionPolicy; import com.intellij.execution.ui.layout.LayoutViewOptions; @@ -48,25 +50,13 @@ import java.util.Collection; /** * @author nik */ -public abstract class DebuggerSessionTabBase extends LogConsoleManagerBase implements DebuggerLogConsoleManager { - @NotNull private final LogFilesManager myManager; - - @NotNull final String mySessionName; - @NotNull protected final RunnerLayoutUi myUi; - +public abstract class DebuggerSessionTabBase extends RunTab implements DebuggerLogConsoleManager { protected ExecutionConsole myConsole; - protected RunContentDescriptor myRunContentDescriptor; - - public DebuggerSessionTabBase(@NotNull Project project, @NotNull String runnerId, @NotNull final String sessionName, - @NotNull GlobalSearchScope searchScope) { - super(project, searchScope); - Disposer.register(project, this); - myManager = new LogFilesManager(project, this, this); - mySessionName = sessionName; + public DebuggerSessionTabBase(@NotNull Project project, @NotNull String runnerId, @NotNull String sessionName, @NotNull GlobalSearchScope searchScope) { + super(project, searchScope, runnerId, XDebuggerBundle.message("xdebugger.default.content.title"), sessionName); - myUi = RunnerLayoutUi.Factory.getInstance(project).create( - runnerId, XDebuggerBundle.message("xdebugger.default.content.title"), sessionName, this); + Disposer.register(project, this); myUi.getDefaults() .initTabDefaults(0, XDebuggerBundle.message("xdebugger.debugger.tab.title"), null) @@ -104,23 +94,6 @@ public abstract class DebuggerSessionTabBase extends LogConsoleManagerBase imple return myUi; } - protected void registerFileMatcher(final RunProfile runConfiguration) { - if (runConfiguration instanceof RunConfigurationBase) { - myManager.registerFileMatcher((RunConfigurationBase)runConfiguration); - } - } - - protected void initLogConsoles(final RunProfile runConfiguration, final ProcessHandler processHandler, ExecutionConsole console) { - if (runConfiguration instanceof RunConfigurationBase) { - myManager.initLogConsoles((RunConfigurationBase)runConfiguration, processHandler); - OutputFileUtil.attachDumpListener((RunConfigurationBase)runConfiguration, processHandler, console); - } - } - - protected LogFilesManager getLogManager() { - return myManager; - } - protected void attachNotificationTo(final Content content) { if (myConsole instanceof ObservableConsoleView) { ObservableConsoleView observable = (ObservableConsoleView)myConsole; diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java index 4b6bea217c54..4c3766f23f5d 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -17,11 +17,8 @@ package com.intellij.xdebugger.impl.ui; import com.intellij.debugger.ui.DebuggerContentInfo; import com.intellij.execution.Executor; -import com.intellij.execution.configurations.RunProfile; import com.intellij.execution.executors.DefaultDebugExecutor; import com.intellij.execution.runners.ExecutionEnvironment; -import com.intellij.execution.runners.ProgramRunner; -import com.intellij.execution.runners.RestartAction; import com.intellij.execution.runners.RunContentBuilder; import com.intellij.execution.ui.ExecutionConsole; import com.intellij.execution.ui.RunContentDescriptor; @@ -29,11 +26,11 @@ import com.intellij.execution.ui.actions.CloseAction; import com.intellij.execution.ui.layout.PlaceInGrid; import com.intellij.execution.ui.layout.impl.ViewImpl; import com.intellij.icons.AllIcons; +import com.intellij.ide.DataManager; import com.intellij.ide.actions.ContextHelpAction; import com.intellij.idea.ActionsBundle; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.ui.AppUIUtil; @@ -41,7 +38,7 @@ import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentManagerAdapter; import com.intellij.ui.content.ContentManagerEvent; import com.intellij.ui.content.tabs.PinToolwindowTabAction; -import com.intellij.xdebugger.XDebugProcess; +import com.intellij.util.SystemProperties; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XDebuggerBundle; import com.intellij.xdebugger.impl.XDebugSessionImpl; @@ -57,29 +54,109 @@ import javax.swing.*; import java.util.ArrayList; import java.util.List; -/** - * @author spleaner - */ public class XDebugSessionTab extends DebuggerSessionTabBase { + private static final DataKey<XDebugSessionTab> TAB_KEY = DataKey.create("XDebugSessionTab"); + private XWatchesViewImpl myWatchesView; private final List<XDebugView> myViews = new ArrayList<XDebugView>(); - public XDebugSessionTab(@NotNull Project project, - @NotNull XDebugSessionImpl session, - @Nullable Icon icon, - @Nullable ExecutionEnvironment environment, - @Nullable ProgramRunner runner) { - super(project, "Debug", session.getSessionName(), GlobalSearchScope.allScope(project)); + @Nullable + private XDebugSessionImpl mySession; + private XDebugSessionData mySessionData; + + @NotNull + public static XDebugSessionTab create(@NotNull XDebugSessionImpl session, + @Nullable Icon icon, + @Nullable ExecutionEnvironment environment, + @Nullable RunContentDescriptor contentToReuse) { + if (contentToReuse != null && SystemProperties.getBooleanProperty("xdebugger.reuse.session.tab", false)) { + JComponent component = contentToReuse.getComponent(); + if (component != null) { + XDebugSessionTab oldTab = TAB_KEY.getData(DataManager.getInstance().getDataContext(component)); + if (oldTab != null) { + oldTab.setSession(session, environment, icon); + oldTab.attachToSession(session); + return oldTab; + } + } + } + return new XDebugSessionTab(session, icon, environment); + } + + private XDebugSessionTab(@NotNull XDebugSessionImpl session, + @Nullable Icon icon, + @Nullable ExecutionEnvironment environment) { + super(session.getProject(), "Debug", session.getSessionName(), GlobalSearchScope.allScope(session.getProject())); + + setSession(session, environment, icon); + + myUi.addContent(createFramesContent(), 0, PlaceInGrid.left, false); + myUi.addContent(createVariablesContent(session), 0, PlaceInGrid.center, false); + myUi.addContent(createWatchesContent(session), 0, PlaceInGrid.right, false); + + for (XDebugView view : myViews) { + Disposer.register(this, view); + } + + attachToSession(session); + + DefaultActionGroup focus = new DefaultActionGroup(); + focus.add(ActionManager.getInstance().getAction(XDebuggerActions.FOCUS_ON_BREAKPOINT)); + myUi.getOptions().setAdditionalFocusActions(focus); + + myUi.addListener(new ContentManagerAdapter() { + @Override + public void selectionChanged(ContentManagerEvent event) { + Content content = event.getContent(); + XDebugSessionImpl session = mySession; + if (session != null && content.isSelected() && DebuggerContentInfo.WATCHES_CONTENT.equals(ViewImpl.ID.get(content))) { + if (myWatchesView.rebuildNeeded()) { + myWatchesView.processSessionEvent(XDebugView.SessionEvent.SETTINGS_CHANGED); + } + } + } + }, this); + + rebuildViews(); + } + + private void setSession(@NotNull XDebugSessionImpl session, @Nullable ExecutionEnvironment environment, @Nullable Icon icon) { if (environment != null) { setEnvironment(environment); } + + mySession = session; + mySessionData = session.getSessionData(); myConsole = session.getConsoleView(); - XDebugProcess debugProcess = session.getDebugProcess(); - myRunContentDescriptor = new RunContentDescriptor(myConsole, debugProcess.getProcessHandler(), myUi.getComponent(), mySessionName, icon); - attachToSession(session, runner, environment, session.getSessionData(), debugProcess); + myRunContentDescriptor = new RunContentDescriptor(myConsole, session.getDebugProcess().getProcessHandler(), myUi.getComponent(), session.getSessionName(), icon); } - private Content createVariablesContent(final XDebugSession session) { + @Nullable + @Override + public Object getData(@NonNls String dataId) { + if (XWatchesView.DATA_KEY.is(dataId)) { + return myWatchesView; + } + else if (TAB_KEY.is(dataId)) { + return this; + } + else if (XDebugSessionData.DATA_KEY.is(dataId)) { + return mySessionData; + } + + if (mySession != null) { + if (XDebugSession.DATA_KEY.is(dataId)) { + return mySession; + } + else if (LangDataKeys.CONSOLE_VIEW.is(dataId)) { + return mySession.getConsoleView(); + } + } + + return super.getData(dataId); + } + + private Content createVariablesContent(@NotNull XDebugSessionImpl session) { final XVariablesView variablesView = new XVariablesView(session); myViews.add(variablesView); Content result = myUi.createContent(DebuggerContentInfo.VARIABLES_CONTENT, variablesView.getPanel(), @@ -89,27 +166,25 @@ public class XDebugSessionTab extends DebuggerSessionTabBase { ActionGroup group = getCustomizedActionGroup(XDebuggerActions.VARIABLES_TREE_TOOLBAR_GROUP); result.setActions(group, ActionPlaces.DEBUGGER_TOOLBAR, variablesView.getTree()); - return result; } - private Content createWatchesContent(final XDebugSessionImpl session, final XDebugSessionData sessionData) { + private Content createWatchesContent(@NotNull XDebugSessionImpl session) { myWatchesView = new XWatchesViewImpl(session); myViews.add(myWatchesView); Content watchesContent = myUi.createContent(DebuggerContentInfo.WATCHES_CONTENT, myWatchesView.getMainPanel(), - XDebuggerBundle.message("debugger.session.tab.watches.title"), AllIcons.Debugger.Watches, null); + XDebuggerBundle.message("debugger.session.tab.watches.title"), AllIcons.Debugger.Watches, null); watchesContent.setCloseable(false); - return watchesContent; } - private Content createFramesContent(final XDebugSession session) { - final XFramesView framesView = new XFramesView(session); + @NotNull + private Content createFramesContent() { + XFramesView framesView = new XFramesView(getProject()); myViews.add(framesView); Content framesContent = myUi.createContent(DebuggerContentInfo.FRAME_CONTENT, framesView.getMainPanel(), XDebuggerBundle.message("debugger.session.tab.frames.title"), AllIcons.Debugger.Frame, null); framesContent.setCloseable(false); - return framesContent; } @@ -132,34 +207,12 @@ public class XDebugSessionTab extends DebuggerSessionTabBase { return myWatchesView; } - private void attachToSession(final @NotNull XDebugSessionImpl session, final @Nullable ProgramRunner runner, - final @Nullable ExecutionEnvironment environment, final @NotNull XDebugSessionData sessionData, - final @NotNull XDebugProcess debugProcess) { - myUi.addContent(createFramesContent(session), 0, PlaceInGrid.left, false); - myUi.addContent(createVariablesContent(session), 0, PlaceInGrid.center, false); - myUi.addContent(createWatchesContent(session, sessionData), 0, PlaceInGrid.right, false); + private void attachToSession(@NotNull XDebugSessionImpl session) { for (XDebugView view : myViews) { - Disposer.register(this, view); - session.addSessionListener(new XDebugViewSessionListener(view, getProject()), this); + session.addSessionListener(new XDebugViewSessionListener(view, session), this); } - myUi.getContentManager().addDataProvider(new DataProvider() { - @Nullable - @Override - public Object getData(@NonNls String dataId) { - if (XWatchesView.DATA_KEY.is(dataId)) { - return myWatchesView; - } - if (LangDataKeys.CONSOLE_VIEW.is(dataId)) { - return session.getConsoleView(); - } - if (XDebugSessionData.DATA_KEY.is(dataId)) { - return sessionData; - } - return null; - } - }); - XDebugTabLayouter layouter = debugProcess.createTabLayouter(); + XDebugTabLayouter layouter = session.getDebugProcess().createTabLayouter(); Content consoleContent = layouter.registerConsoleContent(myUi, myConsole); attachNotificationTo(consoleContent); @@ -172,18 +225,15 @@ public class XDebugSessionTab extends DebuggerSessionTabBase { DefaultActionGroup leftToolbar = new DefaultActionGroup(); final Executor debugExecutor = DefaultDebugExecutor.getDebugExecutorInstance(); - final Executor executor = environment != null ? environment.getExecutor() : debugExecutor; - if (runner != null && environment != null) { - RestartAction restartAction = new RestartAction(executor, runner, myRunContentDescriptor, environment); - leftToolbar.add(restartAction); - restartAction.registerShortcut(myUi.getComponent()); - + ExecutionEnvironment environment = getEnvironment(); + if (environment != null) { List<AnAction> additionalRestartActions = session.getRestartActions(); - leftToolbar.addAll(additionalRestartActions); - if (!additionalRestartActions.isEmpty()) leftToolbar.addSeparator(); + if (!additionalRestartActions.isEmpty()) { + leftToolbar.addAll(additionalRestartActions); + leftToolbar.addSeparator(); + } leftToolbar.addAll(session.getExtraActions()); } - leftToolbar.addAll(getCustomizedActionGroup(XDebuggerActions.TOOL_WINDOW_LEFT_TOOLBAR_GROUP)); for (AnAction action : session.getExtraStopActions()) { @@ -216,7 +266,7 @@ public class XDebugSessionTab extends DebuggerSessionTabBase { if (commonSettings.length > 0) { settings.addSeparator(); } - if (!debugProcess.isValuesCustomSorted()) { + if (!session.getDebugProcess().isValuesCustomSorted()) { settings.add(new ToggleSortValuesAction(commonSettings.length == 0)); } @@ -225,41 +275,25 @@ public class XDebugSessionTab extends DebuggerSessionTabBase { leftToolbar.addSeparator(); leftToolbar.add(PinToolwindowTabAction.getPinAction()); - leftToolbar.add(new CloseAction(executor, myRunContentDescriptor, getProject())); + leftToolbar.add(new CloseAction(environment != null ? environment.getExecutor() : debugExecutor, myRunContentDescriptor, getProject())); leftToolbar.add(new ContextHelpAction(debugExecutor.getHelpId())); DefaultActionGroup topToolbar = new DefaultActionGroup(); topToolbar.addAll(getCustomizedActionGroup(XDebuggerActions.TOOL_WINDOW_TOP_TOOLBAR_GROUP)); - debugProcess.registerAdditionalActions(leftToolbar, topToolbar); + session.getDebugProcess().registerAdditionalActions(leftToolbar, topToolbar); myUi.getOptions().setLeftToolbar(leftToolbar, ActionPlaces.DEBUGGER_TOOLBAR); myUi.getOptions().setTopToolbar(topToolbar, ActionPlaces.DEBUGGER_TOOLBAR); if (environment != null) { - final RunProfile runConfiguration = environment.getRunProfile(); - registerFileMatcher(runConfiguration); - initLogConsoles(runConfiguration, myRunContentDescriptor.getProcessHandler(), myConsole); + initLogConsoles(environment.getRunProfile(), myRunContentDescriptor.getProcessHandler(), myConsole); } - - final DefaultActionGroup focus = new DefaultActionGroup(); - focus.add(ActionManager.getInstance().getAction(XDebuggerActions.FOCUS_ON_BREAKPOINT)); - myUi.getOptions().setAdditionalFocusActions(focus); - - myUi.addListener(new ContentManagerAdapter() { - @Override - public void selectionChanged(ContentManagerEvent event) { - Content content = event.getContent(); - if (content.isSelected() && DebuggerContentInfo.WATCHES_CONTENT.equals(content.getUserData(ViewImpl.ID))) { - if (myWatchesView.rebuildNeeded()) { - myWatchesView.processSessionEvent(XDebugView.SessionEvent.SETTINGS_CHANGED); - } - } - } - }, this); - - rebuildViews(); } + public void detachFromSession() { + assert mySession != null; + mySession = null; + } @Override @Nullable @@ -283,4 +317,4 @@ public class XDebugSessionTab extends DebuggerSessionTabBase { } } } -}
\ No newline at end of file +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XValueTextProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XValueTextProvider.java new file mode 100644 index 000000000000..54ae63776e75 --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XValueTextProvider.java @@ -0,0 +1,23 @@ +/* + * 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.xdebugger.impl.ui; + +/** + * @author egor + */ +public interface XValueTextProvider { + String getValueText(); +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java index 629385c9ad20..13fe7802481c 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java @@ -17,16 +17,19 @@ package com.intellij.xdebugger.impl.ui.tree; import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.codeInsight.lookup.impl.LookupImpl; -import com.intellij.execution.ExecutionManager; +import com.intellij.execution.Executor; import com.intellij.execution.ui.RunContentDescriptor; -import com.intellij.execution.ui.RunContentListener; import com.intellij.execution.ui.RunContentManager; +import com.intellij.execution.ui.RunContentWithExecutorListener; +import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.util.Disposer; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -176,23 +179,22 @@ public abstract class TreeInplaceEditor implements AWTEventListener { } }); - final RunContentManager contentManager = ExecutionManager.getInstance(getProject()).getContentManager(); - final RunContentListener runContentListener = new RunContentListener() { + final Disposable disposable = Disposer.newDisposable(); + getProject().getMessageBus().connect(disposable).subscribe(RunContentManager.TOPIC, new RunContentWithExecutorListener() { @Override - public void contentSelected(RunContentDescriptor descriptor) { + public void contentSelected(@Nullable RunContentDescriptor descriptor, @NotNull Executor executor) { cancelEditing(); } @Override - public void contentRemoved(RunContentDescriptor descriptor) { + public void contentRemoved(@Nullable RunContentDescriptor descriptor, @NotNull Executor executor) { cancelEditing(); } - }; - contentManager.addRunContentListener(runContentListener); + }); myRemoveActions.add(new Runnable() { @Override public void run() { - contentManager.removeRunContentListener(runContentListener); + disposable.dispose(); } }); @@ -246,13 +248,13 @@ public abstract class TreeInplaceEditor implements AWTEventListener { if (id != MouseEvent.MOUSE_PRESSED && id != MouseEvent.MOUSE_RELEASED && id != MouseEvent.MOUSE_CLICKED && id != MouseEvent.MOUSE_WHEEL) { return; } - + final Component sourceComponent = mouseEvent.getComponent(); final Point originalPoint = mouseEvent.getPoint(); final Editor editor = getEditor(); if (editor == null) return; - + final LookupImpl activeLookup = (LookupImpl)LookupManager.getInstance(editor.getProject()).getActiveLookup(); if (activeLookup != null){ final Point lookupPoint = SwingUtilities.convertPoint(sourceComponent, originalPoint, activeLookup.getComponent()); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java index fe32920a7ac6..9e4f471b047d 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -18,6 +18,8 @@ package com.intellij.xdebugger.impl.ui.tree; import com.intellij.ide.dnd.aware.DnDAwareTree; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.keymap.KeymapManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; @@ -26,10 +28,12 @@ import com.intellij.openapi.vcs.changes.issueLinks.TreeLinkMouseListener; import com.intellij.ui.DoubleClickListener; import com.intellij.ui.PopupHandler; import com.intellij.ui.TreeSpeedSearch; +import com.intellij.util.SingleAlarm; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Convertor; import com.intellij.util.containers.TransferToEDTQueue; import com.intellij.util.ui.TextTransferable; +import com.intellij.util.ui.tree.TreeModelAdapter; import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink; @@ -41,6 +45,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.event.TreeModelEvent; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; @@ -58,6 +63,17 @@ public class XDebuggerTree extends DnDAwareTree implements DataProvider, Disposa private final TransferToEDTQueue<Runnable> myLaterInvocator = TransferToEDTQueue.createRunnableMerger("XDebuggerTree later invocator", 100); private static final DataKey<XDebuggerTree> XDEBUGGER_TREE_KEY = DataKey.create("xdebugger.tree"); + private final SingleAlarm myAlarm = new SingleAlarm(new Runnable() { + @Override + public void run() { + final Editor editor = FileEditorManager.getInstance(myProject).getSelectedTextEditor(); + if (editor != null) { + editor.getComponent().revalidate(); + editor.getComponent().repaint(); + } + } + }, 100, this); + private static final Convertor<TreePath, String> SPEED_SEARCH_CONVERTER = new Convertor<TreePath, String>() { @Override public String convert(TreePath o) { @@ -135,6 +151,27 @@ public class XDebuggerTree extends DnDAwareTree implements DataProvider, Disposa myEditorsProvider = editorsProvider; mySourcePosition = sourcePosition; myTreeModel = new DefaultTreeModel(null); + myTreeModel.addTreeModelListener(new TreeModelAdapter() { + @Override + public void treeNodesChanged(TreeModelEvent e) { + updateEditor(); + } + + @Override + public void treeNodesInserted(TreeModelEvent e) { + updateEditor(); + } + + @Override + public void treeNodesRemoved(TreeModelEvent e) { + updateEditor(); + } + + @Override + public void treeStructureChanged(TreeModelEvent e) { + updateEditor(); + } + }); setModel(myTreeModel); setCellRenderer(new XDebuggerTreeRenderer()); new TreeLinkMouseListener(new XDebuggerTreeRenderer()) { @@ -185,6 +222,10 @@ public class XDebuggerTree extends DnDAwareTree implements DataProvider, Disposa setTransferHandler(DEFAULT_TRANSFER_HANDLER); } + private void updateEditor() { + myAlarm.cancelAndRequest(); + } + private boolean expandIfEllipsis() { MessageTreeNode[] treeNodes = getSelectedNodes(MessageTreeNode.class, null); if (treeNodes.length == 1) { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XAddToWatchesAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XAddToWatchesAction.java index 66f22bbfd4f1..7c77bafc6553 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XAddToWatchesAction.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XAddToWatchesAction.java @@ -55,7 +55,7 @@ class XAddToWatchesAction extends XDebuggerTreeActionBase { if (view == null && project != null) { XDebugSession session = XDebuggerManager.getInstance(project).getCurrentSession(); if (session != null) { - view = ((XDebugSessionImpl)session).getSessionTab().getWatchesView(); + return ((XDebugSessionImpl)session).getSessionTab().getWatchesView(); } } return view; 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 index 3926e89ecd4c..13121c7fda16 100644 --- 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 @@ -22,6 +22,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.SmartList; import com.intellij.xdebugger.frame.XFullValueEvaluator; +import com.intellij.xdebugger.impl.ui.XValueTextProvider; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import com.intellij.xdebugger.impl.ui.tree.nodes.HeadlessValueEvaluationCallback; import com.intellij.xdebugger.impl.ui.tree.nodes.WatchMessageNode; @@ -74,7 +75,14 @@ public abstract class XFetchValueActionBase extends AnAction { XValueNodeImpl valueNode = (XValueNodeImpl)node; XFullValueEvaluator fullValueEvaluator = valueNode.getFullValueEvaluator(); if (fullValueEvaluator == null) { - valueCollector.add(StringUtil.notNullize(valueNode.getRawValue())); + String rawValue; + if (valueNode.getValueContainer() instanceof XValueTextProvider) { + rawValue = ((XValueTextProvider)valueNode.getValueContainer()).getValueText(); + } + else { + rawValue = valueNode.getRawValue(); + } + valueCollector.add(StringUtil.notNullize(rawValue)); } else { new CopyValueEvaluationCallback(valueNode, valueCollector).startFetchingValue(fullValueEvaluator); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchesRootNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchesRootNode.java index 204f45a4a02d..cf67f7d5fdb5 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchesRootNode.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchesRootNode.java @@ -21,6 +21,7 @@ import com.intellij.xdebugger.evaluation.XDebuggerEvaluator; import com.intellij.xdebugger.frame.XValue; import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl; import com.intellij.xdebugger.impl.frame.WatchInplaceEditor; +import com.intellij.xdebugger.impl.frame.XDebugView; import com.intellij.xdebugger.impl.frame.XWatchesView; import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; @@ -37,18 +38,15 @@ import java.util.List; * @author nik */ public class WatchesRootNode extends XDebuggerTreeNode { - private final XDebugSession mySession; private final XWatchesView myWatchesView; private List<WatchNode> myChildren; private List<XDebuggerTreeNode> myLoadedChildren; private XDebuggerEvaluator myCurrentEvaluator; - public WatchesRootNode(final @NotNull XDebuggerTree tree, - @NotNull XDebugSession session, + public WatchesRootNode(@NotNull XDebuggerTree tree, @NotNull XWatchesView watchesView, @NotNull XExpression[] watchExpressions) { super(tree, null, false); - mySession = session; myWatchesView = watchesView; myChildren = new ArrayList<WatchNode>(); for (XExpression watchExpression : watchExpressions) { @@ -189,7 +187,10 @@ public class WatchesRootNode extends XDebuggerTreeNode { myChildren.set(index, messageNode); fireNodeStructureChanged(messageNode); } - new WatchInplaceEditor(this, mySession, myWatchesView, messageNode, "watch", node).show(); + XDebugSession session = XDebugView.getSession(myTree); + if (session != null) { + new WatchInplaceEditor(this, session, myWatchesView, messageNode, "watch", node).show(); + } } private class MyEvaluationCallback extends XEvaluationCallbackBase { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java index e01d0ad7ce79..5e3101bff21a 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java @@ -49,8 +49,7 @@ public abstract class XDebuggerTreeNode implements TreeNode, TreeSpeedSearch.Pat @Override public TreeNode getChildAt(final int childIndex) { - if (isLeaf()) return null; - return getChildren().get(childIndex); + return isLeaf() ? null : getChildren().get(childIndex); } @Override @@ -64,7 +63,7 @@ public abstract class XDebuggerTreeNode implements TreeNode, TreeSpeedSearch.Pat } @Override - public int getIndex(final TreeNode node) { + public int getIndex(@NotNull TreeNode node) { if (isLeaf()) return -1; return getChildren().indexOf(node); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java index b808c3ca96d8..1f3d4c77e84f 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -16,14 +16,19 @@ package com.intellij.xdebugger.impl.ui.tree.nodes; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.AppUIUtil; import com.intellij.ui.ColoredTextContainer; import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.NotNullFunction; +import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.frame.*; import com.intellij.xdebugger.frame.presentation.XValuePresentation; import com.intellij.xdebugger.impl.frame.XValueMarkers; +import com.intellij.xdebugger.impl.frame.XVariablesView; import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants; import com.intellij.xdebugger.impl.ui.tree.ValueMarkup; @@ -35,6 +40,9 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.event.MouseEvent; import java.util.Comparator; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; /** * @author nik @@ -111,7 +119,28 @@ public class XValueNodeImpl extends XValueContainerNode<XValue> implements XValu setIcon(icon); myValuePresentation = valuePresentation; myRawValue = XValuePresentationUtil.computeValueText(valuePresentation); - + if (Registry.is("ide.debugger.inline")) { + try { + getValueContainer().computeSourcePosition(new XNavigatable() { + @Override + public void setSourcePosition(@Nullable XSourcePosition sourcePosition) { + Map<Pair<VirtualFile, Integer>, Set<XValueNodeImpl>> map = myTree.getProject().getUserData(XVariablesView.DEBUG_VARIABLES); + if (map == null || sourcePosition == null) return; + VirtualFile file = sourcePosition.getFile(); + int line = sourcePosition.getLine(); + Pair<VirtualFile, Integer> key = Pair.create(file, line); + Set<XValueNodeImpl> presentations = map.get(key); + if (presentations == null) { + presentations = new LinkedHashSet<XValueNodeImpl>(); + map.put(key, presentations); + } + presentations.add(XValueNodeImpl.this); + } + }); + } + catch (Exception ignore) { + } + } updateText(); setLeaf(!hasChildren); fireNodeChanged(); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueTextRendererImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueTextRendererImpl.java index e8b8616e6b69..98410cf62552 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueTextRendererImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueTextRendererImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -27,7 +27,7 @@ import org.jetbrains.annotations.Nullable; /** * @author nik */ -class XValueTextRendererImpl extends XValueTextRendererBase { +public class XValueTextRendererImpl extends XValueTextRendererBase { private final ColoredTextContainer myText; public XValueTextRendererImpl(@NotNull ColoredTextContainer text) { |