241a95fcbd245027b0e212227cc92e6821c7cfb5
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);
100 }
105 //########################################################################
106 //# S C R I P T S
107 //########################################################################
108 ScriptEngine engine;
110 HashMap<String, ScriptEngineAction> scriptEngineActions;
112 public void setEngine(ScriptEngine engine)
113 {
114 this.engine = engine;
115 this.engine.getContext().setWriter(terminal.getOutWriter());
116 this.engine.getContext().setErrorWriter(terminal.getErrWriter());
117 }
120 public ScriptEngine getEngine()
121 {
122 return engine;
123 }
126 public boolean setEngine(String name)
127 {
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;
134 }
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)
144 {
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;
163 }
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)
172 {
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;
190 }
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)
201 {
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);
209 }
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)
219 {
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;
257 }
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)
268 {
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);
276 }
279 class ScriptEngineAction extends AbstractAction
280 {
281 ScriptEngineFactory factory;
284 public void actionPerformed(ActionEvent evt)
285 {
286 setEngine(factory.getScriptEngine());
287 }
289 public ScriptEngineAction(ScriptEngineFactory factory)
290 {
291 super(factory.getEngineName(), null);
292 putValue(SHORT_DESCRIPTION, factory.getLanguageName());
293 this.factory = factory;
294 }
296 }
299 private void initScripts()
300 {
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 }
335 }
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
367 {
369 public void actionPerformed(ActionEvent evt)
370 {
371 //
372 }
374 public NewAction()
375 {
376 super("New", Resource.getIcon("document-new.png"));
377 putValue(SHORT_DESCRIPTION, "Create a new script file");
378 }
380 }
384 class OpenAction extends AbstractAction
385 {
387 public void actionPerformed(ActionEvent evt)
388 {
389 editor.openFile();
390 }
392 public OpenAction()
393 {
394 super("Open", Resource.getIcon("document-open.png"));
395 putValue(SHORT_DESCRIPTION, "Open a script file");
396 }
398 }
402 class QuitAction extends AbstractAction
403 {
405 public void actionPerformed(ActionEvent evt)
406 {
407 setVisible(false);
408 }
410 public QuitAction()
411 {
412 super("Quit", Resource.getIcon("system-log-out.png"));
413 putValue(SHORT_DESCRIPTION, "Quit this script console");
414 }
416 }
420 class RunAction extends AbstractAction
421 {
423 public void actionPerformed(ActionEvent evt)
424 {
425 String txt = editor.getText();
426 doRun(txt);
427 }
429 public RunAction()
430 {
431 super("Run", Resource.getIcon("go-next.png"));
432 putValue(SHORT_DESCRIPTION, "Run the script in the editor");
433 }
435 }
439 class SaveAction extends AbstractAction
440 {
442 public void actionPerformed(ActionEvent evt)
443 {
444 editor.saveFile();
445 }
447 public SaveAction()
448 {
449 super("Save", Resource.getIcon("document-save.png"));
450 putValue(SHORT_DESCRIPTION, "Save file");
451 }
453 }
457 class SaveAsAction extends AbstractAction
458 {
460 public void actionPerformed(ActionEvent evt)
461 {
462 editor.saveAsFile();
463 }
465 public SaveAsAction()
466 {
467 super("SaveAs", Resource.getIcon("document-save-as.png"));
468 putValue(SHORT_DESCRIPTION, "Save under a new file name");
469 }
471 }
475 class StopAction extends AbstractAction
476 {
478 public void actionPerformed(ActionEvent evt)
479 {
480 //#
481 }
483 public StopAction()
484 {
485 super("Stop", Resource.getIcon("process-stop.png"));
486 putValue(SHORT_DESCRIPTION, "Stop the running script");
487 }
489 }
493 HashMap<String, Action> actions;
494 void setupActions()
495 {
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());
504 }
507 public void enableAction(String name)
508 {
509 Action action = actions.get(name);
510 if (action == null)
511 return;
512 action.setEnabled(true);
513 }
515 public void disableAction(String name)
516 {
517 Action action = actions.get(name);
518 if (action == null)
519 return;
520 action.setEnabled(false);
521 }
525 //########################################################################
526 //# S E T U P
527 //########################################################################
529 JButton toolbarButton(Action action)
530 {
531 JButton btn = new JButton(action);
532 btn.setText("");
533 btn.setToolTipText((String)action.getValue(Action.SHORT_DESCRIPTION));
534 return btn;
535 }
538 private boolean setup()
539 {
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));
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);
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);
597 //######################################################
598 //# E N G I N E
599 //######################################################
600 initScripts();
602 return true;
603 }
610 public ScriptConsole()
611 {
612 setup();
613 }
616 private static ScriptConsole _instance = null;
617 public static ScriptConsole getInstance()
618 {
619 if (_instance == null)
620 _instance = new ScriptConsole();
621 return _instance;
622 }
625 public static void main(String argv[])
626 {
627 ScriptConsole sc = getInstance();
628 sc.setVisible(true);
629 }
632 }
633 //########################################################################
634 //# E N D O F F I L E
635 //########################################################################