/** * <copyright> * * Copyright (c) 2002, 2010 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 - Initial API and implementation * * </copyright> * * $Id: ExtendedComboBoxCellEditor.java,v 1.8 2008/12/22 14:26:02 emerks Exp $ */ package net.enilink.komma.common.ui.celleditor; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; import org.eclipse.jface.viewers.ComboBoxCellEditor; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CCombo; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import net.enilink.komma.common.CommonPlugin; /** * This uses a list of objects and a label provider to build a combo box based * on model objects rather than on strings. If sort is true, the list will be * modified to match the order of the sorted labels. */ public class ExtendedComboBoxCellEditor extends ComboBoxCellEditor { private static class StringPositionPair implements Comparable<StringPositionPair> { Comparator<String> comparator = CommonPlugin.INSTANCE.getComparator(); public String key; public int position; StringPositionPair(String key, int position) { this.key = key; this.position = position; } public int compareTo(StringPositionPair object) { if (object == this) { return 0; } else { StringPositionPair that = object; return comparator.compare(key, that.key); } } } public static boolean select(String filter, String labelValue) { if (filter != null && filter.length() > 0) { if (filter.length() > labelValue.length()) { return false; } for (int i = 0; i < filter.length(); i++) { if (Character.toLowerCase(filter.charAt(i)) != Character .toLowerCase(labelValue.charAt(i))) { return false; } } } return true; } public static <T> String[] createItems(List<T> list, ILabelProvider labelProvider, boolean sorted) { return createItems(list, labelProvider, null, sorted); } public static <T> String[] createItems(List<T> list, ILabelProvider labelProvider, String filter, boolean sorted) { String[] result; if (filter != null && filter.length() > 0) { sorted = true; } // If there are objects to populate... if (list != null && list.size() > 0) { if (sorted) { List<T> unsortedList = new ArrayList<T>(list.size()); if (filter != null && filter.length() > 0) { for (int i = 0; i < list.size(); i++) { if (select(filter, labelProvider.getText(list.get(i)))) { unsortedList.add(list.get(i)); } } } else { unsortedList.addAll(list); } list.clear(); StringPositionPair[] pairs = new StringPositionPair[unsortedList .size()]; for (int i = 0, size = unsortedList.size(); i < size; ++i) { Object object = unsortedList.get(i); pairs[i] = new StringPositionPair(labelProvider .getText(object), i); } Arrays.sort(pairs); // Create a new array. result = new String[unsortedList.size()]; // Fill in the result array with labels and re-populate the // original list in order. for (int i = 0, size = unsortedList.size(); i < size; ++i) { result[i] = pairs[i].key; list.add(unsortedList.get(pairs[i].position)); } } else { // Create a new array. result = new String[list.size()]; // Fill in the array with labels. for (int i = 0, size = list.size(); i < size; ++i) { Object object = list.get(i); result[i] = labelProvider.getText(object); } } } else { result = new String[] { "" }; } return result; } /** * This keeps track of the list of model objects. */ protected List<?> originalList; protected List<?> list; protected ILabelProvider labelProvider; protected boolean sorted; public ExtendedComboBoxCellEditor(Composite composite, List<?> list, ILabelProvider labelProvider) { this(composite, list, labelProvider, false, SWT.READ_ONLY); } public ExtendedComboBoxCellEditor(Composite composite, List<?> list, ILabelProvider labelProvider, boolean sorted) { this(composite, list, labelProvider, sorted, SWT.READ_ONLY); } public ExtendedComboBoxCellEditor(Composite composite, List<?> list, ILabelProvider labelProvider, int style) { this(composite, list, labelProvider, false, style); } public ExtendedComboBoxCellEditor(Composite composite, List<?> list, ILabelProvider labelProvider, boolean sorted, int style) { super(composite, createItems( sorted ? list = new ArrayList<Object>(list) : list, labelProvider, null, sorted), style); this.originalList = list; this.list = list; this.labelProvider = labelProvider; this.sorted = sorted; if ((style & SWT.READ_ONLY) != 0) { new FilteringAdapter(getControl()); } } protected void refreshItems(String filter) { CCombo combo = (CCombo) getControl(); if (combo != null && (!combo.isDisposed())) { String[] items = createItems(list = new ArrayList<Object>( originalList), labelProvider, filter, sorted); combo.setItems(items); if (items.length > 0) { combo.select(0); } } } @Override public Object doGetValue() { // Get the index into the list via this call to super. int index = (Integer) super.doGetValue(); return index < list.size() && index >= 0 ? list.get((Integer) super .doGetValue()) : null; } @Override public void doSetValue(Object value) { // Set the index of the object value in the list via this call to super. int index = list.indexOf(value); if (index != -1) { super.doSetValue(list.indexOf(value)); } } public class FilteringAdapter implements KeyListener, FocusListener { public FilteringAdapter(Control control) { control.addKeyListener(this); control.addFocusListener(this); } private StringBuffer filter = new StringBuffer(); private void refreshItems() { ExtendedComboBoxCellEditor.this.refreshItems(filter.toString()); } public void keyPressed(KeyEvent e) { e.doit = false; if (e.keyCode == SWT.DEL || e.keyCode == SWT.BS) { if (filter.length() > 0) { filter = new StringBuffer(filter.substring(0, filter .length() - 1)); } } else if (e.keyCode == SWT.ARROW_UP || e.keyCode == SWT.ARROW_DOWN || e.keyCode == SWT.CR || e.keyCode == SWT.LF) { e.doit = true; } else if (e.keyCode == SWT.ESC) { filter = new StringBuffer(); } else if (e.character != '\0') { filter.append(e.character); } if (!e.doit) { refreshItems(); } } public void keyReleased(KeyEvent e) { // Do nothing } public void focusGained(FocusEvent e) { filter = new StringBuffer(); } public void focusLost(FocusEvent e) { filter = new StringBuffer(); refreshItems(); } } }