source: trunk/src/org/expeditee/items/widgets/JSWidget.java@ 1102

Last change on this file since 1102 was 1102, checked in by davidb, 6 years ago

Reworking of the code-base to separate logic from graphics. This version of Expeditee now supports a JFX graphics as an alternative to SWING

File size: 5.9 KB
Line 
1/**
2 * JSWidget.java
3 * Copyright (C) 2010 New Zealand Digital Library, http://expeditee.org
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package org.expeditee.items.widgets;
20
21import java.awt.BorderLayout;
22import java.awt.Component;
23import java.awt.Graphics2D;
24import java.util.LinkedList;
25import java.util.List;
26
27import javax.script.Invocable;
28import javax.script.ScriptEngine;
29import javax.script.ScriptEngineManager;
30import javax.script.ScriptException;
31
32import javax.swing.JPanel;
33
34import org.expeditee.gui.DisplayController;
35import org.expeditee.items.ItemParentStateChangedEvent;
36import org.expeditee.items.JSThreadable;
37import org.expeditee.items.Text;
38
39/**
40 * Class for extending Expeditee with widgets coded in Javascript
41 *
42 * @author jts21
43 *
44 */
45public class JSWidget extends DataFrameWidget implements JSThreadable {
46
47 private static ScriptEngineManager scriptEngineManager = null;
48 private static ScriptEngine globalScriptEngine = null;
49 private static Object global = null;
50
51 // a method to run that will set up and return the root JComponent for this Widget
52 private final String init;
53 // a method to run to populate a List<String> with our state
54 private final String save;
55 // a method to run that will load state from a String[]
56 private final String load;
57
58 // we have our own script context since it needs to have some global variables which are specific to each widget
59 private final ScriptEngine scriptEngine;
60 private final Invocable invocable;
61 // component created by running our constructor
62 private final Component component;
63 // container for our component
64 private final JPanel container;
65
66 static {
67 try {
68 scriptEngineManager = new ScriptEngineManager();
69 globalScriptEngine = scriptEngineManager.getEngineByMimeType("application/javascript");
70 global = globalScriptEngine.eval("new Object()");
71 } catch (ScriptException e) {
72 e.printStackTrace();
73 }
74 }
75
76 private static Text getSauce() {
77 Text source = new Text(DisplayController.getCurrentFrame().getNextItemID(), "@iw: org.expeditee.items.widgets.JSWidget");
78 source.setParent(DisplayController.getCurrentFrame());
79 return source;
80 }
81
82 private JSWidget(Text source, int width, int height, String init, String save, String load) throws Exception {
83 super(source, new JPanel(new BorderLayout()), -1, width, -1, -1, height, -1);
84
85 this.init = init;
86 this.save = save;
87 this.load = load;
88 this.container = (JPanel) super._swingComponent;
89 this.scriptEngine = scriptEngineManager.getEngineByMimeType("application/javascript");
90 this.invocable = (Invocable) this.scriptEngine;
91 this.scriptEngine.put("global", global);
92 this.scriptEngine.put("invocable", this.invocable);
93 this.scriptEngine.put("widget", this);
94 this.scriptEngine.put("container", this.container);
95 System.out.println(this.init);
96 this.component = (Component) this.scriptEngine.eval("var init = " + this.init + "\ninit()");
97 this.container.add(component);
98 this.scriptEngine.put("component", this.component);
99 this.scriptEngine.eval("save = " + this.save);
100 this.scriptEngine.eval("load = " + this.load);
101 }
102
103 private JSWidget(Text source, String init, String save, String load) throws Exception {
104 this(source, 100, 100, init, save, load);
105 }
106
107 public JSWidget(Text source, String[] args) throws Exception {
108 this(source, source.getData().get(0).replaceAll("\\\\n", "\n"),
109 source.getData().get(1).replaceAll("\\\\n", "\n"),
110 source.getData().get(2).replaceAll("\\\\n", "\n"));
111 this.invocable.invokeFunction("load", (Object) args);
112 }
113
114 public JSWidget(int width, int height, String init, String save, String load) throws Exception {
115 this(getSauce(), width, height, init, save, load);
116 }
117
118 public JSWidget(String init, String save, String load) throws Exception {
119 this(100, 100, init, save, load);
120 }
121
122 @Override
123 protected List<String> getData() {
124 List<String> value = new LinkedList<String>();
125 value.add(this.init.replaceAll("[\n\r]", "\\\\n"));
126 value.add(this.save.replaceAll("[\n\r]", "\\\\n"));
127 value.add(this.load.replaceAll("[\n\r]", "\\\\n"));
128 return value;
129 }
130
131 @Override
132 protected String[] getArgs() {
133 try {
134 List<String> args = new LinkedList<String>();
135 this.invocable.invokeFunction("save", (Object)args);
136 return args.toArray(new String[0]);
137 } catch (Exception e) {
138 e.printStackTrace();
139 return null;
140 }
141 }
142
143 private List<JSThread> threads = new LinkedList<JSThread>();
144
145 public JSThread addThread(String code) {
146 JSThread t = new JSThread(scriptEngine, code);
147 this.threads.add(t);
148 return t;
149 }
150
151 @Override
152 public void onParentStateChanged(int e) {
153 switch (e) {
154 case ItemParentStateChangedEvent.EVENT_TYPE_REMOVED:
155 case ItemParentStateChangedEvent.EVENT_TYPE_REMOVED_VIA_OVERLAY:
156 case ItemParentStateChangedEvent.EVENT_TYPE_HIDDEN:
157 for(JSThread t : this.threads) {
158 t.kill();
159 }
160 break;
161
162 case ItemParentStateChangedEvent.EVENT_TYPE_ADDED:
163 case ItemParentStateChangedEvent.EVENT_TYPE_ADDED_VIA_OVERLAY:
164 case ItemParentStateChangedEvent.EVENT_TYPE_SHOWN:
165 case ItemParentStateChangedEvent.EVENT_TYPE_SHOWN_VIA_OVERLAY:
166 for(JSThread t : this.threads) {
167 t.resume();
168 }
169 break;
170 }
171 }
172
173 @Override
174 protected void paintLink() {
175 return;
176 }
177}
Note: See TracBrowser for help on using the repository browser.