Code

(no commit message)
[inkscape.git] / trunk / 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 public void err(String fmt, Object... arguments)
82 {
83     terminal.errorf("ScriptConsole err:" + fmt + "\n", arguments);
84 }
86 public void msg(String fmt, Object... arguments)
87 {
88     terminal.outputf("ScriptConsole:" + fmt, arguments);
89 }
91 public 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         for(String name: engine.getFactory().getNames())
137                     {
138             if (langName.equalsIgnoreCase(name))
139                 {
140                 setEngine(engine);
141                 return true;
142                             }
143                         }
144                 }
145     return false;
149 /**
150  * Run a script buffer
151  *
152  * @param str the script buffer to execute
153  * @return true if successful, else false
154  */
155 public boolean doRunCmd(String str)
157     if (engine == null)
158         {
159         err("No engine set");
160         return false;
161         }
163     //execute script from buffer
164     try
165         {
166         getEngine().eval(str);
167         }
168     catch (javax.script.ScriptException e)
169         {
170         err("Executing script: " + e);
171         //e.printStackTrace();
172         }
173     terminal.output("\nscript> ");
174     return true;
177 /**
178  * Run a script buffer
179  *
180  * @param str the script buffer to execute
181  * @return true if successful, else false
182  */
183 public boolean doRun(String str)
185     if (engine == null)
186         {
187         err("No engine set");
188         return false;
189         }
191     //execute script from buffer
192     try
193         {
194         getEngine().eval(str);
195         }
196     catch (javax.script.ScriptException e)
197         {
198         err("Executing script: " + e);
199         //e.printStackTrace();
200         }
201     return true;
205 /**
206  * Run a script buffer
207  *
208  * @param lang the scripting language to run
209  * @param str the script buffer to execute
210  * @return true if successful, else false
211  */
212 public boolean doRun(String lang, String str)
214     // find script engine
215     if (!setEngine(lang))
216         {
217         err("doRun: cannot find script engine '" + lang + "'");
218         return false;
219                 }
220     return doRun(str);
224 /**
225  * Run a script file
226  *
227  * @param fname the script file to execute
228  * @return true if successful, else false
229  */
230 public boolean doRunFile(String fname)
232     if (engine == null)
233         {
234         err("No engine set");
235         return false;
236         }
238     //try opening file and feeding into engine
239     FileReader in = null;
240     boolean ret = true;
241     try
242         {
243         in = new FileReader(fname);
244         }
245     catch (java.io.IOException e)
246         {
247         err("Executing file: " + e);
248         return false;
249         }
250     try
251         {
252         engine.eval(in);
253         }
254     catch (javax.script.ScriptException e)
255         {
256         err("Executing file: " + e);
257         ret = false;
258         }
259     try
260         {
261         in.close();
262         }
263     catch (java.io.IOException e)
264         {
265         err("Executing file: " + e);
266         return false;
267         }
268     return ret;
272 /**
273  * Run a script file
274  *
275  * @param lang the scripting language to run
276  * @param fname the script file to execute
277  * @return true if successful, else false
278  */
279 public boolean doRunFile(String lang, String fname)
281     // find script engine
282     if (!setEngine(lang))
283         {
284         err("doRunFile: cannot find script engine '" + lang + "'");
285         return false;
286                 }
287     return doRunFile(fname);
292 class ScriptEngineAction extends AbstractAction
296 public void actionPerformed(ActionEvent evt)
298     int index = engineBox.getSelectedIndex();
299     if (index<0)
300         return;
301     ScriptEngine engine = engines.get(index);
302     setEngine(engine);
305 public ScriptEngineAction()
307     super("SelectEngine", null);
308     putValue(SHORT_DESCRIPTION, "Select a scripting engine");
314 private void initScripts()
316     engines = new ArrayList<ScriptEngine>();
317     Action action = new ScriptEngineAction();
318     engineBox = new JComboBox();
319     engineBox.setAction(action);
320     engineBox.setEditable(false);
321     toolbar.add(engineBox);
323     ScriptEngineManager scriptEngineManager =
324              new ScriptEngineManager();
325     List<ScriptEngineFactory> factories =
326                 scriptEngineManager.getEngineFactories();
327     for (ScriptEngineFactory factory: factories)
328             {
329         trace("ScriptEngineFactory Info");
330         String engName     = factory.getEngineName();
331         String engVersion  = factory.getEngineVersion();
332         String fullEngName = engName + " (" + engVersion + ")";
333         String langName    = factory.getLanguageName();
334         String langVersion = factory.getLanguageVersion();
335         String fullLangName = langName + " (" + langVersion + ")";
336         trace("\t" + fullEngName);
337         List<String> engNames = factory.getNames();
338         for(String name: engNames)
339                     {
340             trace("\tEngine Alias: " + name);
341             }
342         trace("\t" + fullLangName);
343         engines.add(factory.getScriptEngine());
344         engineBox.addItem(fullLangName + " / " + fullEngName);
345         }
346     if (engineBox.getItemCount()>0)
347         {
348         engineBox.setSelectedIndex(0);
349         setEngine(engines.get(0));
350         }
354 static final String defaultCodeStr =
355     "/**\n" +
356     " * This is some example Javascript.\n" +
357     " * Try executing\n" +
358     " */\n" +
359     "importPackage(javax.swing);\n" +
360     "function sayHello() {\n" +
361     "  JOptionPane.showMessageDialog(null, 'Hello, world!',\n" +
362         "     'Welcome to Inkscape', JOptionPane.WARNING_MESSAGE);\n" +
363     "}\n" +
364     "\n" +
365     "sayHello();\n" +
366     "\n";
369 //########################################################################
370 //# A C T I O N S
371 //########################################################################
372 Action newAction;
373 Action openAction;
374 Action quitAction;
375 Action runAction;
376 Action saveAction;
377 Action saveAsAction;
378 Action stopAction;
382 class NewAction extends AbstractAction
385 public void actionPerformed(ActionEvent evt)
387     //
390 public NewAction()
392     super("New", Resource.getIcon("document-new.png"));
393     putValue(SHORT_DESCRIPTION, "Create a new script file");
400 class OpenAction extends AbstractAction
403 public void actionPerformed(ActionEvent evt)
405     editor.openFile();
408 public OpenAction()
410     super("Open", Resource.getIcon("document-open.png"));
411     putValue(SHORT_DESCRIPTION, "Open a script file");
418 class QuitAction extends AbstractAction
421 public void actionPerformed(ActionEvent evt)
423     setVisible(false);
426 public QuitAction()
428     super("Quit", Resource.getIcon("system-log-out.png"));
429     putValue(SHORT_DESCRIPTION, "Quit this script console");
436 class RunAction extends AbstractAction
439 public void actionPerformed(ActionEvent evt)
441     String txt = editor.getText();
442     doRun(txt);
445 public RunAction()
447     super("Run", Resource.getIcon("go-next.png"));
448     putValue(SHORT_DESCRIPTION, "Run the script in the editor");
455 class SaveAction extends AbstractAction
458 public void actionPerformed(ActionEvent evt)
460     editor.saveFile();
463 public SaveAction()
465     super("Save", Resource.getIcon("document-save.png"));
466     putValue(SHORT_DESCRIPTION, "Save file");
473 class SaveAsAction extends AbstractAction
476 public void actionPerformed(ActionEvent evt)
478     editor.saveAsFile();
481 public SaveAsAction()
483     super("SaveAs", Resource.getIcon("document-save-as.png"));
484     putValue(SHORT_DESCRIPTION, "Save under a new file name");
491 class StopAction extends AbstractAction
494 public void actionPerformed(ActionEvent evt)
496     //#
499 public StopAction()
501     super("Stop", Resource.getIcon("process-stop.png"));
502     putValue(SHORT_DESCRIPTION, "Stop the running script");
509 HashMap<String, Action> actions;
510 void setupActions()
512     actions = new HashMap<String, Action>();
513     actions.put("New",    newAction    = new NewAction());
514     actions.put("Open",   openAction   = new OpenAction());
515     actions.put("Quit",   quitAction   = new QuitAction());
516     actions.put("Run",    runAction    = new RunAction());
517     actions.put("Save",   saveAction   = new SaveAction());
518     actions.put("SaveAs", saveAsAction = new SaveAsAction());
519     actions.put("Stop",   stopAction   = new StopAction());
523 public void enableAction(String name)
525     Action action = actions.get(name);
526     if (action == null)
527         return;
528     action.setEnabled(true);
531 public void disableAction(String name)
533     Action action = actions.get(name);
534     if (action == null)
535         return;
536     action.setEnabled(false);
541 //########################################################################
542 //# S E T U P
543 //########################################################################
545 JButton toolbarButton(Action action)
547     JButton btn = new JButton(action);
548     btn.setText("");
549     btn.setToolTipText((String)action.getValue(Action.SHORT_DESCRIPTION));
550     return btn;
554 private boolean setup()
556     setTitle("Inkscape Script Console");
557     setSize(600, 400);
558     setIconImage(Resource.getImage("inkscape.png"));
559     setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
561     //######################################################
562     //#  A C T I O N S
563     //######################################################
564     setupActions();
566     //######################################################
567     //# M E N U
568     //######################################################
569     menubar = new JMenuBar();
570     setJMenuBar(menubar);
572     JMenu menu = new JMenu("File");
573     menubar.add(menu);
574     menu.add(new JMenuItem(openAction));
575     menu.add(new JMenuItem(saveAction));
576     menu.add(new JMenuItem(saveAsAction));
577     menu.add(new JMenuItem(quitAction));
578         
579     menu = new JMenu("Run");
580     menubar.add(menu);
581     menu.add(new JMenuItem(runAction));
582     menu.add(new JMenuItem(stopAction));
584     //######################################################
585     //# T O O L B A R
586     //######################################################
587     toolbar = new JToolBar();
588     getContentPane().add(toolbar, BorderLayout.NORTH);
589     toolbar.add(toolbarButton(openAction));
590     toolbar.add(toolbarButton(saveAction));
591     toolbar.add(toolbarButton(runAction));
592     toolbar.add(toolbarButton(stopAction));
594     //######################################################
595     //# C O N T E N T
596     //######################################################
597     tabPane = new JTabbedPane();
598     getContentPane().add(tabPane, BorderLayout.CENTER);
599     
600     terminal = new Terminal();
601     tabPane.addTab("Console",
602                    Resource.getIcon("utilities-terminal.png"),
603                    terminal);
604     terminal.output("\nscript> ");
606     editor = new Editor(this);
607     tabPane.addTab("Script",
608                    Resource.getIcon("accessories-text-editor.png"),
609                    editor);
611     editor.setText(defaultCodeStr);
612     
613     //######################################################
614     //#  E N G I N E
615     //######################################################
616     initScripts();
618     return true;
626 public ScriptConsole()
628     setup();
632 private static ScriptConsole _instance = null;
633 public static ScriptConsole getInstance()
635     if (_instance == null)
636         _instance = new ScriptConsole();
637     return _instance;
641 public static void main(String argv[])
643     ScriptConsole sc = getInstance();
644     sc.setVisible(true);
649 //########################################################################
650 //# E N D    O F    F I L E
651 //########################################################################