blob: 14679c56623e316a4890b26560eb2a74c9b7bba0 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2002, 2009 IBM Corporation 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:
* IBM Corporation - initial API and implementation
* Mariot Chauvin <mariot.chauvin@obeo.fr> - bug 164513
****************************************************************************/
package org.eclipse.gmf.runtime.diagram.ui.commands;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.workspace.util.WorkspaceSynchronizer;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.requests.CreateRequest;
import org.eclipse.gmf.runtime.common.core.command.AbstractCommand;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.internal.requests.SuppressibleUIRequest;
import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewAndElementRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateUnspecifiedTypeConnectionRequest;
import org.eclipse.gmf.runtime.emf.type.core.IElementType;
import org.eclipse.gmf.runtime.notation.View;
/**
* a command to create the both of the View and Semantic of the connection, but
* the editparts of target and source to obtain the command has not been created
* yet, since we have the ViewAdapter to we can use it to get its editpart once
* it is created and hence on execution time we can get its editpart to get the
* command for our request and then execute it.
*
* <p>
* This command can handle both
* <code>CreateConnectionViewAndElementRequest</code> and
* <code>CreateConnectionViewRequest</code>.
* </p>
*
* @author choang
*/
public class DeferredCreateConnectionViewAndElementCommand
extends AbstractCommand {
CreateRequest request = null;
IAdaptable typeInfoAdapter = null;
IAdaptable sourceViewAdapter = null;
IAdaptable targetViewAdapter = null;
Command command = null;
EditPartViewer viewer = null;
private DeferredCreateConnectionViewAndElementCommand(
IAdaptable sourceViewAdapter, IAdaptable targetViewAdapter,
EditPartViewer currentViewer) {
super(DiagramUIMessages.Commands_CreateCommand_Connection_Label, null);
Assert.isNotNull(currentViewer, "currentViewer is null"); //$NON-NLS-1$
this.sourceViewAdapter = sourceViewAdapter;
this.targetViewAdapter = targetViewAdapter;
this.viewer = currentViewer;
}
/**
* Constructor for DeferredCreateConnectionViewAndElementCommand.
*
* @param request
* the ceate connection request
* @param sourceViewAdapter
* will adapt to the source view at execution time
* @param targetViewAdapter
* will adapt to the target view at execution time
* @param currentViewer
* used to find the editparts for the views
*/
public DeferredCreateConnectionViewAndElementCommand(
CreateConnectionViewAndElementRequest request,
IAdaptable sourceViewAdapter, IAdaptable targetViewAdapter,
EditPartViewer currentViewer) {
this(sourceViewAdapter, targetViewAdapter, currentViewer);
this.request = request;
}
/**
* Constructor for DeferredCreateConnectionViewAndElementCommand.
*
* @param type
* the type to be used in a new
* <code>CreateConnectionViewAndElementRequest</code>
* @param sourceViewAdapter
* will adapt to the source view at execution time
* @param targetViewAdapter
* will adapt to the target view at execution time
* @param currentViewer
* used to find the editparts for the views
*/
public DeferredCreateConnectionViewAndElementCommand(IElementType type,
IAdaptable sourceViewAdapter, IAdaptable targetViewAdapter,
EditPartViewer currentViewer, PreferencesHint preferencesHint) {
this(new CreateConnectionViewAndElementRequest(type, preferencesHint),
sourceViewAdapter, targetViewAdapter, currentViewer);
}
/**
* Constructor for DeferredCreateConnectionViewAndElementCommand.
*
* @param request
* the create connection request
* @param typeInfoAdapter
* extracts the type to be used in a new
* <code>CreateConnectionViewAndElementRequest</code> at
* execution time
* @param sourceViewAdapter
* will adapt to the source view at execution time
* @param targetViewAdapter
* will adapt to the target view at execution time
* @param currentViewer
* used to find the editparts for the views
*/
public DeferredCreateConnectionViewAndElementCommand(CreateRequest request,
IAdaptable typeInfoAdapter, IAdaptable sourceViewAdapter,
IAdaptable targetViewAdapter, EditPartViewer currentViewer) {
this(sourceViewAdapter, targetViewAdapter, currentViewer);
this.request = request;
this.typeInfoAdapter = typeInfoAdapter;
}
public List getAffectedFiles() {
if (viewer != null) {
EditPart editpart = viewer.getRootEditPart().getContents();
if (editpart instanceof IGraphicalEditPart) {
View view = (View) editpart.getModel();
if (view != null) {
IFile f = WorkspaceSynchronizer.getFile(view.eResource());
return f != null ? Collections.singletonList(f)
: Collections.EMPTY_LIST;
}
}
}
return super.getAffectedFiles();
}
public boolean canUndo() {
return command != null && command.canUndo();
}
public boolean canRedo() {
return CommandUtilities.canRedo(command);
}
/**
* gives access to the connection source edit part, which is the edit part
* of the connection's source <code>View</code>
*
* @return the source edit part
*/
protected EditPart getSourceEditPart() {
return (IGraphicalEditPart) viewer.getEditPartRegistry().get(
sourceViewAdapter.getAdapter(View.class));
}
/**
* gives access to the connection target edit part, which is the edit part
* of the connection's target <code>View</code>
*
* @return the source edit part
*/
protected EditPart getTargetEditPart() {
return (IGraphicalEditPart) viewer.getEditPartRegistry().get(
targetViewAdapter.getAdapter(View.class));
}
/*
* (non-Javadoc)
* @see org.eclipse.core.commands.operations.AbstractOperation#canExecute()
*/
public boolean canExecute() {
if (!(request instanceof CreateConnectionViewRequest) && !(request instanceof CreateUnspecifiedTypeConnectionRequest))
return false;
if (request instanceof CreateUnspecifiedTypeConnectionRequest) {
if (typeInfoAdapter == null)
return false;
final IElementType typeInfo = (IElementType) typeInfoAdapter.getAdapter(IElementType.class);
if (typeInfo != null) {
if (((CreateUnspecifiedTypeConnectionRequest) request).getRequestForType(typeInfo) == null)
return false;
}
}
return true;
}
/**
* Finds the source and target editparts by extracting the views from the
* view adapters and searching in the editpart viewer. Creates a connection
* view and element using the request.
*
*/
protected CommandResult doExecuteWithResult(
IProgressMonitor progressMonitor, IAdaptable info)
throws ExecutionException {
CreateConnectionViewRequest req = null;
if (request != null) {
if (request instanceof CreateConnectionViewRequest) {
req = (CreateConnectionViewRequest) request;
}
} else {
return CommandResult.newErrorCommandResult(getLabel());
}
if (typeInfoAdapter != null) {
IElementType typeInfo = (IElementType) typeInfoAdapter
.getAdapter(IElementType.class);
if (typeInfo == null) {
return CommandResult.newErrorCommandResult(getLabel());
}
if (request instanceof CreateUnspecifiedTypeConnectionRequest) {
req = ((CreateConnectionViewRequest) ((CreateUnspecifiedTypeConnectionRequest) request)
.getRequestForType(typeInfo));
}
}
req.setLocation(null);
// Suppressing UI if the target edit part has not been created yet
// this is so that if we are creating a new target the connection
// creation will just take default data instead of prompting
// For Defect RATLC00524293
if (targetViewAdapter.getAdapter(IGraphicalEditPart.class) == null
&& req instanceof SuppressibleUIRequest)
((SuppressibleUIRequest) req).setSuppressibleUI(true);
EditPart sourceEP = getSourceEditPart();
EditPart targetEP = getTargetEditPart();
// There are situations where src or target can be null and we must
// check for these
// ie. When a Select Existing Dialog is presnetd to the user and the
// user presses
// cancel either the src or target can be null.
// So the following assertions have been replaced with a check for null
// on the editparts.
// old code ... Assert.isNotNull(sourceEP); Assert.isNotNull(targetEP);
if ((sourceEP == null) || (targetEP == null))
return null;
if (req instanceof CreateConnectionViewAndElementRequest) {
command = CreateConnectionViewAndElementRequest.getCreateCommand(
req, sourceEP, targetEP);
} else {
command = CreateConnectionViewRequest.getCreateCommand(req,
sourceEP, targetEP);
}
if (command != null && command.canExecute()) {
command.execute();
}
viewer = null;// for garbage collection
View view = (View) req.getConnectionViewDescriptor().getAdapter(
View.class);
if (null == view) {
return CommandResult.newCancelledCommandResult();
}
return CommandResult.newOKCommandResult(req.getNewObject());
}
/**
* @see org.eclipse.gmf.runtime.common.core.command.ICommand#getLabel()
*/
public String getLabel() {
if (command != null) {
return command.getLabel();
}
return null;
}
protected CommandResult doRedoWithResult(IProgressMonitor progressMonitor, IAdaptable info)
throws ExecutionException {
if (command != null) {
command.redo();
}
return CommandResult.newOKCommandResult();
}
protected CommandResult doUndoWithResult(IProgressMonitor progressMonitor, IAdaptable info)
throws ExecutionException {
if (command != null) {
command.undo();
}
return CommandResult.newOKCommandResult();
}
}