00001 package edu.tum.cs.ias.knowrob.vis.applets;
00002
00003 import java.awt.Color;
00004 import java.awt.Cursor;
00005 import java.awt.event.MouseEvent;
00006 import java.awt.event.MouseListener;
00007 import java.awt.event.MouseMotionListener;
00008 import java.awt.event.MouseWheelEvent;
00009 import java.awt.event.MouseWheelListener;
00010 import java.util.ArrayList;
00011 import java.util.HashMap;
00012 import java.util.HashSet;
00013 import java.util.Iterator;
00014 import java.util.Vector;
00015
00016 import javax.vecmath.Vector2f;
00017
00018 import edu.tum.cs.ias.knowrob.owl.OWLThing;
00019 import edu.tum.cs.ias.knowrob.prolog.PrologInterface;
00020 import edu.tum.cs.ias.knowrob.vis.actions.Action;
00021 import edu.tum.cs.ias.knowrob.vis.actions.ActionSelectHistoryInfo;
00022
00023 import processing.core.PApplet;
00024 import processing.core.PFont;
00025
00031 public class PlanVisApplet extends PApplet implements MouseListener, MouseMotionListener,MouseWheelListener {
00032
00033 private static final long serialVersionUID = 7695328948788620463L;
00034
00038 private PFont dejavuFont;
00039
00043 private Action currAction;
00044
00048 private static final Cursor normalCursor = new Cursor(Cursor.DEFAULT_CURSOR);
00049
00053 private static final Cursor handCursor = new Cursor(Cursor.HAND_CURSOR);
00054
00058 private static final Cursor moveCursor = new Cursor(Cursor.MOVE_CURSOR);
00059
00064 private long lastClickTime = 0;
00065
00071 private ArrayList<ActionSelectHistoryInfo> clickHistory = new ArrayList<ActionSelectHistoryInfo>();
00072
00076 private Vector2f drawOffset = new Vector2f(0,0);
00080 private Vector2f draggingStart = new Vector2f(0,0);
00081
00085 public PlanVisApplet()
00086 {
00087 this.redraw();
00088 }
00089
00090 @Override
00091 public void setup()
00092 {
00093 size(1600, 600, P2D);
00094 if (this.frame != null)
00095 {
00096 this.frame.setTitle("Action plans visualisation");
00097 this.frame.setBackground(new Color(10, 10, 10));
00098 }
00099
00100 addMouseMotionListener(this);
00101 addMouseListener(this);
00102
00103 dejavuFont = createFont("DejaVu Sans",13);
00104 textFont(dejavuFont);
00105 hint(ENABLE_ACCURATE_TEXTURES);
00106 ellipseMode(RADIUS);
00107 frameRate(20);
00108 }
00109
00110 @Override
00111 public void draw() {
00112
00113 background(40);
00114
00115 textFont(dejavuFont);
00116 textMode(SCREEN);
00117
00118
00119 drawCurrAction();
00120 drawHistory();
00121
00122
00123 }
00124
00130 private Action loadPrologPlanRecursive(String iri)
00131 {
00132
00133
00134 String label = "";
00135 try
00136 {
00137 HashMap<String, Vector<String>> qLabel = PrologInterface.executeQuery("rdf_has('"+iri+"',rdfs:label,L),util:strip_literal_type(L,Label)");
00138
00139 label = qLabel.get("Label").get(0);
00140 if (label.startsWith("'") && label.endsWith("'"))
00141 {
00142 label = label.substring(1,label.length()-1);
00143 }
00144 } catch (Exception e)
00145 {
00146 if (iri.indexOf('#') >=0)
00147 {
00148 label = iri.substring(iri.lastIndexOf('#')+1);
00149 } else {
00150 label = iri;
00151 }
00152 }
00153
00154 Action ret = Action.getAction(iri, label);
00155
00156
00157 try
00158 {
00159 HashMap<String, Vector<String>> qProp = PrologInterface.executeQuery("class_properties('"+iri+"', Key, V), util:strip_literal_type(V,Val)");
00160
00161 if(qProp != null) {
00162 Vector<String> key = qProp.get("Key");
00163 Vector<String> val = qProp.get("Val");
00164
00165
00166 HashSet<String> alreadyAdded = new HashSet<String>();
00167 if(key != null && val != null)
00168 for(int i=0;i<key.size() && i<val.size();i++) {
00169 if (alreadyAdded.contains(key.get(i)+val.get(i)))
00170 continue;
00171 alreadyAdded.add(key.get(i)+val.get(i));
00172 String k = OWLThing.getShortNameOfIRI(key.get(i));
00173 String v = OWLThing.getShortNameOfIRI(OWLThing.removeSingleQuotes(val.get(i)));
00174
00175 if (k.compareToIgnoreCase("subAction") != 0)
00176 ret.addHasValue(k, v);
00177 }
00178 }
00179 } catch (Exception e)
00180 {
00181 e.printStackTrace();
00182 }
00183
00184
00185 try {
00186 HashMap<String, Vector<String>> qSub = PrologInterface.executeQuery("plan_subevents('"+iri+"',List)");
00187
00188 if(qSub!=null) {
00189
00190 Vector<String> list = qSub.get("List");
00191
00192
00193 HashSet<String> alreadyAdded = new HashSet<String>();
00194
00195 if(list != null) {
00196 for (Iterator<String> i = list.iterator(); i.hasNext();)
00197 {
00198 String o = i.next();
00199
00200 for (String sArr[] : PrologInterface.dottedPairsToArrayList(o))
00201 {
00202 for (String s : sArr)
00203 {
00204 if (alreadyAdded.contains(s))
00205 continue;
00206 alreadyAdded.add(s);
00207 ret.addSubAction(loadPrologPlanRecursive(PrologInterface.removeSingleQuotes(s)));
00208 }
00209 }
00210 }
00211 }
00212 }
00213 } catch (Exception e)
00214 {
00215 e.printStackTrace();
00216 }
00217
00218 return ret;
00219 }
00220
00225 public void loadPrologPlan(String identifier)
00226 {
00227 Action a = loadPrologPlanRecursive(identifier);
00228 if (a!= null)
00229 setMainAction(a);
00230 }
00231
00232
00238 public void setMainAction(Action action)
00239 {
00240 currAction = action;
00241 clickHistory.add(new ActionSelectHistoryInfo(currAction));
00242 updateHistoryPosition();
00243 this.redraw();
00244 }
00245
00253 public static void arrowFromTo(PApplet applet, Vector2f from, Vector2f to, float lineWidth, float blockLength)
00254 {
00255 Vector2f norm = new Vector2f(to.x - from.x, to.y-from.y);
00256 float len = norm.length();
00257 norm.normalize();
00258 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));
00259 Vector2f distLeft = new Vector2f(rot90);
00260 distLeft.scale(-lineWidth);
00261 Vector2f distRight = new Vector2f(rot90);
00262 distRight.scale(lineWidth);
00263
00264
00265
00266
00267 Vector2f p1 = new Vector2f(distLeft);
00268 p1.add(from);
00269
00270 Vector2f p7 = new Vector2f(distRight);
00271 p7.add(from);
00272
00273 if (blockLength < 0)
00274 {
00275 blockLength = Math.max(len*0.5f, len - 3*lineWidth);
00276 }
00277 Vector2f transl = new Vector2f(norm);
00278 transl.scale(blockLength);
00279
00280
00281 Vector2f p2 = new Vector2f(distLeft);
00282
00283 Vector2f p3 = new Vector2f(distLeft);
00284 p3.scale(2);
00285 p2.add(transl);
00286 p2.add(from);
00287 p3.add(transl);
00288 p3.add(from);
00289
00290
00291 Vector2f p6 = new Vector2f(distRight);
00292
00293 Vector2f p5 = new Vector2f(distRight);
00294 p5.scale(2);
00295 p6.add(transl);
00296 p6.add(from);
00297 p5.add(transl);
00298 p5.add(from);
00299
00300
00301 applet.beginShape();
00302
00303 applet.vertex(p1.x,p1.y);
00304 applet.vertex(p2.x,p2.y);
00305 applet.vertex(p3.x,p3.y);
00306 applet.vertex(to.x,to.y);
00307 applet.vertex(p5.x,p5.y);
00308 applet.vertex(p6.x,p6.y);
00309 applet.vertex(p7.x,p7.y);
00310
00311 applet.endShape(CLOSE);
00312
00313
00314 }
00315
00324 public static void arrow(PApplet applet, float x, float y, float width, float height)
00325 {
00326 applet.beginShape();
00327
00328 float indentY = 2f/7f*height;
00329 float indentX = 4f/9f*width;
00330
00331 applet.vertex(x,y+indentY);
00332 applet.vertex(x+indentX,y+indentY);
00333 applet.vertex(x+indentX,y);
00334 applet.vertex(x+width,y+height/2f);
00335 applet.vertex(x+indentX,y+height);
00336 applet.vertex(x+indentX,y+height-indentY);
00337 applet.vertex(x,y+height-indentY);
00338
00339 applet.endShape(CLOSE);
00340 }
00341
00346 private void updateHistoryPosition()
00347 {
00348 float fullWidth = 0;
00349 for (int i= clickHistory.size()-1; i>=0; i--)
00350 {
00351 fullWidth += clickHistory.get(i).getDimension().x;
00352 }
00353 if (fullWidth+50 > this.getSize().width)
00354 {
00355
00356 float prevX = this.getSize().width-50;
00357 for (int i= clickHistory.size()-1; i>=0; i--)
00358 {
00359 float newX = prevX - clickHistory.get(i).getDimension().x;
00360 prevX = newX;
00361 clickHistory.get(i).setPosition(newX, 0, i==clickHistory.size()-1);
00362 }
00363 } else {
00364
00365 float currX = 0;
00366 for (int i= 0; i<clickHistory.size(); i++)
00367 {
00368 clickHistory.get(i).setPosition(currX, 0, i==clickHistory.size()-1);
00369 currX += clickHistory.get(i).getDimension().x;
00370 }
00371 }
00372 }
00373
00377 private void drawHistory()
00378 {
00379 if(clickHistory.size()>=1) {
00380 for (int i= clickHistory.size()-1; i>=0; i--)
00381 {
00382 clickHistory.get(i).Draw(this);
00383 }
00384 }
00385 }
00386
00390 private void drawCurrAction()
00391 {
00392 if (currAction == null)
00393 return;
00394
00395 currAction.getDrawInfo().drawExtendedBox(this, new Vector2f(50+drawOffset.x,80+drawOffset.y), drawOffset);
00396 }
00397
00398 @Override
00399 public void mouseMoved(MouseEvent e) {
00400 if (getHistoryHover(e.getX(), e.getY())>=0)
00401 {
00402 setCursor(handCursor);
00403 return;
00404 }
00405
00406 if (currAction ==null)
00407 {
00408 setCursor(normalCursor);
00409 return;
00410 }
00411 if (currAction.getDrawInfo().updateHover(e.getX(), e.getY()))
00412 setCursor(handCursor);
00413 else
00414 setCursor(normalCursor);
00415 }
00416
00417 @Override
00418 public void mouseDragged(MouseEvent e) {
00419 if (draggingStart != null && currAction != null)
00420 {
00421 drawOffset.x = Math.min(0, drawOffset.x+ e.getX() - draggingStart.x);
00422 drawOffset.y = Math.min(0,drawOffset.y + e.getY() - draggingStart.y);
00423
00424 float viewOffsetX = Math.min(0, this.getWidth()-(currAction.getDrawInfo().getBoundingBox().width+100));
00425 float viewOffsetY = Math.min(0, this.getHeight()-(currAction.getDrawInfo().getBoundingBox().height+130));
00426
00427 drawOffset.x = Math.max(viewOffsetX,drawOffset.x);
00428 drawOffset.y = Math.max(viewOffsetY,drawOffset.y);
00429
00430 draggingStart.x = e.getX();
00431 draggingStart.y = e.getY();
00432 }
00433 }
00434
00435 @Override
00436 public void mousePressed(MouseEvent e) {
00437 if (e.getButton() == 3)
00438 {
00439 draggingStart = new Vector2f(e.getX(),e.getY());
00440 setCursor(moveCursor);
00441 } else {
00442 setCursor(normalCursor);
00443 }
00444 }
00445
00446 @Override
00447 public void mouseReleased(MouseEvent e) {
00448 setCursor(normalCursor);
00449 }
00450
00451 @Override
00452 public void mouseEntered(MouseEvent e) {
00453 }
00454
00455 @Override
00456 public void mouseExited(MouseEvent e) {
00457 }
00458
00459 @Override
00460 public void mouseClicked(MouseEvent e) {
00461 long diff = System.currentTimeMillis()-lastClickTime;
00462 lastClickTime = System.currentTimeMillis();
00463 if (diff < 10)
00464 return;
00465 if (e.getButton() == MouseEvent.BUTTON1 && currAction != null)
00466 {
00467
00468 int idx = getHistoryHover(e.getX(), e.getY());
00469 if (idx >= 0)
00470 {
00471 currAction = clickHistory.get(idx).getAction();
00472 for (int i=clickHistory.size()-1; i>idx; i--)
00473 {
00474 clickHistory.remove(i);
00475 }
00476 updateHistoryPosition();
00477 return;
00478 }
00479
00480
00481 Action a = currAction.getDrawInfo().checkClickExpand(e.getX(), e.getY());
00482 if (a!= null)
00483 {
00484 a.toggleExpand();
00485 currAction.getDrawInfo().notifyModified();
00486 return;
00487 }
00488
00489
00490 a = currAction.getDrawInfo().checkClick(e.getX(), e.getY());
00491 if (a!= null && a != currAction)
00492 {
00493 currAction = a;
00494 if (clickHistory.size()>1 && clickHistory.get(clickHistory.size()-2).getAction()==a)
00495 clickHistory.remove(clickHistory.size()-1);
00496 else
00497 clickHistory.add(new ActionSelectHistoryInfo(currAction));
00498 updateHistoryPosition();
00499 }
00500
00501
00502 }
00503 }
00504
00512 private int getHistoryHover(float x, float y)
00513 {
00514 int idx = -1;
00515 for (int i= 0; i<clickHistory.size()-1; i++)
00516 {
00517 if (idx >= 0)
00518 {
00519 clickHistory.get(i).setHover(false);
00520 } else {
00521 if (clickHistory.get(i).checkHover(x, y))
00522 {
00523 idx = i;
00524 }
00525 }
00526 }
00527 return idx;
00528 }
00529
00536 public boolean highlightAction(Action a, boolean expand)
00537 {
00538 if (currAction == null)
00539 return false;
00540 currAction.getDrawInfo().clearHightlight();
00541 return currAction.getDrawInfo().highlightSubsequence(a,expand);
00542 }
00543
00550 public boolean highlightAction(String identifier, boolean expand)
00551 {
00552 if (currAction == null)
00553 return false;
00554 currAction.getDrawInfo().clearHightlight();
00555 return currAction.getDrawInfo().highlightSubsequence(identifier,expand);
00556 }
00557
00561 public void clearHighlight()
00562 {
00563 if (currAction == null)
00564 return;
00565 currAction.getDrawInfo().clearHightlight();
00566 }
00567
00568 @Override
00569 public void mouseWheelMoved(MouseWheelEvent e) {
00570 int totalScrollAmount = 0;
00571 if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL)
00572 {
00573 totalScrollAmount = e.getUnitsToScroll() * e.getScrollAmount();
00574 } else {
00575 totalScrollAmount = e.getWheelRotation() * 30;
00576 }
00577 draggingStart.y += totalScrollAmount;
00578 }
00579
00580 }