SequenceDiagram.java :  » UML » umlet » com » umlet » element » base » Java Open Source

Java Open Source » UML » umlet 
umlet » com » umlet » element » base » SequenceDiagram.java
// The UMLet source code is distributed under the terms of the GPL; see license.txt
package com.umlet.element.base;

import java.awt.*;
import java.util.*;
import com.umlet.control.*;

import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D;
import java.util.regex.Pattern;
import java.util.regex.Matcher;


//An interaction represents a synchronous/asynchronous message
//that is sent between two objects.
class Interaction
{
    private int srcObj;
    private boolean srcObjHasControl;
    private int arrowKind; //1=SYNC, 2= ASYNC, 3=EDGE, 4=FILLED
    private int lineKind; //1=SOLID, 2=DOTTED
    private int destObj;
    private boolean destObjHasControl;
    private String methodName;


    public Interaction(int srcObj, boolean srcObjHasControl, int arrowKind, int lineKind,
    int destObj, boolean destObjHasControl, String methodName)
    {
      this.srcObj= srcObj;
      this.srcObjHasControl= srcObjHasControl;
      this.arrowKind= arrowKind;
      this.lineKind = lineKind;
      this.destObj= destObj;
      this.destObjHasControl= destObjHasControl;
      this.methodName= methodName;
    }


    public boolean hasControl(int objNum) {
    if ((srcObjHasControl && srcObj== objNum) ||
        (destObjHasControl && destObj== objNum))
        return true;
    else return false;
    }


    public boolean equals(Object o) {
        if (!(o instanceof Interaction)) return false;
        Interaction i = (Interaction)o;

        return srcObj==i.srcObj && srcObjHasControl==i.srcObjHasControl &&
          arrowKind==i.arrowKind && destObj==i.destObj && 
      destObjHasControl==i.destObjHasControl &&
      (methodName == null |  methodName.equals(i.methodName));
    }

    public int hashCode() {
      return (methodName!=null?methodName.hashCode():1) + srcObj + 
        (srcObjHasControl?1:0) + arrowKind + destObj + (destObjHasControl?1:0);
    }

    public int getSrcObj() {return srcObj;}
    public boolean getSrcObjHasControl() {return srcObjHasControl;}
    public int getArrowKind() {return arrowKind;}
    public int getLineKind() {return lineKind;}
    public int getDestObj() {return destObj;}
    public boolean getDestObjHasControl() {return destObjHasControl; }
    public String getMethodName() {return methodName; }
}


//Contains all interactions entered by the user and
//offers various comfort-functions for finding and 
//working with interactions 
class InteractionManagement
{
    private Set<Interaction>[] level;
  //private Set[] level;

    InteractionManagement(int numLevels) {
      level= new HashSet[numLevels];
      for (int i=0; i < numLevels; i++) {
        level[i]= new HashSet<Interaction>();
      }
    }

    public boolean controlBoxExists(int levelNum, int objNum) {
      Iterator<Interaction> it= level[levelNum-1].iterator();
    while (it.hasNext()) {
      Interaction ia= it.next();
        if (ia.hasControl(objNum)) return true;
    }
    return false;
    }

    public void add(int numLevel, Interaction i) {
      level[numLevel-1].add(i);
    }

    public Set<Interaction> getInteractionsInLevel(int levelNum) {
      return level[levelNum-1];
    }

    public int getNumLevels() {
      return level.length;
    }
}


public class SequenceDiagram extends com.umlet.element.base.Entity {

    public int controlFlowBoxWidth = 20;

    //the dimensions for the rectangle(s) (=objects) in the first line
    public final int rectDistance= 60; //distance between two columns
    public int rectHeight; //computed
    public int rectWidth; //computed
    //int extraTextSpace = 0;

    public final int borderDistance= 10; //d between the component bordeR and the diagram
    private int yOffsetforTitle=0;

    public int rectToFirstLevelDistance= 0;
    public int levelHeight= 30;//LME//60;

