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