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