首先申明下,本文为笔者学习《Eclipse插件开发学习笔记》的笔记,并加入笔者自己的理解和归纳总结。
在【extensions】中添加【org.eclipse.ui.editors】。
在【org.eclipse.ui.editors】中添加【editor】。在【class】中指定编辑器类,必须继承IEditorPart
。
DemoEditorView
类,继承FormEditor
,FormEditor
是Eclipse自带的分页编辑器。
public class DemoEditorPart extends FormEditor {
private UserInfoFormPage mInfoFormPage;
private UserPreviewFormPage mPreviewFormPage;
@Override
protected void addPages() {
mInfoFormPage = new UserInfoFormPage(this);
mPreviewFormPage = new UserPreviewFormPage(this);
try {
addPage(mInfoFormPage);
addPage(mPreviewFormPage);
} catch (PartInitException e) {
}
IEditorInput input = getEditorInput();
setPartName(input.getName());
setTitleToolTip(input.getToolTipText());
}
@Override
public void doSave(IProgressMonitor monitor) {
}
@Override
public void doSaveAs() {
}
@Override
public boolean isSaveAsAllowed() {
return false;
}
}
DemoEditorInput
类,继承IEditorInput
,包含数据类UserInfoManager
。
覆盖equals()
方法,避免重复打开同一个内容的编辑器。
public class DemoEditorInput implements IEditorInput {
private User mUser;
private UserInfoManager mManager;
public DemoEditorInput(User user) {
this.mUser = user;
mManager = UserInfoManager.getInstance(mUser.getName());
}
@Override
public T getAdapter(Class adapter) {
return null;
}
@Override
public boolean exists() {
return false;
}
@Override
public ImageDescriptor getImageDescriptor() {
return null;
}
@Override
public String getName() {
return mUser.getName();
}
@Override
public IPersistableElement getPersistable() {
return null;
}
@Override
public String getToolTipText() {
return getName() + "信息";
}
public UserInfoManager getManager() {
return mManager;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof DemoEditorInput) {
return mUser == ((DemoEditorInput) obj).mUser;
}
return super.equals(obj);
}
}
在DemoViewPart
视图中添加双击操作(DemoViewPart
可参考Java Plug-in 视图),调用IWorkbenchPage
的openEditor()
方法打开一个编辑器,
mTableViewer.addDoubleClickListener(new IDoubleClickListener() {
@Override
public void doubleClick(DoubleClickEvent event) {
ISelection selection = mTableViewer.getSelection();
User user = (User) ((IStructuredSelection) selection).getFirstElement();
IWorkbenchPage activePage = getSite().getWorkbenchWindow().getActivePage();
if (activePage != null) {
try {
activePage.openEditor(new DemoEditorInput(user),
"com.plugin.blog.demo.edit.DemoEditorPart");
} catch (PartInitException e) {
}
}
}
});
UserInfo
是数据的父类,其中name
和description
用来显示界面的标题和描述,getText()
方法用来显示整体信息。
public abstract class UserInfo {
private String mTitle, mDescription;
private PropertyChangeSupport mSupport;
public UserInfo(String title, String description) {
this.mTitle = title;
this.mDescription = description;
mSupport = new PropertyChangeSupport(this);
}
public String getTitle() {
return mTitle;
}
public String getDescription() {
return mDescription;
}
public abstract String getText();
public void addPropertyChangeListener(PropertyChangeListener listener) {
mSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
mSupport.removePropertyChangeListener(listener);
}
public void firePropertyChange(String propertyName,
Object oldValue, Object newValue) {
mSupport.firePropertyChange(propertyName, oldValue, newValue);
}
}
UserBasicInfo
类,显示个人基本信息,包括性别和年龄。在setXX()
方法中调用firePropertyChange()
方法,发出修改提示。
public class UserBasicInfo extends UserInfo {
public final static String PROPERTY_MALE = "male";
public final static String PROPERTY_AGE = "age";
private boolean mMale = true;
private int mAge;
public UserBasicInfo() {
super("基本信息", "显示和查看基本信息");
}
public boolean isMale() {
return mMale;
}
public void setMale(boolean male) {
boolean oldValue = mMale;
this.mMale = male;
firePropertyChange(PROPERTY_MALE, oldValue, mMale);
}
public int getAge() {
return mAge;
}
public void setAge(int age) {
int oldValue = mAge;
this.mAge = age;
firePropertyChange(PROPERTY_AGE, oldValue, mAge);
}
@Override
public String getText() {
return "性别:" + (mMale ? "男" : "女") + "\n"
+ "年龄:" + (mAge > 0 ? (mAge + "岁") : "");
}
}
UserContractInfo
类,显示个人联系信息,包括手机和地址。同样在set()
方法中调用firePropertyChange()
方法,发出修改提示。
public class UserContractInfo extends UserInfo {
public final static String PROPERTY_PHONE = "phone";
public final static String PROPERTY_ADDR = "addr";
private String mPhone;
private String mAddress;
public UserContractInfo() {
super("联系信息", "查看和修改联系信息");
}
public String getPhone() {
return mPhone;
}
public void setPhone(String phone) {
String oldValue = mPhone;
this.mPhone = phone;
firePropertyChange(PROPERTY_PHONE, oldValue, mPhone);
}
public String getAddress() {
return mAddress;
}
public void setAddress(String address) {
String oldValue = mAddress;
this.mAddress = address;
firePropertyChange(PROPERTY_PHONE, oldValue, mAddress);
}
@Override
public String getText() {
return "手机号:" + ((mPhone != null) ? mPhone : "") + "\n"
+ "联系地址:" + ((mAddress != null) ? mAddress : "");
}
}
UserInfoManager
类用来读取和存储数据,并且监听数据的修改。
当数据被修改后,isDirty()
方法返回true
,调用doSave()
方法后,isDirty()
方法返回false
。
public class UserInfoManager implements PropertyChangeListener {
private String mName;
private boolean mDirty;
private List mUserInfoList;
private UserBasicInfo mBasicInfo;
private UserContractInfo mContractInfo;
private PropertyChangeSupport mSupport;
private UserInfoManager(String name) {
this.mName = name;
mUserInfoList = new ArrayList<>();
mSupport = new PropertyChangeSupport(this);
load();
mDirty = false;
}
private void load() {
mBasicInfo = new UserBasicInfo();
mContractInfo = new UserContractInfo();
mBasicInfo.addPropertyChangeListener(this);
mUserInfoList.add(mBasicInfo);
mContractInfo.addPropertyChangeListener(this);
mUserInfoList.add(mContractInfo);
}
public Object[] toArray() {
return mUserInfoList.toArray();
}
public boolean isDirty() {
return mDirty;
}
public void doSave(IProgressMonitor monitor) {
mDirty = false;
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (!mDirty) {
mDirty = true;
mSupport.firePropertyChange("PROP_DIRTY", false, mDirty);
}
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
mSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
mSupport.removePropertyChangeListener(listener);
}
public UserInfo getUserInfo(int index) {
if (index >= 0 && index < mUserInfoList.size()) {
return mUserInfoList.get(index);
}
return null;
}
public static UserInfoManager getInstance(String name) {
return new UserInfoManager(name);
}
}
在DemoEditorView
类中addPages()
方法,添加对UserInfoManager
的监听,并使用UserInfoManager
的状态控制自己的状态。
private UserInfoManager mManager;
@Override
protected void addPages() {
mManager = ((DemoEditorInput) input).getManager();
mManager.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
firePropertyChange(PROP_DIRTY);
}
});
}
@Override
public boolean isDirty() {
return mManager.isDirty();
}
@Override
public void doSave(IProgressMonitor monitor) {
mManager.doSave(monitor);
firePropertyChange(PROP_DIRTY);
}
UserInfoFormPage
类,用来编辑数据,使用UserInfoBlock
创建界面。
UserInfoBlock
类继承MasterDetailsBlock
,左边是列表,右边是具体信息。
public class UserInfoFormPage extends FormPage {
private UserInfoBlock mBlock;
public UserInfoFormPage(FormEditor formEditor) {
super(formEditor, "com.plugin.blog.demo.edit.UserInfoFormPage", "编辑");
mBlock = new UserInfoBlock(this);
}
@Override
protected void createFormContent(IManagedForm managedForm) {
ScrolledForm form = managedForm.getForm();
form.setText("编辑个人信息");
form.setBackgroundImage(ImageKeys.getImageDescriptor(
ImageKeys.IMAGE_FORM_BANNER).createImage());
mBlock.createContent(managedForm);
}
public class UserInfoBlock extends MasterDetailsBlock {
private FormPage mFormPage;
private AbstractDetailsPage mBasicInfoDetailPage, mContractInfoDetailsPage;
public UserInfoBlock(FormPage formPage) {
this.mFormPage = formPage;
mBasicInfoDetailPage = new UserBasicInfoDetailsPage();
mContractInfoDetailsPage = new UserContractInfoDetailsPage();
}
@Override
protected void createMasterPart(IManagedForm managedForm, Composite parent) {
FormToolkit toolkit = managedForm.getToolkit();
Section section = toolkit.createSection(parent,
Section.DESCRIPTION | Section.TITLE_BAR);
section.setText("信息列表");
section.setDescription("包括基本信息、联系方式和其他信息");
section.marginHeight = 5;
Composite compUserInfo = toolkit.createComposite(section, SWT.WRAP);
compUserInfo.setLayout(new FillLayout());
Table table = toolkit.createTable(compUserInfo, SWT.NULL);
toolkit.paintBordersFor(compUserInfo);
section.setClient(compUserInfo);
final SectionPart sectionPart = new SectionPart(section);
managedForm.addPart(sectionPart);
TableViewer tableViewer = new TableViewer(table);
tableViewer.setContentProvider(new UserInfoContentProvider());
tableViewer.setLabelProvider(new UserInfoLabelProvider());
tableViewer.setInput(mFormPage.getEditor().getEditorInput());
tableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
managedForm.fireSelectionChanged(sectionPart, event.getSelection());
}
});
}
@Override
protected void registerPages(DetailsPart detailsPart) {
// 和上面的managedForm.fireSelectionChanged()方法相对应
// 最终会调用Selection.element.getClass对应的IDetailsPage
detailsPart.registerPage(UserBasicInfo.class, mBasicInfoDetailPage);
detailsPart.registerPage(UserContractInfo.class, mContractInfoDetailsPage);
}
@Override
protected void createToolBarActions(IManagedForm managedForm) {
}
}
private static class UserInfoContentProvider implements IStructuredContentProvider {
@Override
public Object[] getElements(Object inputElement) {
if (inputElement instanceof DemoEditorInput) {
return ((DemoEditorInput) inputElement).getManager().toArray();
}
return new Object[0];
}
}
private static class UserInfoLabelProvider implements ITableLabelProvider {
@Override
public void addListener(ILabelProviderListener listener) {
}
@Override
public void dispose() {
}
@Override
public boolean isLabelProperty(Object element, String property) {
return false;
}
@Override
public void removeListener(ILabelProviderListener listener) {
}
@Override
public Image getColumnImage(Object element, int columnIndex) {
return null;
}
@Override
public String getColumnText(Object element, int columnIndex) {
if (element instanceof UserInfo) {
return ((UserInfo) element).getTitle();
}
return null;
}
}
}
AbstractDetailsPage
类,
selectionChanged()
方法用来实现点击事件createContentInfo()
方法用来创建界面createText()
和createChoice()
是创建界面的公共方法,分别对其中的Text
和Button
进行监听,并修改数据模型UserInfo
。updateUI()
是修改界面,并且不需要触发界面的监听updateInfo()
是修改数据模型public abstract class AbstractDetailsPage implements IDetailsPage {
private IManagedForm mForm;
protected Section mSection;
private UserInfo mUserInfo;
private boolean mRefresh;
@Override
public void initialize(IManagedForm form) {
this.mForm = form;
}
@Override
public void dispose() {
}
@Override
public boolean isDirty() {
return false;
}
@Override
public void commit(boolean onSave) {
}
@Override
public boolean setFormInput(Object input) {
return false;
}
@Override
public void setFocus() {
}
@Override
public boolean isStale() {
return false;
}
@Override
public void refresh() {
mRefresh = true;
updateUI(mUserInfo);
mRefresh = false;
}
@Override
public void selectionChanged(IFormPart part, ISelection selection) {
if (selection != null && !selection.isEmpty()) {
mUserInfo = (UserInfo) ((IStructuredSelection) selection).getFirstElement();
mSection.setText(mUserInfo.getTitle());
mSection.setDescription(mUserInfo.getDescription());
mRefresh = true;
updateUI(mUserInfo);
mRefresh = false;
}
}
protected void updateUI(UserInfo userInfo) {
}
@Override
public void createContents(Composite parent) {
parent.setLayout(new TableWrapLayout());
FormToolkit toolkit = mForm.getToolkit();
mSection = toolkit.createSection(parent, Section.DESCRIPTION|Section.TITLE_BAR);
TableWrapData td = new TableWrapData(TableWrapData.FILL, TableWrapData.TOP);
td.grabHorizontal = true;
mSection.setLayoutData(td);
Composite compParent = toolkit.createComposite(mSection, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
compParent.setLayout(layout);
mSection.setClient(compParent);
createContentInfo(mForm, compParent);
}
protected abstract void createContentInfo(IManagedForm form, Composite parent);
protected Text createText(IManagedForm form, Composite parent, String name) {
Label label = form.getToolkit().createLabel(parent, name);
GridData labelGd = new GridData(SWT.FILL, SWT.CENTER, false, false);
labelGd.widthHint = 60;
label.setLayoutData(labelGd);
Text text = form.getToolkit().createText(parent, "");
GridData textGd = new GridData(SWT.FILL, SWT.CENTER, true, false);
text.setLayoutData(textGd);
text.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
if (!mRefresh) {
updateInfo(mUserInfo);
}
}
});
return text;
}
protected List
UserBasicInfoDetailsPage
类
public class UserBasicInfoDetailsPage extends AbstractDetailsPage {
private List mSexBtnList;
private Text mText;
@Override
protected void createContentInfo(IManagedForm form, Composite parent) {
FormToolkit toolkit = form.getToolkit();
Label sexLabel = toolkit.createLabel(parent, "性别:");
GridData sexGd = new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1);
sexLabel.setLayoutData(sexGd);
mSexBtnList = createChoice(form, parent, new String[]{"男", "女"}, 0);
mText = createText(form, parent, "年龄");
}
@Override
protected void updateUI(UserInfo userInfo) {
if (userInfo == null) {
mSexBtnList.get(0).setSelection(true);
mSexBtnList.get(1).setSelection(false);
mText.setText("");
} else {
UserBasicInfo userBasicInfo = (UserBasicInfo) userInfo;
boolean male = userBasicInfo.isMale();
mSexBtnList.get(0).setSelection(male);
mSexBtnList.get(1).setSelection(!male);
if (userBasicInfo.getAge() <= 0) {
mText.setText("");
} else {
mText.setText(Integer.toString(userBasicInfo.getAge()));
}
}
}
private int parseInteger(String text) {
try {
return Integer.parseInt(text);
} catch (NumberFormatException e) {
}
return 0;
}
@Override
protected void updateInfo(UserInfo userInfo) {
super.updateInfo(userInfo);
UserBasicInfo userBasicInfo = (UserBasicInfo) userInfo;
if (mSexBtnList.get(0).getSelection()) {
userBasicInfo.setMale(true);
} else if (mSexBtnList.get(1).getSelection()) {
userBasicInfo.setMale(false);
}
userBasicInfo.setAge(parseInteger(mText.getText()));
}
}
显示如下
UserContractInfoDetailsPage
类
public class UserContractInfoDetailsPage extends AbstractDetailsPage {
private Text mPhoneText;
private Text mAddressText;
@Override
protected void createContentInfo(IManagedForm form, Composite parent) {
mPhoneText = createText(form, parent, "手机号");
mAddressText = createText(form, parent, "家庭地址");
}
@Override
protected void updateUI(UserInfo userInfo) {
if (userInfo == null) {
mPhoneText.setText("");
mAddressText.setText("");
} else {
UserContractInfo userContractInfo = (UserContractInfo) userInfo;
mPhoneText.setText(userContractInfo.getPhone() == null ?
"" : userContractInfo.getPhone());
mAddressText.setText(userContractInfo.getAddress() == null ?
"" : userContractInfo.getAddress());
}
}
@Override
protected void updateInfo(UserInfo userInfo) {
super.updateInfo(userInfo);
UserContractInfo userContractInfo = (UserContractInfo) userInfo;
userContractInfo.setPhone(mPhoneText.getText());
userContractInfo.setAddress(mAddressText.getText());
}
}
显示如下
UserPreviewFormPage
类显示预览信息
public class UserPreviewFormPage extends FormPage
implements PropertyChangeListener {
private CTabFolder mTabFolder;
private Text mText;
private UserInfoManager mManager;
public UserPreviewFormPage(FormEditor editor) {
super(editor, "com.plugin.blog.demo.edit.UserPreviewFormPage", "预览");
}
@Override
protected void createFormContent(IManagedForm managedForm) {
ScrolledForm form = managedForm.getForm();
form.setText("信息预览");
form.setBackgroundImage(ImageKeys.getImageDescriptor(
ImageKeys.IMAGE_FORM_BANNER).createImage());
FormToolkit toolkit = managedForm.getToolkit();
Composite parentComp = form.getBody();
parentComp.setLayout(new GridLayout());
mTabFolder = new CTabFolder(parentComp, SWT.FLAT | SWT.TOP);
toolkit.adapt(mTabFolder, true, true);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.heightHint = 0;
mTabFolder.setLayoutData(gd);
toolkit.paintBordersFor(mTabFolder);
createTitle();
createContent(toolkit, parentComp);
mTabFolder.setSelection(0);
mTabFolder.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
updateSelection();
}
});
updateSelection();
}
private void createTitle() {
mManager = ((DemoEditorInput) getEditor().getEditorInput()).getManager();
Object[] elementArray = mManager.toArray();
for (Object element : elementArray) {
CTabItem item = new CTabItem(mTabFolder, SWT.NULL);
UserInfo userInfo = (UserInfo) element;
item.setText(userInfo.getTitle());
userInfo.addPropertyChangeListener(this);
}
}
// 数据模型修改后,刷新当前界面
@Override
public void propertyChange(PropertyChangeEvent evt) {
updateSelection();
}
private void createContent(FormToolkit toolkit, Composite parent) {
Composite tabContentComp = toolkit.createComposite(parent);
tabContentComp.setLayoutData(new GridData(GridData.FILL_BOTH));
tabContentComp.setLayout(new GridLayout());
mText = toolkit.createText(tabContentComp, "", SWT.MULTI | SWT.WRAP);
mText.setLayoutData(new GridData(GridData.FILL_BOTH));
mText.setEditable(false);
}
private void updateSelection() {
if (mTabFolder == null)
return;
int index = mTabFolder.getSelectionIndex();
mText.setText(mManager.getUserInfo(index).getText());
}
}
XMLMemento
可以实现XML文件的存储。在UserInfoManager
的load()
和doSave()
方法中加入文件存储。
private void load() {
mBasicInfo = new UserBasicInfo();
mContractInfo = new UserContractInfo();
try {
XMLMemento memento = XMLMemento.createReadRoot(new FileReader(getStoreFile()));
IMemento child = memento.getChild("basic_info");
mBasicInfo.setMale(child.getBoolean("male"));
mBasicInfo.setAge(child.getInteger("age"));
child = memento.getChild("contract_info");
mContractInfo.setPhone(child.getString("phone"));
mContractInfo.setAddress(child.getString("address"));
} catch (Exception e) {
}
mBasicInfo.addPropertyChangeListener(this);
mUserInfoList.add(mBasicInfo);
mContractInfo.addPropertyChangeListener(this);
mUserInfoList.add(mContractInfo);
}
public void doSave(IProgressMonitor monitor) {
XMLMemento memento = XMLMemento.createWriteRoot("user");
IMemento child = memento.createChild("basic_info");
child.putBoolean("male", mBasicInfo.isMale());
child.putInteger("age", mBasicInfo.getAge());
child = memento.createChild("contract_info");
child.putString("phone", mContractInfo.getPhone());
child.putString("address", mContractInfo.getAddress());
try {
memento.save(new FileWriter(getStoreFile()));
} catch (IOException e) {
e.printStackTrace();
}
mDirty = false;
}
private File getStoreFile() {
return Activator.getDefault().getStateLocation()
.append("user_" + mName + ".xml").toFile();
}
相关文章
Java Plug-in(一) 创建插件项目
Java Plug-in(二) 菜单
Java Plug-in(三) 视图
Java Plug-in(四) 视图菜单
Java Plug-in(五) 编辑器
Java Plug-in(六) 编辑器菜单
Java Plug-in(七) 透视图
Java Plug-in(八) 向导页
Java Plug-in(九) 首选项
Java Plug-in(十) 自定义扩展点
Java Plug-in(十一) 创建RCP项目