2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
3 * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, 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)
319 .getDatasetSequence().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 Iterator e = fr.featureColours.keySet().iterator();
718 float[] sortOrder = new float[fr.featureColours.size()];
719 String[] sortTypes = new String[fr.featureColours.size()];
723 sortTypes[i] = e.next().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 Iterator en = fr.featureGroups.keySet().iterator();
1138 gps = new String[fr.featureColours.size()];
1140 boolean valid = false;
1141 while (en.hasNext())
1143 String gp = (String) en.next();
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
1257 .resolveSourceNicknames(sources);
1258 if (resolved.size() == 0)
1260 resolved = dassourceBrowser.getSelectedSources();
1262 if (resolved.size() > 0)
1264 final List<jalviewSourceI> dassources = resolved;
1265 fetchDAS.setEnabled(false);
1266 // cancelDAS.setEnabled(true); doDasFetch does this.
1267 Runnable fetcher = new Runnable()
1272 doDasFeatureFetch(dassources, true, false);
1282 SwingUtilities.invokeLater(fetcher);
1287 public void saveDAS_actionPerformed(ActionEvent e)
1290 .saveProperties(jalview.bin.Cache.applicationProperties);
1293 public void complete()
1295 fetchDAS.setEnabled(true);
1296 cancelDAS.setEnabled(false);
1297 dassourceBrowser.setGuiEnabled(true);
1301 public void cancelDAS_actionPerformed(ActionEvent e)
1303 if (dasFeatureFetcher != null)
1305 dasFeatureFetcher.cancel();
1310 public void noDasSourceActive()
1313 JOptionPane.showInternalConfirmDialog(Desktop.desktop,
1314 "No das sources were selected.\n"
1315 + "Please select some sources and\n" + " try again.",
1316 "No Sources Selected", JOptionPane.DEFAULT_OPTION,
1317 JOptionPane.INFORMATION_MESSAGE);
1320 // ///////////////////////////////////////////////////////////////////////
1321 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
1322 // ///////////////////////////////////////////////////////////////////////
1323 class FeatureTableModel extends AbstractTableModel
1325 FeatureTableModel(Object[][] data)
1330 private String[] columnNames =
1331 { "Feature Type", "Colour", "Display" };
1333 private Object[][] data;
1335 public Object[][] getData()
1340 public void setData(Object[][] data)
1345 public int getColumnCount()
1347 return columnNames.length;
1350 public Object[] getRow(int row)
1355 public int getRowCount()
1360 public String getColumnName(int col)
1362 return columnNames[col];
1365 public Object getValueAt(int row, int col)
1367 return data[row][col];
1370 public Class getColumnClass(int c)
1372 return getValueAt(0, c).getClass();
1375 public boolean isCellEditable(int row, int col)
1377 return col == 0 ? false : true;
1380 public void setValueAt(Object value, int row, int col)
1382 data[row][col] = value;
1383 fireTableCellUpdated(row, col);
1384 updateFeatureRenderer(data);
1389 class ColorRenderer extends JLabel implements TableCellRenderer
1391 javax.swing.border.Border unselectedBorder = null;
1393 javax.swing.border.Border selectedBorder = null;
1395 final String baseTT = "Click to edit, right/apple click for menu.";
1397 public ColorRenderer()
1399 setOpaque(true); // MUST do this for background to show up.
1400 setHorizontalTextPosition(SwingConstants.CENTER);
1401 setVerticalTextPosition(SwingConstants.CENTER);
1404 public Component getTableCellRendererComponent(JTable table,
1405 Object color, boolean isSelected, boolean hasFocus, int row,
1408 // JLabel comp = new JLabel();
1412 // setBounds(getBounds());
1414 setToolTipText(baseTT);
1415 setBackground(table.getBackground());
1416 if (color instanceof GraduatedColor)
1418 Rectangle cr = table.getCellRect(row, column, false);
1419 FeatureSettings.renderGraduatedColor(this, (GraduatedColor) color,
1420 (int) cr.getWidth(), (int) cr.getHeight());
1427 newColor = (Color) color;
1429 setBackground(newColor);
1430 // comp.setToolTipText("RGB value: " + newColor.getRed() + ", "
1431 // + newColor.getGreen() + ", " + newColor.getBlue());
1435 if (selectedBorder == null)
1437 selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1438 table.getSelectionBackground());
1441 setBorder(selectedBorder);
1445 if (unselectedBorder == null)
1447 unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1448 table.getBackground());
1451 setBorder(unselectedBorder);
1459 * update comp using rendering settings from gcol
1464 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol)
1466 int w = comp.getWidth(), h = comp.getHeight();
1469 w = (int) comp.getPreferredSize().getWidth();
1470 h = (int) comp.getPreferredSize().getHeight();
1477 renderGraduatedColor(comp, gcol, w, h);
1480 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol,
1483 boolean thr = false;
1486 if (gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD)
1490 tt += "Thresholded (Above " + gcol.getThresh() + ") ";
1492 if (gcol.getThreshType() == AnnotationColourGradient.BELOW_THRESHOLD)
1496 tt += "Thresholded (Below " + gcol.getThresh() + ") ";
1498 if (gcol.isColourByLabel())
1500 tt = "Coloured by label text. " + tt;
1510 Color newColor = gcol.getMaxColor();
1511 comp.setBackground(newColor);
1512 // System.err.println("Width is " + w / 2);
1513 Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w, h, thr);
1514 comp.setIcon(ficon);
1515 // tt+="RGB value: Max (" + newColor.getRed() + ", "
1516 // + newColor.getGreen() + ", " + newColor.getBlue()
1517 // + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen()
1518 // + ", " + minCol.getBlue() + ")");
1520 comp.setHorizontalAlignment(SwingConstants.CENTER);
1522 if (tt.length() > 0)
1524 if (comp.getToolTipText() == null)
1526 comp.setToolTipText(tt);
1530 comp.setToolTipText(tt + " " + comp.getToolTipText());
1536 class FeatureIcon implements Icon
1538 GraduatedColor gcol;
1542 boolean midspace = false;
1544 int width = 50, height = 20;
1546 int s1, e1; // start and end of midpoint band for thresholded symbol
1548 Color mpcolour = Color.white;
1550 FeatureIcon(GraduatedColor gfc, Color bg, int w, int h, boolean mspace)
1569 public int getIconWidth()
1574 public int getIconHeight()
1579 public void paintIcon(Component c, Graphics g, int x, int y)
1582 if (gcol.isColourByLabel())
1585 g.fillRect(0, 0, width, height);
1586 // need an icon here.
1587 g.setColor(gcol.getMaxColor());
1589 g.setFont(new Font("Verdana", Font.PLAIN, 9));
1591 // g.setFont(g.getFont().deriveFont(
1592 // AffineTransform.getScaleInstance(
1593 // width/g.getFontMetrics().stringWidth("Label"),
1594 // height/g.getFontMetrics().getHeight())));
1596 g.drawString("Label", 0, 0);
1601 Color minCol = gcol.getMinColor();
1603 g.fillRect(0, 0, s1, height);
1606 g.setColor(Color.white);
1607 g.fillRect(s1, 0, e1 - s1, height);
1609 g.setColor(gcol.getMaxColor());
1610 g.fillRect(0, e1, width - e1, height);
1615 class ColorEditor extends AbstractCellEditor implements TableCellEditor,
1620 GraduatedColor currentGColor;
1622 FeatureColourChooser chooser;
1630 JColorChooser colorChooser;
1634 protected static final String EDIT = "edit";
1636 int selectedRow = 0;
1638 public ColorEditor(FeatureSettings me)
1641 // Set up the editor (from the table's point of view),
1642 // which is a button.
1643 // This button brings up the color chooser dialog,
1644 // which is the editor from the user's point of view.
1645 button = new JButton();
1646 button.setActionCommand(EDIT);
1647 button.addActionListener(this);
1648 button.setBorderPainted(false);
1649 // Set up the dialog that the button brings up.
1650 colorChooser = new JColorChooser();
1651 dialog = JColorChooser.createDialog(button, "Select new Colour", true, // modal
1652 colorChooser, this, // OK button handler
1653 null); // no CANCEL button handler
1657 * Handles events from the editor button and from the dialog's OK button.
1659 public void actionPerformed(ActionEvent e)
1662 if (EDIT.equals(e.getActionCommand()))
1664 // The user has clicked the cell, so
1665 // bring up the dialog.
1666 if (currentColor != null)
1668 // bring up simple color chooser
1669 button.setBackground(currentColor);
1670 colorChooser.setColor(currentColor);
1671 dialog.setVisible(true);
1675 // bring up graduated chooser.
1676 chooser = new FeatureColourChooser(me.fr, type);
1677 chooser.setRequestFocusEnabled(true);
1678 chooser.requestFocus();
1679 chooser.addActionListener(this);
1681 // Make the renderer reappear.
1682 fireEditingStopped();
1686 { // User pressed dialog's "OK" button.
1687 if (currentColor != null)
1689 currentColor = colorChooser.getColor();
1693 // class cast exceptions may be raised if the chooser created on a
1694 // non-graduated color
1695 currentGColor = (GraduatedColor) chooser.getLastColour();
1697 me.table.setValueAt(getCellEditorValue(), selectedRow, 1);
1698 fireEditingStopped();
1699 me.table.validate();
1703 // Implement the one CellEditor method that AbstractCellEditor doesn't.
1704 public Object getCellEditorValue()
1706 if (currentColor == null)
1708 return currentGColor;
1710 return currentColor;
1713 // Implement the one method defined by TableCellEditor.
1714 public Component getTableCellEditorComponent(JTable table, Object value,
1715 boolean isSelected, int row, int column)
1717 currentGColor = null;
1718 currentColor = null;
1719 this.selectedRow = row;
1720 type = me.table.getValueAt(row, 0).toString();
1721 button.setOpaque(true);
1722 button.setBackground(me.getBackground());
1723 if (value instanceof GraduatedColor)
1725 currentGColor = (GraduatedColor) value;
1726 JLabel btn = new JLabel();
1727 btn.setSize(button.getSize());
1728 FeatureSettings.renderGraduatedColor(btn, currentGColor);
1729 button.setBackground(btn.getBackground());
1730 button.setIcon(btn.getIcon());
1731 button.setText(btn.getText());
1736 button.setIcon(null);
1737 currentColor = (Color) value;
1738 button.setBackground(currentColor);