Bug 55576 - [Viewers] Outline popup flickers with decorators on
Summary: [Viewers] Outline popup flickers with decorators on
Status: CLOSED WONTFIX
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.0   Edit
Hardware: PC Windows 2000
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Platform UI Triaged CLA
QA Contact:
URL:
Whiteboard: stalebug
Keywords: helpwanted, performance
: 55545 55820 58866 60527 198884 (view as bug list)
Depends on:
Blocks: 55679
  Show dependency tree
 
Reported: 2004-03-22 14:35 EST by John Arthorne CLA
Modified: 2020-11-05 14:06 EST (History)
8 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description John Arthorne CLA 2004-03-22 14:35:40 EST
I20040322

1) Open an editor on a class file for which there was no attached source (I used
Throwable.class)
2) Hit Ctrl+o to open content outline popup
3) Type the letter "p" to narrow the set of listed methods.

Expected: narrow down member list to only show those with prefix "p"
Actual: All methods disappear from list (even those starting with "p", but all
fields remain.
Comment 1 Dani Megert CLA 2004-03-22 15:13:36 EST
strange: adding a second p and then delete it solves the problem.

Same can be reproduced with source. Steps:
1. open AbstractReconciler
2. ctrl+o
3. check go into top level type¨
4. enter 'i'
   observe: not all members starting with i are shown
5. enter a second i then delete it again
   observe: all members starting with i are shown
Comment 2 Dani Megert CLA 2004-03-23 02:10:19 EST
*** Bug 55545 has been marked as a duplicate of this bug. ***
Comment 3 Dani Megert CLA 2004-03-23 03:28:32 EST
The code seems to got broken with the changes made for key bindings in dialogs:
our code works with I20040317 but not with I20040322.

Investigating...
Comment 4 Dani Megert CLA 2004-03-23 09:35:57 EST
This is caused by some changes in either Platform UI or Team after I20040317.

Note:
- the problem goes away if I disable the decorators
- if the CU is a changed team resource and I type it flickers much more than before

As a workaround I removed the support for decorators for now.

To reproduce you have to load the following CU:
  org.eclipse.jdt.internal.ui.text.JavaOutlineInformationControl (rev. 1.34)
Comment 5 Dani Megert CLA 2004-03-23 09:39:07 EST
If the bug which causes this doesn't affect others then severity and milestone
can be changed since I added a workaround.
Comment 6 Tod Creasey CLA 2004-03-23 16:36:08 EST
The problem appears to be that when the items are filtered the old items are 
not being removed and replaced with new ones.

If you look at the example above there should be 5 entries in that tree which 
there are - they are just the wrong 5.
Comment 7 Dani Megert CLA 2004-03-24 04:20:23 EST
*** Bug 55820 has been marked as a duplicate of this bug. ***
Comment 8 Tod Creasey CLA 2004-03-24 08:31:07 EST
As this one has been worked around by Dani and doesn't seem to be an issue 
elsewhere we will be fixing it for M9.
Comment 9 Tod Creasey CLA 2004-04-19 16:57:10 EDT
Here is the source to test:

/******************************************************************************
*
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 
*******************************************************************************
/
package org.eclipse.jdt.internal.ui.text;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.IProgressMonitor;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.Widget;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.viewers.ViewerSorter;

import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.help.WorkbenchHelp;
import org.eclipse.ui.keys.KeySequence;
import org.eclipse.ui.keys.SWTKeySupport;

import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IImportDeclaration;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaModelException;

import org.eclipse.jdt.ui.JavaElementSorter;
import org.eclipse.jdt.ui.StandardJavaElementContentProvider;

import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.corext.util.SuperTypeHierarchyCache;

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.viewsupport.AppearanceAwareLabelProvider;
import org.eclipse.jdt.internal.ui.viewsupport.DecoratingJavaLabelProvider;
import org.eclipse.jdt.internal.ui.viewsupport.JavaElementLabels;
import org.eclipse.jdt.internal.ui.viewsupport.MemberFilter;

/**
 * Show outline in light-weight control.
 * 
 * @since 2.1
 */
public class JavaOutlineInformationControl extends AbstractInformationControl {
	
	private KeyAdapter fKeyAdapter;
	private OutlineContentProvider fOutlineContentProvider;
	private IJavaElement fInput= null;

	private OutlineSorter fOutlineSorter;
	
	private OutlineLabelProvider fInnerLabelProvider;
	protected Color fForegroundColor;
	
	private boolean fShowOnlyMainType;
	private LexicalSortingAction fLexicalSortingAction;
	private SortByDefiningTypeAction fSortByDefiningTypeAction;
	private ShowOnlyMainTypeAction fShowOnlyMainTypeAction;
	private Map fTypeHierarchies= new HashMap();

	
	private class OutlineLabelProvider extends 
AppearanceAwareLabelProvider {

		private boolean fShowDefiningType;

		private OutlineLabelProvider() {
			super(AppearanceAwareLabelProvider.DEFAULT_TEXTFLAGS 
|  JavaElementLabels.F_APP_TYPE_SIGNATURE, 
AppearanceAwareLabelProvider.DEFAULT_IMAGEFLAGS);
		}
		
		/*
		 * @see ILabelProvider#getText
		 */ 	
		public String getText(Object element) {
			String text= super.getText(element);
			if (fShowDefiningType) {
				try {
					IType type= getDefiningType(element);
					if (type != null) {
						StringBuffer buf= new 
StringBuffer(super.getText(type));
						buf.append
(JavaElementLabels.CONCAT_STRING);
						buf.append(text);
						return buf.toString();	
		
					}
				} catch (JavaModelException e) {
				}
			}
			return text;
		}
		
		/*
		 * @see 
org.eclipse.jdt.internal.ui.viewsupport.JavaUILabelProvider#getForeground
(java.lang.Object)
		 */
		public Color getForeground(Object element) {
			if (fOutlineContentProvider.isShowingInheritedMembers
()) {
				if (element instanceof IJavaElement) {
					IJavaElement je= (IJavaElement)element;
					if (fInput.getElementType() == 
IJavaElement.CLASS_FILE)
						je= je.getAncestor
(IJavaElement.CLASS_FILE);
					else
						je= je.getAncestor
(IJavaElement.COMPILATION_UNIT);
					if (fInput.equals(je)) {
						return null;
					}
				}
				return fForegroundColor;
			}
			return null;
		}
		
		public void setShowDefiningType(boolean showDefiningType) {
			fShowDefiningType= showDefiningType;
		}
		
		public boolean isShowDefiningType() {
			return fShowDefiningType;
		}	
		
		private IType getDefiningType(Object element) throws 
JavaModelException {
			int kind= ((IJavaElement) element).getElementType();
		
			if (kind != IJavaElement.METHOD && kind != 
IJavaElement.FIELD && kind != IJavaElement.INITIALIZER) {
				return null;
			}
			IType declaringType= ((IMember) 
element).getDeclaringType();
			if (kind != IJavaElement.METHOD) {
				return declaringType;
			}
			ITypeHierarchy hierarchy= getSuperTypeHierarchy
(declaringType);
			if (hierarchy == null) {
				return declaringType;
			}
			IMethod method= (IMethod) element;
			int flags= method.getFlags();
			if (Flags.isPrivate(flags) || Flags.isStatic(flags) || 
method.isConstructor()) {
				return declaringType;
			}
			IMethod res= 
JavaModelUtil.findMethodDeclarationInHierarchy(hierarchy, declaringType, 
method.getElementName(), method.getParameterTypes(), false);
			if (res == null || method.equals(res)) {
				return declaringType;
			}
			return res.getDeclaringType();
		}
	}

	
	private class OutlineTreeViewer extends TreeViewer {
		
		private boolean fIsFiltering= false;

		private OutlineTreeViewer(Tree tree) {
			super(tree);
		}
		
		/**
		 * {@inheritDoc}
		 */
		protected Object[] getFilteredChildren(Object parent) {
			Object[] result = getRawChildren(parent);
			int unfilteredChildren= result.length;
			ViewerFilter[] filters = getFilters();
			if (filters != null) {
				for (int i= 0; i < filters.length; i++)
					result = filters[i].filter(this, 
parent, result);
			}
			fIsFiltering= unfilteredChildren != result.length;
			return result;
		}
		
		/**
		 * {@inheritDoc}
		 */
		protected void internalExpandToLevel(Widget node, int level) {
			if (!fIsFiltering && node instanceof Item) {
				Item i= (Item) node;
				if (i.getData() instanceof IJavaElement) {
					IJavaElement je= (IJavaElement) 
i.getData();
					if (je.getElementType() == 
IJavaElement.IMPORT_CONTAINER || isInnerType(je)) {
						setExpanded(i, false);
						return;
					}
				}
			}
			super.internalExpandToLevel(node, level);
		}
		
		private boolean isInnerType(IJavaElement element) {
			if (element != null && element.getElementType() == 
IJavaElement.TYPE) {
				IType type= (IType)element;
				try {
					return type.isMember();
				} catch (JavaModelException e) {
					IJavaElement parent= type.getParent();
					if (parent != null) {
						int parentElementType= 
parent.getElementType();
						return (parentElementType != 
IJavaElement.COMPILATION_UNIT && parentElementType != IJavaElement.CLASS_FILE);
					}
				}
			}
			return false;		
		}
	}
	
	
	private class OutlineContentProvider extends 
StandardJavaElementContentProvider {

		private boolean fShowInheritedMembers;

		/**
		 * Creates a new Outline content provider.
		 * 
		 * @param showInheritedMembers <code>true</code> iff inherited 
members are shown
		 */
		private OutlineContentProvider(boolean showInheritedMembers) {
			super(true);
			fShowInheritedMembers= showInheritedMembers;
		}
		
		public boolean isShowingInheritedMembers() {
			return fShowInheritedMembers;
		}
		
		public void toggleShowInheritedMembers() {
			Tree tree= getTreeViewer().getTree();
			
			tree.setRedraw(false);
			fShowInheritedMembers= !fShowInheritedMembers;
			getTreeViewer().refresh();
			getTreeViewer().expandToLevel(2);
			tree.setRedraw(true);
			
			// reveal selection
			Object selectedElement= getSelectedElement();
			if (selectedElement != null)
				getTreeViewer().reveal(selectedElement);
		}
		
		/**
		 * {@inheritDoc}
		 */
		public Object[] getChildren(Object element) {
			if (fShowOnlyMainType) {
				if (element instanceof ICompilationUnit) {
					element= getMainType((ICompilationUnit)
element);
				} else if (element instanceof IClassFile) {
					element= getMainType((IClassFile)
element);
				}

				if (element == null)
					return NO_CHILDREN;
			}
			
			if (fShowInheritedMembers && element instanceof IType) 
{
				IType type= (IType)element;
				if (type.getDeclaringType() == null) {
					ITypeHierarchy th= 
getSuperTypeHierarchy(type);
					if (th != null) {
						List children= new ArrayList();
						IType[] superClasses= 
th.getAllSupertypes(type);
						children.addAll(Arrays.asList
(super.getChildren(type)));
						for (int i= 0, scLength= 
superClasses.length; i < scLength; i++)
							children.addAll
(Arrays.asList(super.getChildren(superClasses[i])));
						return children.toArray();
					}
				}
			}
			return super.getChildren(element);
		}
		
		/**
		 * {@inheritDoc}
		 */
		public void inputChanged(Viewer viewer, Object oldInput, 
Object newInput) {
			super.inputChanged(viewer, oldInput, newInput);
			fTypeHierarchies.clear();
		}
		
		/**
		 * {@inheritDoc}
		 */
		public void dispose() {
			super.dispose();
			fTypeHierarchies.clear();
		}
		
		/**
		 * Returns the primary type of a compilation unit (has the same
		 * name as the compilation unit).
		 * 
		 * @param compilationUnit the compilation unit
		 * @return returns the primary type of the compilation unit, or
		 * <code>null</code> if is does not have one
		 */
		private IType getMainType(ICompilationUnit compilationUnit) {
			
			if (compilationUnit == null)
				return null;
			
			String name= compilationUnit.getElementName();
			int index= name.indexOf('.');
			if (index != -1)
				name= name.substring(0, index);
			IType type= compilationUnit.getType(name);
			return type.exists() ? type : null;
		}

		/**
		 * Returns the primary type of a class file.
		 * 
		 * @param classFile the class file
		 * @return returns the primary type of the class file, or 
<code>null</code>
		 * if is does not have one
		 */
		private IType getMainType(IClassFile classFile) {
			try {
				IType type= classFile.getType();
				return type != null && type.exists() ? type : 
null;
			} catch (JavaModelException e) {
				return null;	
			}
		}
	}
	
	
	private class ShowOnlyMainTypeAction extends Action {
		
		private static final String 
STORE_GO_INTO_TOP_LEVEL_TYPE_CHECKED= "GoIntoTopLevelTypeAction.isChecked"; //
$NON-NLS-1$
		
		private TreeViewer fOutlineViewer;

		private ShowOnlyMainTypeAction(TreeViewer outlineViewer) {
			super(TextMessages.getString
("JavaOutlineInformationControl.GoIntoTopLevelType.label"), 
IAction.AS_CHECK_BOX); //$NON-NLS-1$
			setToolTipText(TextMessages.getString
("JavaOutlineInformationControl.GoIntoTopLevelType.tooltip")); //$NON-NLS-1$
			setDescription(TextMessages.getString
("JavaOutlineInformationControl.GoIntoTopLevelType.description")); //$NON-NLS-1
$
			
			JavaPluginImages.setLocalImageDescriptors
(this, "gointo_toplevel_type.gif"); //$NON-NLS-1$
			
			WorkbenchHelp.setHelp(this, 
IJavaHelpContextIds.GO_INTO_TOP_LEVEL_TYPE_ACTION);
			
			fOutlineViewer= outlineViewer;

			boolean showclass= getDialogSettings().getBoolean
(STORE_GO_INTO_TOP_LEVEL_TYPE_CHECKED);
			setTopLevelTypeOnly(showclass);
		}

		/*
		 * @see org.eclipse.jface.action.Action#run()
		 */
		public void run() {
			setTopLevelTypeOnly(!fShowOnlyMainType);
		}

		private void setTopLevelTypeOnly(boolean show) {
			fShowOnlyMainType= show;
			setChecked(show);
			
			Tree tree= fOutlineViewer.getTree();
			tree.setRedraw(false);
			
			fOutlineViewer.refresh(false);
			if (!fShowOnlyMainType)
				fOutlineViewer.expandToLevel(2);
			
			tree.setRedraw(true);
			
			// reveal selection
			Object selectedElement= getSelectedElement();
			if (selectedElement != null)
				fOutlineViewer.reveal(selectedElement);
					
			getDialogSettings().put
(STORE_GO_INTO_TOP_LEVEL_TYPE_CHECKED, show);
		}
	}
	
	private class OutlineSorter extends ViewerSorter {

		private static final int OTHER= 1;
		private static final int CLASS= 2;
		private static final int INTERFACE= 3;
		private static final int ANONYM= 4;

		private JavaElementSorter fJavaElementSorter= new 
JavaElementSorter();
		
		/*
		 * @see org.eclipse.jface.viewers.ViewerSorter#sort
(org.eclipse.jface.viewers.Viewer, java.lang.Object[])
		 */
		public void sort(Viewer viewer, Object[] elements) {
			if (!fLexicalSortingAction.isChecked() && !
fSortByDefiningTypeAction.isChecked())
				return;
			
			super.sort(viewer, elements);
		}
		
		/*
		 * @see org.eclipse.jface.viewers.ViewerSorter#compare
(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
		 */
		public int compare(Viewer viewer, Object e1, Object e2) {
			int cat1= category(e1);
			int cat2= category(e2);

			if (cat1 != cat2)
				return cat1 - cat2;
			
			if (cat1 == OTHER) { // method or field
				if (fSortByDefiningTypeAction.isChecked()) {
					try {
						IType def1= (e1 instanceof 
IMethod) ? getDefiningType((IMethod) e1) : null;
						IType def2= (e2 instanceof 
IMethod) ? getDefiningType((IMethod) e2) : null;
						if (def1 != null) {
							if (def2 != null) {
								if (!
def2.equals(def1)) {
									return 
compareInHierarchy(getSuperTypeHierarchy(def1), def1, def2);
								}
							} else {
								return -1;
						
							}		
			
						} else {
							if (def2 != null) {
								return 1;
							}	
						}
					} catch (JavaModelException e) {
						// ignore, default to normal 
comparison
					}
				}
			} else if (cat1 == ANONYM) {
				return 0;
			}
			if (fLexicalSortingAction.isChecked())
				return fJavaElementSorter.compare(viewer, e1, 
e2); // use appearance preference page settings
			else
				return 0;
		}
		
		private IType getDefiningType(IMethod method) throws 
JavaModelException {
			IType declaringType= method.getDeclaringType();
			int flags= method.getFlags();
			if (Flags.isPrivate(flags) || Flags.isStatic(flags) || 
method.isConstructor()) {
				return null;
			}
		
			IMethod res= 
JavaModelUtil.findMethodDeclarationInHierarchy(getSuperTypeHierarchy
(declaringType), declaringType, method.getElementName(), 
method.getParameterTypes(), false);
			if (res == null || method.equals(res)) {
				return null;
			}
			return res.getDeclaringType();
		}

		/*
		 * @see org.eclipse.jface.viewers.ViewerSorter#category
(java.lang.Object)
		 */
		public int category(Object element) {
			if (element instanceof IType) {
				IType type= (IType) element;
				if (type.getElementName().length() == 0) {
					return ANONYM;
				}
				ITypeHierarchy hierarchy= getSuperTypeHierarchy
(type);
				if (hierarchy != null) {
					if (Flags.isInterface
(hierarchy.getCachedFlags((IType) element))) {
						return INTERFACE;
					} else {
						return CLASS;
					}
				}
			}
			return OTHER;
		}

		private int compareInHierarchy(ITypeHierarchy hierarchy, IType 
def1, IType def2) {
			if (isSuperType(hierarchy, def1, def2)) {
				return 1;
			} else if (isSuperType(hierarchy, def2, def1)) {
				return -1;
			}
			// interfaces after classes
			int flags1= hierarchy.getCachedFlags(def1);
			int flags2= hierarchy.getCachedFlags(def2);
			if (Flags.isInterface(flags1)) {
				if (!Flags.isInterface(flags2)) {
					return 1;
				}
			} else if (Flags.isInterface(flags2)) {
				return -1;
			}
			String name1= def1.getElementName();
			String name2= def2.getElementName();
			
			return getCollator().compare(name1, name2);
		}

		private boolean isSuperType(ITypeHierarchy hierarchy, IType 
def1, IType def2) {
			IType superType= hierarchy.getSuperclass(def1);
			if (superType != null) {
				if (superType.equals(def2) || isSuperType
(hierarchy, superType, def2)) {
					return true;
				}
			}
			IType[] superInterfaces= 
hierarchy.getAllSuperInterfaces(def1);
			for (int i= 0; i < superInterfaces.length; i++) {
				IType curr= superInterfaces[i];
				if (curr.equals(def2) || isSuperType
(hierarchy, curr, def2)) {
					return true;
				}		
			}
			return false;
		}
	}
	
	
	private class LexicalSortingAction extends Action {
		
		private static final String 
STORE_LEXICAL_SORTING_CHECKED= "LexicalSortingAction.isChecked"; //$NON-NLS-1$
		
		private TreeViewer fOutlineViewer;

		private LexicalSortingAction(TreeViewer outlineViewer) {
			super(TextMessages.getString
("JavaOutlineInformationControl.LexicalSortingAction.label"), 
IAction.AS_CHECK_BOX); //$NON-NLS-1$
			setToolTipText(TextMessages.getString
("JavaOutlineInformationControl.LexicalSortingAction.tooltip")); //$NON-NLS-1$
			setDescription(TextMessages.getString
("JavaOutlineInformationControl.LexicalSortingAction.description")); //$NON-
NLS-1$
			
			JavaPluginImages.setLocalImageDescriptors
(this, "alphab_sort_co.gif"); //$NON-NLS-1$
			
			fOutlineViewer= outlineViewer;
			
			boolean checked=getDialogSettings().getBoolean
(STORE_LEXICAL_SORTING_CHECKED);
			setChecked(checked);
			WorkbenchHelp.setHelp(this, 
IJavaHelpContextIds.LEXICAL_SORTING_BROWSING_ACTION);
		}

		public void run() {
			valueChanged(isChecked(), true);
		}

		private void valueChanged(final boolean on, boolean store) {
			setChecked(on);
			BusyIndicator.showWhile(fOutlineViewer.getControl
().getDisplay(), new Runnable() {
				public void run() {
					fOutlineViewer.refresh(false);
				}
			});
			
			if (store)
				getDialogSettings().put
(STORE_LEXICAL_SORTING_CHECKED, on);
		}
	}


	private class SortByDefiningTypeAction extends Action {
		
		private static final String 
STORE_SORT_BY_DEFINING_TYPE_CHECKED= "SortByDefiningType.isChecked"; //$NON-
NLS-1$
		
		private TreeViewer fOutlineViewer;
		
		/** 
		 * Creates the action.
		 */
		private SortByDefiningTypeAction(TreeViewer outlineViewer) {
			super(TextMessages.getString
("JavaOutlineInformationControl.SortByDefiningTypeAction.label")); //$NON-NLS-1
$
			setDescription(TextMessages.getString
("JavaOutlineInformationControl.SortByDefiningTypeAction.description")); //
$NON-NLS-1$
			setToolTipText(TextMessages.getString
("JavaOutlineInformationControl.SortByDefiningTypeAction.tooltip")); //$NON-
NLS-1$
			
			JavaPluginImages.setLocalImageDescriptors
(this, "definingtype_sort_co.gif"); //$NON-NLS-1$
			
			fOutlineViewer= outlineViewer;
			
			WorkbenchHelp.setHelp(this, 
IJavaHelpContextIds.SORT_BY_DEFINING_TYPE_ACTION);
	 
			boolean state= getDialogSettings().getBoolean
(STORE_SORT_BY_DEFINING_TYPE_CHECKED);
			setChecked(state);
			fInnerLabelProvider.setShowDefiningType(state);
		}
		
		/*
		 * @see Action#actionPerformed
		 */	
		public void run() {
			BusyIndicator.showWhile(fOutlineViewer.getControl
().getDisplay(), new Runnable() {
				public void run() {
					fInnerLabelProvider.setShowDefiningType
(isChecked());
					getDialogSettings().put
(STORE_SORT_BY_DEFINING_TYPE_CHECKED, isChecked());
					
					fOutlineViewer.refresh(true);
					
					// reveal selection
					Object selectedElement= 
getSelectedElement();
					if (selectedElement != null)
						fOutlineViewer.reveal
(selectedElement);
				}
			});		
		}	
	}
	

	/**
	 * Creates a new Java outline information control.
	 * 
	 * @param parent
	 * @param shellStyle
	 * @param treeStyle
	 * @param commandId
	 */
	public JavaOutlineInformationControl(Shell parent, int shellStyle, int 
treeStyle, String commandId) {
		super(parent, shellStyle, treeStyle, commandId, true);
	}

	/**
	 * {@inheritDoc}
	 */
	protected Text createFilterText(Composite parent) {
		Text text= super.createFilterText(parent);
		text.addKeyListener(getKeyAdapter());
		return text;
	}

	/**
	 * {@inheritDoc}
	 */
	protected TreeViewer createTreeViewer(Composite parent, int style) {
		Tree tree= new Tree(parent, SWT.SINGLE | (style & ~SWT.MULTI));
		tree.setLayoutData(new GridData(GridData.FILL_BOTH));
	
		final TreeViewer treeViewer= new OutlineTreeViewer(tree);
	
		// Hide import declarations but show the container
		treeViewer.addFilter(new ViewerFilter() {
			public boolean select(Viewer viewer, Object 
parentElement, Object element) {
				return !(element instanceof 
IImportDeclaration);
			}
		});
		
		// Hard-coded filters
		treeViewer.addFilter(new NamePatternFilter());
		treeViewer.addFilter(new MemberFilter());

		fForegroundColor= parent.getDisplay().getSystemColor
(SWT.COLOR_DARK_GRAY);
		fInnerLabelProvider= new OutlineLabelProvider();
		
		fLexicalSortingAction= new LexicalSortingAction(treeViewer);
		fSortByDefiningTypeAction= new SortByDefiningTypeAction
(treeViewer);
		fShowOnlyMainTypeAction= new ShowOnlyMainTypeAction
(treeViewer);
		
		fOutlineContentProvider= new OutlineContentProvider(false);
		treeViewer.setContentProvider(fOutlineContentProvider);
		fOutlineSorter= new OutlineSorter();
		treeViewer.setSorter(fOutlineSorter);
		treeViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS);
		
		
		treeViewer.setLabelProvider(new DecoratingJavaLabelProvider
(fInnerLabelProvider));
		treeViewer.getTree().addKeyListener(getKeyAdapter());
		
		return treeViewer;
	}

	/**
	 * {@inheritDoc}
	 */
	protected String getStatusFieldText() {
		KeySequence[] sequences= getInvokingCommandKeySequences();
		if (sequences == null || sequences.length == 0)
			return ""; //$NON-NLS-1$
		
		String keySequence= sequences[0].format();
		
		if (fOutlineContentProvider.isShowingInheritedMembers())
			return JavaUIMessages.getFormattedString
("JavaOutlineControl.statusFieldText.hideInheritedMembers", keySequence); //
$NON-NLS-1$
		else
			return JavaUIMessages.getFormattedString
("JavaOutlineControl.statusFieldText.showInheritedMembers", keySequence); //
$NON-NLS-1$
	}
	
	/*
	 * @see 
org.eclipse.jdt.internal.ui.text.AbstractInformationControl#getId()
	 * @since 3.0
	 */
	protected String getId() {
		return "org.eclipse.jdt.internal.ui.text.QuickOutline"; //$NON-
NLS-1$
	}

	/**
	 * {@inheritDoc}
	 */
	public void setInput(Object information) {
		if (information == null || information instanceof String) {
			inputChanged(null, null);
			return;
		}
		IJavaElement je= (IJavaElement)information;
		ICompilationUnit cu= (ICompilationUnit)je.getAncestor
(IJavaElement.COMPILATION_UNIT);
		if (cu != null)
			fInput= cu;
		else
			fInput= je.getAncestor(IJavaElement.CLASS_FILE);
			
		inputChanged(fInput, information);
	}
	
	private KeyAdapter getKeyAdapter() {
		if (fKeyAdapter == null) {
			fKeyAdapter= new KeyAdapter() {
				public void keyPressed(KeyEvent e) {
					int accelerator = 
SWTKeySupport.convertEventToUnmodifiedAccelerator(e);
					KeySequence keySequence = 
KeySequence.getInstance(SWTKeySupport.convertAcceleratorToKeyStroke
(accelerator));
					KeySequence[] sequences= 
getInvokingCommandKeySequences();
					if (sequences == null)
						return;
					for (int i= 0; i < sequences.length; 
i++) {
						if (sequences[i].equals
(keySequence)) {
							e.doit= false;
						
	toggleShowInheritedMembers();
							return;
						}
					}
				}
			};			
		}
		return fKeyAdapter;		
	}
	
	/**
	 * {@inheritDoc}
	 */
	protected void handleStatusFieldClicked() {
		toggleShowInheritedMembers();
	}

	protected void toggleShowInheritedMembers() {
		int flags= AppearanceAwareLabelProvider.DEFAULT_TEXTFLAGS |  
JavaElementLabels.F_APP_TYPE_SIGNATURE;
		if (!fOutlineContentProvider.isShowingInheritedMembers())
			flags |= JavaElementLabels.ALL_POST_QUALIFIED;
		fInnerLabelProvider.setTextFlags(flags);
		fOutlineContentProvider.toggleShowInheritedMembers();
		updateStatusFieldText();
	}
	
	/*
	 * @see 
org.eclipse.jdt.internal.ui.text.AbstractInformationControl#fillViewMenu
(org.eclipse.jface.action.IMenuManager)
	 */
	protected void fillViewMenu(IMenuManager viewMenu) {
		super.fillViewMenu(viewMenu);
		viewMenu.add(fShowOnlyMainTypeAction); //$NON-NLS-1$

		viewMenu.add(new Separator("Sorters")); //$NON-NLS-1$
		viewMenu.add(fLexicalSortingAction);
		
		viewMenu.add(fSortByDefiningTypeAction);
	}
	
	private ITypeHierarchy getSuperTypeHierarchy(IType type) {
		ITypeHierarchy th= (ITypeHierarchy)fTypeHierarchies.get(type);
		if (th == null) {
			try {
				th= SuperTypeHierarchyCache.getTypeHierarchy
(type, getProgressMonitor());
			} catch (JavaModelException e) {
				return null;
			}
			fTypeHierarchies.put(type, th);
		}
		return th;
	}
	
	private IProgressMonitor getProgressMonitor() {
		IWorkbenchPage wbPage= JavaPlugin.getActivePage();
		if (wbPage == null)
			return null;
		
		IEditorPart editor= wbPage.getActiveEditor();
		if (editor == null)
			return null;
		
		return editor.getEditorSite().getActionBars
().getStatusLineManager().getProgressMonitor();			
	}
}
Comment 10 Tod Creasey CLA 2004-04-20 13:55:35 EDT
The problem was that tree updates were not forcing label updates from the 
decoration scheduler.

