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 {
00152                 NOT_HIGHTLIGHTED,
00156                 CHILD_HIGHLIGHTED,
00160                 THIS_HIGHLIGHTED
00161         }
00165         private HighlightType highlight = HighlightType.NOT_HIGHTLIGHTED;
00166         
00167         
00168         
00169         
00170 
00175         private boolean drawnAsSimple;
00176         
00180         private Color currentBorderColor = borderColor;
00181         private Color currentBackgroundColor = backgroundColor;
00182         private Color currentBackgroundBrightColor = backgroundBrightColor;
00183         private Color currentTextColor = textColor;
00184         
00188         private Color currentExpandBorderColor = arrowExpandBorderColor;
00189         private Color currentExpandBackgroundColor = arrowExpandBackgroundColor;
00190         
00194         private Action action;
00195         
00200         private boolean needsRecalculation = true;
00201         
00205         private boolean isHover = false;
00206         
00210         private float nameWidth;
00211         
00215         private float maxKeyWidth;
00219         private float maxValueWidth;
00223         private float propertiesHeight;
00224         
00228         private float textHeight;
00229         
00230 
00231 
00232 
00233 
00234 
00235 
00236 
00237 
00238 
00239 
00240 
00241 
00242 
00243 
00244 
00245 
00246 
00247 
00248 
00249 
00250         
00255         private float boxOffsetLeft;
00256         
00260         private Vector2f sequenceBoxDimension = new Vector2f();
00261         
00265         private float maxSubsequenceHeight = 0;
00266         
00270         private boolean hasExpandButton = false;
00271 
00275         public Vector2f position;
00276 
00280         public Vector2f localPosOffset;
00281 
00285         public Vector2f globalPosOffset;
00286         
00287         
00288         
00292         private Rectangle boundingBoxExtended = new Rectangle(0,0,0,0);
00293         private Rectangle boundingBoxSimple = new Rectangle(0,0,0,0);
00294         
00295         
00296         
00301         public ActionDrawInformation(Action parent)
00302         {
00303                 action = parent;
00304                 localPosOffset = new Vector2f();
00305                 globalPosOffset = new Vector2f();
00306                 position = new Vector2f();
00307         }
00308         
00313         private void notifyModifiedSubsequences(Action a)
00314         {
00315                 if (a==null)
00316                         return;
00317                 a.getDrawInfo().notifyModified();
00318                 notifyModifiedSubsequences(a.getExpandedSequence());
00319         }
00320         
00325         public void notifyModified()
00326         {
00327                 needsRecalculation = true;
00328                 notifyModifiedSubsequences(action.getExpandedSequence());
00329         }
00330         
00335         public float getNameBoxHeight()
00336         {
00337                 return textHeight*3;
00338         }
00339         
00344         public float getNameWidth()
00345         {
00346                 return nameWidth;
00347         }
00348         
00354         public Vector2f getSimpleBoxDimension()
00355         {
00356                 
00357                 float width = Math.max(nameWidth,maxKeyWidth+maxValueWidth)+ MAIN_BOX_PADDING*2;
00358                 
00359                 
00360                 float height = getNameBoxHeight();
00361                 
00362                 height += propertiesHeight+INNER_CONTENT_PADDING + MAIN_BOX_PADDING;
00363                 
00364                 return new Vector2f(width, height);
00365         }
00366         
00372         public Vector2f getExtendedBoxDimension()
00373         {
00374                 Vector2f dim = getSimpleBoxDimension();
00375                 dim.x = Math.max(dim.x,sequenceBoxDimension.x + 2*MAIN_BOX_PADDING);
00376                 dim.y += sequenceBoxDimension.y + INNER_CONTENT_PADDING;
00377                 
00378                 return dim;
00379         }
00380         
00388         private static void checkAndAddSizeOfExpandedSequence(PApplet applet,Vector2f currentSequenceBoxSize, Action currAction)
00389         {
00390                 if (currAction.getDrawInfo().needsRecalculation)
00391                         currAction.getDrawInfo().recalculateDimensions(applet);
00392                 if (currAction.getExpandedSequence() != null)
00393                 {
00394                         Action exp = currAction.getExpandedSequence();
00395                         currentSequenceBoxSize.x = Math.max(currentSequenceBoxSize.x,exp.getDrawInfo().sequenceBoxDimension.x+2*SEQUENCE_BOX_PADDING);
00396                         currentSequenceBoxSize.y += exp.getDrawInfo().sequenceBoxDimension.y;
00397                 }
00398         }
00399         
00406         public void recalculateDimensions(PApplet applet)
00407         {
00408                 if (!needsRecalculation)
00409                         return;
00410                 
00411                 float totalWidth = 0;
00412                 float totalHeight = 0;
00413                 
00414                 
00415                 textHeight = applet.textAscent();
00416                 nameWidth = applet.textWidth(action.getLabel());
00417                 
00418                 
00419                 maxKeyWidth = 0;
00420                 maxValueWidth = 0;
00421                 propertiesHeight = 0;
00422                 
00423                 
00424                 propertiesHeight += textHeight* LINE_HEIGHT;
00425                 
00426                 Collection<String> keys = action.getProperties().keySet();
00427                 for (Iterator<String> it = keys.iterator(); it.hasNext(); )
00428                 {
00429                         String key = it.next();
00430                         maxKeyWidth = Math.max(maxKeyWidth, applet.textWidth( OWLThing.getShortNameOfIRI(key)+":  "));
00431                         for (String value : action.getProperty(key))
00432                         {
00433                                 maxValueWidth = Math.max(maxValueWidth, applet.textWidth( OWLThing.getShortNameOfIRI(value)));
00434                                 propertiesHeight += textHeight* LINE_HEIGHT;
00435                         }
00436                 }
00437                 
00438                 needsRecalculation = false;
00439                 
00440                 
00441                 sequenceBoxDimension.x = SEQUENCE_BOX_PADDING;
00442                 sequenceBoxDimension.y = 0;
00443                 hasExpandButton = false;
00444                 
00445                 List<Action> sub = action.getSubActions();
00446                 synchronized(sub) {
00447                         for (Action a : sub) {
00448 
00449                                 if (a.getSubActionsCount() > 0)
00450                                         hasExpandButton = true;
00451                                 ActionDrawInformation inf = a.getDrawInfo();
00452 
00453                                 inf.recalculateDimensions(applet);
00454 
00455                                 sequenceBoxDimension.x += inf.getSimpleBoxDimension().x + SEQUENCE_BOX_PADDING;
00456                                 sequenceBoxDimension.y = Math.max(sequenceBoxDimension.y, inf.getSimpleBoxDimension().y + 2*SEQUENCE_BOX_PADDING);
00457                         }
00458                 }
00459                 maxSubsequenceHeight = sequenceBoxDimension.y- 2*SEQUENCE_BOX_PADDING;
00460                 if (hasExpandButton)
00461                         sequenceBoxDimension.y += EXPAND_BOX_HEIGHT;
00462                 checkAndAddSizeOfExpandedSequence(applet,sequenceBoxDimension,action);
00463                 
00464 
00465 
00466 
00467 
00468 
00469 
00470 
00471 
00472 
00473 
00474 
00475 
00476 
00477 
00478 
00479 
00480                 
00481 
00482 
00483 
00484 
00485 
00486 
00487 
00488 
00489 
00490 
00491 
00492 
00493 
00494 
00495 
00496                 
00497 
00498                 
00499 
00500 
00501                 
00502                 totalWidth = Math.max(totalWidth, getExtendedBoxDimension().x);
00503                 totalHeight += getExtendedBoxDimension().y;
00504                 
00505                 boundingBoxExtended.width = (int)totalWidth;
00506                 boundingBoxExtended.height = (int)totalHeight;
00507                 
00508                 boundingBoxSimple.width = (int)getSimpleBoxDimension().x;
00509                 boundingBoxSimple.height = (int)getSimpleBoxDimension().y;
00510 
00511         }
00512         
00519         private void drawBorderAndTitle(PApplet applet, Vector2f position, Vector2f dimension)
00520         {
00521                 
00522             applet.fill(currentBackgroundColor.getRed(), currentBackgroundColor.getGreen(), currentBackgroundColor.getBlue(), currentBackgroundColor.getAlpha());
00523                 applet.rect(position.x, position.y, dimension.x, dimension.y);
00524                 
00525                 
00526                 applet.fill(currentBackgroundBrightColor.getRed(), currentBackgroundBrightColor.getGreen(), currentBackgroundBrightColor.getBlue(), currentBackgroundBrightColor.getAlpha());
00527                 applet.rect(position.x,position.y,dimension.x, getNameBoxHeight());
00528                 applet.fill(currentTextColor.getRed(), currentTextColor.getGreen(), currentTextColor.getBlue(), currentTextColor.getAlpha());
00529                 applet.text(action.getLabel(),position.x + MAIN_BOX_PADDING,position.y + textHeight*2f);
00530         }
00531         
00537         private void drawProperties(PApplet applet, Vector2f position)
00538         {
00539                 applet.fill(currentTextColor.getRed(), currentTextColor.getGreen(), currentTextColor.getBlue(), currentTextColor.getAlpha());
00540                 
00541                 for (String key : action.getProperties().keySet() ) {
00542                         
00543                         for (String value : action.getProperty(key)) {
00544                                 
00545                                 applet.text( OWLThing.getShortNameOfIRI(key) + ":",position.x,position.y+textHeight);
00546                                 applet.text( OWLThing.getShortNameOfIRI(value),position.x + maxKeyWidth, position.y+textHeight);
00547         
00548                                 position.y += textHeight * LINE_HEIGHT;
00549                         }
00550                 }
00551         }
00552         
00559         public void drawSimpleBox(PApplet applet,Vector2f position, Vector2f drawOffset, float minHeight)
00560         {
00561                 drawSimpleBox(applet, position, drawOffset, minHeight,false);
00562         }
00563         
00570         public void drawSimpleBox(PApplet applet, Vector2f position, Vector2f drawOffset, float minHeight, boolean drawExpandBox)
00571         {
00572                 this.drawnAsSimple = true;
00573                 this.position = new Vector2f(position);
00574                 this.globalPosOffset = drawOffset;
00575                 boundingBoxSimple.x = (int)position.x;
00576                 boundingBoxSimple.y = (int)position.y;
00577                 Vector2f tmpPos = new Vector2f(position.x + localPosOffset.x + drawOffset.x, position.y + localPosOffset.y + drawOffset.y);
00578                 recalculateDimensions(applet);
00579                 
00580                 if (highlight == HighlightType.NOT_HIGHTLIGHTED)
00581                         applet.stroke(currentBorderColor.getRed(), currentBorderColor.getGreen(), currentBorderColor.getBlue(), currentBorderColor.getAlpha());
00582                 else if (highlight == HighlightType.CHILD_HIGHLIGHTED)
00583                         applet.stroke(highlightBorderColor.getRed(), highlightBorderColor.getGreen(), highlightBorderColor.getBlue(), highlightBorderColor.getAlpha());
00584                 else if (highlight == HighlightType.THIS_HIGHLIGHTED)
00585                 {
00586                         applet.strokeWeight(currentStroke);
00587                         applet.stroke(highlightBrightBorderColor.getRed(), highlightBrightBorderColor.getGreen(), highlightBrightBorderColor.getBlue(), highlightBrightBorderColor.getAlpha());
00588                 }
00589                 drawBorderAndTitle(applet, tmpPos, new Vector2f(getSimpleBoxDimension().x,Math.max(minHeight, getSimpleBoxDimension().y)));
00590                 applet.strokeWeight(defaultStroke);
00591                 
00592                 if (drawExpandBox)
00593                 {
00594                         applet.stroke(currentExpandBorderColor.getRed(), currentExpandBorderColor.getGreen(), currentExpandBorderColor.getBlue(), currentExpandBorderColor.getAlpha());
00595                     applet.fill(currentExpandBackgroundColor.getRed(), currentExpandBackgroundColor.getGreen(), currentExpandBackgroundColor.getBlue(), currentExpandBackgroundColor.getAlpha());
00596                     
00597 
00598                         Vector2f from = new Vector2f(tmpPos.x+getSimpleBoxDimension().x/2f,tmpPos.y+Math.max(minHeight, getSimpleBoxDimension().y)+4);
00599                         Vector2f to = new Vector2f(tmpPos.x+getSimpleBoxDimension().x/2f,tmpPos.y+Math.max(minHeight, getSimpleBoxDimension().y)+EXPAND_BOX_HEIGHT-4);
00600                     if (action.isExpanded())
00601                         PlanVisApplet.arrowFromTo(applet, to, from, 6,0);
00602                     else
00603                         PlanVisApplet.arrowFromTo(applet, from, to, 6,0);
00604                 }
00605                 
00606                 tmpPos.x += MAIN_BOX_PADDING;
00607                 tmpPos.y += getNameBoxHeight()+INNER_CONTENT_PADDING;
00608                 
00609                 drawProperties(applet, tmpPos);
00610                 
00611                 
00612                 applet.fill(backgroundBrightColor.getRed(), backgroundBrightColor.getGreen(), backgroundBrightColor.getBlue(), backgroundBrightColor.getAlpha());
00613                 applet.stroke(currentBorderColor.getRed(), currentBorderColor.getGreen(), currentBorderColor.getBlue(), currentBorderColor.getAlpha());
00614                 applet.rect(getInboundConnectorPos().x-CONNECTOR_DIM.x/2, getInboundConnectorPos().y-CONNECTOR_DIM.y, CONNECTOR_DIM.x, CONNECTOR_DIM.y);
00615                 
00616                 
00617                 applet.fill(backgroundBrightColor.getRed(), backgroundBrightColor.getGreen(), backgroundBrightColor.getBlue(), backgroundBrightColor.getAlpha());
00618                 applet.stroke(currentBorderColor.getRed(), currentBorderColor.getGreen(), currentBorderColor.getBlue(), currentBorderColor.getAlpha());
00619                 applet.rect(getOutboundConnectorPos().x-CONNECTOR_DIM.x/2, getOutboundConnectorPos().y, CONNECTOR_DIM.x, CONNECTOR_DIM.y);
00620         }
00621         
00622 
00623 
00624 
00625 
00626 
00627 
00628 
00629 
00630 
00631 
00632 
00633 
00634 
00635 
00636 
00637 
00638 
00639 
00640 
00641 
00642 
00643 
00644 
00645         
00646 
00647 
00648 
00649 
00650 
00651 
00652 
00653 
00654 
00655 
00656 
00657 
00658 
00659 
00660 
00661 
00662 
00663 
00664 
00665 
00666 
00667 
00668 
00669 
00670 
00671 
00672 
00673 
00674 
00675 
00676 
00677 
00678 
00679 
00680 
00681 
00682 
00683 
00684 
00685 
00686 
00687 
00688 
00689 
00690 
00691 
00692 
00693 
00694 
00695 
00696 
00697 
00698 
00699 
00700 
00701 
00702 
00703 
00704 
00705 
00706 
00712         private void drawSequence(PApplet applet, Vector2f position, Vector2f drawOffset, boolean isExpandedBox) {
00713                 
00714                 
00715                 List<Action> sub = action.getSubActions();
00716                 
00717                 if (sub.isEmpty())
00718                         return;
00719                 
00720                 synchronized(sub) {
00721 
00722                         
00723                         applet.stroke(currentBorderColor.getRed(), currentBorderColor.getGreen(), currentBorderColor.getBlue(), currentBorderColor.getAlpha());
00724                         
00725                         if (isExpandedBox)
00726                                 applet.fill(currentBackgroundColor.getRed(), currentBackgroundColor.getGreen(), currentBackgroundColor.getBlue(), currentBackgroundColor.getAlpha());
00727                         else
00728                                 applet.fill(currentBackgroundBrightColor.getRed(), currentBackgroundBrightColor.getGreen(), currentBackgroundBrightColor.getBlue(), currentBackgroundBrightColor.getAlpha());
00729                         
00730                         applet.rect(position.x, position.y, sequenceBoxDimension.x, sequenceBoxDimension.y);
00731 
00732                         
00733                         Vector2f tmpPos = new Vector2f(position);
00734                         tmpPos.y += SEQUENCE_BOX_PADDING;
00735                         tmpPos.x += SEQUENCE_BOX_PADDING;
00736 
00737                         
00738                         ArrayList<Float> pos = new ArrayList<Float>();
00739 
00740                         Vector2f expandedParentCorner1 = null;
00741                         Vector2f expandedParentCorner2 = null;
00742 
00743                         Action expSeq = action.getExpandedSequence();
00744 
00745 
00746                         
00747                         for (Action a : sub) {
00748                                 
00749                                 ActionDrawInformation inf = a.getDrawInfo();
00750 
00751                                 inf.drawSimpleBox(applet, tmpPos, drawOffset, maxSubsequenceHeight,a.getSubActionsCount()>0);
00752                                 if (a == expSeq) {
00753                                         expandedParentCorner1 = new Vector2f(tmpPos.x,tmpPos.y+maxSubsequenceHeight);
00754                                         expandedParentCorner2 = new Vector2f(tmpPos.x+inf.getSimpleBoxDimension().x,tmpPos.y+maxSubsequenceHeight);
00755                                 }
00756 
00757                                 tmpPos.x += inf.getSimpleBoxDimension().x + SEQUENCE_BOX_PADDING;
00758                                 pos.add(tmpPos.x);
00759                         }
00760 
00761                         
00762                         for (int i=0; i<pos.size()-1; i++) {
00763                                 
00764                                 applet.stroke(arrowBorderColor.getRed(), arrowBorderColor.getGreen(), arrowBorderColor.getBlue(), arrowBorderColor.getAlpha());
00765                                 applet.fill(arrowBackgroundColor.getRed(), arrowBackgroundColor.getGreen(), arrowBackgroundColor.getBlue(), arrowBackgroundColor.getAlpha());
00766                                 PlanVisApplet.arrow(applet,pos.get(i)-SEQUENCE_BOX_PADDING - 5,tmpPos.y+getNameBoxHeight()/2-10,20,SEQUENCE_BOX_PADDING+11);
00767                         }
00768 
00769                         
00770                         Vector2f startPos = new Vector2f(position);
00771                         startPos.y +=SEQUENCE_BOX_PADDING + maxSubsequenceHeight + EXPAND_BOX_HEIGHT;
00772 
00773                         if (expSeq != null && expandedParentCorner1 != null && expandedParentCorner2 != null) {
00774                                 
00775                                 Vector2f subDim = expSeq.getDrawInfo().sequenceBoxDimension;
00776                                 startPos.x = (expandedParentCorner2.x+expandedParentCorner1.x)/2f;
00777                                 startPos.x -= subDim.x/2f;
00778 
00779                                 startPos.x = Math.max(startPos.x, position.x+SEQUENCE_BOX_PADDING);
00780 
00781                                 startPos.x -= Math.max(0, (startPos.x +subDim.x) - (position.x+sequenceBoxDimension.x-SEQUENCE_BOX_PADDING));
00782 
00783 
00784                                 
00785                                 
00786                                 
00787                                 
00788 
00789                                 expSeq.getDrawInfo().drawSequence(applet, startPos, drawOffset, true);
00790                         }
00791                 }
00792         }
00793         
00800         public void drawExtendedBox(PApplet applet, Vector2f position, Vector2f drawOffset)
00801         {
00802                 this.drawnAsSimple = false;
00803                 recalculateDimensions(applet);
00804                 
00805                 boundingBoxExtended.x = (int)position.x;
00806                 boundingBoxExtended.y = (int)position.y;
00807                 
00808                 Vector2f extendedDim = getExtendedBoxDimension();
00809                 
00810                 
00811 
00812 
00813 
00814 
00815                 
00816                 this.position = new Vector2f(position);
00817                 applet.strokeWeight(currentStroke);
00818                 applet.stroke(hoverBorderColor.getRed(), hoverBorderColor.getGreen(), hoverBorderColor.getBlue(), hoverBorderColor.getAlpha());
00819                 position.x += boxOffsetLeft;
00820                 drawBorderAndTitle(applet, position,extendedDim);       
00821                 applet.strokeWeight(defaultStroke);     
00822                 
00823                 position.x += MAIN_BOX_PADDING;
00824                 position.y += getNameBoxHeight()+INNER_CONTENT_PADDING;
00825                 
00826                 
00827                 drawProperties(applet, position);
00828 
00829                 position.y += INNER_CONTENT_PADDING;
00830                 
00831                 
00832                 drawSequence(applet, position, new Vector2f(), false);
00833                 
00834                 position.y += sequenceBoxDimension.y;
00835                 position.x -= MAIN_BOX_PADDING;
00836                 position.x -= boxOffsetLeft;
00837                 
00838                 position.y += MAIN_BOX_PADDING*2;
00839                 
00840 
00841                 
00842 
00843         }
00844         
00850         private void setHover(boolean hover)
00851         {
00852                 if (hover)
00853                 {
00854                         currentBorderColor = hoverBorderColor;
00855                         currentBackgroundColor = hoverBackgroundColor;
00856                         currentBackgroundBrightColor = hoverBackgroundBrightColor;
00857                         currentTextColor = hoverTextColor;
00858                 } else 
00859                 {
00860                         currentBorderColor = borderColor;
00861                         currentBackgroundColor = backgroundColor;
00862                         currentBackgroundBrightColor = backgroundBrightColor;
00863                         currentTextColor = textColor;
00864                 }
00865                 isHover = hover;
00866         }
00867         
00873         private void setHoverExpand(boolean hover)
00874         {
00875                 if (hover || action.isExpanded())
00876                 {
00877                         currentExpandBorderColor = hoverArrowExpandBorderColor;
00878                         currentExpandBackgroundColor = hoverArrowExpandBackgroundColor;
00879                 } else 
00880                 {
00881                         currentExpandBorderColor = arrowExpandBorderColor;
00882                         currentExpandBackgroundColor = arrowExpandBackgroundColor;
00883                 }
00884         }
00885         
00894         private ActionDrawInformation checkHoverExtendedSequence(float x, float y, Action currAction, ActionDrawInformation found) {
00895                 
00896                 if (currAction == null)
00897                         return null;
00898                 
00899                 
00900                 
00901                 List<Action> sub = action.getSubActions();
00902                 
00903                 synchronized(sub) {
00904 
00905                         for (Action a : sub) {
00906                                 
00907                                 ActionDrawInformation inf = a.getDrawInfo();
00908 
00909                                 if (found != null)
00910                                         inf.setHover(false);
00911                                 else {
00912                                         found = inf.checkHover(x, y,found);     
00913                                 }
00914                         }
00915                         return found;
00916                 }
00917         }
00918         
00926         public ActionDrawInformation checkHover(float x, float y, ActionDrawInformation found)
00927         {
00928 
00929                 if (position == null)
00930                         return found;
00931                         
00932                 
00933                 found = checkHoverExtendedSequence(x,y,action.getExpandedSequence(), found);
00934                 
00935                 
00936                 if (!drawnAsSimple)
00937                 {
00938 
00939                         
00940                         List<Action> sub = action.getSubActions();
00941                         
00942                         synchronized(sub) {
00943 
00944                                 for (Action a : sub) {
00945                                         
00946                                         ActionDrawInformation inf = a.getDrawInfo();
00947 
00948                                         if (found != null)
00949                                                 inf.setHover(false);
00950                                         else
00951                                                 if (inf.checkHover(x, y,found)!=null)
00952                                                         found = inf;
00953                                 }
00954                         }
00955                         
00956 
00957 
00958 
00959 
00960 
00961 
00962 
00963 
00964 
00965 
00966 
00967 
00968 
00969 
00970 
00971 
00972 
00973 
00974 
00975 
00976 
00977 
00978 
00979                         
00980                         
00981                         setHover(false);
00982                         return found; 
00983                         
00984                 } else if(checkPosOverInboundConnector(x, y)!=null) {
00985                         setHover(true);
00986                         return this;            
00987                         
00988                 } else if(checkPosOverOutboundConnector(x, y)!=null) {
00989                         setHover(true);
00990                         return this;
00991                         
00992                 } else {
00993                         
00994                         Vector2f dim = getSimpleBoxDimension();
00995                         float boxX,boxY,boxW,boxH;
00996                         boxX = position.x + localPosOffset.x + globalPosOffset.x;
00997                         boxY = position.y + localPosOffset.y + globalPosOffset.y;
00998                         boxW = dim.x;
00999                         boxH = dim.y;
01000                         if (x>boxX && x<boxX+boxW && y>boxY && y<boxY+boxH)
01001                         {
01002                                 setHover(true);
01003                                 return this;
01004                         } else {
01005                                 setHover(false);
01006                                 return found;
01007                         }
01008                 }
01009                 
01010         }
01011         
01019         private ActionDrawInformation checkHoverExpand(float mouse_x, float mouse_y, boolean hasExpandButton, float sequenceBoxHeight, boolean parentExpanded) {
01020 
01021                 if (position == null)
01022                         return null;
01023                 
01024                 ActionDrawInformation found = null;
01025                         
01026                 
01027                 if (parentExpanded)     {
01028                         
01029                         List<Action> sub = action.getSubActions();
01030                         
01031                         synchronized(sub) {
01032                                 for (Action a : sub) {
01033                                         
01034                                         ActionDrawInformation inf = a.getDrawInfo();
01035 
01036                                         if (found != null)
01037                                                 inf.setHoverExpand(false);
01038                                         else {
01039                                                 ActionDrawInformation d = inf.checkHoverExpand(mouse_x, mouse_y,this.hasExpandButton,this.maxSubsequenceHeight, a.isExpanded());
01040                                                 if (d!=null)
01041                                                         found = d;
01042                                         }
01043                                 }
01044                         }
01045                 }
01046                 
01047                 if (hasExpandButton) {
01048                         
01049                         Vector2f dim = getSimpleBoxDimension();
01050                         float boxX,boxY,boxW,boxH;
01051                         boxX = position.x + localPosOffset.x + globalPosOffset.x;
01052                         boxY = position.y + localPosOffset.y + globalPosOffset.y +sequenceBoxHeight;
01053                         boxW = dim.x;
01054                         boxH = EXPAND_BOX_HEIGHT;
01055                         if (action.getSubActionsCount() > 0 && mouse_x>boxX && mouse_x<boxX+boxW && mouse_y>boxY && mouse_y<boxY+boxH)
01056                         {
01057                                 setHoverExpand(true);
01058                                 return this;
01059                         } else {
01060                                 setHoverExpand(false);
01061                                 return found;
01062                         }
01063                 }
01064                 
01065                 return found;
01066                 
01067         }
01068         
01069         
01077         public Action checkPosOverInboundConnector(float mouse_x, float mouse_y) {
01078                 
01079                 float boxX = getInboundConnectorPos().x-CONNECTOR_DIM.x/2;
01080                 float boxY = getInboundConnectorPos().y-CONNECTOR_DIM.y;
01081                 float boxW = CONNECTOR_DIM.x;
01082                 float boxH = CONNECTOR_DIM.y;
01083                 
01084                 if (mouse_x>boxX && mouse_x<boxX+boxW && 
01085                         mouse_y>boxY && mouse_y<boxY+boxH) {
01086                         return this.action;
01087                 } 
01088                 return null;
01089         }
01090         
01091         
01099         public Action checkPosOverOutboundConnector(float mouse_x, float mouse_y) {
01100                 
01101                 float boxX = getOutboundConnectorPos().x-CONNECTOR_DIM.x/2;
01102                 float boxY = getOutboundConnectorPos().y;
01103                 float boxW = CONNECTOR_DIM.x;
01104                 float boxH = CONNECTOR_DIM.y;
01105                 
01106                 if (mouse_x>boxX && mouse_x<boxX+boxW && 
01107                         mouse_y>boxY && mouse_y<boxY+boxH) {
01108                         
01109                         return this.action;
01110                 } 
01111                 return null;
01112         }
01113         
01114         
01121         public boolean updateHover(float x, float y)
01122         {
01123                 boolean found = checkHover(x,y,null)!=null;
01124                 return (checkHoverExpand(x, y, false,0,true)!=null || found);
01125         }
01126         
01133         public Action checkClick(float x, float y)
01134         {
01135                 ActionDrawInformation a = checkHover(x,y,null);
01136                 if (a==null)
01137                         return null;
01138                 else
01139                         return a.action;
01140         }
01141         
01148         public Action checkClickExpand(float x, float y)
01149         {
01150                 ActionDrawInformation a = checkHoverExpand(x, y, false,0,true);
01151                 if (a==null)
01152                         return null;
01153                 else
01154                         return a.action;
01155         }
01156         
01161         public float getTextHeight()
01162         {
01163                 return textHeight;
01164         }
01165         
01170         public boolean IsHover()
01171         {
01172                 return isHover;
01173         }
01174         
01180         public Rectangle getBoundingBox()
01181         {
01182                 if (drawnAsSimple)
01183                         return boundingBoxSimple;
01184                 else
01185                         return boundingBoxExtended;
01186         }
01187         
01192         public HighlightType getHighlight()
01193         {
01194                 return highlight;
01195         }
01196         
01201         public void setHightlight(HighlightType h)
01202         {
01203                 this.highlight = h;
01204         }
01205         
01210         public void clearHightlight()
01211         {
01212                 if (this.highlight == HighlightType.NOT_HIGHTLIGHTED)
01213                         return;
01214                 else if (this.highlight == HighlightType.THIS_HIGHLIGHTED)
01215                 {
01216                         this.highlight = HighlightType.NOT_HIGHTLIGHTED;
01217                         return;
01218                 }
01219                 
01220                 List<Action> sub = action.getSubActions();
01221                 
01222                 synchronized(sub) {
01223                         for (Action a : sub) {
01224 
01225                                 ActionDrawInformation inf = a.getDrawInfo();
01226 
01227                                 if (inf.highlight == HighlightType.CHILD_HIGHLIGHTED || inf.highlight == HighlightType.THIS_HIGHLIGHTED)
01228                                 {
01229                                         inf.clearHightlight();
01230                                         this.highlight = HighlightType.NOT_HIGHTLIGHTED;
01231                                         return;
01232                                 }
01233                         }
01234                 }
01235         }
01236         
01244         public boolean highlightSubsequence(String identifier, boolean expand)
01245         {
01246                 if (this.action.getIRI().compareTo(identifier)==0) {
01247                         setHightlight(HighlightType.THIS_HIGHLIGHTED);
01248                         notifyModified();
01249                         return true;
01250                 }
01251                 
01252                 
01253                 List<Action> sub = action.getSubActions();
01254                 
01255                 synchronized(sub) {
01256                         for (Action a : sub) {
01257 
01258                                 ActionDrawInformation inf = a.getDrawInfo();
01259 
01260                                 if (a.getIRI().compareTo(identifier)==0) {
01261                                         inf.setHightlight(HighlightType.THIS_HIGHLIGHTED);
01262                                         setHightlight(HighlightType.CHILD_HIGHLIGHTED);
01263                                         notifyModified();
01264                                         return true;
01265                                         
01266                                 } else if (inf.highlightSubsequence(identifier, expand)) {
01267                                         inf.setHightlight(HighlightType.CHILD_HIGHLIGHTED);
01268                                         setHightlight(HighlightType.CHILD_HIGHLIGHTED);
01269                                         if (expand)
01270                                                 action.setExpandedSequence(a);
01271                                         notifyModified();
01272                                         return true;
01273                                 }
01274                         }
01275                 }
01276                 return false;
01277         }
01278         
01286         public boolean highlightSubsequence(Action seq, boolean expand)
01287         {
01288                 if (this.action == seq) {
01289                         setHightlight(HighlightType.THIS_HIGHLIGHTED);
01290                         return true;
01291                 }
01292                 
01293                 
01294                 List<Action> sub = action.getSubActions();
01295                 
01296                 synchronized(sub) {
01297                         for (Action a : sub) {
01298 
01299                                 ActionDrawInformation inf = a.getDrawInfo();
01300 
01301                                 if (a == seq)
01302                                 {
01303                                         inf.setHightlight(HighlightType.THIS_HIGHLIGHTED);
01304                                         setHightlight(HighlightType.CHILD_HIGHLIGHTED);
01305                                         return true;
01306                                 } else if (inf.highlightSubsequence(seq, expand))
01307                                 {
01308                                         inf.setHightlight(HighlightType.CHILD_HIGHLIGHTED);
01309                                         setHightlight(HighlightType.CHILD_HIGHLIGHTED);
01310                                         if (expand)
01311                                                 action.setExpandedSequence(a);
01312                                         return true;
01313                                 }
01314                         }
01315                 }
01316                 return false;
01317         }
01318 
01319         
01320         
01321         public Vector2f getOutboundConnectorPos() {
01322                 
01323                 
01324                 return new Vector2f(position.x + localPosOffset.x + globalPosOffset.x + this.getSimpleBoxDimension().x/2, position.y + localPosOffset.y + globalPosOffset.y + this.getSimpleBoxDimension().y);
01325         }
01326 
01327         public Vector2f getInboundConnectorPos() {
01328                 
01329                 return new Vector2f(position.x + localPosOffset.x + globalPosOffset.x + this.getSimpleBoxDimension().x/2, position.y + localPosOffset.y + globalPosOffset.y);
01330         }
01331 }