Source Code Cross Referenced for DefinitionsPane.java in  » IDE » DrJava » edu » rice » cs » drjava » ui » 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 » DrJava » edu.rice.cs.drjava.ui 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*BEGIN_COPYRIGHT_BLOCK
0002:         *
0003:         * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
0004:         * All rights reserved.
0005:         * 
0006:         * Redistribution and use in source and binary forms, with or without
0007:         * modification, are permitted provided that the following conditions are met:
0008:         *    * Redistributions of source code must retain the above copyright
0009:         *      notice, this list of conditions and the following disclaimer.
0010:         *    * Redistributions in binary form must reproduce the above copyright
0011:         *      notice, this list of conditions and the following disclaimer in the
0012:         *      documentation and/or other materials provided with the distribution.
0013:         *    * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
0014:         *      names of its contributors may be used to endorse or promote products
0015:         *      derived from this software without specific prior written permission.
0016:         * 
0017:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0018:         * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0019:         * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0020:         * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
0021:         * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0022:         * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0023:         * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
0024:         * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
0025:         * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
0026:         * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0027:         * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0028:         *
0029:         * This software is Open Source Initiative approved Open Source Software.
0030:         * Open Source Initative Approved is a trademark of the Open Source Initiative.
0031:         * 
0032:         * This file is part of DrJava.  Download the current version of this project
0033:         * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
0034:         * 
0035:         * END_COPYRIGHT_BLOCK*/
0036:
0037:        package edu.rice.cs.drjava.ui;
0038:
0039:        import javax.swing.*;
0040:        import javax.swing.undo.*;
0041:        import javax.swing.event.*;
0042:        import javax.swing.text.*;
0043:        import java.awt.*;
0044:        import java.awt.event.*;
0045:        import java.util.List;
0046:        import java.util.LinkedList;
0047:
0048:        // TODO: Check synchronization.
0049:        import edu.rice.cs.plt.tuple.Pair;
0050:        import edu.rice.cs.util.UnexpectedException;
0051:        import edu.rice.cs.util.OperationCanceledException;
0052:        import edu.rice.cs.util.swing.HighlightManager;
0053:        import edu.rice.cs.util.swing.RightClickMouseAdapter;
0054:        import edu.rice.cs.util.text.SwingDocument;
0055:        import edu.rice.cs.drjava.model.*;
0056:        import edu.rice.cs.drjava.model.definitions.CompoundUndoManager;
0057:        import edu.rice.cs.drjava.model.definitions.DefinitionsEditorKit;
0058:        import edu.rice.cs.drjava.model.definitions.NoSuchDocumentException;
0059:        import edu.rice.cs.drjava.model.definitions.indent.Indenter;
0060:        import edu.rice.cs.drjava.model.definitions.reducedmodel.ReducedModelState;
0061:        import edu.rice.cs.drjava.config.*;
0062:        import edu.rice.cs.drjava.DrJava;
0063:        import edu.rice.cs.drjava.CodeStatus;
0064:        import edu.rice.cs.drjava.model.debug.Breakpoint;
0065:
0066:        /** The pane in which work on a given OpenDefinitionsDocument occurs. A DefinitionsPane is tied to a single document,
0067:         *  which cannot be changed.
0068:         *  @version $Id: DefinitionsPane.java 4255 2007-08-28 19:17:37Z mgricken $
0069:         */
0070:        public class DefinitionsPane extends AbstractDJPane implements 
0071:                Finalizable<DefinitionsPane> {
0072:
0073:            /** This field NEEDS to be set by setEditorKit() BEFORE any DefinitonsPanes are created. */
0074:            private static DefinitionsEditorKit EDITOR_KIT;
0075:
0076:            /* Minimum number of characters to trigger indent warning prompt */
0077:            private static int INDENT_WARNING_THRESHOLD = 20000;
0078:
0079:            /** Our parent window. */
0080:            private final MainFrame _mainFrame;
0081:            /** Our corresponding ODD */
0082:            private final OpenDefinitionsDocument _doc;
0083:
0084:            private volatile UndoAction _undoAction;
0085:            private volatile RedoAction _redoAction;
0086:            private volatile boolean testVariable; //For Tests ONLY
0087:            //  private Document _defdoc;
0088:
0089:            /** Flag used to determine if the user has already been warned about debugging when the document within 
0090:             *  this defpane has been modified since its last save.
0091:             */
0092:            private volatile boolean _hasWarnedAboutModified = false;
0093:
0094:            //  /** Used by the centering source mechanism to ensure paints */
0095:            //  private boolean _updatePending = false;
0096:
0097:            /** Whether to draw text as antialiased. */
0098:            private volatile boolean _antiAliasText = false;
0099:
0100:            /** Our current compiler error matching highlight. */
0101:            private volatile HighlightManager.HighlightInfo _errorHighlightTag = null;
0102:
0103:            /** Highlight painter for bookmarks. */
0104:            static volatile ReverseHighlighter.DefaultUnderlineHighlightPainter BOOKMARK_PAINTER = new ReverseHighlighter.DefaultUnderlineHighlightPainter(
0105:                    DrJava.getConfig().getSetting(BOOKMARK_COLOR), 3);
0106:
0107:            /** Highlight painter for find results. */
0108:            static volatile ReverseHighlighter.DefaultUnderlineHighlightPainter[] FIND_RESULTS_PAINTERS;
0109:
0110:            static {
0111:                FIND_RESULTS_PAINTERS = new ReverseHighlighter.DefaultUnderlineHighlightPainter[FIND_RESULTS_COLORS.length + 1];
0112:                for (int i = 0; i < FIND_RESULTS_COLORS.length; ++i) {
0113:                    FIND_RESULTS_PAINTERS[i] = new ReverseHighlighter.DefaultUnderlineHighlightPainter(
0114:                            DrJava.getConfig().getSetting(
0115:                                    FIND_RESULTS_COLORS[i]), 3);
0116:                }
0117:                FIND_RESULTS_PAINTERS[FIND_RESULTS_COLORS.length] = new ReverseHighlighter.DefaultUnderlineHighlightPainter(
0118:                        Color.WHITE, 0);
0119:            }
0120:
0121:            /** How many find result panels are using the highlight painters. */
0122:            static volatile int[] FIND_RESULTS_PAINTERS_USAGE = new int[FIND_RESULTS_COLORS.length];
0123:
0124:            /** Highlight painter for breakpoints. */
0125:            static ReverseHighlighter.DrJavaHighlightPainter BREAKPOINT_PAINTER = new ReverseHighlighter.DrJavaHighlightPainter(
0126:                    DrJava.getConfig().getSetting(DEBUG_BREAKPOINT_COLOR));
0127:
0128:            /** Highlight painter for disabled breakpoints. */
0129:            static volatile ReverseHighlighter.DrJavaHighlightPainter DISABLED_BREAKPOINT_PAINTER = new ReverseHighlighter.DrJavaHighlightPainter(
0130:                    DrJava.getConfig().getSetting(
0131:                            DEBUG_BREAKPOINT_DISABLED_COLOR));
0132:
0133:            /** Highlight painter for thread's current location. */
0134:            static volatile ReverseHighlighter.DrJavaHighlightPainter THREAD_PAINTER = new ReverseHighlighter.DrJavaHighlightPainter(
0135:                    DrJava.getConfig().getSetting(DEBUG_THREAD_COLOR));
0136:
0137:            /** The name of the keymap added to the super class (saved so it can be removed). */
0138:            public static final String INDENT_KEYMAP_NAME = "INDENT_KEYMAP";
0139:
0140:            /** Updates match highlights.  Only runs in the event thread except in some unit tests. */
0141:            protected void matchUpdate(int offset) {
0142:                _doc.setCurrentLocation(offset);
0143:                _removePreviousHighlight();
0144:
0145:                // Update the highlight if there is any. Not necessarily executed in event thread
0146:                int to = getCaretPosition();
0147:                int from = _doc.balanceBackward();
0148:                if (from > -1) {
0149:                    // Found a matching open brace to this close brace
0150:                    from = to - from;
0151:                    _addHighlight(from, to);
0152:                    //     Highlighter.Highlight[] _lites = getHighlighter().getHighlights();
0153:
0154:                    String matchText = _matchText(from);
0155:
0156:                    if (matchText != null)
0157:                        _mainFrame.updateStatusField("Bracket matches: "
0158:                                + matchText);
0159:                    else
0160:                        _mainFrame.updateStatusField();
0161:                }
0162:
0163:                // if this wasn't a close brace, check for an open brace
0164:                else {
0165:                    // (getCaretPosition will be the start of the highlight)
0166:                    from = to;
0167:
0168:                    to = _doc.balanceForward();
0169:                    if (to > -1) {
0170:                        to = to + from;
0171:                        _addHighlight(from - 1, to);
0172:                        //        Highlighter.Highlight[] _lites = getHighlighter().getHighlights();
0173:                    }
0174:                    _mainFrame.updateStatusField();
0175:                }
0176:            }
0177:
0178:            /* Returns the text of the line where a matching open brace exists whenever the cursor is at a closing brace */
0179:            private String _matchText(int braceIndex) {
0180:                DJDocument doc = _doc;
0181:                String docText;
0182:                docText = doc.getText();
0183:
0184:                if (docText.charAt(braceIndex) == '{') {//match everything before if we found a curly brace
0185:                    Character charBefore = null;
0186:                    int charBeforeIndex = braceIndex - 1;
0187:                    boolean previousLine = false;
0188:
0189:                    if (charBeforeIndex != -1)
0190:                        charBefore = docText.charAt(charBeforeIndex);
0191:
0192:                    charBeforeIndex--;
0193:
0194:                    while (charBeforeIndex >= 0
0195:                            && (charBefore == '\n' || charBefore == ' ')) {
0196:                        charBefore = docText.charAt(charBeforeIndex);
0197:                        if (!previousLine && charBefore != '\n'
0198:                                && charBefore != ' ')
0199:                            charBeforeIndex = braceIndex - 1;
0200:                        if (charBefore == '\n')
0201:                            previousLine = true;
0202:                        charBeforeIndex--;
0203:                    }
0204:
0205:                    final StringBuilder returnText = new StringBuilder(docText
0206:                            .substring(0, charBeforeIndex + 2));
0207:                    if (previousLine)
0208:                        returnText.append("...");
0209:                    returnText.append("{");
0210:
0211:                    int lastNewLineIndex = returnText.lastIndexOf("\n");
0212:                    return returnText.substring(lastNewLineIndex + 1);
0213:                } else
0214:                    //not a curly brace
0215:                    return null;
0216:            }
0217:
0218:            /** The OptionListener for DEFINITIONS_MATCH_COLOR. */
0219:            private class MatchColorOptionListener implements 
0220:                    OptionListener<Color> {
0221:                public void optionChanged(OptionEvent<Color> oce) {
0222:                    MATCH_PAINTER = new ReverseHighlighter.DrJavaHighlightPainter(
0223:                            oce.value);
0224:                    if (_matchHighlight != null) {
0225:                        int start = _matchHighlight.getStartOffset();
0226:                        int end = _matchHighlight.getEndOffset();
0227:                        _matchHighlight.remove();
0228:                        _addHighlight(start, end);
0229:                    }
0230:                }
0231:            }
0232:
0233:            /** The OptionListener for COMPILER_ERROR_COLOR. */
0234:            private class ErrorColorOptionListener implements 
0235:                    OptionListener<Color> {
0236:                public void optionChanged(OptionEvent<Color> oce) {
0237:                    ERROR_PAINTER = new ReverseHighlighter.DrJavaHighlightPainter(
0238:                            oce.value);
0239:                    if (_errorHighlightTag != null) {
0240:                        int start = _errorHighlightTag.getStartOffset();
0241:                        int end = _errorHighlightTag.getEndOffset();
0242:                        _errorHighlightTag.remove();
0243:                        addErrorHighlight(start, end);
0244:                    }
0245:                }
0246:            }
0247:
0248:            /** The OptionListener for BOOKMARK_COLOR. */
0249:            private class BookmarkColorOptionListener implements 
0250:                    OptionListener<Color> {
0251:                public void optionChanged(OptionEvent<Color> oce) {
0252:                    BOOKMARK_PAINTER = new ReverseHighlighter.DefaultUnderlineHighlightPainter(
0253:                            oce.value, BOOKMARK_PAINTER.getThickness());
0254:                    _mainFrame.refreshBookmarkHighlightPainter();
0255:                }
0256:            }
0257:
0258:            /** The OptionListener for FIND_RESULTS_COLOR. */
0259:            private class FindResultsColorOptionListener implements 
0260:                    OptionListener<Color> {
0261:                private int _index;
0262:
0263:                public FindResultsColorOptionListener(int i) {
0264:                    _index = i;
0265:                }
0266:
0267:                public void optionChanged(OptionEvent<Color> oce) {
0268:                    FIND_RESULTS_PAINTERS[_index] = new ReverseHighlighter.DefaultUnderlineHighlightPainter(
0269:                            oce.value, FIND_RESULTS_PAINTERS[_index]
0270:                                    .getThickness());
0271:                }
0272:            }
0273:
0274:            /** The OptionListener for DEBUG_BREAKPOINT_COLOR. */
0275:            private class BreakpointColorOptionListener implements 
0276:                    OptionListener<Color> {
0277:                public void optionChanged(OptionEvent<Color> oce) {
0278:                    BREAKPOINT_PAINTER = new ReverseHighlighter.DrJavaHighlightPainter(
0279:                            oce.value);
0280:                    _mainFrame.refreshBreakpointHighlightPainter();
0281:                }
0282:            }
0283:
0284:            /** The OptionListener for DEBUG_BREAKPOINT_DISABLED_COLOR. */
0285:            private class DisabledBreakpointColorOptionListener implements 
0286:                    OptionListener<Color> {
0287:                public void optionChanged(OptionEvent<Color> oce) {
0288:                    DISABLED_BREAKPOINT_PAINTER = new ReverseHighlighter.DrJavaHighlightPainter(
0289:                            oce.value);
0290:                    _mainFrame.refreshBreakpointHighlightPainter();
0291:                }
0292:            }
0293:
0294:            /** The OptionListener for DEBUG_THREAD_COLOR. */
0295:            private static class ThreadColorOptionListener implements 
0296:                    OptionListener<Color> {
0297:                public void optionChanged(OptionEvent<Color> oce) {
0298:                    THREAD_PAINTER = new ReverseHighlighter.DrJavaHighlightPainter(
0299:                            oce.value);
0300:                }
0301:            }
0302:
0303:            /** The OptionListener for TEXT_ANTIALIAS. */
0304:            private class AntiAliasOptionListener implements 
0305:                    OptionListener<Boolean> {
0306:                public void optionChanged(OptionEvent<Boolean> oce) {
0307:                    _antiAliasText = oce.value.booleanValue();
0308:                    DefinitionsPane.this .repaint();
0309:                }
0310:            }
0311:
0312:            /** Listens to any undoable events in the document, and adds them to the undo manager.  Must be done in the view 
0313:             * because the edits are stored along with the caret position at the time of the edit.
0314:             */
0315:            private final UndoableEditListener _undoListener = new UndoableEditListener() {
0316:
0317:                /** The function to handle what happens when an UndoableEditEvent occurs.
0318:                 *  @param e
0319:                 */
0320:                public void undoableEditHappened(UndoableEditEvent e) {
0321:                    UndoWithPosition undo = new UndoWithPosition(e.getEdit(),
0322:                            getCaretPosition());
0323:                    if (!_inCompoundEdit) {
0324:                        CompoundUndoManager undoMan = _doc.getUndoManager();
0325:                        _inCompoundEdit = true;
0326:                        _compoundEditKey = undoMan.startCompoundEdit();
0327:                        getUndoAction().updateUndoState();
0328:                        getRedoAction().updateRedoState();
0329:                    }
0330:                    _doc.getUndoManager().addEdit(undo);
0331:                    getRedoAction().setEnabled(false);
0332:                }
0333:            };
0334:
0335:            /** The menu item for the "Toggle Breakpoint" option. Stored in field so that it may be enabled and
0336:             *  disabled depending on Debug Mode.
0337:             */
0338:            private volatile JMenuItem _toggleBreakpointMenuItem;
0339:
0340:            //  /** The menu item for the "Add Watch" option. Stored in field so that it may be enabled and
0341:            //   *  disabled depending on Debug Mode.
0342:            //   */
0343:            //  private JMenuItem _addWatchMenuItem;
0344:
0345:            /** The contextual popup menu for the Definitions Pane. */
0346:            private volatile JPopupMenu _popMenu;
0347:
0348:            /** The mouse adapter for handling a popup menu. */
0349:            private volatile PopupMenuMouseAdapter _popupMenuMA;
0350:
0351:            /** Listens to caret to highlight errors as appropriate. */
0352:            private volatile ErrorCaretListener _errorListener;
0353:
0354:            private volatile ActionListener _setSizeListener = null;
0355:
0356:            /** An action to handle indentation spawned by pressing the tab key. */
0357:            private class IndentKeyActionTab extends AbstractAction {
0358:
0359:                /** Handle the key typed event from the text field. */
0360:                public void actionPerformed(ActionEvent e) {
0361:                    // The following commented out code was moved into the indent() method
0362:                    //int pos = getCaretPosition();
0363:                    //_doc().setCurrentLocation(pos);
0364:                    indent();
0365:                }
0366:            }
0367:
0368:            /** Used for indent action spawned by pressing the enter key, '{', or '}'. */
0369:            private class IndentKeyAction extends AbstractAction {
0370:
0371:                /** The key string ("\n"|"{"|"}") for the key pressed that invokes this
0372:                 *  instance. Not used currently, but there for readability and possible
0373:                 *  future use, e.g., debugging add-ons or the rewrite of the indention code.
0374:                 */
0375:                private final String _key;
0376:
0377:                /** The default action to take when the specified key is pressed. */
0378:                private final Action _defaultAction;
0379:
0380:                /** Whether to perform the indent if the caret is in a String or comment. */
0381:                private final boolean _indentNonCode;
0382:
0383:                /** Creates an IndentKeyAction which only invokes indent if the caret is in code, and not Strings or 
0384:                 *  comments.
0385:                 */
0386:                IndentKeyAction(String key, Action defaultAction) {
0387:                    this (key, defaultAction, false);
0388:                }
0389:
0390:                /** Creates a new IndentKeyAction with the specified parameters.
0391:                 *  @param key name of the key, for debugging purposes
0392:                 *  @param defaultAction action to perform in addition to indenting
0393:                 *  @param indentNonCode whether to indent Strings and comments
0394:                 */
0395:                IndentKeyAction(String key, Action defaultAction,
0396:                        boolean indentNonCode) {
0397:                    _key = key;
0398:                    _defaultAction = defaultAction;
0399:                    _indentNonCode = indentNonCode;
0400:                }
0401:
0402:                /** This method tells what the reason should be for spawning this indent event
0403:                 *  Defaults to Indenter.IndentReason.OTHER
0404:                 */
0405:                protected Indenter.IndentReason getIndentReason() {
0406:                    return Indenter.IndentReason.OTHER;
0407:                }
0408:
0409:                /** Handle the "key typed" event from the text field. Calls the default action to make sure the right things
0410:                 *  happen, then makes a call to indentLine().
0411:                 */
0412:                public void actionPerformed(ActionEvent e) {
0413:                    _defaultAction.actionPerformed(e);
0414:
0415:                    // Only indent if in code
0416:
0417:                    _doc.setCurrentLocation(getCaretPosition());
0418:                    ReducedModelState state = _doc.getStateAtCurrent();
0419:                    if (state.equals(ReducedModelState.FREE) || _indentNonCode)
0420:                        indent(getIndentReason());
0421:                }
0422:            }
0423:
0424:            /** Special action to take care of case when tab key is pressed. */
0425:            private volatile Action _indentKeyActionTab = new IndentKeyActionTab();
0426:
0427:            /** Because the "default" action for the enter key is special, it must be
0428:             *  grabbed from the Keymap using getAction(KeyStroke), which returns the
0429:             *  "default" action for all keys which have behavior extending beyond
0430:             *  regular text keys.
0431:             */
0432:            private final Action _indentKeyActionLine = new IndentKeyAction(
0433:                    "\n", (Action) getActionForKeyStroke(KeyStroke
0434:                            .getKeyStroke(KeyEvent.VK_ENTER, 0)), true /* indent non-code, too */) {
0435:                /* overriding this method is important so that pressing the enter key causes
0436:                 * different indentation than pressing other keys, for bug 681203
0437:                 */
0438:                protected Indenter.IndentReason getIndentReason() {
0439:                    return Indenter.IndentReason.ENTER_KEY_PRESS;
0440:                }
0441:            };
0442:
0443:            /** Likewise, regular text keys like '{', '}', and ':' do not have special actions that are returned by 
0444:             *  getAction(KeyStroke). To make sure these behave right, we use getDefaultAction() instead.
0445:             */
0446:            private final Action _indentKeyActionSquiggly = new IndentKeyAction(
0447:                    "}", getKeymap().getDefaultAction());
0448:            private final Action _indentKeyActionOpenSquiggly = new IndentKeyAction(
0449:                    "{", getKeymap().getDefaultAction());
0450:            private final Action _indentKeyActionColon = new IndentKeyAction(
0451:                    ":", getKeymap().getDefaultAction());
0452:
0453:            /** Tells us whether we currently are in the middle of a CompoundEdit for regular keystrokes.
0454:             *  Helps us with granular undo.
0455:             */
0456:            private volatile boolean _inCompoundEdit = false;
0457:            private volatile int _compoundEditKey;
0458:
0459:            /** Our keymap containing key bindings.  Takes precedence over the default map. */
0460:            final Keymap ourMap;
0461:
0462:            /** Standard Constructor.  Sets up all the defaults.
0463:             *  @param mf the parent window
0464:             */
0465:            public DefinitionsPane(MainFrame mf,
0466:                    final OpenDefinitionsDocument doc) {
0467:                super (new SwingDocument());
0468:
0469:                _mainFrame = mf;
0470:
0471:                addFocusListener(new FocusAdapter() {
0472:                    public void focusGained(FocusEvent e) {
0473:                        _mainFrame.getModel().getDocumentNavigator()
0474:                                .requestSelectionUpdate(doc);
0475:                    }
0476:                });
0477:
0478:                _doc = doc; // NOTE: _doc is final
0479:
0480:                // read the initial selection/scrolling values from the document
0481:                // to be set when the pane is first notified active
0482:                _selStart = _doc.getInitialSelectionStart();
0483:                _selEnd = _doc.getInitialSelectionEnd();
0484:                _savedVScroll = _doc.getInitialVerticalScroll();
0485:                _savedHScroll = _doc.getInitialHorizontalScroll();
0486:
0487:                //super.setDocument(NULL_DOCUMENT);
0488:                _resetUndo();
0489:
0490:                Font mainFont = DrJava.getConfig().getSetting(FONT_MAIN);
0491:                setFont(mainFont);
0492:
0493:                setEditable(true);
0494:
0495:                // add actions for indent key
0496:                ourMap = addKeymap(INDENT_KEYMAP_NAME, getKeymap());
0497:                ourMap.addActionForKeyStroke(KeyStroke.getKeyStroke(
0498:                        KeyEvent.VK_ENTER, 0), _indentKeyActionLine);
0499:                ourMap.addActionForKeyStroke(KeyStroke.getKeyStroke(
0500:                        KeyEvent.VK_TAB, 0), _indentKeyActionTab);
0501:                ourMap.addActionForKeyStroke(KeyStroke.getKeyStroke('}'),
0502:                        _indentKeyActionSquiggly);
0503:                ourMap.addActionForKeyStroke(KeyStroke.getKeyStroke('{'),
0504:                        _indentKeyActionOpenSquiggly);
0505:                ourMap.addActionForKeyStroke(KeyStroke.getKeyStroke(':'),
0506:                        _indentKeyActionColon);
0507:                setKeymap(ourMap);
0508:
0509:                //    Keymap map = ourMap;
0510:                //    KeyStroke[] ks;
0511:                //     ks = ourMap.getBoundKeyStrokes();
0512:                //     for (KeyStroke k:ks) {
0513:                //       System.out.println(k);
0514:                //     }
0515:                //     ourMap = ourMap.getResolveParent();
0516:                //     ks = ourMap.getBoundKeyStrokes();
0517:                //     for (KeyStroke k:ks) {
0518:                //       System.out.println(k);
0519:                //     }
0520:
0521:                //    this.setEditorKit(new StyledEditorKit());
0522:
0523:                _antiAliasText = DrJava.getConfig().getSetting(TEXT_ANTIALIAS)
0524:                        .booleanValue();
0525:
0526:                OptionListener<Color> temp;
0527:                Pair<Option<Color>, OptionListener<Color>> pair;
0528:
0529:                // Setup the color listeners. NOTE: the Foreground/Background listeners add themselves to DrJava.getConfig() 
0530:                // in their own constructors. Rather than refactor it, we decided to work with that design decision.
0531:                temp = new ForegroundColorListener(this );
0532:                pair = new Pair<Option<Color>, OptionListener<Color>>(
0533:                        OptionConstants.DEFINITIONS_NORMAL_COLOR, temp);
0534:                _colorOptionListeners.add(pair);
0535:
0536:                temp = new BackgroundColorListener(this );
0537:                pair = new Pair<Option<Color>, OptionListener<Color>>(
0538:                        OptionConstants.DEFINITIONS_BACKGROUND_COLOR, temp);
0539:                _colorOptionListeners.add(pair);
0540:
0541:                // These listeners do not register themselves in their own constructors.  We do.
0542:                temp = new MatchColorOptionListener();
0543:                pair = new Pair<Option<Color>, OptionListener<Color>>(
0544:                        OptionConstants.DEFINITIONS_MATCH_COLOR, temp);
0545:                _colorOptionListeners.add(pair);
0546:                DrJava.getConfig().addOptionListener(
0547:                        OptionConstants.DEFINITIONS_MATCH_COLOR, temp);
0548:
0549:                temp = new ErrorColorOptionListener();
0550:                pair = new Pair<Option<Color>, OptionListener<Color>>(
0551:                        OptionConstants.COMPILER_ERROR_COLOR, temp);
0552:                _colorOptionListeners.add(pair);
0553:                DrJava.getConfig().addOptionListener(
0554:                        OptionConstants.COMPILER_ERROR_COLOR, temp);
0555:
0556:                temp = new BookmarkColorOptionListener();
0557:                pair = new Pair<Option<Color>, OptionListener<Color>>(
0558:                        OptionConstants.BOOKMARK_COLOR, temp);
0559:                _colorOptionListeners.add(pair);
0560:                DrJava.getConfig().addOptionListener(
0561:                        OptionConstants.BOOKMARK_COLOR, temp);
0562:
0563:                for (int i = 0; i < FIND_RESULTS_COLORS.length; ++i) {
0564:                    temp = new FindResultsColorOptionListener(i);
0565:                    pair = new Pair<Option<Color>, OptionListener<Color>>(
0566:                            OptionConstants.FIND_RESULTS_COLORS[i], temp);
0567:                    _colorOptionListeners.add(pair);
0568:                    DrJava.getConfig().addOptionListener(
0569:                            OptionConstants.FIND_RESULTS_COLORS[i], temp);
0570:                }
0571:
0572:                temp = new BreakpointColorOptionListener();
0573:                pair = new Pair<Option<Color>, OptionListener<Color>>(
0574:                        OptionConstants.DEBUG_BREAKPOINT_COLOR, temp);
0575:                _colorOptionListeners.add(pair);
0576:                DrJava.getConfig().addOptionListener(
0577:                        OptionConstants.DEBUG_BREAKPOINT_COLOR, temp);
0578:
0579:                temp = new DisabledBreakpointColorOptionListener();
0580:                pair = new Pair<Option<Color>, OptionListener<Color>>(
0581:                        OptionConstants.DEBUG_BREAKPOINT_DISABLED_COLOR, temp);
0582:                _colorOptionListeners.add(pair);
0583:                DrJava.getConfig().addOptionListener(
0584:                        OptionConstants.DEBUG_BREAKPOINT_DISABLED_COLOR, temp);
0585:
0586:                temp = new ThreadColorOptionListener();
0587:                pair = new Pair<Option<Color>, OptionListener<Color>>(
0588:                        OptionConstants.DEBUG_THREAD_COLOR, temp);
0589:                _colorOptionListeners.add(pair);
0590:                DrJava.getConfig().addOptionListener(
0591:                        OptionConstants.DEBUG_THREAD_COLOR, temp);
0592:
0593:                OptionListener<Boolean> aaTemp = new AntiAliasOptionListener();
0594:                Pair<Option<Boolean>, OptionListener<Boolean>> aaPair = new Pair<Option<Boolean>, OptionListener<Boolean>>(
0595:                        OptionConstants.TEXT_ANTIALIAS, aaTemp);
0596:                _booleanOptionListeners.add(aaPair);
0597:                DrJava.getConfig().addOptionListener(
0598:                        OptionConstants.TEXT_ANTIALIAS, aaTemp);
0599:
0600:                createPopupMenu();
0601:
0602:                //Add listener to components that can bring up popup menus.
0603:                _popupMenuMA = new PopupMenuMouseAdapter();
0604:                this .addMouseListener(_popupMenuMA);
0605:                this .setHighlighter(new ReverseHighlighter());
0606:                _highlightManager = new HighlightManager(this );
0607:
0608:                int rate = this .getCaret().getBlinkRate();
0609:                // Change the caret to one that doesn't remove selection highlighting when focus is lost.
0610:                // Fixes bug #788295 "No highlight when find/replace switches docs".
0611:                this .setCaret(new DefaultCaret() {
0612:                    public void focusLost(FocusEvent e) {
0613:                        setVisible(false);
0614:                    }
0615:                });
0616:                this .getCaret().setBlinkRate(rate);
0617:                //    Utilities.showDebug("DP constructor finished");    
0618:            }
0619:
0620:            /** Ends a compound edit.*/
0621:            public void endCompoundEdit() {
0622:                if (_inCompoundEdit) {
0623:                    CompoundUndoManager undoMan = _doc.getUndoManager();
0624:                    _inCompoundEdit = false;
0625:                    undoMan.endCompoundEdit(_compoundEditKey);
0626:                }
0627:            }
0628:
0629:            /** Takes in any keyboard input, checks to see if it is in the keyToActionMap in KeybindingManager, if so 
0630:             * executes the action, otherwise checks if it contains the current platform's menu shortcut modifier and 
0631:             * if so, ignores that command (this disallows the execution of the UI's default actions such as 
0632:             * cut/copy/paste/select all), otherwise does whatever normally would be done.
0633:             */
0634:            public void processKeyEvent(KeyEvent e) {
0635:                if (_mainFrame.getAllowKeyEvents()) {
0636:                    KeyStroke ks = KeyStroke.getKeyStrokeForEvent(e);
0637:                    Action a = KeyBindingManager.Singleton.get(ks);
0638:                    // Don't perform the action if the keystroke is NULL_KEYSTROKE (generated by some Windows keys)
0639:                    if ((ks != KeyStrokeOption.NULL_KEYSTROKE) && (a != null)) {
0640:                        //        System.out.println("Keystroke was null");
0641:                        endCompoundEdit();
0642:                        // Performs the action a
0643:                        SwingUtilities.notifyAction(a, ks, e, e.getSource(), e
0644:                                .getModifiers());
0645:
0646:                        // Make sure we don't consume it again
0647:                        e.consume();
0648:                    } else {
0649:                        // Allows one step undoing of the keystrokes defined on the keymap (e.g. enter, tab, '{', '}', ':').
0650:                        Keymap km = getKeymap();
0651:
0652:                        if (km.isLocallyDefined(ks)
0653:                                || km.isLocallyDefined(KeyStroke
0654:                                        .getKeyStroke(ks.getKeyChar()))) {
0655:                            // We're breaking up compound edits at the granularity of "enter"'s.
0656:                            if (e.getKeyCode() == KeyEvent.VK_ENTER)
0657:                                endCompoundEdit();
0658:
0659:                            CompoundUndoManager undoMan = _doc.getUndoManager();
0660:                            //          int key = undoMan.startCompoundEdit();
0661:                            //          System.out.println("supering 1 " + isAltF4);
0662:
0663:                            super .processKeyEvent(e);
0664:                            // We call endCompoundEdit() here because one will automatically start when processKeyEvent finishes 
0665:                            // (see the definition of _undoListener).
0666:                            endCompoundEdit();
0667:                            //          undoMan.endCompoundEdit(key); //commented out because of frenchkeyboard fix
0668:                            //          e.consume();
0669:                        } else {
0670:
0671:                            // The following conditional fixes bug #676586 by ignoring typed events when the meta key is down and fixes
0672:                            // bug #905405 "Undo Alt+Anything Causes Exception" by ignoring typed events when the alt key is down.
0673:                            // NOTE: no longer need to check for alt since we now only start a new compound edit if an undoable edit 
0674:                            // actually happened.
0675:                            if ((e.getModifiers() & InputEvent.META_MASK) != 0
0676:                            // || ((e.getModifiers() & InputEvent.ALT_MASK) != 0)) // omitted for frenchkeyboard support
0677:                                    && e.getKeyCode() == KeyEvent.VK_UNDEFINED) {
0678:
0679:                                //            System.out.println("not supering 1 " + isAltF4);
0680:                                return;
0681:                            }
0682:
0683:                            // The following conditional fixes ease of use issue 693253 by checking if a typed event is
0684:                            // shift-delete or shift-backspace and then performing a delete or backspace operation,
0685:                            // respectively
0686:                            if ((e.getModifiers() & InputEvent.SHIFT_MASK) != 0) {
0687:                                int newModifiers = e.getModifiers()
0688:                                        & ~(InputEvent.SHIFT_MASK);
0689:
0690:                                KeyStroke newKs = KeyStroke.getKeyStroke(ks
0691:                                        .getKeyCode(), newModifiers, ks
0692:                                        .isOnKeyRelease());
0693:                                String name = KeyBindingManager.Singleton
0694:                                        .getName(newKs);
0695:
0696:                                if (name != null
0697:                                        && (name.equals("Delete Previous") || name
0698:                                                .equals("Delete Next"))) {
0699:                                    endCompoundEdit();
0700:                                    // We are unsure about the third and fourth arguments (e and e.getSource()); we simply
0701:                                    // reuse the original values
0702:                                    SwingUtilities.notifyAction(
0703:                                            KeyBindingManager.Singleton
0704:                                                    .get(newKs), newKs, e, e
0705:                                                    .getSource(), newModifiers);
0706:                                    e.consume();
0707:                                    //            System.out.println("not supering 2 " + isAltF4);
0708:                                    return;
0709:                                }
0710:                            }
0711:
0712:                            /* If the KeyEvent is not a pressed event, process it before we do granular undo or _inCompoundEdit may 
0713:                             * get set incorrectly. This code breaks Alt-F4, and may break other system keybindings since the event 
0714:                             * is consumed by us. */
0715:                            if (e.getID() != KeyEvent.KEY_TYPED) {
0716:                                super .processKeyEvent(e);
0717:                                return;
0718:                            }
0719:                        }
0720:                        // This if statement is for tests only
0721:                        if ((e.getModifiers() & InputEvent.ALT_MASK) != 0)
0722:                            testVariable = true; // ALT_MASK actually pressed
0723:                        else
0724:                            testVariable = false;
0725:
0726:                        super .processKeyEvent(e);
0727:                    }
0728:                }
0729:            }
0730:
0731:            /** Sets the editor kit that will be used by all DefinitionsPanes.
0732:             *  @param editorKit The editor kit to use for new DefinitionsPanes.
0733:             */
0734:            public static void setEditorKit(DefinitionsEditorKit editorKit) {
0735:                EDITOR_KIT = editorKit;
0736:            }
0737:
0738:            /** Enable anti-aliased text by overriding paintComponent. */
0739:            protected void paintComponent(Graphics g) {
0740:                if (_antiAliasText && g instanceof  Graphics2D) {
0741:                    Graphics2D g2d = (Graphics2D) g;
0742:                    g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
0743:                            RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
0744:                }
0745:                super .paintComponent(g);
0746:            }
0747:
0748:            /** Creates the popup menu for the DefinitionsPane. */
0749:            private void createPopupMenu() {
0750:                // Create the popup menu.
0751:                _popMenu = new JPopupMenu();
0752:
0753:                _popMenu.add(_mainFrame.cutAction);
0754:                _popMenu.add(_mainFrame.copyAction);
0755:                _popMenu.add(_mainFrame.pasteAction);
0756:                _popMenu.addSeparator();
0757:
0758:                JMenuItem indentItem = new JMenuItem("Indent Line(s)");
0759:                indentItem.addActionListener(new AbstractAction() {
0760:                    public void actionPerformed(ActionEvent ae) {
0761:                        indent();
0762:                    }
0763:                });
0764:                _popMenu.add(indentItem);
0765:
0766:                JMenuItem commentLinesItem = new JMenuItem("Comment Line(s)");
0767:                commentLinesItem.addActionListener(new AbstractAction() {
0768:                    public void actionPerformed(ActionEvent ae) {
0769:                        _mainFrame.hourglassOn();
0770:                        try {
0771:                            _doc.setCurrentLocation(getCaretPosition());
0772:                            _commentLines();
0773:                        } finally {
0774:                            _mainFrame.hourglassOff();
0775:                        }
0776:                    }
0777:                });
0778:                _popMenu.add(commentLinesItem);
0779:
0780:                JMenuItem uncommentLinesItem = new JMenuItem(
0781:                        "Uncomment Line(s)");
0782:                uncommentLinesItem.addActionListener(new AbstractAction() {
0783:                    public void actionPerformed(ActionEvent ae) {
0784:                        _doc.setCurrentLocation(getCaretPosition());
0785:                        _uncommentLines();
0786:                    }
0787:                });
0788:                _popMenu.add(uncommentLinesItem);
0789:
0790:                /* Go to this file... */
0791:                _popMenu.addSeparator();
0792:                JMenuItem gotoFileUnderCursorItem = new JMenuItem(
0793:                        "Go to File Under Cursor");
0794:                gotoFileUnderCursorItem.addActionListener(new AbstractAction() {
0795:                    public void actionPerformed(ActionEvent ae) {
0796:                        _doc.setCurrentLocation(getCaretPosition());
0797:                        _mainFrame._gotoFileUnderCursor();
0798:                    }
0799:                });
0800:                _popMenu.add(gotoFileUnderCursorItem);
0801:
0802:                /* Toggle bookmark */
0803:                JMenuItem toggleBookmarkItem = new JMenuItem("Toggle Bookmark");
0804:                toggleBookmarkItem.addActionListener(new AbstractAction() {
0805:                    /** Toggle the selected line as a bookmark.  Only runs in event thread. */
0806:                    public void actionPerformed(ActionEvent ae) {
0807:                        if (getSelectionStart() == getSelectionEnd()) { // nothing selected
0808:                            // Make sure that the breakpoint is set on the *clicked* line, if within a selection block.
0809:                            // Omit locking since Defintions documents are not accessed from other threads (?)
0810:                            //          _doc.acquireReadLock();
0811:                            //          try { 
0812:                            setCaretPosition(viewToModel(_popupMenuMA
0813:                                    .getLastMouseClick().getPoint()));
0814:                            _mainFrame.toggleBookmark();
0815:                            //          }
0816:                            //          finally {_doc.releaseReadLock(); }
0817:                        }
0818:                    }
0819:                });
0820:                _popMenu.add(toggleBookmarkItem);
0821:
0822:                if (_mainFrame.getModel().getDebugger().isAvailable()) {
0823:                    _popMenu.addSeparator();
0824:
0825:                    // Breakpoint
0826:                    JMenuItem breakpointItem = new JMenuItem(
0827:                            "Toggle Breakpoint");
0828:                    breakpointItem.addActionListener(new AbstractAction() {
0829:                        public void actionPerformed(ActionEvent ae) {
0830:                            // Make sure that the breakpoint is set on the *clicked* line, if within a selection block.
0831:                            // Omit locking since Defintions documents are not accessed from other threads (?)
0832:                            //          _doc.acquireReadLock();
0833:                            //          try { 
0834:                            setCaretPosition(viewToModel(_popupMenuMA
0835:                                    .getLastMouseClick().getPoint()));
0836:                            _mainFrame.debuggerToggleBreakpoint();
0837:                            //          }
0838:                            //          finally
0839:                        }
0840:                    });
0841:                    _toggleBreakpointMenuItem = _popMenu.add(breakpointItem);
0842:                }
0843:            }
0844:
0845:            /* The private MouseAdapter for responding to various clicks concerning the popup menu */
0846:            private class PopupMenuMouseAdapter extends RightClickMouseAdapter {
0847:
0848:                private MouseEvent _lastMouseClick = null;
0849:
0850:                public void mousePressed(MouseEvent e) {
0851:                    super .mousePressed(e);
0852:
0853:                    _lastMouseClick = e;
0854:                    endCompoundEdit();
0855:
0856:                    // if not in the selected area,
0857:                    /*if ((viewToModel(e.getPoint()) < getSelectionStart()) ||
0858:                        (viewToModel(e.getPoint()) > getSelectionEnd()) ) {
0859:                      //move caret to clicked position, deselecting previous selection
0860:                      setCaretPosition(viewToModel(e.getPoint()));
0861:                    }*/
0862:                }
0863:
0864:                protected void _popupAction(MouseEvent e) {
0865:                    requestFocusInWindow();
0866:                    _popMenu.show(e.getComponent(), e.getX(), e.getY());
0867:                }
0868:
0869:                public MouseEvent getLastMouseClick() {
0870:                    return _lastMouseClick;
0871:                }
0872:            }
0873:
0874:            /** Comments out the lines contained within the given selection. */
0875:            private void _commentLines() {
0876:                _mainFrame.commentLines();
0877:                //    _doc.commentLinesInDefinitions(getSelectionStart(), getSelectionEnd());
0878:            }
0879:
0880:            /** Uncomments the lines contained within the given selection. */
0881:            private void _uncommentLines() {
0882:                _mainFrame.uncommentLines();
0883:                //    _doc.uncommentLinesInDefinitions(getSelectionStart(), getSelectionEnd()); 
0884:            }
0885:
0886:            /** @return the undo action. */
0887:            public UndoAction getUndoAction() {
0888:                return _undoAction;
0889:            }
0890:
0891:            /** @return the redo action. */
0892:            public RedoAction getRedoAction() {
0893:                return _redoAction;
0894:            }
0895:
0896:            /** Get the OpenDefinitionsDocument contained in this DefinitionsPane. */
0897:            public OpenDefinitionsDocument getOpenDefDocument() {
0898:                return _doc;
0899:            }
0900:
0901:            /** Get the DJDocument (OpenDefinitionsDocument) contained in this pane.
0902:             *  Required by the super class AbstractDJPane.
0903:             */
0904:            public DJDocument getDJDocument() {
0905:                return _doc;
0906:            }
0907:
0908:            /** Access to the pane's HighlightManager */
0909:            public HighlightManager getHighlightManager() {
0910:                return _highlightManager;
0911:            }
0912:
0913:            /** Set the caret position and also scroll to make sure the location is visible.  Should only run in the event
0914:             * thread.  
0915:             *  @param pos Location to scroll to.
0916:             */
0917:            public void setPositionAndScroll(int pos) {
0918:                assert EventQueue.isDispatchThread();
0919:                try {
0920:                    setCaretPos(pos);
0921:                    scrollRectToVisible(modelToView(pos));
0922:                } catch (BadLocationException ble) {
0923:                    throw new UnexpectedException(ble);
0924:                }
0925:            }
0926:
0927:            /** Override JEditorPane's setDocument to make sure only the Document in our final OpenDefinitionsDocument 
0928:             *  can be used.
0929:             */
0930:            public void setDocument(Document d) {
0931:                if (_doc != null) { // When can _doc be null?
0932:                    if ((d == null) || (!d.equals(_doc))) {
0933:                        throw new IllegalStateException(
0934:                                "Cannot set the document of a DefinitionsPane to a different document.");
0935:                    }
0936:                }
0937:                super .setDocument(d); // If _doc is null should we do this?
0938:            }
0939:
0940:            public boolean checkAltKey() { // For tests only
0941:                return testVariable;
0942:            }
0943:
0944:            /** Add a ErrorCaretListener to this pane, keeping it accessible so its error model can be updated later. */
0945:            public void addErrorCaretListener(ErrorCaretListener listener) {
0946:                _errorListener = listener;
0947:                addCaretListener(listener);
0948:            }
0949:
0950:            /** Gets the ErrorCaretListener for this pane. */
0951:            public ErrorCaretListener getErrorCaretListener() {
0952:                return _errorListener;
0953:            }
0954:
0955:            /** Switches the location of the error highlight in the document if there was one. Otherwise adds the 
0956:             *  highlight. The invariant is that there are zero or one error highlights at any time.
0957:             */
0958:            public void addErrorHighlight(int from, int to) {
0959:                removeErrorHighlight();
0960:                _errorHighlightTag = _highlightManager.addHighlight(from, to,
0961:                        ERROR_PAINTER);
0962:            }
0963:
0964:            /** Removes the previous compiler error highlight from the document after the cursor has moved. */
0965:            public void removeErrorHighlight() {
0966:                if (_errorHighlightTag != null) {
0967:                    _errorHighlightTag.remove();
0968:                    _errorHighlightTag = null;
0969:                }
0970:            }
0971:
0972:            public boolean hasWarnedAboutModified() {
0973:                return _hasWarnedAboutModified;
0974:            }
0975:
0976:            public void hasWarnedAboutModified(boolean hasWarned) {
0977:                _hasWarnedAboutModified = hasWarned;
0978:            }
0979:
0980:            public void addBreakpointHighlight(Breakpoint bp) {
0981:            }
0982:
0983:            public void removeBreakpointHighlight(Breakpoint bp) {
0984:            }
0985:
0986:            /** This instance of the scroll pane is here in order to allow for the definitions pane to save the
0987:             *  horizontal and vertical scroll
0988:             */
0989:            private volatile JScrollPane _scrollPane;
0990:
0991:            public void setScrollPane(JScrollPane s) {
0992:                _scrollPane = s;
0993:            }
0994:
0995:            /** Used to save the caret position, selection, and scroll when setting the definitions pane to be inactive */
0996:            private volatile int _savedVScroll;
0997:            private volatile int _savedHScroll;
0998:            private volatile int _position;
0999:            private volatile int _selStart;
1000:            private volatile int _selEnd;
1001:
1002:            /** This function is called when the active document is changed. this function is called on the pane that is 
1003:             * replaced by the new active pane. It allows the pane to "shutdown" when not in use.  Currently, this procedure 
1004:             *  replaces the Definitions Document with a blank dummy document to help conserve memory (so that the pane will 
1005:             *  not be holding onto the last reference of a definitions document not allowing it to be garbage collected)
1006:             */
1007:            public void notifyInactive() {
1008:                // we catch a NoSuchDocumentException here because during a close/closeAll
1009:                // the model closes the definitions document before the MainFrame switches
1010:                // out the panes.  If this is the case, then the following code does not
1011:                // need to be run.
1012:                try {
1013:                    // Sync caret with location before switching
1014:                    getOpenDefDocument().setCurrentLocation(getCaretPosition());
1015:
1016:                    // Remove any error highlighting in the old def pane
1017:                    removeErrorHighlight();
1018:
1019:                    _position = _doc.getCurrentLocation();
1020:                    _selStart = getSelectionStart();
1021:                    _selEnd = getSelectionEnd();
1022:
1023:                    _savedVScroll = _scrollPane.getVerticalScrollBar()
1024:                            .getValue();
1025:                    _savedHScroll = _scrollPane.getHorizontalScrollBar()
1026:                            .getValue();
1027:
1028:                    super .setDocument(NULL_DOCUMENT);
1029:                } catch (NoSuchDocumentException e) {
1030:                    // This exception was just thrown because the document was just 
1031:                    // closed and so this pane will soon be garbage collected.  
1032:                    // We don't need to do any more cleanup.
1033:                }
1034:            }
1035:
1036:            /** This function is called when switching a pane to be the active document pane.  It allows the pane to do whatever 
1037:             * "startUp" is required.  Since setInactive swapped out the document for a dummy document, we need to reload the 
1038:             * actual document and reset its caret position to the saved location.  Only runs in event thread.
1039:             */
1040:            public void notifyActive() {
1041:                assert !_mainFrame.isVisible() || EventQueue.isDispatchThread();
1042:                super .setDocument(_doc);
1043:                if (_doc.getUndoableEditListeners().length == 0)
1044:                    _resetUndo();
1045:
1046:                _doc.acquireWriteLock();
1047:                int len = _doc.getLength();
1048:                if (len < _position || len < _selEnd) {
1049:                    // the document changed since we're set inactive
1050:                    //so set selection to be none
1051:                    _position = len;
1052:                    _selStart = len;
1053:                    _selEnd = len;
1054:                }
1055:                try {
1056:                    if (_position == _selStart) {
1057:                        setCaretPosition(_selEnd);
1058:                        moveCaretPosition(_selStart);
1059:                        _doc.setCurrentLocation(_selStart);
1060:                    } else {
1061:                        setCaretPosition(_selStart);
1062:                        moveCaretPosition(_selEnd);
1063:                        _doc.setCurrentLocation(_selEnd);
1064:                    }
1065:                } finally {
1066:                    _doc.releaseWriteLock();
1067:                }
1068:                _scrollPane.getVerticalScrollBar().setValue(_savedVScroll);
1069:                _scrollPane.getHorizontalScrollBar().setValue(_savedHScroll);
1070:                // Explicitly set scrollbar policies fixing bug #1445898 
1071:                _scrollPane
1072:                        .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
1073:                _scrollPane
1074:                        .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
1075:            }
1076:
1077:            public int getVerticalScroll() {
1078:                if (getDocument() == NULL_DOCUMENT)
1079:                    return _savedVScroll;
1080:                else
1081:                    return _scrollPane.getVerticalScrollBar().getValue();
1082:            }
1083:
1084:            public int getHorizontalScroll() {
1085:                if (getDocument() == NULL_DOCUMENT)
1086:                    return _savedHScroll;
1087:                else
1088:                    return _scrollPane.getHorizontalScrollBar().getValue();
1089:            }
1090:
1091:            /** Returns the current line of the definitions pane. This is a 1-based number.
1092:             * @return current line of the definitions pane, >=1 */
1093:            public int getCurrentLine() {
1094:                return _doc.getLineOfOffset(getCaretPosition()) + 1;
1095:            }
1096:
1097:            //    try {
1098:            //      int pos = getCaretPosition();
1099:            //      FontMetrics metrics = getFontMetrics(getFont());
1100:            //      Rectangle startRect = modelToView(pos);
1101:            //      if (startRect == null) return 1;
1102:            //      //top left position is (3,3), so font size<=6 will be off
1103:            //      return (new Double (startRect.getY() / metrics.getHeight()).intValue() + 1);
1104:            //    } catch (BadLocationException e) {
1105:            //      // This shouldnt happen b/c we retrieve the caret pos before calling modelToView
1106:            //      throw new UnexpectedException(e);
1107:            //    }
1108:            //  }
1109:
1110:            /** Determines current line using logic in DefinitionsDocument.  Does it differ from getCurrentLine()? */
1111:            public int getCurrentLinefromDoc() {
1112:                return _doc.getCurrentLine();
1113:            }
1114:
1115:            public int getCurrentCol() {
1116:                return _doc.getCurrentCol();
1117:            }
1118:
1119:            public void setSize(int width, int height) {
1120:                super .setSize(width, height);
1121:                if (_setSizeListener != null)
1122:                    _setSizeListener.actionPerformed(null);
1123:            }
1124:
1125:            //  public void addSetSizeListener(ActionListener listener) { _setSizeListener = listener; }
1126:            //  public void removeSetSizeListener() { _setSizeListener = null; }
1127:
1128:            /** Centers the view (pane) on the specified offset. */
1129:            public void centerViewOnOffset(int offset) {
1130:                assert EventQueue.isDispatchThread();
1131:                try {
1132:                    FontMetrics metrics = getFontMetrics(getFont());
1133:                    JViewport defViewPort = _mainFrame.getDefViewport();
1134:                    double viewWidth = defViewPort.getWidth();
1135:                    double viewHeight = defViewPort.getHeight();
1136:                    // Scroll to make sure this item is visible
1137:                    // Centers the selection in the viewport
1138:                    Rectangle startRect;
1139:                    startRect = modelToView(offset);
1140:
1141:                    if (startRect != null) {
1142:                        int startRectX = (int) startRect.getX();
1143:                        int startRectY = (int) startRect.getY();
1144:                        startRect.setLocation(startRectX
1145:                                - (int) (viewWidth / 2), startRectY
1146:                                - (int) (viewHeight / 2));
1147:                        Point endPoint = new Point(startRectX
1148:                                + (int) (viewWidth / 2),
1149:                                startRectY
1150:                                        + (int) (viewHeight / 2 + metrics
1151:                                                .getHeight() / 2));
1152:
1153:                        // Add the end rect onto the start rect to make a rectangle
1154:                        // that encompasses the entire selection
1155:                        startRect.add(endPoint);
1156:
1157:                        scrollRectToVisible(startRect);
1158:                    }
1159:                    //      removeSetSizeListener();  // Why?  None was added
1160:
1161:                    setCaretPos(offset);
1162:                } catch (BadLocationException e) {
1163:                    throw new UnexpectedException(e);
1164:                }
1165:            }
1166:
1167:            public void centerViewOnLine(int lineNumber) {
1168:                FontMetrics metrics = getFontMetrics(getFont());
1169:                Point p = new Point(0, metrics.getHeight() * (lineNumber));
1170:                int offset = this .viewToModel(p);
1171:                this .centerViewOnOffset(offset);
1172:            }
1173:
1174:            /** This method overrides a broken version in JTextComponent.  It allows selection to proceed backwards as well as 
1175:             * forwards.  If selection is backwards, then the caret ends up at the start of the selection rather than the end.
1176:             */
1177:            public void select(int selectionStart, int selectionEnd) {
1178:                _doc.acquireReadLock();
1179:                try {
1180:                    //      if (selectionStart < 0) selectionStart = 0;
1181:                    //      if (selectionEnd < 0) selectionEnd = 0;
1182:                    setCaretPosition(selectionStart);
1183:                    moveCaretPosition(selectionEnd); // What about the caret position in the reduced model?  It is updated by a listener.
1184:                } finally {
1185:                    _doc.releaseReadLock();
1186:                }
1187:            }
1188:
1189:            /** Reset the document Undo list. */
1190:            public void resetUndo() {
1191:                _doc.getUndoManager().discardAllEdits();
1192:
1193:                _undoAction.updateUndoState();
1194:                _redoAction.updateRedoState();
1195:            }
1196:
1197:            /** Reset the document Undo list. */
1198:            private void _resetUndo() {
1199:                if (_undoAction == null)
1200:                    _undoAction = new UndoAction();
1201:                if (_redoAction == null)
1202:                    _redoAction = new RedoAction();
1203:
1204:                _doc.resetUndoManager();
1205:
1206:                getDocument().addUndoableEditListener(_undoListener);
1207:                _undoAction.updateUndoState();
1208:                _redoAction.updateRedoState();
1209:            }
1210:
1211:            /** Overriding this method ensures that all new documents created in this editor pane use our editor 
1212:             *  kit (and thus our model).
1213:             */
1214:            protected EditorKit createDefaultEditorKit() {
1215:                //return _editorKit;
1216:                return EDITOR_KIT;
1217:            }
1218:
1219:            /** Prompt the user whether or not they wish to indent, if the selection size is very large.
1220:             *  Return true if the indent is to be completed
1221:             *  @param selStart - the selection start
1222:             *  @param selEnd - the selection end
1223:             */
1224:            protected boolean shouldIndent(int selStart, int selEnd) {
1225:                if (selEnd > (selStart + INDENT_WARNING_THRESHOLD)) {
1226:                    Object[] options = { "Yes", "No" };
1227:                    int n = JOptionPane
1228:                            .showOptionDialog(
1229:                                    _mainFrame,
1230:                                    "Re-indenting this block may take a very long time.  Are you sure?",
1231:                                    "Confirm Re-indent",
1232:                                    JOptionPane.YES_NO_OPTION,
1233:                                    JOptionPane.QUESTION_MESSAGE, null,
1234:                                    options, options[1]);
1235:                    switch (n) {
1236:                    case JOptionPane.CANCEL_OPTION:
1237:                    case JOptionPane.CLOSED_OPTION:
1238:                    case JOptionPane.NO_OPTION:
1239:                        return false;
1240:                    default:
1241:                        return true;
1242:                    }
1243:                }
1244:                return true;
1245:            }
1246:
1247:            /** Indent the given selection, for the given reason, in the current document.
1248:             * @param selStart - the selection start
1249:             * @param selEnd - the selection end
1250:             * @param reason - the reason for the indent
1251:             * @param pm - the ProgressMonitor used by the indenter
1252:             */
1253:            protected void indentLines(int selStart, int selEnd,
1254:                    Indenter.IndentReason reason, ProgressMonitor pm) {
1255:                //_mainFrame.hourglassOn();
1256:                // final int key = _doc.getUndoManager().startCompoundEdit(); //Commented out in regards to French KeyBoard Fix
1257:                _doc.acquireWriteLock();
1258:                try {
1259:                    _doc.indentLines(selStart, selEnd, reason, pm);
1260:                    endCompoundEdit();
1261:                    setCaretPosition(_doc.getCurrentLocation()); // redundant?  
1262:                } catch (OperationCanceledException oce) {
1263:                    // if canceled, undo the indent; but first, end compound edit
1264:                    endCompoundEdit();
1265:                    _doc.getUndoManager().undo();
1266:                    // pm = null, so cancel can't be pressed
1267:                    throw new UnexpectedException(oce);
1268:                }
1269:                //    catch (RuntimeException e) {
1270:                //      /* Catches the exception to turn off the the hourglass and close the compound edit before throwing out to the
1271:                //       * main frame. */
1272:                //      endCompoundEdit();
1273:                //      throw e;
1274:                //    }
1275:                finally {
1276:                    _doc.releaseWriteLock();
1277:                }
1278:            }
1279:
1280:            /** Saved option listeners kept in this field so they can be removed for garbage collection  */
1281:            private List<Pair<Option<Color>, OptionListener<Color>>> _colorOptionListeners = new LinkedList<Pair<Option<Color>, OptionListener<Color>>>();
1282:
1283:            private List<Pair<Option<Boolean>, OptionListener<Boolean>>> _booleanOptionListeners = new LinkedList<Pair<Option<Boolean>, OptionListener<Boolean>>>();
1284:
1285:            /** Called when the definitions pane is released from duty.  This frees up any option listeners that are holding 
1286:             *  references to this object so this can be garbage collected.
1287:             */
1288:            public void close() {
1289:                for (Pair<Option<Color>, OptionListener<Color>> p : _colorOptionListeners) {
1290:                    DrJava.getConfig().removeOptionListener(p.first(),
1291:                            p.second());
1292:                }
1293:                for (Pair<Option<Boolean>, OptionListener<Boolean>> p : _booleanOptionListeners) {
1294:                    DrJava.getConfig().removeOptionListener(p.first(),
1295:                            p.second());
1296:                }
1297:                _colorOptionListeners.clear();
1298:                _booleanOptionListeners.clear();
1299:
1300:                ourMap.removeBindings();
1301:                removeKeymap(ourMap.getName());
1302:
1303:                _popMenu.removeAll();
1304:            }
1305:
1306:            /** The undo action. */
1307:            public class UndoAction extends AbstractAction {
1308:
1309:                /** Constructor. */
1310:                private UndoAction() {
1311:                    super ("Undo");
1312:                    setEnabled(false);
1313:                }
1314:
1315:                /** What to do when user chooses to undo.
1316:                 *  @param e
1317:                 */
1318:                public void actionPerformed(ActionEvent e) {
1319:                    try {
1320:                        //        UndoableEdit edit = _doc.getNextUndo();
1321:                        //         int pos = -1;
1322:                        //         if (edit != null && edit instanceof UndoWithPosition) {
1323:                        //           pos = ((UndoWithPosition)edit).getPosition();
1324:                        //         }
1325:                        //
1326:                        //         if (pos > -1) {
1327:                        //           //centerViewOnOffset(pos);
1328:                        //           setCaretPosition(pos);
1329:                        //         }
1330:                        _doc.getUndoManager().undo();
1331:                        _doc.updateModifiedSinceSave();
1332:                        _mainFrame.updateStatusField();
1333:                    } catch (CannotUndoException ex) {
1334:                        throw new UnexpectedException(ex);
1335:                    }
1336:                    updateUndoState();
1337:                    _redoAction.updateRedoState();
1338:                }
1339:
1340:                /** Updates the undo list, i.e., where we are as regards undo and redo. */
1341:                protected void updateUndoState() {
1342:                    if (_doc.undoManagerCanUndo()) {
1343:                        setEnabled(true);
1344:                        putValue(Action.NAME, _doc.getUndoManager()
1345:                                .getUndoPresentationName());
1346:                    } else {
1347:                        setEnabled(false);
1348:                        putValue(Action.NAME, "Undo");
1349:                    }
1350:                }
1351:            }
1352:
1353:            /** Redo action. */
1354:            public class RedoAction extends AbstractAction {
1355:
1356:                /** Constructor. */
1357:                private RedoAction() {
1358:                    super ("Redo");
1359:                    setEnabled(false);
1360:                }
1361:
1362:                /** In the event that the user chooses to redo something, this is what's called.
1363:                 *  @param e
1364:                 */
1365:                public void actionPerformed(ActionEvent e) {
1366:                    try {
1367:                        //        UndoableEdit edit = _doc.getNextRedo();
1368:                        //         int pos = -1;
1369:                        //         if (edit instanceof UndoWithPosition) {
1370:                        //           pos = ((UndoWithPosition)edit).getPosition();
1371:                        //         }
1372:                        _doc.getUndoManager().redo();
1373:
1374:                        //         if (pos > -1) {
1375:                        //           //centerViewOnOffset(pos);
1376:                        //           setCaretPosition(pos);
1377:                        //         }
1378:                        _doc.updateModifiedSinceSave();
1379:                        _mainFrame.updateStatusField();
1380:                    } catch (CannotRedoException ex) {
1381:                        throw new UnexpectedException(ex);
1382:                    }
1383:                    updateRedoState();
1384:                    _undoAction.updateUndoState();
1385:                }
1386:
1387:                /** Updates the redo state, i.e., where we are as regards undo and redo. */
1388:                protected void updateRedoState() {
1389:                    if (_doc.undoManagerCanRedo()) {
1390:                        setEnabled(true);
1391:                        putValue(Action.NAME, _doc.getUndoManager()
1392:                                .getRedoPresentationName());
1393:                    } else {
1394:                        setEnabled(false);
1395:                        putValue(Action.NAME, "Redo");
1396:                    }
1397:                }
1398:            }
1399:
1400:            /** Wrapper for UndoableEdit that pairs UndoableEdits with their caret positions */
1401:            private class UndoWithPosition implements  UndoableEdit {
1402:                private final UndoableEdit _undo;
1403:                private final int _pos;
1404:
1405:                public UndoWithPosition(UndoableEdit undo, int pos) {
1406:                    _undo = undo;
1407:                    _pos = pos;
1408:                }
1409:
1410:                public int getPosition() {
1411:                    return _pos;
1412:                }
1413:
1414:                public boolean addEdit(UndoableEdit ue) {
1415:                    return _undo.addEdit(ue);
1416:                }
1417:
1418:                public boolean canRedo() {
1419:                    return _undo.canRedo();
1420:                }
1421:
1422:                public boolean canUndo() {
1423:                    return _undo.canUndo();
1424:                }
1425:
1426:                public void die() {
1427:                    _undo.die();
1428:                }
1429:
1430:                public String getPresentationName() {
1431:                    return _undo.getPresentationName();
1432:                }
1433:
1434:                public String getUndoPresentationName() {
1435:                    return _undo.getUndoPresentationName();
1436:                }
1437:
1438:                public String getRedoPresentationName() {
1439:                    return _undo.getRedoPresentationName();
1440:                }
1441:
1442:                public boolean isSignificant() {
1443:                    return _undo.isSignificant();
1444:                }
1445:
1446:                public void redo() {
1447:                    _undo.redo();
1448:                    if (_pos > -1)
1449:                        setCaretPosition(_pos);
1450:                }
1451:
1452:                public boolean replaceEdit(UndoableEdit ue) {
1453:                    return _undo.replaceEdit(ue);
1454:                }
1455:
1456:                public void undo() {
1457:                    if (_pos > -1)
1458:                        setCaretPosition(_pos);
1459:                    _undo.undo();
1460:                }
1461:            }
1462:
1463:            /** This list of listeners to notify when we are finalized */
1464:            private List<FinalizationListener<DefinitionsPane>> _finalizationListeners = new LinkedList<FinalizationListener<DefinitionsPane>>();
1465:
1466:            /** Registers a finalization listener with the specific instance of the ddoc. NOTE: this should only be used by test 
1467:             *  cases.  This policy ensures that we don't spring memory leaks by allowing our unit tests to keep track of 
1468:             *  whether objects are being finalized (garbage collected).
1469:             *  @param fl the listener to register
1470:             */
1471:            public void addFinalizationListener(
1472:                    FinalizationListener<DefinitionsPane> fl) {
1473:                _finalizationListeners.add(fl);
1474:            }
1475:
1476:            public List<FinalizationListener<DefinitionsPane>> getFinalizationListeners() {
1477:                return _finalizationListeners;
1478:            }
1479:
1480:            /** This method is called when this object becomes unreachable.  Since this class implements
1481:             *  edu.rice.cs.drjava.model.Finalizable, it must notify its listeners.
1482:             */
1483:            protected void finalize() {
1484:                FinalizationEvent<DefinitionsPane> fe = new FinalizationEvent<DefinitionsPane>(
1485:                        this );
1486:                for (FinalizationListener<DefinitionsPane> fl : _finalizationListeners)
1487:                    fl.finalized(fe);
1488:            }
1489:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.