Winner of toughest Bug so far of M9 <grin>....

Fixed in build >20040420
Comment 11 Dani Megert CLA 2004-04-22 11:35:17 EDT
Tod,

will this also fix the problem that the items flicker when changing the filter
text? I remember that besides what's reported in this bug decorations were going
away and coming back during typing in the filter field. This problem is gone now
that we don't use decorators.


Comment 12 Tod Creasey CLA 2004-04-22 11:43:09 EDT
Yes - it was fixing the flicker that exposed this problem.
Comment 13 Dani Megert CLA 2004-04-29 06:48:58 EDT
Tod, the bug has been fixed but it still flickers when e.g. CVS decorators are
enabled. To test:

1. in JavaOutlineInformationControl.createTreeViewer replace:
		
fInnerLabelProvider.addLabelDecorator(newProblemsLabelDecorator(null));
fInnerLabelProvider.addLabelDecorator(new verrideIndicatorLabelDecorator(null));
treeViewer.setLabelProvider(fInnerLabelProvider);

with:
treeViewer.setLabelProvider(new DecoratingJavaLabelProvider(fInnerLabelProvider));


2. start the workbench
3. enable CVS decorators
4. open a type from a CVS shared project
5. press Ctrl+O -> you should see the CVS decorator in the quick outline
6. start filtering by simply typing the top level type's name
observe: decorators of the CU come and go
Comment 14 Tod Creasey CLA 2004-04-29 09:08:09 EDT
Reopening to see if there is anything we can do about the flicker.

