Source Code Cross Referenced for MainFrame.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) 


00001:        /*BEGIN_COPYRIGHT_BLOCK
00002:         *
00003:         * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
00004:         * All rights reserved.
00005:         * 
00006:         * Redistribution and use in source and binary forms, with or without
00007:         * modification, are permitted provided that the following conditions are met:
00008:         *    * Redistributions of source code must retain the above copyright
00009:         *      notice, this list of conditions and the following disclaimer.
00010:         *    * Redistributions in binary form must reproduce the above copyright
00011:         *      notice, this list of conditions and the following disclaimer in the
00012:         *      documentation and/or other materials provided with the distribution.
00013:         *    * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
00014:         *      names of its contributors may be used to endorse or promote products
00015:         *      derived from this software without specific prior written permission.
00016:         * 
00017:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00018:         * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019:         * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00020:         * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
00021:         * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00022:         * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00023:         * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00024:         * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00025:         * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00026:         * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00027:         * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028:         *
00029:         * This software is Open Source Initiative approved Open Source Software.
00030:         * Open Source Initative Approved is a trademark of the Open Source Initiative.
00031:         * 
00032:         * This file is part of DrJava.  Download the current version of this project
00033:         * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
00034:         * 
00035:         * END_COPYRIGHT_BLOCK*/
00036:
00037:        package edu.rice.cs.drjava.ui;
00038:
00039:        import javax.swing.*;
00040:        import javax.swing.text.*;
00041:        import javax.swing.event.*;
00042:        import javax.swing.border.*;
00043:        import java.awt.event.*;
00044:        import java.awt.*;
00045:        import java.awt.print.*;
00046:        import java.awt.dnd.*;
00047:        import java.beans.*;
00048:
00049:        import java.io.*;
00050:        import java.util.Collection;
00051:        import java.util.Hashtable;
00052:        import java.util.HashSet;
00053:        import java.util.List;
00054:        import java.util.LinkedList;
00055:        import java.util.ArrayList;
00056:        import java.util.Vector;
00057:        import java.util.Enumeration;
00058:        import java.net.URL;
00059:        import java.net.MalformedURLException;
00060:        import java.awt.datatransfer.*;
00061:
00062:        import edu.rice.cs.drjava.DrJava;
00063:        import edu.rice.cs.drjava.DrJavaRoot;
00064:        import edu.rice.cs.drjava.platform.*;
00065:        import edu.rice.cs.drjava.config.*;
00066:        import edu.rice.cs.drjava.model.*;
00067:        import edu.rice.cs.drjava.model.compiler.CompilerListener;
00068:        import edu.rice.cs.drjava.model.definitions.NoSuchDocumentException;
00069:        import edu.rice.cs.drjava.model.definitions.DocumentUIListener;
00070:        import edu.rice.cs.drjava.model.definitions.CompoundUndoManager;
00071:        import edu.rice.cs.drjava.model.definitions.ClassNameNotFoundException;
00072:        import edu.rice.cs.drjava.model.definitions.InvalidPackageException;
00073:        import edu.rice.cs.drjava.model.definitions.reducedmodel.*;
00074:        import edu.rice.cs.drjava.model.debug.*;
00075:        import edu.rice.cs.drjava.model.repl.*;
00076:        import edu.rice.cs.drjava.model.javadoc.JavadocModel;
00077:        import edu.rice.cs.drjava.ui.config.ConfigFrame;
00078:        import edu.rice.cs.drjava.ui.predictive.PredictiveInputFrame;
00079:        import edu.rice.cs.drjava.ui.predictive.PredictiveInputModel;
00080:        import edu.rice.cs.drjava.ui.ClipboardHistoryFrame;
00081:        import edu.rice.cs.drjava.model.ClipboardHistoryModel;
00082:        import edu.rice.cs.drjava.model.FileSaveSelector;
00083:        import edu.rice.cs.drjava.project.*;
00084:
00085:        import edu.rice.cs.plt.tuple.Pair;
00086:        import edu.rice.cs.plt.iter.IterUtil;
00087:        import edu.rice.cs.plt.io.IOUtil;
00088:        import edu.rice.cs.util.FileOpenSelector;
00089:        import edu.rice.cs.util.FileOps;
00090:        import edu.rice.cs.util.UnexpectedException;
00091:        import edu.rice.cs.util.OperationCanceledException;
00092:        import edu.rice.cs.util.classloader.ClassFileError;
00093:        import edu.rice.cs.util.docnavigation.*;
00094:        import edu.rice.cs.util.swing.AsyncTask;
00095:        import edu.rice.cs.util.swing.AsyncTaskLauncher;
00096:        import edu.rice.cs.util.swing.BorderlessScrollPane;
00097:        import edu.rice.cs.util.swing.BorderlessSplitPane;
00098:        import edu.rice.cs.util.swing.ConfirmCheckBoxDialog;
00099:        import edu.rice.cs.util.swing.DelegatingAction;
00100:        import edu.rice.cs.util.swing.DirectoryChooser;
00101:        import edu.rice.cs.util.swing.FileDisplayManager;
00102:        import edu.rice.cs.util.swing.HighlightManager;
00103:        import edu.rice.cs.util.swing.RightClickMouseAdapter;
00104:        import edu.rice.cs.util.swing.SwingWorker;
00105:        import edu.rice.cs.util.swing.Utilities;
00106:        import edu.rice.cs.util.swing.*;
00107:        import edu.rice.cs.util.text.AbstractDocumentInterface;
00108:
00109:        import static edu.rice.cs.drjava.config.OptionConstants.*;
00110:        import edu.rice.cs.drjava.RemoteControlClient;
00111:
00112:        /** DrJava's main window. */
00113:        public class MainFrame extends JFrame implements  ClipboardOwner,
00114:                DropTargetListener {
00115:
00116:            private static final int INTERACTIONS_TAB = 0;
00117:            private static final int CONSOLE_TAB = 1;
00118:            private static final String ICON_PATH = "/edu/rice/cs/drjava/ui/icons/";
00119:            private static final String DEBUGGER_OUT_OF_SYNC = " Current document is out of sync with the debugger and should be recompiled!";
00120:
00121:            /** Number of milliseconds to wait before displaying "Stepping..." message after a step is requested in 
00122:             * the debugger.
00123:             */
00124:            private static final int DEBUG_STEP_TIMER_VALUE = 2000;
00125:
00126:            /** The model which controls all logic in DrJava. */
00127:            private final SingleDisplayModel _model;
00128:
00129:            /** The main model listener attached by the main frame to the global model */
00130:            private final ModelListener _mainListener;
00131:
00132:            /** Maps an OpenDefDoc to its JScrollPane. */
00133:            private final Hashtable<OpenDefinitionsDocument, JScrollPane> _defScrollPanes;
00134:
00135:            /** The currently displayed DefinitionsPane. */
00136:            private volatile DefinitionsPane _currentDefPane;
00137:
00138:            /** The filename currently being displayed. */
00139:            private volatile String _fileTitle = "";
00140:
00141:            // Tabbed panel fields
00142:            public final LinkedList<TabbedPanel> _tabs = new LinkedList<TabbedPanel>();
00143:
00144:            private final JTabbedPane _tabbedPane;
00145:            private final CompilerErrorPanel _compilerErrorPanel;
00146:            private final InteractionsPane _consolePane;
00147:            private final JScrollPane _consoleScroll; // redirects focus to embedded _consolePane
00148:            private final ConsoleController _consoleController; // move to controller
00149:            private final InteractionsPane _interactionsPane;
00150:            private final JPanel _interactionsContainer; // redirects focus to embedded _interactionsPane
00151:            private final InteractionsController _interactionsController; // move to controller
00152:            private final JUnitPanel _junitErrorPanel;
00153:            private final JavadocErrorPanel _javadocErrorPanel;
00154:            private final FindReplacePanel _findReplace;
00155:            private final BreakpointsPanel _breakpointsPanel;
00156:            private final BookmarksPanel _bookmarksPanel;
00157:            private final LinkedList<Pair<FindResultsPanel, Hashtable<MovingDocumentRegion, HighlightManager.HighlightInfo>>> _findResults = new LinkedList<Pair<FindResultsPanel, Hashtable<MovingDocumentRegion, HighlightManager.HighlightInfo>>>();
00158:
00159:            private volatile boolean _showDebugger; // whether the supporting context is debugger capable
00160:
00161:            private volatile InteractionsScriptController _interactionsScriptController;
00162:            private volatile InteractionsScriptPane _interactionsScriptPane;
00163:            private volatile DebugPanel _debugPanel;
00164:            private volatile Component _lastFocusOwner;
00165:
00166:            /** Panel to hold both InteractionsPane and its sync message. */
00167:
00168:            // Status bar fields
00169:            private final JPanel _statusBar = new JPanel(new BorderLayout()); //( layout );
00170:            private final JLabel _statusField = new JLabel();
00171:            private final JLabel _statusReport = new JLabel(); //("This is the text for the center message");
00172:            private final JLabel _currLocationField = new JLabel();
00173:            private final PositionListener _posListener = new PositionListener();
00174:
00175:            // Split panes for layout
00176:            private final JSplitPane _docSplitPane;
00177:            private final JSplitPane _debugSplitPane;
00178:            private final JSplitPane _mainSplit;
00179:
00180:            // private Container _docCollectionWidget;
00181:            private volatile JButton _compileButton;
00182:            private volatile JButton _closeButton;
00183:            private volatile JButton _undoButton;
00184:            private volatile JButton _redoButton;
00185:            private volatile JButton _runButton;
00186:            private volatile JButton _junitButton;
00187:
00188:            private final JToolBar _toolBar;
00189:            private final JFileChooser _interactionsHistoryChooser;
00190:
00191:            // Menu fields
00192:            private final JMenuBar _menuBar;
00193:            private final JMenu _fileMenu;
00194:            private final JMenu _editMenu;
00195:            private final JMenu _toolsMenu;
00196:            private final JMenu _projectMenu;
00197:            private final JMenu _languageLevelMenu;
00198:            private final JMenu _helpMenu;
00199:
00200:            private volatile JMenu _debugMenu;
00201:            private volatile JMenuItem _debuggerEnabledMenuItem;
00202:
00203:            // Popup menus
00204:            private JPopupMenu _interactionsPanePopupMenu;
00205:            private JPopupMenu _consolePanePopupMenu;
00206:
00207:            // Cached frames and dialogs
00208:            private final ConfigFrame _configFrame;
00209:            private final HelpFrame _helpFrame;
00210:            private final QuickStartFrame _quickStartFrame;
00211:            private final AboutDialog _aboutDialog;
00212:            private final RecentDocFrame _recentDocFrame;
00213:            /** Holds/shows the history of documents for ctrl-tab. */
00214:
00215:            //  private ProjectPropertiesFrame _projectPropertiesFrame;
00216:            /** Keeps track of the recent files list in the File menu. */
00217:            private final RecentFileManager _recentFileManager;
00218:
00219:            /** Keeps track of the recent projects list in the Project menu */
00220:            private final RecentFileManager _recentProjectManager;
00221:
00222:            private volatile File _currentProjFile;
00223:
00224:            /** Timer to display "Stepping..." message if a step takes longer than a certain amount of time.  All accesses
00225:             *  must be synchronized on it.
00226:             */
00227:            private final Timer _debugStepTimer;
00228:
00229:            /** The current highlight displaying the location of the debugger's thread,
00230:             *  if there is one.  If there is none, this is null.
00231:             */
00232:            private volatile HighlightManager.HighlightInfo _currentThreadLocationHighlight = null;
00233:
00234:            /** Table to map breakpoints to their corresponding highlight objects. */
00235:            private final Hashtable<Breakpoint, HighlightManager.HighlightInfo> _documentBreakpointHighlights;
00236:
00237:            /** Table to map bookmarks to their corresponding highlight objects. */
00238:            private final Hashtable<DocumentRegion, HighlightManager.HighlightInfo> _documentBookmarkHighlights;
00239:
00240:            /** Whether to display a prompt message before quitting. */
00241:            private volatile boolean _promptBeforeQuit;
00242:
00243:            /** For opening files.  We have a persistent dialog to keep track of the last directory from which we opened. */
00244:            private final JFileChooser _openChooser;
00245:
00246:            /** For opening project files. */
00247:            private final JFileChooser _openProjectChooser;
00248:
00249:            /** For saving files. We have a persistent dialog to keep track of the last directory from which we saved. */
00250:            private final JFileChooser _saveChooser;
00251:
00252:            /** Filter for regular java files (.java and .j). */
00253:            private final javax.swing.filechooser.FileFilter _javaSourceFilter = new JavaSourceFilter();
00254:
00255:            /** Filter for drjava project files (.pjt) */
00256:            private final javax.swing.filechooser.FileFilter _projectFilter = new javax.swing.filechooser.FileFilter() {
00257:                public boolean accept(File f) {
00258:                    return f.isDirectory()
00259:                            || f.getPath().endsWith(PROJECT_FILE_EXTENSION);
00260:                }
00261:
00262:                public String getDescription() {
00263:                    return "DrJava Project Files (*.pjt)";
00264:                }
00265:            };
00266:
00267:            /** Returns the files to open to the model (command pattern). */
00268:            private final FileOpenSelector _openSelector = new FileOpenSelector() {
00269:                public File[] getFiles() throws OperationCanceledException {
00270:                    //_openChooser.removeChoosableFileFilter(_projectFilter);
00271:                    _openChooser.resetChoosableFileFilters();
00272:
00273:                    _openChooser.setFileFilter(_javaSourceFilter);
00274:                    return getOpenFiles(_openChooser);
00275:                }
00276:            };
00277:
00278:            /** Returns the files to open to the model (command pattern). */
00279:            private final FileOpenSelector _openFileOrProjectSelector = new FileOpenSelector() {
00280:                public File[] getFiles() throws OperationCanceledException {
00281:                    //_openChooser.removeChoosableFileFilter(_projectFilter);
00282:                    _openChooser.resetChoosableFileFilters();
00283:
00284:                    _openChooser.addChoosableFileFilter(_projectFilter);
00285:                    _openChooser.setFileFilter(_javaSourceFilter);
00286:                    return getOpenFiles(_openChooser);
00287:                }
00288:            };
00289:
00290:            /** Returns the project file to open. */
00291:            private final FileOpenSelector _openProjectSelector = new FileOpenSelector() {
00292:                public File[] getFiles() throws OperationCanceledException {
00293:                    File[] retFiles = getOpenFiles(_openProjectChooser);
00294:                    return retFiles;
00295:                }
00296:            };
00297:
00298:            /** Returns the file to save to the model (command pattern).  */
00299:            private final FileSaveSelector _saveSelector = new FileSaveSelector() {
00300:                public File getFile() throws OperationCanceledException {
00301:                    return getSaveFile(_saveChooser);
00302:                }
00303:
00304:                public boolean warnFileOpen(File f) {
00305:                    return _warnFileOpen(f);
00306:                }
00307:
00308:                public boolean verifyOverwrite() {
00309:                    return _verifyOverwrite();
00310:                }
00311:
00312:                public boolean shouldSaveAfterFileMoved(
00313:                        OpenDefinitionsDocument doc, File oldFile) {
00314:                    _model.setActiveDocument(doc);
00315:                    String text = "File "
00316:                            + oldFile.getAbsolutePath()
00317:                            + "\ncould not be found on disk!  It was probably moved\n"
00318:                            + "or deleted.  Would you like to save it in a new file?";
00319:                    int rc = JOptionPane.showConfirmDialog(MainFrame.this ,
00320:                            text, "File Moved or Deleted",
00321:                            JOptionPane.YES_NO_OPTION);
00322:                    return (rc == JOptionPane.YES_OPTION);
00323:                }
00324:            };
00325:
00326:            /** Returns the file to save to the model (command pattern). */
00327:            private final FileSaveSelector _saveAsSelector = new FileSaveSelector() {
00328:                public File getFile() throws OperationCanceledException {
00329:                    return getSaveFile(_saveChooser);
00330:                }
00331:
00332:                public boolean warnFileOpen(File f) {
00333:                    return _warnFileOpen(f);
00334:                }
00335:
00336:                public boolean verifyOverwrite() {
00337:                    return _verifyOverwrite();
00338:                }
00339:
00340:                public boolean shouldSaveAfterFileMoved(
00341:                        OpenDefinitionsDocument doc, File oldFile) {
00342:                    return true;
00343:                }
00344:            };
00345:
00346:            /** Returns the file to save to the model (command pattern). 
00347:            private final FileSaveSelector _renameSelector = new FileSaveSelector() {
00348:              public File getFile() throws OperationCanceledException { return getSaveFile(_saveChooser); }
00349:              public boolean warnFileOpen(File f) { return _warnFileOpen(f); }
00350:              public boolean verifyOverwrite() { return _verifyOverwrite(); }
00351:              public boolean shouldSaveAfterFileMoved(OpenDefinitionsDocument doc, File oldFile) { return true; }
00352:            }; */
00353:
00354:            /** Provides the view's contribution to the Javadoc interaction. */
00355:            private final JavadocDialog _javadocSelector = new JavadocDialog(
00356:                    this );
00357:
00358:            /** Provides a chooser to open a directory */
00359:            private final DirectoryChooser _folderChooser;
00360:            private final JCheckBox _openRecursiveCheckBox;
00361:
00362:            private final Action _moveToAuxiliaryAction = new AbstractAction(
00363:                    "Include With Project") {
00364:                { /* initalization block */
00365:                    String msg = "<html>Open this document each time this project is opened.<br>"
00366:                            + "This file would then be compiled and tested with the<br>"
00367:                            + "rest of the project.</html>";
00368:                    putValue(Action.SHORT_DESCRIPTION, msg);
00369:                }
00370:
00371:                public void actionPerformed(ActionEvent ae) {
00372:                    _moveToAuxiliary();
00373:                }
00374:            };
00375:            private final Action _removeAuxiliaryAction = new AbstractAction(
00376:                    "Do Not Include With Project") {
00377:                {
00378:                    putValue(Action.SHORT_DESCRIPTION,
00379:                            "Do not open this document next time this project is opened.");
00380:                }
00381:
00382:                public void actionPerformed(ActionEvent ae) {
00383:                    _removeAuxiliary();
00384:                }
00385:            };
00386:            private final Action _moveAllToAuxiliaryAction = new AbstractAction(
00387:                    "Include All With Project") {
00388:                { /* initalization block */
00389:                    String msg = "<html>Open these documents each time this project is opened.<br>"
00390:                            + "These files would then be compiled and tested with the<br>"
00391:                            + "rest of the project.</html>";
00392:                    putValue(Action.SHORT_DESCRIPTION, msg);
00393:                }
00394:
00395:                public void actionPerformed(ActionEvent ae) {
00396:                    _moveAllToAuxiliary();
00397:                }
00398:            };
00399:            private final Action _removeAllAuxiliaryAction = new AbstractAction(
00400:                    "Do Not Include Any With Project") {
00401:                {
00402:                    putValue(Action.SHORT_DESCRIPTION,
00403:                            "Do not open these documents next time this project is opened.");
00404:                }
00405:
00406:                public void actionPerformed(ActionEvent ae) {
00407:                    _removeAllAuxiliary();
00408:                }
00409:            };
00410:
00411:            /** Creates a new blank document and select it in the definitions pane. */
00412:            private final Action _newAction = new AbstractAction("New") {
00413:                public void actionPerformed(ActionEvent ae) {
00414:                    //      System.out.println("------------------new----------------------");
00415:                    _new();
00416:                }
00417:            };
00418:
00419:            private final Action _newProjectAction = new AbstractAction("New") {
00420:                public void actionPerformed(ActionEvent ae) {
00421:                    _newProject();
00422:                }
00423:            };
00424:
00425:            private volatile AbstractAction _runProjectAction = new AbstractAction(
00426:                    "Run Main Document of Project") {
00427:                public void actionPerformed(ActionEvent ae) {
00428:                    _runProject();
00429:                }
00430:            };
00431:
00432:            /** The jar options dialog. */
00433:            private final JarOptionsDialog _jarOptionsDialog;
00434:
00435:            /** Initializes the "Create Jar from Project dialog. */
00436:            private void initJarOptionsDialog() {
00437:                if (DrJava.getConfig().getSetting(
00438:                        DIALOG_JAROPTIONS_STORE_POSITION).booleanValue())
00439:                    _jarOptionsDialog.setFrameState(DrJava.getConfig()
00440:                            .getSetting(DIALOG_JAROPTIONS_STATE));
00441:            }
00442:
00443:            /** Reset the position of the "Create Jar from Project" dialog. */
00444:            public void resetJarOptionsDialogPosition() {
00445:                _jarOptionsDialog.setFrameState("default");
00446:                if (DrJava.getConfig().getSetting(
00447:                        DIALOG_JAROPTIONS_STORE_POSITION).booleanValue()) {
00448:                    DrJava.getConfig().setSetting(DIALOG_JAROPTIONS_STATE,
00449:                            "default");
00450:                }
00451:            }
00452:
00453:            private final Action _jarProjectAction = new AbstractAction(
00454:                    "Create Jar File from Project...") {
00455:                public void actionPerformed(ActionEvent ae) {
00456:                    _jarOptionsDialog.setVisible(true);
00457:                }
00458:            };
00459:
00460:            /** Sets the document in the definitions pane to a new templated junit test class. */
00461:            private final Action _newJUnitTestAction = new AbstractAction(
00462:                    "New JUnit Test Case...") {
00463:                public void actionPerformed(ActionEvent ae) {
00464:                    String testName = JOptionPane
00465:                            .showInputDialog(MainFrame.this ,
00466:                                    "Please enter a name for the test class:",
00467:                                    "New JUnit Test Case",
00468:                                    JOptionPane.QUESTION_MESSAGE);
00469:                    if (testName != null) {
00470:                        String ext;
00471:                        for (int i = 0; i < DrJavaRoot.LANGUAGE_LEVEL_EXTENSIONS.length; i++) {
00472:                            ext = "." + DrJavaRoot.LANGUAGE_LEVEL_EXTENSIONS[i];
00473:                            if (testName.endsWith(ext))
00474:                                testName = testName.substring(0, testName
00475:                                        .length()
00476:                                        - ext.length());
00477:                        }
00478:                        // For now, don't include setUp and tearDown
00479:                        _model.newTestCase(testName, false, false);
00480:                    }
00481:                }
00482:            };
00483:
00484:            /** Asks user for file name and and reads that file into the definitions pane. */
00485:            private final Action _openAction = new AbstractAction("Open...") {
00486:                public void actionPerformed(ActionEvent ae) {
00487:                    _open();
00488:                    _findReplace.updateFirstDocInSearch();
00489:                }
00490:            };
00491:
00492:            /** Asks user for directory name and and reads it's files (and subdirectories files, on request) to
00493:             *  the definitions pane.
00494:             */
00495:            private final Action _openFolderAction = new AbstractAction(
00496:                    "Open Folder...") {
00497:                public void actionPerformed(ActionEvent ae) {
00498:                    _openFolder();
00499:                    _findReplace.updateFirstDocInSearch();
00500:                }
00501:            };
00502:
00503:            /** Asks user for file name and and reads that file into the definitions pane. */
00504:            private final Action _openFileOrProjectAction = new AbstractAction(
00505:                    "Open...") {
00506:                public void actionPerformed(ActionEvent ae) {
00507:                    _openFileOrProject();
00508:                    _findReplace.updateFirstDocInSearch();
00509:                }
00510:            };
00511:
00512:            /** Asks user for project file name and and reads the associated files into the file navigator (and places the first
00513:             *  source file in the editor pane)
00514:             */
00515:            private final Action _openProjectAction = new AbstractAction(
00516:                    "Open...") {
00517:                public void actionPerformed(ActionEvent ae) {
00518:                    _openProject();
00519:                }
00520:            };
00521:
00522:            private final Action _closeProjectAction = new AbstractAction(
00523:                    "Close") {
00524:                public void actionPerformed(ActionEvent ae) {
00525:                    closeProject();
00526:                    _findReplace.updateFirstDocInSearch();
00527:                }
00528:            };
00529:
00530:            /** Closes the current active document, prompting to save if necessary. */
00531:            private final Action _closeAction = new AbstractAction("Close") {
00532:                public void actionPerformed(ActionEvent ae) {
00533:                    _close();
00534:                    _findReplace.updateFirstDocInSearch();
00535:                }
00536:            };
00537:
00538:            /** Closes all open documents, prompting to save if necessary. */
00539:            private final Action _closeAllAction = new AbstractAction(
00540:                    "Close All") {
00541:                public void actionPerformed(ActionEvent ae) {
00542:                    _closeAll();
00543:                    _findReplace.updateFirstDocInSearch();
00544:                }
00545:            };
00546:
00547:            /** Closes all open documents, prompting to save if necessary. */
00548:            private final Action _closeFolderAction = new AbstractAction(
00549:                    "Close Folder") {
00550:                public void actionPerformed(ActionEvent ae) {
00551:                    _closeFolder();
00552:                    _findReplace.updateFirstDocInSearch();
00553:                }
00554:            };
00555:
00556:            /** Opens all the files in the current folder. */
00557:            private final Action _openAllFolderAction = new AbstractAction(
00558:                    "Open All Files") {
00559:                public void actionPerformed(ActionEvent ae) {
00560:                    // now works with multiple selected folders
00561:                    java.util.List<File> l = _model.getDocumentNavigator()
00562:                            .getSelectedFolders();
00563:                    for (File f : l) {
00564:                        File fAbs = new File(_model.getProjectRoot(), f
00565:                                .toString());
00566:                        _openFolder(fAbs, false);
00567:                    }
00568:
00569:                    // The following does not apply anymore:
00570:                    // Get the Folder that was clicked on by the user. When the user clicks on a directory component in the 
00571:                    // navigation pane, the current directory is updated in the openChooser JFileChooser component.  So the 
00572:                    // clicked on directory is obtained in this way
00573:                    // File dir = _openChooser.getCurrentDirectory();
00574:                    // _openFolder(dir, false);  
00575:                    _findReplace.updateFirstDocInSearch();
00576:                }
00577:            };
00578:
00579:            /** Opens a files in the current folder. */
00580:            private final Action _openOneFolderAction = new AbstractAction(
00581:                    "Open File in Folder") {
00582:                public void actionPerformed(ActionEvent ae) {
00583:                    _open();
00584:                    _findReplace.updateFirstDocInSearch();
00585:                }
00586:            };
00587:
00588:            /** Creates a new untitled, empty file in the current folder. */
00589:            public final Action _newFileFolderAction = new AbstractAction(
00590:                    "Create New File in Folder") {
00591:                public void actionPerformed(ActionEvent ae) {
00592:                    //make this new document the document in the document pane
00593:                    _new();
00594:                    _findReplace.updateFirstDocInSearch();
00595:                }
00596:            };
00597:
00598:            /** Tests all the files in a folder. */
00599:            private volatile AbstractAction _junitFolderAction = new AbstractAction(
00600:                    "Test Folder") {
00601:                public final void actionPerformed(ActionEvent ae) {
00602:                    _junitFolder();
00603:                }
00604:            };
00605:
00606:            /** Saves the current document. */
00607:            private final Action _saveAction = new AbstractAction("Save") {
00608:                public final void actionPerformed(ActionEvent ae) {
00609:                    _save();
00610:                }
00611:            };
00612:
00613:            /** Ensures that pack() is run in the event thread. Only used in test code */
00614:            public void pack() {
00615:                Utilities.invokeAndWait(new Runnable() {
00616:                    public void run() {
00617:                        packHelp();
00618:                    }
00619:                });
00620:            }
00621:
00622:            /** Helper method that provides access to super.pack() within the anonymous class new Runnable() {...} above */
00623:            private void packHelp() {
00624:                super .pack();
00625:            }
00626:
00627:            /** Supports MainFrameTest.*/
00628:            public boolean saveEnabledHuh() {
00629:                return _saveAction.isEnabled();
00630:            }
00631:
00632:            /** Asks the user for a file name and saves the document
00633:             *  currently in the definitions pane to that file.
00634:             */
00635:            private final Action _saveAsAction = new AbstractAction(
00636:                    "Save As...") {
00637:                public void actionPerformed(ActionEvent ae) {
00638:                    _saveAs();
00639:                }
00640:            };
00641:
00642:            /** Asks the user for a file name and renames and saves the document
00643:             *  currently in the definitions pane to that file.
00644:             */
00645:            private final Action _renameAction = new AbstractAction("Rename") {
00646:                public void actionPerformed(ActionEvent ae) {
00647:                    _rename();
00648:                }
00649:            };
00650:
00651:            private final Action _saveProjectAction = new AbstractAction("Save") {
00652:                public void actionPerformed(ActionEvent ae) {
00653:                    _saveAll(); // saves project file and all modified project source files; does not save external files
00654:                }
00655:            };
00656:
00657:            private final Action _saveProjectAsAction = new AbstractAction(
00658:                    "Save As...") {
00659:                public void actionPerformed(ActionEvent ae) {
00660:                    if (_saveProjectAs()) { // asks the user for a new project file name; sets _projectFile in global model to this value
00661:                        _saveAll(); // performs a save all operation using this new project file name, but ONLY if the "Save as" was not cancelled
00662:                    }
00663:                }
00664:            };
00665:
00666:            /** Reverts the current document. */
00667:            private final Action _revertAction = new AbstractAction(
00668:                    "Revert to Saved") {
00669:                public void actionPerformed(ActionEvent ae) {
00670:                    String title = "Revert to Saved?";
00671:
00672:                    // update message to reflect the number of files
00673:                    int count = _model.getDocumentNavigator()
00674:                            .getDocumentSelectedCount();
00675:                    String message;
00676:                    if (count == 1) {
00677:                        message = "Are you sure you want to revert the current "
00678:                                + "file to the version on disk?";
00679:                    } else {
00680:                        message = "Are you sure you want to revert the "
00681:                                + count
00682:                                + " selected files to the versions on disk?";
00683:                    }
00684:
00685:                    int rc = JOptionPane.showConfirmDialog(MainFrame.this ,
00686:                            message, title, JOptionPane.YES_NO_OPTION);
00687:                    if (rc == JOptionPane.YES_OPTION) {
00688:                        _revert();
00689:                    }
00690:                }
00691:            };
00692:
00693:            /** Reverts all open documents.
00694:             * (not working yet)
00695:             private Action _revertAllAction = new AbstractAction("Revert All to Saved") {
00696:             public void actionPerformed(ActionEvent ae) {
00697:             String title = "Revert All to Saved?";
00698:             
00699:             String message = "Are you sure you want to revert all open " +
00700:             "files to the versions on disk?";
00701:             
00702:             int rc = JOptionPane.showConfirmDialog(MainFrame.this,
00703:             message,
00704:             title,
00705:             JOptionPane.YES_NO_OPTION);
00706:             if (rc == JOptionPane.YES_OPTION) {
00707:             _revertAll();
00708:             }
00709:             }
00710:             };*/
00711:
00712:            /** Saves all documents, prompting for file names as necessary. */
00713:            final Action _saveAllAction = new AbstractAction("Save All") {
00714:                public void actionPerformed(ActionEvent ae) {
00715:                    _saveAll();
00716:                }
00717:            };
00718:
00719:            /** Prints the current document. */
00720:            private final Action _printDefDocAction = new AbstractAction(
00721:                    "Print...") {
00722:                public void actionPerformed(ActionEvent ae) {
00723:                    _printDefDoc();
00724:                }
00725:            };
00726:
00727:            /** Prints the console document. */
00728:            private final Action _printConsoleAction = new AbstractAction(
00729:                    "Print Console...") {
00730:                public void actionPerformed(ActionEvent ae) {
00731:                    _printConsole();
00732:                }
00733:            };
00734:
00735:            /** Prints the interactions document. */
00736:            private final Action _printInteractionsAction = new AbstractAction(
00737:                    "Print Interactions...") {
00738:                public void actionPerformed(ActionEvent ae) {
00739:                    _printInteractions();
00740:                }
00741:            };
00742:
00743:            /** Opens the print preview window. */
00744:            private final Action _printDefDocPreviewAction = new AbstractAction(
00745:                    "Print Preview...") {
00746:                public void actionPerformed(ActionEvent ae) {
00747:                    _printDefDocPreview();
00748:                }
00749:            };
00750:
00751:            /** Opens the print preview window. */
00752:            private final Action _printConsolePreviewAction = new AbstractAction(
00753:                    "Print Preview...") {
00754:                public void actionPerformed(ActionEvent ae) {
00755:                    _printConsolePreview();
00756:                }
00757:            };
00758:
00759:            /** Opens the print preview window. */
00760:            private final Action _printInteractionsPreviewAction = new AbstractAction(
00761:                    "Print Preview...") {
00762:                public void actionPerformed(ActionEvent ae) {
00763:                    _printInteractionsPreview();
00764:                }
00765:            };
00766:
00767:            /** Opens the page setup window. */
00768:            private final Action _pageSetupAction = new AbstractAction(
00769:                    "Page Setup...") {
00770:                public void actionPerformed(ActionEvent ae) {
00771:                    _pageSetup();
00772:                }
00773:            };
00774:
00775:            //  /** Compiles all the project. */
00776:            //  private Action _compileOpenProjectAction = new AbstractAction("Compile Open Project Files") {
00777:            //    public void actionPerformed(ActionEvent ae) { _compileAll(); } // right now, it's the same as compile all
00778:            //  };
00779:
00780:            /** Compiles the document in the definitions pane. */
00781:            private final Action _compileAction = new AbstractAction(
00782:                    "Compile Current Document") {
00783:                public void actionPerformed(ActionEvent ae) {
00784:                    if (_mainSplit.getDividerLocation() > _mainSplit
00785:                            .getMaximumDividerLocation())
00786:                        _mainSplit.resetToPreferredSizes();
00787:                    updateStatusField("Compiling " + _fileTitle);
00788:                    _compile();
00789:                    updateStatusField("Compilation of current document completed");
00790:                }
00791:            };
00792:
00793:            /** Compiles all the project. */
00794:            private volatile AbstractAction _compileProjectAction = new AbstractAction(
00795:                    "Compile Project") {
00796:                public void actionPerformed(ActionEvent ae) {
00797:                    if (_mainSplit.getDividerLocation() > _mainSplit
00798:                            .getMaximumDividerLocation())
00799:                        _mainSplit.resetToPreferredSizes();
00800:                    updateStatusField("Compiling all source files in open project");
00801:                    _compileProject();
00802:                    _findReplace.updateFirstDocInSearch();
00803:                    updateStatusField("Compilation of open project completed");
00804:                }
00805:            };
00806:
00807:            /** Compiles all documents in the navigators active group. */
00808:            private volatile AbstractAction _compileFolderAction = new AbstractAction(
00809:                    "Compile Folder") {
00810:                public void actionPerformed(ActionEvent ae) {
00811:                    if (_mainSplit.getDividerLocation() > _mainSplit
00812:                            .getMaximumDividerLocation())
00813:                        _mainSplit.resetToPreferredSizes();
00814:                    updateStatusField("Compiling all sources in current folder");
00815:                    _compileFolder();
00816:                    _findReplace.updateFirstDocInSearch();
00817:                    updateStatusField("Compilation of folder completed");
00818:                }
00819:            };
00820:
00821:            /** Compiles all open documents. */
00822:            private volatile AbstractAction _compileAllAction = new AbstractAction(
00823:                    "Compile All Documents") {
00824:                public void actionPerformed(ActionEvent ae) {
00825:                    if (_mainSplit.getDividerLocation() > _mainSplit
00826:                            .getMaximumDividerLocation())
00827:                        _mainSplit.resetToPreferredSizes();
00828:                    _compileAll();
00829:                    _findReplace.updateFirstDocInSearch();
00830:                }
00831:            };
00832:
00833:            /** cleans the build directory */
00834:            private volatile AbstractAction _cleanAction = new AbstractAction(
00835:                    "Clean Build Directory") {
00836:                public void actionPerformed(ActionEvent ae) {
00837:                    _clean();
00838:                }
00839:            };
00840:
00841:            /** Finds and runs the main method of the current document, if it exists. */
00842:            private volatile AbstractAction _runAction = new AbstractAction(
00843:                    "Run Document's Main Method") {
00844:                public void actionPerformed(ActionEvent ae) {
00845:                    _runMain();
00846:                }
00847:            };
00848:
00849:            /** Runs JUnit on the document in the definitions pane. */
00850:            private volatile AbstractAction _junitAction = new AbstractAction(
00851:                    "Test Current Document") {
00852:                public void actionPerformed(ActionEvent ae) {
00853:                    if (_mainSplit.getDividerLocation() > _mainSplit
00854:                            .getMaximumDividerLocation())
00855:                        _mainSplit.resetToPreferredSizes();
00856:                    _junit();
00857:                }
00858:            };
00859:
00860:            /** Runs JUnit over all open JUnit tests. */
00861:            private volatile AbstractAction _junitAllAction = new AbstractAction(
00862:                    "Test All Documents") {
00863:                public void actionPerformed(ActionEvent e) {
00864:                    if (_mainSplit.getDividerLocation() > _mainSplit
00865:                            .getMaximumDividerLocation())
00866:                        _mainSplit.resetToPreferredSizes();
00867:                    _junitAll();
00868:                    _findReplace.updateFirstDocInSearch();
00869:                }
00870:
00871:            };
00872:
00873:            /** Runs JUnit over all open JUnit tests in the project directory. */
00874:            private volatile AbstractAction _junitProjectAction = new AbstractAction(
00875:                    "Test Project") {
00876:                public void actionPerformed(ActionEvent e) {
00877:                    if (_mainSplit.getDividerLocation() > _mainSplit
00878:                            .getMaximumDividerLocation())
00879:                        _mainSplit.resetToPreferredSizes();
00880:                    _junitProject();
00881:                    _findReplace.updateFirstDocInSearch();
00882:                }
00883:            };
00884:
00885:            //  /** JUnit a directory. */
00886:            //  private final Action _junitProjectAction = new AbstractAction("Test Project") {
00887:            //    public void actionPerformed(ActionEvent e) {
00888:            //      new Thread("Running JUnit Tests") {
00889:            //        public void run() {
00890:            //          if (_model.isProjectActive()) {
00891:            //            try {
00892:            //              // hourglassOn();  // also done in junitStarted
00893:            //              _model.junitAll();
00894:            //            }
00895:            //            finally {
00896:            //             //  hourglassOff(); // also done in junitEnded
00897:            //            }
00898:            //          }
00899:            //        }
00900:            //      }.start();
00901:            //    }
00902:            //  };
00903:
00904:            /** Runs Javadoc on all open documents (and the files in their packages). */
00905:            private final Action _javadocAllAction = new AbstractAction(
00906:                    "Javadoc All Documents") {
00907:                public void actionPerformed(ActionEvent ae) {
00908:                    if (_mainSplit.getDividerLocation() > _mainSplit
00909:                            .getMaximumDividerLocation())
00910:                        _mainSplit.resetToPreferredSizes();
00911:                    try {
00912:                        // hourglassOn();
00913:                        JavadocModel jm = _model.getJavadocModel();
00914:                        File suggestedDir = jm.suggestJavadocDestination(_model
00915:                                .getActiveDocument());
00916:                        _javadocSelector.setSuggestedDir(suggestedDir);
00917:                        jm.javadocAll(_javadocSelector, _saveSelector);
00918:                    } catch (IOException ioe) {
00919:                        _showIOError(ioe);
00920:                    } finally {
00921:                        // hourglassOff();
00922:                    }
00923:                }
00924:            };
00925:
00926:            /** Runs Javadoc on the current document. */
00927:            private final Action _javadocCurrentAction = new AbstractAction(
00928:                    "Preview Javadoc for Current Document") {
00929:                public void actionPerformed(ActionEvent ae) {
00930:                    if (_mainSplit.getDividerLocation() > _mainSplit
00931:                            .getMaximumDividerLocation())
00932:                        _mainSplit.resetToPreferredSizes();
00933:                    try {
00934:                        _model.getActiveDocument().generateJavadoc(
00935:                                _saveSelector);
00936:                    } catch (IOException ioe) {
00937:                        _showIOError(ioe);
00938:                    }
00939:                }
00940:            };
00941:
00942:            /** Default cut action.  Returns focus to the correct pane. */
00943:            final Action cutAction = new DefaultEditorKit.CutAction() {
00944:                public void actionPerformed(ActionEvent e) {
00945:                    Component c = MainFrame.this .getFocusOwner();
00946:                    super .actionPerformed(e);
00947:                    if (_currentDefPane.hasFocus()) {
00948:                        String s = Utilities.getClipboardSelection(c);
00949:                        if (s != null && s.length() != 0) {
00950:                            ClipboardHistoryModel.singleton().put(s);
00951:                        }
00952:                    }
00953:                    if (c != null)
00954:                        c.requestFocusInWindow();
00955:                }
00956:            };
00957:
00958:            /** Default copy action.  Returns focus to the correct pane. */
00959:            final Action copyAction = new DefaultEditorKit.CopyAction() {
00960:                public void actionPerformed(ActionEvent e) {
00961:                    Component c = MainFrame.this .getFocusOwner();
00962:                    super .actionPerformed(e);
00963:                    if (_currentDefPane.hasFocus()
00964:                            && _currentDefPane.getSelectedText() != null) {
00965:                        String s = Utilities.getClipboardSelection(c);
00966:                        if (s != null && s.length() != 0) {
00967:                            ClipboardHistoryModel.singleton().put(s);
00968:                        }
00969:                    }
00970:                    if (c != null)
00971:                        c.requestFocusInWindow();
00972:                }
00973:            };
00974:
00975:            /** We lost ownership of what we put in the clipboard. */
00976:            public void lostOwnership(Clipboard clipboard, Transferable contents) {
00977:                // ignore
00978:            }
00979:
00980:            /** Default paste action.  Returns focus to the correct pane. */
00981:            final Action pasteAction = new DefaultEditorKit.PasteAction() {
00982:                public void actionPerformed(ActionEvent e) {
00983:                    Component c = MainFrame.this .getFocusOwner();
00984:                    if (_currentDefPane.hasFocus()) {
00985:                        _currentDefPane.endCompoundEdit();
00986:                        //        CompoundUndoManager undoMan = _model.getActiveDocument().getUndoManager(); // French keyboard fix
00987:                        //        int key = undoMan.startCompoundEdit();                                     // French keyboard fix
00988:                        super .actionPerformed(e);
00989:                        _currentDefPane.endCompoundEdit(); // replaced line below for French keyboard fix
00990:                        //        undoMan.endCompoundEdit(key);                                              // French keyboard fix
00991:                    } else
00992:                        super .actionPerformed(e);
00993:
00994:                    if (c != null)
00995:                        c.requestFocusInWindow();
00996:                }
00997:            };
00998:
00999:            /** Reset the position of the "Clipboard History" dialog. */
01000:            public void resetClipboardHistoryDialogPosition() {
01001:                if (DrJava.getConfig().getSetting(
01002:                        DIALOG_CLIPBOARD_HISTORY_STORE_POSITION).booleanValue()) {
01003:                    DrJava.getConfig().setSetting(
01004:                            DIALOG_CLIPBOARD_HISTORY_STATE, "default");
01005:                }
01006:            }
01007:
01008:            /** The "Clipboard History" dialog. */
01009:            private ClipboardHistoryFrame _clipboardHistoryDialog = null;
01010:
01011:            /** Asks the user for a file name and goes there. */
01012:            private final Action _pasteHistoryAction = new AbstractAction(
01013:                    "Paste from History...") {
01014:                public void actionPerformed(final ActionEvent ae) {
01015:                    final ClipboardHistoryFrame.CloseAction cancelAction = new ClipboardHistoryFrame.CloseAction() {
01016:                        public Object apply(String s) {
01017:                            // "Clipboard History" dialog position and size.
01018:                            if ((DrJava.getConfig().getSetting(
01019:                                    DIALOG_CLIPBOARD_HISTORY_STORE_POSITION)
01020:                                    .booleanValue())
01021:                                    && (_clipboardHistoryDialog != null)
01022:                                    && (_clipboardHistoryDialog.getFrameState() != null)) {
01023:                                DrJava.getConfig().setSetting(
01024:                                        DIALOG_CLIPBOARD_HISTORY_STATE,
01025:                                        (_clipboardHistoryDialog
01026:                                                .getFrameState().toString()));
01027:                            } else {
01028:                                // Reset to defaults to restore pristine behavior.
01029:                                DrJava.getConfig().setSetting(
01030:                                        DIALOG_CLIPBOARD_HISTORY_STATE,
01031:                                        DIALOG_CLIPBOARD_HISTORY_STATE
01032:                                                .getDefault());
01033:                            }
01034:                            return null;
01035:                        }
01036:                    };
01037:                    ClipboardHistoryFrame.CloseAction okAction = new ClipboardHistoryFrame.CloseAction() {
01038:                        public Object apply(String s) {
01039:                            cancelAction.apply(null);
01040:
01041:                            StringSelection ssel = new StringSelection(s);
01042:                            Clipboard cb = MainFrame.this .getToolkit()
01043:                                    .getSystemClipboard();
01044:                            if (cb != null) {
01045:                                cb.setContents(ssel, MainFrame.this );
01046:                                pasteAction.actionPerformed(ae);
01047:                            }
01048:                            return null;
01049:                        }
01050:                    };
01051:
01052:                    _clipboardHistoryDialog = new ClipboardHistoryFrame(
01053:                            MainFrame.this , "Clipboard History",
01054:                            ClipboardHistoryModel.singleton(), okAction,
01055:                            cancelAction);
01056:                    if (DrJava.getConfig().getSetting(
01057:                            DIALOG_CLIPBOARD_HISTORY_STORE_POSITION)
01058:                            .booleanValue()) {
01059:                        _clipboardHistoryDialog.setFrameState(DrJava
01060:                                .getConfig().getSetting(
01061:                                        DIALOG_CLIPBOARD_HISTORY_STATE));
01062:                    }
01063:                    _clipboardHistoryDialog.setVisible(true);
01064:                }
01065:            };
01066:
01067:            /** Copies whatever is currently in the interactions pane at the prompt to the definitions pane.  If the 
01068:             *  current string is empty, then it will attempt to return the last entry from the interactions pane's history.
01069:             */
01070:            private final Action _copyInteractionToDefinitionsAction = new AbstractAction(
01071:                    "Lift Current Interaction to Definitions") {
01072:                public void actionPerformed(ActionEvent a) {
01073:                    String text = _interactionsController.getDocument()
01074:                            .getCurrentInput();
01075:                    if (!text.equals("")) {
01076:                        _putTextIntoDefinitions(text + "\n");
01077:                        return;
01078:                    }
01079:                    try {
01080:                        text = _interactionsController.getDocument()
01081:                                .lastEntry();
01082:                    } catch (Exception e) {
01083:                        return;
01084:                    } // no entry to promote
01085:
01086:                    //It is assumed that empty strings are not put into the history
01087:                    _putTextIntoDefinitions(text + "\n");
01088:                    return;
01089:                }
01090:            };
01091:
01092:            /** Action that copies the previous interaction to the definitions pane.
01093:             *  Is there a good way to get the last history element without perturbing the current document?
01094:             Action copyPreviousInteractionToDefinitionsAction = new AbstractAction("Copy previous interaction to definitions") {
01095:             public void actionPerformed(ActionEvent e) {
01096:             _putTextIntoDefinitions(_interactionsController.getDocument().getCurrentInput() + "\n");
01097:             }
01098:             };*/
01099:
01100:            /** Undoes the last change to the active definitions document. */
01101:            private final DelegatingAction _undoAction = new DelegatingAction() {
01102:                public void actionPerformed(ActionEvent e) {
01103:                    _currentDefPane.endCompoundEdit();
01104:                    super .actionPerformed(e);
01105:                    _currentDefPane.requestFocusInWindow();
01106:                    OpenDefinitionsDocument doc = _model.getActiveDocument();
01107:                    //      Utilities.showDebug("isModifiedSinceSave() = " + doc.isModifiedSinceSave());
01108:                    _saveAction.setEnabled(doc.isModifiedSinceSave()
01109:                            || doc.isUntitled());
01110:                    //      Utilities.showDebug("check status");
01111:                }
01112:            };
01113:
01114:            /** Redoes the last undo to the active definitions document. */
01115:            private final DelegatingAction _redoAction = new DelegatingAction() {
01116:                public void actionPerformed(ActionEvent e) {
01117:                    super .actionPerformed(e);
01118:                    _currentDefPane.requestFocusInWindow();
01119:                    OpenDefinitionsDocument doc = _model.getActiveDocument();
01120:                    _saveAction.setEnabled(doc.isModifiedSinceSave()
01121:                            || doc.isUntitled());
01122:                }
01123:            };
01124:
01125:            /** Quits DrJava.  Optionally displays a prompt before quitting. */
01126:            private final Action _quitAction = new AbstractAction("Quit") {
01127:                public void actionPerformed(ActionEvent ae) {
01128:                    _quit();
01129:                }
01130:            };
01131:
01132:            /** Quits DrJava.  Optionally displays a prompt before quitting. */
01133:            private final Action _forceQuitAction = new AbstractAction(
01134:                    "Force Quit") {
01135:                public void actionPerformed(ActionEvent ae) {
01136:                    _forceQuit();
01137:                }
01138:            };
01139:
01140:            /** Selects all text in window. */
01141:            private final Action _selectAllAction = new AbstractAction(
01142:                    "Select All") {
01143:                public void actionPerformed(ActionEvent ae) {
01144:                    _selectAll();
01145:                }
01146:            };
01147:
01148:            private void _showFindReplaceTab() {
01149:                if (_mainSplit.getDividerLocation() > _mainSplit
01150:                        .getMaximumDividerLocation())
01151:                    _mainSplit.resetToPreferredSizes();
01152:                if (!_findReplace.isDisplayed()) {
01153:                    showTab(_findReplace);
01154:                    _findReplace.beginListeningTo(_currentDefPane);
01155:                }
01156:                _findReplace.setVisible(true);
01157:                _tabbedPane.setSelectedComponent(_findReplace);
01158:            }
01159:
01160:            /** Shows the find/replace tab. */
01161:            private final Action _findReplaceAction = new AbstractAction(
01162:                    "Find/Replace") {
01163:                public void actionPerformed(ActionEvent ae) {
01164:                    _showFindReplaceTab();
01165:                    // Use SwingUtilties.invokeLater to ensure that focus is set AFTER the _findReplace tab has been selected
01166:                    EventQueue.invokeLater(new Runnable() {
01167:                        public void run() {
01168:                            _findReplace.requestFocusInWindow();
01169:                        }
01170:                    });
01171:                }
01172:            };
01173:
01174:            /** Find the next instance of the find word. */
01175:            private final Action _findNextAction = new AbstractAction(
01176:                    "Find Next") {
01177:                public void actionPerformed(ActionEvent ae) {
01178:                    _showFindReplaceTab();
01179:                    if (!DrJava.getConfig().getSetting(
01180:                            FIND_REPLACE_FOCUS_IN_DEFPANE).booleanValue()) {
01181:                        // Use SwingUtilties.invokeLater to ensure that focus is set AFTER the _findReplace tab has been selected
01182:                        EventQueue.invokeLater(new Runnable() {
01183:                            public void run() {
01184:                                _findReplace.requestFocusInWindow();
01185:                            }
01186:                        });
01187:                    }
01188:                    _findReplace.findNext();
01189:                    _currentDefPane.requestFocusInWindow();
01190:                    // atempt to fix intermittent bug where _currentDefPane listens but does not echo and won't undo!
01191:                }
01192:            };
01193:
01194:            /** Does the find next in the opposite direction. If the direction is backward it searches forward. */
01195:            private final Action _findPrevAction = new AbstractAction(
01196:                    "Find Previous") {
01197:                public void actionPerformed(ActionEvent ae) {
01198:                    _showFindReplaceTab();
01199:                    if (!DrJava.getConfig().getSetting(
01200:                            FIND_REPLACE_FOCUS_IN_DEFPANE).booleanValue()) {
01201:                        // Use SwingUtilties.invokeLater to ensure that focus is set AFTER the _findReplace tab has been selected
01202:                        EventQueue.invokeLater(new Runnable() {
01203:                            public void run() {
01204:                                _findReplace.requestFocusInWindow();
01205:                            }
01206:                        });
01207:                    }
01208:                    _findReplace.findPrevious();
01209:                    _currentDefPane.requestFocusInWindow();
01210:                }
01211:            };
01212:
01213:            /** Asks the user for a line number and goes there. */
01214:            private final Action _gotoLineAction = new AbstractAction(
01215:                    "Go to Line...") {
01216:                public void actionPerformed(ActionEvent ae) {
01217:                    int pos = _gotoLine();
01218:                    _currentDefPane.requestFocusInWindow();
01219:                    if (pos != -1)
01220:                        _currentDefPane.setCaretPosition(pos);
01221:                    // The preceding is a brute force attempt to fix intermittent failure to display caret
01222:                }
01223:            };
01224:
01225:            /** Wrapper class for the "Go to File" dialog list entries. Provides the ability to have the same 
01226:             *  OpenDefinitionsDocument in there multiple times with different toString() results.
01227:             */
01228:            private static class GoToFileListEntry implements 
01229:                    Comparable<GoToFileListEntry> {
01230:                public final OpenDefinitionsDocument doc;
01231:                private final String str;
01232:
01233:                public GoToFileListEntry(OpenDefinitionsDocument d, String s) {
01234:                    doc = d;
01235:                    str = s;
01236:                }
01237:
01238:                public String toString() {
01239:                    return str;
01240:                }
01241:
01242:                public int compareTo(GoToFileListEntry other) {
01243:                    return str.toLowerCase().compareTo(other.str.toLowerCase());
01244:                }
01245:
01246:                public boolean equals(Object other) {
01247:                    if (!(other instanceof  GoToFileListEntry))
01248:                        return false;
01249:                    return str.equals(((GoToFileListEntry) other).str);
01250:                }
01251:
01252:                public int hashCode() {
01253:                    return str.hashCode();
01254:                }
01255:            }
01256:
01257:            /** Reset the position of the "Go to File" dialog. */
01258:            public void resetGotoFileDialogPosition() {
01259:                initGotoFileDialog();
01260:                _gotoFileDialog.setFrameState("default");
01261:                if (DrJava.getConfig().getSetting(
01262:                        DIALOG_GOTOFILE_STORE_POSITION).booleanValue()) {
01263:                    DrJava.getConfig().setSetting(DIALOG_GOTOFILE_STATE,
01264:                            "default");
01265:                }
01266:            }
01267:
01268:            /** Initialize dialog if necessary. */
01269:            void initGotoFileDialog() {
01270:                if (_gotoFileDialog == null) {
01271:                    PredictiveInputFrame.InfoSupplier<GoToFileListEntry> info = new PredictiveInputFrame.InfoSupplier<GoToFileListEntry>() {
01272:                        public String apply(GoToFileListEntry entry) {
01273:                            final StringBuilder sb = new StringBuilder();
01274:
01275:                            if (entry.doc != null) {
01276:                                try {
01277:                                    try {
01278:                                        sb.append(FileOps.makeRelativeTo(
01279:                                                entry.doc.getRawFile(),
01280:                                                entry.doc.getSourceRoot()));
01281:                                    } catch (IOException e) {
01282:                                        sb.append(entry.doc.getFile());
01283:                                    }
01284:                                } catch (edu.rice.cs.drjava.model.FileMovedException e) {
01285:                                    sb.append(entry + " was moved");
01286:                                } catch (java.lang.IllegalStateException e) {
01287:                                    sb.append(entry);
01288:                                } catch (InvalidPackageException e) {
01289:                                    sb.append(entry);
01290:                                }
01291:                            } else
01292:                                sb.append(entry);
01293:                            return sb.toString();
01294:                        }
01295:                    };
01296:                    PredictiveInputFrame.CloseAction<GoToFileListEntry> okAction = new PredictiveInputFrame.CloseAction<GoToFileListEntry>() {
01297:                        public Object apply(
01298:                                PredictiveInputFrame<GoToFileListEntry> p) {
01299:                            if (p.getItem() != null) {
01300:                                final OpenDefinitionsDocument newDoc = p
01301:                                        .getItem().doc;
01302:                                //            final boolean docChanged = ! newDoc.equals(_model.getActiveDocument());
01303:                                //            if (docChanged) addToBrowserHistory();
01304:                                final boolean docSwitch = _model
01305:                                        .getActiveDocument() != newDoc;
01306:                                if (docSwitch)
01307:                                    _model.setActiveDocument(newDoc);
01308:                                final int curLine = newDoc.getCurrentLine();
01309:                                final String t = p.getText();
01310:                                final int last = t.lastIndexOf(':');
01311:                                if (last >= 0) {
01312:                                    try {
01313:                                        String end = t.substring(last + 1);
01314:                                        int val = Integer.parseInt(end);
01315:
01316:                                        final int lineNum = Math.max(1, val);
01317:                                        Runnable command = new Runnable() {
01318:                                            public void run() {
01319:                                                try {
01320:                                                    _jumpToLine(lineNum);
01321:                                                } catch (RuntimeException e) {
01322:                                                    _jumpToLine(curLine);
01323:                                                }
01324:                                            }
01325:                                        };
01326:                                        if (docSwitch) {
01327:                                            // postpone running command until after document switch, which is pending in the event queue
01328:                                            EventQueue.invokeLater(command);
01329:                                        } else
01330:                                            command.run();
01331:                                    } catch (RuntimeException e) { /* ignore */
01332:                                    }
01333:                                }
01334:                                //            if (docChanged) {
01335:                                //              // defer executing this code until after active document switch (if any) is complete
01336:                                //              EventQueue.invokeLater(new Runnable() {
01337:                                //                public void run() {
01338:                                //                  addToBrowserHistory();
01339:                                //                }
01340:                                //              });
01341:                                //            }
01342:                            }
01343:                            hourglassOff();
01344:                            return null;
01345:                        }
01346:                    };
01347:                    PredictiveInputFrame.CloseAction<GoToFileListEntry> cancelAction = new PredictiveInputFrame.CloseAction<GoToFileListEntry>() {
01348:                        public Object apply(
01349:                                PredictiveInputFrame<GoToFileListEntry> p) {
01350:                            hourglassOff();
01351:                            return null;
01352:                        }
01353:                    };
01354:                    java.util.ArrayList<PredictiveInputModel.MatchingStrategy<GoToFileListEntry>> strategies = new java.util.ArrayList<PredictiveInputModel.MatchingStrategy<GoToFileListEntry>>();
01355:                    strategies
01356:                            .add(new PredictiveInputModel.FragmentLineNumStrategy<GoToFileListEntry>());
01357:                    strategies
01358:                            .add(new PredictiveInputModel.PrefixLineNumStrategy<GoToFileListEntry>());
01359:                    strategies
01360:                            .add(new PredictiveInputModel.RegExLineNumStrategy<GoToFileListEntry>());
01361:                    _gotoFileDialog = new PredictiveInputFrame<GoToFileListEntry>(
01362:                            MainFrame.this , "Go to File",
01363:                            true, // force
01364:                            true, // ignore case
01365:                            info, strategies, okAction, cancelAction,
01366:                            new GoToFileListEntry(null, "dummy")) {
01367:                        public void setOwnerEnabled(boolean b) {
01368:                            if (b) {
01369:                                hourglassOff();
01370:                            } else {
01371:                                hourglassOn();
01372:                            }
01373:                        }
01374:                    };
01375:                    // putting one dummy entry in the list; it will be changed later anyway
01376:
01377:                    if (DrJava.getConfig().getSetting(
01378:                            DIALOG_GOTOFILE_STORE_POSITION).booleanValue()) {
01379:                        _gotoFileDialog.setFrameState(DrJava.getConfig()
01380:                                .getSetting(DIALOG_GOTOFILE_STATE));
01381:                    }
01382:                }
01383:            }
01384:
01385:            /** The "Go to File" dialog instance. */
01386:            volatile PredictiveInputFrame<GoToFileListEntry> _gotoFileDialog = null;
01387:
01388:            /** Asks the user for a file name and goes there. */
01389:            private final Action _gotoFileAction = new AbstractAction(
01390:                    "Go to File...") {
01391:                public void actionPerformed(ActionEvent ae) {
01392:                    initGotoFileDialog();
01393:                    List<OpenDefinitionsDocument> docs = _model
01394:                            .getOpenDefinitionsDocuments();
01395:                    if (docs == null || docs.size() == 0) {
01396:                        return; // do nothing
01397:                    }
01398:                    GoToFileListEntry currentEntry = null;
01399:                    ArrayList<GoToFileListEntry> list;
01400:                    if (DrJava.getConfig().getSetting(
01401:                            DIALOG_GOTOFILE_FULLY_QUALIFIED).booleanValue()) {
01402:                        list = new ArrayList<GoToFileListEntry>(2 * docs.size());
01403:                    } else {
01404:                        list = new ArrayList<GoToFileListEntry>(docs.size());
01405:                    }
01406:                    for (OpenDefinitionsDocument d : docs) {
01407:                        GoToFileListEntry entry = new GoToFileListEntry(d, d
01408:                                .toString());
01409:                        if (d.equals(_model.getActiveDocument())) {
01410:                            currentEntry = entry;
01411:                        }
01412:                        list.add(entry);
01413:                        if (DrJava.getConfig().getSetting(
01414:                                DIALOG_GOTOFILE_FULLY_QUALIFIED).booleanValue()) {
01415:                            try {
01416:                                try {
01417:                                    File relative = FileOps.makeRelativeTo(d
01418:                                            .getFile(), d.getSourceRoot());
01419:                                    if (!relative.toString().equals(
01420:                                            d.toString())) {
01421:                                        list.add(new GoToFileListEntry(d, d
01422:                                                .getPackageName()
01423:                                                + "." + d.toString()));
01424:                                    }
01425:                                } catch (IOException e) {
01426:                                    // ignore
01427:                                } catch (edu.rice.cs.drjava.model.definitions.InvalidPackageException e) {
01428:                                    // ignore
01429:                                }
01430:                            } catch (IllegalStateException e) {
01431:                                // ignore
01432:                            }
01433:                        }
01434:                    }
01435:                    _gotoFileDialog.setItems(true, list); // ignore case
01436:                    if (currentEntry != null) {
01437:                        _gotoFileDialog.setCurrentItem(currentEntry);
01438:                    }
01439:                    hourglassOn();
01440:                    /* if (!  Utilities.TEST_MODE) */
01441:                    _gotoFileDialog.setVisible(true);
01442:                }
01443:            };
01444:
01445:            /** Goes to the file specified by the word the cursor is on. */
01446:            void _gotoFileUnderCursor() {
01447:                //    Utilities.show("Calling gotoFileUnderCursor()");
01448:                List<OpenDefinitionsDocument> docs = _model
01449:                        .getOpenDefinitionsDocuments();
01450:                if ((docs == null) || (docs.size() == 0))
01451:                    return; // do nothing
01452:
01453:                GoToFileListEntry currentEntry = null;
01454:                ArrayList<GoToFileListEntry> list;
01455:                list = new ArrayList<GoToFileListEntry>(docs.size());
01456:                for (OpenDefinitionsDocument d : docs) {
01457:                    GoToFileListEntry entry = new GoToFileListEntry(d, d
01458:                            .toString());
01459:                    if (d.equals(_model.getActiveDocument()))
01460:                        currentEntry = entry;
01461:                    list.add(entry);
01462:                }
01463:
01464:                PredictiveInputModel<GoToFileListEntry> pim = new PredictiveInputModel<GoToFileListEntry>(
01465:                        true,
01466:                        new PredictiveInputModel.PrefixStrategy<GoToFileListEntry>(),
01467:                        list);
01468:                OpenDefinitionsDocument odd = getCurrentDefPane()
01469:                        .getOpenDefDocument();
01470:                odd.acquireReadLock();
01471:                String mask = "";
01472:                try {
01473:                    int loc = getCurrentDefPane().getCaretPosition();
01474:                    String s = odd.getText();
01475:                    // find start
01476:                    int start = loc;
01477:                    while (start > 0) {
01478:                        if (!Character
01479:                                .isJavaIdentifierPart(s.charAt(start - 1))) {
01480:                            break;
01481:                        }
01482:                        --start;
01483:                    }
01484:                    while ((start < s.length())
01485:                            && (!Character.isJavaIdentifierStart(s
01486:                                    .charAt(start))) && (start < loc)) {
01487:                        ++start;
01488:                    }
01489:                    // find end
01490:                    int end = loc - 1;
01491:                    while (end < s.length() - 1) {
01492:                        if (!Character.isJavaIdentifierPart(s.charAt(end + 1))) {
01493:                            break;
01494:                        }
01495:                        ++end;
01496:                    }
01497:                    if ((start >= 0) && (end < s.length())) {
01498:                        mask = s.substring(start, end + 1);
01499:                        pim.setMask(mask);
01500:                    }
01501:                } finally {
01502:                    odd.releaseReadLock();
01503:                }
01504:
01505:                //    Utilities.show("Matching items are: " + pim.getMatchingItems());
01506:
01507:                if (pim.getMatchingItems().size() == 1) {
01508:                    // exactly one match, go to file
01509:                    if (pim.getCurrentItem() != null) {
01510:                        //        boolean docChanged = !pim.getCurrentItem().doc.equals(_model.getActiveDocument());
01511:                        //        if (docChanged) { addToBrowserHistory(); }
01512:                        _model.setActiveDocument(pim.getCurrentItem().doc);
01513:                        //        if (docChanged) {
01514:                        //          // defer executing this code until after active document switch (if any) is complete
01515:                        //          EventQueue.invokeLater(new Runnable() {
01516:                        //            public void run() { addToBrowserHistory(); } });
01517:                        //        }
01518:                    }
01519:                } else {
01520:                    // try appending ".java" and see if it's unique
01521:                    pim.extendMask(".java");
01522:                    if (pim.getMatchingItems().size() == 1) {
01523:                        // exactly one match with ".java" appended, go to file
01524:                        if (pim.getCurrentItem() != null) {
01525:                            //          boolean docChanged = !pim.getCurrentItem().doc.equals(_model.getActiveDocument());
01526:                            //          if (docChanged) { addToBrowserHistory(); }
01527:                            _model.setActiveDocument(pim.getCurrentItem().doc);
01528:                            //          if (docChanged) {
01529:                            //            // defer executing this code until after active document switch (if any) is complete
01530:                            //            EventQueue.invokeLater(new Runnable() { public void run() { addToBrowserHistory(); } });
01531:                            //          }
01532:                        }
01533:                    } else {
01534:                        // not exactly one match
01535:                        pim.setMask(mask);
01536:                        if (pim.getMatchingItems().size() == 0) {
01537:                            // if there are no matches, shorten the mask until there is at least one
01538:                            mask = pim.getMask();
01539:                            while (mask.length() > 0) {
01540:                                mask = mask.substring(0, mask.length() - 1);
01541:                                pim.setMask(mask);
01542:                                if (pim.getMatchingItems().size() > 0) {
01543:                                    break;
01544:                                }
01545:                            }
01546:                        }
01547:                        initGotoFileDialog();
01548:                        _gotoFileDialog.setModel(true, pim); // ignore case
01549:                        if (currentEntry != null)
01550:                            _gotoFileDialog.setCurrentItem(currentEntry);
01551:                        hourglassOn();
01552:                        /* The following predicate suppresses the display of the dialog during unit testing.  If the unit test is revised
01553:                         * to confirm that the dialog is displayed, this test must be removed. */
01554:                        if (MainFrame.this .isVisible())
01555:                            _gotoFileDialog.setVisible(true); // predicate suppresses display in unit tests
01556:                    }
01557:                }
01558:            }
01559:
01560:            /** Goes to the file specified by the word the cursor is on. */
01561:            final Action gotoFileUnderCursorAction = new AbstractAction(
01562:                    "Go to File Under Cursor") {
01563:                public void actionPerformed(ActionEvent ae) {
01564:                    _gotoFileUnderCursor();
01565:                }
01566:            };
01567:
01568:            /** Wrapper class for the "Open Javadoc" and "Auto Import" dialog list entries.
01569:             * Provides the ability to have the same class name in there multiple times in different packages.
01570:             */
01571:            private static class JavaAPIListEntry implements 
01572:                    Comparable<JavaAPIListEntry> {
01573:                private final String str, fullStr;
01574:                private final URL url;
01575:
01576:                public JavaAPIListEntry(String s, String full, URL u) {
01577:                    str = s;
01578:                    fullStr = full;
01579:                    url = u;
01580:                }
01581:
01582:                public String toString() {
01583:                    return str;
01584:                }
01585:
01586:                public String getFullString() {
01587:                    return fullStr;
01588:                }
01589:
01590:                public URL getURL() {
01591:                    return url;
01592:                }
01593:
01594:                public int compareTo(JavaAPIListEntry other) {
01595:                    return str.toLowerCase().compareTo(other.str.toLowerCase());
01596:                }
01597:
01598:                public boolean equals(Object other) {
01599:                    if (!(other instanceof  JavaAPIListEntry))
01600:                        return false;
01601:                    return fullStr.equals(((JavaAPIListEntry) other).fullStr);
01602:                }
01603:
01604:                public int hashCode() {
01605:                    return fullStr.hashCode();
01606:                }
01607:            }
01608:
01609:            /** Reset the position of the "Open Javadoc" dialog. */
01610:            public void resetOpenJavadocDialogPosition() {
01611:                initOpenJavadocDialog();
01612:                _openJavadocDialog.setFrameState("default");
01613:                if (DrJava.getConfig().getSetting(
01614:                        DIALOG_OPENJAVADOC_STORE_POSITION).booleanValue()) {
01615:                    DrJava.getConfig().setSetting(DIALOG_OPENJAVADOC_STATE,
01616:                            "default");
01617:                }
01618:            }
01619:
01620:            /** Initialize dialog if necessary. */
01621:            void initOpenJavadocDialog() {
01622:                if (_openJavadocDialog == null) {
01623:                    PredictiveInputFrame.InfoSupplier<JavaAPIListEntry> info = new PredictiveInputFrame.InfoSupplier<JavaAPIListEntry>() {
01624:                        public String apply(JavaAPIListEntry entry) {
01625:                            return entry.getFullString();
01626:                        }
01627:                    };
01628:                    PredictiveInputFrame.CloseAction<JavaAPIListEntry> okAction = new PredictiveInputFrame.CloseAction<JavaAPIListEntry>() {
01629:                        public Object apply(
01630:                                PredictiveInputFrame<JavaAPIListEntry> p) {
01631:                            if (p.getItem() != null) {
01632:                                PlatformFactory.ONLY.openURL(p.getItem()
01633:                                        .getURL());
01634:                            }
01635:                            hourglassOff();
01636:                            return null;
01637:                        }
01638:                    };
01639:                    PredictiveInputFrame.CloseAction<JavaAPIListEntry> cancelAction = new PredictiveInputFrame.CloseAction<JavaAPIListEntry>() {
01640:                        public Object apply(
01641:                                PredictiveInputFrame<JavaAPIListEntry> p) {
01642:                            hourglassOff();
01643:                            return null;
01644:                        }
01645:                    };
01646:                    java.util.ArrayList<PredictiveInputModel.MatchingStrategy<JavaAPIListEntry>> strategies = new java.util.ArrayList<PredictiveInputModel.MatchingStrategy<JavaAPIListEntry>>();
01647:                    strategies
01648:                            .add(new PredictiveInputModel.FragmentStrategy<JavaAPIListEntry>());
01649:                    strategies
01650:                            .add(new PredictiveInputModel.PrefixStrategy<JavaAPIListEntry>());
01651:                    strategies
01652:                            .add(new PredictiveInputModel.RegExStrategy<JavaAPIListEntry>());
01653:                    _openJavadocDialog = new PredictiveInputFrame<JavaAPIListEntry>(
01654:                            MainFrame.this ,
01655:                            "Open Java API Javadoc Webpage",
01656:                            true, // force
01657:                            true, // ignore case
01658:                            info, strategies, okAction, cancelAction,
01659:                            new JavaAPIListEntry("dummy", "dummy", null)) {
01660:                        public void setOwnerEnabled(boolean b) {
01661:                            if (b) {
01662:                                hourglassOff();
01663:                            } else {
01664:                                hourglassOn();
01665:                            }
01666:                        }
01667:                    };
01668:                    // putting one dummy entry in the list; it will be changed later anyway
01669:
01670:                    if (DrJava.getConfig().getSetting(
01671:                            DIALOG_OPENJAVADOC_STORE_POSITION).booleanValue()) {
01672:                        _openJavadocDialog.setFrameState(DrJava.getConfig()
01673:                                .getSetting(DIALOG_OPENJAVADOC_STATE));
01674:                    }
01675:                    generateJavaAPIList();
01676:                }
01677:            }
01678:
01679:            /** Generate Java API class list. */
01680:            public void generateJavaAPIList() {
01681:                if (_javaAPIList == null) {
01682:                    // generate list
01683:                    String linkVersion = DrJava.getConfig().getSetting(
01684:                            JAVADOC_LINK_VERSION);
01685:                    String base = "";
01686:                    String suffix = "";
01687:                    if (linkVersion.equals(JAVADOC_1_3_TEXT)) {
01688:                        base = DrJava.getConfig().getSetting(JAVADOC_1_3_LINK);
01689:                        suffix = "/allclasses-1.3.html";
01690:                    } else if (linkVersion.equals(JAVADOC_1_4_TEXT)) {
01691:                        base = DrJava.getConfig().getSetting(JAVADOC_1_4_LINK);
01692:                        suffix = "/allclasses-1.4.html";
01693:                    } else if (linkVersion.equals(JAVADOC_1_5_TEXT)) {
01694:                        base = DrJava.getConfig().getSetting(JAVADOC_1_5_LINK);
01695:                        suffix = "/allclasses-1.5.html";
01696:                    } else {
01697:                        // no valid Javadoc URL
01698:                        return;
01699:                    }
01700:                    // TODO: put this in an AsyncTask
01701:                    try {
01702:                        _javaAPIList = new ArrayList<JavaAPIListEntry>();
01703:                        URL url = MainFrame.class
01704:                                .getResource("/edu/rice/cs/drjava/docs/javaapi"
01705:                                        + suffix);
01706:                        BufferedReader br = new BufferedReader(
01707:                                new InputStreamReader(url.openStream()));
01708:                        String line = br.readLine();
01709:                        while (line != null) {
01710:                            final String aText = "<a href=\"";
01711:                            int aPos = line.toLowerCase().indexOf(aText);
01712:                            int aEndPos = line.toLowerCase().indexOf(
01713:                                    ".html\" ", aPos);
01714:                            if ((aPos >= 0) && (aEndPos >= 0)) {
01715:                                String link = line.substring(aPos
01716:                                        + aText.length(), aEndPos);
01717:                                String fullClassName = link.replace('/', '.');
01718:                                String simpleClassName = fullClassName;
01719:                                int lastDot = fullClassName.lastIndexOf('.');
01720:                                if (lastDot >= 0) {
01721:                                    simpleClassName = fullClassName
01722:                                            .substring(lastDot + 1);
01723:                                }
01724:                                try {
01725:                                    _javaAPIList
01726:                                            .add(new JavaAPIListEntry(
01727:                                                    simpleClassName,
01728:                                                    fullClassName, new URL(base
01729:                                                            + "/" + link
01730:                                                            + ".html")));
01731:                                } catch (MalformedURLException mue) { /* ignore, we'll just not put this class in the list */
01732:                                }
01733:                            }
01734:                            line = br.readLine();
01735:                        }
01736:                    } catch (IOException ioe) { /* ignore, we'll just have an incomplete list */
01737:                    }
01738:                    if (_javaAPIList.size() == 0) {
01739:                        _javaAPIList = null;
01740:                    }
01741:                }
01742:            }
01743:
01744:            /** The "Open Javadoc" dialog instance. */
01745:            PredictiveInputFrame<JavaAPIListEntry> _openJavadocDialog = null;
01746:
01747:            /** The list of Java API classes. */
01748:            List<JavaAPIListEntry> _javaAPIList = null;
01749:
01750:            /** Asks the user for a file name and goes there. */
01751:            private Action _openJavadocAction = new AbstractAction(
01752:                    "Open Java API Javadoc...") {
01753:                public void actionPerformed(ActionEvent ae) {
01754:                    initOpenJavadocDialog();
01755:                    _openJavadocDialog.setItems(true, _javaAPIList); // ignore case
01756:                    hourglassOn();
01757:                    _openJavadocDialog.setVisible(true);
01758:                }
01759:            };
01760:
01761:            /** Opens the Javadoc specified by the word the cursor is on. */
01762:            void _openJavadocUnderCursor() {
01763:                generateJavaAPIList();
01764:                if (_javaAPIList == null) {
01765:                    //      Utilities.show("Cannot load Java API class list. No network connectivity?");
01766:                    return;
01767:                }
01768:                PredictiveInputModel<JavaAPIListEntry> pim = new PredictiveInputModel<JavaAPIListEntry>(
01769:                        true,
01770:                        new PredictiveInputModel.PrefixStrategy<JavaAPIListEntry>(),
01771:                        _javaAPIList);
01772:                OpenDefinitionsDocument odd = getCurrentDefPane()
01773:                        .getOpenDefDocument();
01774:                odd.acquireReadLock();
01775:                String mask = "";
01776:                try {
01777:                    int loc = getCurrentDefPane().getCaretPosition();
01778:                    String s = odd.getText();
01779:                    // find start
01780:                    int start = loc;
01781:                    while (start > 0) {
01782:                        if (!Character
01783:                                .isJavaIdentifierPart(s.charAt(start - 1))) {
01784:                            break;
01785:                        }
01786:                        --start;
01787:                    }
01788:                    while ((start < s.length())
01789:                            && (!Character.isJavaIdentifierStart(s
01790:                                    .charAt(start))) && (start < loc)) {
01791:                        ++start;
01792:                    }
01793:                    // find end
01794:                    int end = loc - 1;
01795:                    while (end < s.length() - 1) {
01796:                        if (!Character.isJavaIdentifierPart(s.charAt(end + 1))) {
01797:                            break;
01798:                        }
01799:                        ++end;
01800:                    }
01801:                    if ((start >= 0) && (end < s.length())) {
01802:                        mask = s.substring(start, end + 1);
01803:                        pim.setMask(mask);
01804:                    }
01805:                } finally {
01806:                    odd.releaseReadLock();
01807:                }
01808:
01809:                //    Utilities.show("Matching items are: " + pim.getMatchingItems());
01810:
01811:                if (pim.getMatchingItems().size() == 1) {
01812:                    // exactly one match, go to file
01813:                    if (pim.getCurrentItem() != null) {
01814:                        PlatformFactory.ONLY.openURL(pim.getCurrentItem()
01815:                                .getURL());
01816:                    }
01817:                } else {
01818:                    // try appending ".java" and see if it's unique
01819:                    pim.extendMask(".java");
01820:                    if (pim.getMatchingItems().size() == 1) {
01821:                        // exactly one match with ".java" appended, go to file
01822:                        if (pim.getCurrentItem() != null) {
01823:                            PlatformFactory.ONLY.openURL(pim.getCurrentItem()
01824:                                    .getURL());
01825:                        }
01826:                    } else {
01827:                        // not exactly one match
01828:                        pim.setMask(mask);
01829:                        JavaAPIListEntry foundItem = null;
01830:                        int found = 0;
01831:                        if (pim.getMatchingItems().size() == 0) {
01832:                            // if there are no matches, shorten the mask until there is at least one
01833:                            mask = pim.getMask();
01834:                            while (mask.length() > 0) {
01835:                                mask = mask.substring(0, mask.length() - 1);
01836:                                pim.setMask(mask);
01837:                                if (pim.getMatchingItems().size() > 0) {
01838:                                    break;
01839:                                }
01840:                            }
01841:                        } else {
01842:                            // there are several matches, see if there is an exact match
01843:                            for (JavaAPIListEntry e : pim.getMatchingItems()) {
01844:                                if (e.toString().equalsIgnoreCase(mask)) {
01845:                                    ++found;
01846:                                    foundItem = e;
01847:                                }
01848:                            }
01849:                        }
01850:                        if (found == 1) {
01851:                            // open unique item and return
01852:                            PlatformFactory.ONLY.openURL(pim.getCurrentItem()
01853:                                    .getURL());
01854:                        } else {
01855:                            initOpenJavadocDialog();
01856:                            _openJavadocDialog.setModel(true, pim); // ignore case
01857:                            hourglassOn();
01858:                            _openJavadocDialog.setVisible(true);
01859:                        }
01860:                    }
01861:                }
01862:            }
01863:
01864:            /** Open Javadoc page specified by the word the cursor is on. */
01865:            final Action _openJavadocUnderCursorAction = new AbstractAction(
01866:                    "Open Java API Javadoc for Word Under Cursor...") {
01867:                public void actionPerformed(ActionEvent ae) {
01868:                    _openJavadocUnderCursor();
01869:                }
01870:            };
01871:
01872:            /** Reset the position of the "Complete Word" dialog. */
01873:            public void resetCompleteWordDialogPosition() {
01874:                initCompleteWordDialog();
01875:                _completeWordDialog.setFrameState("default");
01876:                if (DrJava.getConfig().getSetting(
01877:                        DIALOG_COMPLETE_WORD_STORE_POSITION).booleanValue()) {
01878:                    DrJava.getConfig().setSetting(DIALOG_COMPLETE_WORD_STATE,
01879:                            "default");
01880:                }
01881:            }
01882:
01883:            /** Initialize dialog if necessary. */
01884:            void initCompleteWordDialog() {
01885:                if (_completeWordDialog == null) {
01886:                    PredictiveInputFrame.CloseAction<GoToFileListEntry> okAction = new PredictiveInputFrame.CloseAction<GoToFileListEntry>() {
01887:                        public Object apply(
01888:                                PredictiveInputFrame<GoToFileListEntry> p) {
01889:                            if (p.getItem() != null) {
01890:                                OpenDefinitionsDocument odd = getCurrentDefPane()
01891:                                        .getOpenDefDocument();
01892:                                try {
01893:                                    String mask = "";
01894:                                    int loc = getCurrentDefPane()
01895:                                            .getCaretPosition();
01896:                                    String s = odd.getText(
01897:                                            AbstractDJDocument.DOCSTART, loc);
01898:
01899:                                    // check that we're at the end of a word
01900:                                    if ((loc < s.length())
01901:                                            && (!Character.isWhitespace(s
01902:                                                    .charAt(loc)))
01903:                                            && ("()[]{}<>.,:;/*+-!~&|%"
01904:                                                    .indexOf(s.charAt(loc)) == -1))
01905:                                        return null;
01906:
01907:                                    // find start
01908:                                    int start = loc;
01909:                                    while (start > 0) {
01910:                                        if (!Character.isJavaIdentifierPart(s
01911:                                                .charAt(start - 1))) {
01912:                                            break;
01913:                                        }
01914:                                        --start;
01915:                                    }
01916:                                    while ((start < s.length())
01917:                                            && (!Character
01918:                                                    .isJavaIdentifierStart(s
01919:                                                            .charAt(start)))
01920:                                            && (start < loc)) {
01921:                                        ++start;
01922:                                    }
01923:
01924:                                    if (!s.substring(start, loc).equals(
01925:                                            p.getItem().toString())) {
01926:                                        odd.remove(start, loc - start);
01927:                                        odd.insertString(start, p.getItem()
01928:                                                .toString(), null);
01929:                                    }
01930:                                } catch (BadLocationException ble) { /* ignore, just don't auto-complete */
01931:                                } finally {
01932:                                    odd.releaseWriteLock();
01933:                                }
01934:                            }
01935:                            hourglassOff();
01936:                            return null;
01937:                        }
01938:                    };
01939:                    PredictiveInputFrame.CloseAction<GoToFileListEntry> cancelAction = new PredictiveInputFrame.CloseAction<GoToFileListEntry>() {
01940:                        public Object apply(
01941:                                PredictiveInputFrame<GoToFileListEntry> p) {
01942:                            hourglassOff();
01943:                            return null;
01944:                        }
01945:                    };
01946:                    java.util.ArrayList<PredictiveInputModel.MatchingStrategy<GoToFileListEntry>> strategies = new java.util.ArrayList<PredictiveInputModel.MatchingStrategy<GoToFileListEntry>>();
01947:                    strategies
01948:                            .add(new PredictiveInputModel.FragmentStrategy<GoToFileListEntry>());
01949:                    strategies
01950:                            .add(new PredictiveInputModel.PrefixStrategy<GoToFileListEntry>());
01951:                    strategies
01952:                            .add(new PredictiveInputModel.RegExStrategy<GoToFileListEntry>());
01953:                    _completeWordDialog = new PredictiveInputFrame<GoToFileListEntry>(
01954:                            MainFrame.this , "Auto-Complete Word",
01955:                            true, // force
01956:                            true, // ignore case
01957:                            null, strategies, okAction, cancelAction,
01958:                            new GoToFileListEntry(null, "dummy")) {
01959:                        public void setOwnerEnabled(boolean b) {
01960:                            if (b) {
01961:                                hourglassOff();
01962:                            } else {
01963:                                hourglassOn();
01964:                            }
01965:                        }
01966:                    };
01967:                    // putting one dummy entry in the list; it will be changed later anyway
01968:
01969:                    if (DrJava.getConfig().getSetting(
01970:                            DIALOG_COMPLETE_WORD_STORE_POSITION).booleanValue()) {
01971:                        _completeWordDialog.setFrameState(DrJava.getConfig()
01972:                                .getSetting(DIALOG_COMPLETE_WORD_STATE));
01973:                    }
01974:                }
01975:            }
01976:
01977:            /** The "Complete File" dialog instance. */
01978:            volatile PredictiveInputFrame<GoToFileListEntry> _completeFileDialog = null;
01979:            /** The "Complete Word" dialog instance. */
01980:            volatile PredictiveInputFrame<GoToFileListEntry> _completeWordDialog = null;
01981:
01982:            /** Complete the word the cursor is on. */
01983:            void _completeWordUnderCursor() {
01984:                List<OpenDefinitionsDocument> docs = _model
01985:                        .getOpenDefinitionsDocuments();
01986:                if ((docs == null) || (docs.size() == 0))
01987:                    return; // do nothing
01988:
01989:                GoToFileListEntry currentEntry = null;
01990:                ArrayList<GoToFileListEntry> list;
01991:                if ((DrJava.getConfig().getSetting(
01992:                        DIALOG_COMPLETE_SCAN_CLASS_FILES).booleanValue())
01993:                        && (_completeClassList.size() > 0)) {
01994:                    list = _completeClassList;
01995:                } else {
01996:                    list = new ArrayList<GoToFileListEntry>(docs.size());
01997:                    for (OpenDefinitionsDocument d : docs) {
01998:                        if (d.isUntitled())
01999:                            continue;
02000:                        String str = d.toString();
02001:                        if (str.lastIndexOf('.') >= 0) {
02002:                            str = str.substring(0, str.lastIndexOf('.'));
02003:                        }
02004:                        GoToFileListEntry entry = new GoToFileListEntry(d, str);
02005:                        if (d.equals(_model.getActiveDocument()))
02006:                            currentEntry = entry;
02007:                        list.add(entry);
02008:                    }
02009:                }
02010:
02011:                PredictiveInputModel<GoToFileListEntry> pim = new PredictiveInputModel<GoToFileListEntry>(
02012:                        true,
02013:                        new PredictiveInputModel.PrefixStrategy<GoToFileListEntry>(),
02014:                        list);
02015:                OpenDefinitionsDocument odd = getCurrentDefPane()
02016:                        .getOpenDefDocument();
02017:                odd.acquireWriteLock();
02018:                boolean uniqueMatch = true;
02019:                try {
02020:                    String mask = "";
02021:                    int loc = getCurrentDefPane().getCaretPosition();
02022:                    String s = odd.getText(AbstractDJDocument.DOCSTART, loc);
02023:
02024:                    // check that we're at the end of a word
02025:                    if ((loc < s.length())
02026:                            && (!Character.isWhitespace(s.charAt(loc)))
02027:                            && ("()[]{}<>.,:;/*+-!~&|%".indexOf(s.charAt(loc)) == -1))
02028:                        return;
02029:
02030:                    // find start
02031:                    int start = loc;
02032:                    while (start > 0) {
02033:                        if (!Character
02034:                                .isJavaIdentifierPart(s.charAt(start - 1))) {
02035:                            break;
02036:                        }
02037:                        --start;
02038:                    }
02039:                    while ((start < s.length())
02040:                            && (!Character.isJavaIdentifierStart(s
02041:                                    .charAt(start))) && (start < loc)) {
02042:                        ++start;
02043:                    }
02044:
02045:                    int end = loc - 1;
02046:
02047:                    if ((start >= 0) && (end < s.length())) {
02048:                        mask = s.substring(start, end + 1);
02049:                        pim.setMask(mask);
02050:                    }
02051:
02052:                    if (pim.getMatchingItems().size() == 1) {
02053:                        if (pim.getCurrentItem() != null) {
02054:                            // exactly one match, auto-complete
02055:                            if (!s.substring(start, loc).equals(
02056:                                    pim.getCurrentItem().toString())) {
02057:                                odd.remove(start, loc - start);
02058:                                odd.insertString(start, pim.getCurrentItem()
02059:                                        .toString(), null);
02060:                            }
02061:                            return;
02062:                        }
02063:                    } else {
02064:                        // not exactly one match
02065:                        uniqueMatch = false;
02066:                        pim.setMask(mask);
02067:                        if (pim.getMatchingItems().size() == 0) {
02068:                            // if there are no matches, shorten the mask until there is at least one
02069:                            mask = pim.getMask();
02070:                            while (mask.length() > 0) {
02071:                                mask = mask.substring(0, mask.length() - 1);
02072:                                pim.setMask(mask);
02073:                                if (pim.getMatchingItems().size() > 0) {
02074:                                    break;
02075:                                }
02076:                            }
02077:                        }
02078:                        initCompleteWordDialog();
02079:                        _completeWordDialog.setModel(true, pim); // ignore case
02080:                        _completeWordDialog.selectStrategy();
02081:                        if (currentEntry != null)
02082:                            _completeWordDialog.setCurrentItem(currentEntry);
02083:                        hourglassOn();
02084:                        _completeWordDialog.setVisible(true);
02085:                    }
02086:                } catch (BadLocationException ble) { /* ignore, just don't auto-complete */
02087:                } finally {
02088:                    if (uniqueMatch) {
02089:                        odd.releaseWriteLock();
02090:                    }
02091:                }
02092:            }
02093:
02094:            /** Auto-completes word the cursor is on. */
02095:            final Action completeWordUnderCursorAction = new AbstractAction(
02096:                    "Auto-Complete Word Under Cursor") {
02097:                public void actionPerformed(ActionEvent ae) {
02098:                    _completeWordUnderCursor();
02099:                }
02100:            };
02101:
02102:            /** Indents the current selection. */
02103:            private final Action _indentLinesAction = new AbstractAction(
02104:                    "Indent Line(s)") {
02105:                public void actionPerformed(ActionEvent ae) {
02106:                    _currentDefPane.endCompoundEdit();
02107:                    _currentDefPane.indent();
02108:                }
02109:            };
02110:
02111:            /** Action for commenting out a block of text using wing comments. */
02112:            private final Action _commentLinesAction = new AbstractAction(
02113:                    "Comment Line(s)") {
02114:                public void actionPerformed(ActionEvent ae) {
02115:                    hourglassOn();
02116:                    try {
02117:                        commentLines();
02118:                    } finally {
02119:                        hourglassOff();
02120:                    }
02121:                }
02122:            };
02123:
02124:            /** Action for un-commenting a block of commented text. */
02125:            private final Action _uncommentLinesAction = new AbstractAction(
02126:                    "Uncomment Line(s)") {
02127:                public void actionPerformed(ActionEvent ae) {
02128:                    hourglassOn();
02129:                    try {
02130:                        uncommentLines();
02131:                    } finally {
02132:                        hourglassOff();
02133:                    }
02134:                }
02135:            };
02136:
02137:            /** Clears DrJava's output console. */
02138:            private final Action _clearConsoleAction = new AbstractAction(
02139:                    "Clear Console") {
02140:                public void actionPerformed(ActionEvent ae) {
02141:                    _model.resetConsole();
02142:                }
02143:            };
02144:
02145:            /** Shows the DebugConsole. */
02146:            private final Action _showDebugConsoleAction = new AbstractAction(
02147:                    "Show DrJava Debug Console") {
02148:                public void actionPerformed(ActionEvent e) {
02149:                    DrJavaRoot.showDrJavaDebugConsole(MainFrame.this );
02150:                }
02151:            };
02152:
02153:            /* Enables the reset interactions command. Not currently used, since this action is NEVER disabled. */
02154:            public void enableResetInteractions() {
02155:                _resetInteractionsAction.setEnabled(true);
02156:            }
02157:
02158:            /** Resets the Interactions pane. */
02159:            private final Action _resetInteractionsAction = new AbstractAction(
02160:                    "Reset Interactions") {
02161:                public void actionPerformed(ActionEvent ae) {
02162:                    if (!DrJava.getConfig().getSetting(
02163:                            INTERACTIONS_RESET_PROMPT).booleanValue()) {
02164:                        _doResetInteractions();
02165:                        return;
02166:                    }
02167:
02168:                    String title = "Confirm Reset Interactions";
02169:                    String message = "Are you sure you want to reset the Interactions Pane?";
02170:                    ConfirmCheckBoxDialog dialog = new ConfirmCheckBoxDialog(
02171:                            MainFrame.this , title, message);
02172:                    int rc = dialog.show();
02173:                    if (rc == JOptionPane.YES_OPTION) {
02174:                        _doResetInteractions();
02175:
02176:                        if (dialog.getCheckBoxValue()) {
02177:                            DrJava.getConfig().setSetting(
02178:                                    INTERACTIONS_RESET_PROMPT, Boolean.FALSE);
02179:                        }
02180:                    }
02181:                }
02182:            };
02183:
02184:            private void _doResetInteractions() {
02185:                _tabbedPane.setSelectedIndex(INTERACTIONS_TAB);
02186:                updateStatusField("Resetting Interactions");
02187:
02188:                _model.getInteractionsModel().enableRestart();
02189:                // Lots of work, so use another thread
02190:                new Thread(new Runnable() {
02191:                    public void run() {
02192:                        _model.resetInteractions(_model.getWorkingDirectory(),
02193:                                true);
02194:                    }
02195:                }).start();
02196:            }
02197:
02198:            /** Defines actions that displays the interactions classpath. */
02199:            private final Action _viewInteractionsClassPathAction = new AbstractAction(
02200:                    "View Interactions Classpath...") {
02201:                public void actionPerformed(ActionEvent e) {
02202:                    viewInteractionsClassPath();
02203:                }
02204:            };
02205:
02206:            /** Displays the interactions classpath. */
02207:            public void viewInteractionsClassPath() {
02208:                String cp = IterUtil.multilineToString(_model
02209:                        .getInteractionsClassPath());
02210:                new DrJavaScrollableDialog(this , "Interactions Classpath",
02211:                        "Current Interpreter Classpath", cp).show();
02212:            }
02213:
02214:            /** Shows the user documentation. */
02215:            private final Action _helpAction = new AbstractAction("Help") {
02216:                public void actionPerformed(ActionEvent ae) {
02217:                    // Create frame if we haven't yet
02218:                    //      if (_helpFrame == null) {
02219:                    //        _helpFrame = new HelpFrame();
02220:                    //      }
02221:                    _helpFrame.setVisible(true);
02222:                }
02223:            };
02224:
02225:            /** Shows the quick start documentation. */
02226:            private final Action _quickStartAction = new AbstractAction(
02227:                    "QuickStart") {
02228:                public void actionPerformed(ActionEvent ae) {
02229:                    // Create frame if we haven't yet
02230:                    //      if (_quickStartFrame == null) {
02231:                    //        _quickStartFrame = new QuickStartFrame();
02232:                    //      }
02233:                    _quickStartFrame.setVisible(true);
02234:                }
02235:            };
02236:
02237:            /** Pops up an info dialog. */
02238:            private final Action _aboutAction = new AbstractAction("About") {
02239:                public void actionPerformed(ActionEvent ae) {
02240:                    // Create dialog if we haven't yet
02241:                    //      if (_aboutDialog == null) _aboutDialog = new AboutDialog(MainFrame.this);
02242:                    Point p = MainFrame.this .getLocation();
02243:                    _aboutDialog.setVisible(true);
02244:                    //      _aboutDialog.setLocation(p.x+(MainFrame.this.getWidth() - _aboutDialog.getWidth())/2, 
02245:                    //      p.y+(MainFrame.this.getHeight()-_aboutDialog.getHeight())/2);
02246:
02247:                }
02248:            };
02249:
02250:            /** Pops up the DrJava errors dialog. */
02251:            private final Action _errorsAction = new AbstractAction(
02252:                    "DrJava Errors") {
02253:                public void actionPerformed(ActionEvent ae) {
02254:                    setPopupLoc(DrJavaErrorWindow.singleton());
02255:                    DrJavaErrorWindow.singleton().setVisible(true);
02256:                }
02257:            };
02258:
02259:            /** Switches to next document. */
02260:            private final Action _switchToNextAction = new AbstractAction(
02261:                    "Next Document") {
02262:                public void actionPerformed(ActionEvent ae) {
02263:                    this .setEnabled(false);
02264:                    if (_docSplitPane.getDividerLocation() < _docSplitPane
02265:                            .getMinimumDividerLocation())
02266:                        _docSplitPane.setDividerLocation(DrJava.getConfig()
02267:                                .getSetting(DOC_LIST_WIDTH).intValue());
02268:                    //disables switching documents while the next one is opening up, in order to prevent out of control switching
02269:                    //      addToBrowserHistory();
02270:                    _model.setActiveNextDocument();
02271:                    _findReplace.updateFirstDocInSearch();
02272:                    this .setEnabled(true);
02273:                    //      // defer executing this code until after active document switch (if any) is complete
02274:                    //      EventQueue.invokeLater(new Runnable() { public void run() { addToBrowserHistory(); } });
02275:                }
02276:            };
02277:
02278:            /** Switches to previous document. */
02279:            private final Action _switchToPrevAction = new AbstractAction(
02280:                    "Previous Document") {
02281:                public void actionPerformed(ActionEvent ae) {
02282:                    this .setEnabled(false);
02283:                    if (_docSplitPane.getDividerLocation() < _docSplitPane
02284:                            .getMinimumDividerLocation())
02285:                        _docSplitPane.setDividerLocation(DrJava.getConfig()
02286:                                .getSetting(DOC_LIST_WIDTH).intValue());
02287:                    //      addToBrowserHistory();
02288:                    _model.setActivePreviousDocument();
02289:                    _findReplace.updateFirstDocInSearch();
02290:                    this .setEnabled(true);
02291:                    //      // defer executing this code until after active document switch (if any) is complete
02292:                    //      EventQueue.invokeLater(new Runnable() { public void run() { addToBrowserHistory(); } });
02293:                }
02294:            };
02295:
02296:            /** Switches focus to next pane. */
02297:            private final Action _switchToNextPaneAction = new AbstractAction(
02298:                    "Next Pane") {
02299:                public void actionPerformed(ActionEvent ae) {
02300:                    if (_mainSplit.getDividerLocation() > _mainSplit
02301:                            .getMaximumDividerLocation())
02302:                        _mainSplit.resetToPreferredSizes();
02303:                    this .setEnabled(false);
02304:                    _switchPaneFocus(true);
02305:                    this .setEnabled(true);
02306:                }
02307:            };
02308:
02309:            /** Browse back in the browser history. */
02310:            private final Action _browseBackAction = new AbstractAction(
02311:                    "Browse Back") {
02312:                public void actionPerformed(ActionEvent ae) {
02313:                    updateStatusField("Browsing Back");
02314:                    this .setEnabled(false);
02315:                    if (_docSplitPane.getDividerLocation() < _docSplitPane
02316:                            .getMinimumDividerLocation())
02317:                        _docSplitPane.setDividerLocation(DrJava.getConfig()
02318:                                .getSetting(DOC_LIST_WIDTH).intValue());
02319:                    //disables switching documents while the next one is opening up, in order to prevent out of control switching
02320:
02321:                    RegionManager rm = _model.getBrowserHistoryManager();
02322:
02323:                    // add current location to history
02324:                    addToBrowserHistory();
02325:
02326:                    // then move back    
02327:                    DocumentRegion r = rm.prevCurrentRegion();
02328:                    scrollToDocumentAndOffset(r.getDocument(), r
02329:                            .getStartOffset(), false, false);
02330:
02331:                    this .setEnabled(true);
02332:                }
02333:            };
02334:
02335:            /** Browse forward in the browser history. */
02336:            private final Action _browseForwardAction = new AbstractAction(
02337:                    "Browse Forward") {
02338:                public void actionPerformed(ActionEvent ae) {
02339:                    updateStatusField("Browsing Forward");
02340:                    this .setEnabled(false);
02341:                    if (_docSplitPane.getDividerLocation() < _docSplitPane
02342:                            .getMinimumDividerLocation())
02343:                        _docSplitPane.setDividerLocation(DrJava.getConfig()
02344:                                .getSetting(DOC_LIST_WIDTH).intValue());
02345:                    //disables switching documents while the next one is opening up, in order to prevent out of control switching
02346:
02347:                    RegionManager rm = _model.getBrowserHistoryManager();
02348:
02349:                    // add current location to history
02350:                    addToBrowserHistory();
02351:
02352:                    // then move forward
02353:                    DocumentRegion r = rm.nextCurrentRegion();
02354:                    scrollToDocumentAndOffset(r.getDocument(), r
02355:                            .getStartOffset(), false, false);
02356:
02357:                    this .setEnabled(true);
02358:                }
02359:            };
02360:
02361:            /** Switches focus to previous pane. */
02362:            private final Action _switchToPreviousPaneAction = new AbstractAction(
02363:                    "Previous Pane") {
02364:                public void actionPerformed(ActionEvent ae) {
02365:                    if (_mainSplit.getDividerLocation() > _mainSplit
02366:                            .getMaximumDividerLocation())
02367:                        _mainSplit.resetToPreferredSizes();
02368:                    this .setEnabled(false);
02369:                    _switchPaneFocus(false);
02370:                    this .setEnabled(true);
02371:                }
02372:            };
02373:
02374:            /** Go to the closing brace.  ReadLock omitted because it only runs on definitions documents in the event thread. */
02375:            private final Action _gotoClosingBraceAction = new AbstractAction(
02376:                    "Go to Closing Brace") {
02377:                public void actionPerformed(ActionEvent ae) {
02378:                    OpenDefinitionsDocument odd = getCurrentDefPane()
02379:                            .getOpenDefDocument();
02380:                    //        odd.acquireReadLock();
02381:                    try {
02382:                        int pos = odd.findNextEnclosingBrace(
02383:                                getCurrentDefPane().getCaretPosition(), '{',
02384:                                '}');
02385:                        if (pos != AbstractDJDocument.ERROR_INDEX) {
02386:                            getCurrentDefPane().setCaretPosition(pos);
02387:                        }
02388:                    } catch (BadLocationException ble) { /* just ignore and don't move */
02389:                    }
02390:                    //        finally { odd.releaseReadLock(); }
02391:                }
02392:            };
02393:
02394:            /** Go to the opening brace.  ReadLock omitted because it only runs on definitions documents in the event thread. */
02395:            private final Action _gotoOpeningBraceAction = new AbstractAction(
02396:                    "Go to Opening Brace") {
02397:                public void actionPerformed(ActionEvent ae) {
02398:                    OpenDefinitionsDocument odd = getCurrentDefPane()
02399:                            .getOpenDefDocument();
02400:                    //        odd.acquireReadLock();
02401:                    try {
02402:                        int pos = odd.findPrevEnclosingBrace(
02403:                                getCurrentDefPane().getCaretPosition(), '{',
02404:                                '}');
02405:                        if (pos != AbstractDJDocument.ERROR_INDEX) {
02406:                            getCurrentDefPane().setCaretPosition(pos);
02407:                        }
02408:                    } catch (BadLocationException ble) { /* just ignore and don't move */
02409:                    }
02410:                    //        finally { odd.releaseReadLock(); }
02411:                }
02412:            };
02413:
02414:            /** This takes a component and gives it focus, showing it if it's a tab. The interactionsPane and consolePane
02415:             *  are wrapped in scrollpanes, so we have to specifically check for those and unwrap them.
02416:             *  @param c the pane to switch focus to
02417:             */
02418:            private void _switchToPane(Component c) {
02419:                Component newC = c;
02420:                //    if (c == _interactionsContainer) newC = _interactionsPane;
02421:                //    if (c == _consoleScroll) newC = _consolePane;
02422:                showTab(newC);
02423:            }
02424:
02425:            /** This method allows the user to cycle through the definitions pane and all of the open tabs.
02426:             *  @param next true if we want to go to the next pane, false if the previous.
02427:             */
02428:            private void _switchPaneFocus(boolean next) {
02429:                int numTabs = _tabbedPane.getTabCount();
02430:
02431:                /* If next, then we go to the next tab */
02432:                if (next)
02433:                    _switchToPane(_tabbedPane.getComponentAt((numTabs
02434:                            + _tabbedPane.getSelectedIndex() + 1)
02435:                            % numTabs));
02436:                else
02437:                    _switchToPane(_tabbedPane.getComponentAt((numTabs
02438:                            + _tabbedPane.getSelectedIndex() - 1)
02439:                            % numTabs));
02440:            }
02441:
02442:            /** Calls the ConfigFrame to edit preferences */
02443:
02444:            private final Action _editPreferencesAction = new AbstractAction(
02445:                    "Preferences ...") {
02446:
02447:                public void actionPerformed(ActionEvent ae) {
02448:                    // Create frame if we haven't yet
02449:                    //      if (_configFrame == null) {
02450:                    //        _configFrame = new ConfigFrame(MainFrame.this);
02451:                    //      }
02452:                    _configFrame.setUp();
02453:                    setPopupLoc(_configFrame);
02454:                    _configFrame.setVisible(true);
02455:                    _configFrame.toFront();
02456:                }
02457:            };
02458:
02459:            private volatile AbstractAction _projectPropertiesAction = new AbstractAction(
02460:                    "Project Properties") {
02461:                public void actionPerformed(ActionEvent ae) {
02462:                    _editProject();
02463:                }
02464:            };
02465:
02466:            /** Enables the debugger */
02467:            private final Action _toggleDebuggerAction = new AbstractAction(
02468:                    "Debug Mode") {
02469:                public void actionPerformed(ActionEvent ae) {
02470:                    this .setEnabled(false);
02471:                    debuggerToggle();
02472:                    this .setEnabled(true);
02473:                }
02474:            };
02475:
02476:            /** Resumes debugging */
02477:            private final Action _resumeDebugAction = new AbstractAction(
02478:                    "Resume Debugger") {
02479:                public void actionPerformed(ActionEvent ae) {
02480:                    try {
02481:                        debuggerResume();
02482:                    } catch (DebugException de) {
02483:                        _showDebugError(de);
02484:                    }
02485:                }
02486:            };
02487:
02488:            /** Steps into the next method call */
02489:            private final Action _stepIntoDebugAction = new AbstractAction(
02490:                    "Step Into") {
02491:                public void actionPerformed(ActionEvent ae) {
02492:                    debuggerStep(Debugger.StepType.STEP_INTO);
02493:                }
02494:            };
02495:
02496:            /** Runs the next line, without stepping into methods */
02497:            private final Action _stepOverDebugAction = new AbstractAction(
02498:                    "Step Over") {
02499:                public void actionPerformed(ActionEvent ae) {
02500:                    debuggerStep(Debugger.StepType.STEP_OVER);
02501:                }
02502:            };
02503:
02504:            /** Steps out of the next method call */
02505:            private final Action _stepOutDebugAction = new AbstractAction(
02506:                    "Step Out") {
02507:                public void actionPerformed(ActionEvent ae) {
02508:                    debuggerStep(Debugger.StepType.STEP_OUT);
02509:                }
02510:            };
02511:
02512:            /** Suspend debugging */
02513:            /*private Action _suspendDebugAction =
02514:             new AbstractAction("Suspend Debugger")
02515:             {
02516:             public void actionPerformed(ActionEvent ae) {
02517:             _debugSuspend();
02518:             }
02519:             };*/
02520:
02521:            /** Toggles a breakpoint on the current line */
02522:            final Action _toggleBreakpointAction = new AbstractAction(
02523:                    "Toggle Breakpoint on Current Line") {
02524:                public void actionPerformed(ActionEvent ae) {
02525:                    debuggerToggleBreakpoint();
02526:                }
02527:            };
02528:
02529:            /** Clears all breakpoints */
02530:            private final Action _clearAllBreakpointsAction = new AbstractAction(
02531:                    "Clear All Breakpoints") {
02532:                public void actionPerformed(ActionEvent ae) {
02533:                    debuggerClearAllBreakpoints();
02534:                }
02535:            };
02536:
02537:            /** Shows the breakpoints tab. */
02538:            private final Action _breakpointsPanelAction = new AbstractAction(
02539:                    "Breakpoints") {
02540:                public void actionPerformed(ActionEvent ae) {
02541:                    if (_mainSplit.getDividerLocation() > _mainSplit
02542:                            .getMaximumDividerLocation())
02543:                        _mainSplit.resetToPreferredSizes();
02544:                    if (!_breakpointsPanel.isDisplayed()) {
02545:                        showTab(_breakpointsPanel);
02546:                    }
02547:                    _breakpointsPanel.setVisible(true);
02548:                    _tabbedPane.setSelectedComponent(_breakpointsPanel);
02549:                    // Use SwingUtilties.invokeLater to ensure that focus is set AFTER the _breakpointsPanel has been selected
02550:                    EventQueue.invokeLater(new Runnable() {
02551:                        public void run() {
02552:                            _breakpointsPanel.requestFocusInWindow();
02553:                        }
02554:                    });
02555:                }
02556:            };
02557:
02558:            /** Shows the bookmarks tab. */
02559:            private final Action _bookmarksPanelAction = new AbstractAction(
02560:                    "Bookmarks") {
02561:                public void actionPerformed(ActionEvent ae) {
02562:                    if (_mainSplit.getDividerLocation() > _mainSplit
02563:                            .getMaximumDividerLocation())
02564:                        _mainSplit.resetToPreferredSizes();
02565:                    if (!_bookmarksPanel.isDisplayed()) {
02566:                        showTab(_bookmarksPanel);
02567:                    }
02568:                    _bookmarksPanel.setVisible(true);
02569:                    _tabbedPane.setSelectedComponent(_bookmarksPanel);
02570:                    // Use SwingUtilties.invokeLater to ensure that focus is set AFTER the _bookmarksPanel has been selected
02571:                    EventQueue.invokeLater(new Runnable() {
02572:                        public void run() {
02573:                            _bookmarksPanel.requestFocusInWindow();
02574:                        }
02575:                    });
02576:                }
02577:            };
02578:
02579:            /** Toggles a bookmark. */
02580:            private final Action _toggleBookmarkAction = new AbstractAction(
02581:                    "Toggle Bookmark") {
02582:                public void actionPerformed(ActionEvent ae) {
02583:                    toggleBookmark();
02584:                }
02585:            };
02586:
02587:            /** Toggle a bookmark. */
02588:            public void toggleBookmark() {
02589:                assert EventQueue.isDispatchThread();
02590:                addToBrowserHistory();
02591:                final OpenDefinitionsDocument doc = _model.getActiveDocument();
02592:
02593:                int startSel = _currentDefPane.getSelectionStart();
02594:                int endSel = _currentDefPane.getSelectionEnd();
02595:                //    doc.acquireReadLock();
02596:                try {
02597:                    if (startSel > endSel) {
02598:                        int temp = startSel;
02599:                        startSel = endSel;
02600:                        endSel = temp;
02601:                    } else if (startSel == endSel) {
02602:                        // nothing selected
02603:                        endSel = doc.getLineEndPos(startSel);
02604:                        startSel = doc.getLineStartPos(startSel);
02605:                    }
02606:                    DocumentRegion r = _model.getBookmarkManager()
02607:                            .getRegionOverlapping(doc, startSel, endSel);
02608:                    if (r == null) {
02609:                        final Position startPos = doc.createPosition(startSel);
02610:                        final Position endPos = doc.createPosition(endSel);
02611:                        SimpleDocumentRegion newR = new SimpleDocumentRegion(
02612:                                doc, doc.getFile(), startPos.getOffset(),
02613:                                endPos.getOffset());
02614:                        _model.getBookmarkManager().addRegion(newR);
02615:                    } else {
02616:                        _model.getBookmarkManager().removeRegion(r);
02617:                    }
02618:                } catch (FileMovedException fme) {
02619:                    throw new UnexpectedException(fme);
02620:                } catch (BadLocationException ble) {
02621:                    throw new UnexpectedException(ble);
02622:                }
02623:                //    finally { doc.releaseReadLock(); }
02624:            }
02625:
02626:            /** Add the current location to the browser history. */
02627:            public void addToBrowserHistory() {
02628:                _model.addToBrowserHistory();
02629:            }
02630:
02631:            /** Create a new find results tab.
02632:             * @param rm the region manager that will contain the regions
02633:             * @param title the title for the panel
02634:             * @return new find results tab. */
02635:            public FindResultsPanel createFindResultsPanel(
02636:                    final RegionManager<MovingDocumentRegion> rm, String title) {
02637:                final FindResultsPanel panel = new FindResultsPanel(this , rm,
02638:                        title);
02639:                final Hashtable<MovingDocumentRegion, HighlightManager.HighlightInfo> highlights = new Hashtable<MovingDocumentRegion, HighlightManager.HighlightInfo>();
02640:                Pair<FindResultsPanel, Hashtable<MovingDocumentRegion, HighlightManager.HighlightInfo>> pair = new Pair<FindResultsPanel, Hashtable<MovingDocumentRegion, HighlightManager.HighlightInfo>>(
02641:                        panel, highlights);
02642:                _findResults.add(pair);
02643:
02644:                // hook highlighting listener to find results manager
02645:                rm
02646:                        .addListener(new RegionManagerListener<MovingDocumentRegion>() {
02647:                            public void regionAdded(MovingDocumentRegion r,
02648:                                    int index) {
02649:                                DefinitionsPane bpPane = getDefPaneGivenODD(r
02650:                                        .getDocument());
02651:                                highlights.put(r, bpPane.getHighlightManager()
02652:                                        .addHighlight(r.getStartOffset(),
02653:                                                r.getEndOffset(),
02654:                                                panel.getSelectedPainter()));
02655:                            }
02656:
02657:                            public void regionChanged(MovingDocumentRegion r,
02658:                                    int index) {
02659:                                regionRemoved(r);
02660:                                regionAdded(r, index);
02661:                            }
02662:
02663:                            public void regionRemoved(MovingDocumentRegion r) {
02664:                                HighlightManager.HighlightInfo highlight = highlights
02665:                                        .get(r);
02666:                                if (highlight != null)
02667:                                    highlight.remove();
02668:                                highlights.remove(r);
02669:                                // close the panel when all regions have been removed.
02670:                                if (rm.getRegions().size() == 0) {
02671:                                    panel._close();
02672:                                }
02673:                            }
02674:                        });
02675:
02676:                _tabs.addLast(panel);
02677:                panel.getMainPanel().addFocusListener(new FocusAdapter() {
02678:                    public void focusGained(FocusEvent e) {
02679:                        _lastFocusOwner = panel;
02680:                    }
02681:                });
02682:
02683:                return panel;
02684:            }
02685:
02686:            /** Shows a find results tab. Only runs in event thread. */
02687:            public void showFindResultsPanel(final FindResultsPanel panel) {
02688:                assert EventQueue.isDispatchThread();
02689:                if (_mainSplit.getDividerLocation() > _mainSplit
02690:                        .getMaximumDividerLocation())
02691:                    _mainSplit.resetToPreferredSizes();
02692:                if (!panel.isDisplayed())
02693:                    showTab(panel);
02694:                panel.setVisible(true);
02695:                _tabbedPane.setSelectedComponent(panel);
02696:                // Use SwingUtilties.invokeLater to ensure that focus is set AFTER the findResultsPanel has been selected
02697:                EventQueue.invokeLater(new Runnable() {
02698:                    public void run() {
02699:                        panel.requestFocusInWindow();
02700:                    }
02701:                });
02702:            };
02703:
02704:            /** Cuts from the caret to the end of the current line to the clipboard. */
02705:            protected final Action _cutLineAction = new AbstractAction(
02706:                    "Cut Line") {
02707:                public void actionPerformed(ActionEvent ae) {
02708:                    ActionMap _actionMap = _currentDefPane.getActionMap();
02709:                    int oldCol = _model.getActiveDocument().getCurrentCol();
02710:                    _actionMap.get(DefaultEditorKit.selectionEndLineAction)
02711:                            .actionPerformed(ae);
02712:                    // if oldCol is equal to the current column, then selectionEndLine did
02713:                    // nothing, so we're at the end of the line and should remove the newline
02714:                    // character
02715:                    if (oldCol == _model.getActiveDocument().getCurrentCol()) {
02716:                        // Puts newline character on the clipboard also, not just content as before.
02717:                        _actionMap.get(DefaultEditorKit.selectionForwardAction)
02718:                                .actionPerformed(ae);
02719:                        cutAction.actionPerformed(ae);
02720:                    } else
02721:                        cutAction.actionPerformed(ae);
02722:                }
02723:            };
02724:
02725:            /** Deletes text from the caret to the end of the current line. */
02726:            protected final Action _clearLineAction = new AbstractAction(
02727:                    "Clear Line") {
02728:                public void actionPerformed(ActionEvent ae) {
02729:                    ActionMap _actionMap = _currentDefPane.getActionMap();
02730:                    _actionMap.get(DefaultEditorKit.selectionEndLineAction)
02731:                            .actionPerformed(ae);
02732:                    _actionMap.get(DefaultEditorKit.deleteNextCharAction)
02733:                            .actionPerformed(ae);
02734:                }
02735:            };
02736:
02737:            /** Moves the caret to the "intelligent" beginning of the line.
02738:             *  @see #_getBeginLinePos
02739:             */
02740:            private final Action _beginLineAction = new AbstractAction(
02741:                    "Begin Line") {
02742:                public void actionPerformed(ActionEvent ae) {
02743:                    int beginLinePos = _getBeginLinePos();
02744:                    _currentDefPane.setCaretPosition(beginLinePos);
02745:                }
02746:            };
02747:
02748:            /** Selects to the "intelligent" beginning of the line.
02749:             *  @see #_getBeginLinePos
02750:             */
02751:            private final Action _selectionBeginLineAction = new AbstractAction(
02752:                    "Select to Beginning of Line") {
02753:                public void actionPerformed(ActionEvent ae) {
02754:                    int beginLinePos = _getBeginLinePos();
02755:                    _currentDefPane.moveCaretPosition(beginLinePos);
02756:                }
02757:            };
02758:
02759:            /** Returns the "intelligent" beginning of line.  If the caret is to fhe right of the first non-whitespace character,
02760:             * the position of the first non-whitespace character is returned.  If the caret is on or to the left of the first 
02761:             * non-whitespace character, the beginning of the line is returned.
02762:             */
02763:            private int _getBeginLinePos() {
02764:                try {
02765:                    int currPos = _currentDefPane.getCaretPosition();
02766:                    OpenDefinitionsDocument openDoc = _model
02767:                            .getActiveDocument();
02768:                    openDoc.setCurrentLocation(currPos);
02769:                    return openDoc.getIntelligentBeginLinePos(currPos);
02770:                } catch (BadLocationException ble) {
02771:                    // Shouldn't happen: we're using a legal position
02772:                    throw new UnexpectedException(ble);
02773:                }
02774:            }
02775:
02776:            private final FileOpenSelector _interactionsHistoryFileSelector = new FileOpenSelector() {
02777:                public File[] getFiles() throws OperationCanceledException {
02778:                    return getOpenFiles(_interactionsHistoryChooser);
02779:                }
02780:            };
02781:
02782:            /** Interprets the commands in a file in the interactions window. */
02783:            private final Action _executeHistoryAction = new AbstractAction(
02784:                    "Execute Interactions History...") {
02785:                public void actionPerformed(ActionEvent ae) {
02786:                    // Show interactions tab
02787:                    _tabbedPane.setSelectedIndex(INTERACTIONS_TAB);
02788:
02789:                    _interactionsHistoryChooser
02790:                            .setDialogTitle("Execute Interactions History");
02791:                    try {
02792:                        _model.loadHistory(_interactionsHistoryFileSelector);
02793:                    } catch (FileNotFoundException fnf) {
02794:                        _showFileNotFoundError(fnf);
02795:                    } catch (IOException ioe) {
02796:                        _showIOError(ioe);
02797:                    }
02798:                    _interactionsPane.requestFocusInWindow();
02799:                }
02800:            };
02801:
02802:            /** Closes the currently executing interactions script, if there is one. */
02803:            private void _closeInteractionsScript() {
02804:                if (_interactionsScriptController != null) {
02805:                    _interactionsContainer.remove(_interactionsScriptPane);
02806:                    _interactionsScriptController = null;
02807:                    _interactionsScriptPane = null;
02808:                    _tabbedPane.invalidate();
02809:                    _tabbedPane.repaint();
02810:                }
02811:            }
02812:
02813:            /** Action to load an interactions history as a replayable script. */
02814:            private final Action _loadHistoryScriptAction = new AbstractAction(
02815:                    "Load Interactions History as Script...") {
02816:                public void actionPerformed(ActionEvent e) {
02817:                    try {
02818:                        _interactionsHistoryChooser
02819:                                .setDialogTitle("Load Interactions History");
02820:                        InteractionsScriptModel ism = _model
02821:                                .loadHistoryAsScript(_interactionsHistoryFileSelector);
02822:                        _interactionsScriptController = new InteractionsScriptController(
02823:                                ism, new AbstractAction("Close") {
02824:                                    public void actionPerformed(ActionEvent e) {
02825:                                        _closeInteractionsScript();
02826:                                        _interactionsPane
02827:                                                .requestFocusInWindow();
02828:                                    }
02829:                                }, _interactionsPane);
02830:                        _interactionsScriptPane = _interactionsScriptController
02831:                                .getPane();
02832:                        _interactionsContainer.add(_interactionsScriptPane,
02833:                                BorderLayout.EAST);
02834:                        _tabbedPane.invalidate();
02835:                        _tabbedPane.repaint();
02836:                    } catch (FileNotFoundException fnf) {
02837:                        _showFileNotFoundError(fnf);
02838:                    } catch (IOException ioe) {
02839:                        _showIOError(ioe);
02840:                    } catch (OperationCanceledException oce) {
02841:                    }
02842:                }
02843:            };
02844:
02845:            /** Save the commands in the interactions window's history to a file */
02846:            private final Action _saveHistoryAction = new AbstractAction(
02847:                    "Save Interactions History...") {
02848:                public void actionPerformed(ActionEvent ae) {
02849:                    String[] options = { "Yes", "No", "Cancel" };
02850:                    int resp = JOptionPane.showOptionDialog(MainFrame.this ,
02851:                            "Edit interactions history before saving?",
02852:                            "Edit History?", JOptionPane.YES_NO_CANCEL_OPTION,
02853:                            JOptionPane.QUESTION_MESSAGE, null, options,
02854:                            options[1]);
02855:                    // Cancel
02856:                    if (resp == 2 || resp == JOptionPane.CLOSED_OPTION)
02857:                        return;
02858:
02859:                    String history = _model.getHistoryAsStringWithSemicolons();
02860:
02861:                    // Edit the history
02862:                    if (resp == 0)
02863:                        history = (new HistorySaveDialog(MainFrame.this ))
02864:                                .editHistory(history);
02865:                    if (history == null)
02866:                        return; // save cancelled
02867:
02868:                    _interactionsHistoryChooser
02869:                            .setDialogTitle("Save Interactions History");
02870:                    FileSaveSelector selector = new FileSaveSelector() {
02871:                        public File getFile() throws OperationCanceledException {
02872:                            // Don't try to set the fileName with getSaveFile;
02873:                            // just display the dialog and get file with getChosenFile, otherwise
02874:                            // the suggested file name will be whatever document is open.
02875:                            // ED (8.14.03): Had to add this next block of code from getSaveFile to
02876:                            // fix bug #788311 "NullPointer when saving history"
02877:                            File selection = _interactionsHistoryChooser
02878:                                    .getSelectedFile();//_saveChooser.getSelectedFile();
02879:                            if (selection != null) {
02880:                                _interactionsHistoryChooser
02881:                                        .setSelectedFile(selection
02882:                                                .getParentFile());
02883:                                _interactionsHistoryChooser
02884:                                        .setSelectedFile(selection);
02885:                                _interactionsHistoryChooser
02886:                                        .setSelectedFile(null);
02887:                            }
02888:                            //          return getSaveFile(_interactionsHistoryChooser);
02889:                            int rc = _interactionsHistoryChooser
02890:                                    .showSaveDialog(MainFrame.this );
02891:                            File c = getChosenFile(_interactionsHistoryChooser,
02892:                                    rc);
02893:                            //Moved from history itself to here to account for bug #989232, non-existant default
02894:                            //history file found
02895:                            if (c.getName().indexOf('.') == -1)
02896:                                c = new File(
02897:                                        c.getAbsolutePath()
02898:                                                + "."
02899:                                                + InteractionsHistoryFilter.HIST_EXTENSION);
02900:                            _interactionsHistoryChooser.setSelectedFile(c);
02901:                            return c;
02902:                        }
02903:
02904:                        public boolean warnFileOpen(File f) {
02905:                            return true;
02906:                        }
02907:
02908:                        public boolean verifyOverwrite() {
02909:                            return _verifyOverwrite();
02910:                        }
02911:
02912:                        public boolean shouldSaveAfterFileMoved(
02913:                                OpenDefinitionsDocument doc, File oldFile) {
02914:                            return true;
02915:                        }
02916:                    };
02917:
02918:                    try {
02919:                        _model.saveHistory(selector, history);
02920:                    } catch (IOException ioe) {
02921:                        _showIOError(new IOException(
02922:                                "An error occured writing the history to a file"));
02923:                    }
02924:                    _interactionsPane.requestFocusInWindow();
02925:                }
02926:            };
02927:
02928:            /** Clears the commands in the interaction history. */
02929:            private final Action _clearHistoryAction = new AbstractAction(
02930:                    "Clear Interactions History") {
02931:                public void actionPerformed(ActionEvent ae) {
02932:                    _model.clearHistory();
02933:                    _interactionsPane.requestFocusInWindow();
02934:                }
02935:            };
02936:
02937:            /** How DrJava responds to window events. */
02938:            private final WindowListener _windowCloseListener = new WindowAdapter() {
02939:                public void windowActivated(WindowEvent ev) {
02940:                }
02941:
02942:                public void windowClosed(WindowEvent ev) {
02943:                }
02944:
02945:                public void windowClosing(WindowEvent ev) {
02946:                    _quit();
02947:                }
02948:
02949:                public void windowDeactivated(WindowEvent ev) {
02950:                }
02951:
02952:                public void windowDeiconified(WindowEvent ev) {
02953:                    try {
02954:                        _model.getActiveDocument().revertIfModifiedOnDisk();
02955:                    } catch (FileMovedException fme) {
02956:                        _showFileMovedError(fme);
02957:                    } catch (IOException e) {
02958:                        _showIOError(e);
02959:                    }
02960:                }
02961:
02962:                public void windowIconified(WindowEvent ev) {
02963:                }
02964:
02965:                public void windowOpened(WindowEvent ev) {
02966:                    _currentDefPane.requestFocusInWindow();
02967:                }
02968:            };
02969:
02970:            private final MouseListener _resetFindReplaceListener = new MouseListener() {
02971:                public void mouseClicked(MouseEvent e) {
02972:                }
02973:
02974:                public void mousePressed(MouseEvent e) {
02975:                }
02976:
02977:                //as mouseReleased event so that it happens after the document has been set in the model and defPane
02978:                public void mouseReleased(MouseEvent e) {
02979:                    _findReplace.updateFirstDocInSearch();
02980:                }
02981:
02982:                public void mouseEntered(MouseEvent e) {
02983:                }
02984:
02985:                public void mouseExited(MouseEvent e) {
02986:                }
02987:            };
02988:
02989:            // ------------- File Display Managers for File Icons ------------
02990:
02991:            private static final DJFileDisplayManager _djFileDisplayManager20;
02992:            private static final DJFileDisplayManager _djFileDisplayManager30;
02993:            private static final OddDisplayManager _oddDisplayManager20;
02994:            private static final OddDisplayManager _oddDisplayManager30;
02995:            private static final Icon _djProjectIcon;
02996:
02997:            static {
02998:                Icon java, dj0, dj1, dj2, other, star, jup, juf;
02999:
03000:                java = MainFrame.getIcon("JavaIcon20.gif");
03001:                dj0 = MainFrame.getIcon("ElementaryIcon20.gif");
03002:                dj1 = MainFrame.getIcon("IntermediateIcon20.gif");
03003:                dj2 = MainFrame.getIcon("AdvancedIcon20.gif");
03004:                other = MainFrame.getIcon("OtherIcon20.gif");
03005:                _djFileDisplayManager20 = new DJFileDisplayManager(java, dj0,
03006:                        dj1, dj2, other);
03007:
03008:                java = MainFrame.getIcon("JavaIcon30.gif");
03009:                dj0 = MainFrame.getIcon("ElementaryIcon30.gif");
03010:                dj1 = MainFrame.getIcon("IntermediateIcon30.gif");
03011:                dj2 = MainFrame.getIcon("AdvancedIcon30.gif");
03012:                other = MainFrame.getIcon("OtherIcon30.gif");
03013:                _djFileDisplayManager30 = new DJFileDisplayManager(java, dj0,
03014:                        dj1, dj2, other);
03015:
03016:                star = MainFrame.getIcon("ModStar20.gif");
03017:                jup = MainFrame.getIcon("JUnitPass20.gif");
03018:                juf = MainFrame.getIcon("JUnitFail20.gif");
03019:                _oddDisplayManager20 = new OddDisplayManager(
03020:                        _djFileDisplayManager20, star, jup, juf);
03021:
03022:                star = MainFrame.getIcon("ModStar30.gif");
03023:                jup = MainFrame.getIcon("JUnitPass30.gif");
03024:                juf = MainFrame.getIcon("JUnitFail30.gif");
03025:                _oddDisplayManager30 = new OddDisplayManager(
03026:                        _djFileDisplayManager30, star, jup, juf);
03027:
03028:                _djProjectIcon = MainFrame.getIcon("ProjectIcon.gif");
03029:            }
03030:
03031:            /** This manager is meant to retrieve the correct icons for the given filename. The only files recognized 
03032:             *  are the files obviously listed below in the function (.java, .dj0, .dj1, .dj2). The icons that represent 
03033:             *  each filetype are given into the managers constructor upon instantiation.  This class is static since
03034:             *  it currently does not depend of the main frame for information.
03035:             */
03036:            private static class DJFileDisplayManager extends
03037:                    DefaultFileDisplayManager {
03038:                private final Icon _java;
03039:                private final Icon _dj0;
03040:                private final Icon _dj1;
03041:                private final Icon _dj2;
03042:                private final Icon _other;
03043:
03044:                public DJFileDisplayManager(Icon java, Icon dj0, Icon dj1,
03045:                        Icon dj2, Icon other) {
03046:                    _java = java;
03047:                    _dj0 = dj0;
03048:                    _dj1 = dj1;
03049:                    _dj2 = dj2;
03050:                    _other = other;
03051:                }
03052:
03053:                /** This method chooses the custom icon only for the known filetypes. If these filetypes are not receiving 
03054:                 * the correct icons, make sure the filenames are correct and that the icons are present in the ui/icons 
03055:                 * directory.
03056:                 */
03057:                public Icon getIcon(File f) {
03058:                    if (f == null)
03059:                        return _other;
03060:                    Icon ret = null;
03061:                    if (!f.isDirectory()) {
03062:                        String name = f.getName().toLowerCase();
03063:                        if (name.endsWith(".java"))
03064:                            ret = _java;
03065:                        if (name.endsWith(".dj0"))
03066:                            ret = _dj0;
03067:                        if (name.endsWith(".dj1"))
03068:                            ret = _dj1;
03069:                        if (name.endsWith(".dj2"))
03070:                            ret = _dj2;
03071:                    }
03072:                    if (ret == null) {
03073:                        ret = super .getIcon(f);
03074:                        if (ret.getIconHeight() < _java.getIconHeight()) {
03075:                            ret = new CenteredIcon(ret, _java.getIconWidth(),
03076:                                    _java.getIconHeight());
03077:                        }
03078:                    }
03079:                    return ret;
03080:                }
03081:            }
03082:
03083:            /** This class wraps the file display managers by superimposing any notification icons on top of the base 
03084:             * file icon.  Currently, only the modified star is allowed, but everything is set up to add notification 
03085:             * icons for whether a document has passed the junit test (for display in the tree). This class is static 
03086:             * for now.  It may be necessary to make it dynamic when implementing the junit notifications.
03087:             */
03088:            private static class OddDisplayManager implements 
03089:                    DisplayManager<OpenDefinitionsDocument> {
03090:                private final Icon _star;
03091:                //    private Icon _juPass;
03092:                //    private Icon _juFail;
03093:                private final FileDisplayManager _default;
03094:
03095:                /** Standard constructor.
03096:                 *  @param star The star icon will be put flush to the left 1/4 the way down
03097:                 *  @param junitPass indicator of junit success, placed at bottom right
03098:                 *  @param junitFail indicator of junit failure, placed at bottom right
03099:                 */
03100:                public OddDisplayManager(FileDisplayManager fdm, Icon star,
03101:                        Icon junitPass, Icon junitFail) {
03102:                    _star = star;
03103:                    //      _juPass = junitPass;
03104:                    //      _juFail = junitFail;
03105:                    _default = fdm;
03106:                }
03107:
03108:                public Icon getIcon(OpenDefinitionsDocument odd) {
03109:                    File f = null;
03110:                    try {
03111:                        f = odd.getFile();
03112:                    } catch (FileMovedException fme) { /* do nothing */
03113:                    }
03114:
03115:                    if (odd.isModifiedSinceSave())
03116:                        return makeLayeredIcon(_default.getIcon(f), _star);
03117:                    return _default.getIcon(f);
03118:                }
03119:
03120:                public String getName(OpenDefinitionsDocument doc) {
03121:                    return doc.getFileName();
03122:                }
03123:
03124:                private LayeredIcon makeLayeredIcon(Icon base, Icon star) {
03125:                    return new LayeredIcon(new Icon[] { base, star },
03126:                            new int[] { 0, 0 }, new int[] { 0,
03127:                                    (base.getIconHeight() / 4) });
03128:                }
03129:            };
03130:
03131:            /** This is what is given to the JTreeSortNavigator.  This simply resolves the INavItem to an OpenDefDoc
03132:             * using the model and forwards it to the OddDisplayManager for size 20.
03133:             */
03134:            private final DisplayManager<INavigatorItem> _navPaneDisplayManager = new DisplayManager<INavigatorItem>() {
03135:                public Icon getIcon(INavigatorItem item) {
03136:                    OpenDefinitionsDocument odd = (OpenDefinitionsDocument) item; // FIX THIS!
03137:                    return _oddDisplayManager20.getIcon(odd);
03138:                }
03139:
03140:                public String getName(INavigatorItem name) {
03141:                    return name.getName();
03142:                }
03143:            };
03144:
03145:            public static DJFileDisplayManager getFileDisplayManager20() {
03146:                return _djFileDisplayManager20;
03147:            }
03148:
03149:            public static DJFileDisplayManager getFileDisplayManager30() {
03150:                return _djFileDisplayManager30;
03151:            }
03152:
03153:            public static OddDisplayManager getOddDisplayManager20() {
03154:                return _oddDisplayManager20;
03155:            }
03156:
03157:            public static OddDisplayManager getOddDisplayManager30() {
03158:                return _oddDisplayManager30;
03159:            }
03160:
03161:            public DisplayManager<INavigatorItem> getNavPaneDisplayManager() {
03162:                return _navPaneDisplayManager;
03163:            }
03164:
03165:            /* ----------------------- Constructor is here! --------------------------- */
03166:
03167:            /** Creates the main window, and shows it. */
03168:            public MainFrame() {
03169:
03170:                // Cache the config object, since we use it many, many times.
03171:                final Configuration config = DrJava.getConfig();
03172:
03173:                //    Utilities.show("MainFrame starting");
03174:
03175:                // create our model
03176:                _model = new DefaultGlobalModel();
03177:
03178:                _showDebugger = _model.getDebugger().isAvailable();
03179:                _findReplace = new FindReplacePanel(this , _model);
03180:
03181:                if (_showDebugger) {
03182:                    _debugPanel = new DebugPanel(this );
03183:                    _breakpointsPanel = new BreakpointsPanel(this );
03184:                } else {
03185:                    _debugPanel = null;
03186:                    _breakpointsPanel = null;
03187:                }
03188:
03189:                _compilerErrorPanel = new CompilerErrorPanel(_model, this );
03190:                _consoleController = new ConsoleController(_model
03191:                        .getConsoleDocument(), _model.getSwingConsoleDocument());
03192:                _consolePane = _consoleController.getPane();
03193:
03194:                _consoleScroll = new BorderlessScrollPane(_consolePane) {
03195:                    public boolean requestFocusInWindow() {
03196:                        super .requestFocusInWindow();
03197:                        return _consolePane.requestFocusInWindow();
03198:                    }
03199:                };
03200:
03201:                _interactionsController = new InteractionsController(_model
03202:                        .getInteractionsModel(), _model
03203:                        .getSwingInteractionsDocument());
03204:
03205:                _interactionsPane = _interactionsController.getPane();
03206:                _interactionsController.setCachedCaretPos(0);
03207:                _interactionsController.setCachedPromptPos(_model
03208:                        .getConsoleDocument().getPromptPos());
03209:
03210:                _interactionsContainer = new JPanel(new BorderLayout()); /* {
03211:                     public boolean requestFocusInWindow() { 
03212:                       super.requestFocusInWindow();
03213:                       return _interactionsPane.requestFocusInWindow(); 
03214:                     } 
03215:                   };*/
03216:
03217:                _lastFocusOwner = _interactionsContainer;
03218:
03219:                _junitErrorPanel = new JUnitPanel(_model, this );
03220:                _javadocErrorPanel = new JavadocErrorPanel(_model, this );
03221:
03222:                _bookmarksPanel = new BookmarksPanel(this );
03223:
03224:                // Initialize the status bar
03225:                _setUpStatusBar();
03226:
03227:                // Preliminary layout
03228:
03229:                /* Definitions Pane */
03230:
03231:                /* Ensure that DefinitionsPane uses the correct EditorKit!  This has to be stored as a static field on 
03232:                 * DefinitionsPane because the JEditorPane constructor uses it before we get a chance to assign it to an instance
03233:                 * field ... */
03234:                DefinitionsPane.setEditorKit(_model.getEditorKit());
03235:
03236:                _defScrollPanes = new Hashtable<OpenDefinitionsDocument, JScrollPane>();
03237:
03238:                /* Other panes */
03239:                _tabbedPane = new JTabbedPane();
03240:                _tabbedPane.addFocusListener(new FocusListener() {
03241:                    public void focusGained(FocusEvent e) {
03242:                        Component c = _tabbedPane.getSelectedComponent();
03243:                        //         System.err.println("focus gained in tabbed pane with selected tab " + c + " with paramString " + e.paramString());
03244:                        if (c == _interactionsContainer) {
03245:                            _interactionsPane.requestFocusInWindow();
03246:                            //           System.err.println("Selected tab was interactions container");
03247:                        } else if (c == _findReplace)
03248:                            _findReplace.getFindField().requestFocusInWindow();
03249:                    }
03250:
03251:                    public void focusLost(FocusEvent e) {
03252:                    }
03253:                });
03254:
03255:                JScrollPane defScroll = _createDefScrollPane(_model
03256:                        .getActiveDocument());
03257:
03258:                _docSplitPane = new BorderlessSplitPane(
03259:                        JSplitPane.HORIZONTAL_SPLIT, true, new JScrollPane(
03260:                                _model.getDocumentNavigator().asContainer()),
03261:                        defScroll);
03262:                _debugSplitPane = new BorderlessSplitPane(
03263:                        JSplitPane.VERTICAL_SPLIT, true);
03264:                _mainSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true,
03265:                        _docSplitPane, _tabbedPane);
03266:
03267:                // Any lightweight parsing has been disabled until we have something that is beneficial and works better in the background.
03268:                //    // The OptionListener for LIGHTWEIGHT_PARSING_ENABLED.
03269:                //    OptionListener<Boolean> parsingEnabledListener = new OptionListener<Boolean>() {
03270:                //      public void optionChanged(OptionEvent<Boolean> oce) {
03271:                //        if (oce.value) {
03272:                //          _model.getParsingControl().addListener(new LightWeightParsingListener() {
03273:                //            public void enclosingClassNameUpdated(OpenDefinitionsDocument doc, String old, String updated) {
03274:                //              if (doc==_model.getActiveDocument()) { updateStatusField(); }
03275:                //            }
03276:                //          });
03277:                //        }
03278:                //        _model.getParsingControl().reset();
03279:                //        _model.getParsingControl().setAutomaticUpdates(oce.value);
03280:                //        updateStatusField();
03281:                //      }
03282:                //    };
03283:                //    DrJava.getConfig().addOptionListener(LIGHTWEIGHT_PARSING_ENABLED, parsingEnabledListener);
03284:                //    parsingEnabledListener.optionChanged(new OptionEvent<Boolean>(LIGHTWEIGHT_PARSING_ENABLED, 
03285:                //                                                                  DrJava.getConfig().getSetting(LIGHTWEIGHT_PARSING_ENABLED).booleanValue()));
03286:
03287:                //    Utilities.show("Global Model started");
03288:
03289:                _model.getDocumentNavigator().asContainer().addKeyListener(
03290:                        _historyListener);
03291:                _model.getDocumentNavigator().asContainer().addFocusListener(
03292:                        _focusListenerForRecentDocs);
03293:
03294:                /* Listens for clicks in the document navigator to reset the first document in an all-documents search for wrapping
03295:                 * purposes. */
03296:                _model.getDocumentNavigator().asContainer().addMouseListener(
03297:                        _resetFindReplaceListener);
03298:
03299:                if (_showDebugger)
03300:                    _model.getDebugger().addListener(new UIDebugListener()); // add listener to debug manager
03301:
03302:                // Timer to display a message if a debugging step takes a long time
03303:                _debugStepTimer = new Timer(DEBUG_STEP_TIMER_VALUE,
03304:                        new ActionListener() {
03305:                            public void actionPerformed(ActionEvent e) {
03306:                                _model.printDebugMessage("Stepping...");
03307:                            }
03308:                        });
03309:                _debugStepTimer.setRepeats(false);
03310:
03311:                // Working directory is default place to start (bug #895998).
03312:                File workDir = _model.getMasterWorkingDirectory();
03313:
03314:                // Overrides JFileChooser to display the full path of the directory
03315:                _openChooser = new JFileChooser() {
03316:                    public void setCurrentDirectory(File dir) {
03317:                        //next two lines are order dependent!
03318:                        super .setCurrentDirectory(dir);
03319:                        setDialogTitle("Open:  " + getCurrentDirectory());
03320:                    }
03321:                };
03322:                _openChooser.setPreferredSize(new Dimension(650, 410));
03323:                _openChooser.setCurrentDirectory(workDir);
03324:                _openChooser.setFileFilter(_javaSourceFilter);
03325:                _openChooser.setMultiSelectionEnabled(true);
03326:
03327:                _openRecursiveCheckBox = new JCheckBox(
03328:                        "Open folders recursively");
03329:                _openRecursiveCheckBox.setSelected(config.getSetting(
03330:                        OptionConstants.OPEN_FOLDER_RECURSIVE).booleanValue());
03331:
03332:                _folderChooser = makeFolderChooser(workDir);
03333:
03334:                //Get most recently opened project for filechooser
03335:                Vector<File> recentProjects = config
03336:                        .getSetting(RECENT_PROJECTS);
03337:                _openProjectChooser = new JFileChooser();
03338:                _openProjectChooser.setPreferredSize(new Dimension(650, 410));
03339:
03340:                if (recentProjects.size() > 0
03341:                        && recentProjects.elementAt(0).getParentFile() != null)
03342:                    _openProjectChooser.setCurrentDirectory(recentProjects
03343:                            .elementAt(0).getParentFile());
03344:                else
03345:                    _openProjectChooser.setCurrentDirectory(workDir);
03346:
03347:                _openProjectChooser.setFileFilter(_projectFilter);
03348:                _openProjectChooser.setMultiSelectionEnabled(false);
03349:                _saveChooser = new JFileChooser() {
03350:                    public void setCurrentDirectory(File dir) {
03351:                        //next two lines are order dependent!
03352:                        super .setCurrentDirectory(dir);
03353:                        setDialogTitle("Save:  " + getCurrentDirectory());
03354:                    }
03355:                };
03356:                _saveChooser.setPreferredSize(new Dimension(650, 410));
03357:                _saveChooser.setCurrentDirectory(workDir);
03358:                _saveChooser.setFileFilter(_javaSourceFilter);
03359:
03360:                _interactionsHistoryChooser = new JFileChooser();
03361:                _interactionsHistoryChooser.setPreferredSize(new Dimension(650,
03362:                        410));
03363:                _interactionsHistoryChooser.setCurrentDirectory(workDir);
03364:                _interactionsHistoryChooser
03365:                        .setFileFilter(new InteractionsHistoryFilter());
03366:                _interactionsHistoryChooser.setMultiSelectionEnabled(true);
03367:
03368:                //set up the hourglass cursor
03369:                setGlassPane(new GlassPane());
03370:                setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
03371:
03372:                // Set up listeners
03373:                addWindowListener(_windowCloseListener);
03374:
03375:                // Create the main model listener and attach it to the global model
03376:                _mainListener = new ModelListener();
03377:                _model.addListener(_mainListener);
03378:
03379:                // Initialize tabs before DefPane
03380:                _setUpTabs();
03381:
03382:                // DefinitionsPane
03383:                _recentDocFrame = new RecentDocFrame(this );
03384:                _recentDocFrame.pokeDocument(_model.getActiveDocument());
03385:                _currentDefPane = (DefinitionsPane) defScroll.getViewport()
03386:                        .getView();
03387:                _currentDefPane.notifyActive();
03388:
03389:                // Get proper cross-platform mask.
03390:                int mask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
03391:
03392:                // set up key-bindings
03393:                KeyBindingManager.Singleton.setMainFrame(this );
03394:                KeyBindingManager.Singleton.setActionMap(_currentDefPane
03395:                        .getActionMap());
03396:                _setUpKeyBindingMaps();
03397:
03398:                _posListener.updateLocation();
03399:
03400:                // Need to set undo/redo actions to point to the initial def pane
03401:                // on switching documents later these pointers will also switch
03402:                _undoAction.setDelegatee(_currentDefPane.getUndoAction());
03403:                _redoAction.setDelegatee(_currentDefPane.getRedoAction());
03404:
03405:                _compilerErrorPanel.reset();
03406:                _junitErrorPanel.reset();
03407:                _javadocErrorPanel.reset();
03408:
03409:                // Create menubar and menus
03410:                _menuBar = new MenuBar();
03411:                _fileMenu = _setUpFileMenu(mask);
03412:                _editMenu = _setUpEditMenu(mask);
03413:                _toolsMenu = _setUpToolsMenu(mask);
03414:                _projectMenu = _setUpProjectMenu(mask);
03415:
03416:                if (_showDebugger)
03417:                    _debugMenu = _setUpDebugMenu(mask);
03418:                _languageLevelMenu = _setUpLanguageLevelMenu(mask);
03419:                _helpMenu = _setUpHelpMenu(mask);
03420:
03421:                // initialize menu bar and actions
03422:                _setUpActions();
03423:                _setUpMenuBar();
03424:
03425:                //    _setUpDocumentSelector();
03426:                _setUpContextMenus();
03427:
03428:                // Create toolbar and buttons
03429:
03430:                _toolBar = new JToolBar();
03431:                _undoButton = _createManualToolbarButton(_undoAction);
03432:                _redoButton = _createManualToolbarButton(_redoAction);
03433:
03434:                // initialize _toolBar
03435:
03436:                _setUpToolBar();
03437:
03438:                // add recent file and project manager
03439:
03440:                _recentFileManager = new RecentFileManager(_fileMenu
03441:                        .getItemCount() - 2, _fileMenu,
03442:                        new RecentFileManager.RecentFileAction() {
03443:                            public void actionPerformed(
03444:                                    FileOpenSelector selector) {
03445:                                open(selector);
03446:                            }
03447:                        }, OptionConstants.RECENT_FILES);
03448:
03449:                _recentProjectManager = new RecentFileManager(_projectMenu
03450:                        .getItemCount() - 2, _projectMenu,
03451:                        new RecentFileManager.RecentFileAction() {
03452:                            public void actionPerformed(
03453:                                    FileOpenSelector selector) {
03454:                                openProject(selector);
03455:                            }
03456:                        }, OptionConstants.RECENT_PROJECTS);
03457:
03458:                // Set frame icon
03459:                setIconImage(getIcon("drjava64.png").getImage());
03460:
03461:                // Size and position
03462:                int x = config.getSetting(WINDOW_X).intValue();
03463:                int y = config.getSetting(WINDOW_Y).intValue();
03464:                int width = config.getSetting(WINDOW_WIDTH).intValue();
03465:                int height = config.getSetting(WINDOW_HEIGHT).intValue();
03466:                int state = config.getSetting(WINDOW_STATE).intValue();
03467:
03468:                // Bounds checking.
03469:                // suggested from zaq@nosi.com, to keep the frame on the screen!
03470:                Dimension screenSize = Toolkit.getDefaultToolkit()
03471:                        .getScreenSize();
03472:
03473:                final int menubarHeight = 24;
03474:                if (height > screenSize.height - menubarHeight)
03475:                    height = screenSize.height - menubarHeight; // Too tall, so resize
03476:
03477:                if (width > screenSize.width)
03478:                    width = screenSize.width; // Too wide, so resize
03479:
03480:                // I assume that we want to be contained on the default screen.
03481:                // TODO: support spanning screens in multi-screen setups.
03482:                Rectangle bounds = GraphicsEnvironment
03483:                        .getLocalGraphicsEnvironment().getDefaultScreenDevice()
03484:                        .getDefaultConfiguration().getBounds();
03485:
03486:                if (x == Integer.MAX_VALUE)
03487:                    x = (bounds.width - width + bounds.x) / 2; // magic value for "not set" - center.
03488:                if (y == Integer.MAX_VALUE)
03489:                    y = (bounds.height - height + bounds.y) / 2; // magic value for "not set" - center.
03490:                if (x < bounds.x)
03491:                    x = bounds.x; // Too far left, move to left edge.
03492:                if (y < bounds.y)
03493:                    y = bounds.y; // Too far up, move to top edge.
03494:                if ((x + width) > (bounds.x + bounds.width))
03495:                    x = bounds.width - width + bounds.x;
03496:                // Too far right, move to right edge.
03497:                if ((y + height) > (bounds.y + bounds.height))
03498:                    y = bounds.height - height + bounds.y;
03499:                // Too far down, move to bottom edge.
03500:
03501:                //ensure that we don't set window state to minimized
03502:                state &= ~Frame.ICONIFIED;
03503:
03504:                if (!Toolkit.getDefaultToolkit().isFrameStateSupported(state)) {
03505:                    //we have a bad state, so reset to default
03506:                    state = WINDOW_STATE.getDefault();
03507:                }
03508:
03509:                // Set to the new correct size and location
03510:                setBounds(x, y, width, height);
03511:
03512:                //Work-aroung for Java bug #6365898?
03513:                //setExtendedState does not work until the window in shown on Linux.
03514:                final int stateCopy = state;
03515:                addWindowListener(new WindowAdapter() {
03516:                    public void windowOpened(WindowEvent e) {
03517:                        setExtendedState(stateCopy);
03518:                        //this is a one-off listener
03519:                        removeWindowListener(this );
03520:                    }
03521:                });
03522:
03523:                _setUpPanes();
03524:                updateStatusField();
03525:
03526:                _promptBeforeQuit = config.getSetting(QUIT_PROMPT)
03527:                        .booleanValue();
03528:
03529:                // Set the fonts
03530:                _setMainFont();
03531:                Font doclistFont = config.getSetting(FONT_DOCLIST);
03532:                _model.getDocCollectionWidget().setFont(doclistFont);
03533:
03534:                // Set the colors
03535:                _updateNormalColor();
03536:                _updateBackgroundColor();
03537:
03538:                // Add OptionListeners for the colors.
03539:                config.addOptionListener(DEFINITIONS_NORMAL_COLOR,
03540:                        new NormalColorOptionListener());
03541:                config.addOptionListener(DEFINITIONS_BACKGROUND_COLOR,
03542:                        new BackgroundColorOptionListener());
03543:
03544:                /* Add option listeners for changes to config options.  NOTE: We should only add listeners to view-related (or view-
03545:                 * dependent) config options here.  Model options should go in DefaultGlobalModel._registerOptionListeners(). */
03546:                config.addOptionListener(FONT_MAIN,
03547:                        new MainFontOptionListener());
03548:                config.addOptionListener(FONT_LINE_NUMBERS,
03549:                        new LineNumbersFontOptionListener());
03550:                config.addOptionListener(FONT_DOCLIST,
03551:                        new DoclistFontOptionListener());
03552:                config.addOptionListener(FONT_TOOLBAR,
03553:                        new ToolbarFontOptionListener());
03554:                config.addOptionListener(TOOLBAR_ICONS_ENABLED,
03555:                        new ToolbarOptionListener());
03556:                config.addOptionListener(TOOLBAR_TEXT_ENABLED,
03557:                        new ToolbarOptionListener());
03558:                config.addOptionListener(TOOLBAR_ENABLED,
03559:                        new ToolbarOptionListener());
03560:                config.addOptionListener(LINEENUM_ENABLED,
03561:                        new LineEnumOptionListener());
03562:                config.addOptionListener(QUIT_PROMPT,
03563:                        new QuitPromptOptionListener());
03564:                config.addOptionListener(RECENT_FILES_MAX_SIZE,
03565:                        new RecentFilesOptionListener());
03566:
03567:                config.addOptionListener(LOOK_AND_FEEL,
03568:                        new OptionListener<String>() {
03569:                            public void optionChanged(OptionEvent<String> oe) {
03570:                                //        try {
03571:                                //          UIManager.setLookAndFeel(oe.value);
03572:                                //          SwingUtilities.updateComponentTreeUI(MainFrame.this);
03573:                                //          if (_debugPanel != null) {
03574:                                //            SwingUtilities.updateComponentTreeUI(_debugPanel);
03575:                                //          }
03576:                                //          if (_configFrame != null) {
03577:                                //            SwingUtilities.updateComponentTreeUI(_configFrame);
03578:                                //          }
03579:                                //          if (_helpFrame != null) {
03580:                                //            SwingUtilities.updateComponentTreeUI(_helpFrame);
03581:                                //          }
03582:                                //          if (_aboutDialog != null) {
03583:                                //            SwingUtilities.updateComponentTreeUI(_aboutDialog);
03584:                                //          }
03585:                                //          SwingUtilities.updateComponentTreeUI(_navPanePopupMenu);
03586:                                //          SwingUtilities.updateComponentTreeUI(_interactionsPanePopupMenu);
03587:                                //          SwingUtilities.updateComponentTreeUI(_consolePanePopupMenu);
03588:                                //          SwingUtilities.updateComponentTreeUI(_openChooser);
03589:                                //          SwingUtilities.updateComponentTreeUI(_saveChooser);
03590:                                //          Iterator<TabbedPanel> it = _tabs.iterator();
03591:                                //          while (it.hasNext()) {
03592:                                //            SwingUtilities.updateComponentTreeUI(it.next());
03593:                                //          }
03594:                                //        }
03595:                                //        catch (Exception ex) {
03596:                                //          _showError(ex, "Could Not Set Look and Feel",
03597:                                //                     "An error occurred while trying to set the look and feel.");
03598:                                //        }
03599:
03600:                                String title = "Apply Look and Feel";
03601:                                String msg = "Look and feel changes will take effect when you restart DrJava.";
03602:                                if (config.getSetting(WARN_CHANGE_LAF)
03603:                                        .booleanValue()) {
03604:                                    ConfirmCheckBoxDialog dialog = new ConfirmCheckBoxDialog(
03605:                                            _configFrame, title, msg,
03606:                                            "Do not show this message again",
03607:                                            JOptionPane.INFORMATION_MESSAGE,
03608:                                            JOptionPane.DEFAULT_OPTION);
03609:                                    if (dialog.show() == JOptionPane.OK_OPTION
03610:                                            && dialog.getCheckBoxValue()) {
03611:                                        config.setSetting(WARN_CHANGE_LAF,
03612:                                                Boolean.FALSE);
03613:                                    }
03614:                                }
03615:                            }
03616:                        });
03617:
03618:                config.addOptionListener(SLAVE_JVM_ARGS,
03619:                        new OptionListener<String>() {
03620:                            public void optionChanged(OptionEvent<String> oe) {
03621:                                if (!oe.value.equals("")) {
03622:                                    int result = JOptionPane
03623:                                            .showConfirmDialog(
03624:                                                    _configFrame,
03625:                                                    "Specifying Interations JVM Args is an advanced option. Invalid arguments may cause\n"
03626:                                                            + "the Interactions Pane to stop working.\n"
03627:                                                            + "Are you sure you want to set this option?\n"
03628:                                                            + "(You will have to reset the interactions pane before changes take effect.)",
03629:                                                    "Confirm Interactions JVM Arguments",
03630:                                                    JOptionPane.YES_NO_OPTION);
03631:                                    if (result != JOptionPane.YES_OPTION)
03632:                                        config.setSetting(oe.option, "");
03633:                                }
03634:                            }
03635:                        });
03636:
03637:                config.addOptionListener(MASTER_JVM_ARGS,
03638:                        new OptionListener<String>() {
03639:                            public void optionChanged(OptionEvent<String> oe) {
03640:                                if (!oe.value.equals("")) {
03641:                                    int result = JOptionPane
03642:                                            .showConfirmDialog(
03643:                                                    _configFrame,
03644:                                                    "Specifying Main JVM Args is an advanced option. Invalid arguments may cause\n"
03645:                                                            + "DrJava to fail on start up.  You may need to edit or delete your .drjava preferences file\n"
03646:                                                            + "to recover.\n Are you sure you want to set this option?\n"
03647:                                                            + "(You will have to restart Drjava before changes take effect.)",
03648:                                                    "Confirm Main JVM Arguments",
03649:                                                    JOptionPane.YES_NO_OPTION);
03650:                                    if (result != JOptionPane.YES_OPTION)
03651:                                        config.setSetting(oe.option, "");
03652:                                }
03653:                            }
03654:                        });
03655:
03656:                config.addOptionListener(ALLOW_PRIVATE_ACCESS,
03657:                        new OptionListener<Boolean>() {
03658:                            public void optionChanged(OptionEvent<Boolean> oce) {
03659:                                _model.getInteractionsModel()
03660:                                        .setPrivateAccessible(
03661:                                                oce.value.booleanValue());
03662:                            }
03663:                        });
03664:
03665:                config.addOptionListener(FORCE_TEST_SUFFIX,
03666:                        new OptionListener<Boolean>() {
03667:                            public void optionChanged(OptionEvent<Boolean> oce) {
03668:                                _model.getJUnitModel().setForceTestSuffix(
03669:                                        oce.value.booleanValue());
03670:                            }
03671:                        });
03672:
03673:                // The OptionListener for JAVADOC_LINK_VERSION.
03674:                OptionListener<String> choiceOptionListener = new OptionListener<String>() {
03675:                    public void optionChanged(OptionEvent<String> oce) {
03676:                        _javaAPIList = null;
03677:                        _openJavadocAction.setEnabled(!oce.value
03678:                                .equals(JAVADOC_NONE_TEXT));
03679:                        _openJavadocUnderCursorAction.setEnabled(!oce.value
03680:                                .equals(JAVADOC_NONE_TEXT));
03681:                    }
03682:                };
03683:                DrJava.getConfig().addOptionListener(JAVADOC_LINK_VERSION,
03684:                        choiceOptionListener);
03685:
03686:                // The OptionListener for JAVADOC_XXX_LINK.
03687:                OptionListener<String> link13OptionListener = new OptionListener<String>() {
03688:                    public void optionChanged(OptionEvent<String> oce) {
03689:                        String linkVersion = DrJava.getConfig().getSetting(
03690:                                JAVADOC_LINK_VERSION);
03691:                        if (linkVersion.equals(JAVADOC_1_3_TEXT)) {
03692:                            _javaAPIList = null;
03693:                        }
03694:                    }
03695:                };
03696:                DrJava.getConfig().addOptionListener(JAVADOC_1_3_LINK,
03697:                        link13OptionListener);
03698:                OptionListener<String> link14OptionListener = new OptionListener<String>() {
03699:                    public void optionChanged(OptionEvent<String> oce) {
03700:                        String linkVersion = DrJava.getConfig().getSetting(
03701:                                JAVADOC_LINK_VERSION);
03702:                        if (linkVersion.equals(JAVADOC_1_4_TEXT)) {
03703:                            _javaAPIList = null;
03704:                        }
03705:                    }
03706:                };
03707:                DrJava.getConfig().addOptionListener(JAVADOC_1_4_LINK,
03708:                        link14OptionListener);
03709:                OptionListener<String> link15OptionListener = new OptionListener<String>() {
03710:                    public void optionChanged(OptionEvent<String> oce) {
03711:                        String linkVersion = DrJava.getConfig().getSetting(
03712:                                JAVADOC_LINK_VERSION);
03713:                        if (linkVersion.equals(JAVADOC_1_5_TEXT)) {
03714:                            _javaAPIList = null;
03715:                        }
03716:                    }
03717:                };
03718:                DrJava.getConfig().addOptionListener(JAVADOC_1_5_LINK,
03719:                        link15OptionListener);
03720:
03721:                // Initialize DocumentRegion highlights hashtables, for easy removal of highlights
03722:                _documentBreakpointHighlights = new Hashtable<Breakpoint, HighlightManager.HighlightInfo>();
03723:                _documentBookmarkHighlights = new Hashtable<DocumentRegion, HighlightManager.HighlightInfo>();
03724:
03725:                // Initialize cached frames and dialogs 
03726:                _configFrame = new ConfigFrame(this );
03727:                _helpFrame = new HelpFrame();
03728:                _aboutDialog = new AboutDialog(MainFrame.this );
03729:                _quickStartFrame = new QuickStartFrame();
03730:                _interactionsScriptController = null;
03731:                _jarOptionsDialog = new JarOptionsDialog(MainFrame.this );
03732:                initJarOptionsDialog();
03733:                //    _projectPropertiesFrame = null;
03734:
03735:                // If any errors occurred while parsing config file, show them
03736:                _showConfigException();
03737:
03738:                KeyBindingManager.Singleton.setShouldCheckConflict(false);
03739:
03740:                // Platform-specific UI setup.
03741:                PlatformFactory.ONLY.afterUISetup(_aboutAction,
03742:                        _editPreferencesAction, _quitAction);
03743:                setUpKeys();
03744:
03745:                // discard ` character if it was used for the next/prev recent doc feature
03746:                KeyboardFocusManager.getCurrentKeyboardFocusManager()
03747:                        .addKeyEventDispatcher(new KeyEventDispatcher() {
03748:                            public boolean dispatchKeyEvent(KeyEvent e) {
03749:                                boolean discardEvent = false;
03750:
03751:                                if ((e.getID() == KeyEvent.KEY_TYPED)
03752:                                        && (e.getKeyChar() == '`')
03753:                                        && (((e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) == InputEvent.CTRL_DOWN_MASK) || ((e
03754:                                                .getModifiersEx() & (InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)) == (InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)))
03755:                                        && (e.getComponent().getClass()
03756:                                                .equals(DefinitionsPane.class))) {
03757:                                    //          System.out.println("discarding `, modifiers = "+e.getModifiersEx()+": "+e.getComponent());
03758:                                    discardEvent = true;
03759:                                }
03760:
03761:                                return discardEvent;
03762:                            }
03763:                        });
03764:
03765:                if (DrJava
03766:                        .getConfig()
03767:                        .getSetting(
03768:                                edu.rice.cs.drjava.config.OptionConstants.REMOTE_CONTROL_ENABLED)) {
03769:                    // start remote control server if no server is running
03770:                    try {
03771:                        if (!RemoteControlClient.isServerRunning()) {
03772:                            edu.rice.cs.drjava.RemoteControlServer rcServer = new edu.rice.cs.drjava.RemoteControlServer(
03773:                                    this );
03774:                        }
03775:                    } catch (IOException ioe) {
03776:                        try {
03777:                            RemoteControlClient.openFile(null);
03778:                        } catch (IOException ignored) {
03779:                            // ignore
03780:                        }
03781:                        if (!System.getProperty("user.name").equals(
03782:                                RemoteControlClient.getServerUser())) {
03783:                            Object[] options = { "Disable", "Ignore" };
03784:                            String msg = "<html>Could not start DrJava's remote control server";
03785:                            if (RemoteControlClient.getServerUser() != null) {
03786:                                msg += "<br>because user "
03787:                                        + RemoteControlClient.getServerUser()
03788:                                        + " is already using the same port";
03789:                            }
03790:                            msg += ".<br>Please select an unused port in the Preferences dialog.<br>"
03791:                                    + "In the meantime, do you want to disable the remote control feature?";
03792:                            int n = JOptionPane.showOptionDialog(
03793:                                    MainFrame.this , msg,
03794:                                    "Could Not Start Remote Control Server",
03795:                                    JOptionPane.YES_NO_OPTION,
03796:                                    JOptionPane.QUESTION_MESSAGE, null,
03797:                                    options, options[1]);
03798:                            if (n == JOptionPane.YES_OPTION) {
03799:                                DrJava
03800:                                        .getConfig()
03801:                                        .setSetting(
03802:                                                edu.rice.cs.drjava.config.OptionConstants.REMOTE_CONTROL_ENABLED,
03803:                                                false);
03804:                            }
03805:                        }
03806:                    }
03807:                }
03808:            } // End of MainFrame constructor
03809:
03810:            public void setVisible(boolean b) {
03811:                _updateToolBarVisible();
03812:                super .setVisible(b);
03813:            }
03814:
03815:            /** Set a new painters for existing breakpoint highlights. */
03816:            void refreshBreakpointHighlightPainter() {
03817:                for (java.util.Map.Entry<Breakpoint, HighlightManager.HighlightInfo> pair : _documentBreakpointHighlights
03818:                        .entrySet()) {
03819:                    if (pair.getKey().isEnabled()) {
03820:                        pair.getValue().refresh(
03821:                                DefinitionsPane.BREAKPOINT_PAINTER);
03822:                    } else {
03823:                        pair.getValue().refresh(
03824:                                DefinitionsPane.DISABLED_BREAKPOINT_PAINTER);
03825:                    }
03826:                }
03827:            }
03828:
03829:            /** Set new painter for existing bookmark highlights. */
03830:            void refreshBookmarkHighlightPainter() {
03831:                for (HighlightManager.HighlightInfo hi : _documentBookmarkHighlights
03832:                        .values()) {
03833:                    hi.refresh(DefinitionsPane.BOOKMARK_PAINTER);
03834:                }
03835:            }
03836:
03837:            /** Set new painter for existing find results highlights. */
03838:            void refreshFindResultsHighlightPainter(FindResultsPanel panel,
03839:                    ReverseHighlighter.DefaultUnderlineHighlightPainter painter) {
03840:                for (Pair<FindResultsPanel, Hashtable<MovingDocumentRegion, HighlightManager.HighlightInfo>> pair : _findResults) {
03841:                    if (pair.first() == panel) {
03842:                        Hashtable<MovingDocumentRegion, HighlightManager.HighlightInfo> highlights = pair
03843:                                .second();
03844:                        for (HighlightManager.HighlightInfo hi : highlights
03845:                                .values()) {
03846:                            hi.refresh(painter);
03847:                        }
03848:                    }
03849:                }
03850:            }
03851:
03852:            /** Creates the folder chooser during MainFrame initialization which does not run in event thread. */
03853:            private DirectoryChooser makeFolderChooser(final File workDir) {
03854:                final DirectoryChooser dc = new DirectoryChooser(this );
03855:                /* The following code fragement was moved to the event thread because setSelectedFile occasionally generates an 
03856:                 * ArrayOutOfBoundsException otherwise. */
03857:                Utilities.invokeLater(new Runnable() {
03858:                    public void run() {
03859:                        dc.setSelectedFile(workDir);
03860:                        dc.setApproveButtonText("Select");
03861:                        dc.setDialogTitle("Open Folder");
03862:                        dc.setAccessory(_openRecursiveCheckBox);
03863:                    }
03864:                });
03865:                return dc;
03866:            }
03867:
03868:            //  
03869:            //  private JFileChooser makeFolderChooser(File workDir) {
03870:            //    _folderChooser = new JFileChooser();
03871:            //    _folderChooser.setMultiSelectionEnabled(false);
03872:            //    _folderChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
03873:            //    _folderChooser.setCurrentDirectory(workDir);
03874:            //    _folderChooser.setApproveButtonText("Select");
03875:            //    _folderChooser.setFileFilter(new DirectoryFilter());
03876:            //    _folderChooser.setDialogTitle("Open Folder");
03877:            //    
03878:            //    
03879:            //    Container button_row = (Container)findButtonContainer(_folderChooser, _folderChooser.getApproveButtonText());
03880:            //    Container buttons = (Container) button_row.getParent();
03881:            //    
03882:            ////    Component c2 = ((BorderLayout)_folderChooser.getLayout()).getLayoutComponent(BorderLayout.SOUTH);
03883:            //    
03884:            ////    System.out.println("c1: " + c1);
03885:            ////    System.out.println("c2: " + c2);
03886:            //    
03887:            //    
03888:            ////    JPanel buttons = (JPanel)c2;
03889:            ////    JPanel button_row = (JPanel)buttons.getComponent(3);
03890:            //    JPanel bottom_row = new JPanel();
03891:            //    bottom_row.setLayout(new BorderLayout());
03892:            //    bottom_row.add(new JCheckBox("Recursive Open"), BorderLayout.CENTER);
03893:            //    bottom_row.add(button_row, BorderLayout.EAST);
03894:            //    buttons.add(bottom_row);
03895:            //    
03896:            //    return _folderChooser;
03897:            //  }
03898:
03899:            //  private Container findButtonContainer(Container container, String buttonText) {
03900:            //    Container answer = null;
03901:            //    Component[] cs = container.getComponents();
03902:            //    for(Component c: cs) {
03903:            //      if (c instanceof JButton && ((JButton)c).getText().equals(buttonText)) {
03904:            //        return container;
03905:            //      }else if (c instanceof Container) {
03906:            //        answer = findButtonContainer((Container)c, buttonText);
03907:            //      }
03908:            //      
03909:            //      if (answer != null) break;
03910:            //    }
03911:            //    return answer;
03912:            //  }
03913:
03914:            /** Sets up the ctrl-tab listener. */
03915:            private void setUpKeys() {
03916:                setFocusTraversalKeysEnabled(false);
03917:            }
03918:
03919:            /** Relying on inherited dispose() method. */
03920:
03921:            /** @return The model providing the logic for this view. */
03922:            public SingleDisplayModel getModel() {
03923:                return _model;
03924:            }
03925:
03926:            /** Returns the frame's interactions pane.  (Package private accessor) */
03927:            InteractionsPane getInteractionsPane() {
03928:                return _interactionsPane;
03929:            }
03930:
03931:            /** Returns the frame's interactions controller. (Package private accessor) */
03932:            InteractionsController getInteractionsController() {
03933:                return _interactionsController;
03934:            }
03935:
03936:            /** @return The frame's close button (Package private accessor). */
03937:            JButton getCloseButton() {
03938:                return _closeButton;
03939:            }
03940:
03941:            /** For testing purposes.
03942:             *  @return The frame's compileAll button (Package private accessor)
03943:             */
03944:            JButton getCompileAllButton() {
03945:                return _compileButton;
03946:            }
03947:
03948:            private volatile int _hourglassNestLevel = 0;
03949:
03950:            /** Make the cursor an hourglass. Only runs in the event thread. */
03951:            public void hourglassOn() {
03952:                assert EventQueue.isDispatchThread();
03953:                _hourglassNestLevel++;
03954:                if (_hourglassNestLevel == 1) {
03955:                    getGlassPane().setVisible(true);
03956:                    _currentDefPane.setEditable(false);
03957:                    setAllowKeyEvents(false);
03958:                }
03959:            }
03960:
03961:            /** Return the cursor to normal. Only runs in the event thread. */
03962:            public void hourglassOff() {
03963:                assert EventQueue.isDispatchThread();
03964:                _hourglassNestLevel--;
03965:                if (_hourglassNestLevel == 0) {
03966:                    getGlassPane().setVisible(false);
03967:                    _currentDefPane.setEditable(true);
03968:                    setAllowKeyEvents(true);
03969:                }
03970:            }
03971:
03972:            private volatile boolean _allowKeyEvents = true;
03973:
03974:            public void setAllowKeyEvents(boolean a) {
03975:                _allowKeyEvents = a;
03976:            }
03977:
03978:            public boolean getAllowKeyEvents() {
03979:                return _allowKeyEvents;
03980:            }
03981:
03982:            /** Toggles whether the debugger is enabled or disabled, and updates the display accordingly.  Only runs in the 
03983:             * event thread. */
03984:            public void debuggerToggle() {
03985:                assert EventQueue.isDispatchThread();
03986:                // Make sure the debugger is available
03987:                Debugger debugger = _model.getDebugger();
03988:                if (!debugger.isAvailable())
03989:                    return;
03990:
03991:                updateStatusField("Toggling Debugger Mode");
03992:
03993:                try {
03994:                    if (isDebuggerReady())
03995:                        debugger.shutdown();
03996:                    else {
03997:                        // Turn on debugger
03998:                        hourglassOn();
03999:                        try {
04000:                            debugger.startUp(); // may kick active document (if unmodified) out of memory!
04001:                            _model.refreshActiveDocument();
04002:                            _updateDebugStatus();
04003:                        } finally {
04004:                            hourglassOff();
04005:                        }
04006:                    }
04007:                } catch (DebugException de) {
04008:                    _showError(de, "Debugger Error",
04009:                            "Could not start the debugger.");
04010:                } catch (NoClassDefFoundError err) {
04011:                    _showError(
04012:                            err,
04013:                            "Debugger Error",
04014:                            "Unable to find the JPDA package for the debugger.\n"
04015:                                    + "Please make sure either tools.jar or jpda.jar is\n"
04016:                                    + "in your classpath when you start DrJava.");
04017:                    _setDebugMenuItemsEnabled(false);
04018:                }
04019:            }
04020:
04021:            /** Display the debugger tab and update the Debug menu accordingly. */
04022:            public void showDebugger() {
04023:                _setDebugMenuItemsEnabled(true);
04024:                _showDebuggerPanel();
04025:            }
04026:
04027:            /** Hide the debugger tab and update the Debug menu accordingly. */
04028:            public void hideDebugger() {
04029:                _setDebugMenuItemsEnabled(false);
04030:                _hideDebuggerPanel();
04031:            }
04032:
04033:            private void _showDebuggerPanel() {
04034:                _debugSplitPane.setTopComponent(_docSplitPane);
04035:                _mainSplit.setTopComponent(_debugSplitPane);
04036:                _debugPanel.updateData();
04037:                _lastFocusOwner.requestFocusInWindow();
04038:            }
04039:
04040:            private void _hideDebuggerPanel() {
04041:                _mainSplit.setTopComponent(_docSplitPane);
04042:                _lastFocusOwner.requestFocusInWindow();
04043:            }
04044:
04045:            /** ONLY executes in event thread. */
04046:            public void updateStatusField(String text) {
04047:                assert EventQueue.isDispatchThread();
04048:                _statusField.setText(text);
04049:                _statusField.paint(getGraphics()); // force an immediate repaint
04050:            }
04051:
04052:            /** Updates the status field with the current status of the Definitions Pane. */
04053:            public void updateStatusField() {
04054:                OpenDefinitionsDocument doc = _model.getActiveDocument();
04055:                String fileName = doc.getCompletePath();
04056:                if (!fileName.equals(_fileTitle)) {
04057:                    _fileTitle = fileName;
04058:                    setTitle(fileName);
04059:                    _model.getDocCollectionWidget().repaint();
04060:                }
04061:                String path = doc.getCompletePath();
04062:
04063:                String text = "Editing " + path;
04064:
04065:                // Any lightweight parsing has been disabled until we have something that is beneficial and works better in the background.
04066:                //    if (DrJava.getConfig().getSetting(LIGHTWEIGHT_PARSING_ENABLED).booleanValue()) {
04067:                //      String temp = _model.getParsingControl().getEnclosingClassName(doc);
04068:                //      if ((temp != null) && (temp.length() > 0)) { text = text + " - " + temp; }
04069:
04070:                //    _statusField.setToolTipText("Full path for file: " + path);
04071:
04072:                if (!_statusField.getText().equals(text)) {
04073:                    _statusField.setText(text);
04074:                    _statusField.paint(getGraphics()); // force immediate painting of the _statusField
04075:                }
04076:            }
04077:
04078:            /** Prompt the user to select a place to open files from, then load them. Ask the user if they'd like to save 
04079:             *  previous changes (if the current document has been modified) before opening.
04080:             *  @param jfc the open dialog from which to extract information
04081:             *  @return an array of the files that were chosen
04082:             */
04083:            public File[] getOpenFiles(JFileChooser jfc)
04084:                    throws OperationCanceledException {
04085:                int rc = jfc.showOpenDialog(this );
04086:                return getChosenFiles(jfc, rc);
04087:            }
04088:
04089:            /** Prompt the user to select a place to save the current document. */
04090:            public File getSaveFile(JFileChooser jfc)
04091:                    throws OperationCanceledException {
04092:                // This redundant-looking hack is necessary for JDK 1.3.1 on Mac OS X!
04093:                //    File selection = jfc.getSelectedFile();//_saveChooser.getSelectedFile();
04094:                //    if (selection != null) {
04095:                //      jfc.setSelectedFile(selection.getParentFile());
04096:                //      jfc.setSelectedFile(selection);
04097:                //      jfc.setSelectedFile(null);
04098:                //    }
04099:
04100:                OpenDefinitionsDocument active = _model.getActiveDocument();
04101:
04102:                // Fill in class name
04103:                //if (active.isUntitled()) {
04104:                try {
04105:                    String className = active.getFirstTopLevelClassName();
04106:                    if (!className.equals("")) {
04107:                        jfc.setSelectedFile(new File(jfc.getCurrentDirectory(),
04108:                                className));
04109:                    }
04110:                } catch (ClassNameNotFoundException e) {
04111:                    // Don't set selected file
04112:                }
04113:
04114:                _saveChooser.removeChoosableFileFilter(_projectFilter);
04115:                _saveChooser.removeChoosableFileFilter(_javaSourceFilter);
04116:                _saveChooser.setFileFilter(_javaSourceFilter);
04117:                int rc = jfc.showSaveDialog(this );
04118:                return getChosenFile(jfc, rc);
04119:            }
04120:
04121:            /** Returns the current DefinitionsPane. */
04122:            public DefinitionsPane getCurrentDefPane() {
04123:                return _currentDefPane;
04124:            }
04125:
04126:            /** Returns the currently shown error panel if there is one. Otherwise returns null. */
04127:            public ErrorPanel getSelectedErrorPanel() {
04128:                Component c = _tabbedPane.getSelectedComponent();
04129:                if (c instanceof  ErrorPanel)
04130:                    return (ErrorPanel) c;
04131:                return null;
04132:            }
04133:
04134:            /** Returns whether the compiler output tab is currently showing. */
04135:            public boolean isCompilerTabSelected() {
04136:                return _tabbedPane.getSelectedComponent() == _compilerErrorPanel;
04137:            }
04138:
04139:            /** Returns whether the test output tab is currently showing. */
04140:            public boolean isTestTabSelected() {
04141:                return _tabbedPane.getSelectedComponent() == _junitErrorPanel;
04142:            }
04143:
04144:            /** Returns whether the JavaDoc output tab is currently showing. */
04145:            public boolean isJavadocTabSelected() {
04146:                return _tabbedPane.getSelectedComponent() == _javadocErrorPanel;
04147:            }
04148:
04149:            /** Makes sure save and compile buttons and menu items are enabled and disabled appropriately after document
04150:             *  modifications.
04151:             */
04152:            private void _installNewDocumentListener(
04153:                    final OpenDefinitionsDocument d) {
04154:                d.addDocumentListener(new DocumentUIListener() {
04155:                    public void changedUpdate(DocumentEvent e) {
04156:
04157:                        // Commented out because the only attributes that affect the status of buttons are inserts and removes
04158:                        //        Utilities.invokeLater(new Runnable() {
04159:                        //          public void run() {
04160:                        //            OpenDefinitionsDocument doc = _model.getActiveDocument();
04161:                        //            if (doc.isModifiedSinceSave()) {
04162:                        //              _saveAction.setEnabled(true);
04163:                        //              if (isDebuggerReady() && _debugPanel.getStatusText().equals(""))
04164:                        //                _debugPanel.setStatusText(DEBUGGER_OUT_OF_SYNC);
04165:                        //              updateStatusField();
04166:                        //            }
04167:                        //          }
04168:                        //        });
04169:                    }
04170:
04171:                    public void insertUpdate(DocumentEvent e) {
04172:                        Utilities.invokeLater(new Runnable() {
04173:                            public void run() {
04174:                                _saveAction.setEnabled(true);
04175:                                if (isDebuggerReady()
04176:                                        && _debugPanel.getStatusText().equals(
04177:                                                ""))
04178:                                    _debugPanel
04179:                                            .setStatusText(DEBUGGER_OUT_OF_SYNC);
04180:                                //            updateStatusField();  // file title not changed by insert operation
04181:                            }
04182:                        });
04183:                    }
04184:
04185:                    public void removeUpdate(DocumentEvent e) {
04186:                        Utilities.invokeLater(new Runnable() {
04187:                            public void run() {
04188:                                _saveAction.setEnabled(true);
04189:                                if (isDebuggerReady()
04190:                                        && _debugPanel.getStatusText().equals(
04191:                                                ""))
04192:                                    _debugPanel
04193:                                            .setStatusText(DEBUGGER_OUT_OF_SYNC);
04194:                                //            updateStatusField();  // file title not changed by remove operation
04195:                            }
04196:                        });
04197:                    }
04198:                });
04199:            }
04200:
04201:            /** Changes the message text toward the right of the status bar
04202:             *  @param msg The message to place in the status bar
04203:             */
04204:            public void setStatusMessage(String msg) {
04205:                _statusReport.setText(msg);
04206:            }
04207:
04208:            /** Sets the message text in the status bar to the null string. */
04209:            public void clearStatusMessage() {
04210:                _statusReport.setText("");
04211:            }
04212:
04213:            /** Sets the font of the status bar message
04214:             *  @param f The new font of the status bar message
04215:             */
04216:            public void setStatusMessageFont(Font f) {
04217:                _statusReport.setFont(f);
04218:            }
04219:
04220:            /** Sets the color of the text in the status bar message
04221:             *  @param c The color of the text
04222:             */
04223:            public void setStatusMessageColor(Color c) {
04224:                _statusReport.setForeground(c);
04225:            }
04226:
04227:            // Made package protected rather than private in order to facilitate the ProjectMenuTest.testSaveProject
04228:            void _moveToAuxiliary() {
04229:                // now works with multiple files
04230:                java.util.List<OpenDefinitionsDocument> l = _model
04231:                        .getDocumentNavigator().getSelectedDocuments();
04232:                for (OpenDefinitionsDocument d : l) {
04233:                    if (d != null) {
04234:                        if (!d.isUntitled()) {
04235:                            _model.addAuxiliaryFile(d);
04236:                            try {
04237:                                _model.getDocumentNavigator().refreshDocument(
04238:                                        d,
04239:                                        _model.fixPathForNavigator(d.getFile()
04240:                                                .getCanonicalPath()));
04241:                            } catch (IOException e) { /* do nothing */
04242:                            }
04243:                        }
04244:                    }
04245:                }
04246:            }
04247:
04248:            private void _removeAuxiliary() {
04249:                // now works with multiple files
04250:
04251:                for (OpenDefinitionsDocument d : _model.getDocumentNavigator()
04252:                        .getSelectedDocuments()) {
04253:                    // OpenDefinitionsDocument d = _model.getDocumentNavigator().getCurrent();
04254:                    if (d != null) {
04255:                        if (!d.isUntitled()) {
04256:                            _model.removeAuxiliaryFile(d);
04257:                            try {
04258:                                _model.getDocumentNavigator().refreshDocument(
04259:                                        d,
04260:                                        _model.fixPathForNavigator(d.getFile()
04261:                                                .getCanonicalPath()));
04262:                            } catch (IOException e) { /* do nothing */
04263:                            }
04264:                        }
04265:                    }
04266:                }
04267:            }
04268:
04269:            void _moveAllToAuxiliary() {
04270:                // move all external files to auxiliary files
04271:                OpenDefinitionsDocument d;
04272:                Enumeration<OpenDefinitionsDocument> e = _model
04273:                        .getDocumentNavigator().getDocumentsInBin(
04274:                                _model.getExternalBinTitle());
04275:                while (e.hasMoreElements()) {
04276:                    d = e.nextElement();
04277:                    if (d != null) {
04278:                        if (!d.isUntitled()) {
04279:                            _model.addAuxiliaryFile(d);
04280:                            try {
04281:                                _model.getDocumentNavigator().refreshDocument(
04282:                                        d,
04283:                                        _model.fixPathForNavigator(d.getFile()
04284:                                                .getCanonicalPath()));
04285:                            } catch (IOException ex) { /* do nothing */
04286:                            }
04287:                        }
04288:                    }
04289:                }
04290:                Utilities.invokeLater(new Runnable() {
04291:                    public void run() {
04292:                        _model.getDocumentNavigator().setActiveDoc(
04293:                                _model.getActiveDocument());
04294:                    }
04295:                });
04296:            }
04297:
04298:            private void _removeAllAuxiliary() {
04299:                // move all auxiliary files to external files
04300:                OpenDefinitionsDocument d;
04301:                Enumeration<OpenDefinitionsDocument> e = _model
04302:                        .getDocumentNavigator().getDocumentsInBin(
04303:                                _model.getAuxiliaryBinTitle());
04304:                while (e.hasMoreElements()) {
04305:                    d = e.nextElement();
04306:                    if (d != null) {
04307:                        if (!d.isUntitled()) {
04308:                            _model.removeAuxiliaryFile(d);
04309:                            try {
04310:                                _model.getDocumentNavigator().refreshDocument(
04311:                                        d,
04312:                                        _model.fixPathForNavigator(d.getFile()
04313:                                                .getCanonicalPath()));
04314:                            } catch (IOException ex) { /* do nothing */
04315:                            }
04316:                        }
04317:                    }
04318:                }
04319:                Utilities.invokeLater(new Runnable() {
04320:                    public void run() {
04321:                        _model.getDocumentNavigator().setActiveDoc(
04322:                                _model.getActiveDocument());
04323:                    }
04324:                });
04325:            }
04326:
04327:            private void _new() {
04328:                updateStatusField("Creating a new Untitled Document");
04329:                _model.newFile();
04330:            }
04331:
04332:            private void _open() {
04333:                updateStatusField("Opening File");
04334:                open(_openSelector);
04335:            }
04336:
04337:            private void _openFolder() {
04338:                openFolder(_folderChooser);
04339:            }
04340:
04341:            private void _openFileOrProject() {
04342:                try {
04343:                    final File[] fileList = _openFileOrProjectSelector
04344:                            .getFiles();
04345:
04346:                    FileOpenSelector fos = new FileOpenSelector() {
04347:                        public File[] getFiles() {
04348:                            return fileList;
04349:                        }
04350:                    };
04351:
04352:                    if (_openChooser.getFileFilter().equals(_projectFilter))
04353:                        openProject(fos);
04354:                    else
04355:                        open(fos);
04356:                } catch (OperationCanceledException oce) { /* do nothing */
04357:                }
04358:            }
04359:
04360:            /** Puts the given text into the current definitions pane at the current caret position.  */
04361:            private void _putTextIntoDefinitions(String text) {
04362:                int caretPos = _currentDefPane.getCaretPosition();
04363:
04364:                try {
04365:                    _model.getActiveDocument().insertString(caretPos, text,
04366:                            null);
04367:                } catch (BadLocationException ble) {
04368:                    throw new UnexpectedException(ble);
04369:                }
04370:            }
04371:
04372:            /** Sets the left navigator pane to the correct component as dictated by the model. */
04373:            private void _resetNavigatorPane() {
04374:                if (_model.getDocumentNavigator() instanceof  JTreeSortNavigator) {
04375:                    JTreeSortNavigator<?> nav = (JTreeSortNavigator<?>) _model
04376:                            .getDocumentNavigator();
04377:                    nav.setDisplayManager(getNavPaneDisplayManager());
04378:                    nav.setRootIcon(_djProjectIcon);
04379:                }
04380:                _docSplitPane.remove(_docSplitPane.getLeftComponent());
04381:                _docSplitPane.setLeftComponent(new JScrollPane(_model
04382:                        .getDocumentNavigator().asContainer()));
04383:                Font doclistFont = DrJava.getConfig().getSetting(FONT_DOCLIST);
04384:                _model.getDocCollectionWidget().setFont(doclistFont);
04385:                _updateNormalColor();
04386:                _updateBackgroundColor();
04387:            }
04388:
04389:            /** Asks the user to select the project file to open and starts the process of opening the project. */
04390:            private void _openProject() {
04391:                openProject(_openProjectSelector);
04392:            }
04393:
04394:            public void openProject(FileOpenSelector projectSelector) {
04395:
04396:                try {
04397:                    final File[] files = projectSelector.getFiles();
04398:                    if (files.length < 1)
04399:                        throw new IllegalStateException(
04400:                                "Open project file selection not canceled but no project file was selected.");
04401:                    final File file = files[0];
04402:
04403:                    updateStatusField("Opening project " + file);
04404:
04405:                    try {
04406:                        hourglassOn();
04407:                        // make sure there are no open projects
04408:                        if (!_model.isProjectActive()
04409:                                || (_model.isProjectActive() && _closeProject()))
04410:                            _openProjectHelper(file);
04411:                    } catch (Exception e) {
04412:                        e.printStackTrace(System.out);
04413:                    } finally {
04414:                        hourglassOff();
04415:                    }
04416:                } catch (OperationCanceledException oce) { /* do nothing, we just won't open anything */
04417:                }
04418:
04419:            }
04420:
04421:            /** Oversees the opening of the project by delegating to the model to parse and initialize the project 
04422:             *  while resetting the navigator pane and opening up the files itself.
04423:             *  @param projectFile the file of the project to open
04424:             */
04425:            private void _openProjectHelper(File projectFile) {
04426:                _currentProjFile = projectFile;
04427:                try {
04428:                    _mainListener.resetFNFCount();
04429:                    _model.openProject(projectFile);
04430:                    if (_mainListener.someFilesNotFound())
04431:                        _model.setProjectChanged(true);
04432:                    _completeClassList = new ArrayList<GoToFileListEntry>(); // reset auto-completion list
04433:                } catch (MalformedProjectFileException e) {
04434:                    _showProjectFileParseError(e); // add to an error adapter
04435:                    return;
04436:                } catch (FileNotFoundException e) {
04437:                    _showFileNotFoundError(e); // add to an error adapter
04438:                    return;
04439:                } catch (IOException e) {
04440:                    _showIOError(e); // add to an error adapter
04441:                    return;
04442:                }
04443:            }
04444:
04445:            private void _openProjectUpdate() {
04446:                if (_model.isProjectActive()) {
04447:                    _closeProjectAction.setEnabled(true);
04448:                    _saveProjectAction.setEnabled(true);
04449:                    _saveProjectAsAction.setEnabled(true);
04450:                    _projectPropertiesAction.setEnabled(true);
04451:                    //      _junitProjectAction.setEnabled(true);
04452:                    _junitProjectAction.setEnabled(true);
04453:                    //      _compileOpenProjectAction.setEnabled(true);
04454:                    _compileProjectAction.setEnabled(true);
04455:                    _jarProjectAction.setEnabled(true);
04456:                    if (_model.getBuildDirectory() != null)
04457:                        _cleanAction.setEnabled(true);
04458:                    _resetNavigatorPane();
04459:                    //      _compileButton.setToolTipText("<html>Compile all documents in the project.source tree<br>Auxiliary and external files are excluded.</html>");
04460:                }
04461:            }
04462:
04463:            boolean _closeProject() {
04464:                _completeClassList = new ArrayList<GoToFileListEntry>(); // reset auto-completion list
04465:                _autoImportClassList = new ArrayList<JavaAPIListEntry>(); // reset auto-import list
04466:                return _closeProject(false);
04467:            }
04468:
04469:            /** Closes project when DrJava is not in the process of quitting.
04470:             * @return true if the project is closed, false if cancelled.
04471:             */
04472:            boolean closeProject() {
04473:                updateStatusField("Closing current project");
04474:                return _closeProject();
04475:            }
04476:
04477:            /** Saves the project file; closes all open project files; and calls _model.closeProject(quitting) the 
04478:             * clean up the state of the global model.  It also restores the list view navigator
04479:             * @ param quitting whether the project is being closed as part of quitting DrJava
04480:             * @return true if the project is closed, false if cancelled
04481:             */
04482:            boolean _closeProject(boolean quitting) {
04483:                if (_checkProjectClose()) {
04484:                    List<OpenDefinitionsDocument> projDocs = _model
04485:                            .getProjectDocuments();
04486:                    //      System.err.println("projDocs = " + projDocs);
04487:                    boolean couldClose = _model.closeFiles(projDocs);
04488:                    if (!couldClose)
04489:                        return false;
04490:                    // project file has been saved and all files closed
04491:                    if (quitting)
04492:                        return true;
04493:                    _model.closeProject(quitting);
04494:
04495:                    Component renderer = _model.getDocumentNavigator()
04496:                            .getRenderer();
04497:                    new ForegroundColorListener(renderer);
04498:                    new BackgroundColorListener(renderer);
04499:                    _resetNavigatorPane();
04500:                    if (_model.getDocumentCount() == 1) {
04501:                        _model.setActiveFirstDocument();
04502:                    }
04503:                    _closeProjectAction.setEnabled(false);
04504:                    _saveProjectAction.setEnabled(false);
04505:                    _saveProjectAsAction.setEnabled(false);
04506:                    _projectPropertiesAction.setEnabled(false);
04507:                    //      _junitProjectAction.setEnabled(false);
04508:                    _jarProjectAction.setEnabled(false);
04509:                    _junitProjectAction.setEnabled(false);
04510:                    //      _compileOpenProjectAction.setEnabled(false);
04511:                    _compileProjectAction.setEnabled(false);
04512:                    _setUpContextMenus();
04513:                    _currentProjFile = null;
04514:                    //      _compileButton.setToolTipText("Compile all open documents");
04515:                    return true;
04516:                } else
04517:                    return false; // Project closing cancelled in _checkProjectClose dialog
04518:            }
04519:
04520:            private boolean _checkProjectClose() {
04521:                if (_model.isProjectChanged()) {
04522:                    String fname = _model.getProjectFile().getName();
04523:                    String text = fname
04524:                            + " has been modified. Would you like to save it?";
04525:                    int rc = JOptionPane.showConfirmDialog(MainFrame.this ,
04526:                            text, "Save " + fname + "?",
04527:                            JOptionPane.YES_NO_CANCEL_OPTION);
04528:                    switch (rc) {
04529:                    case JOptionPane.YES_OPTION:
04530:                        _saveProject();
04531:                        return true;
04532:                    case JOptionPane.NO_OPTION:
04533:                        return true;
04534:                    case JOptionPane.CLOSED_OPTION:
04535:                    case JOptionPane.CANCEL_OPTION:
04536:                        return false;
04537:                    default:
04538:                        throw new RuntimeException("Invalid rc: " + rc);
04539:                    }
04540:                }
04541:                return true;
04542:            }
04543:
04544:            public File getCurrentProject() {
04545:                return _currentProjFile;
04546:            }
04547:
04548:            /** Opens all the files returned by the FileOpenSelector prompting the user to handle the cases where files are 
04549:             *  already open, files are missing, or the action was canceled by the user
04550:             *  @param openSelector the selector that returns the files to open
04551:             */
04552:            public void open(FileOpenSelector openSelector) {
04553:                try {
04554:                    hourglassOn();
04555:                    _model.openFiles(openSelector);
04556:                } catch (AlreadyOpenException aoe) {
04557:                    OpenDefinitionsDocument[] openDocs = aoe.getOpenDocuments();
04558:                    for (OpenDefinitionsDocument openDoc : openDocs) {
04559:                        String fileName;
04560:                        try {
04561:                            fileName = openDoc.getFile().getName();
04562:                        } catch (IllegalStateException ise) {
04563:                            // Can't happen: this open document must have a file
04564:                            throw new UnexpectedException(ise);
04565:                        } catch (FileMovedException fme) {
04566:                            // File was deleted, but use the same name anyway
04567:                            fileName = fme.getFile().getName();
04568:                        }
04569:                        try {
04570:                            File f = openDoc.getFile();
04571:                            if (!_model.inProject(f))
04572:                                _recentFileManager.updateOpenFiles(f);
04573:                        } catch (IllegalStateException ise) {
04574:                            // Impossible: saved => has a file
04575:                            throw new UnexpectedException(ise);
04576:                        } catch (FileMovedException fme) {
04577:                            File f = fme.getFile();
04578:                            // Recover, show it in the list anyway
04579:                            if (!_model.inProject(f))
04580:                                _recentFileManager.updateOpenFiles(f);
04581:                        }
04582:                    }
04583:                } catch (OperationCanceledException oce) { /* do not open file */
04584:                } catch (FileNotFoundException fnf) {
04585:                    _showFileNotFoundError(fnf);
04586:                } catch (IOException ioe) {
04587:                    _showIOError(ioe);
04588:                } finally {
04589:                    hourglassOff();
04590:                }
04591:            }
04592:
04593:            /** Opens all the files in the directory returned by the FolderSelector.
04594:             *  @param chooser the selector that returns the files to open
04595:             */
04596:            public void openFolder(DirectoryChooser chooser) {
04597:                String type = "'."
04598:                        + DrJavaRoot.LANGUAGE_LEVEL_EXTENSIONS[DrJava
04599:                                .getConfig().getSetting(LANGUAGE_LEVEL)] + "' ";
04600:                chooser.setDialogTitle("Open All " + type + "Files in ...");
04601:
04602:                File openDir = null;
04603:                try {
04604:                    File activeFile = _model.getActiveDocument().getFile();
04605:                    if (activeFile != null)
04606:                        openDir = activeFile.getParentFile();
04607:                    else
04608:                        openDir = _model.getProjectRoot();
04609:                } catch (FileMovedException e) { /* do nothing */
04610:                }
04611:
04612:                int result = chooser.showDialog(openDir);
04613:                if (result != DirectoryChooser.APPROVE_OPTION)
04614:                    return; // canceled or error
04615:
04616:                File dir = chooser.getSelectedDirectory();
04617:                boolean rec = _openRecursiveCheckBox.isSelected();
04618:                DrJava.getConfig().setSetting(
04619:                        OptionConstants.OPEN_FOLDER_RECURSIVE,
04620:                        Boolean.valueOf(rec));
04621:                updateStatusField("Opening folder " + dir);
04622:                _openFolder(dir, rec);
04623:            }
04624:
04625:            /** Opens all the files in the specified directory; it opens all files in nested folders if rec is true.
04626:             *  @param dir the specified directory
04627:             *  @param rec true if files in nested folders should be opened
04628:             */
04629:            private void _openFolder(File dir, boolean rec) {
04630:                hourglassOn();
04631:                try {
04632:                    _model.openFolder(dir, rec);
04633:                } catch (AlreadyOpenException e) { /* do nothing */
04634:                } catch (IOException e) {
04635:                    _showIOError(e);
04636:                } catch (OperationCanceledException oce) { /* do nothing */
04637:                } finally {
04638:                    hourglassOff();
04639:                }
04640:            }
04641:
04642:            /** Delegates directly to the model to close the active document */
04643:            private void _close() {
04644:                //    LinkedList<OpenDefinitionsDocument> l = new LinkedList<OpenDefinitionsDocument>();
04645:                //    l.add(_model.getActiveDocument());
04646:                //    _model.closeFiles(l);
04647:
04648:                // this works with multiple selected files now
04649:                java.util.List<OpenDefinitionsDocument> l = _model
04650:                        .getDocumentNavigator().getSelectedDocuments();
04651:                boolean queryNecessary = false; // is a query necessary because the files are project or auxiliary files?
04652:                for (OpenDefinitionsDocument doc : l) {
04653:                    if ((_model.isProjectActive() && doc.inProjectPath())
04654:                            || doc.isAuxiliaryFile()) {
04655:                        queryNecessary = true;
04656:                        break;
04657:                    }
04658:                }
04659:                if (queryNecessary) {
04660:                    int rc;
04661:                    String fileName = null;
04662:                    Object[] options = { "Yes", "No" };
04663:                    if (l.size() == 1) {
04664:                        OpenDefinitionsDocument doc = l.get(0);
04665:                        try {
04666:                            if (doc.isUntitled())
04667:                                fileName = "File";
04668:                            else
04669:                                fileName = _model.getActiveDocument().getFile()
04670:                                        .getName();
04671:                        } catch (FileMovedException e) {
04672:                            fileName = e.getFile().getName();
04673:                        }
04674:                        String text = "Closing this file will permanently remove it from the current project."
04675:                                + "\nAre you sure that you want to close this file?";
04676:
04677:                        rc = JOptionPane.showOptionDialog(MainFrame.this , text,
04678:                                "Close " + fileName + "?",
04679:                                JOptionPane.YES_NO_OPTION,
04680:                                JOptionPane.QUESTION_MESSAGE, null, options,
04681:                                options[1]);
04682:                    } else {
04683:                        fileName = l.size() + " files";
04684:                        String text = "Closing these "
04685:                                + fileName
04686:                                + " will permanently remove them from the current project."
04687:                                + "\nAre you sure that you want to close these files?";
04688:
04689:                        rc = JOptionPane.showOptionDialog(MainFrame.this , text,
04690:                                "Close " + l.size() + " files?",
04691:                                JOptionPane.YES_NO_OPTION,
04692:                                JOptionPane.QUESTION_MESSAGE, null, options,
04693:                                options[1]);
04694:                    }
04695:                    if (rc != JOptionPane.YES_OPTION)
04696:                        return;
04697:
04698:                    updateStatusField("Closing " + fileName);
04699:                    _model.setProjectChanged(true);
04700:                }
04701:                // Either this is an external file or user actually wants to close it
04702:                for (OpenDefinitionsDocument doc : l) {
04703:                    _model.closeFile(doc);
04704:                }
04705:            }
04706:
04707:            private void _closeFolder() {
04708:                OpenDefinitionsDocument d;
04709:                Enumeration<OpenDefinitionsDocument> e = _model
04710:                        .getDocumentNavigator().getDocuments();
04711:                final LinkedList<OpenDefinitionsDocument> l = new LinkedList<OpenDefinitionsDocument>();
04712:                if (_model.getDocumentNavigator().isGroupSelected()) {
04713:                    while (e.hasMoreElements()) {
04714:                        d = e.nextElement();
04715:                        if (_model.getDocumentNavigator().isSelectedInGroup(d)) {
04716:                            l.add(d);
04717:                        }
04718:                    }
04719:                    _model.closeFiles(l);
04720:                    if (!l.isEmpty())
04721:                        _model.setProjectChanged(true);
04722:                }
04723:            }
04724:
04725:            private void _printDefDoc() {
04726:                try {
04727:                    _model.getActiveDocument().print();
04728:                } catch (FileMovedException fme) {
04729:                    _showFileMovedError(fme);
04730:                } catch (PrinterException e) {
04731:                    _showError(e, "Print Error",
04732:                            "An error occured while printing.");
04733:                } catch (BadLocationException e) {
04734:                    _showError(e, "Print Error",
04735:                            "An error occured while printing.");
04736:                }
04737:            }
04738:
04739:            private void _printConsole() {
04740:                try {
04741:                    _model.getConsoleDocument().print();
04742:                } catch (PrinterException e) {
04743:                    _showError(e, "Print Error",
04744:                            "An error occured while printing.");
04745:                }
04746:            }
04747:
04748:            private void _printInteractions() {
04749:                try {
04750:                    _model.getInteractionsDocument().print();
04751:                } catch (PrinterException e) {
04752:                    _showError(e, "Print Error",
04753:                            "An error occured while printing.");
04754:                }
04755:            }
04756:
04757:            /** Opens a new PrintPreview frame. */
04758:            private void _printDefDocPreview() {
04759:                try {
04760:                    _model.getActiveDocument().preparePrintJob();
04761:                    new PreviewDefDocFrame(_model, this );
04762:                } catch (FileMovedException fme) {
04763:                    _showFileMovedError(fme);
04764:                } catch (BadLocationException e) {
04765:                    _showError(e, "Print Error",
04766:                            "An error occured while preparing the print preview.");
04767:                } catch (IllegalStateException e) {
04768:                    _showError(e, "Print Error",
04769:                            "An error occured while preparing the print preview.");
04770:                }
04771:            }
04772:
04773:            private void _printConsolePreview() {
04774:                try {
04775:                    _model.getConsoleDocument().preparePrintJob();
04776:                    new PreviewConsoleFrame(_model, this , false);
04777:                } catch (IllegalStateException e) {
04778:                    _showError(e, "Print Error",
04779:                            "An error occured while preparing the print preview.");
04780:                }
04781:            }
04782:
04783:            private void _printInteractionsPreview() {
04784:                try {
04785:                    _model.getInteractionsDocument().preparePrintJob();
04786:                    new PreviewConsoleFrame(_model, this , true);
04787:                } catch (IllegalStateException e) {
04788:                    _showError(e, "Print Error",
04789:                            "An error occured while preparing the print preview.");
04790:                }
04791:            }
04792:
04793:            private void _pageSetup() {
04794:                PrinterJob job = PrinterJob.getPrinterJob();
04795:                _model.setPageFormat(job.pageDialog(_model.getPageFormat()));
04796:            }
04797:
04798:            //Called by testCases
04799:            void closeAll() {
04800:                _closeAll();
04801:            }
04802:
04803:            private void _closeAll() {
04804:                updateStatusField("Closing All Files");
04805:                if (!_model.isProjectActive() || _model.isProjectActive()
04806:                        && _closeProject())
04807:                    _model.closeAllFiles();
04808:            }
04809:
04810:            private boolean _save() {
04811:                updateStatusField("Saving File");
04812:                try {
04813:                    // now works with multiple files
04814:                    List<OpenDefinitionsDocument> l = _model
04815:                            .getDocumentNavigator().getSelectedDocuments();
04816:                    boolean success = false;
04817:                    for (OpenDefinitionsDocument doc : l) {
04818:                        if (doc.saveFile(_saveSelector)) {
04819:                            getDefPaneGivenODD(doc).hasWarnedAboutModified(
04820:                                    false);
04821:                            success = true;
04822:                        }
04823:                    }
04824:                    // _model.refreshActiveDocument() is not sufficient here; it does not re-select
04825:                    // the same document in flat-file mode
04826:                    _model.setActiveDocument(_model.getActiveDocument());
04827:                    return success;
04828:                    //      if (_model.getActiveDocument().saveFile(_saveSelector)) {
04829:                    //        _currentDefPane.hasWarnedAboutModified(false); 
04830:                    //        
04831:                    //        /**This highlights the document in the navigator */
04832:                    //        _model.setActiveDocument(_model.getActiveDocument());
04833:                    //        
04834:                    //        return true;
04835:                    //      }
04836:                    //      else return false;
04837:                } catch (IOException ioe) {
04838:                    _showIOError(ioe);
04839:                    return false;
04840:                }
04841:            }
04842:
04843:            private boolean _saveAs() {
04844:                updateStatusField("Saving File Under New Name");
04845:                try {
04846:                    boolean toReturn = _model.getActiveDocument().saveFileAs(
04847:                            _saveAsSelector);
04848:                    /** this highlights the document in the navigator */
04849:                    _model.setActiveDocument(_model.getActiveDocument());
04850:                    return toReturn;
04851:                } catch (IOException ioe) {
04852:                    _showIOError(ioe);
04853:                    return false;
04854:                }
04855:            }
04856:
04857:            private boolean _rename() {
04858:                try {
04859:                    if (!_model.getActiveDocument().fileExists())
04860:                        return _saveAs();
04861:                    else {
04862:                        File fileToDelete;
04863:                        try {
04864:                            fileToDelete = _model.getActiveDocument().getFile();
04865:                        } catch (FileMovedException fme) {
04866:                            return _saveAs();
04867:                        }
04868:                        boolean toReturn = _model.getActiveDocument()
04869:                                .saveFileAs(_saveAsSelector);
04870:                        /** Delete the old file if save was successful */
04871:                        if (toReturn
04872:                                && !_model.getActiveDocument().getFile()
04873:                                        .equals(fileToDelete))
04874:                            fileToDelete.delete();
04875:                        /** this highlights the document in the navigator */
04876:                        _model.setActiveDocument(_model.getActiveDocument());
04877:                        return toReturn;
04878:                    }
04879:                } catch (IOException ioe) {
04880:                    _showIOError(ioe);
04881:                    return false;
04882:                }
04883:            }
04884:
04885:            /* Package private to allow use in MainFrameTest. */
04886:            void _saveAll() {
04887:                hourglassOn();
04888:                try {
04889:                    if (_model.isProjectActive())
04890:                        _saveProject();
04891:                    _model.saveAllFiles(_saveSelector);
04892:                } catch (IOException ioe) {
04893:                    _showIOError(ioe);
04894:                } finally {
04895:                    hourglassOff();
04896:                }
04897:            }
04898:
04899:            // Called by the ProjectPropertiesFrame
04900:            void saveProject() {
04901:                _saveProject();
04902:            }
04903:
04904:            private void _saveProject() {
04905:                //File file = _model.getProjectFile();
04906:                _saveProjectHelper(_currentProjFile);
04907:            }
04908:
04909:            /** Edit project frame.  */
04910:            private void _editProject() {
04911:                ProjectPropertiesFrame ppf = new ProjectPropertiesFrame(this );
04912:                ppf.setVisible(true);
04913:                ppf.reset();
04914:                ppf.toFront(); // ppf actions save state of ppf in global model
04915:            }
04916:
04917:            /** Closes all files and makes a new project. */
04918:            private void _newProject() {
04919:
04920:                _closeProject(true); // suppress resetting interactions; it will be done in _model.newProject() below
04921:                _saveChooser.setFileFilter(_projectFilter);
04922:                int rc = _saveChooser.showSaveDialog(this );
04923:                if (rc == JFileChooser.APPROVE_OPTION) {
04924:                    File pf = _saveChooser.getSelectedFile(); // project file
04925:                    if (pf.exists() && !_verifyOverwrite()) {
04926:                        return;
04927:                    }
04928:
04929:                    String fileName = pf.getName();
04930:                    // ensure that saved file has extesion ".pjt"
04931:                    if (!fileName.endsWith(".pjt")) {
04932:                        int lastIndex = fileName.lastIndexOf(".");
04933:                        if (lastIndex == -1)
04934:                            pf = new File(pf.getAbsolutePath() + ".pjt");
04935:                        else
04936:                            pf = new File(fileName.substring(0, lastIndex)
04937:                                    + ".pjt");
04938:                    }
04939:
04940:                    _model.createNewProject(pf); // sets model to a new FileGroupingState for project file pf
04941:                    //      ProjectPropertiesFrame ppf = new ProjectPropertiesFrame(MainFrame.this, file);
04942:                    //      ppf.saveSettings();  // Saves new project profile in global model
04943:                    _editProject(); // edits the properties of the new FileGroupingState
04944:                    try {
04945:                        _model.configNewProject();
04946:                    } // configures the new project in the model
04947:                    catch (IOException e) {
04948:                        throw new UnexpectedException(e);
04949:                    }
04950:                    _currentProjFile = pf;
04951:                }
04952:            }
04953:
04954:            /** Pops up the _saveChooser dialog, asks the user for a new project file name, and sets the project file to the 
04955:             *  specified file.  Nothing is written in the file system; this action is performed by a subsequent _saveAll().
04956:             *  @return false if the user canceled the action */
04957:            private boolean _saveProjectAs() {
04958:
04959:                //    // This redundant-looking hack is necessary for JDK 1.3.1 on Mac OS X!
04960:                _saveChooser.removeChoosableFileFilter(_projectFilter);
04961:                _saveChooser.removeChoosableFileFilter(_javaSourceFilter);
04962:                _saveChooser.setFileFilter(_projectFilter);
04963:                //    File selection = _saveChooser.getSelectedFile();
04964:                //    if (selection != null) {  // what is this block of commands for?
04965:                //      _saveChooser.setSelectedFile(selection.getParentFile());
04966:                //      _saveChooser.setSelectedFile(selection);
04967:                //      _saveChooser.setSelectedFile(null);
04968:                //    }
04969:
04970:                if (_currentProjFile != null)
04971:                    _saveChooser.setSelectedFile(_currentProjFile);
04972:
04973:                int rc = _saveChooser.showSaveDialog(this );
04974:                if (rc == JFileChooser.APPROVE_OPTION) {
04975:                    File file = _saveChooser.getSelectedFile();
04976:                    if (!file.exists() || _verifyOverwrite()) {
04977:                        _model.setProjectFile(file);
04978:                        _currentProjFile = file;
04979:                    }
04980:                }
04981:
04982:                return (rc == JFileChooser.APPROVE_OPTION);
04983:            }
04984:
04985:            void _saveProjectHelper(File file) {
04986:                try {
04987:                    if (file.getName().indexOf(".") == -1)
04988:                        file = new File(file.getAbsolutePath() + ".pjt");
04989:                    String fileName = file.getCanonicalPath();
04990:                    _model.saveProject(file, gatherProjectDocInfo());
04991:                    //      if (!(_model.getDocumentNavigator() instanceof JTreeSortNavigator)) {
04992:                    //        _openProjectHelper(file);
04993:                    //      }    
04994:                } catch (IOException ioe) {
04995:                    _showIOError(ioe);
04996:                }
04997:                _recentProjectManager.updateOpenFiles(file);
04998:                _model.setProjectChanged(false);
04999:            }
05000:
05001:            public Hashtable<OpenDefinitionsDocument, DocumentInfoGetter> gatherProjectDocInfo() {
05002:                Hashtable<OpenDefinitionsDocument, DocumentInfoGetter> map = new Hashtable<OpenDefinitionsDocument, DocumentInfoGetter>();
05003:                List<OpenDefinitionsDocument> docs = _model
05004:                        .getProjectDocuments();
05005:                for (OpenDefinitionsDocument doc : docs) {
05006:                    map.put(doc, _makeInfoGetter(doc));
05007:                }
05008:                return map;
05009:            }
05010:
05011:            /** Gets the information to be save for a project document.
05012:             *  Implementation may change if the scroll/selection information is later stored in a place other than the
05013:             *  definitions pane.  Hopefully this info will eventually be backed up in the OpenDefinitionsDocument in which 
05014:             *  case all this code should be refactored into the model's _saveProject method
05015:             */
05016:            private DocumentInfoGetter _makeInfoGetter(
05017:                    final OpenDefinitionsDocument doc) {
05018:                JScrollPane s = _defScrollPanes.get(doc);
05019:                if (s == null) {
05020:                    s = _createDefScrollPane(doc);
05021:                }
05022:                final JScrollPane scroller = s;
05023:                final DefinitionsPane pane = (DefinitionsPane) scroller
05024:                        .getViewport().getView();
05025:
05026:                return new DocumentInfoGetter() {
05027:                    public Pair<Integer, Integer> getSelection() {
05028:                        Integer selStart = new Integer(pane.getSelectionStart());
05029:                        Integer selEnd = new Integer(pane.getSelectionEnd());
05030:                        if (pane.getCaretPosition() == selStart)
05031:                            return new Pair<Integer, Integer>(selEnd, selStart);
05032:                        return new Pair<Integer, Integer>(selStart, selEnd);
05033:                    }
05034:
05035:                    public Pair<Integer, Integer> getScroll() {
05036:                        Integer scrollv = new Integer(pane.getVerticalScroll());
05037:                        Integer scrollh = new Integer(pane
05038:                                .getHorizontalScroll());
05039:                        return new Pair<Integer, Integer>(scrollv, scrollh);
05040:                    }
05041:
05042:                    public File getFile() {
05043:                        return doc.getRawFile();
05044:                    }
05045:
05046:                    public String getPackage() {
05047:                        return doc.getPackageName();
05048:                    }
05049:
05050:                    public boolean isActive() {
05051:                        return _model.getActiveDocument() == doc;
05052:                    }
05053:
05054:                    public boolean isUntitled() {
05055:                        return doc.isUntitled();
05056:                    }
05057:                };
05058:            }
05059:
05060:            private void _revert() {
05061:                // this works with multiple selected files now
05062:                java.util.List<OpenDefinitionsDocument> l = _model
05063:                        .getDocumentNavigator().getSelectedDocuments();
05064:                for (OpenDefinitionsDocument d : l) {
05065:                    _revert(d);
05066:                }
05067:            }
05068:
05069:            private void _revert(OpenDefinitionsDocument doc) {
05070:                try {
05071:                    doc.revertFile();
05072:                } catch (FileMovedException fme) {
05073:                    _showFileMovedError(fme);
05074:                } catch (IOException ioe) {
05075:                    _showIOError(ioe);
05076:                }
05077:            }
05078:
05079:            /**
05080:             private void _revertAll() {
05081:             try {
05082:             _model.revertAllFiles();
05083:             }
05084:             catch (FileMovedException fme) {
05085:             _showFileMovedError(fme);
05086:             }
05087:             catch (IOException ioe) {
05088:             _showIOError(ioe);
05089:             }
05090:             }
05091:             */
05092:
05093:            private void _quit() {
05094:                //    AbstractGlobalModel._log.log("MainFrame.quit() called");
05095:                if (_promptBeforeQuit) {
05096:                    String title = "Quit DrJava?";
05097:                    String message = "Are you sure you want to quit DrJava?";
05098:                    ConfirmCheckBoxDialog dialog = new ConfirmCheckBoxDialog(
05099:                            MainFrame.this , title, message);
05100:                    int rc = dialog.show();
05101:                    if (rc != JOptionPane.YES_OPTION)
05102:                        return;
05103:                    else {
05104:                        // Only remember the checkbox if they say yes
05105:                        if (dialog.getCheckBoxValue() == true) {
05106:                            DrJava.getConfig().setSetting(QUIT_PROMPT,
05107:                                    Boolean.FALSE);
05108:                        }
05109:                    }
05110:                }
05111:                // tried passing false here. seemed to help with bug
05112:                // [ 1478796 ] DrJava Does Not Shut Down With Project Open
05113:                // on HP tc1100 and Toshiba Portege tablet PCs, but did not help in all cases
05114:                if (!_closeProject(true)) {
05115:                    return; /* if user pressed cancel, do not quit */
05116:                }
05117:
05118:                _recentFileManager.saveRecentFiles();
05119:                _recentProjectManager.saveRecentFiles();
05120:                if (!_model.closeAllFilesOnQuit()) {
05121:                    return; /* if user pressed cancel, do not quit */
05122:                }
05123:                _storePositionInfo();
05124:
05125:                // Save recent files, but only if there wasn't a problem at startUp
05126:                // (Don't want to overwrite a custom config file with a simple typo.)
05127:                if (!DrJava.getConfig().hadStartupException()) {
05128:                    try {
05129:                        DrJava.getConfig().saveConfiguration();
05130:                    } catch (IOException ioe) {
05131:                        _showIOError(ioe);
05132:                    }
05133:                }
05134:                //DrJava.consoleOut().println("Quitting DrJava...");
05135:                dispose(); // Free GUI elements of this frame
05136:                _model.quit();
05137:            }
05138:
05139:            private void _forceQuit() {
05140:                _model.forceQuit();
05141:            }
05142:
05143:            /** Stores the current position and size info for window and panes to the config framework. */
05144:            private void _storePositionInfo() {
05145:                Configuration config = DrJava.getConfig();
05146:
05147:                // Window bounds.
05148:                if (config.getSetting(WINDOW_STORE_POSITION).booleanValue()) {
05149:                    Rectangle bounds = getBounds();
05150:                    config
05151:                            .setSetting(WINDOW_HEIGHT, new Integer(
05152:                                    bounds.height));
05153:                    config.setSetting(WINDOW_WIDTH, new Integer(bounds.width));
05154:                    config.setSetting(WINDOW_X, new Integer(bounds.x));
05155:                    config.setSetting(WINDOW_Y, new Integer(bounds.y));
05156:                    config.setSetting(WINDOW_STATE, new Integer(
05157:                            getExtendedState()));
05158:                } else {
05159:                    // Reset to defaults to restore pristine behavior.
05160:                    config
05161:                            .setSetting(WINDOW_HEIGHT, WINDOW_HEIGHT
05162:                                    .getDefault());
05163:                    config.setSetting(WINDOW_WIDTH, WINDOW_WIDTH.getDefault());
05164:                    config.setSetting(WINDOW_X, WINDOW_X.getDefault());
05165:                    config.setSetting(WINDOW_Y, WINDOW_Y.getDefault());
05166:                    config.setSetting(WINDOW_STATE, WINDOW_STATE.getDefault());
05167:                }
05168:
05169:                // "Go to File" dialog position and size.
05170:                if ((DrJava.getConfig().getSetting(
05171:                        DIALOG_GOTOFILE_STORE_POSITION).booleanValue())
05172:                        && (_gotoFileDialog != null)
05173:                        && (_gotoFileDialog.getFrameState() != null)) {
05174:                    config.setSetting(DIALOG_GOTOFILE_STATE, (_gotoFileDialog
05175:                            .getFrameState().toString()));
05176:                } else {
05177:                    // Reset to defaults to restore pristine behavior.
05178:                    config.setSetting(DIALOG_GOTOFILE_STATE,
05179:                            DIALOG_GOTOFILE_STATE.getDefault());
05180:                }
05181:
05182:                // "Open Javadoc" dialog position and size.
05183:                if ((DrJava.getConfig().getSetting(
05184:                        DIALOG_OPENJAVADOC_STORE_POSITION).booleanValue())
05185:                        && (_openJavadocDialog != null)
05186:                        && (_openJavadocDialog.getFrameState() != null)) {
05187:                    config.setSetting(DIALOG_OPENJAVADOC_STATE,
05188:                            (_openJavadocDialog.getFrameState().toString()));
05189:                } else {
05190:                    // Reset to defaults to restore pristine behavior.
05191:                    config.setSetting(DIALOG_OPENJAVADOC_STATE,
05192:                            DIALOG_OPENJAVADOC_STATE.getDefault());
05193:                }
05194:
05195:                // "Complete Word" dialog position and size.
05196:                if ((DrJava.getConfig().getSetting(
05197:                        DIALOG_COMPLETE_WORD_STORE_POSITION).booleanValue())
05198:                        && (_completeWordDialog != null)
05199:                        && (_completeWordDialog.getFrameState() != null)) {
05200:                    config.setSetting(DIALOG_COMPLETE_WORD_STATE,
05201:                            (_completeWordDialog.getFrameState().toString()));
05202:                } else {
05203:                    // Reset to defaults to restore pristine behavior.
05204:                    config.setSetting(DIALOG_COMPLETE_WORD_STATE,
05205:                            DIALOG_COMPLETE_WORD_STATE.getDefault());
05206:                }
05207:
05208:                // "Create Jar from Project" dialog position and size.   
05209:                if ((DrJava.getConfig().getSetting(
05210:                        DIALOG_JAROPTIONS_STORE_POSITION).booleanValue())
05211:                        && (_jarOptionsDialog != null)
05212:                        && (_jarOptionsDialog.getFrameState() != null)) {
05213:                    config.setSetting(DIALOG_JAROPTIONS_STATE,
05214:                            (_jarOptionsDialog.getFrameState().toString()));
05215:                } else {
05216:                    // Reset to defaults to restore pristine behavior.
05217:                    config.setSetting(DIALOG_JAROPTIONS_STATE,
05218:                            DIALOG_JAROPTIONS_STATE.getDefault());
05219:                }
05220:
05221:                // Panel heights.
05222:                if (_showDebugger)
05223:                    config.setSetting(DEBUG_PANEL_HEIGHT, new Integer(
05224:                            _debugPanel.getHeight()));
05225:
05226:                // Doc list width.
05227:                config.setSetting(DOC_LIST_WIDTH, new Integer(_docSplitPane
05228:                        .getDividerLocation()));
05229:            }
05230:
05231:            private void _cleanUpForCompile() {
05232:                if (isDebuggerReady())
05233:                    _model.getDebugger().shutdown();
05234:            }
05235:
05236:            private void _compile() {
05237:                // now works with multiple files
05238:                _cleanUpForCompile();
05239:                hourglassOn();
05240:                try {
05241:                    //      final OpenDefinitionsDocument doc = _model.getActiveDocument();
05242:                    try {
05243:                        _model.getCompilerModel().compile(
05244:                                _model.getDocumentNavigator()
05245:                                        .getSelectedDocuments());
05246:                    } catch (FileMovedException fme) {
05247:                        _showFileMovedError(fme);
05248:                    } catch (IOException ioe) {
05249:                        _showIOError(ioe);
05250:                    }
05251:                } finally {
05252:                    hourglassOff();
05253:                }
05254:                //    update(getGraphics());
05255:            }
05256:
05257:            private void _compileFolder() {
05258:                _cleanUpForCompile();
05259:                hourglassOn();
05260:                try {
05261:                    OpenDefinitionsDocument d;
05262:                    Enumeration<OpenDefinitionsDocument> e = _model
05263:                            .getDocumentNavigator().getDocuments();
05264:                    final LinkedList<OpenDefinitionsDocument> l = new LinkedList<OpenDefinitionsDocument>();
05265:                    if (_model.getDocumentNavigator().isGroupSelected()) {
05266:                        while (e.hasMoreElements()) {
05267:                            d = e.nextElement();
05268:                            if (_model.getDocumentNavigator()
05269:                                    .isSelectedInGroup(d))
05270:                                l.add(d);
05271:                        }
05272:
05273:                        //        new Thread("Compile Folder") {
05274:                        //          public void run() {
05275:                        try {
05276:                            _model.getCompilerModel().compile(l);
05277:                        } catch (FileMovedException fme) {
05278:                            _showFileMovedError(fme);
05279:                        } catch (IOException ioe) {
05280:                            _showIOError(ioe);
05281:                        }
05282:                        //          }
05283:                        //        }.start();
05284:                    }
05285:                } finally {
05286:                    hourglassOff();
05287:                }
05288:                //    update(getGraphics()); 
05289:            }
05290:
05291:            private void _compileProject() {
05292:                _cleanUpForCompile();
05293:                //    new Thread("Compile All") {
05294:                //      public void run() {
05295:                hourglassOn();
05296:                try {
05297:                    _model.getCompilerModel().compileProject();
05298:                } catch (FileMovedException fme) {
05299:                    _showFileMovedError(fme);
05300:                } catch (IOException ioe) {
05301:                    _showIOError(ioe);
05302:                } finally {
05303:                    hourglassOff();
05304:                }
05305:                //      }
05306:                //    }.start();
05307:                //    update(getGraphics()); 
05308:            }
05309:
05310:            private void _compileAll() {
05311:                _cleanUpForCompile();
05312:                //    new Thread("Compile All") {
05313:                //      public void run() {
05314:                hourglassOn();
05315:                try {
05316:                    _model.getCompilerModel().compileAll();
05317:                } catch (FileMovedException fme) {
05318:                    _showFileMovedError(fme);
05319:                } catch (IOException ioe) {
05320:                    _showIOError(ioe);
05321:                } finally {
05322:                    hourglassOff();
05323:                }
05324:                //      }
05325:                //    }.start();
05326:                //    update(getGraphics()); 
05327:            }
05328:
05329:            private boolean showCleanWarning() {
05330:                if (DrJava.getConfig().getSetting(PROMPT_BEFORE_CLEAN)
05331:                        .booleanValue()) {
05332:                    String buildDirTxt = "";
05333:                    try {
05334:                        buildDirTxt = _model.getBuildDirectory()
05335:                                .getCanonicalPath();
05336:                    } catch (Exception e) {
05337:                        buildDirTxt = _model.getBuildDirectory().getPath();
05338:                    }
05339:                    ConfirmCheckBoxDialog dialog = new ConfirmCheckBoxDialog(
05340:                            MainFrame.this ,
05341:                            "Clean Build Directory?",
05342:                            "Cleaning your build directory will delete all\n"
05343:                                    + "class files and empty folders within that directory.\n"
05344:                                    + "Are you sure you want to clean\n"
05345:                                    + buildDirTxt + "?",
05346:                            "Do not show this message again");
05347:                    int rc = dialog.show();
05348:                    switch (rc) {
05349:                    case JOptionPane.YES_OPTION:
05350:                        _saveAll();
05351:                        // Only remember checkbox if they say yes
05352:                        if (dialog.getCheckBoxValue()) {
05353:                            DrJava.getConfig().setSetting(PROMPT_BEFORE_CLEAN,
05354:                                    Boolean.FALSE);
05355:                        }
05356:                        return true;
05357:                    case JOptionPane.NO_OPTION:
05358:                        return false;
05359:                    case JOptionPane.CANCEL_OPTION:
05360:                        return false;
05361:                    case JOptionPane.CLOSED_OPTION:
05362:                        return false;
05363:                    default:
05364:                        throw new RuntimeException(
05365:                                "Invalid rc from showConfirmDialog: " + rc);
05366:                    }
05367:                }
05368:                return true;
05369:            }
05370:
05371:            //  private void _clean() {
05372:            //    final SwingWorker worker = new SwingWorker() {
05373:            //      public Object construct() {
05374:            //        if (showCleanWarning()) {
05375:            //          try {
05376:            //            hourglassOn();
05377:            //            _model.cleanBuildDirectory();
05378:            //          }
05379:            //          catch (FileMovedException fme) { _showFileMovedError(fme); }
05380:            //          catch (IOException ioe) { _showIOError(ioe); }
05381:            //          finally { hourglassOff(); }
05382:            //        }
05383:            //        return null;
05384:            //      }
05385:            //    };
05386:            //    worker.start();
05387:            //  }
05388:
05389:            private void _clean() {
05390:                _model.cleanBuildDirectory(); // The model performs this as an AsyncTask
05391:            }
05392:
05393:            /** List with entries for the complete dialog. */
05394:            ArrayList<GoToFileListEntry> _completeClassList = new ArrayList<GoToFileListEntry>();
05395:
05396:            /** List with entries for the auto-import dialog. */
05397:            ArrayList<JavaAPIListEntry> _autoImportClassList = new ArrayList<JavaAPIListEntry>();
05398:
05399:            /** Scan the build directory for class files and update the auto-completion list. */
05400:            private void _scanClassFiles() {
05401:                Thread t = new Thread(new Runnable() {
05402:                    public void run() {
05403:                        File buildDir = _model.getBuildDirectory();
05404:                        HashSet<GoToFileListEntry> hs = new HashSet<GoToFileListEntry>();
05405:                        HashSet<JavaAPIListEntry> hs2 = new HashSet<JavaAPIListEntry>();
05406:                        if (buildDir != null) {
05407:                            List<File> classFiles = _model.getClassFiles();
05408:                            DummyOpenDefDoc dummyDoc = new DummyOpenDefDoc();
05409:                            for (File f : classFiles) {
05410:                                String s = f.toString();
05411:                                if (s.lastIndexOf(java.io.File.separatorChar) >= 0) {
05412:                                    s = s
05413:                                            .substring(s
05414:                                                    .lastIndexOf(java.io.File.separatorChar) + 1);
05415:                                }
05416:                                s = s.substring(0, s.lastIndexOf(".class"));
05417:                                s = s.replace('$', '.');
05418:                                int pos = 0;
05419:                                boolean ok = true;
05420:                                while ((pos = s.indexOf('.', pos)) >= 0) {
05421:                                    if ((s.length() <= pos + 1)
05422:                                            || (Character.isDigit(s
05423:                                                    .charAt(pos + 1)))) {
05424:                                        ok = false;
05425:                                        break;
05426:                                    }
05427:                                    ++pos;
05428:                                }
05429:                                if (ok) {
05430:                                    if (s.lastIndexOf('.') >= 0) {
05431:                                        s = s.substring(s.lastIndexOf('.') + 1);
05432:                                    }
05433:                                    GoToFileListEntry entry = new GoToFileListEntry(
05434:                                            dummyDoc, s);
05435:                                    hs.add(entry);
05436:                                    try {
05437:                                        File rel = FileOps.makeRelativeTo(f,
05438:                                                buildDir);
05439:                                        String full = rel
05440:                                                .toString()
05441:                                                .replace(
05442:                                                        java.io.File.separatorChar,
05443:                                                        '.');
05444:                                        full = full.substring(0, full
05445:                                                .lastIndexOf(".class"));
05446:                                        if (full.indexOf('$') < 0) {
05447:                                            // no $ in the name means not an inner class
05448:                                            // we do not support inner classes, because that would mean
05449:                                            // having to determine public static scope
05450:                                            hs2.add(new JavaAPIListEntry(s,
05451:                                                    full, null));
05452:                                        }
05453:                                    } catch (IOException ioe) { /* ignore, just don't add this one */
05454:                                    } catch (SecurityException se) { /* ignore, just don't add this one */
05455:                                    }
05456:                                }
05457:                            }
05458:                        }
05459:                        _completeClassList = new ArrayList<GoToFileListEntry>(
05460:                                hs);
05461:                        _autoImportClassList = new ArrayList<JavaAPIListEntry>(
05462:                                hs2);
05463:                    }
05464:                });
05465:                t.setPriority(Thread.MIN_PRIORITY);
05466:                t.start();
05467:            }
05468:
05469:            private void _runProject() {
05470:                if (_model.isProjectActive()) {
05471:                    try {
05472:                        final File f = _model.getMainClass();
05473:                        if (f != null) {
05474:                            updateStatusField("Running Open Project");
05475:                            OpenDefinitionsDocument doc = _model
05476:                                    .getDocumentForFile(f);
05477:                            doc.runMain();
05478:                        }
05479:                    } catch (ClassNameNotFoundException e) {
05480:                        // Display a warning message if a class name can't be found.
05481:                        String msg = "DrJava could not find the top level class name in the\n"
05482:                                + "current document, so it could not run the class.  Please\n"
05483:                                + "make sure that the class is properly defined first.";
05484:
05485:                        JOptionPane.showMessageDialog(MainFrame.this , msg,
05486:                                "No Class Found", JOptionPane.ERROR_MESSAGE);
05487:                    } catch (FileMovedException fme) {
05488:                        _showFileMovedError(fme);
05489:                    } catch (IOException ioe) {
05490:                        _showIOError(ioe);
05491:                    }
05492:                } else
05493:                    _runMain();
05494:            }
05495:
05496:            /** Internal helper method to run the main method of the current document in the interactions pane. */
05497:            private void _runMain() {
05498:                updateStatusField("Running main Method of Current Document");
05499:
05500:                try {
05501:                    _model.getActiveDocument().runMain();
05502:                }
05503:
05504:                catch (ClassNameNotFoundException e) {
05505:                    // Display a warning message if a class name can't be found.
05506:                    String msg = "DrJava could not find the top level class name in the\n"
05507:                            + "current document, so it could not run the class.  Please\n"
05508:                            + "make sure that the class is properly defined first.";
05509:
05510:                    JOptionPane.showMessageDialog(MainFrame.this , msg,
05511:                            "No Class Found", JOptionPane.ERROR_MESSAGE);
05512:                } catch (FileMovedException fme) {
05513:                    _showFileMovedError(fme);
05514:                } catch (IOException ioe) {
05515:                    _showIOError(ioe);
05516:                }
05517:            }
05518:
05519:            private void _junit() {
05520:                hourglassOn(); // turned off in JUnitStarted/NonTestCase  
05521:                new Thread("Run JUnit on Current Document") {
05522:                    public void run() {
05523:                        _disableJUnitActions();
05524:                        // now also works with multiple documents
05525:                        //        hourglassOn();  // moved into the prelude before this thread start  
05526:                        try {
05527:                            _model.getJUnitModel().junitDocs(
05528:                                    _model.getDocumentNavigator()
05529:                                            .getSelectedDocuments());
05530:                            //          _model.getActiveDocument().startJUnit();  // Equivalent to preceding
05531:                        }
05532:
05533:                        //        catch (FileMovedException fme) { _showFileMovedError(fme); }
05534:                        //        catch (IOException ioe) { _showIOError(ioe); }
05535:                        //        catch (ClassNotFoundException cnfe) { _showClassNotFoundError(cnfe); }
05536:                        catch (NoClassDefFoundError ncde) {
05537:                            _showNoClassDefError(ncde);
05538:                        }
05539:                    }
05540:                }.start();
05541:            }
05542:
05543:            private void _junitFolder() {
05544:                updateStatusField("Running Unit Tests in Current Folder");
05545:                hourglassOn(); // turned off when JUnitStarted event is fired
05546:                new Thread("Run JUnit on specified folder") {
05547:                    public void run() {
05548:                        INavigatorItem n;
05549:                        _disableJUnitActions();
05550:                        //        hourglassOn();  // turned off when JUnitStarted event is fired
05551:                        if (_model.getDocumentNavigator().isGroupSelected()) {
05552:                            Enumeration<OpenDefinitionsDocument> docs = _model
05553:                                    .getDocumentNavigator().getDocuments();
05554:                            final LinkedList<OpenDefinitionsDocument> l = new LinkedList<OpenDefinitionsDocument>();
05555:                            while (docs.hasMoreElements()) {
05556:                                OpenDefinitionsDocument doc = docs
05557:                                        .nextElement();
05558:                                if (_model.getDocumentNavigator()
05559:                                        .isSelectedInGroup(doc))
05560:                                    l.add(doc);
05561:                            }
05562:                            try {
05563:                                _model.getJUnitModel().junitDocs(l);
05564:                            } catch (UnexpectedException e) {
05565:                                _junitInterrupted(e);
05566:                            }
05567:                        }
05568:                    }
05569:                }.start();
05570:            }
05571:
05572:            /** Tests the documents in the project source tree. Assumes that DrJava is in project mode. */
05573:            private void _junitProject() {
05574:                updateStatusField("Running JUnit Tests in Project");
05575:                hourglassOn(); // turned off in JUnitStarted/NonTestCase event
05576:                new Thread("Running Junit Tests") {
05577:                    public void run() {
05578:                        _disableJUnitActions();
05579:                        //        hourglassOn();  // turned off in JUnitStarted/NonTestCase event
05580:                        try {
05581:                            _model.getJUnitModel().junitProject();
05582:                        } catch (UnexpectedException e) {
05583:                            _junitInterrupted(e);
05584:                        }
05585:                    }
05586:                }.start();
05587:            }
05588:
05589:            /** Tests all open documents. */
05590:            private void _junitAll() {
05591:                updateStatusField("Running All Open Unit Tests");
05592:                hourglassOn(); // turned off in JUnitStarted/NonTestCase event
05593:                new Thread("Running Junit Tests") {
05594:                    public void run() {
05595:                        _disableJUnitActions();
05596:                        //        hourglassOn();  // turned off in JUnitStarted/NonTestCase event
05597:                        try {
05598:                            _model.getJUnitModel().junitAll();
05599:                        } catch (UnexpectedException e) {
05600:                            _junitInterrupted(e);
05601:                        }
05602:                    }
05603:                }.start();
05604:            }
05605:
05606:            /* These are used to save the state of the enabled property of the actions disabled during junit testing. */
05607:            private volatile DecoratedAction _junit_compileProjectDecoratedAction;
05608:            private volatile DecoratedAction _junit_compileAllDecoratedAction;
05609:            private volatile DecoratedAction _junit_compileFolderDecoratedAction;
05610:            private volatile DecoratedAction _junit_junitFolderDecoratedAction;
05611:            private volatile DecoratedAction _junit_junitAllDecoratedAction;
05612:            private volatile DecoratedAction _junit_junitDecoratedAction;
05613:            private volatile DecoratedAction _junit_junitOpenProjectFilesDecoratedAction;
05614:            private volatile DecoratedAction _junit_cleanDecoratedAction;
05615:            private volatile DecoratedAction _junit_projectPropertiesDecoratedAction;
05616:            private volatile DecoratedAction _junit_runProjectDecoratedAction;
05617:            private volatile DecoratedAction _junit_runDecoratedAction;
05618:
05619:            /** An AbstractAction that prevents changes to the decoree's enabled flag. */
05620:            private class DecoratedAction extends AbstractAction {
05621:                /** The AbstractAction that is being decorated. */
05622:                AbstractAction _decoree;
05623:                /** The "shallow" enabled flag. */
05624:                boolean _shallowEnabled;
05625:
05626:                /** Create an action decorating the specified action, then sets the decoree's enabled flag to b. */
05627:                public DecoratedAction(AbstractAction a, boolean b) {
05628:                    super ((String) a.getValue("Name"));
05629:                    _decoree = a;
05630:                    _shallowEnabled = _decoree.isEnabled();
05631:                    _decoree.setEnabled(b);
05632:                }
05633:
05634:                public void actionPerformed(ActionEvent ae) {
05635:                    _decoree.actionPerformed(ae);
05636:                }
05637:
05638:                /** Do not change the decoree's enabled flag, but cache this value in the shallow enabled flag. */
05639:                public void setEnabled(boolean b) {
05640:                    _shallowEnabled = b;
05641:                }
05642:
05643:                /** Write the shallow enabled flag to the decoree, then return the decoree */
05644:                public AbstractAction getUpdatedDecoree() {
05645:                    _decoree.setEnabled(_shallowEnabled);
05646:                    return _decoree;
05647:                }
05648:            }
05649:
05650:            /** Sets the enabled status to false of all actions that  could conflict with JUnit while its is running a test.
05651:             *  This method saves aside the previous enable state of each action so that when the test is finished, any action
05652:             *  disabled before the test will remain disabled afterward.
05653:             */
05654:            private void _disableJUnitActions() {
05655:                // _compileProjectActionEnabled = _compileProjectAction.isEnabled();
05656:                // _compileAllActionEnabled = _compileAllAction.isEnabled();
05657:                //_compileFolderActionEnabled = _compileFolderAction.isEnabled();
05658:                //_junitFolderActionEnabled = _junitFolderAction.isEnabled();
05659:                //_junitAllActionEnabled = _junitAllAction.isEnabled();
05660:                //_junitActionEnabled = _junitAction.isEnabled();
05661:                //_junitProjectActionEnabled = _junitProjectAction.isEnabled();
05662:                //_cleanActionEnabled = _cleanAction.isEnabled();
05663:                //_projectPropertiesActionEnabled = _projectPropertiesAction.isEnabled();
05664:                //_runProjectActionEnabled = _runProjectAction.isEnabled();
05665:
05666:                // _compileProjectAction.setEnabled(false);
05667:                //_compileAllAction.setEnabled(false);
05668:                //_compileFolderAction.setEnabled(false);
05669:                //_junitFolderAction.setEnabled(false);
05670:                //_junitAllAction.setEnabled(false);
05671:                //_junitAction.setEnabled(false);
05672:                //_junitProjectAction.setEnabled(false);
05673:                //_cleanAction.setEnabled(false);
05674:                //_projectPropertiesAction.setEnabled(false);
05675:                //_runProjectAction.setEnabled(false);
05676:
05677:                _compileProjectAction = _junit_compileProjectDecoratedAction = new DecoratedAction(
05678:                        _compileProjectAction, false);
05679:                _compileAllAction = _junit_compileAllDecoratedAction = new DecoratedAction(
05680:                        _compileAllAction, false);
05681:                _compileFolderAction = _junit_compileFolderDecoratedAction = new DecoratedAction(
05682:                        _compileFolderAction, false);
05683:                _junitFolderAction = _junit_junitFolderDecoratedAction = new DecoratedAction(
05684:                        _junitFolderAction, false);
05685:                _junitAllAction = _junit_junitAllDecoratedAction = new DecoratedAction(
05686:                        _junitAllAction, false);
05687:                _junitAction = _junit_junitDecoratedAction = new DecoratedAction(
05688:                        _junitAction, false);
05689:                _junitProjectAction = _junit_junitOpenProjectFilesDecoratedAction = new DecoratedAction(
05690:                        _junitProjectAction, false);
05691:                _cleanAction = _junit_cleanDecoratedAction = new DecoratedAction(
05692:                        _cleanAction, false);
05693:                _projectPropertiesAction = _junit_projectPropertiesDecoratedAction = new DecoratedAction(
05694:                        _projectPropertiesAction, false);
05695:                _runProjectAction = _junit_runProjectDecoratedAction = new DecoratedAction(
05696:                        _runProjectAction, false);
05697:                _runAction = _junit_runDecoratedAction = new DecoratedAction(
05698:                        _runAction, false);
05699:            }
05700:
05701:            private void _restoreJUnitActionsEnabled() {
05702:                //    _compileProjectAction.setEnabled(_compileProjectActionEnabled);
05703:                //    _compileAllAction.setEnabled(_compileAllActionEnabled);
05704:                //    //_compileOpenProjectAction.setEnabled(_compileOpenProjectActionEnabled);
05705:                //    _compileFolderAction.setEnabled(_compileFolderActionEnabled);
05706:                //    _junitFolderAction.setEnabled(_junitFolderActionEnabled);
05707:                //    _junitAllAction.setEnabled(_junitAllActionEnabled);
05708:                //    _junitAction.setEnabled(_junitActionEnabled);
05709:                //    _junitProjectAction.setEnabled(_junitProjectActionEnabled);
05710:                //    //_junitProjectAction.setEnabled(_junitProjectActionEnabled);
05711:                //    _cleanAction.setEnabled(_cleanActionEnabled);
05712:                //    _projectPropertiesAction.setEnabled(_projectPropertiesActionEnabled);
05713:                //    _runProjectAction.setEnabled(_runProjectActionEnabled);
05714:
05715:                _compileProjectAction = _junit_compileProjectDecoratedAction
05716:                        .getUpdatedDecoree();
05717:                _compileAllAction = _junit_compileAllDecoratedAction
05718:                        .getUpdatedDecoree();
05719:                _compileFolderAction = _junit_compileFolderDecoratedAction
05720:                        .getUpdatedDecoree();
05721:                _junitFolderAction = _junit_junitFolderDecoratedAction
05722:                        .getUpdatedDecoree();
05723:                _junitAllAction = _junit_junitAllDecoratedAction
05724:                        .getUpdatedDecoree();
05725:                _junitAction = _junit_junitDecoratedAction.getUpdatedDecoree();
05726:                _junitProjectAction = _junit_junitOpenProjectFilesDecoratedAction
05727:                        .getUpdatedDecoree();
05728:                _cleanAction = _junit_cleanDecoratedAction.getUpdatedDecoree();
05729:                _projectPropertiesAction = _junit_projectPropertiesDecoratedAction
05730:                        .getUpdatedDecoree();
05731:                _runProjectAction = _junit_runProjectDecoratedAction
05732:                        .getUpdatedDecoree();
05733:                _runAction = _junit_runDecoratedAction.getUpdatedDecoree();
05734:            }
05735:
05736:            //  /**
05737:            //   * Suspends the current execution of the debugger
05738:            //   */
05739:            //  private void debuggerSuspend() throws DebugException {
05740:            //    if (isDebuggerReady())
05741:            //      _model.getDebugger().suspend();
05742:            //  }
05743:
05744:            /** Resumes the debugger's current execution. */
05745:            void debuggerResume() throws DebugException {
05746:                if (isDebuggerReady()) {
05747:                    _model.getDebugger().resume();
05748:                    _removeThreadLocationHighlight();
05749:                }
05750:            }
05751:
05752:            /** Steps in the debugger. */
05753:            void debuggerStep(Debugger.StepType type) {
05754:                if (isDebuggerReady()) {
05755:                    try {
05756:                        _model.getDebugger().step(type);
05757:                    } catch (IllegalStateException ise) {
05758:                        // This may happen if the user if stepping very frequently,
05759:                        // and is even more likely if they are using both hotkeys
05760:                        // and UI buttons. Ignore it in this case.
05761:                        // Hopefully, there are no other situations where
05762:                        // the user can be trying to step while there are no
05763:                        // suspended threads.
05764:                    } catch (DebugException de) {
05765:                        _showError(de, "Debugger Error",
05766:                                "Could not create a step request.");
05767:                    }
05768:                }
05769:            }
05770:
05771:            /** Toggles a breakpoint on the current line. */
05772:            void debuggerToggleBreakpoint() {
05773:                addToBrowserHistory();
05774:                OpenDefinitionsDocument doc = _model.getActiveDocument();
05775:
05776:                boolean isUntitled = doc.isUntitled();
05777:                if (isUntitled) {
05778:                    JOptionPane.showMessageDialog(this ,
05779:                            "You must save and compile this document before you can\n"
05780:                                    + "set a breakpoint in it.",
05781:                            "Must Save and Compile", JOptionPane.ERROR_MESSAGE);
05782:                    return;
05783:                }
05784:
05785:                boolean isModified = doc.isModifiedSinceSave();
05786:                if (isDebuggerReady()
05787:                        && isModified
05788:                        && !_currentDefPane.hasWarnedAboutModified()
05789:                        && DrJava.getConfig().getSetting(
05790:                                WARN_BREAKPOINT_OUT_OF_SYNC).booleanValue()) {
05791:                    String message = "This document has been modified and may be out of sync\n"
05792:                            + "with the debugger.  It is recommended that you first\n"
05793:                            + "save and recompile before continuing to use the debugger,\n"
05794:                            + "to avoid any unexpected errors.  Would you still like to\n"
05795:                            + "toggle the breakpoint on the specified line?";
05796:                    String title = "Toggle breakpoint on modified file?";
05797:
05798:                    ConfirmCheckBoxDialog dialog = new ConfirmCheckBoxDialog(
05799:                            this , title, message);
05800:                    int rc = dialog.show();
05801:                    switch (rc) {
05802:                    case JOptionPane.YES_OPTION:
05803:                        _currentDefPane.hasWarnedAboutModified(true);
05804:                        if (dialog.getCheckBoxValue()) {
05805:                            DrJava.getConfig().setSetting(
05806:                                    WARN_BREAKPOINT_OUT_OF_SYNC, Boolean.FALSE);
05807:                        }
05808:                        break;
05809:
05810:                    case JOptionPane.NO_OPTION:
05811:                        if (dialog.getCheckBoxValue())
05812:                            DrJava.getConfig().setSetting(
05813:                                    WARN_BREAKPOINT_OUT_OF_SYNC, Boolean.FALSE);
05814:                        return;
05815:
05816:                    case JOptionPane.CANCEL_OPTION:
05817:                    case JOptionPane.CLOSED_OPTION:
05818:                        // do nothing
05819:                        return;
05820:
05821:                    default:
05822:                        throw new RuntimeException(
05823:                                "Invalid rc from showConfirmDialog: " + rc);
05824:                    }
05825:                }
05826:
05827:                try {
05828:                    Debugger debugger = _model.getDebugger();
05829:                    debugger.toggleBreakpoint(doc, _currentDefPane
05830:                            .getCaretPosition(), _currentDefPane
05831:                            .getCurrentLine(), true);
05832:                } catch (DebugException de) {
05833:                    _showError(de, "Debugger Error",
05834:                            "Could not set a breakpoint at the current line.");
05835:                }
05836:            }
05837:
05838:            //  private void _getText(String name) { _field = name; }
05839:
05840:            //  /** Adds a watch to a given variable or field. */
05841:            //  void debuggerAddWatch() {
05842:            //    if (isDebuggerReady()) {
05843:            //      //final String field;
05844:            //      OpenDefinitionsDocument doc = _model.getActiveDocument();
05845:            //      final JDialog getFieldDialog = new JDialog(this, "Choose Field to be Watched", true);
05846:            //      //getFieldDialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
05847:            //      final JTextField fieldName = new JTextField();
05848:            //      getFieldDialog.setSize(new Dimension(150, 60));
05849:            //      getFieldDialog.getContentPane().add(fieldName);
05850:            //      fieldName.addActionListener(new ActionListener() {
05851:            //        public void actionPerformed(ActionEvent ae) {
05852:            //          _getText(fieldName.getText());
05853:            //          getFieldDialog.dispose();
05854:            //        }
05855:            //      });
05856:            //      getFieldDialog.setLocation(300,300);
05857:            //      getFieldDialog.show();
05858:            //      Debugger debugger = _model.getDebugger();
05859:            //      debugger.addWatch(_field);
05860:            //    }
05861:            //  }
05862:
05863:            //  /** Displays all breakpoints currently set in the debugger. */
05864:            //  void _printBreakpoints() { _model.getDebugger().printBreakpoints(); }
05865:
05866:            /** Clears all breakpoints from the debugger. */
05867:            void debuggerClearAllBreakpoints() {
05868:                _model.getBreakpointManager().clearRegions();
05869:            }
05870:
05871:            void _showFileMovedError(FileMovedException fme) {
05872:                try {
05873:                    File f = fme.getFile();
05874:                    OpenDefinitionsDocument doc = _model.getDocumentForFile(f);
05875:                    if (doc != null
05876:                            && _saveSelector.shouldSaveAfterFileMoved(doc, f))
05877:                        _saveAs();
05878:                } catch (IOException ioe) { /* Couldn't find the document, so ignore the FME */
05879:                }
05880:            }
05881:
05882:            void _showProjectFileParseError(MalformedProjectFileException mpfe) {
05883:                _showError(mpfe, "Invalid Project File",
05884:                        "DrJava could not read the given project file.");
05885:            }
05886:
05887:            void _showFileNotFoundError(FileNotFoundException fnf) {
05888:                _showError(fnf, "File Not Found",
05889:                        "The specified file was not found on disk.");
05890:            }
05891:
05892:            void _showIOError(IOException ioe) {
05893:                _showError(ioe, "Input/output error",
05894:                        "An I/O exception occurred during the last operation.");
05895:            }
05896:
05897:            void _showClassNotFoundError(ClassNotFoundException cnfe) {
05898:                _showError(
05899:                        cnfe,
05900:                        "Class Not Found",
05901:                        "A ClassNotFound exception occurred during the last operation.\n"
05902:                                + "Please check that your classpath includes all relevant directories.\n\n");
05903:            }
05904:
05905:            void _showNoClassDefError(NoClassDefFoundError ncde) {
05906:                _showError(
05907:                        ncde,
05908:                        "No Class Def",
05909:                        "A NoClassDefFoundError occurred during the last operation.\n"
05910:                                + "Please check that your classpath includes all relevant paths.\n\n");
05911:            }
05912:
05913:            void _showDebugError(DebugException de) {
05914:                _showError(de, "Debug Error",
05915:                        "A Debugger error occurred in the last operation.\n\n");
05916:            }
05917:
05918:            void _showJUnitInterrupted(UnexpectedException e) {
05919:                _showWarning(
05920:                        e.getCause(),
05921:                        "JUnit Testing Interrupted",
05922:                        "The slave JVM has thrown a RemoteException probably indicating that it has been reset.\n\n");
05923:            }
05924:
05925:            private void _showError(Throwable e, String title, String message) {
05926:                JOptionPane.showMessageDialog(this , message + "\n" + e, title,
05927:                        JOptionPane.ERROR_MESSAGE);
05928:            }
05929:
05930:            private void _showWarning(Throwable e, String title, String message) {
05931:                JOptionPane.showMessageDialog(this , message + "\n" + e, title,
05932:                        JOptionPane.WARNING_MESSAGE);
05933:            }
05934:
05935:            /** Check if any errors occurred while parsing the config file, and display a message if necessary. */
05936:            private void _showConfigException() {
05937:                if (DrJava.getConfig().hadStartupException()) {
05938:                    Exception e = DrJava.getConfig().getStartupException();
05939:                    _showError(
05940:                            e,
05941:                            "Error in Config File",
05942:                            "Could not read the '.drjava' configuration file\n"
05943:                                    + "in your home directory.  Starting with default\n"
05944:                                    + "values instead.\n\n"
05945:                                    + "The problem was:\n");
05946:                }
05947:            }
05948:
05949:            /** Returns the File selected by the JFileChooser.
05950:             *  @param fc File chooser presented to the user
05951:             *  @param choice return value from fc
05952:             *  @return Selected File
05953:             *  @throws OperationCanceledException if file choice canceled
05954:             *  @throws RuntimeException if fc returns a bad file or choice
05955:             */
05956:            private File getChosenFile(JFileChooser fc, int choice)
05957:                    throws OperationCanceledException {
05958:                switch (choice) {
05959:                case JFileChooser.CANCEL_OPTION:
05960:                case JFileChooser.ERROR_OPTION:
05961:                    throw new OperationCanceledException();
05962:                case JFileChooser.APPROVE_OPTION:
05963:                    File chosen = fc.getSelectedFile();
05964:                    if (chosen != null) {
05965:                        //append the appropriate language level extension if not written by user
05966:                        if (fc.getFileFilter() instanceof  JavaSourceFilter) {
05967:                            if (chosen.getName().indexOf(".") == -1)
05968:                                return new File(
05969:                                        chosen.getAbsolutePath()
05970:                                                + "."
05971:                                                + DrJavaRoot.LANGUAGE_LEVEL_EXTENSIONS[DrJava
05972:                                                        .getConfig()
05973:                                                        .getSetting(
05974:                                                                LANGUAGE_LEVEL)]);
05975:                        }
05976:                        return chosen;
05977:                    } else
05978:                        throw new RuntimeException(
05979:                                "Filechooser returned null file");
05980:                default: // impossible since rc must be one of these
05981:                    throw new RuntimeException("Filechooser returned bad rc "
05982:                            + choice);
05983:                }
05984:            }
05985:
05986:            /**
05987:             * Returns the Files selected by the JFileChooser.
05988:             * @param fc File chooser presented to the user
05989:             * @param choice return value from fc
05990:             * @return Selected Files - this array will be size 1 for single-selection dialogs.
05991:             * @throws OperationCanceledException if file choice canceled
05992:             * @throws RuntimeException if fc returns a bad file or choice
05993:             */
05994:            private File[] getChosenFiles(JFileChooser fc, int choice)
05995:                    throws OperationCanceledException {
05996:                switch (choice) {
05997:                case JFileChooser.CANCEL_OPTION:
05998:                case JFileChooser.ERROR_OPTION:
05999:                    throw new OperationCanceledException();
06000:                case JFileChooser.APPROVE_OPTION:
06001:                    File[] chosen = fc.getSelectedFiles();
06002:                    if (chosen == null)
06003:                        throw new UnexpectedException(
06004:                                new OperationCanceledException(),
06005:                                "filechooser returned null file");
06006:
06007:                    // Following code reviewed for bug 70902-- JVF
06008:                    // If this is a single-selection dialog, getSelectedFiles() will always
06009:                    // return a zero-size array -- handle it differently.
06010:                    if (chosen.length == 0) {
06011:                        if (!fc.isMultiSelectionEnabled()) {
06012:                            return new File[] { fc.getSelectedFile() };
06013:                        } else {
06014:                            /* This is the workaround for bug 70902: sometimes Mac OS X will return
06015:                             * APPROVE_OPTION when the user clicks the close (x) control button
06016:                             * on the dialog window, even though nothing is selected.
06017:                             */
06018:                            throw new OperationCanceledException();
06019:                        }
06020:                    } else {
06021:                        return chosen;
06022:                    }
06023:
06024:                default: // impossible since rc must be one of these
06025:                    throw new UnexpectedException(
06026:                            new OperationCanceledException(),
06027:                            "filechooser returned bad rc " + choice);
06028:                }
06029:            }
06030:
06031:            private void _selectAll() {
06032:                _currentDefPane.selectAll();
06033:            }
06034:
06035:            /** Jump to the specified line and return the offset.  Only runs in event thread.
06036:             * @return offset */
06037:            public int _jumpToLine(int lineNum) {
06038:                int pos = _model.getActiveDocument().gotoLine(lineNum);
06039:                _currentDefPane.setCaretPosition(pos);
06040:                _currentDefPane.centerViewOnOffset(pos);
06041:                return pos;
06042:            }
06043:
06044:            /** Ask the user what line they'd like to jump to, then go there. */
06045:            private int _gotoLine() {
06046:                final String msg = "What line would you like to go to?";
06047:                final String title = "Go to Line";
06048:                String lineStr = JOptionPane.showInputDialog(this , msg, title,
06049:                        JOptionPane.QUESTION_MESSAGE);
06050:                try {
06051:                    if (lineStr != null) {
06052:                        int lineNum = Integer.parseInt(lineStr);
06053:                        return _jumpToLine(lineNum);
06054:                    }
06055:                } catch (NumberFormatException nfe) {
06056:                    // invalid input for line number
06057:                    Toolkit.getDefaultToolkit().beep();
06058:                    // Do nothing.
06059:                }
06060:                //catch (BadLocationException ble) { }
06061:                return -1;
06062:            }
06063:
06064:            /** Removes the ErrorCaretListener corresponding to the given document, after that document has been closed.
06065:             *  (Allows pane and listener to be garbage collected...)
06066:             */
06067:            private void _removeErrorListener(OpenDefinitionsDocument doc) {
06068:                JScrollPane scroll = _defScrollPanes.get(doc);
06069:                if (scroll != null) {
06070:                    DefinitionsPane pane = (DefinitionsPane) scroll
06071:                            .getViewport().getView();
06072:                    pane.removeCaretListener(pane.getErrorCaretListener());
06073:                }
06074:            }
06075:
06076:            /** Initializes all action objects.  Adds icons and descriptions to several of the actions. Note: this 
06077:             *  initialization will later be done in the constructor of each action, which will subclass AbstractAction.
06078:             */
06079:            private void _setUpActions() {
06080:                _setUpAction(_newAction, "New", "Create a new document");
06081:                _setUpAction(_newJUnitTestAction, "New",
06082:                        "Create a new JUnit test case class");
06083:                _setUpAction(_newProjectAction, "New", "Make a new project");
06084:                _setUpAction(_openAction, "Open", "Open an existing file");
06085:                _setUpAction(_openFolderAction, "Open Folder", "OpenAll",
06086:                        "Open all files within a directory");
06087:                _setUpAction(_openFileOrProjectAction, "Open",
06088:                        "Open an existing file or project");
06089:                _setUpAction(_openProjectAction, "Open",
06090:                        "Open an existing project");
06091:                _setUpAction(_saveAction, "Save", "Save the current document");
06092:                _setUpAction(_saveAsAction, "Save As", "SaveAs",
06093:                        "Save the current document with a new name");
06094:                _setUpAction(_renameAction, "Rename", "Rename",
06095:                        "Rename the current document");
06096:                _setUpAction(_saveProjectAction, "Save", "Save",
06097:                        "Save the current project");
06098:                _saveProjectAction.setEnabled(false);
06099:                _setUpAction(_saveProjectAsAction, "Save As", "SaveAs",
06100:                        "Save current project to new project file");
06101:                _saveProjectAsAction.setEnabled(false);
06102:                _setUpAction(_revertAction, "Revert",
06103:                        "Revert the current document to the saved version");
06104:                // No longer used
06105:                //    _setUpAction(_revertAllAction, "Revert All", "RevertAll",
06106:                //                 "Revert all open documents to the saved versions");
06107:
06108:                _setUpAction(_closeAction, "Close",
06109:                        "Close the current document");
06110:                _setUpAction(_closeAllAction, "Close All", "CloseAll",
06111:                        "Close all documents");
06112:                _setUpAction(_closeProjectAction, "Close", "CloseAll",
06113:                        "Close the current project");
06114:                _closeProjectAction.setEnabled(false);
06115:
06116:                _setUpAction(_projectPropertiesAction, "Project Properties",
06117:                        "Preferences", "Edit Project Properties");
06118:                _projectPropertiesAction.setEnabled(false);
06119:
06120:                //    _setUpAction(_junitProjectAction, "Test", "Test", "Test the current project");
06121:                //    _junitProjectAction.setEnabled(false);    
06122:                _setUpAction(_junitProjectAction, "Test Project",
06123:                        "Test the documents in the project source tree");
06124:                _junitProjectAction.setEnabled(false);
06125:
06126:                //    _setUpAction(_compileOpenProjectAction, "Compile", "Compile", "Compile the open project documents");
06127:                _setUpAction(_compileProjectAction, "Compile Project",
06128:                        "Compile the documents in the project source tree");
06129:                //    _compileOpenProjectAction.setEnabled(false);
06130:                _compileProjectAction.setEnabled(false);
06131:
06132:                _setUpAction(_runProjectAction, "Run Project",
06133:                        "Run the project's main method");
06134:                _runProjectAction.setEnabled(false);
06135:
06136:                _setUpAction(_jarProjectAction, "Jar",
06137:                        "Create a jar archive from this project");
06138:                _jarProjectAction.setEnabled(false);
06139:
06140:                _setUpAction(_saveAllAction, "Save All", "SaveAll",
06141:                        "Save all open documents");
06142:
06143:                _setUpAction(_cleanAction, "Clean", "Clean Build directory");
06144:                _cleanAction.setEnabled(false);
06145:                _setUpAction(_compileAction, "Compile Current Document",
06146:                        "Compile the current document");
06147:                _setUpAction(_compileAllAction, "Compile",
06148:                        "Compile all open documents");
06149:                _setUpAction(_printDefDocAction, "Print",
06150:                        "Print the current main document");
06151:                _setUpAction(_printConsoleAction, "Print",
06152:                        "Print the Console pane");
06153:                _setUpAction(_printInteractionsAction, "Print",
06154:                        "Print the Interactions pane");
06155:                _setUpAction(_pageSetupAction, "Page Setup", "PageSetup",
06156:                        "Change the printer settings");
06157:                _setUpAction(_printDefDocPreviewAction, "Print Preview",
06158:                        "PrintPreview",
06159:                        "Preview how the document will be printed");
06160:                _setUpAction(_printConsolePreviewAction, "Print Preview",
06161:                        "PrintPreview",
06162:                        "Preview how the console document will be printed");
06163:                _setUpAction(_printInteractionsPreviewAction, "Print Preview",
06164:                        "PrintPreview",
06165:                        "Preview how the interactions document will be printed");
06166:
06167:                _setUpAction(_quitAction, "Quit", "Quit", "Quit DrJava");
06168:
06169:                _setUpAction(_undoAction, "Undo", "Undo previous command");
06170:                _setUpAction(_redoAction, "Redo", "Redo last undo");
06171:                _undoAction.putValue(Action.NAME, "Undo Previous Command");
06172:                _redoAction.putValue(Action.NAME, "Redo Last Undo");
06173:
06174:                _setUpAction(cutAction, "Cut",
06175:                        "Cut selected text to the clipboard");
06176:                _setUpAction(copyAction, "Copy",
06177:                        "Copy selected text to the clipboard");
06178:                _setUpAction(pasteAction, "Paste",
06179:                        "Paste text from the clipboard");
06180:                _setUpAction(_pasteHistoryAction, "Paste from History",
06181:                        "Paste text from the clipboard history");
06182:                _setUpAction(_selectAllAction, "Select All", "Select all text");
06183:
06184:                cutAction.putValue(Action.NAME, "Cut");
06185:                copyAction.putValue(Action.NAME, "Copy");
06186:                pasteAction.putValue(Action.NAME, "Paste");
06187:                _pasteHistoryAction.putValue(Action.NAME, "Paste from History");
06188:
06189:                _setUpAction(_indentLinesAction, "Indent Lines",
06190:                        "Indent all selected lines");
06191:                _setUpAction(_commentLinesAction, "Comment Lines",
06192:                        "Comment out all selected lines");
06193:                _setUpAction(_uncommentLinesAction, "Uncomment Lines",
06194:                        "Uncomment all selected lines");
06195:
06196:                _setUpAction(completeWordUnderCursorAction,
06197:                        "Auto-Complete Word Under Cursor",
06198:                        "Auto-complete the word the cursor is currently located on");
06199:                _setUpAction(_bookmarksPanelAction, "Bookmarks",
06200:                        "Display the bookmarks panel");
06201:                _setUpAction(_toggleBookmarkAction, "Toggle Bookmark",
06202:                        "Toggle the bookmark at the current cursor location");
06203:
06204:                _setUpAction(_findReplaceAction, "Find",
06205:                        "Find or replace text in the document");
06206:                _setUpAction(_findNextAction, "Find Next",
06207:                        "Repeats the last find");
06208:                _setUpAction(_findPrevAction, "Find Previous",
06209:                        "Repeats the last find in the opposite direction");
06210:                _setUpAction(_gotoLineAction, "Go to line",
06211:                        "Go to a line number in the document");
06212:                _setUpAction(_gotoFileAction, "Go to File",
06213:                        "Go to a file specified by its name");
06214:                _setUpAction(gotoFileUnderCursorAction,
06215:                        "Go to File Under Cursor",
06216:                        "Go to the file specified by the word the cursor is located on");
06217:
06218:                _setUpAction(_switchToPrevAction, "Previous Document", "Up",
06219:                        "Switch to the previous document");
06220:                _setUpAction(_switchToNextAction, "Next Document", "Down",
06221:                        "Switch to the next document");
06222:
06223:                _setUpAction(_browseBackAction, "Back", "Back",
06224:                        "Move back in the browser history");
06225:                _setUpAction(_browseForwardAction, "Forward", "Forward",
06226:                        "Move forward in the browser history");
06227:
06228:                _setUpAction(_switchToPreviousPaneAction, "Previous Pane",
06229:                        "Switch focus to the previous pane");
06230:                _setUpAction(_switchToNextPaneAction, "Next Pane",
06231:                        "Switch focus to the next pane");
06232:                _setUpAction(_gotoOpeningBraceAction, "Go to Opening Brace",
06233:                        "Go th the opening brace of the block enclosing the cursor");
06234:                _setUpAction(_gotoClosingBraceAction, "Go to Closing Brace",
06235:                        "Go th the closing brace of the block enclosing the cursor");
06236:
06237:                _setUpAction(_editPreferencesAction, "Preferences",
06238:                        "Edit configurable settings in DrJava");
06239:
06240:                _setUpAction(_junitAction, "Test Current",
06241:                        "Run JUnit over the current document");
06242:                _setUpAction(_junitAllAction, "Test",
06243:                        "Run JUnit over all open JUnit tests");
06244:                _setUpAction(_javadocAllAction, "Javadoc",
06245:                        "Create and save Javadoc for the packages of all open documents");
06246:                _setUpAction(_javadocCurrentAction, "Preview Javadoc Current",
06247:                        "Preview the Javadoc for the current document");
06248:                _setUpAction(_runAction, "Run",
06249:                        "Run the main method of the current document");
06250:
06251:                _setUpAction(_openJavadocAction, "Open Java API Javadoc...",
06252:                        "Open the Java API Javadoc Web page for a class");
06253:                _setUpAction(
06254:                        _openJavadocUnderCursorAction,
06255:                        "Open Java API Javadoc for Word Under Cursor...",
06256:                        "Open the Java API "
06257:                                + "Javadoc Web page for the word under the cursor");
06258:
06259:                _setUpAction(_executeHistoryAction, "Execute History",
06260:                        "Load and execute a history of interactions from a file");
06261:                _setUpAction(_loadHistoryScriptAction,
06262:                        "Load History as Script",
06263:                        "Load a history from a file as a series of interactions");
06264:                _setUpAction(_saveHistoryAction, "Save History",
06265:                        "Save the history of interactions to a file");
06266:                _setUpAction(_clearHistoryAction, "Clear History",
06267:                        "Clear the current history of interactions");
06268:
06269:                //_setUpAction(_abortInteractionAction, "Break", "Abort the current interaction");
06270:                _setUpAction(_resetInteractionsAction, "Reset",
06271:                        "Reset the Interactions Pane");
06272:                _resetInteractionsAction.setEnabled(true);
06273:
06274:                _setUpAction(_viewInteractionsClassPathAction,
06275:                        "View Interactions Classpath",
06276:                        "Display the classpath in use by the Interactions Pane");
06277:                _setUpAction(_copyInteractionToDefinitionsAction,
06278:                        "Lift Current Interaction",
06279:                        "Copy the current interaction into the Definitions Pane");
06280:
06281:                _setUpAction(_clearConsoleAction, "Clear Console",
06282:                        "Clear all text in the Console Pane");
06283:                _setUpAction(
06284:                        _showDebugConsoleAction,
06285:                        "Show DrJava Debug Console",
06286:                        "<html>Show a console for debugging DrJava<br>"
06287:                                + "(with \"mainFrame\", \"model\", and \"config\" variables defined)</html>");
06288:
06289:                if (_model.getDebugger().isAvailable()) {
06290:                    _setUpAction(_toggleDebuggerAction, "Debug Mode",
06291:                            "Enable or disable DrJava's debugger");
06292:                    _setUpAction(_toggleBreakpointAction, "Toggle Breakpoint",
06293:                            "Set or clear a breakpoint on the current line");
06294:                    _setUpAction(_clearAllBreakpointsAction,
06295:                            "Clear Breakpoints",
06296:                            "Clear all breakpoints in all classes");
06297:                    _setUpAction(_resumeDebugAction, "Resume",
06298:                            "Resume the current suspended thread");
06299:                    _setUpAction(_stepIntoDebugAction, "Step Into",
06300:                            "Step into the current line or method call");
06301:                    _setUpAction(_stepOverDebugAction, "Step Over",
06302:                            "Step over the current line or method call");
06303:                    _setUpAction(_stepOutDebugAction, "Step Out",
06304:                            "Step out of the current method");
06305:                    _setUpAction(_breakpointsPanelAction, "Breakpoints",
06306:                            "Display the breakpoints panel");
06307:                }
06308:
06309:                _setUpAction(_helpAction, "Help",
06310:                        "Show documentation on how to use DrJava");
06311:                _setUpAction(_quickStartAction, "Help",
06312:                        "View Quick Start Guide for DrJava");
06313:                _setUpAction(_aboutAction, "About", "About DrJava");
06314:                _setUpAction(_errorsAction, "DrJava Errors", "drjavaerror",
06315:                        "Show a window with internal DrJava errors");
06316:                _setUpAction(_forceQuitAction, "Force Quit",
06317:                        "Force DrJava to quit without cleaning up");
06318:            }
06319:
06320:            private void _setUpAction(Action a, String name, String icon,
06321:                    String shortDesc) {
06322:                a.putValue(Action.SMALL_ICON, _getIcon(icon + "16.gif"));
06323:                a.putValue(Action.DEFAULT, name);
06324:                a.putValue(Action.SHORT_DESCRIPTION, shortDesc);
06325:            }
06326:
06327:            private void _setUpAction(Action a, String icon, String shortDesc) {
06328:                _setUpAction(a, icon, icon, shortDesc);
06329:            }
06330:
06331:            /** Returns the icon with the given name. All icons are assumed to reside in the /edu/rice/cs/drjava/ui/icons
06332:             *  directory.
06333:             *  @param name Name of icon image file
06334:             *  @return ImageIcon object constructed from the file
06335:             */
06336:            private ImageIcon _getIcon(String name) {
06337:                return getIcon(name);
06338:            }
06339:
06340:            public static ImageIcon getIcon(String name) {
06341:                URL url = MainFrame.class.getResource(ICON_PATH + name);
06342:                if (url != null)
06343:                    return new ImageIcon(url);
06344:
06345:                return null;
06346:            }
06347:
06348:            /** This allows us to intercept key events when compiling testing and turn them off when the glass pane is up. */
06349:            private class MenuBar extends JMenuBar {
06350:                public boolean processKeyBinding(KeyStroke ks, KeyEvent e,
06351:                        int condition, boolean pressed) {
06352:                    if (MainFrame.this .getAllowKeyEvents())
06353:                        return super .processKeyBinding(ks, e, condition,
06354:                                pressed);
06355:                    return false;
06356:                }
06357:            }
06358:
06359:            /** Sets up the components of the menu bar and links them to the private fields within MainFrame.  This method 
06360:             *  serves to make the code more legible on the higher calling level, i.e., the constructor.
06361:             */
06362:            private void _setUpMenuBar() {
06363:
06364:                _menuBar.add(_fileMenu);
06365:                _menuBar.add(_editMenu);
06366:                _menuBar.add(_toolsMenu);
06367:                _menuBar.add(_projectMenu);
06368:                if (_showDebugger)
06369:                    _menuBar.add(_debugMenu);
06370:                _menuBar.add(_languageLevelMenu);
06371:                _menuBar.add(_helpMenu);
06372:                setJMenuBar(_menuBar);
06373:            }
06374:
06375:            /** Adds an Action as a menu item to the given menu, using the specified configurable keystroke.
06376:             *  @param menu Menu to add item to
06377:             *  @param a Action for the menu item
06378:             *  @param opt Configurable keystroke for the menu item
06379:             */
06380:            private void _addMenuItem(JMenu menu, Action a,
06381:                    Option<KeyStroke> opt) {
06382:                JMenuItem item;
06383:                item = menu.add(a);
06384:                _setMenuShortcut(item, a, opt);
06385:            }
06386:
06387:            /** Sets the given menu item to have the specified configurable keystroke.
06388:             *  @param item Menu item containing the action
06389:             *  @param a Action for the menu item
06390:             *  @param opt Configurable keystroke for the menu item
06391:             */
06392:            private void _setMenuShortcut(JMenuItem item, Action a,
06393:                    Option<KeyStroke> opt) {
06394:                KeyStroke ks = DrJava.getConfig().getSetting(opt);
06395:                // Checks that "a" is the action associated with the keystroke.
06396:                // Need to check in case two actions were assigned to the same
06397:                // key in the config file.
06398:                // Also check that the keystroke isn't the NULL_KEYSTROKE, which
06399:                //  can strangely be triggered by certain keys in Windows.
06400:                KeyBindingManager.Singleton.put(opt, a, item, item.getText());
06401:                if ((ks != KeyStrokeOption.NULL_KEYSTROKE)
06402:                        && (KeyBindingManager.Singleton.get(ks) == a)) {
06403:                    item.setAccelerator(ks);
06404:                    //KeyBindingManager.Singleton.addListener(opt, item);
06405:                }
06406:            }
06407:
06408:            /** Creates and returns a file menu.  Side effects: sets values for _saveMenuItem. */
06409:            private JMenu _setUpFileMenu(int mask) {
06410:                JMenu fileMenu = new JMenu("File");
06411:                fileMenu.setMnemonic(KeyEvent.VK_F);
06412:                // New, open
06413:                _addMenuItem(fileMenu, _newAction, KEY_NEW_FILE);
06414:                _addMenuItem(fileMenu, _newJUnitTestAction, KEY_NEW_TEST);
06415:                _addMenuItem(fileMenu, _openAction, KEY_OPEN_FILE);
06416:                _addMenuItem(fileMenu, _openFolderAction, KEY_OPEN_FOLDER);
06417:                //_addMenuItem(fileMenu, _openProjectAction, KEY_OPEN_PROJECT);
06418:
06419:                fileMenu.addSeparator();
06420:
06421:                _addMenuItem(fileMenu, _saveAction, KEY_SAVE_FILE);
06422:                _saveAction.setEnabled(true);
06423:                _addMenuItem(fileMenu, _saveAsAction, KEY_SAVE_FILE_AS);
06424:                _addMenuItem(fileMenu, _saveAllAction, KEY_SAVE_ALL_FILES);
06425:                _addMenuItem(fileMenu, _renameAction, KEY_RENAME_FILE);
06426:                _renameAction.setEnabled(false);
06427:                //    fileMenu.add(_saveProjectAsAction);
06428:
06429:                _addMenuItem(fileMenu, _revertAction, KEY_REVERT_FILE);
06430:                _revertAction.setEnabled(false);
06431:                //tmpItem = fileMenu.add(_revertAllAction);
06432:
06433:                // Close, Close all
06434:                fileMenu.addSeparator();
06435:                _addMenuItem(fileMenu, _closeAction, KEY_CLOSE_FILE);
06436:                _addMenuItem(fileMenu, _closeAllAction, KEY_CLOSE_ALL_FILES);
06437:                //_addMenuItem(fileMenu, _closeProjectAction, KEY_CLOSE_PROJECT);
06438:
06439:                // Page setup, print preview, print
06440:                fileMenu.addSeparator();
06441:                _addMenuItem(fileMenu, _pageSetupAction, KEY_PAGE_SETUP);
06442:                _addMenuItem(fileMenu, _printDefDocPreviewAction,
06443:                        KEY_PRINT_PREVIEW);
06444:                _addMenuItem(fileMenu, _printDefDocAction, KEY_PRINT);
06445:
06446:                // Quit
06447:                fileMenu.addSeparator();
06448:                _addMenuItem(fileMenu, _quitAction, KEY_QUIT);
06449:
06450:                return fileMenu;
06451:            }
06452:
06453:            /** Creates and returns a edit menu. */
06454:            private JMenu _setUpEditMenu(int mask) {
06455:                JMenu editMenu = new JMenu("Edit");
06456:                editMenu.setMnemonic(KeyEvent.VK_E);
06457:                // Undo, redo
06458:                _addMenuItem(editMenu, _undoAction, KEY_UNDO);
06459:                _addMenuItem(editMenu, _redoAction, KEY_REDO);
06460:
06461:                // Cut, copy, paste, select all
06462:                editMenu.addSeparator();
06463:                _addMenuItem(editMenu, cutAction, KEY_CUT);
06464:                _addMenuItem(editMenu, copyAction, KEY_COPY);
06465:                _addMenuItem(editMenu, pasteAction, KEY_PASTE);
06466:                _addMenuItem(editMenu, _pasteHistoryAction,
06467:                        KEY_PASTE_FROM_HISTORY);
06468:                _addMenuItem(editMenu, _selectAllAction, KEY_SELECT_ALL);
06469:
06470:                // Indent lines, comment lines
06471:                editMenu.addSeparator();
06472:                //_addMenuItem(editMenu, _indentLinesAction, KEY_INDENT);
06473:                JMenuItem editItem = editMenu.add(_indentLinesAction);
06474:                editItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_TAB,
06475:                        0));
06476:                _addMenuItem(editMenu, _commentLinesAction, KEY_COMMENT_LINES);
06477:                _addMenuItem(editMenu, _uncommentLinesAction,
06478:                        KEY_UNCOMMENT_LINES);
06479:                _addMenuItem(editMenu, completeWordUnderCursorAction,
06480:                        KEY_COMPLETE_FILE);
06481:
06482:                // Find/replace, goto
06483:                editMenu.addSeparator();
06484:                _addMenuItem(editMenu, _findReplaceAction, KEY_FIND_REPLACE);
06485:                _addMenuItem(editMenu, _findNextAction, KEY_FIND_NEXT);
06486:                _addMenuItem(editMenu, _findPrevAction, KEY_FIND_PREV);
06487:                _addMenuItem(editMenu, _gotoLineAction, KEY_GOTO_LINE);
06488:                _addMenuItem(editMenu, _gotoFileAction, KEY_GOTO_FILE);
06489:                _addMenuItem(editMenu, gotoFileUnderCursorAction,
06490:                        KEY_GOTO_FILE_UNDER_CURSOR);
06491:
06492:                // Next, prev doc
06493:                editMenu.addSeparator();
06494:                _addMenuItem(editMenu, _switchToPrevAction,
06495:                        KEY_PREVIOUS_DOCUMENT);
06496:                _addMenuItem(editMenu, _switchToNextAction, KEY_NEXT_DOCUMENT);
06497:                _addMenuItem(editMenu, _browseBackAction, KEY_BROWSE_BACK);
06498:                _addMenuItem(editMenu, _browseForwardAction, KEY_BROWSE_FORWARD);
06499:                _addMenuItem(editMenu, _switchToPreviousPaneAction,
06500:                        KEY_PREVIOUS_PANE);
06501:                _addMenuItem(editMenu, _switchToNextPaneAction, KEY_NEXT_PANE);
06502:                _addMenuItem(editMenu, _gotoOpeningBraceAction,
06503:                        KEY_OPENING_BRACE);
06504:                _addMenuItem(editMenu, _gotoClosingBraceAction,
06505:                        KEY_CLOSING_BRACE);
06506:
06507:                // access to configurations GUI
06508:                editMenu.addSeparator();
06509:                _addMenuItem(editMenu, _editPreferencesAction, KEY_PREFERENCES);
06510:
06511:                // Add the menus to the menu bar
06512:                return editMenu;
06513:            }
06514:
06515:            /** Creates and returns a tools menu. */
06516:            private JMenu _setUpToolsMenu(int mask) {
06517:                JMenu toolsMenu = new JMenu("Tools");
06518:                toolsMenu.setMnemonic(KeyEvent.VK_T);
06519:
06520:                // Compile, Test, Javadoc
06521:                _addMenuItem(toolsMenu, _compileAllAction, KEY_COMPILE_ALL);
06522:                _addMenuItem(toolsMenu, _compileAction, KEY_COMPILE);
06523:                _addMenuItem(toolsMenu, _junitAllAction, KEY_TEST_ALL);
06524:                _addMenuItem(toolsMenu, _junitAction, KEY_TEST);
06525:                _addMenuItem(toolsMenu, _javadocAllAction, KEY_JAVADOC_ALL);
06526:                _addMenuItem(toolsMenu, _javadocCurrentAction,
06527:                        KEY_JAVADOC_CURRENT);
06528:                toolsMenu.addSeparator();
06529:
06530:                // Open Javadoc
06531:                _addMenuItem(toolsMenu, _openJavadocAction, KEY_OPEN_JAVADOC);
06532:                _addMenuItem(toolsMenu, _openJavadocUnderCursorAction,
06533:                        KEY_OPEN_JAVADOC_UNDER_CURSOR);
06534:                toolsMenu.addSeparator();
06535:
06536:                // Run
06537:                _addMenuItem(toolsMenu, _runAction, KEY_RUN);
06538:                toolsMenu.addSeparator();
06539:
06540:                _addMenuItem(toolsMenu, _executeHistoryAction,
06541:                        KEY_EXECUTE_HISTORY);
06542:                _addMenuItem(toolsMenu, _loadHistoryScriptAction,
06543:                        KEY_LOAD_HISTORY_SCRIPT);
06544:                _addMenuItem(toolsMenu, _saveHistoryAction, KEY_SAVE_HISTORY);
06545:                _addMenuItem(toolsMenu, _clearHistoryAction, KEY_CLEAR_HISTORY);
06546:                toolsMenu.addSeparator();
06547:
06548:                // Abort/reset interactions, clear console
06549:                /*
06550:                 _abortInteractionAction.setEnabled(false);
06551:                 _addMenuItem(toolsMenu, _abortInteractionAction, KEY_ABORT_INTERACTION);
06552:                 */
06553:                _addMenuItem(toolsMenu, _resetInteractionsAction,
06554:                        KEY_RESET_INTERACTIONS);
06555:                _addMenuItem(toolsMenu, _viewInteractionsClassPathAction,
06556:                        KEY_VIEW_INTERACTIONS_CLASSPATH);
06557:                _addMenuItem(toolsMenu, _copyInteractionToDefinitionsAction,
06558:                        KEY_LIFT_CURRENT_INTERACTION);
06559:                _addMenuItem(toolsMenu, _printInteractionsAction,
06560:                        KEY_PRINT_INTERACTIONS);
06561:                toolsMenu.addSeparator();
06562:
06563:                _addMenuItem(toolsMenu, _clearConsoleAction, KEY_CLEAR_CONSOLE);
06564:                _addMenuItem(toolsMenu, _printConsoleAction, KEY_PRINT_CONSOLE);
06565:                if (DrJava.getConfig().getSetting(SHOW_DEBUG_CONSOLE)
06566:                        .booleanValue()) {
06567:                    toolsMenu.add(_showDebugConsoleAction);
06568:                }
06569:
06570:                toolsMenu.addSeparator();
06571:                _addMenuItem(toolsMenu, _bookmarksPanelAction,
06572:                        KEY_BOOKMARKS_PANEL);
06573:                _addMenuItem(toolsMenu, _toggleBookmarkAction,
06574:                        KEY_BOOKMARKS_TOGGLE);
06575:
06576:                // Add the menus to the menu bar
06577:                return toolsMenu;
06578:            }
06579:
06580:            /** Creates and returns a project menu. */
06581:            private JMenu _setUpProjectMenu(int mask) {
06582:                JMenu projectMenu = new JMenu("Project");
06583:                projectMenu.setMnemonic(KeyEvent.VK_P);
06584:                // New, open
06585:                projectMenu.add(_newProjectAction);
06586:                _addMenuItem(projectMenu, _openProjectAction, KEY_OPEN_PROJECT);
06587:
06588:                //Save
06589:                projectMenu.add(_saveProjectAction);
06590:                //SaveAs
06591:                projectMenu.add(_saveProjectAsAction);
06592:
06593:                // Close
06594:                _addMenuItem(projectMenu, _closeProjectAction,
06595:                        KEY_CLOSE_PROJECT);
06596:
06597:                projectMenu.addSeparator();
06598:                // run project
06599:                projectMenu.add(_cleanAction);
06600:                //    projectMenu.add(_compileOpenProjectAction);
06601:                projectMenu.add(_compileProjectAction);
06602:                projectMenu.add(_jarProjectAction);
06603:                projectMenu.add(_runProjectAction);
06604:                projectMenu.add(_junitProjectAction);
06605:                //    projectMenu.add(_junitProjectAction);
06606:
06607:                projectMenu.addSeparator();
06608:                // eventually add project options
06609:                projectMenu.add(_projectPropertiesAction);
06610:
06611:                return projectMenu;
06612:            }
06613:
06614:            /** Creates and returns a debug menu. */
06615:            private JMenu _setUpDebugMenu(int mask) {
06616:                JMenu debugMenu = new JMenu("Debugger");
06617:                debugMenu.setMnemonic(KeyEvent.VK_D);
06618:                // Enable debugging item
06619:                _debuggerEnabledMenuItem = _newCheckBoxMenuItem(_toggleDebuggerAction);
06620:                _debuggerEnabledMenuItem.setSelected(false);
06621:                _setMenuShortcut(_debuggerEnabledMenuItem,
06622:                        _toggleDebuggerAction, KEY_DEBUG_MODE_TOGGLE);
06623:                debugMenu.add(_debuggerEnabledMenuItem);
06624:                debugMenu.addSeparator();
06625:
06626:                _addMenuItem(debugMenu, _toggleBreakpointAction,
06627:                        KEY_DEBUG_BREAKPOINT_TOGGLE);
06628:                //_printBreakpointsMenuItem = debugMenu.add(_printBreakpointsAction);
06629:                //_clearAllBreakpointsMenuItem =
06630:                _addMenuItem(debugMenu, _clearAllBreakpointsAction,
06631:                        KEY_DEBUG_CLEAR_ALL_BREAKPOINTS);
06632:                _addMenuItem(debugMenu, _breakpointsPanelAction,
06633:                        KEY_DEBUG_BREAKPOINT_PANEL);
06634:                debugMenu.addSeparator();
06635:
06636:                //_addMenuItem(debugMenu, _suspendDebugAction, KEY_DEBUG_SUSPEND);
06637:                _addMenuItem(debugMenu, _resumeDebugAction, KEY_DEBUG_RESUME);
06638:                _addMenuItem(debugMenu, _stepIntoDebugAction,
06639:                        KEY_DEBUG_STEP_INTO);
06640:                _addMenuItem(debugMenu, _stepOverDebugAction,
06641:                        KEY_DEBUG_STEP_OVER);
06642:                _addMenuItem(debugMenu, _stepOutDebugAction, KEY_DEBUG_STEP_OUT);
06643:
06644:                // Start off disabled
06645:                _setDebugMenuItemsEnabled(false);
06646:
06647:                // Add the menu to the menu bar
06648:                return debugMenu;
06649:            }
06650:
06651:            /**
06652:             * Called every time the debug mode checkbox is toggled. The resume and step
06653:             * functions should always be disabled.
06654:             */
06655:            private void _setDebugMenuItemsEnabled(boolean isEnabled) {
06656:
06657:                _debuggerEnabledMenuItem.setSelected(isEnabled);
06658:                //_suspendDebugAction.setEnabled(false);
06659:                _resumeDebugAction.setEnabled(false);
06660:                _stepIntoDebugAction.setEnabled(false);
06661:                _stepOverDebugAction.setEnabled(false);
06662:                _stepOutDebugAction.setEnabled(false);
06663:
06664:                if (_showDebugger)
06665:                    _debugPanel.disableButtons();
06666:            }
06667:
06668:            /** Enables and disables the appropriate menu items in the debug menu depending upon the state of the current thread.
06669:             *  @param isSuspended is true when the current thread has just been suspended
06670:             *         false if the current thread has just been resumed
06671:             */
06672:            private void _setThreadDependentDebugMenuItems(boolean isSuspended) {
06673:                //_suspendDebugAction.setEnabled(!isSuspended);
06674:                _resumeDebugAction.setEnabled(isSuspended);
06675:                _stepIntoDebugAction.setEnabled(isSuspended);
06676:                _stepOverDebugAction.setEnabled(isSuspended);
06677:                _stepOutDebugAction.setEnabled(isSuspended);
06678:                _debugPanel.setThreadDependentButtons(isSuspended);
06679:            }
06680:
06681:            /** Creates and returns the language levels menu. */
06682:            private JMenu _setUpLanguageLevelMenu(int mask) {
06683:                JMenu languageLevelMenu = new JMenu("Language Level");
06684:                languageLevelMenu.setMnemonic(KeyEvent.VK_L);
06685:                ButtonGroup group = new ButtonGroup();
06686:
06687:                final Configuration config = DrJava.getConfig();
06688:                int currentLanguageLevel = config.getSetting(LANGUAGE_LEVEL);
06689:                JRadioButtonMenuItem rbMenuItem;
06690:                rbMenuItem = new JRadioButtonMenuItem("Full Java");
06691:                rbMenuItem.setToolTipText("Use full Java syntax");
06692:                if (currentLanguageLevel == DrJavaRoot.FULL_JAVA) {
06693:                    rbMenuItem.setSelected(true);
06694:                }
06695:                rbMenuItem.addActionListener(new ActionListener() {
06696:                    public void actionPerformed(ActionEvent e) {
06697:                        config.setSetting(LANGUAGE_LEVEL, DrJavaRoot.FULL_JAVA);
06698:                    }
06699:                });
06700:                group.add(rbMenuItem);
06701:                languageLevelMenu.add(rbMenuItem);
06702:                languageLevelMenu.addSeparator();
06703:
06704:                rbMenuItem = new JRadioButtonMenuItem("Elementary");
06705:                rbMenuItem
06706:                        .setToolTipText("Use Elementary language-level features");
06707:                if (currentLanguageLevel == DrJavaRoot.ELEMENTARY_LEVEL) {
06708:                    rbMenuItem.setSelected(true);
06709:                }
06710:                rbMenuItem.addActionListener(new ActionListener() {
06711:                    public void actionPerformed(ActionEvent e) {
06712:                        config.setSetting(LANGUAGE_LEVEL,
06713:                                DrJavaRoot.ELEMENTARY_LEVEL);
06714:                    }
06715:                });
06716:                group.add(rbMenuItem);
06717:                languageLevelMenu.add(rbMenuItem);
06718:
06719:                rbMenuItem = new JRadioButtonMenuItem("Intermediate");
06720:                rbMenuItem
06721:                        .setToolTipText("Use Intermediate language-level features");
06722:                if (currentLanguageLevel == DrJavaRoot.INTERMEDIATE_LEVEL) {
06723:                    rbMenuItem.setSelected(true);
06724:                }
06725:                rbMenuItem.addActionListener(new ActionListener() {
06726:                    public void actionPerformed(ActionEvent e) {
06727:                        config.setSetting(LANGUAGE_LEVEL,
06728:                                DrJavaRoot.INTERMEDIATE_LEVEL);
06729:                    }
06730:                });
06731:                group.add(rbMenuItem);
06732:                languageLevelMenu.add(rbMenuItem);
06733:
06734:                rbMenuItem = new JRadioButtonMenuItem("Advanced");
06735:                rbMenuItem
06736:                        .setToolTipText("Use Advanced language-level features");
06737:                if (currentLanguageLevel == DrJavaRoot.ADVANCED_LEVEL) {
06738:                    rbMenuItem.setSelected(true);
06739:                }
06740:                rbMenuItem.addActionListener(new ActionListener() {
06741:                    public void actionPerformed(ActionEvent e) {
06742:                        config.setSetting(LANGUAGE_LEVEL,
06743:                                DrJavaRoot.ADVANCED_LEVEL);
06744:                    }
06745:                });
06746:                group.add(rbMenuItem);
06747:                languageLevelMenu.add(rbMenuItem);
06748:                return languageLevelMenu;
06749:            }
06750:
06751:            /** Creates and returns a help menu. */
06752:            private JMenu _setUpHelpMenu(int mask) {
06753:                JMenu helpMenu = new JMenu("Help");
06754:                helpMenu.setMnemonic(KeyEvent.VK_H);
06755:                _addMenuItem(helpMenu, _helpAction, KEY_HELP);
06756:                _addMenuItem(helpMenu, _quickStartAction, KEY_QUICKSTART);
06757:                _addMenuItem(helpMenu, _aboutAction, KEY_ABOUT);
06758:                _addMenuItem(helpMenu, _errorsAction, KEY_DRJAVA_ERRORS);
06759:                _addMenuItem(helpMenu, _forceQuitAction, KEY_FORCE_QUIT);
06760:                return helpMenu;
06761:            }
06762:
06763:            /** Creates a toolbar button for undo and redo, which behave differently. */
06764:            JButton _createManualToolbarButton(Action a) {
06765:                final JButton ret;
06766:
06767:                Font buttonFont = DrJava.getConfig().getSetting(FONT_TOOLBAR);
06768:
06769:                // Check whether icons should be shown
06770:                boolean useIcon = DrJava.getConfig().getSetting(
06771:                        TOOLBAR_ICONS_ENABLED).booleanValue();
06772:                boolean useText = DrJava.getConfig().getSetting(
06773:                        TOOLBAR_TEXT_ENABLED).booleanValue();
06774:                final Icon icon = (useIcon) ? (Icon) a
06775:                        .getValue(Action.SMALL_ICON) : null;
06776:                if (icon == null) {
06777:                    ret = new UnfocusableButton((String) a
06778:                            .getValue(Action.DEFAULT));
06779:                } else {
06780:                    ret = new UnfocusableButton(icon);
06781:                    if (useText)
06782:                        ret.setText((String) a.getValue(Action.DEFAULT));
06783:                }
06784:                ret.setEnabled(false);
06785:                ret.addActionListener(a);
06786:                ret.setToolTipText((String) a
06787:                        .getValue(Action.SHORT_DESCRIPTION));
06788:                ret.setFont(buttonFont);
06789:                Boolean test = a instanceof  DelegatingAction;
06790:                a.addPropertyChangeListener(new PropertyChangeListener() {
06791:                    public void propertyChange(PropertyChangeEvent evt) {
06792:                        if ("enabled".equals(evt.getPropertyName())) {
06793:                            Boolean val = (Boolean) evt.getNewValue();
06794:                            ret.setEnabled(val.booleanValue());
06795:                        }
06796:                    }
06797:                });
06798:
06799:                return ret;
06800:            }
06801:
06802:            /** Sets up all buttons for the toolbar except for undo and redo, which use _createManualToolbarButton. */
06803:            public JButton _createToolbarButton(Action a) {
06804:                boolean useText = DrJava.getConfig().getSetting(
06805:                        TOOLBAR_TEXT_ENABLED).booleanValue();
06806:                boolean useIcons = DrJava.getConfig().getSetting(
06807:                        TOOLBAR_ICONS_ENABLED).booleanValue();
06808:                Font buttonFont = DrJava.getConfig().getSetting(FONT_TOOLBAR);
06809:
06810:                final JButton result = new UnfocusableButton(a);
06811:                result.setText((String) a.getValue(Action.DEFAULT));
06812:                result.setFont(buttonFont);
06813:                if (!useIcons)
06814:                    result.setIcon(null);
06815:                if (!useText && (result.getIcon() != null))
06816:                    result.setText("");
06817:                return result;
06818:            }
06819:
06820:            /** Removes the button b from the toolbar and creates new button in its place. */
06821:            public JButton _updateToolbarButton(JButton b, Action a) {
06822:                final JButton result = _createToolbarButton(a);
06823:
06824:                int index = _toolBar.getComponentIndex(b);
06825:                _toolBar.remove(b);
06826:                _toolBar.add(result, index);
06827:
06828:                _fixToolbarHeights();
06829:
06830:                return result;
06831:            }
06832:
06833:            /** Sets up the toolbar with several useful buttons.  Most buttons are always enabled, but those that are not are
06834:             *  maintained in fields to allow enabling and disabling.
06835:             */
06836:            private void _setUpToolBar() {
06837:
06838:                _toolBar.setFloatable(false);
06839:
06840:                //     _toolBar.addSeparator();
06841:
06842:                // New, open, save, close
06843:                _toolBar.add(_createToolbarButton(_newAction));
06844:                _toolBar.add(_createToolbarButton(_openFileOrProjectAction));
06845:                _toolBar.add(_createToolbarButton(_saveAction));
06846:                _closeButton = _createToolbarButton(_closeAction);
06847:                _toolBar.add(_closeButton);
06848:
06849:                // Cut, copy, paste
06850:                _toolBar.addSeparator();
06851:                _toolBar.add(_createToolbarButton(cutAction));
06852:                _toolBar.add(_createToolbarButton(copyAction));
06853:                _toolBar.add(_createToolbarButton(pasteAction));
06854:
06855:                // Undo, redo
06856:                // Simple workaround, for now, for bug # 520742:
06857:                // Undo/Redo button text in JDK 1.3
06858:                // We just manually create the JButtons, and we *don't* set up
06859:                // PropertyChangeListeners on the action's name.
06860:                //_toolBar.addSeparator();
06861:
06862:                _toolBar.add(_undoButton);
06863:                _toolBar.add(_redoButton);
06864:
06865:                // Find
06866:                _toolBar.addSeparator();
06867:                _toolBar.add(_createToolbarButton(_findReplaceAction));
06868:
06869:                // Compile, reset, abort
06870:                _toolBar.addSeparator();
06871:                _toolBar
06872:                        .add(_compileButton = _createToolbarButton(_compileAllAction));
06873:                _toolBar.add(_createToolbarButton(_resetInteractionsAction));
06874:                //_toolBar.add(_createToolbarButton(_abortInteractionAction));
06875:
06876:                // Run, Junit, and JavaDoc
06877:                _toolBar.addSeparator();
06878:
06879:                _toolBar.add(_runButton = _createToolbarButton(_runAction));
06880:                _toolBar
06881:                        .add(_junitButton = _createToolbarButton(_junitAllAction));
06882:                _toolBar.add(_createToolbarButton(_javadocAllAction));
06883:
06884:                // DrJava Errors
06885:                _toolBar.addSeparator();
06886:                final JButton errorsButton = _createToolbarButton(_errorsAction);
06887:                errorsButton.setVisible(false);
06888:                errorsButton.setBackground(DrJava.getConfig().getSetting(
06889:                        DRJAVA_ERRORS_BUTTON_COLOR));
06890:                DrJavaErrorHandler.setButton(errorsButton);
06891:                _toolBar.add(errorsButton);
06892:                /** The OptionListener for DRJAVA_ERRORS_BUTTON_COLOR. */
06893:                OptionListener<Color> errBtnColorOptionListener = new OptionListener<Color>() {
06894:                    public void optionChanged(OptionEvent<Color> oce) {
06895:                        errorsButton.setBackground(oce.value);
06896:                    }
06897:                };
06898:                DrJava.getConfig().addOptionListener(
06899:                        DRJAVA_ERRORS_BUTTON_COLOR, errBtnColorOptionListener);
06900:
06901:                // Correct the vertical height of the buttons.
06902:                _fixToolbarHeights();
06903:
06904:                getContentPane().add(_toolBar, BorderLayout.NORTH);
06905:                //    _updateToolBarVisible();  // created a visible GUI component during  initialization!
06906:            }
06907:
06908:            /** Sets the toolbar as either visible or invisible based on the config option. */
06909:            private void _updateToolBarVisible() {
06910:                _toolBar.setVisible(DrJava.getConfig().getSetting(
06911:                        TOOLBAR_ENABLED));
06912:            }
06913:
06914:            /** Update the toolbar's buttons, following any change to TOOLBAR_ICONS_ENABLED, TOOLBAR_TEXT_ENABLED, or 
06915:             *  FONT_TOOLBAR (name, style, text)
06916:             */
06917:            private void _updateToolbarButtons() {
06918:                _updateToolBarVisible();
06919:                Component[] buttons = _toolBar.getComponents();
06920:
06921:                Font toolbarFont = DrJava.getConfig().getSetting(FONT_TOOLBAR);
06922:                boolean iconsEnabled = DrJava.getConfig().getSetting(
06923:                        TOOLBAR_ICONS_ENABLED).booleanValue();
06924:                boolean textEnabled = DrJava.getConfig().getSetting(
06925:                        TOOLBAR_TEXT_ENABLED).booleanValue();
06926:
06927:                for (int i = 0; i < buttons.length; i++) {
06928:
06929:                    if (buttons[i] instanceof  JButton) {
06930:
06931:                        JButton b = (JButton) buttons[i];
06932:                        Action a = b.getAction();
06933:
06934:                        // Work-around for strange configuration of undo/redo buttons
06935:                        /*
06936:                         if (a == null) {
06937:                         ActionListener[] al = b.getActionListeners(); // 1.4 only
06938:                         
06939:                         for (int j=0; j<al.length; j++) {
06940:                         if (al[j] instanceof Action) {
06941:                         a = (Action) al[j];
06942:                         break;
06943:                         }
06944:                         }
06945:                         }
06946:                         */
06947:
06948:                        b.setFont(toolbarFont);
06949:
06950:                        if (a == null) {
06951:                            if (b == _undoButton)
06952:                                a = _undoAction;
06953:                            else if (b == _redoButton)
06954:                                a = _redoAction;
06955:                            else
06956:                                continue;
06957:                        }
06958:
06959:                        if (b.getIcon() == null) {
06960:                            if (iconsEnabled)
06961:                                b.setIcon((Icon) a.getValue(Action.SMALL_ICON));
06962:                        } else if (!iconsEnabled && b.getText().equals(""))
06963:                            b.setIcon(null);
06964:
06965:                        if (b.getText().equals("")) {
06966:                            if (textEnabled)
06967:                                b.setText((String) a.getValue(Action.DEFAULT));
06968:                        } else if (!textEnabled && b.getIcon() != null)
06969:                            b.setText("");
06970:
06971:                    }
06972:                }
06973:
06974:                // Correct the vertical height of the buttons.
06975:                _fixToolbarHeights();
06976:            }
06977:
06978:            /** Ensures that all toolbar buttons have the same height. */
06979:            private void _fixToolbarHeights() {
06980:                Component[] buttons = _toolBar.getComponents();
06981:
06982:                // First, find the maximum height of all the buttons.
06983:                int max = 0;
06984:                for (int i = 0; i < buttons.length; i++) {
06985:                    // We only care about the JButtons.
06986:                    if (buttons[i] instanceof  JButton) {
06987:                        JButton b = (JButton) buttons[i];
06988:
06989:                        // reset any preferred size we have set
06990:                        b.setPreferredSize(null);
06991:
06992:                        // get the preferred height, since that's what we want to use
06993:                        Dimension d = b.getPreferredSize();
06994:                        int cur = (int) d.getHeight();
06995:                        if (cur > max) {
06996:                            max = cur;
06997:                        }
06998:                    }
06999:                }
07000:
07001:                // Now set all button heights to the max.
07002:                for (int i = 0; i < buttons.length; i++) {
07003:                    // We only care about the JButtons.
07004:                    if (buttons[i] instanceof  JButton) {
07005:                        JButton b = (JButton) buttons[i];
07006:                        Dimension d = new Dimension((int) b.getPreferredSize()
07007:                                .getWidth(), max);
07008:
07009:                        // JToolBar inexplicably uses the max size
07010:                        // also set preferred size for consistency
07011:                        b.setPreferredSize(d);
07012:                        b.setMaximumSize(d);
07013:                    }
07014:                }
07015:
07016:                // _toolbar.revalidate();
07017:            }
07018:
07019:            /** Sets up the status bar with the filename field. Only called from MainFrame constructor. */
07020:            private void _setUpStatusBar() {
07021:
07022:                // Initialize the 3 labels:
07023:
07024:                _statusField.setFont(_statusField.getFont().deriveFont(
07025:                        Font.PLAIN));
07026:                _statusReport.setHorizontalAlignment(SwingConstants.RIGHT);
07027:
07028:                JPanel fileNameAndMessagePanel = new JPanel(new BorderLayout());
07029:                fileNameAndMessagePanel.add(_statusField, BorderLayout.CENTER);
07030:                fileNameAndMessagePanel.add(_statusReport, BorderLayout.EAST);
07031:
07032:                _currLocationField.setFont(_currLocationField.getFont()
07033:                        .deriveFont(Font.PLAIN));
07034:                _currLocationField.setHorizontalAlignment(SwingConstants.RIGHT);
07035:                _currLocationField.setPreferredSize(new Dimension(165, 12));
07036:                //    _currLocationField.setVisible(true);
07037:
07038:                // Initialize the status bar panel
07039:                //    SpringLayout layout = new SpringLayout();
07040:                _statusBar.add(fileNameAndMessagePanel, BorderLayout.CENTER);
07041:                //    _statusBar.add( sbMessagePanel, BorderLayout.CENTER );
07042:                _statusBar.add(_currLocationField, BorderLayout.EAST);
07043:                _statusBar.setBorder(new CompoundBorder(new EmptyBorder(2, 2,
07044:                        2, 2), new CompoundBorder(new BevelBorder(
07045:                        BevelBorder.LOWERED), new EmptyBorder(2, 2, 2, 2))));
07046:                getContentPane().add(_statusBar, BorderLayout.SOUTH);
07047:
07048:                //     //Adjust constraints for the fileName label so it's next to the left edge.
07049:                //     layout.getConstraints(_statusField).setX(Spring.constant(0));
07050:                //     
07051:                //     //Adjust constraints for the message label so it's spaced a bit from the right.
07052:                //     //and doesn't interfere with the left-most label
07053:                //     layout.putConstraint(SpringLayout.EAST, _statusReport, -65,
07054:                //     SpringLayout.EAST, _statusBar);
07055:                //     
07056:                //     //Adjust constraints for the location label so it's next to the right edge.
07057:                //     layout.putConstraint(SpringLayout.EAST, _currLocationField, 0,
07058:                //     SpringLayout.EAST, _statusBar);
07059:                //     
07060:                //     //Adjust constraints for the panel to set its size
07061:                //     layout.putConstraint(SpringLayout.SOUTH, _statusBar, 0,
07062:                //     SpringLayout.SOUTH, _currLocationField);
07063:            }
07064:
07065:            /** Inner class to handle updating the current position in the document.  Registered with the DefinitionsPane. **/
07066:            private class PositionListener implements  CaretListener {
07067:
07068:                /* Cached caret coordinates */
07069:                private int _offset;
07070:                private int _line;
07071:                private int _col;
07072:
07073:                // The following method only runs in the event thread because it is called from DefinitionsPane
07074:                public void caretUpdate(final CaretEvent ce) {
07075:                    OpenDefinitionsDocument doc = _model.getActiveDocument();
07076:                    int offset = ce.getDot();
07077:                    try {
07078:                        if (offset == _offset + 1
07079:                                && doc.getText(_offset, 1).charAt(0) != '\n') {
07080:                            _col += 1;
07081:                            updateLocation(_line, _col);
07082:                            return;
07083:                        }
07084:                    } catch (BadLocationException e) { /* fall through */
07085:                    }
07086:
07087:                    Element root = doc.getDefaultRootElement();
07088:                    int line = root.getElementIndex(offset);
07089:                    _line = line + 1; // line numbers are 1-based
07090:                    _col = offset - root.getElement(line).getStartOffset();
07091:                    updateLocation(_line, _col);
07092:                }
07093:
07094:                // This method appears safe outside the event thread
07095:                public void updateLocation() {
07096:                    OpenDefinitionsDocument doc = _model.getActiveDocument();
07097:                    doc.acquireReadLock(); // lock to ensure consistency of two reads from doc
07098:                    try {
07099:                        updateLocation(doc.getCurrentLine(), doc
07100:                                .getCurrentCol());
07101:                    } finally {
07102:                        doc.releaseReadLock();
07103:                    }
07104:                }
07105:
07106:                private void updateLocation(int line, int col) { // Not run in event thread because setText is thread safe.
07107:                    _currLocationField.setText(line + ":" + col + " \t"); // Space before "\t" required on Mac to avoid obscuring
07108:                    //      Any lightweight parsing has been disabled until we have something that is beneficial and works better in the background.
07109:                    //      _model.getParsingControl().delay();
07110:                }
07111:            }
07112:
07113:            /* Only called from MainFrame constructor. */
07114:            private void _setUpTabs() {
07115:
07116:                // Interactions
07117:                _interactionsController
07118:                        .setPrevPaneAction(_switchToPreviousPaneAction);
07119:                _interactionsController
07120:                        .setNextPaneAction(_switchToNextPaneAction);
07121:
07122:                JScrollPane interactionsScroll = new BorderlessScrollPane(
07123:                        _interactionsPane,
07124:                        JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
07125:                        JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
07126:                _interactionsContainer.add(interactionsScroll,
07127:                        BorderLayout.CENTER);
07128:
07129:                if (_showDebugger) {
07130:                    // hook highlighting listener to breakpoint manager
07131:                    _model.getBreakpointManager().addListener(
07132:                            new RegionManagerListener<Breakpoint>() {
07133:                                /* Called when a breakpoint is added. Only runs in event thread. */
07134:                                public void regionAdded(final Breakpoint bp,
07135:                                        int index) {
07136:                                    DefinitionsPane bpPane = getDefPaneGivenODD(bp
07137:                                            .getDocument());
07138:                                    _documentBreakpointHighlights
07139:                                            .put(
07140:                                                    bp,
07141:                                                    bpPane
07142:                                                            .getHighlightManager()
07143:                                                            .addHighlight(
07144:                                                                    bp
07145:                                                                            .getStartOffset(),
07146:                                                                    bp
07147:                                                                            .getEndOffset(),
07148:                                                                    bp
07149:                                                                            .isEnabled() ? DefinitionsPane.BREAKPOINT_PAINTER
07150:                                                                            : DefinitionsPane.DISABLED_BREAKPOINT_PAINTER));
07151:                                    _updateDebugStatus();
07152:                                }
07153:
07154:                                /** Called when a breakpoint is changed. Only runs in event thread. */
07155:                                public void regionChanged(Breakpoint bp,
07156:                                        int index) {
07157:                                    regionRemoved(bp);
07158:                                    regionAdded(bp, index);
07159:                                }
07160:
07161:                                /** Called when a breakpoint is removed. Only runs in event thread. */
07162:                                public void regionRemoved(final Breakpoint bp) {
07163:                                    HighlightManager.HighlightInfo highlight = _documentBreakpointHighlights
07164:                                            .get(bp);
07165:                                    if (highlight != null)
07166:                                        highlight.remove();
07167:                                    _documentBreakpointHighlights.remove(bp);
07168:                                }
07169:                            });
07170:                }
07171:
07172:                // hook highlighting listener to bookmark manager
07173:                _model.getBookmarkManager().addListener(
07174:                        new RegionManagerListener<DocumentRegion>() {
07175:                            // listener methods only run in the event thread
07176:                            public void regionAdded(DocumentRegion r, int index) {
07177:                                DefinitionsPane bpPane = getDefPaneGivenODD(r
07178:                                        .getDocument());
07179:                                _documentBookmarkHighlights
07180:                                        .put(
07181:                                                r,
07182:                                                bpPane
07183:                                                        .getHighlightManager()
07184:                                                        .addHighlight(
07185:                                                                r
07186:                                                                        .getStartOffset(),
07187:                                                                r
07188:                                                                        .getEndOffset(),
07189:                                                                DefinitionsPane.BOOKMARK_PAINTER));
07190:                            }
07191:
07192:                            public void regionChanged(DocumentRegion r,
07193:                                    int index) {
07194:                                regionRemoved(r);
07195:                                regionAdded(r, index);
07196:                            }
07197:
07198:                            public void regionRemoved(DocumentRegion r) {
07199:                                HighlightManager.HighlightInfo highlight = _documentBookmarkHighlights
07200:                                        .get(r);
07201:                                if (highlight != null)
07202:                                    highlight.remove();
07203:                                _documentBookmarkHighlights.remove(r);
07204:                            }
07205:                        });
07206:
07207:                _tabbedPane.addChangeListener(new ChangeListener() {
07208:                    public void stateChanged(ChangeEvent e) {
07209:                        //        System.err.println("_tabbedPane.stateChanged called with event " + e);
07210:                        clearStatusMessage();
07211:
07212:                        if (_tabbedPane.getSelectedIndex() == INTERACTIONS_TAB) {
07213:                            // Use SwingUtilities because this action must execute AFTER all pending events in the event queue
07214:                            //        System.err.println("Interactions Container Selected");
07215:                            _interactionsContainer.setVisible(true); // kluge to overcome subtle focus bug
07216:                            EventQueue.invokeLater(new Runnable() {
07217:                                public void run() {
07218:                                    _interactionsContainer
07219:                                            .requestFocusInWindow();
07220:                                }
07221:                            });
07222:                        } else if (_tabbedPane.getSelectedIndex() == CONSOLE_TAB) {
07223:                            // Use SwingUtilities because this action must execute AFTER all pending events in the event queue
07224:                            //          System.err.println("Console Scroll Selected");
07225:                            EventQueue.invokeLater(new Runnable() {
07226:                                public void run() {
07227:                                    _consoleScroll.requestFocusInWindow();
07228:                                }
07229:                            });
07230:                        }
07231:                        // Update error highlights?
07232:                        if (_currentDefPane != null) {
07233:                            int pos = _currentDefPane.getCaretPosition();
07234:                            _currentDefPane.removeErrorHighlight(); //this line removes the highlighting whenever the current tabbed pane is switched
07235:                            _currentDefPane.getErrorCaretListener()
07236:                                    .updateHighlight(pos);
07237:                        }
07238:                    }
07239:                });
07240:
07241:                _tabbedPane.add("Interactions", _interactionsContainer);
07242:                _tabbedPane.add("Console", _consoleScroll);
07243:
07244:                _tabs.addLast(_compilerErrorPanel);
07245:                _tabs.addLast(_junitErrorPanel);
07246:                _tabs.addLast(_javadocErrorPanel);
07247:                _tabs.addLast(_findReplace);
07248:                if (_showDebugger) {
07249:                    _tabs.addLast(_breakpointsPanel);
07250:                }
07251:                _tabs.addLast(_bookmarksPanel);
07252:
07253:                _interactionsContainer.addFocusListener(new FocusAdapter() {
07254:                    public void focusGained(FocusEvent e) {
07255:                        EventQueue.invokeLater(new Runnable() {
07256:                            public void run() {
07257:                                //            System.err.println("Requesting focus in interactions pane");
07258:                                _interactionsPane.requestFocusInWindow();
07259:                            }
07260:                        });
07261:                    }
07262:                });
07263:
07264:                _interactionsPane.addFocusListener(new FocusAdapter() {
07265:                    public void focusGained(FocusEvent e) {
07266:                        _lastFocusOwner = _interactionsContainer;
07267:                    }
07268:                });
07269:                _consolePane.addFocusListener(new FocusAdapter() {
07270:                    public void focusGained(FocusEvent e) {
07271:                        _lastFocusOwner = _consoleScroll;
07272:                    }
07273:                });
07274:                _compilerErrorPanel.getMainPanel().addFocusListener(
07275:                        new FocusAdapter() {
07276:                            public void focusGained(FocusEvent e) {
07277:                                _lastFocusOwner = _compilerErrorPanel;
07278:                            }
07279:                        });
07280:                _junitErrorPanel.getMainPanel().addFocusListener(
07281:                        new FocusAdapter() {
07282:                            public void focusGained(FocusEvent e) {
07283:                                _lastFocusOwner = _junitErrorPanel;
07284:                            }
07285:                        });
07286:                _javadocErrorPanel.getMainPanel().addFocusListener(
07287:                        new FocusAdapter() {
07288:                            public void focusGained(FocusEvent e) {
07289:                                _lastFocusOwner = _javadocErrorPanel;
07290:                            }
07291:                        });
07292:                _findReplace.getFindField().addFocusListener(
07293:                        new FocusAdapter() {
07294:                            public void focusGained(FocusEvent e) {
07295:                                _lastFocusOwner = _findReplace;
07296:                            }
07297:                        });
07298:                if (_showDebugger) {
07299:                    _breakpointsPanel.getMainPanel().addFocusListener(
07300:                            new FocusAdapter() {
07301:                                public void focusGained(FocusEvent e) {
07302:                                    _lastFocusOwner = _breakpointsPanel;
07303:                                }
07304:                            });
07305:                }
07306:                _bookmarksPanel.getMainPanel().addFocusListener(
07307:                        new FocusAdapter() {
07308:                            public void focusGained(FocusEvent e) {
07309:                                _lastFocusOwner = _bookmarksPanel;
07310:                            }
07311:                        });
07312:            }
07313:
07314:            /** Realizes this MainFrame by setting it visibile and configures the tabbed Pane. */
07315:            public void start() {
07316:
07317:                // Make the MainFrame visible and show the compiler tab
07318:                EventQueue.invokeLater(new Runnable() {
07319:                    public void run() {
07320:                        setVisible(true);
07321:                        _compilerErrorPanel.setVisible(true);
07322:                        showTab(_compilerErrorPanel);
07323:                        /* The following two step sequence was laboriously developed by trial and error; without it the _tabbedPane
07324:                         * does not display properly. */
07325:                        _tabbedPane.invalidate();
07326:                        _tabbedPane.repaint();
07327:                    }
07328:                });
07329:            }
07330:
07331:            /** Sets up the context menu to show in the document pane. */
07332:            private void _setUpContextMenus() {
07333:                // pop-up menu for a folder in tree view
07334:                //    _navPaneFolderPopupMenu = new JPopupMenu();
07335:                /*
07336:                 * Phil Repicky -smallproj
07337:                 * 2/14/2005
07338:                 * Make these do something:
07339:                 * _navPaneFolderPopupMenu.add("Open a File in this Folder Action");
07340:                 * _navPaneFolderPopupMenu.add("Make a New File in this Folder Action");
07341:                 */
07342:                //    _navPaneFolderPopupMenu.add(_newFileFolderAction);
07343:                //    _navPaneFolderPopupMenu.add(_openOneFolderAction);
07344:                //    _navPaneFolderPopupMenu.add(_openAllFolderAction);
07345:                //    _navPaneFolderPopupMenu.add(_closeFolderAction);
07346:                //    _navPaneFolderPopupMenu.add(_compileFolderAction);
07347:                //    _navPaneFolderPopupMenu.add(_junitFolderAction);
07348:                //    _navPanePopupMenuForRoot = new JPopupMenu();
07349:                //    _navPanePopupMenuForRoot.add(_saveProjectAction);
07350:                //    _navPanePopupMenuForRoot.add(_closeProjectAction);
07351:                //    _navPanePopupMenuForRoot.addSeparator();
07352:                //    _navPanePopupMenuForRoot.add(_compileProjectAction);
07353:                //    _navPanePopupMenuForRoot.add(_runProjectAction);
07354:                //    _navPanePopupMenuForRoot.add(_junitProjectAction);
07355:                //    _navPanePopupMenuForRoot.addSeparator();
07356:                //    _navPanePopupMenuForRoot.add(_projectPropertiesAction);
07357:                //    _navPanePopupMenuForExternal = new JPopupMenu();
07358:                //    _navPanePopupMenuForExternal.add(_saveAction);
07359:                //    _navPanePopupMenuForExternal.add(_saveAsAction);
07360:                //    _navPanePopupMenuForExternal.add(_renameAction);
07361:                //    _navPanePopupMenuForExternal.add(_revertAction);
07362:                //    _navPanePopupMenuForExternal.addSeparator();
07363:                //    _navPanePopupMenuForExternal.add(_closeAction);
07364:                //    _navPanePopupMenuForExternal.addSeparator();
07365:                //    _navPanePopupMenuForExternal.add(_printDefDocAction);
07366:                //    _navPanePopupMenuForExternal.add(_printDefDocPreviewAction);
07367:                //    _navPanePopupMenuForExternal.addSeparator();
07368:                //    _navPanePopupMenuForExternal.add(_compileAction);
07369:                //    _navPanePopupMenuForExternal.add(_junitAction);
07370:                //    _navPanePopupMenuForExternal.add(_javadocCurrentAction);
07371:                //    _navPanePopupMenuForExternal.add(_runAction);
07372:                //    _navPanePopupMenuForExternal.addSeparator();
07373:                //    _navPanePopupMenuForExternal.add(_moveToAuxiliaryAction);
07374:                //    _navPanePopupMenuForAuxiliary = new JPopupMenu();
07375:                //    _navPanePopupMenuForAuxiliary.add(_saveAction);
07376:                //    _navPanePopupMenuForAuxiliary.add(_saveAsAction);
07377:                //    _navPanePopupMenuForAuxiliary.add(_renameAction);
07378:                //    _navPanePopupMenuForAuxiliary.add(_revertAction);
07379:                //    _navPanePopupMenuForAuxiliary.addSeparator();
07380:                //    _navPanePopupMenuForAuxiliary.add(_closeAction);
07381:                //    _navPanePopupMenuForAuxiliary.addSeparator();
07382:                //    _navPanePopupMenuForAuxiliary.add(_printDefDocAction);
07383:                //    _navPanePopupMenuForAuxiliary.add(_printDefDocPreviewAction);
07384:                //    _navPanePopupMenuForAuxiliary.addSeparator();
07385:                //    _navPanePopupMenuForAuxiliary.add(_compileAction);
07386:                //    _navPanePopupMenuForAuxiliary.add(_junitAction);
07387:                //    _navPanePopupMenuForAuxiliary.add(_javadocCurrentAction);
07388:                //    _navPanePopupMenuForAuxiliary.add(_runAction);
07389:                //    _navPanePopupMenuForAuxiliary.addSeparator();
07390:                //    _navPanePopupMenuForAuxiliary.add(_removeAuxiliaryAction);
07391:                // NavPane menu
07392:                //    _navPanePopupMenu = new JPopupMenu();
07393:                //    _navPanePopupMenu.add(_saveAction);
07394:                //    _navPanePopupMenu.add(_saveAsAction);
07395:                //    _navPanePopupMenu.add(_renameAction);
07396:                //    _navPanePopupMenu.add(_revertAction);
07397:                //    _navPanePopupMenu.addSeparator();
07398:                //    _navPanePopupMenu.add(_closeAction);
07399:                //    _navPanePopupMenu.addSeparator();
07400:                //    _navPanePopupMenu.add(_printDefDocAction);
07401:                //    _navPanePopupMenu.add(_printDefDocPreviewAction);
07402:                //    _navPanePopupMenu.addSeparator();
07403:                //    _navPanePopupMenu.add(_compileAction);
07404:                //    _navPanePopupMenu.add(_junitAction);
07405:                //    _navPanePopupMenu.add(_javadocCurrentAction);
07406:                //    _navPanePopupMenu.add(_runAction);
07407:                _model.getDocCollectionWidget().addMouseListener(
07408:                        new RightClickMouseAdapter() {
07409:                            protected void _popupAction(MouseEvent e) {
07410:                                boolean showContextMenu = true;
07411:                                if (!_model.getDocumentNavigator()
07412:                                        .isSelectedAt(e.getX(), e.getY())) {
07413:                                    // click on a item that wasn't selected, change selection
07414:                                    showContextMenu = _model
07415:                                            .getDocumentNavigator()
07416:                                            .selectDocumentAt(e.getX(),
07417:                                                    e.getY());
07418:                                }
07419:                                if (showContextMenu) {
07420:                                    boolean rootSelected = _model
07421:                                            .getDocumentNavigator()
07422:                                            .isRootSelected();
07423:                                    boolean folderSelected = false;
07424:                                    boolean docSelected = false;
07425:                                    boolean externalSelected = false;
07426:                                    boolean auxiliarySelected = false;
07427:                                    boolean externalBinSelected = false;
07428:                                    boolean auxiliaryBinSelected = false;
07429:
07430:                                    final int docSelectedCount = _model
07431:                                            .getDocumentNavigator()
07432:                                            .getDocumentSelectedCount();
07433:                                    final int groupSelectedCount = _model
07434:                                            .getDocumentNavigator()
07435:                                            .getGroupSelectedCount();
07436:                                    try {
07437:                                        java.util.Set<String> groupNames = _model
07438:                                                .getDocumentNavigator()
07439:                                                .getNamesOfSelectedTopLevelGroup();
07440:
07441:                                        if (docSelectedCount > 0) {
07442:                                            // when documents are selected, ignore all other options and only deal with documents
07443:                                            rootSelected = false;
07444:                                            if (groupNames.contains(_model
07445:                                                    .getSourceBinTitle())) {
07446:                                                // a document in the "[ Source Files ]" bin is selected
07447:                                                docSelected = true;
07448:                                            }
07449:                                            if (groupNames.contains(_model
07450:                                                    .getExternalBinTitle())) {
07451:                                                // a document in the "[ External Files ]" bin is selected
07452:                                                externalSelected = true;
07453:                                            }
07454:                                            if (groupNames.contains(_model
07455:                                                    .getAuxiliaryBinTitle())) {
07456:                                                // a document in the "[ Included External Files ]" bin is selected
07457:                                                auxiliarySelected = true;
07458:                                            }
07459:                                        } else {
07460:                                            // no document selected, check other options
07461:                                            if (groupSelectedCount > 0) {
07462:                                                // at least one folder is selected
07463:                                                if (!_model
07464:                                                        .getDocumentNavigator()
07465:                                                        .isTopLevelGroupSelected()) {
07466:                                                    // it is really a folder and not a top level bin, e.g. "[ Source Files ]"
07467:                                                    folderSelected = true;
07468:                                                } else {
07469:                                                    // it is a top level bin, e.g. "[ Source Files ]"
07470:                                                    if (groupNames
07471:                                                            .contains(_model
07472:                                                                    .getSourceBinTitle())) {
07473:                                                        // the "[ Source Files ]" bin is selected, treat as normal folder
07474:                                                        folderSelected = true;
07475:                                                    }
07476:                                                    if (groupNames
07477:                                                            .contains(_model
07478:                                                                    .getExternalBinTitle())) {
07479:                                                        // the "[ External Files ]" bin is selected
07480:                                                        externalBinSelected = true;
07481:                                                    }
07482:                                                    if (groupNames
07483:                                                            .contains(_model
07484:                                                                    .getAuxiliaryBinTitle())) {
07485:                                                        // the "[ Included External Files ]" bin is selected
07486:                                                        auxiliaryBinSelected = true;
07487:                                                    }
07488:                                                }
07489:                                            }
07490:                                        }
07491:                                    } catch (GroupNotSelectedException ex) {
07492:                                        // we're looking at the root of the tree, or we're in list view...
07493:                                        if (_model.isProjectActive()) {
07494:                                            // project view, so the root has been selected
07495:                                            rootSelected = true;
07496:                                        } else {
07497:                                            // list view, so treat it as simple documents
07498:                                            docSelected = true;
07499:                                            rootSelected = false;
07500:                                            folderSelected = false;
07501:                                            externalSelected = false;
07502:                                            auxiliarySelected = false;
07503:                                            externalBinSelected = false;
07504:                                            auxiliaryBinSelected = false;
07505:                                        }
07506:                                    }
07507:
07508:                                    if (!rootSelected && !folderSelected
07509:                                            && !docSelected
07510:                                            && !externalSelected
07511:                                            && !auxiliarySelected
07512:                                            && !externalBinSelected
07513:                                            && !auxiliaryBinSelected) {
07514:                                        // nothing selected, don't display anything
07515:                                        return;
07516:                                    }
07517:
07518:                                    final JPopupMenu m = new JPopupMenu();
07519:                                    if (docSelectedCount == 0) {
07520:                                        docSelected = externalSelected = auxiliarySelected = false;
07521:                                    }
07522:                                    if (groupSelectedCount == 0) {
07523:                                        folderSelected = false;
07524:                                    }
07525:
07526:                                    if (rootSelected) {
07527:                                        // root selected
07528:                                        m.add(Utilities.createDelegateAction(
07529:                                                "Save Project",
07530:                                                _saveProjectAction));
07531:                                        m.add(Utilities.createDelegateAction(
07532:                                                "Close Project",
07533:                                                _closeProjectAction));
07534:                                        m.add(_compileProjectAction);
07535:                                        m.add(_runProjectAction);
07536:                                        m.add(_junitProjectAction);
07537:                                        m.add(_projectPropertiesAction);
07538:                                    }
07539:                                    if (folderSelected) {
07540:                                        // folder selected
07541:                                        if (m.getComponentCount() > 0) {
07542:                                            m.addSeparator();
07543:                                        }
07544:                                        if (groupSelectedCount == 1) {
07545:                                            // "New File in Folder" and "Open File in Folder" only work if exactly
07546:                                            // one folder is selected
07547:                                            m.add(_newFileFolderAction);
07548:                                            m.add(_openOneFolderAction);
07549:
07550:                                            // get singular/plural right
07551:                                            m
07552:                                                    .add(Utilities
07553:                                                            .createDelegateAction(
07554:                                                                    "Open All Files in Folder",
07555:                                                                    _openAllFolderAction));
07556:                                            m.add(_closeFolderAction);
07557:                                            m.add(_compileFolderAction);
07558:                                            m.add(_junitFolderAction);
07559:                                        } else if (groupSelectedCount > 1) {
07560:                                            if (!externalBinSelected
07561:                                                    && !auxiliaryBinSelected) {
07562:                                                // open only makes sense if it's real folders, and not
07563:                                                // the external or auxiliary bins
07564:                                                m
07565:                                                        .add(Utilities
07566:                                                                .createDelegateAction(
07567:                                                                        "Open All Files in All Folders ("
07568:                                                                                + groupSelectedCount
07569:                                                                                + ")",
07570:                                                                        _openAllFolderAction));
07571:                                            }
07572:                                            m
07573:                                                    .add(Utilities
07574:                                                            .createDelegateAction(
07575:                                                                    "Close All Folders ("
07576:                                                                            + groupSelectedCount
07577:                                                                            + ")",
07578:                                                                    _closeFolderAction));
07579:                                            m
07580:                                                    .add(Utilities
07581:                                                            .createDelegateAction(
07582:                                                                    "Compile All Folders ("
07583:                                                                            + groupSelectedCount
07584:                                                                            + ")",
07585:                                                                    _compileFolderAction));
07586:                                            m
07587:                                                    .add(Utilities
07588:                                                            .createDelegateAction(
07589:                                                                    "Test All Folders ("
07590:                                                                            + groupSelectedCount
07591:                                                                            + ")",
07592:                                                                    _junitFolderAction));
07593:
07594:                                        }
07595:                                    }
07596:                                    if (docSelected || externalSelected
07597:                                            || auxiliarySelected) {
07598:                                        // some kind of document selected
07599:                                        if (m.getComponentCount() > 0) {
07600:                                            m.addSeparator();
07601:                                        }
07602:                                        if (docSelectedCount == 1) {
07603:                                            m.add(Utilities
07604:                                                    .createDelegateAction(
07605:                                                            "Save File",
07606:                                                            _saveAction));
07607:                                            m.add(Utilities
07608:                                                    .createDelegateAction(
07609:                                                            "Save File As...",
07610:                                                            _saveAsAction));
07611:                                            m.add(Utilities
07612:                                                    .createDelegateAction(
07613:                                                            "Rename File",
07614:                                                            _renameAction));
07615:                                            m
07616:                                                    .add(Utilities
07617:                                                            .createDelegateAction(
07618:                                                                    "Revert File to Saved",
07619:                                                                    _revertAction));
07620:                                            m.add(Utilities
07621:                                                    .createDelegateAction(
07622:                                                            "Close File",
07623:                                                            _closeAction));
07624:                                            m
07625:                                                    .add(Utilities
07626:                                                            .createDelegateAction(
07627:                                                                    "Print File...",
07628:                                                                    _printDefDocAction));
07629:                                            m
07630:                                                    .add(Utilities
07631:                                                            .createDelegateAction(
07632:                                                                    "Print File Preview...",
07633:                                                                    _printDefDocPreviewAction));
07634:                                            m.add(Utilities
07635:                                                    .createDelegateAction(
07636:                                                            "Compile File",
07637:                                                            _compileAction));
07638:                                            m.add(Utilities
07639:                                                    .createDelegateAction(
07640:                                                            "Test File",
07641:                                                            _junitAction));
07642:                                            m
07643:                                                    .add(Utilities
07644:                                                            .createDelegateAction(
07645:                                                                    "Preview Javadoc for File",
07646:                                                                    _javadocCurrentAction));
07647:                                            m
07648:                                                    .add(Utilities
07649:                                                            .createDelegateAction(
07650:                                                                    "Run File's Main Method",
07651:                                                                    _runAction));
07652:                                        } else if (docSelectedCount > 1) {
07653:                                            m
07654:                                                    .add(Utilities
07655:                                                            .createDelegateAction(
07656:                                                                    "Save All Files ("
07657:                                                                            + docSelectedCount
07658:                                                                            + ")",
07659:                                                                    _saveAction));
07660:                                            m
07661:                                                    .add(Utilities
07662:                                                            .createDelegateAction(
07663:                                                                    "Revert All Files to Saved ("
07664:                                                                            + docSelectedCount
07665:                                                                            + ")",
07666:                                                                    _revertAction));
07667:                                            m
07668:                                                    .add(Utilities
07669:                                                            .createDelegateAction(
07670:                                                                    "Close All Files  ("
07671:                                                                            + docSelectedCount
07672:                                                                            + ")",
07673:                                                                    _closeAction));
07674:                                            m
07675:                                                    .add(Utilities
07676:                                                            .createDelegateAction(
07677:                                                                    "Compile All Files ("
07678:                                                                            + docSelectedCount
07679:                                                                            + ")",
07680:                                                                    _compileAction));
07681:                                            m
07682:                                                    .add(Utilities
07683:                                                            .createDelegateAction(
07684:                                                                    "Test All Files ("
07685:                                                                            + docSelectedCount
07686:                                                                            + ")",
07687:                                                                    _junitAction));
07688:                                        }
07689:                                    }
07690:                                    if (externalSelected && !docSelected
07691:                                            && !auxiliarySelected) {
07692:                                        // external document selected, but no regular or auxiliary documents
07693:                                        if (m.getComponentCount() > 0) {
07694:                                            m.addSeparator();
07695:                                        }
07696:                                        if (docSelectedCount == 1) {
07697:                                            m
07698:                                                    .add(Utilities
07699:                                                            .createDelegateAction(
07700:                                                                    "Include File With Project",
07701:                                                                    _moveToAuxiliaryAction));
07702:                                        } else if (docSelectedCount > 1) {
07703:                                            m
07704:                                                    .add(Utilities
07705:                                                            .createDelegateAction(
07706:                                                                    "Include All Files With Project ("
07707:                                                                            + docSelectedCount
07708:                                                                            + ")",
07709:                                                                    _moveToAuxiliaryAction));
07710:                                        }
07711:                                    }
07712:                                    if (auxiliarySelected && !docSelected
07713:                                            && !externalSelected) {
07714:                                        // auxiliary document selected, but no regular or external documents
07715:                                        if (m.getComponentCount() > 0) {
07716:                                            m.addSeparator();
07717:                                        }
07718:                                        if (docSelectedCount == 1) {
07719:                                            m
07720:                                                    .add(Utilities
07721:                                                            .createDelegateAction(
07722:                                                                    "Do Not Include File With Project",
07723:                                                                    _removeAuxiliaryAction));
07724:                                        } else if (docSelectedCount > 1) {
07725:                                            m
07726:                                                    .add(Utilities
07727:                                                            .createDelegateAction(
07728:                                                                    "Do Not Include Any Files With Project ("
07729:                                                                            + docSelectedCount
07730:                                                                            + ")",
07731:                                                                    _removeAuxiliaryAction));
07732:                                        }
07733:                                    }
07734:                                    if (!folderSelected
07735:                                            && (externalBinSelected || auxiliaryBinSelected)) {
07736:                                        // external or auxiliary bin selected, but no regular folder
07737:                                        if (m.getComponentCount() > 0) {
07738:                                            m.addSeparator();
07739:                                        }
07740:                                        m.add(Utilities.createDelegateAction(
07741:                                                "Close All Files",
07742:                                                _closeFolderAction));
07743:                                        m.add(Utilities.createDelegateAction(
07744:                                                "Compile All Files",
07745:                                                _compileFolderAction));
07746:                                        m.add(Utilities.createDelegateAction(
07747:                                                "Test All Files",
07748:                                                _junitFolderAction));
07749:                                    }
07750:                                    if (externalBinSelected
07751:                                            && !auxiliaryBinSelected) {
07752:                                        // external bin selected
07753:                                        m
07754:                                                .add(Utilities
07755:                                                        .createDelegateAction(
07756:                                                                "Include All Files With Project",
07757:                                                                _moveAllToAuxiliaryAction));
07758:                                    }
07759:                                    if (auxiliaryBinSelected
07760:                                            && !externalBinSelected) {
07761:                                        // auxiliary bin selected
07762:                                        m
07763:                                                .add(Utilities
07764:                                                        .createDelegateAction(
07765:                                                                "Do Not Include Any Files With Project",
07766:                                                                _removeAllAuxiliaryAction));
07767:                                    }
07768:
07769:                                    m
07770:                                            .show(e.getComponent(), e.getX(), e
07771:                                                    .getY());
07772:                                }
07773:                            }
07774:                        });
07775:                //    _model.getDocCollectionWidget().addMouseListener(new RightClickMouseAdapter() {
07776:                //      protected void _popupAction(MouseEvent e) {
07777:                //        if (_model.getDocumentNavigator().selectDocumentAt(e.getX(), e.getY())) {
07778:                //          if (_model.getDocumentNavigator().isGroupSelected())
07779:                //            _navPaneFolderPopupMenu.show(e.getComponent(), e.getX(), e.getY());
07780:                //          
07781:                //          else {
07782:                //            try {
07783:                //              String groupName = _model.getDocumentNavigator().getNameOfSelectedTopLevelGroup();
07784:                //              if (groupName.equals(_model.getSourceBinTitle()))
07785:                //                _navPanePopupMenu.show(e.getComponent(), e.getX(), e.getY());
07786:                //              else if (groupName.equals(_model.getExternalBinTitle())) {
07787:                //                INavigatorItem n = _model.getDocumentNavigator().getCurrent();
07788:                //                if (n != null) {
07789:                //                  OpenDefinitionsDocument d = (OpenDefinitionsDocument) n;
07790:                //                  if (d.isUntitled()) { _navPanePopupMenu.show(e.getComponent(), e.getX(), e.getY()); }
07791:                //                  else _navPanePopupMenuForExternal.show(e.getComponent(), e.getX(), e.getY());
07792:                //                }
07793:                //              }
07794:                //              else if (groupName.equals(_model.getAuxiliaryBinTitle()))
07795:                //                _navPanePopupMenuForAuxiliary.show(e.getComponent(), e.getX(), e.getY());
07796:                //            }
07797:                //            catch(GroupNotSelectedException ex) {
07798:                //              // we're looking at the root of the tree, or we're in list view...
07799:                //              if (_model.isProjectActive())
07800:                //                _navPanePopupMenuForRoot.show(e.getComponent(), e.getX(), e.getY());
07801:                //              else  _navPanePopupMenu.show(e.getComponent(), e.getX(), e.getY());
07802:                //            }
07803:                //          }
07804:                //        }
07805:                //      }
07806:                //    });
07807:
07808:                // Interactions pane menu
07809:                _interactionsPanePopupMenu = new JPopupMenu();
07810:                _interactionsPanePopupMenu.add(cutAction);
07811:                _interactionsPanePopupMenu.add(copyAction);
07812:                _interactionsPanePopupMenu.add(pasteAction);
07813:                _interactionsPanePopupMenu.addSeparator();
07814:                _interactionsPanePopupMenu.add(_printInteractionsAction);
07815:                _interactionsPanePopupMenu.add(_printInteractionsPreviewAction);
07816:                _interactionsPanePopupMenu.addSeparator();
07817:                _interactionsPanePopupMenu.add(_executeHistoryAction);
07818:                _interactionsPanePopupMenu.add(_loadHistoryScriptAction);
07819:                _interactionsPanePopupMenu.add(_saveHistoryAction);
07820:                _interactionsPanePopupMenu.add(_clearHistoryAction);
07821:                _interactionsPanePopupMenu.addSeparator();
07822:                _interactionsPanePopupMenu.add(_resetInteractionsAction);
07823:                _interactionsPanePopupMenu
07824:                        .add(_viewInteractionsClassPathAction);
07825:                _interactionsPanePopupMenu
07826:                        .add(_copyInteractionToDefinitionsAction);
07827:                _interactionsPane
07828:                        .addMouseListener(new RightClickMouseAdapter() {
07829:                            protected void _popupAction(MouseEvent e) {
07830:                                _interactionsPane.requestFocusInWindow();
07831:                                _interactionsPanePopupMenu.show(e
07832:                                        .getComponent(), e.getX(), e.getY());
07833:                            }
07834:                        });
07835:
07836:                // This listener updates the _cachedCaretPosition in the _interactionsController when the cursor is manually set.
07837:                _interactionsPane.addMouseListener(new MouseInputAdapter() {
07838:                    public void mouseClicked(MouseEvent e) {
07839:                        _interactionsController
07840:                                .setCachedCaretPos(_interactionsPane
07841:                                        .viewToModel(e.getPoint()));
07842:                    }
07843:                });
07844:                _consolePanePopupMenu = new JPopupMenu();
07845:                _consolePanePopupMenu.add(_clearConsoleAction);
07846:                _consolePanePopupMenu.addSeparator();
07847:                _consolePanePopupMenu.add(_printConsoleAction);
07848:                _consolePanePopupMenu.add(_printConsolePreviewAction);
07849:                _consolePane.addMouseListener(new RightClickMouseAdapter() {
07850:                    protected void _popupAction(MouseEvent e) {
07851:                        _consolePane.requestFocusInWindow();
07852:                        _consolePanePopupMenu.show(e.getComponent(), e.getX(),
07853:                                e.getY());
07854:                    }
07855:                });
07856:            }
07857:
07858:            private void nextRecentDoc() {
07859:                if (_recentDocFrame.isVisible())
07860:                    _recentDocFrame.next();
07861:                else
07862:                    _recentDocFrame.setVisible(true);
07863:            }
07864:
07865:            private void prevRecentDoc() {
07866:                if (_recentDocFrame.isVisible())
07867:                    _recentDocFrame.prev();
07868:                else
07869:                    _recentDocFrame.setVisible(true);
07870:            }
07871:
07872:            private void hideRecentDocFrame() {
07873:                if (_recentDocFrame.isVisible()) {
07874:                    _recentDocFrame.setVisible(false);
07875:                    OpenDefinitionsDocument doc = _recentDocFrame.getDocument();
07876:                    if (doc != null) {
07877:                        //        addToBrowserHistory();
07878:                        _model.setActiveDocument(doc);
07879:                        //        addToBrowserHistory();
07880:                    }
07881:                }
07882:            }
07883:
07884:            KeyListener _historyListener = new KeyListener() {
07885:                public void keyPressed(KeyEvent e) {
07886:                    if (e.getKeyCode() == java.awt.event.KeyEvent.VK_BACK_QUOTE
07887:                            && e.isControlDown() && !e.isShiftDown())
07888:                        nextRecentDoc();
07889:                    if (e.getKeyCode() == java.awt.event.KeyEvent.VK_BACK_QUOTE
07890:                            && e.isControlDown() && e.isShiftDown())
07891:                        prevRecentDoc();
07892:                    //    else if (e.getKeyCode()==java.awt.event.KeyEvent.VK_BACK_QUOTE) {
07893:                    //        transferFocusUpCycle();
07894:                    //    }
07895:                }
07896:
07897:                public void keyReleased(KeyEvent e) {
07898:                    if (e.getKeyCode() == java.awt.event.KeyEvent.VK_CONTROL)
07899:                        hideRecentDocFrame();
07900:                }
07901:
07902:                public void keyTyped(KeyEvent e) { /* noop */
07903:                }
07904:            };
07905:
07906:            FocusListener _focusListenerForRecentDocs = new FocusListener() {
07907:                public void focusLost(FocusEvent e) {
07908:                    hideRecentDocFrame();
07909:                }
07910:
07911:                public void focusGained(FocusEvent e) {
07912:                }
07913:            };
07914:
07915:            /** Create a new DefinitionsPane and JScrollPane for an open definitions document.  Package private for testing purposes.
07916:             * @param doc The open definitions document to wrap
07917:             * @return JScrollPane containing a DefinitionsPane for the given document.
07918:             */
07919:            JScrollPane _createDefScrollPane(OpenDefinitionsDocument doc) {
07920:                DefinitionsPane pane = new DefinitionsPane(this , doc);
07921:
07922:                pane.addKeyListener(_historyListener);
07923:                pane.addFocusListener(_focusListenerForRecentDocs);
07924:
07925:                // Add listeners
07926:                _installNewDocumentListener(doc);
07927:                ErrorCaretListener caretListener = new ErrorCaretListener(doc,
07928:                        pane, this );
07929:                pane.addErrorCaretListener(caretListener);
07930:
07931:                // Limiting line numbers to just lines existing in the document.
07932:                doc.addDocumentListener(new DocumentUIListener() {
07933:                    private void updateUI() {
07934:                        EventQueue.invokeLater(new Runnable() { // ?? Why EventQueue?
07935:                                    public void run() {
07936:                                        // revalidateLineNums();
07937:                                        if ((_breakpointsPanel != null)
07938:                                                && (_breakpointsPanel
07939:                                                        .isDisplayed())) {
07940:                                            _breakpointsPanel.repaint();
07941:                                        }
07942:                                        if ((_bookmarksPanel != null)
07943:                                                && (_bookmarksPanel
07944:                                                        .isDisplayed())) {
07945:                                            _bookmarksPanel.repaint();
07946:                                        }
07947:                                        for (Pair<FindResultsPanel, Hashtable<MovingDocumentRegion, HighlightManager.HighlightInfo>> pair : _findResults) {
07948:                                            FindResultsPanel panel = pair
07949:                                                    .first();
07950:                                            if ((panel != null)
07951:                                                    && (panel.isDisplayed())) {
07952:                                                panel.repaint();
07953:                                            }
07954:                                        }
07955:                                    }
07956:                                });
07957:                    }
07958:
07959:                    public void changedUpdate(DocumentEvent e) { /* updateUI(); */
07960:                    } // only attribute changes that matter are inserts and removes
07961:
07962:                    public void insertUpdate(DocumentEvent e) {
07963:                        updateUI();
07964:                    }
07965:
07966:                    public void removeUpdate(DocumentEvent e) {
07967:                        updateUI();
07968:                    }
07969:                });
07970:
07971:                // add a listener to update line and column.
07972:                pane.addCaretListener(_posListener);
07973:
07974:                // add a focus listener to this definitions pane.
07975:                pane.addFocusListener(new LastFocusListener());
07976:
07977:                // Add to a scroll pane
07978:                final JScrollPane scroll = new BorderlessScrollPane(pane,
07979:                        JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
07980:                        JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
07981:                pane.setScrollPane(scroll);
07982:                //scroll.setBorder(null); // removes all default borders (MacOS X installs default borders)
07983:
07984:                if (DrJava.getConfig().getSetting(LINEENUM_ENABLED)
07985:                        .booleanValue()) {
07986:                    scroll.setRowHeaderView(new LineEnumRule(pane));
07987:                }
07988:
07989:                _defScrollPanes.put(doc, scroll);
07990:
07991:                return scroll;
07992:            }
07993:
07994:            private void _setUpPanes() {
07995:                // DefinitionsPane
07996:                JScrollPane defScroll = _defScrollPanes.get(_model
07997:                        .getActiveDocument());
07998:
07999:                // Try to create debug panel (see if JSwat is around)
08000:                if (_showDebugger) {
08001:                    try {
08002:                        // Set the panel's size.
08003:                        int debugHeight = DrJava.getConfig().getSetting(
08004:                                DEBUG_PANEL_HEIGHT).intValue();
08005:                        Dimension debugMinSize = _debugPanel.getMinimumSize();
08006:
08007:                        // TODO: check bounds compared to entire window.
08008:                        if ((debugHeight > debugMinSize.height))
08009:                            debugMinSize.height = debugHeight;
08010:                        _debugPanel.setPreferredSize(debugMinSize);
08011:                    } catch (NoClassDefFoundError e) {
08012:                        // Don't use the debugger
08013:                        _showDebugger = false;
08014:                    }
08015:                }
08016:
08017:                _debugSplitPane.setBottomComponent(_debugPanel);
08018:                _mainSplit.setResizeWeight(1.0);
08019:                _debugSplitPane.setResizeWeight(1.0);
08020:                getContentPane().add(_mainSplit, BorderLayout.CENTER);
08021:                // This is annoyingly order-dependent. Since split contains _docSplitPane,
08022:                // we need to get split's divider set up first to give _docSplitPane an
08023:                // overall size. Then we can set _docSplitPane's divider. Ahh, Swing.
08024:                // Also, according to the Swing docs, we need to set these dividers AFTER
08025:                // we have shown the window. How annoying.
08026:                //    int tabHeight = DrJava.getConfig().getSetting(TABS_HEIGHT).intValue();
08027:
08028:                // 2*getHeight()/3
08029:                _mainSplit.setDividerLocation(_mainSplit.getHeight() - 132);
08030:                //    _mainSplit.setDividerLocation(_mainSplit.getHeight() - tabHeight);
08031:                _mainSplit.setOneTouchExpandable(true);
08032:                _debugSplitPane.setOneTouchExpandable(true);
08033:
08034:                int docListWidth = DrJava.getConfig()
08035:                        .getSetting(DOC_LIST_WIDTH).intValue();
08036:
08037:                // TODO: Check bounds.
08038:                _docSplitPane.setDividerLocation(docListWidth);
08039:                _docSplitPane.setOneTouchExpandable(true);
08040:            }
08041:
08042:            /** Switch to the JScrollPane containing the DefinitionsPane for the active document. Must run in event thread.*/
08043:            void _switchDefScrollPane() {
08044:                // demoted to package private protection to test the disabling editing while compiling functionality.
08045:                // and to support brute force fix to DefinitionsPane bug on return from compile with errors
08046:                // Added 2004-May-27
08047:                // Notify the definitions pane that is being replaced (becoming inactive)
08048:                _currentDefPane.notifyInactive();
08049:
08050:                //    Utilities.showDebug("_switchDefScrollPane called");
08051:                //    Utilities.showDebug("Right before getting the scrollPane");
08052:                OpenDefinitionsDocument doc = _model.getActiveDocument();
08053:                JScrollPane scroll = _defScrollPanes.get(doc);
08054:
08055:                if (scroll == null)
08056:                    scroll = _createDefScrollPane(doc);
08057:                // Fix OS X scrollbar bug before switching
08058:
08059:                _reenableScrollBar();
08060:
08061:                int oldLocation = _docSplitPane.getDividerLocation();
08062:                _docSplitPane.setRightComponent(scroll); //crazy line
08063:                _docSplitPane.setDividerLocation(oldLocation);
08064:
08065:                // if the current def pane is uneditable, that means we arrived here from a compile with errors.  We're
08066:                // guaranteed to make it editable again when we return from the compilation, so we take the state
08067:                // with us.  We guarantee only one definitions pane is un-editable at any time.
08068:                if (_currentDefPane.isEditable()) {
08069:                    _currentDefPane = (DefinitionsPane) scroll.getViewport()
08070:                            .getView();
08071:                    _currentDefPane.notifyActive();
08072:                } else {
08073:                    try {
08074:                        _currentDefPane.setEditable(true);
08075:                    } catch (NoSuchDocumentException e) { /* It's OK */
08076:                    }
08077:
08078:                    _currentDefPane = (DefinitionsPane) scroll.getViewport()
08079:                            .getView();
08080:                    _currentDefPane.notifyActive();
08081:                    _currentDefPane.setEditable(false);
08082:                }
08083:                // reset the undo/redo menu items
08084:                resetUndo();
08085:                _updateDebugStatus();
08086:            }
08087:
08088:            /** Refresh the JScrollPane containing the DefinitionsPane for the active document. Must run in event thread.*/
08089:            private void _refreshDefScrollPane() {
08090:                // Added 2004-May-27
08091:                // Notify the definitions pane that is being replaced (becoming inactive)
08092:                _currentDefPane.notifyInactive();
08093:
08094:                //    Utilities.showDebug("_switchDefScrollPane called");
08095:                //    Utilities.showDebug("Right before getting the scrollPane");
08096:                OpenDefinitionsDocument doc = _model.getActiveDocument();
08097:                JScrollPane scroll = _defScrollPanes.get(doc);
08098:
08099:                //    if (scroll == null) scroll = _createDefScrollPane(doc);
08100:                // Fix OS X scrollbar bug before switching
08101:
08102:                _reenableScrollBar();
08103:
08104:                int oldLocation = _docSplitPane.getDividerLocation();
08105:                _docSplitPane.setRightComponent(scroll); //crazy line
08106:                _docSplitPane.setDividerLocation(oldLocation);
08107:
08108:                //    // if the current def pane is uneditable, that means we arrived here from a compile with errors.  We're
08109:                //    // guaranteed to make it editable again when we return from the compilation, so we take the state
08110:                //    // with us.  We guarantee only one definitions pane is un-editable at any time.
08111:                //    if (_currentDefPane.isEditable()) {
08112:                //      _currentDefPane = (DefinitionsPane) scroll.getViewport().getView();
08113:                _currentDefPane.notifyActive();
08114:                //    }
08115:                //    else {
08116:                //      try { _currentDefPane.setEditable(true); }
08117:                //      catch(NoSuchDocumentException e) { /* It's OK */ }
08118:                //      
08119:                //      _currentDefPane = (DefinitionsPane) scroll.getViewport().getView();
08120:                //      _currentDefPane.notifyActive();
08121:                //      _currentDefPane.setEditable(false);
08122:                //    }
08123:                //    // reset the undo/redo menu items
08124:                resetUndo();
08125:                _updateDebugStatus();
08126:            }
08127:
08128:            /** Resets the undo/redo menu items */
08129:            public void resetUndo() {
08130:                _undoAction.setDelegatee(_currentDefPane.getUndoAction());
08131:                _redoAction.setDelegatee(_currentDefPane.getRedoAction());
08132:            }
08133:
08134:            public DefinitionsPane getDefPaneGivenODD(
08135:                    OpenDefinitionsDocument doc) {
08136:                JScrollPane scroll = _defScrollPanes.get(doc);
08137:                if (scroll == null) {
08138:                    throw new UnexpectedException(new Exception(
08139:                            "Region set in a closed document."));
08140:                }
08141:
08142:                DefinitionsPane pane = (DefinitionsPane) scroll.getViewport()
08143:                        .getView();
08144:                return pane;
08145:            }
08146:
08147:            /** Addresses Mac OS X bug where the scrollbars are disabled in one document after opening another. */
08148:            private void _reenableScrollBar() {
08149:                JScrollPane scroll = _defScrollPanes.get(_model
08150:                        .getActiveDocument());
08151:                if (scroll == null)
08152:                    throw new UnexpectedException(new Exception(
08153:                            "Current definitions scroll pane not found."));
08154:
08155:                JScrollBar oldbar = scroll.getVerticalScrollBar();
08156:                JScrollBar newbar = scroll.createVerticalScrollBar();
08157:                newbar.setMinimum(oldbar.getMinimum());
08158:                newbar.setMaximum(oldbar.getMaximum());
08159:                newbar.setValue(oldbar.getValue());
08160:                newbar.setVisibleAmount(oldbar.getVisibleAmount());
08161:                newbar.setEnabled(true);
08162:                newbar.revalidate();
08163:                scroll.setVerticalScrollBar(newbar);
08164:
08165:                // This needs to be repeated for the horizontal scrollbar
08166:                oldbar = scroll.getHorizontalScrollBar();
08167:                newbar = scroll.createHorizontalScrollBar();
08168:                newbar.setMinimum(oldbar.getMinimum());
08169:                newbar.setMaximum(oldbar.getMaximum());
08170:                newbar.setValue(oldbar.getValue());
08171:                newbar.setVisibleAmount(oldbar.getVisibleAmount());
08172:                newbar.setEnabled(true);
08173:                newbar.revalidate();
08174:                scroll.setHorizontalScrollBar(newbar);
08175:                scroll.revalidate();
08176:            }
08177:
08178:            /** Returns a JRadioButtonMenuItem that looks like a JCheckBoxMenuItem. This is a workaround for a known 
08179:             *  bug on OS X's version of Java. (See http://developer.apple.com/qa/qa2001/qa1154.html)
08180:             *  @param action Action for the menu item
08181:             *  @return JRadioButtonMenuItem with a checkbox icon
08182:             */
08183:            private JMenuItem _newCheckBoxMenuItem(Action action) {
08184:                String RADIO_ICON_KEY = "RadioButtonMenuItem.checkIcon";
08185:                String CHECK_ICON_KEY = "CheckBoxMenuItem.checkIcon";
08186:
08187:                // Store the default radio button icon to put back later
08188:                Object radioIcon = UIManager.get(RADIO_ICON_KEY);
08189:
08190:                // Replace radio button's checkIcon with that of JCheckBoxMenuItem
08191:                // so that our menu item looks like a checkbox
08192:                UIManager.put(RADIO_ICON_KEY, UIManager.get(CHECK_ICON_KEY));
08193:                JRadioButtonMenuItem pseudoCheckBox = new JRadioButtonMenuItem(
08194:                        action);
08195:
08196:                // Put original radio button checkIcon back.
08197:                UIManager.put(RADIO_ICON_KEY, radioIcon);
08198:
08199:                return pseudoCheckBox;
08200:            }
08201:
08202:            /** Gets the absolute file, or if necessary, the canonical file.
08203:             *  @param f the file for which to get the full path
08204:             *  @return the file representing the full path to the given file
08205:             */
08206:            private File _getFullFile(File f) throws IOException {
08207:                if (PlatformFactory.ONLY.isWindowsPlatform()
08208:                        && ((f.getAbsolutePath().indexOf("..") != -1)
08209:                                || (f.getAbsolutePath().indexOf("./") != -1) || (f
08210:                                .getAbsolutePath().indexOf(".\\") != -1))) {
08211:                    return f.getCanonicalFile();
08212:                }
08213:                return f.getAbsoluteFile();
08214:            }
08215:
08216:            /** Sets the current directory to be that of the given file. */
08217:            private void _setCurrentDirectory(File file) {
08218:                /* We want to use absolute paths whenever possible, since canonical paths resolve symbolic links and can be quite
08219:                 * long and unintuitive.  However, Windows blows up if you set the current directory of a JFileChooser to an 
08220:                 * absolute path with ".." in it.  In that case, we'll use the canonical path for the file chooser. (Fix for 
08221:                 * bug 707734)  Extended this to fix "./" and ".\" also (bug 774896)
08222:                 */
08223:                try {
08224:                    file = _getFullFile(file);
08225:                    _openChooser.setCurrentDirectory(file);
08226:                    _saveChooser.setCurrentDirectory(file);
08227:                    DrJava.getConfig().setSetting(LAST_DIRECTORY, file);
08228:                } catch (IOException ioe) {
08229:                    // If getCanonicalFile throws an IOException, we can't set the directory of the file chooser.  Oh well.
08230:                }
08231:            }
08232:
08233:            /** Sets the current directory to be that of document's file.   */
08234:            private void _setCurrentDirectory(OpenDefinitionsDocument doc) {
08235:                try {
08236:                    File file = doc.getFile();
08237:                    if (file != null)
08238:                        _setCurrentDirectory(file); // if no file, leave in current directory
08239:                } catch (FileMovedException fme) {
08240:                    // file was deleted, but try to go the directory
08241:                    _setCurrentDirectory(fme.getFile());
08242:                }
08243:            }
08244:
08245:            /** Sets the font of all panes and panels to the main font. */
08246:            private void _setMainFont() {
08247:
08248:                Font f = DrJava.getConfig().getSetting(FONT_MAIN);
08249:
08250:                for (JScrollPane scroll : _defScrollPanes.values()) {
08251:                    if (scroll != null) {
08252:                        DefinitionsPane pane = (DefinitionsPane) scroll
08253:                                .getViewport().getView();
08254:                        pane.setFont(f);
08255:                        // Update the font of the line enumeration rule
08256:                        if (DrJava.getConfig().getSetting(LINEENUM_ENABLED)
08257:                                .booleanValue()) {
08258:                            scroll.setRowHeaderView(new LineEnumRule(pane));
08259:                        }
08260:                    }
08261:                }
08262:
08263:                // Update Interactions Pane
08264:                _interactionsPane.setFont(f);
08265:                _interactionsController.setDefaultFont(f);
08266:
08267:                // Update Console Pane
08268:                _consolePane.setFont(f);
08269:                _consoleController.setDefaultFont(f);
08270:
08271:                _findReplace.setFieldFont(f);
08272:                _compilerErrorPanel.setListFont(f);
08273:                _junitErrorPanel.setListFont(f);
08274:                _javadocErrorPanel.setListFont(f);
08275:            }
08276:
08277:            /** Updates the text color for the doc list. */
08278:            private void _updateNormalColor() {
08279:                // Get the new value.
08280:                Color norm = DrJava.getConfig().getSetting(
08281:                        DEFINITIONS_NORMAL_COLOR);
08282:
08283:                // Change the text (foreground) color for the doc list.
08284:                _model.getDocCollectionWidget().setForeground(norm);
08285:
08286:                // We also need to immediately repaint the foremost scroll pane.
08287:                _repaintLineNums();
08288:            }
08289:
08290:            /** Updates the background color for the doc list. */
08291:            private void _updateBackgroundColor() {
08292:                // Get the new value.
08293:                Color back = DrJava.getConfig().getSetting(
08294:                        DEFINITIONS_BACKGROUND_COLOR);
08295:
08296:                // Change the background color for the doc list.
08297:                _model.getDocCollectionWidget().setBackground(back);
08298:
08299:                // We also need to immediately repaint the foremost scroll pane.
08300:                _repaintLineNums();
08301:            }
08302:
08303:            /** Updates the font and colors of the line number display. */
08304:            private void _updateLineNums() {
08305:                if (DrJava.getConfig().getSetting(LINEENUM_ENABLED)
08306:                        .booleanValue()) {
08307:
08308:                    // Update the font for all line number displays
08309:                    for (JScrollPane spane : _defScrollPanes.values()) {
08310:
08311:                        LineEnumRule ler = (LineEnumRule) spane.getRowHeader()
08312:                                .getView();
08313:                        ler.updateFont();
08314:                        ler.revalidate();
08315:                    }
08316:
08317:                    // We also need to immediately repaint the foremost scroll pane.
08318:                    _repaintLineNums();
08319:                }
08320:            }
08321:
08322:            /** Repaints the line numbers on the active scroll pane. */
08323:            private void _repaintLineNums() {
08324:                JScrollPane front = _defScrollPanes.get(_model
08325:                        .getActiveDocument());
08326:                if (front != null) {
08327:                    JViewport rhvport = front.getRowHeader();
08328:
08329:                    if (rhvport != null) {
08330:                        Component view = rhvport.getView();
08331:                        if (view != null) {
08332:                            view.repaint();
08333:                        }
08334:                    }
08335:                }
08336:            }
08337:
08338:            //  /** Revalidate the line numers, i.e. also redraw the ones not currently visible. */
08339:            //  public void revalidateLineNums() {
08340:            //    if (DrJava.getConfig().getSetting(LINEENUM_ENABLED).booleanValue()) {
08341:            //      JScrollPane sp = _defScrollPanes.get(_model.getActiveDocument());
08342:            //      if (sp!=null) {
08343:            //        LineEnumRule ler = (LineEnumRule)sp.getRowHeader().getView();
08344:            //        ler.revalidate();
08345:            //        _repaintLineNums();
08346:            //      }
08347:            //    }
08348:            //  }
08349:
08350:            /** Update the row header (line number enumeration) for the definitions scroll pane. */
08351:            private void _updateDefScrollRowHeader() {
08352:                boolean ruleEnabled = DrJava.getConfig().getSetting(
08353:                        LINEENUM_ENABLED).booleanValue();
08354:
08355:                for (JScrollPane scroll : _defScrollPanes.values()) {
08356:                    if (scroll != null) {
08357:                        DefinitionsPane pane = (DefinitionsPane) scroll
08358:                                .getViewport().getView();
08359:                        if (scroll.getRowHeader() == null
08360:                                || scroll.getRowHeader().getView() == null) {
08361:                            if (ruleEnabled)
08362:                                scroll.setRowHeaderView(new LineEnumRule(pane));
08363:                        } else if (!ruleEnabled)
08364:                            scroll.setRowHeaderView(null);
08365:                    }
08366:                }
08367:            }
08368:
08369:            /** Removes the current highlight. */
08370:            private void _removeThreadLocationHighlight() {
08371:                if (_currentThreadLocationHighlight != null) {
08372:                    _currentThreadLocationHighlight.remove();
08373:                    _currentThreadLocationHighlight = null;
08374:                }
08375:            }
08376:
08377:            /** Disable any step timer. */
08378:            private void _disableStepTimer() {
08379:                synchronized (_debugStepTimer) {
08380:                    if (_debugStepTimer.isRunning())
08381:                        _debugStepTimer.stop();
08382:                }
08383:            }
08384:
08385:            /** Checks if debugPanel's status bar displays the DEBUGGER_OUT_OF_SYNC message but the current document is 
08386:             *  in sync.  Clears the debugPanel's status bar in this case.  Does not assume that frame is in debug mode.
08387:             *  Must be executed in event thread.
08388:             */
08389:            private void _updateDebugStatus() {
08390:                if (!isDebuggerReady())
08391:                    return;
08392:
08393:                // if the document is untitled, don't show that it is out of sync since it can't be debugged anyway
08394:                if (_model.getActiveDocument().isUntitled()
08395:                        || _model.getActiveDocument().getClassFileInSync()) {
08396:                    // Hide message
08397:                    if (_debugPanel.getStatusText()
08398:                            .equals(DEBUGGER_OUT_OF_SYNC))
08399:                        _debugPanel.setStatusText("");
08400:                } else {
08401:                    // Show message
08402:                    if (_debugPanel.getStatusText().equals("")) {
08403:                        _debugPanel.setStatusText(DEBUGGER_OUT_OF_SYNC);
08404:                    }
08405:                }
08406:                _debugPanel.repaint(); // display the updated panel
08407:            }
08408:
08409:            /** Ensures that the interactions pane is not editable during an interaction. */
08410:            protected void _disableInteractionsPane() {
08411:                // Only change GUI from event-dispatching thread
08412:                Runnable command = new Runnable() {
08413:                    public void run() {
08414:                        _interactionsPane.setEditable(false);
08415:                        _interactionsPane.setCursor(Cursor
08416:                                .getPredefinedCursor(Cursor.WAIT_CURSOR));
08417:
08418:                        if (_interactionsScriptController != null)
08419:                            _interactionsScriptController.setActionsDisabled();
08420:                    }
08421:                };
08422:                Utilities.invokeLater(command);
08423:            }
08424:
08425:            /** Ensures that the interactions pane is editable after an interaction completes. */
08426:            protected void _enableInteractionsPane() {
08427:                // Only change GUI from event-dispatching thread
08428:                Runnable command = new Runnable() {
08429:                    public void run() {
08430:                        //         if (isDebuggerReady()) {
08431:                        //         _disableStepTimer();
08432:                        //         Debugger manager = _model.getDebugger();
08433:                        //         manager.clearCurrentStepRequest();
08434:                        //         _removeThreadLocationHighlight();
08435:                        //         }
08436:
08437:                        _interactionsPane.setCursor(Cursor
08438:                                .getPredefinedCursor(Cursor.TEXT_CURSOR));
08439:                        _interactionsPane.setEditable(true);
08440:                        _interactionsController.moveToEnd();
08441:                        if (_interactionsPane.hasFocus())
08442:                            _interactionsPane.getCaret().setVisible(true);
08443:                        if (_interactionsScriptController != null)
08444:                            _interactionsScriptController.setActionsEnabled();
08445:                    }
08446:                };
08447:                Utilities.invokeLater(command);
08448:            }
08449:
08450:            // Comment out current selection using wing commenting.  Non-private for testing purposes only. Only runs in event thread. */
08451:            void commentLines() {
08452:                // Delegate everything to the DefinitionsDocument.
08453:                OpenDefinitionsDocument openDoc = _model.getActiveDocument();
08454:                int caretPos = _currentDefPane.getCaretPosition();
08455:                openDoc.setCurrentLocation(caretPos);
08456:                int start = _currentDefPane.getSelectionStart();
08457:                int end = _currentDefPane.getSelectionEnd();
08458:                //    _currentDefPane.endCompoundEdit();
08459:                //    _currentDefPane.notifyInactive();
08460:                int newEnd = openDoc.commentLines(start, end);
08461:                //    _currentDefPane.notifyActive();
08462:                _currentDefPane.setCaretPosition(start + 2);
08463:                if (start != end)
08464:                    _currentDefPane.moveCaretPosition(newEnd);
08465:            }
08466:
08467:            // Uncomment out current selection using wing commenting.  Public for testing purposes only. Only runs in event thread. */
08468:            public void uncommentLines() {
08469:                // Delegate everything to the DefinitionsDocument.
08470:                OpenDefinitionsDocument openDoc = _model.getActiveDocument();
08471:                int caretPos = _currentDefPane.getCaretPosition();
08472:                openDoc.setCurrentLocation(caretPos);
08473:                int start = _currentDefPane.getSelectionStart();
08474:                int end = _currentDefPane.getSelectionEnd();
08475:                _currentDefPane.endCompoundEdit();
08476:
08477:                //notify inactive to prevent refreshing of the DefPane every time an insertion is made
08478:                //    _currentDefPane.notifyInactive();
08479:                openDoc.setCurrentLocation(start);
08480:                Position startPos;
08481:                try {
08482:                    startPos = openDoc.createUnwrappedPosition(start);
08483:                } catch (BadLocationException e) {
08484:                    throw new UnexpectedException(e);
08485:                }
08486:
08487:                int startOffset = startPos.getOffset();
08488:                final int newEnd = openDoc.uncommentLines(start, end);
08489:                //    _currentDefPane.notifyActive();
08490:                if (startOffset != startPos.getOffset())
08491:                    start -= 2;
08492:                final int f_start = start;
08493:                final boolean moveSelection = start != end;
08494:                Utilities.invokeAndWait(new Runnable() {
08495:                    public void run() {
08496:                        _currentDefPane.setCaretPosition(f_start);
08497:                        if (moveSelection)
08498:                            _currentDefPane.moveCaretPosition(newEnd);
08499:                    }
08500:                });
08501:            }
08502:
08503:            /** Blocks access to DrJava while the hourglass cursor is on. */
08504:            private static class GlassPane extends JComponent {
08505:
08506:                /** Creates a new GlassPane over the DrJava window. */
08507:                public GlassPane() {
08508:                    addKeyListener(new KeyAdapter() {
08509:                    });
08510:                    addMouseListener(new MouseAdapter() {
08511:                    });
08512:                    super .setCursor(Cursor
08513:                            .getPredefinedCursor(Cursor.WAIT_CURSOR));
08514:                }
08515:            }
08516:
08517:            /** Called when a specific document and offset should be displayed. Must be executed only in the event thread.
08518:             *  @param doc Document to display
08519:             *  @param offset Offset to display
08520:             *  @param shouldHighlight true iff the line should be highlighted.
08521:             */
08522:            public void scrollToDocumentAndOffset(
08523:                    final OpenDefinitionsDocument doc, final int offset,
08524:                    final boolean shouldHighlight) {
08525:                scrollToDocumentAndOffset(doc, offset, shouldHighlight, true);
08526:            }
08527:
08528:            /** Called when a specific document and offset should be displayed. Must be executed only in the event thread.
08529:             *  @param doc Document to display
08530:             *  @param offset Offset to display
08531:             *  @param shouldHighlight true iff the line should be highlighted.
08532:             *  @param shouldAddToHistory true if the location before and after the switch should be added to the browser history
08533:             */
08534:            public void scrollToDocumentAndOffset(
08535:                    final OpenDefinitionsDocument doc, final int offset,
08536:                    final boolean shouldHighlight,
08537:                    final boolean shouldAddToHistory) {
08538:                if (shouldAddToHistory)
08539:                    addToBrowserHistory();
08540:
08541:                boolean toSameDoc = _model.getActiveDocument().equals(doc);
08542:
08543:                if (!toSameDoc) {
08544:                    _model.setActiveDocument(doc);
08545:                    _findReplace.updateFirstDocInSearch();
08546:                } else
08547:                    _model.refreshActiveDocument();
08548:
08549:                Runnable command = new Runnable() {
08550:                    public void run() {
08551:                        // get the line number after the switch of documents was made
08552:                        int lineNumber = doc.getLineOfOffset(offset) + 1;
08553:
08554:                        // this block occurs if the documents is already open and as such has a positive size
08555:                        if (_currentDefPane.getSize().getWidth() > 0
08556:                                && _currentDefPane.getSize().getHeight() > 0) {
08557:                            _currentDefPane.centerViewOnOffset(offset);
08558:                            _currentDefPane.requestFocusInWindow();
08559:                        }
08560:
08561:                        if (shouldHighlight) {
08562:                            _removeThreadLocationHighlight();
08563:                            int startOffset = doc.getOffset(lineNumber); // Much faster to directly search back from offset!
08564:                            if (startOffset > -1) {
08565:                                int endOffset = doc.getLineEndPos(startOffset);
08566:                                if (endOffset > -1) {
08567:                                    _currentThreadLocationHighlight = _currentDefPane
08568:                                            .getHighlightManager()
08569:                                            .addHighlight(
08570:                                                    startOffset,
08571:                                                    endOffset,
08572:                                                    DefinitionsPane.THREAD_PAINTER);
08573:                                }
08574:                            }
08575:                        }
08576:
08577:                        if (_showDebugger) {
08578:                            // Give the interactions pane focus so we can debug
08579:                            _interactionsPane.requestFocusInWindow();
08580:                            //          System.err.println("Showing Interactions Tab" );
08581:                            showTab(_interactionsPane);
08582:                            _updateDebugStatus();
08583:                        }
08584:
08585:                        //        if (shouldAddToHistory) { addToBrowserHistory(); }    
08586:                    }
08587:                };
08588:
08589:                /* Comment by mgricken: If ! toSameDoc, the _currentDefPane hasn't been created yet for a new document.   
08590:                 * Consequently, we need to use EventQueue.invokeLater if ! toSameDoc. */
08591:                /* if (toSameDoc) Utilities.invokeLater(command);  
08592:                else */EventQueue.invokeLater(command);
08593:            }
08594:
08595:            /** Listens to events from the debugger. */
08596:            private class UIDebugListener implements  DebugListener {
08597:                /* Must be executed in evevt thread.*/
08598:                public void debuggerStarted() {
08599:                    showDebugger();
08600:                }
08601:
08602:                /* Must be executed in evevt thread.*/
08603:                public void debuggerShutdown() {
08604:                    _disableStepTimer();
08605:
08606:                    hideDebugger();
08607:                    _removeThreadLocationHighlight();
08608:                }
08609:
08610:                /** Called when a step is requested on the current thread.  Must be executed in event thread. */
08611:                public void stepRequested() {
08612:                    // Print a message if step takes a long time
08613:                    synchronized (_debugStepTimer) {
08614:                        if (!_debugStepTimer.isRunning())
08615:                            _debugStepTimer.start();
08616:                    }
08617:                }
08618:
08619:                public void currThreadSuspended() {
08620:                    _disableStepTimer();
08621:
08622:                    // Only change GUI from event-dispatching thread
08623:                    Runnable command = new Runnable() {
08624:                        public void run() {
08625:                            _setThreadDependentDebugMenuItems(true);
08626:                        }
08627:                    };
08628:                    Utilities.invokeLater(command);
08629:                }
08630:
08631:                /* Must be executed in the event thread. */
08632:                public void currThreadResumed() {
08633:                    _setThreadDependentDebugMenuItems(false);
08634:                    _removeThreadLocationHighlight();
08635:                }
08636:
08637:                /** Called when the given line is reached by the current thread in the debugger, to request that the line be 
08638:                 *  displayed.  Must be executed only in the event thread.
08639:                 *  @param doc Document to display
08640:                 *  @param lineNumber Line to display or highlight
08641:                 *  @param shouldHighlight true iff the line should be highlighted.
08642:                 */
08643:                public void threadLocationUpdated(OpenDefinitionsDocument doc,
08644:                        int lineNumber, boolean shouldHighlight) {
08645:                    scrollToDocumentAndOffset(doc, doc.getOffset(lineNumber),
08646:                            shouldHighlight);
08647:                }
08648:
08649:                /* Must be executed in event thread. */
08650:                public void currThreadDied() {
08651:                    assert EventQueue.isDispatchThread();
08652:                    _disableStepTimer();
08653:
08654:                    if (isDebuggerReady()) {
08655:                        try {
08656:                            if (!_model.getDebugger().hasSuspendedThreads()) {
08657:                                // no more suspended threads, resume default debugger state
08658:                                // all thread dependent debug menu items are disabled
08659:                                _setThreadDependentDebugMenuItems(false);
08660:                                _removeThreadLocationHighlight();
08661:                                // Make sure we're at the prompt
08662:                                // (This should really be fixed in InteractionsController, not here.)
08663:                                _interactionsController.moveToPrompt(); // there are no suspended threads, bring back prompt
08664:                            }
08665:                        } catch (DebugException de) {
08666:                            _showError(de, "Debugger Error",
08667:                                    "Error with a thread in the debugger.");
08668:                        }
08669:                    }
08670:                }
08671:
08672:                public void currThreadSet(DebugThreadData dtd) {
08673:                }
08674:
08675:                public void regionAdded(final Breakpoint bp, int index) {
08676:                }
08677:
08678:                public void breakpointReached(Breakpoint bp) {
08679:                }
08680:
08681:                public void regionChanged(Breakpoint bp, int index) {
08682:                }
08683:
08684:                public void regionRemoved(final Breakpoint bp) {
08685:                }
08686:
08687:                public void watchSet(final DebugWatchData w) {
08688:                }
08689:
08690:                public void watchRemoved(final DebugWatchData w) {
08691:                }
08692:
08693:                public void threadStarted() {
08694:                }
08695:
08696:                public void nonCurrThreadDied() {
08697:                }
08698:            }
08699:
08700:            /** @author jlugo */
08701:            private class DJAsyncTaskLauncher extends AsyncTaskLauncher {
08702:
08703:                protected boolean shouldSetEnabled() {
08704:                    return true;
08705:                }
08706:
08707:                protected void setParentContainerEnabled(boolean enabled) {
08708:                    if (enabled)
08709:                        hourglassOff();
08710:                    else
08711:                        hourglassOn();
08712:                }
08713:
08714:                protected IAsyncProgress createProgressMonitor(
08715:                        final String description, final int min, final int max) {
08716:                    return new IAsyncProgress() {
08717:                        private ProgressMonitor _monitor = new ProgressMonitor(
08718:                                MainFrame.this , description, "", min, max);
08719:
08720:                        public void close() {
08721:                            _monitor.close();
08722:                        }
08723:
08724:                        public int getMaximum() {
08725:                            return _monitor.getMaximum();
08726:                        }
08727:
08728:                        public int getMillisToDecideToPopup() {
08729:                            return _monitor.getMillisToDecideToPopup();
08730:                        }
08731:
08732:                        public int getMillisToPopup() {
08733:                            return _monitor.getMillisToPopup();
08734:                        }
08735:
08736:                        public int getMinimum() {
08737:                            return _monitor.getMinimum();
08738:                        }
08739:
08740:                        public String getNote() {
08741:                            return _monitor.getNote();
08742:                        }
08743:
08744:                        public boolean isCanceled() {
08745:                            return _monitor.isCanceled();
08746:                        }
08747:
08748:                        public void setMaximum(int m) {
08749:                            _monitor.setMaximum(m);
08750:                        }
08751:
08752:                        public void setMinimum(int m) {
08753:                            _monitor.setMinimum(m);
08754:                        }
08755:
08756:                        public void setNote(String note) {
08757:                            _monitor.setNote(note);
08758:                        }
08759:
08760:                        public void setProgress(int nv) {
08761:                            _monitor.setProgress(nv);
08762:                        }
08763:                    };
08764:                }
08765:            }
08766:
08767:            /** Inner class to listen to all events in the model. */
08768:            private class ModelListener implements  GlobalModelListener {
08769:
08770:                public <P, R> void executeAsyncTask(AsyncTask<P, R> task,
08771:                        P param, boolean showProgress, boolean lockUI) {
08772:                    new DJAsyncTaskLauncher().executeTask(task, param,
08773:                            showProgress, lockUI);
08774:                }
08775:
08776:                public void handleAlreadyOpenDocument(
08777:                        OpenDefinitionsDocument doc) {
08778:                    //     boolean docChanged = !doc.equals(_model.getActiveDocument());
08779:                    //     if (docChanged) { addToBrowserHistory(); }
08780:
08781:                    // Always switch to doc
08782:                    _model.setActiveDocument(doc);
08783:
08784:                    //     // defer executing this code until after active document switch (if any) is complete
08785:                    //     EventQueue.invokeLater(new Runnable() { public void run() { addToBrowserHistory(); } });
08786:
08787:                    // Prompt to revert if modified
08788:                    if (doc.isModifiedSinceSave()) {
08789:                        String title = "Revert to Saved?";
08790:                        String message = doc.getFileName()
08791:                                + " is already open and modified.\n"
08792:                                + "Would you like to revert to the version on disk?\n";
08793:                        int choice = JOptionPane.showConfirmDialog(
08794:                                MainFrame.this , message, title,
08795:                                JOptionPane.YES_NO_OPTION);
08796:                        if (choice == JOptionPane.YES_OPTION) {
08797:                            _revert(doc);
08798:                        }
08799:                    }
08800:                }
08801:
08802:                public void newFileCreated(final OpenDefinitionsDocument doc) {
08803:                    Utilities.invokeLater(new Runnable() {
08804:                        public void run() {
08805:                            _createDefScrollPane(doc);
08806:                        }
08807:                    });
08808:                }
08809:
08810:                private volatile int _fnfCount = 0;
08811:
08812:                private boolean resetFNFCount() {
08813:                    return _fnfCount == 0;
08814:                }
08815:
08816:                private boolean someFilesNotFound() {
08817:                    return _fnfCount > 0;
08818:                }
08819:
08820:                public void filesNotFound(File... files) {
08821:                    if (files.length == 0)
08822:                        return;
08823:                    _fnfCount += files.length;
08824:
08825:                    if (files.length == 1) {
08826:                        JOptionPane
08827:                                .showMessageDialog(
08828:                                        MainFrame.this ,
08829:                                        "The following file could not be found and has been removed from the project.\n"
08830:                                                + files[0].getPath(),
08831:                                        "File Not Found",
08832:                                        JOptionPane.ERROR_MESSAGE);
08833:                    } else {
08834:                        final Collection<String> filePaths = new ArrayList<String>();
08835:                        for (File f : files) {
08836:                            filePaths.add(f.getPath());
08837:                        }
08838:
08839:                        ScrollableListDialog dialog = new ScrollableListDialog(
08840:                                MainFrame.this ,
08841:                                "Files Not Found",
08842:                                "The following files could not be found and have been removed from the project.",
08843:                                filePaths, JOptionPane.ERROR_MESSAGE);
08844:
08845:                        setPopupLoc(dialog);
08846:                        dialog.showDialog();
08847:                    }
08848:                }
08849:
08850:                public void fileSaved(final OpenDefinitionsDocument doc) {
08851:                    //      new ScrollableDialog(null, "fileSaved called in ModelListener", "", "").show();
08852:                    Utilities.invokeLater(new Runnable() {
08853:                        public void run() {
08854:                            doc.documentSaved(); // used to update the document cache
08855:                            _saveAction.setEnabled(false);
08856:                            _renameAction.setEnabled(true);
08857:                            _revertAction.setEnabled(true);
08858:                            updateStatusField();
08859:                            _currentDefPane.requestFocusInWindow();
08860:                            try {
08861:                                File f = doc.getFile();
08862:                                if (!_model.inProject(f))
08863:                                    _recentFileManager.updateOpenFiles(f);
08864:                            } catch (FileMovedException fme) {
08865:                                File f = fme.getFile();
08866:                                // Recover, show it in the list anyway
08867:                                if (!_model.inProject(f))
08868:                                    _recentFileManager.updateOpenFiles(f);
08869:                            }
08870:                            // Check class file sync status, in case file was renamed
08871:                            _updateDebugStatus();
08872:                        }
08873:                    });
08874:                }
08875:
08876:                public void fileOpened(final OpenDefinitionsDocument doc) {
08877:                    Utilities.invokeLater(new Runnable() {
08878:                        public void run() {
08879:                            _fileOpened(doc);
08880:                        }
08881:                    });
08882:                }
08883:
08884:                private void _fileOpened(final OpenDefinitionsDocument doc) {
08885:                    try {
08886:                        File f = doc.getFile();
08887:                        if (!_model.inProject(f)) {
08888:                            _recentFileManager.updateOpenFiles(f);
08889:
08890:                        }
08891:                    } catch (FileMovedException fme) {
08892:                        File f = fme.getFile();
08893:                        // Recover, show it in the list anyway
08894:                        if (!_model.inProject(f))
08895:                            _recentFileManager.updateOpenFiles(f);
08896:                    }
08897:                }
08898:
08899:                /** NOTE: Makes certain that this action occurs in the event dispatching thread */
08900:                public void fileClosed(final OpenDefinitionsDocument doc) {
08901:                    Utilities.invokeLater(new Runnable() {
08902:                        public void run() {
08903:                            _fileClosed(doc);
08904:                        }
08905:                    });
08906:                }
08907:
08908:                /** Does the work of closing a file */
08909:                private void _fileClosed(OpenDefinitionsDocument doc) {
08910:                    _recentDocFrame.closeDocument(doc);
08911:                    _removeErrorListener(doc);
08912:                    JScrollPane jsp = _defScrollPanes.get(doc);
08913:                    if (jsp != null) {
08914:                        ((DefinitionsPane) jsp.getViewport().getView()).close();
08915:                        _defScrollPanes.remove(doc);
08916:                    }
08917:                }
08918:
08919:                public void fileReverted(OpenDefinitionsDocument doc) {
08920:                    Utilities.invokeLater(new Runnable() {
08921:                        public void run() {
08922:                            updateStatusField();
08923:                            _saveAction.setEnabled(false);
08924:                            _currentDefPane.resetUndo();
08925:                            _currentDefPane.hasWarnedAboutModified(false);
08926:                            _currentDefPane.setPositionAndScroll(0);
08927:                            _updateDebugStatus();
08928:                        }
08929:                    });
08930:                }
08931:
08932:                public void undoableEditHappened() {
08933:                    Utilities.invokeLater(new Runnable() {
08934:                        public void run() {
08935:                            _currentDefPane.getUndoAction().updateUndoState();
08936:                            _currentDefPane.getRedoAction().updateRedoState();
08937:                        }
08938:                    });
08939:                }
08940:
08941:                public void activeDocumentRefreshed(
08942:                        final OpenDefinitionsDocument active) {
08943:                    Utilities.invokeLater(new Runnable() {
08944:                        public void run() {
08945:                            //          System.err.println("activeDocumentRefreshed");
08946:                            _recentDocFrame.pokeDocument(active);
08947:                            _refreshDefScrollPane();
08948:
08949:                            // Update error highlights
08950:                            int pos = _currentDefPane.getCaretPosition();
08951:                            _currentDefPane.getErrorCaretListener()
08952:                                    .updateHighlight(pos);
08953:                            focusOnLastFocusOwner();
08954:                        }
08955:                    });
08956:                }
08957:
08958:                public void activeDocumentChanged(
08959:                        final OpenDefinitionsDocument active) {
08960:                    //      Utilities.show("MainFrame Listener: ActiveDocument changed to " + active);
08961:                    // code that accesses the GUI must run in the event-dispatching thread. 
08962:                    Utilities.invokeLater(new Runnable() { // invokeAndWait can create occasional deadlocks.
08963:                                public void run() {
08964:                                    _recentDocFrame.pokeDocument(active);
08965:                                    _switchDefScrollPane();
08966:
08967:                                    boolean isModified = active
08968:                                            .isModifiedSinceSave();
08969:                                    boolean canCompile = (!isModified && !active
08970:                                            .isUntitled());
08971:                                    boolean hasName = !active.isUntitled();
08972:                                    _saveAction.setEnabled(!canCompile);
08973:                                    _renameAction.setEnabled(hasName);
08974:                                    _revertAction.setEnabled(hasName);
08975:
08976:                                    // Update error highlights
08977:                                    int pos = _currentDefPane
08978:                                            .getCaretPosition();
08979:                                    _currentDefPane.getErrorCaretListener()
08980:                                            .updateHighlight(pos);
08981:
08982:                                    // Update FileChoosers' directory
08983:                                    _setCurrentDirectory(active);
08984:
08985:                                    // Update title and position
08986:                                    updateStatusField();
08987:                                    _posListener.updateLocation();
08988:
08989:                                    // update display (adding "*") in navigatgorPane
08990:                                    if (isModified)
08991:                                        _model.getDocumentNavigator().repaint();
08992:
08993:                                    try {
08994:                                        active.revertIfModifiedOnDisk();
08995:                                    } catch (FileMovedException fme) {
08996:                                        _showFileMovedError(fme);
08997:                                    } catch (IOException e) {
08998:                                        _showIOError(e);
08999:                                    }
09000:
09001:                                    // Change Find/Replace to the new defpane
09002:                                    if (_findReplace.isDisplayed()) {
09003:                                        _findReplace.stopListening();
09004:                                        _findReplace
09005:                                                .beginListeningTo(_currentDefPane);
09006:                                        //uninstallFindReplaceDialog(_findReplace);
09007:                                        //installFindReplaceDialog(_findReplace);
09008:                                    }
09009:                                    //          _lastFocusOwner = _currentDefPane;
09010:                                    EventQueue.invokeLater(new Runnable() {
09011:                                        public void run() {
09012:                                            _lastFocusOwner = _currentDefPane;
09013:                                            //            System.err.println("Requesting focus on new active document");
09014:                                            _currentDefPane
09015:                                                    .requestFocusInWindow();
09016:                                        }
09017:                                    });
09018:                                }
09019:                            });
09020:                }
09021:
09022:                public void focusOnLastFocusOwner() {
09023:                    //      System.err.println("focusOnLastFocusOwner() called; _lastFocusOwner = " + _lastFocusOwner);
09024:                    _lastFocusOwner.requestFocusInWindow();
09025:                }
09026:
09027:                /** Moves focus in MainFrame to teh definitions pane. */
09028:                public void focusOnDefinitionsPane() {
09029:                    _currentDefPane.requestFocusInWindow();
09030:                }
09031:
09032:                public void interactionStarted() {
09033:                    Utilities.invokeLater(new Runnable() {
09034:                        public void run() {
09035:                            _disableInteractionsPane();
09036:                            _runAction.setEnabled(false);
09037:                            _runProjectAction.setEnabled(false);
09038:                        }
09039:                    });
09040:                }
09041:
09042:                public void interactionEnded() {
09043:                    InteractionsModel im = _model.getInteractionsModel();
09044:                    edu.rice.cs.plt.tuple.Pair<String, String> lastError = im
09045:                            .getLastError();
09046:                    if (DrJava
09047:                            .getConfig()
09048:                            .getSetting(
09049:                                    edu.rice.cs.drjava.config.OptionConstants.DIALOG_AUTOIMPORT_ENABLED)) {
09050:                        if (lastError != null) {
09051:                            // the interaction ended and there was an error
09052:                            String exceptionClass = lastError.first();
09053:                            String message = lastError.second();
09054:                            edu.rice.cs.plt.tuple.Pair<String, String> secondToLastError = im
09055:                                    .getSecondToLastError();
09056:                            if ((secondToLastError == null) || // either there was no 2nd to last error
09057:                                    (!secondToLastError.first().equals(
09058:                                            exceptionClass)) || // or it is different
09059:                                    (!secondToLastError.second()
09060:                                            .equals(message))) {
09061:                                // this aborts the auto-importing if the same class comes up twice in a row
09062:                                if ("koala.dynamicjava.interpreter.error.ExecutionError"
09063:                                        .equals(exceptionClass)
09064:                                        && message != null
09065:                                        && message
09066:                                                .startsWith("Undefined class '")
09067:                                        && message.endsWith("'")) {
09068:                                    // it was an "undefined class" exception
09069:                                    // show auto-import dialog
09070:                                    String undefinedClassName = message
09071:                                            .substring(
09072:                                                    message.indexOf('\'') + 1,
09073:                                                    message.lastIndexOf('\''));
09074:                                    _showAutoImportDialog(undefinedClassName);
09075:                                }
09076:                            }
09077:                        }
09078:                    } else {
09079:                        // reset the last errors, so the dialog works again if it is re-enabled
09080:                        im.resetLastErrors();
09081:                    }
09082:
09083:                    Utilities.invokeLater(new Runnable() {
09084:                        public void run() {
09085:                            _enableInteractionsPane();
09086:                            _runAction.setEnabled(true);
09087:                            _runProjectAction.setEnabled(_model
09088:                                    .isProjectActive());
09089:                        }
09090:                    });
09091:                }
09092:
09093:                public void interactionErrorOccurred(final int offset,
09094:                        final int length) {
09095:                    Utilities.invokeLater(new Runnable() {
09096:                        public void run() {
09097:                            _interactionsPane.highlightError(offset, length);
09098:                        }
09099:                    });
09100:                }
09101:
09102:                /** Called when the active interpreter is changed.
09103:                 *  @param inProgress Whether the new interpreter is currently in progress
09104:                 *         with an interaction (ie. whether an interactionEnded event will be fired)
09105:                 */
09106:                public void interpreterChanged(final boolean inProgress) {
09107:                    Utilities.invokeLater(new Runnable() {
09108:                        public void run() {
09109:                            _runAction.setEnabled(!inProgress);
09110:                            _runProjectAction.setEnabled(!inProgress);
09111:                            if (inProgress)
09112:                                _disableInteractionsPane();
09113:                            else
09114:                                _enableInteractionsPane();
09115:                        }
09116:                    });
09117:                }
09118:
09119:                public void compileStarted() {
09120:                    // Only change GUI from event-dispatching thread
09121:                    Utilities.invokeLater(new Runnable() {
09122:                        public void run() {
09123:                            //          hourglassOn();
09124:                            showTab(_compilerErrorPanel);
09125:                            _compilerErrorPanel.setCompilationInProgress();
09126:                            _saveAction.setEnabled(false);
09127:                        }
09128:                    });
09129:                }
09130:
09131:                public void compileEnded(File workDir,
09132:                        final List<? extends File> excludedFiles) {
09133:                    // Only change GUI from event-dispatching thread
09134:                    Utilities.invokeLater(new Runnable() {
09135:                        public void run() {
09136:                            //          try {
09137:                            _compilerErrorPanel.reset(excludedFiles
09138:                                    .toArray(new File[0]));
09139:                            if (isDebuggerReady()) {
09140:                                //              _model.getActiveDocument().checkIfClassFileInSync();
09141:
09142:                                _updateDebugStatus();
09143:                            }
09144:                            //          }
09145:                            //          finally { hourglassOff(); }
09146:                            if ((DrJava.getConfig().getSetting(
09147:                                    DIALOG_COMPLETE_SCAN_CLASS_FILES)
09148:                                    .booleanValue())
09149:                                    && (_model.getBuildDirectory() != null)) {
09150:                                _scanClassFiles();
09151:                            }
09152:                            _model.refreshActiveDocument();
09153:                        }
09154:                    });
09155:                }
09156:
09157:                public void runStarted(final OpenDefinitionsDocument doc) {
09158:                    // Only change GUI from event-dispatching thread
09159:                    Utilities.invokeLater(new Runnable() {
09160:                        public void run() {
09161:                            // Switch to the interactions pane to show results.
09162:                            showTab(_interactionsPane);
09163:                        }
09164:                    });
09165:                }
09166:
09167:                public void junitStarted() {
09168:                    /* Note: simpleHourglassOn() is done by various junit commands (other than junitClasses); hourglass must be off 
09169:                     * for actual testing; the balancing simpleHourglassOff() is located here and in nonTestCase */
09170:
09171:                    // Only change GUI from event-dispatching thread
09172:                    //      new ScrollableDialog(null, "junitStarted(" + docs + ") called in MainFrame", "", "").show();
09173:                    Utilities.invokeLater(new Runnable() {
09174:                        public void run() {
09175:                            // new ScrollableDialog(null, "Ready for hourglassOn in junitStarted", "", "").show();
09176:
09177:                            try {
09178:                                showTab(_junitErrorPanel);
09179:                                _junitErrorPanel.setJUnitInProgress();
09180:                                // _junitAction.setEnabled(false);
09181:                                // _junitAllAction.setEnabled(false);
09182:                            } finally {
09183:                                hourglassOff();
09184:                            }
09185:                        }
09186:                    });
09187:                }
09188:
09189:                /** We are junit'ing a specific list of classes given their source files. */
09190:                public void junitClassesStarted() {
09191:                    // Only change GUI from event-dispatching thread
09192:                    // new ScrollableDialog(null, "junitClassesStarted called in MainFrame", "", "").show();
09193:                    Utilities.invokeLater(new Runnable() {
09194:                        public void run() {
09195:                            //          new ScrollableDialog(null, "Ready for hourglassOn in junitClassesStarted", "", "").show();
09196:                            //          hourglassOn();
09197:                            showTab(_junitErrorPanel);
09198:                            _junitErrorPanel.setJUnitInProgress();
09199:                            // _junitAction.setEnabled(false);
09200:                            // _junitAllAction.setEnabled(false);
09201:                        } // no hourglassOff here because junitClasses does not perform hourglassOn
09202:                    });
09203:                }
09204:
09205:                //public void junitRunning() { }
09206:
09207:                public void junitSuiteStarted(final int numTests) {
09208:                    Utilities.invokeLater(new Runnable() {
09209:                        public void run() {
09210:                            _junitErrorPanel.progressReset(numTests);
09211:                        }
09212:                    });
09213:                }
09214:
09215:                public void junitTestStarted(final String name) {
09216:                    Utilities.invokeLater(new Runnable() {
09217:                        public void run() {
09218:                            _junitErrorPanel.getErrorListPane().testStarted(
09219:                                    name); /* this does nothing! */
09220:                        }
09221:                    });
09222:                }
09223:
09224:                public void junitTestEnded(final String name,
09225:                        final boolean succeeded, final boolean causedError) {
09226:                    //      new ScrollableDialog(null, "junitTestEnded(" + name + ", " + succeeded + ", " + causedError + ")", "", "").show();
09227:                    // syncUI...?
09228:                    Utilities.invokeLater(new Runnable() {
09229:                        public void run() {
09230:                            _junitErrorPanel.getErrorListPane().testEnded(name,
09231:                                    succeeded, causedError); // this does nothing!
09232:                            _junitErrorPanel.progressStep(succeeded);
09233:                            _model.refreshActiveDocument();
09234:                        }
09235:                    });
09236:                }
09237:
09238:                public void junitEnded() {
09239:                    // Only change GUI from event-dispatching thread
09240:                    //      new ScrollableDialog(null, "MainFrame.junitEnded() called", "", "").show();
09241:                    Utilities.invokeLater(new Runnable() {
09242:                        public void run() {
09243:                            try {
09244:                                _restoreJUnitActionsEnabled();
09245:                                _junitErrorPanel.reset();
09246:                                _model.refreshActiveDocument();
09247:                            } finally {
09248:                                //            new ScrollableDialog(null, "MainFrame.junitEnded() ready to return", "", "").show();
09249:                                //            hourglassOff(); 
09250:                            }
09251:                        }
09252:                    });
09253:                }
09254:
09255:                /** Fire just before javadoc asynchronous thread is started. Only runs in the event thread. */
09256:                public void javadocStarted() {
09257:
09258:                    assert EventQueue.isDispatchThread();
09259:
09260:                    //      // Only change GUI from event-dispatching thread
09261:                    //      Runnable command = new Runnable() {
09262:                    //        public void run() {
09263:                    //          // if we don't lock edits, our error highlighting might break
09264:                    hourglassOn();
09265:
09266:                    showTab(_javadocErrorPanel);
09267:                    _javadocErrorPanel.setJavadocInProgress();
09268:                    _javadocAllAction.setEnabled(false);
09269:                    _javadocCurrentAction.setEnabled(false);
09270:                    //        }
09271:                    //      };
09272:                    //      Utilities.invokeLater(command);
09273:                }
09274:
09275:                public void javadocEnded(final boolean success,
09276:                        final File destDir, final boolean allDocs) {
09277:                    // Only change GUI from event-dispatching thread
09278:                    Runnable command = new Runnable() {
09279:                        public void run() {
09280:                            try {
09281:                                showTab(_javadocErrorPanel);
09282:                                _javadocAllAction.setEnabled(true);
09283:                                _javadocCurrentAction.setEnabled(true);
09284:                                _javadocErrorPanel.reset();
09285:                                _model.refreshActiveDocument();
09286:                            } finally {
09287:                                hourglassOff();
09288:                            }
09289:
09290:                            // Display the results.
09291:                            if (success) {
09292:                                String className;
09293:                                try {
09294:                                    className = _model.getActiveDocument()
09295:                                            .getQualifiedClassName();
09296:                                    className = className.replace('.',
09297:                                            File.separatorChar);
09298:                                } catch (ClassNameNotFoundException cnf) {
09299:                                    // If there is no class name, pass the empty string as a flag.
09300:                                    // We don't want to blow up here.
09301:                                    className = "";
09302:                                }
09303:                                try {
09304:                                    String fileName = (allDocs || className
09305:                                            .equals("")) ? "index.html"
09306:                                            : (className + ".html");
09307:                                    File index = new File(destDir, fileName);
09308:                                    URL address = FileOps.toURL(index
09309:                                            .getAbsoluteFile());
09310:
09311:                                    if (!PlatformFactory.ONLY.openURL(address)) {
09312:                                        JavadocFrame _javadocFrame = new JavadocFrame(
09313:                                                destDir, className, allDocs);
09314:                                        _javadocFrame.setVisible(true);
09315:                                    }
09316:                                } catch (MalformedURLException me) {
09317:                                    throw new UnexpectedException(me);
09318:                                } catch (IllegalStateException ise) {
09319:                                    // JavadocFrame couldn't find any output files!
09320:                                    // Display a message.
09321:                                    String msg = "Javadoc completed successfully, but did not produce any HTML files.\n"
09322:                                            + "Please ensure that your access level in Preferences is appropriate.";
09323:                                    JOptionPane.showMessageDialog(
09324:                                            MainFrame.this , msg,
09325:                                            "No output to display.",
09326:                                            JOptionPane.INFORMATION_MESSAGE);
09327:                                }
09328:                            }
09329:                        }
09330:                    };
09331:                    Utilities.invokeLater(command);
09332:                }
09333:
09334:                public void interpreterExited(final int status) {
09335:                    // Only show prompt if option is set and not in TEST_MODE
09336:                    if (DrJava.getConfig().getSetting(INTERACTIONS_EXIT_PROMPT)
09337:                            .booleanValue()
09338:                            && !Utilities.TEST_MODE
09339:                            && MainFrame.this .isVisible()) {
09340:                        // Synchronously pop up a dialog box concerning restarting the JVM.
09341:                        Utilities.invokeAndWait(new Runnable() {
09342:                            public void run() {
09343:                                String msg = "The interactions window was terminated by a call "
09344:                                        + "to System.exit("
09345:                                        + status
09346:                                        + ").\n"
09347:                                        + "The interactions window will now be restarted.";
09348:
09349:                                String title = "Interactions terminated by System.exit("
09350:                                        + status + ")";
09351:
09352:                                ConfirmCheckBoxDialog dialog = new ConfirmCheckBoxDialog(
09353:                                        MainFrame.this , title, msg,
09354:                                        "Do not show this message again",
09355:                                        JOptionPane.INFORMATION_MESSAGE,
09356:                                        JOptionPane.DEFAULT_OPTION);
09357:                                if (dialog.show() == JOptionPane.OK_OPTION
09358:                                        && dialog.getCheckBoxValue()) {
09359:                                    DrJava.getConfig().setSetting(
09360:                                            INTERACTIONS_EXIT_PROMPT,
09361:                                            Boolean.FALSE);
09362:                                }
09363:                            }
09364:                        });
09365:                    }
09366:                }
09367:
09368:                public void interpreterResetFailed(Throwable t) {
09369:                    interpreterReady(FileOption.NULL_FILE);
09370:                }
09371:
09372:                public void interpreterResetting() {
09373:                    // Only change GUI from event-dispatching thread
09374:                    Runnable command = new Runnable() {
09375:                        public void run() {
09376:                            Debugger dm = _model.getDebugger();
09377:                            //          if (dm.isAvailable() && dm.isReady()) dm.shutdown();
09378:                            //          _resetInteractionsAction.setEnabled(false);
09379:                            _junitAction.setEnabled(false);
09380:                            _junitAllAction.setEnabled(false);
09381:                            _junitProjectAction.setEnabled(false);
09382:                            _runAction.setEnabled(false);
09383:                            _runProjectAction.setEnabled(false);
09384:                            _closeInteractionsScript();
09385:                            _interactionsPane.setEditable(false);
09386:                            _interactionsPane.setCursor(Cursor
09387:                                    .getPredefinedCursor(Cursor.WAIT_CURSOR));
09388:                            if (_showDebugger)
09389:                                _toggleDebuggerAction.setEnabled(false);
09390:                        }
09391:                    };
09392:                    Utilities.invokeLater(command);
09393:                }
09394:
09395:                public void interpreterReady(File wd) {
09396:                    // Only change GUI from event-dispatching thread
09397:                    Runnable command = new Runnable() {
09398:                        public void run() {
09399:                            interactionEnded();
09400:                            _runAction.setEnabled(true);
09401:                            _runProjectAction.setEnabled(_model
09402:                                    .isProjectActive());
09403:                            _junitAction.setEnabled(true);
09404:                            _junitAllAction.setEnabled(true);
09405:                            _junitProjectAction.setEnabled(_model
09406:                                    .isProjectActive());
09407:                            // This action should not be enabled until the slave JVM is used          
09408:                            //          _resetInteractionsAction.setEnabled(true);
09409:                            if (_showDebugger) {
09410:                                _toggleDebuggerAction.setEnabled(true);
09411:                            }
09412:                            //           Moved this line here from interpreterResetting since
09413:                            //           it was possible to get an InputBox in InteractionsController
09414:                            //           between interpreterResetting and interpreterReady.
09415:                            //           Fixes bug #917054 "Interactions Reset Bug".
09416:                            _interactionsController.interruptConsoleInput();
09417:                        }
09418:                    };
09419:                    Utilities.invokeLater(command);
09420:                }
09421:
09422:                public void slaveJVMUsed() { /* _resetInteractionsAction.setEnabled(true);  */
09423:                }
09424:
09425:                public void consoleReset() {
09426:                }
09427:
09428:                public void saveBeforeCompile() {
09429:                    // The following event thread switch supports legacy test code that calls compile methods outside of the
09430:                    // event thread.  The wait is necessary because compilation process cannot proceed until saving is complete.
09431:                    Utilities.invokeAndWait(new Runnable() {
09432:                        public void run() {
09433:                            _saveAllBeforeProceeding(
09434:                                    "To compile, you must first save ALL modified files.\n"
09435:                                            + "Would you like to save and then compile?",
09436:                                    ALWAYS_SAVE_BEFORE_COMPILE,
09437:                                    "Always save before compiling");
09438:                        }
09439:                    });
09440:                }
09441:
09442:                /** Compile all open source files if this option is configured or running as a unit test.  Otherwise, pop up a
09443:                 * dialog to ask if all open source files should be compiled in order to test the program. 
09444:                 */
09445:                public void compileBeforeJUnit(
09446:                        final CompilerListener testAfterCompile) {
09447:                    //      System.err.println("in compileBeforeJUnit, TEST_MODE = " + Utilities.TEST_MODE);
09448:                    if (DrJava.getConfig().getSetting(
09449:                            ALWAYS_COMPILE_BEFORE_JUNIT).booleanValue()
09450:                            || Utilities.TEST_MODE) {
09451:                        // Compile all open source files
09452:                        _model.getCompilerModel().addListener(testAfterCompile); // listener removes itself
09453:                        _compileAll();
09454:                    } else { // pop up a window to ask if all open files should be compiled before testing
09455:                        Utilities.invokeLater(new Runnable() {
09456:                            public void run() {
09457:                                String title = "Must Compile All Source Files to Run Unit Tests";
09458:                                String msg = "To unit test all documents, you must first compile all out of sync source files.\n"
09459:                                        + "Would you like to compile all files and run the specified test?";
09460:                                int rc = JOptionPane.showConfirmDialog(
09461:                                        MainFrame.this , msg, title,
09462:                                        JOptionPane.YES_NO_OPTION);
09463:
09464:                                switch (rc) {
09465:                                case JOptionPane.YES_OPTION: // compile all open source files and test
09466:                                    _model.getCompilerModel().addListener(
09467:                                            testAfterCompile); // listener removes itself
09468:                                    _compileAll();
09469:                                    break;
09470:                                case JOptionPane.CLOSED_OPTION:
09471:                                case JOptionPane.NO_OPTION: // abort unit testing
09472:                                    _model.getJUnitModel().nonTestCase(true); // cleans up
09473:                                    break;
09474:                                default:
09475:                                    throw new UnexpectedException(
09476:                                            "Invalid returnCode from showConfirmDialog: "
09477:                                                    + rc);
09478:                                }
09479:                            }
09480:                        });
09481:                    }
09482:                }
09483:
09484:                public void saveBeforeJavadoc() {
09485:                    Utilities.invokeLater(new Runnable() {
09486:                        public void run() {
09487:                            _saveAllBeforeProceeding(
09488:                                    "To run Javadoc, you must first save ALL modified files.\n"
09489:                                            + "Would you like to save and then run Javadoc?",
09490:                                    ALWAYS_SAVE_BEFORE_JAVADOC,
09491:                                    "Always save before running Javadoc");
09492:                        }
09493:                    });
09494:                }
09495:
09496:                /** Helper method shared by all "saveBeforeX" methods.  In JUnit tests, YES option is automatically selected
09497:                 * @param message a prompt message to be displayed to the user
09498:                 * @param option the BooleanOption for the prompt dialog checkbox
09499:                 * @param checkMsg the description of the checkbox ("Always save before X")
09500:                 */
09501:                private void _saveAllBeforeProceeding(String message,
09502:                        BooleanOption option, String checkMsg) {
09503:                    //      new ScrollableDialog(null, "saveBeforeProceeding called in MainFrame", "", "").show();
09504:                    if (_model.hasModifiedDocuments()) {
09505:                        if (!DrJava.getConfig().getSetting(option)
09506:                                .booleanValue()
09507:                                && !Utilities.TEST_MODE) {
09508:                            ConfirmCheckBoxDialog dialog = new ConfirmCheckBoxDialog(
09509:                                    MainFrame.this ,
09510:                                    "Must Save All Files to Continue", message,
09511:                                    checkMsg);
09512:                            int rc = dialog.show();
09513:
09514:                            switch (rc) {
09515:                            case JOptionPane.YES_OPTION:
09516:                                _saveAll();
09517:                                // Only remember checkbox if they say yes
09518:                                if (dialog.getCheckBoxValue())
09519:                                    DrJava.getConfig().setSetting(option,
09520:                                            Boolean.TRUE);
09521:                                break;
09522:                            case JOptionPane.NO_OPTION:
09523:                            case JOptionPane.CANCEL_OPTION:
09524:                            case JOptionPane.CLOSED_OPTION:
09525:                                // do nothing
09526:                                break;
09527:                            default:
09528:                                throw new RuntimeException(
09529:                                        "Invalid rc from showConfirmDialog: "
09530:                                                + rc);
09531:                            }
09532:                        } else
09533:                            _saveAll();
09534:                    }
09535:                }
09536:
09537:                /** Saves the active document which is untitled. */
09538:                public void saveUntitled() {
09539:                    _saveAs();
09540:                }
09541:
09542:                public void filePathContainsPound() {
09543:                    Utilities.invokeLater(new Runnable() {
09544:                        public void run() {
09545:                            if (DrJava.getConfig().getSetting(
09546:                                    WARN_PATH_CONTAINS_POUND).booleanValue()) {
09547:                                String msg = "Files whose paths contain the '#' symbol cannot be used in the\n"
09548:                                        + "Interactions Pane due to a bug in Java's file to URL conversion.\n"
09549:                                        + "It is suggested that you change the name of the directory\n"
09550:                                        + "containing the '#' symbol.";
09551:
09552:                                String title = "Path Contains Pound Sign";
09553:
09554:                                ConfirmCheckBoxDialog dialog = new ConfirmCheckBoxDialog(
09555:                                        MainFrame.this , title, msg,
09556:                                        "Do not show this message again",
09557:                                        JOptionPane.WARNING_MESSAGE,
09558:                                        JOptionPane.DEFAULT_OPTION);
09559:                                if (dialog.show() == JOptionPane.OK_OPTION
09560:                                        && dialog.getCheckBoxValue()) {
09561:                                    DrJava.getConfig().setSetting(
09562:                                            WARN_PATH_CONTAINS_POUND,
09563:                                            Boolean.FALSE);
09564:                                }
09565:                            }
09566:                        }
09567:                    });
09568:                }
09569:
09570:                /** Event that is fired with there is nothing to test.  JUnit is never started. */
09571:                public void nonTestCase(boolean isTestAll) {
09572:
09573:                    //      Utilities.showStackTrace(new UnexpectedException("We should not have called nonTestCase"));
09574:
09575:                    final String message = isTestAll ? "There are no compiled JUnit TestCases available for execution.\n"
09576:                            + "Perhaps you have not yet compiled your test files."
09577:                            : "The current document is not a valid JUnit test case.\n"
09578:                                    + "Please make sure that:\n"
09579:                                    + "- it has been compiled and\n"
09580:                                    + "- it is a subclass of junit.framework.TestCase.\n";
09581:
09582:                    // Not necessarily invoked from event-handling thread!
09583:
09584:                    Utilities.invokeLater(new Runnable() {
09585:                        public void run() {
09586:                            JOptionPane.showMessageDialog(MainFrame.this ,
09587:                                    message,
09588:                                    "Test Only Executes JUnit test cases",
09589:                                    JOptionPane.ERROR_MESSAGE);
09590:                            // clean up as in JUnitEnded 
09591:                            try {
09592:                                showTab(_junitErrorPanel);
09593:                                _junitAction.setEnabled(true);
09594:                                _junitAllAction.setEnabled(true);
09595:                                _junitProjectAction.setEnabled(_model
09596:                                        .isProjectActive());
09597:                                _junitErrorPanel.reset();
09598:                            } finally {
09599:                                hourglassOff();
09600:                                _restoreJUnitActionsEnabled();
09601:                            }
09602:                        }
09603:                    });
09604:                }
09605:
09606:                /** Event that is fired when testing encounters an illegal class file.  JUnit is never started. */
09607:                public void classFileError(ClassFileError e) {
09608:
09609:                    final String message = "The class file for class "
09610:                            + e.getClassName()
09611:                            + " in source file "
09612:                            + e.getCanonicalPath()
09613:                            + " cannot be loaded.\n "
09614:                            + "When DrJava tries to load it, the following error is generated:\n"
09615:                            + e.getError();
09616:
09617:                    // Not necessarily invoked from event-handling thread!
09618:
09619:                    Utilities.invokeLater(new Runnable() {
09620:                        public void run() {
09621:                            JOptionPane.showMessageDialog(MainFrame.this ,
09622:                                    message,
09623:                                    "Testing works only on valid class files",
09624:                                    JOptionPane.ERROR_MESSAGE);
09625:                            // clean up as junitEnded except hourglassOff (should factored into a private method)
09626:                            showTab(_junitErrorPanel);
09627:                            _junitAction.setEnabled(true);
09628:                            _junitAllAction.setEnabled(true);
09629:                            _junitProjectAction.setEnabled(_model
09630:                                    .isProjectActive());
09631:                            _junitErrorPanel.reset();
09632:                        }
09633:                    });
09634:                }
09635:
09636:                /** Only callable from within the event-handling thread */
09637:                public void currentDirectoryChanged(final File dir) {
09638:                    _setCurrentDirectory(dir);
09639:                }
09640:
09641:                /** Check if the specified document has been modified. If it has, ask the user if he would like to save it 
09642:                 * and save the document if yes. Also give the user a "cancel" option to cancel doing the operation 
09643:                 * that got us here in the first place.
09644:                 *
09645:                 * @return A boolean indicating whether the user cancelled the save process.  False means cancel.
09646:                 */
09647:                public boolean canAbandonFile(OpenDefinitionsDocument doc) {
09648:                    return _fileSaveHelper(doc,
09649:                            JOptionPane.YES_NO_CANCEL_OPTION);
09650:                }
09651:
09652:                private boolean _fileSaveHelper(OpenDefinitionsDocument doc,
09653:                        int paneOption) {
09654:                    String text, fname;
09655:                    OpenDefinitionsDocument lastActive = _model
09656:                            .getActiveDocument();
09657:                    if (lastActive != doc) {
09658:                        _model.setActiveDocument(doc);
09659:                    }
09660:                    boolean notFound = false;
09661:                    try {
09662:                        File file = doc.getFile();
09663:                        if (file == null) {
09664:                            fname = "Untitled file";
09665:                            text = "Untitled file has been modified. Would you like to save it?";
09666:                        } else {
09667:                            fname = file.getName();
09668:                            text = fname
09669:                                    + " has been modified. Would you like to save it?";
09670:                        }
09671:                    } catch (FileMovedException fme) {
09672:                        // File was deleted, but use the same name anyway
09673:                        fname = fme.getFile().getName();
09674:                        text = fname
09675:                                + " not found on disk. Would you like to save to another file?";
09676:                        notFound = true;
09677:                    }
09678:
09679:                    int rc = JOptionPane.showConfirmDialog(MainFrame.this ,
09680:                            text, "Save " + fname + "?", paneOption);
09681:                    switch (rc) {
09682:                    case JOptionPane.YES_OPTION:
09683:                        boolean saved = false;
09684:                        if (notFound)
09685:                            saved = _saveAs();
09686:                        else
09687:                            saved = _save();
09688:                        if (doc != lastActive) {
09689:                            _model.setActiveDocument(lastActive); // breaks when "if" clause omitted
09690:                        }
09691:                        return saved;
09692:                    case JOptionPane.NO_OPTION:
09693:                        if (doc != lastActive) {
09694:                            _model.setActiveDocument(lastActive); // breaks when "if" clause omitted
09695:                        }
09696:                        return true;
09697:                    case JOptionPane.CLOSED_OPTION:
09698:                    case JOptionPane.CANCEL_OPTION:
09699:                        return false;
09700:                    default: // never executed
09701:                        throw new RuntimeException("Invalid option: " + rc);
09702:                    }
09703:                }
09704:
09705:                /** Check if the current document has been modified. If it has, ask the user if he would like to save it 
09706:                 * and save the document if yes.
09707:                 * @return true if quitting should continue, false if the user cancelled
09708:                 */
09709:                public boolean quitFile(OpenDefinitionsDocument doc) {
09710:                    return _fileSaveHelper(doc,
09711:                            JOptionPane.YES_NO_CANCEL_OPTION);
09712:                }
09713:
09714:                /** Called to ask the listener if it is OK to revert the current document to a newer version saved on file. */
09715:                public boolean shouldRevertFile(OpenDefinitionsDocument doc) {
09716:                    String fname;
09717:                    if (!_model.getActiveDocument().equals(doc)) {
09718:                        _model.setActiveDocument(doc);
09719:                    }
09720:                    try {
09721:                        File file = doc.getFile();
09722:                        if (file == null)
09723:                            fname = "Untitled file";
09724:                        else
09725:                            fname = file.getName();
09726:                    } catch (FileMovedException fme) {
09727:                        fname = fme.getFile().getName();
09728:                    }
09729:                    // File was deleted, but use the same name anyway
09730:
09731:                    String text = fname
09732:                            + " has changed on disk. Would you like to reload it?\n"
09733:                            + "This will discard any changes you have made.";
09734:                    int rc = JOptionPane.showConfirmDialog(MainFrame.this ,
09735:                            text, fname + " Modified on Disk",
09736:                            JOptionPane.YES_NO_OPTION);
09737:                    switch (rc) {
09738:                    case JOptionPane.YES_OPTION:
09739:                        return true;
09740:                    case JOptionPane.NO_OPTION:
09741:                        return false;
09742:                    case JOptionPane.CLOSED_OPTION:
09743:                    case JOptionPane.CANCEL_OPTION:
09744:                        return false;
09745:                    default:
09746:                        throw new RuntimeException("Invalid rc: " + rc);
09747:                    }
09748:                }
09749:
09750:                public void interactionIncomplete() {
09751:                }
09752:
09753:                /* Changes to the state */
09754:
09755:                public void projectBuildDirChanged() {
09756:                    if (_model.getBuildDirectory() != null) {
09757:                        _cleanAction.setEnabled(true);
09758:                    } else
09759:                        _cleanAction.setEnabled(false);
09760:                }
09761:
09762:                public void projectWorkDirChanged() {
09763:                }
09764:
09765:                public void projectModified() {
09766:                    //      _saveProjectAction.setEnabled(_model.isProjectChanged());
09767:                }
09768:
09769:                public void projectClosed() {
09770:                    Utilities.invokeAndWait(new Runnable() { // Why the wait?
09771:                                public void run() {
09772:                                    _model.getDocumentNavigator().asContainer()
09773:                                            .addKeyListener(_historyListener);
09774:                                    _model
09775:                                            .getDocumentNavigator()
09776:                                            .asContainer()
09777:                                            .addFocusListener(
09778:                                                    _focusListenerForRecentDocs);
09779:                                    _model.getDocumentNavigator().asContainer()
09780:                                            .addMouseListener(
09781:                                                    _resetFindReplaceListener);
09782:                                    //      new ScrollableDialog(null, "Closing JUnit Error Panel in MainFrame", "", "").show();
09783:                                    removeTab(_junitErrorPanel);
09784:                                    _runButton = _updateToolbarButton(
09785:                                            _runButton, _runAction);
09786:                                    _compileButton = _updateToolbarButton(
09787:                                            _compileButton, _compileAllAction);
09788:                                    _junitButton = _updateToolbarButton(
09789:                                            _junitButton, _junitAllAction);
09790:                                    projectRunnableChanged();
09791:                                }
09792:                            });
09793:                }
09794:
09795:                public void projectOpened(File projectFile,
09796:                        FileOpenSelector files) {
09797:                    _setUpContextMenus();
09798:                    projectRunnableChanged();
09799:                    _compileButton = _updateToolbarButton(_compileButton,
09800:                            _compileProjectAction);
09801:                    _junitButton = _updateToolbarButton(_junitButton,
09802:                            _junitProjectAction);
09803:                    _recentProjectManager.updateOpenFiles(projectFile);
09804:                    open(files);
09805:                    _openProjectUpdate();
09806:                    _model.getDocumentNavigator().asContainer().addKeyListener(
09807:                            _historyListener);
09808:                    _model.getDocumentNavigator().asContainer()
09809:                            .addFocusListener(_focusListenerForRecentDocs);
09810:                    _model.getDocumentNavigator().asContainer()
09811:                            .addMouseListener(_resetFindReplaceListener);
09812:                    _model.refreshActiveDocument();
09813:                }
09814:
09815:                public void projectRunnableChanged() {
09816:                    if (_model.getMainClass() != null
09817:                            && _model.getMainClass().exists()) {
09818:                        _runProjectAction.setEnabled(_model.isProjectActive());
09819:                        _runButton = _updateToolbarButton(_runButton,
09820:                                _runProjectAction);
09821:                    } else {
09822:                        _runProjectAction.setEnabled(false);
09823:                        _runButton = _updateToolbarButton(_runButton,
09824:                                _runAction);
09825:                    }
09826:                }
09827:
09828:                public void documentNotFound(OpenDefinitionsDocument d, File f) {
09829:
09830:                    _model.setProjectChanged(true);
09831:
09832:                    String text = "File "
09833:                            + f.getAbsolutePath()
09834:                            + "\ncould not be found on disk!  It was probably moved\n"
09835:                            + "or deleted.  Would you like to try to find it?";
09836:                    int rc = JOptionPane.showConfirmDialog(MainFrame.this ,
09837:                            text, "File Moved or Deleted",
09838:                            JOptionPane.YES_NO_OPTION);
09839:                    if (rc == JOptionPane.NO_OPTION)
09840:                        return;
09841:                    if (rc == JOptionPane.YES_OPTION) {
09842:                        try {
09843:                            File[] opened = _openSelector.getFiles();
09844:                            d.setFile(opened[0]);
09845:                        } catch (OperationCanceledException oce) {
09846:                            // Interpret cancelled as "NO"
09847:                        }
09848:                    }
09849:                    // The following line was commented out because it breaks when a user want to close but not save a deleted file      
09850:                    //      else throw new DocumentClosedException(d,"Document in " + f + "closed unexpectedly");  // misnamed exception
09851:                }
09852:            } // End of ModelListener class
09853:
09854:            public JViewport getDefViewport() {
09855:                OpenDefinitionsDocument doc = _model.getActiveDocument();
09856:                //    new ScrollableDialog(null, "Active Document is " + doc, "", "").show();
09857:                JScrollPane defScroll = _defScrollPanes.get(doc);
09858:                return defScroll.getViewport();
09859:            }
09860:
09861:            public void removeTab(final Component c) {
09862:                Utilities.invokeLater(new Runnable() {
09863:                    public void run() {
09864:                        if (_tabbedPane.getTabCount() > 1) {
09865:                            if (_tabbedPane.getSelectedIndex() == _tabbedPane
09866:                                    .getTabCount() - 1)
09867:                                _tabbedPane.setSelectedIndex(_tabbedPane
09868:                                        .getSelectedIndex() - 1);
09869:                            else
09870:                                _tabbedPane.setSelectedIndex(_tabbedPane
09871:                                        .getSelectedIndex() + 1);
09872:                            _tabbedPane.remove(c);
09873:                            ((TabbedPanel) c).setDisplayed(false);
09874:                        }
09875:                        _currentDefPane.requestFocusInWindow();
09876:                    }
09877:                });
09878:            }
09879:
09880:            /** Shows the components passed in in the appropriate place in the tabbedPane depending on the position of
09881:             * the component in the _tabs list.  Only runs in the event thread.
09882:             * @param c the component to show in the tabbedPane
09883:             */
09884:            private void showTab(final Component c) {
09885:                // TODO: put all of the _tabbedPane components in _tabs. eliminating special cases for interactions, console (which 
09886:                // are always displayed)
09887:                assert EventQueue.isDispatchThread();
09888:                //    Utilities.invokeLater(new Runnable() {
09889:                //      public void run() {
09890:                int numVisible = 0;
09891:                //        System.err.println("showTab called with c = " + c);
09892:
09893:                if (c == _interactionsContainer) {
09894:                    //          Utilities.show("InteractionsTab selected");
09895:                    _tabbedPane.setSelectedIndex(INTERACTIONS_TAB);
09896:                    c.requestFocusInWindow();
09897:                } else if (c == _consoleScroll) {
09898:                    _tabbedPane.setSelectedIndex(CONSOLE_TAB);
09899:                    c.requestFocusInWindow();
09900:                } else {
09901:                    for (TabbedPanel tp : _tabs) {
09902:                        if (tp == c) {
09903:                            // 2 right now is a magic number for the number of tabs always visible
09904:                            // interactions & console
09905:                            if (!tp.isDisplayed()) {
09906:                                _tabbedPane.insertTab(tp.getName(), null, tp,
09907:                                        null, numVisible + 2);
09908:                                tp.setVisible(true);
09909:                                tp.setDisplayed(true);
09910:                                tp.repaint();
09911:                            }
09912:                            _tabbedPane.setSelectedIndex(numVisible + 2);
09913:
09914:                            c.requestFocusInWindow();
09915:                            return;
09916:                        }
09917:                        if (tp.isDisplayed())
09918:                            numVisible++;
09919:                    }
09920:                }
09921:                //      }
09922:                //    });
09923:            }
09924:
09925:            /**
09926:             * Sets the location of the main divider.
09927:             * (not currently used)
09928:             private void _setDividerLocation() {
09929:             int divLocation = _mainSplit.getHeight() -
09930:             _mainSplit.getDividerSize() -
09931:             (int)_tabbedPane.getMinimumSize().getHeight();
09932:             if (_mainSplit.getDividerLocation() > divLocation)
09933:             _mainSplit.setDividerLocation(divLocation);
09934:             }*/
09935:
09936:            /** Warns the user that the current file is open and query them if they wish to save over the currently open file. */
09937:            private boolean _warnFileOpen(File f) {
09938:                OpenDefinitionsDocument d = null;
09939:                try {
09940:                    d = _model.getDocumentForFile(f);
09941:                } catch (IOException ioe) { /* do nothing */
09942:                }
09943:                Object[] options = { "Yes", "No" };
09944:                if (d == null)
09945:                    return false;
09946:                boolean dMod = d.isModifiedSinceSave();
09947:                String msg = "This file is already open in DrJava"
09948:                        + (dMod ? " and has been modified" : "")
09949:                        + ".  Do you wish to overwrite it?";
09950:                int choice = JOptionPane
09951:                        .showOptionDialog(MainFrame.this , msg,
09952:                                "File Open Warning", JOptionPane.YES_NO_OPTION,
09953:                                JOptionPane.QUESTION_MESSAGE, null, options,
09954:                                options[1]);
09955:                if (choice == JOptionPane.YES_OPTION)
09956:                    return _model.closeFileWithoutPrompt(d);
09957:                return false;
09958:            }
09959:
09960:            /**
09961:             * Confirms with the user that the file should be overwritten.
09962:             * @return <code>true</code> iff the user accepts overwriting.
09963:             */
09964:            private boolean _verifyOverwrite() {
09965:                Object[] options = { "Yes", "No" };
09966:                int n = JOptionPane
09967:                        .showOptionDialog(
09968:                                MainFrame.this ,
09969:                                "This file already exists.  Do you wish to overwrite the file?",
09970:                                "Confirm Overwrite", JOptionPane.YES_NO_OPTION,
09971:                                JOptionPane.QUESTION_MESSAGE, null, options,
09972:                                options[1]);
09973:                return (n == JOptionPane.YES_OPTION);
09974:            }
09975:
09976:            /* Pops up a message and cleans up after unit testing has been interrupted. */
09977:            private void _junitInterrupted(final UnexpectedException e) {
09978:                Utilities.invokeLater(new Runnable() {
09979:                    public void run() {
09980:                        _showJUnitInterrupted(e);
09981:                        removeTab(_junitErrorPanel);
09982:                        _model.refreshActiveDocument();
09983:                        // hourglassOff();
09984:                    }
09985:                });
09986:            }
09987:
09988:            boolean isDebuggerReady() {
09989:                return _showDebugger && _model.getDebugger().isReady();
09990:            }
09991:
09992:            /** Return the find replace dialog. Package protected for use in tests. */
09993:            FindReplacePanel getFindReplaceDialog() {
09994:                return _findReplace;
09995:            }
09996:
09997:            /** Builds the Hashtables in KeyBindingManager that are used to keep track of key-bindings and allows for live 
09998:             * updating, conflict resolution, and intelligent error messages (the ActionToNameMap).  
09999:             * IMPORTANT: Don't use this way to put actions into the KeyBindingManager if the action is a menu item. It will 
10000:             * already have been put in.  Putting in again will cause bug #803304 "Uncomment lines wont rebind".
10001:             */
10002:            private void _setUpKeyBindingMaps() {
10003:                final ActionMap _actionMap = _currentDefPane.getActionMap();
10004:
10005:                KeyBindingManager.Singleton
10006:                        .put(KEY_BACKWARD, _actionMap
10007:                                .get(DefaultEditorKit.backwardAction), null,
10008:                                "Backward");
10009:                KeyBindingManager.Singleton.addShiftAction(KEY_BACKWARD,
10010:                        DefaultEditorKit.selectionBackwardAction);
10011:
10012:                KeyBindingManager.Singleton.put(KEY_BEGIN_DOCUMENT, _actionMap
10013:                        .get(DefaultEditorKit.beginAction), null,
10014:                        "Begin Document");
10015:                KeyBindingManager.Singleton.addShiftAction(KEY_BEGIN_DOCUMENT,
10016:                        DefaultEditorKit.selectionBeginAction);
10017:
10018:                //    KeyBindingManager.Singleton.put(KEY_BEGIN_LINE, _actionMap.get(DefaultEditorKit.beginLineAction), null, 
10019:                //                                    "Begin Line");
10020:                KeyBindingManager.Singleton.put(KEY_BEGIN_LINE,
10021:                        _beginLineAction, null, "Begin Line");
10022:                //    KeyBindingManager.Singleton.addShiftAction(KEY_BEGIN_LINE,
10023:                //                                               DefaultEditorKit.selectionBeginLineAction);
10024:                KeyBindingManager.Singleton.addShiftAction(KEY_BEGIN_LINE,
10025:                        _selectionBeginLineAction);
10026:
10027:                KeyBindingManager.Singleton.put(KEY_PREVIOUS_WORD, _actionMap
10028:                        .get(DefaultEditorKit.previousWordAction), null,
10029:                        "Previous Word");
10030:                KeyBindingManager.Singleton.addShiftAction(KEY_PREVIOUS_WORD,
10031:                        DefaultEditorKit.selectionPreviousWordAction);
10032:
10033:                KeyBindingManager.Singleton.put(KEY_DOWN, _actionMap
10034:                        .get(DefaultEditorKit.downAction), null, "Down");
10035:                KeyBindingManager.Singleton.addShiftAction(KEY_DOWN,
10036:                        DefaultEditorKit.selectionDownAction);
10037:
10038:                KeyBindingManager.Singleton.put(KEY_END_DOCUMENT, _actionMap
10039:                        .get(DefaultEditorKit.endAction), null, "End Document");
10040:                KeyBindingManager.Singleton.addShiftAction(KEY_END_DOCUMENT,
10041:                        DefaultEditorKit.selectionEndAction);
10042:
10043:                KeyBindingManager.Singleton.put(KEY_END_LINE, _actionMap
10044:                        .get(DefaultEditorKit.endLineAction), null, "End Line");
10045:                KeyBindingManager.Singleton.addShiftAction(KEY_END_LINE,
10046:                        DefaultEditorKit.selectionEndLineAction);
10047:
10048:                KeyBindingManager.Singleton.put(KEY_NEXT_WORD, _actionMap
10049:                        .get(DefaultEditorKit.nextWordAction), null,
10050:                        "Next Word");
10051:                KeyBindingManager.Singleton.addShiftAction(KEY_NEXT_WORD,
10052:                        DefaultEditorKit.selectionNextWordAction);
10053:
10054:                KeyBindingManager.Singleton.put(KEY_FORWARD, _actionMap
10055:                        .get(DefaultEditorKit.forwardAction), null, "Forward");
10056:                KeyBindingManager.Singleton.addShiftAction(KEY_FORWARD,
10057:                        DefaultEditorKit.selectionForwardAction);
10058:
10059:                KeyBindingManager.Singleton.put(KEY_UP, _actionMap
10060:                        .get(DefaultEditorKit.upAction), null, "Up");
10061:                KeyBindingManager.Singleton.addShiftAction(KEY_UP,
10062:                        DefaultEditorKit.selectionUpAction);
10063:
10064:                // These last methods have no default selection methods
10065:                KeyBindingManager.Singleton.put(KEY_PAGE_DOWN, _actionMap
10066:                        .get(DefaultEditorKit.pageDownAction), null,
10067:                        "Page Down");
10068:                KeyBindingManager.Singleton.put(KEY_PAGE_UP, _actionMap
10069:                        .get(DefaultEditorKit.pageUpAction), null, "Page Up");
10070:                KeyBindingManager.Singleton.put(KEY_CUT_LINE, _cutLineAction,
10071:                        null, "Cut Line");
10072:                KeyBindingManager.Singleton.put(KEY_CLEAR_LINE,
10073:                        _clearLineAction, null, "Clear Line");
10074:                KeyBindingManager.Singleton.put(KEY_SHIFT_DELETE_PREVIOUS,
10075:                        _actionMap.get(DefaultEditorKit.deletePrevCharAction),
10076:                        null, "Delete Previous");
10077:                KeyBindingManager.Singleton.put(KEY_SHIFT_DELETE_NEXT,
10078:                        _actionMap.get(DefaultEditorKit.deleteNextCharAction),
10079:                        null, "Delete Next");
10080:            }
10081:
10082:            /** @param listener The ComponentListener to add to the open documents list
10083:             *  This method allows for testing of the dancing UI (See MainFrameTest.testDancingUI()).
10084:             */
10085:            public void addComponentListenerToOpenDocumentsList(
10086:                    ComponentListener listener) {
10087:                _docSplitPane.getLeftComponent().addComponentListener(listener);
10088:            }
10089:
10090:            /**For test purposes only. Returns the text in the status bar. Is used to test brace matching*/
10091:            public String getFileNameField() {
10092:                return _statusField.getText();
10093:            }
10094:
10095:            /**For test purposes only. Returns the edit menu*/
10096:            public JMenu getEditMenu() {
10097:                return _editMenu;
10098:            }
10099:
10100:            /** The OptionListener for FONT_MAIN */
10101:            private class MainFontOptionListener implements 
10102:                    OptionListener<Font> {
10103:                public void optionChanged(OptionEvent<Font> oce) {
10104:                    _setMainFont();
10105:                }
10106:            }
10107:
10108:            /** The OptionListener for FONT_LINE_NUMBERS */
10109:            private class LineNumbersFontOptionListener implements 
10110:                    OptionListener<Font> {
10111:                public void optionChanged(OptionEvent<Font> oce) {
10112:                    _updateLineNums();
10113:                }
10114:            }
10115:
10116:            /** The OptionListener for FONT_DOCLIST */
10117:            private class DoclistFontOptionListener implements 
10118:                    OptionListener<Font> {
10119:                public void optionChanged(OptionEvent<Font> oce) {
10120:                    Font doclistFont = DrJava.getConfig().getSetting(
10121:                            FONT_DOCLIST);
10122:                    _model.getDocCollectionWidget().setFont(doclistFont);
10123:                }
10124:            }
10125:
10126:            /** The OptionListener for FONT_TOOLBAR */
10127:            private class ToolbarFontOptionListener implements 
10128:                    OptionListener<Font> {
10129:                public void optionChanged(OptionEvent<Font> oce) {
10130:                    _updateToolbarButtons();
10131:                }
10132:            }
10133:
10134:            /** The OptionListener for DEFINITIONS_NORMAL_COLOR */
10135:            private class NormalColorOptionListener implements 
10136:                    OptionListener<Color> {
10137:                public void optionChanged(OptionEvent<Color> oce) {
10138:                    _updateNormalColor();
10139:                }
10140:            }
10141:
10142:            /** The OptionListener for DEFINITIONS_BACKGROUND_COLOR */
10143:            private class BackgroundColorOptionListener implements 
10144:                    OptionListener<Color> {
10145:                public void optionChanged(OptionEvent<Color> oce) {
10146:                    _updateBackgroundColor();
10147:                }
10148:            }
10149:
10150:            /** The OptionListener for TOOLBAR options */
10151:            private class ToolbarOptionListener implements 
10152:                    OptionListener<Boolean> {
10153:                public void optionChanged(OptionEvent<Boolean> oce) {
10154:                    _updateToolbarButtons();
10155:                }
10156:            }
10157:
10158:            /** The OptionListener for LINEENUM_ENABLED. */
10159:            private class LineEnumOptionListener implements 
10160:                    OptionListener<Boolean> {
10161:                public void optionChanged(OptionEvent<Boolean> oce) {
10162:                    _updateDefScrollRowHeader();
10163:                }
10164:            }
10165:
10166:            /** The OptionListener for QUIT_PROMPT. */
10167:            private class QuitPromptOptionListener implements 
10168:                    OptionListener<Boolean> {
10169:                public void optionChanged(OptionEvent<Boolean> oce) {
10170:                    _promptBeforeQuit = oce.value.booleanValue();
10171:                }
10172:            }
10173:
10174:            /** The OptionListener for RECENT_FILES_MAX_SIZE. */
10175:            private class RecentFilesOptionListener implements 
10176:                    OptionListener<Integer> {
10177:                public void optionChanged(OptionEvent<Integer> oce) {
10178:                    _recentFileManager.updateMax(oce.value.intValue());
10179:                    _recentFileManager.numberItems();
10180:                    _recentProjectManager.updateMax(oce.value.intValue());
10181:                    _recentProjectManager.numberItems();
10182:                }
10183:            }
10184:
10185:            private class LastFocusListener extends FocusAdapter {
10186:                public void focusGained(FocusEvent e) {
10187:                    _lastFocusOwner = e.getComponent();
10188:                    //      System.err.println("_lastFocusOwner = " + _lastFocusOwner);
10189:                }
10190:            };
10191:
10192:            /** Wrapper for setPopupLoc(Window, Component) that uses the window's owner as the owner to center the popup on.
10193:             * @param popup the Popup window
10194:             */
10195:            public void setPopupLoc(Window popup) {
10196:                MainFrame.setPopupLoc(popup, (popup.getOwner() != null) ? popup
10197:                        .getOwner() : this );
10198:            }
10199:
10200:            /** Sets the location of the popup in a consistant way.  If the popup has an owner, the popup is centered over the
10201:             * owner.  If the popup has no owner(owner == null), the popup is centered over the first monitor.  In either case,
10202:             * the popup is moved and scaled if any part of it is not on the screen.  This method should be called for all popups
10203:             * to maintain consistancy.
10204:             * @param popup the popup window
10205:             * @param owner the parent component for the popup
10206:             */
10207:            public static void setPopupLoc(Window popup, Component owner) {
10208:                Rectangle frameRect = popup.getBounds();
10209:
10210:                Point ownerLoc = null;
10211:                Dimension ownerSize = null;
10212:                if (owner != null) {
10213:                    ownerLoc = owner.getLocation();
10214:                    ownerSize = owner.getSize();
10215:                } else {
10216:                    //for multi-monitor support
10217:                    //Question: do we want it to popup on the first monitor always?
10218:                    GraphicsDevice[] dev = GraphicsEnvironment
10219:                            .getLocalGraphicsEnvironment().getScreenDevices();
10220:                    Rectangle rec = dev[0].getDefaultConfiguration()
10221:                            .getBounds();
10222:                    ownerLoc = rec.getLocation();
10223:                    ownerSize = rec.getSize();
10224:                }
10225:
10226:                // center it on owner
10227:                Point loc = new Point(ownerLoc.x
10228:                        + (ownerSize.width - frameRect.width) / 2, ownerLoc.y
10229:                        + (ownerSize.height - frameRect.height) / 2);
10230:                frameRect.setLocation(loc);
10231:
10232:                // now find the GraphicsConfiguration the popup is on
10233:                GraphicsConfiguration gcBest = null;
10234:                int gcBestArea = -1;
10235:                GraphicsEnvironment ge = GraphicsEnvironment
10236:                        .getLocalGraphicsEnvironment();
10237:                GraphicsDevice[] gs = ge.getScreenDevices();
10238:                for (GraphicsDevice gd : gs) {
10239:                    GraphicsConfiguration gc = gd.getDefaultConfiguration();
10240:                    Rectangle isect = frameRect.intersection(gc.getBounds());
10241:                    int gcArea = isect.width * isect.height;
10242:                    if (gcArea > gcBestArea) {
10243:                        gcBest = gc;
10244:                        gcBestArea = gcArea;
10245:                    }
10246:                }
10247:
10248:                // make it fit on the screen
10249:                Rectangle screenRect = gcBest.getBounds();
10250:                Dimension screenSize = screenRect.getSize();
10251:                Dimension frameSize = popup.getSize();
10252:
10253:                if (frameSize.height > screenSize.height)
10254:                    frameSize.height = screenSize.height;
10255:                if (frameSize.width > screenSize.width)
10256:                    frameSize.width = screenSize.width;
10257:
10258:                frameRect.setSize(frameSize);
10259:
10260:                // center it on owner again
10261:                loc = new Point(ownerLoc.x
10262:                        + (ownerSize.width - frameRect.width) / 2, ownerLoc.y
10263:                        + (ownerSize.height - frameRect.height) / 2);
10264:                frameRect.setLocation(loc);
10265:
10266:                // now fit it on the screen
10267:                if (frameRect.x < screenRect.x)
10268:                    frameRect.x = screenRect.x;
10269:                if (frameRect.x + frameRect.width > screenRect.x
10270:                        + screenRect.width)
10271:                    frameRect.x = screenRect.x + screenRect.width
10272:                            - frameRect.width;
10273:
10274:                if (frameRect.y < screenRect.y)
10275:                    frameRect.y = screenRect.y;
10276:                if (frameRect.y + frameRect.height > screenRect.y
10277:                        + screenRect.height)
10278:                    frameRect.y = screenRect.y + screenRect.height
10279:                            - frameRect.height;
10280:
10281:                popup.setSize(frameRect.getSize());
10282:                popup.setLocation(frameRect.getLocation());
10283:            }
10284:
10285:            /** Drag and drop target. */
10286:            DropTarget dropTarget = new DropTarget(this , this );
10287:
10288:            /** Linux URI drag-and-drop data flavor. */
10289:            private static DataFlavor uriListFlavor;
10290:            static {
10291:                try {
10292:                    uriListFlavor = new DataFlavor(
10293:                            "text/uri-list;class=java.lang.String");
10294:                } catch (ClassNotFoundException cnfe) {
10295:                    uriListFlavor = null;
10296:                }
10297:            }
10298:
10299:            /** User dragged something into the component. */
10300:            public void dragEnter(DropTargetDragEvent dropTargetDragEvent) {
10301:                dropTargetDragEvent
10302:                        .acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
10303:            }
10304:
10305:            public void dragExit(DropTargetEvent dropTargetEvent) {
10306:            }
10307:
10308:            public void dragOver(DropTargetDragEvent dropTargetDragEvent) {
10309:            }
10310:
10311:            public void dropActionChanged(
10312:                    DropTargetDragEvent dropTargetDragEvent) {
10313:            }
10314:
10315:            /** User dropped something on the component. */
10316:            public synchronized void drop(
10317:                    DropTargetDropEvent dropTargetDropEvent) {
10318:                try {
10319:                    Transferable tr = dropTargetDropEvent.getTransferable();
10320:                    if (tr.isDataFlavorSupported(DataFlavor.javaFileListFlavor)
10321:                            || ((uriListFlavor != null) && (tr
10322:                                    .isDataFlavorSupported(uriListFlavor)))) {
10323:                        dropTargetDropEvent
10324:                                .acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
10325:                        java.util.List<File> fileList;
10326:                        if (tr
10327:                                .isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
10328:                            @SuppressWarnings("unchecked")
10329:                            java.util.List<File> data = (java.util.List<File>) tr
10330:                                    .getTransferData(DataFlavor.javaFileListFlavor);
10331:                            fileList = data;
10332:                        } else {
10333:                            // work-around for Linux drag-and-drop
10334:                            // see Java bug 4899516
10335:                            @SuppressWarnings("unchecked")
10336:                            String data = (String) tr
10337:                                    .getTransferData(uriListFlavor);
10338:                            fileList = textURIListToFileList(data);
10339:                        }
10340:                        java.util.Iterator<File> iterator = fileList.iterator();
10341:                        java.util.List<File> filteredFileList = new java.util.ArrayList<File>();
10342:                        while (iterator.hasNext()) {
10343:                            File file = (File) iterator.next();
10344:                            if ((file.isFile())
10345:                                    && ((file.getName().endsWith(".java"))
10346:                                            || (file.getName().endsWith(".dj0"))
10347:                                            || (file.getName().endsWith(".dj1"))
10348:                                            || (file.getName().endsWith(".dj2"))
10349:                                            || (file.getName().endsWith(".dj0")) || (file
10350:                                            .getName().endsWith(".txt")))) {
10351:                                filteredFileList.add(file);
10352:                            }
10353:                        }
10354:                        final File[] fileArray = filteredFileList
10355:                                .toArray(new File[filteredFileList.size()]);
10356:                        FileOpenSelector fs = new FileOpenSelector() {
10357:                            public File[] getFiles() {
10358:                                return fileArray;
10359:                            }
10360:                        };
10361:                        open(fs);
10362:                        dropTargetDropEvent.getDropTargetContext()
10363:                                .dropComplete(true);
10364:                    } else {
10365:                        dropTargetDropEvent.rejectDrop();
10366:                    }
10367:                } catch (IOException ioe) {
10368:                    ioe.printStackTrace();
10369:                    dropTargetDropEvent.rejectDrop();
10370:                } catch (UnsupportedFlavorException ufe) {
10371:                    ufe.printStackTrace();
10372:                    dropTargetDropEvent.rejectDrop();
10373:                }
10374:            }
10375:
10376:            /**
10377:             * Convert a string with URIs to a list of files.
10378:             * @param data string with URIs
10379:             * @return list of files
10380:             */
10381:            private static java.util.List<File> textURIListToFileList(
10382:                    String data) {
10383:                java.util.List<File> list = new java.util.ArrayList<File>();
10384:                java.util.StringTokenizer st = new java.util.StringTokenizer(
10385:                        data, "\r\n");
10386:                while (st.hasMoreTokens()) {
10387:                    String s = st.nextToken();
10388:                    if (s.startsWith("#")) {
10389:                        // the line is a comment (as per the RFC 2483)
10390:                        continue;
10391:                    }
10392:                    try {
10393:                        java.net.URI uri = new java.net.URI(s);
10394:                        java.io.File file = new java.io.File(uri);
10395:                        list.add(file);
10396:                    } catch (java.net.URISyntaxException e) {
10397:                        // malformed URI
10398:                    } catch (IllegalArgumentException e) {
10399:                        // the URI is not a valid 'file:' URI
10400:                    }
10401:                }
10402:                return list;
10403:            }
10404:
10405:            /** Reset the position of the "Open Javadoc" dialog. */
10406:            public void resetAutoImportDialogPosition() {
10407:                initAutoImportDialog();
10408:                _autoImportDialog.setFrameState("default");
10409:                if (DrJava.getConfig().getSetting(
10410:                        DIALOG_AUTOIMPORT_STORE_POSITION).booleanValue()) {
10411:                    DrJava.getConfig().setSetting(DIALOG_AUTOIMPORT_STATE,
10412:                            "default");
10413:                }
10414:            }
10415:
10416:            /** Initialize dialog if necessary. */
10417:            void initAutoImportDialog() {
10418:                if (_autoImportDialog == null) {
10419:                    _autoImportPackageCheckbox = new JCheckBox("Import Package");
10420:                    _autoImportPackageCheckbox
10421:                            .addActionListener(new ActionListener() {
10422:                                public void actionPerformed(ActionEvent e) {
10423:                                    _autoImportDialog.resetFocus();
10424:                                }
10425:                            });
10426:                    _autoImportPackageCheckbox.setMnemonic('p');
10427:                    PredictiveInputFrame.InfoSupplier<JavaAPIListEntry> info = new PredictiveInputFrame.InfoSupplier<JavaAPIListEntry>() {
10428:                        public String apply(JavaAPIListEntry entry) {
10429:                            // show full class name as information
10430:                            return entry.getFullString();
10431:                        }
10432:                    };
10433:                    PredictiveInputFrame.CloseAction<JavaAPIListEntry> okAction = new PredictiveInputFrame.CloseAction<JavaAPIListEntry>() {
10434:                        public Object apply(
10435:                                PredictiveInputFrame<JavaAPIListEntry> p) {
10436:                            String text;
10437:                            if (p.getItem() != null) {
10438:                                // if a class was selected...
10439:                                text = p.getItem().getFullString();
10440:                            } else {
10441:                                // otherwise use the text that was entered
10442:                                text = p.getText();
10443:                            }
10444:                            if (_autoImportPackageCheckbox.isSelected()) {
10445:                                int lastDot = text.lastIndexOf('.');
10446:                                if (lastDot > 0) {
10447:                                    text = text.substring(0, lastDot + 1) + "*";
10448:                                }
10449:                            }
10450:                            final InteractionsModel im = _model
10451:                                    .getInteractionsModel();
10452:                            // get the last line (the one that caused the error)
10453:                            // and remove it from the history
10454:                            String lastLine = im.removeLastFromHistory();
10455:                            // import the selected class...
10456:                            String importLine = "import " + text
10457:                                    + "; // auto-import";
10458:                            // ...and try to do the last line again
10459:                            final String code = importLine
10460:                                    + ((lastLine != null) ? ("\n" + lastLine)
10461:                                            : "");
10462:                            EventQueue.invokeLater(new Runnable() {
10463:                                public void run() {
10464:                                    // interpret with the added import
10465:                                    im.append(code,
10466:                                            InteractionsDocument.DEFAULT_STYLE);
10467:                                    im.interpretCurrentInteraction();
10468:                                    hourglassOff();
10469:                                }
10470:                            });
10471:                            return null;
10472:                        }
10473:                    };
10474:                    PredictiveInputFrame.CloseAction<JavaAPIListEntry> cancelAction = new PredictiveInputFrame.CloseAction<JavaAPIListEntry>() {
10475:                        public Object apply(
10476:                                PredictiveInputFrame<JavaAPIListEntry> p) {
10477:                            // if no class was selected, do nothing
10478:                            // just reset the error information so the dialog box works next time
10479:                            _model.getInteractionsModel().resetLastErrors();
10480:                            hourglassOff();
10481:                            return null;
10482:                        }
10483:                    };
10484:                    java.util.ArrayList<PredictiveInputModel.MatchingStrategy<JavaAPIListEntry>> strategies = new java.util.ArrayList<PredictiveInputModel.MatchingStrategy<JavaAPIListEntry>>();
10485:                    strategies
10486:                            .add(new PredictiveInputModel.FragmentStrategy<JavaAPIListEntry>());
10487:                    strategies
10488:                            .add(new PredictiveInputModel.PrefixStrategy<JavaAPIListEntry>());
10489:                    strategies
10490:                            .add(new PredictiveInputModel.RegExStrategy<JavaAPIListEntry>());
10491:                    _autoImportDialog = new PredictiveInputFrame<JavaAPIListEntry>(
10492:                            MainFrame.this , "Auto Import Class",
10493:                            false, // force
10494:                            true, // ignore case
10495:                            info, strategies, okAction, cancelAction,
10496:                            new JavaAPIListEntry("dummy", "dummy", null)) {
10497:                        public void setOwnerEnabled(boolean b) {
10498:                            if (b) {
10499:                                hourglassOff();
10500:                            } else {
10501:                                hourglassOn();
10502:                            }
10503:                        }
10504:
10505:                        protected JComponent[] makeOptions() {
10506:                            return new JComponent[] { _autoImportPackageCheckbox };
10507:                        }
10508:                    };
10509:                    // putting one dummy entry in the list; it will be changed later anyway
10510:
10511:                    if (DrJava.getConfig().getSetting(
10512:                            DIALOG_AUTOIMPORT_STORE_POSITION).booleanValue()) {
10513:                        _autoImportDialog.setFrameState(DrJava.getConfig()
10514:                                .getSetting(DIALOG_AUTOIMPORT_STATE));
10515:                    }
10516:                    generateJavaAPIList();
10517:                }
10518:            }
10519:
10520:            /** The "Auto Import" dialog instance. */
10521:            PredictiveInputFrame<JavaAPIListEntry> _autoImportDialog = null;
10522:            JCheckBox _autoImportPackageCheckbox;
10523:
10524:            /** Imports a class. */
10525:            void _showAutoImportDialog(String s) {
10526:                generateJavaAPIList();
10527:                if (_javaAPIList == null) {
10528:                    return;
10529:                }
10530:                List<JavaAPIListEntry> autoImportList = new ArrayList<JavaAPIListEntry>(
10531:                        _javaAPIList);
10532:                if ((DrJava.getConfig().getSetting(
10533:                        DIALOG_COMPLETE_SCAN_CLASS_FILES).booleanValue())
10534:                        && (_autoImportClassList.size() > 0)) {
10535:                    autoImportList.addAll(_autoImportClassList);
10536:                } else {
10537:                    File projectRoot = _model.getProjectRoot();
10538:                    List<OpenDefinitionsDocument> docs = _model
10539:                            .getOpenDefinitionsDocuments();
10540:                    if (docs != null) {
10541:                        for (OpenDefinitionsDocument d : docs) {
10542:                            if (d.isUntitled())
10543:                                continue;
10544:                            try {
10545:                                File rel = FileOps.makeRelativeTo(d
10546:                                        .getRawFile(), projectRoot);
10547:                                String full = rel.toString().replace(
10548:                                        java.io.File.separatorChar, '.');
10549:                                for (String ext : edu.rice.cs.drjava.model.compiler.CompilerModel.EXTENSIONS) {
10550:                                    if (full.endsWith(ext)) {
10551:                                        full = full.substring(0, full
10552:                                                .lastIndexOf(ext));
10553:                                        break;
10554:                                    }
10555:                                }
10556:                                String simple = full;
10557:                                if (simple.lastIndexOf('.') >= 0) {
10558:                                    simple = simple.substring(simple
10559:                                            .lastIndexOf('.') + 1);
10560:                                }
10561:                                JavaAPIListEntry entry = new JavaAPIListEntry(
10562:                                        simple, full, null);
10563:                                if (!autoImportList.contains(entry)) {
10564:                                    autoImportList.add(entry);
10565:                                }
10566:                            } catch (IOException ioe) { /* ignore, just don't add this one */
10567:                            } catch (SecurityException se) { /* ignore, just don't add this one */
10568:                            }
10569:                        }
10570:                    }
10571:                }
10572:                PredictiveInputModel<JavaAPIListEntry> pim = new PredictiveInputModel<JavaAPIListEntry>(
10573:                        true,
10574:                        new PredictiveInputModel.PrefixStrategy<JavaAPIListEntry>(),
10575:                        autoImportList);
10576:                pim.setMask(s);
10577:                initAutoImportDialog();
10578:                _autoImportDialog.setModel(true, pim); // ignore case
10579:                hourglassOn();
10580:                _autoImportPackageCheckbox.setSelected(false);
10581:                _autoImportDialog.setVisible(true);
10582:            }
10583:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.