2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
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
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.
25 import java.util.List;
27 import java.awt.event.*;
28 import java.beans.PropertyChangeEvent;
29 import java.beans.PropertyChangeListener;
32 import javax.swing.event.*;
33 import javax.swing.table.*;
35 import jalview.analysis.AlignmentSorter;
36 import jalview.bin.Cache;
37 import jalview.commands.OrderCommand;
38 import jalview.datamodel.*;
40 import jalview.schemes.AnnotationColourGradient;
41 import jalview.schemes.GraduatedColor;
42 import jalview.util.MessageManager;
43 import jalview.ws.dbsources.das.api.jalviewSourceI;
45 public class FeatureSettings extends JPanel
47 DasSourceBrowser dassourceBrowser;
49 jalview.ws.DasSequenceFeatureFetcher dasFeatureFetcher;
51 JPanel settingsPane = new JPanel();
53 JPanel dasSettingsPane = new JPanel();
55 final FeatureRenderer fr;
57 public final AlignFrame af;
59 Object[][] originalData;
61 final JInternalFrame frame;
63 JScrollPane scrollPane = new JScrollPane();
69 JSlider transparency = new JSlider();
71 JPanel transPanel = new JPanel(new GridLayout(1, 2));
73 public FeatureSettings(AlignFrame af)
76 fr = af.getFeatureRenderer();
78 transparency.setMaximum(100 - (int) (fr.transparency * 100));
83 } catch (Exception ex)
89 table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));
90 table.setFont(new Font("Verdana", Font.PLAIN, 12));
91 table.setDefaultRenderer(Color.class, new ColorRenderer());
93 table.setDefaultEditor(Color.class, new ColorEditor(this));
95 table.setDefaultEditor(GraduatedColor.class, new ColorEditor(this));
96 table.setDefaultRenderer(GraduatedColor.class, new ColorRenderer());
97 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
99 table.addMouseListener(new MouseAdapter()
101 public void mousePressed(MouseEvent evt)
103 selectedRow = table.rowAtPoint(evt.getPoint());
104 if (evt.isPopupTrigger())
106 popupSort(selectedRow, (String) table.getValueAt(selectedRow, 0),
107 table.getValueAt(selectedRow, 1), fr.minmax, evt.getX(),
110 else if (evt.getClickCount() == 2)
112 fr.ap.alignFrame.avc.markColumnsContainingFeatures(
113 evt.isAltDown(), evt.isShiftDown() || evt.isMetaDown(),
115 (String) table.getValueAt(selectedRow, 0));
120 table.addMouseMotionListener(new MouseMotionAdapter()
122 public void mouseDragged(MouseEvent evt)
124 int newRow = table.rowAtPoint(evt.getPoint());
125 if (newRow != selectedRow && selectedRow != -1 && newRow != -1)
127 Object[] temp = new Object[3];
128 temp[0] = table.getValueAt(selectedRow, 0);
129 temp[1] = table.getValueAt(selectedRow, 1);
130 temp[2] = table.getValueAt(selectedRow, 2);
132 table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0);
133 table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1);
134 table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2);
136 table.setValueAt(temp[0], newRow, 0);
137 table.setValueAt(temp[1], newRow, 1);
138 table.setValueAt(temp[2], newRow, 2);
140 selectedRow = newRow;
144 table.setToolTipText(JvSwingUtils
145 .wrapTooltip(true, MessageManager.getString("label.feature_settings_click_drag")));
146 scrollPane.setViewportView(table);
148 dassourceBrowser = new DasSourceBrowser(this);
149 dasSettingsPane.add(dassourceBrowser, BorderLayout.CENTER);
151 if (af.getViewport().featuresDisplayed == null
152 || fr.renderOrder == null)
154 fr.findAllFeatures(true); // display everything!
158 final PropertyChangeListener change;
159 final FeatureSettings fs = this;
160 fr.addPropertyChangeListener(change = new PropertyChangeListener()
162 public void propertyChange(PropertyChangeEvent evt)
164 if (!fs.resettingTable && !fs.handlingUpdate)
166 fs.handlingUpdate = true;
167 fs.resetTable(null); // new groups may be added with new seuqence
168 // feature types only
169 fs.handlingUpdate = false;
175 frame = new JInternalFrame();
176 frame.setContentPane(this);
177 if (new jalview.util.Platform().isAMac())
179 Desktop.addInternalFrame(frame,
180 MessageManager.getString("label.sequence_feature_settings"),
185 Desktop.addInternalFrame(frame,
186 MessageManager.getString("label.sequence_feature_settings"),
190 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
192 public void internalFrameClosed(
193 javax.swing.event.InternalFrameEvent evt)
195 fr.removePropertyChangeListener(change);
196 dassourceBrowser.fs = null;
199 frame.setLayer(JLayeredPane.PALETTE_LAYER);
202 protected void popupSort(final int selectedRow, final String type,
203 final Object typeCol, final Hashtable minmax, int x, int y)
205 JPopupMenu men = new JPopupMenu(MessageManager.formatMessage(
206 "label.settings_for_param", new String[]
208 JMenuItem scr = new JMenuItem(
209 MessageManager.getString("label.sort_by_score"));
211 final FeatureSettings me = this;
212 scr.addActionListener(new ActionListener()
215 public void actionPerformed(ActionEvent e)
217 me.sortByScore(new String[]
222 JMenuItem dens = new JMenuItem(
223 MessageManager.getString("label.sort_by_density"));
224 dens.addActionListener(new ActionListener()
227 public void actionPerformed(ActionEvent e)
229 me.sortByDens(new String[]
237 final Object typeMinMax = minmax.get(type);
239 * final JCheckBoxMenuItem chb = new JCheckBoxMenuItem("Vary Height"); //
240 * this is broken at the moment and isn't that useful anyway!
241 * chb.setSelected(minmax.get(type) != null); chb.addActionListener(new
244 * public void actionPerformed(ActionEvent e) {
245 * chb.setState(chb.getState()); if (chb.getState()) { minmax.put(type,
246 * null); } else { minmax.put(type, typeMinMax); } }
252 if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null)
254 // if (table.getValueAt(row, column));
255 // graduated colourschemes for those where minmax exists for the
256 // positional features
257 final JCheckBoxMenuItem mxcol = new JCheckBoxMenuItem(
259 mxcol.setSelected(!(typeCol instanceof Color));
261 mxcol.addActionListener(new ActionListener()
263 JColorChooser colorChooser;
265 public void actionPerformed(ActionEvent e)
267 if (e.getSource() == mxcol)
269 if (typeCol instanceof Color)
271 FeatureColourChooser fc = new FeatureColourChooser(me.fr,
273 fc.addActionListener(this);
277 // bring up simple color chooser
278 colorChooser = new JColorChooser();
279 JDialog dialog = JColorChooser.createDialog(me,
280 "Select new Colour", true, // modal
281 colorChooser, this, // OK button handler
282 null); // no CANCEL button handler
283 colorChooser.setColor(((GraduatedColor) typeCol)
285 dialog.setVisible(true);
290 if (e.getSource() instanceof FeatureColourChooser)
292 FeatureColourChooser fc = (FeatureColourChooser) e
294 table.setValueAt(fc.getLastColour(), selectedRow, 1);
299 // probably the color chooser!
300 table.setValueAt(colorChooser.getColor(), selectedRow, 1);
302 me.updateFeatureRenderer(
303 ((FeatureTableModel) table.getModel()).getData(),
312 JMenuItem selCols = new JMenuItem(
313 MessageManager.getString("label.select_columns_containing"));
314 selCols.addActionListener(new ActionListener()
318 public void actionPerformed(ActionEvent arg0)
320 fr.ap.alignFrame.avc.markColumnsContainingFeatures(false, false,
324 JMenuItem clearCols = new JMenuItem(
325 MessageManager.getString("label.select_columns_not_containing"));
326 clearCols.addActionListener(new ActionListener()
330 public void actionPerformed(ActionEvent arg0)
332 fr.ap.alignFrame.avc.markColumnsContainingFeatures(true, false,
338 men.show(table, x, y);
342 * true when Feature Settings are updating from feature renderer
344 private boolean handlingUpdate = false;
347 * contains a float[3] for each feature type string. created by setTableData
349 Hashtable typeWidth = null;
351 synchronized public void setTableData()
353 if (fr.featureGroups == null)
355 fr.featureGroups = new Hashtable();
357 Vector allFeatures = new Vector();
358 Vector allGroups = new Vector();
359 SequenceFeature[] tmpfeatures;
361 for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
363 if (af.getViewport().getAlignment().getSequenceAt(i)
364 .getDatasetSequence().getSequenceFeatures() == null)
369 tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
370 .getDatasetSequence().getSequenceFeatures();
373 while (index < tmpfeatures.length)
375 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
381 if (tmpfeatures[index].getFeatureGroup() != null)
383 group = tmpfeatures[index].featureGroup;
384 if (!allGroups.contains(group))
386 allGroups.addElement(group);
389 checkGroupState(group);
394 if (!allFeatures.contains(tmpfeatures[index].getType()))
396 allFeatures.addElement(tmpfeatures[index].getType());
410 * @return true if group has been seen before and is already added to set.
412 private boolean checkGroupState(String group)
415 if (fr.featureGroups.containsKey(group))
417 visible = ((Boolean) fr.featureGroups.get(group)).booleanValue();
421 visible = true; // new group is always made visible
424 if (groupPanel == null)
426 groupPanel = new JPanel();
429 boolean alreadyAdded = false;
430 for (int g = 0; g < groupPanel.getComponentCount(); g++)
432 if (((JCheckBox) groupPanel.getComponent(g)).getText().equals(group))
435 ((JCheckBox) groupPanel.getComponent(g)).setSelected(visible);
446 fr.featureGroups.put(group, new Boolean(visible));
447 final String grp = group;
448 final JCheckBox check = new JCheckBox(group, visible);
449 check.setFont(new Font("Serif", Font.BOLD, 12));
450 check.addItemListener(new ItemListener()
452 public void itemStateChanged(ItemEvent evt)
454 fr.featureGroups.put(check.getText(),
455 new Boolean(check.isSelected()));
456 af.alignPanel.seqPanel.seqCanvas.repaint();
457 if (af.alignPanel.overviewPanel != null)
459 af.alignPanel.overviewPanel.updateOverviewImage();
462 resetTable(new String[]
466 groupPanel.add(check);
470 boolean resettingTable = false;
472 synchronized void resetTable(String[] groupChanged)
474 if (resettingTable == true)
478 resettingTable = true;
479 typeWidth = new Hashtable();
480 // TODO: change avWidth calculation to 'per-sequence' average and use long
482 float[] avWidth = null;
483 SequenceFeature[] tmpfeatures;
484 String group = null, type;
485 Vector visibleChecks = new Vector();
487 // Find out which features should be visible depending on which groups
488 // are selected / deselected
489 // and recompute average width ordering
490 for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
493 tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
494 .getDatasetSequence().getSequenceFeatures();
495 if (tmpfeatures == null)
501 while (index < tmpfeatures.length)
503 group = tmpfeatures[index].featureGroup;
505 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
511 if (group == null || fr.featureGroups.get(group) == null
512 || ((Boolean) fr.featureGroups.get(group)).booleanValue())
515 checkGroupState(group);
516 type = tmpfeatures[index].getType();
517 if (!visibleChecks.contains(type))
519 visibleChecks.addElement(type);
522 if (!typeWidth.containsKey(tmpfeatures[index].getType()))
524 typeWidth.put(tmpfeatures[index].getType(),
525 avWidth = new float[3]);
529 avWidth = (float[]) typeWidth.get(tmpfeatures[index].getType());
532 if (tmpfeatures[index].getBegin() > tmpfeatures[index].getEnd())
534 avWidth[1] += 1 + tmpfeatures[index].getBegin()
535 - tmpfeatures[index].getEnd();
539 avWidth[1] += 1 + tmpfeatures[index].getEnd()
540 - tmpfeatures[index].getBegin();
546 int fSize = visibleChecks.size();
547 Object[][] data = new Object[fSize][3];
550 if (fr.renderOrder != null)
553 fr.findAllFeatures(groupChanged != null); // prod to update
554 // colourschemes. but don't
556 // First add the checks in the previous render order,
557 // in case the window has been closed and reopened
558 for (int ro = fr.renderOrder.length - 1; ro > -1; ro--)
560 type = fr.renderOrder[ro];
562 if (!visibleChecks.contains(type))
567 data[dataIndex][0] = type;
568 data[dataIndex][1] = fr.getFeatureStyle(type);
569 data[dataIndex][2] = new Boolean(
570 af.getViewport().featuresDisplayed.containsKey(type));
572 visibleChecks.removeElement(type);
576 fSize = visibleChecks.size();
577 for (int i = 0; i < fSize; i++)
579 // These must be extra features belonging to the group
580 // which was just selected
581 type = visibleChecks.elementAt(i).toString();
582 data[dataIndex][0] = type;
584 data[dataIndex][1] = fr.getFeatureStyle(type);
585 if (data[dataIndex][1] == null)
587 // "Colour has been updated in another view!!"
588 fr.renderOrder = null;
592 data[dataIndex][2] = new Boolean(true);
596 if (originalData == null)
598 originalData = new Object[data.length][3];
599 for (int i = 0; i < data.length; i++)
601 System.arraycopy(data[i], 0, originalData[i], 0, 3);
605 table.setModel(new FeatureTableModel(data));
606 table.getColumnModel().getColumn(0).setPreferredWidth(200);
608 if (groupPanel != null)
610 groupPanel.setLayout(new GridLayout(fr.featureGroups.size() / 4 + 1,
613 groupPanel.validate();
614 bigPanel.add(groupPanel, BorderLayout.NORTH);
617 updateFeatureRenderer(data, groupChanged != null);
618 resettingTable = false;
622 * reorder data based on the featureRenderers global priority list.
626 private void ensureOrder(Object[][] data)
628 boolean sort = false;
629 float[] order = new float[data.length];
630 for (int i = 0; i < order.length; i++)
632 order[i] = fr.getOrder(data[i][0].toString());
634 order[i] = fr.setOrder(data[i][0].toString(), i / order.length);
636 sort = sort || order[i - 1] > order[i];
639 jalview.util.QuickSort.sort(order, data);
644 JalviewFileChooser chooser = new JalviewFileChooser(
645 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
646 { "fc" }, new String[]
647 { "Sequence Feature Colours" }, "Sequence Feature Colours");
648 chooser.setFileView(new jalview.io.JalviewFileView());
649 chooser.setDialogTitle(MessageManager.getString("label.load_feature_colours"));
650 chooser.setToolTipText(MessageManager.getString("action.load"));
652 int value = chooser.showOpenDialog(this);
654 if (value == JalviewFileChooser.APPROVE_OPTION)
656 File file = chooser.getSelectedFile();
660 InputStreamReader in = new InputStreamReader(new FileInputStream(
663 jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
664 jucs = (jalview.schemabinding.version2.JalviewUserColours) jucs
667 for (int i = jucs.getColourCount() - 1; i >= 0; i--)
670 jalview.schemabinding.version2.Colour newcol = jucs.getColour(i);
673 Color mincol = null, maxcol = null;
676 mincol = new Color(Integer.parseInt(newcol.getMinRGB(), 16));
677 maxcol = new Color(Integer.parseInt(newcol.getRGB(), 16));
679 } catch (Exception e)
681 Cache.log.warn("Couldn't parse out graduated feature color.",
684 GraduatedColor gcol = new GraduatedColor(mincol, maxcol,
685 newcol.getMin(), newcol.getMax());
686 if (newcol.hasAutoScale())
688 gcol.setAutoScaled(newcol.getAutoScale());
690 if (newcol.hasColourByLabel())
692 gcol.setColourByLabel(newcol.getColourByLabel());
694 if (newcol.hasThreshold())
696 gcol.setThresh(newcol.getThreshold());
697 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD); // default
699 if (newcol.getThreshType().length() > 0)
701 String ttyp = newcol.getThreshType();
702 if (ttyp.equalsIgnoreCase("NONE"))
704 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD);
706 if (ttyp.equalsIgnoreCase("ABOVE"))
708 gcol.setThreshType(AnnotationColourGradient.ABOVE_THRESHOLD);
710 if (ttyp.equalsIgnoreCase("BELOW"))
712 gcol.setThreshType(AnnotationColourGradient.BELOW_THRESHOLD);
715 fr.setColour(name = newcol.getName(), gcol);
719 fr.setColour(name = jucs.getColour(i).getName(), new Color(
720 Integer.parseInt(jucs.getColour(i).getRGB(), 16)));
722 fr.setOrder(name, (i == 0) ? 0 : i / jucs.getColourCount());
727 Object[][] data = ((FeatureTableModel) table.getModel())
730 updateFeatureRenderer(data, false);
733 } catch (Exception ex)
735 System.out.println("Error loading User Colour File\n" + ex);
742 JalviewFileChooser chooser = new JalviewFileChooser(
743 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
744 { "fc" }, new String[]
745 { "Sequence Feature Colours" }, "Sequence Feature Colours");
746 chooser.setFileView(new jalview.io.JalviewFileView());
747 chooser.setDialogTitle(MessageManager.getString("label.save_feature_colours"));
748 chooser.setToolTipText(MessageManager.getString("action.save"));
750 int value = chooser.showSaveDialog(this);
752 if (value == JalviewFileChooser.APPROVE_OPTION)
754 String choice = chooser.getSelectedFile().getPath();
755 jalview.schemabinding.version2.JalviewUserColours ucs = new jalview.schemabinding.version2.JalviewUserColours();
756 ucs.setSchemeName("Sequence Features");
759 PrintWriter out = new PrintWriter(new OutputStreamWriter(
760 new FileOutputStream(choice), "UTF-8"));
762 Iterator e = fr.featureColours.keySet().iterator();
763 float[] sortOrder = new float[fr.featureColours.size()];
764 String[] sortTypes = new String[fr.featureColours.size()];
768 sortTypes[i] = e.next().toString();
769 sortOrder[i] = fr.getOrder(sortTypes[i]);
772 jalview.util.QuickSort.sort(sortOrder, sortTypes);
776 for (i = 0; i < sortTypes.length; i++)
778 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
779 col.setName(sortTypes[i]);
780 col.setRGB(jalview.util.Format.getHexString(fr.getColour(col
782 fcol = fr.getFeatureStyle(sortTypes[i]);
783 if (fcol instanceof GraduatedColor)
785 gcol = (GraduatedColor) fcol;
786 col.setMin(gcol.getMin());
787 col.setMax(gcol.getMax());
788 col.setMinRGB(jalview.util.Format.getHexString(gcol
790 col.setAutoScale(gcol.isAutoScale());
791 col.setThreshold(gcol.getThresh());
792 col.setColourByLabel(gcol.isColourByLabel());
793 switch (gcol.getThreshType())
795 case AnnotationColourGradient.NO_THRESHOLD:
796 col.setThreshType("NONE");
798 case AnnotationColourGradient.ABOVE_THRESHOLD:
799 col.setThreshType("ABOVE");
801 case AnnotationColourGradient.BELOW_THRESHOLD:
802 col.setThreshType("BELOW");
810 } catch (Exception ex)
812 ex.printStackTrace();
817 public void invertSelection()
819 for (int i = 0; i < table.getRowCount(); i++)
821 Boolean value = (Boolean) table.getValueAt(i, 2);
823 table.setValueAt(new Boolean(!value.booleanValue()), i, 2);
827 public void orderByAvWidth()
829 if (table == null || table.getModel() == null)
831 Object[][] data = ((FeatureTableModel) table.getModel()).getData();
832 float[] width = new float[data.length];
836 for (int i = 0; i < data.length; i++)
838 awidth = (float[]) typeWidth.get(data[i][0]);
841 width[i] = awidth[1] / awidth[0];// *awidth[0]*awidth[2]; - better
842 // weight - but have to make per
843 // sequence, too (awidth[2])
844 // if (width[i]==1) // hack to distinguish single width sequences.
854 boolean sort = false;
855 for (int i = 0; i < width.length; i++)
857 // awidth = (float[]) typeWidth.get(data[i][0]);
860 width[i] = fr.getOrder(data[i][0].toString());
863 width[i] = fr.setOrder(data[i][0].toString(), i / data.length);
868 width[i] /= max; // normalize
869 fr.setOrder(data[i][0].toString(), width[i]); // store for later
872 sort = sort || width[i - 1] > width[i];
875 jalview.util.QuickSort.sort(width, data);
876 // update global priority order
878 updateFeatureRenderer(data, false);
886 frame.setClosed(true);
887 } catch (Exception exe)
893 public void updateFeatureRenderer(Object[][] data)
895 updateFeatureRenderer(data, true);
898 private void updateFeatureRenderer(Object[][] data, boolean visibleNew)
900 fr.setFeaturePriority(data, visibleNew);
901 af.alignPanel.paintAlignment(true);
904 int selectedRow = -1;
906 JTabbedPane tabbedPane = new JTabbedPane();
908 BorderLayout borderLayout1 = new BorderLayout();
910 BorderLayout borderLayout2 = new BorderLayout();
912 BorderLayout borderLayout3 = new BorderLayout();
914 JPanel bigPanel = new JPanel();
916 BorderLayout borderLayout4 = new BorderLayout();
918 JButton invert = new JButton();
920 JPanel buttonPanel = new JPanel();
922 JButton cancel = new JButton();
924 JButton ok = new JButton();
926 JButton loadColours = new JButton();
928 JButton saveColours = new JButton();
930 JPanel dasButtonPanel = new JPanel();
932 JButton fetchDAS = new JButton();
934 JButton saveDAS = new JButton();
936 JButton cancelDAS = new JButton();
938 JButton optimizeOrder = new JButton();
940 JButton sortByScore = new JButton();
942 JButton sortByDens = new JButton();
944 JPanel transbuttons = new JPanel(new GridLayout(4, 1));
946 private void jbInit() throws Exception
948 this.setLayout(borderLayout1);
949 settingsPane.setLayout(borderLayout2);
950 dasSettingsPane.setLayout(borderLayout3);
951 bigPanel.setLayout(borderLayout4);
952 invert.setFont(JvSwingUtils.getLabelFont());
953 invert.setText(MessageManager.getString("label.invert_selection"));
954 invert.addActionListener(new ActionListener()
956 public void actionPerformed(ActionEvent e)
961 optimizeOrder.setFont(JvSwingUtils.getLabelFont());
962 optimizeOrder.setText(MessageManager.getString("label.optimise_order"));
963 optimizeOrder.addActionListener(new ActionListener()
965 public void actionPerformed(ActionEvent e)
970 sortByScore.setFont(JvSwingUtils.getLabelFont());
972 .setText(MessageManager.getString("label.seq_sort_by_score"));
973 sortByScore.addActionListener(new ActionListener()
975 public void actionPerformed(ActionEvent e)
980 sortByDens.setFont(JvSwingUtils.getLabelFont());
981 sortByDens.setText(MessageManager
982 .getString("label.sequence_sort_by_density"));
983 sortByDens.addActionListener(new ActionListener()
985 public void actionPerformed(ActionEvent e)
990 cancel.setFont(JvSwingUtils.getLabelFont());
991 cancel.setText(MessageManager.getString("action.cancel"));
992 cancel.addActionListener(new ActionListener()
994 public void actionPerformed(ActionEvent e)
996 updateFeatureRenderer(originalData);
1000 ok.setFont(JvSwingUtils.getLabelFont());
1001 ok.setText(MessageManager.getString("action.ok"));
1002 ok.addActionListener(new ActionListener()
1004 public void actionPerformed(ActionEvent e)
1009 loadColours.setFont(JvSwingUtils.getLabelFont());
1010 loadColours.setText(MessageManager.getString("label.load_colours"));
1011 loadColours.addActionListener(new ActionListener()
1013 public void actionPerformed(ActionEvent e)
1018 saveColours.setFont(JvSwingUtils.getLabelFont());
1019 saveColours.setText(MessageManager.getString("label.save_colours"));
1020 saveColours.addActionListener(new ActionListener()
1022 public void actionPerformed(ActionEvent e)
1027 transparency.addChangeListener(new ChangeListener()
1029 public void stateChanged(ChangeEvent evt)
1031 fr.setTransparency((float) (100 - transparency.getValue()) / 100f);
1032 af.alignPanel.paintAlignment(true);
1036 transparency.setMaximum(70);
1037 fetchDAS.setText(MessageManager.getString("label.fetch_das_features"));
1038 fetchDAS.addActionListener(new ActionListener()
1040 public void actionPerformed(ActionEvent e)
1042 fetchDAS_actionPerformed(e);
1045 saveDAS.setText(MessageManager.getString("action.save_as_default"));
1046 saveDAS.addActionListener(new ActionListener()
1048 public void actionPerformed(ActionEvent e)
1050 saveDAS_actionPerformed(e);
1053 dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
1054 dasSettingsPane.setBorder(null);
1055 cancelDAS.setEnabled(false);
1056 cancelDAS.setText(MessageManager.getString("action.cancel_fetch"));
1057 cancelDAS.addActionListener(new ActionListener()
1059 public void actionPerformed(ActionEvent e)
1061 cancelDAS_actionPerformed(e);
1064 this.add(tabbedPane, java.awt.BorderLayout.CENTER);
1065 tabbedPane.addTab(MessageManager.getString("label.feature_settings"), settingsPane);
1066 tabbedPane.addTab(MessageManager.getString("label.das_settings"), dasSettingsPane);
1067 bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
1068 transbuttons.add(optimizeOrder);
1069 transbuttons.add(invert);
1070 transbuttons.add(sortByScore);
1071 transbuttons.add(sortByDens);
1072 transPanel.add(transparency);
1073 transPanel.add(transbuttons);
1074 buttonPanel.add(ok);
1075 buttonPanel.add(cancel);
1076 buttonPanel.add(loadColours);
1077 buttonPanel.add(saveColours);
1078 bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
1079 dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
1080 dasButtonPanel.add(fetchDAS);
1081 dasButtonPanel.add(cancelDAS);
1082 dasButtonPanel.add(saveDAS);
1083 settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);
1084 settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
1087 protected void sortByDens(String[] typ)
1089 sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY);
1092 protected void sortBy(String[] typ, String methodText, final String method)
1096 typ = getDisplayedFeatureTypes();
1098 String gps[] = null;
1099 gps = getDisplayedFeatureGroups();
1102 ArrayList types = new ArrayList();
1103 for (int i = 0; i < typ.length; i++)
1109 typ = new String[types.size()];
1115 ArrayList grps = new ArrayList();
1117 for (int i = 0; i < gps.length; i++)
1124 gps = new String[grps.size()];
1127 AlignmentPanel alignPanel = af.alignPanel;
1128 AlignmentI al = alignPanel.av.getAlignment();
1131 SequenceGroup sg = alignPanel.av.getSelectionGroup();
1134 start = sg.getStartRes();
1135 stop = sg.getEndRes();
1140 stop = al.getWidth();
1142 SequenceI[] oldOrder = al.getSequencesArray();
1143 AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
1144 af.addHistoryItem(new OrderCommand(methodText, oldOrder, alignPanel.av
1146 alignPanel.paintAlignment(true);
1150 protected void sortByScore(String[] typ)
1152 sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE);
1155 private String[] getDisplayedFeatureTypes()
1157 String[] typ = null;
1160 synchronized (fr.renderOrder)
1162 typ = new String[fr.renderOrder.length];
1163 System.arraycopy(fr.renderOrder, 0, typ, 0, typ.length);
1164 for (int i = 0; i < typ.length; i++)
1166 if (af.viewport.featuresDisplayed.get(typ[i]) == null)
1176 private String[] getDisplayedFeatureGroups()
1178 String[] gps = null;
1179 ArrayList<String> _gps = new ArrayList<String>();
1183 if (fr.featureGroups != null)
1185 Iterator en = fr.featureGroups.keySet().iterator();
1187 boolean valid = false;
1188 while (en.hasNext())
1190 String gp = (String) en.next();
1191 Boolean on = (Boolean) fr.featureGroups.get(gp);
1192 if (on != null && on.booleanValue())
1204 gps = new String[_gps.size()];
1212 public void fetchDAS_actionPerformed(ActionEvent e)
1214 fetchDAS.setEnabled(false);
1215 cancelDAS.setEnabled(true);
1216 dassourceBrowser.setGuiEnabled(false);
1217 Vector selectedSources = dassourceBrowser.getSelectedSources();
1218 doDasFeatureFetch(selectedSources, true, true);
1222 * get the features from selectedSources for all or the current selection
1224 * @param selectedSources
1225 * @param checkDbRefs
1226 * @param promptFetchDbRefs
1228 private void doDasFeatureFetch(List<jalviewSourceI> selectedSources,
1229 boolean checkDbRefs, boolean promptFetchDbRefs)
1231 SequenceI[] dataset, seqs;
1233 AlignViewport vp = af.getViewport();
1234 if (vp.getSelectionGroup() != null
1235 && vp.getSelectionGroup().getSize() > 0)
1237 iSize = vp.getSelectionGroup().getSize();
1238 dataset = new SequenceI[iSize];
1239 seqs = vp.getSelectionGroup().getSequencesInOrder(vp.getAlignment());
1243 iSize = vp.getAlignment().getHeight();
1244 seqs = vp.getAlignment().getSequencesArray();
1247 dataset = new SequenceI[iSize];
1248 for (int i = 0; i < iSize; i++)
1250 dataset[i] = seqs[i].getDatasetSequence();
1253 cancelDAS.setEnabled(true);
1254 dasFeatureFetcher = new jalview.ws.DasSequenceFeatureFetcher(dataset,
1255 this, selectedSources, checkDbRefs, promptFetchDbRefs);
1256 af.getViewport().setShowSequenceFeatures(true);
1257 af.showSeqFeatures.setSelected(true);
1261 * blocking call to initialise the das source browser
1263 public void initDasSources()
1265 dassourceBrowser.initDasSources();
1269 * examine the current list of das sources and return any matching the given
1270 * nicknames in sources
1273 * Vector of Strings to resolve to DAS source nicknames.
1274 * @return sources that are present in source list.
1276 public List<jalviewSourceI> resolveSourceNicknames(Vector sources)
1278 return dassourceBrowser.sourceRegistry.resolveSourceNicknames(sources);
1282 * get currently selected das sources. ensure you have called initDasSources
1283 * before calling this.
1285 * @return vector of selected das source nicknames
1287 public Vector getSelectedSources()
1289 return dassourceBrowser.getSelectedSources();
1293 * properly initialise DAS fetcher and then initiate a new thread to fetch
1294 * features from the named sources (rather than any turned on by default)
1298 * if true then runs in same thread, otherwise passes to the Swing
1301 public void fetchDasFeatures(Vector sources, boolean block)
1304 List<jalviewSourceI> resolved = dassourceBrowser.sourceRegistry
1305 .resolveSourceNicknames(sources);
1306 if (resolved.size() == 0)
1308 resolved = dassourceBrowser.getSelectedSources();
1310 if (resolved.size() > 0)
1312 final List<jalviewSourceI> dassources = resolved;
1313 fetchDAS.setEnabled(false);
1314 // cancelDAS.setEnabled(true); doDasFetch does this.
1315 Runnable fetcher = new Runnable()
1320 doDasFeatureFetch(dassources, true, false);
1330 SwingUtilities.invokeLater(fetcher);
1335 public void saveDAS_actionPerformed(ActionEvent e)
1338 .saveProperties(jalview.bin.Cache.applicationProperties);
1341 public void complete()
1343 fetchDAS.setEnabled(true);
1344 cancelDAS.setEnabled(false);
1345 dassourceBrowser.setGuiEnabled(true);
1349 public void cancelDAS_actionPerformed(ActionEvent e)
1351 if (dasFeatureFetcher != null)
1353 dasFeatureFetcher.cancel();
1358 public void noDasSourceActive()
1362 .showInternalConfirmDialog(
1365 .getString("label.no_das_sources_selected_warn"),
1367 .getString("label.no_das_sources_selected_title"),
1368 JOptionPane.DEFAULT_OPTION,
1369 JOptionPane.INFORMATION_MESSAGE);
1372 // ///////////////////////////////////////////////////////////////////////
1373 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
1374 // ///////////////////////////////////////////////////////////////////////
1375 class FeatureTableModel extends AbstractTableModel
1377 FeatureTableModel(Object[][] data)
1382 private String[] columnNames =
1383 { MessageManager.getString("label.feature_type"), MessageManager.getString("action.colour"), MessageManager.getString("label.display") };
1385 private Object[][] data;
1387 public Object[][] getData()
1392 public void setData(Object[][] data)
1397 public int getColumnCount()
1399 return columnNames.length;
1402 public Object[] getRow(int row)
1407 public int getRowCount()
1412 public String getColumnName(int col)
1414 return columnNames[col];
1417 public Object getValueAt(int row, int col)
1419 return data[row][col];
1422 public Class getColumnClass(int c)
1424 return getValueAt(0, c).getClass();
1427 public boolean isCellEditable(int row, int col)
1429 return col == 0 ? false : true;
1432 public void setValueAt(Object value, int row, int col)
1434 data[row][col] = value;
1435 fireTableCellUpdated(row, col);
1436 updateFeatureRenderer(data);
1441 class ColorRenderer extends JLabel implements TableCellRenderer
1443 javax.swing.border.Border unselectedBorder = null;
1445 javax.swing.border.Border selectedBorder = null;
1447 final String baseTT = "Click to edit, right/apple click for menu.";
1449 public ColorRenderer()
1451 setOpaque(true); // MUST do this for background to show up.
1452 setHorizontalTextPosition(SwingConstants.CENTER);
1453 setVerticalTextPosition(SwingConstants.CENTER);
1456 public Component getTableCellRendererComponent(JTable table,
1457 Object color, boolean isSelected, boolean hasFocus, int row,
1460 // JLabel comp = new JLabel();
1464 // setBounds(getBounds());
1466 setToolTipText(baseTT);
1467 setBackground(table.getBackground());
1468 if (color instanceof GraduatedColor)
1470 Rectangle cr = table.getCellRect(row, column, false);
1471 FeatureSettings.renderGraduatedColor(this, (GraduatedColor) color,
1472 (int) cr.getWidth(), (int) cr.getHeight());
1479 newColor = (Color) color;
1481 setBackground(newColor);
1482 // comp.setToolTipText("RGB value: " + newColor.getRed() + ", "
1483 // + newColor.getGreen() + ", " + newColor.getBlue());
1487 if (selectedBorder == null)
1489 selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1490 table.getSelectionBackground());
1493 setBorder(selectedBorder);
1497 if (unselectedBorder == null)
1499 unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1500 table.getBackground());
1503 setBorder(unselectedBorder);
1511 * update comp using rendering settings from gcol
1516 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol)
1518 int w = comp.getWidth(), h = comp.getHeight();
1521 w = (int) comp.getPreferredSize().getWidth();
1522 h = (int) comp.getPreferredSize().getHeight();
1529 renderGraduatedColor(comp, gcol, w, h);
1532 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol,
1535 boolean thr = false;
1538 if (gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD)
1542 tt += "Thresholded (Above " + gcol.getThresh() + ") ";
1544 if (gcol.getThreshType() == AnnotationColourGradient.BELOW_THRESHOLD)
1548 tt += "Thresholded (Below " + gcol.getThresh() + ") ";
1550 if (gcol.isColourByLabel())
1552 tt = "Coloured by label text. " + tt;
1562 Color newColor = gcol.getMaxColor();
1563 comp.setBackground(newColor);
1564 // System.err.println("Width is " + w / 2);
1565 Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w, h, thr);
1566 comp.setIcon(ficon);
1567 // tt+="RGB value: Max (" + newColor.getRed() + ", "
1568 // + newColor.getGreen() + ", " + newColor.getBlue()
1569 // + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen()
1570 // + ", " + minCol.getBlue() + ")");
1572 comp.setHorizontalAlignment(SwingConstants.CENTER);
1574 if (tt.length() > 0)
1576 if (comp.getToolTipText() == null)
1578 comp.setToolTipText(tt);
1582 comp.setToolTipText(tt + " " + comp.getToolTipText());
1588 class FeatureIcon implements Icon
1590 GraduatedColor gcol;
1594 boolean midspace = false;
1596 int width = 50, height = 20;
1598 int s1, e1; // start and end of midpoint band for thresholded symbol
1600 Color mpcolour = Color.white;
1602 FeatureIcon(GraduatedColor gfc, Color bg, int w, int h, boolean mspace)
1621 public int getIconWidth()
1626 public int getIconHeight()
1631 public void paintIcon(Component c, Graphics g, int x, int y)
1634 if (gcol.isColourByLabel())
1637 g.fillRect(0, 0, width, height);
1638 // need an icon here.
1639 g.setColor(gcol.getMaxColor());
1641 g.setFont(new Font("Verdana", Font.PLAIN, 9));
1643 // g.setFont(g.getFont().deriveFont(
1644 // AffineTransform.getScaleInstance(
1645 // width/g.getFontMetrics().stringWidth("Label"),
1646 // height/g.getFontMetrics().getHeight())));
1648 g.drawString(MessageManager.getString("label.label"), 0, 0);
1653 Color minCol = gcol.getMinColor();
1655 g.fillRect(0, 0, s1, height);
1658 g.setColor(Color.white);
1659 g.fillRect(s1, 0, e1 - s1, height);
1661 g.setColor(gcol.getMaxColor());
1662 g.fillRect(0, e1, width - e1, height);
1667 class ColorEditor extends AbstractCellEditor implements TableCellEditor,
1672 GraduatedColor currentGColor;
1674 FeatureColourChooser chooser;
1682 JColorChooser colorChooser;
1686 protected static final String EDIT = "edit";
1688 int selectedRow = 0;
1690 public ColorEditor(FeatureSettings me)
1693 // Set up the editor (from the table's point of view),
1694 // which is a button.
1695 // This button brings up the color chooser dialog,
1696 // which is the editor from the user's point of view.
1697 button = new JButton();
1698 button.setActionCommand(EDIT);
1699 button.addActionListener(this);
1700 button.setBorderPainted(false);
1701 // Set up the dialog that the button brings up.
1702 colorChooser = new JColorChooser();
1703 dialog = JColorChooser.createDialog(button, "Select new Colour", true, // modal
1704 colorChooser, this, // OK button handler
1705 null); // no CANCEL button handler
1709 * Handles events from the editor button and from the dialog's OK button.
1711 public void actionPerformed(ActionEvent e)
1714 if (EDIT.equals(e.getActionCommand()))
1716 // The user has clicked the cell, so
1717 // bring up the dialog.
1718 if (currentColor != null)
1720 // bring up simple color chooser
1721 button.setBackground(currentColor);
1722 colorChooser.setColor(currentColor);
1723 dialog.setVisible(true);
1727 // bring up graduated chooser.
1728 chooser = new FeatureColourChooser(me.fr, type);
1729 chooser.setRequestFocusEnabled(true);
1730 chooser.requestFocus();
1731 chooser.addActionListener(this);
1733 // Make the renderer reappear.
1734 fireEditingStopped();
1738 { // User pressed dialog's "OK" button.
1739 if (currentColor != null)
1741 currentColor = colorChooser.getColor();
1745 // class cast exceptions may be raised if the chooser created on a
1746 // non-graduated color
1747 currentGColor = (GraduatedColor) chooser.getLastColour();
1749 me.table.setValueAt(getCellEditorValue(), selectedRow, 1);
1750 fireEditingStopped();
1751 me.table.validate();
1755 // Implement the one CellEditor method that AbstractCellEditor doesn't.
1756 public Object getCellEditorValue()
1758 if (currentColor == null)
1760 return currentGColor;
1762 return currentColor;
1765 // Implement the one method defined by TableCellEditor.
1766 public Component getTableCellEditorComponent(JTable table, Object value,
1767 boolean isSelected, int row, int column)
1769 currentGColor = null;
1770 currentColor = null;
1771 this.selectedRow = row;
1772 type = me.table.getValueAt(row, 0).toString();
1773 button.setOpaque(true);
1774 button.setBackground(me.getBackground());
1775 if (value instanceof GraduatedColor)
1777 currentGColor = (GraduatedColor) value;
1778 JLabel btn = new JLabel();
1779 btn.setSize(button.getSize());
1780 FeatureSettings.renderGraduatedColor(btn, currentGColor);
1781 button.setBackground(btn.getBackground());
1782 button.setIcon(btn.getIcon());
1783 button.setText(btn.getText());
1788 button.setIcon(null);
1789 currentColor = (Color) value;
1790 button.setBackground(currentColor);