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