### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.ui Index: ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyLifeCycle.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyLifeCycle.java,v retrieving revision 1.46 diff -u -r1.46 TypeHierarchyLifeCycle.java --- ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyLifeCycle.java 31 Dec 2008 21:13:30 -0000 1.46 +++ ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyLifeCycle.java 30 Oct 2009 09:21:43 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2009 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 @@ -14,12 +14,19 @@ import java.util.ArrayList; import java.util.List; +import org.eclipse.swt.widgets.Display; + import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.ui.progress.IWorkbenchSiteProgressService; + import org.eclipse.jdt.core.ElementChangedEvent; import org.eclipse.jdt.core.IClassFile; import org.eclipse.jdt.core.ICompilationUnit; @@ -37,6 +44,9 @@ import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.internal.corext.util.JavaModelUtil; +import org.eclipse.jdt.internal.corext.util.Messages; + +import org.eclipse.jdt.ui.JavaElementLabels; import org.eclipse.jdt.internal.ui.JavaPlugin; @@ -52,8 +62,30 @@ private List fChangeListeners; - public TypeHierarchyLifeCycle() { + /** + * The type hierarchy view part. + * + * @since 3.6 + */ + private TypeHierarchyViewPart fTypeHierarchyViewPart; + + /** + * The job that runs in the background to refresh the type hierarchy. + * + * @since 3.6 + */ + private Job fRefreshHierarchyJob; + + /** + * Creates the type hierarchy life cycle. + * + * @param part the type hierarchy view part + * @since 3.6 + */ + public TypeHierarchyLifeCycle(TypeHierarchyViewPart part) { this(false); + fTypeHierarchyViewPart= part; + fRefreshHierarchyJob= null; } public TypeHierarchyLifeCycle(boolean isSuperTypesOnly) { @@ -98,7 +130,27 @@ } } + /** + * Refreshes the type hierarchy for the java element if it exists. + * + * @param element the java element for which the type hierarchy is computed + * @param context the runnable context + * @throws InterruptedException thrown from the OperationCanceledException when the monitor is canceled + * @throws InvocationTargetException thrown from the JavaModelException if the java element does not exist or if an exception occurs while accessing its corresponding resource + */ public void ensureRefreshedTypeHierarchy(final IJavaElement element, IRunnableContext context) throws InvocationTargetException, InterruptedException { + synchronized (this) { + if (fRefreshHierarchyJob != null) { + fRefreshHierarchyJob.cancel(); + try { + fRefreshHierarchyJob.join(); + } catch (InterruptedException e) { + // ignore + } finally { + fRefreshHierarchyJob= null; + } + } + } if (element == null || !element.exists()) { freeHierarchy(); return; @@ -106,21 +158,86 @@ boolean hierachyCreationNeeded= (fHierarchy == null || !element.equals(fInputElement)); if (hierachyCreationNeeded || fHierarchyRefreshNeeded) { - - IRunnableWithProgress op= new IRunnableWithProgress() { - public void run(IProgressMonitor pm) throws InvocationTargetException, InterruptedException { - try { - doHierarchyRefresh(element, pm); - } catch (JavaModelException e) { - throw new InvocationTargetException(e); - } catch (OperationCanceledException e) { - throw new InterruptedException(); + if (fTypeHierarchyViewPart == null) { + IRunnableWithProgress op= new IRunnableWithProgress() { + public void run(IProgressMonitor pm) throws InvocationTargetException, InterruptedException { + try { + doHierarchyRefresh(element, pm); + } catch (JavaModelException e) { + throw new InvocationTargetException(e); + } catch (OperationCanceledException e) { + throw new InterruptedException(); + } + } + }; + fHierarchyRefreshNeeded= true; + context.run(true, true, op); + fHierarchyRefreshNeeded= false; + } else { + final String label= Messages.format(TypeHierarchyMessages.TypeHierarchyLifeCycle_computeInput, JavaElementLabels.getElementLabel(element, JavaElementLabels.ALL_DEFAULT)); + fRefreshHierarchyJob= new Job(label) { + /* + * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor) + */ + public IStatus run(IProgressMonitor pm) { + pm.beginTask(label, LONG); + try { + doHierarchyRefreshBackground(element, pm); + } catch (OperationCanceledException e) { + fTypeHierarchyViewPart.setCanceledViewer(false); + return Status.CANCEL_STATUS; + } catch (JavaModelException e) { + return e.getStatus(); + } finally { + fHierarchyRefreshNeeded= true; + pm.done(); + } + return Status.OK_STATUS; } + }; + fRefreshHierarchyJob.setUser(true); + IWorkbenchSiteProgressService progressService= (IWorkbenchSiteProgressService)fTypeHierarchyViewPart.getSite() + .getAdapter(IWorkbenchSiteProgressService.class); + progressService.schedule(fRefreshHierarchyJob, 0); + + } + } + } + + /** + * Returns true if the refresh job is running, false otherwise. + * + * @return true if the refresh job is running, false otherwise + * + * @since 3.6 + */ + public boolean isRefreshJob() { + return fRefreshHierarchyJob != null; + } + + /** + * Refreshes the hierarchy in the background and updates the hierarchy viewer asynchronously in + * the UI thread. + * + * @param element the java element on which the hierarchy is computed + * @param pm the progress monitor + * @throws JavaModelException if the java element does not exist or if an exception occurs while + * accessing its corresponding resource. + * + * @since 3.6 + */ + protected void doHierarchyRefreshBackground(final IJavaElement element, final IProgressMonitor pm) throws JavaModelException { + doHierarchyRefresh(element, pm); + if (!pm.isCanceled()) { + Display.getDefault().asyncExec(new Runnable() { + /* + * @see java.lang.Runnable#run() + */ + public void run() { + fTypeHierarchyViewPart.setViewerInput(); + fTypeHierarchyViewPart.updateViewers(); } - }; - fHierarchyRefreshNeeded= true; - context.run(true, true, op); - fHierarchyRefreshNeeded= false; + }); } } @@ -160,7 +277,7 @@ } - public synchronized void doHierarchyRefresh(IJavaElement element, IProgressMonitor pm) throws JavaModelException { + public void doHierarchyRefresh(IJavaElement element, IProgressMonitor pm) throws JavaModelException { boolean hierachyCreationNeeded= (fHierarchy == null || !element.equals(fInputElement)); // to ensure the order of the two listeners always remove / add listeners on operations // on type hierarchies @@ -176,6 +293,8 @@ fInputElement= element; } else { fHierarchy.refresh(pm); + if (pm != null && pm.isCanceled()) + throw new OperationCanceledException(); } fHierarchy.addTypeHierarchyChangedListener(this); JavaCore.addElementChangedListener(this); Index: ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyMessages.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyMessages.java,v retrieving revision 1.12 diff -u -r1.12 TypeHierarchyMessages.java --- ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyMessages.java 6 Aug 2009 13:53:47 -0000 1.12 +++ ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyMessages.java 30 Oct 2009 09:21:43 -0000 @@ -72,6 +72,7 @@ public static String TypeHierarchyViewPart_ws_tooltip; public static String TypeHierarchyViewPart_restoreinput; public static String TypeHierarchyViewPart_layout_submenu; + public static String TypeHierarchyLifeCycle_computeInput; public static String ToggleViewAction_subtypes_label; public static String ToggleViewAction_subtypes_tooltip; public static String ToggleViewAction_subtypes_description; Index: ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyMessages.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyMessages.properties,v retrieving revision 1.59 diff -u -r1.59 TypeHierarchyMessages.properties --- ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyMessages.properties 17 Aug 2009 15:28:36 -0000 1.59 +++ ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyMessages.properties 30 Oct 2009 09:21:43 -0000 @@ -62,6 +62,7 @@ SortByDefiningTypeAction_label=Sort by the Defining Type SortByDefiningTypeAction_tooltip=Sort Methods by the Defining Type SortByDefiningTypeAction_description=Sort methods by the defining type +TypeHierarchyLifeCycle_computeInput=Computing type hierarchy of ''{0}''... TypeHierarchyViewPart_error_title=Open Type Hierarchy TypeHierarchyViewPart_createinput=Creating type hierarchy of ''{0}''... Index: ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyViewPart.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyViewPart.java,v retrieving revision 1.227 diff -u -r1.227 TypeHierarchyViewPart.java --- ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyViewPart.java 6 Aug 2009 13:53:47 -0000 1.227 +++ ui/org/eclipse/jdt/internal/ui/typehierarchy/TypeHierarchyViewPart.java 30 Oct 2009 09:21:44 -0000 @@ -242,6 +242,20 @@ private OpenAction fOpenAction; + /** + * Indicates whether the restore job was canceled. + * + * @since 3.6 + */ + private boolean fIsRestoreJobCancel= false; + + /** + * Indicates whether the current viewer shown is the empty viewer. + * + * @since 3.6 + */ + private boolean fIsShowingEmptyViewer= true; + public TypeHierarchyViewPart() { fSelectedType= null; @@ -251,7 +265,7 @@ fSelectInEditor= true; fRestoreStateJob= null; - fHierarchyLifeCycle= new TypeHierarchyLifeCycle(); + fHierarchyLifeCycle= new TypeHierarchyLifeCycle(this); fTypeHierarchyLifeCycleListener= new ITypeHierarchyLifeCycleListener() { public void typeHierarchyChanged(TypeHierarchyLifeCycle typeHierarchy, IType[] changedTypes) { doTypeHierarchyChanged(typeHierarchy, changedTypes); @@ -511,6 +525,7 @@ synchronized (this) { if (fRestoreStateJob != null) { fRestoreStateJob.cancel(); + fIsRestoreJobCancel= true; try { fRestoreStateJob.join(); } catch (InterruptedException e) { @@ -529,6 +544,11 @@ if (inputElement == null) { clearInput(); } else { + if (!inputElement.equals(prevInput)) { + for (int i= 0; i < fAllViewers.length; i++) { + fAllViewers[i].setInput(null); + } + } fInputElement= inputElement; fNoHierarchyShownLabel.setText(Messages.format(TypeHierarchyMessages.TypeHierarchyViewPart_createinput, JavaElementLabels.getElementLabel(inputElement, JavaElementLabels.ALL_DEFAULT))); try { @@ -537,34 +557,45 @@ } catch (InvocationTargetException e) { ExceptionHandler.handle(e, getSite().getShell(), TypeHierarchyMessages.TypeHierarchyViewPart_exception_title, TypeHierarchyMessages.TypeHierarchyViewPart_exception_message); clearInput(); - return; + return;// panic code. This code wont be executed. } catch (InterruptedException e) { fNoHierarchyShownLabel.setText(TypeHierarchyMessages.TypeHierarchyViewPart_empty); - return; + return;// panic code. This code wont be executed. } if (inputElement.getElementType() != IJavaElement.TYPE) { setHierarchyMode(HIERARCHY_MODE_CLASSIC); } - // turn off member filtering - fSelectInEditor= false; - setMemberFilter(null); - internalSelectType(null, false); // clear selection - fIsEnableMemberFilter= false; - if (!inputElement.equals(prevInput)) { - updateHierarchyViewer(true); - } - IType root= getSelectableType(inputElement); - internalSelectType(root, true); - updateMethodViewer(root); - updateToolbarButtons(); - updateToolTipAndDescription(); - showMembersInHierarchy(false); - fPagebook.showPage(fTypeMethodsSplitter); - fSelectInEditor= true; + updateViewers(); } } + /** + * Updates the viewers, toolbar buttons and tooltip. + * + * @since 3.6 + */ + public void updateViewers() { + if (!fHierarchyLifeCycle.isRefreshJob()) { + setViewerInput(); + } + setViewerVisibility(true); + // turn off member filtering + fSelectInEditor= false; + setMemberFilter(null); + internalSelectType(null, false); // clear selection + fIsEnableMemberFilter= false; + updateHierarchyViewer(true); + IType root= getSelectableType(fInputElement); + internalSelectType(root, true); + updateMethodViewer(root); + updateToolbarButtons(); + updateToolTipAndDescription(); + showMembersInHierarchy(false); + fPagebook.showPage(fTypeMethodsSplitter); + fSelectInEditor= true; + } + private void processOutstandingEvents() { Display display= getDisplay(); if (display != null && !display.isDisposed()) @@ -1086,7 +1117,7 @@ /* * Toggles between the empty viewer page and the hierarchy */ - private void setViewerVisibility(boolean showHierarchy) { + public void setViewerVisibility(boolean showHierarchy) { if (showHierarchy) { fViewerbook.showPage(getCurrentViewer().getControl()); } else { @@ -1124,7 +1155,7 @@ * updateHierarchyViewer brings up the correct view and refreshes * the current tree */ - private void updateHierarchyViewer(final boolean doExpand) { + public void updateHierarchyViewer(final boolean doExpand) { if (fInputElement == null) { fNoHierarchyShownLabel.setText(TypeHierarchyMessages.TypeHierarchyViewPart_empty); fPagebook.showPage(fNoHierarchyShownLabel); @@ -1139,9 +1170,14 @@ if (!isChildVisible(fViewerbook, getCurrentViewer().getControl())) { setViewerVisibility(true); } - } else { - fEmptyTypesViewer.setText(Messages.format(TypeHierarchyMessages.TypeHierarchyViewPart_nodecl, JavaElementLabels.getElementLabel(fInputElement, JavaElementLabels.ALL_DEFAULT))); - setViewerVisibility(false); + } else if (!fIsShowingEmptyViewer) {//Show the empty hierarchy viewer till fresh computation is done. + if (fIsRestoreJobCancel) { + setCanceledViewer(false); + fIsRestoreJobCancel= false; + } else { + fEmptyTypesViewer.setText(Messages.format(TypeHierarchyMessages.TypeHierarchyViewPart_nodecl, JavaElementLabels.getElementLabel(fInputElement, JavaElementLabels.ALL_DEFAULT))); + setViewerVisibility(false); + } } } } @@ -1566,6 +1602,7 @@ } catch (JavaModelException e) { return e.getStatus(); } catch (OperationCanceledException e) { + setCanceledViewer(true); return Status.CANCEL_STATUS; } return Status.OK_STATUS; @@ -1579,17 +1616,16 @@ private void doRestoreInBackground(final IMemento memento, final IJavaElement hierarchyInput, IProgressMonitor monitor) throws JavaModelException { fHierarchyLifeCycle.doHierarchyRefresh(hierarchyInput, monitor); final boolean doRestore= !monitor.isCanceled(); - Display.getDefault().asyncExec(new Runnable() { - public void run() { - // running async: check first if view still exists - if (fPagebook != null && !fPagebook.isDisposed()) { - if (doRestore) + if (doRestore) { + Display.getDefault().asyncExec(new Runnable() { + public void run() { + // running async: check first if view still exists + if (fPagebook != null && !fPagebook.isDisposed()) { doRestoreState(memento, hierarchyInput); - else - fNoHierarchyShownLabel.setText(TypeHierarchyMessages.TypeHierarchyViewPart_empty); + } } - } - }); + }); + } } @@ -1602,6 +1638,7 @@ } fWorkingSetActionGroup.restoreState(memento); + setShowingEmptyViewer(false); setInputElement(input); Integer viewerIndex= memento.getInteger(TAG_VIEW); @@ -1640,6 +1677,19 @@ } /** + * Sets whether the previous viewer shown was an empty viewer. + * + * @param isShowingEmptyViewer true if the previous viewer was empty, + * false otherwise + * + * @since 3.6 + */ + private void setShowingEmptyViewer(boolean isShowingEmptyViewer) { + fIsShowingEmptyViewer= isShowingEmptyViewer; + + } + + /** * View part becomes visible. * * @param isVisible true if visible @@ -1731,4 +1781,54 @@ fNeedRefresh= false; } + /** + * Sets the empty viewer after the canceled job in the display thread. + * @param isRestoreJob true when restore job is canceled, false otherwise + * + * @since 3.6 + */ + public void setCanceledViewer(final boolean isRestoreJob) { + Display.getDefault().asyncExec(new Runnable() { + public void run() { + if (isRestoreJob) { + fNoHierarchyShownLabel.setText(TypeHierarchyMessages.TypeHierarchyViewPart_empty); + } else { + setViewerVisibility(false); + String label= "Type Hierarchy computation canceled"; //$NON-NLS-1$ + fEmptyTypesViewer.setText(""); //$NON-NLS-1$ + updateMethodViewer(null); + setContentDescription(label); + setTitleToolTip(""); //$NON-NLS-1$ + for (int i= 0; i < fViewActions.length; i++) { + fViewActions[i].setEnabled(false); + } + } + setShowingEmptyViewer(true); + } + }); + } + + /** + * Returns the type hierarchy life cycle. + * + * @return the type hierarchy life cycle + * + * @since 3.6 + */ + public TypeHierarchyLifeCycle getTypeHierarchyLifeCycle() { + return fHierarchyLifeCycle; + + } + + /** + * Sets the input for all the hierarchy viewers with their respective viewer instances. + * + * @since 3.6 + */ + public void setViewerInput() { + for (int i= 0; i < fAllViewers.length; i++) { + fAllViewers[i].setInput(fAllViewers[i]); + } + setShowingEmptyViewer(false); + } }