/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.ui.editors; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IEditorReference; import org.eclipse.ui.IWorkbenchPage; import org.teiid.designer.ui.UiPlugin; import org.teiid.designer.ui.common.util.UiUtil; /** * ModelEditorProjectListener is an implementation of IResourceChangeListener that is responsible for * closing un-initialized editors that are otherwise left open when a Project is closed or deleted. * I have no idea why Eclipse does not handle this for us, but it doesn't. Eclipse also does not make * this easy - uninitialized editor tabs are difficult to close or even find out what resource they * are placeholders for. I have a nagging feeling that there must be a better way to do this, but I * haven't found it. * * @since 8.0 */ public class ModelEditorProjectListener implements IResourceChangeListener { /* (non-Javadoc) * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent) */ @Override public void resourceChanged(final IResourceChangeEvent event) { // It appears that the event is not guarenteed to be NON-NULL, so we need to add the check if( event != null ) { int type = event.getType(); if ( type == IResourceChangeEvent.PRE_CLOSE || type == IResourceChangeEvent.PRE_DELETE ) { UiUtil.runInSwtThread(new Runnable() { @Override public void run() { handleResourceChanged(event); } }, false); } } } private void handleResourceChanged(IResourceChangeEvent event) { final IWorkbenchPage page = UiPlugin.getDefault().getCurrentWorkbenchWindow().getActivePage(); // NPE today when exiting using the new VDB Explorer View. Closing the view is ending up firing an event if( UiPlugin.getDefault() == null || UiPlugin.getDefault().getCurrentWorkbenchWindow() == null || page == null ) return; // PRE_CLOSE and PRE_DELETE are fired when a project is about to close or be deleted. // The resource is always a Project, and the event.getDelta() will return null, so it's useless. String projectName = event.getResource().getName(); // get references to all the open editors final IEditorReference[] referenceArray = page.getEditorReferences(); for ( int i=0 ; i<referenceArray.length ; ++i ) { // Any IEditorReference that has a null editor must be closed by this class. // Editors that have been created and initialized can handle their own close. if ( referenceArray[i].getEditor(false) == null ) { // Have to find the project name, but I could not find any way to get a file or even // an IMomento for this EditorReference. The only way I can find the project name is // to parse it out of the tooltip (I CAN'T BELIEVE I HAVE TO DO THIS) String filePath = referenceArray[i].getTitleToolTip(); // make sure filePath exists and has a slash as a safety check if ((filePath != null) && (filePath.length() > 0)) { int index = filePath.indexOf('/'); if (index != -1) { String project = filePath.substring(0, index); if ( projectName.equals(project) ) { // this editor is in the project that is closing/being deleted. It must be closed. final IEditorReference ref = referenceArray[i]; Display.getDefault().syncExec(new Runnable() { @Override public void run() { // casting to WorkbenchPage is the only way I've found to close an editor reference page.closeEditors(new IEditorReference[] {ref}, false); } }); } } } } } } }