View Javadoc

1   /*
2    * Copyright (c) 2005, The K-Wf Grid Consortium
3    * Fraunhofer Institute for Computer Architecture and Software Technology
4    * See http://www.kwfgrid.eu and http://www.first.fraunhofer.de for more details.
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                 //data token
135                 text = token.getData().toXML();
136             } else {
137                 // control token
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); // HACK to update the textarea
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 	// _view.invalidate();
288 
289 	int token_num = _tokenbox.getItemCount()-1;
290 
291 	_label_token_num.setText(token_num+" Token"+(token_num!=1?"s":""));
292 
293 	// _view.setSize(_view.getLayout().preferredLayoutSize(_view));
294 	// _view.doLayout();
295 	// _view.validate();
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                 //data token
334                 _tokenarea.setText(token.getData().toXML());
335             } else {
336                 // control token
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 }