/* $Id: FigMessage.java 18558 2010-07-24 15:53:42Z linus $ ***************************************************************************** * Copyright (c) 2009-2010 Contributors - see below * 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: * mvw * Linus Tolke ***************************************************************************** * * Some portions of this file was previously release using the BSD License: */ // Copyright (c) 1996-2009 The Regents of the University of California. All // Rights Reserved. Permission to use, copy, modify, and distribute this // software and its documentation without fee, and without a written // agreement is hereby granted, provided that the above copyright notice // and this paragraph appear in all copies. This software program and // documentation are copyrighted by The Regents of the University of // California. The software program and documentation are supplied "AS // IS", without any accompanying services from The Regents. The Regents // does not warrant that the operation of the program will be // uninterrupted or error-free. The end-user understands that the program // was developed for research purposes and is advised not to rely // exclusively on the program for any reason. IN NO EVENT SHALL THE // UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, // ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF // THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF // SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE // PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, // UPDATES, ENHANCEMENTS, OR MODIFICATIONS. package org.argouml.uml.diagram.ui; import java.awt.Color; import java.awt.Dimension; import java.awt.Polygon; import java.awt.Rectangle; import java.beans.PropertyChangeEvent; import java.util.Iterator; import java.util.Vector; import org.argouml.model.Model; import org.argouml.notation.NotationProviderFactory2; import org.argouml.uml.diagram.DiagramSettings; import org.argouml.uml.diagram.collaboration.ui.FigAssociationRole; import org.tigris.gef.base.Layer; import org.tigris.gef.presentation.Fig; import org.tigris.gef.presentation.FigPoly; import org.tigris.gef.presentation.FigText; /** * Class to display graphics for a UML Message * above an AssociationRole in a collaborations diagram. * * @author agauthie */ public class FigMessage extends FigNodeModelElement { private static Vector<String> arrowDirections; private static final int SOUTH = 0; private static final int EAST = 1; private static final int WEST = 2; private static final int NORTH = 3; static { arrowDirections = new Vector<String>(4); // TODO: i18n arrowDirections.add(SOUTH, "South"); arrowDirections.add(EAST, "East"); arrowDirections.add(WEST, "West"); arrowDirections.add(NORTH, "North"); } private FigPoly figPoly; /** * The current arrow direction set to constants above. */ private int arrowDirection = -1; private void initFigs() { setShadowSize(0); // Issue 2714. getNameFig().setLineWidth(0); getNameFig().setReturnAction(FigText.END_EDITING); getNameFig().setFilled(false); Dimension nameMin = getNameFig().getMinimumSize(); getNameFig().setBounds(X0, Y0, 90, nameMin.height); getBigPort().setBounds(X0, Y0, 90, nameMin.height); figPoly = new FigPoly(LINE_COLOR, SOLID_FILL_COLOR); int[] xpoints = {75, 75, 77, 75, 73, 75}; int[] ypoints = {33, 24, 24, 15, 24, 24}; Polygon polygon = new Polygon(xpoints, ypoints, 6); figPoly.setPolygon(polygon); figPoly.setBounds(100, 10, 5, 18); getBigPort().setFilled(false); getBigPort().setLineWidth(0); // add Figs to the FigNode in back-to-front order addFig(getBigPort()); addFig(getNameFig()); addFig(figPoly); } /** * Construct a FigMessage. * * @param owner owning UML element * @param bounds position and size * @param settings render settings */ public FigMessage(Object owner, Rectangle bounds, DiagramSettings settings) { super(owner, bounds, settings); initFigs(); updateNameText(); } /* * @see org.argouml.uml.diagram.ui.FigNodeModelElement#getNotationProviderType() */ @Override protected int getNotationProviderType() { return NotationProviderFactory2.TYPE_MESSAGE; } /* * @see org.argouml.uml.diagram.ui.FigNodeModelElement#updateListeners( * java.lang.Object, java.lang.Object) */ @Override protected void updateListeners(Object oldOwner, Object newOwner) { if (oldOwner != null) { removeElementListener(oldOwner); } if (newOwner != null) { addElementListener(newOwner, "remove"); } } @Override public Object clone() { FigMessage figClone = (FigMessage) super.clone(); Iterator it = figClone.getFigs().iterator(); figClone.setNameFig((FigText) it.next()); figClone.figPoly = (FigPoly) it.next(); //figClone._polygon = (Polygon) _polygon.clone(); return figClone; } /* * @see org.tigris.gef.presentation.Fig#setLineColor(java.awt.Color) */ @Override public void setLineColor(Color col) { figPoly.setLineColor(col); getNameFig().setLineColor(col); } /* * @see org.tigris.gef.presentation.Fig#getLineColor() */ @Override public Color getLineColor() { return figPoly.getLineColor(); } /* * @see org.tigris.gef.presentation.Fig#setFillColor(java.awt.Color) */ @Override public void setFillColor(Color col) { //figPoly.setFillColor(col); getNameFig().setFillColor(col); } /* * @see org.tigris.gef.presentation.Fig#getFillColor() */ @Override public Color getFillColor() { return getNameFig().getFillColor(); } /* * @see org.tigris.gef.presentation.Fig#setFilled(boolean) */ @Override public void setFilled(boolean f) { } @Override public boolean isFilled() { return true; } /* * @see org.tigris.gef.presentation.Fig#setLineWidth(int) */ @Override public void setLineWidth(int w) { figPoly.setLineWidth(w); } /* * @see org.tigris.gef.presentation.Fig#getLineWidth() */ @Override public int getLineWidth() { return figPoly.getLineWidth(); } /** * @param direction for the arrow * FigMessage.SOUTH * FigMessage.EAST * FigMessage.WEST * FigMessage.NORTH */ public void setArrow(int direction) { Rectangle bbox = getBounds(); if (arrowDirection == direction) { return; } arrowDirection = direction; switch (direction) { case SOUTH: { int[] xpoints = {75, 75, 77, 75, 73, 75}; int[] ypoints = {15, 24, 24, 33, 24, 24}; Polygon polygon = new Polygon(xpoints, ypoints, 6); figPoly.setPolygon(polygon); break; } case EAST: { int[] xpoints = {66, 75, 75, 84, 75, 75}; int[] ypoints = {24, 24, 26, 24, 22, 24}; Polygon polygon = new Polygon(xpoints, ypoints, 6); figPoly.setPolygon(polygon); break; } case WEST: { int[] xpoints = {84, 75, 75, 66, 75, 75}; int[] ypoints = {24, 24, 26, 24, 22, 24}; Polygon polygon = new Polygon(xpoints, ypoints, 6); figPoly.setPolygon(polygon); break; } default: { // north int[] xpoints = {75, 75, 77, 75, 73, 75}; int[] ypoints = {33, 24, 24, 15, 24, 24}; Polygon polygon = new Polygon(xpoints, ypoints, 6); figPoly.setPolygon(polygon); break; } } setBounds(bbox); } /** * @return the arrow direction */ public int getArrow() { return arrowDirection; } /* * @see org.tigris.gef.presentation.Fig#getMinimumSize() */ @Override public Dimension getMinimumSize() { Dimension nameMin = getNameFig().getMinimumSize(); Dimension figPolyMin = figPoly.getSize(); int h = Math.max(figPolyMin.height, nameMin.height); int w = figPolyMin.width + nameMin.width; return new Dimension(w, h); } /* * Override setBounds to keep shapes looking right. * @see org.tigris.gef.presentation.Fig#setBounds(int, int, int, int) */ @Override protected void setStandardBounds(int x, int y, int w, int h) { if (getNameFig() == null) { return; } Rectangle oldBounds = getBounds(); Dimension nameMin = getNameFig().getMinimumSize(); int ht = 0; if (nameMin.height > figPoly.getHeight()) { ht = (nameMin.height - figPoly.getHeight()) / 2; } getNameFig().setBounds(x, y, w - figPoly.getWidth(), nameMin.height); getBigPort().setBounds(x, y, w - figPoly.getWidth(), nameMin.height); figPoly.setBounds(x + getNameFig().getWidth(), y + ht, figPoly.getWidth(), figPoly.getHeight()); firePropChange("bounds", oldBounds, getBounds()); calcBounds(); //_x = x; _y = y; _w = w; _h = h; updateEdges(); } /* * TODO: The code implementing this method is from 2003 (see issue 2171) - * mechanically integrated by tfmorris in May 2007. Needs to be * reviewed/updated. * * @author Decki,Endi,Yayan, Politechnic of Bandung. Computer Departement * method for changing text of Message */ @Override protected void modelChanged(PropertyChangeEvent mee) { super.modelChanged(mee); // Do nothing until code is reviewed if (true) { return; } if (Model.getFacade().isAMessage(getOwner())) { if (Model.getFacade().isAParameter(mee.getSource())) { Object par = mee.getSource(); updateArgumentsFromParameter(getOwner(), par); } if (mee == null || mee.getSource() == getOwner() || Model.getFacade().isAAction(mee.getSource()) || Model.getFacade().isAOperation(mee.getSource()) || Model.getFacade().isAArgument(mee.getSource()) || Model.getFacade().isASignal(mee.getSource())) { updateListeners(getOwner()); } // needs to be updated for changes in Notation subsystem - tfm // String nameStr = Notation.generate(this, getOwner()).trim(); // getNameFig().setText(nameStr); updateArrow(); damage(); } } /** * TODO: The code implementing this method is from 2003 (see issue 2171) - * mechanically integrated by tfmorris in May 2007. Needs to be * reviewed/updated. * * @author Decki,Endi,Yayan, Politechnic of Bandung. Computer Departement * method for changing text of Message * @param newOwner * @param parameter */ protected void updateArgumentsFromParameter(Object newOwner, Object parameter) { // Do nothing until code is reviewed if (true) { return; } if (newOwner != null) { Object act = Model.getFacade().getAction(newOwner); if (Model.getFacade().isACallAction(act)) { if (Model.getFacade().getOperation(act) != null) { Object operation = Model.getFacade().getOperation(act); if (Model.getDirectionKind().getInParameter().equals( Model.getFacade().getKind(parameter))) { // Update for changes in Model subsystem - tfm // Collection colpar = Model.getFacade().getInParameters( // operation); // Collection colarg = Model.getFacade() // .getActualArguments(act); // if (colpar.size() == colarg.size()) { // Iterator iter = colarg.iterator(); // while (iter.hasNext()) { // Object arg = iter.next(); // if (!iter.hasNext()) { // Model.getCommonBehaviorHelper() // .removeActualArgument(act, arg); // } // } // } Object newArgument = Model.getCommonBehaviorFactory() .createArgument(); Model.getCommonBehaviorHelper().setValue( newArgument, Model.getDataTypesFactory().createExpression( "", Model.getFacade().getName(parameter))); Model.getCoreHelper().setName(newArgument, Model.getFacade().getName(parameter)); Model.getCommonBehaviorHelper().addActualArgument(act, newArgument); Model.getPump().removeModelEventListener(this, parameter); Model.getPump().addModelEventListener(this, parameter); } } } } } /** * TODO: The code implementing this method is from 2003 (see issue 2171) - * mechanically integrated by tfmorris in May 2007. Needs to be * reviewed/updated. * * @author Decki,Endi,Yayan, Politechnic of Bandung. Computer Departement * method for changing text of Message * @param newOwner model element which should now be listened to */ protected void updateListeners(Object newOwner) { // Our superclass no longer has this method, so perhaps this whole // thing should be removed? - tfm // super.updateListeners(newOwner); // TODO: Do nothing until code is reviewed if (true) { return; } if (newOwner != null) { Object act = Model.getFacade().getAction(newOwner); if (act != null) { Model.getPump().removeModelEventListener(this, act); Model.getPump().addModelEventListener(this, act); Iterator iter = Model.getFacade().getActualArguments(act) .iterator(); while (iter.hasNext()) { Object arg = iter.next(); Model.getPump().removeModelEventListener(this, arg); Model.getPump().addModelEventListener(this, arg); } if (Model.getFacade().isACallAction(act)) { Object oper = Model.getFacade().getOperation(act); if (oper != null) { Model.getPump().removeModelEventListener(this, oper); Model.getPump().addModelEventListener(this, oper); Iterator it2 = Model.getFacade().getParameters(oper) .iterator(); while (it2.hasNext()) { Object param = it2.next(); Model.getPump().removeModelEventListener(this, param); Model.getPump().addModelEventListener(this, param); } } } if (Model.getFacade().isASendAction(act)) { Object sig = Model.getFacade().getSignal(act); if (sig != null) { Model.getPump().removeModelEventListener(this, sig); } Model.getPump().addModelEventListener(this, sig); } } } } /** * Determines the direction of the message arrow. Determination of the type * of arrow happens in modelChanged. */ public void updateArrow() { Object mes = getOwner(); // Message if (mes == null || getLayer() == null) { return; } Object sender = Model.getFacade().getSender(mes); // ClassifierRole Object receiver = Model.getFacade().getReceiver(mes); // ClassifierRole Fig senderPort = getLayer().presentationFor(sender); Fig receiverPort = getLayer().presentationFor(receiver); if (senderPort == null || receiverPort == null) { return; } int sx = senderPort.getX(); int sy = senderPort.getY(); int rx = receiverPort.getX(); int ry = receiverPort.getY(); if (sx < rx && Math.abs(sy - ry) <= Math.abs(sx - rx)) { // east setArrow(EAST); } else if (sx > rx && Math.abs(sy - ry) <= Math.abs(sx - rx)) { // west setArrow(WEST); } else if (sy < ry) { // south setArrow(SOUTH); } else { setArrow(NORTH); } } /** * Add the FigMessage to the Path Items of its FigAssociationRole. * * @param lay the Layer */ public void addPathItemToFigAssociationRole(Layer lay) { Object associationRole = Model.getFacade().getCommunicationConnection(getOwner()); if (associationRole != null && lay != null) { FigAssociationRole figAssocRole = (FigAssociationRole) lay.presentationFor(associationRole); if (figAssocRole != null) { figAssocRole.addMessage(this); lay.bringToFront(this); } } } /* * @see org.argouml.uml.diagram.ui.FigNodeModelElement#renderingChanged() */ @Override public void renderingChanged() { super.renderingChanged(); updateArrow(); } /** * @return Returns the arrowDirections. */ public static Vector<String> getArrowDirections() { return arrowDirections; } }