2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.5)
3 * Copyright (C) 2010 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
11 * Jalview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
24 import java.awt.event.*;
25 import java.awt.geom.AffineTransform;
26 import java.awt.image.BufferedImage;
27 import java.beans.PropertyChangeEvent;
28 import java.beans.PropertyChangeListener;
31 import javax.swing.event.*;
32 import javax.swing.table.*;
34 import jalview.analysis.AlignmentSorter;
35 import jalview.bin.Cache;
36 import jalview.commands.OrderCommand;
37 import jalview.datamodel.*;
39 import jalview.schemes.AnnotationColourGradient;
40 import jalview.schemes.GraduatedColor;
42 public class FeatureSettings extends JPanel
44 DasSourceBrowser dassourceBrowser;
46 jalview.ws.DasSequenceFeatureFetcher dasFeatureFetcher;
48 JPanel settingsPane = new JPanel();
50 JPanel dasSettingsPane = new JPanel();
52 final FeatureRenderer fr;
54 public final AlignFrame af;
56 Object[][] originalData;
58 final JInternalFrame frame;
60 JScrollPane scrollPane = new JScrollPane();
66 JSlider transparency = new JSlider();
68 JPanel transPanel = new JPanel(new GridLayout(1, 2));
70 public FeatureSettings(AlignFrame af)
73 fr = af.getFeatureRenderer();
75 transparency.setMaximum(100 - (int) (fr.transparency * 100));
80 } catch (Exception ex)
86 table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));
87 table.setFont(new Font("Verdana", Font.PLAIN, 12));
88 table.setDefaultRenderer(Color.class, new ColorRenderer());
90 table.setDefaultEditor(Color.class, new ColorEditor(this));
92 table.setDefaultEditor(GraduatedColor.class, new ColorEditor(this));
93 table.setDefaultRenderer(GraduatedColor.class, new ColorRenderer());
94 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
96 table.addMouseListener(new MouseAdapter()
98 public void mousePressed(MouseEvent evt)
100 selectedRow = table.rowAtPoint(evt.getPoint());
101 if (javax.swing.SwingUtilities.isRightMouseButton(evt))
103 popupSort(selectedRow, (String) table.getValueAt(selectedRow, 0),
104 table.getValueAt(selectedRow, 1), fr.minmax, evt.getX(),
110 table.addMouseMotionListener(new MouseMotionAdapter()
112 public void mouseDragged(MouseEvent evt)
114 int newRow = table.rowAtPoint(evt.getPoint());
115 if (newRow != selectedRow && selectedRow != -1 && newRow != -1)
117 Object[] temp = new Object[3];
118 temp[0] = table.getValueAt(selectedRow, 0);
119 temp[1] = table.getValueAt(selectedRow, 1);
120 temp[2] = table.getValueAt(selectedRow, 2);
122 table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0);
123 table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1);
124 table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2);
126 table.setValueAt(temp[0], newRow, 0);
127 table.setValueAt(temp[1], newRow, 1);
128 table.setValueAt(temp[2], newRow, 2);
130 selectedRow = newRow;
135 scrollPane.setViewportView(table);
137 dassourceBrowser = new DasSourceBrowser(this);
138 dasSettingsPane.add(dassourceBrowser, BorderLayout.CENTER);
140 if (af.getViewport().featuresDisplayed == null
141 || fr.renderOrder == null)
143 fr.findAllFeatures(true); // display everything!
147 final PropertyChangeListener change;
148 final FeatureSettings fs = this;
149 fr.addPropertyChangeListener(change = new PropertyChangeListener()
151 public void propertyChange(PropertyChangeEvent evt)
153 if (!fs.resettingTable && !fs.handlingUpdate)
155 fs.handlingUpdate = true;
156 fs.resetTable(null); // new groups may be added with new seuqence
157 // feature types only
158 fs.handlingUpdate = false;
164 frame = new JInternalFrame();
165 frame.setContentPane(this);
166 if (new jalview.util.Platform().isAMac())
168 Desktop.addInternalFrame(frame, "Sequence Feature Settings", 475, 480);
170 Desktop.addInternalFrame(frame, "Sequence Feature Settings", 400, 450);
174 .addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
176 public void internalFrameClosed(
177 javax.swing.event.InternalFrameEvent evt)
179 fr.removePropertyChangeListener(change);
180 dassourceBrowser.fs = null;
183 frame.setLayer(JLayeredPane.PALETTE_LAYER);
186 protected void popupSort(final int selectedRow, final String type,
187 final Object typeCol, final Hashtable minmax, int x, int y)
189 JPopupMenu men = new JPopupMenu("Settings for " + type);
190 JMenuItem scr = new JMenuItem("Sort by Score");
192 final FeatureSettings me = this;
193 scr.addActionListener(new ActionListener()
196 public void actionPerformed(ActionEvent e)
198 me.sortByScore(new String[]
203 JMenuItem dens = new JMenuItem("Sort by Density");
204 dens.addActionListener(new ActionListener()
207 public void actionPerformed(ActionEvent e)
209 me.sortByDens(new String[]
217 final Object typeMinMax = minmax.get(type);
219 * final JCheckBoxMenuItem chb = new JCheckBoxMenuItem("Vary Height"); //
220 * this is broken at the moment and isn't that useful anyway!
221 * chb.setSelected(minmax.get(type) != null); chb.addActionListener(new
224 * public void actionPerformed(ActionEvent e) {
225 * chb.setState(chb.getState()); if (chb.getState()) { minmax.put(type,
226 * null); } else { minmax.put(type, typeMinMax); } }
232 if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null)
234 // if (table.getValueAt(row, column));
235 // graduated colourschemes for those where minmax exists for the
236 // positional features
237 final JCheckBoxMenuItem mxcol = new JCheckBoxMenuItem(
239 mxcol.setSelected(!(typeCol instanceof Color));
241 mxcol.addActionListener(new ActionListener()
243 JColorChooser colorChooser;
245 public void actionPerformed(ActionEvent e)
247 if (e.getSource() == mxcol)
249 if (typeCol instanceof Color)
251 FeatureColourChooser fc = new FeatureColourChooser(me.fr,
253 fc.addActionListener(this);
257 // bring up simple color chooser
258 colorChooser = new JColorChooser();
259 JDialog dialog = JColorChooser.createDialog(me,
260 "Select new Colour", true, // modal
261 colorChooser, this, // OK button handler
262 null); // no CANCEL button handler
263 colorChooser.setColor(((GraduatedColor) typeCol)
265 dialog.setVisible(true);
270 if (e.getSource() instanceof FeatureColourChooser)
272 FeatureColourChooser fc = (FeatureColourChooser) e
274 table.setValueAt(fc.getLastColour(), selectedRow, 1);
279 // probably the color chooser!
280 table.setValueAt(colorChooser.getColor(), selectedRow, 1);
282 me.updateFeatureRenderer(((FeatureTableModel) table
283 .getModel()).getData(), false);
291 men.show(table, x, y);
295 * true when Feature Settings are updating from feature renderer
297 private boolean handlingUpdate = false;
300 * contains a float[3] for each feature type string. created by setTableData
302 Hashtable typeWidth = null;
304 synchronized public void setTableData()
306 if (fr.featureGroups == null)
308 fr.featureGroups = new Hashtable();
310 Vector allFeatures = new Vector();
311 Vector allGroups = new Vector();
312 SequenceFeature[] tmpfeatures;
314 for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)
316 if (af.getViewport().alignment.getSequenceAt(i).getDatasetSequence()
317 .getSequenceFeatures() == null)
322 tmpfeatures = af.getViewport().alignment.getSequenceAt(i)
323 .getDatasetSequence().getSequenceFeatures();
326 while (index < tmpfeatures.length)
328 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
334 if (tmpfeatures[index].getFeatureGroup() != null)
336 group = tmpfeatures[index].featureGroup;
337 if (!allGroups.contains(group))
339 allGroups.addElement(group);
342 checkGroupState(group);
347 if (!allFeatures.contains(tmpfeatures[index].getType()))
349 allFeatures.addElement(tmpfeatures[index].getType());
363 * @return true if group has been seen before and is already added to set.
365 private boolean checkGroupState(String group)
368 if (fr.featureGroups.containsKey(group))
370 visible = ((Boolean) fr.featureGroups.get(group)).booleanValue();
374 visible = true; // new group is always made visible
377 if (groupPanel == null)
379 groupPanel = new JPanel();
382 boolean alreadyAdded = false;
383 for (int g = 0; g < groupPanel.getComponentCount(); g++)
385 if (((JCheckBox) groupPanel.getComponent(g)).getText().equals(group))
388 ((JCheckBox) groupPanel.getComponent(g)).setSelected(visible);
399 fr.featureGroups.put(group, new Boolean(visible));
400 final String grp = group;
401 final JCheckBox check = new JCheckBox(group, visible);
402 check.setFont(new Font("Serif", Font.BOLD, 12));
403 check.addItemListener(new ItemListener()
405 public void itemStateChanged(ItemEvent evt)
407 fr.featureGroups.put(check.getText(), new Boolean(check
409 af.alignPanel.seqPanel.seqCanvas.repaint();
410 if (af.alignPanel.overviewPanel != null)
412 af.alignPanel.overviewPanel.updateOverviewImage();
415 resetTable(new String[]
419 groupPanel.add(check);
423 boolean resettingTable = false;
425 synchronized void resetTable(String[] groupChanged)
427 if (resettingTable == true)
431 resettingTable = true;
432 typeWidth = new Hashtable();
433 // TODO: change avWidth calculation to 'per-sequence' average and use long
435 float[] avWidth = null;
436 SequenceFeature[] tmpfeatures;
437 String group = null, type;
438 Vector visibleChecks = new Vector();
440 // Find out which features should be visible depending on which groups
441 // are selected / deselected
442 // and recompute average width ordering
443 for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)
446 tmpfeatures = af.getViewport().alignment.getSequenceAt(i)
447 .getDatasetSequence().getSequenceFeatures();
448 if (tmpfeatures == null)
454 while (index < tmpfeatures.length)
456 group = tmpfeatures[index].featureGroup;
458 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
464 if (group == null || fr.featureGroups.get(group) == null
465 || ((Boolean) fr.featureGroups.get(group)).booleanValue())
468 checkGroupState(group);
469 type = tmpfeatures[index].getType();
470 if (!visibleChecks.contains(type))
472 visibleChecks.addElement(type);
475 if (!typeWidth.containsKey(tmpfeatures[index].getType()))
477 typeWidth.put(tmpfeatures[index].getType(),
478 avWidth = new float[3]);
482 avWidth = (float[]) typeWidth.get(tmpfeatures[index].getType());
485 if (tmpfeatures[index].getBegin() > tmpfeatures[index].getEnd())
487 avWidth[1] += 1 + tmpfeatures[index].getBegin()
488 - tmpfeatures[index].getEnd();
492 avWidth[1] += 1 + tmpfeatures[index].getEnd()
493 - tmpfeatures[index].getBegin();
499 int fSize = visibleChecks.size();
500 Object[][] data = new Object[fSize][3];
503 if (fr.renderOrder != null)
506 fr.findAllFeatures(groupChanged != null); // prod to update
507 // colourschemes. but don't
509 // First add the checks in the previous render order,
510 // in case the window has been closed and reopened
511 for (int ro = fr.renderOrder.length - 1; ro > -1; ro--)
513 type = fr.renderOrder[ro];
515 if (!visibleChecks.contains(type))
520 data[dataIndex][0] = type;
521 data[dataIndex][1] = fr.getFeatureStyle(type);
522 data[dataIndex][2] = new Boolean(af.getViewport().featuresDisplayed
525 visibleChecks.removeElement(type);
529 fSize = visibleChecks.size();
530 for (int i = 0; i < fSize; i++)
532 // These must be extra features belonging to the group
533 // which was just selected
534 type = visibleChecks.elementAt(i).toString();
535 data[dataIndex][0] = type;
537 data[dataIndex][1] = fr.getFeatureStyle(type);
538 if (data[dataIndex][1] == null)
540 // "Colour has been updated in another view!!"
541 fr.renderOrder = null;
545 data[dataIndex][2] = new Boolean(true);
549 if (originalData == null)
551 originalData = new Object[data.length][3];
552 for (int i = 0; i < data.length; i++)
554 System.arraycopy(data[i], 0, originalData[i], 0, 3);
558 table.setModel(new FeatureTableModel(data));
559 table.getColumnModel().getColumn(0).setPreferredWidth(200);
561 if (groupPanel != null)
563 groupPanel.setLayout(new GridLayout(fr.featureGroups.size() / 4 + 1,
566 groupPanel.validate();
567 bigPanel.add(groupPanel, BorderLayout.NORTH);
570 updateFeatureRenderer(data, groupChanged != null);
571 resettingTable = false;
575 * reorder data based on the featureRenderers global priority list.
579 private void ensureOrder(Object[][] data)
581 boolean sort = false;
582 float[] order = new float[data.length];
583 for (int i = 0; i < order.length; i++)
585 order[i] = fr.getOrder(data[i][0].toString());
587 order[i] = fr.setOrder(data[i][0].toString(), i / order.length);
589 sort = sort || order[i - 1] > order[i];
592 jalview.util.QuickSort.sort(order, data);
597 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
598 .getProperty("LAST_DIRECTORY"), new String[]
599 { "fc" }, new String[]
600 { "Sequence Feature Colours" }, "Sequence Feature Colours");
601 chooser.setFileView(new jalview.io.JalviewFileView());
602 chooser.setDialogTitle("Load Feature Colours");
603 chooser.setToolTipText("Load");
605 int value = chooser.showOpenDialog(this);
607 if (value == JalviewFileChooser.APPROVE_OPTION)
609 File file = chooser.getSelectedFile();
613 InputStreamReader in = new InputStreamReader(new FileInputStream(
616 jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
617 jucs = (jalview.schemabinding.version2.JalviewUserColours) jucs
620 for (int i = jucs.getColourCount() - 1; i >= 0; i--)
623 jalview.schemabinding.version2.Colour newcol = jucs.getColour(i);
626 Color mincol = null, maxcol = null;
629 mincol = new Color(Integer.parseInt(newcol.getMinRGB(), 16));
630 maxcol = new Color(Integer.parseInt(newcol.getRGB(), 16));
632 } catch (Exception e)
634 Cache.log.warn("Couldn't parse out graduated feature color.",
637 GraduatedColor gcol = new GraduatedColor(mincol, maxcol, newcol
638 .getMin(), newcol.getMax());
639 if (newcol.hasAutoScale())
641 gcol.setAutoScaled(newcol.getAutoScale());
643 if (newcol.hasColourByLabel())
645 gcol.setColourByLabel(newcol.getColourByLabel());
647 if (newcol.hasThreshold())
649 gcol.setThresh(newcol.getThreshold());
650 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD); // default
652 if (newcol.getThreshType().length() > 0)
654 String ttyp = newcol.getThreshType();
655 if (ttyp.equalsIgnoreCase("NONE"))
657 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD);
659 if (ttyp.equalsIgnoreCase("ABOVE"))
662 .setThreshType(AnnotationColourGradient.ABOVE_THRESHOLD);
664 if (ttyp.equalsIgnoreCase("BELOW"))
667 .setThreshType(AnnotationColourGradient.BELOW_THRESHOLD);
670 fr.setColour(name = newcol.getName(), gcol);
674 fr.setColour(name = jucs.getColour(i).getName(), new Color(
675 Integer.parseInt(jucs.getColour(i).getRGB(), 16)));
677 fr.setOrder(name, (i == 0) ? 0 : i / jucs.getColourCount());
682 Object[][] data = ((FeatureTableModel) table.getModel())
685 updateFeatureRenderer(data, false);
688 } catch (Exception ex)
690 System.out.println("Error loading User Colour File\n" + ex);
697 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
698 .getProperty("LAST_DIRECTORY"), new String[]
699 { "fc" }, new String[]
700 { "Sequence Feature Colours" }, "Sequence Feature Colours");
701 chooser.setFileView(new jalview.io.JalviewFileView());
702 chooser.setDialogTitle("Save Feature Colour Scheme");
703 chooser.setToolTipText("Save");
705 int value = chooser.showSaveDialog(this);
707 if (value == JalviewFileChooser.APPROVE_OPTION)
709 String choice = chooser.getSelectedFile().getPath();
710 jalview.schemabinding.version2.JalviewUserColours ucs = new jalview.schemabinding.version2.JalviewUserColours();
711 ucs.setSchemeName("Sequence Features");
714 PrintWriter out = new PrintWriter(new OutputStreamWriter(
715 new FileOutputStream(choice), "UTF-8"));
717 Enumeration e = fr.featureColours.keys();
718 float[] sortOrder = new float[fr.featureColours.size()];
719 String[] sortTypes = new String[fr.featureColours.size()];
721 while (e.hasMoreElements())
723 sortTypes[i] = e.nextElement().toString();
724 sortOrder[i] = fr.getOrder(sortTypes[i]);
727 jalview.util.QuickSort.sort(sortOrder, sortTypes);
731 for (i = 0; i < sortTypes.length; i++)
733 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
734 col.setName(sortTypes[i]);
735 col.setRGB(jalview.util.Format.getHexString(fr.getColour(col
737 fcol = fr.getFeatureStyle(sortTypes[i]);
738 if (fcol instanceof GraduatedColor)
740 gcol = (GraduatedColor) fcol;
741 col.setMin(gcol.getMin());
742 col.setMax(gcol.getMax());
743 col.setMinRGB(jalview.util.Format.getHexString(gcol
745 col.setAutoScale(gcol.isAutoScale());
746 col.setThreshold(gcol.getThresh());
747 col.setColourByLabel(gcol.isColourByLabel());
748 switch (gcol.getThreshType())
750 case AnnotationColourGradient.NO_THRESHOLD:
751 col.setThreshType("NONE");
753 case AnnotationColourGradient.ABOVE_THRESHOLD:
754 col.setThreshType("ABOVE");
756 case AnnotationColourGradient.BELOW_THRESHOLD:
757 col.setThreshType("BELOW");
765 } catch (Exception ex)
767 ex.printStackTrace();
772 public void invertSelection()
774 for (int i = 0; i < table.getRowCount(); i++)
776 Boolean value = (Boolean) table.getValueAt(i, 2);
778 table.setValueAt(new Boolean(!value.booleanValue()), i, 2);
782 public void orderByAvWidth()
784 if (table == null || table.getModel() == null)
786 Object[][] data = ((FeatureTableModel) table.getModel()).getData();
787 float[] width = new float[data.length];
791 for (int i = 0; i < data.length; i++)
793 awidth = (float[]) typeWidth.get(data[i][0]);
796 width[i] = awidth[1] / awidth[0];// *awidth[0]*awidth[2]; - better
797 // weight - but have to make per
798 // sequence, too (awidth[2])
799 // if (width[i]==1) // hack to distinguish single width sequences.
809 boolean sort = false;
810 for (int i = 0; i < width.length; i++)
812 // awidth = (float[]) typeWidth.get(data[i][0]);
815 width[i] = fr.getOrder(data[i][0].toString());
818 width[i] = fr.setOrder(data[i][0].toString(), i / data.length);
823 width[i] /= max; // normalize
824 fr.setOrder(data[i][0].toString(), width[i]); // store for later
827 sort = sort || width[i - 1] > width[i];
830 jalview.util.QuickSort.sort(width, data);
831 // update global priority order
833 updateFeatureRenderer(data, false);
841 frame.setClosed(true);
842 } catch (Exception exe)
848 public void updateFeatureRenderer(Object[][] data)
850 updateFeatureRenderer(data, true);
853 private void updateFeatureRenderer(Object[][] data, boolean visibleNew)
855 fr.setFeaturePriority(data, visibleNew);
856 af.alignPanel.paintAlignment(true);
859 int selectedRow = -1;
861 JTabbedPane tabbedPane = new JTabbedPane();
863 BorderLayout borderLayout1 = new BorderLayout();
865 BorderLayout borderLayout2 = new BorderLayout();
867 BorderLayout borderLayout3 = new BorderLayout();
869 JPanel bigPanel = new JPanel();
871 BorderLayout borderLayout4 = new BorderLayout();
873 JButton invert = new JButton();
875 JPanel buttonPanel = new JPanel();
877 JButton cancel = new JButton();
879 JButton ok = new JButton();
881 JButton loadColours = new JButton();
883 JButton saveColours = new JButton();
885 JPanel dasButtonPanel = new JPanel();
887 JButton fetchDAS = new JButton();
889 JButton saveDAS = new JButton();
891 JButton cancelDAS = new JButton();
893 JButton optimizeOrder = new JButton();
895 JButton sortByScore = new JButton();
897 JButton sortByDens = new JButton();
899 JPanel transbuttons = new JPanel(new GridLayout(4, 1));
901 private void jbInit() throws Exception
903 this.setLayout(borderLayout1);
904 settingsPane.setLayout(borderLayout2);
905 dasSettingsPane.setLayout(borderLayout3);
906 bigPanel.setLayout(borderLayout4);
907 invert.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
908 invert.setText("Invert Selection");
909 invert.addActionListener(new ActionListener()
911 public void actionPerformed(ActionEvent e)
916 optimizeOrder.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
917 optimizeOrder.setText("Optimise Order");
918 optimizeOrder.addActionListener(new ActionListener()
920 public void actionPerformed(ActionEvent e)
925 sortByScore.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
926 sortByScore.setText("Seq sort by Score");
927 sortByScore.addActionListener(new ActionListener()
929 public void actionPerformed(ActionEvent e)
934 sortByDens.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
935 sortByDens.setText("Seq Sort by density");
936 sortByDens.addActionListener(new ActionListener()
938 public void actionPerformed(ActionEvent e)
943 cancel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
944 cancel.setText("Cancel");
945 cancel.addActionListener(new ActionListener()
947 public void actionPerformed(ActionEvent e)
949 updateFeatureRenderer(originalData);
953 ok.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
955 ok.addActionListener(new ActionListener()
957 public void actionPerformed(ActionEvent e)
962 loadColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
963 loadColours.setText("Load Colours");
964 loadColours.addActionListener(new ActionListener()
966 public void actionPerformed(ActionEvent e)
971 saveColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
972 saveColours.setText("Save Colours");
973 saveColours.addActionListener(new ActionListener()
975 public void actionPerformed(ActionEvent e)
980 transparency.addChangeListener(new ChangeListener()
982 public void stateChanged(ChangeEvent evt)
984 fr.setTransparency((float) (100 - transparency.getValue()) / 100f);
985 af.alignPanel.paintAlignment(true);
989 transparency.setMaximum(70);
990 fetchDAS.setText("Fetch DAS Features");
991 fetchDAS.addActionListener(new ActionListener()
993 public void actionPerformed(ActionEvent e)
995 fetchDAS_actionPerformed(e);
998 saveDAS.setText("Save as default");
999 saveDAS.addActionListener(new ActionListener()
1001 public void actionPerformed(ActionEvent e)
1003 saveDAS_actionPerformed(e);
1006 dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
1007 dasSettingsPane.setBorder(null);
1008 cancelDAS.setEnabled(false);
1009 cancelDAS.setText("Cancel Fetch");
1010 cancelDAS.addActionListener(new ActionListener()
1012 public void actionPerformed(ActionEvent e)
1014 cancelDAS_actionPerformed(e);
1017 this.add(tabbedPane, java.awt.BorderLayout.CENTER);
1018 tabbedPane.addTab("Feature Settings", settingsPane);
1019 tabbedPane.addTab("DAS Settings", dasSettingsPane);
1020 bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
1021 transbuttons.add(optimizeOrder);
1022 transbuttons.add(invert);
1023 transbuttons.add(sortByScore);
1024 transbuttons.add(sortByDens);
1025 transPanel.add(transparency);
1026 transPanel.add(transbuttons);
1027 buttonPanel.add(ok);
1028 buttonPanel.add(cancel);
1029 buttonPanel.add(loadColours);
1030 buttonPanel.add(saveColours);
1031 bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
1032 dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
1033 dasButtonPanel.add(fetchDAS);
1034 dasButtonPanel.add(cancelDAS);
1035 dasButtonPanel.add(saveDAS);
1036 settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);
1037 settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
1040 protected void sortByDens(String[] typ)
1042 sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY);
1045 protected void sortBy(String[] typ, String methodText, final String method)
1049 typ = getDisplayedFeatureTypes();
1051 String gps[] = null;
1052 gps = getDisplayedFeatureGroups();
1055 ArrayList types = new ArrayList();
1056 for (int i = 0; i < typ.length; i++)
1062 typ = new String[types.size()];
1068 ArrayList grps = new ArrayList();
1070 for (int i = 0; i < gps.length; i++)
1077 gps = new String[grps.size()];
1080 AlignmentPanel alignPanel = af.alignPanel;
1081 AlignmentI al = alignPanel.av.getAlignment();
1084 SequenceGroup sg = alignPanel.av.getSelectionGroup();
1087 start = sg.getStartRes();
1088 stop = sg.getEndRes();
1093 stop = al.getWidth();
1095 SequenceI[] oldOrder = al.getSequencesArray();
1096 AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
1097 af.addHistoryItem(new OrderCommand(methodText, oldOrder, alignPanel.av
1099 alignPanel.paintAlignment(true);
1103 protected void sortByScore(String[] typ)
1105 sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE);
1108 private String[] getDisplayedFeatureTypes()
1110 String[] typ = null;
1113 synchronized (fr.renderOrder)
1115 typ = new String[fr.renderOrder.length];
1116 System.arraycopy(fr.renderOrder, 0, typ, 0, typ.length);
1117 for (int i = 0; i < typ.length; i++)
1119 if (af.viewport.featuresDisplayed.get(typ[i]) == null)
1129 private String[] getDisplayedFeatureGroups()
1131 String[] gps = null;
1135 if (fr.featureGroups != null)
1137 Enumeration en = fr.featureGroups.keys();
1138 gps = new String[fr.featureColours.size()];
1140 boolean valid = false;
1141 while (en.hasMoreElements())
1143 String gp = (String) en.nextElement();
1144 Boolean on = (Boolean) fr.featureGroups.get(gp);
1145 if (on != null && on.booleanValue())
1151 while (g < gps.length)
1164 public void fetchDAS_actionPerformed(ActionEvent e)
1166 fetchDAS.setEnabled(false);
1167 cancelDAS.setEnabled(true);
1168 dassourceBrowser.setGuiEnabled(false);
1169 Vector selectedSources = dassourceBrowser.getSelectedSources();
1170 doDasFeatureFetch(selectedSources, true, true);
1174 * get the features from selectedSources for all or the current selection
1176 * @param selectedSources
1177 * @param checkDbRefs
1178 * @param promptFetchDbRefs
1180 private void doDasFeatureFetch(Vector selectedSources,
1181 boolean checkDbRefs, boolean promptFetchDbRefs)
1183 SequenceI[] dataset, seqs;
1185 AlignViewport vp = af.getViewport();
1186 if (vp.getSelectionGroup() != null
1187 && vp.getSelectionGroup().getSize() > 0)
1189 iSize = vp.getSelectionGroup().getSize();
1190 dataset = new SequenceI[iSize];
1191 seqs = vp.getSelectionGroup().getSequencesInOrder(vp.getAlignment());
1195 iSize = vp.getAlignment().getHeight();
1196 seqs = vp.getAlignment().getSequencesArray();
1199 dataset = new SequenceI[iSize];
1200 for (int i = 0; i < iSize; i++)
1202 dataset[i] = seqs[i].getDatasetSequence();
1205 cancelDAS.setEnabled(true);
1206 dasFeatureFetcher = new jalview.ws.DasSequenceFeatureFetcher(dataset,
1207 this, selectedSources, checkDbRefs, promptFetchDbRefs);
1208 af.getViewport().setShowSequenceFeatures(true);
1209 af.showSeqFeatures.setSelected(true);
1213 * blocking call to initialise the das source browser
1215 public void initDasSources()
1217 dassourceBrowser.initDasSources();
1221 * examine the current list of das sources and return any matching the given
1222 * nicknames in sources
1225 * Vector of Strings to resolve to DAS source nicknames.
1226 * @return sources that are present in source list.
1228 public Vector resolveSourceNicknames(Vector sources)
1230 return dassourceBrowser.resolveSourceNicknames(sources);
1234 * get currently selected das sources. ensure you have called initDasSources
1235 * before calling this.
1237 * @return vector of selected das source nicknames
1239 public Vector getSelectedSources()
1241 return dassourceBrowser.getSelectedSources();
1245 * properly initialise DAS fetcher and then initiate a new thread to fetch
1246 * features from the named sources (rather than any turned on by default)
1250 * if true then runs in same thread, otherwise passes to the Swing
1253 public void fetchDasFeatures(Vector sources, boolean block)
1256 Vector resolved = resolveSourceNicknames(sources);
1257 if (resolved.size() == 0)
1259 resolved = dassourceBrowser.getSelectedSources();
1261 if (resolved.size() > 0)
1263 final Vector dassources = resolved;
1264 fetchDAS.setEnabled(false);
1265 // cancelDAS.setEnabled(true); doDasFetch does this.
1266 Runnable fetcher = new Runnable()
1271 doDasFeatureFetch(dassources, true, false);
1281 SwingUtilities.invokeLater(fetcher);
1286 public void saveDAS_actionPerformed(ActionEvent e)
1289 .saveProperties(jalview.bin.Cache.applicationProperties);
1292 public void complete()
1294 fetchDAS.setEnabled(true);
1295 cancelDAS.setEnabled(false);
1296 dassourceBrowser.setGuiEnabled(true);
1300 public void cancelDAS_actionPerformed(ActionEvent e)
1302 if (dasFeatureFetcher != null)
1304 dasFeatureFetcher.cancel();
1309 public void noDasSourceActive()
1312 JOptionPane.showInternalConfirmDialog(Desktop.desktop,
1313 "No das sources were selected.\n"
1314 + "Please select some sources and\n" + " try again.",
1315 "No Sources Selected", JOptionPane.DEFAULT_OPTION,
1316 JOptionPane.INFORMATION_MESSAGE);
1319 // ///////////////////////////////////////////////////////////////////////
1320 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
1321 // ///////////////////////////////////////////////////////////////////////
1322 class FeatureTableModel extends AbstractTableModel
1324 FeatureTableModel(Object[][] data)
1329 private String[] columnNames =
1330 { "Feature Type", "Colour", "Display" };
1332 private Object[][] data;
1334 public Object[][] getData()
1339 public void setData(Object[][] data)
1344 public int getColumnCount()
1346 return columnNames.length;
1349 public Object[] getRow(int row)
1354 public int getRowCount()
1359 public String getColumnName(int col)
1361 return columnNames[col];
1364 public Object getValueAt(int row, int col)
1366 return data[row][col];
1369 public Class getColumnClass(int c)
1371 return getValueAt(0, c).getClass();
1374 public boolean isCellEditable(int row, int col)
1376 return col == 0 ? false : true;
1379 public void setValueAt(Object value, int row, int col)
1381 data[row][col] = value;
1382 fireTableCellUpdated(row, col);
1383 updateFeatureRenderer(data);
1388 class ColorRenderer extends JLabel implements TableCellRenderer
1390 javax.swing.border.Border unselectedBorder = null;
1392 javax.swing.border.Border selectedBorder = null;
1394 final String baseTT = "Click to edit, right/apple click for menu.";
1396 public ColorRenderer()
1398 setOpaque(true); // MUST do this for background to show up.
1399 setHorizontalTextPosition(SwingConstants.CENTER);
1400 setVerticalTextPosition(SwingConstants.CENTER);
1403 public Component getTableCellRendererComponent(JTable table,
1404 Object color, boolean isSelected, boolean hasFocus, int row,
1407 // JLabel comp = new JLabel();
1411 // setBounds(getBounds());
1413 setToolTipText(baseTT);
1414 setBackground(table.getBackground());
1415 if (color instanceof GraduatedColor)
1417 Rectangle cr = table.getCellRect(row, column, false);
1418 FeatureSettings.renderGraduatedColor(this, (GraduatedColor) color,
1419 (int) cr.getWidth(), (int) cr.getHeight());
1426 newColor = (Color) color;
1428 setBackground(newColor);
1429 // comp.setToolTipText("RGB value: " + newColor.getRed() + ", "
1430 // + newColor.getGreen() + ", " + newColor.getBlue());
1434 if (selectedBorder == null)
1436 selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1437 table.getSelectionBackground());
1440 setBorder(selectedBorder);
1444 if (unselectedBorder == null)
1446 unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1447 table.getBackground());
1450 setBorder(unselectedBorder);
1458 * update comp using rendering settings from gcol
1463 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol)
1465 int w = comp.getWidth(), h = comp.getHeight();
1468 w = (int) comp.getPreferredSize().getWidth();
1469 h = (int) comp.getPreferredSize().getHeight();
1476 renderGraduatedColor(comp, gcol, w, h);
1479 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol,
1482 boolean thr = false;
1485 if (gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD)
1489 tt += "Thresholded (Above " + gcol.getThresh() + ") ";
1491 if (gcol.getThreshType() == AnnotationColourGradient.BELOW_THRESHOLD)
1495 tt += "Thresholded (Below " + gcol.getThresh() + ") ";
1497 if (gcol.isColourByLabel())
1499 tt = "Coloured by label text. " + tt;
1509 Color newColor = gcol.getMaxColor();
1510 comp.setBackground(newColor);
1511 // System.err.println("Width is " + w / 2);
1512 Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w, h, thr);
1513 comp.setIcon(ficon);
1514 // tt+="RGB value: Max (" + newColor.getRed() + ", "
1515 // + newColor.getGreen() + ", " + newColor.getBlue()
1516 // + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen()
1517 // + ", " + minCol.getBlue() + ")");
1519 comp.setHorizontalAlignment(SwingConstants.CENTER);
1521 if (tt.length() > 0)
1523 if (comp.getToolTipText() == null)
1525 comp.setToolTipText(tt);
1529 comp.setToolTipText(tt + " " + comp.getToolTipText());
1535 class FeatureIcon implements Icon
1537 GraduatedColor gcol;
1541 boolean midspace = false;
1543 int width = 50, height = 20;
1545 int s1, e1; // start and end of midpoint band for thresholded symbol
1547 Color mpcolour = Color.white;
1549 FeatureIcon(GraduatedColor gfc, Color bg, int w, int h, boolean mspace)
1568 public int getIconWidth()
1573 public int getIconHeight()
1578 public void paintIcon(Component c, Graphics g, int x, int y)
1581 if (gcol.isColourByLabel())
1584 g.fillRect(0, 0, width, height);
1585 // need an icon here.
1586 g.setColor(gcol.getMaxColor());
1588 g.setFont(new Font("Verdana", Font.PLAIN, 9));
1590 // g.setFont(g.getFont().deriveFont(
1591 // AffineTransform.getScaleInstance(
1592 // width/g.getFontMetrics().stringWidth("Label"),
1593 // height/g.getFontMetrics().getHeight())));
1595 g.drawString("Label", 0, 0);
1600 Color minCol = gcol.getMinColor();
1602 g.fillRect(0, 0, s1, height);
1605 g.setColor(Color.white);
1606 g.fillRect(s1, 0, e1 - s1, height);
1608 g.setColor(gcol.getMaxColor());
1609 g.fillRect(0, e1, width - e1, height);
1614 class ColorEditor extends AbstractCellEditor implements TableCellEditor,
1619 GraduatedColor currentGColor;
1621 FeatureColourChooser chooser;
1629 JColorChooser colorChooser;
1633 protected static final String EDIT = "edit";
1635 int selectedRow = 0;
1637 public ColorEditor(FeatureSettings me)
1640 // Set up the editor (from the table's point of view),
1641 // which is a button.
1642 // This button brings up the color chooser dialog,
1643 // which is the editor from the user's point of view.
1644 button = new JButton();
1645 button.setActionCommand(EDIT);
1646 button.addActionListener(this);
1647 button.setBorderPainted(false);
1648 // Set up the dialog that the button brings up.
1649 colorChooser = new JColorChooser();
1650 dialog = JColorChooser.createDialog(button, "Select new Colour", true, // modal
1651 colorChooser, this, // OK button handler
1652 null); // no CANCEL button handler
1656 * Handles events from the editor button and from the dialog's OK button.
1658 public void actionPerformed(ActionEvent e)
1661 if (EDIT.equals(e.getActionCommand()))
1663 // The user has clicked the cell, so
1664 // bring up the dialog.
1665 if (currentColor != null)
1667 // bring up simple color chooser
1668 button.setBackground(currentColor);
1669 colorChooser.setColor(currentColor);
1670 dialog.setVisible(true);
1674 // bring up graduated chooser.
1675 chooser = new FeatureColourChooser(me.fr, type);
1676 chooser.setRequestFocusEnabled(true);
1677 chooser.requestFocus();
1678 chooser.addActionListener(this);
1680 // Make the renderer reappear.
1681 fireEditingStopped();
1685 { // User pressed dialog's "OK" button.
1686 if (currentColor != null)
1688 currentColor = colorChooser.getColor();
1692 // class cast exceptions may be raised if the chooser created on a
1693 // non-graduated color
1694 currentGColor = (GraduatedColor) chooser.getLastColour();
1696 me.table.setValueAt(getCellEditorValue(), selectedRow, 1);
1697 fireEditingStopped();
1698 me.table.validate();
1702 // Implement the one CellEditor method that AbstractCellEditor doesn't.
1703 public Object getCellEditorValue()
1705 if (currentColor == null)
1707 return currentGColor;
1709 return currentColor;
1712 // Implement the one method defined by TableCellEditor.
1713 public Component getTableCellEditorComponent(JTable table, Object value,
1714 boolean isSelected, int row, int column)
1716 currentGColor = null;
1717 currentColor = null;
1718 this.selectedRow = row;
1719 type = me.table.getValueAt(row, 0).toString();
1720 button.setOpaque(true);
1721 button.setBackground(me.getBackground());
1722 if (value instanceof GraduatedColor)
1724 currentGColor = (GraduatedColor) value;
1725 JLabel btn = new JLabel();
1726 btn.setSize(button.getSize());
1727 FeatureSettings.renderGraduatedColor(btn, currentGColor);
1728 button.setBackground(btn.getBackground());
1729 button.setIcon(btn.getIcon());
1730 button.setText(btn.getText());
1735 button.setIcon(null);
1736 currentColor = (Color) value;
1737 button.setBackground(currentColor);