X-Git-Url: http://secure.phpeclipse.com diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaOutlineInformationControl.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaOutlineInformationControl.java new file mode 100644 index 0000000..badd6d4 --- /dev/null +++ b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/JavaOutlineInformationControl.java @@ -0,0 +1,640 @@ +/******************************************************************************* + * 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 net.sourceforge.phpdt.internal.ui.text; + +import net.sourceforge.phpdt.core.ICompilationUnit; +import net.sourceforge.phpdt.core.IJavaElement; +import net.sourceforge.phpdt.core.IParent; +import net.sourceforge.phpdt.core.JavaModelException; +import net.sourceforge.phpdt.internal.ui.actions.OpenActionUtil; +import net.sourceforge.phpdt.internal.ui.util.StringMatcher; +import net.sourceforge.phpdt.internal.ui.viewsupport.AppearanceAwareLabelProvider; +import net.sourceforge.phpdt.internal.ui.viewsupport.DecoratingJavaLabelProvider; +import net.sourceforge.phpdt.internal.ui.viewsupport.JavaElementLabels; +import net.sourceforge.phpdt.ui.JavaElementSorter; +import net.sourceforge.phpdt.ui.StandardJavaElementContentProvider; +import net.sourceforge.phpeclipse.ui.WebUI; +//import net.sourceforge.phpeclipse.PHPeclipsePlugin; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.text.IInformationControl; +import org.eclipse.jface.text.IInformationControlExtension; +import org.eclipse.jface.text.IInformationControlExtension2; +import org.eclipse.jface.viewers.AbstractTreeViewer; +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.FontMetrics; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +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.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Layout; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; + +/** + * @author dmegert + * + * To change this generated comment edit the template variable "typecomment": + * Window>Preferences>Java>Templates. To enable and disable the creation of type + * comments go to Window>Preferences>Java>Code Generation. + */ +public class JavaOutlineInformationControl implements IInformationControl, + IInformationControlExtension, IInformationControlExtension2 { + + /** + * The NamePatternFilter selects the elements which match the given string + * patterns. + *

+ * The following characters have special meaning: ? => any character * => + * any string + *

