Code

241a95fcbd245027b0e212227cc92e6821c7cfb5
[inkscape.git] / src / bind / java / org / inkscape / script / ScriptConsole.java
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.JMenuBar;
36 import javax.swing.JMenuItem;
37 import javax.swing.JRadioButtonMenuItem;
38 import javax.swing.ButtonGroup;
39 import javax.swing.JOptionPane;
40 import javax.swing.JTabbedPane;
41 import javax.swing.JToolBar;
42 import javax.swing.Action;
43 import javax.swing.AbstractAction;
46 import java.awt.event.ActionEvent;
47 import java.awt.event.ActionListener;
48 import java.awt.BorderLayout;
50 import java.io.File;
51 import java.io.FileReader;
52 import java.io.FileWriter;
53 import java.io.IOException;
56 import java.util.List;
57 import java.util.HashMap;
61 /**
62  *
63  */
64 public class ScriptConsole extends JFrame
65 {
66 Terminal    terminal;
67 Editor      editor;
69 JTabbedPane tabPane;
70 JToolBar    toolbar;
71 JMenuBar    menubar;
74 //########################################################################
75 //# MESSSAGES
76 //########################################################################
77 void err(String fmt, Object... arguments)
78 {
79     terminal.errorf("ScriptConsole err:" + fmt + "\n", arguments);
80 }
82 void msg(String fmt, Object... arguments)
83 {
84     terminal.outputf("ScriptConsole:" + fmt, arguments);
85 }
87 void trace(String fmt, Object... arguments)
88 {
89     terminal.outputf("ScriptConsole:" + fmt + "\n", arguments);
90 }
97 void alert(String msg)
98 {
99     JOptionPane.showMessageDialog(this, msg);
105 //########################################################################
106 //# S C R I P T S
107 //########################################################################
108 ScriptEngine engine;
110 HashMap<String, ScriptEngineAction> scriptEngineActions;
112 public void setEngine(ScriptEngine engine)
114     this.engine = engine;
115     this.engine.getContext().setWriter(terminal.getOutWriter());
116     this.engine.getContext().setErrorWriter(terminal.getErrWriter());
120 public ScriptEngine getEngine()
122     return engine;
126 public boolean setEngine(String name)
128     ScriptEngineAction action = scriptEngineActions.get(name);
129     if (action == null)
130         return false;
131     action.setEnabled(true);
132     setEngine(action.factory.getScriptEngine());
133     return true;
137 /**
138  * Run a script buffer
139  *
140  * @param str the script buffer to execute
141  * @return true if successful, else false
142  */
143 public boolean doRunCmd(String str)
145     if (engine == null)
146         {
147         err("No engine set");
148         return false;
149         }
151     //execute script from buffer
152     try
153         {
154         getEngine().eval(str);
155         }
156     catch (javax.script.ScriptException e)
157         {
158         err("Executing script: " + e);
159         //e.printStackTrace();
160         }
161     terminal.output("\nscript> ");
162     return true;
165 /**
166  * Run a script buffer
167  *
168  * @param str the script buffer to execute
169  * @return true if successful, else false
170  */
171 public boolean doRun(String str)
173     if (engine == null)
174         {
175         err("No engine set");
176         return false;
177         }
179     //execute script from buffer
180     try
181         {
182         getEngine().eval(str);
183         }
184     catch (javax.script.ScriptException e)
185         {
186         err("Executing script: " + e);
187         //e.printStackTrace();
188         }
189     return true;
193 /**
194  * Run a script buffer
195  *
196  * @param lang the scripting language to run
197  * @param str the script buffer to execute
198  * @return true if successful, else false
199  */
200 public boolean doRun(String lang, String str)
202     // find script engine
203     if (!setEngine(lang))
204         {
205         err("doRun: cannot find script engine '" + lang + "'");
206         return false;
207                 }
208     return doRun(str);
212 /**
213  * Run a script file
214  *
215  * @param fname the script file to execute
216  * @return true if successful, else false
217  */
218 public boolean doRunFile(String fname)
220     if (engine == null)
221         {
222         err("No engine set");
223         return false;
224         }
226     //try opening file and feeding into engine
227     FileReader in = null;
228     boolean ret = true;
229     try
230         {
231         in = new FileReader(fname);
232         }
233     catch (java.io.IOException e)
234         {
235         err("Executing file: " + e);
236         return false;
237         }
238     try
239         {
240         engine.eval(in);
241         }
242     catch (javax.script.ScriptException e)
243         {
244         err("Executing file: " + e);
245         ret = false;
246         }
247     try
248         {
249         in.close();
250         }
251     catch (java.io.IOException e)
252         {
253         err("Executing file: " + e);
254         return false;
255         }
256     return ret;
260 /**
261  * Run a script file
262  *
263  * @param lang the scripting language to run
264  * @param fname the script file to execute
265  * @return true if successful, else false
266  */
267 public boolean doRunFile(String lang, String fname)
269     // find script engine
270     if (!setEngine(lang))
271         {
272         err("doRunFile: cannot find script engine '" + lang + "'");
273         return false;
274                 }
275     return doRunFile(fname);
279 class ScriptEngineAction extends AbstractAction
281 ScriptEngineFactory factory;
284 public void actionPerformed(ActionEvent evt)
286     setEngine(factory.getScriptEngine());
289 public ScriptEngineAction(ScriptEngineFactory factory)
291     super(factory.getEngineName(), null);
292     putValue(SHORT_DESCRIPTION, factory.getLanguageName());
293     this.factory = factory;
299 private void initScripts()
301     JMenu menu = new JMenu("Language");
302     ButtonGroup group = new ButtonGroup();
303     menubar.add(menu);
305     ScriptEngineManager scriptEngineManager =
306              new ScriptEngineManager();
307     List<ScriptEngineFactory> factories =
308           scriptEngineManager.getEngineFactories();
309     for (ScriptEngineFactory factory: factories)
310             {
311         trace("ScriptEngineFactory Info");
312         String engName     = factory.getEngineName();
313         String engVersion  = factory.getEngineVersion();
314         String langName    = factory.getLanguageName();
315         String langVersion = factory.getLanguageVersion();
316         trace("\tScript Engine: %s (%s)", engName, engVersion);
317         List<String> engNames = factory.getNames();
318         for(String name: engNames)
319                     {
320             trace("\tEngine Alias: %s", name);
321             }
322         trace("\tLanguage: %s (%s)", langName, langVersion);
323         ScriptEngineAction action = new ScriptEngineAction(factory);
324         JRadioButtonMenuItem item = new JRadioButtonMenuItem(action);
325         group.add(item);
326         menu.add(item);
327         }
328     if (menu.getItemCount()>0)
329         {
330         JMenuItem item = menu.getItem(0);
331         group.setSelected(item.getModel(), true);
332         ScriptEngineAction action = (ScriptEngineAction)item.getAction();
333         setEngine(action.factory.getScriptEngine());
334         }
338 static final String defaultCodeStr =
339     "/**\n" +
340     " * This is some example Javascript.\n" +
341     " * Try executing\n" +
342     " */\n" +
343     "importPackage(javax.swing);\n" +
344     "function sayHello() {\n" +
345     "  JOptionPane.showMessageDialog(null, 'Hello, world!',\n" +
346         "     'Welcome to Inkscape', JOptionPane.WARNING_MESSAGE);\n" +
347     "}\n" +
348     "\n" +
349     "sayHello();\n" +
350     "\n";
353 //########################################################################
354 //# A C T I O N S
355 //########################################################################
356 Action newAction;
357 Action openAction;
358 Action quitAction;
359 Action runAction;
360 Action saveAction;
361 Action saveAsAction;
362 Action stopAction;
366 class NewAction extends AbstractAction
369 public void actionPerformed(ActionEvent evt)
371     //
374 public NewAction()
376     super("New", Resource.getIcon("document-new.png"));
377     putValue(SHORT_DESCRIPTION, "Create a new script file");
384 class OpenAction extends AbstractAction
387 public void actionPerformed(ActionEvent evt)
389     editor.openFile();
392 public OpenAction()
394     super("Open", Resource.getIcon("document-open.png"));
395     putValue(SHORT_DESCRIPTION, "Open a script file");
402 class QuitAction extends AbstractAction
405 public void actionPerformed(ActionEvent evt)
407     setVisible(false);
410 public QuitAction()
412     super("Quit", Resource.getIcon("system-log-out.png"));
413     putValue(SHORT_DESCRIPTION, "Quit this script console");
420 class RunAction extends AbstractAction
423 public void actionPerformed(ActionEvent evt)
425     String txt = editor.getText();
426     doRun(txt);
429 public RunAction()
431     super("Run", Resource.getIcon("go-next.png"));
432     putValue(SHORT_DESCRIPTION, "Run the script in the editor");
439 class SaveAction extends AbstractAction
442 public void actionPerformed(ActionEvent evt)
444     editor.saveFile();
447 public SaveAction()
449     super("Save", Resource.getIcon("document-save.png"));
450     putValue(SHORT_DESCRIPTION, "Save file");
457 class SaveAsAction extends AbstractAction
460 public void actionPerformed(ActionEvent evt)
462     editor.saveAsFile();
465 public SaveAsAction()
467     super("SaveAs", Resource.getIcon("document-save-as.png"));
468     putValue(SHORT_DESCRIPTION, "Save under a new file name");
475 class StopAction extends AbstractAction
478 public void actionPerformed(ActionEvent evt)
480     //#
483 public StopAction()
485     super("Stop", Resource.getIcon("process-stop.png"));
486     putValue(SHORT_DESCRIPTION, "Stop the running script");
493 HashMap<String, Action> actions;
494 void setupActions()
496     actions = new HashMap<String, Action>();
497     actions.put("New",    newAction    = new NewAction());
498     actions.put("Open",   openAction   = new OpenAction());
499     actions.put("Quit",   quitAction   = new QuitAction());
500     actions.put("Run",    runAction    = new RunAction());
501     actions.put("Save",   saveAction   = new SaveAction());
502     actions.put("SaveAs", saveAsAction = new SaveAsAction());
503     actions.put("Stop",   stopAction   = new StopAction());
507 public void enableAction(String name)
509     Action action = actions.get(name);
510     if (action == null)
511         return;
512     action.setEnabled(true);
515 public void disableAction(String name)
517     Action action = actions.get(name);
518     if (action == null)
519         return;
520     action.setEnabled(false);
525 //########################################################################
526 //# S E T U P
527 //########################################################################
529 JButton toolbarButton(Action action)
531     JButton btn = new JButton(action);
532     btn.setText("");
533     btn.setToolTipText((String)action.getValue(Action.SHORT_DESCRIPTION));
534     return btn;
538 private boolean setup()
540     setTitle("Inkscape Script Console");
541     setSize(600, 400);
542     setIconImage(Resource.getImage("inkscape.png"));
543     setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
545     //######################################################
546     //#  A C T I O N S
547     //######################################################
548     setupActions();
550     //######################################################
551     //# M E N U
552     //######################################################
553     menubar = new JMenuBar();
554     setJMenuBar(menubar);
556     JMenu menu = new JMenu("File");
557     menubar.add(menu);
558     menu.add(new JMenuItem(openAction));
559     menu.add(new JMenuItem(saveAction));
560     menu.add(new JMenuItem(saveAsAction));
561     menu.add(new JMenuItem(quitAction));
562         
563     menu = new JMenu("Run");
564     menubar.add(menu);
565     menu.add(new JMenuItem(runAction));
566     menu.add(new JMenuItem(stopAction));
568     //######################################################
569     //# T O O L B A R
570     //######################################################
571     toolbar = new JToolBar();
572     getContentPane().add(toolbar, BorderLayout.NORTH);
573     toolbar.add(toolbarButton(openAction));
574     toolbar.add(toolbarButton(saveAction));
575     toolbar.add(toolbarButton(runAction));
576     toolbar.add(toolbarButton(stopAction));
578     //######################################################
579     //# C O N T E N T
580     //######################################################
581     tabPane = new JTabbedPane();
582     getContentPane().add(tabPane, BorderLayout.CENTER);
583     
584     terminal = new Terminal();
585     tabPane.addTab("Console",
586                    Resource.getIcon("utilities-terminal.png"),
587                    terminal);
588     terminal.output("\nscript> ");
590     editor = new Editor(this);
591     tabPane.addTab("Script",
592                    Resource.getIcon("accessories-text-editor.png"),
593                    editor);
595     editor.setText(defaultCodeStr);
596     
597     //######################################################
598     //#  E N G I N E
599     //######################################################
600     initScripts();
602     return true;
610 public ScriptConsole()
612     setup();
616 private static ScriptConsole _instance = null;
617 public static ScriptConsole getInstance()
619     if (_instance == null)
620         _instance = new ScriptConsole();
621     return _instance;
625 public static void main(String argv[])
627     ScriptConsole sc = getInstance();
628     sc.setVisible(true);
633 //########################################################################
634 //# E N D    O F    F I L E
635 //########################################################################