static void setOrRefreshErrorStripeRenderer(
      @NotNull EditorMarkupModel editorMarkupModel,
      @NotNull Project project,
      @NotNull Document document,
      PsiFile file) {
    ApplicationManager.getApplication().assertIsDispatchThread();
    if (!editorMarkupModel.isErrorStripeVisible()
        || !DaemonCodeAnalyzer.getInstance(project).isHighlightingAvailable(file)) {
      return;
    }
    ErrorStripeRenderer renderer = editorMarkupModel.getErrorStripeRenderer();
    if (renderer instanceof TrafficLightRenderer) {
      TrafficLightRenderer tlr = (TrafficLightRenderer) renderer;
      tlr.refresh();
      ((EditorMarkupModelImpl) editorMarkupModel).repaintVerticalScrollBar();
      if (tlr.myFile == null || tlr.myFile.isValid()) return;
      Disposer.dispose(tlr);
    }
    EditorImpl editor = (EditorImpl) editorMarkupModel.getEditor();

    if (!editor.isDisposed()) {
      renderer = new TrafficLightRenderer(project, document, file);
      Disposer.register(editor.getDisposable(), (Disposable) renderer);
      editorMarkupModel.setErrorStripeRenderer(renderer);
    }
  }
Beispiel #2
0
 int getVisualLineWidth(
     VisualLinesIterator visualLinesIterator, @Nullable Runnable quickEvaluationListener) {
   assert !visualLinesIterator.atEnd();
   int visualLine = visualLinesIterator.getVisualLine();
   FoldRegion[] topLevelRegions = myEditor.getFoldingModel().fetchTopLevel();
   if (quickEvaluationListener != null
       && (topLevelRegions == null || topLevelRegions.length == 0)
       && myEditor.getSoftWrapModel().getRegisteredSoftWraps().isEmpty()
       && !myView.getTextLayoutCache().hasCachedLayoutFor(visualLine)) {
     // fast path - speeds up editor opening
     quickEvaluationListener.run();
     return myView
             .getLogicalPositionCache()
             .offsetToLogicalColumn(
                 visualLine,
                 myDocument.getLineEndOffset(visualLine)
                     - myDocument.getLineStartOffset(visualLine))
         * myView.getMaxCharWidth();
   }
   float x = 0;
   int maxOffset = visualLinesIterator.getVisualLineStartOffset();
   for (VisualLineFragmentsIterator.Fragment fragment :
       VisualLineFragmentsIterator.create(myView, visualLinesIterator, quickEvaluationListener)) {
     x = fragment.getEndX();
     maxOffset = Math.max(maxOffset, fragment.getMaxOffset());
   }
   if (myEditor.getSoftWrapModel().getSoftWrap(maxOffset) != null) {
     x +=
         myEditor
             .getSoftWrapModel()
             .getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED);
   }
   return (int) x;
 }
  private boolean paintPlaceholderText(Graphics2D g) {
    CharSequence hintText = myEditor.getPlaceholder();
    EditorComponentImpl editorComponent = myEditor.getContentComponent();
    if (myDocument.getTextLength() > 0
        || hintText == null
        || hintText.length() == 0
        || KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() == editorComponent
            && !myEditor.getShowPlaceholderWhenFocused()) {
      return false;
    }

    hintText =
        SwingUtilities.layoutCompoundLabel(
            g.getFontMetrics(),
            hintText.toString(),
            null,
            0,
            0,
            0,
            0,
            editorComponent.getBounds(),
            new Rectangle(),
            new Rectangle(),
            0);
    g.setColor(myEditor.getFoldingModel().getPlaceholderAttributes().getForegroundColor());
    g.setFont(myEditor.getColorsScheme().getFont(EditorFontType.PLAIN));
    g.drawString(hintText.toString(), 0, myView.getAscent());
    return true;
  }
  private void paintSelectionOnFirstSoftWrapLineIfNecessary(
      Graphics2D g, int columnStart, float xStart, float xEnd, int y) {
    VisualPosition selectionStartPosition =
        myEditor.getSelectionModel().getSelectionStartPosition();
    VisualPosition selectionEndPosition = myEditor.getSelectionModel().getSelectionEndPosition();
    int visualLine = myView.yToVisualLine(y);

    if (selectionStartPosition.equals(selectionEndPosition)
        || visualLine < selectionStartPosition.line
        || visualLine > selectionEndPosition.line
        || visualLine == selectionEndPosition.line && selectionEndPosition.column <= columnStart) {
      return;
    }

    float startX =
        selectionStartPosition.line == visualLine && selectionStartPosition.column > columnStart
            ? myView.visualPositionToXY(selectionStartPosition).x
            : xStart;
    float endX =
        selectionEndPosition.line == visualLine
            ? myView.visualPositionToXY(selectionEndPosition).x
            : xEnd;

    paintBackground(
        g,
        myEditor.getColorsScheme().getColor(EditorColors.SELECTION_BACKGROUND_COLOR),
        startX,
        y,
        endX - startX);
  }
