diff options
author | Christian W. Damus | 2021-07-07 12:25:35 +0000 |
---|---|---|
committer | Patrick Tessier | 2021-08-25 09:51:46 +0000 |
commit | bfce4da24ec5ccbbd757df2d4d2ec0354ebfb3a4 (patch) | |
tree | 3b78cefc737dff4203f568fd68ded7fba328625a | |
parent | 61950140c31a96d51ad95daf9b439f4dd88d461e (diff) | |
download | org.eclipse.papyrus-bfce4da24ec5ccbbd757df2d4d2ec0354ebfb3a4.tar.gz org.eclipse.papyrus-bfce4da24ec5ccbbd757df2d4d2ec0354ebfb3a4.tar.xz org.eclipse.papyrus-bfce4da24ec5ccbbd757df2d4d2ec0354ebfb3a4.zip |
Bug 573987: [Toolsmiths] Properties Editor improvements (Perspective, Toolbar)
- open the editor on completion of the new properties context wizard
- remove toggle action for showing data contexts
- filter out inapplicable child/sibling creation actions for virtual
nodes in the editor tree
- add preference for action to take on opening the Context Editor
- fix the tracking of state of the Preview View toggle button
- compute initial generator and source model in the wizard from
the current workbench selection, where applicable
Change-Id: I20f40f34bc71ac6ea1b885aed6f5118ee97132ec
Signed-off-by: Christian W. Damus <give.a.damus@gmail.com>
28 files changed, 989 insertions, 385 deletions
diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.ui/META-INF/MANIFEST.MF b/plugins/infra/ui/org.eclipse.papyrus.infra.ui/META-INF/MANIFEST.MF index 69d5d9722b8..9215e2ba831 100644 --- a/plugins/infra/ui/org.eclipse.papyrus.infra.ui/META-INF/MANIFEST.MF +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.ui/META-INF/MANIFEST.MF @@ -45,7 +45,7 @@ Require-Bundle: org.eclipse.core.databinding;bundle-version="[1.9.0,2.0.0)", org.eclipse.ui.views.properties.tabbed;bundle-version="[3.8.0,4.0.0)", org.eclipse.uml2.types;bundle-version="[2.5.0,3.0.0)" Bundle-Vendor: %providerName -Bundle-Version: 3.2.0.qualifier +Bundle-Version: 3.3.0.qualifier Eclipse-BuddyPolicy: dependent Bundle-ManifestVersion: 2 Bundle-Activator: org.eclipse.papyrus.infra.ui.Activator diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.ui/pom.xml b/plugins/infra/ui/org.eclipse.papyrus.infra.ui/pom.xml index 77ba081eec3..6a16c912371 100644 --- a/plugins/infra/ui/org.eclipse.papyrus.infra.ui/pom.xml +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.ui/pom.xml @@ -9,7 +9,7 @@ <version>0.0.1-SNAPSHOT</version> </parent> <artifactId>org.eclipse.papyrus.infra.ui</artifactId> - <version>3.2.0-SNAPSHOT</version> + <version>3.3.0-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> <description>Plugin dedicated to manage generic menus and actions, linked to EMF but not to UML nor GMF technologies.</description> </project>
\ No newline at end of file diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.ui/src/org/eclipse/papyrus/infra/ui/util/EditorHelper.java b/plugins/infra/ui/org.eclipse.papyrus.infra.ui/src/org/eclipse/papyrus/infra/ui/util/EditorHelper.java index feb1c50e5a8..67355d16c17 100644 --- a/plugins/infra/ui/org.eclipse.papyrus.infra.ui/src/org/eclipse/papyrus/infra/ui/util/EditorHelper.java +++ b/plugins/infra/ui/org.eclipse.papyrus.infra.ui/src/org/eclipse/papyrus/infra/ui/util/EditorHelper.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2012, 2016 CEA LIST, Christian W. Damus, and others. + * Copyright (c) 2012, 2021 CEA LIST, Christian W. Damus, and others. * * * All rights reserved. This program and the accompanying materials @@ -11,7 +11,7 @@ * * Contributors: * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation - * Christian W. Damus - bug 488965 + * Christian W. Damus - bugs 488965, 573987 * *****************************************************************************/ package org.eclipse.papyrus.infra.ui.util; @@ -26,9 +26,9 @@ import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; /** + * A helper that provides convenient access to the UI context of editors in a workbench, + * such as active window, part, editor, page, etc. * - * a helper for the Editor - * * @since 1.2 * */ @@ -40,9 +40,44 @@ public class EditorHelper { /** + * Obtain a specific helper instance for the given {@code workbench} that + * makes the best effort to get results, even if they are not actually + * active elements of the workbench. + * + * @param workbench + * the workbench + * + * @return the specific nest-effort helper instance for the {@code workbench} + * + * @since 3.3 + * @see #getInstance(IWorkbench, boolean) + */ + public static Instance getInstance(IWorkbench workbench) { + return getInstance(workbench, true); + } + + /** + * Obtain a specific helper instance for the given {@code workbench} that + * optionally makes the best effort to get results, even if they are not + * actually active elements of the workbench. + * + * @param workbench + * the workbench + * @param bestEffort + * whether to make a best effort to get an element, even if none is actually active in the literal sense + * + * @return the specific helper instance for the {@code workbench} + * + * @since 3.3 + */ + public static Instance getInstance(IWorkbench workbench, boolean bestEffort) { + return new Instance(workbench, bestEffort); + } + + /** * * @return - * the current workbench window or <code>null</code> if not found + * the current workbench window or <code>null</code> if not found */ public static final Shell getActiveShell() { final IWorkbench workbench = PlatformUI.getWorkbench(); @@ -55,7 +90,7 @@ public class EditorHelper { /** * * @return - * the current workbench window or <code>null</code> if not found + * the current workbench window or <code>null</code> if not found */ public static final IWorkbenchWindow getActiveWindow() { final IWorkbench workbench = PlatformUI.getWorkbench(); @@ -68,7 +103,7 @@ public class EditorHelper { /** * * @return - * the current editor or <code>null</code> if not found + * the current editor or <code>null</code> if not found */ public static final IEditorPart getCurrentEditor() { final IWorkbench workbench = PlatformUI.getWorkbench(); @@ -87,7 +122,7 @@ public class EditorHelper { /** * * @return - * the current active part or <code>null</code> if not found + * the current active part or <code>null</code> if not found */ public static final IWorkbenchPart getActivePart() { final IWorkbench workbench = PlatformUI.getWorkbench(); @@ -102,4 +137,110 @@ public class EditorHelper { } return null; } + + // + // Nested types + // + + /** + * A specific editor-helper instance for a workbench. + * + * @since 3.3 + */ + public static final class Instance { + + private final IWorkbench workbench; + private final boolean bestEffort; + + private Instance(IWorkbench workbench, boolean bestEffort) { + super(); + + this.workbench = workbench; + this.bestEffort = bestEffort; + } + + /** + * Get the currently active workbench window shell, or whatever is the display's + * active shell if no workbench window actually is active. + * + * @return the current active shell + */ + public Shell getActiveShell() { + IWorkbenchWindow window = getActiveWindow(); + return (window == null) ? Display.getCurrent().getActiveShell() : window.getShell(); + } + + /** + * Get the currently active workbench window, or the first available window as a best-effort + * guess if applicable. + * + * @return the active workbench window, or a best-effort guess if I am so configured + */ + public IWorkbenchWindow getActiveWindow() { + if (workbench == null) { + return null; + } + + IWorkbenchWindow result = workbench.getActiveWorkbenchWindow(); + + if (result == null && bestEffort && workbench.getWorkbenchWindowCount() > 0) { + // There isn't actually an active page. So just get some page + result = workbench.getWorkbenchWindows()[0]; + } + + return result; + } + + /** + * Get the currently active workbench page, or the first available page as a best-effort + * guess if applicable. + * + * @return the active workbench page, or a best-effort guess if I am so configured + */ + public IWorkbenchPage getActivePage() { + IWorkbenchPage result = null; + + IWorkbenchWindow window = getActiveWindow(); + if (window != null) { + result = window.getActivePage(); + if (result == null && bestEffort) { + // It's not active. Just get some page + IWorkbenchPage[] pages = window.getPages(); + if (pages.length > 0) { + result = pages[0]; + } + } + } + + return result; + } + + /** + * Get the currently active editor, if any, in the currently active {@linkplain #getActivePage() workbench page}. + * + * @return the active editor in the active page, or {@code null} if either the active page has no active editor or + * an active page could not be determined + * + * @see #getActivePage() + */ + public IEditorPart getActiveEditor() { + IWorkbenchPage page = getActivePage(); + return (page == null) ? null : page.getActiveEditor(); + } + + /** + * Get the currently active part, if any, in the currently active {@linkplain #getActivePage() workbench page}. + * + * @return the active part in the active page, or {@code null} if either the active page has no active part or + * an active page could not be determined + * + * @see #getActivePage() + */ + public IWorkbenchPart getActivePart() { + IWorkbenchPage page = getActivePage(); + return (page == null) ? null : page.getActivePart(); + } + + } + } diff --git a/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/META-INF/MANIFEST.MF b/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/META-INF/MANIFEST.MF index 053d6a71522..4a1aff57ecb 100644 --- a/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/META-INF/MANIFEST.MF +++ b/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/META-INF/MANIFEST.MF @@ -27,7 +27,8 @@ Require-Bundle: org.eclipse.core.databinding.property;bundle-version="[1.8.0,2.0 org.eclipse.papyrus.views.properties.toolsmiths;bundle-version="[3.0.0,4.0.0)", org.eclipse.ui.views.properties.tabbed;bundle-version="[3.8.0,4.0.0)", org.eclipse.uml2.uml;bundle-version="[5.5.0,6.0.0)", - org.eclipse.papyrus.emf.facet.custom.ui;bundle-version="[4.0.0,5.0.0)" + org.eclipse.papyrus.emf.facet.custom.ui;bundle-version="[4.0.0,5.0.0)", + org.eclipse.papyrus.infra.ui;bundle-version="[3.3.0,4.0.0)" Bundle-Vendor: %Bundle-Vendor Bundle-ActivationPolicy: lazy Bundle-ClassPath: ., diff --git a/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/generators/EcoreGenerator.java b/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/generators/EcoreGenerator.java index 40cacd80a4c..712f9f0fb06 100644 --- a/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/generators/EcoreGenerator.java +++ b/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/generators/EcoreGenerator.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2010, 2019 CEA LIST. + * Copyright (c) 2010, 2021 CEA LIST, Christian W. Damus, and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -12,6 +12,7 @@ * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation * Thibault Le Ouay t.leouay@sherpa-eng.com - Strategy improvement of generated files * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Bug 544869 + * Christian W. Damus - bug 573987 *****************************************************************************/ package org.eclipse.papyrus.customization.properties.generation.generators; @@ -25,6 +26,9 @@ import java.util.List; import java.util.Set; import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.content.IContentType; import org.eclipse.emf.common.notify.Notifier; import org.eclipse.emf.common.util.TreeIterator; import org.eclipse.emf.common.util.URI; @@ -36,6 +40,7 @@ import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.EcorePackage; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.m2m.qvt.oml.BasicModelExtent; import org.eclipse.m2m.qvt.oml.ModelExtent; @@ -68,7 +73,7 @@ public class EcoreGenerator extends AbstractQVTGenerator { protected List<EPackage> listEPackages; @Override - public void createControls(Composite parent) { + public void createControls(Composite parent, IFile workbenchSelection) { Composite root = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(2, false); layout.marginWidth = 0; @@ -86,6 +91,12 @@ public class EcoreGenerator extends AbstractQVTGenerator { listEPackages = new ArrayList<>(); + if (workbenchSelection != null) { + IFile suggestion = getSourceFile(workbenchSelection); + if (suggestion != null) { + sourceFileChooser.setFile(suggestion); + } + } } @Override @@ -393,6 +404,15 @@ public class EcoreGenerator extends AbstractQVTGenerator { } + @Override + public IFile getSourceFile(IFile file, IContentType contentType) { + if (contentType == null) { + return null; // Ecore content type is registered, so the file is not an Ecore model + } + + IContentType ecore = Platform.getContentTypeManager().getContentType(EcorePackage.eCONTENT_TYPE); + return ecore != null && contentType.isKindOf(ecore) ? file : null; + } } diff --git a/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/generators/IGenerator.java b/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/generators/IGenerator.java index 38b3cd6b45a..80410535140 100644 --- a/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/generators/IGenerator.java +++ b/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/generators/IGenerator.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2010, 2014 CEA LIST and others. + * Copyright (c) 2010, 2021 CEA LIST, Christian W. Damus, and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -12,14 +12,21 @@ * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation * Thibault Le Ouay t.leouay@sherpa-eng.com - Strategy improvement of generated files * Christian W. Damus (CEA) - bug 422257 + * Christian W. Damus - bug 573987 * *****************************************************************************/ package org.eclipse.papyrus.customization.properties.generation.generators; import java.util.List; +import java.util.Optional; import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.content.IContentDescription; +import org.eclipse.core.runtime.content.IContentType; import org.eclipse.emf.common.util.URI; +import org.eclipse.papyrus.customization.properties.generation.Activator; import org.eclipse.papyrus.infra.properties.contexts.Context; import org.eclipse.papyrus.infra.properties.contexts.DataContextElement; import org.eclipse.papyrus.infra.properties.contexts.Property; @@ -54,8 +61,29 @@ public interface IGenerator { * * @param parent * The Composite in which the controls will be displayed + * + * @deprecated Implement the {@link #createControls(Composite, IFile)} method, instead + */ + @Deprecated + public default void createControls(Composite parent) { + // Extant classes already override this. New ones should not + throw new AbstractMethodError("createControls(Composite)"); //$NON-NLS-1$ + } + + /** + * Creates the controls for this Generator. The generator is responsible + * for displaying any Control useful for editing its options, and listening + * for changes on them. + * + * @param parent + * The Composite in which the controls will be displayed + * @param workbenchSelection + * the file currently selected in the workbench, if any. + * May be {@code null} */ - public void createControls(Composite parent); + public default void createControls(Composite parent, IFile workbenchSelection) { + createControls(parent); + } /** * Gets the description for this Generator @@ -148,4 +176,60 @@ public interface IGenerator { */ public void dispose(); + /** + * Query the preferred source model for generation of a <em>Properties Context</em> model based on + * the given file selection in the workbench. + * + * @param file + * the file selection in the workbench + * @param contentType + * the content type of the {@code file}. May be {@code null} if the content type cannot + * be determined or if the {@code file}'s content type is not registered in the platform + * @return the preferred file to use as input for the generation. This should be related in some way to + * the selected {@code file}, usually being that {@code file} itself. Or else {@code null} to indicate + * that the given {@code file} is not handled at all by this generator + * + * @see #getSourceFile(IFile, IContentType) + */ + public default IFile getSourceFile(IFile file) { + try { + Optional<IContentType> contentType = Optional.ofNullable(file.getContentDescription()).map(IContentDescription::getContentType); + return getSourceFile(file, contentType.orElse(null)); + } catch (CoreException e) { + Activator.log.error("Could not determine content type of " + file, e); //$NON-NLS-1$ + return null; + } + } + + /** + * Query the preferred source model for generation of a <em>Properties Context</em> model based on + * the given file selection in the workbench. + * + * @param file + * the file selection in the workbench + * @param contentType + * the content type of the {@code file}. May be {@code null} if the content type cannot + * be determined or if the {@code file}'s content type is not registered in the platform + * @return the preferred file to use as input for the generation. This should be related in some way to + * the selected {@code file}, usually being that {@code file} itself. Or else {@code null} to indicate + * that the given {@code file} is not handled at all by this generator + */ + public default IFile getSourceFile(IFile file, IContentType contentType) { + return null; + } + + /** + * Query whether I can generate a <em>Properties Context</em> model from the given file selected in the workbench. + * + * @param selectedFile + * the file currently selected in the workbench. Must not be {@code null} + * @param contentType + * the content type of the selected file. May be {@code null} if the content type cannot + * be determined or if the selected file's content type is not registered in the platform + * @return + */ + public default boolean canGenerate(IFile selectedFile, IContentType contentType) { + return getSourceFile(selectedFile, contentType) != null; + } + } diff --git a/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/generators/ProfileGenerator.java b/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/generators/ProfileGenerator.java index 9a894763f7e..4a6291a1d54 100644 --- a/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/generators/ProfileGenerator.java +++ b/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/generators/ProfileGenerator.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2010 CEA LIST. + * Copyright (c) 2010, 2021 CEA LIST, Christian W. Damus, and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -11,6 +11,7 @@ * Contributors: * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation * Thibault Le Ouay t.leouay@sherpa-eng.com - Strategy improvement of generated files + * Christian W. Damus - bug 573987 *****************************************************************************/ package org.eclipse.papyrus.customization.properties.generation.generators; @@ -24,6 +25,9 @@ import java.util.List; import java.util.Set; import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.content.IContentType; import org.eclipse.emf.common.util.TreeIterator; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; @@ -33,6 +37,7 @@ import org.eclipse.m2m.qvt.oml.ModelExtent; import org.eclipse.papyrus.customization.properties.generation.Activator; import org.eclipse.papyrus.customization.properties.generation.messages.Messages; import org.eclipse.papyrus.customization.properties.generation.wizard.widget.FileChooser; +import org.eclipse.papyrus.infra.core.resource.sasheditor.DiModel; import org.eclipse.papyrus.infra.properties.contexts.Context; import org.eclipse.papyrus.infra.properties.contexts.DataContextElement; import org.eclipse.papyrus.infra.properties.contexts.Property; @@ -51,6 +56,8 @@ import org.eclipse.uml2.uml.Package; import org.eclipse.uml2.uml.PackageImport; import org.eclipse.uml2.uml.PrimitiveType; import org.eclipse.uml2.uml.Profile; +import org.eclipse.uml2.uml.UMLPackage; +import org.eclipse.uml2.uml.resource.UMLResource; /** * An IGenerator for building Contexts from a UML Profile @@ -71,7 +78,7 @@ public class ProfileGenerator extends AbstractQVTGenerator { @Override - public void createControls(Composite parent) { + public void createControls(Composite parent, IFile workbenchSelection) { Composite root = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(2, false); layout.marginWidth = 0; @@ -87,6 +94,13 @@ public class ProfileGenerator extends AbstractQVTGenerator { sourceFileChooser.setFilterExtensions(FileExtensions.umlProfileExtensions); sourceFileChooser.addListener(this); listEObject = new ArrayList<>(); + + if (workbenchSelection != null) { + IFile suggestion = getSourceFile(workbenchSelection); + if (suggestion != null) { + sourceFileChooser.setFile(suggestion); + } + } } @Override @@ -371,4 +385,27 @@ public class ProfileGenerator extends AbstractQVTGenerator { return null; } + + @Override + public IFile getSourceFile(IFile file, IContentType contentType) { + IFile result = null; + + if (DiModel.DI_FILE_EXTENSION.equals(file.getFileExtension())) { + // Get the associated UML file, if it exists + IFile umlFile = file.getProject().getFile(file.getProjectRelativePath().removeFileExtension().addFileExtension(UMLResource.FILE_EXTENSION)); + if (umlFile != null && umlFile.isAccessible()) { + result = getSourceFile(umlFile); + } + } else if (contentType != null) { + // The only other supported input is the UML file, itself, and the UML content type is registered + IContentType uml = Platform.getContentTypeManager().getContentType(UMLPackage.eCONTENT_TYPE); + + if (uml != null && contentType.isKindOf(uml)) { + result = file; + } + } + + return result; + } + } diff --git a/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/wizard/CreateContextMainPage.java b/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/wizard/CreateContextMainPage.java index 1db719f14be..d049c4a1772 100644 --- a/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/wizard/CreateContextMainPage.java +++ b/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/wizard/CreateContextMainPage.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2010, 2014 CEA LIST and others. + * Copyright (c) 2010, 2021 CEA LIST, Christian W. Damus, and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -12,13 +12,19 @@ * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation * Thibault Le Ouay t.leouay@sherpa-eng.com - Add SelectOutputPage * Christian W. Damus (CEA) - bug 422257 + * Christian W. Damus - bug 573987 * *****************************************************************************/ package org.eclipse.papyrus.customization.properties.generation.wizard; import java.util.List; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.content.IContentDescription; +import org.eclipse.core.runtime.content.IContentType; import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.papyrus.customization.properties.generation.Activator; import org.eclipse.papyrus.customization.properties.generation.extensionpoint.GeneratorExtensionPoint; import org.eclipse.papyrus.customization.properties.generation.generators.IGenerator; import org.eclipse.papyrus.customization.properties.generation.messages.Messages; @@ -64,6 +70,7 @@ public class CreateContextMainPage extends AbstractCreateContextPage implements } } + @Override public void createControl(Composite parent) { Composite root = new Composite(parent, SWT.NONE); root.setLayout(new GridLayout(1, false)); @@ -80,6 +87,8 @@ public class CreateContextMainPage extends AbstractCreateContextPage implements setControl(root); setDescription(Messages.CreateContextMainPage_description); + + getWizard().getCurrentlySelectedFile().ifPresent(this::selectGenerator); } @Override @@ -90,8 +99,32 @@ public class CreateContextMainPage extends AbstractCreateContextPage implements return getWizard().generatorPage; } + @Override public void handleEvent(Event event) { super.setPageComplete(true); } + /** + * Select the best-fitting generator, if any, for the file currently selected + * in the workbench. + * + * @param selectedFile + * the currently selected file. Must not be {@code null} + */ + private void selectGenerator(IFile selectedFile) { + IContentType contentType = null; + + try { + IContentDescription description = selectedFile.getContentDescription(); + contentType = (description != null) ? description.getContentType() : null; + } catch (CoreException e) { + Activator.log.error("Failed to determine content type of " + selectedFile, e); //$NON-NLS-1$ + } + + IContentType _contentType = contentType; + generators.stream().filter(gen -> gen.canGenerate(selectedFile, _contentType)) + .findFirst() + .ifPresent(gen -> combo.select(generators.indexOf(gen))); + } + } diff --git a/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/wizard/CreateContextWizard.java b/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/wizard/CreateContextWizard.java index 0c61bcc3f91..5b71bd56090 100644 --- a/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/wizard/CreateContextWizard.java +++ b/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/wizard/CreateContextWizard.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2010, 2015, 2017 CEA LIST, Christian W. Damus, and others. + * Copyright (c) 2010, 2021, 2017 CEA LIST, Christian W. Damus, and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -11,11 +11,13 @@ * Contributors: * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation * Christian W. Damus (CEA) - bug 422257 - * Christian W. Damus - bug 482927 - * Vincent Lorenzo (CEA LIST) - bug 520271 + * Christian W. Damus - bugs 482927, 573987 + * Vincent Lorenzo (CEA LIST) - bug 520271 *****************************************************************************/ package org.eclipse.papyrus.customization.properties.generation.wizard; +import static java.util.stream.StreamSupport.stream; + import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; @@ -25,11 +27,16 @@ import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.Optional; import java.util.Set; +import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.xmi.XMLResource; import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.util.Policy; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.wizard.Wizard; import org.eclipse.papyrus.customization.properties.generation.Activator; @@ -40,6 +47,7 @@ import org.eclipse.papyrus.customization.properties.generation.generators.IGener import org.eclipse.papyrus.customization.properties.generation.layout.ILayoutGenerator; import org.eclipse.papyrus.customization.properties.generation.messages.Messages; import org.eclipse.papyrus.customization.properties.generation.wizard.widget.TernaryButton; +import org.eclipse.papyrus.infra.emf.utils.ResourceUtils; import org.eclipse.papyrus.infra.properties.contexts.Context; import org.eclipse.papyrus.infra.properties.contexts.ContextsFactory; import org.eclipse.papyrus.infra.properties.contexts.DataContextElement; @@ -52,8 +60,12 @@ import org.eclipse.papyrus.infra.properties.ui.UiFactory; import org.eclipse.papyrus.infra.properties.ui.ValueAttribute; import org.eclipse.papyrus.infra.properties.ui.runtime.IConfigurationManager; import org.eclipse.papyrus.infra.properties.ui.runtime.PropertiesRuntime; +import org.eclipse.papyrus.infra.ui.util.EditorHelper; import org.eclipse.ui.INewWizard; import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.ide.IDE; /** * A Wizard for generating Property view contexts @@ -87,14 +99,20 @@ public class CreateContextWizard extends Wizard implements INewWizard { */ protected ILayoutGenerator layoutGenerator; + private IWorkbenchPage workbenchPage; + + private Optional<IFile> currentlySelectedFile; + public CreateContextWizard() { setDefaultPageImageDescriptor(Activator.getDefault().getImageDescriptor("/icons/wizban-custom.png")); //$NON-NLS-1$ } @Override public boolean performFinish() { + boolean result = false; + if (generator == null || contexts == null || contexts.isEmpty() || layoutGenerator == null) { - return false; + return result; } IConfigurationManager configManager = PropertiesRuntime.getConfigurationManager(); @@ -124,9 +142,9 @@ public class CreateContextWizard extends Wizard implements INewWizard { continue; } - List<PropertyEditor> editors = new LinkedList<PropertyEditor>(); + List<PropertyEditor> editors = new LinkedList<>(); // the list of properties for the current view - final List<Property> properties = new ArrayList<Property>(); + final List<Property> properties = new ArrayList<>(); for (DataContextElement element : getAllContextElements(view.getDatacontexts())) { for (Property property : element.getProperties()) { if (isSelected(fieldSelection, property, view.getElementMultiplicity() != 1)) { @@ -135,9 +153,9 @@ public class CreateContextWizard extends Wizard implements INewWizard { } } - final List<Property> tmpProperties = new ArrayList<Property>(properties); + final List<Property> tmpProperties = new ArrayList<>(properties); for (Property p1 : tmpProperties) { - //Bug 519090 + // Bug 519090 // we remove all redefined properties from the list properties.removeAll(p1.getRedefinedProperties()); } @@ -169,11 +187,12 @@ public class CreateContextWizard extends Wizard implements INewWizard { setNeedsProgressMonitor(true); final Context currentContext = context; - final Map<String, Object> saveOptions = new HashMap<String, Object>(); + final Map<String, Object> saveOptions = new HashMap<>(); saveOptions.put(XMLResource.OPTION_PROCESS_DANGLING_HREF, XMLResource.OPTION_PROCESS_DANGLING_HREF_RECORD); getContainer().run(true, true, new IRunnableWithProgress() { + @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask(Messages.CreateContextWizard_propertyViewGenerationJobName + currentContext.getUserLabel(), numberOfSections + 1); monitor.worked(1); @@ -204,9 +223,24 @@ public class CreateContextWizard extends Wizard implements INewWizard { Activator.log.error(ex); } + result = true; } - return true; + if (result) { + // Open the "main" generated context file + URI uriToOpen = contexts.get(0).eResource().getURI(); + if (uriToOpen.isPlatformResource()) { + IFile file = ResourceUtils.getFile(contexts.get(0).eResource()); + + try { + IDE.openEditor(workbenchPage, file); + } catch (PartInitException e) { + Policy.getStatusHandler().show(e.getStatus(), getWindowTitle()); + } + } + } + + return result; } private boolean isSelected(FieldSelection fieldSelection, Property property, boolean multiple) { @@ -276,7 +310,7 @@ public class CreateContextWizard extends Wizard implements INewWizard { protected List<String> getPropertyPath(DataContextElement element) { List<String> result; if (element.getPackage() == null) { - result = new LinkedList<String>(); + result = new LinkedList<>(); } else { result = getPropertyPath(element.getPackage()); } @@ -285,7 +319,7 @@ public class CreateContextWizard extends Wizard implements INewWizard { } private Set<DataContextElement> getAllContextElements(Collection<DataContextElement> source) { - Set<DataContextElement> result = new HashSet<DataContextElement>(); + Set<DataContextElement> result = new HashSet<>(); for (DataContextElement element : source) { getAllContextElements(element, result); } @@ -303,21 +337,36 @@ public class CreateContextWizard extends Wizard implements INewWizard { } } + @Override public void init(IWorkbench workbench, IStructuredSelection selection) { addPage(mainPage = new CreateContextMainPage()); addPage(generatorPage = new GeneratorPage()); addPage(selectOutputPage = new SelectOutputPage()); addPage(selectFieldsPage = new SelectFieldsPage()); - // addPage(layout = new LayoutPage()); setWindowTitle(Messages.CreateContextWizard_pageTitle); + workbenchPage = EditorHelper.getInstance(workbench).getActivePage(); + currentlySelectedFile = stream(((Iterable<?>) selection).spliterator(), false) + .filter(IFile.class::isInstance).map(IFile.class::cast) + .findFirst(); + } + + /** + * Query the file that was selected in the workbench when the user launched the wizard. + * + * @return the currently selected file + */ + Optional<IFile> getCurrentlySelectedFile() { + return currentlySelectedFile; } protected void setGenerator(IGenerator generator) { - this.generator = generator; - generatorPage.setGenerator(generator); - generatorPage.doBinding(); + if (!Objects.equals(this.generator, generator)) { + this.generator = generator; + generatorPage.setGenerator(generator); + generatorPage.doBinding(); + } } protected void setContexts(List<Context> contexts) { diff --git a/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/wizard/GeneratorPage.java b/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/wizard/GeneratorPage.java index 41423893f01..abe06fe6e7e 100644 --- a/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/wizard/GeneratorPage.java +++ b/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/wizard/GeneratorPage.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2010, 2014 CEA LIST and others. + * Copyright (c) 2010, 2021 CEA LIST, Christian W. Damus, and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -12,6 +12,7 @@ * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation * Thibault Le Ouay t.leouay@sherpa-eng.com - Strategy improvement of generated files * Christian W. Damus (CEA) - bug 422257 + * Christian W. Damus - bug 573987 * *****************************************************************************/ package org.eclipse.papyrus.customization.properties.generation.wizard; @@ -23,8 +24,6 @@ import org.eclipse.core.databinding.DataBindingContext; import org.eclipse.core.databinding.UpdateValueStrategy; import org.eclipse.core.databinding.conversion.IConverter; import org.eclipse.core.databinding.observable.value.IObservableValue; -import org.eclipse.core.databinding.observable.value.IValueChangeListener; -import org.eclipse.core.databinding.observable.value.ValueChangeEvent; import org.eclipse.core.runtime.IStatus; import org.eclipse.emf.common.util.URI; import org.eclipse.jface.databinding.wizard.WizardPageSupport; @@ -110,7 +109,7 @@ public class GeneratorPage extends AbstractCreateContextPage implements Listener setDescription(generator.getDescription()); this.generator = generator; - generator.createControls(generatorControl); + generator.createControls(generatorControl, getWizard().getCurrentlySelectedFile().orElse(null)); generatorControl.layout(); srcTextObservable = this.generator.getObservableValue(); root.layout(); @@ -284,26 +283,26 @@ public class GeneratorPage extends AbstractCreateContextPage implements Listener targetFieldStrategy.setAfterConvertValidator(srcValidator); binding = ctx.bindValue(srcTextObservable, targetTextObservable, srcFieldStrategy, targetFieldStrategy); - } - } - - @Override - public boolean canFlipToNextPage() { - binding.getValidationStatus().addValueChangeListener(new IValueChangeListener() { - - @Override - public void handleValueChange(ValueChangeEvent event) { - IStatus status = (IStatus) event.diff.getNewValue(); + binding.getValidationStatus().addValueChangeListener(event -> { + IStatus status = event.diff.getNewValue(); if (status.isOK() || status.getSeverity() == IStatus.WARNING) { setNext(true); } else { setNext(false); } - } - - }); + }); + // The source file is the "target", which the binding would not normally update to the "model." + // But if the source file is already suggested, then we do want to initialize the output file + // from it, so update the "target" to the "model" in binding-speak + if (srcTextObservable.getValue() != null && !"".equals(srcTextObservable.getValue())) { + binding.updateTargetToModel(); + } + } + } + @Override + public boolean canFlipToNextPage() { return this.next; } diff --git a/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/wizard/widget/FileChooser.java b/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/wizard/widget/FileChooser.java index 39750946bbb..1c4767cabdd 100644 --- a/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/wizard/widget/FileChooser.java +++ b/plugins/uml/properties/org.eclipse.papyrus.uml.properties.generation/src/org/eclipse/papyrus/customization/properties/generation/wizard/widget/FileChooser.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2010 CEA LIST. + * Copyright (c) 2010, 2021 CEA LIST, Christian W. Damus, and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -10,6 +10,7 @@ * * Contributors: * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus - bug 573987 *****************************************************************************/ package org.eclipse.papyrus.customization.properties.generation.wizard.widget; @@ -18,13 +19,14 @@ import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import org.eclipse.core.databinding.observable.value.IObservableValue; import org.eclipse.core.resources.IFile; import org.eclipse.emf.common.ui.dialogs.WorkspaceResourceDialog; import org.eclipse.jface.databinding.swt.IWidgetValueProperty; -import org.eclipse.jface.databinding.swt.WidgetProperties; +import org.eclipse.jface.databinding.swt.typed.WidgetProperties; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.jface.window.Window; @@ -66,6 +68,8 @@ public class FileChooser extends Composite implements SelectionListener, Listene private boolean newFile; + private IObservableValue<String> textObservable; + /** * Constructs a new FileChooser in the given Composite * @@ -89,6 +93,9 @@ public class FileChooser extends Composite implements SelectionListener, Listene browse.setText(Messages.FileChooser_browseWorkspace); browse.addSelectionListener(this); this.newFile = newFile; + + IWidgetValueProperty<Text, String> prop = WidgetProperties.text(SWT.Modify); + textObservable = prop.observeDelayed(600, text); } /** @@ -207,9 +214,7 @@ public class FileChooser extends Composite implements SelectionListener, Listene if (result.length > 0) { Object file = result[0]; if (file instanceof IFile) { - this.currentFile = ((IFile) file); - text.setText(currentFile.getFullPath().toString()); - notifyChange(); + setFile((IFile) file); } } } @@ -226,11 +231,32 @@ public class FileChooser extends Composite implements SelectionListener, Listene } public IObservableValue getObservableValue() { - IWidgetValueProperty prop = WidgetProperties.text(SWT.Modify); - return prop.observeDelayed(600, text); + return textObservable; } public void setText(String s) { text.setText(s); } + + /** + * Set the currently selected file. + * + * @param file + * the currently selected file. May be {@code null} to clear the selection + */ + public void setFile(IFile file) { + if (!Objects.equals(file, currentFile) && !text.isDisposed()) { + currentFile = file; + if (file == null) { + text.setText(""); //$NON-NLS-1$ + } else { + text.setText(file.getFullPath().toString()); + } + + // Trigger the update immediately + getObservableValue().getValue(); + + notifyChange(); + } + } } diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/META-INF/MANIFEST.MF b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/META-INF/MANIFEST.MF index dccb834864b..75072e0473f 100755 --- a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/META-INF/MANIFEST.MF +++ b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/META-INF/MANIFEST.MF @@ -33,7 +33,7 @@ Bundle-Vendor: %Bundle-Vendor Bundle-ActivationPolicy: lazy Bundle-ClassPath: ., bin -Bundle-Version: 3.1.0.qualifier +Bundle-Version: 3.2.0.qualifier Bundle-Name: %Bundle-Name Bundle-Activator: org.eclipse.papyrus.views.properties.toolsmiths.Activator Bundle-ManifestVersion: 2 diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/plugin.xml b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/plugin.xml index c76e83ff3f1..f9ccef435d4 100644 --- a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/plugin.xml +++ b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/plugin.xml @@ -97,10 +97,6 @@ class="org.eclipse.papyrus.views.properties.toolsmiths.editor.actions.TogglePreviewAction" commandId="org.eclipse.papyrus.customization.properties.TogglePreview"> </handler> - <handler - class="org.eclipse.papyrus.views.properties.toolsmiths.editor.actions.ToggleDataContextAction" - commandId="org.eclipse.papyrus.customization.properties.ToggleDataContext"> - </handler> </extension> <extension point="org.eclipse.ui.commands"> @@ -114,19 +110,10 @@ id="org.eclipse.papyrus.customization.properties.TogglePreview" name="%command.name.0"> <state - class="org.eclipse.papyrus.views.properties.toolsmiths.editor.actions.TogglePreviewState" + class="org.eclipse.jface.commands.ToggleState" id="org.eclipse.ui.commands.toggleState"> </state> </command> - <command - description="%command.description.1" - id="org.eclipse.papyrus.customization.properties.ToggleDataContext" - name="%command.name.1"> - <state - class="org.eclipse.papyrus.views.properties.toolsmiths.editor.actions.ToggleDataContextState" - id="org.eclipse.papyrus.customizatio.propertiesn.displayContextState"> - </state> - </command> </extension> <extension point="org.eclipse.ui.menus"> @@ -169,22 +156,6 @@ </with> </visibleWhen> </command> - <command - commandId="org.eclipse.papyrus.customization.properties.ToggleDataContext" - icon="icons/DataContexts.gif" - id="org.eclipse.papyrus.customization.properties.toggleDataContext" - label="%command.label.0" - style="toggle" - tooltip="%command.tooltip.0"> - <visibleWhen> - <with - variable="activeEditorId"> - <equals - value="org.eclipse.papyrus.customization.properties.UIEditor"> - </equals> - </with> - </visibleWhen> - </command> </toolbar> </menuContribution> </extension> diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/pom.xml b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/pom.xml index 6f5f61ec653..76c7ed54449 100644 --- a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/pom.xml +++ b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/pom.xml @@ -13,6 +13,6 @@ <relativePath>../../../toolsmiths/pom.xml</relativePath> </parent> <artifactId>org.eclipse.papyrus.views.properties.toolsmiths</artifactId> - <version>3.1.0-SNAPSHOT</version> + <version>3.2.0-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> </project>
\ No newline at end of file diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/editor/ContextEditorActionBarContributor.java b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/editor/ContextEditorActionBarContributor.java index 8e30244da7e..974e0dfc54f 100644 --- a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/editor/ContextEditorActionBarContributor.java +++ b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/editor/ContextEditorActionBarContributor.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2010 CEA LIST. + * Copyright (c) 2010, 2021 CEA LIST, Christian W. Damus, and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -10,6 +10,7 @@ * * Contributors: * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus - bug 573987 *****************************************************************************/ package org.eclipse.papyrus.views.properties.toolsmiths.editor; @@ -26,6 +27,7 @@ import org.eclipse.emf.edit.ui.action.DeleteAction; import org.eclipse.emf.edit.ui.action.PasteAction; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; @@ -39,8 +41,8 @@ import org.eclipse.papyrus.views.properties.toolsmiths.editor.actions.MoDiscoCop import org.eclipse.papyrus.views.properties.toolsmiths.editor.actions.MoDiscoCutAction; import org.eclipse.papyrus.views.properties.toolsmiths.editor.actions.MoDiscoDeleteAction; import org.eclipse.papyrus.views.properties.toolsmiths.editor.actions.MoDiscoPasteAction; -import org.eclipse.papyrus.views.properties.toolsmiths.editor.actions.ToggleDataContextAction; import org.eclipse.papyrus.views.properties.toolsmiths.editor.actions.ValidationAction; +import org.eclipse.papyrus.views.properties.toolsmiths.messages.Messages; import org.eclipse.papyrus.views.properties.toolsmiths.util.ActionUtil; /** @@ -52,8 +54,11 @@ import org.eclipse.papyrus.views.properties.toolsmiths.util.ActionUtil; */ public class ContextEditorActionBarContributor extends EcoreActionBarContributor { + private static final String MENU_ID = "org.eclipse.papyrus.views.properties.toolsmiths.editor.menu"; //$NON-NLS-1$ private int i = 0; + private final ActionUtil actionUtil; + /** * * Constructor. @@ -61,10 +66,17 @@ public class ContextEditorActionBarContributor extends EcoreActionBarContributor */ public ContextEditorActionBarContributor() { super(); + + actionUtil = new ActionUtil(this, super::selectionChanged, super::generateCreateChildActions, super::generateCreateSiblingActions); validateAction = new ValidationAction(); } @Override + protected IMenuManager createSubmenuManager() { + return new MenuManager(Messages.ContextEditorActionBarContributor_0, MENU_ID); + } + + @Override protected void addGlobalActions(IMenuManager menuManager) { super.addGlobalActions(menuManager); } @@ -76,21 +88,17 @@ public class ContextEditorActionBarContributor extends EcoreActionBarContributor @Override protected Collection<IAction> generateCreateChildActions(Collection<?> descriptors, ISelection selection) { - Collection<IAction> result = super.generateCreateChildActions(descriptors, selection); - if (selection instanceof IStructuredSelection) { - IStructuredSelection sSelection = (IStructuredSelection) selection; - if (sSelection.size() == 1) { - Object firstElement = sSelection.getFirstElement(); - if (firstElement instanceof View) { - result.addAll(createChildForView(selection, (View) sSelection.getFirstElement())); - } else if (firstElement instanceof Section) { - result.addAll(createChildForSection(selection)); - } else if (firstElement instanceof Tab) { - removeChildActionsForTab(result); - } else if (firstElement instanceof Context) { - removeChildActionsForContext(result); - } - } + Collection<IAction> result = actionUtil.createNewChildActions(descriptors, selection); + + Object firstElement = ActionUtil.getElement(selection); + if (firstElement instanceof View) { + result.addAll(createChildForView(selection, (View) firstElement)); + } else if (firstElement instanceof Section) { + result.addAll(createChildForSection(selection)); + } else if (firstElement instanceof Tab) { + removeChildActionsForTab(result); + } else if (firstElement instanceof Context) { + removeChildActionsForContext(result); } return result; @@ -98,7 +106,8 @@ public class ContextEditorActionBarContributor extends EcoreActionBarContributor @Override protected Collection<IAction> generateCreateSiblingActions(Collection<?> descriptors, ISelection selection) { - Collection<IAction> result = super.generateCreateSiblingActions(descriptors, selection); + Collection<IAction> result = actionUtil.createNewSiblingActions(descriptors, selection); + if (selection instanceof IStructuredSelection) { IStructuredSelection sSelection = (IStructuredSelection) selection; if (sSelection.size() == 1) { @@ -126,7 +135,7 @@ public class ContextEditorActionBarContributor extends EcoreActionBarContributor IAction action = iterator.next(); if (action instanceof CreateChildAction) { CreateChildAction createChildAction = (CreateChildAction) action; - if (createChildAction.getText().equals("Section")) { //It's the only relevant property we have access to... //$NON-NLS-1$ + if (createChildAction.getText().equals("Section")) { // It's the only relevant property we have access to... //$NON-NLS-1$ iterator.remove(); } } @@ -145,10 +154,8 @@ public class ContextEditorActionBarContributor extends EcoreActionBarContributor IAction action = iterator.next(); if (action instanceof CreateChildAction) { CreateChildAction createChildAction = (CreateChildAction) action; - if (!ToggleDataContextAction.showDataContext) { - if (createChildAction.getText().equals("Data Context Root")) { //It's the only relevant property we have access to... //$NON-NLS-1$ - iterator.remove(); - } + if (createChildAction.getText().equals("Data Context Root")) { // It's the only relevant property we have access to... //$NON-NLS-1$ + iterator.remove(); } } } @@ -166,7 +173,7 @@ public class ContextEditorActionBarContributor extends EcoreActionBarContributor IAction action = iterator.next(); if (action instanceof CreateSiblingAction) { CreateSiblingAction createSiblingAction = (CreateSiblingAction) action; - if (createSiblingAction.getText().equals("Data Context Root")) { //It's the only relevant property we have access to... //$NON-NLS-1$ + if (createSiblingAction.getText().equals("Data Context Root")) { // It's the only relevant property we have access to... //$NON-NLS-1$ iterator.remove(); } } @@ -185,7 +192,7 @@ public class ContextEditorActionBarContributor extends EcoreActionBarContributor IAction action = iterator.next(); if (action instanceof CreateSiblingAction) { CreateSiblingAction createSiblingAction = (CreateSiblingAction) action; - if (createSiblingAction.getText().equals("Section")) { //It's the only relevant property we have access to... //$NON-NLS-1$ + if (createSiblingAction.getText().equals("Section")) { // It's the only relevant property we have access to... //$NON-NLS-1$ iterator.remove(); } } @@ -203,7 +210,7 @@ public class ContextEditorActionBarContributor extends EcoreActionBarContributor * The list of newly created {@link IAction}s */ protected Collection<IAction> createSiblingActionsForSection(ISelection selection, Section section) { - Collection<IAction> actions = new LinkedList<IAction>(); + Collection<IAction> actions = new LinkedList<>(); // TODO : We need to retrieve the view owning the section. It is only possible with an access to the // ITreeElements, which we don't have here. Find a way to retrieve it. @@ -227,7 +234,7 @@ public class ContextEditorActionBarContributor extends EcoreActionBarContributor * The list of newly created {@link IAction}s */ protected Collection<IAction> createChildForView(ISelection selection, View view) { - Collection<IAction> actions = new LinkedList<IAction>(); + Collection<IAction> actions = new LinkedList<>(); if (view.getContext() == null) { return actions; } @@ -301,7 +308,7 @@ public class ContextEditorActionBarContributor extends EcoreActionBarContributor * The newly created {@link IAction}s */ protected Collection<IAction> createChildForSection(ISelection selection) { - Collection<IAction> actions = new LinkedList<IAction>(); + Collection<IAction> actions = new LinkedList<>(); actions.add(new CreateSectionWidgetAction(selection)); @@ -310,11 +317,7 @@ public class ContextEditorActionBarContributor extends EcoreActionBarContributor @Override public void selectionChanged(SelectionChangedEvent event) { - ISelection newSelection = ActionUtil.getAdaptedSelection(event.getSelection()); - - SelectionChangedEvent newEvent = new SelectionChangedEvent(event.getSelectionProvider(), newSelection); - - super.selectionChanged(newEvent); + actionUtil.selectionChanged(event); } @Override diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/editor/UIEditor.java b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/editor/UIEditor.java index a9bf613121c..178ada406f1 100644 --- a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/editor/UIEditor.java +++ b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/editor/UIEditor.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2010, 2013, 2019 CEA LIST. + * Copyright (c) 2010, 2021, 2019 CEA LIST, Christian W. Damus, and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -12,9 +12,12 @@ * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation * Christian W. Damus (CEA) - Factor out workspace storage for pluggable storage providers (CDO) * Nicolas FAUVERGUE (CEA) nicolas.fauvergue@cea.fr - Bug 548720 + * Christian W. Damus - bug 573987 *****************************************************************************/ package org.eclipse.papyrus.views.properties.toolsmiths.editor; +import static org.eclipse.papyrus.views.properties.toolsmiths.preferences.CustomizationEditorActionKind.getOnOpenCustomizationEditorAction; + import java.io.IOException; import java.io.OutputStream; import java.util.EventObject; @@ -82,7 +85,9 @@ import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Tree; +import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IEditorSite; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.IPerspectiveDescriptor; import org.eclipse.ui.IWorkbenchPage; @@ -109,6 +114,14 @@ public class UIEditor extends EcoreEditor implements ITabbedPropertySheetPageCon private TreeViewer selectionViewer; @Override + public void init(IEditorSite site, IEditorInput editorInput) { + super.init(site, editorInput); + + IWorkbenchPage page = site.getPage(); + page.getWorkbenchWindow().getShell().getDisplay().asyncExec(() -> getOnOpenCustomizationEditorAction().perform(page)); + } + + @Override public void createPages() { // Creates the model from the editor input // diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/editor/actions/ToggleDataContextAction.java b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/editor/actions/ToggleDataContextAction.java deleted file mode 100644 index 588fe94c306..00000000000 --- a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/editor/actions/ToggleDataContextAction.java +++ /dev/null @@ -1,50 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2011 CEA LIST. - * - * 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: - * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation - *****************************************************************************/ -package org.eclipse.papyrus.views.properties.toolsmiths.editor.actions; - -import org.eclipse.core.commands.AbstractHandler; -import org.eclipse.core.commands.ExecutionEvent; -import org.eclipse.core.commands.ExecutionException; -import org.eclipse.papyrus.views.properties.toolsmiths.editor.UIEditor; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.PlatformUI; - -/** - * An action to toggle the display of the DataContextElements in the UIEditor - * - * @author Camille Letavernier - * - */ -public class ToggleDataContextAction extends AbstractHandler { - - /** - * Indicates if the DataContextElements should be displayed - */ - public static boolean showDataContext = false; - - @Override - public Object execute(ExecutionEvent event) throws ExecutionException { - showDataContext = !showDataContext; - IEditorPart editor = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); - if (editor instanceof UIEditor) { - UIEditor uiEditor = (UIEditor) editor; - uiEditor.getViewer().refresh(); - } - - // State state = event.getCommand().getState("org.eclipse.papyrus.customization.properties.displayContextState"); //$NON-NLS-1$ - // state.setValue(showDataContext); - return null; - } - -} diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/editor/actions/ToggleDataContextState.java b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/editor/actions/ToggleDataContextState.java deleted file mode 100644 index 3a6c413ce9d..00000000000 --- a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/editor/actions/ToggleDataContextState.java +++ /dev/null @@ -1,21 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2011 CEA LIST. - * - * 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: - * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation - *****************************************************************************/ -package org.eclipse.papyrus.views.properties.toolsmiths.editor.actions; - -import org.eclipse.core.commands.State; - - -public class ToggleDataContextState extends State { - -} diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/editor/actions/TogglePreviewAction.java b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/editor/actions/TogglePreviewAction.java index 3d5fc4654f4..7dc57289d4f 100644 --- a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/editor/actions/TogglePreviewAction.java +++ b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/editor/actions/TogglePreviewAction.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2011 CEA LIST. + * Copyright (c) 2011, 2021 CEA LIST, Christian W. Damus, and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -10,17 +10,23 @@ * * Contributors: * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus - bug 573987 *****************************************************************************/ package org.eclipse.papyrus.views.properties.toolsmiths.editor.actions; import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.Command; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.State; import org.eclipse.papyrus.views.properties.toolsmiths.Activator; +import org.eclipse.ui.ISources; import org.eclipse.ui.IViewReference; import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PartInitException; -import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.commands.ICommandService; +import org.eclipse.ui.handlers.HandlerUtil; import org.eclipse.ui.part.ViewPart; /** @@ -30,34 +36,22 @@ import org.eclipse.ui.part.ViewPart; */ public class TogglePreviewAction extends AbstractHandler { + private static final String STATE_ID = "org.eclipse.ui.commands.toggleState"; //$NON-NLS-1$ + private static final String COMMAND_ID = "org.eclipse.papyrus.customization.properties.TogglePreview"; //$NON-NLS-1$ + @Override public Object execute(ExecutionEvent event) throws ExecutionException { - - // System.out.println("Toggle"); - - event.getCommand().getState("org.eclipse.papyrus.customization.properties.previewstate"); //$NON-NLS-1$ - - IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + IWorkbenchPage activePage = HandlerUtil.getActiveWorkbenchWindowChecked(event).getActivePage(); if (activePage == null) { return null; } - // System.out.println("ActivePage is " + activePage); - - IViewReference viewReference = null; - - for (IViewReference reference : activePage.getViewReferences()) { - if (reference.getId().equals(Activator.PREVIEW_ID)) { - viewReference = reference; - } - } + IViewReference viewReference = activePage.findViewReference(Activator.PREVIEW_ID); try { if (viewReference == null) { - // System.out.println("Opening view"); activePage.showView(Activator.PREVIEW_ID); } else { - // System.out.println("Closing view"); activePage.hideView((ViewPart) viewReference.getPart(false)); } } catch (PartInitException ex) { @@ -67,5 +61,26 @@ public class TogglePreviewAction extends AbstractHandler { return null; } + @Override + public void setEnabled(Object evaluationContext) { + super.setEnabled(evaluationContext); + + IWorkbenchWindow activeWindow = (IWorkbenchWindow) HandlerUtil.getVariable(evaluationContext, ISources.ACTIVE_WORKBENCH_WINDOW_NAME); + IWorkbenchPage activePage = activeWindow == null ? null : activeWindow.getActivePage(); + if (activePage == null) { + return; + } + + ICommandService commandService = activeWindow.getService(ICommandService.class); + Command command = commandService.getCommand(COMMAND_ID); + + State state = (command == null) ? null : command.getState(STATE_ID); + if (state == null) { + return; + } + + IViewReference viewReference = activePage.findViewReference(Activator.PREVIEW_ID); + state.setValue(viewReference != null); + } } diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/editor/actions/TogglePreviewState.java b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/editor/actions/TogglePreviewState.java deleted file mode 100644 index e370ec3c223..00000000000 --- a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/editor/actions/TogglePreviewState.java +++ /dev/null @@ -1,153 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2011 CEA LIST. - * - * 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: - * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation - *****************************************************************************/ -package org.eclipse.papyrus.views.properties.toolsmiths.editor.actions; - -import org.eclipse.core.commands.State; -import org.eclipse.papyrus.views.properties.toolsmiths.editor.preview.Preview; -import org.eclipse.ui.IPartListener; -import org.eclipse.ui.IWindowListener; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.IWorkbenchPart; -import org.eclipse.ui.IWorkbenchWindow; - -/** - * A State to determine if the Preview view is opened in the current perspective - * The State should listen on the workbench an update itself when the perspective - * changes, or when the preview is opened or closed - * - * @FIXME : the state is not correctly retrieved - * @author Camille Letavernier - */ -public class TogglePreviewState extends State implements IWindowListener, IPartListener { - - private boolean isPreviewOpen; - - public TogglePreviewState() { - // System.out.println("Building ToggleState"); - // - // IWorkbench workbench = PlatformUI.getWorkbench(); - // - // workbench.addWindowListener(this); - // for(IWorkbenchWindow window : workbench.getWorkbenchWindows()) { - // System.out.println("Listening on " + window); - // window.getPartService().addPartListener(this); - // } - // refreshState(); - } - - private void refreshState() { - // isPreviewOpen = false; - // System.out.println("Refresh state"); - // - // IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); - // if(window != null) { - // IWorkbenchPage page = window.getActivePage(); - // - // if(page != null) { - // for(IViewReference reference : page.getViewReferences()) { - // if(reference.getId().equals(Activator.PREVIEW_ID)) { - // isPreviewOpen = true; - // break; - // } - // } - // } - // } - // - // System.out.println("IsOpen : " + isPreviewOpen); - // - // setValue(isPreviewOpen); - } - - @Override - public Object getValue() { - return isPreviewOpen; - } - - // IWindowListener - - @Override - public void windowOpened(IWorkbenchWindow window) { - // System.out.println("Listening on " + window); - window.getPartService().addPartListener(this); - refreshState(); - } - - @Override - public void windowClosed(IWorkbenchWindow window) { - // window.removePageListener(this); - window.getPartService().removePartListener(this); - } - - // IPageListener - // - // public void pageOpened(IWorkbenchPage page) { - // page.addPartListener(this); - // } - // - // public void pageClosed(IWorkbenchPage page) { - // page.removePartListener(this); - // } - - // IPartListener - - @Override - public void partOpened(IWorkbenchPart part) { - if (part instanceof Preview) { - // System.out.println("Closing preview"); - refreshState(); - } - } - - @Override - public void partClosed(IWorkbenchPart part) { - if (part instanceof Preview) { - // System.out.println("Closing preview"); - refreshState(); - } - } - - // Ignored methods - - @Override - public void partActivated(IWorkbenchPart part) { - // System.out.println("Part activated"); - // refreshState(); - } - - @Override - public void partBroughtToTop(IWorkbenchPart part) { - // Nothing - } - - @Override - public void partDeactivated(IWorkbenchPart part) { - // System.out.println("Part activated"); - // refreshState(); - } - - @Override - public void windowActivated(IWorkbenchWindow window) { - // Nothing - } - - @Override - public void windowDeactivated(IWorkbenchWindow window) { - // Nothing - } - - public void pageActivated(IWorkbenchPage page) { - // Nothing - } - -} diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/messages/Messages.java b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/messages/Messages.java index ce4247120f6..c27f5baf4d4 100644 --- a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/messages/Messages.java +++ b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/messages/Messages.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2010, 2013 CEA LIST. + * Copyright (c) 2010, 2021 CEA LIST, Christian W. Damus, and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -11,6 +11,7 @@ * Contributors: * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation * Christian W. Damus (CEA) - Factor out workspace storage for pluggable storage providers (CDO) + * Christian W. Damus - bug 573987 *****************************************************************************/ package org.eclipse.papyrus.views.properties.toolsmiths.messages; @@ -21,6 +22,8 @@ public class Messages extends NLS { private static final String BUNDLE_NAME = "org.eclipse.papyrus.views.properties.toolsmiths.messages.messages"; //$NON-NLS-1$ + public static String ContextEditorActionBarContributor_0; + public static String CopyContextAction_Copying; public static String CopyContextAction_InitializingTheCopyOf; @@ -73,6 +76,18 @@ public class Messages extends NLS { public static String CustomizationDialog_selectContextToEdit; + public static String CustomizationEditorActionKind_0; + + public static String CustomizationEditorActionKind_1; + + public static String CustomizationEditorActionKind_2; + + public static String CustomizationEditorActionKind_3; + + public static String CustomizationEditorActionKind_4; + + public static String CustomizationPreferencePage_0; + public static String CustomizationPreferencePage_AskForConfirmation; public static String CustomizationPreferencePage_OpenCustomizationPerspective; diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/messages/messages.properties b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/messages/messages.properties index bdc5b473bf5..46e961536aa 100644 --- a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/messages/messages.properties +++ b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/messages/messages.properties @@ -1,5 +1,5 @@ ############################################################################# -# Copyright (c) 2011, 2013 CEA LIST. +# Copyright (c) 2011, 2021 CEA LIST, Christian W. Damus, and others. # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License 2.0 @@ -11,7 +11,9 @@ # Contributors: # CEA LIST - Initial API and implementation # Christian W. Damus (CEA) - Factor out workspace storage for pluggable storage providers (CDO) +# Christian W. Damus - bug 573987 ############################################################################# +ContextEditorActionBarContributor_0=Context Editor CopyContextAction_Copying=Copying CopyContextAction_InitializingTheCopyOf=Initializing the copy of CopyContextAction_ThisMayTakeSomeTime=. This may take some time @@ -38,6 +40,12 @@ CustomizationDialog_enterConfigurationName=Enter the new configuration name CustomizationDialog_plugin=\ (Read-only) CustomizationDialog_removeSelectedContext=Removes the selected Context. This option is only available for writeable Contexts CustomizationDialog_selectContextToEdit=Select a context to edit. Read-only contexts should be copied before they can be edited. +CustomizationEditorActionKind_0=Customization Perspective +CustomizationEditorActionKind_1=Customization Preview +CustomizationEditorActionKind_2=Remember my decision +CustomizationEditorActionKind_3=Customization Editor +CustomizationEditorActionKind_4=The customization editor is usually associated with the customization perspective or preview view. What would you like to do? +CustomizationPreferencePage_0=On opening the customization editor CustomizationPreferencePage_AskForConfirmation=Ask for confirmation CustomizationPreferencePage_OpenCustomizationPerspective=Open customization perspective CustomizationPreferencePage_PropertyViewCustomizationPreferences=Property view customization preferences diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/preferences/CustomizationEditorActionKind.java b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/preferences/CustomizationEditorActionKind.java new file mode 100644 index 00000000000..55f264b232b --- /dev/null +++ b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/preferences/CustomizationEditorActionKind.java @@ -0,0 +1,156 @@ +/***************************************************************************** + * Copyright (c) 2021 Christian W. Damus, CEA LIST, 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 + * http://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.views.properties.toolsmiths.preferences; + +import static java.util.function.Predicate.not; +import static org.eclipse.papyrus.views.properties.toolsmiths.preferences.CustomizationPreferencePage.ON_OPEN_CUSTOMIZATION_EDITOR; + +import java.util.EnumSet; +import java.util.LinkedHashMap; +import java.util.Optional; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.dialogs.MessageDialogWithToggle; +import org.eclipse.jface.util.Policy; +import org.eclipse.papyrus.views.properties.toolsmiths.Activator; +import org.eclipse.papyrus.views.properties.toolsmiths.messages.Messages; +import org.eclipse.ui.IPerspectiveDescriptor; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.WorkbenchException; + +/** + * Enumeration of action preferences for the opening of the customization editor. + */ +public enum CustomizationEditorActionKind { + /** An "action" that simply does nothing when the customization editor is opened. */ + NOTHING("Do nothing"), //$NON-NLS-1$ + /** An action that switches the editor's window's perspective to the <em>Customization Perspective</em>. */ + PERSPECTIVE("Open the customization perspective"), //$NON-NLS-1$ + /** An action that shows the <em>Customization Preview</em> view in the editor's workbench page. */ + PREVIEW("Open the customization preview view"), //$NON-NLS-1$ + /** + * An action that prompts the user which action to take, with option to remember the decision in the + * preferences, and then delegates to the selected action. + */ + PROMPT("Ask what to do"); //$NON-NLS-1$ + + private final String label; + + CustomizationEditorActionKind(String label) { + this.label = label; + } + + /** + * Obtain a label to present in the user interface, in the preference selection + * and dialog buttons. + * + * @return a translatable label + */ + public String getLabel() { + return label; + } + + /** + * Perform the action that I represent. Note that all actions are no-ops if the current perspective + * of the given workbench page is the <em>Customization Perspective</em>, as that is the ideal scenario. + * Most especially, in that case the user would not be prompted for an action if the current preference + * is to ask each time. + * + * @param workbenchPage + * the workbench page in which the customization editor is opened + */ + public void perform(IWorkbenchPage workbenchPage) { + IPerspectiveDescriptor perspective = workbenchPage.getPerspective(); + if (perspective != null && Activator.CUSTOMIZATION_PERSPECTIVE_ID.equals(perspective.getId())) { + // Nothing to do + return; + } + + switch (this) { + case PERSPECTIVE: + try { + workbenchPage.getWorkbenchWindow().getWorkbench().showPerspective(Activator.CUSTOMIZATION_PERSPECTIVE_ID, workbenchPage.getWorkbenchWindow()); + } catch (WorkbenchException e) { + Policy.getStatusHandler().show(e.getStatus(), Messages.CustomizationEditorActionKind_0); + } + break; + case PREVIEW: + try { + // There's no harm in showing a view that is already present. And it would be brought + // to the front of its stack + workbenchPage.showView(Activator.PREVIEW_ID); + } catch (PartInitException e) { + Policy.getStatusHandler().show(e.getStatus(), Messages.CustomizationEditorActionKind_1); + } + break; + case PROMPT: + prompt(workbenchPage); + break; + default: + // Pass + break; + } + } + + /** + * Query the action to perform on opening the customization editor. + * + * @return the customization editor action kind + */ + public static CustomizationEditorActionKind getOnOpenCustomizationEditorAction() { + String pref = Optional.ofNullable(Activator.getDefault().getPreferenceStore().getString(ON_OPEN_CUSTOMIZATION_EDITOR)) + .filter(not(String::isBlank)).orElse(getDefault().name()); + return CustomizationEditorActionKind.valueOf(pref); + } + + /** + * Query the default value of the customization editor action preference. + * + * @return the default preference value, which is to {@linkplain #PROMPT prompt the user} + */ + public static CustomizationEditorActionKind getDefault() { + return PROMPT; + } + + private static void prompt(IWorkbenchPage workbenchPage) { + String toggleMessage = Messages.CustomizationEditorActionKind_2; + LinkedHashMap<String, Integer> buttons = new LinkedHashMap<>(); + EnumSet.complementOf(EnumSet.of(PROMPT)).forEach(v -> buttons.put(v.getLabel(), v.toButtonCode())); + + MessageDialogWithToggle dialog = new MessageDialogWithToggle(workbenchPage.getWorkbenchWindow().getShell(), + Messages.CustomizationEditorActionKind_3, null, Messages.CustomizationEditorActionKind_4, + MessageDialog.QUESTION, buttons, PREVIEW.ordinal(), + toggleMessage, false); + CustomizationEditorActionKind.forButtonCode(dialog.open()).ifPresent(result -> { + // The result cannot be "prompt" + result.perform(workbenchPage); + if (dialog.getToggleState()) { + Activator.getDefault().getPreferenceStore().setValue(ON_OPEN_CUSTOMIZATION_EDITOR, result.name()); + } + }); + } + + int toButtonCode() { + // Avoid the stock OK and Cancel values + return ordinal() + 2; + } + + static Optional<CustomizationEditorActionKind> forButtonCode(int code) { + return code < 2 ? Optional.empty() : Optional.of(values()[code - 2]); + } + +} diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/preferences/CustomizationPreferencePage.java b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/preferences/CustomizationPreferencePage.java index 10cd711442a..de0a90c6790 100644 --- a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/preferences/CustomizationPreferencePage.java +++ b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/preferences/CustomizationPreferencePage.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2010 CEA LIST. + * Copyright (c) 2010, 2021 CEA LIST, Christian W. Damus, and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -10,10 +10,14 @@ * * Contributors: * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus - bug 573987 *****************************************************************************/ package org.eclipse.papyrus.views.properties.toolsmiths.preferences; +import java.util.stream.Stream; + import org.eclipse.jface.preference.BooleanFieldEditor; +import org.eclipse.jface.preference.ComboFieldEditor; import org.eclipse.jface.preference.FieldEditorPreferencePage; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.papyrus.views.properties.toolsmiths.Activator; @@ -38,6 +42,8 @@ public class CustomizationPreferencePage extends FieldEditorPreferencePage imple */ public static final String ASK_FOR_CONFIRMATION = "askForConfirmation"; //$NON-NLS-1$ + public static final String ON_OPEN_CUSTOMIZATION_EDITOR = "onOpenCustomizationEditor"; //$NON-NLS-1$ + /** * * Constructor. @@ -89,6 +95,11 @@ public class CustomizationPreferencePage extends FieldEditorPreferencePage imple protected void createFieldEditors() { addField(new BooleanFieldEditor(OPEN_CUSTOMIZATION_PERSPECTIVE, Messages.CustomizationPreferencePage_OpenCustomizationPerspective, getFieldEditorParent())); addField(new BooleanFieldEditor(ASK_FOR_CONFIRMATION, Messages.CustomizationPreferencePage_AskForConfirmation, getFieldEditorParent())); + + String[][] onOpenCustomizationEditor = Stream.of(CustomizationEditorActionKind.values()) + .map(v -> new String[] { v.getLabel(), v.name() }) + .toArray(String[][]::new); + addField(new ComboFieldEditor(ON_OPEN_CUSTOMIZATION_EDITOR, Messages.CustomizationPreferencePage_0, onOpenCustomizationEditor, getFieldEditorParent())); } /** @@ -109,4 +120,5 @@ public class CustomizationPreferencePage extends FieldEditorPreferencePage imple public static boolean askForConfirmation() { return Activator.getDefault().getPreferenceStore().getBoolean(ASK_FOR_CONFIRMATION); } + } diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/preferences/CustomizationPreferencesInitializer.java b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/preferences/CustomizationPreferencesInitializer.java index c56f0a73eb0..f0c7be8894a 100644 --- a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/preferences/CustomizationPreferencesInitializer.java +++ b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/preferences/CustomizationPreferencesInitializer.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2011 CEA LIST. + * Copyright (c) 2011, 2021 CEA LIST, Christian W. Damus, and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -10,12 +10,12 @@ * * Contributors: * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus - bug 573987 *****************************************************************************/ package org.eclipse.papyrus.views.properties.toolsmiths.preferences; import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.papyrus.views.properties.toolsmiths.preferences.CustomizationPreferencePage; import org.eclipse.papyrus.views.properties.toolsmiths.Activator; /** @@ -30,6 +30,7 @@ public class CustomizationPreferencesInitializer extends AbstractPreferenceIniti IPreferenceStore store = Activator.getDefault().getPreferenceStore(); store.setDefault(CustomizationPreferencePage.OPEN_CUSTOMIZATION_PERSPECTIVE, true); store.setDefault(CustomizationPreferencePage.ASK_FOR_CONFIRMATION, true); + store.setDefault(CustomizationPreferencePage.OPEN_CUSTOMIZATION_PERSPECTIVE, CustomizationEditorActionKind.getDefault().name()); } } diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/query/GetVisibleFeaturesQuery.java b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/query/GetVisibleFeaturesQuery.java index 4599ca629f9..2f35923e17e 100644 --- a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/query/GetVisibleFeaturesQuery.java +++ b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/query/GetVisibleFeaturesQuery.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2016 CEA LIST and others. + * Copyright (c) 2016, 2021 CEA LIST, Christian W. Damus, and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -10,6 +10,7 @@ * * Contributors: * CEA LIST - Initial API and implementation + * Christian W. Damus - bug 573987 * *****************************************************************************/ @@ -35,7 +36,6 @@ import org.eclipse.papyrus.infra.properties.contexts.Context; import org.eclipse.papyrus.infra.properties.contexts.ContextsPackage; import org.eclipse.papyrus.infra.properties.contexts.util.ContextsSwitch; import org.eclipse.papyrus.infra.properties.ui.UiPackage; -import org.eclipse.papyrus.views.properties.toolsmiths.editor.actions.ToggleDataContextAction; /** * @author Camille Letavernier @@ -104,9 +104,7 @@ public class GetVisibleFeaturesQuery implements IJavaQuery2<EObject, List<ERefer protected Predicate<EReference> filterContextReferences(Context object) { return ref -> { - if (ref == ContextsPackage.Literals.CONTEXT__DATA_CONTEXTS) { // Show DataContexts only if the corresponding action is enabled - return ToggleDataContextAction.showDataContext; - } else if (ref == ContextsPackage.Literals.CONTEXT__PROTOTYPE) { // Show the Prototype reference only if it is set + if (ref == ContextsPackage.Literals.CONTEXT__PROTOTYPE) { // Show the Prototype reference only if it is set return object.getPrototype() != null; } return true; diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/query/ShowContextQuery.java b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/query/ShowContextQuery.java index b3029b40850..0ea0a305520 100644 --- a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/query/ShowContextQuery.java +++ b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/query/ShowContextQuery.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2011 CEA LIST. + * Copyright (c) 2011, 2021 CEA LIST, Christian W. Damus, and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -10,6 +10,7 @@ * * Contributors: * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus - bug 573987 *****************************************************************************/ package org.eclipse.papyrus.views.properties.toolsmiths.query; @@ -18,19 +19,22 @@ import org.eclipse.papyrus.emf.facet.efacet.core.exception.DerivedTypedElementEx import org.eclipse.papyrus.emf.facet.query.java.core.IJavaQuery2; import org.eclipse.papyrus.emf.facet.query.java.core.IParameterValueList2; import org.eclipse.papyrus.infra.properties.contexts.Context; -import org.eclipse.papyrus.views.properties.toolsmiths.editor.actions.ToggleDataContextAction; +import org.eclipse.papyrus.infra.properties.contexts.DataContextElement; /** - * A Query to test if the DataContextElements should be displayed in the UIEditor + * A Query to test if the {@link DataContextElement}s should be displayed in the {@code UIEditor}. * * @author Camille Letavernier + * + * @deprecated Since the 3.2 release of the bundle, contexts are always shown in the editor. */ +@Deprecated(since = "3.2") public class ShowContextQuery implements IJavaQuery2<Context, Boolean> { @Override public Boolean evaluate(Context source, IParameterValueList2 parameterValues, IFacetManager facetManager) throws DerivedTypedElementException { - Boolean result = ToggleDataContextAction.showDataContext; + Boolean result = true; return result; } diff --git a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/util/ActionUtil.java b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/util/ActionUtil.java index 8afdd39c7e0..f1a9f0b2071 100644 --- a/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/util/ActionUtil.java +++ b/plugins/views/properties/org.eclipse.papyrus.views.properties.toolsmiths/src/org/eclipse/papyrus/views/properties/toolsmiths/util/ActionUtil.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2010 CEA LIST. + * Copyright (c) 2010, 2021 CEA LIST, Christian W. Damus, and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -10,27 +10,80 @@ * * Contributors: * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus - bug 573987 *****************************************************************************/ package org.eclipse.papyrus.views.properties.toolsmiths.util; +import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.function.BiFunction; +import java.util.function.Consumer; import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.edit.command.CommandParameter; +import org.eclipse.emf.edit.domain.EditingDomain; +import org.eclipse.emf.edit.domain.IEditingDomainProvider; +import org.eclipse.emf.edit.ui.action.EditingDomainActionBarContributor; +import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.papyrus.emf.facet.custom.metamodel.v0_2_0.internal.treeproxy.EAttributeTreeElement; +import org.eclipse.papyrus.emf.facet.custom.metamodel.v0_2_0.internal.treeproxy.EObjectTreeElement; +import org.eclipse.papyrus.emf.facet.custom.metamodel.v0_2_0.internal.treeproxy.EReferenceTreeElement; +import org.eclipse.papyrus.emf.facet.custom.metamodel.v0_2_0.internal.treeproxy.EStructuralFeatureTreeElement; +import org.eclipse.papyrus.emf.facet.custom.metamodel.v0_2_0.internal.treeproxy.TreeElement; import org.eclipse.papyrus.infra.emf.utils.EMFHelper; /** - * Utility class for Actions + * Utility class for Actions. * * @author Camille Letavernier * */ public class ActionUtil { + private final EditingDomainActionBarContributor contributor; + private final Consumer<? super SelectionChangedEvent> selectionChangedHandler; + private final BiFunction<? super Collection<?>, ? super ISelection, ? extends Collection<IAction>> newChildActionsGenerator; + private final BiFunction<? super Collection<?>, ? super ISelection, ? extends Collection<IAction>> newSiblingActionsGenerator; + + private ISelection originalSelection; + + /** + * Initialize a utility instance for use in an action bar {@code contributor}. + * + * @param contributor + * the action-bar contributor that owns me + * @param selectionChangedHandler + * the basic selection-change handler of the {@code contributor}. This should usually be its EMF-generated + * implementation of {@link ISelectionChangedListener#selectionChanged(SelectionChangedEvent)} + * @param newChildActionsGenerator + * the basic new child actions creation method of the {@code contributor}. This should usually be its + * EMF-generated implementation of {@code generateCreateChildActions(...)} + * @param newSiblingActionsGenerator + * the basic new sibling actions creation method of the {@code contributor}. This should usually be its + * EMF-generated implementation of {@code generateCreateSiblingActions(...)} + */ + public ActionUtil(EditingDomainActionBarContributor contributor, + Consumer<? super SelectionChangedEvent> selectionChangedHandler, + BiFunction<? super Collection<?>, ? super ISelection, ? extends Collection<IAction>> newChildActionsGenerator, + BiFunction<? super Collection<?>, ? super ISelection, ? extends Collection<IAction>> newSiblingActionsGenerator) { + + super(); + + this.contributor = contributor; + this.selectionChangedHandler = selectionChangedHandler; + this.newChildActionsGenerator = newChildActionsGenerator; + this.newSiblingActionsGenerator = newSiblingActionsGenerator; + } + /** * EMF can only handle collections of EObjects. However, as the * customization plugin relies a lot on EMF Facet, we often have to handle @@ -45,7 +98,7 @@ public class ActionUtil { * The adapted selection */ public static Collection<Object> getAdaptedSelection(Collection<? extends Object> selection) { - Collection<Object> newSelection = new LinkedList<Object>(); + Collection<Object> newSelection = new LinkedList<>(); for (Object o : selection) { EObject semantic = EMFHelper.getEObject(o); newSelection.add(semantic == null ? o : semantic); @@ -69,7 +122,7 @@ public class ActionUtil { public static ISelection getAdaptedSelection(ISelection sourceSelection) { if (sourceSelection instanceof StructuredSelection) { StructuredSelection currentSelection = (StructuredSelection) sourceSelection; - List<Object> newSelection = new LinkedList<Object>(); + List<Object> newSelection = new LinkedList<>(); Iterator<?> it = currentSelection.iterator(); while (it.hasNext()) { @@ -84,4 +137,193 @@ public class ActionUtil { return sourceSelection; } } + + /** + * Get the only element of a {@code selection} if it is a structured selection containing exactly one element. + * + * @param selection + * a selection + * @return its one and only (structured) element + */ + public static Object getElement(ISelection selection) { + Object result = null; + + if (selection instanceof IStructuredSelection) { + IStructuredSelection structured = (IStructuredSelection) selection; + if (structured.size() == 1) { + result = structured.getFirstElement(); + } + } + + return result; + } + + /** + * If the {@code selection} contains an <em>EMF Facet</em> tree node, get the object from it + * that either the node represents or that owns it if the node is a feature node. + * + * @param selection + * a selection + * @return the EMF object that it represents, or {@code null} + * if the selection is just a regular EMF object or something else + */ + public static EObject unwrapTreeNode(ISelection selection) { + EObject result = null; + Object firstElement = getElement(selection); + if (firstElement instanceof TreeElement) { + result = unwrapTreeNode((TreeElement) firstElement); + } + return result; + } + + private static EObject unwrapTreeNode(TreeElement treeElement) { + EObject result = null; + + if (treeElement instanceof EObjectTreeElement) { + result = ((EObjectTreeElement) treeElement).getEObject(); + } else if (treeElement instanceof EStructuralFeatureTreeElement) { + EStructuralFeatureTreeElement featureElement = (EStructuralFeatureTreeElement) treeElement; + if (featureElement.getParent() != null) { + result = unwrapTreeNode(featureElement.getParent()); + } + } + + return result; + } + + /** + * If the {@code selection} contains an <em>EMF Facet</em> feature node, get the feature from it. + * + * @param selection + * a selection + * @return the EMF structural feature that it represents, or {@code null} + * if the selection is just a regular EMF object or something else + */ + public static EStructuralFeature unwrapTreeFeature(ISelection selection) { + EStructuralFeature result = null; + Object firstElement = getElement(selection); + if (firstElement instanceof EStructuralFeatureTreeElement) { + result = unwrapTreeFeature((EStructuralFeatureTreeElement) firstElement); + } + return result; + } + + private static EStructuralFeature unwrapTreeFeature(EStructuralFeatureTreeElement treeElement) { + EStructuralFeature result = null; + + if (treeElement instanceof EAttributeTreeElement) { + result = ((EAttributeTreeElement) treeElement).getEAttribute(); + } else if (treeElement instanceof EReferenceTreeElement) { + result = ((EReferenceTreeElement) treeElement).getEReference(); + } + + return result; + } + + /** + * If the {@code selection} contains an <em>EMF Facet</em> feature node, get the object that + * owns the feature (from this node's parent). + * + * @param selection + * a selection + * @return the EMF object that it owns the feature that the node represents, or {@code null} + * if the selection is just a regular EMF object or something else + */ + public static EStructuralFeature unwrapTreeParentFeature(ISelection selection) { + EStructuralFeature result = null; + Object firstElement = getElement(selection); + if (firstElement instanceof EObjectTreeElement) { + EObjectTreeElement object = (EObjectTreeElement) firstElement; + if (object.getParent() instanceof EStructuralFeatureTreeElement) { + result = unwrapTreeFeature((EStructuralFeatureTreeElement) object.getParent()); + } + } + return result; + } + + /** + * Handle the selection change on behalf of the owning action bar contributor. + * + * @param event + * the selection change event received by the action bar contributor + */ + public void selectionChanged(SelectionChangedEvent event) { + originalSelection = event.getSelection(); + + try { + ISelection newSelection = ActionUtil.getAdaptedSelection(event.getSelection()); + + SelectionChangedEvent newEvent = new SelectionChangedEvent(event.getSelectionProvider(), newSelection); + + selectionChangedHandler.accept(newEvent); + } finally { + originalSelection = null; + } + + } + + /** + * Create new child actions on behalf of the owning action bar contributor. + * + * @param descriptors + * the new-child descriptors gathered by the base EMF contributor framework + * @param the + * selection forward by the EMF contributor framework (which was replaced by this utility) + * @return the actions that the contributor should return to the EMF editor + */ + public Collection<IAction> createNewChildActions(Collection<?> descriptors, ISelection selection) { + Collection<IAction> result; + EObject unwrappedTreeObject = unwrapTreeNode(originalSelection); + EStructuralFeature unwrappedTreeFeature = unwrapTreeFeature(originalSelection); + + if (unwrappedTreeObject != null && unwrappedTreeFeature != null) { + descriptors = getEditingDomain().getNewChildDescriptors(unwrappedTreeObject, null); + descriptors.removeIf(d -> !(d instanceof CommandParameter) || ((CommandParameter) d).getEStructuralFeature() != unwrappedTreeFeature); + result = newChildActionsGenerator.apply(descriptors, new StructuredSelection(unwrappedTreeObject)); + } else { + result = newChildActionsGenerator.apply(descriptors, selection); + } + + return result; + } + + /** + * Create new sibling actions on behalf of the owning action bar contributor. + * + * @param descriptors + * the new-sibling descriptors gathered by the base EMF contributor framework + * @param the + * selection forward by the EMF contributor framework (which was replaced by this utility) + * @return the actions that the contributor should return to the EMF editor + */ + public Collection<IAction> createNewSiblingActions(Collection<?> descriptors, ISelection selection) { + Collection<IAction> result; + EObject unwrappedTreeObject = unwrapTreeNode(originalSelection); + EStructuralFeature unwrappedTreeFeature = unwrapTreeFeature(originalSelection); + EStructuralFeature unwrappedTreeParentFeature = unwrapTreeParentFeature(originalSelection); + + if (unwrappedTreeObject != null && unwrappedTreeFeature != null) { + descriptors = getEditingDomain().getNewChildDescriptors(null, unwrappedTreeObject); + descriptors.removeIf(d -> !(d instanceof CommandParameter) || ((CommandParameter) d).getEStructuralFeature() != unwrappedTreeFeature); + result = newSiblingActionsGenerator.apply(descriptors, new StructuredSelection(unwrappedTreeObject)); + } else if (unwrappedTreeObject != null && unwrappedTreeParentFeature != null) { + descriptors = new ArrayList<>(descriptors); + descriptors.removeIf(d -> !(d instanceof CommandParameter) || ((CommandParameter) d).getEStructuralFeature() != unwrappedTreeParentFeature); + result = newSiblingActionsGenerator.apply(descriptors, new StructuredSelection(unwrappedTreeObject)); + } else { + result = newSiblingActionsGenerator.apply(descriptors, selection); + } + + return result; + } + + /** + * Get the editor's editing domain from the contributor that owns me. + * + * @return the editing domain + */ + protected EditingDomain getEditingDomain() { + return ((IEditingDomainProvider) contributor.getActiveEditor()).getEditingDomain(); + } + } |