> 文档中心 > Eclipse插件(RCP)自定义编辑器

Eclipse插件(RCP)自定义编辑器


前言

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 / 修改过。
  • 添加 changeDirtyStatetoDirtyclearDirty 方法,备用。
  • 完善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;@Overridepublic void doSave(IProgressMonitor monitor) {clearDirty();}@Overridepublic void doSaveAs() {}@Overridepublic void init(IEditorSite site, IEditorInput input) throws PartInitException {this.setSite(site);this.setInput(input);}@Overridepublic boolean isDirty() {return isDirty;}@Overridepublic boolean isSaveAsAllowed() {return false;}@Overridepublic void createPartControl(Composite parent) {viewer = new FormEditViewer(parent,this);}@Overridepublic 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);}}

三、创建编辑器UIFormEditViewer

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;// 缓存 EditorsetEditor(editor);// 绘制UIbuildPageUI();}// 创建UIprivate 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
ownerNameownerPhone这两个Text会变宽,这是因为Group会变宽,并且它们在Group的GridLayout中是填充的和水平抢占的。
browsedelete这两个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效果

致谢

  • 理解SWT布局(第一部分)