Beispiel #5
0
  int getPreferredHeight() {
    int lineHeight = myView.getLineHeight();
    if (myEditor.isOneLineMode()) return lineHeight;

    // Preferred height of less than a single line height doesn't make sense:
    // at least a single line with a blinking caret on it is to be displayed
    int size = Math.max(myEditor.getVisibleLineCount(), 1) * lineHeight;

    EditorSettings settings = myEditor.getSettings();
    if (settings.isAdditionalPageAtBottom()) {
      int visibleAreaHeight = myEditor.getScrollingModel().getVisibleArea().height;
      // There is a possible case that user with 'show additional page at bottom' scrolls to that
      // virtual page; switched to another
      // editor (another tab); and then returns to the previously used editor (the one scrolled to
      // virtual page). We want to preserve
      // correct view size then because viewport position is set to the end of the original text
      // otherwise.
      if (visibleAreaHeight > 0 || myVirtualPageHeight <= 0) {
        myVirtualPageHeight = Math.max(visibleAreaHeight - 2 * lineHeight, lineHeight);
      }

      size += Math.max(myVirtualPageHeight, 0);
    } else {
      size += settings.getAdditionalLinesCount() * lineHeight;
    }

    Insets insets = myView.getInsets();
    return size + insets.top + insets.bottom;
  }
 @Override
 public int calcColumnNumber(
     @NotNull final CharSequence text, final int start, final int offset, final int tabSize) {
   int hostStart = myDocumentWindow.injectedToHost(start);
   int hostOffset = myDocumentWindow.injectedToHost(offset);
   return myDelegate.calcColumnNumber(
       myDelegate.getDocument().getText(), hostStart, hostOffset, tabSize);
 }
 EditorSizeManager(EditorView view) {
   myView = view;
   myEditor = view.getEditor();
   myDocument = myEditor.getDocument();
   myDocument.addDocumentListener(this, this);
   myEditor.getFoldingModel().addListener(this, this);
   myEditor.getSoftWrapModel().getApplianceManager().addListener(mySoftWrapChangeListener);
 }
