在EMF自动生成的editor中,只提供了TreeViewer作为编辑控件,自动生成的代码能让TreeViewer处理Redo&Undo操作,如果还需要对EMF对应的Attribute使用Text, Combo等Widget进行编辑的话,那么如何将这些Widget的编辑也能实现Undo&Redo操作呢?
首先我们来分析一下,对于TreeViewer是如何实现Redo&Undo操作的,在生成的editor代码中有类似这样的一句(这个是我改写后的,实际生成的可能有所区别):为了只针对Redo&Undo对UI进行更新,还需要对RedoAction和UndoAction做进一步处理:
其做法就是要让editor知道当前的Action,然后在修改UI的时候,取得该Action看是否是我们指定的Action(RedoAction&UndoAction).
- viewer.setContentProvider(new AdapterFactoryContentProvider(
- getAdapterFactory()));
AdapterFactoryContentProvider实现了INotifyChangedListener接口,该接口就是用来处理在EMF模型发生变动时,如何更新绑定的UI控件:
- public void notifyChanged(Notification notification)
- {
- if (viewer != null && viewer.getControl() != null && !viewer.getControl().isDisposed())
- {
- // If the notification is an IViewerNotification, it specifies how ViewerRefresh should behave. Otherwise fall
- // back to NotifyChangedToViewerRefresh, which determines how to refresh the viewer directly from the model
- // notification.
- //
- if (notification instanceof IViewerNotification)
- {
- if (viewerRefresh == null)
- {
- viewerRefresh = new ViewerRefresh(viewer);
- }
- if (viewerRefresh.addNotification((IViewerNotification)notification))
- {
- viewer.getControl().getDisplay().asyncExec(viewerRefresh);
- }
- }
- else
- {
- NotifyChangedToViewerRefresh.handleNotifyChanged(
- viewer,
- notification.getNotifier(),
- notification.getEventType(),
- notification.getFeature(),
- notification.getOldValue(),
- notification.getNewValue(),
- notification.getPosition());
- }
- }
- }
再看代码:
- public AdapterFactoryContentProvider(AdapterFactory adapterFactory)
- {
- this.adapterFactory = adapterFactory;
- if (adapterFactory instanceof IChangeNotifier)
- {
- ((IChangeNotifier)adapterFactory).addListener(this);
- }
- }
这里关键的一句就是:
- ((IChangeNotifier)adapterFactory).addListener(this);
它将更新UI的通知操作与adapterFactory关联起来,然后在EMF模型发生变动的时候,会从adapterFactory来找到所有注册的INotifyChangedListener
因此做法就相当简单了,即将EMF模型对应的编辑控件实现INotifyChangedListener接口,然后拿到adapterFactory,并把该控件注册进去.
下面我的一个实现:
AbstractDoradoSection包含了EMF模型当前节点属性的对应编辑控件集合,让其实现INotifyChangedListener接口
并在构造函数中注册到adapterFactory中:
- public AbstractDoradoSection(IAdaptable adaptable, Object input,
- Composite parent, String title, int style) {
- this.adaptable = adaptable;
- this.input = input;
- this.title = title;
- this.style = ExpandableComposite.TITLE_BAR | style;
- AdapterFactory adapterFactory = (AdapterFactory) adaptable
- .getAdapter(AdapterFactory.class);
- ((IChangeNotifier) adapterFactory).addListener(this);
- initialize(parent);
- }
- /**
- * 当emf模型发生变化之后,更新ui,主要针对redo和undo处理
- *
- * @see org.eclipse.emf.edit.provider.INotifyChangedListener#notifyChanged(org.eclipse.emf.common.notify.Notification)
- */
- public void notifyChanged(final Notification notification) {
- IActionProvider actionProvider = (IActionProvider) adaptable
- .getAdapter(IActionProvider.class);
- if (actionProvider.getAction() instanceof NotifierAction) {
- Object feature = notification.getFeature();
- if (feature instanceof EAttribute && rows != null) {
- for (Iterator iter = rows.iterator(); iter.hasNext();) {
- final AttributeRow row = (AttributeRow) iter.next();
- if (row.getAttribute() == feature) {
- row.setTextContent(notification.getNewStringValue(), true);
- break;
- }
- }
- }
- }
安徽新华电脑学校专业职业规划师为你提供更多帮助【在线咨询】