2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ 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
10 * of the License, or (at your option) any later version.
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.
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.
23 import jalview.datamodel.AlignmentAnnotation;
24 import jalview.datamodel.GraphLine;
25 import jalview.schemes.AnnotationColourGradient;
26 import jalview.util.MessageManager;
28 import java.awt.Color;
29 import java.awt.Dimension;
30 import java.awt.event.ActionEvent;
31 import java.awt.event.ActionListener;
32 import java.awt.event.FocusAdapter;
33 import java.awt.event.FocusEvent;
34 import java.awt.event.ItemEvent;
35 import java.awt.event.ItemListener;
36 import java.awt.event.MouseAdapter;
37 import java.awt.event.MouseEvent;
38 import java.util.HashMap;
40 import java.util.Vector;
42 import javax.swing.JButton;
43 import javax.swing.JCheckBox;
44 import javax.swing.JComboBox;
45 import javax.swing.JInternalFrame;
46 import javax.swing.JPanel;
47 import javax.swing.JSlider;
48 import javax.swing.JTextField;
49 import javax.swing.event.ChangeEvent;
50 import javax.swing.event.ChangeListener;
52 @SuppressWarnings("serial")
53 public abstract class AnnotationRowFilter extends JPanel
55 protected AlignViewport av;
57 protected AlignmentPanel ap;
59 protected int[] annmap;
61 protected boolean adjusting = false;
63 protected JCheckBox seqAssociated = new JCheckBox();
65 protected JCheckBox percentThreshold = new JCheckBox();
67 protected JSlider slider = new JSlider();
69 protected JTextField thresholdValue = new JTextField(20);
71 protected JInternalFrame frame;
73 protected JButton ok = new JButton();
75 protected JButton cancel = new JButton();
78 * enabled if the user is dragging the slider - try to keep updates to a
81 protected boolean sliderDragging = false;
83 protected JComboBox<String> threshold = new JComboBox<>();
85 protected JComboBox<String> annotations;
88 * map from annotation to its menu item display label
89 * - so we know which item to pre-select on restore
91 private Map<AlignmentAnnotation, String> annotationLabels;
93 private AlignmentAnnotation currentAnnotation;
101 public AnnotationRowFilter(AlignViewport viewport,
102 final AlignmentPanel alignPanel)
105 this.ap = alignPanel;
106 thresholdValue.addFocusListener(new FocusAdapter()
109 public void focusLost(FocusEvent e)
111 thresholdValue_actionPerformed();
116 protected void addSliderChangeListener()
119 slider.addChangeListener(new ChangeListener()
122 public void stateChanged(ChangeEvent evt)
126 setThresholdValueText();
127 valueChanged(!sliderDragging);
134 * update the text field from the threshold slider. preserves state of
135 * 'adjusting' so safe to call in init.
137 protected void setThresholdValueText()
139 boolean oldadj = adjusting;
141 if (percentThreshold.isSelected())
143 thresholdValue.setText("" + (slider.getValue() - slider.getMinimum())
144 * 100f / (slider.getMaximum() - slider.getMinimum()));
148 thresholdValue.setText((slider.getValue() / 1000f) + "");
153 protected void addSliderMouseListeners()
156 slider.addMouseListener(new MouseAdapter()
159 public void mousePressed(MouseEvent e)
161 sliderDragging = true;
162 super.mousePressed(e);
166 public void mouseDragged(MouseEvent e)
168 sliderDragging = true;
169 super.mouseDragged(e);
173 public void mouseReleased(MouseEvent evt)
175 sliderDragReleased();
181 * Builds and returns a list of menu items (display text) for choice of
182 * annotation. Also builds maps between annotations, their positions in the
183 * list, and their display labels in the list.
185 * @param isSeqAssociated
188 public Vector<String> getAnnotationItems(boolean isSeqAssociated)
190 annotationLabels = new HashMap<>();
192 Vector<String> list = new Vector<>();
194 int[] anmap = new int[av.getAlignment()
195 .getAlignmentAnnotation().length];
196 seqAssociated.setEnabled(false);
197 for (int i = 0; i < av.getAlignment()
198 .getAlignmentAnnotation().length; i++)
200 AlignmentAnnotation annotation = av.getAlignment()
201 .getAlignmentAnnotation()[i];
202 if (annotation.sequenceRef == null)
211 seqAssociated.setEnabled(true);
213 String label = annotation.label;
214 // add associated sequence ID if available
215 if (!isSeqAssociated && annotation.sequenceRef != null)
217 label = label + "_" + annotation.sequenceRef.getName();
220 if (!list.contains(label))
222 anmap[list.size()] = i;
224 annotationLabels.put(annotation, label);
228 if (!isSeqAssociated)
230 anmap[list.size()] = i;
231 label = label + "_" + (index++);
233 annotationLabels.put(annotation, label);
237 this.annmap = new int[list.size()];
238 System.arraycopy(anmap, 0, this.annmap, 0, this.annmap.length);
242 protected int getSelectedThresholdItem(int indexValue)
244 int selectedThresholdItem = -1;
247 selectedThresholdItem = AnnotationColourGradient.ABOVE_THRESHOLD;
249 else if (indexValue == 2)
251 selectedThresholdItem = AnnotationColourGradient.BELOW_THRESHOLD;
253 return selectedThresholdItem;
256 public void ok_actionPerformed()
260 frame.setClosed(true);
261 } catch (Exception ex)
266 public void cancel_actionPerformed()
269 ap.paintAlignment(true, true);
272 frame.setClosed(true);
273 } catch (Exception ex)
278 protected void thresholdCheck_actionPerformed()
283 protected void selectedAnnotationChanged()
288 protected void threshold_actionPerformed()
293 protected void thresholdValue_actionPerformed()
297 float f = Float.parseFloat(thresholdValue.getText());
298 if (percentThreshold.isSelected())
300 slider.setValue(slider.getMinimum() + ((int) ((f / 100f)
301 * (slider.getMaximum() - slider.getMinimum()))));
305 slider.setValue((int) (f * 1000));
308 } catch (NumberFormatException ex)
313 protected void percentageValue_actionPerformed()
315 setThresholdValueText();
318 protected void thresholdIsMin_actionPerformed()
323 protected void populateThresholdComboBox(JComboBox<String> thresh)
325 thresh.addItem(MessageManager
326 .getString("label.threshold_feature_no_threshold"));
327 thresh.addItem(MessageManager
328 .getString("label.threshold_feature_above_threshold"));
329 thresh.addItem(MessageManager
330 .getString("label.threshold_feature_below_threshold"));
334 * Rebuilds the drop-down list of annotations to choose from when the 'per
335 * sequence only' checkbox is checked or unchecked.
339 protected void seqAssociated_actionPerformed(JComboBox<String> anns)
342 String cursel = (String) anns.getSelectedItem();
343 boolean isvalid = false;
344 boolean isseqs = seqAssociated.isSelected();
345 anns.removeAllItems();
346 for (String anitem : getAnnotationItems(seqAssociated.isSelected()))
348 if (anitem.equals(cursel) || (isseqs && cursel.startsWith(anitem)))
353 anns.addItem(anitem);
357 anns.setSelectedItem(cursel);
361 if (anns.getItemCount() > 0)
363 anns.setSelectedIndex(0);
372 protected void propagateSeqAssociatedThreshold(boolean allAnnotation,
373 AlignmentAnnotation annotation)
375 if (annotation.sequenceRef == null || annotation.threshold == null)
380 float thr = annotation.threshold.value;
381 for (int i = 0; i < av.getAlignment()
382 .getAlignmentAnnotation().length; i++)
384 AlignmentAnnotation aa = av.getAlignment()
385 .getAlignmentAnnotation()[i];
386 if (aa.label.equals(annotation.label)
387 && (annotation.getCalcId() == null ? aa.getCalcId() == null
388 : annotation.getCalcId().equals(aa.getCalcId())))
390 if (aa.threshold == null)
392 aa.threshold = new GraphLine(annotation.threshold);
396 aa.threshold.value = thr;
402 public AlignmentAnnotation getCurrentAnnotation()
404 return currentAnnotation;
407 protected void setCurrentAnnotation(AlignmentAnnotation annotation)
409 this.currentAnnotation = annotation;
413 * update associated view model and trigger any necessary repaints.
415 * @param updateAllAnnotation
417 protected abstract void valueChanged(boolean updateAllAnnotation);
419 protected abstract void updateView();
421 protected abstract void reset();
423 protected String getAnnotationMenuLabel(AlignmentAnnotation ann)
425 return annotationLabels.get(ann);
428 protected void jbInit()
431 ok.setText(MessageManager.getString("action.ok"));
432 ok.addActionListener(new ActionListener()
435 public void actionPerformed(ActionEvent e)
437 ok_actionPerformed();
441 cancel.setOpaque(false);
442 cancel.setText(MessageManager.getString("action.cancel"));
443 cancel.addActionListener(new ActionListener()
446 public void actionPerformed(ActionEvent e)
448 cancel_actionPerformed();
452 annotations.addItemListener(new ItemListener()
455 public void itemStateChanged(ItemEvent e)
457 selectedAnnotationChanged();
460 annotations.setToolTipText(
461 MessageManager.getString("info.select_annotation_row"));
463 threshold.addActionListener(new ActionListener()
466 public void actionPerformed(ActionEvent e)
468 threshold_actionPerformed();
472 thresholdValue.setEnabled(false);
473 thresholdValue.setColumns(7);
474 thresholdValue.addActionListener(new ActionListener()
477 public void actionPerformed(ActionEvent e)
479 thresholdValue_actionPerformed();
484 .setText(MessageManager.getString("label.as_percentage"));
485 percentThreshold.addActionListener(new ActionListener()
488 public void actionPerformed(ActionEvent e)
492 percentageValue_actionPerformed();
496 slider.setPaintLabels(false);
497 slider.setPaintTicks(true);
498 slider.setBackground(Color.white);
499 slider.setEnabled(false);
500 slider.setOpaque(false);
501 slider.setPreferredSize(new Dimension(100, 32));
504 public JComboBox<String> getThreshold()
509 public void setThreshold(JComboBox<String> thresh)
511 this.threshold = thresh;
514 public JComboBox<String> getAnnotations()
519 public void setAnnotations(JComboBox<String> anns)
521 this.annotations = anns;
524 protected void sliderDragReleased()
528 sliderDragging = false;