Beispiel #8
0
 private void assertValidState() {
   if (myDocument.isInBulkUpdate() || myDirty) return;
   if (myLineWidths.size() != myEditor.getVisibleLineCount()) {
     LOG.error("Inconsistent state", new Attachment("editor.txt", myEditor.dumpState()));
     reset();
   }
   assert myLineWidths.size() == myEditor.getVisibleLineCount();
 }
 private void paintBackground(Graphics2D g, Color color, float x, int y, float width) {
   if (width <= 0
       || color == null
       || color.equals(myEditor.getColorsScheme().getDefaultBackground())
       || color.equals(myEditor.getBackgroundColor())) return;
   g.setColor(color);
   g.fillRect((int) x, y, (int) width, myView.getLineHeight());
 }
  private void paintRightMargin(Graphics g, Rectangle clip) {
    EditorSettings settings = myEditor.getSettings();
    Color rightMargin = myEditor.getColorsScheme().getColor(EditorColors.RIGHT_MARGIN_COLOR);
    if (!settings.isRightMarginShown() || rightMargin == null) return;

    int x = settings.getRightMargin(myEditor.getProject()) * myView.getPlainSpaceWidth();
    g.setColor(rightMargin);
    UIUtil.drawLine(g, x, clip.y, x, clip.y + clip.height);
  }
  private void paintCaret(Graphics2D g_) {
    EditorImpl.CaretRectangle[] locations = myEditor.getCaretLocations(true);
    if (locations == null) return;

    Graphics2D g = IdeBackgroundUtil.getOriginalGraphics(g_);
    int lineHeight = myView.getLineHeight();
    EditorSettings settings = myEditor.getSettings();
    Color caretColor = myEditor.getColorsScheme().getColor(EditorColors.CARET_COLOR);
    if (caretColor == null) caretColor = new JBColor(CARET_DARK, CARET_LIGHT);
    g.setColor(caretColor);
    for (EditorImpl.CaretRectangle location : locations) {
      int x = location.myPoint.x;
      int y = location.myPoint.y;
      Caret caret = location.myCaret;
      boolean isRtl = location.myIsRtl;
      if (myEditor.isInsertMode() != settings.isBlockCursor()) {
        int lineWidth = JBUI.scale(settings.getLineCursorWidth());
        g.fillRect(x, y, lineWidth, lineHeight);
        if (myDocument.getTextLength() > 0
            && caret != null
            && !myView.getLineLayout(caret.getLogicalPosition().line).isLtr()) {
          g.fillPolygon(
              new int[] {
                isRtl ? x + lineWidth : x,
                isRtl ? x + lineWidth - CARET_DIRECTION_MARK_SIZE : x + CARET_DIRECTION_MARK_SIZE,
                isRtl ? x + lineWidth : x
              },
              new int[] {y, y, y + CARET_DIRECTION_MARK_SIZE},
              3);
        }
      } else {
        int width = location.myWidth;
        int startX = Math.max(0, isRtl ? x - width : x);
        g.fillRect(startX, y, width, lineHeight - 1);
        if (myDocument.getTextLength() > 0 && caret != null) {
          int targetVisualColumn = caret.getVisualPosition().column;
          for (VisualLineFragmentsIterator.Fragment fragment :
              VisualLineFragmentsIterator.create(myView, caret.getVisualLineStart(), false)) {
            int startVisualColumn = fragment.getStartVisualColumn();
            int endVisualColumn = fragment.getEndVisualColumn();
            if (startVisualColumn < targetVisualColumn && endVisualColumn > targetVisualColumn
                || startVisualColumn == targetVisualColumn && !isRtl
                || endVisualColumn == targetVisualColumn && isRtl) {
              g.setColor(ColorUtil.isDark(caretColor) ? CARET_LIGHT : CARET_DARK);
              fragment.draw(
                  g,
                  startX,
                  y + myView.getAscent(),
                  targetVisualColumn - startVisualColumn - (isRtl ? 1 : 0),
                  targetVisualColumn - startVisualColumn + (isRtl ? 0 : 1));
              break;
            }
          }
        }
      }
    }
  }
 void repaintCarets() {
   EditorImpl.CaretRectangle[] locations = myEditor.getCaretLocations(false);
   if (locations == null) return;
   int lineHeight = myView.getLineHeight();
   for (EditorImpl.CaretRectangle location : locations) {
     int x = location.myPoint.x;
     int y = location.myPoint.y;
     int width = Math.max(location.myWidth, CARET_DIRECTION_MARK_SIZE);
     myEditor.getContentComponent().repaintEditorComponent(x - width, y, width * 2, lineHeight);
   }
 }
 Dimension getPreferredSize() {
   int width = getPreferredWidth();
   if (!myDocument.isInBulkUpdate()) {
     for (Caret caret : myEditor.getCaretModel().getAllCarets()) {
       if (caret.isUpToDate()) {
         int caretX = myView.visualPositionToXY(caret.getVisualPosition()).x;
         width = Math.max(caretX, width);
       }
     }
   }
   width += myEditor.getSettings().getAdditionalColumnsCount() * myView.getPlainSpaceWidth();
   return new Dimension(width, myEditor.getPreferredHeight());
 }
 private EditorWindow(
     @NotNull DocumentWindowImpl documentWindow,
     @NotNull final EditorImpl delegate,
     @NotNull PsiFile injectedFile,
     boolean oneLine) {
   myDocumentWindow = documentWindow;
   myDelegate = delegate;
   myInjectedFile = injectedFile;
   myOneLine = oneLine;
   myCaretModelDelegate = new CaretModelWindow(myDelegate.getCaretModel(), this);
   mySelectionModelDelegate = new SelectionModelWindow(myDelegate, myDocumentWindow, this);
   myMarkupModelDelegate =
       new MarkupModelWindow((MarkupModelEx) myDelegate.getMarkupModel(), myDocumentWindow);
   myFoldingModelWindow = new FoldingModelWindow(delegate.getFoldingModel(), documentWindow, this);
 }
 @Override
 public void removeEditorMouseMotionListener(@NotNull final EditorMouseMotionListener listener) {
   EditorMouseMotionListener wrapper = myEditorMouseMotionListeners.removeWrapper(listener);
   if (wrapper != null) {
     myDelegate.removeEditorMouseMotionListener(wrapper);
   }
 }
  private void dispose() {
    assert !myDisposed;
    myCaretModelDelegate.disposeModel();

    for (EditorMouseListener wrapper : myEditorMouseListeners.wrappers()) {
      myDelegate.removeEditorMouseListener(wrapper);
    }
    myEditorMouseListeners.clear();
    for (EditorMouseMotionListener wrapper : myEditorMouseMotionListeners.wrappers()) {
      myDelegate.removeEditorMouseMotionListener(wrapper);
    }
    myEditorMouseMotionListeners.clear();

    myDisposed = true;
    Disposer.dispose(myDocumentWindow);
  }
 private void validateMaxLineWithExtension() {
   if (myMaxLineWithExtensionWidth > 0) {
     Project project = myEditor.getProject();
     VirtualFile virtualFile = myEditor.getVirtualFile();
     if (project != null && virtualFile != null) {
       for (EditorLinePainter painter : EditorLinePainter.EP_NAME.getExtensions()) {
         Collection<LineExtensionInfo> extensions =
             painter.getLineExtensions(project, virtualFile, myWidestLineWithExtension);
         if (extensions != null && !extensions.isEmpty()) {
           return;
         }
       }
     }
     myMaxLineWithExtensionWidth = 0;
   }
 }
 @Override
 @NotNull
 public LogicalPosition xyToLogicalPosition(@NotNull final Point p) {
   assert isValid();
   LogicalPosition hostPos = myDelegate.xyToLogicalPosition(p);
   return hostToInjected(hostPos);
 }
 private static List<BidiRun> createRuns(EditorImpl editor, char[] text, int startOffsetInEditor) {
   int textLength = text.length;
   if (editor.myDisableRtl) return Collections.singletonList(new BidiRun((byte) 0, 0, textLength));
   List<BidiRun> runs = new ArrayList<BidiRun>();
   if (startOffsetInEditor >= 0) {
     // running bidi algorithm separately for text fragments corresponding to different lexer
     // tokens
     int lastOffset = startOffsetInEditor;
     IElementType lastToken = null;
     HighlighterIterator iterator = editor.getHighlighter().createIterator(startOffsetInEditor);
     int endOffsetInEditor = startOffsetInEditor + textLength;
     while (!iterator.atEnd() && iterator.getStart() < endOffsetInEditor) {
       IElementType currentToken = iterator.getTokenType();
       if (distinctTokens(lastToken, currentToken)) {
         int tokenStart = Math.max(iterator.getStart(), startOffsetInEditor);
         addRuns(runs, text, lastOffset - startOffsetInEditor, tokenStart - startOffsetInEditor);
         lastToken = currentToken;
         lastOffset = tokenStart;
       }
       iterator.advance();
     }
     addRuns(
         runs, text, lastOffset - startOffsetInEditor, endOffsetInEditor - startOffsetInEditor);
   } else {
     addRuns(runs, text, 0, textLength);
   }
   return runs;
 }
 private void paintVirtualSelectionIfNecessary(
     Graphics2D g,
     Map<Integer, Couple<Integer>> virtualSelectionMap,
     int columnStart,
     float xStart,
     float xEnd,
     int y) {
   int visualLine = myView.yToVisualLine(y);
   Couple<Integer> selectionRange = virtualSelectionMap.get(visualLine);
   if (selectionRange == null || selectionRange.second <= columnStart) return;
   float startX =
       selectionRange.first <= columnStart
           ? xStart
           : myView.visualPositionToXY(new VisualPosition(visualLine, selectionRange.first)).x;
   float endX =
       Math.min(
           xEnd,
           myView.visualPositionToXY(new VisualPosition(visualLine, selectionRange.second)).x);
   paintBackground(
       g,
       myEditor.getColorsScheme().getColor(EditorColors.SELECTION_BACKGROUND_COLOR),
       startX,
       y,
       endX - startX);
 }
 @Override
 protected void revertStateOnFinish() {
   final Editor editor = InjectedLanguageUtil.getTopLevelEditor(myEditor);
   if (editor == FileEditorManager.getInstance(myProject).getSelectedTextEditor()) {
     ((EditorImpl) editor).startDumb();
   }
   revertState();
 }
