JAL-1620 version bump and release notes
[jalview.git] / src / jalview / appletgui / FeatureColourChooser.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2b1)
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 FeatureColourChooser extends Panel implements ActionListener,
33         AdjustmentListener, ItemListener, MouseListener
34 {
35   JVDialog frame;
36
37   Frame owner;
38
39   FeatureRenderer fr;
40
41   FeatureSettings fs = null;
42
43   // AlignmentPanel ap;
44
45   GraduatedColor cs;
46
47   Object oldcs;
48
49   Hashtable oldgroupColours;
50
51   boolean adjusting = false;
52
53   private float min, max;
54
55   String type = null;
56
57   private AlignFrame af = null;
58
59   public FeatureColourChooser(AlignFrame af, String type)
60   {
61     this.af = af;
62     init(af.getSeqcanvas().getFeatureRenderer(), type);
63   }
64
65   public FeatureColourChooser(FeatureSettings fsettings, String type)
66   {
67     this.fs = fsettings;
68     init(fsettings.fr, type);
69     // this.ap = fsettings.ap;
70   }
71
72   private void init(FeatureRenderer frenderer, String type)
73   {
74     this.type = type;
75     fr = frenderer;
76     float mm[] = ((float[][]) fr.minmax.get(type))[0];
77     min = mm[0];
78     max = mm[1];
79     oldcs = fr.featureColours.get(type);
80     if (oldcs instanceof GraduatedColor)
81     {
82       cs = new GraduatedColor((GraduatedColor) oldcs, min, max);
83     }
84     else
85     {
86       // promote original color to a graduated color
87       Color bl = Color.black;
88       if (oldcs instanceof Color)
89       {
90         bl = (Color) oldcs;
91       }
92       // original colour becomes the maximum colour
93       cs = new GraduatedColor(Color.white, bl, mm[0], mm[1]);
94     }
95     minColour.setBackground(cs.getMinColor());
96     maxColour.setBackground(cs.getMaxColor());
97     minColour.setForeground(cs.getMinColor());
98     maxColour.setForeground(cs.getMaxColor());
99     colourFromLabel.setState(cs.isColourByLabel());
100     adjusting = true;
101
102     try
103     {
104       jbInit();
105     } catch (Exception ex)
106     {
107     }
108     threshold
109             .select(cs.getThreshType() == AnnotationColourGradient.NO_THRESHOLD ? 0
110                     : cs.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD ? 1
111                             : 2);
112
113     adjusting = false;
114     changeColour();
115     colourFromLabel.addItemListener(this);
116     slider.addAdjustmentListener(this);
117     slider.addMouseListener(this);
118     owner = (af != null) ? af : fs.frame;
119     frame = new JVDialog(owner, MessageManager.formatMessage(
120             "label.graduated_color_for_params", new String[]
121             { type }), true, 480, 248);
122     frame.setMainPanel(this);
123     validate();
124     frame.setVisible(true);
125     if (frame.accept)
126     {
127       changeColour();
128     }
129     else
130     {
131       // cancel
132       reset();
133       PaintRefresher.Refresh(this, fr.av.getSequenceSetId());
134       frame.setVisible(false);
135     }
136   }
137
138   public FeatureColourChooser()
139   {
140     try
141     {
142       jbInit();
143     } catch (Exception ex)
144     {
145       ex.printStackTrace();
146     }
147   }
148
149   private void jbInit() throws Exception
150   {
151     Label minLabel = new Label(MessageManager.getString("label.min")), maxLabel = new Label(
152             MessageManager.getString("label.max"));
153     minLabel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
154     maxLabel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
155     // minColour.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
156     // minColour.setLabel("Min Colour");
157
158     minColour.setBounds(0, 0, 40, 27);
159     maxColour.setBounds(0, 0, 40, 27);
160     minColour.addMouseListener(this);
161
162     maxColour.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
163     maxColour.addMouseListener(this);
164
165     thresholdIsMin.addItemListener(this);
166
167     this.setLayout(new GridLayout(4, 1));
168     jPanel1.setLayout(new FlowLayout());
169     jPanel2.setLayout(new FlowLayout());
170     jPanel3.setLayout(new GridLayout(1, 1));
171     jPanel4.setLayout(new FlowLayout());
172     jPanel1.setBackground(Color.white);
173     jPanel2.setBackground(Color.white);
174     jPanel4.setBackground(Color.white);
175     threshold.addItemListener(this);
176     threshold.addItem(MessageManager
177             .getString("label.threshold_feature_no_thereshold"));
178     threshold.addItem(MessageManager
179             .getString("label.threshold_feature_above_thereshold"));
180     threshold.addItem(MessageManager
181             .getString("label.threshold_feature_below_thereshold"));
182     thresholdValue.addActionListener(this);
183     slider.setBackground(Color.white);
184     slider.setEnabled(false);
185     slider.setSize(new Dimension(93, 21));
186     thresholdValue.setEnabled(false);
187     thresholdValue.setSize(new Dimension(79, 22)); // setBounds(new
188                                                    // Rectangle(248, 2, 79,
189                                                    // 22));
190     thresholdValue.setColumns(5);
191     jPanel3.setBackground(Color.white);
192
193     colourFromLabel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
194     colourFromLabel.setLabel(MessageManager
195             .getString("label.colour_by_label"));
196     colourFromLabel.setSize(new Dimension(139, 22));
197     // threshold.setBounds(new Rectangle(11, 3, 139, 22));
198     thresholdIsMin.setBackground(Color.white);
199     thresholdIsMin.setLabel(MessageManager
200             .getString("label.threshold_minmax"));
201     thresholdIsMin.setSize(new Dimension(135, 23));
202     // thresholdIsMin.setBounds(new Rectangle(328, 3, 135, 23));
203     jPanel1.add(minLabel);
204     jPanel1.add(minColour);
205     jPanel1.add(maxLabel);
206     jPanel1.add(maxColour);
207     jPanel1.add(colourFromLabel);
208     jPanel2.add(threshold);
209     jPanel3.add(slider);
210     jPanel4.add(thresholdValue);
211     jPanel4.add(thresholdIsMin);
212     this.add(jPanel1);// , java.awt.BorderLayout.NORTH);
213     this.add(jPanel2);// , java.awt.BorderLayout.NORTH);
214     this.add(jPanel3);// , java.awt.BorderLayout.CENTER);
215     this.add(jPanel4);// , java.awt.BorderLayout.CENTER);
216   }
217
218   Panel minColour = new Panel();
219
220   Panel maxColour = new Panel();
221
222   Panel jPanel1 = new Panel();
223
224   Panel jPanel2 = new Panel();
225
226   Choice threshold = new Choice();
227
228   Panel jPanel3 = new Panel();
229
230   Panel jPanel4 = new Panel();
231
232   Scrollbar slider = new Scrollbar(Scrollbar.HORIZONTAL);
233
234   TextField thresholdValue = new TextField(20);
235
236   // BorderLayout borderLayout1 = new BorderLayout();
237
238   Checkbox thresholdIsMin = new Checkbox();
239
240   Checkbox colourFromLabel = new Checkbox();
241
242   private GraphLine threshline;
243
244   public void actionPerformed(ActionEvent evt)
245   {
246     if (evt.getSource() == thresholdValue)
247     {
248       try
249       {
250         float f = new Float(thresholdValue.getText()).floatValue();
251         slider.setValue((int) (f * 1000));
252         adjustmentValueChanged(null);
253       } catch (NumberFormatException ex)
254       {
255       }
256     }
257     else if (evt.getSource() == minColour)
258     {
259       minColour_actionPerformed(null);
260     }
261     else if (evt.getSource() == maxColour)
262     {
263       maxColour_actionPerformed(null);
264     }
265     else
266     {
267       changeColour();
268     }
269   }
270
271   public void itemStateChanged(ItemEvent evt)
272   {
273     maxColour.setEnabled(!colourFromLabel.getState());
274     minColour.setEnabled(!colourFromLabel.getState());
275     changeColour();
276   }
277
278   public void adjustmentValueChanged(AdjustmentEvent evt)
279   {
280     if (!adjusting)
281     {
282       thresholdValue.setText(((float) slider.getValue() / 1000f) + "");
283       valueChanged();
284     }
285   }
286
287   protected void valueChanged()
288   {
289     threshline.value = (float) slider.getValue() / 1000f;
290     cs.setThresh(threshline.value);
291     changeColour();
292     PaintRefresher.Refresh(this, fr.av.getSequenceSetId());
293     // ap.paintAlignment(false);
294   }
295
296   public void minColour_actionPerformed(Color newCol)
297   {
298     if (newCol == null)
299     {
300       UserDefinedColours udc = new UserDefinedColours(this,
301               minColour.getBackground(), owner,
302               MessageManager.getString("label.select_colour_minimum_value")); // frame.owner,
303     }
304     else
305     {
306       minColour.setBackground(newCol);
307       minColour.setForeground(newCol);
308       minColour.repaint();
309       changeColour();
310     }
311
312   }
313
314   public void maxColour_actionPerformed(Color newCol)
315   {
316     if (newCol == null)
317     {
318
319       // UserDefinedColours udc = new UserDefinedColours(this,
320       // "Select Colour for Maximum Value",maxColour.getBackground(),true);
321       UserDefinedColours udc = new UserDefinedColours(this,
322               maxColour.getBackground(), owner,
323               MessageManager.getString("label.select_colour_maximum_value"));
324     }
325     else
326     {
327       maxColour.setBackground(newCol);
328       maxColour.setForeground(newCol);
329       maxColour.repaint();
330       changeColour();
331     }
332   }
333
334   void changeColour()
335   {
336     // Check if combobox is still adjusting
337     if (adjusting)
338     {
339       return;
340     }
341
342     int aboveThreshold = AnnotationColourGradient.NO_THRESHOLD;
343     if (threshold.getSelectedIndex() == 1)
344     {
345       aboveThreshold = AnnotationColourGradient.ABOVE_THRESHOLD;
346     }
347     else if (threshold.getSelectedIndex() == 2)
348     {
349       aboveThreshold = AnnotationColourGradient.BELOW_THRESHOLD;
350     }
351
352     slider.setEnabled(true);
353     thresholdValue.setEnabled(true);
354     GraduatedColor acg = new GraduatedColor(minColour.getBackground(),
355             maxColour.getBackground(), min, max);
356
357     acg.setColourByLabel(colourFromLabel.getState());
358     maxColour.setEnabled(!colourFromLabel.getState());
359     minColour.setEnabled(!colourFromLabel.getState());
360     if (aboveThreshold == AnnotationColourGradient.NO_THRESHOLD)
361     {
362       slider.setEnabled(false);
363       thresholdValue.setEnabled(false);
364       thresholdValue.setText("");
365     }
366
367     else if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD
368             && threshline == null)
369     {
370       // todo visual indication of feature threshold
371       threshline = new jalview.datamodel.GraphLine((max - min) / 2f,
372               "Threshold", Color.black);
373     }
374
375     if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
376     {
377       adjusting = true;
378       acg.setThresh(threshline.value);
379
380       float range = max * 1000f - min * 1000f;
381
382       slider.setMinimum((int) (min * 1000));
383       slider.setMaximum((int) (max * 1000));
384       slider.setValue((int) (threshline.value * 1000));
385       thresholdValue.setText(threshline.value + "");
386       slider.setEnabled(true);
387       thresholdValue.setEnabled(true);
388       adjusting = false;
389     }
390
391     acg.setThreshType(aboveThreshold);
392     if (thresholdIsMin.getState()
393             && aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
394     {
395       if (aboveThreshold == AnnotationColourGradient.ABOVE_THRESHOLD)
396       {
397         acg = new GraduatedColor(acg, threshline.value, max);
398       }
399       else
400       {
401         acg = new GraduatedColor(acg, min, threshline.value);
402       }
403     }
404
405     fr.featureColours.put(type, acg);
406     cs = acg;
407     PaintRefresher.Refresh(this, fr.av.getSequenceSetId());
408     // ap.paintAlignment(false);
409   }
410
411   void reset()
412   {
413     fr.featureColours.put(type, oldcs);
414     PaintRefresher.Refresh(this, fr.av.getSequenceSetId());
415     // ap.paintAlignment(true);
416
417   }
418
419   public void mouseClicked(MouseEvent evt)
420   {
421   }
422
423   public void mousePressed(MouseEvent evt)
424   {
425   }
426
427   public void mouseReleased(MouseEvent evt)
428   {
429     if (evt.getSource() == minColour || evt.getSource() == maxColour)
430     {
431       // relay the event
432       actionPerformed(new ActionEvent(evt.getSource(), 1, "Clicked"));
433     }
434     else
435     {
436       PaintRefresher.Refresh(this, fr.av.getSequenceSetId());
437     }
438     // ap.paintAlignment(true);
439   }
440
441   public void mouseEntered(MouseEvent evt)
442   {
443   }
444
445   public void mouseExited(MouseEvent evt)
446   {
447   }
448
449 }