2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
3 * Copyright (C) 2014 The Jalview Authors
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/>.
17 * The Jalview Authors are detailed in the 'AUTHORS' file.
24 import java.awt.event.*;
27 import javax.swing.event.*;
29 import net.miginfocom.swing.MigLayout;
31 import jalview.bin.Cache;
32 import jalview.datamodel.*;
33 import jalview.schemes.*;
34 import jalview.util.MessageManager;
36 import java.awt.Dimension;
38 public class AnnotationColourChooser extends JPanel
48 Hashtable oldgroupColours;
50 jalview.datamodel.AlignmentAnnotation currentAnnotation;
52 boolean adjusting = false;
54 * enabled if the user is dragging the slider - try to keep updates to a minimun
56 boolean sliderDragging = false;
58 public AnnotationColourChooser(AlignViewport av, final AlignmentPanel ap)
60 oldcs = av.getGlobalColourScheme();
61 if (av.getAlignment().getGroups() != null)
63 oldgroupColours = new Hashtable();
64 for (SequenceGroup sg : ap.av.getAlignment().getGroups())
68 oldgroupColours.put(sg, sg.cs);
74 frame = new JInternalFrame();
75 frame.setContentPane(this);
76 frame.setLayer(JLayeredPane.PALETTE_LAYER);
77 Desktop.addInternalFrame(frame, MessageManager.getString("label.colour_by_annotation"), 520, 215);
79 slider.addChangeListener(new ChangeListener()
81 public void stateChanged(ChangeEvent evt)
85 thresholdValue.setText(((float) slider.getValue() / 1000f) + "");
86 valueChanged(!sliderDragging);
90 slider.addMouseListener(new MouseAdapter()
93 public void mousePressed(MouseEvent e)
96 super.mousePressed(e);
100 public void mouseDragged(MouseEvent e)
103 super.mouseDragged(e);
105 public void mouseReleased(MouseEvent evt)
109 sliderDragging=false;
112 ap.paintAlignment(true);
116 if (av.getAlignment().getAlignmentAnnotation() == null)
121 // Always get default shading from preferences.
125 if (oldcs instanceof AnnotationColourGradient)
127 AnnotationColourGradient acg = (AnnotationColourGradient) oldcs;
128 currentColours.setSelected(acg.isPredefinedColours() || acg.getBaseColour()!=null);
129 if (!acg.isPredefinedColours() && acg.getBaseColour()==null)
131 minColour.setBackground(acg.getMinColour());
132 maxColour.setBackground(acg.getMaxColour());
134 seqAssociated.setSelected(acg.isSeqAssociated());
137 annotations = new JComboBox(
138 getAnnotationItems(seqAssociated.isSelected()));
140 threshold.addItem(MessageManager.getString("label.threshold_feature_no_thereshold"));
141 threshold.addItem(MessageManager.getString("label.threshold_feature_above_thereshold"));
142 threshold.addItem(MessageManager.getString("label.threshold_feature_below_thereshold"));
144 if (oldcs instanceof AnnotationColourGradient)
146 AnnotationColourGradient acg = (AnnotationColourGradient) oldcs;
147 annotations.setSelectedItem(acg.getAnnotation());
148 switch (acg.getAboveThreshold())
150 case AnnotationColourGradient.NO_THRESHOLD:
151 threshold.setSelectedIndex(0);
153 case AnnotationColourGradient.ABOVE_THRESHOLD:
154 threshold.setSelectedIndex(1);
156 case AnnotationColourGradient.BELOW_THRESHOLD:
157 threshold.setSelectedIndex(2);
161 "Implementation error: don't know about threshold setting for current AnnotationColourGradient.");
163 thresholdIsMin.setSelected(acg.thresholdIsMinMax);
164 thresholdValue.setText("" + acg.getAnnotationThreshold());
170 } catch (Exception ex)
182 private Vector<String> getAnnotationItems(boolean isSeqAssociated)
184 Vector<String> list = new Vector<String>();
186 int[] anmap = new int[av.getAlignment().getAlignmentAnnotation().length];
187 boolean enableSeqAss = false;
188 for (int i = 0; i < av.getAlignment().getAlignmentAnnotation().length; i++)
190 if (av.getAlignment().getAlignmentAnnotation()[i].sequenceRef == null)
201 String label = av.getAlignment().getAlignmentAnnotation()[i].label;
202 if (!list.contains(label))
204 anmap[list.size()] = i;
205 list.addElement(label);
210 if (!isSeqAssociated)
212 anmap[list.size()] = i;
213 list.addElement(label + "_" + (index++));
217 seqAssociated.setEnabled(enableSeqAss);
218 annmap = new int[list.size()];
219 System.arraycopy(anmap, 0, annmap, 0, annmap.length);
222 private void setDefaultMinMax()
224 minColour.setBackground(Cache.getDefaultColour("ANNOTATIONCOLOUR_MIN",
226 maxColour.setBackground(Cache.getDefaultColour("ANNOTATIONCOLOUR_MAX",
230 public AnnotationColourChooser()
235 } catch (Exception ex)
237 ex.printStackTrace();
241 private void jbInit() throws Exception
243 minColour.setFont(JvSwingUtils.getLabelFont());
244 minColour.setBorder(BorderFactory.createEtchedBorder());
245 minColour.setPreferredSize(new Dimension(40, 20));
246 minColour.setToolTipText(MessageManager.getString("label.min_colour"));
247 minColour.addMouseListener(new MouseAdapter()
249 public void mousePressed(MouseEvent e)
251 if (minColour.isEnabled())
253 minColour_actionPerformed();
257 maxColour.setFont(JvSwingUtils.getLabelFont());
258 maxColour.setBorder(BorderFactory.createEtchedBorder());
259 maxColour.setPreferredSize(new Dimension(40, 20));
260 maxColour.setToolTipText(MessageManager.getString("label.max_colour"));
261 maxColour.addMouseListener(new MouseAdapter()
263 public void mousePressed(MouseEvent e)
265 if (maxColour.isEnabled())
267 maxColour_actionPerformed();
272 ok.setText(MessageManager.getString("action.ok"));
273 ok.addActionListener(new ActionListener()
275 public void actionPerformed(ActionEvent e)
277 ok_actionPerformed(e);
280 cancel.setOpaque(false);
281 cancel.setText(MessageManager.getString("action.cancel"));
282 cancel.addActionListener(new ActionListener()
284 public void actionPerformed(ActionEvent e)
286 cancel_actionPerformed(e);
289 defColours.setOpaque(false);
290 defColours.setText(MessageManager.getString("action.set_defaults"));
292 .setToolTipText(MessageManager.getString("label.reset_min_max_colours_to_defaults"));
293 defColours.addActionListener(new ActionListener()
297 public void actionPerformed(ActionEvent arg0)
299 resetColours_actionPerformed(arg0);
303 annotations.addActionListener(new ActionListener()
305 public void actionPerformed(ActionEvent e)
307 annotations_actionPerformed(e);
310 threshold.addActionListener(new ActionListener()
312 public void actionPerformed(ActionEvent e)
314 threshold_actionPerformed(e);
317 thresholdValue.addActionListener(new ActionListener()
319 public void actionPerformed(ActionEvent e)
321 thresholdValue_actionPerformed(e);
324 slider.setPaintLabels(false);
325 slider.setPaintTicks(true);
326 slider.setBackground(Color.white);
327 slider.setEnabled(false);
328 slider.setOpaque(false);
329 slider.setPreferredSize(new Dimension(100, 32));
330 thresholdValue.setEnabled(false);
331 thresholdValue.setColumns(7);
332 currentColours.setFont(JvSwingUtils.getLabelFont());
333 currentColours.setOpaque(false);
334 currentColours.setText(MessageManager.getString("label.use_original_colours"));
335 currentColours.addActionListener(new ActionListener()
337 public void actionPerformed(ActionEvent e)
339 currentColours_actionPerformed(e);
342 thresholdIsMin.setBackground(Color.white);
343 thresholdIsMin.setFont(JvSwingUtils.getLabelFont());
344 thresholdIsMin.setText(MessageManager.getString("label.threshold_minmax"));
345 thresholdIsMin.addActionListener(new ActionListener()
347 public void actionPerformed(ActionEvent actionEvent)
349 thresholdIsMin_actionPerformed(actionEvent);
352 seqAssociated.setBackground(Color.white);
353 seqAssociated.setFont(JvSwingUtils.getLabelFont());
354 seqAssociated.setText(MessageManager.getString("label.per_sequence_only"));
355 seqAssociated.addActionListener(new ActionListener()
359 public void actionPerformed(ActionEvent arg0)
361 seqAssociated_actionPerformed(arg0);
365 this.setLayout(borderLayout1);
366 jPanel2.setLayout(new MigLayout("", "[left][center][right]", "[][][]"));
367 jPanel1.setBackground(Color.white);
368 jPanel2.setBackground(Color.white);
372 jPanel2.add(annotations, "grow, wrap");
373 jPanel2.add(seqAssociated);
374 jPanel2.add(currentColours);
375 JPanel colpanel = new JPanel(new FlowLayout());
376 colpanel.setBackground(Color.white);
377 colpanel.add(minColour);
378 colpanel.add(maxColour);
379 jPanel2.add(colpanel, "wrap");
380 jPanel2.add(threshold);
381 jPanel2.add(defColours, "skip 1, wrap");
382 jPanel2.add(thresholdIsMin);
383 jPanel2.add(slider, "grow");
384 jPanel2.add(thresholdValue, "grow");
385 this.add(jPanel1, java.awt.BorderLayout.SOUTH);
386 this.add(jPanel2, java.awt.BorderLayout.CENTER);
390 protected void seqAssociated_actionPerformed(ActionEvent arg0)
393 String cursel = (String) annotations.getSelectedItem();
394 boolean isvalid = false, isseqs = seqAssociated.isSelected();
395 this.annotations.removeAllItems();
396 for (String anitem : getAnnotationItems(seqAssociated.isSelected()))
398 if (anitem.equals(cursel) || (isseqs && cursel.startsWith(anitem)))
403 this.annotations.addItem(anitem);
408 this.annotations.setSelectedItem(cursel);
412 if (annotations.getItemCount() > 0)
414 annotations.setSelectedIndex(0);
419 protected void resetColours_actionPerformed(ActionEvent arg0)
425 JComboBox annotations;
429 JPanel minColour = new JPanel();
431 JPanel maxColour = new JPanel();
433 JButton defColours = new JButton();
435 JButton ok = new JButton();
437 JButton cancel = new JButton();
439 JPanel jPanel1 = new JPanel();
441 JPanel jPanel2 = new JPanel();
443 BorderLayout borderLayout1 = new BorderLayout();
445 JComboBox threshold = new JComboBox();
447 JSlider slider = new JSlider();
449 JTextField thresholdValue = new JTextField(20);
451 JCheckBox currentColours = new JCheckBox();
453 JCheckBox thresholdIsMin = new JCheckBox();
455 JCheckBox seqAssociated = new JCheckBox();
457 public void minColour_actionPerformed()
459 Color col = JColorChooser.showDialog(this,
460 "Select Colour for Minimum Value", minColour.getBackground());
463 minColour.setBackground(col);
469 public void maxColour_actionPerformed()
471 Color col = JColorChooser.showDialog(this,
472 "Select Colour for Maximum Value", maxColour.getBackground());
475 maxColour.setBackground(col);
483 // Check if combobox is still adjusting
489 currentAnnotation = av.getAlignment().getAlignmentAnnotation()[annmap[annotations
490 .getSelectedIndex()]];
492 int aboveThreshold = -1;
493 if (threshold.getSelectedIndex()==1)
495 aboveThreshold = AnnotationColourGradient.ABOVE_THRESHOLD;
497 else if (threshold.getSelectedIndex()==2)
499 aboveThreshold = AnnotationColourGradient.BELOW_THRESHOLD;
502 slider.setEnabled(true);
503 thresholdValue.setEnabled(true);
504 thresholdIsMin.setEnabled(true);
506 if (aboveThreshold == AnnotationColourGradient.NO_THRESHOLD)
508 slider.setEnabled(false);
509 thresholdValue.setEnabled(false);
510 thresholdValue.setText("");
511 thresholdIsMin.setEnabled(false);
513 else if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD
514 && currentAnnotation.threshold == null)
517 .setThreshold(new jalview.datamodel.GraphLine(
518 (currentAnnotation.graphMax - currentAnnotation.graphMin) / 2f,
519 "Threshold", Color.black));
522 if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
525 float range = currentAnnotation.graphMax * 1000
526 - currentAnnotation.graphMin * 1000;
528 slider.setMinimum((int) (currentAnnotation.graphMin * 1000));
529 slider.setMaximum((int) (currentAnnotation.graphMax * 1000));
530 slider.setValue((int) (currentAnnotation.threshold.value * 1000));
531 thresholdValue.setText(currentAnnotation.threshold.value + "");
532 slider.setMajorTickSpacing((int) (range / 10f));
533 slider.setEnabled(true);
534 thresholdValue.setEnabled(true);
538 AnnotationColourGradient acg = null;
539 if (currentColours.isSelected())
541 acg = new AnnotationColourGradient(currentAnnotation,
542 av.getGlobalColourScheme(), aboveThreshold);
546 acg = new AnnotationColourGradient(currentAnnotation,
547 minColour.getBackground(), maxColour.getBackground(),
550 acg.setSeqAssociated(seqAssociated.isSelected());
552 if (currentAnnotation.graphMin == 0f
553 && currentAnnotation.graphMax == 0f)
555 acg.setPredefinedColours(true);
558 acg.thresholdIsMinMax = thresholdIsMin.isSelected();
560 av.setGlobalColourScheme(acg);
562 if (av.getAlignment().getGroups() != null)
565 for (SequenceGroup sg : ap.av.getAlignment().getGroups())
572 if (currentColours.isSelected())
574 sg.cs = new AnnotationColourGradient(currentAnnotation, sg.cs,
576 ((AnnotationColourGradient) sg.cs).setSeqAssociated(seqAssociated
582 sg.cs = new AnnotationColourGradient(currentAnnotation,
583 minColour.getBackground(), maxColour.getBackground(),
585 ((AnnotationColourGradient) sg.cs).setSeqAssociated(seqAssociated
591 ap.alignmentChanged();
592 // ensure all associated views (overviews, structures, etc) are notified of
594 ap.paintAlignment(true);
597 public void ok_actionPerformed(ActionEvent e)
602 frame.setClosed(true);
603 } catch (Exception ex)
608 public void cancel_actionPerformed(ActionEvent e)
611 // ensure all original colouring is propagated to listeners.
612 ap.paintAlignment(true);
615 frame.setClosed(true);
616 } catch (Exception ex)
623 av.setGlobalColourScheme(oldcs);
624 if (av.getAlignment().getGroups() != null)
627 for (SequenceGroup sg : ap.av.getAlignment().getGroups())
629 sg.cs = (ColourSchemeI) oldgroupColours.get(sg);
634 public void thresholdCheck_actionPerformed(ActionEvent e)
639 public void annotations_actionPerformed(ActionEvent e)
644 public void threshold_actionPerformed(ActionEvent e)
649 public void thresholdValue_actionPerformed(ActionEvent e)
653 float f = Float.parseFloat(thresholdValue.getText());
654 slider.setValue((int) (f * 1000));
655 } catch (NumberFormatException ex)
660 public void valueChanged(boolean updateAllAnnotation)
662 if (currentColours.isSelected()
663 && !(av.getGlobalColourScheme() instanceof AnnotationColourGradient))
667 currentAnnotation.threshold.value = (float) slider.getValue() / 1000f;
668 propagateSeqAssociatedThreshold(updateAllAnnotation);
669 ap.paintAlignment(false);
672 private void propagateSeqAssociatedThreshold(boolean allAnnotation)
674 if (currentAnnotation.sequenceRef == null
675 || currentAnnotation.threshold == null)
679 // TODO: JAL-1327 only update visible annotation thresholds if allAnnotation is false, since we only need to provide a quick visual indicator
681 float thr = currentAnnotation.threshold.value;
682 for (int i = 0; i < av.getAlignment().getAlignmentAnnotation().length; i++)
684 AlignmentAnnotation aa = av.getAlignment().getAlignmentAnnotation()[i];
685 if (aa.label.equals(currentAnnotation.label))
687 aa.threshold.value = thr;
692 public void currentColours_actionPerformed(ActionEvent e)
694 if (currentColours.isSelected())
699 maxColour.setEnabled(!currentColours.isSelected());
700 minColour.setEnabled(!currentColours.isSelected());
705 public void thresholdIsMin_actionPerformed(ActionEvent actionEvent)