Beispiel #22
0
 void textLayoutPerformed(int startOffset, int endOffset) {
   if (myDocument.isInBulkUpdate()) return;
   if (myEditor.getFoldingModel().isInBatchFoldingOperation()) {
     myDeferredRanges.add(new TextRange(startOffset, endOffset));
   } else {
     onTextLayoutPerformed(startOffset, endOffset);
   }
 }
Beispiel #23
0
 private boolean checkDirty() {
   if (myEditor.getSoftWrapModel().isDirty()) {
     myDirty = true;
     return true;
   }
   if (myDirty) {
     int visibleLineCount = myEditor.getVisibleLineCount();
     int lineDiff = visibleLineCount - myLineWidths.size();
     if (lineDiff > 0) myLineWidths.add(new int[lineDiff]);
     else if (lineDiff < 0) myLineWidths.remove(visibleLineCount, -lineDiff);
     for (int i = 0; i < visibleLineCount; i++) {
       myLineWidths.set(i, UNKNOWN_WIDTH);
     }
     myDirty = false;
   }
   return false;
 }
 @Override
 public void removeEditorMouseListener(@NotNull final EditorMouseListener listener) {
   EditorMouseListener wrapper = myEditorMouseListeners.removeWrapper(listener);
   // HintManager might have an old editor instance
   if (wrapper != null) {
     myDelegate.removeEditorMouseListener(wrapper);
   }
 }
