View Javadoc

1   /*
2    * $Id: URISelectionPane.java,v 1.20 2007/09/26 09:12:12 edankert Exp $
3    *
4    * The contents of this file are subject to the Mozilla Public License 
5    * Version 1.1 (the "License"); you may not use this file except in 
6    * compliance with the License. You may obtain a copy of the License at 
7    * http://www.mozilla.org/MPL/ 
8    *
9    * Software distributed under the License is distributed on an "AS IS" basis, 
10   * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
11   * for the specific language governing rights and limitations under the License.
12   *
13   * The Original Code is XML Hammer code. (org.xmlhammer.*)
14   *
15   * The Initial Developer of the Original Code is Edwin Dankert. Portions created 
16   * by the Initial Developer are Copyright (C) 2005 - 2006 the Initial Developer. 
17   * All Rights Reserved.
18   *
19   * Contributor(s): Edwin Dankert <edankert@gmail.com>
20   */
21  
22  package org.xmlhammer.gui.util;
23  
24  import java.awt.BorderLayout;
25  import java.awt.Dialog;
26  import java.awt.Dimension;
27  import java.awt.FlowLayout;
28  import java.awt.Frame;
29  import java.awt.event.ActionEvent;
30  import java.awt.event.ActionListener;
31  import java.io.File;
32  import java.net.MalformedURLException;
33  import java.net.URI;
34  import java.net.URISyntaxException;
35  import java.net.URL;
36  import java.util.ArrayList;
37  import java.util.List;
38  
39  import javax.swing.Box;
40  import javax.swing.ImageIcon;
41  import javax.swing.JButton;
42  import javax.swing.JFileChooser;
43  import javax.swing.JLabel;
44  import javax.swing.JPanel;
45  import javax.swing.JTextField;
46  import javax.swing.SwingUtilities;
47  import javax.swing.border.EmptyBorder;
48  import javax.swing.event.ChangeEvent;
49  import javax.swing.event.ChangeListener;
50  import javax.swing.event.DocumentEvent;
51  import javax.swing.event.DocumentListener;
52  import javax.swing.event.EventListenerList;
53  import javax.swing.undo.AbstractUndoableEdit;
54  import javax.swing.undo.UndoManager;
55  
56  import org.apache.log4j.Logger;
57  import org.bounce.FormLayout;
58  import org.bounce.image.ImageLoader;
59  import org.bounce.util.URIUtils;
60  import org.xmlhammer.gui.Page;
61  import org.xmlhammer.gui.history.HistoryComboBox;
62  import org.xmlhammer.gui.history.HistoryComboBoxModel;
63  import org.xmlhammer.gui.preferences.PropertiesDialog;
64  import org.xmlhammer.model.project.Parameter;
65  
66  /***
67   * Put comment...
68   * 
69   * @version $Revision: 1.20 $, $Date: 2007/09/26 09:12:12 $
70   * @author Edwin Dankert <edankert@gmail.com>
71   */
72  public class URISelectionPane extends JPanel implements DocumentListener {
73  	
74      private static final ImageIcon PARAMETER_ICON = ImageLoader.get().getImage( "/org/xmlhammer/gui/icons/eview16/stackframe.gif");
75      private static final ImageIcon EDIT_ICON = ImageLoader.get().getImage( "/org/xmlhammer/gui/icons/obj16/write_obj.gif");
76      private static final ImageIcon ERROR_ICON = ImageLoader.get().getImage( "/org/xmlhammer/gui/icons/obj16/error_obj.gif");
77  
78      private static final long serialVersionUID = 3257847696986551094L;
79  	private static final String EMPTY_URI_STRING = "<Please specify a URI>";
80  	
81      private EventListenerList listeners = null;
82      private ParametersDialog parametersDialog   = null;
83  
84      private Page page                     = null;
85      private JLabel label                  = null;
86  	private JButton browseButton          = null;
87      private JButton parametersButton      = null;
88      private JButton editButton            = null;
89  	private JFileChooser chooser          = null;
90      private JLabel errorLabel             = null;
91  	private URIHistoryComboBox uriField   = null;
92      private List<Parameter> parameters  = null;
93  
94      /***
95       * Constructs a URISelectionPane, with a label, combobox, 
96       * filechooser and a button.
97       * 
98       * @param text the label text.
99       * @param chooser the file chooser.
100      */
101     public URISelectionPane(Page page, UndoManager undoManager, String text, JFileChooser chooser, HistoryComboBoxModel model) {
102         this(page, undoManager, text, chooser, -1, model, false);
103     }
104     
105     public URISelectionPane(Page page, UndoManager undoManager, String text, JFileChooser chooser, HistoryComboBoxModel model, boolean parameters) {
106         this(page, undoManager, text, chooser, -1, model, parameters);
107     }
108 
109     public URISelectionPane(Page page, UndoManager undoManager, String text, JFileChooser chooser, int labelWidth, HistoryComboBoxModel model) {
110 		this(page, undoManager, text, chooser, labelWidth, model, false);
111 	}
112 
113     public URISelectionPane(Page page, UndoManager undoManager, String text, JFileChooser chooser, int labelWidth, HistoryComboBoxModel model, boolean parameters) {
114         this(page, undoManager, text, chooser, labelWidth, model, EMPTY_URI_STRING, parameters);
115     }
116 
117     public URISelectionPane(Page page, UndoManager undoManager, String text, JFileChooser chooser, int labelWidth, HistoryComboBoxModel model, String emptyText) {
118         this(page, undoManager, text, chooser, labelWidth, model, emptyText, false);
119     }
120 
121     public URISelectionPane(Page page, UndoManager undoManager, String text, JFileChooser chooser, int labelWidth, HistoryComboBoxModel model, String emptyText, boolean parameters) {
122 		super( new BorderLayout( 10, 0));
123 		
124         this.chooser = chooser;
125 		this.page = page;
126         
127         listeners = new EventListenerList();
128 
129         JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
130         
131         if (parameters) {
132             parametersButton = new BrowseButton();
133             parametersButton.setToolTipText("Specify Parameters");
134             parametersButton.setIcon(PARAMETER_ICON);
135             parametersButton.addActionListener( new ActionListener() {
136                 public void actionPerformed( ActionEvent e) {
137                     showParametersDialog();
138                 }
139             });
140 
141             buttonPanel.add(parametersButton);
142             buttonPanel.add(Box.createHorizontalStrut(5));
143         }
144         
145         editButton = new BrowseButton();
146         editButton.setToolTipText("Edit Document");
147         editButton.setIcon(EDIT_ICON);
148         editButton.addActionListener( new ActionListener() {
149             public void actionPerformed( ActionEvent e) {
150                 editDocument();
151             }
152         });
153 
154         buttonPanel.add(editButton);
155         buttonPanel.add(Box.createHorizontalStrut(5));
156 
157         browseButton = new BrowseButton();
158         browseButton.setToolTipText("Select Document");
159         buttonPanel.add(browseButton);
160 
161         uriField = new URIHistoryComboBox(page, model);
162         ((JTextField)uriField.getEditor().getEditorComponent()).getDocument().addDocumentListener(this);
163         uriField.setEmptyValue(emptyText);
164 		uriField.setPreferredSize( new Dimension( uriField.getPreferredSize().width, browseButton.getPreferredSize().height));
165         
166         errorLabel = new JLabel(ERROR_ICON);
167         errorLabel.setVisible(false);
168         errorLabel.setBorder(new EmptyBorder(2, 0, 0, 0));
169         errorLabel.setHorizontalAlignment(JLabel.LEFT);
170         
171         JPanel uriPanel = new JPanel(new FormLayout());
172         uriPanel.add(uriField, FormLayout.FULL_FILL);
173         uriPanel.add(errorLabel, FormLayout.FULL_FILL);
174 
175         label = new JLabel( text);
176 
177         if (labelWidth != -1) {
178             label.setPreferredSize(new Dimension(labelWidth, uriField.getPreferredSize().height));
179             label.setHorizontalAlignment(JLabel.RIGHT);
180         } else {
181             label.setPreferredSize(new Dimension(label.getPreferredSize().width, uriField.getPreferredSize().height));
182         }
183         
184         JPanel labelPanel = new JPanel(new BorderLayout());
185         labelPanel.add(label, BorderLayout.NORTH);
186 
187         add(labelPanel, BorderLayout.WEST);
188 		add(uriPanel, BorderLayout.CENTER);
189 		add(buttonPanel, BorderLayout.EAST);
190 				
191 		browseButton.addActionListener( new ActionListener() {
192 			public void actionPerformed( ActionEvent e) {
193 				chooseFile();
194 			}
195 		});
196 	}
197     
198     public boolean isParameters() {
199         return parametersButton != null;
200     }
201     
202     public void dispose() {
203         uriField.dispose();
204     }
205 	
206 	public int getButtonWidth() {
207 		return (browseButton.getPreferredSize().width * 2) + 5;
208 	}
209 
210     public HistoryComboBox getURIField() {
211         return uriField;
212     }
213     
214     private void editDocument() {
215         ExternalApplicationLauncher.getInstance().edit(getURI(), 0, 0);
216     }
217 
218     private void showParametersDialog() {
219         if (parametersDialog == null) {
220             if (page != null) {
221                 parametersDialog = new ParametersDialog(page.getProjectView().getProjectsView().getRoot());
222             } else {
223                 parametersDialog = new ParametersDialog(getFrame());
224             }
225         }
226 
227         List<Parameter> parameters = getParameters();
228 
229         parametersDialog.setParameters(parameters);
230 
231         if (parametersDialog.open() == PropertiesDialog.OK_OPTION) {
232             List<Parameter> newParameters = parametersDialog.getParameters();
233 
234             if (page != null) {
235                 page.getProjectView().getUndoManager().addEdit(new UndoableParameterEdit(parameters, newParameters));
236                 page.getProjectView().getFieldManager().setFieldsChanged(true);
237             }
238             
239             setParameters(newParameters);
240             fireStateChanged();
241         }
242     }
243 
244     public void setParameters(List<Parameter> parameters) {
245         this.parameters = parameters;
246     }
247 
248     public List<Parameter> getParameters() {
249         if (parameters == null) {
250             parameters = new ArrayList<Parameter>();
251         }
252         
253         return parameters;
254     }
255 
256     // choose a file...
257 	private void chooseFile() {
258         String selection = uriField.getValue();
259         try {
260             URI uri = null;
261             
262             if (selection != null && selection.length() > 0) {
263                 uri = URIUtils.createURI(selection);
264             } else if (((HistoryComboBoxModel)uriField.getModel()).getSize() > 0) {
265                 uri = URIUtils.createURI(((HistoryComboBoxModel)uriField.getModel()).getElementAt(0).toString());
266             } else if (page != null) {
267                 uri = page.getProjectView().getURI();
268             }
269 
270             if (uri != null) {
271                 chooser.setSelectedFile(new File(uri));
272             }
273         } catch (IllegalArgumentException x) {
274             Logger.getLogger(URISelectionPane.class).info( "URI Syntax Error", x);
275         }
276 
277         int value = chooser.showOpenDialog( this);
278 
279         if ( value == JFileChooser.APPROVE_OPTION) {
280 			File file = chooser.getSelectedFile();
281 			URL url = null;
282 			
283 			try {
284 				url = file.toURL();
285 			} catch ( MalformedURLException x) {
286                 Logger.getLogger(this.getClass()).error("Malformed URL Error", x);
287 			}
288 			
289             final String urlValue = url.toString();
290 			JTextField editor = (JTextField)uriField.getEditor().getEditorComponent();
291             editor.requestFocusInWindow();
292             
293             SwingUtilities.invokeLater(new Runnable() {
294                 public void run() {
295                     JTextField editor = (JTextField)uriField.getEditor().getEditorComponent();
296 
297                     editor.setText(urlValue);
298                     editor.setCaretPosition(0);
299                     editor.getInputVerifier().verify(uriField);
300                 }
301                 
302             });
303 		}
304 	}
305 	
306 	/***
307 	 * Get the URI selected in the combobox.
308 	 * 
309 	 * @return the selected URI.
310 	 */
311 	public URI getURI() {
312         URI uri = null;
313         
314 		if ( !uriField.isEmpty()) {
315             try {
316                 uri = URIUtils.createURI(uriField.getEditor().getItem().toString());
317             } catch (Throwable t) {
318                 // illegal argument exception might be thrown.
319             }
320 		}
321 		
322 		return uri;
323 	}
324 	
325 //	public String getValue() {
326 //		return (String)uriField.getEditor().getItem().toString();
327 //	}
328 
329 	/***
330 	 * Set the URI selected in the combobox.
331 	 * 
332 	 * @param uri the selected URI.
333 	 */
334 	public void setURI( URI uri) {
335         uriField.setURI( uri);
336 //		if ( uri != null && uri.toString().length() > 0) {
337 //            uriField.setValue( URIUtils.toString(uri));
338 //		} else {
339 //			uriField.setValue(null);
340 //		}
341 	}
342 	
343 	public void setEnabled( boolean enabled) {
344 		super.setEnabled(enabled);
345 		label.setEnabled(enabled);
346 		browseButton.setEnabled(enabled);
347         editButton.setEnabled(enabled);
348         
349         if (parametersButton != null) {
350             parametersButton.setEnabled(enabled);
351         }
352 		
353         chooser.setEnabled(enabled);
354 		uriField.setEnabled(enabled);
355 	}
356     
357     protected void fireStateChanged() {
358         // Guaranteed to return a non-null array
359         Object[] list = listeners.getListenerList();
360         
361         // Process the listeners last to first, notifying
362         // those that are interested in this event
363         for ( int i = list.length-2; i >= 0; i -= 2) {
364             if ( list[i] == ChangeListener.class) {
365                 ChangeEvent event = new ChangeEvent(this);
366                 ((ChangeListener)list[i+1]).stateChanged(event);
367             }
368         }
369     }
370 
371     /***
372      * Adds a thread listener to the panel. 
373      */ 
374     public void addListener(ChangeListener listener) {
375         listeners.add(ChangeListener.class, listener);
376     }
377 
378     /***
379      * Removes a listener from the panel. 
380      */ 
381     public void removeListener(ChangeListener listener) {
382         listeners.remove(ChangeListener.class, listener);
383     }
384     
385     private void checkForErrors() {
386         try {
387             URI uri = null;
388 
389             if ( !uriField.isEmpty()) {
390                 uri = URIUtils.createURI(uriField.getEditor().getItem().toString());
391             }
392 
393             if (uri == null || uri.isAbsolute()) {
394                 errorLabel.setVisible(false);
395             } else {
396                 errorLabel.setText("Absolute URI expected");
397                 errorLabel.setVisible(true);
398             }
399         } catch (Throwable cause) {
400             while (cause.getCause() != null) {
401                 cause = cause.getCause();
402             }
403     
404             if (cause instanceof URISyntaxException) {
405                 errorLabel.setText(((URISyntaxException)cause).getReason()+" at position "+((URISyntaxException)cause).getIndex());
406             } else {
407                 errorLabel.setText(cause.getMessage());
408             }
409 
410             errorLabel.setVisible(true);
411         }
412     }
413     
414     public String getError() {
415         if (errorLabel.isVisible()) {
416             return errorLabel.getText();
417         }
418         
419         return null;
420     }
421 
422     public void insertUpdate(DocumentEvent arg0) {
423         checkForErrors();
424     }
425 
426     public void removeUpdate(DocumentEvent arg0) {
427         checkForErrors();
428     }
429     
430     private Frame getFrame() {
431         return (Frame)((Dialog)SwingUtilities.getRoot(this)).getParent();
432     }
433 
434     public void changedUpdate(DocumentEvent arg0) {}
435 
436     public class UndoableParameterEdit extends AbstractUndoableEdit {
437         private static final long serialVersionUID = 8615885869967750791L;
438 
439         private List<Parameter> oldValue = null;
440         private List<Parameter> newValue = null;
441         
442         public UndoableParameterEdit(List<Parameter> oldValue, List<Parameter> newValue) {
443             super();
444             
445             this.oldValue = oldValue;
446             this.newValue = newValue;
447         }
448 
449         public void undo() {
450             super.undo();
451             
452             if (page != null) {
453                 page.getProjectView().getFieldManager().setFieldsChanged(true);
454             }
455 
456             setParameters(oldValue);
457             fireStateChanged();
458         }
459 
460         public void redo() {
461             super.redo();
462 
463             if (page != null) {
464                 page.getProjectView().getFieldManager().setFieldsChanged(true);
465             }
466 
467             setParameters(newValue);
468             fireStateChanged();
469         }
470     }    
471 }