source: trunk/src/org/expeditee/items/JSItem.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: 7.2 KB
Line 
1/**
2 * JSItem.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;
20
21import java.util.LinkedList;
22import java.util.List;
23
24import javax.script.Invocable;
25import javax.script.ScriptEngine;
26import javax.script.ScriptEngineManager;
27import javax.script.ScriptException;
28
29import org.expeditee.Util;
30import org.expeditee.core.bounds.AxisAlignedBoxBounds;
31import org.expeditee.gui.DisplayController;
32
33public class JSItem extends XRayable implements JSThreadable {
34
35 private static ScriptEngineManager scriptEngineManager = null;
36 private static ScriptEngine globalScriptEngine = null;
37 private static Object global = null;
38
39 // a method to run that will set up and return the root JComponent for this Widget
40 private final String init;
41 // a method to run to populate a List<String> with our state
42 private final String save;
43 // a method to run that will load state from a String[]
44 private final String load;
45 // a method to run that will paint our item using a Graphics2D object
46 private final String paint;
47
48 // we have our own script context since it needs to have some global variables which are specific to each widget
49 private final ScriptEngine scriptEngine;
50 private final Invocable invocable;
51
52 private int _width, _height;
53
54 static {
55 try {
56 scriptEngineManager = new ScriptEngineManager();
57 globalScriptEngine = scriptEngineManager.getEngineByMimeType("application/javascript");
58 global = globalScriptEngine.eval("new Object()");
59 } catch (ScriptException e) {
60 e.printStackTrace();
61 }
62 }
63
64 private static Text getSauce(int width, int height) {
65 Text source = new Text(DisplayController.getCurrentFrame().getNextItemID(), "@js: " + width + " " + height);
66 source.setParent(DisplayController.getCurrentFrame());
67 return source;
68 }
69
70 private JSItem(Text source, String init, String save, String load, String paint) throws Exception {
71 super(source);
72 this.init = init;
73 this.save = save;
74 this.load = load;
75 this.paint = paint;
76 this.scriptEngine = scriptEngineManager.getEngineByMimeType("application/javascript");
77 this.invocable = (Invocable) this.scriptEngine;
78 this.scriptEngine.put("global", global);
79 this.scriptEngine.put("invocable", this.invocable);
80 this.scriptEngine.put("item", this);
81 this.scriptEngine.put("source", this._source);
82 this.parseSource();
83 System.out.println(this.init);
84 this.scriptEngine.eval("var init = " + this.init + "\ninit()");
85 this.scriptEngine.eval("save = " + this.save);
86 this.scriptEngine.eval("paint = " + this.paint);
87 this.updateSource();
88 }
89
90 public JSItem(Text source) throws Exception {
91 this(source, source.getData().get(0).replaceAll("\\\\n", "\n"),
92 source.getData().get(1).replaceAll("\\\\n", "\n"),
93 source.getData().get(2).replaceAll("\\\\n", "\n"),
94 source.getData().get(3).replaceAll("\\\\n", "\n"));
95 }
96
97 public JSItem(int width, int height, String init, String save, String load, String paint) throws Exception {
98 this(getSauce(width, height), init, save, load, paint);
99 }
100
101 public JSItem(String init, String save, String load, String paint) throws Exception {
102 this(100, 100, init, save, load, paint);
103 }
104
105 @Override
106 public Item copy() {
107 try {
108 return new JSItem(_source.copy());
109 } catch (Exception e) {
110 e.printStackTrace();
111 }
112 return null;
113 }
114
115 @Override
116 public void paint(/*Graphics2D g*/) {
117 try {
118 // Not sure of the consequences of changing this? cts16
119 //this.invocable.invokeFunction("paint", (Object)g);
120 this.invocable.invokeFunction("paint");
121 } catch (Exception e) {
122 e.printStackTrace();
123 }
124 }
125
126 @Override
127 public void setAnnotation(boolean val) {
128 // TODO Auto-generated method stub
129
130 }
131
132 @Override
133 public AxisAlignedBoxBounds updateBounds()
134 {
135 return new AxisAlignedBoxBounds(getX(), getY(), _width, _height);
136 }
137
138 private void parseSource() {
139 String text = _source.getText();
140 text = text.replaceFirst("@js:", "");
141 text = text.replaceAll("\n", "");
142 text = text.trim();
143 int index = text.indexOf(':');
144 String[] values;
145 if(index != -1) {
146 values = text.substring(0, index).split("\\s+");
147 } else {
148 values = text.split("\\s+");
149 }
150 if(values.length >= 2) {
151 _width = Integer.parseInt(values[0]);
152 _height = Integer.parseInt(values[1]);
153 }
154
155 if(index == -1) {
156 return;
157 }
158 String[] args = Util.parseArgs(text.substring(index));
159 try {
160 this.scriptEngine.eval("load = " + this.load);
161 this.invocable.invokeFunction("load", (Object) args);
162 } catch (Exception e) {
163 e.printStackTrace();
164 }
165 }
166
167 private String[] saveArgs() {
168 try {
169 List<String> args = new LinkedList<String>();
170 this.invocable.invokeFunction("save", (Object)args);
171 return args.toArray(new String[0]);
172 } catch (Exception e) {
173 e.printStackTrace();
174 }
175 return null;
176 }
177
178 private void updateSource() {
179 List<String> data = new LinkedList<String>();
180 data.add(this.init.replaceAll("[\n\r]", "\\\\n"));
181 data.add(this.save.replaceAll("[\n\r]", "\\\\n"));
182 data.add(this.load.replaceAll("[\n\r]", "\\\\n"));
183 data.add(this.paint.replaceAll("[\n\r]", "\\\\n"));
184 _source.setData(data);
185
186 StringBuffer newText = new StringBuffer("@js: ");
187 newText.append(_width).append(" ").append(_height);
188
189 String stateArgs = Util.formatArgs(saveArgs());
190 if (stateArgs != null) {
191 newText.append(':');
192 newText.append(stateArgs);
193 }
194
195 _source.setText(newText.toString());
196 }
197
198 @Override
199 public Integer getWidth() {
200 return this._width;
201 }
202
203 @Override
204 public int getHeight() {
205 return this._height;
206 }
207
208 private List<JSThread> threads = new LinkedList<JSThread>();
209
210 public JSThread addThread(String code) {
211 JSThread t = new JSThread(scriptEngine, code);
212 this.threads.add(t);
213 return t;
214 }
215
216 @Override
217 public void onParentStateChanged(ItemParentStateChangedEvent e) {
218 switch (e.getEventType()) {
219 case ItemParentStateChangedEvent.EVENT_TYPE_REMOVED:
220 case ItemParentStateChangedEvent.EVENT_TYPE_REMOVED_VIA_OVERLAY:
221 case ItemParentStateChangedEvent.EVENT_TYPE_HIDDEN:
222 for(JSThread t : this.threads) {
223 t.kill();
224 }
225 break;
226
227 case ItemParentStateChangedEvent.EVENT_TYPE_ADDED:
228 case ItemParentStateChangedEvent.EVENT_TYPE_ADDED_VIA_OVERLAY:
229 case ItemParentStateChangedEvent.EVENT_TYPE_SHOWN:
230 case ItemParentStateChangedEvent.EVENT_TYPE_SHOWN_VIA_OVERLAY:
231 for(JSThread t : this.threads) {
232 t.resume();
233 }
234 break;
235
236 }
237 }
238
239 @Override
240 public float getSize() {
241 // TODO Auto-generated method stub
242 return 0;
243 }
244
245}
Note: See TracBrowser for help on using the repository browser.