Beispiel #25
0
 Dimension getPreferredSize() {
   int widthWithoutCaret = getPreferredWidth();
   int width = widthWithoutCaret;
   if (!myDocument.isInBulkUpdate()) {
     for (Caret caret : myEditor.getCaretModel().getAllCarets()) {
       if (caret.isUpToDate()) {
         int caretX = myView.visualPositionToXY(caret.getVisualPosition()).x;
         width = Math.max(caretX, width);
       }
     }
   }
   if (shouldRespectAdditionalColumns(widthWithoutCaret)) {
     width += myEditor.getSettings().getAdditionalColumnsCount() * myView.getPlainSpaceWidth();
   }
   Insets insets = myView.getInsets();
   return new Dimension(width + insets.left + insets.right, getPreferredHeight());
 }
Beispiel #26
0
 private void onTextLayoutPerformed(int startOffset, int endOffset) {
   if (checkDirty()) return;
   boolean purePaintingMode = myEditor.isPurePaintingMode();
   boolean foldingEnabled = myEditor.getFoldingModel().isFoldingEnabled();
   myEditor.setPurePaintingMode(false);
   myEditor.getFoldingModel().setFoldingEnabled(true);
   try {
     int startVisualLine = myView.offsetToVisualLine(startOffset, false);
     int endVisualLine = myView.offsetToVisualLine(endOffset, true);
     boolean sizeInvalidated = false;
     for (int i = startVisualLine; i <= endVisualLine; i++) {
       if (myLineWidths.get(i) < 0) {
         myLineWidths.set(i, UNKNOWN_WIDTH);
         sizeInvalidated = true;
       }
     }
     if (sizeInvalidated) {
       myWidthInPixels = -1;
       myEditor.getContentComponent().revalidate();
     }
   } finally {
     myEditor.setPurePaintingMode(purePaintingMode);
     myEditor.getFoldingModel().setFoldingEnabled(foldingEnabled);
   }
 }
  public boolean equals(final Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    final EditorWindow that = (EditorWindow) o;

    DocumentWindow thatWindow = that.getDocument();
    return myDelegate.equals(that.myDelegate) && myDocumentWindow.equals(thatWindow);
  }
