From 41d098da72990706a7f21c5e8f13a2c01b778543 Mon Sep 17 00:00:00 2001 From: Alain Magloire Date: Sat, 27 Aug 2005 22:50:52 +0000 Subject: [PATCH] 2005-08-27 Alain Magloire Fix PR 108206: Do not use the UI thread when parsing the working copy for the outliner. * src/org/eclipse/cdt/internal/ui/CElementAdapterFactory.java * src/org/eclipse/cdt/internal/ui/DeferredCWorkbenchAdapter.java * src/org/eclipse/cdt/internal/ui/editor/CContentOutlinePage.java * src/org/eclipse/cdt/internal/ui/editor/CContentOutlineProvider.java --- core/org.eclipse.cdt.ui/ChangeLog | 8 + .../internal/ui/CElementAdapterFactory.java | 73 ++- .../ui/DeferredCWorkbenchAdapter.java | 53 +- .../ui/editor/CContentOutlinePage.java | 99 ++-- .../ui/editor/CContentOutlinerProvider.java | 546 ++++++++++-------- 5 files changed, 421 insertions(+), 358 deletions(-) diff --git a/core/org.eclipse.cdt.ui/ChangeLog b/core/org.eclipse.cdt.ui/ChangeLog index c4308149a7f..96b72c56ed9 100644 --- a/core/org.eclipse.cdt.ui/ChangeLog +++ b/core/org.eclipse.cdt.ui/ChangeLog @@ -1,3 +1,11 @@ +2005-08-27 Alain Magloire + Fix PR 108206: Do not use the UI thread when parsing + the working copy for the outliner. + * src/org/eclipse/cdt/internal/ui/CElementAdapterFactory.java + * src/org/eclipse/cdt/internal/ui/DeferredCWorkbenchAdapter.java + * src/org/eclipse/cdt/internal/ui/editor/CContentOutlinePage.java + * src/org/eclipse/cdt/internal/ui/editor/CContentOutlineProvider.java + 2005-08-27 Alain Magloire Fix PR 108205: limit the number of refresh by ignoring WorkingCopies events. * src/org/eclipse/cdt/ui/CElementContentProvider.java diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CElementAdapterFactory.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CElementAdapterFactory.java index 5697445b9b4..776ca983d82 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CElementAdapterFactory.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CElementAdapterFactory.java @@ -40,8 +40,7 @@ public class CElementAdapterFactory implements IAdapterFactory { IActionFilter.class }; - private static CWorkbenchAdapter fgCWorkbenchAdapter= new CWorkbenchAdapter(); - private static DeferredCWorkbenchAdapter fgDeferredCWorkbenchAdapter= new DeferredCWorkbenchAdapter(); + private static CWorkbenchAdapter fgCWorkbenchAdapter; /** * @see CElementAdapterFactory#getAdapterList @@ -55,37 +54,63 @@ public class CElementAdapterFactory implements IAdapterFactory { */ public Object getAdapter(Object element, Class key) { ICElement celem = (ICElement) element; - IResource res = null; if (IPropertySource.class.equals(key)) { - if (celem instanceof IBinary) { - return new BinaryPropertySource((IBinary)celem); - } - res = celem.getResource(); - if (res != null) { - if (res instanceof IFile) { - return new FilePropertySource((IFile)res); - } - return new ResourcePropertySource(res); - } - return new CElementPropertySource(celem); + return getPropertySource(celem); } else if (IWorkspaceRoot.class.equals(key)) { - res = celem.getUnderlyingResource(); - if (res != null) - return res.getWorkspace().getRoot(); + return getWorkspaceRoot(celem); } else if (IProject.class.equals(key)) { - res = celem.getResource(); - if (res != null) - return res.getProject(); + return getProject(celem); } else if (IResource.class.equals(key)) { - return celem.getResource(); + return getResource(celem); } else if (IDeferredWorkbenchAdapter.class.equals(key)) { - return fgDeferredCWorkbenchAdapter; + return getDeferredWorkbenchAdapter(celem); } else if (IWorkbenchAdapter.class.equals(key)) { - return fgCWorkbenchAdapter; + return getWorkbenchAdapter(celem); } else if (IActionFilter.class.equals(key)) { - return fgCWorkbenchAdapter; + return getWorkbenchAdapter(celem); } return null; } + + private IPropertySource getPropertySource(ICElement celement) { + if (celement instanceof IBinary) { + return new BinaryPropertySource((IBinary)celement); + } + IResource res = celement.getResource(); + if (res != null) { + if (res instanceof IFile) { + return new FilePropertySource((IFile)res); + } + return new ResourcePropertySource(res); + } + return new CElementPropertySource(celement); + } + + private IWorkspaceRoot getWorkspaceRoot(ICElement celement) { + IResource res = celement.getUnderlyingResource(); + if (res != null) { + return res.getWorkspace().getRoot(); + } + return null; + } + + private IProject getProject(ICElement celement) { + return celement.getCProject().getProject(); + } + + private IResource getResource(ICElement celement) { + return celement.getResource(); + } + + private IDeferredWorkbenchAdapter getDeferredWorkbenchAdapter(ICElement celement) { + return new DeferredCWorkbenchAdapter(celement); + } + + private IWorkbenchAdapter getWorkbenchAdapter(ICElement celement) { + if (fgCWorkbenchAdapter == null) { + fgCWorkbenchAdapter = new CWorkbenchAdapter(); + } + return fgCWorkbenchAdapter; + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/DeferredCWorkbenchAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/DeferredCWorkbenchAdapter.java index ceee02f804f..cc6daf3f911 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/DeferredCWorkbenchAdapter.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/DeferredCWorkbenchAdapter.java @@ -10,26 +10,21 @@ *******************************************************************************/ package org.eclipse.cdt.internal.ui; +import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.IParent; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.ui.progress.IDeferredWorkbenchAdapter; import org.eclipse.ui.progress.IElementCollector; -public class DeferredCWorkbenchAdapter extends CWorkbenchAdapter - implements IDeferredWorkbenchAdapter { +public class DeferredCWorkbenchAdapter extends CWorkbenchAdapter implements IDeferredWorkbenchAdapter { - private static boolean fSerializeFetching = false; - private static boolean fBatchFetchedChildren = true; - - final ISchedulingRule mutexRule = new ISchedulingRule() { - public boolean isConflicting(ISchedulingRule rule) { - return rule == mutexRule; - } - public boolean contains(ISchedulingRule rule) { - return rule == mutexRule; - } - }; + private ICElement fCElement; + + public DeferredCWorkbenchAdapter(ICElement element) { + super(); + fCElement = element; + } /* * (non-Javadoc) @@ -39,25 +34,12 @@ public class DeferredCWorkbenchAdapter extends CWorkbenchAdapter * org.eclipse.core.runtime.IProgressMonitor) */ public void fetchDeferredChildren(Object object, IElementCollector collector, IProgressMonitor monitor) { - if (object instanceof IParent) { - if (fBatchFetchedChildren) { - Object[] children = getChildren(object); - if (children.length > 0) - collector.add(children, monitor); - } else { - // TODO right now there is no advantage to this - // over the batched case above, but in the future - // we could have another method of progressively - // iterating over an ICElement's children - Object[] children = getChildren(object); - for (int i = 0; i < children.length; i++) { - if (monitor.isCanceled()) { - return; - } - collector.add(children[i], monitor); - } - } + Object[] children = getChildren(object); + if (monitor.isCanceled()) { + return; } + collector.add(children, monitor); + collector.done(); } /* @@ -66,7 +48,7 @@ public class DeferredCWorkbenchAdapter extends CWorkbenchAdapter * @see org.eclipse.ui.progress.IDeferredWorkbenchAdapter#isContainer() */ public boolean isContainer() { - return true; + return fCElement instanceof IParent; } /* @@ -75,11 +57,6 @@ public class DeferredCWorkbenchAdapter extends CWorkbenchAdapter * @see org.eclipse.ui.progress.IDeferredWorkbenchAdapter#getRule(java.lang.Object) */ public ISchedulingRule getRule(final Object object) { - if (fSerializeFetching) { - // only one ICElement parent can fetch children at a time - return mutexRule; - } - // allow several ICElement parents to fetch children concurrently - return null; + return fCElement.getResource(); } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CContentOutlinePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CContentOutlinePage.java index 5ce6215dfb4..5955561abac 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CContentOutlinePage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CContentOutlinePage.java @@ -72,10 +72,11 @@ import org.eclipse.ui.views.navigator.LocalSelectionTransfer; public class CContentOutlinePage extends Page implements IContentOutlinePage, ISelectionChangedListener { private CEditor fEditor; private ITranslationUnit fInput; - private ProblemTreeViewer treeViewer; + private ProblemTreeViewer fTreeViewer; private ListenerList selectionChangedListeners = new ListenerList(); private TogglePresentationAction fTogglePresentation; private String fContextMenuId; + private Menu fMenu; protected OpenIncludeAction fOpenIncludeAction; private IncludeGroupingAction fIncludeGroupingAction; @@ -247,20 +248,26 @@ public class CContentOutlinePage extends Page implements IContentOutlinePage, IS fRefactoringActionGroup.fillContextMenu(menu); } - + + protected CContentOutlinerProvider createContentProvider(TreeViewer viewer) { + return new CContentOutlinerProvider(viewer, CUIPlugin.getActiveWorkbenchWindow().getActivePage().getActivePart().getSite()); + } + + protected ProblemTreeViewer createTreeViewer(Composite parent) { + fTreeViewer = new ProblemTreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); + fTreeViewer.setContentProvider(createContentProvider(fTreeViewer)); + fTreeViewer.setLabelProvider(new DecoratingCLabelProvider(new StandardCElementLabelProvider(), true)); + fTreeViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS); + fTreeViewer.setUseHashlookup(true); + fTreeViewer.addSelectionChangedListener(this); + return fTreeViewer; + } + /* (non-Javadoc) * @see org.eclipse.ui.part.IPage#createControl(org.eclipse.swt.widgets.Composite) */ public void createControl(Composite parent) { - treeViewer = new ProblemTreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); - - //treeViewer.setContentProvider(new CElementContentProvider(true, true)); - treeViewer.setContentProvider(new CContentOutlinerProvider(treeViewer)); - treeViewer.setLabelProvider(new DecoratingCLabelProvider(new StandardCElementLabelProvider(), true)); - treeViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS); - treeViewer.setUseHashlookup(true); - treeViewer.addSelectionChangedListener(this); - + fTreeViewer = createTreeViewer(parent); initDragAndDrop(); MenuManager manager= new MenuManager(fContextMenuId); @@ -270,11 +277,11 @@ public class CContentOutlinePage extends Page implements IContentOutlinePage, IS contextMenuAboutToShow(manager); } }); - Control control= treeViewer.getControl(); - Menu menu= manager.createContextMenu(control); - control.setMenu(menu); + Control control= fTreeViewer.getControl(); + fMenu= manager.createContextMenu(control); + control.setMenu(fMenu); - treeViewer.addDoubleClickListener(new IDoubleClickListener() { + fTreeViewer.addDoubleClickListener(new IDoubleClickListener() { /* (non-Javadoc) * @see org.eclipse.jface.viewers.IDoubleClickListener#doubleClick(org.eclipse.jface.viewers.DoubleClickEvent) */ @@ -286,8 +293,8 @@ public class CContentOutlinePage extends Page implements IContentOutlinePage, IS }); // register global actions IPageSite site= getSite(); - site.registerContextMenu(fContextMenuId, manager, treeViewer); - site.setSelectionProvider(treeViewer); + site.registerContextMenu(fContextMenuId, manager, fTreeViewer); + site.setSelectionProvider(fTreeViewer); IActionBars bars= site.getActionBars(); bars.setGlobalActionHandler(ITextEditorActionDefinitionIds.TOGGLE_SHOW_SELECTED_ELEMENT_ONLY, fTogglePresentation); @@ -298,13 +305,16 @@ public class CContentOutlinePage extends Page implements IContentOutlinePage, IS // Custom filter group fCustomFiltersActionGroup= new CustomFiltersActionGroup("org.eclipse.cdt.ui.COutlinePage", getTreeViewer()); //$NON-NLS-1$ - treeViewer.setInput(fInput); + // Do this before setting input but after the initializations of the fields filtering + registerActionBars(bars); + + fTreeViewer.setInput(fInput); PlatformUI.getWorkbench().getHelpSystem().setHelp(control, ICHelpContextIds.COUTLINE_VIEW); } public void dispose() { - if (treeViewer != null) { - treeViewer.removeSelectionChangedListener(this); + if (fTreeViewer != null) { + fTreeViewer.removeSelectionChangedListener(this); } if (fTogglePresentation != null) { @@ -330,27 +340,34 @@ public class CContentOutlinePage extends Page implements IContentOutlinePage, IS fSelectionSearchGroup.dispose(); fSelectionSearchGroup= null; } - + + if (fCustomFiltersActionGroup != null) { + fCustomFiltersActionGroup.dispose(); + fCustomFiltersActionGroup= null; + } + if (selectionChangedListeners != null) { selectionChangedListeners.clear(); selectionChangedListeners= null; } - + + if (fMenu != null && !fMenu.isDisposed()) { + fMenu.dispose(); + fMenu= null; + } + fInput= null; super.dispose(); } - /* (non-Javadoc) - * @see org.eclipse.ui.part.IPage#setActionBars(org.eclipse.ui.IActionBars) - */ - public void setActionBars(IActionBars actionBars) { + private void registerActionBars(IActionBars actionBars) { IToolBarManager toolBarManager= actionBars.getToolBarManager(); LexicalSortingAction action= new LexicalSortingAction(getTreeViewer()); toolBarManager.add(action); - fMemberFilterActionGroup= new MemberFilterActionGroup(treeViewer, "COutlineViewer"); //$NON-NLS-1$ + fMemberFilterActionGroup= new MemberFilterActionGroup(fTreeViewer, "COutlineViewer"); //$NON-NLS-1$ fMemberFilterActionGroup.fillActionBars(actionBars); fCustomFiltersActionGroup.fillActionBars(actionBars); @@ -391,18 +408,18 @@ public class CContentOutlinePage extends Page implements IContentOutlinePage, IS * Method declared on IPage (and Page). */ public Control getControl() { - if (treeViewer == null) + if (fTreeViewer == null) return null; - return treeViewer.getControl(); + return fTreeViewer.getControl(); } /* (non-Javadoc) * Method declared on ISelectionProvider. */ public ISelection getSelection() { - if (treeViewer == null) + if (fTreeViewer == null) return StructuredSelection.EMPTY; - return treeViewer.getSelection(); + return fTreeViewer.getSelection(); } /** @@ -412,7 +429,7 @@ public class CContentOutlinePage extends Page implements IContentOutlinePage, IS * createControl has not been called yet */ protected TreeViewer getTreeViewer() { - return treeViewer; + return fTreeViewer; } /* (non-Javadoc) @@ -434,15 +451,15 @@ public class CContentOutlinePage extends Page implements IContentOutlinePage, IS * Sets focus to a part in the page. */ public void setFocus() { - treeViewer.getControl().setFocus(); + fTreeViewer.getControl().setFocus(); } /* (non-Javadoc) * Method declared on ISelectionProvider. */ public void setSelection(ISelection selection) { - if (treeViewer != null) - treeViewer.setSelection(selection); + if (fTreeViewer != null) + fTreeViewer.setSelection(selection); } /** @@ -451,8 +468,8 @@ public class CContentOutlinePage extends Page implements IContentOutlinePage, IS */ public void setInput(ITranslationUnit unit) { fInput = unit; - if (treeViewer != null) { - treeViewer.setInput (fInput); + if (fTreeViewer != null) { + fTreeViewer.setInput (fInput); } } @@ -464,15 +481,15 @@ public class CContentOutlinePage extends Page implements IContentOutlinePage, IS // Drop Adapter TransferDropTargetListener[] dropListeners= new TransferDropTargetListener[] { - new SelectionTransferDropAdapter(treeViewer) + new SelectionTransferDropAdapter(fTreeViewer) }; - treeViewer.addDropSupport(ops | DND.DROP_DEFAULT, transfers, new DelegatingDropAdapter(dropListeners)); + fTreeViewer.addDropSupport(ops | DND.DROP_DEFAULT, transfers, new DelegatingDropAdapter(dropListeners)); // Drag Adapter TransferDragSourceListener[] dragListeners= new TransferDragSourceListener[] { - new SelectionTransferDragAdapter(treeViewer) + new SelectionTransferDragAdapter(fTreeViewer) }; - treeViewer.addDragSupport(ops, transfers, new CDTViewerDragAdapter(treeViewer, dragListeners)); + fTreeViewer.addDragSupport(ops, transfers, new CDTViewerDragAdapter(fTreeViewer, dragListeners)); } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CContentOutlinerProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CContentOutlinerProvider.java index f8dc6bcbdb4..c5249fc59fb 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CContentOutlinerProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CContentOutlinerProvider.java @@ -30,287 +30,323 @@ import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; +import org.eclipse.ui.IWorkbenchPartSite; +import org.eclipse.ui.progress.DeferredTreeContentManager; /** - * Manages contents of the outliner. + * Manages contents of the outliner. */ public class CContentOutlinerProvider extends BaseCElementContentProvider { - /** Tree viewer which handles this content provider. */ - TreeViewer treeViewer; - /** Translation unit's root. */ - ITranslationUnit root; - /** Something changed listener. */ - private ElementChangedListener fListener; - /** Property change listener. */ - private IPropertyChangeListener fPropertyListener; - /** Filter for files to outline. */ - private String filter = "*"; //$NON-NLS-1$ + /** Tree viewer which handles this content provider. */ + TreeViewer treeViewer; - /** - * Creates new content provider for dialog. - * @param viewer Tree viewer. - */ - public CContentOutlinerProvider(TreeViewer viewer) - { - super(true, true); - treeViewer = viewer; - setIncludesGrouping(PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.OUTLINE_GROUP_INCLUDES)); - } + /** Translation unit's root. */ + ITranslationUnit root; - /** - * Sets new filter and updates contents. - * @param newFilter New filter. - */ - public void updateFilter(String newFilter) - { - filter = newFilter; - contentUpdated(); - } + /** Something changed listener. */ + private ElementChangedListener fListener; - /** - * Called by the editor to signal that the content has updated. - */ - public void contentUpdated() - { - if (treeViewer != null && !treeViewer.getControl().isDisposed()) - { - treeViewer.getControl().getDisplay().asyncExec(new Runnable() - { - public void run() - { - if (!treeViewer.getControl().isDisposed()) - { - final ISelection sel = treeViewer.getSelection(); - treeViewer.setSelection(updateSelection(sel)); - treeViewer.refresh(); - } - } - } - ); - } - } + /** Property change listener. */ + private IPropertyChangeListener fPropertyListener; - /** - * @see org.eclipse.jface.viewers.IContentProvider#dispose() - */ - public void dispose() - { - super.dispose(); - if (fListener != null) - { - CoreModel.getDefault().removeElementChangedListener(fListener); - fListener = null; - } - if (fPropertyListener != null) { - PreferenceConstants.getPreferenceStore().removePropertyChangeListener(fPropertyListener); - fPropertyListener = null; - } - } + /** Filter for files to outline. */ + private StringMatcher filter = new StringMatcher("*", true, false); //$NON-NLS-1$ - /** - * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) - */ - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) - { - final boolean isTU = newInput instanceof ITranslationUnit; + /** + * Remote content manager to retrieve content in the background. + */ + private DeferredTreeContentManager fManager; - if (isTU && fListener == null) - { - root = (ITranslationUnit) newInput; - fListener = new ElementChangedListener(); - CoreModel.getDefault().addElementChangedListener(fListener); - fPropertyListener = new PropertyListener(); - PreferenceConstants.getPreferenceStore().addPropertyChangeListener(fPropertyListener); - } - else if (!isTU && fListener != null) - { - CoreModel.getDefault().removeElementChangedListener(fListener); - fListener = null; - root = null; - } - } + /** + * We only want to use the DeferredContentManager, the first time + * because the Outliner is initialize in the UI thread. So to not block + * the UI thread we deferred, after it is not necessary the reconciler is + * running in a separate thread not affecting the UI. + */ + private boolean fUseContentManager = false; - /** - * @see org.eclipse.cdt.internal.ui.BaseCElementContentProvider#getChildren(java.lang.Object) - */ - public Object[] getChildren(Object element) - { - final StringMatcher stringMatcher = new StringMatcher(filter, true, false); - Object[] children = super.getChildren(element); - final List filtered = new ArrayList(); - for (int i = 0; i < children.length; i++) - { - if (stringMatcher.match(children[i].toString())) - { - filtered.add(children[i]); - } - } - final int size = filtered.size(); - children = new Object[size]; - filtered.toArray(children); - return children; - } + public CContentOutlinerProvider(TreeViewer viewer) { + this(viewer, null); + } - /** - * Updates current selection. - * @param sel Selection to update. - * @return Updated selection. - */ - protected ISelection updateSelection(ISelection sel) - { - final ArrayList newSelection = new ArrayList(); - if (sel instanceof IStructuredSelection) - { - final Iterator iter = ((IStructuredSelection) sel).iterator(); - while (iter.hasNext()) - { - final Object o = iter.next(); - if (o instanceof ICElement) - { - newSelection.add(o); - } - } - } - return new StructuredSelection(newSelection); - } + /** + * Creates new content provider for dialog. + * + * @param viewer + * Tree viewer. + */ + public CContentOutlinerProvider(TreeViewer viewer, IWorkbenchPartSite site) { + super(true, true); + treeViewer = viewer; + setIncludesGrouping(PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.OUTLINE_GROUP_INCLUDES)); + fManager = createContentManager(viewer, site); + } - /** - * The element change listener of the C outline viewer. - * @see IElementChangedListener - */ - class ElementChangedListener implements IElementChangedListener - { + protected DeferredTreeContentManager createContentManager(TreeViewer viewer, IWorkbenchPartSite site) { + if (site == null) { + return new DeferredTreeContentManager(this, viewer); + } + return new DeferredTreeContentManager(this, viewer, site); + } - /** - * Default constructor. - */ - public ElementChangedListener() - { - // nothing to initialize. - } + /** + * Sets new filter and updates contents. + * + * @param newFilter + * New filter. + */ + public void updateFilter(String newFilter) { + filter = new StringMatcher(newFilter, true, false); + contentUpdated(); + } - /** - * @see org.eclipse.cdt.core.model.IElementChangedListener#elementChanged(org.eclipse.cdt.core.model.ElementChangedEvent) - */ - public void elementChanged(final ElementChangedEvent e) - { - final ICElementDelta delta = findElement(root, e.getDelta()); - if (delta != null) - { - contentUpdated(); - return; - } - } + /** + * Called by the editor to signal that the content has updated. + */ + public void contentUpdated() { + if (treeViewer != null && !treeViewer.getControl().isDisposed()) { + treeViewer.getControl().getDisplay().asyncExec(new Runnable() { + public void run() { + if (!treeViewer.getControl().isDisposed()) { + final ISelection sel = treeViewer.getSelection(); + treeViewer.setSelection(updateSelection(sel)); + treeViewer.refresh(); + } + } + }); + } + } - /** - * Determines is structural change. - * @param cuDelta Delta to check. - * @return true if structural change. - */ - private boolean isPossibleStructuralChange(ICElementDelta cuDelta) - { - boolean ret; - if (cuDelta.getKind() != ICElementDelta.CHANGED) - { - ret = true; // add or remove - } - else - { - final int flags = cuDelta.getFlags(); - if ((flags & ICElementDelta.F_CHILDREN) != 0) - { - ret = true; - } - else - { - ret = (flags & (ICElementDelta.F_CONTENT | ICElementDelta.F_FINE_GRAINED)) == ICElementDelta.F_CONTENT; - } - } - return ret; - } + /** + * @see org.eclipse.jface.viewers.IContentProvider#dispose() + */ + public void dispose() { + super.dispose(); + if (fListener != null) { + CoreModel.getDefault().removeElementChangedListener(fListener); + fListener = null; + } + if (fPropertyListener != null) { + PreferenceConstants.getPreferenceStore().removePropertyChangeListener(fPropertyListener); + fPropertyListener = null; + } + if (root != null) { + fManager.cancel(root); + } + } - /** - * Searches for element. - * @param unit Unit to search in. - * @param delta Delta. - * @return Found element. - */ - protected ICElementDelta findElement(ICElement unit, ICElementDelta delta) - { - if (delta == null || unit == null) - { - return null; - } + /** + * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, + * java.lang.Object, java.lang.Object) + */ + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + boolean isTU = newInput instanceof ITranslationUnit; - final ICElement element = delta.getElement(); + if (isTU && fListener == null) { + fUseContentManager = true; + if (root != null) { + fManager.cancel(root); + } + root = (ITranslationUnit) newInput; + fListener = new ElementChangedListener(); + CoreModel.getDefault().addElementChangedListener(fListener); + fPropertyListener = new PropertyListener(); + PreferenceConstants.getPreferenceStore().addPropertyChangeListener( + fPropertyListener); + } else if (!isTU && fListener != null) { + fUseContentManager = false; + CoreModel.getDefault().removeElementChangedListener(fListener); + fListener = null; + root = null; + if (oldInput != null) { + fManager.cancel(oldInput); + } + } + } - if (unit.equals(element)) - { - if (isPossibleStructuralChange(delta)) - { - return delta; - } - return null; - } + /** + * @see org.eclipse.cdt.internal.ui.BaseCElementContentProvider#getChildren(java.lang.Object) + */ + public Object[] getChildren(Object element) { + Object[] children = null; + // Use the deferred manager for the first time (when parsing) + if (fUseContentManager && element instanceof ITranslationUnit) { + children = fManager.getChildren(element); + fUseContentManager = false; + } + if (children == null) { + children = super.getChildren(element); + } + List filtered = new ArrayList(); + for (int i = 0; i < children.length; i++) { + if (filter.match(children[i].toString())) { + filtered.add(children[i]); + } + } + int size = filtered.size(); + children = new Object[size]; + filtered.toArray(children); + return children; + } - if (element.getElementType() > ICElement.C_UNIT) - { - return null; - } + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object) + */ + public boolean hasChildren(Object element) { + if (fUseContentManager) { + return fManager.mayHaveChildren(element); + } + return super.hasChildren(element); + } - final ICElementDelta[] children = delta.getAffectedChildren(); - if (children == null || children.length == 0) - { - return null; - } + /** + * Updates current selection. + * + * @param sel + * Selection to update. + * @return Updated selection. + */ + protected ISelection updateSelection(ISelection sel) { + final ArrayList newSelection = new ArrayList(); + if (sel instanceof IStructuredSelection) { + final Iterator iter = ((IStructuredSelection) sel).iterator(); + while (iter.hasNext()) { + final Object o = iter.next(); + if (o instanceof ICElement) { + newSelection.add(o); + } + } + } + return new StructuredSelection(newSelection); + } - for (int i = 0; i < children.length; i++) - { - final ICElementDelta d = findElement(unit, children[i]); - if (d != null) - { - return d; - } - } + /** + * The element change listener of the C outline viewer. + * + * @see IElementChangedListener + */ + class ElementChangedListener implements IElementChangedListener { - return null; - } - } + /** + * Default constructor. + */ + public ElementChangedListener() { + // nothing to initialize. + } - /** - * - * Property change listener. - * @author P.Tomaszewski - */ - class PropertyListener implements IPropertyChangeListener { + /** + * @see org.eclipse.cdt.core.model.IElementChangedListener#elementChanged(org.eclipse.cdt.core.model.ElementChangedEvent) + */ + public void elementChanged(final ElementChangedEvent e) { + final ICElementDelta delta = findElement(root, e.getDelta()); + if (delta != null) { + contentUpdated(); + return; + } + } - /** - * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent) - */ - public void propertyChange(PropertyChangeEvent event){ - String prop = event.getProperty(); - if (prop.equals(PreferenceConstants.OUTLINE_GROUP_INCLUDES)) { - Object newValue = event.getNewValue(); - if (newValue instanceof Boolean) { - boolean value = ((Boolean)newValue).booleanValue(); - if (areIncludesGroup() != value) { - setIncludesGrouping(value); - contentUpdated(); - } - } - } else if (prop.equals(PreferenceConstants.OUTLINE_GROUP_NAMESPACES)) { - Object newValue = event.getNewValue(); - if (newValue instanceof Boolean) { - boolean value = ((Boolean)newValue).booleanValue(); - if (areNamespacesGroup() != value) { - setNamespacesGrouping(value); - contentUpdated(); - } - } - } - } + /** + * Determines is structural change. + * + * @param cuDelta + * Delta to check. + * @return true if structural change. + */ + private boolean isPossibleStructuralChange(ICElementDelta cuDelta) { + boolean ret; + if (cuDelta.getKind() != ICElementDelta.CHANGED) { + ret = true; // add or remove + } else { + final int flags = cuDelta.getFlags(); + if ((flags & ICElementDelta.F_CHILDREN) != 0) { + ret = true; + } else { + ret = (flags & (ICElementDelta.F_CONTENT | ICElementDelta.F_FINE_GRAINED)) == ICElementDelta.F_CONTENT; + } + } + return ret; + } - } + /** + * Searches for element. + * + * @param unit + * Unit to search in. + * @param delta + * Delta. + * @return Found element. + */ + protected ICElementDelta findElement(ICElement unit, + ICElementDelta delta) { + if (delta == null || unit == null) { + return null; + } + + final ICElement element = delta.getElement(); + + if (unit.equals(element)) { + if (isPossibleStructuralChange(delta)) { + return delta; + } + return null; + } + + if (element.getElementType() > ICElement.C_UNIT) { + return null; + } + + final ICElementDelta[] children = delta.getAffectedChildren(); + if (children == null || children.length == 0) { + return null; + } + + for (int i = 0; i < children.length; i++) { + final ICElementDelta d = findElement(unit, children[i]); + if (d != null) { + return d; + } + } + + return null; + } + } + + /** + * + * Property change listener. + * + * @author P.Tomaszewski + */ + class PropertyListener implements IPropertyChangeListener { + + /** + * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent) + */ + public void propertyChange(PropertyChangeEvent event) { + String prop = event.getProperty(); + if (prop.equals(PreferenceConstants.OUTLINE_GROUP_INCLUDES)) { + Object newValue = event.getNewValue(); + if (newValue instanceof Boolean) { + boolean value = ((Boolean) newValue).booleanValue(); + if (areIncludesGroup() != value) { + setIncludesGrouping(value); + contentUpdated(); + } + } + } else if (prop + .equals(PreferenceConstants.OUTLINE_GROUP_NAMESPACES)) { + Object newValue = event.getNewValue(); + if (newValue instanceof Boolean) { + boolean value = ((Boolean) newValue).booleanValue(); + if (areNamespacesGroup() != value) { + setNamespacesGrouping(value); + contentUpdated(); + } + } + } + } + + } }