Source Code Cross Referenced for EditorOperator.java in  » IDE-Netbeans » jellytools » org » netbeans » jellytools » 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 » jellytools » org.netbeans.jellytools 
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-2007 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:        package org.netbeans.jellytools;
0042:
0043:        import java.awt.Component;
0044:        import java.awt.Container;
0045:        import java.awt.event.KeyEvent;
0046:        import java.lang.reflect.Field;
0047:        import java.lang.reflect.Method;
0048:        import java.util.ArrayList;
0049:        import java.util.Iterator;
0050:        import javax.swing.JComponent;
0051:        import javax.swing.JToolBar;
0052:        import javax.swing.text.AbstractDocument;
0053:        import javax.swing.text.BadLocationException;
0054:        import javax.swing.text.Document;
0055:        import javax.swing.text.JTextComponent;
0056:        import javax.swing.text.StyledDocument;
0057:        import org.netbeans.api.editor.fold.Fold;
0058:        import org.netbeans.api.editor.fold.FoldHierarchy;
0059:        import org.netbeans.api.editor.fold.FoldUtilities;
0060:        import org.netbeans.core.windows.ModeImpl;
0061:        import org.netbeans.core.windows.WindowManagerImpl;
0062:        import org.netbeans.jemmy.ComponentChooser;
0063:        import org.netbeans.jemmy.ComponentSearcher;
0064:        import org.netbeans.jemmy.JemmyException;
0065:        import org.netbeans.jemmy.QueueTool;
0066:        import org.netbeans.jemmy.Timeouts;
0067:        import org.netbeans.jemmy.Waitable;
0068:        import org.netbeans.jemmy.Waiter;
0069:        import org.netbeans.jemmy.operators.AbstractButtonOperator;
0070:        import org.netbeans.jemmy.operators.ContainerOperator;
0071:        import org.netbeans.jemmy.operators.JComboBoxOperator;
0072:        import org.netbeans.jemmy.operators.JEditorPaneOperator;
0073:        import org.netbeans.jemmy.operators.JLabelOperator;
0074:        import org.openide.cookies.LineCookie;
0075:        import org.openide.loaders.DataObject;
0076:        import org.openide.text.Annotation;
0077:        import org.openide.text.CloneableEditor;
0078:        import org.openide.text.Line;
0079:        import org.openide.text.NbDocument;
0080:        import org.openide.text.Line.Set;
0081:        import org.openide.windows.TopComponent;
0082:
0083:        /**
0084:         * Handle an editor top component in NetBeans IDE. It enables to get, select, insert or
0085:         * delete text, move caret, work with annotations and with toolbar buttons.
0086:         * Majority of operations is done by JEditorPane API calls. If you want
0087:         * to do operations by key navigation, use methods of JEditorPaneOperator
0088:         * instance by {@link #txtEditorPane()}. For example, call
0089:         * <code>txtEditorPane().changeCaretPosition(int)</code> instead of
0090:         * <code>{@link #setCaretPosition(int)}</code>.
0091:         * <p>
0092:         * Usage:<br>
0093:         * <pre>
0094:         EditorOperator eo = new EditorOperator(filename);
0095:         eo.setCaretPositionToLine(10);
0096:         eo.insert("// My new comment\n");
0097:         eo.select("// My new comment");
0098:         eo.deleteLine(10);
0099:         eo.getToolbarButton("Toggle Bookmark").push();
0100:         // discard changes and close
0101:         eo.close(false);
0102:         // save changes and close
0103:         eo.close(true);
0104:         // try to close all opened documents (confirmation dialog may appear)
0105:         eo.closeAllDocuments();
0106:         // close all opened documents and discard all changes
0107:         eo.closeDiscardAll();
0108:         * </pre>
0109:         *
0110:         * @author Jiri.Skrivanek@sun.com
0111:         */
0112:        public class EditorOperator extends TopComponentOperator {
0113:
0114:            private static int WAIT_TIME = 60000;
0115:
0116:            static {
0117:                Timeouts.initDefault("EditorOperator.WaitModifiedTimeout",
0118:                        WAIT_TIME);
0119:            }
0120:
0121:            /** Components operators. */
0122:            private JEditorPaneOperator _txtEditorPane;
0123:            private JLabelOperator _lblRowColumn;
0124:            private JLabelOperator _lblInputMode;
0125:            private JLabelOperator _lblStatusBar;
0126:
0127:            /** Waits for the first opened editor with given name. 
0128:             * If not active, it is activated.
0129:             * @param filename name of file showed in the editor (it used to be label of tab)
0130:             */
0131:            public EditorOperator(String filename) {
0132:                this (filename, 0);
0133:            }
0134:
0135:            /** Waits for index-th opened editor with given name.
0136:             * If not active, it is activated.
0137:             * @param filename name of file showed in the editor (it used to be label of tab)
0138:             * @param index index of editor to be find
0139:             */
0140:            public EditorOperator(String filename, int index) {
0141:                super (waitTopComponent(null, filename, index,
0142:                        new EditorSubchooser()));
0143:                this .requestFocus(); // needed for pushKey() methods
0144:            }
0145:
0146:            /** Waits for first open editor with given name in specified container.
0147:             * If not active, it is activated.
0148:             * @param contOper container where to search
0149:             * @param filename name of file showed in the editor (it used to be label of tab)
0150:             */
0151:            public EditorOperator(ContainerOperator contOper, String filename) {
0152:                this (contOper, filename, 0);
0153:            }
0154:
0155:            /** Creates new operator instance for given component.
0156:             * It is used in FormDesignerOperator.
0157:             * @param editorComponent instance of editor
0158:             */
0159:            public EditorOperator(JComponent editorComponent) {
0160:                super (editorComponent);
0161:            }
0162:
0163:            /** Waits for index-th opened editor with given name in specified container.
0164:             * If not active, it is activated.
0165:             * @param contOper container where to search
0166:             * @param filename name of file showed in the editor (it used to be label of tab)
0167:             * @param index index of editor to be find
0168:             */
0169:            public EditorOperator(ContainerOperator contOper, String filename,
0170:                    int index) {
0171:                super (waitTopComponent(contOper, filename, index,
0172:                        new EditorSubchooser()));
0173:                copyEnvironment(contOper);
0174:                this .requestFocus(); // needed for pushKey() methods
0175:            }
0176:
0177:            /** Closes all opened documents and discards all changes by IDE API calls.
0178:             * It works also if no file is modified, so it is a safe way how to close
0179:             * documents and no block further execution.
0180:             */
0181:            public static void closeDiscardAll() {
0182:                // run in dispatch thread
0183:                ModeImpl mode = (ModeImpl) new QueueTool()
0184:                        .invokeSmoothly(new QueueTool.QueueAction("findMode") { // NOI18N
0185:                            public Object launch() {
0186:                                return WindowManagerImpl.getInstance()
0187:                                        .findMode("editor"); //NOI18N
0188:                            }
0189:                        });
0190:                Iterator iter = mode.getOpenedTopComponents().iterator();
0191:                while (iter.hasNext()) {
0192:                    EditorOperator.close(iter.next(), false);
0193:                }
0194:            }
0195:
0196:            /** Closes this editor by IDE API call and depending on given flag 
0197:             * it saves or discards changes.
0198:             * @param save true - save changes, false - discard changes
0199:             */
0200:            public void close(boolean save) {
0201:                if (save) {
0202:                    super .save();
0203:                    close();
0204:                } else {
0205:                    closeDiscard();
0206:                }
0207:            }
0208:
0209:            /** Closes top component. It saves it or not depending on given flag. 
0210:             * Other top components like VCS outputs are closed directly.
0211:             * It is package private because it is also used by EditorWindowOperator. 
0212:             */
0213:            static void close(final Object tc, boolean save) {
0214:                // firstly test whether it is still opened (run in dispatch thread)
0215:                Boolean isOpened = (Boolean) new QueueTool()
0216:                        .invokeSmoothly(new QueueTool.QueueAction("isOpened") { // NOI18N
0217:                            public Object launch() {
0218:                                return new Boolean(((TopComponent) tc)
0219:                                        .isOpened());
0220:                            }
0221:                        });
0222:                if (isOpened.booleanValue()) {
0223:                    // it is still opened => try to close (otherwise do nothing)
0224:                    TopComponentOperator tco = new TopComponentOperator(
0225:                            (TopComponent) tc);
0226:                    if (save) {
0227:                        tco.save();
0228:                        tco.close();
0229:                    } else {
0230:                        tco.closeDiscard();
0231:                    }
0232:                }
0233:            }
0234:
0235:            /** Returns operator of currently shown editor pane.
0236:             * @return  JTabbedPaneOperator instance of editor pane
0237:             */
0238:            public JEditorPaneOperator txtEditorPane() {
0239:                if (_txtEditorPane == null) {
0240:                    _txtEditorPane = new JEditorPaneOperator(this );
0241:                }
0242:                return _txtEditorPane;
0243:            }
0244:
0245:            /** Returns operator of label showing current row and column at the left
0246:             * corner of the Source Editor window.
0247:             * @return JLabelOperator instance of row:column label
0248:             */
0249:            public JLabelOperator lblRowColumn() {
0250:                if (_lblRowColumn == null) {
0251:                    _lblRowColumn = new JLabelOperator(this , 0);
0252:                }
0253:                return _lblRowColumn;
0254:            }
0255:
0256:            /** Returns operator of label showing current input mode (INS/OVR -
0257:             * insert/overwrite).
0258:             * @return JLabelOperator instance of input mode label
0259:             */
0260:            public JLabelOperator lblInputMode() {
0261:                if (_lblInputMode == null) {
0262:                    _lblInputMode = new JLabelOperator(this , 1);
0263:                }
0264:                return _lblInputMode;
0265:            }
0266:
0267:            /** Returns operator of status bar at the bottom of the Source Editor.
0268:             * @return JLabelOperator instance of status bar
0269:             */
0270:            public JLabelOperator lblStatusBar() {
0271:                if (_lblStatusBar == null) {
0272:                    _lblStatusBar = new JLabelOperator(this , 2);
0273:                }
0274:                return _lblStatusBar;
0275:            }
0276:
0277:            /************** Get, select, delete, insert text ************************/
0278:
0279:            /** Gets text from the currently opened Editor window.
0280:             * @return a string representing whole content of the Editor window
0281:             * (including new line characters)
0282:             */
0283:            public String getText() {
0284:                return txtEditorPane().getText();
0285:            }
0286:
0287:            /** Gets text from specified line.
0288:             * It might fail on the last line of a file because of issues
0289:             * http://www.netbeans.org/issues/show_bug.cgi?id=24434 and
0290:             * http://www.netbeans.org/issues/show_bug.cgi?id=24433.
0291:             * @param lineNumber number of line (beggining from 1)
0292:             * @return a string representing content of the line including new line
0293:             * character
0294:             */
0295:            public String getText(int lineNumber) {
0296:                return ((Line) getLine(lineNumber)).getText();
0297:            }
0298:
0299:            /** Returns instance of org.openide.text.Line for given line number.
0300:             * @param lineNumber number of line (beggining at 1)
0301:             * @return org.openide.text.Line instance
0302:             */
0303:            private Object getLine(int lineNumber) {
0304:                Document doc = txtEditorPane().getDocument();
0305:                DataObject od = (DataObject) doc
0306:                        .getProperty(Document.StreamDescriptionProperty);
0307:                Set set = ((LineCookie) od.getCookie(LineCookie.class))
0308:                        .getLineSet();
0309:                try {
0310:                    return set.getCurrent(lineNumber - 1);
0311:                } catch (IndexOutOfBoundsException e) {
0312:                    throw new JemmyException("Index must be > 0", e);
0313:                }
0314:            }
0315:
0316:            /** Checks if editor window contains text specified as parameter text.
0317:             * @param text text to compare to
0318:             * @return true if text was found, false otherwise
0319:             */
0320:            public boolean contains(String text) {
0321:                return getText().indexOf(text) != -1;
0322:            }
0323:
0324:            /** Selects whole line specified by its number. Caret will stand at the
0325:             * next available line.
0326:             * @param lineNumber number of line (beggining from 1)
0327:             */
0328:            public void select(int lineNumber) {
0329:                int lineOffset = getLineOffset(lineNumber);
0330:                setCaretPosition(lineOffset);
0331:                txtEditorPane().moveCaretPosition(
0332:                        lineOffset + getText(lineNumber).length());
0333:            }
0334:
0335:            /** Selects text between line1 and line2 (both are included). Caret will
0336:             * stand behing the selection (at the next line if available).
0337:             * @param line1 number of line where to begin (beggining from 1)
0338:             * @param line2 number of line where to finish (beggining from 1)
0339:             */
0340:            public void select(int line1, int line2) {
0341:                setCaretPosition(getLineOffset(line1));
0342:                txtEditorPane().moveCaretPosition(
0343:                        getLineOffset(line2) + getText(line2).length());
0344:            }
0345:
0346:            /** Selects text in specified line on position defined by column1
0347:             * and column2 (both are included). Caret will stand at the end of
0348:             * the selection.
0349:             * @param lineNumber number of line (beggining from 1)
0350:             * @param column1 column position where selection starts (beggining from 1)
0351:             * @param column2 column position where selection ends (beggining from 1) */
0352:            public void select(int lineNumber, int column1, int column2) {
0353:                int lineOffset = getLineOffset(lineNumber);
0354:                setCaretPosition(lineOffset + column1 - 1);
0355:                txtEditorPane().moveCaretPosition(lineOffset + column2);
0356:            }
0357:
0358:            /** Selects index-th occurence of given text.
0359:             * @param text text to be selected
0360:             * @param index index of text occurence (first occurence has index 0)
0361:             * @see #select(String)
0362:             */
0363:            public void select(String text, int index) {
0364:                int position = txtEditorPane().getPositionByText(text, index);
0365:                if (position == -1) {
0366:                    throw new JemmyException(index + "-th occurence of \""
0367:                            + text + "\" not found.");
0368:                }
0369:                setCaretPosition(position);
0370:                txtEditorPane().moveCaretPosition(position + text.length());
0371:            }
0372:
0373:            /** Selects first occurence of given text.
0374:             * @param text text to be selected
0375:             * @see #select(String, int)
0376:             */
0377:            public void select(String text) {
0378:                select(text, 0);
0379:            }
0380:
0381:            /** Replaces first occurence of oldText by newText.
0382:             * @param oldText text to be replaced
0383:             * @param newText text to write instead
0384:             */
0385:            public void replace(String oldText, String newText) {
0386:                replace(oldText, newText, 0);
0387:            }
0388:
0389:            /** Replaced index-th occurence of oldText by newText.
0390:             * @param oldText text to be replaced
0391:             * @param newText text to write instead
0392:             * @param index index of oldText occurence (first occurence has index 0)
0393:             */
0394:            public void replace(String oldText, String newText, int index) {
0395:                select(oldText, index);
0396:                txtEditorPane().replaceSelection(newText);
0397:            }
0398:
0399:            /** Inserts text to current position. Caret will stand at the end
0400:             * of newly inserted text.
0401:             * @param text a string to be inserted
0402:             */
0403:            public void insert(final String text) {
0404:                final int offset = txtEditorPane().getCaretPosition();
0405:                runMapping(new MapVoidAction("insertString") {
0406:                    public void map() {
0407:                        try {
0408:                            txtEditorPane().getDocument().insertString(offset,
0409:                                    text, null);
0410:                        } catch (BadLocationException e) {
0411:                            throw new JemmyException("Cannot insert \"" + text
0412:                                    + "\" to position " + offset + ".", e);
0413:                        }
0414:                    }
0415:                });
0416:            }
0417:
0418:            /** Inserts text to position specified by line number and column.
0419:             * Caret will stand at the end of newly inserted text.
0420:             * @param text a string to be inserted
0421:             * @param lineNumber number of line (beggining from 1)
0422:             * @param column column position (beggining from 1)
0423:             */
0424:            public void insert(String text, int lineNumber, int column) {
0425:                setCaretPosition(lineNumber, column);
0426:                insert(text);
0427:            }
0428:
0429:            /** Deletes given number of characters from specified possition.
0430:             * Position of caret will not change.
0431:             * @param offset position inside document (0 means the beginning)
0432:             * @param length number of characters to be deleted
0433:             */
0434:            public void delete(final int offset, final int length) {
0435:                // run in dispatch thread
0436:                runMapping(new MapVoidAction("remove") { // NOI18N
0437:                    public void map() {
0438:                        try {
0439:                            txtEditorPane().getDocument()
0440:                                    .remove(offset, length);
0441:                        } catch (BadLocationException e) {
0442:                            throw new JemmyException("Cannot delete " + length
0443:                                    + " characters from position " + offset
0444:                                    + ".", e);
0445:                        }
0446:                    }
0447:                });
0448:            }
0449:
0450:            /** Deletes given number of characters from current caret possition.
0451:             * Position of caret will not change.
0452:             * @param length number of characters to be deleted
0453:             */
0454:            public void delete(int length) {
0455:                delete(txtEditorPane().getCaretPosition(), length);
0456:            }
0457:
0458:            /** Delete specified line.
0459:             * Position of caret will not change.
0460:             * @param line number of line (beggining from 1)
0461:             */
0462:            public void deleteLine(int line) {
0463:                delete(getLineOffset(line), getText(line).length());
0464:            }
0465:
0466:            /** Deletes characters between column1 and column2 (both are included)
0467:             * on the specified line.
0468:             * @param lineNumber number of line (beggining from 1)
0469:             * @param column1 column position where to start deleting (beggining from 1)
0470:             * @param column2 column position where to stop deleting (beggining from 1) */
0471:            public void delete(int lineNumber, int column1, int column2) {
0472:                delete(getLineOffset(lineNumber) + column1 - 1, column2
0473:                        - column1 + 1);
0474:            }
0475:
0476:            /********************** Caret manipulation ************************/
0477:
0478:            /** Returns current line number.
0479:             * @return number of line where the caret stays (first line == 1)
0480:             */
0481:            public int getLineNumber() {
0482:                StyledDocument doc = (StyledDocument) txtEditorPane()
0483:                        .getDocument();
0484:                int offset = txtEditorPane().getCaretPosition();
0485:                return NbDocument.findLineNumber(doc, offset) + 1;
0486:            }
0487:
0488:            /**
0489:             * Pushes key of requested key code.
0490:             * @param keyCode key code
0491:             */
0492:            public void pushKey(int keyCode) {
0493:                // need to request focus before any key push
0494:                this .requestFocus();
0495:                txtEditorPane().pushKey(keyCode);
0496:            }
0497:
0498:            /** Pushes Home key (KeyEvent.VK_HOME) */
0499:            public void pushHomeKey() {
0500:                pushKey(KeyEvent.VK_HOME);
0501:            }
0502:
0503:            /** Pushes End key (KeyEvent.VK_END) */
0504:            public void pushEndKey() {
0505:                pushKey(KeyEvent.VK_END);
0506:            }
0507:
0508:            /** Pushes Tab key (KeyEvent.VK_TAB) */
0509:            public void pushTabKey() {
0510:                pushKey(KeyEvent.VK_TAB);
0511:            }
0512:
0513:            /** Pushes Down key (KeyEvent.VK_DOWN) */
0514:            public void pushDownArrowKey() {
0515:                pushKey(KeyEvent.VK_DOWN);
0516:            }
0517:
0518:            /** Pushes Up key (KeyEvent.VK_UP) */
0519:            public void pushUpArrowKey() {
0520:                pushKey(KeyEvent.VK_UP);
0521:            }
0522:
0523:            /** Returns offset of the beginning of a line.
0524:             * @param lineNumber number of line (starts at 1)
0525:             * @return offset offset of line from the beginning of a file
0526:             */
0527:            private int getLineOffset(int lineNumber) {
0528:                try {
0529:                    StyledDocument doc = (StyledDocument) txtEditorPane()
0530:                            .getDocument();
0531:                    return NbDocument.findLineOffset(doc, lineNumber - 1);
0532:                } catch (IndexOutOfBoundsException e) {
0533:                    throw new JemmyException("Invalid line number "
0534:                            + lineNumber, e);
0535:                }
0536:            }
0537:
0538:            /** Sets caret position relatively to current position.
0539:             * @param relativeMove count of charaters to move caret
0540:             */
0541:            public void setCaretPositionRelative(int relativeMove) {
0542:                setCaretPosition(txtEditorPane().getCaretPosition()
0543:                        + relativeMove);
0544:            }
0545:
0546:            /** Sets caret position to the beginning of specified line.
0547:             * Lines are numbered from 1, so setCaretPosition(1) will set caret
0548:             * to the beginning of the first line.
0549:             * @param lineNumber number of line (beggining from 1)
0550:             */
0551:            public void setCaretPositionToLine(int lineNumber) {
0552:                txtEditorPane().setCaretPosition(getLineOffset(lineNumber));
0553:            }
0554:
0555:            /** Sets caret position to the end of specified line.
0556:             * Lines are numbered from 1, so setCaretPosition(1) will set caret
0557:             * to the end of the first line.
0558:             * @param lineNumber number of line (beggining from 1)
0559:             */
0560:            public void setCaretPositionToEndOfLine(int lineNumber) {
0561:                // getText returns contents of line plus \n, that's why we use length()-1
0562:                txtEditorPane().setCaretPosition(
0563:                        getLineOffset(lineNumber)
0564:                                + getText(lineNumber).length() - 1);
0565:            }
0566:
0567:            /** Sets caret position to specified line and column
0568:             * @param lineNumber line number where to set caret
0569:             * @param column column where to set caret (1 means beginning of the row)
0570:             */
0571:            public void setCaretPosition(int lineNumber, int column) {
0572:                setCaretPosition(getLineOffset(lineNumber) + column - 1);
0573:            }
0574:
0575:            /** Sets caret to desired position.
0576:             * @param position a position to set caret to (number of characters from
0577:             * the beggining of the file - 0 means beginning of the file).
0578:             */
0579:            public void setCaretPosition(int position) {
0580:                if (position < 0 || position > getText().length()) {
0581:                    throw new JemmyException("Invalid caret position "
0582:                            + position);
0583:                }
0584:                txtEditorPane().setCaretPosition(position);
0585:            }
0586:
0587:            /** Sets caret position before or after index-th occurence of given string.
0588:             * @param text text to be searched
0589:             * @param index index of text occurence (first occurence has index 0)
0590:             * @param before if true put caret before text, otherwise after.
0591:             */
0592:            public void setCaretPosition(String text, int index, boolean before) {
0593:                setCaretPosition(txtEditorPane().getPositionByText(text, index)
0594:                        + (before ? 0 : text.length()));
0595:            }
0596:
0597:            /** Sets caret position before or after first occurence of given string.
0598:             * @param text text to be searched
0599:             * @param before if true put caret before text, otherwise after.
0600:             */
0601:            public void setCaretPosition(String text, boolean before) {
0602:                setCaretPosition(text, 0, before);
0603:            }
0604:
0605:            /**************************** Annotations ******************************/
0606:            /************** thanks to Jan Lahoda for valuable input  ***************/
0607:
0608:            /** Gets an array of annotations attached to given line.
0609:             * @param lineNumber number of line (beggining from 1)
0610:             * @return an array of org.openide.text.Annotation instances
0611:             * @see #getAnnotationShortDescription
0612:             * @see #getAnnotationType
0613:             */
0614:            public Object[] getAnnotations(int lineNumber) {
0615:                ArrayList<Object> result = new ArrayList<Object>();
0616:                try {
0617:                    Class annotationsClass = Class
0618:                            .forName("org.netbeans.editor.Annotations");
0619:                    Method getLineAnnotationsMethod = annotationsClass
0620:                            .getDeclaredMethod("getLineAnnotations",
0621:                                    new Class[] { int.class });
0622:                    getLineAnnotationsMethod.setAccessible(true);
0623:                    Object lineAnnotations = getLineAnnotationsMethod.invoke(
0624:                            getAnnotationsInstance(),
0625:                            new Object[] { new Integer(lineNumber - 1) });
0626:                    if (lineAnnotations != null) {
0627:                        result = getAnnotations(lineAnnotations);
0628:                    }
0629:                } catch (Exception e) {
0630:                    throw new JemmyException("getAnnotations failed.", e);
0631:                }
0632:                return result.toArray(new Annotation[result.size()]);
0633:            }
0634:
0635:            /**Gets all annotations for current editor (Document).
0636:             * @return array of org.openide.text.Annotation containing all annotations
0637:             *         attached to this editor.
0638:             * @see #getAnnotationShortDescription
0639:             * @see #getAnnotationType
0640:             */
0641:            public Object[] getAnnotations() {
0642:                ArrayList<Object> result = new ArrayList<Object>();
0643:                try {
0644:                    Class annotationsClass = Class
0645:                            .forName("org.netbeans.editor.Annotations");
0646:                    Field lineAnnotationsArrayField = annotationsClass
0647:                            .getDeclaredField("lineAnnotationsArray");
0648:                    lineAnnotationsArrayField.setAccessible(true);
0649:                    ArrayList lineAnnotationsArray = (ArrayList) lineAnnotationsArrayField
0650:                            .get(getAnnotationsInstance());
0651:                    // loop through all lines
0652:                    for (int i = 0; i < lineAnnotationsArray.size(); i++) {
0653:                        result.addAll(getAnnotations(lineAnnotationsArray
0654:                                .get(i)));
0655:                    }
0656:                } catch (Exception e) {
0657:                    throw new JemmyException("getAnnotations failed.", e);
0658:                }
0659:                return result.toArray(new Annotation[result.size()]);
0660:            }
0661:
0662:            /** Returns instance of org.netbeans.editor.Annotations object for this
0663:             * document. */
0664:            private Object getAnnotationsInstance() throws Exception {
0665:                Class baseDocumentClass = Class
0666:                        .forName("org.netbeans.editor.BaseDocument");
0667:                Method getAnnotationsMethod = baseDocumentClass
0668:                        .getDeclaredMethod("getAnnotations", (Class[]) null);
0669:                getAnnotationsMethod.setAccessible(true);
0670:                return getAnnotationsMethod.invoke(txtEditorPane()
0671:                        .getDocument(), (Object[]) null);
0672:            }
0673:
0674:            /** Returns ArrayList of org.openide.text.Annotation from given LineAnnotations
0675:             * object. */
0676:            private ArrayList<Object> getAnnotations(Object lineAnnotations)
0677:                    throws Exception {
0678:                Class lineAnnotationsClass = Class
0679:                        .forName("org.netbeans.editor.Annotations$LineAnnotations");
0680:                Class annotationDescDelegateClass = Class
0681:                        .forName("org.netbeans.modules.editor.NbEditorDocument$AnnotationDescDelegate");
0682:                Field delegateField = annotationDescDelegateClass
0683:                        .getDeclaredField("delegate");
0684:                delegateField.setAccessible(true);
0685:
0686:                Method getAnnotationsMethod = lineAnnotationsClass
0687:                        .getDeclaredMethod("getAnnotations", (Class[]) null);
0688:                getAnnotationsMethod.setAccessible(true);
0689:                Iterator annotations = (Iterator) getAnnotationsMethod.invoke(
0690:                        lineAnnotations, (Object[]) null);
0691:                ArrayList<Object> result = new ArrayList<Object>();
0692:                for (Iterator it = annotations; it.hasNext();) {
0693:                    result.add(delegateField.get(it.next()));
0694:                }
0695:                return result;
0696:            }
0697:
0698:            /** Returns a string uniquely identifying annotation. For editor bookmark
0699:             * it is for example
0700:             * org.netbeans.modules.editor.NbEditorKit.BOOKMARK_ANNOTATION_TYPE.
0701:             * @param annotation instance of org.openide.text.Annotation
0702:             * @return a string uniquely identifying annotation
0703:             * @see #getAnnotations()
0704:             *@see #getAnnotations(int)
0705:             */
0706:            public static String getAnnotationType(Object annotation) {
0707:                return ((Annotation) annotation).getAnnotationType();
0708:            }
0709:
0710:            /** Returns a short description of annotation. It is localized.
0711:             * @param annotation instance of org.openide.text.Annotation
0712:             * @return a short description of annotation according to current locale
0713:             */
0714:            public static String getAnnotationShortDescription(Object annotation) {
0715:                return ((Annotation) annotation).getShortDescription();
0716:            }
0717:
0718:            /***************** Methods for toolbar manipulation *******************/
0719:
0720:            /** Return AbstractButtonOperator representing a toolbar button found by given
0721:             * tooltip within the Source Editor.
0722:             * @param buttonTooltip tooltip of toolbar button
0723:             * @return AbstractButtonOperator instance of found toolbar button
0724:             */
0725:            public AbstractButtonOperator getToolbarButton(String buttonTooltip) {
0726:                ToolbarButtonChooser chooser = new ToolbarButtonChooser(
0727:                        buttonTooltip, getComparator());
0728:                return new AbstractButtonOperator(AbstractButtonOperator
0729:                        .waitAbstractButton((Container) this .getSource(),
0730:                                chooser));
0731:            }
0732:
0733:            /** Return AbstractButtonOperator representing index-th toolbar button within
0734:             * the Source Editor.
0735:             * @param index index of toolbar button to find
0736:             * @return AbstractButtonOperator instance of found toolbar button
0737:             */
0738:            public AbstractButtonOperator getToolbarButton(int index) {
0739:                // finds JToolbar
0740:                ComponentChooser chooser = new ComponentChooser() {
0741:                    public boolean checkComponent(Component comp) {
0742:                        return comp instanceof  JToolBar;
0743:                    }
0744:
0745:                    public String getDescription() {
0746:                        return "javax.swing.JToolBar";
0747:                    }
0748:                };
0749:                Container toolbar = (Container) findComponent(
0750:                        (Container) getSource(), chooser);
0751:                if (toolbar == null) {
0752:                    throw new JemmyException("Toolbar not present.");
0753:                }
0754:                // if "quick browse" combo box is present, skip first button (MetalComboBoxButton usualy)
0755:                Component combo = JComboBoxOperator.findJComboBox(toolbar,
0756:                        ComponentSearcher.getTrueChooser("JComboBox"));
0757:                if (combo != null) {
0758:                    index++;
0759:                }
0760:                return new AbstractButtonOperator(AbstractButtonOperator
0761:                        .waitAbstractButton((Container) toolbar,
0762:                                ComponentSearcher
0763:                                        .getTrueChooser("AbstractButton"),
0764:                                index));
0765:            }
0766:
0767:            /** Chooser which can be used to find a component with given tooltip,
0768:             * in this case a toolbar button.
0769:             */
0770:            private static class ToolbarButtonChooser implements 
0771:                    ComponentChooser {
0772:                private String buttonTooltip;
0773:                private StringComparator comparator;
0774:
0775:                public ToolbarButtonChooser(String buttonTooltip,
0776:                        StringComparator comparator) {
0777:                    this .buttonTooltip = buttonTooltip;
0778:                    this .comparator = comparator;
0779:                }
0780:
0781:                public boolean checkComponent(Component comp) {
0782:                    return comparator.equals(((JComponent) comp)
0783:                            .getToolTipText(), buttonTooltip);
0784:                }
0785:
0786:                public String getDescription() {
0787:                    return "Toolbar button with tooltip \"" + buttonTooltip
0788:                            + "\".";
0789:                }
0790:            }
0791:
0792:            /********************************** Code folding **************************/
0793:            /*************************** Thanks to Martin Roskanin ********************/
0794:
0795:            /** Waits for code folding initialization. */
0796:            public void waitFolding() {
0797:                JTextComponent textComponent = (JTextComponent) txtEditorPane()
0798:                        .getSource();
0799:                final AbstractDocument adoc = (AbstractDocument) txtEditorPane()
0800:                        .getDocument();
0801:                // Dump fold hierarchy
0802:                final FoldHierarchy hierarchy = FoldHierarchy
0803:                        .get(textComponent);
0804:                getOutput().printTrace("Wait folding is initialized.");
0805:                waitState(new ComponentChooser() {
0806:                    public boolean checkComponent(Component comp) {
0807:                        adoc.readLock();
0808:                        try {
0809:                            hierarchy.lock();
0810:                            try {
0811:                                return hierarchy.getRootFold().getFoldCount() > 0;
0812:                            } finally {
0813:                                hierarchy.unlock();
0814:                            }
0815:                        } finally {
0816:                            adoc.readUnlock();
0817:                        }
0818:                    }
0819:
0820:                    public String getDescription() {
0821:                        return ("Folding initialized"); // NOI18N
0822:                    }
0823:                });
0824:            }
0825:
0826:            /** Waits for fold at cursor position is collapsed. */
0827:            public void waitCollapsed() {
0828:                getOutput().printTrace(
0829:                        "Wait fold is collapsed at line " + getLineNumber());
0830:                waitState(new ComponentChooser() {
0831:                    public boolean checkComponent(Component comp) {
0832:                        return isCollapsed();
0833:                    }
0834:
0835:                    public String getDescription() {
0836:                        return ("Fold collapsed");
0837:                    }
0838:                });
0839:            }
0840:
0841:            /** Waits for fold at cursor position is expanded. */
0842:            public void waitExpanded() {
0843:                getOutput().printTrace(
0844:                        "Wait fold is expanded at line " + getLineNumber());
0845:                waitState(new ComponentChooser() {
0846:                    public boolean checkComponent(Component comp) {
0847:                        return !isCollapsed();
0848:                    }
0849:
0850:                    public String getDescription() {
0851:                        return ("Fold expanded");
0852:                    }
0853:                });
0854:            }
0855:
0856:            /** Collapses fold at cursor position using CTRL+'-'. It waits until fold 
0857:             * is not collapsed.
0858:             */
0859:            public void collapseFold() {
0860:                getOutput().printTrace(
0861:                        "Collapse fold at line " + getLineNumber());
0862:                requestFocus();
0863:                txtEditorPane().pushKey(KeyEvent.VK_SUBTRACT,
0864:                        KeyEvent.CTRL_DOWN_MASK);
0865:                waitCollapsed();
0866:            }
0867:
0868:            /** Collapses fold at specified line using CTRL+'-'. It waits until fold 
0869:             * is not collapsed.
0870:             * @param lineNumber number of line (starts at 1)
0871:             */
0872:            public void collapseFold(int lineNumber) {
0873:                setCaretPositionToLine(lineNumber);
0874:                collapseFold();
0875:            }
0876:
0877:            /** Expands fold at specified line using CTRL+'+'. It waits until fold 
0878:             * is not expanded.
0879:             */
0880:            public void expandFold() {
0881:                getOutput()
0882:                        .printTrace("Expand fold at line " + getLineNumber());
0883:                requestFocus();
0884:                txtEditorPane().pushKey(KeyEvent.VK_ADD,
0885:                        KeyEvent.CTRL_DOWN_MASK);
0886:                waitExpanded();
0887:            }
0888:
0889:            /** Expands fold at specified line using CTRL+'+'. It waits until fold 
0890:             * is not expanded.
0891:             * @param lineNumber number of line (starts at 1)
0892:             */
0893:            public void expandFold(int lineNumber) {
0894:                setCaretPositionToLine(lineNumber);
0895:                expandFold();
0896:            }
0897:
0898:            /** Returns true if fold at cursor position is collapsed, false if it is 
0899:             * expanded.
0900:             * @return true if fold is collapsed, false if it is  expanded.
0901:             */
0902:            public boolean isCollapsed() {
0903:                return isCollapsed(getLineNumber());
0904:            }
0905:
0906:            /** Returns true if fold at specified line is collapsed, false if it is 
0907:             * expanded.
0908:             * @param lineNumber number of line (starts at 1)
0909:             * @return true if fold is collapsed, false if it is expanded.
0910:             */
0911:            public boolean isCollapsed(int lineNumber) {
0912:                JTextComponent textComponent = (JTextComponent) txtEditorPane()
0913:                        .getSource();
0914:                FoldHierarchy hierarchy = FoldHierarchy.get(textComponent);
0915:                int dot = getLineOffset(lineNumber);
0916:                hierarchy.lock();
0917:                try {
0918:                    try {
0919:                        int rowStart = javax.swing.text.Utilities.getRowStart(
0920:                                textComponent, dot);
0921:                        int rowEnd = javax.swing.text.Utilities.getRowEnd(
0922:                                textComponent, dot);
0923:                        Fold fold = getLineFold(hierarchy, dot, rowStart,
0924:                                rowEnd);
0925:                        if (fold != null) {
0926:                            return fold.isCollapsed();
0927:                        } else {
0928:                            throw new JemmyException(
0929:                                    "No fold found at position " + dot + ".");
0930:                        }
0931:                    } catch (BadLocationException ble) {
0932:                        throw new JemmyException(
0933:                                "BadLocationException when seraching for fold.",
0934:                                ble);
0935:                    }
0936:                } finally {
0937:                    hierarchy.unlock();
0938:                }
0939:            }
0940:
0941:            /** Returns the fold that should be collapsed/expanded in the caret row
0942:             *  @param hierarchy hierarchy under which all folds should be collapsed/expanded.
0943:             *  @param dot caret position offset
0944:             *  @param lineStart offset of the start of line
0945:             *  @param lineEnd offset of the end of line
0946:             *  @return the fold that meet common criteria in accordance with the caret position
0947:             */
0948:            private static Fold getLineFold(FoldHierarchy hierarchy, int dot,
0949:                    int lineStart, int lineEnd) {
0950:                Fold caretOffsetFold = FoldUtilities.findOffsetFold(hierarchy,
0951:                        dot);
0952:
0953:                // beginning searching from the lineStart
0954:                Fold fold = FoldUtilities.findNearestFold(hierarchy, lineStart);
0955:
0956:                while (fold != null && (fold.getEndOffset() <= dot || // find next available fold if the 'fold' is one-line
0957:                        // or it has children and the caret is in the fold body
0958:                        // i.e. class A{ |public void method foo(){}}
0959:                        (!fold.isCollapsed() && fold.getFoldCount() > 0 && fold
0960:                                .getStartOffset() + 1 < dot))) {
0961:
0962:                    // look for next fold in forward direction
0963:                    Fold nextFold = FoldUtilities
0964:                            .findNearestFold(hierarchy,
0965:                                    (fold.getFoldCount() > 0) ? fold
0966:                                            .getStartOffset() + 1 : fold
0967:                                            .getEndOffset());
0968:                    if (nextFold != null && nextFold.getStartOffset() < lineEnd) {
0969:                        if (nextFold == fold)
0970:                            return fold;
0971:                        fold = nextFold;
0972:                    } else {
0973:                        break;
0974:                    }
0975:                }
0976:
0977:                // a fold on the next line was found, returning fold at offset (in most cases inner class)
0978:                if (fold == null || fold.getStartOffset() > lineEnd) {
0979:                    // in the case:
0980:                    // class A{
0981:                    // }     |
0982:                    // try to find an offset fold on the offset of the line beginning
0983:                    if (caretOffsetFold == null) {
0984:                        caretOffsetFold = FoldUtilities.findOffsetFold(
0985:                                hierarchy, lineStart);
0986:                    }
0987:                    return caretOffsetFold;
0988:                }
0989:
0990:                // no fold at offset found, in this case return the fold
0991:                if (caretOffsetFold == null) {
0992:                    return fold;
0993:                }
0994:
0995:                // skip possible inner class members validating if the innerclass fold is collapsed
0996:                if (caretOffsetFold.isCollapsed()) {
0997:                    return caretOffsetFold;
0998:                }
0999:
1000:                // in the case:
1001:                // class A{
1002:                // public vo|id foo(){} }
1003:                // 'fold' (in this case fold of the method foo) will be returned
1004:                if (caretOffsetFold.getEndOffset() > fold.getEndOffset()
1005:                        && fold.getEndOffset() > dot) {
1006:                    return fold;
1007:                }
1008:
1009:                // class A{
1010:                // |} public void method foo(){}
1011:                // inner class fold will be returned
1012:                if (fold.getStartOffset() > caretOffsetFold.getEndOffset()) {
1013:                    return caretOffsetFold;
1014:                }
1015:
1016:                // class A{
1017:                // public void foo(){} |}
1018:                // returning innerclass fold
1019:                if (fold.getEndOffset() < dot) {
1020:                    return caretOffsetFold;
1021:                }
1022:                return fold;
1023:            }
1024:
1025:            /********************************** Miscellaneous **************************/
1026:
1027:            /** Waits for given modified state of edited source.
1028:             * @param modified boolean true waits for file state change to modified, false for change to
1029:             * unmodified (saved).
1030:             * Throws TimeoutExpiredException when EditorOperator.WaitModifiedTimeout expires.
1031:             */
1032:            public void waitModified(final boolean modified) {
1033:                try {
1034:                    Waiter waiter = new Waiter(new Waitable() {
1035:                        public Object actionProduced(Object obj) {
1036:                            return isModified() == modified ? new Object()
1037:                                    : null;
1038:                        }
1039:
1040:                        public String getDescription() {
1041:                            return ("Wait Modified State");
1042:                        }
1043:                    });
1044:                    Timeouts times = getTimeouts().cloneThis();
1045:                    times.setTimeout("Waiter.WaitingTime", times
1046:                            .getTimeout("EditorOperator.WaitModifiedTimeout"));
1047:                    waiter.setTimeouts(times);
1048:                    waiter.setOutput(getOutput());
1049:                    waiter.waitAction(null);
1050:                } catch (InterruptedException e) {
1051:                }
1052:            }
1053:
1054:            /** Saves content of this Editor by API. If it is not applicable or content 
1055:             * is not modified, it does nothing.
1056:             */
1057:            public void save() {
1058:                super .save();
1059:                if (getVerification()) {
1060:                    waitModified(false);
1061:                }
1062:            }
1063:
1064:            /** Performs verification by accessing all sub-components */
1065:            public void verify() {
1066:                txtEditorPane();
1067:                lblInputMode();
1068:                lblRowColumn();
1069:                lblStatusBar();
1070:            }
1071:
1072:            /** SubChooser to determine Editor TopComponent
1073:             * Used in findTopComponent method.
1074:             */
1075:            public static final class EditorSubchooser implements 
1076:                    ComponentChooser {
1077:                /** Checks component.
1078:                 * @param comp component
1079:                 * @return true if component instance of CloneableEditor
1080:                 */
1081:                public boolean checkComponent(Component comp) {
1082:                    return (comp instanceof  CloneableEditor);
1083:                }
1084:
1085:                /** Description.
1086:                 * @return Description
1087:                 */
1088:                public String getDescription() {
1089:                    return "org.openide.text.CloneableEditor";
1090:                }
1091:            }
1092:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.