$search
00001 package edu.tum.cs.ias.knowrob.vis.applets; 00002 00003 import java.awt.Color; 00004 import java.awt.Container; 00005 import java.awt.Cursor; 00006 import java.awt.Frame; 00007 import java.awt.event.KeyEvent; 00008 import java.awt.event.KeyListener; 00009 import java.awt.event.MouseEvent; 00010 import java.awt.event.MouseListener; 00011 import java.awt.event.MouseMotionListener; 00012 import java.util.ArrayList; 00013 import java.util.Collections; 00014 import java.util.List; 00015 import java.util.Map; 00016 import java.util.Vector; 00017 00018 import javax.vecmath.Vector2f; 00019 00020 import controlP5.ControlEvent; 00021 import controlP5.ControlP5; 00022 import controlP5.Textfield; 00023 00024 import edu.tum.cs.ias.knowrob.owl.OWLIndividual; 00025 import edu.tum.cs.ias.knowrob.owl.OWLThing; 00026 import edu.tum.cs.ias.knowrob.prolog.PrologInterface; 00027 import edu.tum.cs.ias.knowrob.vis.actions.Action; 00028 import edu.tum.cs.ias.knowrob.vis.actions.ActionDrawInformation; 00029 import edu.tum.cs.ias.knowrob.vis.actions.ActionDrawInformation.HighlightType; 00030 import edu.tum.cs.ias.knowrob.vis.actions.ActionSelectHistoryInfo; 00031 import edu.tum.cs.ias.knowrob.vis.actions.ActionTransition; 00032 import edu.tum.cs.ias.knowrob.vis.actions.ActionTransitions; 00033 import edu.tum.cs.ias.knowrob.vis.themes.GreyTheme; 00034 00035 import processing.core.PApplet; 00036 import processing.core.PFont; 00037 00043 public class PlanVisAppletFsm extends PApplet implements MouseListener, MouseMotionListener, KeyListener, IAddActionCallback { 00044 00045 private static final long serialVersionUID = 7695328948788620463L; 00046 00050 private PFont dejavuFont; 00051 00055 private Action selectedAction; 00056 00060 private Action currTask = null; 00061 00062 00066 private Action draggedAction; 00067 00072 private Action newTransitionFromAction; 00073 00074 private Vector2f newTransitionToLocation = new Vector2f(); 00075 00076 00077 00081 private static final Cursor normalCursor = new Cursor(Cursor.DEFAULT_CURSOR); 00082 00086 private static final Cursor handCursor = new Cursor(Cursor.HAND_CURSOR); 00087 00091 private static final Cursor moveCursor = new Cursor(Cursor.MOVE_CURSOR); 00092 00097 private long lastClickTime = 0; 00098 00104 private ArrayList<ActionSelectHistoryInfo> clickHistory = new ArrayList<ActionSelectHistoryInfo>(); 00105 00109 private Vector2f globalPosOffset = new Vector2f(0,0); 00113 private Vector2f draggingStart = new Vector2f(0,0); 00114 00115 private ActionTransition activeTransition; 00116 00117 00118 public ControlP5 controlP5; 00119 00120 private Textfield base_iri = null; 00121 private Textfield new_recipe_shortname = null; 00122 private Textfield new_recipe_label = null; 00123 private Textfield start_action; 00124 private Textfield end_action; 00125 00126 private boolean select_start = false; 00127 private boolean select_end = false; 00128 00129 00130 @Override 00131 public void setup() 00132 { 00133 size(1200, 600, P2D); 00134 00135 addMouseMotionListener(this); 00136 addMouseListener(this); 00137 00138 dejavuFont = createFont("DejaVu Sans",13); 00139 textFont(dejavuFont); 00140 hint(ENABLE_ACCURATE_TEXTURES); 00141 ellipseMode(RADIUS); 00142 frameRate(15); 00143 00144 initControlP5(); 00145 00146 if (this.frame != null) { 00147 this.frame.setTitle("Action plans visualisation"); 00148 this.frame.setBackground(new Color(10, 10, 10)); 00149 } 00150 } 00151 00152 @Override 00153 public void draw() { 00154 00155 if(this.frame==null) 00156 return; 00157 00158 background(40); 00159 00160 textFont(dejavuFont); 00161 textMode(SCREEN); 00162 00163 if(currTask != null) { 00164 drawActions(); 00165 00166 drawTransitions(this); 00167 00168 drawActions(); 00169 00170 drawHistory(); 00171 00172 if(this.newTransitionFromAction!=null) { 00173 arrowFromTo(this, newTransitionFromAction.getDrawInfo().getOutboundConnectorPos(), newTransitionToLocation, 5, -1); 00174 } 00175 } 00176 controlP5.draw(); 00177 } 00178 00179 00185 public void loadPrologPlan(String identifier) { 00186 00187 Action a = Action.getAction(identifier); 00188 a.readFromProlog(); 00189 a.getDrawInfo().recalculateDimensions(this); 00190 00191 if (a!= null) 00192 setTask(a); 00193 00194 // set base URL text field 00195 base_iri.setText(a.getIRIPrefix()+"#"); 00196 00197 Vector<String> start = a.getHasValue().get("http://ias.cs.tum.edu/kb/knowrob.owl#taskStartState"); 00198 if(start!=null && !start.isEmpty()) { 00199 start_action.setText(OWLThing.getShortNameOfIRI(start.firstElement())); 00200 } 00201 00202 Vector<String> end = a.getHasValue().get("http://ias.cs.tum.edu/kb/knowrob.owl#taskEndState"); 00203 if(end!=null && !end.isEmpty()) { 00204 end_action.setText(OWLThing.getShortNameOfIRI(end.firstElement())); 00205 } 00206 } 00207 00208 00214 public void setTask(Action action) 00215 { 00216 currTask = action; 00217 selectedAction = null; 00218 clickHistory.clear(); 00219 clickHistory.add(new ActionSelectHistoryInfo(currTask)); 00220 updateHistoryPosition(); 00221 00222 } 00223 00231 public static void arrowFromTo(PApplet applet, Vector2f from, Vector2f to, float lineWidth, float blockLength) 00232 { 00233 00234 Vector<Vector2f> vertices = getArrowVertices(applet, from, to, lineWidth, blockLength); 00235 00236 applet.beginShape(); 00237 00238 for(Vector2f p : vertices) 00239 applet.vertex(p.x,p.y); 00240 00241 applet.endShape(CLOSE); 00242 00243 } 00244 00245 public static Vector<Vector2f> getArrowVertices(PApplet applet, Vector2f from, Vector2f to, float lineWidth, float blockLength) { 00246 00247 Vector<Vector2f> vertices = new Vector<Vector2f>(); 00248 00249 Vector2f norm = new Vector2f(to.x - from.x, to.y-from.y); 00250 float len = norm.length(); 00251 norm.normalize(); 00252 Vector2f rot90 = new Vector2f(norm.x*(float)Math.cos(Math.PI/2f)-norm.y*(float)Math.sin(Math.PI/2f),norm.x*(float)Math.sin(Math.PI/2f)+norm.y*(float)Math.cos(Math.PI/2f)); 00253 Vector2f distLeft = new Vector2f(rot90); 00254 distLeft.scale(-lineWidth); 00255 Vector2f distRight = new Vector2f(rot90); 00256 distRight.scale(lineWidth); 00257 00258 //following points are described as if the arrow is pointing from left to right horizontally 00259 00260 //upper left 00261 Vector2f p1 = new Vector2f(distLeft); 00262 p1.add(from); 00263 //bottom left 00264 Vector2f p7 = new Vector2f(distRight); 00265 p7.add(from); 00266 00267 if (blockLength < 0) 00268 { 00269 blockLength = Math.max(len*0.5f, len - 3*lineWidth); 00270 } 00271 Vector2f transl = new Vector2f(norm); 00272 transl.scale(blockLength); 00273 00274 //middle up on line 00275 Vector2f p2 = new Vector2f(distLeft); 00276 //upper tip 00277 Vector2f p3 = new Vector2f(distLeft); 00278 p3.scale(2); 00279 p2.add(transl); 00280 p2.add(from); 00281 p3.add(transl); 00282 p3.add(from); 00283 00284 //middle bottom on line 00285 Vector2f p6 = new Vector2f(distRight); 00286 //bottom tip 00287 Vector2f p5 = new Vector2f(distRight); 00288 p5.scale(2); 00289 p6.add(transl); 00290 p6.add(from); 00291 p5.add(transl); 00292 p5.add(from); 00293 00294 vertices.add(p1); vertices.add(p2); vertices.add(p3); vertices.add(to); 00295 vertices.add(p5); vertices.add(p6); vertices.add(p7); 00296 00297 return vertices; 00298 } 00299 00300 00309 public static void arrow(PApplet applet, float x, float y, float width, float height) 00310 { 00311 applet.beginShape(); 00312 00313 float indentY = 2f/7f*height; 00314 float indentX = 4f/9f*width; 00315 00316 applet.vertex(x,y+indentY); 00317 applet.vertex(x+indentX,y+indentY); 00318 applet.vertex(x+indentX,y); 00319 applet.vertex(x+width,y+height/2f); 00320 applet.vertex(x+indentX,y+height); 00321 applet.vertex(x+indentX,y+height-indentY); 00322 applet.vertex(x,y+height-indentY); 00323 00324 applet.endShape(CLOSE); 00325 } 00326 00331 private void updateHistoryPosition() 00332 { 00333 float fullWidth = 0; 00334 for (int i= clickHistory.size()-1; i>=0; i--) 00335 { 00336 fullWidth += clickHistory.get(i).getDimension().x; 00337 } 00338 if (fullWidth+50 > this.getSize().width) 00339 { 00340 //There is not enough space for all history, so begin from right to left 00341 float prevX = this.getSize().width-50; 00342 for (int i= clickHistory.size()-1; i>=0; i--) 00343 { 00344 float newX = prevX - clickHistory.get(i).getDimension().x; 00345 prevX = newX; 00346 clickHistory.get(i).setPosition(newX, 0, i==clickHistory.size()-1); 00347 } 00348 } else { 00349 //Enough space, begin from left 00350 float currX = 0; 00351 for (int i= 0; i<clickHistory.size(); i++) 00352 { 00353 clickHistory.get(i).setPosition(currX, 0, i==clickHistory.size()-1); 00354 currX += clickHistory.get(i).getDimension().x; 00355 } 00356 } 00357 } 00358 00362 private void drawHistory() 00363 { 00364 if(clickHistory.size()>=1) { 00365 for (int i= clickHistory.size()-1; i>=0; i--) 00366 { 00367 clickHistory.get(i).Draw(this); 00368 } 00369 } 00370 } 00371 00375 public void drawActionsTreeLayout() { 00376 00377 Vector2f currentPosition = new Vector2f(50+globalPosOffset.x,80+globalPosOffset.y); 00378 Map<Integer, Vector<Action>> levels = currTask.getTransitionsRecursive().getTreeLevels(); 00379 Map<Integer, Float> levelWidths = currTask.getTransitionsRecursive().getLevelWidths(); 00380 00381 if(levels.size()>0) { 00382 00383 // compute horizontal center as half of the maximum level width 00384 float center_x = currentPosition.x + Collections.max(levelWidths.values())/2; 00385 00386 for(int level : levels.keySet()) { 00387 00388 // left corner of the first action is maxWidth - curWidth 00389 currentPosition.x = center_x - levelWidths.get(level)/2; 00390 00391 00392 float maxHeight = 0.0f; 00393 for(Action a : levels.get(level)) { 00394 00395 if(a.isExpanded()) { 00396 a.getDrawInfo().drawSimpleBox(this, currentPosition, globalPosOffset, 10, true); 00397 } else { 00398 a.getDrawInfo().drawSimpleBox(this, currentPosition, globalPosOffset, 10, false); 00399 } 00400 00401 // increase x-position after each action on this level 00402 currentPosition.x += a.getDrawInfo().getSimpleBoxDimension().x + ActionDrawInformation.SEQUENCE_BOX_PADDING; 00403 00404 // remember max. action height per level to know where to start the next one 00405 maxHeight = Math.max(maxHeight, a.getDrawInfo().getSimpleBoxDimension().y); 00406 } 00407 00408 // increase y-coordinate for the next level 00409 currentPosition.y += maxHeight + 2*ActionDrawInformation.MAIN_BOX_PADDING; 00410 } 00411 } 00412 00413 00414 // draw all actions that are currently not connected in the upper left corner 00415 currentPosition = new Vector2f(50+globalPosOffset.x,80+globalPosOffset.y); 00416 for(Action a : currTask.getSubActions()) { 00417 00418 if( currTask.getTransitionsRecursive().getTransitionsFrom(a).isEmpty() && 00419 currTask.getTransitionsRecursive().getTransitionsTo(a).isEmpty()) { 00420 00421 if(a.isExpanded()) { 00422 a.getDrawInfo().drawSimpleBox(this, currentPosition, globalPosOffset, 10, true); 00423 } else { 00424 a.getDrawInfo().drawSimpleBox(this, currentPosition, globalPosOffset, 10, false); 00425 } 00426 00427 } 00428 } 00429 } 00430 00431 00432 // draw actions wherever they have been drawn before (don't re-arrange layout) 00433 private void drawActions() { 00434 00435 List<Action> subactions = currTask.getSubActions(); 00436 if(subactions!=null) { 00437 synchronized(subactions) { 00438 for(Action a : subactions) { 00439 00440 if(a.isExpanded()) { 00441 a.getDrawInfo().drawSimpleBox(this, a.getDrawInfo().position, globalPosOffset, 10, true); 00442 } else { 00443 a.getDrawInfo().drawSimpleBox(this, a.getDrawInfo().position, globalPosOffset, 10, false); 00444 } 00445 } 00446 } 00447 } 00448 } 00449 00450 00451 public synchronized void drawTransitions(PApplet app) { 00452 00453 ActionTransitions trans = currTask.getTransitionsRecursive(); 00454 if(trans!=null) { 00455 //synchronized(trans) { 00456 // draw transition arrows 00457 for(ActionTransition t : trans) { 00458 t.drawConnection(app); 00459 } 00460 //} 00461 } 00462 } 00463 00464 00465 private void initControlP5() { 00466 00467 // wait till window has been created 00468 while(findFrame()==null) { 00469 try { Thread.sleep(50); 00470 } catch (InterruptedException e) { 00471 e.printStackTrace(); } 00472 } 00473 this.frame = findFrame(); 00474 00475 controlP5 = new ControlP5(this); 00476 GreyTheme.applyStyle(controlP5); 00477 00478 00479 GreyTheme.applyStyle(controlP5.addGroup("recipe properties", 900, 20, 230).setBackgroundHeight(200)); 00480 00481 base_iri = GreyTheme.applyStyle(controlP5.addTextfield("base iri", 10, 10, 210, 20).setGroup("recipe properties")); 00482 base_iri.setText("http://www.roboearth.org/kb/roboearth.owl#"); 00483 00484 start_action = GreyTheme.applyStyle(controlP5.addTextfield("start action", 10, 55, 160, 20).setGroup("recipe properties")); 00485 GreyTheme.applyStyle(controlP5.addButton("select start", 1f, 180, 55, 40, 20).setGroup("recipe properties")).getCaptionLabel().set("select"); 00486 00487 end_action = GreyTheme.applyStyle(controlP5.addTextfield("end action", 10, 100, 160, 20).setGroup("recipe properties")); 00488 GreyTheme.applyStyle(controlP5.addButton("select end", 2f, 180, 100, 40, 20).setGroup("recipe properties")).getCaptionLabel().set("select"); 00489 00490 GreyTheme.applyStyle(controlP5.addButton("add new action to recipe", 3f, 10, 160, 125, 20).setGroup("recipe properties")); 00491 00492 00493 00494 00495 GreyTheme.applyStyle(controlP5.addGroup("create new recipe", 900, 250, 230).setBackgroundHeight(120)); 00496 00497 new_recipe_shortname = GreyTheme.applyStyle(controlP5.addTextfield("shortname", 10, 10, 210, 20).setGroup("create new recipe")); 00498 new_recipe_shortname.setText("UniqueIdentifierForRecipe"); 00499 00500 new_recipe_label = GreyTheme.applyStyle(controlP5.addTextfield("label", 10, 55, 210, 20).setGroup("create new recipe")); 00501 new_recipe_label.setText("natural-language label"); 00502 00503 GreyTheme.applyStyle(controlP5.addButton("create", 46f, 185, 90, 35, 20).setGroup("create new recipe")); 00504 00505 00506 } 00507 00508 00509 00510 @Override 00511 public void mouseMoved(MouseEvent e) { 00512 00513 if(newTransitionFromAction!=null) { 00514 newTransitionToLocation.x = e.getX(); 00515 newTransitionToLocation.y = e.getY(); 00516 redraw(); 00517 } 00518 00519 if (getHistoryHover(e.getX(), e.getY())>=0) { 00520 setCursor(handCursor); 00521 return; 00522 } 00523 00524 if(currTask!=null) { 00525 for(Action a : currTask.getSubActions()) { 00526 00527 if (a.getDrawInfo().updateHover(e.getX(), e.getY())) 00528 setCursor(handCursor); 00529 else 00530 setCursor(normalCursor); 00531 } 00532 } 00533 00534 if(controlP5!=null) 00535 controlP5.controlWindow.mouseEvent(e); 00536 00537 if (selectedAction==null) { 00538 setCursor(normalCursor); 00539 return; 00540 } 00541 } 00542 00543 @Override 00544 public void mouseDragged(MouseEvent e) { 00545 00546 00547 if (draggingStart != null) { 00548 00549 // check if we clicked on an action -> move only that action box 00550 if(draggedAction!=null) { 00551 00552 draggedAction.getDrawInfo().localPosOffset.x += e.getX() - draggingStart.x; 00553 draggedAction.getDrawInfo().localPosOffset.y += e.getY() - draggingStart.y; 00554 00555 draggingStart.x = e.getX(); 00556 draggingStart.y = e.getY(); 00557 return; 00558 } 00559 00560 // no action wanted the drag event, so let's move the whole canvas: 00561 globalPosOffset.x += e.getX() - draggingStart.x; 00562 globalPosOffset.y += e.getY() - draggingStart.y; 00563 00564 draggingStart.x = e.getX(); 00565 draggingStart.y = e.getY(); 00566 } 00567 00568 00569 // only send left-button events to contolP5 00570 if(controlP5!=null && e.getButton() == MouseEvent.BUTTON1) 00571 controlP5.controlWindow.mouseEvent(e); 00572 } 00573 00574 @Override 00575 public void mousePressed(MouseEvent e) { 00576 00577 if(currTask!=null) { 00578 00579 if (e.getButton() == MouseEvent.BUTTON1) { 00580 00581 // check if we clicked on an action -> move only that action box 00582 for(Action a : currTask.getSubActions()) { 00583 if(a.getDrawInfo().checkClick(e.getX(), e.getY())!=null) { 00584 draggedAction = a; 00585 00586 draggingStart = new Vector2f(e.getX(),e.getY()); 00587 setCursor(moveCursor); 00588 } 00589 } 00590 00591 // only send left-button events to contolP5 00592 if(controlP5!=null && e.getButton() == MouseEvent.BUTTON1) 00593 controlP5.controlWindow.mouseEvent(e); 00594 00595 } else if (e.getButton() == MouseEvent.BUTTON3) { 00596 00597 draggingStart = new Vector2f(e.getX(),e.getY()); 00598 setCursor(moveCursor); 00599 00600 } else { 00601 setCursor(normalCursor); 00602 } 00603 } 00604 00605 // only send left-button events to contolP5 00606 if(controlP5!=null && e.getButton() == MouseEvent.BUTTON1) 00607 controlP5.controlWindow.mouseEvent(e); 00608 } 00609 00610 @Override 00611 public void mouseReleased(MouseEvent e) { 00612 setCursor(normalCursor); 00613 draggingStart = null; 00614 draggedAction = null; 00615 00616 00617 // only send left-button events to contolP5 00618 if(controlP5!=null && e.getButton() == MouseEvent.BUTTON1) 00619 controlP5.controlWindow.mouseEvent(e); 00620 } 00621 00622 00623 00624 @Override 00625 public void mouseClicked(MouseEvent e) { 00626 00627 00628 long diff = System.currentTimeMillis()-lastClickTime; 00629 lastClickTime = System.currentTimeMillis(); 00630 00631 if (diff < 150) { // double-fired event 00632 return; 00633 } 00634 00635 00636 // only send left-button events to contolP5 00637 if(controlP5!=null && e.getButton() == MouseEvent.BUTTON1) 00638 controlP5.controlWindow.mouseEvent(e); 00639 00640 if(currTask==null) {return;} 00641 00642 if (e.getButton() == MouseEvent.BUTTON1) { 00643 00644 00645 // Check if clicked on outbound connector 00646 for(Action a : currTask.getSubActions()) { 00647 00648 Action clicked_on = a.getDrawInfo().checkPosOverOutboundConnector(e.getX(), e.getY()); 00649 if (clicked_on!= null) { 00650 00651 // clicked nowhere special, reset highlight 00652 clearHighlight(); 00653 selectedAction=null; 00654 if(activeTransition!=null) 00655 activeTransition.setActive(false); 00656 activeTransition = null; 00657 00658 newTransitionFromAction = clicked_on; 00659 newTransitionToLocation.x = e.getX(); 00660 newTransitionToLocation.y = e.getY(); 00661 return; 00662 } 00663 } 00664 00665 00666 00667 // Check if clicked on action in different modes 00668 for(Action a : currTask.getSubActions()) { 00669 if (a.getDrawInfo().checkHover(e.getX(), e.getY(), null)!= null) { 00670 00671 // Check if in connection mode 00672 if(newTransitionFromAction!=null) { 00673 00674 OWLIndividual t_ind = OWLIndividual.getOWLIndividualOfClass("http://ias.cs.tum.edu/kb/knowrob.owl#Transition"); 00675 newTransitionFromAction.addTransition(ActionTransition.getActionTransition(t_ind.getIRI(), newTransitionFromAction, a, "OK")); 00676 redraw(); 00677 00678 // clicked nowhere special, reset highlight 00679 clearHighlight(); 00680 selectedAction=null; 00681 if(activeTransition!=null) 00682 activeTransition.setActive(false); 00683 activeTransition = null; 00684 00685 newTransitionFromAction = null; 00686 newTransitionToLocation = new Vector2f(); 00687 return; 00688 00689 } else if(select_start) { 00690 00691 start_action.setText(a.getShortName()); 00692 00693 if(currTask.getHasValue().containsKey("http://ias.cs.tum.edu/kb/knowrob.owl#taskStartState")) 00694 currTask.getHasValue().get("http://ias.cs.tum.edu/kb/knowrob.owl#taskStartState").clear(); 00695 00696 currTask.addHasValue("http://ias.cs.tum.edu/kb/knowrob.owl#taskStartState", a.getIRI()); 00697 select_start = false; 00698 00699 } else if(select_end) { 00700 00701 end_action.setText(a.getShortName()); 00702 00703 if(currTask.getHasValue().containsKey("http://ias.cs.tum.edu/kb/knowrob.owl#taskEndState")) 00704 currTask.getHasValue().get("http://ias.cs.tum.edu/kb/knowrob.owl#taskEndState").clear(); 00705 00706 currTask.addHasValue("http://ias.cs.tum.edu/kb/knowrob.owl#taskEndState", a.getIRI()); 00707 select_end = false; 00708 } 00709 } 00710 } 00711 00712 00713 // reset connection mode if clicked elsewhere 00714 newTransitionFromAction = null; 00715 newTransitionToLocation = new Vector2f(); 00716 00717 00718 // check if (double)clicked on action 00719 for(Action a : currTask.getSubActions()) { 00720 00721 Action clicked_on = a.getDrawInfo().checkClick(e.getX(), e.getY()); 00722 00723 if (clicked_on!= null) { 00724 00725 clearHighlight(); 00726 if(activeTransition!=null) 00727 activeTransition.setActive(false); 00728 activeTransition = null; 00729 00730 // edit action if double-clicked 00731 if(e.getClickCount()==2) { 00732 00733 // open action editor 00734 ActionEditorWindow f = new ActionEditorWindow(); 00735 f.setAddActionCallback(this); 00736 f.setBaseIRI(base_iri.getText()); 00737 00738 while(!f.applet.isInitialized()) { 00739 try {Thread.sleep(10); 00740 } catch (InterruptedException e1) {e1.printStackTrace(); } 00741 } 00742 00743 // init action editor 00744 f.applet.setIdentifier(a.getIRI()); 00745 f.applet.setEditing(true); 00746 f.applet.setActionClass(a.getSuperClasses().firstElement().getIRI()); 00747 f.applet.setActionProperties(a.getProperties()); 00748 00749 // update click time if init took longer 00750 lastClickTime = System.currentTimeMillis(); 00751 00752 return; 00753 00754 } else { 00755 00756 // activate action after single click 00757 selectedAction = clicked_on; 00758 highlightAction(selectedAction, false); 00759 00760 return; 00761 } 00762 } 00763 } 00764 00765 // activate transition arrow after click 00766 ActionTransitions trans = currTask.getTransitionsRecursive(); 00767 synchronized(trans) { 00768 for(ActionTransition t : trans) { 00769 00770 boolean inside = t.checkPosInArrow(new Vector2f(e.getX(), e.getY()), this); 00771 00772 if (inside) { 00773 00774 if(e.getClickCount()==2) { 00775 00776 00777 //debug 00778 System.out.println("double click on transition"); 00779 new TransitionPropertiesEditor(this, t); 00780 00781 } else { 00782 00783 // deactivate transition with second click 00784 if(t.isActive()) { 00785 t.setActive(false); 00786 activeTransition = null; 00787 } 00788 00789 // reset action selection 00790 clearHighlight(); 00791 selectedAction=null; 00792 00793 // reset previously active transition, set to t 00794 t.setActive(true); 00795 00796 if(activeTransition!=null) 00797 activeTransition.setActive(false); 00798 00799 activeTransition = t; 00800 return; 00801 } 00802 } 00803 } 00804 } 00805 00806 // clicked nowhere special, reset highlight 00807 clearHighlight(); 00808 selectedAction=null; 00809 00810 if(activeTransition!=null) 00811 activeTransition.setActive(false); 00812 00813 activeTransition = null; 00814 } 00815 00816 00817 00818 // TODO: adapt to multi-action case and reactivate 00819 // //Check if clicked on history element 00820 // int idx = getHistoryHover(e.getX(), e.getY()); 00821 // if (idx >= 0) { 00822 // selectedAction = clickHistory.get(idx).getAction(); 00823 // for (int i=clickHistory.size()-1; i>idx; i--) 00824 // { 00825 // clickHistory.remove(i); 00826 // } 00827 // updateHistoryPosition(); 00828 // return; 00829 // } 00830 // 00831 00832 // TODO: adapt to multi-action case and reactivate 00833 // //Check if clicked on an expand button 00834 // for(Action a : actions) { 00835 // 00836 // Action clicked_on = a.getDrawInfo().checkClickExpand(e.getX(), e.getY()); 00837 // if (clicked_on!= null) { 00838 // 00839 // clicked_on.toggleExpand(); 00840 // selectedAction.getDrawInfo().notifyModified(); 00841 // return; 00842 // } 00843 // } 00844 } 00845 00846 00847 @Override 00848 public void mouseEntered(MouseEvent e) { 00849 00850 if(controlP5!=null) 00851 controlP5.controlWindow.mouseEvent(e); 00852 } 00853 00854 @Override 00855 public void mouseExited(MouseEvent e) { 00856 00857 if(controlP5!=null) 00858 controlP5.controlWindow.mouseEvent(e); 00859 } 00860 00861 00862 public void keyPressed(KeyEvent e) { 00863 00864 00865 if(e.getKeyCode() == KeyEvent.VK_DELETE) { 00866 00867 if(currTask!=null) { 00868 ActionTransitions trans = currTask.getTransitionsRecursive(); 00869 synchronized(trans) { 00870 00871 if(activeTransition!=null) { 00872 activeTransition.getFrom().removeTransition(activeTransition); 00873 this.activeTransition = null; 00874 currTask.setSaveToProlog(true); 00875 } 00876 00877 if(selectedAction!=null) { 00878 00879 currTask.removeSubAction(selectedAction); 00880 00881 for(ActionTransition t : trans) { 00882 if(t.getFrom().equals(selectedAction) || 00883 t.getTo().equals(selectedAction)) { 00884 00885 t.getFrom().removeTransition(t); 00886 } 00887 } 00888 00889 this.selectedAction = null; 00890 currTask.setSaveToProlog(true); 00891 } 00892 } 00893 } 00894 } 00895 00896 if(controlP5!=null) 00897 controlP5.keyHandler.keyEvent(e, controlP5.controlWindow, true); 00898 00899 } 00900 00901 00907 public void controlEvent(ControlEvent ev) { 00908 00909 if(ev.isController()) { 00910 00911 // open action creation dialog 00912 if(ev.getController().getName().equals("add new action to recipe")) { 00913 00914 ActionEditorWindow f = new ActionEditorWindow(); 00915 f.setAddActionCallback(this); 00916 f.setBaseIRI(base_iri.getText()); 00917 00918 00919 } else if(ev.getController().getName().equals("create")) { 00920 00921 // create new recipe 00922 Action new_action = Action.getAction(base_iri.getText() + new_recipe_shortname.getText(), 00923 new_recipe_label.getText()); 00924 new_action.addSuperClass(Action.getOWLClass("http://ias.cs.tum.edu/kb/knowrob.owl#PurposefulAction")); 00925 new_action.getDrawInfo().recalculateDimensions(this); 00926 this.setTask(new_action); 00927 00928 00929 } else if(ev.getController().getName().equals("select start")) { 00930 select_start = true; 00931 } else if(ev.getController().getName().equals("select end")) { 00932 select_end = true; 00933 } 00934 } 00935 } 00936 00937 00941 public void syncWithProlog() { 00942 currTask.setSaveToProlog(true); 00943 this.currTask.writeToProlog(); 00944 } 00945 00946 00947 00955 private int getHistoryHover(float x, float y) 00956 { 00957 int idx = -1; 00958 for (int i= 0; i<clickHistory.size()-1; i++) 00959 { 00960 if (idx >= 0) 00961 { 00962 clickHistory.get(i).setHover(false); 00963 } else { 00964 if (clickHistory.get(i).checkHover(x, y)) 00965 { 00966 idx = i; 00967 } 00968 } 00969 } 00970 return idx; 00971 } 00972 00979 public boolean highlightAction(Action a, boolean expand) { 00980 00981 if (currTask == null) 00982 return false; 00983 00984 return highlightAction(a.getIRI(), expand); 00985 } 00986 00993 public boolean highlightAction(String identifier, boolean expand) { 00994 00995 if (currTask == null) 00996 return false; 00997 00998 // find action with this identifier 00999 for(Action a : currTask.getSubActionsRecursive()) { 01000 a.getDrawInfo().clearHightlight(); 01001 if(a.getIRI().equals(identifier)) { 01002 clearHighlight(); 01003 a.getDrawInfo().setHightlight(HighlightType.THIS_HIGHLIGHTED); 01004 selectedAction=a; 01005 return true; 01006 } 01007 } 01008 return false; 01009 // selectedAction.getDrawInfo().clearHightlight(); 01010 // return selectedAction.getDrawInfo().highlightSubsequence(identifier,expand); 01011 } 01012 01016 public void clearHighlight() 01017 { 01018 if (currTask == null) 01019 return; 01020 01021 for(Action a : currTask.getSubActionsRecursive()) { 01022 a.getDrawInfo().clearHightlight(); 01023 } 01024 } 01025 01026 01027 public void addAction(Action a) { 01028 01029 a.getDrawInfo().position = new Vector2f(50+globalPosOffset.x,80+globalPosOffset.y); 01030 currTask.addSubAction(a); 01031 01032 } 01033 01034 01035 public Frame findFrame() { 01036 01037 Container f = this.getParent(); 01038 while (!(f instanceof Frame) && f!=null) 01039 f = f.getParent(); 01040 return (Frame) f; 01041 } 01042 01043 public Action getCurrTask() { 01044 return currTask; 01045 } 01046 01047 01048 01054 public class ActionEditorWindow extends Frame { 01055 01056 private static final long serialVersionUID = 543157068719461737L; 01057 public ActionPropertiesEditor applet; 01058 01059 public ActionEditorWindow() { 01060 PrologInterface.initJPLProlog("ias_knowledge_base"); 01061 01062 setBounds(100,100,500,500); 01063 applet = new ActionPropertiesEditor(); 01064 applet.frame = this; 01065 add(applet); 01066 applet.init(); 01067 this.setVisible(true); 01068 } 01069 01070 public void setAddActionCallback(IAddActionCallback cb) { 01071 applet.setAddActionCallback(cb); 01072 } 01073 01074 public void setBaseIRI(String base_iri) { 01075 applet.setBaseIRI(base_iri); 01076 } 01077 } 01078 01079 }