    //these two constants are important for the arrowhead
    public final int arrowX= 5; 
    public final int arrowY= 5;

    public final int SYNC=   1;
    public final int ASYNC=  2;
    public final int EDGE=   3; //LME
    public final int FILLED= 4; //LME
    public final int SOLID=  1; //LME
    public final int DOTTED= 2; //LME


    private Map<String, Integer> labeltonumber;
    private int levelNum= 0; 
    private InteractionManagement im;


    public SequenceDiagram() {
      rectHeight= 2*Constants.getDistLineToText() + Constants.getFontsize() + 10;
    }


    public void paint(Graphics g) {
      // Some unimportant initialization stuff; setting color, font 
      // quality, etc. You should not have to change this.
      Graphics2D g2=(Graphics2D) g; g2.setFont(Constants.getFont());
      g2.setColor(_activeColor); Constants.getFRC(g2);
      
      //draw the border
      g2.drawRect(0, 0, this.getWidth()-1, this.getHeight()-1);

      levelNum=1;
      
      Vector<String> lines=Constants.decomposeStrings(this.getPanelAttributes(), "\n");
      
      if (lines.size() == 0) return;
      if(lines.elementAt(0).startsWith("title:")) {
        String title = lines.elementAt(0).substring("title:".length());
        if(title != null && title.length()>0) {
          Constants.write(g2,title,10,Constants.getFontsize()+Constants.getDistLineToText(),false);
          int titlewidth=Constants.getPixelWidth(g2,title);
          int ty = 8+Constants.getFontsize()+Constants.getDistTextToLine();
          g2.drawLine(0,ty,titlewidth+10,ty);
          g2.drawLine(titlewidth+10,ty,titlewidth+ty+10,0);
          lines.remove(0);
          yOffsetforTitle=25;
        }
      } else yOffsetforTitle=0;
      
      
      for (int i=1; i < lines.size(); i++) {
        String element = lines.elementAt(i);
        if(element.indexOf("iframe{")>=0) {
          element = "9999->0:"+element; //dummy: space for interactionframe
          lines.set(i,element);
        } else if(element.indexOf("iframe}")>=0) {
          element = "9999<-0:"+element; //dummy: space for interactionframe
          lines.set(i,element);
        }
        if (lines.elementAt(i).matches("\\A\\s*\\z")) continue;
        levelNum++;
      }

      String firstLine= lines.elementAt(0);
    Vector<String> obj= Constants.decomposeStrings(firstLine, "|");
    int numObjects= obj.size();
    
    //LABEL ADDING
    //get the labels of the Sequencediagram
    String newhead = ""; //delete the ids from the header
    this.labeltonumber = new HashMap<String,Integer>();
    Pattern p_label = Pattern.compile("([^\\~]+)(\\~([a-zA-Z0-9]+))?(\\_)?");
    for(int i=1; i <= numObjects; i++) {
      Matcher m = p_label.matcher(obj.get(i-1));
      if(m.matches() && m.group(2) != null) {
        this.labeltonumber.put(m.group(3), i);
        newhead += "|" + m.group(1) + (m.group(4)==null?"":m.group(4));
      }
      else
        newhead += "|" + obj.get(i-1);
      if(!this.labeltonumber.containsKey(Integer.toString(i))) //only write number if no other label has this number
        this.labeltonumber.put(Integer.toString(i), i); //columnnumber as label for backward compatibility      
    }
    obj = Constants.decomposeStrings(newhead.length() > 0?newhead.substring(1):"", "|");
    //LABELADDING STOP (exchanged parseInteger Methods with labeltonumber.get methods
    
    //parse the messages
    int curLevel= 0;
    im= new InteractionManagement(levelNum);
    String boxStrings="";
    for (int i=1; i < lines.size(); i++) {
        if (lines.elementAt(i).matches("\\A\\s*\\z")) continue;
        curLevel++;
        Vector<String> interactions= Constants.decomposeStrings(lines.elementAt(i), ";");
  
        for (int j=0; j < interactions.size(); j++) {
          Pattern p= 
            //Pattern.compile("\\A(\\d+)(->>|->|-/>|.>>|.>|./>|->>>|.>>>)(\\d+)(:((\\d+)(,(\\d+))*))*(?::(.*))?\\z");
            Pattern.compile("\\A(\\w+)(->>|->|-/>|.>>|.>|./>|->>>|.>>>|<<-|<-|</-|<<.|<.|</.|<<<-|<<<.)(\\w+)(:((\\w+)(,(\\w+))*))?(?::(.*))?\\z");
            //1->2:1,2:methodName
            //1->2:abc
          Matcher m= p.matcher(interactions.elementAt(j));
          if (!m.matches()) continue;
          Integer srcObj= this.labeltonumber.get(m.group(1));
          
          int arrowKind= -1;
          int lineKind= -1;
          boolean reverse=false; //arrow direction flag
          if (m.group(2).equals("->"))       {arrowKind= ASYNC; lineKind=SOLID;}
          else if (m.group(2).equals("->>"))  {arrowKind= SYNC; lineKind=SOLID;}
          else if (m.group(2).equals("-/>"))  {arrowKind= EDGE; lineKind=SOLID;} //LME
          else if (m.group(2).equals("->>>")) {arrowKind= FILLED; lineKind=SOLID;} //LME
          else if (m.group(2).equals(".>"))   {arrowKind= ASYNC; lineKind=DOTTED;} //LME
          else if (m.group(2).equals(".>>"))  {arrowKind= SYNC; lineKind=DOTTED;} //LME
          else if (m.group(2).equals("./>"))  {arrowKind= EDGE; lineKind=DOTTED;} //LME
          else if (m.group(2).equals(".>>>")) {arrowKind= FILLED; lineKind=DOTTED;} //LME
          else if (m.group(2).equals("<-"))   {arrowKind= ASYNC; lineKind=SOLID; reverse=true;}
          else if (m.group(2).equals("<<-"))  {arrowKind= SYNC; lineKind=SOLID; reverse=true;}
          else if (m.group(2).equals("</-"))  {arrowKind= EDGE; lineKind=SOLID; reverse=true;} //LME
          else if (m.group(2).equals("<<<-")) {arrowKind= FILLED; lineKind=SOLID; reverse=true;} //LME
          else if (m.group(2).equals("<."))   {arrowKind= ASYNC; lineKind=DOTTED; reverse=true;} //LME
          else if (m.group(2).equals("<<."))  {arrowKind= SYNC; lineKind=DOTTED; reverse=true;} //LME
          else if (m.group(2).equals("</."))  {arrowKind= EDGE; lineKind=DOTTED; reverse=true;} //LME
          else if (m.group(2).equals("<<<.")) {arrowKind= FILLED; lineKind=DOTTED; reverse=true;} //LME
  
          Integer destObj= this.labeltonumber.get(m.group(3));
          String group=m.group(5);
          if(group==null) {
            group="#";
            String element = interactions.elementAt(j);
            if(element.indexOf("iframe")>=0) group+=element.substring(element.indexOf("iframe")); //append info for interactionframe
          }
          else // LABLING ADD
          {
            String[] grouparray = group.split(",");
            group = "";
            for(String tmp : grouparray) {
              Integer tempgroup = this.labeltonumber.get(tmp);
              if(tempgroup != null)
                group += "," + tempgroup; 
            }
            if(group.length()>0)
              group = group.substring(1);
          } //STOP LABLING ADD
          boxStrings += ";"+group; //LME: get alive Objects
          
          boolean srcObjHasControl= srcObj!=null?group.contains(String.valueOf(srcObj)):false;
          boolean destObjHasControl= destObj!=null?group.contains(String.valueOf(destObj)):false;
          String methodName= m.group(9);
          
          //LME: removed (in V6) since not necessary
          //if(destObj==srcObj) levelNum++; //LME: expand the Entity's size

          if ((srcObj == null) || (destObj == null)) continue;
  
          if(!reverse) im.add(curLevel, new Interaction(srcObj,srcObjHasControl, arrowKind, lineKind, destObj, destObjHasControl, methodName)); //normal arrow direction  1->2
          else      im.add(curLevel, new Interaction(destObj, destObjHasControl, arrowKind, lineKind, srcObj,srcObjHasControl, methodName)); //reverse arrow direction 1<-2
        } //#for
    }  
    //end message parsing

    

    //find out the width of the column with the longest text
    double maxWidth= 0;
    for (int i=0; i < numObjects; i++) {
        String s= obj.elementAt(i);
        if (s.startsWith("_") && s.endsWith("_") && s.length()>2) {
          s=s.substring(1,s.length()-1);
        }
        TextLayout layout= new TextLayout(s, Constants.getFont(), g2.getFontRenderContext());
        maxWidth= Math.max(layout.getBounds().getWidth(), maxWidth);
    }

    rectWidth= (int)Math.floor(maxWidth+1)+ 2* Constants.getDistLineToText() + Constants.getFontsize();

    //draw the first line of the sequence diagram
    int ypos= borderDistance+yOffsetforTitle;
    int xpos= borderDistance;
    for (int i=0; i < numObjects; i++) {
        boolean underline= false;
        String s= obj.elementAt(i);
        if (s.startsWith("_") && s.endsWith("_") && s.length()>2) {
          underline=true;
          s=s.substring(1,s.length()-1);
        }
        TextLayout layout= new TextLayout(s, Constants.getFont(), 
                  g2.getFontRenderContext());
  
        g2.drawRect(xpos, ypos, rectWidth-1, rectHeight-1);
  
        int dx= (rectWidth-2 - (int)Math.floor(layout.getBounds().getWidth()+1)) / 2;
        int dy= (rectHeight-2 - (int)Math.floor(layout.getBounds().getHeight()+1)) / 2;
        int tx= xpos + dx;
        int ty= ypos + dy + (int)layout.getBounds().getHeight();
  
        layout.draw(g2, tx, ty);
  
        if (underline)
        g2.drawLine(tx, 
              ty+Constants.getDistTextToLine()/2, 
              tx+(int)layout.getBounds().getWidth(), 
              ty+Constants.getDistTextToLine()/2);
  
        xpos += rectWidth + rectDistance;
    }

    //draw the messages
    int maxTextXpos = drawMessages(g2);
    maxTextXpos+=3*Constants.getDistTextToLine(); //add extra space
    if(boxStrings!=null && boxStrings.length()>1) {
      try {
        drawControlFlowBoxesWithLines(g2, boxStrings.substring(1),numObjects); //LME: 1,2;1,2;... cut first ;-character
      } catch(ArrayIndexOutOfBoundsException e) {
        //do nothing: this exception is thrown, when entering text, 
        //that is not rendered to an control flow box
      }
    }

    //set our component to the correct size
    int rWidth = rectWidth * numObjects + rectDistance * (numObjects-1) + 2 * borderDistance;
    int rHeight = 2 * borderDistance + yOffsetforTitle + rectHeight + rectToFirstLevelDistance + levelNum * levelHeight;
    rWidth=(rWidth>maxTextXpos?rWidth:maxTextXpos);
    //align the borders to the grid
    rWidth  += Umlet.getInstance().getMainUnit()-rWidth%Umlet.getInstance().getMainUnit();
    rHeight += Umlet.getInstance().getMainUnit()-rHeight%Umlet.getInstance().getMainUnit();
    setSize(rWidth, rHeight);
    }


