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(), evt.isMetaDown(),
114 (String) table.getValueAt(selectedRow, 0));
119 table.addMouseMotionListener(new MouseMotionAdapter()
121 public void mouseDragged(MouseEvent evt)
123 int newRow = table.rowAtPoint(evt.getPoint());
124 if (newRow != selectedRow && selectedRow != -1 && newRow != -1)
126 Object[] temp = new Object[3];
127 temp[0] = table.getValueAt(selectedRow, 0);
128 temp[1] = table.getValueAt(selectedRow, 1);
129 temp[2] = table.getValueAt(selectedRow, 2);
131 table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0);
132 table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1);
133 table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2);
135 table.setValueAt(temp[0], newRow, 0);
136 table.setValueAt(temp[1], newRow, 1);
137 table.setValueAt(temp[2], newRow, 2);
139 selectedRow = newRow;
143 table.setToolTipText("<html>"+JvSwingUtils
144 .wrapTooltip("Click/drag feature types up or down to change render order.<br/>Double click to select columns containing feature in alignment/current selection<br/>Pressing Alt will select columns outside features rather than inside<br/>Pressing Shift to modify current selection (rather than clear current selection)<br/>Press CTRL or Command/Meta to toggle columns in/outside features<br/>")+"</html>");
145 scrollPane.setViewportView(table);
147 dassourceBrowser = new DasSourceBrowser(this);
148 dasSettingsPane.add(dassourceBrowser, BorderLayout.CENTER);
150 if (af.getViewport().featuresDisplayed == null
151 || fr.renderOrder == null)
153 fr.findAllFeatures(true); // display everything!
157 final PropertyChangeListener change;
158 final FeatureSettings fs = this;
159 fr.addPropertyChangeListener(change = new PropertyChangeListener()
161 public void propertyChange(PropertyChangeEvent evt)
163 if (!fs.resettingTable && !fs.handlingUpdate)
165 fs.handlingUpdate = true;
166 fs.resetTable(null); // new groups may be added with new seuqence
167 // feature types only
168 fs.handlingUpdate = false;
174 frame = new JInternalFrame();
175 frame.setContentPane(this);
176 if (new jalview.util.Platform().isAMac())
178 Desktop.addInternalFrame(frame, MessageManager.getString("label.sequence_feature_settings"), 475, 480);
182 Desktop.addInternalFrame(frame, MessageManager.getString("label.sequence_feature_settings"), 400, 450);
185 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
187 public void internalFrameClosed(
188 javax.swing.event.InternalFrameEvent evt)
190 fr.removePropertyChangeListener(change);
191 dassourceBrowser.fs = null;
194 frame.setLayer(JLayeredPane.PALETTE_LAYER);
197 protected void popupSort(final int selectedRow, final String type,
198 final Object typeCol, final Hashtable minmax, int x, int y)
200 JPopupMenu men = new JPopupMenu(MessageManager.formatMessage("label.settings_for_param", new String[]{type}));
201 JMenuItem scr = new JMenuItem(MessageManager.getString("label.sort_by_score"));
203 final FeatureSettings me = this;
204 scr.addActionListener(new ActionListener()
207 public void actionPerformed(ActionEvent e)
209 me.sortByScore(new String[]
214 JMenuItem dens = new JMenuItem(MessageManager.getString("label.sort_by_density"));
215 dens.addActionListener(new ActionListener()
218 public void actionPerformed(ActionEvent e)
220 me.sortByDens(new String[]
228 final Object typeMinMax = minmax.get(type);
230 * final JCheckBoxMenuItem chb = new JCheckBoxMenuItem("Vary Height"); //
231 * this is broken at the moment and isn't that useful anyway!
232 * chb.setSelected(minmax.get(type) != null); chb.addActionListener(new
235 * public void actionPerformed(ActionEvent e) {
236 * chb.setState(chb.getState()); if (chb.getState()) { minmax.put(type,
237 * null); } else { minmax.put(type, typeMinMax); } }
243 if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null)
245 // if (table.getValueAt(row, column));
246 // graduated colourschemes for those where minmax exists for the
247 // positional features
248 final JCheckBoxMenuItem mxcol = new JCheckBoxMenuItem(
250 mxcol.setSelected(!(typeCol instanceof Color));
252 mxcol.addActionListener(new ActionListener()
254 JColorChooser colorChooser;
256 public void actionPerformed(ActionEvent e)
258 if (e.getSource() == mxcol)
260 if (typeCol instanceof Color)
262 FeatureColourChooser fc = new FeatureColourChooser(me.fr,
264 fc.addActionListener(this);
268 // bring up simple color chooser
269 colorChooser = new JColorChooser();
270 JDialog dialog = JColorChooser.createDialog(me,
271 "Select new Colour", true, // modal
272 colorChooser, this, // OK button handler
273 null); // no CANCEL button handler
274 colorChooser.setColor(((GraduatedColor) typeCol)
276 dialog.setVisible(true);
281 if (e.getSource() instanceof FeatureColourChooser)
283 FeatureColourChooser fc = (FeatureColourChooser) e
285 table.setValueAt(fc.getLastColour(), selectedRow, 1);
290 // probably the color chooser!
291 table.setValueAt(colorChooser.getColor(), selectedRow, 1);
293 me.updateFeatureRenderer(
294 ((FeatureTableModel) table.getModel()).getData(),
303 JMenuItem selCols = new JMenuItem(MessageManager.getString("label.select_columns_containing"));
304 selCols.addActionListener(new ActionListener()
308 public void actionPerformed(ActionEvent arg0)
310 fr.ap.alignFrame.avc.markColumnsContainingFeatures(false, false, false, type);
313 JMenuItem clearCols = new JMenuItem(MessageManager.getString("label.select_columns_not_containing"));
314 clearCols.addActionListener(new ActionListener()
318 public void actionPerformed(ActionEvent arg0)
320 fr.ap.alignFrame.avc.markColumnsContainingFeatures(true, false, false, type);
325 men.show(table, x, y);
329 * true when Feature Settings are updating from feature renderer
331 private boolean handlingUpdate = false;
334 * contains a float[3] for each feature type string. created by setTableData
336 Hashtable typeWidth = null;
338 synchronized public void setTableData()
340 if (fr.featureGroups == null)
342 fr.featureGroups = new Hashtable();
344 Vector allFeatures = new Vector();
345 Vector allGroups = new Vector();
346 SequenceFeature[] tmpfeatures;
348 for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
350 if (af.getViewport().getAlignment().getSequenceAt(i)
351 .getDatasetSequence().getSequenceFeatures() == null)
356 tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
357 .getDatasetSequence().getSequenceFeatures();
360 while (index < tmpfeatures.length)
362 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
368 if (tmpfeatures[index].getFeatureGroup() != null)
370 group = tmpfeatures[index].featureGroup;
371 if (!allGroups.contains(group))
373 allGroups.addElement(group);
376 checkGroupState(group);
381 if (!allFeatures.contains(tmpfeatures[index].getType()))
383 allFeatures.addElement(tmpfeatures[index].getType());
397 * @return true if group has been seen before and is already added to set.
399 private boolean checkGroupState(String group)
402 if (fr.featureGroups.containsKey(group))
404 visible = ((Boolean) fr.featureGroups.get(group)).booleanValue();
408 visible = true; // new group is always made visible
411 if (groupPanel == null)
413 groupPanel = new JPanel();
416 boolean alreadyAdded = false;
417 for (int g = 0; g < groupPanel.getComponentCount(); g++)
419 if (((JCheckBox) groupPanel.getComponent(g)).getText().equals(group))
422 ((JCheckBox) groupPanel.getComponent(g)).setSelected(visible);
433 fr.featureGroups.put(group, new Boolean(visible));
434 final String grp = group;
435 final JCheckBox check = new JCheckBox(group, visible);
436 check.setFont(new Font("Serif", Font.BOLD, 12));
437 check.addItemListener(new ItemListener()
439 public void itemStateChanged(ItemEvent evt)
441 fr.featureGroups.put(check.getText(),
442 new Boolean(check.isSelected()));
443 af.alignPanel.seqPanel.seqCanvas.repaint();
444 if (af.alignPanel.overviewPanel != null)
446 af.alignPanel.overviewPanel.updateOverviewImage();
449 resetTable(new String[]
453 groupPanel.add(check);
457 boolean resettingTable = false;
459 synchronized void resetTable(String[] groupChanged)
461 if (resettingTable == true)
465 resettingTable = true;
466 typeWidth = new Hashtable();
467 // TODO: change avWidth calculation to 'per-sequence' average and use long
469 float[] avWidth = null;
470 SequenceFeature[] tmpfeatures;
471 String group = null, type;
472 Vector visibleChecks = new Vector();
474 // Find out which features should be visible depending on which groups
475 // are selected / deselected
476 // and recompute average width ordering
477 for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
480 tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
481 .getDatasetSequence().getSequenceFeatures();
482 if (tmpfeatures == null)
488 while (index < tmpfeatures.length)
490 group = tmpfeatures[index].featureGroup;
492 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
498 if (group == null || fr.featureGroups.get(group) == null
499 || ((Boolean) fr.featureGroups.get(group)).booleanValue())
502 checkGroupState(group);
503 type = tmpfeatures[index].getType();
504 if (!visibleChecks.contains(type))
506 visibleChecks.addElement(type);
509 if (!typeWidth.containsKey(tmpfeatures[index].getType()))
511 typeWidth.put(tmpfeatures[index].getType(),
512 avWidth = new float[3]);
516 avWidth = (float[]) typeWidth.get(tmpfeatures[index].getType());
519 if (tmpfeatures[index].getBegin() > tmpfeatures[index].getEnd())
521 avWidth[1] += 1 + tmpfeatures[index].getBegin()
522 - tmpfeatures[index].getEnd();
526 avWidth[1] += 1 + tmpfeatures[index].getEnd()
527 - tmpfeatures[index].getBegin();
533 int fSize = visibleChecks.size();
534 Object[][] data = new Object[fSize][3];
537 if (fr.renderOrder != null)
540 fr.findAllFeatures(groupChanged != null); // prod to update
541 // colourschemes. but don't
543 // First add the checks in the previous render order,
544 // in case the window has been closed and reopened
545 for (int ro = fr.renderOrder.length - 1; ro > -1; ro--)
547 type = fr.renderOrder[ro];
549 if (!visibleChecks.contains(type))
554 data[dataIndex][0] = type;
555 data[dataIndex][1] = fr.getFeatureStyle(type);
556 data[dataIndex][2] = new Boolean(
557 af.getViewport().featuresDisplayed.containsKey(type));
559 visibleChecks.removeElement(type);
563 fSize = visibleChecks.size();
564 for (int i = 0; i < fSize; i++)
566 // These must be extra features belonging to the group
567 // which was just selected
568 type = visibleChecks.elementAt(i).toString();
569 data[dataIndex][0] = type;
571 data[dataIndex][1] = fr.getFeatureStyle(type);
572 if (data[dataIndex][1] == null)
574 // "Colour has been updated in another view!!"
575 fr.renderOrder = null;
579 data[dataIndex][2] = new Boolean(true);
583 if (originalData == null)
585 originalData = new Object[data.length][3];
586 for (int i = 0; i < data.length; i++)
588 System.arraycopy(data[i], 0, originalData[i], 0, 3);
592 table.setModel(new FeatureTableModel(data));
593 table.getColumnModel().getColumn(0).setPreferredWidth(200);
595 if (groupPanel != null)
597 groupPanel.setLayout(new GridLayout(fr.featureGroups.size() / 4 + 1,
600 groupPanel.validate();
601 bigPanel.add(groupPanel, BorderLayout.NORTH);
604 updateFeatureRenderer(data, groupChanged != null);
605 resettingTable = false;
609 * reorder data based on the featureRenderers global priority list.
613 private void ensureOrder(Object[][] data)
615 boolean sort = false;
616 float[] order = new float[data.length];
617 for (int i = 0; i < order.length; i++)
619 order[i] = fr.getOrder(data[i][0].toString());
621 order[i] = fr.setOrder(data[i][0].toString(), i / order.length);
623 sort = sort || order[i - 1] > order[i];
626 jalview.util.QuickSort.sort(order, data);
631 JalviewFileChooser chooser = new JalviewFileChooser(
632 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
633 { "fc" }, new String[]
634 { "Sequence Feature Colours" }, "Sequence Feature Colours");
635 chooser.setFileView(new jalview.io.JalviewFileView());
636 chooser.setDialogTitle("Load Feature Colours");
637 chooser.setToolTipText(MessageManager.getString("action.load"));
639 int value = chooser.showOpenDialog(this);
641 if (value == JalviewFileChooser.APPROVE_OPTION)
643 File file = chooser.getSelectedFile();
647 InputStreamReader in = new InputStreamReader(new FileInputStream(
650 jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
651 jucs = (jalview.schemabinding.version2.JalviewUserColours) jucs
654 for (int i = jucs.getColourCount() - 1; i >= 0; i--)
657 jalview.schemabinding.version2.Colour newcol = jucs.getColour(i);
660 Color mincol = null, maxcol = null;
663 mincol = new Color(Integer.parseInt(newcol.getMinRGB(), 16));
664 maxcol = new Color(Integer.parseInt(newcol.getRGB(), 16));
666 } catch (Exception e)
668 Cache.log.warn("Couldn't parse out graduated feature color.",
671 GraduatedColor gcol = new GraduatedColor(mincol, maxcol,
672 newcol.getMin(), newcol.getMax());
673 if (newcol.hasAutoScale())
675 gcol.setAutoScaled(newcol.getAutoScale());
677 if (newcol.hasColourByLabel())
679 gcol.setColourByLabel(newcol.getColourByLabel());
681 if (newcol.hasThreshold())
683 gcol.setThresh(newcol.getThreshold());
684 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD); // default
686 if (newcol.getThreshType().length() > 0)
688 String ttyp = newcol.getThreshType();
689 if (ttyp.equalsIgnoreCase("NONE"))
691 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD);
693 if (ttyp.equalsIgnoreCase("ABOVE"))
695 gcol.setThreshType(AnnotationColourGradient.ABOVE_THRESHOLD);
697 if (ttyp.equalsIgnoreCase("BELOW"))
699 gcol.setThreshType(AnnotationColourGradient.BELOW_THRESHOLD);
702 fr.setColour(name = newcol.getName(), gcol);
706 fr.setColour(name = jucs.getColour(i).getName(), new Color(
707 Integer.parseInt(jucs.getColour(i).getRGB(), 16)));
709 fr.setOrder(name, (i == 0) ? 0 : i / jucs.getColourCount());
714 Object[][] data = ((FeatureTableModel) table.getModel())
717 updateFeatureRenderer(data, false);
720 } catch (Exception ex)
722 System.out.println("Error loading User Colour File\n" + ex);
729 JalviewFileChooser chooser = new JalviewFileChooser(
730 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
731 { "fc" }, new String[]
732 { "Sequence Feature Colours" }, "Sequence Feature Colours");
733 chooser.setFileView(new jalview.io.JalviewFileView());
734 chooser.setDialogTitle("Save Feature Colour Scheme");
735 chooser.setToolTipText(MessageManager.getString("action.save"));
737 int value = chooser.showSaveDialog(this);
739 if (value == JalviewFileChooser.APPROVE_OPTION)
741 String choice = chooser.getSelectedFile().getPath();
742 jalview.schemabinding.version2.JalviewUserColours ucs = new jalview.schemabinding.version2.JalviewUserColours();
743 ucs.setSchemeName("Sequence Features");
746 PrintWriter out = new PrintWriter(new OutputStreamWriter(
747 new FileOutputStream(choice), "UTF-8"));
749 Iterator e = fr.featureColours.keySet().iterator();
750 float[] sortOrder = new float[fr.featureColours.size()];
751 String[] sortTypes = new String[fr.featureColours.size()];
755 sortTypes[i] = e.next().toString();
756 sortOrder[i] = fr.getOrder(sortTypes[i]);
759 jalview.util.QuickSort.sort(sortOrder, sortTypes);
763 for (i = 0; i < sortTypes.length; i++)
765 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
766 col.setName(sortTypes[i]);
767 col.setRGB(jalview.util.Format.getHexString(fr.getColour(col
769 fcol = fr.getFeatureStyle(sortTypes[i]);
770 if (fcol instanceof GraduatedColor)
772 gcol = (GraduatedColor) fcol;
773 col.setMin(gcol.getMin());
774 col.setMax(gcol.getMax());
775 col.setMinRGB(jalview.util.Format.getHexString(gcol
777 col.setAutoScale(gcol.isAutoScale());
778 col.setThreshold(gcol.getThresh());
779 col.setColourByLabel(gcol.isColourByLabel());
780 switch (gcol.getThreshType())
782 case AnnotationColourGradient.NO_THRESHOLD:
783 col.setThreshType("NONE");
785 case AnnotationColourGradient.ABOVE_THRESHOLD:
786 col.setThreshType("ABOVE");
788 case AnnotationColourGradient.BELOW_THRESHOLD:
789 col.setThreshType("BELOW");
797 } catch (Exception ex)
799 ex.printStackTrace();
804 public void invertSelection()
806 for (int i = 0; i < table.getRowCount(); i++)
808 Boolean value = (Boolean) table.getValueAt(i, 2);
810 table.setValueAt(new Boolean(!value.booleanValue()), i, 2);
814 public void orderByAvWidth()
816 if (table == null || table.getModel() == null)
818 Object[][] data = ((FeatureTableModel) table.getModel()).getData();
819 float[] width = new float[data.length];
823 for (int i = 0; i < data.length; i++)
825 awidth = (float[]) typeWidth.get(data[i][0]);
828 width[i] = awidth[1] / awidth[0];// *awidth[0]*awidth[2]; - better
829 // weight - but have to make per
830 // sequence, too (awidth[2])
831 // if (width[i]==1) // hack to distinguish single width sequences.
841 boolean sort = false;
842 for (int i = 0; i < width.length; i++)
844 // awidth = (float[]) typeWidth.get(data[i][0]);
847 width[i] = fr.getOrder(data[i][0].toString());
850 width[i] = fr.setOrder(data[i][0].toString(), i / data.length);
855 width[i] /= max; // normalize
856 fr.setOrder(data[i][0].toString(), width[i]); // store for later
859 sort = sort || width[i - 1] > width[i];
862 jalview.util.QuickSort.sort(width, data);
863 // update global priority order
865 updateFeatureRenderer(data, false);
873 frame.setClosed(true);
874 } catch (Exception exe)
880 public void updateFeatureRenderer(Object[][] data)
882 updateFeatureRenderer(data, true);
885 private void updateFeatureRenderer(Object[][] data, boolean visibleNew)
887 fr.setFeaturePriority(data, visibleNew);
888 af.alignPanel.paintAlignment(true);
891 int selectedRow = -1;
893 JTabbedPane tabbedPane = new JTabbedPane();
895 BorderLayout borderLayout1 = new BorderLayout();
897 BorderLayout borderLayout2 = new BorderLayout();
899 BorderLayout borderLayout3 = new BorderLayout();
901 JPanel bigPanel = new JPanel();
903 BorderLayout borderLayout4 = new BorderLayout();
905 JButton invert = new JButton();
907 JPanel buttonPanel = new JPanel();
909 JButton cancel = new JButton();
911 JButton ok = new JButton();
913 JButton loadColours = new JButton();
915 JButton saveColours = new JButton();
917 JPanel dasButtonPanel = new JPanel();
919 JButton fetchDAS = new JButton();
921 JButton saveDAS = new JButton();
923 JButton cancelDAS = new JButton();
925 JButton optimizeOrder = new JButton();
927 JButton sortByScore = new JButton();
929 JButton sortByDens = new JButton();
931 JPanel transbuttons = new JPanel(new GridLayout(4, 1));
933 private void jbInit() throws Exception
935 this.setLayout(borderLayout1);
936 settingsPane.setLayout(borderLayout2);
937 dasSettingsPane.setLayout(borderLayout3);
938 bigPanel.setLayout(borderLayout4);
939 invert.setFont(JvSwingUtils.getLabelFont());
940 invert.setText(MessageManager.getString("label.invert_selection"));
941 invert.addActionListener(new ActionListener()
943 public void actionPerformed(ActionEvent e)
948 optimizeOrder.setFont(JvSwingUtils.getLabelFont());
949 optimizeOrder.setText(MessageManager.getString("label.optimise_order"));
950 optimizeOrder.addActionListener(new ActionListener()
952 public void actionPerformed(ActionEvent e)
957 sortByScore.setFont(JvSwingUtils.getLabelFont());
958 sortByScore.setText(MessageManager.getString("label.seq_sort_by_score"));
959 sortByScore.addActionListener(new ActionListener()
961 public void actionPerformed(ActionEvent e)
966 sortByDens.setFont(JvSwingUtils.getLabelFont());
967 sortByDens.setText(MessageManager.getString("label.sequence_sort_by_density"));
968 sortByDens.addActionListener(new ActionListener()
970 public void actionPerformed(ActionEvent e)
975 cancel.setFont(JvSwingUtils.getLabelFont());
976 cancel.setText(MessageManager.getString("action.cancel"));
977 cancel.addActionListener(new ActionListener()
979 public void actionPerformed(ActionEvent e)
981 updateFeatureRenderer(originalData);
985 ok.setFont(JvSwingUtils.getLabelFont());
986 ok.setText(MessageManager.getString("action.ok"));
987 ok.addActionListener(new ActionListener()
989 public void actionPerformed(ActionEvent e)
994 loadColours.setFont(JvSwingUtils.getLabelFont());
995 loadColours.setText(MessageManager.getString("label.load_colours"));
996 loadColours.addActionListener(new ActionListener()
998 public void actionPerformed(ActionEvent e)
1003 saveColours.setFont(JvSwingUtils.getLabelFont());
1004 saveColours.setText(MessageManager.getString("label.save_colours"));
1005 saveColours.addActionListener(new ActionListener()
1007 public void actionPerformed(ActionEvent e)
1012 transparency.addChangeListener(new ChangeListener()
1014 public void stateChanged(ChangeEvent evt)
1016 fr.setTransparency((float) (100 - transparency.getValue()) / 100f);
1017 af.alignPanel.paintAlignment(true);
1021 transparency.setMaximum(70);
1022 fetchDAS.setText(MessageManager.getString("label.fetch_das_features"));
1023 fetchDAS.addActionListener(new ActionListener()
1025 public void actionPerformed(ActionEvent e)
1027 fetchDAS_actionPerformed(e);
1030 saveDAS.setText(MessageManager.getString("action.save_as_default"));
1031 saveDAS.addActionListener(new ActionListener()
1033 public void actionPerformed(ActionEvent e)
1035 saveDAS_actionPerformed(e);
1038 dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
1039 dasSettingsPane.setBorder(null);
1040 cancelDAS.setEnabled(false);
1041 cancelDAS.setText(MessageManager.getString("action.cancel_fetch"));
1042 cancelDAS.addActionListener(new ActionListener()
1044 public void actionPerformed(ActionEvent e)
1046 cancelDAS_actionPerformed(e);
1049 this.add(tabbedPane, java.awt.BorderLayout.CENTER);
1050 tabbedPane.addTab("Feature Settings", settingsPane);
1051 tabbedPane.addTab("DAS Settings", dasSettingsPane);
1052 bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
1053 transbuttons.add(optimizeOrder);
1054 transbuttons.add(invert);
1055 transbuttons.add(sortByScore);
1056 transbuttons.add(sortByDens);
1057 transPanel.add(transparency);
1058 transPanel.add(transbuttons);
1059 buttonPanel.add(ok);
1060 buttonPanel.add(cancel);
1061 buttonPanel.add(loadColours);
1062 buttonPanel.add(saveColours);
1063 bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
1064 dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
1065 dasButtonPanel.add(fetchDAS);
1066 dasButtonPanel.add(cancelDAS);
1067 dasButtonPanel.add(saveDAS);
1068 settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);
1069 settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
1072 protected void sortByDens(String[] typ)
1074 sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY);
1077 protected void sortBy(String[] typ, String methodText, final String method)
1081 typ = getDisplayedFeatureTypes();
1083 String gps[] = null;
1084 gps = getDisplayedFeatureGroups();
1087 ArrayList types = new ArrayList();
1088 for (int i = 0; i < typ.length; i++)
1094 typ = new String[types.size()];
1100 ArrayList grps = new ArrayList();
1102 for (int i = 0; i < gps.length; i++)
1109 gps = new String[grps.size()];
1112 AlignmentPanel alignPanel = af.alignPanel;
1113 AlignmentI al = alignPanel.av.getAlignment();
1116 SequenceGroup sg = alignPanel.av.getSelectionGroup();
1119 start = sg.getStartRes();
1120 stop = sg.getEndRes();
1125 stop = al.getWidth();
1127 SequenceI[] oldOrder = al.getSequencesArray();
1128 AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
1129 af.addHistoryItem(new OrderCommand(methodText, oldOrder, alignPanel.av
1131 alignPanel.paintAlignment(true);
1135 protected void sortByScore(String[] typ)
1137 sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE);
1140 private String[] getDisplayedFeatureTypes()
1142 String[] typ = null;
1145 synchronized (fr.renderOrder)
1147 typ = new String[fr.renderOrder.length];
1148 System.arraycopy(fr.renderOrder, 0, typ, 0, typ.length);
1149 for (int i = 0; i < typ.length; i++)
1151 if (af.viewport.featuresDisplayed.get(typ[i]) == null)
1161 private String[] getDisplayedFeatureGroups()
1163 String[] gps = null;
1164 ArrayList<String> _gps = new ArrayList<String>();
1168 if (fr.featureGroups != null)
1170 Iterator en = fr.featureGroups.keySet().iterator();
1172 boolean valid = false;
1173 while (en.hasNext())
1175 String gp = (String) en.next();
1176 Boolean on = (Boolean) fr.featureGroups.get(gp);
1177 if (on != null && on.booleanValue())
1187 gps = new String[_gps.size()];
1195 public void fetchDAS_actionPerformed(ActionEvent e)
1197 fetchDAS.setEnabled(false);
1198 cancelDAS.setEnabled(true);
1199 dassourceBrowser.setGuiEnabled(false);
1200 Vector selectedSources = dassourceBrowser.getSelectedSources();
1201 doDasFeatureFetch(selectedSources, true, true);
1205 * get the features from selectedSources for all or the current selection
1207 * @param selectedSources
1208 * @param checkDbRefs
1209 * @param promptFetchDbRefs
1211 private void doDasFeatureFetch(List<jalviewSourceI> selectedSources,
1212 boolean checkDbRefs, boolean promptFetchDbRefs)
1214 SequenceI[] dataset, seqs;
1216 AlignViewport vp = af.getViewport();
1217 if (vp.getSelectionGroup() != null
1218 && vp.getSelectionGroup().getSize() > 0)
1220 iSize = vp.getSelectionGroup().getSize();
1221 dataset = new SequenceI[iSize];
1222 seqs = vp.getSelectionGroup().getSequencesInOrder(vp.getAlignment());
1226 iSize = vp.getAlignment().getHeight();
1227 seqs = vp.getAlignment().getSequencesArray();
1230 dataset = new SequenceI[iSize];
1231 for (int i = 0; i < iSize; i++)
1233 dataset[i] = seqs[i].getDatasetSequence();
1236 cancelDAS.setEnabled(true);
1237 dasFeatureFetcher = new jalview.ws.DasSequenceFeatureFetcher(dataset,
1238 this, selectedSources, checkDbRefs, promptFetchDbRefs);
1239 af.getViewport().setShowSequenceFeatures(true);
1240 af.showSeqFeatures.setSelected(true);
1244 * blocking call to initialise the das source browser
1246 public void initDasSources()
1248 dassourceBrowser.initDasSources();
1252 * examine the current list of das sources and return any matching the given
1253 * nicknames in sources
1256 * Vector of Strings to resolve to DAS source nicknames.
1257 * @return sources that are present in source list.
1259 public List<jalviewSourceI> resolveSourceNicknames(Vector sources)
1261 return dassourceBrowser.sourceRegistry.resolveSourceNicknames(sources);
1265 * get currently selected das sources. ensure you have called initDasSources
1266 * before calling this.
1268 * @return vector of selected das source nicknames
1270 public Vector getSelectedSources()
1272 return dassourceBrowser.getSelectedSources();
1276 * properly initialise DAS fetcher and then initiate a new thread to fetch
1277 * features from the named sources (rather than any turned on by default)
1281 * if true then runs in same thread, otherwise passes to the Swing
1284 public void fetchDasFeatures(Vector sources, boolean block)
1287 List<jalviewSourceI> resolved = dassourceBrowser.sourceRegistry
1288 .resolveSourceNicknames(sources);
1289 if (resolved.size() == 0)
1291 resolved = dassourceBrowser.getSelectedSources();
1293 if (resolved.size() > 0)
1295 final List<jalviewSourceI> dassources = resolved;
1296 fetchDAS.setEnabled(false);
1297 // cancelDAS.setEnabled(true); doDasFetch does this.
1298 Runnable fetcher = new Runnable()
1303 doDasFeatureFetch(dassources, true, false);
1313 SwingUtilities.invokeLater(fetcher);
1318 public void saveDAS_actionPerformed(ActionEvent e)
1321 .saveProperties(jalview.bin.Cache.applicationProperties);
1324 public void complete()
1326 fetchDAS.setEnabled(true);
1327 cancelDAS.setEnabled(false);
1328 dassourceBrowser.setGuiEnabled(true);
1332 public void cancelDAS_actionPerformed(ActionEvent e)
1334 if (dasFeatureFetcher != null)
1336 dasFeatureFetcher.cancel();
1341 public void noDasSourceActive()
1344 JOptionPane.showInternalConfirmDialog(Desktop.desktop,
1345 MessageManager.getString("label.no_das_sources_selected_warn"),
1346 MessageManager.getString("label.no_das_sources_selected_title"), JOptionPane.DEFAULT_OPTION,
1347 JOptionPane.INFORMATION_MESSAGE);
1350 // ///////////////////////////////////////////////////////////////////////
1351 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
1352 // ///////////////////////////////////////////////////////////////////////
1353 class FeatureTableModel extends AbstractTableModel
1355 FeatureTableModel(Object[][] data)
1360 private String[] columnNames =
1361 { "Feature Type", "Colour", "Display" };
1363 private Object[][] data;
1365 public Object[][] getData()
1370 public void setData(Object[][] data)
1375 public int getColumnCount()
1377 return columnNames.length;
1380 public Object[] getRow(int row)
1385 public int getRowCount()
1390 public String getColumnName(int col)
1392 return columnNames[col];
1395 public Object getValueAt(int row, int col)
1397 return data[row][col];
1400 public Class getColumnClass(int c)
1402 return getValueAt(0, c).getClass();
1405 public boolean isCellEditable(int row, int col)
1407 return col == 0 ? false : true;
1410 public void setValueAt(Object value, int row, int col)
1412 data[row][col] = value;
1413 fireTableCellUpdated(row, col);
1414 updateFeatureRenderer(data);
1419 class ColorRenderer extends JLabel implements TableCellRenderer
1421 javax.swing.border.Border unselectedBorder = null;
1423 javax.swing.border.Border selectedBorder = null;
1425 final String baseTT = "Click to edit, right/apple click for menu.";
1427 public ColorRenderer()
1429 setOpaque(true); // MUST do this for background to show up.
1430 setHorizontalTextPosition(SwingConstants.CENTER);
1431 setVerticalTextPosition(SwingConstants.CENTER);
1434 public Component getTableCellRendererComponent(JTable table,
1435 Object color, boolean isSelected, boolean hasFocus, int row,
1438 // JLabel comp = new JLabel();
1442 // setBounds(getBounds());
1444 setToolTipText(baseTT);
1445 setBackground(table.getBackground());
1446 if (color instanceof GraduatedColor)
1448 Rectangle cr = table.getCellRect(row, column, false);
1449 FeatureSettings.renderGraduatedColor(this, (GraduatedColor) color,
1450 (int) cr.getWidth(), (int) cr.getHeight());
1457 newColor = (Color) color;
1459 setBackground(newColor);
1460 // comp.setToolTipText("RGB value: " + newColor.getRed() + ", "
1461 // + newColor.getGreen() + ", " + newColor.getBlue());
1465 if (selectedBorder == null)
1467 selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1468 table.getSelectionBackground());
1471 setBorder(selectedBorder);
1475 if (unselectedBorder == null)
1477 unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1478 table.getBackground());
1481 setBorder(unselectedBorder);
1489 * update comp using rendering settings from gcol
1494 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol)
1496 int w = comp.getWidth(), h = comp.getHeight();
1499 w = (int) comp.getPreferredSize().getWidth();
1500 h = (int) comp.getPreferredSize().getHeight();
1507 renderGraduatedColor(comp, gcol, w, h);
1510 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol,
1513 boolean thr = false;
1516 if (gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD)
1520 tt += "Thresholded (Above " + gcol.getThresh() + ") ";
1522 if (gcol.getThreshType() == AnnotationColourGradient.BELOW_THRESHOLD)
1526 tt += "Thresholded (Below " + gcol.getThresh() + ") ";
1528 if (gcol.isColourByLabel())
1530 tt = "Coloured by label text. " + tt;
1540 Color newColor = gcol.getMaxColor();
1541 comp.setBackground(newColor);
1542 // System.err.println("Width is " + w / 2);
1543 Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w, h, thr);
1544 comp.setIcon(ficon);
1545 // tt+="RGB value: Max (" + newColor.getRed() + ", "
1546 // + newColor.getGreen() + ", " + newColor.getBlue()
1547 // + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen()
1548 // + ", " + minCol.getBlue() + ")");
1550 comp.setHorizontalAlignment(SwingConstants.CENTER);
1552 if (tt.length() > 0)
1554 if (comp.getToolTipText() == null)
1556 comp.setToolTipText(tt);
1560 comp.setToolTipText(tt + " " + comp.getToolTipText());
1566 class FeatureIcon implements Icon
1568 GraduatedColor gcol;
1572 boolean midspace = false;
1574 int width = 50, height = 20;
1576 int s1, e1; // start and end of midpoint band for thresholded symbol
1578 Color mpcolour = Color.white;
1580 FeatureIcon(GraduatedColor gfc, Color bg, int w, int h, boolean mspace)
1599 public int getIconWidth()
1604 public int getIconHeight()
1609 public void paintIcon(Component c, Graphics g, int x, int y)
1612 if (gcol.isColourByLabel())
1615 g.fillRect(0, 0, width, height);
1616 // need an icon here.
1617 g.setColor(gcol.getMaxColor());
1619 g.setFont(new Font("Verdana", Font.PLAIN, 9));
1621 // g.setFont(g.getFont().deriveFont(
1622 // AffineTransform.getScaleInstance(
1623 // width/g.getFontMetrics().stringWidth("Label"),
1624 // height/g.getFontMetrics().getHeight())));
1626 g.drawString(MessageManager.getString("label.label"), 0, 0);
1631 Color minCol = gcol.getMinColor();
1633 g.fillRect(0, 0, s1, height);
1636 g.setColor(Color.white);
1637 g.fillRect(s1, 0, e1 - s1, height);
1639 g.setColor(gcol.getMaxColor());
1640 g.fillRect(0, e1, width - e1, height);
1645 class ColorEditor extends AbstractCellEditor implements TableCellEditor,
1650 GraduatedColor currentGColor;
1652 FeatureColourChooser chooser;
1660 JColorChooser colorChooser;
1664 protected static final String EDIT = "edit";
1666 int selectedRow = 0;
1668 public ColorEditor(FeatureSettings me)
1671 // Set up the editor (from the table's point of view),
1672 // which is a button.
1673 // This button brings up the color chooser dialog,
1674 // which is the editor from the user's point of view.
1675 button = new JButton();
1676 button.setActionCommand(EDIT);
1677 button.addActionListener(this);
1678 button.setBorderPainted(false);
1679 // Set up the dialog that the button brings up.
1680 colorChooser = new JColorChooser();
1681 dialog = JColorChooser.createDialog(button, "Select new Colour", true, // modal
1682 colorChooser, this, // OK button handler
1683 null); // no CANCEL button handler
1687 * Handles events from the editor button and from the dialog's OK button.
1689 public void actionPerformed(ActionEvent e)
1692 if (EDIT.equals(e.getActionCommand()))
1694 // The user has clicked the cell, so
1695 // bring up the dialog.
1696 if (currentColor != null)
1698 // bring up simple color chooser
1699 button.setBackground(currentColor);
1700 colorChooser.setColor(currentColor);
1701 dialog.setVisible(true);
1705 // bring up graduated chooser.
1706 chooser = new FeatureColourChooser(me.fr, type);
1707 chooser.setRequestFocusEnabled(true);
1708 chooser.requestFocus();
1709 chooser.addActionListener(this);
1711 // Make the renderer reappear.
1712 fireEditingStopped();
1716 { // User pressed dialog's "OK" button.
1717 if (currentColor != null)
1719 currentColor = colorChooser.getColor();
1723 // class cast exceptions may be raised if the chooser created on a
1724 // non-graduated color
1725 currentGColor = (GraduatedColor) chooser.getLastColour();
1727 me.table.setValueAt(getCellEditorValue(), selectedRow, 1);
1728 fireEditingStopped();
1729 me.table.validate();
1733 // Implement the one CellEditor method that AbstractCellEditor doesn't.
1734 public Object getCellEditorValue()
1736 if (currentColor == null)
1738 return currentGColor;
1740 return currentColor;
1743 // Implement the one method defined by TableCellEditor.
1744 public Component getTableCellEditorComponent(JTable table, Object value,
1745 boolean isSelected, int row, int column)
1747 currentGColor = null;
1748 currentColor = null;
1749 this.selectedRow = row;
1750 type = me.table.getValueAt(row, 0).toString();
1751 button.setOpaque(true);
1752 button.setBackground(me.getBackground());
1753 if (value instanceof GraduatedColor)
1755 currentGColor = (GraduatedColor) value;
1756 JLabel btn = new JLabel();
1757 btn.setSize(button.getSize());
1758 FeatureSettings.renderGraduatedColor(btn, currentGColor);
1759 button.setBackground(btn.getBackground());
1760 button.setIcon(btn.getIcon());
1761 button.setText(btn.getText());
1766 button.setIcon(null);
1767 currentColor = (Color) value;
1768 button.setBackground(currentColor);