/******************************************************************************* * Copyright (c) 2000, 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Sebastian Davids <sdavids@gmx.de> - Fix for bug 19346 - Dialog font should be activated and used by other components. * Vincent Zurczak <vincent.zurczak@petalslink.com> - Fork to support styled cell label providers. * Vincent Zurczak <vincent.zurczak@petalslink.com> - Added type parameters. *******************************************************************************/ package com.ebmwebsourcing.petals.common.internal.provisional.swt; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.regex.Pattern; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider; import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Table; import org.eclipse.ui.dialogs.FilteredList; import org.eclipse.ui.progress.WorkbenchJob; /** * An alternative to {@link FilteredList} supporting styled cell label providers. * @author Vincent Zurczak - EBM WebSourcing */ public class StyledFilteredList extends Composite { private final DelegatingStyledCellLabelProvider labelProvider; private final TableViewer viewer; private Object[] elements = new Object[ 0 ]; private final List<Object> filteredElements = new ArrayList<Object> (); private final List<Object> selectedElements = new ArrayList<Object> (); private boolean ignoreCase = true; private String filter = ""; //$NON-NLS-1$ private Pattern filterPattern; private TableUpdateJob fUpdateJob; /** * Constructs a new filtered list. * @param parent * @param style * @param labelProvider */ public StyledFilteredList( Composite parent, int style, IStyledLabelProvider labelProvider ) { super( parent, SWT.NONE ); GridLayout layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; setLayout( layout ); Table table = new Table( this, style ); table.setLayoutData(new GridData( GridData.FILL_BOTH )); table.addDisposeListener( new DisposeListener() { @Override public void widgetDisposed( DisposeEvent e ) { StyledFilteredList.this.labelProvider.dispose(); if( StyledFilteredList.this.fUpdateJob != null ) StyledFilteredList.this.fUpdateJob.cancel(); } }); this.viewer = new TableViewer( table ); this.viewer.setContentProvider( new ArrayContentProvider()); this.labelProvider = new DelegatingStyledCellLabelProvider( labelProvider ); this.viewer.setLabelProvider( this.labelProvider ); this.viewer.addSelectionChangedListener( new ISelectionChangedListener() { @Override public void selectionChanged( SelectionChangedEvent event ) { StyledFilteredList.this.selectedElements.clear(); Object[] sel = ((IStructuredSelection) event.getSelection()).toArray(); StyledFilteredList.this.selectedElements.addAll( Arrays.asList( sel )); } }); } /** * @param elements */ public void setElements( Object[] elements ) { if( elements == null ) this.elements = new Object[ 0 ]; else this.elements = Arrays.copyOf( elements, elements.length ); updateList(); } /** * Updates the filtering pattern. */ private void updateMatchingPattern() { String _filter = this.filter != null ? this.filter : ""; String regex = _filter.replaceAll( "\\*", "(\\.)*" ); if( this.ignoreCase ) this.filterPattern = Pattern.compile( regex, Pattern.CASE_INSENSITIVE ); else this.filterPattern = Pattern.compile( regex ); updateList(); } /** * @return true if the list of filtered elements is empty */ public boolean isEmpty() { return this.filteredElements.isEmpty(); } /** * Updates the list of elements to display. */ private void updateList() { // FIXME: should we use a viewer filter for this? // Performances might be better. this.filteredElements.clear(); IStyledLabelProvider p = this.labelProvider.getStyledStringProvider(); for( Object o : this.elements ) { if( this.filterPattern.matcher( p.getStyledText( o ).getString()).find()) this.filteredElements.add( o ); } if( this.fUpdateJob != null ) this.fUpdateJob.cancel(); this.fUpdateJob = new TableUpdateJob(); this.fUpdateJob.schedule(); } /** * @param selection */ public void setSelection( Object[] selection ) { this.selectedElements.clear(); if( selection != null ) this.selectedElements.addAll( Arrays.asList( selection )); } /** * @return */ public Object[] getSelection() { return this.selectedElements.toArray(); } /** * @param selectionListener */ public void addSelectionListener( SelectionListener selectionListener ) { this.viewer.getTable().addSelectionListener( selectionListener ); } /** * @param selectionListener */ public void removeSelectionListener( SelectionListener selectionListener ) { this.viewer.getTable().removeSelectionListener( selectionListener ); } /** * A job to update the viewer content. */ private class TableUpdateJob extends WorkbenchJob { /** * Create a new instance of a job used to update the table viewer. */ public TableUpdateJob() { super( "Updating the displayed elements..." ); setSystem( true ); } /* * (non-Javadoc) * @see org.eclipse.ui.progress.UIJob * #runInUIThread(org.eclipse.core.runtime.IProgressMonitor) */ @Override public IStatus runInUIThread( IProgressMonitor monitor ) { if( StyledFilteredList.this.viewer.getTable().isDisposed()) return Status.CANCEL_STATUS; // Refresh the viewer StyledFilteredList.this.viewer.setInput( StyledFilteredList.this.filteredElements ); StyledFilteredList.this.viewer.refresh(); // Restore the selected elements StyledFilteredList.this.viewer.setSelection( new StructuredSelection( StyledFilteredList.this.selectedElements )); return Status.OK_STATUS; } } /* * SETTERS & GETTERS */ /** * @return the ignoreCase */ public boolean isIgnoreCase() { return this.ignoreCase; } /** * @param ignoreCase the ignoreCase to set */ public void setIgnoreCase( boolean ignoreCase ) { this.ignoreCase = ignoreCase; updateMatchingPattern(); } /** * @return the filter */ public String getFilter() { return this.filter; } /** * @param filter the filter to set */ public void setFilter( String filter ) { this.filter = filter; updateMatchingPattern(); } }