it = info.getResourceSet().getResources().iterator(); it.hasNext();) {
+ Resource nextResource = it.next();
+
+ // bug 347300: skip faulty URIs
+ if( isBadURI(nextResource)) {
+ continue;
+ }
+ IFile file = WorkspaceSynchronizer.getFile(nextResource);
+ if(file != null) {
+ if(file.getLocation() != null) {
+ result += file.getLocation().toFile().lastModified();
+ } else {
+ result += file.getModificationStamp();
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Return true if the URI is a faulty URI, false otherwise.
+ * Faulty URI: scheme = pathmap, platform
+ * @param resource
+ * @return
+ */
+ private boolean isBadURI(Resource resource) {
+ try {
+ java.net.URI uri = new java.net.URI(resource.getURI().toString());
+ String scheme = uri.getScheme();
+ if( "pathmap".equals(scheme) || "platform".equals(scheme)) {
+ return true;
+ }
+
+ // not a bad uri
+ return false;
+ } catch (URISyntaxException e) {
+ return true;
+ }
+ }
+
+ /**
+ * @generated
+ */
+ protected IDocument createEmptyDocument() {
+ DiagramDocument document = new DiagramDocument();
+ document.setEditingDomain(createEditingDomain());
+ return document;
+ }
+
+ /**
+ * Create the editing Domain. All Editing Domain will be created with the same ResourceSet. The
+ * first creation will record the ResourceSet, other creation will use it.
+ */
+ private TransactionalEditingDomain createEditingDomain() {
+
+ TransactionalEditingDomain editingDomain = null;
+ // System.out.println(this.getClass().getSimpleName() + "- (" + this + ")");
+ // Check if edit domain exist
+ if(sharedEditingDomain != null) { // Already initialized
+ editingDomain = sharedEditingDomain;
+// System.out.println(this.getClass().getSimpleName()
+// + ".createEditingDomain() - got EditingDomain from previous call (" + editingDomain + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+ return editingDomain;
+ }
+
+ // No editingDomain. Create and initialize a new one.
+
+ // Try to get a registered one if any
+ editingDomain = TransactionalEditingDomain.Registry.INSTANCE.getEditingDomain(EditingDomainID);
+ if(editingDomain != null) {
+ // got it
+ sharedEditingDomain = editingDomain;
+ Activator.log.debug((this.getClass().getSimpleName()
+ + ".createEditingDomain() - got EditingDomain from REGISTRY (" + editingDomain + ")")); //$NON-NLS-1$ //$NON-NLS-2$
+ return editingDomain;
+ }
+
+ // Create EditingDomain using provided ResourceSet if any.
+ if(resourceSet == null) {
+ editingDomain = DiagramEditingDomainFactory.getInstance().createEditingDomain();
+ } else {
+ editingDomain = DiagramEditingDomainFactory.getInstance().createEditingDomain(resourceSet);
+ }
+ sharedEditingDomain = editingDomain;
+ editingDomain.setID(EditingDomainID); //$NON-NLS-1$
+ Activator.log.debug(this.getClass().getSimpleName()
+ + ".createEditingDomain() - create a new EditingDomain (" + editingDomain + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ configureEditingDomain(editingDomain);
+
+ return editingDomain;
+ }
+
+ /**
+ * Configure an EditingDomain suitable for GMF. This method should be called only once for an
+ * EditingDomain.
+ *
+ * @param editingDomain
+ */
+ private void configureEditingDomain(TransactionalEditingDomain editingDomain) {
+ // Add listener on resource change
+ final NotificationFilter diagramResourceModifiedFilter = NotificationFilter.createNotifierFilter(
+ editingDomain.getResourceSet()).and(NotificationFilter.createEventTypeFilter(Notification.ADD)).and(
+ NotificationFilter.createFeatureFilter(ResourceSet.class, ResourceSet.RESOURCE_SET__RESOURCES));
+ editingDomain.getResourceSet().eAdapters().add(new Adapter() {
+
+ private Notifier myTarger;
+
+ public Notifier getTarget() {
+ return myTarger;
+ }
+
+ public boolean isAdapterForType(Object type) {
+ return false;
+ }
+
+ public void notifyChanged(Notification notification) {
+ if(diagramResourceModifiedFilter.matches(notification)) {
+ Object value = notification.getNewValue();
+ if(value instanceof Resource) {
+ ((Resource)value).setTrackingModification(true);
+ }
+ }
+ }
+
+ public void setTarget(Notifier newTarget) {
+ myTarger = newTarget;
+ }
+
+ });
+ }
+
+ /**
+ * @generated
+ */
+ protected void setDocumentContent(IDocument document, IEditorInput element) throws CoreException {
+ IDiagramDocument diagramDocument = (IDiagramDocument)document;
+ TransactionalEditingDomain domain = diagramDocument.getEditingDomain();
+ if(element instanceof FileEditorInput) {
+ IStorage storage = ((FileEditorInput)element).getStorage();
+ Diagram diagram = DiagramIOUtil.load(domain, storage, true, getProgressMonitor());
+ document.setContent(diagram);
+ } else if(element instanceof URIEditorInput) {
+ URI uri = ((URIEditorInput)element).getURI();
+ Resource resource = null;
+ try {
+ resource = domain.getResourceSet().getResource(uri.trimFragment(), false);
+ if(resource == null) {
+ resource = domain.getResourceSet().createResource(uri.trimFragment());
+ }
+ if(!resource.isLoaded()) {
+ try {
+ Map options = new HashMap(GMFResourceFactory.getDefaultLoadOptions());
+ // @see 171060
+ // options.put(org.eclipse.emf.ecore.xmi.XMLResource.OPTION_RECORD_UNKNOWN_FEATURE,
+ // Boolean.TRUE);
+ resource.load(options);
+ } catch (IOException e) {
+ resource.unload();
+ throw e;
+ }
+ }
+ if(uri.fragment() != null) {
+ EObject rootElement = resource.getEObject(uri.fragment());
+ if(rootElement instanceof Diagram) {
+ document.setContent((Diagram)rootElement);
+ return;
+ }
+ } else {
+ for(Iterator it = resource.getContents().iterator(); it.hasNext();) {
+ Object rootElement = it.next();
+ if(rootElement instanceof Diagram) {
+ document.setContent((Diagram)rootElement);
+ return;
+ }
+ }
+ }
+ throw new RuntimeException(Messages.GmfMultiDiagramDocumentProvider_NoDiagramInResourceError);
+ } catch (Exception e) {
+ CoreException thrownExcp = null;
+ if(e instanceof CoreException) {
+ thrownExcp = (CoreException)e;
+ } else {
+ String msg = e.getLocalizedMessage();
+ thrownExcp = new CoreException(new Status(IStatus.ERROR, Activator.ID, 0, msg != null ? msg
+ : Messages.GmfMultiDiagramDocumentProvider_DiagramLoadingError, e));
+ }
+ throw thrownExcp;
+ }
+ } else {
+ throw new CoreException(new Status(IStatus.ERROR, Activator.ID, 0, NLS.bind(
+ Messages.GmfMultiDiagramDocumentProvider_IncorrectInputError, new Object[]{ element, "org.eclipse.ui.part.FileEditorInput", "org.eclipse.emf.common.ui.URIEditorInput" }), //$NON-NLS-1$ //$NON-NLS-2$
+ null));
+ }
+ }
+
+ /**
+ * @generated
+ */
+ public long getModificationStamp(Object element) {
+ ResourceSetInfo info = getResourceSetInfo(element);
+ if(info != null) {
+ return computeModificationStamp(info);
+ }
+ return super.getModificationStamp(element);
+ }
+
+ /**
+ * @generated
+ */
+ public boolean isDeleted(Object element) {
+ IDiagramDocument document = getDiagramDocument(element);
+ if(document != null) {
+ Resource diagramResource = document.getDiagram().eResource();
+ if(diagramResource != null) {
+ IFile file = WorkspaceSynchronizer.getFile(diagramResource);
+ return file == null || file.getLocation() == null || !file.getLocation().toFile().exists();
+ }
+ }
+ return super.isDeleted(element);
+ }
+
+ /**
+ * @generated
+ */
+ public ResourceSetInfo getResourceSetInfo(Object editorInput) {
+ return (ResourceSetInfo)super.getElementInfo(editorInput);
+ }
+
+ /**
+ * @generated
+ */
+ protected void disposeElementInfo(Object element, ElementInfo info) {
+ if(info instanceof ResourceSetInfo) {
+ ResourceSetInfo resourceSetInfo = (ResourceSetInfo)info;
+ resourceSetInfo.dispose();
+ }
+ super.disposeElementInfo(element, info);
+ }
+
+ /**
+ * @generated
+ */
+ protected void doValidateState(Object element, Object computationContext) throws CoreException {
+ ResourceSetInfo info = getResourceSetInfo(element);
+ if(info != null) {
+ Collection files2Validate = new ArrayList();
+ for(Iterator it = info.getResourceSet().getResources().iterator(); it.hasNext();) {
+ Resource nextResource = (Resource)it.next();
+ IFile file = WorkspaceSynchronizer.getFile(nextResource);
+ if(file != null && file.isReadOnly()) {
+ files2Validate.add(file);
+ }
+ }
+ ResourcesPlugin.getWorkspace().validateEdit(
+ (IFile[])files2Validate.toArray(new IFile[files2Validate.size()]), computationContext);
+ }
+
+ super.doValidateState(element, computationContext);
+ }
+
+ /**
+ * @generated
+ */
+ public boolean isReadOnly(Object element) {
+ ResourceSetInfo info = getResourceSetInfo(element);
+ if(info != null) {
+ if(info.isUpdateCache()) {
+ try {
+ updateCache(element);
+ } catch (CoreException ex) {
+ Activator.getInstance().logError(Messages.GmfMultiDiagramDocumentProvider_isModifiable, ex);
+ // Error message to log was initially taken from
+ // org.eclipse.gmf.runtime.diagram.ui.resources.editor.ide.internal.l10n.EditorMessages.StorageDocumentProvider_isModifiable
+ }
+ }
+ return info.isReadOnly();
+ }
+ return super.isReadOnly(element);
+ }
+
+ /**
+ * @generated
+ */
+ public boolean isModifiable(Object element) {
+ if(!isStateValidated(element)) {
+ if(element instanceof FileEditorInput || element instanceof URIEditorInput) {
+ return true;
+ }
+ }
+ ResourceSetInfo info = getResourceSetInfo(element);
+ if(info != null) {
+ if(info.isUpdateCache()) {
+ try {
+ updateCache(element);
+ } catch (CoreException ex) {
+ Activator.getInstance().logError(Messages.GmfMultiDiagramDocumentProvider_isModifiable, ex);
+ // Error message to log was initially taken from
+ // org.eclipse.gmf.runtime.diagram.ui.resources.editor.ide.internal.l10n.EditorMessages.StorageDocumentProvider_isModifiable
+ }
+ }
+ return info.isModifiable();
+ }
+ return super.isModifiable(element);
+ }
+
+ /**
+ * @generated
+ */
+ protected void updateCache(Object element) throws CoreException {
+ ResourceSetInfo info = getResourceSetInfo(element);
+ if(info != null) {
+ for(Iterator it = info.getResourceSet().getResources().iterator(); it.hasNext();) {
+ Resource nextResource = (Resource)it.next();
+ IFile file = WorkspaceSynchronizer.getFile(nextResource);
+ if(file != null && file.isReadOnly()) {
+ info.setReadOnly(true);
+ info.setModifiable(false);
+ return;
+ }
+ }
+ info.setReadOnly(false);
+ info.setModifiable(true);
+ return;
+ }
+ }
+
+ /**
+ * @generated
+ */
+ protected void doUpdateStateCache(Object element) throws CoreException {
+ ResourceSetInfo info = getResourceSetInfo(element);
+ if(info != null) {
+ info.setUpdateCache(true);
+ }
+ super.doUpdateStateCache(element);
+ }
+
+ /**
+ * @generated
+ */
+ public boolean isSynchronized(Object element) {
+ ResourceSetInfo info = getResourceSetInfo(element);
+ if(info != null) {
+ return info.isSynchronized();
+ }
+ return super.isSynchronized(element);
+ }
+
+ /**
+ * @generated
+ */
+ protected ISchedulingRule getResetRule(Object element) {
+ ResourceSetInfo info = getResourceSetInfo(element);
+ if(info != null) {
+ Collection rules = new ArrayList();
+ for(Iterator it = info.getResourceSet().getResources().iterator(); it.hasNext();) {
+ Resource nextResource = (Resource)it.next();
+ IFile file = WorkspaceSynchronizer.getFile(nextResource);
+ if(file != null) {
+ rules.add(ResourcesPlugin.getWorkspace().getRuleFactory().modifyRule(file));
+ }
+ }
+ return new MultiRule((ISchedulingRule[])rules.toArray(new ISchedulingRule[rules.size()]));
+ }
+ return null;
+ }
+
+ /**
+ * @generated
+ */
+ protected ISchedulingRule getSaveRule(Object element) {
+ ResourceSetInfo info = getResourceSetInfo(element);
+ if(info != null) {
+ Collection rules = new ArrayList();
+ for(Iterator it = info.getResourceSet().getResources().iterator(); it.hasNext();) {
+ Resource nextResource = (Resource)it.next();
+ IFile file = WorkspaceSynchronizer.getFile(nextResource);
+ if(file != null) {
+ rules.add(computeSchedulingRule(file));
+ }
+ }
+ return new MultiRule((ISchedulingRule[])rules.toArray(new ISchedulingRule[rules.size()]));
+ }
+ return null;
+ }
+
+ /**
+ * @generated
+ */
+ protected ISchedulingRule getSynchronizeRule(Object element) {
+ ResourceSetInfo info = getResourceSetInfo(element);
+ if(info != null) {
+ Collection rules = new ArrayList();
+ for(Iterator it = info.getResourceSet().getResources().iterator(); it.hasNext();) {
+ Resource nextResource = (Resource)it.next();
+ IFile file = WorkspaceSynchronizer.getFile(nextResource);
+ if(file != null) {
+ rules.add(ResourcesPlugin.getWorkspace().getRuleFactory().refreshRule(file));
+ }
+ }
+ return new MultiRule((ISchedulingRule[])rules.toArray(new ISchedulingRule[rules.size()]));
+ }
+ return null;
+ }
+
+ /**
+ * @generated
+ */
+ protected ISchedulingRule getValidateStateRule(Object element) {
+ ResourceSetInfo info = getResourceSetInfo(element);
+ if(info != null) {
+ Collection files = new ArrayList();
+ for(Iterator it = info.getResourceSet().getResources().iterator(); it.hasNext();) {
+ Resource nextResource = (Resource)it.next();
+ IFile file = WorkspaceSynchronizer.getFile(nextResource);
+ if(file != null) {
+ files.add(file);
+ }
+ }
+ return ResourcesPlugin.getWorkspace().getRuleFactory().validateEditRule(
+ (IFile[])files.toArray(new IFile[files.size()]));
+ }
+ return null;
+ }
+
+ /**
+ * @generated
+ */
+ private ISchedulingRule computeSchedulingRule(IResource toCreateOrModify) {
+ if(toCreateOrModify.exists())
+ return ResourcesPlugin.getWorkspace().getRuleFactory().modifyRule(toCreateOrModify);
+
+ IResource parent = toCreateOrModify;
+ do {
+ /*
+ * XXX This is a workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=67601
+ * IResourceRuleFactory.createRule should iterate the hierarchy itself.
+ */
+ toCreateOrModify = parent;
+ parent = toCreateOrModify.getParent();
+ } while(parent != null && !parent.exists());
+
+ return ResourcesPlugin.getWorkspace().getRuleFactory().createRule(toCreateOrModify);
+ }
+
+ /**
+ * @generated
+ */
+ protected void doSynchronize(Object element, IProgressMonitor monitor) throws CoreException {
+ ResourceSetInfo info = getResourceSetInfo(element);
+ if(info != null) {
+ for(Iterator it = info.getResourceSet().getResources().iterator(); it.hasNext();) {
+ Resource nextResource = (Resource)it.next();
+ handleElementChanged(info, nextResource, monitor);
+ }
+ return;
+ }
+ super.doSynchronize(element, monitor);
+ }
+
+ /**
+ * @generated
+ */
+ protected void doSaveDocument(IProgressMonitor monitor, Object element, IDocument document, boolean overwrite)
+ throws CoreException {
+ ResourceSetInfo info = getResourceSetInfo(element);
+ if(info != null) {
+ if(!overwrite && !info.isSynchronized()) {
+ throw new CoreException(new Status(IStatus.ERROR, Activator.ID, IResourceStatus.OUT_OF_SYNC_LOCAL,
+ Messages.GmfMultiDiagramDocumentProvider_UnsynchronizedFileSaveError, null));
+ }
+ info.stopResourceListening();
+ fireElementStateChanging(element);
+ List resources = info.getResourceSet().getResources();
+ try {
+ monitor.beginTask(Messages.GmfMultiDiagramDocumentProvider_SaveDiagramTask, resources.size() + 1); // "Saving diagram"
+ for(Iterator it = resources.iterator(); it.hasNext();) {
+ Resource nextResource = (Resource)it.next();
+ monitor.setTaskName(NLS.bind(Messages.GmfMultiDiagramDocumentProvider_SaveNextResourceTask,
+ nextResource.getURI()));
+ if(nextResource.isLoaded() && !info.getEditingDomain().isReadOnly(nextResource)) {
+ try {
+ nextResource.save(UMLDiagramEditorUtil.getSaveOptions());
+ } catch (IOException e) {
+ fireElementStateChangeFailed(element);
+ throw new CoreException(new Status(IStatus.ERROR, Activator.ID,
+ EditorStatusCodes.RESOURCE_FAILURE, e.getLocalizedMessage(), null));
+ }
+ }
+ monitor.worked(1);
+ }
+ monitor.done();
+ info.setModificationStamp(computeModificationStamp(info));
+ } catch (RuntimeException x) {
+ fireElementStateChangeFailed(element);
+ throw x;
+ } finally {
+ info.startResourceListening();
+ }
+ } else {
+ URI newResoruceURI;
+ List affectedFiles = null;
+ if(element instanceof FileEditorInput) {
+ IFile newFile = ((FileEditorInput)element).getFile();
+ affectedFiles = Collections.singletonList(newFile);
+ newResoruceURI = URI.createPlatformResourceURI(newFile.getFullPath().toString(), true);
+ } else if(element instanceof URIEditorInput) {
+ newResoruceURI = ((URIEditorInput)element).getURI();
+ } else {
+ fireElementStateChangeFailed(element);
+ throw new CoreException(new Status(IStatus.ERROR, Activator.ID, 0, NLS.bind(
+ Messages.GmfMultiDiagramDocumentProvider_IncorrectInputError, new Object[]{ element, "org.eclipse.ui.part.FileEditorInput", "org.eclipse.emf.common.ui.URIEditorInput" }), //$NON-NLS-1$ //$NON-NLS-2$
+ null));
+ }
+ if(false == document instanceof IDiagramDocument) {
+ fireElementStateChangeFailed(element);
+ throw new CoreException(
+ new Status(
+ IStatus.ERROR,
+ Activator.ID,
+ 0,
+ "Incorrect document used: " + document + " instead of org.eclipse.gmf.runtime.diagram.ui.resources.editor.document.IDiagramDocument", null)); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ IDiagramDocument diagramDocument = (IDiagramDocument)document;
+ final Resource newResource = diagramDocument.getEditingDomain().getResourceSet().createResource(
+ newResoruceURI);
+ final Diagram diagramCopy = (Diagram)EcoreUtil.copy(diagramDocument.getDiagram());
+ try {
+ new AbstractTransactionalCommand(diagramDocument.getEditingDomain(), NLS.bind(
+ Messages.GmfMultiDiagramDocumentProvider_SaveAsOperation, diagramCopy.getName()), affectedFiles) {
+
+ protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info)
+ throws ExecutionException {
+ newResource.getContents().add(diagramCopy);
+ return CommandResult.newOKCommandResult();
+ }
+ }.execute(monitor, null);
+ newResource.save(UMLDiagramEditorUtil.getSaveOptions());
+ } catch (ExecutionException e) {
+ fireElementStateChangeFailed(element);
+ throw new CoreException(new Status(IStatus.ERROR, Activator.ID, 0, e.getLocalizedMessage(), null));
+ } catch (IOException e) {
+ fireElementStateChangeFailed(element);
+ throw new CoreException(new Status(IStatus.ERROR, Activator.ID, 0, e.getLocalizedMessage(), null));
+ }
+ newResource.unload();
+ }
+ }
+
+ /**
+ * @generated
+ */
+ protected void handleElementChanged(ResourceSetInfo info, Resource changedResource, IProgressMonitor monitor) {
+ IFile file = WorkspaceSynchronizer.getFile(changedResource);
+ if(file != null) {
+ try {
+ file.refreshLocal(IResource.DEPTH_INFINITE, monitor);
+ } catch (CoreException ex) {
+ Activator.getInstance().logError(Messages.GmfMultiDiagramDocumentProvider_handleElementContentChanged,
+ ex);
+ // Error message to log was initially taken from
+ // org.eclipse.gmf.runtime.diagram.ui.resources.editor.ide.internal.l10n.EditorMessages.FileDocumentProvider_handleElementContentChanged
+ }
+ }
+ changedResource.unload();
+
+ fireElementContentAboutToBeReplaced(info.getEditorInput());
+ removeUnchangedElementListeners(info.getEditorInput(), info);
+ info.fStatus = null;
+ try {
+ setDocumentContent(info.fDocument, info.getEditorInput());
+ } catch (CoreException e) {
+ info.fStatus = e.getStatus();
+ }
+ if(!info.fCanBeSaved) {
+ info.setModificationStamp(computeModificationStamp(info));
+ }
+ addUnchangedElementListeners(info.getEditorInput(), info);
+ fireElementContentReplaced(info.getEditorInput());
+ }
+
+ /**
+ * @generated
+ */
+ protected void handleElementMoved(IEditorInput input, URI uri) {
+ if(input instanceof FileEditorInput) {
+ IFile newFile = ResourcesPlugin.getWorkspace().getRoot().getFile(
+ new Path(URI.decode(uri.path())).removeFirstSegments(1));
+ fireElementMoved(input, newFile == null ? null : new FileEditorInput(newFile));
+ return;
+ }
+ // TODO: append suffix to the URI! (use diagram as a parameter)
+ fireElementMoved(input, new URIEditorInput(uri));
+ }
+
+ /**
+ * @generated
+ */
+ public IEditorInput createInputWithEditingDomain(IEditorInput editorInput, TransactionalEditingDomain domain) {
+ return editorInput;
+ }
+
+ /**
+ * @generated
+ */
+ public IDiagramDocument getDiagramDocument(Object element) {
+ IDocument doc = getDocument(element);
+ if(doc instanceof IDiagramDocument) {
+ return (IDiagramDocument)doc;
+ }
+ return null;
+ }
+
+ /**
+ * @generated
+ */
+ protected IRunnableContext getOperationRunner(IProgressMonitor monitor) {
+ return null;
+ }
+
+ /**
+ * @generated
+ */
+ protected class ResourceSetInfo extends ElementInfo {
+
+ /**
+ * @generated
+ */
+ private long myModificationStamp = IResource.NULL_STAMP;
+
+ /**
+ * @generated
+ */
+ private WorkspaceSynchronizer mySynchronizer;
+
+ /**
+ * @generated
+ */
+ private Collection myUnSynchronizedResources = new ArrayList();
+
+ /**
+ * @generated
+ */
+ private IDiagramDocument myDocument;
+
+ /**
+ * @generated
+ */
+ private IEditorInput myEditorInput;
+
+ /**
+ * @generated
+ */
+ private boolean myUpdateCache = true;
+
+ /**
+ * @generated
+ */
+ private boolean myModifiable = false;
+
+ /**
+ * @generated
+ */
+ private boolean myReadOnly = true;
+
+ /**
+ * @generated
+ */
+ private ResourceSetModificationListener myResourceSetListener;
+
+ /**
+ * @generated
+ */
+ public ResourceSetInfo(IDiagramDocument document, IEditorInput editorInput) {
+ super(document);
+ myDocument = document;
+ myEditorInput = editorInput;
+ startResourceListening();
+ myResourceSetListener = new ResourceSetModificationListener(this);
+ getResourceSet().eAdapters().add(myResourceSetListener);
+ }
+
+ /**
+ * @generated
+ */
+ public long getModificationStamp() {
+ return myModificationStamp;
+ }
+
+ /**
+ * @generated
+ */
+ public void setModificationStamp(long modificationStamp) {
+ myModificationStamp = modificationStamp;
+ }
+
+ /**
+ * @generated
+ */
+ public TransactionalEditingDomain getEditingDomain() {
+ return myDocument.getEditingDomain();
+ }
+
+ /**
+ * @generated
+ */
+ public ResourceSet getResourceSet() {
+ return getEditingDomain().getResourceSet();
+ }
+
+ /**
+ * @generated
+ */
+ public IEditorInput getEditorInput() {
+ return myEditorInput;
+ }
+
+ /**
+ * @generated
+ */
+ public void dispose() {
+ stopResourceListening();
+ getResourceSet().eAdapters().remove(myResourceSetListener);
+ for(Iterator it = getResourceSet().getResources().iterator(); it.hasNext();) {
+ Resource resource = (Resource)it.next();
+ // Do not unload the resource because the DocumentProvider can be disposed while its
+ // Diagram node is
+ // kept for future re-openeing.
+ // resource.unload();
+ }
+ }
+
+ /**
+ * @generated
+ */
+ public boolean isSynchronized() {
+ return myUnSynchronizedResources.size() == 0;
+ }
+
+ /**
+ * @generated
+ */
+ public void setUnSynchronized(Resource resource) {
+ myUnSynchronizedResources.add(resource);
+ }
+
+ /**
+ * @generated
+ */
+ public void setSynchronized(Resource resource) {
+ myUnSynchronizedResources.remove(resource);
+ }
+
+ /**
+ * @generated
+ */
+ public final void stopResourceListening() {
+ // mySynchronizer.dispose();
+ mySynchronizer = null;
+ }
+
+ /**
+ * @generated
+ */
+ public final void startResourceListening() {
+ // Do not listen because all document use the same EditingDomain
+ // mySynchronizer = new WorkspaceSynchronizer(getEditingDomain(), new
+ // SynchronizerDelegate());
+ }
+
+ /**
+ * @generated
+ */
+ public boolean isUpdateCache() {
+ return myUpdateCache;
+ }
+
+ /**
+ * @generated
+ */
+ public void setUpdateCache(boolean update) {
+ myUpdateCache = update;
+ }
+
+ /**
+ * @generated
+ */
+ public boolean isModifiable() {
+ return myModifiable;
+ }
+
+ /**
+ * @generated
+ */
+ public void setModifiable(boolean modifiable) {
+ myModifiable = modifiable;
+ }
+
+ /**
+ * @generated
+ */
+ public boolean isReadOnly() {
+ return myReadOnly;
+ }
+
+ /**
+ * @generated
+ */
+ public void setReadOnly(boolean readOnly) {
+ myReadOnly = readOnly;
+ }
+
+ /**
+ * @generated
+ */
+ private class SynchronizerDelegate implements WorkspaceSynchronizer.Delegate {
+
+ /**
+ * @generated
+ */
+ public void dispose() {
+ }
+
+ /**
+ * @generated
+ */
+ public boolean handleResourceChanged(final Resource resource) {
+ synchronized(ResourceSetInfo.this) {
+ if(ResourceSetInfo.this.fCanBeSaved) {
+ ResourceSetInfo.this.setUnSynchronized(resource);
+ return true;
+ }
+ }
+ Display.getDefault().asyncExec(new Runnable() {
+
+ public void run() {
+ handleElementChanged(ResourceSetInfo.this, resource, null);
+ }
+ });
+ return true;
+ }
+
+ /**
+ * @generated
+ */
+ public boolean handleResourceDeleted(Resource resource) {
+ synchronized(ResourceSetInfo.this) {
+ if(ResourceSetInfo.this.fCanBeSaved) {
+ ResourceSetInfo.this.setUnSynchronized(resource);
+ return true;
+ }
+ }
+ Display.getDefault().asyncExec(new Runnable() {
+
+ public void run() {
+ fireElementDeleted(ResourceSetInfo.this.getEditorInput());
+ }
+ });
+ return true;
+ }
+
+ /**
+ * @generated
+ */
+ public boolean handleResourceMoved(Resource resource, final URI newURI) {
+ synchronized(ResourceSetInfo.this) {
+ if(ResourceSetInfo.this.fCanBeSaved) {
+ ResourceSetInfo.this.setUnSynchronized(resource);
+ return true;
+ }
+ }
+ if(myDocument.getDiagram().eResource() == resource) {
+ Display.getDefault().asyncExec(new Runnable() {
+
+ public void run() {
+ handleElementMoved(ResourceSetInfo.this.getEditorInput(), newURI);
+ }
+ });
+ } else {
+ handleResourceDeleted(resource);
+ }
+ return true;
+ }
+
+ }
+
+ }
+
+ /**
+ * @generated
+ */
+ private class ResourceSetModificationListener extends EContentAdapter {
+
+ /**
+ * @generated
+ */
+ private NotificationFilter myModifiedFilter;
+
+ /**
+ * @generated
+ */
+ private ResourceSetInfo myInfo;
+
+ /**
+ * @generated
+ */
+ public ResourceSetModificationListener(ResourceSetInfo info) {
+ myInfo = info;
+ myModifiedFilter = NotificationFilter.createEventTypeFilter(Notification.SET).or(
+ NotificationFilter.createEventTypeFilter(Notification.UNSET)).and(
+ NotificationFilter.createFeatureFilter(Resource.class, Resource.RESOURCE__IS_MODIFIED));
+ }
+
+ /**
+ * @generated
+ */
+ public void notifyChanged(Notification notification) {
+ if(notification.getNotifier() instanceof ResourceSet) {
+ super.notifyChanged(notification);
+ }
+ if(!notification.isTouch() && myModifiedFilter.matches(notification)) {
+ if(notification.getNotifier() instanceof Resource) {
+ Resource resource = (Resource)notification.getNotifier();
+ if(resource.isLoaded()) {
+ boolean modified = false;
+ for(Iterator it = myInfo.getResourceSet().getResources().iterator(); it.hasNext() && !modified;) {
+ Resource nextResource = (Resource)it.next();
+ if(nextResource.isLoaded()) {
+ modified = nextResource.isModified();
+ }
+ }
+ boolean dirtyStateChanged = false;
+ synchronized(myInfo) {
+ if(modified != myInfo.fCanBeSaved) {
+ myInfo.fCanBeSaved = modified;
+ dirtyStateChanged = true;
+ }
+ if(!resource.isModified()) {
+ myInfo.setSynchronized(resource);
+ }
+ }
+ if(dirtyStateChanged) {
+ fireElementDirtyStateChanged(myInfo.getEditorInput(), modified);
+
+ if(!modified) {
+ myInfo.setModificationStamp(computeModificationStamp(myInfo));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Return the editingDomain
+ */
+ public EditingDomain getEditingDomain() {
+ if(sharedEditingDomain == null) {
+ createEditingDomain();
+ }
+ return sharedEditingDomain;
+ }
+
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.adaptor.gmf/src/org/eclipse/papyrus/infra/core/adaptor/gmf/Messages.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.adaptor.gmf/src/org/eclipse/papyrus/infra/core/adaptor/gmf/Messages.java
new file mode 100644
index 00000000000..c3a6797ccf9
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.adaptor.gmf/src/org/eclipse/papyrus/infra/core/adaptor/gmf/Messages.java
@@ -0,0 +1,80 @@
+/*****************************************************************************
+ * Copyright (c) 2008 CEA LIST.
+ *
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Cedric Dumoulin Cedric.dumoulin@lifl.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.infra.core.adaptor.gmf;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * @generated
+ */
+public class Messages extends NLS {
+
+ /**
+ * @generated
+ */
+ static {
+ NLS.initializeMessages("messages", Messages.class); //$NON-NLS-1$
+ }
+
+ /**
+ * @generated
+ */
+ private Messages() {
+ }
+
+ public static String MultiPagesEditorActionBarContributor_PapyrusMenu;
+
+ public static String AbstractPapyrusGmfCreateDiagramCommandHandler_CreateDiagramCommandLabel;
+
+ public static String AbstractPapyrusGmfCreateDiagramCommandHandler_NewDiagramName;
+
+ public static String AbstractPapyrusGmfCreateDiagramCommandHandler_NotSupportedEditor;
+
+ public static String AbstractPapyrusGmfCreateDiagramCommandHandler_SelectNewDiagramName;
+
+ public static String AbstractPapyrusGmfCreateDiagramCommandHandler_UnableCreateModelAndDiagram;
+
+ public static String GmfEditorFactory_ErrorCreatingEditorPart;
+
+ public static String GmfEditorFactory_ErrorRetrievingDiagram;
+
+ public static String GmfMultiDiagramDocumentProvider_isModifiable;
+
+ public static String GmfMultiDiagramDocumentProvider_handleElementContentChanged;
+
+ public static String GmfMultiDiagramDocumentProvider_IncorrectInputError;
+
+ public static String GmfMultiDiagramDocumentProvider_NoDiagramInResourceError;
+
+ public static String GmfMultiDiagramDocumentProvider_DiagramLoadingError;
+
+ public static String GmfMultiDiagramDocumentProvider_UnsynchronizedFileSaveError;
+
+ public static String GmfMultiDiagramDocumentProvider_SaveDiagramTask;
+
+ public static String GmfMultiDiagramDocumentProvider_SaveNextResourceTask;
+
+ public static String GmfMultiDiagramDocumentProvider_SaveAsOperation;
+
+ public static String ModelManagerEditor_SavingDeletedFile;
+
+ public static String ModelManagerEditor_SaveAsErrorTitle;
+
+ public static String ModelManagerEditor_SaveAsErrorMessage;
+
+ public static String ModelManagerEditor_SaveErrorTitle;
+
+ public static String ModelManagerEditor_SaveErrorMessage;
+
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.adaptor.gmf/src/org/eclipse/papyrus/infra/core/adaptor/gmf/ModelManagerEditor.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.adaptor.gmf/src/org/eclipse/papyrus/infra/core/adaptor/gmf/ModelManagerEditor.java
new file mode 100644
index 00000000000..f1e898f02ae
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.adaptor.gmf/src/org/eclipse/papyrus/infra/core/adaptor/gmf/ModelManagerEditor.java
@@ -0,0 +1,594 @@
+/*****************************************************************************
+ * Copyright (c) 2008 CEA LIST.
+ *
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Cedric Dumoulin Cedric.dumoulin@lifl.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.infra.core.adaptor.gmf;
+
+import java.beans.PropertyChangeSupport;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.ILog;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.emf.common.notify.Adapter;
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.common.notify.Notifier;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.diagram.ui.resources.editor.document.DiagramDocument;
+import org.eclipse.gmf.runtime.diagram.ui.resources.editor.document.IDiagramDocument;
+import org.eclipse.gmf.runtime.diagram.ui.resources.editor.document.IDocument;
+import org.eclipse.gmf.runtime.diagram.ui.resources.editor.document.IDocumentProvider;
+import org.eclipse.gmf.runtime.diagram.ui.resources.editor.document.MEditingDomainElement;
+import org.eclipse.gmf.runtime.diagram.ui.resources.editor.internal.l10n.EditorMessages;
+import org.eclipse.gmf.runtime.notation.Diagram;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.window.Window;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorMatchingStrategy;
+import org.eclipse.ui.IEditorReference;
+import org.eclipse.ui.IEditorRegistry;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.SaveAsDialog;
+import org.eclipse.ui.part.FileEditorInput;
+import org.osgi.framework.Bundle;
+
+/**
+ * This class is used as an model manager for regular GMF Editor. All editor capabilities are
+ * neutralize, except the model load and save capabilities.
+ *
+ * @author dumoulin
+ *
+ */
+public class ModelManagerEditor {
+
+ public static final String DIAGRAM_ADDED = "DIAGRAM_ADDED"; //$NON-NLS-1$
+
+ public static final String DIAGRAM_MOVED = "DIAGRAM_MOVED"; //$NON-NLS-1$
+
+ public static final String DIAGRAM_REMOVED = "DIAGRAM_REMOVED"; //$NON-NLS-1$
+
+ /**
+ * The underlying document provider.
+ */
+ protected IDocumentProvider documentProvider;
+
+ /**
+ * EditorInput provided when the editor is created.
+ */
+ protected IEditorInput editorInput;
+
+ protected IEditorSite site;
+
+ /**
+ * Listener on diagram added/removed.
+ */
+ private PropertyChangeSupport diagramListListener = new PropertyChangeSupport(this);
+
+ /**
+ * Adapter listening to diagram addition/remove events
+ */
+ private Adapter adapter = new Adapter() {
+
+ Notifier notifier;
+
+ public Notifier getTarget() {
+ return notifier;
+ }
+
+ public boolean isAdapterForType(Object type) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /**
+ * Notifies that a change to some feature has occurred.
+ *
+ * @param notification
+ * a description of the change.
+ */
+ public void notifyChanged(Notification notification) {
+ // System.out.println("notifyChanged("+ notification +")");
+ // System.out.println("getEventType=" + notification.getEventType() );
+ // System.out.println("getFeature=" + notification.getFeature() );
+ // System.out.println("getNotifier=" + notification.getNotifier() );
+
+ int eventType = notification.getEventType();
+ if(eventType == Notification.ADD) {
+ Object newValue = notification.getNewValue();
+ if(newValue instanceof Diagram)
+ diagramListListener.firePropertyChange(DIAGRAM_ADDED, null, newValue);
+ } else if(eventType == Notification.MOVE) {
+ Object newValue = notification.getNewValue();
+ if(newValue instanceof Diagram)
+ diagramListListener.firePropertyChange(DIAGRAM_MOVED, null, newValue);
+
+ } else if(eventType == Notification.REMOVE) {
+ Object newValue = notification.getNewValue();
+ if(newValue == null)
+ Activator.log.debug(getClass().getName() + "- Warning: can't get removed object."); //$NON-NLS-1$
+
+ if(newValue instanceof Diagram)
+ diagramListListener.firePropertyChange(DIAGRAM_REMOVED, null, newValue);
+ }
+ }
+
+ public void setTarget(Notifier newTarget) {
+ notifier = newTarget;
+
+ }
+
+ };
+
+ /**
+ * @param hasFlyoutPalette
+ */
+ public ModelManagerEditor(IDocumentProvider documentProvider) {
+ this.documentProvider = documentProvider;
+ }
+
+ public IDocumentProvider getDocumentProvider() {
+ return documentProvider;
+ }
+
+ /**
+ *
+ */
+ public TransactionalEditingDomain getEditingDomain() {
+ IDocument document = getEditorInput() != null ? getDocumentProvider().getDocument(getEditorInput()) : null;
+ if(document instanceof IDiagramDocument) {
+ return ((IDiagramDocument)document).getEditingDomain();
+ }
+ return getEditorInput() instanceof MEditingDomainElement ? ((MEditingDomainElement)getEditorInput())
+ .getEditingDomain() : null;
+ }
+
+ /**
+ * @cdm
+ */
+ public void setInput(IEditorInput input) {
+ Activator.log.debug(this + ".setInput(IEditorInput input)"); //$NON-NLS-1$
+ }
+
+ /**
+ *
+ * @param site
+ * @param input
+ * @throws PartInitException
+ */
+ public void init(IEditorSite site, IEditorInput input) throws PartInitException {
+ // System.out.println(this + ".init(IEditorSite site, IEditorInput input)");
+ this.editorInput = input;
+ this.site = site;
+ try {
+ getDocumentProvider().connect(input);
+ } catch (CoreException x) {
+ // code from DiagramDocumentEditor.setInput(IEditorInput)
+ String title = EditorMessages.Editor_error_setinput_title;
+ String msg = EditorMessages.Editor_error_setinput_message;
+ Shell shell = site.getShell();
+ ErrorDialog.openError(shell, title, msg, x.getStatus());
+ }
+ }
+
+ /**
+ * Returns diagram list listener. This listener send event whenever a diagram is added or
+ * removed to the eResource.
+ *
+ * @return the listener
+ */
+ public PropertyChangeSupport getDiagramListListener() {
+ return diagramListListener;
+ }
+
+ /**
+ * Called when the editor should be activated. Subclass should implements this method to
+ * register listeners to the model.
+ *
+ */
+ public void activate() {
+ getNotationModelEResource().eAdapters().add(adapter);
+
+ }
+
+ /**
+ * Called when the editor is deactivated.
+ *
+ */
+ public void deactivate() {
+ getNotationModelEResource().eAdapters().remove(adapter);
+ }
+
+ private Resource getNotationModelEResource() {
+ // Get the default diagram document
+ DiagramDocument document = (DiagramDocument)getDocumentProvider().getDocument(getEditorInput());
+ Diagram diagram = document.getDiagram();
+
+ return diagram.eResource();
+ }
+
+ /**
+ * Get the resource for notation model.
+ *
+ * @return
+ */
+ public Resource getNotationResource() {
+ return getNotationModelEResource();
+ }
+
+ /**
+ * Get the resource for the domain model.
+ *
+ * @return
+ */
+ public Resource getDomainResource() {
+ // Get the default diagram document
+ DiagramDocument document = (DiagramDocument)getDocumentProvider().getDocument(getEditorInput());
+ Diagram diagram = document.getDiagram();
+
+ EObject rootObject = diagram.getElement();
+ return rootObject.eResource();
+ }
+
+ /**
+ * @return the editorInput
+ */
+ public IEditorInput getEditorInput() {
+ return editorInput;
+ }
+
+ /**
+ * The AbstractDiagramEditor
implementation of this IEditorPart
method
+ * may be extended by subclasses.
+ *
+ * @param progressMonitor
+ * the progress monitor for communicating result state or null
+ */
+ public void doSave(IProgressMonitor progressMonitor) {
+
+ IDocumentProvider p = getDocumentProvider();
+ if(p == null)
+ return;
+
+ if(p.isDeleted(getEditorInput())) {
+
+ if(isSaveAsAllowed()) {
+
+ /*
+ * 1GEUSSR: ITPUI:ALL - User should never loose changes made in the editors. Changed
+ * Behavior to make sure that if called inside a regular save (because of deletion
+ * of input element) there is a way to report back to the caller.
+ */
+ performSaveAs(progressMonitor);
+
+ } else {
+
+ Shell shell = getSite().getShell();
+ String title = EditorMessages.Editor_error_save_deleted_title;
+ String msg = EditorMessages.Editor_error_save_deleted_message;
+ MessageDialog.openError(shell, title, msg);
+ }
+
+ } else {
+ updateState(getEditorInput());
+ validateState(getEditorInput());
+ performSave(false, progressMonitor);
+ }
+ }
+
+ /**
+ * Updates the state of the given editor input such as read-only flag.
+ *
+ * @param input
+ * the input to be validated
+ *
+ */
+ protected void updateState(IEditorInput input) {
+ IDocumentProvider provider = getDocumentProvider();
+ try {
+
+ provider.updateStateCache(input);
+
+ // if (getDiagramEditPart() != null) {
+ // if(isEditable())
+ // getDiagramEditPart().enableEditMode();
+ // else
+ // getDiagramEditPart().disableEditMode();
+ // }
+
+ } catch (CoreException x) {
+ Bundle bundle = Platform.getBundle(PlatformUI.PLUGIN_ID);
+ ILog log = Platform.getLog(bundle);
+ log.log(x.getStatus());
+ }
+ }
+
+ /**
+ * Validates the state of the given editor input. The predominate intent of this method is to
+ * take any action probably necessary to ensure that the input can persistently be changed.
+ *
+ * @param input
+ * the input to be validated
+ *
+ */
+ protected void validateState(IEditorInput input) {
+
+ IDocumentProvider provider = getDocumentProvider();
+
+ try {
+
+ provider.validateState(input, getSite().getShell());
+
+ } catch (CoreException x) {
+ IStatus status = x.getStatus();
+ if(status == null || status.getSeverity() != IStatus.CANCEL) {
+ Bundle bundle = Platform.getBundle(PlatformUI.PLUGIN_ID);
+ ILog log = Platform.getLog(bundle);
+ log.log(x.getStatus());
+
+ Shell shell = getSite().getShell();
+ String title = EditorMessages.Editor_error_validateEdit_title;
+ String msg = EditorMessages.Editor_error_validateEdit_message;
+ ErrorDialog.openError(shell, title, msg, x.getStatus());
+ }
+ return;
+ }
+
+ // if (getDiagramEditPart() != null) {
+ // if(isEditable())
+ // getDiagramEditPart().enableEditMode();
+ // else
+ // getDiagramEditPart().disableEditMode();
+ // }
+
+ }
+
+ /**
+ * @generated
+ */
+ public boolean isSaveAsAllowed() {
+ return true;
+ }
+
+ /**
+ * @generated
+ */
+ public void doSaveAs() {
+ performSaveAs(new NullProgressMonitor());
+ }
+
+ /**
+ * Performs the save and handles errors appropriately.
+ *
+ * @param overwrite
+ * indicates whether or not overwriting is allowed
+ * @param progressMonitor
+ * the monitor in which to run the operation
+ *
+ */
+ protected void performSave(boolean overwrite, IProgressMonitor progressMonitor) {
+
+ IDocumentProvider provider = getDocumentProvider();
+ if(provider == null)
+ return;
+
+ try {
+
+ provider.aboutToChange(getEditorInput());
+ IEditorInput input = getEditorInput();
+ provider.saveDocument(progressMonitor, input, getDocumentProvider().getDocument(input), overwrite);
+ // editorSaved();
+
+ } catch (CoreException x) {
+ IStatus status = x.getStatus();
+ if(status == null || status.getSeverity() != IStatus.CANCEL)
+ handleExceptionOnSave(x, progressMonitor);
+ } finally {
+ provider.changed(getEditorInput());
+ }
+ }
+
+ /**
+ * @generated
+ */
+ protected void performSaveAs(IProgressMonitor progressMonitor) {
+ Shell shell = getSite().getShell();
+ IEditorInput input = getEditorInput();
+ SaveAsDialog dialog = new SaveAsDialog(shell);
+ IFile original = input instanceof IFileEditorInput ? ((IFileEditorInput)input).getFile() : null;
+ if(original != null) {
+ dialog.setOriginalFile(original);
+ }
+ dialog.create();
+ IDocumentProvider provider = getDocumentProvider();
+ if(provider == null) {
+ // editor has been programmatically closed while the dialog was open
+ return;
+ }
+ if(provider.isDeleted(input) && original != null) {
+ String message = NLS.bind(Messages.ModelManagerEditor_SavingDeletedFile, original.getName());
+ dialog.setErrorMessage(null);
+ dialog.setMessage(message, IMessageProvider.WARNING);
+ }
+ if(dialog.open() == Window.CANCEL) {
+ if(progressMonitor != null) {
+ progressMonitor.setCanceled(true);
+ }
+ return;
+ }
+ IPath filePath = dialog.getResult();
+ if(filePath == null) {
+ if(progressMonitor != null) {
+ progressMonitor.setCanceled(true);
+ }
+ return;
+ }
+ IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+ IFile file = workspaceRoot.getFile(filePath);
+ final IEditorInput newInput = new FileEditorInput(file);
+ // Check if the editor is already open
+ IEditorMatchingStrategy matchingStrategy = getEditorDescriptor().getEditorMatchingStrategy();
+ IEditorReference[] editorRefs = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
+ .getEditorReferences();
+ for(int i = 0; i < editorRefs.length; i++) {
+ if(matchingStrategy.matches(editorRefs[i], newInput)) {
+ MessageDialog.openWarning(shell, Messages.ModelManagerEditor_SaveAsErrorTitle,
+ Messages.ModelManagerEditor_SaveAsErrorMessage);
+ return;
+ }
+ }
+ boolean success = false;
+ try {
+ provider.aboutToChange(newInput);
+ // getDocumentProvider(newInput).saveDocument(progressMonitor, newInput,
+ // getDocumentProvider().getDocument(getEditorInput()), true);
+ getDocumentProvider().saveDocument(progressMonitor, newInput,
+ getDocumentProvider().getDocument(getEditorInput()), true);
+ success = true;
+ } catch (CoreException x) {
+ IStatus status = x.getStatus();
+ if(status == null || status.getSeverity() != IStatus.CANCEL) {
+ ErrorDialog.openError(shell, Messages.ModelManagerEditor_SaveErrorTitle,
+ Messages.ModelManagerEditor_SaveErrorMessage, x.getStatus());
+ }
+ } finally {
+ provider.changed(newInput);
+ if(success) {
+ setInput(newInput);
+ }
+ }
+ if(progressMonitor != null) {
+ progressMonitor.setCanceled(!success);
+ }
+ }
+
+ /**
+ * Retrieves the descriptor for this editor
+ *
+ * @return the editor descriptor
+ */
+ final protected IEditorDescriptor getEditorDescriptor() {
+ IEditorRegistry editorRegistry = PlatformUI.getWorkbench().getEditorRegistry();
+ IEditorDescriptor editorDesc = editorRegistry.findEditor(getSite().getId());
+ return editorDesc;
+ }
+
+ /**
+ * The number of re-entrances into error correction code while saving.
+ *
+ */
+ private int fErrorCorrectionOnSave;
+
+ /**
+ * Handles the given exception. If the exception reports an out-of-sync situation, this is
+ * reported to the user. Otherwise, the exception is generically reported.
+ *
+ * @param exception
+ * the exception to handle
+ * @param progressMonitor
+ * the progress monitor
+ */
+ protected void handleExceptionOnSave(CoreException exception, IProgressMonitor progressMonitor) {
+
+ try {
+ ++fErrorCorrectionOnSave;
+
+ Shell shell = getSite().getShell();
+
+ boolean isSynchronized = false;
+ IDocumentProvider p = getDocumentProvider();
+
+ isSynchronized = p.isSynchronized(getEditorInput());
+
+ if(isNotSynchronizedException(exception) && fErrorCorrectionOnSave == 1 && !isSynchronized) {
+ String title = EditorMessages.Editor_error_save_outofsync_title;
+ String msg = EditorMessages.Editor_error_save_outofsync_message;
+
+ if(MessageDialog.openQuestion(shell, title, msg))
+ performSave(true, progressMonitor);
+ else {
+ /*
+ * 1GEUPKR: ITPJUI:ALL - Loosing work with simultaneous edits Set progress
+ * monitor to canceled in order to report back to enclosing operations.
+ */
+ if(progressMonitor != null)
+ progressMonitor.setCanceled(true);
+ }
+ } else {
+ String title = EditorMessages.Editor_error_save_title;
+ String msg = EditorMessages.Editor_error_save_message;
+ ErrorDialog.openError(shell, title, msg, exception.getStatus());
+
+ /*
+ * 1GEUPKR: ITPJUI:ALL - Loosing work with simultaneous edits Set progress monitor
+ * to canceled in order to report back to enclosing operations.
+ */
+ if(progressMonitor != null)
+ progressMonitor.setCanceled(true);
+ }
+ } finally {
+ --fErrorCorrectionOnSave;
+ }
+ }
+
+ /**
+ * Tells whether the given core exception is exactly the exception which is thrown for a
+ * non-synchronized element.
+ *
+ * XXX: After 3.1 this method must be delegated to the document provider see
+ *
+ *
+ * @param ex
+ * the core exception
+ * @return true
iff the given core exception is exactly the exception which is
+ * thrown for a non-synchronized element
+ *
+ */
+ private boolean isNotSynchronizedException(CoreException ex) {
+ if(ex == null)
+ return false;
+
+ IStatus status = ex.getStatus();
+ if(status == null || status instanceof MultiStatus)
+ return false;
+
+ if(status.getException() != null)
+ return false;
+
+ // Can't access IResourceStatus.OUT_OF_SYNC_LOCAL, using value: 274
+ return status.getCode() == 274;
+ }
+
+ /**
+ * @return the site
+ */
+ public IEditorSite getSite() {
+ return site;
+ }
+
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.adaptor.gmf/src/org/eclipse/papyrus/infra/core/adaptor/gmf/SemanticFromGMFElement.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.adaptor.gmf/src/org/eclipse/papyrus/infra/core/adaptor/gmf/SemanticFromGMFElement.java
new file mode 100644
index 00000000000..d1b1fc795f3
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.adaptor.gmf/src/org/eclipse/papyrus/infra/core/adaptor/gmf/SemanticFromGMFElement.java
@@ -0,0 +1,44 @@
+/*****************************************************************************
+ * Copyright (c) 2010 CEA LIST.
+ *
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Patrick Tessier (CEA LIST) Patrick.tessier@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.infra.core.adaptor.gmf;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
+import org.eclipse.papyrus.infra.core.IElementWithSemantic;
+
+/**
+ * this class is used to obtain the semantic element for element of a gmf diagram
+ *
+ */
+public class SemanticFromGMFElement implements IElementWithSemantic {
+ /**
+ *
+ * @see org.eclipse.papyrus.infra.core.IElementWithSemantic#getSemanticElement(java.lang.Object)
+ *
+ * @param wrapper can be for examplean editpart of gmf
+ * @return the semantic element linked to this or null element
+ */
+ public Object getSemanticElement(Object wrapper) {
+ if(wrapper instanceof IGraphicalEditPart){
+ return ((IGraphicalEditPart)wrapper).resolveSemanticElement();
+ }
+ if( wrapper instanceof IAdaptable){
+ return ((IAdaptable)wrapper).getAdapter(EObject.class);
+ }
+ return null;
+ }
+
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.adaptor.gmf/src/org/eclipse/papyrus/infra/core/adaptor/gmf/SynchronizableGmfDiagramEditor.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.adaptor.gmf/src/org/eclipse/papyrus/infra/core/adaptor/gmf/SynchronizableGmfDiagramEditor.java
new file mode 100644
index 00000000000..4b553193a58
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.adaptor.gmf/src/org/eclipse/papyrus/infra/core/adaptor/gmf/SynchronizableGmfDiagramEditor.java
@@ -0,0 +1,101 @@
+/*****************************************************************************
+ * Copyright (c) 2010 CEA LIST.
+ *
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Patrick Tessier (CEA LIST) Patrick.tessier@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.infra.core.adaptor.gmf;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.emf.workspace.impl.WorkspaceCommandStackImpl;
+import org.eclipse.gef.DefaultEditDomain;
+import org.eclipse.gef.GraphicalViewer;
+import org.eclipse.gef.commands.CommandStack;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.editparts.IPrimaryEditPart;
+import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditDomain;
+import org.eclipse.gmf.runtime.diagram.ui.resources.editor.parts.DiagramDocumentEditor;
+import org.eclipse.papyrus.commands.CheckedDiagramCommandStack;
+import org.eclipse.papyrus.infra.core.ui.IRevealSemanticElement;
+
+/**
+ /**
+ *
+ * This GMF editor contains a methods in order to reveal visual element from a list of semantic element.
+ *
+ */
+
+public class SynchronizableGmfDiagramEditor extends DiagramDocumentEditor implements IRevealSemanticElement {
+
+ public SynchronizableGmfDiagramEditor(boolean hasFlyoutPalette) {
+ super(hasFlyoutPalette);
+ }
+
+
+ /**
+ * reveal all editpart that represent an element in the given list.
+ * @see org.eclipse.papyrus.infra.core.ui.IRevealSemanticElement#revealSemanticElement(java.util.List)
+ *
+ */
+ public void revealSemanticElement(List> elementList) {
+ //create an instance that can get semantic element from gmf
+ SemanticFromGMFElement semanticFromGMFElement= new SemanticFromGMFElement();
+
+ // get the graphical viewer
+ GraphicalViewer graphicalViewer =getGraphicalViewer() ;
+ if( graphicalViewer!=null){
+
+ //look for among all edit part if the semantic is contained in the list
+ Iterator> iter=graphicalViewer.getEditPartRegistry().values().iterator();
+ IGraphicalEditPart researchedEditPart=null;
+ while(iter.hasNext()&& researchedEditPart==null) {
+ Object currentEditPart = (Object)iter.next();
+ //look for only among IPrimary editpart to avoid compartment and labels of links
+ if(currentEditPart instanceof IPrimaryEditPart){
+ if(elementList.contains(semanticFromGMFElement.getSemanticElement(currentEditPart))){
+ researchedEditPart=((IGraphicalEditPart)currentEditPart);}
+ }
+
+ }
+ //an editpart has been found so put selection on it.
+ if(researchedEditPart!=null){
+ graphicalViewer.select(researchedEditPart);
+ }
+ }
+ }
+
+ /**
+ * Configures my diagram edit domain with its command stack.
+ * This method has been completely overridden in order to use a proxy stack.
+ */
+ @Override
+ protected void configureDiagramEditDomain() {
+
+ DefaultEditDomain editDomain = getEditDomain();
+
+ if(editDomain != null) {
+ CommandStack stack = editDomain.getCommandStack();
+ if(stack != null) {
+ // dispose the old stack
+ stack.dispose();
+ }
+
+ // create and assign the new stack
+ CheckedDiagramCommandStack diagramStack = new CheckedDiagramCommandStack(getDiagramEditDomain());
+
+ editDomain.setCommandStack(diagramStack);
+ }
+
+ DiagramEditDomain diagEditDomain = (DiagramEditDomain)getDiagramEditDomain();
+ diagEditDomain.setActionManager(createActionManager());
+ }
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.adaptor.gmf/src/org/eclipse/papyrus/infra/core/adaptor/gmf/UMLDiagramEditorUtil.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.adaptor.gmf/src/org/eclipse/papyrus/infra/core/adaptor/gmf/UMLDiagramEditorUtil.java
new file mode 100644
index 00000000000..29d549ca7a6
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.adaptor.gmf/src/org/eclipse/papyrus/infra/core/adaptor/gmf/UMLDiagramEditorUtil.java
@@ -0,0 +1,37 @@
+/*****************************************************************************
+ * Copyright (c) 2008 CEA LIST.
+ *
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Cedric Dumoulin Cedric.dumoulin@lifl.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.infra.core.adaptor.gmf;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.xmi.XMLResource;
+
+/**
+ * @generated
+ */
+public class UMLDiagramEditorUtil {
+
+ /**
+ * @generated
+ */
+ public static Map getSaveOptions() {
+ Map saveOptions = new HashMap();
+ saveOptions.put(XMLResource.OPTION_ENCODING, "UTF-8"); //$NON-NLS-1$
+ saveOptions.put(Resource.OPTION_SAVE_ONLY_IF_CHANGED, Resource.OPTION_SAVE_ONLY_IF_CHANGED_MEMORY_BUFFER);
+ return saveOptions;
+ }
+
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.log/META-INF/MANIFEST.MF b/plugins/infra/core/org.eclipse.papyrus.infra.core.log/META-INF/MANIFEST.MF
index f4dc9b1fa38..35ff14081d5 100644
--- a/plugins/infra/core/org.eclipse.papyrus.infra.core.log/META-INF/MANIFEST.MF
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.log/META-INF/MANIFEST.MF
@@ -1,12 +1,12 @@
Manifest-Version: 1.0
-Export-Package: org.eclipse.papyrus.log
+Export-Package: org.eclipse.papyrus.infra.core.log
Require-Bundle: org.eclipse.core.runtime
Bundle-Vendor: %providerName
Bundle-ActivationPolicy: lazy
Bundle-Version: 0.9.0.qualifier
Bundle-Localization: plugin
Bundle-Name: %pluginName
-Bundle-Activator: org.eclipse.papyrus.log.internal.Activator
+Bundle-Activator: org.eclipse.papyrus.infra.core.log.internal.Activator
Bundle-ManifestVersion: 2
Bundle-SymbolicName: org.eclipse.papyrus.infra.core.log
Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.log/src/org/eclipse/papyrus/infra/core/log/LogHelper.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.log/src/org/eclipse/papyrus/infra/core/log/LogHelper.java
new file mode 100644
index 00000000000..33a5ae706b0
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.log/src/org/eclipse/papyrus/infra/core/log/LogHelper.java
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Atos Origin.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Atos Origin - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.papyrus.infra.core.log;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.logging.Logger;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+
+/**
+ * A Log Helper.
+ *
+ * @author tszadel
+ *
+ */
+public class LogHelper {
+
+ /** The plugin Id. */
+ private String pluginId;
+
+ /** The plugin related to that helper. */
+ private Plugin activator;
+
+
+
+ /**
+ * Default Constructor.
+ * The associated plugin can be set later.
+ * If no plugin is set, use java log.
+ */
+ public LogHelper() {
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param activator
+ * The activator.
+ */
+ public LogHelper(Plugin activator) {
+ setPlugin(activator);
+ }
+
+ /**
+ * Set the associated plugin.
+ * This plugin log will be used as log.
+ * @param activator
+ */
+ public void setPlugin( Plugin activator ) {
+ this.pluginId = activator.getBundle().getSymbolicName();
+ this.activator = activator;
+ }
+
+ /**
+ * Log an informative message into the Eclipse log file
+ *
+ * @param message
+ * the message to log
+ */
+ public void info(String message) {
+ log(message, IStatus.INFO);
+ }
+
+ /**
+ * Log a debug message into the Eclipse log file
+ *
+ * @param message
+ * the message to log
+ */
+ public void debug(String message) {
+ if(isDebugEnabled()) {
+ log("[DEBUG] " + message, IStatus.INFO);
+ }
+ }
+
+ /**
+ * Test if the platform is in debug mode.
+ *
+ * @return True if the platform is in debug mode.
+ */
+ public boolean isDebugEnabled() {
+ if( activator != null)
+ return Platform.inDebugMode();
+
+ return false;
+ }
+
+ /**
+ * Log a message with given level into the Eclipse log file
+ *
+ * @param message
+ * the message to log
+ * @param level
+ * the message priority
+ */
+ private void log(String message, int level) {
+ log( new Status(level, pluginId, message ));
+ }
+
+ /**
+ *
+ * @param status
+ */
+ private void log( IStatus status ) {
+
+ if( activator == null) {
+ // TODO Do log with java ?
+ }
+ else {
+ activator.getLog().log(status );
+ }
+ }
+
+ /**
+ * Log a warning message.
+ *
+ * @param e
+ * the exception to log
+ */
+ public void warn(String message) {
+ log(message, IStatus.WARNING);
+ }
+
+
+ /**
+ * Log an exception into the Eclipse log file
+ *
+ * @param e
+ * the exception to log
+ */
+ public void error(Throwable e) {
+ error("Unexpected Error", e);
+ }
+
+ /**
+ * Log an exception into the Eclipse log file
+ *
+ * @param message
+ * the message
+ * @param e
+ * the exception to log
+ */
+ public void error(String message, Throwable e) {
+
+ Throwable t = e;
+ if(e instanceof InvocationTargetException) {
+ t = ((InvocationTargetException)e).getTargetException();
+ }
+
+ IStatus status;
+ if(t instanceof CoreException) {
+ status = ((CoreException)t).getStatus();
+ } else {
+ status = new Status(IStatus.ERROR, pluginId, message, e);
+ }
+
+ log(status);
+ }
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.log/src/org/eclipse/papyrus/infra/core/log/internal/Activator.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.log/src/org/eclipse/papyrus/infra/core/log/internal/Activator.java
new file mode 100644
index 00000000000..384c6029c5e
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.log/src/org/eclipse/papyrus/infra/core/log/internal/Activator.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Atos Origin.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Atos Origin - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.papyrus.infra.core.log.internal;
+
+import org.eclipse.core.runtime.Plugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends Plugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.eclipse.papyrus.infra.log";
+
+ // The shared instance
+ private static Activator plugin;
+
+ /**
+ * The constructor
+ */
+ public Activator() {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.Plugins#start(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.log/src/org/eclipse/papyrus/log/LogHelper.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.log/src/org/eclipse/papyrus/log/LogHelper.java
deleted file mode 100644
index 5db8c6fc71a..00000000000
--- a/plugins/infra/core/org.eclipse.papyrus.infra.core.log/src/org/eclipse/papyrus/log/LogHelper.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009 Atos Origin.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Atos Origin - initial API and implementation
- *******************************************************************************/
-package org.eclipse.papyrus.log;
-
-import java.lang.reflect.InvocationTargetException;
-import java.util.logging.Logger;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Platform;
-import org.eclipse.core.runtime.Plugin;
-import org.eclipse.core.runtime.Status;
-
-/**
- * A Log Helper.
- *
- * @author tszadel
- *
- */
-public class LogHelper {
-
- /** The plugin Id. */
- private String pluginId;
-
- /** The plugin related to that helper. */
- private Plugin activator;
-
-
-
- /**
- * Default Constructor.
- * The associated plugin can be set later.
- * If no plugin is set, use java log.
- */
- public LogHelper() {
- }
-
- /**
- * Constructor.
- *
- * @param activator
- * The activator.
- */
- public LogHelper(Plugin activator) {
- setPlugin(activator);
- }
-
- /**
- * Set the associated plugin.
- * This plugin log will be used as log.
- * @param activator
- */
- public void setPlugin( Plugin activator ) {
- this.pluginId = activator.getBundle().getSymbolicName();
- this.activator = activator;
- }
-
- /**
- * Log an informative message into the Eclipse log file
- *
- * @param message
- * the message to log
- */
- public void info(String message) {
- log(message, IStatus.INFO);
- }
-
- /**
- * Log a debug message into the Eclipse log file
- *
- * @param message
- * the message to log
- */
- public void debug(String message) {
- if(isDebugEnabled()) {
- log("[DEBUG] " + message, IStatus.INFO);
- }
- }
-
- /**
- * Test if the platform is in debug mode.
- *
- * @return True if the platform is in debug mode.
- */
- public boolean isDebugEnabled() {
- if( activator != null)
- return Platform.inDebugMode();
-
- return false;
- }
-
- /**
- * Log a message with given level into the Eclipse log file
- *
- * @param message
- * the message to log
- * @param level
- * the message priority
- */
- private void log(String message, int level) {
- log( new Status(level, pluginId, message ));
- }
-
- /**
- *
- * @param status
- */
- private void log( IStatus status ) {
-
- if( activator == null) {
- // TODO Do log with java ?
- }
- else {
- activator.getLog().log(status );
- }
- }
-
- /**
- * Log a warning message.
- *
- * @param e
- * the exception to log
- */
- public void warn(String message) {
- log(message, IStatus.WARNING);
- }
-
-
- /**
- * Log an exception into the Eclipse log file
- *
- * @param e
- * the exception to log
- */
- public void error(Throwable e) {
- error("Unexpected Error", e);
- }
-
- /**
- * Log an exception into the Eclipse log file
- *
- * @param message
- * the message
- * @param e
- * the exception to log
- */
- public void error(String message, Throwable e) {
-
- Throwable t = e;
- if(e instanceof InvocationTargetException) {
- t = ((InvocationTargetException)e).getTargetException();
- }
-
- IStatus status;
- if(t instanceof CoreException) {
- status = ((CoreException)t).getStatus();
- } else {
- status = new Status(IStatus.ERROR, pluginId, message, e);
- }
-
- log(status);
- }
-}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.log/src/org/eclipse/papyrus/log/internal/Activator.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.log/src/org/eclipse/papyrus/log/internal/Activator.java
deleted file mode 100644
index e40f9fbc22d..00000000000
--- a/plugins/infra/core/org.eclipse.papyrus.infra.core.log/src/org/eclipse/papyrus/log/internal/Activator.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009 Atos Origin.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Atos Origin - initial API and implementation
- *******************************************************************************/
-package org.eclipse.papyrus.log.internal;
-
-import org.eclipse.core.runtime.Plugin;
-import org.osgi.framework.BundleContext;
-
-/**
- * The activator class controls the plug-in life cycle
- */
-public class Activator extends Plugin {
-
- // The plug-in ID
- public static final String PLUGIN_ID = "org.eclipse.papyrus.infra.log";
-
- // The shared instance
- private static Activator plugin;
-
- /**
- * The constructor
- */
- public Activator() {
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.core.runtime.Plugins#start(org.osgi.framework.BundleContext)
- */
- @Override
- public void start(BundleContext context) throws Exception {
- super.start(context);
- plugin = this;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)
- */
- @Override
- public void stop(BundleContext context) throws Exception {
- plugin = null;
- super.stop(context);
- }
-
- /**
- * Returns the shared instance
- *
- * @return the shared instance
- */
- public static Activator getDefault() {
- return plugin;
- }
-
-}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/.project b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/.project
index ebd7fbdba7e..46189987209 100644
--- a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/.project
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/.project
@@ -1,6 +1,6 @@
- org.eclipse.papyrus.infra.sasheditor.di
+ org.eclipse.papyrus.infra.core.sasheditor.di
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/META-INF/MANIFEST.MF b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/META-INF/MANIFEST.MF
index be0aa23f171..1fd48589df7 100644
--- a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/META-INF/MANIFEST.MF
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/META-INF/MANIFEST.MF
@@ -1,19 +1,19 @@
Manifest-Version: 1.0
Require-Bundle: org.eclipse.swt;bundle-version="3.5.0";visibility:=reexport,
- org.eclipse.papyrus.infra.sasheditor;bundle-version="0.9.0";visibility:=reexport,
+ org.eclipse.papyrus.infra.core.sasheditor;bundle-version="0.9.0";visibility:=reexport,
org.eclipse.ui;bundle-version="3.6.0",
org.eclipse.core.runtime;bundle-version="3.6.0",
org.eclipse.emf.ecore;visibility:=reexport,
org.eclipse.emf.ecore.xmi;bundle-version="2.5.0",
org.eclipse.emf.transaction;bundle-version="1.4.0",
org.eclipse.gmf.runtime.notation;bundle-version="1.5.0"
-Export-Package: org.eclipse.papyrus.sasheditor.contentprovider.di,
- org.eclipse.papyrus.sasheditor.contentprovider.di.commands,
- org.eclipse.papyrus.sasheditor.contentprovider.di.utils,
- org.eclipse.papyrus.sashwindows.di,
- org.eclipse.papyrus.sashwindows.di.exception,
- org.eclipse.papyrus.sashwindows.di.impl,
- org.eclipse.papyrus.sashwindows.di.util
+Export-Package: org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider,
+ org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.commands,
+ org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.utils,
+ org.eclipse.papyrus.infra.core.sashwindows.di,
+ org.eclipse.papyrus.infra.core.sashwindows.di.exception,
+ org.eclipse.papyrus.infra.core.sashwindows.di.impl,
+ org.eclipse.papyrus.infra.core.sashwindows.di.util
Bundle-Vendor: %providerName
Bundle-ActivationPolicy: lazy
Bundle-ClassPath: .
@@ -21,6 +21,6 @@ Bundle-Version: 0.9.0.qualifier
Bundle-Localization: plugin
Bundle-Name: %pluginName
Bundle-ManifestVersion: 2
-Bundle-SymbolicName: org.eclipse.papyrus.infra.sasheditor.di;singleton:=true
+Bundle-SymbolicName: org.eclipse.papyrus.infra.core.sasheditor.di;singleton:=true
Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/antBuild.xml b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/antBuild.xml
index 35ad5315f91..e332a1d501d 100644
--- a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/antBuild.xml
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/antBuild.xml
@@ -4,7 +4,7 @@
-
+
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/DiSashModelMngr.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/DiSashModelMngr.java
new file mode 100644
index 00000000000..cc22d3b7b16
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/DiSashModelMngr.java
@@ -0,0 +1,235 @@
+/*****************************************************************************
+ * Copyright (c) 2009 CEA LIST & LIFL
+ *
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Cedric Dumoulin Cedric.dumoulin@lifl.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider;
+
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IContentChangedProvider;
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageMngr;
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ISashWindowsContentProvider;
+import org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.internal.ContentChangedEventProvider;
+import org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.internal.DiContentProvider;
+import org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.internal.PageMngrImpl;
+import org.eclipse.papyrus.infra.core.sashwindows.di.SashWindowsMngr;
+import org.eclipse.papyrus.infra.core.sashwindows.di.util.DiUtils;
+
+/**
+ * Class used as main entry point to access a sash model build on EMF / di
+ *
+ * @author cedric dumoulin
+ */
+public class DiSashModelMngr {
+
+ /** The EMF model used to store the sash windows structure and pages */
+ protected SashWindowsMngr sashWindowMngr;
+
+ /**
+ * Instance of the pageMngr.
+ */
+ private PageMngrImpl pageMngr = null;
+
+ /**
+ * Instance of the DiContentProvider used to manipulate SashModel.
+ */
+ private DiContentProvider contentProvider;
+
+ /**
+ * Object used externally listen to model changes. The object is also used
+ * internally to control how events are fired (limit multiple events).
+ */
+ protected ContentChangedEventProvider contentChangedEventProvider;
+
+ /** The factory used to create IPageModel */
+ private IPageModelFactory pageModelFactory;
+
+ /**
+ * Constructor. Create a DiSashModelMngr with the specified factory. A
+ * SashModel is created but not attached to a resource. This constructor is
+ * for subclasses. The subclasses should initialize the sashWindowMngr
+ *
+ * @param pageModelFactory
+ * @param createDefaultSashModel
+ * If true, create the default SashModel by calling {@link #createDefaultSashModel()}
+ */
+ protected DiSashModelMngr(IPageModelFactory pageModelFactory, boolean createDefaultSashModel) {
+ this.pageModelFactory = pageModelFactory;
+ // Create a SashModel
+ if(createDefaultSashModel) {
+ sashWindowMngr = createDefaultSashModel();
+ }
+ }
+
+ /**
+ * Constructor. Create a DiSashModelMngr with the specified factory. A
+ * SashModel is created but not attached to a resource.
+ *
+ * @param pageModelFactory
+ */
+ public DiSashModelMngr(IPageModelFactory pageModelFactory) {
+ this.pageModelFactory = pageModelFactory;
+ // Create a SashModel
+ sashWindowMngr = createDefaultSashModel();
+ }
+
+ /**
+ * Constructor. Create a DiSashModelMngr with the specified factory. The
+ * SashModel is searched in the Resource. If not found, create one in the
+ * resource.
+ *
+ * @param pageModelFactory
+ * @param diResource
+ */
+ public DiSashModelMngr(IPageModelFactory pageModelFactory, Resource diResource) {
+ this.pageModelFactory = pageModelFactory;
+
+ // lookup the SashModel
+ sashWindowMngr = lookupSashWindowMngr(diResource);
+ if(sashWindowMngr == null) {
+ // Create a default model and attach it to resource.
+ sashWindowMngr = createDefaultSashModel();
+ diResource.getContents().add(sashWindowMngr);
+ }
+ }
+
+ /**
+ * Constructor. Create a DiSashModelMngr with the specified factory and
+ * sashModel.
+ *
+ * @param pageModelFactory
+ * @param sashModel
+ */
+ public DiSashModelMngr(IPageModelFactory pageModelFactory, SashWindowsMngr sashModel) {
+ this.pageModelFactory = pageModelFactory;
+ this.sashWindowMngr = sashModel;
+ }
+
+ /**
+ * Get the internal EMF implementation. Intended to be used by tests.
+ *
+ * @return the sashWindowMngr
+ */
+ protected SashWindowsMngr getDiSashWindowsMngr() {
+ return sashWindowMngr;
+ }
+
+ /**
+ * Return the internal implementation of ContentProvider. Create if if
+ * needed. This method should not be subclassed
+ *
+ * @return the contentProvider
+ */
+ protected final DiContentProvider getDiContentProvider() {
+ if(contentProvider == null) {
+ contentProvider = new DiContentProvider(sashWindowMngr.getSashModel(), pageModelFactory, getContentChangedEventProvider());
+ }
+ return contentProvider;
+ }
+
+ /**
+ * Return the internal implementation of PageMngr. Create if if needed. This
+ * method should not be subclassed
+ *
+ * @return the PageMngrImpl
+ */
+ protected final PageMngrImpl getPageMngrImpl() {
+ if(pageMngr == null) {
+ pageMngr = new PageMngrImpl(sashWindowMngr, getContentChangedEventProvider());
+ }
+
+ return pageMngr;
+ }
+
+ /**
+ * Return the internal implementation of ContentChangedEventProvider. Create
+ * if if needed. This method should not be subclassed
+ *
+ * @return the PageMngrImpl
+ */
+ protected final ContentChangedEventProvider getContentChangedEventProvider() {
+ if(contentChangedEventProvider == null) {
+ contentChangedEventProvider = new ContentChangedEventProvider(sashWindowMngr);
+ }
+
+ return contentChangedEventProvider;
+ }
+
+ /**
+ * Get the IPageMngr providing basic methods to manage Pages in the sash
+ * model.
+ *
+ * @return
+ */
+ public IPageMngr getIPageMngr() {
+ return getPageMngrImpl();
+ }
+
+ /**
+ * Get the ContentProvider used by the SashWindows system. This class can
+ * also be used to accurately manage the sash model.
+ *
+ * @return
+ */
+ public ISashWindowsContentProvider getISashWindowsContentProvider() {
+
+ return getDiContentProvider();
+
+ }
+
+ /**
+ * Get the ContentChangedProvider for the SashModel
+ *
+ * @return
+ */
+ public IContentChangedProvider getSashModelContentChangedProvider() {
+ return getContentChangedEventProvider();
+ }
+
+ /**
+ * Create a default model with one window and one folder.
+ *
+ * @param diResource
+ * @return
+ */
+ protected SashWindowsMngr createDefaultSashModel() {
+ return DiUtils.createDefaultSashWindowsMngr();
+ }
+
+ /**
+ * Lookup for the SashModel object in the resource
+ *
+ * @param diResource
+ * @return
+ */
+ protected SashWindowsMngr lookupSashWindowMngr(Resource diResource) {
+
+ return DiUtils.lookupSashWindowsMngr(diResource);
+ }
+
+ /**
+ * Create an instance of IPageMngr acting on the provided resource. This
+ * instance is suitable to add, remove, close or open diagrams.
+ *
+ * @param diResource
+ * @return The non transactional version of the IPageMngr
+ */
+ public static IPageMngr createIPageMngr(Resource diResource) {
+
+ // Create an instance of the DiSashModelMngr with no factory.
+ // The factory is not needed since we don't get the
+ // ISashWindowsContentProvider.
+ return new DiSashModelMngr(null, diResource).getIPageMngr();
+
+ }
+
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/IPageModelFactory.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/IPageModelFactory.java
new file mode 100644
index 00000000000..0359df0d9e5
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/IPageModelFactory.java
@@ -0,0 +1,40 @@
+/*****************************************************************************
+ * Copyright (c) 2009 CEA LIST & LIFL
+ *
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Cedric Dumoulin Cedric.dumoulin@lifl.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageMngr;
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageModel;
+
+/**
+ * Factory used to create IPageModel from an object identifying a page.
+ * IPageModel are objects used by the Sash Windows to create a page.
+ *
+ * @author cedric dumoulin
+ */
+public interface IPageModelFactory {
+
+ /**
+ * Create the IPageModel for the pageIdentifier. The pageIdentifier is the
+ * object passed to the {@link IPageMngr#addEditor(EObject)}. This factory
+ * method is called by the Sash Windows whenever it needs to create a page.
+ * The identifier is found in the sash model.
+ *
+ * @param pageIdentifier
+ * The identifier identifying the page to create.
+ * @return
+ */
+ public IPageModel createIPageModel(Object pageIdentifier);
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/TransactionalDiSashModelMngr.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/TransactionalDiSashModelMngr.java
new file mode 100644
index 00000000000..87888ff0681
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/TransactionalDiSashModelMngr.java
@@ -0,0 +1,132 @@
+/**
+ *
+ */
+package org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider;
+
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.transaction.RecordingCommand;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageMngr;
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ISashWindowsContentProvider;
+import org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.internal.TransactionalDiContentProvider;
+import org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.internal.TransactionalPageMngrImpl;
+
+/**
+ * DiSashModelMngr providing transactional commands to modify SashModel.
+ *
+ * @author cedric dumoulin
+ *
+ */
+public class TransactionalDiSashModelMngr extends DiSashModelMngr {
+
+ private TransactionalDiContentProvider transDiContentProvider;
+
+ private TransactionalPageMngrImpl transPageMngrImpl;
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param pageModelFactory
+ * @param diResource
+ */
+ public TransactionalDiSashModelMngr(IPageModelFactory pageModelFactory, final Resource diResource, TransactionalEditingDomain editingDomain) {
+ super(pageModelFactory, false);
+
+ // lookup the SashModel
+ sashWindowMngr = lookupSashWindowMngr(diResource);
+ // If no SashWindow structure is found, create a new one using a
+ // transaction.
+ if(sashWindowMngr == null) {
+ RecordingCommand command = new RecordingCommand(editingDomain) {
+
+ @Override
+ protected void doExecute() {
+ // Create a default model and attach it to resource.
+ sashWindowMngr = createDefaultSashModel();
+ diResource.getContents().add(sashWindowMngr);
+ }
+ };
+ editingDomain.getCommandStack().execute(command);
+ }
+
+ // Create the TransactionalDiContentProvider
+ transDiContentProvider = new TransactionalDiContentProvider(getDiContentProvider(), editingDomain);
+
+ // Create the TransactionalPageMngrImpl
+ transPageMngrImpl = new TransactionalPageMngrImpl(getPageMngrImpl(), editingDomain);
+ }
+
+ /**
+ *
+ * Constructor. Only create a {@link IPageMngr} impl. Do not create the
+ * DiContentProvider as there is no factory provided. Internal use.
+ *
+ * @param pageModelFactory
+ * @param diResource
+ */
+ private TransactionalDiSashModelMngr(final Resource diResource, TransactionalEditingDomain editingDomain) {
+ super(null, false);
+
+ // lookup the SashModel
+ sashWindowMngr = lookupSashWindowMngr(diResource);
+ // If no SashWindow structure is found, create a new one using a
+ // transaction.
+ if(sashWindowMngr == null) {
+ RecordingCommand command = new RecordingCommand(editingDomain) {
+
+ @Override
+ protected void doExecute() {
+ // Create a default model and attach it to resource.
+ sashWindowMngr = createDefaultSashModel();
+ diResource.getContents().add(sashWindowMngr);
+ }
+ };
+ editingDomain.getCommandStack().execute(command);
+ }
+
+ // Create the TransactionalPageMngrImpl
+ transPageMngrImpl = new TransactionalPageMngrImpl(getPageMngrImpl(), editingDomain);
+ }
+
+ /**
+ * Return the transactional version
+ *
+ * @see org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.DiSashModelMngr#getISashWindowsContentProvider()
+ * @return
+ *
+ */
+ @Override
+ public ISashWindowsContentProvider getISashWindowsContentProvider() {
+ return transDiContentProvider;
+ }
+
+ /**
+ * Return the transactional version
+ *
+ * @see org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.DiSashModelMngr#getIPageMngr()
+ *
+ * @return
+ */
+ @Override
+ public IPageMngr getIPageMngr() {
+ return transPageMngrImpl;
+ }
+
+ /**
+ * Create an instance of IPageMngr acting on the provided resource. This
+ * instance is suitable to add, remove, close or open diagrams.
+ *
+ * @param diResource
+ * @return The non transactional version of the IPageMngr
+ */
+ public static IPageMngr createIPageMngr(Resource diResource, TransactionalEditingDomain editingDomain) {
+
+ // Create an instance of the DiSashModelMngr with no factory.
+ // The factory is not needed since we don't get the
+ // ISashWindowsContentProvider.
+ return new TransactionalDiSashModelMngr(diResource, editingDomain).getIPageMngr();
+
+ }
+
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/commands/CloseAllDiagramsCommand.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/commands/CloseAllDiagramsCommand.java
new file mode 100644
index 00000000000..997ff32487c
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/commands/CloseAllDiagramsCommand.java
@@ -0,0 +1,77 @@
+/**
+ *
+ */
+package org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.commands;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageMngr;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * A command to be used with the Eclipse Commands Framework. This command allows
+ * to close all diagrams openened in the current SashContainer implemented on
+ * di.
+ *
+ * @author cedric dumoulin
+ *
+ */
+public class CloseAllDiagramsCommand extends AbstractHandler {
+
+ /**
+ * Check if the Command is enabled.
+ */
+ @Override
+ public void setEnabled(Object evaluationContext) {
+ // System.out.println("call to CloseAllDiagramsCommand.setEnable(" +
+ // evaluationContext + ")");
+ }
+
+ /**
+ * Execute the command. This method is called when the action is triggered.
+ *
+ */
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ IPageMngr pageMngr;
+ try {
+ pageMngr = getPageMngr(event);
+ } catch (NullPointerException e) {
+ // PageMngr can't be found
+ return null;
+ }
+ execute(pageMngr);
+
+ return null;
+ }
+
+ /**
+ * Get the PageMngr used to interact with the content provider.
+ *
+ * @param event
+ * @return
+ * @throws NullPointerException
+ * if the PageMngr can't be found.
+ */
+ private IPageMngr getPageMngr(ExecutionEvent event) {
+
+ IEditorPart part = HandlerUtil.getActiveEditor(event);
+ IPageMngr pageMngr = (IPageMngr)part.getAdapter(IPageMngr.class);
+
+ return pageMngr;
+
+ }
+
+ /**
+ * Close all the diagrams.
+ *
+ * @param pageMngr
+ */
+ public void execute(IPageMngr pageMngr) {
+
+ pageMngr.closeAllOpenedPages();
+ }
+
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/commands/CloseDiagramCommand.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/commands/CloseDiagramCommand.java
new file mode 100644
index 00000000000..16d9ea06138
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/commands/CloseDiagramCommand.java
@@ -0,0 +1,72 @@
+/**
+ *
+ */
+package org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.commands;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageMngr;
+import org.eclipse.papyrus.infra.core.sasheditor.editor.ISashWindowsContainer;
+import org.eclipse.papyrus.infra.core.sashwindows.di.PageRef;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * A command to be used with the Eclipse Commands Framework. This command is to
+ * be used with {@link SashWindowsContainer} implemented with the Di model. This
+ * command allows to close the currently openened diagram.
+ *
+ * @author cedric dumoulin
+ *
+ */
+public class CloseDiagramCommand extends AbstractHandler {
+
+ /**
+ * Check if the Command is enabled.
+ */
+ @Override
+ public void setEnabled(Object evaluationContext) {
+ // System.out.println("call to CloseDiagramCommand.setEnable(" +
+ // evaluationContext + ")");
+ }
+
+ /**
+ * Execute the command. This method is called when the action is triggered.
+ *
+ */
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ try {
+ IEditorPart part = HandlerUtil.getActiveEditor(event);
+ IPageMngr pageMngr = (IPageMngr)part.getAdapter(IPageMngr.class);
+ ISashWindowsContainer container = (ISashWindowsContainer)part.getAdapter(ISashWindowsContainer.class);
+ Object pageIdentifier = container.getActiveSashWindowsPage().getRawModel();
+ // Bug from sash Di to be corrected
+ if(pageIdentifier instanceof PageRef) {
+ pageIdentifier = ((PageRef)pageIdentifier).getPageIdentifier();
+ }
+
+ execute(pageMngr, pageIdentifier);
+
+ } catch (NullPointerException e) {
+ // PageMngr can't be found
+ return null;
+ }
+
+ return null;
+ }
+
+ /**
+ * Close selected page.
+ *
+ * @param pageMngr
+ */
+ public void execute(IPageMngr pageMngr, Object pageIdentifier) {
+
+ if(pageMngr.isOpen(pageIdentifier)) {
+ pageMngr.closePage(pageIdentifier);
+ }
+ }
+
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/commands/CloseOtherDiagramsCommand.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/commands/CloseOtherDiagramsCommand.java
new file mode 100644
index 00000000000..f0030935646
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/commands/CloseOtherDiagramsCommand.java
@@ -0,0 +1,70 @@
+/**
+ *
+ */
+package org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.commands;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageMngr;
+import org.eclipse.papyrus.infra.core.sasheditor.editor.ISashWindowsContainer;
+import org.eclipse.papyrus.infra.core.sashwindows.di.PageRef;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * A command to be used with the Eclipse Commands Framework. This command is to
+ * be used with {@link SashWindowsContainer} implemented with the Di model. This
+ * command allows to close all diagrams in the folder, except the currently
+ * openened one.
+ *
+ * @author cedric dumoulin
+ *
+ */
+public class CloseOtherDiagramsCommand extends AbstractHandler {
+
+ /**
+ * Check if the Command is enabled.
+ */
+ @Override
+ public void setEnabled(Object evaluationContext) {
+ // System.out.println("call to CloseDiagramCommand.setEnable(" +
+ // evaluationContext + ")");
+ }
+
+ /**
+ * Execute the command. This method is called when the action is triggered.
+ *
+ */
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+
+ try {
+ IEditorPart part = HandlerUtil.getActiveEditor(event);
+ IPageMngr pageMngr = (IPageMngr)part.getAdapter(IPageMngr.class);
+ ISashWindowsContainer container = (ISashWindowsContainer)part.getAdapter(ISashWindowsContainer.class);
+ Object pageIdentifier = container.getActiveSashWindowsPage().getRawModel();
+ // Bug from sash Di to be corrected
+ if(pageIdentifier instanceof PageRef) {
+ pageIdentifier = ((PageRef)pageIdentifier).getPageIdentifier();
+ }
+ execute(pageMngr, pageIdentifier);
+
+ } catch (NullPointerException e) {
+ // PageMngr can't be found
+ return null;
+ }
+
+ return null;
+ }
+
+ /**
+ * Close selected page.
+ *
+ * @param pageMngr
+ */
+ public void execute(IPageMngr pageMngr, Object pageIdentifier) {
+
+ pageMngr.closeOtherPages(pageIdentifier);
+ }
+
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/internal/ContentChangedEventProvider.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/internal/ContentChangedEventProvider.java
new file mode 100644
index 00000000000..4fd2f8b2e05
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/internal/ContentChangedEventProvider.java
@@ -0,0 +1,198 @@
+/**
+ *
+ */
+package org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.ecore.util.EContentAdapter;
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IContentChangedListener;
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IContentChangedProvider;
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IContentChangedListener.ContentEvent;
+import org.eclipse.papyrus.infra.core.sashwindows.di.AbstractPanel;
+import org.eclipse.papyrus.infra.core.sashwindows.di.PageRef;
+import org.eclipse.papyrus.infra.core.sashwindows.di.SashModel;
+import org.eclipse.papyrus.infra.core.sashwindows.di.SashWindowsMngr;
+import org.eclipse.papyrus.infra.core.sashwindows.di.Window;
+
+/**
+ * A class listening on changes on the internal model and delivering events to
+ * registered listeners.
+ *
+ * @author cedric dumoulin
+ *
+ */
+public class ContentChangedEventProvider implements IContentChangedProvider {
+
+ private List listeners;
+
+ /** Is this mngr delivering events ? */
+ private boolean isDeliverEnable = true;
+
+ /** Last event stored when isDeliverEnable == false; */
+ private ContentEvent storedEvent;
+
+ private EMFAdapter emfAdapter = new EMFAdapter();
+
+ /**
+ * The model firing events
+ */
+ private SashModel diSashModel;
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param diSashModel
+ */
+ public ContentChangedEventProvider(SashModel diSashModel) {
+ this.diSashModel = diSashModel;
+ activate();
+ }
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param diSashModel
+ */
+ public ContentChangedEventProvider(SashWindowsMngr sashWindowMngr) {
+ this(sashWindowMngr.getSashModel());
+ }
+
+ /**
+ * Connect EMF changeListener to the {@link ContentChangeListenerManager}.
+ * Changes in the EMF di model will be fired by the
+ * ContentChangeListenerManager.
+ */
+ protected void activate() {
+ diSashModel.eAdapters().add(emfAdapter);
+ setDeliver(true);
+ }
+
+ protected void deactivate() {
+ setDeliver(false);
+ diSashModel.eAdapters().remove(emfAdapter);
+ }
+
+ /**
+ * @return the isDeliverEnable
+ */
+ protected boolean isDeliver() {
+ return isDeliverEnable;
+ }
+
+ /**
+ * @param isDeliverEnable
+ * the isDeliverEnable to set
+ */
+ protected void setDeliver(boolean isDeliverEnable) {
+
+ if(this.isDeliverEnable == isDeliverEnable)
+ return;
+
+ // Check if the old value is not delivering event
+ if(!this.isDeliverEnable) {
+ this.isDeliverEnable = true;
+ // reenable events. Check if an event is stored
+ if(storedEvent != null)
+ fireContentChanged(storedEvent);
+
+ } else
+ this.isDeliverEnable = isDeliverEnable;
+
+ storedEvent = null;
+ }
+
+ /**
+ * Add a listener listening on content changed. This listener will be
+ * notified each time the content change.
+ *
+ * @param listener
+ */
+ public void addListener(IContentChangedListener listener) {
+ if(listeners == null)
+ createListeners();
+
+ // Check if already exists.
+ if(listeners.contains(listener))
+ return;
+
+ listeners.add(listener);
+ }
+
+ /**
+ * Add a listener listening on content changed. This listener will be
+ * notified each time the content change.
+ *
+ * @param listener
+ */
+ public void removeListener(IContentChangedListener listener) {
+ if(listeners == null)
+ return;
+
+ listeners.remove(listener);
+ }
+
+ /**
+ * Create the list of listeners.
+ */
+ private void createListeners() {
+ if(listeners == null)
+ listeners = new ArrayList();
+
+ }
+
+ /**
+ * Fire the changed event.
+ *
+ * @param event
+ */
+ protected void fireContentChanged(ContentEvent event) {
+ if(listeners == null)
+ return;
+
+ if(!isDeliverEnable) {
+ storedEvent = event;
+ return;
+ }
+
+ for(IContentChangedListener listener : listeners) {
+ listener.contentChanged(event);
+ }
+ }
+
+ /**
+ * Change event Adapter. Forward EMF changeEvent to the {@link ContentChangeListenerManager}.
+ *
+ * @author cedric dumoulin
+ */
+ public class EMFAdapter extends EContentAdapter {
+
+ /**
+ * ContentProvider Model has changed. Changes includes : ADD, REMOVE and
+ * MOVE of elements
+ *
+ * @see org.eclipse.emf.common.notify.impl.AdapterImpl#notifyChanged(org.eclipse.emf.common.notify.Notification)
+ *
+ * @param msg
+ */
+ @Override
+ public void notifyChanged(Notification msg) {
+ super.notifyChanged(msg);
+
+ // Filter out notification of type RESOLVE
+ // We don't need to be noti
+ if(msg.getEventType() == Notification.RESOLVE)
+ return;
+
+ // W
+ Object sender = msg.getNotifier();
+ if(sender instanceof AbstractPanel || sender instanceof Window || sender instanceof PageRef)
+ fireContentChanged(new ContentEvent(msg.getEventType(), sender, null));
+ }
+ }
+
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/internal/DiContentProvider.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/internal/DiContentProvider.java
new file mode 100644
index 00000000000..894faa2455f
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/internal/DiContentProvider.java
@@ -0,0 +1,288 @@
+/*****************************************************************************
+ * Copyright (c) 2009 CEA LIST & LIFL
+ *
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Cedric Dumoulin Cedric.dumoulin@lifl.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.internal;
+
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IAbstractPanelModel;
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ISashWindowsContentProvider;
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ITabFolderModel;
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IContentChangedListener.ContentEvent;
+import org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.IPageModelFactory;
+import org.eclipse.papyrus.infra.core.sashwindows.di.DiFactory;
+import org.eclipse.papyrus.infra.core.sashwindows.di.SashModel;
+import org.eclipse.papyrus.infra.core.sashwindows.di.SashPanel;
+import org.eclipse.papyrus.infra.core.sashwindows.di.TabFolder;
+
+/**
+ * EMF implementation of the {@link ISashWindowsContentProvider}.
+ *
+ * @author dumoulin
+ */
+public class DiContentProvider implements ISashWindowsContentProvider {
+
+ /** Internal EMF model */
+ private SashModel diSashModel;
+
+ /** Factory used to create SWT Editor or Component from Page Identifiers. */
+ private IPageModelFactory pageModelFactory;
+
+ /**
+ * Object delivering event to listeners. Used to control how the events are
+ * triggered
+ */
+ private ContentChangedEventProvider contentChangedEventProvider;
+
+ /**
+ * Create a ContentProvider
+ *
+ * @param diSashModel
+ * @param pageModelFactory
+ * The factory that will be used when a page will be created.
+ * @throws IllegalArgumentException
+ * If the factory is null.
+ */
+ public DiContentProvider(SashModel diSashModel, IPageModelFactory pageModelFactory) throws IllegalArgumentException {
+
+ this(diSashModel, pageModelFactory, new ContentChangedEventProvider(diSashModel));
+ }
+
+ /**
+ * Create a ContentProvider
+ *
+ * @param diSashModel
+ * @param pageModelFactory
+ * The factory that will be used when a page will be created.
+ * @throws IllegalArgumentException
+ * If the factory is null.
+ */
+ public DiContentProvider(SashModel diSashModel, IPageModelFactory pageModelFactory, ContentChangedEventProvider contentChangedEventProvider) throws IllegalArgumentException {
+
+ if(pageModelFactory == null)
+ throw new IllegalArgumentException("A IPageModelFactory should be provided.");
+
+ this.diSashModel = diSashModel;
+ this.pageModelFactory = pageModelFactory;
+ this.contentChangedEventProvider = contentChangedEventProvider;
+ }
+
+ /**
+ * Access to internal structure for tests. This method is not intended to be
+ * used for other purpose.
+ *
+ * @return the diSashModel
+ */
+ protected SashModel getDiSashModel() {
+ return diSashModel;
+ }
+
+ /**
+ * @return the contentChangedEventProvider
+ */
+ protected ContentChangedEventProvider getContentChangedEventProvider() {
+ return contentChangedEventProvider;
+ }
+
+ /**
+ * Add a page identifier to the SashModel. This page identifier will be
+ * added as "child" of the current TabFolder.
+ *
+ * @param pageIdentifier
+ */
+ public void addPage(Object pageIdentifier) {
+ diSashModel.addPage(pageIdentifier);
+ }
+
+ /**
+ * Add a page to the current folder. Create the Page (Editor or Component)
+ * with the help of the factory.
+ *
+ * @see org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ISashWindowsContentProvider#addPage(int,
+ * org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageModel)
+ *
+ * @param index
+ * @param tabItem
+ */
+ public void addPage(Object page, int index) {
+
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * @see org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ISashWindowsContentProvider#createFolder(org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ITabFolderModel,
+ * int, org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ITabFolderModel, int)
+ *
+ * @param tabFolder
+ * @param tabIndex
+ * @param targetFolder
+ * @param side
+ * @return
+ */
+ public void createFolder(ITabFolderModel tabFolder, int tabIndex, ITabFolderModel targetFolder, int side) {
+
+ // disable fired events
+ contentChangedEventProvider.setDeliver(false);
+ // Create new folder. Parent will be set when inserted.
+ TabFolder newFolder = DiFactory.eINSTANCE.createTabFolder();
+
+ TabFolder refFolder = ((TabFolderModel)targetFolder).getTabFolder();
+ TabFolder pageSrcFolder = ((TabFolderModel)tabFolder).getTabFolder();
+
+ // Insert folder
+ diSashModel.insertFolder(newFolder, refFolder, side);
+ // Move tab from folder to folder
+ diSashModel.movePage(pageSrcFolder, tabIndex, newFolder);
+ // Remove unused folder if necessary
+ diSashModel.removeEmptyFolder(pageSrcFolder);
+ diSashModel.setCurrentSelection(newFolder);
+
+ // Reenable events, and fire the last one
+ contentChangedEventProvider.setDeliver(true);
+
+ }
+
+ /**
+ * Set the current folder.
+ *
+ * @see org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ISashWindowsContentProvider#setCurrentFolder(java.lang.Object)
+ *
+ * @param rawModel
+ * The object identifying the folder.
+ */
+ public void setCurrentFolder(Object rawModel) {
+
+ if(!(rawModel instanceof TabFolder)) {
+ return;
+ }
+ diSashModel.setCurrentSelection((TabFolder)rawModel);
+ }
+
+ /**
+ * Get the node used as root of the SashWindows. For now, this is the first
+ * window.
+ *
+ * @see org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ISashWindowsContentProvider#getRootModel()
+ *
+ * @return
+ */
+ public Object getRootModel() {
+ // Get the first window.
+ return diSashModel.getWindows().get(0).getPanel();
+ }
+
+ /**
+ * Create the IPanelModel for the rootModel returned by {@link DiContentProvider#getRootModel()}.
+ *
+ * @see org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ISashWindowsContentProvider#createChildSashModel(java.lang.Object)
+ *
+ * @param root
+ * @return
+ */
+ public IAbstractPanelModel createChildSashModel(Object root) {
+
+ if(root instanceof SashPanel)
+ return new SashPanelModel((SashPanel)root, pageModelFactory);
+ else if(root instanceof TabFolder)
+ return new TabFolderModel((TabFolder)root, pageModelFactory);
+ else
+ throw new IllegalArgumentException("Can't create IPanelModel from raw model '" + root + "'.");
+ }
+
+ /**
+ * @see org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ISashWindowsContentProvider#movePage(org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ITabFolderModel,
+ * int, int)
+ *
+ * @param folderModel
+ * @param oldIndex
+ * @param newIndex
+ */
+ public void movePage(ITabFolderModel folderModel, int oldIndex, int newIndex) {
+ TabFolder folder = ((TabFolderModel)folderModel).getTabFolder();
+
+ contentChangedEventProvider.setDeliver(false);
+ folder.movePage(oldIndex, newIndex);
+ diSashModel.setCurrentSelection(folder);
+ contentChangedEventProvider.setDeliver(true);
+ }
+
+ /**
+ * @see org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ISashWindowsContentProvider#movePage(org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ITabFolderModel,
+ * int, org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ITabFolderModel, int)
+ *
+ * @param srcFolderModel
+ * @param sourceIndex
+ * @param targetFolderModel
+ * @param targetIndex
+ */
+ public void movePage(ITabFolderModel srcFolderModel, int sourceIndex, ITabFolderModel targetFolderModel, int targetIndex) {
+
+ TabFolder srcFolder = ((TabFolderModel)srcFolderModel).getTabFolder();
+ TabFolder targetFolder = ((TabFolderModel)targetFolderModel).getTabFolder();
+
+ contentChangedEventProvider.setDeliver(false);
+ diSashModel.movePage(srcFolder, sourceIndex, targetFolder, targetIndex);
+ diSashModel.removeEmptyFolder(srcFolder);
+ diSashModel.setCurrentSelection(targetFolder);
+ contentChangedEventProvider.setDeliver(true);
+
+ }
+
+ /**
+ * Remove specified page from the current folder.
+ *
+ * @see org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ISashWindowsContentProvider#removePage(int)
+ *
+ * @param index
+ */
+ public void removePage(int index) {
+ diSashModel.removePage(index);
+
+ }
+
+ /**
+ * @see org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ISashWindowsContentProvider#removePage(org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageModel)
+ *
+ * @param tabItem
+ */
+ public void removePage(Object page) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+
+ }
+
+ /**
+ * @see org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ISashWindowsContentProvider#removePage(org.eclipse.papyrus.infra.core.sasheditor.contentprovider.ITabFolderModel,
+ * int)
+ *
+ * @param parentFolder
+ * @param tabIndex
+ */
+ public void removePage(ITabFolderModel parentFolder, int tabIndex) {
+ TabFolder folder = ((TabFolderModel)parentFolder).getTabFolder();
+
+ contentChangedEventProvider.setDeliver(false);
+ folder.removePage(tabIndex);
+ diSashModel.removeEmptyFolder(folder);
+ contentChangedEventProvider.setDeliver(true);
+ }
+
+ /**
+ * Add a listener listening on content changed. This listener will be
+ * notified each time the content change.
+ *
+ * @param listener
+ */
+ protected void firePropertyChanged(ContentEvent event) {
+ contentChangedEventProvider.fireContentChanged(event);
+ }
+
+}
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/internal/PageMngrImpl.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/internal/PageMngrImpl.java
new file mode 100644
index 00000000000..23d568c6922
--- /dev/null
+++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor.di/custom-src/org/eclipse/papyrus/infra/core/sasheditor/di/contentprovider/internal/PageMngrImpl.java
@@ -0,0 +1,373 @@
+/*****************************************************************************
+ * Copyright (c) 2009 CEA LIST & LIFL
+ *
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Cedric Dumoulin Cedric.dumoulin@lifl.fr - Initial API and implementation
+ * Anass Radouani (Atos) - add history management
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.infra.core.sasheditor.di.contentprovider.internal;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Stack;
+
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageMngr;
+import org.eclipse.papyrus.infra.core.sasheditor.editor.IPage;
+import org.eclipse.papyrus.infra.core.sashwindows.di.PageRef;
+import org.eclipse.papyrus.infra.core.sashwindows.di.SashWindowsMngr;
+import org.eclipse.ui.ISelectionService;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Implementation of the page manager. The page manager provides basic methods
+ * to access the DiSashModel and its PageList. This is the users interface to
+ * add, open, close and remove pages.
+ *
+ * @author cedric dumoulin
+ */
+public class PageMngrImpl implements IPageMngr {
+
+ /** Internal EMF model */
+ private SashWindowsMngr diSashModel;
+
+ /** Contains the current page and previously opened pages */
+ private Stack