2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
3 * Copyright (C) 2014 The Jalview Authors
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/>.
17 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import java.util.List;
26 import java.awt.event.*;
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;
41 import jalview.util.MessageManager;
42 import jalview.ws.dbsources.das.api.jalviewSourceI;
44 public class FeatureSettings extends JPanel
46 DasSourceBrowser dassourceBrowser;
48 jalview.ws.DasSequenceFeatureFetcher dasFeatureFetcher;
50 JPanel settingsPane = new JPanel();
52 JPanel dasSettingsPane = new JPanel();
54 final FeatureRenderer fr;
56 public final AlignFrame af;
58 Object[][] originalData;
60 final JInternalFrame frame;
62 JScrollPane scrollPane = new JScrollPane();
68 JSlider transparency = new JSlider();
70 JPanel transPanel = new JPanel(new GridLayout(1, 2));
72 public FeatureSettings(AlignFrame af)
75 fr = af.getFeatureRenderer();
77 transparency.setMaximum(100 - (int) (fr.transparency * 100));
82 } catch (Exception ex)
88 table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));
89 table.setFont(new Font("Verdana", Font.PLAIN, 12));
90 table.setDefaultRenderer(Color.class, new ColorRenderer());
92 table.setDefaultEditor(Color.class, new ColorEditor(this));
94 table.setDefaultEditor(GraduatedColor.class, new ColorEditor(this));
95 table.setDefaultRenderer(GraduatedColor.class, new ColorRenderer());
96 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
98 table.addMouseListener(new MouseAdapter()
100 public void mousePressed(MouseEvent evt)
102 selectedRow = table.rowAtPoint(evt.getPoint());
103 if (javax.swing.SwingUtilities.isRightMouseButton(evt))
105 popupSort(selectedRow, (String) table.getValueAt(selectedRow, 0),
106 table.getValueAt(selectedRow, 1), fr.minmax, evt.getX(),
112 table.addMouseMotionListener(new MouseMotionAdapter()
114 public void mouseDragged(MouseEvent evt)
116 int newRow = table.rowAtPoint(evt.getPoint());
117 if (newRow != selectedRow && selectedRow != -1 && newRow != -1)
119 Object[] temp = new Object[3];
120 temp[0] = table.getValueAt(selectedRow, 0);
121 temp[1] = table.getValueAt(selectedRow, 1);
122 temp[2] = table.getValueAt(selectedRow, 2);
124 table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0);
125 table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1);
126 table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2);
128 table.setValueAt(temp[0], newRow, 0);
129 table.setValueAt(temp[1], newRow, 1);
130 table.setValueAt(temp[2], newRow, 2);
132 selectedRow = newRow;
137 scrollPane.setViewportView(table);
139 dassourceBrowser = new DasSourceBrowser(this);
140 dasSettingsPane.add(dassourceBrowser, BorderLayout.CENTER);
142 if (af.getViewport().featuresDisplayed == null
143 || fr.renderOrder == null)
145 fr.findAllFeatures(true); // display everything!
149 final PropertyChangeListener change;
150 final FeatureSettings fs = this;
151 fr.addPropertyChangeListener(change = new PropertyChangeListener()
153 public void propertyChange(PropertyChangeEvent evt)
155 if (!fs.resettingTable && !fs.handlingUpdate)
157 fs.handlingUpdate = true;
158 fs.resetTable(null); // new groups may be added with new seuqence
159 // feature types only
160 fs.handlingUpdate = false;
166 frame = new JInternalFrame();
167 frame.setContentPane(this);
168 if (new jalview.util.Platform().isAMac())
170 Desktop.addInternalFrame(frame, "Sequence Feature Settings", 475, 480);
174 Desktop.addInternalFrame(frame, "Sequence Feature Settings", 400, 450);
177 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
179 public void internalFrameClosed(
180 javax.swing.event.InternalFrameEvent evt)
182 fr.removePropertyChangeListener(change);
183 dassourceBrowser.fs = null;
186 frame.setLayer(JLayeredPane.PALETTE_LAYER);
189 protected void popupSort(final int selectedRow, final String type,
190 final Object typeCol, final Hashtable minmax, int x, int y)
192 JPopupMenu men = new JPopupMenu("Settings for " + type);
193 JMenuItem scr = new JMenuItem("Sort by Score");
195 final FeatureSettings me = this;
196 scr.addActionListener(new ActionListener()
199 public void actionPerformed(ActionEvent e)
201 me.sortByScore(new String[]
206 JMenuItem dens = new JMenuItem("Sort by Density");
207 dens.addActionListener(new ActionListener()
210 public void actionPerformed(ActionEvent e)
212 me.sortByDens(new String[]
220 final Object typeMinMax = minmax.get(type);
222 * final JCheckBoxMenuItem chb = new JCheckBoxMenuItem("Vary Height"); //
223 * this is broken at the moment and isn't that useful anyway!
224 * chb.setSelected(minmax.get(type) != null); chb.addActionListener(new
227 * public void actionPerformed(ActionEvent e) {
228 * chb.setState(chb.getState()); if (chb.getState()) { minmax.put(type,
229 * null); } else { minmax.put(type, typeMinMax); } }
235 if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null)
237 // if (table.getValueAt(row, column));
238 // graduated colourschemes for those where minmax exists for the
239 // positional features
240 final JCheckBoxMenuItem mxcol = new JCheckBoxMenuItem(
242 mxcol.setSelected(!(typeCol instanceof Color));
244 mxcol.addActionListener(new ActionListener()
246 JColorChooser colorChooser;
248 public void actionPerformed(ActionEvent e)
250 if (e.getSource() == mxcol)
252 if (typeCol instanceof Color)
254 FeatureColourChooser fc = new FeatureColourChooser(me.fr,
256 fc.addActionListener(this);
260 // bring up simple color chooser
261 colorChooser = new JColorChooser();
262 JDialog dialog = JColorChooser.createDialog(me,
263 "Select new Colour", true, // modal
264 colorChooser, this, // OK button handler
265 null); // no CANCEL button handler
266 colorChooser.setColor(((GraduatedColor) typeCol)
268 dialog.setVisible(true);
273 if (e.getSource() instanceof FeatureColourChooser)
275 FeatureColourChooser fc = (FeatureColourChooser) e
277 table.setValueAt(fc.getLastColour(), selectedRow, 1);
282 // probably the color chooser!
283 table.setValueAt(colorChooser.getColor(), selectedRow, 1);
285 me.updateFeatureRenderer(
286 ((FeatureTableModel) table.getModel()).getData(),
295 men.show(table, x, y);
299 * true when Feature Settings are updating from feature renderer
301 private boolean handlingUpdate = false;
304 * contains a float[3] for each feature type string. created by setTableData
306 Hashtable typeWidth = null;
308 synchronized public void setTableData()
310 if (fr.featureGroups == null)
312 fr.featureGroups = new Hashtable();
314 Vector allFeatures = new Vector();
315 Vector allGroups = new Vector();
316 SequenceFeature[] tmpfeatures;
318 for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
320 if (af.getViewport().getAlignment().getSequenceAt(i)
321 .getDatasetSequence().getSequenceFeatures() == null)
326 tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
327 .getDatasetSequence().getSequenceFeatures();
330 while (index < tmpfeatures.length)
332 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
338 if (tmpfeatures[index].getFeatureGroup() != null)
340 group = tmpfeatures[index].featureGroup;
341 if (!allGroups.contains(group))
343 allGroups.addElement(group);
346 checkGroupState(group);
351 if (!allFeatures.contains(tmpfeatures[index].getType()))
353 allFeatures.addElement(tmpfeatures[index].getType());
367 * @return true if group has been seen before and is already added to set.
369 private boolean checkGroupState(String group)
372 if (fr.featureGroups.containsKey(group))
374 visible = ((Boolean) fr.featureGroups.get(group)).booleanValue();
378 visible = true; // new group is always made visible
381 if (groupPanel == null)
383 groupPanel = new JPanel();
386 boolean alreadyAdded = false;
387 for (int g = 0; g < groupPanel.getComponentCount(); g++)
389 if (((JCheckBox) groupPanel.getComponent(g)).getText().equals(group))
392 ((JCheckBox) groupPanel.getComponent(g)).setSelected(visible);
403 fr.featureGroups.put(group, new Boolean(visible));
404 final String grp = group;
405 final JCheckBox check = new JCheckBox(group, visible);
406 check.setFont(new Font("Serif", Font.BOLD, 12));
407 check.addItemListener(new ItemListener()
409 public void itemStateChanged(ItemEvent evt)
411 fr.featureGroups.put(check.getText(),
412 new Boolean(check.isSelected()));
413 af.alignPanel.seqPanel.seqCanvas.repaint();
414 if (af.alignPanel.overviewPanel != null)
416 af.alignPanel.overviewPanel.updateOverviewImage();
419 resetTable(new String[]
423 groupPanel.add(check);
427 boolean resettingTable = false;
429 synchronized void resetTable(String[] groupChanged)
431 if (resettingTable == true)
435 resettingTable = true;
436 typeWidth = new Hashtable();
437 // TODO: change avWidth calculation to 'per-sequence' average and use long
439 float[] avWidth = null;
440 SequenceFeature[] tmpfeatures;
441 String group = null, type;
442 Vector visibleChecks = new Vector();
444 // Find out which features should be visible depending on which groups
445 // are selected / deselected
446 // and recompute average width ordering
447 for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
450 tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
451 .getDatasetSequence().getSequenceFeatures();
452 if (tmpfeatures == null)
458 while (index < tmpfeatures.length)
460 group = tmpfeatures[index].featureGroup;
462 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
468 if (group == null || fr.featureGroups.get(group) == null
469 || ((Boolean) fr.featureGroups.get(group)).booleanValue())
472 checkGroupState(group);
473 type = tmpfeatures[index].getType();
474 if (!visibleChecks.contains(type))
476 visibleChecks.addElement(type);
479 if (!typeWidth.containsKey(tmpfeatures[index].getType()))
481 typeWidth.put(tmpfeatures[index].getType(),
482 avWidth = new float[3]);
486 avWidth = (float[]) typeWidth.get(tmpfeatures[index].getType());
489 if (tmpfeatures[index].getBegin() > tmpfeatures[index].getEnd())
491 avWidth[1] += 1 + tmpfeatures[index].getBegin()
492 - tmpfeatures[index].getEnd();
496 avWidth[1] += 1 + tmpfeatures[index].getEnd()
497 - tmpfeatures[index].getBegin();
503 int fSize = visibleChecks.size();
504 Object[][] data = new Object[fSize][3];
507 if (fr.renderOrder != null)
510 fr.findAllFeatures(groupChanged != null); // prod to update
511 // colourschemes. but don't
513 // First add the checks in the previous render order,
514 // in case the window has been closed and reopened
515 for (int ro = fr.renderOrder.length - 1; ro > -1; ro--)
517 type = fr.renderOrder[ro];
519 if (!visibleChecks.contains(type))
524 data[dataIndex][0] = type;
525 data[dataIndex][1] = fr.getFeatureStyle(type);
526 data[dataIndex][2] = new Boolean(
527 af.getViewport().featuresDisplayed.containsKey(type));
529 visibleChecks.removeElement(type);
533 fSize = visibleChecks.size();
534 for (int i = 0; i < fSize; i++)
536 // These must be extra features belonging to the group
537 // which was just selected
538 type = visibleChecks.elementAt(i).toString();
539 data[dataIndex][0] = type;
541 data[dataIndex][1] = fr.getFeatureStyle(type);
542 if (data[dataIndex][1] == null)
544 // "Colour has been updated in another view!!"
545 fr.renderOrder = null;
549 data[dataIndex][2] = new Boolean(true);
553 if (originalData == null)
555 originalData = new Object[data.length][3];
556 for (int i = 0; i < data.length; i++)
558 System.arraycopy(data[i], 0, originalData[i], 0, 3);
562 table.setModel(new FeatureTableModel(data));
563 table.getColumnModel().getColumn(0).setPreferredWidth(200);
565 if (groupPanel != null)
567 groupPanel.setLayout(new GridLayout(fr.featureGroups.size() / 4 + 1,
570 groupPanel.validate();
571 bigPanel.add(groupPanel, BorderLayout.NORTH);
574 updateFeatureRenderer(data, groupChanged != null);
575 resettingTable = false;
579 * reorder data based on the featureRenderers global priority list.
583 private void ensureOrder(Object[][] data)
585 boolean sort = false;
586 float[] order = new float[data.length];
587 for (int i = 0; i < order.length; i++)
589 order[i] = fr.getOrder(data[i][0].toString());
591 order[i] = fr.setOrder(data[i][0].toString(), i / order.length);
593 sort = sort || order[i - 1] > order[i];
596 jalview.util.QuickSort.sort(order, data);
601 JalviewFileChooser chooser = new JalviewFileChooser(
602 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
603 { "fc" }, new String[]
604 { "Sequence Feature Colours" }, "Sequence Feature Colours");
605 chooser.setFileView(new jalview.io.JalviewFileView());
606 chooser.setDialogTitle("Load Feature Colours");
607 chooser.setToolTipText("Load");
609 int value = chooser.showOpenDialog(this);
611 if (value == JalviewFileChooser.APPROVE_OPTION)
613 File file = chooser.getSelectedFile();
617 InputStreamReader in = new InputStreamReader(new FileInputStream(
620 jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
621 jucs = (jalview.schemabinding.version2.JalviewUserColours) jucs
624 for (int i = jucs.getColourCount() - 1; i >= 0; i--)
627 jalview.schemabinding.version2.Colour newcol = jucs.getColour(i);
630 Color mincol = null, maxcol = null;
633 mincol = new Color(Integer.parseInt(newcol.getMinRGB(), 16));
634 maxcol = new Color(Integer.parseInt(newcol.getRGB(), 16));
636 } catch (Exception e)
638 Cache.log.warn("Couldn't parse out graduated feature color.",
641 GraduatedColor gcol = new GraduatedColor(mincol, maxcol,
642 newcol.getMin(), newcol.getMax());
643 if (newcol.hasAutoScale())
645 gcol.setAutoScaled(newcol.getAutoScale());
647 if (newcol.hasColourByLabel())
649 gcol.setColourByLabel(newcol.getColourByLabel());
651 if (newcol.hasThreshold())
653 gcol.setThresh(newcol.getThreshold());
654 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD); // default
656 if (newcol.getThreshType().length() > 0)
658 String ttyp = newcol.getThreshType();
659 if (ttyp.equalsIgnoreCase("NONE"))
661 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD);
663 if (ttyp.equalsIgnoreCase("ABOVE"))
665 gcol.setThreshType(AnnotationColourGradient.ABOVE_THRESHOLD);
667 if (ttyp.equalsIgnoreCase("BELOW"))
669 gcol.setThreshType(AnnotationColourGradient.BELOW_THRESHOLD);
672 fr.setColour(name = newcol.getName(), gcol);
676 fr.setColour(name = jucs.getColour(i).getName(), new Color(
677 Integer.parseInt(jucs.getColour(i).getRGB(), 16)));
679 fr.setOrder(name, (i == 0) ? 0 : i / jucs.getColourCount());
684 Object[][] data = ((FeatureTableModel) table.getModel())
687 updateFeatureRenderer(data, false);
690 } catch (Exception ex)
692 System.out.println("Error loading User Colour File\n" + ex);
699 JalviewFileChooser chooser = new JalviewFileChooser(
700 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
701 { "fc" }, new String[]
702 { "Sequence Feature Colours" }, "Sequence Feature Colours");
703 chooser.setFileView(new jalview.io.JalviewFileView());
704 chooser.setDialogTitle("Save Feature Colour Scheme");
705 chooser.setToolTipText("Save");
707 int value = chooser.showSaveDialog(this);
709 if (value == JalviewFileChooser.APPROVE_OPTION)
711 String choice = chooser.getSelectedFile().getPath();
712 jalview.schemabinding.version2.JalviewUserColours ucs = new jalview.schemabinding.version2.JalviewUserColours();
713 ucs.setSchemeName("Sequence Features");
716 PrintWriter out = new PrintWriter(new OutputStreamWriter(
717 new FileOutputStream(choice), "UTF-8"));
719 Iterator e = fr.featureColours.keySet().iterator();
720 float[] sortOrder = new float[fr.featureColours.size()];
721 String[] sortTypes = new String[fr.featureColours.size()];
725 sortTypes[i] = e.next().toString();
726 sortOrder[i] = fr.getOrder(sortTypes[i]);
729 jalview.util.QuickSort.sort(sortOrder, sortTypes);
733 for (i = 0; i < sortTypes.length; i++)
735 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
736 col.setName(sortTypes[i]);
737 col.setRGB(jalview.util.Format.getHexString(fr.getColour(col
739 fcol = fr.getFeatureStyle(sortTypes[i]);
740 if (fcol instanceof GraduatedColor)
742 gcol = (GraduatedColor) fcol;
743 col.setMin(gcol.getMin());
744 col.setMax(gcol.getMax());
745 col.setMinRGB(jalview.util.Format.getHexString(gcol
747 col.setAutoScale(gcol.isAutoScale());
748 col.setThreshold(gcol.getThresh());
749 col.setColourByLabel(gcol.isColourByLabel());
750 switch (gcol.getThreshType())
752 case AnnotationColourGradient.NO_THRESHOLD:
753 col.setThreshType("NONE");
755 case AnnotationColourGradient.ABOVE_THRESHOLD:
756 col.setThreshType("ABOVE");
758 case AnnotationColourGradient.BELOW_THRESHOLD:
759 col.setThreshType("BELOW");
767 } catch (Exception ex)
769 ex.printStackTrace();
774 public void invertSelection()
776 for (int i = 0; i < table.getRowCount(); i++)
778 Boolean value = (Boolean) table.getValueAt(i, 2);
780 table.setValueAt(new Boolean(!value.booleanValue()), i, 2);
784 public void orderByAvWidth()
786 if (table == null || table.getModel() == null)
788 Object[][] data = ((FeatureTableModel) table.getModel()).getData();
789 float[] width = new float[data.length];
793 for (int i = 0; i < data.length; i++)
795 awidth = (float[]) typeWidth.get(data[i][0]);
798 width[i] = awidth[1] / awidth[0];// *awidth[0]*awidth[2]; - better
799 // weight - but have to make per
800 // sequence, too (awidth[2])
801 // if (width[i]==1) // hack to distinguish single width sequences.
811 boolean sort = false;
812 for (int i = 0; i < width.length; i++)
814 // awidth = (float[]) typeWidth.get(data[i][0]);
817 width[i] = fr.getOrder(data[i][0].toString());
820 width[i] = fr.setOrder(data[i][0].toString(), i / data.length);
825 width[i] /= max; // normalize
826 fr.setOrder(data[i][0].toString(), width[i]); // store for later
829 sort = sort || width[i - 1] > width[i];
832 jalview.util.QuickSort.sort(width, data);
833 // update global priority order
835 updateFeatureRenderer(data, false);
843 frame.setClosed(true);
844 } catch (Exception exe)
850 public void updateFeatureRenderer(Object[][] data)
852 updateFeatureRenderer(data, true);
855 private void updateFeatureRenderer(Object[][] data, boolean visibleNew)
857 fr.setFeaturePriority(data, visibleNew);
858 af.alignPanel.paintAlignment(true);
861 int selectedRow = -1;
863 JTabbedPane tabbedPane = new JTabbedPane();
865 BorderLayout borderLayout1 = new BorderLayout();
867 BorderLayout borderLayout2 = new BorderLayout();
869 BorderLayout borderLayout3 = new BorderLayout();
871 JPanel bigPanel = new JPanel();
873 BorderLayout borderLayout4 = new BorderLayout();
875 JButton invert = new JButton();
877 JPanel buttonPanel = new JPanel();
879 JButton cancel = new JButton();
881 JButton ok = new JButton();
883 JButton loadColours = new JButton();
885 JButton saveColours = new JButton();
887 JPanel dasButtonPanel = new JPanel();
889 JButton fetchDAS = new JButton();
891 JButton saveDAS = new JButton();
893 JButton cancelDAS = new JButton();
895 JButton optimizeOrder = new JButton();
897 JButton sortByScore = new JButton();
899 JButton sortByDens = new JButton();
901 JPanel transbuttons = new JPanel(new GridLayout(4, 1));
903 private void jbInit() throws Exception
905 this.setLayout(borderLayout1);
906 settingsPane.setLayout(borderLayout2);
907 dasSettingsPane.setLayout(borderLayout3);
908 bigPanel.setLayout(borderLayout4);
909 invert.setFont(JvSwingUtils.getLabelFont());
910 invert.setText(MessageManager.getString("label.invert_selection"));
911 invert.addActionListener(new ActionListener()
913 public void actionPerformed(ActionEvent e)
918 optimizeOrder.setFont(JvSwingUtils.getLabelFont());
919 optimizeOrder.setText(MessageManager.getString("label.optimise_order"));
920 optimizeOrder.addActionListener(new ActionListener()
922 public void actionPerformed(ActionEvent e)
927 sortByScore.setFont(JvSwingUtils.getLabelFont());
928 sortByScore.setText(MessageManager.getString("label.seq_sort_by_score"));
929 sortByScore.addActionListener(new ActionListener()
931 public void actionPerformed(ActionEvent e)
936 sortByDens.setFont(JvSwingUtils.getLabelFont());
937 sortByDens.setText("Seq Sort by density");
938 sortByDens.addActionListener(new ActionListener()
940 public void actionPerformed(ActionEvent e)
945 cancel.setFont(JvSwingUtils.getLabelFont());
946 cancel.setText(MessageManager.getString("action.cancel"));
947 cancel.addActionListener(new ActionListener()
949 public void actionPerformed(ActionEvent e)
951 updateFeatureRenderer(originalData);
955 ok.setFont(JvSwingUtils.getLabelFont());
956 ok.setText(MessageManager.getString("action.ok"));
957 ok.addActionListener(new ActionListener()
959 public void actionPerformed(ActionEvent e)
964 loadColours.setFont(JvSwingUtils.getLabelFont());
965 loadColours.setText(MessageManager.getString("label.load_colours"));
966 loadColours.addActionListener(new ActionListener()
968 public void actionPerformed(ActionEvent e)
973 saveColours.setFont(JvSwingUtils.getLabelFont());
974 saveColours.setText(MessageManager.getString("label.save_colours"));
975 saveColours.addActionListener(new ActionListener()
977 public void actionPerformed(ActionEvent e)
982 transparency.addChangeListener(new ChangeListener()
984 public void stateChanged(ChangeEvent evt)
986 fr.setTransparency((float) (100 - transparency.getValue()) / 100f);
987 af.alignPanel.paintAlignment(true);
991 transparency.setMaximum(70);
992 fetchDAS.setText(MessageManager.getString("label.fetch_das_features"));
993 fetchDAS.addActionListener(new ActionListener()
995 public void actionPerformed(ActionEvent e)
997 fetchDAS_actionPerformed(e);
1000 saveDAS.setText(MessageManager.getString("action.save_as_default"));
1001 saveDAS.addActionListener(new ActionListener()
1003 public void actionPerformed(ActionEvent e)
1005 saveDAS_actionPerformed(e);
1008 dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
1009 dasSettingsPane.setBorder(null);
1010 cancelDAS.setEnabled(false);
1011 cancelDAS.setText(MessageManager.getString("action.cancel_fetch"));
1012 cancelDAS.addActionListener(new ActionListener()
1014 public void actionPerformed(ActionEvent e)
1016 cancelDAS_actionPerformed(e);
1019 this.add(tabbedPane, java.awt.BorderLayout.CENTER);
1020 tabbedPane.addTab("Feature Settings", settingsPane);
1021 tabbedPane.addTab("DAS Settings", dasSettingsPane);
1022 bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
1023 transbuttons.add(optimizeOrder);
1024 transbuttons.add(invert);
1025 transbuttons.add(sortByScore);
1026 transbuttons.add(sortByDens);
1027 transPanel.add(transparency);
1028 transPanel.add(transbuttons);
1029 buttonPanel.add(ok);
1030 buttonPanel.add(cancel);
1031 buttonPanel.add(loadColours);
1032 buttonPanel.add(saveColours);
1033 bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
1034 dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
1035 dasButtonPanel.add(fetchDAS);
1036 dasButtonPanel.add(cancelDAS);
1037 dasButtonPanel.add(saveDAS);
1038 settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);
1039 settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
1042 protected void sortByDens(String[] typ)
1044 sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY);
1047 protected void sortBy(String[] typ, String methodText, final String method)
1051 typ = getDisplayedFeatureTypes();
1053 String gps[] = null;
1054 gps = getDisplayedFeatureGroups();
1057 ArrayList types = new ArrayList();
1058 for (int i = 0; i < typ.length; i++)
1064 typ = new String[types.size()];
1070 ArrayList grps = new ArrayList();
1072 for (int i = 0; i < gps.length; i++)
1079 gps = new String[grps.size()];
1082 AlignmentPanel alignPanel = af.alignPanel;
1083 AlignmentI al = alignPanel.av.getAlignment();
1086 SequenceGroup sg = alignPanel.av.getSelectionGroup();
1089 start = sg.getStartRes();
1090 stop = sg.getEndRes();
1095 stop = al.getWidth();
1097 SequenceI[] oldOrder = al.getSequencesArray();
1098 AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
1099 af.addHistoryItem(new OrderCommand(methodText, oldOrder, alignPanel.av
1101 alignPanel.paintAlignment(true);
1105 protected void sortByScore(String[] typ)
1107 sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE);
1110 private String[] getDisplayedFeatureTypes()
1112 String[] typ = null;
1115 synchronized (fr.renderOrder)
1117 typ = new String[fr.renderOrder.length];
1118 System.arraycopy(fr.renderOrder, 0, typ, 0, typ.length);
1119 for (int i = 0; i < typ.length; i++)
1121 if (af.viewport.featuresDisplayed.get(typ[i]) == null)
1131 private String[] getDisplayedFeatureGroups()
1133 String[] gps = null;
1137 if (fr.featureGroups != null)
1139 Iterator en = fr.featureGroups.keySet().iterator();
1140 gps = new String[fr.featureColours.size()];
1142 boolean valid = false;
1143 while (en.hasNext())
1145 String gp = (String) en.next();
1146 Boolean on = (Boolean) fr.featureGroups.get(gp);
1147 if (on != null && on.booleanValue())
1153 while (g < gps.length)
1166 public void fetchDAS_actionPerformed(ActionEvent e)
1168 fetchDAS.setEnabled(false);
1169 cancelDAS.setEnabled(true);
1170 dassourceBrowser.setGuiEnabled(false);
1171 Vector selectedSources = dassourceBrowser.getSelectedSources();
1172 doDasFeatureFetch(selectedSources, true, true);
1176 * get the features from selectedSources for all or the current selection
1178 * @param selectedSources
1179 * @param checkDbRefs
1180 * @param promptFetchDbRefs
1182 private void doDasFeatureFetch(List<jalviewSourceI> selectedSources,
1183 boolean checkDbRefs, boolean promptFetchDbRefs)
1185 SequenceI[] dataset, seqs;
1187 AlignViewport vp = af.getViewport();
1188 if (vp.getSelectionGroup() != null
1189 && vp.getSelectionGroup().getSize() > 0)
1191 iSize = vp.getSelectionGroup().getSize();
1192 dataset = new SequenceI[iSize];
1193 seqs = vp.getSelectionGroup().getSequencesInOrder(vp.getAlignment());
1197 iSize = vp.getAlignment().getHeight();
1198 seqs = vp.getAlignment().getSequencesArray();
1201 dataset = new SequenceI[iSize];
1202 for (int i = 0; i < iSize; i++)
1204 dataset[i] = seqs[i].getDatasetSequence();
1207 cancelDAS.setEnabled(true);
1208 dasFeatureFetcher = new jalview.ws.DasSequenceFeatureFetcher(dataset,
1209 this, selectedSources, checkDbRefs, promptFetchDbRefs);
1210 af.getViewport().setShowSequenceFeatures(true);
1211 af.showSeqFeatures.setSelected(true);
1215 * blocking call to initialise the das source browser
1217 public void initDasSources()
1219 dassourceBrowser.initDasSources();
1223 * examine the current list of das sources and return any matching the given
1224 * nicknames in sources
1227 * Vector of Strings to resolve to DAS source nicknames.
1228 * @return sources that are present in source list.
1230 public List<jalviewSourceI> resolveSourceNicknames(Vector sources)
1232 return dassourceBrowser.sourceRegistry.resolveSourceNicknames(sources);
1236 * get currently selected das sources. ensure you have called initDasSources
1237 * before calling this.
1239 * @return vector of selected das source nicknames
1241 public Vector getSelectedSources()
1243 return dassourceBrowser.getSelectedSources();
1247 * properly initialise DAS fetcher and then initiate a new thread to fetch
1248 * features from the named sources (rather than any turned on by default)
1252 * if true then runs in same thread, otherwise passes to the Swing
1255 public void fetchDasFeatures(Vector sources, boolean block)
1258 List<jalviewSourceI> resolved = dassourceBrowser.sourceRegistry
1259 .resolveSourceNicknames(sources);
1260 if (resolved.size() == 0)
1262 resolved = dassourceBrowser.getSelectedSources();
1264 if (resolved.size() > 0)
1266 final List<jalviewSourceI> dassources = resolved;
1267 fetchDAS.setEnabled(false);
1268 // cancelDAS.setEnabled(true); doDasFetch does this.
1269 Runnable fetcher = new Runnable()
1274 doDasFeatureFetch(dassources, true, false);
1284 SwingUtilities.invokeLater(fetcher);
1289 public void saveDAS_actionPerformed(ActionEvent e)
1292 .saveProperties(jalview.bin.Cache.applicationProperties);
1295 public void complete()
1297 fetchDAS.setEnabled(true);
1298 cancelDAS.setEnabled(false);
1299 dassourceBrowser.setGuiEnabled(true);
1303 public void cancelDAS_actionPerformed(ActionEvent e)
1305 if (dasFeatureFetcher != null)
1307 dasFeatureFetcher.cancel();
1312 public void noDasSourceActive()
1315 JOptionPane.showInternalConfirmDialog(Desktop.desktop,
1316 MessageManager.getString("label.no_das_sources_selected_warn"),
1317 MessageManager.getString("label.no_das_sources_selected_title"), JOptionPane.DEFAULT_OPTION,
1318 JOptionPane.INFORMATION_MESSAGE);
1321 // ///////////////////////////////////////////////////////////////////////
1322 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
1323 // ///////////////////////////////////////////////////////////////////////
1324 class FeatureTableModel extends AbstractTableModel
1326 FeatureTableModel(Object[][] data)
1331 private String[] columnNames =
1332 { "Feature Type", "Colour", "Display" };
1334 private Object[][] data;
1336 public Object[][] getData()
1341 public void setData(Object[][] data)
1346 public int getColumnCount()
1348 return columnNames.length;
1351 public Object[] getRow(int row)
1356 public int getRowCount()
1361 public String getColumnName(int col)
1363 return columnNames[col];
1366 public Object getValueAt(int row, int col)
1368 return data[row][col];
1371 public Class getColumnClass(int c)
1373 return getValueAt(0, c).getClass();
1376 public boolean isCellEditable(int row, int col)
1378 return col == 0 ? false : true;
1381 public void setValueAt(Object value, int row, int col)
1383 data[row][col] = value;
1384 fireTableCellUpdated(row, col);
1385 updateFeatureRenderer(data);
1390 class ColorRenderer extends JLabel implements TableCellRenderer
1392 javax.swing.border.Border unselectedBorder = null;
1394 javax.swing.border.Border selectedBorder = null;
1396 final String baseTT = "Click to edit, right/apple click for menu.";
1398 public ColorRenderer()
1400 setOpaque(true); // MUST do this for background to show up.
1401 setHorizontalTextPosition(SwingConstants.CENTER);
1402 setVerticalTextPosition(SwingConstants.CENTER);
1405 public Component getTableCellRendererComponent(JTable table,
1406 Object color, boolean isSelected, boolean hasFocus, int row,
1409 // JLabel comp = new JLabel();
1413 // setBounds(getBounds());
1415 setToolTipText(baseTT);
1416 setBackground(table.getBackground());
1417 if (color instanceof GraduatedColor)
1419 Rectangle cr = table.getCellRect(row, column, false);
1420 FeatureSettings.renderGraduatedColor(this, (GraduatedColor) color,
1421 (int) cr.getWidth(), (int) cr.getHeight());
1428 newColor = (Color) color;
1430 setBackground(newColor);
1431 // comp.setToolTipText("RGB value: " + newColor.getRed() + ", "
1432 // + newColor.getGreen() + ", " + newColor.getBlue());
1436 if (selectedBorder == null)
1438 selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1439 table.getSelectionBackground());
1442 setBorder(selectedBorder);
1446 if (unselectedBorder == null)
1448 unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1449 table.getBackground());
1452 setBorder(unselectedBorder);
1460 * update comp using rendering settings from gcol
1465 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol)
1467 int w = comp.getWidth(), h = comp.getHeight();
1470 w = (int) comp.getPreferredSize().getWidth();
1471 h = (int) comp.getPreferredSize().getHeight();
1478 renderGraduatedColor(comp, gcol, w, h);
1481 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol,
1484 boolean thr = false;
1487 if (gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD)
1491 tt += "Thresholded (Above " + gcol.getThresh() + ") ";
1493 if (gcol.getThreshType() == AnnotationColourGradient.BELOW_THRESHOLD)
1497 tt += "Thresholded (Below " + gcol.getThresh() + ") ";
1499 if (gcol.isColourByLabel())
1501 tt = "Coloured by label text. " + tt;
1511 Color newColor = gcol.getMaxColor();
1512 comp.setBackground(newColor);
1513 // System.err.println("Width is " + w / 2);
1514 Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w, h, thr);
1515 comp.setIcon(ficon);
1516 // tt+="RGB value: Max (" + newColor.getRed() + ", "
1517 // + newColor.getGreen() + ", " + newColor.getBlue()
1518 // + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen()
1519 // + ", " + minCol.getBlue() + ")");
1521 comp.setHorizontalAlignment(SwingConstants.CENTER);
1523 if (tt.length() > 0)
1525 if (comp.getToolTipText() == null)
1527 comp.setToolTipText(tt);
1531 comp.setToolTipText(tt + " " + comp.getToolTipText());
1537 class FeatureIcon implements Icon
1539 GraduatedColor gcol;
1543 boolean midspace = false;
1545 int width = 50, height = 20;
1547 int s1, e1; // start and end of midpoint band for thresholded symbol
1549 Color mpcolour = Color.white;
1551 FeatureIcon(GraduatedColor gfc, Color bg, int w, int h, boolean mspace)
1570 public int getIconWidth()
1575 public int getIconHeight()
1580 public void paintIcon(Component c, Graphics g, int x, int y)
1583 if (gcol.isColourByLabel())
1586 g.fillRect(0, 0, width, height);
1587 // need an icon here.
1588 g.setColor(gcol.getMaxColor());
1590 g.setFont(new Font("Verdana", Font.PLAIN, 9));
1592 // g.setFont(g.getFont().deriveFont(
1593 // AffineTransform.getScaleInstance(
1594 // width/g.getFontMetrics().stringWidth("Label"),
1595 // height/g.getFontMetrics().getHeight())));
1597 g.drawString(MessageManager.getString("label.label"), 0, 0);
1602 Color minCol = gcol.getMinColor();
1604 g.fillRect(0, 0, s1, height);
1607 g.setColor(Color.white);
1608 g.fillRect(s1, 0, e1 - s1, height);
1610 g.setColor(gcol.getMaxColor());
1611 g.fillRect(0, e1, width - e1, height);
1616 class ColorEditor extends AbstractCellEditor implements TableCellEditor,
1621 GraduatedColor currentGColor;
1623 FeatureColourChooser chooser;
1631 JColorChooser colorChooser;
1635 protected static final String EDIT = "edit";
1637 int selectedRow = 0;
1639 public ColorEditor(FeatureSettings me)
1642 // Set up the editor (from the table's point of view),
1643 // which is a button.
1644 // This button brings up the color chooser dialog,
1645 // which is the editor from the user's point of view.
1646 button = new JButton();
1647 button.setActionCommand(EDIT);
1648 button.addActionListener(this);
1649 button.setBorderPainted(false);
1650 // Set up the dialog that the button brings up.
1651 colorChooser = new JColorChooser();
1652 dialog = JColorChooser.createDialog(button, "Select new Colour", true, // modal
1653 colorChooser, this, // OK button handler
1654 null); // no CANCEL button handler
1658 * Handles events from the editor button and from the dialog's OK button.
1660 public void actionPerformed(ActionEvent e)
1663 if (EDIT.equals(e.getActionCommand()))
1665 // The user has clicked the cell, so
1666 // bring up the dialog.
1667 if (currentColor != null)
1669 // bring up simple color chooser
1670 button.setBackground(currentColor);
1671 colorChooser.setColor(currentColor);
1672 dialog.setVisible(true);
1676 // bring up graduated chooser.
1677 chooser = new FeatureColourChooser(me.fr, type);
1678 chooser.setRequestFocusEnabled(true);
1679 chooser.requestFocus();
1680 chooser.addActionListener(this);
1682 // Make the renderer reappear.
1683 fireEditingStopped();
1687 { // User pressed dialog's "OK" button.
1688 if (currentColor != null)
1690 currentColor = colorChooser.getColor();
1694 // class cast exceptions may be raised if the chooser created on a
1695 // non-graduated color
1696 currentGColor = (GraduatedColor) chooser.getLastColour();
1698 me.table.setValueAt(getCellEditorValue(), selectedRow, 1);
1699 fireEditingStopped();
1700 me.table.validate();
1704 // Implement the one CellEditor method that AbstractCellEditor doesn't.
1705 public Object getCellEditorValue()
1707 if (currentColor == null)
1709 return currentGColor;
1711 return currentColor;
1714 // Implement the one method defined by TableCellEditor.
1715 public Component getTableCellEditorComponent(JTable table, Object value,
1716 boolean isSelected, int row, int column)
1718 currentGColor = null;
1719 currentColor = null;
1720 this.selectedRow = row;
1721 type = me.table.getValueAt(row, 0).toString();
1722 button.setOpaque(true);
1723 button.setBackground(me.getBackground());
1724 if (value instanceof GraduatedColor)
1726 currentGColor = (GraduatedColor) value;
1727 JLabel btn = new JLabel();
1728 btn.setSize(button.getSize());
1729 FeatureSettings.renderGraduatedColor(btn, currentGColor);
1730 button.setBackground(btn.getBackground());
1731 button.setIcon(btn.getIcon());
1732 button.setText(btn.getText());
1737 button.setIcon(null);
1738 currentColor = (Color) value;
1739 button.setBackground(currentColor);