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: package org.openide.util;
043:
044: import java.awt.Component;
045: import java.awt.event.ActionEvent;
046: import java.awt.event.ActionListener;
047: import java.awt.event.KeyEvent;
048: import java.util.ArrayList;
049: import java.util.Arrays;
050: import java.util.List;
051: import java.util.Locale;
052: import javax.swing.AbstractAction;
053: import javax.swing.AbstractButton;
054: import javax.swing.Action;
055: import javax.swing.JButton;
056: import javax.swing.JMenuItem;
057: import javax.swing.JPopupMenu;
058: import javax.swing.KeyStroke;
059: import junit.framework.TestCase;
060: import org.netbeans.junit.MockServices;
061: import org.netbeans.modules.openide.util.AWTBridge;
062: import org.openide.util.actions.Presenter;
063: import org.openide.util.lookup.Lookups;
064:
065: /**
066: * @author Jiri Rechtacek et al.
067: */
068: public class UtilitiesTest extends TestCase {
069:
070: public UtilitiesTest(String testName) {
071: super (testName);
072: }
073:
074: private String originalOsName;
075:
076: protected void setUp() throws Exception {
077: super .setUp();
078: Utilities.resetOperatingSystem();
079: originalOsName = System.getProperty("os.name");
080: }
081:
082: protected void tearDown() throws Exception {
083: System.setProperty("os.name", originalOsName);
084: super .tearDown();
085: }
086:
087: public void testGetOperatingSystemWinNT() {
088: System.setProperty("os.name", "Windows NT");
089: //assertEquals ("System.getProperty (os.name) returns Windows NT", "Windows NT", System.getProperty ("os.name"));
090: assertEquals("Windows NT recognized as OS_WINNT",
091: Utilities.OS_WINNT, Utilities.getOperatingSystem());
092: }
093:
094: public void testGetOperatingSystemFreebsd() {
095: System.setProperty("os.name", "FreeBSD");
096: assertEquals("System.getProperty (os.name) returns FreeBSD",
097: "FreeBSD", System.getProperty("os.name"));
098: assertEquals("System.getProperty (os.name) returns freebsd",
099: "freebsd", System.getProperty("os.name").toLowerCase(
100: Locale.US));
101: assertEquals("FreeBSD recognized as OS_FREEBSD",
102: Utilities.OS_FREEBSD, Utilities.getOperatingSystem());
103: }
104:
105: public void testGetOperatingSystemFreeBSDLowerCase() {
106: System.setProperty("os.name", "freebsd");
107: assertEquals("FreeBSD recognized as OS_FREEBSD",
108: Utilities.OS_FREEBSD, Utilities.getOperatingSystem());
109: }
110:
111: public void testGetUnknownOperatingSystem() {
112: System.setProperty("os.name", "Unknown");
113: assertEquals("Windows NT recognized as Unknown",
114: Utilities.OS_OTHER, Utilities.getOperatingSystem());
115: }
116:
117: public void testWhatIsWinXP() {
118: System.setProperty("os.name", "Windows XP");
119: assertTrue("Windows XP isWindows", Utilities.isWindows());
120: assertFalse("Windows XP not isUnix", Utilities.isUnix());
121: }
122:
123: public void testWhatIsLinux() {
124: System.setProperty("os.name", "Linux");
125: assertFalse("Linux not isWindows", Utilities.isWindows());
126: assertTrue("Linux isUnix", Utilities.isUnix());
127: }
128:
129: public void testWhatIsMac() {
130: System.setProperty("os.name", "Mac OS X");
131: assertFalse("Mac not isWindows", Utilities.isWindows());
132: assertTrue("Mac isMac", Utilities.isMac());
133: }
134:
135: public void testWhatIsFreeBSD() {
136: System.setProperty("os.name", "freebsd");
137: assertFalse("freebsd is not isWindows", Utilities.isWindows());
138: assertTrue("freebsd isUnix", Utilities.isUnix());
139: }
140:
141: // XXX sorry, but NoCustomCursorToolkit does not compile on JDK 6:
142: // org.openide.util.UtilitiesTest.NoCustomCursorToolkit is not abstract and does not override abstract method isModalExclusionTypeSupported(java.awt.Dialog.ModalExclusionType) in java.awt.Toolkit
143: // and since Toolkit is not an interface, we can't use java.lang.reflect.Proxy to solve the problem...
144: // Filed as #6313637.
145: /*
146: public void testCustomCursorNotSupported() {
147: NoCustomCursorToolkit toolkit = new NoCustomCursorToolkit();
148: CustomToolkitComponent c = new CustomToolkitComponent( toolkit );
149: Image icon = new BufferedImage( 16, 16, BufferedImage.TYPE_BYTE_BINARY );
150: Cursor cursor = Utilities.createCustomCursor( c, icon, "junittest" );
151: assertTrue( "fallback to wait cursor", Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR ).equals( cursor ) );
152: assertTrue( "getBestCursorSize was called", toolkit.getBestCursorSizeCalled );
153: assertFalse( "no custom cursor created", toolkit.createCustomCursorCalled );
154: }
155: */
156:
157: public void testSpecialKeyworksOn14AsWell15() throws Exception {
158: KeyStroke ks = Utilities.stringToKey("C-CONTEXT_MENU");
159: assertNotNull("key stroke created", ks);
160: KeyStroke alt = ks.getKeyStroke(ks.getKeyCode(),
161: KeyEvent.ALT_MASK);
162: String s = Utilities.keyToString(alt);
163: assertEquals("Correctly converted", "A-CONTEXT_MENU", s);
164: }
165:
166: public void testSpecialKeyworksOn14AsWell15WithoutModificators()
167: throws Exception {
168: KeyStroke ks = Utilities.stringToKey("CONTEXT_MENU");
169: assertNotNull("key stroke created", ks);
170: String s = Utilities.keyToString(ks);
171: assertEquals("Correctly converted", "CONTEXT_MENU", s);
172: }
173:
174: public void testActionsToPopupWithLookup() throws Exception {
175: MockServices.setServices(AwtBridgeImpl.class);
176: final List<String> commands = new ArrayList<String>();
177: class BasicAction extends AbstractAction {
178: public BasicAction(String name) {
179: super (name);
180: }
181:
182: public void actionPerformed(ActionEvent e) {
183: commands.add((String) getValue(Action.NAME));
184: }
185: }
186: class ContextAction extends BasicAction implements
187: ContextAwareAction {
188: public ContextAction(String name) {
189: super (name);
190: }
191:
192: public Action createContextAwareInstance(
193: final Lookup actionContext) {
194: return new AbstractAction() {
195: public void actionPerformed(ActionEvent e) {
196: commands.add(ContextAction.this
197: .getValue(Action.NAME)
198: + "/"
199: + actionContext.lookup(String.class));
200: }
201: };
202: }
203: }
204: class SpecialMenuAction extends BasicAction implements
205: Presenter.Popup {
206: public SpecialMenuAction(String name) {
207: super (name);
208: }
209:
210: public JMenuItem getPopupPresenter() {
211: JMenuItem item = new JMenuItem(
212: (String) getValue(Action.NAME));
213: item.addActionListener(new ActionListener() {
214: public void actionPerformed(ActionEvent e) {
215: commands.add(((String) getValue(Action.NAME))
216: + "/popup");
217: }
218: });
219: return item;
220: }
221: }
222: Action duplicated = new BasicAction("duplicated");
223: Action[] actions = new Action[] { null, null,
224: new BasicAction("first"), duplicated, null, null,
225: new BasicAction("second"), duplicated, null,
226: new ContextAction("context"),
227: new SpecialMenuAction("presenter"), null,
228: new BasicAction("top"), new BasicAction("HIDDEN"),
229: null, new BasicAction("bottom"), null, null, };
230: Lookup l = Lookups.singleton("thing");
231: JPopupMenu menu = Utilities.actionsToPopup(actions, l);
232: for (Component element : menu.getComponents()) { // including separators
233: if (element instanceof AbstractButton) {
234: ((AbstractButton) element).doClick();
235: } else {
236: commands.add(null);
237: }
238: }
239: String[] expectedCommands = new String[] {
240: // leading separators must be stripped
241: "first", "duplicated", null, // adjacent separators must be collapsed
242: "second",
243: // do not add the same action twice
244: null, "context/thing", // ContextAwareAction was checked for
245: "presenter/popup", // Presenter.Popup was checked for
246: null, "top",
247: // exclude HIDDEN because of AwtBridgeImpl.convertComponents
248: // separator should however remain
249: null, "bottom",
250: // trailing separators must be stripped
251: };
252: assertEquals("correct generated menu", Arrays
253: .asList(expectedCommands), commands);
254: }
255:
256: /*
257: private static class CustomToolkitComponent extends Component {
258: private Toolkit customToolkit;
259:
260: public CustomToolkitComponent( Toolkit t ) {
261: this.customToolkit = t;
262: }
263:
264: public Toolkit getToolkit() {
265: return customToolkit;
266: }
267: }
268:
269: private static class NoCustomCursorToolkit extends Toolkit {
270: public FontMetrics getFontMetrics(Font font) {
271: return Toolkit.getDefaultToolkit().getFontMetrics( font );
272: }
273:
274: protected TextFieldPeer createTextField(TextField target) throws HeadlessException {
275: throw new IllegalStateException("Method not implemented");
276: }
277:
278: protected ListPeer createList(java.awt.List target) throws HeadlessException {
279: throw new IllegalStateException("Method not implemented");
280: }
281:
282: protected MenuBarPeer createMenuBar(MenuBar target) throws HeadlessException {
283: throw new IllegalStateException("Method not implemented");
284: }
285:
286: public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException {
287: return Toolkit.getDefaultToolkit().createDragSourceContextPeer( dge );
288: }
289:
290: public boolean prepareImage(Image image, int width, int height, ImageObserver observer) {
291: return Toolkit.getDefaultToolkit().prepareImage( image, width, height, observer );
292: }
293:
294: public int checkImage(Image image, int width, int height, ImageObserver observer) {
295: return Toolkit.getDefaultToolkit().checkImage( image, width, height, observer );
296: }
297:
298: protected PopupMenuPeer createPopupMenu(PopupMenu target) throws HeadlessException {
299: throw new IllegalStateException("Method not implemented");
300: }
301:
302: public PrintJob getPrintJob(Frame frame, String jobtitle, Properties props) {
303: return Toolkit.getDefaultToolkit().getPrintJob( frame, jobtitle, props );
304: }
305:
306: protected ButtonPeer createButton(Button target) throws HeadlessException {
307: throw new IllegalStateException("Method not implemented");
308: }
309:
310: public Image createImage(ImageProducer producer) {
311: return Toolkit.getDefaultToolkit().createImage( producer );
312: }
313:
314: protected CanvasPeer createCanvas(Canvas target) {
315: throw new IllegalStateException("Method not implemented");
316: }
317:
318: protected ScrollbarPeer createScrollbar(Scrollbar target) throws HeadlessException {
319: throw new IllegalStateException("Method not implemented");
320: }
321:
322: public Image getImage(String filename) {
323: return Toolkit.getDefaultToolkit().getImage( filename );
324: }
325:
326: public Image createImage(String filename) {
327: return Toolkit.getDefaultToolkit().createImage( filename );
328: }
329:
330: protected MenuPeer createMenu(Menu target) throws HeadlessException {
331: throw new IllegalStateException("Method not implemented");
332: }
333:
334: protected MenuItemPeer createMenuItem(MenuItem target) throws HeadlessException {
335: throw new IllegalStateException("Method not implemented");
336: }
337:
338: public Map mapInputMethodHighlight(InputMethodHighlight highlight) throws HeadlessException {
339: return Toolkit.getDefaultToolkit().mapInputMethodHighlight( highlight );
340: }
341:
342: public Image createImage(byte[] imagedata, int imageoffset, int imagelength) {
343: return Toolkit.getDefaultToolkit().createImage( imagedata, imageoffset, imagelength );
344: }
345:
346: public Image getImage(URL url) {
347: return Toolkit.getDefaultToolkit().getImage( url );
348: }
349:
350: protected CheckboxPeer createCheckbox(Checkbox target) throws HeadlessException {
351: throw new IllegalStateException("Method not implemented");
352: }
353:
354: public Image createImage(URL url) {
355: return Toolkit.getDefaultToolkit().createImage( url );
356: }
357:
358: protected TextAreaPeer createTextArea(TextArea target) throws HeadlessException {
359: throw new IllegalStateException("Method not implemented");
360: }
361:
362: protected FileDialogPeer createFileDialog(FileDialog target) throws HeadlessException {
363: throw new IllegalStateException("Method not implemented");
364: }
365:
366: protected ScrollPanePeer createScrollPane(ScrollPane target) throws HeadlessException {
367: throw new IllegalStateException("Method not implemented");
368: }
369:
370: protected DialogPeer createDialog(Dialog target) throws HeadlessException {
371: throw new IllegalStateException("Method not implemented");
372: }
373:
374: protected PanelPeer createPanel(Panel target) {
375: throw new IllegalStateException("Method not implemented");
376: }
377:
378: protected ChoicePeer createChoice(Choice target) throws HeadlessException {
379: throw new IllegalStateException("Method not implemented");
380: }
381:
382: protected FramePeer createFrame(Frame target) throws HeadlessException {
383: throw new IllegalStateException("Method not implemented");
384: }
385:
386: protected LabelPeer createLabel(Label target) throws HeadlessException {
387: throw new IllegalStateException("Method not implemented");
388: }
389:
390: protected FontPeer getFontPeer(String name, int style) {
391: throw new IllegalStateException("Method not implemented");
392: }
393:
394: protected CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target) throws HeadlessException {
395: throw new IllegalStateException("Method not implemented");
396: }
397:
398: protected WindowPeer createWindow(Window target) throws HeadlessException {
399: throw new IllegalStateException("Method not implemented");
400: }
401:
402: public void sync() {
403: Toolkit.getDefaultToolkit().sync();
404: }
405:
406: protected EventQueue getSystemEventQueueImpl() {
407: return Toolkit.getDefaultToolkit().getSystemEventQueue();
408: }
409:
410: public Clipboard getSystemClipboard() throws HeadlessException {
411: return Toolkit.getDefaultToolkit().getSystemClipboard();
412: }
413:
414: public Dimension getScreenSize() throws HeadlessException {
415: return Toolkit.getDefaultToolkit().getScreenSize();
416: }
417:
418: public int getScreenResolution() throws HeadlessException {
419: return Toolkit.getDefaultToolkit().getScreenResolution();
420: }
421:
422: public String[] getFontList() {
423: return Toolkit.getDefaultToolkit().getFontList();
424: }
425:
426: public ColorModel getColorModel() throws HeadlessException {
427: return Toolkit.getDefaultToolkit().getColorModel();
428: }
429:
430: public void beep() {
431: Toolkit.getDefaultToolkit().beep();
432: }
433:
434: boolean createCustomCursorCalled = false;
435: public Cursor createCustomCursor(Image cursor, Point hotSpot, String name) throws IndexOutOfBoundsException, HeadlessException {
436:
437: createCustomCursorCalled = true;
438: return Toolkit.getDefaultToolkit().createCustomCursor(cursor, hotSpot, name);
439: }
440:
441: boolean getBestCursorSizeCalled = false;
442: public Dimension getBestCursorSize(int preferredWidth, int preferredHeight) throws HeadlessException {
443: getBestCursorSizeCalled = true;
444: return new Dimension(0,0);
445: }
446: }
447: */
448:
449: public static final class AwtBridgeImpl extends AWTBridge {
450: public JPopupMenu createEmptyPopup() {
451: return new JPopupMenu();
452: }
453:
454: public JMenuItem createMenuPresenter(Action action) {
455: return new JMenuItem(action);
456: }
457:
458: public JMenuItem createPopupPresenter(Action action) {
459: return new JMenuItem(action);
460: }
461:
462: public Component createToolbarPresenter(Action action) {
463: return new JButton(action);
464: }
465:
466: public Component[] convertComponents(Component comp) {
467: if (comp instanceof JMenuItem
468: && "HIDDEN".equals(((JMenuItem) comp).getText())) {
469: return new Component[0];
470: } else {
471: return new Component[] { comp };
472: }
473: }
474: }
475:
476: }
|