blob: d08d93d31cc5ee0fa23a109e93418082c118067c [file] [log] [blame]
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.ide.favoritesTreeView;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.favoritesTreeView.actions.AddToFavoritesAction;
import com.intellij.ide.projectView.impl.*;
import com.intellij.ide.projectView.impl.nodes.LibraryGroupElement;
import com.intellij.ide.projectView.impl.nodes.NamedLibraryElement;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.DumbAwareRunnable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.ui.InputValidator;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.*;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtilBase;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.TreeItem;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import static com.intellij.ide.favoritesTreeView.FavoritesListProvider.EP_NAME;
public class FavoritesManager implements ProjectComponent, JDOMExternalizable {
// fav list name -> list of (root: root url, root class)
private final Map<String, List<TreeItem<Pair<AbstractUrl, String>>>> myName2FavoritesRoots =
new TreeMap<String, List<TreeItem<Pair<AbstractUrl, String>>>>();
private final Map<String, String> myDescriptions = new HashMap<String, String>();
private final Project myProject;
private final List<FavoritesListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private final FavoritesViewSettings myViewSettings = new FavoritesViewSettings();
private final Map<String, FavoritesListProvider> myProviders = new HashMap<String, FavoritesListProvider>();
private void rootsChanged() {
for (FavoritesListener listener : myListeners) {
listener.rootsChanged();
}
}
private void listAdded(String listName) {
for (FavoritesListener listener : myListeners) {
listener.listAdded(listName);
}
}
private void listRemoved(String listName) {
for (FavoritesListener listener : myListeners) {
listener.listRemoved(listName);
}
}
public void renameList(final Project project, @NotNull String listName) {
final String newName = Messages
.showInputDialog(project, IdeBundle.message("prompt.input.favorites.list.new.name", listName), IdeBundle.message("title.rename.favorites.list"),
Messages.getInformationIcon(), listName, new InputValidator() {
@Override
public boolean checkInput(String inputString) {
return inputString != null && inputString.trim().length() > 0;
}
@Override
public boolean canClose(String inputString) {
inputString = inputString.trim();
if (myName2FavoritesRoots.keySet().contains(inputString) || myProviders.keySet().contains(inputString)) {
Messages.showErrorDialog(project, IdeBundle.message("error.favorites.list.already.exists", inputString.trim()),
IdeBundle.message("title.unable.to.add.favorites.list"));
return false;
}
return !inputString.isEmpty();
}
});
if (newName != null && renameFavoritesList(listName, newName)) {
rootsChanged();
}
}
public void addFavoritesListener(FavoritesListener listener) {
myListeners.add(listener);
listener.rootsChanged();
}
public void removeFavoritesListener(FavoritesListener listener) {
myListeners.remove(listener);
}
List<AbstractTreeNode> createRootNodes() {
List<AbstractTreeNode> result = new ArrayList<AbstractTreeNode>();
for (String listName : myName2FavoritesRoots.keySet()) {
result.add(new FavoritesListNode(myProject, listName, myDescriptions.get(listName)));
}
ArrayList<FavoritesListProvider> providers = new ArrayList<FavoritesListProvider>(myProviders.values());
Collections.sort(providers);
for (FavoritesListProvider provider : providers) {
result.add(provider.createFavoriteListNode(myProject));
}
return result;
}
public static FavoritesManager getInstance(Project project) {
return project.getComponent(FavoritesManager.class);
}
public FavoritesManager(Project project) {
myProject = project;
}
@NotNull
public List<String> getAvailableFavoritesListNames() {
return new ArrayList<String>(myName2FavoritesRoots.keySet());
}
public synchronized void createNewList(@NotNull String listName) {
myName2FavoritesRoots.put(listName, new ArrayList<TreeItem<Pair<AbstractUrl, String>>>());
listAdded(listName);
}
public synchronized void fireListeners(@NotNull final String listName) {
rootsChanged();
}
public FavoritesViewSettings getViewSettings() {
return myViewSettings;
}
public synchronized boolean removeFavoritesList(@NotNull String name) {
boolean result = myName2FavoritesRoots.remove(name) != null;
myDescriptions.remove(name);
listRemoved(name);
return result;
}
@NotNull
public List<TreeItem<Pair<AbstractUrl, String>>> getFavoritesListRootUrls(@NotNull String name) {
final List<TreeItem<Pair<AbstractUrl, String>>> pairs = myName2FavoritesRoots.get(name);
return pairs == null ? new ArrayList<TreeItem<Pair<AbstractUrl, String>>>() : pairs;
}
public synchronized boolean addRoots(@NotNull String name, Module moduleContext, @NotNull Object elements) {
Collection<AbstractTreeNode> nodes = AddToFavoritesAction.createNodes(myProject, moduleContext, elements, true, getViewSettings());
return !nodes.isEmpty() && addRoots(name, nodes);
}
public synchronized Comparator<FavoritesTreeNodeDescriptor> getCustomComparator(@NotNull final String name) {
return myProviders.get(name);
}
private Pair<AbstractUrl, String> createPairForNode(AbstractTreeNode node) {
final String className = node.getClass().getName();
final Object value = node.getValue();
final AbstractUrl url = createUrlByElement(value, myProject);
if (url == null) return null;
return Pair.create(url, className);
}
public boolean addRoots(final String name, final Collection<AbstractTreeNode> nodes) {
final Collection<TreeItem<Pair<AbstractUrl, String>>> list = getFavoritesListRootUrls(name);
final HashSet<AbstractUrl> set =
new HashSet<AbstractUrl>(ContainerUtil.map(list, new Function<TreeItem<Pair<AbstractUrl,String>>, AbstractUrl>() {
@Override
public AbstractUrl fun(TreeItem<Pair<AbstractUrl, String>> item) {
return item.getData().getFirst();
}
}));
for (AbstractTreeNode node : nodes) {
final Pair<AbstractUrl, String> pair = createPairForNode(node);
if (pair != null) {
if (set.contains(pair.getFirst())) continue;
final TreeItem<Pair<AbstractUrl, String>> treeItem = new TreeItem<Pair<AbstractUrl, String>>(pair);
list.add(treeItem);
set.add(pair.getFirst());
appendChildNodes(node, treeItem);
}
}
rootsChanged();
return true;
}
private void appendChildNodes(AbstractTreeNode node, TreeItem<Pair<AbstractUrl, String>> treeItem) {
final Collection<? extends AbstractTreeNode> children = node.getChildren();
for (AbstractTreeNode child : children) {
final TreeItem<Pair<AbstractUrl, String>> childTreeItem = new TreeItem<Pair<AbstractUrl, String>>(createPairForNode(child));
treeItem.addChild(childTreeItem);
appendChildNodes(child, childTreeItem);
}
}
public synchronized boolean addRoot(@NotNull String name,
@NotNull List<AbstractTreeNode> parentElements,
final AbstractTreeNode newElement,
@Nullable AbstractTreeNode sibling) {
final List<TreeItem<Pair<AbstractUrl, String>>> items = myName2FavoritesRoots.get(name);
if (items == null) return false;
AbstractUrl url = createUrlByElement(newElement.getValue(), myProject);
if (url == null) return false;
final TreeItem<Pair<AbstractUrl, String>> newItem =
new TreeItem<Pair<AbstractUrl, String>>(Pair.create(url, newElement.getClass().getName()));
if (parentElements.isEmpty()) {
// directly to list
if (sibling != null) {
TreeItem<Pair<AbstractUrl, String>> after = null;
AbstractUrl siblingUrl = createUrlByElement(sibling.getValue(), myProject);
int idx = -1;
for (int i = 0; i < items.size(); i++) {
TreeItem<Pair<AbstractUrl, String>> item = items.get(i);
if (item.getData().getFirst().equals(siblingUrl)) {
idx = i;
break;
}
}
if (idx != -1) {
items.add(idx, newItem);
}
else {
items.add(newItem);
}
}
else {
items.add(newItem);
}
rootsChanged();
return true;
}
Collection<TreeItem<Pair<AbstractUrl, String>>> list = items;
TreeItem<Pair<AbstractUrl, String>> item = null;
for (AbstractTreeNode obj : parentElements) {
AbstractUrl objUrl = createUrlByElement(obj.getValue(), myProject);
item = findNextItem(objUrl, list);
if (item == null) return false;
list = item.getChildren();
}
if (sibling != null) {
TreeItem<Pair<AbstractUrl, String>> after = null;
AbstractUrl siblingUrl = createUrlByElement(sibling.getValue(), myProject);
for (TreeItem<Pair<AbstractUrl, String>> treeItem : list) {
if (treeItem.getData().getFirst().equals(siblingUrl)) {
after = treeItem;
break;
}
}
if (after == null) {
item.addChild(newItem);
}
else {
item.addChildAfter(newItem, after);
}
}
else {
item.addChild(newItem);
}
rootsChanged();
return true;
}
private <T> boolean findListToRemoveFrom(@NotNull String name, @NotNull final List<T> elements,
final Convertor<T, AbstractUrl> convertor) {
Collection<TreeItem<Pair<AbstractUrl, String>>> list = getFavoritesListRootUrls(name);
if (elements.size() > 1) {
final List<T> sublist = elements.subList(0, elements.size() - 1);
for (T obj : sublist) {
AbstractUrl objUrl = convertor.convert(obj);
final TreeItem<Pair<AbstractUrl, String>> item = findNextItem(objUrl, list);
if (item == null || item.getChildren() == null) return false;
list = item.getChildren();
}
}
TreeItem<Pair<AbstractUrl, String>> found = null;
AbstractUrl url = convertor.convert(elements.get(elements.size() - 1));
if (url == null) return false;
for (TreeItem<Pair<AbstractUrl, String>> pair : list) {
if (url.equals(pair.getData().getFirst())) {
found = pair;
break;
}
}
if (found != null) {
list.remove(found);
rootsChanged();
return true;
}
return false;
}
public synchronized boolean removeRoot(@NotNull String name, @NotNull List<AbstractTreeNode> elements) {
final Convertor<AbstractTreeNode, AbstractUrl> convertor = new Convertor<AbstractTreeNode, AbstractUrl>() {
@Override
public AbstractUrl convert(AbstractTreeNode obj) {
return createUrlByElement(obj.getValue(), myProject);
}
};
boolean result = true;
for (AbstractTreeNode element : elements) {
final List<AbstractTreeNode> path = TaskDefaultFavoriteListProvider.getPathToUsualNode(element);
result &= findListToRemoveFrom(name, path.subList(1, path.size()), convertor);
}
return result;
}
private TreeItem<Pair<AbstractUrl, String>> findNextItem(AbstractUrl url, Collection<TreeItem<Pair<AbstractUrl, String>>> list) {
for (TreeItem<Pair<AbstractUrl, String>> pair : list) {
if (url.equals(pair.getData().getFirst())) {
return pair;
}
}
return null;
}
private boolean renameFavoritesList(@NotNull String oldName, @NotNull String newName) {
List<TreeItem<Pair<AbstractUrl, String>>> list = myName2FavoritesRoots.remove(oldName);
if (list != null && newName.length() > 0) {
myName2FavoritesRoots.put(newName, list);
String description = myDescriptions.remove(oldName);
if (description != null) {
myDescriptions.put(newName, description);
}
rootsChanged();
return true;
}
return false;
}
@Override
public void initComponent() {
}
@Override
public void disposeComponent() {
}
@Override
public void projectOpened() {
if (!ApplicationManager.getApplication().isUnitTestMode()) {
StartupManager.getInstance(myProject).registerPostStartupActivity(new DumbAwareRunnable() {
@Override
public void run() {
final FavoritesListProvider[] providers = Extensions.getExtensions(EP_NAME, myProject);
for (FavoritesListProvider provider : providers) {
myProviders.put(provider.getListName(myProject), provider);
}
final MyRootsChangeAdapter myPsiTreeChangeAdapter = new MyRootsChangeAdapter();
PsiManager.getInstance(myProject).addPsiTreeChangeListener(myPsiTreeChangeAdapter, myProject);
if (myName2FavoritesRoots.isEmpty()) {
myDescriptions.put(myProject.getName(), "auto-added");
createNewList(myProject.getName());
}
}
});
}
}
@Override
public void projectClosed() {
}
@Override
@NotNull
public String getComponentName() {
return "FavoritesManager";
}
@Nullable
public FavoritesListProvider getListProvider(@Nullable String name) {
return myProviders.get(name);
}
@Override
public void readExternal(Element element) throws InvalidDataException {
myName2FavoritesRoots.clear();
for (Object list : element.getChildren(ELEMENT_FAVORITES_LIST)) {
final String name = ((Element)list).getAttributeValue(ATTRIBUTE_NAME);
List<TreeItem<Pair<AbstractUrl, String>>> roots = readRoots((Element)list, myProject);
myName2FavoritesRoots.put(name, roots);
}
DefaultJDOMExternalizer.readExternal(this, element);
}
@NonNls private static final String CLASS_NAME = "klass";
@NonNls private static final String FAVORITES_ROOT = "favorite_root";
@NonNls private static final String ELEMENT_FAVORITES_LIST = "favorites_list";
@NonNls private static final String ATTRIBUTE_NAME = "name";
private static List<TreeItem<Pair<AbstractUrl, String>>> readRoots(final Element list, Project project) {
List<TreeItem<Pair<AbstractUrl, String>>> result = new ArrayList<TreeItem<Pair<AbstractUrl, String>>>();
readFavoritesOneLevel(list, project, result);
return result;
}
private static void readFavoritesOneLevel(Element list, Project project, Collection<TreeItem<Pair<AbstractUrl, String>>> result) {
final List listChildren = list.getChildren(FAVORITES_ROOT);
if (listChildren == null || listChildren.isEmpty()) return;
for (Object favorite : listChildren) {
final Element favoriteElement = (Element)favorite;
final String className = favoriteElement.getAttributeValue(CLASS_NAME);
final AbstractUrl abstractUrl = readUrlFromElement(favoriteElement, project);
if (abstractUrl != null) {
final TreeItem<Pair<AbstractUrl, String>> treeItem = new TreeItem<Pair<AbstractUrl, String>>(Pair.create(abstractUrl, className));
result.add(treeItem);
readFavoritesOneLevel(favoriteElement, project, treeItem.getChildren());
}
}
}
private static final ArrayList<AbstractUrl> ourAbstractUrlProviders = new ArrayList<AbstractUrl>();
static {
ourAbstractUrlProviders.add(new ModuleUrl(null, null));
ourAbstractUrlProviders.add(new DirectoryUrl(null, null));
ourAbstractUrlProviders.add(new ModuleGroupUrl(null));
ourAbstractUrlProviders.add(new PsiFileUrl(null));
ourAbstractUrlProviders.add(new LibraryModuleGroupUrl(null));
ourAbstractUrlProviders.add(new NamedLibraryUrl(null, null));
}
@NonNls private static final String ATTRIBUTE_TYPE = "type";
@NonNls private static final String ATTRIBUTE_URL = "url";
@NonNls private static final String ATTRIBUTE_MODULE = "module";
@Nullable
private static AbstractUrl readUrlFromElement(Element element, Project project) {
final String type = element.getAttributeValue(ATTRIBUTE_TYPE);
final String urlValue = element.getAttributeValue(ATTRIBUTE_URL);
final String moduleName = element.getAttributeValue(ATTRIBUTE_MODULE);
for (FavoriteNodeProvider nodeProvider : Extensions.getExtensions(FavoriteNodeProvider.EP_NAME, project)) {
if (nodeProvider.getFavoriteTypeId().equals(type)) {
return new AbstractUrlFavoriteAdapter(urlValue, moduleName, nodeProvider);
}
}
for (AbstractUrl urlProvider : ourAbstractUrlProviders) {
AbstractUrl url = urlProvider.createUrl(type, moduleName, urlValue);
if (url != null) return url;
}
return null;
}
@Override
public void writeExternal(Element element) throws WriteExternalException {
for (final String name : myName2FavoritesRoots.keySet()) {
Element list = new Element(ELEMENT_FAVORITES_LIST);
list.setAttribute(ATTRIBUTE_NAME, name);
writeRoots(list, myName2FavoritesRoots.get(name));
element.addContent(list);
}
DefaultJDOMExternalizer.writeExternal(this, element);
}
@Nullable
public static AbstractUrl createUrlByElement(Object element, final Project project) {
if (element instanceof SmartPsiElementPointer) element = ((SmartPsiElementPointer)element).getElement();
for (FavoriteNodeProvider nodeProvider : Extensions.getExtensions(FavoriteNodeProvider.EP_NAME, project)) {
String url = nodeProvider.getElementUrl(element);
if (url != null) {
return new AbstractUrlFavoriteAdapter(url, nodeProvider.getElementModuleName(element), nodeProvider);
}
}
for (AbstractUrl urlProvider : ourAbstractUrlProviders) {
AbstractUrl url = urlProvider.createUrlByElement(element);
if (url != null) return url;
}
return null;
}
private static void writeRoots(Element element, Collection<TreeItem<Pair<AbstractUrl, String>>> roots) {
for (TreeItem<Pair<AbstractUrl, String>> root : roots) {
final AbstractUrl url = root.getData().getFirst();
if (url == null) continue;
final Element list = new Element(FAVORITES_ROOT);
url.write(list);
list.setAttribute(CLASS_NAME, root.getData().getSecond());
element.addContent(list);
final List<TreeItem<Pair<AbstractUrl, String>>> children = root.getChildren();
if (children != null && !children.isEmpty()) {
writeRoots(list, children);
}
}
}
public String getFavoriteListName(@Nullable final String currentSubId, @NotNull final VirtualFile vFile) {
if (currentSubId != null && contains(currentSubId, vFile)) {
return currentSubId;
}
for (String listName : myName2FavoritesRoots.keySet()) {
if (contains(listName, vFile)) {
return listName;
}
}
return null;
}
// currently only one level here..
public boolean contains(@NotNull String name, @NotNull final VirtualFile vFile) {
final ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
final Set<Boolean> find = new HashSet<Boolean>();
final ContentIterator contentIterator = new ContentIterator() {
@Override
public boolean processFile(VirtualFile fileOrDir) {
if (fileOrDir != null && fileOrDir.getPath().equals(vFile.getPath())) {
find.add(Boolean.TRUE);
}
return true;
}
};
Collection<TreeItem<Pair<AbstractUrl, String>>> urls = getFavoritesListRootUrls(name);
for (TreeItem<Pair<AbstractUrl, String>> pair : urls) {
AbstractUrl abstractUrl = pair.getData().getFirst();
if (abstractUrl == null) {
continue;
}
final Object[] path = abstractUrl.createPath(myProject);
if (path == null || path.length < 1 || path[0] == null) {
continue;
}
Object element = path[path.length - 1];
if (element instanceof SmartPsiElementPointer) {
final VirtualFile virtualFile = PsiUtilBase.getVirtualFile(((SmartPsiElementPointer)element).getElement());
if (virtualFile == null) continue;
if (vFile.getPath().equals(virtualFile.getPath())) {
return true;
}
if (!virtualFile.isDirectory()) {
continue;
}
projectFileIndex.iterateContentUnderDirectory(virtualFile, contentIterator);
}
if (element instanceof PsiElement) {
final VirtualFile virtualFile = PsiUtilBase.getVirtualFile((PsiElement)element);
if (virtualFile == null) continue;
if (vFile.getPath().equals(virtualFile.getPath())) {
return true;
}
if (!virtualFile.isDirectory()) {
continue;
}
projectFileIndex.iterateContentUnderDirectory(virtualFile, contentIterator);
}
if (element instanceof Module) {
ModuleRootManager.getInstance((Module)element).getFileIndex().iterateContent(contentIterator);
}
if (element instanceof LibraryGroupElement) {
final boolean inLibrary =
ModuleRootManager.getInstance(((LibraryGroupElement)element).getModule()).getFileIndex().isInContent(vFile) &&
projectFileIndex.isInLibraryClasses(vFile);
if (inLibrary) {
return true;
}
}
if (element instanceof NamedLibraryElement) {
NamedLibraryElement namedLibraryElement = (NamedLibraryElement)element;
final VirtualFile[] files = namedLibraryElement.getOrderEntry().getRootFiles(OrderRootType.CLASSES);
if (files != null && ArrayUtil.find(files, vFile) > -1) {
return true;
}
}
if (element instanceof ModuleGroup) {
ModuleGroup group = (ModuleGroup)element;
final Collection<Module> modules = group.modulesInGroup(myProject, true);
for (Module module : modules) {
ModuleRootManager.getInstance(module).getFileIndex().iterateContent(contentIterator);
}
}
for (FavoriteNodeProvider provider : Extensions.getExtensions(FavoriteNodeProvider.EP_NAME, myProject)) {
if (provider.elementContainsFile(element, vFile)) {
return true;
}
}
if (!find.isEmpty()) {
return true;
}
}
return false;
}
private static void iterateTreeItems(final Collection<TreeItem<Pair<AbstractUrl, String>>> coll,
Consumer<TreeItem<Pair<AbstractUrl, String>>> consumer) {
final ArrayDeque<TreeItem<Pair<AbstractUrl, String>>> queue = new ArrayDeque<TreeItem<Pair<AbstractUrl, String>>>();
queue.addAll(coll);
while (!queue.isEmpty()) {
final TreeItem<Pair<AbstractUrl, String>> item = queue.removeFirst();
consumer.consume(item);
final List<TreeItem<Pair<AbstractUrl, String>>> children = item.getChildren();
if (children != null && !children.isEmpty()) {
queue.addAll(children);
}
}
}
private class MyRootsChangeAdapter extends PsiTreeChangeAdapter {
@Override
public void beforeChildMovement(@NotNull final PsiTreeChangeEvent event) {
final PsiElement oldParent = event.getOldParent();
final PsiElement newParent = event.getNewParent();
final PsiElement child = event.getChild();
if (newParent instanceof PsiDirectory) {
final Module module = ModuleUtil.findModuleForPsiElement(newParent);
if (module == null) return;
AbstractUrl childUrl = null;
if (child instanceof PsiFile) {
childUrl = new PsiFileUrl(((PsiDirectory)newParent).getVirtualFile().getUrl() + "/" + ((PsiFile)child).getName());
}
else if (child instanceof PsiDirectory) {
childUrl =
new DirectoryUrl(((PsiDirectory)newParent).getVirtualFile().getUrl() + "/" + ((PsiDirectory)child).getName(), module.getName());
}
for (String listName : myName2FavoritesRoots.keySet()) {
final List<TreeItem<Pair<AbstractUrl, String>>> roots = myName2FavoritesRoots.get(listName);
final AbstractUrl finalChildUrl = childUrl;
iterateTreeItems(roots, new Consumer<TreeItem<Pair<AbstractUrl, String>>>() {
@Override
public void consume(TreeItem<Pair<AbstractUrl, String>> item) {
final Pair<AbstractUrl, String> root = item.getData();
final Object[] path = root.first.createPath(myProject);
if (path == null || path.length < 1 || path[0] == null) {
return;
}
final Object element = path[path.length - 1];
if (element == child && finalChildUrl != null) {
item.setData(Pair.create(finalChildUrl, root.second));
}
else {
if (element == oldParent) {
item.setData(Pair.create(root.first.createUrlByElement(newParent), root.second));
}
}
}
});
}
}
}
@Override
public void beforePropertyChange(@NotNull final PsiTreeChangeEvent event) {
if (event.getPropertyName().equals(PsiTreeChangeEvent.PROP_FILE_NAME) ||
event.getPropertyName().equals(PsiTreeChangeEvent.PROP_DIRECTORY_NAME)) {
final PsiElement psiElement = event.getChild();
if (psiElement instanceof PsiFile || psiElement instanceof PsiDirectory) {
final Module module = ModuleUtil.findModuleForPsiElement(psiElement);
if (module == null) return;
final String url = ((PsiDirectory)psiElement.getParent()).getVirtualFile().getUrl() + "/" + event.getNewValue();
final AbstractUrl childUrl = psiElement instanceof PsiFile ? new PsiFileUrl(url) : new DirectoryUrl(url, module.getName());
for (String listName : myName2FavoritesRoots.keySet()) {
final List<TreeItem<Pair<AbstractUrl, String>>> roots = myName2FavoritesRoots.get(listName);
iterateTreeItems(roots, new Consumer<TreeItem<Pair<AbstractUrl, String>>>() {
@Override
public void consume(TreeItem<Pair<AbstractUrl, String>> item) {
final Pair<AbstractUrl, String> root = item.getData();
final Object[] path = root.first.createPath(myProject);
if (path == null || path.length < 1 || path[0] == null) {
return;
}
final Object element = path[path.length - 1];
if (element == psiElement && psiElement instanceof PsiFile) {
item.setData(Pair.create(childUrl, root.second));
}
else {
item.setData(root);
}
}
});
}
}
}
}
}
}