ensure lastSeq is refreshed if new feature added
[jalview.git] / src / jalview / gui / AnnotationColourChooser.java
1 /*\r
2 * Jalview - A Sequence Alignment Editor and Viewer\r
3 * Copyright (C) 2006 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 javax.swing.*;\r
22 import java.awt.event.*;\r
23 import java.awt.*;\r
24 \r
25 import jalview.schemes.*;\r
26 import javax.swing.event.*;\r
27 import java.util.*;\r
28 import jalview.datamodel.SequenceGroup;\r
29 import java.awt.Dimension;\r
30 import javax.swing.BorderFactory;\r
31 \r
32 public class AnnotationColourChooser\r
33     extends JPanel\r
34 {\r
35   JInternalFrame frame;\r
36   AlignViewport av;\r
37   AlignmentPanel ap;\r
38   ColourSchemeI oldcs;\r
39   Hashtable oldgroupColours;\r
40   jalview.datamodel.AlignmentAnnotation currentAnnotation;\r
41   boolean adjusting = false;\r
42 \r
43   public AnnotationColourChooser(AlignViewport av, AlignmentPanel ap)\r
44   {\r
45     oldcs = av.getGlobalColourScheme();\r
46     if (av.alignment.getGroups() != null)\r
47     {\r
48       oldgroupColours = new Hashtable();\r
49       Vector allGroups = ap.av.alignment.getGroups();\r
50       SequenceGroup sg;\r
51       for (int g = 0; g < allGroups.size(); g++)\r
52       {\r
53         sg = (SequenceGroup) allGroups.get(g);\r
54         if(sg.cs!=null)\r
55           oldgroupColours.put(sg, sg.cs);\r
56       }\r
57     }\r
58     this.av = av;\r
59     this.ap = ap;\r
60     frame = new JInternalFrame();\r
61     frame.setContentPane(this);\r
62     frame.setLayer(JLayeredPane.PALETTE_LAYER);\r
63     Desktop.addInternalFrame(frame, "Colour by Annotation", 480, 145);\r
64 \r
65     try\r
66     {\r
67       jbInit();\r
68     }\r
69     catch (Exception ex)\r
70     {}\r
71 \r
72     slider.addChangeListener(new ChangeListener()\r
73     {\r
74       public void stateChanged(ChangeEvent evt)\r
75       {\r
76         if(!adjusting)\r
77         {\r
78           thresholdValue.setText( ( (float) slider.getValue() / 1000f) + "");\r
79           valueChanged();\r
80         }\r
81       }\r
82     });\r
83 \r
84     if (av.alignment.getAlignmentAnnotation() == null)\r
85       return;\r
86 \r
87     if (oldcs instanceof AnnotationColourGradient)\r
88     {\r
89       AnnotationColourGradient acg = (AnnotationColourGradient) oldcs;\r
90       minColour.setBackground(acg.getMinColour());\r
91       maxColour.setBackground(acg.getMaxColour());\r
92     }\r
93     else\r
94     {\r
95       minColour.setBackground(Color.orange);\r
96       maxColour.setBackground(Color.red);\r
97     }\r
98 \r
99     adjusting = true;\r
100     for (int i = 0; i < av.alignment.getAlignmentAnnotation().length; i++)\r
101     {\r
102       if (av.alignment.getAlignmentAnnotation()[i].graph > 0)\r
103         annotations.addItem(av.alignment.getAlignmentAnnotation()[i].label);\r
104     }\r
105 \r
106     threshold.addItem("No Threshold");\r
107     threshold.addItem("Above Threshold");\r
108     threshold.addItem("Below Threshold");\r
109 \r
110     adjusting = false;\r
111 \r
112     changeColour();\r
113 \r
114   }\r
115 \r
116   public AnnotationColourChooser()\r
117   {\r
118     try\r
119     {\r
120       jbInit();\r
121     }\r
122     catch (Exception ex)\r
123     {\r
124       ex.printStackTrace();\r
125     }\r
126   }\r
127 \r
128   private void jbInit()\r
129       throws Exception\r
130   {\r
131     minColour.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));\r
132     minColour.setBorder(BorderFactory.createEtchedBorder());\r
133     minColour.setPreferredSize(new Dimension(40, 20));\r
134     minColour.setToolTipText("Minimum Colour");\r
135     minColour.addMouseListener(new MouseAdapter()\r
136     {\r
137       public void mousePressed(MouseEvent e)\r
138       {\r
139         if (minColour.isEnabled())\r
140           minColour_actionPerformed();\r
141       }\r
142     });\r
143     maxColour.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));\r
144     maxColour.setBorder(BorderFactory.createEtchedBorder());\r
145     maxColour.setPreferredSize(new Dimension(40, 20));\r
146     maxColour.setToolTipText("Maximum Colour");\r
147     maxColour.addMouseListener(new MouseAdapter()\r
148     {\r
149       public void mousePressed(MouseEvent e)\r
150       {\r
151         if (maxColour.isEnabled())\r
152           maxColour_actionPerformed();\r
153       }\r
154     });\r
155     ok.setOpaque(false);\r
156     ok.setText("OK");\r
157     ok.addActionListener(new ActionListener()\r
158     {\r
159       public void actionPerformed(ActionEvent e)\r
160       {\r
161         ok_actionPerformed(e);\r
162       }\r
163     });\r
164     cancel.setOpaque(false);\r
165     cancel.setText("Cancel");\r
166     cancel.addActionListener(new ActionListener()\r
167     {\r
168       public void actionPerformed(ActionEvent e)\r
169       {\r
170         cancel_actionPerformed(e);\r
171       }\r
172     });\r
173     this.setLayout(borderLayout1);\r
174     jPanel2.setLayout(flowLayout1);\r
175     annotations.addActionListener(new ActionListener()\r
176     {\r
177       public void actionPerformed(ActionEvent e)\r
178       {\r
179         annotations_actionPerformed(e);\r
180       }\r
181     });\r
182     jPanel1.setBackground(Color.white);\r
183     jPanel2.setBackground(Color.white);\r
184     threshold.addActionListener(new ActionListener()\r
185     {\r
186       public void actionPerformed(ActionEvent e)\r
187       {\r
188         threshold_actionPerformed(e);\r
189       }\r
190     });\r
191     jPanel3.setLayout(flowLayout2);\r
192     thresholdValue.addActionListener(new ActionListener()\r
193     {\r
194       public void actionPerformed(ActionEvent e)\r
195       {\r
196         thresholdValue_actionPerformed(e);\r
197       }\r
198     });\r
199     slider.setPaintLabels(false);\r
200     slider.setPaintTicks(true);\r
201     slider.setBackground(Color.white);\r
202     slider.setEnabled(false);\r
203     slider.setOpaque(false);\r
204     slider.setPreferredSize(new Dimension(150, 32));\r
205     thresholdValue.setEnabled(false);\r
206     thresholdValue.setColumns(10);\r
207     jPanel3.setBackground(Color.white);\r
208     currentColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));\r
209     currentColours.setOpaque(false);\r
210     currentColours.setText("Use Original Colours");\r
211     currentColours.addActionListener(new ActionListener()\r
212     {\r
213       public void actionPerformed(ActionEvent e)\r
214       {\r
215         currentColours_actionPerformed(e);\r
216       }\r
217     });\r
218     jPanel1.add(ok);\r
219     jPanel1.add(cancel);\r
220     jPanel2.add(annotations);\r
221     jPanel2.add(currentColours);\r
222     jPanel2.add(minColour);\r
223     jPanel2.add(maxColour);\r
224     this.add(jPanel3, java.awt.BorderLayout.CENTER);\r
225     jPanel3.add(threshold);\r
226     jPanel3.add(slider);\r
227     jPanel3.add(thresholdValue);\r
228     this.add(jPanel1, java.awt.BorderLayout.SOUTH);\r
229     this.add(jPanel2, java.awt.BorderLayout.NORTH);\r
230   }\r
231 \r
232   JComboBox annotations = new JComboBox();\r
233   JPanel minColour = new JPanel();\r
234   JPanel maxColour = new JPanel();\r
235   JButton ok = new JButton();\r
236   JButton cancel = new JButton();\r
237   JPanel jPanel1 = new JPanel();\r
238   JPanel jPanel2 = new JPanel();\r
239   BorderLayout borderLayout1 = new BorderLayout();\r
240   JComboBox threshold = new JComboBox();\r
241   FlowLayout flowLayout1 = new FlowLayout();\r
242   JPanel jPanel3 = new JPanel();\r
243   FlowLayout flowLayout2 = new FlowLayout();\r
244   JSlider slider = new JSlider();\r
245   JTextField thresholdValue = new JTextField(20);\r
246   JCheckBox currentColours = new JCheckBox();\r
247 \r
248   public void minColour_actionPerformed()\r
249   {\r
250     Color col = JColorChooser.showDialog(this,\r
251                                          "Select Colour for Minimum Value",\r
252                                          minColour.getBackground());\r
253     if (col != null)\r
254       minColour.setBackground(col);\r
255     minColour.repaint();\r
256     changeColour();\r
257   }\r
258 \r
259   public void maxColour_actionPerformed()\r
260   {\r
261     Color col = JColorChooser.showDialog(this,\r
262                                          "Select Colour for Maximum Value",\r
263                                          maxColour.getBackground());\r
264     if (col != null)\r
265       maxColour.setBackground(col);\r
266     maxColour.repaint();\r
267     changeColour();\r
268   }\r
269 \r
270   void changeColour()\r
271   {\r
272     // Check if combobox is still adjusting\r
273     if (adjusting)\r
274       return;\r
275 \r
276     // We removed the non-graph annotations when filling the combobox\r
277     // so allow for them again here\r
278     int nograph = 0, graph = -1;\r
279     for (int i = 0; i < av.alignment.getAlignmentAnnotation().length; i++)\r
280     {\r
281       if (av.alignment.getAlignmentAnnotation()[i].graph == 0)\r
282         nograph++;\r
283       else\r
284         graph++;\r
285 \r
286       if (graph == annotations.getSelectedIndex())\r
287         break;\r
288     }\r
289 \r
290     currentAnnotation = av.alignment.getAlignmentAnnotation()[graph + nograph];\r
291 \r
292     int aboveThreshold = -1;\r
293     if (threshold.getSelectedItem().equals("Above Threshold"))\r
294       aboveThreshold = AnnotationColourGradient.ABOVE_THRESHOLD;\r
295     else if (threshold.getSelectedItem().equals("Below Threshold"))\r
296       aboveThreshold = AnnotationColourGradient.BELOW_THRESHOLD;\r
297 \r
298     slider.setEnabled(true);\r
299     thresholdValue.setEnabled(true);\r
300 \r
301     if (aboveThreshold == AnnotationColourGradient.NO_THRESHOLD)\r
302     {\r
303       slider.setEnabled(false);\r
304       thresholdValue.setEnabled(false);\r
305       thresholdValue.setText("");\r
306     }\r
307     else if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD &&\r
308              currentAnnotation.threshold == null)\r
309     {\r
310       currentAnnotation.setThreshold(new jalview.datamodel.GraphLine\r
311                                      ( (currentAnnotation.graphMax -\r
312                                         currentAnnotation.graphMin) / 2f,\r
313                                       "Threshold",\r
314                                       Color.black));\r
315     }\r
316 \r
317     if(aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)\r
318     {\r
319       adjusting = true;\r
320       float range = currentAnnotation.graphMax * 1000 -\r
321           currentAnnotation.graphMin * 1000;\r
322 \r
323       slider.setMinimum( (int) (currentAnnotation.graphMin * 1000));\r
324       slider.setMaximum( (int) (currentAnnotation.graphMax * 1000));\r
325       slider.setValue( (int) (currentAnnotation.threshold.value * 1000));\r
326       thresholdValue.setText(currentAnnotation.threshold.value + "");\r
327       slider.setMajorTickSpacing( (int) (range / 10f));\r
328       slider.setEnabled(true);\r
329       thresholdValue.setEnabled(true);\r
330       adjusting = false;\r
331     }\r
332 \r
333     AnnotationColourGradient acg = null;\r
334     if (currentColours.isSelected())\r
335       acg = new AnnotationColourGradient(\r
336           currentAnnotation,\r
337           av.getGlobalColourScheme(), aboveThreshold);\r
338     else\r
339       acg =\r
340           new AnnotationColourGradient(\r
341               currentAnnotation,\r
342               minColour.getBackground(),\r
343               maxColour.getBackground(),\r
344               aboveThreshold);\r
345 \r
346     av.setGlobalColourScheme(acg);\r
347 \r
348     if (av.alignment.getGroups() != null)\r
349     {\r
350       Vector allGroups = ap.av.alignment.getGroups();\r
351       SequenceGroup sg;\r
352       for (int g = 0; g < allGroups.size(); g++)\r
353       {\r
354         sg = (SequenceGroup) allGroups.get(g);\r
355 \r
356         if (sg.cs == null)\r
357         {\r
358           continue;\r
359         }\r
360 \r
361         if (currentColours.isSelected())\r
362           sg.cs = new AnnotationColourGradient(\r
363               currentAnnotation,\r
364               sg.cs, aboveThreshold);\r
365         else\r
366           sg.cs = new AnnotationColourGradient(\r
367               currentAnnotation,\r
368               minColour.getBackground(),\r
369               maxColour.getBackground(),\r
370               aboveThreshold);\r
371 \r
372       }\r
373     }\r
374 \r
375     ap.repaint();\r
376   }\r
377 \r
378   public void ok_actionPerformed(ActionEvent e)\r
379   {\r
380     changeColour();\r
381     try\r
382     {\r
383       frame.setClosed(true);\r
384     }\r
385     catch (Exception ex)\r
386     {}\r
387   }\r
388 \r
389   public void cancel_actionPerformed(ActionEvent e)\r
390   {\r
391     reset();\r
392     try\r
393     {\r
394       frame.setClosed(true);\r
395     }\r
396     catch (Exception ex)\r
397     {}\r
398   }\r
399 \r
400 \r
401   void reset()\r
402   {\r
403     av.setGlobalColourScheme(oldcs);\r
404     if (av.alignment.getGroups() != null)\r
405     {\r
406       Vector allGroups = ap.av.alignment.getGroups();\r
407       SequenceGroup sg;\r
408       for (int g = 0; g < allGroups.size(); g++)\r
409       {\r
410         sg = (SequenceGroup) allGroups.get(g);\r
411         sg.cs = (ColourSchemeI)oldgroupColours.get(sg);\r
412       }\r
413     }\r
414   }\r
415 \r
416   public void thresholdCheck_actionPerformed(ActionEvent e)\r
417   {\r
418     changeColour();\r
419   }\r
420 \r
421   public void annotations_actionPerformed(ActionEvent e)\r
422   {\r
423     changeColour();\r
424   }\r
425 \r
426   public void threshold_actionPerformed(ActionEvent e)\r
427   {\r
428     changeColour();\r
429   }\r
430 \r
431   public void thresholdValue_actionPerformed(ActionEvent e)\r
432   {\r
433     try\r
434     {\r
435       float f = Float.parseFloat(thresholdValue.getText());\r
436       slider.setValue( (int) (f * 1000));\r
437     }\r
438     catch (NumberFormatException ex)\r
439     {}\r
440   }\r
441 \r
442   public void valueChanged()\r
443   {\r
444     if (currentColours.isSelected()\r
445         && !(av.getGlobalColourScheme() instanceof AnnotationColourGradient))\r
446     {\r
447       changeColour();\r
448     }\r
449 \r
450     currentAnnotation.threshold.value = (float)slider.getValue()/1000f;\r
451     ap.repaint();\r
452   }\r
453 \r
454   public void currentColours_actionPerformed(ActionEvent e)\r
455   {\r
456     if(currentColours.isSelected())\r
457     {\r
458       reset();\r
459     }\r
460 \r
461     maxColour.setEnabled(!currentColours.isSelected());\r
462     minColour.setEnabled(!currentColours.isSelected());\r
463 \r
464     changeColour();\r
465   }\r
466 \r
467 }\r