001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: /*
043: * PropertySheetTest.java
044: *
045: * Created on August 24, 2001, 4:25 PM
046: */
047:
048: package org.openide.explorer.propertysheet;
049:
050: import java.awt.Color;
051: import java.awt.Component;
052: import java.awt.DisplayMode;
053: import java.awt.Font;
054: import java.awt.Graphics;
055: import java.awt.GraphicsEnvironment;
056: import java.awt.Image;
057: import java.awt.KeyboardFocusManager;
058: import java.awt.Point;
059: import java.awt.Rectangle;
060: import java.awt.event.KeyEvent;
061: import java.awt.event.MouseEvent;
062: import java.awt.event.WindowAdapter;
063: import java.awt.event.WindowEvent;
064: import java.awt.image.BufferedImage;
065: import org.openide.*;
066: import org.openide.nodes.*;
067: import org.openide.explorer.propertysheet.*;
068: import org.openide.explorer.propertysheet.editors.*;
069: import java.beans.*;
070: import java.lang.reflect.*;
071: import javax.swing.*;
072: import javax.swing.ImageIcon;
073: import junit.framework.*;
074: import junit.textui.TestRunner;
075: import org.netbeans.junit.*;
076: import org.openide.util.Lookup;
077: import org.openide.util.Utilities;
078:
079: /** Tests property marking functionality and the ability of a Property to
080: * provide a "postSetAction" action hint, which will be run if the user
081: * successfully changes the property value.
082: */
083: public class ComboTest extends NbTestCase {
084: private static boolean setup = false;
085:
086: static {
087: registerPropertyEditors();
088: }
089:
090: public static void registerPropertyEditors() {
091: //org.netbeans.core.startup.Main.registerPropertyEditors();
092: }
093:
094: public ComboTest(String name) {
095: super (name);
096: }
097:
098: static SheetTable tb = null;
099: static JFrame jf = null;
100:
101: /*
102: * This test creates a Property, Editor and Node. First test checks if initialized
103: * editor contains the same value as property. The second checks if the property
104: * value is changed if the same change will be done in the editor.
105: */
106: protected void setUp() throws Exception {
107: if (setup)
108: return;
109:
110: try {
111:
112: tp = new TProperty("oh", true);
113: tp1 = new TProperty2("the", true);
114: postSetAction = new PostSetAction();
115:
116: tn = new TNode();
117: // PropUtils.forceRadioButtons=true;
118: final PropertySheet ps = new PropertySheet();
119:
120: //ensure no stored value in preferences:
121: ps.setCurrentNode(tn);
122: sleep();
123: ps.setSortingMode(PropertySheet.UNSORTED);
124:
125: jf = new JFrame();
126: jf.getContentPane().add(ps);
127: jf.setLocation(20, 20);
128: jf.setSize(300, 400);
129: new WaitWindow(jf);
130: tb = ps.table;
131:
132: SwingUtilities.invokeLater(new Runnable() {
133: public void run() {
134: try {
135: ps.setSortingMode(ps.SORTED_BY_NAMES);
136: } catch (Exception e) {
137: }
138: }
139: });
140:
141: } catch (Exception e) {
142: e.printStackTrace();
143: fail("FAILED - Exception thrown " + e.getClass().toString());
144: } finally {
145: setup = true;
146: }
147: }
148:
149: public void tearDown() {
150: jf.hide();
151: jf.dispose();
152: }
153:
154: static boolean checkGraphicsEnvironment() {
155: if (GraphicsEnvironment.getLocalGraphicsEnvironment()
156: .isHeadless()) {
157: System.err
158: .println("Cannot run test in a headless environment");
159: }
160: DisplayMode dm = GraphicsEnvironment
161: .getLocalGraphicsEnvironment().getDefaultScreenDevice()
162: .getDisplayMode();
163: int i = dm.getBitDepth();
164: if (i == dm.BIT_DEPTH_MULTI || i >= 16) {
165: return true;
166: }
167: return false;
168: }
169:
170: public void testFoo() throws Exception {
171: }
172:
173: private static class WaitWindow extends WindowAdapter {
174: boolean shown = false;
175:
176: public WaitWindow(JFrame f) {
177: f.addWindowListener(this );
178: f.show();
179: if (!shown) {
180: synchronized (this ) {
181: try {
182: wait(5000);
183: } catch (Exception e) {
184: }
185: }
186: }
187: }
188:
189: public void windowOpened(WindowEvent e) {
190: shown = true;
191: synchronized (this ) {
192: notifyAll();
193: ((JFrame) e.getSource()).removeWindowListener(this );
194: }
195: }
196: }
197:
198: private static final int SLEEP_LENGTH = 1000;
199:
200: private void sleep() {
201: //useful when running interactively
202:
203: try {
204: // Thread.currentThread().sleep(800);
205: //jf.getTreeLock().wait();
206: SwingUtilities.invokeAndWait(new Runnable() {
207: public void run() {
208: System.currentTimeMillis();
209: }
210: });
211: //jf.getTreeLock().wait();
212: SwingUtilities.invokeAndWait(new Runnable() {
213: public void run() {
214: System.currentTimeMillis();
215: }
216: });
217: } catch (Exception e) {
218: }
219:
220: }
221:
222: private static Color checkColor = null;
223: private Exception throwMe = null;
224:
225: private static int count = 0;
226:
227: /** Asserts that a pixel at a given position in an image matches a
228: * pixel in a given position in a component */
229: private synchronized void assertPixelFromImage(final Image i,
230: final Component c, final int imageX, final int imageY,
231: final int compX, final int compY) throws Exception {
232: final BufferedImage bi = i instanceof BufferedImage ? (BufferedImage) i
233: : toBufferedImage(i);
234: throwMe = null;
235: sleep();
236:
237: int rgb = bi.getRGB(imageX, imageY);
238: Color color = new Color(rgb);
239:
240: //uncomment the code below for diagnosing painting problems
241: //and seeing which pixel you'return really checking
242: JFrame jf = new JFrame("assertPixelFromImage " + count
243: + " (look for the yellow line)") {
244: public void paint(Graphics g) {
245: new ImageIcon(bi).paintIcon(this , g, 25, 25);
246: g.setColor(Color.YELLOW);
247: g.drawLine(imageX + 20, imageY + 25, imageX + 25,
248: imageY + 25);
249: }
250: };
251: jf.setLocation(500, 500);
252: jf.setSize(100, 100);
253: jf.show();
254:
255: try {
256: assertPixel(c, color, compX, compY);
257: } catch (Exception e) {
258: throwMe = e;
259: }
260: if (throwMe != null) {
261: throw throwMe;
262: }
263: }
264:
265: private Exception throwMe2 = null;
266:
267: private synchronized void assertPixel(final Component c,
268: final Color toMatch, final int x, final int y)
269: throws Exception {
270: sleep();
271: throwMe2 = null;
272: if (true) {
273: doAssertPixel(c, toMatch, x, y);
274: return;
275: }
276: SwingUtilities.invokeAndWait(new Runnable() {
277: public void run() {
278: try {
279: doAssertPixel(c, toMatch, x, y);
280: } catch (Exception e) {
281: throwMe2 = e;
282: }
283: }
284: });
285: if (throwMe2 != null) {
286: throw throwMe2;
287: }
288: }
289:
290: private synchronized void doAssertPixel(final Component c,
291: final Color toMatch, final int x, final int y)
292: throws Exception {
293: final BufferedImage bi = new BufferedImage(700, 700,
294: BufferedImage.TYPE_INT_RGB);
295:
296: sleep();
297: ((JComponent) c).paintAll(bi.getGraphics());
298: sleep();
299: int[] cArr = new int[3];
300: bi.getData().getPixel(x, y, cArr);
301: checkColor = new Color(cArr[0], cArr[1], cArr[2]);
302:
303: //uncomment the code below for diagnosing painting problems
304: //and seeing which pixel you'return really checking
305: JFrame jf = new JFrame("Assert pixel test " + count
306: + " (look for the yellow line)") {
307: public void paint(Graphics g) {
308: new ImageIcon(bi).paintIcon(this , g, 25, 25);
309: g.setColor(Color.YELLOW);
310: g.drawLine(x + 20, y + 25, x + 25, y + 25);
311: }
312: };
313: jf.setLocation(400, 400);
314: jf.setSize(500, 500);
315: jf.show();
316: count++;
317:
318: assertEquals("Color at " + x + "," + y + " does not match",
319: toMatch, checkColor);
320:
321: }
322:
323: private void clickOn(final SheetTable tb, final int row,
324: final int col) throws Exception {
325: SwingUtilities.invokeAndWait(new Runnable() {
326: public void run() {
327: Rectangle r = tb.getCellRect(row, col, false);
328: Point toClick = r.getLocation();
329: toClick.x += 15;
330: toClick.y += 3;
331: MouseEvent me = new MouseEvent(tb,
332: MouseEvent.MOUSE_PRESSED, System
333: .currentTimeMillis(),
334: MouseEvent.BUTTON1_MASK, toClick.x, toClick.y,
335: 2, false);
336: tb.dispatchEvent(me);
337: }
338: });
339: sleep();
340: }
341:
342: private void releaseKey(final Component target, final int key)
343: throws Exception {
344: SwingUtilities.invokeAndWait(new Runnable() {
345: public void run() {
346: KeyEvent ke = new KeyEvent(target,
347: KeyEvent.KEY_RELEASED, System
348: .currentTimeMillis(), 0, key,
349: (char) key);
350: target.dispatchEvent(ke);
351: }
352: });
353: sleep();
354: }
355:
356: private void pressKey(final Component target, final int key)
357: throws Exception {
358: SwingUtilities.invokeAndWait(new Runnable() {
359: public void run() {
360: KeyEvent ke = new KeyEvent(target,
361: KeyEvent.KEY_PRESSED, System
362: .currentTimeMillis(), 0, key,
363: (char) key);
364: target.dispatchEvent(ke);
365: }
366: });
367: sleep();
368: }
369:
370: private void typeKey(final Component target, final int key)
371: throws Exception {
372: SwingUtilities.invokeAndWait(new Runnable() {
373: public void run() {
374: KeyEvent ke = new KeyEvent(target, KeyEvent.KEY_TYPED,
375: System.currentTimeMillis(), 0,
376: KeyEvent.VK_UNDEFINED, (char) key);
377: target.dispatchEvent(ke);
378: }
379: });
380: sleep();
381: }
382:
383: //Node definition
384: public class TNode extends AbstractNode {
385: //create Node
386: public TNode() {
387: super (Children.LEAF);
388: setName("TNode"); // or, super.setName if needed
389: setDisplayName("TNode");
390: }
391:
392: //clone existing Node
393: public Node cloneNode() {
394: return new TNode();
395: }
396:
397: public void addProp(Node.Property p) {
398: props.put(p);
399: this .firePropertyChange(PROP_PROPERTY_SETS, null, null);
400: this .firePropertySetsChange(null, null);
401: }
402:
403: Sheet sheet = null;
404: Sheet.Set props = null;
405:
406: // Create a property sheet:
407: protected Sheet createSheet() {
408: sheet = super .createSheet();
409: // Make sure there is a "Properties" set:
410: props = sheet.get(Sheet.PROPERTIES);
411: if (props == null) {
412: props = Sheet.createPropertiesSet();
413: sheet.put(props);
414: }
415: props.put(tp);
416: props.put(tp1);
417: return sheet;
418: }
419:
420: // Method firing changes
421: public void fireMethod(String s, Object o1, Object o2) {
422: firePropertyChange(s, o1, o2);
423: }
424: }
425:
426: public static void main(String args[]) {
427: LookAndFeel lf = UIManager.getLookAndFeel();
428: TestRunner.run(suite());
429: }
430:
431: public static Test suite() {
432: return new ComboTestSuite();
433: }
434:
435: private static final class ComboTestSuite extends NbTestSuite {
436: public ComboTestSuite() {
437: super (ComboTest.class);
438: }
439:
440: public void run(final TestResult tr) {
441: super .run(tr);
442: }
443: }
444:
445: // Property definition
446: public class TProperty extends PropertySupport {
447: private Object myValue = "Value";
448:
449: // Create new Property
450: public TProperty(String name, boolean isWriteable) {
451: super (name, String.class, name, "", true, isWriteable);
452: }
453:
454: // get property value
455: public Object getValue() {
456: return myValue;
457: }
458:
459: // set property value
460: public void setValue(Object value)
461: throws IllegalArgumentException,
462: IllegalAccessException, InvocationTargetException {
463: Object oldVal = myValue;
464: myValue = value;
465: tn.fireMethod(getName(), oldVal, myValue);
466: }
467:
468: // get the property editor
469: public PropertyEditor getPropertyEditor() {
470: return new TEditor();
471: }
472:
473: public Object getValue(String key) {
474: if ("nameIcon".equals(key)) {
475: return new NameIcon();
476: } else if ("valueIcon".equals(key)) {
477: return new ValueIcon();
478: } else if ("postSetAction".equals(key)) {
479: return postSetAction;
480: }
481: return super .getValue(key);
482: }
483: }
484:
485: // Editor definition
486: public class TEditor extends PropertyEditorSupport {
487: PropertyEnv env;
488:
489: // Create new TEditor
490: public TEditor() {
491: }
492:
493: /*
494: * This method is called by the IDE to pass
495: * the environment to the property editor.
496: */
497: public void attachEnv(PropertyEnv env) {
498: this .env = env;
499: }
500:
501: // Set that this Editor doesn't support custom Editor
502: public boolean supportsCustomEditor() {
503: return false;
504: }
505:
506: // Set the Property value threw the Editor
507: public void setValue(Object newValue) {
508: super .setValue(newValue);
509: }
510:
511: public String getAsText() {
512: return getValue() == null ? "null" : getValue().toString();
513: }
514: }
515:
516: public class TagsEditor extends PropertyEditorSupport implements
517: ExPropertyEditor {
518: PropertyEnv env;
519:
520: public TagsEditor() {
521: }
522:
523: public String[] getTags() {
524: return new String[] { "a", "b", "c", "d", "Value" };
525: }
526:
527: public void attachEnv(PropertyEnv env) {
528: this .env = env;
529:
530: env.getFeatureDescriptor().setValue("canEditAsText",
531: Boolean.TRUE);
532: }
533:
534: public boolean supportsCustomEditor() {
535: return false;
536: }
537:
538: public void setValue(Object newValue) {
539: super .setValue(newValue);
540: }
541: }
542:
543: // Property definition
544: public class TProperty2 extends PropertySupport {
545: private Object myValue = "Value";
546:
547: // Create new Property
548: public TProperty2(String name, boolean isWriteable) {
549: super (name, Object.class, name, "", true, isWriteable);
550: }
551:
552: // get property value
553: public Object getValue() {
554: return myValue;
555: }
556:
557: // set property value
558: public void setValue(Object value)
559: throws IllegalArgumentException,
560: IllegalAccessException, InvocationTargetException {
561: Object oldVal = myValue;
562: myValue = value;
563: tn.fireMethod(getName(), oldVal, myValue);
564: }
565:
566: // get the property editor
567: public PropertyEditor getPropertyEditor() {
568: return new TagsEditor();
569: }
570:
571: public Object getValue(String key) {
572: if ("canEditAsText".equals(key)) {
573: return Boolean.TRUE;
574: } else {
575: return super .getValue(key);
576: }
577: }
578: }
579:
580: // Property definition
581: public class TProperty3 extends PropertySupport {
582: private Boolean myValue = Boolean.FALSE;
583:
584: // Create new Property
585: public TProperty3(String name, boolean isWriteable) {
586: super (name, Boolean.class, name, "", true, isWriteable);
587: }
588:
589: // get property value
590: public Object getValue() {
591: return myValue;
592: }
593:
594: // set property value
595: public void setValue(Object value)
596: throws IllegalArgumentException,
597: IllegalAccessException, InvocationTargetException {
598: Object oldVal = myValue;
599: myValue = (Boolean) value;
600: tn.fireMethod(getName(), oldVal, myValue);
601: }
602:
603: public Object getValue(String key) {
604: if ("nameIcon".equals(key)) {
605: return new NameIcon();
606: } else if ("valueIcon".equals(key)) {
607: return new ValueIcon();
608: } else if ("postSetAction".equals(key)) {
609: return postSetAction;
610: }
611: return super .getValue(key);
612: }
613:
614: public PropertyEditor getPropertyEditor() {
615: return new WrapperEx(super .getPropertyEditor());
616: }
617:
618: public class WrapperEx implements ExPropertyEditor {
619: private PropertyEditor orig;
620:
621: public WrapperEx(PropertyEditor orig) {
622: this .orig = orig;
623: }
624:
625: public void attachEnv(PropertyEnv env) {
626: env
627: .setState(myValue == Boolean.FALSE ? env.STATE_INVALID
628: : env.STATE_VALID);
629: }
630:
631: public void addPropertyChangeListener(
632: PropertyChangeListener listener) {
633: orig.addPropertyChangeListener(listener);
634: }
635:
636: public String getAsText() {
637: return orig.getAsText();
638: }
639:
640: public java.awt.Component getCustomEditor() {
641: return orig.getCustomEditor();
642: }
643:
644: public String getJavaInitializationString() {
645: return orig.getJavaInitializationString();
646: }
647:
648: public String[] getTags() {
649: return orig.getTags();
650: }
651:
652: public Object getValue() {
653: return orig.getValue();
654: }
655:
656: public boolean isPaintable() {
657: return orig.isPaintable();
658: }
659:
660: public void paintValue(java.awt.Graphics gfx,
661: java.awt.Rectangle box) {
662: orig.paintValue(gfx, box);
663: }
664:
665: public void removePropertyChangeListener(
666: PropertyChangeListener listener) {
667: orig.removePropertyChangeListener(listener);
668: }
669:
670: public void setAsText(String text)
671: throws java.lang.IllegalArgumentException {
672: orig.setAsText(text);
673: }
674:
675: public void setValue(Object value) {
676: orig.setValue(value);
677: }
678:
679: public boolean supportsCustomEditor() {
680: return orig.supportsCustomEditor();
681: }
682: }
683: }
684:
685: public class BadEditor extends PropertyEditorSupport implements
686: ExPropertyEditor {
687: PropertyEnv env;
688:
689: public BadEditor() {
690: }
691:
692: public String[] getTags() {
693: //return new String[] {"a","b","c","d","Value"};
694: return null;
695: }
696:
697: public void attachEnv(PropertyEnv env) {
698: this .env = env;
699: env.setState(env.STATE_INVALID);
700: }
701:
702: public boolean supportsCustomEditor() {
703: return false;
704: }
705:
706: public void setValue(Object newValue) {
707: super .setValue(newValue);
708: }
709: }
710:
711: private class NameIcon implements Icon {
712:
713: public int getIconHeight() {
714: return 12;
715: }
716:
717: public int getIconWidth() {
718: return 12;
719: }
720:
721: public void paintIcon(Component c, Graphics g, int x, int y) {
722: Color col = g.getColor();
723: try {
724: g.setColor(Color.BLUE);
725: g.drawRect(x, y, getIconWidth(), getIconHeight());
726: g.fillRect(x + 3, y + 3, getIconWidth() - 5,
727: getIconHeight() - 5);
728: } finally {
729: g.setColor(col);
730: }
731: }
732:
733: }
734:
735: private class ValueIcon implements Icon {
736:
737: public int getIconHeight() {
738: return 12;
739: }
740:
741: public int getIconWidth() {
742: return 12;
743: }
744:
745: public void paintIcon(Component c, Graphics g, int x, int y) {
746: Color col = g.getColor();
747: try {
748: g.setColor(Color.GREEN);
749: g.drawRect(x, y, getIconWidth(), getIconHeight());
750: g.fillRect(x + 3, y + 3, getIconWidth() - 5,
751: getIconHeight() - 5);
752: } finally {
753: g.setColor(col);
754: }
755: }
756: }
757:
758: private class PostSetAction extends AbstractAction {
759: boolean performed = false;
760:
761: public void assertPerformed() {
762: assertTrue("Action was not performed", performed);
763: performed = false;
764: }
765:
766: public void assertNotPerformed() {
767: assertTrue(
768: "Action should not be performed before an appropriate event is triggered",
769: !performed);
770: }
771:
772: public void actionPerformed(java.awt.event.ActionEvent e) {
773: performed = true;
774: }
775:
776: }
777:
778: private static TNode tn;
779: private static TProperty tp;
780: private static TProperty2 tp1;
781: private static TEditor te;
782: private static PostSetAction postSetAction;
783: private static String initEditorValue;
784: private static String initPropertyValue;
785: private static String postChangePropertyValue;
786: private static String postChangeEditorValue;
787:
788: //Shamelessly stolen from util.IconManager
789: private static final BufferedImage toBufferedImage(Image img) {
790: // load the image
791: new javax.swing.ImageIcon(img);
792: java.awt.image.BufferedImage rep = createBufferedImage(img
793: .getWidth(null), img.getHeight(null));
794: java.awt.Graphics g = rep.createGraphics();
795: g.drawImage(img, 0, 0, null);
796: g.dispose();
797: img.flush();
798: return rep;
799: }
800:
801: /** Creates BufferedImage 16x16 and Transparency.BITMASK */
802: private static final java.awt.image.BufferedImage createBufferedImage(
803: int width, int height) {
804: java.awt.image.ColorModel model = java.awt.GraphicsEnvironment
805: .getLocalGraphicsEnvironment().getDefaultScreenDevice()
806: .getDefaultConfiguration().getColorModel(
807: java.awt.Transparency.BITMASK);
808: java.awt.image.BufferedImage buffImage = new java.awt.image.BufferedImage(
809: model, model.createCompatibleWritableRaster(width,
810: height), model.isAlphaPremultiplied(), null);
811: return buffImage;
812: }
813:
814: }
|