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