1) Moved net.sourceforge.phpeclipse.ui\src\net\sourceforge\phpdt back to net.sourcefo...
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / text / JavaOutlineInformationControl.java
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/JavaOutlineInformationControl.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/JavaOutlineInformationControl.java
new file mode 100644 (file)
index 0000000..b99ee96
--- /dev/null
@@ -0,0 +1,639 @@
+/*******************************************************************************
+ * 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.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.
+        * <p>
+        * The following characters have special meaning: ? => any character * =>
+        * any string
+        * </p>
+        * 
+        * @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.
+                * <p>
+                * The following characters have special meaning: ? => any character * =>
+                * any string
+                * </p>
+                */
+               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) {
+                               PHPeclipsePlugin.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);
+       }
+}