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