NewResourceDialog.java
001 /*
002  *  Copyright (c) 1995-2013, The University of Sheffield. See the file
003  *  COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
004  *
005  *  This file is part of GATE (see http://gate.ac.uk/), and is free
006  *  software, licenced under the GNU Library General Public License,
007  *  Version 2, June 1991 (in the distribution as file licence.html,
008  *  and also available at http://gate.ac.uk/gate/licence.html).
009  *
010  *  Valentin Tablan 23/01/2001
011  *
012  *  $Id: NewResourceDialog.java 18933 2015-10-02 13:19:21Z markagreenwood $
013  *
014  */
015 
016 package gate.gui;
017 
018 import gate.Factory;
019 import gate.FeatureMap;
020 import gate.Gate;
021 import gate.ProcessingResource;
022 import gate.Resource;
023 import gate.creole.ResourceData;
024 import gate.creole.ResourceInstantiationException;
025 import gate.util.Err;
026 
027 import java.awt.Dimension;
028 import java.awt.Frame;
029 import java.awt.event.ActionEvent;
030 import java.awt.event.KeyEvent;
031 import java.text.NumberFormat;
032 
033 import javax.swing.AbstractAction;
034 import javax.swing.Action;
035 import javax.swing.ActionMap;
036 import javax.swing.Box;
037 import javax.swing.BoxLayout;
038 import javax.swing.InputMap;
039 import javax.swing.JButton;
040 import javax.swing.JComponent;
041 import javax.swing.JDialog;
042 import javax.swing.JLabel;
043 import javax.swing.JOptionPane;
044 import javax.swing.JPanel;
045 import javax.swing.JScrollPane;
046 import javax.swing.JTable;
047 import javax.swing.JTextField;
048 import javax.swing.KeyStroke;
049 import javax.swing.SwingUtilities;
050 import javax.swing.table.TableCellEditor;
051 
052 @SuppressWarnings("serial")
053 public class NewResourceDialog extends JDialog {
054 
055   public NewResourceDialog(Frame frame, String title, boolean modal) {
056     super(frame, title, modal/*, frame.getGraphicsConfiguration()*/);
057     MainFrame.getGuiRoots().add(this);
058     initLocalData();
059     initGuiComponents();
060     initListeners();
061   }
062 
063 
064   protected void initLocalData(){
065     // nothing
066   }
067 
068   protected void initGuiComponents(){
069     this.getContentPane().setLayout(new BoxLayout(this.getContentPane(),
070                                                   BoxLayout.Y_AXIS));
071 
072     //name field
073     Box nameBox = Box.createHorizontalBox();
074     nameBox.add(Box.createHorizontalStrut(5));
075     nameBox.add(new JLabel("Name: "));
076     nameBox.add(Box.createHorizontalStrut(5));
077     nameField = new JTextField(30);
078     nameField.setMaximumSize(
079         new Dimension(Integer.MAX_VALUE, nameField.getPreferredSize().height));
080     nameField.setRequestFocusEnabled(true);
081     nameField.selectAll();
082     nameField.setVerifyInputWhenFocusTarget(false);
083     nameBox.add(nameField);
084     nameField.setToolTipText("Enter a name for the resource");
085     
086     nameBox.add(Box.createHorizontalStrut(5));
087     nameBox.add(Box.createHorizontalGlue());
088     this.getContentPane().add(nameBox);
089     this.getContentPane().add(Box.createVerticalStrut(5));
090 
091     //parameters table
092     parametersEditor = new ResourceParametersEditor();
093     tableScroll = new JScrollPane(parametersEditor);
094     this.getContentPane().add(tableScroll);
095     this.getContentPane().add(Box.createVerticalStrut(5));
096     this.getContentPane().add(Box.createVerticalGlue());
097     //buttons box
098     JPanel buttonsBox = new JPanel();
099     buttonsBox.setLayout(new BoxLayout(buttonsBox, BoxLayout.X_AXIS));
100     buttonsBox.add(Box.createHorizontalStrut(10));
101     buttonsBox.add(okBtn = new JButton("OK"));
102     buttonsBox.add(Box.createHorizontalStrut(10));
103     buttonsBox.add(cancelBtn = new JButton("Cancel"));
104     buttonsBox.add(Box.createHorizontalStrut(10));
105     buttonsBox.add(helpBtn = new JButton("Help"));
106     buttonsBox.add(Box.createHorizontalStrut(10));
107     this.getContentPane().add(buttonsBox);
108     this.getContentPane().add(Box.createVerticalStrut(5));
109     setSize(400300);
110 
111     getRootPane().setDefaultButton(okBtn);
112   }// protected void initGuiComponents()
113 
114 
115   protected void initListeners(){
116     Action applyAction = new AbstractAction() {
117       @Override
118       public void actionPerformed(ActionEvent e) {
119         userCanceled = false;
120         TableCellEditor cellEditor = parametersEditor.getCellEditor();
121         if(cellEditor != null){
122           cellEditor.stopCellEditing();
123         }
124         setVisible(false);
125       }
126     };
127     Action helpAction = new AbstractAction() {
128       @Override
129       public void actionPerformed(ActionEvent e) {
130         MainFrame.getInstance().showHelpFrame(resourceData.getHelpURL(),
131           resourceData.getClassName());
132       }
133     };
134     Action cancelAction = new AbstractAction() {
135       @Override
136       public void actionPerformed(ActionEvent e) {
137         userCanceled = true;
138         setVisible(false);
139       }
140     };
141 
142     okBtn.addActionListener(applyAction);
143     helpBtn.addActionListener(helpAction);
144     cancelBtn.addActionListener(cancelAction);
145 
146     // disable Enter key in the table so this key will confirm the dialog
147     InputMap im = parametersEditor.getInputMap(
148       JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
149     KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
150     im.put(enter, "none");
151 
152     // define keystrokes action bindings at the level of the main window
153     InputMap inputMap = ((JComponent)this.getContentPane()).
154       getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
155     ActionMap actionMap =
156       ((JComponent)this.getContentPane()).getActionMap();
157     inputMap.put(KeyStroke.getKeyStroke("ENTER")"Apply");
158     actionMap.put("Apply", applyAction);
159     inputMap.put(KeyStroke.getKeyStroke("F1")"Help");
160     actionMap.put("Help", helpAction);
161     inputMap.put(KeyStroke.getKeyStroke("ESCAPE")"Cancel");
162     actionMap.put("Cancel", cancelAction);
163   }
164 
165   JButton okBtn, helpBtn, cancelBtn;
166   JTextField nameField;
167   ResourceParametersEditor parametersEditor;
168   JScrollPane tableScroll;
169   ResourceData resourceData;
170   Resource resource;
171 
172   boolean userCanceled;
173 
174   /** This method is intended to be used in conjunction with
175     * getSelectedParameters(). The method will not instantiate the resource
176     * like {@link #show(ResourceData)} but it is intended to collect the params
177     * required to instantiate a resource. Returns true if the user pressed OK
178     * and false otherwise.
179     */
180   public synchronized boolean show(ResourceData rData, String aTitle) {
181     this.resourceData = rData;
182     if (aTitle != nullsetTitle(aTitle);
183 
184     parametersEditor.init(null,
185                           rData.getParameterList().getInitimeParameters());
186     pack();
187     nameField.requestFocusInWindow();
188     userCanceled = true;
189     setModal(true);
190     setLocationRelativeTo(getOwner());
191     super.setVisible(true);
192     dispose();
193     if(userCanceledreturn false;
194     else return true;
195   }//show();
196 
197   /** Returns the selected params for the resource or null if none was selected
198     * or the user pressed cancel
199     */
200   public FeatureMap getSelectedParameters(){
201     if (parametersEditor != null)
202       return parametersEditor.getParameterValues();
203     else
204       return null;
205   }// getSelectedParameters()
206 
207   /**
208    * Return the String entered into the resource name field of the dialog. 
209    */
210   public String getResourceName() {
211     return nameField.getText();
212   }
213   
214   public synchronized void show(ResourceData rData) {
215     if(rData != null) {
216       this.resourceData = rData;
217 
218       String name = "";
219       try {
220         // Only try to generate a name for a PR - other types should be named after what they contain, really!
221         if (ProcessingResource.class.isAssignableFrom(rData.getResourceClass())) {
222           name = rData.getName() " " + Gate.genSym();
223         }
224       catch (ClassNotFoundException e){
225         Err.getPrintWriter().println("Couldn't load input resource class when showing dialogue.");
226       }
227       nameField.setText(name);
228 
229       parametersEditor.init(null, rData,
230                             rData.getParameterList().getInitimeParameters());
231       pack();
232       setLocationRelativeTo(getOwner());
233     else {
234       // dialog already populated
235     }
236     //default case when the dialog just gets closed 
237     userCanceled = true;
238     //show the dialog
239     setVisible(true);
240     if(userCanceled){
241       //release resources
242       dispose();
243       return;
244     else {
245       Runnable runnable = new Runnable(){
246         @Override
247         public void run(){
248           //create the new resource
249           FeatureMap params = parametersEditor.getParameterValues();
250 
251           gate.event.StatusListener sListener =
252             (gate.event.StatusListener)Gate.getListeners().
253                                        get("gate.event.StatusListener");
254           if(sListener != nullsListener.statusChanged("Loading " +
255                                                         nameField.getText() +
256                                                         "...");
257 
258           gate.event.ProgressListener pListener =
259             (gate.event.ProgressListener)Gate.getListeners().
260                                          get("gate.event.ProgressListener");
261           if(pListener != null){
262             pListener.progressChanged(0);
263           }
264           boolean success = true;
265           try {
266             long startTime = System.currentTimeMillis();
267             FeatureMap features = Factory.newFeatureMap();
268             String name = nameField.getText();
269             if(name == null || name.length() == 0name = null;
270             Factory.createResource(resourceData.getClassName(), params,
271                                          features, name);
272             long endTime = System.currentTimeMillis();
273             if(sListener != nullsListener.statusChanged(
274                 nameField.getText() " loaded in " +
275                 NumberFormat.getInstance().format(
276                 (double)(endTime - startTime1000" seconds");
277             if(pListener != nullpListener.processFinished();
278           catch(ResourceInstantiationException rie){
279             success = false;
280             JOptionPane.showMessageDialog(getOwner(),
281                                           "Resource could not be created!\n" +
282                                           rie.toString(),
283                                           "GATE", JOptionPane.ERROR_MESSAGE);
284             rie.printStackTrace(Err.getPrintWriter());
285             
286             if(sListener != nullsListener.statusChanged("Error loading " +
287                                                           nameField.getText() +
288                                                           "!");
289             if(pListener != nullpListener.processFinished();
290           }catch(Throwable thr){
291             success = false;
292             JOptionPane.showMessageDialog(getOwner(),
293                     "Unhandled error!\n" +
294                     thr.toString(),
295                     "GATE", JOptionPane.ERROR_MESSAGE);
296             thr.printStackTrace(Err.getPrintWriter());
297             if(sListener != nullsListener.statusChanged("Error loading " +
298                                                 nameField.getText() +
299                                                 "!");
300             if(pListener != nullpListener.processFinished();
301           finally {
302             if(!success) {
303               // re-show the dialog, to allow the suer to correct the entry
304               SwingUtilities.invokeLater(new Runnable() {
305                 @Override
306                 public void run() {
307                   show(null);    
308                 }
309               });
310             }
311             else {
312               dispose();
313             }
314           }
315         }//public void run()
316       };
317       Thread thread = new Thread(runnable, "");
318       thread.setPriority(Thread.MIN_PRIORITY);
319       thread.start();
320     }
321   }// public synchronized Resource show(ResourceData rData)
322   
323   @Override
324   public void dispose() {
325     // when we have finished with the dialog release the data about the resource
326     // we were trying to create so that, at a later date, we can garbage collect
327     // the classloader if the plugin is unloaded
328     resourceData = null;
329   }
330 
331 }//class NewResourceDialog