2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.5)
3 * Copyright (C) 2010 J Procter, AM Waterhouse, 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/>.
24 import java.awt.event.*;
25 import java.awt.geom.AffineTransform;
26 import java.awt.image.BufferedImage;
27 import java.beans.PropertyChangeEvent;
28 import java.beans.PropertyChangeListener;
31 import javax.swing.event.*;
32 import javax.swing.table.*;
34 import jalview.analysis.AlignmentSorter;
35 import jalview.bin.Cache;
36 import jalview.commands.OrderCommand;
37 import jalview.datamodel.*;
39 import jalview.schemes.AnnotationColourGradient;
40 import jalview.schemes.GraduatedColor;
42 public class FeatureSettings extends JPanel
44 DasSourceBrowser dassourceBrowser;
46 jalview.ws.DasSequenceFeatureFetcher dasFeatureFetcher;
48 JPanel settingsPane = new JPanel();
50 JPanel dasSettingsPane = new JPanel();
52 final FeatureRenderer fr;
54 public final AlignFrame af;
56 Object[][] originalData;
58 final JInternalFrame frame;
60 JScrollPane scrollPane = new JScrollPane();
66 JSlider transparency = new JSlider();
68 JPanel transPanel = new JPanel(new GridLayout(1, 2));
70 public FeatureSettings(AlignFrame af)
73 fr = af.getFeatureRenderer();
75 transparency.setMaximum(100 - (int) (fr.transparency * 100));
80 } catch (Exception ex)
86 table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));
87 table.setFont(new Font("Verdana", Font.PLAIN, 12));
88 table.setDefaultRenderer(Color.class, new ColorRenderer());
90 table.setDefaultEditor(Color.class, new ColorEditor(this));
92 table.setDefaultEditor(GraduatedColor.class, new ColorEditor(this));
93 table.setDefaultRenderer(GraduatedColor.class, new ColorRenderer());
94 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
96 table.addMouseListener(new MouseAdapter()
98 public void mousePressed(MouseEvent evt)
100 selectedRow = table.rowAtPoint(evt.getPoint());
101 if (javax.swing.SwingUtilities.isRightMouseButton(evt))
103 popupSort(selectedRow, (String) table.getValueAt(selectedRow, 0),
104 table.getValueAt(selectedRow, 1), fr.minmax, evt.getX(),
110 table.addMouseMotionListener(new MouseMotionAdapter()
112 public void mouseDragged(MouseEvent evt)
114 int newRow = table.rowAtPoint(evt.getPoint());
115 if (newRow != selectedRow && selectedRow != -1 && newRow != -1)
117 Object[] temp = new Object[3];
118 temp[0] = table.getValueAt(selectedRow, 0);
119 temp[1] = table.getValueAt(selectedRow, 1);
120 temp[2] = table.getValueAt(selectedRow, 2);
122 table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0);
123 table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1);
124 table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2);
126 table.setValueAt(temp[0], newRow, 0);
127 table.setValueAt(temp[1], newRow, 1);
128 table.setValueAt(temp[2], newRow, 2);
130 selectedRow = newRow;
135 scrollPane.setViewportView(table);
137 dassourceBrowser = new DasSourceBrowser(this);
138 dasSettingsPane.add(dassourceBrowser, BorderLayout.CENTER);
140 if (af.getViewport().featuresDisplayed == null
141 || fr.renderOrder == null)
143 fr.findAllFeatures(true); // display everything!
147 final PropertyChangeListener change;
148 final FeatureSettings fs = this;
149 fr.addPropertyChangeListener(change = new PropertyChangeListener()
151 public void propertyChange(PropertyChangeEvent evt)
153 if (!fs.resettingTable && !fs.handlingUpdate)
155 fs.handlingUpdate = true;
156 fs.resetTable(null); // new groups may be added with new seuqence
157 // feature types only
158 fs.handlingUpdate = false;
164 frame = new JInternalFrame();
165 frame.setContentPane(this);
166 Desktop.addInternalFrame(frame, "Sequence Feature Settings", 400, 450);
168 .addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
170 public void internalFrameClosed(
171 javax.swing.event.InternalFrameEvent evt)
173 fr.removePropertyChangeListener(change);
174 dassourceBrowser.fs = null;
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
614 for (int i = jucs.getColourCount() - 1; i >= 0; i--)
617 jalview.schemabinding.version2.Colour newcol = jucs.getColour(i);
620 Color mincol = null, maxcol = null;
623 mincol = new Color(Integer.parseInt(newcol.getMinRGB(), 16));
624 maxcol = new Color(Integer.parseInt(newcol.getRGB(), 16));
626 } catch (Exception e)
628 Cache.log.warn("Couldn't parse out graduated feature color.",
631 GraduatedColor gcol = new GraduatedColor(mincol, maxcol, newcol
632 .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"))
651 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD);
653 if (ttyp.equalsIgnoreCase("ABOVE"))
656 .setThreshType(AnnotationColourGradient.ABOVE_THRESHOLD);
658 if (ttyp.equalsIgnoreCase("BELOW"))
661 .setThreshType(AnnotationColourGradient.BELOW_THRESHOLD);
664 fr.setColour(name = newcol.getName(), gcol);
668 fr.setColour(name = jucs.getColour(i).getName(), new Color(
669 Integer.parseInt(jucs.getColour(i).getRGB(), 16)));
671 fr.setOrder(name, (i == 0) ? 0 : i / jucs.getColourCount());
676 Object[][] data = ((FeatureTableModel) table.getModel())
679 updateFeatureRenderer(data, false);
682 } catch (Exception ex)
684 System.out.println("Error loading User Colour File\n" + ex);
691 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
692 .getProperty("LAST_DIRECTORY"), new String[]
693 { "fc" }, new String[]
694 { "Sequence Feature Colours" }, "Sequence Feature Colours");
695 chooser.setFileView(new jalview.io.JalviewFileView());
696 chooser.setDialogTitle("Save Feature Colour Scheme");
697 chooser.setToolTipText("Save");
699 int value = chooser.showSaveDialog(this);
701 if (value == JalviewFileChooser.APPROVE_OPTION)
703 String choice = chooser.getSelectedFile().getPath();
704 jalview.schemabinding.version2.JalviewUserColours ucs = new jalview.schemabinding.version2.JalviewUserColours();
705 ucs.setSchemeName("Sequence Features");
708 PrintWriter out = new PrintWriter(new OutputStreamWriter(
709 new FileOutputStream(choice), "UTF-8"));
711 Enumeration e = fr.featureColours.keys();
712 float[] sortOrder = new float[fr.featureColours.size()];
713 String[] sortTypes = new String[fr.featureColours.size()];
715 while (e.hasMoreElements())
717 sortTypes[i] = e.nextElement().toString();
718 sortOrder[i] = fr.getOrder(sortTypes[i]);
721 jalview.util.QuickSort.sort(sortOrder, sortTypes);
725 for (i = 0; i < sortTypes.length; i++)
727 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
728 col.setName(sortTypes[i]);
729 col.setRGB(jalview.util.Format.getHexString(fr.getColour(col
731 fcol = fr.getFeatureStyle(sortTypes[i]);
732 if (fcol instanceof GraduatedColor)
734 gcol = (GraduatedColor) fcol;
735 col.setMin(gcol.getMin());
736 col.setMax(gcol.getMax());
737 col.setMinRGB(jalview.util.Format.getHexString(gcol
739 col.setAutoScale(gcol.isAutoScale());
740 col.setThreshold(gcol.getThresh());
741 col.setColourByLabel(gcol.isColourByLabel());
742 switch (gcol.getThreshType())
744 case AnnotationColourGradient.NO_THRESHOLD:
745 col.setThreshType("NONE");
747 case AnnotationColourGradient.ABOVE_THRESHOLD:
748 col.setThreshType("ABOVE");
750 case AnnotationColourGradient.BELOW_THRESHOLD:
751 col.setThreshType("BELOW");
759 } catch (Exception ex)
761 ex.printStackTrace();
766 public void invertSelection()
768 for (int i = 0; i < table.getRowCount(); i++)
770 Boolean value = (Boolean) table.getValueAt(i, 2);
772 table.setValueAt(new Boolean(!value.booleanValue()), i, 2);
776 public void orderByAvWidth()
778 if (table == null || table.getModel() == null)
780 Object[][] data = ((FeatureTableModel) table.getModel()).getData();
781 float[] width = new float[data.length];
785 for (int i = 0; i < data.length; i++)
787 awidth = (float[]) typeWidth.get(data[i][0]);
790 width[i] = awidth[1] / awidth[0];// *awidth[0]*awidth[2]; - better
791 // weight - but have to make per
792 // sequence, too (awidth[2])
793 // if (width[i]==1) // hack to distinguish single width sequences.
803 boolean sort = false;
804 for (int i = 0; i < width.length; i++)
806 // awidth = (float[]) typeWidth.get(data[i][0]);
809 width[i] = fr.getOrder(data[i][0].toString());
812 width[i] = fr.setOrder(data[i][0].toString(), i / data.length);
817 width[i] /= max; // normalize
818 fr.setOrder(data[i][0].toString(), width[i]); // store for later
821 sort = sort || width[i - 1] > width[i];
824 jalview.util.QuickSort.sort(width, data);
825 // update global priority order
827 updateFeatureRenderer(data, false);
835 frame.setClosed(true);
836 } catch (Exception exe)
842 public void updateFeatureRenderer(Object[][] data)
844 updateFeatureRenderer(data, true);
847 private void updateFeatureRenderer(Object[][] data, boolean visibleNew)
849 fr.setFeaturePriority(data, visibleNew);
850 af.alignPanel.paintAlignment(true);
853 int selectedRow = -1;
855 JTabbedPane tabbedPane = new JTabbedPane();
857 BorderLayout borderLayout1 = new BorderLayout();
859 BorderLayout borderLayout2 = new BorderLayout();
861 BorderLayout borderLayout3 = new BorderLayout();
863 JPanel bigPanel = new JPanel();
865 BorderLayout borderLayout4 = new BorderLayout();
867 JButton invert = new JButton();
869 JPanel buttonPanel = new JPanel();
871 JButton cancel = new JButton();
873 JButton ok = new JButton();
875 JButton loadColours = new JButton();
877 JButton saveColours = new JButton();
879 JPanel dasButtonPanel = new JPanel();
881 JButton fetchDAS = new JButton();
883 JButton saveDAS = new JButton();
885 JButton cancelDAS = new JButton();
887 JButton optimizeOrder = new JButton();
889 JButton sortByScore = new JButton();
891 JButton sortByDens = new JButton();
893 JPanel transbuttons = new JPanel(new GridLayout(4, 1));
895 private void jbInit() throws Exception
897 this.setLayout(borderLayout1);
898 settingsPane.setLayout(borderLayout2);
899 dasSettingsPane.setLayout(borderLayout3);
900 bigPanel.setLayout(borderLayout4);
901 invert.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
902 invert.setText("Invert Selection");
903 invert.addActionListener(new ActionListener()
905 public void actionPerformed(ActionEvent e)
910 optimizeOrder.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
911 optimizeOrder.setText("Optimise Order");
912 optimizeOrder.addActionListener(new ActionListener()
914 public void actionPerformed(ActionEvent e)
919 sortByScore.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
920 sortByScore.setText("Seq sort by Score");
921 sortByScore.addActionListener(new ActionListener()
923 public void actionPerformed(ActionEvent e)
928 sortByDens.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
929 sortByDens.setText("Seq Sort by density");
930 sortByDens.addActionListener(new ActionListener()
932 public void actionPerformed(ActionEvent e)
937 cancel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
938 cancel.setText("Cancel");
939 cancel.addActionListener(new ActionListener()
941 public void actionPerformed(ActionEvent e)
943 updateFeatureRenderer(originalData);
947 ok.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
949 ok.addActionListener(new ActionListener()
951 public void actionPerformed(ActionEvent e)
956 loadColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
957 loadColours.setText("Load Colours");
958 loadColours.addActionListener(new ActionListener()
960 public void actionPerformed(ActionEvent e)
965 saveColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
966 saveColours.setText("Save Colours");
967 saveColours.addActionListener(new ActionListener()
969 public void actionPerformed(ActionEvent e)
974 transparency.addChangeListener(new ChangeListener()
976 public void stateChanged(ChangeEvent evt)
978 fr.setTransparency((float) (100 - transparency.getValue()) / 100f);
979 af.alignPanel.paintAlignment(true);
983 transparency.setMaximum(70);
984 fetchDAS.setText("Fetch DAS Features");
985 fetchDAS.addActionListener(new ActionListener()
987 public void actionPerformed(ActionEvent e)
989 fetchDAS_actionPerformed(e);
992 saveDAS.setText("Save as default");
993 saveDAS.addActionListener(new ActionListener()
995 public void actionPerformed(ActionEvent e)
997 saveDAS_actionPerformed(e);
1000 dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
1001 dasSettingsPane.setBorder(null);
1002 cancelDAS.setEnabled(false);
1003 cancelDAS.setText("Cancel Fetch");
1004 cancelDAS.addActionListener(new ActionListener()
1006 public void actionPerformed(ActionEvent e)
1008 cancelDAS_actionPerformed(e);
1011 this.add(tabbedPane, java.awt.BorderLayout.CENTER);
1012 tabbedPane.addTab("Feature Settings", settingsPane);
1013 tabbedPane.addTab("DAS Settings", dasSettingsPane);
1014 bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
1015 transbuttons.add(optimizeOrder);
1016 transbuttons.add(invert);
1017 transbuttons.add(sortByScore);
1018 transbuttons.add(sortByDens);
1019 transPanel.add(transparency);
1020 transPanel.add(transbuttons);
1021 buttonPanel.add(ok);
1022 buttonPanel.add(cancel);
1023 buttonPanel.add(loadColours);
1024 buttonPanel.add(saveColours);
1025 bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
1026 dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
1027 dasButtonPanel.add(fetchDAS);
1028 dasButtonPanel.add(cancelDAS);
1029 dasButtonPanel.add(saveDAS);
1030 settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);
1031 settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
1034 protected void sortByDens(String[] typ)
1036 sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY);
1039 protected void sortBy(String[] typ, String methodText, final String method)
1043 typ = getDisplayedFeatureTypes();
1045 String gps[] = null;
1046 gps = getDisplayedFeatureGroups();
1049 ArrayList types = new ArrayList();
1050 for (int i = 0; i < typ.length; i++)
1056 typ = new String[types.size()];
1062 ArrayList grps = new ArrayList();
1064 for (int i = 0; i < gps.length; i++)
1071 gps = new String[grps.size()];
1074 AlignmentPanel alignPanel = af.alignPanel;
1075 AlignmentI al = alignPanel.av.getAlignment();
1078 SequenceGroup sg = alignPanel.av.getSelectionGroup();
1081 start = sg.getStartRes();
1082 stop = sg.getEndRes();
1087 stop = al.getWidth();
1089 SequenceI[] oldOrder = al.getSequencesArray();
1090 AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
1091 af.addHistoryItem(new OrderCommand(methodText, oldOrder, alignPanel.av
1093 alignPanel.paintAlignment(true);
1097 protected void sortByScore(String[] typ)
1099 sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE);
1102 private String[] getDisplayedFeatureTypes()
1104 String[] typ = null;
1107 synchronized (fr.renderOrder)
1109 typ = new String[fr.renderOrder.length];
1110 System.arraycopy(fr.renderOrder, 0, typ, 0, typ.length);
1111 for (int i = 0; i < typ.length; i++)
1113 if (af.viewport.featuresDisplayed.get(typ[i]) == null)
1123 private String[] getDisplayedFeatureGroups()
1125 String[] gps = null;
1129 if (fr.featureGroups != null)
1131 Enumeration en = fr.featureGroups.keys();
1132 gps = new String[fr.featureColours.size()];
1134 boolean valid = false;
1135 while (en.hasMoreElements())
1137 String gp = (String) en.nextElement();
1138 Boolean on = (Boolean) fr.featureGroups.get(gp);
1139 if (on != null && on.booleanValue())
1145 while (g < gps.length)
1158 public void fetchDAS_actionPerformed(ActionEvent e)
1160 fetchDAS.setEnabled(false);
1161 cancelDAS.setEnabled(true);
1162 dassourceBrowser.setGuiEnabled(false);
1163 Vector selectedSources = dassourceBrowser.getSelectedSources();
1164 doDasFeatureFetch(selectedSources, true, true);
1168 * get the features from selectedSources for all or the current selection
1170 * @param selectedSources
1171 * @param checkDbRefs
1172 * @param promptFetchDbRefs
1174 private void doDasFeatureFetch(Vector selectedSources,
1175 boolean checkDbRefs, boolean promptFetchDbRefs)
1177 SequenceI[] dataset, seqs;
1179 AlignViewport vp = af.getViewport();
1180 if (vp.getSelectionGroup() != null
1181 && vp.getSelectionGroup().getSize() > 0)
1183 iSize = vp.getSelectionGroup().getSize();
1184 dataset = new SequenceI[iSize];
1185 seqs = vp.getSelectionGroup().getSequencesInOrder(vp.getAlignment());
1189 iSize = vp.getAlignment().getHeight();
1190 seqs = vp.getAlignment().getSequencesArray();
1193 dataset = new SequenceI[iSize];
1194 for (int i = 0; i < iSize; i++)
1196 dataset[i] = seqs[i].getDatasetSequence();
1199 cancelDAS.setEnabled(true);
1200 dasFeatureFetcher = new jalview.ws.DasSequenceFeatureFetcher(dataset,
1201 this, selectedSources, checkDbRefs, promptFetchDbRefs);
1202 af.getViewport().setShowSequenceFeatures(true);
1203 af.showSeqFeatures.setSelected(true);
1207 * blocking call to initialise the das source browser
1209 public void initDasSources()
1211 dassourceBrowser.initDasSources();
1215 * examine the current list of das sources and return any matching the given
1216 * nicknames in sources
1219 * Vector of Strings to resolve to DAS source nicknames.
1220 * @return sources that are present in source list.
1222 public Vector resolveSourceNicknames(Vector sources)
1224 return dassourceBrowser.resolveSourceNicknames(sources);
1228 * get currently selected das sources. ensure you have called initDasSources
1229 * before calling this.
1231 * @return vector of selected das source nicknames
1233 public Vector getSelectedSources()
1235 return dassourceBrowser.getSelectedSources();
1239 * properly initialise DAS fetcher and then initiate a new thread to fetch
1240 * features from the named sources (rather than any turned on by default)
1244 * if true then runs in same thread, otherwise passes to the Swing
1247 public void fetchDasFeatures(Vector sources, boolean block)
1250 Vector resolved = resolveSourceNicknames(sources);
1251 if (resolved.size() == 0)
1253 resolved = dassourceBrowser.getSelectedSources();
1255 if (resolved.size() > 0)
1257 final Vector dassources = resolved;
1258 fetchDAS.setEnabled(false);
1259 // cancelDAS.setEnabled(true); doDasFetch does this.
1260 Runnable fetcher = new Runnable()
1265 doDasFeatureFetch(dassources, true, false);
1275 SwingUtilities.invokeLater(fetcher);
1280 public void saveDAS_actionPerformed(ActionEvent e)
1283 .saveProperties(jalview.bin.Cache.applicationProperties);
1286 public void complete()
1288 fetchDAS.setEnabled(true);
1289 cancelDAS.setEnabled(false);
1290 dassourceBrowser.setGuiEnabled(true);
1294 public void cancelDAS_actionPerformed(ActionEvent e)
1296 if (dasFeatureFetcher != null)
1298 dasFeatureFetcher.cancel();
1303 public void noDasSourceActive()
1306 JOptionPane.showInternalConfirmDialog(Desktop.desktop,
1307 "No das sources were selected.\n"
1308 + "Please select some sources and\n" + " try again.",
1309 "No Sources Selected", JOptionPane.DEFAULT_OPTION,
1310 JOptionPane.INFORMATION_MESSAGE);
1313 // ///////////////////////////////////////////////////////////////////////
1314 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
1315 // ///////////////////////////////////////////////////////////////////////
1316 class FeatureTableModel extends AbstractTableModel
1318 FeatureTableModel(Object[][] data)
1323 private String[] columnNames =
1324 { "Feature Type", "Colour", "Display" };
1326 private Object[][] data;
1328 public Object[][] getData()
1333 public void setData(Object[][] data)
1338 public int getColumnCount()
1340 return columnNames.length;
1343 public Object[] getRow(int row)
1348 public int getRowCount()
1353 public String getColumnName(int col)
1355 return columnNames[col];
1358 public Object getValueAt(int row, int col)
1360 return data[row][col];
1363 public Class getColumnClass(int c)
1365 return getValueAt(0, c).getClass();
1368 public boolean isCellEditable(int row, int col)
1370 return col == 0 ? false : true;
1373 public void setValueAt(Object value, int row, int col)
1375 data[row][col] = value;
1376 fireTableCellUpdated(row, col);
1377 updateFeatureRenderer(data);
1382 class ColorRenderer extends JLabel implements TableCellRenderer
1384 javax.swing.border.Border unselectedBorder = null;
1386 javax.swing.border.Border selectedBorder = null;
1388 final String baseTT = "Click to edit, right/apple click for menu.";
1390 public ColorRenderer()
1392 setOpaque(true); // MUST do this for background to show up.
1393 setHorizontalTextPosition(SwingConstants.CENTER);
1394 setVerticalTextPosition(SwingConstants.CENTER);
1397 public Component getTableCellRendererComponent(JTable table,
1398 Object color, boolean isSelected, boolean hasFocus, int row,
1401 // JLabel comp = new JLabel();
1405 // setBounds(getBounds());
1407 setToolTipText(baseTT);
1408 setBackground(table.getBackground());
1409 if (color instanceof GraduatedColor)
1411 Rectangle cr = table.getCellRect(row, column, false);
1412 FeatureSettings.renderGraduatedColor(this, (GraduatedColor) color,
1413 (int) cr.getWidth(), (int) cr.getHeight());
1420 newColor = (Color) color;
1422 setBackground(newColor);
1423 // comp.setToolTipText("RGB value: " + newColor.getRed() + ", "
1424 // + newColor.getGreen() + ", " + newColor.getBlue());
1428 if (selectedBorder == null)
1430 selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1431 table.getSelectionBackground());
1434 setBorder(selectedBorder);
1438 if (unselectedBorder == null)
1440 unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1441 table.getBackground());
1444 setBorder(unselectedBorder);
1452 * update comp using rendering settings from gcol
1457 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol)
1459 int w = comp.getWidth(), h = comp.getHeight();
1462 w = (int) comp.getPreferredSize().getWidth();
1463 h = (int) comp.getPreferredSize().getHeight();
1470 renderGraduatedColor(comp, gcol, w, h);
1473 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol,
1476 boolean thr = false;
1479 if (gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD)
1483 tt += "Thresholded (Above " + gcol.getThresh() + ") ";
1485 if (gcol.getThreshType() == AnnotationColourGradient.BELOW_THRESHOLD)
1489 tt += "Thresholded (Below " + gcol.getThresh() + ") ";
1491 if (gcol.isColourByLabel())
1493 tt = "Coloured by label text. " + tt;
1503 Color newColor = gcol.getMaxColor();
1504 comp.setBackground(newColor);
1505 // System.err.println("Width is " + w / 2);
1506 Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w, h, thr);
1507 comp.setIcon(ficon);
1508 // tt+="RGB value: Max (" + newColor.getRed() + ", "
1509 // + newColor.getGreen() + ", " + newColor.getBlue()
1510 // + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen()
1511 // + ", " + minCol.getBlue() + ")");
1513 comp.setHorizontalAlignment(SwingConstants.CENTER);
1515 if (tt.length() > 0)
1517 if (comp.getToolTipText() == null)
1519 comp.setToolTipText(tt);
1523 comp.setToolTipText(tt + " " + comp.getToolTipText());
1529 class FeatureIcon implements Icon
1531 GraduatedColor gcol;
1535 boolean midspace = false;
1537 int width = 50, height = 20;
1539 int s1, e1; // start and end of midpoint band for thresholded symbol
1541 Color mpcolour = Color.white;
1543 FeatureIcon(GraduatedColor gfc, Color bg, int w, int h, boolean mspace)
1562 public int getIconWidth()
1567 public int getIconHeight()
1572 public void paintIcon(Component c, Graphics g, int x, int y)
1575 if (gcol.isColourByLabel())
1578 g.fillRect(0, 0, width, height);
1579 // need an icon here.
1580 g.setColor(gcol.getMaxColor());
1582 g.setFont(new Font("Verdana", Font.PLAIN, 9));
1584 // g.setFont(g.getFont().deriveFont(
1585 // AffineTransform.getScaleInstance(
1586 // width/g.getFontMetrics().stringWidth("Label"),
1587 // height/g.getFontMetrics().getHeight())));
1589 g.drawString("Label", 0, 0);
1594 Color minCol = gcol.getMinColor();
1596 g.fillRect(0, 0, s1, height);
1599 g.setColor(Color.white);
1600 g.fillRect(s1, 0, e1 - s1, height);
1602 g.setColor(gcol.getMaxColor());
1603 g.fillRect(0, e1, width - e1, height);
1608 class ColorEditor extends AbstractCellEditor implements TableCellEditor,
1613 GraduatedColor currentGColor;
1615 FeatureColourChooser chooser;
1623 JColorChooser colorChooser;
1627 protected static final String EDIT = "edit";
1629 int selectedRow = 0;
1631 public ColorEditor(FeatureSettings me)
1634 // Set up the editor (from the table's point of view),
1635 // which is a button.
1636 // This button brings up the color chooser dialog,
1637 // which is the editor from the user's point of view.
1638 button = new JButton();
1639 button.setActionCommand(EDIT);
1640 button.addActionListener(this);
1641 button.setBorderPainted(false);
1642 // Set up the dialog that the button brings up.
1643 colorChooser = new JColorChooser();
1644 dialog = JColorChooser.createDialog(button, "Select new Colour", true, // modal
1645 colorChooser, this, // OK button handler
1646 null); // no CANCEL button handler
1650 * Handles events from the editor button and from the dialog's OK button.
1652 public void actionPerformed(ActionEvent e)
1655 if (EDIT.equals(e.getActionCommand()))
1657 // The user has clicked the cell, so
1658 // bring up the dialog.
1659 if (currentColor != null)
1661 // bring up simple color chooser
1662 button.setBackground(currentColor);
1663 colorChooser.setColor(currentColor);
1664 dialog.setVisible(true);
1668 // bring up graduated chooser.
1669 chooser = new FeatureColourChooser(me.fr, type);
1670 chooser.setRequestFocusEnabled(true);
1671 chooser.requestFocus();
1672 chooser.addActionListener(this);
1674 // Make the renderer reappear.
1675 fireEditingStopped();
1679 { // User pressed dialog's "OK" button.
1680 if (currentColor != null)
1682 currentColor = colorChooser.getColor();
1686 // class cast exceptions may be raised if the chooser created on a
1687 // non-graduated color
1688 currentGColor = (GraduatedColor) chooser.getLastColour();
1690 me.table.setValueAt(getCellEditorValue(), selectedRow, 1);
1691 fireEditingStopped();
1692 me.table.validate();
1696 // Implement the one CellEditor method that AbstractCellEditor doesn't.
1697 public Object getCellEditorValue()
1699 if (currentColor == null)
1701 return currentGColor;
1703 return currentColor;
1706 // Implement the one method defined by TableCellEditor.
1707 public Component getTableCellEditorComponent(JTable table, Object value,
1708 boolean isSelected, int row, int column)
1710 currentGColor = null;
1711 currentColor = null;
1712 this.selectedRow = row;
1713 type = me.table.getValueAt(row, 0).toString();
1714 button.setOpaque(true);
1715 button.setBackground(me.getBackground());
1716 if (value instanceof GraduatedColor)
1718 currentGColor = (GraduatedColor) value;
1719 JLabel btn = new JLabel();
1720 btn.setSize(button.getSize());
1721 FeatureSettings.renderGraduatedColor(btn, currentGColor);
1722 button.setBackground(btn.getBackground());
1723 button.setIcon(btn.getIcon());
1724 button.setText(btn.getText());
1729 button.setIcon(null);
1730 currentColor = (Color) value;
1731 button.setBackground(currentColor);