import com.intellij.openapi.editor.Caret;
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.HighlighterTargetArea;
+import com.intellij.openapi.editor.markup.RangeHighlighter;
+import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.ui.popup.ListPopup;
import com.intellij.openapi.ui.popup.PopupStep;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
import com.intellij.openapi.util.AsyncResult;
+import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.xdebugger.impl.breakpoints.ui.grouping.XBreakpointFileGroupingRule;
import com.intellij.xdebugger.impl.evaluate.quick.common.ValueLookupManager;
import com.intellij.xdebugger.impl.settings.XDebuggerSettingsManager;
+import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase;
import com.intellij.xdebugger.settings.XDebuggerSettings;
+import com.intellij.xdebugger.ui.DebuggerColors;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
import java.util.*;
/**
*/
public class XDebuggerUtilImpl extends XDebuggerUtil {
private XLineBreakpointType<?>[] myLineBreakpointTypes;
- private Map<Class<? extends XBreakpointType>, XBreakpointType<?,?>> myBreakpointTypeByClass;
+ private Map<Class<? extends XBreakpointType>, XBreakpointType<?, ?>> myBreakpointTypeByClass;
@Override
public XLineBreakpointType<?>[] getLineBreakpointTypes() {
@NotNull
public static <P extends XBreakpointProperties> AsyncResult<XLineBreakpoint> toggleAndReturnLineBreakpoint(@NotNull final Project project,
- @NotNull final XLineBreakpointType<P> type,
- @NotNull final XSourcePosition position,
- final boolean temporary,
- final RelativePoint relativePoint) {
+ @NotNull final XLineBreakpointType<P> type,
+ @NotNull final XSourcePosition position,
+ final boolean temporary,
+ @Nullable final Editor editor) {
return new WriteAction<AsyncResult<XLineBreakpoint>>() {
@Override
protected void run(@NotNull Result<AsyncResult<XLineBreakpoint>> result) throws Throwable {
final XLineBreakpointVariantsProvider<XLineBreakpointVariant> provider =
(XLineBreakpointVariantsProvider<XLineBreakpointVariant>)type;
List<XLineBreakpointVariant> variants = provider.computeLineBreakpointVariants(project, position);
- if (!variants.isEmpty()) {
+ if (!variants.isEmpty() && editor != null) {
+ RelativePoint relativePoint = DebuggerUIUtil.calcPopupLocation(editor, line);
if (variants.size() > 1 && relativePoint != null) {
final AsyncResult<XLineBreakpoint> res = new AsyncResult<XLineBreakpoint>();
- JBPopupFactory.getInstance().createListPopup(
+ class MySelectionListener implements ListSelectionListener {
+ RangeHighlighter myHighlighter = null;
+
+ @Override
+ public void valueChanged(ListSelectionEvent e) {
+ if (!e.getValueIsAdjusting()) {
+ clearHighlighter();
+ Object value = ((JList)e.getSource()).getSelectedValue();
+ if (value instanceof XLineBreakpointVariant) {
+ TextRange range = ((XLineBreakpointVariant)value).getHighlightRange();
+ TextRange lineRange =
+ TextRange.create(editor.getDocument().getLineStartOffset(line), editor.getDocument().getLineEndOffset(line));
+ if (range != null) {
+ range = range.intersection(lineRange);
+ }
+ else {
+ range = lineRange;
+ }
+ if (range != null && !range.isEmpty()) {
+ EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
+ TextAttributes attributes = scheme.getAttributes(DebuggerColors.BREAKPOINT_ATTRIBUTES);
+ myHighlighter = editor.getMarkupModel().addRangeHighlighter(
+ range.getStartOffset(), range.getEndOffset(), DebuggerColors.BREAKPOINT_HIGHLIGHTER_LAYER, attributes,
+ HighlighterTargetArea.EXACT_RANGE);
+ }
+ }
+ }
+ }
+
+ private void clearHighlighter() {
+ if (myHighlighter != null) {
+ myHighlighter.dispose();
+ }
+ }
+ }
+ final MySelectionListener selectionListener = new MySelectionListener();
+ ListPopup popup = JBPopupFactory.getInstance().createListPopup(
new BaseListPopupStep<XLineBreakpointVariant>("Create breakpoint for", variants) {
@NotNull
@Override
return value.getIcon();
}
+ @Override
+ public void canceled() {
+ selectionListener.clearHighlighter();
+ }
+
@Override
public PopupStep onChosen(final XLineBreakpointVariant selectedValue, boolean finalChoice) {
+ selectionListener.clearHighlighter();
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
});
return FINAL_CHOICE;
}
- }).show(relativePoint);
+ });
+ popup.addListSelectionListener(selectionListener);
+ popup.show(relativePoint);
result.setResult(res);
return;
}
@Override
public <B extends XBreakpoint<?>> XBreakpointType<B, ?> findBreakpointType(@NotNull Class<? extends XBreakpointType<B, ?>> typeClass) {
if (myBreakpointTypeByClass == null) {
- myBreakpointTypeByClass = new THashMap<Class<? extends XBreakpointType>, XBreakpointType<?,?>>();
+ myBreakpointTypeByClass = new THashMap<Class<? extends XBreakpointType>, XBreakpointType<?, ?>>();
for (XBreakpointType<?, ?> breakpointType : XBreakpointUtil.getBreakpointTypes()) {
myBreakpointTypeByClass.put(breakpointType.getClass(), breakpointType);
}
@Nullable
private static Editor getEditor(@NotNull Project project, DataContext context) {
Editor editor = CommonDataKeys.EDITOR.getData(context);
- if(editor == null) {
+ if (editor == null) {
return FileEditorManager.getInstance(project).getSelectedTextEditor();
}
return editor;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.ui.awt.RelativePoint;
import com.intellij.xdebugger.XDebuggerManager;
import com.intellij.xdebugger.XDebuggerUtil;
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.impl.XSourcePositionImpl;
import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointItem;
import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointPanelProvider;
-import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
List<BreakpointItem> items = new ArrayList<BreakpointItem>();
for (DebuggerSupport support : debuggerSupports) {
support.getBreakpointPanelProvider().provideBreakpointItems(project, items);
- if (items.contains(breakpointItem))
+ if (items.contains(breakpointItem)) {
return support;
+ }
items.clear();
}
return null;
if (typeWinner != null) {
XSourcePosition winPosition = (lineStart == lineWinner) ? position : XSourcePositionImpl.create(file, lineWinner);
if (winPosition != null) {
- RelativePoint point = editor != null ? DebuggerUIUtil.calcPopupLocation(editor, lineWinner) : null;
AsyncResult<XLineBreakpoint> res =
- XDebuggerUtilImpl.toggleAndReturnLineBreakpoint(project, typeWinner, winPosition, temporary, point);
+ XDebuggerUtilImpl.toggleAndReturnLineBreakpoint(project, typeWinner, winPosition, temporary, editor);
if (editor != null && lineStart != lineWinner) {
int offset = editor.getDocument().getLineStartOffset(lineWinner);