Mercurial > hg > graal-compiler
diff agent/src/share/classes/sun/jvm/hotspot/ui/SourceCodePanel.java @ 0:a61af66fc99e jdk7-b24
Initial load
author | duke |
---|---|
date | Sat, 01 Dec 2007 00:00:00 +0000 |
parents | |
children | c18cbe5936b8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/ui/SourceCodePanel.java Sat Dec 01 00:00:00 2007 +0000 @@ -0,0 +1,303 @@ +/* + * Copyright 2001-2002 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.ui; + +import java.awt.*; +import java.awt.event.*; +import java.io.*; +import java.net.*; +import java.util.*; +import javax.swing.*; +import javax.swing.text.BadLocationException; + +/** Panel supporting loading of and scrolling through source code. + Contains convenience routines for implementing the Editor + interface. */ + +public class SourceCodePanel extends JPanel { + private JTextArea source; + private RowHeader header; + private String filename; + // Amount of white space between edges, line numbers and icons + private static final int LINE_NO_SPACE = 4; + // Size of icons in resources directory + private static final int ICON_SIZE = 12; + // Icons used in panel drawing + private static Icon topFrameCurLine; + private static Icon lowerFrameCurLine; + private static Icon breakpoint; + // State + private int highlightedLine = -1; + private Set/*<Integer>*/ breakpoints = new HashSet(); // Zero-based lines internally + // Parent Editor container and EditorCommands object for setting breakpoints + private EditorCommands comm; + private Editor parent; + + /** Support for displaying icons and line numbers in row header of + scroll pane */ + class RowHeader extends JPanel { + private JViewport view; + private boolean showLineNumbers; + private int width; + private int rowHeight; + private boolean initted; + + public RowHeader() { + super(); + initted = true; + addHierarchyBoundsListener(new HierarchyBoundsAdapter() { + public void ancestorResized(HierarchyEvent e) { + recomputeSize(); + } + }); + } + + public void paint(Graphics g) { + super.paint(g); + if (getShowLineNumbers()) { + // Visible region of header panel, in coordinate system of the + // panel, is provided by clip bounds of Graphics object. This + // is used to figure out which line numbers to draw. + Rectangle clip = g.getClipBounds(); + // To avoid missing lines, round down starting line number and + // round up ending line number + int start = clip.y / rowHeight; + int end = start + (clip.height + (rowHeight - 1)) / rowHeight; + // Draw these line numbers, right justified to look better + FontMetrics fm = getFontMetrics(getFont()); + int ascent = fm.getMaxAscent(); // Causes proper alignment -- trial-and-error + for (int i = start; i <= end; i++) { + // Line numbers are 1-based + String str = Integer.toString(i + 1); + int strWidth = GraphicsUtilities.getStringWidth(str, fm); + g.drawString(str, width - strWidth - LINE_NO_SPACE, ascent + rowHeight * i); + + // Draw breakpoint if necessary + if (breakpoints.contains(new Integer(i))) { + breakpoint.paintIcon(this, g, LINE_NO_SPACE, rowHeight * i); + } + + // Draw current line icon if necessary + if (i == highlightedLine) { + // FIXME: use correct icon (not always topmost frame) + topFrameCurLine.paintIcon(this, g, LINE_NO_SPACE, rowHeight * i); + } + } + } + } + + public boolean getShowLineNumbers() { + return showLineNumbers; + } + + public void setShowLineNumbers(boolean val) { + if (val != showLineNumbers) { + showLineNumbers = val; + recomputeSize(); + // Force re-layout + invalidate(); + validate(); + } + } + + public void setFont(Font f) { + super.setFont(f); + rowHeight = getFontMetrics(f).getHeight(); + recomputeSize(); + } + + void setViewport(JViewport view) { + this.view = view; + } + + void recomputeSize() { + if (!initted) return; + if (view == null) return; + width = ICON_SIZE + 2 * LINE_NO_SPACE; + try { + int numLines = 1 + source.getLineOfOffset(source.getDocument().getEndPosition().getOffset() - 1); + String str = Integer.toString(numLines); + if (getShowLineNumbers()) { + // Compute width based on whether we are drawing line numbers + width += GraphicsUtilities.getStringWidth(str, getFontMetrics(getFont())) + LINE_NO_SPACE; + } + // FIXME: add on width for all icons (breakpoint, current line, + // current line in caller frame) + Dimension d = new Dimension(width, numLines * getFontMetrics(getFont()).getHeight()); + setSize(d); + setPreferredSize(d); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + } + + public SourceCodePanel() { + maybeLoadIcons(); + + // Build user interface + setLayout(new BorderLayout()); + source = new JTextArea(); + source.setEditable(false); + source.getCaret().setVisible(true); + header = new RowHeader(); + header.setShowLineNumbers(true); + JScrollPane scroller = new JScrollPane(source); + JViewport rowView = new JViewport(); + rowView.setView(header); + header.setViewport(rowView); + rowView.setScrollMode(JViewport.SIMPLE_SCROLL_MODE); + scroller.setRowHeader(rowView); + add(scroller, BorderLayout.CENTER); + // Reset font now that header and source are present + setFont(getFont()); + + source.addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent e) { + source.getCaret().setVisible(true); + } + }); + + source.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_F9) { + int lineNo = getCurrentLineNumber(); + // Only the debugger can figure out whether we are setting + // or clearing a breakpoint, since it has the debug + // information available and knows whether we're on a + // valid line + comm.toggleBreakpointAtLine(parent, lineNo); + } + } + }); + + } + + public void setFont(Font f) { + super.setFont(f); + if (source != null) { + source.setFont(f); + } + if (header != null) { + header.setFont(f); + } + } + + public boolean getShowLineNumbers() { + return header.getShowLineNumbers(); + } + + public void setShowLineNumbers(boolean val) { + header.setShowLineNumbers(val); + } + + public boolean openFile(String filename) { + try { + this.filename = filename; + File file = new File(filename); + int len = (int) file.length(); + StringBuffer buf = new StringBuffer(len); // Approximation + char[] tmp = new char[4096]; + FileReader in = new FileReader(file); + int res = 0; + do { + res = in.read(tmp, 0, tmp.length); + if (res >= 0) { + buf.append(tmp, 0, res); + } + } while (res != -1); + in.close(); + String text = buf.toString(); + source.setText(text); + header.recomputeSize(); + return true; + } catch (IOException e) { + return false; + } + } + + public String getSourceFileName() { + return filename; + } + + /** Line number is one-based */ + public int getCurrentLineNumber() { + try { + return 1 + source.getLineOfOffset(source.getCaretPosition()); + } catch (BadLocationException e) { + return 0; + } + } + + /** Line number is one-based */ + public void showLineNumber(int lineNo) { + try { + int offset = source.getLineStartOffset(lineNo - 1); + Rectangle rect = source.modelToView(offset); + if (rect == null) { + return; + } + source.scrollRectToVisible(rect); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + /** Line number is one-based */ + public void highlightLineNumber(int lineNo) { + highlightedLine = lineNo - 1; + } + + public void showBreakpointAtLine(int lineNo) { breakpoints.add(new Integer(lineNo - 1)); repaint(); } + public boolean hasBreakpointAtLine(int lineNo){ return breakpoints.contains(new Integer(lineNo - 1)); } + public void clearBreakpointAtLine(int lineNo) { breakpoints.remove(new Integer(lineNo - 1)); repaint(); } + public void clearBreakpoints() { breakpoints.clear(); repaint(); } + + public void setEditorCommands(EditorCommands comm, Editor parent) { + this.comm = comm; + this.parent = parent; + } + + public void requestFocus() { + source.requestFocus(); + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private void maybeLoadIcons() { + if (topFrameCurLine == null) { + topFrameCurLine = loadIcon("resources/arrow.png"); + lowerFrameCurLine = loadIcon("resources/triangle.png"); + breakpoint = loadIcon("resources/breakpoint.png"); + } + } + + private Icon loadIcon(String which) { + URL url = getClass().getResource(which); + return new ImageIcon(url); + } +}