Plug-in 编辑器

来源:互联网 发布:软件发布 编辑:程序博客网 时间:2024/06/08 09:40

Plug-in 编辑器

首先申明下,本文为笔者学习《Eclipse插件开发学习笔记》的笔记,并加入笔者自己的理解和归纳总结。

1、创建编辑器

在【extensions】中添加【org.eclipse.ui.editors】。
在【org.eclipse.ui.editors】中添加【editor】。在"class"中指定编辑器类,必须继承IEditorPart。

<extensionpoint="org.eclipse.ui.editors"><editorclass="com.plugin.blog.demo.edit.DemoEditorPart"default="false"icon="icons/icon_editor.png"id="com.plugin.blog.demo.edit.DemoEditorPart"name="DemoEditorPart"></editor></extension>
DemoEditorView类,继承FormEditor,FormEditor是Eclipse自带的分页编辑器。
public class DemoEditorPart extends FormEditor {private UserInfoFormPage mInfoFormPage;private UserPreviewFormPage mPreviewFormPage;@Overrideprotected 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());}@Overridepublic void doSave(IProgressMonitor monitor) {}@Overridepublic void doSaveAs() {}@Overridepublic boolean isSaveAsAllowed() {return false;}}

2、打开编辑器

DemoEditorInputt类,继承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());}@Overridepublic <T> T getAdapter(Class<T> adapter) {return null;}@Overridepublic boolean exists() {return false;}@Overridepublic ImageDescriptor getImageDescriptor() {return null;}@Overridepublic String getName() {return mUser.getName();}@Overridepublic IPersistableElement getPersistable() {return null;}@Overridepublic String getToolTipText() {return getName() + "信息";}public UserInfoManager getManager() {return mManager;}@Overridepublic boolean equals(Object obj) {if (obj instanceof DemoEditorInput) {return mUser == ((DemoEditorInput) obj).mUser;}return super.equals(obj);}}
在DemoViewPart视图中添加双击操作(DemoViewPart可参考前面博客),调用IWorkbenchPage的openEditor方法打开一个编辑器,
mTableViewer.addDoubleClickListener(new IDoubleClickListener() {@Overridepublic 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) {}}}});

3、数据模型

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类,显示个人基本信息,包括性别和年龄。在set方法中调用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);}@Overridepublic 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);}@Overridepublic String getText() {return "手机号:" + ((mPhone != null) ? mPhone : "") + "\n"+ "联系地址:" + ((mAddress != null) ? mAddress : "");}}

4、编辑器状态

UserInfoManager类用来读取和存储数据,并且监听数据的修改。
当数据被修改后,isDirty方法返回true,调用doSave方法后,isDirty方法返回false。

public class UserInfoManager implements PropertyChangeListener {private String mName;private boolean mDirty;private List<UserInfo> 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;}@Overridepublic 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;@Overrideprotected void addPages() {mManager = ((DemoEditorInput) input).getManager();mManager.addPropertyChangeListener(new PropertyChangeListener() {@Overridepublic void propertyChange(PropertyChangeEvent evt) {firePropertyChange(PROP_DIRTY);}});}@Overridepublic boolean isDirty() {return mManager.isDirty();}@Overridepublic void doSave(IProgressMonitor monitor) {mManager.doSave(monitor);firePropertyChange(PROP_DIRTY);}

5、添加编辑页

(1) UserInfoFormPage类,用来编辑数据,使用UserInfoBlockk创建界面。
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);}@Overrideprotected 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();}@Overrideprotected 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() {@Overridepublic void selectionChanged(SelectionChangedEvent event) {managedForm.fireSelectionChanged(sectionPart, event.getSelection());}});}@Overrideprotected void registerPages(DetailsPart detailsPart) {// 和上面的managedForm.fireSelectionChanged()方法相对应// 最终会调用Selection.element.getClass对应的IDetailsPagedetailsPart.registerPage(UserBasicInfo.class, mBasicInfoDetailPage);detailsPart.registerPage(UserContractInfo.class, mContractInfoDetailsPage);}@Overrideprotected void createToolBarActions(IManagedForm managedForm) {}}private static class UserInfoContentProvider implements IStructuredContentProvider {@Overridepublic Object[] getElements(Object inputElement) {if (inputElement instanceof DemoEditorInput) {return ((DemoEditorInput) inputElement).getManager().toArray();}return new Object[0];}}private static class UserInfoLabelProvider implements ITableLabelProvider {@Overridepublic void addListener(ILabelProviderListener listener) {}@Overridepublic void dispose() {}@Overridepublic boolean isLabelProperty(Object element, String property) {return false;}@Overridepublic void removeListener(ILabelProviderListener listener) {}@Overridepublic Image getColumnImage(Object element, int columnIndex) {return null;}@Overridepublic 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;@Overridepublic void initialize(IManagedForm form) {this.mForm = form;}@Overridepublic void dispose() {}@Overridepublic boolean isDirty() {return false;}@Overridepublic void commit(boolean onSave) {}@Overridepublic boolean setFormInput(Object input) {return false;}@Overridepublic void setFocus() {}@Overridepublic boolean isStale() {return false;}@Overridepublic void refresh() {mRefresh = true;updateUI(mUserInfo);mRefresh = false;}@Overridepublic 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) {}@Overridepublic 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() {@Overridepublic void modifyText(ModifyEvent e) {if (!mRefresh) {updateInfo(mUserInfo);}}});return text;}protected List<Button> createChoice(IManagedForm form, Composite parent,String[] array, int selectIndex) {Composite choiceComp = form.getToolkit().createComposite(parent);GridData choiceCompGd = new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1);choiceComp.setLayoutData(choiceCompGd);GridLayout choiceCompLayout = new GridLayout(array.length, false);choiceComp.setLayout(choiceCompLayout);List<Button> btnList = new ArrayList<>();for (String str : array) {Button btn = form.getToolkit().createButton(choiceComp, str, SWT.RADIO);btn.setText(str);GridData btnGd = new GridData(SWT.FILL, SWT.CENTER, false, false);btn.setLayoutData(btnGd);btn.addSelectionListener(new SelectionAdapter() {@Overridepublic void widgetSelected(SelectionEvent e) {if (!mRefresh) {updateInfo(mUserInfo);}}});btnList.add(btn);}btnList.get(selectIndex).setSelection(true);return btnList;}protected void updateInfo(UserInfo userInfo) {}}
UserBasicInfoDetailsPage类
public class UserBasicInfoDetailsPage extends AbstractDetailsPage {private List<Button> mSexBtnList;private Text mText;@Overrideprotected 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, "年龄");}@Overrideprotected 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;}@Overrideprotected 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;@Overrideprotected void createContentInfo(IManagedForm form, Composite parent) {mPhoneText = createText(form, parent, "手机号");mAddressText = createText(form, parent, "家庭地址");}@Overrideprotected 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());}}@Overrideprotected void updateInfo(UserInfo userInfo) {super.updateInfo(userInfo);UserContractInfo userContractInfo = (UserContractInfo) userInfo;userContractInfo.setPhone(mPhoneText.getText());userContractInfo.setAddress(mAddressText.getText());}}
显示如下

(2) 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", "预览");}@Overrideprotected 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() {@Overridepublic 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);}}// 数据模型修改后,刷新当前界面@Overridepublic 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());}}
显示如下
    

6、文件存储

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();}

原创粉丝点击