2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
3 * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, G Barton, M Clamp, S Searle
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/>.
22 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 (javax.swing.SwingUtilities.isRightMouseButton(evt))
104 popupSort(selectedRow, (String) table.getValueAt(selectedRow, 0),
105 table.getValueAt(selectedRow, 1), fr.minmax, evt.getX(),
111 table.addMouseMotionListener(new MouseMotionAdapter()
113 public void mouseDragged(MouseEvent evt)
115 int newRow = table.rowAtPoint(evt.getPoint());
116 if (newRow != selectedRow && selectedRow != -1 && newRow != -1)
118 Object[] temp = new Object[3];
119 temp[0] = table.getValueAt(selectedRow, 0);
120 temp[1] = table.getValueAt(selectedRow, 1);
121 temp[2] = table.getValueAt(selectedRow, 2);
123 table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0);
124 table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1);
125 table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2);
127 table.setValueAt(temp[0], newRow, 0);
128 table.setValueAt(temp[1], newRow, 1);
129 table.setValueAt(temp[2], newRow, 2);
131 selectedRow = newRow;
136 scrollPane.setViewportView(table);
138 dassourceBrowser = new DasSourceBrowser(this);
139 dasSettingsPane.add(dassourceBrowser, BorderLayout.CENTER);
141 if (af.getViewport().featuresDisplayed == null
142 || fr.renderOrder == null)
144 fr.findAllFeatures(true); // display everything!
148 final PropertyChangeListener change;
149 final FeatureSettings fs = this;
150 fr.addPropertyChangeListener(change = new PropertyChangeListener()
152 public void propertyChange(PropertyChangeEvent evt)
154 if (!fs.resettingTable && !fs.handlingUpdate)
156 fs.handlingUpdate = true;
157 fs.resetTable(null); // new groups may be added with new seuqence
158 // feature types only
159 fs.handlingUpdate = false;
165 frame = new JInternalFrame();
166 frame.setContentPane(this);
167 if (new jalview.util.Platform().isAMac())
169 Desktop.addInternalFrame(frame, "Sequence Feature Settings", 475, 480);
173 Desktop.addInternalFrame(frame, "Sequence Feature Settings", 400, 450);
176 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
178 public void internalFrameClosed(
179 javax.swing.event.InternalFrameEvent evt)
181 fr.removePropertyChangeListener(change);
182 dassourceBrowser.fs = null;
185 frame.setLayer(JLayeredPane.PALETTE_LAYER);
188 protected void popupSort(final int selectedRow, final String type,
189 final Object typeCol, final Hashtable minmax, int x, int y)
191 JPopupMenu men = new JPopupMenu("Settings for " + type);
192 JMenuItem scr = new JMenuItem("Sort by Score");
194 final FeatureSettings me = this;
195 scr.addActionListener(new ActionListener()
198 public void actionPerformed(ActionEvent e)
200 me.sortByScore(new String[]
205 JMenuItem dens = new JMenuItem("Sort by Density");
206 dens.addActionListener(new ActionListener()
209 public void actionPerformed(ActionEvent e)
211 me.sortByDens(new String[]
219 final Object typeMinMax = minmax.get(type);
221 * final JCheckBoxMenuItem chb = new JCheckBoxMenuItem("Vary Height"); //
222 * this is broken at the moment and isn't that useful anyway!
223 * chb.setSelected(minmax.get(type) != null); chb.addActionListener(new
226 * public void actionPerformed(ActionEvent e) {
227 * chb.setState(chb.getState()); if (chb.getState()) { minmax.put(type,
228 * null); } else { minmax.put(type, typeMinMax); } }
234 if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null)
236 // if (table.getValueAt(row, column));
237 // graduated colourschemes for those where minmax exists for the
238 // positional features
239 final JCheckBoxMenuItem mxcol = new JCheckBoxMenuItem(
241 mxcol.setSelected(!(typeCol instanceof Color));
243 mxcol.addActionListener(new ActionListener()
245 JColorChooser colorChooser;
247 public void actionPerformed(ActionEvent e)
249 if (e.getSource() == mxcol)
251 if (typeCol instanceof Color)
253 FeatureColourChooser fc = new FeatureColourChooser(me.fr,
255 fc.addActionListener(this);
259 // bring up simple color chooser
260 colorChooser = new JColorChooser();
261 JDialog dialog = JColorChooser.createDialog(me,
262 "Select new Colour", true, // modal
263 colorChooser, this, // OK button handler
264 null); // no CANCEL button handler
265 colorChooser.setColor(((GraduatedColor) typeCol)
267 dialog.setVisible(true);
272 if (e.getSource() instanceof FeatureColourChooser)
274 FeatureColourChooser fc = (FeatureColourChooser) e
276 table.setValueAt(fc.getLastColour(), selectedRow, 1);
281 // probably the color chooser!
282 table.setValueAt(colorChooser.getColor(), selectedRow, 1);
284 me.updateFeatureRenderer(
285 ((FeatureTableModel) table.getModel()).getData(),
294 men.show(table, x, y);
298 * true when Feature Settings are updating from feature renderer
300 private boolean handlingUpdate = false;
303 * contains a float[3] for each feature type string. created by setTableData
305 Hashtable typeWidth = null;
307 synchronized public void setTableData()
309 if (fr.featureGroups == null)
311 fr.featureGroups = new Hashtable();
313 Vector allFeatures = new Vector();
314 Vector allGroups = new Vector();
315 SequenceFeature[] tmpfeatures;
317 for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
319 if (af.getViewport().getAlignment().getSequenceAt(i)
320 .getDatasetSequence().getSequenceFeatures() == null)
325 tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
326 .getDatasetSequence().getSequenceFeatures();
329 while (index < tmpfeatures.length)
331 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
337 if (tmpfeatures[index].getFeatureGroup() != null)
339 group = tmpfeatures[index].featureGroup;
340 if (!allGroups.contains(group))
342 allGroups.addElement(group);
345 checkGroupState(group);
350 if (!allFeatures.contains(tmpfeatures[index].getType()))
352 allFeatures.addElement(tmpfeatures[index].getType());
366 * @return true if group has been seen before and is already added to set.
368 private boolean checkGroupState(String group)
371 if (fr.featureGroups.containsKey(group))
373 visible = ((Boolean) fr.featureGroups.get(group)).booleanValue();
377 visible = true; // new group is always made visible
380 if (groupPanel == null)
382 groupPanel = new JPanel();
385 boolean alreadyAdded = false;
386 for (int g = 0; g < groupPanel.getComponentCount(); g++)
388 if (((JCheckBox) groupPanel.getComponent(g)).getText().equals(group))
391 ((JCheckBox) groupPanel.getComponent(g)).setSelected(visible);
402 fr.featureGroups.put(group, new Boolean(visible));
403 final String grp = group;
404 final JCheckBox check = new JCheckBox(group, visible);
405 check.setFont(new Font("Serif", Font.BOLD, 12));
406 check.addItemListener(new ItemListener()
408 public void itemStateChanged(ItemEvent evt)
410 fr.featureGroups.put(check.getText(),
411 new Boolean(check.isSelected()));
412 af.alignPanel.seqPanel.seqCanvas.repaint();
413 if (af.alignPanel.overviewPanel != null)
415 af.alignPanel.overviewPanel.updateOverviewImage();
418 resetTable(new String[]
422 groupPanel.add(check);
426 boolean resettingTable = false;
428 synchronized void resetTable(String[] groupChanged)
430 if (resettingTable == true)
434 resettingTable = true;
435 typeWidth = new Hashtable();
436 // TODO: change avWidth calculation to 'per-sequence' average and use long
438 float[] avWidth = null;
439 SequenceFeature[] tmpfeatures;
440 String group = null, type;
441 Vector visibleChecks = new Vector();
443 // Find out which features should be visible depending on which groups
444 // are selected / deselected
445 // and recompute average width ordering
446 for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
449 tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
450 .getDatasetSequence().getSequenceFeatures();
451 if (tmpfeatures == null)
457 while (index < tmpfeatures.length)
459 group = tmpfeatures[index].featureGroup;
461 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
467 if (group == null || fr.featureGroups.get(group) == null
468 || ((Boolean) fr.featureGroups.get(group)).booleanValue())
471 checkGroupState(group);
472 type = tmpfeatures[index].getType();
473 if (!visibleChecks.contains(type))
475 visibleChecks.addElement(type);
478 if (!typeWidth.containsKey(tmpfeatures[index].getType()))
480 typeWidth.put(tmpfeatures[index].getType(),
481 avWidth = new float[3]);
485 avWidth = (float[]) typeWidth.get(tmpfeatures[index].getType());
488 if (tmpfeatures[index].getBegin() > tmpfeatures[index].getEnd())
490 avWidth[1] += 1 + tmpfeatures[index].getBegin()
491 - tmpfeatures[index].getEnd();
495 avWidth[1] += 1 + tmpfeatures[index].getEnd()
496 - tmpfeatures[index].getBegin();
502 int fSize = visibleChecks.size();
503 Object[][] data = new Object[fSize][3];
506 if (fr.renderOrder != null)
509 fr.findAllFeatures(groupChanged != null); // prod to update
510 // colourschemes. but don't
512 // First add the checks in the previous render order,
513 // in case the window has been closed and reopened
514 for (int ro = fr.renderOrder.length - 1; ro > -1; ro--)
516 type = fr.renderOrder[ro];
518 if (!visibleChecks.contains(type))
523 data[dataIndex][0] = type;
524 data[dataIndex][1] = fr.getFeatureStyle(type);
525 data[dataIndex][2] = new Boolean(
526 af.getViewport().featuresDisplayed.containsKey(type));
528 visibleChecks.removeElement(type);
532 fSize = visibleChecks.size();
533 for (int i = 0; i < fSize; i++)
535 // These must be extra features belonging to the group
536 // which was just selected
537 type = visibleChecks.elementAt(i).toString();
538 data[dataIndex][0] = type;
540 data[dataIndex][1] = fr.getFeatureStyle(type);
541 if (data[dataIndex][1] == null)
543 // "Colour has been updated in another view!!"
544 fr.renderOrder = null;
548 data[dataIndex][2] = new Boolean(true);
552 if (originalData == null)
554 originalData = new Object[data.length][3];
555 for (int i = 0; i < data.length; i++)
557 System.arraycopy(data[i], 0, originalData[i], 0, 3);
561 table.setModel(new FeatureTableModel(data));
562 table.getColumnModel().getColumn(0).setPreferredWidth(200);
564 if (groupPanel != null)
566 groupPanel.setLayout(new GridLayout(fr.featureGroups.size() / 4 + 1,
569 groupPanel.validate();
570 bigPanel.add(groupPanel, BorderLayout.NORTH);
573 updateFeatureRenderer(data, groupChanged != null);
574 resettingTable = false;
578 * reorder data based on the featureRenderers global priority list.
582 private void ensureOrder(Object[][] data)
584 boolean sort = false;
585 float[] order = new float[data.length];
586 for (int i = 0; i < order.length; i++)
588 order[i] = fr.getOrder(data[i][0].toString());
590 order[i] = fr.setOrder(data[i][0].toString(), i / order.length);
592 sort = sort || order[i - 1] > order[i];
595 jalview.util.QuickSort.sort(order, data);
600 JalviewFileChooser chooser = new JalviewFileChooser(
601 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
602 { "fc" }, new String[]
603 { "Sequence Feature Colours" }, "Sequence Feature Colours");
604 chooser.setFileView(new jalview.io.JalviewFileView());
605 chooser.setDialogTitle("Load Feature Colours");
606 chooser.setToolTipText("Load");
608 int value = chooser.showOpenDialog(this);
610 if (value == JalviewFileChooser.APPROVE_OPTION)
612 File file = chooser.getSelectedFile();
616 InputStreamReader in = new InputStreamReader(new FileInputStream(
619 jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
620 jucs = (jalview.schemabinding.version2.JalviewUserColours) jucs
623 for (int i = jucs.getColourCount() - 1; i >= 0; i--)
626 jalview.schemabinding.version2.Colour newcol = jucs.getColour(i);
629 Color mincol = null, maxcol = null;
632 mincol = new Color(Integer.parseInt(newcol.getMinRGB(), 16));
633 maxcol = new Color(Integer.parseInt(newcol.getRGB(), 16));
635 } catch (Exception e)
637 Cache.log.warn("Couldn't parse out graduated feature color.",
640 GraduatedColor gcol = new GraduatedColor(mincol, maxcol,
641 newcol.getMin(), newcol.getMax());
642 if (newcol.hasAutoScale())
644 gcol.setAutoScaled(newcol.getAutoScale());
646 if (newcol.hasColourByLabel())
648 gcol.setColourByLabel(newcol.getColourByLabel());
650 if (newcol.hasThreshold())
652 gcol.setThresh(newcol.getThreshold());
653 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD); // default
655 if (newcol.getThreshType().length() > 0)
657 String ttyp = newcol.getThreshType();
658 if (ttyp.equalsIgnoreCase("NONE"))
660 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD);
662 if (ttyp.equalsIgnoreCase("ABOVE"))
664 gcol.setThreshType(AnnotationColourGradient.ABOVE_THRESHOLD);
666 if (ttyp.equalsIgnoreCase("BELOW"))
668 gcol.setThreshType(AnnotationColourGradient.BELOW_THRESHOLD);
671 fr.setColour(name = newcol.getName(), gcol);
675 fr.setColour(name = jucs.getColour(i).getName(), new Color(
676 Integer.parseInt(jucs.getColour(i).getRGB(), 16)));
678 fr.setOrder(name, (i == 0) ? 0 : i / jucs.getColourCount());
683 Object[][] data = ((FeatureTableModel) table.getModel())
686 updateFeatureRenderer(data, false);
689 } catch (Exception ex)
691 System.out.println("Error loading User Colour File\n" + ex);
698 JalviewFileChooser chooser = new JalviewFileChooser(
699 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
700 { "fc" }, new String[]
701 { "Sequence Feature Colours" }, "Sequence Feature Colours");
702 chooser.setFileView(new jalview.io.JalviewFileView());
703 chooser.setDialogTitle("Save Feature Colour Scheme");
704 chooser.setToolTipText("Save");
706 int value = chooser.showSaveDialog(this);
708 if (value == JalviewFileChooser.APPROVE_OPTION)
710 String choice = chooser.getSelectedFile().getPath();
711 jalview.schemabinding.version2.JalviewUserColours ucs = new jalview.schemabinding.version2.JalviewUserColours();
712 ucs.setSchemeName("Sequence Features");
715 PrintWriter out = new PrintWriter(new OutputStreamWriter(
716 new FileOutputStream(choice), "UTF-8"));
718 Iterator e = fr.featureColours.keySet().iterator();
719 float[] sortOrder = new float[fr.featureColours.size()];
720 String[] sortTypes = new String[fr.featureColours.size()];
724 sortTypes[i] = e.next().toString();
725 sortOrder[i] = fr.getOrder(sortTypes[i]);
728 jalview.util.QuickSort.sort(sortOrder, sortTypes);
732 for (i = 0; i < sortTypes.length; i++)
734 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
735 col.setName(sortTypes[i]);
736 col.setRGB(jalview.util.Format.getHexString(fr.getColour(col
738 fcol = fr.getFeatureStyle(sortTypes[i]);
739 if (fcol instanceof GraduatedColor)
741 gcol = (GraduatedColor) fcol;
742 col.setMin(gcol.getMin());
743 col.setMax(gcol.getMax());
744 col.setMinRGB(jalview.util.Format.getHexString(gcol
746 col.setAutoScale(gcol.isAutoScale());
747 col.setThreshold(gcol.getThresh());
748 col.setColourByLabel(gcol.isColourByLabel());
749 switch (gcol.getThreshType())
751 case AnnotationColourGradient.NO_THRESHOLD:
752 col.setThreshType("NONE");
754 case AnnotationColourGradient.ABOVE_THRESHOLD:
755 col.setThreshType("ABOVE");
757 case AnnotationColourGradient.BELOW_THRESHOLD:
758 col.setThreshType("BELOW");
766 } catch (Exception ex)
768 ex.printStackTrace();
773 public void invertSelection()
775 for (int i = 0; i < table.getRowCount(); i++)
777 Boolean value = (Boolean) table.getValueAt(i, 2);
779 table.setValueAt(new Boolean(!value.booleanValue()), i, 2);
783 public void orderByAvWidth()
785 if (table == null || table.getModel() == null)
787 Object[][] data = ((FeatureTableModel) table.getModel()).getData();
788 float[] width = new float[data.length];
792 for (int i = 0; i < data.length; i++)
794 awidth = (float[]) typeWidth.get(data[i][0]);
797 width[i] = awidth[1] / awidth[0];// *awidth[0]*awidth[2]; - better
798 // weight - but have to make per
799 // sequence, too (awidth[2])
800 // if (width[i]==1) // hack to distinguish single width sequences.
810 boolean sort = false;
811 for (int i = 0; i < width.length; i++)
813 // awidth = (float[]) typeWidth.get(data[i][0]);
816 width[i] = fr.getOrder(data[i][0].toString());
819 width[i] = fr.setOrder(data[i][0].toString(), i / data.length);
824 width[i] /= max; // normalize
825 fr.setOrder(data[i][0].toString(), width[i]); // store for later
828 sort = sort || width[i - 1] > width[i];
831 jalview.util.QuickSort.sort(width, data);
832 // update global priority order
834 updateFeatureRenderer(data, false);
842 frame.setClosed(true);
843 } catch (Exception exe)
849 public void updateFeatureRenderer(Object[][] data)
851 updateFeatureRenderer(data, true);
854 private void updateFeatureRenderer(Object[][] data, boolean visibleNew)
856 fr.setFeaturePriority(data, visibleNew);
857 af.alignPanel.paintAlignment(true);
860 int selectedRow = -1;
862 JTabbedPane tabbedPane = new JTabbedPane();
864 BorderLayout borderLayout1 = new BorderLayout();
866 BorderLayout borderLayout2 = new BorderLayout();
868 BorderLayout borderLayout3 = new BorderLayout();
870 JPanel bigPanel = new JPanel();
872 BorderLayout borderLayout4 = new BorderLayout();
874 JButton invert = new JButton();
876 JPanel buttonPanel = new JPanel();
878 JButton cancel = new JButton();
880 JButton ok = new JButton();
882 JButton loadColours = new JButton();
884 JButton saveColours = new JButton();
886 JPanel dasButtonPanel = new JPanel();
888 JButton fetchDAS = new JButton();
890 JButton saveDAS = new JButton();
892 JButton cancelDAS = new JButton();
894 JButton optimizeOrder = new JButton();
896 JButton sortByScore = new JButton();
898 JButton sortByDens = new JButton();
900 JPanel transbuttons = new JPanel(new GridLayout(4, 1));
902 private void jbInit() throws Exception
904 this.setLayout(borderLayout1);
905 settingsPane.setLayout(borderLayout2);
906 dasSettingsPane.setLayout(borderLayout3);
907 bigPanel.setLayout(borderLayout4);
908 invert.setFont(JvSwingUtils.getLabelFont());
909 invert.setText(MessageManager.getString("label.invert_selection"));
910 invert.addActionListener(new ActionListener()
912 public void actionPerformed(ActionEvent e)
917 optimizeOrder.setFont(JvSwingUtils.getLabelFont());
918 optimizeOrder.setText(MessageManager.getString("label.optimise_order"));
919 optimizeOrder.addActionListener(new ActionListener()
921 public void actionPerformed(ActionEvent e)
926 sortByScore.setFont(JvSwingUtils.getLabelFont());
927 sortByScore.setText(MessageManager.getString("label.seq_sort_by_score"));
928 sortByScore.addActionListener(new ActionListener()
930 public void actionPerformed(ActionEvent e)
935 sortByDens.setFont(JvSwingUtils.getLabelFont());
936 sortByDens.setText("Seq Sort by density");
937 sortByDens.addActionListener(new ActionListener()
939 public void actionPerformed(ActionEvent e)
944 cancel.setFont(JvSwingUtils.getLabelFont());
945 cancel.setText(MessageManager.getString("action.cancel"));
946 cancel.addActionListener(new ActionListener()
948 public void actionPerformed(ActionEvent e)
950 updateFeatureRenderer(originalData);
954 ok.setFont(JvSwingUtils.getLabelFont());
955 ok.setText(MessageManager.getString("action.ok"));
956 ok.addActionListener(new ActionListener()
958 public void actionPerformed(ActionEvent e)
963 loadColours.setFont(JvSwingUtils.getLabelFont());
964 loadColours.setText(MessageManager.getString("label.load_colours"));
965 loadColours.addActionListener(new ActionListener()
967 public void actionPerformed(ActionEvent e)
972 saveColours.setFont(JvSwingUtils.getLabelFont());
973 saveColours.setText(MessageManager.getString("label.save_colours"));
974 saveColours.addActionListener(new ActionListener()
976 public void actionPerformed(ActionEvent e)
981 transparency.addChangeListener(new ChangeListener()
983 public void stateChanged(ChangeEvent evt)
985 fr.setTransparency((float) (100 - transparency.getValue()) / 100f);
986 af.alignPanel.paintAlignment(true);
990 transparency.setMaximum(70);
991 fetchDAS.setText(MessageManager.getString("label.fetch_das_features"));
992 fetchDAS.addActionListener(new ActionListener()
994 public void actionPerformed(ActionEvent e)
996 fetchDAS_actionPerformed(e);
999 saveDAS.setText(MessageManager.getString("action.save_as_default"));
1000 saveDAS.addActionListener(new ActionListener()
1002 public void actionPerformed(ActionEvent e)
1004 saveDAS_actionPerformed(e);
1007 dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
1008 dasSettingsPane.setBorder(null);
1009 cancelDAS.setEnabled(false);
1010 cancelDAS.setText(MessageManager.getString("action.cancel_fetch"));
1011 cancelDAS.addActionListener(new ActionListener()
1013 public void actionPerformed(ActionEvent e)
1015 cancelDAS_actionPerformed(e);
1018 this.add(tabbedPane, java.awt.BorderLayout.CENTER);
1019 tabbedPane.addTab("Feature Settings", settingsPane);
1020 tabbedPane.addTab("DAS Settings", dasSettingsPane);
1021 bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
1022 transbuttons.add(optimizeOrder);
1023 transbuttons.add(invert);
1024 transbuttons.add(sortByScore);
1025 transbuttons.add(sortByDens);
1026 transPanel.add(transparency);
1027 transPanel.add(transbuttons);
1028 buttonPanel.add(ok);
1029 buttonPanel.add(cancel);
1030 buttonPanel.add(loadColours);
1031 buttonPanel.add(saveColours);
1032 bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
1033 dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
1034 dasButtonPanel.add(fetchDAS);
1035 dasButtonPanel.add(cancelDAS);
1036 dasButtonPanel.add(saveDAS);
1037 settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);
1038 settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
1041 protected void sortByDens(String[] typ)
1043 sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY);
1046 protected void sortBy(String[] typ, String methodText, final String method)
1050 typ = getDisplayedFeatureTypes();
1052 String gps[] = null;
1053 gps = getDisplayedFeatureGroups();
1056 ArrayList types = new ArrayList();
1057 for (int i = 0; i < typ.length; i++)
1063 typ = new String[types.size()];
1069 ArrayList grps = new ArrayList();
1071 for (int i = 0; i < gps.length; i++)
1078 gps = new String[grps.size()];
1081 AlignmentPanel alignPanel = af.alignPanel;
1082 AlignmentI al = alignPanel.av.getAlignment();
1085 SequenceGroup sg = alignPanel.av.getSelectionGroup();
1088 start = sg.getStartRes();
1089 stop = sg.getEndRes();
1094 stop = al.getWidth();
1096 SequenceI[] oldOrder = al.getSequencesArray();
1097 AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
1098 af.addHistoryItem(new OrderCommand(methodText, oldOrder, alignPanel.av
1100 alignPanel.paintAlignment(true);
1104 protected void sortByScore(String[] typ)
1106 sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE);
1109 private String[] getDisplayedFeatureTypes()
1111 String[] typ = null;
1114 synchronized (fr.renderOrder)
1116 typ = new String[fr.renderOrder.length];
1117 System.arraycopy(fr.renderOrder, 0, typ, 0, typ.length);
1118 for (int i = 0; i < typ.length; i++)
1120 if (af.viewport.featuresDisplayed.get(typ[i]) == null)
1130 private String[] getDisplayedFeatureGroups()
1132 String[] gps = null;
1136 if (fr.featureGroups != null)
1138 Iterator en = fr.featureGroups.keySet().iterator();
1139 gps = new String[fr.featureColours.size()];
1141 boolean valid = false;
1142 while (en.hasNext())
1144 String gp = (String) en.next();
1145 Boolean on = (Boolean) fr.featureGroups.get(gp);
1146 if (on != null && on.booleanValue())
1152 while (g < gps.length)
1165 public void fetchDAS_actionPerformed(ActionEvent e)
1167 fetchDAS.setEnabled(false);
1168 cancelDAS.setEnabled(true);
1169 dassourceBrowser.setGuiEnabled(false);
1170 Vector selectedSources = dassourceBrowser.getSelectedSources();
1171 doDasFeatureFetch(selectedSources, true, true);
1175 * get the features from selectedSources for all or the current selection
1177 * @param selectedSources
1178 * @param checkDbRefs
1179 * @param promptFetchDbRefs
1181 private void doDasFeatureFetch(List<jalviewSourceI> selectedSources,
1182 boolean checkDbRefs, boolean promptFetchDbRefs)
1184 SequenceI[] dataset, seqs;
1186 AlignViewport vp = af.getViewport();
1187 if (vp.getSelectionGroup() != null
1188 && vp.getSelectionGroup().getSize() > 0)
1190 iSize = vp.getSelectionGroup().getSize();
1191 dataset = new SequenceI[iSize];
1192 seqs = vp.getSelectionGroup().getSequencesInOrder(vp.getAlignment());
1196 iSize = vp.getAlignment().getHeight();
1197 seqs = vp.getAlignment().getSequencesArray();
1200 dataset = new SequenceI[iSize];
1201 for (int i = 0; i < iSize; i++)
1203 dataset[i] = seqs[i].getDatasetSequence();
1206 cancelDAS.setEnabled(true);
1207 dasFeatureFetcher = new jalview.ws.DasSequenceFeatureFetcher(dataset,
1208 this, selectedSources, checkDbRefs, promptFetchDbRefs);
1209 af.getViewport().setShowSequenceFeatures(true);
1210 af.showSeqFeatures.setSelected(true);
1214 * blocking call to initialise the das source browser
1216 public void initDasSources()
1218 dassourceBrowser.initDasSources();
1222 * examine the current list of das sources and return any matching the given
1223 * nicknames in sources
1226 * Vector of Strings to resolve to DAS source nicknames.
1227 * @return sources that are present in source list.
1229 public List<jalviewSourceI> resolveSourceNicknames(Vector sources)
1231 return dassourceBrowser.sourceRegistry.resolveSourceNicknames(sources);
1235 * get currently selected das sources. ensure you have called initDasSources
1236 * before calling this.
1238 * @return vector of selected das source nicknames
1240 public Vector getSelectedSources()
1242 return dassourceBrowser.getSelectedSources();
1246 * properly initialise DAS fetcher and then initiate a new thread to fetch
1247 * features from the named sources (rather than any turned on by default)
1251 * if true then runs in same thread, otherwise passes to the Swing
1254 public void fetchDasFeatures(Vector sources, boolean block)
1257 List<jalviewSourceI> resolved = dassourceBrowser.sourceRegistry
1258 .resolveSourceNicknames(sources);
1259 if (resolved.size() == 0)
1261 resolved = dassourceBrowser.getSelectedSources();
1263 if (resolved.size() > 0)
1265 final List<jalviewSourceI> dassources = resolved;
1266 fetchDAS.setEnabled(false);
1267 // cancelDAS.setEnabled(true); doDasFetch does this.
1268 Runnable fetcher = new Runnable()
1273 doDasFeatureFetch(dassources, true, false);
1283 SwingUtilities.invokeLater(fetcher);
1288 public void saveDAS_actionPerformed(ActionEvent e)
1291 .saveProperties(jalview.bin.Cache.applicationProperties);
1294 public void complete()
1296 fetchDAS.setEnabled(true);
1297 cancelDAS.setEnabled(false);
1298 dassourceBrowser.setGuiEnabled(true);
1302 public void cancelDAS_actionPerformed(ActionEvent e)
1304 if (dasFeatureFetcher != null)
1306 dasFeatureFetcher.cancel();
1311 public void noDasSourceActive()
1314 JOptionPane.showInternalConfirmDialog(Desktop.desktop,
1315 MessageManager.getString("label.no_das_sources_selected_warn"),
1316 MessageManager.getString("label.no_das_sources_selected_title"), JOptionPane.DEFAULT_OPTION,
1317 JOptionPane.INFORMATION_MESSAGE);
1320 // ///////////////////////////////////////////////////////////////////////
1321 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
1322 // ///////////////////////////////////////////////////////////////////////
1323 class FeatureTableModel extends AbstractTableModel
1325 FeatureTableModel(Object[][] data)
1330 private String[] columnNames =
1331 { "Feature Type", "Colour", "Display" };
1333 private Object[][] data;
1335 public Object[][] getData()
1340 public void setData(Object[][] data)
1345 public int getColumnCount()
1347 return columnNames.length;
1350 public Object[] getRow(int row)
1355 public int getRowCount()
1360 public String getColumnName(int col)
1362 return columnNames[col];
1365 public Object getValueAt(int row, int col)
1367 return data[row][col];
1370 public Class getColumnClass(int c)
1372 return getValueAt(0, c).getClass();
1375 public boolean isCellEditable(int row, int col)
1377 return col == 0 ? false : true;
1380 public void setValueAt(Object value, int row, int col)
1382 data[row][col] = value;
1383 fireTableCellUpdated(row, col);
1384 updateFeatureRenderer(data);
1389 class ColorRenderer extends JLabel implements TableCellRenderer
1391 javax.swing.border.Border unselectedBorder = null;
1393 javax.swing.border.Border selectedBorder = null;
1395 final String baseTT = "Click to edit, right/apple click for menu.";
1397 public ColorRenderer()
1399 setOpaque(true); // MUST do this for background to show up.
1400 setHorizontalTextPosition(SwingConstants.CENTER);
1401 setVerticalTextPosition(SwingConstants.CENTER);
1404 public Component getTableCellRendererComponent(JTable table,
1405 Object color, boolean isSelected, boolean hasFocus, int row,
1408 // JLabel comp = new JLabel();
1412 // setBounds(getBounds());
1414 setToolTipText(baseTT);
1415 setBackground(table.getBackground());
1416 if (color instanceof GraduatedColor)
1418 Rectangle cr = table.getCellRect(row, column, false);
1419 FeatureSettings.renderGraduatedColor(this, (GraduatedColor) color,
1420 (int) cr.getWidth(), (int) cr.getHeight());
1427 newColor = (Color) color;
1429 setBackground(newColor);
1430 // comp.setToolTipText("RGB value: " + newColor.getRed() + ", "
1431 // + newColor.getGreen() + ", " + newColor.getBlue());
1435 if (selectedBorder == null)
1437 selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1438 table.getSelectionBackground());
1441 setBorder(selectedBorder);
1445 if (unselectedBorder == null)
1447 unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1448 table.getBackground());
1451 setBorder(unselectedBorder);
1459 * update comp using rendering settings from gcol
1464 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol)
1466 int w = comp.getWidth(), h = comp.getHeight();
1469 w = (int) comp.getPreferredSize().getWidth();
1470 h = (int) comp.getPreferredSize().getHeight();
1477 renderGraduatedColor(comp, gcol, w, h);
1480 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol,
1483 boolean thr = false;
1486 if (gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD)
1490 tt += "Thresholded (Above " + gcol.getThresh() + ") ";
1492 if (gcol.getThreshType() == AnnotationColourGradient.BELOW_THRESHOLD)
1496 tt += "Thresholded (Below " + gcol.getThresh() + ") ";
1498 if (gcol.isColourByLabel())
1500 tt = "Coloured by label text. " + tt;
1510 Color newColor = gcol.getMaxColor();
1511 comp.setBackground(newColor);
1512 // System.err.println("Width is " + w / 2);
1513 Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w, h, thr);
1514 comp.setIcon(ficon);
1515 // tt+="RGB value: Max (" + newColor.getRed() + ", "
1516 // + newColor.getGreen() + ", " + newColor.getBlue()
1517 // + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen()
1518 // + ", " + minCol.getBlue() + ")");
1520 comp.setHorizontalAlignment(SwingConstants.CENTER);
1522 if (tt.length() > 0)
1524 if (comp.getToolTipText() == null)
1526 comp.setToolTipText(tt);
1530 comp.setToolTipText(tt + " " + comp.getToolTipText());
1536 class FeatureIcon implements Icon
1538 GraduatedColor gcol;
1542 boolean midspace = false;
1544 int width = 50, height = 20;
1546 int s1, e1; // start and end of midpoint band for thresholded symbol
1548 Color mpcolour = Color.white;
1550 FeatureIcon(GraduatedColor gfc, Color bg, int w, int h, boolean mspace)
1569 public int getIconWidth()
1574 public int getIconHeight()
1579 public void paintIcon(Component c, Graphics g, int x, int y)
1582 if (gcol.isColourByLabel())
1585 g.fillRect(0, 0, width, height);
1586 // need an icon here.
1587 g.setColor(gcol.getMaxColor());
1589 g.setFont(new Font("Verdana", Font.PLAIN, 9));
1591 // g.setFont(g.getFont().deriveFont(
1592 // AffineTransform.getScaleInstance(
1593 // width/g.getFontMetrics().stringWidth("Label"),
1594 // height/g.getFontMetrics().getHeight())));
1596 g.drawString(MessageManager.getString("label.label"), 0, 0);
1601 Color minCol = gcol.getMinColor();
1603 g.fillRect(0, 0, s1, height);
1606 g.setColor(Color.white);
1607 g.fillRect(s1, 0, e1 - s1, height);
1609 g.setColor(gcol.getMaxColor());
1610 g.fillRect(0, e1, width - e1, height);
1615 class ColorEditor extends AbstractCellEditor implements TableCellEditor,
1620 GraduatedColor currentGColor;
1622 FeatureColourChooser chooser;
1630 JColorChooser colorChooser;
1634 protected static final String EDIT = "edit";
1636 int selectedRow = 0;
1638 public ColorEditor(FeatureSettings me)
1641 // Set up the editor (from the table's point of view),
1642 // which is a button.
1643 // This button brings up the color chooser dialog,
1644 // which is the editor from the user's point of view.
1645 button = new JButton();
1646 button.setActionCommand(EDIT);
1647 button.addActionListener(this);
1648 button.setBorderPainted(false);
1649 // Set up the dialog that the button brings up.
1650 colorChooser = new JColorChooser();
1651 dialog = JColorChooser.createDialog(button, "Select new Colour", true, // modal
1652 colorChooser, this, // OK button handler
1653 null); // no CANCEL button handler
1657 * Handles events from the editor button and from the dialog's OK button.
1659 public void actionPerformed(ActionEvent e)
1662 if (EDIT.equals(e.getActionCommand()))
1664 // The user has clicked the cell, so
1665 // bring up the dialog.
1666 if (currentColor != null)
1668 // bring up simple color chooser
1669 button.setBackground(currentColor);
1670 colorChooser.setColor(currentColor);
1671 dialog.setVisible(true);
1675 // bring up graduated chooser.
1676 chooser = new FeatureColourChooser(me.fr, type);
1677 chooser.setRequestFocusEnabled(true);
1678 chooser.requestFocus();
1679 chooser.addActionListener(this);
1681 // Make the renderer reappear.
1682 fireEditingStopped();
1686 { // User pressed dialog's "OK" button.
1687 if (currentColor != null)
1689 currentColor = colorChooser.getColor();
1693 // class cast exceptions may be raised if the chooser created on a
1694 // non-graduated color
1695 currentGColor = (GraduatedColor) chooser.getLastColour();
1697 me.table.setValueAt(getCellEditorValue(), selectedRow, 1);
1698 fireEditingStopped();
1699 me.table.validate();
1703 // Implement the one CellEditor method that AbstractCellEditor doesn't.
1704 public Object getCellEditorValue()
1706 if (currentColor == null)
1708 return currentGColor;
1710 return currentColor;
1713 // Implement the one method defined by TableCellEditor.
1714 public Component getTableCellEditorComponent(JTable table, Object value,
1715 boolean isSelected, int row, int column)
1717 currentGColor = null;
1718 currentColor = null;
1719 this.selectedRow = row;
1720 type = me.table.getValueAt(row, 0).toString();
1721 button.setOpaque(true);
1722 button.setBackground(me.getBackground());
1723 if (value instanceof GraduatedColor)
1725 currentGColor = (GraduatedColor) value;
1726 JLabel btn = new JLabel();
1727 btn.setSize(button.getSize());
1728 FeatureSettings.renderGraduatedColor(btn, currentGColor);
1729 button.setBackground(btn.getBackground());
1730 button.setIcon(btn.getIcon());
1731 button.setText(btn.getText());
1736 button.setIcon(null);
1737 currentColor = (Color) value;
1738 button.setBackground(currentColor);