Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 174739 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/jface/viewers/ComboBoxCellEditor.java (-249 / +323 lines)
Lines 11-17 Link Here
11
11
12
package org.eclipse.jface.viewers;
12
package org.eclipse.jface.viewers;
13
13
14
import java.text.MessageFormat;	// Not using ICU to support standalone JFace scenario
14
import java.text.MessageFormat; // Not using ICU to support standalone JFace
15
// scenario
15
16
16
import org.eclipse.core.runtime.Assert;
17
import org.eclipse.core.runtime.Assert;
17
import org.eclipse.swt.SWT;
18
import org.eclipse.swt.SWT;
Lines 29-291 Link Here
29
import org.eclipse.swt.widgets.Control;
30
import org.eclipse.swt.widgets.Control;
30
31
31
/**
32
/**
32
 * A cell editor that presents a list of items in a combo box.
33
 * A cell editor that presents a list of items in a combo box. The cell editor's
33
 * The cell editor's value is the zero-based index of the selected
34
 * value is the zero-based index of the selected item.
34
 * item.
35
 * <p>
35
 * <p>
36
 * This class may be instantiated; it is not intended to be subclassed.
36
 * This class may be instantiated; it is not intended to be subclassed.
37
 * </p>
37
 * </p>
38
 */
38
 */
