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