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