blob: e43ed24bf885bd4d20dc2bb3cd8f05f30f5961f1 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 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.ui.internal;
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.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
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.Item;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.ui.internal.misc.StringMatcher;
/**
* @since 3.0
*/
public abstract class AbstractTableInformationControl {
/**
* The NamePatternFilter selects the elements which match the given string
* patterns.
*/
protected class NamePatternFilter extends ViewerFilter {
public NamePatternFilter() {
}
/*
* (non-Javadoc) Method declared on ViewerFilter.
*/
public boolean select(
Viewer viewer,
Object parentElement,
Object element) {
StringMatcher matcher = getMatcher();
if (matcher == null || !(viewer instanceof TableViewer))
return true;
TableViewer tableViewer = (TableViewer) viewer;
String matchName =
((ILabelProvider) tableViewer.getLabelProvider()).getText(
element);
return matchName != null && matcher.match(matchName);
}
}
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 table widget */
private TableViewer fTableViewer;
/** The control width constraint */
//private int fMaxWidth= -1;
/** The control height constraint */
//private int fMaxHeight= -1;
/** The current string matcher */
private StringMatcher fStringMatcher;
/**
* Creates an information control with the given shell as parent. The given
* styles are applied to the shell and the table widget.
*
* @param parent
* the parent shell
* @param shellStyle
* the additional styles for the shell
* @param controlStyle
* the additional styles for the control
*/
public AbstractTableInformationControl(
Shell parent,
int shellStyle,
int controlStyle) {
fShell = new Shell(parent, shellStyle);
Display display = fShell.getDisplay();
fShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
// Composite for filter text and viewer
fComposite = new Composite(fShell, SWT.RESIZE);
GridLayout layout = new GridLayout(1, false);
fComposite.setLayout(layout);
// fComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
createFilterText(fComposite);
fTableViewer = createTableViewer(fComposite, controlStyle);
final Table table = fTableViewer.getTable();
table.addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) {
if (e.character == 0x1B) // ESC
dispose();
}
public void keyReleased(KeyEvent e) {
// do nothing
}
});
table.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
// do nothing
}
public void widgetDefaultSelected(SelectionEvent e) {
gotoSelectedElement();
}
});
table.addMouseMoveListener(new MouseMoveListener() {
TableItem fLastItem = null;
public void mouseMove(MouseEvent e) {
if (table.equals(e.getSource())) {
Object o = table.getItem(new Point(e.x, e.y));
if (o instanceof TableItem) {
if (!o.equals(fLastItem)) {
fLastItem = (TableItem) o;
table.setSelection(new TableItem[] { fLastItem });
} else if (e.y < table.getItemHeight() / 4) {
// Scroll up
Point p = table.toDisplay(e.x, e.y);
Item item = fTableViewer.scrollUp(p.x, p.y);
if (item instanceof TableItem) {
fLastItem = (TableItem) item;
table.setSelection(
new TableItem[] { fLastItem });
}
} else if (
e.y
> table.getBounds().height
- table.getItemHeight() / 4) {
// Scroll down
Point p = table.toDisplay(e.x, e.y);
Item item = fTableViewer.scrollDown(p.x, p.y);
if (item instanceof TableItem) {
fLastItem = (TableItem) item;
table.setSelection(
new TableItem[] { fLastItem });
}
}
}
}
}
});
table.addMouseListener(new MouseAdapter() {
public void mouseUp(MouseEvent e) {
if (table.getSelectionCount() < 1)
return;
if (e.button != 1)
return;
if (table.equals(e.getSource())) {
Object o = table.getItem(new Point(e.x, e.y));
TableItem selection = table.getSelection()[0];
if (selection.equals(o))
gotoSelectedElement();
}
}
});
int border = ((shellStyle & SWT.NO_TRIM) == 0) ? 0 : BORDER;
fShell.setLayout(new BorderFillLayout(border));
setInfoSystemColor();
installFilter();
}
protected abstract TableViewer createTableViewer(
Composite parent,
int style);
protected TableViewer getTableViewer() {
return fTableViewer;
}
protected 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)
fTableViewer.getTable().setFocus();
if (e.keyCode == SWT.ARROW_UP)
fTableViewer.getTable().setFocus();
if (e.character == 0x1B) // ESC
dispose();
}
public void keyReleased(KeyEvent e) {
// do nothing
}
});
// Horizontal 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() {
fFilterText.setText(""); //$NON-NLS-1$
fFilterText.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
String text = ((Text) e.widget).getText();
int length = text.length();
if (length > 0 && text.charAt(length - 1) != '*') {
text = text + '*';
}
setMatcherString(text);
}
});
}
/**
* The string matcher has been modified. The default implementation
* refreshes the view and selects the first macthed element
*/
protected void stringMatcherUpdated() {
// refresh viewer to refilter
fTableViewer.getControl().setRedraw(false);
fTableViewer.refresh();
selectFirstMatch();
fTableViewer.getControl().setRedraw(true);
}
/**
* Sets the patterns to filter out for the receiver.
* <p>
* The following characters have special meaning: ? => any character * =>
* any string
* </p>
*/
protected void setMatcherString(String pattern) {
if (pattern.length() == 0) {
fStringMatcher = null;
} else {
boolean ignoreCase = pattern.toLowerCase().equals(pattern);
fStringMatcher = new StringMatcher(pattern, ignoreCase, false);
}
stringMatcherUpdated();
}
protected StringMatcher getMatcher() {
return fStringMatcher;
}
/**
* Implementers can modify
*/
protected Object getSelectedElement() {
return ((IStructuredSelection) fTableViewer.getSelection())
.getFirstElement();
}
protected abstract void gotoSelectedElement();
/**
* Selects the first element in the table which matches the current filter
* pattern.
*/
protected void selectFirstMatch() {
Table table = fTableViewer.getTable();
Object element = findElement(table.getItems());
if (element != null)
fTableViewer.setSelection(new StructuredSelection(element), true);
else
fTableViewer.setSelection(StructuredSelection.EMPTY);
}
private Object findElement(TableItem[] items) {
ILabelProvider labelProvider =
(ILabelProvider) fTableViewer.getLabelProvider();
for (int i = 0; i < items.length; i++) {
Object element = items[i].getData();
if (fStringMatcher == null)
return element;
if (element != null) {
String label = labelProvider.getText(element);
if (fStringMatcher.match(label))
return element;
}
}
return null;
}
/*
* @see IInformationControlExtension2#setInput(Object)
*/
public abstract void setInput(Object information);
protected void inputChanged(Object newInput, Object newSelection) {
fFilterText.setText(""); //$NON-NLS-1$
fTableViewer.setInput(newInput);
if (newSelection != null) {
fTableViewer.setSelection(new StructuredSelection(newSelection));
}
}
/*
* @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;
fTableViewer = null;
fComposite = null;
fFilterText = null;
}
}
/*
* @see org.eclipse.jface.text.IInformationControlExtension#hasContents()
*/
public boolean hasContents() {
return fTableViewer != null && fTableViewer.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) {
fTableViewer.getTable().setForeground(foreground);
fFilterText.setForeground(foreground);
fComposite.setForeground(foreground);
}
/*
* @see IInformationControl#setBackgroundColor(Color)
*/
public void setBackgroundColor(Color background) {
fTableViewer.getTable().setBackground(background);
fFilterText.setBackground(background);
fComposite.setBackground(background);
}
/*
* @see IInformationControl#isFocusControl()
*/
public boolean isFocusControl() {
return fTableViewer.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);
}
}