39
public class ComboBoxCellEditor extends CellEditor {
39
public class ComboBoxCellEditor extends CellEditor {
40
40
41
    /**
41
	/**
42
     * The list of items to present in the combo box.
42
	 * The list of items to present in the combo box.
43
     */
43
	 */
44
    private String[] items;
44
	private String[] items;
45
45
46
    /**
46
	/**
47
     * The zero-based index of the selected item.
47
	 * The zero-based index of the selected item.
48
     */
48
	 */
49
    int selection;
49
	int selection;
50
50
51
    /**
51
	/**
52
     * The custom combo box control.
52
	 * The custom combo box control.
53
     */
53
	 */
54
    CCombo comboBox;
54
	CCombo comboBox;
55
55
56
    /**
56
	/**
57
     * Default ComboBoxCellEditor style
57
	 * Default ComboBoxCellEditor style
58
     */
58
	 */
59
    private static final int defaultStyle = SWT.NONE;
59
	private static final int defaultStyle = SWT.NONE;
60
60
61
    /**
61
	/**
62
     * Creates a new cell editor with no control and no  st of choices. Initially,
62
	 * The list is dropped down when the activation is done through the mouse
63
     * the cell editor has no cell validator.
63
	 */
64
     * 
64
	public static final int DROP_DOWN_ON_MOUSE_ACTIVATION = 1;
65
     * @since 2.1
65
66
     * @see CellEditor#setStyle
66
	/**
67
     * @see CellEditor#create
67
	 * The list is dropped down when the activation is done through the keyboard
68
     * @see ComboBoxCellEditor#setItems
68
	 */
69
     * @see CellEditor#dispose
69
	public static final int DROP_DOWN_ON_KEY_ACTIVATION = 1 << 1;
70
     */
70
71
    public ComboBoxCellEditor() {
71
	/**
72
        setStyle(defaultStyle);
72
	 * The list is dropped down when the activation is done without
73
    }
73
	 * ui-interaction
74
74
	 */
75
    /**
75
	public static final int DROP_DOWN_ON_PROGRAMMATIC_ACTIVATION = 1 << 2;
76
     * Creates a new cell editor with a combo containing the given 
76
77
     * list of choices and parented under the given control. The cell
77
	/**
78
     * editor value is the zero-based index of the selected item.
78
	 * The list is dropped down when the activation is done by traversing from
79
     * Initially, the cell editor has no cell validator and
79
	 * cell to cell
80
     * the first item in the list is selected. 
80
	 */
81
     *
81
	public static final int DROP_DOWN_ON_TRAVSE_ACTIVATION = 1 << 3;
82
     * @param parent the parent control
82
83
     * @param items the list of strings for the combo box
83
	private int activationStyle = SWT.NONE;
84
     */
84
85
    public ComboBoxCellEditor(Composite parent, String[] items) {
85
	/**
86
        this(parent, items, defaultStyle);
86
	 * Creates a new cell editor with no control and no st of choices.
87
    }
87
	 * Initially, the cell editor has no cell validator.
88
88
	 *
89
    /**
89
	 * @since 2.1
90
     * Creates a new cell editor with a combo containing the given 
90
	 * @see CellEditor#setStyle
91
     * list of choices and parented under the given control. The cell
91
	 * @see CellEditor#create
92
     * editor value is the zero-based index of the selected item.
92
	 * @see ComboBoxCellEditor#setItems
93
     * Initially, the cell editor has no cell validator and
93
	 * @see CellEditor#dispose
94
     * the first item in the list is selected. 
94
	 */
95
     *
95
	public ComboBoxCellEditor() {
96
     * @param parent the parent control
96
		setStyle(defaultStyle);
97
     * @param items the list of strings for the combo box
97
	}
98
     * @param style the style bits
98
99
     * @since 2.1
99
	/**
100
     */
100
	 * Creates a new cell editor with a combo containing the given list of
101
    public ComboBoxCellEditor(Composite parent, String[] items, int style) {
101
	 * choices and parented under the given control. The cell editor value is
102
        super(parent, style);
102
	 * the zero-based index of the selected item. Initially, the cell editor has
103
        setItems(items);
103
	 * no cell validator and the first item in the list is selected.
104
    }
104
	 *
105
105
	 * @param parent
106
    /**
106
	 *            the parent control
107
     * Returns the list of choices for the combo box
107
	 * @param items
108
     *
108
	 *            the list of strings for the combo box
109
     * @return the list of choices for the combo box
109
	 */
110
     */
110
	public ComboBoxCellEditor(Composite parent, String[] items) {
111
    public String[] getItems() {
111
		this(parent, items, defaultStyle);
112
        return this.items;
112
	}
113
    }
113
114
114
	/**
115
    /**
115
	 * Creates a new cell editor with a combo containing the given list of
116
     * Sets the list of choices for the combo box
116
	 * choices and parented under the given control. The cell editor value is
117
     *
117
	 * the zero-based index of the selected item. Initially, the cell editor has
118
     * @param items the list of choices for the combo box
118
	 * no cell validator and the first item in the list is selected.
119
     */
119
	 *
120
    public void setItems(String[] items) {
120
	 * @param parent
121
        Assert.isNotNull(items);
121
	 *            the parent control
122
        this.items = items;
122
	 * @param items
123
        populateComboBoxItems();
123
	 *            the list of strings for the combo box
124
    }
124
	 * @param style
125
125
	 *            the style bits
126
    /* (non-Javadoc)
126
	 * @since 2.1
127
     * Method declared on CellEditor.
127
	 */
128
     */
128
	public ComboBoxCellEditor(Composite parent, String[] items, int style) {
129
    protected Control createControl(Composite parent) {
129
		super(parent, style);
130
130
		setItems(items);
131
        comboBox = new CCombo(parent, getStyle());
131
	}
132
        comboBox.setFont(parent.getFont());
132
133
        
133
	/**
134
        populateComboBoxItems();
134
	 * Returns the list of choices for the combo box
135
135
	 *
136
        comboBox.addKeyListener(new KeyAdapter() {
136
	 * @return the list of choices for the combo box
137
            // hook key pressed - see PR 14201  
137
	 */
138
            public void keyPressed(KeyEvent e) {
138
	public String[] getItems() {
139
                keyReleaseOccured(e);
139
		return this.items;
140
            }
140
	}
141
        });
141
142
142
	/**
143
        comboBox.addSelectionListener(new SelectionAdapter() {
143
	 * Sets the list of choices for the combo box
144
            public void widgetDefaultSelected(SelectionEvent event) {
144
	 *
145
                applyEditorValueAndDeactivate();
145
	 * @param items
146
            }
146
	 *            the list of choices for the combo box
147
147
	 */
148
            public void widgetSelected(SelectionEvent event) {
148
	public void setItems(String[] items) {
149
                selection = comboBox.getSelectionIndex();
149
		Assert.isNotNull(items);
150
            }
150
		this.items = items;
151
        });
151
		populateComboBoxItems();
152
152
	}
153
        comboBox.addTraverseListener(new TraverseListener() {
153
154
            public void keyTraversed(TraverseEvent e) {
154
	/*
155
                if (e.detail == SWT.TRAVERSE_ESCAPE
155
	 * (non-Javadoc) Method declared on CellEditor.
156
                        || e.detail == SWT.TRAVERSE_RETURN) {
156
	 */
157
                    e.doit = false;
157
	protected Control createControl(Composite parent) {
158
                }
158
159
            }
159
		comboBox = new CCombo(parent, getStyle());
160
        });
160
		comboBox.setFont(parent.getFont());
161
161
162
        comboBox.addFocusListener(new FocusAdapter() {
162
		populateComboBoxItems();
163
            public void focusLost(FocusEvent e) {
163
164
                ComboBoxCellEditor.this.focusLost();
164
		comboBox.addKeyListener(new KeyAdapter() {
165
            }
165
			// hook key pressed - see PR 14201
166
        });
166
			public void keyPressed(KeyEvent e) {
167
        return comboBox;
167
				keyReleaseOccured(e);
168
    }
168
			}
169
169
		});
