Source Code Cross Referenced for SwingGui.java in  » Scripting » rhino » org » mozilla » javascript » tools » debugger » 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 » Scripting » rhino » org.mozilla.javascript.tools.debugger 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
0002:         *
0003:         * ***** BEGIN LICENSE BLOCK *****
0004:         * Version: MPL 1.1/GPL 2.0
0005:         *
0006:         * The contents of this file are subject to the Mozilla Public License Version
0007:         * 1.1 (the "License"); you may not use this file except in compliance with
0008:         * the License. You may obtain a copy of the License at
0009:         * http://www.mozilla.org/MPL/
0010:         *
0011:         * Software distributed under the License is distributed on an "AS IS" basis,
0012:         * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
0013:         * for the specific language governing rights and limitations under the
0014:         * License.
0015:         *
0016:         * The Original Code is Rhino JavaScript Debugger code, released
0017:         * November 21, 2000.
0018:         *
0019:         * The Initial Developer of the Original Code is
0020:         * SeeBeyond Corporation.
0021:         * Portions created by the Initial Developer are Copyright (C) 2000
0022:         * the Initial Developer. All Rights Reserved.
0023:         *
0024:         * Contributor(s):
0025:         *   Igor Bukanov
0026:         *   Matt Gould
0027:         *   Cameron McCormack
0028:         *   Christopher Oliver
0029:         *   Hannes Wallnoefer
0030:         *
0031:         * Alternatively, the contents of this file may be used under the terms of
0032:         * the GNU General Public License Version 2 or later (the "GPL"), in which
0033:         * case the provisions of the GPL are applicable instead of those above. If
0034:         * you wish to allow use of your version of this file only under the terms of
0035:         * the GPL and not to allow others to use your version of this file under the
0036:         * MPL, indicate your decision by deleting the provisions above and replacing
0037:         * them with the notice and other provisions required by the GPL. If you do
0038:         * not delete the provisions above, a recipient may use your version of this
0039:         * file under either the MPL or the GPL.
0040:         *
0041:         * ***** END LICENSE BLOCK ***** */
0042:        package org.mozilla.javascript.tools.debugger;
0043:
0044:        import javax.swing.*;
0045:        import javax.swing.text.*;
0046:        import javax.swing.event.*;
0047:        import javax.swing.table.*;
0048:        import java.awt.*;
0049:        import java.awt.event.*;
0050:
0051:        import java.util.*;
0052:        import java.io.*;
0053:        import javax.swing.tree.DefaultTreeCellRenderer;
0054:        import javax.swing.tree.TreePath;
0055:        import java.lang.reflect.Method;
0056:
0057:        import org.mozilla.javascript.Kit;
0058:        import org.mozilla.javascript.SecurityUtilities;
0059:
0060:        import org.mozilla.javascript.tools.shell.ConsoleTextArea;
0061:
0062:        import org.mozilla.javascript.tools.debugger.downloaded.JTreeTable;
0063:        import org.mozilla.javascript.tools.debugger.downloaded.TreeTableModel;
0064:        import org.mozilla.javascript.tools.debugger.downloaded.TreeTableModelAdapter;
0065:
0066:        /**
0067:         * GUI for the Rhino debugger.
0068:         */
0069:        public class SwingGui extends JFrame implements  GuiCallback {
0070:
0071:            /**
0072:             * Serializable magic number.
0073:             */
0074:            private static final long serialVersionUID = -8217029773456711621L;
0075:
0076:            /**
0077:             * The debugger.
0078:             */
0079:            Dim dim;
0080:
0081:            /**
0082:             * The action to run when the 'Exit' menu item is chosen or the
0083:             * frame is closed.
0084:             */
0085:            private Runnable exitAction;
0086:
0087:            /**
0088:             * The {@link JDesktopPane} that holds the script windows.
0089:             */
0090:            private JDesktopPane desk;
0091:
0092:            /**
0093:             * The {@link JPanel} that shows information about the context.
0094:             */
0095:            private ContextWindow context;
0096:
0097:            /**
0098:             * The menu bar.
0099:             */
0100:            private Menubar menubar;
0101:
0102:            /**
0103:             * The tool bar.
0104:             */
0105:            private JToolBar toolBar;
0106:
0107:            /**
0108:             * The console that displays I/O from the script.
0109:             */
0110:            private JSInternalConsole console;
0111:
0112:            /**
0113:             * The {@link JSplitPane} that separates {@link #desk} from
0114:             * {@link org.mozilla.javascript.Context}.
0115:             */
0116:            private JSplitPane split1;
0117:
0118:            /**
0119:             * The status bar.
0120:             */
0121:            private JLabel statusBar;
0122:
0123:            /**
0124:             * Hash table of internal frame names to the internal frames themselves.
0125:             */
0126:            private Hashtable toplevels = new Hashtable();
0127:
0128:            /**
0129:             * Hash table of script URLs to their internal frames.
0130:             */
0131:            private Hashtable fileWindows = new Hashtable();
0132:
0133:            /**
0134:             * The {@link FileWindow} that last had the focus.
0135:             */
0136:            private FileWindow currentWindow;
0137:
0138:            /**
0139:             * File choose dialog for loading a script.
0140:             */
0141:            JFileChooser dlg;
0142:
0143:            /**
0144:             * The AWT EventQueue.  Used for manually pumping AWT events from
0145:             * {@link #dispatchNextGuiEvent()}.
0146:             */
0147:            private EventQueue awtEventQueue;
0148:
0149:            /**
0150:             * Creates a new SwingGui.
0151:             */
0152:            public SwingGui(Dim dim, String title) {
0153:                super (title);
0154:                this .dim = dim;
0155:                init();
0156:                dim.setGuiCallback(this );
0157:            }
0158:
0159:            /**
0160:             * Returns the Menubar of this debugger frame.
0161:             */
0162:            public Menubar getMenubar() {
0163:                return menubar;
0164:            }
0165:
0166:            /**
0167:             * Sets the {@link Runnable} that will be run when the "Exit" menu
0168:             * item is chosen.
0169:             */
0170:            public void setExitAction(Runnable r) {
0171:                exitAction = r;
0172:            }
0173:
0174:            /**
0175:             * Returns the debugger console component.
0176:             */
0177:            public JSInternalConsole getConsole() {
0178:                return console;
0179:            }
0180:
0181:            /**
0182:             * Sets the visibility of the debugger GUI.
0183:             */
0184:            public void setVisible(boolean b) {
0185:                super .setVisible(b);
0186:                if (b) {
0187:                    // this needs to be done after the window is visible
0188:                    console.consoleTextArea.requestFocus();
0189:                    context.split.setDividerLocation(0.5);
0190:                    try {
0191:                        console.setMaximum(true);
0192:                        console.setSelected(true);
0193:                        console.show();
0194:                        console.consoleTextArea.requestFocus();
0195:                    } catch (Exception exc) {
0196:                    }
0197:                }
0198:            }
0199:
0200:            /**
0201:             * Records a new internal frame.
0202:             */
0203:            void addTopLevel(String key, JFrame frame) {
0204:                if (frame != this ) {
0205:                    toplevels.put(key, frame);
0206:                }
0207:            }
0208:
0209:            /**
0210:             * Constructs the debugger GUI.
0211:             */
0212:            private void init() {
0213:                menubar = new Menubar(this );
0214:                setJMenuBar(menubar);
0215:                toolBar = new JToolBar();
0216:                JButton button;
0217:                JButton breakButton, goButton, stepIntoButton, stepOverButton, stepOutButton;
0218:                String[] toolTips = { "Break (Pause)", "Go (F5)",
0219:                        "Step Into (F11)", "Step Over (F7)", "Step Out (F8)" };
0220:                int count = 0;
0221:                button = breakButton = new JButton("Break");
0222:                button.setToolTipText("Break");
0223:                button.setActionCommand("Break");
0224:                button.addActionListener(menubar);
0225:                button.setEnabled(true);
0226:                button.setToolTipText(toolTips[count++]);
0227:
0228:                button = goButton = new JButton("Go");
0229:                button.setToolTipText("Go");
0230:                button.setActionCommand("Go");
0231:                button.addActionListener(menubar);
0232:                button.setEnabled(false);
0233:                button.setToolTipText(toolTips[count++]);
0234:
0235:                button = stepIntoButton = new JButton("Step Into");
0236:                button.setToolTipText("Step Into");
0237:                button.setActionCommand("Step Into");
0238:                button.addActionListener(menubar);
0239:                button.setEnabled(false);
0240:                button.setToolTipText(toolTips[count++]);
0241:
0242:                button = stepOverButton = new JButton("Step Over");
0243:                button.setToolTipText("Step Over");
0244:                button.setActionCommand("Step Over");
0245:                button.setEnabled(false);
0246:                button.addActionListener(menubar);
0247:                button.setToolTipText(toolTips[count++]);
0248:
0249:                button = stepOutButton = new JButton("Step Out");
0250:                button.setToolTipText("Step Out");
0251:                button.setActionCommand("Step Out");
0252:                button.setEnabled(false);
0253:                button.addActionListener(menubar);
0254:                button.setToolTipText(toolTips[count++]);
0255:
0256:                Dimension dim = stepOverButton.getPreferredSize();
0257:                breakButton.setPreferredSize(dim);
0258:                breakButton.setMinimumSize(dim);
0259:                breakButton.setMaximumSize(dim);
0260:                breakButton.setSize(dim);
0261:                goButton.setPreferredSize(dim);
0262:                goButton.setMinimumSize(dim);
0263:                goButton.setMaximumSize(dim);
0264:                stepIntoButton.setPreferredSize(dim);
0265:                stepIntoButton.setMinimumSize(dim);
0266:                stepIntoButton.setMaximumSize(dim);
0267:                stepOverButton.setPreferredSize(dim);
0268:                stepOverButton.setMinimumSize(dim);
0269:                stepOverButton.setMaximumSize(dim);
0270:                stepOutButton.setPreferredSize(dim);
0271:                stepOutButton.setMinimumSize(dim);
0272:                stepOutButton.setMaximumSize(dim);
0273:                toolBar.add(breakButton);
0274:                toolBar.add(goButton);
0275:                toolBar.add(stepIntoButton);
0276:                toolBar.add(stepOverButton);
0277:                toolBar.add(stepOutButton);
0278:
0279:                JPanel contentPane = new JPanel();
0280:                contentPane.setLayout(new BorderLayout());
0281:                getContentPane().add(toolBar, BorderLayout.NORTH);
0282:                getContentPane().add(contentPane, BorderLayout.CENTER);
0283:                desk = new JDesktopPane();
0284:                desk.setPreferredSize(new Dimension(600, 300));
0285:                desk.setMinimumSize(new Dimension(150, 50));
0286:                desk.add(console = new JSInternalConsole("JavaScript Console"));
0287:                context = new ContextWindow(this );
0288:                context.setPreferredSize(new Dimension(600, 120));
0289:                context.setMinimumSize(new Dimension(50, 50));
0290:
0291:                split1 = new JSplitPane(JSplitPane.VERTICAL_SPLIT, desk,
0292:                        context);
0293:                split1.setOneTouchExpandable(true);
0294:                SwingGui.setResizeWeight(split1, 0.66);
0295:                contentPane.add(split1, BorderLayout.CENTER);
0296:                statusBar = new JLabel();
0297:                statusBar.setText("Thread: ");
0298:                contentPane.add(statusBar, BorderLayout.SOUTH);
0299:                dlg = new JFileChooser();
0300:
0301:                javax.swing.filechooser.FileFilter filter = new javax.swing.filechooser.FileFilter() {
0302:                    public boolean accept(File f) {
0303:                        if (f.isDirectory()) {
0304:                            return true;
0305:                        }
0306:                        String n = f.getName();
0307:                        int i = n.lastIndexOf('.');
0308:                        if (i > 0 && i < n.length() - 1) {
0309:                            String ext = n.substring(i + 1).toLowerCase();
0310:                            if (ext.equals("js")) {
0311:                                return true;
0312:                            }
0313:                        }
0314:                        return false;
0315:                    }
0316:
0317:                    public String getDescription() {
0318:                        return "JavaScript Files (*.js)";
0319:                    }
0320:                };
0321:                dlg.addChoosableFileFilter(filter);
0322:                addWindowListener(new WindowAdapter() {
0323:                    public void windowClosing(WindowEvent e) {
0324:                        exit();
0325:                    }
0326:                });
0327:            }
0328:
0329:            /**
0330:             * Runs the {@link #exitAction}.
0331:             */
0332:            private void exit() {
0333:                if (exitAction != null) {
0334:                    SwingUtilities.invokeLater(exitAction);
0335:                }
0336:                dim.setReturnValue(Dim.EXIT);
0337:            }
0338:
0339:            /**
0340:             * Returns the {@link FileWindow} for the given URL.
0341:             */
0342:            FileWindow getFileWindow(String url) {
0343:                if (url == null || url.equals("<stdin>")) {
0344:                    return null;
0345:                }
0346:                return (FileWindow) fileWindows.get(url);
0347:            }
0348:
0349:            /**
0350:             * Returns a short version of the given URL.
0351:             */
0352:            static String getShortName(String url) {
0353:                int lastSlash = url.lastIndexOf('/');
0354:                if (lastSlash < 0) {
0355:                    lastSlash = url.lastIndexOf('\\');
0356:                }
0357:                String shortName = url;
0358:                if (lastSlash >= 0 && lastSlash + 1 < url.length()) {
0359:                    shortName = url.substring(lastSlash + 1);
0360:                }
0361:                return shortName;
0362:            }
0363:
0364:            /**
0365:             * Closes the given {@link FileWindow}.
0366:             */
0367:            void removeWindow(FileWindow w) {
0368:                fileWindows.remove(w.getUrl());
0369:                JMenu windowMenu = getWindowMenu();
0370:                int count = windowMenu.getItemCount();
0371:                JMenuItem lastItem = windowMenu.getItem(count - 1);
0372:                String name = getShortName(w.getUrl());
0373:                for (int i = 5; i < count; i++) {
0374:                    JMenuItem item = windowMenu.getItem(i);
0375:                    if (item == null)
0376:                        continue; // separator
0377:                    String text = item.getText();
0378:                    //1 D:\foo.js
0379:                    //2 D:\bar.js
0380:                    int pos = text.indexOf(' ');
0381:                    if (text.substring(pos + 1).equals(name)) {
0382:                        windowMenu.remove(item);
0383:                        // Cascade    [0]
0384:                        // Tile       [1]
0385:                        // -------    [2]
0386:                        // Console    [3]
0387:                        // -------    [4]
0388:                        if (count == 6) {
0389:                            // remove the final separator
0390:                            windowMenu.remove(4);
0391:                        } else {
0392:                            int j = i - 4;
0393:                            for (; i < count - 1; i++) {
0394:                                JMenuItem this Item = windowMenu.getItem(i);
0395:                                if (this Item != null) {
0396:                                    //1 D:\foo.js
0397:                                    //2 D:\bar.js
0398:                                    text = this Item.getText();
0399:                                    if (text.equals("More Windows...")) {
0400:                                        break;
0401:                                    } else {
0402:                                        pos = text.indexOf(' ');
0403:                                        this Item.setText((char) ('0' + j) + " "
0404:                                                + text.substring(pos + 1));
0405:                                        this Item.setMnemonic('0' + j);
0406:                                        j++;
0407:                                    }
0408:                                }
0409:                            }
0410:                            if (count - 6 == 0 && lastItem != item) {
0411:                                if (lastItem.getText()
0412:                                        .equals("More Windows...")) {
0413:                                    windowMenu.remove(lastItem);
0414:                                }
0415:                            }
0416:                        }
0417:                        break;
0418:                    }
0419:                }
0420:                windowMenu.revalidate();
0421:            }
0422:
0423:            /**
0424:             * Shows the line at which execution in the given stack frame just stopped.
0425:             */
0426:            void showStopLine(Dim.StackFrame frame) {
0427:                String sourceName = frame.getUrl();
0428:                if (sourceName == null || sourceName.equals("<stdin>")) {
0429:                    if (console.isVisible()) {
0430:                        console.show();
0431:                    }
0432:                } else {
0433:                    showFileWindow(sourceName, -1);
0434:                    int lineNumber = frame.getLineNumber();
0435:                    FileWindow w = getFileWindow(sourceName);
0436:                    if (w != null) {
0437:                        setFilePosition(w, lineNumber);
0438:                    }
0439:                }
0440:            }
0441:
0442:            /**
0443:             * Shows a {@link FileWindow} for the given source, creating it
0444:             * if it doesn't exist yet. if <code>lineNumber</code> is greater
0445:             * than -1, it indicates the line number to select and display.
0446:             * @param sourceUrl the source URL
0447:             * @param lineNumber the line number to select, or -1
0448:             */
0449:            protected void showFileWindow(String sourceUrl, int lineNumber) {
0450:                FileWindow w = getFileWindow(sourceUrl);
0451:                if (w == null) {
0452:                    Dim.SourceInfo si = dim.sourceInfo(sourceUrl);
0453:                    createFileWindow(si, -1);
0454:                    w = getFileWindow(sourceUrl);
0455:                }
0456:                if (lineNumber > -1) {
0457:                    int start = w.getPosition(lineNumber - 1);
0458:                    int end = w.getPosition(lineNumber) - 1;
0459:                    w.textArea.select(start);
0460:                    w.textArea.setCaretPosition(start);
0461:                    w.textArea.moveCaretPosition(end);
0462:                }
0463:                try {
0464:                    if (w.isIcon()) {
0465:                        w.setIcon(false);
0466:                    }
0467:                    w.setVisible(true);
0468:                    w.moveToFront();
0469:                    w.setSelected(true);
0470:                    requestFocus();
0471:                    w.requestFocus();
0472:                    w.textArea.requestFocus();
0473:                } catch (Exception exc) {
0474:                }
0475:            }
0476:
0477:            /**
0478:             * Creates and shows a new {@link FileWindow} for the given source.
0479:             */
0480:            protected void createFileWindow(Dim.SourceInfo sourceInfo, int line) {
0481:                boolean activate = true;
0482:
0483:                String url = sourceInfo.url();
0484:                FileWindow w = new FileWindow(this , sourceInfo);
0485:                fileWindows.put(url, w);
0486:                if (line != -1) {
0487:                    if (currentWindow != null) {
0488:                        currentWindow.setPosition(-1);
0489:                    }
0490:                    try {
0491:                        w.setPosition(w.textArea.getLineStartOffset(line - 1));
0492:                    } catch (BadLocationException exc) {
0493:                        try {
0494:                            w.setPosition(w.textArea.getLineStartOffset(0));
0495:                        } catch (BadLocationException ee) {
0496:                            w.setPosition(-1);
0497:                        }
0498:                    }
0499:                }
0500:                desk.add(w);
0501:                if (line != -1) {
0502:                    currentWindow = w;
0503:                }
0504:                menubar.addFile(url);
0505:                w.setVisible(true);
0506:
0507:                if (activate) {
0508:                    try {
0509:                        w.setMaximum(true);
0510:                        w.setSelected(true);
0511:                        w.moveToFront();
0512:                    } catch (Exception exc) {
0513:                    }
0514:                }
0515:            }
0516:
0517:            /**
0518:             * Update the source text for <code>sourceInfo</code>. This returns true
0519:             * if a {@link FileWindow} for the given source exists and could be updated.
0520:             * Otherwise, this does nothing and returns false.
0521:             * @param sourceInfo the source info
0522:             * @return true if a {@link FileWindow} for the given source exists
0523:             *              and could be updated, false otherwise.
0524:             */
0525:            protected boolean updateFileWindow(Dim.SourceInfo sourceInfo) {
0526:                String fileName = sourceInfo.url();
0527:                FileWindow w = getFileWindow(fileName);
0528:                if (w != null) {
0529:                    w.updateText(sourceInfo);
0530:                    w.show();
0531:                    return true;
0532:                }
0533:                return false;
0534:            }
0535:
0536:            /**
0537:             * Moves the current position in the given {@link FileWindow} to the
0538:             * given line.
0539:             */
0540:            private void setFilePosition(FileWindow w, int line) {
0541:                boolean activate = true;
0542:                JTextArea ta = w.textArea;
0543:                try {
0544:                    if (line == -1) {
0545:                        w.setPosition(-1);
0546:                        if (currentWindow == w) {
0547:                            currentWindow = null;
0548:                        }
0549:                    } else {
0550:                        int loc = ta.getLineStartOffset(line - 1);
0551:                        if (currentWindow != null && currentWindow != w) {
0552:                            currentWindow.setPosition(-1);
0553:                        }
0554:                        w.setPosition(loc);
0555:                        currentWindow = w;
0556:                    }
0557:                } catch (BadLocationException exc) {
0558:                    // fix me
0559:                }
0560:                if (activate) {
0561:                    if (w.isIcon()) {
0562:                        desk.getDesktopManager().deiconifyFrame(w);
0563:                    }
0564:                    desk.getDesktopManager().activateFrame(w);
0565:                    try {
0566:                        w.show();
0567:                        w.toFront(); // required for correct frame layering (JDK 1.4.1)
0568:                        w.setSelected(true);
0569:                    } catch (Exception exc) {
0570:                    }
0571:                }
0572:            }
0573:
0574:            /**
0575:             * Handles script interruption.
0576:             */
0577:            void enterInterruptImpl(Dim.StackFrame lastFrame,
0578:                    String threadTitle, String alertMessage) {
0579:                statusBar.setText("Thread: " + threadTitle);
0580:
0581:                showStopLine(lastFrame);
0582:
0583:                if (alertMessage != null) {
0584:                    MessageDialogWrapper.showMessageDialog(this , alertMessage,
0585:                            "Exception in Script", JOptionPane.ERROR_MESSAGE);
0586:                }
0587:
0588:                updateEnabled(true);
0589:
0590:                Dim.ContextData contextData = lastFrame.contextData();
0591:
0592:                JComboBox ctx = context.context;
0593:                Vector toolTips = context.toolTips;
0594:                context.disableUpdate();
0595:                int frameCount = contextData.frameCount();
0596:                ctx.removeAllItems();
0597:                // workaround for JDK 1.4 bug that caches selected value even after
0598:                // removeAllItems() is called
0599:                ctx.setSelectedItem(null);
0600:                toolTips.removeAllElements();
0601:                for (int i = 0; i < frameCount; i++) {
0602:                    Dim.StackFrame frame = contextData.getFrame(i);
0603:                    String url = frame.getUrl();
0604:                    int lineNumber = frame.getLineNumber();
0605:                    String shortName = url;
0606:                    if (url.length() > 20) {
0607:                        shortName = "..." + url.substring(url.length() - 17);
0608:                    }
0609:                    String location = "\"" + shortName + "\", line "
0610:                            + lineNumber;
0611:                    ctx.insertItemAt(location, i);
0612:                    location = "\"" + url + "\", line " + lineNumber;
0613:                    toolTips.addElement(location);
0614:                }
0615:                context.enableUpdate();
0616:                ctx.setSelectedIndex(0);
0617:                ctx.setMinimumSize(new Dimension(50,
0618:                        ctx.getMinimumSize().height));
0619:            }
0620:
0621:            /**
0622:             * Returns the 'Window' menu.
0623:             */
0624:            private JMenu getWindowMenu() {
0625:                return menubar.getMenu(3);
0626:            }
0627:
0628:            /**
0629:             * Displays a {@link JFileChooser} and returns the selected filename.
0630:             */
0631:            private String chooseFile(String title) {
0632:                dlg.setDialogTitle(title);
0633:                File CWD = null;
0634:                String dir = SecurityUtilities.getSystemProperty("user.dir");
0635:                if (dir != null) {
0636:                    CWD = new File(dir);
0637:                }
0638:                if (CWD != null) {
0639:                    dlg.setCurrentDirectory(CWD);
0640:                }
0641:                int returnVal = dlg.showOpenDialog(this );
0642:                if (returnVal == JFileChooser.APPROVE_OPTION) {
0643:                    try {
0644:                        String result = dlg.getSelectedFile()
0645:                                .getCanonicalPath();
0646:                        CWD = dlg.getSelectedFile().getParentFile();
0647:                        Properties props = System.getProperties();
0648:                        props.put("user.dir", CWD.getPath());
0649:                        System.setProperties(props);
0650:                        return result;
0651:                    } catch (IOException ignored) {
0652:                    } catch (SecurityException ignored) {
0653:                    }
0654:                }
0655:                return null;
0656:            }
0657:
0658:            /**
0659:             * Returns the current selected internal frame.
0660:             */
0661:            private JInternalFrame getSelectedFrame() {
0662:                JInternalFrame[] frames = desk.getAllFrames();
0663:                for (int i = 0; i < frames.length; i++) {
0664:                    if (frames[i].isShowing()) {
0665:                        return frames[i];
0666:                    }
0667:                }
0668:                return frames[frames.length - 1];
0669:            }
0670:
0671:            /**
0672:             * Enables or disables the menu and tool bars with respect to the
0673:             * state of script execution.
0674:             */
0675:            private void updateEnabled(boolean interrupted) {
0676:                ((Menubar) getJMenuBar()).updateEnabled(interrupted);
0677:                for (int ci = 0, cc = toolBar.getComponentCount(); ci < cc; ci++) {
0678:                    boolean enableButton;
0679:                    if (ci == 0) {
0680:                        // Break
0681:                        enableButton = !interrupted;
0682:                    } else {
0683:                        enableButton = interrupted;
0684:                    }
0685:                    toolBar.getComponent(ci).setEnabled(enableButton);
0686:                }
0687:                if (interrupted) {
0688:                    toolBar.setEnabled(true);
0689:                    // raise the debugger window
0690:                    int state = getExtendedState();
0691:                    if (state == Frame.ICONIFIED) {
0692:                        setExtendedState(Frame.NORMAL);
0693:                    }
0694:                    toFront();
0695:                    context.enable();
0696:                } else {
0697:                    if (currentWindow != null)
0698:                        currentWindow.setPosition(-1);
0699:                    context.disable();
0700:                }
0701:            }
0702:
0703:            /**
0704:             * Calls {@link JSplitPane#setResizeWeight} via reflection.
0705:             * For compatibility, since JDK &lt; 1.3 does not have this method.
0706:             */
0707:            static void setResizeWeight(JSplitPane pane, double weight) {
0708:                try {
0709:                    Method m = JSplitPane.class.getMethod("setResizeWeight",
0710:                            new Class[] { double.class });
0711:                    m.invoke(pane, new Object[] { new Double(weight) });
0712:                } catch (NoSuchMethodException exc) {
0713:                } catch (IllegalAccessException exc) {
0714:                } catch (java.lang.reflect.InvocationTargetException exc) {
0715:                }
0716:            }
0717:
0718:            /**
0719:             * Reads the file with the given name and returns its contents as a String.
0720:             */
0721:            private String readFile(String fileName) {
0722:                String text;
0723:                try {
0724:                    Reader r = new FileReader(fileName);
0725:                    try {
0726:                        text = Kit.readReader(r);
0727:                    } finally {
0728:                        r.close();
0729:                    }
0730:                } catch (IOException ex) {
0731:                    MessageDialogWrapper.showMessageDialog(this , ex
0732:                            .getMessage(), "Error reading " + fileName,
0733:                            JOptionPane.ERROR_MESSAGE);
0734:                    text = null;
0735:                }
0736:                return text;
0737:            }
0738:
0739:            // GuiCallback
0740:
0741:            /**
0742:             * Called when the source text for a script has been updated.
0743:             */
0744:            public void updateSourceText(Dim.SourceInfo sourceInfo) {
0745:                RunProxy proxy = new RunProxy(this , RunProxy.UPDATE_SOURCE_TEXT);
0746:                proxy.sourceInfo = sourceInfo;
0747:                SwingUtilities.invokeLater(proxy);
0748:            }
0749:
0750:            /**
0751:             * Called when the interrupt loop has been entered.
0752:             */
0753:            public void enterInterrupt(Dim.StackFrame lastFrame,
0754:                    String threadTitle, String alertMessage) {
0755:                if (SwingUtilities.isEventDispatchThread()) {
0756:                    enterInterruptImpl(lastFrame, threadTitle, alertMessage);
0757:                } else {
0758:                    RunProxy proxy = new RunProxy(this ,
0759:                            RunProxy.ENTER_INTERRUPT);
0760:                    proxy.lastFrame = lastFrame;
0761:                    proxy.threadTitle = threadTitle;
0762:                    proxy.alertMessage = alertMessage;
0763:                    SwingUtilities.invokeLater(proxy);
0764:                }
0765:            }
0766:
0767:            /**
0768:             * Returns whether the current thread is the GUI event thread.
0769:             */
0770:            public boolean isGuiEventThread() {
0771:                return SwingUtilities.isEventDispatchThread();
0772:            }
0773:
0774:            /**
0775:             * Processes the next GUI event.
0776:             */
0777:            public void dispatchNextGuiEvent() throws InterruptedException {
0778:                EventQueue queue = awtEventQueue;
0779:                if (queue == null) {
0780:                    queue = Toolkit.getDefaultToolkit().getSystemEventQueue();
0781:                    awtEventQueue = queue;
0782:                }
0783:                AWTEvent event = queue.getNextEvent();
0784:                if (event instanceof  ActiveEvent) {
0785:                    ((ActiveEvent) event).dispatch();
0786:                } else {
0787:                    Object source = event.getSource();
0788:                    if (source instanceof  Component) {
0789:                        Component comp = (Component) source;
0790:                        comp.dispatchEvent(event);
0791:                    } else if (source instanceof  MenuComponent) {
0792:                        ((MenuComponent) source).dispatchEvent(event);
0793:                    }
0794:                }
0795:            }
0796:
0797:            // ActionListener
0798:
0799:            /**
0800:             * Performs an action from the menu or toolbar.
0801:             */
0802:            public void actionPerformed(ActionEvent e) {
0803:                String cmd = e.getActionCommand();
0804:                int returnValue = -1;
0805:                if (cmd.equals("Cut") || cmd.equals("Copy")
0806:                        || cmd.equals("Paste")) {
0807:                    JInternalFrame f = getSelectedFrame();
0808:                    if (f != null && f instanceof  ActionListener) {
0809:                        ((ActionListener) f).actionPerformed(e);
0810:                    }
0811:                } else if (cmd.equals("Step Over")) {
0812:                    returnValue = Dim.STEP_OVER;
0813:                } else if (cmd.equals("Step Into")) {
0814:                    returnValue = Dim.STEP_INTO;
0815:                } else if (cmd.equals("Step Out")) {
0816:                    returnValue = Dim.STEP_OUT;
0817:                } else if (cmd.equals("Go")) {
0818:                    returnValue = Dim.GO;
0819:                } else if (cmd.equals("Break")) {
0820:                    dim.setBreak();
0821:                } else if (cmd.equals("Exit")) {
0822:                    exit();
0823:                } else if (cmd.equals("Open")) {
0824:                    String fileName = chooseFile("Select a file to compile");
0825:                    if (fileName != null) {
0826:                        String text = readFile(fileName);
0827:                        if (text != null) {
0828:                            RunProxy proxy = new RunProxy(this ,
0829:                                    RunProxy.OPEN_FILE);
0830:                            proxy.fileName = fileName;
0831:                            proxy.text = text;
0832:                            new Thread(proxy).start();
0833:                        }
0834:                    }
0835:                } else if (cmd.equals("Load")) {
0836:                    String fileName = chooseFile("Select a file to execute");
0837:                    if (fileName != null) {
0838:                        String text = readFile(fileName);
0839:                        if (text != null) {
0840:                            RunProxy proxy = new RunProxy(this ,
0841:                                    RunProxy.LOAD_FILE);
0842:                            proxy.fileName = fileName;
0843:                            proxy.text = text;
0844:                            new Thread(proxy).start();
0845:                        }
0846:                    }
0847:                } else if (cmd.equals("More Windows...")) {
0848:                    MoreWindows dlg = new MoreWindows(this , fileWindows,
0849:                            "Window", "Files");
0850:                    dlg.showDialog(this );
0851:                } else if (cmd.equals("Console")) {
0852:                    if (console.isIcon()) {
0853:                        desk.getDesktopManager().deiconifyFrame(console);
0854:                    }
0855:                    console.show();
0856:                    desk.getDesktopManager().activateFrame(console);
0857:                    console.consoleTextArea.requestFocus();
0858:                } else if (cmd.equals("Cut")) {
0859:                } else if (cmd.equals("Copy")) {
0860:                } else if (cmd.equals("Paste")) {
0861:                } else if (cmd.equals("Go to function...")) {
0862:                    FindFunction dlg = new FindFunction(this , "Go to function",
0863:                            "Function");
0864:                    dlg.showDialog(this );
0865:                } else if (cmd.equals("Tile")) {
0866:                    JInternalFrame[] frames = desk.getAllFrames();
0867:                    int count = frames.length;
0868:                    int rows, cols;
0869:                    rows = cols = (int) Math.sqrt(count);
0870:                    if (rows * cols < count) {
0871:                        cols++;
0872:                        if (rows * cols < count) {
0873:                            rows++;
0874:                        }
0875:                    }
0876:                    Dimension size = desk.getSize();
0877:                    int w = size.width / cols;
0878:                    int h = size.height / rows;
0879:                    int x = 0;
0880:                    int y = 0;
0881:                    for (int i = 0; i < rows; i++) {
0882:                        for (int j = 0; j < cols; j++) {
0883:                            int index = (i * cols) + j;
0884:                            if (index >= frames.length) {
0885:                                break;
0886:                            }
0887:                            JInternalFrame f = frames[index];
0888:                            try {
0889:                                f.setIcon(false);
0890:                                f.setMaximum(false);
0891:                            } catch (Exception exc) {
0892:                            }
0893:                            desk.getDesktopManager().setBoundsForFrame(f, x, y,
0894:                                    w, h);
0895:                            x += w;
0896:                        }
0897:                        y += h;
0898:                        x = 0;
0899:                    }
0900:                } else if (cmd.equals("Cascade")) {
0901:                    JInternalFrame[] frames = desk.getAllFrames();
0902:                    int count = frames.length;
0903:                    int x, y, w, h;
0904:                    x = y = 0;
0905:                    h = desk.getHeight();
0906:                    int d = h / count;
0907:                    if (d > 30)
0908:                        d = 30;
0909:                    for (int i = count - 1; i >= 0; i--, x += d, y += d) {
0910:                        JInternalFrame f = frames[i];
0911:                        try {
0912:                            f.setIcon(false);
0913:                            f.setMaximum(false);
0914:                        } catch (Exception exc) {
0915:                        }
0916:                        Dimension dimen = f.getPreferredSize();
0917:                        w = dimen.width;
0918:                        h = dimen.height;
0919:                        desk.getDesktopManager().setBoundsForFrame(f, x, y, w,
0920:                                h);
0921:                    }
0922:                } else {
0923:                    Object obj = getFileWindow(cmd);
0924:                    if (obj != null) {
0925:                        FileWindow w = (FileWindow) obj;
0926:                        try {
0927:                            if (w.isIcon()) {
0928:                                w.setIcon(false);
0929:                            }
0930:                            w.setVisible(true);
0931:                            w.moveToFront();
0932:                            w.setSelected(true);
0933:                        } catch (Exception exc) {
0934:                        }
0935:                    }
0936:                }
0937:                if (returnValue != -1) {
0938:                    updateEnabled(false);
0939:                    dim.setReturnValue(returnValue);
0940:                }
0941:            }
0942:        }
0943:
0944:        /**
0945:         * Helper class for showing a message dialog.
0946:         */
0947:        class MessageDialogWrapper {
0948:
0949:            /**
0950:             * Shows a message dialog, wrapping the <code>msg</code> at 60
0951:             * columns.
0952:             */
0953:            public static void showMessageDialog(Component parent, String msg,
0954:                    String title, int flags) {
0955:                if (msg.length() > 60) {
0956:                    StringBuffer buf = new StringBuffer();
0957:                    int len = msg.length();
0958:                    int j = 0;
0959:                    int i;
0960:                    for (i = 0; i < len; i++, j++) {
0961:                        char c = msg.charAt(i);
0962:                        buf.append(c);
0963:                        if (Character.isWhitespace(c)) {
0964:                            int k;
0965:                            for (k = i + 1; k < len; k++) {
0966:                                if (Character.isWhitespace(msg.charAt(k))) {
0967:                                    break;
0968:                                }
0969:                            }
0970:                            if (k < len) {
0971:                                int nextWordLen = k - i;
0972:                                if (j + nextWordLen > 60) {
0973:                                    buf.append('\n');
0974:                                    j = 0;
0975:                                }
0976:                            }
0977:                        }
0978:                    }
0979:                    msg = buf.toString();
0980:                }
0981:                JOptionPane.showMessageDialog(parent, msg, title, flags);
0982:            }
0983:        }
0984:
0985:        /**
0986:         * Extension of JTextArea for script evaluation input.
0987:         */
0988:        class EvalTextArea extends JTextArea implements  KeyListener,
0989:                DocumentListener {
0990:
0991:            /**
0992:             * Serializable magic number.
0993:             */
0994:            private static final long serialVersionUID = -3918033649601064194L;
0995:
0996:            /**
0997:             * The debugger GUI.
0998:             */
0999:            private SwingGui debugGui;
1000:
1001:            /**
1002:             * History of expressions that have been evaluated
1003:             */
1004:            private Vector history;
1005:
1006:            /**
1007:             * Index of the selected history item.
1008:             */
1009:            private int historyIndex = -1;
1010:
1011:            /**
1012:             * Position in the display where output should go.
1013:             */
1014:            private int outputMark;
1015:
1016:            /**
1017:             * Creates a new EvalTextArea.
1018:             */
1019:            public EvalTextArea(SwingGui debugGui) {
1020:                this .debugGui = debugGui;
1021:                history = new java.util.Vector();
1022:                Document doc = getDocument();
1023:                doc.addDocumentListener(this );
1024:                addKeyListener(this );
1025:                setLineWrap(true);
1026:                setFont(new Font("Monospaced", 0, 12));
1027:                append("% ");
1028:                outputMark = doc.getLength();
1029:            }
1030:
1031:            /**
1032:             * Selects a subrange of the text.
1033:             */
1034:            public void select(int start, int end) {
1035:                //requestFocus();
1036:                super .select(start, end);
1037:            }
1038:
1039:            /**
1040:             * Called when Enter is pressed.
1041:             */
1042:            private synchronized void returnPressed() {
1043:                Document doc = getDocument();
1044:                int len = doc.getLength();
1045:                Segment segment = new Segment();
1046:                try {
1047:                    doc.getText(outputMark, len - outputMark, segment);
1048:                } catch (javax.swing.text.BadLocationException ignored) {
1049:                    ignored.printStackTrace();
1050:                }
1051:                String text = segment.toString();
1052:                if (debugGui.dim.stringIsCompilableUnit(text)) {
1053:                    if (text.trim().length() > 0) {
1054:                        history.addElement(text);
1055:                        historyIndex = history.size();
1056:                    }
1057:                    append("\n");
1058:                    String result = debugGui.dim.eval(text);
1059:                    if (result.length() > 0) {
1060:                        append(result);
1061:                        append("\n");
1062:                    }
1063:                    append("% ");
1064:                    outputMark = doc.getLength();
1065:                } else {
1066:                    append("\n");
1067:                }
1068:            }
1069:
1070:            /**
1071:             * Writes output into the text area.
1072:             */
1073:            public synchronized void write(String str) {
1074:                insert(str, outputMark);
1075:                int len = str.length();
1076:                outputMark += len;
1077:                select(outputMark, outputMark);
1078:            }
1079:
1080:            // KeyListener
1081:
1082:            /**
1083:             * Called when a key is pressed.
1084:             */
1085:            public void keyPressed(KeyEvent e) {
1086:                int code = e.getKeyCode();
1087:                if (code == KeyEvent.VK_BACK_SPACE || code == KeyEvent.VK_LEFT) {
1088:                    if (outputMark == getCaretPosition()) {
1089:                        e.consume();
1090:                    }
1091:                } else if (code == KeyEvent.VK_HOME) {
1092:                    int caretPos = getCaretPosition();
1093:                    if (caretPos == outputMark) {
1094:                        e.consume();
1095:                    } else if (caretPos > outputMark) {
1096:                        if (!e.isControlDown()) {
1097:                            if (e.isShiftDown()) {
1098:                                moveCaretPosition(outputMark);
1099:                            } else {
1100:                                setCaretPosition(outputMark);
1101:                            }
1102:                            e.consume();
1103:                        }
1104:                    }
1105:                } else if (code == KeyEvent.VK_ENTER) {
1106:                    returnPressed();
1107:                    e.consume();
1108:                } else if (code == KeyEvent.VK_UP) {
1109:                    historyIndex--;
1110:                    if (historyIndex >= 0) {
1111:                        if (historyIndex >= history.size()) {
1112:                            historyIndex = history.size() - 1;
1113:                        }
1114:                        if (historyIndex >= 0) {
1115:                            String str = (String) history
1116:                                    .elementAt(historyIndex);
1117:                            int len = getDocument().getLength();
1118:                            replaceRange(str, outputMark, len);
1119:                            int caretPos = outputMark + str.length();
1120:                            select(caretPos, caretPos);
1121:                        } else {
1122:                            historyIndex++;
1123:                        }
1124:                    } else {
1125:                        historyIndex++;
1126:                    }
1127:                    e.consume();
1128:                } else if (code == KeyEvent.VK_DOWN) {
1129:                    int caretPos = outputMark;
1130:                    if (history.size() > 0) {
1131:                        historyIndex++;
1132:                        if (historyIndex < 0) {
1133:                            historyIndex = 0;
1134:                        }
1135:                        int len = getDocument().getLength();
1136:                        if (historyIndex < history.size()) {
1137:                            String str = (String) history
1138:                                    .elementAt(historyIndex);
1139:                            replaceRange(str, outputMark, len);
1140:                            caretPos = outputMark + str.length();
1141:                        } else {
1142:                            historyIndex = history.size();
1143:                            replaceRange("", outputMark, len);
1144:                        }
1145:                    }
1146:                    select(caretPos, caretPos);
1147:                    e.consume();
1148:                }
1149:            }
1150:
1151:            /**
1152:             * Called when a key is typed.
1153:             */
1154:            public void keyTyped(KeyEvent e) {
1155:                int keyChar = e.getKeyChar();
1156:                if (keyChar == 0x8 /* KeyEvent.VK_BACK_SPACE */) {
1157:                    if (outputMark == getCaretPosition()) {
1158:                        e.consume();
1159:                    }
1160:                } else if (getCaretPosition() < outputMark) {
1161:                    setCaretPosition(outputMark);
1162:                }
1163:            }
1164:
1165:            /**
1166:             * Called when a key is released.
1167:             */
1168:            public synchronized void keyReleased(KeyEvent e) {
1169:            }
1170:
1171:            // DocumentListener
1172:
1173:            /**
1174:             * Called when text was inserted into the text area.
1175:             */
1176:            public synchronized void insertUpdate(DocumentEvent e) {
1177:                int len = e.getLength();
1178:                int off = e.getOffset();
1179:                if (outputMark > off) {
1180:                    outputMark += len;
1181:                }
1182:            }
1183:
1184:            /**
1185:             * Called when text was removed from the text area.
1186:             */
1187:            public synchronized void removeUpdate(DocumentEvent e) {
1188:                int len = e.getLength();
1189:                int off = e.getOffset();
1190:                if (outputMark > off) {
1191:                    if (outputMark >= off + len) {
1192:                        outputMark -= len;
1193:                    } else {
1194:                        outputMark = off;
1195:                    }
1196:                }
1197:            }
1198:
1199:            /**
1200:             * Attempts to clean up the damage done by {@link #updateUI()}.
1201:             */
1202:            public synchronized void postUpdateUI() {
1203:                //requestFocus();
1204:                setCaret(getCaret());
1205:                select(outputMark, outputMark);
1206:            }
1207:
1208:            /**
1209:             * Called when text has changed in the text area.
1210:             */
1211:            public synchronized void changedUpdate(DocumentEvent e) {
1212:            }
1213:        }
1214:
1215:        /**
1216:         * An internal frame for evaluating script.
1217:         */
1218:        class EvalWindow extends JInternalFrame implements  ActionListener {
1219:
1220:            /**
1221:             * Serializable magic number.
1222:             */
1223:            private static final long serialVersionUID = -2860585845212160176L;
1224:
1225:            /**
1226:             * The text area into which expressions can be typed.
1227:             */
1228:            private EvalTextArea evalTextArea;
1229:
1230:            /**
1231:             * Creates a new EvalWindow.
1232:             */
1233:            public EvalWindow(String name, SwingGui debugGui) {
1234:                super (name, true, false, true, true);
1235:                evalTextArea = new EvalTextArea(debugGui);
1236:                evalTextArea.setRows(24);
1237:                evalTextArea.setColumns(80);
1238:                JScrollPane scroller = new JScrollPane(evalTextArea);
1239:                setContentPane(scroller);
1240:                //scroller.setPreferredSize(new Dimension(600, 400));
1241:                pack();
1242:                setVisible(true);
1243:            }
1244:
1245:            /**
1246:             * Sets whether the text area is enabled.
1247:             */
1248:            public void setEnabled(boolean b) {
1249:                super .setEnabled(b);
1250:                evalTextArea.setEnabled(b);
1251:            }
1252:
1253:            // ActionListener
1254:
1255:            /**
1256:             * Performs an action on the text area.
1257:             */
1258:            public void actionPerformed(ActionEvent e) {
1259:                String cmd = e.getActionCommand();
1260:                if (cmd.equals("Cut")) {
1261:                    evalTextArea.cut();
1262:                } else if (cmd.equals("Copy")) {
1263:                    evalTextArea.copy();
1264:                } else if (cmd.equals("Paste")) {
1265:                    evalTextArea.paste();
1266:                }
1267:            }
1268:        }
1269:
1270:        /**
1271:         * Internal frame for the console.
1272:         */
1273:        class JSInternalConsole extends JInternalFrame implements 
1274:                ActionListener {
1275:
1276:            /**
1277:             * Serializable magic number.
1278:             */
1279:            private static final long serialVersionUID = -5523468828771087292L;
1280:
1281:            /**
1282:             * Creates a new JSInternalConsole.
1283:             */
1284:            public JSInternalConsole(String name) {
1285:                super (name, true, false, true, true);
1286:                consoleTextArea = new ConsoleTextArea(null);
1287:                consoleTextArea.setRows(24);
1288:                consoleTextArea.setColumns(80);
1289:                JScrollPane scroller = new JScrollPane(consoleTextArea);
1290:                setContentPane(scroller);
1291:                pack();
1292:                addInternalFrameListener(new InternalFrameAdapter() {
1293:                    public void internalFrameActivated(InternalFrameEvent e) {
1294:                        // hack
1295:                        if (consoleTextArea.hasFocus()) {
1296:                            consoleTextArea.getCaret().setVisible(false);
1297:                            consoleTextArea.getCaret().setVisible(true);
1298:                        }
1299:                    }
1300:                });
1301:            }
1302:
1303:            /**
1304:             * The console text area.
1305:             */
1306:            ConsoleTextArea consoleTextArea;
1307:
1308:            /**
1309:             * Returns the input stream of the console text area.
1310:             */
1311:            public InputStream getIn() {
1312:                return consoleTextArea.getIn();
1313:            }
1314:
1315:            /**
1316:             * Returns the output stream of the console text area.
1317:             */
1318:            public PrintStream getOut() {
1319:                return consoleTextArea.getOut();
1320:            }
1321:
1322:            /**
1323:             * Returns the error stream of the console text area.
1324:             */
1325:            public PrintStream getErr() {
1326:                return consoleTextArea.getErr();
1327:            }
1328:
1329:            // ActionListener
1330:
1331:            /**
1332:             * Performs an action on the text area.
1333:             */
1334:            public void actionPerformed(ActionEvent e) {
1335:                String cmd = e.getActionCommand();
1336:                if (cmd.equals("Cut")) {
1337:                    consoleTextArea.cut();
1338:                } else if (cmd.equals("Copy")) {
1339:                    consoleTextArea.copy();
1340:                } else if (cmd.equals("Paste")) {
1341:                    consoleTextArea.paste();
1342:                }
1343:            }
1344:        }
1345:
1346:        /**
1347:         * Popup menu class for right-clicking on {@link FileTextArea}s.
1348:         */
1349:        class FilePopupMenu extends JPopupMenu {
1350:
1351:            /**
1352:             * Serializable magic number.
1353:             */
1354:            private static final long serialVersionUID = 3589525009546013565L;
1355:
1356:            /**
1357:             * The popup x position.
1358:             */
1359:            int x;
1360:
1361:            /**
1362:             * The popup y position.
1363:             */
1364:            int y;
1365:
1366:            /**
1367:             * Creates a new FilePopupMenu.
1368:             */
1369:            public FilePopupMenu(FileTextArea w) {
1370:                JMenuItem item;
1371:                add(item = new JMenuItem("Set Breakpoint"));
1372:                item.addActionListener(w);
1373:                add(item = new JMenuItem("Clear Breakpoint"));
1374:                item.addActionListener(w);
1375:                add(item = new JMenuItem("Run"));
1376:                item.addActionListener(w);
1377:            }
1378:
1379:            /**
1380:             * Displays the menu at the given coordinates.
1381:             */
1382:            public void show(JComponent comp, int x, int y) {
1383:                this .x = x;
1384:                this .y = y;
1385:                super .show(comp, x, y);
1386:            }
1387:        }
1388:
1389:        /**
1390:         * Text area to display script source.
1391:         */
1392:        class FileTextArea extends JTextArea implements  ActionListener,
1393:                PopupMenuListener, KeyListener, MouseListener {
1394:
1395:            /**
1396:             * Serializable magic number.
1397:             */
1398:            private static final long serialVersionUID = -25032065448563720L;
1399:
1400:            /**
1401:             * The owning {@link FileWindow}.
1402:             */
1403:            private FileWindow w;
1404:
1405:            /**
1406:             * The popup menu.
1407:             */
1408:            private FilePopupMenu popup;
1409:
1410:            /**
1411:             * Creates a new FileTextArea.
1412:             */
1413:            public FileTextArea(FileWindow w) {
1414:                this .w = w;
1415:                popup = new FilePopupMenu(this );
1416:                popup.addPopupMenuListener(this );
1417:                addMouseListener(this );
1418:                addKeyListener(this );
1419:                setFont(new Font("Monospaced", 0, 12));
1420:            }
1421:
1422:            /**
1423:             * Moves the selection to the given offset.
1424:             */
1425:            public void select(int pos) {
1426:                if (pos >= 0) {
1427:                    try {
1428:                        int line = getLineOfOffset(pos);
1429:                        Rectangle rect = modelToView(pos);
1430:                        if (rect == null) {
1431:                            select(pos, pos);
1432:                        } else {
1433:                            try {
1434:                                Rectangle nrect = modelToView(getLineStartOffset(line + 1));
1435:                                if (nrect != null) {
1436:                                    rect = nrect;
1437:                                }
1438:                            } catch (Exception exc) {
1439:                            }
1440:                            JViewport vp = (JViewport) getParent();
1441:                            Rectangle viewRect = vp.getViewRect();
1442:                            if (viewRect.y + viewRect.height > rect.y) {
1443:                                // need to scroll up
1444:                                select(pos, pos);
1445:                            } else {
1446:                                // need to scroll down
1447:                                rect.y += (viewRect.height - rect.height) / 2;
1448:                                scrollRectToVisible(rect);
1449:                                select(pos, pos);
1450:                            }
1451:                        }
1452:                    } catch (BadLocationException exc) {
1453:                        select(pos, pos);
1454:                        //exc.printStackTrace();
1455:                    }
1456:                }
1457:            }
1458:
1459:            /**
1460:             * Checks if the popup menu should be shown.
1461:             */
1462:            private void checkPopup(MouseEvent e) {
1463:                if (e.isPopupTrigger()) {
1464:                    popup.show(this , e.getX(), e.getY());
1465:                }
1466:            }
1467:
1468:            // MouseListener
1469:
1470:            /**
1471:             * Called when a mouse button is pressed.
1472:             */
1473:            public void mousePressed(MouseEvent e) {
1474:                checkPopup(e);
1475:            }
1476:
1477:            /**
1478:             * Called when the mouse is clicked.
1479:             */
1480:            public void mouseClicked(MouseEvent e) {
1481:                checkPopup(e);
1482:                requestFocus();
1483:                getCaret().setVisible(true);
1484:            }
1485:
1486:            /**
1487:             * Called when the mouse enters the component.
1488:             */
1489:            public void mouseEntered(MouseEvent e) {
1490:            }
1491:
1492:            /**
1493:             * Called when the mouse exits the component.
1494:             */
1495:            public void mouseExited(MouseEvent e) {
1496:            }
1497:
1498:            /**
1499:             * Called when a mouse button is released.
1500:             */
1501:            public void mouseReleased(MouseEvent e) {
1502:                checkPopup(e);
1503:            }
1504:
1505:            // PopupMenuListener
1506:
1507:            /**
1508:             * Called before the popup menu will become visible.
1509:             */
1510:            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
1511:            }
1512:
1513:            /**
1514:             * Called before the popup menu will become invisible.
1515:             */
1516:            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
1517:            }
1518:
1519:            /**
1520:             * Called when the popup menu is cancelled.
1521:             */
1522:            public void popupMenuCanceled(PopupMenuEvent e) {
1523:            }
1524:
1525:            // ActionListener
1526:
1527:            /**
1528:             * Performs an action.
1529:             */
1530:            public void actionPerformed(ActionEvent e) {
1531:                int pos = viewToModel(new Point(popup.x, popup.y));
1532:                popup.setVisible(false);
1533:                String cmd = e.getActionCommand();
1534:                int line = -1;
1535:                try {
1536:                    line = getLineOfOffset(pos);
1537:                } catch (Exception exc) {
1538:                }
1539:                if (cmd.equals("Set Breakpoint")) {
1540:                    w.setBreakPoint(line + 1);
1541:                } else if (cmd.equals("Clear Breakpoint")) {
1542:                    w.clearBreakPoint(line + 1);
1543:                } else if (cmd.equals("Run")) {
1544:                    w.load();
1545:                }
1546:            }
1547:
1548:            // KeyListener
1549:
1550:            /**
1551:             * Called when a key is pressed.
1552:             */
1553:            public void keyPressed(KeyEvent e) {
1554:                switch (e.getKeyCode()) {
1555:                case KeyEvent.VK_BACK_SPACE:
1556:                case KeyEvent.VK_ENTER:
1557:                case KeyEvent.VK_DELETE:
1558:                case KeyEvent.VK_TAB:
1559:                    e.consume();
1560:                    break;
1561:                }
1562:            }
1563:
1564:            /**
1565:             * Called when a key is typed.
1566:             */
1567:            public void keyTyped(KeyEvent e) {
1568:                e.consume();
1569:            }
1570:
1571:            /**
1572:             * Called when a key is released.
1573:             */
1574:            public void keyReleased(KeyEvent e) {
1575:                e.consume();
1576:            }
1577:        }
1578:
1579:        /**
1580:         * Dialog to list the available windows.
1581:         */
1582:        class MoreWindows extends JDialog implements  ActionListener {
1583:
1584:            /**
1585:             * Serializable magic number.
1586:             */
1587:            private static final long serialVersionUID = 5177066296457377546L;
1588:
1589:            /**
1590:             * Last selected value.
1591:             */
1592:            private String value;
1593:
1594:            /**
1595:             * The list component.
1596:             */
1597:            private JList list;
1598:
1599:            /**
1600:             * Our parent frame.
1601:             */
1602:            private SwingGui swingGui;
1603:
1604:            /**
1605:             * The "Select" button.
1606:             */
1607:            private JButton setButton;
1608:
1609:            /**
1610:             * The "Cancel" button.
1611:             */
1612:            private JButton cancelButton;
1613:
1614:            /**
1615:             * Creates a new MoreWindows.
1616:             */
1617:            MoreWindows(SwingGui frame, Hashtable fileWindows, String title,
1618:                    String labelText) {
1619:                super (frame, title, true);
1620:                this .swingGui = frame;
1621:                //buttons
1622:                cancelButton = new JButton("Cancel");
1623:                setButton = new JButton("Select");
1624:                cancelButton.addActionListener(this );
1625:                setButton.addActionListener(this );
1626:                getRootPane().setDefaultButton(setButton);
1627:
1628:                //dim part of the dialog
1629:                list = new JList(new DefaultListModel());
1630:                DefaultListModel model = (DefaultListModel) list.getModel();
1631:                model.clear();
1632:                //model.fireIntervalRemoved(model, 0, size);
1633:                Enumeration e = fileWindows.keys();
1634:                while (e.hasMoreElements()) {
1635:                    String data = e.nextElement().toString();
1636:                    model.addElement(data);
1637:                }
1638:                list.setSelectedIndex(0);
1639:                //model.fireIntervalAdded(model, 0, data.length);
1640:                setButton.setEnabled(true);
1641:                list
1642:                        .setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
1643:                list.addMouseListener(new MouseHandler());
1644:                JScrollPane listScroller = new JScrollPane(list);
1645:                listScroller.setPreferredSize(new Dimension(320, 240));
1646:                //XXX: Must do the following, too, or else the scroller thinks
1647:                //XXX: it's taller than it is:
1648:                listScroller.setMinimumSize(new Dimension(250, 80));
1649:                listScroller.setAlignmentX(LEFT_ALIGNMENT);
1650:
1651:                //Create a container so that we can add a title around
1652:                //the scroll pane.  Can't add a title directly to the
1653:                //scroll pane because its background would be white.
1654:                //Lay out the label and scroll pane from top to button.
1655:                JPanel listPane = new JPanel();
1656:                listPane.setLayout(new BoxLayout(listPane, BoxLayout.Y_AXIS));
1657:                JLabel label = new JLabel(labelText);
1658:                label.setLabelFor(list);
1659:                listPane.add(label);
1660:                listPane.add(Box.createRigidArea(new Dimension(0, 5)));
1661:                listPane.add(listScroller);
1662:                listPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10,
1663:                        10));
1664:
1665:                //Lay out the buttons from left to right.
1666:                JPanel buttonPane = new JPanel();
1667:                buttonPane
1668:                        .setLayout(new BoxLayout(buttonPane, BoxLayout.X_AXIS));
1669:                buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10,
1670:                        10));
1671:                buttonPane.add(Box.createHorizontalGlue());
1672:                buttonPane.add(cancelButton);
1673:                buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
1674:                buttonPane.add(setButton);
1675:
1676:                //Put everything together, using the content pane's BorderLayout.
1677:                Container contentPane = getContentPane();
1678:                contentPane.add(listPane, BorderLayout.CENTER);
1679:                contentPane.add(buttonPane, BorderLayout.SOUTH);
1680:                pack();
1681:                addKeyListener(new KeyAdapter() {
1682:                    public void keyPressed(KeyEvent ke) {
1683:                        int code = ke.getKeyCode();
1684:                        if (code == KeyEvent.VK_ESCAPE) {
1685:                            ke.consume();
1686:                            value = null;
1687:                            setVisible(false);
1688:                        }
1689:                    }
1690:                });
1691:            }
1692:
1693:            /**
1694:             * Shows the dialog.
1695:             */
1696:            public String showDialog(Component comp) {
1697:                value = null;
1698:                setLocationRelativeTo(comp);
1699:                setVisible(true);
1700:                return value;
1701:            }
1702:
1703:            // ActionListener
1704:
1705:            /**
1706:             * Performs an action.
1707:             */
1708:            public void actionPerformed(ActionEvent e) {
1709:                String cmd = e.getActionCommand();
1710:                if (cmd.equals("Cancel")) {
1711:                    setVisible(false);
1712:                    value = null;
1713:                } else if (cmd.equals("Select")) {
1714:                    value = (String) list.getSelectedValue();
1715:                    setVisible(false);
1716:                    swingGui.showFileWindow(value, -1);
1717:                }
1718:            }
1719:
1720:            /**
1721:             * MouseListener implementation for {@link #list}.
1722:             */
1723:            private class MouseHandler extends MouseAdapter {
1724:                public void mouseClicked(MouseEvent e) {
1725:                    if (e.getClickCount() == 2) {
1726:                        setButton.doClick();
1727:                    }
1728:                }
1729:            }
1730:        }
1731:
1732:        /**
1733:         * Find function dialog.
1734:         */
1735:        class FindFunction extends JDialog implements  ActionListener {
1736:
1737:            /**
1738:             * Serializable magic number.
1739:             */
1740:            private static final long serialVersionUID = 559491015232880916L;
1741:
1742:            /**
1743:             * Last selected function.
1744:             */
1745:            private String value;
1746:
1747:            /**
1748:             * List of functions.
1749:             */
1750:            private JList list;
1751:
1752:            /**
1753:             * The debug GUI frame.
1754:             */
1755:            private SwingGui debugGui;
1756:
1757:            /**
1758:             * The "Select" button.
1759:             */
1760:            private JButton setButton;
1761:
1762:            /**
1763:             * The "Cancel" button.
1764:             */
1765:            private JButton cancelButton;
1766:
1767:            /**
1768:             * Creates a new FindFunction.
1769:             */
1770:            public FindFunction(SwingGui debugGui, String title,
1771:                    String labelText) {
1772:                super (debugGui, title, true);
1773:                this .debugGui = debugGui;
1774:
1775:                cancelButton = new JButton("Cancel");
1776:                setButton = new JButton("Select");
1777:                cancelButton.addActionListener(this );
1778:                setButton.addActionListener(this );
1779:                getRootPane().setDefaultButton(setButton);
1780:
1781:                list = new JList(new DefaultListModel());
1782:                DefaultListModel model = (DefaultListModel) list.getModel();
1783:                model.clear();
1784:
1785:                String[] a = debugGui.dim.functionNames();
1786:                java.util.Arrays.sort(a);
1787:                for (int i = 0; i < a.length; i++) {
1788:                    model.addElement(a[i]);
1789:                }
1790:                list.setSelectedIndex(0);
1791:
1792:                setButton.setEnabled(a.length > 0);
1793:                list
1794:                        .setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
1795:                list.addMouseListener(new MouseHandler());
1796:                JScrollPane listScroller = new JScrollPane(list);
1797:                listScroller.setPreferredSize(new Dimension(320, 240));
1798:                listScroller.setMinimumSize(new Dimension(250, 80));
1799:                listScroller.setAlignmentX(LEFT_ALIGNMENT);
1800:
1801:                //Create a container so that we can add a title around
1802:                //the scroll pane.  Can't add a title directly to the
1803:                //scroll pane because its background would be white.
1804:                //Lay out the label and scroll pane from top to button.
1805:                JPanel listPane = new JPanel();
1806:                listPane.setLayout(new BoxLayout(listPane, BoxLayout.Y_AXIS));
1807:                JLabel label = new JLabel(labelText);
1808:                label.setLabelFor(list);
1809:                listPane.add(label);
1810:                listPane.add(Box.createRigidArea(new Dimension(0, 5)));
1811:                listPane.add(listScroller);
1812:                listPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10,
1813:                        10));
1814:
1815:                //Lay out the buttons from left to right.
1816:                JPanel buttonPane = new JPanel();
1817:                buttonPane
1818:                        .setLayout(new BoxLayout(buttonPane, BoxLayout.X_AXIS));
1819:                buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10,
1820:                        10));
1821:                buttonPane.add(Box.createHorizontalGlue());
1822:                buttonPane.add(cancelButton);
1823:                buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
1824:                buttonPane.add(setButton);
1825:
1826:                //Put everything together, using the content pane's BorderLayout.
1827:                Container contentPane = getContentPane();
1828:                contentPane.add(listPane, BorderLayout.CENTER);
1829:                contentPane.add(buttonPane, BorderLayout.SOUTH);
1830:                pack();
1831:                addKeyListener(new KeyAdapter() {
1832:                    public void keyPressed(KeyEvent ke) {
1833:                        int code = ke.getKeyCode();
1834:                        if (code == KeyEvent.VK_ESCAPE) {
1835:                            ke.consume();
1836:                            value = null;
1837:                            setVisible(false);
1838:                        }
1839:                    }
1840:                });
1841:            }
1842:
1843:            /**
1844:             * Shows the dialog.
1845:             */
1846:            public String showDialog(Component comp) {
1847:                value = null;
1848:                setLocationRelativeTo(comp);
1849:                setVisible(true);
1850:                return value;
1851:            }
1852:
1853:            // ActionListener
1854:
1855:            /**
1856:             * Performs an action.
1857:             */
1858:            public void actionPerformed(ActionEvent e) {
1859:                String cmd = e.getActionCommand();
1860:                if (cmd.equals("Cancel")) {
1861:                    setVisible(false);
1862:                    value = null;
1863:                } else if (cmd.equals("Select")) {
1864:                    if (list.getSelectedIndex() < 0) {
1865:                        return;
1866:                    }
1867:                    try {
1868:                        value = (String) list.getSelectedValue();
1869:                    } catch (ArrayIndexOutOfBoundsException exc) {
1870:                        return;
1871:                    }
1872:                    setVisible(false);
1873:                    Dim.FunctionSource item = debugGui.dim
1874:                            .functionSourceByName(value);
1875:                    if (item != null) {
1876:                        Dim.SourceInfo si = item.sourceInfo();
1877:                        String url = si.url();
1878:                        int lineNumber = item.firstLine();
1879:                        debugGui.showFileWindow(url, lineNumber);
1880:                    }
1881:                }
1882:            }
1883:
1884:            /**
1885:             * MouseListener implementation for {@link #list}.
1886:             */
1887:            class MouseHandler extends MouseAdapter {
1888:                public void mouseClicked(MouseEvent e) {
1889:                    if (e.getClickCount() == 2) {
1890:                        setButton.doClick();
1891:                    }
1892:                }
1893:            }
1894:        }
1895:
1896:        /**
1897:         * Gutter for FileWindows.
1898:         */
1899:        class FileHeader extends JPanel implements  MouseListener {
1900:
1901:            /**
1902:             * Serializable magic number.
1903:             */
1904:            private static final long serialVersionUID = -2858905404778259127L;
1905:
1906:            /**
1907:             * The line that the mouse was pressed on.
1908:             */
1909:            private int pressLine = -1;
1910:
1911:            /**
1912:             * The owning FileWindow.
1913:             */
1914:            private FileWindow fileWindow;
1915:
1916:            /**
1917:             * Creates a new FileHeader.
1918:             */
1919:            public FileHeader(FileWindow fileWindow) {
1920:                this .fileWindow = fileWindow;
1921:                addMouseListener(this );
1922:                update();
1923:            }
1924:
1925:            /**
1926:             * Updates the gutter.
1927:             */
1928:            public void update() {
1929:                FileTextArea textArea = fileWindow.textArea;
1930:                Font font = textArea.getFont();
1931:                setFont(font);
1932:                FontMetrics metrics = getFontMetrics(font);
1933:                int h = metrics.getHeight();
1934:                int lineCount = textArea.getLineCount() + 1;
1935:                String dummy = Integer.toString(lineCount);
1936:                if (dummy.length() < 2) {
1937:                    dummy = "99";
1938:                }
1939:                Dimension d = new Dimension();
1940:                d.width = metrics.stringWidth(dummy) + 16;
1941:                d.height = lineCount * h + 100;
1942:                setPreferredSize(d);
1943:                setSize(d);
1944:            }
1945:
1946:            /**
1947:             * Paints the component.
1948:             */
1949:            public void paint(Graphics g) {
1950:                super .paint(g);
1951:                FileTextArea textArea = fileWindow.textArea;
1952:                Font font = textArea.getFont();
1953:                g.setFont(font);
1954:                FontMetrics metrics = getFontMetrics(font);
1955:                Rectangle clip = g.getClipBounds();
1956:                g.setColor(getBackground());
1957:                g.fillRect(clip.x, clip.y, clip.width, clip.height);
1958:                int ascent = metrics.getMaxAscent();
1959:                int h = metrics.getHeight();
1960:                int lineCount = textArea.getLineCount() + 1;
1961:                String dummy = Integer.toString(lineCount);
1962:                if (dummy.length() < 2) {
1963:                    dummy = "99";
1964:                }
1965:                int startLine = clip.y / h;
1966:                int endLine = (clip.y + clip.height) / h + 1;
1967:                int width = getWidth();
1968:                if (endLine > lineCount)
1969:                    endLine = lineCount;
1970:                for (int i = startLine; i < endLine; i++) {
1971:                    String text;
1972:                    int pos = -2;
1973:                    try {
1974:                        pos = textArea.getLineStartOffset(i);
1975:                    } catch (BadLocationException ignored) {
1976:                    }
1977:                    boolean isBreakPoint = fileWindow.isBreakPoint(i + 1);
1978:                    text = Integer.toString(i + 1) + " ";
1979:                    int y = i * h;
1980:                    g.setColor(Color.blue);
1981:                    g.drawString(text, 0, y + ascent);
1982:                    int x = width - ascent;
1983:                    if (isBreakPoint) {
1984:                        g.setColor(new Color(0x80, 0x00, 0x00));
1985:                        int dy = y + ascent - 9;
1986:                        g.fillOval(x, dy, 9, 9);
1987:                        g.drawOval(x, dy, 8, 8);
1988:                        g.drawOval(x, dy, 9, 9);
1989:                    }
1990:                    if (pos == fileWindow.currentPos) {
1991:                        Polygon arrow = new Polygon();
1992:                        int dx = x;
1993:                        y += ascent - 10;
1994:                        int dy = y;
1995:                        arrow.addPoint(dx, dy + 3);
1996:                        arrow.addPoint(dx + 5, dy + 3);
1997:                        for (x = dx + 5; x <= dx + 10; x++, y++) {
1998:                            arrow.addPoint(x, y);
1999:                        }
2000:                        for (x = dx + 9; x >= dx + 5; x--, y++) {
2001:                            arrow.addPoint(x, y);
2002:                        }
2003:                        arrow.addPoint(dx + 5, dy + 7);
2004:                        arrow.addPoint(dx, dy + 7);
2005:                        g.setColor(Color.yellow);
2006:                        g.fillPolygon(arrow);
2007:                        g.setColor(Color.black);
2008:                        g.drawPolygon(arrow);
2009:                    }
2010:                }
2011:            }
2012:
2013:            // MouseListener
2014:
2015:            /**
2016:             * Called when the mouse enters the component.
2017:             */
2018:            public void mouseEntered(MouseEvent e) {
2019:            }
2020:
2021:            /**
2022:             * Called when a mouse button is pressed.
2023:             */
2024:            public void mousePressed(MouseEvent e) {
2025:                Font font = fileWindow.textArea.getFont();
2026:                FontMetrics metrics = getFontMetrics(font);
2027:                int h = metrics.getHeight();
2028:                pressLine = e.getY() / h;
2029:            }
2030:
2031:            /**
2032:             * Called when the mouse is clicked.
2033:             */
2034:            public void mouseClicked(MouseEvent e) {
2035:            }
2036:
2037:            /**
2038:             * Called when the mouse exits the component.
2039:             */
2040:            public void mouseExited(MouseEvent e) {
2041:            }
2042:
2043:            /**
2044:             * Called when a mouse button is released.
2045:             */
2046:            public void mouseReleased(MouseEvent e) {
2047:                if (e.getComponent() == this 
2048:                        && (e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0) {
2049:                    int y = e.getY();
2050:                    Font font = fileWindow.textArea.getFont();
2051:                    FontMetrics metrics = getFontMetrics(font);
2052:                    int h = metrics.getHeight();
2053:                    int line = y / h;
2054:                    if (line == pressLine) {
2055:                        fileWindow.toggleBreakPoint(line + 1);
2056:                    } else {
2057:                        pressLine = -1;
2058:                    }
2059:                }
2060:            }
2061:        }
2062:
2063:        /**
2064:         * An internal frame for script files.
2065:         */
2066:        class FileWindow extends JInternalFrame implements  ActionListener {
2067:
2068:            /**
2069:             * Serializable magic number.
2070:             */
2071:            private static final long serialVersionUID = -6212382604952082370L;
2072:
2073:            /**
2074:             * The debugger GUI.
2075:             */
2076:            private SwingGui debugGui;
2077:
2078:            /**
2079:             * The SourceInfo object that describes the file.
2080:             */
2081:            private Dim.SourceInfo sourceInfo;
2082:
2083:            /**
2084:             * The FileTextArea that displays the file.
2085:             */
2086:            FileTextArea textArea;
2087:
2088:            /**
2089:             * The FileHeader that is the gutter for {@link #textArea}.
2090:             */
2091:            private FileHeader fileHeader;
2092:
2093:            /**
2094:             * Scroll pane for containing {@link #textArea}.
2095:             */
2096:            private JScrollPane p;
2097:
2098:            /**
2099:             * The current offset position.
2100:             */
2101:            int currentPos;
2102:
2103:            /**
2104:             * Loads the file.
2105:             */
2106:            void load() {
2107:                String url = getUrl();
2108:                if (url != null) {
2109:                    RunProxy proxy = new RunProxy(debugGui, RunProxy.LOAD_FILE);
2110:                    proxy.fileName = url;
2111:                    proxy.text = sourceInfo.source();
2112:                    new Thread(proxy).start();
2113:                }
2114:            }
2115:
2116:            /**
2117:             * Returns the offset position for the given line.
2118:             */
2119:            public int getPosition(int line) {
2120:                int result = -1;
2121:                try {
2122:                    result = textArea.getLineStartOffset(line);
2123:                } catch (javax.swing.text.BadLocationException exc) {
2124:                }
2125:                return result;
2126:            }
2127:
2128:            /**
2129:             * Returns whether the given line has a breakpoint.
2130:             */
2131:            public boolean isBreakPoint(int line) {
2132:                return sourceInfo.breakableLine(line)
2133:                        && sourceInfo.breakpoint(line);
2134:            }
2135:
2136:            /**
2137:             * Toggles the breakpoint on the given line.
2138:             */
2139:            public void toggleBreakPoint(int line) {
2140:                if (!isBreakPoint(line)) {
2141:                    setBreakPoint(line);
2142:                } else {
2143:                    clearBreakPoint(line);
2144:                }
2145:            }
2146:
2147:            /**
2148:             * Sets a breakpoint on the given line.
2149:             */
2150:            public void setBreakPoint(int line) {
2151:                if (sourceInfo.breakableLine(line)) {
2152:                    boolean changed = sourceInfo.breakpoint(line, true);
2153:                    if (changed) {
2154:                        fileHeader.repaint();
2155:                    }
2156:                }
2157:            }
2158:
2159:            /**
2160:             * Clears a breakpoint from the given line.
2161:             */
2162:            public void clearBreakPoint(int line) {
2163:                if (sourceInfo.breakableLine(line)) {
2164:                    boolean changed = sourceInfo.breakpoint(line, false);
2165:                    if (changed) {
2166:                        fileHeader.repaint();
2167:                    }
2168:                }
2169:            }
2170:
2171:            /**
2172:             * Creates a new FileWindow.
2173:             */
2174:            public FileWindow(SwingGui debugGui, Dim.SourceInfo sourceInfo) {
2175:                super (SwingGui.getShortName(sourceInfo.url()), true, true,
2176:                        true, true);
2177:                this .debugGui = debugGui;
2178:                this .sourceInfo = sourceInfo;
2179:                updateToolTip();
2180:                currentPos = -1;
2181:                textArea = new FileTextArea(this );
2182:                textArea.setRows(24);
2183:                textArea.setColumns(80);
2184:                p = new JScrollPane();
2185:                fileHeader = new FileHeader(this );
2186:                p.setViewportView(textArea);
2187:                p.setRowHeaderView(fileHeader);
2188:                setContentPane(p);
2189:                pack();
2190:                updateText(sourceInfo);
2191:                textArea.select(0);
2192:            }
2193:
2194:            /**
2195:             * Updates the tool tip contents.
2196:             */
2197:            private void updateToolTip() {
2198:                // Try to set tool tip on frame. On Mac OS X 10.5,
2199:                // the number of components is different, so try to be safe.
2200:                int n = getComponentCount() - 1;
2201:                if (n > 1) {
2202:                    n = 1;
2203:                } else if (n < 0) {
2204:                    return;
2205:                }
2206:                Component c = getComponent(n);
2207:                // this will work at least for Metal L&F
2208:                if (c != null && c instanceof  JComponent) {
2209:                    ((JComponent) c).setToolTipText(getUrl());
2210:                }
2211:            }
2212:
2213:            /**
2214:             * Returns the URL of the source.
2215:             */
2216:            public String getUrl() {
2217:                return sourceInfo.url();
2218:            }
2219:
2220:            /**
2221:             * Called when the text of the script has changed.
2222:             */
2223:            public void updateText(Dim.SourceInfo sourceInfo) {
2224:                this .sourceInfo = sourceInfo;
2225:                String newText = sourceInfo.source();
2226:                if (!textArea.getText().equals(newText)) {
2227:                    textArea.setText(newText);
2228:                    int pos = 0;
2229:                    if (currentPos != -1) {
2230:                        pos = currentPos;
2231:                    }
2232:                    textArea.select(pos);
2233:                }
2234:                fileHeader.update();
2235:                fileHeader.repaint();
2236:            }
2237:
2238:            /**
2239:             * Sets the cursor position.
2240:             */
2241:            public void setPosition(int pos) {
2242:                textArea.select(pos);
2243:                currentPos = pos;
2244:                fileHeader.repaint();
2245:            }
2246:
2247:            /**
2248:             * Selects a range of characters.
2249:             */
2250:            public void select(int start, int end) {
2251:                int docEnd = textArea.getDocument().getLength();
2252:                textArea.select(docEnd, docEnd);
2253:                textArea.select(start, end);
2254:            }
2255:
2256:            /**
2257:             * Disposes this FileWindow.
2258:             */
2259:            public void dispose() {
2260:                debugGui.removeWindow(this );
2261:                super .dispose();
2262:            }
2263:
2264:            // ActionListener
2265:
2266:            /**
2267:             * Performs an action.
2268:             */
2269:            public void actionPerformed(ActionEvent e) {
2270:                String cmd = e.getActionCommand();
2271:                if (cmd.equals("Cut")) {
2272:                    // textArea.cut();
2273:                } else if (cmd.equals("Copy")) {
2274:                    textArea.copy();
2275:                } else if (cmd.equals("Paste")) {
2276:                    // textArea.paste();
2277:                }
2278:            }
2279:        }
2280:
2281:        /**
2282:         * Table model class for watched expressions.
2283:         */
2284:        class MyTableModel extends AbstractTableModel {
2285:
2286:            /**
2287:             * Serializable magic number.
2288:             */
2289:            private static final long serialVersionUID = 2971618907207577000L;
2290:
2291:            /**
2292:             * The debugger GUI.
2293:             */
2294:            private SwingGui debugGui;
2295:
2296:            /**
2297:             * Vector of watched expressions.
2298:             */
2299:            private Vector expressions;
2300:
2301:            /**
2302:             * Vector of values from evaluated from {@link #expressions}.
2303:             */
2304:            private Vector values;
2305:
2306:            /**
2307:             * Creates a new MyTableModel.
2308:             */
2309:            public MyTableModel(SwingGui debugGui) {
2310:                this .debugGui = debugGui;
2311:                expressions = new Vector();
2312:                values = new Vector();
2313:                expressions.addElement("");
2314:                values.addElement("");
2315:            }
2316:
2317:            /**
2318:             * Returns the number of columns in the table (2).
2319:             */
2320:            public int getColumnCount() {
2321:                return 2;
2322:            }
2323:
2324:            /**
2325:             * Returns the number of rows in the table.
2326:             */
2327:            public int getRowCount() {
2328:                return expressions.size();
2329:            }
2330:
2331:            /**
2332:             * Returns the name of the given column.
2333:             */
2334:            public String getColumnName(int column) {
2335:                switch (column) {
2336:                case 0:
2337:                    return "Expression";
2338:                case 1:
2339:                    return "Value";
2340:                }
2341:                return null;
2342:            }
2343:
2344:            /**
2345:             * Returns whether the given cell is editable.
2346:             */
2347:            public boolean isCellEditable(int row, int column) {
2348:                return true;
2349:            }
2350:
2351:            /**
2352:             * Returns the value in the given cell.
2353:             */
2354:            public Object getValueAt(int row, int column) {
2355:                switch (column) {
2356:                case 0:
2357:                    return expressions.elementAt(row);
2358:                case 1:
2359:                    return values.elementAt(row);
2360:                }
2361:                return "";
2362:            }
2363:
2364:            /**
2365:             * Sets the value in the given cell.
2366:             */
2367:            public void setValueAt(Object value, int row, int column) {
2368:                switch (column) {
2369:                case 0:
2370:                    String expr = value.toString();
2371:                    expressions.setElementAt(expr, row);
2372:                    String result = "";
2373:                    if (expr.length() > 0) {
2374:                        result = debugGui.dim.eval(expr);
2375:                        if (result == null)
2376:                            result = "";
2377:                    }
2378:                    values.setElementAt(result, row);
2379:                    updateModel();
2380:                    if (row + 1 == expressions.size()) {
2381:                        expressions.addElement("");
2382:                        values.addElement("");
2383:                        fireTableRowsInserted(row + 1, row + 1);
2384:                    }
2385:                    break;
2386:                case 1:
2387:                    // just reset column 2; ignore edits
2388:                    fireTableDataChanged();
2389:                }
2390:            }
2391:
2392:            /**
2393:             * Re-evaluates the expressions in the table.
2394:             */
2395:            void updateModel() {
2396:                for (int i = 0; i < expressions.size(); ++i) {
2397:                    Object value = expressions.elementAt(i);
2398:                    String expr = value.toString();
2399:                    String result = "";
2400:                    if (expr.length() > 0) {
2401:                        result = debugGui.dim.eval(expr);
2402:                        if (result == null)
2403:                            result = "";
2404:                    } else {
2405:                        result = "";
2406:                    }
2407:                    result = result.replace('\n', ' ');
2408:                    values.setElementAt(result, i);
2409:                }
2410:                fireTableDataChanged();
2411:            }
2412:        }
2413:
2414:        /**
2415:         * A table for evaluated expressions.
2416:         */
2417:        class Evaluator extends JTable {
2418:
2419:            /**
2420:             * Serializable magic number.
2421:             */
2422:            private static final long serialVersionUID = 8133672432982594256L;
2423:
2424:            /**
2425:             * The {@link TableModel} for this table.
2426:             */
2427:            MyTableModel tableModel;
2428:
2429:            /**
2430:             * Creates a new Evaluator.
2431:             */
2432:            public Evaluator(SwingGui debugGui) {
2433:                super (new MyTableModel(debugGui));
2434:                tableModel = (MyTableModel) getModel();
2435:            }
2436:        }
2437:
2438:        /**
2439:         * Tree model for script object inspection.
2440:         */
2441:        class VariableModel implements  TreeTableModel {
2442:
2443:            /**
2444:             * Serializable magic number.
2445:             */
2446:            private static final String[] cNames = { " Name", " Value" };
2447:
2448:            /**
2449:             * Tree column types.
2450:             */
2451:            private static final Class[] cTypes = { TreeTableModel.class,
2452:                    String.class };
2453:
2454:            /**
2455:             * Empty {@link VariableNode} array.
2456:             */
2457:            private static final VariableNode[] CHILDLESS = new VariableNode[0];
2458:
2459:            /**
2460:             * The debugger.
2461:             */
2462:            private Dim debugger;
2463:
2464:            /**
2465:             * The root node.
2466:             */
2467:            private VariableNode root;
2468:
2469:            /**
2470:             * Creates a new VariableModel.
2471:             */
2472:            public VariableModel() {
2473:            }
2474:
2475:            /**
2476:             * Creates a new VariableModel.
2477:             */
2478:            public VariableModel(Dim debugger, Object scope) {
2479:                this .debugger = debugger;
2480:                this .root = new VariableNode(scope, "this");
2481:            }
2482:
2483:            // TreeTableModel
2484:
2485:            /**
2486:             * Returns the root node of the tree.
2487:             */
2488:            public Object getRoot() {
2489:                if (debugger == null) {
2490:                    return null;
2491:                }
2492:                return root;
2493:            }
2494:
2495:            /**
2496:             * Returns the number of children of the given node.
2497:             */
2498:            public int getChildCount(Object nodeObj) {
2499:                if (debugger == null) {
2500:                    return 0;
2501:                }
2502:                VariableNode node = (VariableNode) nodeObj;
2503:                return children(node).length;
2504:            }
2505:
2506:            /**
2507:             * Returns a child of the given node.
2508:             */
2509:            public Object getChild(Object nodeObj, int i) {
2510:                if (debugger == null) {
2511:                    return null;
2512:                }
2513:                VariableNode node = (VariableNode) nodeObj;
2514:                return children(node)[i];
2515:            }
2516:
2517:            /**
2518:             * Returns whether the given node is a leaf node.
2519:             */
2520:            public boolean isLeaf(Object nodeObj) {
2521:                if (debugger == null) {
2522:                    return true;
2523:                }
2524:                VariableNode node = (VariableNode) nodeObj;
2525:                return children(node).length == 0;
2526:            }
2527:
2528:            /**
2529:             * Returns the index of a node under its parent.
2530:             */
2531:            public int getIndexOfChild(Object parentObj, Object childObj) {
2532:                if (debugger == null) {
2533:                    return -1;
2534:                }
2535:                VariableNode parent = (VariableNode) parentObj;
2536:                VariableNode child = (VariableNode) childObj;
2537:                VariableNode[] children = children(parent);
2538:                for (int i = 0; i != children.length; i++) {
2539:                    if (children[i] == child) {
2540:                        return i;
2541:                    }
2542:                }
2543:                return -1;
2544:            }
2545:
2546:            /**
2547:             * Returns whether the given cell is editable.
2548:             */
2549:            public boolean isCellEditable(Object node, int column) {
2550:                return column == 0;
2551:            }
2552:
2553:            /**
2554:             * Sets the value at the given cell.
2555:             */
2556:            public void setValueAt(Object value, Object node, int column) {
2557:            }
2558:
2559:            /**
2560:             * Adds a TreeModelListener to this tree.
2561:             */
2562:            public void addTreeModelListener(TreeModelListener l) {
2563:            }
2564:
2565:            /**
2566:             * Removes a TreeModelListener from this tree.
2567:             */
2568:            public void removeTreeModelListener(TreeModelListener l) {
2569:            }
2570:
2571:            public void valueForPathChanged(TreePath path, Object newValue) {
2572:            }
2573:
2574:            // TreeTableNode
2575:
2576:            /**
2577:             * Returns the number of columns.
2578:             */
2579:            public int getColumnCount() {
2580:                return cNames.length;
2581:            }
2582:
2583:            /**
2584:             * Returns the name of the given column.
2585:             */
2586:            public String getColumnName(int column) {
2587:                return cNames[column];
2588:            }
2589:
2590:            /**
2591:             * Returns the type of value stored in the given column.
2592:             */
2593:            public Class getColumnClass(int column) {
2594:                return cTypes[column];
2595:            }
2596:
2597:            /**
2598:             * Returns the value at the given cell.
2599:             */
2600:            public Object getValueAt(Object nodeObj, int column) {
2601:                if (debugger == null) {
2602:                    return null;
2603:                }
2604:                VariableNode node = (VariableNode) nodeObj;
2605:                switch (column) {
2606:                case 0: // Name
2607:                    return node.toString();
2608:                case 1: // Value
2609:                    String result;
2610:                    try {
2611:                        result = debugger.objectToString(getValue(node));
2612:                    } catch (RuntimeException exc) {
2613:                        result = exc.getMessage();
2614:                    }
2615:                    StringBuffer buf = new StringBuffer();
2616:                    int len = result.length();
2617:                    for (int i = 0; i < len; i++) {
2618:                        char ch = result.charAt(i);
2619:                        if (Character.isISOControl(ch)) {
2620:                            ch = ' ';
2621:                        }
2622:                        buf.append(ch);
2623:                    }
2624:                    return buf.toString();
2625:                }
2626:                return null;
2627:            }
2628:
2629:            /**
2630:             * Returns an array of the children of the given node.
2631:             */
2632:            private VariableNode[] children(VariableNode node) {
2633:                if (node.children != null) {
2634:                    return node.children;
2635:                }
2636:
2637:                VariableNode[] children;
2638:
2639:                Object value = getValue(node);
2640:                Object[] ids = debugger.getObjectIds(value);
2641:                if (ids == null || ids.length == 0) {
2642:                    children = CHILDLESS;
2643:                } else {
2644:                    Arrays.sort(ids, new Comparator() {
2645:                        public int compare(Object l, Object r) {
2646:                            if (l instanceof  String) {
2647:                                if (r instanceof  Integer) {
2648:                                    return -1;
2649:                                }
2650:                                return ((String) l)
2651:                                        .compareToIgnoreCase((String) r);
2652:                            } else {
2653:                                if (r instanceof  String) {
2654:                                    return 1;
2655:                                }
2656:                                int lint = ((Integer) l).intValue();
2657:                                int rint = ((Integer) r).intValue();
2658:                                return lint - rint;
2659:                            }
2660:                        }
2661:                    });
2662:                    children = new VariableNode[ids.length];
2663:                    for (int i = 0; i != ids.length; ++i) {
2664:                        children[i] = new VariableNode(value, ids[i]);
2665:                    }
2666:                }
2667:                node.children = children;
2668:                return children;
2669:            }
2670:
2671:            /**
2672:             * Returns the value of the given node.
2673:             */
2674:            public Object getValue(VariableNode node) {
2675:                try {
2676:                    return debugger.getObjectProperty(node.object, node.id);
2677:                } catch (Exception exc) {
2678:                    return "undefined";
2679:                }
2680:            }
2681:
2682:            /**
2683:             * A variable node in the tree.
2684:             */
2685:            private static class VariableNode {
2686:
2687:                /**
2688:                 * The script object.
2689:                 */
2690:                private Object object;
2691:
2692:                /**
2693:                 * The object name.  Either a String or an Integer.
2694:                 */
2695:                private Object id;
2696:
2697:                /**
2698:                 * Array of child nodes.  This is filled with the properties of
2699:                 * the object.
2700:                 */
2701:                private VariableNode[] children;
2702:
2703:                /**
2704:                 * Creates a new VariableNode.
2705:                 */
2706:                public VariableNode(Object object, Object id) {
2707:                    this .object = object;
2708:                    this .id = id;
2709:                }
2710:
2711:                /**
2712:                 * Returns a string representation of this node.
2713:                 */
2714:                public String toString() {
2715:                    return id instanceof  String ? (String) id : "["
2716:                            + ((Integer) id).intValue() + "]";
2717:                }
2718:            }
2719:        }
2720:
2721:        /**
2722:         * A tree table for browsing script objects.
2723:         */
2724:        class MyTreeTable extends JTreeTable {
2725:
2726:            /**
2727:             * Serializable magic number.
2728:             */
2729:            private static final long serialVersionUID = 3457265548184453049L;
2730:
2731:            /**
2732:             * Creates a new MyTreeTable.
2733:             */
2734:            public MyTreeTable(VariableModel model) {
2735:                super (model);
2736:            }
2737:
2738:            /**
2739:             * Initializes a tree for this tree table.
2740:             */
2741:            public JTree resetTree(TreeTableModel treeTableModel) {
2742:                tree = new TreeTableCellRenderer(treeTableModel);
2743:
2744:                // Install a tableModel representing the visible rows in the tree.
2745:                super .setModel(new TreeTableModelAdapter(treeTableModel, tree));
2746:
2747:                // Force the JTable and JTree to share their row selection models.
2748:                ListToTreeSelectionModelWrapper selectionWrapper = new ListToTreeSelectionModelWrapper();
2749:                tree.setSelectionModel(selectionWrapper);
2750:                setSelectionModel(selectionWrapper.getListSelectionModel());
2751:
2752:                // Make the tree and table row heights the same.
2753:                if (tree.getRowHeight() < 1) {
2754:                    // Metal looks better like this.
2755:                    setRowHeight(18);
2756:                }
2757:
2758:                // Install the tree editor renderer and editor.
2759:                setDefaultRenderer(TreeTableModel.class, tree);
2760:                setDefaultEditor(TreeTableModel.class,
2761:                        new TreeTableCellEditor());
2762:                setShowGrid(true);
2763:                setIntercellSpacing(new Dimension(1, 1));
2764:                tree.setRootVisible(false);
2765:                tree.setShowsRootHandles(true);
2766:                DefaultTreeCellRenderer r = (DefaultTreeCellRenderer) tree
2767:                        .getCellRenderer();
2768:                r.setOpenIcon(null);
2769:                r.setClosedIcon(null);
2770:                r.setLeafIcon(null);
2771:                return tree;
2772:            }
2773:
2774:            /**
2775:             * Returns whether the cell under the coordinates of the mouse
2776:             * in the {@link EventObject} is editable.
2777:             */
2778:            public boolean isCellEditable(EventObject e) {
2779:                if (e instanceof  MouseEvent) {
2780:                    MouseEvent me = (MouseEvent) e;
2781:                    // If the modifiers are not 0 (or the left mouse button),
2782:                    // tree may try and toggle the selection, and table
2783:                    // will then try and toggle, resulting in the
2784:                    // selection remaining the same. To avoid this, we
2785:                    // only dispatch when the modifiers are 0 (or the left mouse
2786:                    // button).
2787:                    if (me.getModifiers() == 0
2788:                            || ((me.getModifiers() & (InputEvent.BUTTON1_MASK | 1024)) != 0 && (me
2789:                                    .getModifiers() & (InputEvent.SHIFT_MASK
2790:                                    | InputEvent.CTRL_MASK
2791:                                    | InputEvent.ALT_MASK
2792:                                    | InputEvent.BUTTON2_MASK
2793:                                    | InputEvent.BUTTON3_MASK | 64 | //SHIFT_DOWN_MASK
2794:                                    128 | //CTRL_DOWN_MASK
2795:                                    512 | // ALT_DOWN_MASK
2796:                                    2048 | //BUTTON2_DOWN_MASK
2797:                            4096 //BUTTON3_DOWN_MASK
2798:                            )) == 0)) {
2799:                        int row = rowAtPoint(me.getPoint());
2800:                        for (int counter = getColumnCount() - 1; counter >= 0; counter--) {
2801:                            if (TreeTableModel.class == getColumnClass(counter)) {
2802:                                MouseEvent newME = new MouseEvent(
2803:                                        MyTreeTable.this .tree, me.getID(), me
2804:                                                .getWhen(), me.getModifiers(),
2805:                                        me.getX()
2806:                                                - getCellRect(row, counter,
2807:                                                        true).x, me.getY(), me
2808:                                                .getClickCount(), me
2809:                                                .isPopupTrigger());
2810:                                MyTreeTable.this .tree.dispatchEvent(newME);
2811:                                break;
2812:                            }
2813:                        }
2814:                    }
2815:                    if (me.getClickCount() >= 3) {
2816:                        return true;
2817:                    }
2818:                    return false;
2819:                }
2820:                if (e == null) {
2821:                    return true;
2822:                }
2823:                return false;
2824:            }
2825:        }
2826:
2827:        /**
2828:         * Panel that shows information about the context.
2829:         */
2830:        class ContextWindow extends JPanel implements  ActionListener {
2831:
2832:            /**
2833:             * Serializable magic number.
2834:             */
2835:            private static final long serialVersionUID = 2306040975490228051L;
2836:
2837:            /**
2838:             * The debugger GUI.
2839:             */
2840:            private SwingGui debugGui;
2841:
2842:            /**
2843:             * The combo box that holds the stack frames.
2844:             */
2845:            JComboBox context;
2846:
2847:            /**
2848:             * Tool tips for the stack frames.
2849:             */
2850:            Vector toolTips;
2851:
2852:            /**
2853:             * Tabbed pane for "this" and "locals".
2854:             */
2855:            private JTabbedPane tabs;
2856:
2857:            /**
2858:             * Tabbed pane for "watch" and "evaluate".
2859:             */
2860:            private JTabbedPane tabs2;
2861:
2862:            /**
2863:             * The table showing the "this" object.
2864:             */
2865:            private MyTreeTable this Table;
2866:
2867:            /**
2868:             * The table showing the stack local variables.
2869:             */
2870:            private MyTreeTable localsTable;
2871:
2872:            /**
2873:             * The {@link #evaluator}'s table model.
2874:             */
2875:            private MyTableModel tableModel;
2876:
2877:            /**
2878:             * The script evaluator table.
2879:             */
2880:            private Evaluator evaluator;
2881:
2882:            /**
2883:             * The script evaluation text area.
2884:             */
2885:            private EvalTextArea cmdLine;
2886:
2887:            /**
2888:             * The split pane.
2889:             */
2890:            JSplitPane split;
2891:
2892:            /**
2893:             * Whether the ContextWindow is enabled.
2894:             */
2895:            private boolean enabled;
2896:
2897:            /**
2898:             * Creates a new ContextWindow.
2899:             */
2900:            public ContextWindow(final SwingGui debugGui) {
2901:                this .debugGui = debugGui;
2902:                enabled = false;
2903:                JPanel left = new JPanel();
2904:                JToolBar t1 = new JToolBar();
2905:                t1.setName("Variables");
2906:                t1.setLayout(new GridLayout());
2907:                t1.add(left);
2908:                JPanel p1 = new JPanel();
2909:                p1.setLayout(new GridLayout());
2910:                JPanel p2 = new JPanel();
2911:                p2.setLayout(new GridLayout());
2912:                p1.add(t1);
2913:                JLabel label = new JLabel("Context:");
2914:                context = new JComboBox();
2915:                context.setLightWeightPopupEnabled(false);
2916:                toolTips = new java.util.Vector();
2917:                label.setBorder(context.getBorder());
2918:                context.addActionListener(this );
2919:                context.setActionCommand("ContextSwitch");
2920:                GridBagLayout layout = new GridBagLayout();
2921:                left.setLayout(layout);
2922:                GridBagConstraints lc = new GridBagConstraints();
2923:                lc.insets.left = 5;
2924:                lc.anchor = GridBagConstraints.WEST;
2925:                lc.ipadx = 5;
2926:                layout.setConstraints(label, lc);
2927:                left.add(label);
2928:                GridBagConstraints c = new GridBagConstraints();
2929:                c.gridwidth = GridBagConstraints.REMAINDER;
2930:                c.fill = GridBagConstraints.HORIZONTAL;
2931:                c.anchor = GridBagConstraints.WEST;
2932:                layout.setConstraints(context, c);
2933:                left.add(context);
2934:                tabs = new JTabbedPane(SwingConstants.BOTTOM);
2935:                tabs.setPreferredSize(new Dimension(500, 300));
2936:                this Table = new MyTreeTable(new VariableModel());
2937:                JScrollPane jsp = new JScrollPane(this Table);
2938:                jsp.getViewport().setViewSize(new Dimension(5, 2));
2939:                tabs.add("this", jsp);
2940:                localsTable = new MyTreeTable(new VariableModel());
2941:                localsTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
2942:                localsTable.setPreferredSize(null);
2943:                jsp = new JScrollPane(localsTable);
2944:                tabs.add("Locals", jsp);
2945:                c.weightx = c.weighty = 1;
2946:                c.gridheight = GridBagConstraints.REMAINDER;
2947:                c.fill = GridBagConstraints.BOTH;
2948:                c.anchor = GridBagConstraints.WEST;
2949:                layout.setConstraints(tabs, c);
2950:                left.add(tabs);
2951:                evaluator = new Evaluator(debugGui);
2952:                cmdLine = new EvalTextArea(debugGui);
2953:                //cmdLine.requestFocus();
2954:                tableModel = evaluator.tableModel;
2955:                jsp = new JScrollPane(evaluator);
2956:                JToolBar t2 = new JToolBar();
2957:                t2.setName("Evaluate");
2958:                tabs2 = new JTabbedPane(SwingConstants.BOTTOM);
2959:                tabs2.add("Watch", jsp);
2960:                tabs2.add("Evaluate", new JScrollPane(cmdLine));
2961:                tabs2.setPreferredSize(new Dimension(500, 300));
2962:                t2.setLayout(new GridLayout());
2963:                t2.add(tabs2);
2964:                p2.add(t2);
2965:                evaluator.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
2966:                split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, p1, p2);
2967:                split.setOneTouchExpandable(true);
2968:                SwingGui.setResizeWeight(split, 0.5);
2969:                setLayout(new BorderLayout());
2970:                add(split, BorderLayout.CENTER);
2971:
2972:                final JToolBar finalT1 = t1;
2973:                final JToolBar finalT2 = t2;
2974:                final JPanel finalP1 = p1;
2975:                final JPanel finalP2 = p2;
2976:                final JSplitPane finalSplit = split;
2977:                final JPanel finalThis = this ;
2978:
2979:                ComponentListener clistener = new ComponentListener() {
2980:                    boolean t2Docked = true;
2981:
2982:                    void check(Component comp) {
2983:                        Component this Parent = finalThis.getParent();
2984:                        if (this Parent == null) {
2985:                            return;
2986:                        }
2987:                        Component parent = finalT1.getParent();
2988:                        boolean leftDocked = true;
2989:                        boolean rightDocked = true;
2990:                        boolean adjustVerticalSplit = false;
2991:                        if (parent != null) {
2992:                            if (parent != finalP1) {
2993:                                while (!(parent instanceof  JFrame)) {
2994:                                    parent = parent.getParent();
2995:                                }
2996:                                JFrame frame = (JFrame) parent;
2997:                                debugGui.addTopLevel("Variables", frame);
2998:
2999:                                // We need the following hacks because:
3000:                                // - We want an undocked toolbar to be
3001:                                //   resizable.
3002:                                // - We are using JToolbar as a container of a
3003:                                //   JComboBox. Without this JComboBox's popup
3004:                                //   can get left floating when the toolbar is
3005:                                //   re-docked.
3006:                                //
3007:                                // We make the frame resizable and then
3008:                                // remove JToolbar's window listener
3009:                                // and insert one of our own that first ensures
3010:                                // the JComboBox's popup window is closed
3011:                                // and then calls JToolbar's window listener.
3012:                                if (!frame.isResizable()) {
3013:                                    frame.setResizable(true);
3014:                                    frame
3015:                                            .setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
3016:                                    final EventListener[] l = frame
3017:                                            .getListeners(WindowListener.class);
3018:                                    frame
3019:                                            .removeWindowListener((WindowListener) l[0]);
3020:                                    frame
3021:                                            .addWindowListener(new WindowAdapter() {
3022:                                                public void windowClosing(
3023:                                                        WindowEvent e) {
3024:                                                    context.hidePopup();
3025:                                                    ((WindowListener) l[0])
3026:                                                            .windowClosing(e);
3027:                                                }
3028:                                            });
3029:                                    //adjustVerticalSplit = true;
3030:                                }
3031:                                leftDocked = false;
3032:                            } else {
3033:                                leftDocked = true;
3034:                            }
3035:                        }
3036:                        parent = finalT2.getParent();
3037:                        if (parent != null) {
3038:                            if (parent != finalP2) {
3039:                                while (!(parent instanceof  JFrame)) {
3040:                                    parent = parent.getParent();
3041:                                }
3042:                                JFrame frame = (JFrame) parent;
3043:                                debugGui.addTopLevel("Evaluate", frame);
3044:                                frame.setResizable(true);
3045:                                rightDocked = false;
3046:                            } else {
3047:                                rightDocked = true;
3048:                            }
3049:                        }
3050:                        if (leftDocked && t2Docked && rightDocked && t2Docked) {
3051:                            // no change
3052:                            return;
3053:                        }
3054:                        t2Docked = rightDocked;
3055:                        JSplitPane split = (JSplitPane) this Parent;
3056:                        if (leftDocked) {
3057:                            if (rightDocked) {
3058:                                finalSplit.setDividerLocation(0.5);
3059:                            } else {
3060:                                finalSplit.setDividerLocation(1.0);
3061:                            }
3062:                            if (adjustVerticalSplit) {
3063:                                split.setDividerLocation(0.66);
3064:                            }
3065:
3066:                        } else if (rightDocked) {
3067:                            finalSplit.setDividerLocation(0.0);
3068:                            split.setDividerLocation(0.66);
3069:                        } else {
3070:                            // both undocked
3071:                            split.setDividerLocation(1.0);
3072:                        }
3073:                    }
3074:
3075:                    public void componentHidden(ComponentEvent e) {
3076:                        check(e.getComponent());
3077:                    }
3078:
3079:                    public void componentMoved(ComponentEvent e) {
3080:                        check(e.getComponent());
3081:                    }
3082:
3083:                    public void componentResized(ComponentEvent e) {
3084:                        check(e.getComponent());
3085:                    }
3086:
3087:                    public void componentShown(ComponentEvent e) {
3088:                        check(e.getComponent());
3089:                    }
3090:                };
3091:                p1.addContainerListener(new ContainerListener() {
3092:                    public void componentAdded(ContainerEvent e) {
3093:                        Component this Parent = finalThis.getParent();
3094:                        JSplitPane split = (JSplitPane) this Parent;
3095:                        if (e.getChild() == finalT1) {
3096:                            if (finalT2.getParent() == finalP2) {
3097:                                // both docked
3098:                                finalSplit.setDividerLocation(0.5);
3099:                            } else {
3100:                                // left docked only
3101:                                finalSplit.setDividerLocation(1.0);
3102:                            }
3103:                            split.setDividerLocation(0.66);
3104:                        }
3105:                    }
3106:
3107:                    public void componentRemoved(ContainerEvent e) {
3108:                        Component this Parent = finalThis.getParent();
3109:                        JSplitPane split = (JSplitPane) this Parent;
3110:                        if (e.getChild() == finalT1) {
3111:                            if (finalT2.getParent() == finalP2) {
3112:                                // right docked only
3113:                                finalSplit.setDividerLocation(0.0);
3114:                                split.setDividerLocation(0.66);
3115:                            } else {
3116:                                // both undocked
3117:                                split.setDividerLocation(1.0);
3118:                            }
3119:                        }
3120:                    }
3121:                });
3122:                t1.addComponentListener(clistener);
3123:                t2.addComponentListener(clistener);
3124:                disable();
3125:            }
3126:
3127:            /**
3128:             * Disables the component.
3129:             */
3130:            public void disable() {
3131:                context.setEnabled(false);
3132:                this Table.setEnabled(false);
3133:                localsTable.setEnabled(false);
3134:                evaluator.setEnabled(false);
3135:                cmdLine.setEnabled(false);
3136:            }
3137:
3138:            /**
3139:             * Enables the component.
3140:             */
3141:            public void enable() {
3142:                context.setEnabled(true);
3143:                this Table.setEnabled(true);
3144:                localsTable.setEnabled(true);
3145:                evaluator.setEnabled(true);
3146:                cmdLine.setEnabled(true);
3147:            }
3148:
3149:            /**
3150:             * Disables updating of the component.
3151:             */
3152:            public void disableUpdate() {
3153:                enabled = false;
3154:            }
3155:
3156:            /**
3157:             * Enables updating of the component.
3158:             */
3159:            public void enableUpdate() {
3160:                enabled = true;
3161:            }
3162:
3163:            // ActionListener
3164:
3165:            /**
3166:             * Performs an action.
3167:             */
3168:            public void actionPerformed(ActionEvent e) {
3169:                if (!enabled)
3170:                    return;
3171:                if (e.getActionCommand().equals("ContextSwitch")) {
3172:                    Dim.ContextData contextData = debugGui.dim
3173:                            .currentContextData();
3174:                    if (contextData == null) {
3175:                        return;
3176:                    }
3177:                    int frameIndex = context.getSelectedIndex();
3178:                    context.setToolTipText(toolTips.elementAt(frameIndex)
3179:                            .toString());
3180:                    int frameCount = contextData.frameCount();
3181:                    if (frameIndex >= frameCount) {
3182:                        return;
3183:                    }
3184:                    Dim.StackFrame frame = contextData.getFrame(frameIndex);
3185:                    Object scope = frame.scope();
3186:                    Object this Obj = frame.this Obj();
3187:                    this Table
3188:                            .resetTree(new VariableModel(debugGui.dim, this Obj));
3189:                    VariableModel scopeModel;
3190:                    if (scope != this Obj) {
3191:                        scopeModel = new VariableModel(debugGui.dim, scope);
3192:                    } else {
3193:                        scopeModel = new VariableModel();
3194:                    }
3195:                    localsTable.resetTree(scopeModel);
3196:                    debugGui.dim.contextSwitch(frameIndex);
3197:                    debugGui.showStopLine(frame);
3198:                    tableModel.updateModel();
3199:                }
3200:            }
3201:        }
3202:
3203:        /**
3204:         * The debugger frame menu bar.
3205:         */
3206:        class Menubar extends JMenuBar implements  ActionListener {
3207:
3208:            /**
3209:             * Serializable magic number.
3210:             */
3211:            private static final long serialVersionUID = 3217170497245911461L;
3212:
3213:            /**
3214:             * Items that are enabled only when interrupted.
3215:             */
3216:            private Vector interruptOnlyItems = new Vector();
3217:
3218:            /**
3219:             * Items that are enabled only when running.
3220:             */
3221:            private Vector runOnlyItems = new Vector();
3222:
3223:            /**
3224:             * The debugger GUI.
3225:             */
3226:            private SwingGui debugGui;
3227:
3228:            /**
3229:             * The menu listing the internal frames.
3230:             */
3231:            private JMenu windowMenu;
3232:
3233:            /**
3234:             * The "Break on exceptions" menu item.
3235:             */
3236:            private JCheckBoxMenuItem breakOnExceptions;
3237:
3238:            /**
3239:             * The "Break on enter" menu item.
3240:             */
3241:            private JCheckBoxMenuItem breakOnEnter;
3242:
3243:            /**
3244:             * The "Break on return" menu item.
3245:             */
3246:            private JCheckBoxMenuItem breakOnReturn;
3247:
3248:            /**
3249:             * Creates a new Menubar.
3250:             */
3251:            Menubar(SwingGui debugGui) {
3252:                super ();
3253:                this .debugGui = debugGui;
3254:                String[] fileItems = { "Open...", "Run...", "", "Exit" };
3255:                String[] fileCmds = { "Open", "Load", "", "Exit" };
3256:                char[] fileShortCuts = { '0', 'N', 0, 'X' };
3257:                int[] fileAccelerators = { KeyEvent.VK_O, KeyEvent.VK_N, 0,
3258:                        KeyEvent.VK_Q };
3259:                String[] editItems = { "Cut", "Copy", "Paste",
3260:                        "Go to function..." };
3261:                char[] editShortCuts = { 'T', 'C', 'P', 'F' };
3262:                String[] debugItems = { "Break", "Go", "Step Into",
3263:                        "Step Over", "Step Out" };
3264:                char[] debugShortCuts = { 'B', 'G', 'I', 'O', 'T' };
3265:                String[] plafItems = { "Metal", "Windows", "Motif" };
3266:                char[] plafShortCuts = { 'M', 'W', 'F' };
3267:                int[] debugAccelerators = { KeyEvent.VK_PAUSE, KeyEvent.VK_F5,
3268:                        KeyEvent.VK_F11, KeyEvent.VK_F7, KeyEvent.VK_F8, 0, 0 };
3269:
3270:                JMenu fileMenu = new JMenu("File");
3271:                fileMenu.setMnemonic('F');
3272:                JMenu editMenu = new JMenu("Edit");
3273:                editMenu.setMnemonic('E');
3274:                JMenu plafMenu = new JMenu("Platform");
3275:                plafMenu.setMnemonic('P');
3276:                JMenu debugMenu = new JMenu("Debug");
3277:                debugMenu.setMnemonic('D');
3278:                windowMenu = new JMenu("Window");
3279:                windowMenu.setMnemonic('W');
3280:                for (int i = 0; i < fileItems.length; ++i) {
3281:                    if (fileItems[i].length() == 0) {
3282:                        fileMenu.addSeparator();
3283:                    } else {
3284:                        JMenuItem item = new JMenuItem(fileItems[i],
3285:                                fileShortCuts[i]);
3286:                        item.setActionCommand(fileCmds[i]);
3287:                        item.addActionListener(this );
3288:                        fileMenu.add(item);
3289:                        if (fileAccelerators[i] != 0) {
3290:                            KeyStroke k = KeyStroke.getKeyStroke(
3291:                                    fileAccelerators[i], Event.CTRL_MASK);
3292:                            item.setAccelerator(k);
3293:                        }
3294:                    }
3295:                }
3296:                for (int i = 0; i < editItems.length; ++i) {
3297:                    JMenuItem item = new JMenuItem(editItems[i],
3298:                            editShortCuts[i]);
3299:                    item.addActionListener(this );
3300:                    editMenu.add(item);
3301:                }
3302:                for (int i = 0; i < plafItems.length; ++i) {
3303:                    JMenuItem item = new JMenuItem(plafItems[i],
3304:                            plafShortCuts[i]);
3305:                    item.addActionListener(this );
3306:                    plafMenu.add(item);
3307:                }
3308:                for (int i = 0; i < debugItems.length; ++i) {
3309:                    JMenuItem item = new JMenuItem(debugItems[i],
3310:                            debugShortCuts[i]);
3311:                    item.addActionListener(this );
3312:                    if (debugAccelerators[i] != 0) {
3313:                        KeyStroke k = KeyStroke.getKeyStroke(
3314:                                debugAccelerators[i], 0);
3315:                        item.setAccelerator(k);
3316:                    }
3317:                    if (i != 0) {
3318:                        interruptOnlyItems.add(item);
3319:                    } else {
3320:                        runOnlyItems.add(item);
3321:                    }
3322:                    debugMenu.add(item);
3323:                }
3324:                breakOnExceptions = new JCheckBoxMenuItem("Break on Exceptions");
3325:                breakOnExceptions.setMnemonic('X');
3326:                breakOnExceptions.addActionListener(this );
3327:                breakOnExceptions.setSelected(false);
3328:                debugMenu.add(breakOnExceptions);
3329:
3330:                breakOnEnter = new JCheckBoxMenuItem("Break on Function Enter");
3331:                breakOnEnter.setMnemonic('E');
3332:                breakOnEnter.addActionListener(this );
3333:                breakOnEnter.setSelected(false);
3334:                debugMenu.add(breakOnEnter);
3335:
3336:                breakOnReturn = new JCheckBoxMenuItem(
3337:                        "Break on Function Return");
3338:                breakOnReturn.setMnemonic('R');
3339:                breakOnReturn.addActionListener(this );
3340:                breakOnReturn.setSelected(false);
3341:                debugMenu.add(breakOnReturn);
3342:
3343:                add(fileMenu);
3344:                add(editMenu);
3345:                //add(plafMenu);
3346:                add(debugMenu);
3347:                JMenuItem item;
3348:                windowMenu.add(item = new JMenuItem("Cascade", 'A'));
3349:                item.addActionListener(this );
3350:                windowMenu.add(item = new JMenuItem("Tile", 'T'));
3351:                item.addActionListener(this );
3352:                windowMenu.addSeparator();
3353:                windowMenu.add(item = new JMenuItem("Console", 'C'));
3354:                item.addActionListener(this );
3355:                add(windowMenu);
3356:
3357:                updateEnabled(false);
3358:            }
3359:
3360:            /**
3361:             * Returns the "Break on exceptions" menu item.
3362:             */
3363:            public JCheckBoxMenuItem getBreakOnExceptions() {
3364:                return breakOnExceptions;
3365:            }
3366:
3367:            /**
3368:             * Returns the "Break on enter" menu item.
3369:             */
3370:            public JCheckBoxMenuItem getBreakOnEnter() {
3371:                return breakOnEnter;
3372:            }
3373:
3374:            /**
3375:             * Returns the "Break on return" menu item.
3376:             */
3377:            public JCheckBoxMenuItem getBreakOnReturn() {
3378:                return breakOnReturn;
3379:            }
3380:
3381:            /**
3382:             * Returns the "Debug" menu.
3383:             */
3384:            public JMenu getDebugMenu() {
3385:                return getMenu(2);
3386:            }
3387:
3388:            // ActionListener
3389:
3390:            /**
3391:             * Performs an action.
3392:             */
3393:            public void actionPerformed(ActionEvent e) {
3394:                String cmd = e.getActionCommand();
3395:                String plaf_name = null;
3396:                if (cmd.equals("Metal")) {
3397:                    plaf_name = "javax.swing.plaf.metal.MetalLookAndFeel";
3398:                } else if (cmd.equals("Windows")) {
3399:                    plaf_name = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
3400:                } else if (cmd.equals("Motif")) {
3401:                    plaf_name = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
3402:                } else {
3403:                    Object source = e.getSource();
3404:                    if (source == breakOnExceptions) {
3405:                        debugGui.dim.setBreakOnExceptions(breakOnExceptions
3406:                                .isSelected());
3407:                    } else if (source == breakOnEnter) {
3408:                        debugGui.dim.setBreakOnEnter(breakOnEnter.isSelected());
3409:                    } else if (source == breakOnReturn) {
3410:                        debugGui.dim.setBreakOnReturn(breakOnReturn
3411:                                .isSelected());
3412:                    } else {
3413:                        debugGui.actionPerformed(e);
3414:                    }
3415:                    return;
3416:                }
3417:                try {
3418:                    UIManager.setLookAndFeel(plaf_name);
3419:                    SwingUtilities.updateComponentTreeUI(debugGui);
3420:                    SwingUtilities.updateComponentTreeUI(debugGui.dlg);
3421:                } catch (Exception ignored) {
3422:                    //ignored.printStackTrace();
3423:                }
3424:            }
3425:
3426:            /**
3427:             * Adds a file to the window menu.
3428:             */
3429:            public void addFile(String url) {
3430:                int count = windowMenu.getItemCount();
3431:                JMenuItem item;
3432:                if (count == 4) {
3433:                    windowMenu.addSeparator();
3434:                    count++;
3435:                }
3436:                JMenuItem lastItem = windowMenu.getItem(count - 1);
3437:                boolean hasMoreWin = false;
3438:                int maxWin = 5;
3439:                if (lastItem != null
3440:                        && lastItem.getText().equals("More Windows...")) {
3441:                    hasMoreWin = true;
3442:                    maxWin++;
3443:                }
3444:                if (!hasMoreWin && count - 4 == 5) {
3445:                    windowMenu
3446:                            .add(item = new JMenuItem("More Windows...", 'M'));
3447:                    item.setActionCommand("More Windows...");
3448:                    item.addActionListener(this );
3449:                    return;
3450:                } else if (count - 4 <= maxWin) {
3451:                    if (hasMoreWin) {
3452:                        count--;
3453:                        windowMenu.remove(lastItem);
3454:                    }
3455:                    String shortName = SwingGui.getShortName(url);
3456:
3457:                    windowMenu.add(item = new JMenuItem(
3458:                            (char) ('0' + (count - 4)) + " " + shortName,
3459:                            '0' + (count - 4)));
3460:                    if (hasMoreWin) {
3461:                        windowMenu.add(lastItem);
3462:                    }
3463:                } else {
3464:                    return;
3465:                }
3466:                item.setActionCommand(url);
3467:                item.addActionListener(this );
3468:            }
3469:
3470:            /**
3471:             * Updates the enabledness of menu items.
3472:             */
3473:            public void updateEnabled(boolean interrupted) {
3474:                for (int i = 0; i != interruptOnlyItems.size(); ++i) {
3475:                    JMenuItem item = (JMenuItem) interruptOnlyItems
3476:                            .elementAt(i);
3477:                    item.setEnabled(interrupted);
3478:                }
3479:
3480:                for (int i = 0; i != runOnlyItems.size(); ++i) {
3481:                    JMenuItem item = (JMenuItem) runOnlyItems.elementAt(i);
3482:                    item.setEnabled(!interrupted);
3483:                }
3484:            }
3485:        }
3486:
3487:        /**
3488:         * Class to consolidate all cases that require to implement Runnable
3489:         * to avoid class generation bloat.
3490:         */
3491:        class RunProxy implements  Runnable {
3492:
3493:            // Constants for 'type'.
3494:            static final int OPEN_FILE = 1;
3495:            static final int LOAD_FILE = 2;
3496:            static final int UPDATE_SOURCE_TEXT = 3;
3497:            static final int ENTER_INTERRUPT = 4;
3498:
3499:            /**
3500:             * The debugger GUI.
3501:             */
3502:            private SwingGui debugGui;
3503:
3504:            /**
3505:             * The type of Runnable this object is.  Takes one of the constants
3506:             * defined in this class.
3507:             */
3508:            private int type;
3509:
3510:            /**
3511:             * The name of the file to open or load.
3512:             */
3513:            String fileName;
3514:
3515:            /**
3516:             * The source text to update.
3517:             */
3518:            String text;
3519:
3520:            /**
3521:             * The source for which to update the text.
3522:             */
3523:            Dim.SourceInfo sourceInfo;
3524:
3525:            /**
3526:             * The frame to interrupt in.
3527:             */
3528:            Dim.StackFrame lastFrame;
3529:
3530:            /**
3531:             * The name of the interrupted thread.
3532:             */
3533:            String threadTitle;
3534:
3535:            /**
3536:             * The message of the exception thrown that caused the thread
3537:             * interruption, if any.
3538:             */
3539:            String alertMessage;
3540:
3541:            /**
3542:             * Creates a new RunProxy.
3543:             */
3544:            public RunProxy(SwingGui debugGui, int type) {
3545:                this .debugGui = debugGui;
3546:                this .type = type;
3547:            }
3548:
3549:            /**
3550:             * Runs this Runnable.
3551:             */
3552:            public void run() {
3553:                switch (type) {
3554:                case OPEN_FILE:
3555:                    try {
3556:                        debugGui.dim.compileScript(fileName, text);
3557:                    } catch (RuntimeException ex) {
3558:                        MessageDialogWrapper.showMessageDialog(debugGui, ex
3559:                                .getMessage(), "Error Compiling " + fileName,
3560:                                JOptionPane.ERROR_MESSAGE);
3561:                    }
3562:                    break;
3563:
3564:                case LOAD_FILE:
3565:                    try {
3566:                        debugGui.dim.evalScript(fileName, text);
3567:                    } catch (RuntimeException ex) {
3568:                        MessageDialogWrapper.showMessageDialog(debugGui, ex
3569:                                .getMessage(), "Run error for " + fileName,
3570:                                JOptionPane.ERROR_MESSAGE);
3571:                    }
3572:                    break;
3573:
3574:                case UPDATE_SOURCE_TEXT: {
3575:                    String fileName = sourceInfo.url();
3576:                    if (!debugGui.updateFileWindow(sourceInfo)
3577:                            && !fileName.equals("<stdin>")) {
3578:                        debugGui.createFileWindow(sourceInfo, -1);
3579:                    }
3580:                }
3581:                    break;
3582:
3583:                case ENTER_INTERRUPT:
3584:                    debugGui.enterInterruptImpl(lastFrame, threadTitle,
3585:                            alertMessage);
3586:                    break;
3587:
3588:                default:
3589:                    throw new IllegalArgumentException(String.valueOf(type));
3590:
3591:                }
3592:            }
3593:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.