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