    private int drawMessages(Graphics2D g2) {
      int maxTextXpos = 0;
      for (int i=0; i < im.getNumLevels(); i++) {
        Set<Interaction> interactions= im.getInteractionsInLevel(i+1);
        Iterator<Interaction> it= interactions.iterator();
        while (it.hasNext()) {
          Interaction ia= it.next();
          if (ia.getSrcObj() == ia.getDestObj()) {
            //draw an arc-arrow
            int xTextOffset=0;
            int w= 30;
            int h= (int)(levelHeight * 0.66);
            int x= hCenterForObj(ia.getSrcObj()) - w/2;
            //nt y= vCenterForLevel(i+1) - h/2;
            int ay= vCenterForLevel(i+1)+5; //+ levelHeight/2 -1;
              if (im.controlBoxExists(i+1, ia.getSrcObj())) {
                x += controlFlowBoxWidth/2;
                xTextOffset=controlFlowBoxWidth/2;
              }
              g2.drawArc(x,ay,w,h, 90,-180);
              Point p1= new Point(x+w/2, ay+h);
              Point d1= new Point(x+w/2 + 3, p1.y -6);
              Point d2= new Point(x+w/2+4, p1.y +4);

              if (ia.getArrowKind() == ASYNC) { //Pfeil offen
                g2.drawLine(p1.x,p1.y, d1.x, d1.y);
                g2.drawLine(p1.x,p1.y, d2.x,d2.y);
              } else if(ia.getArrowKind() == SYNC){
                int xs[] = {p1.x, d1.x, d2.x};
                int ys[] = {p1.y, d1.y, d2.y};
                Color oldColor= g2.getColor();
                g2.setColor(_fillColor);
                g2.fillPolygon(xs,ys,3);
                g2.setColor(oldColor);
                g2.drawPolygon(xs,ys,3);
              } else if(ia.getArrowKind() == EDGE) {
                g2.drawLine(p1.x,p1.y, d2.x,d2.y);
              } else if(ia.getArrowKind()==FILLED) {
                Polygon p = new Polygon();
              p.addPoint(p1.x, p1.y);
              p.addPoint(d1.x, d1.y);
              p.addPoint(d2.x, d2.y);
              g2.fillPolygon(p);
              }

              //print the methodname
              if (ia.getMethodName() != null && !ia.getMethodName().equals("")){
                int fx1= x +w +2;
                int fy1= ay;
                int fx2= hCenterForObj(ia.getSrcObj()) + rectWidth/2;
                int fy2= ay + h;
                int tx = printMethodName(g2, ia.getMethodName(), fx1+xTextOffset,fx2+xTextOffset,
                    fy1, fy2, true, false);
                maxTextXpos=maxTextXpos>tx?maxTextXpos:tx;
              }

          } else {
            //draw an arrow from the source-object to the destination object
            int begX= hCenterForObj(ia.getSrcObj());
            int endX= (ia.getSrcObj() < ia.getDestObj())? hCenterForObj(ia.getDestObj())-1: hCenterForObj(ia.getDestObj())+1;
            int arrowY= vCenterForLevel(i+1) + levelHeight/2 -1;

            if (ia.getSrcObjHasControl()) { //LME: shrink arrow if box exists  
              begX += (ia.getSrcObj() < ia.getDestObj()) ? (controlFlowBoxWidth/2) : (-controlFlowBoxWidth/2);
            }
            if(ia.getDestObjHasControl()) { //LME: shrink arrow if box exists
              endX += (ia.getSrcObj() < ia.getDestObj()) ? (-controlFlowBoxWidth/2) : (controlFlowBoxWidth/2);
            }

            drawArrow(g2, new Point(begX,arrowY), new Point(endX, arrowY), ia.getArrowKind(), ia.getLineKind());

            if (ia.getMethodName() != null && !ia.getMethodName().equals("")) {
              final int b= 2;
              if (ia.getSrcObj() < ia.getDestObj()) { 
                int tx = printMethodName(g2, ia.getMethodName(), begX+b, endX-arrowX-b, arrowY-1-levelHeight/1, arrowY-1, false,true);
                maxTextXpos=maxTextXpos>tx?maxTextXpos:tx;
              } else {
                int tx = printMethodName(g2, ia.getMethodName(), endX+arrowX+b, begX-b, arrowY-1 - levelHeight/2, arrowY-1, false,true);
                maxTextXpos=maxTextXpos>tx?maxTextXpos:tx;
              }
            }
          }
        }
      }
      return maxTextXpos;
    }

