Missing brace
[jalview.git] / src / jalview / gui / FeatureSettings.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  *\r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.gui;\r
20 \r
21 import jalview.datamodel.*;\r
22 import javax.swing.*;\r
23 import javax.swing.event.*;\r
24 import java.awt.*;\r
25 import java.util.*;\r
26 import javax.swing.BorderFactory;\r
27 import java.awt.event.*;\r
28 import javax.swing.table.*;\r
29 import java.io.*;\r
30 import jalview.io.JalviewFileChooser;\r
31 \r
32 public class FeatureSettings extends JPanel\r
33 {\r
34 \r
35   final FeatureRenderer fr;\r
36   final AlignmentPanel ap;\r
37   final AlignViewport av;\r
38   Object [][] originalData;\r
39   final JInternalFrame frame;\r
40   JScrollPane scrollPane = new JScrollPane();\r
41   JTable table;\r
42 \r
43   public FeatureSettings(AlignViewport av, final AlignmentPanel ap)\r
44   {\r
45     this.ap = ap;\r
46     this.av = av;\r
47     fr = ap.seqPanel.seqCanvas.getFeatureRenderer();\r
48     av.alignment.getSequences();\r
49     frame = new JInternalFrame();\r
50     frame.setContentPane(this);\r
51     Desktop.addInternalFrame(frame, "Sequence Feature Settings", 400, 300);\r
52 \r
53     setTableData();\r
54 \r
55     final JSlider transparency = new JSlider(0, 70, 0);\r
56     transparency.addChangeListener(new ChangeListener()\r
57     {\r
58       public void stateChanged(ChangeEvent evt)\r
59       {\r
60         fr.setTransparency( (float) (100 - transparency.getValue()) / 100f);\r
61         ap.repaint();\r
62       }\r
63     });\r
64 \r
65     JPanel transPanel = new JPanel(new FlowLayout());\r
66     transPanel.add(new JLabel("Transparency"));\r
67     transPanel.add(transparency);\r
68 \r
69     //////////////////////////////////////////////\r
70     //We're going to need those OK cancel buttons\r
71     JPanel buttonPanel = new JPanel(new FlowLayout());\r
72     JButton button = new JButton("OK");\r
73     button.addActionListener(new ActionListener()\r
74     {\r
75       public void actionPerformed(ActionEvent evt)\r
76       {\r
77         try\r
78         {\r
79           frame.setClosed(true);\r
80         }\r
81         catch (Exception exe)\r
82         {}\r
83       }\r
84     });\r
85     buttonPanel.add(button);\r
86     button = new JButton("Cancel");\r
87     button.addActionListener(new ActionListener()\r
88     {\r
89       public void actionPerformed(ActionEvent evt)\r
90       {\r
91         try\r
92         {\r
93           updateFeatureRenderer(originalData);\r
94           frame.setClosed(true);\r
95         }\r
96         catch (Exception exe)\r
97         {}\r
98       }\r
99     });\r
100     buttonPanel.add(button);\r
101 \r
102     button = new JButton("Load Colours");\r
103     button.addActionListener(new ActionListener()\r
104     {\r
105       public void actionPerformed(ActionEvent evt)\r
106       {\r
107         load();\r
108       }\r
109     });\r
110     buttonPanel.add(button);\r
111     button = new JButton("Save Colours");\r
112     button.addActionListener(new ActionListener()\r
113     {\r
114       public void actionPerformed(ActionEvent evt)\r
115       {\r
116         save();\r
117       }\r
118     });\r
119     buttonPanel.add(button);\r
120 \r
121     this.setLayout(new BorderLayout());\r
122     JPanel bigPanel = new JPanel(new BorderLayout());\r
123     bigPanel.add(transPanel, BorderLayout.SOUTH);\r
124     bigPanel.add(scrollPane, BorderLayout.CENTER);\r
125 \r
126     add(bigPanel, BorderLayout.CENTER);\r
127     add(buttonPanel, BorderLayout.SOUTH);\r
128 \r
129 \r
130   }\r
131 \r
132   void setTableData()\r
133   {\r
134     Vector allFeatures = new Vector();\r
135     Vector features;\r
136     Enumeration e;\r
137     SequenceFeature sf;\r
138 \r
139   for (int i = 0; i < av.alignment.getHeight(); i++)\r
140   {\r
141     features = av.alignment.getSequenceAt(i).getDatasetSequence().\r
142         getSequenceFeatures();\r
143     if (features == null)\r
144       continue;\r
145 \r
146     e = features.elements();\r
147     while (e.hasMoreElements())\r
148     {\r
149       sf = (SequenceFeature) e.nextElement();\r
150       if (!allFeatures.contains(sf.getType()))\r
151       {\r
152         allFeatures.addElement(sf.getType());\r
153       }\r
154     }\r
155   }\r
156     if(allFeatures.size()<1)\r
157      {\r
158        try{\r
159          frame.setClosed(true);\r
160        }catch(Exception ex){}\r
161        return;\r
162      }\r
163 \r
164     int fSize = allFeatures.size();\r
165 \r
166     String type;\r
167     boolean originalExists = false;\r
168     if(originalData!=null)\r
169       originalExists = true;\r
170     else\r
171       originalData = new Object[fSize][3];\r
172 \r
173     Object [][] data = new Object[fSize][3];\r
174     for(int i=0; i<fSize; i++)\r
175     {\r
176       type = allFeatures.elementAt(i).toString();\r
177       Color col = fr.getColour(type);\r
178       data[i][0]=type;\r
179       data[i][1]=col;\r
180       if(fr.featuresDisplayed!=null)\r
181          data[i][2] = new Boolean(fr.featuresDisplayed.contains(type));\r
182       else\r
183         data[i][2] = new Boolean(true);\r
184 \r
185       if(!originalExists)\r
186       {\r
187         originalData[i][0] = type;\r
188         originalData[i][1] = col;\r
189         if (fr.featuresDisplayed != null)\r
190           originalData[i][2] = new Boolean(fr.featuresDisplayed.contains(type));\r
191         else\r
192           originalData[i][2] = new Boolean(true);\r
193       }\r
194     }\r
195     ////////////////////////////////////\r
196         //Now build the table\r
197         table = new JTable(new FeatureTableModel(data));\r
198         scrollPane.setViewportView(table);\r
199         table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));\r
200         table.setFont(new Font("Verdana", Font.PLAIN, 12));\r
201         table.setDefaultRenderer(Color.class,\r
202                              new ColorRenderer());\r
203 \r
204         table.setDefaultEditor(Color.class,\r
205                           new ColorEditor());\r
206 \r
207         table.getColumnModel().getColumn(0).setPreferredWidth(200);\r
208 \r
209         table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);\r
210 \r
211         table.addMouseListener(new MouseAdapter()\r
212             {\r
213               public void mousePressed(MouseEvent evt)\r
214               {\r
215                 selectedRow = table.rowAtPoint(evt.getPoint());\r
216               }\r
217             });\r
218 \r
219         table.addMouseMotionListener(new MouseMotionAdapter()\r
220             {\r
221               public void mouseDragged(MouseEvent evt)\r
222               {\r
223                 int newRow = table.rowAtPoint(evt.getPoint());\r
224                 if(newRow!=selectedRow\r
225                    && selectedRow!=-1\r
226                    && newRow!=-1)\r
227                 {\r
228                   Object[] temp = new Object[3];\r
229                   temp[0] = table.getValueAt(selectedRow, 0);\r
230                   temp[1] = table.getValueAt(selectedRow, 1);\r
231                   temp[2] = table.getValueAt(selectedRow, 2);\r
232 \r
233                   table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0);\r
234                   table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1);\r
235                   table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2);\r
236 \r
237                   table.setValueAt(temp[0], newRow, 0);\r
238                   table.setValueAt(temp[1], newRow, 1);\r
239                   table.setValueAt(temp[2], newRow, 2);\r
240 \r
241                   selectedRow = newRow;\r
242                 }\r
243               }\r
244         });\r
245 \r
246   }\r
247 \r
248   void load()\r
249   {\r
250     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(\r
251                  "LAST_DIRECTORY"), new String[] { "fc" },\r
252              new String[] { "Sequence Feature Colours" }, "Sequence Feature Colours");\r
253      chooser.setFileView(new jalview.io.JalviewFileView());\r
254      chooser.setDialogTitle("Load Feature Colours");\r
255      chooser.setToolTipText("Load");\r
256 \r
257      int value = chooser.showOpenDialog(this);\r
258 \r
259      if (value == JalviewFileChooser.APPROVE_OPTION)\r
260      {\r
261        File file = chooser.getSelectedFile();\r
262 \r
263        try\r
264        {\r
265          InputStreamReader in = new InputStreamReader(new FileInputStream(\r
266              file), "UTF-8");\r
267 \r
268          jalview.binding.JalviewUserColours jucs = new jalview.binding.\r
269              JalviewUserColours();\r
270          jucs = (jalview.binding.JalviewUserColours) jucs.unmarshal(in);\r
271 \r
272 \r
273          for (int i = 0; i < jucs.getColourCount(); i++)\r
274          {\r
275            fr.setColour( jucs.getColour(i).getName(),\r
276                           new Color(Integer.parseInt( jucs.getColour(i).getRGB(), 16)));\r
277          }\r
278 \r
279          setTableData();\r
280          ap.repaint();\r
281        }\r
282        catch (Exception ex)\r
283        {\r
284          System.out.println("Error loading User ColourFile\n" + ex);\r
285        }\r
286      }\r
287   }\r
288 \r
289   void save()\r
290   {\r
291     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(\r
292                 "LAST_DIRECTORY"), new String[] { "fc" },\r
293             new String[] { "Sequence Feature Colours" }, "Sequence Feature Colours");\r
294     chooser.setFileView(new jalview.io.JalviewFileView());\r
295     chooser.setDialogTitle("Save Feature Colour Scheme");\r
296     chooser.setToolTipText("Save");\r
297 \r
298     int value = chooser.showSaveDialog(this);\r
299 \r
300     if (value == JalviewFileChooser.APPROVE_OPTION)\r
301     {\r
302         String choice = chooser.getSelectedFile().getPath();\r
303         jalview.binding.JalviewUserColours ucs = new jalview.binding.JalviewUserColours();\r
304         ucs.setSchemeName("Sequence Features");\r
305         try\r
306         {\r
307             PrintWriter out = new PrintWriter(new OutputStreamWriter(\r
308                         new FileOutputStream(choice), "UTF-8"));\r
309 \r
310             Enumeration e = fr.featureColours.keys();\r
311            while(e.hasMoreElements())\r
312            {\r
313 \r
314 \r
315                 jalview.binding.Colour col = new jalview.binding.Colour();\r
316                 col.setName(e.nextElement().toString());\r
317                 col.setRGB(jalview.util.Format.getHexString(\r
318                         fr.getColour(col.getName())));\r
319                 ucs.addColour(col);\r
320             }\r
321 \r
322             ucs.marshal(out);\r
323             out.close();\r
324         }\r
325         catch (Exception ex)\r
326         {\r
327             ex.printStackTrace();\r
328         }\r
329     }\r
330 \r
331   }\r
332 \r
333   public void updateFeatureRenderer(Object [][] data)\r
334   {\r
335     fr.setFeaturePriority( data );\r
336     ap.repaint();\r
337 \r
338     if(ap.overviewPanel!=null)\r
339       ap.overviewPanel.updateOverviewImage();\r
340   }\r
341 \r
342   int selectedRow =-1;\r
343 \r
344 \r
345   /////////////////////////////////////////////////////////////////////////\r
346   // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html\r
347   /////////////////////////////////////////////////////////////////////////\r
348   class FeatureTableModel\r
349       extends AbstractTableModel\r
350   {\r
351     FeatureTableModel(Object[][] data)\r
352     {\r
353       this.data = data;\r
354     }\r
355 \r
356     private String[] columnNames = {"Feature Type", "Colour","Display"};\r
357           private Object[][] data;\r
358 \r
359           public Object[][] getData()\r
360           {\r
361             return data;\r
362           }\r
363 \r
364           public int getColumnCount() {\r
365               return columnNames.length;\r
366           }\r
367 \r
368           public Object[] getRow(int row)\r
369           {\r
370             return data[row];\r
371           }\r
372 \r
373           public int getRowCount() {\r
374               return data.length;\r
375           }\r
376 \r
377           public String getColumnName(int col) {\r
378               return columnNames[col];\r
379           }\r
380 \r
381           public Object getValueAt(int row, int col) {\r
382               return data[row][col];\r
383           }\r
384 \r
385           public Class getColumnClass(int c) {\r
386               return getValueAt(0, c).getClass();\r
387           }\r
388 \r
389           public boolean isCellEditable(int row, int col) {\r
390               return col==0 ? false:true;\r
391           }\r
392 \r
393           public void setValueAt(Object value, int row, int col) {\r
394               data[row][col] = value;\r
395               fireTableCellUpdated(row, col);\r
396               updateFeatureRenderer(data);\r
397           }\r
398 \r
399     }\r
400     class ColorRenderer extends JLabel\r
401                               implements TableCellRenderer {\r
402        javax.swing.border.Border unselectedBorder = null;\r
403        javax.swing.border.Border selectedBorder = null;\r
404 \r
405        public ColorRenderer() {\r
406            setOpaque(true); //MUST do this for background to show up.\r
407        }\r
408 \r
409        public Component getTableCellRendererComponent(\r
410                                JTable table, Object color,\r
411                                boolean isSelected, boolean hasFocus,\r
412                                int row, int column) {\r
413            Color newColor = (Color)color;\r
414            setBackground(newColor);\r
415                if (isSelected) {\r
416                    if (selectedBorder == null) {\r
417                        selectedBorder = BorderFactory.createMatteBorder(2,5,2,5,\r
418                                                  table.getSelectionBackground());\r
419                    }\r
420                    setBorder(selectedBorder);\r
421                } else {\r
422                    if (unselectedBorder == null) {\r
423                        unselectedBorder = BorderFactory.createMatteBorder(2,5,2,5,\r
424                                                  table.getBackground());\r
425                    }\r
426                    setBorder(unselectedBorder);\r
427                }\r
428 \r
429            setToolTipText("RGB value: " + newColor.getRed() + ", "\r
430                                         + newColor.getGreen() + ", "\r
431                                         + newColor.getBlue());\r
432            return this;\r
433        }\r
434    }\r
435 }\r
436 \r
437  class ColorEditor extends AbstractCellEditor\r
438                           implements TableCellEditor,\r
439                                      ActionListener {\r
440      Color currentColor;\r
441      JButton button;\r
442      JColorChooser colorChooser;\r
443      JDialog dialog;\r
444      protected static final String EDIT = "edit";\r
445 \r
446      public ColorEditor() {\r
447          //Set up the editor (from the table's point of view),\r
448          //which is a button.\r
449          //This button brings up the color chooser dialog,\r
450          //which is the editor from the user's point of view.\r
451          button = new JButton();\r
452          button.setActionCommand(EDIT);\r
453          button.addActionListener(this);\r
454          button.setBorderPainted(false);\r
455          //Set up the dialog that the button brings up.\r
456          colorChooser = new JColorChooser();\r
457          dialog = JColorChooser.createDialog(button,\r
458                                          "Select new Colour",\r
459                                          true,  //modal\r
460                                          colorChooser,\r
461                                          this,  //OK button handler\r
462                                          null); //no CANCEL button handler\r
463      }\r
464 \r
465      /**\r
466       * Handles events from the editor button and from\r
467       * the dialog's OK button.\r
468       */\r
469      public void actionPerformed(ActionEvent e) {\r
470 \r
471           if (EDIT.equals(e.getActionCommand())) {\r
472              //The user has clicked the cell, so\r
473              //bring up the dialog.\r
474              button.setBackground(currentColor);\r
475              colorChooser.setColor(currentColor);\r
476              dialog.setVisible(true);\r
477 \r
478              //Make the renderer reappear.\r
479              fireEditingStopped();\r
480 \r
481          } else { //User pressed dialog's "OK" button.\r
482              currentColor = colorChooser.getColor();\r
483          }\r
484      }\r
485 \r
486      //Implement the one CellEditor method that AbstractCellEditor doesn't.\r
487      public Object getCellEditorValue() {\r
488          return currentColor;\r
489      }\r
490 \r
491      //Implement the one method defined by TableCellEditor.\r
492      public Component getTableCellEditorComponent(JTable table,\r
493                                                   Object value,\r
494                                                   boolean isSelected,\r
495                                                   int row,\r
496                                                   int column) {\r
497          currentColor = (Color)value;\r
498          return button;\r
499      }\r
500 }\r