IDEA-131134 Support multiple breakpoints within on single line - highlight variants...
authorEgor.Ushakov <egor.ushakov@jetbrains.com>
Mon, 15 Jun 2015 18:03:23 +0000 (21:03 +0300)
committerEgor.Ushakov <egor.ushakov@jetbrains.com>
Mon, 15 Jun 2015 18:04:21 +0000 (21:04 +0300)
platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java
platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointUtil.java

index bc5288599510ec520ba6e95fba411168a29662eb..4c1e8db900c63f93a961bd3fe8f7453b43bdb67f 100644 (file)
@@ -24,15 +24,22 @@ import com.intellij.openapi.application.WriteAction;
 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.*;
@@ -57,13 +64,17 @@ import com.intellij.xdebugger.impl.breakpoints.XLineBreakpointVariantsProvider;
 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.*;
 
 /**
@@ -71,7 +82,7 @@ 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() {
@@ -125,10 +136,10 @@ public class XDebuggerUtilImpl extends XDebuggerUtil {
 
   @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 {
@@ -144,10 +155,47 @@ public class XDebuggerUtilImpl extends XDebuggerUtil {
             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
@@ -160,8 +208,14 @@ public class XDebuggerUtilImpl extends XDebuggerUtil {
                       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() {
@@ -171,7 +225,9 @@ public class XDebuggerUtilImpl extends XDebuggerUtil {
                       });
                       return FINAL_CHOICE;
                     }
-                  }).show(relativePoint);
+                  });
+                popup.addListSelectionListener(selectionListener);
+                popup.show(relativePoint);
                 result.setResult(res);
                 return;
               }
@@ -206,7 +262,7 @@ public class XDebuggerUtilImpl extends XDebuggerUtil {
   @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);
       }
@@ -275,7 +331,7 @@ public class XDebuggerUtilImpl extends XDebuggerUtil {
   @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;
index 09f936bdad72a0b9b06fa432cceff4293a40a39c..7b49b34dc05f0ba4ae4a754759a984215d715cde 100644 (file)
@@ -26,7 +26,6 @@ import com.intellij.openapi.util.AsyncResult;
 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;
@@ -36,7 +35,6 @@ import com.intellij.xdebugger.impl.XDebuggerUtilImpl;
 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;
@@ -123,8 +121,9 @@ public class XBreakpointUtil {
     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;
@@ -180,9 +179,8 @@ public class XBreakpointUtil {
     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);