/* * 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 static org.teiid.designer.ui.PluginConstants.Prefs.General.AUTO_OPEN_PERSPECTIVE_WHEN_MODEL_EDITOR_OPENED; import static org.teiid.designer.ui.UiConstants.Extensions.PERSPECTIVE; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.eclipse.core.commands.operations.IUndoContext; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.resources.WorkspaceJob; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.edit.provider.INotifyChangedListener; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IStatusLineManager; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.MessageDialogWithToggle; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.IFindReplaceTarget; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.window.Window; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IEditorActionBarContributor; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.INavigationLocation; import org.eclipse.ui.INavigationLocationProvider; import org.eclipse.ui.IViewPart; import org.eclipse.ui.IWindowListener; import org.eclipse.ui.IWorkbenchCommandConstants; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PartInitException; import org.eclipse.ui.actions.ActionFactory; import org.eclipse.ui.actions.WorkspaceModifyOperation; import org.eclipse.ui.dialogs.ISelectionStatusValidator; import org.eclipse.ui.ide.IDE; import org.eclipse.ui.operations.RedoActionHandler; import org.eclipse.ui.operations.UndoActionHandler; import org.eclipse.ui.part.EditorPart; import org.eclipse.ui.texteditor.ITextEditorExtension2; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; import org.eclipse.ui.views.properties.IPropertySheetPage; import org.teiid.core.designer.event.EventObjectListener; import org.teiid.core.designer.event.EventSourceException; import org.teiid.core.designer.util.I18nUtil; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.core.notification.util.NotificationUtilities; import org.teiid.designer.core.search.ModelWorkspaceSearch; import org.teiid.designer.core.search.runtime.ResourceImportRecord; import org.teiid.designer.core.workspace.ModelFileUtil; import org.teiid.designer.core.workspace.ModelResource; import org.teiid.designer.core.workspace.ModelResourceReloadVetoListener; import org.teiid.designer.core.workspace.ModelUtil; import org.teiid.designer.core.workspace.ModelWorkspaceException; import org.teiid.designer.ui.UiConstants; import org.teiid.designer.ui.UiPlugin; import org.teiid.designer.ui.common.dialog.CheckedListSelectionDialog; import org.teiid.designer.ui.common.print.IPrintable; import org.teiid.designer.ui.common.util.UiUtil; import org.teiid.designer.ui.common.viewsupport.ListContentProvider; import org.teiid.designer.ui.common.viewsupport.StatusInfo; import org.teiid.designer.ui.common.viewsupport.UiBusyIndicator; import org.teiid.designer.ui.event.ModelResourceEvent; import org.teiid.designer.ui.explorer.ModelExplorerLabelProvider; import org.teiid.designer.ui.explorer.ModelExplorerResourceNavigator; import org.teiid.designer.ui.outline.ModelOutlinePage; import org.teiid.designer.ui.properties.ModelObjectPropertySourceProvider; import org.teiid.designer.ui.refactor.ModelCopyCommand; import org.teiid.designer.ui.undo.IUndoManager; import org.teiid.designer.ui.undo.ModelerUndoManager; import org.teiid.designer.ui.viewsupport.MarkerUtilities; import org.teiid.designer.ui.viewsupport.ModelIdentifier; import org.teiid.designer.ui.viewsupport.ModelLabelProvider; import org.teiid.designer.ui.viewsupport.ModelObjectUtilities; import org.teiid.designer.ui.viewsupport.ModelUtilities; import org.teiid.designer.ui.viewsupport.StatusBarUpdater; /** * ModelEditor is a MultiPageEditorPart shell that ModelEditorPage extensions can provide ModelEditorPage pages. * * @since 8.0 */ public class ModelEditor extends MultiPageModelEditor implements IEditorActionExporter, INavigationLocationProvider, INotifyChangedListener, ITextEditorExtension2, UiConstants.ExtensionPoints.ModelEditorPage, IResourceChangeListener, INavigationSupported, IInitializationCompleteListener, IInlineRenameable, UiConstants { static final String PREFIX = I18nUtil.getPropertyPrefix(ModelEditor.class); /** Test Harness override of isDirty */ public static boolean NEVER_DIRTY = false; /** Initial modification stamp value. */ public static long INITIAL_STAMP = -1; private ModelOutlinePage contentOutlinePage; private ModelObjectPropertySourceProvider propertySourceProvider; private ModelEditorSelectionProvider selectionProvider; private ModelEditorSelectionSynchronizer selectionSynchronizer; private ModelExplorerLabelProvider labelProvider = new ModelExplorerLabelProvider(); ModelResource modelResource; // private IResource modelProject; private ModelEditorActionContributor actionBarHandler; private ArrayList completionEditors = new ArrayList(1); private int nEditorsCompleted = 0; /** cache for the current state of the ModelResource */ boolean resourceDirty = false; /** flag to determine if this ModelEditor has been initialized */ private boolean initialized = false; /** flag to ignore any ModelResource changes due to closing */ boolean isClosing = false; /** The context menu to be disposed. */ private Menu contextMenu; /** The veto listener for reloads */ private ModelResourceReloadVetoListener vetoListener; /** The ModelResource listener for file system changes on models and projects */ EventObjectListener modelResourceListener; private UndoActionHandler undoAction; private RedoActionHandler redoAction; private int iCurrentPage; /** * Creates a multi-page editor example. */ public ModelEditor() { super(); } /** * Determine if thie ModelEditor has been initialized and therefore knows which ModelResource it is working on. This is * important because a ModelEditor that is showing in a tab from a previous Eclipse run may not have been initialized if it's * tab is never activated. Accessing this editor's data programatically may not be possible if this method returns false. */ public boolean hasInitialized() { return initialized; } /** * Creates the pages of the multi-page editor by loading any extensions of the ModelEditorPage extension-point. Note that the * ModelEditorPages will not have their createPartControl methods called until the superclass calls back to * initializeEditor(), so no attempt to hook up listeners should be made until then. */ @Override protected void createPages() { // Get this editor's IEditorActionBarContributor which was created when the // plugin was activated actionBarHandler = (ModelEditorActionContributor)getEditorSite().getActionBarContributor(); // give the model file to the contributor so that it can update status bar with readonly/writable state actionBarHandler.setEditorInput((IFileEditorInput)getEditorInput()); // get the ModelEditorPage extension point from the plugin class IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(UiConstants.PLUGIN_ID, ID); // get the all extensions to the ModelEditorPage extension point IExtension[] extensions = extensionPoint.getExtensions(); Object[] editorList = new Object[10]; String[] nameList = new String[10]; // make executable extensions for every CLASSNAME for (int i = extensions.length - 1; i >= 0; --i) { IConfigurationElement[] elements = extensions[i].getConfigurationElements(); for (int j = 0; j < elements.length; ++j) { // catch any Exception that occurred initializing a ModelEditorPage so that // it can be removed and other pages function normally try { Object extension = elements[j].createExecutableExtension(CLASSNAME); String orderString = elements[j].getAttribute(ORDER); if (orderString != null) { int order = extensions.length; try { order = new Integer(orderString).intValue(); } catch (Exception e) { // leave order as pre-computed; } boolean tryAgain = true; int index = order; while (tryAgain) { if (editorList[index] == null) { editorList[index] = extension; nameList[index] = elements[j].getAttribute(TABNAME); tryAgain = false; } else { ++index; } } } } catch (Exception e) { // catch any Exception that occurred initializing a ModelEditorPage so that // it can be removed and other pages function normally String message = UiConstants.Util.getString("ModelEditor.pageInitializationErrorMessage", elements[j].getAttribute(CLASSNAME)); //$NON-NLS-1$ UiConstants.Util.log(IStatus.ERROR, e, message); String title = UiConstants.Util.getString("ModelEditor.pageInitializationErrorTitle"); //$NON-NLS-1$ MessageDialog.openError(getSite().getShell(), title, message); } } } // walk through the ordered list of editors and insert all that can edit the input for (int i = 0; i < editorList.length; ++i) { int index = -1; Object extension = editorList[i]; try { if (extension instanceof ModelEditorPage) { ModelEditorPage page = (ModelEditorPage)extension; if (page.canDisplay(getEditorInput())) { // set label provider in case this is necessary for the tab page.setLabelProvider(this.labelProvider); if (page instanceof IInitializationCompleteNotifier) { ((IInitializationCompleteNotifier)page).addListener(this); completionEditors.add(page); } // add it to this multi-page editor index = addPage(page, getEditorInput()); // Store the name on the page for use later. // Some page editors don't supply a title other than // in the plugin. This way the page can always get back to this // title value when necessary (i.e. via refreshEditorTabs) page.setTitleText(nameList[i]); setPageText(index, nameList[i]); setPageImage(index, page.getTitleImage()); setPageToolTipText(index, page.getTitleToolTip()); } else { // We need to get rid of the remaining pages, that can't be displayed page.preDispose(); } } } catch (Exception e) { // catch any Exception that occurred initializing a ModelEditorPage so that // it can be removed and other pages function normally String message = UiConstants.Util.getString("ModelEditor.pageInitializationErrorMessage", extension.toString()); //$NON-NLS-1$ UiConstants.Util.log(IStatus.ERROR, e, message); String title = UiConstants.Util.getString("ModelEditor.pageInitializationErrorTitle"); //$NON-NLS-1$ MessageDialog.openError(getSite().getShell(), title, message); if (index != -1) { // attempt to remove the page, but this may not work since we don't know // what state things were in when the exception was thrown. try { removePage(index); } catch (Exception ex) { // swallowed intentionally, just need to move on to the next page } } } } // create a synchronizer to handle selections and double-click between for this editor selectionSynchronizer = new ModelEditorSelectionSynchronizer(this, ((IFileEditorInput)getEditorInput()).getFile()); // add the Synchronizer as a listener to the ModelEditorSelectionProvider so that // selection in the editor can be synchronized with the ModelViewers this.getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(selectionSynchronizer); // hook up our status bar manager for EObject selection in the editor IStatusLineManager slManager = getEditorSite().getActionBars().getStatusLineManager(); selectionProvider.addSelectionChangedListener(new StatusBarUpdater(slManager)); // Register to listen for Change Notifications ModelUtilities.addNotifyChangedListener(this); ModelerCore.getWorkspace().addResourceChangeListener(this); try { if (modelResource.getEmfResource().isModified()) { resourceDirty = true; firePropertyChange(PROP_DIRTY); } } catch (ModelWorkspaceException e) { UiConstants.Util.log(IStatus.ERROR, e, e.getMessage()); } modelResourceListener = new ModelEditorEventObjectListener(this); try { UiPlugin.getDefault().getEventBroker().addListener(ModelResourceEvent.class, modelResourceListener); } catch (EventSourceException e) { Util.log(IStatus.ERROR, e, e.getMessage()); } } /** * Callback from the super class when a specified editor is lazily loaded. */ @Override protected void initializeEditor( IEditorPart editor ) { if (editor instanceof EventObjectListener) { try { UiPlugin.getDefault().getEventBroker().addListener(ModelResourceEvent.class, (EventObjectListener)editor); } catch (EventSourceException e) { Util.log(IStatus.ERROR, e, e.getMessage()); } } ModelEditorPage page = (ModelEditorPage)editor; // see if the extension has an action bar contributor. create it's context menu AbstractModelEditorPageActionBarContributor contributor = page.getActionBarContributor(); if (contributor != null) { actionBarHandler.addContributor(editor, contributor); contributor.createContextMenu(); contributor.getActionService(); } // set the editor's ILabelProvider for model objects page.setLabelProvider(labelProvider); // give the editor a reference to this class (necessary for navigation) if (page instanceof INavigationSupported) { ((INavigationSupported)page).setParent(this); } getContentOutline().addOutlineContribution(page); IEditorInput input = getEditorInput(); if (input instanceof IFileEditorInput) { page.initializeEditorPage(); } } public ModelResource getModelResource() { return this.modelResource; } public IFile getModelFile() { return ((IFileEditorInput)this.getEditorInput()).getFile(); } /** * Saves the multi-page editor's document. */ @Override public void doSave( IProgressMonitor monitor ) { // anticipate ugly error message saving to read-only file if (ModelUtil.isIResourceReadOnly(this.modelResource.getResource())) { String message = UiConstants.Util.getString("ModelEditor.resourceReadonlySaveError", modelResource.getResource().getName()); //$NON-NLS-1$ String title = UiConstants.Util.getString("ModelEditor.resourceSaveErrorTitle"); //$NON-NLS-1$ MessageDialog.openError(getSite().getShell(), title, message); // if (monitor != null) // monitor.setCanceled(true); return; } super.preSave(false); WorkspaceJob job = new WorkspaceJob(UiConstants.Util.getString("ModelEditor.saveModelJob", //$NON-NLS-1$ this.modelResource.getResource().getName())) { @Override public IStatus runInWorkspace( final IProgressMonitor monitor ) throws CoreException { try { ModelUtilities.saveModelResource(modelResource, monitor, true, this); resourceDirty = false; // property changes must be handled in UI thread UiUtil.runInSwtThread(new Runnable() { @SuppressWarnings( "synthetic-access" ) @Override public void run() { ModelEditor.this.firePropertyChange(PROP_DIRTY); } }, true); return Status.OK_STATUS; } catch (final Exception e) { throw new CoreException(new Status(IStatus.ERROR, PLUGIN_ID, IStatus.OK, e.getLocalizedMessage(), e)); } } }; job.setRule(this.modelResource.getResource()); job.schedule(); } /** * Method declared on IEditorPart. */ @Override public boolean isSaveAsAllowed() { IWorkbenchPart activePart = getSite().getWorkbenchWindow().getPartService().getActivePart(); return this == activePart; } /** * Saves the multi-page editor's document as another file. Also updates the text for page 0's tab, and updates this multi-page * editor's input to correspond to the nested editor's. */ @Override public void doSaveAs() { final SaveAsDialog dialog = new SaveAsDialog(getSite().getWorkbenchWindow().getShell(), this.modelResource); int result = dialog.open(); if (result == Window.OK) { ModelDependencyCheck check = new ModelDependencyCheck(dialog.getCommand()); UiBusyIndicator.showWhile(null, check); result = check.result; if (result == Window.OK) { // execute the copy command WorkspaceModifyOperation operation = new WorkspaceModifyOperation() { @Override protected void execute( IProgressMonitor progressMonitor ) throws CoreException { String undoLabel = UiConstants.Util.getString("ModelEditor.saveAs="); //$NON-NLS-1$ final boolean started = ModelerCore.startTxn(true, false, undoLabel, ModelEditor.this); boolean succeeded = false; try { IStatus status = dialog.getCommand().execute(progressMonitor); if (status != null && !status.isOK()) { // swjTODO: display the problems dialog } else { modelResource.close(); ModelEditorManager.close((IFile)modelResource.getResource(), false); ModelEditorManager.activate(dialog.getCommand().getNewIFile(), true); } succeeded = true; } finally { if (started) { if (succeeded) ModelerCore.commitTxn(); else ModelerCore.rollbackTxn(); } } } }; try { new ProgressMonitorDialog(getSite().getShell()).run(false, false, operation); } catch (InvocationTargetException e) { UiConstants.Util.log(e.getTargetException()); } catch (InterruptedException e) { } } } } /** * Method declared on IEditorPart */ @Override public void gotoMarker( IMarker marker ) { String sMarkerType = marker.getAttribute(Navigation.MARKER_TYPE, Navigation.UNKNOWN); if (sMarkerType.equals(Navigation.NAVIGATION)) { // look for a DELEGATE, and pass this call through if there is one: Object oDelegate = MarkerUtilities.getMarkerAttribute(marker, Navigation.DELEGATE); Object oDelegatesMarker = MarkerUtilities.getMarkerAttribute(marker, Navigation.DELEGATES_MARKER); if (oDelegate != null && oDelegate instanceof IEditorPart && oDelegatesMarker != null && oDelegatesMarker instanceof IMarker) { IEditorPart iepDelegate = (IEditorPart)oDelegate; IDE.gotoMarker(iepDelegate, (IMarker)oDelegatesMarker); } else { // if no delegate, this is a routine tab index change: int iPage = marker.getAttribute(Navigation.TAB_INDEX, 0); setActivePage(iPage); } } else { // if NOT a navigation marker, handle this way: EObject targetEObject = ModelObjectUtilities.getMarkedEObject(marker); // find the ModelPage for this object and delegate to its 'gotoMarker' if (targetEObject != null) { if (ModelEditorManager.canEdit(targetEObject)) { if (getActiveObjectEditor() == null) { ModelEditorManager.edit(targetEObject); } else if (!getActiveObjectEditor().isEditingObject(targetEObject)) { ModelEditorManager.edit(targetEObject); } } else if (getActiveObjectEditor() != null) { closeObjectEditor(); } // Now let's go ahead and check for active page and call goToMarker() so selection occurs. ModelEditorPage page = null; // getModelPageFor(targetEObject); Collection allPages = getModelPagesFor(targetEObject); boolean foundPage = false; for (Iterator iter = allPages.iterator(); iter.hasNext();) { page = (ModelEditorPage)iter.next(); if (page != null) { if (!super.hasInitialized(page)) { super.initializePage(page); } IDE.gotoMarker(page, marker); foundPage = true; } } if (!foundPage) { // no editor page can handle the marker, see if the model explorer is open and pass the marker to it. final IViewPart part = UiUtil.getWorkbenchPage().findView(UiConstants.Extensions.Explorer.VIEW); if (part != null) { ((ModelExplorerResourceNavigator)part).gotoMarker(marker); } } } } } /** * The <code>ModelEditor</code> implementation of this <code>IEditorPart</code> method sets its site to the given site, its * input to the given input, and the site's selection provider to a <code>ModelEditorSelectionProvider</code>. Subclasses may * extend this method. */ @Override public void init( IEditorSite site, IEditorInput input ) throws PartInitException { super.init(site, input); // check that the input is an instance of IFileEditorInput. // also need to make sure that the file exists on the filesystem. this is because when Eclipse shuts // down it saves a restore state. if a resource was deleted outside of Eclipse that was part of the // restore state Eclipse still creates an IResource for it which we don't want to happen. if (!(input instanceof IFileEditorInput) || !ModelUtilities.existsOnFilesystem(((IFileEditorInput)input).getFile())) { String message = UiConstants.Util.getString("ModelEditor.invalidInputError", input.getName()); //$NON-NLS-1$ throw new PartInitException(message); } final IFile file = ((IFileEditorInput)input).getFile(); // If the resource has a model file extension but with the wrong case then throw exception (defect 17709) if (ModelUtil.isModelFile(file)) { // continue // If the IFile extension does not match the set of well-known model file extensions with // a case-sensitive check but does match when the check is case-insensitive then error (defect 17709) } else if (!ModelFileUtil.isModelFileExtension(file.getFileExtension(), true) && ModelFileUtil.isModelFileExtension(file.getFileExtension(), false)) { final String actualFileName = file.getName(); final String actualExtension = file.getFileExtension(); final int endIndex = actualFileName.length() - actualExtension.length(); final String expectedFileName = actualFileName.substring(0, endIndex) + actualExtension.toLowerCase(); final Object[] params = new Object[] {actualFileName, expectedFileName}; final String msg = UiConstants.Util.getString("ModelEditor.file_extension_not_correct_case_please_rename_file", params); //$NON-NLS-1$ throw new PartInitException(msg); } // get the ModelResource. try { modelResource = ModelUtil.getModelResource(((IFileEditorInput)input).getFile(), false); if (modelResource == null) { String message = UiConstants.Util.getString("ModelEditor.modelResourceError", input.getName()); //$NON-NLS-1$ throw new PartInitException(message); } // Register this editor's veto listener with the workspace ... this.vetoListener = new ModelResourceReloadVetoListener() { @Override public boolean canReload( final ModelResource theModelResource ) { return handleCanReload(theModelResource); } }; modelResource.getModelWorkspace().addModelResourceReloadVetoListener(this.vetoListener); // MetamodelDescriptor descriptor = modelResource.getPrimaryMetamodelDescriptor(); // String descriptorUri = null; // if (descriptor != null) { // descriptorUri = descriptor.getNamespaceURI(); // } // add the ModelResource to the OpenEditorMap OpenEditorMap.getInstance().addModelEditor(this, modelResource); } catch (ModelWorkspaceException e) { String message = UiConstants.Util.getString("ModelEditor.modelResourceError", input.getName()); //$NON-NLS-1$ throw new PartInitException(message, e); } // initialize this IEditorPart setSite(site); setInput(input); setPartName(((IFileEditorInput)getEditorInput()).getFile().getName()); setTitleImage(ModelIdentifier.getModelImage(modelResource)); // connect the ModelEditorSelectionProvider as the selection provider for the workbench selectionProvider = new ModelEditorSelectionProvider(this); super.getEditorSite().setSelectionProvider(selectionProvider); // check the readonly status of the editor resource each time the modeler window is activated getEditorSite().getWorkbenchWindow().getWorkbench().addWindowListener(new IWindowListener() { @Override public void windowActivated( IWorkbenchWindow theWindow ) { getActionBarContributor().setReadOnlyState(); } @Override public void windowOpened( IWorkbenchWindow theWindow ) { } @Override public void windowDeactivated( IWorkbenchWindow theWindow ) { } @Override public void windowClosed( IWorkbenchWindow theWindow ) { } }); // Add in undo / redo command wiring IUndoContext undoContext = ModelerUndoManager.getInstance().getUndoContext(); undoAction= new UndoActionHandler(getSite(), undoContext); undoAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_UNDO); redoAction= new RedoActionHandler(getSite(), undoContext); redoAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_REDO); getEditorSite().getActionBars().setGlobalActionHandler(ActionFactory.UNDO.getId(), undoAction); getEditorSite().getActionBars().setGlobalActionHandler(ActionFactory.REDO.getId(), redoAction); this.initialized = true; } protected boolean handleCanReload( final ModelResource theModelResource ) { boolean canReload = true; if (this.modelResource != null && this.modelResource.equals(theModelResource)) { // The supplied resource is the "same" as this resource, so ask user whether to reload ... final ReloadRequestRunnable runnable = new ReloadRequestRunnable(); Display.getDefault().syncExec(runnable); canReload = runnable.canReload(); } return canReload; } /** * Obtains the ModelEditorActionBarContributor */ public ModelEditorActionContributor getActionBarContributor() { return (ModelEditorActionContributor)getEditorSite().getActionBarContributor(); } public IEditorPart getCurrentPage() { return getActiveEditor(); } /** * @see org.teiid.designer.ui.editors.IEditorActionExporter#contributeExportedActions(org.eclipse.jface.action.IMenuManager) */ @Override public void contributeExportedActions( IMenuManager theMenuMgr ) { // called by action service contributeToContextMenu ModelEditorPage page = (ModelEditorPage)getCurrentPage(); AbstractModelEditorPageActionBarContributor contributor = page.getActionBarContributor(); if (contributor != null) { contributor.contributeExportedActions(theMenuMgr); } } /** * @see org.teiid.designer.ui.editors.IEditorActionExporter#getAdditionalModelingActions(org.eclipse.jface.viewers.ISelection) * @since 5.0 */ @Override public List<IAction> getAdditionalModelingActions( ISelection selection ) { // called by action service contributeToContextMenu ModelEditorPage page = (ModelEditorPage)getCurrentPage(); AbstractModelEditorPageActionBarContributor contributor = page.getActionBarContributor(); if (contributor != null) { return contributor.getAdditionalModelingActions(selection); } return Collections.EMPTY_LIST; } /** * implements {@link org.eclipse.jface.viewers.ISelectionProvider} to return this editor's overall selection. */ public ISelection getSelection() { return selectionProvider.getSelection(); } /** * @see org.teiid.designer.ui.editors.MultiPageModelEditor#setFocus() */ @Override public void setFocus() { // because of the way Eclipse activates views, we must set focus to a control in our editor // before calling super.setFocus(). If we don't then we get a "recursive attempt to activate part" warning. ModelEditorPage page = (ModelEditorPage)getActiveEditor(); if ((page != null) && (page.getControl() != null)) { // control is null if editor has not been created yet page.getControl().setFocus(); } super.setFocus(); ModelEditorActionContributor abc = getActionBarContributor(); if (abc != null) { abc.setEditorInput((IFileEditorInput)getEditorInput()); abc.setReadOnlyState(); // let's notify the model editors that read-only changed. if (page != null) { page.updateReadOnlyState(abc.getReadOnlyState()); } updateReadOnlyState(); } // endif } public void setSelection( ISelection selection ) { selectionProvider.setSelection(selection); } /** * Overridden to intercept and provide IContentOutlinePage adapter * * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) */ @Override public Object getAdapter( Class key ) { // get the EMF Editor's OutlinePage does the Outline page too if (key.equals(IContentOutlinePage.class)) { return getContentOutline(); } else if (key.equals(IPropertySheetPage.class)) { if (propertySourceProvider == null) { propertySourceProvider = ModelUtilities.getPropertySourceProvider(); } return propertySourceProvider.getPropertySheetPage(); } else if (key.equals(IFindReplaceTarget.class)) { if (this.editorContainer.hasFocus()) { if (this.editorContainer.getActiveEditor() instanceof IAdaptable) { return ((IAdaptable)this.editorContainer.getActiveEditor()).getAdapter(key); } return null; } return (getCurrentPage() == null) ? null : getCurrentPage().getAdapter(key); } else if (key.equals(IPrintable.class)) { /* * Get the current page, and call its 'getAdapter( IPrintable.class )' */ if (getCurrentPage() != null) { return getCurrentPage().getAdapter(IPrintable.class); } } else if (key.equals(IUndoManager.class)) { if (this.editorContainer.hasFocus()) { ModelObjectEditorPage objectEditor = this.editorContainer.getActiveEditor(); if (objectEditor instanceof IAdaptable) { Object undoMgr = ((IAdaptable)objectEditor).getAdapter(key); if (undoMgr != null) { return undoMgr; } } } } return super.getAdapter(key); } public IAdaptable getExternalAdaptable() { if (editorContainer != null) { return editorContainer; } return null; } public ModelObjectEditorPanel getEditorContainer() { return editorContainer; } @Override public void dispose() { // // NOTE: DO NOT dispose of the ModelEditorActionContributor !!!!! // The Eclipse framework disposes of it when the last ModelEditor is closed. The framework // also constructs a new contributor when the first ModelEditor is opened. // if (propertySourceProvider != null) { propertySourceProvider.dispose(); } if (contentOutlinePage != null) { contentOutlinePage.dispose(); } if (selectionSynchronizer != null) { selectionSynchronizer.dispose(); this.getSite().getWorkbenchWindow().getSelectionService().removeSelectionListener(selectionSynchronizer); } if (contextMenu != null) { contextMenu.dispose(); } // Un-Register this for notifications ModelUtilities.removeNotifyChangedListener(this); // Un-Register this for Resource change events ModelerCore.getWorkspace().removeResourceChangeListener(this); // Un-Register this for Reload vetos ... modelResource.getModelWorkspace().removeModelResourceReloadVetoListener(this.vetoListener); // Need to walk through editors and remove ModelResourceEvent listeners Iterator iter = getAllEditors().iterator(); Object nextEditor = null; while (iter.hasNext()) { nextEditor = iter.next(); if (nextEditor instanceof EventObjectListener) { try { UiPlugin.getDefault().getEventBroker().removeListener(ModelResourceEvent.class, (EventObjectListener)nextEditor); } catch (EventSourceException e) { Util.log(IStatus.ERROR, e, e.getMessage()); } } } // Let's remove the model editor from event broker try { UiPlugin.getDefault().getEventBroker().removeListener(ModelResourceEvent.class, modelResourceListener); } catch (EventSourceException e) { Util.log(IStatus.ERROR, e, e.getMessage()); } // Dispose created O/S-related resources this.labelProvider.dispose(); if (this.modelResource != null && this.modelResource.isOpen()) { try { OpenEditorMap.getInstance().removeModelEditor(this.modelResource); if (isDirty()) { ModelResourceEvent event = new ModelResourceEvent(this.modelResource, ModelResourceEvent.CLOSING, this); UiPlugin.getDefault().getEventBroker().processEvent(event); this.modelResource.close(); event = new ModelResourceEvent(this.modelResource, ModelResourceEvent.CLOSED, this); UiPlugin.getDefault().getEventBroker().processEvent(event); // defect 16805 - notify listeners that this model will be reloaded // since the changes have been discarded (even though, yes, // technically it hasn't been reloaded yet) event = new ModelResourceEvent(this.modelResource, ModelResourceEvent.RELOADED, this); UiPlugin.getDefault().getEventBroker().processEvent(event); } } catch (ModelWorkspaceException e) { String message = UiConstants.Util.getString("ModelEditor.modelResourceCloseError", this.modelResource); //$NON-NLS-1$ UiConstants.Util.log(IStatus.ERROR, e, message); } } super.dispose(); // this disposes of the nested pages } public boolean canOpenModelObject( Object modelObject ) { boolean result = false; if (modelObject != null) { for (int i = 0; i < super.getPageCount(); ++i) { ModelEditorPage page = (ModelEditorPage)getEditor(i); if (page.canOpenContext(modelObject)) { result = true; break; } } } return result; } public ModelEditorPage getModelPageFor( Object modelObject ) { ModelEditorPage result = null; if (modelObject != null) { for (int i = 0; i < super.getPageCount(); ++i) { ModelEditorPage page = (ModelEditorPage)getEditor(i); if (page.canOpenContext(modelObject)) { result = page; break; } } } return result; } public Collection getModelPagesFor( Object modelObject ) { Collection pages = new ArrayList(); if (modelObject != null) { for (int i = 0; i < super.getPageCount(); ++i) { ModelEditorPage page = (ModelEditorPage)getEditor(i); if (page.canOpenContext(modelObject)) { pages.add(page); } } } if (pages.isEmpty()) return Collections.EMPTY_LIST; return pages; } /** * The editor responds by calling openContext for each page that responds positively to canOpenContext. The currently active * page (if it can open the new context) will stay the active page, else the first page that can open the new context will * become the active page. * * @see org.eclipse.jface.viewers.IDoubleClickListener#doubleClick(org.eclipse.jface.viewers.DoubleClickEvent) * @param modelObject the new editor context * @return true if the object was opened in a ModelEditorPage, false if all pages ignored the object. */ public boolean openModelObject( Object modelObject ) { // calls the real openModelObject, defaulting forceRefesh to false return openModelObject(modelObject, false); } /** * The editor responds by calling openContext for each page that responds positively to canOpenContext. The currently active * page (if it can open the new context) will stay the active page, else the first page that can open the new context will * become the active page. * * @see org.eclipse.jface.viewers.IDoubleClickListener#doubleClick(org.eclipse.jface.viewers.DoubleClickEvent) * @param modelObject the new editor context * @param forceRefresh whether or not to refresh the context after open * @return true if the object was opened in a ModelEditorPage, false if all pages ignored the object. */ public boolean openModelObject( Object modelObject, boolean forceRefresh ) { // System.out.println("ModelEditor.openModelObject()"); //$NON-NLS-1$ boolean result = false; ModelEditorPage focusPage = null; int pageIndex = -1; if (modelObject != null) { for (int i = 0; i < super.getPageCount(); ++i) { ModelEditorPage page = (ModelEditorPage)getEditor(i); if (page.canOpenContext(modelObject)) { if (!hasInitialized(page)) { initializePage(page); } page.openContext(modelObject, forceRefresh); // keep current active page the same if possible if ((focusPage == null) || (getActiveEditor() == page)) { focusPage = page; pageIndex = i; result = true; } } } if (focusPage != null) { if (getActiveEditor() != focusPage) { if (!hasInitialized(focusPage)) { super.initializePage(focusPage, super.getItem(pageIndex)); } super.setActivePage(pageIndex); } pageChange(pageIndex); if (getActiveEditor() != focusPage) { setFocus(); // ---------------------------- // Defect 22844 - the individual page.setFocus() was not being called. This is required // to help with this defect. // ---------------------------- focusPage.setFocus(); } // Tell this editor's SelectionProvider about the new page if (selectionProvider != null) { selectionProvider.setSourcePage(focusPage); } setPageImage(pageIndex, focusPage.getTitleImage()); setPageText(pageIndex, focusPage.getTitle()); setPageToolTipText(pageIndex, focusPage.getTitleToolTip()); } } return result; } public void refreshEditorTabs() { for (int i = 0; i < super.getPageCount(); ++i) { ModelEditorPage page = (ModelEditorPage)getEditor(i); if (page != null) { setPageImage(i, page.getTitleImage()); setPageText(i, page.getTitle()); setPageToolTipText(i, page.getTitleToolTip()); } } } private ModelOutlinePage getContentOutline() { if (contentOutlinePage == null) { contentOutlinePage = new ModelOutlinePage(this); } return contentOutlinePage; } /** * Overridden to allow the action bar contributers to be activated and deactivated, and the ModelOutlinePage to enable/disable * any outline page contributions. */ @Override protected void pageChange( int newPageIndex ) { // XXX: Workaround for 1GCN531: SWT:WIN2000 - CTabFolder child's visibility is false on notification Control control = getControl(newPageIndex); if (control != null) { control.setVisible(true); } // XXX: End workaround // this is our only chance to keep track of what page we are on; createMarker() will use this: iCurrentPage = newPageIndex; IEditorPart activeEditor = getEditor(newPageIndex); if (activeEditor != null) { // handle tabs right here in ModelEditor IWorkbenchPage workbenchPage = UiUtil.getWorkbenchPage(); if (workbenchPage != null) { workbenchPage.getNavigationHistory().markLocation(this); } // endif // notify the ModelOutlinePage that the active editor page has changed getContentOutline().setActiveEditorPage((ModelEditorPage)activeEditor); if (selectionProvider != null) { // Tell this editor's SelectionProvider who the current page is selectionProvider.setSourcePage((ModelEditorPage)activeEditor); } // ---------------------------- // Defect 22844 - the individual activeEditor.setFocus() was not being called on pageChange(). // This is required to help with this defect. // ---------------------------- activeEditor.setFocus(); } else { // System.out.println("[ModelEditor.pageChange] activeEditor was NULL! " ); //$NON-NLS-1$ } // let the contributor know about the new page IEditorActionBarContributor contributor = getEditorSite().getActionBarContributor(); if ((contributor != null) && (contributor instanceof ModelEditorActionContributor) && activeEditor != null) { ((ModelEditorActionContributor)contributor).setActivePage(activeEditor); } } public void displayModelEditorPage( ModelEditorPage mepPageEditor ) { for (int i = 0; i < super.getPageCount(); ++i) { ModelEditorPage page = (ModelEditorPage)getEditor(i); if (page == mepPageEditor) { this.setActivePage(i); break; } } } /** * @see org.eclipse.emf.edit.provider.INotifyChangedListener#notifyChanged(org.eclipse.emf.common.notify.Notification) */ @Override public void notifyChanged( final Notification notification ) { if (this.modelResource.isOpen()) { // pass the notification on to all pages that have a NotifyChangeListener Display.getDefault().asyncExec(new Runnable() { @Override public void run() { for (int i = 0; i < getPageCount(); ++i) { ModelEditorPage page = (ModelEditorPage)getEditor(i); if (page != null && hasInitialized(page)) { INotifyChangedListener listener = page.getNotifyChangedListener(); if (listener != null) { listener.notifyChanged(notification); } } } } }); if (!resourceDirty && NotificationUtilities.isChanged(notification)) { try { if (this.modelResource.isOpen()) { if (this.modelResource.getEmfResource().isModified()) { resourceDirty = true; Display.getDefault().asyncExec(new Runnable() { @Override public void run() { dirtyProperty(); } }); } } } catch (ModelWorkspaceException mwe) { UiConstants.Util.log(mwe); } } else if (notification.getNotifier() instanceof Resource) { try { if (this.modelResource.isOpen()) { final boolean rsrcDirty = this.modelResource.getEmfResource().isModified(); if (rsrcDirty != this.resourceDirty) { this.resourceDirty = rsrcDirty; Display.getDefault().asyncExec(new Runnable() { @Override public void run() { dirtyProperty(); } }); } } } catch (ModelWorkspaceException mwe) { UiConstants.Util.log(mwe); } } // Need to ask the activeObjectEditor if it's resource is still valid if (getActiveObjectEditor() != null && !getActiveObjectEditor().isResourceValid()) Display.getDefault().asyncExec(new Runnable() { @Override public void run() { closeObjectEditor(); } }); } } void dirtyProperty() { firePropertyChange(PROP_DIRTY); } /** * @see org.eclipse.ui.ISaveablePart#isDirty() */ @Override public boolean isResourceDirty() { return this.resourceDirty; } /** * @see org.eclipse.ui.ISaveablePart#isDirty() */ @Override public boolean isDirty() { if (NEVER_DIRTY || isClosing) { return false; } return super.isDirty(); } /** * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent) */ @Override public void resourceChanged( IResourceChangeEvent event ) { int type = event.getType(); if (type == IResourceChangeEvent.POST_CHANGE) { try { IResourceDelta delta = event.getDelta(); if (delta != null) { delta.accept(new IResourceDeltaVisitor() { @Override public boolean visit( IResourceDelta delta ) { if (delta.getResource().equals(getModelFile()) && ((delta.getKind() & IResourceDelta.REMOVED) != 0)) { Display.getDefault().asyncExec(new Runnable() { @Override public void run() { if (Display.getDefault().isDisposed()) { return; } if (UiPlugin.getDefault().getCurrentWorkbenchWindow() != null && UiPlugin.getDefault().getCurrentWorkbenchWindow().getActivePage() != null) { UiPlugin.getDefault().getCurrentWorkbenchWindow().getActivePage().closeEditor(ModelEditor.this, false); } } }); return false; } return true; } }); } } catch (CoreException e) { UiConstants.Util.log(IStatus.ERROR, e, e.getMessage()); } } } // =========================================== // ITextEditorExtension2 interface methods // =========================================== @Override public boolean isEditorInputModifiable() { IFindReplaceTarget target = (IFindReplaceTarget)getAdapter(IFindReplaceTarget.class); return (target == null ? false : target.isEditable()); } @Override public boolean validateEditorInputState() { return true; } /** * <p> * </p> * * @see org.eclipse.ui.INavigationLocationProvider#createEmptyNavigationLocation() * @since 4.0 */ @Override public INavigationLocation createEmptyNavigationLocation() { // System.out.println("[ModelEditor.createEmptyNavigationLocation] TOP"); //$NON-NLS-1$ return null; // Defect 22290 reflects memory (leaks) issues within designer. (See createNavigationLocation() comments below) // return neNavigableEditor.createEmptyNavigationLocation(); } /** * <p> * </p> * * @see org.eclipse.ui.INavigationLocationProvider#createNavigationLocation() * @since 4.0 */ @Override public INavigationLocation createNavigationLocation() { // if no editor, return null (and no history entry will be created) return null; } /** * @see org.teiid.designer.ui.editors.INavigationSupported */ @Override public IMarker createMarker() { // System.out.println("[ModelEditor.createMarker] TOP"); //$NON-NLS-1$ NavigationMarker nmMarker = new NavigationMarker(); // if activeEditor instanceof INavigationLocationProvider, use it as a DELEGATE IEditorPart iepActiveEditor = getActiveEditor(); nmMarker.setAttribute(Navigation.MARKER_TYPE, Navigation.NAVIGATION); if (iepActiveEditor != null) { if (iepActiveEditor instanceof INavigationLocationProvider && iepActiveEditor instanceof INavigationSupported) { nmMarker.setAttribute(Navigation.DELEGATE, iepActiveEditor); nmMarker.setAttribute(Navigation.DELEGATES_MARKER, ((INavigationSupported)iepActiveEditor).createMarker()); } else { nmMarker.setAttribute(Navigation.TAB_INDEX, iCurrentPage); } } return nmMarker; } public void openComplete() { // pass the notification on to all pages that have a NotifyChangeListener Display display = getSite().getWorkbenchWindow().getShell().getDisplay(); UiBusyIndicator.showWhile(display, new Runnable() { @Override public void run() { for (int i = 0; i < getPageCount(); ++i) { ModelEditorPage page = (ModelEditorPage)getEditor(i); if (page != null && hasInitialized(page)) { page.openComplete(); } } } }); } /** * When the final completionEditor responds, we do a check if the resource for this editor is dirty and automatically save. * This insures that any model created during import or otherwise that contains children that can be displayed in a diagram * will cause diagrams and diagram entities to be created in the diagram editor. This is a specific case, but there may be * other editors that could potentially make the model dirty while opening the editor to edit the resource. * * @see org.teiid.designer.ui.editors.IInitializationCompleteListener#processInitializationComplete() * @since 4.3 */ @Override public void processInitializationComplete() { // System.out.println(" ModelEditor.processInitComplete() called!!!!! isDirty = " + isDirty() + " isResourceDirty() = " + // isResourceDirty() + " isClosing = " + isClosing); if (nEditorsCompleted < completionEditors.size()) { nEditorsCompleted++; if (nEditorsCompleted == completionEditors.size()) { nEditorsCompleted = 0; // Initialization complete. Now fork off cleaning up the listeners and SAVE if dirty Display.getCurrent().asyncExec(new Runnable() { @Override public void run() { final List allEditors = getAllEditors(); for (Iterator iter = allEditors.iterator(); iter.hasNext();) { Object nextEditor = iter.next(); if (nextEditor instanceof IInitializationCompleteNotifier) { ((IInitializationCompleteNotifier)nextEditor).removeListener(ModelEditor.this); } } if ((resourceDirty || isDirty()) && !isClosing) { // All editors have completed initialization // Default behavior is we save the editor IProgressMonitor monitor = new NullProgressMonitor(); doSave(monitor); } if (isClosing) return; // switch to Designer perspective if user wants to and we need to try { // if Designer perspective already in focus no need to do anything if ((UiUtil.getPerspectiveId() != null) && UiUtil.getPerspectiveId().equals(PERSPECTIVE)) { return; } // switch to Designer perspective if user wants to IPreferenceStore prefStore = UiPlugin.getDefault().getPreferenceStore(); String openPerspective = prefStore.getString(AUTO_OPEN_PERSPECTIVE_WHEN_MODEL_EDITOR_OPENED); boolean shouldOpen = false; if (MessageDialogWithToggle.ALWAYS.equals(openPerspective)) { shouldOpen = true; } else if (!MessageDialogWithToggle.NEVER.equals(openPerspective)) { // show dialog here and set dialog settings Shell shell = ModelEditor.this.getSite().getShell(); String title = Util.getString(PREFIX + "OpenPerspectiveDialog.title"); //$NON-NLS-1$ String msg = Util.getString(PREFIX + "OpenPerspectiveDialog.msg"); //$NON-NLS-1$ String toggleMsg = Util.getString(PREFIX + "OpenPerspectiveDialog.toggleMsg"); //$NON-NLS-1$ MessageDialogWithToggle dialog = MessageDialogWithToggle.openYesNoQuestion(shell, title, msg, toggleMsg, false, UiPlugin.getDefault().getPreferenceStore(), AUTO_OPEN_PERSPECTIVE_WHEN_MODEL_EDITOR_OPENED); shouldOpen = (dialog.getReturnCode() == IDialogConstants.YES_ID); // save if user wants decision remembered if (dialog.getToggleState()) { UiPlugin.getDefault().getPreferences().flush(); } } // switch to Designer perspective if requested if (shouldOpen) { UiUtil.openPerspective(UiConstants.Extensions.PERSPECTIVE); } } catch (Exception e) { // don't let any exception here change the state of success UiConstants.Util.log(e); } } }); } } } /** * @see org.teiid.designer.ui.editors.INavigationSupported#setParent() */ @Override public void setParent( ModelEditor meParentEditor ) { } /** * @see org.teiid.designer.ui.editors.IInlineRenameable#canRenameInline(org.eclipse.emf.ecore.EObject) * @since 5.0 */ @Override public IInlineRenameable getInlineRenameable( EObject theObj ) { // there may be more than one renameable editor, however only ONE can be in focus // Search the editors and return a single focused renameable editor or NULL final List allEditors = getAllEditors(); for (Iterator iter = allEditors.iterator(); iter.hasNext();) { Object nextEditor = iter.next(); if (nextEditor instanceof IInlineRenameable && nextEditor instanceof EditorPart) { boolean isThisActivePage = getActiveEditor() == nextEditor; if (isThisActivePage) { return (IInlineRenameable)nextEditor; } } } return null; } /** * @see org.teiid.designer.ui.editors.IInlineRenameable#renameInline(org.eclipse.emf.ecore.EObject) * @since 5.0 */ @Override public void renameInline( EObject theObj, IInlineRenameable renameable ) { IWorkbenchWindow window = getSite().getWorkbenchWindow(); // find the renamable editor, set focus then call rename on it. boolean isThisActivePage = window.getActivePage().getActivePart() == renameable; if (renameable != null) { if (!isThisActivePage) { ((IWorkbenchPart)renameable).setFocus(); } renameable.renameInline(theObj, renameable); } } /** * A runnable for checking model dependencies before Save As. Since this search can take several seconds the logic was * implemented as a Runnable that can be passed to a progress dialog or busy indicator. * * @since 4.2 */ public class ModelDependencyCheck implements Runnable { public int result; public ModelCopyCommand copyCommand; public ModelDependencyCheck( ModelCopyCommand copyCommand ) { this.copyCommand = copyCommand; } @Override public void run() { result = Window.OK; // determine if there are any models dependent upon this one // search the workspace for any models that import anything beneath the path that is moving ModelWorkspaceSearch search = new ModelWorkspaceSearch(); Collection colDependentResources = search.getModelsImportingResources(modelResource.getResource().getFullPath().toString()); if (!colDependentResources.isEmpty()) { // build a collection of files from the search result Collection fileList = new ArrayList(colDependentResources.size()); for (Iterator iter = colDependentResources.iterator(); iter.hasNext();) { String pathString = ((ResourceImportRecord)iter.next()).getPath(); IPath path = new Path(pathString); fileList.add(ModelerCore.getWorkspace().getRoot().getFile(path)); } // display the files to the user and allow them to select which, if any, should be redirected to the copy ModelLabelProvider labelProvider = new ModelLabelProvider(); labelProvider.setFullpath(true); CheckedListSelectionDialog depDialog = new CheckedListSelectionDialog( getSite().getWorkbenchWindow().getShell(), fileList, new ListContentProvider(), labelProvider, UiConstants.Util.getString("ModelEditor.redirectReferencesMessage") //$NON-NLS-1$ ); depDialog.setTitle(UiConstants.Util.getString("ModelEditor.redirectReferencesTitle")); //$NON-NLS-1$ depDialog.setSelectionStatusValidator(new ISelectionStatusValidator() { private Collection dirtyFiles = ModelEditorManager.getDirtyResources(); @Override public IStatus validate( Object[] selection ) { for (int i = 0; i < selection.length; ++i) { if (ModelUtil.isIResourceReadOnly((IFile)selection[i])) { final String name = ((IFile)selection[i]).getName(); return new StatusInfo( UiConstants.PLUGIN_ID, IStatus.ERROR, UiConstants.Util.getString("ModelEditor.redirectReferencesReadOnlyError", name)); //$NON-NLS-1$ } else if (dirtyFiles.contains(selection[i])) { final String name = ((IFile)selection[i]).getName(); return new StatusInfo( UiConstants.PLUGIN_ID, IStatus.ERROR, UiConstants.Util.getString("ModelEditor.redirectReferencesDirtyFileError", name)); //$NON-NLS-1$ } } return null; } }); result = depDialog.open(); if (result == Window.OK) { Object[] models = depDialog.getResult(); if (models != null && models.length > 0) { ArrayList modelList = new ArrayList(models.length); for (int i = 0; i < models.length; ++i) { IFile file = (IFile)models[i]; if (file.exists()) { try { modelList.add(ModelUtil.getModelResource(file, true)); } catch (ModelWorkspaceException e) { String message = UiConstants.Util.getString("ModelEditor.modelResourceError", file.getName()); //$NON-NLS-1$ UiConstants.Util.log(IStatus.ERROR, e, message); } } } copyCommand.setModelsToRedirect(modelList); } } } } } protected class ReloadRequestRunnable implements Runnable { private boolean reload; /** * @see java.lang.Runnable#run() * @since 4.2 */ @Override public void run() { this.reload = MessageDialog.openQuestion(getSite().getShell(), Util.getString(PREFIX + "dialog.fileSystemChange.title"), //$NON-NLS-1$ Util.getString(PREFIX + "dialog.fileSystemChange.msg", //$NON-NLS-1$ new Object[] {ModelEditor.this.modelResource.getItemName()})); } public boolean canReload() { return this.reload; } } }