Dani if you use only fast decorators (anything but CVS) does this still 
happen? It may be a factor of the computation time.
Comment 15 Dani Megert CLA 2004-04-29 09:34:03 EDT
You also see it for non-cvs decorators: e.g. proceed as described in comment 13,
 enable override decorator and then open ArrayList using Ctrl+O.
Comment 16 Tod Creasey CLA 2004-04-30 09:34:39 EDT
*** Bug 58866 has been marked as a duplicate of this bug. ***
Comment 17 Tod Creasey CLA 2004-05-26 09:35:34 EDT
*** Bug 60527 has been marked as a duplicate of this bug. ***
Comment 18 Dani Megert CLA 2007-06-07 03:33:40 EDT
This is not minor, depending on how many items you have in the Outline and given the duplicate bug reports we receive over time.

See also bug 118996 and bug 191355.
Comment 19 Boris Bokowski CLA 2008-05-02 14:56:25 EDT
Mass update - removing 3.4 target. This was one of the bugs I marked for investigation (and potential fixing) in 3.4 but I ran out of time. Please ping on the bug if fixing it would be really important for 3.4, and does not require API changes or feature work.
Comment 20 Boris Bokowski CLA 2009-11-26 09:51:03 EST
Hitesh is now responsible for watching bugs in the [Viewers] component area.
Comment 21 Lars Vogel CLA 2018-11-15 06:33:17 EST
*** Bug 198884 has been marked as a duplicate of this bug. ***
Comment 22 Eclipse Genie CLA 2020-11-05 14:06:24 EST
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. As such, we're closing this bug.

If you have further information on the current state of the bug, please add it and reopen this bug. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.