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