Example #1
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;
  }
  private Content getOrCreateConsoleContent(final ContentManager contentManager) {
    final String displayName = VcsBundle.message("vcs.console.toolwindow.display.name");
    Content content = contentManager.findContent(displayName);
    if (content == null) {
      releaseEditor();
      final EditorFactory editorFactory = EditorFactory.getInstance();
      final Editor editor = editorFactory.createViewer(editorFactory.createDocument(""), myProject);
      EditorSettings editorSettings = editor.getSettings();
      editorSettings.setLineMarkerAreaShown(false);
      editorSettings.setIndentGuidesShown(false);
      editorSettings.setLineNumbersShown(false);
      editorSettings.setFoldingOutlineShown(false);

      ((EditorEx) editor).getScrollPane().setBorder(null);
      myEditorAdapter = new EditorAdapter(editor, myProject, false);
      final JPanel panel = new JPanel(new BorderLayout());
      panel.add(editor.getComponent(), BorderLayout.CENTER);

      content = ContentFactory.SERVICE.getInstance().createContent(panel, displayName, true);
      contentManager.addContent(content);

      for (Pair<String, TextAttributes> pair : myPendingOutput) {
        myEditorAdapter.appendString(pair.first, pair.second);
      }
      myPendingOutput.clear();
    }
    return content;
  }
Example #3
0
  public void testSoftWrapCacheReset() throws IOException {
    // Inspired by IDEA-76537 - the point is to drop cached document info on complete soft wraps
    // recalculation
    String text = "\t first line\n" + "\t second line\n" + "\t third line";

    // Make soft wraps to build a document info cache.
    init(40, text);

    // Modify document while soft wraps processing is off.
    final EditorSettings settings = getEditor().getSettings();
    settings.setUseSoftWraps(false);
    int startOffset = text.indexOf("\t third") - 1;
    getEditor().getDocument().deleteString(startOffset, text.length());

    // Enable soft wraps and ensure that the cache is correctly re-built.
    settings.setUseSoftWraps(true);

    getEditor().getCaretModel().moveToOffset(getEditor().getDocument().getTextLength());
    type("\n test");

    final int offset = getEditor().getDocument().getTextLength() - 1;
    final LogicalPosition logicalPosition = getEditor().offsetToLogicalPosition(offset);
    assertEquals(offset, getEditor().logicalPositionToOffset(logicalPosition));

    final VisualPosition visualPosition = getEditor().offsetToVisualPosition(offset);
    assertEquals(visualPosition, getEditor().logicalToVisualPosition(logicalPosition));
    assertEquals(logicalPosition, getEditor().visualToLogicalPosition(visualPosition));
  }
  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;
            }
          }
        }
      }
    }
  }
