update author list in license for (JAL-826)
[jalview.git] / src / jalview / appletgui / AnnotationColourChooser.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
3  * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, 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 import javax.swing.BoxLayout;
30
31 public class AnnotationColourChooser extends Panel implements
32         ActionListener, AdjustmentListener, ItemListener, MouseListener
33 {
34   Frame 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, AlignmentPanel ap)
49   {
50     try
51     {
52       jbInit();
53     } catch (Exception ex)
54     {
55     }
56
57     oldcs = av.getGlobalColourScheme();
58     if (av.alignment.getGroups() != null)
59     {
60       oldgroupColours = new Hashtable();
61       Vector allGroups = ap.av.alignment.getGroups();
62       SequenceGroup sg;
63       for (int g = 0; g < allGroups.size(); g++)
64       {
65         sg = (SequenceGroup) allGroups.elementAt(g);
66         if (sg.cs != null)
67         {
68           oldgroupColours.put(sg, sg.cs);
69         }
70         else
71         {
72           oldgroupColours.put(sg, "null");
73         }
74       }
75     }
76     this.av = av;
77     this.ap = ap;
78
79     slider.addAdjustmentListener(this);
80     slider.addMouseListener(this);
81
82     if (av.alignment.getAlignmentAnnotation() == null)
83     {
84       return;
85     }
86
87     setDefaultMinMax();
88     
89     if (oldcs instanceof AnnotationColourGradient)
90     {
91       AnnotationColourGradient acg = (AnnotationColourGradient) oldcs;
92       currentColours.setState(acg.predefinedColours);
93       if (!acg.predefinedColours) {
94         minColour.setBackground(acg.getMinColour());
95         maxColour.setBackground(acg.getMaxColour());
96       }
97     }
98
99     adjusting = true;
100
101     Vector list = new Vector();
102     int index = 1;
103     for (int i = 0; i < av.alignment.getAlignmentAnnotation().length; i++)
104     {
105       String label = av.alignment.getAlignmentAnnotation()[i].label;
106       if (!list.contains(label))
107         list.addElement(label);
108       else
109         list.addElement(label + "_" + (index++));
110     }
111
112     for (int i = 0; i < list.size(); i++)
113     {
114       annotations.addItem(list.elementAt(i).toString());
115     }
116
117     threshold.addItem("No Threshold");
118     threshold.addItem("Above Threshold");
119     threshold.addItem("Below Threshold");
120
121     if (oldcs instanceof AnnotationColourGradient)
122     {
123       AnnotationColourGradient acg = (AnnotationColourGradient) oldcs;
124       annotations.select(acg.getAnnotation());
125       switch (acg.getAboveThreshold()) {
126       case AnnotationColourGradient.NO_THRESHOLD:
127           threshold.select("No Threshold");
128         break;
129       case AnnotationColourGradient.ABOVE_THRESHOLD:
130           threshold.select("Above Threshold");
131         break;
132       case AnnotationColourGradient.BELOW_THRESHOLD:
133         threshold.select("Below Threshold");
134         break;
135         default:
136           throw new Error("Implementation error: don't know about threshold setting for current AnnotationColourGradient.");
137       }
138       thresholdIsMin.setState(acg.thresholdIsMinMax);
139       thresholdValue.setText(""+acg.getAnnotationThreshold());
140     }
141
142     adjusting = false;
143
144     changeColour();
145
146     frame = new Frame();
147     frame.add(this);
148     jalview.bin.JalviewLite.addFrame(frame, "Colour by Annotation", 560,
149             175);
150     validate();
151   }
152
153   private void setDefaultMinMax()
154   {
155     minColour.setBackground(av.applet.getDefaultColourParameter("ANNOTATIONCOLOUR_MIN",Color.orange));
156     maxColour.setBackground(av.applet.getDefaultColourParameter("ANNOTATIONCOLOUR_MAX",Color.red));
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     
220     jPanel1.add(ok);
221     jPanel1.add(cancel);
222     
223     jPanel2.add(annotations);
224     jPanel2.add(currentColours);
225     jPanel2.add(minColour);
226     jPanel2.add(maxColour);
227     
228     
229     jPanel4.add(thresholdIsMin, BorderLayout.WEST);
230     jPanel4.add(slider, BorderLayout.CENTER);
231     jPanel4.add(thresholdValue, BorderLayout.EAST);
232     
233     Panel jPanel34 = new Panel();
234     jPanel34.setLayout(new BorderLayout());
235     jPanel34.setBackground(Color.white);
236     jPanel34.add(jPanel2, BorderLayout.NORTH);
237     jPanel34.add(threshold, BorderLayout.WEST);
238     jPanel3.add(defColours);
239     jPanel34.add(jPanel3,  BorderLayout.EAST);
240     jPanel34.add(jPanel4, BorderLayout.SOUTH);
241     
242     this.add(jPanel34, java.awt.BorderLayout.CENTER);
243     this.add(jPanel1, java.awt.BorderLayout.SOUTH);
244     
245   }
246
247   Choice annotations = new Choice();
248
249   Button minColour = new Button();
250
251   Button maxColour = new Button();
252
253   Button ok = new Button();
254
255   Button cancel = new Button();
256   
257   Button defColours = new Button();
258
259   Panel jPanel1 = new Panel();
260
261   Panel jPanel2 = new Panel();
262
263   Choice threshold = new Choice();
264
265   FlowLayout flowLayout1 = new FlowLayout();
266
267   Panel jPanel3 = new Panel();
268
269   Scrollbar slider = new Scrollbar(Scrollbar.HORIZONTAL);
270
271   TextField thresholdValue = new TextField(20);
272
273   Checkbox currentColours = new Checkbox();
274
275   BorderLayout borderLayout1 = new BorderLayout();
276
277   Checkbox thresholdIsMin = new Checkbox();
278
279   public void actionPerformed(ActionEvent evt)
280   {
281     if (evt.getSource() == thresholdValue)
282     {
283       try
284       {
285         float f = new Float(thresholdValue.getText()).floatValue();
286         slider.setValue((int) (f * 1000));
287         adjustmentValueChanged(null);
288       } catch (NumberFormatException ex)
289       {
290       }
291     }
292     else if (evt.getSource() == minColour)
293     {
294       minColour_actionPerformed(null);
295     }
296     else if (evt.getSource() == maxColour)
297     {
298       maxColour_actionPerformed(null);
299     }
300     else if (evt.getSource() == defColours)
301     {
302         defColour_actionPerformed();
303     }
304     else if (evt.getSource() == ok)
305     {
306       changeColour();
307       frame.setVisible(false);
308     }
309     else if (evt.getSource() == cancel)
310     {
311       reset();
312       ap.paintAlignment(true);
313       frame.setVisible(false);
314     }
315
316     else
317     {
318       changeColour();
319     }
320   }
321
322   public void itemStateChanged(ItemEvent evt)
323   {
324     if (evt.getSource() == currentColours)
325     {
326       if (currentColours.getState())
327       {
328         reset();
329       }
330
331       maxColour.setEnabled(!currentColours.getState());
332       minColour.setEnabled(!currentColours.getState());
333
334     }
335
336     changeColour();
337   }
338
339   public void adjustmentValueChanged(AdjustmentEvent evt)
340   {
341     if (!adjusting)
342     {
343       thresholdValue.setText(((float) slider.getValue() / 1000f) + "");
344       if (currentColours.getState()
345               && !(av.getGlobalColourScheme() instanceof AnnotationColourGradient))
346       {
347         changeColour();
348       }
349
350       currentAnnotation.threshold.value = (float) slider.getValue() / 1000f;
351       ap.paintAlignment(false);
352     }
353   }
354
355   public void minColour_actionPerformed(Color newCol)
356   {
357     if (newCol != null)
358     {
359       minColour.setBackground(newCol);
360       minColour.repaint();
361       changeColour();
362     }
363     else
364     {
365       new UserDefinedColours(this, "Min Colour", minColour.getBackground());
366     }
367
368   }
369
370   public void maxColour_actionPerformed(Color newCol)
371   {
372     if (newCol != null)
373     {
374       maxColour.setBackground(newCol);
375       maxColour.repaint();
376       changeColour();
377     }
378     else
379     {
380       new UserDefinedColours(this, "Max Colour", maxColour.getBackground());
381     }
382   }
383   public void defColour_actionPerformed()
384   {
385     setDefaultMinMax();
386     minColour.repaint();
387     maxColour.repaint();
388     changeColour();
389   }
390   void changeColour()
391   {
392     // Check if combobox is still adjusting
393     if (adjusting)
394     {
395       return;
396     }
397
398     currentAnnotation = av.alignment.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.alignment.getGroups() != null)
468     {
469       Vector allGroups = ap.av.alignment.getGroups();
470       SequenceGroup sg;
471       for (int g = 0; g < allGroups.size(); g++)
472       {
473         sg = (SequenceGroup) allGroups.elementAt(g);
474
475         if (sg.cs == null)
476         {
477           continue;
478         }
479
480         if (currentColours.getState())
481         {
482           sg.cs = new AnnotationColourGradient(currentAnnotation, sg.cs,
483                   aboveThreshold);
484         }
485         else
486         {
487           sg.cs = new AnnotationColourGradient(currentAnnotation,
488                   minColour.getBackground(), maxColour.getBackground(),
489                   aboveThreshold);
490         }
491
492       }
493     }
494
495     // update colours in linked windows
496     ap.paintAlignment(true);
497   }
498
499   void reset()
500   {
501     av.setGlobalColourScheme(oldcs);
502     if (av.alignment.getGroups() != null)
503     {
504       Vector allGroups = ap.av.alignment.getGroups();
505       SequenceGroup sg;
506       for (int g = 0; g < allGroups.size(); g++)
507       {
508         sg = (SequenceGroup) allGroups.elementAt(g);
509         Object cs = oldgroupColours.get(sg);
510         if (cs instanceof ColourSchemeI)
511         {
512           sg.cs = (ColourSchemeI) cs;
513         }
514         else
515         {
516           // probably the "null" string we set it to if it was null originally.
517           sg.cs = null;
518         }
519       }
520     }
521     ap.paintAlignment(true);
522
523   }
524
525   public void mouseClicked(MouseEvent evt)
526   {
527   }
528
529   public void mousePressed(MouseEvent evt)
530   {
531   }
532
533   public void mouseReleased(MouseEvent evt)
534   {
535     ap.paintAlignment(true);
536   }
537
538   public void mouseEntered(MouseEvent evt)
539   {
540   }
541
542   public void mouseExited(MouseEvent evt)
543   {
544   }
545
546 }