/**
* Դ�������ƣ�EMFFormEditor.java
* �������Ȩ���������ӹɷ�����˾ ��Ȩ����
* ϵͳ���ƣ�JRES Studio
* ģ�����ƣ�com.hundsun.ares.studio.jres.ui
* ����˵����JRES Studio�Ľ���չ�ֻ�����ܺͱ༭��ع���
* ����ĵ���
* ���ߣ�
*/
package com.hundsun.ares.studio.ui.editor;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EventObject;
import java.util.List;
import org.apache.log4j.Logger;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourceAttributes;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.command.BasicCommandStack;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CommandStackListener;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.domain.IEditingDomainProvider;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.TriggerListener;
import org.eclipse.emf.transaction.impl.EditingDomainManager;
import org.eclipse.emf.transaction.impl.TransactionalCommandStackImpl;
import org.eclipse.emf.transaction.impl.TransactionalEditingDomainImpl;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.ui.forms.editor.FormEditor;
import org.eclipse.ui.forms.editor.FormPage;
import org.eclipse.ui.forms.editor.IFormPage;
import org.eclipse.ui.forms.widgets.FormToolkit;
import com.hundsun.ares.studio.core.ARESCore;
import com.hundsun.ares.studio.core.ARESModelException;
import com.hundsun.ares.studio.core.IARESResource;
import com.hundsun.ares.studio.core.model.ExtensibleModel;
import com.hundsun.ares.studio.ui.ARESElementLabelProvider;
import com.hundsun.ares.studio.ui.IARESResourceEditorInput;
import com.hundsun.ares.studio.ui.editor.editable.IEditableControl;
import com.hundsun.ares.studio.ui.editor.editable.JresDefaultEditableControler;
import com.hundsun.ares.studio.ui.editor.extend.ExtensibleModelUtils;
import com.hundsun.ares.studio.ui.editor.sync.IFileSyncnizeUnit;
import com.hundsun.ares.studio.ui.editor.sync.JRESDefaultSyncnizeUnit;
import com.hundsun.ares.studio.ui.editor.sync.JRESEditorSyncManager;
import com.hundsun.ares.studio.ui.extendpoint.manager.ExtendPageInfo;
import com.hundsun.ares.studio.ui.extendpoint.manager.ExtendPageManager;
import com.hundsun.ares.studio.ui.extendpoint.manager.IExtendedPage;
import com.hundsun.ares.studio.ui.page.ExtendPageWithMyDirtySystem;
import com.hundsun.ares.studio.ui.page.IExtendItemLoader;
import com.hundsun.ares.studio.ui.util.ARESUIUtil;
/**
* <ul>
* <li>����{@link EditingDomain}��Ϊ�༭��ȡģ����Ϣ</li>
* <li></li>
* <li>��״̬������<code>CommandStack</code>����ɡ�</li>
* <li>{@link #getAdapter}֧�ַ���{@link EditingDomain}��{@link Resource}</li>
* </ul>
* ע������
* <ul>
* <li>���༭����ע��ʱ��Ӧ����Դ��ע���ʱ��info-class������{@link EObject}��������</li>
* </ul>
* @author gongyf
*
*/
public abstract class EMFFormEditor extends FormEditor implements IEditingDomainProvider {
public static ILabelProvider TITLE_LABEL_PROVIDER = new ARESElementLabelProvider();
protected static final String ACTIVE_EDITOR_INDEX = "active_editor_index";//�༭����������id
private int editorIndex = 0;//���ı༭��
protected final Logger logger = Logger.getLogger(getClass());
//�ļ�ͬ����Ԫ
protected IFileSyncnizeUnit fileSyncUnit;
/**
* ʹ��ͳһ������
*/
static protected Collection<Object> myclipboard;
private TransactionalEditingDomain editingDomain;
private EObject info = null;
private IEditableControl editableControl;
// ��չҳ���б�
protected List<IExtendedPage> extendsPages = new ArrayList<IExtendedPage>();
public TransactionalEditingDomain getEditingDomain() {
return editingDomain;
}
public EMFFormActionBarContributor getActionBarContributor() {
return (EMFFormActionBarContributor) getEditorSite().getActionBarContributor();
}
/**
* @return the info
*/
public EObject getInfo() {
return info;
}
/**
* ��ʼ��editingDomain
* �����������adapterFactory
* @param adapterFactory
*/
protected void configureComposedAdapterFactory(ComposedAdapterFactory adapterFactory) {
// do nothing
}
protected void createEditDomain() {
ComposedAdapterFactory adapterFactory = new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
configureComposedAdapterFactory(adapterFactory);
// Create the editing domain with a special command stack.
//
TransactionalCommandStackImpl commandStack = new TransactionalCommandStackImpl(){
@Override
public void execute(Command command) {
if (command != null) {
if (editingDomain.isReadOnly(getInfo().eResource())) {
try{
handleLock();
}finally{
command.dispose();
}
}
}
super.execute(command);
}
};
editingDomain = new TransactionalEditingDomainImpl(adapterFactory,commandStack) {
public boolean isReadOnly(Resource resource) {
if (isInReferencedLibrary()) {
// ���ð���Ϊֻ��
return true;
}
if (resource == null || resource.getURI() == null) {
return false;
}
return super.isReadOnly(resource);
}
@Override
public Collection<Object> getClipboard() {
return EMFFormEditor.myclipboard;
}
@Override
public void setClipboard(Collection<Object> clipboard) {
EMFFormEditor.myclipboard = clipboard;
};
};
// ���һЩע��ļ�����
EditingDomainManager.getInstance().configureListeners(getEditingDomainID(), editingDomain);
// Add a listener to set the most recent command's affected objects to be the selection of the viewer with focus.
//
editingDomain.getCommandStack().addCommandStackListener
(new CommandStackListener() {
public void commandStackChanged(final EventObject event) {
getSite().getShell().getDisplay().asyncExec
(new Runnable() {
public void run() {
firePropertyChange(IEditorPart.PROP_DIRTY);
}
});
}
});
// ������չģ�͵ij�ʼ��֧�֣���һ���µ�ExtensibleModel���������Զ���ʼ��map����
editingDomain.addResourceSetListener(new TriggerListener() {
@Override
protected Command trigger(TransactionalEditingDomain domain,
Notification notification) {
List<ExtensibleModel> modelList = new ArrayList<ExtensibleModel>();
if (notification.getNewValue() instanceof ExtensibleModel) {
modelList.add((ExtensibleModel) notification.getNewValue());
} else if (notification.getNewValue() instanceof Collection<?>) {
for (Object o : (Collection<?>)notification.getNewValue()) {
if (o instanceof ExtensibleModel) {
modelList.add((ExtensibleModel) o);
}
}
}
if (modelList.isEmpty()) {
return null;
}
return new ExtensibleModelTriggerCommand(domain, getARESResource(),
modelList);
}
});
}
/**
* ��������
*/
private void handleLock (){
if (this.getARESResource().getResource() == null) {
return;
}
IPath path = this.getARESResource().getResource().getProjectRelativePath();
IFile file = getARESResource().getARESProject().getProject().getFile(path);
if (file.exists()) {
boolean readonly = file.isReadOnly();
file.getWorkspace().validateEdit(new IFile[]{file}, null);
if (file.isReadOnly() != readonly) {
Display display = getSite().getShell().getDisplay();
display.asyncExec(new Runnable() {
public void run() {
getSite().getPage().closeEditor(EMFFormEditor.this, false);
try {
ARESUIUtil.openEditor(getARESResource());
} catch (PartInitException e) {
e.printStackTrace();
}
}
});
}
}
}
/**
* ��ȡ�༭���ID������null��ʾ����Ҫid
* @return
*/
protected String getEditingDomainID() {
return getEditorSite().getId();
}
/**
* �жϵ�ǰ�Ƿ���������Դ���д�
* @return
*/
public boolean isInReferencedLibrary() {
return getARESResource().getLib() != null;
}
@Override
protected void setInput(IEditorInput input) {
super.setInput(input);
//����ļ�ͬ��
fileSyncUnit = new JRESDefaultSyncnizeUnit(this);
JRESEditorSyncManager.getInstance().addSyncUnit(fileSyncUnit);
}
public IARESResource getARESResource() {
IARESResource aresResource = null;
if (getEditorInput() instanceof IFileEditorInput) {
aresResource = (IARESResource) ARESCore.create(((IFileEditorInput) getEditorInput()).getFile());
} else if (getEditorInput() instanceof IARESResourceEditorInput) {
aresResource = ((IARESResourceEditorInput)getEditorInput()).getARESResource();
} // TODO: Զ����Դ����
return aresResource;
}
/**
* ��ȡ�༭�����EMF��
* @return
*/
protected abstract EClass getInfoClass();
/**
* �����༭��Ͷ�ȡģ����Ϣ
* @throws ARESModelException
*/
protected void createModel() throws ARESModelException {
//try {
// �Ȼ�ȡARES��Դ����
IARESResource aresResource = getARESResource();
Assert.isTrue(aresResource != null, "������ת��ΪIARESResource����");
if(getInfoClass() == null) {
info = (EObject) aresResource.getWorkingCopy(getInfoClassInstance());
}else {
info = (EObject) aresResource.getWorkingCopy(getInfoClass().getInstanceClass());
}
// ----------------------------------------
// ���Դ��� begin
// ----------------------------------------
if (info == null) {
logger.error("û�ж�ȡ��ģ�����ݣ����Զ�����һ��ȫ��ģ�͡���Դ��" + aresResource.getElementName());
Resource r = new XMLResourceImpl();
info = getInfoClass().getEPackage().getEFactoryInstance().create(getInfoClass());
r.getContents().add(info);
}
// ----------------------------------------
// ���Դ��� end
// ----------------------------------------
ExtensibleModelUtils.extendResource(getARESResource(), info.eResource(), false);
editingDomain.getResourceSet().getResources().clear();
try {
//���ԭresourceset��ע���package
editingDomain.getResourceSet().getPackageRegistry().putAll(info.eResource().getResourceSet().getPackageRegistry());
} catch (Exception e) {
}
((BasicCommandStack)editingDomain.getCommandStack()).flush();
editingDomain.getResourceSet().getResources().add(info.eResource());
// } catch (Exception e) {
// //MessageDialog.openError(getSite().getShell(), "����ģ�ʹ���", e.getMessage());
// logger.error(e.getMessage(), e);
// throw e;
// }
}
/**
* ֱ�ӻ�ȡClass���� ���û�Ԫ����
* ��ʱ����getInfoClass()����null
* @return
*/
protected Class<?> getInfoClassInstance() {
return EObject.class;
}
@Override
public Object getAdapter(Class adapter) {
if (adapter == EditingDomain.class) {
return getEditingDomain();
} else if (adapter.isAssignableFrom(getInfo().getClass())) {
return getInfo();
}
return super.getAdapter(adapter);
}
@Override
public boolean isDirty() {
return ((BasicCommandStack)editingDomain.getCommandStack()).isSaveNeeded();
}
/**
* ָʾ��ǰ�༭���Ƿ�ΪӦ��Ϊֻ��״̬�����������Ӱ������ϵĿؼ��ɱ༭״̬<BR>
* ������{@link #createModel()}����
* @return
*/
public boolean isReadOnly() {
ResourceAttributes attributes = getARESResource().getResource().getResourceAttributes();
boolean resourceIsReadOnly = false;//�ļ�ϵͳ�и�ϵͳ�Ƿ�Ϊֻ��,Ĭ�ϲ�Ϊ
if(attributes!=null){
resourceIsReadOnly = attributes.isReadOnly();
}
return editingDomain.isReadOnly(info.eResource()) || resourceIsReadOnly;
}
protected void createEditableControl() {
//��ʼ��ֻ��������
editableControl = new JresDefaultEditableControler(this);
editableControl.refreshResourceReadonlyStatus();
}
@Override
public void init(IEditorSite site, IEditorInput input)
throws PartInitException {
super.init(site, input);
try {
createEditDomain();
createModel();
createEditableControl();
} catch (Exception e) {
throw new PartInitException(e.getMessage(), e);
}
}
@Override
protected void createPages() {
super.createPages();
for (IExtendedPage page : extendsPages) {
page.onCreate();
}
setPartName(getEditorTitle());
setActivePage(getEditorIndex());
}
protected String getEditorTitle() {
// ���ñ༭������
String partName = TITLE_LABEL_PROVIDER.getText(getARESResource());
if (isReadOnly()) {
partName += "(ֻ��)";
}
return partName;
}
/* (non-Javadoc)
* @see org.eclipse.ui.forms.editor.FormEditor#configurePage(int, org.eclipse.ui.forms.editor.IFormPage)
*/
@Override
protected void configurePage(int index, IFormPage page) throws PartInitException {
super.configurePage(index, page);
if (page instanceof IEMFFormPage) {
((IEMFFormPage) page).setEditableControl(editableControl);
}
}
/**
* ��ȡ��չҳ��
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
protected void createExtendPage() {
for(ExtendPageInfo info:ExtendPageManager.getDefault().getPageInfo(getSite().getId())){
try {
Class cls = info.getPageClass();
Constructor cst = null;
try {
cst = cls.getConstructor(new Class[] { FormEditor.class, String.class, String.class });
} catch (Exception e) { }
IExtendedPage page = null;
if (cst != null) {
page = (IExtendedPage) cst.newInstance(new Object[] { this, info.getPageId(), info.getPageName() });
} else {
page = (IExtendedPage) cls.newInstance();
((IExtendedPage) page).init(this);
}
if (page instanceof ExtendPageWithMyDirtySystem) {
((ExtendPageWithMyDirtySystem)page).setInfo(getInfo());
if (!info.isHidden() && ((IExtendItemLoader) page).shouldLoad()) {
addPage((FormPage)page);
}
}
extendsPages.add(page);
} catch (Exception e) {
logger.error("��ȡ��չҳ���쳣", e);
}
}
}
protected void handleBeforeSave() {
for (IExtendedPage page : extendsPages) {
page.beforeSave();
}
}
protected void handleAfterSave() {
for (IExtendedPage page : extendsPages) {
page.afterSave();
}
}
@Override
final public void doSave(IProgressMonitor monitor) {
fileSyncUnit.beforeSave();
if (isReadOnly()) {
MessageDialog.openInformation(getSite().getShell(), "������", "��ǰ��Դ��ֻ��״̬�������б���");
} else {
handleBeforeSave();
WorkspaceModifyOperation operation =
new WorkspaceModifyOperation() {
@Override
public void execute(IProgressMonitor monitor) {
try {
IARESResource aresResource = getARESResource();
aresResource.save(getInfo(), true, monitor);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
};
try {
operation.run(monitor);
((BasicCommandStack)editingDomain.getCommandStack()).saveIsDone();
firePropertyChange(IEditorPart.PROP_DIRTY);
handleAfterSave();
} catch (Exception exception) {
MessageDialog.openError(getSite().getShell(), "����ʧ��", "�쳣��Ϣ��" + exception.getMessage());
}
}
}
@Override
public void doSaveAs() {
throw new UnsupportedOperationException();
}
@Override
public boolean isSaveAsAllowed() {
return false;
}
/* (non-Javadoc)
* @see org.eclipse.ui.forms.editor.FormEditor#createToolkit(org.eclipse.swt.widgets.Display)
*/
@Override
protected FormToolkit createToolkit(Display display) {
return new FormToolkitEx(display);
}
/**
* ���ر༭������ı༭��
* @return
*/
protected IDialogSettings getDialogSettings() {
IDialogSettings settings = ARESEditorPlugin.getDefault().getDialogSettings();
EClass eClass =getInfoClass();
IDialogSettings blockSettings = null;
if(eClass!=null){
blockSettings = settings.getSection(eClass.getInstanceClassName());
if (blockSettings == null) {
blockSettings = settings.addNewSection(eClass.getInstanceClassName());
blockSettings.put(ACTIVE_EDITOR_INDEX, 0);
}
}
return blockSettings;
}
/**
* ���ر༭�����Ļ�ı༭��
* @return
*/
protected int getEditorIndex() {
IDialogSettings settings = getDialogSettings();
if (settings != null) {
try{
editorIndex = settings.getInt(ACTIVE_EDITOR_INDEX);
}catch(Exception e){
editorIndex = 0;
}
}
if(editorIndex <0){
editorIndex = 0;
}
return editorIndex;
}
@Override
public void dispose() {
EditingDomainManager.getInstance().deconfigureListeners(getEditingDomainID(), editingDomain);
JRESEditorSyncManager.getInstance().removeSyncUnit(fileSyncUnit);
super.dispose();
IDialogSettings settings = getDialogSettings();
if(settings!=null){
settings.put(ACTIVE_EDITOR_INDEX, getCurrentPage());
}
}
}