void (final DefaultMutableTreeNode node) { final StateWorker stateWorker = new StateWorker(node, myNodeConvertor); final VirtualFile vf = stateWorker.getVf(); if (vf == null) return; final TreeNodeState state = getStateImpl(stateWorker); if (TreeNodeState.HAVE_SELECTED_ABOVE.equals(state)) return; if (TreeNodeState.CLEAR.equals(state) && (! myState.canAddSelection())) return; final Set<VirtualFile> old = myState.getSelected(); final TreeNodeState futureState = myState.putAndPass(vf, TreeNodeState.SELECTED.equals(state) ? TreeNodeState.CLEAR : TreeNodeState.SELECTED); // for those possibly duplicate nodes (i.e. when we have root for module and root for VCS root, each file is shown twice in a tree -> // clear all suspicious cached) if (! TreeNodeState.SELECTED.equals(futureState)) { myState.clearAllCachedMatching(virtualFile -> VfsUtilCore.isAncestor(virtualFile, vf, false)); } stateWorker.iterateParents(myState, (virtualFile, state1) -> { if (TreeNodeState.SELECTED.equals(futureState)) { myState.putAndPass(virtualFile, TreeNodeState.HAVE_SELECTED_BELOW); } else { myState.remove(virtualFile); } return true; }); // todo vf, vf - what is correct? myState.clearAllCachedMatching(vf1 -> VfsUtilCore.isAncestor(stateWorker.getVf(), vf1, false)); for (VirtualFile selected : myState.getSelected()) { if (VfsUtilCore.isAncestor(stateWorker.getVf(), selected, true)) { myState.remove(selected); } } final Set<VirtualFile> selectedAfter = myState.getSelected(); if (mySelectionChangeListener != null && ! old.equals(selectedAfter)) { final Collection<VirtualFile> removed = subtract(old, selectedAfter); final Collection<VirtualFile> newlyAdded = subtract(selectedAfter, old); for (VirtualFile file : newlyAdded) { if (mySelectionChangeListener != null) { mySelectionChangeListener.plus(file); } } for (VirtualFile file : removed) { if (mySelectionChangeListener != null) { mySelectionChangeListener.minus(file); } } } }