2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
3 * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, 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/>.
22 import java.util.List;
25 import java.awt.event.*;
26 import java.beans.PropertyChangeEvent;
27 import java.beans.PropertyChangeListener;
30 import javax.swing.event.*;
31 import javax.swing.table.*;
33 import jalview.analysis.AlignmentSorter;
34 import jalview.bin.Cache;
35 import jalview.commands.OrderCommand;
36 import jalview.datamodel.*;
38 import jalview.schemes.AnnotationColourGradient;
39 import jalview.schemes.GraduatedColor;
40 import jalview.ws.dbsources.das.api.jalviewSourceI;
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);
172 Desktop.addInternalFrame(frame, "Sequence Feature Settings", 400, 450);
175 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
177 public void internalFrameClosed(
178 javax.swing.event.InternalFrameEvent evt)
180 fr.removePropertyChangeListener(change);
181 dassourceBrowser.fs = null;
184 frame.setLayer(JLayeredPane.PALETTE_LAYER);
187 protected void popupSort(final int selectedRow, final String type,
188 final Object typeCol, final Hashtable minmax, int x, int y)
190 JPopupMenu men = new JPopupMenu("Settings for " + type);
191 JMenuItem scr = new JMenuItem("Sort by Score");
193 final FeatureSettings me = this;
194 scr.addActionListener(new ActionListener()
197 public void actionPerformed(ActionEvent e)
199 me.sortByScore(new String[]
204 JMenuItem dens = new JMenuItem("Sort by Density");
205 dens.addActionListener(new ActionListener()
208 public void actionPerformed(ActionEvent e)
210 me.sortByDens(new String[]
218 final Object typeMinMax = minmax.get(type);
220 * final JCheckBoxMenuItem chb = new JCheckBoxMenuItem("Vary Height"); //
221 * this is broken at the moment and isn't that useful anyway!
222 * chb.setSelected(minmax.get(type) != null); chb.addActionListener(new
225 * public void actionPerformed(ActionEvent e) {
226 * chb.setState(chb.getState()); if (chb.getState()) { minmax.put(type,
227 * null); } else { minmax.put(type, typeMinMax); } }
233 if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null)
235 // if (table.getValueAt(row, column));
236 // graduated colourschemes for those where minmax exists for the
237 // positional features
238 final JCheckBoxMenuItem mxcol = new JCheckBoxMenuItem(
240 mxcol.setSelected(!(typeCol instanceof Color));
242 mxcol.addActionListener(new ActionListener()
244 JColorChooser colorChooser;
246 public void actionPerformed(ActionEvent e)
248 if (e.getSource() == mxcol)
250 if (typeCol instanceof Color)
252 FeatureColourChooser fc = new FeatureColourChooser(me.fr,
254 fc.addActionListener(this);
258 // bring up simple color chooser
259 colorChooser = new JColorChooser();
260 JDialog dialog = JColorChooser.createDialog(me,
261 "Select new Colour", true, // modal
262 colorChooser, this, // OK button handler
263 null); // no CANCEL button handler
264 colorChooser.setColor(((GraduatedColor) typeCol)
266 dialog.setVisible(true);
271 if (e.getSource() instanceof FeatureColourChooser)
273 FeatureColourChooser fc = (FeatureColourChooser) e
275 table.setValueAt(fc.getLastColour(), selectedRow, 1);
280 // probably the color chooser!
281 table.setValueAt(colorChooser.getColor(), selectedRow, 1);
283 me.updateFeatureRenderer(
284 ((FeatureTableModel) table.getModel()).getData(),
293 men.show(table, x, y);
297 * true when Feature Settings are updating from feature renderer
299 private boolean handlingUpdate = false;
302 * contains a float[3] for each feature type string. created by setTableData
304 Hashtable typeWidth = null;
306 synchronized public void setTableData()
308 if (fr.featureGroups == null)
310 fr.featureGroups = new Hashtable();
312 Vector allFeatures = new Vector();
313 Vector allGroups = new Vector();
314 SequenceFeature[] tmpfeatures;
316 for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
318 if (af.getViewport().getAlignment().getSequenceAt(i).getDatasetSequence()
319 .getSequenceFeatures() == null)
324 tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
325 .getDatasetSequence().getSequenceFeatures();
328 while (index < tmpfeatures.length)
330 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
336 if (tmpfeatures[index].getFeatureGroup() != null)
338 group = tmpfeatures[index].featureGroup;
339 if (!allGroups.contains(group))
341 allGroups.addElement(group);
344 checkGroupState(group);
349 if (!allFeatures.contains(tmpfeatures[index].getType()))
351 allFeatures.addElement(tmpfeatures[index].getType());
365 * @return true if group has been seen before and is already added to set.
367 private boolean checkGroupState(String group)
370 if (fr.featureGroups.containsKey(group))
372 visible = ((Boolean) fr.featureGroups.get(group)).booleanValue();
376 visible = true; // new group is always made visible
379 if (groupPanel == null)
381 groupPanel = new JPanel();
384 boolean alreadyAdded = false;
385 for (int g = 0; g < groupPanel.getComponentCount(); g++)
387 if (((JCheckBox) groupPanel.getComponent(g)).getText().equals(group))
390 ((JCheckBox) groupPanel.getComponent(g)).setSelected(visible);
401 fr.featureGroups.put(group, new Boolean(visible));
402 final String grp = group;
403 final JCheckBox check = new JCheckBox(group, visible);
404 check.setFont(new Font("Serif", Font.BOLD, 12));
405 check.addItemListener(new ItemListener()
407 public void itemStateChanged(ItemEvent evt)
409 fr.featureGroups.put(check.getText(),
410 new Boolean(check.isSelected()));
411 af.alignPanel.seqPanel.seqCanvas.repaint();
412 if (af.alignPanel.overviewPanel != null)
414 af.alignPanel.overviewPanel.updateOverviewImage();
417 resetTable(new String[]
421 groupPanel.add(check);
425 boolean resettingTable = false;
427 synchronized void resetTable(String[] groupChanged)
429 if (resettingTable == true)
433 resettingTable = true;
434 typeWidth = new Hashtable();
435 // TODO: change avWidth calculation to 'per-sequence' average and use long
437 float[] avWidth = null;
438 SequenceFeature[] tmpfeatures;
439 String group = null, type;
440 Vector visibleChecks = new Vector();
442 // Find out which features should be visible depending on which groups
443 // are selected / deselected
444 // and recompute average width ordering
445 for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
448 tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
449 .getDatasetSequence().getSequenceFeatures();
450 if (tmpfeatures == null)
456 while (index < tmpfeatures.length)
458 group = tmpfeatures[index].featureGroup;
460 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
466 if (group == null || fr.featureGroups.get(group) == null
467 || ((Boolean) fr.featureGroups.get(group)).booleanValue())
470 checkGroupState(group);
471 type = tmpfeatures[index].getType();
472 if (!visibleChecks.contains(type))
474 visibleChecks.addElement(type);
477 if (!typeWidth.containsKey(tmpfeatures[index].getType()))
479 typeWidth.put(tmpfeatures[index].getType(),
480 avWidth = new float[3]);
484 avWidth = (float[]) typeWidth.get(tmpfeatures[index].getType());
487 if (tmpfeatures[index].getBegin() > tmpfeatures[index].getEnd())
489 avWidth[1] += 1 + tmpfeatures[index].getBegin()
490 - tmpfeatures[index].getEnd();
494 avWidth[1] += 1 + tmpfeatures[index].getEnd()
495 - tmpfeatures[index].getBegin();
501 int fSize = visibleChecks.size();
502 Object[][] data = new Object[fSize][3];
505 if (fr.renderOrder != null)
508 fr.findAllFeatures(groupChanged != null); // prod to update
509 // colourschemes. but don't
511 // First add the checks in the previous render order,
512 // in case the window has been closed and reopened
513 for (int ro = fr.renderOrder.length - 1; ro > -1; ro--)
515 type = fr.renderOrder[ro];
517 if (!visibleChecks.contains(type))
522 data[dataIndex][0] = type;
523 data[dataIndex][1] = fr.getFeatureStyle(type);
524 data[dataIndex][2] = new Boolean(
525 af.getViewport().featuresDisplayed.containsKey(type));
527 visibleChecks.removeElement(type);
531 fSize = visibleChecks.size();
532 for (int i = 0; i < fSize; i++)
534 // These must be extra features belonging to the group
535 // which was just selected
536 type = visibleChecks.elementAt(i).toString();
537 data[dataIndex][0] = type;
539 data[dataIndex][1] = fr.getFeatureStyle(type);
540 if (data[dataIndex][1] == null)
542 // "Colour has been updated in another view!!"
543 fr.renderOrder = null;
547 data[dataIndex][2] = new Boolean(true);
551 if (originalData == null)
553 originalData = new Object[data.length][3];
554 for (int i = 0; i < data.length; i++)
556 System.arraycopy(data[i], 0, originalData[i], 0, 3);
560 table.setModel(new FeatureTableModel(data));
561 table.getColumnModel().getColumn(0).setPreferredWidth(200);
563 if (groupPanel != null)
565 groupPanel.setLayout(new GridLayout(fr.featureGroups.size() / 4 + 1,
568 groupPanel.validate();
569 bigPanel.add(groupPanel, BorderLayout.NORTH);
572 updateFeatureRenderer(data, groupChanged != null);
573 resettingTable = false;
577 * reorder data based on the featureRenderers global priority list.
581 private void ensureOrder(Object[][] data)
583 boolean sort = false;
584 float[] order = new float[data.length];
585 for (int i = 0; i < order.length; i++)
587 order[i] = fr.getOrder(data[i][0].toString());
589 order[i] = fr.setOrder(data[i][0].toString(), i / order.length);
591 sort = sort || order[i - 1] > order[i];
594 jalview.util.QuickSort.sort(order, data);
599 JalviewFileChooser chooser = new JalviewFileChooser(
600 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
601 { "fc" }, new String[]
602 { "Sequence Feature Colours" }, "Sequence Feature Colours");
603 chooser.setFileView(new jalview.io.JalviewFileView());
604 chooser.setDialogTitle("Load Feature Colours");
605 chooser.setToolTipText("Load");
607 int value = chooser.showOpenDialog(this);
609 if (value == JalviewFileChooser.APPROVE_OPTION)
611 File file = chooser.getSelectedFile();
615 InputStreamReader in = new InputStreamReader(new FileInputStream(
618 jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
619 jucs = (jalview.schemabinding.version2.JalviewUserColours) jucs
622 for (int i = jucs.getColourCount() - 1; i >= 0; i--)
625 jalview.schemabinding.version2.Colour newcol = jucs.getColour(i);
628 Color mincol = null, maxcol = null;
631 mincol = new Color(Integer.parseInt(newcol.getMinRGB(), 16));
632 maxcol = new Color(Integer.parseInt(newcol.getRGB(), 16));
634 } catch (Exception e)
636 Cache.log.warn("Couldn't parse out graduated feature color.",
639 GraduatedColor gcol = new GraduatedColor(mincol, maxcol,
640 newcol.getMin(), newcol.getMax());
641 if (newcol.hasAutoScale())
643 gcol.setAutoScaled(newcol.getAutoScale());
645 if (newcol.hasColourByLabel())
647 gcol.setColourByLabel(newcol.getColourByLabel());
649 if (newcol.hasThreshold())
651 gcol.setThresh(newcol.getThreshold());
652 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD); // default
654 if (newcol.getThreshType().length() > 0)
656 String ttyp = newcol.getThreshType();
657 if (ttyp.equalsIgnoreCase("NONE"))
659 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD);
661 if (ttyp.equalsIgnoreCase("ABOVE"))
663 gcol.setThreshType(AnnotationColourGradient.ABOVE_THRESHOLD);
665 if (ttyp.equalsIgnoreCase("BELOW"))
667 gcol.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(
698 jalview.bin.Cache.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(JvSwingUtils.getLabelFont());
908 invert.setText("Invert Selection");
909 invert.addActionListener(new ActionListener()
911 public void actionPerformed(ActionEvent e)
916 optimizeOrder.setFont(JvSwingUtils.getLabelFont());
917 optimizeOrder.setText("Optimise Order");
918 optimizeOrder.addActionListener(new ActionListener()
920 public void actionPerformed(ActionEvent e)
925 sortByScore.setFont(JvSwingUtils.getLabelFont());
926 sortByScore.setText("Seq sort by Score");
927 sortByScore.addActionListener(new ActionListener()
929 public void actionPerformed(ActionEvent e)
934 sortByDens.setFont(JvSwingUtils.getLabelFont());
935 sortByDens.setText("Seq Sort by density");
936 sortByDens.addActionListener(new ActionListener()
938 public void actionPerformed(ActionEvent e)
943 cancel.setFont(JvSwingUtils.getLabelFont());
944 cancel.setText("Cancel");
945 cancel.addActionListener(new ActionListener()
947 public void actionPerformed(ActionEvent e)
949 updateFeatureRenderer(originalData);
953 ok.setFont(JvSwingUtils.getLabelFont());
955 ok.addActionListener(new ActionListener()
957 public void actionPerformed(ActionEvent e)
962 loadColours.setFont(JvSwingUtils.getLabelFont());
963 loadColours.setText("Load Colours");
964 loadColours.addActionListener(new ActionListener()
966 public void actionPerformed(ActionEvent e)
971 saveColours.setFont(JvSwingUtils.getLabelFont());
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(List<jalviewSourceI> 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 List<jalviewSourceI> resolveSourceNicknames(Vector sources)
1230 return dassourceBrowser.sourceRegistry.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 List<jalviewSourceI> resolved = dassourceBrowser.sourceRegistry.resolveSourceNicknames(sources);
1257 if (resolved.size() == 0)
1259 resolved = dassourceBrowser.getSelectedSources();
1261 if (resolved.size() > 0)
1263 final List<jalviewSourceI> 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);