package org.eclipse.uml2.diagram.sequence.edit.policies;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.IFigure;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.NodeListener;
import org.eclipse.gef.editpolicies.AbstractEditPolicy;
import org.eclipse.gmf.runtime.diagram.core.listener.DiagramEventBroker;
import org.eclipse.gmf.runtime.diagram.core.listener.NotificationListener;
import org.eclipse.uml2.diagram.sequence.edit.parts.BehaviorExecutionSpecification2EditPart;
import org.eclipse.uml2.diagram.sequence.edit.parts.MessageEditPart;
import org.eclipse.uml2.diagram.sequence.figures.ExecutionSpecificationShape;
import org.eclipse.uml2.diagram.sequence.internal.missed.MissedMethods;
import org.eclipse.uml2.uml.Message;
import org.eclipse.uml2.uml.MessageSort;
import org.eclipse.uml2.uml.UMLPackage;
public class BehaviorExecutionColorVisualEffect2 extends AbstractEditPolicy implements NodeListener, NotificationListener {
private final Set<Message> myMessagesToListen = new HashSet<Message>();
@Override
public void activate() {
super.activate();
refreshEffect();
getHostImpl().addNodeListener(this);
for (Object next : getHostImpl().getTargetConnections()){
hookConnection((ConnectionEditPart) next);
}
}
@Override
public void deactivate() {
getHostImpl().removeNodeListener(this);
ArrayList<Message> messages = new ArrayList<Message>(myMessagesToListen);
for (Message next : messages){
getDiagramEventBroker().removeNotificationListener(next, this);
}
myMessagesToListen.clear();
super.deactivate();
}
public void refreshEffect() {
refreshEffect(null);
}
public void refreshEffect(ConnectionEditPart toBeRemoved) {
refreshColorScheme_(toBeRemoved);
refreshCross();
}
private void refreshCross(){
boolean isDestruction = MissedMethods._executionSpecification().isDestruction(getHostImpl().getNotationView());
getHostFigure().setCrossVisible(isDestruction);
}
private void refreshColorScheme_(ConnectionEditPart toBeRemoved) {
boolean isRoot = hasOutgoingMessages(toBeRemoved) && !hasIncomingMessages(toBeRemoved);
IFigure figure = getHostImpl().getPrimaryShape();
if (isRoot){
figure.setBackgroundColor(ColorConstants.lightGray);
figure.setForegroundColor(ColorConstants.darkGray);
} else {
figure.setBackgroundColor(ColorConstants.white);
figure.setForegroundColor(ColorConstants.black);
}
}
private BehaviorExecutionSpecification2EditPart getHostImpl(){
return (BehaviorExecutionSpecification2EditPart)getHost();
}
private boolean hasIncomingMessages(ConnectionEditPart toBeRemoved){
BehaviorExecutionSpecification2EditPart host = getHostImpl();
List<?> targetConnections = host.getTargetConnections();
return containsMessageEditParts(targetConnections, toBeRemoved);
}
private boolean hasOutgoingMessages(ConnectionEditPart toBeRemoved){
BehaviorExecutionSpecification2EditPart host = getHostImpl();
List<?> sourceConnections = host.getSourceConnections();
return containsMessageEditParts(sourceConnections, toBeRemoved);
}
private boolean containsMessageEditParts(List<?> connections, ConnectionEditPart toBeRemoved){
for (Object next : connections){
if (next == toBeRemoved){
continue;
}
if (next instanceof MessageEditPart){
MessageEditPart nextMessageEditPart = (MessageEditPart)next;
Message message = (Message)nextMessageEditPart.resolveSemanticElement();
if (message != null && message.getMessageSort() != MessageSort.REPLY_LITERAL){
return true;
}
}
}
return false;
}
public void removingSourceConnection(ConnectionEditPart connection, int index) {
refreshEffect(connection);
}
public void removingTargetConnection(ConnectionEditPart connection, int index) {
refreshEffect(connection);
unhookConnection(connection);
}
public void sourceConnectionAdded(ConnectionEditPart connection, int index) {
refreshEffect(null);
}
public void targetConnectionAdded(ConnectionEditPart connection, int index) {
refreshEffect(null);
hookConnection(connection);
}
private ExecutionSpecificationShape getHostFigure(){
return getHostImpl().getPrimaryShape();
}
private void hookConnection(ConnectionEditPart ep){
if (ep instanceof MessageEditPart){
MessageEditPart messageEP = (MessageEditPart)ep;
Message message = (Message) messageEP.resolveSemanticElement();
if (!myMessagesToListen.contains(message)){
getDiagramEventBroker().addNotificationListener(message, UMLPackage.eINSTANCE.getMessage_MessageSort(), this);
myMessagesToListen.add(message);
}
}
}
private void unhookConnection(ConnectionEditPart ep){
if (ep instanceof MessageEditPart){
MessageEditPart messageEP = (MessageEditPart)ep;
Message message = (Message) messageEP.resolveSemanticElement();
getDiagramEventBroker().removeNotificationListener(message, this);
myMessagesToListen.remove(message);
}
}
public void notifyChanged(Notification notification) {
if (notification.getFeature() == UMLPackage.eINSTANCE.getMessage_MessageSort()){
refreshCross();
}
}
private DiagramEventBroker getDiagramEventBroker(){
return DiagramEventBroker.getInstance(getHostImpl().getEditingDomain());
}
}