RSS

Search Engine

Monday, June 28, 2010

Highlighting elements - StyledCellLabelProvider

It is also possible to use a StyleCellLabelProvider to highlight the search result. StyleCellLabelProvider can do much more but we will look at the simple case.

First create the following helper class which will determine which occurrence of the search string is in the column.

   
package de.vogella.jface.tableviewer.util;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.widgets.Display;

public class SearchUtil {
public static int[] getSearchTermOccurrences(String searchTerm,
String content) {
List styleRange;
List ranges;
Display disp = Display.getCurrent();
StyleRange myStyleRange = new StyleRange(0, 0, null, disp
.getSystemColor(SWT.COLOR_YELLOW));

styleRange = new ArrayList(); // reset the StyleRange-Array
// for each new field
ranges = new ArrayList(); // reset the ranges-array
// empty search term ==> return an empty StyleRange array
if (searchTerm.equals("")) {
return new int[] {};
}

// determine all occurrences of the searchText and write the beginning
// and length of each occurrence into an array
for (int i = 0; i < content.length(); i++) {
if (i + searchTerm.length() <= content.length()
&& content.substring(i, i + searchTerm.length())
.equalsIgnoreCase(searchTerm)) {
// ranges format: n->start of the range, n+1->length of the
// range
ranges.add(i);
ranges.add(searchTerm.length());
}
}
// convert the list into an int[] and make sure that overlapping
// search term occurrences are are merged
int[] intRanges = new int[ranges.size()];
int arrayIndexCounter = 0;
for (int listIndexCounter = 0; listIndexCounter < ranges.size(); listIndexCounter++) {
if (listIndexCounter % 2 == 0) {
if (searchTerm.length() > 1
&& listIndexCounter != 0
&& ranges.get(listIndexCounter - 2)
+ ranges.get(listIndexCounter - 1) >= ranges
.get(listIndexCounter)) {
intRanges[arrayIndexCounter - 1] = 0
- ranges.get(listIndexCounter - 2)
+ ranges.get(listIndexCounter)
+ ranges.get(++listIndexCounter);
} else {
intRanges[arrayIndexCounter++] = ranges
.get(listIndexCounter);
}
} else {
intRanges[arrayIndexCounter++] = ranges.get(listIndexCounter);
styleRange.add(myStyleRange);
}
}
// if there have been any overlappings we need to reduce the size of
// the array to avoid conflicts in the setStyleRanges method
int[] intRangesCorrectSize = new int[arrayIndexCounter];
System.arraycopy(intRanges, 0, intRangesCorrectSize, 0,
arrayIndexCounter);

return intRangesCorrectSize;
}
}

Change your PersonLabelProvider to the following.

   
package de.vogella.jface.tableviewer.providers;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import de.vogella.jface.tableviewer.Activator;

import de.vogella.jface.tableviewer.model.Person;
import de.vogella.jface.tableviewer.util.SearchUtil;

public class PersonLabelProvider extends StyledCellLabelProvider {
// We use icons
private static final Image CHECKED = Activator.getImageDescriptor(
"icons/checked.gif").createImage();
private static final Image UNCHECKED = Activator.getImageDescriptor(
"icons/unchecked.gif").createImage();
private String searchText;
private Color systemColor;

public PersonLabelProvider() {
systemColor = Display.getCurrent().getSystemColor(SWT.COLOR_YELLOW);
}

public void setSearchText(String searchText) {
this.searchText = searchText;

}

@Override
public void update(ViewerCell cell) {
Person element = (Person) cell.getElement();
int index = cell.getColumnIndex();
String columnText = getColumnText(element, index);
cell.setText(columnText);
cell.setImage(getColumnImage(element, index));
if (searchText != null && searchText.length() > 0) {
int intRangesCorrectSize[] = SearchUtil.getSearchTermOccurrences(
searchText, columnText);
List styleRange = new ArrayList();
for (int i = 0; i < intRangesCorrectSize.length / 2; i++) {
StyleRange myStyleRange = new StyleRange(0, 0, null,
systemColor);
myStyleRange.start = intRangesCorrectSize[i];
myStyleRange.length = intRangesCorrectSize[++i];
styleRange.add(myStyleRange);
}
cell.setStyleRanges(styleRange.toArray(new StyleRange[styleRange
.size()]));
} else {
cell.setStyleRanges(null);
}

super.update(cell);

}

private String getColumnText(Object element, int columnIndex) {
Person person = (Person) element;
switch (columnIndex) {
case 0:
return person.getFirstName();
case 1:
return person.getLastName();
case 2:
return person.getGender();
case 3:
return String.valueOf(person.isMarried());
default:
throw new RuntimeException("Should not happen");
}
}

private Image getColumnImage(Object element, int columnIndex) {
// In case you don't like image just return null here
if (columnIndex == 3) {
if (((Person) element).isMarried()) {
return CHECKED;
}
return UNCHECKED;
}
return null;
}

}

