| /******************************************************************************* |
| * Copyright (c) 2000, 2006 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.ui.actions; |
| |
| import com.ibm.icu.text.Collator; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.BusyIndicator; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Shell; |
| |
| import org.eclipse.jface.action.Action; |
| import org.eclipse.jface.action.IContributionItem; |
| import org.eclipse.jface.action.IMenuListener; |
| import org.eclipse.jface.action.IMenuManager; |
| import org.eclipse.jface.action.Separator; |
| import org.eclipse.jface.dialogs.Dialog; |
| import org.eclipse.jface.preference.IPreferenceStore; |
| import org.eclipse.jface.viewers.ILabelProvider; |
| import org.eclipse.jface.viewers.ILabelProviderListener; |
| import org.eclipse.jface.viewers.StructuredViewer; |
| import org.eclipse.jface.viewers.Viewer; |
| import org.eclipse.jface.viewers.ViewerFilter; |
| import org.eclipse.jface.viewers.ViewerSorter; |
| import org.eclipse.jface.window.Window; |
| |
| import org.eclipse.jface.text.Assert; |
| |
| import org.eclipse.ui.actions.ActionGroup; |
| import org.eclipse.ui.dialogs.SelectionStatusDialog; |
| |
| import org.eclipse.jdt.core.IClassFile; |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IJavaModel; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IMember; |
| import org.eclipse.jdt.core.IPackageFragment; |
| import org.eclipse.jdt.core.IPackageFragmentRoot; |
| import org.eclipse.jdt.core.JavaModelException; |
| |
| import org.eclipse.jdt.internal.ui.JavaPlugin; |
| import org.eclipse.jdt.internal.ui.JavaPluginImages; |
| import org.eclipse.jdt.internal.ui.wizards.dialogfields.CheckedListDialogField; |
| import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField; |
| import org.eclipse.jdt.internal.ui.wizards.dialogfields.IListAdapter; |
| import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil; |
| import org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField; |
| |
| public class CategoryFilterActionGroup extends ActionGroup { |
| |
| private class CategoryFilter extends ViewerFilter { |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public boolean select(Viewer viewer, Object parentElement, Object element) { |
| if (element instanceof IMember) { |
| IMember member= (IMember)element; |
| try { |
| String[] categories= member.getCategories(); |
| if (categories.length == 0) |
| return !fFilterUncategorizedMembers; |
| |
| for (int i= 0; i < categories.length; i++) { |
| if (!fFilteredCategories.contains(categories[i])) |
| return true; |
| } |
| return false; |
| } catch (JavaModelException e) { |
| JavaPlugin.log(e); |
| } |
| } |
| return true; |
| } |
| |
| } |
| |
| private class CategoryFilterSelectionDialog extends SelectionStatusDialog implements IListAdapter { |
| |
| private static final int SELECT_ALL= 0; |
| private static final int DESELECT_ALL= 1; |
| |
| private final CheckedListDialogField fCategoryList; |
| |
| public CategoryFilterSelectionDialog(Shell parent, List categories, List selectedCategories) { |
| super(parent); |
| |
| setTitle(ActionMessages.CategoryFilterActionGroup_JavaCategoryFilter_title); |
| |
| String[] buttons= { |
| ActionMessages.CategoryFilterActionGroup_SelectAllCategories, |
| ActionMessages.CategoryFilterActionGroup_DeselectAllCategories |
| }; |
| |
| fCategoryList= new CheckedListDialogField(this, buttons, new ILabelProvider() { |
| public Image getImage(Object element) {return null;} |
| public String getText(Object element) {return (String)element;} |
| public void addListener(ILabelProviderListener listener) {} |
| public void dispose() {} |
| public boolean isLabelProperty(Object element, String property) {return false;} |
| public void removeListener(ILabelProviderListener listener) {} |
| }); |
| fCategoryList.addElements(categories); |
| fCategoryList.setViewerSorter(new ViewerSorter()); |
| fCategoryList.setLabelText(ActionMessages.CategoryFilterActionGroup_SelectCategoriesDescription); |
| fCategoryList.checkAll(true); |
| for (Iterator iter= selectedCategories.iterator(); iter.hasNext();) { |
| String selected= (String)iter.next(); |
| fCategoryList.setChecked(selected, false); |
| } |
| if (categories.size() == 0) { |
| fCategoryList.setEnabled(false); |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| protected Control createDialogArea(Composite parent) { |
| Composite composite= new Composite(parent, SWT.NONE); |
| composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); |
| composite.setLayout(new GridLayout(1, true)); |
| composite.setFont(parent.getFont()); |
| |
| Composite list= new Composite(composite, SWT.NONE); |
| list.setFont(composite.getFont()); |
| LayoutUtil.doDefaultLayout(list, new DialogField[] { fCategoryList }, true); |
| LayoutUtil.setHorizontalGrabbing(fCategoryList.getListControl(null)); |
| Dialog.applyDialogFont(composite); |
| |
| setHelpAvailable(false); |
| |
| return composite; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| protected void computeResult() { |
| setResult(fCategoryList.getCheckedElements()); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void customButtonPressed(ListDialogField field, int index) { |
| if (index == SELECT_ALL) { |
| fCategoryList.checkAll(true); |
| fCategoryList.refresh(); |
| } else if (index == DESELECT_ALL) { |
| fCategoryList.checkAll(false); |
| fCategoryList.refresh(); |
| } |
| } |
| |
| public void doubleClicked(ListDialogField field) { |
| List selectedElements= field.getSelectedElements(); |
| if (selectedElements.size() == 1) { |
| Object selected= selectedElements.get(0); |
| fCategoryList.setChecked(selected, !fCategoryList.isChecked(selected)); |
| } |
| } |
| public void selectionChanged(ListDialogField field) {} |
| } |
| |
| private class CategoryFilterMenuAction extends Action { |
| |
| public CategoryFilterMenuAction() { |
| setDescription(ActionMessages.CategoryFilterActionGroup_ShowCategoriesActionDescription); |
| setToolTipText(ActionMessages.CategoryFilterActionGroup_ShowCategoriesToolTip); |
| setText(ActionMessages.CategoryFilterActionGroup_ShowCategoriesLabel); |
| JavaPluginImages.setLocalImageDescriptors(this, "category_menu.gif"); //$NON-NLS-1$ |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void run() { |
| showCategorySelectionDialog(fInputElement); |
| } |
| |
| } |
| |
| private class CategoryFilterAction extends Action { |
| |
| private final String fCategory; |
| |
| public CategoryFilterAction(String category, int count) { |
| fCategory= category; |
| StringBuffer buf = new StringBuffer(); |
| buf.append('&').append(count).append(' ').append(fCategory); |
| setText(buf.toString()); |
| setChecked(!fFilteredCategories.contains(fCategory)); |
| setId(FILTER_CATEGORY_ACTION_ID); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void run() { |
| super.run(); |
| if (fFilteredCategories.contains(fCategory)) { |
| fFilteredCategories.remove(fCategory); |
| } else { |
| fFilteredCategories.add(fCategory); |
| } |
| fLRUList.put(fCategory, fCategory); |
| storeSettings(); |
| fireSelectionChange(); |
| } |
| |
| } |
| |
| private class FilterUncategorizedMembersAction extends Action { |
| |
| public FilterUncategorizedMembersAction() { |
| setText(ActionMessages.CategoryFilterActionGroup_ShowUncategorizedMembers); |
| setChecked(!fFilterUncategorizedMembers); |
| setId(FILTER_CATEGORY_ACTION_ID); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void run() { |
| fFilterUncategorizedMembers= !fFilterUncategorizedMembers; |
| storeSettings(); |
| fireSelectionChange(); |
| } |
| } |
| |
| private interface IResultCollector { |
| public boolean accept(String[] category); |
| } |
| |
| private static int COUNTER= 0;//WORKAROUND for Bug 132669 https://bugs.eclipse.org/bugs/show_bug.cgi?id=132669 |
| |
| private static final String FILTER_CATEGORY_ACTION_ID= "FilterCategoryActionId"; //$NON-NLS-1$ |
| private final String CATEGORY_MENU_GROUP_NAME= "CategoryMenuGroup" + (COUNTER++); //$NON-NLS-1$ |
| private static final int MAX_NUMBER_OF_CATEGORIES_IN_MENU= 5; |
| |
| private final StructuredViewer fViewer; |
| private final String fViewerId; |
| private final CategoryFilter fFilter; |
| private final HashSet fFilteredCategories; |
| private IJavaElement[] fInputElement; |
| private final CategoryFilterMenuAction fMenuAction; |
| private IMenuManager fMenuManager; |
| private IMenuListener fMenuListener; |
| private final LinkedHashMap fLRUList; |
| private boolean fFilterUncategorizedMembers; |
| |
| public CategoryFilterActionGroup(final StructuredViewer viewer, final String viewerId, IJavaElement[] input) { |
| Assert.isLegal(viewer != null); |
| Assert.isLegal(viewerId != null); |
| Assert.isLegal(input != null); |
| |
| fLRUList= new LinkedHashMap(MAX_NUMBER_OF_CATEGORIES_IN_MENU * 2, 0.75f, true) { |
| private static final long serialVersionUID= 1L; |
| protected boolean removeEldestEntry(Map.Entry eldest) { |
| return size() > MAX_NUMBER_OF_CATEGORIES_IN_MENU; |
| } |
| }; |
| fViewer= viewer; |
| fViewerId= viewerId; |
| fInputElement= input; |
| |
| fFilter= new CategoryFilter(); |
| |
| fFilteredCategories= new HashSet(); |
| loadSettings(); |
| |
| fMenuAction= new CategoryFilterMenuAction(); |
| |
| fViewer.addFilter(fFilter); |
| } |
| |
| public void setInput(IJavaElement[] input) { |
| Assert.isLegal(input != null); |
| fInputElement= input; |
| } |
| |
| private void loadSettings() { |
| fFilteredCategories.clear(); |
| IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore(); |
| String string= store.getString(getPreferenceKey()); |
| if (string != null && string.length() > 0) { |
| String[] categories= string.split(";"); //$NON-NLS-1$ |
| for (int i= 0; i < categories.length; i++) { |
| fFilteredCategories.add(categories[i]); |
| } |
| } |
| string= store.getString(getPreferenceKey()+".LRU"); //$NON-NLS-1$ |
| if (string != null && string.length() > 0) { |
| String[] categories= string.split(";"); //$NON-NLS-1$ |
| for (int i= categories.length - 1; i >= 0; i--) { |
| fLRUList.put(categories[i], categories[i]); |
| } |
| } |
| fFilterUncategorizedMembers= store.getBoolean(getPreferenceKey()+".FilterUncategorized"); //$NON-NLS-1$ |
| } |
| |
| private void storeSettings() { |
| IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore(); |
| if (fFilteredCategories.size() == 0) { |
| store.setValue(getPreferenceKey(), ""); //$NON-NLS-1$ |
| } else { |
| StringBuffer buf= new StringBuffer(); |
| Iterator iter= fFilteredCategories.iterator(); |
| String element= (String)iter.next(); |
| buf.append(element); |
| while (iter.hasNext()) { |
| element= (String)iter.next(); |
| buf.append(';'); |
| buf.append(element); |
| } |
| store.setValue(getPreferenceKey(), buf.toString()); |
| buf= new StringBuffer(); |
| iter= fLRUList.values().iterator(); |
| element= (String)iter.next(); |
| buf.append(element); |
| while (iter.hasNext()) { |
| element= (String)iter.next(); |
| buf.append(';'); |
| buf.append(element); |
| } |
| store.setValue(getPreferenceKey()+".LRU", buf.toString()); //$NON-NLS-1$ |
| store.setValue(getPreferenceKey()+".FilterUncategorized", fFilterUncategorizedMembers); //$NON-NLS-1$ |
| } |
| } |
| |
| public void contributeToViewMenu(IMenuManager menuManager) { |
| menuManager.add(new Separator(CATEGORY_MENU_GROUP_NAME)); |
| menuManager.appendToGroup(CATEGORY_MENU_GROUP_NAME, fMenuAction); |
| fMenuListener= new IMenuListener() { |
| public void menuAboutToShow(IMenuManager manager) { |
| if (!manager.isVisible()) |
| return; |
| updateMenu(manager); |
| } |
| }; |
| menuManager.addMenuListener(fMenuListener); |
| fMenuManager= menuManager; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void dispose() { |
| super.dispose(); |
| if (fMenuManager != null) { |
| fMenuManager.removeMenuListener(fMenuListener); |
| fMenuManager= null; |
| fMenuListener= null; |
| } |
| } |
| |
| private void updateMenu(IMenuManager manager) { |
| IContributionItem[] items= manager.getItems(); |
| if (items != null) { |
| for (int i= 0; i < items.length; i++) { |
| IContributionItem item= items[i]; |
| if (item != null && item.getId() != null && item.getId().equals(FILTER_CATEGORY_ACTION_ID)) |
| manager.remove(item); |
| } |
| } |
| List menuEntries= new ArrayList(); |
| boolean hasUncategorizedMembers= getMenuCategories(menuEntries); |
| Collections.sort(menuEntries, Collator.getInstance()); |
| |
| if (menuEntries.size() > 0 && hasUncategorizedMembers) |
| manager.appendToGroup(CATEGORY_MENU_GROUP_NAME, new FilterUncategorizedMembersAction()); |
| |
| int count= 0; |
| for (Iterator iter= menuEntries.iterator(); iter.hasNext();) { |
| String category= (String)iter.next(); |
| manager.appendToGroup(CATEGORY_MENU_GROUP_NAME, new CategoryFilterAction(category, count + 1)); |
| count++; |
| } |
| } |
| |
| private boolean getMenuCategories(List result) { |
| final HashSet/*<String>*/ categories= new HashSet(); |
| final HashSet/*<String>*/ foundLRUCategories= new HashSet(); |
| final boolean hasUncategorizedMember[]= new boolean[] {false}; |
| for (int i= 0; i < fInputElement.length && !(hasUncategorizedMember[0] && foundLRUCategories.size() >= MAX_NUMBER_OF_CATEGORIES_IN_MENU); i++) { |
| collectCategories(fInputElement[i], new IResultCollector() { |
| public boolean accept(String[] cats) { |
| if (cats.length > 0) { |
| for (int j= 0; j < cats.length; j++) { |
| String category= cats[j]; |
| categories.add(category); |
| if (fLRUList.containsKey(category)) { |
| foundLRUCategories.add(category); |
| } |
| } |
| } else { |
| hasUncategorizedMember[0]= true; |
| } |
| return hasUncategorizedMember[0] && foundLRUCategories.size() >= MAX_NUMBER_OF_CATEGORIES_IN_MENU; |
| } |
| }); |
| } |
| int count= 0; |
| for (Iterator iter= foundLRUCategories.iterator(); iter.hasNext();) { |
| String element= (String)iter.next(); |
| result.add(element); |
| count++; |
| } |
| if (count < MAX_NUMBER_OF_CATEGORIES_IN_MENU) { |
| List sortedCategories= new ArrayList(categories); |
| Collections.sort(sortedCategories, Collator.getInstance()); |
| for (Iterator iter= sortedCategories.iterator(); iter.hasNext() && count < MAX_NUMBER_OF_CATEGORIES_IN_MENU;) { |
| String element= (String)iter.next(); |
| if (!foundLRUCategories.contains(element)) { |
| result.add(element); |
| count++; |
| } |
| } |
| } |
| return hasUncategorizedMember[0]; |
| } |
| |
| private boolean collectCategories(IJavaElement element, IResultCollector collector) {//HashSet result, int max, LinkedHashMap lruList) { |
| try { |
| if (element instanceof IMember) { |
| IMember member= (IMember)element; |
| collector.accept(member.getCategories()); |
| return processChildren(member.getChildren(), collector); |
| } else if (element instanceof ICompilationUnit) { |
| return processChildren(((ICompilationUnit)element).getChildren(), collector); |
| } else if (element instanceof IClassFile) { |
| return processChildren(((IClassFile)element).getChildren(), collector); |
| } else if (element instanceof IJavaModel) { |
| return processChildren(((IJavaModel)element).getChildren(), collector); |
| } else if (element instanceof IJavaProject) { |
| return processChildren(((IJavaProject)element).getChildren(), collector); |
| } else if (element instanceof IPackageFragment) { |
| return processChildren(((IPackageFragment)element).getChildren(), collector); |
| } else if (element instanceof IPackageFragmentRoot) { |
| return processChildren(((IPackageFragmentRoot)element).getChildren(), collector); |
| } |
| return false; |
| } catch (JavaModelException e) { |
| JavaPlugin.log(e); |
| return true; |
| } |
| } |
| |
| private boolean processChildren(IJavaElement[] children, IResultCollector collector) { |
| for (int i= 0; i < children.length; i++) { |
| if (collectCategories(children[i], collector)) |
| return true; |
| } |
| return false; |
| } |
| |
| private void fireSelectionChange() { |
| fViewer.getControl().setRedraw(false); |
| BusyIndicator.showWhile(fViewer.getControl().getDisplay(), new Runnable() { |
| public void run() { |
| fViewer.refresh(); |
| } |
| }); |
| fViewer.getControl().setRedraw(true); |
| } |
| |
| private String getPreferenceKey() { |
| return "CategoryFilterActionGroup." + fViewerId; //$NON-NLS-1$ |
| } |
| |
| private void showCategorySelectionDialog(IJavaElement[] input) { |
| final HashSet/*<String>*/ categories= new HashSet(); |
| for (int i= 0; i < input.length; i++) { |
| collectCategories(input[i], new IResultCollector() { |
| public boolean accept(String[] cats) { |
| for (int j= 0; j < cats.length; j++) { |
| categories.add(cats[j]); |
| } |
| return false; |
| } |
| }); |
| } |
| CategoryFilterSelectionDialog dialog= new CategoryFilterSelectionDialog(fViewer.getControl().getShell(), new ArrayList(categories), new ArrayList(fFilteredCategories)); |
| if (dialog.open() == Window.OK) { |
| Object[] selected= dialog.getResult(); |
| for (Iterator iter= categories.iterator(); iter.hasNext();) { |
| String category= (String)iter.next(); |
| if (contains(selected, category)) { |
| if (fFilteredCategories.remove(category)) |
| fLRUList.put(category, category); |
| } else { |
| if (fFilteredCategories.add(category)) |
| fLRUList.put(category, category); |
| } |
| } |
| storeSettings(); |
| fireSelectionChange(); |
| } |
| } |
| |
| private boolean contains(Object[] selected, String category) { |
| for (int i= 0; i < selected.length; i++) { |
| if (selected[i].equals(category)) |
| return true; |
| } |
| return false; |
| } |
| |
| } |