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