/*******************************************************************************
* Copyright (c) 2004, 2010 BREDEX GmbH.
* 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:
* BREDEX GmbH - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.jubula.client.ui.widgets;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.commons.lang.Validate;
import org.eclipse.jubula.tools.internal.constants.StringConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
/**
* @author BREDEX GmbH
* @created 07.02.2006
*
* @param <TheObject> the class which entities are the base for the set of choices
*/
public class DirectCombo<TheObject> extends Combo {
/** List of Objects to display */
private List<TheObject> m_values;
// display options
/**
* is a null selection allowed? this implies an empty entry
* in the items.
*/
private boolean m_nullSelectionAllowed;
/** optional comparator, may be null if no sort is required */
private Comparator<String> m_comparator;
/**
* A Combo which supports Objects as keys and a String as displayable
* value.
*
* {@inheritDoc}
* @param parent {@inheritDoc}
* @param style {@inheritDoc}
* @param values
* Object represented by combobox
* @param displayValues
* Strings to be display for each value object
* @param isNullSelectionAllowed
* true if the Combo should start with an empty entry to support
* null selection
* @param comparator Sorting criteria for display values. <code>null</code>
* is allowed. In this case no sorting is done.
*/
public DirectCombo(Composite parent, int style, List<TheObject> values,
List<String> displayValues, boolean isNullSelectionAllowed,
Comparator<String> comparator) {
super(parent, style | SWT.READ_ONLY);
m_nullSelectionAllowed = isNullSelectionAllowed;
m_comparator = comparator;
init(values, displayValues, isNullSelectionAllowed, comparator);
}
/**
* A Combo which supports I18N
*
* {@inheritDoc}
* @param parent {@inheritDoc}
* @param style {@inheritDoc}
* @param values
* Object represented by combobox
* @param displayValues
* Strings to be display for each value object
* @param isNullSelectionAllowed
* true if the Combo should start with an empty entry to support
* null selection
* @param sortEntries
* Sort the display values by the standard String compareTo()
* method.
*/
public DirectCombo(Composite parent, int style, List<TheObject> values,
List<String> displayValues, boolean isNullSelectionAllowed,
boolean sortEntries) {
this(parent, style, values, displayValues, isNullSelectionAllowed,
sortEntries ? new Comparator<String>() {
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
} : null);
}
/**
* @param values values
* @param displayValues displayValues
* @param isNullSelectionAllowed isNullSelectionAllowed
* @param comparator comparator
*/
private void init(List<TheObject> values, List<String> displayValues,
boolean isNullSelectionAllowed, Comparator<String> comparator) {
Validate.isTrue(values.size() == displayValues.size(),
"values and displayValues don't have the same number of items."); //$NON-NLS-1$
List<String> display = displayValues;
if (comparator == null) { // no sorting requested
m_values = new ArrayList<TheObject>(values);
if (isNullSelectionAllowed) {
m_values.add(0, null);
display.add(0, StringConstants.EMPTY);
}
} else {
display = sortKeys(values, display, comparator,
isNullSelectionAllowed);
}
removeAll();
for (String displayValue : display) {
super.add(displayValue);
}
TheObject defaultSelectedObject;
if (isNullSelectionAllowed) {
defaultSelectedObject = null;
} else {
if (values.size() > 0) {
defaultSelectedObject = values.get(0);
} else {
defaultSelectedObject = null;
}
}
setSelectedObject(defaultSelectedObject);
}
/**
* Sort the keys according to the comparator which is applied to the display
* values. For performance reasons the display values are generated and
* returned, the keys are stored internally.
* @param values the original objects
* @param displayValues the Strings to be displayed in the Combo
* @param comparator how to compare the display string values
* @param isNullSelectionAllowed add an empty entry at the start of the list?
* @return a sorted list of display values
*/
private List<String> sortKeys(List<TheObject> values,
List<String> displayValues, Comparator<String> comparator,
boolean isNullSelectionAllowed) {
SortedMap<String, TheObject> sorter = new TreeMap<String, TheObject>(
comparator);
int size = values.size();
for (int i = 0; i < size; ++i) {
sorter.put(displayValues.get(i), values.get(i));
}
if (isNullSelectionAllowed) {
size++;
}
m_values = new ArrayList<TheObject>(size);
List<String> result = new ArrayList<String>(size);
if (isNullSelectionAllowed) {
m_values.add(null);
result.add(StringConstants.EMPTY);
}
for (Entry<String, TheObject> entry : sorter.entrySet()) {
m_values.add(entry.getValue());
result.add(entry.getKey());
}
return result;
}
/**
* @param o the Object which the Combo should display
*/
public void setSelectedObject(TheObject o) {
int index = m_values.indexOf(o);
select(index);
}
/**
* @return the associated Object for the selected display entry
*/
public TheObject getSelectedObject() {
int index = getSelectionIndex();
if (index == -1) { // nothing selected
return null;
}
return m_values.get(index);
}
/**
* @param values
* Object represented by combobox
* @param displayValues
* Strings to be display for each value object
*/
public void setItems(List<TheObject> values, List<String> displayValues) {
init(values, displayValues, m_nullSelectionAllowed, m_comparator);
}
/**
* @return Returns the comparator.
*/
protected Comparator<String> getComparator() {
return m_comparator;
}
/**
* @return Returns the nullSelectionAllowed.
*/
protected boolean isNullSelectionAllowed() {
return m_nullSelectionAllowed;
}
/**
* @return Returns the values.
*/
public List<TheObject> getValues() {
return m_values;
}
/**
* {@inheritDoc}
*/
protected void checkSubclass() {
// do nothing, therefore allowing subclassing
}
/**
* This methods has no meaning for this subclass and must not
* be called.
* {@inheritDoc}
* @deprecated
*/
@Deprecated
public void add(String string, int index) {
super.add(string, index);
}
/**
* This methods has no meaning for this subclass and must not
* be called.
* {@inheritDoc}
* @deprecated
*/
@Deprecated
public void add(String string) {
super.add(string);
}
/**
* This methods has no meaning for this subclass and must not
* be called.
* {@inheritDoc}
* @deprecated
*/
@Deprecated
public void remove(int start, int end) {
super.remove(start, end);
}
/**
* This methods has no meaning for this subclass and must not
* be called.
* {@inheritDoc}
* @deprecated
*/
@Deprecated
public void remove(int index) {
super.remove(index);
}
/**
* This methods has no meaning for this subclass and must not
* be called.
* {@inheritDoc}
* @deprecated
*/
@Deprecated
public void remove(String string) {
super.remove(string);
}
/**
* This methods has no meaning for this subclass and must not
* be called.
* {@inheritDoc}
* @deprecated
*/
@Deprecated
public void setItem(int index, String string) {
super.setItem(index, string);
}
/**
* This methods has no meaning for this subclass and must not
* be called.
* {@inheritDoc}
* @deprecated
*/
@Deprecated
public void setItems(String[] items) {
super.setItems(items);
}
/**
* This methods has no meaning for this subclass and must not
* be called.
* {@inheritDoc}
* @deprecated
*/
@Deprecated
public void setText(String string) {
super.setText(string);
}
}