    //prints the given methodName in an intelligent manner into
    //the supplied rectangle. 
    //The method may put pixels anywhere into the supplied rectangle
    //including the borders. (In other words eg. the point begX/endY
    //may be set by this method.)
    private int printMethodName(Graphics2D g2, String methodName, 
         int begX, int endX, int begY, int endY,
         boolean centerVertically, boolean centerHorizontically) {

      if (methodName == null || methodName.equals("")) {
        System.err.println("SequenceDiagram->printMethodName was called with an invalid argument.");
        return 0;
      }

      Font font= Constants.getFont();
      String displayMethodName= methodName;

      TextLayout layout= new TextLayout(displayMethodName, font, g2.getFontRenderContext());
  
      if ((int)layout.getBounds().getHeight() > endY-begY) {
        //TODO: increase levelHeight and paint it again
        System.err.println("Error in SequenceDiagram->printMethodName: "+
             "Cannot print the methodName because there is "+
             "not enough vertical space. Maybe the font size "+
             "is too big.");
        return 0;
      }

      /*if (layout.getBounds().getWidth() > endX-begX) {
        while (methodName.length() > 0 && layout.getBounds().getWidth() > endX-begX) {
          methodName= methodName.substring(0, methodName.length()-1);
          displayMethodName= methodName + "...";
          layout= new TextLayout(displayMethodName, font,
               g2.getFontRenderContext());
        }
      }*/      
      
      //draw it horizontally centered
      int dx=endX-begX-20+Constants.getDistLineToText();
      if(centerHorizontically) dx= (endX-begX - (int)layout.getBounds().getWidth()) / 2;
      int dy= (centerVertically)? 
          (endY-begY - (int)layout.getBounds().getHeight())/2 : 1;
      
      
      layout.draw(g2, begX + dx, endY - dy );
/* Expand Entity bounds if text exceeds width       
      System.out.println(dx+Constants.getFontsize()*displayMethodName.length());
      int eX = Umlet.getInstance().getEditedEntity().getX();
      int eW = Umlet.getInstance().getEditedEntity().getWidth();
      Rectangle2D r2d=layout.getBounds();
      int rTextPos = (int)r2d.getWidth() + (int)r2d.getX()+ begX+dx;
*/      
      return begX+dx+(int)layout.getBounds().getWidth(); //LMEXX
    }

    
    public void drawControlFlowBoxesWithLines(Graphics2D g2, String s, int numObjects) { //LME
      int level=1;
      StringTokenizer mainTokens = new StringTokenizer(s,";");
      
      int tokNum = mainTokens.countTokens();
      int[][] tField = new int[numObjects][tokNum+2];

      Vector<Integer> interactionframes = new Vector<Integer>();
      HashMap<String,String> interactionframesText = new HashMap<String,String>();
      
      //collect all tokens into an array: create another view to sequentially access data of a specific object
      //1,2;#;1,3;1,3;1;3 will be transfomed to
      //  tField:  [110]
      //      [000]
      //      [101]
      //      [101]
      //      [100]
      //      [001]
      while(mainTokens.hasMoreTokens()) {
        String main = mainTokens.nextToken();
        if(main.indexOf("#")>=0) { //if no box, clear entire row
          for(int i=0;i<numObjects;i++) tField[i][level-1]=0; //clear
          if(main.indexOf("#iframe{")>=0 || main.indexOf("#iframe}")>=0) {
            if(main.indexOf("#iframe{")>=0) interactionframes.add(new Integer(level));
            else interactionframes.add(new Integer(level*(-1))); //distinguish betweeen start and end of the iframe
            if(main.indexOf("iframe{:")>=0) {
              interactionframesText.put(""+level,main.substring(main.indexOf("iframe{:")+8)); //put text into hashmap
            }
          }
          level++;
        } else {
          StringTokenizer innerT = new StringTokenizer(main,",");
          for(int i=0;i<numObjects;i++) tField[i][level-1]=0; //clear
          while(innerT.hasMoreTokens()) {
            String is = innerT.nextToken();
            int objNum = Integer.parseInt(is);
            tField[objNum-1][level-1]=1;
          }
          level++;
        } //#else
        } //#while

      
      for(int actObjNum=0;actObjNum<numObjects;actObjNum++) {
        int offset=2;
        int objNum=actObjNum+1;
        int x1 = hCenterForObj(objNum) - controlFlowBoxWidth/2; 
        int startLevel=-1,boxSize=0;
        
        int lineX= hCenterForObj(actObjNum+1);
        int lineY1= borderDistance + yOffsetforTitle + rectHeight;

        for(int i=0;i<tokNum+1;i++) {
          if(tField[actObjNum][i]==1) {
            if(startLevel==-1) startLevel=i;
            boxSize++;
          }
          if((tField[actObjNum][i]==0)&&(startLevel!=-1)) {
            int y1 = vCenterForLevel(startLevel+offset) - levelHeight-1;
              g2.drawRect(x1,y1,controlFlowBoxWidth-1, levelHeight*boxSize); //draw the box
              
              g2.setStroke(Constants.getStroke(1,1));  //#draw the line between the boxes
              g2.drawLine(lineX, lineY1, lineX, y1);  //#
              g2.setStroke(Constants.getStroke(0,1));  //#
              lineY1=y1+levelHeight*boxSize;      //#
              startLevel=-1; boxSize=0;              
          }
        } //#for(int i
        //LME: draw the tail
        int lineY2=borderDistance+yOffsetforTitle+rectHeight + levelNum* levelHeight + rectToFirstLevelDistance;
        g2.setStroke(Constants.getStroke(1,1));
        g2.drawLine(lineX, lineY1, lineX,lineY2 );
        g2.setStroke(Constants.getStroke(0,1));
      } //#for(int actObjNum  
      
      //LME: draw the interaction frames
      int fullSets = interactionframes.size()-(interactionframes.size()%2);
      if(fullSets>=2) {
        int pos=0;
        while(pos<fullSets) {
          pos=recurseInteractionFrames(g2,interactionframes,interactionframesText,pos,0);
          pos++;
        }
      }
    }

