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