2 * Jalview - A Sequence Alignment Editor and Viewer (Development Version 2.4.1)
3 * Copyright (C) 2009 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 import java.awt.event.*;
26 import java.awt.geom.AffineTransform;
27 import java.awt.image.BufferedImage;
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;
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();
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 Desktop.addInternalFrame(frame, "Sequence Feature Settings", 400, 450);
169 .addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
171 public void internalFrameClosed(
172 javax.swing.event.InternalFrameEvent evt)
174 fr.removePropertyChangeListener(change);
177 frame.setLayer(JLayeredPane.PALETTE_LAYER);
180 protected void popupSort(final int selectedRow, final String type,
181 final Object typeCol, final Hashtable minmax, int x, int y)
183 JPopupMenu men = new JPopupMenu("Settings for " + type);
184 JMenuItem scr = new JMenuItem("Sort by Score");
186 final FeatureSettings me = this;
187 scr.addActionListener(new ActionListener()
190 public void actionPerformed(ActionEvent e)
192 me.sortByScore(new String[]
197 JMenuItem dens = new JMenuItem("Sort by Density");
198 dens.addActionListener(new ActionListener()
201 public void actionPerformed(ActionEvent e)
203 me.sortByDens(new String[]
211 final Object typeMinMax = minmax.get(type);
213 * final JCheckBoxMenuItem chb = new JCheckBoxMenuItem("Vary Height"); //
214 * this is broken at the moment and isn't that useful anyway!
215 * chb.setSelected(minmax.get(type) != null); chb.addActionListener(new
218 * public void actionPerformed(ActionEvent e) {
219 * chb.setState(chb.getState()); if (chb.getState()) { minmax.put(type,
220 * null); } else { minmax.put(type, typeMinMax); } }
226 if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null)
228 // if (table.getValueAt(row, column));
229 // graduated colourschemes for those where minmax exists for the
230 // positional features
231 final JCheckBoxMenuItem mxcol = new JCheckBoxMenuItem(
233 mxcol.setSelected(!(typeCol instanceof Color));
235 mxcol.addActionListener(new ActionListener()
237 JColorChooser colorChooser;
239 public void actionPerformed(ActionEvent e)
241 if (e.getSource() == mxcol)
243 if (typeCol instanceof Color)
245 FeatureColourChooser fc = new FeatureColourChooser(me.fr,
247 fc.addActionListener(this);
251 // bring up simple color chooser
252 colorChooser = new JColorChooser();
253 JDialog dialog = JColorChooser.createDialog(me,
254 "Select new Colour", true, // modal
255 colorChooser, this, // OK button handler
256 null); // no CANCEL button handler
257 colorChooser.setColor(((GraduatedColor) typeCol)
259 dialog.setVisible(true);
264 if (e.getSource() instanceof FeatureColourChooser)
266 FeatureColourChooser fc = (FeatureColourChooser) e
268 table.setValueAt(fc.getLastColour(), selectedRow, 1);
273 // probably the color chooser!
274 table.setValueAt(colorChooser.getColor(), selectedRow, 1);
276 me.updateFeatureRenderer(((FeatureTableModel) table
277 .getModel()).getData(), false);
285 men.show(table, x, y);
289 * true when Feature Settings are updating from feature renderer
291 private boolean handlingUpdate = false;
294 * contains a float[3] for each feature type string. created by setTableData
296 Hashtable typeWidth = null;
298 synchronized public void setTableData()
300 if (fr.featureGroups == null)
302 fr.featureGroups = new Hashtable();
304 Vector allFeatures = new Vector();
305 Vector allGroups = new Vector();
306 SequenceFeature[] tmpfeatures;
308 for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)
310 if (af.getViewport().alignment.getSequenceAt(i).getDatasetSequence()
311 .getSequenceFeatures() == null)
316 tmpfeatures = af.getViewport().alignment.getSequenceAt(i)
317 .getDatasetSequence().getSequenceFeatures();
320 while (index < tmpfeatures.length)
322 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
328 if (tmpfeatures[index].getFeatureGroup() != null)
330 group = tmpfeatures[index].featureGroup;
331 if (!allGroups.contains(group))
333 allGroups.addElement(group);
336 checkGroupState(group);
341 if (!allFeatures.contains(tmpfeatures[index].getType()))
343 allFeatures.addElement(tmpfeatures[index].getType());
357 * @return true if group has been seen before and is already added to set.
359 private boolean checkGroupState(String group)
362 if (fr.featureGroups.containsKey(group))
364 visible = ((Boolean) fr.featureGroups.get(group)).booleanValue();
368 visible = true; // new group is always made visible
371 if (groupPanel == null)
373 groupPanel = new JPanel();
376 boolean alreadyAdded = false;
377 for (int g = 0; g < groupPanel.getComponentCount(); g++)
379 if (((JCheckBox) groupPanel.getComponent(g)).getText().equals(group))
382 ((JCheckBox) groupPanel.getComponent(g)).setSelected(visible);
393 fr.featureGroups.put(group, new Boolean(visible));
394 final String grp = group;
395 final JCheckBox check = new JCheckBox(group, visible);
396 check.setFont(new Font("Serif", Font.BOLD, 12));
397 check.addItemListener(new ItemListener()
399 public void itemStateChanged(ItemEvent evt)
401 fr.featureGroups.put(check.getText(), new Boolean(check
403 af.alignPanel.seqPanel.seqCanvas.repaint();
404 if (af.alignPanel.overviewPanel != null)
406 af.alignPanel.overviewPanel.updateOverviewImage();
409 resetTable(new String[]
413 groupPanel.add(check);
417 boolean resettingTable = false;
419 synchronized void resetTable(String[] groupChanged)
421 if (resettingTable == true)
425 resettingTable = true;
426 typeWidth = new Hashtable();
427 // TODO: change avWidth calculation to 'per-sequence' average and use long
429 float[] avWidth = null;
430 SequenceFeature[] tmpfeatures;
431 String group = null, type;
432 Vector visibleChecks = new Vector();
434 // Find out which features should be visible depending on which groups
435 // are selected / deselected
436 // and recompute average width ordering
437 for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)
440 tmpfeatures = af.getViewport().alignment.getSequenceAt(i)
441 .getDatasetSequence().getSequenceFeatures();
442 if (tmpfeatures == null)
448 while (index < tmpfeatures.length)
450 group = tmpfeatures[index].featureGroup;
452 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
458 if (group == null || fr.featureGroups.get(group) == null
459 || ((Boolean) fr.featureGroups.get(group)).booleanValue())
462 checkGroupState(group);
463 type = tmpfeatures[index].getType();
464 if (!visibleChecks.contains(type))
466 visibleChecks.addElement(type);
469 if (!typeWidth.containsKey(tmpfeatures[index].getType()))
471 typeWidth.put(tmpfeatures[index].getType(),
472 avWidth = new float[3]);
476 avWidth = (float[]) typeWidth.get(tmpfeatures[index].getType());
479 if (tmpfeatures[index].getBegin() > tmpfeatures[index].getEnd())
481 avWidth[1] += 1 + tmpfeatures[index].getBegin()
482 - tmpfeatures[index].getEnd();
486 avWidth[1] += 1 + tmpfeatures[index].getEnd()
487 - tmpfeatures[index].getBegin();
493 int fSize = visibleChecks.size();
494 Object[][] data = new Object[fSize][3];
497 if (fr.renderOrder != null)
500 fr.findAllFeatures(groupChanged != null); // prod to update
501 // colourschemes. but don't
503 // First add the checks in the previous render order,
504 // in case the window has been closed and reopened
505 for (int ro = fr.renderOrder.length - 1; ro > -1; ro--)
507 type = fr.renderOrder[ro];
509 if (!visibleChecks.contains(type))
514 data[dataIndex][0] = type;
515 data[dataIndex][1] = fr.getFeatureStyle(type);
516 data[dataIndex][2] = new Boolean(af.getViewport().featuresDisplayed
519 visibleChecks.removeElement(type);
523 fSize = visibleChecks.size();
524 for (int i = 0; i < fSize; i++)
526 // These must be extra features belonging to the group
527 // which was just selected
528 type = visibleChecks.elementAt(i).toString();
529 data[dataIndex][0] = type;
531 data[dataIndex][1] = fr.getFeatureStyle(type);
532 if (data[dataIndex][1] == null)
534 // "Colour has been updated in another view!!"
535 fr.renderOrder = null;
539 data[dataIndex][2] = new Boolean(true);
543 if (originalData == null)
545 originalData = new Object[data.length][3];
546 for (int i = 0; i < data.length; i++)
548 System.arraycopy(data[i], 0, originalData[i], 0, 3);
552 table.setModel(new FeatureTableModel(data));
553 table.getColumnModel().getColumn(0).setPreferredWidth(200);
555 if (groupPanel != null)
557 groupPanel.setLayout(new GridLayout(fr.featureGroups.size() / 4 + 1,
560 groupPanel.validate();
561 bigPanel.add(groupPanel, BorderLayout.NORTH);
564 updateFeatureRenderer(data, groupChanged != null);
565 resettingTable = false;
569 * reorder data based on the featureRenderers global priority list.
573 private void ensureOrder(Object[][] data)
575 boolean sort = false;
576 float[] order = new float[data.length];
577 for (int i = 0; i < order.length; i++)
579 order[i] = fr.getOrder(data[i][0].toString());
581 order[i] = fr.setOrder(data[i][0].toString(), i / order.length);
583 sort = sort || order[i - 1] > order[i];
586 jalview.util.QuickSort.sort(order, data);
591 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
592 .getProperty("LAST_DIRECTORY"), new String[]
593 { "fc" }, new String[]
594 { "Sequence Feature Colours" }, "Sequence Feature Colours");
595 chooser.setFileView(new jalview.io.JalviewFileView());
596 chooser.setDialogTitle("Load Feature Colours");
597 chooser.setToolTipText("Load");
599 int value = chooser.showOpenDialog(this);
601 if (value == JalviewFileChooser.APPROVE_OPTION)
603 File file = chooser.getSelectedFile();
607 InputStreamReader in = new InputStreamReader(new FileInputStream(
610 jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
611 jucs = (jalview.schemabinding.version2.JalviewUserColours) jucs.unmarshal(in);
613 for (int i = jucs.getColourCount() - 1; i >= 0; i--)
616 jalview.schemabinding.version2.Colour newcol = jucs.getColour(i);
619 Color mincol=null,maxcol=null;
622 Integer.parseInt(newcol.getMinRGB(), 16));
624 Integer.parseInt(newcol.getRGB(), 16));
626 } catch (Exception e)
628 Cache.log.warn("Couldn't parse out graduated feature color.",e);
630 GraduatedColor gcol =
631 new GraduatedColor(mincol,maxcol,
632 newcol.getMin(),newcol.getMax());
633 if (newcol.hasAutoScale())
635 gcol.setAutoScaled(newcol.getAutoScale());
637 if (newcol.hasColourByLabel())
639 gcol.setColourByLabel(newcol.getColourByLabel());
641 if (newcol.hasThreshold())
643 gcol.setThresh(newcol.getThreshold());
644 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD); // default
646 if (newcol.getThreshType().length()>0)
648 String ttyp = newcol.getThreshType();
649 if (ttyp.equalsIgnoreCase("NONE")) {
650 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD);
652 if (ttyp.equalsIgnoreCase("ABOVE"))
654 gcol.setThreshType(AnnotationColourGradient.ABOVE_THRESHOLD);
656 if (ttyp.equalsIgnoreCase("BELOW")){
657 gcol.setThreshType(AnnotationColourGradient.BELOW_THRESHOLD);
660 fr.setColour(name = newcol.getName(), gcol);
662 fr.setColour(name = jucs.getColour(i).getName(), new Color(
663 Integer.parseInt(jucs.getColour(i).getRGB(), 16)));
665 fr.setOrder(name, (i == 0) ? 0 : i / jucs.getColourCount());
670 Object[][] data = ((FeatureTableModel) table.getModel())
673 updateFeatureRenderer(data, false);
676 } catch (Exception ex)
678 System.out.println("Error loading User Colour File\n" + ex);
685 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
686 .getProperty("LAST_DIRECTORY"), new String[]
687 { "fc" }, new String[]
688 { "Sequence Feature Colours" }, "Sequence Feature Colours");
689 chooser.setFileView(new jalview.io.JalviewFileView());
690 chooser.setDialogTitle("Save Feature Colour Scheme");
691 chooser.setToolTipText("Save");
693 int value = chooser.showSaveDialog(this);
695 if (value == JalviewFileChooser.APPROVE_OPTION)
697 String choice = chooser.getSelectedFile().getPath();
698 jalview.schemabinding.version2.JalviewUserColours ucs = new jalview.schemabinding.version2.JalviewUserColours();
699 ucs.setSchemeName("Sequence Features");
702 PrintWriter out = new PrintWriter(new OutputStreamWriter(
703 new FileOutputStream(choice), "UTF-8"));
705 Enumeration e = fr.featureColours.keys();
706 float[] sortOrder = new float[fr.featureColours.size()];
707 String[] sortTypes = new String[fr.featureColours.size()];
709 while (e.hasMoreElements())
711 sortTypes[i] = e.nextElement().toString();
712 sortOrder[i] = fr.getOrder(sortTypes[i]);
715 jalview.util.QuickSort.sort(sortOrder, sortTypes);
719 for (i = 0; i < sortTypes.length; i++)
721 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
722 col.setName(sortTypes[i]);
723 col.setRGB(jalview.util.Format.getHexString(fr.getColour(col
725 fcol = fr.getFeatureStyle(sortTypes[i]);
726 if (fcol instanceof GraduatedColor)
728 gcol = (GraduatedColor) fcol;
729 col.setMin(gcol.getMin());
730 col.setMax(gcol.getMax());
731 col.setMinRGB(jalview.util.Format.getHexString(gcol
733 col.setAutoScale(gcol.isAutoScale());
734 col.setThreshold(gcol.getThresh());
735 col.setColourByLabel(gcol.isColourByLabel());
736 switch (gcol.getThreshType())
738 case AnnotationColourGradient.NO_THRESHOLD:
739 col.setThreshType("NONE");
741 case AnnotationColourGradient.ABOVE_THRESHOLD:
742 col.setThreshType("ABOVE");
744 case AnnotationColourGradient.BELOW_THRESHOLD:
745 col.setThreshType("BELOW");
753 } catch (Exception ex)
755 ex.printStackTrace();
760 public void invertSelection()
762 for (int i = 0; i < table.getRowCount(); i++)
764 Boolean value = (Boolean) table.getValueAt(i, 2);
766 table.setValueAt(new Boolean(!value.booleanValue()), i, 2);
770 public void orderByAvWidth()
772 if (table == null || table.getModel() == null)
774 Object[][] data = ((FeatureTableModel) table.getModel()).getData();
775 float[] width = new float[data.length];
779 for (int i = 0; i < data.length; i++)
781 awidth = (float[]) typeWidth.get(data[i][0]);
784 width[i] = awidth[1] / awidth[0];// *awidth[0]*awidth[2]; - better
785 // weight - but have to make per
786 // sequence, too (awidth[2])
787 // if (width[i]==1) // hack to distinguish single width sequences.
797 boolean sort = false;
798 for (int i = 0; i < width.length; i++)
800 // awidth = (float[]) typeWidth.get(data[i][0]);
803 width[i] = fr.getOrder(data[i][0].toString());
806 width[i] = fr.setOrder(data[i][0].toString(), i / data.length);
811 width[i] /= max; // normalize
812 fr.setOrder(data[i][0].toString(), width[i]); // store for later
815 sort = sort || width[i - 1] > width[i];
818 jalview.util.QuickSort.sort(width, data);
819 // update global priority order
821 updateFeatureRenderer(data, false);
829 frame.setClosed(true);
830 } catch (Exception exe)
836 public void updateFeatureRenderer(Object[][] data)
838 updateFeatureRenderer(data, true);
841 private void updateFeatureRenderer(Object[][] data, boolean visibleNew)
843 fr.setFeaturePriority(data, visibleNew);
844 af.alignPanel.paintAlignment(true);
847 int selectedRow = -1;
849 JTabbedPane tabbedPane = new JTabbedPane();
851 BorderLayout borderLayout1 = new BorderLayout();
853 BorderLayout borderLayout2 = new BorderLayout();
855 BorderLayout borderLayout3 = new BorderLayout();
857 JPanel bigPanel = new JPanel();
859 BorderLayout borderLayout4 = new BorderLayout();
861 JButton invert = new JButton();
863 JPanel buttonPanel = new JPanel();
865 JButton cancel = new JButton();
867 JButton ok = new JButton();
869 JButton loadColours = new JButton();
871 JButton saveColours = new JButton();
873 JPanel dasButtonPanel = new JPanel();
875 JButton fetchDAS = new JButton();
877 JButton saveDAS = new JButton();
879 JButton cancelDAS = new JButton();
881 JButton optimizeOrder = new JButton();
883 JButton sortByScore = new JButton();
885 JButton sortByDens = new JButton();
887 JPanel transbuttons = new JPanel(new GridLayout(4, 1));
889 private void jbInit() throws Exception
891 this.setLayout(borderLayout1);
892 settingsPane.setLayout(borderLayout2);
893 dasSettingsPane.setLayout(borderLayout3);
894 bigPanel.setLayout(borderLayout4);
895 invert.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
896 invert.setText("Invert Selection");
897 invert.addActionListener(new ActionListener()
899 public void actionPerformed(ActionEvent e)
904 optimizeOrder.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
905 optimizeOrder.setText("Optimise Order");
906 optimizeOrder.addActionListener(new ActionListener()
908 public void actionPerformed(ActionEvent e)
913 sortByScore.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
914 sortByScore.setText("Seq sort by Score");
915 sortByScore.addActionListener(new ActionListener()
917 public void actionPerformed(ActionEvent e)
922 sortByDens.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
923 sortByDens.setText("Seq Sort by density");
924 sortByDens.addActionListener(new ActionListener()
926 public void actionPerformed(ActionEvent e)
931 cancel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
932 cancel.setText("Cancel");
933 cancel.addActionListener(new ActionListener()
935 public void actionPerformed(ActionEvent e)
937 updateFeatureRenderer(originalData);
941 ok.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
943 ok.addActionListener(new ActionListener()
945 public void actionPerformed(ActionEvent e)
950 loadColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
951 loadColours.setText("Load Colours");
952 loadColours.addActionListener(new ActionListener()
954 public void actionPerformed(ActionEvent e)
959 saveColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
960 saveColours.setText("Save Colours");
961 saveColours.addActionListener(new ActionListener()
963 public void actionPerformed(ActionEvent e)
968 transparency.addChangeListener(new ChangeListener()
970 public void stateChanged(ChangeEvent evt)
972 fr.setTransparency((float) (100 - transparency.getValue()) / 100f);
973 af.alignPanel.paintAlignment(true);
977 transparency.setMaximum(70);
978 fetchDAS.setText("Fetch DAS Features");
979 fetchDAS.addActionListener(new ActionListener()
981 public void actionPerformed(ActionEvent e)
983 fetchDAS_actionPerformed(e);
986 saveDAS.setText("Save as default");
987 saveDAS.addActionListener(new ActionListener()
989 public void actionPerformed(ActionEvent e)
991 saveDAS_actionPerformed(e);
994 dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
995 dasSettingsPane.setBorder(null);
996 cancelDAS.setEnabled(false);
997 cancelDAS.setText("Cancel Fetch");
998 cancelDAS.addActionListener(new ActionListener()
1000 public void actionPerformed(ActionEvent e)
1002 cancelDAS_actionPerformed(e);
1005 this.add(tabbedPane, java.awt.BorderLayout.CENTER);
1006 tabbedPane.addTab("Feature Settings", settingsPane);
1007 tabbedPane.addTab("DAS Settings", dasSettingsPane);
1008 bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
1009 transbuttons.add(optimizeOrder);
1010 transbuttons.add(invert);
1011 transbuttons.add(sortByScore);
1012 transbuttons.add(sortByDens);
1013 transPanel.add(transparency);
1014 transPanel.add(transbuttons);
1015 buttonPanel.add(ok);
1016 buttonPanel.add(cancel);
1017 buttonPanel.add(loadColours);
1018 buttonPanel.add(saveColours);
1019 bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
1020 dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
1021 dasButtonPanel.add(fetchDAS);
1022 dasButtonPanel.add(cancelDAS);
1023 dasButtonPanel.add(saveDAS);
1024 settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);
1025 settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
1028 protected void sortByDens(String[] typ)
1030 sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY);
1033 protected void sortBy(String[] typ, String methodText, final String method)
1037 typ = getDisplayedFeatureTypes();
1039 String gps[] = null;
1040 gps = getDisplayedFeatureGroups();
1043 for (int i = 0; i < typ.length; i++)
1045 System.err.println("Sorting on Types:" + typ[i]);
1051 for (int i = 0; i < gps.length; i++)
1053 System.err.println("Sorting on groups:" + gps[i]);
1056 AlignmentPanel alignPanel = af.alignPanel;
1057 AlignmentI al = alignPanel.av.getAlignment();
1060 SequenceGroup sg = alignPanel.av.getSelectionGroup();
1063 start = sg.getStartRes();
1064 stop = sg.getEndRes();
1069 stop = al.getWidth();
1071 SequenceI[] oldOrder = al.getSequencesArray();
1072 AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
1073 af.addHistoryItem(new OrderCommand(methodText, oldOrder, alignPanel.av
1075 alignPanel.paintAlignment(true);
1079 protected void sortByScore(String[] typ)
1081 sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE);
1084 private String[] getDisplayedFeatureTypes()
1086 String[] typ = null;
1089 synchronized (fr.renderOrder)
1091 typ = new String[fr.renderOrder.length];
1092 System.arraycopy(fr.renderOrder, 0, typ, 0, typ.length);
1093 for (int i = 0; i < typ.length; i++)
1095 if (af.viewport.featuresDisplayed.get(typ[i]) == null)
1105 private String[] getDisplayedFeatureGroups()
1107 String[] gps = null;
1111 if (fr.featureGroups != null)
1113 Enumeration en = fr.featureGroups.keys();
1114 gps = new String[fr.featureColours.size()];
1116 boolean valid = false;
1117 while (en.hasMoreElements())
1119 String gp = (String) en.nextElement();
1120 Boolean on = (Boolean) fr.featureGroups.get(gp);
1121 if (on != null && on.booleanValue())
1127 while (g < gps.length)
1140 public void fetchDAS_actionPerformed(ActionEvent e)
1142 fetchDAS.setEnabled(false);
1143 cancelDAS.setEnabled(true);
1144 Vector selectedSources = dassourceBrowser.getSelectedSources();
1145 doDasFeatureFetch(selectedSources, true, true);
1149 * get the features from selectedSources for all or the current selection
1151 * @param selectedSources
1152 * @param checkDbRefs
1153 * @param promptFetchDbRefs
1155 private void doDasFeatureFetch(Vector selectedSources,
1156 boolean checkDbRefs, boolean promptFetchDbRefs)
1158 SequenceI[] dataset, seqs;
1160 AlignViewport vp = af.getViewport();
1161 if (vp.getSelectionGroup() != null
1162 && vp.getSelectionGroup().getSize() > 0)
1164 iSize = vp.getSelectionGroup().getSize();
1165 dataset = new SequenceI[iSize];
1166 seqs = vp.getSelectionGroup().getSequencesInOrder(vp.getAlignment());
1170 iSize = vp.getAlignment().getHeight();
1171 seqs = vp.getAlignment().getSequencesArray();
1174 dataset = new SequenceI[iSize];
1175 for (int i = 0; i < iSize; i++)
1177 dataset[i] = seqs[i].getDatasetSequence();
1180 cancelDAS.setEnabled(true);
1181 dasFeatureFetcher = new jalview.ws.DasSequenceFeatureFetcher(dataset,
1182 this, selectedSources, checkDbRefs, promptFetchDbRefs);
1183 af.getViewport().setShowSequenceFeatures(true);
1184 af.showSeqFeatures.setSelected(true);
1188 * blocking call to initialise the das source browser
1190 public void initDasSources()
1192 dassourceBrowser.initDasSources();
1196 * examine the current list of das sources and return any matching the given
1197 * nicknames in sources
1200 * Vector of Strings to resolve to DAS source nicknames.
1201 * @return sources that are present in source list.
1203 public Vector resolveSourceNicknames(Vector sources)
1205 return dassourceBrowser.resolveSourceNicknames(sources);
1209 * get currently selected das sources. ensure you have called initDasSources
1210 * before calling this.
1212 * @return vector of selected das source nicknames
1214 public Vector getSelectedSources()
1216 return dassourceBrowser.getSelectedSources();
1220 * properly initialise DAS fetcher and then initiate a new thread to fetch
1221 * features from the named sources (rather than any turned on by default)
1225 * if true then runs in same thread, otherwise passes to the Swing
1228 public void fetchDasFeatures(Vector sources, boolean block)
1231 Vector resolved = resolveSourceNicknames(sources);
1232 if (resolved.size() == 0)
1234 resolved = dassourceBrowser.getSelectedSources();
1236 if (resolved.size() > 0)
1238 final Vector dassources = resolved;
1239 fetchDAS.setEnabled(false);
1240 // cancelDAS.setEnabled(true); doDasFetch does this.
1241 Runnable fetcher = new Runnable()
1246 doDasFeatureFetch(dassources, true, false);
1256 SwingUtilities.invokeLater(fetcher);
1261 public void saveDAS_actionPerformed(ActionEvent e)
1264 .saveProperties(jalview.bin.Cache.applicationProperties);
1267 public void complete()
1269 fetchDAS.setEnabled(true);
1270 cancelDAS.setEnabled(false);
1273 public void cancelDAS_actionPerformed(ActionEvent e)
1275 if (dasFeatureFetcher != null)
1277 dasFeatureFetcher.cancel();
1279 fetchDAS.setEnabled(true);
1280 cancelDAS.setEnabled(false);
1283 public void noDasSourceActive()
1286 JOptionPane.showInternalConfirmDialog(Desktop.desktop,
1287 "No das sources were selected.\n"
1288 + "Please select some sources and\n" + " try again.",
1289 "No Sources Selected", JOptionPane.DEFAULT_OPTION,
1290 JOptionPane.INFORMATION_MESSAGE);
1293 // ///////////////////////////////////////////////////////////////////////
1294 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
1295 // ///////////////////////////////////////////////////////////////////////
1296 class FeatureTableModel extends AbstractTableModel
1298 FeatureTableModel(Object[][] data)
1303 private String[] columnNames =
1304 { "Feature Type", "Colour", "Display" };
1306 private Object[][] data;
1308 public Object[][] getData()
1313 public void setData(Object[][] data)
1318 public int getColumnCount()
1320 return columnNames.length;
1323 public Object[] getRow(int row)
1328 public int getRowCount()
1333 public String getColumnName(int col)
1335 return columnNames[col];
1338 public Object getValueAt(int row, int col)
1340 return data[row][col];
1343 public Class getColumnClass(int c)
1345 return getValueAt(0, c).getClass();
1348 public boolean isCellEditable(int row, int col)
1350 return col == 0 ? false : true;
1353 public void setValueAt(Object value, int row, int col)
1355 data[row][col] = value;
1356 fireTableCellUpdated(row, col);
1357 updateFeatureRenderer(data);
1362 class ColorRenderer extends JLabel implements TableCellRenderer
1364 javax.swing.border.Border unselectedBorder = null;
1366 javax.swing.border.Border selectedBorder = null;
1368 final String baseTT = "Click to edit, right/apple click for menu.";
1370 public ColorRenderer()
1372 setOpaque(true); // MUST do this for background to show up.
1375 public Component getTableCellRendererComponent(JTable table,
1376 Object color, boolean isSelected, boolean hasFocus, int row,
1379 // JLabel comp = new JLabel();
1383 // setBounds(getBounds());
1385 setToolTipText(baseTT);
1386 setBackground(table.getBackground());
1387 if (color instanceof GraduatedColor)
1389 Rectangle cr = table.getCellRect(row, column, false);
1390 FeatureSettings.renderGraduatedColor(this, (GraduatedColor) color,
1391 (int) cr.getWidth(), (int) cr.getHeight());
1398 newColor = (Color) color;
1400 setBackground(newColor);
1401 // comp.setToolTipText("RGB value: " + newColor.getRed() + ", "
1402 // + newColor.getGreen() + ", " + newColor.getBlue());
1406 if (selectedBorder == null)
1408 selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1409 table.getSelectionBackground());
1412 setBorder(selectedBorder);
1416 if (unselectedBorder == null)
1418 unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1419 table.getBackground());
1422 setBorder(unselectedBorder);
1430 * update comp using rendering settings from gcol
1435 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol)
1437 int w = comp.getWidth(), h = comp.getHeight();
1440 w = (int) comp.getPreferredSize().getWidth();
1441 h = (int) comp.getPreferredSize().getHeight();
1448 renderGraduatedColor(comp, gcol, w, h);
1451 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol,
1457 if (gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD)
1460 tt += "Thresholded (Above " + gcol.getThresh() + ") ";
1462 if (gcol.getThreshType() == AnnotationColourGradient.BELOW_THRESHOLD)
1465 tt += "Thresholded (Below " + gcol.getThresh() + ") ";
1467 if (gcol.isColourByLabel())
1469 tt = "Coloured by label text. " + tt;
1475 Color newColor = gcol.getMaxColor();
1476 comp.setBackground(newColor);
1477 System.err.println("Width is " + w / 2);
1478 Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w / 2, h);
1479 comp.setIcon(ficon);
1480 // tt+="RGB value: Max (" + newColor.getRed() + ", "
1481 // + newColor.getGreen() + ", " + newColor.getBlue()
1482 // + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen()
1483 // + ", " + minCol.getBlue() + ")");
1486 if (tt.length() > 0)
1488 if (comp.getToolTipText() == null)
1490 comp.setToolTipText(tt);
1494 comp.setToolTipText(tt + " " + comp.getToolTipText());
1500 class FeatureIcon implements Icon
1502 GraduatedColor gcol;
1506 int width = 50, height = 20;
1508 FeatureIcon(GraduatedColor gfc, Color bg, int w, int h)
1516 public int getIconWidth()
1521 public int getIconHeight()
1526 public void paintIcon(Component c, Graphics g, int x, int y)
1529 if (gcol.isColourByLabel())
1532 g.fillRect(0, 0, width, height);
1533 // need an icon here.
1534 g.setColor(gcol.getMaxColor());
1536 g.setFont(new Font("Verdana", Font.PLAIN, 9));
1538 // g.setFont(g.getFont().deriveFont(
1539 // AffineTransform.getScaleInstance(
1540 // width/g.getFontMetrics().stringWidth("Label"),
1541 // height/g.getFontMetrics().getHeight())));
1543 g.drawString("Label", 0, 0);
1548 Color minCol = gcol.getMinColor();
1550 g.fillRect(0, 0, width, height);
1555 class ColorEditor extends AbstractCellEditor implements TableCellEditor,
1560 GraduatedColor currentGColor;
1562 FeatureColourChooser chooser;
1570 JColorChooser colorChooser;
1574 protected static final String EDIT = "edit";
1576 int selectedRow = 0;
1578 public ColorEditor(FeatureSettings me)
1581 // Set up the editor (from the table's point of view),
1582 // which is a button.
1583 // This button brings up the color chooser dialog,
1584 // which is the editor from the user's point of view.
1585 button = new JButton();
1586 button.setActionCommand(EDIT);
1587 button.addActionListener(this);
1588 button.setBorderPainted(false);
1589 // Set up the dialog that the button brings up.
1590 colorChooser = new JColorChooser();
1591 dialog = JColorChooser.createDialog(button, "Select new Colour", true, // modal
1592 colorChooser, this, // OK button handler
1593 null); // no CANCEL button handler
1597 * Handles events from the editor button and from the dialog's OK button.
1599 public void actionPerformed(ActionEvent e)
1602 if (EDIT.equals(e.getActionCommand()))
1604 // The user has clicked the cell, so
1605 // bring up the dialog.
1606 if (currentColor != null)
1608 // bring up simple color chooser
1609 button.setBackground(currentColor);
1610 colorChooser.setColor(currentColor);
1611 dialog.setVisible(true);
1615 // bring up graduated chooser.
1616 chooser = new FeatureColourChooser(me.fr, type);
1617 chooser.setRequestFocusEnabled(true);
1618 chooser.requestFocus();
1619 chooser.addActionListener(this);
1621 // Make the renderer reappear.
1622 fireEditingStopped();
1626 { // User pressed dialog's "OK" button.
1627 if (currentColor != null)
1629 currentColor = colorChooser.getColor();
1633 // class cast exceptions may be raised if the chooser created on a
1634 // non-graduated color
1635 currentGColor = (GraduatedColor) chooser.getLastColour();
1637 me.table.setValueAt(getCellEditorValue(), selectedRow, 1);
1638 fireEditingStopped();
1639 me.table.validate();
1643 // Implement the one CellEditor method that AbstractCellEditor doesn't.
1644 public Object getCellEditorValue()
1646 if (currentColor == null)
1648 return currentGColor;
1650 return currentColor;
1653 // Implement the one method defined by TableCellEditor.
1654 public Component getTableCellEditorComponent(JTable table, Object value,
1655 boolean isSelected, int row, int column)
1657 currentGColor = null;
1658 currentColor = null;
1659 this.selectedRow = row;
1660 type = me.table.getValueAt(row, 0).toString();
1661 button.setOpaque(true);
1662 button.setBackground(me.getBackground());
1663 if (value instanceof GraduatedColor)
1665 currentGColor = (GraduatedColor) value;
1666 JLabel btn = new JLabel();
1667 btn.setSize(button.getSize());
1668 FeatureSettings.renderGraduatedColor(btn, currentGColor);
1669 button.setBackground(btn.getBackground());
1670 button.setIcon(btn.getIcon());
1671 button.setText(btn.getText());
1676 button.setIcon(null);
1677 currentColor = (Color) value;
1678 button.setBackground(currentColor);