前言
Eclipse 提供了文本编辑器(org.eclipse.ui.editors.text.TextEditor
),这类编辑器很适合文本类编辑。但是RCP中,并不是所有的资源都是通过文本编辑的,我们需要定制出客户业务相关的、简洁直观的表单类编辑器。本文给出这样一个案例。简图如下
以下是创建该编辑器过程
一、在plugin.xml
中扩展Editor
编辑器扩展自Eclipse插件扩展点 org.eclipse.ui.editors
,代码如下:
<!-- 编辑器扩展 -->
<extension
id="XzbdEditor"
point="org.eclipse.ui.editors">
<editor
class="com.xzbd.editor.FormEditor"
default="false"
extensions="pconf"
icon="icons/message.png"
id="com.xzbd.editor.FormEditor"
name="表单编辑">
</editor>
</extension>
二、创建编辑器类FormEditor
- 继承
EditorPart
类 - 实现父类定义的抽象方法或接口
- 在
init
方法中添加this.setSite(site); this.setInput(input);
- 定义
isDirty
变量,并完善方法isDirty
,该变量表示编辑器内容是否修改过,false
/ 没有修改过,true
/ 修改过。 - 添加
changeDirtyState
、toDirty
、clearDirty
方法,备用。 - 完善
createPartControl
方法,该方法用于创建编辑器内容, 为了代码整洁我们新建一个类FormEditViewer
完成编辑器UI
部分,并将编辑器传入其中,以便后期调用编辑器方法。
FormEditor
代码如下
package com.xzbd.editor;
/**
* 表单编辑器
*/
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.EditorPart;
import com.xzbd.view.demos.FormEditViewer;
public class FormEditor extends EditorPart {
public static String ID = "com.xzbd.editor.FormEditor";
public boolean isDirty = false;
private FormEditViewer viewer;
@Override
public void doSave(IProgressMonitor monitor) {
clearDirty();
}
@Override
public void doSaveAs() {
}
@Override
public void init(IEditorSite site, IEditorInput input) throws PartInitException {
this.setSite(site);
this.setInput(input);
}
@Override
public boolean isDirty() {
return isDirty;
}
@Override
public boolean isSaveAsAllowed() {
return false;
}
@Override
public void createPartControl(Composite parent) {
viewer = new FormEditViewer(parent,this);
}
@Override
public void setFocus() {
}
/**
* 转换编辑器状态
*
* @param isDirty
*/
public void changeDirtyState(boolean isDirty) {
this.isDirty = true;
firePropertyChange(PROP_DIRTY);
}
public void toDirty() {
changeDirtyState(true);
}
public void clearDirty() {
changeDirtyState(false);
}
}
三、创建编辑器UI
类FormEditViewer
FormEditViewer
是一个普通类,代码可以自己随便组织,其中 UI
部分源自 理解SWT布局(第一部分) 一文中最后一个demo,该文章对RCP
布局做了非常精彩的讲解,需要学习布局的同学可以移步去看看。
package com.xzbd.view.demos;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Text;
import com.xzbd.editor.FormEditor;
/**
*
* 编辑器视图
*
*/
public class FormEditViewer {
private ProjectConfigEditor editor;
private Composite parent;
private Text dogName;
private Combo dogBreed;
private Canvas dogPhoto;
private Image dogImage;
private List categories;
private Text ownerName;
private Text ownerPhone;
public ProjectConfigEditViewer(Composite parent, ProjectConfigEditor editor) {
this.parent = parent;
// 缓存 Editor
setEditor(editor);
// 绘制UI
buildPageUI();
}
// 创建UI
private void buildPageUI() {
// 设置 parent 布局,采用3列 GridLayout 方式布局
GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 3;
parent.setLayout(gridLayout);
new Label(parent, SWT.NONE).setText("Dog's Name:");
dogName = new Text(parent, SWT.SINGLE | SWT.BORDER);
// 设置 label 布局,横向占两列满填充
GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gridData.horizontalSpan = 2;
dogName.setLayoutData(gridData);
new Label(parent, SWT.NONE).setText("Breed:");
dogBreed = new Combo(parent, SWT.NONE);
dogBreed.setItems(new String[] { "Collie", "Pitbull", "Poodle", "Scottie" });
dogBreed.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
Label label = new Label(parent, SWT.NONE);
label.setText("Categories");
label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_CENTER));
new Label(parent, SWT.NONE).setText("Photo:");
dogPhoto = new Canvas(parent, SWT.BORDER);
gridData = new GridData(GridData.FILL_BOTH);
gridData.widthHint = 80;
gridData.heightHint = 80;
gridData.verticalSpan = 3;
dogPhoto.setLayoutData(gridData);
dogPhoto.addPaintListener(new PaintListener() {
public void paintControl(final PaintEvent event) {
if (dogImage != null) {
event.gc.drawImage(dogImage, 0, 0);
}
}
});
categories = new List(parent, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL);
categories.setItems(new String[] { "Best of Breed", "Prettiest Female", "Handsomest Male", "Best Dressed",
"Fluffiest Ears", "Most Colors", "Best Performer", "Loudest Bark", "Best Behaved", "Prettiest Eyes",
"Most Hair", "Longest Tail", "Cutest Trick" });
gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL);
gridData.verticalSpan = 4;
int listHeight = categories.getItemHeight() * 12;
Rectangle trim = categories.computeTrim(0, 0, 0, listHeight);
gridData.heightHint = trim.height;
categories.setLayoutData(gridData);
Button browse = new Button(parent, SWT.PUSH);
browse.setText("Browse...");
gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gridData.horizontalIndent = 5;
browse.setLayoutData(gridData);
browse.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
String fileName = new FileDialog(parent.getShell()).open();
if (fileName != null) {
dogImage = new Image(parent.getDisplay(), fileName);
}
}
});
Button delete = new Button(parent, SWT.PUSH);
delete.setText("Delete");
gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_BEGINNING);
gridData.horizontalIndent = 5;
delete.setLayoutData(gridData);
delete.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
if (dogImage != null) {
dogImage.dispose();
dogImage = null;
dogPhoto.redraw();
}
}
});
Group ownerInfo = new Group(parent, SWT.NONE);
ownerInfo.setText("Owner Info");
gridLayout = new GridLayout();
gridLayout.numColumns = 2;
ownerInfo.setLayout(gridLayout);
gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gridData.horizontalSpan = 2;
ownerInfo.setLayoutData(gridData);
new Label(ownerInfo, SWT.NONE).setText("Name:");
ownerName = new Text(ownerInfo, SWT.SINGLE | SWT.BORDER);
ownerName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
new Label(ownerInfo, SWT.NONE).setText("Phone:");
ownerPhone = new Text(ownerInfo, SWT.SINGLE | SWT.BORDER);
ownerPhone.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Button enter = new Button(parent, SWT.PUSH);
enter.setText("Enter");
gridData = new GridData(GridData.HORIZONTAL_ALIGN_END);
gridData.horizontalSpan = 3;
enter.setLayoutData(gridData);
enter.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
System.out.println("/nDog Name: " + dogName.getText());
System.out.println("Dog Breed: " + dogBreed.getText());
System.out.println("Owner Name: " + ownerName.getText());
System.out.println("Owner Phone: " + ownerPhone.getText());
System.out.println("Categories:");
String cats[] = categories.getSelection();
for (int i = 0; i < cats.length; i++) {
System.out.println("/t" + cats[i]);
}
}
});
if (dogImage != null) {
dogImage.dispose();
}
}
public ProjectConfigEditor getEditor() {
return editor;
}
public void setEditor(ProjectConfigEditor editor) {
this.editor = editor;
}
}
布局部分讲解
注意下面这些问题:
• 这里有3列7行。
• dogPhoto
这个Canvas会变宽和变高同,这是因为它是填充的并且水平地和垂直的抢占的(虽然我们本应该缩放图片,但我们没有对图片进行缩放)。
• dogBreed
这个Combo会变宽,因为它是水平的填充的,并且它和Canvans
在同一列。
• dogName
这个Text会变宽,那是因为它是水平填充的,并且它所跨越的其中一列包含有Canvas。
• Categories
这个List会变高,这是因为它是垂直填充的,并且它和Canvas
跨越了相同的行。
• 因为categories
这个List变高了,它的垂直滚动条消失了(它并没有变宽)。
• ownerInfo
这个Group会变宽,这是因为它是水平的填充的,并且它所跨越的其中一列包含有Canvas。
• 作为Composite的子类,ownerInfo
这个Group有它自己的2列2行的GridLayout
。
• ownerName
和ownerPhone
这两个Text会变宽,这是因为Group会变宽,并且它们在Group的GridLayout
中是填充的和水平抢占的。
• browse
和delete
这两个Button会稍微的缩进,而且因为它们都是水平填充的,它们有相同的宽度。
• delete
这个Button在它的行的顶部垂直的对齐。
• Categories
这个Label在categories这个List的顶端居中。
• enter
这个Button是水平地对齐到它所跨越的3列的最右边。
• dogPhoto
这个Canvas用宽度和高度hint来创建,这是因为如果可能的话,我们要让Image有80象素×80象素的大小。
• categories
这个List用List的字体的12倍的高度hint值来创建,这是因为我们要让List在初始状态下显示十二个项。
作者:贱小得
链接:https://www.jianshu.com/p/d7c17559f349
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
四、运行
- 运行
RCP
应用 - 在
RCP
中建一个以pconf
为后缀的文件 - 双击打开该文件,即刻看到编辑器正常打开了
总结
以上就是RCP
创建表单UI
内容,本文仅仅简单介绍了RCP
自定义编辑器的创建,后续会继续完善。
Eclipse插件(RCP)自定义编辑器添加Dirty效果