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("<html>"
146 .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/>")
148 scrollPane.setViewportView(table);
150 dassourceBrowser = new DasSourceBrowser(this);
151 dasSettingsPane.add(dassourceBrowser, BorderLayout.CENTER);
153 if (af.getViewport().featuresDisplayed == null
154 || fr.renderOrder == null)
156 fr.findAllFeatures(true); // display everything!
160 final PropertyChangeListener change;
161 final FeatureSettings fs = this;
162 fr.addPropertyChangeListener(change = new PropertyChangeListener()
164 public void propertyChange(PropertyChangeEvent evt)
166 if (!fs.resettingTable && !fs.handlingUpdate)
168 fs.handlingUpdate = true;
169 fs.resetTable(null); // new groups may be added with new seuqence
170 // feature types only
171 fs.handlingUpdate = false;
177 frame = new JInternalFrame();
178 frame.setContentPane(this);
179 if (new jalview.util.Platform().isAMac())
181 Desktop.addInternalFrame(frame,
182 MessageManager.getString("label.sequence_feature_settings"),
187 Desktop.addInternalFrame(frame,
188 MessageManager.getString("label.sequence_feature_settings"),
192 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
194 public void internalFrameClosed(
195 javax.swing.event.InternalFrameEvent evt)
197 fr.removePropertyChangeListener(change);
198 dassourceBrowser.fs = null;
201 frame.setLayer(JLayeredPane.PALETTE_LAYER);
204 protected void popupSort(final int selectedRow, final String type,
205 final Object typeCol, final Hashtable minmax, int x, int y)
207 JPopupMenu men = new JPopupMenu(MessageManager.formatMessage(
208 "label.settings_for_param", new String[]
210 JMenuItem scr = new JMenuItem(
211 MessageManager.getString("label.sort_by_score"));
213 final FeatureSettings me = this;
214 scr.addActionListener(new ActionListener()
217 public void actionPerformed(ActionEvent e)
219 me.sortByScore(new String[]
224 JMenuItem dens = new JMenuItem(
225 MessageManager.getString("label.sort_by_density"));
226 dens.addActionListener(new ActionListener()
229 public void actionPerformed(ActionEvent e)
231 me.sortByDens(new String[]
239 final Object typeMinMax = minmax.get(type);
241 * final JCheckBoxMenuItem chb = new JCheckBoxMenuItem("Vary Height"); //
242 * this is broken at the moment and isn't that useful anyway!
243 * chb.setSelected(minmax.get(type) != null); chb.addActionListener(new
246 * public void actionPerformed(ActionEvent e) {
247 * chb.setState(chb.getState()); if (chb.getState()) { minmax.put(type,
248 * null); } else { minmax.put(type, typeMinMax); } }
254 if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null)
256 // if (table.getValueAt(row, column));
257 // graduated colourschemes for those where minmax exists for the
258 // positional features
259 final JCheckBoxMenuItem mxcol = new JCheckBoxMenuItem(
261 mxcol.setSelected(!(typeCol instanceof Color));
263 mxcol.addActionListener(new ActionListener()
265 JColorChooser colorChooser;
267 public void actionPerformed(ActionEvent e)
269 if (e.getSource() == mxcol)
271 if (typeCol instanceof Color)
273 FeatureColourChooser fc = new FeatureColourChooser(me.fr,
275 fc.addActionListener(this);
279 // bring up simple color chooser
280 colorChooser = new JColorChooser();
281 JDialog dialog = JColorChooser.createDialog(me,
282 "Select new Colour", true, // modal
283 colorChooser, this, // OK button handler
284 null); // no CANCEL button handler
285 colorChooser.setColor(((GraduatedColor) typeCol)
287 dialog.setVisible(true);
292 if (e.getSource() instanceof FeatureColourChooser)
294 FeatureColourChooser fc = (FeatureColourChooser) e
296 table.setValueAt(fc.getLastColour(), selectedRow, 1);
301 // probably the color chooser!
302 table.setValueAt(colorChooser.getColor(), selectedRow, 1);
304 me.updateFeatureRenderer(
305 ((FeatureTableModel) table.getModel()).getData(),
314 JMenuItem selCols = new JMenuItem(
315 MessageManager.getString("label.select_columns_containing"));
316 selCols.addActionListener(new ActionListener()
320 public void actionPerformed(ActionEvent arg0)
322 fr.ap.alignFrame.avc.markColumnsContainingFeatures(false, false,
326 JMenuItem clearCols = new JMenuItem(
327 MessageManager.getString("label.select_columns_not_containing"));
328 clearCols.addActionListener(new ActionListener()
332 public void actionPerformed(ActionEvent arg0)
334 fr.ap.alignFrame.avc.markColumnsContainingFeatures(true, false,
340 men.show(table, x, y);
344 * true when Feature Settings are updating from feature renderer
346 private boolean handlingUpdate = false;
349 * contains a float[3] for each feature type string. created by setTableData
351 Hashtable typeWidth = null;
353 synchronized public void setTableData()
355 if (fr.featureGroups == null)
357 fr.featureGroups = new Hashtable();
359 Vector allFeatures = new Vector();
360 Vector allGroups = new Vector();
361 SequenceFeature[] tmpfeatures;
363 for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
365 if (af.getViewport().getAlignment().getSequenceAt(i)
366 .getDatasetSequence().getSequenceFeatures() == null)
371 tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
372 .getDatasetSequence().getSequenceFeatures();
375 while (index < tmpfeatures.length)
377 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
383 if (tmpfeatures[index].getFeatureGroup() != null)
385 group = tmpfeatures[index].featureGroup;
386 if (!allGroups.contains(group))
388 allGroups.addElement(group);
391 checkGroupState(group);
396 if (!allFeatures.contains(tmpfeatures[index].getType()))
398 allFeatures.addElement(tmpfeatures[index].getType());
412 * @return true if group has been seen before and is already added to set.
414 private boolean checkGroupState(String group)
417 if (fr.featureGroups.containsKey(group))
419 visible = ((Boolean) fr.featureGroups.get(group)).booleanValue();
423 visible = true; // new group is always made visible
426 if (groupPanel == null)
428 groupPanel = new JPanel();
431 boolean alreadyAdded = false;
432 for (int g = 0; g < groupPanel.getComponentCount(); g++)
434 if (((JCheckBox) groupPanel.getComponent(g)).getText().equals(group))
437 ((JCheckBox) groupPanel.getComponent(g)).setSelected(visible);
448 fr.featureGroups.put(group, new Boolean(visible));
449 final String grp = group;
450 final JCheckBox check = new JCheckBox(group, visible);
451 check.setFont(new Font("Serif", Font.BOLD, 12));
452 check.addItemListener(new ItemListener()
454 public void itemStateChanged(ItemEvent evt)
456 fr.featureGroups.put(check.getText(),
457 new Boolean(check.isSelected()));
458 af.alignPanel.seqPanel.seqCanvas.repaint();
459 if (af.alignPanel.overviewPanel != null)
461 af.alignPanel.overviewPanel.updateOverviewImage();
464 resetTable(new String[]
468 groupPanel.add(check);
472 boolean resettingTable = false;
474 synchronized void resetTable(String[] groupChanged)
476 if (resettingTable == true)
480 resettingTable = true;
481 typeWidth = new Hashtable();
482 // TODO: change avWidth calculation to 'per-sequence' average and use long
484 float[] avWidth = null;
485 SequenceFeature[] tmpfeatures;
486 String group = null, type;
487 Vector visibleChecks = new Vector();
489 // Find out which features should be visible depending on which groups
490 // are selected / deselected
491 // and recompute average width ordering
492 for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
495 tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
496 .getDatasetSequence().getSequenceFeatures();
497 if (tmpfeatures == null)
503 while (index < tmpfeatures.length)
505 group = tmpfeatures[index].featureGroup;
507 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
513 if (group == null || fr.featureGroups.get(group) == null
514 || ((Boolean) fr.featureGroups.get(group)).booleanValue())
517 checkGroupState(group);
518 type = tmpfeatures[index].getType();
519 if (!visibleChecks.contains(type))
521 visibleChecks.addElement(type);
524 if (!typeWidth.containsKey(tmpfeatures[index].getType()))
526 typeWidth.put(tmpfeatures[index].getType(),
527 avWidth = new float[3]);
531 avWidth = (float[]) typeWidth.get(tmpfeatures[index].getType());
534 if (tmpfeatures[index].getBegin() > tmpfeatures[index].getEnd())
536 avWidth[1] += 1 + tmpfeatures[index].getBegin()
537 - tmpfeatures[index].getEnd();
541 avWidth[1] += 1 + tmpfeatures[index].getEnd()
542 - tmpfeatures[index].getBegin();
548 int fSize = visibleChecks.size();
549 Object[][] data = new Object[fSize][3];
552 if (fr.renderOrder != null)
555 fr.findAllFeatures(groupChanged != null); // prod to update
556 // colourschemes. but don't
558 // First add the checks in the previous render order,
559 // in case the window has been closed and reopened
560 for (int ro = fr.renderOrder.length - 1; ro > -1; ro--)
562 type = fr.renderOrder[ro];
564 if (!visibleChecks.contains(type))
569 data[dataIndex][0] = type;
570 data[dataIndex][1] = fr.getFeatureStyle(type);
571 data[dataIndex][2] = new Boolean(
572 af.getViewport().featuresDisplayed.containsKey(type));
574 visibleChecks.removeElement(type);
578 fSize = visibleChecks.size();
579 for (int i = 0; i < fSize; i++)
581 // These must be extra features belonging to the group
582 // which was just selected
583 type = visibleChecks.elementAt(i).toString();
584 data[dataIndex][0] = type;
586 data[dataIndex][1] = fr.getFeatureStyle(type);
587 if (data[dataIndex][1] == null)
589 // "Colour has been updated in another view!!"
590 fr.renderOrder = null;
594 data[dataIndex][2] = new Boolean(true);
598 if (originalData == null)
600 originalData = new Object[data.length][3];
601 for (int i = 0; i < data.length; i++)
603 System.arraycopy(data[i], 0, originalData[i], 0, 3);
607 table.setModel(new FeatureTableModel(data));
608 table.getColumnModel().getColumn(0).setPreferredWidth(200);
610 if (groupPanel != null)
612 groupPanel.setLayout(new GridLayout(fr.featureGroups.size() / 4 + 1,
615 groupPanel.validate();
616 bigPanel.add(groupPanel, BorderLayout.NORTH);
619 updateFeatureRenderer(data, groupChanged != null);
620 resettingTable = false;
624 * reorder data based on the featureRenderers global priority list.
628 private void ensureOrder(Object[][] data)
630 boolean sort = false;
631 float[] order = new float[data.length];
632 for (int i = 0; i < order.length; i++)
634 order[i] = fr.getOrder(data[i][0].toString());
636 order[i] = fr.setOrder(data[i][0].toString(), i / order.length);
638 sort = sort || order[i - 1] > order[i];
641 jalview.util.QuickSort.sort(order, data);
646 JalviewFileChooser chooser = new JalviewFileChooser(
647 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
648 { "fc" }, new String[]
649 { "Sequence Feature Colours" }, "Sequence Feature Colours");
650 chooser.setFileView(new jalview.io.JalviewFileView());
651 chooser.setDialogTitle("Load Feature Colours");
652 chooser.setToolTipText(MessageManager.getString("action.load"));
654 int value = chooser.showOpenDialog(this);
656 if (value == JalviewFileChooser.APPROVE_OPTION)
658 File file = chooser.getSelectedFile();
662 InputStreamReader in = new InputStreamReader(new FileInputStream(
665 jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
666 jucs = (jalview.schemabinding.version2.JalviewUserColours) jucs
669 for (int i = jucs.getColourCount() - 1; i >= 0; i--)
672 jalview.schemabinding.version2.Colour newcol = jucs.getColour(i);
675 Color mincol = null, maxcol = null;
678 mincol = new Color(Integer.parseInt(newcol.getMinRGB(), 16));
679 maxcol = new Color(Integer.parseInt(newcol.getRGB(), 16));
681 } catch (Exception e)
683 Cache.log.warn("Couldn't parse out graduated feature color.",
686 GraduatedColor gcol = new GraduatedColor(mincol, maxcol,
687 newcol.getMin(), newcol.getMax());
688 if (newcol.hasAutoScale())
690 gcol.setAutoScaled(newcol.getAutoScale());
692 if (newcol.hasColourByLabel())
694 gcol.setColourByLabel(newcol.getColourByLabel());
696 if (newcol.hasThreshold())
698 gcol.setThresh(newcol.getThreshold());
699 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD); // default
701 if (newcol.getThreshType().length() > 0)
703 String ttyp = newcol.getThreshType();
704 if (ttyp.equalsIgnoreCase("NONE"))
706 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD);
708 if (ttyp.equalsIgnoreCase("ABOVE"))
710 gcol.setThreshType(AnnotationColourGradient.ABOVE_THRESHOLD);
712 if (ttyp.equalsIgnoreCase("BELOW"))
714 gcol.setThreshType(AnnotationColourGradient.BELOW_THRESHOLD);
717 fr.setColour(name = newcol.getName(), gcol);
721 fr.setColour(name = jucs.getColour(i).getName(), new Color(
722 Integer.parseInt(jucs.getColour(i).getRGB(), 16)));
724 fr.setOrder(name, (i == 0) ? 0 : i / jucs.getColourCount());
729 Object[][] data = ((FeatureTableModel) table.getModel())
732 updateFeatureRenderer(data, false);
735 } catch (Exception ex)
737 System.out.println("Error loading User Colour File\n" + ex);
744 JalviewFileChooser chooser = new JalviewFileChooser(
745 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
746 { "fc" }, new String[]
747 { "Sequence Feature Colours" }, "Sequence Feature Colours");
748 chooser.setFileView(new jalview.io.JalviewFileView());
749 chooser.setDialogTitle("Save Feature Colour Scheme");
750 chooser.setToolTipText(MessageManager.getString("action.save"));
752 int value = chooser.showSaveDialog(this);
754 if (value == JalviewFileChooser.APPROVE_OPTION)
756 String choice = chooser.getSelectedFile().getPath();
757 jalview.schemabinding.version2.JalviewUserColours ucs = new jalview.schemabinding.version2.JalviewUserColours();
758 ucs.setSchemeName("Sequence Features");
761 PrintWriter out = new PrintWriter(new OutputStreamWriter(
762 new FileOutputStream(choice), "UTF-8"));
764 Iterator e = fr.featureColours.keySet().iterator();
765 float[] sortOrder = new float[fr.featureColours.size()];
766 String[] sortTypes = new String[fr.featureColours.size()];
770 sortTypes[i] = e.next().toString();
771 sortOrder[i] = fr.getOrder(sortTypes[i]);
774 jalview.util.QuickSort.sort(sortOrder, sortTypes);
778 for (i = 0; i < sortTypes.length; i++)
780 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
781 col.setName(sortTypes[i]);
782 col.setRGB(jalview.util.Format.getHexString(fr.getColour(col
784 fcol = fr.getFeatureStyle(sortTypes[i]);
785 if (fcol instanceof GraduatedColor)
787 gcol = (GraduatedColor) fcol;
788 col.setMin(gcol.getMin());
789 col.setMax(gcol.getMax());
790 col.setMinRGB(jalview.util.Format.getHexString(gcol
792 col.setAutoScale(gcol.isAutoScale());
793 col.setThreshold(gcol.getThresh());
794 col.setColourByLabel(gcol.isColourByLabel());
795 switch (gcol.getThreshType())
797 case AnnotationColourGradient.NO_THRESHOLD:
798 col.setThreshType("NONE");
800 case AnnotationColourGradient.ABOVE_THRESHOLD:
801 col.setThreshType("ABOVE");
803 case AnnotationColourGradient.BELOW_THRESHOLD:
804 col.setThreshType("BELOW");
812 } catch (Exception ex)
814 ex.printStackTrace();
819 public void invertSelection()
821 for (int i = 0; i < table.getRowCount(); i++)
823 Boolean value = (Boolean) table.getValueAt(i, 2);
825 table.setValueAt(new Boolean(!value.booleanValue()), i, 2);
829 public void orderByAvWidth()
831 if (table == null || table.getModel() == null)
833 Object[][] data = ((FeatureTableModel) table.getModel()).getData();
834 float[] width = new float[data.length];
838 for (int i = 0; i < data.length; i++)
840 awidth = (float[]) typeWidth.get(data[i][0]);
843 width[i] = awidth[1] / awidth[0];// *awidth[0]*awidth[2]; - better
844 // weight - but have to make per
845 // sequence, too (awidth[2])
846 // if (width[i]==1) // hack to distinguish single width sequences.
856 boolean sort = false;
857 for (int i = 0; i < width.length; i++)
859 // awidth = (float[]) typeWidth.get(data[i][0]);
862 width[i] = fr.getOrder(data[i][0].toString());
865 width[i] = fr.setOrder(data[i][0].toString(), i / data.length);
870 width[i] /= max; // normalize
871 fr.setOrder(data[i][0].toString(), width[i]); // store for later
874 sort = sort || width[i - 1] > width[i];
877 jalview.util.QuickSort.sort(width, data);
878 // update global priority order
880 updateFeatureRenderer(data, false);
888 frame.setClosed(true);
889 } catch (Exception exe)
895 public void updateFeatureRenderer(Object[][] data)
897 updateFeatureRenderer(data, true);
900 private void updateFeatureRenderer(Object[][] data, boolean visibleNew)
902 fr.setFeaturePriority(data, visibleNew);
903 af.alignPanel.paintAlignment(true);
906 int selectedRow = -1;
908 JTabbedPane tabbedPane = new JTabbedPane();
910 BorderLayout borderLayout1 = new BorderLayout();
912 BorderLayout borderLayout2 = new BorderLayout();
914 BorderLayout borderLayout3 = new BorderLayout();
916 JPanel bigPanel = new JPanel();
918 BorderLayout borderLayout4 = new BorderLayout();
920 JButton invert = new JButton();
922 JPanel buttonPanel = new JPanel();
924 JButton cancel = new JButton();
926 JButton ok = new JButton();
928 JButton loadColours = new JButton();
930 JButton saveColours = new JButton();
932 JPanel dasButtonPanel = new JPanel();
934 JButton fetchDAS = new JButton();
936 JButton saveDAS = new JButton();
938 JButton cancelDAS = new JButton();
940 JButton optimizeOrder = new JButton();
942 JButton sortByScore = new JButton();
944 JButton sortByDens = new JButton();
946 JPanel transbuttons = new JPanel(new GridLayout(4, 1));
948 private void jbInit() throws Exception
950 this.setLayout(borderLayout1);
951 settingsPane.setLayout(borderLayout2);
952 dasSettingsPane.setLayout(borderLayout3);
953 bigPanel.setLayout(borderLayout4);
954 invert.setFont(JvSwingUtils.getLabelFont());
955 invert.setText(MessageManager.getString("label.invert_selection"));
956 invert.addActionListener(new ActionListener()
958 public void actionPerformed(ActionEvent e)
963 optimizeOrder.setFont(JvSwingUtils.getLabelFont());
964 optimizeOrder.setText(MessageManager.getString("label.optimise_order"));
965 optimizeOrder.addActionListener(new ActionListener()
967 public void actionPerformed(ActionEvent e)
972 sortByScore.setFont(JvSwingUtils.getLabelFont());
974 .setText(MessageManager.getString("label.seq_sort_by_score"));
975 sortByScore.addActionListener(new ActionListener()
977 public void actionPerformed(ActionEvent e)
982 sortByDens.setFont(JvSwingUtils.getLabelFont());
983 sortByDens.setText(MessageManager
984 .getString("label.sequence_sort_by_density"));
985 sortByDens.addActionListener(new ActionListener()
987 public void actionPerformed(ActionEvent e)
992 cancel.setFont(JvSwingUtils.getLabelFont());
993 cancel.setText(MessageManager.getString("action.cancel"));
994 cancel.addActionListener(new ActionListener()
996 public void actionPerformed(ActionEvent e)
998 updateFeatureRenderer(originalData);
1002 ok.setFont(JvSwingUtils.getLabelFont());
1003 ok.setText(MessageManager.getString("action.ok"));
1004 ok.addActionListener(new ActionListener()
1006 public void actionPerformed(ActionEvent e)
1011 loadColours.setFont(JvSwingUtils.getLabelFont());
1012 loadColours.setText(MessageManager.getString("label.load_colours"));
1013 loadColours.addActionListener(new ActionListener()
1015 public void actionPerformed(ActionEvent e)
1020 saveColours.setFont(JvSwingUtils.getLabelFont());
1021 saveColours.setText(MessageManager.getString("label.save_colours"));
1022 saveColours.addActionListener(new ActionListener()
1024 public void actionPerformed(ActionEvent e)
1029 transparency.addChangeListener(new ChangeListener()
1031 public void stateChanged(ChangeEvent evt)
1033 fr.setTransparency((float) (100 - transparency.getValue()) / 100f);
1034 af.alignPanel.paintAlignment(true);
1038 transparency.setMaximum(70);
1039 fetchDAS.setText(MessageManager.getString("label.fetch_das_features"));
1040 fetchDAS.addActionListener(new ActionListener()
1042 public void actionPerformed(ActionEvent e)
1044 fetchDAS_actionPerformed(e);
1047 saveDAS.setText(MessageManager.getString("action.save_as_default"));
1048 saveDAS.addActionListener(new ActionListener()
1050 public void actionPerformed(ActionEvent e)
1052 saveDAS_actionPerformed(e);
1055 dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
1056 dasSettingsPane.setBorder(null);
1057 cancelDAS.setEnabled(false);
1058 cancelDAS.setText(MessageManager.getString("action.cancel_fetch"));
1059 cancelDAS.addActionListener(new ActionListener()
1061 public void actionPerformed(ActionEvent e)
1063 cancelDAS_actionPerformed(e);
1066 this.add(tabbedPane, java.awt.BorderLayout.CENTER);
1067 tabbedPane.addTab("Feature Settings", settingsPane);
1068 tabbedPane.addTab("DAS Settings", dasSettingsPane);
1069 bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
1070 transbuttons.add(optimizeOrder);
1071 transbuttons.add(invert);
1072 transbuttons.add(sortByScore);
1073 transbuttons.add(sortByDens);
1074 transPanel.add(transparency);
1075 transPanel.add(transbuttons);
1076 buttonPanel.add(ok);
1077 buttonPanel.add(cancel);
1078 buttonPanel.add(loadColours);
1079 buttonPanel.add(saveColours);
1080 bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
1081 dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
1082 dasButtonPanel.add(fetchDAS);
1083 dasButtonPanel.add(cancelDAS);
1084 dasButtonPanel.add(saveDAS);
1085 settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);
1086 settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
1089 protected void sortByDens(String[] typ)
1091 sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY);
1094 protected void sortBy(String[] typ, String methodText, final String method)
1098 typ = getDisplayedFeatureTypes();
1100 String gps[] = null;
1101 gps = getDisplayedFeatureGroups();
1104 ArrayList types = new ArrayList();
1105 for (int i = 0; i < typ.length; i++)
1111 typ = new String[types.size()];
1117 ArrayList grps = new ArrayList();
1119 for (int i = 0; i < gps.length; i++)
1126 gps = new String[grps.size()];
1129 AlignmentPanel alignPanel = af.alignPanel;
1130 AlignmentI al = alignPanel.av.getAlignment();
1133 SequenceGroup sg = alignPanel.av.getSelectionGroup();
1136 start = sg.getStartRes();
1137 stop = sg.getEndRes();
1142 stop = al.getWidth();
1144 SequenceI[] oldOrder = al.getSequencesArray();
1145 AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
1146 af.addHistoryItem(new OrderCommand(methodText, oldOrder, alignPanel.av
1148 alignPanel.paintAlignment(true);
1152 protected void sortByScore(String[] typ)
1154 sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE);
1157 private String[] getDisplayedFeatureTypes()
1159 String[] typ = null;
1162 synchronized (fr.renderOrder)
1164 typ = new String[fr.renderOrder.length];
1165 System.arraycopy(fr.renderOrder, 0, typ, 0, typ.length);
1166 for (int i = 0; i < typ.length; i++)
1168 if (af.viewport.featuresDisplayed.get(typ[i]) == null)
1178 private String[] getDisplayedFeatureGroups()
1180 String[] gps = null;
1181 ArrayList<String> _gps = new ArrayList<String>();
1185 if (fr.featureGroups != null)
1187 Iterator en = fr.featureGroups.keySet().iterator();
1189 boolean valid = false;
1190 while (en.hasNext())
1192 String gp = (String) en.next();
1193 Boolean on = (Boolean) fr.featureGroups.get(gp);
1194 if (on != null && on.booleanValue())
1206 gps = new String[_gps.size()];
1214 public void fetchDAS_actionPerformed(ActionEvent e)
1216 fetchDAS.setEnabled(false);
1217 cancelDAS.setEnabled(true);
1218 dassourceBrowser.setGuiEnabled(false);
1219 Vector selectedSources = dassourceBrowser.getSelectedSources();
1220 doDasFeatureFetch(selectedSources, true, true);
1224 * get the features from selectedSources for all or the current selection
1226 * @param selectedSources
1227 * @param checkDbRefs
1228 * @param promptFetchDbRefs
1230 private void doDasFeatureFetch(List<jalviewSourceI> selectedSources,
1231 boolean checkDbRefs, boolean promptFetchDbRefs)
1233 SequenceI[] dataset, seqs;
1235 AlignViewport vp = af.getViewport();
1236 if (vp.getSelectionGroup() != null
1237 && vp.getSelectionGroup().getSize() > 0)
1239 iSize = vp.getSelectionGroup().getSize();
1240 dataset = new SequenceI[iSize];
1241 seqs = vp.getSelectionGroup().getSequencesInOrder(vp.getAlignment());
1245 iSize = vp.getAlignment().getHeight();
1246 seqs = vp.getAlignment().getSequencesArray();
1249 dataset = new SequenceI[iSize];
1250 for (int i = 0; i < iSize; i++)
1252 dataset[i] = seqs[i].getDatasetSequence();
1255 cancelDAS.setEnabled(true);
1256 dasFeatureFetcher = new jalview.ws.DasSequenceFeatureFetcher(dataset,
1257 this, selectedSources, checkDbRefs, promptFetchDbRefs);
1258 af.getViewport().setShowSequenceFeatures(true);
1259 af.showSeqFeatures.setSelected(true);
1263 * blocking call to initialise the das source browser
1265 public void initDasSources()
1267 dassourceBrowser.initDasSources();
1271 * examine the current list of das sources and return any matching the given
1272 * nicknames in sources
1275 * Vector of Strings to resolve to DAS source nicknames.
1276 * @return sources that are present in source list.
1278 public List<jalviewSourceI> resolveSourceNicknames(Vector sources)
1280 return dassourceBrowser.sourceRegistry.resolveSourceNicknames(sources);
1284 * get currently selected das sources. ensure you have called initDasSources
1285 * before calling this.
1287 * @return vector of selected das source nicknames
1289 public Vector getSelectedSources()
1291 return dassourceBrowser.getSelectedSources();
1295 * properly initialise DAS fetcher and then initiate a new thread to fetch
1296 * features from the named sources (rather than any turned on by default)
1300 * if true then runs in same thread, otherwise passes to the Swing
1303 public void fetchDasFeatures(Vector sources, boolean block)
1306 List<jalviewSourceI> resolved = dassourceBrowser.sourceRegistry
1307 .resolveSourceNicknames(sources);
1308 if (resolved.size() == 0)
1310 resolved = dassourceBrowser.getSelectedSources();
1312 if (resolved.size() > 0)
1314 final List<jalviewSourceI> dassources = resolved;
1315 fetchDAS.setEnabled(false);
1316 // cancelDAS.setEnabled(true); doDasFetch does this.
1317 Runnable fetcher = new Runnable()
1322 doDasFeatureFetch(dassources, true, false);
1332 SwingUtilities.invokeLater(fetcher);
1337 public void saveDAS_actionPerformed(ActionEvent e)
1340 .saveProperties(jalview.bin.Cache.applicationProperties);
1343 public void complete()
1345 fetchDAS.setEnabled(true);
1346 cancelDAS.setEnabled(false);
1347 dassourceBrowser.setGuiEnabled(true);
1351 public void cancelDAS_actionPerformed(ActionEvent e)
1353 if (dasFeatureFetcher != null)
1355 dasFeatureFetcher.cancel();
1360 public void noDasSourceActive()
1364 .showInternalConfirmDialog(
1367 .getString("label.no_das_sources_selected_warn"),
1369 .getString("label.no_das_sources_selected_title"),
1370 JOptionPane.DEFAULT_OPTION,
1371 JOptionPane.INFORMATION_MESSAGE);
1374 // ///////////////////////////////////////////////////////////////////////
1375 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
1376 // ///////////////////////////////////////////////////////////////////////
1377 class FeatureTableModel extends AbstractTableModel
1379 FeatureTableModel(Object[][] data)
1384 private String[] columnNames =
1385 { "Feature Type", "Colour", "Display" };
1387 private Object[][] data;
1389 public Object[][] getData()
1394 public void setData(Object[][] data)
1399 public int getColumnCount()
1401 return columnNames.length;
1404 public Object[] getRow(int row)
1409 public int getRowCount()
1414 public String getColumnName(int col)
1416 return columnNames[col];
1419 public Object getValueAt(int row, int col)
1421 return data[row][col];
1424 public Class getColumnClass(int c)
1426 return getValueAt(0, c).getClass();
1429 public boolean isCellEditable(int row, int col)
1431 return col == 0 ? false : true;
1434 public void setValueAt(Object value, int row, int col)
1436 data[row][col] = value;
1437 fireTableCellUpdated(row, col);
1438 updateFeatureRenderer(data);
1443 class ColorRenderer extends JLabel implements TableCellRenderer
1445 javax.swing.border.Border unselectedBorder = null;
1447 javax.swing.border.Border selectedBorder = null;
1449 final String baseTT = "Click to edit, right/apple click for menu.";
1451 public ColorRenderer()
1453 setOpaque(true); // MUST do this for background to show up.
1454 setHorizontalTextPosition(SwingConstants.CENTER);
1455 setVerticalTextPosition(SwingConstants.CENTER);
1458 public Component getTableCellRendererComponent(JTable table,
1459 Object color, boolean isSelected, boolean hasFocus, int row,
1462 // JLabel comp = new JLabel();
1466 // setBounds(getBounds());
1468 setToolTipText(baseTT);
1469 setBackground(table.getBackground());
1470 if (color instanceof GraduatedColor)
1472 Rectangle cr = table.getCellRect(row, column, false);
1473 FeatureSettings.renderGraduatedColor(this, (GraduatedColor) color,
1474 (int) cr.getWidth(), (int) cr.getHeight());
1481 newColor = (Color) color;
1483 setBackground(newColor);
1484 // comp.setToolTipText("RGB value: " + newColor.getRed() + ", "
1485 // + newColor.getGreen() + ", " + newColor.getBlue());
1489 if (selectedBorder == null)
1491 selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1492 table.getSelectionBackground());
1495 setBorder(selectedBorder);
1499 if (unselectedBorder == null)
1501 unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1502 table.getBackground());
1505 setBorder(unselectedBorder);
1513 * update comp using rendering settings from gcol
1518 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol)
1520 int w = comp.getWidth(), h = comp.getHeight();
1523 w = (int) comp.getPreferredSize().getWidth();
1524 h = (int) comp.getPreferredSize().getHeight();
1531 renderGraduatedColor(comp, gcol, w, h);
1534 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol,
1537 boolean thr = false;
1540 if (gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD)
1544 tt += "Thresholded (Above " + gcol.getThresh() + ") ";
1546 if (gcol.getThreshType() == AnnotationColourGradient.BELOW_THRESHOLD)
1550 tt += "Thresholded (Below " + gcol.getThresh() + ") ";
1552 if (gcol.isColourByLabel())
1554 tt = "Coloured by label text. " + tt;
1564 Color newColor = gcol.getMaxColor();
1565 comp.setBackground(newColor);
1566 // System.err.println("Width is " + w / 2);
1567 Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w, h, thr);
1568 comp.setIcon(ficon);
1569 // tt+="RGB value: Max (" + newColor.getRed() + ", "
1570 // + newColor.getGreen() + ", " + newColor.getBlue()
1571 // + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen()
1572 // + ", " + minCol.getBlue() + ")");
1574 comp.setHorizontalAlignment(SwingConstants.CENTER);
1576 if (tt.length() > 0)
1578 if (comp.getToolTipText() == null)
1580 comp.setToolTipText(tt);
1584 comp.setToolTipText(tt + " " + comp.getToolTipText());
1590 class FeatureIcon implements Icon
1592 GraduatedColor gcol;
1596 boolean midspace = false;
1598 int width = 50, height = 20;
1600 int s1, e1; // start and end of midpoint band for thresholded symbol
1602 Color mpcolour = Color.white;
1604 FeatureIcon(GraduatedColor gfc, Color bg, int w, int h, boolean mspace)
1623 public int getIconWidth()
1628 public int getIconHeight()
1633 public void paintIcon(Component c, Graphics g, int x, int y)
1636 if (gcol.isColourByLabel())
1639 g.fillRect(0, 0, width, height);
1640 // need an icon here.
1641 g.setColor(gcol.getMaxColor());
1643 g.setFont(new Font("Verdana", Font.PLAIN, 9));
1645 // g.setFont(g.getFont().deriveFont(
1646 // AffineTransform.getScaleInstance(
1647 // width/g.getFontMetrics().stringWidth("Label"),
1648 // height/g.getFontMetrics().getHeight())));
1650 g.drawString(MessageManager.getString("label.label"), 0, 0);
1655 Color minCol = gcol.getMinColor();
1657 g.fillRect(0, 0, s1, height);
1660 g.setColor(Color.white);
1661 g.fillRect(s1, 0, e1 - s1, height);
1663 g.setColor(gcol.getMaxColor());
1664 g.fillRect(0, e1, width - e1, height);
1669 class ColorEditor extends AbstractCellEditor implements TableCellEditor,
1674 GraduatedColor currentGColor;
1676 FeatureColourChooser chooser;
1684 JColorChooser colorChooser;
1688 protected static final String EDIT = "edit";
1690 int selectedRow = 0;
1692 public ColorEditor(FeatureSettings me)
1695 // Set up the editor (from the table's point of view),
1696 // which is a button.
1697 // This button brings up the color chooser dialog,
1698 // which is the editor from the user's point of view.
1699 button = new JButton();
1700 button.setActionCommand(EDIT);
1701 button.addActionListener(this);
1702 button.setBorderPainted(false);
1703 // Set up the dialog that the button brings up.
1704 colorChooser = new JColorChooser();
1705 dialog = JColorChooser.createDialog(button, "Select new Colour", true, // modal
1706 colorChooser, this, // OK button handler
1707 null); // no CANCEL button handler
1711 * Handles events from the editor button and from the dialog's OK button.
1713 public void actionPerformed(ActionEvent e)
1716 if (EDIT.equals(e.getActionCommand()))
1718 // The user has clicked the cell, so
1719 // bring up the dialog.
1720 if (currentColor != null)
1722 // bring up simple color chooser
1723 button.setBackground(currentColor);
1724 colorChooser.setColor(currentColor);
1725 dialog.setVisible(true);
1729 // bring up graduated chooser.
1730 chooser = new FeatureColourChooser(me.fr, type);
1731 chooser.setRequestFocusEnabled(true);
1732 chooser.requestFocus();
1733 chooser.addActionListener(this);
1735 // Make the renderer reappear.
1736 fireEditingStopped();
1740 { // User pressed dialog's "OK" button.
1741 if (currentColor != null)
1743 currentColor = colorChooser.getColor();
1747 // class cast exceptions may be raised if the chooser created on a
1748 // non-graduated color
1749 currentGColor = (GraduatedColor) chooser.getLastColour();
1751 me.table.setValueAt(getCellEditorValue(), selectedRow, 1);
1752 fireEditingStopped();
1753 me.table.validate();
1757 // Implement the one CellEditor method that AbstractCellEditor doesn't.
1758 public Object getCellEditorValue()
1760 if (currentColor == null)
1762 return currentGColor;
1764 return currentColor;
1767 // Implement the one method defined by TableCellEditor.
1768 public Component getTableCellEditorComponent(JTable table, Object value,
1769 boolean isSelected, int row, int column)
1771 currentGColor = null;
1772 currentColor = null;
1773 this.selectedRow = row;
1774 type = me.table.getValueAt(row, 0).toString();
1775 button.setOpaque(true);
1776 button.setBackground(me.getBackground());
1777 if (value instanceof GraduatedColor)
1779 currentGColor = (GraduatedColor) value;
1780 JLabel btn = new JLabel();
1781 btn.setSize(button.getSize());
1782 FeatureSettings.renderGraduatedColor(btn, currentGColor);
1783 button.setBackground(btn.getBackground());
1784 button.setIcon(btn.getIcon());
1785 button.setText(btn.getText());
1790 button.setIcon(null);
1791 currentColor = (Color) value;
1792 button.setBackground(currentColor);