Example #6
0
 @Override
 protected void tearDown() throws Exception {
   if (myEditor != null) {
     EditorSettings settings = myEditor.getSettings();
     settings.setUseSoftWraps(false);
     settings.setSmartHome(mySmartHome);
   }
   super.tearDown();
 }
  @Override
  protected void setUp() throws Exception {
    super.setUp();
    if (myEditor == null) {
      return;
    }

    EditorSettings settings = myEditor.getSettings();
    mySmartHome = settings.isSmartHome();
  }
  private static void setupEditorDefault(EditorEx editor) {
    ConsoleViewUtil.setupConsoleEditor(editor, false, false);
    editor.getContentComponent().setFocusCycleRoot(false);
    editor.setHorizontalScrollbarVisible(false);
    editor.setVerticalScrollbarVisible(true);
    editor.setBorder(null);

    final EditorSettings editorSettings = editor.getSettings();
    editorSettings.setAdditionalLinesCount(0);
    editorSettings.setAdditionalColumnsCount(1);
    editorSettings.setRightMarginShown(false);
  }
  @NotNull
  private static Editor createView(Project project) {
    EditorFactory editorFactory = EditorFactory.getInstance();
    Document document = editorFactory.createDocument("");
    Editor result = editorFactory.createViewer(document, project);

    EditorSettings editorSettings = result.getSettings();
    editorSettings.setLineMarkerAreaShown(false);
    editorSettings.setLineNumbersShown(false);
    editorSettings.setIndentGuidesShown(false);
    editorSettings.setFoldingOutlineShown(false);
    return result;
  }
  public SoftWrapModelImpl(
      @NotNull EditorEx editor,
      @NotNull SoftWrapsStorage storage,
      @NotNull SoftWrapPainter painter,
      @NotNull SoftWrapApplianceManager applianceManager,
      @NotNull CachingSoftWrapDataMapper dataMapper) {
    myEditor = editor;
    myStorage = storage;
    myPainter = painter;
    myApplianceManager = applianceManager;
    myDataMapper = dataMapper;
    myFoldBasedApplianceStrategy = new SoftWrapFoldBasedApplianceStrategy(editor);
    myVisualSizeManager = new SoftWrapAwareVisualSizeManager(painter);

    myDocumentListeners.add(myApplianceManager);
    myFoldListeners.add(myApplianceManager);
    applianceManager.addListener(myVisualSizeManager);
    EditorSettings settings = myEditor.getSettings();
    myAdditionalColumnsCount = settings.getAdditionalColumnsCount();
    myUseSoftWraps = settings.isUseSoftWraps();

    editor.addPropertyChangeListener(this);
  }
  private void paintLineMarkerSeparator(RangeHighlighter marker, Rectangle clip, Graphics g) {
    Color separatorColor = marker.getLineSeparatorColor();
    LineSeparatorRenderer lineSeparatorRenderer = marker.getLineSeparatorRenderer();
    if (separatorColor == null && lineSeparatorRenderer == null) {
      return;
    }
    int line =
        myDocument.getLineNumber(
            marker.getLineSeparatorPlacement() == SeparatorPlacement.TOP
                ? marker.getStartOffset()
                : marker.getEndOffset());
    int visualLine =
        myView.logicalToVisualPosition(
                new LogicalPosition(
                    line + (marker.getLineSeparatorPlacement() == SeparatorPlacement.TOP ? 0 : 1),
                    0),
                false)
            .line;
    int y = myView.visualLineToY(visualLine) - 1;
    int endShift = clip.x + clip.width;
    EditorSettings settings = myEditor.getSettings();
    if (settings.isRightMarginShown()
        && myEditor.getColorsScheme().getColor(EditorColors.RIGHT_MARGIN_COLOR) != null) {
      endShift =
          Math.min(
              endShift,
              settings.getRightMargin(myEditor.getProject()) * myView.getPlainSpaceWidth());
    }

    g.setColor(separatorColor);
    if (lineSeparatorRenderer != null) {
      lineSeparatorRenderer.drawLine(g, 0, endShift, y);
    } else {
      UIUtil.drawLine(g, 0, y, endShift, y);
    }
  }
 /**
  * Called on editor settings change. Current model is expected to drop all cached information
  * about the settings if any.
  */
 public void reinitSettings() {
   boolean softWrapsUsedBefore = myUseSoftWraps;
   EditorSettings settings = myEditor.getSettings();
   myUseSoftWraps = settings.isUseSoftWraps();
   if (myUseSoftWraps && (!softWrapsUsedBefore || settings.getAdditionalColumnsCount() > 0)) {
     myApplianceManager.reset();
     myDeferredFoldRegions.clear();
     myAdditionalColumnsCount = settings.getAdditionalColumnsCount();
     settings.setAdditionalColumnsCount(0);
     myEditor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
   } else if (!myUseSoftWraps && softWrapsUsedBefore) {
     settings.setAdditionalColumnsCount(myAdditionalColumnsCount);
     myEditor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
   }
 }
  private Editor createEditor() {
    EditorFactory editorFactory = EditorFactory.getInstance();
    Document doc =
        myFile == null
            ? editorFactory.createDocument(myTemplate == null ? "" : myTemplate.getText())
            : PsiDocumentManager.getInstance(myFile.getProject()).getDocument(myFile);
    Editor editor =
        myProject == null
            ? editorFactory.createEditor(doc)
            : editorFactory.createEditor(doc, myProject);

    EditorSettings editorSettings = editor.getSettings();
    editorSettings.setVirtualSpace(false);
    editorSettings.setLineMarkerAreaShown(false);
    editorSettings.setIndentGuidesShown(false);
    editorSettings.setLineNumbersShown(false);
    editorSettings.setFoldingOutlineShown(false);
    editorSettings.setAdditionalColumnsCount(3);
    editorSettings.setAdditionalLinesCount(3);

    EditorColorsScheme scheme = editor.getColorsScheme();
    scheme.setColor(EditorColors.CARET_ROW_COLOR, null);

    editor
        .getDocument()
        .addDocumentListener(
            new DocumentAdapter() {
              @Override
              public void documentChanged(DocumentEvent e) {
                onTextChanged();
              }
            });

    ((EditorEx) editor).setHighlighter(createHighlighter());
    mySplitter.setFirstComponent(editor.getComponent());
    return editor;
  }
  public static Editor createEditor(boolean isReadOnly, final CharSequence text) {
    EditorFactory editorFactory = EditorFactory.getInstance();
    Document doc = editorFactory.createDocument(text);
    Editor editor =
        (isReadOnly ? editorFactory.createViewer(doc) : editorFactory.createEditor(doc));

    EditorSettings editorSettings = editor.getSettings();
    editorSettings.setVirtualSpace(false);
    editorSettings.setLineMarkerAreaShown(false);
    editorSettings.setIndentGuidesShown(false);
    editorSettings.setLineNumbersShown(false);
    editorSettings.setFoldingOutlineShown(false);

    EditorColorsScheme scheme = editor.getColorsScheme();
    scheme.setColor(EditorColors.CARET_ROW_COLOR, null);

    return editor;
  }
  private void updatePreview() {
    ConnectionHandler connectionHandler = variablesBundle.getActiveConnection();
    Project project = connectionHandler.getProject();

    String previewText =
        variablesBundle.prepareStatementText(connectionHandler, this.statementText, true);

    for (StatementExecutionVariableValueForm variableValueForm : variableValueForms) {
      String errorText = variablesBundle.getError(variableValueForm.getVariable());
      if (errorText == null) variableValueForm.hideErrorLabel();
      else variableValueForm.showErrorLabel(errorText);
    }

    if (previewDocument == null) {
      PsiFileFactory psiFileFactory = PsiFileFactory.getInstance(project);

      SQLFile selectStatementFile =
          (SQLFile)
              psiFileFactory.createFileFromText(
                  "filter.sql",
                  connectionHandler.getLanguageDialect(SQLLanguage.INSTANCE),
                  previewText);

      selectStatementFile.setActiveConnection(connectionHandler);
      selectStatementFile.setCurrentSchema(variablesBundle.getCurrentSchema());
      previewDocument = DocumentUtil.getDocument(selectStatementFile);

      viewer = (EditorEx) EditorFactory.getInstance().createViewer(previewDocument, project);
      viewer.setEmbeddedIntoDialogWrapper(true);
      JScrollPane viewerScrollPane = viewer.getScrollPane();
      SyntaxHighlighter syntaxHighlighter =
          connectionHandler.getLanguageDialect(SQLLanguage.INSTANCE).getSyntaxHighlighter();
      EditorColorsScheme colorsScheme = viewer.getColorsScheme();
      viewer.setHighlighter(HighlighterFactory.createHighlighter(syntaxHighlighter, colorsScheme));
      viewer.setBackgroundColor(colorsScheme.getColor(ColorKey.find("CARET_ROW_COLOR")));
      viewerScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
      viewerScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
      // viewerScrollPane.setBorder(null);
      viewerScrollPane.setViewportBorder(
          new LineBorder(CompatibilityUtil.getEditorBackgroundColor(viewer), 4, false));

      EditorSettings settings = viewer.getSettings();
      settings.setFoldingOutlineShown(false);
      settings.setLineMarkerAreaShown(false);
      settings.setLineNumbersShown(false);
      settings.setVirtualSpace(false);
      settings.setDndEnabled(false);
      settings.setAdditionalLinesCount(2);
      settings.setRightMarginShown(false);
      previewPanel.add(viewer.getComponent(), BorderLayout.CENTER);

    } else {
      final String finalPreviewText = previewText;

      new WriteActionRunner() {
        public void run() {
          previewDocument.setText(finalPreviewText);
        }
      }.start();
    }
  }
  public ImplementationViewComponent(PsiElement[] elements, final int index) {
    super(new BorderLayout());

    final Project project = elements.length > 0 ? elements[0].getProject() : null;
    EditorFactory factory = EditorFactory.getInstance();
    Document doc = factory.createDocument("");
    doc.setReadOnly(true);
    myEditor = factory.createEditor(doc, project);
    ((EditorEx) myEditor).setBackgroundColor(EditorFragmentComponent.getBackgroundColor(myEditor));

    final EditorSettings settings = myEditor.getSettings();
    settings.setAdditionalLinesCount(1);
    settings.setAdditionalColumnsCount(1);
    settings.setLineMarkerAreaShown(false);
    settings.setIndentGuidesShown(false);
    settings.setLineNumbersShown(false);
    settings.setFoldingOutlineShown(false);

    myBinarySwitch = new CardLayout();
    myViewingPanel = new JPanel(myBinarySwitch);
    myEditor.setBorder(null);
    ((EditorEx) myEditor).getScrollPane().setViewportBorder(JBScrollPane.createIndentBorder());
    myViewingPanel.add(myEditor.getComponent(), TEXT_PAGE_KEY);

    myBinaryPanel = new JPanel(new BorderLayout());
    myViewingPanel.add(myBinaryPanel, BINARY_PAGE_KEY);

    add(myViewingPanel, BorderLayout.CENTER);

    myToolbar = createToolbar();
    myLocationLabel = new JLabel();
    myCountLabel = new JLabel();

    final JPanel header = new JPanel(new BorderLayout(2, 0));
    header.setBorder(
        BorderFactory.createCompoundBorder(
            IdeBorderFactory.createBorder(SideBorder.BOTTOM),
            IdeBorderFactory.createEmptyBorder(0, 0, 0, 5)));
    final JPanel toolbarPanel = new JPanel(new GridBagLayout());
    final GridBagConstraints gc =
        new GridBagConstraints(
            GridBagConstraints.RELATIVE,
            0,
            1,
            1,
            0,
            0,
            GridBagConstraints.WEST,
            GridBagConstraints.NONE,
            new Insets(0, 2, 0, 0),
            0,
            0);
    toolbarPanel.add(myToolbar.getComponent(), gc);

    setPreferredSize(new Dimension(600, 400));

    update(
        elements,
        new PairFunction<PsiElement[], List<FileDescriptor>, Boolean>() {
          @Override
          public Boolean fun(
              final PsiElement[] psiElements, final List<FileDescriptor> fileDescriptors) {
            if (psiElements.length == 0) return false;
            myElements = psiElements;

            myIndex = index < myElements.length ? index : 0;
            PsiFile psiFile = getContainingFile(myElements[myIndex]);

            VirtualFile virtualFile = psiFile.getVirtualFile();
            EditorHighlighter highlighter;
            if (virtualFile != null)
              highlighter = HighlighterFactory.createHighlighter(project, virtualFile);
            else {
              String fileName = psiFile.getName(); // some artificial psi file, lets do best we can
              highlighter = HighlighterFactory.createHighlighter(project, fileName);
            }

            ((EditorEx) myEditor).setHighlighter(highlighter);

            gc.fill = GridBagConstraints.HORIZONTAL;
            gc.weightx = 1;
            if (myElements.length > 1) {
              myFileChooser =
                  new ComboBox(
                      fileDescriptors.toArray(new FileDescriptor[fileDescriptors.size()]), 250);
              updateRenderer(project);

              myFileChooser.addActionListener(
                  new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                      int index = myFileChooser.getSelectedIndex();
                      if (myIndex != index) {
                        myIndex = index;
                        updateControls();
                      }
                    }
                  });

              myLabel = new JLabel();
              myLabel.setVisible(false);
              toolbarPanel.add(myFileChooser, gc);
            } else {
              myFileChooser = new ComboBox();
              myFileChooser.setVisible(false);
              myCountLabel.setVisible(false);

              myLabel = new JLabel();
              VirtualFile file = psiFile.getVirtualFile();
              if (file != null) {
                myLabel.setIcon(getIconForFile(psiFile));
                myLabel.setForeground(
                    FileStatusManager.getInstance(project).getStatus(file).getColor());
                myLabel.setText(file.getPresentableName());
                myLabel.setBorder(
                    new CompoundBorder(
                        IdeBorderFactory.createRoundedBorder(),
                        IdeBorderFactory.createEmptyBorder(0, 0, 0, 5)));
              }
              toolbarPanel.add(myLabel, gc);
            }

            gc.fill = GridBagConstraints.NONE;
            gc.weightx = 0;
            toolbarPanel.add(myCountLabel, gc);

            header.add(toolbarPanel, BorderLayout.CENTER);
            header.add(myLocationLabel, BorderLayout.EAST);

            add(header, BorderLayout.NORTH);

            updateControls();
            return true;
          }
        });
  }
  private static void reinitSettings(final EditorEx editor) {
    EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
    editor.setColorsScheme(scheme);
    EditorSettings settings = editor.getSettings();
    settings.setLineNumbersShown(false);
    settings.setWhitespacesShown(false);
    settings.setLineMarkerAreaShown(false);
    settings.setIndentGuidesShown(false);
    settings.setFoldingOutlineShown(false);
    settings.setAdditionalColumnsCount(0);
    settings.setAdditionalLinesCount(0);
    settings.setRightMarginShown(true);
    settings.setRightMargin(60);
    settings.setVirtualSpace(false);

    editor.setHighlighter(new LexerEditorHighlighter(new PropertiesValueHighlighter(), scheme));
    editor.setVerticalScrollbarVisible(true);
  }
  public void moveToVisualPosition(@NotNull VisualPosition pos) {
    assertIsDispatchThread();
    validateCallContext();
    myDesiredX = -1;
    int column = pos.column;
    int line = pos.line;

    if (column < 0) column = 0;

    if (line < 0) line = 0;

    int lastLine = myEditor.getVisibleLineCount() - 1;
    if (lastLine <= 0) {
      lastLine = 0;
    }

    if (line > lastLine) {
      line = lastLine;
    }

    EditorSettings editorSettings = myEditor.getSettings();

    if (!editorSettings.isVirtualSpace() && line <= lastLine) {
      int lineEndColumn = EditorUtil.getLastVisualLineColumnNumber(myEditor, line);
      if (column > lineEndColumn) {
        column = lineEndColumn;
      }

      if (column < 0 && line > 0) {
        line--;
        column = EditorUtil.getLastVisualLineColumnNumber(myEditor, line);
      }
    }

    myVisibleCaret = new VisualPosition(line, column);

    VerticalInfo oldInfo = myCaretInfo;
    LogicalPosition oldPosition = myLogicalCaret;

    setCurrentLogicalCaret(myEditor.visualToLogicalPosition(myVisibleCaret));
    myOffset = myEditor.logicalPositionToOffset(myLogicalCaret);
    LOG.assertTrue(myOffset >= 0 && myOffset <= myEditor.getDocument().getTextLength());

    myVisualLineStart =
        myEditor.logicalPositionToOffset(
            myEditor.visualToLogicalPosition(new VisualPosition(myVisibleCaret.line, 0)));
    myVisualLineEnd =
        myEditor.logicalPositionToOffset(
            myEditor.visualToLogicalPosition(new VisualPosition(myVisibleCaret.line + 1, 0)));

    ((FoldingModelImpl) myEditor.getFoldingModel()).flushCaretPosition();

    myEditor.setLastColumnNumber(myVisibleCaret.column);
    myEditor.updateCaretCursor();
    requestRepaint(oldInfo);

    if (oldPosition.column != myLogicalCaret.column || oldPosition.line != myLogicalCaret.line) {
      CaretEvent event = new CaretEvent(myEditor, oldPosition, myLogicalCaret);

      for (CaretListener listener : myCaretListeners) {
        listener.caretPositionChanged(event);
      }
    }
  }
  public void moveCaretRelatively(
      int columnShift,
      int lineShift,
      boolean withSelection,
      boolean blockSelection,
      boolean scrollToCaret) {
    assertIsDispatchThread();
    SelectionModel selectionModel = myEditor.getSelectionModel();
    int selectionStart = selectionModel.getLeadSelectionOffset();
    LogicalPosition blockSelectionStart =
        selectionModel.hasBlockSelection() ? selectionModel.getBlockStart() : getLogicalPosition();
    EditorSettings editorSettings = myEditor.getSettings();
    VisualPosition visualCaret = getVisualPosition();

    int desiredX = myDesiredX;
    if (columnShift == 0) {
      if (myDesiredX < 0) {
        desiredX = myEditor.visualPositionToXY(visualCaret).x;
      }
    } else {
      myDesiredX = desiredX = -1;
    }

    int newLineNumber = visualCaret.line + lineShift;
    int newColumnNumber = visualCaret.column + columnShift;
    if (desiredX >= 0 && !ApplicationManager.getApplication().isUnitTestMode()) {
      newColumnNumber =
          myEditor.xyToVisualPosition(
                  new Point(desiredX, Math.max(0, newLineNumber) * myEditor.getLineHeight()))
              .column;
    }

    Document document = myEditor.getDocument();
    if (!editorSettings.isVirtualSpace()
        && columnShift == 0
        && getLogicalPosition().softWrapLinesOnCurrentLogicalLine <= 0) {
      newColumnNumber = myEditor.getLastColumnNumber();
    } else if (!editorSettings.isVirtualSpace() && lineShift == 0 && columnShift == 1) {
      int lastLine = document.getLineCount() - 1;
      if (lastLine < 0) lastLine = 0;
      if (EditorModificationUtil.calcAfterLineEnd(myEditor) >= 0
          && newLineNumber
              < myEditor.logicalToVisualPosition(new LogicalPosition(lastLine, 0)).line) {
        newColumnNumber = 0;
        newLineNumber++;
      }
    } else if (!editorSettings.isVirtualSpace() && lineShift == 0 && columnShift == -1) {
      if (newColumnNumber < 0 && newLineNumber > 0) {
        newLineNumber--;
        newColumnNumber = EditorUtil.getLastVisualLineColumnNumber(myEditor, newLineNumber);
      }
    }

    if (newColumnNumber < 0) newColumnNumber = 0;

    // There is a possible case that caret is located at the first line and user presses 'Shift+Up'.
    // We want to select all text
    // from the document start to the current caret position then. So, we have a dedicated flag for
    // tracking that.
    boolean selectToDocumentStart = false;
    if (newLineNumber < 0) {
      selectToDocumentStart = true;
      newLineNumber = 0;

      // We want to move caret to the first column if it's already located at the first line and
      // 'Up' is pressed.
      newColumnNumber = 0;
      desiredX = -1;
    }

    VisualPosition pos = new VisualPosition(newLineNumber, newColumnNumber);
    int lastColumnNumber = newColumnNumber;
    if (!editorSettings.isCaretInsideTabs() && !myEditor.getSoftWrapModel().isInsideSoftWrap(pos)) {
      LogicalPosition log =
          myEditor.visualToLogicalPosition(new VisualPosition(newLineNumber, newColumnNumber));
      int offset = myEditor.logicalPositionToOffset(log);
      if (offset >= document.getTextLength()) {
        int lastOffsetColumn = myEditor.offsetToVisualPosition(document.getTextLength()).column;
        // We want to move caret to the last column if if it's located at the last line and 'Down'
        // is pressed.
        newColumnNumber = lastColumnNumber = Math.max(lastOffsetColumn, newColumnNumber);
        desiredX = -1;
      }
      CharSequence text = document.getCharsSequence();
      if (offset >= 0 && offset < document.getTextLength()) {
        if (text.charAt(offset) == '\t' && (columnShift <= 0 || offset == myOffset)) {
          if (columnShift <= 0) {
            newColumnNumber = myEditor.offsetToVisualPosition(offset).column;
          } else {
            SoftWrap softWrap = myEditor.getSoftWrapModel().getSoftWrap(offset + 1);
            // There is a possible case that tabulation symbol is the last document symbol
            // represented on a visual line before
            // soft wrap. We can't just use column from 'offset + 1' because it would point on a
            // next visual line.
            if (softWrap == null) {
              newColumnNumber = myEditor.offsetToVisualPosition(offset + 1).column;
            } else {
              newColumnNumber = EditorUtil.getLastVisualLineColumnNumber(myEditor, newLineNumber);
            }
          }
        }
      }
    }

    pos = new VisualPosition(newLineNumber, newColumnNumber);
    if (columnShift != 0 && lineShift == 0 && myEditor.getSoftWrapModel().isInsideSoftWrap(pos)) {
      LogicalPosition logical = myEditor.visualToLogicalPosition(pos);
      int softWrapOffset = myEditor.logicalPositionToOffset(logical);
      if (columnShift >= 0) {
        moveToOffset(softWrapOffset);
      } else {
        int line = myEditor.offsetToVisualLine(softWrapOffset - 1);
        moveToVisualPosition(
            new VisualPosition(line, EditorUtil.getLastVisualLineColumnNumber(myEditor, line)));
      }
    } else {
      moveToVisualPosition(pos);
      if (!editorSettings.isVirtualSpace() && columnShift == 0) {
        myEditor.setLastColumnNumber(lastColumnNumber);
      }
    }

    if (withSelection) {
      if (blockSelection) {
        selectionModel.setBlockSelection(blockSelectionStart, getLogicalPosition());
      } else {
        if (selectToDocumentStart) {
          selectionModel.setSelection(selectionStart, 0);
        } else if (pos.line >= myEditor.getVisibleLineCount()) {
          if (selectionStart < document.getTextLength()) {
            selectionModel.setSelection(selectionStart, document.getTextLength());
          }
        } else {
          selectionModel.setSelection(selectionStart, getVisualPosition(), getOffset());
        }
      }
    } else {
      selectionModel.removeSelection();
    }

    if (scrollToCaret) {
      myEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
    }

    if (desiredX >= 0) {
      myDesiredX = desiredX;
    }

    EditorActionUtil.selectNonexpandableFold(myEditor);
  }
  private void moveToLogicalPosition(LogicalPosition pos, boolean locateBeforeSoftWrap) {
    assertIsDispatchThread();
    myDesiredX = -1;
    validateCallContext();
    int column = pos.column;
    int line = pos.line;
    int softWrapLinesBefore = pos.softWrapLinesBeforeCurrentLogicalLine;
    int softWrapLinesCurrent = pos.softWrapLinesOnCurrentLogicalLine;
    int softWrapColumns = pos.softWrapColumnDiff;

    Document doc = myEditor.getDocument();

    if (column < 0) {
      column = 0;
      softWrapColumns = 0;
    }
    if (line < 0) {
      line = 0;
      softWrapLinesBefore = 0;
      softWrapLinesCurrent = 0;
    }

    int lineCount = doc.getLineCount();
    if (lineCount == 0) {
      line = 0;
    } else if (line > lineCount - 1) {
      line = lineCount - 1;
      softWrapLinesBefore = 0;
      softWrapLinesCurrent = 0;
    }

    EditorSettings editorSettings = myEditor.getSettings();

    if (!editorSettings.isVirtualSpace()
        && line < lineCount
        && !myEditor.getSelectionModel().hasBlockSelection()) {
      int lineEndOffset = doc.getLineEndOffset(line);
      int lineEndColumnNumber = myEditor.offsetToLogicalPosition(lineEndOffset).column;
      if (column > lineEndColumnNumber) {
        column = lineEndColumnNumber;
        if (softWrapColumns != 0) {
          softWrapColumns -= column - lineEndColumnNumber;
        }
      }
    }

    ((FoldingModelImpl) myEditor.getFoldingModel()).flushCaretPosition();

    VerticalInfo oldInfo = myCaretInfo;
    LogicalPosition oldCaretPosition = myLogicalCaret;

    LogicalPosition logicalPositionToUse;
    if (pos.visualPositionAware) {
      logicalPositionToUse =
          new LogicalPosition(
              line,
              column,
              softWrapLinesBefore,
              softWrapLinesCurrent,
              softWrapColumns,
              pos.foldedLines,
              pos.foldingColumnDiff);
    } else {
      logicalPositionToUse = new LogicalPosition(line, column);
    }
    setCurrentLogicalCaret(logicalPositionToUse);

    final int offset = myEditor.logicalPositionToOffset(myLogicalCaret);

    FoldRegion collapsedAt = myEditor.getFoldingModel().getCollapsedRegionAtOffset(offset);

    if (collapsedAt != null && offset > collapsedAt.getStartOffset()) {
      Runnable runnable =
          new Runnable() {
            public void run() {
              FoldRegion[] allCollapsedAt =
                  ((FoldingModelImpl) myEditor.getFoldingModel()).fetchCollapsedAt(offset);
              for (FoldRegion foldRange : allCollapsedAt) {
                foldRange.setExpanded(true);
              }
            }
          };

      myEditor.getFoldingModel().runBatchFoldingOperation(runnable);
    }

    myEditor.setLastColumnNumber(myLogicalCaret.column);
    myVisibleCaret = myEditor.logicalToVisualPosition(myLogicalCaret);

    myOffset = myEditor.logicalPositionToOffset(myLogicalCaret);
    LOG.assertTrue(myOffset >= 0 && myOffset <= myEditor.getDocument().getTextLength());

    myVisualLineStart =
        myEditor.logicalPositionToOffset(
            myEditor.visualToLogicalPosition(new VisualPosition(myVisibleCaret.line, 0)));
    myVisualLineEnd =
        myEditor.logicalPositionToOffset(
            myEditor.visualToLogicalPosition(new VisualPosition(myVisibleCaret.line + 1, 0)));

    myEditor.updateCaretCursor();
    requestRepaint(oldInfo);

    if (locateBeforeSoftWrap && SoftWrapHelper.isCaretAfterSoftWrap(myEditor)) {
      int lineToUse = myVisibleCaret.line - 1;
      if (lineToUse >= 0) {
        moveToVisualPosition(
            new VisualPosition(
                lineToUse, EditorUtil.getLastVisualLineColumnNumber(myEditor, lineToUse)));
        return;
      }
    }

    if (!oldCaretPosition.toVisualPosition().equals(myLogicalCaret.toVisualPosition())) {
      CaretEvent event = new CaretEvent(myEditor, oldCaretPosition, myLogicalCaret);
      for (CaretListener listener : myCaretListeners) {
        listener.caretPositionChanged(event);
      }
    }
  }