在TableViewer或TreeViewer编辑时候,Eclipse提供了基本的CellEditor,如TextCellEditor、CheckboxCellEditor、ComboBoxCellEditor、DialogCellEditor等,但在实际应用过程中,我们通常有特殊需要,如下图类型的单元格编辑器:

实现的方式相当简单,我组合了ComboBoxCellEditor、DialogCellEditor,其中ComboBox支持手工输入,返回为String类型值(原ComboBoxCellEditor为Integer类型),贴下具体代码吧:
package com.test.ui.properties.invoke;

import java.text.MessageFormat;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Layout;


public abstract class ComboBoxDialogCellEditor extends CellEditor
{

//Combo Items
private String[] items;

private Composite editor;
private CCombo comboBox;
private Control contents;
private Button button;
private FocusListener buttonFocusListener;

private ModifyListener modifyListener;
private Object value = null;


/** *//**
* Internal class for laying out the dialog.
*/

private class DialogCellLayout extends Layout
{

public void layout(Composite editor, boolean force)
{
Rectangle bounds = editor.getClientArea();
Point size = button.computeSize(SWT.DEFAULT, SWT.DEFAULT, force);

if (contents != null)
{
contents.setBounds(0, 0, bounds.width - size.x, bounds.height);
}
button.setBounds(bounds.width - size.x, 0, size.x, bounds.height);
}

public Point computeSize(Composite editor, int wHint, int hHint,

boolean force)
{

if (wHint != SWT.DEFAULT && hHint != SWT.DEFAULT)
{
return new Point(wHint, hHint);
}
Point contentsSize = contents.computeSize(SWT.DEFAULT, SWT.DEFAULT,
force);
Point buttonSize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT,
force);
// Just return the button width to ensure the button is not clipped
// if the label is long.
// The label will just use whatever extra width there is
Point result = new Point(buttonSize.x, Math.max(contentsSize.y,
buttonSize.y));
return result;
}
}

//Combo default style
private static final int defaultStyle = SWT.NONE;


public ComboBoxDialogCellEditor()
{
setStyle(defaultStyle);
}


public ComboBoxDialogCellEditor(Composite parent, String[] items)
{
this(parent, items, defaultStyle);
}


public ComboBoxDialogCellEditor(Composite parent, String[] items, int style)
{
super(parent, style);
setItems(items);
}


public String[] getItems()
{
return items;
}


public void setItems(String[] items)
{
Assert.isNotNull(items);
this.items = items;
populateComboBoxItems();
}

