@Override
  public void dispose() {
    if (mySelectedEditor != null) {
      for (final Map.Entry<PropertiesFile, Editor> entry : myEditors.entrySet()) {
        if (mySelectedEditor.equals(entry.getValue())) {
          writeEditorPropertyValue(mySelectedEditor, entry.getKey(), null);
        }
      }
    }

    VirtualFileManager.getInstance().removeVirtualFileListener(myVfsListener);
    myDisposed = true;
    Disposer.dispose(myStructureViewComponent);
    releaseAllEditors();
  }
  public FileDocumentManagerImpl(
      @NotNull VirtualFileManager virtualFileManager, @NotNull ProjectManager projectManager) {
    virtualFileManager.addVirtualFileListener(this);
    projectManager.addProjectManagerListener(this);

    myBus = ApplicationManager.getApplication().getMessageBus();
    InvocationHandler handler =
        new InvocationHandler() {
          @Nullable
          @Override
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            multiCast(method, args);
            return null;
          }
        };

    final ClassLoader loader = FileDocumentManagerListener.class.getClassLoader();
    myMultiCaster =
        (FileDocumentManagerListener)
            Proxy.newProxyInstance(
                loader, new Class[] {FileDocumentManagerListener.class}, handler);
  }
  private void installPropertiesChangeListeners() {
    final VirtualFileManager virtualFileManager = VirtualFileManager.getInstance();
    if (myVfsListener != null) {
      assert false;
      virtualFileManager.removeVirtualFileListener(myVfsListener);
    }
    myVfsListener =
        new VirtualFileAdapter() {
          @Override
          public void fileCreated(@NotNull VirtualFileEvent event) {
            if (PropertiesImplUtil.isPropertiesFile(event.getFile(), myProject)) {
              recreateEditorsPanel();
            }
          }

          @Override
          public void fileDeleted(@NotNull VirtualFileEvent event) {
            for (PropertiesFile file : myEditors.keySet()) {
              if (Comparing.equal(file.getVirtualFile(), event.getFile())) {
                recreateEditorsPanel();
                return;
              }
            }
          }

          @Override
          public void propertyChanged(@NotNull VirtualFilePropertyEvent event) {
            if (PropertiesImplUtil.isPropertiesFile(event.getFile(), myProject)) {
              if (VirtualFile.PROP_NAME.equals(event.getPropertyName())) {
                recreateEditorsPanel();
              } else {
                updateEditorsFromProperties();
              }
            }
          }
        };

    virtualFileManager.addVirtualFileListener(myVfsListener, this);
    PsiTreeChangeAdapter psiTreeChangeAdapter =
        new PsiTreeChangeAdapter() {
          @Override
          public void childAdded(@NotNull PsiTreeChangeEvent event) {
            childrenChanged(event);
          }

          @Override
          public void childRemoved(@NotNull PsiTreeChangeEvent event) {
            childrenChanged(event);
          }

          @Override
          public void childReplaced(@NotNull PsiTreeChangeEvent event) {
            childrenChanged(event);
          }

          @Override
          public void childMoved(@NotNull PsiTreeChangeEvent event) {
            childrenChanged(event);
          }

          @Override
          public void childrenChanged(@NotNull PsiTreeChangeEvent event) {
            final PsiFile file = event.getFile();
            PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile(file);
            if (propertiesFile == null) return;
            if (!propertiesFile.getResourceBundle().equals(myResourceBundle)) return;
            updateEditorsFromProperties();
          }
        };
    PsiManager.getInstance(myProject).addPsiTreeChangeListener(psiTreeChangeAdapter, this);
  }