Source Code Cross Referenced for QuaquaUtilities.java in  » Swing-Library » substance-look-feel » contrib » ch » randelshofer » quaqua » 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 » Swing Library » substance look feel » contrib.ch.randelshofer.quaqua 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * @(#)QuaquaUtilities.java  3.1  2006-09-04
003:         *
004:         * Copyright (c) 2003-2006 Werner Randelshofer
005:         * Staldenmattweg 2, Immensee, CH-6405, Switzerland.
006:         * All rights reserved.
007:         *
008:         * This software is the confidential and proprietary information of
009:         * Werner Randelshofer. ("Confidential Information").  You shall not
010:         * disclose such Confidential Information and shall use it only in
011:         * accordance with the terms of the license agreement you entered into
012:         * with Werner Randelshofer.
013:         */
014:
015:        package contrib.ch.randelshofer.quaqua;
016:
017:        import java.applet.*;
018:        import java.awt.*;
019:        import java.awt.event.*;
020:        import java.awt.font.*;
021:        import java.awt.image.*;
022:        import java.awt.peer.*;
023:        import java.net.*;
024:        import javax.swing.*;
025:        import javax.swing.text.*;
026:        import javax.swing.border.*;
027:        import javax.swing.plaf.*;
028:        import javax.swing.plaf.basic.*;
029:
030:        import contrib.ch.randelshofer.quaqua.util.*;
031:
032:        /**
033:         * Utility class for the Quaqua LAF.
034:         *
035:         * @author Werner Randelshofer, Staldenmattweg 2, CH-6405 Immensee, Switzerland
036:         * @version 3.1 2006-09-04 Added method compositeRequestFocus.
037:         * <br>3.0.5 2006-08-20 Method endGraphics must not set
038:         * KEY_TEXT_ANTIALIASING to null.
039:         * <br>3.0.4 2006-02-19 Catch Throwable in method setWindowAlpha instead
040:         * of catching NoSuchMethodException.
041:         * <br>3.0.3 2006-01-08 Don't set Window alpha, when running on
042:         * Java 1.4.2_05 on Mac OS X 10.3.5. Because this only has the effect of turning
043:         * the background color of the Window to white.
044:         * <br>3.0.2 2005-12-10 Method isOnActiveWindow() did not reliably
045:         * return true.
046:         * <br>3.0.1 2005-11-12 Fixed NPE in method repaint border.
047:         * <br>3.0 2005-09-24 Removed all reflection helper methods. Moved Sheet
048:         * helper methods out into class Sheets.
049:         * <br>2.6 2005-09-17 Method isOnFocusedWindow returns true, if
050:         * the window returns false on "getFocusableWindowState".
051:         * <br>2.5 2005-03-13 Renamed method isFrameActive to isOnActiveFrame.
052:         * <br>2.4 2004-12-28 Method createBufferdImage added. Method
053:         * isOnActiveWindow() renamed to isFrameActive().
054:         * <br>2.3 2004-12-14 Method getUI added.
055:         * <br>2.2.1 2004-12-01 Methods setDragEnabled and getDragEnabled never
056:         * worked because the attempted to get method objects on the wrong class.
057:         * <br>2.2 2004-09-19 Refined algorithm of method isFrameActive.
058:         * <br>2.1 2004-07-04 Methods repaintBorder, beginFont, endFont and
059:         * isFocused added.
060:         * <br>2.0 2004-04-27 Renamed from QuaquaGraphicUtils to QuaquaUtilities.
061:         * Added method isFrameActive(Component).
062:         * <br>1.1.1 2003-10-08 Diagnostic output to System.out removed.
063:         * <br>1.1 2003-10-05 Methods getModifiersText and getModifiersUnicode
064:         * added.
065:         * <br>1.0 2003-07-19 Created.
066:         */
067:        public class QuaquaUtilities extends BasicGraphicsUtils implements 
068:                SwingConstants {
069:            /** Prevent instance creation. */
070:            private QuaquaUtilities() {
071:            }
072:
073:            /*
074:             * Convenience function for determining ComponentOrientation.  Helps us
075:             * avoid having Munge directives throughout the code.
076:             */
077:            public static boolean isLeftToRight(Component c) {
078:                return c.getComponentOrientation().isLeftToRight();
079:            }
080:
081:            /**
082:             * Draw a string with the graphics <code>g</code> at location
083:             * (<code>x</code>, <code>y</code>)
084:             * just like <code>g.drawString</code> would.
085:             * The character at index <code>underlinedIndex</code>
086:             * in text will be underlined. If <code>index</code> is beyond the
087:             * bounds of <code>text</code> (including < 0), nothing will be
088:             * underlined.
089:             *
090:             * @param g Graphics to draw with
091:             * @param text String to draw
092:             * @param underlinedIndex Index of character in text to underline
093:             * @param x x coordinate to draw at
094:             * @param y y coordinate to draw at
095:             * @since 1.4
096:             */
097:            public static void drawStringUnderlineCharAt(Graphics g,
098:                    String text, int underlinedIndex, int x, int y) {
099:                g.drawString(text, x, y);
100:                if (underlinedIndex >= 0 && underlinedIndex < text.length()) {
101:                    FontMetrics fm = g.getFontMetrics();
102:                    int underlineRectX = x
103:                            + fm
104:                                    .stringWidth(text.substring(0,
105:                                            underlinedIndex));
106:                    int underlineRectY = y;
107:                    int underlineRectWidth = fm.charWidth(text
108:                            .charAt(underlinedIndex));
109:                    int underlineRectHeight = 1;
110:                    g.fillRect(underlineRectX, underlineRectY + fm.getDescent()
111:                            - 1, underlineRectWidth, underlineRectHeight);
112:                }
113:            }
114:
115:            /**
116:             * Returns index of the first occurrence of <code>mnemonic</code>
117:             * within string <code>text</code>. Matching algorithm is not
118:             * case-sensitive.
119:             *
120:             * @param text The text to search through, may be null
121:             * @param mnemonic The mnemonic to find the character for.
122:             * @return index into the string if exists, otherwise -1
123:             */
124:            static int findDisplayedMnemonicIndex(String text, int mnemonic) {
125:                if (text == null || mnemonic == '\0') {
126:                    return -1;
127:                }
128:
129:                char uc = Character.toUpperCase((char) mnemonic);
130:                char lc = Character.toLowerCase((char) mnemonic);
131:
132:                int uci = text.indexOf(uc);
133:                int lci = text.indexOf(lc);
134:
135:                if (uci == -1) {
136:                    return lci;
137:                } else if (lci == -1) {
138:                    return uci;
139:                } else {
140:                    return (lci < uci) ? lci : uci;
141:                }
142:            }
143:
144:            /**
145:             * Returns true if the component is on a Dialog or a Frame, which is active,
146:             * or if it is on a Window, which is focused.
147:             * Always returns true, if the component has no parent window.
148:             */
149:            public static boolean isOnActiveWindow(Component c) {
150:                // In the RootPaneUI, we set a client property on the whole component
151:                // tree, if the ancestor Frame gets activated or deactivated.
152:                if (c instanceof  JComponent) {
153:                    Boolean value = (Boolean) ((JComponent) c)
154:                            .getClientProperty("Frame.active");
155:                    // Unfortunately, the value is not always reliable.
156:                    // Therefore we can only do a short circuit, if the value is true.
157:                    if (value != null && value.booleanValue()) {
158:                        return true;
159:                        //return value.booleanValue();
160:                    }
161:                }
162:                /*
163:                // This is how I would have implemented the code, if Quaqua would
164:                // not be required to work an a Java 1.3 VM.
165:                Window window = SwingUtilities.getWindowAncestor(c);
166:                if (window == null) {
167:                    return true;
168:                } else if ((window instanceof Frame) || (window instanceof Dialog)) {
169:                    return window.isActive();
170:                } else {
171:                    if (window.getFocusableWindowState()) {
172:                        return window.isFocused();
173:                    } else {
174:                        return true;
175:                    }
176:                }
177:                 */
178:
179:                // If we missed the client property or if it was false, we have to
180:                // figure out the activation state on our own.
181:                // The following code works from Java 1.3 onwards.
182:                Window window = SwingUtilities.getWindowAncestor(c);
183:                boolean isOnActiveWindow;
184:                if (window == null) {
185:                    isOnActiveWindow = true;
186:                } else if ((window instanceof  Frame)
187:                        || (window instanceof  Dialog)) {
188:                    isOnActiveWindow = Methods.invokeGetter(window, "isActive",
189:                            true);
190:                } else {
191:                    if (Methods.invokeGetter(window, "getFocusableWindowState",
192:                            true)) {
193:                        isOnActiveWindow = Methods.invokeGetter(window,
194:                                "isFocused", true);
195:                    } else {
196:                        isOnActiveWindow = true;
197:                    }
198:                }
199:
200:                // In case the activation property is true, we fix the value of the
201:                // client property, so that we can do a short circuit next time.
202:                if (isOnActiveWindow && (c instanceof  JComponent)) {
203:                    ((JComponent) c).putClientProperty("Frame.active",
204:                            new Boolean(isOnActiveWindow));
205:                }
206:                return isOnActiveWindow;
207:            }
208:
209:            /**
210:             * Returns a Mac OS X specific String describing the modifier key(s),
211:             * such as "Shift", or "Ctrl+Shift".
212:             *
213:             * @return string a text description of the combination of modifier
214:             *                keys that were held down during the event
215:             */
216:            public static String getKeyModifiersText(int modifiers,
217:                    boolean leftToRight) {
218:                return getKeyModifiersUnicode(modifiers, leftToRight);
219:            }
220:
221:            static String getKeyModifiersUnicode(int modifiers,
222:                    boolean leftToRight) {
223:                char[] cs = new char[4];
224:                int count = 0;
225:                if (leftToRight) {
226:                    if ((modifiers & InputEvent.CTRL_MASK) != 0)
227:                        cs[count++] = '\u2303'; // Unicode: UP ARROWHEAD
228:                    if ((modifiers & (InputEvent.ALT_MASK | InputEvent.ALT_GRAPH_MASK)) != 0)
229:                        cs[count++] = '\u2325'; // Unicode: OPTION KEY
230:                    if ((modifiers & InputEvent.SHIFT_MASK) != 0)
231:                        cs[count++] = '\u21e7'; // Unicode: UPWARDS WHITE ARROW
232:                    if ((modifiers & InputEvent.META_MASK) != 0)
233:                        cs[count++] = '\u2318'; // Unicode: PLACE OF INTEREST SIGN
234:                } else {
235:                    if ((modifiers & InputEvent.META_MASK) != 0)
236:                        cs[count++] = '\u2318'; // Unicode: PLACE OF INTEREST SIGN
237:                    if ((modifiers & InputEvent.SHIFT_MASK) != 0)
238:                        cs[count++] = '\u21e7'; // Unicode: UPWARDS WHITE ARROW
239:                    if ((modifiers & (InputEvent.ALT_MASK | InputEvent.ALT_GRAPH_MASK)) != 0)
240:                        cs[count++] = '\u2325'; // Unicode: OPTION KEY
241:                    if ((modifiers & InputEvent.CTRL_MASK) != 0)
242:                        cs[count++] = '\u2303'; // Unicode: UP ARROWHEAD
243:                }
244:                return new String(cs, 0, count);
245:            }
246:
247:            public static void repaintBorder(JComponent component) {
248:                JComponent c = component;
249:                Border border = null;
250:                Container container = component.getParent();
251:                if (container instanceof  JViewport) {
252:                    c = (JComponent) container.getParent();
253:                    if (c != null) {
254:                        border = c.getBorder();
255:                    }
256:                }
257:                if (border == null) {
258:                    border = component.getBorder();
259:                    c = component;
260:                }
261:                if (border != null && c != null) {
262:                    int w = c.getWidth();
263:                    int h = c.getHeight();
264:                    Insets insets = c.getInsets();
265:                    c.repaint(0, 0, w, insets.top);
266:                    c.repaint(0, 0, insets.left, h);
267:                    c.repaint(0, h - insets.bottom, w, insets.bottom);
268:                    c.repaint(w - insets.right, 0, insets.right, h);
269:                }
270:            }
271:
272:            public static final Object beginGraphics(Graphics2D graphics2d) {
273:                Object object = graphics2d
274:                        .getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING);
275:                graphics2d.setRenderingHint(
276:                        RenderingHints.KEY_TEXT_ANTIALIASING,
277:                        RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
278:                return object;
279:            }
280:
281:            public static final void endGraphics(Graphics2D graphics2d,
282:                    Object oldHints) {
283:                if (oldHints != null) {
284:                    graphics2d.setRenderingHint(
285:                            RenderingHints.KEY_TEXT_ANTIALIASING, oldHints);
286:                }
287:            }
288:
289:            public static final boolean isFocused(Component component) {
290:                if (QuaquaUtilities.isOnActiveWindow(component)) {
291:                    Component c = component;
292:                    if (c instanceof  JComponent) {
293:                        if (c instanceof  JScrollPane) {
294:                            JViewport viewport = ((JScrollPane) component)
295:                                    .getViewport();
296:                            if (viewport != null) {
297:                                c = viewport.getView();
298:                            }
299:                        }
300:                        if (c instanceof  JTextComponent
301:                                && !((JTextComponent) c).isEditable()) {
302:                            return false;
303:                        }
304:                        return c != null
305:                                && (((JComponent) c).hasFocus() || ((JComponent) c)
306:                                        .getClientProperty("Quaqua.drawFocusBorder") == Boolean.TRUE);
307:                    }
308:                }
309:                return false;
310:            }
311:
312:            static boolean isHeadless() {
313:                return Methods.invokeStaticGetter(GraphicsEnvironment.class,
314:                        "isHeadless", false);
315:            }
316:
317:            public static int getLeftSideBearing(Font f, String string) {
318:                return ((Integer) Methods.invokeStatic(
319:                        "com.sun.java.swing.SwingUtilities2",
320:                        "getLeftSideBearing", new Class[] { Font.class,
321:                                String.class }, new Object[] { f, string },
322:                        new Integer(0))).intValue();
323:            }
324:
325:            /**
326:             * Invoked when the user attempts an invalid operation,
327:             * such as pasting into an uneditable <code>JTextField</code>
328:             * that has focus. The default implementation beeps. Subclasses
329:             * that wish different behavior should override this and provide
330:             * the additional feedback.
331:             *
332:             * @param component Component the error occured in, may be null
333:             *			indicating the error condition is not directly
334:             *			associated with a <code>Component</code>.
335:             */
336:            static void provideErrorFeedback(Component component) {
337:                Toolkit toolkit = null;
338:                if (component != null) {
339:                    toolkit = component.getToolkit();
340:                } else {
341:                    toolkit = Toolkit.getDefaultToolkit();
342:                }
343:                toolkit.beep();
344:            } // provideErrorFeedback()
345:
346:            public static BufferedImage createBufferedImage(URL location) {
347:                Image image = Toolkit.getDefaultToolkit().createImage(location);
348:                BufferedImage buf;
349:                if (image instanceof  BufferedImage) {
350:                    buf = (BufferedImage) image;
351:                } else {
352:                    loadImage(image);
353:                    //buf = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
354:                    buf = GraphicsEnvironment.getLocalGraphicsEnvironment()
355:                            .getDefaultScreenDevice().getDefaultConfiguration()
356:                            .createCompatibleImage(image.getWidth(null),
357:                                    image.getHeight(null), Transparency.OPAQUE);
358:
359:                    Graphics g = buf.getGraphics();
360:                    g.drawImage(image, 0, 0, null);
361:                    g.dispose();
362:                    image.flush();
363:                }
364:                return buf;
365:            }
366:
367:            public static TexturePaint createTexturePaint(URL location) {
368:                BufferedImage texture = createBufferedImage(location);
369:                TexturePaint paint = new TexturePaint(texture, new Rectangle(0,
370:                        0, texture.getWidth(), texture.getHeight()));
371:                return paint;
372:            }
373:
374:            /**
375:             * Loads the image, returning only when the image is loaded.
376:             * @param image the image
377:             */
378:            private static void loadImage(Image image) {
379:                Component component = new Component() {
380:                };
381:                MediaTracker tracker = new MediaTracker(component);
382:                synchronized (tracker) {
383:                    int id = 0;
384:
385:                    tracker.addImage(image, id);
386:                    try {
387:                        tracker.waitForID(id, 0);
388:                    } catch (InterruptedException e) {
389:                        System.out.println("INTERRUPTED while loading Image");
390:                    }
391:                    int loadStatus = tracker.statusID(id, false);
392:                    tracker.removeImage(image, id);
393:                }
394:            }
395:
396:            /**
397:             * Compute and return the location of the icons origin, the
398:             * location of origin of the text baseline, and a possibly clipped
399:             * version of the compound labels string.  Locations are computed
400:             * relative to the viewR rectangle.
401:             * The JComponents orientation (LEADING/TRAILING) will also be taken
402:             * into account and translated into LEFT/RIGHT values accordingly.
403:             */
404:            public static String layoutCompoundLabel(JComponent c,
405:                    FontMetrics fm, String text, Icon icon,
406:                    int verticalAlignment, int horizontalAlignment,
407:                    int verticalTextPosition, int horizontalTextPosition,
408:                    Rectangle viewR, Rectangle iconR, Rectangle textR,
409:                    int textIconGap) {
410:                boolean orientationIsLeftToRight = true;
411:                int hAlign = horizontalAlignment;
412:                int hTextPos = horizontalTextPosition;
413:
414:                if (c != null) {
415:                    if (!(c.getComponentOrientation().isLeftToRight())) {
416:                        orientationIsLeftToRight = false;
417:                    }
418:                }
419:
420:                // Translate LEADING/TRAILING values in horizontalAlignment
421:                // to LEFT/RIGHT values depending on the components orientation
422:                switch (horizontalAlignment) {
423:                case LEADING:
424:                    hAlign = (orientationIsLeftToRight) ? LEFT : RIGHT;
425:                    break;
426:                case TRAILING:
427:                    hAlign = (orientationIsLeftToRight) ? RIGHT : LEFT;
428:                    break;
429:                }
430:
431:                // Translate LEADING/TRAILING values in horizontalTextPosition
432:                // to LEFT/RIGHT values depending on the components orientation
433:                switch (horizontalTextPosition) {
434:                case LEADING:
435:                    hTextPos = (orientationIsLeftToRight) ? LEFT : RIGHT;
436:                    break;
437:                case TRAILING:
438:                    hTextPos = (orientationIsLeftToRight) ? RIGHT : LEFT;
439:                    break;
440:                }
441:
442:                return layoutCompoundLabelImpl(c, fm, text, icon,
443:                        verticalAlignment, hAlign, verticalTextPosition,
444:                        hTextPos, viewR, iconR, textR, textIconGap);
445:            }
446:
447:            /**
448:             * Compute and return the location of the icons origin, the
449:             * location of origin of the text baseline, and a possibly clipped
450:             * version of the compound labels string.  Locations are computed
451:             * relative to the viewR rectangle.
452:             * This layoutCompoundLabel() does not know how to handle LEADING/TRAILING
453:             * values in horizontalTextPosition (they will default to RIGHT) and in
454:             * horizontalAlignment (they will default to CENTER).
455:             * Use the other version of layoutCompoundLabel() instead.
456:             */
457:            public static String layoutCompoundLabel(FontMetrics fm,
458:                    String text, Icon icon, int verticalAlignment,
459:                    int horizontalAlignment, int verticalTextPosition,
460:                    int horizontalTextPosition, Rectangle viewR,
461:                    Rectangle iconR, Rectangle textR, int textIconGap) {
462:                return layoutCompoundLabelImpl(null, fm, text, icon,
463:                        verticalAlignment, horizontalAlignment,
464:                        verticalTextPosition, horizontalTextPosition, viewR,
465:                        iconR, textR, textIconGap);
466:            }
467:
468:            /**
469:             * Compute and return the location of the icons origin, the
470:             * location of origin of the text baseline, and a possibly clipped
471:             * version of the compound labels string.  Locations are computed
472:             * relative to the viewR rectangle.
473:             * This layoutCompoundLabel() does not know how to handle LEADING/TRAILING
474:             * values in horizontalTextPosition (they will default to RIGHT) and in
475:             * horizontalAlignment (they will default to CENTER).
476:             * Use the other version of layoutCompoundLabel() instead.
477:             *
478:             * This is the same as SwingUtilities.layoutCompoundLabelImpl, except for
479:             * the algorithm for clipping the text. If a text is too long, "..." are
480:             * inserted at the middle of the text instead of at the end.
481:             */
482:            private static String layoutCompoundLabelImpl(JComponent c,
483:                    FontMetrics fm, String text, Icon icon,
484:                    int verticalAlignment, int horizontalAlignment,
485:                    int verticalTextPosition, int horizontalTextPosition,
486:                    Rectangle viewR, Rectangle iconR, Rectangle textR,
487:                    int textIconGap) {
488:                /* Initialize the icon bounds rectangle iconR.
489:                 */
490:
491:                if (icon != null) {
492:                    iconR.width = icon.getIconWidth();
493:                    iconR.height = icon.getIconHeight();
494:                } else {
495:                    iconR.width = iconR.height = 0;
496:                }
497:
498:                /* Initialize the text bounds rectangle textR.  If a null
499:                 * or and empty String was specified we substitute "" here
500:                 * and use 0,0,0,0 for textR.
501:                 */
502:
503:                boolean textIsEmpty = (text == null) || text.equals("");
504:                int lsb = 0;
505:
506:                View v = null;
507:                if (textIsEmpty) {
508:                    textR.width = textR.height = 0;
509:                    text = "";
510:                } else {
511:                    v = (c != null) ? (View) c.getClientProperty("html") : null;
512:                    if (v != null) {
513:                        textR.width = (int) v.getPreferredSpan(View.X_AXIS);
514:                        textR.height = (int) v.getPreferredSpan(View.Y_AXIS);
515:                    } else {
516:                        textR.width = SwingUtilities.computeStringWidth(fm,
517:                                text);
518:
519:                        lsb = getLeftSideBearing(fm.getFont(), text);
520:                        if (lsb < 0) {
521:                            // If lsb is negative, add it to the width, the
522:                            // text bounds will later be adjusted accordingly.
523:                            textR.width -= lsb;
524:                        }
525:                        textR.height = fm.getHeight();
526:                    }
527:                }
528:
529:                /* Unless both text and icon are non-null, we effectively ignore
530:                 * the value of textIconGap.  The code that follows uses the
531:                 * value of gap instead of textIconGap.
532:                 */
533:
534:                int gap = (textIsEmpty || (icon == null)) ? 0 : textIconGap;
535:
536:                if (!textIsEmpty) {
537:
538:                    /* If the label text string is too wide to fit within the available
539:                     * space "..." and as many characters as will fit will be
540:                     * displayed instead.
541:                     */
542:
543:                    int availTextWidth;
544:
545:                    if (horizontalTextPosition == CENTER) {
546:                        availTextWidth = viewR.width;
547:                    } else {
548:                        availTextWidth = viewR.width - (iconR.width + gap);
549:                    }
550:
551:                    if (textR.width > availTextWidth) {
552:                        if (v != null) {
553:                            textR.width = availTextWidth;
554:                        } else {
555:                            String clipString = "...";
556:                            int totalWidth = SwingUtilities.computeStringWidth(
557:                                    fm, clipString);
558:                            int nChars;
559:                            int len = text.length();
560:                            for (nChars = 0; nChars < len; nChars++) {
561:                                int charIndex = (nChars % 2 == 0) ? nChars / 2
562:                                        : len - 1 - nChars / 2;
563:                                totalWidth += fm.charWidth(text
564:                                        .charAt(charIndex));
565:                                if (totalWidth > availTextWidth) {
566:                                    break;
567:                                }
568:                            }
569:                            text = text.substring(0, nChars / 2) + clipString
570:                                    + text.substring(len - nChars / 2);
571:                            textR.width = SwingUtilities.computeStringWidth(fm,
572:                                    text);
573:                        }
574:                    }
575:                }
576:
577:                /* Compute textR.x,y given the verticalTextPosition and
578:                 * horizontalTextPosition properties
579:                 */
580:
581:                if (verticalTextPosition == TOP) {
582:                    if (horizontalTextPosition != CENTER) {
583:                        textR.y = 0;
584:                    } else {
585:                        textR.y = -(textR.height + gap);
586:                    }
587:                } else if (verticalTextPosition == CENTER) {
588:                    textR.y = (iconR.height / 2) - (textR.height / 2);
589:                } else { // (verticalTextPosition == BOTTOM)
590:                    if (horizontalTextPosition != CENTER) {
591:                        textR.y = iconR.height - textR.height;
592:                    } else {
593:                        textR.y = (iconR.height + gap);
594:                    }
595:                }
596:
597:                if (horizontalTextPosition == LEFT) {
598:                    textR.x = -(textR.width + gap);
599:                } else if (horizontalTextPosition == CENTER) {
600:                    textR.x = (iconR.width / 2) - (textR.width / 2);
601:                } else { // (horizontalTextPosition == RIGHT)
602:                    textR.x = (iconR.width + gap);
603:                }
604:
605:                /* labelR is the rectangle that contains iconR and textR.
606:                 * Move it to its proper position given the labelAlignment
607:                 * properties.
608:                 *
609:                 * To avoid actually allocating a Rectangle, Rectangle.union
610:                 * has been inlined below.
611:                 */
612:                int labelR_x = Math.min(iconR.x, textR.x);
613:                int labelR_width = Math.max(iconR.x + iconR.width, textR.x
614:                        + textR.width)
615:                        - labelR_x;
616:                int labelR_y = Math.min(iconR.y, textR.y);
617:                int labelR_height = Math.max(iconR.y + iconR.height, textR.y
618:                        + textR.height)
619:                        - labelR_y;
620:
621:                int dx, dy;
622:
623:                if (verticalAlignment == TOP) {
624:                    dy = viewR.y - labelR_y;
625:                } else if (verticalAlignment == CENTER) {
626:                    dy = (viewR.y + (viewR.height / 2))
627:                            - (labelR_y + (labelR_height / 2));
628:                } else { // (verticalAlignment == BOTTOM)
629:                    dy = (viewR.y + viewR.height) - (labelR_y + labelR_height);
630:                }
631:
632:                if (horizontalAlignment == LEFT) {
633:                    dx = viewR.x - labelR_x;
634:                } else if (horizontalAlignment == RIGHT) {
635:                    dx = (viewR.x + viewR.width) - (labelR_x + labelR_width);
636:                } else { // (horizontalAlignment == CENTER)
637:                    dx = (viewR.x + (viewR.width / 2))
638:                            - (labelR_x + (labelR_width / 2));
639:                }
640:
641:                /* Translate textR and glypyR by dx,dy.
642:                 */
643:
644:                textR.x += dx;
645:                textR.y += dy;
646:
647:                iconR.x += dx;
648:                iconR.y += dy;
649:
650:                if (lsb < 0) {
651:                    // lsb is negative. We previously adjusted the bounds by lsb,
652:                    // we now need to shift the x location so that the text is
653:                    // drawn at the right location. The result is textR does not
654:                    // line up with the actual bounds (on the left side), but we will
655:                    // have provided enough space for the text.
656:                    textR.width += lsb;
657:                    textR.x -= lsb;
658:                }
659:
660:                return text;
661:            }
662:
663:            public static void configureGraphics(Graphics gr) {
664:                Graphics2D g = (Graphics2D) gr;
665:                g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
666:                        RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
667:                g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
668:                        RenderingHints.VALUE_ANTIALIAS_ON);
669:                g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
670:                        RenderingHints.VALUE_FRACTIONALMETRICS_ON);
671:            }
672:
673:            /** Copied from BasicLookAndFeel.
674:             */
675:            public static Component compositeRequestFocus(Component component) {
676:                try {
677:                    if (component instanceof  Container) {
678:                        Container container = (Container) component;
679:                        if (Methods.invokeGetter(container, "isFocusCycleRoot",
680:                                false)) {
681:
682:                            Object policy = Methods.invokeGetter(container,
683:                                    "getFocusTraversalPolicy", null);
684:                            Component comp = (Component) Methods.invoke(policy,
685:                                    "getDefaultComponent", Container.class,
686:                                    container);
687:                            if (comp != null) {
688:                                comp.requestFocus();
689:                                return comp;
690:                            }
691:                        }
692:                        Container rootAncestor = (Container) Methods
693:                                .invokeGetter(container,
694:                                        "getFocusCycleRootAncestor", null);
695:                        if (rootAncestor != null) {
696:                            Object policy = Methods.invokeGetter(rootAncestor,
697:                                    "getFocusTraversalPolicy", null);
698:                            Component comp = (Component) Methods.invoke(policy,
699:                                    "getComponentAfter", new Class[] {
700:                                            Container.class, Component.class },
701:                                    new Object[] { rootAncestor, container });
702:
703:                            if (comp != null
704:                                    && SwingUtilities.isDescendingFrom(comp,
705:                                            container)) {
706:                                comp.requestFocus();
707:                                return comp;
708:                            }
709:                        }
710:                    }
711:                } catch (NoSuchMethodException e) {
712:                    // ignore
713:                }
714:                if (Methods.invokeGetter(component, "isFocusable", true)) {
715:                    component.requestFocus();
716:                    return component;
717:                }
718:                return null;
719:            }
720:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.