0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.jdt.internal.ui.dialogs;
0011:
0012: import java.io.IOException;
0013: import java.io.StringReader;
0014: import java.io.StringWriter;
0015: import java.lang.reflect.InvocationTargetException;
0016: import java.text.MessageFormat;
0017: import java.util.ArrayList;
0018: import java.util.Comparator;
0019: import java.util.HashMap;
0020: import java.util.List;
0021: import java.util.Map;
0022:
0023: import org.eclipse.core.runtime.CoreException;
0024: import org.eclipse.core.runtime.IProgressMonitor;
0025: import org.eclipse.core.runtime.IStatus;
0026: import org.eclipse.core.runtime.Platform;
0027: import org.eclipse.core.runtime.Status;
0028: import org.eclipse.core.runtime.SubProgressMonitor;
0029: import org.eclipse.core.runtime.jobs.IJobManager;
0030: import org.eclipse.core.runtime.jobs.Job;
0031:
0032: import org.eclipse.swt.graphics.Color;
0033: import org.eclipse.swt.graphics.Image;
0034: import org.eclipse.swt.layout.GridData;
0035: import org.eclipse.swt.widgets.Composite;
0036: import org.eclipse.swt.widgets.Control;
0037: import org.eclipse.swt.widgets.Display;
0038: import org.eclipse.swt.widgets.Item;
0039: import org.eclipse.swt.widgets.Shell;
0040: import org.eclipse.swt.widgets.Table;
0041: import org.eclipse.swt.widgets.Text;
0042:
0043: import org.eclipse.jface.action.Action;
0044: import org.eclipse.jface.action.IAction;
0045: import org.eclipse.jface.action.IMenuManager;
0046: import org.eclipse.jface.action.Separator;
0047: import org.eclipse.jface.dialogs.IDialogSettings;
0048: import org.eclipse.jface.dialogs.MessageDialog;
0049: import org.eclipse.jface.operation.IRunnableContext;
0050: import org.eclipse.jface.operation.IRunnableWithProgress;
0051: import org.eclipse.jface.resource.ImageDescriptor;
0052: import org.eclipse.jface.util.IPropertyChangeListener;
0053: import org.eclipse.jface.util.PropertyChangeEvent;
0054: import org.eclipse.jface.viewers.ILabelDecorator;
0055: import org.eclipse.jface.viewers.ISelection;
0056: import org.eclipse.jface.viewers.LabelProvider;
0057: import org.eclipse.jface.viewers.LabelProviderChangedEvent;
0058:
0059: import org.eclipse.jface.text.ITextSelection;
0060:
0061: import org.eclipse.ui.IMemento;
0062: import org.eclipse.ui.IWorkbenchWindow;
0063: import org.eclipse.ui.IWorkingSet;
0064: import org.eclipse.ui.PlatformUI;
0065: import org.eclipse.ui.WorkbenchException;
0066: import org.eclipse.ui.XMLMemento;
0067: import org.eclipse.ui.dialogs.FilteredItemsSelectionDialog;
0068: import org.eclipse.ui.dialogs.ISelectionStatusValidator;
0069: import org.eclipse.ui.dialogs.PreferencesUtil;
0070:
0071: import org.eclipse.jdt.core.IPackageFragmentRoot;
0072: import org.eclipse.jdt.core.IType;
0073: import org.eclipse.jdt.core.JavaConventions;
0074: import org.eclipse.jdt.core.JavaCore;
0075: import org.eclipse.jdt.core.JavaModelException;
0076: import org.eclipse.jdt.core.WorkingCopyOwner;
0077: import org.eclipse.jdt.core.search.IJavaSearchConstants;
0078: import org.eclipse.jdt.core.search.IJavaSearchScope;
0079: import org.eclipse.jdt.core.search.SearchEngine;
0080: import org.eclipse.jdt.core.search.SearchPattern;
0081: import org.eclipse.jdt.core.search.TypeNameMatch;
0082: import org.eclipse.jdt.core.search.TypeNameMatchRequestor;
0083: import org.eclipse.jdt.core.search.TypeNameRequestor;
0084:
0085: import org.eclipse.jdt.internal.corext.util.Messages;
0086: import org.eclipse.jdt.internal.corext.util.OpenTypeHistory;
0087: import org.eclipse.jdt.internal.corext.util.Strings;
0088: import org.eclipse.jdt.internal.corext.util.TypeFilter;
0089: import org.eclipse.jdt.internal.corext.util.TypeInfoFilter;
0090: import org.eclipse.jdt.internal.corext.util.TypeInfoRequestorAdapter;
0091:
0092: import org.eclipse.jdt.launching.IVMInstall;
0093: import org.eclipse.jdt.launching.IVMInstallType;
0094: import org.eclipse.jdt.launching.JavaRuntime;
0095: import org.eclipse.jdt.launching.LibraryLocation;
0096:
0097: import org.eclipse.jdt.ui.JavaElementLabels;
0098: import org.eclipse.jdt.ui.JavaUI;
0099: import org.eclipse.jdt.ui.dialogs.ITypeInfoFilterExtension;
0100: import org.eclipse.jdt.ui.dialogs.ITypeInfoImageProvider;
0101: import org.eclipse.jdt.ui.dialogs.ITypeSelectionComponent;
0102: import org.eclipse.jdt.ui.dialogs.TypeSelectionExtension;
0103:
0104: import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
0105: import org.eclipse.jdt.internal.ui.JavaPlugin;
0106: import org.eclipse.jdt.internal.ui.JavaUIMessages;
0107: import org.eclipse.jdt.internal.ui.preferences.TypeFilterPreferencePage;
0108: import org.eclipse.jdt.internal.ui.search.JavaSearchScopeFactory;
0109: import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
0110: import org.eclipse.jdt.internal.ui.util.TypeNameMatchLabelProvider;
0111: import org.eclipse.jdt.internal.ui.viewsupport.ColoredJavaElementLabels;
0112: import org.eclipse.jdt.internal.ui.viewsupport.ColoredString;
0113: import org.eclipse.jdt.internal.ui.viewsupport.ColoredViewersManager;
0114: import org.eclipse.jdt.internal.ui.viewsupport.OwnerDrawSupport;
0115: import org.eclipse.jdt.internal.ui.workingsets.WorkingSetFilterActionGroup;
0116:
0117: /**
0118: * Shows a list of Java types to the user with a text entry field for a string
0119: * pattern used to filter the list of types.
0120: *
0121: * @since 3.3
0122: */
0123: public class FilteredTypesSelectionDialog extends
0124: FilteredItemsSelectionDialog implements ITypeSelectionComponent {
0125:
0126: /**
0127: * Disabled "Show Container for Duplicates because of
0128: * https://bugs.eclipse.org/bugs/show_bug.cgi?id=184693 .
0129: */
0130: private static final boolean BUG_184693 = true;
0131:
0132: private static final String DIALOG_SETTINGS = "org.eclipse.jdt.internal.ui.dialogs.FilteredTypesSelectionDialog"; //$NON-NLS-1$
0133:
0134: private static final String SHOW_CONTAINER_FOR_DUPLICATES = "ShowContainerForDuplicates"; //$NON-NLS-1$
0135:
0136: private static final String WORKINGS_SET_SETTINGS = "WorkingSet"; //$NON-NLS-1$
0137:
0138: private WorkingSetFilterActionGroup fFilterActionGroup;
0139:
0140: private final TypeItemLabelProvider fTypeInfoLabelProvider;
0141:
0142: private String fTitle;
0143:
0144: private ShowContainerForDuplicatesAction fShowContainerForDuplicatesAction;
0145:
0146: private IJavaSearchScope fSearchScope;
0147:
0148: private boolean fAllowScopeSwitching;
0149:
0150: /**
0151: * Flags defining nature of searched elements; the only valid
0152: * values are:
0153: * {@link IJavaSearchConstants#TYPE},
0154: * {@link IJavaSearchConstants#ANNOTATION_TYPE},
0155: * {@link IJavaSearchConstants#INTERFACE},
0156: * {@link IJavaSearchConstants#ENUM},
0157: * {@link IJavaSearchConstants#CLASS_AND_INTERFACE},
0158: * {@link IJavaSearchConstants#CLASS_AND_ENUM}.
0159: */
0160: private final int fElementKinds;
0161:
0162: private final ITypeInfoFilterExtension fFilterExtension;
0163:
0164: private final TypeSelectionExtension fExtension;
0165:
0166: private ISelectionStatusValidator fValidator;
0167:
0168: private final TypeInfoUtil fTypeInfoUtil;
0169:
0170: private static boolean fgFirstTime = true;
0171:
0172: private final TypeItemsComparator fTypeItemsComparator;
0173:
0174: private int fTypeFilterVersion = 0;
0175:
0176: /**
0177: * Creates new FilteredTypesSelectionDialog instance
0178: *
0179: * @param parent
0180: * shell to parent the dialog on
0181: * @param multi
0182: * <code>true</code> if multiple selection is allowed
0183: * @param context
0184: * context used to execute long-running operations associated
0185: * with this dialog
0186: * @param scope
0187: * scope used when searching for types
0188: * @param elementKinds
0189: * flags defining nature of searched elements; the only valid
0190: * values are: <code>IJavaSearchConstants.TYPE</code>
0191: * <code>IJavaSearchConstants.ANNOTATION_TYPE</code>
0192: * <code>IJavaSearchConstants.INTERFACE</code>
0193: * <code>IJavaSearchConstants.ENUM</code>
0194: * <code>IJavaSearchConstants.CLASS_AND_INTERFACE</code>
0195: * <code>IJavaSearchConstants.CLASS_AND_ENUM</code>.
0196: * Please note that the bitwise OR combination of the elementary
0197: * constants is not supported.
0198: */
0199: public FilteredTypesSelectionDialog(Shell parent, boolean multi,
0200: IRunnableContext context, IJavaSearchScope scope,
0201: int elementKinds) {
0202: this (parent, multi, context, scope, elementKinds, null);
0203: }
0204:
0205: /**
0206: * Creates new FilteredTypesSelectionDialog instance.
0207: *
0208: * @param shell
0209: * shell to parent the dialog on
0210: * @param multi
0211: * <code>true</code> if multiple selection is allowed
0212: * @param context
0213: * context used to execute long-running operations associated
0214: * with this dialog
0215: * @param scope
0216: * scope used when searching for types. If the scope is <code>null</code>,
0217: * then workspace is scope is used as default, and the user can
0218: * choose a working set as scope.
0219: * @param elementKinds
0220: * flags defining nature of searched elements; the only valid
0221: * values are: <code>IJavaSearchConstants.TYPE</code>
0222: * <code>IJavaSearchConstants.ANNOTATION_TYPE</code>
0223: * <code>IJavaSearchConstants.INTERFACE</code>
0224: * <code>IJavaSearchConstants.ENUM</code>
0225: * <code>IJavaSearchConstants.CLASS_AND_INTERFACE</code>
0226: * <code>IJavaSearchConstants.CLASS_AND_ENUM</code>.
0227: * Please note that the bitwise OR combination of the elementary
0228: * constants is not supported.
0229: * @param extension
0230: * an extension of the standard type selection dialog; See
0231: * {@link TypeSelectionExtension}
0232: */
0233: public FilteredTypesSelectionDialog(Shell shell, boolean multi,
0234: IRunnableContext context, IJavaSearchScope scope,
0235: int elementKinds, TypeSelectionExtension extension) {
0236: super (shell, multi);
0237:
0238: setSelectionHistory(new TypeSelectionHistory());
0239:
0240: if (scope == null) {
0241: fAllowScopeSwitching = true;
0242: scope = SearchEngine.createWorkspaceScope();
0243: }
0244:
0245: fElementKinds = elementKinds;
0246: fExtension = extension;
0247: fFilterExtension = (extension == null) ? null : extension
0248: .getFilterExtension();
0249: fSearchScope = scope;
0250:
0251: if (extension != null) {
0252: fValidator = extension.getSelectionValidator();
0253: }
0254:
0255: fTypeInfoUtil = new TypeInfoUtil(extension != null ? extension
0256: .getImageProvider() : null);
0257:
0258: fTypeInfoLabelProvider = new TypeItemLabelProvider();
0259:
0260: setListLabelProvider(fTypeInfoLabelProvider);
0261: setListSelectionLabelDecorator(fTypeInfoLabelProvider);
0262: setDetailsLabelProvider(new TypeItemDetailsLabelProvider(
0263: fTypeInfoUtil));
0264:
0265: fTypeItemsComparator = new TypeItemsComparator();
0266: }
0267:
0268: /*
0269: * (non-Javadoc)
0270: *
0271: * @see org.eclipse.ui.dialogs.SelectionDialog#setTitle(java.lang.String)
0272: */
0273: public void setTitle(String title) {
0274: super .setTitle(title);
0275: fTitle = title;
0276: }
0277:
0278: /**
0279: * Adds or replaces subtitle of the dialog
0280: *
0281: * @param text
0282: * the new subtitle for this dialog
0283: */
0284: private void setSubtitle(String text) {
0285: if (text == null || text.length() == 0) {
0286: getShell().setText(fTitle);
0287: } else {
0288: getShell()
0289: .setText(
0290: Messages
0291: .format(
0292: JavaUIMessages.FilteredTypeSelectionDialog_titleFormat,
0293: new String[] { fTitle, text }));
0294: }
0295: }
0296:
0297: /*
0298: * (non-Javadoc)
0299: *
0300: * @see org.eclipse.ui.dialogs.AbstractSearchDialog#getDialogSettings()
0301: */
0302: protected IDialogSettings getDialogSettings() {
0303: IDialogSettings settings = JavaPlugin.getDefault()
0304: .getDialogSettings().getSection(DIALOG_SETTINGS);
0305:
0306: if (settings == null) {
0307: settings = JavaPlugin.getDefault().getDialogSettings()
0308: .addNewSection(DIALOG_SETTINGS);
0309: }
0310:
0311: return settings;
0312: }
0313:
0314: /*
0315: * (non-Javadoc)
0316: *
0317: * @see org.eclipse.ui.dialogs.AbstractSearchDialog#storeDialog(org.eclipse.jface.dialogs.IDialogSettings)
0318: */
0319: protected void storeDialog(IDialogSettings settings) {
0320: super .storeDialog(settings);
0321:
0322: if (!BUG_184693) {
0323: settings.put(SHOW_CONTAINER_FOR_DUPLICATES,
0324: fShowContainerForDuplicatesAction.isChecked());
0325: }
0326:
0327: if (fFilterActionGroup != null) {
0328: XMLMemento memento = XMLMemento
0329: .createWriteRoot("workingSet"); //$NON-NLS-1$
0330: fFilterActionGroup.saveState(memento);
0331: fFilterActionGroup.dispose();
0332: StringWriter writer = new StringWriter();
0333: try {
0334: memento.save(writer);
0335: settings.put(WORKINGS_SET_SETTINGS, writer.getBuffer()
0336: .toString());
0337: } catch (IOException e) {
0338: // don't do anything. Simply don't store the settings
0339: JavaPlugin.log(e);
0340: }
0341: }
0342: }
0343:
0344: /*
0345: * (non-Javadoc)
0346: *
0347: * @see org.eclipse.ui.dialogs.AbstractSearchDialog#restoreDialog(org.eclipse.jface.dialogs.IDialogSettings)
0348: */
0349: protected void restoreDialog(IDialogSettings settings) {
0350: super .restoreDialog(settings);
0351:
0352: if (!BUG_184693) {
0353: boolean showContainer = settings
0354: .getBoolean(SHOW_CONTAINER_FOR_DUPLICATES);
0355: fShowContainerForDuplicatesAction.setChecked(showContainer);
0356: fTypeInfoLabelProvider.setContainerInfo(showContainer);
0357: } else {
0358: fTypeInfoLabelProvider.setContainerInfo(true);
0359: }
0360:
0361: if (fAllowScopeSwitching) {
0362: String setting = settings.get(WORKINGS_SET_SETTINGS);
0363: if (setting != null) {
0364: try {
0365: IMemento memento = XMLMemento
0366: .createReadRoot(new StringReader(setting));
0367: fFilterActionGroup.restoreState(memento);
0368: } catch (WorkbenchException e) {
0369: // don't do anything. Simply don't restore the settings
0370: JavaPlugin.log(e);
0371: }
0372: }
0373: IWorkingSet ws = fFilterActionGroup.getWorkingSet();
0374: if (ws == null
0375: || (ws.isAggregateWorkingSet() && ws.isEmpty())) {
0376: setSearchScope(SearchEngine.createWorkspaceScope());
0377: setSubtitle(null);
0378: } else {
0379: setSearchScope(JavaSearchScopeFactory.getInstance()
0380: .createJavaSearchScope(ws, true));
0381: setSubtitle(ws.getLabel());
0382: }
0383: }
0384:
0385: // TypeNameMatch[] types = OpenTypeHistory.getInstance().getTypeInfos();
0386: //
0387: // for (int i = 0; i < types.length; i++) {
0388: // TypeNameMatch type = types[i];
0389: // accessedHistoryItem(type);
0390: // }
0391: }
0392:
0393: /*
0394: * (non-Javadoc)
0395: *
0396: * @see org.eclipse.ui.dialogs.AbstractSearchDialog#fillViewMenu(org.eclipse.jface.action.IMenuManager)
0397: */
0398: protected void fillViewMenu(IMenuManager menuManager) {
0399: super .fillViewMenu(menuManager);
0400:
0401: if (!BUG_184693) {
0402: fShowContainerForDuplicatesAction = new ShowContainerForDuplicatesAction();
0403: menuManager.add(fShowContainerForDuplicatesAction);
0404: }
0405: if (fAllowScopeSwitching) {
0406: fFilterActionGroup = new WorkingSetFilterActionGroup(
0407: getShell(), JavaPlugin.getActivePage(),
0408: new IPropertyChangeListener() {
0409: public void propertyChange(
0410: PropertyChangeEvent event) {
0411: IWorkingSet ws = (IWorkingSet) event
0412: .getNewValue();
0413: if (ws == null
0414: || (ws.isAggregateWorkingSet() && ws
0415: .isEmpty())) {
0416: setSearchScope(SearchEngine
0417: .createWorkspaceScope());
0418: setSubtitle(null);
0419: } else {
0420: setSearchScope(JavaSearchScopeFactory
0421: .getInstance()
0422: .createJavaSearchScope(ws, true));
0423: setSubtitle(ws.getLabel());
0424: }
0425:
0426: applyFilter();
0427: }
0428: });
0429: fFilterActionGroup.fillViewMenu(menuManager);
0430: }
0431:
0432: menuManager.add(new Separator());
0433: menuManager.add(new TypeFiltersPreferencesAction());
0434: }
0435:
0436: /*
0437: * (non-Javadoc)
0438: *
0439: * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#createExtendedContentArea(org.eclipse.swt.widgets.Composite)
0440: */
0441: protected Control createExtendedContentArea(Composite parent) {
0442: Control addition = null;
0443:
0444: if (fExtension != null) {
0445:
0446: addition = fExtension.createContentArea(parent);
0447: if (addition != null) {
0448: GridData gd = new GridData(GridData.FILL_HORIZONTAL);
0449: gd.horizontalSpan = 2;
0450: addition.setLayoutData(gd);
0451:
0452: }
0453:
0454: fExtension.initialize(this );
0455: }
0456:
0457: return addition;
0458: }
0459:
0460: /*
0461: * (non-Javadoc)
0462: *
0463: * @see org.eclipse.ui.dialogs.SelectionDialog#setResult(java.util.List)
0464: */
0465: protected void setResult(List newResult) {
0466:
0467: List resultToReturn = new ArrayList();
0468:
0469: for (int i = 0; i < newResult.size(); i++) {
0470: if (newResult.get(i) instanceof TypeNameMatch) {
0471: IType type = ((TypeNameMatch) newResult.get(i))
0472: .getType();
0473: if (type.exists()) {
0474: // items are added to history in the
0475: // org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#computeResult()
0476: // method
0477: resultToReturn.add(type);
0478: } else {
0479: TypeNameMatch typeInfo = (TypeNameMatch) newResult
0480: .get(i);
0481: IPackageFragmentRoot root = typeInfo
0482: .getPackageFragmentRoot();
0483: String containerName = JavaElementLabels
0484: .getElementLabel(root,
0485: JavaElementLabels.ROOT_QUALIFIED);
0486: String message = Messages
0487: .format(
0488: JavaUIMessages.FilteredTypesSelectionDialog_dialogMessage,
0489: new String[] {
0490: typeInfo
0491: .getFullyQualifiedName(),
0492: containerName });
0493: MessageDialog
0494: .openError(getShell(), fTitle, message);
0495: getSelectionHistory().remove(typeInfo);
0496: }
0497: }
0498: }
0499:
0500: super .setResult(resultToReturn);
0501: }
0502:
0503: /*
0504: * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#create()
0505: */
0506: public void create() {
0507: super .create();
0508: Control patternControl = getPatternControl();
0509: if (patternControl instanceof Text) {
0510: TextFieldNavigationHandler.install((Text) patternControl);
0511: }
0512: }
0513:
0514: /*
0515: * (non-Javadoc)
0516: *
0517: * @see org.eclipse.jface.window.Window#open()
0518: */
0519: public int open() {
0520: if (getInitialPattern() == null) {
0521: IWorkbenchWindow window = JavaPlugin
0522: .getActiveWorkbenchWindow();
0523: if (window != null) {
0524: ISelection selection = window.getSelectionService()
0525: .getSelection();
0526: if (selection instanceof ITextSelection) {
0527: String text = ((ITextSelection) selection)
0528: .getText();
0529: if (text != null) {
0530: text = text.trim();
0531: if (text.length() > 0
0532: && JavaConventions
0533: .validateJavaTypeName(text,
0534: JavaCore.VERSION_1_3,
0535: JavaCore.VERSION_1_3)
0536: .isOK()) {
0537: setInitialPattern(text, FULL_SELECTION);
0538: }
0539: }
0540: }
0541: }
0542: }
0543: return super .open();
0544: }
0545:
0546: /**
0547: * Sets a new validator.
0548: *
0549: * @param validator
0550: * the new validator
0551: */
0552: public void setValidator(ISelectionStatusValidator validator) {
0553: fValidator = validator;
0554: }
0555:
0556: /*
0557: * (non-Javadoc)
0558: *
0559: * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#createFilter()
0560: */
0561: protected ItemsFilter createFilter() {
0562: return new TypeItemsFilter(fSearchScope, fElementKinds,
0563: fFilterExtension);
0564: }
0565:
0566: /*
0567: * @see org.eclipse.ui.dialogs.SelectionStatusDialog#configureShell(org.eclipse.swt.widgets.Shell)
0568: */
0569: protected void configureShell(Shell shell) {
0570: super .configureShell(shell);
0571: PlatformUI.getWorkbench().getHelpSystem().setHelp(shell,
0572: IJavaHelpContextIds.TYPE_SELECTION_DIALOG2);
0573: }
0574:
0575: protected Control createContents(Composite parent) {
0576: Control contents = super .createContents(parent);
0577: if (ColoredViewersManager.showColoredLabels()) {
0578: if (contents instanceof Composite) {
0579: Table listControl = findTableControl((Composite) contents);
0580: if (listControl != null) {
0581: installOwnerDraw(listControl);
0582: }
0583: }
0584: }
0585: return contents;
0586: }
0587:
0588: private void installOwnerDraw(Table tableControl) {
0589: new OwnerDrawSupport(tableControl) { // installs the owner draw listeners
0590: public ColoredString getColoredLabel(Item item) {
0591: String text = item.getText();
0592: ColoredString str = new ColoredString(text);
0593: int index = text.indexOf('-');
0594: if (index != -1) {
0595: str.colorize(index, str.length() - index,
0596: ColoredJavaElementLabels.QUALIFIER_STYLE);
0597: }
0598: return str;
0599: }
0600:
0601: public Color getColor(String foregroundColorName,
0602: Display display) {
0603: return PlatformUI.getWorkbench().getThemeManager()
0604: .getCurrentTheme().getColorRegistry().get(
0605: foregroundColorName);
0606: }
0607: };
0608: }
0609:
0610: private Table findTableControl(Composite composite) {
0611: Control[] children = composite.getChildren();
0612: for (int i = 0; i < children.length; i++) {
0613: Control curr = children[i];
0614: if (curr instanceof Table) {
0615: return (Table) curr;
0616: } else if (curr instanceof Composite) {
0617: Table res = findTableControl((Composite) curr);
0618: if (res != null) {
0619: return res;
0620: }
0621: }
0622: }
0623: return null;
0624: }
0625:
0626: /*
0627: * (non-Javadoc)
0628: *
0629: * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#fillContentProvider(org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.AbstractContentProvider,
0630: * org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.ItemsFilter,
0631: * org.eclipse.core.runtime.IProgressMonitor)
0632: */
0633: protected void fillContentProvider(
0634: AbstractContentProvider provider, ItemsFilter itemsFilter,
0635: IProgressMonitor progressMonitor) throws CoreException {
0636: TypeItemsFilter typeSearchFilter = (TypeItemsFilter) itemsFilter;
0637: TypeSearchRequestor requestor = new TypeSearchRequestor(
0638: provider, typeSearchFilter);
0639: SearchEngine engine = new SearchEngine((WorkingCopyOwner) null);
0640: String packPattern = typeSearchFilter.getPackagePattern();
0641: progressMonitor
0642: .setTaskName(JavaUIMessages.FilteredTypesSelectionDialog_searchJob_taskName);
0643:
0644: /*
0645: * Setting the filter into match everything mode avoids filtering twice
0646: * by the same pattern (the search engine only provides filtered
0647: * matches). For the case when the pattern is a camel case pattern with
0648: * a terminator, the filter is not set to match everything mode because
0649: * jdt.core's SearchPattern does not support that case.
0650: */
0651: String typePattern = typeSearchFilter.getNamePattern();
0652: int matchRule = typeSearchFilter.getMatchRule();
0653: typeSearchFilter.setMatchEverythingMode(true);
0654:
0655: try {
0656: engine.searchAllTypeNames(packPattern == null ? null
0657: : packPattern.toCharArray(), typeSearchFilter
0658: .getPackageFlags(), typePattern.toCharArray(),
0659: matchRule, typeSearchFilter.getElementKind(),
0660: typeSearchFilter.getSearchScope(), requestor,
0661: IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH,
0662: progressMonitor);
0663: } finally {
0664: typeSearchFilter.setMatchEverythingMode(false);
0665: }
0666: }
0667:
0668: /*
0669: * (non-Javadoc)
0670: *
0671: * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getItemsComparator()
0672: */
0673: protected Comparator getItemsComparator() {
0674: return fTypeItemsComparator;
0675: }
0676:
0677: /*
0678: * (non-Javadoc)
0679: *
0680: * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#getElementName(java.lang.Object)
0681: */
0682: public String getElementName(Object item) {
0683: TypeNameMatch type = (TypeNameMatch) item;
0684: return fTypeInfoUtil.getText(type);
0685: }
0686:
0687: /*
0688: * (non-Javadoc)
0689: *
0690: * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#validateItem(java.lang.Object)
0691: */
0692: protected IStatus validateItem(Object item) {
0693:
0694: if (item == null)
0695: return new Status(IStatus.ERROR, JavaPlugin.getPluginId(),
0696: IStatus.ERROR, "", null); //$NON-NLS-1$
0697:
0698: if (fValidator != null) {
0699: IType type = ((TypeNameMatch) item).getType();
0700: if (!type.exists())
0701: return new Status(
0702: IStatus.ERROR,
0703: JavaPlugin.getPluginId(),
0704: IStatus.ERROR,
0705: Messages
0706: .format(
0707: JavaUIMessages.FilteredTypesSelectionDialog_error_type_doesnot_exist,
0708: ((TypeNameMatch) item)
0709: .getFullyQualifiedName()),
0710: null);
0711: Object[] elements = { type };
0712: return fValidator.validate(elements);
0713: } else
0714: return new Status(IStatus.OK, JavaPlugin.getPluginId(),
0715: IStatus.OK, "", null); //$NON-NLS-1$
0716: }
0717:
0718: /**
0719: * Sets search scope used when searching for types.
0720: *
0721: * @param scope
0722: * the new scope
0723: */
0724: private void setSearchScope(IJavaSearchScope scope) {
0725: fSearchScope = scope;
0726: }
0727:
0728: /*
0729: * We only have to ensure history consistency here since the search engine
0730: * takes care of working copies.
0731: */
0732: private static class ConsistencyRunnable implements
0733: IRunnableWithProgress {
0734: public void run(IProgressMonitor monitor)
0735: throws InvocationTargetException, InterruptedException {
0736: if (fgFirstTime) {
0737: // Join the initialize after load job.
0738: IJobManager manager = Job.getJobManager();
0739: manager.join(JavaUI.ID_PLUGIN, monitor);
0740: }
0741: OpenTypeHistory history = OpenTypeHistory.getInstance();
0742: if (fgFirstTime || history.isEmpty()) {
0743: if (history.needConsistencyCheck()) {
0744: monitor
0745: .beginTask(
0746: JavaUIMessages.TypeSelectionDialog_progress_consistency,
0747: 100);
0748: refreshSearchIndices(new SubProgressMonitor(
0749: monitor, 90));
0750: history.checkConsistency(new SubProgressMonitor(
0751: monitor, 10));
0752: } else {
0753: refreshSearchIndices(monitor);
0754: }
0755: monitor.done();
0756: fgFirstTime = false;
0757: } else {
0758: history.checkConsistency(monitor);
0759: }
0760: }
0761:
0762: public static boolean needsExecution() {
0763: OpenTypeHistory history = OpenTypeHistory.getInstance();
0764: return fgFirstTime || history.isEmpty()
0765: || history.needConsistencyCheck();
0766: }
0767:
0768: private void refreshSearchIndices(IProgressMonitor monitor)
0769: throws InvocationTargetException {
0770: try {
0771: new SearchEngine()
0772: .searchAllTypeNames(
0773: null,
0774: 0,
0775: // make sure we search a concrete name. This is faster according to Kent
0776: "_______________".toCharArray(), //$NON-NLS-1$
0777: SearchPattern.R_EXACT_MATCH
0778: | SearchPattern.R_CASE_SENSITIVE,
0779: IJavaSearchConstants.ENUM,
0780: SearchEngine.createWorkspaceScope(),
0781: new TypeNameRequestor() {
0782: },
0783: IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH,
0784: monitor);
0785: } catch (JavaModelException e) {
0786: throw new InvocationTargetException(e);
0787: }
0788: }
0789: }
0790:
0791: /*
0792: * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog#reloadCache(boolean, org.eclipse.core.runtime.IProgressMonitor)
0793: */
0794: public void reloadCache(boolean checkDuplicates,
0795: IProgressMonitor monitor) {
0796: IProgressMonitor remainingMonitor;
0797: if (ConsistencyRunnable.needsExecution()) {
0798: monitor
0799: .beginTask(
0800: JavaUIMessages.TypeSelectionDialog_progress_consistency,
0801: 10);
0802: try {
0803: ConsistencyRunnable runnable = new ConsistencyRunnable();
0804: runnable.run(new SubProgressMonitor(monitor, 1));
0805: } catch (InvocationTargetException e) {
0806: ExceptionHandler
0807: .handle(
0808: e,
0809: JavaUIMessages.TypeSelectionDialog_error3Title,
0810: JavaUIMessages.TypeSelectionDialog_error3Message);
0811: close();
0812: return;
0813: } catch (InterruptedException e) {
0814: // cancelled by user
0815: close();
0816: return;
0817: }
0818: remainingMonitor = new SubProgressMonitor(monitor, 9);
0819: } else {
0820: remainingMonitor = monitor;
0821: }
0822: super .reloadCache(checkDuplicates, remainingMonitor);
0823: monitor.done();
0824: }
0825:
0826: /*
0827: * @see org.eclipse.jdt.ui.dialogs.ITypeSelectionComponent#triggerSearch()
0828: */
0829: public void triggerSearch() {
0830: fTypeFilterVersion++;
0831: applyFilter();
0832: }
0833:
0834: /**
0835: * The <code>ShowContainerForDuplicatesAction</code> provides means to
0836: * show/hide container information for duplicate elements.
0837: */
0838: private class ShowContainerForDuplicatesAction extends Action {
0839:
0840: /**
0841: * Creates a new instance of the class
0842: */
0843: public ShowContainerForDuplicatesAction() {
0844: super (
0845: JavaUIMessages.FilteredTypeSelectionDialog_showContainerForDuplicatesAction,
0846: IAction.AS_CHECK_BOX);
0847: }
0848:
0849: /*
0850: * (non-Javadoc)
0851: *
0852: * @see org.eclipse.jface.action.Action#run()
0853: */
0854: public void run() {
0855: fTypeInfoLabelProvider.setContainerInfo(isChecked());
0856: }
0857: }
0858:
0859: private class TypeFiltersPreferencesAction extends Action {
0860:
0861: public TypeFiltersPreferencesAction() {
0862: super (
0863: JavaUIMessages.FilteredTypesSelectionDialog_TypeFiltersPreferencesAction_label);
0864: }
0865:
0866: /*
0867: * (non-Javadoc)
0868: *
0869: * @see org.eclipse.jface.action.Action#run()
0870: */
0871: public void run() {
0872: String typeFilterID = TypeFilterPreferencePage.TYPE_FILTER_PREF_PAGE_ID;
0873: PreferencesUtil.createPreferenceDialogOn(getShell(),
0874: typeFilterID, new String[] { typeFilterID }, null)
0875: .open();
0876: triggerSearch();
0877: }
0878: }
0879:
0880: /**
0881: * A <code>LabelProvider</code> for (the table of) types.
0882: */
0883: private class TypeItemLabelProvider extends LabelProvider implements
0884: ILabelDecorator {
0885:
0886: private boolean fContainerInfo;
0887:
0888: /**
0889: * Construct a new <code>TypeItemLabelProvider</code>. F
0890: */
0891: public TypeItemLabelProvider() {
0892:
0893: }
0894:
0895: public void setContainerInfo(boolean containerInfo) {
0896: fContainerInfo = containerInfo;
0897: fireLabelProviderChanged(new LabelProviderChangedEvent(this ));
0898: }
0899:
0900: /*
0901: * (non-Javadoc)
0902: *
0903: * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object)
0904: */
0905: public Image getImage(Object element) {
0906: if (!(element instanceof TypeNameMatch)) {
0907: return super .getImage(element);
0908: }
0909: return TypeNameMatchLabelProvider.getImage(
0910: (TypeNameMatch) element,
0911: TypeNameMatchLabelProvider.SHOW_TYPE_ONLY);
0912: }
0913:
0914: /*
0915: * (non-Javadoc)
0916: *
0917: * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
0918: */
0919: public String getText(Object element) {
0920: if (!(element instanceof TypeNameMatch)) {
0921: return super .getText(element);
0922: }
0923:
0924: if (fContainerInfo && isDuplicateElement(element)) {
0925: return fTypeInfoUtil
0926: .getFullyQualifiedText((TypeNameMatch) element);
0927: }
0928:
0929: if (!fContainerInfo && isDuplicateElement(element)) {
0930: return fTypeInfoUtil
0931: .getQualifiedText((TypeNameMatch) element);
0932: }
0933:
0934: return fTypeInfoUtil.getText(element);
0935: }
0936:
0937: /*
0938: * (non-Javadoc)
0939: *
0940: * @see org.eclipse.jface.viewers.ILabelDecorator#decorateImage(org.eclipse.swt.graphics.Image,
0941: * java.lang.Object)
0942: */
0943: public Image decorateImage(Image image, Object element) {
0944: return null;
0945: }
0946:
0947: /*
0948: * (non-Javadoc)
0949: *
0950: * @see org.eclipse.jface.viewers.ILabelDecorator#decorateText(java.lang.String,
0951: * java.lang.Object)
0952: */
0953: public String decorateText(String text, Object element) {
0954: if (!(element instanceof TypeNameMatch)) {
0955: return null;
0956: }
0957:
0958: if (fContainerInfo && isDuplicateElement(element)) {
0959: return fTypeInfoUtil
0960: .getFullyQualifiedText((TypeNameMatch) element);
0961: }
0962:
0963: return fTypeInfoUtil
0964: .getQualifiedText((TypeNameMatch) element);
0965: }
0966:
0967: }
0968:
0969: /**
0970: * A <code>LabelProvider</code> for the label showing type details.
0971: */
0972: private static class TypeItemDetailsLabelProvider extends
0973: LabelProvider {
0974:
0975: private final TypeInfoUtil fTypeInfoUtil;
0976:
0977: public TypeItemDetailsLabelProvider(TypeInfoUtil typeInfoUtil) {
0978: fTypeInfoUtil = typeInfoUtil;
0979: }
0980:
0981: /*
0982: * (non-Javadoc)
0983: *
0984: * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object)
0985: */
0986: public Image getImage(Object element) {
0987: if (element instanceof TypeNameMatch) {
0988: return TypeNameMatchLabelProvider
0989: .getImage(
0990: (TypeNameMatch) element,
0991: TypeNameMatchLabelProvider.SHOW_TYPE_CONTAINER_ONLY);
0992: }
0993:
0994: return super .getImage(element);
0995: }
0996:
0997: /*
0998: * (non-Javadoc)
0999: *
1000: * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
1001: */
1002: public String getText(Object element) {
1003: if (element instanceof TypeNameMatch) {
1004: return fTypeInfoUtil
1005: .getQualificationText((TypeNameMatch) element);
1006: }
1007:
1008: return super .getText(element);
1009: }
1010: }
1011:
1012: private static class TypeInfoUtil {
1013:
1014: private final ITypeInfoImageProvider fProviderExtension;
1015:
1016: private final TypeInfoRequestorAdapter fAdapter = new TypeInfoRequestorAdapter();
1017:
1018: private final Map fLib2Name = new HashMap();
1019:
1020: private final String[] fInstallLocations;
1021:
1022: private final String[] fVMNames;
1023:
1024: private boolean fFullyQualifyDuplicates;
1025:
1026: public TypeInfoUtil(ITypeInfoImageProvider extension) {
1027: fProviderExtension = extension;
1028: List locations = new ArrayList();
1029: List labels = new ArrayList();
1030: IVMInstallType[] installs = JavaRuntime.getVMInstallTypes();
1031: for (int i = 0; i < installs.length; i++) {
1032: processVMInstallType(installs[i], locations, labels);
1033: }
1034: fInstallLocations = (String[]) locations
1035: .toArray(new String[locations.size()]);
1036: fVMNames = (String[]) labels.toArray(new String[labels
1037: .size()]);
1038:
1039: }
1040:
1041: public void setFullyQualifyDuplicates(boolean value) {
1042: fFullyQualifyDuplicates = value;
1043: }
1044:
1045: private void processVMInstallType(IVMInstallType installType,
1046: List locations, List labels) {
1047: if (installType != null) {
1048: IVMInstall[] installs = installType.getVMInstalls();
1049: boolean isMac = Platform.OS_MACOSX.equals(Platform
1050: .getOS());
1051: final String HOME_SUFFIX = "/Home"; //$NON-NLS-1$
1052: for (int i = 0; i < installs.length; i++) {
1053: String label = getFormattedLabel(installs[i]
1054: .getName());
1055: LibraryLocation[] libLocations = installs[i]
1056: .getLibraryLocations();
1057: if (libLocations != null) {
1058: processLibraryLocation(libLocations, label);
1059: } else {
1060: String filePath = installs[i]
1061: .getInstallLocation().getAbsolutePath();
1062: // on MacOS X install locations end in an additional
1063: // "/Home" segment; remove it
1064: if (isMac && filePath.endsWith(HOME_SUFFIX))
1065: filePath = filePath.substring(0, filePath
1066: .length()
1067: - HOME_SUFFIX.length() + 1);
1068: locations.add(filePath);
1069: labels.add(label);
1070: }
1071: }
1072: }
1073: }
1074:
1075: private void processLibraryLocation(
1076: LibraryLocation[] libLocations, String label) {
1077: for (int l = 0; l < libLocations.length; l++) {
1078: LibraryLocation location = libLocations[l];
1079: fLib2Name.put(location.getSystemLibraryPath()
1080: .toOSString(), label);
1081: }
1082: }
1083:
1084: private String getFormattedLabel(String name) {
1085: return Messages
1086: .format(
1087: JavaUIMessages.FilteredTypesSelectionDialog_library_name_format,
1088: name);
1089: }
1090:
1091: public String getText(Object element) {
1092: return ((TypeNameMatch) element).getSimpleTypeName();
1093: }
1094:
1095: public String getQualifiedText(TypeNameMatch type) {
1096: StringBuffer result = new StringBuffer();
1097: result.append(type.getSimpleTypeName());
1098: String containerName = type.getTypeContainerName();
1099: result.append(JavaElementLabels.CONCAT_STRING);
1100: if (containerName.length() > 0) {
1101: result.append(containerName);
1102: } else {
1103: result
1104: .append(JavaUIMessages.FilteredTypesSelectionDialog_default_package);
1105: }
1106: return result.toString();
1107: }
1108:
1109: public String getFullyQualifiedText(TypeNameMatch type) {
1110: StringBuffer result = new StringBuffer();
1111: result.append(type.getSimpleTypeName());
1112: String containerName = type.getTypeContainerName();
1113: if (containerName.length() > 0) {
1114: result.append(JavaElementLabels.CONCAT_STRING);
1115: result.append(containerName);
1116: }
1117: result.append(JavaElementLabels.CONCAT_STRING);
1118: result.append(getContainerName(type));
1119: return result.toString();
1120: }
1121:
1122: public String getText(TypeNameMatch last,
1123: TypeNameMatch current, TypeNameMatch next) {
1124: StringBuffer result = new StringBuffer();
1125: int qualifications = 0;
1126: String currentTN = current.getSimpleTypeName();
1127: result.append(currentTN);
1128: String currentTCN = getTypeContainerName(current);
1129: if (last != null) {
1130: String lastTN = last.getSimpleTypeName();
1131: String lastTCN = getTypeContainerName(last);
1132: if (currentTCN.equals(lastTCN)) {
1133: if (currentTN.equals(lastTN)) {
1134: result.append(JavaElementLabels.CONCAT_STRING);
1135: result.append(currentTCN);
1136: result.append(JavaElementLabels.CONCAT_STRING);
1137: result.append(getContainerName(current));
1138: return result.toString();
1139: }
1140: } else if (currentTN.equals(lastTN)) {
1141: qualifications = 1;
1142: }
1143: }
1144: if (next != null) {
1145: String nextTN = next.getSimpleTypeName();
1146: String nextTCN = getTypeContainerName(next);
1147: if (currentTCN.equals(nextTCN)) {
1148: if (currentTN.equals(nextTN)) {
1149: result.append(JavaElementLabels.CONCAT_STRING);
1150: result.append(currentTCN);
1151: result.append(JavaElementLabels.CONCAT_STRING);
1152: result.append(getContainerName(current));
1153: return result.toString();
1154: }
1155: } else if (currentTN.equals(nextTN)) {
1156: qualifications = 1;
1157: }
1158: }
1159: if (qualifications > 0) {
1160: result.append(JavaElementLabels.CONCAT_STRING);
1161: result.append(currentTCN);
1162: if (fFullyQualifyDuplicates) {
1163: result.append(JavaElementLabels.CONCAT_STRING);
1164: result.append(getContainerName(current));
1165: }
1166: }
1167: return result.toString();
1168: }
1169:
1170: public String getQualificationText(TypeNameMatch type) {
1171: StringBuffer result = new StringBuffer();
1172: String containerName = type.getTypeContainerName();
1173: if (containerName.length() > 0) {
1174: result.append(containerName);
1175: result.append(JavaElementLabels.CONCAT_STRING);
1176: }
1177: result.append(getContainerName(type));
1178: return result.toString();
1179: }
1180:
1181: public ImageDescriptor getImageDescriptor(Object element) {
1182: TypeNameMatch type = (TypeNameMatch) element;
1183: if (fProviderExtension != null) {
1184: fAdapter.setMatch(type);
1185: ImageDescriptor descriptor = fProviderExtension
1186: .getImageDescriptor(fAdapter);
1187: if (descriptor != null)
1188: return descriptor;
1189: }
1190: return TypeNameMatchLabelProvider.getImageDescriptor(type,
1191: TypeNameMatchLabelProvider.SHOW_TYPE_ONLY);
1192: }
1193:
1194: private String getTypeContainerName(TypeNameMatch info) {
1195: String result = info.getTypeContainerName();
1196: if (result.length() > 0)
1197: return result;
1198: return JavaUIMessages.FilteredTypesSelectionDialog_default_package;
1199: }
1200:
1201: private String getContainerName(TypeNameMatch type) {
1202: IPackageFragmentRoot root = type.getPackageFragmentRoot();
1203: if (root.isExternal()) {
1204: String name = root.getPath().toOSString();
1205: for (int i = 0; i < fInstallLocations.length; i++) {
1206: if (name.startsWith(fInstallLocations[i])) {
1207: return fVMNames[i];
1208: }
1209: }
1210: String lib = (String) fLib2Name.get(name);
1211: if (lib != null)
1212: return lib;
1213: }
1214: StringBuffer buf = new StringBuffer();
1215: JavaElementLabels.getPackageFragmentRootLabel(root,
1216: JavaElementLabels.ROOT_QUALIFIED
1217: | JavaElementLabels.ROOT_VARIABLE, buf);
1218: return buf.toString();
1219: }
1220: }
1221:
1222: /**
1223: * Filters types using pattern, scope, element kind and filter extension.
1224: */
1225: private class TypeItemsFilter extends ItemsFilter {
1226:
1227: private boolean fMatchEverything = false;
1228:
1229: private final int fMyTypeFilterVersion = fTypeFilterVersion;
1230:
1231: private final TypeInfoFilter fTypeInfoFilter;
1232:
1233: /**
1234: * Creates instance of TypeItemsFilter
1235: *
1236: * @param scope
1237: * @param elementKind
1238: * @param extension
1239: */
1240: public TypeItemsFilter(IJavaSearchScope scope, int elementKind,
1241: ITypeInfoFilterExtension extension) {
1242: /*
1243: * Horribly convoluted initialization:
1244: * FilteredItemsSelectionDialog.ItemsFilter#ItemsFilter(SearchPattern)
1245: * fetches the pattern string from the Text widget of the outer class and
1246: * initializes the given SearchPattern with that string.
1247: * The default SearchPattern also removes whitespace from the pattern string,
1248: * which is why we have to supply our own (dummy) implementation.
1249: */
1250: super (new TypeSearchPattern());
1251: String pattern = patternMatcher.getPattern();
1252: fTypeInfoFilter = new TypeInfoFilter(pattern, scope,
1253: elementKind, extension);
1254: }
1255:
1256: /*
1257: * (non-Javadoc)
1258: *
1259: * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.ItemsFilter#isSubFilter(org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.ItemsFilter)
1260: */
1261: public boolean isSubFilter(ItemsFilter filter) {
1262: if (!(filter instanceof TypeItemsFilter))
1263: return false;
1264: TypeItemsFilter typeItemsFilter = (TypeItemsFilter) filter;
1265: if (fMyTypeFilterVersion != typeItemsFilter
1266: .getMyTypeFilterVersion())
1267: return false;
1268:
1269: //Caveat: This method is defined the wrong way 'round in FilteredItemsSelectionDialog!
1270: //WRONG (has reverse meaning!): return fTypeInfoFilter.isSubFilter(filter.getPattern());
1271: return typeItemsFilter.fTypeInfoFilter
1272: .isSubFilter(fTypeInfoFilter.getText());
1273: }
1274:
1275: public boolean equalsFilter(ItemsFilter iFilter) {
1276: if (!(iFilter instanceof TypeItemsFilter))
1277: return false;
1278: TypeItemsFilter typeItemsFilter = (TypeItemsFilter) iFilter;
1279: if (!getPattern().equals(typeItemsFilter.getPattern()))
1280: return false;
1281: if (getSearchScope() != typeItemsFilter.getSearchScope())
1282: return false;
1283: if (fMyTypeFilterVersion != typeItemsFilter
1284: .getMyTypeFilterVersion())
1285: return false;
1286: return true;
1287: }
1288:
1289: public int getElementKind() {
1290: return fTypeInfoFilter.getElementKind();
1291: }
1292:
1293: public IJavaSearchScope getSearchScope() {
1294: return fTypeInfoFilter.getSearchScope();
1295: }
1296:
1297: public int getMyTypeFilterVersion() {
1298: return fMyTypeFilterVersion;
1299: }
1300:
1301: public String getNamePattern() {
1302: return fTypeInfoFilter.getNamePattern();
1303: }
1304:
1305: public String getPackagePattern() {
1306: return fTypeInfoFilter.getPackagePattern();
1307: }
1308:
1309: public int getPackageFlags() {
1310: return fTypeInfoFilter.getPackageFlags();
1311: }
1312:
1313: public boolean matchesRawNamePattern(TypeNameMatch type) {
1314: return fTypeInfoFilter.matchesRawNamePattern(type);
1315: }
1316:
1317: public boolean matchesFilterExtension(TypeNameMatch type) {
1318: return fTypeInfoFilter.matchesFilterExtension(type);
1319: }
1320:
1321: /**
1322: * Set filter to "match everything" mode.
1323: *
1324: * @param matchEverything if <code>true</code>, {@link #matchItem(Object)} always returns true.
1325: * If <code>false</code>, the filter is enabled.
1326: */
1327: public void setMatchEverythingMode(boolean matchEverything) {
1328: fMatchEverything = matchEverything;
1329: }
1330:
1331: /*
1332: * (non-Javadoc)
1333: *
1334: * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.ItemsFilter#isConsistentItem(java.lang.Object)
1335: */
1336: public boolean isConsistentItem(Object item) {
1337: return true;
1338: }
1339:
1340: /*
1341: * (non-Javadoc)
1342: *
1343: * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.ItemsFilter#matchItem(java.lang.Object)
1344: */
1345: public boolean matchItem(Object item) {
1346: if (fMatchEverything)
1347: return true;
1348:
1349: TypeNameMatch type = (TypeNameMatch) item;
1350: return fTypeInfoFilter.matchesHistoryElement(type);
1351: }
1352:
1353: /*
1354: * (non-Javadoc)
1355: *
1356: * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.ItemsFilter#matchesRawNamePattern(java.lang.Object)
1357: */
1358: public boolean matchesRawNamePattern(Object item) {
1359: TypeNameMatch type = (TypeNameMatch) item;
1360: return matchesRawNamePattern(type);
1361: }
1362:
1363: /**
1364: * @return search flags
1365: * @see org.eclipse.jdt.core.search.SearchPattern#getMatchRule()
1366: */
1367: public int getMatchRule() {
1368: return fTypeInfoFilter.getSearchFlags();
1369: }
1370:
1371: public String getPattern() {
1372: return fTypeInfoFilter.getText();
1373: }
1374:
1375: public boolean isCamelCasePattern() {
1376: return fTypeInfoFilter.isCamelCasePattern();
1377: }
1378:
1379: /**
1380: * @param text
1381: * @return never returns
1382: * @throws UnsupportedOperationException always
1383: *
1384: * @deprecated not used
1385: */
1386: protected boolean matches(String text) {
1387: throw new UnsupportedOperationException();
1388: }
1389: }
1390:
1391: /**
1392: * Replaces functionality of {@link org.eclipse.ui.dialogs.SearchPattern} with an
1393: * adapter implementation that delegates to {@link TypeInfoFilter}.
1394: */
1395: private static class TypeSearchPattern extends
1396: org.eclipse.ui.dialogs.SearchPattern {
1397:
1398: private String fPattern;
1399:
1400: public void setPattern(String stringPattern) {
1401: fPattern = stringPattern;
1402: }
1403:
1404: public String getPattern() {
1405: return fPattern;
1406: }
1407: }
1408:
1409: /**
1410: * A <code>TypeSearchRequestor</code> collects matches filtered using
1411: * <code>TypeItemsFilter</code>. The attached content provider is filled
1412: * on the basis of the collected entries (instances of
1413: * <code>TypeNameMatch</code>).
1414: */
1415: private static class TypeSearchRequestor extends
1416: TypeNameMatchRequestor {
1417: private volatile boolean fStop;
1418:
1419: private final AbstractContentProvider fContentProvider;
1420:
1421: private final TypeItemsFilter fTypeItemsFilter;
1422:
1423: public TypeSearchRequestor(
1424: AbstractContentProvider contentProvider,
1425: TypeItemsFilter typeItemsFilter) {
1426: super ();
1427: fContentProvider = contentProvider;
1428: fTypeItemsFilter = typeItemsFilter;
1429: }
1430:
1431: public void cancel() {
1432: fStop = true;
1433: }
1434:
1435: /*
1436: * (non-Javadoc)
1437: *
1438: * @see org.eclipse.jdt.core.search.TypeNameMatchRequestor#acceptTypeNameMatch(org.eclipse.jdt.core.search.TypeNameMatch)
1439: */
1440: public void acceptTypeNameMatch(TypeNameMatch match) {
1441: if (fStop)
1442: return;
1443: if (TypeFilter.isFiltered(match))
1444: return;
1445: if (fTypeItemsFilter.matchesFilterExtension(match))
1446: fContentProvider.add(match, fTypeItemsFilter);
1447: }
1448:
1449: }
1450:
1451: /**
1452: * Compares TypeItems is used during sorting
1453: */
1454: private static class TypeItemsComparator implements Comparator {
1455:
1456: private final Map fLib2Name = new HashMap();
1457:
1458: private final String[] fInstallLocations;
1459:
1460: private final String[] fVMNames;
1461:
1462: /**
1463: * Creates new instance of TypeItemsComparator
1464: */
1465: public TypeItemsComparator() {
1466: List locations = new ArrayList();
1467: List labels = new ArrayList();
1468: IVMInstallType[] installs = JavaRuntime.getVMInstallTypes();
1469: for (int i = 0; i < installs.length; i++) {
1470: processVMInstallType(installs[i], locations, labels);
1471: }
1472: fInstallLocations = (String[]) locations
1473: .toArray(new String[locations.size()]);
1474: fVMNames = (String[]) labels.toArray(new String[labels
1475: .size()]);
1476: }
1477:
1478: private void processVMInstallType(IVMInstallType installType,
1479: List locations, List labels) {
1480: if (installType != null) {
1481: IVMInstall[] installs = installType.getVMInstalls();
1482: boolean isMac = Platform.OS_MACOSX.equals(Platform
1483: .getOS());
1484: final String HOME_SUFFIX = "/Home"; //$NON-NLS-1$
1485: for (int i = 0; i < installs.length; i++) {
1486: String label = getFormattedLabel(installs[i]
1487: .getName());
1488: LibraryLocation[] libLocations = installs[i]
1489: .getLibraryLocations();
1490: if (libLocations != null) {
1491: processLibraryLocation(libLocations, label);
1492: } else {
1493: String filePath = installs[i]
1494: .getInstallLocation().getAbsolutePath();
1495: // on MacOS X install locations end in an additional
1496: // "/Home" segment; remove it
1497: if (isMac && filePath.endsWith(HOME_SUFFIX))
1498: filePath = filePath.substring(0, filePath
1499: .length()
1500: - HOME_SUFFIX.length() + 1);
1501: locations.add(filePath);
1502: labels.add(label);
1503: }
1504: }
1505: }
1506: }
1507:
1508: private void processLibraryLocation(
1509: LibraryLocation[] libLocations, String label) {
1510: for (int l = 0; l < libLocations.length; l++) {
1511: LibraryLocation location = libLocations[l];
1512: fLib2Name.put(location.getSystemLibraryPath()
1513: .toString(), label);
1514: }
1515: }
1516:
1517: private String getFormattedLabel(String name) {
1518: return MessageFormat
1519: .format(
1520: JavaUIMessages.FilteredTypesSelectionDialog_library_name_format,
1521: new Object[] { name });
1522: }
1523:
1524: /*
1525: * (non-Javadoc)
1526: *
1527: * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
1528: */
1529: public int compare(Object left, Object right) {
1530:
1531: TypeNameMatch leftInfo = (TypeNameMatch) left;
1532: TypeNameMatch rightInfo = (TypeNameMatch) right;
1533:
1534: int result = compareName(leftInfo.getSimpleTypeName(),
1535: rightInfo.getSimpleTypeName());
1536: if (result != 0)
1537: return result;
1538: result = compareTypeContainerName(leftInfo
1539: .getTypeContainerName(), rightInfo
1540: .getTypeContainerName());
1541: if (result != 0)
1542: return result;
1543:
1544: int leftCategory = getElementTypeCategory(leftInfo);
1545: int rightCategory = getElementTypeCategory(rightInfo);
1546: if (leftCategory < rightCategory)
1547: return -1;
1548: if (leftCategory > rightCategory)
1549: return +1;
1550: return compareContainerName(leftInfo, rightInfo);
1551: }
1552:
1553: private int compareName(String leftString, String rightString) {
1554: int result = leftString.compareToIgnoreCase(rightString);
1555: if (result != 0 || rightString.length() == 0) {
1556: return result;
1557: } else if (Strings.isLowerCase(leftString.charAt(0))
1558: && !Strings.isLowerCase(rightString.charAt(0))) {
1559: return +1;
1560: } else if (Strings.isLowerCase(rightString.charAt(0))
1561: && !Strings.isLowerCase(leftString.charAt(0))) {
1562: return -1;
1563: } else {
1564: return leftString.compareTo(rightString);
1565: }
1566: }
1567:
1568: private int compareTypeContainerName(String leftString,
1569: String rightString) {
1570: int leftLength = leftString.length();
1571: int rightLength = rightString.length();
1572: if (leftLength == 0 && rightLength > 0)
1573: return -1;
1574: if (leftLength == 0 && rightLength == 0)
1575: return 0;
1576: if (leftLength > 0 && rightLength == 0)
1577: return +1;
1578: return compareName(leftString, rightString);
1579: }
1580:
1581: private int compareContainerName(TypeNameMatch leftType,
1582: TypeNameMatch rightType) {
1583: return getContainerName(leftType).compareTo(
1584: getContainerName(rightType));
1585: }
1586:
1587: private String getContainerName(TypeNameMatch type) {
1588: IPackageFragmentRoot root = type.getPackageFragmentRoot();
1589: if (root.isExternal()) {
1590: String name = root.getPath().toOSString();
1591: for (int i = 0; i < fInstallLocations.length; i++) {
1592: if (name.startsWith(fInstallLocations[i])) {
1593: return fVMNames[i];
1594: }
1595: }
1596: String lib = (String) fLib2Name.get(name);
1597: if (lib != null)
1598: return lib;
1599: }
1600: StringBuffer buf = new StringBuffer();
1601: JavaElementLabels.getPackageFragmentRootLabel(root,
1602: JavaElementLabels.ROOT_QUALIFIED
1603: | JavaElementLabels.ROOT_VARIABLE, buf);
1604: return buf.toString();
1605: }
1606:
1607: private int getElementTypeCategory(TypeNameMatch type) {
1608: try {
1609: if (type.getPackageFragmentRoot().getKind() == IPackageFragmentRoot.K_SOURCE)
1610: return 0;
1611: } catch (JavaModelException e) {
1612: JavaPlugin.log(e);
1613: }
1614: return 1;
1615: }
1616: }
1617:
1618: /**
1619: * Extends the <code>SelectionHistory</code>, providing support for
1620: * <code>OpenTypeHistory</code>.
1621: */
1622: protected class TypeSelectionHistory extends SelectionHistory {
1623:
1624: /**
1625: * Creates new instance of TypeSelectionHistory
1626: */
1627:
1628: public TypeSelectionHistory() {
1629: super ();
1630: }
1631:
1632: /*
1633: * (non-Javadoc)
1634: *
1635: * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.SelectionHistory#accessed(java.lang.Object)
1636: */
1637: public synchronized void accessed(Object object) {
1638: super .accessed(object);
1639: }
1640:
1641: /*
1642: * (non-Javadoc)
1643: *
1644: * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.SelectionHistory#remove(java.lang.Object)
1645: */
1646: public synchronized boolean remove(Object element) {
1647: OpenTypeHistory.getInstance().remove(
1648: (TypeNameMatch) element);
1649: return super .remove(element);
1650: }
1651:
1652: /*
1653: * (non-Javadoc)
1654: *
1655: * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.SelectionHistory#load(org.eclipse.ui.IMemento)
1656: */
1657: public void load(IMemento memento) {
1658: TypeNameMatch[] types = OpenTypeHistory.getInstance()
1659: .getTypeInfos();
1660:
1661: for (int i = 0; i < types.length; i++) {
1662: TypeNameMatch type = types[i];
1663: accessed(type);
1664: }
1665: }
1666:
1667: /*
1668: * (non-Javadoc)
1669: *
1670: * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.SelectionHistory#save(org.eclipse.ui.IMemento)
1671: */
1672: public void save(IMemento memento) {
1673: persistHistory();
1674: }
1675:
1676: /**
1677: * Stores contents of the local history into persistent history
1678: * container.
1679: */
1680: private synchronized void persistHistory() {
1681: if (getReturnCode() == OK) {
1682: Object[] items = getHistoryItems();
1683: for (int i = 0; i < items.length; i++) {
1684: OpenTypeHistory.getInstance().accessed(
1685: (TypeNameMatch) items[i]);
1686: }
1687: }
1688: }
1689:
1690: protected Object restoreItemFromMemento(IMemento element) {
1691: return null;
1692: }
1693:
1694: /*
1695: * (non-Javadoc)
1696: *
1697: * @see org.eclipse.ui.dialogs.FilteredItemsSelectionDialog.SelectionHistory#storeItemToMemento(java.lang.Object,
1698: * org.eclipse.ui.IMemento)
1699: */
1700: protected void storeItemToMemento(Object item, IMemento element) {
1701:
1702: }
1703:
1704: }
1705:
1706: }
|