Clover coverage report - DrJava Test Coverage (drjava-20120304-r5456)
Coverage timestamp: Sun Mar 4 2012 03:13:23 CST
file stats: LOC: 765   Methods: 78
NCLOC: 492   Classes: 10
 
 Source file Conditionals Statements Methods TOTAL
DebugPanel.java 2.6% 47.6% 26.9% 38.9%
coverage coverage
 1    /*BEGIN_COPYRIGHT_BLOCK
 2    *
 3    * Copyright (c) 2001-2010, JavaPLT group at Rice University (drjava@rice.edu)
 4    * All rights reserved.
 5    *
 6    * Redistribution and use in source and binary forms, with or without
 7    * modification, are permitted provided that the following conditions are met:
 8    * * Redistributions of source code must retain the above copyright
 9    * notice, this list of conditions and the following disclaimer.
 10    * * Redistributions in binary form must reproduce the above copyright
 11    * notice, this list of conditions and the following disclaimer in the
 12    * documentation and/or other materials provided with the distribution.
 13    * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
 14    * names of its contributors may be used to endorse or promote products
 15    * derived from this software without specific prior written permission.
 16    *
 17    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18    * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 19    * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 20    * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 21    * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 22    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 23    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 24    * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 25    * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 26    * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 27    * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28    *
 29    * This software is Open Source Initiative approved Open Source Software.
 30    * Open Source Initative Approved is a trademark of the Open Source Initiative.
 31    *
 32    * This file is part of DrJava. Download the current version of this project
 33    * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
 34    *
 35    * END_COPYRIGHT_BLOCK*/
 36   
 37    package edu.rice.cs.drjava.ui;
 38   
 39    import java.util.ArrayList;
 40   
 41    import javax.swing.*;
 42    import javax.swing.table.*;
 43    import java.awt.event.*;
 44    import java.awt.*;
 45   
 46    import edu.rice.cs.drjava.ui.avail.*;
 47    import edu.rice.cs.drjava.model.SingleDisplayModel;
 48    import edu.rice.cs.drjava.model.debug.*;
 49    import edu.rice.cs.drjava.model.OpenDefinitionsDocument;
 50    import edu.rice.cs.drjava.config.*;
 51    import edu.rice.cs.util.swing.Utilities;
 52    import edu.rice.cs.util.swing.RightClickMouseAdapter;
 53   
 54    /**
 55    * Panel for displaying the debugger input and output in MainFrame. This
 56    * class is a swing view class and hence should only be accessed from the
 57    * event-handling thread.
 58    * @version $Id: DebugPanel.java 5333 2010-07-22 21:38:28Z mgricken $
 59    */
 60    public class DebugPanel extends JPanel implements OptionConstants {
 61   
 62    private JSplitPane _tabsPane;
 63    private JTabbedPane _leftPane;
 64    private JTabbedPane _rightPane;
 65    private JPanel _tabsAndStatusPane;
 66   
 67    private JTable _watchTable;
 68    private JTable _stackTable;
 69    private JTable _threadTable;
 70    private long _currentThreadID;
 71   
 72    // private JPopupMenu _threadRunningPopupMenu;
 73    private JPopupMenu _threadSuspendedPopupMenu;
 74    private JPopupMenu _stackPopupMenu;
 75    private JPopupMenu _watchPopupMenu;
 76    private DebugThreadData _threadInPopup;
 77   
 78    private final SingleDisplayModel _model;
 79    private final MainFrame _frame;
 80    private final Debugger _debugger;
 81   
 82    private JPanel _buttonPanel;
 83    private JButton _closeButton;
 84    private JButton _resumeButton;
 85    private JButton _automaticTraceButton;
 86    private JButton _stepIntoButton;
 87    private JButton _stepOverButton;
 88    private JButton _stepOutButton;
 89    private JLabel _statusBar;
 90   
 91    private ArrayList<DebugWatchData> _watches;
 92    private ArrayList<DebugThreadData> _threads;
 93    private ArrayList<DebugStackData> _stackFrames;
 94   
 95    /* The following field is commented out because it was never written (and hence always null). */
 96    // private DefaultTreeCellRenderer dtcr;
 97   
 98    /** Constructs a new panel to display debugging information when the Debugger is active. This is swing view class and hence should only
 99    * be accessed from the event-handling thread.
 100    */
 101  38 public DebugPanel(MainFrame frame) {
 102   
 103  38 this.setLayout(new BorderLayout());
 104   
 105  38 _frame = frame;
 106  38 _model = frame.getModel();
 107  38 _debugger = _model.getDebugger();
 108   
 109  38 _watches = new ArrayList<DebugWatchData>();
 110  38 _threads = new ArrayList<DebugThreadData>();
 111  38 _stackFrames = new ArrayList<DebugStackData>();
 112  38 _leftPane = new JTabbedPane();
 113  38 _rightPane = new JTabbedPane();
 114   
 115  38 _setupTabPanes();
 116   
 117  38 _tabsPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, _leftPane, _rightPane);
 118  38 _tabsPane.setOneTouchExpandable(true);
 119  38 _tabsPane.setDividerLocation((int)(_frame.getWidth()/2.5));
 120   
 121  38 _tabsAndStatusPane = new JPanel(new BorderLayout());
 122  38 _tabsAndStatusPane.add(_tabsPane, BorderLayout.CENTER);
 123   
 124  38 _statusBar = new JLabel("");
 125  38 _statusBar.setForeground(Color.blue.darker());
 126   
 127  38 _tabsAndStatusPane.add(_statusBar, BorderLayout.SOUTH);
 128   
 129  38 this.add(_tabsAndStatusPane, BorderLayout.CENTER);
 130   
 131  38 _buttonPanel = new JPanel(new BorderLayout());
 132  38 _setupButtonPanel();
 133  38 this.add(_buttonPanel, BorderLayout.EAST);
 134   
 135  38 _debugger.addListener(new DebugPanelListener());
 136   
 137    // Setup the color listeners.
 138  38 _setColors(_watchTable);
 139  38 _setColors(_stackTable);
 140  38 _setColors(_threadTable);
 141    }
 142   
 143    /** Quick helper for setting up color listeners. */
 144  114 private static void _setColors(Component c) {
 145  114 new ForegroundColorListener(c);
 146  114 new BackgroundColorListener(c);
 147    }
 148   
 149    /** Causes all display tables to update their information from the debug manager. */
 150  0 public void updateData() {
 151  0 assert EventQueue.isDispatchThread();
 152  0 if (_debugger.isReady()) {
 153  0 try {
 154  0 _watches = _debugger.getWatches();
 155   
 156  0 if (_debugger.isCurrentThreadSuspended()) _stackFrames = _debugger.getCurrentStackFrameData();
 157  0 else _stackFrames = new ArrayList<DebugStackData>();
 158   
 159  0 _threads = _debugger.getCurrentThreadData();
 160    }
 161    catch (DebugException de) {
 162    // Thrown if
 163  0 MainFrameStatics.showDebugError(_frame, de);
 164    }
 165    }
 166    else {
 167    // Clean up if debugger dies
 168  0 _watches = new ArrayList<DebugWatchData>();
 169  0 _threads = new ArrayList<DebugThreadData>();
 170  0 _stackFrames = new ArrayList<DebugStackData>();
 171    }
 172   
 173  0 ((AbstractTableModel)_watchTable.getModel()).fireTableDataChanged();
 174  0 ((AbstractTableModel)_stackTable.getModel()).fireTableDataChanged();
 175  0 ((AbstractTableModel)_threadTable.getModel()).fireTableDataChanged();
 176    }
 177   
 178   
 179    /** Creates the tabbed panes in the debug panel. */
 180  38 private void _setupTabPanes() {
 181   
 182    // Watches table
 183  38 _initWatchTable();
 184   
 185    // Stack table
 186  38 _stackTable = new JTable( new StackTableModel());
 187  38 _stackTable.addMouseListener(new StackMouseAdapter());
 188   
 189  38 _rightPane.addTab("Stack", new JScrollPane(_stackTable));
 190   
 191    // Thread table
 192  38 _initThreadTable();
 193   
 194    // Sets the method column to always be 7 times as wide as the line column
 195  38 TableColumn methodColumn;
 196  38 TableColumn lineColumn;
 197  38 methodColumn = _stackTable.getColumnModel().getColumn(0);
 198  38 lineColumn = _stackTable.getColumnModel().getColumn(1);
 199  38 methodColumn.setPreferredWidth(7*lineColumn.getPreferredWidth());
 200   
 201  38 _initPopup();
 202    }
 203   
 204  38 private void _initWatchTable() {
 205  38 _watchTable = new JTable( new WatchTableModel());
 206  38 _watchTable.setDefaultEditor(_watchTable.getColumnClass(0), new WatchEditor());
 207  38 _watchTable.setDefaultRenderer(_watchTable.getColumnClass(0), new WatchRenderer());
 208   
 209  38 _leftPane.addTab("Watches", new JScrollPane(_watchTable));
 210    }
 211   
 212  38 private void _initThreadTable() {
 213  38 _threadTable = new JTable(new ThreadTableModel());
 214  38 _threadTable.addMouseListener(new ThreadMouseAdapter());
 215  38 _rightPane.addTab("Threads", new JScrollPane(_threadTable));
 216   
 217    // Sets the name column to always be 2 times as wide as the status column
 218  38 TableColumn nameColumn;
 219  38 TableColumn statusColumn;
 220  38 nameColumn = _threadTable.getColumnModel().getColumn(0);
 221  38 statusColumn = _threadTable.getColumnModel().getColumn(1);
 222  38 nameColumn.setPreferredWidth(2*statusColumn.getPreferredWidth());
 223   
 224    // Adds a cell renderer to the threads table
 225  38 _currentThreadID = 0;
 226  38 TableCellRenderer threadTableRenderer = new DefaultTableCellRenderer() {
 227  0 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
 228    boolean hasFocus, int row, int column) {
 229  0 Component renderer =
 230    super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
 231   
 232  0 _setThreadCellFont(row);
 233   
 234  0 return renderer;
 235    }
 236   
 237    /**
 238    * Sets the font for a cell in the thread table.
 239    * @param row the current row
 240    */
 241  0 private void _setThreadCellFont(int row) {
 242  0 DebugThreadData currThread = _threads.get(row);
 243  0 if (currThread.getUniqueID() == _currentThreadID &&
 244    currThread.isSuspended()) {
 245  0 setFont(getFont().deriveFont(Font.BOLD));
 246    }
 247    }
 248    };
 249  38 _threadTable.getColumnModel().getColumn(0).setCellRenderer(threadTableRenderer);
 250  38 _threadTable.getColumnModel().getColumn(1).setCellRenderer(threadTableRenderer);
 251    }
 252   
 253    /** Adds config color support to DefaultCellEditor. */
 254    private static class WatchEditor extends DefaultCellEditor {
 255   
 256  38 WatchEditor() { super(new JTextField()); }
 257   
 258    /**
 259    * Overrides the default editor component to use proper coloring.
 260    */
 261  0 public Component getTableCellEditorComponent
 262    (JTable table, Object value, boolean isSelected, int row, int column) {
 263  0 Component editor = super.getTableCellEditorComponent
 264    (table, value, isSelected, row, column);
 265  0 _setColors(editor);
 266  0 return editor;
 267    }
 268    }
 269   
 270    /** Adds config color support to DefaultTableCellRenderer. */
 271    private class WatchRenderer extends DefaultTableCellRenderer {
 272   
 273    /**
 274    * Overrides the default rederer component to use proper coloring.
 275    */
 276  0 public Component getTableCellRendererComponent
 277    (JTable table, Object value, boolean isSelected, boolean hasFocus,
 278    int row, int column) {
 279  0 Component renderer = super.getTableCellRendererComponent
 280    (table, value, isSelected, hasFocus, row, column);
 281  0 _setColors(renderer);
 282  0 _setWatchCellFont(row);
 283  0 return renderer;
 284    }
 285   
 286    /**
 287    * Sets the font for a cell in the watch table.
 288    * @param row the current row
 289    */
 290  0 private void _setWatchCellFont(int row) {
 291  0 int numWatches = _watches.size();
 292  0 if (row < numWatches) {
 293  0 DebugWatchData currWatch = _watches.get(row);
 294  0 if (currWatch.isChanged()) {
 295  0 setFont(getFont().deriveFont(Font.BOLD));
 296    }
 297    }
 298    }
 299    }
 300   
 301    /** A table for displaying the watched variables and fields. Where is the synchronization for this class? */
 302    public class WatchTableModel extends AbstractTableModel {
 303   
 304    private String[] _columnNames = {"Name", "Value", "Type"};
 305   
 306  114 public String getColumnName(int col) { return _columnNames[col]; }
 307  0 public int getRowCount() { return _watches.size() + 1; }
 308  152 public int getColumnCount() { return _columnNames.length; }
 309  0 public Object getValueAt(int row, int col) {
 310  0 if (row < _watches.size()) {
 311  0 DebugWatchData watch = _watches.get(row);
 312  0 switch(col) {
 313  0 case 0: return watch.getName();
 314  0 case 1: return watch.getValue();
 315  0 case 2: return watch.getType();
 316    }
 317  0 fireTableRowsUpdated(row, _watches.size()-1);
 318  0 return null;
 319    }
 320    else {
 321  0 fireTableRowsUpdated(row, _watches.size()-1);
 322    // Last row blank
 323  0 return "";
 324    }
 325    }
 326  0 public boolean isCellEditable(int row, int col) {
 327    // First col for entering new values
 328  0 if (col == 0) return true;
 329  0 return false;
 330    }
 331  0 public void setValueAt(Object value, int row, int col) {
 332  0 try {
 333  0 if ((value == null) || (value.equals(""))) {
 334    // Remove value
 335  0 _debugger.removeWatch(row);
 336    }
 337    else {
 338  0 if (row < _watches.size())
 339  0 _debugger.removeWatch(row);
 340    // Add value
 341  0 _debugger.addWatch(String.valueOf(value));
 342    }
 343    //fireTableCellUpdated(row, col);
 344  0 fireTableRowsUpdated(row, _watches.size()-1);
 345    }
 346  0 catch (DebugException de) { MainFrameStatics.showDebugError(_frame, de); }
 347    }
 348    }
 349   
 350    /** A table for displaying the current stack trace. */
 351    public class StackTableModel extends AbstractTableModel {
 352   
 353    private String[] _columnNames = {"Method", "Line"}; // Do we need #?
 354   
 355  76 public String getColumnName(int col) { return _columnNames[col]; }
 356   
 357  0 public int getRowCount() {
 358  0 if (_stackFrames == null) return 0;
 359  0 return _stackFrames.size();
 360    }
 361  114 public int getColumnCount() { return _columnNames.length; }
 362   
 363  0 public Object getValueAt(int row, int col) {
 364  0 DebugStackData frame = _stackFrames.get(row);
 365  0 switch(col) {
 366  0 case 0: return frame.getMethod();
 367  0 case 1: return Integer.valueOf(frame.getLine());
 368    }
 369  0 return null;
 370    }
 371  0 public boolean isCellEditable(int row, int col) {
 372  0 return false;
 373    }
 374    }
 375   
 376    /** A table for displaying all current threads. Where is the synchronization for this class? */
 377    public class ThreadTableModel extends AbstractTableModel {
 378   
 379    private String[] _columnNames = {"Name", "Status"};
 380   
 381  76 public String getColumnName(int col) { return _columnNames[col]; }
 382   
 383  0 public int getRowCount() {
 384  0 if (_threads == null) return 0;
 385  0 return _threads.size();
 386    }
 387   
 388  114 public int getColumnCount() {
 389  114 return _columnNames.length;
 390    }
 391   
 392  0 public Object getValueAt(int row, int col) {
 393  0 DebugThreadData threadData = _threads.get(row);
 394  0 switch(col) {
 395  0 case 0: return threadData.getName();
 396  0 case 1: return threadData.getStatus();
 397  0 default: return null;
 398    }
 399   
 400    }
 401   
 402  0 public boolean isCellEditable(int row, int col) { return false; }
 403    }
 404   
 405    /** Creates the buttons for controlling the debugger. */
 406  38 private void _setupButtonPanel() {
 407  38 JPanel mainButtons = new JPanel();
 408  38 JPanel emptyPanel = new JPanel();
 409  38 JPanel closeButtonPanel = new JPanel(new BorderLayout());
 410  38 GridBagLayout gbLayout = new GridBagLayout();
 411  38 GridBagConstraints c = new GridBagConstraints();
 412  38 mainButtons.setLayout(gbLayout);
 413   
 414  38 Action resumeAction = new AbstractAction("Resume") {
 415  0 public void actionPerformed(ActionEvent ae) {
 416  0 try { _frame.debuggerResume(); }
 417  0 catch (DebugException de) { MainFrameStatics.showDebugError(_frame, de); }
 418    }
 419    };
 420  38 _resumeButton = new JButton(resumeAction);
 421  38 _frame._addGUIAvailabilityListener(_resumeButton,
 422    GUIAvailabilityListener.ComponentType.DEBUGGER,
 423    GUIAvailabilityListener.ComponentType.DEBUGGER_SUSPENDED);
 424   
 425  38 Action automaticTrace = new AbstractAction("Automatic Trace") {
 426  0 public void actionPerformed(ActionEvent ae) {
 427  0 _frame.debuggerAutomaticTrace();
 428    }
 429    };
 430  38 _automaticTraceButton = new JButton(automaticTrace);
 431  38 _frame._addGUIAvailabilityListener(_automaticTraceButton,
 432    GUIAvailabilityListener.ComponentType.DEBUGGER,
 433    GUIAvailabilityListener.ComponentType.DEBUGGER_SUSPENDED);
 434   
 435  38 Action stepIntoAction = new AbstractAction("Step Into") {
 436  0 public void actionPerformed(ActionEvent ae) {
 437  0 _frame.debuggerStep(Debugger.StepType.STEP_INTO);
 438    }
 439    };
 440  38 _stepIntoButton = new JButton(stepIntoAction);
 441  38 _frame._addGUIAvailabilityListener(_stepIntoButton,
 442    GUIAvailabilityListener.ComponentType.DEBUGGER,
 443    GUIAvailabilityListener.ComponentType.DEBUGGER_SUSPENDED);
 444   
 445  38 Action stepOverAction = new AbstractAction("Step Over") {
 446  0 public void actionPerformed(ActionEvent ae) {
 447  0 _frame.debuggerStep(Debugger.StepType.STEP_OVER);
 448    }
 449    };
 450  38 _stepOverButton = new JButton(stepOverAction);
 451  38 _frame._addGUIAvailabilityListener(_stepOverButton,
 452    GUIAvailabilityListener.ComponentType.DEBUGGER,
 453    GUIAvailabilityListener.ComponentType.DEBUGGER_SUSPENDED);
 454   
 455  38 Action stepOutAction = new AbstractAction( "Step Out" ) {
 456  0 public void actionPerformed(ActionEvent ae) {
 457  0 _frame.debuggerStep(Debugger.StepType.STEP_OUT);
 458    }
 459    };
 460  38 _stepOutButton = new JButton(stepOutAction);
 461  38 _frame._addGUIAvailabilityListener(_stepOutButton,
 462    GUIAvailabilityListener.ComponentType.DEBUGGER,
 463    GUIAvailabilityListener.ComponentType.DEBUGGER_SUSPENDED);
 464   
 465  38 ActionListener closeListener =
 466    new ActionListener() {
 467  0 public void actionPerformed(ActionEvent ae) {
 468  0 _frame.debuggerToggle();
 469    }
 470    };
 471   
 472  38 _closeButton = new CommonCloseButton(closeListener);
 473   
 474  38 closeButtonPanel.add(_closeButton, BorderLayout.NORTH);
 475  38 mainButtons.add(_resumeButton);
 476  38 mainButtons.add(_automaticTraceButton);
 477  38 mainButtons.add(_stepIntoButton);
 478  38 mainButtons.add(_stepOverButton);
 479  38 mainButtons.add(_stepOutButton);
 480  38 mainButtons.add(emptyPanel);
 481   
 482  38 c.fill = GridBagConstraints.HORIZONTAL;
 483  38 c.anchor = GridBagConstraints.NORTH;
 484  38 c.gridwidth = GridBagConstraints.REMAINDER;
 485  38 c.weightx = 1.0;
 486   
 487  38 gbLayout.setConstraints(_resumeButton, c);
 488  38 gbLayout.setConstraints(_automaticTraceButton, c);
 489  38 gbLayout.setConstraints(_stepIntoButton, c);
 490  38 gbLayout.setConstraints(_stepOverButton, c);
 491  38 gbLayout.setConstraints(_stepOutButton, c);
 492   
 493  38 c.fill = GridBagConstraints.BOTH;
 494  38 c.anchor = GridBagConstraints.SOUTH;
 495  38 c.gridheight = GridBagConstraints.REMAINDER;
 496  38 c.weighty = 1.0;
 497   
 498  38 gbLayout.setConstraints(emptyPanel, c);
 499   
 500  38 updateButtons();
 501  38 _buttonPanel.add(mainButtons, BorderLayout.CENTER);
 502  38 _buttonPanel.add(closeButtonPanel, BorderLayout.EAST);
 503    }
 504   
 505    /** Initializes the pop-up menu that is revealed when the user
 506    * right-clicks on a row in the thread table or stack table.
 507    */
 508  38 private void _initPopup() {
 509    // this is commented out because we do not currently support manual
 510    // suspension of a running thread.
 511    // _threadRunningPopupMenu = new JPopupMenu("Thread Selection");
 512    // JMenuItem threadRunningSuspend = new JMenuItem();
 513    // Action suspendAction = new AbstractAction("Suspend Thread") {
 514    // public void actionPerformed(ActionEvent e) {
 515    // try{
 516    // _debugger.suspend(getSelectedThread());
 517    // }
 518    // catch(DebugException exception) {
 519    // JOptionPane.showMessageDialog(_frame, "Cannot suspend the thread.", "Debugger Error", JOptionPane.ERROR_MESSAGE);
 520    // }
 521    // }
 522    // };
 523    // threadRunningSuspend.setAction(suspendAction);
 524    // _threadRunningPopupMenu.add(threadRunningSuspend);
 525    // threadRunningSuspend.setText("Suspend and Select Thread");
 526   
 527  38 Action selectAction = new AbstractAction("Select Thread") {
 528  0 public void actionPerformed(ActionEvent e) { _selectCurrentThread(); }
 529    };
 530   
 531  38 _threadSuspendedPopupMenu = new JPopupMenu("Thread Selection");
 532  38 _threadSuspendedPopupMenu.add(selectAction);
 533  38 _threadSuspendedPopupMenu.add(new AbstractAction("Resume Thread") {
 534  0 public void actionPerformed(ActionEvent e) {
 535  0 try {
 536  0 if (_threadInPopup.isSuspended()) _debugger.resume(_threadInPopup);
 537    }
 538  0 catch (DebugException dbe) { MainFrameStatics.showDebugError(_frame, dbe); }
 539    }
 540    });
 541   
 542  38 _stackPopupMenu = new JPopupMenu("Stack Selection");
 543  38 _stackPopupMenu.add(new AbstractAction("Scroll to Source") {
 544  0 public void actionPerformed(ActionEvent e) {
 545  0 try {
 546  0 _debugger.scrollToSource(getSelectedStackItem());
 547    }
 548  0 catch (DebugException de) { MainFrameStatics.showDebugError(_frame, de); }
 549    }
 550    });
 551   
 552  38 _watchPopupMenu = new JPopupMenu("Watches");
 553  38 _watchPopupMenu.add(new AbstractAction("Remove Watch") {
 554  0 public void actionPerformed(ActionEvent e) {
 555  0 try {
 556  0 _debugger.removeWatch(_watchTable.getSelectedRow());
 557  0 _watchTable.revalidate();
 558  0 _watchTable.repaint();
 559    }
 560  0 catch (DebugException de) { MainFrameStatics.showDebugError(_frame, de); }
 561    }
 562    });
 563  38 _watchTable.addMouseListener(new DebugTableMouseAdapter(_watchTable) {
 564  0 protected void _showPopup(MouseEvent e) {
 565  0 if (_watchTable.getSelectedRow() < _watchTable.getRowCount() - 1) {
 566  0 _watchPopupMenu.show(e.getComponent(), e.getX(), e.getY());
 567    }
 568    }
 569  0 protected void _action() {
 570    }
 571    });
 572    }
 573   
 574    /**
 575    */
 576  0 private void _selectCurrentThread() {
 577  0 if (_threadInPopup.isSuspended()) {
 578  0 try { _debugger.setCurrentThread(_threadInPopup); }
 579  0 catch(DebugException de) { MainFrameStatics.showDebugError(_frame, de); }
 580    }
 581    }
 582   
 583    /** gets the thread that is currently selected in the thread table
 584    * @return the highlighted thread
 585    */
 586  0 public DebugThreadData getSelectedThread() {
 587  0 int row = _threadTable.getSelectedRow();
 588  0 if (row == -1) {
 589  0 row = 0; // if there is no selected index, just return the first element
 590    }
 591  0 return _threads.get(row);
 592    }
 593   
 594    /** Gets the DebugStackData that is currently selected in the stack table
 595    * @return the highlighted stack element
 596    */
 597  0 public DebugStackData getSelectedStackItem() {
 598  0 return _stackFrames.get(_stackTable.getSelectedRow());
 599    }
 600   
 601    /** @return the selected watch */
 602  0 public DebugWatchData getSelectedWatch() {
 603  0 return _watches.get(_watchTable.getSelectedRow());
 604    }
 605   
 606    /** Listens to events from the debug manager to keep the panel updated. */
 607    class DebugPanelListener implements DebugListener {
 608    /** Called when the current thread is suspended. */
 609  0 public void currThreadSuspended() {
 610    // Only change GUI from event-dispatching thread
 611  0 Utilities.invokeLater(new Runnable() { public void run() { updateData(); } });
 612    }
 613   
 614    /** Called when the current thread is resumed */
 615  0 public void currThreadResumed() {
 616    // Only change GUI from event-dispatching thread
 617  0 Utilities.invokeLater(new Runnable() { public void run() { updateData(); } });
 618    }
 619   
 620    /** Called when a thread starts. Only runs in event thread. */
 621  0 public void threadStarted() { updateData(); }
 622   
 623    /** Called when the current thread dies. Only runs in event thread. */
 624  0 public void currThreadDied() { updateData(); }
 625   
 626    /** Called when any thread other than the current thread dies. Only runs in event thread. */
 627  0 public void nonCurrThreadDied() { updateData(); }
 628   
 629    /** Called when the current (selected) thread is set in the debugger.
 630    * @param thread the thread that was set as current
 631    */
 632  0 public void currThreadSet(DebugThreadData thread) {
 633  0 _currentThreadID = thread.getUniqueID();
 634   
 635    // Only change GUI from event-dispatching thread
 636  0 Utilities.invokeLater(new Runnable() { public void run() { updateData(); } });
 637    }
 638   
 639  0 public void threadLocationUpdated(OpenDefinitionsDocument doc, int lineNumber, boolean shouldHighlight) { }
 640  0 public void debuggerStarted() { }
 641  0 public void debuggerShutdown() { }
 642  0 public void breakpointReached(final Breakpoint bp) { }
 643  0 public void watchSet(final DebugWatchData w) { }
 644  0 public void watchRemoved(final DebugWatchData w) { }
 645  0 public void stepRequested() { }
 646  0 public void regionAdded(Breakpoint r) { }
 647  0 public void regionChanged(Breakpoint r) { }
 648  0 public void regionRemoved(Breakpoint r) { }
 649    }
 650   
 651  38 public void updateButtons() {
 652    // setAutomaticTraceButtonText();
 653    }
 654   
 655    /**Sets the AutomaticTraceButton text as well as the Automatic Trace check box menu item under Debugger based on whether automatic trace is enabled or not*/
 656  38 public void setAutomaticTraceButtonText() {
 657  38 if(_model.getDebugger().isAutomaticTraceEnabled()) {
 658  0 _automaticTraceButton.setText("Disable Trace");
 659    }
 660    else {
 661  38 _automaticTraceButton.setText("Automatic Trace");
 662    }
 663  38 _frame.setAutomaticTraceMenuItemStatus();
 664    }
 665   
 666  12 public void setStatusText(String text) { _statusBar.setText(text); }
 667   
 668  84 public String getStatusText() { return _statusBar.getText(); }
 669   
 670    /** Updates the UI to a new look and feel.
 671    * Need to update the contained popup menus as well.
 672    *
 673    * Currently, we don't support changing the look and feel
 674    * on the fly, so this is disabled.
 675    *
 676    public void updateUI() {
 677    super.updateUI();
 678    if (_threadSuspendedPopupMenu != null) {
 679    SwingUtilities.updateComponentTreeUI(_threadSuspendedPopupMenu);
 680    }
 681    if (_stackPopupMenu != null) {
 682    SwingUtilities.updateComponentTreeUI(_stackPopupMenu);
 683    }
 684    if (_watchPopupMenu != null) {
 685    SwingUtilities.updateComponentTreeUI(_watchPopupMenu);
 686    }
 687    }*/
 688   
 689    /** Concrete DebugTableMouseAdapter for the thread table.
 690    */
 691    private class ThreadMouseAdapter extends DebugTableMouseAdapter {
 692  38 public ThreadMouseAdapter() {
 693  38 super(_threadTable);
 694    }
 695   
 696  0 protected void _showPopup(MouseEvent e) {
 697  0 _threadInPopup = _threads.get(_lastRow);
 698  0 if (_threadInPopup.isSuspended()) {
 699  0 _threadSuspendedPopupMenu.show(e.getComponent(), e.getX(), e.getY());
 700    }
 701    // else {
 702    // _threadRunningPopupMenu.show(e.getComponent(), e.getX(), e.getY());
 703    // }
 704    }
 705   
 706  0 protected void _action() {
 707  0 _threadInPopup = _threads.get(_lastRow);
 708  0 _selectCurrentThread();
 709    }
 710    }
 711   
 712    /** Concrete DebugTableMouseAdapter for the stack table.
 713    */
 714    private class StackMouseAdapter extends DebugTableMouseAdapter {
 715  38 public StackMouseAdapter() {
 716  38 super(_stackTable);
 717    }
 718   
 719  0 protected void _showPopup(MouseEvent e) {
 720  0 _stackPopupMenu.show(e.getComponent(), e.getX(), e.getY());
 721    }
 722   
 723  0 protected void _action() {
 724  0 try {
 725  0 _debugger.scrollToSource(_stackFrames.get(_lastRow));
 726    }
 727    catch (DebugException de) {
 728  0 MainFrameStatics.showDebugError(_frame, de);
 729    }
 730    }
 731    }
 732   
 733    /** A mouse adapter that allows for double-clicking and
 734    * bringing up a right-click menu.
 735    */
 736    private abstract class DebugTableMouseAdapter extends RightClickMouseAdapter {
 737    protected JTable _table;
 738    protected int _lastRow;
 739   
 740  114 public DebugTableMouseAdapter(JTable table) {
 741  114 _table = table;
 742  114 _lastRow = -1;
 743    }
 744   
 745    protected abstract void _showPopup(MouseEvent e);
 746    protected abstract void _action();
 747   
 748  0 protected void _popupAction(MouseEvent e) {
 749  0 _lastRow = _table.rowAtPoint(e.getPoint());
 750  0 _table.setRowSelectionInterval(_lastRow, _lastRow);
 751  0 _showPopup(e);
 752    }
 753   
 754  0 public void mousePressed(MouseEvent e) {
 755  0 super.mousePressed(e);
 756   
 757  0 if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2) {
 758  0 _lastRow = _table.rowAtPoint(e.getPoint());
 759  0 _action();
 760    }
 761    }
 762    }
 763   
 764   
 765    }