/******************************************************************************* | |
* Copyright (c) 2008, 2019 Mia-Software and others. | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Eclipse Public License v2.0 | |
* which accompanies this distribution, and is available at | |
* http://www.eclipse.org/legal/epl-v20.html | |
* | |
* Contributors: | |
* Nicolas Bros (Mia-Software) - initial API and implementation | |
* Nicolas Payneau (Mia-Software) - Enable editability | |
* | |
*******************************************************************************/ | |
package org.eclipse.modisco.infra.browser.editors; | |
import java.util.ArrayList; | |
import java.util.Collection; | |
import java.util.Iterator; | |
import org.eclipse.emf.common.command.AbstractCommand; | |
import org.eclipse.emf.common.command.Command; | |
import org.eclipse.emf.common.command.UnexecutableCommand; | |
import org.eclipse.emf.common.util.URI; | |
import org.eclipse.emf.ecore.EObject; | |
import org.eclipse.emf.ecore.EPackage; | |
import org.eclipse.emf.ecore.EReference; | |
import org.eclipse.emf.ecore.resource.Resource; | |
import org.eclipse.emf.ecore.resource.ResourceSet; | |
import org.eclipse.emf.edit.command.DeleteCommand; | |
import org.eclipse.emf.edit.command.RemoveCommand; | |
import org.eclipse.emf.edit.command.SetCommand; | |
import org.eclipse.emf.edit.domain.EditingDomain; | |
import org.eclipse.emf.edit.ui.action.CreateChildAction; | |
import org.eclipse.emf.edit.ui.action.CreateSiblingAction; | |
import org.eclipse.emf.edit.ui.action.CutAction; | |
import org.eclipse.emf.edit.ui.action.DeleteAction; | |
import org.eclipse.emf.edit.ui.action.EditingDomainActionBarContributor; | |
import org.eclipse.emf.edit.ui.action.ValidateAction; | |
import org.eclipse.jface.action.Action; | |
import org.eclipse.jface.action.ActionContributionItem; | |
import org.eclipse.jface.action.GroupMarker; | |
import org.eclipse.jface.action.IAction; | |
import org.eclipse.jface.action.IContributionItem; | |
import org.eclipse.jface.action.IContributionManager; | |
import org.eclipse.jface.action.IMenuListener; | |
import org.eclipse.jface.action.IMenuManager; | |
import org.eclipse.jface.action.IToolBarManager; | |
import org.eclipse.jface.action.MenuManager; | |
import org.eclipse.jface.action.Separator; | |
import org.eclipse.jface.action.SubContributionItem; | |
import org.eclipse.jface.dialogs.MessageDialog; | |
import org.eclipse.jface.viewers.ISelection; | |
import org.eclipse.jface.viewers.ISelectionProvider; | |
import org.eclipse.jface.viewers.IStructuredSelection; | |
import org.eclipse.jface.viewers.SelectionChangedEvent; | |
import org.eclipse.jface.viewers.StructuredSelection; | |
import org.eclipse.modisco.infra.browser.Messages; | |
import org.eclipse.modisco.infra.browser.actions.BrowseAction; | |
import org.eclipse.modisco.infra.browser.actions.DecreaseFontSizeAction; | |
import org.eclipse.modisco.infra.browser.actions.ExecuteSelectedQueryAction; | |
import org.eclipse.modisco.infra.browser.actions.IBrowserActionBarContributor; | |
import org.eclipse.modisco.infra.browser.actions.IncreaseFontSizeAction; | |
import org.eclipse.modisco.infra.browser.actions.LoadCustomizationsAction; | |
import org.eclipse.modisco.infra.browser.actions.LoadFacetsAction; | |
import org.eclipse.modisco.infra.browser.actions.OpenTableEditorAction; | |
import org.eclipse.modisco.infra.browser.actions.RefreshViewerAction; | |
import org.eclipse.modisco.infra.browser.actions.RemoveQueryAction; | |
import org.eclipse.modisco.infra.browser.actions.RestoreFontSizeAction; | |
import org.eclipse.modisco.infra.browser.actions.SelectQueryAction; | |
import org.eclipse.modisco.infra.browser.actions.ShowBothPanelsAction; | |
import org.eclipse.modisco.infra.browser.actions.ShowOnlyInstancesPanelAction; | |
import org.eclipse.modisco.infra.browser.actions.ShowOnlyTypesPanelAction; | |
import org.eclipse.modisco.infra.browser.actions.ShowPropertiesViewAction; | |
import org.eclipse.modisco.infra.browser.core.QueryItem; | |
import org.eclipse.modisco.infra.browser.editors.table.TableEditor; | |
import org.eclipse.modisco.infra.browser.uicore.internal.model.ITreeElement; | |
import org.eclipse.modisco.infra.browser.uicore.internal.model.LinkItem; | |
import org.eclipse.modisco.infra.browser.uicore.internal.model.ModelElementItem; | |
import org.eclipse.swt.SWT; | |
import org.eclipse.ui.IEditorPart; | |
import org.eclipse.ui.IWorkbenchActionConstants; | |
/** Action bar contributor for the MoDisco Ecore model browser. */ | |
public class BrowserActionBarContributor extends EditingDomainActionBarContributor implements | |
IBrowserSelectionChangedListener, IBrowserActionBarContributor { | |
private static final String EDIT_MENU_ID = "org.eclipse.modisco.infra.browser.editMenu"; //$NON-NLS-1$ | |
/** This keeps track of the active editor. */ | |
private IEditorPart fActiveEditor; | |
/** This keeps track of the current selection provider. */ | |
private ISelectionProvider selectionProvider; | |
/** This action opens the "Properties" view. */ | |
private final IAction showPropertiesViewAction = new ShowPropertiesViewAction(); | |
public EcoreBrowser getBrowser() { | |
return (EcoreBrowser) this.fActiveEditor; | |
} | |
/** This action opens a table editor on the current selection. */ | |
private final IAction openTableEditorAction = new OpenTableEditorAction(this); | |
/** | |
* This action refreshes the viewer of the current editor if the editor | |
* implements {@link org.eclipse.emf.common.ui.viewer.IViewerProvider}. | |
*/ | |
private final IAction refreshViewerAction = new RefreshViewerAction(this); | |
/** | |
* This action makes it possible to select a query to be shown on each | |
* occurrence of the selected model element | |
*/ | |
private final IAction selectQueryAction = new SelectQueryAction(this); | |
/** Executes the selected query(-ies) */ | |
private final IAction executeSelectedQueryAction = new ExecuteSelectedQueryAction(this); | |
/** Removes the selected query(-ies) */ | |
private final IAction removeQueryAction = new RemoveQueryAction(this); | |
/** | |
* The current selection, updated when an event is received from the | |
* selection provider | |
*/ | |
private ISelection fSelection; | |
public ISelection getSelection() { | |
return this.fSelection; | |
} | |
/** | |
* An action to show the selected element in the list of instances of its | |
* metaclass | |
*/ | |
private final Action browseAction = new BrowseAction(this); | |
/** An action to increase font size */ | |
private final Action increaseFontSizeAction = new IncreaseFontSizeAction(this); | |
/** An action to decrease font size */ | |
private final Action decreaseFontSizeAction = new DecreaseFontSizeAction(this); | |
/** An action to restore font size */ | |
private final Action restoreFontSizeAction = new RestoreFontSizeAction(this); | |
private final Action loadCustomizationsAction = new LoadCustomizationsAction(this); | |
private final Action loadFacetsAction = new LoadFacetsAction(this); | |
private final Action showOnlyInstancesPanelAction = new ShowOnlyInstancesPanelAction(this); | |
private final Action showOnlyTypesPanelAction = new ShowOnlyTypesPanelAction(this); | |
private final Action showBothPanelsAction = new ShowBothPanelsAction(this); | |
/** | |
* This will contain one | |
* {@link org.eclipse.emf.edit.ui.action.CreateChildAction} corresponding to | |
* each descriptor generated for the current selection by the item provider. | |
*/ | |
private Collection<IAction> createChildActions; | |
/** | |
* This is the menu manager into which menu contribution items should be | |
* added for CreateChild actions. | |
*/ | |
private IMenuManager createChildMenuManager; | |
private IMenuManager editorMenuManager; | |
// private final IAction loadMetamodelAction = new Action( | |
// Messages.BrowserActionBarContributor_loadMetamodel) { | |
// @Override | |
// public void run() { | |
// UriSelectionDialog uriSelectionDialog = new UriSelectionDialog( | |
// BrowserActionBarContributor.this.fActiveEditor.getSite().getShell()); | |
// uriSelectionDialog.setTitle(Messages.BrowserActionBarContributor_chooseMetamodel); | |
// if (uriSelectionDialog.open() == Window.OK) { | |
// String uri = uriSelectionDialog.getUriSelected(); | |
// EPackage ePackage = EPackage.Registry.INSTANCE.getEPackage(uri); | |
// EList<Resource> resources = getBrowser().getResourceSet().getResources(); | |
// if (ePackage.eResource() != null && | |
// !resources.contains(ePackage.eResource())) { | |
// resources.add(ePackage.eResource()); | |
// } | |
// } | |
// } | |
// }; | |
// /** | |
// * This will contain one | |
// * {@link org.eclipse.emf.edit.ui.action.CreateSiblingAction} | |
// corresponding | |
// * to each descriptor generated for the current selection by the item | |
// * provider. | |
// */ | |
// private Collection<IAction> createSiblingActions; | |
// | |
// /** | |
// * This is the menu manager into which menu contribution items should be | |
// * added for CreateSibling actions. | |
// */ | |
// private IMenuManager createSiblingMenuManager; | |
public BrowserActionBarContributor() { | |
super(EditingDomainActionBarContributor.ADDITIONS_LAST_STYLE); | |
this.validateAction = new ValidateAction() { | |
@Override | |
public boolean updateSelection(final IStructuredSelection selection) { | |
return super.updateSelection((IStructuredSelection) BrowserUtils | |
.unwrapSelection(selection)); | |
} | |
}; | |
} | |
/** This adds {@link Action}s to the tool bar. */ | |
@Override | |
public void contributeToToolBar(final IToolBarManager toolBarManager) { | |
toolBarManager.add(this.increaseFontSizeAction); | |
toolBarManager.add(this.decreaseFontSizeAction); | |
toolBarManager.add(this.restoreFontSizeAction); | |
toolBarManager.add(this.loadCustomizationsAction); | |
toolBarManager.add(this.loadFacetsAction); | |
} | |
/** | |
* When the active editor changes, this remembers the change and registers | |
* with it as a selection provider. | |
*/ | |
@Override | |
public void setActiveEditor(final IEditorPart part) { | |
super.setActiveEditor(part); | |
this.fActiveEditor = part; | |
// Switch to the new selection provider. | |
if (this.selectionProvider != null) { | |
this.selectionProvider.removeSelectionChangedListener(this); | |
} | |
if (part == null) { | |
this.selectionProvider = null; | |
} else { | |
if (part instanceof EcoreBrowser) { | |
final EcoreBrowser browser = (EcoreBrowser) part; | |
this.selectionProvider = browser.getSite().getSelectionProvider(); | |
this.selectionProvider.addSelectionChangedListener(this); | |
// Fake a selection changed event to update the menus. | |
if (browser.getEditorSelection() != null) { | |
selectionChanged(new SelectionChangedEvent(this.selectionProvider, | |
browser.getEditorSelection())); | |
} | |
} | |
} | |
} | |
/** | |
* This implements | |
* {@link org.eclipse.jface.viewers.ISelectionChangedListener}, memorizing | |
* {@link org.eclipse.jface.viewers.SelectionChangedEvent}s to be able to | |
* build the menu when they are about to be shown (see | |
* {@link BrowserActionBarContributor#menuAboutToShow(IMenuManager)}). | |
*/ | |
public void selectionChanged(final SelectionChangedEvent event) { | |
this.fSelection = event.getSelection(); | |
} | |
/** Update actions state depending on the selection in the editor */ | |
private void updateActions(final ISelection selection) { | |
this.browseAction.setEnabled(enableBrowse(selection)); | |
this.openTableEditorAction.setEnabled(TableEditor.canBeOpenedOnSelection(selection)); | |
if (selection instanceof IStructuredSelection) { | |
IStructuredSelection structuredSelection = (IStructuredSelection) selection; | |
this.validateAction.updateSelection(structuredSelection); | |
} else { | |
this.validateAction.updateSelection(StructuredSelection.EMPTY); | |
} | |
} | |
/** | |
* Whether to enable the browse action. The browse action is enabled only if | |
* the selected element corresponds to an EObject. | |
*/ | |
private boolean enableBrowse(final ISelection selection) { | |
if (selection instanceof IStructuredSelection) { | |
final IStructuredSelection structuredSelection = (IStructuredSelection) selection; | |
if (structuredSelection.size() != 1) { | |
return false; | |
} | |
final Object element = structuredSelection.getFirstElement(); | |
if (element instanceof ModelElementItem) { | |
EObject eObject = ((ModelElementItem) element).getEObject(); | |
Resource eResource = eObject.eResource(); | |
if (eResource != null) { | |
ResourceSet resourceSet = eResource.getResourceSet(); | |
if (resourceSet == getBrowser().getResourceSet()) { | |
return true; | |
} | |
} | |
return false; | |
} | |
} | |
return false; | |
} | |
/** This populates the pop-up menu before it appears. */ | |
@Override | |
public void menuAboutToShow(final IMenuManager menuManager) { | |
if (!getBrowser().isReadOnly()) { | |
final MenuManager submenuManager = new MenuManager(Messages.UI_CreateChild_menu_item); | |
submenuManager.setRemoveAllWhenShown(true); | |
submenuManager.addMenuListener(new IMenuListener() { | |
public void menuAboutToShow(final IMenuManager manager) { | |
updateMenu(); | |
populateManager(submenuManager, | |
BrowserActionBarContributor.this.createChildActions, null); | |
} | |
}); | |
menuManager.add(submenuManager); | |
// submenuManager = new | |
// MenuManager(Messages.UI_CreateSibling_menu_item); | |
// populateManager(submenuManager, this.createSiblingActions, null); | |
// menuManager.insertBefore("edit", submenuManager); //$NON-NLS-1$ | |
} | |
menuManager.add(this.browseAction); | |
menuManager.add(this.openTableEditorAction); | |
int nSelectedModelElementItems = selectionCount(ModelElementItem.class); | |
if (nSelectedModelElementItems > 0) { | |
menuManager.add(this.selectQueryAction); | |
if (nSelectedModelElementItems > 1) { | |
this.selectQueryAction.setText(Messages.SelectQueryAction_addQueryOnElements); | |
} else { | |
this.selectQueryAction.setText(Messages.SelectQueryAction_addQueryOnElement); | |
} | |
} | |
int nSelectedQueries = selectionCount(QueryItem.class); | |
if (nSelectedQueries > 0) { | |
menuManager.add(this.executeSelectedQueryAction); | |
menuManager.add(this.removeQueryAction); | |
if (nSelectedQueries > 1) { | |
this.executeSelectedQueryAction.setText(Messages.ExecuteQueryAction_executeQueries); | |
this.removeQueryAction.setText(Messages.RemoveQueryAction_removeQueries); | |
} else { | |
this.executeSelectedQueryAction | |
.setText(Messages.ExecuteQueryAction_executeSelectedQuery); | |
this.removeQueryAction.setText(Messages.RemoveQueryAction_removeQuery); | |
} | |
} | |
if (!getBrowser().isReadOnly()) { | |
super.menuAboutToShow(menuManager); | |
} | |
updateActions(getSelection()); | |
menuManager.add(new Separator()); | |
menuManager.add(this.showPropertiesViewAction); | |
menuManager.add(this.refreshViewerAction); | |
menuManager.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); | |
} | |
/** | |
* De-populate and re-populate the menu based on the current selection. | |
* Query for the children and siblings that can be added to the selected | |
* object and update the menus accordingly. | |
*/ | |
private void updateMenu() { | |
// Remove any menu items for old selection | |
if (this.createChildMenuManager != null) { | |
depopulateManager(this.createChildMenuManager, this.createChildActions); | |
} | |
// if (this.createSiblingMenuManager != null) { | |
// depopulateManager(this.createSiblingMenuManager, | |
// this.createSiblingActions); | |
// } | |
Collection<?> newChildDescriptors = null; | |
// Collection<?> newSiblingDescriptors = null; | |
ISelection selectionOnBrowser = null; | |
if (this.fSelection instanceof IStructuredSelection | |
&& ((IStructuredSelection) this.fSelection).size() == 1) { | |
if (this.fActiveEditor instanceof EcoreBrowser) { | |
selectionOnBrowser = ((EcoreBrowser) this.fActiveEditor).getSelection(); | |
Object selectedObject = ((IStructuredSelection) this.fSelection).getFirstElement(); | |
EditingDomain domain = getBrowser().getEditingDomain(); | |
newChildDescriptors = domain.getNewChildDescriptors(selectedObject, null); | |
// newSiblingDescriptors = domain.getNewChildDescriptors(null, | |
// selectedObject); | |
if (selectedObject instanceof LinkItem) { | |
LinkItem linkItem = (LinkItem) selectedObject; | |
selectionOnBrowser = new StructuredSelection( | |
((ModelElementItem) linkItem.getTreeParent()).getEObject()); | |
} | |
} | |
} | |
// Generate actions for selection; populate and redraw the menus | |
this.createChildActions = generateCreateChildActions(newChildDescriptors, | |
selectionOnBrowser); | |
// this.createSiblingActions = | |
// generateCreateSiblingActions(newSiblingDescriptors, | |
// selectionOnBrowser); | |
if (this.createChildMenuManager != null) { | |
populateManager(this.createChildMenuManager, this.createChildActions, null); | |
this.createChildMenuManager.update(true); | |
} | |
// if (this.createSiblingMenuManager != null) { | |
// populateManager(this.createSiblingMenuManager, | |
// this.createSiblingActions, null); | |
// this.createSiblingMenuManager.update(true); | |
// } | |
} | |
private int selectionCount(final Class<?> clazz) { | |
ISelection selection = getSelection(); | |
int count = 0; | |
if (selection instanceof IStructuredSelection) { | |
IStructuredSelection structuredSelection = (IStructuredSelection) selection; | |
Iterator<?> iterator = structuredSelection.iterator(); | |
while (iterator.hasNext()) { | |
Object element = iterator.next(); | |
if (clazz.isAssignableFrom(element.getClass())) { | |
count++; | |
} | |
} | |
} | |
return count; | |
} | |
@Override | |
public IEditorPart getActiveEditor() { | |
return this.fActiveEditor; | |
} | |
@Override | |
public void contributeToMenu(final IMenuManager menuManager) { | |
super.contributeToMenu(menuManager); | |
this.editorMenuManager = new MenuManager(Messages.UI_modiscoEditor_menu, | |
BrowserActionBarContributor.EDIT_MENU_ID); | |
menuManager.insertAfter("additions", this.editorMenuManager); //$NON-NLS-1$ | |
this.editorMenuManager.add(this.increaseFontSizeAction); | |
this.editorMenuManager.add(this.decreaseFontSizeAction); | |
this.editorMenuManager.add(this.restoreFontSizeAction); | |
this.editorMenuManager.add(this.loadCustomizationsAction); | |
this.editorMenuManager.add(this.loadFacetsAction); | |
this.editorMenuManager.add(new Separator()); | |
this.editorMenuManager.add(this.showOnlyInstancesPanelAction); | |
this.editorMenuManager.add(this.showOnlyTypesPanelAction); | |
this.editorMenuManager.add(this.showBothPanelsAction); | |
this.editorMenuManager.add(new Separator()); | |
this.editorMenuManager.add(this.showPropertiesViewAction); | |
this.editorMenuManager.add(this.refreshViewerAction); | |
this.editorMenuManager.add(new Separator("settings")); //$NON-NLS-1$ | |
this.editorMenuManager.add(new Separator("actions")); //$NON-NLS-1$ | |
this.editorMenuManager.add(new Separator("additions")); //$NON-NLS-1$ | |
this.editorMenuManager.add(new Separator("additions-end")); //$NON-NLS-1$ | |
// Prepare for CreateChild item addition or removal. | |
this.createChildMenuManager = new MenuManager(Messages.UI_CreateChild_menu_item); | |
this.createChildMenuManager.setRemoveAllWhenShown(true); | |
this.createChildMenuManager.addMenuListener(new IMenuListener() { | |
public void menuAboutToShow(final IMenuManager manager) { | |
// so that the "New Child" item is updated in the main menu | |
updateMenu(); | |
} | |
}); | |
this.editorMenuManager.insertBefore("additions", this.createChildMenuManager); //$NON-NLS-1$ | |
// Prepare for CreateSibling item addition or removal. | |
// this.createSiblingMenuManager = new | |
// MenuManager(Messages.UI_CreateSibling_menu_item); | |
// submenuManager.insertBefore("additions", this.createSiblingMenuManager); //$NON-NLS-1$ | |
// Force an update because Eclipse hides empty menus now. | |
this.editorMenuManager.addMenuListener(new IMenuListener() { | |
public void menuAboutToShow(final IMenuManager menuManag) { | |
menuManag.updateAll(true); | |
} | |
}); | |
addGlobalActions(this.editorMenuManager); | |
} | |
/** | |
* This generates a {@link org.eclipse.emf.edit.ui.action.CreateChildAction} | |
* for each object in <code>descriptors</code>, and returns the collection | |
* of these actions. | |
*/ | |
protected Collection<IAction> generateCreateChildActions(final Collection<?> descriptors, | |
final ISelection selection) { | |
Collection<IAction> actions = new ArrayList<IAction>(); | |
if (descriptors != null) { | |
for (Object descriptor : descriptors) { | |
actions.add(new CreateChildAction(this.fActiveEditor, selection, descriptor)); | |
} | |
} | |
return actions; | |
} | |
/** | |
* This generates a | |
* {@link org.eclipse.emf.edit.ui.action.CreateSiblingAction} for each | |
* object in <code>descriptors</code>, and returns the collection of these | |
* actions. | |
*/ | |
protected Collection<IAction> generateCreateSiblingActions(final Collection<?> descriptors, | |
final ISelection selection) { | |
Collection<IAction> actions = new ArrayList<IAction>(); | |
if (descriptors != null) { | |
for (Object descriptor : descriptors) { | |
actions.add(new CreateSiblingAction(this.fActiveEditor, selection, descriptor)); | |
} | |
} | |
return actions; | |
} | |
/** | |
* This populates the specified <code>manager</code> with | |
* {@link org.eclipse.jface.action.ActionContributionItem}s based on the | |
* {@link org.eclipse.jface.action.IAction}s contained in the | |
* <code>actions</code> collection, by inserting them before the specified | |
* contribution item <code>contributionID</code>. If | |
* <code>contributionID</code> is <code>null</code>, they are simply added. | |
*/ | |
protected void populateManager(final IContributionManager manager, | |
final Collection<? extends IAction> actions, final String contributionID) { | |
if (actions != null) { | |
for (IAction action : actions) { | |
if (contributionID != null) { | |
manager.insertBefore(contributionID, action); | |
} else { | |
manager.add(action); | |
} | |
} | |
} | |
// manager.add(this.loadMetamodelAction); | |
} | |
/** | |
* This removes from the specified <code>manager</code> all | |
* {@link org.eclipse.jface.action.ActionContributionItem}s based on the | |
* {@link org.eclipse.jface.action.IAction}s contained in the | |
* <code>actions</code> collection. | |
*/ | |
protected void depopulateManager(final IContributionManager manager, | |
final Collection<? extends IAction> actions) { | |
if (actions != null) { | |
IContributionItem[] items = manager.getItems(); | |
for (IContributionItem contributionItem : items) { | |
// Look into SubContributionItems | |
while (contributionItem instanceof SubContributionItem) { | |
contributionItem = ((SubContributionItem) contributionItem).getInnerItem(); | |
} | |
// Delete the ActionContributionItems with matching action. | |
if (contributionItem instanceof ActionContributionItem) { | |
IAction action = ((ActionContributionItem) contributionItem).getAction(); | |
if (actions.contains(action)) { | |
manager.remove(contributionItem); | |
} | |
} | |
} | |
} | |
} | |
@Override | |
protected boolean removeAllReferencesOnDelete() { | |
return true; | |
} | |
/** | |
* Overridden to deny deleting elements from the EPackage registry | |
* (metamodels), and ask the user whether to delete an element from the | |
* whole model or only remove it from under a reference | |
*/ | |
@Override | |
protected DeleteAction createDeleteAction() { | |
return new DeleteAction(removeAllReferencesOnDelete()) { | |
@Override | |
public Command createCommand(final Collection<?> selection) { | |
if (allowEditing(selection)) { | |
ISelection originalSelection = null; | |
EcoreBrowser browser = getBrowser(); | |
if (browser != null) { | |
originalSelection = browser.getEditorSelection(); | |
} | |
LinkItem parentLinkItem = null; | |
if (originalSelection instanceof IStructuredSelection) { | |
IStructuredSelection structuredSelection = (IStructuredSelection) originalSelection; | |
Iterator<?> iterator = structuredSelection.iterator(); | |
while (iterator.hasNext()) { | |
Object selected = iterator.next(); | |
if (selected instanceof ModelElementItem) { | |
ModelElementItem modelElementItem = (ModelElementItem) selected; | |
ITreeElement treeParent = modelElementItem.getTreeParent(); | |
if (treeParent instanceof LinkItem) { | |
LinkItem linkItem = (LinkItem) treeParent; | |
if (parentLinkItem == null) { | |
parentLinkItem = linkItem; | |
} else if (parentLinkItem != linkItem) { | |
parentLinkItem = null; | |
break; | |
} | |
} else { | |
parentLinkItem = null; | |
break; | |
} | |
} else { | |
parentLinkItem = null; | |
break; | |
} | |
} | |
} | |
if (parentLinkItem != null) { | |
EReference reference = parentLinkItem.getReference(); | |
if (!reference.isContainer() && !reference.isContainment() | |
&& !reference.isDerived()) { | |
return removeOrDeleteCommand(this.domain, selection, | |
parentLinkItem.getParent(), reference); | |
} | |
} | |
return super.createCommand(selection); | |
} | |
// editing not allowed | |
return UnexecutableCommand.INSTANCE; | |
} | |
}; | |
} | |
protected Command removeOrDeleteCommand(final EditingDomain domain, | |
final Collection<?> selection, final EObject owner, final EReference reference) { | |
final Command deleteCommand = DeleteCommand.create(domain, selection); | |
final Command removeCommand; | |
if (reference.isMany()) { | |
removeCommand = RemoveCommand.create(domain, owner, reference, selection); | |
} else { | |
removeCommand = SetCommand.create(domain, owner, reference, null); | |
} | |
AbstractCommand askUserCommand = new AbstractCommand() { | |
private static final int DELETE_FROM_MODEL = 0; | |
private static final int REMOVE_FROM_LINK = 1; | |
private static final int NO_OPERATION = 2; | |
private int operation = -1; | |
private void performCommand() { | |
if (this.operation == DELETE_FROM_MODEL) { | |
if (deleteCommand.canExecute()) { | |
deleteCommand.execute(); | |
} | |
} else if (this.operation == REMOVE_FROM_LINK) { | |
if (removeCommand.canExecute()) { | |
removeCommand.execute(); | |
} | |
} | |
} | |
public void redo() { | |
if (this.operation == DELETE_FROM_MODEL) { | |
deleteCommand.redo(); | |
} else if (this.operation == REMOVE_FROM_LINK) { | |
removeCommand.redo(); | |
} | |
} | |
@Override | |
public boolean canExecute() { | |
return deleteCommand.canExecute() || removeCommand.canExecute(); | |
} | |
public void execute() { | |
if (this.operation == -1) { | |
if (deleteCommand.canExecute() && removeCommand.canExecute()) { | |
MessageDialog dialog = new MessageDialog(null, | |
Messages.BrowserActionBarContributor_deleteOrRemove, null, | |
Messages.BrowserActionBarContributor_deleteOrRemove2, | |
MessageDialog.QUESTION, new String[] { | |
Messages.BrowserActionBarContributor_delete, | |
Messages.BrowserActionBarContributor_remove }, 1) { | |
{ | |
// style hint for MacOSX | |
setShellStyle(getShellStyle() | SWT.SHEET); | |
} | |
}; | |
this.operation = dialog.open(); | |
} else if (deleteCommand.canExecute()) { | |
if (MessageDialog.openQuestion(null, | |
Messages.BrowserActionBarContributor_deleteElement, | |
Messages.BrowserActionBarContributor_deleteButNotUnlink)) { | |
this.operation = DELETE_FROM_MODEL; | |
} else { | |
this.operation = NO_OPERATION; | |
} | |
} else if (removeCommand.canExecute()) { | |
if (MessageDialog.openQuestion(null, | |
Messages.BrowserActionBarContributor_removeElement, | |
Messages.BrowserActionBarContributor_removeButNotDelete)) { | |
this.operation = REMOVE_FROM_LINK; | |
} else { | |
this.operation = NO_OPERATION; | |
} | |
} | |
} | |
performCommand(); | |
} | |
@Override | |
public boolean canUndo() { | |
if (this.operation == DELETE_FROM_MODEL) { | |
return deleteCommand.canUndo(); | |
} else if (this.operation == REMOVE_FROM_LINK) { | |
return removeCommand.canUndo(); | |
} | |
return true; | |
} | |
@Override | |
public void undo() { | |
if (this.operation == DELETE_FROM_MODEL) { | |
deleteCommand.undo(); | |
} else if (this.operation == REMOVE_FROM_LINK) { | |
removeCommand.undo(); | |
} | |
} | |
}; | |
return askUserCommand; | |
} | |
/** | |
* Overridden to deny deleting elements from the EPackage registry | |
* (metamodels) | |
*/ | |
@Override | |
protected CutAction createCutAction() { | |
return new CutAction() { | |
@Override | |
public Command createCommand(final Collection<?> selection) { | |
if (allowEditing(selection)) { | |
return super.createCommand(selection); | |
} | |
return UnexecutableCommand.INSTANCE; | |
} | |
}; | |
} | |
/** | |
* Returns false to avoid changing elements from the EPackage registry (i.e. | |
* metamodels) | |
* | |
* @see Bug 319015 - [Model Browser] Null Pointer after deleting a field in | |
* a model | |
* @see Bug 319016 - [Model Browser] ClassCastException while saving a model | |
*/ | |
private static boolean allowEditing(final Collection<?> selection) { | |
for (Object selected : selection) { | |
if (selected instanceof EObject) { | |
EObject eObject = (EObject) selected; | |
Resource eResource = eObject.eResource(); | |
if (eResource != null) { | |
URI uri = eResource.getURI(); | |
if (uri != null | |
&& EPackage.Registry.INSTANCE.getEPackage(uri.toString()) != null) { | |
return false; | |
} | |
} | |
} | |
} | |
return true; | |
} | |
} |