Source Code Cross Referenced for Text.java in  » 6.0-JDK-Modules » j2me » com » sun » midp » lcdui » 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 » 6.0 JDK Modules » j2me » com.sun.midp.lcdui 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *   
0003:         *
0004:         * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved. 
0005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER 
0006:         *  
0007:         * This program is free software; you can redistribute it and/or 
0008:         * modify it under the terms of the GNU General Public License version 
0009:         * 2 only, as published by the Free Software Foundation. 
0010:         *  
0011:         * This program is distributed in the hope that it will be useful, but 
0012:         * WITHOUT ANY WARRANTY; without even the implied warranty of 
0013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
0014:         * General Public License version 2 for more details (a copy is 
0015:         * included at /legal/license.txt). 
0016:         *  
0017:         * You should have received a copy of the GNU General Public License 
0018:         * version 2 along with this work; if not, write to the Free Software 
0019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 
0020:         * 02110-1301 USA 
0021:         *  
0022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa 
0023:         * Clara, CA 95054 or visit www.sun.com if you need additional 
0024:         * information or have any questions.
0025:         */
0026:
0027:        package com.sun.midp.lcdui;
0028:
0029:        import javax.microedition.lcdui.Font;
0030:        import javax.microedition.lcdui.Graphics;
0031:
0032:        import com.sun.midp.chameleon.skins.StringItemSkin;
0033:        import com.sun.midp.i18n.Resource;
0034:        import com.sun.midp.i18n.ResourceConstants;
0035:
0036:        /**
0037:         * Static method class use to draw and size text.
0038:         */
0039:
0040:        public class Text {
0041:
0042:            /** Character to be used as a truncation indiactor,
0043:             *  for example, \u2026 which is ellipsis (...). */
0044:            private static final char truncationMark = Resource.getString(
0045:                    ResourceConstants.TRUNCATION_MARK).charAt(0);//'\u2026';
0046:
0047:            // the following are used in calling the getNextLine method
0048:
0049:            /** Line start. */
0050:            private static final int GNL_LINE_START = 0;
0051:            /** Line end. */
0052:            private static final int GNL_LINE_END = 1;
0053:            /** New line start. */
0054:            private static final int GNL_NEW_LINE_START = 2;
0055:            /** Screen width available. */
0056:            private static final int GNL_WIDTH = 3;
0057:            /** Screen height available. */
0058:            private static final int GNL_HEIGHT = 4;
0059:            /** Font height. */
0060:            private static final int GNL_FONT_HEIGHT = 5;
0061:            /** Line number. */
0062:            private static final int GNL_NUM_LINES = 6;
0063:            /** Text options (NORMAL, INVERT...) see below. */
0064:            private static final int GNL_OPTIONS = 7;
0065:            /** Text pixel offset. */
0066:            private static final int GNL_OFFSET = 8;
0067:            /** Width of the ellipsis in the current font. */
0068:            private static final int GNL_ELLIP_WIDTH = 9;
0069:            /** Line width in pixels. */
0070:            private static final int GNL_LINE_WIDTH = 10;
0071:
0072:            /** Number of GNL_ parameter constants. */
0073:            private static final int GNL_NUM_PARAMS = 11;
0074:
0075:            // constants to affect how text drawing is handled
0076:            // These values can be OR'd together. no error checking is performed
0077:
0078:            /** NORMAL text. */
0079:            public static final int NORMAL = 0x0;
0080:            /** INVERTED text color. */
0081:            public static final int INVERT = 0x1;
0082:            /** Draw a hyperlink for the text. */
0083:            public static final int HYPERLINK = 0x2;
0084:            /** Truncate the text and put a "..." if the text doesn't fit the bounds. */
0085:            public static final int TRUNCATE = 0x4;
0086:
0087:            // these values are stored used as setting in a TextCursor object
0088:            /** 
0089:             * When a paint occurs use the cursor index to know when to
0090:             * paint the cursor.
0091:             */
0092:            public static final int PAINT_USE_CURSOR_INDEX = 0;
0093:
0094:            /** 
0095:             * When a paint occurs try to find the best value for the cursor
0096:             * index based on the x,y coordinates of the cursor.
0097:             */
0098:            public static final int PAINT_GET_CURSOR_INDEX = 1;
0099:
0100:            /**
0101:             * Don't draw a cursor.
0102:             */
0103:            public static final int PAINT_HIDE_CURSOR = 2;
0104:
0105:            /**
0106:             * Sets up a new inout structure used in various 
0107:             * text methods.
0108:             * @param font the font to use
0109:             * @param w the available width for the text
0110:             * @param h the available height for the text
0111:             * @param options any of NORMAL | INVERT | HYPERLINK | TRUNCATE
0112:             * @param offset the first line pixel offset
0113:             * @return initialized GNL_struct 
0114:             */
0115:            public static int[] initGNL(Font font, int w, int h, int options,
0116:                    int offset) {
0117:
0118:                int[] inout = new int[GNL_NUM_PARAMS];
0119:
0120:                inout[GNL_FONT_HEIGHT] = font.getHeight();
0121:                inout[GNL_WIDTH] = w;
0122:                inout[GNL_HEIGHT] = h;
0123:                inout[GNL_OPTIONS] = options;
0124:                inout[GNL_OFFSET] = offset;
0125:                inout[GNL_ELLIP_WIDTH] = font.charWidth(truncationMark);
0126:                inout[GNL_LINE_START] = 0;
0127:                inout[GNL_LINE_END] = 0;
0128:                inout[GNL_NEW_LINE_START] = 0;
0129:                inout[GNL_LINE_WIDTH] = 0;
0130:                inout[GNL_NUM_LINES] = 0;
0131:
0132:                return inout;
0133:            }
0134:
0135:            /**
0136:             * Paints the text in a single line, scrolling left or right as 
0137:             * necessary to keep the cursor visible within the available
0138:             * width for the text.  The offset of the text after the 
0139:             * paintLine call, whether modified or not, is returned.
0140:             * <p>
0141:             * If the cursor is null, signifying an uneditable TextField is
0142:             * being painted, the text will not be scrolled left or right, and
0143:             * the returned value will always equal the <code>offset</code>
0144:             * argument passed in to this method.
0145:             *
0146:             * @param g the Graphics object to paint in
0147:             * @param str the String to paint
0148:             * @param font the font to use
0149:             * @param fgColor foreground color
0150:             * @param w the available width for the text
0151:             * @param h the available height for the text
0152:             * @param cursor TextCursor object to use for cursor placement
0153:             * @param offset the pixel offset of the text (possibly negative)
0154:             * @return the current scroll offset
0155:             */
0156:            public static int paintLine(Graphics g, String str, Font font,
0157:                    int fgColor, int w, int h, TextCursor cursor, int offset) {
0158:                if (w <= 0
0159:                        || (cursor == null && (str == null || str.length() == 0))) {
0160:                    return 0;
0161:                }
0162:
0163:                if (str == null) {
0164:                    str = "";
0165:                }
0166:
0167:                g.setFont(font);
0168:                g.setColor(fgColor);
0169:
0170:                char[] text = str.toCharArray();
0171:                int fontHeight = font.getHeight();
0172:
0173:                if (cursor != null && cursor.visible == false) {
0174:                    cursor = null;
0175:                }
0176:
0177:                // side-scroll distance in pixels, with default
0178:                int scrollPix = w / 2;
0179:
0180:                //
0181:                // draw a vertical cursor indicator if required
0182:                //
0183:                if (cursor != null && cursor.option == PAINT_USE_CURSOR_INDEX
0184:                        && cursor.index >= 0 && cursor.index <= str.length()) {
0185:                    int pos = offset;
0186:                    if (cursor.index > 0) {
0187:                        pos += font.charsWidth(text, 0, cursor.index);
0188:                    }
0189:                    // IMPL_NOTE: optimize this with math instead of iteration
0190:                    cursor.x = pos;
0191:                    if (cursor.x >= w) {
0192:                        while (cursor.x >= w) {
0193:                            offset -= scrollPix;
0194:                            cursor.x -= scrollPix;
0195:                        }
0196:                    } else {
0197:                        while ((cursor.x < w / 2) && (offset < 0)) {
0198:                            offset += scrollPix;
0199:                            cursor.x += scrollPix;
0200:                        }
0201:                    }
0202:                    cursor.y = fontHeight;
0203:                    cursor.width = 1;
0204:                    cursor.height = fontHeight;
0205:
0206:                    cursor.paint(g);
0207:                    cursor = null;
0208:                }
0209:                g.drawChars(text, 0, text.length, offset, h, Graphics.BOTTOM
0210:                        | Graphics.LEFT);
0211:
0212:                return offset;
0213:            }
0214:
0215:            /**
0216:             * Creates a current TextInfo struct, linewraping text
0217:             * when necessary.  TextInfo struct is updated when
0218:             * <code>str</code> changes, or when scrolling happens.
0219:             * This method does not do any painting, but updates
0220:             * <code>info</code> to be current for use by the
0221:             * paint routine, <code>paintText</code>...
0222:             *
0223:             * @param str the text to use
0224:             * @param font the font to use for sizing
0225:             * @param w the available width for the text
0226:             * @param h the available height for the text
0227:             * @param offset the pixel offset of the text (possibly negative)
0228:             * @param options only TRUNCATE matters here
0229:             * @param cursor text cursor object for cursor position
0230:             * @param info TextInfo structure to fill
0231:             * @return true if successful, false if there was an error
0232:             */
0233:            // IMPL_NOTE: break into 3 simpler update methods: text, Y scroll, X scroll
0234:            public static boolean updateTextInfo(String str, Font font, int w,
0235:                    int h, int offset, int options, TextCursor cursor,
0236:                    TextInfo info) {
0237:                if (w <= 0
0238:                        || (cursor == null && (str == null || str.length() == 0))) {
0239:                    return false;
0240:                }
0241:
0242:                if (str == null) {
0243:                    str = "";
0244:                }
0245:
0246:                char[] text = str.toCharArray();
0247:
0248:                int fontHeight = font.getHeight();
0249:
0250:                if (cursor != null && cursor.visible == false) {
0251:                    cursor = null;
0252:                }
0253:
0254:                if (info.isModified) {
0255:
0256:                    int[] inout = initGNL(font, w, h, options, offset);
0257:
0258:                    int numLines = 0;
0259:                    int height = 0;
0260:
0261:                    do {
0262:                        numLines++;
0263:                        height += fontHeight;
0264:                        info.numLines = numLines;
0265:                        if (height < h) {
0266:                            info.visLines = info.numLines;
0267:                        }
0268:
0269:                        inout[GNL_NUM_LINES] = numLines;
0270:
0271:                        getNextLine(text, font, inout);
0272:
0273:                        int lineStart = inout[GNL_LINE_START];
0274:                        int lineEnd = inout[GNL_LINE_END];
0275:                        int newLineStart = inout[GNL_NEW_LINE_START];
0276:
0277:                        // IMPL_NOTE: add accessor fn to TextInfo and hide this
0278:                        //
0279:                        // check that we don't exceed info's capacity
0280:                        // before we cache line data and expand if needed
0281:                        //
0282:                        if (numLines > info.lineStart.length) {
0283:                            info.expand();
0284:                        }
0285:                        info.lineStart[numLines - 1] = lineStart;
0286:                        info.lineEnd[numLines - 1] = lineEnd;
0287:
0288:                        inout[GNL_LINE_START] = newLineStart;
0289:                        inout[GNL_OFFSET] = 0;
0290:                        offset = 0;
0291:                    } while (inout[GNL_LINE_END] < text.length);
0292:                    info.height = height;
0293:                }
0294:                if (info.scrollY) {
0295:                    // if (lineEnd > lineStart) {
0296:
0297:                    // we are given x,y coordinates and we must calculate
0298:                    // the best array index to put the cursor
0299:                    //
0300:                    if (cursor != null
0301:                            && cursor.option == PAINT_GET_CURSOR_INDEX
0302:                            && cursor.x >= 0) {
0303:                        // cursor.y == height) {
0304:
0305:                        int curLine = (cursor.y / fontHeight) - 1;
0306:                        int curX = curLine == 0 ? offset : 0;
0307:                        int curY = cursor.y;
0308:                        int bestX = curX;
0309:                        int bestIndex = info.lineStart[curLine];
0310:
0311:                        // take one character at a time and check its position
0312:                        // against the supplied coordinates in cursor
0313:                        //
0314:                        int lineStart = info.lineStart[curLine];
0315:                        int lineEnd = info.lineEnd[curLine];
0316:
0317:                        for (int i = lineStart; i < lineEnd; i++) {
0318:
0319:                            char ch = text[i];
0320:                            if (Math.abs(curX - cursor.preferredX) < Math
0321:                                    .abs(bestX - cursor.preferredX)) {
0322:                                bestIndex = i;
0323:                                bestX = curX;
0324:                            }
0325:                            curX += font.charWidth(ch);
0326:                        }
0327:
0328:                        if (Math.abs(curX - cursor.preferredX) < Math.abs(bestX
0329:                                - cursor.preferredX)) {
0330:                            bestIndex = lineEnd;
0331:                            bestX = curX;
0332:                        }
0333:
0334:                        cursor.index = bestIndex;
0335:                        cursor.x = bestX;
0336:                        // cursor.y = height;
0337:                        cursor.option = PAINT_USE_CURSOR_INDEX;
0338:                        info.cursorLine = curLine;
0339:                    }
0340:                }
0341:                if (info.scrollX || info.isModified) {
0342:                    if (cursor != null
0343:                            && cursor.option == PAINT_USE_CURSOR_INDEX) {
0344:                        if (cursor.index >= info.lineStart[info.cursorLine]
0345:                                && cursor.index <= info.lineEnd[info.cursorLine]) {
0346:                            // no change to info.cursorLine
0347:                        } else {
0348:                            // IMPL_NOTE: start at cursorLine and search before/after
0349:                            //      as this search is non-optimal
0350:                            for (int i = 0; i < info.numLines; i++) {
0351:                                // we are given an index...what line is it on? 
0352:                                if (cursor.index >= info.lineStart[i]
0353:                                        && cursor.index <= info.lineEnd[i]) {
0354:                                    info.cursorLine = i;
0355:                                    break;
0356:                                }
0357:                            }
0358:                        }
0359:                    }
0360:                }
0361:                // check scroll position and move if needed
0362:                if (cursor != null
0363:                        && (info.isModified || info.scrollX || info.scrollY)) {
0364:                    if (info.numLines > info.visLines) {
0365:                        if (info.cursorLine > info.topVis + info.visLines - 1) {
0366:                            int diff = info.cursorLine
0367:                                    - (info.topVis + info.visLines - 1);
0368:                            info.topVis += diff;
0369:                        } else if (info.cursorLine < info.topVis) {
0370:                            int diff = info.topVis - info.cursorLine;
0371:                            info.topVis -= diff;
0372:                        }
0373:
0374:                        if (info.topVis + info.visLines > info.numLines) {
0375:                            info.topVis = info.numLines - info.visLines;
0376:                        }
0377:
0378:                    } else {
0379:                        info.topVis = 0;
0380:                    }
0381:                    cursor.yOffset = info.topVis * fontHeight;
0382:                }
0383:                info.scrollX = info.scrollY = info.isModified = false;
0384:                return true;
0385:            }
0386:
0387:            /**
0388:             * Paints text from a TextInfo structure.
0389:             *
0390:             * @param info the TextInfo struct
0391:             * @param g the Graphics to paint with
0392:             * @param str the text to paint
0393:             * @param font the font to use in painting the text
0394:             * @param fgColor foreground color
0395:             * @param fgHColor foreground hilight color
0396:             * @param w the available width for the text
0397:             * @param h the available height for the text
0398:             * @param offset the first line pixel offset
0399:             * @param options any of NORMAL | INVERT | HYPERLINK | TRUNCATE
0400:             * @param cursor text cursor object
0401:             */
0402:            public static void paintText(TextInfo info, Graphics g, String str,
0403:                    Font font, int fgColor, int fgHColor, int w, int h,
0404:                    int offset, int options, TextCursor cursor) {
0405:
0406:                // NOTE paint not called if TextInfo struct fails
0407:                g.setFont(font);
0408:                g.setColor(fgColor);
0409:
0410:                char[] text = str.toCharArray();
0411:                int fontHeight = font.getHeight();
0412:
0413:                if (cursor != null && cursor.visible == false) {
0414:                    cursor = null;
0415:                }
0416:
0417:                int currentLine = info.topVis;
0418:                int height = currentLine * fontHeight;
0419:                int y = 0;
0420:
0421:                while (currentLine < (info.topVis + info.visLines)) {
0422:                    height += fontHeight;
0423:                    y += fontHeight;
0424:
0425:                    g.drawChars(text, info.lineStart[currentLine],
0426:                            info.lineEnd[currentLine]
0427:                                    - info.lineStart[currentLine], offset, y,
0428:                            Graphics.BOTTOM | Graphics.LEFT);
0429:
0430:                    // draw the vertical cursor indicator if needed
0431:                    // update the cursor.x and cursor.y info
0432:                    if (cursor != null
0433:                            && cursor.option == PAINT_USE_CURSOR_INDEX
0434:                            && cursor.index >= info.lineStart[currentLine]
0435:                            && cursor.index <= info.lineEnd[currentLine]) {
0436:
0437:                        int off = offset;
0438:                        if (cursor.index > info.lineStart[currentLine]) {
0439:                            off += font.charsWidth(text,
0440:                                    info.lineStart[currentLine], cursor.index
0441:                                            - info.lineStart[currentLine]);
0442:                        }
0443:
0444:                        cursor.x = off;
0445:                        cursor.y = height;
0446:                        cursor.width = 1; // IMPL_NOTE: must these always be set?
0447:                        cursor.height = fontHeight;
0448:
0449:                        cursor.paint(g);
0450:                        cursor = null;
0451:                    }
0452:                    offset = 0;
0453:                    currentLine++;
0454:                }
0455:            }
0456:
0457:            /**
0458:             * Paints the text, linewrapping when necessary.
0459:             *
0460:             * @param g the Graphics to use to paint with
0461:             * @param str the text to paint
0462:             * @param font the font to use to paint the text
0463:             * @param fgColor foreground color
0464:             * @param fgHColor foreground highlight color
0465:             * @param w the available width for the text
0466:             * @param h the available height for the text
0467:             * @param offset the first line pixel offset
0468:             * @param options any of NORMAL | INVERT | HYPERLINK | TRUNCATE
0469:             * @param cursor text cursor object to use to draw vertical bar
0470:             * @return the width of the last line painted
0471:             */
0472:            public static int paint(Graphics g, String str, Font font,
0473:                    int fgColor, int fgHColor, int w, int h, int offset,
0474:                    int options, TextCursor cursor) {
0475:
0476:                if (w <= 0
0477:                        || (cursor == null && (str == null || str.length() == 0))) {
0478:                    return 0;
0479:                }
0480:
0481:                if (str == null) {
0482:                    str = "";
0483:                }
0484:
0485:                g.setFont(font);
0486:                g.setColor(fgColor);
0487:
0488:                char[] text = str.toCharArray();
0489:                int fontHeight = font.getHeight();
0490:
0491:                if (cursor != null && cursor.visible == false) {
0492:                    cursor = null;
0493:                }
0494:
0495:                int[] inout = initGNL(font, w, h, options, offset);
0496:
0497:                int numLines = 0;
0498:                int height = 0;
0499:
0500:                do {
0501:                    numLines++;
0502:                    height += fontHeight;
0503:
0504:                    if (height > h) {
0505:                        break;
0506:                    }
0507:
0508:                    inout[GNL_NUM_LINES] = numLines;
0509:
0510:                    boolean truncate = getNextLine(text, font, inout);
0511:
0512:                    int lineStart = inout[GNL_LINE_START];
0513:                    int lineEnd = inout[GNL_LINE_END];
0514:                    int newLineStart = inout[GNL_NEW_LINE_START];
0515:
0516:                    //
0517:                    // now we can get around to actually draw the text
0518:                    // lineStart is the array index of the first character to
0519:                    // start drawing, while lineEnd is the index just after
0520:                    // the last character to draw.
0521:                    //
0522:                    if (lineEnd > lineStart) {
0523:
0524:                        if ((options & INVERT) == INVERT) {
0525:                            g.setColor(fgHColor);
0526:                        } else {
0527:                            g.setColor(fgColor);
0528:                        }
0529:                        if ((options & HYPERLINK) == HYPERLINK) {
0530:                            drawHyperLink(g, offset, height,
0531:                                    inout[GNL_LINE_WIDTH]);
0532:                        }
0533:
0534:                        //
0535:                        // we are given x,y coordinates and we must calculate
0536:                        // the best array index to put the cursor
0537:                        //
0538:                        if (cursor != null
0539:                                && cursor.option == PAINT_GET_CURSOR_INDEX
0540:                                && cursor.x >= 0 && cursor.y == height) {
0541:
0542:                            int bestIndex = lineStart;
0543:                            int bestX = offset;
0544:                            int curX = offset;
0545:                            int curY = height;
0546:
0547:                            //
0548:                            // draw one character at a time and check its position
0549:                            // against the supplied coordinates in cursor
0550:                            //
0551:                            for (int i = lineStart; i < lineEnd; i++) {
0552:
0553:                                char ch = text[i];
0554:
0555:                                g.drawChar(ch, curX, curY, Graphics.BOTTOM
0556:                                        | Graphics.LEFT);
0557:
0558:                                if (Math.abs(curX - cursor.preferredX) < Math
0559:                                        .abs(bestX - cursor.preferredX)) {
0560:                                    bestIndex = i;
0561:                                    bestX = curX;
0562:                                }
0563:
0564:                                curX += font.charWidth(ch);
0565:                            }
0566:
0567:                            if (Math.abs(curX - cursor.preferredX) < Math
0568:                                    .abs(bestX - cursor.preferredX)) {
0569:                                bestIndex = lineEnd;
0570:                                bestX = curX;
0571:                            }
0572:
0573:                            //
0574:                            // draw the ellipsis
0575:                            //
0576:                            if (truncate) {
0577:                                g.drawChar(truncationMark, curX, curY,
0578:                                        Graphics.BOTTOM | Graphics.LEFT);
0579:                            }
0580:
0581:                            cursor.index = bestIndex;
0582:                            cursor.x = bestX;
0583:                            cursor.y = height;
0584:                            cursor.option = PAINT_USE_CURSOR_INDEX;
0585:
0586:                        } else {
0587:                            g.drawChars(text, lineStart, lineEnd - lineStart,
0588:                                    offset, height, Graphics.BOTTOM
0589:                                            | Graphics.LEFT);
0590:
0591:                            //
0592:                            // draw the ellipsis
0593:                            //
0594:                            if (truncate) {
0595:                                g.drawChar(truncationMark, offset
0596:                                        + font.charsWidth(text, lineStart,
0597:                                                lineEnd), height,
0598:                                        Graphics.BOTTOM | Graphics.LEFT);
0599:                            }
0600:                        }
0601:                    }
0602:
0603:                    //
0604:                    // try to draw a vertical cursor indicator
0605:                    //
0606:                    if (cursor != null
0607:                            && cursor.option == PAINT_USE_CURSOR_INDEX
0608:                            && cursor.index >= lineStart
0609:                            && cursor.index <= lineEnd) {
0610:
0611:                        int off = offset;
0612:                        if (cursor.index > lineStart) {
0613:                            off += font.charsWidth(text, lineStart,
0614:                                    cursor.index - lineStart);
0615:                        }
0616:
0617:                        cursor.x = off;
0618:                        cursor.y = height;
0619:                        cursor.width = 1;
0620:                        cursor.height = fontHeight;
0621:
0622:                        cursor.paint(g);
0623:                        cursor = null;
0624:                    }
0625:
0626:                    inout[GNL_LINE_START] = newLineStart;
0627:                    inout[GNL_OFFSET] = 0;
0628:                    offset = 0;
0629:
0630:                } while (inout[GNL_LINE_END] < text.length);
0631:
0632:                return inout[GNL_LINE_WIDTH];
0633:            }
0634:
0635:            /**
0636:             * Draws a hyperlink image.
0637:             *
0638:             * @param g the graphics to use to draw the image
0639:             * @param x the x location of the image
0640:             * @param y the y location of the image
0641:             * @param w the width of the hyperlink image
0642:             */
0643:            public static void drawHyperLink(Graphics g, int x, int y, int w) {
0644:
0645:                if (StringItemSkin.IMAGE_LINK == null) {
0646:                    // System.err.println("Hyperlink image is null");
0647:                    return;
0648:                }
0649:                int linkHeight = StringItemSkin.IMAGE_LINK.getHeight();
0650:                int linkWidth = StringItemSkin.IMAGE_LINK.getWidth();
0651:
0652:                int oldClipX = g.getClipX();
0653:                int oldClipW = g.getClipWidth();
0654:                int oldClipY = g.getClipY();
0655:                int oldClipH = g.getClipHeight();
0656:
0657:                g.clipRect(x, oldClipY, w, oldClipH);
0658:
0659:                // Then, loop from the end of the string to the beginning,
0660:                // drawing the image as we go
0661:                for (int j = x + w - linkWidth, first = x - linkWidth; j > first; j -= linkWidth) {
0662:                    g.drawImage(StringItemSkin.IMAGE_LINK, j, y,
0663:                            Graphics.BOTTOM | Graphics.LEFT);
0664:                }
0665:
0666:                g.setClip(oldClipX, oldClipY, oldClipW, oldClipH);
0667:            }
0668:
0669:            /**
0670:             * Gets the height in pixels and the width of the widest line in pixels
0671:             * for the given string, calculated based on the availableWidth.
0672:             * size[WIDTH] and size[HEIGHT] should be set by this method.
0673:             * @param size The array that holds Item content size and location 
0674:             *             in Item internal bounds coordinate system.
0675:             * @param availableWidth The width available for this Item
0676:             * @param str the string to render
0677:             * @param font the font to use to render the string
0678:             * @param offset the pixel offset for the first line
0679:             * 
0680:             */
0681:            public static void getSizeForWidth(int[] size, int availableWidth,
0682:                    String str, Font font, int offset) {
0683:                // Case 0: null or empty string, no height
0684:                if (str == null || str.length() == 0 || availableWidth <= 0) {
0685:                    size[HEIGHT] = 0;
0686:                    size[WIDTH] = 0;
0687:                    return;
0688:                }
0689:
0690:                char[] text = str.toCharArray();
0691:
0692:                int[] inout = initGNL(font, availableWidth, 0, Text.NORMAL,
0693:                        offset);
0694:
0695:                int numLines = 0;
0696:                int widest = 0;
0697:                boolean widthFound = false;
0698:
0699:                do {
0700:
0701:                    numLines++;
0702:
0703:                    inout[GNL_NUM_LINES] = numLines;
0704:
0705:                    getNextLine(text, font, inout);
0706:
0707:                    if (!widthFound) {
0708:                        // a long line with no spaces
0709:                        if (inout[GNL_LINE_WIDTH] > availableWidth
0710:                                && offset == 0) {
0711:                            widest = availableWidth;
0712:                            widthFound = true;
0713:                        } else if (inout[GNL_LINE_WIDTH] > widest) {
0714:                            widest = inout[GNL_LINE_WIDTH];
0715:                        }
0716:                    }
0717:
0718:                    inout[GNL_LINE_START] = inout[GNL_NEW_LINE_START];
0719:                    inout[GNL_OFFSET] = 0;
0720:
0721:                } while (inout[GNL_LINE_END] < text.length);
0722:
0723:                size[WIDTH] = widest;
0724:                size[HEIGHT] = font.getHeight() * numLines;
0725:                // return values in size[]
0726:            }
0727:
0728:            /**
0729:             * Gets the height in pixels to render the given string.
0730:             * @param str the string to render
0731:             * @param font the font to use to render the string
0732:             * @param w the available width for the string
0733:             * @param offset the pixel offset for the first line
0734:             * @return the height in pixels required to render this string completely
0735:             */
0736:            // IMPL_NOTE - could remove and use getSizeForWidth()
0737:            public static int getHeightForWidth(String str, Font font, int w,
0738:                    int offset) {
0739:
0740:                int[] tmpSize = new int[] { 0, 0, 0, 0 };
0741:
0742:                getSizeForWidth(tmpSize, w, str, font, offset);
0743:                return tmpSize[HEIGHT];
0744:            }
0745:
0746:            /**
0747:             * Utility method to retrieve the length of the longest line of the 
0748:             * text given the width. this may not necessarily be the entire 
0749:             * string if there are line breaks or word wraps.
0750:             *
0751:             * @param str the String to use.
0752:             * @param offset a pixel offset for the first line
0753:             * @param width the available width for the text
0754:             * @param font the font to render the text in
0755:             * @return the length of the longest line given the width
0756:             */
0757:            // IMPL_NOTE - could remove and use getSizeForWidth()
0758:            public static int getWidestLineWidth(String str, int offset,
0759:                    int width, Font font) {
0760:
0761:                int[] tmpSize = new int[] { 0, 0, 0, 0 };
0762:
0763:                getSizeForWidth(tmpSize, width, str, font, offset);
0764:                return tmpSize[WIDTH];
0765:            }
0766:
0767:            /**
0768:             * Calculates the starting and ending points for a new line of
0769:             * text given the font and input parameters. Beware of the
0770:             * multiple returns statements within the body.
0771:             *
0772:             * @param text text to process. this must not be null
0773:             * @param font font to use for width information
0774:             * @param inout an array of in/out parameters, the GNL_ constants
0775:             *              define the meaning of each element;
0776:             *              this array implements a structure that keeps data
0777:             *              between invocations of getNextLine.
0778:             * @return true if the text had to be truncated, false otherwise
0779:             */
0780:            private static boolean getNextLine(char[] text, Font font,
0781:                    int[] inout) {
0782:
0783:                //
0784:                // this inner loop will set lineEnd and newLineStart to 
0785:                // the proper values so that a line is broken correctly
0786:                //
0787:                int curLoc = inout[GNL_LINE_START];
0788:                boolean foundBreak = false;
0789:                int leftWidth = 0;
0790:
0791:                inout[GNL_LINE_WIDTH] = 0;
0792:                int prevLineWidth = 0;
0793:                int curLineWidth = 0;
0794:
0795:                while (curLoc < text.length) {
0796:
0797:                    //
0798:                    // a newLine forces a break and immediately terminates
0799:                    // the loop
0800:                    //
0801:                    // a space will be remembered as a possible place to break
0802:                    //
0803:                    if (text[curLoc] == '\n') {
0804:                        inout[GNL_LINE_END] = curLoc;
0805:                        inout[GNL_NEW_LINE_START] = curLoc + 1;
0806:                        inout[GNL_LINE_WIDTH] = prevLineWidth;
0807:                        return (((inout[GNL_OPTIONS] & TRUNCATE) == TRUNCATE) && ((inout[GNL_NUM_LINES] + 1)
0808:                                * inout[GNL_FONT_HEIGHT] > inout[GNL_HEIGHT]));
0809:
0810:                    } else if (text[curLoc] == ' ') {
0811:                        inout[GNL_LINE_END] = curLoc;
0812:                        inout[GNL_NEW_LINE_START] = curLoc + 1;
0813:                        inout[GNL_LINE_WIDTH] = prevLineWidth;
0814:                        foundBreak = true;
0815:                    }
0816:
0817:                    //
0818:                    // if the text is longer than one line then we
0819:                    // cut the word at a word boundary if possible, 
0820:                    // otherwise the word is broken. 
0821:                    //
0822:
0823:                    curLineWidth = prevLineWidth + font.charWidth(text[curLoc]);
0824:
0825:                    // check up the mode is "truncate" and we reached the end of
0826:                    // the last line that we can put into the specifed rectangle area
0827:                    // (inout[GNL_WIDTH] x inout[GNL_HEIGHT])
0828:                    if (((inout[GNL_OPTIONS] & TRUNCATE) == TRUNCATE)
0829:                            && ((inout[GNL_NUM_LINES] + 1)
0830:                                    * inout[GNL_FONT_HEIGHT] > inout[GNL_HEIGHT])
0831:                            && (inout[GNL_OFFSET] + curLineWidth
0832:                                    + inout[GNL_ELLIP_WIDTH] > inout[GNL_WIDTH])) {
0833:
0834:                        leftWidth = font.charsWidth(text, curLoc + 1,
0835:                                text.length - curLoc - 1);
0836:                        //
0837:                        // we are on the last line and at the point where
0838:                        // we will need to put an ellipsis if we can't fit
0839:                        // the rest of the line
0840:                        //
0841:                        // if the rest of the line will fit, then don't
0842:                        // put an ellipsis
0843:                        //
0844:                        if (inout[GNL_OFFSET] + curLineWidth + leftWidth > inout[GNL_WIDTH]) {
0845:
0846:                            prevLineWidth += inout[GNL_ELLIP_WIDTH];
0847:
0848:                            inout[GNL_LINE_END] = curLoc;
0849:                            inout[GNL_NEW_LINE_START] = curLoc;
0850:                            inout[GNL_LINE_WIDTH] = prevLineWidth;
0851:
0852:                            return true;
0853:
0854:                        } else {
0855:
0856:                            curLineWidth += leftWidth;
0857:
0858:                            inout[GNL_LINE_END] = text.length;
0859:                            inout[GNL_NEW_LINE_START] = text.length;
0860:                            inout[GNL_LINE_WIDTH] = curLineWidth;
0861:
0862:                            return false;
0863:                        }
0864:                        // reached the end of the line
0865:                    } else if (inout[GNL_OFFSET] + curLineWidth > inout[GNL_WIDTH]) {
0866:
0867:                        if (!foundBreak) {
0868:                            if (inout[GNL_OFFSET] > 0) {
0869:                                // move to the next line which will have 0 offset
0870:                                inout[GNL_LINE_END] = inout[GNL_LINE_START];
0871:                                inout[GNL_NEW_LINE_START] = inout[GNL_LINE_START];
0872:                                inout[GNL_LINE_WIDTH] = 0;
0873:                            } else {
0874:                                // the line is too long and we need to break it
0875:                                inout[GNL_LINE_END] = curLoc;
0876:                                inout[GNL_NEW_LINE_START] = curLoc;
0877:                                inout[GNL_LINE_WIDTH] = prevLineWidth;
0878:                            }
0879:                        }
0880:
0881:                        return false;
0882:                    }
0883:
0884:                    // go to next character            
0885:                    curLoc++;
0886:                    prevLineWidth = curLineWidth;
0887:
0888:                } // while end
0889:
0890:                // we reach this code only if we reach the end of the text
0891:                inout[GNL_LINE_END] = text.length;
0892:                inout[GNL_NEW_LINE_START] = text.length;
0893:                inout[GNL_LINE_WIDTH] = curLineWidth;
0894:
0895:                return false;
0896:            }
0897:
0898:            /**
0899:             * Utility method to calculate the width and height in which 2 
0900:             * strings can fit  given the strings, fonts and maximum width 
0901:             * in which those strings should fit. Returned width is either 
0902:             * the passed in width or a smaller one.
0903:             * The offset in pixels for the first string is 0, second string is 
0904:             * laid out right after the first one with padding in between 
0905:             * equal to the passed in value.
0906:             * 
0907:             * The width in which both strings would fit given the maximum 
0908:             * is returned in size[WIDTH].  The height in which both strings
0909:             * would fit is returned in size[HEIGHT];
0910:             *
0911:             * @param size The array that returns contents size
0912:             * @param firstStr the first string to use.
0913:             * @param secondStr the first string to use.
0914:             * @param width the available width for the text
0915:             * @param firstFont the font to render the first string in
0916:             * @param secondFont the font to render the second string in
0917:             * @param pad the horizontal padding that should be used between strings
0918:             */
0919:            public static void getTwoStringsSize(int[] size, String firstStr,
0920:                    String secondStr, Font firstFont, Font secondFont,
0921:                    int width, int pad) {
0922:                if (((firstStr == null || firstStr.length() == 0) && (secondStr == null || secondStr
0923:                        .length() == 0))
0924:                        || (width <= 0)) {
0925:                    size[WIDTH] = size[HEIGHT] = 0;
0926:                    return;
0927:                }
0928:
0929:                int[] inout = new int[GNL_NUM_PARAMS];
0930:
0931:                char[] text;
0932:
0933:                int offset = 0;
0934:                int widest = 0;
0935:                int numLines = 0;
0936:                int height = 0;
0937:                int fontHeight = 0;
0938:
0939:                if (firstStr != null && firstStr.length() > 0) {
0940:
0941:                    text = firstStr.toCharArray();
0942:
0943:                    fontHeight = firstFont.getHeight();
0944:
0945:                    inout = initGNL(firstFont, width, 0, Text.NORMAL, 0);
0946:
0947:                    do {
0948:
0949:                        numLines++;
0950:                        height += fontHeight;
0951:
0952:                        inout[GNL_NUM_LINES] = numLines;
0953:
0954:                        getNextLine(text, firstFont, inout);
0955:
0956:                        if (inout[GNL_LINE_WIDTH] > widest) {
0957:                            widest = inout[GNL_LINE_WIDTH];
0958:                        }
0959:
0960:                        inout[GNL_LINE_START] = inout[GNL_NEW_LINE_START];
0961:
0962:                    } while (inout[GNL_LINE_END] < firstStr.length());
0963:
0964:                    offset = inout[GNL_LINE_WIDTH];
0965:
0966:                    if (secondStr == null || secondStr.length() == 0) {
0967:                        // last \n in the two strings should be ignored
0968:                        if (firstStr.charAt(firstStr.length() - 1) == '\n') {
0969:                            height -= fontHeight;
0970:                        }
0971:                        size[HEIGHT] = height;
0972:                        size[WIDTH] = widest;
0973:                        return;
0974:                    }
0975:                }
0976:                // Second string is not null and it is not empty
0977:                if (secondStr != null && secondStr.length() > 0) {
0978:                    if (offset > 0) {
0979:                        offset += pad;
0980:                    }
0981:
0982:                    text = secondStr.toCharArray();
0983:
0984:                    fontHeight = secondFont.getHeight();
0985:
0986:                    // Line that has the end of the first string and the beginning
0987:                    // of the second one is a special one;
0988:                    // We have to make sure that it is not counted twice and that
0989:                    // the right font height is being added (the max of the two)
0990:                    if (numLines > 0) {
0991:                        numLines--;
0992:                        if (inout[GNL_FONT_HEIGHT] > fontHeight) {
0993:                            height -= fontHeight;
0994:                        } else {
0995:                            height -= inout[GNL_FONT_HEIGHT];
0996:                        }
0997:                    }
0998:
0999:                    inout = initGNL(secondFont, width, 0, Text.NORMAL, offset);
1000:
1001:                    do {
1002:                        numLines++;
1003:                        height += fontHeight;
1004:
1005:                        inout[GNL_NUM_LINES] = numLines;
1006:
1007:                        getNextLine(text, secondFont, inout);
1008:
1009:                        if (inout[GNL_OFFSET] + inout[GNL_LINE_WIDTH] > widest) {
1010:                            widest = inout[GNL_OFFSET] + inout[GNL_LINE_WIDTH];
1011:                        }
1012:
1013:                        inout[GNL_LINE_START] = inout[GNL_NEW_LINE_START];
1014:                        inout[GNL_OFFSET] = 0;
1015:
1016:                    } while (inout[GNL_LINE_END] < secondStr.length());
1017:
1018:                    // last \n should be ignored
1019:                    if (secondStr.charAt(secondStr.length() - 1) == '\n') {
1020:                        height -= fontHeight;
1021:                    }
1022:                }
1023:
1024:                size[WIDTH] = widest;
1025:                size[HEIGHT] = height;
1026:                return;
1027:            }
1028:
1029:            // IMPL_NOTE:  remove these - there must be a common place to get them
1030:            /** Used as an index into the size[], for the x. */
1031:            public final static int X = 0;
1032:
1033:            /** Used as an index into the size[], for the y. */
1034:            public final static int Y = 1;
1035:
1036:            /** Used as an index into the size[], for the width. */
1037:            public final static int WIDTH = 2;
1038:
1039:            /** Used as an index into the size[], for the height. */
1040:            public final static int HEIGHT = 3;
1041:
1042:            /**
1043:             *
1044:             *
1045:             * @param g the Graphics to paint with
1046:             * @param text the string to be painted
1047:             * @param font the font to be used
1048:             * @param fgColor foreground text color
1049:             * @param shdColor shadow color
1050:             * @param shdAlign shadow alignment
1051:             * @param titlew width
1052:
1053:             */
1054:            public static void drawTruncStringShadowed(Graphics g, String text,
1055:                    Font font, int fgColor, int shdColor, int shdAlign,
1056:                    int titlew) {
1057:                int dx = 1, dy = 1;
1058:                // draw the shadow
1059:                if (shdColor != fgColor) {
1060:                    switch (shdAlign) {
1061:                    case (Graphics.TOP | Graphics.LEFT):
1062:                        dx = -1;
1063:                        dy = -1;
1064:                        break;
1065:                    case (Graphics.TOP | Graphics.RIGHT):
1066:                        dx = 1;
1067:                        dy = -1;
1068:                        break;
1069:                    case (Graphics.BOTTOM | Graphics.LEFT):
1070:                        dx = -1;
1071:                        dy = 1;
1072:                        break;
1073:                    case (Graphics.BOTTOM | Graphics.RIGHT):
1074:                    default:
1075:                        dx = 1;
1076:                        dy = 1;
1077:                        break;
1078:                    }
1079:                    g.translate(dx, dy);
1080:                    drawTruncString(g, text, font, shdColor, titlew);
1081:                    /* if we wanted multi-line text output, we would use this:
1082:                     paint(g, text, font,
1083:                     shdColor, 0,
1084:                     titlew, titleh, 0,
1085:                     TRUNCATE, null);
1086:                     */
1087:                    g.translate(-dx, -dy);
1088:                }
1089:                // now draw the text whose shadow we have drawn above
1090:                drawTruncString(g, text, font, fgColor, titlew);
1091:                /* if we wanted multi-line text output, we would use this:
1092:                 paint(g, text, font,
1093:                 fgColor, 0,
1094:                 titlew, titleh, 0,
1095:                 TRUNCATE, null);
1096:                 */
1097:            }
1098:
1099:            /**
1100:             * Given a string, determine the length of a substring that can be drawn
1101:             * within the current clipping area.
1102:             * If the whole string fits into the clip area,
1103:             * return the length of the string.
1104:             * Else, return the length of a substring (starting from the beginning
1105:             * of the original string) that can be drawn within the current clipping
1106:             * area before the truncation indicator.
1107:             * The truncation indicator, typically, ellipsis, is not included into
1108:             * the returned length.
1109:             *
1110:             * @param g the Graphics to paint with
1111:             * @param str the string to be painted
1112:             * @param width the available width, including room
1113:             *          for the truncation indicator
1114:             * @return either the length of str (if it fits into the clip area),
1115:             *          or the length of the substring that can fit into the clip area
1116:             *          (not including the truncation mark)
1117:             */
1118:            public static int canDrawStringPart(Graphics g, String str,
1119:                    int width) {
1120:                if (width < 0) {
1121:                    return 0;
1122:                }
1123:                final Font font = g.getFont();
1124:                final int stringWidth = font.stringWidth(str);
1125:
1126:                if (width >= stringWidth) {
1127:                    return str.length();
1128:                }
1129:                final int widthForTruncatedText = width
1130:                        - font.charWidth(truncationMark);
1131:                int availableLength;
1132:                for (availableLength = str.length() - 1; font.substringWidth(
1133:                        str, 0, availableLength) > widthForTruncatedText; availableLength--) {
1134:                }
1135:                ;
1136:                return availableLength;
1137:            }
1138:
1139:            /**
1140:             * Draw the string within the specified width.
1141:             * If the string does not fit in the available width,
1142:             * it is truncated at the end,
1143:             * and a truncation indicator is displayed (usually,
1144:             * an ellipsis, but this can be changed).
1145:             * Use Graphics.translate(x,y) to specify the anchor point location
1146:             * (the alignment will be TOP|LEFT relative to 0,0).
1147:             *
1148:             * @param g the Graphics to paint with
1149:             * @param str the string to be painted
1150:             * @param font the font to be used
1151:             * @param fgColor the color to paint with
1152:             * @param width the width available for painting
1153:             */
1154:            public static void drawTruncString(Graphics g, String str,
1155:                    Font font, int fgColor, int width) {
1156:                g.setFont(font);
1157:                g.setColor(fgColor);
1158:                int lengthThatCanBeShown = canDrawStringPart(g, str, width);
1159:                if (lengthThatCanBeShown == str.length()) {
1160:                    g.drawString(str, 0, 0, Graphics.TOP | Graphics.LEFT);
1161:                } else {
1162:                    String s = str.substring(0, lengthThatCanBeShown)
1163:                            + truncationMark;
1164:                    g.drawString(s, 0, 0, Graphics.TOP | Graphics.LEFT);
1165:                }
1166:            }
1167:
1168:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.