Beispiel #28
0
 public void testLeadingTabWithShiftedWidth() throws IOException {
   // Inspired by IDEA-76353. The point is that we need to consider cached information about tab
   // symbols width during logical
   // position to offset mapping
   String text = "\t test";
   init(15, text);
   ((EditorImpl) myEditor).setPrefixTextAndAttributes(" ", new TextAttributes());
   myEditor.getCaretModel().moveToOffset(text.length());
 }
  private void paintBackground(
      Graphics2D g, Rectangle clip, int startVisualLine, int endVisualLine) {
    int lineCount = myEditor.getVisibleLineCount();
    final Map<Integer, Couple<Integer>> virtualSelectionMap =
        createVirtualSelectionMap(startVisualLine, endVisualLine);
    for (int visualLine = startVisualLine; visualLine <= endVisualLine; visualLine++) {
      int y = myView.visualLineToY(visualLine);
      LineLayout prefixLayout = myView.getPrefixLayout();
      if (visualLine == 0 && prefixLayout != null) {
        paintBackground(g, myView.getPrefixAttributes(), 0, y, prefixLayout.getWidth());
      }
      if (visualLine >= lineCount) break;
      paintLineFragments(
          g,
          clip,
          visualLine,
          y,
          new LineFragmentPainter() {
            @Override
            public void paintBeforeLineStart(
                Graphics2D g, TextAttributes attributes, int columnEnd, float xEnd, int y) {
              paintBackground(g, attributes, 0, y, xEnd);
              paintSelectionOnSecondSoftWrapLineIfNecessary(g, columnEnd, xEnd, y);
            }

            @Override
            public void paint(
                Graphics2D g,
                VisualLineFragmentsIterator.Fragment fragment,
                int start,
                int end,
                TextAttributes attributes,
                float xStart,
                float xEnd,
                int y) {
              paintBackground(g, attributes, xStart, y, xEnd - xStart);
            }

            @Override
            public void paintAfterLineEnd(
                Graphics2D g, Rectangle clip, IterationState it, int columnStart, float x, int y) {
              paintBackground(
                  g, it.getPastLineEndBackgroundAttributes(), x, y, clip.x + clip.width - x);
              int offset = it.getEndOffset();
              SoftWrap softWrap = myEditor.getSoftWrapModel().getSoftWrap(offset);
              if (softWrap == null) {
                paintVirtualSelectionIfNecessary(
                    g, virtualSelectionMap, columnStart, x, clip.x + clip.width, y);
              } else {
                paintSelectionOnFirstSoftWrapLineIfNecessary(
                    g, columnStart, x, clip.x + clip.width, y);
              }
            }
          });
    }
  }
 private void paintTextEffect(
     Graphics2D g, float xFrom, float xTo, int y, Color effectColor, EffectType effectType) {
   int xStart = (int) xFrom;
   int xEnd = (int) xTo;
   g.setColor(effectColor);
   if (effectType == EffectType.LINE_UNDERSCORE) {
     UIUtil.drawLine(g, xStart, y + 1, xEnd, y + 1);
   } else if (effectType == EffectType.BOLD_LINE_UNDERSCORE) {
     int height = JBUI.scale(Registry.intValue("editor.bold.underline.height", 2));
     g.fillRect(xStart, y, xEnd - xStart, height);
   } else if (effectType == EffectType.STRIKEOUT) {
     int y1 = y - myView.getCharHeight() / 2;
     UIUtil.drawLine(g, xStart, y1, xEnd, y1);
   } else if (effectType == EffectType.WAVE_UNDERSCORE) {
     UIUtil.drawWave(g, new Rectangle(xStart, y + 1, xEnd - xStart, myView.getDescent() - 1));
   } else if (effectType == EffectType.BOLD_DOTTED_LINE) {
     UIUtil.drawBoldDottedLine(
         g,
         xStart,
         xEnd,
         SystemInfo.isMac ? y : y + 1,
         myEditor.getBackgroundColor(),
         g.getColor(),
         false);
   }
 }