1 33 34 package edu.rice.cs.drjava.ui; 35 36 import java.util.Vector ; 37 38 import java.util.Enumeration ; 39 40 import javax.swing.*; 41 import javax.swing.tree.*; 42 import javax.swing.table.*; 43 import java.awt.event.*; 44 import java.awt.*; 45 46 import edu.rice.cs.drjava.model.SingleDisplayModel; 47 import edu.rice.cs.drjava.model.debug.*; 48 import edu.rice.cs.drjava.model.OpenDefinitionsDocument; 49 import edu.rice.cs.drjava.config.*; 50 import edu.rice.cs.util.swing.Utilities; 51 import edu.rice.cs.util.swing.RightClickMouseAdapter; 52 53 59 public class DebugPanel extends JPanel implements OptionConstants { 60 61 private JSplitPane _tabsPane; 62 private JTabbedPane _leftPane; 63 private JTabbedPane _rightPane; 64 private JPanel _tabsAndStatusPane; 65 66 private JTable _watchTable; 67 private JTable _stackTable; 68 private JTable _threadTable; 69 private long _currentThreadID; 70 71 private JPopupMenu _threadSuspendedPopupMenu; 73 private JPopupMenu _stackPopupMenu; 74 private JPopupMenu _watchPopupMenu; 75 private DebugThreadData _threadInPopup; 76 77 private final SingleDisplayModel _model; 78 private final MainFrame _frame; 79 private final Debugger _debugger; 80 81 private JPanel _buttonPanel; 82 private JButton _closeButton; 83 private JButton _resumeButton; 84 private JButton _stepIntoButton; 85 private JButton _stepOverButton; 86 private JButton _stepOutButton; 87 private JLabel _statusBar; 88 89 private Vector <DebugWatchData> _watches; 90 private Vector <DebugThreadData> _threads; 91 private Vector <DebugStackData> _stackFrames; 92 93 private DefaultTreeCellRenderer dtcr; 94 95 98 public DebugPanel(MainFrame frame) { 99 100 this.setLayout(new BorderLayout()); 101 102 _frame = frame; 103 _model = frame.getModel(); 104 _debugger = _model.getDebugger(); 105 106 _watches = new Vector <DebugWatchData>(); 107 _threads = new Vector <DebugThreadData>(); 108 _stackFrames = new Vector <DebugStackData>(); 109 _leftPane = new JTabbedPane(); 110 _rightPane = new JTabbedPane(); 111 112 _setupTabPanes(); 113 114 _tabsPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, _leftPane, _rightPane); 115 _tabsPane.setOneTouchExpandable(true); 116 _tabsPane.setDividerLocation((int)(_frame.getWidth()/2.5)); 117 118 _tabsAndStatusPane = new JPanel(new BorderLayout()); 119 _tabsAndStatusPane.add(_tabsPane, BorderLayout.CENTER); 120 121 _statusBar = new JLabel(""); 122 _statusBar.setForeground(Color.blue.darker()); 123 124 _tabsAndStatusPane.add(_statusBar, BorderLayout.SOUTH); 125 126 this.add(_tabsAndStatusPane, BorderLayout.CENTER); 127 128 _buttonPanel = new JPanel(new BorderLayout()); 129 _setupButtonPanel(); 130 this.add(_buttonPanel, BorderLayout.EAST); 131 132 _debugger.addListener(new DebugPanelListener()); 133 134 _setColors(_watchTable); 136 _setColors(_stackTable); 137 _setColors(_threadTable); 138 } 139 140 141 private static void _setColors(Component c) { 142 new ForegroundColorListener(c); 143 new BackgroundColorListener(c); 144 } 145 146 147 public void updateData() { 148 assert EventQueue.isDispatchThread(); 149 if (_debugger.isReady()) { 150 try { 151 _watches = _debugger.getWatches(); 152 153 if (_debugger.isCurrentThreadSuspended()) _stackFrames = _debugger.getCurrentStackFrameData(); 154 else _stackFrames = new Vector <DebugStackData>(); 155 156 _threads = _debugger.getCurrentThreadData(); 157 } 158 catch (DebugException de) { 159 _frame._showDebugError(de); 161 } 162 } 163 else { 164 _watches = new Vector <DebugWatchData>(); 166 _threads = new Vector <DebugThreadData>(); 167 _stackFrames = new Vector <DebugStackData>(); 168 } 169 170 ((AbstractTableModel)_watchTable.getModel()).fireTableDataChanged(); 171 ((AbstractTableModel)_stackTable.getModel()).fireTableDataChanged(); 172 ((AbstractTableModel)_threadTable.getModel()).fireTableDataChanged(); 173 } 174 175 176 177 private void _setupTabPanes() { 178 179 _initWatchTable(); 181 182 _stackTable = new JTable( new StackTableModel()); 184 _stackTable.addMouseListener(new StackMouseAdapter()); 185 186 _rightPane.addTab("Stack", new JScrollPane(_stackTable)); 187 188 _initThreadTable(); 190 191 TableColumn methodColumn; 193 TableColumn lineColumn; 194 methodColumn = _stackTable.getColumnModel().getColumn(0); 195 lineColumn = _stackTable.getColumnModel().getColumn(1); 196 methodColumn.setPreferredWidth(7*lineColumn.getPreferredWidth()); 197 198 _initPopup(); 199 } 200 201 private void _initWatchTable() { 202 _watchTable = new JTable( new WatchTableModel()); 203 _watchTable.setDefaultEditor(_watchTable.getColumnClass(0), new WatchEditor()); 204 _watchTable.setDefaultRenderer(_watchTable.getColumnClass(0), new WatchRenderer()); 205 206 _leftPane.addTab("Watches", new JScrollPane(_watchTable)); 207 } 208 209 private void _initThreadTable() { 210 _threadTable = new JTable(new ThreadTableModel()); 211 _threadTable.addMouseListener(new ThreadMouseAdapter()); 212 _rightPane.addTab("Threads", new JScrollPane(_threadTable)); 213 214 TableColumn nameColumn; 216 TableColumn statusColumn; 217 nameColumn = _threadTable.getColumnModel().getColumn(0); 218 statusColumn = _threadTable.getColumnModel().getColumn(1); 219 nameColumn.setPreferredWidth(2*statusColumn.getPreferredWidth()); 220 221 _currentThreadID = 0; 223 TableCellRenderer threadTableRenderer = new DefaultTableCellRenderer() { 224 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, 225 boolean hasFocus, int row, int column) { 226 Component renderer = 227 super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); 228 229 _setThreadCellFont(row); 230 231 return renderer; 232 } 233 234 238 private void _setThreadCellFont(int row) { 239 DebugThreadData currThread = _threads.get(row); 240 if (currThread.getUniqueID() == _currentThreadID && 241 currThread.isSuspended()) { 242 setFont(getFont().deriveFont(Font.BOLD)); 243 } 244 } 245 }; 246 _threadTable.getColumnModel().getColumn(0).setCellRenderer(threadTableRenderer); 247 _threadTable.getColumnModel().getColumn(1).setCellRenderer(threadTableRenderer); 248 } 249 250 251 private static class WatchEditor extends DefaultCellEditor { 252 253 WatchEditor() { super(new JTextField()); } 254 255 258 public Component getTableCellEditorComponent 259 (JTable table, Object value, boolean isSelected, int row, int column) { 260 Component editor = super.getTableCellEditorComponent 261 (table, value, isSelected, row, column); 262 _setColors(editor); 263 return editor; 264 } 265 } 266 267 268 private class WatchRenderer extends DefaultTableCellRenderer { 269 270 273 public Component getTableCellRendererComponent 274 (JTable table, Object value, boolean isSelected, boolean hasFocus, 275 int row, int column) { 276 Component renderer = super.getTableCellRendererComponent 277 (table, value, isSelected, hasFocus, row, column); 278 _setColors(renderer); 279 _setWatchCellFont(row); 280 return renderer; 281 } 282 283 287 private void _setWatchCellFont(int row) { 288 int numWatches = _watches.size(); 289 if (row < numWatches) { 290 DebugWatchData currWatch = _watches.get(row); 291 if (currWatch.isChanged()) { 292 setFont(getFont().deriveFont(Font.BOLD)); 293 } 294 } 295 } 296 } 297 298 299 public class WatchTableModel extends AbstractTableModel { 300 301 private String [] _columnNames = {"Name", "Value", "Type"}; 302 303 public String getColumnName(int col) { return _columnNames[col]; } 304 public int getRowCount() { return _watches.size() + 1; } 305 public int getColumnCount() { return _columnNames.length; } 306 public Object getValueAt(int row, int col) { 307 if (row < _watches.size()) { 308 DebugWatchData watch = _watches.get(row); 309 switch(col) { 310 case 0: return watch.getName(); 311 case 1: return watch.getValue(); 312 case 2: return watch.getType(); 313 } 314 fireTableRowsUpdated(row, _watches.size()-1); 315 return null; 316 } 317 else { 318 fireTableRowsUpdated(row, _watches.size()-1); 319 return ""; 321 } 322 } 323 public boolean isCellEditable(int row, int col) { 324 if (col == 0) return true; 326 return false; 327 } 328 public void setValueAt(Object value, int row, int col) { 329 try { 330 if ((value == null) || (value.equals(""))) { 331 _debugger.removeWatch(row); 333 } 334 else { 335 if (row < _watches.size()) 336 _debugger.removeWatch(row); 337 _debugger.addWatch(String.valueOf(value)); 339 } 340 fireTableRowsUpdated(row, _watches.size()-1); 342 } 343 catch (DebugException de) { _frame._showDebugError(de); } 344 } 345 } 346 347 348 public class StackTableModel extends AbstractTableModel { 349 350 private String [] _columnNames = {"Method", "Line"}; 352 public String getColumnName(int col) { return _columnNames[col]; } 353 354 public int getRowCount() { 355 if (_stackFrames == null) return 0; 356 return _stackFrames.size(); 357 } 358 public int getColumnCount() { return _columnNames.length; } 359 360 public Object getValueAt(int row, int col) { 361 DebugStackData frame = _stackFrames.get(row); 362 switch(col) { 363 case 0: return frame.getMethod(); 364 case 1: return new Integer (frame.getLine()); 365 } 366 return null; 367 } 368 public boolean isCellEditable(int row, int col) { 369 return false; 370 } 371 } 372 373 374 public class ThreadTableModel extends AbstractTableModel { 375 376 private String [] _columnNames = {"Name", "Status"}; 377 378 public String getColumnName(int col) { return _columnNames[col]; } 379 380 public int getRowCount() { 381 if (_threads == null) return 0; 382 return _threads.size(); 383 } 384 385 public int getColumnCount() { 386 return _columnNames.length; 387 } 388 389 public Object getValueAt(int row, int col) { 390 DebugThreadData threadData = _threads.get(row); 391 switch(col) { 392 case 0: return threadData.getName(); 393 case 1: return threadData.getStatus(); 394 default: return null; 395 } 396 397 } 398 399 public boolean isCellEditable(int row, int col) { return false; } 400 } 401 402 403 private void _setupButtonPanel() { 404 JPanel mainButtons = new JPanel(); 405 JPanel emptyPanel = new JPanel(); 406 JPanel closeButtonPanel = new JPanel(new BorderLayout()); 407 GridBagLayout gbLayout = new GridBagLayout(); 408 GridBagConstraints c = new GridBagConstraints(); 409 mainButtons.setLayout(gbLayout); 410 411 Action resumeAction = new AbstractAction("Resume") { 412 public void actionPerformed(ActionEvent ae) { 413 try { _frame.debuggerResume(); } 414 catch (DebugException de) { _frame._showDebugError(de); } 415 } 416 }; 417 _resumeButton = new JButton(resumeAction); 418 419 Action stepIntoAction = new AbstractAction("Step Into") { 420 public void actionPerformed(ActionEvent ae) { 421 _frame.debuggerStep(Debugger.STEP_INTO); 422 } 423 }; 424 _stepIntoButton = new JButton(stepIntoAction); 425 426 Action stepOverAction = new AbstractAction("Step Over") { 427 public void actionPerformed(ActionEvent ae) { 428 _frame.debuggerStep(Debugger.STEP_OVER); 429 } 430 }; 431 _stepOverButton = new JButton(stepOverAction); 432 433 Action stepOutAction = new AbstractAction( "Step Out" ) { 434 public void actionPerformed(ActionEvent ae) { 435 _frame.debuggerStep(Debugger.STEP_OUT); 436 } 437 }; 438 _stepOutButton = new JButton(stepOutAction); 439 440 ActionListener closeListener = 441 new ActionListener() { 442 public void actionPerformed(ActionEvent ae) { 443 _frame.debuggerToggle(); 444 } 445 }; 446 447 _closeButton = new CommonCloseButton(closeListener); 448 449 closeButtonPanel.add(_closeButton, BorderLayout.NORTH); 450 mainButtons.add(_resumeButton); 451 mainButtons.add(_stepIntoButton); 452 mainButtons.add(_stepOverButton); 453 mainButtons.add(_stepOutButton); 454 mainButtons.add(emptyPanel); 455 456 c.fill = GridBagConstraints.HORIZONTAL; 457 c.anchor = GridBagConstraints.NORTH; 458 c.gridwidth = GridBagConstraints.REMAINDER; 459 c.weightx = 1.0; 460 461 gbLayout.setConstraints(_resumeButton, c); 462 gbLayout.setConstraints(_stepIntoButton, c); 463 gbLayout.setConstraints(_stepOverButton, c); 464 gbLayout.setConstraints(_stepOutButton, c); 465 466 c.fill = GridBagConstraints.BOTH; 467 c.anchor = GridBagConstraints.SOUTH; 468 c.gridheight = GridBagConstraints.REMAINDER; 469 c.weighty = 1.0; 470 471 gbLayout.setConstraints(emptyPanel, c); 472 473 disableButtons(); 474 _buttonPanel.add(mainButtons, BorderLayout.CENTER); 475 _buttonPanel.add(closeButtonPanel, BorderLayout.EAST); 476 } 477 478 482 private void _initPopup() { 483 501 Action selectAction = new AbstractAction("Select Thread") { 502 public void actionPerformed(ActionEvent e) { _selectCurrentThread(); } 503 }; 504 505 _threadSuspendedPopupMenu = new JPopupMenu("Thread Selection"); 506 _threadSuspendedPopupMenu.add(selectAction); 507 _threadSuspendedPopupMenu.add(new AbstractAction("Resume Thread") { 508 public void actionPerformed(ActionEvent e) { 509 try { 510 if (_threadInPopup.isSuspended()) _debugger.resume(_threadInPopup); 511 } 512 catch (DebugException dbe) { _frame._showDebugError(dbe); } 513 } 514 }); 515 516 _stackPopupMenu = new JPopupMenu("Stack Selection"); 517 _stackPopupMenu.add(new AbstractAction("Scroll to Source") { 518 public void actionPerformed(ActionEvent e) { 519 try { 520 _debugger.scrollToSource(getSelectedStackItem()); 521 } 522 catch (DebugException de) { _frame._showDebugError(de); } 523 } 524 }); 525 526 _watchPopupMenu = new JPopupMenu("Watches"); 527 _watchPopupMenu.add(new AbstractAction("Remove Watch") { 528 public void actionPerformed(ActionEvent e) { 529 try { 530 _debugger.removeWatch(_watchTable.getSelectedRow()); 531 _watchTable.revalidate(); 532 _watchTable.repaint(); 533 } 534 catch (DebugException de) { _frame._showDebugError(de); } 535 } 536 }); 537 _watchTable.addMouseListener(new DebugTableMouseAdapter(_watchTable) { 538 protected void _showPopup(MouseEvent e) { 539 if (_watchTable.getSelectedRow() < _watchTable.getRowCount() - 1) { 540 _watchPopupMenu.show(e.getComponent(), e.getX(), e.getY()); 541 } 542 } 543 protected void _action() { 544 } 545 }); 546 } 547 548 550 private void _selectCurrentThread() { 551 if (_threadInPopup.isSuspended()) { 552 try { 553 _debugger.setCurrentThread(_threadInPopup); 554 } 555 catch(DebugException de) { 556 _frame._showDebugError(de); 557 } 558 } 559 } 560 561 565 public DebugThreadData getSelectedThread() { 566 int row = _threadTable.getSelectedRow(); 567 if (row == -1) { 568 row = 0; } 570 return _threads.get(row); 571 } 572 573 576 public DebugStackData getSelectedStackItem() { 577 return _stackFrames.get(_stackTable.getSelectedRow()); 578 } 579 580 581 public DebugWatchData getSelectedWatch() { 582 return _watches.get(_watchTable.getSelectedRow()); 583 } 584 585 586 class DebugPanelListener implements DebugListener { 587 588 public void currThreadSuspended() { 589 Utilities.invokeLater(new Runnable () { public void run() { updateData(); } }); 591 } 592 593 594 public void currThreadResumed() { 595 Utilities.invokeLater(new Runnable () { public void run() { updateData(); } }); 597 } 598 599 600 public void threadStarted() { updateData(); } 601 602 603 public void currThreadDied() { updateData(); } 604 605 606 public void nonCurrThreadDied() { updateData(); } 607 608 611 public void currThreadSet(DebugThreadData thread) { 612 _currentThreadID = thread.getUniqueID(); 613 614 Utilities.invokeLater(new Runnable () { public void run() { updateData(); } }); 616 } 617 618 public void threadLocationUpdated(OpenDefinitionsDocument doc, int lineNumber, boolean shouldHighlight) { } 619 public void debuggerStarted() { } 620 public void debuggerShutdown() { } 621 public void breakpointReached(final Breakpoint bp) { } 622 public void watchSet(final DebugWatchData w) { } 623 public void watchRemoved(final DebugWatchData w) { } 624 public void stepRequested() { } 625 public void regionAdded(Breakpoint r, int index) { } 626 public void regionChanged(Breakpoint r, int index) { } 627 public void regionRemoved(Breakpoint r) { } 628 } 629 630 631 636 public void setThreadDependentButtons(boolean isSuspended) { 637 _resumeButton.setEnabled(isSuspended); 638 _stepIntoButton.setEnabled(isSuspended); 639 _stepOverButton.setEnabled(isSuspended); 640 _stepOutButton.setEnabled(isSuspended); 641 } 642 public void disableButtons() { 643 setThreadDependentButtons(false); 644 } 645 646 public void setStatusText(String text) { _statusBar.setText(text); } 647 648 public String getStatusText() { return _statusBar.getText(); } 649 650 669 670 673 private class ThreadMouseAdapter extends DebugTableMouseAdapter { 674 public ThreadMouseAdapter() { 675 super(_threadTable); 676 } 677 678 protected void _showPopup(MouseEvent e) { 679 _threadInPopup = _threads.get(_lastRow); 680 if (_threadInPopup.isSuspended()) { 681 _threadSuspendedPopupMenu.show(e.getComponent(), e.getX(), e.getY()); 682 } 683 } 687 688 protected void _action() { 689 _threadInPopup = _threads.get(_lastRow); 690 _selectCurrentThread(); 691 } 692 } 693 694 697 private class StackMouseAdapter extends DebugTableMouseAdapter { 698 public StackMouseAdapter() { 699 super(_stackTable); 700 } 701 702 protected void _showPopup(MouseEvent e) { 703 _stackPopupMenu.show(e.getComponent(), e.getX(), e.getY()); 704 } 705 706 protected void _action() { 707 try { 708 _debugger.scrollToSource(_stackFrames.get(_lastRow)); 709 } 710 catch (DebugException de) { 711 _frame._showDebugError(de); 712 } 713 } 714 } 715 716 720 private abstract class DebugTableMouseAdapter extends RightClickMouseAdapter { 721 protected JTable _table; 722 protected int _lastRow; 723 724 public DebugTableMouseAdapter(JTable table) { 725 _table = table; 726 _lastRow = -1; 727 } 728 729 protected abstract void _showPopup(MouseEvent e); 730 protected abstract void _action(); 731 732 protected void _popupAction(MouseEvent e) { 733 _lastRow = _table.rowAtPoint(e.getPoint()); 734 _table.setRowSelectionInterval(_lastRow, _lastRow); 735 _showPopup(e); 736 } 737 738 public void mousePressed(MouseEvent e) { 739 super.mousePressed(e); 740 741 if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2) { 742 _lastRow = _table.rowAtPoint(e.getPoint()); 743 _action(); 744 } 745 } 746 } 747 748 private class BPTree extends JTree { 749 public BPTree(DefaultTreeModel s) { 750 super(s); 751 } 752 753 public void setForeground(Color c) { 754 super.setForeground(c); 755 if (dtcr != null) dtcr.setTextNonSelectionColor(c); 756 } 757 758 public void setBackground(Color c) { 759 super.setBackground(c); 760 if (DebugPanel.this != null && dtcr != null) dtcr.setBackgroundNonSelectionColor(c); 761 } 762 } 763 } 764 | Popular Tags |