| /******************************************************************************* |
| * Copyright (c) 2000, 2011 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.dialogs; |
| |
| import java.util.ArrayList; |
| import java.util.HashSet; |
| import java.util.List; |
| |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| 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.Link; |
| import org.eclipse.swt.widgets.Shell; |
| |
| import org.eclipse.core.runtime.IStatus; |
| |
| import org.eclipse.jface.action.Action; |
| import org.eclipse.jface.action.ToolBarManager; |
| import org.eclipse.jface.dialogs.IDialogSettings; |
| import org.eclipse.jface.viewers.CheckboxTreeViewer; |
| import org.eclipse.jface.viewers.ITreeContentProvider; |
| import org.eclipse.jface.viewers.Viewer; |
| import org.eclipse.jface.viewers.ViewerComparator; |
| |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.dialogs.ContainerCheckedTreeViewer; |
| import org.eclipse.ui.dialogs.ISelectionStatusValidator; |
| |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.core.dom.CompilationUnit; |
| import org.eclipse.jdt.core.dom.IBinding; |
| import org.eclipse.jdt.core.dom.IMethodBinding; |
| import org.eclipse.jdt.core.dom.IPackageBinding; |
| import org.eclipse.jdt.core.dom.ITypeBinding; |
| import org.eclipse.jdt.core.dom.Modifier; |
| |
| import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility2; |
| import org.eclipse.jdt.internal.corext.dom.ASTNodes; |
| import org.eclipse.jdt.internal.corext.dom.Bindings; |
| import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser; |
| import org.eclipse.jdt.internal.corext.template.java.CodeTemplateContextType; |
| import org.eclipse.jdt.internal.corext.util.Messages; |
| |
| import org.eclipse.jdt.internal.ui.IJavaHelpContextIds; |
| import org.eclipse.jdt.internal.ui.JavaPlugin; |
| import org.eclipse.jdt.internal.ui.JavaPluginImages; |
| import org.eclipse.jdt.internal.ui.JavaUIMessages; |
| import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider; |
| import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor; |
| import org.eclipse.jdt.internal.ui.util.ViewerPane; |
| import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider; |
| |
| public class OverrideMethodDialog extends SourceActionDialog { |
| |
| private class OverrideFlatTreeAction extends Action { |
| |
| private boolean fToggle; |
| |
| public OverrideFlatTreeAction() { |
| setToolTipText(JavaUIMessages.OverrideMethodDialog_groupMethodsByTypes); |
| |
| JavaPluginImages.setLocalImageDescriptors(this, "impl_co.gif"); //$NON-NLS-1$ |
| |
| fToggle= getOverrideContentProvider().isShowTypes(); |
| setChecked(fToggle); |
| } |
| |
| private OverrideMethodContentProvider getOverrideContentProvider() { |
| return (OverrideMethodContentProvider) getContentProvider(); |
| } |
| |
| @Override |
| public void run() { |
| // http://bugs.eclipse.org/bugs/show_bug.cgi?id=39264 |
| Object[] elementList= getOverrideContentProvider().getViewer().getCheckedElements(); |
| fToggle= !fToggle; |
| setChecked(fToggle); |
| getOverrideContentProvider().setShowTypes(fToggle); |
| getOverrideContentProvider().getViewer().setCheckedElements(elementList); |
| } |
| |
| } |
| |
| private static class OverrideMethodContentProvider implements ITreeContentProvider { |
| |
| private final Object[] fEmpty= new Object[0]; |
| |
| private IMethodBinding[] fMethods; |
| |
| private IDialogSettings fSettings; |
| |
| private boolean fShowTypes; |
| |
| private Object[] fTypes; |
| |
| private ContainerCheckedTreeViewer fViewer; |
| |
| private final String SETTINGS_SECTION= "OverrideMethodDialog"; //$NON-NLS-1$ |
| |
| private final String SETTINGS_SHOWTYPES= "showtypes"; //$NON-NLS-1$ |
| |
| /** |
| * Constructor for OverrideMethodContentProvider. |
| */ |
| public OverrideMethodContentProvider() { |
| IDialogSettings dialogSettings= JavaPlugin.getDefault().getDialogSettings(); |
| fSettings= dialogSettings.getSection(SETTINGS_SECTION); |
| if (fSettings == null) { |
| fSettings= dialogSettings.addNewSection(SETTINGS_SECTION); |
| fSettings.put(SETTINGS_SHOWTYPES, true); |
| } |
| fShowTypes= fSettings.getBoolean(SETTINGS_SHOWTYPES); |
| } |
| |
| /* |
| * @see IContentProvider#dispose() |
| */ |
| public void dispose() { |
| } |
| |
| /* |
| * @see ITreeContentProvider#getChildren(Object) |
| */ |
| public Object[] getChildren(Object parentElement) { |
| if (parentElement instanceof ITypeBinding) { |
| ArrayList<IMethodBinding> result= new ArrayList<IMethodBinding>(fMethods.length); |
| for (int index= 0; index < fMethods.length; index++) { |
| if (fMethods[index].getDeclaringClass().isEqualTo((IBinding) parentElement)) |
| result.add(fMethods[index]); |
| } |
| return result.toArray(); |
| } |
| return fEmpty; |
| } |
| |
| /* |
| * @see IStructuredContentProvider#getElements(Object) |
| */ |
| public Object[] getElements(Object inputElement) { |
| return fShowTypes ? fTypes : fMethods; |
| } |
| |
| /* |
| * @see ITreeContentProvider#getParent(Object) |
| */ |
| public Object getParent(Object element) { |
| if (element instanceof IMethodBinding) { |
| return ((IMethodBinding) element).getDeclaringClass(); |
| } |
| return null; |
| } |
| |
| public ContainerCheckedTreeViewer getViewer() { |
| return fViewer; |
| } |
| |
| /* |
| * @see ITreeContentProvider#hasChildren(Object) |
| */ |
| public boolean hasChildren(Object element) { |
| return getChildren(element).length > 0; |
| } |
| |
| public void init(IMethodBinding[] methods, ITypeBinding[] types) { |
| fMethods= methods; |
| fTypes= types; |
| } |
| |
| /* |
| * @see IContentProvider#inputChanged(Viewer, Object, Object) |
| */ |
| public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { |
| fViewer= (ContainerCheckedTreeViewer) viewer; |
| } |
| |
| public boolean isShowTypes() { |
| return fShowTypes; |
| } |
| |
| public void setShowTypes(boolean showTypes) { |
| if (fShowTypes != showTypes) { |
| fShowTypes= showTypes; |
| fSettings.put(SETTINGS_SHOWTYPES, showTypes); |
| if (fViewer != null) |
| fViewer.refresh(); |
| } |
| } |
| } |
| |
| private static class OverrideMethodComparator extends ViewerComparator { |
| |
| private ITypeBinding[] fAllTypes= new ITypeBinding[0]; |
| |
| public OverrideMethodComparator(ITypeBinding curr) { |
| if (curr != null) { |
| ITypeBinding[] superTypes= Bindings.getAllSuperTypes(curr); |
| fAllTypes= new ITypeBinding[superTypes.length + 1]; |
| fAllTypes[0]= curr; |
| System.arraycopy(superTypes, 0, fAllTypes, 1, superTypes.length); |
| } |
| } |
| |
| /* |
| * @see ViewerSorter#compare(Viewer, Object, Object) |
| */ |
| @Override |
| public int compare(Viewer viewer, Object first, Object second) { |
| if (first instanceof ITypeBinding && second instanceof ITypeBinding) { |
| final ITypeBinding left= (ITypeBinding) first; |
| final ITypeBinding right= (ITypeBinding) second; |
| if (right.getQualifiedName().equals("java.lang.Object")) //$NON-NLS-1$ |
| return -1; |
| if (left.isEqualTo(right)) |
| return 0; |
| if (Bindings.isSuperType(left, right)) |
| return +1; |
| else if (Bindings.isSuperType(right, left)) |
| return -1; |
| return 0; |
| } else |
| return super.compare(viewer, first, second); |
| } |
| } |
| |
| private static class OverrideMethodValidator implements ISelectionStatusValidator { |
| |
| private static int fNumMethods; |
| |
| public OverrideMethodValidator(int entries) { |
| fNumMethods= entries; |
| } |
| |
| /* |
| * @see ISelectionValidator#validate(Object[]) |
| */ |
| public IStatus validate(Object[] selection) { |
| int count= 0; |
| for (int index= 0; index < selection.length; index++) { |
| if (selection[index] instanceof IMethodBinding) |
| count++; |
| } |
| if (count == 0) |
| return new StatusInfo(IStatus.ERROR, ""); //$NON-NLS-1$ |
| return new StatusInfo(IStatus.INFO, Messages.format(JavaUIMessages.OverrideMethodDialog_selectioninfo_more, new String[] { String.valueOf(count), String.valueOf(fNumMethods)})); |
| } |
| } |
| |
| private static ITypeBinding getSuperType(final ITypeBinding binding, final String name) { |
| |
| if (binding.isArray() || binding.isPrimitive()) |
| return null; |
| |
| if (binding.getQualifiedName().startsWith(name)) |
| return binding; |
| |
| final ITypeBinding type= binding.getSuperclass(); |
| if (type != null) { |
| final ITypeBinding result= getSuperType(type, name); |
| if (result != null) |
| return result; |
| } |
| final ITypeBinding[] types= binding.getInterfaces(); |
| for (int index= 0; index < types.length; index++) { |
| final ITypeBinding result= getSuperType(types[index], name); |
| if (result != null) |
| return result; |
| } |
| return null; |
| } |
| |
| private CompilationUnit fUnit= null; |
| |
| public OverrideMethodDialog(Shell shell, CompilationUnitEditor editor, IType type, boolean isSubType) throws JavaModelException { |
| super(shell, new BindingLabelProvider(), new OverrideMethodContentProvider(), editor, type, false); |
| RefactoringASTParser parser= new RefactoringASTParser(ASTProvider.SHARED_AST_LEVEL); |
| fUnit= parser.parse(type.getCompilationUnit(), true); |
| final ITypeBinding binding= ASTNodes.getTypeBinding(fUnit, type); |
| List<IMethodBinding> toImplement= new ArrayList<IMethodBinding>(); |
| IMethodBinding[] overridable= null; |
| if (binding != null) { |
| final IPackageBinding pack= binding.getPackage(); |
| final IMethodBinding[] methods= StubUtility2.getOverridableMethods(fUnit.getAST(), binding, false); |
| List<IMethodBinding> list= new ArrayList<IMethodBinding>(methods.length); |
| for (int index= 0; index < methods.length; index++) { |
| final IMethodBinding cur= methods[index]; |
| if (Bindings.isVisibleInHierarchy(cur, pack)) |
| list.add(cur); |
| } |
| overridable= list.toArray(new IMethodBinding[list.size()]); |
| } else |
| overridable= new IMethodBinding[] {}; |
| for (int i= 0; i < overridable.length; i++) { |
| if (Modifier.isAbstract(overridable[i].getModifiers())) { |
| toImplement.add(overridable[i]); |
| } |
| } |
| |
| if (binding != null) { |
| ITypeBinding cloneable= getSuperType(binding, "java.lang.Cloneable"); //$NON-NLS-1$ |
| if (cloneable != null) { |
| IMethodBinding[] methods= fUnit.getAST().resolveWellKnownType("java.lang.Object").getDeclaredMethods(); //$NON-NLS-1$ |
| for (int index= 0; index < methods.length; index++) { |
| IMethodBinding method= methods[index]; |
| if (method.getName().equals("clone") && method.getParameterTypes().length == 0) //$NON-NLS-1$ |
| toImplement.add(method); |
| } |
| } |
| } |
| |
| IMethodBinding[] toImplementArray= toImplement.toArray(new IMethodBinding[toImplement.size()]); |
| setInitialSelections(toImplementArray); |
| |
| HashSet<ITypeBinding> expanded= new HashSet<ITypeBinding>(toImplementArray.length); |
| for (int i= 0; i < toImplementArray.length; i++) { |
| expanded.add(toImplementArray[i].getDeclaringClass()); |
| } |
| |
| HashSet<ITypeBinding> types= new HashSet<ITypeBinding>(overridable.length); |
| for (int i= 0; i < overridable.length; i++) { |
| types.add(overridable[i].getDeclaringClass()); |
| } |
| |
| ITypeBinding[] typesArrays= types.toArray(new ITypeBinding[types.size()]); |
| OverrideMethodComparator comparator= new OverrideMethodComparator(binding); |
| if (expanded.isEmpty() && typesArrays.length > 0) { |
| comparator.sort(null, typesArrays); |
| expanded.add(typesArrays[0]); |
| } |
| setExpandedElements(expanded.toArray()); |
| |
| ((OverrideMethodContentProvider) getContentProvider()).init(overridable, typesArrays); |
| |
| setTitle(JavaUIMessages.OverrideMethodDialog_dialog_title); |
| setMessage(null); |
| setValidator(new OverrideMethodValidator(overridable.length)); |
| setComparator(comparator); |
| setContainerMode(true); |
| setSize(60, 18); |
| setInput(new Object()); |
| } |
| |
| public CompilationUnit getCompilationUnit() { |
| return fUnit; |
| } |
| |
| /* |
| * @see org.eclipse.jface.window.Window#configureShell(Shell) |
| */ |
| @Override |
| protected void configureShell(Shell newShell) { |
| super.configureShell(newShell); |
| PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell, IJavaHelpContextIds.OVERRIDE_TREE_SELECTION_DIALOG); |
| } |
| |
| /* |
| * @see org.eclipse.jdt.internal.ui.dialogs.SourceActionDialog#createLinkControl(org.eclipse.swt.widgets.Composite) |
| */ |
| @Override |
| protected Control createLinkControl(Composite composite) { |
| Link link= new Link(composite, SWT.WRAP); |
| link.setText(JavaUIMessages.OverrideMethodDialog_link_message); |
| link.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| openCodeTempatePage(CodeTemplateContextType.OVERRIDECOMMENT_ID); |
| } |
| }); |
| link.setToolTipText(JavaUIMessages.OverrideMethodDialog_link_tooltip); |
| |
| GridData gridData= new GridData(SWT.FILL, SWT.BEGINNING, true, false); |
| gridData.widthHint= convertWidthInCharsToPixels(40); // only expand further if anyone else requires it |
| link.setLayoutData(gridData); |
| return link; |
| } |
| |
| /* |
| * @see CheckedTreeSelectionDialog#createTreeViewer(Composite) |
| */ |
| @Override |
| protected CheckboxTreeViewer createTreeViewer(Composite composite) { |
| initializeDialogUnits(composite); |
| ViewerPane pane= new ViewerPane(composite, SWT.BORDER | SWT.FLAT); |
| pane.setText(JavaUIMessages.OverrideMethodDialog_dialog_description); |
| CheckboxTreeViewer treeViewer= super.createTreeViewer(pane); |
| pane.setContent(treeViewer.getControl()); |
| GridLayout paneLayout= new GridLayout(); |
| paneLayout.marginHeight= 0; |
| paneLayout.marginWidth= 0; |
| paneLayout.numColumns= 1; |
| pane.setLayout(paneLayout); |
| GridData gd= new GridData(GridData.FILL_BOTH); |
| gd.widthHint= convertWidthInCharsToPixels(55); |
| gd.heightHint= convertHeightInCharsToPixels(15); |
| pane.setLayoutData(gd); |
| ToolBarManager manager= pane.getToolBarManager(); |
| manager.add(new OverrideFlatTreeAction()); // create after tree is created |
| manager.update(true); |
| treeViewer.getTree().setFocus(); |
| return treeViewer; |
| } |
| |
| public boolean hasMethodsToOverride() { |
| return getContentProvider().getElements(null).length > 0; |
| } |
| |
| } |