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 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; } } } } } }
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 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); }
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); } }
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); }
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); } } }
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); }
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); } } }