package org.eclipse.uml2.diagram.common.sheet.chooser;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.dialogs.FilteredList;
import org.eclipse.ui.dialogs.FilteredList.FilterMatcher;
/*
* This control repeats functionality from org.eclipse.ui.dialogs.AbstractElementListSelectionDialog.
* We don't need any dialog here, that's why we cannot use the original class, but copy the code instead.
* See #263012 'Add FilterText composite to FilteredList'
* See #263035 'Filtered List: Provide access to fList field'
*/
public class FilteredListControl extends Composite {
private boolean fIgnoreCase = true;
private boolean fIsMultipleSelection = false;
private boolean fMatchEmptyString = true;
private boolean fAllowDuplicates = true;
private Text fFilterText;
private List<Object> myInitialSelections = new ArrayList<Object>();
private String fFilter = null;
protected FilteredList fFilteredList;
private final ILabelProvider fRenderer;
private FilteredList myFilteredList;
private TableViewer viewer;
public FilteredListControl(Composite parent, ILabelProvider renderer) {
super(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.marginWidth = 0;
layout.marginHeight = 0;
setLayout(layout);
setLayoutData(new GridData(GridData.FILL_BOTH));
fRenderer = renderer;
createFilterText(this);
myFilteredList = createFilteredList(this);
}
protected void setFilterMatcher(FilterMatcher filterMatcher) {
myFilteredList.setFilterMatcher(filterMatcher);
}
public void setInitialSelections(Object[] selectedElements) {
myInitialSelections = new ArrayList<Object>(selectedElements.length);
for (int i = 0; i < selectedElements.length; i++) {
myInitialSelections.add(selectedElements[i]);
}
}
@Override
public boolean setFocus() {
if (myFilteredList != null) {
return myFilteredList.setFocus();
}
return super.setFocus();
}
protected Text createFilterText(Composite parent) {
Text text = new Text(parent, SWT.BORDER);
GridData data = new GridData();
data.grabExcessVerticalSpace = false;
data.grabExcessHorizontalSpace = true;
data.horizontalAlignment = GridData.FILL;
data.verticalAlignment = GridData.BEGINNING;
text.setLayoutData(data);
text.setFont(parent.getFont());
text.setText((fFilter == null ? "" : fFilter)); //$NON-NLS-1$
Listener listener = new Listener() {
public void handleEvent(Event e) {
fFilteredList.setFilter(fFilterText.getText());
}
};
text.addListener(SWT.Modify, listener);
text.addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) {
if (e.keyCode == SWT.ARROW_DOWN) {
fFilteredList.setFocus();
}
}
public void keyReleased(KeyEvent e) {
}
});
fFilterText = text;
return text;
}
/*
* Hack to add Double-Click Listener
* See #263035 'Filtered List: Provide access to fList field'
*/
private Table getTable(FilteredList list) {
try {
Field field = list.getClass().getDeclaredField("fList"); //$NON-NLS-1$
if (!field.isAccessible()) {
field.setAccessible(true);
}
Object value = field.get(list);
return (Table) value;
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
protected FilteredList createFilteredList(Composite parent) {
int flags = SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | (fIsMultipleSelection ? SWT.MULTI : SWT.SINGLE);
FilteredList list = new FilteredList(parent, flags, fRenderer, fIgnoreCase, fAllowDuplicates, fMatchEmptyString);
Table table = getTable(list);
if (table != null) {
viewer = new TableViewer(table);
}
GridData data = new GridData();
// data.widthHint = convertWidthInCharsToPixels(fWidth);
// data.heightHint = convertHeightInCharsToPixels(fHeight);
data.grabExcessVerticalSpace = true;
data.grabExcessHorizontalSpace = true;
data.horizontalAlignment = GridData.FILL;
data.verticalAlignment = GridData.FILL;
list.setLayoutData(data);
list.setFont(parent.getFont());
list.setFilter((fFilter == null ? "" : fFilter)); //$NON-NLS-1$
fFilteredList = list;
return list;
}
protected void setListElements(Object[] elements) {
Assert.isNotNull(fFilteredList);
fFilteredList.setElements(elements);
}
/**
* Sets the filter pattern.
*
* @param filter
* the filter pattern.
*/
public void setFilter(String filter) {
if (fFilterText == null) {
fFilter = filter;
} else {
fFilterText.setText(filter);
}
}
/**
* Returns the current filter pattern.
*
* @return returns the current filter pattern or
* <code>null<code> if filter was not set.
*/
public String getFilter() {
if (fFilteredList == null) {
return fFilter;
} else {
return fFilteredList.getFilter();
}
}
/**
* Returns the indices referring the current selection. To be called within
* open().
*
* @return returns the indices of the current selection.
*/
protected int[] getSelectionIndices() {
Assert.isNotNull(fFilteredList);
return fFilteredList.getSelectionIndices();
}
/**
* Returns an index referring the first current selection. To be called
* within open().
*
* @return returns the indices of the current selection.
*/
protected int getSelectionIndex() {
Assert.isNotNull(fFilteredList);
return fFilteredList.getSelectionIndex();
}
/**
* Sets the selection referenced by an array of elements. Empty or null
* array removes selection. To be called within open().
*
* @param selection
* the indices of the selection.
*/
protected void setSelection(Object[] selection) {
Assert.isNotNull(fFilteredList);
fFilteredList.setSelection(selection);
}
/**
* Returns an array of the currently selected elements. To be called within
* or after open().
*
* @return returns an array of the currently selected elements.
*/
protected Object[] getSelectedElements() {
Assert.isNotNull(fFilteredList);
return fFilteredList.getSelection();
}
/**
* Returns all elements which are folded together to one entry in the list.
*
* @param index
* the index selecting the entry in the list.
* @return returns an array of elements folded together.
*/
public Object[] getFoldedElements(int index) {
Assert.isNotNull(fFilteredList);
return fFilteredList.getFoldedElements(index);
}
public void addDoubleClickListener(IDoubleClickListener l) {
viewer.addDoubleClickListener(l);
}
public void addSelectionListener(final ISelectionChangedListener l) {
viewer.addSelectionChangedListener(l);
}
}