$search
00001 package edu.tum.cs.ias.knowrob.vis.actions; 00002 00003 import java.awt.Color; 00004 import java.awt.Rectangle; 00005 import java.util.ArrayList; 00006 import java.util.Collection; 00007 import java.util.Iterator; 00008 import java.util.List; 00009 00010 import javax.vecmath.Vector2f; 00011 00012 import edu.tum.cs.ias.knowrob.owl.OWLThing; 00013 import edu.tum.cs.ias.knowrob.vis.applets.PlanVisApplet; 00014 00015 import processing.core.PApplet; 00016 00028 public class ActionDrawInformation { 00029 00033 public final static float LINE_HEIGHT = 1.5f; 00038 public final static float INNER_CONTENT_PADDING = 10f; 00042 public final static float MAIN_BOX_PADDING = 15f; 00046 public final static float SEQUENCE_BOX_PADDING = 10f; 00050 public final static float EXPAND_BOX_HEIGHT = 18f; 00051 00055 public final static Vector2f CONNECTOR_DIM = new Vector2f(50f, 7f); 00056 00060 private final static float defaultStroke = 1f; 00064 private final static float currentStroke = 1.5f; 00065 00066 00067 00068 00069 00070 00074 private final static Color borderColor = new Color(100, 100, 100); 00078 private final static Color backgroundColor = new Color(30,30,30); 00082 private final static Color backgroundBrightColor = new Color(50,50,50); 00086 private final static Color textColor = new Color(240,240,240); 00090 private final static Color hoverBorderColor = new Color(200, 200, 200); 00094 private final static Color hoverBackgroundColor = new Color(60,60,60); 00098 private final static Color hoverBackgroundBrightColor = new Color(100,100,100); 00102 private final static Color hoverTextColor = new Color(255,255,255); 00106 private final static Color arrowBorderColor = new Color(27, 56, 102); 00110 private final static Color arrowBackgroundColor = new Color(51,105,192,230); 00114 private final static Color arrowExpandBorderColor = new Color(94, 61, 61); 00118 private final static Color arrowExpandBackgroundColor = new Color(125,67,67,230); 00122 private final static Color hoverArrowExpandBorderColor = new Color(190, 123, 123); 00126 private final static Color hoverArrowExpandBackgroundColor = new Color(190,141,141,230); 00130 private final static Color highlightBorderColor = new Color(103,134,85); 00134 private final static Color highlightBrightBorderColor = new Color(167,217,137); 00135 00136 00137 00138 00139 00140 00141 00148 public static enum HighlightType { 00149 NOT_HIGHTLIGHTED, //Use default color 00150 CHILD_HIGHLIGHTED, //Use highlight color 00151 THIS_HIGHLIGHTED //Use bright highlight color 00152 } 00156 private HighlightType highlight = HighlightType.NOT_HIGHTLIGHTED; 00157 00158 00159 00160 00161 00166 private boolean drawnAsSimple; 00167 00171 private Color currentBorderColor = borderColor; 00172 private Color currentBackgroundColor = backgroundColor; 00173 private Color currentBackgroundBrightColor = backgroundBrightColor; 00174 private Color currentTextColor = textColor; 00175 00179 private Color currentExpandBorderColor = arrowExpandBorderColor; 00180 private Color currentExpandBackgroundColor = arrowExpandBackgroundColor; 00181 00185 private Action action; 00186 00191 private boolean needsRecalculation = true; 00192 00196 private boolean isHover = false; 00197 00201 private float nameWidth; 00202 00206 private float maxKeyWidth; 00210 private float maxValueWidth; 00214 private float propertiesHeight; 00215 00219 private float textHeight; 00220 00221 // /** 00222 // * Maximum box height over all parent actions of this action. 00223 // * Used to draw all parents with same height 00224 // */ 00225 // private float parentsMaxHeight; 00226 // /** 00227 // * Maximum box height over all child actions of this action. 00228 // * Used to draw all parents with same height 00229 // */ 00230 // private float childrenMaxHeight; 00231 // 00232 // /** 00233 // * X position of parent boxes 00234 // */ 00235 // private float parentStartX; 00236 // 00237 // /** 00238 // * X position of child boxes 00239 // */ 00240 // private float childStartX; 00241 00246 private float boxOffsetLeft; 00247 00251 private Vector2f sequenceBoxDimension = new Vector2f(); 00252 00256 private float maxSubsequenceHeight = 0; 00257 00261 private boolean hasExpandButton = false; 00262 00266 public Vector2f position; 00267 00271 public Vector2f localPosOffset; 00272 00276 public Vector2f globalPosOffset; 00277 00278 00279 00283 private Rectangle boundingBoxExtended = new Rectangle(0,0,0,0); 00284 private Rectangle boundingBoxSimple = new Rectangle(0,0,0,0); 00285 00286 00287 00292 public ActionDrawInformation(Action parent) 00293 { 00294 action = parent; 00295 localPosOffset = new Vector2f(); 00296 globalPosOffset = new Vector2f(); 00297 position = new Vector2f(); 00298 } 00299 00304 private void notifyModifiedSubsequences(Action a) 00305 { 00306 if (a==null) 00307 return; 00308 a.getDrawInfo().notifyModified(); 00309 notifyModifiedSubsequences(a.getExpandedSequence()); 00310 } 00311 00316 public void notifyModified() 00317 { 00318 needsRecalculation = true; 00319 notifyModifiedSubsequences(action.getExpandedSequence()); 00320 } 00321 00326 public float getNameBoxHeight() 00327 { 00328 return textHeight*3; 00329 } 00330 00335 public float getNameWidth() 00336 { 00337 return nameWidth; 00338 } 00339 00345 public Vector2f getSimpleBoxDimension() 00346 { 00347 //Max with of name or properties 00348 float width = Math.max(nameWidth,maxKeyWidth+maxValueWidth)+ MAIN_BOX_PADDING*2; 00349 00350 //Height of name box 00351 float height = getNameBoxHeight(); 00352 00353 height += propertiesHeight+INNER_CONTENT_PADDING + MAIN_BOX_PADDING; 00354 00355 return new Vector2f(width, height); 00356 } 00357 00363 public Vector2f getExtendedBoxDimension() 00364 { 00365 Vector2f dim = getSimpleBoxDimension(); 00366 dim.x = Math.max(dim.x,sequenceBoxDimension.x + 2*MAIN_BOX_PADDING); 00367 dim.y += sequenceBoxDimension.y + INNER_CONTENT_PADDING; 00368 00369 return dim; 00370 } 00371 00379 private static void checkAndAddSizeOfExpandedSequence(PApplet applet,Vector2f currentSequenceBoxSize, Action currAction) 00380 { 00381 if (currAction.getDrawInfo().needsRecalculation) 00382 currAction.getDrawInfo().recalculateDimensions(applet); 00383 if (currAction.getExpandedSequence() != null) 00384 { 00385 Action exp = currAction.getExpandedSequence(); 00386 currentSequenceBoxSize.x = Math.max(currentSequenceBoxSize.x,exp.getDrawInfo().sequenceBoxDimension.x+2*SEQUENCE_BOX_PADDING); 00387 currentSequenceBoxSize.y += exp.getDrawInfo().sequenceBoxDimension.y; 00388 } 00389 } 00390 00397 public void recalculateDimensions(PApplet applet) 00398 { 00399 if (!needsRecalculation) 00400 return; 00401 00402 float totalWidth = 0; 00403 float totalHeight = 0; 00404 00405 //Text dimension 00406 textHeight = applet.textAscent(); 00407 nameWidth = applet.textWidth(action.getLabel()); 00408 00409 //Properties of the action 00410 maxKeyWidth = 0; 00411 maxValueWidth = 0; 00412 propertiesHeight = 0; 00413 00414 // add one line to properties for type: info 00415 propertiesHeight += textHeight* LINE_HEIGHT; 00416 00417 Collection<String> keys = action.getProperties().keySet(); 00418 for (Iterator<String> it = keys.iterator(); it.hasNext(); ) 00419 { 00420 String key = it.next(); 00421 maxKeyWidth = Math.max(maxKeyWidth, applet.textWidth( OWLThing.getShortNameOfIRI(key)+": ")); 00422 for (String value : action.getProperty(key)) 00423 { 00424 maxValueWidth = Math.max(maxValueWidth, applet.textWidth( OWLThing.getShortNameOfIRI(value))); 00425 propertiesHeight += textHeight* LINE_HEIGHT; 00426 } 00427 } 00428 00429 needsRecalculation = false; 00430 00431 //Calculation for sequence boxes 00432 sequenceBoxDimension.x = SEQUENCE_BOX_PADDING; 00433 sequenceBoxDimension.y = 0; 00434 hasExpandButton = false; 00435 00436 List<Action> sub = action.getSubActions(); 00437 synchronized(sub) { 00438 for (Action a : sub) { 00439 00440 if (a.getSubActionsCount() > 0) 00441 hasExpandButton = true; 00442 ActionDrawInformation inf = a.getDrawInfo(); 00443 00444 inf.recalculateDimensions(applet); 00445 00446 sequenceBoxDimension.x += inf.getSimpleBoxDimension().x + SEQUENCE_BOX_PADDING; 00447 sequenceBoxDimension.y = Math.max(sequenceBoxDimension.y, inf.getSimpleBoxDimension().y + 2*SEQUENCE_BOX_PADDING); 00448 } 00449 } 00450 maxSubsequenceHeight = sequenceBoxDimension.y- 2*SEQUENCE_BOX_PADDING; 00451 if (hasExpandButton) 00452 sequenceBoxDimension.y += EXPAND_BOX_HEIGHT; 00453 checkAndAddSizeOfExpandedSequence(applet,sequenceBoxDimension,action); 00454 00455 // //Calculation for parent boxes 00456 // parentsMaxHeight = 0; 00457 // float parentsWidth = 0; 00458 // for (Iterator<Action> i = action.getParentActionsIterator(); i.hasNext(); ) 00459 // { 00460 // ActionDrawInformation inf = i.next().getDrawInfo(); 00461 // 00462 // inf.recalculateDimensions(applet); 00463 // 00464 // parentsMaxHeight = Math.max(parentsMaxHeight, inf.getSimpleBoxDimension().y); 00465 // parentsWidth += inf.getSimpleBoxDimension().x+MAIN_BOX_PADDING; 00466 // } 00467 // parentsWidth = Math.max(0, parentsWidth-MAIN_BOX_PADDING); 00468 // 00469 // totalWidth = Math.max(totalWidth, parentsWidth); 00470 // totalHeight += parentsMaxHeight+MAIN_BOX_PADDING; 00471 00472 // //Calculation for child boxes 00473 // childrenMaxHeight = 0; 00474 // float childrenWidth = 0; 00475 // for (Iterator<Action> i = action.getChildActionsIterator(); i.hasNext(); ) 00476 // { 00477 // ActionDrawInformation inf = i.next().getDrawInfo(); 00478 // 00479 // inf.recalculateDimensions(applet); 00480 // 00481 // childrenMaxHeight = Math.max(childrenMaxHeight, inf.getSimpleBoxDimension().y); 00482 // childrenWidth += inf.getSimpleBoxDimension().x+MAIN_BOX_PADDING; 00483 // } 00484 // childrenWidth = Math.max(0, childrenWidth-MAIN_BOX_PADDING); 00485 // totalWidth = Math.max(totalWidth, childrenWidth); 00486 // totalHeight += childrenMaxHeight+MAIN_BOX_PADDING; 00487 00488 // this.boxOffsetLeft = Math.max(0, Math.max((parentsWidth-getExtendedBoxDimension().x)/2f,(childrenWidth-getExtendedBoxDimension().x)/2f)); 00489 00490 // this.parentStartX = Math.max(0, getExtendedBoxDimension().x/2f-parentsWidth/2f); 00491 // this.childStartX = Math.max(0, getExtendedBoxDimension().x/2f-childrenWidth/2f); 00492 00493 totalWidth = Math.max(totalWidth, getExtendedBoxDimension().x); 00494 totalHeight += getExtendedBoxDimension().y; 00495 00496 boundingBoxExtended.width = (int)totalWidth; 00497 boundingBoxExtended.height = (int)totalHeight; 00498 00499 boundingBoxSimple.width = (int)getSimpleBoxDimension().x; 00500 boundingBoxSimple.height = (int)getSimpleBoxDimension().y; 00501 00502 } 00503 00510 private void drawBorderAndTitle(PApplet applet, Vector2f position, Vector2f dimension) 00511 { 00512 //Draw outer border and background 00513 applet.fill(currentBackgroundColor.getRed(), currentBackgroundColor.getGreen(), currentBackgroundColor.getBlue(), currentBackgroundColor.getAlpha()); 00514 applet.rect(position.x, position.y, dimension.x, dimension.y); 00515 00516 //Draw box title 00517 applet.fill(currentBackgroundBrightColor.getRed(), currentBackgroundBrightColor.getGreen(), currentBackgroundBrightColor.getBlue(), currentBackgroundBrightColor.getAlpha()); 00518 applet.rect(position.x,position.y,dimension.x, getNameBoxHeight()); 00519 applet.fill(currentTextColor.getRed(), currentTextColor.getGreen(), currentTextColor.getBlue(), currentTextColor.getAlpha()); 00520 applet.text(action.getLabel(),position.x + MAIN_BOX_PADDING,position.y + textHeight*2f); 00521 } 00522 00528 private void drawProperties(PApplet applet, Vector2f position) 00529 { 00530 applet.fill(currentTextColor.getRed(), currentTextColor.getGreen(), currentTextColor.getBlue(), currentTextColor.getAlpha()); 00531 00532 for (String key : action.getProperties().keySet() ) { 00533 00534 for (String value : action.getProperty(key)) { 00535 00536 applet.text( OWLThing.getShortNameOfIRI(key) + ":",position.x,position.y+textHeight); 00537 applet.text( OWLThing.getShortNameOfIRI(value),position.x + maxKeyWidth, position.y+textHeight); 00538 00539 position.y += textHeight * LINE_HEIGHT; 00540 } 00541 } 00542 } 00543 00550 public void drawSimpleBox(PApplet applet,Vector2f position, Vector2f drawOffset, float minHeight) 00551 { 00552 drawSimpleBox(applet, position, drawOffset, minHeight,false); 00553 } 00554 00561 public void drawSimpleBox(PApplet applet, Vector2f position, Vector2f drawOffset, float minHeight, boolean drawExpandBox) 00562 { 00563 this.drawnAsSimple = true; 00564 this.position = new Vector2f(position); 00565 this.globalPosOffset = drawOffset; 00566 boundingBoxSimple.x = (int)position.x; 00567 boundingBoxSimple.y = (int)position.y; 00568 Vector2f tmpPos = new Vector2f(position.x + localPosOffset.x + drawOffset.x, position.y + localPosOffset.y + drawOffset.y); 00569 recalculateDimensions(applet); 00570 00571 if (highlight == HighlightType.NOT_HIGHTLIGHTED) 00572 applet.stroke(currentBorderColor.getRed(), currentBorderColor.getGreen(), currentBorderColor.getBlue(), currentBorderColor.getAlpha()); 00573 else if (highlight == HighlightType.CHILD_HIGHLIGHTED) 00574 applet.stroke(highlightBorderColor.getRed(), highlightBorderColor.getGreen(), highlightBorderColor.getBlue(), highlightBorderColor.getAlpha()); 00575 else if (highlight == HighlightType.THIS_HIGHLIGHTED) 00576 { 00577 applet.strokeWeight(currentStroke); 00578 applet.stroke(highlightBrightBorderColor.getRed(), highlightBrightBorderColor.getGreen(), highlightBrightBorderColor.getBlue(), highlightBrightBorderColor.getAlpha()); 00579 } 00580 drawBorderAndTitle(applet, tmpPos, new Vector2f(getSimpleBoxDimension().x,Math.max(minHeight, getSimpleBoxDimension().y))); 00581 applet.strokeWeight(defaultStroke); 00582 00583 if (drawExpandBox) 00584 { 00585 applet.stroke(currentExpandBorderColor.getRed(), currentExpandBorderColor.getGreen(), currentExpandBorderColor.getBlue(), currentExpandBorderColor.getAlpha()); 00586 applet.fill(currentExpandBackgroundColor.getRed(), currentExpandBackgroundColor.getGreen(), currentExpandBackgroundColor.getBlue(), currentExpandBackgroundColor.getAlpha()); 00587 00588 00589 Vector2f from = new Vector2f(tmpPos.x+getSimpleBoxDimension().x/2f,tmpPos.y+Math.max(minHeight, getSimpleBoxDimension().y)+4); 00590 Vector2f to = new Vector2f(tmpPos.x+getSimpleBoxDimension().x/2f,tmpPos.y+Math.max(minHeight, getSimpleBoxDimension().y)+EXPAND_BOX_HEIGHT-4); 00591 if (action.isExpanded()) 00592 PlanVisApplet.arrowFromTo(applet, to, from, 6,0); 00593 else 00594 PlanVisApplet.arrowFromTo(applet, from, to, 6,0); 00595 } 00596 00597 tmpPos.x += MAIN_BOX_PADDING; 00598 tmpPos.y += getNameBoxHeight()+INNER_CONTENT_PADDING; 00599 00600 drawProperties(applet, tmpPos); 00601 00602 // draw inbound and outbound connectors 00603 applet.fill(backgroundBrightColor.getRed(), backgroundBrightColor.getGreen(), backgroundBrightColor.getBlue(), backgroundBrightColor.getAlpha()); 00604 applet.stroke(currentBorderColor.getRed(), currentBorderColor.getGreen(), currentBorderColor.getBlue(), currentBorderColor.getAlpha()); 00605 applet.rect(getInboundConnectorPos().x-CONNECTOR_DIM.x/2, getInboundConnectorPos().y-CONNECTOR_DIM.y, CONNECTOR_DIM.x, CONNECTOR_DIM.y); 00606 00607 // draw inbound and outbound connectors 00608 applet.fill(backgroundBrightColor.getRed(), backgroundBrightColor.getGreen(), backgroundBrightColor.getBlue(), backgroundBrightColor.getAlpha()); 00609 applet.stroke(currentBorderColor.getRed(), currentBorderColor.getGreen(), currentBorderColor.getBlue(), currentBorderColor.getAlpha()); 00610 applet.rect(getOutboundConnectorPos().x-CONNECTOR_DIM.x/2, getOutboundConnectorPos().y, CONNECTOR_DIM.x, CONNECTOR_DIM.y); 00611 } 00612 00613 // /** 00614 // * Draw the parent boxes of this action. These are located over the action box 00615 // * @param applet Applet to draw on 00616 // * @param position start position where to begin to draw 00617 // * @return ArrayList of Vector2f with the points at the center bottom for drawing connection arrows 00618 // */ 00619 // private ArrayList<Vector2f> drawParentBoxes(PApplet applet, Vector2f position, Vector2f drawOffset) 00620 // { 00621 // Vector2f tmpPos = new Vector2f(position); 00622 // ArrayList<Vector2f> retPoints = new ArrayList<Vector2f>(); 00623 // 00624 // for (Iterator<Action> i = action.getParentActionsIterator(); i.hasNext(); ) 00625 // { 00626 // ActionDrawInformation inf = i.next().getDrawInfo(); 00627 // 00628 // inf.drawSimpleBox(applet, tmpPos, drawOffset, parentsMaxHeight); 00629 // 00630 // retPoints.add(new Vector2f(tmpPos.x + inf.getSimpleBoxDimension().x/2f, tmpPos.y+parentsMaxHeight-5)); 00631 // 00632 // tmpPos.x += inf.getSimpleBoxDimension().x + MAIN_BOX_PADDING; 00633 // } 00634 // return retPoints; 00635 // } 00636 00637 // /** 00638 // * Draw the child boxes of this action. These are located under the extended action box 00639 // * @param applet Applet to draw on 00640 // * @param position start position where to begin to draw 00641 // * @return ArrayList of Vector2f with the points at the center bottom for drawing connection arrows 00642 // */ 00643 // private ArrayList<Vector2f> drawChildrenBoxes(PApplet applet, Vector2f position, Vector2f drawOffset) 00644 // { 00645 // Vector2f tmpPos = new Vector2f(position); 00646 // ArrayList<Vector2f> retPoints = new ArrayList<Vector2f>(); 00647 // 00648 // for (Iterator<Action> i = action.getChildActionsIterator(); i.hasNext(); ) 00649 // { 00650 // ActionDrawInformation inf = i.next().getDrawInfo(); 00651 // 00652 // inf.drawSimpleBox(applet, tmpPos, drawOffset, childrenMaxHeight); 00653 // 00654 // retPoints.add(new Vector2f(tmpPos.x + inf.getSimpleBoxDimension().x/2f, tmpPos.y+5)); 00655 // 00656 // tmpPos.x += inf.getSimpleBoxDimension().x + MAIN_BOX_PADDING; 00657 // } 00658 // return retPoints; 00659 // } 00660 // 00661 // /** 00662 // * Connect each point of parentPoints with the current action box. Do the same with child points. 00663 // * The target points will be calculated by this function with a homogeneous distribution over the 00664 // * whole with of the current action box. 00665 // * 00666 // * @param applet Applet to draw on 00667 // * @param parentPoints Connection points of parent actions 00668 // * @param childPoints Connection points of child actions 00669 // */ 00670 // private void drawArrows(PApplet applet, ArrayList<Vector2f> parentPoints, ArrayList<Vector2f> childPoints) 00671 // { 00672 // applet.stroke(arrowBorderColor.getRed(), arrowBorderColor.getGreen(), arrowBorderColor.getBlue(), arrowBorderColor.getAlpha()); 00673 // applet.fill(arrowBackgroundColor.getRed(), arrowBackgroundColor.getGreen(), arrowBackgroundColor.getBlue(), arrowBackgroundColor.getAlpha()); 00674 // 00675 // Vector2f connPointParent = new Vector2f(position.x + localPosOffset.x + globalPosOffset.x, position.y + localPosOffset.y + globalPosOffset.x); 00676 // connPointParent.x+=boxOffsetLeft; 00677 // Vector2f connPointChildren = new Vector2f(connPointParent); 00678 // connPointChildren.y += getExtendedBoxDimension().y-5; 00679 // connPointParent.y += 5; 00680 // 00681 // float diffParent = getExtendedBoxDimension().x / (parentPoints.size()+1); 00682 // 00683 // for (int i=0; i<parentPoints.size(); i++) 00684 // { 00685 // connPointParent.x += diffParent; 00686 // PlanVisApplet.arrowFromTo(applet, parentPoints.get(i), connPointParent, 5,-1); 00687 // } 00688 // 00689 // float diffChild = getExtendedBoxDimension().x / (childPoints.size()+1); 00690 // 00691 // for (int i=0; i<childPoints.size(); i++) 00692 // { 00693 // connPointChildren.x += diffChild; 00694 // PlanVisApplet.arrowFromTo(applet, connPointChildren,childPoints.get(i), 5,-1); 00695 // } 00696 // } 00697 00703 private void drawSequence(PApplet applet, Vector2f position, Vector2f drawOffset, boolean isExpandedBox) { 00704 00705 00706 List<Action> sub = action.getSubActions(); 00707 00708 if (sub.isEmpty()) 00709 return; 00710 00711 synchronized(sub) { 00712 00713 //Draw outer box of sequence list 00714 applet.stroke(currentBorderColor.getRed(), currentBorderColor.getGreen(), currentBorderColor.getBlue(), currentBorderColor.getAlpha()); 00715 00716 if (isExpandedBox) 00717 applet.fill(currentBackgroundColor.getRed(), currentBackgroundColor.getGreen(), currentBackgroundColor.getBlue(), currentBackgroundColor.getAlpha()); 00718 else 00719 applet.fill(currentBackgroundBrightColor.getRed(), currentBackgroundBrightColor.getGreen(), currentBackgroundBrightColor.getBlue(), currentBackgroundBrightColor.getAlpha()); 00720 00721 applet.rect(position.x, position.y, sequenceBoxDimension.x, sequenceBoxDimension.y); 00722 00723 //Calculate start pos of inner boxes 00724 Vector2f tmpPos = new Vector2f(position); 00725 tmpPos.y += SEQUENCE_BOX_PADDING; 00726 tmpPos.x += SEQUENCE_BOX_PADDING; 00727 00728 //Store the positions of each box to connect them afterwards 00729 ArrayList<Float> pos = new ArrayList<Float>(); 00730 00731 Vector2f expandedParentCorner1 = null; 00732 Vector2f expandedParentCorner2 = null; 00733 00734 Action expSeq = action.getExpandedSequence(); 00735 00736 00737 //Draw inner boxes 00738 for (Action a : sub) { 00739 00740 ActionDrawInformation inf = a.getDrawInfo(); 00741 00742 inf.drawSimpleBox(applet, tmpPos, drawOffset, maxSubsequenceHeight,a.getSubActionsCount()>0); 00743 if (a == expSeq) { 00744 expandedParentCorner1 = new Vector2f(tmpPos.x,tmpPos.y+maxSubsequenceHeight); 00745 expandedParentCorner2 = new Vector2f(tmpPos.x+inf.getSimpleBoxDimension().x,tmpPos.y+maxSubsequenceHeight); 00746 } 00747 00748 tmpPos.x += inf.getSimpleBoxDimension().x + SEQUENCE_BOX_PADDING; 00749 pos.add(tmpPos.x); 00750 } 00751 00752 //Draw connection arrows for each sequence box 00753 for (int i=0; i<pos.size()-1; i++) { 00754 00755 applet.stroke(arrowBorderColor.getRed(), arrowBorderColor.getGreen(), arrowBorderColor.getBlue(), arrowBorderColor.getAlpha()); 00756 applet.fill(arrowBackgroundColor.getRed(), arrowBackgroundColor.getGreen(), arrowBackgroundColor.getBlue(), arrowBackgroundColor.getAlpha()); 00757 PlanVisApplet.arrow(applet,pos.get(i)-SEQUENCE_BOX_PADDING - 5,tmpPos.y+getNameBoxHeight()/2-10,20,SEQUENCE_BOX_PADDING+11); 00758 } 00759 00760 //Draw expanded subsequences if any 00761 Vector2f startPos = new Vector2f(position); 00762 startPos.y +=SEQUENCE_BOX_PADDING + maxSubsequenceHeight + EXPAND_BOX_HEIGHT; 00763 00764 if (expSeq != null && expandedParentCorner1 != null && expandedParentCorner2 != null) { 00765 00766 Vector2f subDim = expSeq.getDrawInfo().sequenceBoxDimension; 00767 startPos.x = (expandedParentCorner2.x+expandedParentCorner1.x)/2f; 00768 startPos.x -= subDim.x/2f; 00769 00770 startPos.x = Math.max(startPos.x, position.x+SEQUENCE_BOX_PADDING); 00771 00772 startPos.x -= Math.max(0, (startPos.x +subDim.x) - (position.x+sequenceBoxDimension.x-SEQUENCE_BOX_PADDING)); 00773 00774 00775 //applet.stroke(currentBorderColor.getRed(), currentBorderColor.getGreen(), currentBorderColor.getBlue(), currentBorderColor.getAlpha()); 00776 //applet.fill(currentBackgroundColor.getRed(), currentBackgroundColor.getGreen(), currentBackgroundColor.getBlue(), currentBackgroundColor.getAlpha()); 00777 //applet.line(expandedParentCorner1.x, expandedParentCorner1.y, startPos.x, startPos.y); 00778 //applet.line(expandedParentCorner2.x, expandedParentCorner2.y, startPos.x+subDim.x, startPos.y); 00779 00780 expSeq.getDrawInfo().drawSequence(applet, startPos, drawOffset, true); 00781 } 00782 } 00783 } 00784 00791 public void drawExtendedBox(PApplet applet, Vector2f position, Vector2f drawOffset) 00792 { 00793 this.drawnAsSimple = false; 00794 recalculateDimensions(applet); 00795 00796 boundingBoxExtended.x = (int)position.x; 00797 boundingBoxExtended.y = (int)position.y; 00798 00799 Vector2f extendedDim = getExtendedBoxDimension(); 00800 00801 //Draw parents 00802 // ArrayList<Vector2f> parentPoints = drawParentBoxes(applet, new Vector2f(position.x + parentStartX,position.y), drawOffset); 00803 // 00804 // position.y += parentsMaxHeight+MAIN_BOX_PADDING; 00805 00806 //Border & title 00807 this.position = new Vector2f(position); 00808 applet.strokeWeight(currentStroke); 00809 applet.stroke(hoverBorderColor.getRed(), hoverBorderColor.getGreen(), hoverBorderColor.getBlue(), hoverBorderColor.getAlpha()); 00810 position.x += boxOffsetLeft; 00811 drawBorderAndTitle(applet, position,extendedDim); 00812 applet.strokeWeight(defaultStroke); 00813 00814 position.x += MAIN_BOX_PADDING; 00815 position.y += getNameBoxHeight()+INNER_CONTENT_PADDING; 00816 00817 //Properties 00818 drawProperties(applet, position); 00819 00820 position.y += INNER_CONTENT_PADDING; 00821 00822 //Subsequences 00823 drawSequence(applet, position, new Vector2f(), false); 00824 00825 position.y += sequenceBoxDimension.y; 00826 position.x -= MAIN_BOX_PADDING; 00827 position.x -= boxOffsetLeft; 00828 00829 position.y += MAIN_BOX_PADDING*2; 00830 //Children 00831 // ArrayList<Vector2f> childPoints = drawChildrenBoxes(applet, new Vector2f(position.x + childStartX,position.y), drawOffset); 00832 00833 // drawArrows(applet, parentPoints, childPoints); 00834 } 00835 00841 private void setHover(boolean hover) 00842 { 00843 if (hover) 00844 { 00845 currentBorderColor = hoverBorderColor; 00846 currentBackgroundColor = hoverBackgroundColor; 00847 currentBackgroundBrightColor = hoverBackgroundBrightColor; 00848 currentTextColor = hoverTextColor; 00849 } else 00850 { 00851 currentBorderColor = borderColor; 00852 currentBackgroundColor = backgroundColor; 00853 currentBackgroundBrightColor = backgroundBrightColor; 00854 currentTextColor = textColor; 00855 } 00856 isHover = hover; 00857 } 00858 00864 private void setHoverExpand(boolean hover) 00865 { 00866 if (hover || action.isExpanded()) 00867 { 00868 currentExpandBorderColor = hoverArrowExpandBorderColor; 00869 currentExpandBackgroundColor = hoverArrowExpandBackgroundColor; 00870 } else 00871 { 00872 currentExpandBorderColor = arrowExpandBorderColor; 00873 currentExpandBackgroundColor = arrowExpandBackgroundColor; 00874 } 00875 } 00876 00885 private ActionDrawInformation checkHoverExtendedSequence(float x, float y, Action currAction, ActionDrawInformation found) { 00886 00887 if (currAction == null) 00888 return null; 00889 00890 //over sequences? 00891 00892 List<Action> sub = action.getSubActions(); 00893 00894 synchronized(sub) { 00895 00896 for (Action a : sub) { 00897 00898 ActionDrawInformation inf = a.getDrawInfo(); 00899 00900 if (found != null) 00901 inf.setHover(false); 00902 else { 00903 found = inf.checkHover(x, y,found); 00904 } 00905 } 00906 return found; 00907 } 00908 } 00909 00917 public ActionDrawInformation checkHover(float x, float y, ActionDrawInformation found) 00918 { 00919 00920 if (position == null) 00921 return found; 00922 00923 //over extended sequences? 00924 found = checkHoverExtendedSequence(x,y,action.getExpandedSequence(), found); 00925 00926 //Check for extended box 00927 if (!drawnAsSimple) 00928 { 00929 00930 //over sequences? 00931 List<Action> sub = action.getSubActions(); 00932 00933 synchronized(sub) { 00934 00935 for (Action a : sub) { 00936 00937 ActionDrawInformation inf = a.getDrawInfo(); 00938 00939 if (found != null) 00940 inf.setHover(false); 00941 else 00942 if (inf.checkHover(x, y,found)!=null) 00943 found = inf; 00944 } 00945 } 00946 00947 // //over parent? 00948 // for (Iterator<Action> i = action.getParentActionsIterator(); i.hasNext(); ) 00949 // { 00950 // ActionDrawInformation inf = i.next().getDrawInfo(); 00951 // 00952 // if (found != null) 00953 // inf.setHover(false); 00954 // else 00955 // if (inf.checkHover(x, y,found)!=null) 00956 // found = inf; 00957 // } 00958 // 00959 // //over child 00960 // for (Iterator<Action> i = action.getChildActionsIterator(); i.hasNext(); ) 00961 // { 00962 // ActionDrawInformation inf = i.next().getDrawInfo(); 00963 // 00964 // if (found != null) 00965 // inf.setHover(false); 00966 // else 00967 // if (inf.checkHover(x, y,found)!=null) 00968 // found = inf; 00969 // } 00970 00971 //not hovering, so set correct colors 00972 setHover(false); 00973 return found; //will be null 00974 00975 } else if(checkPosOverInboundConnector(x, y)!=null) { 00976 setHover(true); 00977 return this; 00978 00979 } else if(checkPosOverOutboundConnector(x, y)!=null) { 00980 setHover(true); 00981 return this; 00982 00983 } else { 00984 //Check hovering if drawn as simple box 00985 Vector2f dim = getSimpleBoxDimension(); 00986 float boxX,boxY,boxW,boxH; 00987 boxX = position.x + localPosOffset.x + globalPosOffset.x; 00988 boxY = position.y + localPosOffset.y + globalPosOffset.y; 00989 boxW = dim.x; 00990 boxH = dim.y; 00991 if (x>boxX && x<boxX+boxW && y>boxY && y<boxY+boxH) 00992 { 00993 setHover(true); 00994 return this; 00995 } else { 00996 setHover(false); 00997 return found; 00998 } 00999 } 01000 01001 } 01002 01010 private ActionDrawInformation checkHoverExpand(float mouse_x, float mouse_y, boolean hasExpandButton, float sequenceBoxHeight, boolean parentExpanded) { 01011 01012 if (position == null) 01013 return null; 01014 01015 ActionDrawInformation found = null; 01016 01017 //over sequences? 01018 if (parentExpanded) { 01019 01020 List<Action> sub = action.getSubActions(); 01021 01022 synchronized(sub) { 01023 for (Action a : sub) { 01024 01025 ActionDrawInformation inf = a.getDrawInfo(); 01026 01027 if (found != null) 01028 inf.setHoverExpand(false); 01029 else { 01030 ActionDrawInformation d = inf.checkHoverExpand(mouse_x, mouse_y,this.hasExpandButton,this.maxSubsequenceHeight, a.isExpanded()); 01031 if (d!=null) 01032 found = d; 01033 } 01034 } 01035 } 01036 } 01037 01038 if (hasExpandButton) { 01039 //Check hovering if drawn as simple box 01040 Vector2f dim = getSimpleBoxDimension(); 01041 float boxX,boxY,boxW,boxH; 01042 boxX = position.x + localPosOffset.x + globalPosOffset.x; 01043 boxY = position.y + localPosOffset.y + globalPosOffset.y +sequenceBoxHeight; 01044 boxW = dim.x; 01045 boxH = EXPAND_BOX_HEIGHT; 01046 if (action.getSubActionsCount() > 0 && mouse_x>boxX && mouse_x<boxX+boxW && mouse_y>boxY && mouse_y<boxY+boxH) 01047 { 01048 setHoverExpand(true); 01049 return this; 01050 } else { 01051 setHoverExpand(false); 01052 return found; 01053 } 01054 } 01055 01056 return found; 01057 01058 } 01059 01060 01068 public Action checkPosOverInboundConnector(float mouse_x, float mouse_y) { 01069 01070 float boxX = getInboundConnectorPos().x-CONNECTOR_DIM.x/2; 01071 float boxY = getInboundConnectorPos().y-CONNECTOR_DIM.y; 01072 float boxW = CONNECTOR_DIM.x; 01073 float boxH = CONNECTOR_DIM.y; 01074 01075 if (mouse_x>boxX && mouse_x<boxX+boxW && 01076 mouse_y>boxY && mouse_y<boxY+boxH) { 01077 return this.action; 01078 } 01079 return null; 01080 } 01081 01082 01090 public Action checkPosOverOutboundConnector(float mouse_x, float mouse_y) { 01091 01092 float boxX = getOutboundConnectorPos().x-CONNECTOR_DIM.x/2; 01093 float boxY = getOutboundConnectorPos().y; 01094 float boxW = CONNECTOR_DIM.x; 01095 float boxH = CONNECTOR_DIM.y; 01096 01097 if (mouse_x>boxX && mouse_x<boxX+boxW && 01098 mouse_y>boxY && mouse_y<boxY+boxH) { 01099 01100 return this.action; 01101 } 01102 return null; 01103 } 01104 01105 01112 public boolean updateHover(float x, float y) 01113 { 01114 boolean found = checkHover(x,y,null)!=null; 01115 return (checkHoverExpand(x, y, false,0,true)!=null || found); 01116 } 01117 01124 public Action checkClick(float x, float y) 01125 { 01126 ActionDrawInformation a = checkHover(x,y,null); 01127 if (a==null) 01128 return null; 01129 else 01130 return a.action; 01131 } 01132 01139 public Action checkClickExpand(float x, float y) 01140 { 01141 ActionDrawInformation a = checkHoverExpand(x, y, false,0,true); 01142 if (a==null) 01143 return null; 01144 else 01145 return a.action; 01146 } 01147 01152 public float getTextHeight() 01153 { 01154 return textHeight; 01155 } 01156 01161 public boolean IsHover() 01162 { 01163 return isHover; 01164 } 01165 01171 public Rectangle getBoundingBox() 01172 { 01173 if (drawnAsSimple) 01174 return boundingBoxSimple; 01175 else 01176 return boundingBoxExtended; 01177 } 01178 01183 public HighlightType getHighlight() 01184 { 01185 return highlight; 01186 } 01187 01192 public void setHightlight(HighlightType h) 01193 { 01194 this.highlight = h; 01195 } 01196 01201 public void clearHightlight() 01202 { 01203 if (this.highlight == HighlightType.NOT_HIGHTLIGHTED) 01204 return; 01205 else if (this.highlight == HighlightType.THIS_HIGHLIGHTED) 01206 { 01207 this.highlight = HighlightType.NOT_HIGHTLIGHTED; 01208 return; 01209 } 01210 01211 List<Action> sub = action.getSubActions(); 01212 01213 synchronized(sub) { 01214 for (Action a : sub) { 01215 01216 ActionDrawInformation inf = a.getDrawInfo(); 01217 01218 if (inf.highlight == HighlightType.CHILD_HIGHLIGHTED || inf.highlight == HighlightType.THIS_HIGHLIGHTED) 01219 { 01220 inf.clearHightlight(); 01221 this.highlight = HighlightType.NOT_HIGHTLIGHTED; 01222 return; 01223 } 01224 } 01225 } 01226 } 01227 01235 public boolean highlightSubsequence(String identifier, boolean expand) 01236 { 01237 if (this.action.getIRI().compareTo(identifier)==0) { 01238 setHightlight(HighlightType.THIS_HIGHLIGHTED); 01239 notifyModified(); 01240 return true; 01241 } 01242 01243 //Check sequence of this action 01244 List<Action> sub = action.getSubActions(); 01245 01246 synchronized(sub) { 01247 for (Action a : sub) { 01248 01249 ActionDrawInformation inf = a.getDrawInfo(); 01250 01251 if (a.getIRI().compareTo(identifier)==0) { 01252 inf.setHightlight(HighlightType.THIS_HIGHLIGHTED); 01253 setHightlight(HighlightType.CHILD_HIGHLIGHTED); 01254 notifyModified(); 01255 return true; 01256 01257 } else if (inf.highlightSubsequence(identifier, expand)) { 01258 inf.setHightlight(HighlightType.CHILD_HIGHLIGHTED); 01259 setHightlight(HighlightType.CHILD_HIGHLIGHTED); 01260 if (expand) 01261 action.setExpandedSequence(a); 01262 notifyModified(); 01263 return true; 01264 } 01265 } 01266 } 01267 return false; 01268 } 01269 01277 public boolean highlightSubsequence(Action seq, boolean expand) 01278 { 01279 if (this.action == seq) { 01280 setHightlight(HighlightType.THIS_HIGHLIGHTED); 01281 return true; 01282 } 01283 01284 //Check sequence of this action 01285 List<Action> sub = action.getSubActions(); 01286 01287 synchronized(sub) { 01288 for (Action a : sub) { 01289 01290 ActionDrawInformation inf = a.getDrawInfo(); 01291 01292 if (a == seq) 01293 { 01294 inf.setHightlight(HighlightType.THIS_HIGHLIGHTED); 01295 setHightlight(HighlightType.CHILD_HIGHLIGHTED); 01296 return true; 01297 } else if (inf.highlightSubsequence(seq, expand)) 01298 { 01299 inf.setHightlight(HighlightType.CHILD_HIGHLIGHTED); 01300 setHightlight(HighlightType.CHILD_HIGHLIGHTED); 01301 if (expand) 01302 action.setExpandedSequence(a); 01303 return true; 01304 } 01305 } 01306 } 01307 return false; 01308 } 01309 01310 01311 01312 public Vector2f getOutboundConnectorPos() { 01313 01314 // TODO: replace with better computation, taking extended status into account 01315 return new Vector2f(position.x + localPosOffset.x + globalPosOffset.x + this.getSimpleBoxDimension().x/2, position.y + localPosOffset.y + globalPosOffset.y + this.getSimpleBoxDimension().y); 01316 } 01317 01318 public Vector2f getInboundConnectorPos() { 01319 // TODO: replace with better computation, taking extended status into account 01320 return new Vector2f(position.x + localPosOffset.x + globalPosOffset.x + this.getSimpleBoxDimension().x/2, position.y + localPosOffset.y + globalPosOffset.y); 01321 } 01322 }