170
    /**
170
171
     * The <code>ComboBoxCellEditor</code> implementation of
171
		comboBox.addSelectionListener(new SelectionAdapter() {
172
     * this <code>CellEditor</code> framework method returns
172
			public void widgetDefaultSelected(SelectionEvent event) {
173
     * the zero-based index of the current selection.
173
				applyEditorValueAndDeactivate();
174
     *
174
			}
175
     * @return the zero-based index of the current selection wrapped
175
176
     *  as an <code>Integer</code>
176
			public void widgetSelected(SelectionEvent event) {
177
     */
177
				selection = comboBox.getSelectionIndex();
178
    protected Object doGetValue() {
178
			}
179
        return new Integer(selection);
179
		});
180
    }
180
181
181
		comboBox.addTraverseListener(new TraverseListener() {
182
    /* (non-Javadoc)
182
			public void keyTraversed(TraverseEvent e) {
183
     * Method declared on CellEditor.
183
				if (e.detail == SWT.TRAVERSE_ESCAPE
184
     */
184
						|| e.detail == SWT.TRAVERSE_RETURN) {
185
    protected void doSetFocus() {
185
					e.doit = false;
186
        comboBox.setFocus();
186
				}
187
    }
187
			}
188
188
		});
189
    /**
189
190
     * The <code>ComboBoxCellEditor</code> implementation of
190
		comboBox.addFocusListener(new FocusAdapter() {
191
     * this <code>CellEditor</code> framework method sets the 
191
			public void focusLost(FocusEvent e) {
192
     * minimum width of the cell.  The minimum width is 10 characters
192
				ComboBoxCellEditor.this.focusLost();
193
     * if <code>comboBox</code> is not <code>null</code> or <code>disposed</code>
193
			}
194
     * else it is 60 pixels to make sure the arrow button and some text is visible.
194
		});
195
     * The list of CCombo will be wide enough to show its longest item.
195
		return comboBox;
196
     */
196
	}
197
    public LayoutData getLayoutData() {
197
198
        LayoutData layoutData = super.getLayoutData();
198
	/**
199
        if ((comboBox == null) || comboBox.isDisposed()) {
199
	 * The <code>ComboBoxCellEditor</code> implementation of this
200
	 * <code>CellEditor</code> framework method returns the zero-based index
201
	 * of the current selection.
202
	 *
203
	 * @return the zero-based index of the current selection wrapped as an
204
	 *         <code>Integer</code>
205
	 */
206
	protected Object doGetValue() {
207
		return new Integer(selection);
208
	}
209
210
	/*
211
	 * (non-Javadoc) Method declared on CellEditor.
212
	 */
213
	protected void doSetFocus() {
214
		comboBox.setFocus();
215
	}
216
217
	/**
218
	 * The <code>ComboBoxCellEditor</code> implementation of this
219
	 * <code>CellEditor</code> framework method sets the minimum width of the
220
	 * cell. The minimum width is 10 characters if <code>comboBox</code> is
221
	 * not <code>null</code> or <code>disposed</code> else it is 60 pixels
222
	 * to make sure the arrow button and some text is visible. The list of
223
	 * CCombo will be wide enough to show its longest item.
224
	 */
225
	public LayoutData getLayoutData() {
226
		LayoutData layoutData = super.getLayoutData();
227
		if ((comboBox == null) || comboBox.isDisposed()) {
200
			layoutData.minimumWidth = 60;
228
			layoutData.minimumWidth = 60;
201
		} else {
229
		} else {
202
            // make the comboBox 10 characters wide
230
			// make the comboBox 10 characters wide
203
            GC gc = new GC(comboBox);
231
			GC gc = new GC(comboBox);
204
            layoutData.minimumWidth = (gc.getFontMetrics()
232
			layoutData.minimumWidth = (gc.getFontMetrics()
205
                    .getAverageCharWidth() * 10) + 10;
233
					.getAverageCharWidth() * 10) + 10;
206
            gc.dispose();
234
			gc.dispose();
207
        }
235
		}
208
        return layoutData;
236
		return layoutData;
209
    }
