blob: 3a80bdc4741f694750b713cbc218dd8e3906b30f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2006 Sybase, Inc. and others.
*
* 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:
* Sybase, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.jsf.facesconfig.ui;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EventObject;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
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.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
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.Status;
import org.eclipse.emf.common.command.BasicCommandStack;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.domain.IEditingDomainProvider;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory;
import org.eclipse.emf.edit.provider.resource.ResourceItemProviderAdapterFactory;
import org.eclipse.gef.commands.CommandStack;
import org.eclipse.gef.commands.CommandStackListener;
import org.eclipse.gef.editparts.ZoomManager;
import org.eclipse.gef.ui.actions.ActionRegistry;
import org.eclipse.gef.ui.actions.EditorPartAction;
import org.eclipse.gef.ui.actions.SaveAction;
import org.eclipse.gef.ui.actions.UpdateAction;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jst.jsf.common.ui.internal.actions.IOpenPage;
import org.eclipse.jst.jsf.core.IJSFCoreConstants;
import org.eclipse.jst.jsf.facesconfig.edit.provider.FacesConfigItemProviderAdapterFactory;
import org.eclipse.jst.jsf.facesconfig.emf.FacesConfigType;
import org.eclipse.jst.jsf.facesconfig.ui.page.ComponentsPage;
import org.eclipse.jst.jsf.facesconfig.ui.page.IntroductionPage;
import org.eclipse.jst.jsf.facesconfig.ui.page.ManagedBeanPage;
import org.eclipse.jst.jsf.facesconfig.ui.page.OthersPage;
import org.eclipse.jst.jsf.facesconfig.ui.page.OverviewPage;
import org.eclipse.jst.jsf.facesconfig.ui.page.WaitForLoadPage;
import org.eclipse.jst.jsf.facesconfig.ui.pageflow.DelegatingZoomManager;
import org.eclipse.jst.jsf.facesconfig.ui.pageflow.PageflowEditor;
import org.eclipse.jst.jsf.facesconfig.ui.pageflow.command.DelegatingCommandStack;
import org.eclipse.jst.jsf.facesconfig.ui.pageflow.command.EMFCommandStackGEFAdapter;
import org.eclipse.jst.jsf.facesconfig.ui.pageflow.layout.PageflowLayoutManager;
import org.eclipse.jst.jsf.facesconfig.ui.preference.GEMPreferences;
import org.eclipse.jst.jsf.facesconfig.util.FacesConfigArtifactEdit;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.ui.IActionBars;
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.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.ui.dialogs.SaveAsDialog;
import org.eclipse.ui.forms.editor.FormEditor;
import org.eclipse.ui.forms.editor.FormPage;
import org.eclipse.ui.forms.editor.IFormPage;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.ide.IGotoMarker;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
import org.eclipse.ui.views.properties.IPropertySheetPage;
import org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
import org.eclipse.wst.common.project.facet.core.IFacetedProject;
import org.eclipse.wst.common.project.facet.core.IProjectFacet;
import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;
import org.eclipse.wst.common.project.facet.core.ProjectFacetsManager;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.ui.StructuredTextEditor;
/**
* This is the main editor for the faces-config file. Note that the model
* load can involve long-running socket operations (shouldn't but can),
* so the editor UI is load asynchronously. This is means that any
* operations that need to be executed on editor open should be run
* using AddPagesTask.pageSafeExecute() to ensure that they occur
* after all editor pages have finished loading.
*
* @author sfshi
*
*/
public class FacesConfigEditor extends FormEditor implements
IEditingDomainProvider, ISelectionProvider {
/**
* This editor's ID. TODO: this should prob be in plugin.properties?
*/
public static final String EDITOR_ID = "org.eclipse.jst.jsf.facesconfig.ui.FacesConfigEditor"; //$NON-NLS-1$
/**
* editing domain that is used to track all changes to the model
*/
private AdapterFactoryEditingDomain editingDomain;
/**
* adapter factory used for providing views of the model
*/
private ComposedAdapterFactory adapterFactory;
/** id of the pageflowPage */
private int pageflowPageID;
private int managedBeanPageID;
private int componentsPageID;
private int othersPageID;
private int sourcePageId;
private PageflowEditor pageflowPage;
/** The source text editor. */
private StructuredTextEditor sourcePage;
private Collection selectionChangedListeners = new ArrayList();
private ISelection editorSelection = StructuredSelection.EMPTY;
private IContentOutlinePage outlinePage;
private IProject currentProject;
private boolean isWebProject;
private ModelLoader _modelLoader;
/**
* only true once dispose() has been called
* used to signal that the editor was disposed.
*/
private boolean _isDisposed; // = false;
/**
* Used to load editor pages when the model is loaded
*/
private final AddPagesTask _addPagesTask = new AddPagesTask();
/**
* Default constructor
*/
public FacesConfigEditor() {
initializeEMF();
}
/**
* This listens for workspace changes. <!-- begin-user-doc --> <!--
* end-user-doc -->
*
* @generated
*/
protected IResourceChangeListener resourceChangeListener = new IResourceChangeListener() {
public void resourceChanged(IResourceChangeEvent event) {
// Only listening to these.
// if (event.getType() == IResourceDelta.POST_CHANGE)
{
IResourceDelta delta = event.getDelta();
try {
class ResourceDeltaVisitor implements IResourceDeltaVisitor {
protected ResourceSet resourceSet = editingDomain
.getResourceSet();
@SuppressWarnings("hiding") //$NON-NLS-1$
protected Collection changedResources = new ArrayList();
@SuppressWarnings("hiding") //$NON-NLS-1$
protected Collection removedResources = new ArrayList();
public boolean visit(IResourceDelta delta_) {
if (delta_.getFlags() != IResourceDelta.MARKERS
&& delta_.getResource().getType() == IResource.FILE) {
if ((delta_.getKind() & (IResourceDelta.CHANGED | IResourceDelta.REMOVED)) != 0) {
Resource resource = resourceSet
.getResource(URI.createURI(delta_
.getFullPath().toString()),
false);
if (resource != null) {
if ((delta_.getKind() & IResourceDelta.REMOVED) != 0) {
removedResources.add(resource);
} else {
changedResources.add(resource);
}
}
}
}
return true;
}
public Collection getChangedResources() {
return changedResources;
}
public Collection getRemovedResources() {
return removedResources;
}
}
ResourceDeltaVisitor visitor = new ResourceDeltaVisitor();
delta.accept(visitor);
if (!visitor.getRemovedResources().isEmpty()) {
removedResources.addAll(visitor.getRemovedResources());
if (!isDirty()) {
getSite().getShell().getDisplay().asyncExec(
new Runnable() {
public void run() {
getSite().getPage().closeEditor(
FacesConfigEditor.this,
false);
FacesConfigEditor.this.dispose();
}
});
}
}
if (!visitor.getChangedResources().isEmpty()) {
changedResources.addAll(visitor.getChangedResources());
}
} catch (CoreException exception) {
// log it.
EditorPlugin.getDefault().getLog().log(
new Status(IStatus.ERROR, EditorPlugin
.getPluginId(), IStatus.OK, exception
.getMessage() == null ? "" : exception //$NON-NLS-1$
.getMessage(), exception));
}
}
}
};
/**
* Resources that have been removed since last activation.
*
* @generated
*/
Collection removedResources = new ArrayList();
/**
* Resources that have been changed since last activation.
*
* @generated
*/
Collection changedResources = new ArrayList();
/**
* Resources that have been saved.
*
* @generated
*/
Collection savedResources = new ArrayList();
/**
* Initializes the EMF support.
*/
private void initializeEMF() {
// create an adapter factory that yields item providers
List factories = new ArrayList();
factories.add(new ResourceItemProviderAdapterFactory());
factories.add(new FacesConfigItemProviderAdapterFactory());
factories.add(new ReflectiveItemProviderAdapterFactory());
adapterFactory = new ComposedAdapterFactory(factories);
// create the command stack that will notify this editor as commands are
// executed
BasicCommandStack commandStack = new BasicCommandStack();
commandStack
.addCommandStackListener(new org.eclipse.emf.common.command.CommandStackListener() {
public void commandStackChanged(final EventObject event) {
getContainer().getShell().getDisplay().asyncExec(
new Runnable() {
public void run() {
editorDirtyStateChanged();
getActionBarContributor()
.updateActionBars();
}
});
}
});
// commandStack.addCommandStackListener(this);
// create the editing domain with a special command stack
editingDomain = new AdapterFactoryEditingDomain(adapterFactory,
commandStack, new HashMap());
}
/*
* @see org.eclipse.ui.IEditorPart#init(org.eclipse.ui.IEditorSite,
* org.eclipse.ui.IEditorInput)
*/
public void init(IEditorSite site, IEditorInput input)
throws PartInitException {
try {
super.init(site, input);
} catch (Exception e) {
MessageDialog.openError(null,
EditorMessages.FacesConfigEditor_Error_OpenModel_Title,
EditorMessages.FacesConfigEditor_Error_OpenModel);
throw new PartInitException(
EditorMessages.FacesConfigEditor_Error_OpenModel);
}
setPartName(input.getName());
if (!isValidInput(input)) {
PlatformUI.getWorkbench().getActiveWorkbenchWindow()
.getActivePage().openEditor(input,
"org.eclipse.ui.DefaultTextEditor"); //$NON-NLS-1$
close(false);
return;
}
createActions();
ResourcesPlugin.getWorkspace().addResourceChangeListener(
resourceChangeListener, IResourceChangeEvent.POST_CHANGE);
}
/*
* @see org.eclipse.ui.part.EditorPart#setInput(org.eclipse.ui.IEditorInput)
*/
protected void setInput(IEditorInput input)
{
isWebProject = matches(input);
super.setInput(input);
IFile inputFile = (IFile) input.getAdapter(IFile.class);
if (inputFile != null)
{
final IProject project = inputFile.getProject();
final IPath inputPath = inputFile.getFullPath();
_modelLoader = new ModelLoader();
_modelLoader.load(project, inputPath, isWebProject, _addPagesTask);
}
}
protected void addPages()
{
// try loading wait page
// if we get to here before model load completes,
// then wait page will give the user the indication
// that something is happening in the background before
// the editor full loads.
// if the model is already loaded, this call should do nothing
_addPagesTask.maybeAddWaitPage();
}
/**
* This runnable is used to used to manage the loading of the
* editor pages for editor in a deferred fashion. Because the model
* loading for this editor can be noticably long and (unfortunately)
* may involve socket calls that block, loadModel(), runs this on a
* separate thread. This class is intended to be used in two ways:
*
* 1) by the model loading code to signal it is finished by executing
* the run() via a display.asyncExec().
*
* 2) by the addPages() call back on the the main editor as a way to
* load a "Please wait for loading" page if the loading is still running
* by the time the editor is ready to visualize itself.
*
* Note that in both cases methods of this class *must* be running on the
* main display thread.
*
* @author cbateman
*
*/
private class AddPagesTask extends ModelLoader.ModelLoaderComplete
{
private final AtomicBoolean _arePagesLoaded = new AtomicBoolean(false); // set to true when the regular editor pages are loaded
private FormPage _waitPage;
private List<Runnable> _deferredRunnables = new ArrayList<Runnable>();
/**
* If the editor pages are loaded, runnable.run() is invoked immediately
* If the editor pages are not loaded yet, runnable is queued and will be
* executed in the order they are added immediately after the pages are loaded
*
* @param runnable
*/
public synchronized void pageSafeExecute(Runnable runnable)
{
if (!_isDisposed)
{
if (!_arePagesLoaded.get())
{
_deferredRunnables.add(runnable);
}
else
{
runnable.run();
}
}
}
/**
* @return true if the pages are loaded
*/
public synchronized boolean getArePagesLoaded()
{
return _arePagesLoaded.get();
}
/**
* Remove the wait page if present.
*/
public synchronized void removeWaitPage()
{
if (_waitPage != null)
{
int index = _waitPage.getIndex();
if (index >= 0)
{
removePage(index);
}
}
}
/**
* Add the wait page if the main pages aren't already loaded
*/
public synchronized void maybeAddWaitPage()
{
// only load the wait page if the other pages haven't been loaded
if (!getArePagesLoaded())
{
_waitPage = new WaitForLoadPage(FacesConfigEditor.this, "WaitForLoad", EditorMessages.FacesConfigEditor_WaitForLoad_EditorTabTitle); //$NON-NLS-1$
try
{
addPage(0,_waitPage);
}
catch(PartInitException pie)
{
_waitPage =null;
EditorPlugin.getDefault().getLog().log(
new Status(IStatus.ERROR, EditorPlugin.getPluginId(),
IStatus.OK, pie.getMessage() == null ? "" : pie //$NON-NLS-1$
.getMessage(), pie));
}
}
}
/**
* Must be run on the UI thread
*/
public void doRun(FacesConfigArtifactEdit edit)
{
synchronized(this)
{
// ensure wait page gets removed
removeWaitPage();
if (!getArePagesLoaded()
&& !_isDisposed) // NOTE: we assume that access to variable does not need to
// to be synchronous since this method must
// be run on the UI thread. The only way
// that isDisposed should be true is if model loading took a long
// time and the user closed the editor before it completed (trigger dispose to be called)
{
try
{
if (isWebProject && edit != null && edit.getFacesConfig() != null)
{
// only add the intro editor if the preference
// is set to do so.
if (GEMPreferences.getShowIntroEditor())
{
IntroductionPage page1 = new IntroductionPage(FacesConfigEditor.this);
addPage(page1, null);
}
IFormPage overviewPage = new OverviewPage(FacesConfigEditor.this);
addPage(overviewPage, null);
// Page flow
createAndAddPageflowPage();
// pages
IFormPage managedBeanPage = new ManagedBeanPage(FacesConfigEditor.this);
managedBeanPageID = addPage(managedBeanPage, null);
IFormPage componentsPage = new ComponentsPage(FacesConfigEditor.this);
componentsPageID = addPage(componentsPage, null);
IFormPage othersPage = new OthersPage(FacesConfigEditor.this);
othersPageID = addPage(othersPage, null);
}
sourcePage = new StructuredTextEditor();
sourcePage.setEditorPart(FacesConfigEditor.this);
sourcePageId = addPage(sourcePage, FacesConfigEditor.this.getEditorInput());
setPageText(sourcePageId,
EditorMessages.FacesConfigEditor_Source_TabName);
sourcePage.update();
// default active page to 0
setActivePage(0);
// execute deferred runnables
for (Runnable runnable : _deferredRunnables)
{
runnable.run();
}
// flag the fact that the regular editor pages have been added
_arePagesLoaded.set(true);
} catch (PartInitException e) {
EditorPlugin.getDefault().getLog().log(
new Status(IStatus.ERROR, EditorPlugin.getPluginId(),
IStatus.OK, e.getMessage() == null ? "" : e //$NON-NLS-1$
.getMessage(), e));
}
}
}
}
}
/**
* Creates the pageflow page of the multi-page editor.
* @throws PartInitException
*/
protected void createAndAddPageflowPage() throws PartInitException {
pageflowPage = new PageflowEditor(this);
pageflowPageID = addPage(pageflowPage, getEditorInput());
setPageText(pageflowPageID,
EditorMessages.FacesConfigEditor_Pageflow_TabName);
addPageActionRegistry(pageflowPage);
pageflowPage.getModelsTransform().setFacesConfig(getFacesConfig());
pageflowPage.getModelsTransform().setPageflow(
pageflowPage.getPageflow());
boolean fornew = pageflowPage.getModelsTransform()
.updatePageflowModelFromEMF();
pageflowPage.setGraphicalViewerContents(pageflowPage.getPageflow());
if (fornew) {
PageflowLayoutManager.getInstance().layoutPageflow(
pageflowPage.getPageflow());
}
pageflowPage.getModelsTransform().setListenToNotify(true);
}
/**
* TODO: this is used only for testing
* @return the page flow editor
*/
public PageflowEditor getPageflowPage() {
return pageflowPage;
}
/**
* get the action's registry of sub pages.
* @param page
*
*/
protected void addPageActionRegistry(IEditorPart page) {
if (page != null) {
ActionRegistry pageActionRegisty = (ActionRegistry) page
.getAdapter(ActionRegistry.class);
if (pageActionRegisty != null) {
for (Iterator iter = pageActionRegisty.getActions(); iter
.hasNext();) {
getActionRegistry().registerAction((IAction) iter.next());
}
}
}
}
/** the editor's action registry */
private ActionRegistry actionRegistry = null;
/**
* Returns the action registry of this editor.
*
* @return - the action registry
*/
protected ActionRegistry getActionRegistry() {
if (null == actionRegistry)
actionRegistry = new ActionRegistry();
return actionRegistry;
}
/**
* Returns the root object of the configuration model.
*
* @return the root object. Should not, but may return null.
*/
public FacesConfigType getFacesConfig()
{
FacesConfigArtifactEdit edit = _modelLoader.getEdit();
if (edit != null)
{
return edit.getFacesConfig();
}
return null;
}
/*
* @see org.eclipse.ui.ISaveablePart#isDirty()
*/
public boolean isDirty() {
return ((BasicCommandStack) editingDomain.getCommandStack())
.isSaveNeeded()
|| super.isDirty();
}
/**
* This class listens for command stack changes of the pages contained in
* this editor and decides if the editor is dirty or not.
*/
private class MultiPageCommandStackListener implements CommandStackListener {
/** the observed command stacks */
private List commandStacks = new ArrayList(2);
/** to get the editorpart from command stack */
private HashMap mapEditorCommandStack = new HashMap();
private boolean saveLocation = false;
/**
* Adds a <code>CommandStack</code> to observe.
*
* @param commandStack
* @param editor
*/
public void addCommandStack(CommandStack commandStack,
IEditorPart editor) {
if (commandStack == null)
return;
if (mapEditorCommandStack.get(commandStack) == editor)
return;
commandStacks.add(commandStack);
commandStack.addCommandStackListener(this);
mapEditorCommandStack.put(commandStack, editor);
}
/**
* set the dirty status for the models of different editor
*
* @param editor -
* editor, e.g., pageflow or databinding page.
* @param dirty -
* true or false
*/
private void setEditorDirty(IEditorPart editor, boolean dirty) {
// do nothing
}
/** the list of action ids that are to CommandStack actions */
private List stackActionIDs = new ArrayList();
/**
* Updates the specified actions.
*
* @param actionIds -
* the list of ids of actions to update
*/
private void updateActions(List actionIds) {
for (Iterator ids = actionIds.iterator(); ids.hasNext();) {
IAction action = getActionRegistry().getAction(ids.next());
if (null != action && action instanceof UpdateAction) {
((UpdateAction) action).update();
}
}
}
/*
* (non-Javadoc)
*
* @see CommandStackListener#commandStackChanged(java.util.EventObject)
*/
public void commandStackChanged(EventObject event) {
// enable or disable the actions
updateActions(stackActionIDs);
if (((CommandStack) event.getSource()).isDirty()) {
// set the editor's model dirty status
setEditorDirty((IEditorPart) mapEditorCommandStack
.get(event.getSource()), true);
// at least one command stack is dirty,
// so the multi page editor is dirty too
setDirty(true);
} else {
// set the editor's model dirty status, if it is from not save
// location.
if (!saveLocation) {
setEditorDirty((IEditorPart) mapEditorCommandStack
.get(event.getSource()), true);
setDirty(true);
} else {
setDirty(false);
}
}
}
/** the pageflow page editor's dirty state */
private boolean isDirty = false;
/**
* Changes the dirty state.
*
* @param dirty -
* dirty state
*/
public void setDirty(boolean dirty) {
if (isDirty != dirty) {
isDirty = dirty;
firePropertyChange(IEditorPart.PROP_DIRTY);
}
}
/**
* Disposed the listener
*/
public void dispose() {
for (Iterator stacks = commandStacks.iterator(); stacks.hasNext();) {
((CommandStack) stacks.next()).removeCommandStackListener(this);
}
commandStacks.clear();
}
/**
* Marks every observed command stack beeing saved. This method should
* be called whenever the editor/model was saved.
*/
public void markSaveLocations() {
saveLocation = true;
for (Iterator stacks = commandStacks.iterator(); stacks.hasNext();) {
CommandStack stack = (CommandStack) stacks.next();
stack.markSaveLocation();
}
saveLocation = false;
}
/**
* Flushes every observed command stack and resets the save location to
* zero.
*/
public void flush() {
for (Iterator stacks = commandStacks.iterator(); stacks.hasNext();) {
CommandStack stack = (CommandStack) stacks.next();
stack.flush();
}
}
}
/** the <code>CommandStackListener</code> */
private MultiPageCommandStackListener multiPageCommandStackListener = null;
/**
* Returns the global command stack listener.
*
* @return the <code>CommandStackListener</code>
*/
protected MultiPageCommandStackListener getMultiPageCommandStackListener() {
if (null == multiPageCommandStackListener)
multiPageCommandStackListener = new MultiPageCommandStackListener();
return multiPageCommandStackListener;
}
/*
* @see org.eclipse.ui.ISaveablePart#doSave(org.eclipse.core.runtime.IProgressMonitor)
*/
public void doSave(IProgressMonitor monitor) {
// do the work within an operation because this is a long running
// activity that modifies the workbench
WorkspaceModifyOperation operation = new WorkspaceModifyOperation() {
public void execute(IProgressMonitor monitor_) {
try {
if (isWebProject &&
_modelLoader.getEdit() != null) {
// modelResource.save(Collections.EMPTY_MAP);
_modelLoader.getEdit()
.getDeploymentDescriptorResource().save(
Collections.EMPTY_MAP);
IFile file = ((IFileEditorInput) getEditorInput())
.getFile();
pageflowPage.doSave(file, monitor_);
}
sourcePage.doSave(monitor_);
getMultiPageCommandStackListener().markSaveLocations();
} catch (Exception e) {
EditorPlugin.getDefault().getLog().log(
new Status(IStatus.ERROR, EditorPlugin
.getPluginId(), IStatus.OK,
e.getMessage() == null ? "" : e //$NON-NLS-1$
.getMessage(), e));
}
}
};
try {
// commit all pending changes in form pages
for (Iterator iter = pages.iterator(); iter.hasNext();) {
Object obj = iter.next();
if (obj instanceof FormPage) {
((FormPage) obj).doSave(monitor);
}
// else if (obj instanceof PageflowEditor) {
// ((PageflowEditor) obj).doSave(monitor);
// }
}
operation.run(null);// .run(true, false,
// operation;
// runs the operation, and shows progress
// new ProgressMonitorDialog();
// refresh the necessary state
((BasicCommandStack) editingDomain.getCommandStack()).saveIsDone();
editorDirtyStateChanged();
} catch (Exception e) {
EditorPlugin.getDefault().getLog().log(
new Status(IStatus.ERROR, EditorPlugin.getPluginId(),
IStatus.OK, e.getMessage(), e));
}
}
public void doSaveAs() {
SaveAsDialog saveAsDialog = new SaveAsDialog(getSite().getShell());
saveAsDialog.open();
IPath path = saveAsDialog.getResult();
if (path != null) {
IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
if (file != null) {
doSaveAs(URI.createPlatformResourceURI(file.getFullPath()
.toString(), false), new FileEditorInput(file));
}
}
}
/**
* @param uri
* @param editorInput
*/
protected void doSaveAs(URI uri, IEditorInput editorInput) {
editingDomain.getResourceSet().getResources().get(0)
.setURI(uri);
setInputWithNotify(editorInput);
setPartName(editorInput.getName());
IProgressMonitor progressMonitor = getActionBars()
.getStatusLineManager() != null ? getActionBars()
.getStatusLineManager().getProgressMonitor()
: new NullProgressMonitor();
doSave(progressMonitor);
}
public boolean isSaveAsAllowed() {
return true;
}
/**
* Returns the <code>TabbedPropertySheetPage</code> for this editor.
*
* @return - the <code>TabbedPropertySheetPage</code>
*/
protected IPropertySheetPage getPropertySheetPage() {
return new TabbedPropertySheetPage(
new ITabbedPropertySheetPageContributor() {
public String getContributorId() {
return EDITOR_ID;
}
});
}
/** the delegating ZoomManager */
private DelegatingZoomManager delegatingZoomManager = null;
/**
* check whether the input is related with IFile.
*
* @param input
* @return
*/
private boolean isValidInput(IEditorInput input) {
if (input != null) {
IFile file = (IFile) input.getAdapter(IResource.class);
if (file != null) {
return true;
}
}
return false;
}
/**
* Returns the <code>DelegatingZoomManager</code> for this editor.
*
* @return - the <code>DelegatingZoomManager</code>
*/
protected DelegatingZoomManager getDelegatingZoomManager() {
if (!isValidInput(getEditorInput()) || !isWebProject || !_addPagesTask.getArePagesLoaded()) {
return null;
}
if (null == delegatingZoomManager) {
delegatingZoomManager = new DelegatingZoomManager();
delegatingZoomManager
.setCurrentZoomManager((ZoomManager) pageflowPage
.getAdapter(ZoomManager.class));
}
return delegatingZoomManager;
}
/** the delegating CommandStack */
private DelegatingCommandStack delegatingCommandStack = null;
/**
* Returns the <code>CommandStack</code> for this editor.
*
* @return - the <code>CommandStack</code>
*/
public DelegatingCommandStack getDelegatingCommandStack() {
if (null == delegatingCommandStack) {
delegatingCommandStack = new DelegatingCommandStack();
}
return delegatingCommandStack;
}
/*
* @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
*/
public Object getAdapter(Class adapter) {
if (adapter == IEditingDomainProvider.class) {
return new IEditingDomainProvider() {
public EditingDomain getEditingDomain() {
return editingDomain;
}
};
}
if (adapter == EditingDomain.class) {
return editingDomain;
}
if (adapter == AdapterFactory.class) {
return adapterFactory;
}
if (adapter == IEditorPart.class) {
return getActiveEditor();
}
if (adapter == CommandStack.class) {
return getDelegatingCommandStack();
}
if (adapter == ZoomManager.class) {
return getDelegatingZoomManager();
}
if (adapter == ActionRegistry.class) {
return getActionRegistry();
}
if (adapter == IGotoMarker.class) {
return new IGotoMarker() {
public void gotoMarker(final IMarker marker) {
// this may be called on an editor open (i.e. double-click the Problems view)
// so ensure it runs safely with respect to the page load
_addPagesTask.pageSafeExecute(new Runnable()
{
public void run()
{
FacesConfigEditor.this.gotoMarker(marker);
}
});
}
};
}
if (adapter == StructuredTextEditor.class) {
return sourcePage;
}
if (adapter == IContentOutlinePage.class) {
return getOutlinePage();
}
if (adapter == IPropertySheetPage.class) {
return getPropertySheetPage();
}
if (adapter == IProject.class) {
return getProject();
}
if (adapter == CTabFolder.class) {
return getContainer();
}
if (adapter == IOpenPage.class) {
return new IOpenPage() {
public void setActiveEditorPage(String pageID) {
FacesConfigEditor.this.setActiveEditorPage(pageID);
}
};
}
return super.getAdapter(adapter);
}
private EMFCommandStackGEFAdapter sourceCommandStack;
/**
* get or create the source page's GEF command stack based on its EMF
* command stack.
*
* @return
*/
private CommandStack getSourcePageCommandStack() {
if (sourceCommandStack == null) {
IDocument doc = sourcePage.getDocumentProvider().getDocument(getEditorInput());
if (doc instanceof IStructuredDocument) {
IStructuredModel model = StructuredModelManager.getModelManager().getExistingModelForEdit(doc);
if (model == null) {
model = StructuredModelManager.getModelManager().getModelForEdit((IStructuredDocument) doc);
}
sourceCommandStack = new EMFCommandStackGEFAdapter(
(BasicCommandStack) model.getUndoManager()
.getCommandStack());
}
else
{
EditorPlugin.getDefault().getLog().log(
new Status(IStatus.ERROR, EditorPlugin.getPluginId(), 0,
"Error getting undo stack for Faces Config editor. Undo may be disabled", //$NON-NLS-1$
new Throwable()));
}
}
return sourceCommandStack;
}
/** the list of action ids that are to CommandStack actions */
// private List stackActionIDs = new ArrayList();
/** the list of action ids that are editor actions */
private List editorActionIDs = new ArrayList();
/**
* Adds an editor action to this editor.
* <p>
* Editor actions are actions that depend and work on the editor.
*
* @param action -
* the editor action
*/
protected void addEditorAction(EditorPartAction action) {
getActionRegistry().registerAction(action);
editorActionIDs.add(action.getId());
}
/**
* Creates different kinds of actions and registers them to the
* ActionRegistry.
*/
protected void createActions() {
// register save action
addEditorAction(new SaveAction(this));
}
/**
* Indicates that the current page has changed.
* <p>
* We update the DelegatingCommandStack, OutlineViewer and other things
* here. //
*/
protected void currentPageChanged() {
IEditorPart activeEditor = getActiveEditor();
if (activeEditor == null) {
return;
}
// update command stack
CommandStack cmdStack = null;
if (activeEditor == pageflowPage) {
cmdStack = (CommandStack) activeEditor
.getAdapter(CommandStack.class);
} else if (activeEditor == sourcePage)// other page will delegate the
// GEF command stack to source
// page's.
{
cmdStack = this.getSourcePageCommandStack();
}
// Add command stacks
getMultiPageCommandStackListener().addCommandStack(cmdStack,
activeEditor);
getDelegatingCommandStack().setCurrentCommandStack(cmdStack);
// enable or disable the actions
// updateActions(stackActionIDs);
// update zoom actions
ZoomManager zoomManager = null;
zoomManager = (ZoomManager) activeEditor.getAdapter(ZoomManager.class);
if (zoomManager != null) {
getDelegatingZoomManager().setCurrentZoomManager(zoomManager);
}
IEditorActionBarContributor contributor = getEditorSite()
.getActionBarContributor();
if (contributor != null
&& contributor instanceof FacesConfigActionBarContributor) {
((FacesConfigActionBarContributor) contributor)
.setActivePage(activeEditor);
}
}
/*
* (non-Javadoc)
*
* @see MultiPageEditorPart#pageChange(int)
*/
protected void pageChange(int newPageIndex) {
super.pageChange(newPageIndex);
// getActionBarContributor().setActivePage(getActiveEditor());
// refresh content depending on current page
currentPageChanged();
}
public void dispose()
{
// signal that we have been disposed
// do this before anything else
_isDisposed = true;
_modelLoader.dispose();
ResourcesPlugin.getWorkspace().removeResourceChangeListener(
resourceChangeListener);
adapterFactory.dispose();
if (this.outlinePage != null) {
outlinePage.dispose();
}
super.dispose();
}
/**
* get the project of the faces config file that the editor is working on.
*
* @return IProject
*/
public IProject getProject() {
if (currentProject == null) {
if (_modelLoader.getEdit() != null) {
IFile file = _modelLoader.getEdit().getFile();
if (file != null)
currentProject = file.getProject();
}
}
return currentProject;
}
public EditingDomain getEditingDomain() {
return editingDomain;
}
/**
* Returns the <code>IContentOutlinePage</code> for this editor.
*
* @return - the <code>IContentOutlinePage</code>
*/
protected IContentOutlinePage getOutlinePage() {
if (null == outlinePage) {
outlinePage = new MultiPageEditorOutlinePage();
}
return outlinePage;
}
public void addSelectionChangedListener(ISelectionChangedListener listener) {
selectionChangedListeners.add(listener);
}
public ISelection getSelection() {
return editorSelection;
}
public void removeSelectionChangedListener(
ISelectionChangedListener listener) {
selectionChangedListeners.remove(listener);
}
public void setSelection(ISelection selection) {
editorSelection = selection;
for (Iterator listeners = selectionChangedListeners.iterator(); listeners
.hasNext();) {
ISelectionChangedListener listener = (ISelectionChangedListener) listeners
.next();
listener
.selectionChanged(new SelectionChangedEvent(this, selection));
}
}
private void gotoMarker(IMarker marker) {
setActivePage(sourcePageId);
IDE.gotoMarker(this.sourcePage, marker);
}
/**
* FIXME: this is used only for testing. Should isolate better
* @return the action bar
*/
public FacesConfigActionBarContributor getActionBarContributor() {
return (FacesConfigActionBarContributor) getEditorSite()
.getActionBarContributor();
}
private IActionBars getActionBars() {
return getActionBarContributor().getActionBars();
}
/**
* Shows a dialog that asks if conflicting changes should be discarded.
* @return the user's response.
*/
protected boolean handleDirtyConflict() {
return MessageDialog
.openQuestion(
getSite().getShell(),
EditorMessages.FacesConfigEditor_ErrorHandlingUndoConflicts_DialogTitle,
EditorMessages.FacesConfigEditor_ErrorHandlingUndoConflicts_DialogMessage);
}
/**
* Handles what to do with changed resources on activation.
*
* @generated
*/
protected void handleChangedResources() {
if (!changedResources.isEmpty()
&& (!isDirty() || handleDirtyConflict())) {
editingDomain.getCommandStack().flush();
for (Iterator i = changedResources.iterator(); i.hasNext();) {
Resource resource = (Resource) i.next();
if (resource.isLoaded()) {
resource.unload();
try {
resource.load(Collections.EMPTY_MAP);
} catch (IOException exception) {
EditorPlugin.getDefault().getLog().log(
new Status(IStatus.ERROR, EditorPlugin
.getPluginId(), IStatus.OK, exception
.getMessage() == null ? "" : exception //$NON-NLS-1$
.getMessage(), exception));
}
}
}
}
}
/**
* TODO this is used only for testing. Should be able to remove if we
* go to true automated UI testing
* @param pageID
*/
public void setActiveEditorPage(String pageID) {
if (pageID.equals(PageflowEditor.PAGE_ID)) {
setActivePage(pageflowPageID);
} else if (pageID.equals(ManagedBeanPage.PAGE_ID)) {
setActivePage(managedBeanPageID);
} else if (pageID.equals(ComponentsPage.PAGE_ID)) {
setActivePage(componentsPageID);
} else if (pageID.equals(OthersPage.PAGE_ID)) {
setActivePage(othersPageID);
}
}
private boolean matches(IEditorInput input) {
final IResource file = (IResource) input.getAdapter(IResource.class);
boolean hasWebFacet = false;
boolean hasJSFFacet = false;
if (file != null) {
final IProject project = file.getProject();
if (project != null) {
try {
final IFacetedProject facetedProject = ProjectFacetsManager
.create(project);
if (facetedProject != null) {
final Set facets = facetedProject.getProjectFacets();
for (final Iterator it = facets.iterator(); it
.hasNext();) {
final IProjectFacetVersion version = (IProjectFacetVersion) it
.next();
IProjectFacet facet = version.getProjectFacet();
if (IJSFCoreConstants.JSF_CORE_FACET_ID.equals(facet.getId())) {
hasJSFFacet = true;
} else if ("jst.web".equals(facet.getId())) { //$NON-NLS-1$
hasWebFacet = true;
}
}
}
} catch (CoreException ex) {
EditorPlugin.getDefault().getLog().log(
new Status(IStatus.ERROR, EditorPlugin
.getPluginId(), IStatus.OK,
ex.getMessage() == null ? "" : ex //$NON-NLS-1$
.getMessage(), ex));
}
}
}
return hasWebFacet && hasJSFFacet;
}
/**
* DANGER! This call is for testing only! Should not be used,
* even internally, by production code.
* @param timeoutMs the time to wait in milliseconds
* @throws InterruptedException
*/
public void doPageLoad(long timeoutMs) throws InterruptedException
{
_modelLoader.waitForLoad(timeoutMs);
_addPagesTask.doRun(_modelLoader.getEdit());
}
}