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;
620 float thrsh=Float.NaN;
623 Integer.parseInt(newcol.getMinRGB(), 16));
625 Integer.parseInt(newcol.getRGB(), 16));
627 } catch (Exception e)
629 Cache.log.warn("Couldn't parse out graduated feature color.",e);
631 GraduatedColor gcol =
632 new GraduatedColor(mincol,maxcol,
633 newcol.getMin(),newcol.getMax());
634 if (newcol.hasAutoScale())
636 gcol.setAutoScaled(newcol.getAutoScale());
638 if (newcol.hasColourByLabel())
640 gcol.setColourByLabel(newcol.getColourByLabel());
642 if (newcol.hasThreshold())
644 gcol.setThresh(newcol.getThreshold());
645 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD); // default
647 if (newcol.getThreshType().length()>0)
649 String ttyp = newcol.getThreshType();
650 if (ttyp.equalsIgnoreCase("NONE")) {
651 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD);
653 if (ttyp.equalsIgnoreCase("ABOVE"))
655 gcol.setThreshType(AnnotationColourGradient.ABOVE_THRESHOLD);
657 if (ttyp.equalsIgnoreCase("BELOW")){
658 gcol.setThreshType(AnnotationColourGradient.BELOW_THRESHOLD);
661 fr.setColour(name = newcol.getName(), gcol);
663 fr.setColour(name = jucs.getColour(i).getName(), new Color(
664 Integer.parseInt(jucs.getColour(i).getRGB(), 16)));
666 fr.setOrder(name, (i == 0) ? 0 : i / jucs.getColourCount());
671 Object[][] data = ((FeatureTableModel) table.getModel())
674 updateFeatureRenderer(data, false);
677 } catch (Exception ex)
679 System.out.println("Error loading User Colour File\n" + ex);
686 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
687 .getProperty("LAST_DIRECTORY"), new String[]
688 { "fc" }, new String[]
689 { "Sequence Feature Colours" }, "Sequence Feature Colours");
690 chooser.setFileView(new jalview.io.JalviewFileView());
691 chooser.setDialogTitle("Save Feature Colour Scheme");
692 chooser.setToolTipText("Save");
694 int value = chooser.showSaveDialog(this);
696 if (value == JalviewFileChooser.APPROVE_OPTION)
698 String choice = chooser.getSelectedFile().getPath();
699 jalview.schemabinding.version2.JalviewUserColours ucs = new jalview.schemabinding.version2.JalviewUserColours();
700 ucs.setSchemeName("Sequence Features");
703 PrintWriter out = new PrintWriter(new OutputStreamWriter(
704 new FileOutputStream(choice), "UTF-8"));
706 Enumeration e = fr.featureColours.keys();
707 float[] sortOrder = new float[fr.featureColours.size()];
708 String[] sortTypes = new String[fr.featureColours.size()];
710 while (e.hasMoreElements())
712 sortTypes[i] = e.nextElement().toString();
713 sortOrder[i] = fr.getOrder(sortTypes[i]);
716 jalview.util.QuickSort.sort(sortOrder, sortTypes);
720 for (i = 0; i < sortTypes.length; i++)
722 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
723 col.setName(sortTypes[i]);
724 col.setRGB(jalview.util.Format.getHexString(fr.getColour(col
726 fcol = fr.getFeatureStyle(sortTypes[i]);
727 if (fcol instanceof GraduatedColor)
729 gcol = (GraduatedColor) fcol;
730 col.setMin(gcol.getMin());
731 col.setMax(gcol.getMax());
732 col.setMinRGB(jalview.util.Format.getHexString(gcol
734 col.setAutoScale(gcol.isAutoScale());
735 col.setThreshold(gcol.getThresh());
736 col.setColourByLabel(gcol.isColourByLabel());
737 switch (gcol.getThreshType())
739 case AnnotationColourGradient.NO_THRESHOLD:
740 col.setThreshType("NONE");
742 case AnnotationColourGradient.ABOVE_THRESHOLD:
743 col.setThreshType("ABOVE");
745 case AnnotationColourGradient.BELOW_THRESHOLD:
746 col.setThreshType("BELOW");
754 } catch (Exception ex)
756 ex.printStackTrace();
761 public void invertSelection()
763 for (int i = 0; i < table.getRowCount(); i++)
765 Boolean value = (Boolean) table.getValueAt(i, 2);
767 table.setValueAt(new Boolean(!value.booleanValue()), i, 2);
771 public void orderByAvWidth()
773 if (table == null || table.getModel() == null)
775 Object[][] data = ((FeatureTableModel) table.getModel()).getData();
776 float[] width = new float[data.length];
780 for (int i = 0; i < data.length; i++)
782 awidth = (float[]) typeWidth.get(data[i][0]);
785 width[i] = awidth[1] / awidth[0];// *awidth[0]*awidth[2]; - better
786 // weight - but have to make per
787 // sequence, too (awidth[2])
788 // if (width[i]==1) // hack to distinguish single width sequences.
798 boolean sort = false;
799 for (int i = 0; i < width.length; i++)
801 // awidth = (float[]) typeWidth.get(data[i][0]);
804 width[i] = fr.getOrder(data[i][0].toString());
807 width[i] = fr.setOrder(data[i][0].toString(), i / data.length);
812 width[i] /= max; // normalize
813 fr.setOrder(data[i][0].toString(), width[i]); // store for later
816 sort = sort || width[i - 1] > width[i];
819 jalview.util.QuickSort.sort(width, data);
820 // update global priority order
822 updateFeatureRenderer(data, false);
830 frame.setClosed(true);
831 } catch (Exception exe)
837 public void updateFeatureRenderer(Object[][] data)
839 updateFeatureRenderer(data, true);
842 private void updateFeatureRenderer(Object[][] data, boolean visibleNew)
844 fr.setFeaturePriority(data, visibleNew);
845 af.alignPanel.paintAlignment(true);
848 int selectedRow = -1;
850 JTabbedPane tabbedPane = new JTabbedPane();
852 BorderLayout borderLayout1 = new BorderLayout();
854 BorderLayout borderLayout2 = new BorderLayout();
856 BorderLayout borderLayout3 = new BorderLayout();
858 JPanel bigPanel = new JPanel();
860 BorderLayout borderLayout4 = new BorderLayout();
862 JButton invert = new JButton();
864 JPanel buttonPanel = new JPanel();
866 JButton cancel = new JButton();
868 JButton ok = new JButton();
870 JButton loadColours = new JButton();
872 JButton saveColours = new JButton();
874 JPanel dasButtonPanel = new JPanel();
876 JButton fetchDAS = new JButton();
878 JButton saveDAS = new JButton();
880 JButton cancelDAS = new JButton();
882 JButton optimizeOrder = new JButton();
884 JButton sortByScore = new JButton();
886 JButton sortByDens = new JButton();
888 JPanel transbuttons = new JPanel(new GridLayout(4, 1));
890 private void jbInit() throws Exception
892 this.setLayout(borderLayout1);
893 settingsPane.setLayout(borderLayout2);
894 dasSettingsPane.setLayout(borderLayout3);
895 bigPanel.setLayout(borderLayout4);
896 invert.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
897 invert.setText("Invert Selection");
898 invert.addActionListener(new ActionListener()
900 public void actionPerformed(ActionEvent e)
905 optimizeOrder.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
906 optimizeOrder.setText("Optimise Order");
907 optimizeOrder.addActionListener(new ActionListener()
909 public void actionPerformed(ActionEvent e)
914 sortByScore.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
915 sortByScore.setText("Seq sort by Score");
916 sortByScore.addActionListener(new ActionListener()
918 public void actionPerformed(ActionEvent e)
923 sortByDens.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
924 sortByDens.setText("Seq Sort by density");
925 sortByDens.addActionListener(new ActionListener()
927 public void actionPerformed(ActionEvent e)
932 cancel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
933 cancel.setText("Cancel");
934 cancel.addActionListener(new ActionListener()
936 public void actionPerformed(ActionEvent e)
938 updateFeatureRenderer(originalData);
942 ok.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
944 ok.addActionListener(new ActionListener()
946 public void actionPerformed(ActionEvent e)
951 loadColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
952 loadColours.setText("Load Colours");
953 loadColours.addActionListener(new ActionListener()
955 public void actionPerformed(ActionEvent e)
960 saveColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
961 saveColours.setText("Save Colours");
962 saveColours.addActionListener(new ActionListener()
964 public void actionPerformed(ActionEvent e)
969 transparency.addChangeListener(new ChangeListener()
971 public void stateChanged(ChangeEvent evt)
973 fr.setTransparency((float) (100 - transparency.getValue()) / 100f);
974 af.alignPanel.paintAlignment(true);
978 transparency.setMaximum(70);
979 fetchDAS.setText("Fetch DAS Features");
980 fetchDAS.addActionListener(new ActionListener()
982 public void actionPerformed(ActionEvent e)
984 fetchDAS_actionPerformed(e);
987 saveDAS.setText("Save as default");
988 saveDAS.addActionListener(new ActionListener()
990 public void actionPerformed(ActionEvent e)
992 saveDAS_actionPerformed(e);
995 dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
996 dasSettingsPane.setBorder(null);
997 cancelDAS.setEnabled(false);
998 cancelDAS.setText("Cancel Fetch");
999 cancelDAS.addActionListener(new ActionListener()
1001 public void actionPerformed(ActionEvent e)
1003 cancelDAS_actionPerformed(e);
1006 this.add(tabbedPane, java.awt.BorderLayout.CENTER);
1007 tabbedPane.addTab("Feature Settings", settingsPane);
1008 tabbedPane.addTab("DAS Settings", dasSettingsPane);
1009 bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
1010 transbuttons.add(optimizeOrder);
1011 transbuttons.add(invert);
1012 transbuttons.add(sortByScore);
1013 transbuttons.add(sortByDens);
1014 transPanel.add(transparency);
1015 transPanel.add(transbuttons);
1016 buttonPanel.add(ok);
1017 buttonPanel.add(cancel);
1018 buttonPanel.add(loadColours);
1019 buttonPanel.add(saveColours);
1020 bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
1021 dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
1022 dasButtonPanel.add(fetchDAS);
1023 dasButtonPanel.add(cancelDAS);
1024 dasButtonPanel.add(saveDAS);
1025 settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);
1026 settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
1029 protected void sortByDens(String[] typ)
1031 sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY);
1034 protected void sortBy(String[] typ, String methodText, final String method)
1038 typ = getDisplayedFeatureTypes();
1040 String gps[] = null;
1041 gps = getDisplayedFeatureGroups();
1044 for (int i = 0; i < typ.length; i++)
1046 System.err.println("Sorting on Types:" + typ[i]);
1052 for (int i = 0; i < gps.length; i++)
1054 System.err.println("Sorting on groups:" + gps[i]);
1057 AlignmentPanel alignPanel = af.alignPanel;
1058 AlignmentI al = alignPanel.av.getAlignment();
1061 SequenceGroup sg = alignPanel.av.getSelectionGroup();
1064 start = sg.getStartRes();
1065 stop = sg.getEndRes();
1070 stop = al.getWidth();
1072 SequenceI[] oldOrder = al.getSequencesArray();
1073 AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
1074 af.addHistoryItem(new OrderCommand(methodText, oldOrder, alignPanel.av
1076 alignPanel.paintAlignment(true);
1080 protected void sortByScore(String[] typ)
1082 sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE);
1085 private String[] getDisplayedFeatureTypes()
1087 String[] typ = null;
1090 synchronized (fr.renderOrder)
1092 typ = new String[fr.renderOrder.length];
1093 System.arraycopy(fr.renderOrder, 0, typ, 0, typ.length);
1094 for (int i = 0; i < typ.length; i++)
1096 if (af.viewport.featuresDisplayed.get(typ[i]) == null)
1106 private String[] getDisplayedFeatureGroups()
1108 String[] gps = null;
1112 if (fr.featureGroups != null)
1114 Enumeration en = fr.featureGroups.keys();
1115 gps = new String[fr.featureColours.size()];
1117 boolean valid = false;
1118 while (en.hasMoreElements())
1120 String gp = (String) en.nextElement();
1121 Boolean on = (Boolean) fr.featureGroups.get(gp);
1122 if (on != null && on.booleanValue())
1128 while (g < gps.length)
1141 public void fetchDAS_actionPerformed(ActionEvent e)
1143 fetchDAS.setEnabled(false);
1144 cancelDAS.setEnabled(true);
1145 Vector selectedSources = dassourceBrowser.getSelectedSources();
1146 doDasFeatureFetch(selectedSources, true, true);
1150 * get the features from selectedSources for all or the current selection
1152 * @param selectedSources
1153 * @param checkDbRefs
1154 * @param promptFetchDbRefs
1156 private void doDasFeatureFetch(Vector selectedSources,
1157 boolean checkDbRefs, boolean promptFetchDbRefs)
1159 SequenceI[] dataset, seqs;
1161 AlignViewport vp = af.getViewport();
1162 if (vp.getSelectionGroup() != null
1163 && vp.getSelectionGroup().getSize() > 0)
1165 iSize = vp.getSelectionGroup().getSize();
1166 dataset = new SequenceI[iSize];
1167 seqs = vp.getSelectionGroup().getSequencesInOrder(vp.getAlignment());
1171 iSize = vp.getAlignment().getHeight();
1172 seqs = vp.getAlignment().getSequencesArray();
1175 dataset = new SequenceI[iSize];
1176 for (int i = 0; i < iSize; i++)
1178 dataset[i] = seqs[i].getDatasetSequence();
1181 cancelDAS.setEnabled(true);
1182 dasFeatureFetcher = new jalview.ws.DasSequenceFeatureFetcher(dataset,
1183 this, selectedSources, checkDbRefs, promptFetchDbRefs);
1184 af.getViewport().setShowSequenceFeatures(true);
1185 af.showSeqFeatures.setSelected(true);
1189 * blocking call to initialise the das source browser
1191 public void initDasSources()
1193 dassourceBrowser.initDasSources();
1197 * examine the current list of das sources and return any matching the given
1198 * nicknames in sources
1201 * Vector of Strings to resolve to DAS source nicknames.
1202 * @return sources that are present in source list.
1204 public Vector resolveSourceNicknames(Vector sources)
1206 return dassourceBrowser.resolveSourceNicknames(sources);
1210 * get currently selected das sources. ensure you have called initDasSources
1211 * before calling this.
1213 * @return vector of selected das source nicknames
1215 public Vector getSelectedSources()
1217 return dassourceBrowser.getSelectedSources();
1221 * properly initialise DAS fetcher and then initiate a new thread to fetch
1222 * features from the named sources (rather than any turned on by default)
1226 * if true then runs in same thread, otherwise passes to the Swing
1229 public void fetchDasFeatures(Vector sources, boolean block)
1232 Vector resolved = resolveSourceNicknames(sources);
1233 if (resolved.size() == 0)
1235 resolved = dassourceBrowser.getSelectedSources();
1237 if (resolved.size() > 0)
1239 final Vector dassources = resolved;
1240 fetchDAS.setEnabled(false);
1241 // cancelDAS.setEnabled(true); doDasFetch does this.
1242 Runnable fetcher = new Runnable()
1247 doDasFeatureFetch(dassources, true, false);
1257 SwingUtilities.invokeLater(fetcher);
1262 public void saveDAS_actionPerformed(ActionEvent e)
1265 .saveProperties(jalview.bin.Cache.applicationProperties);
1268 public void complete()
1270 fetchDAS.setEnabled(true);
1271 cancelDAS.setEnabled(false);
1274 public void cancelDAS_actionPerformed(ActionEvent e)
1276 if (dasFeatureFetcher != null)
1278 dasFeatureFetcher.cancel();
1280 fetchDAS.setEnabled(true);
1281 cancelDAS.setEnabled(false);
1284 public void noDasSourceActive()
1287 JOptionPane.showInternalConfirmDialog(Desktop.desktop,
1288 "No das sources were selected.\n"
1289 + "Please select some sources and\n" + " try again.",
1290 "No Sources Selected", JOptionPane.DEFAULT_OPTION,
1291 JOptionPane.INFORMATION_MESSAGE);
1294 // ///////////////////////////////////////////////////////////////////////
1295 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
1296 // ///////////////////////////////////////////////////////////////////////
1297 class FeatureTableModel extends AbstractTableModel
1299 FeatureTableModel(Object[][] data)
1304 private String[] columnNames =
1305 { "Feature Type", "Colour", "Display" };
1307 private Object[][] data;
1309 public Object[][] getData()
1314 public void setData(Object[][] data)
1319 public int getColumnCount()
1321 return columnNames.length;
1324 public Object[] getRow(int row)
1329 public int getRowCount()
1334 public String getColumnName(int col)
1336 return columnNames[col];
1339 public Object getValueAt(int row, int col)
1341 return data[row][col];
1344 public Class getColumnClass(int c)
1346 return getValueAt(0, c).getClass();
1349 public boolean isCellEditable(int row, int col)
1351 return col == 0 ? false : true;
1354 public void setValueAt(Object value, int row, int col)
1356 data[row][col] = value;
1357 fireTableCellUpdated(row, col);
1358 updateFeatureRenderer(data);
1363 class ColorRenderer extends JLabel implements TableCellRenderer
1365 javax.swing.border.Border unselectedBorder = null;
1367 javax.swing.border.Border selectedBorder = null;
1369 final String baseTT = "Click to edit, right/apple click for menu.";
1371 public ColorRenderer()
1373 setOpaque(true); // MUST do this for background to show up.
1376 public Component getTableCellRendererComponent(JTable table,
1377 Object color, boolean isSelected, boolean hasFocus, int row,
1380 // JLabel comp = new JLabel();
1384 // setBounds(getBounds());
1386 setToolTipText(baseTT);
1387 setBackground(table.getBackground());
1388 if (color instanceof GraduatedColor)
1390 Rectangle cr = table.getCellRect(row, column, false);
1391 FeatureSettings.renderGraduatedColor(this, (GraduatedColor) color,
1392 (int) cr.getWidth(), (int) cr.getHeight());
1399 newColor = (Color) color;
1401 setBackground(newColor);
1402 // comp.setToolTipText("RGB value: " + newColor.getRed() + ", "
1403 // + newColor.getGreen() + ", " + newColor.getBlue());
1407 if (selectedBorder == null)
1409 selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1410 table.getSelectionBackground());
1413 setBorder(selectedBorder);
1417 if (unselectedBorder == null)
1419 unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1420 table.getBackground());
1423 setBorder(unselectedBorder);
1431 * update comp using rendering settings from gcol
1436 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol)
1438 int w = comp.getWidth(), h = comp.getHeight();
1441 w = (int) comp.getPreferredSize().getWidth();
1442 h = (int) comp.getPreferredSize().getHeight();
1449 renderGraduatedColor(comp, gcol, w, h);
1452 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol,
1458 if (gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD)
1461 tt += "Thresholded (Above " + gcol.getThresh() + ") ";
1463 if (gcol.getThreshType() == AnnotationColourGradient.BELOW_THRESHOLD)
1466 tt += "Thresholded (Below " + gcol.getThresh() + ") ";
1468 if (gcol.isColourByLabel())
1470 tt = "Coloured by label text. " + tt;
1476 Color newColor = gcol.getMaxColor();
1477 comp.setBackground(newColor);
1478 System.err.println("Width is " + w / 2);
1479 Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w / 2, h);
1480 comp.setIcon(ficon);
1481 // tt+="RGB value: Max (" + newColor.getRed() + ", "
1482 // + newColor.getGreen() + ", " + newColor.getBlue()
1483 // + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen()
1484 // + ", " + minCol.getBlue() + ")");
1487 if (tt.length() > 0)
1489 if (comp.getToolTipText() == null)
1491 comp.setToolTipText(tt);
1495 comp.setToolTipText(tt + " " + comp.getToolTipText());
1501 class FeatureIcon implements Icon
1503 GraduatedColor gcol;
1507 int width = 50, height = 20;
1509 FeatureIcon(GraduatedColor gfc, Color bg, int w, int h)
1517 public int getIconWidth()
1522 public int getIconHeight()
1527 public void paintIcon(Component c, Graphics g, int x, int y)
1530 if (gcol.isColourByLabel())
1533 g.fillRect(0, 0, width, height);
1534 // need an icon here.
1535 g.setColor(gcol.getMaxColor());
1537 g.setFont(new Font("Verdana", Font.PLAIN, 9));
1539 // g.setFont(g.getFont().deriveFont(
1540 // AffineTransform.getScaleInstance(
1541 // width/g.getFontMetrics().stringWidth("Label"),
1542 // height/g.getFontMetrics().getHeight())));
1544 g.drawString("Label", 0, 0);
1549 Color minCol = gcol.getMinColor();
1551 g.fillRect(0, 0, width, height);
1556 class ColorEditor extends AbstractCellEditor implements TableCellEditor,
1561 GraduatedColor currentGColor;
1563 FeatureColourChooser chooser;
1571 JColorChooser colorChooser;
1575 protected static final String EDIT = "edit";
1577 int selectedRow = 0;
1579 public ColorEditor(FeatureSettings me)
1582 // Set up the editor (from the table's point of view),
1583 // which is a button.
1584 // This button brings up the color chooser dialog,
1585 // which is the editor from the user's point of view.
1586 button = new JButton();
1587 button.setActionCommand(EDIT);
1588 button.addActionListener(this);
1589 button.setBorderPainted(false);
1590 // Set up the dialog that the button brings up.
1591 colorChooser = new JColorChooser();
1592 dialog = JColorChooser.createDialog(button, "Select new Colour", true, // modal
1593 colorChooser, this, // OK button handler
1594 null); // no CANCEL button handler
1598 * Handles events from the editor button and from the dialog's OK button.
1600 public void actionPerformed(ActionEvent e)
1603 if (EDIT.equals(e.getActionCommand()))
1605 // The user has clicked the cell, so
1606 // bring up the dialog.
1607 if (currentColor != null)
1609 // bring up simple color chooser
1610 button.setBackground(currentColor);
1611 colorChooser.setColor(currentColor);
1612 dialog.setVisible(true);
1616 // bring up graduated chooser.
1617 chooser = new FeatureColourChooser(me.fr, type);
1618 chooser.setRequestFocusEnabled(true);
1619 chooser.requestFocus();
1620 chooser.addActionListener(this);
1622 // Make the renderer reappear.
1623 fireEditingStopped();
1627 { // User pressed dialog's "OK" button.
1628 if (currentColor != null)
1630 currentColor = colorChooser.getColor();
1634 // class cast exceptions may be raised if the chooser created on a
1635 // non-graduated color
1636 currentGColor = (GraduatedColor) chooser.getLastColour();
1638 me.table.setValueAt(getCellEditorValue(), selectedRow, 1);
1639 fireEditingStopped();
1640 me.table.validate();
1644 // Implement the one CellEditor method that AbstractCellEditor doesn't.
1645 public Object getCellEditorValue()
1647 if (currentColor == null)
1649 return currentGColor;
1651 return currentColor;
1654 // Implement the one method defined by TableCellEditor.
1655 public Component getTableCellEditorComponent(JTable table, Object value,
1656 boolean isSelected, int row, int column)
1658 currentGColor = null;
1659 currentColor = null;
1660 this.selectedRow = row;
1661 type = me.table.getValueAt(row, 0).toString();
1662 button.setOpaque(true);
1663 button.setBackground(me.getBackground());
1664 if (value instanceof GraduatedColor)
1666 currentGColor = (GraduatedColor) value;
1667 JLabel btn = new JLabel();
1668 btn.setSize(button.getSize());
1669 FeatureSettings.renderGraduatedColor(btn, currentGColor);
1670 button.setBackground(btn.getBackground());
1671 button.setIcon(btn.getIcon());
1672 button.setText(btn.getText());
1677 button.setIcon(null);
1678 currentColor = (Color) value;
1679 button.setBackground(currentColor);