1 19 20 package org.openide.explorer.propertysheet; 21 22 import java.awt.Color ; 23 import java.awt.Component ; 24 import java.awt.KeyboardFocusManager ; 25 import java.awt.Point ; 26 import java.awt.Rectangle ; 27 import java.awt.event.KeyEvent ; 28 import java.awt.event.MouseEvent ; 29 import java.awt.event.WindowAdapter ; 30 import java.awt.event.WindowEvent ; 31 import java.awt.image.BufferedImage ; 32 import java.beans.FeatureDescriptor ; 33 import java.beans.PropertyEditor ; 34 import java.beans.PropertyEditorManager ; 35 import java.beans.PropertyEditorSupport ; 36 import java.lang.reflect.InvocationTargetException ; 37 import javax.swing.JComboBox ; 38 import javax.swing.JComponent ; 39 import javax.swing.JFrame ; 40 import javax.swing.SwingUtilities ; 41 import org.netbeans.junit.NbTestCase; 42 import org.openide.nodes.AbstractNode; 43 import org.openide.nodes.Children; 44 import org.openide.nodes.Node; 45 import org.openide.nodes.PropertySupport; 46 import org.openide.nodes.Sheet; 47 48 public class SheetTableTest extends NbTestCase { 50 51 static { 52 String [] syspesp = PropertyEditorManager.getEditorSearchPath(); 53 String [] nbpesp = new String [] { 54 "org.netbeans.beaninfo.editors", "org.openide.explorer.propertysheet.editors", }; 57 String [] allpesp = new String [syspesp.length + nbpesp.length]; 58 System.arraycopy(nbpesp, 0, allpesp, 0, nbpesp.length); 59 System.arraycopy(syspesp, 0, allpesp, nbpesp.length, syspesp.length); 60 PropertyEditorManager.setEditorSearchPath(allpesp); 61 } 62 63 64 public SheetTableTest(String name) { 65 super(name); 66 } 67 68 73 protected void setUp() throws Exception { 74 if (setup) return; 75 PropUtils.forceRadioButtons =false; 76 final JFrame jf = new JFrame (); 77 tp = new TProperty("What a", true); 79 tp1 = new TProperty2("marvelous", true); 80 tp2 = new TProperty2("use of", true); 81 tp3 = new TProperty2("technology!", true); 82 tp4 = new TProperty3("AAAA", true); 83 tp5 = new TProperty4("vvvv", true); 84 te = new TEditor(); 86 tn = new TNode(); 88 89 try { 90 PropUtils.forceRadioButtons=false; 91 final PropertySheet ps = new PropertySheet(); 92 ps.setCurrentNode(tn); 94 sleep(); 95 96 setSortingMode(ps, PropertySheet.UNSORTED); 97 98 jf.getContentPane().add(ps); 99 jf.setLocation(20,20); 100 jf.setSize(300, 400); 101 102 103 new WaitWindow(jf); 104 105 final SheetTable tb = ps.table; 106 107 SheetCellEditor editor = tb.getEditor(); 108 109 tb.requestFocus(); 110 sleep(); 111 112 assertTrue("Table should have focus", KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() == tb); 113 114 clickOn(tb, 1, 0); 115 116 fd_after1_0click = tb._getSelection(); 117 ie_after1_0click = editor.getInplaceEditor(); 118 119 System.err.println("Selection after 1_0 click is " + fd_after1_0click + " - inplaceEditor=" + ie_after1_0click); 120 121 clickOn(tb, 1, 1); 122 123 fd_after1_1click = tb._getSelection(); 124 ie_after1_1click = editor.getInplaceEditor(); 125 126 System.err.println("Selection after 1_1 click is " + fd_after1_1click + " - inplaceEditor=" + ie_after1_1click); 127 128 clickOn(tb, 1, 0); 129 130 fd_after1_0click2 = tb._getSelection(); 131 ie_after1_0click2 = editor.getInplaceEditor(); 132 133 System.err.println("Selection after 1_0 click2 is " + fd_after1_0click2 + " - inplaceEditor=" + ie_after1_0click2); 134 135 sleep(); 136 pressKey(tb, KeyEvent.VK_SPACE); 138 sleep(); 139 ie_afterSpaceKeystroke = editor.getInplaceEditor(); 140 141 System.err.println("IE AFTER PRESSING SPACE" + ie_afterSpaceKeystroke); 142 143 try {Thread.currentThread().sleep(300);}catch(Exception e){} 144 Component comp = ie_afterSpaceKeystroke==null ? null : ie_afterSpaceKeystroke.getComponent(); 145 sleep(); 146 editorFocusedAfterSpacebarInitiation = (comp != null) && comp == KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner(); 147 if (comp == null) { 148 fail("Failed to get editor"); 149 } 150 151 typeKey(comp, KeyEvent.VK_H); 152 typeKey(comp, KeyEvent.VK_I); 153 typeKey(comp, KeyEvent.VK_SPACE); 154 typeKey(comp, KeyEvent.VK_M); 155 typeKey(comp, KeyEvent.VK_O); 156 typeKey(comp, KeyEvent.VK_M); 157 158 pressKey(comp, KeyEvent.VK_ENTER); 159 160 valAfterTyping = tp.getValue(); 161 162 sleep(); 163 164 pressKey(tb, KeyEvent.VK_SPACE); 165 typeKey(comp, KeyEvent.VK_B); 166 typeKey(comp, KeyEvent.VK_Y); 167 typeKey(comp, KeyEvent.VK_E); 168 typeKey(comp, KeyEvent.VK_SPACE); 169 typeKey(comp, KeyEvent.VK_M); 170 typeKey(comp, KeyEvent.VK_O); 171 typeKey(comp, KeyEvent.VK_M); 172 sleep(); 173 174 pressKey(comp, KeyEvent.VK_ESCAPE); 175 176 valAfterEscape = tp.getValue(); 177 178 clickOn(tb, 4, 1); 180 sleep(); 181 popupConsistent &= (editor.getInplaceEditor() instanceof JComboBox ) && 182 ((JComboBox ) editor.getInplaceEditor()).isPopupVisible(); 183 184 clickOn(tb, 3, 1); 185 sleep(); 186 popupConsistent &= (editor.getInplaceEditor() instanceof JComboBox ) && 187 ((JComboBox ) editor.getInplaceEditor()).isPopupVisible(); 188 189 clickOn(tb, 2, 1); 190 sleep(); 191 popupConsistent &= (editor.getInplaceEditor() instanceof JComboBox ) && 192 ((JComboBox ) editor.getInplaceEditor()).isPopupVisible(); 193 194 comp = editor.getInplaceEditor().getComponent(); 195 pressKey(comp, KeyEvent.VK_ESCAPE); 196 escClosedPopup = !((JComboBox ) comp).isPopupVisible(); 197 inplaceReferenceCleared = editor.getInplaceEditor() == null; 198 199 clickOn(tb, 0,0); 200 closedSetSuccessfullyWithMouse = tb.getRowCount() == 1; 201 202 pressKey(tb, KeyEvent.VK_SPACE); 203 reopenedSetSuccessfullyWithMouse = tb.getRowCount() > 1; 204 205 pressKey(tb, KeyEvent.VK_SPACE); 206 closedSetSuccessfullyWithKeyboard = tb.getRowCount() == 1; 207 208 clickOn(tb, 0,0); 209 reopenedSetSuccessfullyWithMouse = tb.getRowCount() > 1; 210 211 try {Thread.currentThread().sleep(300);}catch(Exception e){} 212 if (GraphicsTestCase.canSafelyRunPixelTests()) { 213 grayMarginEdgePaintedWhenSortByCategory = checkPixel(ps, PropUtils.getSetRendererColor(), 6, 200); 214 } else { 215 grayMarginEdgePaintedWhenSortByCategory = true; 216 System.err.println("CANNOT RUN PAINTING TESTS IN A <16 BIT OR HEADLESS ENVIRONMENT"); 217 } 218 219 setSortingMode(ps, PropertySheet.SORTED_BY_NAMES); 220 221 try {Thread.currentThread().sleep(300);}catch(Exception e){} 222 223 grayMarginEdgeNotPaintedWhenSortByName = checkPixel(ps, ps.getBackground(), 6, 200); 224 225 clickOn(tb, 0,0); 226 boolPropFirst = tb._getSelection() == tp4; 227 228 clickOn(tb, 0, 1); 229 boolNowTrue = Boolean.TRUE.equals(tp4.getValue()); 230 231 pressKey(tb, KeyEvent.VK_SPACE); 232 boolNowFalse = Boolean.FALSE.equals(tp4.getValue()); 233 234 int i = tb.getRowCount(); 235 tn.addProp(new TProperty2("ZZZZ", true)); 236 237 sleep(); 238 239 addedPropertiesFound = tb.getRowCount() == i+1; 240 241 PropUtils.noAltBg = Boolean.FALSE; 242 PropUtils.altBg = new Color (255,255, 200); 243 jf.repaint(); 244 245 246 } catch (Exception e) { 247 e.printStackTrace(); 248 fail("FAILED - Exception thrown "+e.getClass().toString()); 249 } finally { 250 setup = true; 251 } 254 } 255 256 257 private static Exception throwMe=null; 258 private synchronized void setSortingMode(final PropertySheet ps, final int mode) throws Exception { 259 throwMe = null; 260 SwingUtilities.invokeAndWait(new Runnable () { 261 public void run() { 262 try { 263 ps.setSortingMode(mode); 264 } catch (Exception e) { 265 throwMe = e; 266 } 267 } 268 }); 269 if (throwMe != null) { 270 Exception ex = throwMe; 271 throwMe = null; 272 throw (throwMe); 273 } 274 } 275 276 private static class WaitWindow extends WindowAdapter { 277 boolean shown=false; 278 public WaitWindow(JFrame f) { 279 f.addWindowListener(this); 280 f.show(); 281 if (!shown) { 282 synchronized(this) { 283 try { 284 wait(5000); 286 } catch (Exception e) {} 287 } 288 } 289 } 290 291 public void windowOpened(WindowEvent e) { 292 shown = true; 293 synchronized(this) { 294 notifyAll(); 296 ((JFrame ) e.getSource()).removeWindowListener(this); 297 } 298 } 299 } 300 301 private static final int SLEEP_LENGTH=1000; 302 private void sleep() { 303 305 312 313 314 315 316 318 try { 319 SwingUtilities.invokeAndWait(new Runnable () { 321 public void run() { 322 System.currentTimeMillis(); 323 } 324 }); 325 SwingUtilities.invokeAndWait(new Runnable () { 327 public void run() { 328 System.currentTimeMillis(); 329 } 330 }); 331 } catch (Exception e) { 332 } 333 334 335 } 336 337 338 public void testSpaceBarToggleBoolean() { 339 assertTrue("After sending spacebar with boolean property selected, boolean value unchanged", boolNowFalse); 340 } 341 342 public void testSingleClickToggleBoolean() { 343 assertTrue("Property named AAA should be first property in alphabetic sort but isn't", boolPropFirst); 344 } 345 346 public void testFindAddedProperties() { 347 assertTrue("Adding a new property to the node did not change the number of table rows displayed", addedPropertiesFound); 348 } 349 350 private static boolean addedPropertiesFound=false; 351 private static boolean boolNowTrue=false; 352 private static boolean boolNowFalse=false; 353 private static boolean boolPropFirst=false; 354 private static boolean grayMarginEdgePaintedWhenSortByCategory=false; 355 private static boolean grayMarginEdgeNotPaintedWhenSortByName=false; 356 private static Color checkColor=null; 357 private synchronized boolean checkPixel(final Component c, final Color toMatch, final int x, final int y) throws Exception { 358 SwingUtilities.invokeAndWait(new Runnable () { 359 public void run() { 360 final BufferedImage bi = new BufferedImage (500, 500, BufferedImage.TYPE_INT_RGB); 361 ((JComponent ) c).paintAll(bi.getGraphics()); 362 int[] cArr = new int[3]; 363 bi.getData().getPixel(6, 200, cArr); 364 checkColor = new Color (cArr[0], cArr[1], cArr[2]); 365 378 } 379 }); 380 boolean result = toMatch.equals(checkColor); 381 return result; 382 } 383 384 public void testGrayMarginEdgeNotPaintedWhenSortByName() { 385 assertTrue("Gray margin edge painted when in sort by names mode, but shouldn't be", grayMarginEdgeNotPaintedWhenSortByName); 386 } 387 388 public void testGrayMarginEdgePaintedWhenSortByCategory() { 389 assertTrue("Gray margin edge not painted in sort by category mode", grayMarginEdgePaintedWhenSortByCategory); 390 } 391 392 public void testCloseSetWithMouse() { 393 assertTrue("Click on row 0 in upper left did not close property set", closedSetSuccessfullyWithMouse); 394 } 395 396 public void testOpenSetWithKeyboard() { 397 assertTrue("Spacebar on closed set did not open it", reopenedSetSuccessfullyWithMouse); 398 } 399 400 public void testCloseSetWithKeyboard() { 401 assertTrue("Spacebar on open set did not close it", closedSetSuccessfullyWithKeyboard); 402 } 403 404 public void testOpenWithMouse() { 405 assertTrue("Mouse on closed set did not open it", reopenedSetSuccessfullyWithMouse); 406 } 407 408 public void testPopupConsistent() throws Exception { 409 assertTrue("Popup not always shown when mouse repeatedly clicked on different rows with popups", popupConsistent); 410 } 411 412 public void testInplaceReferenceCleared() { 413 assertTrue("After cancelling an edit with escape, SheetCellEditor should no longer hold a reference to the former editor", inplaceReferenceCleared); 414 } 415 416 private static boolean setup=false; 417 418 static boolean popupConsistent=true; 419 static boolean closedSetSuccessfullyWithMouse=false; 420 static boolean reopenedSetSuccessfullyWithMouse=false; 421 static boolean reopenedSetSuccessfullyWithKeyboard=false; 422 static boolean closedSetSuccessfullyWithKeyboard=false; 423 static FeatureDescriptor fd_after1_0click=null; 424 static InplaceEditor ie_after1_0click=null; 425 static FeatureDescriptor fd_after1_1click=null; 426 static InplaceEditor ie_after1_1click=null; 427 static FeatureDescriptor fd_after1_0click2=null; 428 static InplaceEditor ie_after1_0click2=null; 429 static InplaceEditor ie_afterSpaceKeystroke=null; 430 static Object valAfterTyping=null; 431 static Object valAfterEscape=null; 432 static boolean editorFocusedAfterSpacebarInitiation=false; 433 static boolean escClosedPopup=false; 434 static boolean inplaceReferenceCleared=false; 435 436 public void testEscClosesPopup() { 437 assertTrue("After sending escape key to open combo inplace editor, popup is still open", escClosedPopup); 438 } 439 440 public void testEditorFocusedAfterSpacebarInitiation() throws Exception { 441 assertTrue("After instantiating inplace editor with spacebar, editor was not focus owner", editorFocusedAfterSpacebarInitiation); 442 } 443 444 public void testEditModeAfterSpacePressed() { 445 assertTrue("Should be in edit mode after pressing space bar", ie_afterSpaceKeystroke instanceof StringInplaceEditor); 446 } 447 448 public void testValAfterTyping() { 449 assertTrue("Value after faking keyboard events to edit should be \"HI MOM\" but is \"" + valAfterTyping +"\"", "HI MOM".equals(valAfterTyping)); 450 } 451 452 public void testValAfterEscape() { 453 assertTrue("Value after faking keyboard events to edit, then cancelling with Escape should be \"HI MOM\" but is \"" + valAfterEscape +"\"", "HI MOM".equals(valAfterEscape)); 454 } 455 456 public void testNoEditAfterNameClick() throws Exception { 457 assertTrue("Clicking name should not put property sheet into edit mode", ie_after1_0click==null); 458 } 459 460 public void testSelectionAfter1_0Click() throws Exception { 461 assertTrue("Selection should be first element after click on row 1, column 0, but is " + fd_after1_0click, fd_after1_0click==tp); 462 } 463 464 public void testEditorAfter1_1Click() throws Exception { 465 assertTrue("Should be editing using string editor after click on row 1, column 1, but editor is " + ie_after1_1click, ie_after1_1click instanceof StringInplaceEditor); 466 } 467 468 public void testSelectionAfter1_1Click() throws Exception { 469 assertTrue("Selection should be first element after click on row 1, column 1, but is " + fd_after1_1click, fd_after1_1click==tp); 470 } 471 472 public void testEditCancelledAfterNameClick() throws Exception { 473 assertTrue("Clicking name should cancel editing, but editor.getInplaceEditor() returns " + ie_after1_0click2, ie_after1_0click2==null); 474 } 475 476 private void clickOn(final SheetTable tb, final int row, final int col) throws Exception { 477 SwingUtilities.invokeAndWait(new Runnable () { 478 public void run() { 479 Rectangle r = tb.getCellRect(row, col, false); 480 Point toClick = r.getLocation(); 481 toClick.x += 15; 482 toClick.y +=3; 483 MouseEvent me = new MouseEvent (tb, MouseEvent.MOUSE_PRESSED, System.currentTimeMillis(), MouseEvent.BUTTON1_MASK, toClick.x, toClick.y, 2, false); 484 tb.dispatchEvent(me); 485 } 486 }); 487 sleep(); 488 } 489 490 private void releaseKey(final Component target, final int key) throws Exception { 491 SwingUtilities.invokeAndWait(new Runnable () { 492 public void run() { 493 KeyEvent ke = new KeyEvent (target, KeyEvent.KEY_RELEASED, System.currentTimeMillis(), 0, key, (char) key); 494 target.dispatchEvent(ke); 495 } 496 }); 497 sleep(); 498 } 499 500 private void pressKey(final Component target, final int key) throws Exception { 501 SwingUtilities.invokeAndWait(new Runnable () { 502 public void run() { 503 KeyEvent ke = new KeyEvent (target, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), 0, key, (char) key); 504 target.dispatchEvent(ke); 505 } 506 }); 507 sleep(); 508 } 509 510 private void typeKey(final Component target, final int key) throws Exception { 511 SwingUtilities.invokeAndWait(new Runnable () { 512 public void run() { 513 KeyEvent ke = new KeyEvent (target, KeyEvent.KEY_TYPED, System.currentTimeMillis(), 0, KeyEvent.VK_UNDEFINED, (char) key); 514 target.dispatchEvent(ke); 515 } 516 }); 517 sleep(); 518 } 519 520 public class TNode extends AbstractNode { 522 public TNode() { 524 super(Children.LEAF); 525 setName("TNode"); setDisplayName("TNode"); 527 } 528 public Node cloneNode() { 530 return new TNode(); 531 } 532 533 public void addProp(Node.Property p) { 534 props.put(p); 535 this.firePropertyChange(PROP_PROPERTY_SETS, null, null); 536 this.firePropertySetsChange(null, null); 537 } 538 539 Sheet sheet=null; 540 Sheet.Set props=null; 541 protected Sheet createSheet() { 543 sheet = super.createSheet(); 544 props = sheet.get(Sheet.PROPERTIES); 546 if (props == null) { 547 props = Sheet.createPropertiesSet(); 548 sheet.put(props); 549 } 550 props.put(tp); 551 props.put(tp1); 552 props.put(tp2); 553 props.put(tp3); 554 props.put(tp4); 555 return sheet; 557 } 558 public void fireMethod(String s, Object o1, Object o2) { 560 firePropertyChange(s,o1,o2); 561 } 562 } 563 564 public class TProperty extends PropertySupport { 566 private Object myValue = "Value"; 567 public TProperty(String name, boolean isWriteable) { 569 super(name, Object .class, name, "", true, isWriteable); 570 } 571 public Object getValue() { 573 return myValue; 574 } 575 public void setValue(Object value) throws IllegalArgumentException ,IllegalAccessException , InvocationTargetException { 577 Object oldVal = myValue; 578 myValue = value; 579 tn.fireMethod(getName(), oldVal, myValue); 580 } 581 public PropertyEditor getPropertyEditor() { 583 return te; 584 } 585 } 586 587 public class TEditor extends PropertyEditorSupport implements ExPropertyEditor { 589 PropertyEnv env; 590 591 public TEditor() { 593 } 594 595 599 public void attachEnv(PropertyEnv env) { 600 this.env = env; 601 } 602 603 public boolean supportsCustomEditor() { 605 return true; 606 } 607 608 public void setValue(Object newValue) { 610 super.setValue(newValue); 611 } 612 613 public String getAsText() { 614 return getValue() == null ? "null" : getValue().toString(); 615 } 616 } 617 618 public class TagsEditor extends PropertyEditorSupport implements ExPropertyEditor { 619 PropertyEnv env; 620 621 public TagsEditor() { 622 } 623 624 public String [] getTags() { 625 return new String [] {"a","b","c","d","Value"}; 626 } 627 628 public void attachEnv(PropertyEnv env) { 629 this.env = env; 630 } 631 632 public boolean supportsCustomEditor() { 633 return false; 634 } 635 636 public void setValue(Object newValue) { 637 super.setValue(newValue); 638 } 639 } 640 641 public class TProperty2 extends PropertySupport { 643 private Object myValue = "Value"; 644 public TProperty2(String name, boolean isWriteable) { 646 super(name, Object .class, name, "", true, isWriteable); 647 } 648 public Object getValue() { 650 return myValue; 651 } 652 public void setValue(Object value) throws IllegalArgumentException ,IllegalAccessException , InvocationTargetException { 654 Object oldVal = myValue; 655 myValue = value; 656 tn.fireMethod(getName(), oldVal, myValue); 657 } 658 public PropertyEditor getPropertyEditor() { 660 return new TagsEditor(); 661 } 662 } 663 664 public class TProperty3 extends PropertySupport { 666 private Boolean myValue = Boolean.FALSE; 667 public TProperty3(String name, boolean isWriteable) { 669 super(name, Boolean .class, name, "", true, isWriteable); 670 } 671 public Object getValue() { 673 return myValue; 674 } 675 public void setValue(Object value) throws IllegalArgumentException ,IllegalAccessException , InvocationTargetException { 677 Object oldVal = myValue; 678 myValue = (Boolean ) value; 679 tn.fireMethod(getName(), oldVal, myValue); 680 } 681 } 682 683 public class TProperty4 extends PropertySupport { 685 private Boolean myValue = Boolean.FALSE; 686 public TProperty4(String name, boolean isWriteable) { 688 super(name, String .class, name, "", true, isWriteable); 689 } 690 public Object getValue() { 692 return myValue; 693 } 694 public void setValue(Object value) throws IllegalArgumentException ,IllegalAccessException , InvocationTargetException { 696 Object oldVal = myValue; 697 myValue = (Boolean ) value; 698 tn.fireMethod(getName(), oldVal, myValue); 699 } 700 public PropertyEditor getPropertyEditor() { 701 return new BadEditor(); 702 } 703 } 704 705 public class BadEditor extends PropertyEditorSupport implements ExPropertyEditor { 706 PropertyEnv env; 707 708 public BadEditor() { 709 } 710 711 public String [] getTags() { 712 return null; 714 } 715 716 public void attachEnv(PropertyEnv env) { 717 this.env = env; 718 env.setState(env.STATE_INVALID); 719 } 720 721 public boolean supportsCustomEditor() { 722 return false; 723 } 724 725 public void setValue(Object newValue) { 726 super.setValue(newValue); 727 } 728 729 public Object getValue() { 730 return Boolean.FALSE; 731 } 732 } 733 734 735 private static TNode tn; 736 private static TProperty tp; 737 private static TProperty2 tp1; 738 private static TProperty2 tp2; 739 private static TProperty2 tp3; 740 private static TProperty3 tp4; 741 private static TProperty4 tp5; 742 private static TEditor te; 743 private static String initEditorValue; 744 private static String initPropertyValue; 745 private static String postChangePropertyValue; 746 private static String postChangeEditorValue; 747 748 public boolean canRun() { 749 if( !ExtTestCase.canSafelyRunFocusTests() ) 750 return false; 751 752 return super.canRun(); 753 } 754 } 755 | Popular Tags |