Code

890d78189184be78e9773d226c3f272556bdb3c1
[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.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)
103     JOptionPane.showMessageDialog(this, msg);
109 //########################################################################
110 //# S C R I P T S
111 //########################################################################
112 ScriptEngine engine;
114 ArrayList<ScriptEngine> engines;
117 public void setEngine(ScriptEngine engine)
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
126 public ScriptEngine getEngine()
128     return engine;
132 public boolean setEngine(String langName)
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;
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)
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;
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)
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;
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)
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);
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)
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;
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)
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);
289 class ScriptEngineAction extends AbstractAction
293 public void actionPerformed(ActionEvent evt)
295     int index = engineBox.getSelectedIndex();
296     if (index<0)
297         return;
298     ScriptEngine engine = engines.get(index);
299     setEngine(engine);
302 public ScriptEngineAction()
304     super("SelectEngine", null);
305     putValue(SHORT_DESCRIPTION, "Select a scripting engine");
311 private void initScripts()
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         }
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
381 public void actionPerformed(ActionEvent evt)
383     //
386 public NewAction()
388     super("New", Resource.getIcon("document-new.png"));
389     putValue(SHORT_DESCRIPTION, "Create a new script file");
396 class OpenAction extends AbstractAction
399 public void actionPerformed(ActionEvent evt)
401     editor.openFile();
404 public OpenAction()
406     super("Open", Resource.getIcon("document-open.png"));
407     putValue(SHORT_DESCRIPTION, "Open a script file");
414 class QuitAction extends AbstractAction
417 public void actionPerformed(ActionEvent evt)
419     setVisible(false);
422 public QuitAction()
424     super("Quit", Resource.getIcon("system-log-out.png"));
425     putValue(SHORT_DESCRIPTION, "Quit this script console");
432 class RunAction extends AbstractAction
435 public void actionPerformed(ActionEvent evt)
437     String txt = editor.getText();
438     doRun(txt);
441 public RunAction()
443     super("Run", Resource.getIcon("go-next.png"));
444     putValue(SHORT_DESCRIPTION, "Run the script in the editor");
451 class SaveAction extends AbstractAction
454 public void actionPerformed(ActionEvent evt)
456     editor.saveFile();
459 public SaveAction()
461     super("Save", Resource.getIcon("document-save.png"));
462     putValue(SHORT_DESCRIPTION, "Save file");
469 class SaveAsAction extends AbstractAction
472 public void actionPerformed(ActionEvent evt)
474     editor.saveAsFile();
477 public SaveAsAction()
479     super("SaveAs", Resource.getIcon("document-save-as.png"));
480     putValue(SHORT_DESCRIPTION, "Save under a new file name");
487 class StopAction extends AbstractAction
490 public void actionPerformed(ActionEvent evt)
492     //#
495 public StopAction()
497     super("Stop", Resource.getIcon("process-stop.png"));
498     putValue(SHORT_DESCRIPTION, "Stop the running script");
505 HashMap<String, Action> actions;
506 void setupActions()
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());
519 public void enableAction(String name)
521     Action action = actions.get(name);
522     if (action == null)
523         return;
524     action.setEnabled(true);
527 public void disableAction(String name)
529     Action action = actions.get(name);
530     if (action == null)
531         return;
532     action.setEnabled(false);
537 //########################################################################
538 //# S E T U P
539 //########################################################################
541 JButton toolbarButton(Action action)
543     JButton btn = new JButton(action);
544     btn.setText("");
545     btn.setToolTipText((String)action.getValue(Action.SHORT_DESCRIPTION));
546     return btn;
550 private boolean setup()
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));
574         
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);
595     
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);
608     
609     //######################################################
610     //#  E N G I N E
611     //######################################################
612     initScripts();
614     return true;
622 public ScriptConsole()
624     setup();
628 private static ScriptConsole _instance = null;
629 public static ScriptConsole getInstance()
631     if (_instance == null)
632         _instance = new ScriptConsole();
633     return _instance;
637 public static void main(String argv[])
639     ScriptConsole sc = getInstance();
640     sc.setVisible(true);
645 //########################################################################
646 //# E N D    O F    F I L E
647 //########################################################################