protected Button createButton(Composite parent)
{
Button result = new Button(parent, SWT.DOWN);
result.setText("
"); //$NON-NLS-1$
return result;
}


protected Control createContents(Composite cell)
{
comboBox = new CCombo(cell, getStyle());
comboBox.setFont(cell.getFont());
populateComboBoxItems();


comboBox.addKeyListener(new KeyAdapter()
{

public void keyPressed(KeyEvent e)
{
keyReleaseOccured(e);
}
});

comboBox.addModifyListener(getModifyListener());


comboBox.addSelectionListener(new SelectionAdapter()
{

public void widgetDefaultSelected(SelectionEvent event)
{
applyEditorValueAndDeactivate();
}

public void widgetSelected(SelectionEvent event)
{
value = comboBox.getText();
}
});

comboBox.addTraverseListener(new TraverseListener()
{

public void keyTraversed(TraverseEvent e)
{
if (e.detail == SWT.TRAVERSE_ESCAPE

|| e.detail == SWT.TRAVERSE_RETURN)
{
e.doit = false;
}
}
});


comboBox.addFocusListener(new FocusAdapter()
{

public void focusLost(FocusEvent e)
{

if(!button.isFocusControl())
{
ComboBoxDialogCellEditor.this.focusLost();
}
}
});

return comboBox;
}
@Override

protected Control createControl(Composite parent)
{
Font font = parent.getFont();
Color bg = parent.getBackground();

editor = new Composite(parent, getStyle());
editor.setFont(font);
editor.setBackground(bg);
editor.setLayout(new DialogCellLayout());

contents = createContents(editor);
updateContents(value);
button = createButton(editor);
button.setFont(font);


button.addKeyListener(new KeyAdapter()
{

public void keyReleased(KeyEvent e)
{

if (e.character == '\u001b')
{ // Escape
fireCancelEditor();
}
}
});
button.addFocusListener(getButtonFocusListener());

button.addSelectionListener(new SelectionAdapter()
{

public void widgetSelected(SelectionEvent event)
{
button.removeFocusListener(getButtonFocusListener());
Object newValue = openDialogBox(editor);
button.addFocusListener(getButtonFocusListener());

if (newValue != null)
{
boolean newValidState = isCorrect(newValue);

if (newValidState)
{
markDirty();
doSetValue(newValue);

} else
{
setErrorMessage(MessageFormat.format(getErrorMessage(),

new Object[]
{ newValue.toString() }));
}
fireApplyEditorValue();
}
}
});

setValueValid(true);
return editor;
}


public void deactivate()
{

if (button != null && !button.isDisposed())
{
button.removeFocusListener(getButtonFocusListener());
}
super.deactivate();
}

@Override

protected Object doGetValue()
{
return value;
}

@Override

protected void doSetFocus()
{
if (comboBox != null)
comboBox.setFocus();
}

@Override

protected void doSetValue(Object value)
{
this.value = value;
updateContents(value);
}


private void populateComboBoxItems()
{

if (comboBox != null && items != null)
{
comboBox.removeAll();

for (int i = 0; i < items.length; i++)
{
comboBox.add(items[i], i);
}
comboBox.setText("");
}
}


void applyEditorValueAndDeactivate()
{
Object newValue = comboBox.getText();

if (newValue != null && !newValue.equals(value.toString()))
{
boolean newValidState = isCorrect(newValue);

if (newValidState)
{
markDirty();
doSetValue(newValue);

} else
{
setErrorMessage(MessageFormat.format(getErrorMessage(),

new Object[]
{ newValue.toString() }));
}
}
fireApplyEditorValue();
deactivate();
}

/**//*
* (non-Javadoc)
* @see org.eclipse.jface.viewers.CellEditor#focusLost()
*/

protected void focusLost()
{

if (isActivated())
{
applyEditorValueAndDeactivate();
}
}


/**//*
* (non-Javadoc)
* @see org.eclipse.jface.viewers.CellEditor#keyReleaseOccured(org.eclipse.swt.events.KeyEvent)
*/

protected void keyReleaseOccured(KeyEvent keyEvent)
{

if (keyEvent.character == '\r')
{ // Return key
if (comboBox != null && !comboBox.isDisposed())
fireCancelEditor();

} else if (keyEvent.character == '\t')
{ // tab key
applyEditorValueAndDeactivate();
}
}


protected void editOccured(ModifyEvent e)
{
String value = comboBox.getText();

if (value == null)
{
value = "";//$NON-NLS-1$
}
Object typedValue = value;
boolean oldValidState = isValueValid();
boolean newValidState = isCorrect(typedValue);

if (typedValue == null && newValidState)
{
Assert.isTrue(false,
"Validator isn't limiting the cell editor's type range");//$NON-NLS-1$
}

if (!newValidState)
{
// try to insert the current value into the error message.
setErrorMessage(MessageFormat.format(getErrorMessage(),

new Object[]
{ value }));
}
valueChanged(oldValidState, newValidState);
}


private ModifyListener getModifyListener()
{

if (modifyListener == null)
{

modifyListener = new ModifyListener()
{

public void modifyText(ModifyEvent e)
{
editOccured(e);
}
};
}
return modifyListener;
}


private FocusListener getButtonFocusListener()
{

if (buttonFocusListener == null)
{

buttonFocusListener = new FocusListener()
{

public void focusGained(FocusEvent e)
{};

public void focusLost(FocusEvent e)
{
ComboBoxDialogCellEditor.this.focusLost();
}
};
};
return buttonFocusListener;
}


private void updateContents(Object value)
{
Assert.isTrue(comboBox != null);

if (value != null && value instanceof String)
{
comboBox.removeModifyListener(getModifyListener());
comboBox.setText((String) value);
comboBox.addModifyListener(getModifyListener());
}
}
protected abstract Object openDialogBox(Control cellEditorWindow);

}

posted on 2008-06-02 13:46
自由 阅读(3930)
评论(2) 编辑 收藏 所属分类:
SWT