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 ArrayList types = new ArrayList();
1044 for (int i = 0; i < typ.length; i++)
1050 typ = new String[types.size()];
1056 ArrayList grps = new ArrayList();
1058 for (int i = 0; i < gps.length; i++)
1064 gps = new String[grps.size()];
1067 AlignmentPanel alignPanel = af.alignPanel;
1068 AlignmentI al = alignPanel.av.getAlignment();
1071 SequenceGroup sg = alignPanel.av.getSelectionGroup();
1074 start = sg.getStartRes();
1075 stop = sg.getEndRes();
1080 stop = al.getWidth();
1082 SequenceI[] oldOrder = al.getSequencesArray();
1083 AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
1084 af.addHistoryItem(new OrderCommand(methodText, oldOrder, alignPanel.av
1086 alignPanel.paintAlignment(true);
1090 protected void sortByScore(String[] typ)
1092 sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE);
1095 private String[] getDisplayedFeatureTypes()
1097 String[] typ = null;
1100 synchronized (fr.renderOrder)
1102 typ = new String[fr.renderOrder.length];
1103 System.arraycopy(fr.renderOrder, 0, typ, 0, typ.length);
1104 for (int i = 0; i < typ.length; i++)
1106 if (af.viewport.featuresDisplayed.get(typ[i]) == null)
1116 private String[] getDisplayedFeatureGroups()
1118 String[] gps = null;
1122 if (fr.featureGroups != null)
1124 Enumeration en = fr.featureGroups.keys();
1125 gps = new String[fr.featureColours.size()];
1127 boolean valid = false;
1128 while (en.hasMoreElements())
1130 String gp = (String) en.nextElement();
1131 Boolean on = (Boolean) fr.featureGroups.get(gp);
1132 if (on != null && on.booleanValue())
1138 while (g < gps.length)
1151 public void fetchDAS_actionPerformed(ActionEvent e)
1153 fetchDAS.setEnabled(false);
1154 cancelDAS.setEnabled(true);
1155 Vector selectedSources = dassourceBrowser.getSelectedSources();
1156 doDasFeatureFetch(selectedSources, true, true);
1160 * get the features from selectedSources for all or the current selection
1162 * @param selectedSources
1163 * @param checkDbRefs
1164 * @param promptFetchDbRefs
1166 private void doDasFeatureFetch(Vector selectedSources,
1167 boolean checkDbRefs, boolean promptFetchDbRefs)
1169 SequenceI[] dataset, seqs;
1171 AlignViewport vp = af.getViewport();
1172 if (vp.getSelectionGroup() != null
1173 && vp.getSelectionGroup().getSize() > 0)
1175 iSize = vp.getSelectionGroup().getSize();
1176 dataset = new SequenceI[iSize];
1177 seqs = vp.getSelectionGroup().getSequencesInOrder(vp.getAlignment());
1181 iSize = vp.getAlignment().getHeight();
1182 seqs = vp.getAlignment().getSequencesArray();
1185 dataset = new SequenceI[iSize];
1186 for (int i = 0; i < iSize; i++)
1188 dataset[i] = seqs[i].getDatasetSequence();
1191 cancelDAS.setEnabled(true);
1192 dasFeatureFetcher = new jalview.ws.DasSequenceFeatureFetcher(dataset,
1193 this, selectedSources, checkDbRefs, promptFetchDbRefs);
1194 af.getViewport().setShowSequenceFeatures(true);
1195 af.showSeqFeatures.setSelected(true);
1199 * blocking call to initialise the das source browser
1201 public void initDasSources()
1203 dassourceBrowser.initDasSources();
1207 * examine the current list of das sources and return any matching the given
1208 * nicknames in sources
1211 * Vector of Strings to resolve to DAS source nicknames.
1212 * @return sources that are present in source list.
1214 public Vector resolveSourceNicknames(Vector sources)
1216 return dassourceBrowser.resolveSourceNicknames(sources);
1220 * get currently selected das sources. ensure you have called initDasSources
1221 * before calling this.
1223 * @return vector of selected das source nicknames
1225 public Vector getSelectedSources()
1227 return dassourceBrowser.getSelectedSources();
1231 * properly initialise DAS fetcher and then initiate a new thread to fetch
1232 * features from the named sources (rather than any turned on by default)
1236 * if true then runs in same thread, otherwise passes to the Swing
1239 public void fetchDasFeatures(Vector sources, boolean block)
1242 Vector resolved = resolveSourceNicknames(sources);
1243 if (resolved.size() == 0)
1245 resolved = dassourceBrowser.getSelectedSources();
1247 if (resolved.size() > 0)
1249 final Vector dassources = resolved;
1250 fetchDAS.setEnabled(false);
1251 // cancelDAS.setEnabled(true); doDasFetch does this.
1252 Runnable fetcher = new Runnable()
1257 doDasFeatureFetch(dassources, true, false);
1267 SwingUtilities.invokeLater(fetcher);
1272 public void saveDAS_actionPerformed(ActionEvent e)
1275 .saveProperties(jalview.bin.Cache.applicationProperties);
1278 public void complete()
1280 fetchDAS.setEnabled(true);
1281 cancelDAS.setEnabled(false);
1284 public void cancelDAS_actionPerformed(ActionEvent e)
1286 if (dasFeatureFetcher != null)
1288 dasFeatureFetcher.cancel();
1290 fetchDAS.setEnabled(true);
1291 cancelDAS.setEnabled(false);
1294 public void noDasSourceActive()
1297 JOptionPane.showInternalConfirmDialog(Desktop.desktop,
1298 "No das sources were selected.\n"
1299 + "Please select some sources and\n" + " try again.",
1300 "No Sources Selected", JOptionPane.DEFAULT_OPTION,
1301 JOptionPane.INFORMATION_MESSAGE);
1304 // ///////////////////////////////////////////////////////////////////////
1305 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
1306 // ///////////////////////////////////////////////////////////////////////
1307 class FeatureTableModel extends AbstractTableModel
1309 FeatureTableModel(Object[][] data)
1314 private String[] columnNames =
1315 { "Feature Type", "Colour", "Display" };
1317 private Object[][] data;
1319 public Object[][] getData()
1324 public void setData(Object[][] data)
1329 public int getColumnCount()
1331 return columnNames.length;
1334 public Object[] getRow(int row)
1339 public int getRowCount()
1344 public String getColumnName(int col)
1346 return columnNames[col];
1349 public Object getValueAt(int row, int col)
1351 return data[row][col];
1354 public Class getColumnClass(int c)
1356 return getValueAt(0, c).getClass();
1359 public boolean isCellEditable(int row, int col)
1361 return col == 0 ? false : true;
1364 public void setValueAt(Object value, int row, int col)
1366 data[row][col] = value;
1367 fireTableCellUpdated(row, col);
1368 updateFeatureRenderer(data);
1373 class ColorRenderer extends JLabel implements TableCellRenderer
1375 javax.swing.border.Border unselectedBorder = null;
1377 javax.swing.border.Border selectedBorder = null;
1379 final String baseTT = "Click to edit, right/apple click for menu.";
1381 public ColorRenderer()
1383 setOpaque(true); // MUST do this for background to show up.
1384 setHorizontalTextPosition(SwingConstants.CENTER);
1385 setVerticalTextPosition(SwingConstants.CENTER);
1388 public Component getTableCellRendererComponent(JTable table,
1389 Object color, boolean isSelected, boolean hasFocus, int row,
1392 // JLabel comp = new JLabel();
1396 // setBounds(getBounds());
1398 setToolTipText(baseTT);
1399 setBackground(table.getBackground());
1400 if (color instanceof GraduatedColor)
1402 Rectangle cr = table.getCellRect(row, column, false);
1403 FeatureSettings.renderGraduatedColor(this, (GraduatedColor) color,
1404 (int) cr.getWidth(), (int) cr.getHeight());
1411 newColor = (Color) color;
1413 setBackground(newColor);
1414 // comp.setToolTipText("RGB value: " + newColor.getRed() + ", "
1415 // + newColor.getGreen() + ", " + newColor.getBlue());
1419 if (selectedBorder == null)
1421 selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1422 table.getSelectionBackground());
1425 setBorder(selectedBorder);
1429 if (unselectedBorder == null)
1431 unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1432 table.getBackground());
1435 setBorder(unselectedBorder);
1443 * update comp using rendering settings from gcol
1448 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol)
1450 int w = comp.getWidth(), h = comp.getHeight();
1453 w = (int) comp.getPreferredSize().getWidth();
1454 h = (int) comp.getPreferredSize().getHeight();
1461 renderGraduatedColor(comp, gcol, w, h);
1464 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol,
1470 if (gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD)
1474 tt += "Thresholded (Above " + gcol.getThresh() + ") ";
1476 if (gcol.getThreshType() == AnnotationColourGradient.BELOW_THRESHOLD)
1480 tt += "Thresholded (Below " + gcol.getThresh() + ") ";
1482 if (gcol.isColourByLabel())
1484 tt = "Coloured by label text. " + tt;
1494 Color newColor = gcol.getMaxColor();
1495 comp.setBackground(newColor);
1496 // System.err.println("Width is " + w / 2);
1497 Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w, h, thr);
1498 comp.setIcon(ficon);
1499 // tt+="RGB value: Max (" + newColor.getRed() + ", "
1500 // + newColor.getGreen() + ", " + newColor.getBlue()
1501 // + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen()
1502 // + ", " + minCol.getBlue() + ")");
1504 comp.setHorizontalAlignment(SwingConstants.CENTER);
1506 if (tt.length() > 0)
1508 if (comp.getToolTipText() == null)
1510 comp.setToolTipText(tt);
1514 comp.setToolTipText(tt + " " + comp.getToolTipText());
1520 class FeatureIcon implements Icon
1522 GraduatedColor gcol;
1525 boolean midspace=false;
1526 int width = 50, height = 20;
1527 int s1,e1; // start and end of midpoint band for thresholded symbol
1528 Color mpcolour = Color.white;
1530 FeatureIcon(GraduatedColor gfc, Color bg, int w, int h, boolean mspace)
1547 public int getIconWidth()
1552 public int getIconHeight()
1557 public void paintIcon(Component c, Graphics g, int x, int y)
1560 if (gcol.isColourByLabel())
1563 g.fillRect(0, 0, width, height);
1564 // need an icon here.
1565 g.setColor(gcol.getMaxColor());
1567 g.setFont(new Font("Verdana", Font.PLAIN, 9));
1569 // g.setFont(g.getFont().deriveFont(
1570 // AffineTransform.getScaleInstance(
1571 // width/g.getFontMetrics().stringWidth("Label"),
1572 // height/g.getFontMetrics().getHeight())));
1574 g.drawString("Label", 0, 0);
1579 Color minCol = gcol.getMinColor();
1581 g.fillRect(0, 0, s1, height);
1584 g.setColor(Color.white);
1585 g.fillRect(s1,0,e1-s1, height);
1587 g.setColor(gcol.getMaxColor());
1588 g.fillRect(0,e1, width-e1, height);
1593 class ColorEditor extends AbstractCellEditor implements TableCellEditor,
1598 GraduatedColor currentGColor;
1600 FeatureColourChooser chooser;
1608 JColorChooser colorChooser;
1612 protected static final String EDIT = "edit";
1614 int selectedRow = 0;
1616 public ColorEditor(FeatureSettings me)
1619 // Set up the editor (from the table's point of view),
1620 // which is a button.
1621 // This button brings up the color chooser dialog,
1622 // which is the editor from the user's point of view.
1623 button = new JButton();
1624 button.setActionCommand(EDIT);
1625 button.addActionListener(this);
1626 button.setBorderPainted(false);
1627 // Set up the dialog that the button brings up.
1628 colorChooser = new JColorChooser();
1629 dialog = JColorChooser.createDialog(button, "Select new Colour", true, // modal
1630 colorChooser, this, // OK button handler
1631 null); // no CANCEL button handler
1635 * Handles events from the editor button and from the dialog's OK button.
1637 public void actionPerformed(ActionEvent e)
1640 if (EDIT.equals(e.getActionCommand()))
1642 // The user has clicked the cell, so
1643 // bring up the dialog.
1644 if (currentColor != null)
1646 // bring up simple color chooser
1647 button.setBackground(currentColor);
1648 colorChooser.setColor(currentColor);
1649 dialog.setVisible(true);
1653 // bring up graduated chooser.
1654 chooser = new FeatureColourChooser(me.fr, type);
1655 chooser.setRequestFocusEnabled(true);
1656 chooser.requestFocus();
1657 chooser.addActionListener(this);
1659 // Make the renderer reappear.
1660 fireEditingStopped();
1664 { // User pressed dialog's "OK" button.
1665 if (currentColor != null)
1667 currentColor = colorChooser.getColor();
1671 // class cast exceptions may be raised if the chooser created on a
1672 // non-graduated color
1673 currentGColor = (GraduatedColor) chooser.getLastColour();
1675 me.table.setValueAt(getCellEditorValue(), selectedRow, 1);
1676 fireEditingStopped();
1677 me.table.validate();
1681 // Implement the one CellEditor method that AbstractCellEditor doesn't.
1682 public Object getCellEditorValue()
1684 if (currentColor == null)
1686 return currentGColor;
1688 return currentColor;
1691 // Implement the one method defined by TableCellEditor.
1692 public Component getTableCellEditorComponent(JTable table, Object value,
1693 boolean isSelected, int row, int column)
1695 currentGColor = null;
1696 currentColor = null;
1697 this.selectedRow = row;
1698 type = me.table.getValueAt(row, 0).toString();
1699 button.setOpaque(true);
1700 button.setBackground(me.getBackground());
1701 if (value instanceof GraduatedColor)
1703 currentGColor = (GraduatedColor) value;
1704 JLabel btn = new JLabel();
1705 btn.setSize(button.getSize());
1706 FeatureSettings.renderGraduatedColor(btn, currentGColor);
1707 button.setBackground(btn.getBackground());
1708 button.setIcon(btn.getIcon());
1709 button.setText(btn.getText());
1714 button.setIcon(null);
1715 currentColor = (Color) value;
1716 button.setBackground(currentColor);