Source code: jpicedt/ui/util/BeanShell.java
1 /*
2 BeanShell.java - July 30, 2002 - jPicEdt 1.3.2, a picture editor for LaTeX.
3 Copyright (C) 1999-2002 Sylvain Reynal
4
5 Département de Physique
6 Ecole Nationale Supérieure de l'Electronique et de ses Applications (ENSEA)
7 6, avenue du Ponceau
8 F-95014 CERGY CEDEX
9
10 Tel : +33 130 736 245
11 Fax : +33 130 736 667
12 e-mail : reynal@ensea.fr
13 jPicEdt web page : http://www.jpicedt.org/
14
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License
17 as published by the Free Software Foundation; either version 2
18 of the License, or any later version.
19
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 */
29
30 package jpicedt.ui.util;
31
32 import jpicedt.JPicEdt;
33
34 import javax.swing.*;
35 import java.awt.*;
36 import java.awt.event.*;
37 import java.util.*;
38 import java.io.*;
39
40 import bsh.*;
41 import bsh.util.*;
42
43 /**
44 * Wrapper for the BSH interpreter console + some useful static methods for running scripts from inside JPicEdt.
45 */
46 public class BeanShell extends JFrame implements Runnable {
47
48 private Interpreter interpreter; // for use by BeanShell() (i.e. BSH Console)
49
50 public static void _main(String[] args){
51 JFrame f = new JFrame();
52 JButton b = new JButton("console");
53 f.getContentPane().add(b);
54 b.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent ae){
55 BeanShell bsh = new BeanShell();
56 //Thread t = new Thread(bsh);t.start();
57 }});
58 f.addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent e){System.out.println("Exiting...");System.exit(0);}});
59 f.pack();
60 f.setVisible(true);
61 }
62
63 /**
64 * Open a new BSH console, and start the BSH interpreter interactively in it.
65 */
66 public BeanShell(){
67
68 super("BeanShell Console");
69 setSize(400,400);
70
71 //System.out.println("Creating console...");
72 JConsole console = new JConsole();
73 getContentPane().add(console);
74 //System.out.println("Creating interpreter...");
75 interpreter = new Interpreter(console);
76 //System.out.println("Setting predefined variables and methods...");
77 try {
78 //interpreter.eval("import jpicedt.*;");
79 interpreter.eval(
80 "preferences=jpicedt.JPicEdt.getPreferences();" +
81 "clipboard=jpicedt.JPicEdt.getClipboard();" +
82 "mdimgr=jpicedt.JPicEdt.getMDIManager();" +
83 "board(){return jpicedt.JPicEdt.getSelectedDrawingBoard();}" +
84 "canvas(){return jpicedt.JPicEdt.getSelectedCanvas();}" +
85 "drawing(){return jpicedt.JPicEdt.getSelectedDrawing();}" +
86 "editorkit(){return jpicedt.JPicEdt.getSelectedEditorKit();}");
87 }
88 catch (Exception ex){ex.printStackTrace();}
89 //System.out.println("Show !");
90 setVisible(true);
91 //System.out.println("Done !");
92
93 //SwingUtilities.invokeLater(this); // [pending] But why the hell does it block ????
94 Thread t = new Thread(this);t.start();
95 }
96
97 /**
98 * Run the BSH interpreter in interactive mode.
99 */
100 public void run(){
101 //System.out.println("Starting interpreter...");
102 interpreter.run(); // run interactively
103 }
104
105 /////////////////////// STATIC ///////////////////////////
106 /**
107 * Run a BSH script with the given path.
108 * @param scriptPath absolute script path
109 * @param scriptName script name, for instance "Repeat copy" ; used mainly for undo/redo menus.
110 */
111 public static void runScript(String scriptPath, String scriptName){
112 if (scriptPath == null) return;
113 //System.out.println("Running script : " + scriptPath);
114 Interpreter interpreter = new Interpreter(); // no console
115 try {
116 interpreter.eval(
117 "preferences=jpicedt.JPicEdt.getPreferences();" +
118 "clipboard=jpicedt.JPicEdt.getClipboard();" +
119 "mdimgr=jpicedt.JPicEdt.getMDIManager();" +
120 "board(){return jpicedt.JPicEdt.getSelectedDrawingBoard();}" +
121 "canvas(){return jpicedt.JPicEdt.getSelectedCanvas();}" +
122 "drawing(){return jpicedt.JPicEdt.getSelectedDrawing();}" +
123 "editorkit(){return jpicedt.JPicEdt.getSelectedEditorKit();}");
124 // start new UndoableEdit :
125 jpicedt.graphic.PECanvas canvas = jpicedt.JPicEdt.getSelectedCanvas();
126 if (canvas != null) canvas.beginUndoableUpdate("Script: " + scriptName);
127 interpreter.source(scriptPath);
128 if (canvas != null) canvas.endUndoableUpdate();
129 }
130 catch ( TargetError te ) { // The script threw an exception
131 JOptionPane.showMessageDialog(null,
132 "BeanShell script threw exception :"
133 + "\n\"" + te.getTarget() + "\""
134 + "\nat line " + te.getErrorLineNumber()
135 + " in file [" + te.getErrorSourceFile() + "]",
136 "BeanShell script",
137 JOptionPane.ERROR_MESSAGE);
138 }
139 catch ( EvalError ee ) { // General Error evaluating script
140 JOptionPane.showMessageDialog(null,
141 "BeanShell script evaluation error :"
142 + "\n\"" + ee.getErrorText() + "\""
143 + "\nat line " + ee.getErrorLineNumber()
144 + " in file [" + ee.getErrorSourceFile() + "]",
145 "BeanShell script",
146 JOptionPane.ERROR_MESSAGE);
147 }
148 catch(Exception ex){ // Other exception
149 JOptionPane.showMessageDialog(null,
150 "BeanShell script :\n" + ex.getMessage(),
151 "BeanShell script",
152 JOptionPane.ERROR_MESSAGE);
153 }
154 }
155
156 public static void main(String[] args){
157 JMenu menu = createMenu();
158 for (int i=0; i<menu.getMenuComponentCount(); i++){
159 System.out.println("item " + i + "=" + menu.getMenuComponent(i));
160 System.out.println();
161 }
162 }
163
164 /**
165 * Return a JMenu containing a hierarchy of JMenu's and JMenuItem's built from
166 * the BSH scripts contained, first in the installation script directory, then
167 * in the user script directory.
168 * @return an empty JMenu if no BSH scripts were found in either directory.
169 */
170 public static JMenu createMenu(){
171 // 1°) scan install script directory :
172 String jpicedtHome = jpicedt.MiscUtilities.getJPicEdtHome();
173 JMenu installScriptsMenu = null;
174 if (jpicedtHome!=null) installScriptsMenu=createMenu(new File(jpicedtHome,"macros"));
175 // 2°) scan user script directory :
176 JMenu userScriptsMenu = null;
177 if (JPicEdt.getUserSettingsDirectory() != null)
178 userScriptsMenu = createMenu(new File(JPicEdt.getUserSettingsDirectory(),"macros"));
179 // build array :
180 JMenu menu = new JMenu("Macros");
181 if (installScriptsMenu != null) {
182 Component[] cc = installScriptsMenu.getMenuComponents();
183 for(int i=0; i<cc.length; i++){
184 menu.add(cc[i]);
185 }
186 }
187 menu.add(new JSeparator());
188 if (userScriptsMenu != null) {
189 Component[] cc = userScriptsMenu.getMenuComponents();
190 for(int i=0; i<cc.length; i++){
191 menu.add(cc[i]);
192 }
193 }
194 return menu;
195 }
196
197 /**
198 * Return a JMenu containing a hierarchy of JMenu's and JMenuItem's built from
199 * the BSH scripts contained in the given directory and its children.
200 * @param directory path where to look for .bsh scripts, or subdirectories.
201 * @return null if directory (or one of its children) doesn't exist, or contains no BSH script.
202 */
203 private static JMenu createMenu(File directory){
204 if (!directory.exists()) return null;
205 String[] dirContent = directory.list();
206 if (dirContent==null) return null; // directory is empty
207 Arrays.sort(dirContent);
208 // [pending] sort dir content
209 JMenu menu = null; // so that we return null if nothing gets added...
210 for (int i=0; i<dirContent.length; i++){
211 String fileName = dirContent[i];
212 File file = new File(directory, fileName); // create full path name
213 // 1°) file is a BSH script :
214 if (fileName.toLowerCase().endsWith(".bsh")){
215 String label = fileName.substring(0,fileName.indexOf(".bsh")).replace('_',' ');
216 JMenuItem menuItem = new JMenuItem(label);
217 menuItem.addActionListener(new MenuScriptsAA(file.getPath(), label));
218 // [pending] add CTRL+? shortcut
219 if (menu==null) menu = new JMenu(directory.getName());
220 menu.add(menuItem);
221 }
222 // 2°) file is a subdirectory :
223 else if (file.isDirectory()){
224 JMenu subMenu = createMenu(file);
225 if (subMenu != null) {
226 if (menu==null) menu = new JMenu(directory.getName());
227 menu.add(subMenu);
228 }
229 }
230 }
231 return menu;
232 }
233
234 /**
235 * ActionAdapter for Scripts menuitems.
236 */
237 private static class MenuScriptsAA implements ActionListener{
238
239 String scriptPath;
240 String scriptName;
241 MenuScriptsAA(String scriptPath, String scriptName) {
242 this.scriptPath = scriptPath;
243 this.scriptName = scriptName;
244 }
245 public void actionPerformed(ActionEvent e) {
246 BeanShell.runScript(scriptPath, scriptName);
247 }
248 }
249
250 }
251
252