    /**
     * Recusion level step of interactionframes
     * ie:
     * iframe{
     *   iframe{
     *   }
     *   iframe{
     *   }
     * } 
     */
    public int recurseInteractionFrames(Graphics2D g2, Vector<Integer>interactionframes, HashMap<String,String> interactionframesText, int pos, int recursionLevel) {
      int pos1=interactionframes.elementAt(pos);
      int posX;
      while((pos<interactionframes.size())&&(posX=interactionframes.elementAt(pos))>0) { //traverse through iframes an same level
        pos1=posX;
        pos++;
        pos = recurseInteractionFrames(g2, interactionframes, interactionframesText, pos, recursionLevel+1); //step on level deeper into recursion
        if(pos1<=0) return pos;
        int pos2 = interactionframes.elementAt(pos) * (-1);
        drawInteractionFrame(g2, pos1, pos2, recursionLevel, interactionframesText.get(""+pos1));
        pos++;
      }
      return pos;
    }
    
    
    
    private void drawInteractionFrame(Graphics2D g2, int pos1, int pos2, int recursionLevel, String text) {
      int pos11 = (pos1+1)*levelHeight+ yOffsetforTitle;
    int h = (pos2-pos1)*levelHeight;
    int x=Constants.getDistTextToText()*2+recursionLevel*4;
    g2.drawRect(x,pos11,this.getWidth()-Constants.getDistTextToText()*4-1-recursionLevel*8,h);
    int uLinePos = pos11+Constants.getDistLineToText()+Constants.getFontsize()+Constants.getDistTextToLine();
    int textPos = pos11+Constants.getDistLineToText()+Constants.getFontsize();
    
    int textWidth = 0;
    if(text==null||text.equals("")) text=" ";
    g2.drawString(text,x+10,textPos);
    int pW = Constants.getPixelWidth(g2,text);
        textWidth=(pW>textWidth)?(pW):(textWidth);

    g2.drawLine(x,uLinePos,x+textWidth+15,uLinePos);
    g2.drawLine(x+textWidth+15,uLinePos,x+textWidth+25,pos11+10);
    g2.drawLine(x+textWidth+25,pos11,x+textWidth+25,pos11+10);
    }


