source: trunk/src/org/expeditee/items/JSItem.java@ 919

Last change on this file since 919 was 919, checked in by jts21, 10 years ago

Added license headers to all files, added full GPL3 license file, moved license header generator script to dev/bin/scripts

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