Make the following changes to the View. .

   
package de.vogella.jface.tableviewer;

import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.part.ViewPart;

import de.vogella.jface.tableviewer.filter.PersonFilter;
import de.vogella.jface.tableviewer.model.ModelProvider;
import de.vogella.jface.tableviewer.providers.PersonContentProvider;
import de.vogella.jface.tableviewer.providers.PersonEditingSupport;
import de.vogella.jface.tableviewer.providers.PersonLabelProvider;
import de.vogella.jface.tableviewer.sorter.TableSorter;

public class View extends ViewPart {
public static final String ID = "de.vogella.jface.tableviewer.view";

private TableViewer viewer;

private TableSorter tableSorter;

private PersonFilter filter;

private PersonLabelProvider labelProvider;

public void createPartControl(Composite parent) {
GridLayout layout = new GridLayout(2, false);
parent.setLayout(layout);
Label searchLabel = new Label(parent, SWT.NONE);
searchLabel.setText("Search: ");
final Text searchText = new Text(parent, SWT.BORDER | SWT.SEARCH);
searchText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
| GridData.HORIZONTAL_ALIGN_FILL));
searchText.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent ke) {
filter.setSearchText(searchText.getText());
labelProvider.setSearchText(searchText.getText());
viewer.refresh();
}
});

createViewer(parent);


// Get the content for the viewer, setInput will call getElements in the
// contentProvider
viewer.setInput(ModelProvider.getInstance().getPersons());
// Make the selection available
getSite().setSelectionProvider(viewer);
// Set the sorter for the table
tableSorter = new TableSorter();
viewer.setSorter(tableSorter);
filter = new PersonFilter();
viewer.addFilter(filter);

// Layout the viewer
GridData gridData = new GridData();
gridData.verticalAlignment = GridData.FILL;
gridData.horizontalSpan = 2;
gridData.grabExcessHorizontalSpace = true;
gridData.grabExcessVerticalSpace = true;
gridData.horizontalAlignment = GridData.FILL;
viewer.getControl().setLayoutData(gridData);
}
private void createViewer(Composite parent) {
viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
| SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
createColumns(viewer);
viewer.setContentProvider(new PersonContentProvider());
labelProvider = new PersonLabelProvider();
viewer.setLabelProvider(labelProvider);
}

public TableViewer getViewer() {
return viewer;
}

// This will create the columns for the table
private void createColumns(final TableViewer viewer) {
Table table = viewer.getTable();
String[] titles = { "First name", "Last name", "Gender", "Married" };
int[] bounds = { 100, 100, 100, 100 };

for (int i = 0; i < titles.length; i++) {
final int index = i;
final TableViewerColumn viewerColumn = new TableViewerColumn(
viewer, SWT.NONE);
final TableColumn column = viewerColumn.getColumn();
column.setText(titles[i]);
column.setWidth(bounds[i]);
column.setResizable(true);
column.setMoveable(true);
// Setting the right sorter
column.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
tableSorter.setColumn(index);
int dir = viewer.getTable().getSortDirection();
if (viewer.getTable().getSortColumn() == column) {
dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
} else {

dir = SWT.DOWN;
}
viewer.getTable().setSortDirection(dir);
viewer.getTable().setSortColumn(column);
viewer.refresh();
}
});
viewerColumn.setEditingSupport(new PersonEditingSupport(viewer, i));
}
table.setHeaderVisible(true);
table.setLinesVisible(true);
}

/**
* Passing the focus request to the viewer's control.
*/
public void setFocus() {
viewer.getControl().setFocus();
}
}

Run the example, if you search now the selected content should get highlighted should work.

0 comments:

Post a Comment