From a8aa75fa8d1dfd6029fdc6f80ad9135ba34867d2 Mon Sep 17 00:00:00 2001 From: fros4943 Date: Thu, 11 Jun 2009 10:06:47 +0000 Subject: [PATCH] updated code watcher user interfaces: added support for disabling breakpoints without removing them + several minor fixes --- .../cooja/mspmote/plugins/BreakpointsUI.java | 305 +++++++++--------- .../se/sics/cooja/mspmote/plugins/CodeUI.java | 113 +++---- 2 files changed, 208 insertions(+), 210 deletions(-) diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/BreakpointsUI.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/BreakpointsUI.java index 7f0b42e98..768301bd7 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/BreakpointsUI.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/BreakpointsUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Swedish Institute of Computer Science. + * Copyright (c) 2009, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: BreakpointsUI.java,v 1.2 2008/11/03 18:10:34 fros4943 Exp $ + * $Id: BreakpointsUI.java,v 1.3 2009/06/11 10:06:47 fros4943 Exp $ */ package se.sics.cooja.mspmote.plugins; @@ -34,57 +34,165 @@ package se.sics.cooja.mspmote.plugins; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; import java.io.File; -import java.util.Vector; import javax.swing.*; import javax.swing.table.AbstractTableModel; import org.apache.log4j.Logger; -import se.sics.cooja.mspmote.plugins.MspCodeWatcher.Breakpoints; -import se.sics.cooja.mspmote.plugins.MspCodeWatcher.Breakpoints.Breakpoint; - +/** + * Displays a set of breakpoints. + * + * @author Fredrik Osterlind + */ public class BreakpointsUI extends JPanel { private static Logger logger = Logger.getLogger(BreakpointsUI.class); - private JTable breakpointsTable = null; - private Breakpoints breakpoints = null; + private MspBreakpointContainer breakpoints = null; + private JTable table = null; + + public BreakpointsUI(MspBreakpointContainer breakpoints, final MspCodeWatcher codeWatcher) { + this.breakpoints = breakpoints; + + /* Breakpoints table */ + table = new JTable(tableModel) { + public String getToolTipText(MouseEvent e) { + + /* Tooltips: show full file paths */ + java.awt.Point p = e.getPoint(); + int rowIndex = table.rowAtPoint(p); + int colIndex = table.columnAtPoint(p); + int realColumnIndex = table.convertColumnIndexToModel(colIndex); + + if (realColumnIndex != 1) { + return null; + } + + MspBreakpoint[] allBreakpoints = BreakpointsUI.this.breakpoints.getBreakpoints(); + if (rowIndex < 0 || rowIndex >= allBreakpoints.length) { + return null; + } + File file = allBreakpoints[rowIndex].getCodeFile(); + if (file == null) { + return null; + } + return file.getPath(); + } + }; + table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + table.getColumnModel().getColumn(0).setPreferredWidth(60); /* XXX */ + table.getColumnModel().getColumn(0).setMaxWidth(60); + table.getColumnModel().getColumn(2).setPreferredWidth(60); + table.getColumnModel().getColumn(2).setMaxWidth(60); + table.getColumnModel().getColumn(3).setPreferredWidth(60); + table.getColumnModel().getColumn(3).setMaxWidth(60); + + /* Show source file on breakpoint mouse click */ + table.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + + java.awt.Point p = e.getPoint(); + int rowIndex = table.rowAtPoint(p); + int colIndex = table.columnAtPoint(p); + int realColumnIndex = table.convertColumnIndexToModel(colIndex); + + if (realColumnIndex != 1 && realColumnIndex != 2) { + return; + } + + MspBreakpoint[] allBreakpoints = BreakpointsUI.this.breakpoints.getBreakpoints(); + if (rowIndex < 0 || rowIndex >= allBreakpoints.length) { + return; + } + File file = allBreakpoints[rowIndex].getCodeFile(); + int line = allBreakpoints[rowIndex].getLineNumber(); + if (file == null) { + return; + } + + /* Display source code */ + codeWatcher.displaySourceFile(file, line); + } + }); + + /* Update when breakpoints are triggered/added/removed */ + breakpoints.addWatchpointListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + MspBreakpoint triggered = BreakpointsUI.this.breakpoints.getLastWatchpoint(); + if (triggered == null) { + table.repaint(); + return; + } + + flashBreakpoint(triggered); + } + }); + + setLayout(new BorderLayout()); + add(BorderLayout.NORTH, table.getTableHeader()); + add(BorderLayout.CENTER, table); + } + + private void flashBreakpoint(MspBreakpoint breakpoint) { + /* Locate breakpoints table index */ + int index = -1; + MspBreakpoint[] all = breakpoints.getBreakpoints(); + for (int i=0; i < breakpoints.getBreakpointsCount(); i++) { + if (breakpoint == all[i]) { + index = i; + break; + } + } + if (index < 0) { + return; + } + + final int breakpointIndex = index; + SwingUtilities.invokeLater(new Runnable() { + public void run() { + table.setRowSelectionInterval(breakpointIndex, breakpointIndex); + } + }); + } private AbstractTableModel tableModel = new AbstractTableModel() { - private String[] tableColumnNames = { + private final String[] tableColumnNames = { "Address", - "File", - "Line", + "File:Line", + "Breaks", "Remove" }; - - public String getColumnName(int col) { return tableColumnNames[col].toString(); } - public int getRowCount() { return breakpoints.getBreakpoints().size(); } - public int getColumnCount() { return tableColumnNames.length; } + public String getColumnName(int col) { + return tableColumnNames[col].toString(); + } + public int getRowCount() { + return breakpoints.getBreakpointsCount(); + } + public int getColumnCount() { + return tableColumnNames.length; + } public Object getValueAt(int row, int col) { - // Display executable address in hexadecimal + MspBreakpoint breakpoint = breakpoints.getBreakpoints()[row]; + + /* Executable address in hexadecimal */ if (col == 0) { - Integer address = breakpoints.getBreakpoints().get(row).getExecutableAddress(); + Integer address = breakpoint.getExecutableAddress(); return "0x" + Integer.toHexString(address.intValue()); } - // Display only name of file + /* Source file + line number */ if (col == 1) { - File file = breakpoints.getBreakpoints().get(row).getCodeFile(); + File file = breakpoint.getCodeFile(); if (file == null) { return ""; } - return file.getName(); + return file.getName() + ":" + breakpoint.getLineNumber(); } - // Display line number + /* Stops simulation */ if (col == 2) { - Integer line = breakpoints.getBreakpoints().get(row).getLineNumber(); - if (line == null) { - return ""; - } - return line; + return breakpoint.stopsSimulation(); } return new Boolean(false); @@ -93,138 +201,23 @@ public class BreakpointsUI extends JPanel { return getColumnClass(col) == Boolean.class; } public void setValueAt(Object value, int row, int col) { - fireTableCellUpdated(row, col); - Integer address = breakpoints.getBreakpoints().get(row).getExecutableAddress(); + MspBreakpoint breakpoint = breakpoints.getBreakpoints()[row]; + + if (col == 2) { + /* Toggle stop state */ + breakpoint.setStopsSimulation(!breakpoint.stopsSimulation()); + fireTableCellUpdated(row, col); + return; + } + + /* Remove breakpoint */ + Integer address = breakpoint.getExecutableAddress(); breakpoints.removeBreakpoint(address); + + fireTableCellUpdated(row, col); } - public Class getColumnClass(int c) { + public Class getColumnClass(int c) { return getValueAt(0, c).getClass(); } - }; - - public BreakpointsUI(Breakpoints breakpoints, final MspCodeWatcher codeWatcher) { - this.breakpoints = breakpoints; - breakpoints.addBreakpointListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Breakpoint triggered = BreakpointsUI.this.breakpoints.getLastTriggered(); - if (triggered != null) { - flashBreakpoint(triggered); - } - - breakpointsTable.repaint(); - } - }); - - breakpointsTable = new JTable(tableModel) { - public String getToolTipText(MouseEvent e) { - String tip = null; - java.awt.Point p = e.getPoint(); - int rowIndex = breakpointsTable.rowAtPoint(p); - int colIndex = breakpointsTable.columnAtPoint(p); - int realColumnIndex = breakpointsTable.convertColumnIndexToModel(colIndex); - - if (realColumnIndex == 1) { - Vector allBreakpoints = BreakpointsUI.this.breakpoints.getBreakpoints(); - if (rowIndex < 0 || rowIndex >= allBreakpoints.size()) { - return ""; - } - File file = allBreakpoints.get(rowIndex).getCodeFile(); - if (file == null) { - return ""; - } else { - tip = file.getPath(); - } - } - return tip; - } - }; - - /* Open file on mouse click */ - breakpointsTable.addMouseListener(new MouseListener() { - - public void mouseClicked(MouseEvent e) { - java.awt.Point p = e.getPoint(); - int rowIndex = breakpointsTable.rowAtPoint(p); - int colIndex = breakpointsTable.columnAtPoint(p); - int realColumnIndex = breakpointsTable.convertColumnIndexToModel(colIndex); - - if (realColumnIndex == 1 || realColumnIndex == 2) { - Vector allBreakpoints = BreakpointsUI.this.breakpoints.getBreakpoints(); - if (rowIndex < 0 || rowIndex >= allBreakpoints.size()) { - return; - } - File file = allBreakpoints.get(rowIndex).getCodeFile(); - int line = allBreakpoints.get(rowIndex).getLineNumber(); - if (file == null) { - return; - } else { - /* Display source code */ - codeWatcher.displaySourceFile(file, line); - } - } - } - - public void mouseEntered(MouseEvent e) { - } - - public void mouseExited(MouseEvent e) { - } - - public void mousePressed(MouseEvent e) { - } - - public void mouseReleased(MouseEvent e) { - } - - }); - - setLayout(new BorderLayout()); - add(breakpointsTable.getTableHeader(), BorderLayout.PAGE_START); - add(breakpointsTable, BorderLayout.CENTER); - } - - private int flashCounter = 0; - private Color oldColor; - private void flashBreakpoint(Breakpoint breakpoint) { - int index = breakpoints.getBreakpoints().indexOf(breakpoint); - breakpointsTable.setRowSelectionInterval(index, index); - oldColor = breakpointsTable.getSelectionBackground(); - breakpointsTable.setSelectionBackground(Color.RED); - - flashCounter = 8; - - final Timer timer = new Timer(100, null); - timer.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (flashCounter-- <= 0) { - timer.stop(); - SwingUtilities.invokeLater(new Runnable() { - public void run() { - breakpointsTable.setSelectionBackground(oldColor); - } - }); - return; - } - // Toggle background color - if (breakpointsTable.getSelectionBackground() != Color.RED) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - breakpointsTable.setSelectionBackground(Color.RED); - } - }); - } else { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - breakpointsTable.setSelectionBackground(oldColor); - } - }); - } - } - }); - - timer.start(); - - } - } diff --git a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/CodeUI.java b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/CodeUI.java index 52367bb3e..6d7f28503 100644 --- a/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/CodeUI.java +++ b/tools/cooja/apps/mspsim/src/se/sics/cooja/mspmote/plugins/CodeUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Swedish Institute of Computer Science. + * Copyright (c) 2009, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: CodeUI.java,v 1.5 2008/11/03 18:10:52 fros4943 Exp $ + * $Id: CodeUI.java,v 1.6 2009/06/11 10:06:47 fros4943 Exp $ */ package se.sics.cooja.mspmote.plugins; @@ -37,12 +37,12 @@ import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.io.File; -import java.util.Enumeration; +import java.util.ArrayList; +import java.util.Iterator; import java.util.Vector; import javax.swing.*; import org.apache.log4j.Logger; -import se.sics.cooja.mspmote.plugins.MspCodeWatcher.Breakpoints; import se.sics.mspsim.extutil.highlight.CScanner; import se.sics.mspsim.extutil.highlight.Token; import se.sics.mspsim.extutil.highlight.TokenTypes; @@ -57,9 +57,9 @@ public class CodeUI extends JPanel { private JPanel panel = null; private JList codeList = null; - private File currentFile = null; - private Breakpoints breakpoints = null; + private MspBreakpointContainer breakpoints = null; + protected File displayedFile = null; private Token tokensArray[][] = null; private int tokensStartPos[] = null; @@ -67,7 +67,7 @@ public class CodeUI extends JPanel { /** * @param breakpoints Breakpoints */ - public CodeUI(Breakpoints breakpoints) { + public CodeUI(MspBreakpointContainer breakpoints) { this.breakpoints = breakpoints; setLayout(new BorderLayout()); @@ -76,14 +76,17 @@ public class CodeUI extends JPanel { add(panel, BorderLayout.CENTER); displayNoCode(); - breakpoints.addBreakpointListener(new ActionListener() { + breakpoints.addWatchpointListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - if (codeList != null) { - codeList.updateUI(); - } + SwingUtilities.invokeLater(new Runnable() { + public void run() { + if (codeList != null) { + codeList.updateUI(); + } + } + }); } }); - } /** @@ -97,17 +100,19 @@ public class CodeUI extends JPanel { panel.repaint(); } }); - currentFile = null; + displayedFile = null; return; } - private void createTokens(Vector codeData) { + private void createTokens(String[] codeData) { /* Merge code lines */ - String code = ""; + StringBuilder sb = new StringBuilder(); for (String line: codeData) { - code += line + "\n"; + sb.append(line); + sb.append('\n'); } + String code = sb.toString(); /* Scan code */ CScanner cScanner = new CScanner(); @@ -116,30 +121,30 @@ public class CodeUI extends JPanel { nrTokens = cScanner.scan(code.toCharArray(), 0, code.length()); /* Extract tokens */ - Vector codeTokensVector = new Vector(); + ArrayList codeTokensVector = new ArrayList(); for (int i=0; i < nrTokens; i++) { Token token = cScanner.getToken(i); codeTokensVector.add(token); } /* Create new line token array */ - Token newTokensArray[][] = new Token[codeData.size()][]; - int[] newTokensStartPos = new int[codeData.size()]; + Token newTokensArray[][] = new Token[codeData.length][]; + int[] newTokensStartPos = new int[codeData.length]; int lineStart=0, lineEnd=-1; - Enumeration tokensEnum = codeTokensVector.elements(); - Token currentToken = tokensEnum.nextElement(); + Iterator tokens = codeTokensVector.iterator(); + Token currentToken = tokens.next(); for (int i=0; i < newTokensArray.length; i++) { lineStart = lineEnd + 1; - lineEnd = lineStart + codeData.get(i).length(); + lineEnd = lineStart + codeData[i].length(); newTokensStartPos[i] = lineStart;; /* Advance tokens until correct line */ while (currentToken.position + currentToken.symbol.name.length() < lineStart) { - if (!tokensEnum.hasMoreElements()) { + if (!tokens.hasNext()) { break; } - currentToken = tokensEnum.nextElement(); + currentToken = tokens.next(); } /* Advance tokens until last token on line */ @@ -147,10 +152,10 @@ public class CodeUI extends JPanel { while (currentToken.position < lineEnd) { lineTokens.add(currentToken); - if (!tokensEnum.hasMoreElements()) { + if (!tokens.hasNext()) { break; } - currentToken = tokensEnum.nextElement(); + currentToken = tokens.next(); } if (currentToken == null) { @@ -177,10 +182,10 @@ public class CodeUI extends JPanel { * @param codeData Source code * @param lineNr Line numer */ - public void displayNewCode(final File codeFile, final Vector codeData, final int lineNr) { - currentFile = codeFile; + public void displayNewCode(final File codeFile, final String[] codeData, final int lineNr) { + displayedFile = codeFile; - if (codeData == null || codeData.size() == 0) { + if (codeData == null || codeData.length == 0) { displayNoCode(); return; } @@ -216,7 +221,7 @@ public class CodeUI extends JPanel { displayLine(lineNr); } }); - } + } /** * Mark given line number in shown source code. @@ -224,21 +229,24 @@ public class CodeUI extends JPanel { * @param lineNumber Line number */ public void displayLine(final int lineNumber) { - if (codeList == null) { + if (codeList == null || lineNumber < 0) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + codeList.updateUI(); + } + }); return; } SwingUtilities.invokeLater(new Runnable() { public void run() { - if (lineNumber > 0) { - ((CodeCellRenderer) codeList.getCellRenderer()).changeCurrentLine(lineNumber); - int index = lineNumber - 1; - codeList.setSelectedIndex(index); + ((CodeCellRenderer) codeList.getCellRenderer()).changeCurrentLine(lineNumber); + int index = lineNumber - 1; + codeList.setSelectedIndex(index); - codeList.ensureIndexIsVisible(Math.max(0, index-3)); - codeList.ensureIndexIsVisible(Math.min(index+3, codeList.getModel().getSize())); - codeList.ensureIndexIsVisible(index); - } + codeList.ensureIndexIsVisible(Math.max(0, index-3)); + codeList.ensureIndexIsVisible(Math.min(index+3, codeList.getModel().getSize())); + codeList.ensureIndexIsVisible(index); codeList.updateUI(); } }); @@ -259,7 +267,7 @@ public class CodeUI extends JPanel { codeList.setSelectedIndex(currentLine - 1); } }); - JPopupMenu popupMenu = createPopupMenu(currentFile, currentLine); + JPopupMenu popupMenu = createPopupMenu(displayedFile, currentLine); popupMenu.setLocation(menuLocation); popupMenu.setInvoker(codeList); @@ -269,10 +277,7 @@ public class CodeUI extends JPanel { private JPopupMenu createPopupMenu(final File codeFile, final int lineNr) { final Integer executableAddress = breakpoints.getExecutableAddressOf(codeFile, lineNr); - boolean breakpointExists = false; - if (executableAddress != null) { - breakpointExists = breakpoints.breakpointExists(executableAddress); - } + boolean breakpointExists = breakpoints.breakpointExists(codeFile, lineNr); JPopupMenu menuMotePlugins = new JPopupMenu(); JMenuItem headerMenuItem = new JMenuItem("Breakpoints:"); @@ -308,27 +313,27 @@ public class CodeUI extends JPanel { } private class CodeListModel extends AbstractListModel { - private Vector codeData; + private String[] codeData; - public CodeListModel(Vector codeData) { + public CodeListModel(String[] codeData) { super(); this.codeData = codeData; } public int getSize() { - if (codeData == null || codeData.isEmpty()) { + if (codeData == null || codeData.length == 0) { return 0; } - return codeData.size(); + return codeData.length; } public Object getElementAt(int index) { - if (codeData == null || codeData.isEmpty()) { + if (codeData == null || codeData.length == 0) { return "No code to display"; } - return codeData.get(index); + return codeData[index]; } } @@ -399,7 +404,9 @@ public class CodeUI extends JPanel { String html = ""; /* Add line number */ - html += "" + lineNr + ": "; + String lineString = "0000" + Integer.toString(lineNr); + lineString = lineString.substring(lineString.length() - 4); + html += "" + lineString + ": "; /* Add code */ if (tokens == null || tokens.length == 0 || lineStartPos < 0) { @@ -460,7 +467,6 @@ public class CodeUI extends JPanel { return html; } - public Component getListCellRendererComponent( JList list, Object value, @@ -487,8 +493,7 @@ public class CodeUI extends JPanel { } setEnabled(list.isEnabled()); - Integer executableAddress = breakpoints.getExecutableAddressOf(currentFile, lineNr); - if (breakpoints.breakpointExists(executableAddress)) { + if (breakpoints.breakpointExists(displayedFile, lineNr)) { setFont(list.getFont().deriveFont(Font.BOLD)); } else { setFont(list.getFont());