$search
00001 package edu.tum.cs.ias.knowrob.vis.applets; 00002 00003 import java.awt.Color; 00004 import java.awt.Frame; 00005 import java.awt.event.KeyEvent; 00006 import java.awt.event.MouseListener; 00007 import java.awt.event.MouseMotionListener; 00008 import java.util.Collections; 00009 import java.util.HashMap; 00010 import java.util.Map; 00011 import java.util.Vector; 00012 00013 import controlP5.Button; 00014 import controlP5.ControlEvent; 00015 import controlP5.ControlGroup; 00016 import controlP5.ControlP5; 00017 import controlP5.ListBox; 00018 import controlP5.ListBoxItem; 00019 import controlP5.Textfield; 00020 import edu.tum.cs.ias.knowrob.owl.OWLClass; 00021 import edu.tum.cs.ias.knowrob.owl.OWLThing; 00022 import edu.tum.cs.ias.knowrob.vis.actions.Action; 00023 import edu.tum.cs.ias.knowrob.vis.themes.GreyTheme; 00024 00025 00026 import processing.core.PApplet; 00027 import processing.core.PFont; 00028 00029 00030 public class ActionPropertiesEditor extends PApplet implements MouseListener, MouseMotionListener, IClassSelectionCallback { 00031 00032 private static final long serialVersionUID = 7695328948788620463L; 00033 00034 public ControlP5 controlP5; 00035 00039 private PFont dejavuFont; 00040 00044 OwlClassSelectorApplet class_selector; 00045 00049 private IAddActionCallback callback; 00050 00051 00055 private Button submit; 00056 00060 private ListBox action_props; 00061 00065 private ListBox props; 00066 00070 private ListBoxItem currentActionProp; 00071 00075 private ListBoxItem currentProp; 00076 00081 private Map<Integer, ListBoxItem> actionpropId2item; 00082 00087 private Map<Integer, ListBoxItem> propId2item; 00088 00092 private int listBoxHeight = 20; 00093 00097 private boolean initialized = false; 00098 00102 private boolean editing = false; 00103 00104 private Textfield identifier; 00105 00106 private Textfield cls; 00107 00108 private Textfield value; 00109 00110 private boolean propsIsActive; 00111 00112 private String base_iri; 00113 00114 00115 00116 00117 // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // 00118 // 00119 // Init/drawing methods 00120 // 00121 00122 00123 @Override 00124 public void setup() 00125 { 00126 size(500, 500); 00127 00128 if (this.frame != null) 00129 { 00130 this.frame.setTitle("Edit action properties"); 00131 this.frame.setBackground(new Color(40, 40, 40)); 00132 } 00133 00134 dejavuFont = createFont("DejaVu Sans",12); 00135 textFont(dejavuFont); 00136 00137 frameRate(15); 00138 background(50); 00139 00140 initControlP5(); 00141 } 00142 00143 00147 @Override 00148 public void draw() { 00149 00150 background(40); 00151 00152 if(initialized) { 00153 controlP5.draw(); 00154 } 00155 } 00156 00157 00158 00159 // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // 00160 // 00161 // Public getter/setter interface 00162 // 00163 00164 00170 public void setIdentifier(String id) { 00171 ((Textfield) this.controlP5.getController("identifier")).setValue(id); 00172 } 00173 00179 public String getIdentifier() { 00180 return ((Textfield) this.controlP5.getController("identifier")).getStringValue(); 00181 } 00182 00188 // TODO: extend to the case of multiple super-classes 00189 public void setActionClass(String cl) { 00190 ((Textfield) this.controlP5.getController("class")).setValue(cl); 00191 } 00192 00198 public String getActionClass() { 00199 return ((Textfield) this.controlP5.getController("class")).getStringValue(); 00200 } 00201 00202 00209 public void setActionProperties(Map<String, Vector<String>> props) { 00210 00211 synchronized (action_props) { 00212 action_props.clear(); 00213 } 00214 addActionProperties(props); 00215 } 00216 00217 00224 public void addActionProperties(Map<String, Vector<String>> new_props) { 00225 00226 for(String prop : new_props.keySet()) { 00227 for(String val : new_props.get(prop)) { 00228 00229 if(prop.endsWith("type")) { 00230 this.setActionClass(val); 00231 } else { 00232 addActionPropItem(prop, val); 00233 } 00234 } 00235 } 00236 } 00237 00238 00245 public void addActionPropItem(String prop, String val) { 00246 00247 String prop_short = OWLThing.getShortNameOfIRI(prop); 00248 00249 // find largest index (not necessarily consecutive) 00250 int props_idx = props.getListBoxItems().length + 1; 00251 for(String[] item : props.getListBoxItems()) { 00252 if(Integer.valueOf(item[2]) > props_idx) 00253 props_idx = Integer.valueOf(item[3]); 00254 } 00255 props_idx++; 00256 00257 // add property to properties list if not there yet so that mapping shortname->IRI works 00258 if(getIRIForPropShortName(prop_short) == null) { 00259 synchronized (props) { 00260 propId2item.put(props_idx, props.addItem(prop, props_idx).setText(OWLThing.getShortNameOfIRI(prop))); 00261 } 00262 } 00263 00264 addActionPropItem(prop_short + " -- " + val); 00265 00266 } 00267 00268 00276 private void addActionPropItem(String name) { 00277 00278 int idx = 0; 00279 if(actionpropId2item.size()>0) 00280 idx = Collections.max(actionpropId2item.keySet()) + 1; 00281 00282 synchronized (action_props) { 00283 ListBoxItem item = actionpropId2item.put(idx, action_props.addItem(name, idx)); 00284 setCurrentActionPropItem(item); 00285 } 00286 00287 // adjust height of the action properties ListBox and position of the submit button 00288 if(submit.getPosition().y < this.height-50) { 00289 00290 listBoxHeight += 20; 00291 synchronized (action_props) { 00292 action_props.setHeight(listBoxHeight); 00293 } 00294 submit.setPosition(submit.getPosition().x, submit.getPosition().y + 20); 00295 } 00296 } 00297 00298 00304 private void removeActionPropItem(ListBoxItem item) { 00305 00306 if(item!=null) { 00307 00308 // remove from action class 00309 String id = ((Textfield) controlP5.getController("identifier")).getText(); 00310 Action act = Action.getAction(id, null); 00311 00312 String[] prop_val = item.getName().split(" -- ", 2); 00313 String prop = getIRIForPropShortName(prop_val[0]); 00314 String val = prop_val[1]; 00315 00316 if(act.getHasValue().containsKey(prop)) { 00317 act.getHasValue().get(prop).remove(val); // TODO: we should directly propagate the change to Prolog here... 00318 00319 if(act.getHasValue().get(prop).isEmpty()) 00320 act.getHasValue().remove(prop); 00321 } 00322 if(act.getSomeValuesFrom().containsKey(prop)) { 00323 act.getSomeValuesFrom().get(prop).remove(val); 00324 00325 if(act.getSomeValuesFrom().get(prop).isEmpty()) 00326 act.getSomeValuesFrom().remove(prop); 00327 } 00328 act.getDrawInfo().notifyModified(); 00329 00330 synchronized (action_props) { 00331 00332 // update gui 00333 action_props.removeItem(item.getName()); 00334 currentActionProp = null; 00335 actionpropId2item.remove(item.getValue()); 00336 00337 // adapt layout 00338 listBoxHeight += 20; 00339 action_props.setHeight(listBoxHeight); 00340 submit.setPosition(submit.getPosition().x, submit.getPosition().y - 20); 00341 } 00342 } 00343 } 00344 00350 private void setCurrentActionPropItem(ListBoxItem item) { 00351 00352 if(currentActionProp!=null) { 00353 currentActionProp.setColorBackground(color(80)); 00354 } 00355 00356 // also allow 'null' as item -> reset highlight 00357 currentActionProp = item; 00358 00359 if(item!=null) { 00360 item.setColorBackground(color(120)); 00361 } 00362 } 00363 00364 00365 public boolean isEditing() { 00366 return editing; 00367 } 00368 00369 public void setEditing(boolean e) { 00370 00371 this.editing = e; 00372 if(editing) { 00373 Textfield id = ((Textfield) controlP5.getController("identifier")); 00374 controlP5.addTextlabel("edited identifier", "Editing action: '" +id.getText() +"'", (int)id.getPosition().x, (int)id.getPosition().y); 00375 id.setVisible(false); 00376 00377 controlP5.getController("submit").setCaptionLabel("update action"); 00378 } 00379 } 00380 00381 public boolean isInitialized() { 00382 return initialized; 00383 } 00384 00385 private String getIRIForPropShortName(String shortname) { 00386 00387 // getListBoxItems returns String[]{name, value} 00388 synchronized (props) { 00389 for(String[] i : props.getListBoxItems()) { 00390 if(i[0].endsWith(shortname)) { 00391 return i[0]; 00392 } 00393 } 00394 } 00395 return null; 00396 } 00397 00398 00399 00400 // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // 00401 // 00402 // Event handling 00403 // 00404 00408 public void controlEvent(ControlEvent ev) { 00409 00410 00411 if(ev.isController()) { 00412 00413 00414 // open class selection dialog 00415 if(ev.getController().getName().equals("class") || ev.getController().getName().equals("select class")) { 00416 OWLClassSelect f = new OWLClassSelect("http://ias.cs.tum.edu/kb/knowrob.owl#PurposefulAction"); 00417 f.setClassSelectedCallback(this); 00418 } 00419 00420 00421 // add action property 00422 if(ev.getController().getName().equals("add property") || ev.getController().getName().equals("value")) { 00423 00424 00425 synchronized (props) { 00426 00427 addActionPropItem(propId2item.get((int)props.getValue()).getName(), ((Textfield) controlP5.getController("value")).getText()); 00428 00429 // add to action class 00430 String id = ((Textfield) controlP5.getController("identifier")).getText(); 00431 00432 // add default namespace if none is given 00433 if(!id.contains("#")) { 00434 id = base_iri + id; 00435 } 00436 00437 Action act = Action.getAction(id, null); 00438 act.addHasValue(propId2item.get((int)props.getValue()).getName(), ((Textfield) controlP5.getController("value")).getText()); 00439 act.setSaveToProlog(true); 00440 act.getDrawInfo().notifyModified(); 00441 00442 // TODO: somehow distinguish between someValuesfrom and hasValue -> create OWLProperty type and use hasValue for DataProperties? 00443 00444 } 00445 00446 // reset text field and properties box 00447 ((Textfield) controlP5.getController("value")).setText(""); 00448 00449 if(currentProp!=null) 00450 currentProp.setColorBackground(color(80)); 00451 00452 currentProp = null; 00453 } 00454 00455 00456 // remove action property 00457 if(ev.getController().getName().equals("remove property")) { 00458 if(currentActionProp!=null) { 00459 removeActionPropItem(currentActionProp); 00460 currentActionProp = null; 00461 } 00462 } 00463 00464 // submit action to parent object 00465 if(ev.getController().getName().equals("submit")) { 00466 00467 String id = ((Textfield) controlP5.getController("identifier")).getText(); // TODO: add label field to the action editor forms 00468 00469 // add default namespace if none is given 00470 if(!id.contains("#")) { 00471 id = base_iri + id; 00472 } 00473 Action act = Action.getAction(id, null); 00474 act.setSaveToProlog(true); 00475 00476 OWLClass sup = OWLClass.getOWLClass(((Textfield) controlP5.getController("class")).getText()); 00477 act.getSuperClasses().clear(); 00478 act.addSuperClass(sup); 00479 00480 if(!editing) 00481 this.callback.addAction(act); 00482 00483 // Note: updates are automatically propagated since actions are implemented as singletons 00484 00485 this.frame.setVisible(false); 00486 } 00487 } 00488 00489 00490 if(ev.isGroup()) { 00491 00492 if(ev.getGroup().getName().equals("Action properties")) { 00493 00494 ListBoxItem item = actionpropId2item.get((int)ev.getValue()); 00495 setCurrentActionPropItem(item); 00496 } 00497 00498 00499 if(ev.getGroup().getName().equals("Properties")) { 00500 00501 ListBoxItem item = propId2item.get((int)ev.getValue()); 00502 00503 if(item!=null) { 00504 if(currentProp!=null) 00505 currentProp.setColorBackground(color(80)); 00506 00507 currentProp = item; 00508 item.setColorBackground(color(120)); 00509 } 00510 } 00511 } 00512 00513 } 00514 00515 00516 public void keyPressed(KeyEvent e) { 00517 00518 // iterate through form fields with TAB 00519 if(e.getKeyCode() == KeyEvent.VK_TAB) { 00520 00521 if(identifier.isActive()) { 00522 identifier.setFocus(false); 00523 if(e.isShiftDown()) 00524 value.setFocus(true); 00525 else 00526 cls.setFocus(true); 00527 return; 00528 00529 } else if(cls.isActive()) { 00530 cls.setFocus(false); 00531 props.setValue(0); 00532 if(e.isShiftDown()) 00533 identifier.setFocus(true); 00534 else 00535 propsIsActive = true; 00536 return; 00537 00538 00539 } else if(propsIsActive) { 00540 propsIsActive = false; 00541 if(e.isShiftDown()) 00542 cls.setFocus(true); 00543 else 00544 value.setFocus(true); 00545 return; 00546 00547 } else if(value.isActive()) { 00548 value.setFocus(false); 00549 if(e.isShiftDown()) 00550 propsIsActive = true; 00551 else 00552 identifier.setFocus(true); 00553 return; 00554 } 00555 00556 } else if(e.getKeyCode() == KeyEvent.VK_DOWN && propsIsActive) { 00557 if(props.getValue() < props.getListBoxItems().length-1) 00558 props.setValue(props.getValue()+1); 00559 00560 } else if(e.getKeyCode() == KeyEvent.VK_UP && propsIsActive) { 00561 if(props.getValue() > 0) 00562 props.setValue(props.getValue()-1); 00563 00564 } else { 00565 controlP5.keyHandler.keyEvent(e, controlP5.controlWindow, true); 00566 } 00567 } 00568 00569 00570 00571 00572 // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // 00573 // 00574 // Callback methods 00575 // 00576 00577 00578 00585 @Override 00586 public void owlClassSelected(String cl) { 00587 setActionClass(cl); 00588 } 00589 00594 public void setAddActionCallback(IAddActionCallback cb) { 00595 this.callback = cb; 00596 } 00597 00602 public void setBaseIRI(String base_iri) { 00603 this.base_iri = base_iri; 00604 } 00605 00606 00612 public class OWLClassSelect extends Frame { 00613 private static final long serialVersionUID = -7174804883131977878L; 00614 00615 public OWLClassSelect(String baseclass) { 00616 setBounds(100,100,800,600); 00617 class_selector = new OwlClassSelectorApplet(); 00618 class_selector.frame = this; 00619 add(class_selector); 00620 class_selector.init(); 00621 class_selector.setBaseClass(baseclass); 00622 this.setVisible(true); 00623 } 00624 00625 public void setClassSelectedCallback(IClassSelectionCallback cb) { 00626 class_selector.setClassSelectedCallback(cb); 00627 } 00628 } 00629 00630 00631 00632 00633 // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // 00634 // 00635 // GUI initialization and styling 00636 // 00637 00641 private void initControlP5() { 00642 00643 controlP5 = new ControlP5(this); 00644 GreyTheme.applyStyle(controlP5); 00645 00646 00647 identifier = controlP5.addTextfield("identifier", 20, 20, 300, 20).setAutoClear(false).setFocus(true); 00648 00649 cls = controlP5.addTextfield("class", 20, 60, 300, 20).setAutoClear(false); 00650 controlP5.addButton("select class", 1, 330, 60, 35, 20).setCaptionLabel("select"); 00651 00652 submit = controlP5.addButton("submit", 1, 355, 275, 65, 20).setCaptionLabel("add to task"); 00653 00654 00655 ControlGroup<?> new_prop = GreyTheme.applyStyle(controlP5.addGroup("Add properties", 20, 120, 400)); 00656 new_prop.setBackgroundHeight(105); 00657 00658 00659 props = controlP5.addListBox("Properties", 10, 30, 200, 75); 00660 props.setBarHeight(15).setItemHeight(15); 00661 props.setColorValue(color(120,40,40)); 00662 GreyTheme.applyStyle(props, 15).moveTo(new_prop); 00663 00664 int props_idx = 0; 00665 propId2item = new HashMap<Integer, ListBoxItem>(); 00666 00667 // TODO read properties from KnowRob 00668 String[] properties = new String[]{"http://ias.cs.tum.edu/kb/knowrob.owl#objectActedOn", 00669 "http://ias.cs.tum.edu/kb/knowrob.owl#reactionType", 00670 "http://ias.cs.tum.edu/kb/knowrob.owl#spokenText", 00671 "http://ias.cs.tum.edu/kb/knowrob.owl#queryText", 00672 "http://ias.cs.tum.edu/kb/knowrob.owl#toLocation", 00673 "http://ias.cs.tum.edu/kb/knowrob.owl#fromLocation", 00674 "http://ias.cs.tum.edu/kb/knowrob.owl#operatorType", 00675 "http://ias.cs.tum.edu/kb/knowrob.owl#bodyPartUsed", 00676 "http://ias.cs.tum.edu/kb/knowrob.owl#compressionLevel", 00677 "http://ias.cs.tum.edu/kb/knowrob.owl#downscaleFactor"}; 00678 00679 synchronized (props) { 00680 for(String property : properties) { 00681 propId2item.put(props_idx, props.addItem(property, props_idx).setText(OWLThing.getShortNameOfIRI(property))); 00682 props_idx++; 00683 } 00684 } 00685 00686 value = controlP5.addTextfield("value", 230, 15, 160, 20).setAutoClear(true).moveTo(new_prop); 00687 00688 controlP5.addButton("add property", 2, 230, 55, 33, 20).moveTo(new_prop).setCaptionLabel(" add"); 00689 controlP5.addButton("remove property", 2, 280, 55, 50, 20).moveTo(new_prop).setCaptionLabel(" remove"); 00690 00691 action_props = controlP5.addListBox("Action properties", 20, 260, 400, listBoxHeight).setBarHeight(15).setItemHeight(20); 00692 GreyTheme.applyStyle(action_props, 20); 00693 00694 actionpropId2item = new HashMap<Integer, ListBoxItem>(); 00695 setCurrentActionPropItem(null); 00696 00697 this.initialized = true; 00698 00699 } 00700 00701 00702 00703 // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // 00704 // 00705 // Main method 00706 // 00707 00708 00709 public static void main(String args[]) { 00710 PApplet.main(new String[] { "edu.tum.cs.ias.knowrob.vis.applets.ActionPropertiesEditor" }); 00711 } 00712 00713 00714 00715 } 00716