237
	}
210
238
211
    /**
239
	/**
212
     * The <code>ComboBoxCellEditor</code> implementation of
240
	 * The <code>ComboBoxCellEditor</code> implementation of this
213
     * this <code>CellEditor</code> framework method
241
	 * <code>CellEditor</code> framework method accepts a zero-based index of
214
     * accepts a zero-based index of a selection.
242
	 * a selection.
215
     *
243
	 *
216
     * @param value the zero-based index of the selection wrapped
244
	 * @param value
217
     *   as an <code>Integer</code>
245
	 *            the zero-based index of the selection wrapped as an
218
     */
246
	 *            <code>Integer</code>
219
    protected void doSetValue(Object value) {
247
	 */
220
        Assert.isTrue(comboBox != null && (value instanceof Integer));
248
	protected void doSetValue(Object value) {
221
        selection = ((Integer) value).intValue();
249
		Assert.isTrue(comboBox != null && (value instanceof Integer));
222
        comboBox.select(selection);
250
		selection = ((Integer) value).intValue();
223
    }
251
		comboBox.select(selection);
224
252
	}
225
    /**
253
226
     * Updates the list of choices for the combo box for the current control.
254
	/**
227
     */
255
	 * Updates the list of choices for the combo box for the current control.
228
    private void populateComboBoxItems() {
256
	 */
229
        if (comboBox != null && items != null) {
257
	private void populateComboBoxItems() {
230
            comboBox.removeAll();
258
		if (comboBox != null && items != null) {
231
            for (int i = 0; i < items.length; i++) {
259
			comboBox.removeAll();
260
			for (int i = 0; i < items.length; i++) {
232
				comboBox.add(items[i], i);
261
				comboBox.add(items[i], i);
233
			}
262
			}
234
263
235
            setValueValid(true);
264
			setValueValid(true);
236
            selection = 0;
265
			selection = 0;
237
        }
266
		}
238
    }
267
	}
239
268
240
    /**
269
	/**
241
     * Applies the currently selected value and deactivates the cell editor
270
	 * Applies the currently selected value and deactivates the cell editor
242
     */
271
	 */
243
    void applyEditorValueAndDeactivate() {
272
	void applyEditorValueAndDeactivate() {
244
        //	must set the selection before getting value
273
		// must set the selection before getting value
245
        selection = comboBox.getSelectionIndex();
274
		selection = comboBox.getSelectionIndex();
246
        Object newValue = doGetValue();
275
		Object newValue = doGetValue();
247
        markDirty();
276
		markDirty();
248
        boolean isValid = isCorrect(newValue);
277
		boolean isValid = isCorrect(newValue);
249
        setValueValid(isValid);
278
		setValueValid(isValid);
250
        
279
251
        if (!isValid) {
280
		if (!isValid) {
252
        	// Only format if the 'index' is valid
281
			// Only format if the 'index' is valid
253
        	if (items.length > 0 && selection >= 0 && selection < items.length) {
282
			if (items.length > 0 && selection >= 0 && selection < items.length) {
254
	            // try to insert the current value into the error message.
283
				// try to insert the current value into the error message.
255
	            setErrorMessage(MessageFormat.format(getErrorMessage(),
284
				setErrorMessage(MessageFormat.format(getErrorMessage(),
256
	                    new Object[] { items[selection] }));
285
						new Object[] { items[selection] }));
257
        	}
286
			} else {
258
        	else {
287
				// Since we don't have a valid index, assume we're using an
259
	            // Since we don't have a valid index, assume we're using an 'edit'
288
				// 'edit'
260
        		// combo so format using its text value
289
				// combo so format using its text value
261
	            setErrorMessage(MessageFormat.format(getErrorMessage(),
290
				setErrorMessage(MessageFormat.format(getErrorMessage(),
262
	                    new Object[] { comboBox.getText() }));
291
						new Object[] { comboBox.getText() }));
263
        	}
292
			}
264
        }
293
		}
265
294
266
        fireApplyEditorValue();
295
		fireApplyEditorValue();
267
        deactivate();
296
		deactivate();
268
    }
297
	}
