show breakpoint icon when debugger is suspended on non-line breakpoint (IDEA-70208)

This commit is contained in:
nik
2011-06-07 14:58:03 +04:00
parent 45e1fa348a
commit 861db01273
12 changed files with 618 additions and 414 deletions
@@ -18,11 +18,11 @@ package com.intellij.xdebugger.breakpoints;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.project.Project;
import com.intellij.xdebugger.XDebuggerUtil;
import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel;
import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroupingRule;
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
import com.intellij.xdebugger.ui.DebuggerIcons;
import com.intellij.xdebugger.XDebuggerUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -30,8 +30,8 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.Collections;
import java.util.List;
import java.util.Comparator;
import java.util.List;
/**
* Implement this class to support new type of breakpoints. An implementation should be registered in a plugin.xml:
@@ -100,6 +100,11 @@ public abstract class XBreakpointType<B extends XBreakpoint<P>, P extends XBreak
return DebuggerIcons.DISABLED_BREAKPOINT_ICON;
}
@NotNull
public Icon getDisabledDependentIcon() {
return DebuggerIcons.DISABLED_DEPENDENT_BREAKPOINT_ICON;
}
public abstract String getDisplayText(B breakpoint);
@Nullable
@@ -19,19 +19,17 @@ package com.intellij.xdebugger.breakpoints;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XDebuggerBundle;
import com.intellij.xdebugger.XDebuggerUtil;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.ui.DebuggerIcons;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Collections;
/**
* Implement this class to support new type of line breakpoints. An implementation should be registered in a plugin.xml:
@@ -75,11 +73,6 @@ public abstract class XLineBreakpointType<P extends XBreakpointProperties> exten
return XDebuggerBundle.message("xbreakpoint.default.display.text", breakpoint.getLine() + 1, breakpoint.getPresentableFilePath());
}
@NotNull
public Icon getDisabledDependentIcon() {
return DebuggerIcons.DISABLED_DEPENDENT_BREAKPOINT_ICON;
}
@NotNull
public Comparator<XLineBreakpoint<P>> getBreakpointComparator() {
return XDebuggerUtil.getInstance().getDefaultLineBreakpointComparator();
@@ -33,6 +33,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.markup.GutterIconRenderer;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.Disposer;
@@ -85,6 +86,7 @@ public class XDebugSessionImpl implements XDebugSession {
private String mySessionName;
private XDebugSessionTab mySessionTab;
private XDebugSessionData mySessionData;
private XBreakpoint<?> myActiveNonLineBreakpoint;
private final EventDispatcher<XDebugSessionListener> myDispatcher = EventDispatcher.create(XDebugSessionListener.class);
private Project myProject;
private @Nullable ExecutionEnvironment myEnvironment;
@@ -307,7 +309,7 @@ public class XDebugSessionImpl implements XDebugSession {
}
@Nullable
public CustomizedBreakpointPresentation getBreakpointPresentation(@NotNull XLineBreakpoint<?> breakpoint) {
public CustomizedBreakpointPresentation getBreakpointPresentation(@NotNull XBreakpoint<?> breakpoint) {
synchronized (myRegisteredBreakpoints) {
return myRegisteredBreakpoints.get(breakpoint);
}
@@ -424,10 +426,11 @@ public class XDebugSessionImpl implements XDebugSession {
private void doResume() {
myDispatcher.getMulticaster().beforeSessionResume();
myDebuggerManager.setActiveSession(this, null, false);
myDebuggerManager.setActiveSession(this, null, false, null);
mySuspendContext = null;
myCurrentStackFrame = null;
myCurrentPosition = null;
myActiveNonLineBreakpoint = null;
myPaused = false;
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
@@ -442,7 +445,7 @@ public class XDebugSessionImpl implements XDebugSession {
public void updateExecutionPosition() {
XExecutionStack activeExecutionStack = mySuspendContext.getActiveExecutionStack();
boolean isTopFrame = activeExecutionStack != null && activeExecutionStack.getTopFrame() == myCurrentStackFrame;
myDebuggerManager.updateExecutionPoint(myCurrentStackFrame.getSourcePosition(), !isTopFrame);
myDebuggerManager.updateExecutionPoint(myCurrentStackFrame.getSourcePosition(), !isTopFrame, isTopFrame ? getPositionIconRenderer() : null);
}
@@ -476,13 +479,25 @@ public class XDebugSessionImpl implements XDebugSession {
if (position != null) {
XExecutionStack activeExecutionStack = mySuspendContext.getActiveExecutionStack();
boolean isTopFrame = activeExecutionStack != null && activeExecutionStack.getTopFrame() == myCurrentStackFrame;
myDebuggerManager.setActiveSession(this, position, !isTopFrame);
myDebuggerManager.setActiveSession(this, position, !isTopFrame, isTopFrame ? getPositionIconRenderer() : null);
}
else {
myDebuggerManager.setActiveSession(this, null, false);
myDebuggerManager.setActiveSession(this, null, false, null);
}
}
public XBreakpoint<?> getActiveNonLineBreakpoint() {
return myActiveNonLineBreakpoint;
}
@Nullable
public GutterIconRenderer getPositionIconRenderer() {
if (myActiveNonLineBreakpoint != null) {
return ((XBreakpointBase<?,?,?>)myActiveNonLineBreakpoint).createGutterIconRenderer();
}
return null;
}
public void updateBreakpointPresentation(@NotNull final XLineBreakpoint<?> breakpoint,
@Nullable final Icon icon,
@Nullable final String errorMessage) {
@@ -544,6 +559,7 @@ public class XDebugSessionImpl implements XDebugSession {
return false;
}
myActiveNonLineBreakpoint = !(breakpoint instanceof XLineBreakpoint<?>) ? breakpoint : null;
positionReached(suspendContext);
return true;
}
@@ -591,7 +607,7 @@ public class XDebugSessionImpl implements XDebugSession {
myPaused = true;
if (myCurrentPosition != null) {
myDebuggerManager.setActiveSession(this, myCurrentPosition, false);
myDebuggerManager.setActiveSession(this, myCurrentPosition, false, getPositionIconRenderer());
}
UIUtil.invokeLaterIfNeeded(new Runnable() {
public void run() {
@@ -634,7 +650,7 @@ public class XDebugSessionImpl implements XDebugSession {
myCurrentPosition = null;
myCurrentStackFrame = null;
mySuspendContext = null;
myDebuggerManager.setActiveSession(this, null, false);
myDebuggerManager.setActiveSession(this, null, false, null);
XBreakpointManagerImpl breakpointManager = myDebuggerManager.getBreakpointManager();
breakpointManager.removeBreakpointListener(myBreakpointListener);
breakpointManager.getDependentBreakpointManager().removeListener(myDependentBreakpointListener);
@@ -29,6 +29,7 @@ import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.editor.markup.GutterIconRenderer;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.FileEditorManagerAdapter;
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
@@ -40,6 +41,10 @@ import com.intellij.openapi.vfs.impl.http.HttpVirtualFile;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.xmlb.annotations.Property;
import com.intellij.xdebugger.*;
import com.intellij.xdebugger.breakpoints.XBreakpoint;
import com.intellij.xdebugger.breakpoints.XBreakpointAdapter;
import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
import com.intellij.xdebugger.impl.breakpoints.XBreakpointBase;
import com.intellij.xdebugger.impl.breakpoints.XBreakpointManagerImpl;
import com.intellij.xdebugger.impl.ui.ExecutionPointHighlighter;
import com.intellij.xdebugger.impl.ui.XDebugSessionData;
@@ -81,6 +86,19 @@ public class XDebuggerManagerImpl extends XDebuggerManager implements ProjectCom
}
}
});
myBreakpointManager.addBreakpointListener(new XBreakpointAdapter<XBreakpoint<?>>() {
@Override
public void breakpointChanged(@NotNull XBreakpoint<?> breakpoint) {
if (!(breakpoint instanceof XLineBreakpoint)) {
final XDebugSessionImpl session = getCurrentSession();
if (session != null && breakpoint.equals(session.getActiveNonLineBreakpoint())) {
final XBreakpointBase breakpointBase = (XBreakpointBase)breakpoint;
breakpointBase.clearIcon();
myExecutionPointHighlighter.updateGutterIcon(breakpointBase.createGutterIconRenderer());
}
}
}
});
messageBus.connect().subscribe(RunContentManagerImpl.RUN_CONTENT_TOPIC, new RunContentWithExecutorListener() {
@Override
@@ -91,7 +109,7 @@ public class XDebuggerManagerImpl extends XDebuggerManager implements ProjectCom
session.activateSession();
}
else {
setActiveSession(null, null, false);
setActiveSession(null, null, false, null);
}
}
}
@@ -195,18 +213,19 @@ public class XDebuggerManagerImpl extends XDebuggerManager implements ProjectCom
}
}
public void setActiveSession(@Nullable XDebugSessionImpl session, @Nullable XSourcePosition position, boolean useSelection) {
public void setActiveSession(@Nullable XDebugSessionImpl session, @Nullable XSourcePosition position, boolean useSelection,
final @Nullable GutterIconRenderer gutterIconRenderer) {
boolean sessionChanged = myActiveSession != session;
myActiveSession = session;
updateExecutionPoint(position, useSelection);
updateExecutionPoint(position, useSelection, gutterIconRenderer);
if (sessionChanged) {
onActiveSessionChanged();
}
}
public void updateExecutionPoint(XSourcePosition position, boolean useSelection) {
public void updateExecutionPoint(XSourcePosition position, boolean useSelection, @Nullable GutterIconRenderer gutterIconRenderer) {
if (position != null) {
myExecutionPointHighlighter.show(position, useSelection);
myExecutionPointHighlighter.show(position, useSelection, gutterIconRenderer);
}
else {
myExecutionPointHighlighter.hide();
@@ -0,0 +1,135 @@
/*
* Copyright 2000-2011 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.breakpoints;
import com.intellij.util.xmlb.annotations.Attribute;
import com.intellij.util.xmlb.annotations.Property;
import com.intellij.util.xmlb.annotations.Tag;
import com.intellij.util.xmlb.annotations.Transient;
import com.intellij.xdebugger.breakpoints.SuspendPolicy;
import com.intellij.xdebugger.breakpoints.XBreakpoint;
import com.intellij.xdebugger.breakpoints.XBreakpointProperties;
import com.intellij.xdebugger.breakpoints.XBreakpointType;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
@Tag("breakpoint")
public class BreakpointState<B extends XBreakpoint<P>, P extends XBreakpointProperties, T extends XBreakpointType<B,P>> {
private String myTypeId;
private boolean myEnabled;
private Element myPropertiesElement;
private SuspendPolicy mySuspendPolicy = SuspendPolicy.ALL;
private boolean myLogMessage;
private String myLogExpression;
private String myCondition;
private XBreakpointDependencyState myDependencyState;
public BreakpointState() {
}
public BreakpointState(final boolean enabled, final String typeId) {
myEnabled = enabled;
myTypeId = typeId;
}
@Attribute("enabled")
public boolean isEnabled() {
return myEnabled;
}
public void setEnabled(final boolean enabled) {
myEnabled = enabled;
}
@Attribute("type")
public String getTypeId() {
return myTypeId;
}
public void setTypeId(final String typeId) {
myTypeId = typeId;
}
@Tag("properties")
public Element getPropertiesElement() {
return myPropertiesElement;
}
public void setPropertiesElement(final Element propertiesElement) {
myPropertiesElement = propertiesElement;
}
@Attribute("suspend")
public String getSuspendPolicyString() {
return mySuspendPolicy.name();
}
public void setSuspendPolicyString(final String suspendPolicy) {
mySuspendPolicy = SuspendPolicy.valueOf(suspendPolicy);
}
@Transient
public SuspendPolicy getSuspendPolicy() {
return mySuspendPolicy;
}
public void setSuspendPolicy(SuspendPolicy suspendPolicy) {
mySuspendPolicy = suspendPolicy;
}
@Attribute("log-message")
public boolean isLogMessage() {
return myLogMessage;
}
public void setLogMessage(final boolean logMessage) {
myLogMessage = logMessage;
}
@Tag("log-expression")
public String getLogExpression() {
return myLogExpression;
}
public void setLogExpression(final String logExpression) {
myLogExpression = logExpression;
}
@Tag("condition")
public String getCondition() {
return myCondition;
}
public void setCondition(final String condition) {
myCondition = condition;
}
@Property(surroundWithTag = false)
public XBreakpointDependencyState getDependencyState() {
return myDependencyState;
}
public void setDependencyState(final XBreakpointDependencyState dependencyState) {
myDependencyState = dependencyState;
}
public XBreakpointBase<B,P,?> createBreakpoint(@NotNull T type, @NotNull XBreakpointManagerImpl breakpointManager) {
return new XBreakpointBase<B, P, BreakpointState<B,P,?>>(type, breakpointManager, this);
}
}
@@ -0,0 +1,63 @@
/*
* Copyright 2000-2011 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.breakpoints;
import com.intellij.util.xmlb.annotations.Tag;
import com.intellij.xdebugger.breakpoints.XBreakpointProperties;
import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
import com.intellij.xdebugger.breakpoints.XLineBreakpointType;
import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
@Tag("line-breakpoint")
public class LineBreakpointState<P extends XBreakpointProperties> extends
BreakpointState<XLineBreakpoint<P>, P, XLineBreakpointType<P>> {
private String myFileUrl;
private int myLine;
public LineBreakpointState() {
}
public LineBreakpointState(final boolean enabled, final String typeId, final String fileUrl, final int line) {
super(enabled, typeId);
myFileUrl = fileUrl;
myLine = line;
}
@Tag("url")
public String getFileUrl() {
return myFileUrl;
}
public void setFileUrl(final String fileUrl) {
myFileUrl = fileUrl;
}
@Tag("line")
public int getLine() {
return myLine;
}
public void setLine(final int line) {
myLine = line;
}
public XBreakpointBase<XLineBreakpoint<P>,P, ?> createBreakpoint(@NotNull final XLineBreakpointType<P> type, @NotNull XBreakpointManagerImpl breakpointManager) {
return new XLineBreakpointImpl<P>(type, breakpointManager, this);
}
}
@@ -0,0 +1,38 @@
/*
* Copyright 2000-2011 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.breakpoints;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.xdebugger.XDebuggerBundle;
import com.intellij.xdebugger.XDebuggerUtil;
import com.intellij.xdebugger.breakpoints.XBreakpointProperties;
/**
* @author nik
*/
class RemoveBreakpointGutterIconAction<P extends XBreakpointProperties> extends AnAction {
private XBreakpointBase<?,?,?> myBreakpoint;
RemoveBreakpointGutterIconAction(XBreakpointBase<?, ?, ?> breakpoint) {
super(XDebuggerBundle.message("xdebugger.remove.line.breakpoint.action.text"));
myBreakpoint = breakpoint;
}
public void actionPerformed(final AnActionEvent e) {
XDebuggerUtil.getInstance().removeBreakpoint(myBreakpoint.getProject(), myBreakpoint);
}
}
@@ -0,0 +1,37 @@
/*
* Copyright 2000-2011 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.breakpoints;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.xdebugger.XDebuggerBundle;
import com.intellij.xdebugger.breakpoints.XBreakpoint;
/**
* @author nik
*/
class ToggleBreakpointGutterIconAction extends AnAction {
private XBreakpoint<?> myBreakpoint;
ToggleBreakpointGutterIconAction(XBreakpoint<?> breakpoint) {
super(breakpoint.isEnabled() ? XDebuggerBundle.message("xdebugger.disable.breakpoint.action.text") : XDebuggerBundle.message("xdebugger.enable.breakpoint.action.text"));
this.myBreakpoint = breakpoint;
}
public void actionPerformed(final AnActionEvent e) {
myBreakpoint.setEnabled(!myBreakpoint.isEnabled());
}
}
@@ -15,34 +15,52 @@
*/
package com.intellij.xdebugger.impl.breakpoints;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.Separator;
import com.intellij.openapi.editor.markup.GutterDraggableObject;
import com.intellij.openapi.editor.markup.GutterIconRenderer;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.pom.Navigatable;
import com.intellij.util.StringBuilderSpinAllocator;
import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
import com.intellij.util.xmlb.XmlSerializer;
import com.intellij.util.xmlb.annotations.Attribute;
import com.intellij.util.xmlb.annotations.Property;
import com.intellij.util.xmlb.annotations.Tag;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XDebuggerBundle;
import com.intellij.xdebugger.XDebuggerManager;
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.impl.XDebugSessionImpl;
import com.intellij.xdebugger.impl.XDebuggerUtilImpl;
import com.intellij.xdebugger.breakpoints.SuspendPolicy;
import com.intellij.xdebugger.breakpoints.XBreakpoint;
import com.intellij.xdebugger.breakpoints.XBreakpointProperties;
import com.intellij.xdebugger.breakpoints.XBreakpointType;
import com.intellij.xdebugger.impl.actions.ViewBreakpointsAction;
import com.intellij.xdebugger.ui.DebuggerIcons;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.Collections;
import java.util.List;
/**
* @author nik
*/
public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointProperties, S extends XBreakpointBase.BreakpointState> extends UserDataHolderBase implements XBreakpoint<P> {
public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointProperties, S extends BreakpointState> extends UserDataHolderBase implements XBreakpoint<P> {
private static final SkipDefaultValuesSerializationFilters SERIALIZATION_FILTERS = new SkipDefaultValuesSerializationFilters();
@NonNls private static final String BR_NBSP = "<br>&nbsp;";
private final XBreakpointType<Self, P> myType;
private final @Nullable P myProperties;
protected final S myState;
private final XBreakpointManagerImpl myBreakpointManager;
private Icon myIcon;
private CustomizedBreakpointPresentation myCustomizedPresentation;
public XBreakpointBase(final XBreakpointType<Self, P> type, XBreakpointManagerImpl breakpointManager, final @Nullable P properties, final S state) {
myState = state;
@@ -101,12 +119,12 @@ public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointP
@NotNull
public SuspendPolicy getSuspendPolicy() {
return myState.mySuspendPolicy;
return myState.getSuspendPolicy();
}
public void setSuspendPolicy(@NotNull SuspendPolicy policy) {
if (myState.mySuspendPolicy != policy) {
myState.mySuspendPolicy = policy;
if (myState.getSuspendPolicy() != policy) {
myState.setSuspendPolicy(policy);
fireBreakpointChanged();
}
}
@@ -148,7 +166,7 @@ public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointP
return true;
}
@Nullable
@Nullable
public P getProperties() {
return myProperties;
}
@@ -175,104 +193,209 @@ public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointP
public void dispose() {
}
@Tag("breakpoint")
public static class BreakpointState<B extends XBreakpoint<P>, P extends XBreakpointProperties, T extends XBreakpointType<B,P>> {
private String myTypeId;
private boolean myEnabled;
private Element myPropertiesElement;
private SuspendPolicy mySuspendPolicy = SuspendPolicy.ALL;
private boolean myLogMessage;
private String myLogExpression;
private String myCondition;
private XBreakpointDependencyState myDependencyState;
public BreakpointState() {
}
public BreakpointState(final boolean enabled, final String typeId) {
myEnabled = enabled;
myTypeId = typeId;
}
@Attribute("enabled")
public boolean isEnabled() {
return myEnabled;
}
public void setEnabled(final boolean enabled) {
myEnabled = enabled;
}
@Attribute("type")
public String getTypeId() {
return myTypeId;
}
public void setTypeId(final String typeId) {
myTypeId = typeId;
}
@Tag("properties")
public Element getPropertiesElement() {
return myPropertiesElement;
}
public void setPropertiesElement(final Element propertiesElement) {
myPropertiesElement = propertiesElement;
}
@Attribute("suspend")
public String getSuspendPolicy() {
return mySuspendPolicy.name();
}
public void setSuspendPolicy(final String suspendPolicy) {
mySuspendPolicy = SuspendPolicy.valueOf(suspendPolicy);
}
@Attribute("log-message")
public boolean isLogMessage() {
return myLogMessage;
}
public void setLogMessage(final boolean logMessage) {
myLogMessage = logMessage;
}
@Tag("log-expression")
public String getLogExpression() {
return myLogExpression;
}
public void setLogExpression(final String logExpression) {
myLogExpression = logExpression;
}
@Tag("condition")
public String getCondition() {
return myCondition;
}
public void setCondition(final String condition) {
myCondition = condition;
}
@Property(surroundWithTag = false)
public XBreakpointDependencyState getDependencyState() {
return myDependencyState;
}
public void setDependencyState(final XBreakpointDependencyState dependencyState) {
myDependencyState = dependencyState;
}
public XBreakpointBase<B,P,?> createBreakpoint(@NotNull T type, @NotNull XBreakpointManagerImpl breakpointManager) {
return new XBreakpointBase<B, P, BreakpointState<B,P,?>>(type, breakpointManager, this);
}
}
@Override
public String toString() {
return "XBreakpointBase(type=" + myType + ")";
}
@Nullable
protected GutterDraggableObject createBreakpointDraggableObject() {
return null;
}
protected List<? extends AnAction> getAdditionalPopupMenuActions(XDebugSession session) {
return Collections.emptyList();
}
public String getDescription() {
@NonNls StringBuilder builder = StringBuilderSpinAllocator.alloc();
try {
builder.append("<html><body>");
builder.append(XBreakpointUtil.getDisplayText(this));
String errorMessage = getErrorMessage();
if (errorMessage != null) {
builder.append(BR_NBSP);
builder.append("<font color=\"red\">");
builder.append(errorMessage);
builder.append("</font>");
}
SuspendPolicy suspendPolicy = getSuspendPolicy();
if (suspendPolicy == SuspendPolicy.THREAD) {
builder.append(BR_NBSP).append(XDebuggerBundle.message("xbreakpoint.tooltip.suspend.policy.thread"));
}
else if (suspendPolicy == SuspendPolicy.NONE) {
builder.append(BR_NBSP).append(XDebuggerBundle.message("xbreakpoint.tooltip.suspend.policy.none"));
}
String condition = getCondition();
if (condition != null) {
builder.append(BR_NBSP);
builder.append(XDebuggerBundle.message("xbreakpoint.tooltip.condition"));
builder.append("&nbsp;");
builder.append(condition);
}
if (isLogMessage()) {
builder.append(BR_NBSP).append(XDebuggerBundle.message("xbreakpoint.tooltip.log.message"));
}
String logExpression = getLogExpression();
if (logExpression != null) {
builder.append(BR_NBSP);
builder.append(XDebuggerBundle.message("xbreakpoint.tooltip.log.expression"));
builder.append("&nbsp;");
builder.append(logExpression);
}
XBreakpoint<?> masterBreakpoint = getBreakpointManager().getDependentBreakpointManager().getMasterBreakpoint(this);
if (masterBreakpoint != null) {
builder.append(BR_NBSP);
String str = XDebuggerBundle.message("xbreakpoint.tooltip.depends.on");
builder.append(str);
builder.append("&nbsp;");
builder.append(XBreakpointUtil.getDisplayText(masterBreakpoint));
}
builder.append("</body><html");
return builder.toString();
}
finally {
StringBuilderSpinAllocator.dispose(builder);
}
}
protected void updateIcon() {
myIcon = calculateIcon();
}
@NotNull
private Icon calculateIcon() {
if (!isEnabled()) {
// disabled icon takes precedence to other to visually distinguish it and provide feedback then it is enabled/disabled
// (e.g. in case of mute-mode we would like to differentiate muted but enabled breakpoints from simply disabled ones)
return getType().getDisabledIcon();
}
XDebugSessionImpl session = getBreakpointManager().getDebuggerManager().getCurrentSession();
if (session == null) {
if (getBreakpointManager().getDependentBreakpointManager().getMasterBreakpoint(this) != null) {
return getType().getDisabledDependentIcon();
}
}
else {
if (session.areBreakpointsMuted()) {
return DebuggerIcons.MUTED_BREAKPOINT_ICON;
}
if (session.isDisabledSlaveBreakpoint(this)) {
return getType().getDisabledDependentIcon();
}
CustomizedBreakpointPresentation presentation = session.getBreakpointPresentation(this);
if (presentation != null) {
Icon icon = presentation.getIcon();
if (icon != null) {
return icon;
}
}
}
if (myCustomizedPresentation != null) {
final Icon icon = myCustomizedPresentation.getIcon();
if (icon != null) {
return icon;
}
}
return getType().getEnabledIcon();
}
public Icon getIcon() {
if (myIcon == null) {
updateIcon();
}
return myIcon;
}
@Nullable
public String getErrorMessage() {
final XDebugSessionImpl currentSession = getBreakpointManager().getDebuggerManager().getCurrentSession();
if (currentSession != null) {
CustomizedBreakpointPresentation presentation = currentSession.getBreakpointPresentation(this);
if (presentation != null) {
final String message = presentation.getErrorMessage();
if (message != null) return message;
}
}
return myCustomizedPresentation != null ? myCustomizedPresentation.getErrorMessage() : null;
}
public void setCustomizedPresentation(CustomizedBreakpointPresentation presentation) {
myCustomizedPresentation = presentation;
}
@NotNull
public GutterIconRenderer createGutterIconRenderer() {
return new BreakpointGutterIconRenderer();
}
public void clearIcon() {
myIcon = null;
}
protected class BreakpointGutterIconRenderer extends GutterIconRenderer {
@NotNull
public Icon getIcon() {
return XBreakpointBase.this.getIcon();
}
@Nullable
public AnAction getClickAction() {
return new RemoveBreakpointGutterIconAction(XBreakpointBase.this);
}
@Nullable
public AnAction getMiddleButtonClickAction() {
return new ToggleBreakpointGutterIconAction(XBreakpointBase.this);
}
@Nullable
public ActionGroup getPopupMenuActions() {
DefaultActionGroup group = new DefaultActionGroup();
final XDebuggerManager debuggerManager = XDebuggerManager.getInstance(getProject());
if (!debuggerManager.getBreakpointManager().isDefaultBreakpoint(XBreakpointBase.this)) {
group.add(new RemoveBreakpointGutterIconAction(XBreakpointBase.this));
}
group.add(new ToggleBreakpointGutterIconAction(XBreakpointBase.this));
for (AnAction action : getAdditionalPopupMenuActions(debuggerManager.getCurrentSession())) {
group.add(action);
}
group.add(new Separator());
group.add(new ViewBreakpointsAction(XDebuggerBundle.message("xdebugger.view.breakpoint.properties.action"), XBreakpointBase.this));
return group;
}
@Nullable
public String getTooltipText() {
return getDescription();
}
@Override
public GutterDraggableObject getDraggableObject() {
return createBreakpointDraggableObject();
}
private XBreakpointBase<?,?,?> getBreakpoint() {
return XBreakpointBase.this;
}
@Override
public boolean equals(Object obj) {
return obj instanceof XLineBreakpointImpl.BreakpointGutterIconRenderer
&& getBreakpoint() == ((XLineBreakpointImpl.BreakpointGutterIconRenderer)obj).getBreakpoint()
&& Comparing.equal(getIcon(), ((XLineBreakpointImpl.BreakpointGutterIconRenderer)obj).getIcon())
;
}
@Override
public int hashCode() {
return getBreakpoint().hashCode();
}
}
}
@@ -114,8 +114,8 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta
private <T extends XBreakpointProperties> XBreakpointBase<?, T, ?> createBreakpoint(XBreakpointType<XBreakpoint<T>, T> type,
T properties, final boolean enabled) {
XBreakpointBase.BreakpointState<?,T,?> state = new XBreakpointBase.BreakpointState<XBreakpoint<T>,T,XBreakpointType<XBreakpoint<T>,T>>(enabled, type.getId());
return new XBreakpointBase<XBreakpoint<T>,T, XBreakpointBase.BreakpointState<?,T,?>>(type, this, properties, state);
BreakpointState<?,T,?> state = new BreakpointState<XBreakpoint<T>,T,XBreakpointType<XBreakpoint<T>,T>>(enabled, type.getId());
return new XBreakpointBase<XBreakpoint<T>,T, BreakpointState<?,T,?>>(type, this, properties, state);
}
private <T extends XBreakpointProperties> void addBreakpoint(final XBreakpointBase<?, T, ?> breakpoint, final boolean defaultBreakpoint,
@@ -286,7 +286,7 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta
myDependentBreakpointManager.saveState();
BreakpointManagerState state = new BreakpointManagerState();
for (XBreakpointBase<?, ?, ?> breakpoint : myDefaultBreakpoints.values()) {
final XBreakpointBase.BreakpointState breakpointState = breakpoint.getState();
final BreakpointState breakpointState = breakpoint.getState();
if (differsFromDefault(breakpoint.getType(), breakpointState)) {
state.getDefaultBreakpoints().add(breakpointState);
}
@@ -301,13 +301,13 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta
}
private <P extends XBreakpointProperties> boolean differsFromDefault(XBreakpointType<?, P> type,
XBreakpointBase.BreakpointState state) {
BreakpointState state) {
final XBreakpoint<P> defaultBreakpoint = createDefaultBreakpoint(type);
if (defaultBreakpoint == null) {
return false;
}
XBreakpointBase.BreakpointState defaultState = ((XBreakpointBase)defaultBreakpoint).getState();
BreakpointState defaultState = ((XBreakpointBase)defaultBreakpoint).getState();
Element defaultElement = XmlSerializer.serialize(defaultState, SERIALIZATION_FILTER);
Element currentElement = XmlSerializer.serialize(state, SERIALIZATION_FILTER);
return !JDOMUtil.areElementsEqual(defaultElement, currentElement);
@@ -323,7 +323,7 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta
}
myDefaultBreakpoints.clear();
for (XBreakpointBase.BreakpointState breakpointState : state.getDefaultBreakpoints()) {
for (BreakpointState breakpointState : state.getDefaultBreakpoints()) {
loadBreakpoint(breakpointState, true);
}
for (XBreakpointType<?, ?> type : XBreakpointUtil.getBreakpointTypes()) {
@@ -335,7 +335,7 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta
for (XBreakpointBase<?,?,?> breakpoint : myBreakpoints.values()) {
doRemoveBreakpoint(breakpoint);
}
for (XBreakpointBase.BreakpointState breakpointState : state.getBreakpoints()) {
for (BreakpointState breakpointState : state.getBreakpoints()) {
loadBreakpoint(breakpointState, false);
}
myDependentBreakpointManager.loadState();
@@ -361,7 +361,7 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta
});
}
private void loadBreakpoint(XBreakpointBase.BreakpointState breakpointState, final boolean defaultBreakpoint) {
private void loadBreakpoint(BreakpointState breakpointState, final boolean defaultBreakpoint) {
XBreakpointBase<?,?,?> breakpoint = createBreakpoint(breakpointState);
if (breakpoint != null) {
addBreakpoint(breakpoint, defaultBreakpoint, false);
@@ -378,7 +378,7 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta
}
@Nullable
private XBreakpointBase<?,?,?> createBreakpoint(final XBreakpointBase.BreakpointState breakpointState) {
private XBreakpointBase<?,?,?> createBreakpoint(final BreakpointState breakpointState) {
XBreakpointType<?,?> type = XBreakpointUtil.findType(breakpointState.getTypeId());
if (type == null) return null;
//noinspection unchecked
@@ -388,20 +388,20 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta
@Tag("breakpoint-manager")
public static class BreakpointManagerState {
private List<XBreakpointBase.BreakpointState> myDefaultBreakpoints = new ArrayList<XBreakpointBase.BreakpointState>();
private List<XBreakpointBase.BreakpointState> myBreakpoints = new ArrayList<XBreakpointBase.BreakpointState>();
private List<BreakpointState> myDefaultBreakpoints = new ArrayList<BreakpointState>();
private List<BreakpointState> myBreakpoints = new ArrayList<BreakpointState>();
private Map<String, XBreakpointTypeDialogState> myBreakpointTypeDialogProperties = new HashMap<String, XBreakpointTypeDialogState>();
@Tag("default-breakpoints")
@AbstractCollection(surroundWithTag = false)
public List<XBreakpointBase.BreakpointState> getDefaultBreakpoints() {
public List<BreakpointState> getDefaultBreakpoints() {
return myDefaultBreakpoints;
}
@Tag("breakpoints")
@AbstractCollection(surroundWithTag = false,
elementTypes = {XBreakpointBase.BreakpointState.class, XLineBreakpointImpl.LineBreakpointState.class})
public List<XBreakpointBase.BreakpointState> getBreakpoints() {
elementTypes = {BreakpointState.class, LineBreakpointState.class})
public List<BreakpointState> getBreakpoints() {
return myBreakpoints;
}
@@ -412,11 +412,11 @@ public class XBreakpointManagerImpl implements XBreakpointManager, PersistentSta
return myBreakpointTypeDialogProperties;
}
public void setBreakpoints(final List<XBreakpointBase.BreakpointState> breakpoints) {
public void setBreakpoints(final List<BreakpointState> breakpoints) {
myBreakpoints = breakpoints;
}
public void setDefaultBreakpoints(List<XBreakpointBase.BreakpointState> defaultBreakpoints) {
public void setDefaultBreakpoints(List<BreakpointState> defaultBreakpoints) {
myDefaultBreakpoints = defaultBreakpoints;
}
@@ -15,7 +15,7 @@
*/
package com.intellij.xdebugger.impl.breakpoints;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.application.Result;
@@ -24,7 +24,6 @@ import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.ex.MarkupModelEx;
import com.intellij.openapi.editor.markup.GutterDraggableObject;
import com.intellij.openapi.editor.markup.GutterIconRenderer;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.fileEditor.FileDocumentManager;
@@ -34,44 +33,37 @@ import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.util.StringBuilderSpinAllocator;
import com.intellij.util.xmlb.annotations.Tag;
import com.intellij.xdebugger.XDebuggerBundle;
import com.intellij.xdebugger.XDebuggerManager;
import com.intellij.xdebugger.XDebuggerUtil;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.breakpoints.*;
import com.intellij.xdebugger.impl.XDebugSessionImpl;
import com.intellij.xdebugger.breakpoints.XBreakpointProperties;
import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
import com.intellij.xdebugger.breakpoints.XLineBreakpointType;
import com.intellij.xdebugger.impl.XSourcePositionImpl;
import com.intellij.xdebugger.impl.actions.ViewBreakpointsAction;
import com.intellij.xdebugger.ui.DebuggerColors;
import com.intellij.xdebugger.ui.DebuggerIcons;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.dnd.DragSource;
import java.util.List;
/**
* @author nik
*/
public class XLineBreakpointImpl<P extends XBreakpointProperties> extends XBreakpointBase<XLineBreakpoint<P>, P, XLineBreakpointImpl.LineBreakpointState<P>> implements XLineBreakpoint<P> {
public class XLineBreakpointImpl<P extends XBreakpointProperties> extends XBreakpointBase<XLineBreakpoint<P>, P, LineBreakpointState<P>> implements XLineBreakpoint<P> {
@Nullable private RangeHighlighter myHighlighter;
private final XLineBreakpointType<P> myType;
private Icon myIcon;
private XSourcePosition mySourcePosition;
@NonNls private static final String BR_NBSP = "<br>&nbsp;";
private boolean myDisposed;
private CustomizedBreakpointPresentation myCustomizedPresentation;
public XLineBreakpointImpl(final XLineBreakpointType<P> type, XBreakpointManagerImpl breakpointManager, String url, int line, @Nullable final P properties) {
super(type, breakpointManager, properties, new LineBreakpointState<P>(true, type.getId(), url, line));
myType = type;
}
private XLineBreakpointImpl(final XLineBreakpointType<P> type, XBreakpointManagerImpl breakpointManager, final LineBreakpointState<P> breakpointState) {
XLineBreakpointImpl(final XLineBreakpointType<P> type,
XBreakpointManagerImpl breakpointManager,
final LineBreakpointState<P> breakpointState) {
super(type, breakpointManager, breakpointState);
myType = type;
}
@@ -92,7 +84,7 @@ public class XLineBreakpointImpl<P extends XBreakpointProperties> extends XBreak
attributes);
if (highlighter != null) {
updateIcon();
setupGutterRenderer(highlighter);
highlighter.setGutterIconRenderer(createGutterIconRenderer());
}
myHighlighter = highlighter;
}
@@ -109,57 +101,11 @@ public class XLineBreakpointImpl<P extends XBreakpointProperties> extends XBreak
return VirtualFileManager.getInstance().findFileByUrl(getFileUrl());
}
private void setupGutterRenderer(final RangeHighlighter highlighter) {
highlighter.setGutterIconRenderer(new BreakpointGutterIconRenderer());
}
@NotNull
public XLineBreakpointType<P> getType() {
return myType;
}
private void updateIcon() {
myIcon = calculateIcon();
}
@NotNull
private Icon calculateIcon() {
if (!isEnabled()) {
// disabled icon takes precedence to other to visually distinguish it and provide feedback then it is enabled/disabled
// (e.g. in case of mute-mode we would like to differentiate muted but enabled breakpoints from simply disabled ones)
return myType.getDisabledIcon();
}
XDebugSessionImpl session = getBreakpointManager().getDebuggerManager().getCurrentSession();
if (session == null) {
if (getBreakpointManager().getDependentBreakpointManager().getMasterBreakpoint(this) != null) {
return myType.getDisabledDependentIcon();
}
}
else {
if (session.areBreakpointsMuted()) {
return DebuggerIcons.MUTED_BREAKPOINT_ICON;
}
if (session.isDisabledSlaveBreakpoint(this)) {
return myType.getDisabledDependentIcon();
}
CustomizedBreakpointPresentation presentation = session.getBreakpointPresentation(this);
if (presentation != null) {
Icon icon = presentation.getIcon();
if (icon != null) {
return icon;
}
}
}
if (myCustomizedPresentation != null) {
final Icon icon = myCustomizedPresentation.getIcon();
if (icon != null) {
return icon;
}
}
return myType.getEnabledIcon();
}
public int getLine() {
return myState.getLine();
}
@@ -208,88 +154,28 @@ public class XLineBreakpointImpl<P extends XBreakpointProperties> extends XBreak
}
}
public Icon getIcon() {
if (myIcon == null) {
updateIcon();
}
return myIcon;
}
public String getDescription() {
@NonNls StringBuilder builder = StringBuilderSpinAllocator.alloc();
try {
builder.append("<html><body>");
builder.append(myType.getDisplayText(this));
String errorMessage = getErrorMessage();
if (errorMessage != null) {
builder.append(BR_NBSP);
builder.append("<font color=\"red\">");
builder.append(errorMessage);
builder.append("</font>");
@Override
protected GutterDraggableObject createBreakpointDraggableObject() {
return new GutterDraggableObject() {
public boolean copy(int line, VirtualFile file) {
if (canMoveTo(line, file)) {
setFileUrl(file.getUrl());
setLine(line);
return true;
}
return false;
}
SuspendPolicy suspendPolicy = getSuspendPolicy();
if (suspendPolicy == SuspendPolicy.THREAD) {
builder.append(BR_NBSP).append(XDebuggerBundle.message("xbreakpoint.tooltip.suspend.policy.thread"));
public Cursor getCursor(int line) {
return canMoveTo(line, getFile()) ? DragSource.DefaultMoveDrop : DragSource.DefaultMoveNoDrop;
}
else if (suspendPolicy == SuspendPolicy.NONE) {
builder.append(BR_NBSP).append(XDebuggerBundle.message("xbreakpoint.tooltip.suspend.policy.none"));
}
String condition = getCondition();
if (condition != null) {
builder.append(BR_NBSP);
builder.append(XDebuggerBundle.message("xbreakpoint.tooltip.condition"));
builder.append("&nbsp;");
builder.append(condition);
}
if (isLogMessage()) {
builder.append(BR_NBSP).append(XDebuggerBundle.message("xbreakpoint.tooltip.log.message"));
}
String logExpression = getLogExpression();
if (logExpression != null) {
builder.append(BR_NBSP);
builder.append(XDebuggerBundle.message("xbreakpoint.tooltip.log.expression"));
builder.append("&nbsp;");
builder.append(logExpression);
}
XBreakpoint<?> masterBreakpoint = getBreakpointManager().getDependentBreakpointManager().getMasterBreakpoint(this);
if (masterBreakpoint != null) {
builder.append(BR_NBSP);
String str = XDebuggerBundle.message("xbreakpoint.tooltip.depends.on");
builder.append(str);
builder.append("&nbsp;");
builder.append(XBreakpointUtil.getDisplayText(masterBreakpoint));
}
builder.append("</body><html");
return builder.toString();
}
finally {
StringBuilderSpinAllocator.dispose(builder);
}
};
}
private boolean canMoveTo(int line, VirtualFile file) {
return file != null && myType.canPutAt(file, line, getProject()) && getBreakpointManager().findBreakpointAtLine(myType, file, line) == null;
}
@Nullable
public String getErrorMessage() {
final XDebugSessionImpl currentSession = getBreakpointManager().getDebuggerManager().getCurrentSession();
if (currentSession != null) {
CustomizedBreakpointPresentation presentation = currentSession.getBreakpointPresentation(this);
if (presentation != null) {
final String message = presentation.getErrorMessage();
if (message != null) return message;
}
}
return myCustomizedPresentation != null ? myCustomizedPresentation.getErrorMessage() : null;
}
public void updatePosition() {
if (myHighlighter != null && myHighlighter.isValid()) {
Document document = myHighlighter.getDocument();
@@ -313,134 +199,7 @@ public class XLineBreakpointImpl<P extends XBreakpointProperties> extends XBreak
}
}
public void setCustomizedPresentation(CustomizedBreakpointPresentation presentation) {
myCustomizedPresentation = presentation;
protected List<? extends AnAction> getAdditionalPopupMenuActions(final XDebugSession session) {
return getType().getAdditionalPopupMenuActions(this, session);
}
@Tag("line-breakpoint")
public static class LineBreakpointState<P extends XBreakpointProperties> extends XBreakpointBase.BreakpointState<XLineBreakpoint<P>, P, XLineBreakpointType<P>> {
private String myFileUrl;
private int myLine;
public LineBreakpointState() {
}
public LineBreakpointState(final boolean enabled, final String typeId, final String fileUrl, final int line) {
super(enabled, typeId);
myFileUrl = fileUrl;
myLine = line;
}
@Tag("url")
public String getFileUrl() {
return myFileUrl;
}
public void setFileUrl(final String fileUrl) {
myFileUrl = fileUrl;
}
@Tag("line")
public int getLine() {
return myLine;
}
public void setLine(final int line) {
myLine = line;
}
public XBreakpointBase<XLineBreakpoint<P>,P, ?> createBreakpoint(@NotNull final XLineBreakpointType<P> type, @NotNull XBreakpointManagerImpl breakpointManager) {
return new XLineBreakpointImpl<P>(type, breakpointManager, this);
}
}
private class BreakpointGutterIconRenderer extends GutterIconRenderer {
@NotNull
public Icon getIcon() {
return XLineBreakpointImpl.this.getIcon();
}
@Nullable
public AnAction getClickAction() {
return new MyRemoveBreakpointAction();
}
@Nullable
public AnAction getMiddleButtonClickAction() {
return new MyToggleBreakpointAction();
}
@Nullable
public ActionGroup getPopupMenuActions() {
DefaultActionGroup group = new DefaultActionGroup();
group.add(new MyRemoveBreakpointAction());
group.add(new MyToggleBreakpointAction());
for (AnAction action : myType.getAdditionalPopupMenuActions(XLineBreakpointImpl.this, XDebuggerManager.getInstance(getProject()).getCurrentSession())) {
group.add(action);
}
group.add(new Separator());
group.add(new ViewBreakpointsAction(XDebuggerBundle.message("xdebugger.view.breakpoint.properties.action"), XLineBreakpointImpl.this));
return group;
}
@Nullable
public String getTooltipText() {
return getDescription();
}
@Override
public GutterDraggableObject getDraggableObject() {
return new GutterDraggableObject() {
public boolean copy(int line, VirtualFile file) {
if (canMoveTo(line, file)) {
setFileUrl(file.getUrl());
setLine(line);
return true;
}
return false;
}
public Cursor getCursor(int line) {
return canMoveTo(line, getFile()) ? DragSource.DefaultMoveDrop : DragSource.DefaultMoveNoDrop;
}
};
}
private XLineBreakpointImpl getXLineBreakpoint() {
return XLineBreakpointImpl.this;
}
@Override
public boolean equals(Object obj) {
return obj.getClass() == getClass()
&& getXLineBreakpoint() == ((BreakpointGutterIconRenderer)obj).getXLineBreakpoint()
&& Comparing.equal(getIcon(), ((BreakpointGutterIconRenderer)obj).getIcon())
;
}
@Override
public int hashCode() {
return getXLineBreakpoint().hashCode();
}
}
private class MyRemoveBreakpointAction extends AnAction {
private MyRemoveBreakpointAction() {
super(XDebuggerBundle.message("xdebugger.remove.line.breakpoint.action.text"));
}
public void actionPerformed(final AnActionEvent e) {
XDebuggerUtil.getInstance().removeBreakpoint(XLineBreakpointImpl.this.getProject(), XLineBreakpointImpl.this);
}
}
private class MyToggleBreakpointAction extends AnAction {
private MyToggleBreakpointAction() {
super(isEnabled() ? XDebuggerBundle.message("xdebugger.disable.breakpoint.action.text") : XDebuggerBundle.message("xdebugger.enable.breakpoint.action.text"));
}
public void actionPerformed(final AnActionEvent e) {
setEnabled(!isEnabled());
}
}
}
@@ -20,6 +20,7 @@ import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.markup.GutterIconRenderer;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditorManager;
@@ -41,16 +42,18 @@ public class ExecutionPointHighlighter {
private XSourcePosition mySourcePosition;
private OpenFileDescriptor myOpenFileDescriptor;
private boolean myUseSelection;
private GutterIconRenderer myGutterIconRenderer;
public ExecutionPointHighlighter(final Project project) {
myProject = project;
}
public void show(final @NotNull XSourcePosition position, final boolean useSelection) {
public void show(final @NotNull XSourcePosition position, final boolean useSelection,
@Nullable final GutterIconRenderer gutterIconRenderer) {
DebuggerUIUtil.invokeOnEventDispatch(new Runnable() {
public void run() {
if (!myProject.isDisposed()) {
doShow(position, useSelection);
doShow(position, useSelection, gutterIconRenderer);
}
}
});
@@ -76,16 +79,28 @@ public class ExecutionPointHighlighter {
}
public void update() {
show(mySourcePosition, myUseSelection);
show(mySourcePosition, myUseSelection, myGutterIconRenderer);
}
private void doShow(@NotNull XSourcePosition position, final boolean useSelection) {
public void updateGutterIcon(@NotNull final GutterIconRenderer renderer) {
DebuggerUIUtil.invokeOnEventDispatch(new Runnable() {
@Override
public void run() {
if (myRangeHighlighter != null && myGutterIconRenderer != null) {
myRangeHighlighter.setGutterIconRenderer(renderer);
}
}
});
}
private void doShow(@NotNull XSourcePosition position, final boolean useSelection, @Nullable GutterIconRenderer renderer) {
ApplicationManager.getApplication().assertIsDispatchThread();
removeHighlighter();
mySourcePosition = position;
myEditor = openEditor();
myUseSelection = useSelection;
myGutterIconRenderer = renderer;
if (myEditor != null) {
addHighlighter();
}
@@ -137,5 +152,6 @@ public class ExecutionPointHighlighter {
EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
myRangeHighlighter = myEditor.getMarkupModel().addLineHighlighter(line, DebuggerColors.EXECUTION_LINE_HIGHLIGHTERLAYER,
scheme.getAttributes(DebuggerColors.EXECUTIONPOINT_ATTRIBUTES));
myRangeHighlighter.setGutterIconRenderer(myGutterIconRenderer);
}
}