]>
Commit | Line | Data |
---|---|---|
1b2798f6 EK |
1 | /******************************************************************************* |
2 | * Copyright (c) 2000, 2011 IBM Corporation and others. | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | * | |
8 | * Contributors: | |
9 | * IBM Corporation - initial API and implementation | |
10 | *******************************************************************************/ | |
11 | package org.eclipse.jdt.internal.ui.actions; | |
12 | ||
13 | import java.util.ArrayList; | |
14 | import java.util.Collections; | |
15 | import java.util.HashSet; | |
16 | import java.util.Iterator; | |
17 | import java.util.LinkedHashMap; | |
18 | import java.util.List; | |
19 | import java.util.Map; | |
20 | ||
21 | import com.ibm.icu.text.Collator; | |
22 | ||
23 | import org.eclipse.swt.custom.BusyIndicator; | |
24 | import org.eclipse.swt.graphics.Image; | |
25 | import org.eclipse.swt.widgets.Composite; | |
26 | import org.eclipse.swt.widgets.Control; | |
27 | import org.eclipse.swt.widgets.Shell; | |
28 | ||
29 | import org.eclipse.core.runtime.Assert; | |
30 | ||
31 | import org.eclipse.jface.action.Action; | |
32 | import org.eclipse.jface.action.IContributionItem; | |
33 | import org.eclipse.jface.action.IMenuListener; | |
34 | import org.eclipse.jface.action.IMenuManager; | |
35 | import org.eclipse.jface.action.Separator; | |
36 | import org.eclipse.jface.preference.IPreferenceStore; | |
37 | import org.eclipse.jface.viewers.ILabelProvider; | |
38 | import org.eclipse.jface.viewers.ILabelProviderListener; | |
39 | import org.eclipse.jface.viewers.StructuredViewer; | |
40 | import org.eclipse.jface.viewers.Viewer; | |
41 | import org.eclipse.jface.viewers.ViewerFilter; | |
42 | import org.eclipse.jface.window.Window; | |
43 | ||
44 | import org.eclipse.ui.actions.ActionGroup; | |
45 | import org.eclipse.ui.dialogs.SelectionStatusDialog; | |
46 | ||
47 | import org.eclipse.jdt.core.IClassFile; | |
48 | import org.eclipse.jdt.core.ICompilationUnit; | |
49 | import org.eclipse.jdt.core.IJavaElement; | |
50 | import org.eclipse.jdt.core.IJavaModel; | |
51 | import org.eclipse.jdt.core.IJavaProject; | |
52 | import org.eclipse.jdt.core.IMember; | |
53 | import org.eclipse.jdt.core.IPackageFragment; | |
54 | import org.eclipse.jdt.core.IPackageFragmentRoot; | |
55 | import org.eclipse.jdt.core.JavaModelException; | |
56 | ||
57 | import org.eclipse.jdt.internal.ui.JavaPlugin; | |
58 | import org.eclipse.jdt.internal.ui.JavaPluginImages; | |
59 | import org.eclipse.jdt.internal.ui.text.JavaOutlineInformationControl; | |
60 | import org.eclipse.jdt.internal.ui.wizards.dialogfields.CheckedListDialogField; | |
61 | import org.eclipse.jdt.internal.ui.wizards.dialogfields.IListAdapter; | |
62 | import org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField; | |
63 | ||
64 | public class CategoryFilterActionGroup extends ActionGroup { | |
65 | ||
66 | private class CategoryFilter extends ViewerFilter { | |
67 | ||
68 | /** | |
69 | * {@inheritDoc} | |
70 | */ | |
71 | @Override | |
72 | public boolean select(Viewer viewer, Object parentElement, Object element) { | |
73 | if (element instanceof IMember) { | |
74 | IMember member= (IMember)element; | |
75 | try { | |
76 | String[] categories= member.getCategories(); | |
77 | if (categories.length == 0) | |
78 | return !fFilterUncategorizedMembers; | |
79 | ||
80 | for (int i= 0; i < categories.length; i++) { | |
81 | if (!fFilteredCategories.contains(categories[i])) | |
82 | return true; | |
83 | } | |
84 | return false; | |
85 | } catch (JavaModelException e) { | |
86 | JavaPlugin.log(e); | |
87 | } | |
88 | } | |
89 | return true; | |
90 | } | |
91 | ||
92 | } | |
93 | ||
94 | public class CategoryFilterSelectionDialog extends SelectionStatusDialog implements IListAdapter<String> { | |
95 | ||
96 | private static final int SELECT_ALL= 0; | |
97 | private static final int DESELECT_ALL= 1; | |
98 | ||
99 | public final CheckedListDialogField<String> fCategoryList; | |
100 | ||
101 | public CategoryFilterSelectionDialog(Shell parent, List<String> categories, List<String> selectedCategories) { | |
102 | super(parent); | |
103 | ||
104 | setTitle(ActionMessages.CategoryFilterActionGroup_JavaCategoryFilter_title); | |
105 | ||
106 | String[] buttons= { | |
107 | ActionMessages.CategoryFilterActionGroup_SelectAllCategories, | |
108 | ActionMessages.CategoryFilterActionGroup_DeselectAllCategories | |
109 | }; | |
110 | ||
111 | fCategoryList= new CheckedListDialogField<String>(this, buttons, new ILabelProvider() { | |
112 | public Image getImage(Object element) {return null;} | |
113 | public String getText(Object element) {return (String)element;} | |
114 | public void addListener(ILabelProviderListener listener) {} | |
115 | public void dispose() {} | |
116 | public boolean isLabelProperty(Object element, String property) {return false;} | |
117 | public void removeListener(ILabelProviderListener listener) {} | |
118 | }); | |
119 | fCategoryList.generated_4293917878755686083(categories, selectedCategories); | |
120 | } | |
121 | ||
122 | /** | |
123 | * {@inheritDoc} | |
124 | */ | |
125 | @Override | |
126 | protected Control createDialogArea(Composite parent) { | |
127 | Composite composite= (Composite) super.createDialogArea(parent); | |
128 | return fCategoryList.generated_585437789103773980(this, parent, composite); | |
129 | } | |
130 | ||
131 | /** | |
132 | * {@inheritDoc} | |
133 | */ | |
134 | @Override | |
135 | protected void computeResult() { | |
136 | setResult(fCategoryList.getCheckedElements()); | |
137 | } | |
138 | ||
139 | /** | |
140 | * {@inheritDoc} | |
141 | */ | |
142 | public void customButtonPressed(ListDialogField<String> field, int index) { | |
143 | if (index == SELECT_ALL) { | |
144 | fCategoryList.checkAll(true); | |
145 | fCategoryList.refresh(); | |
146 | } else if (index == DESELECT_ALL) { | |
147 | fCategoryList.generated_6416030852630094187(); | |
148 | } | |
149 | } | |
150 | ||
151 | public void doubleClicked(ListDialogField<String> field) { | |
152 | List<?> selectedElements= field.getSelectedElements(); | |
153 | if (selectedElements.size() == 1) { | |
154 | String selected= (String) selectedElements.get(0); | |
155 | fCategoryList.generated_2746165791554941058(selected); | |
156 | } | |
157 | } | |
158 | ||
159 | public void selectionChanged(ListDialogField<String> field) {} | |
160 | ||
161 | public void generated_6402606077000119142(final HashSet<String> categories, CategoryFilterActionGroup categoryfilteractiongroup) { | |
162 | if (open() == Window.OK) { | |
163 | Object[] selected= getResult(); | |
164 | for (Iterator<String> iter= categories.iterator(); iter.hasNext();) { | |
165 | String category= iter.next(); | |
166 | if (categoryfilteractiongroup.contains(selected, category)) { | |
167 | if (categoryfilteractiongroup.fFilteredCategories.remove(category)) | |
168 | categoryfilteractiongroup.fLRUList.put(category, category); | |
169 | } else { | |
170 | if (categoryfilteractiongroup.fFilteredCategories.add(category)) | |
171 | categoryfilteractiongroup.fLRUList.put(category, category); | |
172 | } | |
173 | } | |
174 | categoryfilteractiongroup.storeSettings(); | |
175 | categoryfilteractiongroup.fireSelectionChange(); | |
176 | } | |
177 | } | |
178 | } | |
179 | ||
180 | private class CategoryFilterMenuAction extends Action { | |
181 | ||
182 | public CategoryFilterMenuAction() { | |
183 | setDescription(ActionMessages.CategoryFilterActionGroup_ShowCategoriesActionDescription); | |
184 | setToolTipText(ActionMessages.CategoryFilterActionGroup_ShowCategoriesToolTip); | |
185 | setText(ActionMessages.CategoryFilterActionGroup_ShowCategoriesLabel); | |
186 | JavaPluginImages.setLocalImageDescriptors(this, "category_menu.gif"); //$NON-NLS-1$ | |
187 | } | |
188 | ||
189 | /** | |
190 | * {@inheritDoc} | |
191 | */ | |
192 | @Override | |
193 | public void run() { | |
194 | showCategorySelectionDialog(fInputElement); | |
195 | } | |
196 | ||
197 | } | |
198 | ||
199 | private class CategoryFilterAction extends Action { | |
200 | ||
201 | private final String fCategory; | |
202 | ||
203 | public CategoryFilterAction(String category, int count) { | |
204 | fCategory= category; | |
205 | StringBuffer buf = new StringBuffer(); | |
206 | buf.append('&').append(count).append(' ').append(fCategory); | |
207 | setText(buf.toString()); | |
208 | setChecked(!fFilteredCategories.contains(fCategory)); | |
209 | setId(FILTER_CATEGORY_ACTION_ID); | |
210 | } | |
211 | ||
212 | /** | |
213 | * {@inheritDoc} | |
214 | */ | |
215 | @Override | |
216 | public void run() { | |
217 | super.run(); | |
218 | if (fFilteredCategories.contains(fCategory)) { | |
219 | fFilteredCategories.remove(fCategory); | |
220 | } else { | |
221 | fFilteredCategories.add(fCategory); | |
222 | } | |
223 | fLRUList.put(fCategory, fCategory); | |
224 | storeSettings(); | |
225 | fireSelectionChange(); | |
226 | } | |
227 | ||
228 | } | |
229 | ||
230 | private class FilterUncategorizedMembersAction extends Action { | |
231 | ||
232 | public FilterUncategorizedMembersAction() { | |
233 | setText(ActionMessages.CategoryFilterActionGroup_ShowUncategorizedMembers); | |
234 | setChecked(!fFilterUncategorizedMembers); | |
235 | setId(FILTER_CATEGORY_ACTION_ID); | |
236 | } | |
237 | ||
238 | /** | |
239 | * {@inheritDoc} | |
240 | */ | |
241 | @Override | |
242 | public void run() { | |
243 | fFilterUncategorizedMembers= !fFilterUncategorizedMembers; | |
244 | storeSettings(); | |
245 | fireSelectionChange(); | |
246 | } | |
247 | } | |
248 | ||
249 | private interface IResultCollector { | |
250 | public boolean accept(String[] category); | |
251 | } | |
252 | ||
253 | private static int COUNTER= 0;//WORKAROUND for Bug 132669 https://bugs.eclipse.org/bugs/show_bug.cgi?id=132669 | |
254 | ||
255 | private static final String FILTER_CATEGORY_ACTION_ID= "FilterCategoryActionId"; //$NON-NLS-1$ | |
256 | private final String CATEGORY_MENU_GROUP_NAME= "CategoryMenuGroup" + (COUNTER++); //$NON-NLS-1$ | |
257 | private static final int MAX_NUMBER_OF_CATEGORIES_IN_MENU= 5; | |
258 | ||
259 | private final StructuredViewer fViewer; | |
260 | private final String fViewerId; | |
261 | private final CategoryFilter fFilter; | |
262 | private final HashSet<String> fFilteredCategories; | |
263 | private IJavaElement[] fInputElement; | |
264 | private final CategoryFilterMenuAction fMenuAction; | |
265 | private IMenuManager fMenuManager; | |
266 | private IMenuListener fMenuListener; | |
267 | private final LinkedHashMap<String, String> fLRUList; | |
268 | private boolean fFilterUncategorizedMembers; | |
269 | ||
270 | public CategoryFilterActionGroup(final StructuredViewer viewer, final String viewerId, IJavaElement[] input) { | |
271 | Assert.isLegal(viewer != null); | |
272 | Assert.isLegal(viewerId != null); | |
273 | Assert.isLegal(input != null); | |
274 | ||
275 | fLRUList= new LinkedHashMap<String, String>(MAX_NUMBER_OF_CATEGORIES_IN_MENU * 2, 0.75f, true) { | |
276 | private static final long serialVersionUID= 1L; | |
277 | @Override | |
278 | protected boolean removeEldestEntry(Map.Entry<String, String> eldest) { | |
279 | return size() > MAX_NUMBER_OF_CATEGORIES_IN_MENU; | |
280 | } | |
281 | }; | |
282 | fViewer= viewer; | |
283 | fViewerId= viewerId; | |
284 | fInputElement= input; | |
285 | ||
286 | fFilter= new CategoryFilter(); | |
287 | ||
288 | fFilteredCategories= new HashSet<String>(); | |
289 | loadSettings(); | |
290 | ||
291 | fMenuAction= new CategoryFilterMenuAction(); | |
292 | ||
293 | fViewer.addFilter(fFilter); | |
294 | } | |
295 | ||
296 | public void setInput(IJavaElement[] input) { | |
297 | Assert.isLegal(input != null); | |
298 | fInputElement= input; | |
299 | } | |
300 | ||
301 | private void loadSettings() { | |
302 | fFilteredCategories.clear(); | |
303 | IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore(); | |
304 | String string= store.getString(getPreferenceKey()); | |
305 | if (string != null && string.length() > 0) { | |
306 | String[] categories= string.split(";"); //$NON-NLS-1$ | |
307 | for (int i= 0; i < categories.length; i++) { | |
308 | fFilteredCategories.add(categories[i]); | |
309 | } | |
310 | } | |
311 | string= store.getString(getPreferenceKey()+".LRU"); //$NON-NLS-1$ | |
312 | if (string != null && string.length() > 0) { | |
313 | String[] categories= string.split(";"); //$NON-NLS-1$ | |
314 | for (int i= categories.length - 1; i >= 0; i--) { | |
315 | fLRUList.put(categories[i], categories[i]); | |
316 | } | |
317 | } | |
318 | fFilterUncategorizedMembers= store.getBoolean(getPreferenceKey()+".FilterUncategorized"); //$NON-NLS-1$ | |
319 | } | |
320 | ||
321 | private void storeSettings() { | |
322 | IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore(); | |
323 | if (fFilteredCategories.size() == 0) { | |
324 | store.setValue(getPreferenceKey(), ""); //$NON-NLS-1$ | |
325 | } else { | |
326 | StringBuffer buf= new StringBuffer(); | |
327 | Iterator<String> iter= fFilteredCategories.iterator(); | |
328 | String element= iter.next(); | |
329 | buf.append(element); | |
330 | while (iter.hasNext()) { | |
331 | element= iter.next(); | |
332 | buf.append(';'); | |
333 | buf.append(element); | |
334 | } | |
335 | store.setValue(getPreferenceKey(), buf.toString()); | |
336 | buf= new StringBuffer(); | |
337 | iter= fLRUList.values().iterator(); | |
338 | element= iter.next(); | |
339 | buf.append(element); | |
340 | while (iter.hasNext()) { | |
341 | element= iter.next(); | |
342 | buf.append(';'); | |
343 | buf.append(element); | |
344 | } | |
345 | store.setValue(getPreferenceKey()+".LRU", buf.toString()); //$NON-NLS-1$ | |
346 | store.setValue(getPreferenceKey()+".FilterUncategorized", fFilterUncategorizedMembers); //$NON-NLS-1$ | |
347 | } | |
348 | } | |
349 | ||
350 | public void contributeToViewMenu(IMenuManager menuManager) { | |
351 | menuManager.add(new Separator(CATEGORY_MENU_GROUP_NAME)); | |
352 | menuManager.appendToGroup(CATEGORY_MENU_GROUP_NAME, fMenuAction); | |
353 | fMenuListener= new IMenuListener() { | |
354 | public void menuAboutToShow(IMenuManager manager) { | |
355 | if (!manager.isVisible()) | |
356 | return; | |
357 | updateMenu(manager); | |
358 | } | |
359 | }; | |
360 | menuManager.addMenuListener(fMenuListener); | |
361 | fMenuManager= menuManager; | |
362 | } | |
363 | ||
364 | /** | |
365 | * {@inheritDoc} | |
366 | */ | |
367 | @Override | |
368 | public void dispose() { | |
369 | super.dispose(); | |
370 | if (fMenuManager != null) { | |
371 | fMenuManager.removeMenuListener(fMenuListener); | |
372 | fMenuManager= null; | |
373 | fMenuListener= null; | |
374 | } | |
375 | } | |
376 | ||
377 | private void updateMenu(IMenuManager manager) { | |
378 | IContributionItem[] items= manager.getItems(); | |
379 | if (items != null) { | |
380 | for (int i= 0; i < items.length; i++) { | |
381 | IContributionItem item= items[i]; | |
382 | if (item != null && item.getId() != null && item.getId().equals(FILTER_CATEGORY_ACTION_ID)) { | |
383 | IContributionItem removed= manager.remove(item); | |
384 | if (removed != null) { | |
385 | item.dispose(); | |
386 | } | |
387 | } | |
388 | } | |
389 | } | |
390 | List<String> menuEntries= new ArrayList<String>(); | |
391 | boolean hasUncategorizedMembers= getMenuCategories(menuEntries); | |
392 | Collections.sort(menuEntries, Collator.getInstance()); | |
393 | ||
394 | if (menuEntries.size() > 0 && hasUncategorizedMembers) | |
395 | manager.appendToGroup(CATEGORY_MENU_GROUP_NAME, new FilterUncategorizedMembersAction()); | |
396 | ||
397 | int count= 0; | |
398 | for (Iterator<String> iter= menuEntries.iterator(); iter.hasNext();) { | |
399 | String category= iter.next(); | |
400 | manager.appendToGroup(CATEGORY_MENU_GROUP_NAME, new CategoryFilterAction(category, count + 1)); | |
401 | count++; | |
402 | } | |
403 | } | |
404 | ||
405 | private boolean getMenuCategories(List<String> result) { | |
406 | final HashSet<String> categories= new HashSet<String>(); | |
407 | final HashSet<String> foundLRUCategories= new HashSet<String>(); | |
408 | final boolean hasUncategorizedMember[]= new boolean[] {false}; | |
409 | for (int i= 0; i < fInputElement.length && !(hasUncategorizedMember[0] && foundLRUCategories.size() >= MAX_NUMBER_OF_CATEGORIES_IN_MENU); i++) { | |
410 | collectCategories(fInputElement[i], new IResultCollector() { | |
411 | public boolean accept(String[] cats) { | |
412 | if (cats.length > 0) { | |
413 | for (int j= 0; j < cats.length; j++) { | |
414 | String category= cats[j]; | |
415 | categories.add(category); | |
416 | if (fLRUList.containsKey(category)) { | |
417 | foundLRUCategories.add(category); | |
418 | } | |
419 | } | |
420 | } else { | |
421 | hasUncategorizedMember[0]= true; | |
422 | } | |
423 | return hasUncategorizedMember[0] && foundLRUCategories.size() >= MAX_NUMBER_OF_CATEGORIES_IN_MENU; | |
424 | } | |
425 | }); | |
426 | } | |
427 | int count= 0; | |
428 | for (Iterator<String> iter= foundLRUCategories.iterator(); iter.hasNext();) { | |
429 | String element= iter.next(); | |
430 | result.add(element); | |
431 | count++; | |
432 | } | |
433 | if (count < MAX_NUMBER_OF_CATEGORIES_IN_MENU) { | |
434 | List<String> sortedCategories= new ArrayList<String>(categories); | |
435 | Collections.sort(sortedCategories, Collator.getInstance()); | |
436 | for (Iterator<String> iter= sortedCategories.iterator(); iter.hasNext() && count < MAX_NUMBER_OF_CATEGORIES_IN_MENU;) { | |
437 | String element= iter.next(); | |
438 | if (!foundLRUCategories.contains(element)) { | |
439 | result.add(element); | |
440 | count++; | |
441 | } | |
442 | } | |
443 | } | |
444 | return hasUncategorizedMember[0]; | |
445 | } | |
446 | ||
447 | private boolean collectCategories(IJavaElement element, IResultCollector collector) {//HashSet result, int max, LinkedHashMap lruList) { | |
448 | try { | |
449 | if (element instanceof IMember) { | |
450 | IMember member= (IMember)element; | |
451 | collector.accept(member.getCategories()); | |
452 | return processChildren(member.getChildren(), collector); | |
453 | } else if (element instanceof ICompilationUnit) { | |
454 | return processChildren(((ICompilationUnit)element).getChildren(), collector); | |
455 | } else if (element instanceof IClassFile) { | |
456 | return processChildren(((IClassFile)element).getChildren(), collector); | |
457 | } else if (element instanceof IJavaModel) { | |
458 | return processChildren(((IJavaModel)element).getChildren(), collector); | |
459 | } else if (element instanceof IJavaProject) { | |
460 | return processChildren(((IJavaProject)element).getChildren(), collector); | |
461 | } else if (element instanceof IPackageFragment) { | |
462 | return processChildren(((IPackageFragment)element).getChildren(), collector); | |
463 | } else if (element instanceof IPackageFragmentRoot) { | |
464 | return processChildren(((IPackageFragmentRoot)element).getChildren(), collector); | |
465 | } | |
466 | return false; | |
467 | } catch (JavaModelException e) { | |
468 | JavaPlugin.log(e); | |
469 | return true; | |
470 | } | |
471 | } | |
472 | ||
473 | private boolean processChildren(IJavaElement[] children, IResultCollector collector) { | |
474 | for (int i= 0; i < children.length; i++) { | |
475 | if (collectCategories(children[i], collector)) | |
476 | return true; | |
477 | } | |
478 | return false; | |
479 | } | |
480 | ||
481 | private void fireSelectionChange() { | |
482 | fViewer.getControl().setRedraw(false); | |
483 | BusyIndicator.showWhile(fViewer.getControl().getDisplay(), new Runnable() { | |
484 | public void run() { | |
485 | fViewer.refresh(); | |
486 | } | |
487 | }); | |
488 | fViewer.getControl().setRedraw(true); | |
489 | } | |
490 | ||
491 | private String getPreferenceKey() { | |
492 | return "CategoryFilterActionGroup." + fViewerId; //$NON-NLS-1$ | |
493 | } | |
494 | ||
495 | private void showCategorySelectionDialog(IJavaElement[] input) { | |
496 | final HashSet<String> categories= new HashSet<String>(); | |
497 | for (int i= 0; i < input.length; i++) { | |
498 | collectCategories(input[i], new IResultCollector() { | |
499 | public boolean accept(String[] cats) { | |
500 | for (int j= 0; j < cats.length; j++) { | |
501 | categories.add(cats[j]); | |
502 | } | |
503 | return false; | |
504 | } | |
505 | }); | |
506 | } | |
507 | CategoryFilterSelectionDialog dialog= new CategoryFilterSelectionDialog(fViewer.getControl().getShell(), new ArrayList<String>(categories), new ArrayList<String>(fFilteredCategories)); | |
508 | dialog.generated_6402606077000119142(categories, this); | |
509 | } | |
510 | ||
511 | private boolean contains(Object[] selected, String category) { | |
512 | for (int i= 0; i < selected.length; i++) { | |
513 | if (selected[i].equals(category)) | |
514 | return true; | |
515 | } | |
516 | return false; | |
517 | } | |
518 | ||
519 | public void generated_5832668516256418237(JavaOutlineInformationControl javaoutlineinformationcontrol, IMenuManager viewMenu) { | |
520 | viewMenu.add(javaoutlineinformationcontrol.fShowOnlyMainTypeAction); | |
521 | ||
522 | viewMenu.add(new Separator("Sorters")); //$NON-NLS-1$ | |
523 | viewMenu.add(javaoutlineinformationcontrol.fLexicalSortingAction); | |
524 | ||
525 | viewMenu.add(javaoutlineinformationcontrol.fSortByDefiningTypeAction); | |
526 | ||
527 | setInput(javaoutlineinformationcontrol.getInputForCategories()); | |
528 | contributeToViewMenu(viewMenu); | |
529 | } | |
530 | ||
531 | } |