use of com.intellij.openapi.editor.event.DocumentListener in project intellij-community by JetBrains.
the class SearchDialog method createEditor.
protected Editor createEditor(final SearchContext searchContext, String text) {
Editor editor = null;
if (fileTypes != null) {
final FileType fileType = (FileType) fileTypes.getSelectedItem();
final Language dialect = (Language) dialects.getSelectedItem();
final StructuralSearchProfile profile = StructuralSearchUtil.getProfileByFileType(fileType);
if (profile != null) {
editor = profile.createEditor(searchContext, fileType, dialect, text, useLastConfiguration);
}
}
if (editor == null) {
final EditorFactory factory = EditorFactory.getInstance();
final Document document = factory.createDocument("");
editor = factory.createEditor(document, searchContext.getProject());
editor.getSettings().setFoldingOutlineShown(false);
}
editor.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void beforeDocumentChange(final DocumentEvent event) {
}
@Override
public void documentChanged(final DocumentEvent event) {
initiateValidation();
}
});
return editor;
}
use of com.intellij.openapi.editor.event.DocumentListener in project intellij-community by JetBrains.
the class AutoHardWrapHandler method wrapLineIfNecessary.
/**
* The user is allowed to configured IJ in a way that it automatically wraps line on right margin exceeding on typing
* (check {@link EditorSettings#isWrapWhenTypingReachesRightMargin(Project)}).
* <p/>
* This method encapsulates that functionality, i.e. it performs the following logical actions:
* <pre>
* <ol>
* <li>Check if IJ is configured to perform automatic line wrapping on typing. Return in case of the negative answer;</li>
* <li>Check if right margin is exceeded. Return in case of the negative answer;</li>
* <li>Perform line wrapping;</li>
* </ol>
</pre>
*
* @param editor active editor
* @param dataContext current data context
* @param modificationStampBeforeTyping document modification stamp before the current symbols typing
*/
public void wrapLineIfNecessary(@NotNull Editor editor, @NotNull DataContext dataContext, long modificationStampBeforeTyping) {
Project project = editor.getProject();
Document document = editor.getDocument();
AutoWrapChange change = myAutoWrapChanges.get(document);
if (change != null) {
change.charTyped(editor, modificationStampBeforeTyping);
}
// Return eagerly if we don't need to auto-wrap line, e.g. because of right margin exceeding.
if (/*editor.isOneLineMode()
|| */
project == null || !editor.getSettings().isWrapWhenTypingReachesRightMargin(project) || (TemplateManager.getInstance(project) != null && TemplateManager.getInstance(project).getActiveTemplate(editor) != null)) {
return;
}
CaretModel caretModel = editor.getCaretModel();
int caretOffset = caretModel.getOffset();
int line = document.getLineNumber(caretOffset);
int startOffset = document.getLineStartOffset(line);
int endOffset = document.getLineEndOffset(line);
final CharSequence endOfString = document.getCharsSequence().subSequence(caretOffset, endOffset);
final boolean endsWithSpaces = StringUtil.isEmptyOrSpaces(String.valueOf(endOfString));
// Check if right margin is exceeded.
int margin = editor.getSettings().getRightMargin(project);
if (margin <= 0) {
return;
}
VisualPosition visEndLinePosition = editor.offsetToVisualPosition(endOffset);
if (margin >= visEndLinePosition.column) {
if (change != null) {
change.modificationStamp = document.getModificationStamp();
}
return;
}
// We assume that right margin is exceeded if control flow reaches this place. Hence, we define wrap position and perform
// smart line break there.
LineWrapPositionStrategy strategy = LanguageLineWrapPositionStrategy.INSTANCE.forEditor(editor);
// We want to prevent such behavior, hence, we remove automatically generated wraps and wrap the line as a whole.
if (change == null) {
change = new AutoWrapChange();
myAutoWrapChanges.put(document, change);
} else {
final int start = change.change.getStart();
final int end = change.change.getEnd();
if (!change.isEmpty() && start < end) {
document.replaceString(start, end, change.change.getText());
}
change.reset();
}
change.update(editor);
// Is assumed to be max possible number of characters inserted on the visual line with caret.
int maxPreferredOffset = editor.logicalPositionToOffset(editor.visualToLogicalPosition(new VisualPosition(caretModel.getVisualPosition().line, margin - FormatConstants.RESERVED_LINE_WRAP_WIDTH_IN_COLUMNS)));
int wrapOffset = strategy.calculateWrapPosition(document, project, startOffset, endOffset, maxPreferredOffset, true, false);
if (wrapOffset < 0) {
return;
}
WhiteSpaceFormattingStrategy formattingStrategy = WhiteSpaceFormattingStrategyFactory.getStrategy(editor);
if (wrapOffset <= startOffset || wrapOffset > maxPreferredOffset || formattingStrategy.check(document.getCharsSequence(), startOffset, wrapOffset) >= wrapOffset) {
// on first non-white space symbol because wrapped part will have the same indent value).
return;
}
final int[] wrapIntroducedSymbolsNumber = new int[1];
final int[] caretOffsetDiff = new int[1];
final int baseCaretOffset = caretModel.getOffset();
DocumentListener listener = new DocumentListener() {
@Override
public void beforeDocumentChange(DocumentEvent event) {
if (event.getOffset() < baseCaretOffset + caretOffsetDiff[0]) {
caretOffsetDiff[0] += event.getNewLength() - event.getOldLength();
}
if (autoFormatted(event)) {
return;
}
wrapIntroducedSymbolsNumber[0] += event.getNewLength() - event.getOldLength();
}
private boolean autoFormatted(DocumentEvent event) {
return event.getNewLength() <= event.getOldLength() && endsWithSpaces;
}
@Override
public void documentChanged(DocumentEvent event) {
}
};
caretModel.moveToOffset(wrapOffset);
DataManager.getInstance().saveInDataContext(dataContext, AUTO_WRAP_LINE_IN_PROGRESS_KEY, true);
document.addDocumentListener(listener);
try {
EditorActionManager.getInstance().getActionHandler(IdeActions.ACTION_EDITOR_ENTER).execute(editor, dataContext);
} finally {
DataManager.getInstance().saveInDataContext(dataContext, AUTO_WRAP_LINE_IN_PROGRESS_KEY, null);
document.removeDocumentListener(listener);
}
change.modificationStamp = document.getModificationStamp();
change.change.setStart(wrapOffset);
change.change.setEnd(wrapOffset + wrapIntroducedSymbolsNumber[0]);
caretModel.moveToOffset(baseCaretOffset + caretOffsetDiff[0]);
}
use of com.intellij.openapi.editor.event.DocumentListener in project intellij-community by JetBrains.
the class GroovyExtractMethodDialog method setUpNameField.
private void setUpNameField() {
myNameLabel.setLabelFor(myNameField);
myNameField.addDocumentListener(new DocumentListener() {
@Override
public void beforeDocumentChange(DocumentEvent event) {
}
@Override
public void documentChanged(DocumentEvent event) {
fireNameDataChanged();
}
});
myListenerList.add(DataChangedListener.class, new DataChangedListener());
}
use of com.intellij.openapi.editor.event.DocumentListener in project intellij-community by JetBrains.
the class SrcFileAnnotator method hideCoverageData.
public void hideCoverageData() {
Editor editor = myEditor;
PsiFile file = myFile;
Document document = myDocument;
if (editor == null || editor.isDisposed() || file == null || document == null)
return;
final FileEditorManager fileEditorManager = FileEditorManager.getInstance(myProject);
final List<RangeHighlighter> highlighters = editor.getUserData(COVERAGE_HIGHLIGHTERS);
if (highlighters != null) {
for (final RangeHighlighter highlighter : highlighters) {
ApplicationManager.getApplication().invokeLater(() -> highlighter.dispose());
}
editor.putUserData(COVERAGE_HIGHLIGHTERS, null);
}
final Map<FileEditor, EditorNotificationPanel> map = file.getCopyableUserData(NOTIFICATION_PANELS);
if (map != null) {
final VirtualFile vFile = getVirtualFile(file);
boolean freeAll = !fileEditorManager.isFileOpen(vFile);
file.putCopyableUserData(NOTIFICATION_PANELS, null);
for (FileEditor fileEditor : map.keySet()) {
if (!freeAll && !isCurrentEditor(fileEditor)) {
continue;
}
fileEditorManager.removeTopComponent(fileEditor, map.get(fileEditor));
}
}
final DocumentListener documentListener = editor.getUserData(COVERAGE_DOCUMENT_LISTENER);
if (documentListener != null) {
document.removeDocumentListener(documentListener);
editor.putUserData(COVERAGE_DOCUMENT_LISTENER, null);
}
}
use of com.intellij.openapi.editor.event.DocumentListener in project intellij-community by JetBrains.
the class SrcFileAnnotator method showCoverageInformation.
public void showCoverageInformation(final CoverageSuitesBundle suite) {
// Store the values of myFile and myEditor in local variables to avoid an NPE after dispose() has been called in the EDT.
final PsiFile psiFile = myFile;
final Editor editor = myEditor;
final Document document = myDocument;
if (editor == null || psiFile == null || document == null)
return;
final VirtualFile file = getVirtualFile(psiFile);
final MyEditorBean editorBean = new MyEditorBean(editor, file, document);
final MarkupModel markupModel = DocumentMarkupModel.forDocument(document, myProject, true);
final List<RangeHighlighter> highlighters = new ArrayList<>();
final ProjectData data = suite.getCoverageData();
if (data == null) {
coverageDataNotFound(suite);
return;
}
final CoverageEngine engine = suite.getCoverageEngine();
final Set<String> qualifiedNames = engine.getQualifiedNames(psiFile);
// let's find old content in local history and build mapping from old lines to new one
// local history doesn't index libraries, so let's distinguish libraries content with other one
final ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
final long fileTimeStamp = file.getTimeStamp();
final long coverageTimeStamp = suite.getLastCoverageTimeStamp();
final TIntIntHashMap oldToNewLineMapping;
//do not show coverage info over cls
if (engine.isInLibraryClasses(myProject, file)) {
return;
}
// if in libraries content
if (projectFileIndex.isInLibrarySource(file)) {
// compare file and coverage timestamps
if (fileTimeStamp > coverageTimeStamp) {
showEditorWarningMessage(CodeInsightBundle.message("coverage.data.outdated"));
return;
}
oldToNewLineMapping = null;
} else {
// check local history
oldToNewLineMapping = getOldToNewLineMapping(coverageTimeStamp, editorBean);
if (oldToNewLineMapping == null) {
// if history for file isn't available let's check timestamps
if (fileTimeStamp > coverageTimeStamp && classesArePresentInCoverageData(data, qualifiedNames)) {
showEditorWarningMessage(CodeInsightBundle.message("coverage.data.outdated"));
return;
}
}
}
if (editor.getUserData(COVERAGE_HIGHLIGHTERS) != null) {
//highlighters already collected - no need to do it twice
return;
}
final Module module = ApplicationManager.getApplication().runReadAction(new Computable<Module>() {
@Nullable
@Override
public Module compute() {
return ModuleUtilCore.findModuleForPsiElement(psiFile);
}
});
if (module != null) {
if (engine.recompileProjectAndRerunAction(module, suite, () -> CoverageDataManager.getInstance(myProject).chooseSuitesBundle(suite))) {
return;
}
}
// now if oldToNewLineMapping is null we should use f(x)=id(x) mapping
// E.g. all *.class files for java source file with several classes
final Set<File> outputFiles = engine.getCorrespondingOutputFiles(psiFile, module, suite);
final boolean subCoverageActive = CoverageDataManager.getInstance(myProject).isSubCoverageActive();
final boolean coverageByTestApplicable = suite.isCoverageByTestApplicable() && !(subCoverageActive && suite.isCoverageByTestEnabled());
final TreeMap<Integer, LineData> executableLines = new TreeMap<>();
final TreeMap<Integer, Object[]> classLines = new TreeMap<>();
final TreeMap<Integer, String> classNames = new TreeMap<>();
class HighlightersCollector {
private void collect(File outputFile, final String qualifiedName) {
final ClassData fileData = data.getClassData(qualifiedName);
if (fileData != null) {
final Object[] lines = fileData.getLines();
if (lines != null) {
final Object[] postProcessedLines = suite.getCoverageEngine().postProcessExecutableLines(lines, editor);
for (Object lineData : postProcessedLines) {
if (lineData instanceof LineData) {
final int line = ((LineData) lineData).getLineNumber() - 1;
final int lineNumberInCurrent;
if (oldToNewLineMapping != null) {
// use mapping based on local history
if (!oldToNewLineMapping.contains(line)) {
continue;
}
lineNumberInCurrent = oldToNewLineMapping.get(line);
} else {
// use id mapping
lineNumberInCurrent = line;
}
executableLines.put(line, (LineData) lineData);
classLines.put(line, postProcessedLines);
classNames.put(line, qualifiedName);
ApplicationManager.getApplication().invokeLater(() -> {
if (lineNumberInCurrent >= document.getLineCount())
return;
if (editorBean.isDisposed())
return;
final RangeHighlighter highlighter = createRangeHighlighter(suite.getLastCoverageTimeStamp(), markupModel, coverageByTestApplicable, executableLines, qualifiedName, line, lineNumberInCurrent, suite, postProcessedLines, editorBean);
highlighters.add(highlighter);
});
}
}
}
} else if (outputFile != null && !subCoverageActive && engine.includeUntouchedFileInCoverage(qualifiedName, outputFile, psiFile, suite)) {
collectNonCoveredFileInfo(outputFile, highlighters, markupModel, executableLines, coverageByTestApplicable, editorBean);
}
}
}
final HighlightersCollector collector = new HighlightersCollector();
if (!outputFiles.isEmpty()) {
for (File outputFile : outputFiles) {
final String qualifiedName = engine.getQualifiedName(outputFile, psiFile);
if (qualifiedName != null) {
collector.collect(outputFile, qualifiedName);
}
}
} else {
//check non-compilable classes which present in ProjectData
for (String qName : qualifiedNames) {
collector.collect(null, qName);
}
}
ApplicationManager.getApplication().invokeLater(() -> {
if (!editorBean.isDisposed() && highlighters.size() > 0) {
editor.putUserData(COVERAGE_HIGHLIGHTERS, highlighters);
}
});
final DocumentListener documentListener = new DocumentAdapter() {
@Override
public void documentChanged(final DocumentEvent e) {
myNewToOldLines = null;
myOldToNewLines = null;
List<RangeHighlighter> rangeHighlighters = editor.getUserData(COVERAGE_HIGHLIGHTERS);
if (rangeHighlighters == null)
rangeHighlighters = new ArrayList<>();
int offset = e.getOffset();
final int lineNumber = document.getLineNumber(offset);
final int lastLineNumber = document.getLineNumber(offset + e.getNewLength());
final TextRange changeRange = new TextRange(document.getLineStartOffset(lineNumber), document.getLineEndOffset(lastLineNumber));
for (Iterator<RangeHighlighter> it = rangeHighlighters.iterator(); it.hasNext(); ) {
final RangeHighlighter highlighter = it.next();
if (!highlighter.isValid() || TextRange.create(highlighter).intersects(changeRange)) {
highlighter.dispose();
it.remove();
}
}
final List<RangeHighlighter> highlighters = rangeHighlighters;
myUpdateAlarm.cancelAllRequests();
if (!myUpdateAlarm.isDisposed()) {
myUpdateAlarm.addRequest(() -> {
final TIntIntHashMap newToOldLineMapping = getNewToOldLineMapping(suite.getLastCoverageTimeStamp(), editorBean);
if (newToOldLineMapping != null) {
ApplicationManager.getApplication().invokeLater(() -> {
if (editorBean.isDisposed())
return;
for (int line = lineNumber; line <= lastLineNumber; line++) {
final int oldLineNumber = newToOldLineMapping.get(line);
final LineData lineData = executableLines.get(oldLineNumber);
if (lineData != null) {
RangeHighlighter rangeHighlighter = createRangeHighlighter(suite.getLastCoverageTimeStamp(), markupModel, coverageByTestApplicable, executableLines, classNames.get(oldLineNumber), oldLineNumber, line, suite, classLines.get(oldLineNumber), editorBean);
highlighters.add(rangeHighlighter);
}
}
editor.putUserData(COVERAGE_HIGHLIGHTERS, highlighters.size() > 0 ? highlighters : null);
});
}
}, 100);
}
}
};
document.addDocumentListener(documentListener);
editor.putUserData(COVERAGE_DOCUMENT_LISTENER, documentListener);
}
Aggregations