Source Code Cross Referenced for Utilities.java in  » Apache-Harmony-Java-SE » org-package » org » apache » harmony » x » swing » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Apache Harmony Java SE » org package » org.apache.harmony.x.swing 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
0003:         *  contributor license agreements.  See the NOTICE file distributed with
0004:         *  this work for additional information regarding copyright ownership.
0005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
0006:         *  (the "License"); you may not use this file except in compliance with
0007:         *  the License.  You may obtain a copy of the License at
0008:         *
0009:         *     http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         *  Unless required by applicable law or agreed to in writing, software
0012:         *  distributed under the License is distributed on an "AS IS" BASIS,
0013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         *  See the License for the specific language governing permissions and
0015:         *  limitations under the License.
0016:         */
0017:        /**
0018:         * @author Alexander T. Simbirtsev, Anton Avtamonov
0019:         * @version $Revision$
0020:         */package org.apache.harmony.x.swing;
0021:
0022:        import java.awt.Color;
0023:        import java.awt.Component;
0024:        import java.awt.Container;
0025:        import java.awt.Dialog;
0026:        import java.awt.Dimension;
0027:        import java.awt.Font;
0028:        import java.awt.FontMetrics;
0029:        import java.awt.Frame;
0030:        import java.awt.Graphics;
0031:        import java.awt.GraphicsConfiguration;
0032:        import java.awt.GraphicsEnvironment;
0033:        import java.awt.HeadlessException;
0034:        import java.awt.Insets;
0035:        import java.awt.MouseInfo;
0036:        import java.awt.Point;
0037:        import java.awt.Rectangle;
0038:        import java.awt.Toolkit;
0039:        import java.awt.Window;
0040:        import java.awt.event.InputEvent;
0041:        import java.awt.event.KeyEvent;
0042:        import java.security.AccessController;
0043:        import java.security.PrivilegedAction;
0044:        import java.util.ArrayList;
0045:
0046:        import javax.swing.Icon;
0047:        import javax.swing.InputMap;
0048:        import javax.swing.JComponent;
0049:        import javax.swing.JMenuBar;
0050:        import javax.swing.JPopupMenu;
0051:        import javax.swing.KeyStroke;
0052:        import javax.swing.LookAndFeel;
0053:        import javax.swing.MenuElement;
0054:        import javax.swing.SwingConstants;
0055:        import javax.swing.SwingUtilities;
0056:        import javax.swing.UIManager;
0057:        import javax.swing.plaf.UIResource;
0058:        import javax.swing.plaf.basic.BasicComboPopup;
0059:        import javax.swing.plaf.basic.BasicGraphicsUtils;
0060:        import javax.swing.text.Position;
0061:
0062:        import org.apache.harmony.x.swing.internal.nls.Messages;
0063:
0064:        /**
0065:         * SwingUtilities extension. This class provides utility
0066:         * methods which are widely used in Swing classes.
0067:         *
0068:         */
0069:        public class Utilities implements  SwingConstants {
0070:            /**
0071:             * This interface allows to access list data
0072:             */
0073:            public interface ListModelAccessor {
0074:                /**
0075:                 * Returns the list data element according to specified index
0076:                 * 
0077:                 * @param index of the element
0078:                 * @return element, specified by index
0079:                 */
0080:                public Object getElementAt(final int index);
0081:
0082:                /**
0083:                 * Returns the size of the list
0084:                 * @return size of the list
0085:                 */
0086:                public int getSize();
0087:            }
0088:
0089:            /**
0090:             * Returns the index of the next element of the list according to specified
0091:             * prefix, start index and bias
0092:             * 
0093:             * @param model of the list
0094:             * @param prefix of the list element
0095:             * @param startIndex index to start search from
0096:             * @param bias
0097:             * @return index of the next element
0098:             */
0099:            public static int getNextMatch(final ListModelAccessor model,
0100:                    final String prefix, final int startIndex,
0101:                    final Position.Bias bias) {
0102:                if (prefix == null) {
0103:                    throw new IllegalArgumentException(Messages
0104:                            .getString("swing.6F")); //$NON-NLS-1$
0105:                }
0106:
0107:                if (startIndex < 0 || startIndex >= model.getSize()) {
0108:                    throw new IllegalArgumentException(Messages
0109:                            .getString("swing.6D")); //$NON-NLS-1$
0110:                }
0111:
0112:                String ucPrefix = prefix.toUpperCase();
0113:                if (Position.Bias.Forward == bias) {
0114:                    for (int i = startIndex; i < model.getSize(); i++) {
0115:                        String elementAsString = model.getElementAt(i)
0116:                                .toString().toUpperCase();
0117:                        if (elementAsString.startsWith(ucPrefix)) {
0118:                            return i;
0119:                        }
0120:                    }
0121:                    for (int i = 0; i < startIndex; i++) {
0122:                        String elementAsString = model.getElementAt(i)
0123:                                .toString().toUpperCase();
0124:                        if (elementAsString.startsWith(ucPrefix)) {
0125:                            return i;
0126:                        }
0127:                    }
0128:                } else if (Position.Bias.Backward == bias) {
0129:                    for (int i = startIndex; i >= 0; i--) {
0130:                        String elementAsString = model.getElementAt(i)
0131:                                .toString().toUpperCase();
0132:                        if (elementAsString.startsWith(ucPrefix)) {
0133:                            return i;
0134:                        }
0135:                    }
0136:                    for (int i = model.getSize() - 1; i > startIndex; i--) {
0137:                        String elementAsString = model.getElementAt(i)
0138:                                .toString().toUpperCase();
0139:                        if (elementAsString.startsWith(ucPrefix)) {
0140:                            return i;
0141:                        }
0142:                    }
0143:                }
0144:
0145:                return -1;
0146:            }
0147:
0148:            /**
0149:             * Clips string due to the width of an area available for painting the text.
0150:             *
0151:             * @param fm FontMetrics for the text font
0152:             * @param text original (not clipped) text
0153:             * @param width width of the area available for painting the text
0154:             * @return clipped string (ending with "...") or the original string if it fits the available width
0155:             */
0156:            public static String clipString(final FontMetrics fm,
0157:                    final String text, final int width) {
0158:                final String dots = "...";
0159:                final int stringWidth = fm.stringWidth(text);
0160:                if (width >= stringWidth) {
0161:                    return text;
0162:                }
0163:
0164:                final int dotsWidth = fm.stringWidth(dots);
0165:                if (width <= dotsWidth) {
0166:                    return dots;
0167:                }
0168:
0169:                return text.substring(0, getSuitableSubstringLength(fm, text,
0170:                        width - dotsWidth))
0171:                        + dots;
0172:            }
0173:
0174:            /**
0175:             * Returns given index if underscored part of the string isn't clipped,
0176:             * <code>-1</code>  otherwise.
0177:             *
0178:             * @param original original text
0179:             * @param clipped clipped text
0180:             * @param underscoreIndex index of the character in <code>text</code> to be
0181:             *  underscored
0182:             * @return underscoreIndex or <code>-1</code> if the position is clipped
0183:             */
0184:            public static int getClippedUnderscoreIndex(final String original,
0185:                    final String clipped, final int underscoreIndex) {
0186:                return insideString(clipped, underscoreIndex)
0187:                        && original.charAt(underscoreIndex) == clipped
0188:                                .charAt(underscoreIndex) ? underscoreIndex : -1;
0189:            }
0190:
0191:            /**
0192:             * Draws part of 3D-like rectangle with given parameters.
0193:             *
0194:             * @see java.awt.Graphics2D#draw3DRect(int, int, int, int, boolean)
0195:             * @param shadow color for dark parts of the rectangle
0196:             * @param highlight color for light parts of the rectangle
0197:             * @param raised if <code>true</code> left and top sides of rectangle will be drawn light
0198:             */
0199:            public static void draw3DRect(final Graphics g, final int x,
0200:                    final int y, final int w, final int h, final Color shadow,
0201:                    final Color highlight, final boolean raised) {
0202:                final Color oldColor = g.getColor();
0203:                final int bottom = y + h - 1;
0204:                final int right = x + w - 1;
0205:                final Color topLeft = raised ? highlight : shadow;
0206:                final Color bottomRight = raised ? shadow : highlight;
0207:                g.setColor(topLeft);
0208:                g.drawLine(x, y, x, bottom);
0209:                g.drawLine(x, y, right, y);
0210:                g.setColor(bottomRight);
0211:                g.drawLine(right, y, right, bottom);
0212:                g.drawLine(x, bottom, right, bottom);
0213:                g.setColor(oldColor);
0214:            }
0215:
0216:            /**
0217:             * Converts keyCode to mnemonic keyChar if possible. Note there is no 1 to 1 conversion.
0218:             * @param keyCode KeyCode to be converted to a char
0219:             * @return char or {@link java.awt.event.KeyEvent#VK_UNDEFINED} if conversion could not be done.
0220:             */
0221:            public static char keyCodeToKeyChar(final int keyCode) {
0222:                if (keyCode < 0 || keyCode > 0xFFFF) {
0223:                    return KeyEvent.VK_UNDEFINED;
0224:                }
0225:
0226:                return Character.toUpperCase((char) keyCode);
0227:            }
0228:
0229:            /**
0230:             * Converts mnemonic keyChar to keyCode.
0231:             *
0232:             * @param keyChar char to be converted to keyCode
0233:             * @return converted keyCode or the <code>int</code> value of <code>keyChar</code>.
0234:             */
0235:            public static int keyCharToKeyCode(final char keyChar) {
0236:                if (keyChar > 127) {
0237:                    return keyChar;
0238:                }
0239:
0240:                return Character.toUpperCase(keyChar);
0241:            }
0242:
0243:            /**
0244:             * Returns optimal location to display popup based on the anchor bounds
0245:             * requested, popup size and location of popup related to anchor. The optimal
0246:             * location fulfills the condition popup fits on screen, not overlaps with
0247:             * anchor and is verticaly or horizontaly positioned relative to anchor. If
0248:             * position is vertical the popup left or right bound is aligned with
0249:             * anchor bound depending on <code>leftToRight</code>.
0250:             *
0251:             * @param anchor anchor bounds relative to
0252:             * @param size requested popup size
0253:             * @param leftToRight horizontal alignment
0254:             * @param horizontal placement relative to anchor
0255:             * @return optimal popup location
0256:             */
0257:            public static Point getPopupLocation(final Rectangle anchor,
0258:                    final Dimension size, final boolean leftToRight,
0259:                    final boolean horizontal, final GraphicsConfiguration gc) {
0260:                Point result = getPopupLocation(anchor, size, leftToRight,
0261:                        horizontal);
0262:                return adjustPopupLocation(result, size, anchor, horizontal, gc);
0263:            }
0264:
0265:            /**
0266:             * Gets popup location basing on the invoker position.
0267:             *
0268:             * @param anchor Rectangle which specified the bounds of the popup invoker
0269:             * @param size Dimension of the popup size
0270:             * @param leftToRight boolean value representing ComponentOrientation.isLeftToRight() state
0271:             * @param horizontal boolean value representing ComponentOrientation.isHorizontal() state
0272:             * @return Popup location
0273:             */
0274:            public static Point getPopupLocation(final Rectangle anchor,
0275:                    final Dimension size, final boolean leftToRight,
0276:                    final boolean horizontal) {
0277:                Point result = anchor.getLocation();
0278:                if (horizontal) {
0279:                    if (leftToRight) {
0280:                        result.x += anchor.width;
0281:                    } else {
0282:                        result.x -= size.width;
0283:                    }
0284:                } else {
0285:                    result.y += anchor.height;
0286:                    if (!leftToRight) {
0287:                        result.x += anchor.width - size.width;
0288:                    }
0289:                }
0290:
0291:                return result;
0292:            }
0293:
0294:            /**
0295:             * Determizes the 'optimal' popup location to provide the entire popup is shown.
0296:             *
0297:             * @param location Point of the proposed location
0298:             * @param size Dimension of the popup size
0299:             * @param anchor Rectangle which specified the bounds of the popup invoker
0300:             * @param horizontal boolean value representing ComponentOrientation.isHorizontal() state
0301:             * @param gc GraphicsConfiguration of the parent Window
0302:             *
0303:             * @return Optimal popup location
0304:             */
0305:            public static Point adjustPopupLocation(final Point location,
0306:                    final Dimension size, final Rectangle anchor,
0307:                    final boolean horizontal, final GraphicsConfiguration gc) {
0308:                final Point result = location;
0309:                final Rectangle screenBounds = getScreenClientBounds(gc);
0310:                if (screenBounds.contains(new Rectangle(result, size))) {
0311:                    return result;
0312:                }
0313:                if (horizontal) {
0314:                    if (screenBounds.width < result.x + size.width) {
0315:                        result.x = anchor.x - size.width;
0316:                    }
0317:                    if (screenBounds.x > result.x) {
0318:                        result.x = anchor.x + anchor.width;
0319:                    }
0320:                    if (screenBounds.height < result.y + size.height) {
0321:                        result.y = anchor.y + anchor.height - size.height;
0322:                    }
0323:                    if (screenBounds.y > result.y + size.height) {
0324:                        result.y = screenBounds.y + 20;
0325:                    }
0326:                } else {
0327:                    if (screenBounds.height < result.y + size.height) {
0328:                        result.y = anchor.y - size.height;
0329:                    }
0330:                    if (screenBounds.width < result.x + size.width) {
0331:                        result.x = screenBounds.width - size.width - 20;
0332:                    }
0333:                    if (screenBounds.x > result.x) {
0334:                        result.x = screenBounds.x + 20;
0335:                    }
0336:                    if (screenBounds.y > result.y + size.height) {
0337:                        result.y = screenBounds.y + 20;
0338:                    }
0339:                }
0340:
0341:                return result;
0342:            }
0343:
0344:            /**
0345:             * If the window is <code>Frame</code> or <code>Dialog</code>, the function
0346:             * returns <code>true</code> the window is resizable. Otherwise
0347:             * <code>false</code> is returned. This function can be used
0348:             * when implementing L&F for <code>JRootPane</code>.
0349:             *
0350:             * @param window the window to determine if it is resizable
0351:             *
0352:             * @return <code>true</code> if the window is <code>Frame</code> or
0353:             *         <code>Dialog</code> and is resizable, otherwise
0354:             *         <code>false</code> is returned
0355:             */
0356:            public static final boolean isResizableWindow(final Window window) {
0357:                if (window instanceof  Frame) {
0358:                    return ((Frame) window).isResizable();
0359:                } else if (window instanceof  Dialog) {
0360:                    return ((Dialog) window).isResizable();
0361:                }
0362:                return false;
0363:            }
0364:
0365:            /**
0366:             * Returns <code>true</code> if the parameter is a maximized frame.
0367:             * This function can be used when implementing L&F for
0368:             * <code>JRootPane</code>.
0369:             *
0370:             * @param window the window to determine if it is maximized
0371:             *
0372:             * @return <code>true</code> if the window is <code>Frame</code>
0373:             *         and it is maximized
0374:             */
0375:            public static final boolean isMaximumFrame(final Window window) {
0376:                return window instanceof  Frame
0377:                        && (((Frame) window).getExtendedState() & Frame.MAXIMIZED_BOTH) != 0;
0378:            }
0379:
0380:            /**
0381:             * This function implements evaluation of maximum/minimum/preferred sizes
0382:             * of <code>JRootPane</code>. Depending on the size to be evaluated,
0383:             * the parameters are maximum/minimum/preferred sizes of subcomponents.
0384:             *
0385:             * @param contentPaneSize the maximum/minimum/preferred size of
0386:             *        <code>contentPane</code>
0387:             * @param menuBarSize the maximum/minimum/preferred size of
0388:             *        <code>menuBar</code>; may be <code>null</code>
0389:             * @param titlePaneSize the maximum/minimum/preferred size of
0390:             *        <code>titlePane</code>; may be <code>null</code>
0391:             * @param insets the insets of <code>JRootPane</code>
0392:             *
0393:             * @return the maximum/minimum/preferred size of <code>JRootPane</code>
0394:             */
0395:            public static final Dimension getRootPaneLayoutSize(
0396:                    final Dimension contentPaneSize,
0397:                    final Dimension menuBarSize, final Dimension titlePaneSize,
0398:                    final Insets insets) {
0399:
0400:                Dimension result = new Dimension(contentPaneSize);
0401:
0402:                if (menuBarSize != null) {
0403:                    result.height += menuBarSize.height;
0404:                    result.width = Math.max(result.width, menuBarSize.width);
0405:                }
0406:
0407:                if (titlePaneSize != null) {
0408:                    result.height += titlePaneSize.height;
0409:                    result.width = Math.max(result.width, titlePaneSize.width);
0410:                }
0411:
0412:                return addInsets(result, insets);
0413:            }
0414:
0415:            /**
0416:             * Removes colors and font installed by <code>LookAndFeel</code>.
0417:             *
0418:             * @see javax.swing.LookAndFeel#installColorsAndFont(JComponent, String, String, String)
0419:             * @param comp Component for which UI colors and font should be uninstalled
0420:             */
0421:            public static final void uninstallColorsAndFont(
0422:                    final JComponent comp) {
0423:                if (comp.getBackground() instanceof  UIResource) {
0424:                    comp.setBackground(null);
0425:                }
0426:                if (comp.getForeground() instanceof  UIResource) {
0427:                    comp.setForeground(null);
0428:                }
0429:                if (comp.getFont() instanceof  UIResource) {
0430:                    comp.setFont(null);
0431:                }
0432:            }
0433:
0434:            /**
0435:             * Enlarges <code>size</code> by insets size. <code>size</code> fields
0436:             * are changed.
0437:             *
0438:             * @param size initial dimension
0439:             * @param insets insets to add
0440:             * @return Enlarged dimension
0441:             */
0442:            public static final Dimension addInsets(final Dimension size,
0443:                    final Insets insets) {
0444:                size.setSize(size.width + insets.left + insets.right,
0445:                        size.height + insets.top + insets.bottom);
0446:                return size;
0447:            }
0448:
0449:            /**
0450:             * Reduces width and height of <code>rect</code> by insets
0451:             * and moves its origin. The fields of <code>insets</code>
0452:             * are not changed.
0453:             *
0454:             * @param rect initial rectangle, its fields will be modified
0455:             * @param insets insets to subract
0456:             * @return Area inside the insets
0457:             */
0458:            public static final Rectangle subtractInsets(final Rectangle rect,
0459:                    final Insets insets) {
0460:                if (insets == null) {
0461:                    return rect;
0462:                }
0463:                rect.setBounds(rect.x + insets.left, rect.y + insets.top,
0464:                        rect.width - insets.left - insets.right, rect.height
0465:                                - insets.top - insets.bottom);
0466:                return rect;
0467:            }
0468:
0469:            /**
0470:             * Adds values from second argument to the first one and returns first argument.
0471:             *
0472:             * @param recipient Insets to be enlarged
0473:             * @param addition Instes to be added to the recipient
0474:             *
0475:             * @return Recipient
0476:             */
0477:            public static final Insets addInsets(final Insets recipient,
0478:                    final Insets addition) {
0479:                if (addition == null) {
0480:                    return recipient;
0481:                }
0482:                recipient.set(recipient.top + addition.top, recipient.left
0483:                        + addition.left, recipient.bottom + addition.bottom,
0484:                        recipient.right + addition.right);
0485:
0486:                return recipient;
0487:            }
0488:
0489:            /**
0490:             * Returns string size due to the given font metrics.
0491:             *
0492:             * @param str String which size should be calculated
0493:             * @param fm FontMetrics of the measuring String
0494:             * @return String size
0495:             */
0496:            public static Dimension getStringSize(final String str,
0497:                    final FontMetrics fm) {
0498:                return !isEmptyString(str) ? new Dimension(fm.stringWidth(str),
0499:                        fm.getHeight()) : new Dimension();
0500:            }
0501:
0502:            /**
0503:             * Draws string with given font and color.
0504:             *
0505:             * @param g Graphics to draw on
0506:             * @param str String to draw
0507:             * @param x int representing text x-coordinate
0508:             * @param y int representing text y-coordinate
0509:             * @param fm FontMetrics of the text to draw
0510:             * @param c Color to draw with
0511:             * @param underscoreIndex int value representing underscore index to be underlined or -1 if
0512:             *        no underlining is required
0513:             */
0514:            public static void drawString(final Graphics g, final String str,
0515:                    final int x, final int y, final FontMetrics fm,
0516:                    final Color c, final int underscoreIndex) {
0517:                if (isEmptyString(str)) {
0518:                    return;
0519:                }
0520:                final Color oldColor = g.getColor();
0521:                final Font oldFont = g.getFont();
0522:                g.setColor(c);
0523:                g.setFont(fm.getFont());
0524:                BasicGraphicsUtils.drawStringUnderlineCharAt(g, str,
0525:                        underscoreIndex, x, y);
0526:                g.setColor(oldColor);
0527:                g.setFont(oldFont);
0528:            }
0529:
0530:            /**
0531:             * Calculates the baseline for text being rendered on compound label
0532:             * based on the FontMetrics and bounding rectangle <code>y</code> coordinate.
0533:             *
0534:             * @param fm FontMetrics of the text
0535:             * @param textR Rectangle representing text bounds
0536:             *
0537:             * @return Y-coordinate to draw text from
0538:             */
0539:            public static int getTextY(final FontMetrics fm,
0540:                    final Rectangle textR) {
0541:                return textR.y + fm.getAscent();
0542:            }
0543:
0544:            /**
0545:             * Calculates size for the label that consists of a text message and an icon.
0546:             *
0547:             * @see javax.swing.SwingUtilities#layoutCompoundLabel(FontMetrics, String, Icon, int, int, int, int, Rectangle, Rectangle, Rectangle, int)
0548:             * @return Preferred size
0549:             */
0550:            public static Dimension getCompoundLabelSize(final JComponent c,
0551:                    final String text, final Icon icon,
0552:                    final int verticalTextPosition,
0553:                    final int horizontalTextPosition, final int iconTextGap) {
0554:
0555:                final Dimension result = new Dimension();
0556:                final FontMetrics fm = getFontMetrics(c);
0557:                if (fm == null) {
0558:                    return result;
0559:                }
0560:                Rectangle viewR = new Rectangle(Short.MAX_VALUE,
0561:                        Short.MAX_VALUE);
0562:                Rectangle iconR = new Rectangle();
0563:                Rectangle textR = new Rectangle();
0564:
0565:                SwingUtilities.layoutCompoundLabel(fm, text, icon, TOP, LEFT,
0566:                        verticalTextPosition, horizontalTextPosition, viewR,
0567:                        iconR, textR, iconTextGap);
0568:                result.width = Math.max(iconR.x + iconR.width, textR.x
0569:                        + textR.width);
0570:                result.height = Math.max(iconR.y + iconR.height, textR.y
0571:                        + textR.height);
0572:
0573:                return result;
0574:            }
0575:
0576:            /**
0577:             * Checks whether a string is empty, null is considered to be empty string.
0578:             *
0579:             * @param str string to check
0580:             * @return <code>true</code>, if <code>str</code> is <code>null</code>
0581:             *          or is empty.
0582:             */
0583:            public static boolean isEmptyString(final String str) {
0584:                return str == null || str.length() == 0;
0585:            }
0586:
0587:            /**
0588:             * Gets component FontMetrics.
0589:             *
0590:             * @param c Component which FontMetrics requested
0591:             * @return Component FontMetrics correspondent to current components font
0592:             */
0593:            public static FontMetrics getFontMetrics(final JComponent c) {
0594:                final Font font = c.getFont();
0595:                return font != null ? c.getFontMetrics(font) : null;
0596:            }
0597:
0598:            /**
0599:             * Checks whether an array is empty, null is considered to be empty array.
0600:             *
0601:             * @param arr array to check
0602:             * @return <code>true</code>, if <code>array</code> is <code>null</code>
0603:             *          or contains 0 elements.
0604:             */
0605:            public static boolean isEmptyArray(final Object[] arr) {
0606:                return arr == null || arr.length == 0;
0607:            }
0608:
0609:            /**
0610:             * Checks whether an array is empty, null is considered to be empty array.
0611:             *
0612:             * @param arr array to check
0613:             * @return <code>true</code>, if <code>array</code> is <code>null</code>
0614:             *          or contains 0 elements.
0615:             */
0616:            public static boolean isEmptyArray(final int[] arr) {
0617:                return arr == null || arr.length == 0;
0618:            }
0619:
0620:            /**
0621:             * Aligns rectangle with the inner bounds of the box taking into account
0622:             * alignments given.
0623:             *
0624:             * @param rect rectangle to align
0625:             * @param box box to align with
0626:             * @param horizontalAlign one of LEFT/RIGHT/CENTER
0627:             * @param verticalAlign one of TOP/BOTTOM/CENTER
0628:             */
0629:            public static void alignRect(final Rectangle rect,
0630:                    final Rectangle box, final int horizontalAlign,
0631:                    final int verticalAlign) {
0632:                rect.y = verticallyAlignRect(rect.height, box, verticalAlign);
0633:                rect.x = horizontallyAlignRect(rect.width, box, horizontalAlign);
0634:            }
0635:
0636:            /**
0637:             * Installs UI input map to the given component
0638:             * also installs RTL input map if available and needed.
0639:             *
0640:             * @param c component input map should be installed to
0641:             * @param condition condition for the input map
0642:             * @param inputMapKey key of the input map record in the defaults table.
0643:             * @param rtlInputMapKey key of the right-to-left input map record in the defaults table.
0644:             */
0645:            public static void installKeyboardActions(final JComponent c,
0646:                    final int condition, final String inputMapKey,
0647:                    final String rtlInputMapKey) {
0648:                InputMap uiInputMap = (InputMap) UIManager.get(inputMapKey);
0649:                if (rtlInputMapKey != null
0650:                        && !c.getComponentOrientation().isLeftToRight()) {
0651:                    final InputMap rtlInputMap = (InputMap) UIManager
0652:                            .get(rtlInputMapKey);
0653:                    if (rtlInputMap != null) {
0654:                        rtlInputMap.setParent(uiInputMap);
0655:                        uiInputMap = rtlInputMap;
0656:                    }
0657:                }
0658:                SwingUtilities.replaceUIInputMap(c, condition, uiInputMap);
0659:            }
0660:
0661:            /**
0662:             * Uninstalls UI InputMap from the component.
0663:             *
0664:             * @param c component from which UI input map to be removed
0665:             * @param condition condition for which input map should be removed.
0666:             */
0667:            public static void uninstallKeyboardActions(final JComponent c,
0668:                    final int condition) {
0669:                SwingUtilities.replaceUIInputMap(c, condition, null);
0670:            }
0671:
0672:            /**
0673:             * Checks if object is installed by UI or <code>null</code>.
0674:             * @param obj Object to be checked if it is an instance of UIResource or not.
0675:             *
0676:             * @return true if the obj instance of UIResource or null, false otherwise
0677:             */
0678:            public static boolean isUIResource(final Object obj) {
0679:                return (obj == null) || (obj instanceof  UIResource);
0680:            }
0681:
0682:            /**
0683:             * Draws triangle-like arrow (for scrollbars).
0684:             *
0685:             * @param g Grpahics to draw on
0686:             * @param x x-coordinate of the bounding rectangle
0687:             * @param y y-coordinate of the bounding rectangle
0688:             * @param direction of the NORTH, SOUTH, WEST, EAST
0689:             * @param width int representing size of the bounding rectangle
0690:             * @param wide boolean determining if the arrow basis should be wide
0691:             * @param color Color to draw the arrow with
0692:             */
0693:            public static void paintArrow(final Graphics g, final int x,
0694:                    final int y, final int direction, final int width,
0695:                    final boolean wide, final Color color) {
0696:                paintArrow(g, x, y, direction, width, wide, color, false);
0697:            }
0698:
0699:            /**
0700:             * Draws filled triangle-like arrow (for scrollbars).
0701:             *
0702:             * @param g Grpahics to draw on
0703:             * @param x x-coordinate of the bounding rectangle
0704:             * @param y y-coordinate of the bounding rectangle
0705:             * @param direction of the NORTH, SOUTH, WEST, EAST
0706:             * @param width int representing size of the bounding rectangle
0707:             * @param wide boolean determining if the arrow basis should be wide
0708:             * @param color Color to fill the arrow with
0709:             */
0710:            public static void fillArrow(final Graphics g, final int x,
0711:                    final int y, final int direction, final int width,
0712:                    final boolean wide, final Color color) {
0713:                paintArrow(g, x, y, direction, width, wide, color, true);
0714:            }
0715:
0716:            /**
0717:             * Returns mouse pointer location in the screen coordinates.
0718:             * If <code>GraphicsEnvironment.isHeadless()</code> returns
0719:             * <code>true</code> or there is no mouse, <code>null</code> is returned.
0720:             * This function should be used to determine mouse displacement
0721:             * when <code>JFrame</code> is dragged or resized with mouse.
0722:             *
0723:             * @return Point of the current mouse pointer location in the screen coordinates
0724:             * @see java.awt.MouseInfo#getPointerInfo()
0725:             */
0726:            public static Point getMousePointerScreenLocation() {
0727:                Point p = null;
0728:                try {
0729:                    p = AccessController
0730:                            .doPrivileged(new PrivilegedAction<Point>() {
0731:                                public Point run() {
0732:                                    return MouseInfo.getPointerInfo()
0733:                                            .getLocation();
0734:                                }
0735:                            });
0736:                } catch (final HeadlessException ex) {
0737:                }
0738:
0739:                return p;
0740:            }
0741:
0742:            /**
0743:             * Returns parent of <code>c</code> if <code>c</code> is not <code>Window</code> decsendant,
0744:             *  <code>null</code> otherwise.
0745:             *
0746:             *  @param c Component which parent is requested
0747:             *  @return Container where c is located or null if specified component is Window
0748:             */
0749:            public static Container getNotWindowParent(final Component c) {
0750:                return !(c instanceof  Window) ? c.getParent() : null;
0751:            }
0752:
0753:            /**
0754:             * Converts LEADING/TRAILING to LEFT/RIGHT regarding to component orientation.
0755:             * Passes by any other values.
0756:             *
0757:             * @param value to convert
0758:             * @param c component where value is to be applied
0759:             * @return converted value
0760:             */
0761:            public static int convertLeadTrail(final int value,
0762:                    final Component c) {
0763:                final boolean isLTR = (c == null)
0764:                        || c.getComponentOrientation().isLeftToRight();
0765:                if (value == LEADING) {
0766:                    return isLTR ? LEFT : RIGHT;
0767:                }
0768:                if (value == TRAILING) {
0769:                    return isLTR ? RIGHT : LEFT;
0770:                }
0771:                return value;
0772:            }
0773:
0774:            /**
0775:             * Generates accelarator displayed text.
0776:             *
0777:             * @param acc KeyStroke of the accelerator
0778:             * @param delimiter String representation the delimiter of the key in a key sequence
0779:             * @return Accelerator displayed text
0780:             */
0781:            public static String getAcceleratorText(final KeyStroke acc,
0782:                    final String delimiter) {
0783:                if (acc == null) {
0784:                    return null;
0785:                }
0786:
0787:                String text = InputEvent.getModifiersExText(acc.getModifiers());
0788:                if (!delimiter.equals("+")) {
0789:                    text = text.replaceAll("[+]", delimiter);
0790:                }
0791:                if (text.length() > 0) {
0792:                    text += delimiter;
0793:                }
0794:                text += acc.getKeyCode() != KeyEvent.VK_UNDEFINED ? KeyEvent
0795:                        .getKeyText(acc.getKeyCode()) : "" + acc.getKeyChar();
0796:                return text;
0797:            }
0798:
0799:            /**
0800:             * Checks if given key is appropriate constant for vertical alignment, throws IAE otherwise.
0801:             *
0802:             * @param key value to check
0803:             * @param exceptionText text of exception message
0804:             * @return given key
0805:             * @throws IllegalArgumentException with the specified exceptionText if the key is not valid
0806:             */
0807:            public static int checkVerticalKey(final int key,
0808:                    final String exceptionText) {
0809:                switch (key) {
0810:                case TOP:
0811:                case CENTER:
0812:                case BOTTOM:
0813:                    return key;
0814:                default:
0815:                    throw new IllegalArgumentException(exceptionText);
0816:                }
0817:            }
0818:
0819:            /**
0820:             * Checks if given key is appropriate constant for horizontal alignment, throws IAE otherwise.
0821:             *
0822:             * @param key value to check
0823:             * @param exceptionText text of exception message
0824:             * @return given key
0825:             * @throws IllegalArgumentException with the specified exceptionText if the key is not valid
0826:             */
0827:            public static int checkHorizontalKey(final int key,
0828:                    final String exceptionText) {
0829:                switch (key) {
0830:                case RIGHT:
0831:                case LEFT:
0832:                case CENTER:
0833:                case LEADING:
0834:                case TRAILING:
0835:                    return key;
0836:                default:
0837:                    throw new IllegalArgumentException(exceptionText);
0838:                }
0839:            }
0840:
0841:            /**
0842:             * Calculates mnemonic index in the text for the given keyChar.
0843:             *
0844:             * @param text text in which mnemonic index should be found
0845:             * @param mnemonicChar mnemonic char
0846:             * @return index in the text or -1 if there is no index for the specified mnemonic
0847:             */
0848:            public static int getDisplayedMnemonicIndex(final String text,
0849:                    final char mnemonicChar) {
0850:                return text != null ? text.toUpperCase().indexOf(
0851:                        Character.toUpperCase(mnemonicChar)) : -1;
0852:            }
0853:
0854:            /**
0855:             * Returns components that implements MenuElement interface.
0856:             *
0857:             * @param menu container among whose components MenuElements will be looked for
0858:             * @return MenuElements array
0859:             */
0860:            public static MenuElement[] getSubElements(final Container menu) {
0861:                final Component[] components = menu.getComponents();
0862:                final ArrayList<MenuElement> result = new ArrayList<MenuElement>(
0863:                        components.length);
0864:                for (int i = 0; i < components.length; i++) {
0865:                    if (components[i] instanceof  MenuElement) {
0866:                        result.add((MenuElement) components[i]);
0867:                    }
0868:                }
0869:
0870:                return result.toArray(new MenuElement[result.size()]);
0871:            }
0872:
0873:            /**
0874:             * Returns if <code>element</code> is the subElement of <code>container</code>.
0875:             *
0876:             * @param container menu to look for sub element at
0877:             * @param element element to check
0878:             * @return <code>true</code> if <code>element</code> is the subElement of <code>container</code>,
0879:             * <code>false</code> otherwise
0880:             */
0881:            public static boolean isMenuSubElement(final MenuElement container,
0882:                    final MenuElement element) {
0883:                final MenuElement[] subElements = container.getSubElements();
0884:                for (int i = 0; i < subElements.length; i++) {
0885:                    if (subElements[i] == element) {
0886:                        return true;
0887:                    }
0888:                }
0889:                return false;
0890:            }
0891:
0892:            /**
0893:             * Returns menu path of given menuElement up to the <code>JMenuBar</code>.
0894:             *
0895:             * @param element MenuElement which path is requested
0896:             * @return MenuElement[] representing menu path for the specified element
0897:             */
0898:            public static MenuElement[] getMenuElementPath(
0899:                    final MenuElement element) {
0900:                if (!(element instanceof  Container)) {
0901:                    return new MenuElement[0];
0902:                }
0903:                final ArrayList<MenuElement> hierarchy = new ArrayList<MenuElement>();
0904:                Container c = (Container) element;
0905:                do {
0906:                    hierarchy.add(0, (MenuElement) c);
0907:                    if (c instanceof  JMenuBar) {
0908:                        break;
0909:                    }
0910:                    if (c instanceof  JPopupMenu) {
0911:                        c = (Container) ((JPopupMenu) c).getInvoker();
0912:                    } else {
0913:                        c = c.getParent();
0914:                    }
0915:                } while (c != null && c instanceof  MenuElement);
0916:
0917:                return hierarchy.toArray(new MenuElement[hierarchy.size()]);
0918:            }
0919:
0920:            /**
0921:             * Adds item to the corresponding place in the menu selection path.
0922:             * Trims path if necessary.
0923:             *
0924:             * @param path old path
0925:             * @param item element being added
0926:             * @return new path including new element
0927:             */
0928:            public static MenuElement[] addToPath(final MenuElement[] path,
0929:                    final MenuElement item) {
0930:                int commonPathLength;
0931:                for (commonPathLength = 0; commonPathLength < path.length; commonPathLength++) {
0932:                    if (Utilities
0933:                            .isMenuSubElement(path[commonPathLength], item)) {
0934:                        commonPathLength++;
0935:                        break;
0936:                    }
0937:                }
0938:                final MenuElement[] result = new MenuElement[commonPathLength + 1];
0939:                System.arraycopy(path, 0, result, 0, commonPathLength);
0940:                result[result.length - 1] = item;
0941:                return result;
0942:            }
0943:
0944:            /**
0945:             * Gets first visible and enabled item from the list of MenuElements.
0946:             *
0947:             * @param children the list of elements to select from
0948:             * @return visible and enabled element if any, null otherwise
0949:             */
0950:            public static MenuElement getFirstSelectableItem(
0951:                    final MenuElement[] children) {
0952:                if (isEmptyArray(children)) {
0953:                    return null;
0954:                }
0955:
0956:                for (int i = 0; i < children.length; i++) {
0957:                    Component component = children[i].getComponent();
0958:                    if (component == null && children[i] instanceof  Component) {
0959:                        component = (Component) children[i];
0960:                    }
0961:                    if (component != null && component.isVisible()
0962:                            && component.isEnabled()) {
0963:                        return children[i];
0964:                    }
0965:                }
0966:
0967:                return null;
0968:            }
0969:
0970:            /**
0971:             * Checks if the given item is the valid menu path root.
0972:             *
0973:             * @param item MenuItem to be checked
0974:             * @return true if the specified item is valid menu path root, false otherwise
0975:             */
0976:            public static boolean isValidFirstPathElement(final MenuElement item) {
0977:                return (item instanceof  JMenuBar)
0978:                        || ((item instanceof  JPopupMenu) && !(item instanceof  BasicComboPopup));
0979:            }
0980:
0981:            /**
0982:             * Removes element from menu selection path.
0983:             * Trims path if necessary.
0984:             *
0985:             * @param path old path
0986:             * @param item element being removed
0987:             * @return updated path
0988:             */
0989:            public static MenuElement[] removeFromPath(
0990:                    final MenuElement[] path, final MenuElement item) {
0991:                if (isEmptyArray(path)) {
0992:                    return new MenuElement[0];
0993:                }
0994:                int lastSurvivor = path.length - 1;
0995:                for (int i = path.length - 1; i >= 0; i--) {
0996:                    if (path[i] == item) {
0997:                        lastSurvivor = i - 1;
0998:                        break;
0999:                    }
1000:                }
1001:                final MenuElement[] result = new MenuElement[lastSurvivor + 1];
1002:                System.arraycopy(path, 0, result, 0, result.length);
1003:                return result;
1004:            }
1005:
1006:            /**
1007:             * Returns value that lies between given bounds.
1008:             *
1009:             * @param x given value
1010:             * @param min bottom bound for x
1011:             * @param max top bound for x
1012:             * @return min if x less than min, max if x larger than max, x otherwise
1013:             */
1014:            public static int range(final int x, final int min, final int max) {
1015:                return Math.max(min, Math.min(x, max));
1016:            }
1017:
1018:            /**
1019:             * Returns sum of two integers. This function prevents overflow, and
1020:             * if the result were greater than Integer.MAX_VALUE, the maximum
1021:             * integer would be returned.
1022:             * <p><strong>Note:</strong> this does not prevent underflow.
1023:             *
1024:             * @param item1 the first number
1025:             * @param item2 the second number
1026:             * @return the sum
1027:             */
1028:            public static int safeIntSum(final int item1, final int item2) {
1029:                if (item2 > 0) {
1030:                    return (item1 > Integer.MAX_VALUE - item2) ? Integer.MAX_VALUE
1031:                            : item1 + item2;
1032:                }
1033:                // TODO Handle negative values correctly: MIN_VALUE - 1 == MIN_VALUE
1034:                return item1 + item2;
1035:            }
1036:
1037:            /**
1038:             * Checks if <code>underscoreIndex</code> is inside <code>clipped</code>.
1039:             * @param clipped String which may be clipped (partially replaced with "...")
1040:             * @param underscoreIndex the index to check
1041:             * @return <code>true</code> if <code>underscoreIndex</code> is inside
1042:             *         <code>clipped</code>.
1043:             *
1044:             * @see Utilities#clipString(FontMetrics, String, int)
1045:             */
1046:            public static boolean insideString(final String clipped,
1047:                    final int underscoreIndex) {
1048:                return (-1 < underscoreIndex && underscoreIndex < clipped
1049:                        .length());
1050:            }
1051:
1052:            /**
1053:             * Checks if the currently installed Look and feel supports window
1054:             * decorations.
1055:             *
1056:             * @return <code>true</code> if the currently installed Look and feel
1057:             *         is not <code>null</code> and supports window decorations.
1058:             */
1059:            public static boolean lookAndFeelSupportsWindowDecorations() {
1060:                LookAndFeel lnf = UIManager.getLookAndFeel();
1061:                return lnf != null && lnf.getSupportsWindowDecorations();
1062:            }
1063:
1064:            /**
1065:             * Calculates the Container from which paint process should be started. The result
1066:             * can differ from the specified component in case component hierarchy contains
1067:             * JComponents with non-optimized drawing (#see javax.swing.JComponent.isOptimizedDrawingEnabled())
1068:             * and specified component is not on the top child hierarchy. Durign the calculation
1069:             * paintRect should be considered to decide if its overlapped with the potentially
1070:             * overlapping hierarchy or not. Is not curretnly used due to performance reasons.
1071:             *
1072:             * @param c JComponent to be painted
1073:             * @param paintRect region of JComponent to painted. Currently is not used due to
1074:             *                    the performance reasons
1075:             *
1076:             * @return Container from which actual painting to be started
1077:             */
1078:            public static Container getDrawingRoot(final JComponent c,
1079:                    final Rectangle paintRect) {
1080:                Container parent = c.getParent();
1081:                Component child = c;
1082:                Container result = c;
1083:                while (parent instanceof  JComponent) {
1084:                    if (!((JComponent) parent).isOptimizedDrawingEnabled()
1085:                            && ((JComponent) parent).getComponentZOrder(child) != 0) {
1086:
1087:                        result = parent;
1088:                    }
1089:
1090:                    child = parent;
1091:                    parent = parent.getParent();
1092:                }
1093:
1094:                return result;
1095:            }
1096:
1097:            private static int getSuitableSubstringLength(final FontMetrics fm,
1098:                    final String text, final int width) {
1099:                final int textLength = text.length();
1100:                for (int i = 1; i < textLength; i++) {
1101:                    final int substrWidth = fm
1102:                            .stringWidth(text.substring(0, i));
1103:                    if (substrWidth > width) {
1104:                        return i - 1;
1105:                    }
1106:                }
1107:
1108:                return textLength;
1109:            }
1110:
1111:            private static Rectangle getScreenClientBounds(
1112:                    final GraphicsConfiguration graphConfig) {
1113:                GraphicsConfiguration gc = graphConfig;
1114:                if (gc == null) {
1115:                    gc = GraphicsEnvironment.getLocalGraphicsEnvironment()
1116:                            .getDefaultScreenDevice().getDefaultConfiguration();
1117:                }
1118:                final Rectangle screenRect = gc.getBounds();
1119:                final Insets screenInsets = Toolkit.getDefaultToolkit()
1120:                        .getScreenInsets(gc);
1121:                return subtractInsets(screenRect, screenInsets);
1122:            }
1123:
1124:            private static void paintArrow(final Graphics g, final int x,
1125:                    final int y, final int direction, final int size,
1126:                    final boolean wide, final Color color, final boolean fill) {
1127:
1128:                final int halfHeight = (size + 1) / 2;
1129:                final int height = halfHeight * 2;
1130:                final int width = wide ? halfHeight : height;
1131:
1132:                final int[] heights = new int[] { 0, halfHeight - 1, height - 2 };
1133:                final int[] lWidths = new int[] { width - 1, 0, width - 1 };
1134:                final int[] rWidths = new int[] { 0, width - 1, 0 };
1135:                int[] px = null;
1136:                int[] py = null;
1137:                switch (direction) {
1138:                case NORTH:
1139:                    px = heights;
1140:                    py = lWidths;
1141:                    break;
1142:                case SOUTH:
1143:                    px = heights;
1144:                    py = rWidths;
1145:                    break;
1146:                case WEST:
1147:                case LEFT:
1148:                    px = lWidths;
1149:                    py = heights;
1150:                    break;
1151:                case EAST:
1152:                case RIGHT:
1153:                    px = rWidths;
1154:                    py = heights;
1155:                    break;
1156:                default:
1157:                    assert false : "incorrect direction";
1158:                    return;
1159:                }
1160:
1161:                final Color oldColor = g.getColor();
1162:                g.setColor(color);
1163:                g.translate(x, y);
1164:                g.drawPolygon(px, py, 3);
1165:                if (fill) {
1166:                    g.fillPolygon(px, py, 3);
1167:                }
1168:                g.translate(-x, -y);
1169:                g.setColor(oldColor);
1170:            }
1171:
1172:            private static int horizontallyAlignRect(final int rectWidth,
1173:                    final Rectangle box, final int horizontalAlign) {
1174:                int result = 0;
1175:                if (horizontalAlign != LEFT) {
1176:                    result = box.width - rectWidth;
1177:                    if (horizontalAlign == CENTER) {
1178:                        result /= 2;
1179:                    }
1180:                }
1181:                result += box.x;
1182:                return result;
1183:            }
1184:
1185:            private static int verticallyAlignRect(final int rectHeight,
1186:                    final Rectangle box, final int verticalAlign) {
1187:                int result = 0;
1188:                if (verticalAlign != TOP) {
1189:                    result = box.height - rectHeight;
1190:                    if (verticalAlign == CENTER) {
1191:                        result /= 2;
1192:                    }
1193:                }
1194:                result += box.y;
1195:                return result;
1196:            }
1197:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.