blob: 3b3f8bd06dc88b55292f6cc4df1cffe61ea266cd [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2004, 2008 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
****************************************************************************/
package org.eclipse.gmf.runtime.diagram.ui.internal.commands;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.workspace.AbstractEMFOperation;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.commands.Command;
import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.CanonicalEditPolicy;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.EditPolicyRoles;
import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages;
/**
* A command that will enable/disable the canonical editpolicy
* installed on the supplied editparts.
* @author mhanner
*/
public class ToggleCanonicalModeCommand extends Command {
/** enablement flag. */
private boolean _enable;
/** list of semantic elements canonical editpolicies are listening to. */
private Collection _semanticHosts = new ArrayList();
// an operation to enable undo using Transaction API is possible
private AbstractEMFOperation op = null;
// domain to use to record the change that will happenwhen we re-enable the edit policy
private TransactionalEditingDomain domain;
/**
* Create an instance.
* @param editParts collection of editparts who's canonical editpolicies will be affected.
* @param enable enablement flag
*/
public ToggleCanonicalModeCommand(Collection editParts, boolean enable) {
super(DiagramUIMessages.ToggleCanonicalModeCommand_Label);
Object[] editparts = new Object[editParts.size()];
editParts.toArray(editparts);
for ( int i = 0; i < editparts.length; i++ ) {
EditPart editPart = (EditPart)editparts[i];
if (editPart != null) {
CanonicalEditPolicy editPolicy = getCanonicalEditPolicy(editPart);
if ( editPolicy != null ) {
_semanticHosts.add( new WeakReference(editPolicy.getSemanticHost()) );
}
}
}
_enable = enable;
}
/**
* Create an instance.
* @param element a semantic element
* @param enable enablement flag
*/
public ToggleCanonicalModeCommand( EObject element, boolean enable ) {
super(DiagramUIMessages.ToggleCanonicalModeCommand_Label);
_semanticHosts.add( new WeakReference(element) );
_enable = enable;
}
/**
* Create an instance.
* @param target the target editpart
* @param enable the enablement flag
*/
public ToggleCanonicalModeCommand(EditPart target, boolean enable) {
this( Collections.singletonList(target), enable);
}
/**
* <code>ToggleCanonicalModeCommand</code> factory method.
* @param editParts collection of editparts who's canonical editpolicies will be affected.
* @param enable enablement flag
* @return a <code>ToggleCanonicalModeCommand</code> if at least one of the supplied editparts
* has a <code>CanonicalEditPolicy</code> installed on it, otherwise <tt>null</tt>.
*/
public static ToggleCanonicalModeCommand getToggleCanonicalModeCommand( Collection editParts, boolean enable) {
ToggleCanonicalModeCommand cmd = new ToggleCanonicalModeCommand( editParts, enable );
return cmd.getSemanticHosts().isEmpty() ? null : cmd;
}
/**
* <code>ToggleCanonicalModeCommand</code> factory method. This copy constructor style factory
* will return a new command that shares the supplied commands semantic hosts.
* @param tcmd a <code>ToggleCanonicalModeCommand</code>
* @param enable enablement flag
* @return a <code>ToggleCanonicalModeCommand</code> if at least one of the supplied editparts
* has a <code>CanonicalEditPolicy</code> installed on it, otherwise <tt>null</tt>.
*/
public static ToggleCanonicalModeCommand getToggleCanonicalModeCommand( ToggleCanonicalModeCommand tcmd, boolean enable) {
if ( tcmd == null || tcmd.getSemanticHosts().isEmpty() ) {
return null;
}
ToggleCanonicalModeCommand cmd = new ToggleCanonicalModeCommand( Collections.EMPTY_LIST, enable );
cmd.setSemanticHosts( tcmd.getSemanticHosts() );
return cmd;
}
/**
* Return the set of semantic hosts on which a canonical editpolicy is listening.
* @return semantic hosts
*/
protected final Collection getSemanticHosts() {
return _semanticHosts;
}
private final void setSemanticHosts( Collection hosts ) {
_semanticHosts.clear();
_semanticHosts.addAll(hosts);
}
/**
* Return the canonical editpolicy installed on the supplied editpart.
* @param editPart edit part to use
* @return the canoncial edit policy if there is any
*/
protected static CanonicalEditPolicy getCanonicalEditPolicy(
EditPart editPart) {
// If the editpart is a group, then we want to get the first parent
// that isn't a group and get the canonical editpolicy there.
while (editPart instanceof GroupEditPart) {
editPart = editPart.getParent();
}
return (CanonicalEditPolicy) editPart
.getEditPolicy(EditPolicyRoles.CANONICAL_ROLE);
}
/** Removes the canonical editpolict from the target editpart. */
public void execute() {
// try to record only if we are enabling the edit policy
if (_enable && domain != null) {
op = new AbstractEMFOperation(domain, "") { //$NON-NLS-1$
protected IStatus doExecute(IProgressMonitor monitor, IAdaptable info)
throws ExecutionException {
DoEnable(_enable);
return Status.OK_STATUS;
}
};
try {
op.execute(null, null);
} catch (ExecutionException e) {
//I give up... just do the enable.
DoEnable(_enable);
}
}else{
DoEnable(_enable);
}
}
/**
* Enables the canonical editpolicies listening of the list of
* semantic elements.
* @param enable enablement flag
*/
private void DoEnable(boolean enable) {
Iterator references = getSemanticHosts().iterator();
while( references.hasNext() ) {
WeakReference wr = (WeakReference)references.next();
EObject semanticHost = (EObject)wr.get();
if (semanticHost != null) {
List ceps = CanonicalEditPolicy.getRegisteredEditPolicies(semanticHost);
for ( int i = 0; i < ceps.size(); i++ ) {
CanonicalEditPolicy cep = (CanonicalEditPolicy)ceps.get(i);
cep.enableRefresh(enable);
}
}
}
}
/* (non-Javadoc)
* @see org.eclipse.gef.commands.Command#redo()
*/
public void redo() {
if (op != null) {
try {
op.redo(null, null);
} catch (ExecutionException e) {
// Give up...
}
}
DoEnable(_enable);
}
/* (non-Javadoc)
* @see org.eclipse.gef.commands.Command#undo()
*/
public void undo() {
// the enable is not an EMF command, so we had to undo it manually before undo the EMF operation
DoEnable(!_enable);
if (op != null) {
try {
op.undo(null, null);
} catch (ExecutionException e) {
// Give up...
}
}
}
public void setDomain(TransactionalEditingDomain d) {
domain = d;
}
}