wrong file in FileEditorManagerListener#fileOpened
I am trying to install caret listener on open editors
i have this code on a FileEditorManagerListener:
public void fileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
Log.log(LOGGER::debug, "fileOpened: editor:{},editorFile:{},file:{}",
source.getSelectedEditor(),source.getSelectedEditor().getFile(), file);
Editor editor = source.getSelectedTextEditor();
addCaretListener(editor, file);
}
running the plugin with runIde and a sample java project with two classes Test and Main, the second fileOpened event gives me an unexpected file. i get the editor for Test but the file argument is for Main. is this expected ? if yes, why is it like that?
2022-03-24 07:37:40,519 [ 4969] DEBUG - plugin.listener.EditorListener - selectionChanged: editor:Editor: file://home/my/plugin/src/com/company/Test.java, newFile:file://home/my/plugin/src/com/company/Test.java, oldFile:null
2022-03-24 07:37:40,615 [ 5065] DEBUG - plugin.listener.EditorListener - fileOpened:editor:Editor: file://home/my/plugin/src/com/company/Test.java,
editorFile:file://home/my/plugin/src/com/company/Test.java,
file:file://home/my/plugin/src/com/company/Test.java
2022-03-24 07:37:40,739 [ 5189] DEBUG - plugin.listener.EditorListener - fileOpened: editor:
Editor: file://home/my/plugin/src/com/company/Test.java,
editorFile:file://home/my/plugin/src/com/company/Test.java,
file:file://home/my/plugin/src/com/company/Main.java
2022-03-24 07:37:40,770 [ 5220] DEBUG - plugin.listener.EditorListener - selectionChanged: editor:Editor: file://home/my/plugin/src/com/company/Main.java, newFile:file://home/my/plugin/src/com/company/Main.java, oldFile:file://home/my/plugin/src/com/company/Test.java
请先登录再写评论。
I wonder, are editors reused? if i install a caret listener for an editor can i be sure this editor edits the same file since its opened and until its closed?
Hi,
Editors are not reused, they are created for every file/document.
The alarming part in your code is getSelectedTextEditor(). Its Javadoc states:
Also, see fileOpened() Javadoc:
Thank you , i will do the necessary changes. but i still don't understand why when fileOpened is invoked sometimes the
source.getSelectedEditor().getFile() and file argument are different ?
The reason is that getSelectedEditor() returns the previous focused editor, not the opened file editor which is probably not focused yet at the moment of calling this method.
OK, I understand. so getSelectedEditor() is the previous selected, and what about getSelectedTextEditor(), is it the opened file editor or the previous too?
i saw a plugin called psiviewer that did the caret listener installation only in selectionChanged() probably for that reason. so i wonder where is the right place and time to install a caret listener on editor?
about FileEditorManager.runWhenLoaded(Editor, Runnable)) , i don't mind installing the caret listener before the editor gained focus, should that be a problem?
what about fileClosed , is getSelectedEditor() there the one that is being closed?
Yes (it's in Javadoc).
I would avoid using getSelected*Editor() methods and would use other methods from FileEditorManager, like getAllEditors(file). Keep in mind, that there can be multiple editor providers for an opened file.
Karol Lewandowski Thank you for your help, i got it right now.
> I would avoid using getSelected*Editor() methods and would use other methods from FileEditorManager, like getAllEditors(file)
`getAllEditors` returns FileEditor object. How can I get text editor from FileEditor?
What I am trying to do is: get caret position from ‘navigate’ event. My idea was to hook into `fileOpened` and then `getSelectedTextEditor() →getCaretModel→getLogicalPosition()`.
That does not work, logical position is previous and not new one. I assume that `navigate` will send position update later.
So now my idea: inside fileOpen event set a listener for position change. Then in listener do this: 1) get position 2) remove myself from listeners
Does htis make sense?
to get Editor from FileEditor
if (fileEditor is TextEditor) {
val textEditor: Editor = fileEditor.editor
Yes, That's what I do, Listen to FileEditorManagerListener#selectionChanged , register CaretListener on the new editor to get caretPositionChanged events, remove the listener on FileEditorManagerListener#fileClosed , I do it with disposable that i keep in a map and call dispose when i want to remove the listener
private void addCaretListener(@NotNull Editor editor, @NotNull VirtualFile file) {
Disposable parentDisposable = Disposer.newDisposable();
disposables.put(file, parentDisposable);
editor.getCaretModel().addCaretListener(…, parentDisposable)
}
void removeCaretListener(VirtualFile file) {
if (disposables.containsKey(file)) {
Disposer.dispose(disposables.remove(file));
}
}
If you ask why i don't use fileOpen to register the listener , then i don't completely remember, something didn't work correctly. but maybe it will work for you.