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