001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jface.viewers;
011:
012: import java.text.MessageFormat; // Not using ICU to support standalone JFace scenario
013:
014: import org.eclipse.core.runtime.Assert;
015: import org.eclipse.swt.SWT;
016: import org.eclipse.swt.custom.CCombo;
017: import org.eclipse.swt.events.FocusAdapter;
018: import org.eclipse.swt.events.FocusEvent;
019: import org.eclipse.swt.events.KeyAdapter;
020: import org.eclipse.swt.events.KeyEvent;
021: import org.eclipse.swt.events.SelectionAdapter;
022: import org.eclipse.swt.events.SelectionEvent;
023: import org.eclipse.swt.events.TraverseEvent;
024: import org.eclipse.swt.events.TraverseListener;
025: import org.eclipse.swt.graphics.GC;
026: import org.eclipse.swt.widgets.Composite;
027: import org.eclipse.swt.widgets.Control;
028:
029: /**
030: * A cell editor that presents a list of items in a combo box.
031: * The cell editor's value is the zero-based index of the selected
032: * item.
033: * <p>
034: * This class may be instantiated; it is not intended to be subclassed.
035: * </p>
036: */
037: public class ComboBoxCellEditor extends CellEditor {
038:
039: /**
040: * The list of items to present in the combo box.
041: */
042: private String[] items;
043:
044: /**
045: * The zero-based index of the selected item.
046: */
047: int selection;
048:
049: /**
050: * The custom combo box control.
051: */
052: CCombo comboBox;
053:
054: /**
055: * Default ComboBoxCellEditor style
056: */
057: private static final int defaultStyle = SWT.NONE;
058:
059: /**
060: * Creates a new cell editor with no control and no st of choices. Initially,
061: * the cell editor has no cell validator.
062: *
063: * @since 2.1
064: * @see CellEditor#setStyle
065: * @see CellEditor#create
066: * @see ComboBoxCellEditor#setItems
067: * @see CellEditor#dispose
068: */
069: public ComboBoxCellEditor() {
070: setStyle(defaultStyle);
071: }
072:
073: /**
074: * Creates a new cell editor with a combo containing the given
075: * list of choices and parented under the given control. The cell
076: * editor value is the zero-based index of the selected item.
077: * Initially, the cell editor has no cell validator and
078: * the first item in the list is selected.
079: *
080: * @param parent the parent control
081: * @param items the list of strings for the combo box
082: */
083: public ComboBoxCellEditor(Composite parent, String[] items) {
084: this (parent, items, defaultStyle);
085: }
086:
087: /**
088: * Creates a new cell editor with a combo containing the given
089: * list of choices and parented under the given control. The cell
090: * editor value is the zero-based index of the selected item.
091: * Initially, the cell editor has no cell validator and
092: * the first item in the list is selected.
093: *
094: * @param parent the parent control
095: * @param items the list of strings for the combo box
096: * @param style the style bits
097: * @since 2.1
098: */
099: public ComboBoxCellEditor(Composite parent, String[] items,
100: int style) {
101: super (parent, style);
102: setItems(items);
103: }
104:
105: /**
106: * Returns the list of choices for the combo box
107: *
108: * @return the list of choices for the combo box
109: */
110: public String[] getItems() {
111: return this .items;
112: }
113:
114: /**
115: * Sets the list of choices for the combo box
116: *
117: * @param items the list of choices for the combo box
118: */
119: public void setItems(String[] items) {
120: Assert.isNotNull(items);
121: this .items = items;
122: populateComboBoxItems();
123: }
124:
125: /* (non-Javadoc)
126: * Method declared on CellEditor.
127: */
128: protected Control createControl(Composite parent) {
129:
130: comboBox = new CCombo(parent, getStyle());
131: comboBox.setFont(parent.getFont());
132:
133: populateComboBoxItems();
134:
135: comboBox.addKeyListener(new KeyAdapter() {
136: // hook key pressed - see PR 14201
137: public void keyPressed(KeyEvent e) {
138: keyReleaseOccured(e);
139: }
140: });
141:
142: comboBox.addSelectionListener(new SelectionAdapter() {
143: public void widgetDefaultSelected(SelectionEvent event) {
144: applyEditorValueAndDeactivate();
145: }
146:
147: public void widgetSelected(SelectionEvent event) {
148: selection = comboBox.getSelectionIndex();
149: }
150: });
151:
152: comboBox.addTraverseListener(new TraverseListener() {
153: public void keyTraversed(TraverseEvent e) {
154: if (e.detail == SWT.TRAVERSE_ESCAPE
155: || e.detail == SWT.TRAVERSE_RETURN) {
156: e.doit = false;
157: }
158: }
159: });
160:
161: comboBox.addFocusListener(new FocusAdapter() {
162: public void focusLost(FocusEvent e) {
163: ComboBoxCellEditor.this .focusLost();
164: }
165: });
166: return comboBox;
167: }
168:
169: /**
170: * The <code>ComboBoxCellEditor</code> implementation of
171: * this <code>CellEditor</code> framework method returns
172: * the zero-based index of the current selection.
173: *
174: * @return the zero-based index of the current selection wrapped
175: * as an <code>Integer</code>
176: */
177: protected Object doGetValue() {
178: return new Integer(selection);
179: }
180:
181: /* (non-Javadoc)
182: * Method declared on CellEditor.
183: */
184: protected void doSetFocus() {
185: comboBox.setFocus();
186: }
187:
188: /**
189: * The <code>ComboBoxCellEditor</code> implementation of
190: * this <code>CellEditor</code> framework method sets the
191: * minimum width of the cell. The minimum width is 10 characters
192: * if <code>comboBox</code> is not <code>null</code> or <code>disposed</code>
193: * else it is 60 pixels to make sure the arrow button and some text is visible.
194: * The list of CCombo will be wide enough to show its longest item.
195: */
196: public LayoutData getLayoutData() {
197: LayoutData layoutData = super .getLayoutData();
198: if ((comboBox == null) || comboBox.isDisposed()) {
199: layoutData.minimumWidth = 60;
200: } else {
201: // make the comboBox 10 characters wide
202: GC gc = new GC(comboBox);
203: layoutData.minimumWidth = (gc.getFontMetrics()
204: .getAverageCharWidth() * 10) + 10;
205: gc.dispose();
206: }
207: return layoutData;
208: }
209:
210: /**
211: * The <code>ComboBoxCellEditor</code> implementation of
212: * this <code>CellEditor</code> framework method
213: * accepts a zero-based index of a selection.
214: *
215: * @param value the zero-based index of the selection wrapped
216: * as an <code>Integer</code>
217: */
218: protected void doSetValue(Object value) {
219: Assert.isTrue(comboBox != null && (value instanceof Integer));
220: selection = ((Integer) value).intValue();
221: comboBox.select(selection);
222: }
223:
224: /**
225: * Updates the list of choices for the combo box for the current control.
226: */
227: private void populateComboBoxItems() {
228: if (comboBox != null && items != null) {
229: comboBox.removeAll();
230: for (int i = 0; i < items.length; i++) {
231: comboBox.add(items[i], i);
232: }
233:
234: setValueValid(true);
235: selection = 0;
236: }
237: }
238:
239: /**
240: * Applies the currently selected value and deactivates the cell editor
241: */
242: void applyEditorValueAndDeactivate() {
243: // must set the selection before getting value
244: selection = comboBox.getSelectionIndex();
245: Object newValue = doGetValue();
246: markDirty();
247: boolean isValid = isCorrect(newValue);
248: setValueValid(isValid);
249:
250: if (!isValid) {
251: // Only format if the 'index' is valid
252: if (items.length > 0 && selection >= 0
253: && selection < items.length) {
254: // try to insert the current value into the error message.
255: setErrorMessage(MessageFormat.format(getErrorMessage(),
256: new Object[] { items[selection] }));
257: } else {
258: // Since we don't have a valid index, assume we're using an 'edit'
259: // combo so format using its text value
260: setErrorMessage(MessageFormat.format(getErrorMessage(),
261: new Object[] { comboBox.getText() }));
262: }
263: }
264:
265: fireApplyEditorValue();
266: deactivate();
267: }
268:
269: /*
270: * (non-Javadoc)
271: * @see org.eclipse.jface.viewers.CellEditor#focusLost()
272: */
273: protected void focusLost() {
274: if (isActivated()) {
275: applyEditorValueAndDeactivate();
276: }
277: }
278:
279: /*
280: * (non-Javadoc)
281: * @see org.eclipse.jface.viewers.CellEditor#keyReleaseOccured(org.eclipse.swt.events.KeyEvent)
282: */
283: protected void keyReleaseOccured(KeyEvent keyEvent) {
284: if (keyEvent.character == '\u001b') { // Escape character
285: fireCancelEditor();
286: } else if (keyEvent.character == '\t') { // tab key
287: applyEditorValueAndDeactivate();
288: }
289: }
290: }
|