2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.1)
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.
23 import java.util.List;
25 import java.awt.event.*;
26 import java.beans.PropertyChangeEvent;
27 import java.beans.PropertyChangeListener;
30 import javax.swing.event.*;
31 import javax.swing.table.*;
33 import jalview.analysis.AlignmentSorter;
34 import jalview.bin.Cache;
35 import jalview.commands.OrderCommand;
36 import jalview.datamodel.*;
38 import jalview.schemes.AnnotationColourGradient;
39 import jalview.schemes.GraduatedColor;
40 import jalview.util.MessageManager;
41 import jalview.ws.dbsources.das.api.jalviewSourceI;
43 public class FeatureSettings extends JPanel
45 DasSourceBrowser dassourceBrowser;
47 jalview.ws.DasSequenceFeatureFetcher dasFeatureFetcher;
49 JPanel settingsPane = new JPanel();
51 JPanel dasSettingsPane = new JPanel();
53 final FeatureRenderer fr;
55 public final AlignFrame af;
57 Object[][] originalData;
59 final JInternalFrame frame;
61 JScrollPane scrollPane = new JScrollPane();
67 JSlider transparency = new JSlider();
69 JPanel transPanel = new JPanel(new GridLayout(1, 2));
71 public FeatureSettings(AlignFrame af)
74 fr = af.getFeatureRenderer();
76 transparency.setMaximum(100 - (int) (fr.transparency * 100));
81 } catch (Exception ex)
87 table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));
88 table.setFont(new Font("Verdana", Font.PLAIN, 12));
89 table.setDefaultRenderer(Color.class, new ColorRenderer());
91 table.setDefaultEditor(Color.class, new ColorEditor(this));
93 table.setDefaultEditor(GraduatedColor.class, new ColorEditor(this));
94 table.setDefaultRenderer(GraduatedColor.class, new ColorRenderer());
95 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
97 table.addMouseListener(new MouseAdapter()
99 public void mousePressed(MouseEvent evt)
101 selectedRow = table.rowAtPoint(evt.getPoint());
102 if (evt.isPopupTrigger())
104 popupSort(selectedRow, (String) table.getValueAt(selectedRow, 0),
105 table.getValueAt(selectedRow, 1), fr.minmax, evt.getX(),
108 else if (evt.getClickCount() == 2)
110 fr.ap.alignFrame.avc.markColumnsContainingFeatures(
111 evt.isAltDown(),evt.isShiftDown() || evt.isMetaDown(), evt.isMetaDown(),
112 (String) table.getValueAt(selectedRow, 0));
117 table.addMouseMotionListener(new MouseMotionAdapter()
119 public void mouseDragged(MouseEvent evt)
121 int newRow = table.rowAtPoint(evt.getPoint());
122 if (newRow != selectedRow && selectedRow != -1 && newRow != -1)
124 Object[] temp = new Object[3];
125 temp[0] = table.getValueAt(selectedRow, 0);
126 temp[1] = table.getValueAt(selectedRow, 1);
127 temp[2] = table.getValueAt(selectedRow, 2);
129 table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0);
130 table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1);
131 table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2);
133 table.setValueAt(temp[0], newRow, 0);
134 table.setValueAt(temp[1], newRow, 1);
135 table.setValueAt(temp[2], newRow, 2);
137 selectedRow = newRow;
141 table.setToolTipText("<html>"+JvSwingUtils
142 .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>");
143 scrollPane.setViewportView(table);
145 dassourceBrowser = new DasSourceBrowser(this);
146 dasSettingsPane.add(dassourceBrowser, BorderLayout.CENTER);
148 if (af.getViewport().featuresDisplayed == null
149 || fr.renderOrder == null)
151 fr.findAllFeatures(true); // display everything!
155 final PropertyChangeListener change;
156 final FeatureSettings fs = this;
157 fr.addPropertyChangeListener(change = new PropertyChangeListener()
159 public void propertyChange(PropertyChangeEvent evt)
161 if (!fs.resettingTable && !fs.handlingUpdate)
163 fs.handlingUpdate = true;
164 fs.resetTable(null); // new groups may be added with new seuqence
165 // feature types only
166 fs.handlingUpdate = false;
172 frame = new JInternalFrame();
173 frame.setContentPane(this);
174 if (new jalview.util.Platform().isAMac())
176 Desktop.addInternalFrame(frame, MessageManager.getString("label.sequence_feature_settings"), 475, 480);
180 Desktop.addInternalFrame(frame, MessageManager.getString("label.sequence_feature_settings"), 400, 450);
183 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
185 public void internalFrameClosed(
186 javax.swing.event.InternalFrameEvent evt)
188 fr.removePropertyChangeListener(change);
189 dassourceBrowser.fs = null;
192 frame.setLayer(JLayeredPane.PALETTE_LAYER);
195 protected void popupSort(final int selectedRow, final String type,
196 final Object typeCol, final Hashtable minmax, int x, int y)
198 JPopupMenu men = new JPopupMenu(MessageManager.formatMessage("label.settings_for_param", new String[]{type}));
199 JMenuItem scr = new JMenuItem(MessageManager.getString("label.sort_by_score"));
201 final FeatureSettings me = this;
202 scr.addActionListener(new ActionListener()
205 public void actionPerformed(ActionEvent e)
207 me.sortByScore(new String[]
212 JMenuItem dens = new JMenuItem(MessageManager.getString("label.sort_by_density"));
213 dens.addActionListener(new ActionListener()
216 public void actionPerformed(ActionEvent e)
218 me.sortByDens(new String[]
226 final Object typeMinMax = minmax.get(type);
228 * final JCheckBoxMenuItem chb = new JCheckBoxMenuItem("Vary Height"); //
229 * this is broken at the moment and isn't that useful anyway!
230 * chb.setSelected(minmax.get(type) != null); chb.addActionListener(new
233 * public void actionPerformed(ActionEvent e) {
234 * chb.setState(chb.getState()); if (chb.getState()) { minmax.put(type,
235 * null); } else { minmax.put(type, typeMinMax); } }
241 if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null)
243 // if (table.getValueAt(row, column));
244 // graduated colourschemes for those where minmax exists for the
245 // positional features
246 final JCheckBoxMenuItem mxcol = new JCheckBoxMenuItem(
248 mxcol.setSelected(!(typeCol instanceof Color));
250 mxcol.addActionListener(new ActionListener()
252 JColorChooser colorChooser;
254 public void actionPerformed(ActionEvent e)
256 if (e.getSource() == mxcol)
258 if (typeCol instanceof Color)
260 FeatureColourChooser fc = new FeatureColourChooser(me.fr,
262 fc.addActionListener(this);
266 // bring up simple color chooser
267 colorChooser = new JColorChooser();
268 JDialog dialog = JColorChooser.createDialog(me,
269 "Select new Colour", true, // modal
270 colorChooser, this, // OK button handler
271 null); // no CANCEL button handler
272 colorChooser.setColor(((GraduatedColor) typeCol)
274 dialog.setVisible(true);
279 if (e.getSource() instanceof FeatureColourChooser)
281 FeatureColourChooser fc = (FeatureColourChooser) e
283 table.setValueAt(fc.getLastColour(), selectedRow, 1);
288 // probably the color chooser!
289 table.setValueAt(colorChooser.getColor(), selectedRow, 1);
291 me.updateFeatureRenderer(
292 ((FeatureTableModel) table.getModel()).getData(),
301 JMenuItem selCols = new JMenuItem(MessageManager.getString("label.select_columns_containing"));
302 selCols.addActionListener(new ActionListener()
306 public void actionPerformed(ActionEvent arg0)
308 fr.ap.alignFrame.avc.markColumnsContainingFeatures(false, false, false, type);
311 JMenuItem clearCols = new JMenuItem(MessageManager.getString("label.select_columns_not_containing"));
312 clearCols.addActionListener(new ActionListener()
316 public void actionPerformed(ActionEvent arg0)
318 fr.ap.alignFrame.avc.markColumnsContainingFeatures(true, false, false, type);
323 men.show(table, x, y);
327 * true when Feature Settings are updating from feature renderer
329 private boolean handlingUpdate = false;
332 * contains a float[3] for each feature type string. created by setTableData
334 Hashtable typeWidth = null;
336 synchronized public void setTableData()
338 if (fr.featureGroups == null)
340 fr.featureGroups = new Hashtable();
342 Vector allFeatures = new Vector();
343 Vector allGroups = new Vector();
344 SequenceFeature[] tmpfeatures;
346 for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
348 if (af.getViewport().getAlignment().getSequenceAt(i)
349 .getDatasetSequence().getSequenceFeatures() == null)
354 tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
355 .getDatasetSequence().getSequenceFeatures();
358 while (index < tmpfeatures.length)
360 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
366 if (tmpfeatures[index].getFeatureGroup() != null)
368 group = tmpfeatures[index].featureGroup;
369 if (!allGroups.contains(group))
371 allGroups.addElement(group);
374 checkGroupState(group);
379 if (!allFeatures.contains(tmpfeatures[index].getType()))
381 allFeatures.addElement(tmpfeatures[index].getType());
395 * @return true if group has been seen before and is already added to set.
397 private boolean checkGroupState(String group)
400 if (fr.featureGroups.containsKey(group))
402 visible = ((Boolean) fr.featureGroups.get(group)).booleanValue();
406 visible = true; // new group is always made visible
409 if (groupPanel == null)
411 groupPanel = new JPanel();
414 boolean alreadyAdded = false;
415 for (int g = 0; g < groupPanel.getComponentCount(); g++)
417 if (((JCheckBox) groupPanel.getComponent(g)).getText().equals(group))
420 ((JCheckBox) groupPanel.getComponent(g)).setSelected(visible);
431 fr.featureGroups.put(group, new Boolean(visible));
432 final String grp = group;
433 final JCheckBox check = new JCheckBox(group, visible);
434 check.setFont(new Font("Serif", Font.BOLD, 12));
435 check.addItemListener(new ItemListener()
437 public void itemStateChanged(ItemEvent evt)
439 fr.featureGroups.put(check.getText(),
440 new Boolean(check.isSelected()));
441 af.alignPanel.seqPanel.seqCanvas.repaint();
442 if (af.alignPanel.overviewPanel != null)
444 af.alignPanel.overviewPanel.updateOverviewImage();
447 resetTable(new String[]
451 groupPanel.add(check);
455 boolean resettingTable = false;
457 synchronized void resetTable(String[] groupChanged)
459 if (resettingTable == true)
463 resettingTable = true;
464 typeWidth = new Hashtable();
465 // TODO: change avWidth calculation to 'per-sequence' average and use long
467 float[] avWidth = null;
468 SequenceFeature[] tmpfeatures;
469 String group = null, type;
470 Vector visibleChecks = new Vector();
472 // Find out which features should be visible depending on which groups
473 // are selected / deselected
474 // and recompute average width ordering
475 for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
478 tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
479 .getDatasetSequence().getSequenceFeatures();
480 if (tmpfeatures == null)
486 while (index < tmpfeatures.length)
488 group = tmpfeatures[index].featureGroup;
490 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
496 if (group == null || fr.featureGroups.get(group) == null
497 || ((Boolean) fr.featureGroups.get(group)).booleanValue())
500 checkGroupState(group);
501 type = tmpfeatures[index].getType();
502 if (!visibleChecks.contains(type))
504 visibleChecks.addElement(type);
507 if (!typeWidth.containsKey(tmpfeatures[index].getType()))
509 typeWidth.put(tmpfeatures[index].getType(),
510 avWidth = new float[3]);
514 avWidth = (float[]) typeWidth.get(tmpfeatures[index].getType());
517 if (tmpfeatures[index].getBegin() > tmpfeatures[index].getEnd())
519 avWidth[1] += 1 + tmpfeatures[index].getBegin()
520 - tmpfeatures[index].getEnd();
524 avWidth[1] += 1 + tmpfeatures[index].getEnd()
525 - tmpfeatures[index].getBegin();
531 int fSize = visibleChecks.size();
532 Object[][] data = new Object[fSize][3];
535 if (fr.renderOrder != null)
538 fr.findAllFeatures(groupChanged != null); // prod to update
539 // colourschemes. but don't
541 // First add the checks in the previous render order,
542 // in case the window has been closed and reopened
543 for (int ro = fr.renderOrder.length - 1; ro > -1; ro--)
545 type = fr.renderOrder[ro];
547 if (!visibleChecks.contains(type))
552 data[dataIndex][0] = type;
553 data[dataIndex][1] = fr.getFeatureStyle(type);
554 data[dataIndex][2] = new Boolean(
555 af.getViewport().featuresDisplayed.containsKey(type));
557 visibleChecks.removeElement(type);
561 fSize = visibleChecks.size();
562 for (int i = 0; i < fSize; i++)
564 // These must be extra features belonging to the group
565 // which was just selected
566 type = visibleChecks.elementAt(i).toString();
567 data[dataIndex][0] = type;
569 data[dataIndex][1] = fr.getFeatureStyle(type);
570 if (data[dataIndex][1] == null)
572 // "Colour has been updated in another view!!"
573 fr.renderOrder = null;
577 data[dataIndex][2] = new Boolean(true);
581 if (originalData == null)
583 originalData = new Object[data.length][3];
584 for (int i = 0; i < data.length; i++)
586 System.arraycopy(data[i], 0, originalData[i], 0, 3);
590 table.setModel(new FeatureTableModel(data));
591 table.getColumnModel().getColumn(0).setPreferredWidth(200);
593 if (groupPanel != null)
595 groupPanel.setLayout(new GridLayout(fr.featureGroups.size() / 4 + 1,
598 groupPanel.validate();
599 bigPanel.add(groupPanel, BorderLayout.NORTH);
602 updateFeatureRenderer(data, groupChanged != null);
603 resettingTable = false;
607 * reorder data based on the featureRenderers global priority list.
611 private void ensureOrder(Object[][] data)
613 boolean sort = false;
614 float[] order = new float[data.length];
615 for (int i = 0; i < order.length; i++)
617 order[i] = fr.getOrder(data[i][0].toString());
619 order[i] = fr.setOrder(data[i][0].toString(), i / order.length);
621 sort = sort || order[i - 1] > order[i];
624 jalview.util.QuickSort.sort(order, data);
629 JalviewFileChooser chooser = new JalviewFileChooser(
630 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
631 { "fc" }, new String[]
632 { "Sequence Feature Colours" }, "Sequence Feature Colours");
633 chooser.setFileView(new jalview.io.JalviewFileView());
634 chooser.setDialogTitle("Load Feature Colours");
635 chooser.setToolTipText(MessageManager.getString("action.load"));
637 int value = chooser.showOpenDialog(this);
639 if (value == JalviewFileChooser.APPROVE_OPTION)
641 File file = chooser.getSelectedFile();
645 InputStreamReader in = new InputStreamReader(new FileInputStream(
648 jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
649 jucs = (jalview.schemabinding.version2.JalviewUserColours) jucs
652 for (int i = jucs.getColourCount() - 1; i >= 0; i--)
655 jalview.schemabinding.version2.Colour newcol = jucs.getColour(i);
658 Color mincol = null, maxcol = null;
661 mincol = new Color(Integer.parseInt(newcol.getMinRGB(), 16));
662 maxcol = new Color(Integer.parseInt(newcol.getRGB(), 16));
664 } catch (Exception e)
666 Cache.log.warn("Couldn't parse out graduated feature color.",
669 GraduatedColor gcol = new GraduatedColor(mincol, maxcol,
670 newcol.getMin(), newcol.getMax());
671 if (newcol.hasAutoScale())
673 gcol.setAutoScaled(newcol.getAutoScale());
675 if (newcol.hasColourByLabel())
677 gcol.setColourByLabel(newcol.getColourByLabel());
679 if (newcol.hasThreshold())
681 gcol.setThresh(newcol.getThreshold());
682 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD); // default
684 if (newcol.getThreshType().length() > 0)
686 String ttyp = newcol.getThreshType();
687 if (ttyp.equalsIgnoreCase("NONE"))
689 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD);
691 if (ttyp.equalsIgnoreCase("ABOVE"))
693 gcol.setThreshType(AnnotationColourGradient.ABOVE_THRESHOLD);
695 if (ttyp.equalsIgnoreCase("BELOW"))
697 gcol.setThreshType(AnnotationColourGradient.BELOW_THRESHOLD);
700 fr.setColour(name = newcol.getName(), gcol);
704 fr.setColour(name = jucs.getColour(i).getName(), new Color(
705 Integer.parseInt(jucs.getColour(i).getRGB(), 16)));
707 fr.setOrder(name, (i == 0) ? 0 : i / jucs.getColourCount());
712 Object[][] data = ((FeatureTableModel) table.getModel())
715 updateFeatureRenderer(data, false);
718 } catch (Exception ex)
720 System.out.println("Error loading User Colour File\n" + ex);
727 JalviewFileChooser chooser = new JalviewFileChooser(
728 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
729 { "fc" }, new String[]
730 { "Sequence Feature Colours" }, "Sequence Feature Colours");
731 chooser.setFileView(new jalview.io.JalviewFileView());
732 chooser.setDialogTitle("Save Feature Colour Scheme");
733 chooser.setToolTipText(MessageManager.getString("action.save"));
735 int value = chooser.showSaveDialog(this);
737 if (value == JalviewFileChooser.APPROVE_OPTION)
739 String choice = chooser.getSelectedFile().getPath();
740 jalview.schemabinding.version2.JalviewUserColours ucs = new jalview.schemabinding.version2.JalviewUserColours();
741 ucs.setSchemeName("Sequence Features");
744 PrintWriter out = new PrintWriter(new OutputStreamWriter(
745 new FileOutputStream(choice), "UTF-8"));
747 Iterator e = fr.featureColours.keySet().iterator();
748 float[] sortOrder = new float[fr.featureColours.size()];
749 String[] sortTypes = new String[fr.featureColours.size()];
753 sortTypes[i] = e.next().toString();
754 sortOrder[i] = fr.getOrder(sortTypes[i]);
757 jalview.util.QuickSort.sort(sortOrder, sortTypes);
761 for (i = 0; i < sortTypes.length; i++)
763 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
764 col.setName(sortTypes[i]);
765 col.setRGB(jalview.util.Format.getHexString(fr.getColour(col
767 fcol = fr.getFeatureStyle(sortTypes[i]);
768 if (fcol instanceof GraduatedColor)
770 gcol = (GraduatedColor) fcol;
771 col.setMin(gcol.getMin());
772 col.setMax(gcol.getMax());
773 col.setMinRGB(jalview.util.Format.getHexString(gcol
775 col.setAutoScale(gcol.isAutoScale());
776 col.setThreshold(gcol.getThresh());
777 col.setColourByLabel(gcol.isColourByLabel());
778 switch (gcol.getThreshType())
780 case AnnotationColourGradient.NO_THRESHOLD:
781 col.setThreshType("NONE");
783 case AnnotationColourGradient.ABOVE_THRESHOLD:
784 col.setThreshType("ABOVE");
786 case AnnotationColourGradient.BELOW_THRESHOLD:
787 col.setThreshType("BELOW");
795 } catch (Exception ex)
797 ex.printStackTrace();
802 public void invertSelection()
804 for (int i = 0; i < table.getRowCount(); i++)
806 Boolean value = (Boolean) table.getValueAt(i, 2);
808 table.setValueAt(new Boolean(!value.booleanValue()), i, 2);
812 public void orderByAvWidth()
814 if (table == null || table.getModel() == null)
816 Object[][] data = ((FeatureTableModel) table.getModel()).getData();
817 float[] width = new float[data.length];
821 for (int i = 0; i < data.length; i++)
823 awidth = (float[]) typeWidth.get(data[i][0]);
826 width[i] = awidth[1] / awidth[0];// *awidth[0]*awidth[2]; - better
827 // weight - but have to make per
828 // sequence, too (awidth[2])
829 // if (width[i]==1) // hack to distinguish single width sequences.
839 boolean sort = false;
840 for (int i = 0; i < width.length; i++)
842 // awidth = (float[]) typeWidth.get(data[i][0]);
845 width[i] = fr.getOrder(data[i][0].toString());
848 width[i] = fr.setOrder(data[i][0].toString(), i / data.length);
853 width[i] /= max; // normalize
854 fr.setOrder(data[i][0].toString(), width[i]); // store for later
857 sort = sort || width[i - 1] > width[i];
860 jalview.util.QuickSort.sort(width, data);
861 // update global priority order
863 updateFeatureRenderer(data, false);
871 frame.setClosed(true);
872 } catch (Exception exe)
878 public void updateFeatureRenderer(Object[][] data)
880 updateFeatureRenderer(data, true);
883 private void updateFeatureRenderer(Object[][] data, boolean visibleNew)
885 fr.setFeaturePriority(data, visibleNew);
886 af.alignPanel.paintAlignment(true);
889 int selectedRow = -1;
891 JTabbedPane tabbedPane = new JTabbedPane();
893 BorderLayout borderLayout1 = new BorderLayout();
895 BorderLayout borderLayout2 = new BorderLayout();
897 BorderLayout borderLayout3 = new BorderLayout();
899 JPanel bigPanel = new JPanel();
901 BorderLayout borderLayout4 = new BorderLayout();
903 JButton invert = new JButton();
905 JPanel buttonPanel = new JPanel();
907 JButton cancel = new JButton();
909 JButton ok = new JButton();
911 JButton loadColours = new JButton();
913 JButton saveColours = new JButton();
915 JPanel dasButtonPanel = new JPanel();
917 JButton fetchDAS = new JButton();
919 JButton saveDAS = new JButton();
921 JButton cancelDAS = new JButton();
923 JButton optimizeOrder = new JButton();
925 JButton sortByScore = new JButton();
927 JButton sortByDens = new JButton();
929 JPanel transbuttons = new JPanel(new GridLayout(4, 1));
931 private void jbInit() throws Exception
933 this.setLayout(borderLayout1);
934 settingsPane.setLayout(borderLayout2);
935 dasSettingsPane.setLayout(borderLayout3);
936 bigPanel.setLayout(borderLayout4);
937 invert.setFont(JvSwingUtils.getLabelFont());
938 invert.setText(MessageManager.getString("label.invert_selection"));
939 invert.addActionListener(new ActionListener()
941 public void actionPerformed(ActionEvent e)
946 optimizeOrder.setFont(JvSwingUtils.getLabelFont());
947 optimizeOrder.setText(MessageManager.getString("label.optimise_order"));
948 optimizeOrder.addActionListener(new ActionListener()
950 public void actionPerformed(ActionEvent e)
955 sortByScore.setFont(JvSwingUtils.getLabelFont());
956 sortByScore.setText(MessageManager.getString("label.seq_sort_by_score"));
957 sortByScore.addActionListener(new ActionListener()
959 public void actionPerformed(ActionEvent e)
964 sortByDens.setFont(JvSwingUtils.getLabelFont());
965 sortByDens.setText(MessageManager.getString("label.sequence_sort_by_density"));
966 sortByDens.addActionListener(new ActionListener()
968 public void actionPerformed(ActionEvent e)
973 cancel.setFont(JvSwingUtils.getLabelFont());
974 cancel.setText(MessageManager.getString("action.cancel"));
975 cancel.addActionListener(new ActionListener()
977 public void actionPerformed(ActionEvent e)
979 updateFeatureRenderer(originalData);
983 ok.setFont(JvSwingUtils.getLabelFont());
984 ok.setText(MessageManager.getString("action.ok"));
985 ok.addActionListener(new ActionListener()
987 public void actionPerformed(ActionEvent e)
992 loadColours.setFont(JvSwingUtils.getLabelFont());
993 loadColours.setText(MessageManager.getString("label.load_colours"));
994 loadColours.addActionListener(new ActionListener()
996 public void actionPerformed(ActionEvent e)
1001 saveColours.setFont(JvSwingUtils.getLabelFont());
1002 saveColours.setText(MessageManager.getString("label.save_colours"));
1003 saveColours.addActionListener(new ActionListener()
1005 public void actionPerformed(ActionEvent e)
1010 transparency.addChangeListener(new ChangeListener()
1012 public void stateChanged(ChangeEvent evt)
1014 fr.setTransparency((float) (100 - transparency.getValue()) / 100f);
1015 af.alignPanel.paintAlignment(true);
1019 transparency.setMaximum(70);
1020 fetchDAS.setText(MessageManager.getString("label.fetch_das_features"));
1021 fetchDAS.addActionListener(new ActionListener()
1023 public void actionPerformed(ActionEvent e)
1025 fetchDAS_actionPerformed(e);
1028 saveDAS.setText(MessageManager.getString("action.save_as_default"));
1029 saveDAS.addActionListener(new ActionListener()
1031 public void actionPerformed(ActionEvent e)
1033 saveDAS_actionPerformed(e);
1036 dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
1037 dasSettingsPane.setBorder(null);
1038 cancelDAS.setEnabled(false);
1039 cancelDAS.setText(MessageManager.getString("action.cancel_fetch"));
1040 cancelDAS.addActionListener(new ActionListener()
1042 public void actionPerformed(ActionEvent e)
1044 cancelDAS_actionPerformed(e);
1047 this.add(tabbedPane, java.awt.BorderLayout.CENTER);
1048 tabbedPane.addTab("Feature Settings", settingsPane);
1049 tabbedPane.addTab("DAS Settings", dasSettingsPane);
1050 bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
1051 transbuttons.add(optimizeOrder);
1052 transbuttons.add(invert);
1053 transbuttons.add(sortByScore);
1054 transbuttons.add(sortByDens);
1055 transPanel.add(transparency);
1056 transPanel.add(transbuttons);
1057 buttonPanel.add(ok);
1058 buttonPanel.add(cancel);
1059 buttonPanel.add(loadColours);
1060 buttonPanel.add(saveColours);
1061 bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
1062 dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
1063 dasButtonPanel.add(fetchDAS);
1064 dasButtonPanel.add(cancelDAS);
1065 dasButtonPanel.add(saveDAS);
1066 settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);
1067 settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
1070 protected void sortByDens(String[] typ)
1072 sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY);
1075 protected void sortBy(String[] typ, String methodText, final String method)
1079 typ = getDisplayedFeatureTypes();
1081 String gps[] = null;
1082 gps = getDisplayedFeatureGroups();
1085 ArrayList types = new ArrayList();
1086 for (int i = 0; i < typ.length; i++)
1092 typ = new String[types.size()];
1098 ArrayList grps = new ArrayList();
1100 for (int i = 0; i < gps.length; i++)
1107 gps = new String[grps.size()];
1110 AlignmentPanel alignPanel = af.alignPanel;
1111 AlignmentI al = alignPanel.av.getAlignment();
1114 SequenceGroup sg = alignPanel.av.getSelectionGroup();
1117 start = sg.getStartRes();
1118 stop = sg.getEndRes();
1123 stop = al.getWidth();
1125 SequenceI[] oldOrder = al.getSequencesArray();
1126 AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
1127 af.addHistoryItem(new OrderCommand(methodText, oldOrder, alignPanel.av
1129 alignPanel.paintAlignment(true);
1133 protected void sortByScore(String[] typ)
1135 sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE);
1138 private String[] getDisplayedFeatureTypes()
1140 String[] typ = null;
1143 synchronized (fr.renderOrder)
1145 typ = new String[fr.renderOrder.length];
1146 System.arraycopy(fr.renderOrder, 0, typ, 0, typ.length);
1147 for (int i = 0; i < typ.length; i++)
1149 if (af.viewport.featuresDisplayed.get(typ[i]) == null)
1159 private String[] getDisplayedFeatureGroups()
1161 String[] gps = null;
1162 ArrayList<String> _gps = new ArrayList<String>();
1166 if (fr.featureGroups != null)
1168 Iterator en = fr.featureGroups.keySet().iterator();
1170 boolean valid = false;
1171 while (en.hasNext())
1173 String gp = (String) en.next();
1174 Boolean on = (Boolean) fr.featureGroups.get(gp);
1175 if (on != null && on.booleanValue())
1185 gps = new String[_gps.size()];
1193 public void fetchDAS_actionPerformed(ActionEvent e)
1195 fetchDAS.setEnabled(false);
1196 cancelDAS.setEnabled(true);
1197 dassourceBrowser.setGuiEnabled(false);
1198 Vector selectedSources = dassourceBrowser.getSelectedSources();
1199 doDasFeatureFetch(selectedSources, true, true);
1203 * get the features from selectedSources for all or the current selection
1205 * @param selectedSources
1206 * @param checkDbRefs
1207 * @param promptFetchDbRefs
1209 private void doDasFeatureFetch(List<jalviewSourceI> selectedSources,
1210 boolean checkDbRefs, boolean promptFetchDbRefs)
1212 SequenceI[] dataset, seqs;
1214 AlignViewport vp = af.getViewport();
1215 if (vp.getSelectionGroup() != null
1216 && vp.getSelectionGroup().getSize() > 0)
1218 iSize = vp.getSelectionGroup().getSize();
1219 dataset = new SequenceI[iSize];
1220 seqs = vp.getSelectionGroup().getSequencesInOrder(vp.getAlignment());
1224 iSize = vp.getAlignment().getHeight();
1225 seqs = vp.getAlignment().getSequencesArray();
1228 dataset = new SequenceI[iSize];
1229 for (int i = 0; i < iSize; i++)
1231 dataset[i] = seqs[i].getDatasetSequence();
1234 cancelDAS.setEnabled(true);
1235 dasFeatureFetcher = new jalview.ws.DasSequenceFeatureFetcher(dataset,
1236 this, selectedSources, checkDbRefs, promptFetchDbRefs);
1237 af.getViewport().setShowSequenceFeatures(true);
1238 af.showSeqFeatures.setSelected(true);
1242 * blocking call to initialise the das source browser
1244 public void initDasSources()
1246 dassourceBrowser.initDasSources();
1250 * examine the current list of das sources and return any matching the given
1251 * nicknames in sources
1254 * Vector of Strings to resolve to DAS source nicknames.
1255 * @return sources that are present in source list.
1257 public List<jalviewSourceI> resolveSourceNicknames(Vector sources)
1259 return dassourceBrowser.sourceRegistry.resolveSourceNicknames(sources);
1263 * get currently selected das sources. ensure you have called initDasSources
1264 * before calling this.
1266 * @return vector of selected das source nicknames
1268 public Vector getSelectedSources()
1270 return dassourceBrowser.getSelectedSources();
1274 * properly initialise DAS fetcher and then initiate a new thread to fetch
1275 * features from the named sources (rather than any turned on by default)
1279 * if true then runs in same thread, otherwise passes to the Swing
1282 public void fetchDasFeatures(Vector sources, boolean block)
1285 List<jalviewSourceI> resolved = dassourceBrowser.sourceRegistry
1286 .resolveSourceNicknames(sources);
1287 if (resolved.size() == 0)
1289 resolved = dassourceBrowser.getSelectedSources();
1291 if (resolved.size() > 0)
1293 final List<jalviewSourceI> dassources = resolved;
1294 fetchDAS.setEnabled(false);
1295 // cancelDAS.setEnabled(true); doDasFetch does this.
1296 Runnable fetcher = new Runnable()
1301 doDasFeatureFetch(dassources, true, false);
1311 SwingUtilities.invokeLater(fetcher);
1316 public void saveDAS_actionPerformed(ActionEvent e)
1319 .saveProperties(jalview.bin.Cache.applicationProperties);
1322 public void complete()
1324 fetchDAS.setEnabled(true);
1325 cancelDAS.setEnabled(false);
1326 dassourceBrowser.setGuiEnabled(true);
1330 public void cancelDAS_actionPerformed(ActionEvent e)
1332 if (dasFeatureFetcher != null)
1334 dasFeatureFetcher.cancel();
1339 public void noDasSourceActive()
1342 JOptionPane.showInternalConfirmDialog(Desktop.desktop,
1343 MessageManager.getString("label.no_das_sources_selected_warn"),
1344 MessageManager.getString("label.no_das_sources_selected_title"), JOptionPane.DEFAULT_OPTION,
1345 JOptionPane.INFORMATION_MESSAGE);
1348 // ///////////////////////////////////////////////////////////////////////
1349 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
1350 // ///////////////////////////////////////////////////////////////////////
1351 class FeatureTableModel extends AbstractTableModel
1353 FeatureTableModel(Object[][] data)
1358 private String[] columnNames =
1359 { "Feature Type", "Colour", "Display" };
1361 private Object[][] data;
1363 public Object[][] getData()
1368 public void setData(Object[][] data)
1373 public int getColumnCount()
1375 return columnNames.length;
1378 public Object[] getRow(int row)
1383 public int getRowCount()
1388 public String getColumnName(int col)
1390 return columnNames[col];
1393 public Object getValueAt(int row, int col)
1395 return data[row][col];
1398 public Class getColumnClass(int c)
1400 return getValueAt(0, c).getClass();
1403 public boolean isCellEditable(int row, int col)
1405 return col == 0 ? false : true;
1408 public void setValueAt(Object value, int row, int col)
1410 data[row][col] = value;
1411 fireTableCellUpdated(row, col);
1412 updateFeatureRenderer(data);
1417 class ColorRenderer extends JLabel implements TableCellRenderer
1419 javax.swing.border.Border unselectedBorder = null;
1421 javax.swing.border.Border selectedBorder = null;
1423 final String baseTT = "Click to edit, right/apple click for menu.";
1425 public ColorRenderer()
1427 setOpaque(true); // MUST do this for background to show up.
1428 setHorizontalTextPosition(SwingConstants.CENTER);
1429 setVerticalTextPosition(SwingConstants.CENTER);
1432 public Component getTableCellRendererComponent(JTable table,
1433 Object color, boolean isSelected, boolean hasFocus, int row,
1436 // JLabel comp = new JLabel();
1440 // setBounds(getBounds());
1442 setToolTipText(baseTT);
1443 setBackground(table.getBackground());
1444 if (color instanceof GraduatedColor)
1446 Rectangle cr = table.getCellRect(row, column, false);
1447 FeatureSettings.renderGraduatedColor(this, (GraduatedColor) color,
1448 (int) cr.getWidth(), (int) cr.getHeight());
1455 newColor = (Color) color;
1457 setBackground(newColor);
1458 // comp.setToolTipText("RGB value: " + newColor.getRed() + ", "
1459 // + newColor.getGreen() + ", " + newColor.getBlue());
1463 if (selectedBorder == null)
1465 selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1466 table.getSelectionBackground());
1469 setBorder(selectedBorder);
1473 if (unselectedBorder == null)
1475 unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1476 table.getBackground());
1479 setBorder(unselectedBorder);
1487 * update comp using rendering settings from gcol
1492 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol)
1494 int w = comp.getWidth(), h = comp.getHeight();
1497 w = (int) comp.getPreferredSize().getWidth();
1498 h = (int) comp.getPreferredSize().getHeight();
1505 renderGraduatedColor(comp, gcol, w, h);
1508 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol,
1511 boolean thr = false;
1514 if (gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD)
1518 tt += "Thresholded (Above " + gcol.getThresh() + ") ";
1520 if (gcol.getThreshType() == AnnotationColourGradient.BELOW_THRESHOLD)
1524 tt += "Thresholded (Below " + gcol.getThresh() + ") ";
1526 if (gcol.isColourByLabel())
1528 tt = "Coloured by label text. " + tt;
1538 Color newColor = gcol.getMaxColor();
1539 comp.setBackground(newColor);
1540 // System.err.println("Width is " + w / 2);
1541 Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w, h, thr);
1542 comp.setIcon(ficon);
1543 // tt+="RGB value: Max (" + newColor.getRed() + ", "
1544 // + newColor.getGreen() + ", " + newColor.getBlue()
1545 // + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen()
1546 // + ", " + minCol.getBlue() + ")");
1548 comp.setHorizontalAlignment(SwingConstants.CENTER);
1550 if (tt.length() > 0)
1552 if (comp.getToolTipText() == null)
1554 comp.setToolTipText(tt);
1558 comp.setToolTipText(tt + " " + comp.getToolTipText());
1564 class FeatureIcon implements Icon
1566 GraduatedColor gcol;
1570 boolean midspace = false;
1572 int width = 50, height = 20;
1574 int s1, e1; // start and end of midpoint band for thresholded symbol
1576 Color mpcolour = Color.white;
1578 FeatureIcon(GraduatedColor gfc, Color bg, int w, int h, boolean mspace)
1597 public int getIconWidth()
1602 public int getIconHeight()
1607 public void paintIcon(Component c, Graphics g, int x, int y)
1610 if (gcol.isColourByLabel())
1613 g.fillRect(0, 0, width, height);
1614 // need an icon here.
1615 g.setColor(gcol.getMaxColor());
1617 g.setFont(new Font("Verdana", Font.PLAIN, 9));
1619 // g.setFont(g.getFont().deriveFont(
1620 // AffineTransform.getScaleInstance(
1621 // width/g.getFontMetrics().stringWidth("Label"),
1622 // height/g.getFontMetrics().getHeight())));
1624 g.drawString(MessageManager.getString("label.label"), 0, 0);
1629 Color minCol = gcol.getMinColor();
1631 g.fillRect(0, 0, s1, height);
1634 g.setColor(Color.white);
1635 g.fillRect(s1, 0, e1 - s1, height);
1637 g.setColor(gcol.getMaxColor());
1638 g.fillRect(0, e1, width - e1, height);
1643 class ColorEditor extends AbstractCellEditor implements TableCellEditor,
1648 GraduatedColor currentGColor;
1650 FeatureColourChooser chooser;
1658 JColorChooser colorChooser;
1662 protected static final String EDIT = "edit";
1664 int selectedRow = 0;
1666 public ColorEditor(FeatureSettings me)
1669 // Set up the editor (from the table's point of view),
1670 // which is a button.
1671 // This button brings up the color chooser dialog,
1672 // which is the editor from the user's point of view.
1673 button = new JButton();
1674 button.setActionCommand(EDIT);
1675 button.addActionListener(this);
1676 button.setBorderPainted(false);
1677 // Set up the dialog that the button brings up.
1678 colorChooser = new JColorChooser();
1679 dialog = JColorChooser.createDialog(button, "Select new Colour", true, // modal
1680 colorChooser, this, // OK button handler
1681 null); // no CANCEL button handler
1685 * Handles events from the editor button and from the dialog's OK button.
1687 public void actionPerformed(ActionEvent e)
1690 if (EDIT.equals(e.getActionCommand()))
1692 // The user has clicked the cell, so
1693 // bring up the dialog.
1694 if (currentColor != null)
1696 // bring up simple color chooser
1697 button.setBackground(currentColor);
1698 colorChooser.setColor(currentColor);
1699 dialog.setVisible(true);
1703 // bring up graduated chooser.
1704 chooser = new FeatureColourChooser(me.fr, type);
1705 chooser.setRequestFocusEnabled(true);
1706 chooser.requestFocus();
1707 chooser.addActionListener(this);
1709 // Make the renderer reappear.
1710 fireEditingStopped();
1714 { // User pressed dialog's "OK" button.
1715 if (currentColor != null)
1717 currentColor = colorChooser.getColor();
1721 // class cast exceptions may be raised if the chooser created on a
1722 // non-graduated color
1723 currentGColor = (GraduatedColor) chooser.getLastColour();
1725 me.table.setValueAt(getCellEditorValue(), selectedRow, 1);
1726 fireEditingStopped();
1727 me.table.validate();
1731 // Implement the one CellEditor method that AbstractCellEditor doesn't.
1732 public Object getCellEditorValue()
1734 if (currentColor == null)
1736 return currentGColor;
1738 return currentColor;
1741 // Implement the one method defined by TableCellEditor.
1742 public Component getTableCellEditorComponent(JTable table, Object value,
1743 boolean isSelected, int row, int column)
1745 currentGColor = null;
1746 currentColor = null;
1747 this.selectedRow = row;
1748 type = me.table.getValueAt(row, 0).toString();
1749 button.setOpaque(true);
1750 button.setBackground(me.getBackground());
1751 if (value instanceof GraduatedColor)
1753 currentGColor = (GraduatedColor) value;
1754 JLabel btn = new JLabel();
1755 btn.setSize(button.getSize());
1756 FeatureSettings.renderGraduatedColor(btn, currentGColor);
1757 button.setBackground(btn.getBackground());
1758 button.setIcon(btn.getIcon());
1759 button.setText(btn.getText());
1764 button.setIcon(null);
1765 currentColor = (Color) value;
1766 button.setBackground(currentColor);