    public void drawArrow(Graphics2D g2, Point srcObj, Point destObj, int arrowKind, int lineKind) {
      Point p1, p2;
    if (srcObj.x < destObj.x){
      p1 = new Point(destObj.x-arrowX, destObj.y+arrowY);
      p2 = new Point(destObj.x-arrowX, destObj.y-arrowY);
      } else {
        p1 = new Point(destObj.x+arrowX, destObj.y+arrowY);
        p2 = new Point(destObj.x+arrowX, destObj.y-arrowY);
      }
     
    if(arrowKind==SYNC) {    
      g2.drawLine(p1.x, p1.y, p2.x, p2.y);
       g2.drawLine(destObj.x, destObj.y, p1.x, p1.y);
       g2.drawLine(destObj.x, destObj.y, p2.x, p2.y);

       if(lineKind==DOTTED) g2.setStroke(Constants.getStroke(1,1));
       g2.drawLine(srcObj.x,srcObj.y,p1.x, destObj.y);
    } else if(arrowKind==ASYNC) {
      g2.drawLine(destObj.x, destObj.y, p1.x, p1.y);
      g2.drawLine(destObj.x, destObj.y, p2.x, p2.y);

      if(lineKind==DOTTED) g2.setStroke(Constants.getStroke(1,1));
      g2.drawLine(srcObj.x,srcObj.y,destObj.x, destObj.y);
    } else if(arrowKind==EDGE) {
      g2.drawLine(destObj.x, destObj.y, p2.x, p2.y);
      
      if(lineKind==DOTTED) g2.setStroke(Constants.getStroke(1,1));
      g2.drawLine(srcObj.x,srcObj.y,destObj.x, destObj.y);
    } else if(arrowKind==FILLED) {
      Polygon p = new Polygon();
      p.addPoint(p1.x, p1.y);
      p.addPoint(p2.x, p2.y);
      p.addPoint(destObj.x, destObj.y);
      g2.fillPolygon(p);
      
       if(lineKind==DOTTED) g2.setStroke(Constants.getStroke(1,1));
       g2.drawLine(srcObj.x,srcObj.y,p1.x, destObj.y);
    }
    g2.setStroke(Constants.getStroke(0,1));
    }


    protected int hCenterForObj(int objNum) {
      return (objNum*rectWidth + (objNum-1)*rectDistance + borderDistance -
          rectWidth/2);
    }

    protected int vCenterForLevel(int level) {
      return (level*levelHeight + rectToFirstLevelDistance + 
          rectHeight + borderDistance+yOffsetforTitle - levelHeight/2);
    }


    public int getPossibleResizeDirections() { return 0; } //deny size changes: dynamic resize is done by the diagram itself

    public StickingPolygon getStickingBorder() {
      StickingPolygon p = new StickingPolygon();
    
    p.addLine(new Point(0,0), new Point(this.getWidth()-1,0),
        Constants.RESIZE_TOP);
    p.addLine(new Point(this.getWidth()-1,0), 
        new Point(this.getWidth()-1,this.getHeight()-1),
        Constants.RESIZE_RIGHT);
    p.addLine(new Point(this.getWidth()-1,this.getHeight()-1), 
        new Point(0,this.getHeight()-1),Constants.RESIZE_BOTTOM);
    p.addLine(new Point(0,this.getHeight()-1), new
        Point(0,0),Constants.RESIZE_LEFT);
    
    return p;
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.