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 

 

0

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?

0

Hi,

Editors are not reused, they are created for every file/document.

The alarming part in your code is getSelectedTextEditor(). Its Javadoc states:

Returns: currently selected text editor. The method returns null in case there is no selected editor at all or selected editor is not a text one. Must be called from EDT.

Also, see fileOpened() Javadoc:

This method is called after the focus settles down (if requested) in a newly created FileEditor. Be aware though, that this isn't always true in case of editors loaded asynchronously, which, in general, may happen with any text editor. In that case, the focus request is postponed until after the editor is fully loaded, which means that it may gain the focus way after this method is called. When necessary, use FileEditorManager.runWhenLoaded(Editor, Runnable)) to ensure the desired ordering.
fileOpenedSync(FileEditorManager, VirtualFile, List) is always invoked before this method, either in the same or the previous EDT event.

 

0

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 ?

 

2022-03-24 12:09:22,030 [   5592]  DEBUG - plugin.listener.EditorListener - fileOpened:

editor:Editor: file:///home/shalom/workspace/digma/digma-jetbrains-plugin/sample-projects/simple-idea-java-project/src/com/company/Main.java,

file:file:///home/shalom/workspace/digma/digma-jetbrains-plugin/sample-projects/simple-idea-java-project/src/com/company/Test.java 

0

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.

0

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?

 

0

OK, I understand. so getSelectedEditor()  is the previous selected, and what about getSelectedTextEditor(), is it the opened file editor or the previous too?

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.

0

Karol Lewandowski   Thank you for your help, i got it right now.

0

> 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? 

0

to get Editor from FileEditor

 if (fileEditor is TextEditor) {
    val textEditor: Editor = fileEditor.editor

 

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? 

 

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.

0

请先登录再写评论。