2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
3 * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
5 * This file is part of Jalview.
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.
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.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
23 import java.awt.event.*;
26 import javax.swing.event.*;
28 import net.miginfocom.swing.MigLayout;
30 import jalview.bin.Cache;
31 import jalview.datamodel.*;
32 import jalview.schemes.*;
33 import java.awt.Dimension;
35 public class AnnotationColourChooser extends JPanel
45 Hashtable oldgroupColours;
47 jalview.datamodel.AlignmentAnnotation currentAnnotation;
49 boolean adjusting = false;
51 public AnnotationColourChooser(AlignViewport av, final AlignmentPanel ap)
53 oldcs = av.getGlobalColourScheme();
54 if (av.getAlignment().getGroups() != null)
56 oldgroupColours = new Hashtable();
57 for (SequenceGroup sg:ap.av.getAlignment().getGroups())
61 oldgroupColours.put(sg, sg.cs);
67 frame = new JInternalFrame();
68 frame.setContentPane(this);
69 frame.setLayer(JLayeredPane.PALETTE_LAYER);
70 Desktop.addInternalFrame(frame, "Colour by Annotation", 520, 215);
72 slider.addChangeListener(new ChangeListener()
74 public void stateChanged(ChangeEvent evt)
78 thresholdValue.setText(((float) slider.getValue() / 1000f) + "");
83 slider.addMouseListener(new MouseAdapter()
85 public void mouseReleased(MouseEvent evt)
87 ap.paintAlignment(true);
91 if (av.getAlignment().getAlignmentAnnotation() == null)
96 // Always get default shading from preferences.
99 if (oldcs instanceof AnnotationColourGradient)
101 AnnotationColourGradient acg = (AnnotationColourGradient) oldcs;
102 currentColours.setSelected(acg.predefinedColours);
103 if (!acg.predefinedColours)
105 minColour.setBackground(acg.getMinColour());
106 maxColour.setBackground(acg.getMaxColour());
108 seqAssociated.setSelected(acg.isSeqAssociated());
111 annotations = new JComboBox(getAnnotationItems(seqAssociated.isSelected()));
113 threshold.addItem("No Threshold");
114 threshold.addItem("Above Threshold");
115 threshold.addItem("Below Threshold");
117 if (oldcs instanceof AnnotationColourGradient)
119 AnnotationColourGradient acg = (AnnotationColourGradient) oldcs;
120 annotations.setSelectedItem(acg.getAnnotation());
121 switch (acg.getAboveThreshold()) {
122 case AnnotationColourGradient.NO_THRESHOLD:
123 threshold.setSelectedItem("No Threshold");
125 case AnnotationColourGradient.ABOVE_THRESHOLD:
126 threshold.setSelectedItem("Above Threshold");
128 case AnnotationColourGradient.BELOW_THRESHOLD:
129 threshold.setSelectedItem("Below Threshold");
132 throw new Error("Implementation error: don't know about threshold setting for current AnnotationColourGradient.");
134 thresholdIsMin.setSelected(acg.thresholdIsMinMax);
135 thresholdValue.setText(""+acg.getAnnotationThreshold());
141 } catch (Exception ex)
153 private Vector<String> getAnnotationItems(boolean isSeqAssociated) {
154 Vector<String> list = new Vector<String>();
156 int[] anmap = new int[av.getAlignment().getAlignmentAnnotation().length];
157 boolean enableSeqAss=false;
158 for (int i = 0; i < av.getAlignment().getAlignmentAnnotation().length; i++)
160 if (av.getAlignment().getAlignmentAnnotation()[i].sequenceRef==null)
169 String label = av.getAlignment().getAlignmentAnnotation()[i].label;
170 if (!list.contains(label))
171 {anmap[list.size()] = i;
172 list.addElement(label);
175 if (!isSeqAssociated) {
176 anmap[list.size()] = i;
177 list.addElement(label + "_" + (index++));
181 seqAssociated.setEnabled(enableSeqAss);
182 annmap = new int[list.size()];
183 System.arraycopy(anmap, 0, annmap, 0, annmap.length);
186 private void setDefaultMinMax()
188 minColour.setBackground(Cache.getDefaultColour("ANNOTATIONCOLOUR_MIN", Color.orange));
189 maxColour.setBackground(Cache.getDefaultColour("ANNOTATIONCOLOUR_MAX", Color.red));
192 public AnnotationColourChooser()
197 } catch (Exception ex)
199 ex.printStackTrace();
203 private void jbInit() throws Exception
205 minColour.setFont(JvSwingUtils.getLabelFont());
206 minColour.setBorder(BorderFactory.createEtchedBorder());
207 minColour.setPreferredSize(new Dimension(40, 20));
208 minColour.setToolTipText("Minimum Colour");
209 minColour.addMouseListener(new MouseAdapter()
211 public void mousePressed(MouseEvent e)
213 if (minColour.isEnabled())
215 minColour_actionPerformed();
219 maxColour.setFont(JvSwingUtils.getLabelFont());
220 maxColour.setBorder(BorderFactory.createEtchedBorder());
221 maxColour.setPreferredSize(new Dimension(40, 20));
222 maxColour.setToolTipText("Maximum Colour");
223 maxColour.addMouseListener(new MouseAdapter()
225 public void mousePressed(MouseEvent e)
227 if (maxColour.isEnabled())
229 maxColour_actionPerformed();
235 ok.addActionListener(new ActionListener()
237 public void actionPerformed(ActionEvent e)
239 ok_actionPerformed(e);
242 cancel.setOpaque(false);
243 cancel.setText("Cancel");
244 cancel.addActionListener(new ActionListener()
246 public void actionPerformed(ActionEvent e)
248 cancel_actionPerformed(e);
251 defColours.setOpaque(false);
252 defColours.setText("Defaults");
253 defColours.setToolTipText("Reset min and max colours to defaults from user preferences.");
254 defColours.addActionListener(new ActionListener()
258 public void actionPerformed(ActionEvent arg0)
260 resetColours_actionPerformed(arg0);
264 annotations.addActionListener(new ActionListener()
266 public void actionPerformed(ActionEvent e)
268 annotations_actionPerformed(e);
271 threshold.addActionListener(new ActionListener()
273 public void actionPerformed(ActionEvent e)
275 threshold_actionPerformed(e);
278 thresholdValue.addActionListener(new ActionListener()
280 public void actionPerformed(ActionEvent e)
282 thresholdValue_actionPerformed(e);
285 slider.setPaintLabels(false);
286 slider.setPaintTicks(true);
287 slider.setBackground(Color.white);
288 slider.setEnabled(false);
289 slider.setOpaque(false);
290 slider.setPreferredSize(new Dimension(100, 32));
291 thresholdValue.setEnabled(false);
292 thresholdValue.setColumns(7);
293 currentColours.setFont(JvSwingUtils.getLabelFont());
294 currentColours.setOpaque(false);
295 currentColours.setText("Use Original Colours");
296 currentColours.addActionListener(new ActionListener()
298 public void actionPerformed(ActionEvent e)
300 currentColours_actionPerformed(e);
303 thresholdIsMin.setBackground(Color.white);
304 thresholdIsMin.setFont(JvSwingUtils.getLabelFont());
305 thresholdIsMin.setText("Threshold is Min/Max");
306 thresholdIsMin.addActionListener(new ActionListener()
308 public void actionPerformed(ActionEvent actionEvent)
310 thresholdIsMin_actionPerformed(actionEvent);
313 seqAssociated.setBackground(Color.white);
314 seqAssociated.setFont(JvSwingUtils.getLabelFont());
315 seqAssociated.setText("Per-sequence only");
316 seqAssociated.addActionListener(new ActionListener()
320 public void actionPerformed(ActionEvent arg0)
322 seqAssociated_actionPerformed(arg0);
326 this.setLayout(borderLayout1);
327 jPanel2.setLayout(new MigLayout("","[left][center][right]","[][][]"));
328 jPanel1.setBackground(Color.white);
329 jPanel2.setBackground(Color.white);
333 jPanel2.add(annotations, "grow, wrap");
334 jPanel2.add(seqAssociated);
335 jPanel2.add(currentColours);
336 JPanel colpanel = new JPanel(new FlowLayout());
337 colpanel.setBackground(Color.white);
338 colpanel.add(minColour);
339 colpanel.add(maxColour);
340 jPanel2.add(colpanel, "wrap");
341 jPanel2.add(threshold);
342 jPanel2.add(defColours,"skip 1, wrap");
343 jPanel2.add(thresholdIsMin);
344 jPanel2.add(slider, "grow");
345 jPanel2.add(thresholdValue, "grow");
346 this.add(jPanel1, java.awt.BorderLayout.SOUTH);
347 this.add(jPanel2, java.awt.BorderLayout.CENTER);
351 protected void seqAssociated_actionPerformed(ActionEvent arg0)
354 String cursel = (String) annotations.getSelectedItem();
355 boolean isvalid=false,isseqs=seqAssociated.isSelected();
356 this.annotations.removeAllItems();
357 for (String anitem:getAnnotationItems(seqAssociated.isSelected()))
359 if (anitem.equals( cursel) || (isseqs && cursel.startsWith(anitem)))
364 this.annotations.addItem(anitem);
367 if (isvalid) { this.annotations.setSelectedItem(cursel); } else {
368 if (annotations.getItemCount()>0) {
369 annotations.setSelectedIndex(0);
374 protected void resetColours_actionPerformed(ActionEvent arg0)
380 JComboBox annotations;
382 JPanel minColour = new JPanel();
384 JPanel maxColour = new JPanel();
385 JButton defColours = new JButton();
386 JButton ok = new JButton();
388 JButton cancel = new JButton();
390 JPanel jPanel1 = new JPanel();
391 JPanel jPanel2 = new JPanel();
393 BorderLayout borderLayout1 = new BorderLayout();
395 JComboBox threshold = new JComboBox();
398 JSlider slider = new JSlider();
400 JTextField thresholdValue = new JTextField(20);
402 JCheckBox currentColours = new JCheckBox();
404 JCheckBox thresholdIsMin = new JCheckBox();
406 JCheckBox seqAssociated = new JCheckBox();
408 public void minColour_actionPerformed()
410 Color col = JColorChooser.showDialog(this,
411 "Select Colour for Minimum Value", minColour.getBackground());
414 minColour.setBackground(col);
420 public void maxColour_actionPerformed()
422 Color col = JColorChooser.showDialog(this,
423 "Select Colour for Maximum Value", maxColour.getBackground());
426 maxColour.setBackground(col);
434 // Check if combobox is still adjusting
440 currentAnnotation = av.getAlignment().getAlignmentAnnotation()[annmap[annotations
441 .getSelectedIndex()]];
443 int aboveThreshold = -1;
444 if (threshold.getSelectedItem().equals("Above Threshold"))
446 aboveThreshold = AnnotationColourGradient.ABOVE_THRESHOLD;
448 else if (threshold.getSelectedItem().equals("Below Threshold"))
450 aboveThreshold = AnnotationColourGradient.BELOW_THRESHOLD;
453 slider.setEnabled(true);
454 thresholdValue.setEnabled(true);
455 thresholdIsMin.setEnabled(true);
457 if (aboveThreshold == AnnotationColourGradient.NO_THRESHOLD)
459 slider.setEnabled(false);
460 thresholdValue.setEnabled(false);
461 thresholdValue.setText("");
462 thresholdIsMin.setEnabled(false);
464 else if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD
465 && currentAnnotation.threshold == null)
468 .setThreshold(new jalview.datamodel.GraphLine(
469 (currentAnnotation.graphMax - currentAnnotation.graphMin) / 2f,
470 "Threshold", Color.black));
473 if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
476 float range = currentAnnotation.graphMax * 1000
477 - currentAnnotation.graphMin * 1000;
479 slider.setMinimum((int) (currentAnnotation.graphMin * 1000));
480 slider.setMaximum((int) (currentAnnotation.graphMax * 1000));
481 slider.setValue((int) (currentAnnotation.threshold.value * 1000));
482 thresholdValue.setText(currentAnnotation.threshold.value + "");
483 slider.setMajorTickSpacing((int) (range / 10f));
484 slider.setEnabled(true);
485 thresholdValue.setEnabled(true);
489 AnnotationColourGradient acg = null;
490 if (currentColours.isSelected())
492 acg = new AnnotationColourGradient(currentAnnotation,
493 av.getGlobalColourScheme(), aboveThreshold);
497 acg = new AnnotationColourGradient(currentAnnotation,
498 minColour.getBackground(), maxColour.getBackground(),
501 acg.setSeqAssociated(seqAssociated.isSelected());
503 if (currentAnnotation.graphMin == 0f
504 && currentAnnotation.graphMax == 0f)
506 acg.predefinedColours = true;
509 acg.thresholdIsMinMax = thresholdIsMin.isSelected();
511 av.setGlobalColourScheme(acg);
513 if (av.getAlignment().getGroups() != null)
516 for (SequenceGroup sg:ap.av.getAlignment().getGroups())
523 if (currentColours.isSelected())
525 sg.cs = new AnnotationColourGradient(currentAnnotation, sg.cs,
527 ((AnnotationColourGradient)sg.cs).setSeqAssociated(seqAssociated.isSelected());
532 sg.cs = new AnnotationColourGradient(currentAnnotation,
533 minColour.getBackground(), maxColour.getBackground(),
535 ((AnnotationColourGradient)sg.cs).setSeqAssociated(seqAssociated.isSelected());
540 ap.alignmentChanged();
541 // ensure all associated views (overviews, structures, etc) are notified of updated colours.
542 ap.paintAlignment(true);
545 public void ok_actionPerformed(ActionEvent e)
550 frame.setClosed(true);
551 } catch (Exception ex)
556 public void cancel_actionPerformed(ActionEvent e)
559 // ensure all original colouring is propagated to listeners.
560 ap.paintAlignment(true);
563 frame.setClosed(true);
564 } catch (Exception ex)
571 av.setGlobalColourScheme(oldcs);
572 if (av.getAlignment().getGroups() != null)
575 for (SequenceGroup sg:ap.av.getAlignment().getGroups())
577 sg.cs = (ColourSchemeI) oldgroupColours.get(sg);
582 public void thresholdCheck_actionPerformed(ActionEvent e)
587 public void annotations_actionPerformed(ActionEvent e)
592 public void threshold_actionPerformed(ActionEvent e)
597 public void thresholdValue_actionPerformed(ActionEvent e)
601 float f = Float.parseFloat(thresholdValue.getText());
602 slider.setValue((int) (f * 1000));
603 } catch (NumberFormatException ex)
608 public void valueChanged()
610 if (currentColours.isSelected()
611 && !(av.getGlobalColourScheme() instanceof AnnotationColourGradient))
616 currentAnnotation.threshold.value = (float) slider.getValue() / 1000f;
617 ap.paintAlignment(false);
620 public void currentColours_actionPerformed(ActionEvent e)
622 if (currentColours.isSelected())
627 maxColour.setEnabled(!currentColours.isSelected());
628 minColour.setEnabled(!currentColours.isSelected());
633 public void thresholdIsMin_actionPerformed(ActionEvent actionEvent)