001: /*
002: *Copyright 2007 Wilken GmbH
003: */
004: package gui.section;
005:
006: import org.eclipse.core.runtime.Assert;
007: import org.eclipse.jface.viewers.CellEditor;
008: import org.eclipse.swt.SWT;
009: import org.eclipse.swt.custom.CCombo;
010: import org.eclipse.swt.events.FocusAdapter;
011: import org.eclipse.swt.events.FocusEvent;
012: import org.eclipse.swt.events.KeyAdapter;
013: import org.eclipse.swt.events.KeyEvent;
014: import org.eclipse.swt.events.ModifyEvent;
015: import org.eclipse.swt.events.ModifyListener;
016: import org.eclipse.swt.events.SelectionAdapter;
017: import org.eclipse.swt.events.SelectionEvent;
018: import org.eclipse.swt.events.TraverseEvent;
019: import org.eclipse.swt.events.TraverseListener;
020: import org.eclipse.swt.graphics.GC;
021: import org.eclipse.swt.widgets.Composite;
022: import org.eclipse.swt.widgets.Control;
023:
024: /**
025: * A cell editor that presents a list of items in a combo box
026: * and allows to edit the content of the editor.
027: * The cell editor's value is the zero-based index of the selected
028: * item.
029: * <p>
030: * This class may be instantiated; it is not intended to be subclassed.
031: * </p>
032: */
033: public class StringComboBoxCellEditor extends CellEditor {
034:
035: /**
036: * The list of items to present in the combo box.
037: */
038: protected String[] items;
039:
040: /**
041: * The zero-based index of the selected item.
042: */
043: private int selection;
044:
045: /**
046: * The custom combo box control.
047: */
048: protected CCombo comboBox;
049:
050: /**
051: * Default ComboBoxCellEditor style
052: */
053: private static final int defaultStyle = SWT.NONE;
054:
055: private ModifyListener modifyListener;
056:
057: /**
058: * Creates a new cell editor with no control and no st of choices. Initially,
059: * the cell editor has no cell validator.
060: *
061: * @since 2.1
062: * @see #setStyle
063: * @see #create
064: * @see #setItems
065: * @see #dispose
066: */
067:
068: public StringComboBoxCellEditor() {
069: setStyle(defaultStyle);
070: }
071:
072: /**
073: * Creates a new cell editor with a combo containing the given
074: * list of choices and parented under the given control. The cell
075: * editor value is the zero-based index of the selected item.
076: * Initially, the cell editor has no cell validator and
077: * the first item in the list is selected.
078: *
079: * @param parent the parent control
080: * @param items the list of strings for the combo box
081: */
082: public StringComboBoxCellEditor(Composite parent, String[] items) {
083: this (parent, items, defaultStyle);
084: }
085:
086: /**
087: * Creates a new cell editor with a combo containing the given
088: * list of choices and parented under the given control. The cell
089: * editor value is the zero-based index of the selected item.
090: * Initially, the cell editor has no cell validator and
091: * the first item in the list is selected.
092: *
093: * @param parent the parent control
094: * @param items the list of strings for the combo box
095: * @param style the style bits
096: * @since 2.1
097: */
098: public StringComboBoxCellEditor(Composite parent, String[] items,
099: int style) {
100: super (parent, style);
101: setItems(items);
102: }
103:
104: public StringComboBoxCellEditor(Composite parent) {
105: this (parent, new String[0]);
106: }
107:
108: /**
109: * Returns the list of choices for the combo box
110: *
111: * @return the list of choices for the combo box
112: */
113: public String[] getItems() {
114: return this .items;
115: }
116:
117: /**
118: * Sets the list of choices for the combo box
119: *
120: * @param items the list of choices for the combo box
121: */
122: public void setItems(String[] items) {
123: Assert.isNotNull(items);
124: this .items = items;
125: populateComboBoxItems();
126: }
127:
128: protected Control createControl(Composite parent) {
129: comboBox = new CCombo(parent, getStyle());
130: comboBox.setFont(parent.getFont());
131: comboBox.addKeyListener(new KeyAdapter() {
132: public void keyPressed(KeyEvent e) {
133: keyReleaseOccured(e);
134: }
135: });
136:
137: comboBox.addSelectionListener(new SelectionAdapter() {
138: public void widgetDefaultSelected(SelectionEvent event) {
139: applyEditorValueAndDeactivate();
140: }
141: });
142:
143: comboBox.addTraverseListener(new TraverseListener() {
144: public void keyTraversed(TraverseEvent e) {
145: if (e.detail == SWT.TRAVERSE_ESCAPE
146: || e.detail == SWT.TRAVERSE_RETURN) {
147: e.doit = false;
148: }
149: }
150: });
151:
152: comboBox.addFocusListener(new FocusAdapter() {
153: public void focusLost(FocusEvent e) {
154: StringComboBoxCellEditor.this .focusLost();
155: }
156: });
157:
158: comboBox.addModifyListener(getModifyListener());
159: return comboBox;
160: }
161:
162: /**
163: * The <code>ComboBoxCellEditor</code> implementation of
164: * this <code>CellEditor</code> framework method returns
165: * the zero-based index of the current selection.
166: *
167: * @return the zero-based index of the current selection wrapped
168: * as an <code>Integer</code>
169: */
170: protected Object doGetValue() {
171: //********************************************************
172: //* The doGetValue() must handle the 2 possible cases, if
173: //* called. It could be, that a selection in the dropdown
174: //* was made, then use the selectionIndex. Or a direct
175: //* editing action was made and then it is necessary to
176: //* use getText() to get the result of the CComboBoxEditor.
177: //*********************************************************
178: int curSelected = comboBox.getSelectionIndex();
179: String strComboSelectedContent = null;
180: if (curSelected != -1) {
181: strComboSelectedContent = comboBox.getItem(curSelected);
182: } else {
183: strComboSelectedContent = comboBox.getText();
184: }
185:
186: return strComboSelectedContent;
187: }
188:
189: protected void doSetFocus() {
190: comboBox.setFocus();
191: }
192:
193: /**
194: * method getLayoutData ( overwriting method )
195: *
196: * The <code>StringComboBoxCellEditor</code> implementation of
197: * this <code>CellEditor</code> framework method sets the
198: * minimum width of the cell. The minimum width is 10 characters
199: * if <code>comboBox</code> is not <code>null</code> or <code>disposed</code>
200: * eles it is 60 pixels to make sure the arrow button and some text is visible.
201: * The list of CCombo will be wide enough to show its longest item.
202: *
203: * Import are the grabHorizontal and the horizontalAlignment settings, because
204: * so you can control, that the button for dropdownbox is at the right corner
205: * of your parent composite. In the CellEditor implementation it would be outside
206: * the parent control (as wide as the longest item in the dropdown list.
207: */
208: public LayoutData getLayoutData() {
209: LayoutData layoutData = super .getLayoutData();
210: if ((comboBox == null) || comboBox.isDisposed()) {
211: layoutData.minimumWidth = 60;
212: layoutData.grabHorizontal = true;
213: layoutData.horizontalAlignment = SWT.RIGHT;
214: } else {
215: // make the comboBox 10 characters wide
216: GC gc = new GC(comboBox);
217: layoutData.minimumWidth = (gc.getFontMetrics()
218: .getAverageCharWidth() * 10) + 10;
219: layoutData.grabHorizontal = true;
220: layoutData.horizontalAlignment = SWT.RIGHT;
221: gc.dispose();
222: }
223: return layoutData;
224: }
225:
226: /**
227: * The <code>ComboBoxCellEditor</code> implementation of
228: * this <code>CellEditor</code> framework method
229: * accepts a zero-based index of a selection.
230: *
231: * @param value the zero-based index of the selection wrapped
232: * as an <code>Integer</code>
233: */
234: protected void doSetValue(Object value) {
235: Assert
236: .isTrue(comboBox != null
237: && ((value instanceof Integer) || (value instanceof String)));
238:
239: if (value instanceof Integer) {
240: selection = ((Integer) value).intValue();
241: comboBox.select(selection);
242: } else if (value instanceof String) {
243: comboBox.setText((String) value);
244: }
245: }
246:
247: /**
248: * Updates the list of choices for the combo box for the current control.
249: *
250: */
251: private void populateComboBoxItems() {
252: int num = 0;
253:
254: if (comboBox != null && items != null) {
255: num = comboBox.getItemCount();
256: comboBox.remove(0, num - 1);
257:
258: for (int i = 0; i < items.length; i++)
259: comboBox.add(items[i], i);
260:
261: setValueValid(true);
262: selection = 0;
263: }
264: }
265:
266: /**
267: * Applies the currently selected value if they are valid
268: * and deactiavates the cell editor;
269: */
270: private void applyEditorValueAndDeactivate() {
271: // must set the selection before getting value
272: selection = comboBox.getSelectionIndex();
273: Object newValue = doGetValue();
274: markDirty();
275: boolean isValid = isCorrect(newValue);
276: setValueValid(isValid);
277:
278: if (!isValid) {
279: // try to insert the current value into the error message.
280: setErrorMessage(getErrorMessage());
281: } else {
282: fireApplyEditorValue();
283: deactivate();
284: }
285: }
286:
287: protected void focusLost() {
288: if (isActivated()) {
289: applyEditorValueAndDeactivate();
290: }
291: }
292:
293: /**
294: * Return the modify listener.
295: */
296: private ModifyListener getModifyListener() {
297: if (modifyListener == null) {
298: modifyListener = new ModifyListener() {
299: public void modifyText(ModifyEvent e) {
300: //editOccured(e);
301: fireEditorValueChanged(true, true);
302: }
303: };
304: }
305: return modifyListener;
306: }
307:
308: protected void keyReleaseOccured(KeyEvent keyEvent) {
309: if (keyEvent.character == '\u001b') {
310: // Escape character
311: fireCancelEditor();
312: } else if (keyEvent.character == '\t') { // tab key
313: applyEditorValueAndDeactivate();
314: }
315: }
316: }
|