1 import javax
.swing
.JFrame
;
2 import javax
.swing
.JTextArea
;
3 import javax
.swing
.JPanel
;
4 import javax
.swing
.JScrollPane
;
5 import javax
.swing
.JButton
;
6 import javax
.swing
.JComponent
;
7 import javax
.swing
.JFileChooser
;
8 import javax
.swing
.JOptionPane
;
9 import javax
.swing
.text
.Document
;
10 import javax
.swing
.event
.DocumentListener
;
11 import javax
.swing
.event
.DocumentEvent
;
13 import java
.awt
.FlowLayout
;
14 import java
.awt
.Graphics
;
15 import java
.awt
.Color
;
17 import java
.awt
.FontMetrics
;
18 import java
.awt
.Polygon
;
19 import java
.awt
.Rectangle
;
20 import java
.awt
.Dimension
;
21 import java
.awt
.event
.ActionListener
;
22 import java
.awt
.event
.ActionEvent
;
25 import java
.io
.InputStream
;
26 import java
.io
.FileInputStream
;
27 import java
.io
.FileOutputStream
;
28 import java
.io
.IOException
;
30 import drafts
.com
.sun
.star
.script
.framework
.runtime
.XScriptContext
;
31 import bsh
.Interpreter
;
33 public class OOBeanShellDebugger
implements OOScriptDebugger
, ActionListener
, DocumentListener
{
37 private GlyphGutter gg
;
38 private XScriptContext context
;
39 private int currentPosition
= -1;
40 private int linecount
;
41 private Interpreter sessionInterpreter
;
42 private Thread execThread
= null;
43 private String filename
= null;
45 /* Entry point for script execution */
46 public void go(XScriptContext context
, String filename
) {
47 if (filename
!= null && filename
!= "") {
49 FileInputStream fis
= new FileInputStream(filename
);
50 this.filename
= filename
;
53 catch (IOException ioe
) {
54 JOptionPane
.showMessageDialog(frame
,
55 "Error loading file: " + ioe
.getMessage(),
56 "Error", JOptionPane
.ERROR_MESSAGE
);
61 /* Entry point for script execution */
62 public void go(XScriptContext context
, InputStream in
) {
63 this.context
= context
;
70 catch (IOException ioe
) {
71 JOptionPane
.showMessageDialog(frame
,
72 "Error loading stream: " + ioe
.getMessage(),
73 "Error", JOptionPane
.ERROR_MESSAGE
);
78 public void loadFile(InputStream in
) throws IOException
{
80 /* Remove ourselves as a DocumentListener while loading the file
81 so we don't get a storm of DocumentEvents during loading */
82 ta
.getDocument().removeDocumentListener(this);
84 byte[] contents
= new byte[1024];
87 while ((len
= in
.read(contents
, 0, 1024)) != -1) {
88 ta
.insert(new String(contents
, 0, len
), pos
);
95 catch (IOException ignore
) {
98 /* Update the GlyphGutter and add back the DocumentListener */
100 ta
.getDocument().addDocumentListener(this);
103 private void initUI() {
104 frame
= new JFrame("BeanShell Debug Window");
105 ta
= new JTextArea();
108 ta
.setLineWrap(false);
109 linecount
= ta
.getLineCount();
111 gg
= new GlyphGutter(this);
113 final JScrollPane sp
= new JScrollPane();
114 sp
.setViewportView(ta
);
115 sp
.setRowHeaderView(gg
);
117 ta
.getDocument().addDocumentListener(this);
118 String
[] labels
= {"Run", "Clear", "Save", "Close"};
119 JPanel p
= new JPanel();
120 p
.setLayout(new FlowLayout());
122 for (int i
= 0; i
< labels
.length
; i
++) {
123 JButton b
= new JButton(labels
[i
]);
124 b
.addActionListener(this);
127 if (labels
[i
].equals("Save") && filename
== null) {
132 frame
.getContentPane().add(sp
, "Center");
133 frame
.getContentPane().add(p
, "South");
138 /* Implementation of DocumentListener interface */
139 public void insertUpdate(DocumentEvent e
) {
143 public void removeUpdate(DocumentEvent e
) {
147 public void changedUpdate(DocumentEvent e
) {
151 /* If the number of lines in the JTextArea has changed then update the
153 public void doChanged(DocumentEvent e
) {
154 if (linecount
!= ta
.getLineCount()) {
156 linecount
= ta
.getLineCount();
160 private void startExecution() {
161 execThread
= new Thread() {
163 Interpreter interpreter
= new Interpreter();
164 interpreter
.getNameSpace().clear();
166 // reset position and repaint gutter so no red arrow appears
167 currentPosition
= -1;
171 interpreter
.set("context", context
);
172 interpreter
.eval(ta
.getText());
174 catch (bsh
.EvalError err
) {
175 currentPosition
= err
.getErrorLineNumber() - 1;
177 // scroll to line of the error
178 int line
= ta
.getLineStartOffset(currentPosition
);
179 Rectangle rect
= ta
.modelToView(line
);
180 ta
.scrollRectToVisible(rect
);
182 catch (Exception e
) {
183 // couldn't scroll to line, do nothing
187 JOptionPane
.showMessageDialog(frame
, "Error at line " +
188 String
.valueOf(err
.getErrorLineNumber()) +
189 "\n\n: " + err
.getErrorText(),
190 "Error", JOptionPane
.ERROR_MESSAGE
);
192 catch (Exception e
) {
193 JOptionPane
.showMessageDialog(frame
,
194 "Error: " + e
.getMessage(),
195 "Error", JOptionPane
.ERROR_MESSAGE
);
202 private void promptForSaveName() {
203 JFileChooser chooser
= new JFileChooser();
204 chooser
.setFileFilter(new javax
.swing
.filechooser
.FileFilter() {
205 public boolean accept(File f
) {
206 if (f
.isDirectory() || f
.getName().endsWith(".bsh")) {
212 public String
getDescription() {
213 return ("BeanShell files: *.bsh");
217 int ret
= chooser
.showSaveDialog(frame
);
219 if (ret
== JFileChooser
.APPROVE_OPTION
) {
220 filename
= chooser
.getSelectedFile().getAbsolutePath();
221 if (!filename
.endsWith(".bsh")) {
228 private void saveTextArea() {
229 if (filename
== null) {
233 FileOutputStream fos
= null;
234 if (filename
!= null) {
236 File f
= new File(filename
);
237 fos
= new FileOutputStream(f
);
238 String s
= ta
.getText();
239 fos
.write(s
.getBytes(), 0, s
.length());
241 catch (IOException ioe
) {
242 JOptionPane
.showMessageDialog(frame
,
243 "Error saving file: " + ioe
.getMessage(),
244 "Error", JOptionPane
.ERROR_MESSAGE
);
251 catch (IOException ignore
) {
258 public void actionPerformed(ActionEvent e
) {
259 if (e
.getActionCommand().equals("Run")) {
262 else if (e
.getActionCommand().equals("Close")) {
265 else if (e
.getActionCommand().equals("Save")) {
268 else if (e
.getActionCommand().equals("Clear")) {
273 public JTextArea
getTextArea() {
277 public int getCurrentPosition() {
278 return currentPosition
;
282 class GlyphGutter
extends JComponent
{
284 private OOBeanShellDebugger debugger
;
285 private final String DUMMY_STRING
= "99";
287 GlyphGutter(OOBeanShellDebugger debugger
) {
288 this.debugger
= debugger
;
292 public void update() {
293 JTextArea textArea
= debugger
.getTextArea();
294 Font font
= textArea
.getFont();
297 FontMetrics metrics
= getFontMetrics(font
);
298 int h
= metrics
.getHeight();
299 int lineCount
= textArea
.getLineCount() + 1;
301 String dummy
= Integer
.toString(lineCount
);
302 if (dummy
.length() < 2) {
303 dummy
= DUMMY_STRING
;
306 Dimension d
= new Dimension();
307 d
.width
= metrics
.stringWidth(dummy
) + 16;
308 d
.height
= lineCount
* h
+ 100;
313 public void paintComponent(Graphics g
) {
314 JTextArea textArea
= debugger
.getTextArea();
316 Font font
= textArea
.getFont();
319 FontMetrics metrics
= getFontMetrics(font
);
320 Rectangle clip
= g
.getClipBounds();
322 g
.setColor(getBackground());
323 g
.fillRect(clip
.x
, clip
.y
, clip
.width
, clip
.height
);
325 int ascent
= metrics
.getMaxAscent();
326 int h
= metrics
.getHeight();
327 int lineCount
= textArea
.getLineCount() + 1;
329 int startLine
= clip
.y
/ h
;
330 int endLine
= (clip
.y
+ clip
.height
) / h
+ 1;
331 int width
= getWidth();
332 if (endLine
> lineCount
) {
336 for (int i
= startLine
; i
< endLine
; i
++) {
338 text
= Integer
.toString(i
+ 1) + " ";
339 int w
= metrics
.stringWidth(text
);
341 g
.setColor(Color
.blue
);
342 g
.drawString(text
, 0, y
+ ascent
);
343 int x
= width
- ascent
;
345 // if currentPosition is not -1 then a red arrow will be drawn
346 if (i
== debugger
.getCurrentPosition()) {
347 drawArrow(g
, ascent
, x
, y
);
352 private void drawArrow(Graphics g
, int ascent
, int x
, int y
) {
353 Polygon arrow
= new Polygon();
357 arrow
.addPoint(dx
, dy
+ 3);
358 arrow
.addPoint(dx
+ 5, dy
+ 3);
359 for (x
= dx
+ 5; x
<= dx
+ 10; x
++, y
++) {
360 arrow
.addPoint(x
, y
);
362 for (x
= dx
+ 9; x
>= dx
+ 5; x
--, y
++) {
363 arrow
.addPoint(x
, y
);
365 arrow
.addPoint(dx
+ 5, dy
+ 7);
366 arrow
.addPoint(dx
, dy
+ 7);
368 g
.setColor(Color
.red
);
369 g
.fillPolygon(arrow
);
370 g
.setColor(Color
.black
);
371 g
.drawPolygon(arrow
);