1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.ui.text;
13 import net.sourceforge.phpdt.core.ICompilationUnit;
14 import net.sourceforge.phpdt.core.IJavaElement;
15 import net.sourceforge.phpdt.core.IParent;
16 import net.sourceforge.phpdt.core.JavaModelException;
17 import net.sourceforge.phpdt.internal.ui.actions.OpenActionUtil;
18 import net.sourceforge.phpdt.internal.ui.util.StringMatcher;
19 import net.sourceforge.phpdt.internal.ui.viewsupport.AppearanceAwareLabelProvider;
20 import net.sourceforge.phpdt.internal.ui.viewsupport.DecoratingJavaLabelProvider;
21 import net.sourceforge.phpdt.internal.ui.viewsupport.JavaElementLabels;
22 import net.sourceforge.phpdt.ui.JavaElementSorter;
23 import net.sourceforge.phpdt.ui.StandardJavaElementContentProvider;
24 import net.sourceforge.phpeclipse.ui.WebUI;
25 //import net.sourceforge.phpeclipse.PHPeclipsePlugin;
27 import org.eclipse.core.runtime.CoreException;
28 import org.eclipse.jface.text.IInformationControl;
29 import org.eclipse.jface.text.IInformationControlExtension;
30 import org.eclipse.jface.text.IInformationControlExtension2;
31 import org.eclipse.jface.viewers.AbstractTreeViewer;
32 import org.eclipse.jface.viewers.IBaseLabelProvider;
33 import org.eclipse.jface.viewers.ILabelProvider;
34 import org.eclipse.jface.viewers.IStructuredSelection;
35 import org.eclipse.jface.viewers.StructuredSelection;
36 import org.eclipse.jface.viewers.StructuredViewer;
37 import org.eclipse.jface.viewers.TreeViewer;
38 import org.eclipse.jface.viewers.Viewer;
39 import org.eclipse.jface.viewers.ViewerFilter;
40 import org.eclipse.swt.SWT;
41 import org.eclipse.swt.events.DisposeListener;
42 import org.eclipse.swt.events.FocusListener;
43 import org.eclipse.swt.events.KeyEvent;
44 import org.eclipse.swt.events.KeyListener;
45 import org.eclipse.swt.events.ModifyEvent;
46 import org.eclipse.swt.events.ModifyListener;
47 import org.eclipse.swt.events.SelectionEvent;
48 import org.eclipse.swt.events.SelectionListener;
49 import org.eclipse.swt.graphics.Color;
50 import org.eclipse.swt.graphics.FontMetrics;
51 import org.eclipse.swt.graphics.GC;
52 import org.eclipse.swt.graphics.Point;
53 import org.eclipse.swt.graphics.Rectangle;
54 import org.eclipse.swt.layout.GridData;
55 import org.eclipse.swt.layout.GridLayout;
56 import org.eclipse.swt.widgets.Composite;
57 import org.eclipse.swt.widgets.Control;
58 import org.eclipse.swt.widgets.Display;
59 import org.eclipse.swt.widgets.Label;
60 import org.eclipse.swt.widgets.Layout;
61 import org.eclipse.swt.widgets.Shell;
62 import org.eclipse.swt.widgets.Text;
63 import org.eclipse.swt.widgets.Tree;
64 import org.eclipse.swt.widgets.TreeItem;
69 * To change this generated comment edit the template variable "typecomment":
70 * Window>Preferences>Java>Templates. To enable and disable the creation of type
71 * comments go to Window>Preferences>Java>Code Generation.
73 public class JavaOutlineInformationControl implements IInformationControl,
74 IInformationControlExtension, IInformationControlExtension2 {
77 * The NamePatternFilter selects the elements which match the given string
80 * The following characters have special meaning: ? => any character * =>
86 private static class NamePatternFilter extends ViewerFilter {
87 private String fPattern;
89 private StringMatcher fMatcher;
91 private ILabelProvider fLabelProvider;
93 private Viewer fViewer;
95 private StringMatcher getMatcher() {
100 * (non-Javadoc) Method declared on ViewerFilter.
102 public boolean select(Viewer viewer, Object parentElement,
104 if (fMatcher == null)
107 ILabelProvider labelProvider = getLabelProvider(viewer);
109 String matchName = null;
110 if (labelProvider != null)
111 matchName = ((ILabelProvider) labelProvider).getText(element);
112 else if (element instanceof IJavaElement)
113 matchName = ((IJavaElement) element).getElementName();
115 if (matchName != null && fMatcher.match(matchName))
118 return hasUnfilteredChild(viewer, element);
121 private ILabelProvider getLabelProvider(Viewer viewer) {
122 if (fViewer == viewer)
123 return fLabelProvider;
125 fLabelProvider = null;
126 IBaseLabelProvider baseLabelProvider = null;
127 if (viewer instanceof StructuredViewer)
128 baseLabelProvider = ((StructuredViewer) viewer)
131 if (baseLabelProvider instanceof ILabelProvider)
132 fLabelProvider = (ILabelProvider) baseLabelProvider;
134 return fLabelProvider;
137 private boolean hasUnfilteredChild(Viewer viewer, Object element) {
138 IJavaElement[] children;
139 if (element instanceof IParent) {
141 children = ((IParent) element).getChildren();
142 } catch (JavaModelException ex) {
145 for (int i = 0; i < children.length; i++)
146 if (select(viewer, element, children[i]))
153 * Sets the patterns to filter out for the receiver.
155 * The following characters have special meaning: ? => any character * =>
159 public void setPattern(String pattern) {
161 if (fPattern == null) {
165 boolean ignoreCase = pattern.toLowerCase().equals(pattern);
166 fMatcher = new StringMatcher(pattern, ignoreCase, false);
170 private static class BorderFillLayout extends Layout {
172 /** The border widths. */
173 final int fBorderSize;
176 * Creates a fill layout with a border.
178 public BorderFillLayout(int borderSize) {
180 throw new IllegalArgumentException();
181 fBorderSize = borderSize;
185 * Returns the border size.
187 public int getBorderSize() {
192 * @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite,
195 protected Point computeSize(Composite composite, int wHint, int hHint,
196 boolean flushCache) {
198 Control[] children = composite.getChildren();
199 Point minSize = new Point(0, 0);
201 if (children != null) {
202 for (int i = 0; i < children.length; i++) {
203 Point size = children[i].computeSize(wHint, hHint,
205 minSize.x = Math.max(minSize.x, size.x);
206 minSize.y = Math.max(minSize.y, size.y);
210 minSize.x += fBorderSize * 2 + RIGHT_MARGIN;
211 minSize.y += fBorderSize * 2;
217 * @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite,
220 protected void layout(Composite composite, boolean flushCache) {
222 Control[] children = composite.getChildren();
223 Point minSize = new Point(composite.getClientArea().width,
224 composite.getClientArea().height);
226 if (children != null) {
227 for (int i = 0; i < children.length; i++) {
228 Control child = children[i];
229 child.setSize(minSize.x - fBorderSize * 2, minSize.y
231 child.setLocation(fBorderSize, fBorderSize);
237 /** Border thickness in pixels. */
238 private static final int BORDER = 1;
240 /** Right margin in pixels. */
241 private static final int RIGHT_MARGIN = 3;
243 /** The control's shell */
244 private Shell fShell;
247 Composite fComposite;
249 /** The control's text widget */
250 private Text fFilterText;
252 /** The control's tree widget */
253 private TreeViewer fTreeViewer;
255 /** The control width constraint */
256 private int fMaxWidth = -1;
258 /** The control height constraint */
259 private int fMaxHeight = -1;
261 private StringMatcher fStringMatcher;
264 * Creates a tree information control with the given shell as parent. The
265 * given style is applied to the tree widget.
270 * the additional styles for the tree widget
272 public JavaOutlineInformationControl(Shell parent, int style) {
273 this(parent, SWT.RESIZE, style);
277 * Creates a tree information control with the given shell as parent. No
278 * additional styles are applied.
283 // public JavaOutlineInformationControl(Shell parent) {
284 // this(parent, SWT.NONE);
288 * Creates a tree information control with the given shell as parent. The
289 * given styles are applied to the shell and the tree widget.
294 * the additional styles for the shell
296 * the additional styles for the tree widget
298 public JavaOutlineInformationControl(Shell parent, int shellStyle,
300 fShell = new Shell(parent, shellStyle);
301 Display display = fShell.getDisplay();
302 fShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
304 // Composite for filter text and tree
305 fComposite = new Composite(fShell, SWT.RESIZE);
306 GridLayout layout = new GridLayout(1, false);
307 fComposite.setLayout(layout);
308 fComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
310 createFilterText(fComposite);
311 createTreeViewer(fComposite, treeStyle);
313 int border = ((shellStyle & SWT.NO_TRIM) == 0) ? 0 : BORDER;
314 fShell.setLayout(new BorderFillLayout(border));
316 setInfoSystemColor();
320 private void createTreeViewer(Composite parent, int style) {
321 Tree tree = new Tree(parent, SWT.SINGLE | (style & ~SWT.MULTI));
322 GridData data = new GridData(GridData.FILL_BOTH);
323 tree.setLayoutData(data);
325 fTreeViewer = new TreeViewer(tree);
327 // Hide import declartions but show the container
328 // fTreeViewer.addFilter(new ViewerFilter() {
329 // public boolean select(Viewer viewer, Object parentElement, Object
331 // return !(element instanceof IImportDeclaration);
335 fTreeViewer.setContentProvider(new StandardJavaElementContentProvider(
337 fTreeViewer.setSorter(new JavaElementSorter());
338 fTreeViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS);
340 AppearanceAwareLabelProvider lprovider = new AppearanceAwareLabelProvider(
341 AppearanceAwareLabelProvider.DEFAULT_TEXTFLAGS
342 | JavaElementLabels.F_APP_TYPE_SIGNATURE,
343 AppearanceAwareLabelProvider.DEFAULT_IMAGEFLAGS);
345 .setLabelProvider(new DecoratingJavaLabelProvider(lprovider));
347 fTreeViewer.getTree().addKeyListener(new KeyListener() {
348 public void keyPressed(KeyEvent e) {
349 if (e.character == 0x1B) // ESC
353 public void keyReleased(KeyEvent e) {
358 fTreeViewer.getTree().addSelectionListener(new SelectionListener() {
359 public void widgetSelected(SelectionEvent e) {
363 public void widgetDefaultSelected(SelectionEvent e) {
364 gotoSelectedElement();
369 private Text createFilterText(Composite parent) {
370 fFilterText = new Text(parent, SWT.FLAT);
372 GridData data = new GridData();
373 GC gc = new GC(parent);
374 gc.setFont(parent.getFont());
375 FontMetrics fontMetrics = gc.getFontMetrics();
378 data.heightHint = org.eclipse.jface.dialogs.Dialog
379 .convertHeightInCharsToPixels(fontMetrics, 1);
380 data.horizontalAlignment = GridData.FILL;
381 data.verticalAlignment = GridData.BEGINNING;
382 fFilterText.setLayoutData(data);
384 fFilterText.addKeyListener(new KeyListener() {
385 public void keyPressed(KeyEvent e) {
386 if (e.keyCode == 0x0D) // return
387 gotoSelectedElement();
388 if (e.keyCode == SWT.ARROW_DOWN)
389 fTreeViewer.getTree().setFocus();
390 if (e.keyCode == SWT.ARROW_UP)
391 fTreeViewer.getTree().setFocus();
392 if (e.character == 0x1B) // ESC
396 public void keyReleased(KeyEvent e) {
401 // Horizonral separator line
402 Label separator = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL
404 separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
409 private void setInfoSystemColor() {
410 Display display = fShell.getDisplay();
411 setForegroundColor(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
412 setBackgroundColor(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
415 private void installFilter() {
416 final NamePatternFilter viewerFilter = new NamePatternFilter();
417 fTreeViewer.addFilter(viewerFilter);
418 fFilterText.setText(""); //$NON-NLS-1$
420 fFilterText.addModifyListener(new ModifyListener() {
421 public void modifyText(ModifyEvent e) {
422 String pattern = fFilterText.getText();
423 if (pattern != null) {
424 int length = pattern.length();
427 else if (pattern.charAt(length - 1) != '*')
428 pattern = pattern + '*';
431 viewerFilter.setPattern(pattern);
432 fStringMatcher = viewerFilter.getMatcher();
433 fTreeViewer.getControl().setRedraw(false);
434 fTreeViewer.refresh();
435 fTreeViewer.expandAll();
437 fTreeViewer.getControl().setRedraw(true);
442 private void gotoSelectedElement() {
443 Object selectedElement = ((IStructuredSelection) fTreeViewer
444 .getSelection()).getFirstElement();
445 if (selectedElement != null) {
448 OpenActionUtil.open(selectedElement, true);
449 } catch (CoreException ex) {
456 * Selects the first element in the tree which matches the current filter
459 private void selectFirstMatch() {
460 Tree tree = fTreeViewer.getTree();
461 Object element = findElement(tree.getItems());
463 fTreeViewer.setSelection(new StructuredSelection(element), true);
465 fTreeViewer.setSelection(StructuredSelection.EMPTY);
468 private IJavaElement findElement(TreeItem[] items) {
469 ILabelProvider labelProvider = (ILabelProvider) fTreeViewer
471 for (int i = 0; i < items.length; i++) {
472 IJavaElement element = (IJavaElement) items[i].getData();
473 if (fStringMatcher == null)
476 if (element != null) {
477 String label = labelProvider.getText(element);
478 if (fStringMatcher.match(label))
482 element = findElement(items[i].getItems());
490 * @see IInformationControl#setInformation(String)
492 public void setInformation(String information) {
493 // this method is ignored, see IInformationControlExtension2
497 * @see IInformationControlExtension2#setInput(Object)
499 public void setInput(Object information) {
500 fFilterText.setText(""); //$NON-NLS-1$
501 if (information == null || information instanceof String) {
505 IJavaElement je = (IJavaElement) information;
506 IJavaElement sel = null;
507 ICompilationUnit cu = (ICompilationUnit) je
508 .getAncestor(IJavaElement.COMPILATION_UNIT);
512 sel = je.getAncestor(IJavaElement.CLASS_FILE);
513 fTreeViewer.setInput(sel);
514 fTreeViewer.setSelection(new StructuredSelection(information));
518 * @see IInformationControl#setVisible(boolean)
520 public void setVisible(boolean visible) {
521 fShell.setVisible(visible);
525 * @see IInformationControl#dispose()
527 public void dispose() {
528 if (fShell != null) {
529 if (!fShell.isDisposed())
539 * @see org.eclipse.jface.text.IInformationControlExtension#hasContents()
541 public boolean hasContents() {
542 return fTreeViewer != null && fTreeViewer.getInput() != null;
546 * @see org.eclipse.jface.text.IInformationControl#setSizeConstraints(int,
549 public void setSizeConstraints(int maxWidth, int maxHeight) {
550 fMaxWidth = maxWidth;
551 fMaxHeight = maxHeight;
555 * @see org.eclipse.jface.text.IInformationControl#computeSizeHint()
557 public Point computeSizeHint() {
558 return fShell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
562 * @see IInformationControl#setLocation(Point)
564 public void setLocation(Point location) {
565 Rectangle trim = fShell.computeTrim(0, 0, 0, 0);
566 Point textLocation = fComposite.getLocation();
567 location.x += trim.x - textLocation.x;
568 location.y += trim.y - textLocation.y;
569 fShell.setLocation(location);
573 * @see IInformationControl#setSize(int, int)
575 public void setSize(int width, int height) {
576 fShell.setSize(width, height);
580 * @see IInformationControl#addDisposeListener(DisposeListener)
582 public void addDisposeListener(DisposeListener listener) {
583 fShell.addDisposeListener(listener);
587 * @see IInformationControl#removeDisposeListener(DisposeListener)
589 public void removeDisposeListener(DisposeListener listener) {
590 fShell.removeDisposeListener(listener);
594 * @see IInformationControl#setForegroundColor(Color)
596 public void setForegroundColor(Color foreground) {
597 fTreeViewer.getTree().setForeground(foreground);
598 fFilterText.setForeground(foreground);
599 fComposite.setForeground(foreground);
603 * @see IInformationControl#setBackgroundColor(Color)
605 public void setBackgroundColor(Color background) {
606 fTreeViewer.getTree().setBackground(background);
607 fFilterText.setBackground(background);
608 fComposite.setBackground(background);
612 * @see IInformationControl#isFocusControl()
614 public boolean isFocusControl() {
615 return fTreeViewer.getControl().isFocusControl()
616 || fFilterText.isFocusControl();
620 * @see IInformationControl#setFocus()
622 public void setFocus() {
624 fFilterText.setFocus();
628 * @see IInformationControl#addFocusListener(FocusListener)
630 public void addFocusListener(FocusListener listener) {
631 fShell.addFocusListener(listener);
635 * @see IInformationControl#removeFocusListener(FocusListener)
637 public void removeFocusListener(FocusListener listener) {
638 fShell.removeFocusListener(listener);