InputOutputAnnotationSetsDialog.java
001 /*
002  *  Copyright (c) 1995-2012, 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  *  Ian Roberts 14/02/2009
011  *
012  *  $Id: InputOutputAnnotationSetsDialog.java 17865 2014-04-18 08:45:27Z markagreenwood $
013  *
014  */
015 
016 package gate.gui.teamware;
017 
018 import gate.Controller;
019 
020 import java.awt.Component;
021 import java.awt.GridBagConstraints;
022 import java.awt.GridBagLayout;
023 import java.awt.GridLayout;
024 import java.awt.event.ActionEvent;
025 import java.util.Arrays;
026 import java.util.Collection;
027 import java.util.Comparator;
028 import java.util.Set;
029 
030 import javax.swing.AbstractAction;
031 import javax.swing.Action;
032 import javax.swing.BorderFactory;
033 import javax.swing.Box;
034 import javax.swing.DefaultListModel;
035 import javax.swing.JButton;
036 import javax.swing.JComboBox;
037 import javax.swing.JList;
038 import javax.swing.JOptionPane;
039 import javax.swing.JPanel;
040 import javax.swing.JScrollPane;
041 
042 /**
043  * Dialog box to edit the lists of input and output annotation set names
044  * for the "export to teamware" option.
045  */
046 public class InputOutputAnnotationSetsDialog {
047 
048   /**
049    * The controller being exported.
050    */
051   private Controller controller;
052 
053   private JPanel panel;
054 
055   /**
056    * Editor component for the input annotation set names.
057    */
058   private AnnotationSetsList inputList;
059 
060   private Set<String> inputSetNames;
061 
062   /**
063    * Editor component for the output annotation set names.
064    */
065   private AnnotationSetsList outputList;
066 
067   private Set<String> outputSetNames;
068 
069   public InputOutputAnnotationSetsDialog(Controller controller) {
070     this.controller = controller;
071     initGuiComponents();
072   }
073 
074   /**
075    * Set up the GUI.
076    */
077   protected void initGuiComponents() {
078     panel = new JPanel();
079     panel.setLayout(new GridLayout(1255));
080 
081     // get the list of annotation set names from last time the app was
082     // saved, or make an educated guess if it hasn't been saved before.
083     inputSetNames = TeamwareUtils.getInputAnnotationSets(controller);
084     outputSetNames = TeamwareUtils.getOutputAnnotationSets(controller);
085 
086     Set<String> likelyInputSetNames = TeamwareUtils
087             .getLikelyInputAnnotationSets(controller);
088     Set<String> likelyOutputSetNames = TeamwareUtils
089             .getLikelyOutputAnnotationSets(controller);
090 
091     inputList = new AnnotationSetsList(likelyInputSetNames, inputSetNames);
092     outputList = new AnnotationSetsList(likelyOutputSetNames, outputSetNames);
093 
094     inputList.setBorder(BorderFactory.createTitledBorder(BorderFactory
095             .createEtchedBorder()"Input annotation sets"));
096     outputList.setBorder(BorderFactory.createTitledBorder(BorderFactory
097             .createEtchedBorder()"Output annotation sets"));
098 
099     panel.add(inputList);
100     panel.add(outputList);
101   }
102 
103   /**
104    * Show the dialog. If the dialog is closed with the OK button, the
105    * contents of the two lists (input and output annotation set names)
106    * are persisted back to the relevant Controller features.
107    
108    @return true if the dialog was closed with the OK button, false
109    *         otherwise.
110    */
111   public boolean showDialog(Component parent) {
112     int selectedOption = JOptionPane.showConfirmDialog(parent, panel,
113             "Select input and output annotation sets",
114             JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
115     if(selectedOption == JOptionPane.OK_OPTION) {
116       inputSetNames.clear();
117       for(int i = 0; i < inputList.listModel.size(); i++) {
118         inputSetNames.add(inputList.listModel.get(i));
119       }
120 
121       outputSetNames.clear();
122       for(int i = 0; i < outputList.listModel.size(); i++) {
123         outputSetNames.add(outputList.listModel.get(i));
124       }
125 
126       return true;
127     }
128     else {
129       return false;
130     }
131   }
132 
133   /**
134    * Panel representing the list of annotation set names for either
135    * input or output.
136    */
137   @SuppressWarnings("serial")
138   class AnnotationSetsList extends JPanel {
139     private JList<String> annotationSetsList;
140 
141     private DefaultListModel<String> listModel;
142 
143     private JComboBox<String> combo;
144 
145     private JButton addButton;
146 
147     private JButton removeButton;
148 
149     /**
150      * Adds the currently selected annotation set name to the list, if
151      * it is not already present.
152      */
153     protected class AddAction extends AbstractAction {
154       AddAction() {
155         super("Add");
156         putValue(SHORT_DESCRIPTION, "Add the edited value to the list");
157       }
158 
159       @Override
160       public void actionPerformed(ActionEvent e) {
161         String selected = (String)combo.getSelectedItem();
162         // find where to insert
163         int index = 0;
164         while(index < listModel.size()
165                 && NATURAL_COMPARATOR.compare(listModel.get(index),
166                         selected0) {
167           index++;
168         }
169         if(index == listModel.size()) {
170           // moved past the end of the list, so add there
171           listModel.addElement(selected);
172         }
173         else {
174           // add if the value is not already present
175           if(NATURAL_COMPARATOR.compare(listModel.get(index), selected!= 0) {
176             listModel.add(index, selected);
177           }
178         }
179       }
180     }
181 
182     /**
183      * Removes the selected element(s) from the list
184      */
185     protected class RemoveAction extends AbstractAction {
186       RemoveAction() {
187         super("Remove");
188         putValue(SHORT_DESCRIPTION,
189                 "Remove the selected value(s) from the list");
190       }
191 
192       @Override
193       public void actionPerformed(ActionEvent e) {
194         int[] indices = annotationSetsList.getSelectedIndices();
195         Arrays.sort(indices);
196         for(int i = indices.length - 1; i >= 0; i--) {
197           listModel.remove(indices[i]);
198         }
199       }
200     }
201 
202     AnnotationSetsList(Collection<String> hintSetNames,
203             Collection<String> initialSetNames) {
204       GridBagLayout layout = new GridBagLayout();
205       setLayout(layout);
206       GridBagConstraints c = new GridBagConstraints();
207       c.gridx = 0;
208       c.ipady = 2;
209       c.weightx = 1.0;
210 
211       String[] hintSetNamesArray = hintSetNames.toArray(new String[hintSetNames
212               .size()]);
213       Arrays.sort(hintSetNamesArray, NATURAL_COMPARATOR);
214       combo = new JComboBox<String>(hintSetNamesArray);
215       combo.setEditable(true);
216       // custom editor to handle the default annotation set.
217       combo.setEditor(new AnnotationSetNameComboEditor(combo.getEditor()));
218 
219       // set up renderer
220       combo.setRenderer(new AnnotationSetNameCellRenderer());
221 
222       c.fill = GridBagConstraints.HORIZONTAL;
223       add(combo, c);
224 
225       // add and remove buttons
226       Action addAction = new AddAction();
227       Action removeAction = new RemoveAction();
228 
229       Box buttonsBox = Box.createHorizontalBox();
230       buttonsBox.add(Box.createHorizontalGlue());
231       addButton = new JButton(addAction);
232       buttonsBox.add(addButton);
233       buttonsBox.add(Box.createHorizontalStrut(5));
234       removeButton = new JButton(removeAction);
235       buttonsBox.add(removeButton);
236       buttonsBox.add(Box.createHorizontalGlue());
237 
238       add(buttonsBox, c);
239 
240       listModel = new DefaultListModel<String>();
241       String[] initialSetNamesArray = initialSetNames
242               .toArray(new String[initialSetNames.size()]);
243       Arrays.sort(initialSetNamesArray, NATURAL_COMPARATOR);
244       for(String name : initialSetNamesArray) {
245         listModel.addElement(name);
246       }
247 
248       annotationSetsList = new JList<String>(listModel);
249       // set up list cell renderer
250       annotationSetsList.setCellRenderer(new AnnotationSetNameCellRenderer());
251 
252       c.fill = GridBagConstraints.BOTH;
253       c.weighty = 1.0;
254       add(new JScrollPane(annotationSetsList), c);
255     }
256   }
257 
258   /**
259    * A comparator for strings that uses their natural order, treating
260    <code>null</code> as less than anything non-<code>null</code>.
261    */
262   protected static class NaturalComparator implements Comparator<String> {
263     @Override
264     public int compare(String a, String b) {
265       if(a == null) {
266         if(b == null) {
267           return 0;
268         }
269         else {
270           return -1;
271         }
272       }
273       else if(b == null) {
274         return 1;
275       }
276       else {
277         return a.compareTo(b);
278       }
279     }
280   }
281 
282   private static final Comparator<String> NATURAL_COMPARATOR = new NaturalComparator();
283 
284 }