/*****************************************************************************
* Copyright (c) 2008 CEA LIST.
*
*
* 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:
* Patrick Tessier (CEA LIST) Patrick.tessier@cea.fr - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.clazz.custom.helper;
import java.util.ArrayList;
import java.util.Iterator;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.requests.ReconnectRequest;
import org.eclipse.gmf.runtime.common.core.command.CompositeCommand;
import org.eclipse.gmf.runtime.common.core.util.StringStatics;
import org.eclipse.gmf.runtime.diagram.core.commands.SetConnectionAnchorsCommand;
import org.eclipse.gmf.runtime.diagram.core.commands.SetConnectionEndsCommand;
import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.editparts.INodeEditPart;
import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages;
import org.eclipse.gmf.runtime.emf.core.util.EObjectAdapter;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.GeneralizationSetEditPart;
import org.eclipse.papyrus.uml.diagram.common.helper.ElementHelper;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.uml2.uml.Generalization;
import org.eclipse.uml2.uml.GeneralizationSet;
import org.eclipse.uml2.uml.UMLFactory;
/**
* The Class GeneralizationSetHelper in charge to manage the creation and the movement of the
* GeneralizationSet.
*/
public class GeneralizationSetHelper extends ElementHelper {
protected static final String CHOOSE_A_FOLLOWING_GENERALIZATION_SET_TO_CONNECT = "Choose a following generalizationSet to connect:";
/**
* The listener interface for receiving dialog events. The class that is interested in
* processing a dialog event implements this interface, and the object created with that class
* is registered with a component using the component's <code>addDialogListener<code> method. When
* the dialog event occurs, that object's appropriate
* method is invoked.
*
* @see DialogEvent
*/
private class DialogListener implements Listener {
/** The abutton ok. */
private Button abuttonOk;
/** The acombo. */
private List acombo;
/** The ageneralization set. */
private GeneralizationSet ageneralizationSet = null;
/** The ageneralization set list. */
private ArrayList<GeneralizationSet> ageneralizationSetList;
/**
* Instantiates a new dialog listener.
*
* @param generalizationSetList
* the generalization set list
* @param combo
* the combo
* @param buttonOK
* the button ok
*/
public DialogListener(ArrayList<GeneralizationSet> generalizationSetList, List combo, Button buttonOK) {
this.ageneralizationSetList = generalizationSetList;
this.acombo = combo;
this.abuttonOk = buttonOK;
}
/**
* Gets the result.
*
* @return the result
*/
public GeneralizationSet getResult() {
return ageneralizationSet;
}
/**
* {@inheritedDoc}
*/
public void handleEvent(Event event) {
if(event.widget.equals(abuttonOk)) {
// look for selected button
int selectedButtonIndex = 0;
selectedButtonIndex = acombo.getSelectionIndex();
if(selectedButtonIndex >= 0) {
ageneralizationSet = ageneralizationSetList.get(selectedButtonIndex);
}
((Shell)abuttonOk.getParent()).close();
}
}
}
protected static final String WOULD_YOU_LIKE_TO_CREATE_A_NEW_GENERALIZATION = "Would you like to create a new Generalization?";
/** The generalization setto create. */
private GeneralizationSet generalizationSettoCreate;
/**
* Instantiates a new generalization set helper.
*
* @param editDomain
* the edit domain
*/
public GeneralizationSetHelper(TransactionalEditingDomain editDomain) {
this.editDomain = editDomain;
}
/**
* Creates the generalization set.
*
* @param source
* the source of the GenralizationSet
* @param target
* the target the Target of the Generalization
* @param container
* the container of the GeneralizationSet
*
* @return the generalization set
*/
public GeneralizationSet createGeneralizationSet(Generalization source, Generalization target, org.eclipse.uml2.uml.Package container) {
final ArrayList<GeneralizationSet> generalizationSetList = new ArrayList<GeneralizationSet>(source.getGeneralizationSets());
Iterator<GeneralizationSet> iterator = target.getGeneralizationSets().iterator();
while(iterator.hasNext()) {
GeneralizationSet currentGeneralizationSet = (GeneralizationSet)iterator.next();
if(!generalizationSetList.contains(currentGeneralizationSet)) {
generalizationSetList.add(currentGeneralizationSet);
}
}
if(generalizationSetList.size() > 0) {
launchDialog(generalizationSetList, getEditingDomain());
}
if(generalizationSettoCreate == null) {
generalizationSettoCreate = UMLFactory.eINSTANCE.createGeneralizationSet();
generalizationSettoCreate.setName("GeneralizationSet_" + source.getSpecific().getName() + "_" + target.getSpecific().getName());
container.getPackagedElements().add(generalizationSettoCreate);
}
if(!generalizationSettoCreate.getGeneralizations().contains(source)) {
generalizationSettoCreate.getGeneralizations().add(source);
}
if(!generalizationSettoCreate.getGeneralizations().contains(target)) {
generalizationSettoCreate.getGeneralizations().add(target);
}
return generalizationSettoCreate;
}
/**
* In change to move anchor of other GeneralizationSet when moving one
*
* @param request
* a request ReconnectRequest
* @param command
* the command that will move anchor of other Generalization that have the same
* semantic
* @param node
* the node
* @param targetAnchor
* the target anchor
*
* @return the move target
*/
public org.eclipse.gef.commands.Command getMoveTarget(ReconnectRequest request, org.eclipse.gef.commands.Command command, INodeEditPart node, ConnectionAnchor targetAnchor) {
//System.err.println("custom reconnection for GeneralizationSet target");
org.eclipse.gef.commands.CompoundCommand cc = new org.eclipse.gef.commands.CompoundCommand();
// look for all Generalization set connected to the source location that reference the same
// generalizationSet
ArrayList linkList = new ArrayList();
linkList.addAll(node.getSourceConnections());
linkList.addAll(node.getTargetConnections());
// remove reconnected link
linkList.remove(request.getConnectionEditPart());
// get the link that refer the same model element
GeneralizationSetEditPart edgeToMove = null;
Iterator iterator = linkList.iterator();
while(iterator.hasNext()) {
Object currentObject = iterator.next();
if(currentObject instanceof GeneralizationSetEditPart) {
if(((GeneralizationSetEditPart)request.getConnectionEditPart()).resolveSemanticElement().equals(((GeneralizationSetEditPart)currentObject).resolveSemanticElement())) {
edgeToMove = (GeneralizationSetEditPart)currentObject;
}
}
}
cc.add(command);
if(edgeToMove != null) {
SetConnectionAnchorsCommand scaCommandbis = new SetConnectionAnchorsCommand(getEditingDomain(), StringStatics.BLANK);
scaCommandbis.setEdgeAdaptor(new EObjectAdapter((View)edgeToMove.getModel()));
if(node.getSourceConnections().contains(edgeToMove)) {
scaCommandbis.setNewSourceTerminal(node.mapConnectionAnchorToTerminal(targetAnchor));
} else {
scaCommandbis.setNewTargetTerminal(node.mapConnectionAnchorToTerminal(targetAnchor));
}
cc.add(new ICommandProxy(scaCommandbis));
}
return cc;
}
/**
* this command is used to overload the reconnect source command in order to move other
* GeneralizationSet that have the same semantic
*
* @param request
* the request
* @param node
* the node
*
* @return the reconnect source command
*/
public Command getReconnectSourceCommand(ReconnectRequest request, INodeEditPart node) {
// System.err.println("custom reconnection for GeneralizationSet source");
// System.err.println("node--> " + node);
if(node == null)
return null;
TransactionalEditingDomain editingDomain = getEditingDomain();
ConnectionAnchor sourceAnchor = node.getSourceConnectionAnchor(request);
// System.err.println("sourceAnchor--> " + sourceAnchor.getReferencePoint());
SetConnectionEndsCommand sceCommand = new SetConnectionEndsCommand(editingDomain, StringStatics.BLANK);
sceCommand.setEdgeAdaptor(new EObjectAdapter((View)request.getConnectionEditPart().getModel()));
sceCommand.setNewSourceAdaptor(new EObjectAdapter((View)node.getModel()));
SetConnectionAnchorsCommand scaCommand = new SetConnectionAnchorsCommand(editingDomain, StringStatics.BLANK);
scaCommand.setEdgeAdaptor(new EObjectAdapter((View)request.getConnectionEditPart().getModel()));
scaCommand.setNewSourceTerminal(node.mapConnectionAnchorToTerminal(sourceAnchor));
CompositeCommand cc = new CompositeCommand(DiagramUIMessages.Commands_SetConnectionEndsCommand_Source);
cc.compose(sceCommand);
cc.compose(scaCommand);
// look for all Generalization set connected to the source location that reference the same
// generalizationSet
ArrayList linkList = new ArrayList();
linkList.addAll(node.getSourceConnections());
linkList.addAll(node.getTargetConnections());
// remove reconnected link
linkList.remove(request.getConnectionEditPart());
// get the link that refer the same model element
GeneralizationSetEditPart edgeToMove = null;
Iterator iterator = linkList.iterator();
while(iterator.hasNext()) {
Object currentObject = iterator.next();
if(currentObject instanceof GeneralizationSetEditPart) {
if(((GeneralizationSetEditPart)request.getConnectionEditPart()).resolveSemanticElement().equals(((GeneralizationSetEditPart)currentObject).resolveSemanticElement())) {
edgeToMove = (GeneralizationSetEditPart)currentObject;
}
}
}
if(edgeToMove != null) {
SetConnectionAnchorsCommand scaCommandbis = new SetConnectionAnchorsCommand(editingDomain, StringStatics.BLANK);
scaCommandbis.setEdgeAdaptor(new EObjectAdapter((View)edgeToMove.getModel()));
if(node.getSourceConnections().contains(edgeToMove)) {
scaCommandbis.setNewSourceTerminal(node.mapConnectionAnchorToTerminal(sourceAnchor));
} else {
scaCommandbis.setNewTargetTerminal(node.mapConnectionAnchorToTerminal(sourceAnchor));
}
cc.compose(scaCommandbis);
}
return new ICommandProxy(cc);
}
/**
* Launch dialog when a GeneralizationSet is created. I ask to the user if he would like to
* create a new semantic or reuse an existed semantic
*
* @param generalizationSetList
* the generalization set list
* @param editingDomain
* the editing domain
*/
private void launchDialog(final ArrayList<GeneralizationSet> generalizationSetList, TransactionalEditingDomain editingDomain) {
// Thread myThread = new Thread(new Runnable() {
// public void run() {
Display.getDefault().syncExec(new Runnable() {
public void run() {
Display display = Display.getCurrent();// new Display();
final Button[] radios = new Button[2];
final Shell dialog = new Shell(display, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
dialog.setBackground(ColorConstants.white);
GridLayout gridLayout = new GridLayout(2, false);
gridLayout.verticalSpacing = 8;
dialog.setLayout(gridLayout);
dialog.setText("GeneralizationSet Selection");
// Line1: Proposition of a new GeneralizationSet
Label text = new Label(dialog, SWT.CENTER);
text.setText(WOULD_YOU_LIKE_TO_CREATE_A_NEW_GENERALIZATION);
text.setBackground(ColorConstants.white);
GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gridData.horizontalSpan = 1;
text.setLayoutData(gridData);
radios[0] = new Button(dialog, SWT.RADIO);
radios[0].setBackground(ColorConstants.white);
gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gridData.horizontalSpan = 1;
radios[0].setLayoutData(gridData);
// Line2:
text = new Label(dialog, SWT.CENTER);
text.setBackground(ColorConstants.white);
text.setText(CHOOSE_A_FOLLOWING_GENERALIZATION_SET_TO_CONNECT);
gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gridData.horizontalSpan = 1;
text.setLayoutData(gridData);
radios[1] = new Button(dialog, SWT.RADIO);
radios[1].setBackground(ColorConstants.white);
gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gridData.horizontalSpan = 1;
radios[1].setLayoutData(gridData);
// Line3..X: the combo
final List list = new List(dialog, SWT.MULTI | SWT.BORDER);
gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gridData.horizontalSpan = 2;
list.setLayoutData(gridData);
for(int i = 0; i < generalizationSetList.size(); i++) {
if(generalizationSetList.get(i).getLabel() != null) {
list.add(generalizationSetList.get(i).getLabel());
} else {
list.add("GeneralizationSet" + i);
}
}
radios[0].addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
}
public void widgetSelected(SelectionEvent e) {
list.setEnabled(!radios[0].getSelection());
}
});
radios[1].setSelection(true);
// button
final org.eclipse.swt.widgets.Button buttonok = new Button(dialog, SWT.PUSH);
gridData = new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
gridData.horizontalSpan = 1;
gridData.horizontalAlignment = GridData.END;
buttonok.setLayoutData(gridData);
buttonok.setText(" OK ");
// button Cancel
Button cancel = new Button(dialog, SWT.PUSH);
gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gridData.horizontalSpan = 1;
gridData.horizontalAlignment = GridData.END;
cancel.setLayoutData(gridData);
cancel.setText("Cancel");
// listener of button
DialogListener listener = new DialogListener(generalizationSetList, list, buttonok);
buttonok.addListener(SWT.Selection, listener);
cancel.addListener(SWT.Selection, listener);
dialog.pack();
dialog.open();
while(!dialog.isDisposed()) {
if(!display.readAndDispatch())
display.sleep();
}
generalizationSettoCreate = listener.getResult();
}
});
}
}