blob: a341b7b42182651940efb647787b4e6f38cdfb4c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011-2012 EclipseSource Muenchen GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Eugen Neufeld - initial API and implementation
*
*******************************************************************************/
package org.eclipse.emf.ecp.spi.ui.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecp.core.ECPProject;
import org.eclipse.emf.ecp.core.ECPProjectManager;
import org.eclipse.emf.ecp.core.ECPProvider;
import org.eclipse.emf.ecp.core.ECPRepository;
import org.eclipse.emf.ecp.core.exceptions.ECPProjectWithNameExistsException;
import org.eclipse.emf.ecp.core.util.ECPCheckoutSource;
import org.eclipse.emf.ecp.core.util.ECPContainer;
import org.eclipse.emf.ecp.core.util.ECPProperties;
import org.eclipse.emf.ecp.core.util.ECPUtil;
import org.eclipse.emf.ecp.internal.ui.Activator;
import org.eclipse.emf.ecp.internal.ui.Messages;
import org.eclipse.emf.ecp.internal.ui.dialogs.DeleteDialog;
import org.eclipse.emf.ecp.internal.ui.dialogs.ProjectPropertiesDialog;
import org.eclipse.emf.ecp.internal.ui.dialogs.RepositoryPropertiesDialog;
import org.eclipse.emf.ecp.internal.ui.util.HandlerHelperUtil;
import org.eclipse.emf.ecp.internal.wizards.AddRepositoryWizard;
import org.eclipse.emf.ecp.internal.wizards.CheckoutProjectWizard;
import org.eclipse.emf.ecp.internal.wizards.CreateProjectWizard;
import org.eclipse.emf.ecp.internal.wizards.FilterModelElementWizard;
import org.eclipse.emf.ecp.spi.common.ui.CheckedModelClassComposite;
import org.eclipse.emf.ecp.spi.common.ui.SelectModelElementWizard;
import org.eclipse.emf.ecp.spi.common.ui.composites.SelectionComposite;
import org.eclipse.emf.ecp.spi.core.InternalProject;
import org.eclipse.emf.ecp.spi.core.InternalProvider;
import org.eclipse.emf.ecp.spi.core.InternalProvider.LifecycleEvent;
import org.eclipse.emf.ecp.ui.common.AddRepositoryComposite;
import org.eclipse.emf.ecp.ui.common.CheckoutProjectComposite;
import org.eclipse.emf.ecp.ui.common.CreateProjectComposite;
import org.eclipse.emf.ecp.ui.common.ECPCompositeFactory;
import org.eclipse.emf.ecp.ui.util.ECPModelElementOpenTester;
import org.eclipse.emf.ecp.ui.util.ECPModelElementOpener;
import org.eclipse.emf.ecp.ui.util.ECPModelElementOpenerWithContext;
import org.eclipse.emf.edit.command.ChangeCommand;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.dialogs.ListSelectionDialog;
/**
* This is a utility class providing commonly necessary methods.
*
* @author Eugen Neufeld
* @since 1.4
*/
public final class ECPHandlerHelper {
private ECPHandlerHelper() {
}
private static void showError(Shell shell, String title, String message) {
MessageDialog.openError(shell, title, message);
}
/**
* This method allows to checkout a list of {@link ECPCheckoutSource} into the workspace.
*
* @param checkoutObjects the List of {@link ECPCheckoutSource} to checkout
* @param shell the {@link Shell} to use for diplaying UI
*/
public static void checkout(final List<ECPCheckoutSource> checkoutObjects, final Shell shell) {
for (final ECPCheckoutSource checkoutSource : checkoutObjects) {
final CheckoutProjectComposite checkoutCompposite = ECPCompositeFactory
.getCheckoutProjectComposite(checkoutSource);
final CheckoutProjectWizard wizard = new CheckoutProjectWizard();
wizard.setCompositeProvider(checkoutCompposite);
final WizardDialog wd = new WizardDialog(shell, wizard);
final int result = wd.open();
if (result == Window.OK) {
final String projectName = checkoutCompposite.getProjectName();
final ECPProperties projectProperties = checkoutCompposite.getProjectProperties();
try {
checkoutSource.checkout(projectName, projectProperties);
} catch (final ECPProjectWithNameExistsException ex) {
showError(shell, "Cannot checkout project", "A project with name " + projectName //$NON-NLS-1$ //$NON-NLS-2$
+ " already exists in the workspace."); //$NON-NLS-1$
}
}
}
}
/**
* This helper method is used to delete model elements from a project.
*
* @param project the project to delete from
* @param objects the model elements to delete
*/
public static void deleteModelElement(final ECPProject project, final Collection<Object> objects) {
if (project != null) {
project.deleteElements(objects);
}
}
/**
* This method creates a new project.
*
* @param shell the shell for displaying the wizard
* @return the created {@link ECPProject}
*/
public static ECPProject createProject(final Shell shell) {
final List<ECPProvider> providers = new ArrayList<ECPProvider>();
for (final ECPProvider provider : ECPUtil.getECPProviderRegistry().getProviders()) {
if (provider.hasCreateProjectWithoutRepositorySupport()) {
providers.add(provider);
}
}
if (providers.size() == 0) {
// TODO language
showError(shell, "No Provider", "Please check if a suitable provider is installed."); //$NON-NLS-1$//$NON-NLS-2$
return null;
}
final CreateProjectComposite createProjectComposite = ECPCompositeFactory.getCreateProjectComposite(providers);
final CreateProjectWizard wizard = new CreateProjectWizard();
wizard.setCompositeProvider(createProjectComposite);
final WizardDialog wd = new WizardDialog(shell, wizard);
final int result = wd.open();
if (result == Window.OK) {
final ECPProvider selectedProvider = createProjectComposite.getProvider();
if (selectedProvider == null) {
showError(shell, "No project created", "Please check if a suitable provider is installed."); //$NON-NLS-1$//$NON-NLS-2$
return null;
}
final ECPProperties projectProperties = createProjectComposite.getProperties();
final String projectName = createProjectComposite.getProjectName();
ECPProject project = null;
try {
project = ECPUtil.getECPProjectManager()
.createProject(selectedProvider, projectName, projectProperties);
} catch (final ECPProjectWithNameExistsException ex) {
showError(shell, "No project created", "A project with name " + projectName //$NON-NLS-1$ //$NON-NLS-2$
+ " already exists in the workspace."); //$NON-NLS-1$
return null;
}
if (project == null) {
showError(shell, "No project created", "Please check the log."); //$NON-NLS-1$//$NON-NLS-2$
return null;
}
((InternalProvider) selectedProvider).handleLifecycle(project, LifecycleEvent.CREATE);
project.open();
return project;
}
return null;
}
/**
* Add a new {@link EObject} to the root of an {@link ECPProject}.
*
* @param ecpProject the {@link ECPProject} to add the {@link EObject} to
* @param shell the {@link Shell} used to display the UI
* @param open whether to open the corresponding editor or not
* @return the created {@link EObject}
*/
public static EObject addModelElement(final ECPProject ecpProject, final Shell shell, boolean open) {
final EClass newMEType = openSelectModelElementWizard(ecpProject, shell, open);
if (ecpProject != null && newMEType != null) {
// create ME
final EObject newMEInstance = createModelElementInstance(newMEType);
ecpProject.getEditingDomain().getCommandStack().execute(new ChangeCommand(newMEInstance) {
@Override
protected void doExecute() {
ecpProject.getContents().add(newMEInstance);
}
});
if (open) {
openModelElement(newMEInstance, ecpProject);
}
return newMEInstance;
}
return null;
}
/**
* @param resource the resource
* @param activeShell current active shell
* @param open if model element should be directly opened in an editor after it is added to project.
*
* @return the created model element.
*/
public static EObject addModelElement(final Resource resource, Shell activeShell, boolean open) {
final ECPProject ecpProject = ECPUtil.getECPProjectManager().getProject(resource);
if (ecpProject == null) {
return null;
}
final EClass newMEType = openSelectModelElementWizard(ecpProject, activeShell, open);
if (resource != null && newMEType != null) {
// create ME
final EObject newMEInstance = createModelElementInstance(newMEType);
ecpProject.getEditingDomain().getCommandStack().execute(new ChangeCommand(newMEInstance) {
@Override
protected void doExecute() {
resource.getContents().add(newMEInstance);
}
});
if (open) {
openModelElement(newMEInstance, ecpProject);
}
return newMEInstance;
}
return null;
}
/**
* @param newMEType
* @return
*/
private static EObject createModelElementInstance(final EClass newMEType) {
final EPackage ePackage = newMEType.getEPackage();
final EObject newMEInstance = ePackage.getEFactoryInstance().create(newMEType);
return newMEInstance;
}
/**
* @param ecpProject
* @param shell
* @param open
* @return
*/
private static EClass openSelectModelElementWizard(final ECPProject ecpProject, final Shell shell, boolean open) {
final SelectionComposite<TreeViewer> helper = ECPCompositeFactory.getSelectModelClassComposite(ecpProject);
final SelectModelElementWizard wizard = new SelectModelElementWizard(
Messages.NewModelElementWizardHandler_Title,
Messages.NewModelElementWizard_WizardTitle_AddModelElement,
Messages.NewModelElementWizard_PageTitle_AddModelElement,
Messages.NewModelElementWizard_PageDescription_AddModelElement);
wizard.setCompositeProvider(helper);
final WizardDialog wd = new WizardDialog(shell, wizard);
final int wizardResult = wd.open();
if (wizardResult == Window.OK) {
final Object[] selection = helper.getSelection();
if (selection != null && selection.length > 0) {
return (EClass) selection[0];
}
}
return null;
}
/**
* This method allows the user to filter the visible packages and classes.
*
* @param ecpProject the project to filter
* @param shell the {@link Shell} to use for UI
*/
public static void filterProjectPackages(final ECPProject ecpProject, final Shell shell) {
final Set<EPackage> ePackages = ECPUtil.getAllRegisteredEPackages();
final CheckedModelClassComposite checkedModelComposite = ECPCompositeFactory
.getCheckedModelClassComposite(ePackages);
final Set<Object> initialSelectionSet = new HashSet<Object>();
initialSelectionSet.addAll(((InternalProject) ecpProject).getVisiblePackages());
initialSelectionSet.addAll(((InternalProject) ecpProject).getVisibleEClasses());
checkedModelComposite.setInitialSelection(initialSelectionSet.toArray());
final FilterModelElementWizard wizard = new FilterModelElementWizard();
wizard.setCompositeProvider(checkedModelComposite);
final WizardDialog wd = new WizardDialog(shell, wizard);
final int wizardResult = wd.open();
if (wizardResult == Window.OK) {
final Object[] dialogSelection = checkedModelComposite.getChecked();
final Set<EPackage> filtererdPackages = new HashSet<EPackage>();
final Set<EClass> filtererdEClasses = new HashSet<EClass>();
for (final Object object : dialogSelection) {
if (object instanceof EPackage) {
filtererdPackages.add((EPackage) object);
} else if (object instanceof EClass) {
final EClass eClass = (EClass) object;
if (!filtererdPackages.contains(eClass.getEPackage())) {
filtererdEClasses.add(eClass);
}
}
}
((InternalProject) ecpProject).setVisiblePackages(filtererdPackages);
((InternalProject) ecpProject).setVisibleEClasses(filtererdEClasses);
}
}
/**
* This method created a new Repository.
*
* @param shell the shell for the Wizard
* @return the created {@link ECPRepository}
*/
public static ECPRepository createRepository(final Shell shell) {
final AddRepositoryComposite addRepositoryComposite = ECPCompositeFactory.getAddRepositoryComposite();
final AddRepositoryWizard wizard = new AddRepositoryWizard();
wizard.setCompositeProvider(addRepositoryComposite);
final WizardDialog wd = new WizardDialog(shell, wizard);
final int wizardResult = wd.open();
if (wizardResult == Window.OK) {
final ECPRepository ecpRepository = ECPUtil.getECPRepositoryManager().addRepository(
addRepositoryComposite.getProvider(), addRepositoryComposite.getRepositoryName(),
addRepositoryComposite.getRepositoryLabel() == null ? "" : addRepositoryComposite.getRepositoryLabel(), //$NON-NLS-1$
addRepositoryComposite.getRepositoryDescription() == null ? "" : addRepositoryComposite //$NON-NLS-1$
.getRepositoryDescription(),
addRepositoryComposite.getProperties());
return ecpRepository;
}
return null;
}
/**
* This method closes/opens an array of ECPProject.
*
* @param closeables the {@link ECPProject}s to change the state for
* @param currentType the action to do
*/
public static void changeCloseState(ECPProject[] closeables, String currentType) {
for (final ECPProject closeable : closeables) {
if ("open".equalsIgnoreCase(currentType)) { //$NON-NLS-1$
closeable.open();
} else if ("close".equalsIgnoreCase(currentType)) { //$NON-NLS-1$
closeable.close();
}
}
}
/**
* Deletes the provided {@link ECPContainer} elements.
*
* @param deletables the List of {@link ECPContainer}s to delete
* @param shell the shell to use for UI
*/
public static void deleteHandlerHelper(List<ECPContainer> deletables, Shell shell) {
if (!deletables.isEmpty()) {
final DeleteDialog dialog = new DeleteDialog(shell, deletables);
if (dialog.open() == Window.OK) {
for (final ECPContainer deletable : deletables) {
deletable.delete();
}
}
}
}
/**
* Triggers the save on an {@link ECPProject}.
*
* @param project the project to save the changes on
*/
public static void saveProject(ECPProject project) {
project.saveContents();
}
/**
* Resolve the a {@link ECPModelElementOpener} for the given model element.
*
* @param modelElement the element to find a opener for
* @return a {@link ECPModelElementOpener} or null if no opener has been found
*
* @since 1.12
*/
public static ECPModelElementOpener resolveElementOpener(final Object modelElement) {
if (modelElement == null) {
MessageDialog.openError(Display.getCurrent().getActiveShell(),
Messages.ActionHelper_ErrorTitle_ElementDeleted, Messages.ActionHelper_ErrorMessage_ElementDeleted);
return null;
}
IConfigurationElement[] modelelementopener = Platform.getExtensionRegistry().getConfigurationElementsFor(
"org.eclipse.emf.ecp.ui.modelElementOpener"); //$NON-NLS-1$
ECPModelElementOpener bestCandidate = null;
int bestValue = -1;
for (final IConfigurationElement element : modelelementopener) {
modelelementopener = null;
try {
final ECPModelElementOpener modelelementOpener = (ECPModelElementOpener) element
.createExecutableExtension("class"); //$NON-NLS-1$
for (final IConfigurationElement testerElement : element.getChildren()) {
if ("staticTester".equals(testerElement.getName())) {//$NON-NLS-1$
final int priority = Integer.parseInt(testerElement.getAttribute("priority"));//$NON-NLS-1$
final String type = testerElement.getAttribute("modelElement"); //$NON-NLS-1$
try {
final Class<?> supportedClassType = HandlerHelperUtil.loadClass(testerElement
.getContributor().getName(),
type);
if (supportedClassType.isInstance(modelElement)) {
if (priority > bestValue) {
bestCandidate = modelelementOpener;
bestValue = priority;
}
}
} catch (final ClassNotFoundException ex) {
Activator.log(ex);
}
} else if ("dynamicTester".equals(testerElement.getName())) {//$NON-NLS-1$
final ECPModelElementOpenTester tester = (ECPModelElementOpenTester) testerElement
.createExecutableExtension("tester"); //$NON-NLS-1$
final int value = tester.isApplicable(modelElement);
if (value > bestValue) {
bestCandidate = modelelementOpener;
bestValue = value;
}
}
}
} catch (final CoreException e) {
Activator.log(e);
}
}
return bestCandidate;
}
/**
* Open a view for the given model element.
*
* @param modelElement
* ModelElement to open
* the view that requested the open model element
* @param ecpProject the {@link ECPProject} of the model element
*/
public static void openModelElement(final Object modelElement, ECPProject ecpProject) {
openModelElement(modelElement, ecpProject, new LinkedHashMap<Object, Object>());
}
/**
* Open a view for the given model element.
*
* @param modelElement
* ModelElement to open
* the view that requested the open model element
* @param ecpProject the {@link ECPProject} of the model element
* @param contextMap context map
* @since 1.12
*/
public static void openModelElement(final Object modelElement, ECPProject ecpProject,
Map<Object, Object> contextMap) {
final ECPModelElementOpener opener = resolveElementOpener(modelElement);
// TODO: find solution
// ECPWorkspaceManager.getObserverBus().notify(ModelElementOpenObserver.class).onOpen(me, sourceView, name);
// BEGIN SUPRESS CATCH EXCEPTION
if (opener == null) {
return;
}
try {
if (opener instanceof ECPModelElementOpenerWithContext) {
((ECPModelElementOpenerWithContext) opener).openModelElement(modelElement, ecpProject, contextMap);
} else {
opener.openModelElement(modelElement, ecpProject);
}
} catch (final RuntimeException e) {
Activator.log(e);
}
// END SUPRESS CATCH EXCEPTION
}
/**
* Opens a Dialog showing the properties of the provided {@link ECPProject}.
*
* @param project the project whose properties should be shown
* @param editable whether the properties should be editable
* @param shell the {@link Shell} to use for the dialog
*/
public static void openProjectProperties(ECPProject project, boolean editable, Shell shell) {
new ProjectPropertiesDialog(shell, editable, project).open();
}
/**
* Opens a Dialog showing the properties of the provided {@link ECPRepository}.
*
* @param repository the repository whose properties should be shown
* @param editable whether the properties should be editable
* @param shell the {@link Shell} to use for the dialog
*/
public static void openRepositoryProperties(ECPRepository repository, boolean editable, Shell shell) {
new RepositoryPropertiesDialog(shell, editable, repository).open();
}
/**
* Opens a dialog to save dirty projects.
*
* @param shell to open the dialog in
* @return if the save was triggered
*/
public static boolean showDirtyProjectsDialog(Shell shell) {
final ECPProjectManager manager = ECPUtil.getECPProjectManager();
final List<ECPProject> dirtyProjects = new ArrayList<ECPProject>();
for (final ECPProject project : manager.getProjects()) {
if (project.isOpen() && project.hasDirtyContents()) {
dirtyProjects.add(project);
}
}
if (dirtyProjects.isEmpty()) {
return true;
}
final ListSelectionDialog lsd = new ListSelectionDialog(shell, dirtyProjects,
ArrayContentProvider.getInstance(),
new LabelProvider() {
@Override
public Image getImage(Object element) {
if (ECPProject.class.isInstance(element)) {
return Activator.getImage("icons/project_open.gif"); //$NON-NLS-1$
}
return super.getImage(element);
}
@Override
public String getText(Object element) {
if (ECPProject.class.isInstance(element)) {
return ((ECPProject) element).getName();
}
return super.getText(element);
}
}, "Select the projects, which should be saved."); //$NON-NLS-1$
lsd.setInitialSelections(manager.getProjects().toArray());
lsd.setTitle("Unsaved Projects"); //$NON-NLS-1$
final int result = lsd.open();
if (Window.OK == result) {
for (final Object o : lsd.getResult()) {
ECPHandlerHelper.saveProject((ECPProject) o);
}
return true;
}
return false;
}
}