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;
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.util.MessageManager;
41 import jalview.ws.dbsources.das.api.jalviewSourceI;
43 public class FeatureSettings extends JPanel
45 DasSourceBrowser dassourceBrowser;
47 jalview.ws.DasSequenceFeatureFetcher dasFeatureFetcher;
49 JPanel settingsPane = new JPanel();
51 JPanel dasSettingsPane = new JPanel();
53 final FeatureRenderer fr;
55 public final AlignFrame af;
57 Object[][] originalData;
59 final JInternalFrame frame;
61 JScrollPane scrollPane = new JScrollPane();
67 JSlider transparency = new JSlider();
69 JPanel transPanel = new JPanel(new GridLayout(1, 2));
71 public FeatureSettings(AlignFrame af)
74 fr = af.getFeatureRenderer();
76 transparency.setMaximum(100 - (int) (fr.transparency * 100));
81 } catch (Exception ex)
87 table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));
88 table.setFont(new Font("Verdana", Font.PLAIN, 12));
89 table.setDefaultRenderer(Color.class, new ColorRenderer());
91 table.setDefaultEditor(Color.class, new ColorEditor(this));
93 table.setDefaultEditor(GraduatedColor.class, new ColorEditor(this));
94 table.setDefaultRenderer(GraduatedColor.class, new ColorRenderer());
95 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
97 table.addMouseListener(new MouseAdapter()
99 public void mousePressed(MouseEvent evt)
101 selectedRow = table.rowAtPoint(evt.getPoint());
102 if (evt.isPopupTrigger())
104 popupSort(selectedRow, (String) table.getValueAt(selectedRow, 0),
105 table.getValueAt(selectedRow, 1), fr.minmax, evt.getX(),
111 table.addMouseMotionListener(new MouseMotionAdapter()
113 public void mouseDragged(MouseEvent evt)
115 int newRow = table.rowAtPoint(evt.getPoint());
116 if (newRow != selectedRow && selectedRow != -1 && newRow != -1)
118 Object[] temp = new Object[3];
119 temp[0] = table.getValueAt(selectedRow, 0);
120 temp[1] = table.getValueAt(selectedRow, 1);
121 temp[2] = table.getValueAt(selectedRow, 2);
123 table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0);
124 table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1);
125 table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2);
127 table.setValueAt(temp[0], newRow, 0);
128 table.setValueAt(temp[1], newRow, 1);
129 table.setValueAt(temp[2], newRow, 2);
131 selectedRow = newRow;
136 scrollPane.setViewportView(table);
138 dassourceBrowser = new DasSourceBrowser(this);
139 dasSettingsPane.add(dassourceBrowser, BorderLayout.CENTER);
141 if (af.getViewport().featuresDisplayed == null
142 || fr.renderOrder == null)
144 fr.findAllFeatures(true); // display everything!
148 final PropertyChangeListener change;
149 final FeatureSettings fs = this;
150 fr.addPropertyChangeListener(change = new PropertyChangeListener()
152 public void propertyChange(PropertyChangeEvent evt)
154 if (!fs.resettingTable && !fs.handlingUpdate)
156 fs.handlingUpdate = true;
157 fs.resetTable(null); // new groups may be added with new seuqence
158 // feature types only
159 fs.handlingUpdate = false;
165 frame = new JInternalFrame();
166 frame.setContentPane(this);
167 if (new jalview.util.Platform().isAMac())
169 Desktop.addInternalFrame(frame, MessageManager.getString("label.sequence_feature_settings"), 475, 480);
173 Desktop.addInternalFrame(frame, MessageManager.getString("label.sequence_feature_settings"), 400, 450);
176 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
178 public void internalFrameClosed(
179 javax.swing.event.InternalFrameEvent evt)
181 fr.removePropertyChangeListener(change);
182 dassourceBrowser.fs = null;
185 frame.setLayer(JLayeredPane.PALETTE_LAYER);
188 protected void popupSort(final int selectedRow, final String type,
189 final Object typeCol, final Hashtable minmax, int x, int y)
191 JPopupMenu men = new JPopupMenu(MessageManager.formatMessage("label.settings_for_param", new String[]{type}));
192 JMenuItem scr = new JMenuItem(MessageManager.getString("label.sort_by_score"));
194 final FeatureSettings me = this;
195 scr.addActionListener(new ActionListener()
198 public void actionPerformed(ActionEvent e)
200 me.sortByScore(new String[]
205 JMenuItem dens = new JMenuItem(MessageManager.getString("label.sort_by_density"));
206 dens.addActionListener(new ActionListener()
209 public void actionPerformed(ActionEvent e)
211 me.sortByDens(new String[]
219 final Object typeMinMax = minmax.get(type);
221 * final JCheckBoxMenuItem chb = new JCheckBoxMenuItem("Vary Height"); //
222 * this is broken at the moment and isn't that useful anyway!
223 * chb.setSelected(minmax.get(type) != null); chb.addActionListener(new
226 * public void actionPerformed(ActionEvent e) {
227 * chb.setState(chb.getState()); if (chb.getState()) { minmax.put(type,
228 * null); } else { minmax.put(type, typeMinMax); } }
234 if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null)
236 // if (table.getValueAt(row, column));
237 // graduated colourschemes for those where minmax exists for the
238 // positional features
239 final JCheckBoxMenuItem mxcol = new JCheckBoxMenuItem(
241 mxcol.setSelected(!(typeCol instanceof Color));
243 mxcol.addActionListener(new ActionListener()
245 JColorChooser colorChooser;
247 public void actionPerformed(ActionEvent e)
249 if (e.getSource() == mxcol)
251 if (typeCol instanceof Color)
253 FeatureColourChooser fc = new FeatureColourChooser(me.fr,
255 fc.addActionListener(this);
259 // bring up simple color chooser
260 colorChooser = new JColorChooser();
261 JDialog dialog = JColorChooser.createDialog(me,
262 "Select new Colour", true, // modal
263 colorChooser, this, // OK button handler
264 null); // no CANCEL button handler
265 colorChooser.setColor(((GraduatedColor) typeCol)
267 dialog.setVisible(true);
272 if (e.getSource() instanceof FeatureColourChooser)
274 FeatureColourChooser fc = (FeatureColourChooser) e
276 table.setValueAt(fc.getLastColour(), selectedRow, 1);
281 // probably the color chooser!
282 table.setValueAt(colorChooser.getColor(), selectedRow, 1);
284 me.updateFeatureRenderer(
285 ((FeatureTableModel) table.getModel()).getData(),
294 JMenuItem selCols = new JMenuItem(MessageManager.getString("label.select_columns_containing"));
295 selCols.addActionListener(new ActionListener()
299 public void actionPerformed(ActionEvent arg0)
301 fr.ap.alignFrame.avc.markColumnsContainingFeatures(false, type);
304 JMenuItem clearCols = new JMenuItem(MessageManager.getString("label.select_columns_not_containing"));
305 clearCols.addActionListener(new ActionListener()
309 public void actionPerformed(ActionEvent arg0)
311 fr.ap.alignFrame.avc.markColumnsContainingFeatures(true, type);
316 men.show(table, x, y);
320 * true when Feature Settings are updating from feature renderer
322 private boolean handlingUpdate = false;
325 * contains a float[3] for each feature type string. created by setTableData
327 Hashtable typeWidth = null;
329 synchronized public void setTableData()
331 if (fr.featureGroups == null)
333 fr.featureGroups = new Hashtable();
335 Vector allFeatures = new Vector();
336 Vector allGroups = new Vector();
337 SequenceFeature[] tmpfeatures;
339 for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
341 if (af.getViewport().getAlignment().getSequenceAt(i)
342 .getDatasetSequence().getSequenceFeatures() == null)
347 tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
348 .getDatasetSequence().getSequenceFeatures();
351 while (index < tmpfeatures.length)
353 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
359 if (tmpfeatures[index].getFeatureGroup() != null)
361 group = tmpfeatures[index].featureGroup;
362 if (!allGroups.contains(group))
364 allGroups.addElement(group);
367 checkGroupState(group);
372 if (!allFeatures.contains(tmpfeatures[index].getType()))
374 allFeatures.addElement(tmpfeatures[index].getType());
388 * @return true if group has been seen before and is already added to set.
390 private boolean checkGroupState(String group)
393 if (fr.featureGroups.containsKey(group))
395 visible = ((Boolean) fr.featureGroups.get(group)).booleanValue();
399 visible = true; // new group is always made visible
402 if (groupPanel == null)
404 groupPanel = new JPanel();
407 boolean alreadyAdded = false;
408 for (int g = 0; g < groupPanel.getComponentCount(); g++)
410 if (((JCheckBox) groupPanel.getComponent(g)).getText().equals(group))
413 ((JCheckBox) groupPanel.getComponent(g)).setSelected(visible);
424 fr.featureGroups.put(group, new Boolean(visible));
425 final String grp = group;
426 final JCheckBox check = new JCheckBox(group, visible);
427 check.setFont(new Font("Serif", Font.BOLD, 12));
428 check.addItemListener(new ItemListener()
430 public void itemStateChanged(ItemEvent evt)
432 fr.featureGroups.put(check.getText(),
433 new Boolean(check.isSelected()));
434 af.alignPanel.seqPanel.seqCanvas.repaint();
435 if (af.alignPanel.overviewPanel != null)
437 af.alignPanel.overviewPanel.updateOverviewImage();
440 resetTable(new String[]
444 groupPanel.add(check);
448 boolean resettingTable = false;
450 synchronized void resetTable(String[] groupChanged)
452 if (resettingTable == true)
456 resettingTable = true;
457 typeWidth = new Hashtable();
458 // TODO: change avWidth calculation to 'per-sequence' average and use long
460 float[] avWidth = null;
461 SequenceFeature[] tmpfeatures;
462 String group = null, type;
463 Vector visibleChecks = new Vector();
465 // Find out which features should be visible depending on which groups
466 // are selected / deselected
467 // and recompute average width ordering
468 for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
471 tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
472 .getDatasetSequence().getSequenceFeatures();
473 if (tmpfeatures == null)
479 while (index < tmpfeatures.length)
481 group = tmpfeatures[index].featureGroup;
483 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
489 if (group == null || fr.featureGroups.get(group) == null
490 || ((Boolean) fr.featureGroups.get(group)).booleanValue())
493 checkGroupState(group);
494 type = tmpfeatures[index].getType();
495 if (!visibleChecks.contains(type))
497 visibleChecks.addElement(type);
500 if (!typeWidth.containsKey(tmpfeatures[index].getType()))
502 typeWidth.put(tmpfeatures[index].getType(),
503 avWidth = new float[3]);
507 avWidth = (float[]) typeWidth.get(tmpfeatures[index].getType());
510 if (tmpfeatures[index].getBegin() > tmpfeatures[index].getEnd())
512 avWidth[1] += 1 + tmpfeatures[index].getBegin()
513 - tmpfeatures[index].getEnd();
517 avWidth[1] += 1 + tmpfeatures[index].getEnd()
518 - tmpfeatures[index].getBegin();
524 int fSize = visibleChecks.size();
525 Object[][] data = new Object[fSize][3];
528 if (fr.renderOrder != null)
531 fr.findAllFeatures(groupChanged != null); // prod to update
532 // colourschemes. but don't
534 // First add the checks in the previous render order,
535 // in case the window has been closed and reopened
536 for (int ro = fr.renderOrder.length - 1; ro > -1; ro--)
538 type = fr.renderOrder[ro];
540 if (!visibleChecks.contains(type))
545 data[dataIndex][0] = type;
546 data[dataIndex][1] = fr.getFeatureStyle(type);
547 data[dataIndex][2] = new Boolean(
548 af.getViewport().featuresDisplayed.containsKey(type));
550 visibleChecks.removeElement(type);
554 fSize = visibleChecks.size();
555 for (int i = 0; i < fSize; i++)
557 // These must be extra features belonging to the group
558 // which was just selected
559 type = visibleChecks.elementAt(i).toString();
560 data[dataIndex][0] = type;
562 data[dataIndex][1] = fr.getFeatureStyle(type);
563 if (data[dataIndex][1] == null)
565 // "Colour has been updated in another view!!"
566 fr.renderOrder = null;
570 data[dataIndex][2] = new Boolean(true);
574 if (originalData == null)
576 originalData = new Object[data.length][3];
577 for (int i = 0; i < data.length; i++)
579 System.arraycopy(data[i], 0, originalData[i], 0, 3);
583 table.setModel(new FeatureTableModel(data));
584 table.getColumnModel().getColumn(0).setPreferredWidth(200);
586 if (groupPanel != null)
588 groupPanel.setLayout(new GridLayout(fr.featureGroups.size() / 4 + 1,
591 groupPanel.validate();
592 bigPanel.add(groupPanel, BorderLayout.NORTH);
595 updateFeatureRenderer(data, groupChanged != null);
596 resettingTable = false;
600 * reorder data based on the featureRenderers global priority list.
604 private void ensureOrder(Object[][] data)
606 boolean sort = false;
607 float[] order = new float[data.length];
608 for (int i = 0; i < order.length; i++)
610 order[i] = fr.getOrder(data[i][0].toString());
612 order[i] = fr.setOrder(data[i][0].toString(), i / order.length);
614 sort = sort || order[i - 1] > order[i];
617 jalview.util.QuickSort.sort(order, data);
622 JalviewFileChooser chooser = new JalviewFileChooser(
623 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
624 { "fc" }, new String[]
625 { "Sequence Feature Colours" }, "Sequence Feature Colours");
626 chooser.setFileView(new jalview.io.JalviewFileView());
627 chooser.setDialogTitle("Load Feature Colours");
628 chooser.setToolTipText(MessageManager.getString("action.load"));
630 int value = chooser.showOpenDialog(this);
632 if (value == JalviewFileChooser.APPROVE_OPTION)
634 File file = chooser.getSelectedFile();
638 InputStreamReader in = new InputStreamReader(new FileInputStream(
641 jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
642 jucs = (jalview.schemabinding.version2.JalviewUserColours) jucs
645 for (int i = jucs.getColourCount() - 1; i >= 0; i--)
648 jalview.schemabinding.version2.Colour newcol = jucs.getColour(i);
651 Color mincol = null, maxcol = null;
654 mincol = new Color(Integer.parseInt(newcol.getMinRGB(), 16));
655 maxcol = new Color(Integer.parseInt(newcol.getRGB(), 16));
657 } catch (Exception e)
659 Cache.log.warn("Couldn't parse out graduated feature color.",
662 GraduatedColor gcol = new GraduatedColor(mincol, maxcol,
663 newcol.getMin(), newcol.getMax());
664 if (newcol.hasAutoScale())
666 gcol.setAutoScaled(newcol.getAutoScale());
668 if (newcol.hasColourByLabel())
670 gcol.setColourByLabel(newcol.getColourByLabel());
672 if (newcol.hasThreshold())
674 gcol.setThresh(newcol.getThreshold());
675 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD); // default
677 if (newcol.getThreshType().length() > 0)
679 String ttyp = newcol.getThreshType();
680 if (ttyp.equalsIgnoreCase("NONE"))
682 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD);
684 if (ttyp.equalsIgnoreCase("ABOVE"))
686 gcol.setThreshType(AnnotationColourGradient.ABOVE_THRESHOLD);
688 if (ttyp.equalsIgnoreCase("BELOW"))
690 gcol.setThreshType(AnnotationColourGradient.BELOW_THRESHOLD);
693 fr.setColour(name = newcol.getName(), gcol);
697 fr.setColour(name = jucs.getColour(i).getName(), new Color(
698 Integer.parseInt(jucs.getColour(i).getRGB(), 16)));
700 fr.setOrder(name, (i == 0) ? 0 : i / jucs.getColourCount());
705 Object[][] data = ((FeatureTableModel) table.getModel())
708 updateFeatureRenderer(data, false);
711 } catch (Exception ex)
713 System.out.println("Error loading User Colour File\n" + ex);
720 JalviewFileChooser chooser = new JalviewFileChooser(
721 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
722 { "fc" }, new String[]
723 { "Sequence Feature Colours" }, "Sequence Feature Colours");
724 chooser.setFileView(new jalview.io.JalviewFileView());
725 chooser.setDialogTitle("Save Feature Colour Scheme");
726 chooser.setToolTipText(MessageManager.getString("action.save"));
728 int value = chooser.showSaveDialog(this);
730 if (value == JalviewFileChooser.APPROVE_OPTION)
732 String choice = chooser.getSelectedFile().getPath();
733 jalview.schemabinding.version2.JalviewUserColours ucs = new jalview.schemabinding.version2.JalviewUserColours();
734 ucs.setSchemeName("Sequence Features");
737 PrintWriter out = new PrintWriter(new OutputStreamWriter(
738 new FileOutputStream(choice), "UTF-8"));
740 Iterator e = fr.featureColours.keySet().iterator();
741 float[] sortOrder = new float[fr.featureColours.size()];
742 String[] sortTypes = new String[fr.featureColours.size()];
746 sortTypes[i] = e.next().toString();
747 sortOrder[i] = fr.getOrder(sortTypes[i]);
750 jalview.util.QuickSort.sort(sortOrder, sortTypes);
754 for (i = 0; i < sortTypes.length; i++)
756 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
757 col.setName(sortTypes[i]);
758 col.setRGB(jalview.util.Format.getHexString(fr.getColour(col
760 fcol = fr.getFeatureStyle(sortTypes[i]);
761 if (fcol instanceof GraduatedColor)
763 gcol = (GraduatedColor) fcol;
764 col.setMin(gcol.getMin());
765 col.setMax(gcol.getMax());
766 col.setMinRGB(jalview.util.Format.getHexString(gcol
768 col.setAutoScale(gcol.isAutoScale());
769 col.setThreshold(gcol.getThresh());
770 col.setColourByLabel(gcol.isColourByLabel());
771 switch (gcol.getThreshType())
773 case AnnotationColourGradient.NO_THRESHOLD:
774 col.setThreshType("NONE");
776 case AnnotationColourGradient.ABOVE_THRESHOLD:
777 col.setThreshType("ABOVE");
779 case AnnotationColourGradient.BELOW_THRESHOLD:
780 col.setThreshType("BELOW");
788 } catch (Exception ex)
790 ex.printStackTrace();
795 public void invertSelection()
797 for (int i = 0; i < table.getRowCount(); i++)
799 Boolean value = (Boolean) table.getValueAt(i, 2);
801 table.setValueAt(new Boolean(!value.booleanValue()), i, 2);
805 public void orderByAvWidth()
807 if (table == null || table.getModel() == null)
809 Object[][] data = ((FeatureTableModel) table.getModel()).getData();
810 float[] width = new float[data.length];
814 for (int i = 0; i < data.length; i++)
816 awidth = (float[]) typeWidth.get(data[i][0]);
819 width[i] = awidth[1] / awidth[0];// *awidth[0]*awidth[2]; - better
820 // weight - but have to make per
821 // sequence, too (awidth[2])
822 // if (width[i]==1) // hack to distinguish single width sequences.
832 boolean sort = false;
833 for (int i = 0; i < width.length; i++)
835 // awidth = (float[]) typeWidth.get(data[i][0]);
838 width[i] = fr.getOrder(data[i][0].toString());
841 width[i] = fr.setOrder(data[i][0].toString(), i / data.length);
846 width[i] /= max; // normalize
847 fr.setOrder(data[i][0].toString(), width[i]); // store for later
850 sort = sort || width[i - 1] > width[i];
853 jalview.util.QuickSort.sort(width, data);
854 // update global priority order
856 updateFeatureRenderer(data, false);
864 frame.setClosed(true);
865 } catch (Exception exe)
871 public void updateFeatureRenderer(Object[][] data)
873 updateFeatureRenderer(data, true);
876 private void updateFeatureRenderer(Object[][] data, boolean visibleNew)
878 fr.setFeaturePriority(data, visibleNew);
879 af.alignPanel.paintAlignment(true);
882 int selectedRow = -1;
884 JTabbedPane tabbedPane = new JTabbedPane();
886 BorderLayout borderLayout1 = new BorderLayout();
888 BorderLayout borderLayout2 = new BorderLayout();
890 BorderLayout borderLayout3 = new BorderLayout();
892 JPanel bigPanel = new JPanel();
894 BorderLayout borderLayout4 = new BorderLayout();
896 JButton invert = new JButton();
898 JPanel buttonPanel = new JPanel();
900 JButton cancel = new JButton();
902 JButton ok = new JButton();
904 JButton loadColours = new JButton();
906 JButton saveColours = new JButton();
908 JPanel dasButtonPanel = new JPanel();
910 JButton fetchDAS = new JButton();
912 JButton saveDAS = new JButton();
914 JButton cancelDAS = new JButton();
916 JButton optimizeOrder = new JButton();
918 JButton sortByScore = new JButton();
920 JButton sortByDens = new JButton();
922 JPanel transbuttons = new JPanel(new GridLayout(4, 1));
924 private void jbInit() throws Exception
926 this.setLayout(borderLayout1);
927 settingsPane.setLayout(borderLayout2);
928 dasSettingsPane.setLayout(borderLayout3);
929 bigPanel.setLayout(borderLayout4);
930 invert.setFont(JvSwingUtils.getLabelFont());
931 invert.setText(MessageManager.getString("label.invert_selection"));
932 invert.addActionListener(new ActionListener()
934 public void actionPerformed(ActionEvent e)
939 optimizeOrder.setFont(JvSwingUtils.getLabelFont());
940 optimizeOrder.setText(MessageManager.getString("label.optimise_order"));
941 optimizeOrder.addActionListener(new ActionListener()
943 public void actionPerformed(ActionEvent e)
948 sortByScore.setFont(JvSwingUtils.getLabelFont());
949 sortByScore.setText(MessageManager.getString("label.seq_sort_by_score"));
950 sortByScore.addActionListener(new ActionListener()
952 public void actionPerformed(ActionEvent e)
957 sortByDens.setFont(JvSwingUtils.getLabelFont());
958 sortByDens.setText(MessageManager.getString("label.sequence_sort_by_density"));
959 sortByDens.addActionListener(new ActionListener()
961 public void actionPerformed(ActionEvent e)
966 cancel.setFont(JvSwingUtils.getLabelFont());
967 cancel.setText(MessageManager.getString("action.cancel"));
968 cancel.addActionListener(new ActionListener()
970 public void actionPerformed(ActionEvent e)
972 updateFeatureRenderer(originalData);
976 ok.setFont(JvSwingUtils.getLabelFont());
977 ok.setText(MessageManager.getString("action.ok"));
978 ok.addActionListener(new ActionListener()
980 public void actionPerformed(ActionEvent e)
985 loadColours.setFont(JvSwingUtils.getLabelFont());
986 loadColours.setText(MessageManager.getString("label.load_colours"));
987 loadColours.addActionListener(new ActionListener()
989 public void actionPerformed(ActionEvent e)
994 saveColours.setFont(JvSwingUtils.getLabelFont());
995 saveColours.setText(MessageManager.getString("label.save_colours"));
996 saveColours.addActionListener(new ActionListener()
998 public void actionPerformed(ActionEvent e)
1003 transparency.addChangeListener(new ChangeListener()
1005 public void stateChanged(ChangeEvent evt)
1007 fr.setTransparency((float) (100 - transparency.getValue()) / 100f);
1008 af.alignPanel.paintAlignment(true);
1012 transparency.setMaximum(70);
1013 fetchDAS.setText(MessageManager.getString("label.fetch_das_features"));
1014 fetchDAS.addActionListener(new ActionListener()
1016 public void actionPerformed(ActionEvent e)
1018 fetchDAS_actionPerformed(e);
1021 saveDAS.setText(MessageManager.getString("action.save_as_default"));
1022 saveDAS.addActionListener(new ActionListener()
1024 public void actionPerformed(ActionEvent e)
1026 saveDAS_actionPerformed(e);
1029 dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
1030 dasSettingsPane.setBorder(null);
1031 cancelDAS.setEnabled(false);
1032 cancelDAS.setText(MessageManager.getString("action.cancel_fetch"));
1033 cancelDAS.addActionListener(new ActionListener()
1035 public void actionPerformed(ActionEvent e)
1037 cancelDAS_actionPerformed(e);
1040 this.add(tabbedPane, java.awt.BorderLayout.CENTER);
1041 tabbedPane.addTab("Feature Settings", settingsPane);
1042 tabbedPane.addTab("DAS Settings", dasSettingsPane);
1043 bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
1044 transbuttons.add(optimizeOrder);
1045 transbuttons.add(invert);
1046 transbuttons.add(sortByScore);
1047 transbuttons.add(sortByDens);
1048 transPanel.add(transparency);
1049 transPanel.add(transbuttons);
1050 buttonPanel.add(ok);
1051 buttonPanel.add(cancel);
1052 buttonPanel.add(loadColours);
1053 buttonPanel.add(saveColours);
1054 bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
1055 dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
1056 dasButtonPanel.add(fetchDAS);
1057 dasButtonPanel.add(cancelDAS);
1058 dasButtonPanel.add(saveDAS);
1059 settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);
1060 settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
1063 protected void sortByDens(String[] typ)
1065 sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY);
1068 protected void sortBy(String[] typ, String methodText, final String method)
1072 typ = getDisplayedFeatureTypes();
1074 String gps[] = null;
1075 gps = getDisplayedFeatureGroups();
1078 ArrayList types = new ArrayList();
1079 for (int i = 0; i < typ.length; i++)
1085 typ = new String[types.size()];
1091 ArrayList grps = new ArrayList();
1093 for (int i = 0; i < gps.length; i++)
1100 gps = new String[grps.size()];
1103 AlignmentPanel alignPanel = af.alignPanel;
1104 AlignmentI al = alignPanel.av.getAlignment();
1107 SequenceGroup sg = alignPanel.av.getSelectionGroup();
1110 start = sg.getStartRes();
1111 stop = sg.getEndRes();
1116 stop = al.getWidth();
1118 SequenceI[] oldOrder = al.getSequencesArray();
1119 AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
1120 af.addHistoryItem(new OrderCommand(methodText, oldOrder, alignPanel.av
1122 alignPanel.paintAlignment(true);
1126 protected void sortByScore(String[] typ)
1128 sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE);
1131 private String[] getDisplayedFeatureTypes()
1133 String[] typ = null;
1136 synchronized (fr.renderOrder)
1138 typ = new String[fr.renderOrder.length];
1139 System.arraycopy(fr.renderOrder, 0, typ, 0, typ.length);
1140 for (int i = 0; i < typ.length; i++)
1142 if (af.viewport.featuresDisplayed.get(typ[i]) == null)
1152 private String[] getDisplayedFeatureGroups()
1154 String[] gps = null;
1158 if (fr.featureGroups != null)
1160 Iterator en = fr.featureGroups.keySet().iterator();
1161 gps = new String[fr.featureColours.size()];
1163 boolean valid = false;
1164 while (en.hasNext())
1166 String gp = (String) en.next();
1167 Boolean on = (Boolean) fr.featureGroups.get(gp);
1168 if (on != null && on.booleanValue())
1174 while (g < gps.length)
1187 public void fetchDAS_actionPerformed(ActionEvent e)
1189 fetchDAS.setEnabled(false);
1190 cancelDAS.setEnabled(true);
1191 dassourceBrowser.setGuiEnabled(false);
1192 Vector selectedSources = dassourceBrowser.getSelectedSources();
1193 doDasFeatureFetch(selectedSources, true, true);
1197 * get the features from selectedSources for all or the current selection
1199 * @param selectedSources
1200 * @param checkDbRefs
1201 * @param promptFetchDbRefs
1203 private void doDasFeatureFetch(List<jalviewSourceI> selectedSources,
1204 boolean checkDbRefs, boolean promptFetchDbRefs)
1206 SequenceI[] dataset, seqs;
1208 AlignViewport vp = af.getViewport();
1209 if (vp.getSelectionGroup() != null
1210 && vp.getSelectionGroup().getSize() > 0)
1212 iSize = vp.getSelectionGroup().getSize();
1213 dataset = new SequenceI[iSize];
1214 seqs = vp.getSelectionGroup().getSequencesInOrder(vp.getAlignment());
1218 iSize = vp.getAlignment().getHeight();
1219 seqs = vp.getAlignment().getSequencesArray();
1222 dataset = new SequenceI[iSize];
1223 for (int i = 0; i < iSize; i++)
1225 dataset[i] = seqs[i].getDatasetSequence();
1228 cancelDAS.setEnabled(true);
1229 dasFeatureFetcher = new jalview.ws.DasSequenceFeatureFetcher(dataset,
1230 this, selectedSources, checkDbRefs, promptFetchDbRefs);
1231 af.getViewport().setShowSequenceFeatures(true);
1232 af.showSeqFeatures.setSelected(true);
1236 * blocking call to initialise the das source browser
1238 public void initDasSources()
1240 dassourceBrowser.initDasSources();
1244 * examine the current list of das sources and return any matching the given
1245 * nicknames in sources
1248 * Vector of Strings to resolve to DAS source nicknames.
1249 * @return sources that are present in source list.
1251 public List<jalviewSourceI> resolveSourceNicknames(Vector sources)
1253 return dassourceBrowser.sourceRegistry.resolveSourceNicknames(sources);
1257 * get currently selected das sources. ensure you have called initDasSources
1258 * before calling this.
1260 * @return vector of selected das source nicknames
1262 public Vector getSelectedSources()
1264 return dassourceBrowser.getSelectedSources();
1268 * properly initialise DAS fetcher and then initiate a new thread to fetch
1269 * features from the named sources (rather than any turned on by default)
1273 * if true then runs in same thread, otherwise passes to the Swing
1276 public void fetchDasFeatures(Vector sources, boolean block)
1279 List<jalviewSourceI> resolved = dassourceBrowser.sourceRegistry
1280 .resolveSourceNicknames(sources);
1281 if (resolved.size() == 0)
1283 resolved = dassourceBrowser.getSelectedSources();
1285 if (resolved.size() > 0)
1287 final List<jalviewSourceI> dassources = resolved;
1288 fetchDAS.setEnabled(false);
1289 // cancelDAS.setEnabled(true); doDasFetch does this.
1290 Runnable fetcher = new Runnable()
1295 doDasFeatureFetch(dassources, true, false);
1305 SwingUtilities.invokeLater(fetcher);
1310 public void saveDAS_actionPerformed(ActionEvent e)
1313 .saveProperties(jalview.bin.Cache.applicationProperties);
1316 public void complete()
1318 fetchDAS.setEnabled(true);
1319 cancelDAS.setEnabled(false);
1320 dassourceBrowser.setGuiEnabled(true);
1324 public void cancelDAS_actionPerformed(ActionEvent e)
1326 if (dasFeatureFetcher != null)
1328 dasFeatureFetcher.cancel();
1333 public void noDasSourceActive()
1336 JOptionPane.showInternalConfirmDialog(Desktop.desktop,
1337 MessageManager.getString("label.no_das_sources_selected_warn"),
1338 MessageManager.getString("label.no_das_sources_selected_title"), JOptionPane.DEFAULT_OPTION,
1339 JOptionPane.INFORMATION_MESSAGE);
1342 // ///////////////////////////////////////////////////////////////////////
1343 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
1344 // ///////////////////////////////////////////////////////////////////////
1345 class FeatureTableModel extends AbstractTableModel
1347 FeatureTableModel(Object[][] data)
1352 private String[] columnNames =
1353 { "Feature Type", "Colour", "Display" };
1355 private Object[][] data;
1357 public Object[][] getData()
1362 public void setData(Object[][] data)
1367 public int getColumnCount()
1369 return columnNames.length;
1372 public Object[] getRow(int row)
1377 public int getRowCount()
1382 public String getColumnName(int col)
1384 return columnNames[col];
1387 public Object getValueAt(int row, int col)
1389 return data[row][col];
1392 public Class getColumnClass(int c)
1394 return getValueAt(0, c).getClass();
1397 public boolean isCellEditable(int row, int col)
1399 return col == 0 ? false : true;
1402 public void setValueAt(Object value, int row, int col)
1404 data[row][col] = value;
1405 fireTableCellUpdated(row, col);
1406 updateFeatureRenderer(data);
1411 class ColorRenderer extends JLabel implements TableCellRenderer
1413 javax.swing.border.Border unselectedBorder = null;
1415 javax.swing.border.Border selectedBorder = null;
1417 final String baseTT = "Click to edit, right/apple click for menu.";
1419 public ColorRenderer()
1421 setOpaque(true); // MUST do this for background to show up.
1422 setHorizontalTextPosition(SwingConstants.CENTER);
1423 setVerticalTextPosition(SwingConstants.CENTER);
1426 public Component getTableCellRendererComponent(JTable table,
1427 Object color, boolean isSelected, boolean hasFocus, int row,
1430 // JLabel comp = new JLabel();
1434 // setBounds(getBounds());
1436 setToolTipText(baseTT);
1437 setBackground(table.getBackground());
1438 if (color instanceof GraduatedColor)
1440 Rectangle cr = table.getCellRect(row, column, false);
1441 FeatureSettings.renderGraduatedColor(this, (GraduatedColor) color,
1442 (int) cr.getWidth(), (int) cr.getHeight());
1449 newColor = (Color) color;
1451 setBackground(newColor);
1452 // comp.setToolTipText("RGB value: " + newColor.getRed() + ", "
1453 // + newColor.getGreen() + ", " + newColor.getBlue());
1457 if (selectedBorder == null)
1459 selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1460 table.getSelectionBackground());
1463 setBorder(selectedBorder);
1467 if (unselectedBorder == null)
1469 unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1470 table.getBackground());
1473 setBorder(unselectedBorder);
1481 * update comp using rendering settings from gcol
1486 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol)
1488 int w = comp.getWidth(), h = comp.getHeight();
1491 w = (int) comp.getPreferredSize().getWidth();
1492 h = (int) comp.getPreferredSize().getHeight();
1499 renderGraduatedColor(comp, gcol, w, h);
1502 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol,
1505 boolean thr = false;
1508 if (gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD)
1512 tt += "Thresholded (Above " + gcol.getThresh() + ") ";
1514 if (gcol.getThreshType() == AnnotationColourGradient.BELOW_THRESHOLD)
1518 tt += "Thresholded (Below " + gcol.getThresh() + ") ";
1520 if (gcol.isColourByLabel())
1522 tt = "Coloured by label text. " + tt;
1532 Color newColor = gcol.getMaxColor();
1533 comp.setBackground(newColor);
1534 // System.err.println("Width is " + w / 2);
1535 Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w, h, thr);
1536 comp.setIcon(ficon);
1537 // tt+="RGB value: Max (" + newColor.getRed() + ", "
1538 // + newColor.getGreen() + ", " + newColor.getBlue()
1539 // + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen()
1540 // + ", " + minCol.getBlue() + ")");
1542 comp.setHorizontalAlignment(SwingConstants.CENTER);
1544 if (tt.length() > 0)
1546 if (comp.getToolTipText() == null)
1548 comp.setToolTipText(tt);
1552 comp.setToolTipText(tt + " " + comp.getToolTipText());
1558 class FeatureIcon implements Icon
1560 GraduatedColor gcol;
1564 boolean midspace = false;
1566 int width = 50, height = 20;
1568 int s1, e1; // start and end of midpoint band for thresholded symbol
1570 Color mpcolour = Color.white;
1572 FeatureIcon(GraduatedColor gfc, Color bg, int w, int h, boolean mspace)
1591 public int getIconWidth()
1596 public int getIconHeight()
1601 public void paintIcon(Component c, Graphics g, int x, int y)
1604 if (gcol.isColourByLabel())
1607 g.fillRect(0, 0, width, height);
1608 // need an icon here.
1609 g.setColor(gcol.getMaxColor());
1611 g.setFont(new Font("Verdana", Font.PLAIN, 9));
1613 // g.setFont(g.getFont().deriveFont(
1614 // AffineTransform.getScaleInstance(
1615 // width/g.getFontMetrics().stringWidth("Label"),
1616 // height/g.getFontMetrics().getHeight())));
1618 g.drawString(MessageManager.getString("label.label"), 0, 0);
1623 Color minCol = gcol.getMinColor();
1625 g.fillRect(0, 0, s1, height);
1628 g.setColor(Color.white);
1629 g.fillRect(s1, 0, e1 - s1, height);
1631 g.setColor(gcol.getMaxColor());
1632 g.fillRect(0, e1, width - e1, height);
1637 class ColorEditor extends AbstractCellEditor implements TableCellEditor,
1642 GraduatedColor currentGColor;
1644 FeatureColourChooser chooser;
1652 JColorChooser colorChooser;
1656 protected static final String EDIT = "edit";
1658 int selectedRow = 0;
1660 public ColorEditor(FeatureSettings me)
1663 // Set up the editor (from the table's point of view),
1664 // which is a button.
1665 // This button brings up the color chooser dialog,
1666 // which is the editor from the user's point of view.
1667 button = new JButton();
1668 button.setActionCommand(EDIT);
1669 button.addActionListener(this);
1670 button.setBorderPainted(false);
1671 // Set up the dialog that the button brings up.
1672 colorChooser = new JColorChooser();
1673 dialog = JColorChooser.createDialog(button, "Select new Colour", true, // modal
1674 colorChooser, this, // OK button handler
1675 null); // no CANCEL button handler
1679 * Handles events from the editor button and from the dialog's OK button.
1681 public void actionPerformed(ActionEvent e)
1684 if (EDIT.equals(e.getActionCommand()))
1686 // The user has clicked the cell, so
1687 // bring up the dialog.
1688 if (currentColor != null)
1690 // bring up simple color chooser
1691 button.setBackground(currentColor);
1692 colorChooser.setColor(currentColor);
1693 dialog.setVisible(true);
1697 // bring up graduated chooser.
1698 chooser = new FeatureColourChooser(me.fr, type);
1699 chooser.setRequestFocusEnabled(true);
1700 chooser.requestFocus();
1701 chooser.addActionListener(this);
1703 // Make the renderer reappear.
1704 fireEditingStopped();
1708 { // User pressed dialog's "OK" button.
1709 if (currentColor != null)
1711 currentColor = colorChooser.getColor();
1715 // class cast exceptions may be raised if the chooser created on a
1716 // non-graduated color
1717 currentGColor = (GraduatedColor) chooser.getLastColour();
1719 me.table.setValueAt(getCellEditorValue(), selectedRow, 1);
1720 fireEditingStopped();
1721 me.table.validate();
1725 // Implement the one CellEditor method that AbstractCellEditor doesn't.
1726 public Object getCellEditorValue()
1728 if (currentColor == null)
1730 return currentGColor;
1732 return currentColor;
1735 // Implement the one method defined by TableCellEditor.
1736 public Component getTableCellEditorComponent(JTable table, Object value,
1737 boolean isSelected, int row, int column)
1739 currentGColor = null;
1740 currentColor = null;
1741 this.selectedRow = row;
1742 type = me.table.getValueAt(row, 0).toString();
1743 button.setOpaque(true);
1744 button.setBackground(me.getBackground());
1745 if (value instanceof GraduatedColor)
1747 currentGColor = (GraduatedColor) value;
1748 JLabel btn = new JLabel();
1749 btn.setSize(button.getSize());
1750 FeatureSettings.renderGraduatedColor(btn, currentGColor);
1751 button.setBackground(btn.getBackground());
1752 button.setIcon(btn.getIcon());
1753 button.setText(btn.getText());
1758 button.setIcon(null);
1759 currentColor = (Color) value;
1760 button.setBackground(currentColor);