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();
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);
176 frame.setLayer(JLayeredPane.PALETTE_LAYER);
179 protected void popupSort(final int selectedRow, final String type,
180 final Object typeCol, final Hashtable minmax, int x, int y)
182 JPopupMenu men = new JPopupMenu("Settings for " + type);
183 JMenuItem scr = new JMenuItem("Sort by Score");
185 final FeatureSettings me = this;
186 scr.addActionListener(new ActionListener()
189 public void actionPerformed(ActionEvent e)
191 me.sortByScore(new String[]
196 JMenuItem dens = new JMenuItem("Sort by Density");
197 dens.addActionListener(new ActionListener()
200 public void actionPerformed(ActionEvent e)
202 me.sortByDens(new String[]
210 final Object typeMinMax = minmax.get(type);
212 * final JCheckBoxMenuItem chb = new JCheckBoxMenuItem("Vary Height"); //
213 * this is broken at the moment and isn't that useful anyway!
214 * chb.setSelected(minmax.get(type) != null); chb.addActionListener(new
217 * public void actionPerformed(ActionEvent e) {
218 * chb.setState(chb.getState()); if (chb.getState()) { minmax.put(type,
219 * null); } else { minmax.put(type, typeMinMax); } }
225 if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null)
227 // if (table.getValueAt(row, column));
228 // graduated colourschemes for those where minmax exists for the
229 // positional features
230 final JCheckBoxMenuItem mxcol = new JCheckBoxMenuItem(
232 mxcol.setSelected(!(typeCol instanceof Color));
234 mxcol.addActionListener(new ActionListener()
236 JColorChooser colorChooser;
238 public void actionPerformed(ActionEvent e)
240 if (e.getSource() == mxcol)
242 if (typeCol instanceof Color)
244 FeatureColourChooser fc = new FeatureColourChooser(me.fr,
246 fc.addActionListener(this);
250 // bring up simple color chooser
251 colorChooser = new JColorChooser();
252 JDialog dialog = JColorChooser.createDialog(me,
253 "Select new Colour", true, // modal
254 colorChooser, this, // OK button handler
255 null); // no CANCEL button handler
256 colorChooser.setColor(((GraduatedColor) typeCol)
258 dialog.setVisible(true);
263 if (e.getSource() instanceof FeatureColourChooser)
265 FeatureColourChooser fc = (FeatureColourChooser) e
267 table.setValueAt(fc.getLastColour(), selectedRow, 1);
272 // probably the color chooser!
273 table.setValueAt(colorChooser.getColor(), selectedRow, 1);
275 me.updateFeatureRenderer(((FeatureTableModel) table
276 .getModel()).getData(), false);
284 men.show(table, x, y);
288 * true when Feature Settings are updating from feature renderer
290 private boolean handlingUpdate = false;
293 * contains a float[3] for each feature type string. created by setTableData
295 Hashtable typeWidth = null;
297 synchronized public void setTableData()
299 if (fr.featureGroups == null)
301 fr.featureGroups = new Hashtable();
303 Vector allFeatures = new Vector();
304 Vector allGroups = new Vector();
305 SequenceFeature[] tmpfeatures;
307 for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)
309 if (af.getViewport().alignment.getSequenceAt(i).getDatasetSequence()
310 .getSequenceFeatures() == null)
315 tmpfeatures = af.getViewport().alignment.getSequenceAt(i)
316 .getDatasetSequence().getSequenceFeatures();
319 while (index < tmpfeatures.length)
321 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
327 if (tmpfeatures[index].getFeatureGroup() != null)
329 group = tmpfeatures[index].featureGroup;
330 if (!allGroups.contains(group))
332 allGroups.addElement(group);
335 checkGroupState(group);
340 if (!allFeatures.contains(tmpfeatures[index].getType()))
342 allFeatures.addElement(tmpfeatures[index].getType());
356 * @return true if group has been seen before and is already added to set.
358 private boolean checkGroupState(String group)
361 if (fr.featureGroups.containsKey(group))
363 visible = ((Boolean) fr.featureGroups.get(group)).booleanValue();
367 visible = true; // new group is always made visible
370 if (groupPanel == null)
372 groupPanel = new JPanel();
375 boolean alreadyAdded = false;
376 for (int g = 0; g < groupPanel.getComponentCount(); g++)
378 if (((JCheckBox) groupPanel.getComponent(g)).getText().equals(group))
381 ((JCheckBox) groupPanel.getComponent(g)).setSelected(visible);
392 fr.featureGroups.put(group, new Boolean(visible));
393 final String grp = group;
394 final JCheckBox check = new JCheckBox(group, visible);
395 check.setFont(new Font("Serif", Font.BOLD, 12));
396 check.addItemListener(new ItemListener()
398 public void itemStateChanged(ItemEvent evt)
400 fr.featureGroups.put(check.getText(), new Boolean(check
402 af.alignPanel.seqPanel.seqCanvas.repaint();
403 if (af.alignPanel.overviewPanel != null)
405 af.alignPanel.overviewPanel.updateOverviewImage();
408 resetTable(new String[]
412 groupPanel.add(check);
416 boolean resettingTable = false;
418 synchronized void resetTable(String[] groupChanged)
420 if (resettingTable == true)
424 resettingTable = true;
425 typeWidth = new Hashtable();
426 // TODO: change avWidth calculation to 'per-sequence' average and use long
428 float[] avWidth = null;
429 SequenceFeature[] tmpfeatures;
430 String group = null, type;
431 Vector visibleChecks = new Vector();
433 // Find out which features should be visible depending on which groups
434 // are selected / deselected
435 // and recompute average width ordering
436 for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)
439 tmpfeatures = af.getViewport().alignment.getSequenceAt(i)
440 .getDatasetSequence().getSequenceFeatures();
441 if (tmpfeatures == null)
447 while (index < tmpfeatures.length)
449 group = tmpfeatures[index].featureGroup;
451 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
457 if (group == null || fr.featureGroups.get(group) == null
458 || ((Boolean) fr.featureGroups.get(group)).booleanValue())
461 checkGroupState(group);
462 type = tmpfeatures[index].getType();
463 if (!visibleChecks.contains(type))
465 visibleChecks.addElement(type);
468 if (!typeWidth.containsKey(tmpfeatures[index].getType()))
470 typeWidth.put(tmpfeatures[index].getType(),
471 avWidth = new float[3]);
475 avWidth = (float[]) typeWidth.get(tmpfeatures[index].getType());
478 if (tmpfeatures[index].getBegin() > tmpfeatures[index].getEnd())
480 avWidth[1] += 1 + tmpfeatures[index].getBegin()
481 - tmpfeatures[index].getEnd();
485 avWidth[1] += 1 + tmpfeatures[index].getEnd()
486 - tmpfeatures[index].getBegin();
492 int fSize = visibleChecks.size();
493 Object[][] data = new Object[fSize][3];
496 if (fr.renderOrder != null)
499 fr.findAllFeatures(groupChanged != null); // prod to update
500 // colourschemes. but don't
502 // First add the checks in the previous render order,
503 // in case the window has been closed and reopened
504 for (int ro = fr.renderOrder.length - 1; ro > -1; ro--)
506 type = fr.renderOrder[ro];
508 if (!visibleChecks.contains(type))
513 data[dataIndex][0] = type;
514 data[dataIndex][1] = fr.getFeatureStyle(type);
515 data[dataIndex][2] = new Boolean(af.getViewport().featuresDisplayed
518 visibleChecks.removeElement(type);
522 fSize = visibleChecks.size();
523 for (int i = 0; i < fSize; i++)
525 // These must be extra features belonging to the group
526 // which was just selected
527 type = visibleChecks.elementAt(i).toString();
528 data[dataIndex][0] = type;
530 data[dataIndex][1] = fr.getFeatureStyle(type);
531 if (data[dataIndex][1] == null)
533 // "Colour has been updated in another view!!"
534 fr.renderOrder = null;
538 data[dataIndex][2] = new Boolean(true);
542 if (originalData == null)
544 originalData = new Object[data.length][3];
545 for (int i = 0; i < data.length; i++)
547 System.arraycopy(data[i], 0, originalData[i], 0, 3);
551 table.setModel(new FeatureTableModel(data));
552 table.getColumnModel().getColumn(0).setPreferredWidth(200);
554 if (groupPanel != null)
556 groupPanel.setLayout(new GridLayout(fr.featureGroups.size() / 4 + 1,
559 groupPanel.validate();
560 bigPanel.add(groupPanel, BorderLayout.NORTH);
563 updateFeatureRenderer(data, groupChanged != null);
564 resettingTable = false;
568 * reorder data based on the featureRenderers global priority list.
572 private void ensureOrder(Object[][] data)
574 boolean sort = false;
575 float[] order = new float[data.length];
576 for (int i = 0; i < order.length; i++)
578 order[i] = fr.getOrder(data[i][0].toString());
580 order[i] = fr.setOrder(data[i][0].toString(), i / order.length);
582 sort = sort || order[i - 1] > order[i];
585 jalview.util.QuickSort.sort(order, data);
590 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
591 .getProperty("LAST_DIRECTORY"), new String[]
592 { "fc" }, new String[]
593 { "Sequence Feature Colours" }, "Sequence Feature Colours");
594 chooser.setFileView(new jalview.io.JalviewFileView());
595 chooser.setDialogTitle("Load Feature Colours");
596 chooser.setToolTipText("Load");
598 int value = chooser.showOpenDialog(this);
600 if (value == JalviewFileChooser.APPROVE_OPTION)
602 File file = chooser.getSelectedFile();
606 InputStreamReader in = new InputStreamReader(new FileInputStream(
609 jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
610 jucs = (jalview.schemabinding.version2.JalviewUserColours) jucs
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 mincol = new Color(Integer.parseInt(newcol.getMinRGB(), 16));
623 maxcol = new Color(Integer.parseInt(newcol.getRGB(), 16));
625 } catch (Exception e)
627 Cache.log.warn("Couldn't parse out graduated feature color.",
630 GraduatedColor gcol = new GraduatedColor(mincol, maxcol, newcol
631 .getMin(), newcol.getMax());
632 if (newcol.hasAutoScale())
634 gcol.setAutoScaled(newcol.getAutoScale());
636 if (newcol.hasColourByLabel())
638 gcol.setColourByLabel(newcol.getColourByLabel());
640 if (newcol.hasThreshold())
642 gcol.setThresh(newcol.getThreshold());
643 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD); // default
645 if (newcol.getThreshType().length() > 0)
647 String ttyp = newcol.getThreshType();
648 if (ttyp.equalsIgnoreCase("NONE"))
650 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD);
652 if (ttyp.equalsIgnoreCase("ABOVE"))
655 .setThreshType(AnnotationColourGradient.ABOVE_THRESHOLD);
657 if (ttyp.equalsIgnoreCase("BELOW"))
660 .setThreshType(AnnotationColourGradient.BELOW_THRESHOLD);
663 fr.setColour(name = newcol.getName(), gcol);
667 fr.setColour(name = jucs.getColour(i).getName(), new Color(
668 Integer.parseInt(jucs.getColour(i).getRGB(), 16)));
670 fr.setOrder(name, (i == 0) ? 0 : i / jucs.getColourCount());
675 Object[][] data = ((FeatureTableModel) table.getModel())
678 updateFeatureRenderer(data, false);
681 } catch (Exception ex)
683 System.out.println("Error loading User Colour File\n" + ex);
690 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
691 .getProperty("LAST_DIRECTORY"), new String[]
692 { "fc" }, new String[]
693 { "Sequence Feature Colours" }, "Sequence Feature Colours");
694 chooser.setFileView(new jalview.io.JalviewFileView());
695 chooser.setDialogTitle("Save Feature Colour Scheme");
696 chooser.setToolTipText("Save");
698 int value = chooser.showSaveDialog(this);
700 if (value == JalviewFileChooser.APPROVE_OPTION)
702 String choice = chooser.getSelectedFile().getPath();
703 jalview.schemabinding.version2.JalviewUserColours ucs = new jalview.schemabinding.version2.JalviewUserColours();
704 ucs.setSchemeName("Sequence Features");
707 PrintWriter out = new PrintWriter(new OutputStreamWriter(
708 new FileOutputStream(choice), "UTF-8"));
710 Enumeration e = fr.featureColours.keys();
711 float[] sortOrder = new float[fr.featureColours.size()];
712 String[] sortTypes = new String[fr.featureColours.size()];
714 while (e.hasMoreElements())
716 sortTypes[i] = e.nextElement().toString();
717 sortOrder[i] = fr.getOrder(sortTypes[i]);
720 jalview.util.QuickSort.sort(sortOrder, sortTypes);
724 for (i = 0; i < sortTypes.length; i++)
726 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
727 col.setName(sortTypes[i]);
728 col.setRGB(jalview.util.Format.getHexString(fr.getColour(col
730 fcol = fr.getFeatureStyle(sortTypes[i]);
731 if (fcol instanceof GraduatedColor)
733 gcol = (GraduatedColor) fcol;
734 col.setMin(gcol.getMin());
735 col.setMax(gcol.getMax());
736 col.setMinRGB(jalview.util.Format.getHexString(gcol
738 col.setAutoScale(gcol.isAutoScale());
739 col.setThreshold(gcol.getThresh());
740 col.setColourByLabel(gcol.isColourByLabel());
741 switch (gcol.getThreshType())
743 case AnnotationColourGradient.NO_THRESHOLD:
744 col.setThreshType("NONE");
746 case AnnotationColourGradient.ABOVE_THRESHOLD:
747 col.setThreshType("ABOVE");
749 case AnnotationColourGradient.BELOW_THRESHOLD:
750 col.setThreshType("BELOW");
758 } catch (Exception ex)
760 ex.printStackTrace();
765 public void invertSelection()
767 for (int i = 0; i < table.getRowCount(); i++)
769 Boolean value = (Boolean) table.getValueAt(i, 2);
771 table.setValueAt(new Boolean(!value.booleanValue()), i, 2);
775 public void orderByAvWidth()
777 if (table == null || table.getModel() == null)
779 Object[][] data = ((FeatureTableModel) table.getModel()).getData();
780 float[] width = new float[data.length];
784 for (int i = 0; i < data.length; i++)
786 awidth = (float[]) typeWidth.get(data[i][0]);
789 width[i] = awidth[1] / awidth[0];// *awidth[0]*awidth[2]; - better
790 // weight - but have to make per
791 // sequence, too (awidth[2])
792 // if (width[i]==1) // hack to distinguish single width sequences.
802 boolean sort = false;
803 for (int i = 0; i < width.length; i++)
805 // awidth = (float[]) typeWidth.get(data[i][0]);
808 width[i] = fr.getOrder(data[i][0].toString());
811 width[i] = fr.setOrder(data[i][0].toString(), i / data.length);
816 width[i] /= max; // normalize
817 fr.setOrder(data[i][0].toString(), width[i]); // store for later
820 sort = sort || width[i - 1] > width[i];
823 jalview.util.QuickSort.sort(width, data);
824 // update global priority order
826 updateFeatureRenderer(data, false);
834 frame.setClosed(true);
835 } catch (Exception exe)
841 public void updateFeatureRenderer(Object[][] data)
843 updateFeatureRenderer(data, true);
846 private void updateFeatureRenderer(Object[][] data, boolean visibleNew)
848 fr.setFeaturePriority(data, visibleNew);
849 af.alignPanel.paintAlignment(true);
852 int selectedRow = -1;
854 JTabbedPane tabbedPane = new JTabbedPane();
856 BorderLayout borderLayout1 = new BorderLayout();
858 BorderLayout borderLayout2 = new BorderLayout();
860 BorderLayout borderLayout3 = new BorderLayout();
862 JPanel bigPanel = new JPanel();
864 BorderLayout borderLayout4 = new BorderLayout();
866 JButton invert = new JButton();
868 JPanel buttonPanel = new JPanel();
870 JButton cancel = new JButton();
872 JButton ok = new JButton();
874 JButton loadColours = new JButton();
876 JButton saveColours = new JButton();
878 JPanel dasButtonPanel = new JPanel();
880 JButton fetchDAS = new JButton();
882 JButton saveDAS = new JButton();
884 JButton cancelDAS = new JButton();
886 JButton optimizeOrder = new JButton();
888 JButton sortByScore = new JButton();
890 JButton sortByDens = new JButton();
892 JPanel transbuttons = new JPanel(new GridLayout(4, 1));
894 private void jbInit() throws Exception
896 this.setLayout(borderLayout1);
897 settingsPane.setLayout(borderLayout2);
898 dasSettingsPane.setLayout(borderLayout3);
899 bigPanel.setLayout(borderLayout4);
900 invert.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
901 invert.setText("Invert Selection");
902 invert.addActionListener(new ActionListener()
904 public void actionPerformed(ActionEvent e)
909 optimizeOrder.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
910 optimizeOrder.setText("Optimise Order");
911 optimizeOrder.addActionListener(new ActionListener()
913 public void actionPerformed(ActionEvent e)
918 sortByScore.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
919 sortByScore.setText("Seq sort by Score");
920 sortByScore.addActionListener(new ActionListener()
922 public void actionPerformed(ActionEvent e)
927 sortByDens.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
928 sortByDens.setText("Seq Sort by density");
929 sortByDens.addActionListener(new ActionListener()
931 public void actionPerformed(ActionEvent e)
936 cancel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
937 cancel.setText("Cancel");
938 cancel.addActionListener(new ActionListener()
940 public void actionPerformed(ActionEvent e)
942 updateFeatureRenderer(originalData);
946 ok.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
948 ok.addActionListener(new ActionListener()
950 public void actionPerformed(ActionEvent e)
955 loadColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
956 loadColours.setText("Load Colours");
957 loadColours.addActionListener(new ActionListener()
959 public void actionPerformed(ActionEvent e)
964 saveColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
965 saveColours.setText("Save Colours");
966 saveColours.addActionListener(new ActionListener()
968 public void actionPerformed(ActionEvent e)
973 transparency.addChangeListener(new ChangeListener()
975 public void stateChanged(ChangeEvent evt)
977 fr.setTransparency((float) (100 - transparency.getValue()) / 100f);
978 af.alignPanel.paintAlignment(true);
982 transparency.setMaximum(70);
983 fetchDAS.setText("Fetch DAS Features");
984 fetchDAS.addActionListener(new ActionListener()
986 public void actionPerformed(ActionEvent e)
988 fetchDAS_actionPerformed(e);
991 saveDAS.setText("Save as default");
992 saveDAS.addActionListener(new ActionListener()
994 public void actionPerformed(ActionEvent e)
996 saveDAS_actionPerformed(e);
999 dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
1000 dasSettingsPane.setBorder(null);
1001 cancelDAS.setEnabled(false);
1002 cancelDAS.setText("Cancel Fetch");
1003 cancelDAS.addActionListener(new ActionListener()
1005 public void actionPerformed(ActionEvent e)
1007 cancelDAS_actionPerformed(e);
1010 this.add(tabbedPane, java.awt.BorderLayout.CENTER);
1011 tabbedPane.addTab("Feature Settings", settingsPane);
1012 tabbedPane.addTab("DAS Settings", dasSettingsPane);
1013 bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
1014 transbuttons.add(optimizeOrder);
1015 transbuttons.add(invert);
1016 transbuttons.add(sortByScore);
1017 transbuttons.add(sortByDens);
1018 transPanel.add(transparency);
1019 transPanel.add(transbuttons);
1020 buttonPanel.add(ok);
1021 buttonPanel.add(cancel);
1022 buttonPanel.add(loadColours);
1023 buttonPanel.add(saveColours);
1024 bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
1025 dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
1026 dasButtonPanel.add(fetchDAS);
1027 dasButtonPanel.add(cancelDAS);
1028 dasButtonPanel.add(saveDAS);
1029 settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);
1030 settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
1033 protected void sortByDens(String[] typ)
1035 sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY);
1038 protected void sortBy(String[] typ, String methodText, final String method)
1042 typ = getDisplayedFeatureTypes();
1044 String gps[] = null;
1045 gps = getDisplayedFeatureGroups();
1048 ArrayList types = new ArrayList();
1049 for (int i = 0; i < typ.length; i++)
1055 typ = new String[types.size()];
1061 ArrayList grps = new ArrayList();
1063 for (int i = 0; i < gps.length; i++)
1070 gps = new String[grps.size()];
1073 AlignmentPanel alignPanel = af.alignPanel;
1074 AlignmentI al = alignPanel.av.getAlignment();
1077 SequenceGroup sg = alignPanel.av.getSelectionGroup();
1080 start = sg.getStartRes();
1081 stop = sg.getEndRes();
1086 stop = al.getWidth();
1088 SequenceI[] oldOrder = al.getSequencesArray();
1089 AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
1090 af.addHistoryItem(new OrderCommand(methodText, oldOrder, alignPanel.av
1092 alignPanel.paintAlignment(true);
1096 protected void sortByScore(String[] typ)
1098 sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE);
1101 private String[] getDisplayedFeatureTypes()
1103 String[] typ = null;
1106 synchronized (fr.renderOrder)
1108 typ = new String[fr.renderOrder.length];
1109 System.arraycopy(fr.renderOrder, 0, typ, 0, typ.length);
1110 for (int i = 0; i < typ.length; i++)
1112 if (af.viewport.featuresDisplayed.get(typ[i]) == null)
1122 private String[] getDisplayedFeatureGroups()
1124 String[] gps = null;
1128 if (fr.featureGroups != null)
1130 Enumeration en = fr.featureGroups.keys();
1131 gps = new String[fr.featureColours.size()];
1133 boolean valid = false;
1134 while (en.hasMoreElements())
1136 String gp = (String) en.nextElement();
1137 Boolean on = (Boolean) fr.featureGroups.get(gp);
1138 if (on != null && on.booleanValue())
1144 while (g < gps.length)
1157 public void fetchDAS_actionPerformed(ActionEvent e)
1159 fetchDAS.setEnabled(false);
1160 cancelDAS.setEnabled(true);
1161 Vector selectedSources = dassourceBrowser.getSelectedSources();
1162 doDasFeatureFetch(selectedSources, true, true);
1166 * get the features from selectedSources for all or the current selection
1168 * @param selectedSources
1169 * @param checkDbRefs
1170 * @param promptFetchDbRefs
1172 private void doDasFeatureFetch(Vector selectedSources,
1173 boolean checkDbRefs, boolean promptFetchDbRefs)
1175 SequenceI[] dataset, seqs;
1177 AlignViewport vp = af.getViewport();
1178 if (vp.getSelectionGroup() != null
1179 && vp.getSelectionGroup().getSize() > 0)
1181 iSize = vp.getSelectionGroup().getSize();
1182 dataset = new SequenceI[iSize];
1183 seqs = vp.getSelectionGroup().getSequencesInOrder(vp.getAlignment());
1187 iSize = vp.getAlignment().getHeight();
1188 seqs = vp.getAlignment().getSequencesArray();
1191 dataset = new SequenceI[iSize];
1192 for (int i = 0; i < iSize; i++)
1194 dataset[i] = seqs[i].getDatasetSequence();
1197 cancelDAS.setEnabled(true);
1198 dasFeatureFetcher = new jalview.ws.DasSequenceFeatureFetcher(dataset,
1199 this, selectedSources, checkDbRefs, promptFetchDbRefs);
1200 af.getViewport().setShowSequenceFeatures(true);
1201 af.showSeqFeatures.setSelected(true);
1205 * blocking call to initialise the das source browser
1207 public void initDasSources()
1209 dassourceBrowser.initDasSources();
1213 * examine the current list of das sources and return any matching the given
1214 * nicknames in sources
1217 * Vector of Strings to resolve to DAS source nicknames.
1218 * @return sources that are present in source list.
1220 public Vector resolveSourceNicknames(Vector sources)
1222 return dassourceBrowser.resolveSourceNicknames(sources);
1226 * get currently selected das sources. ensure you have called initDasSources
1227 * before calling this.
1229 * @return vector of selected das source nicknames
1231 public Vector getSelectedSources()
1233 return dassourceBrowser.getSelectedSources();
1237 * properly initialise DAS fetcher and then initiate a new thread to fetch
1238 * features from the named sources (rather than any turned on by default)
1242 * if true then runs in same thread, otherwise passes to the Swing
1245 public void fetchDasFeatures(Vector sources, boolean block)
1248 Vector resolved = resolveSourceNicknames(sources);
1249 if (resolved.size() == 0)
1251 resolved = dassourceBrowser.getSelectedSources();
1253 if (resolved.size() > 0)
1255 final Vector dassources = resolved;
1256 fetchDAS.setEnabled(false);
1257 // cancelDAS.setEnabled(true); doDasFetch does this.
1258 Runnable fetcher = new Runnable()
1263 doDasFeatureFetch(dassources, true, false);
1273 SwingUtilities.invokeLater(fetcher);
1278 public void saveDAS_actionPerformed(ActionEvent e)
1281 .saveProperties(jalview.bin.Cache.applicationProperties);
1284 public void complete()
1286 fetchDAS.setEnabled(true);
1287 cancelDAS.setEnabled(false);
1290 public void cancelDAS_actionPerformed(ActionEvent e)
1292 if (dasFeatureFetcher != null)
1294 dasFeatureFetcher.cancel();
1296 fetchDAS.setEnabled(true);
1297 cancelDAS.setEnabled(false);
1300 public void noDasSourceActive()
1303 JOptionPane.showInternalConfirmDialog(Desktop.desktop,
1304 "No das sources were selected.\n"
1305 + "Please select some sources and\n" + " try again.",
1306 "No Sources Selected", JOptionPane.DEFAULT_OPTION,
1307 JOptionPane.INFORMATION_MESSAGE);
1310 // ///////////////////////////////////////////////////////////////////////
1311 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
1312 // ///////////////////////////////////////////////////////////////////////
1313 class FeatureTableModel extends AbstractTableModel
1315 FeatureTableModel(Object[][] data)
1320 private String[] columnNames =
1321 { "Feature Type", "Colour", "Display" };
1323 private Object[][] data;
1325 public Object[][] getData()
1330 public void setData(Object[][] data)
1335 public int getColumnCount()
1337 return columnNames.length;
1340 public Object[] getRow(int row)
1345 public int getRowCount()
1350 public String getColumnName(int col)
1352 return columnNames[col];
1355 public Object getValueAt(int row, int col)
1357 return data[row][col];
1360 public Class getColumnClass(int c)
1362 return getValueAt(0, c).getClass();
1365 public boolean isCellEditable(int row, int col)
1367 return col == 0 ? false : true;
1370 public void setValueAt(Object value, int row, int col)
1372 data[row][col] = value;
1373 fireTableCellUpdated(row, col);
1374 updateFeatureRenderer(data);
1379 class ColorRenderer extends JLabel implements TableCellRenderer
1381 javax.swing.border.Border unselectedBorder = null;
1383 javax.swing.border.Border selectedBorder = null;
1385 final String baseTT = "Click to edit, right/apple click for menu.";
1387 public ColorRenderer()
1389 setOpaque(true); // MUST do this for background to show up.
1390 setHorizontalTextPosition(SwingConstants.CENTER);
1391 setVerticalTextPosition(SwingConstants.CENTER);
1394 public Component getTableCellRendererComponent(JTable table,
1395 Object color, boolean isSelected, boolean hasFocus, int row,
1398 // JLabel comp = new JLabel();
1402 // setBounds(getBounds());
1404 setToolTipText(baseTT);
1405 setBackground(table.getBackground());
1406 if (color instanceof GraduatedColor)
1408 Rectangle cr = table.getCellRect(row, column, false);
1409 FeatureSettings.renderGraduatedColor(this, (GraduatedColor) color,
1410 (int) cr.getWidth(), (int) cr.getHeight());
1417 newColor = (Color) color;
1419 setBackground(newColor);
1420 // comp.setToolTipText("RGB value: " + newColor.getRed() + ", "
1421 // + newColor.getGreen() + ", " + newColor.getBlue());
1425 if (selectedBorder == null)
1427 selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1428 table.getSelectionBackground());
1431 setBorder(selectedBorder);
1435 if (unselectedBorder == null)
1437 unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1438 table.getBackground());
1441 setBorder(unselectedBorder);
1449 * update comp using rendering settings from gcol
1454 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol)
1456 int w = comp.getWidth(), h = comp.getHeight();
1459 w = (int) comp.getPreferredSize().getWidth();
1460 h = (int) comp.getPreferredSize().getHeight();
1467 renderGraduatedColor(comp, gcol, w, h);
1470 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol,
1473 boolean thr = false;
1476 if (gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD)
1480 tt += "Thresholded (Above " + gcol.getThresh() + ") ";
1482 if (gcol.getThreshType() == AnnotationColourGradient.BELOW_THRESHOLD)
1486 tt += "Thresholded (Below " + gcol.getThresh() + ") ";
1488 if (gcol.isColourByLabel())
1490 tt = "Coloured by label text. " + tt;
1500 Color newColor = gcol.getMaxColor();
1501 comp.setBackground(newColor);
1502 // System.err.println("Width is " + w / 2);
1503 Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w, h, thr);
1504 comp.setIcon(ficon);
1505 // tt+="RGB value: Max (" + newColor.getRed() + ", "
1506 // + newColor.getGreen() + ", " + newColor.getBlue()
1507 // + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen()
1508 // + ", " + minCol.getBlue() + ")");
1510 comp.setHorizontalAlignment(SwingConstants.CENTER);
1512 if (tt.length() > 0)
1514 if (comp.getToolTipText() == null)
1516 comp.setToolTipText(tt);
1520 comp.setToolTipText(tt + " " + comp.getToolTipText());
1526 class FeatureIcon implements Icon
1528 GraduatedColor gcol;
1532 boolean midspace = false;
1534 int width = 50, height = 20;
1536 int s1, e1; // start and end of midpoint band for thresholded symbol
1538 Color mpcolour = Color.white;
1540 FeatureIcon(GraduatedColor gfc, Color bg, int w, int h, boolean mspace)
1559 public int getIconWidth()
1564 public int getIconHeight()
1569 public void paintIcon(Component c, Graphics g, int x, int y)
1572 if (gcol.isColourByLabel())
1575 g.fillRect(0, 0, width, height);
1576 // need an icon here.
1577 g.setColor(gcol.getMaxColor());
1579 g.setFont(new Font("Verdana", Font.PLAIN, 9));
1581 // g.setFont(g.getFont().deriveFont(
1582 // AffineTransform.getScaleInstance(
1583 // width/g.getFontMetrics().stringWidth("Label"),
1584 // height/g.getFontMetrics().getHeight())));
1586 g.drawString("Label", 0, 0);
1591 Color minCol = gcol.getMinColor();
1593 g.fillRect(0, 0, s1, height);
1596 g.setColor(Color.white);
1597 g.fillRect(s1, 0, e1 - s1, height);
1599 g.setColor(gcol.getMaxColor());
1600 g.fillRect(0, e1, width - e1, height);
1605 class ColorEditor extends AbstractCellEditor implements TableCellEditor,
1610 GraduatedColor currentGColor;
1612 FeatureColourChooser chooser;
1620 JColorChooser colorChooser;
1624 protected static final String EDIT = "edit";
1626 int selectedRow = 0;
1628 public ColorEditor(FeatureSettings me)
1631 // Set up the editor (from the table's point of view),
1632 // which is a button.
1633 // This button brings up the color chooser dialog,
1634 // which is the editor from the user's point of view.
1635 button = new JButton();
1636 button.setActionCommand(EDIT);
1637 button.addActionListener(this);
1638 button.setBorderPainted(false);
1639 // Set up the dialog that the button brings up.
1640 colorChooser = new JColorChooser();
1641 dialog = JColorChooser.createDialog(button, "Select new Colour", true, // modal
1642 colorChooser, this, // OK button handler
1643 null); // no CANCEL button handler
1647 * Handles events from the editor button and from the dialog's OK button.
1649 public void actionPerformed(ActionEvent e)
1652 if (EDIT.equals(e.getActionCommand()))
1654 // The user has clicked the cell, so
1655 // bring up the dialog.
1656 if (currentColor != null)
1658 // bring up simple color chooser
1659 button.setBackground(currentColor);
1660 colorChooser.setColor(currentColor);
1661 dialog.setVisible(true);
1665 // bring up graduated chooser.
1666 chooser = new FeatureColourChooser(me.fr, type);
1667 chooser.setRequestFocusEnabled(true);
1668 chooser.requestFocus();
1669 chooser.addActionListener(this);
1671 // Make the renderer reappear.
1672 fireEditingStopped();
1676 { // User pressed dialog's "OK" button.
1677 if (currentColor != null)
1679 currentColor = colorChooser.getColor();
1683 // class cast exceptions may be raised if the chooser created on a
1684 // non-graduated color
1685 currentGColor = (GraduatedColor) chooser.getLastColour();
1687 me.table.setValueAt(getCellEditorValue(), selectedRow, 1);
1688 fireEditingStopped();
1689 me.table.validate();
1693 // Implement the one CellEditor method that AbstractCellEditor doesn't.
1694 public Object getCellEditorValue()
1696 if (currentColor == null)
1698 return currentGColor;
1700 return currentColor;
1703 // Implement the one method defined by TableCellEditor.
1704 public Component getTableCellEditorComponent(JTable table, Object value,
1705 boolean isSelected, int row, int column)
1707 currentGColor = null;
1708 currentColor = null;
1709 this.selectedRow = row;
1710 type = me.table.getValueAt(row, 0).toString();
1711 button.setOpaque(true);
1712 button.setBackground(me.getBackground());
1713 if (value instanceof GraduatedColor)
1715 currentGColor = (GraduatedColor) value;
1716 JLabel btn = new JLabel();
1717 btn.setSize(button.getSize());
1718 FeatureSettings.renderGraduatedColor(btn, currentGColor);
1719 button.setBackground(btn.getBackground());
1720 button.setIcon(btn.getIcon());
1721 button.setText(btn.getText());
1726 button.setIcon(null);
1727 currentColor = (Color) value;
1728 button.setBackground(currentColor);