Opened unchanged editors marked as dirty... [message #1105230] |
Mon, 09 September 2013 10:46  |
Eclipse User |
|
|
|
Hi all,
I try to build some kind of modeling tool based on Graphiti with CDO as back end storage.
When I create a new element, I also create a new empty diagram and open the corresponding editor which is marked as dirty ('*').
I then successfully save my created element and its associated diagram in a dedicated resource in CDO.
To achieve this, I slightly modified the default update and persistency behaviors.
I use a 'CDO compliant' transactional editing domain and commit the opened CDO transaction when saving.
My problem occurs when I create a second element and its empty diagram.
Then the first opened editor is marked as dirty !?
Moreover, when I save the second editor and close my modeling tool, it doesn't ask for saving the first opened editor. So, even if marked, it seems it's not considered as dirty...
While browsing this forum, I found a reference to the bug 35109 "Unconditional Auto-refresh for Diagrams". It describes 3 situations in which an update can happen and how it is handled by Graphiti diagram type provider.
The third case "EMF object changes from within the same editing domain" corresponds to my situation.
But It's written that no update should happen on a saved editor...
Any idea of what's wrong and how to solve this ?
Kind regards
|
|
|
|
|
Re: Opened unchanged editors marked as dirty... [message #1112214 is a reply to message #1108228] |
Thu, 19 September 2013 05:03   |
Eclipse User |
|
|
|
Hi Michael,
Dawn implements its own "isDirty strategy" and overrides the corresponding method(s).
Before I do that, I would like to better understand what happens...
When opening my first diagram, no problem, it's not dirty.
DiagramBehavior#isDirty calls GFWorkspaceCommandStackImpl(WorkspaceCommandStackImpl)#isSaveNeeded :
public boolean isSaveNeeded() {
// We override the execute method and never call the super implementation
// so we have to implement the isSaveNeeded method ourselves.
IUndoableOperation nextUndoableOperation = history.getUndoOperation(getDefaultUndoContext());
if (nextUndoableOperation == null) {
return savedContext != null;
}
return savedContext != null ? !nextUndoableOperation.hasContext(getSavedContext()) : true;
}
nextUndoableOperation and savedContext are null, thus the method returns false which is coherent.
But, when opening a second diagram (regarding another EMF object of same type), nextUndoableOperation = EMFCommandOperation with 'update' label and encapsulating a EmfOnGefCommand !?
And the first opened editor becomes dirty...
In debug mode, I noticed this operation is also added to the operation history when opening the first editor but 'disappears' somehow before isSaveNeeded is called.
Actually this method is called a couple of times when opening each editor.
When opening the first one, I get like 4 calls all returning false.
When opening the second one, I get about 3 times true and a last call returning false !?
I also noticed that, when opening only one diagram displaying two emf objects with a containment relation (like 'service' and its 'operations'), the editor is always dirty. Whereas, for a diagram containing two objects without containment relationship (like two services), the opened editor is 'clean' until I open another one...
To sum up, this EmfOnGefCommand - a Graphiti object - appears to be the reason why an editor becomes dirty. Not knowing Graphiti internals, I'm confused. Any idea of what may happen ?
Regards,
Laurent
|
|
|
|
|
Re: Opened unchanged editors marked as dirty... [message #1115793 is a reply to message #1113064] |
Tue, 24 September 2013 11:30  |
Eclipse User |
|
|
|
Hi again,
Just to say that i created a TED for my explorer and also one per editor instance and it now works just fine.
Many thanks for your help Michael !
Some more details for anyone interested.
Hereafter an extension of DiagramEditor to use a CDO TED :
@SuppressWarnings("restriction")
public class GraphitiEditor extends DiagramEditor {
private CDODiagramEditorInput input = null;
@Override
public void init(IEditorSite site, IEditorInput input) throws PartInitException {
this.input = (CDODiagramEditorInput) input;
super.init(site, input);
}
@Override
protected DiagramBehavior createDiagramBehavior() {
return new DiagramBehavior(this) {
/*
* Modify the default update behavior to use CDO compliant transactional editing domain
* @see org.eclipse.graphiti.ui.editor.DiagramBehavior#createUpdateBehavior()
*/
@Override
protected DefaultUpdateBehavior createUpdateBehavior() {
return new DefaultUpdateBehavior(this) {
@Override
protected void createEditingDomain() {
TransactionalEditingDomain editingDomain =
(new CDOTransactionalEditingDomainImpl.CDOFactoryImpl()).createEditingDomain();
initializeEditingDomain(editingDomain);
}
@Override
protected void disposeEditingDomain() {
getEditingDomain().dispose();
}
};
}
@Override
protected DefaultPersistencyBehavior getPersistencyBehavior() {
return new DefaultPersistencyBehavior(this) {
/*
* Make sure the resource containing the diagram is added to the TED before loading...
* @see org.eclipse.graphiti.ui.editor.DefaultPersistencyBehavior#loadDiagram(org.eclipse.emf.common.util.URI)
*/
@Override
public Diagram loadDiagram(URI uri) {
if (uri != null) {
final TransactionalEditingDomain editingDomain = diagramBehavior.getEditingDomain();
if (editingDomain != null) {
// Adding the diagram resource to the TED
IEclipseContext context = EclipseContextFactory.getServiceContext(Activator.getContext());
CDOTransaction transaction = (CDOTransaction) context.get("openedCDOTransaction");
Resource diagRes = transaction.getResource(uri.path());
editingDomain.getResourceSet().getResources().add(diagRes);
// Find object but using CDO API...
EObject modelElement = null;
try {
modelElement = transaction.getObject(input.getDiagramId(), false);
if (modelElement == null) {
modelElement = transaction.getObject(input.getDiagramId(), true);
if (modelElement == null) {
return null;
}
}
} catch (WrappedException e) {
// Log only if debug tracing is active to avoid user
// confusion (message is shown in the editor anyhow)
T.racer().debug("Diagram with URI '" + uri.toString() + "' could not be loaded", e); //$NON-NLS-1$ //$NON-NLS-2$
return null;
}
modelElement.eResource().setTrackingModification(true);
return (Diagram) modelElement;
}
}
return null;
}
/*
* Modify the default persistency behavior to add CDO transaction commit while saving the editor modifications
* @see org.eclipse.graphiti.ui.editor.DefaultPersistencyBehavior#save(org.eclipse.emf.transaction.TransactionalEditingDomain, java.util.Map, org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
protected Set<Resource> save(TransactionalEditingDomain editingDomain, Map<Resource,Map<?,?>> saveOptions,
IProgressMonitor monitor) {
Set<Resource> resSet = super.save(editingDomain, saveOptions, monitor);
IEclipseContext context = EclipseContextFactory.getServiceContext(Activator.getContext());
CDOTransaction transaction = (CDOTransaction) context.get("openedCDOTransaction");
try {
transaction.commit();
} catch (ConcurrentAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CommitException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return resSet;
}
};
}
};
}
}
The used CDO Diagram Editor Input :
public class CDODiagramEditorInput implements IDiagramEditorInput, IEditorInput {
private String providerId = null;
private URI diagramURI = null;
private CDOEditorInput cdoEditorInput = null;
private CDOID diagramId = null;
public CDODiagramEditorInput(CDOView view, URI resourceURI, boolean viewOwned, CDOID ID) {
cdoEditorInput = CDOEditorUtil.createCDOEditorInput(view, resourceURI.path(), viewOwned);
this.diagramURI = resourceURI;
this.diagramId = ID;
}
/*
* From the diagram CDO ID, it's possible to get the editor TED in the eclipse context map.
*/
public CDOID getDiagramId() {
return diagramId;
}
/*
* Compare diagrams in order not to open several Graphiti editors on the same content
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (obj instanceof CDODiagramEditorInput) {
return ((CDODiagramEditorInput)obj).diagramId.equals(diagramId);
}
return false;
}
@Override
public String getUriString() {
return cdoEditorInput.getResourcePath();
}
@Override
public URI getUri() {
return this.diagramURI;
}
@Override
public String getProviderId() {
return this.providerId;
}
@Override
public void setProviderId(String providerId) {
this.providerId = providerId;
}
@Override
public void updateUri(URI newURI) {
this.diagramURI = newURI;
}
@Override
public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
return cdoEditorInput.getAdapter(adapter);
}
@Override
public boolean exists() {
return cdoEditorInput.exists();
}
@Override
public ImageDescriptor getImageDescriptor() {
return cdoEditorInput.getImageDescriptor();
}
@Override
public String getName() {
return cdoEditorInput.getName();
}
@Override
public IPersistableElement getPersistable() {
return cdoEditorInput.getPersistable();
}
@Override
public String getToolTipText() {
return cdoEditorInput.getToolTipText();
}
}
And a link to the CDO TED code itself :
http://www.eclipse.org/forums/index.php/m/1121603/#msg_1121603
[Updated on: Mon, 30 September 2013 16:17] by Moderator
|
|
|
Powered by
FUDForum. Page generated in 0.04786 seconds