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