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
/ 修改过。 - 添加
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;@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);}}
三、创建编辑器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;// 缓存 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
。
• 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效果
致谢
- 理解SWT布局(第一部分)