890d78189184be78e9773d226c3f272556bdb3c1
1 /**
2 * This is a simple mechanism to bind Inkscape to Java, and thence
3 * to all of the nice things that can be layered upon that.
4 *
5 * Authors:
6 * Bob Jamison
7 *
8 * Copyright (C) 2007-2008 Bob Jamison
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 3 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
25 package org.inkscape.script;
27 import org.inkscape.cmn.Resource;
29 import javax.script.*;
31 import javax.swing.WindowConstants;
32 import javax.swing.JFrame;
33 import javax.swing.JButton;
34 import javax.swing.JMenu;
35 import javax.swing.JLabel;
36 import javax.swing.JMenuBar;
37 import javax.swing.JMenuItem;
38 import javax.swing.JComboBox;
39 import javax.swing.ButtonGroup;
40 import javax.swing.JOptionPane;
41 import javax.swing.JTabbedPane;
42 import javax.swing.JToolBar;
43 import javax.swing.Action;
44 import javax.swing.AbstractAction;
47 import java.awt.event.ActionEvent;
48 import java.awt.event.ActionListener;
49 import java.awt.BorderLayout;
51 import java.io.File;
52 import java.io.FileReader;
53 import java.io.FileWriter;
54 import java.io.IOException;
57 import java.util.List;
58 import java.util.HashMap;
59 import java.util.ArrayList;
60 import java.util.List;
64 /**
65 * This is the main Script Console window. It contains
66 * a terminal-like console, and a simple script editor.
67 */
68 public class ScriptConsole extends JFrame
69 {
70 Terminal terminal;
71 Editor editor;
73 JTabbedPane tabPane;
74 JToolBar toolbar;
75 JMenuBar menubar;
76 JComboBox engineBox;
78 //########################################################################
79 //# MESSSAGES
80 //########################################################################
81 void err(String fmt, Object... arguments)
82 {
83 terminal.errorf("ScriptConsole err:" + fmt + "\n", arguments);
84 }
86 void msg(String fmt, Object... arguments)
87 {
88 terminal.outputf("ScriptConsole:" + fmt, arguments);
89 }
91 void trace(String fmt, Object... arguments)
92 {
93 terminal.outputf("ScriptConsole:" + fmt + "\n", arguments);
94 }
101 void alert(String msg)
102 {
103 JOptionPane.showMessageDialog(this, msg);
104 }
109 //########################################################################
110 //# S C R I P T S
111 //########################################################################
112 ScriptEngine engine;
114 ArrayList<ScriptEngine> engines;
117 public void setEngine(ScriptEngine engine)
118 {
119 this.engine = engine;
120 this.engine.getContext().setWriter(terminal.getOutWriter());
121 this.engine.getContext().setErrorWriter(terminal.getErrWriter());
122 //do something to make the combobox show the current engine
123 }
126 public ScriptEngine getEngine()
127 {
128 return engine;
129 }
132 public boolean setEngine(String langName)
133 {
134 for (ScriptEngine engine : engines)
135 {
136 if (langName.equalsIgnoreCase(engine.getFactory().getLanguageName()))
137 {
138 setEngine(engine);
139 return true;
140 }
141 }
142 return false;
143 }
146 /**
147 * Run a script buffer
148 *
149 * @param str the script buffer to execute
150 * @return true if successful, else false
151 */
152 public boolean doRunCmd(String str)
153 {
154 if (engine == null)
155 {
156 err("No engine set");
157 return false;
158 }
160 //execute script from buffer
161 try
162 {
163 getEngine().eval(str);
164 }
165 catch (javax.script.ScriptException e)
166 {
167 err("Executing script: " + e);
168 //e.printStackTrace();
169 }
170 terminal.output("\nscript> ");
171 return true;
172 }
174 /**
175 * Run a script buffer
176 *
177 * @param str the script buffer to execute
178 * @return true if successful, else false
179 */
180 public boolean doRun(String str)
181 {
182 if (engine == null)
183 {
184 err("No engine set");
185 return false;
186 }
188 //execute script from buffer
189 try
190 {
191 getEngine().eval(str);
192 }
193 catch (javax.script.ScriptException e)
194 {
195 err("Executing script: " + e);
196 //e.printStackTrace();
197 }
198 return true;
199 }
202 /**
203 * Run a script buffer
204 *
205 * @param lang the scripting language to run
206 * @param str the script buffer to execute
207 * @return true if successful, else false
208 */
209 public boolean doRun(String lang, String str)
210 {
211 // find script engine
212 if (!setEngine(lang))
213 {
214 err("doRun: cannot find script engine '" + lang + "'");
215 return false;
216 }
217 return doRun(str);
218 }
221 /**
222 * Run a script file
223 *
224 * @param fname the script file to execute
225 * @return true if successful, else false
226 */
227 public boolean doRunFile(String fname)
228 {
229 if (engine == null)
230 {
231 err("No engine set");
232 return false;
233 }
235 //try opening file and feeding into engine
236 FileReader in = null;
237 boolean ret = true;
238 try
239 {
240 in = new FileReader(fname);
241 }
242 catch (java.io.IOException e)
243 {
244 err("Executing file: " + e);
245 return false;
246 }
247 try
248 {
249 engine.eval(in);
250 }
251 catch (javax.script.ScriptException e)
252 {
253 err("Executing file: " + e);
254 ret = false;
255 }
256 try
257 {
258 in.close();
259 }
260 catch (java.io.IOException e)
261 {
262 err("Executing file: " + e);
263 return false;
264 }
265 return ret;
266 }
269 /**
270 * Run a script file
271 *
272 * @param lang the scripting language to run
273 * @param fname the script file to execute
274 * @return true if successful, else false
275 */
276 public boolean doRunFile(String lang, String fname)
277 {
278 // find script engine
279 if (!setEngine(lang))
280 {
281 err("doRunFile: cannot find script engine '" + lang + "'");
282 return false;
283 }
284 return doRunFile(fname);
285 }
289 class ScriptEngineAction extends AbstractAction
290 {
293 public void actionPerformed(ActionEvent evt)
294 {
295 int index = engineBox.getSelectedIndex();
296 if (index<0)
297 return;
298 ScriptEngine engine = engines.get(index);
299 setEngine(engine);
300 }
302 public ScriptEngineAction()
303 {
304 super("SelectEngine", null);
305 putValue(SHORT_DESCRIPTION, "Select a scripting engine");
306 }
308 }
311 private void initScripts()
312 {
313 engines = new ArrayList<ScriptEngine>();
314 Action action = new ScriptEngineAction();
315 engineBox = new JComboBox();
316 engineBox.setAction(action);
317 engineBox.setEditable(false);
318 toolbar.add(engineBox);
320 ScriptEngineManager scriptEngineManager =
321 new ScriptEngineManager();
322 List<ScriptEngineFactory> factories =
323 scriptEngineManager.getEngineFactories();
324 for (ScriptEngineFactory factory: factories)
325 {
326 trace("ScriptEngineFactory Info");
327 String engName = factory.getEngineName();
328 String engVersion = factory.getEngineVersion();
329 String langName = factory.getLanguageName();
330 String langVersion = factory.getLanguageVersion();
331 trace("\tScript Engine: %s (%s)", engName, engVersion);
332 List<String> engNames = factory.getNames();
333 for(String name: engNames)
334 {
335 trace("\tEngine Alias: %s", name);
336 }
337 trace("\tLanguage: %s (%s)", langName, langVersion);
338 engines.add(factory.getScriptEngine());
339 //JLabel item = new JLabel(langName);
340 engineBox.addItem(langName);
341 }
342 if (engineBox.getItemCount()>0)
343 {
344 engineBox.setSelectedIndex(0);
345 setEngine(engines.get(0));
346 }
347 }
350 static final String defaultCodeStr =
351 "/**\n" +
352 " * This is some example Javascript.\n" +
353 " * Try executing\n" +
354 " */\n" +
355 "importPackage(javax.swing);\n" +
356 "function sayHello() {\n" +
357 " JOptionPane.showMessageDialog(null, 'Hello, world!',\n" +
358 " 'Welcome to Inkscape', JOptionPane.WARNING_MESSAGE);\n" +
359 "}\n" +
360 "\n" +
361 "sayHello();\n" +
362 "\n";
365 //########################################################################
366 //# A C T I O N S
367 //########################################################################
368 Action newAction;
369 Action openAction;
370 Action quitAction;
371 Action runAction;
372 Action saveAction;
373 Action saveAsAction;
374 Action stopAction;
378 class NewAction extends AbstractAction
379 {
381 public void actionPerformed(ActionEvent evt)
382 {
383 //
384 }
386 public NewAction()
387 {
388 super("New", Resource.getIcon("document-new.png"));
389 putValue(SHORT_DESCRIPTION, "Create a new script file");
390 }
392 }
396 class OpenAction extends AbstractAction
397 {
399 public void actionPerformed(ActionEvent evt)
400 {
401 editor.openFile();
402 }
404 public OpenAction()
405 {
406 super("Open", Resource.getIcon("document-open.png"));
407 putValue(SHORT_DESCRIPTION, "Open a script file");
408 }
410 }
414 class QuitAction extends AbstractAction
415 {
417 public void actionPerformed(ActionEvent evt)
418 {
419 setVisible(false);
420 }
422 public QuitAction()
423 {
424 super("Quit", Resource.getIcon("system-log-out.png"));
425 putValue(SHORT_DESCRIPTION, "Quit this script console");
426 }
428 }
432 class RunAction extends AbstractAction
433 {
435 public void actionPerformed(ActionEvent evt)
436 {
437 String txt = editor.getText();
438 doRun(txt);
439 }
441 public RunAction()
442 {
443 super("Run", Resource.getIcon("go-next.png"));
444 putValue(SHORT_DESCRIPTION, "Run the script in the editor");
445 }
447 }
451 class SaveAction extends AbstractAction
452 {
454 public void actionPerformed(ActionEvent evt)
455 {
456 editor.saveFile();
457 }
459 public SaveAction()
460 {
461 super("Save", Resource.getIcon("document-save.png"));
462 putValue(SHORT_DESCRIPTION, "Save file");
463 }
465 }
469 class SaveAsAction extends AbstractAction
470 {
472 public void actionPerformed(ActionEvent evt)
473 {
474 editor.saveAsFile();
475 }
477 public SaveAsAction()
478 {
479 super("SaveAs", Resource.getIcon("document-save-as.png"));
480 putValue(SHORT_DESCRIPTION, "Save under a new file name");
481 }
483 }
487 class StopAction extends AbstractAction
488 {
490 public void actionPerformed(ActionEvent evt)
491 {
492 //#
493 }
495 public StopAction()
496 {
497 super("Stop", Resource.getIcon("process-stop.png"));
498 putValue(SHORT_DESCRIPTION, "Stop the running script");
499 }
501 }
505 HashMap<String, Action> actions;
506 void setupActions()
507 {
508 actions = new HashMap<String, Action>();
509 actions.put("New", newAction = new NewAction());
510 actions.put("Open", openAction = new OpenAction());
511 actions.put("Quit", quitAction = new QuitAction());
512 actions.put("Run", runAction = new RunAction());
513 actions.put("Save", saveAction = new SaveAction());
514 actions.put("SaveAs", saveAsAction = new SaveAsAction());
515 actions.put("Stop", stopAction = new StopAction());
516 }
519 public void enableAction(String name)
520 {
521 Action action = actions.get(name);
522 if (action == null)
523 return;
524 action.setEnabled(true);
525 }
527 public void disableAction(String name)
528 {
529 Action action = actions.get(name);
530 if (action == null)
531 return;
532 action.setEnabled(false);
533 }
537 //########################################################################
538 //# S E T U P
539 //########################################################################
541 JButton toolbarButton(Action action)
542 {
543 JButton btn = new JButton(action);
544 btn.setText("");
545 btn.setToolTipText((String)action.getValue(Action.SHORT_DESCRIPTION));
546 return btn;
547 }
550 private boolean setup()
551 {
552 setTitle("Inkscape Script Console");
553 setSize(600, 400);
554 setIconImage(Resource.getImage("inkscape.png"));
555 setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
557 //######################################################
558 //# A C T I O N S
559 //######################################################
560 setupActions();
562 //######################################################
563 //# M E N U
564 //######################################################
565 menubar = new JMenuBar();
566 setJMenuBar(menubar);
568 JMenu menu = new JMenu("File");
569 menubar.add(menu);
570 menu.add(new JMenuItem(openAction));
571 menu.add(new JMenuItem(saveAction));
572 menu.add(new JMenuItem(saveAsAction));
573 menu.add(new JMenuItem(quitAction));
575 menu = new JMenu("Run");
576 menubar.add(menu);
577 menu.add(new JMenuItem(runAction));
578 menu.add(new JMenuItem(stopAction));
580 //######################################################
581 //# T O O L B A R
582 //######################################################
583 toolbar = new JToolBar();
584 getContentPane().add(toolbar, BorderLayout.NORTH);
585 toolbar.add(toolbarButton(openAction));
586 toolbar.add(toolbarButton(saveAction));
587 toolbar.add(toolbarButton(runAction));
588 toolbar.add(toolbarButton(stopAction));
590 //######################################################
591 //# C O N T E N T
592 //######################################################
593 tabPane = new JTabbedPane();
594 getContentPane().add(tabPane, BorderLayout.CENTER);
596 terminal = new Terminal();
597 tabPane.addTab("Console",
598 Resource.getIcon("utilities-terminal.png"),
599 terminal);
600 terminal.output("\nscript> ");
602 editor = new Editor(this);
603 tabPane.addTab("Script",
604 Resource.getIcon("accessories-text-editor.png"),
605 editor);
607 editor.setText(defaultCodeStr);
609 //######################################################
610 //# E N G I N E
611 //######################################################
612 initScripts();
614 return true;
615 }
622 public ScriptConsole()
623 {
624 setup();
625 }
628 private static ScriptConsole _instance = null;
629 public static ScriptConsole getInstance()
630 {
631 if (_instance == null)
632 _instance = new ScriptConsole();
633 return _instance;
634 }
637 public static void main(String argv[])
638 {
639 ScriptConsole sc = getInstance();
640 sc.setVisible(true);
641 }
644 }
645 //########################################################################
646 //# E N D O F F I L E
647 //########################################################################