269
298
270
    /*
299
	/*
271
     *  (non-Javadoc)
300
	 * (non-Javadoc)
272
     * @see org.eclipse.jface.viewers.CellEditor#focusLost()
301
	 *
273
     */
302
	 * @see org.eclipse.jface.viewers.CellEditor#focusLost()
274
    protected void focusLost() {
303
	 */
275
        if (isActivated()) {
304
	protected void focusLost() {
276
            applyEditorValueAndDeactivate();
305
		if (isActivated()) {
277
        }
306
			applyEditorValueAndDeactivate();
278
    }
307
		}
279
308
	}
280
    /*
309
281
     *  (non-Javadoc)
310
	/*
282
     * @see org.eclipse.jface.viewers.CellEditor#keyReleaseOccured(org.eclipse.swt.events.KeyEvent)
311
	 * (non-Javadoc)
283
     */
312
	 *
284
    protected void keyReleaseOccured(KeyEvent keyEvent) {
313
	 * @see org.eclipse.jface.viewers.CellEditor#keyReleaseOccured(org.eclipse.swt.events.KeyEvent)
285
        if (keyEvent.character == '\u001b') { // Escape character
314
	 */
286
            fireCancelEditor();
315
	protected void keyReleaseOccured(KeyEvent keyEvent) {
287
        } else if (keyEvent.character == '\t') { // tab key
316
		if (keyEvent.character == '\u001b') { // Escape character
288
            applyEditorValueAndDeactivate();
317
			fireCancelEditor();
289
        }
318
		} else if (keyEvent.character == '\t') { // tab key
290
    }
319
			applyEditorValueAndDeactivate();
320
		}
321
	}
322
323
	/*
324
	 * (non-Javadoc)
325
	 *
326
	 * @see org.eclipse.jface.viewers.CellEditor#activate(org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent)
327
	 */
328
	public void activate(ColumnViewerEditorActivationEvent activationEvent) {
329
		super.activate(activationEvent);
330
		if( activationStyle != SWT.NONE ) {
331
			boolean dropDown = false;
332
			if ((activationEvent.eventType == ColumnViewerEditorActivationEvent.MOUSE_CLICK_SELECTION || activationEvent.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION)
333
					&& (activationStyle & DROP_DOWN_ON_MOUSE_ACTIVATION) == DROP_DOWN_ON_MOUSE_ACTIVATION) {
334
				dropDown = true;
335
			} else if( activationEvent.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && (activationStyle & DROP_DOWN_ON_KEY_ACTIVATION) == DROP_DOWN_ON_KEY_ACTIVATION ) {
336
				dropDown = true;
337
			} else if( activationEvent.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC && (activationStyle & DROP_DOWN_ON_PROGRAMMATIC_ACTIVATION) == DROP_DOWN_ON_PROGRAMMATIC_ACTIVATION ) {
338
				dropDown = true;
339
			} else if( activationEvent.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL && (activationStyle & DROP_DOWN_ON_TRAVSE_ACTIVATION) == DROP_DOWN_ON_TRAVSE_ACTIVATION ) {
340
				dropDown = true;
341
			}
342
343
			if( dropDown ) {
344
				getControl().getDisplay().asyncExec(new Runnable() {
345
346
					public void run() {
347
						((CCombo)getControl()).setListVisible(true);
348
					}
349
350
				});
351
352
			}
353
		}
354
	}
355
356
	/**
357
	 * This method allows to control how the combo reacts when activated
358
	 *
359
	 * @param activationStyle
360
	 *            the style used
361
	 */
362
	public void setActivationStyle(int activationStyle) {
363
		this.activationStyle = activationStyle;
364
	}
291
}
365
}

Return to bug 174739