1 19 20 package org.openide.explorer.propertysheet; 21 22 import com.sun.java.swing.plaf.windows.WindowsLookAndFeel; 23 import java.awt.BorderLayout ; 24 import java.awt.Component ; 25 import java.awt.FlowLayout ; 26 import java.awt.Point ; 27 import java.awt.event.FocusEvent ; 28 import java.awt.event.FocusListener ; 29 import java.awt.event.KeyEvent ; 30 import java.awt.event.MouseEvent ; 31 import java.awt.event.WindowAdapter ; 32 import java.awt.event.WindowEvent ; 33 import java.beans.PropertyEditor ; 34 import java.beans.PropertyEditorSupport ; 35 import java.lang.reflect.InvocationTargetException ; 36 import javax.swing.JFrame ; 37 import javax.swing.JLabel ; 38 import javax.swing.JPanel ; 39 import javax.swing.SwingUtilities ; 40 import javax.swing.border.Border ; 41 import javax.swing.border.TitledBorder ; 42 import javax.swing.event.ChangeEvent ; 43 import javax.swing.event.ChangeListener ; 44 import org.netbeans.junit.NbTestCase; 45 import org.netbeans.modules.openide.explorer.UIException; 46 import org.openide.ErrorManager; 47 import org.openide.nodes.AbstractNode; 48 import org.openide.nodes.Children; 49 import org.openide.nodes.Node; 50 import org.openide.nodes.PropertySupport; 51 import org.openide.nodes.Sheet; 52 53 54 public class RendererDisplayerTest extends NbTestCase { 55 56 static { 57 ComboTest.registerPropertyEditors(); 58 } 59 60 public RendererDisplayerTest(String name) { 61 super(name); 62 } 63 68 69 RendererPropertyDisplayer basicRen; 70 RendererPropertyDisplayer tagsRen1; 71 RendererPropertyDisplayer tagsRen2; 72 RendererPropertyDisplayer tagsRen3; 73 RendererPropertyDisplayer boolRen; 74 RendererPropertyDisplayer custRen; 75 RendererPropertyDisplayer custRen2; 76 RendererPropertyDisplayer exRen; 77 RendererPropertyDisplayer numRen; 78 RendererPropertyDisplayer edRen; 79 80 private TNode tn; 81 private BasicProperty basicProp; 82 private TagsProperty tags1; 83 private TagsProperty tags2; 84 private TagsProperty tags3; 85 private BooleanProperty booleanProp; 86 private EditorCustom ec; 87 private CustomProperty customProp; 88 private CustomProperty customProp2; 89 private BasicEditor te; 90 private boolean setup=false; 91 private JFrame jf=null; 92 private JPanel jp=null; 93 private int SLEEP_LENGTH=10; 94 95 protected void tearDown() { 96 if (jf != null) { 97 } 100 } 101 102 protected void setUp() throws Exception { 103 PropUtils.forceRadioButtons =false; 106 if (setup) return; 107 basicProp= new BasicProperty("basicProp", true); 109 tags1 = new TagsProperty("tags1", true, new String [] {"What","is","the","meaning","of","life"}); 110 tags2 = new TagsProperty("tags2", true, new String [] {"Austrolopithecines","automatically","engender","every","one"}); 111 tags3 = new TagsProperty("tags3", true, new String [] {"Behold","the","power","of","cheese"}); 112 booleanProp = new BooleanProperty("I am boolean, hear me roar", true); 113 customProp = new CustomProperty("CustomProp", true); 114 customProp2 = new CustomProperty("CustomProp2", true); 115 ExceptionProperty exProp = new ExceptionProperty("Exception prop", true); 116 NumProperty numProp = new NumProperty("Int prop", true); 117 EditableNumProperty edProp = new EditableNumProperty("Editable", true); 118 119 120 te = new BasicEditor(); 122 ec = new EditorCustom(); 123 tn = new TNode(); 125 126 jf = new JFrame (); 127 jf.getContentPane().setLayout(new BorderLayout ()); 128 jp = new JPanel (); 129 jp.setLayout(new FlowLayout ()); 130 jf.getContentPane().add(jp, BorderLayout.CENTER); 131 jf.setLocation(20,20); 132 jf.setSize(600, 200); 133 134 basicRen = new RendererPropertyDisplayer(basicProp); 135 tagsRen1 = new RendererPropertyDisplayer(tags1); 136 tagsRen2 = new RendererPropertyDisplayer(tags2); 137 tagsRen3 = new RendererPropertyDisplayer(tags3); 138 boolRen = new RendererPropertyDisplayer(booleanProp); 139 custRen = new RendererPropertyDisplayer(customProp); 140 custRen2 = new RendererPropertyDisplayer(customProp2); 141 exRen = new RendererPropertyDisplayer(exProp); 142 numRen = new RendererPropertyDisplayer(numProp); 143 edRen = new RendererPropertyDisplayer(edProp); 144 145 tagsRen2.setRadioButtonMax(10); 146 147 jp.add(basicRen); 148 jp.add(tagsRen1); 149 jp.add(tagsRen2); 150 jp.add(tagsRen3); 151 jp.add(boolRen); 152 jp.add(custRen); 153 jp.add(custRen2); 154 jp.add(exRen); 155 jp.add(numRen); 156 jp.add(edRen); 157 new WaitWindow(jf); setup = true; 159 } 160 161 public void testUseTitle() throws Exception { 162 sleep(); 163 sleep(); 164 tagsRen2.setUseLabels(true); 165 sleep(); 166 167 Component c = tagsRen2.getRenderer(tagsRen2); 168 if (!(c instanceof InplaceEditor)) { 169 fail("Did not get an inplace editor for a renderer"); 170 } 171 InplaceEditor ine = (InplaceEditor) c; 172 InplaceEditor innermost = PropUtils.findInnermostInplaceEditor(ine); 173 if (!(innermost instanceof RadioInplaceEditor)) { 174 fail("Should have gotten an instance of RadioInplaceEditor, not " + innermost); 175 } 176 177 Border b = innermost.getComponent().getBorder(); 178 assertNotNull("Border should not be null when set to use labels", b); 179 180 assertTrue("Border should be an instance of TitledBorder, not " + b, b instanceof TitledBorder ); 181 182 183 boolRen.setUseLabels(true); 184 c = boolRen.getRenderer(boolRen); 185 if (!(c instanceof InplaceEditor)) { 186 fail("Did not get an inplace editor for a renderer"); 187 } 188 ine = (InplaceEditor) c; 189 innermost = PropUtils.findInnermostInplaceEditor(ine); 190 if (!(innermost instanceof CheckboxInplaceEditor)) { 191 fail("Should have gotten an instance of RadioInplaceEditor, not " + innermost); 192 } 193 CheckboxInplaceEditor cb = (CheckboxInplaceEditor) innermost; 194 assertEquals("If using labels, checkbox text should be the property display name", cb.getText(), boolRen.getProperty().getDisplayName()); 195 } 196 197 private class FL implements FocusListener { 198 private FocusEvent gainedEvent=null; 199 private FocusEvent lostEvent=null; 200 private int gainedCount=0; 201 private int lostCount=0; 202 public void assertGained() { 203 assertNotNull("No focus gained received after clicking on an editable renderer", gainedEvent); 204 assertTrue("Received wrong number of focus gained events for a single click on a renderer " + gainedCount, gainedCount == 1); 205 } 206 207 public void assertLost() { 208 assertNotNull("No focus lost event received after clicking away from a focused, editable renderer", lostEvent); 209 assertTrue("Received wrong number of focus lost events for a single click away from a focused renderer" + lostCount, lostCount == 1); 210 } 211 212 public void focusGained(FocusEvent e) { 213 gainedEvent = e; 214 gainedCount++; 215 } 216 217 public void focusLost(FocusEvent e) { 218 lostEvent = e; 219 lostCount++; 220 } 221 } 222 223 private class CL implements ChangeListener { 224 225 private ChangeEvent e; 226 public void assertEvent(String msg) { 227 sleep(); assertNotNull(msg, e); 229 e = null; 230 } 231 232 public void assertNoEvent(String msg) { 233 sleep(); 234 assertNull(e); 235 e = null; 236 } 237 238 public void stateChanged(ChangeEvent e) { 239 this.e = e; 240 } 241 242 } 243 244 private static class TestGCVal extends Object { 245 public String toString() { 246 return "TestGCVal"; 247 } 248 } 249 250 private static class WaitWindow extends WindowAdapter { 251 boolean shown=false; 252 public WaitWindow(JFrame f) { 253 f.addWindowListener(this); 254 f.show(); 255 if (!shown) { 256 synchronized(this) { 257 try { 258 wait(5000); 260 } catch (Exception e) {} 261 } 262 } 263 } 264 265 public void windowOpened(WindowEvent e) { 266 shown = true; 267 synchronized(this) { 268 notifyAll(); 270 ((JFrame ) e.getSource()).removeWindowListener(this); 271 } 272 } 273 } 274 275 private void sleep() { 276 278 try { 279 Thread.currentThread().sleep(SLEEP_LENGTH); 280 } catch (InterruptedException ie) { 281 } 283 284 285 286 288 try { 289 SwingUtilities.invokeAndWait(new Runnable () { 291 public void run() { 292 System.currentTimeMillis(); 293 } 294 }); 295 SwingUtilities.invokeAndWait(new Runnable () { 297 public void run() { 298 System.currentTimeMillis(); 299 } 300 }); 301 } catch (Exception e) { 302 } 303 304 305 } 306 307 private void changeProperty(final RendererPropertyDisplayer ren, final Node.Property newProp) throws Exception { 308 SwingUtilities.invokeAndWait(new Runnable () { 309 public void run() { 310 ren.setProperty(newProp); 311 } 312 }); 313 } 314 315 private void clickOn(final RendererPropertyDisplayer ren, final int fromRight, final int fromTop) throws Exception { 316 SwingUtilities.invokeAndWait(new Runnable () { 317 public void run() { 318 Point toClick = new Point (ren.getWidth() - fromRight, fromTop); 319 Component target=ren.getComponentAt(toClick); 320 toClick = SwingUtilities.convertPoint(ren, toClick, target); 321 System.err.println("Target component is " + target.getClass().getName() + " - " + target + " clicking at " + toClick); 322 323 MouseEvent me = new MouseEvent (target, MouseEvent.MOUSE_PRESSED, System.currentTimeMillis(), MouseEvent.BUTTON1_MASK, toClick.x, toClick.y, 2, false); 324 target.dispatchEvent(me); 325 me = new MouseEvent (target, MouseEvent.MOUSE_RELEASED, System.currentTimeMillis(), MouseEvent.BUTTON1_MASK, toClick.x, toClick.y, 2, false); 326 target.dispatchEvent(me); 327 me = new MouseEvent (target, MouseEvent.MOUSE_CLICKED, System.currentTimeMillis(), MouseEvent.BUTTON1_MASK, toClick.x, toClick.y, 2, false); 328 } 329 }); 330 sleep(); 331 } 332 333 private void clickOn(final RendererPropertyDisplayer ren) throws Exception { 334 SwingUtilities.invokeAndWait(new Runnable () { 335 public void run() { 336 Point toClick = new Point (5,5); 337 Component target=ren.getComponentAt(toClick); 338 MouseEvent me = new MouseEvent (target, MouseEvent.MOUSE_PRESSED, System.currentTimeMillis(), MouseEvent.BUTTON1_MASK, toClick.x, toClick.y, 2, false); 339 target.dispatchEvent(me); 340 } 341 }); 342 sleep(); 343 } 344 345 private void setEnabled(final RendererPropertyDisplayer ren,final boolean val) throws Exception { 346 SwingUtilities.invokeAndWait(new Runnable () { 347 public void run() { 348 ren.setEnabled(val); 349 } 350 }); 351 sleep(); 352 } 353 354 private Exception throwMe = null; 355 private String flushResult = null; 356 private String flushValue(final RendererPropertyDisplayer ren) throws Exception { 357 SwingUtilities.invokeAndWait(new Runnable () { 358 public void run() { 359 try { 360 } catch (Exception e) { 362 throwMe = e; 363 flushResult = null; 364 } 365 } 366 }); 367 if (throwMe != null) { 368 try { 369 throw throwMe; 370 } finally { 371 throwMe = null; 372 } 373 } 374 return flushResult; 375 } 376 377 378 private void releaseKey(final Component target, final int key) throws Exception { 379 SwingUtilities.invokeAndWait(new Runnable () { 380 public void run() { 381 KeyEvent ke = new KeyEvent (target, KeyEvent.KEY_RELEASED, System.currentTimeMillis(), 0, key, (char) key); 382 target.dispatchEvent(ke); 383 } 384 }); 385 sleep(); 386 } 387 388 private void pressKey(final Component target, final int key) throws Exception { 389 SwingUtilities.invokeAndWait(new Runnable () { 390 public void run() { 391 KeyEvent ke = new KeyEvent (target, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), 0, key, (char) key); 392 target.dispatchEvent(ke); 393 } 394 }); 395 sleep(); 396 } 397 398 private void shiftPressKey(final Component target, final int key) throws Exception { 399 SwingUtilities.invokeAndWait(new Runnable () { 400 public void run() { 401 KeyEvent ke = new KeyEvent (target, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), KeyEvent.SHIFT_MASK, key, (char) key); 402 target.dispatchEvent(ke); 403 } 404 }); 405 sleep(); 406 } 407 408 409 private void typeKey(final Component target, final int key) throws Exception { 410 SwingUtilities.invokeAndWait(new Runnable () { 411 public void run() { 412 KeyEvent ke = new KeyEvent (target, KeyEvent.KEY_TYPED, System.currentTimeMillis(), 0, KeyEvent.VK_UNDEFINED, (char) key); 413 target.dispatchEvent(ke); 414 } 415 }); 416 sleep(); 417 } 418 419 public class TNode extends AbstractNode { 421 public TNode() { 423 super(Children.LEAF); 424 setName("TNode"); setDisplayName("TNode"); 426 createSheet(); 427 } 428 public Node cloneNode() { 430 return new TNode(); 431 } 432 433 public void addProp(Node.Property p) { 434 props.put(p); 435 this.firePropertyChange(PROP_PROPERTY_SETS, null, null); 436 this.firePropertySetsChange(null, null); 437 } 438 439 Sheet sheet=null; 440 Sheet.Set props=null; 441 protected Sheet createSheet() { 443 sheet = super.createSheet(); 444 props = sheet.get(Sheet.PROPERTIES); 446 if (props == null) { 447 props = Sheet.createPropertiesSet(); 448 sheet.put(props); 449 } 450 props.put(basicProp); 451 props.put(tags1); 452 props.put(tags2); 453 props.put(tags3); 454 props.put(booleanProp); 455 props.put(customProp); 456 457 return sheet; 458 } 459 public void fireMethod(String s, Object o1, Object o2) { 461 firePropertyChange(s,o1,o2); 462 } 463 } 464 465 public class BasicProperty extends PropertySupport { 467 private Object myValue = "Value"; 468 public BasicProperty(String name, boolean isWriteable) { 470 super(name, Object .class, name, "", true, isWriteable); 471 } 472 public Object getValue() { 474 return myValue; 475 } 476 public void setValue(Object value) throws IllegalArgumentException ,IllegalAccessException , InvocationTargetException { 478 Object oldVal = myValue; 479 myValue = value; 480 tn.fireMethod(getName(), oldVal, myValue); 481 } 482 public PropertyEditor getPropertyEditor() { 484 return te; 485 } 486 } 487 488 public class BasicEditor extends PropertyEditorSupport implements ExPropertyEditor { 490 PropertyEnv env; 491 492 public BasicEditor() { 494 } 495 496 500 public void attachEnv(PropertyEnv env) { 501 this.env = env; 502 } 503 504 public boolean supportsCustomEditor() { 506 return false; 507 } 508 509 public void setValue(Object newValue) { 511 super.setValue(newValue); 512 } 513 514 public String getAsText() { 515 return getValue() == null ? "null" : getValue().toString(); 516 } 517 } 518 519 520 private static class PseudoWindowsLookAndFeel extends WindowsLookAndFeel { 521 public boolean isSupportedLookAndFeel() { 522 return true; 523 } 524 } 525 526 public class TagsEditor extends PropertyEditorSupport implements ExPropertyEditor { 527 PropertyEnv env; 528 String [] tags; 529 public TagsEditor(String [] tags) { 530 this.tags = tags; 531 } 532 533 public String [] getTags() { 534 return tags; 535 } 536 537 public void attachEnv(PropertyEnv env) { 538 this.env = env; 539 } 540 541 public boolean supportsCustomEditor() { 542 return false; 543 } 544 545 public void setValue(Object newValue) { 546 super.setValue(newValue); 547 } 548 549 550 } 551 552 public class TagsProperty extends PropertySupport { 554 private Object myValue = "Value"; 555 private String [] tags; 556 public TagsProperty(String name, boolean isWriteable, String [] tags) { 558 super(name, Object .class, name, "", true, isWriteable); 559 this.tags = tags; 560 } 561 public Object getValue() { 563 return myValue; 564 } 565 public void setValue(Object value) throws IllegalArgumentException ,IllegalAccessException , InvocationTargetException { 567 Object oldVal = myValue; 568 myValue = value; 569 tn.fireMethod(getName(), oldVal, myValue); 570 } 571 public PropertyEditor getPropertyEditor() { 573 return new TagsEditor(tags); 574 } 575 576 public String getShortDescription() { 577 return "I have tags!"; 578 } 579 } 580 581 public class BooleanProperty extends PropertySupport { 583 private Boolean myValue = Boolean.FALSE; 584 public BooleanProperty(String name, boolean isWriteable) { 586 super(name, Boolean .class, name, "", true, isWriteable); 587 } 588 public Object getValue() { 590 return myValue; 591 } 592 public void setValue(Object value) throws IllegalArgumentException ,IllegalAccessException , InvocationTargetException { 594 Object oldVal = myValue; 595 myValue = (Boolean ) value; 596 tn.fireMethod(getName(), oldVal, myValue); 597 } 598 } 599 600 public class CustomProperty extends PropertySupport { 601 private Object myValue = "Value"; 602 public CustomProperty(String name, boolean isWriteable) { 604 super(name, Object .class, name, "", true, isWriteable); 605 } 606 public Object getValue() { 608 return myValue; 609 } 610 public void setValue(Object value) throws IllegalArgumentException ,IllegalAccessException , InvocationTargetException { 612 Object oldVal = myValue; 613 myValue = value; 614 tn.fireMethod(getName(), oldVal, myValue); 615 } 616 public PropertyEditor getPropertyEditor() { 618 return ec; 619 } 620 } 621 622 public class ExceptionProperty extends PropertySupport { 623 private Object myValue = "Value"; 624 public ExceptionProperty(String name, boolean isWriteable) { 626 super(name, Object .class, name, "", true, isWriteable); 627 } 628 public Object getValue() { 630 return myValue; 631 } 632 public void setValue(Object value) throws IllegalArgumentException ,IllegalAccessException , InvocationTargetException { 634 Object oldVal = myValue; 635 myValue = value; 636 tn.fireMethod(getName(), oldVal, myValue); 637 } 638 public PropertyEditor getPropertyEditor() { 640 return exed; 641 } 642 } 643 644 private ExEditor exed = new ExEditor(); 645 public static class ExEditor extends PropertyEditorSupport { 646 private Object myVal="Value"; 647 public ExEditor() {} 648 public void setAsText(String val) { 649 if (val.equals("Value")) { 651 myVal = val; 652 } else { 653 IllegalArgumentException iae = new IllegalArgumentException ("No!"); 654 UIException.annotateUser(iae, "NoNo!", "Localized message", null, 655 null); 656 throw iae; 657 } 658 } 659 660 public void setValue(Object newValue) { 661 myVal = newValue; 662 firePropertyChange(); 663 } 664 665 public Object getValue() { 666 return "Value"; 667 } 668 } 669 670 671 public class EditorCustom extends PropertyEditorSupport implements ExPropertyEditor { 673 PropertyEnv env; 674 675 public EditorCustom() { 677 } 678 679 683 public void attachEnv(PropertyEnv env) { 684 this.env = env; 685 } 686 687 public boolean supportsCustomEditor() { 689 return true; 690 } 691 692 public void setValue(Object newValue) { 694 super.setValue(newValue); 695 } 696 697 public String getAsText() { 698 return getValue() == null ? "null" : getValue().toString(); 699 } 700 701 public Component getCustomEditor() { 702 return new JPanel (); 703 } 704 } 705 706 public class NumProperty extends PropertySupport { 707 private Integer myValue = new Integer (4); 708 public NumProperty(String name, boolean isWriteable) { 710 super(name, Integer .class, name, "", true, isWriteable); 711 } 712 public Object getValue() { 714 return myValue; 715 } 716 public void setValue(Object value) throws IllegalArgumentException ,IllegalAccessException , InvocationTargetException { 718 if (!(value instanceof Integer )) { 719 throw new IllegalArgumentException ("Not an integer - " + value); 720 } 721 Object oldVal = myValue; 722 myValue = (Integer ) value; 723 tn.fireMethod(getName(), oldVal, myValue); 724 } 725 public PropertyEditor getPropertyEditor() { 727 return new NumberedTagsEditor(); 728 } 729 } 730 731 public class EditableNumProperty extends TagsProperty { 732 public EditableNumProperty(String name, boolean isWriteable) { 733 super(name, isWriteable, new String []{"boo"}); 734 } 735 736 public PropertyEditor getPropertyEditor() { 737 return new RendererDisplayerTest.EditableTagsEditor(); 738 } 739 } 740 741 742 public class NumberedTagsEditor extends PropertyEditorSupport { 744 private int val=3; 745 public NumberedTagsEditor() { 747 } 748 749 public String [] getTags() { 750 return new String [] {"zero","one","two","three","four","five","six","seven"}; 751 } 752 753 754 public void setValue(Object newValue) { 756 val = ((Integer ) newValue).intValue(); 757 firePropertyChange(); 758 } 759 760 public String getAsText() { 761 return getTags()[((Integer ) getValue()).intValue()]; 762 } 763 764 public void setAsText(String txt) { 765 String [] t = getTags(); 766 for (int i=0; i < t.length; i++) { 767 if (txt.trim().equals(t[i])) { 768 setValue(new Integer (i)); 769 return; 770 } 771 } 772 IllegalArgumentException iae = new IllegalArgumentException (txt); 773 UIException.annotateUser(iae, txt, txt + " is not a valid value", 774 null, null); 775 } 776 777 public Object getValue() { 778 return new Integer (val); 779 } 780 781 public Component getCustomEditor() { 782 return new JPanel (); 783 } 784 } 785 786 public class EditableTagsEditor extends TagsEditor implements ExPropertyEditor { 787 private Object val="woof"; 788 public EditableTagsEditor() { 789 super(new String [] {"miaou","woof","moo","quack"}); 790 } 791 public void attachEnv(PropertyEnv env) { 792 env.getFeatureDescriptor().setValue("canEditAsText", Boolean.TRUE); 793 } 794 public void setAsText(String s) { 795 setValue(s); 796 } 797 public void setValue(Object val) { 798 this.val = val; 799 } 800 public Object getValue() { 801 return val; 802 } 803 public String getAsText() { 804 return val.toString(); 805 } 806 public boolean supportsCustomEditor() { 807 return true; 808 } 809 public Component getCustomEditor() { 810 return new JLabel ("You called?"); 811 } 812 } 813 } 814 | Popular Tags |