1
2
3
4
5
6 package net.kwfgrid.gwui.gui;
7
8 import org.glassbox.Theme;
9 import org.glassbox.gui.Visible;
10 import org.glassbox.executor.Executor;
11
12 import net.kwfgrid.gwui.SwingFactory2;
13 import net.kwfgrid.gwui.GWUI;
14 import net.kwfgrid.gwui.workflow.XMLUtilities;
15 import net.kwfgrid.gworkflowdl.structure.*;
16 import net.kwfgrid.gworkflowdl.protocol.structure.*;
17
18 import java.awt.*;
19 import java.awt.event.ActionEvent;
20 import java.awt.event.ActionListener;
21 import java.awt.event.MouseEvent;
22 import java.awt.event.MouseListener;
23 import java.awt.event.MouseAdapter;
24 import java.awt.event.ItemEvent;
25 import java.awt.event.ItemListener;
26 import java.io.*;
27 import javax.swing.*;
28 import javax.swing.border.TitledBorder;
29 import javax.swing.event.DocumentListener;
30 import javax.swing.event.DocumentEvent;
31 import java.util.List;
32 import java.util.Iterator;
33
34 import org.apache.log4j.Logger;
35
36 /***
37 An editor for the tokens of a place.
38 */
39 public class PlaceTokenEditor extends AbstractWorkflowElementEditor {
40 private static final Logger logger = Logger.getLogger(PlaceTokenEditor.class);
41
42 protected static final String DEFAULT_ICON_KEY = "kwfgrid.gwui.UAA.default.icon";
43 protected static final Icon DEFAULT_ICON = Theme.getIcon(DEFAULT_ICON_KEY);
44 protected static final String HIGHLIGHT_ICON_KEY = "kwfgrid.gwui.UAA.highlight.icon";
45 protected static final Icon HIGHLIGHT_ICON = Theme.getIcon(HIGHLIGHT_ICON_KEY);
46 protected static final String PRESSED_ICON_KEY = "kwfgrid.gwui.UAA.pressed.icon";
47 protected static final Icon PRESSED_ICON = Theme.getIcon(PRESSED_ICON_KEY);
48
49 protected static final String ADD_COMMAND = "ADD";
50 protected static final String CLONE_COMMAND = "CLONE";
51 protected static final String REMOVE_COMMAND = "REMOVE";
52 protected static final String SAVE_COMMAND = "SAVE";
53 protected static final String UPLOAD_COMMAND = "UPLOAD";
54 protected static final String CONTROL_TOKEN_TRUE_COMMAND = "CTT";
55 protected static final String CONTROL_TOKEN_FALSE_COMMAND = "CTF";
56
57 protected static final String CONTROL_TOKEN_TRUE = "<control xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xsd:boolean\">true</control>";
58 protected static final String CONTROL_TOKEN_FALSE = "<control xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"xsd:boolean\">false</control>";
59
60 protected ActionListener ACTION_LISTENER = new ActionListener() {
61 public void actionPerformed(ActionEvent e) {
62 String c = e.getActionCommand();
63 if (ADD_COMMAND.equals(c) ||
64 CLONE_COMMAND.equals(c)) {
65 performAddToken();
66 } else if (REMOVE_COMMAND.equals(c)) {
67 performRemoveToken();
68 } else if (SAVE_COMMAND.equals(c)) {
69 int ret = _chooser.showSaveDialog(_view);
70 try {
71 if( ret == JFileChooser.APPROVE_OPTION ) {
72 File file = _chooser.getSelectedFile();
73 GWUI.writeFile(file, _tokenarea.getText());
74 }
75 } catch (IOException x) {
76 logger.error("Could not write file.", x);
77 }
78 } else if (UPLOAD_COMMAND.equals(c)) {
79 int ret = _chooser.showOpenDialog(_view);
80 try {
81 if( ret == JFileChooser.APPROVE_OPTION ) {
82 File file = _chooser.getSelectedFile();
83 String token = GWUI.readFile(file.toString());
84 _tokenarea.setText(token);
85 }
86 } catch (IOException x) {
87 logger.error("Could not read file.", x);
88 }
89 } else if (CONTROL_TOKEN_TRUE_COMMAND.equals(c)) {
90 _tokenarea.setText(CONTROL_TOKEN_TRUE);
91 } else if (CONTROL_TOKEN_FALSE_COMMAND.equals(c)) {
92 _tokenarea.setText(CONTROL_TOKEN_FALSE);
93 }
94 }
95 };
96
97 protected MouseListener MOUSE_LISTENER = new MouseAdapter() {
98 public void mouseClicked(MouseEvent e) {
99 if (e.getButton()!=MouseEvent.BUTTON1) {
100 _popup.show(_tokenarea, e.getX(), e.getY());
101 }
102 }
103 };
104
105 protected DocumentListener INPUT_LISTENER = new DocumentListener() {
106 private void update() {
107 if (_tokenbox.getSelectedIndex()<_tokenbox.getItemCount()-1) {
108 _tokenbox.removeItemListener(ITEM_LISTENER);
109 _tokenbox.setSelectedIndex(_tokenbox.getItemCount()-1);
110 _tokenbox.addItemListener(ITEM_LISTENER);
111 }
112 _newtoken = _tokenarea.getText();
113 updateView();
114 }
115
116 public void insertUpdate(DocumentEvent e) {
117 update();
118 }
119
120 public void removeUpdate(DocumentEvent e) {
121 update();
122 }
123
124 public void changedUpdate(DocumentEvent e) {
125 }
126 };
127
128 protected ItemListener ITEM_LISTENER = new ItemListener() {
129 public void itemStateChanged(ItemEvent e) {
130 String text = null;
131 if (_tokenbox.getSelectedIndex()<_tokenbox.getItemCount()-1) {
132 Token token = (Token)_tokenbox.getSelectedItem();
133 if (token.getData() != null) {
134
135 text = token.getData().toXML();
136 } else {
137
138 Boolean control = token.getControl();
139 text = (control.booleanValue() ? "<control>true</control>" : "<control>false</control>");
140 }
141 } else {
142 text = _newtoken;
143 }
144 _tokenarea.getDocument().removeDocumentListener(INPUT_LISTENER);
145 _tokenarea.setText(text);
146 _tokenarea.getDocument().addDocumentListener(INPUT_LISTENER);
147 updateView();
148 }
149 };
150
151 protected class TokenBoxModel extends DefaultComboBoxModel {
152 public TokenBoxModel(Object[] tokens) {
153 super(tokens);
154 String bottom = "New Token";
155 addElement(bottom);
156 }
157
158 public TokenBoxModel(Object[] tokens, Object selected) {
159 this(tokens);
160 if (selected!=null) {
161 for (int i=0; i<getSize(); i++) {
162 if (selected.equals(getElementAt(i))) {
163 setSelectedItem(selected);
164 break;
165 }
166 }
167 }
168 }
169 }
170
171 protected JComponent _view;
172 protected JButton _button_add_clone;
173 protected JButton _button_remove;
174 protected JTextArea _tokenarea;
175 protected JComboBox _tokenbox;
176 protected JLabel _label_token_num;
177 protected JFileChooser _chooser;
178 protected JPopupMenu _popup;
179 protected JMenuItem _mitem_controltoken_true;
180 protected JMenuItem _mitem_controltoken_false;
181 protected JMenuItem _mitem_save;
182
183 protected String _newtoken;
184
185 public PlaceTokenEditor(Executor executor, ProtocolWorkflow workflow, ProtocolPlace place) {
186 super(executor, workflow, place);
187 _view = null;
188 _newtoken = null;
189 }
190
191 public void objectsAdded(IStructureObject parent, String namespace, String name, List objects) {
192 if (affectsTokenSet(parent, namespace, name)) updateTokenList();
193 }
194
195 public void objectsRemoved(IStructureObject parent, String namespace, String name, List objects) {
196 if (affectsTokenSet(parent, namespace, name)) updateTokenList();
197 }
198
199 private boolean affectsTokenSet(IStructureObject parent, String namespace, String name) {
200 return
201 parent == getElement() &&
202 ProtocolToken.NAME.equals(name) &&
203 ProtocolToken.NAMESPACE.equals(namespace);
204 }
205
206 private void updateTokenList() {
207 Object selected = _tokenbox.getSelectedItem();
208 _tokenbox.setModel(new TokenBoxModel(((Place)getElement()).getTokens(), selected));
209 ITEM_LISTENER.itemStateChanged(null);
210 updateView();
211 }
212
213 protected void performAddToken() {
214 setPerformingTask(true);
215 final String xml = _tokenarea.getText();
216 getExecutor().execute(new GUIMethodCallTask("Adding token...", getExecutor(), this) {
217 protected void execute() throws CapacityException, WorkflowFormatException {
218 Data d = Factory.newData();
219 d.fromXML(xml);
220 Token t = Factory.newToken(d);
221 logger.debug("***** Token is of type "+t.getClass().getName());
222 ((Place)getElement()).addToken(t);
223 }
224 });
225 }
226
227 protected void performRemoveToken() {
228 setPerformingTask(true);
229 final Token token = (Token)_tokenbox.getSelectedItem();
230 getExecutor().execute(new GUIMethodCallTask("Removing token...", getExecutor(), this) {
231 protected void execute() {
232 ((Place)getElement()).removeToken(token);
233 }
234 });
235 }
236
237 public void setEditable(boolean editable) {
238 boolean iseditable = _tokenarea.isEditable();
239 if (iseditable && !editable)
240 _tokenarea.removeMouseListener(MOUSE_LISTENER);
241 if (editable && !iseditable)
242 _tokenarea.addMouseListener(MOUSE_LISTENER);
243 _tokenarea.setEditable(editable);
244 super.setEditable(editable);
245 }
246
247 protected void updateState() {
248 String text = _tokenarea.getText();
249 boolean newtoken = _tokenbox.getSelectedIndex()==_tokenbox.getItemCount()-1;
250 boolean textentered = text!=null && text.length()>0;
251 boolean editable = _tokenarea.isEditable();
252
253 if (!isEnabled() || isPerformingTask()) {
254 _button_add_clone.setEnabled(false);
255 _button_remove.setEnabled(false);
256 _tokenarea.setEnabled(false);
257 _tokenbox.setEnabled(false);
258 _label_token_num.setEnabled(false);
259 } else {
260 _tokenarea.setEnabled(true);
261 _tokenbox.setEnabled(true);
262 _label_token_num.setEnabled(true);
263 if (newtoken) {
264 _button_remove.setEnabled(false);
265 _button_add_clone.setText("add");
266 _button_add_clone.setEnabled(textentered && editable);
267 _button_add_clone.setActionCommand(ADD_COMMAND);
268 } else {
269 _button_remove.setEnabled(editable);
270 _button_add_clone.setText("clone");
271 _button_add_clone.setEnabled(editable);
272 _button_add_clone.setActionCommand(CLONE_COMMAND);
273 }
274 if (XMLUtilities.isControlPlace((Place)getElement())) {
275 _mitem_controltoken_false.setEnabled(true);
276 _mitem_controltoken_true.setEnabled(true);
277 } else {
278 _mitem_controltoken_false.setEnabled(false);
279 _mitem_controltoken_true.setEnabled(false);
280 }
281 _mitem_save.setEnabled(textentered);
282 }
283 }
284
285 protected void updateView() {
286 updateState();
287
288
289 int token_num = _tokenbox.getItemCount()-1;
290
291 _label_token_num.setText(token_num+" Token"+(token_num!=1?"s":""));
292
293
294
295
296 }
297
298 public JComponent getView() {
299 if (_view==null) {
300 _chooser = SwingFactory2.getFileChooser(GWUI.TOKEN_FILE_CHOOSER);
301
302 JMenuItem upload = new JMenuItem("new Token from File ...");
303 upload.addActionListener(ACTION_LISTENER);
304 upload.setActionCommand(UPLOAD_COMMAND);
305 _mitem_controltoken_true = new JMenuItem("new control Token 'true'");
306 _mitem_controltoken_true.addActionListener(ACTION_LISTENER);
307 _mitem_controltoken_true.setActionCommand(CONTROL_TOKEN_TRUE_COMMAND);
308 _mitem_controltoken_false = new JMenuItem("new control Token 'false'");
309 _mitem_controltoken_false.addActionListener(ACTION_LISTENER);
310 _mitem_controltoken_false.setActionCommand(CONTROL_TOKEN_FALSE_COMMAND);
311 _mitem_save = new JMenuItem("save current ...");
312 _mitem_save.addActionListener(ACTION_LISTENER);
313 _mitem_save.setActionCommand(SAVE_COMMAND);
314 _popup = new JPopupMenu("Content of Token");
315 _popup.add(upload);
316 _popup.add(_mitem_controltoken_true);
317 _popup.add(_mitem_controltoken_false);
318 _popup.add(new JPopupMenu.Separator());
319 _popup.add(_mitem_save);
320 _popup.pack();
321
322 _button_add_clone = new JButton("clone");
323 _button_add_clone.addActionListener(ACTION_LISTENER);
324 _button_remove = new JButton("remove");
325 _button_remove.addActionListener(ACTION_LISTENER);
326 _button_remove.setActionCommand(REMOVE_COMMAND);
327 _tokenbox = new JComboBox(new TokenBoxModel(((Place)getElement()).getTokens()));
328 _tokenbox.addItemListener(ITEM_LISTENER);
329 _tokenarea = new JTextArea(10, 40);
330 if (_tokenbox.getSelectedItem() instanceof Token) {
331 Token token = (Token)_tokenbox.getSelectedItem();
332 if (token.getData() != null) {
333
334 _tokenarea.setText(token.getData().toXML());
335 } else {
336
337 Boolean control = token.getControl();
338 _tokenarea.setText(control.booleanValue() ? "<control>true</control>" : "<control>false</control>");
339 }
340 }
341 _tokenarea.addMouseListener(MOUSE_LISTENER);
342 _tokenarea.getDocument().addDocumentListener(INPUT_LISTENER);
343 _label_token_num = new JLabel("0 Tokens");
344
345 GridBagLayout gridbag = new GridBagLayout();
346 GridBagConstraints c = new GridBagConstraints();
347
348 _view = new JPanel();
349 _view.setLayout(gridbag);
350 _view.setBorder(createBorder("Tokens"));
351
352 c.fill = GridBagConstraints.BOTH;
353 c.insets = new Insets(5, 5, 0, 5);
354 c.weighty = 0.0;
355 c.weightx = 0.0;
356 c.gridx = 0;
357 c.gridy = 0;
358 c.fill = GridBagConstraints.BOTH;
359 c.anchor = GridBagConstraints.CENTER;
360 c.gridwidth = GridBagConstraints.RELATIVE;
361
362 _view.add(_label_token_num, c);
363
364 c.weightx = 1.0;
365 c.gridx = 1;
366 c.gridwidth = GridBagConstraints.REMAINDER;
367
368 _view.add(_tokenbox, c);
369
370 c.weighty = 1.0;
371 c.gridx = 0;
372 c.gridy = 1;
373 c.gridwidth = GridBagConstraints.REMAINDER;
374
375 _view.add(new JScrollPane(_tokenarea), c);
376
377 c.weightx = 0.0;
378 c.weighty = 0.0;
379 c.insets = new Insets(5, 5, 5, 5);
380 c.anchor = GridBagConstraints.WEST;
381 c.gridwidth = 1;
382 c.fill = GridBagConstraints.NONE;
383 c.gridy = 2;
384 c.gridx = 0;
385 _view.add(_button_remove, c);
386
387 c.anchor = GridBagConstraints.EAST;
388 c.gridwidth = GridBagConstraints.REMAINDER;
389 c.gridx = 2;
390
391 _view.add(_button_add_clone, c);
392
393 updateView();
394 }
395 return _view;
396 }
397 }