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.
16 package com.intellij.ide.util.scopeChooser;
18 import com.intellij.ide.DataManager;
19 import com.intellij.ide.IdeBundle;
20 import com.intellij.ide.favoritesTreeView.FavoritesManager;
21 import com.intellij.ide.ui.ListCellRendererWrapper;
22 import com.intellij.openapi.Disposable;
23 import com.intellij.openapi.actionSystem.DataContext;
24 import com.intellij.openapi.actionSystem.LangDataKeys;
25 import com.intellij.openapi.actionSystem.PlatformDataKeys;
26 import com.intellij.openapi.editor.Editor;
27 import com.intellij.openapi.extensions.Extensions;
28 import com.intellij.openapi.fileEditor.FileEditorManager;
29 import com.intellij.openapi.module.Module;
30 import com.intellij.openapi.module.ModuleUtil;
31 import com.intellij.openapi.project.Project;
32 import com.intellij.openapi.vfs.VirtualFile;
33 import com.intellij.packageDependencies.ChangeListsScopesProvider;
34 import com.intellij.packageDependencies.DependencyValidationManager;
35 import com.intellij.psi.PsiDocumentManager;
36 import com.intellij.psi.PsiElement;
37 import com.intellij.psi.PsiFile;
38 import com.intellij.psi.PsiWhiteSpace;
39 import com.intellij.psi.search.*;
40 import com.intellij.psi.search.scope.packageSet.NamedScope;
41 import com.intellij.psi.search.scope.packageSet.NamedScopeManager;
42 import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
43 import com.intellij.psi.util.PsiTreeUtil;
44 import com.intellij.psi.util.PsiUtilBase;
45 import com.intellij.psi.util.PsiUtilCore;
46 import com.intellij.ui.ComboboxWithBrowseButton;
47 import com.intellij.usages.Usage;
48 import com.intellij.usages.UsageView;
49 import com.intellij.usages.UsageViewManager;
50 import com.intellij.usages.rules.PsiElementUsage;
51 import com.intellij.util.ArrayUtil;
52 import com.intellij.util.PlatformUtils;
53 import org.jetbrains.annotations.NotNull;
54 import org.jetbrains.annotations.Nullable;
57 import java.awt.event.ActionEvent;
58 import java.awt.event.ActionListener;
61 public class ScopeChooserCombo extends ComboboxWithBrowseButton implements Disposable {
62 private Project myProject;
63 private boolean mySuggestSearchInLibs;
64 private boolean myPrevSearchFiles;
66 private NamedScopesHolder.ScopeListener myScopeListener;
67 private NamedScopeManager myNamedScopeManager;
68 private DependencyValidationManager myValidationManager;
70 public ScopeChooserCombo() {
73 public ScopeChooserCombo(final Project project, boolean suggestSearchInLibs, boolean prevSearchWholeFiles, String preselect) {
74 init(project, suggestSearchInLibs, prevSearchWholeFiles, preselect);
77 public void init(final Project project, final String preselect){
78 init(project, false, true, preselect);
81 public void init(final Project project, final boolean suggestSearchInLibs, final boolean prevSearchWholeFiles, final String preselect) {
82 mySuggestSearchInLibs = suggestSearchInLibs;
83 myPrevSearchFiles = prevSearchWholeFiles;
84 final JComboBox combo = getComboBox();
86 myScopeListener = new NamedScopesHolder.ScopeListener() {
87 public void scopesChanged() {
88 final SearchScope selectedScope = getSelectedScope();
90 if (selectedScope != null) {
91 selectScope(selectedScope.getDisplayName());
95 myNamedScopeManager = NamedScopeManager.getInstance(project);
96 myNamedScopeManager.addScopeListener(myScopeListener);
97 myValidationManager = DependencyValidationManager.getInstance(project);
98 myValidationManager.addScopeListener(myScopeListener);
99 addActionListener(createScopeChooserListener());
101 combo.setRenderer(new ListCellRendererWrapper<ScopeDescriptor>(combo.getRenderer()) {
103 public void customize(final JList list, final ScopeDescriptor value, final int index, final boolean selected, final boolean hasFocus) {
104 if (value != null) setText(value.getDisplay());
110 selectScope(preselect);
114 public void dispose() {
116 if (myValidationManager != null) {
117 myValidationManager.removeScopeListener(myScopeListener);
118 myValidationManager = null;
120 if (myNamedScopeManager != null) {
121 myNamedScopeManager.removeScopeListener(myScopeListener);
122 myNamedScopeManager = null;
124 myScopeListener = null;
127 private void selectScope(String preselect) {
128 if (preselect != null) {
129 final JComboBox combo = getComboBox();
130 DefaultComboBoxModel model = (DefaultComboBoxModel)combo.getModel();
131 for (int i = 0; i < model.getSize(); i++) {
132 ScopeDescriptor descriptor = (ScopeDescriptor)model.getElementAt(i);
133 if (preselect.equals(descriptor.getDisplay())) {
134 combo.setSelectedIndex(i);
141 private ActionListener createScopeChooserListener() {
142 return new ActionListener() {
143 public void actionPerformed(ActionEvent e) {
144 final String selection = getSelectedScopeName();
145 final EditScopesDialog dlg = EditScopesDialog.showDialog(myProject, selection);
148 final NamedScope namedScope = dlg.getSelectedScope();
149 if (namedScope != null) {
150 selectScope(namedScope.getName());
157 private void rebuildModel() {
158 getComboBox().setModel(createModel());
161 private DefaultComboBoxModel createModel() {
162 DefaultComboBoxModel model = new DefaultComboBoxModel();
163 createPredefinedScopeDescriptors(model);
165 List<NamedScope> changeLists = ChangeListsScopesProvider.getInstance(myProject).getCustomScopes();
166 for (NamedScope changeListScope : changeLists) {
167 model.addElement(new ScopeDescriptor(GlobalSearchScopes.filterScope(myProject, changeListScope)));
169 final NamedScopesHolder[] holders = NamedScopesHolder.getAllNamedScopeHolders(myProject);
170 for (NamedScopesHolder holder : holders) {
171 NamedScope[] scopes = holder.getEditableScopes(); //predefined scopes already included
172 for (NamedScope scope : scopes) {
173 model.addElement(new ScopeDescriptor(GlobalSearchScopes.filterScope(myProject, scope)));
181 private void createPredefinedScopeDescriptors(DefaultComboBoxModel model) {
182 for (SearchScope scope : getPredefinedScopes(myProject, DataManager.getInstance().getDataContext(), mySuggestSearchInLibs, myPrevSearchFiles, true, true)) {
183 model.addElement(new ScopeDescriptor(scope));
185 for (ScopeDescriptorProvider provider : Extensions.getExtensions(ScopeDescriptorProvider.EP_NAME)) {
186 for (ScopeDescriptor scopeDescriptor : provider.getScopeDescriptors(myProject)) {
187 model.addElement(scopeDescriptor);
192 public static List<SearchScope> getPredefinedScopes(@NotNull final Project project,
193 @Nullable final DataContext dataContext,
194 boolean suggestSearchInLibs,
195 boolean prevSearchFiles,
196 boolean currentSelection,
198 ArrayList<SearchScope> result = new ArrayList<SearchScope>();
199 result.add(GlobalSearchScope.projectScope(project));
200 if (suggestSearchInLibs) {
201 result.add(GlobalSearchScope.allScope(project));
204 if (!PlatformUtils.isCidr()) { // TODO: fix these scopes in AppCode
205 result.add(GlobalSearchScopes.projectProductionScope(project));
206 result.add(GlobalSearchScopes.projectTestScope(project));
209 if (dataContext != null) {
210 PsiElement dataContextElement = getDataContextElement(dataContext);
212 if (dataContextElement != null) {
213 if (!PlatformUtils.isCidr()) { // TODO: have an API to disable module scopes.
214 Module module = ModuleUtil.findModuleForPsiElement(dataContextElement);
215 if (module == null) {
216 module = LangDataKeys.MODULE.getData(dataContext);
218 if (module != null) {
219 result.add(module.getModuleScope());
222 if (dataContextElement.getContainingFile() != null) {
223 result.add(new LocalSearchScope(dataContextElement, IdeBundle.message("scope.current.file")));
228 if (currentSelection) {
229 FileEditorManager fileEditorManager = FileEditorManager.getInstance(project);
230 final Editor selectedTextEditor = fileEditorManager.getSelectedTextEditor();
231 if (selectedTextEditor != null) {
232 final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(selectedTextEditor.getDocument());
233 if (psiFile != null) {
234 if (selectedTextEditor.getSelectionModel().hasSelection()) {
235 final PsiElement startElement = psiFile.findElementAt(selectedTextEditor.getSelectionModel().getSelectionStart());
236 if (startElement != null) {
237 final PsiElement endElement = psiFile.findElementAt(selectedTextEditor.getSelectionModel().getSelectionEnd());
238 if (endElement != null) {
239 final PsiElement parent = PsiTreeUtil.findCommonParent(startElement, endElement);
240 if (parent != null) {
241 final List<PsiElement> elements = new ArrayList<PsiElement>();
242 final PsiElement[] children = parent.getChildren();
243 for (PsiElement child : children) {
244 if (!(child instanceof PsiWhiteSpace) && child.getContainingFile() != null) {
248 if (!elements.isEmpty()) {
249 SearchScope local = new LocalSearchScope(PsiUtilCore.toPsiElementArray(elements), IdeBundle.message("scope.selection"));
261 UsageView selectedUsageView = UsageViewManager.getInstance(project).getSelectedUsageView();
262 if (selectedUsageView != null && !selectedUsageView.isSearchInProgress()) {
263 final Set<Usage> usages = selectedUsageView.getUsages();
264 final List<PsiElement> results = new ArrayList<PsiElement>(usages.size());
266 if (prevSearchFiles) {
267 final Set<VirtualFile> files = new HashSet<VirtualFile>();
268 for (Usage usage : usages) {
269 if (usage instanceof PsiElementUsage) {
270 PsiElement psiElement = ((PsiElementUsage)usage).getElement();
271 if (psiElement != null && psiElement.isValid()) {
272 PsiFile psiFile = psiElement.getContainingFile();
273 if (psiFile != null) {
274 VirtualFile file = psiFile.getVirtualFile();
275 if (file != null) files.add(file);
280 if (!files.isEmpty()) {
281 GlobalSearchScope prev = new GlobalSearchScope(project) {
282 public String getDisplayName() {
283 return IdeBundle.message("scope.files.in.previous.search.result");
286 public boolean contains(VirtualFile file) {
287 return files.contains(file);
290 public int compare(VirtualFile file1, VirtualFile file2) {
294 public boolean isSearchInModuleContent(@NotNull Module aModule) {
298 public boolean isSearchInLibraries() {
306 for (Usage usage : usages) {
307 if (usage instanceof PsiElementUsage) {
308 final PsiElement element = ((PsiElementUsage)usage).getElement();
309 if (element != null && element.isValid() && element.getContainingFile() != null) {
310 results.add(element);
315 if (!results.isEmpty()) {
316 result.add(new LocalSearchScope(PsiUtilBase.toPsiElementArray(results), IdeBundle.message("scope.previous.search.results")));
322 final FavoritesManager favoritesManager = FavoritesManager.getInstance(project);
323 String[] favoritesLists = favoritesManager == null ? ArrayUtil.EMPTY_STRING_ARRAY : favoritesManager.getAvailableFavoritesLists();
324 for (final String favorite : favoritesLists) {
325 result.add(new GlobalSearchScope(project) {
327 public String getDisplayName() {
328 return "Favorite \'" + favorite + "\'";
332 public boolean contains(final VirtualFile file) {
333 return favoritesManager.contains(favorite, file);
337 public int compare(final VirtualFile file1, final VirtualFile file2) {
342 public boolean isSearchInModuleContent(@NotNull final Module aModule) {
347 public boolean isSearchInLibraries() {
353 if (dataContext != null) {
354 final VirtualFile[] files = PlatformDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext);
356 final List<VirtualFile> openFiles = Arrays.asList(files);
357 result.add(new DelegatingGlobalSearchScope(GlobalSearchScope.filesScope(project, openFiles)){
359 public String getDisplayName() {
360 return "Selected files";
369 public static PsiElement getDataContextElement(DataContext dataContext) {
370 PsiElement dataContextElement = LangDataKeys.PSI_FILE.getData(dataContext);
372 if (dataContextElement == null) {
373 dataContextElement = LangDataKeys.PSI_ELEMENT.getData(dataContext);
375 return dataContextElement;
380 public SearchScope getSelectedScope() {
381 JComboBox combo = getComboBox();
382 int idx = combo.getSelectedIndex();
383 if (idx < 0) return null;
384 return ((ScopeDescriptor)combo.getSelectedItem()).getScope();
388 public String getSelectedScopeName() {
389 JComboBox combo = getComboBox();
390 int idx = combo.getSelectedIndex();
391 if (idx < 0) return null;
392 return ((ScopeDescriptor)combo.getSelectedItem()).getDisplay();