| /* |
| * Copyright 2000-2009 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.todo.nodes; |
| |
| import com.intellij.ide.IdeBundle; |
| import com.intellij.ide.projectView.PresentationData; |
| import com.intellij.ide.projectView.ViewSettings; |
| import com.intellij.ide.projectView.impl.nodes.PackageElement; |
| import com.intellij.ide.projectView.impl.nodes.PackageElementNode; |
| import com.intellij.ide.todo.HighlightedRegionProvider; |
| import com.intellij.ide.todo.TodoFileDirAndModuleComparator; |
| import com.intellij.ide.todo.TodoTreeBuilder; |
| import com.intellij.ide.todo.TodoTreeStructure; |
| import com.intellij.ide.util.treeView.AbstractTreeNode; |
| import com.intellij.openapi.editor.colors.EditorColorsScheme; |
| import com.intellij.openapi.editor.markup.TextAttributes; |
| import com.intellij.openapi.ide.CopyPasteManager; |
| import com.intellij.openapi.module.Module; |
| import com.intellij.openapi.project.IndexNotReadyException; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.roots.ProjectFileIndex; |
| import com.intellij.openapi.roots.ProjectRootManager; |
| import com.intellij.psi.JavaDirectoryService; |
| import com.intellij.psi.PsiDirectory; |
| import com.intellij.psi.PsiFile; |
| import com.intellij.psi.PsiPackage; |
| import com.intellij.psi.search.GlobalSearchScope; |
| import com.intellij.ui.HighlightedRegion; |
| import com.intellij.usageView.UsageTreeColors; |
| import com.intellij.usageView.UsageTreeColorsScheme; |
| import com.intellij.util.ArrayUtil; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import java.awt.*; |
| import java.util.*; |
| |
| public final class TodoPackageNode extends PackageElementNode implements HighlightedRegionProvider { |
| private final ArrayList<HighlightedRegion> myHighlightedRegions; |
| private final TodoTreeBuilder myBuilder; |
| @Nullable private final String myPresentationName; |
| |
| public TodoPackageNode(@NotNull Project project, |
| PackageElement element, |
| TodoTreeBuilder builder) { |
| this(project, element, builder,null); |
| } |
| |
| public TodoPackageNode(@NotNull Project project, |
| PackageElement element, |
| TodoTreeBuilder builder, |
| @Nullable String name) { |
| super(project, element, ViewSettings.DEFAULT); |
| myBuilder = builder; |
| myHighlightedRegions = new ArrayList<HighlightedRegion>(2); |
| if (element != null && name == null){ |
| final PsiPackage aPackage = element.getPackage(); |
| myPresentationName = aPackage.getName(); |
| } |
| else { |
| myPresentationName = name; |
| } |
| } |
| |
| |
| @Override |
| public ArrayList<HighlightedRegion> getHighlightedRegions() { |
| return myHighlightedRegions; |
| } |
| |
| @Override |
| protected void update(PresentationData data) { |
| super.update(data); |
| final PackageElement packageElement = getValue(); |
| |
| try { |
| if (packageElement == null || !packageElement.getPackage().isValid()) { |
| setValue(null); |
| return; |
| } |
| |
| int fileCount = getFileCount(packageElement); |
| if (fileCount == 0){ |
| setValue(null); |
| return; |
| } |
| |
| PsiPackage aPackage = packageElement.getPackage(); |
| String newName; |
| if (getStructure().areFlattenPackages()) { |
| newName = aPackage.getQualifiedName(); |
| } |
| else { |
| newName = myPresentationName != null ? myPresentationName : ""; |
| } |
| |
| int nameEndOffset = newName.length(); |
| int todoItemCount = getTodoItemCount(packageElement); |
| newName = IdeBundle.message("node.todo.group", newName, todoItemCount, fileCount); |
| |
| myHighlightedRegions.clear(); |
| |
| TextAttributes textAttributes = new TextAttributes(); |
| Color newColor = null; |
| |
| if (CopyPasteManager.getInstance().isCutElement(packageElement)) { |
| newColor = CopyPasteManager.CUT_COLOR; |
| } |
| textAttributes.setForegroundColor(newColor); |
| myHighlightedRegions.add(new HighlightedRegion(0, nameEndOffset, textAttributes)); |
| |
| EditorColorsScheme colorsScheme = UsageTreeColorsScheme.getInstance().getScheme(); |
| myHighlightedRegions.add( |
| new HighlightedRegion(nameEndOffset, newName.length(), colorsScheme.getAttributes(UsageTreeColors.NUMBER_OF_USAGES))); |
| |
| data.setPresentableText(newName); |
| } |
| catch (IndexNotReadyException e) { |
| LOG.info(e); |
| data.setPresentableText("N/A"); |
| } |
| } |
| |
| @Override |
| public void apply(@NotNull Map<String, String> info) { |
| info.put("toDoFileCount", String.valueOf(getFileCount(getValue()))); |
| info.put("toDoItemCount", String.valueOf(getTodoItemCount(getValue()))); |
| } |
| |
| private int getFileCount(final PackageElement packageElement) { |
| int count = 0; |
| if (getSettings().isFlattenPackages()) { |
| final PsiPackage aPackage = packageElement.getPackage(); |
| final Module module = packageElement.getModule(); |
| final GlobalSearchScope scope = |
| module != null ? GlobalSearchScope.moduleScope(module) : GlobalSearchScope.projectScope(aPackage.getProject()); |
| final PsiDirectory[] directories = aPackage.getDirectories(scope); |
| for (PsiDirectory directory : directories) { |
| Iterator<PsiFile> iterator = myBuilder.getFilesUnderDirectory(directory); |
| while (iterator.hasNext()) { |
| PsiFile psiFile = iterator.next(); |
| if (getStructure().accept(psiFile)) count++; |
| } |
| } |
| } |
| else { |
| Iterator<PsiFile> iterator = getFiles(packageElement); |
| while (iterator.hasNext()) { |
| PsiFile psiFile = iterator.next(); |
| if (getStructure().accept(psiFile)) { |
| count++; |
| } |
| } |
| } |
| return count; |
| } |
| |
| public int getTodoItemCount(PackageElement packageElement) { |
| int count = 0; |
| if (getSettings().isFlattenPackages()){ |
| final PsiPackage aPackage = packageElement.getPackage(); |
| final Module module = packageElement.getModule(); |
| GlobalSearchScope scope = module != null ? GlobalSearchScope.moduleScope(module) : GlobalSearchScope.projectScope(aPackage.getProject()); |
| final PsiDirectory[] directories = aPackage.getDirectories(scope); |
| for (PsiDirectory directory : directories) { |
| Iterator<PsiFile> iterator = myBuilder.getFilesUnderDirectory(directory); |
| while(iterator.hasNext()){ |
| PsiFile psiFile = iterator.next(); |
| count+=getStructure().getTodoItemCount(psiFile); |
| } |
| } |
| } else { |
| Iterator<PsiFile> iterator = getFiles(packageElement); |
| while(iterator.hasNext()){ |
| PsiFile psiFile = iterator.next(); |
| count+=getStructure().getTodoItemCount(psiFile); |
| } |
| } |
| return count; |
| } |
| |
| private TodoTreeStructure getStructure() { |
| return myBuilder.getTodoTreeStructure(); |
| } |
| |
| @Override |
| @NotNull |
| public Collection<AbstractTreeNode> getChildren() { |
| ArrayList<AbstractTreeNode> children = new ArrayList<AbstractTreeNode>(); |
| final Project project = getProject(); |
| final ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex(); |
| final PsiPackage psiPackage = getValue().getPackage(); |
| final Module module = getValue().getModule(); |
| if (!getStructure().getIsFlattenPackages() || psiPackage == null) { |
| final Iterator<PsiFile> iterator = getFiles(getValue()); |
| while (iterator.hasNext()) { |
| final PsiFile psiFile = iterator.next(); |
| final Module psiFileModule = projectFileIndex.getModuleForFile(psiFile.getVirtualFile()); |
| //group by module |
| if (module != null && psiFileModule != null && !module.equals(psiFileModule)){ |
| continue; |
| } |
| // Add files |
| final PsiDirectory containingDirectory = psiFile.getContainingDirectory(); |
| TodoFileNode todoFileNode = new TodoFileNode(project, psiFile, myBuilder, false); |
| if (ArrayUtil.find(psiPackage.getDirectories(), containingDirectory) > -1 && !children.contains(todoFileNode)) { |
| children.add(todoFileNode); |
| continue; |
| } |
| // Add packages |
| PsiDirectory _dir = psiFile.getContainingDirectory(); |
| while (_dir != null) { |
| final PsiDirectory parentDirectory = _dir.getParentDirectory(); |
| if (parentDirectory != null){ |
| PsiPackage _package = JavaDirectoryService.getInstance().getPackage(_dir); |
| if (_package != null && _package.getParentPackage() != null && psiPackage.equals(_package.getParentPackage())) { |
| final GlobalSearchScope scope = module != null ? GlobalSearchScope.moduleScope(module) : GlobalSearchScope.projectScope(project); |
| _package = TodoJavaTreeHelper.findNonEmptyPackage(_package, module, project, myBuilder, scope); //compact empty middle packages |
| final String name = _package.getParentPackage().equals(psiPackage) |
| ? null //non compacted |
| : _package.getQualifiedName().substring(psiPackage.getQualifiedName().length() + 1); |
| TodoPackageNode todoPackageNode = new TodoPackageNode(project, new PackageElement(module, _package, false), myBuilder, name); |
| if (!children.contains(todoPackageNode)) { |
| children.add(todoPackageNode); |
| break; |
| } |
| } |
| } |
| _dir = parentDirectory; |
| } |
| } |
| } |
| else { // flatten packages |
| final Iterator<PsiFile> iterator = getFiles(getValue()); |
| while (iterator.hasNext()) { |
| final PsiFile psiFile = iterator.next(); |
| //group by module |
| final Module psiFileModule = projectFileIndex.getModuleForFile(psiFile.getVirtualFile()); |
| if (module != null && psiFileModule != null && !module.equals(psiFileModule)){ |
| continue; |
| } |
| final PsiDirectory _dir = psiFile.getContainingDirectory(); |
| // Add files |
| TodoFileNode todoFileNode = new TodoFileNode(getProject(), psiFile, myBuilder, false); |
| if (ArrayUtil.find(psiPackage.getDirectories(), _dir) > -1 && !children.contains(todoFileNode)) { |
| children.add(todoFileNode); |
| continue; |
| } |
| } |
| } |
| Collections.sort(children, TodoFileDirAndModuleComparator.INSTANCE); |
| return children; |
| } |
| |
| /** |
| * @return read-only iterator of all valid PSI files that can have T.O.D.O items |
| * and which are located under specified <code>psiDirctory</code>. |
| */ |
| public Iterator<PsiFile> getFiles(PackageElement packageElement) { |
| ArrayList<PsiFile> psiFileList = new ArrayList<PsiFile>(); |
| GlobalSearchScope scope = packageElement.getModule() != null ? GlobalSearchScope.moduleScope(packageElement.getModule()) : |
| GlobalSearchScope.projectScope(myProject); |
| final PsiDirectory[] directories = packageElement.getPackage().getDirectories(scope); |
| for (PsiDirectory directory : directories) { |
| Iterator<PsiFile> files = myBuilder.getFiles(directory, false); |
| for (;files.hasNext();) { |
| psiFileList.add(files.next()); |
| } |
| } |
| return psiFileList.iterator(); |
| } |
| |
| @Override |
| public int getWeight() { |
| return 3; |
| } |
| } |
| |