25e08b046099ee9e09236a0163a9b08f398e9f35
[jalview.git] / src / jalview / appletgui / 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.appletgui;
19
20 import java.util.*;
21
22 import java.awt.*;
23 import java.awt.event.*;
24
25 import jalview.datamodel.*;
26 import jalview.schemes.*;
27 import java.awt.Rectangle;
28
29 public class AnnotationColourChooser extends Panel implements
30         ActionListener, AdjustmentListener, ItemListener, MouseListener
31 {
32   Frame frame;
33
34   AlignViewport av;
35
36   AlignmentPanel ap;
37
38   ColourSchemeI oldcs;
39
40   Hashtable oldgroupColours;
41
42   jalview.datamodel.AlignmentAnnotation currentAnnotation;
43
44   boolean adjusting = false;
45
46   public AnnotationColourChooser(AlignViewport av, AlignmentPanel ap)
47   {
48     try
49     {
50       jbInit();
51     } catch (Exception ex)
52     {
53     }
54
55     oldcs = av.getGlobalColourScheme();
56     if (av.alignment.getGroups() != null)
57     {
58       oldgroupColours = new Hashtable();
59       Vector allGroups = ap.av.alignment.getGroups();
60       SequenceGroup sg;
61       for (int g = 0; g < allGroups.size(); g++)
62       {
63         sg = (SequenceGroup) allGroups.elementAt(g);
64         if (sg.cs != null)
65         {
66           oldgroupColours.put(sg, sg.cs);
67         }
68         else
69         {
70           oldgroupColours.put(sg, "null");
71         }
72       }
73     }
74     this.av = av;
75     this.ap = ap;
76
77     slider.addAdjustmentListener(this);
78     slider.addMouseListener(this);
79
80     if (av.alignment.getAlignmentAnnotation() == null)
81     {
82       return;
83     }
84
85     minColour.setBackground(av.applet.getDefaultColourParameter("ANNOTATIONCOLOUR_MIN",Color.orange));
86     maxColour.setBackground(av.applet.getDefaultColourParameter("ANNOTATIONCOLOUR_MAX",Color.red));
87
88     if (oldcs instanceof AnnotationColourGradient)
89     {
90       AnnotationColourGradient acg = (AnnotationColourGradient) oldcs;
91       currentColours.setState(acg.predefinedColours);
92       if (!acg.predefinedColours) {
93         minColour.setBackground(acg.getMinColour());
94         maxColour.setBackground(acg.getMaxColour());
95       }
96     }
97
98     adjusting = true;
99
100     Vector list = new Vector();
101     int index = 1;
102     for (int i = 0; i < av.alignment.getAlignmentAnnotation().length; i++)
103     {
104       String label = av.alignment.getAlignmentAnnotation()[i].label;
105       if (!list.contains(label))
106         list.addElement(label);
107       else
108         list.addElement(label + "_" + (index++));
109     }
110
111     for (int i = 0; i < list.size(); i++)
112     {
113       annotations.addItem(list.elementAt(i).toString());
114     }
115
116     threshold.addItem("No Threshold");
117     threshold.addItem("Above Threshold");
118     threshold.addItem("Below Threshold");
119
120     if (oldcs instanceof AnnotationColourGradient)
121     {
122       AnnotationColourGradient acg = (AnnotationColourGradient) oldcs;
123       annotations.select(acg.getAnnotation());
124       switch (acg.getAboveThreshold()) {
125       case AnnotationColourGradient.NO_THRESHOLD:
126           threshold.select("No Threshold");
127         break;
128       case AnnotationColourGradient.ABOVE_THRESHOLD:
129           threshold.select("Above Threshold");
130         break;
131       case AnnotationColourGradient.BELOW_THRESHOLD:
132         threshold.select("Below Threshold");
133         break;
134         default:
135           throw new Error("Implementation error: don't know about threshold setting for current AnnotationColourGradient.");
136       }
137       thresholdIsMin.setState(acg.thresholdIsMinMax);
138       thresholdValue.setText(""+acg.getAnnotationThreshold());
139     }
140
141     adjusting = false;
142
143     changeColour();
144
145     frame = new Frame();
146     frame.add(this);
147     jalview.bin.JalviewLite.addFrame(frame, "Colour by Annotation", 480,
148             145);
149     validate();
150   }
151
152   public AnnotationColourChooser()
153   {
154     try
155     {
156       jbInit();
157     } catch (Exception ex)
158     {
159       ex.printStackTrace();
160     }
161   }
162
163   private void jbInit() throws Exception
164   {
165     minColour.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
166     minColour.setLabel("Min Colour");
167     minColour.addActionListener(this);
168
169     maxColour.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
170     maxColour.setLabel("Max Colour");
171     maxColour.addActionListener(this);
172
173     thresholdIsMin.addItemListener(this);
174     ok.setLabel("OK");
175     ok.addActionListener(this);
176
177     cancel.setLabel("Cancel");
178     cancel.addActionListener(this);
179
180     this.setLayout(borderLayout1);
181     jPanel2.setLayout(flowLayout1);
182     annotations.addItemListener(this);
183
184     jPanel1.setBackground(Color.white);
185     jPanel2.setBackground(Color.white);
186     threshold.addItemListener(this);
187     jPanel3.setLayout(null);
188     thresholdValue.addActionListener(this);
189
190     slider.setBackground(Color.white);
191     slider.setEnabled(false);
192     slider.setBounds(new Rectangle(153, 3, 93, 21));
193     thresholdValue.setEnabled(false);
194     thresholdValue.setBounds(new Rectangle(248, 2, 79, 22));
195     thresholdValue.setColumns(5);
196     jPanel3.setBackground(Color.white);
197     currentColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
198     currentColours.setLabel("Use Original Colours");
199     currentColours.addItemListener(this);
200
201     threshold.setBounds(new Rectangle(11, 3, 139, 22));
202     thresholdIsMin.setBackground(Color.white);
203     thresholdIsMin.setLabel("Threshold is min/max");
204     thresholdIsMin.setBounds(new Rectangle(328, 3, 135, 23));
205     jPanel1.add(ok);
206     jPanel1.add(cancel);
207     jPanel2.add(annotations);
208     jPanel2.add(currentColours);
209     jPanel2.add(minColour);
210     jPanel2.add(maxColour);
211     jPanel3.add(threshold);
212     jPanel3.add(slider);
213     jPanel3.add(thresholdValue);
214     jPanel3.add(thresholdIsMin);
215     this.add(jPanel2, java.awt.BorderLayout.NORTH);
216     this.add(jPanel3, java.awt.BorderLayout.CENTER);
217     this.add(jPanel1, java.awt.BorderLayout.SOUTH);
218   }
219
220   Choice annotations = new Choice();
221
222   Button minColour = new Button();
223
224   Button maxColour = new Button();
225
226   Button ok = new Button();
227
228   Button cancel = new Button();
229
230   Panel jPanel1 = new Panel();
231
232   Panel jPanel2 = new Panel();
233
234   Choice threshold = new Choice();
235
236   FlowLayout flowLayout1 = new FlowLayout();
237
238   Panel jPanel3 = new Panel();
239
240   Scrollbar slider = new Scrollbar(Scrollbar.HORIZONTAL);
241
242   TextField thresholdValue = new TextField(20);
243
244   Checkbox currentColours = new Checkbox();
245
246   BorderLayout borderLayout1 = new BorderLayout();
247
248   Checkbox thresholdIsMin = new Checkbox();
249
250   public void actionPerformed(ActionEvent evt)
251   {
252     if (evt.getSource() == thresholdValue)
253     {
254       try
255       {
256         float f = new Float(thresholdValue.getText()).floatValue();
257         slider.setValue((int) (f * 1000));
258         adjustmentValueChanged(null);
259       } catch (NumberFormatException ex)
260       {
261       }
262     }
263     else if (evt.getSource() == minColour)
264     {
265       minColour_actionPerformed(null);
266     }
267     else if (evt.getSource() == maxColour)
268     {
269       maxColour_actionPerformed(null);
270     }
271
272     else if (evt.getSource() == ok)
273     {
274       changeColour();
275       frame.setVisible(false);
276     }
277     else if (evt.getSource() == cancel)
278     {
279       reset();
280       ap.paintAlignment(true);
281       frame.setVisible(false);
282     }
283
284     else
285     {
286       changeColour();
287     }
288   }
289
290   public void itemStateChanged(ItemEvent evt)
291   {
292     if (evt.getSource() == currentColours)
293     {
294       if (currentColours.getState())
295       {
296         reset();
297       }
298
299       maxColour.setEnabled(!currentColours.getState());
300       minColour.setEnabled(!currentColours.getState());
301
302     }
303
304     changeColour();
305   }
306
307   public void adjustmentValueChanged(AdjustmentEvent evt)
308   {
309     if (!adjusting)
310     {
311       thresholdValue.setText(((float) slider.getValue() / 1000f) + "");
312       if (currentColours.getState()
313               && !(av.getGlobalColourScheme() instanceof AnnotationColourGradient))
314       {
315         changeColour();
316       }
317
318       currentAnnotation.threshold.value = (float) slider.getValue() / 1000f;
319       ap.paintAlignment(false);
320     }
321   }
322
323   public void minColour_actionPerformed(Color newCol)
324   {
325     if (newCol != null)
326     {
327       minColour.setBackground(newCol);
328       minColour.repaint();
329       changeColour();
330     }
331     else
332     {
333       new UserDefinedColours(this, "Min Colour", minColour.getBackground());
334     }
335
336   }
337
338   public void maxColour_actionPerformed(Color newCol)
339   {
340     if (newCol != null)
341     {
342       maxColour.setBackground(newCol);
343       maxColour.repaint();
344       changeColour();
345     }
346     else
347     {
348       new UserDefinedColours(this, "Max Colour", maxColour.getBackground());
349     }
350   }
351
352   void changeColour()
353   {
354     // Check if combobox is still adjusting
355     if (adjusting)
356     {
357       return;
358     }
359
360     currentAnnotation = av.alignment.getAlignmentAnnotation()[annotations
361             .getSelectedIndex()];
362
363     int aboveThreshold = -1;
364     if (threshold.getSelectedItem().equals("Above Threshold"))
365     {
366       aboveThreshold = AnnotationColourGradient.ABOVE_THRESHOLD;
367     }
368     else if (threshold.getSelectedItem().equals("Below Threshold"))
369     {
370       aboveThreshold = AnnotationColourGradient.BELOW_THRESHOLD;
371     }
372
373     slider.setEnabled(true);
374     thresholdValue.setEnabled(true);
375
376     if (aboveThreshold == AnnotationColourGradient.NO_THRESHOLD)
377     {
378       slider.setEnabled(false);
379       thresholdValue.setEnabled(false);
380       thresholdValue.setText("");
381     }
382     else if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD
383             && currentAnnotation.threshold == null)
384     {
385       currentAnnotation
386               .setThreshold(new jalview.datamodel.GraphLine(
387                       (currentAnnotation.graphMax - currentAnnotation.graphMin) / 2f,
388                       "Threshold", Color.black));
389     }
390
391     if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
392     {
393       adjusting = true;
394
395       slider.setMinimum((int) (currentAnnotation.graphMin * 1000));
396       slider.setMaximum((int) (currentAnnotation.graphMax * 1000));
397       slider.setValue((int) (currentAnnotation.threshold.value * 1000));
398       thresholdValue.setText(currentAnnotation.threshold.value + "");
399       slider.setEnabled(true);
400       thresholdValue.setEnabled(true);
401       adjusting = false;
402     }
403
404     AnnotationColourGradient acg = null;
405     if (currentColours.getState())
406     {
407       acg = new AnnotationColourGradient(currentAnnotation,
408               av.getGlobalColourScheme(), aboveThreshold);
409     }
410     else
411     {
412       acg = new AnnotationColourGradient(currentAnnotation,
413               minColour.getBackground(), maxColour.getBackground(),
414               aboveThreshold);
415     }
416
417     if (currentAnnotation.graphMin == 0f
418             && currentAnnotation.graphMax == 0f)
419     {
420       acg.predefinedColours = true;
421     }
422
423     acg.thresholdIsMinMax = thresholdIsMin.getState();
424
425     av.setGlobalColourScheme(acg);
426
427     if (av.alignment.getGroups() != null)
428     {
429       Vector allGroups = ap.av.alignment.getGroups();
430       SequenceGroup sg;
431       for (int g = 0; g < allGroups.size(); g++)
432       {
433         sg = (SequenceGroup) allGroups.elementAt(g);
434
435         if (sg.cs == null)
436         {
437           continue;
438         }
439
440         if (currentColours.getState())
441         {
442           sg.cs = new AnnotationColourGradient(currentAnnotation, sg.cs,
443                   aboveThreshold);
444         }
445         else
446         {
447           sg.cs = new AnnotationColourGradient(currentAnnotation,
448                   minColour.getBackground(), maxColour.getBackground(),
449                   aboveThreshold);
450         }
451
452       }
453     }
454
455     // update colours in linked windows
456     ap.paintAlignment(true);
457   }
458
459   void reset()
460   {
461     av.setGlobalColourScheme(oldcs);
462     if (av.alignment.getGroups() != null)
463     {
464       Vector allGroups = ap.av.alignment.getGroups();
465       SequenceGroup sg;
466       for (int g = 0; g < allGroups.size(); g++)
467       {
468         sg = (SequenceGroup) allGroups.elementAt(g);
469         Object cs = oldgroupColours.get(sg);
470         if (cs instanceof ColourSchemeI)
471         {
472           sg.cs = (ColourSchemeI) cs;
473         }
474         else
475         {
476           // probably the "null" string we set it to if it was null originally.
477           sg.cs = null;
478         }
479       }
480     }
481     ap.paintAlignment(true);
482
483   }
484
485   public void mouseClicked(MouseEvent evt)
486   {
487   }
488
489   public void mousePressed(MouseEvent evt)
490   {
491   }
492
493   public void mouseReleased(MouseEvent evt)
494   {
495     ap.paintAlignment(true);
496   }
497
498   public void mouseEntered(MouseEvent evt)
499   {
500   }
501
502   public void mouseExited(MouseEvent evt)
503   {
504   }
505
506 }