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.*;
045: import java.awt.event.KeyEvent;
046: import java.awt.event.ActionListener;
047: import java.awt.event.ActionEvent;
048: import java.awt.event.FocusListener;
049: import java.beans.PropertyChangeListener;
050: import java.beans.VetoableChangeListener;
051: import java.util.*;
052: import java.util.List;
053: import java.lang.reflect.*;
054: import java.lang.ref.Reference;
055: import java.lang.ref.SoftReference;
056: import java.io.InputStreamReader;
057: import java.io.BufferedReader;
058: import java.io.File;
059: import java.io.IOException;
060: import java.lang.ref.ReferenceQueue;
061: import java.net.*;
062: import java.text.BreakIterator;
063: import javax.swing.Action;
064: import javax.swing.JMenuItem;
065: import javax.swing.KeyStroke;
066: import javax.swing.Timer;
067: import javax.swing.event.ChangeListener;
068: import javax.swing.event.DocumentListener;
069:
070: import org.openide.ErrorManager;
071:
072: /** Otherwise uncategorized useful static methods.
073: *
074: * @author Jan Palka, Ian Formanek, Jaroslav Tulach
075: */
076: public final class Utilities {
077: private Utilities() {
078: }
079:
080: /** Operating system is Windows NT. */
081: public static final int OS_WINNT = 1 << 0;
082: /** Operating system is Windows 95. */
083: public static final int OS_WIN95 = OS_WINNT << 1;
084: /** Operating system is Windows 98. */
085: public static final int OS_WIN98 = OS_WIN95 << 1;
086: /** Operating system is Solaris. */
087: public static final int OS_SOLARIS = OS_WIN98 << 1;
088: /** Operating system is Linux. */
089: public static final int OS_LINUX = OS_SOLARIS << 1;
090: /** Operating system is HP-UX. */
091: public static final int OS_HP = OS_LINUX << 1;
092: /** Operating system is IBM AIX. */
093: public static final int OS_AIX = OS_HP << 1;
094: /** Operating system is SGI IRIX. */
095: public static final int OS_IRIX = OS_AIX << 1;
096: /** Operating system is Sun OS. */
097: public static final int OS_SUNOS = OS_IRIX << 1;
098: /** Operating system is Compaq TRU64 Unix */
099: public static final int OS_TRU64 = OS_SUNOS << 1;
100: /** @deprecated please use OS_TRU64 instead */
101: public static final int OS_DEC = OS_TRU64 << 1;
102: /** Operating system is OS/2. */
103: public static final int OS_OS2 = OS_DEC << 1;
104: /** Operating system is Mac. */
105: public static final int OS_MAC = OS_OS2 << 1;
106: /** Operating system is Windows 2000. */
107: public static final int OS_WIN2000 = OS_MAC << 1;
108: /** Operating system is Compaq OpenVMS */
109: public static final int OS_VMS = OS_WIN2000 << 1;
110: /**
111: *Operating system is one of the Windows variants but we don't know which
112: *one it is
113: */
114: public static final int OS_WIN_OTHER = OS_VMS << 1;
115: /** Operating system is unknown. */
116: public static final int OS_OTHER = OS_WIN_OTHER << 1;
117: /** Operating system is FreeBSD
118: * @since 4.50
119: */
120: public static final int OS_FREEBSD = OS_OTHER << 1;
121:
122: /** A mask for Windows platforms. */
123: public static final int OS_WINDOWS_MASK = OS_WINNT | OS_WIN95
124: | OS_WIN98 | OS_WIN2000 | OS_WIN_OTHER;
125: /** A mask for Unix platforms. */
126: public static final int OS_UNIX_MASK = OS_SOLARIS | OS_LINUX
127: | OS_HP | OS_AIX | OS_IRIX | OS_SUNOS | OS_TRU64 | OS_MAC
128: | OS_FREEBSD;
129:
130: /** A height of the windows's taskbar */
131: public static final int TYPICAL_WINDOWS_TASKBAR_HEIGHT = 27;
132:
133: /** A height of the Mac OS X's menu */
134: private static final int TYPICAL_MACOSX_MENU_HEIGHT = 24;
135:
136: /** Get the operating system on which the IDE is running.
137: * @return one of the <code>OS_*</code> constants (such as {@link #OS_WINNT})
138: */
139: public static final int getOperatingSystem() {
140: if (operatingSystem == -1) {
141: String osName = System.getProperty("os.name");
142: if ("Windows NT".equals(osName)) // NOI18N
143: operatingSystem = OS_WINNT;
144: else if ("Windows 95".equals(osName)) // NOI18N
145: operatingSystem = OS_WIN95;
146: else if ("Windows 98".equals(osName)) // NOI18N
147: operatingSystem = OS_WIN98;
148: else if ("Windows 2000".equals(osName)) // NOI18N
149: operatingSystem = OS_WIN2000;
150: else if (osName.startsWith("Windows ")) // NOI18N
151: operatingSystem = OS_WIN_OTHER;
152: else if ("Solaris".equals(osName)) // NOI18N
153: operatingSystem = OS_SOLARIS;
154: else if (osName.startsWith("SunOS")) // NOI18N
155: operatingSystem = OS_SOLARIS;
156: // JDK 1.4 b2 defines os.name for me as "Redhat Linux" -jglick
157: else if (osName.endsWith("Linux")) // NOI18N
158: operatingSystem = OS_LINUX;
159: else if ("HP-UX".equals(osName)) // NOI18N
160: operatingSystem = OS_HP;
161: else if ("AIX".equals(osName)) // NOI18N
162: operatingSystem = OS_AIX;
163: else if ("Irix".equals(osName)) // NOI18N
164: operatingSystem = OS_IRIX;
165: else if ("SunOS".equals(osName)) // NOI18N
166: operatingSystem = OS_SUNOS;
167: else if ("Digital UNIX".equals(osName)) // NOI18N
168: operatingSystem = OS_TRU64;
169: else if ("OS/2".equals(osName)) // NOI18N
170: operatingSystem = OS_OS2;
171: else if ("OpenVMS".equals(osName)) // NOI18N
172: operatingSystem = OS_VMS;
173: else if (osName.equals("Mac OS X")) // NOI18N
174: operatingSystem = OS_MAC;
175: else if (osName.startsWith("Darwin")) // NOI18N
176: operatingSystem = OS_MAC;
177: else if (osName.toLowerCase(Locale.US)
178: .startsWith("freebsd")) { // NOI18N
179: operatingSystem = OS_FREEBSD;
180: } else
181: operatingSystem = OS_OTHER;
182: }
183: return operatingSystem;
184: }
185:
186: /** Test whether the IDE is running on some variant of Windows.
187: * @return <code>true</code> if Windows, <code>false</code> if some other manner of operating system
188: */
189: public static final boolean isWindows() {
190: return (getOperatingSystem() & OS_WINDOWS_MASK) != 0;
191: }
192:
193: /** Test whether the IDE is running on some variant of Unix.
194: * Linux is included as well as the commercial vendors.
195: * @return <code>true</code> some sort of Unix, <code>false</code> if some other manner of operating system
196: */
197: public static final boolean isUnix() {
198: return (getOperatingSystem() & OS_UNIX_MASK) != 0;
199: }
200:
201: /** The operating system on which NetBeans runs*/
202: private static int operatingSystem = -1;
203:
204: // only for UtilitiesTest purposes
205: final static void resetOperatingSystem() {
206: operatingSystem = -1;
207: }
208:
209: /**
210: * Convert an array of objects to an array of primitive types.
211: * E.g. an <code>Integer[]</code> would be changed to an <code>int[]</code>.
212: * @param array the wrapper array
213: * @return a primitive array
214: * @throws IllegalArgumentException if the array element type is not a primitive wrapper
215: */
216: public static Object toPrimitiveArray(Object[] array) {
217: if (array instanceof Integer[]) {
218: int[] r = new int[array.length];
219: int i, k = array.length;
220: for (i = 0; i < k; i++)
221: r[i] = (((Integer) array[i]) == null) ? 0
222: : ((Integer) array[i]).intValue();
223: return r;
224: }
225: if (array instanceof Boolean[]) {
226: boolean[] r = new boolean[array.length];
227: int i, k = array.length;
228: for (i = 0; i < k; i++)
229: r[i] = (((Boolean) array[i]) == null) ? false
230: : ((Boolean) array[i]).booleanValue();
231: return r;
232: }
233: if (array instanceof Byte[]) {
234: byte[] r = new byte[array.length];
235: int i, k = array.length;
236: for (i = 0; i < k; i++)
237: r[i] = (((Byte) array[i]) == null) ? 0
238: : ((Byte) array[i]).byteValue();
239: return r;
240: }
241: if (array instanceof Character[]) {
242: char[] r = new char[array.length];
243: int i, k = array.length;
244: for (i = 0; i < k; i++)
245: r[i] = (((Character) array[i]) == null) ? 0
246: : ((Character) array[i]).charValue();
247: return r;
248: }
249: if (array instanceof Double[]) {
250: double[] r = new double[array.length];
251: int i, k = array.length;
252: for (i = 0; i < k; i++)
253: r[i] = (((Double) array[i]) == null) ? 0
254: : ((Double) array[i]).doubleValue();
255: return r;
256: }
257: if (array instanceof Float[]) {
258: float[] r = new float[array.length];
259: int i, k = array.length;
260: for (i = 0; i < k; i++)
261: r[i] = (((Float) array[i]) == null) ? 0
262: : ((Float) array[i]).floatValue();
263: return r;
264: }
265: if (array instanceof Long[]) {
266: long[] r = new long[array.length];
267: int i, k = array.length;
268: for (i = 0; i < k; i++)
269: r[i] = (((Long) array[i]) == null) ? 0
270: : ((Long) array[i]).longValue();
271: return r;
272: }
273: if (array instanceof Short[]) {
274: short[] r = new short[array.length];
275: int i, k = array.length;
276: for (i = 0; i < k; i++)
277: r[i] = (((Short) array[i]) == null) ? 0
278: : ((Short) array[i]).shortValue();
279: return r;
280: }
281: throw new IllegalArgumentException();
282: }
283:
284: /**
285: * Convert an array of primitive types to an array of objects.
286: * E.g. an <code>int[]</code> would be turned into an <code>Integer[]</code>.
287: * @param array the primitive array
288: * @return a wrapper array
289: * @throws IllegalArgumentException if the array element type is not primitive
290: */
291: public static Object[] toObjectArray(Object array) {
292: if (array instanceof Object[])
293: return (Object[]) array;
294: if (array instanceof int[]) {
295: int i, k = ((int[]) array).length;
296: Integer[] r = new Integer[k];
297: for (i = 0; i < k; i++)
298: r[i] = new Integer(((int[]) array)[i]);
299: return r;
300: }
301: if (array instanceof boolean[]) {
302: int i, k = ((boolean[]) array).length;
303: Boolean[] r = new Boolean[k];
304: for (i = 0; i < k; i++)
305: r[i] = ((boolean[]) array)[i] ? Boolean.TRUE
306: : Boolean.FALSE;
307: return r;
308: }
309: if (array instanceof byte[]) {
310: int i, k = ((byte[]) array).length;
311: Byte[] r = new Byte[k];
312: for (i = 0; i < k; i++)
313: r[i] = new Byte(((byte[]) array)[i]);
314: return r;
315: }
316: if (array instanceof char[]) {
317: int i, k = ((char[]) array).length;
318: Character[] r = new Character[k];
319: for (i = 0; i < k; i++)
320: r[i] = new Character(((char[]) array)[i]);
321: return r;
322: }
323: if (array instanceof double[]) {
324: int i, k = ((double[]) array).length;
325: Double[] r = new Double[k];
326: for (i = 0; i < k; i++)
327: r[i] = new Double(((double[]) array)[i]);
328: return r;
329: }
330: if (array instanceof float[]) {
331: int i, k = ((float[]) array).length;
332: Float[] r = new Float[k];
333: for (i = 0; i < k; i++)
334: r[i] = new Float(((float[]) array)[i]);
335: return r;
336: }
337: if (array instanceof long[]) {
338: int i, k = ((long[]) array).length;
339: Long[] r = new Long[k];
340: for (i = 0; i < k; i++)
341: r[i] = new Long(((long[]) array)[i]);
342: return r;
343: }
344: if (array instanceof short[]) {
345: int i, k = ((short[]) array).length;
346: Short[] r = new Short[k];
347: for (i = 0; i < k; i++)
348: r[i] = new Short(((short[]) array)[i]);
349: return r;
350: }
351: throw new IllegalArgumentException();
352: }
353:
354: /**
355: * Get the object type for given primitive type.
356: *
357: * @param c primitive type (e.g. <code>int</code>)
358: * @return object type (e.g. <code>Integer</code>)
359: */
360: public static Class getObjectType(Class c) {
361: if (!c.isPrimitive())
362: return c;
363: if (c == Integer.TYPE)
364: return Integer.class;
365: if (c == Boolean.TYPE)
366: return Boolean.class;
367: if (c == Byte.TYPE)
368: return Byte.class;
369: if (c == Character.TYPE)
370: return Character.class;
371: if (c == Double.TYPE)
372: return Double.class;
373: if (c == Float.TYPE)
374: return Float.class;
375: if (c == Long.TYPE)
376: return Long.class;
377: if (c == Short.TYPE)
378: return Short.class;
379: throw new IllegalArgumentException();
380: }
381:
382: /**
383: * Get the primitive type for given object type.
384: *
385: * @param c object type (e.g. <code>Integer</code>)
386: * @return primitive type (e.g. <code>int</code>)
387: */
388: public static Class getPrimitiveType(Class c) {
389: if (!c.isPrimitive())
390: return c;
391: if (c == Integer.class)
392: return Integer.TYPE;
393: if (c == Boolean.class)
394: return Boolean.TYPE;
395: if (c == Byte.class)
396: return Byte.TYPE;
397: if (c == Character.class)
398: return Character.TYPE;
399: if (c == Double.class)
400: return Double.TYPE;
401: if (c == Float.class)
402: return Float.TYPE;
403: if (c == Long.class)
404: return Long.TYPE;
405: if (c == Short.class)
406: return Short.TYPE;
407: throw new IllegalArgumentException();
408: }
409:
410: /**
411: * Finds out the monitor where the user currently has the input focus.
412: * This method is usually used to help the client code to figure out on
413: * which monitor it should place newly created windows/frames/dialogs.
414: *
415: * @return the GraphicsConfiguration of the monitor which currently has the
416: * input focus
417: */
418: private static GraphicsConfiguration getCurrentGraphicsConfiguration() {
419: Frame[] frames = Frame.getFrames();
420:
421: for (int i = 0; i < frames.length; i++) {
422: if (javax.swing.SwingUtilities.findFocusOwner(frames[i]) != null) {
423: return frames[i].getGraphicsConfiguration();
424: }
425: }
426: return GraphicsEnvironment.getLocalGraphicsEnvironment()
427: .getDefaultScreenDevice().getDefaultConfiguration();
428: }
429:
430: /**
431: * Returns the usable area of the screen where applications can place its
432: * windows. The method subtracts from the screen the area of taskbars,
433: * system menus and the like. The screen this method applies to is the one
434: * which is considered current, ussually the one where the current input
435: * focus is.
436: *
437: * @return the rectangle of the screen where one can place windows
438: *
439: * @since 2.5
440: */
441: public static Rectangle getUsableScreenBounds() {
442: return getUsableScreenBounds(getCurrentGraphicsConfiguration());
443: }
444:
445: /**
446: * Returns the usable area of the screen where applications can place its
447: * windows. The method subtracts from the screen the area of taskbars,
448: * system menus and the like.
449: *
450: * @param gconf the GraphicsConfiguration of the monitor
451: * @return the rectangle of the screen where one can place windows
452: *
453: * @since 2.5
454: */
455: public static Rectangle getUsableScreenBounds(
456: GraphicsConfiguration gconf) {
457: if (gconf == null)
458: gconf = GraphicsEnvironment.getLocalGraphicsEnvironment()
459: .getDefaultScreenDevice().getDefaultConfiguration();
460:
461: Rectangle bounds = new Rectangle(gconf.getBounds());
462:
463: String str;
464:
465: str = System.getProperty("netbeans.screen.insets"); // NOI18N
466: if (str != null) {
467: StringTokenizer st = new StringTokenizer(str, ", "); // NOI18N
468: if (st.countTokens() == 4) {
469: try {
470: bounds.y = Integer.parseInt(st.nextToken());
471: bounds.x = Integer.parseInt(st.nextToken());
472: bounds.height -= bounds.y
473: + Integer.parseInt(st.nextToken());
474: bounds.width -= bounds.x
475: + Integer.parseInt(st.nextToken());
476: } catch (NumberFormatException ex) {
477: ErrorManager.getDefault().notify(
478: ErrorManager.WARNING, ex);
479: }
480: }
481: return bounds;
482: }
483:
484: str = System.getProperty("netbeans.taskbar.height"); // NOI18N
485: if (str != null) {
486: bounds.height -= Integer.getInteger(str, 0).intValue();
487: return bounds;
488: }
489:
490: try {
491: Toolkit toolkit = Toolkit.getDefaultToolkit();
492: Insets insets = toolkit.getScreenInsets(gconf);
493: bounds.y += insets.top;
494: bounds.x += insets.left;
495: bounds.height -= insets.top + insets.bottom;
496: bounds.width -= insets.left + insets.right;
497: } catch (Exception ex) {
498: ErrorManager.getDefault().notify(ErrorManager.WARNING, ex);
499: }
500: return bounds;
501: }
502:
503: /**
504: * Helps client code place components on the center of the screen. It
505: * handles multiple monitor configuration correctly
506: *
507: * @param componentSize the size of the component
508: * @return bounds of the centered component
509: *
510: * @since 2.5
511: */
512: public static Rectangle findCenterBounds(Dimension componentSize) {
513: return findCenterBounds(getCurrentGraphicsConfiguration(),
514: componentSize);
515: }
516:
517: /**
518: * Helps client code place components on the center of the screen. It
519: * handles multiple monitor configuration correctly
520: *
521: * @param gconf the GraphicsConfiguration of the monitor
522: * @param componentSize the size of the component
523: * @return bounds of the centered component
524: */
525: private static Rectangle findCenterBounds(
526: GraphicsConfiguration gconf, Dimension componentSize) {
527: if (gconf == null)
528: gconf = GraphicsEnvironment.getLocalGraphicsEnvironment()
529: .getDefaultScreenDevice().getDefaultConfiguration();
530:
531: Rectangle bounds = gconf.getBounds();
532: return new Rectangle(bounds.x
533: + (bounds.width - componentSize.width) / 2, bounds.y
534: + (bounds.height - componentSize.height) / 2,
535: componentSize.width, componentSize.height);
536: }
537: }
|