+ * + * @since 2.0 + */ + private static class NamePatternFilter extends ViewerFilter { + private String fPattern; + + private StringMatcher fMatcher; + + private ILabelProvider fLabelProvider; + + private Viewer fViewer; + + private StringMatcher getMatcher() { + return fMatcher; + } + + /* + * (non-Javadoc) Method declared on ViewerFilter. + */ + public boolean select(Viewer viewer, Object parentElement, + Object element) { + if (fMatcher == null) + return true; + + ILabelProvider labelProvider = getLabelProvider(viewer); + + String matchName = null; + if (labelProvider != null) + matchName = ((ILabelProvider) labelProvider).getText(element); + else if (element instanceof IJavaElement) + matchName = ((IJavaElement) element).getElementName(); + + if (matchName != null && fMatcher.match(matchName)) + return true; + + return hasUnfilteredChild(viewer, element); + } + + private ILabelProvider getLabelProvider(Viewer viewer) { + if (fViewer == viewer) + return fLabelProvider; + + fLabelProvider = null; + IBaseLabelProvider baseLabelProvider = null; + if (viewer instanceof StructuredViewer) + baseLabelProvider = ((StructuredViewer) viewer) + .getLabelProvider(); + + if (baseLabelProvider instanceof ILabelProvider) + fLabelProvider = (ILabelProvider) baseLabelProvider; + + return fLabelProvider; + } + + private boolean hasUnfilteredChild(Viewer viewer, Object element) { + IJavaElement[] children; + if (element instanceof IParent) { + try { + children = ((IParent) element).getChildren(); + } catch (JavaModelException ex) { + return false; + } + for (int i = 0; i < children.length; i++) + if (select(viewer, element, children[i])) + return true; + } + return false; + } + + /** + * Sets the patterns to filter out for the receiver. + *

+ * The following characters have special meaning: ? => any character * => + * any string + *

+ */ + public void setPattern(String pattern) { + fPattern = pattern; + if (fPattern == null) { + fMatcher = null; + return; + } + boolean ignoreCase = pattern.toLowerCase().equals(pattern); + fMatcher = new StringMatcher(pattern, ignoreCase, false); + } + } + + private static class BorderFillLayout extends Layout { + + /** The border widths. */ + final int fBorderSize; + + /** + * Creates a fill layout with a border. + */ + public BorderFillLayout(int borderSize) { + if (borderSize < 0) + throw new IllegalArgumentException(); + fBorderSize = borderSize; + } + + /** + * Returns the border size. + */ + public int getBorderSize() { + return fBorderSize; + } + + /* + * @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite, + * int, int, boolean) + */ + protected Point computeSize(Composite composite, int wHint, int hHint, + boolean flushCache) { + + Control[] children = composite.getChildren(); + Point minSize = new Point(0, 0); + + if (children != null) { + for (int i = 0; i < children.length; i++) { + Point size = children[i].computeSize(wHint, hHint, + flushCache); + minSize.x = Math.max(minSize.x, size.x); + minSize.y = Math.max(minSize.y, size.y); + } + } + + minSize.x += fBorderSize * 2 + RIGHT_MARGIN; + minSize.y += fBorderSize * 2; + + return minSize; + } + + /* + * @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, + * boolean) + */ + protected void layout(Composite composite, boolean flushCache) { + + Control[] children = composite.getChildren(); + Point minSize = new Point(composite.getClientArea().width, + composite.getClientArea().height); + + if (children != null) { + for (int i = 0; i < children.length; i++) { + Control child = children[i]; + child.setSize(minSize.x - fBorderSize * 2, minSize.y + - fBorderSize * 2); + child.setLocation(fBorderSize, fBorderSize); + } + } + } + } + + /** Border thickness in pixels. */ + private static final int BORDER = 1; + + /** Right margin in pixels. */ + private static final int RIGHT_MARGIN = 3; + + /** The control's shell */ + private Shell fShell; + + /** The composite */ + Composite fComposite; + + /** The control's text widget */ + private Text fFilterText; + + /** The control's tree widget */ + private TreeViewer fTreeViewer; + + /** The control width constraint */ + private int fMaxWidth = -1; + + /** The control height constraint */ + private int fMaxHeight = -1; + + private StringMatcher fStringMatcher; + + /** + * Creates a tree information control with the given shell as parent. The + * given style is applied to the tree widget. + * + * @param parent + * the parent shell + * @param style + * the additional styles for the tree widget + */ + public JavaOutlineInformationControl(Shell parent, int style) { + this(parent, SWT.RESIZE, style); + } + + /** + * Creates a tree information control with the given shell as parent. No + * additional styles are applied. + * + * @param parent + * the parent shell + */ + public JavaOutlineInformationControl(Shell parent) { + this(parent, SWT.NONE); + } + + /** + * Creates a tree information control with the given shell as parent. The + * given styles are applied to the shell and the tree widget. + * + * @param parent + * the parent shell + * @param shellStyle + * the additional styles for the shell + * @param treeStyle + * the additional styles for the tree widget + */ + public JavaOutlineInformationControl(Shell parent, int shellStyle, + int treeStyle) { + fShell = new Shell(parent, shellStyle); + Display display = fShell.getDisplay(); + fShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); + + // Composite for filter text and tree + fComposite = new Composite(fShell, SWT.RESIZE); + GridLayout layout = new GridLayout(1, false); + fComposite.setLayout(layout); + fComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + createFilterText(fComposite); + createTreeViewer(fComposite, treeStyle); + + int border = ((shellStyle & SWT.NO_TRIM) == 0) ? 0 : BORDER; + fShell.setLayout(new BorderFillLayout(border)); + + setInfoSystemColor(); + installFilter(); + } + + private void createTreeViewer(Composite parent, int style) { + Tree tree = new Tree(parent, SWT.SINGLE | (style & ~SWT.MULTI)); + GridData data = new GridData(GridData.FILL_BOTH); + tree.setLayoutData(data); + + fTreeViewer = new TreeViewer(tree); + + // Hide import declartions but show the container + // fTreeViewer.addFilter(new ViewerFilter() { + // public boolean select(Viewer viewer, Object parentElement, Object + // element) { + // return !(element instanceof IImportDeclaration); + // } + // }); + + fTreeViewer.setContentProvider(new StandardJavaElementContentProvider( + true, true)); + fTreeViewer.setSorter(new JavaElementSorter()); + fTreeViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS); + + AppearanceAwareLabelProvider lprovider = new AppearanceAwareLabelProvider( + AppearanceAwareLabelProvider.DEFAULT_TEXTFLAGS + | JavaElementLabels.F_APP_TYPE_SIGNATURE, + AppearanceAwareLabelProvider.DEFAULT_IMAGEFLAGS); + fTreeViewer + .setLabelProvider(new DecoratingJavaLabelProvider(lprovider)); + + fTreeViewer.getTree().addKeyListener(new KeyListener() { + public void keyPressed(KeyEvent e) { + if (e.character == 0x1B) // ESC + dispose(); + } + + public void keyReleased(KeyEvent e) { + // do nothing + } + }); + + fTreeViewer.getTree().addSelectionListener(new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + // do nothing + } + + public void widgetDefaultSelected(SelectionEvent e) { + gotoSelectedElement(); + } + }); + } + + private Text createFilterText(Composite parent) { + fFilterText = new Text(parent, SWT.FLAT); + + GridData data = new GridData(); + GC gc = new GC(parent); + gc.setFont(parent.getFont()); + FontMetrics fontMetrics = gc.getFontMetrics(); + gc.dispose(); + + data.heightHint = org.eclipse.jface.dialogs.Dialog + .convertHeightInCharsToPixels(fontMetrics, 1); + data.horizontalAlignment = GridData.FILL; + data.verticalAlignment = GridData.BEGINNING; + fFilterText.setLayoutData(data); + + fFilterText.addKeyListener(new KeyListener() { + public void keyPressed(KeyEvent e) { + if (e.keyCode == 0x0D) // return + gotoSelectedElement(); + if (e.keyCode == SWT.ARROW_DOWN) + fTreeViewer.getTree().setFocus(); + if (e.keyCode == SWT.ARROW_UP) + fTreeViewer.getTree().setFocus(); + if (e.character == 0x1B) // ESC + dispose(); + } + + public void keyReleased(KeyEvent e) { + // do nothing + } + }); + + // Horizonral separator line + Label separator = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL + | SWT.LINE_DOT); + separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + return fFilterText; + } + + private void setInfoSystemColor() { + Display display = fShell.getDisplay(); + setForegroundColor(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); + setBackgroundColor(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); + } + + private void installFilter() { + final NamePatternFilter viewerFilter = new NamePatternFilter(); + fTreeViewer.addFilter(viewerFilter); + fFilterText.setText(""); //$NON-NLS-1$ + + fFilterText.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + String pattern = fFilterText.getText(); + if (pattern != null) { + int length = pattern.length(); + if (length == 0) + pattern = null; + else if (pattern.charAt(length - 1) != '*') + pattern = pattern + '*'; + } else + pattern = null; + viewerFilter.setPattern(pattern); + fStringMatcher = viewerFilter.getMatcher(); + fTreeViewer.getControl().setRedraw(false); + fTreeViewer.refresh(); + fTreeViewer.expandAll(); + selectFirstMatch(); + fTreeViewer.getControl().setRedraw(true); + } + }); + } + + private void gotoSelectedElement() { + Object selectedElement = ((IStructuredSelection) fTreeViewer + .getSelection()).getFirstElement(); + if (selectedElement != null) { + try { + dispose(); + OpenActionUtil.open(selectedElement, true); + } catch (CoreException ex) { + WebUI.log(ex); + } + } + } + + /** + * Selects the first element in the tree which matches the current filter + * pattern. + */ + private void selectFirstMatch() { + Tree tree = fTreeViewer.getTree(); + Object element = findElement(tree.getItems()); + if (element != null) + fTreeViewer.setSelection(new StructuredSelection(element), true); + else + fTreeViewer.setSelection(StructuredSelection.EMPTY); + } + + private IJavaElement findElement(TreeItem[] items) { + ILabelProvider labelProvider = (ILabelProvider) fTreeViewer + .getLabelProvider(); + for (int i = 0; i < items.length; i++) { + IJavaElement element = (IJavaElement) items[i].getData(); + if (fStringMatcher == null) + return element; + + if (element != null) { + String label = labelProvider.getText(element); + if (fStringMatcher.match(label)) + return element; + } + + element = findElement(items[i].getItems()); + if (element != null) + return element; + } + return null; + } + + /* + * @see IInformationControl#setInformation(String) + */ + public void setInformation(String information) { + // this method is ignored, see IInformationControlExtension2 + } + + /* + * @see IInformationControlExtension2#setInput(Object) + */ + public void setInput(Object information) { + fFilterText.setText(""); //$NON-NLS-1$ + if (information == null || information instanceof String) { + setInput(null); + return; + } + IJavaElement je = (IJavaElement) information; + IJavaElement sel = null; + ICompilationUnit cu = (ICompilationUnit) je + .getAncestor(IJavaElement.COMPILATION_UNIT); + if (cu != null) + sel = cu; + else + sel = je.getAncestor(IJavaElement.CLASS_FILE); + fTreeViewer.setInput(sel); + fTreeViewer.setSelection(new StructuredSelection(information)); + } + + /* + * @see IInformationControl#setVisible(boolean) + */ + public void setVisible(boolean visible) { + fShell.setVisible(visible); + } + + /* + * @see IInformationControl#dispose() + */ + public void dispose() { + if (fShell != null) { + if (!fShell.isDisposed()) + fShell.dispose(); + fShell = null; + fTreeViewer = null; + fComposite = null; + fFilterText = null; + } + } + + /* + * @see org.eclipse.jface.text.IInformationControlExtension#hasContents() + */ + public boolean hasContents() { + return fTreeViewer != null && fTreeViewer.getInput() != null; + } + + /* + * @see org.eclipse.jface.text.IInformationControl#setSizeConstraints(int, + * int) + */ + public void setSizeConstraints(int maxWidth, int maxHeight) { + fMaxWidth = maxWidth; + fMaxHeight = maxHeight; + } + + /* + * @see org.eclipse.jface.text.IInformationControl#computeSizeHint() + */ + public Point computeSizeHint() { + return fShell.computeSize(SWT.DEFAULT, SWT.DEFAULT); + } + + /* + * @see IInformationControl#setLocation(Point) + */ + public void setLocation(Point location) { + Rectangle trim = fShell.computeTrim(0, 0, 0, 0); + Point textLocation = fComposite.getLocation(); + location.x += trim.x - textLocation.x; + location.y += trim.y - textLocation.y; + fShell.setLocation(location); + } + + /* + * @see IInformationControl#setSize(int, int) + */ + public void setSize(int width, int height) { + fShell.setSize(width, height); + } + + /* + * @see IInformationControl#addDisposeListener(DisposeListener) + */ + public void addDisposeListener(DisposeListener listener) { + fShell.addDisposeListener(listener); + } + + /* + * @see IInformationControl#removeDisposeListener(DisposeListener) + */ + public void removeDisposeListener(DisposeListener listener) { + fShell.removeDisposeListener(listener); + } + + /* + * @see IInformationControl#setForegroundColor(Color) + */ + public void setForegroundColor(Color foreground) { + fTreeViewer.getTree().setForeground(foreground); + fFilterText.setForeground(foreground); + fComposite.setForeground(foreground); + } + + /* + * @see IInformationControl#setBackgroundColor(Color) + */ + public void setBackgroundColor(Color background) { + fTreeViewer.getTree().setBackground(background); + fFilterText.setBackground(background); + fComposite.setBackground(background); + } + + /* + * @see IInformationControl#isFocusControl() + */ + public boolean isFocusControl() { + return fTreeViewer.getControl().isFocusControl() + || fFilterText.isFocusControl(); + } + + /* + * @see IInformationControl#setFocus() + */ + public void setFocus() { + fShell.forceFocus(); + fFilterText.setFocus(); + } + + /* + * @see IInformationControl#addFocusListener(FocusListener) + */ + public void addFocusListener(FocusListener listener) { + fShell.addFocusListener(listener); + } + + /* + * @see IInformationControl#removeFocusListener(FocusListener) + */ + public void removeFocusListener(FocusListener listener) { + fShell.removeFocusListener(listener); + } +}