InputOutputAnnotationSetsDialog.java
001 /*
002  *  Copyright (c) 1995-2010, 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 12006 2009-12-01 17:24:28Z thomas_heitz $
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((String)inputList.listModel.get(i));
119       }
120 
121       outputSetNames.clear();
122       for(int i = 0; i < outputList.listModel.size(); i++) {
123         outputSetNames.add((String)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   class AnnotationSetsList extends JPanel {
138     private JList annotationSetsList;
139 
140     private DefaultListModel listModel;
141 
142     private JComboBox combo;
143 
144     private JButton addButton;
145 
146     private JButton removeButton;
147 
148     /**
149      * Adds the currently selected annotation set name to the list, if
150      * it is not already present.
151      */
152     protected class AddAction extends AbstractAction {
153       AddAction() {
154         super("Add");
155         putValue(SHORT_DESCRIPTION, "Add the edited value to the list");
156       }
157 
158       public void actionPerformed(ActionEvent e) {
159         String selected = (String)combo.getSelectedItem();
160         // find where to insert
161         int index = 0;
162         while(index < listModel.size()
163                 && NATURAL_COMPARATOR.compare((String)listModel.get(index),
164                         selected0) {
165           index++;
166         }
167         if(index == listModel.size()) {
168           // moved past the end of the list, so add there
169           listModel.addElement(selected);
170         }
171         else {
172           // add if the value is not already present
173           if(NATURAL_COMPARATOR.compare((String)listModel.get(index), selected!= 0) {
174             listModel.add(index, selected);
175           }
176         }
177       }
178     }
179 
180     /**
181      * Removes the selected element(s) from the list
182      */
183     protected class RemoveAction extends AbstractAction {
184       RemoveAction() {
185         super("Remove");
186         putValue(SHORT_DESCRIPTION,
187                 "Remove the selected value(s) from the list");
188       }
189 
190       public void actionPerformed(ActionEvent e) {
191         int[] indices = annotationSetsList.getSelectedIndices();
192         Arrays.sort(indices);
193         for(int i = indices.length - 1; i >= 0; i--) {
194           listModel.remove(indices[i]);
195         }
196       }
197     }
198 
199     AnnotationSetsList(Collection<String> hintSetNames,
200             Collection<String> initialSetNames) {
201       GridBagLayout layout = new GridBagLayout();
202       setLayout(layout);
203       GridBagConstraints c = new GridBagConstraints();
204       c.gridx = 0;
205       c.ipady = 2;
206       c.weightx = 1.0;
207 
208       String[] hintSetNamesArray = hintSetNames.toArray(new String[hintSetNames
209               .size()]);
210       Arrays.sort(hintSetNamesArray, NATURAL_COMPARATOR);
211       combo = new JComboBox(hintSetNamesArray);
212       combo.setEditable(true);
213       // custom editor to handle the default annotation set.
214       combo.setEditor(new AnnotationSetNameComboEditor(combo.getEditor()));
215 
216       // set up renderer
217       combo.setRenderer(new AnnotationSetNameCellRenderer());
218 
219       c.fill = GridBagConstraints.HORIZONTAL;
220       add(combo, c);
221 
222       // add and remove buttons
223       Action addAction = new AddAction();
224       Action removeAction = new RemoveAction();
225 
226       Box buttonsBox = Box.createHorizontalBox();
227       buttonsBox.add(Box.createHorizontalGlue());
228       addButton = new JButton(addAction);
229       buttonsBox.add(addButton);
230       buttonsBox.add(Box.createHorizontalStrut(5));
231       removeButton = new JButton(removeAction);
232       buttonsBox.add(removeButton);
233       buttonsBox.add(Box.createHorizontalGlue());
234 
235       add(buttonsBox, c);
236 
237       listModel = new DefaultListModel();
238       String[] initialSetNamesArray = initialSetNames
239               .toArray(new String[initialSetNames.size()]);
240       Arrays.sort(initialSetNamesArray, NATURAL_COMPARATOR);
241       for(String name : initialSetNamesArray) {
242         listModel.addElement(name);
243       }
244 
245       annotationSetsList = new JList(listModel);
246       // set up list cell renderer
247       annotationSetsList.setCellRenderer(new AnnotationSetNameCellRenderer());
248 
249       c.fill = GridBagConstraints.BOTH;
250       c.weighty = 1.0;
251       add(new JScrollPane(annotationSetsList), c);
252     }
253   }
254 
255   /**
256    * A comparator for strings that uses their natural order, treating
257    <code>null</code> as less than anything non-<code>null</code>.
258    */
259   protected static class NaturalComparator implements Comparator<String> {
260     public int compare(String a, String b) {
261       if(a == null) {
262         if(b == null) {
263           return 0;
264         }
265         else {
266           return -1;
267         }
268       }
269       else if(b == null) {
270         return 1;
271       }
272       else {
273         return a.compareTo(b);
274       }
275     }
276   }
277 
278   private static final Comparator<String> NATURAL_COMPARATOR = new NaturalComparator();
279 
280 }