JAL-1355 (basic i18n support)
[jalview.git] / src / jalview / gui / FeatureColourChooser.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.gui;
19
20 import java.util.*;
21
22 import java.awt.*;
23 import java.awt.event.*;
24 import javax.swing.*;
25 import javax.swing.border.LineBorder;
26 import javax.swing.event.*;
27
28 import jalview.datamodel.*;
29 import jalview.schemes.*;
30 import jalview.util.MessageManager;
31
32 import java.awt.Dimension;
33
34 public class FeatureColourChooser extends JalviewDialog
35 {
36   // FeatureSettings fs;
37   FeatureRenderer fr;
38
39   private GraduatedColor cs;
40
41   private Object oldcs;
42
43   /**
44    * 
45    * @return the last colour setting selected by user - either oldcs (which may
46    *         be a java.awt.Color) or the new GraduatedColor
47    */
48   public Object getLastColour()
49   {
50     if (cs == null)
51     {
52       return oldcs;
53     }
54     return cs;
55   }
56
57   Hashtable oldgroupColours;
58
59   AlignmentPanel ap;
60
61   boolean adjusting = false;
62
63   private float min;
64
65   private float max;
66
67   String type = null;
68
69   public FeatureColourChooser(FeatureRenderer frender, String type)
70   {
71     this(frender, false, type);
72   }
73
74   public FeatureColourChooser(FeatureRenderer frender, boolean block,
75           String type)
76   {
77     this.fr = frender;
78     this.type = type;
79     ap = fr.ap;
80     initDialogFrame(this, true, block, "Graduated Feature Colour for "
81             + type, 480, 185);
82     // frame.setLayer(JLayeredPane.PALETTE_LAYER);
83     // Desktop.addInternalFrame(frame, "Graduated Feature Colour for "+type,
84     // 480, 145);
85
86     slider.addChangeListener(new ChangeListener()
87     {
88       public void stateChanged(ChangeEvent evt)
89       {
90         if (!adjusting)
91         {
92           thresholdValue.setText(((float) slider.getValue() / 1000f) + "");
93           valueChanged();
94         }
95       }
96     });
97     slider.addMouseListener(new MouseAdapter()
98     {
99       public void mouseReleased(MouseEvent evt)
100       {
101         if (ap != null)
102         {
103           ap.paintAlignment(true);
104         }
105         ;
106       }
107     });
108
109     float mm[] = ((float[][]) fr.minmax.get(type))[0];
110     min = mm[0];
111     max = mm[1];
112     oldcs = fr.featureColours.get(type);
113     if (oldcs instanceof GraduatedColor)
114     {
115       if (((GraduatedColor) oldcs).isAutoScale())
116       {
117         // update the scale
118         cs = new GraduatedColor((GraduatedColor) oldcs, min, max);
119       }
120       else
121       {
122         cs = new GraduatedColor((GraduatedColor) oldcs);
123       }
124     }
125     else
126     {
127       // promote original color to a graduated color
128       Color bl = Color.black;
129       if (oldcs instanceof Color)
130       {
131         bl = (Color) oldcs;
132       }
133       // original colour becomes the maximum colour
134       cs = new GraduatedColor(Color.white, bl, mm[0], mm[1]);
135       cs.setColourByLabel(false);
136     }
137     minColour.setBackground(oldminColour = cs.getMinColor());
138     maxColour.setBackground(oldmaxColour = cs.getMaxColor());
139     adjusting = true;
140
141     try
142     {
143       jbInit();
144     } catch (Exception ex)
145     {
146     }
147     // update the gui from threshold state
148     thresholdIsMin.setSelected(!cs.isAutoScale());
149     colourByLabel.setSelected(cs.isColourByLabel());
150     if (cs.getThreshType() != AnnotationColourGradient.NO_THRESHOLD)
151     {
152       // initialise threshold slider and selector
153       threshold
154               .setSelectedIndex(cs.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD ? 1
155                       : 2);
156       slider.setEnabled(true);
157       thresholdValue.setEnabled(true);
158       threshline = new jalview.datamodel.GraphLine((max - min) / 2f,
159               "Threshold", Color.black);
160
161     }
162
163     adjusting = false;
164
165     changeColour();
166     waitForInput();
167   }
168
169   public FeatureColourChooser()
170   {
171     try
172     {
173       jbInit();
174     } catch (Exception ex)
175     {
176       ex.printStackTrace();
177     }
178   }
179
180   private void jbInit() throws Exception
181   {
182
183     minColour.setFont(JvSwingUtils.getLabelFont());
184     minColour.setBorder(BorderFactory.createLineBorder(Color.black));
185     minColour.setPreferredSize(new Dimension(40, 20));
186     minColour.setToolTipText(MessageManager.getString("label.min_colour"));
187     minColour.addMouseListener(new MouseAdapter()
188     {
189       public void mousePressed(MouseEvent e)
190       {
191         if (minColour.isEnabled())
192         {
193           minColour_actionPerformed();
194         }
195       }
196     });
197     maxColour.setFont(JvSwingUtils.getLabelFont());
198     maxColour.setBorder(BorderFactory.createLineBorder(Color.black));
199     maxColour.setPreferredSize(new Dimension(40, 20));
200     maxColour.setToolTipText(MessageManager.getString("label.max_colour"));
201     maxColour.addMouseListener(new MouseAdapter()
202     {
203       public void mousePressed(MouseEvent e)
204       {
205         if (maxColour.isEnabled())
206         {
207           maxColour_actionPerformed();
208         }
209       }
210     });
211     maxColour.setBorder(new LineBorder(Color.black));
212     minText.setText(MessageManager.getString("label.min"));
213     minText.setFont(JvSwingUtils.getLabelFont());
214     maxText.setText(MessageManager.getString("label.max"));
215     maxText.setFont(JvSwingUtils.getLabelFont());
216     this.setLayout(borderLayout1);
217     jPanel2.setLayout(flowLayout1);
218     jPanel1.setBackground(Color.white);
219     jPanel2.setBackground(Color.white);
220     threshold.addActionListener(new ActionListener()
221     {
222       public void actionPerformed(ActionEvent e)
223       {
224         threshold_actionPerformed(e);
225       }
226     });
227     threshold.setToolTipText(MessageManager.getString("label.threshold_feature_display_by_score"));
228     threshold.addItem(MessageManager.getString("label.threshold_feature_no_thereshold")); // index 0
229     threshold.addItem(MessageManager.getString("label.threshold_feature_above_thereshold")); // index 1
230     threshold.addItem(MessageManager.getString("label.threshold_feature_below_thereshold")); // index 2
231     jPanel3.setLayout(flowLayout2);
232     thresholdValue.addActionListener(new ActionListener()
233     {
234       public void actionPerformed(ActionEvent e)
235       {
236         thresholdValue_actionPerformed(e);
237       }
238     });
239     slider.setPaintLabels(false);
240     slider.setPaintTicks(true);
241     slider.setBackground(Color.white);
242     slider.setEnabled(false);
243     slider.setOpaque(false);
244     slider.setPreferredSize(new Dimension(100, 32));
245     slider.setToolTipText(MessageManager.getString("label.adjust_thereshold"));
246     thresholdValue.setEnabled(false);
247     thresholdValue.setColumns(7);
248     jPanel3.setBackground(Color.white);
249     thresholdIsMin.setBackground(Color.white);
250     thresholdIsMin.setText(MessageManager.getString("label.threshold_minmax"));
251     thresholdIsMin
252             .setToolTipText(MessageManager.getString("label.toggle_absolute_relative_display_threshold"));
253     thresholdIsMin.addActionListener(new ActionListener()
254     {
255       public void actionPerformed(ActionEvent actionEvent)
256       {
257         thresholdIsMin_actionPerformed(actionEvent);
258       }
259     });
260     colourByLabel.setBackground(Color.white);
261     colourByLabel.setText(MessageManager.getString("label.colour_by_label"));
262     colourByLabel
263             .setToolTipText(MessageManager.getString("label.display_features_same_type_different_label_using_different_colour"));
264     colourByLabel.addActionListener(new ActionListener()
265     {
266       public void actionPerformed(ActionEvent actionEvent)
267       {
268         colourByLabel_actionPerformed(actionEvent);
269       }
270     });
271     colourPanel.setBackground(Color.white);
272     jPanel1.add(ok);
273     jPanel1.add(cancel);
274     jPanel2.add(colourByLabel, java.awt.BorderLayout.WEST);
275     jPanel2.add(colourPanel, java.awt.BorderLayout.EAST);
276     colourPanel.add(minText);
277     colourPanel.add(minColour);
278     colourPanel.add(maxText);
279     colourPanel.add(maxColour);
280     this.add(jPanel3, java.awt.BorderLayout.CENTER);
281     jPanel3.add(threshold);
282     jPanel3.add(slider);
283     jPanel3.add(thresholdValue);
284     jPanel3.add(thresholdIsMin);
285     this.add(jPanel1, java.awt.BorderLayout.SOUTH);
286     this.add(jPanel2, java.awt.BorderLayout.NORTH);
287   }
288
289   JLabel minText = new JLabel();
290
291   JLabel maxText = new JLabel();
292
293   JPanel minColour = new JPanel();
294
295   JPanel maxColour = new JPanel();
296
297   JPanel colourPanel = new JPanel();
298
299   JPanel jPanel1 = new JPanel();
300
301   JPanel jPanel2 = new JPanel();
302
303   BorderLayout borderLayout1 = new BorderLayout();
304
305   JComboBox threshold = new JComboBox();
306
307   FlowLayout flowLayout1 = new FlowLayout();
308
309   JPanel jPanel3 = new JPanel();
310
311   FlowLayout flowLayout2 = new FlowLayout();
312
313   JSlider slider = new JSlider();
314
315   JTextField thresholdValue = new JTextField(20);
316
317   // TODO implement GUI for tolower flag
318   // JCheckBox toLower = new JCheckBox();
319
320   JCheckBox thresholdIsMin = new JCheckBox();
321
322   JCheckBox colourByLabel = new JCheckBox();
323
324   private GraphLine threshline;
325
326   private Color oldmaxColour;
327
328   private Color oldminColour;
329
330   public void minColour_actionPerformed()
331   {
332     Color col = JColorChooser.showDialog(this,
333             MessageManager.getString("label.select_colour_minimum_value"), minColour.getBackground());
334     if (col != null)
335     {
336       minColour.setBackground(col);
337       minColour.setForeground(col);
338     }
339     minColour.repaint();
340     changeColour();
341   }
342
343   public void maxColour_actionPerformed()
344   {
345     Color col = JColorChooser.showDialog(this,
346             MessageManager.getString("label.select_colour_maximum_value"), maxColour.getBackground());
347     if (col != null)
348     {
349       maxColour.setBackground(col);
350       maxColour.setForeground(col);
351     }
352     maxColour.repaint();
353     changeColour();
354   }
355
356   void changeColour()
357   {
358     // Check if combobox is still adjusting
359     if (adjusting)
360     {
361       return;
362     }
363
364     int aboveThreshold = AnnotationColourGradient.NO_THRESHOLD;
365     if (threshold.getSelectedIndex()==1)
366     {
367       aboveThreshold = AnnotationColourGradient.ABOVE_THRESHOLD;
368     }
369     else if (threshold.getSelectedIndex()==2)
370     {
371       aboveThreshold = AnnotationColourGradient.BELOW_THRESHOLD;
372     }
373
374     slider.setEnabled(true);
375     thresholdValue.setEnabled(true);
376
377     GraduatedColor acg;
378     if (cs.isColourByLabel())
379     {
380       acg = new GraduatedColor(oldminColour, oldmaxColour, min, max);
381     }
382     else
383     {
384       acg = new GraduatedColor(oldminColour = minColour.getBackground(),
385               oldmaxColour = maxColour.getBackground(), min, max);
386
387     }
388
389     if (aboveThreshold == AnnotationColourGradient.NO_THRESHOLD)
390     {
391       slider.setEnabled(false);
392       thresholdValue.setEnabled(false);
393       thresholdValue.setText("");
394       thresholdIsMin.setEnabled(false);
395     }
396     else if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD
397             && threshline == null)
398     {
399       // todo visual indication of feature threshold
400       threshline = new jalview.datamodel.GraphLine((max - min) / 2f,
401               "Threshold", Color.black);
402     }
403
404     if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
405     {
406       adjusting = true;
407       acg.setThresh(threshline.value);
408
409       float range = max * 1000f - min * 1000f;
410
411       slider.setMinimum((int) (min * 1000));
412       slider.setMaximum((int) (max * 1000));
413       slider.setValue((int) (threshline.value * 1000));
414       thresholdValue.setText(threshline.value + "");
415       slider.setMajorTickSpacing((int) (range / 10f));
416       slider.setEnabled(true);
417       thresholdValue.setEnabled(true);
418       thresholdIsMin.setEnabled(!colourByLabel.isSelected());
419       adjusting = false;
420     }
421
422     acg.setThreshType(aboveThreshold);
423     if (thresholdIsMin.isSelected()
424             && aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
425     {
426       acg.setAutoScaled(false);
427       if (aboveThreshold == AnnotationColourGradient.ABOVE_THRESHOLD)
428       {
429         acg = new GraduatedColor(acg, threshline.value, max);
430       }
431       else
432       {
433         acg = new GraduatedColor(acg, min, threshline.value);
434       }
435     }
436     else
437     {
438       acg.setAutoScaled(true);
439     }
440     acg.setColourByLabel(colourByLabel.isSelected());
441     if (acg.isColourByLabel())
442     {
443       maxColour.setEnabled(false);
444       minColour.setEnabled(false);
445       maxColour.setBackground(this.getBackground());
446       maxColour.setForeground(this.getBackground());
447       minColour.setBackground(this.getBackground());
448       minColour.setForeground(this.getBackground());
449
450     }
451     else
452     {
453       maxColour.setEnabled(true);
454       minColour.setEnabled(true);
455       maxColour.setBackground(oldmaxColour);
456       minColour.setBackground(oldminColour);
457       maxColour.setForeground(oldmaxColour);
458       minColour.setForeground(oldminColour);
459     }
460     fr.featureColours.put(type, acg);
461     cs = acg;
462     ap.paintAlignment(false);
463   }
464
465   protected void raiseClosed()
466   {
467     if (this.colourEditor != null)
468     {
469       colourEditor.actionPerformed(new ActionEvent(this, 0, "CLOSED"));
470     }
471   }
472
473   public void okPressed()
474   {
475     changeColour();
476   }
477
478   public void cancelPressed()
479   {
480     reset();
481   }
482
483   void reset()
484   {
485     fr.featureColours.put(type, oldcs);
486     ap.paintAlignment(false);
487     cs = null;
488   }
489
490   public void thresholdCheck_actionPerformed(ActionEvent e)
491   {
492     changeColour();
493   }
494
495   public void annotations_actionPerformed(ActionEvent e)
496   {
497     changeColour();
498   }
499
500   public void threshold_actionPerformed(ActionEvent e)
501   {
502     changeColour();
503   }
504
505   public void thresholdValue_actionPerformed(ActionEvent e)
506   {
507     try
508     {
509       float f = Float.parseFloat(thresholdValue.getText());
510       slider.setValue((int) (f * 1000));
511       threshline.value = f;
512     } catch (NumberFormatException ex)
513     {
514     }
515   }
516
517   public void valueChanged()
518   {
519     threshline.value = (float) slider.getValue() / 1000f;
520     cs.setThresh(threshline.value);
521     changeColour();
522     ap.paintAlignment(false);
523   }
524
525   public void thresholdIsMin_actionPerformed(ActionEvent actionEvent)
526   {
527     changeColour();
528   }
529
530   public void colourByLabel_actionPerformed(ActionEvent actionEvent)
531   {
532     changeColour();
533   }
534
535   ActionListener colourEditor = null;
536
537   public void addActionListener(ActionListener graduatedColorEditor)
538   {
539     if (colourEditor != null)
540     {
541       System.err
542               .println("IMPLEMENTATION ISSUE: overwriting action listener for FeatureColourChooser");
543     }
544     colourEditor = graduatedColorEditor;
545   }
546
547 }