/*******************************************************************************
* Copyright (c) 2006-2013 The RCP Company and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* The RCP Company - initial API and implementation
*******************************************************************************/
package com.rcpcompany.uibindings.handlers;
import java.util.List;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.command.AddCommand;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.actions.CompoundContributionItem;
import org.eclipse.ui.menus.IWorkbenchContribution;
import org.eclipse.ui.services.IEvaluationService;
import org.eclipse.ui.services.IServiceLocator;
import com.rcpcompany.uibindings.Constants;
import com.rcpcompany.uibindings.IChildCreationSpecification;
import com.rcpcompany.uibindings.IManager;
import com.rcpcompany.uibindings.IValueBinding;
import com.rcpcompany.uibindings.IViewerBinding;
import com.rcpcompany.uibindings.utils.IBindingObjectInformation;
import com.rcpcompany.uibindings.utils.UIBEcoreUtils;
/**
* Adds items to the "New..." sub-menu based on the current element of the current viewer.
*
* @author Tonny Madsen, The RCP Company
*/
public class NewHandlerMenuContributor extends CompoundContributionItem implements IWorkbenchContribution {
private IServiceLocator myServiceLocator;
public NewHandlerMenuContributor() {
}
public NewHandlerMenuContributor(String id) {
super(id);
}
@Override
public void initialize(IServiceLocator serviceLocator) {
myServiceLocator = serviceLocator;
}
/**
* Empty set of items.
* <p>
* Used when no items can be found in {@link #getContributionItems()}. This is needed as the
* menu is other not updated as it is visible but disable when it is empty...
*/
private static final IContributionItem[] EMPTY_ITEMS = new IContributionItem[1];
{
EMPTY_ITEMS[0] = new ContributionItem() {
@Override
public void fill(Menu menu, int index) {
final MenuItem item = new MenuItem(menu, SWT.NONE);
item.setText("Nothing to create...");
item.setEnabled(false);
};
};
}
@Override
protected IContributionItem[] getContributionItems() {
final IEvaluationService evalService = (IEvaluationService) myServiceLocator
.getService(IEvaluationService.class);
Object bb = evalService.getCurrentState().getVariable(Constants.SOURCES_ACTIVE_CONTAINER_BINDING);
if (!(bb instanceof IViewerBinding)) return EMPTY_ITEMS;
// The viewer
final IViewerBinding container = (IViewerBinding) bb;
bb = evalService.getCurrentState().getVariable(Constants.SOURCES_ACTIVE_BINDING);
final EObject obj;
if (bb instanceof IValueBinding) {
obj = ((IValueBinding) bb).getModelObject();
} else {
obj = null;
}
/*
* Only one selection please
*/
final List<IChildCreationSpecification> specs = container.getPossibleChildObjects(obj, null);
if (specs == null) return EMPTY_ITEMS;
// Only handle containment relations
for (final IChildCreationSpecification sp : specs.toArray(new IChildCreationSpecification[specs.size()])) {
if (!sp.getReference().isContainment()) {
specs.remove(sp);
}
}
/*
* Less than one specs... no need for an open with menu... Ignore.
*/
if (specs == null || specs.size() < 1) return EMPTY_ITEMS;
/*
* Create contributions items for all the specifications
*/
final IContributionItem[] items = new IContributionItem[specs.size()];
for (int i = 0; i < items.length; i++) {
final IChildCreationSpecification sp = specs.get(i);
final IContributionItem item = new NewContributionItem(sp, container, container.getEditingDomain());
items[i] = item;
}
return items;
}
/**
* A single menu entry.
*
* @author Tonny Madsen, The RCP Company
*/
public class NewContributionItem extends ContributionItem implements SelectionListener {
private final IChildCreationSpecification mySpec;
private final IViewerBinding myContainer;
private final EditingDomain myEditingDomain;
public NewContributionItem(IChildCreationSpecification sp, IViewerBinding container, EditingDomain ed) {
mySpec = sp;
myContainer = container;
myEditingDomain = ed;
}
private MenuItem myItem;
@Override
public void fill(Menu menu, int index) {
final IBindingObjectInformation i = IBindingObjectInformation.Factory.createObjectInformation(mySpec
.getChildType());
myItem = new MenuItem(menu, SWT.PUSH, index);
myItem.setText(i.getLabel());
myItem.setImage(i.getImage());
myItem.addSelectionListener(this);
}
protected void createObject() {
/*
* Two possible cases:
*
* - the reference is a containment reference, in which case, we want to add a new
* object,
*
* - or the reference is "normal" reference, in which case, we want to use a dialog
* first to select the object to add
*/
final EObject child;
Command initializeCommand;
if (mySpec.getReference().isContainment()) {
child = EcoreUtil.create(mySpec.getChildType());
/*
* Initialize the object
*/
initializeCommand = IManager.Factory.getManager().initializeObject(myEditingDomain, mySpec.getParent(),
mySpec.getReference(), child, false);
if (initializeCommand == null) return;
} else {
child = null;
UIBEcoreUtils.showErrorDialog("New Aborted", "Cannot add the selected objects", null);
return;
}
final CompoundCommand cmd = new CompoundCommand();
if (initializeCommand != null) {
cmd.append(initializeCommand);
}
if (mySpec.getReference().isMany()) {
cmd.append(AddCommand.create(myEditingDomain, mySpec.getParent(), mySpec.getReference(), child));
} else {
cmd.append(SetCommand.create(myEditingDomain, mySpec.getParent(), mySpec.getReference(), child));
}
/*
* Execute if possible...
*
* TODO return value
*/
if (!cmd.canExecute()) {
UIBEcoreUtils.showErrorDialog("New Aborted", "Cannot add the selected objects", null);
return;
}
// LogUtils.debug(this, "execute");
myEditingDomain.getCommandStack().execute(cmd);
/*
* Select the new child object
*/
final ColumnViewer viewer = myContainer.getViewer();
viewer.setSelection(new StructuredSelection(child), true);
/*
* Possibly open an editor
*/
// TODO
}
@Override
public void widgetSelected(SelectionEvent e) {
createObject();
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
createObject();
}
}
}