Source Code Cross Referenced for Utilities.java in  » IDE-Netbeans » editor » org » netbeans » editor » 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 » IDE Netbeans » editor » org.netbeans.editor 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:
0042:        package org.netbeans.editor;
0043:
0044:        import java.awt.Rectangle;
0045:        import java.awt.Frame;
0046:        import java.awt.event.ActionEvent;
0047:        import java.awt.event.KeyEvent;
0048:        import java.util.logging.Level;
0049:        import java.util.logging.Logger;
0050:        import javax.swing.SwingUtilities;
0051:        import javax.swing.Action;
0052:        import javax.swing.KeyStroke;
0053:        import javax.swing.text.JTextComponent;
0054:        import javax.swing.text.BadLocationException;
0055:        import javax.swing.text.EditorKit;
0056:        import javax.swing.text.Document;
0057:        import javax.swing.text.TextAction;
0058:        import javax.swing.text.Caret;
0059:        import javax.swing.plaf.TextUI;
0060:        import javax.swing.text.Element;
0061:        import javax.swing.text.View;
0062:        import org.netbeans.lib.editor.util.CharSequenceUtilities;
0063:        import org.netbeans.lib.editor.util.swing.DocumentUtilities;
0064:        import org.openide.util.NbBundle;
0065:
0066:        /**
0067:         * Various useful editor functions. Some of the methods have
0068:         * the same names and signatures like in javax.swing.Utilities but
0069:         * there is also many other useful methods.
0070:         * All the methods are static so there's no reason to instantiate Utilities.
0071:         *
0072:         * All the methods working with the document rely on that it is locked against
0073:         * modification so they don't acquire document read/write lock by themselves
0074:         * to guarantee the full thread safety of the execution.
0075:         * It's the user's task to lock the document appropriately
0076:         * before using methods described here.
0077:         *
0078:         * Most of the methods require org.netbeans.editor.BaseDocument instance
0079:         * not just the javax.swing.text.Document.
0080:         * The reason for that is to mark that the methods work on BaseDocument
0081:         * instances only, not on generic documents. To convert the Document
0082:         * to BaseDocument the simple conversion (BaseDocument)target.getDocument()
0083:         * can be done or the method getDocument(target) can be called.
0084:         * There are also other conversion methods like getEditorUI(), getKit()
0085:         * or getKitClass().
0086:         *
0087:         * @author Miloslav Metelka
0088:         * @version 0.10
0089:         */
0090:
0091:        public class Utilities {
0092:
0093:            private static final String WRONG_POSITION_LOCALE = "wrong_position"; // NOI18N
0094:
0095:            /** Switch the case to capital letters. Used in changeCase() */
0096:            public static final int CASE_UPPER = 0;
0097:
0098:            /** Switch the case to small letters. Used in changeCase() */
0099:            public static final int CASE_LOWER = 1;
0100:
0101:            /** Switch the case to reverse. Used in changeCase() */
0102:            public static final int CASE_SWITCH = 2;
0103:
0104:            /** Fake TextAction for getting the info of the focused component */
0105:            private static TextAction focusedComponentAction;
0106:
0107:            private Utilities() {
0108:                // instantiation has no sense
0109:            }
0110:
0111:            /** Get the starting position of the row.
0112:             * @param c text component to operate on
0113:             * @param offset position in document where to start searching
0114:             * @return position of the start of the row or -1 for invalid position
0115:             */
0116:            public static int getRowStart(JTextComponent c, int offset)
0117:                    throws BadLocationException {
0118:                Rectangle r = c.modelToView(offset);
0119:                if (r == null) {
0120:                    return -1;
0121:                }
0122:                EditorUI eui = getEditorUI(c);
0123:                if (eui != null) {
0124:                    return c.viewToModel(new java.awt.Point(
0125:                            eui.textLeftMarginWidth, r.y));
0126:                }
0127:                return -1;
0128:            }
0129:
0130:            /** Get the starting position of the row.
0131:             * @param doc document to operate on
0132:             * @param offset position in document where to start searching
0133:             * @return position of the start of the row or -1 for invalid position
0134:             */
0135:            public static int getRowStart(BaseDocument doc, int offset)
0136:                    throws BadLocationException {
0137:                return getRowStart(doc, offset, 0);
0138:            }
0139:
0140:            /** Get the starting position of the row while providing relative count
0141:             * of row how the given position should be shifted. This is the most
0142:             * efficient way how to move by lines in the document based on some
0143:             * position. There is no similair getRowEnd() method that would have
0144:             * shifting parameter.
0145:             * @param doc document to operate on
0146:             * @param offset position in document where to start searching
0147:             * @param lineShift shift the given offset forward/back relatively
0148:             *  by some amount of lines
0149:             * @return position of the start of the row or -1 for invalid position
0150:             */
0151:            public static int getRowStart(BaseDocument doc, int offset,
0152:                    int lineShift) throws BadLocationException {
0153:
0154:                checkOffsetValid(doc, offset);
0155:
0156:                if (lineShift != 0) {
0157:                    Element lineRoot = doc.getParagraphElement(0)
0158:                            .getParentElement();
0159:                    int line = lineRoot.getElementIndex(offset);
0160:                    line += lineShift;
0161:                    if (line < 0 || line >= lineRoot.getElementCount()) {
0162:                        return -1; // invalid line shift
0163:                    }
0164:                    return lineRoot.getElement(line).getStartOffset();
0165:
0166:                } else { // no shift
0167:                    return doc.getParagraphElement(offset).getStartOffset();
0168:                }
0169:            }
0170:
0171:            /** Get the first non-white character on the line.
0172:             * The document.isWhitespace() is used to test whether the particular
0173:             * character is white space or not.
0174:             * @param doc document to operate on
0175:             * @param offset position in document anywhere on the line
0176:             * @return position of the first non-white char on the line or -1
0177:             *   if there's no non-white character on that line.
0178:             */
0179:            public static int getRowFirstNonWhite(BaseDocument doc, int offset)
0180:                    throws BadLocationException {
0181:
0182:                checkOffsetValid(doc, offset);
0183:
0184:                Element lineElement = doc.getParagraphElement(offset);
0185:                return getFirstNonWhiteFwd(doc, lineElement.getStartOffset(),
0186:                        lineElement.getEndOffset() - 1);
0187:            }
0188:
0189:            /** Get the last non-white character on the line.
0190:             * The document.isWhitespace() is used to test whether the particular
0191:             * character is white space or not.
0192:             * @param doc document to operate on
0193:             * @param offset position in document anywhere on the line
0194:             * @return position of the last non-white char on the line or -1
0195:             *   if there's no non-white character on that line.
0196:             */
0197:            public static int getRowLastNonWhite(BaseDocument doc, int offset)
0198:                    throws BadLocationException {
0199:
0200:                checkOffsetValid(doc, offset);
0201:
0202:                Element lineElement = doc.getParagraphElement(offset);
0203:                return getFirstNonWhiteBwd(doc, lineElement.getEndOffset() - 1,
0204:                        lineElement.getStartOffset());
0205:            }
0206:
0207:            /** Get indentation on the current line. If this line is white then
0208:             * return -1.
0209:             * @param doc document to operate on
0210:             * @param offset position in document anywhere on the line
0211:             * @return indentation or -1 if the line is white
0212:             */
0213:            public static int getRowIndent(BaseDocument doc, int offset)
0214:                    throws BadLocationException {
0215:                offset = getRowFirstNonWhite(doc, offset);
0216:                if (offset == -1) {
0217:                    return -1;
0218:                }
0219:                return doc.getVisColFromPos(offset);
0220:            }
0221:
0222:            /** Get indentation on the current line. If this line is white then
0223:             * go either up or down an return indentation of the first non-white row.
0224:             * The <tt>getRowFirstNonWhite()</tt> is used to find the indentation
0225:             * on particular line.
0226:             * @param doc document to operate on
0227:             * @param offset position in document anywhere on the line
0228:             * @param downDir if this flag is set to true then if the row is white
0229:             *   then the indentation of the next first non-white row is returned. If it's
0230:             *   false then the indentation of the previous first non-white row is returned.
0231:             * @return indentation or -1 if there's no non-white line in the specified direction
0232:             */
0233:            public static int getRowIndent(BaseDocument doc, int offset,
0234:                    boolean downDir) throws BadLocationException {
0235:                int p = getRowFirstNonWhite(doc, offset);
0236:                if (p == -1) {
0237:                    p = getFirstNonWhiteRow(doc, offset, downDir);
0238:                    if (p == -1) {
0239:                        return -1; // non-white line not found
0240:                    }
0241:                    p = getRowFirstNonWhite(doc, p);
0242:                    if (p == -1) {
0243:                        return -1; // non-white line not found
0244:                    }
0245:                }
0246:                return doc.getVisColFromPos(p);
0247:            }
0248:
0249:            /** Get the end position of the row right before the new-line character.
0250:             * @param c text component to operate on
0251:             * @param offset position in document where to start searching
0252:             * @param relLine shift offset forward/back by some amount of lines
0253:             * @return position of the end of the row or -1 for invalid position
0254:             */
0255:            public static int getRowEnd(JTextComponent c, int offset)
0256:                    throws BadLocationException {
0257:                Rectangle r = c.modelToView(offset);
0258:                if (r == null) {
0259:                    return -1;
0260:                }
0261:                return c
0262:                        .viewToModel(new java.awt.Point(Integer.MAX_VALUE, r.y));
0263:            }
0264:
0265:            public static int getRowEnd(BaseDocument doc, int offset)
0266:                    throws BadLocationException {
0267:                checkOffsetValid(doc, offset);
0268:
0269:                return doc.getParagraphElement(offset).getEndOffset() - 1;
0270:            }
0271:
0272:            private static int findBestSpan(JTextComponent c, int lineBegin,
0273:                    int lineEnd, int x) throws BadLocationException {
0274:                if (lineBegin == lineEnd) {
0275:                    return lineEnd;
0276:                }
0277:                int low = lineBegin;
0278:                int high = lineEnd;
0279:                while (low <= high) {
0280:
0281:                    if (high - low < 3) {
0282:                        int bestSpan = Integer.MAX_VALUE;
0283:                        int bestPos = -1;
0284:                        for (int i = low; i <= high; i++) {
0285:                            Rectangle tempRect = c.modelToView(i);
0286:                            if (Math.abs(x - tempRect.x) < bestSpan) {
0287:                                bestSpan = Math.abs(x - tempRect.x);
0288:                                bestPos = i;
0289:                            }
0290:                        }
0291:                        return bestPos;
0292:                    }
0293:
0294:                    int mid = (low + high) / 2;
0295:
0296:                    Rectangle tempRect = c.modelToView(mid);
0297:                    if (tempRect.x > x) {
0298:                        high = mid;
0299:                    } else if (tempRect.x < x) {
0300:                        low = mid;
0301:                    } else {
0302:                        return mid;
0303:                    }
0304:                }
0305:                return lineBegin;
0306:            }
0307:
0308:            /** Get the position that is one line above and visually at some
0309:             * x-coordinate value.
0310:             * @param doc document to operate on
0311:             * @param offset position in document from which the current line is determined
0312:             * @param x float x-coordinate value
0313:             * @return position of the character that is at the one line above at
0314:             *   the required x-coordinate value
0315:             */
0316:            public static int getPositionAbove(JTextComponent c, int offset,
0317:                    int x) throws BadLocationException {
0318:                int rowStart = getRowStart(c, offset);
0319:                int endInit = c.getUI().getNextVisualPositionFrom(c, rowStart,
0320:                        null, javax.swing.SwingConstants.WEST, null);
0321:
0322:                if (x == BaseKit.MAGIC_POSITION_MAX) {
0323:                    return endInit;
0324:                }
0325:
0326:                EditorUI eui = getEditorUI(c);
0327:                if (eui == null) {
0328:                    return offset; //skip
0329:                }
0330:
0331:                Rectangle r = c.modelToView(endInit);
0332:                if (r == null) {
0333:                    return offset; //skip
0334:                }
0335:
0336:                if (x == eui.textLeftMarginWidth) {
0337:                    return getRowStart(c, endInit);
0338:                }
0339:
0340:                int end = c.viewToModel(new java.awt.Point(Math.max(
0341:                        eui.textLeftMarginWidth, x + 2 * r.width), r.y));
0342:                Rectangle tempRect = c.modelToView(end);
0343:                if (tempRect == null || tempRect.x < x) {
0344:                    end = endInit;
0345:                }
0346:
0347:                int start = c.viewToModel(new java.awt.Point(Math.max(
0348:                        eui.textLeftMarginWidth, x - 2 * r.width), r.y));
0349:                tempRect = c.modelToView(start);
0350:                if (tempRect == null && tempRect.x > x) {
0351:                    start = getRowStart(c, end);
0352:                }
0353:
0354:                int best = findBestSpan(c, start, end, x);
0355:
0356:                if (best < c.getDocument().getLength()) {
0357:                    // #56056
0358:                    int tmp = best + 1;
0359:                    int nextVisualPosition = c.getUI()
0360:                            .getNextVisualPositionFrom(c, tmp,
0361:                                    javax.swing.text.Position.Bias.Backward,
0362:                                    javax.swing.SwingConstants.WEST, null);
0363:                    if (nextVisualPosition < best && nextVisualPosition >= 0) {
0364:                        return nextVisualPosition;
0365:                    }
0366:                }
0367:
0368:                return best;
0369:            }
0370:
0371:            /** Get the position that is one line above and visually at some
0372:             * x-coordinate value.
0373:             * @param c text component to operate on
0374:             * @param offset position in document from which the current line is determined
0375:             * @param x float x-coordinate value
0376:             * @return position of the character that is at the one line above at
0377:             *   the required x-coordinate value
0378:             */
0379:            public static int getPositionBelow(JTextComponent c, int offset,
0380:                    int x) throws BadLocationException {
0381:                int startInit = getRowEnd(c, offset) + 1;
0382:
0383:                Rectangle r = c.modelToView(startInit);
0384:                if (r == null) {
0385:                    return offset; // skip
0386:                }
0387:
0388:                EditorUI eui = getEditorUI(c);
0389:                if (eui != null && x == eui.textLeftMarginWidth) {
0390:                    return startInit;
0391:                }
0392:
0393:                int start = c.viewToModel(new java.awt.Point(Math.min(
0394:                        Integer.MAX_VALUE, r.x + x - 2 * r.width), r.y));
0395:                Rectangle tempRect = c.modelToView(start);
0396:                if (tempRect != null && tempRect.x > x) {
0397:                    start = startInit;
0398:                }
0399:
0400:                int end = c.viewToModel(new java.awt.Point(Math.min(
0401:                        Integer.MAX_VALUE, r.x + x + 2 * r.width), r.y));
0402:                tempRect = c.modelToView(end);
0403:                if (tempRect != null && tempRect.x < x) {
0404:                    end = getRowEnd(c, start);
0405:                }
0406:
0407:                int best = findBestSpan(c, start, end, x);
0408:
0409:                if (best > 0) {
0410:                    // #70254 - make sure $best is not in collapsed fold area. Try
0411:                    // getNextVisualPositionFrom to EAST from the position $best-1.
0412:                    // If the resulted next visual position is not equal to $best,
0413:                    // $best is in the collapsed fold and foldEnd or foldStart 
0414:                    // should be returned.
0415:                    int tmp = best - 1;
0416:                    int nextVisualPosition = c.getUI()
0417:                            .getNextVisualPositionFrom(c, tmp,
0418:                                    javax.swing.text.Position.Bias.Forward,
0419:                                    javax.swing.SwingConstants.EAST, null);
0420:                    if (nextVisualPosition > best
0421:                            && nextVisualPosition <= c.getDocument()
0422:                                    .getLength()) {
0423:                        // We are in the collapsed fold, now try to find which position
0424:                        // is the best, whether foldEnd or foldStart
0425:                        tempRect = c.modelToView(nextVisualPosition);
0426:                        if (tempRect == null) {
0427:                            return nextVisualPosition;
0428:                        }
0429:                        int rightX = tempRect.x;
0430:                        int nextVisualPositionLeft = c
0431:                                .getUI()
0432:                                .getNextVisualPositionFrom(
0433:                                        c,
0434:                                        nextVisualPosition,
0435:                                        javax.swing.text.Position.Bias.Backward,
0436:                                        javax.swing.SwingConstants.WEST, null);
0437:                        tempRect = c.modelToView(nextVisualPositionLeft);
0438:                        if (tempRect == null) {
0439:                            return nextVisualPosition;
0440:                        }
0441:                        int leftX = tempRect.x;
0442:
0443:                        if (Math.abs(leftX - x) > Math.abs(rightX - x)) {
0444:                            return nextVisualPosition;
0445:                        } else {
0446:                            return nextVisualPositionLeft;
0447:                        }
0448:                    }
0449:                }
0450:
0451:                return best;
0452:            }
0453:
0454:            /** Get start of the current word. If there are no more words till
0455:             * the begining of the document, this method returns -1.
0456:             * @param c text component to operate on
0457:             * @param offset position in document from which the current line is determined
0458:             */
0459:            public static int getWordStart(JTextComponent c, int offset)
0460:                    throws BadLocationException {
0461:                return getWordStart((BaseDocument) c.getDocument(), offset);
0462:            }
0463:
0464:            public static int getWordStart(BaseDocument doc, int offset)
0465:                    throws BadLocationException {
0466:                return doc.find(new FinderFactory.PreviousWordBwdFinder(doc,
0467:                        false, true), offset, 0);
0468:            }
0469:
0470:            public static int getWordEnd(JTextComponent c, int offset)
0471:                    throws BadLocationException {
0472:                return getWordEnd((BaseDocument) c.getDocument(), offset);
0473:            }
0474:
0475:            public static int getWordEnd(BaseDocument doc, int offset)
0476:                    throws BadLocationException {
0477:                int ret = doc.find(new FinderFactory.NextWordFwdFinder(doc,
0478:                        false, true), offset, -1);
0479:                return (ret > 0) ? ret : doc.getLength();
0480:            }
0481:
0482:            public static int getNextWord(JTextComponent c, int offset)
0483:                    throws BadLocationException {
0484:                int nextWordOffset = getNextWord(
0485:                        (BaseDocument) c.getDocument(), offset);
0486:                int nextVisualPosition = -1;
0487:                if (nextWordOffset > 0) {
0488:                    nextVisualPosition = c.getUI().getNextVisualPositionFrom(c,
0489:                            nextWordOffset - 1, null,
0490:                            javax.swing.SwingConstants.EAST, null);
0491:                }
0492:                return (nextVisualPosition == -1) ? nextWordOffset
0493:                        : nextVisualPosition;
0494:            }
0495:
0496:            public static int getNextWord(BaseDocument doc, int offset)
0497:                    throws BadLocationException {
0498:                Finder nextWordFinder = (Finder) doc
0499:                        .getProperty(SettingsNames.NEXT_WORD_FINDER);
0500:                offset = doc.find(nextWordFinder, offset, -1);
0501:                if (offset < 0) {
0502:                    offset = doc.getLength();
0503:                }
0504:                return offset;
0505:            }
0506:
0507:            public static int getPreviousWord(JTextComponent c, int offset)
0508:                    throws BadLocationException {
0509:                int prevWordOffset = getPreviousWord((BaseDocument) c
0510:                        .getDocument(), offset);
0511:                int nextVisualPosition = c.getUI().getNextVisualPositionFrom(c,
0512:                        prevWordOffset, null, javax.swing.SwingConstants.WEST,
0513:                        null);
0514:                if (nextVisualPosition == 0 && prevWordOffset == 0) {
0515:                    return 0;
0516:                }
0517:                return (nextVisualPosition + 1 == prevWordOffset) ? prevWordOffset
0518:                        : nextVisualPosition + 1;
0519:            }
0520:
0521:            public static int getPreviousWord(BaseDocument doc, int offset)
0522:                    throws BadLocationException {
0523:                Finder prevWordFinder = (Finder) doc
0524:                        .getProperty(SettingsNames.PREVIOUS_WORD_FINDER);
0525:                offset = doc.find(prevWordFinder, offset, 0);
0526:                if (offset < 0) {
0527:                    offset = 0;
0528:                }
0529:                return offset;
0530:            }
0531:
0532:            /** Get first white character in document in forward direction
0533:             * @param doc document to operate on
0534:             * @param offset position in document where to start searching
0535:             * @return position of the first white character or -1
0536:             */
0537:            public static int getFirstWhiteFwd(BaseDocument doc, int offset)
0538:                    throws BadLocationException {
0539:                return getFirstWhiteFwd(doc, offset, -1);
0540:            }
0541:
0542:            /** Get first white character in document in forward direction
0543:             * @param doc document to operate on
0544:             * @param offset position in document where to start searching
0545:             * @param limitPos position in document (greater or equal than offset) where
0546:             *   the search will stop reporting unsuccessful search by returning -1
0547:             * @return position of the first non-white character or -1
0548:             */
0549:            public static int getFirstWhiteFwd(BaseDocument doc, int offset,
0550:                    int limitPos) throws BadLocationException {
0551:                return doc.find(new FinderFactory.WhiteFwdFinder(doc), offset,
0552:                        limitPos);
0553:            }
0554:
0555:            /** Get first non-white character in document in forward direction
0556:             * @param doc document to operate on
0557:             * @param offset position in document where to start searching
0558:             * @return position of the first non-white character or -1
0559:             */
0560:            public static int getFirstNonWhiteFwd(BaseDocument doc, int offset)
0561:                    throws BadLocationException {
0562:                return getFirstNonWhiteFwd(doc, offset, -1);
0563:            }
0564:
0565:            /** Get first non-white character in document in forward direction
0566:             * @param doc document to operate on
0567:             * @param offset position in document where to start searching
0568:             * @param limitPos position in document (greater or equal than offset) where
0569:             *   the search will stop reporting unsuccessful search by returning -1
0570:             * @return position of the first non-white character or -1
0571:             */
0572:            public static int getFirstNonWhiteFwd(BaseDocument doc, int offset,
0573:                    int limitPos) throws BadLocationException {
0574:                return doc.find(new FinderFactory.NonWhiteFwdFinder(doc),
0575:                        offset, limitPos);
0576:            }
0577:
0578:            /** Get first white character in document in backward direction.
0579:             * The character right before the character at position offset will
0580:             * be searched as first.
0581:             * @param doc document to operate on
0582:             * @param offset position in document where to start searching
0583:             * @return position of the first white character or -1
0584:             */
0585:            public static int getFirstWhiteBwd(BaseDocument doc, int offset)
0586:                    throws BadLocationException {
0587:                return getFirstWhiteBwd(doc, offset, 0);
0588:            }
0589:
0590:            /** Get first white character in document in backward direction.
0591:             * The character right before the character at position offset will
0592:             * be searched as first.
0593:             * @param doc document to operate on
0594:             * @param offset position in document where to start searching
0595:             * @param limitPos position in document (lower or equal than offset) where
0596:             *   the search will stop reporting unsuccessful search by returning -1
0597:             * @return position of the first white character or -1
0598:             */
0599:            public static int getFirstWhiteBwd(BaseDocument doc, int offset,
0600:                    int limitPos) throws BadLocationException {
0601:                return doc.find(new FinderFactory.WhiteBwdFinder(doc), offset,
0602:                        limitPos);
0603:            }
0604:
0605:            /** Get first non-white character in document in backward direction.
0606:             * The character right before the character at position offset will
0607:             * be searched as first.
0608:             * @param doc document to operate on
0609:             * @param offset position in document where to start searching
0610:             * @return position of the first non-white character or -1
0611:             */
0612:            public static int getFirstNonWhiteBwd(BaseDocument doc, int offset)
0613:                    throws BadLocationException {
0614:                return getFirstNonWhiteBwd(doc, offset, 0);
0615:            }
0616:
0617:            /** Get first non-white character in document in backward direction.
0618:             * The character right before the character at position offset will
0619:             * be searched as first.
0620:             * @param doc document to operate on
0621:             * @param offset position in document where to start searching
0622:             * @param limitPos position in document (lower or equal than offset) where
0623:             *   the search will stop reporting unsuccessful search by returning -1
0624:             * @return position of the first non-white character or -1
0625:             */
0626:            public static int getFirstNonWhiteBwd(BaseDocument doc, int offset,
0627:                    int limitPos) throws BadLocationException {
0628:                return doc.find(new FinderFactory.NonWhiteBwdFinder(doc),
0629:                        offset, limitPos);
0630:            }
0631:
0632:            /** Return line offset (line number - 1) for some position in the document
0633:             * @param doc document to operate on
0634:             * @param offset position in document where to start searching
0635:             */
0636:            public static int getLineOffset(BaseDocument doc, int offset)
0637:                    throws BadLocationException {
0638:
0639:                checkOffsetValid(offset, doc.getLength() + 1);
0640:
0641:                Element lineRoot = doc.getParagraphElement(0)
0642:                        .getParentElement();
0643:                return lineRoot.getElementIndex(offset);
0644:            }
0645:
0646:            /** Return start offset of the line
0647:             * @param lineIndex line index starting from 0
0648:             * @return start position of the line or -1 if lineIndex was invalid
0649:             */
0650:            public static int getRowStartFromLineOffset(BaseDocument doc,
0651:                    int lineIndex) {
0652:                Element lineRoot = doc.getParagraphElement(0)
0653:                        .getParentElement();
0654:                if (lineIndex < 0 || lineIndex >= lineRoot.getElementCount()) {
0655:                    return -1; // invalid line number
0656:
0657:                } else {
0658:                    return lineRoot.getElement(lineIndex).getStartOffset();
0659:                }
0660:            }
0661:
0662:            /** Return visual column (with expanded tabs) on the line.
0663:             * @param doc document to operate on
0664:             * @param offset position in document for which the visual column should be found
0665:             * @return visual column on the line determined by position
0666:             */
0667:            public static int getVisualColumn(BaseDocument doc, int offset)
0668:                    throws BadLocationException {
0669:
0670:                int docLen = doc.getLength();
0671:                if (offset == docLen + 1) { // at ending extra '\n' => make docLen to proceed without BLE
0672:                    offset = docLen;
0673:                }
0674:
0675:                return doc.getVisColFromPos(offset);
0676:            }
0677:
0678:            /** Get the identifier around the given position or null if there's no identifier
0679:             * @see getIdentifierBlock()
0680:             */
0681:            public static String getIdentifier(BaseDocument doc, int offset)
0682:                    throws BadLocationException {
0683:                int[] blk = getIdentifierBlock(doc, offset);
0684:                return (blk != null) ? doc.getText(blk[0], blk[1] - blk[0])
0685:                        : null;
0686:            }
0687:
0688:            /** Get the identifier around the given position or null if there's no identifier
0689:             * around the given position. The identifier is not verified against SyntaxSupport.isIdentifier().
0690:             * @param c JTextComponent to work on
0691:             * @param offset position in document - usually the caret.getDot()
0692:             * @return the block (starting and ending position) enclosing the identifier
0693:             * or null if no identifier was found
0694:             */
0695:            public static int[] getIdentifierBlock(JTextComponent c, int offset)
0696:                    throws BadLocationException {
0697:                CharSequence id = null;
0698:                int[] ret = null;
0699:                Document doc = c.getDocument();
0700:                int idStart = javax.swing.text.Utilities
0701:                        .getWordStart(c, offset);
0702:                if (idStart >= 0) {
0703:                    int idEnd = javax.swing.text.Utilities.getWordEnd(c,
0704:                            idStart);
0705:                    if (idEnd >= 0) {
0706:                        id = DocumentUtilities.getText(doc, idStart, idEnd
0707:                                - idStart);
0708:                        ret = new int[] { idStart, idEnd };
0709:                        CharSequence trim = CharSequenceUtilities.trim(id);
0710:                        if (trim.length() == 0
0711:                                || (trim.length() == 1 && !Character
0712:                                        .isJavaIdentifierPart(trim.charAt(0)))) {
0713:                            int prevWordStart = javax.swing.text.Utilities
0714:                                    .getPreviousWord(c, offset);
0715:                            if (offset == javax.swing.text.Utilities
0716:                                    .getWordEnd(c, prevWordStart)) {
0717:                                ret = new int[] { prevWordStart, offset };
0718:                            } else {
0719:                                return null;
0720:                            }
0721:                        } else if ((id != null)
0722:                                && (id.length() != 0)
0723:                                && (CharSequenceUtilities.indexOf(id, '.') != -1)) { //NOI18N
0724:                            int index = offset - idStart;
0725:                            int begin = CharSequenceUtilities.lastIndexOf(id
0726:                                    .subSequence(0, index), '.');
0727:                            begin = (begin == -1) ? 0 : begin + 1; //first index after the dot, if exists
0728:                            int end = CharSequenceUtilities.indexOf(id, '.',
0729:                                    index);
0730:                            end = (end == -1) ? id.length() : end;
0731:                            ret = new int[] { idStart + begin, idStart + end };
0732:                        }
0733:                    }
0734:                }
0735:                return ret;
0736:            }
0737:
0738:            /** Get the identifier around the given position or null if there's no identifier
0739:             * around the given position. The identifier must be
0740:             * accepted by SyntaxSupport.isIdnetifier() otherwise null is returned.
0741:             * @param doc document to work on
0742:             * @param offset position in document - usually the caret.getDot()
0743:             * @return the block (starting and ending position) enclosing the identifier
0744:             *   or null if no identifier was found
0745:             */
0746:            public static int[] getIdentifierBlock(BaseDocument doc, int offset)
0747:                    throws BadLocationException {
0748:                int[] ret = null;
0749:                int idStart = getWordStart(doc, offset);
0750:                if (idStart >= 0) {
0751:                    int idEnd = getWordEnd(doc, idStart);
0752:                    if (idEnd >= 0) {
0753:                        String id = doc.getText(idStart, idEnd - idStart);
0754:                        if (doc.getSyntaxSupport().isIdentifier(id)) {
0755:                            ret = new int[] { idStart, idEnd };
0756:                        } else { // not identifier by syntax support
0757:                            id = getWord(doc, offset); // try right at offset
0758:                            if (doc.getSyntaxSupport().isIdentifier(id)) {
0759:                                ret = new int[] { offset, offset + id.length() };
0760:                            }
0761:                        }
0762:                    }
0763:                }
0764:                return ret;
0765:            }
0766:
0767:            /** Get the word around the given position .
0768:             * @param c component to work with
0769:             * @param offset position in document - usually the caret.getDot()
0770:             * @return the word.
0771:             */
0772:            public static String getWord(JTextComponent c, int offset)
0773:                    throws BadLocationException {
0774:                int[] blk = getIdentifierBlock(c, offset);
0775:                Document doc = c.getDocument();
0776:                return (blk != null) ? doc.getText(blk[0], blk[1] - blk[0])
0777:                        : null;
0778:            }
0779:
0780:            /** Get the selection if there's any or get the identifier around
0781:             * the position if there's no selection.
0782:             * @param c component to work with
0783:             * @param offset position in document - usually the caret.getDot()
0784:             * @return the block (starting and ending position) enclosing the identifier
0785:             *   or null if no identifier was found
0786:             */
0787:            public static int[] getSelectionOrIdentifierBlock(JTextComponent c,
0788:                    int offset) throws BadLocationException {
0789:                Document doc = c.getDocument();
0790:                Caret caret = c.getCaret();
0791:                int[] ret;
0792:                if (Utilities.isSelectionShowing(caret)) {
0793:                    ret = new int[] { c.getSelectionStart(),
0794:                            c.getSelectionEnd() };
0795:                } else if (doc instanceof  BaseDocument) {
0796:                    ret = getIdentifierBlock((BaseDocument) doc, caret.getDot());
0797:                } else {
0798:                    ret = getIdentifierBlock(c, offset);
0799:                }
0800:                return ret;
0801:            }
0802:
0803:            /** Get the selection or identifier at the current caret position
0804:             * @see getSelectionOrIdentifierBlock(JTextComponent, int)
0805:             */
0806:            public static int[] getSelectionOrIdentifierBlock(JTextComponent c) {
0807:                try {
0808:                    return getSelectionOrIdentifierBlock(c, c.getCaret()
0809:                            .getDot());
0810:                } catch (BadLocationException e) {
0811:                    return null;
0812:                }
0813:            }
0814:
0815:            /** Get the identifier before the given position (ending at given offset)
0816:             * or null if there's no identifier
0817:             */
0818:            public static String getIdentifierBefore(BaseDocument doc,
0819:                    int offset) throws BadLocationException {
0820:                int wordStart = getWordStart(doc, offset);
0821:                if (wordStart != -1) {
0822:                    String word = new String(doc.getChars(wordStart, offset
0823:                            - wordStart), 0, offset - wordStart);
0824:                    if (doc.getSyntaxSupport().isIdentifier(word)) {
0825:                        return word;
0826:                    }
0827:                }
0828:                return null;
0829:            }
0830:
0831:            /** Get the selection if there's any or get the identifier around
0832:             * the position if there's no selection.
0833:             */
0834:            public static String getSelectionOrIdentifier(JTextComponent c,
0835:                    int offset) throws BadLocationException {
0836:                Document doc = c.getDocument();
0837:                Caret caret = c.getCaret();
0838:                String ret;
0839:                if (Utilities.isSelectionShowing(caret)) {
0840:                    ret = c.getSelectedText();
0841:                    if (ret != null)
0842:                        return ret;
0843:                }
0844:                if (doc instanceof  BaseDocument) {
0845:                    ret = getIdentifier((BaseDocument) doc, caret.getDot());
0846:                } else {
0847:                    ret = getWord(c, offset);
0848:                }
0849:                return ret;
0850:            }
0851:
0852:            /** Get the selection or identifier at the current caret position */
0853:            public static String getSelectionOrIdentifier(JTextComponent c) {
0854:                try {
0855:                    return getSelectionOrIdentifier(c, c.getCaret().getDot());
0856:                } catch (BadLocationException e) {
0857:                    return null;
0858:                }
0859:            }
0860:
0861:            /** Get the word at given position.
0862:             */
0863:            public static String getWord(BaseDocument doc, int offset)
0864:                    throws BadLocationException {
0865:                int wordEnd = getWordEnd(doc, offset);
0866:                if (wordEnd != -1) {
0867:                    return new String(doc.getChars(offset, wordEnd - offset),
0868:                            0, wordEnd - offset);
0869:                }
0870:                return null;
0871:            }
0872:
0873:            /** Change the case for specified part of document
0874:             * @param doc document to operate on
0875:             * @param offset position in document determines the changed area begining
0876:             * @param len number of chars to change
0877:             * @param type either CASE_CAPITAL, CASE_SMALL or CASE_SWITCH
0878:             */
0879:            public static boolean changeCase(BaseDocument doc, int offset,
0880:                    int len, int type) throws BadLocationException {
0881:                char[] orig = doc.getChars(offset, len);
0882:                char[] changed = (char[]) orig.clone();
0883:                for (int i = 0; i < orig.length; i++) {
0884:                    switch (type) {
0885:                    case CASE_UPPER:
0886:                        changed[i] = Character.toUpperCase(orig[i]);
0887:                        break;
0888:                    case CASE_LOWER:
0889:                        changed[i] = Character.toLowerCase(orig[i]);
0890:                        break;
0891:                    case CASE_SWITCH:
0892:                        if (Character.isUpperCase(orig[i])) {
0893:                            changed[i] = Character.toLowerCase(orig[i]);
0894:                        } else if (Character.isLowerCase(orig[i])) {
0895:                            changed[i] = Character.toUpperCase(orig[i]);
0896:                        }
0897:                        break;
0898:                    }
0899:                }
0900:                // check chars for difference and possibly change document
0901:                for (int i = 0; i < orig.length; i++) {
0902:                    if (orig[i] != changed[i]) {
0903:                        doc.atomicLock();
0904:                        try {
0905:                            doc.remove(offset, orig.length);
0906:                            doc.insertString(offset, new String(changed), null);
0907:                        } finally {
0908:                            doc.atomicUnlock();
0909:                        }
0910:                        return true; // changed
0911:                    }
0912:                }
0913:                return false;
0914:            }
0915:
0916:            /** Tests whether the line contains no characters except the ending new-line.
0917:             * @param doc document to operate on
0918:             * @param offset position anywhere on the tested line
0919:             * @return whether the line is empty or not
0920:             */
0921:            public static boolean isRowEmpty(BaseDocument doc, int offset)
0922:                    throws BadLocationException {
0923:                Element lineElement = doc.getParagraphElement(offset);
0924:                return (lineElement.getStartOffset() + 1 == lineElement
0925:                        .getEndOffset());
0926:            }
0927:
0928:            public static int getFirstNonEmptyRow(BaseDocument doc, int offset,
0929:                    boolean downDir) throws BadLocationException {
0930:                while (offset != -1 && isRowEmpty(doc, offset)) {
0931:                    offset = getRowStart(doc, offset, downDir ? +1 : -1);
0932:                }
0933:                return offset;
0934:            }
0935:
0936:            /** Tests whether the line contains only whitespace characters.
0937:             * @param doc document to operate on
0938:             * @param offset position anywhere on the tested line
0939:             * @return whether the line is empty or not
0940:             */
0941:            public static boolean isRowWhite(BaseDocument doc, int offset)
0942:                    throws BadLocationException {
0943:                Element lineElement = doc.getParagraphElement(offset);
0944:                offset = doc.find(new FinderFactory.NonWhiteFwdFinder(doc),
0945:                        lineElement.getStartOffset(), lineElement
0946:                                .getEndOffset() - 1);
0947:                return (offset == -1);
0948:            }
0949:
0950:            public static int getFirstNonWhiteRow(BaseDocument doc, int offset,
0951:                    boolean downDir) throws BadLocationException {
0952:                if (isRowWhite(doc, offset)) {
0953:                    if (downDir) { // search down for non-white line
0954:                        offset = getFirstNonWhiteFwd(doc, offset);
0955:                    } else { // search up for non-white line
0956:                        offset = getFirstNonWhiteBwd(doc, offset);
0957:                    }
0958:                }
0959:                return offset;
0960:            }
0961:
0962:            /**
0963:             * Reformat a block of code.
0964:             * <br/>
0965:             * The document should not be locked prior entering of this method.
0966:             * <br/>
0967:             * The method should be called from AWT thread so that the given offsets are more stable.
0968:             * 
0969:             * @param doc document to work with
0970:             * @param startOffset offset at which the formatting starts
0971:             * @param endOffset offset at which the formatting ends
0972:             * @return length of the reformatted code
0973:             */
0974:            public static int reformat(BaseDocument doc, int startOffset,
0975:                    int endOffset) throws BadLocationException {
0976:                Formatter formatter = doc.getFormatter();
0977:                formatter.reformatLock();
0978:                doc.atomicLock();
0979:                try {
0980:                    return formatter.reformat(doc, startOffset, endOffset);
0981:                } finally {
0982:                    doc.atomicUnlock();
0983:                    formatter.reformatUnlock();
0984:                }
0985:            }
0986:
0987:            /**
0988:             * Reformat the line around the given position.
0989:             * <br/>
0990:             * The document should not be locked prior entering of this method.
0991:             * <br/>
0992:             * The method should be called from AWT thread so that the given offsets are more stable.
0993:             * 
0994:             */
0995:            public static void reformatLine(BaseDocument doc, int pos)
0996:                    throws BadLocationException {
0997:                int lineStart = getRowStart(doc, pos);
0998:                int lineEnd = getRowEnd(doc, pos);
0999:                reformat(doc, lineStart, lineEnd);
1000:            }
1001:
1002:            /** Count of rows between these two positions */
1003:            public static int getRowCount(BaseDocument doc, int startPos,
1004:                    int endPos) throws BadLocationException {
1005:                if (startPos > endPos) {
1006:                    return 0;
1007:                }
1008:                Element lineRoot = doc.getParagraphElement(0)
1009:                        .getParentElement();
1010:                return lineRoot.getElementIndex(endPos)
1011:                        - lineRoot.getElementIndex(startPos) + 1;
1012:            }
1013:
1014:            /** Get the total count of lines in the document */
1015:            public static int getRowCount(BaseDocument doc) {
1016:                return doc.getParagraphElement(0).getParentElement()
1017:                        .getElementCount();
1018:            }
1019:
1020:            /** @deprecated
1021:             * @see Formatter.insertTabString()
1022:             */
1023:            public static String getTabInsertString(BaseDocument doc, int offset)
1024:                    throws BadLocationException {
1025:                int col = getVisualColumn(doc, offset);
1026:                Formatter f = doc.getFormatter();
1027:                boolean expandTabs = f.expandTabs();
1028:                if (expandTabs) {
1029:                    int spacesPerTab = f.getSpacesPerTab();
1030:                    int len = (col + spacesPerTab) / spacesPerTab
1031:                            * spacesPerTab - col;
1032:                    return new String(Analyzer.getSpacesBuffer(len), 0, len);
1033:                } else { // insert pure tab
1034:                    return "\t"; // NOI18N
1035:                }
1036:            }
1037:
1038:            /** Get the visual column corresponding to the position after pressing
1039:             * the TAB key.
1040:             * @param doc document to work with
1041:             * @param offset position at which the TAB was pressed
1042:             */
1043:            public static int getNextTabColumn(BaseDocument doc, int offset)
1044:                    throws BadLocationException {
1045:                int col = getVisualColumn(doc, offset);
1046:                int tabSize = doc.getFormatter().getSpacesPerTab();
1047:                return (col + tabSize) / tabSize * tabSize;
1048:            }
1049:
1050:            public static void setStatusText(JTextComponent c, String text) {
1051:                EditorUI eui = getEditorUI(c);
1052:                StatusBar sb = eui == null ? null : eui.getStatusBar();
1053:                if (sb != null) {
1054:                    sb.setText(StatusBar.CELL_MAIN, text);
1055:                }
1056:            }
1057:
1058:            public static void setStatusText(JTextComponent c, String text,
1059:                    Coloring extraColoring) {
1060:                EditorUI eui = getEditorUI(c);
1061:                StatusBar sb = eui == null ? null : eui.getStatusBar();
1062:                if (sb != null) {
1063:                    sb.setText(StatusBar.CELL_MAIN, text, extraColoring);
1064:                }
1065:            }
1066:
1067:            public static void setStatusBoldText(JTextComponent c, String text) {
1068:                EditorUI eui = getEditorUI(c);
1069:                StatusBar sb = eui == null ? null : eui.getStatusBar();
1070:                if (sb != null) {
1071:                    sb.setBoldText(StatusBar.CELL_MAIN, text);
1072:                }
1073:            }
1074:
1075:            public static String getStatusText(JTextComponent c) {
1076:                EditorUI eui = getEditorUI(c);
1077:                StatusBar sb = eui == null ? null : eui.getStatusBar();
1078:                return (sb != null) ? sb.getText(StatusBar.CELL_MAIN) : null;
1079:            }
1080:
1081:            public static void clearStatusText(JTextComponent c) {
1082:                setStatusText(c, ""); // NOI18N
1083:            }
1084:
1085:            public static void insertMark(BaseDocument doc, Mark mark,
1086:                    int offset) throws BadLocationException,
1087:                    InvalidMarkException {
1088:                mark.insert(doc, offset);
1089:            }
1090:
1091:            public static void moveMark(BaseDocument doc, Mark mark,
1092:                    int newOffset) throws BadLocationException,
1093:                    InvalidMarkException {
1094:                mark.move(doc, newOffset);
1095:            }
1096:
1097:            public static void returnFocus() {
1098:                JTextComponent c = getLastActiveComponent();
1099:                if (c != null) {
1100:                    requestFocus(c);
1101:                }
1102:            }
1103:
1104:            public static void requestFocus(JTextComponent c) {
1105:                if (c != null) {
1106:                    if (!ImplementationProvider.getDefault().activateComponent(
1107:                            c)) {
1108:                        Frame f = EditorUI.getParentFrame(c);
1109:                        if (f != null) {
1110:                            f.requestFocus();
1111:                        }
1112:                        c.requestFocus();
1113:                    }
1114:                }
1115:            }
1116:
1117:            public static void runInEventDispatchThread(Runnable r) {
1118:                if (SwingUtilities.isEventDispatchThread()) {
1119:                    r.run();
1120:                } else {
1121:                    SwingUtilities.invokeLater(r);
1122:                }
1123:            }
1124:
1125:            public static String debugPosition(BaseDocument doc, int offset) {
1126:                String ret;
1127:
1128:                if (offset >= 0) {
1129:                    try {
1130:                        int line = getLineOffset(doc, offset) + 1;
1131:                        int col = getVisualColumn(doc, offset) + 1;
1132:                        ret = String.valueOf(line) + ":" + String.valueOf(col); // NOI18N
1133:                    } catch (BadLocationException e) {
1134:                        ret = NbBundle.getBundle(BaseKit.class).getString(
1135:                                WRONG_POSITION_LOCALE)
1136:                                + ' ' + offset + " > " + doc.getLength(); // NOI18N
1137:                    }
1138:                } else {
1139:                    ret = String.valueOf(offset);
1140:                }
1141:
1142:                return ret;
1143:            }
1144:
1145:            public static String offsetToLineColumnString(BaseDocument doc,
1146:                    int offset) {
1147:                return String.valueOf(offset) + "["
1148:                        + debugPosition(doc, offset) + "]"; // NOI18N
1149:            }
1150:
1151:            /** Display the identity of the document together with the title property
1152:             * and stream-description property.
1153:             */
1154:            public static String debugDocument(Document doc) {
1155:                return "<"
1156:                        + System.identityHashCode(doc) // NOI18N
1157:                        + ", title='" + doc.getProperty(Document.TitleProperty)
1158:                        + "', stream='"
1159:                        + doc.getProperty(Document.StreamDescriptionProperty)
1160:                        + ", " + doc.toString() + ">"; // NOI18N
1161:            }
1162:
1163:            public static void performAction(Action a, ActionEvent evt,
1164:                    JTextComponent target) {
1165:                if (a instanceof  BaseAction) {
1166:                    ((BaseAction) a).actionPerformed(evt, target);
1167:                } else {
1168:                    a.actionPerformed(evt);
1169:                }
1170:            }
1171:
1172:            /** Returns last activated component. If the component was closed, 
1173:             *  then previous component is returned */
1174:            public static JTextComponent getLastActiveComponent() {
1175:                return Registry.getMostActiveComponent();
1176:            }
1177:
1178:            /**
1179:             * Fetches the text component that currently has focus. It delegates to 
1180:             * TextAction.getFocusedComponent().
1181:             * @return the component
1182:             */
1183:            public static JTextComponent getFocusedComponent() {
1184:                /** Fake action for getting the focused component */
1185:                class FocusedComponentAction extends TextAction {
1186:
1187:                    FocusedComponentAction() {
1188:                        super ("focused-component"); // NOI18N
1189:                    }
1190:
1191:                    /** adding this method because of protected final getFocusedComponent */
1192:                    JTextComponent getFocusedComponent2() {
1193:                        return getFocusedComponent();
1194:                    }
1195:
1196:                    public void actionPerformed(ActionEvent evt) {
1197:                    }
1198:                }
1199:                ;
1200:
1201:                if (focusedComponentAction == null) {
1202:                    focusedComponentAction = new FocusedComponentAction();
1203:                }
1204:
1205:                return ((FocusedComponentAction) focusedComponentAction)
1206:                        .getFocusedComponent2();
1207:            }
1208:
1209:            /** Helper method to obtain instance of EditorUI (extended UI)
1210:             * from the existing JTextComponent.
1211:             * It doesn't require any document locking.
1212:             * @param target JTextComponent for which the extended UI should be obtained
1213:             * @return extended ui instance or null if the component.getUI()
1214:             *   does not return BaseTextUI instance.
1215:             */
1216:            public static EditorUI getEditorUI(JTextComponent target) {
1217:                TextUI ui = target.getUI();
1218:                return (ui instanceof  BaseTextUI) ? ((BaseTextUI) ui)
1219:                        .getEditorUI() : null;
1220:            }
1221:
1222:            /** Helper method to obtain instance of editor kit from existing JTextComponent.
1223:             * If the kit of the component is not an instance
1224:             * of the <tt>org.netbeans.editor.BaseKit</tt> the method returns null.
1225:             * The method doesn't require any document locking.
1226:             * @param target JTextComponent for which the editor kit should be obtained
1227:             * @return BaseKit instance or null
1228:             */
1229:            public static BaseKit getKit(JTextComponent target) {
1230:                if (target == null)
1231:                    return null; // #19574
1232:                EditorKit ekit = target.getUI().getEditorKit(target);
1233:                return (ekit instanceof  BaseKit) ? (BaseKit) ekit : null;
1234:            }
1235:
1236:            /** 
1237:             * Gets the class of an editor kit installed in <code>JTextComponent</code>.
1238:             * The method doesn't require any document locking.
1239:             * 
1240:             * <div class="nonnormative">
1241:             * <p>WARNING: The implementation class of an editor kit is most likely
1242:             * not what you want. Please see {@link BaseKit#getKit(Class)} for more
1243:             * details.
1244:             * 
1245:             * <p>Unfortunatelly, there are still places in editor libraries where
1246:             * an editor kit class is required.
1247:             * One of them is the editor settings infrastructure built around the
1248:             * <code>Settings</code> class. So, if you really need it go ahead and use it,
1249:             * there is nothing wrong with the method itself.
1250:             * </div>
1251:             * 
1252:             * @param target The <code>JTextComponent</code> to get the kit class for.
1253:             *   Can be <code>null</code>.
1254:             * @return The implementation class of the editor kit or <code>null</code>
1255:             *   if the <code>target</code> is <code>null</code>.
1256:             */
1257:            public static Class getKitClass(JTextComponent target) {
1258:                EditorKit kit = (target != null) ? target.getUI().getEditorKit(
1259:                        target) : null;
1260:                return (kit != null) ? kit.getClass() : null;
1261:            }
1262:
1263:            /** Helper method to obtain instance of BaseDocument from JTextComponent.
1264:             * If the document of the component is not an instance
1265:             * of the <tt>org.netbeans.editor.BaseDocument</tt> the method returns null.
1266:             * The method doesn't require any document locking.
1267:             * @param target JTextComponent for which the document should be obtained
1268:             * @return BaseDocument instance or null
1269:             */
1270:            public static BaseDocument getDocument(JTextComponent target) {
1271:                Document doc = target.getDocument();
1272:                return (doc instanceof  BaseDocument) ? (BaseDocument) doc
1273:                        : null;
1274:            }
1275:
1276:            /** Get the syntax-support class that belongs to the document of the given
1277:             * component. Besides using directly this method, the <tt>SyntaxSupport</tt>
1278:             * can be obtained by calling <tt>doc.getSyntaxSupport()</tt>.
1279:             * The method can return null in case the document is not
1280:             * an instance of the BaseDocument.
1281:             * The method doesn't require any document locking.
1282:             * @param target JTextComponent for which the syntax-support should be obtained
1283:             * @return SyntaxSupport instance or null
1284:             */
1285:            public static SyntaxSupport getSyntaxSupport(JTextComponent target) {
1286:                Document doc = target.getDocument();
1287:                return (doc instanceof  BaseDocument) ? ((BaseDocument) doc)
1288:                        .getSyntaxSupport() : null;
1289:            }
1290:
1291:            /**
1292:             * Get first view in the hierarchy that is an instance of the given class.
1293:             * It allows to skip various wrapper-views around the doc-view that holds
1294:             * the child views for the lines.
1295:             *
1296:             * @param component component from which the root view is fetched.
1297:             * @param rootViewClass class of the view to return.
1298:             * @return view being instance of the requested class or null if there
1299:             *  is not one.
1300:             */
1301:            public static View getRootView(JTextComponent component,
1302:                    Class rootViewClass) {
1303:                View view = null;
1304:                TextUI textUI = component.getUI();
1305:                if (textUI != null) {
1306:                    view = textUI.getRootView(component);
1307:                    while (view != null && !rootViewClass.isInstance(view)
1308:                            && view.getViewCount() == 1 // must be wrapper view
1309:                    ) {
1310:                        view = view.getView(0); // get the only child
1311:                    }
1312:                }
1313:
1314:                return view;
1315:            }
1316:
1317:            /**
1318:             * Get the view that covers the whole area of the document
1319:             * and holds a child view for each line in the document
1320:             * (or for a bunch of lines in case there is a code folding present).
1321:             */
1322:            public static View getDocumentView(JTextComponent component) {
1323:                return getRootView(component, DrawEngineDocView.class);
1324:            }
1325:
1326:            /**
1327:             * Creates nice textual description of sequence of KeyStrokes. Usable for
1328:             * displaying MultiKeyBindings. The keyStrokes are delimited by space.
1329:             * @param Array of KeyStrokes representing the actual sequence.
1330:             * @return String describing the KeyStroke sequence.
1331:             */
1332:            public static String keySequenceToString(KeyStroke[] seq) {
1333:                StringBuffer sb = new StringBuffer();
1334:                for (int i = 0; i < seq.length; i++) {
1335:                    if (i > 0)
1336:                        sb.append(' '); // NOI18N
1337:                    sb.append(keyStrokeToString(seq[i]));
1338:                }
1339:                return sb.toString();
1340:            }
1341:
1342:            /**
1343:             * Creates nice textual representation of KeyStroke.
1344:             * Modifiers and an actual key label are concated by plus signs
1345:             * @param the KeyStroke to get description of
1346:             * @return String describing the KeyStroke
1347:             */
1348:            public static String keyStrokeToString(KeyStroke stroke) {
1349:                String modifText = KeyEvent.getKeyModifiersText(stroke
1350:                        .getModifiers());
1351:                String keyText = (stroke.getKeyCode() == KeyEvent.VK_UNDEFINED) ? String
1352:                        .valueOf(stroke.getKeyChar())
1353:                        : getKeyText(stroke.getKeyCode());
1354:                if (modifText.length() > 0)
1355:                    return modifText + '+' + keyText;
1356:                else
1357:                    return keyText;
1358:            }
1359:
1360:            /** @return slight modification of what KeyEvent.getKeyText() returns.
1361:             *  The numpad Left, Right, Down, Up get extra result.
1362:             */
1363:            private static String getKeyText(int keyCode) {
1364:                String ret = KeyEvent.getKeyText(keyCode);
1365:                if (ret != null) {
1366:                    switch (keyCode) {
1367:                    case KeyEvent.VK_KP_DOWN:
1368:                        ret = prefixNumpad(ret, KeyEvent.VK_DOWN);
1369:                        break;
1370:                    case KeyEvent.VK_KP_LEFT:
1371:                        ret = prefixNumpad(ret, KeyEvent.VK_LEFT);
1372:                        break;
1373:                    case KeyEvent.VK_KP_RIGHT:
1374:                        ret = prefixNumpad(ret, KeyEvent.VK_RIGHT);
1375:                        break;
1376:                    case KeyEvent.VK_KP_UP:
1377:                        ret = prefixNumpad(ret, KeyEvent.VK_UP);
1378:                        break;
1379:                    }
1380:                }
1381:                return ret;
1382:            }
1383:
1384:            private static String prefixNumpad(String key, int testKeyCode) {
1385:                if (key.equals(KeyEvent.getKeyText(testKeyCode))) {
1386:                    key = NbBundle.getBundle(BaseKit.class).getString(
1387:                            "key-prefix-numpad")
1388:                            + key;
1389:                }
1390:                return key;
1391:            }
1392:
1393:            private static void checkOffsetValid(Document doc, int offset)
1394:                    throws BadLocationException {
1395:                checkOffsetValid(offset, doc.getLength());
1396:            }
1397:
1398:            private static void checkOffsetValid(int offset, int limitOffset)
1399:                    throws BadLocationException {
1400:                if (offset < 0 || offset > limitOffset) {
1401:                    throw new BadLocationException("Invalid offset=" + offset // NOI18N
1402:                            + " not within <0, " + limitOffset + ">", // NOI18N
1403:                            offset);
1404:                }
1405:            }
1406:
1407:            /** 
1408:             * Writes a <code>Throwable</code> to a log file.
1409:             * 
1410:             * <p class="nonnormative">The method is internally using 
1411:             * <code>org.netbeans.editor</code> logger and <code>Level.INFO</code>.
1412:             * 
1413:             * @param t The exception that will be logged.
1414:             * @deprecated Use java.util.logging.Logger instead with the proper name,
1415:             * log level and message.
1416:             */
1417:            public static void annotateLoggable(Throwable t) {
1418:                Logger.getLogger("org.netbeans.editor")
1419:                        .log(Level.INFO, null, t); //NOI18N
1420:            }
1421:
1422:            /**
1423:             * Check whether caret's selection is visible and there is at least
1424:             * one selected character showing.
1425:             * 
1426:             * @param caret non-null caret.
1427:             * @return true if selection is visible and there is at least one selected character.
1428:             */
1429:            public static boolean isSelectionShowing(Caret caret) {
1430:                return caret.isSelectionVisible()
1431:                        && caret.getDot() != caret.getMark();
1432:            }
1433:
1434:            /**
1435:             * @see isSelectionShowing(Caret)
1436:             * @param component non-null component.
1437:             * @return if selection is showing for component's caret.
1438:             */
1439:            public static boolean isSelectionShowing(JTextComponent component) {
1440:                Caret caret = component.getCaret();
1441:                return (caret != null) && isSelectionShowing(caret);
1442:            }
1443:
1444:            /**
1445:             * Gets the mime type of a document. If the mime type can't be determined
1446:             * this method will return <code>null</code>. This method should work reliably
1447:             * for Netbeans documents that have their mime type stored in a special
1448:             * property. For any other documents it will probably just return <code>null</code>.
1449:             * 
1450:             * @param doc The document to get the mime type for.
1451:             * 
1452:             * @return The mime type of the document or <code>null</code>.
1453:             * @see NbEditorDocument#MIME_TYPE_PROP
1454:             */
1455:            /* package */static String getMimeType(Document doc) {
1456:                return (String) doc.getProperty("mimeType"); //NOI18N
1457:            }
1458:
1459:            /**
1460:             * Gets the mime type of a document in <code>JTextComponent</code>. If
1461:             * the mime type can't be determined this method will return <code>null</code>.
1462:             * It tries to determine the document's mime type first and if that does not
1463:             * work it uses mime type from the <code>EditorKit</code> attached to the
1464:             * component.
1465:             * 
1466:             * @param component The component to get the mime type for.
1467:             * 
1468:             * @return The mime type of a document opened in the component or <code>null</code>.
1469:             */
1470:            /* package */static String getMimeType(JTextComponent component) {
1471:                Document doc = component.getDocument();
1472:                String mimeType = getMimeType(doc);
1473:                if (mimeType == null) {
1474:                    EditorKit kit = component.getUI().getEditorKit(component);
1475:                    if (kit != null) {
1476:                        mimeType = kit.getContentType();
1477:                    }
1478:                }
1479:                return mimeType;
1480:            }
1481:
1482:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.