JFace的TableViewer中,通过方法TableViewer.setCellEditors(…)方法可以设置每一列对应的CellEditor。但是如果这样做的话,就会导致无法根据当前行的信息来设置不同的CellEditor,这里介绍一种可以根据不同行设置同一列对应的CellEditor: EditingSupport。
TableColumn paramNameColumn = new TableColumn(table, SWT.NONE); paramNameColumn.setWidth(350); paramNameColumn.setText("参数名"); TableColumn paramValueColumn = new TableColumn(table, SWT.NONE); paramValueColumn.setWidth(400); paramValueColumn.setText("参数值"); commonParamTableViewer.setColumnProperties(COMMON_PARAM_TITLE); CellEditor[] cellEditors = new CellEditor[COMMON_PARAM_TITLE.length]; commonParamTableViewer.setCellEditors(cellEditors); TableViewerColumn paramNameViewerColumn = new TableViewerColumn(commonParamTableViewer, paramNameColumn); paramNameViewerColumn.setEditingSupport(new EmptyEditingSupport(commonParamTableViewer)); TableViewerColumn paramValueViewerColumn = new TableViewerColumn(commonParamTableViewer, paramValueColumn); paramValueViewerColumn.setEditingSupport(new ConfigurableEditingSupport(commonParamTableViewer, ruleEditorListener));
而对于EditingSupport有哪些方法?顾名思义,EditingSupport就是为了能够提供编辑支持,该字段能否编辑(canEdit),编辑时得到的值(getValue),编辑后设置的值(setValue),以及使用哪种编辑器(CellEditor)。
于是在getCellEditor方法中,就可以根据当前行值(方法中的参数element)设置对应不同的CellEditor。
对于特殊的参照式的Editor(如下图),在单击按钮时弹出对话框(对话框的内容自定义),是如何实现的?
eclipse中已经提供了用于dialog的celleditor类:
org.eclipse.jface.viewers.DialogCellEditor
我们可以直接从这点入手,进行扩展,其中的openDialogBox方法就是建立弹出对话框中的内容面板,用户可以在上面进行编辑,并得到返回值结果,这里我们在该方法中直接打开一个RefPaneDialog用于打开对应的对话框。
@Override protected Object openDialogBox(Control cellEditorWindow) { if (dialogComposite == null) { MessageDialog.openError(cellEditorWindow.getShell(), "", ""); returnnull; } // textEditorChanged = false; dialog = new RefPaneDialog(cellEditorWindow.getShell(), valueObj, dialogComposite); int result = dialog.open(); if(result == IDialogConstants.OK_ID) { valueObj = dialogComposite.getResultValue(); // if(valueObj != null){ text.setText(valueObj == null ? "" : dialogComposite.getDisplayText(valueObj)); text.setFocus(); } // } returnvalueObj; }
而对于对话框中的内容,这里采用了策略模式,交给具体的IDialogComposite来扩展,其中的主要方法和说明如下:
package com.yonyou.nc.codevalidator.runtime.plugin.celleditor; import java.util.List; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; /** * 参照对话框中用于定义的界面处理接口,其中包括显示数据,获取最终结果值操作等 * @author mazqa * */ public interface IDialogComposite { /** * 创建对话框界面Area * @param parent * @param value * @return */ public void createDialogArea(final Composite parent, Object value); /** * 创建对话框内容方法,可以更改对话框的大小和显示标题 * @param parent * @param value * @return */ public void createContents(final Control parent, Object value); /** * 得到对话框中显示的按钮 * @return */ public List<DialogButtonObj> getDialogButtons(); /** * 对按钮事件的处理方法 * @param buttonId */ public void buttonPressed(int buttonId); /** * 获取最终的返回结果对象, 如果不是同一个对象,最好返回序列化复制后的对象, * 以便能够在编辑完成后进行刷新 * @return */ public Object getResultValue(); /** * 在参照编辑状态中显示在左侧text中的值 * @param value * @return */ public String getDisplayText(Object value); /** * 从参照的text获得Object值, * @param textValue * @return * @throws Exception 转换失败,格式不正确时 */ public Object getObjectFromText(String textValue) throws Exception; /** * 参照前面的文本框是否可用,如果不可用{@link #getObjectFromText(String)}方法也不会被调用到 * @return */ public boolean isTextEnable(); /** * 参照非编辑状态显示的值 * @param value * @return */ public String getDisplayLabel(Object value); /** * 得到TitleAreaDialog中的标题内容 * @return */ public String getTitle(); /** * 得到TitleAreaDialog中的描述内容 * @return */ public String getDescription(); /** * 显示在dialog中的button对象 * @author mazqa * */ public static class DialogButtonObj{ int id; String name; boolean defaultButton; public DialogButtonObj(int id, String name, boolean defaultButton) { super(); this.id = id; this.name = name; this.defaultButton = defaultButton; } public int getId() { return id; } public String getName() { return name; } public boolean isDefaultButton() { return defaultButton; } } }
而RefPaneDialog对话框直接继承自org.eclipse.jface.dialogs.TitleAreaDialog,其中的所有创建按钮,面板,以及操作的方法都是委托对应的IDialogComposite实现的。
在创建对话框的过程中,加入了显示在屏幕中央的处理逻辑:
createActualContents(parent, value); Rectangle displayBounds = Display.getCurrent().getPrimaryMonitor().getBounds(); Rectangle shellBounds = parent.getShell().getBounds(); int x = displayBounds.x + (displayBounds.width - shellBounds.width) >> 1; int y = displayBounds.y + (displayBounds.height - shellBounds.height) >> 1; parent.getShell().setLocation(x, y);
由上述步骤,简易的参照功能就已经能够实现了,并保证了良好的扩展性(本功能的扩展性是建立在本程序需求的基础之上,没有通用参考价值)。