private void updatePathFromTree(final List<VirtualFile> selection, boolean now) {
    if (!isToShowTextField() || myTreeIsUpdating) return;

    String text = "";
    if (selection.size() > 0) {
      text = VfsUtil.getReadableUrl(selection.get(0));
    } else {
      final List<VirtualFile> roots = myChooserDescriptor.getRoots();
      if (!myFileSystemTree.getTree().isRootVisible() && roots.size() == 1) {
        text = VfsUtil.getReadableUrl(roots.get(0));
      }
    }

    myPathTextField.setText(
        text,
        now,
        () -> {
          myPathTextField.getField().selectAll();
          setErrorText(null);
        });
  }
  private void selectInTree(final VirtualFile[] array, final boolean requestFocus) {
    myTreeIsUpdating = true;
    final List<VirtualFile> fileList = Arrays.asList(array);
    if (!Arrays.asList(myFileSystemTree.getSelectedFiles()).containsAll(fileList)) {
      myFileSystemTree.select(
          array,
          new Runnable() {
            public void run() {
              if (!myFileSystemTree.areHiddensShown()
                  && !Arrays.asList(myFileSystemTree.getSelectedFiles()).containsAll(fileList)) {
                myFileSystemTree.showHiddens(true);
                selectInTree(array, requestFocus);
                return;
              }

              myTreeIsUpdating = false;
              setErrorText(null);
              if (requestFocus) {
                //noinspection SSBasedInspection
                SwingUtilities.invokeLater(
                    new Runnable() {
                      public void run() {
                        myFileSystemTree.getTree().requestFocus();
                      }
                    });
              }
            }
          });
    } else {
      myTreeIsUpdating = false;
      setErrorText(null);
    }
  }
 public JComponent getPreferredFocusedComponent() {
   if (isToShowTextField()) {
     return myPathTextField != null ? myPathTextField.getField() : null;
   } else {
     return myFileSystemTree != null ? myFileSystemTree.getTree() : null;
   }
 }
  protected JTree createTree() {
    myFileSystemTree = new FileSystemTreeImpl(myProject, myChooserDescriptor);
    Disposer.register(myDisposable, myFileSystemTree);

    myFileSystemTree.addOkAction(
        new Runnable() {
          public void run() {
            doOKAction();
          }
        });
    JTree tree = myFileSystemTree.getTree();
    tree.setCellRenderer(new NodeRenderer());
    tree.getSelectionModel().addTreeSelectionListener(new FileTreeSelectionListener());
    tree.addTreeExpansionListener(new FileTreeExpansionListener());
    setOKActionEnabled(false);

    myFileSystemTree.addListener(
        new FileSystemTree.Listener() {
          public void selectionChanged(final List<VirtualFile> selection) {
            updatePathFromTree(selection, false);
          }
        },
        myDisposable);

    new FileDrop(
        tree,
        new FileDrop.Target() {
          public FileChooserDescriptor getDescriptor() {
            return myChooserDescriptor;
          }

          public boolean isHiddenShown() {
            return myFileSystemTree.areHiddensShown();
          }

          public void dropFiles(final List<VirtualFile> files) {
            if (!myChooserDescriptor.isChooseMultiple() && files.size() > 0) {
              selectInTree(new VirtualFile[] {files.get(0)}, true);
            } else {
              selectInTree(VfsUtilCore.toVirtualFileArray(files), true);
            }
          }
        });

    return tree;
  }
  private void registerFileChooserShortcut(
      @NonNls final String baseActionId, @NonNls final String fileChooserActionId) {
    final JTree tree = myFileSystemTree.getTree();
    final AnAction syncAction = ActionManager.getInstance().getAction(fileChooserActionId);

    AnAction original = ActionManager.getInstance().getAction(baseActionId);
    syncAction.registerCustomShortcutSet(original.getShortcutSet(), tree, myDisposable);
  }
  private void updateTextFieldShowing() {
    myTextFieldAction.update();
    myNorthPanel.remove(myPathTextFieldWrapper);
    if (isToShowTextField()) {
      final ArrayList<VirtualFile> selection = new ArrayList<VirtualFile>();
      if (myFileSystemTree.getSelectedFile() != null) {
        selection.add(myFileSystemTree.getSelectedFile());
      }
      updatePathFromTree(selection, true);
      myNorthPanel.add(myPathTextFieldWrapper, BorderLayout.CENTER);
    } else {
      setErrorText(null);
    }
    myPathTextField.getField().requestFocus();

    myNorthPanel.revalidate();
    myNorthPanel.repaint();
  }
  private VirtualFile[] getSelectedFilesInt() {
    if (myTreeIsUpdating || !myUiUpdater.isEmpty()) {
      if (isTextFieldActive() && !StringUtil.isEmpty(myPathTextField.getTextFieldText())) {
        LookupFile toFind = myPathTextField.getFile();
        if (toFind instanceof LocalFsFinder.VfsFile && toFind.exists()) {
          VirtualFile file = ((LocalFsFinder.VfsFile) toFind).getFile();
          if (file != null) {
            return new VirtualFile[] {file};
          }
        }
      }
      return VirtualFile.EMPTY_ARRAY;
    }

    return myFileSystemTree.getSelectedFiles();
  }
  protected void restoreSelection(@Nullable VirtualFile toSelect) {
    final VirtualFile lastOpenedFile = FileChooserUtil.getLastOpenedFile(myProject);
    final VirtualFile file =
        FileChooserUtil.getFileToSelect(myChooserDescriptor, myProject, toSelect, lastOpenedFile);

    if (file != null && file.isValid()) {
      myFileSystemTree.select(
          file,
          new Runnable() {
            public void run() {
              if (!file.equals(myFileSystemTree.getSelectedFile())) {
                VirtualFile parent = file.getParent();
                if (parent != null) {
                  myFileSystemTree.select(parent, null);
                }
              } else if (file.isDirectory()) {
                myFileSystemTree.expand(file, null);
              }
            }
          });
    }
  }
  private void selectInTree(VirtualFile[] array, boolean requestFocus, boolean updatePathNeeded) {
    myTreeIsUpdating = true;
    final List<VirtualFile> fileList = Arrays.asList(array);
    if (!Arrays.asList(myFileSystemTree.getSelectedFiles()).containsAll(fileList)) {
      myFileSystemTree.select(
          array,
          () -> {
            if (!myFileSystemTree.areHiddensShown()
                && !Arrays.asList(myFileSystemTree.getSelectedFiles()).containsAll(fileList)) {
              // try to select files in hidden folders
              myFileSystemTree.showHiddens(true);
              selectInTree(array, requestFocus, updatePathNeeded);
              return;
            }
            if (array.length == 1
                && !Arrays.asList(myFileSystemTree.getSelectedFiles()).containsAll(fileList)) {
              // try to select a parent of a missed file
              VirtualFile parent = array[0].getParent();
              if (parent != null && parent.isValid()) {
                selectInTree(new VirtualFile[] {parent}, requestFocus, updatePathNeeded);
                return;
              }
            }

            reportFileNotFound();
            if (updatePathNeeded) {
              updatePathFromTree(fileList, true);
            }
            if (requestFocus) {
              //noinspection SSBasedInspection
              SwingUtilities.invokeLater(() -> myFileSystemTree.getTree().requestFocus());
            }
          });
    } else {
      reportFileNotFound();
      if (updatePathNeeded) {
        updatePathFromTree(fileList, true);
      }
    }
  }
 protected final void registerMouseListener(final ActionGroup group) {
   myFileSystemTree.registerMouseListener(group);
 }
  protected JComponent createCenterPanel() {
    JPanel panel = new MyPanel();

    myUiUpdater = new MergingUpdateQueue("FileChooserUpdater", 200, false, panel);
    Disposer.register(myDisposable, myUiUpdater);
    new UiNotifyConnector(panel, myUiUpdater);

    panel.setBorder(JBUI.Borders.empty());

    createTree();

    final DefaultActionGroup group = createActionGroup();
    ActionToolbar toolBar =
        ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true);
    toolBar.setTargetComponent(panel);

    final JPanel toolbarPanel = new JPanel(new BorderLayout());
    toolbarPanel.add(toolBar.getComponent(), BorderLayout.CENTER);

    myTextFieldAction =
        new TextFieldAction() {
          public void linkSelected(final LinkLabel aSource, final Object aLinkData) {
            toggleShowTextField();
          }
        };
    toolbarPanel.add(myTextFieldAction, BorderLayout.EAST);

    myPathTextFieldWrapper = new JPanel(new BorderLayout());
    myPathTextFieldWrapper.setBorder(JBUI.Borders.emptyBottom(2));
    myPathTextField =
        new FileTextFieldImpl.Vfs(
            FileChooserFactoryImpl.getMacroMap(),
            getDisposable(),
            new LocalFsFinder.FileChooserFilter(myChooserDescriptor, myFileSystemTree)) {
          protected void onTextChanged(final String newValue) {
            myUiUpdater.cancelAllUpdates();
            updateTreeFromPath(newValue);
          }
        };
    Disposer.register(myDisposable, myPathTextField);
    myPathTextFieldWrapper.add(myPathTextField.getField(), BorderLayout.CENTER);
    if (getRecentFiles().length > 0) {
      myPathTextFieldWrapper.add(createHistoryButton(), BorderLayout.EAST);
    }

    myNorthPanel = new JPanel(new BorderLayout());
    myNorthPanel.add(toolbarPanel, BorderLayout.NORTH);

    updateTextFieldShowing();

    panel.add(myNorthPanel, BorderLayout.NORTH);

    registerMouseListener(group);

    JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myFileSystemTree.getTree());
    // scrollPane.setBorder(BorderFactory.createLineBorder(new Color(148, 154, 156)));
    panel.add(scrollPane, BorderLayout.CENTER);
    panel.setPreferredSize(JBUI.size(400));

    panel.add(
        new JLabel(
            "<html><center><small><font color=gray>Drag and drop a file into the space above to quickly locate it in the tree.</font></small></center></html>",
            SwingConstants.CENTER),
        BorderLayout.SOUTH);

    ApplicationManager.getApplication()
        .getMessageBus()
        .connect(getDisposable())
        .subscribe(
            ApplicationActivationListener.TOPIC,
            new ApplicationActivationListener.Adapter() {
              @Override
              public void applicationActivated(IdeFrame ideFrame) {
                ((SaveAndSyncHandlerImpl) SaveAndSyncHandler.getInstance())
                    .maybeRefresh(ModalityState.current());
              }
            });

    return panel;
  }
 private void registerTreeActionShortcut(@NonNls final String actionId) {
   final JTree tree = myFileSystemTree.getTree();
   final AnAction action = ActionManager.getInstance().getAction(actionId);
   action.registerCustomShortcutSet(action.getShortcutSet(), tree, myDisposable);
 }