2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 package com
.intellij
.ide
.projectView
.impl
;
22 import com
.intellij
.ide
.IdeBundle
;
23 import com
.intellij
.ide
.SelectInTarget
;
24 import com
.intellij
.ide
.impl
.PackagesPaneSelectInTarget
;
25 import com
.intellij
.ide
.projectView
.ProjectView
;
26 import com
.intellij
.ide
.projectView
.ViewSettings
;
27 import com
.intellij
.ide
.projectView
.impl
.nodes
.PackageElement
;
28 import com
.intellij
.ide
.projectView
.impl
.nodes
.PackageUtil
;
29 import com
.intellij
.ide
.projectView
.impl
.nodes
.PackageViewProjectNode
;
30 import com
.intellij
.ide
.util
.treeView
.AbstractTreeBuilder
;
31 import com
.intellij
.ide
.util
.treeView
.AbstractTreeNode
;
32 import com
.intellij
.ide
.util
.treeView
.AbstractTreeStructure
;
33 import com
.intellij
.ide
.util
.treeView
.AbstractTreeUpdater
;
34 import com
.intellij
.openapi
.actionSystem
.*;
35 import com
.intellij
.openapi
.actionSystem
.ex
.DataConstantsEx
;
36 import com
.intellij
.openapi
.module
.Module
;
37 import com
.intellij
.openapi
.project
.Project
;
38 import com
.intellij
.openapi
.roots
.OrderEntry
;
39 import com
.intellij
.openapi
.roots
.ProjectFileIndex
;
40 import com
.intellij
.openapi
.roots
.ProjectRootManager
;
41 import com
.intellij
.openapi
.util
.IconLoader
;
42 import com
.intellij
.openapi
.vfs
.VirtualFile
;
43 import com
.intellij
.psi
.*;
44 import com
.intellij
.psi
.search
.GlobalSearchScope
;
45 import org
.jetbrains
.annotations
.NonNls
;
46 import org
.jetbrains
.annotations
.NotNull
;
47 import org
.jetbrains
.annotations
.Nullable
;
50 import javax
.swing
.tree
.DefaultMutableTreeNode
;
51 import javax
.swing
.tree
.DefaultTreeModel
;
52 import java
.util
.HashSet
;
53 import java
.util
.List
;
56 public final class PackageViewPane
extends AbstractProjectViewPSIPane
{
57 @NonNls public static final String ID
= "PackagesPane";
58 public static final Icon ICON
= IconLoader
.getIcon("/general/packagesTab.png");
60 public PackageViewPane(Project project
) {
64 public String
getTitle() {
65 return IdeBundle
.message("title.packages");
68 public Icon
getIcon() {
73 public String
getId() {
77 public AbstractTreeStructure
getTreeStructure() {
78 return myTreeStructure
;
82 protected PsiElement
getPSIElement(@Nullable final Object element
) {
83 if (element
instanceof PackageElement
) {
84 PsiPackage aPackage
= ((PackageElement
)element
).getPackage();
85 return aPackage
!= null && aPackage
.isValid() ? aPackage
: null;
87 return super.getPSIElement(element
);
91 public Object
getData(final String dataId
) {
92 if (DataConstantsEx
.PACKAGE_ELEMENT
.equals(dataId
)) {
93 final PackageElement packageElement
= getSelectedPackageElement();
95 if (DataConstants
.MODULE
.equals(dataId
)) {
96 final PackageElement packageElement
= getSelectedPackageElement();
97 if (packageElement
!= null) {
98 return packageElement
.getModule();
101 return super.getData(dataId
);
105 private PackageElement
getSelectedPackageElement() {
106 PackageElement result
= null;
107 final DefaultMutableTreeNode selectedNode
= getSelectedNode();
108 if (selectedNode
!= null) {
109 Object o
= selectedNode
.getUserObject();
110 if (o
instanceof AbstractTreeNode
) {
111 Object selected
= ((AbstractTreeNode
)o
).getValue();
112 result
= selected
instanceof PackageElement ?
(PackageElement
)selected
: null;
119 public PsiDirectory
[] getSelectedDirectories() {
120 final PackageElement packageElement
= getSelectedPackageElement();
121 if (packageElement
!= null) {
122 final Module module
= packageElement
.getModule();
123 final PsiPackage aPackage
= packageElement
.getPackage();
124 if (module
!= null && aPackage
!= null) {
125 return aPackage
.getDirectories(GlobalSearchScope
.moduleScope(module
));
128 return super.getSelectedDirectories();
131 private final class ShowModulesAction
extends ToggleAction
{
132 private ShowModulesAction() {
133 super(IdeBundle
.message("action.show.modules"), IdeBundle
.message("action.description.show.modules"), IconLoader
.getIcon("/objectBrowser/showModules.png"));
136 public boolean isSelected(AnActionEvent event
) {
137 return ProjectView
.getInstance(myProject
).isShowModules(getId());
140 public void setSelected(AnActionEvent event
, boolean flag
) {
141 final ProjectViewImpl projectView
= (ProjectViewImpl
)ProjectView
.getInstance(myProject
);
142 projectView
.setShowModules(flag
, getId());
145 public void update(AnActionEvent e
) {
147 final Presentation presentation
= e
.getPresentation();
148 final ProjectViewImpl projectView
= (ProjectViewImpl
)ProjectView
.getInstance(myProject
);
149 presentation
.setVisible(projectView
.getCurrentProjectViewPane() == PackageViewPane
.this);
153 private final class ShowLibraryContentsAction
extends ToggleAction
{
154 private ShowLibraryContentsAction() {
155 super(IdeBundle
.message("action.show.libraries.contents"), IdeBundle
.message("action.show.hide.library.contents"), IconLoader
.getIcon("/objectBrowser/showLibraryContents.png"));
158 public boolean isSelected(AnActionEvent event
) {
159 return ProjectView
.getInstance(myProject
).isShowLibraryContents(getId());
162 public void setSelected(AnActionEvent event
, boolean flag
) {
163 final ProjectViewImpl projectView
= (ProjectViewImpl
)ProjectView
.getInstance(myProject
);
164 projectView
.setShowLibraryContents(flag
, getId());
167 public void update(AnActionEvent e
) {
169 final Presentation presentation
= e
.getPresentation();
170 final ProjectViewImpl projectView
= (ProjectViewImpl
)ProjectView
.getInstance(myProject
);
171 presentation
.setVisible(projectView
.getCurrentProjectViewPane() == PackageViewPane
.this);
175 public void addToolbarActions(DefaultActionGroup actionGroup
) {
176 actionGroup
.addAction(new ShowModulesAction()).setAsSecondary(true);
177 actionGroup
.addAction(new ShowLibraryContentsAction()).setAsSecondary(true);
180 protected AbstractTreeUpdater
createTreeUpdater(AbstractTreeBuilder treeBuilder
) {
181 return new PackageViewTreeUpdater(treeBuilder
);
184 public SelectInTarget
createSelectInTarget() {
185 return new PackagesPaneSelectInTarget(myProject
);
188 protected ProjectAbstractTreeStructureBase
createStructure() {
189 return new ProjectTreeStructure(myProject
, ID
){
190 protected AbstractTreeNode
createRoot(final Project project
, ViewSettings settings
) {
191 return new PackageViewProjectNode(project
, settings
);
196 protected ProjectViewTree
createTree(DefaultTreeModel treeModel
) {
197 return new ProjectViewTree(treeModel
) {
198 public String
toString() {
199 return getTitle() + " " + super.toString();
202 public DefaultMutableTreeNode
getSelectedNode() {
203 return PackageViewPane
.this.getSelectedNode();
209 public String
getComponentName() {
210 return "PackagesPane";
213 public int getWeight() {
217 private final class PackageViewTreeUpdater
extends AbstractTreeUpdater
{
218 private PackageViewTreeUpdater(final AbstractTreeBuilder treeBuilder
) {
222 public boolean addSubtreeToUpdateByElement(Object element
) {
223 // should convert PsiDirectories into PackageElements
224 if (element
instanceof PsiDirectory
) {
225 PsiDirectory dir
= (PsiDirectory
)element
;
226 final PsiPackage aPackage
= JavaDirectoryService
.getInstance().getPackage(dir
);
227 if (ProjectView
.getInstance(myProject
).isShowModules(getId())) {
228 Module
[] modules
= getModulesFor(dir
);
230 for (Module module
: modules
) {
231 rv
|= addPackageElementToUpdate(aPackage
, module
);
236 return addPackageElementToUpdate(aPackage
, null);
240 return super.addSubtreeToUpdateByElement(element
);
243 private boolean addPackageElementToUpdate(final PsiPackage aPackage
, Module module
) {
244 final ProjectTreeStructure packageTreeStructure
= (ProjectTreeStructure
)myTreeStructure
;
245 PsiPackage packageToUpdateFrom
= aPackage
;
246 if (!packageTreeStructure
.isFlattenPackages() && packageTreeStructure
.isHideEmptyMiddlePackages()) {
247 // optimization: this check makes sense only if flattenPackages == false && HideEmptyMiddle == true
248 while (packageToUpdateFrom
!= null && packageToUpdateFrom
.isValid() && PackageUtil
.isPackageEmpty(packageToUpdateFrom
, module
, true, false)) {
249 packageToUpdateFrom
= packageToUpdateFrom
.getParentPackage();
253 while (!(addedOk
= super.addSubtreeToUpdateByElement(getTreeElementToUpdateFrom(packageToUpdateFrom
, module
)))) {
254 if (packageToUpdateFrom
== null) {
257 packageToUpdateFrom
= packageToUpdateFrom
.getParentPackage();
262 private Object
getTreeElementToUpdateFrom(PsiPackage packageToUpdateFrom
, Module module
) {
263 if (packageToUpdateFrom
== null || !packageToUpdateFrom
.isValid() || "".equals(packageToUpdateFrom
.getQualifiedName())) {
264 return module
== null ? myTreeStructure
.getRootElement() : module
;
267 return new PackageElement(module
, packageToUpdateFrom
, false);
271 private Module
[] getModulesFor(PsiDirectory dir
) {
272 final ProjectFileIndex fileIndex
= ProjectRootManager
.getInstance(myProject
).getFileIndex();
273 final VirtualFile vFile
= dir
.getVirtualFile();
274 final Set
<Module
> modules
= new HashSet
<Module
>();
275 final Module module
= fileIndex
.getModuleForFile(vFile
);
276 if (module
!= null) {
279 if (fileIndex
.isInLibrarySource(vFile
) || fileIndex
.isInLibraryClasses(vFile
)) {
280 final List
<OrderEntry
> orderEntries
= fileIndex
.getOrderEntriesForFile(vFile
);
281 if (orderEntries
.isEmpty()) {
282 return Module
.EMPTY_ARRAY
;
284 for (OrderEntry entry
: orderEntries
) {
285 modules
.add(entry
.getOwnerModule());
288 return modules
.toArray(new Module
[modules
.size()]);