2 * Jalview - A Sequence Alignment Editor and Viewer (Development Version 2.4.1)
3 * Copyright (C) 2009 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 import java.awt.event.*;
26 import java.awt.geom.AffineTransform;
27 import java.awt.image.BufferedImage;
28 import java.beans.PropertyChangeEvent;
29 import java.beans.PropertyChangeListener;
32 import javax.swing.event.*;
33 import javax.swing.table.*;
35 import jalview.analysis.AlignmentSorter;
36 import jalview.commands.OrderCommand;
37 import jalview.datamodel.*;
39 import jalview.schemes.AnnotationColourGradient;
40 import jalview.schemes.GraduatedColor;
42 public class FeatureSettings extends JPanel
44 DasSourceBrowser dassourceBrowser;
46 jalview.ws.DasSequenceFeatureFetcher dasFeatureFetcher;
48 JPanel settingsPane = new JPanel();
50 JPanel dasSettingsPane = new JPanel();
52 final FeatureRenderer fr;
54 public final AlignFrame af;
56 Object[][] originalData;
58 final JInternalFrame frame;
60 JScrollPane scrollPane = new JScrollPane();
66 JSlider transparency = new JSlider();
68 JPanel transPanel = new JPanel(new GridLayout(1, 2));
70 public FeatureSettings(AlignFrame af)
73 fr = af.getFeatureRenderer();
75 transparency.setMaximum(100 - (int) (fr.transparency * 100));
80 } catch (Exception ex)
86 table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));
87 table.setFont(new Font("Verdana", Font.PLAIN, 12));
88 table.setDefaultRenderer(Color.class, new ColorRenderer());
90 table.setDefaultEditor(Color.class, new ColorEditor(this));
92 table.setDefaultEditor(GraduatedColor.class, new ColorEditor(this));
93 table.setDefaultRenderer(GraduatedColor.class, new ColorRenderer());
94 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
96 table.addMouseListener(new MouseAdapter()
98 public void mousePressed(MouseEvent evt)
100 selectedRow = table.rowAtPoint(evt.getPoint());
101 if (javax.swing.SwingUtilities.isRightMouseButton(evt))
103 popupSort(selectedRow, (String) table.getValueAt(selectedRow, 0),
104 table.getValueAt(selectedRow, 1), fr.minmax, evt.getX(),
110 table.addMouseMotionListener(new MouseMotionAdapter()
112 public void mouseDragged(MouseEvent evt)
114 int newRow = table.rowAtPoint(evt.getPoint());
115 if (newRow != selectedRow && selectedRow != -1 && newRow != -1)
117 Object[] temp = new Object[3];
118 temp[0] = table.getValueAt(selectedRow, 0);
119 temp[1] = table.getValueAt(selectedRow, 1);
120 temp[2] = table.getValueAt(selectedRow, 2);
122 table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0);
123 table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1);
124 table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2);
126 table.setValueAt(temp[0], newRow, 0);
127 table.setValueAt(temp[1], newRow, 1);
128 table.setValueAt(temp[2], newRow, 2);
130 selectedRow = newRow;
135 scrollPane.setViewportView(table);
137 dassourceBrowser = new DasSourceBrowser();
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 Desktop.addInternalFrame(frame, "Sequence Feature Settings", 400, 450);
168 .addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
170 public void internalFrameClosed(
171 javax.swing.event.InternalFrameEvent evt)
173 fr.removePropertyChangeListener(change);
176 frame.setLayer(JLayeredPane.PALETTE_LAYER);
179 protected void popupSort(final int selectedRow, final String type,
180 final Object typeCol, final Hashtable minmax, int x, int y)
182 JPopupMenu men = new JPopupMenu("Settings for " + type);
183 JMenuItem scr = new JMenuItem("Sort by Score");
185 final FeatureSettings me = this;
186 scr.addActionListener(new ActionListener()
189 public void actionPerformed(ActionEvent e)
191 me.sortByScore(new String[]
196 JMenuItem dens = new JMenuItem("Sort by Density");
197 dens.addActionListener(new ActionListener()
200 public void actionPerformed(ActionEvent e)
202 me.sortByDens(new String[]
210 final Object typeMinMax = minmax.get(type);
212 * final JCheckBoxMenuItem chb = new JCheckBoxMenuItem("Vary Height"); //
213 * this is broken at the moment and isn't that useful anyway!
214 * chb.setSelected(minmax.get(type) != null); chb.addActionListener(new
217 * public void actionPerformed(ActionEvent e) {
218 * chb.setState(chb.getState()); if (chb.getState()) { minmax.put(type,
219 * null); } else { minmax.put(type, typeMinMax); } }
225 if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null)
227 // if (table.getValueAt(row, column));
228 // graduated colourschemes for those where minmax exists for the
229 // positional features
230 final JCheckBoxMenuItem mxcol = new JCheckBoxMenuItem(
232 mxcol.setSelected(!(typeCol instanceof Color));
234 mxcol.addActionListener(new ActionListener()
236 JColorChooser colorChooser;
238 public void actionPerformed(ActionEvent e)
240 if (e.getSource() == mxcol)
242 if (typeCol instanceof Color)
244 FeatureColourChooser fc = new FeatureColourChooser(me.fr,
246 fc.addActionListener(this);
250 // bring up simple color chooser
251 colorChooser = new JColorChooser();
252 JDialog dialog = JColorChooser.createDialog(me,
253 "Select new Colour", true, // modal
254 colorChooser, this, // OK button handler
255 null); // no CANCEL button handler
256 colorChooser.setColor(((GraduatedColor) typeCol)
258 dialog.setVisible(true);
263 if (e.getSource() instanceof FeatureColourChooser)
265 FeatureColourChooser fc = (FeatureColourChooser) e
267 table.setValueAt(fc.getLastColour(), selectedRow, 1);
272 // probably the color chooser!
273 table.setValueAt(colorChooser.getColor(), selectedRow, 1);
275 me.updateFeatureRenderer(((FeatureTableModel) table
276 .getModel()).getData(), false);
284 men.show(table, x, y);
288 * true when Feature Settings are updating from feature renderer
290 private boolean handlingUpdate = false;
293 * contains a float[3] for each feature type string. created by setTableData
295 Hashtable typeWidth = null;
297 synchronized public void setTableData()
299 if (fr.featureGroups == null)
301 fr.featureGroups = new Hashtable();
303 Vector allFeatures = new Vector();
304 Vector allGroups = new Vector();
305 SequenceFeature[] tmpfeatures;
307 for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)
309 if (af.getViewport().alignment.getSequenceAt(i).getDatasetSequence()
310 .getSequenceFeatures() == null)
315 tmpfeatures = af.getViewport().alignment.getSequenceAt(i)
316 .getDatasetSequence().getSequenceFeatures();
319 while (index < tmpfeatures.length)
321 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
327 if (tmpfeatures[index].getFeatureGroup() != null)
329 group = tmpfeatures[index].featureGroup;
330 if (!allGroups.contains(group))
332 allGroups.addElement(group);
335 checkGroupState(group);
340 if (!allFeatures.contains(tmpfeatures[index].getType()))
342 allFeatures.addElement(tmpfeatures[index].getType());
356 * @return true if group has been seen before and is already added to set.
358 private boolean checkGroupState(String group)
361 if (fr.featureGroups.containsKey(group))
363 visible = ((Boolean) fr.featureGroups.get(group)).booleanValue();
367 visible = true; // new group is always made visible
370 if (groupPanel == null)
372 groupPanel = new JPanel();
375 boolean alreadyAdded = false;
376 for (int g = 0; g < groupPanel.getComponentCount(); g++)
378 if (((JCheckBox) groupPanel.getComponent(g)).getText().equals(group))
381 ((JCheckBox) groupPanel.getComponent(g)).setSelected(visible);
392 fr.featureGroups.put(group, new Boolean(visible));
393 final String grp = group;
394 final JCheckBox check = new JCheckBox(group, visible);
395 check.setFont(new Font("Serif", Font.BOLD, 12));
396 check.addItemListener(new ItemListener()
398 public void itemStateChanged(ItemEvent evt)
400 fr.featureGroups.put(check.getText(), new Boolean(check
402 af.alignPanel.seqPanel.seqCanvas.repaint();
403 if (af.alignPanel.overviewPanel != null)
405 af.alignPanel.overviewPanel.updateOverviewImage();
408 resetTable(new String[]
412 groupPanel.add(check);
416 boolean resettingTable = false;
418 synchronized void resetTable(String[] groupChanged)
420 if (resettingTable == true)
424 resettingTable = true;
425 typeWidth = new Hashtable();
426 // TODO: change avWidth calculation to 'per-sequence' average and use long
428 float[] avWidth = null;
429 SequenceFeature[] tmpfeatures;
430 String group = null, type;
431 Vector visibleChecks = new Vector();
433 // Find out which features should be visible depending on which groups
434 // are selected / deselected
435 // and recompute average width ordering
436 for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)
439 tmpfeatures = af.getViewport().alignment.getSequenceAt(i)
440 .getDatasetSequence().getSequenceFeatures();
441 if (tmpfeatures == null)
447 while (index < tmpfeatures.length)
449 group = tmpfeatures[index].featureGroup;
451 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
457 if (group == null || fr.featureGroups.get(group) == null
458 || ((Boolean) fr.featureGroups.get(group)).booleanValue())
461 checkGroupState(group);
462 type = tmpfeatures[index].getType();
463 if (!visibleChecks.contains(type))
465 visibleChecks.addElement(type);
468 if (!typeWidth.containsKey(tmpfeatures[index].getType()))
470 typeWidth.put(tmpfeatures[index].getType(),
471 avWidth = new float[3]);
475 avWidth = (float[]) typeWidth.get(tmpfeatures[index].getType());
478 if (tmpfeatures[index].getBegin() > tmpfeatures[index].getEnd())
480 avWidth[1] += 1 + tmpfeatures[index].getBegin()
481 - tmpfeatures[index].getEnd();
485 avWidth[1] += 1 + tmpfeatures[index].getEnd()
486 - tmpfeatures[index].getBegin();
492 int fSize = visibleChecks.size();
493 Object[][] data = new Object[fSize][3];
496 if (fr.renderOrder != null)
499 fr.findAllFeatures(groupChanged != null); // prod to update
500 // colourschemes. but don't
502 // First add the checks in the previous render order,
503 // in case the window has been closed and reopened
504 for (int ro = fr.renderOrder.length - 1; ro > -1; ro--)
506 type = fr.renderOrder[ro];
508 if (!visibleChecks.contains(type))
513 data[dataIndex][0] = type;
514 data[dataIndex][1] = fr.getFeatureStyle(type);
515 data[dataIndex][2] = new Boolean(af.getViewport().featuresDisplayed
518 visibleChecks.removeElement(type);
522 fSize = visibleChecks.size();
523 for (int i = 0; i < fSize; i++)
525 // These must be extra features belonging to the group
526 // which was just selected
527 type = visibleChecks.elementAt(i).toString();
528 data[dataIndex][0] = type;
530 data[dataIndex][1] = fr.getFeatureStyle(type);
531 if (data[dataIndex][1] == null)
533 // "Colour has been updated in another view!!"
534 fr.renderOrder = null;
538 data[dataIndex][2] = new Boolean(true);
542 if (originalData == null)
544 originalData = new Object[data.length][3];
545 for (int i = 0; i < data.length; i++)
547 System.arraycopy(data[i], 0, originalData[i], 0, 3);
551 table.setModel(new FeatureTableModel(data));
552 table.getColumnModel().getColumn(0).setPreferredWidth(200);
554 if (groupPanel != null)
556 groupPanel.setLayout(new GridLayout(fr.featureGroups.size() / 4 + 1,
559 groupPanel.validate();
560 bigPanel.add(groupPanel, BorderLayout.NORTH);
563 updateFeatureRenderer(data, groupChanged != null);
564 resettingTable = false;
568 * reorder data based on the featureRenderers global priority list.
572 private void ensureOrder(Object[][] data)
574 boolean sort = false;
575 float[] order = new float[data.length];
576 for (int i = 0; i < order.length; i++)
578 order[i] = fr.getOrder(data[i][0].toString());
580 order[i] = fr.setOrder(data[i][0].toString(), i / order.length);
582 sort = sort || order[i - 1] > order[i];
585 jalview.util.QuickSort.sort(order, data);
590 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
591 .getProperty("LAST_DIRECTORY"), new String[]
592 { "fc" }, new String[]
593 { "Sequence Feature Colours" }, "Sequence Feature Colours");
594 chooser.setFileView(new jalview.io.JalviewFileView());
595 chooser.setDialogTitle("Load Feature Colours");
596 chooser.setToolTipText("Load");
598 int value = chooser.showOpenDialog(this);
600 if (value == JalviewFileChooser.APPROVE_OPTION)
602 File file = chooser.getSelectedFile();
606 InputStreamReader in = new InputStreamReader(new FileInputStream(
609 jalview.binding.JalviewUserColours jucs = new jalview.binding.JalviewUserColours();
610 jucs = (jalview.binding.JalviewUserColours) jucs.unmarshal(in);
612 for (int i = jucs.getColourCount() - 1; i >= 0; i--)
615 // TODO: update Colour XML
616 fr.setColour(name = jucs.getColour(i).getName(), new Color(
617 Integer.parseInt(jucs.getColour(i).getRGB(), 16)));
618 fr.setOrder(name, (i == 0) ? 0 : i / jucs.getColourCount());
623 Object[][] data = ((FeatureTableModel) table.getModel())
626 updateFeatureRenderer(data, false);
629 } catch (Exception ex)
631 System.out.println("Error loading User Colour File\n" + ex);
638 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache
639 .getProperty("LAST_DIRECTORY"), new String[]
640 { "fc" }, new String[]
641 { "Sequence Feature Colours" }, "Sequence Feature Colours");
642 chooser.setFileView(new jalview.io.JalviewFileView());
643 chooser.setDialogTitle("Save Feature Colour Scheme");
644 chooser.setToolTipText("Save");
646 int value = chooser.showSaveDialog(this);
648 if (value == JalviewFileChooser.APPROVE_OPTION)
650 String choice = chooser.getSelectedFile().getPath();
651 jalview.binding.JalviewUserColours ucs = new jalview.binding.JalviewUserColours();
652 ucs.setSchemeName("Sequence Features");
655 PrintWriter out = new PrintWriter(new OutputStreamWriter(
656 new FileOutputStream(choice), "UTF-8"));
658 Enumeration e = fr.featureColours.keys();
659 float[] sortOrder = new float[fr.featureColours.size()];
660 String[] sortTypes = new String[fr.featureColours.size()];
662 while (e.hasMoreElements())
664 sortTypes[i] = e.nextElement().toString();
665 sortOrder[i] = fr.getOrder(sortTypes[i]);
668 jalview.util.QuickSort.sort(sortOrder, sortTypes);
670 for (i = 0; i < sortTypes.length; i++)
672 jalview.binding.Colour col = new jalview.binding.Colour();
673 col.setName(sortTypes[i]);
674 col.setRGB(jalview.util.Format.getHexString(fr.getColour(col
680 } catch (Exception ex)
682 ex.printStackTrace();
687 public void invertSelection()
689 for (int i = 0; i < table.getRowCount(); i++)
691 Boolean value = (Boolean) table.getValueAt(i, 2);
693 table.setValueAt(new Boolean(!value.booleanValue()), i, 2);
697 public void orderByAvWidth()
699 if (table == null || table.getModel() == null)
701 Object[][] data = ((FeatureTableModel) table.getModel()).getData();
702 float[] width = new float[data.length];
706 for (int i = 0; i < data.length; i++)
708 awidth = (float[]) typeWidth.get(data[i][0]);
711 width[i] = awidth[1] / awidth[0];// *awidth[0]*awidth[2]; - better
712 // weight - but have to make per
713 // sequence, too (awidth[2])
714 // if (width[i]==1) // hack to distinguish single width sequences.
724 boolean sort = false;
725 for (int i = 0; i < width.length; i++)
727 // awidth = (float[]) typeWidth.get(data[i][0]);
730 width[i] = fr.getOrder(data[i][0].toString());
733 width[i] = fr.setOrder(data[i][0].toString(), i / data.length);
738 width[i] /= max; // normalize
739 fr.setOrder(data[i][0].toString(), width[i]); // store for later
742 sort = sort || width[i - 1] > width[i];
745 jalview.util.QuickSort.sort(width, data);
746 // update global priority order
748 updateFeatureRenderer(data, false);
756 frame.setClosed(true);
757 } catch (Exception exe)
763 public void updateFeatureRenderer(Object[][] data)
765 updateFeatureRenderer(data, true);
768 private void updateFeatureRenderer(Object[][] data, boolean visibleNew)
770 fr.setFeaturePriority(data, visibleNew);
771 af.alignPanel.paintAlignment(true);
774 int selectedRow = -1;
776 JTabbedPane tabbedPane = new JTabbedPane();
778 BorderLayout borderLayout1 = new BorderLayout();
780 BorderLayout borderLayout2 = new BorderLayout();
782 BorderLayout borderLayout3 = new BorderLayout();
784 JPanel bigPanel = new JPanel();
786 BorderLayout borderLayout4 = new BorderLayout();
788 JButton invert = new JButton();
790 JPanel buttonPanel = new JPanel();
792 JButton cancel = new JButton();
794 JButton ok = new JButton();
796 JButton loadColours = new JButton();
798 JButton saveColours = new JButton();
800 JPanel dasButtonPanel = new JPanel();
802 JButton fetchDAS = new JButton();
804 JButton saveDAS = new JButton();
806 JButton cancelDAS = new JButton();
808 JButton optimizeOrder = new JButton();
810 JButton sortByScore = new JButton();
812 JButton sortByDens = new JButton();
814 JPanel transbuttons = new JPanel(new GridLayout(4, 1));
816 private void jbInit() throws Exception
818 this.setLayout(borderLayout1);
819 settingsPane.setLayout(borderLayout2);
820 dasSettingsPane.setLayout(borderLayout3);
821 bigPanel.setLayout(borderLayout4);
822 invert.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
823 invert.setText("Invert Selection");
824 invert.addActionListener(new ActionListener()
826 public void actionPerformed(ActionEvent e)
831 optimizeOrder.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
832 optimizeOrder.setText("Optimise Order");
833 optimizeOrder.addActionListener(new ActionListener()
835 public void actionPerformed(ActionEvent e)
840 sortByScore.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
841 sortByScore.setText("Seq sort by Score");
842 sortByScore.addActionListener(new ActionListener()
844 public void actionPerformed(ActionEvent e)
849 sortByDens.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
850 sortByDens.setText("Seq Sort by density");
851 sortByDens.addActionListener(new ActionListener()
853 public void actionPerformed(ActionEvent e)
858 cancel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
859 cancel.setText("Cancel");
860 cancel.addActionListener(new ActionListener()
862 public void actionPerformed(ActionEvent e)
864 updateFeatureRenderer(originalData);
868 ok.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
870 ok.addActionListener(new ActionListener()
872 public void actionPerformed(ActionEvent e)
877 loadColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
878 loadColours.setText("Load Colours");
879 loadColours.addActionListener(new ActionListener()
881 public void actionPerformed(ActionEvent e)
886 saveColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
887 saveColours.setText("Save Colours");
888 saveColours.addActionListener(new ActionListener()
890 public void actionPerformed(ActionEvent e)
895 transparency.addChangeListener(new ChangeListener()
897 public void stateChanged(ChangeEvent evt)
899 fr.setTransparency((float) (100 - transparency.getValue()) / 100f);
900 af.alignPanel.paintAlignment(true);
904 transparency.setMaximum(70);
905 fetchDAS.setText("Fetch DAS Features");
906 fetchDAS.addActionListener(new ActionListener()
908 public void actionPerformed(ActionEvent e)
910 fetchDAS_actionPerformed(e);
913 saveDAS.setText("Save as default");
914 saveDAS.addActionListener(new ActionListener()
916 public void actionPerformed(ActionEvent e)
918 saveDAS_actionPerformed(e);
921 dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
922 dasSettingsPane.setBorder(null);
923 cancelDAS.setEnabled(false);
924 cancelDAS.setText("Cancel Fetch");
925 cancelDAS.addActionListener(new ActionListener()
927 public void actionPerformed(ActionEvent e)
929 cancelDAS_actionPerformed(e);
932 this.add(tabbedPane, java.awt.BorderLayout.CENTER);
933 tabbedPane.addTab("Feature Settings", settingsPane);
934 tabbedPane.addTab("DAS Settings", dasSettingsPane);
935 bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
936 transbuttons.add(optimizeOrder);
937 transbuttons.add(invert);
938 transbuttons.add(sortByScore);
939 transbuttons.add(sortByDens);
940 transPanel.add(transparency);
941 transPanel.add(transbuttons);
943 buttonPanel.add(cancel);
944 buttonPanel.add(loadColours);
945 buttonPanel.add(saveColours);
946 bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
947 dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
948 dasButtonPanel.add(fetchDAS);
949 dasButtonPanel.add(cancelDAS);
950 dasButtonPanel.add(saveDAS);
951 settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);
952 settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
955 protected void sortByDens(String[] typ)
957 sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY);
960 protected void sortBy(String[] typ, String methodText, final String method)
964 typ = getDisplayedFeatureTypes();
967 gps = getDisplayedFeatureGroups();
970 for (int i = 0; i < typ.length; i++)
972 System.err.println("Sorting on Types:" + typ[i]);
978 for (int i = 0; i < gps.length; i++)
980 System.err.println("Sorting on groups:" + gps[i]);
983 AlignmentPanel alignPanel = af.alignPanel;
984 AlignmentI al = alignPanel.av.getAlignment();
987 SequenceGroup sg = alignPanel.av.getSelectionGroup();
990 start = sg.getStartRes();
991 stop = sg.getEndRes();
996 stop = al.getWidth();
998 SequenceI[] oldOrder = al.getSequencesArray();
999 AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
1000 af.addHistoryItem(new OrderCommand(methodText, oldOrder, alignPanel.av
1002 alignPanel.paintAlignment(true);
1006 protected void sortByScore(String[] typ)
1008 sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE);
1011 private String[] getDisplayedFeatureTypes()
1013 String[] typ = null;
1016 synchronized (fr.renderOrder)
1018 typ = new String[fr.renderOrder.length];
1019 System.arraycopy(fr.renderOrder, 0, typ, 0, typ.length);
1020 for (int i = 0; i < typ.length; i++)
1022 if (af.viewport.featuresDisplayed.get(typ[i]) == null)
1032 private String[] getDisplayedFeatureGroups()
1034 String[] gps = null;
1038 if (fr.featureGroups != null)
1040 Enumeration en = fr.featureGroups.keys();
1041 gps = new String[fr.featureColours.size()];
1043 boolean valid = false;
1044 while (en.hasMoreElements())
1046 String gp = (String) en.nextElement();
1047 Boolean on = (Boolean) fr.featureGroups.get(gp);
1048 if (on != null && on.booleanValue())
1054 while (g < gps.length)
1067 public void fetchDAS_actionPerformed(ActionEvent e)
1069 fetchDAS.setEnabled(false);
1070 cancelDAS.setEnabled(true);
1071 Vector selectedSources = dassourceBrowser.getSelectedSources();
1072 doDasFeatureFetch(selectedSources, true, true);
1076 * get the features from selectedSources for all or the current selection
1078 * @param selectedSources
1079 * @param checkDbRefs
1080 * @param promptFetchDbRefs
1082 private void doDasFeatureFetch(Vector selectedSources,
1083 boolean checkDbRefs, boolean promptFetchDbRefs)
1085 SequenceI[] dataset, seqs;
1087 AlignViewport vp = af.getViewport();
1088 if (vp.getSelectionGroup() != null
1089 && vp.getSelectionGroup().getSize() > 0)
1091 iSize = vp.getSelectionGroup().getSize();
1092 dataset = new SequenceI[iSize];
1093 seqs = vp.getSelectionGroup().getSequencesInOrder(vp.getAlignment());
1097 iSize = vp.getAlignment().getHeight();
1098 seqs = vp.getAlignment().getSequencesArray();
1101 dataset = new SequenceI[iSize];
1102 for (int i = 0; i < iSize; i++)
1104 dataset[i] = seqs[i].getDatasetSequence();
1107 cancelDAS.setEnabled(true);
1108 dasFeatureFetcher = new jalview.ws.DasSequenceFeatureFetcher(dataset,
1109 this, selectedSources, checkDbRefs, promptFetchDbRefs);
1110 af.getViewport().setShowSequenceFeatures(true);
1111 af.showSeqFeatures.setSelected(true);
1115 * blocking call to initialise the das source browser
1117 public void initDasSources()
1119 dassourceBrowser.initDasSources();
1123 * examine the current list of das sources and return any matching the given
1124 * nicknames in sources
1127 * Vector of Strings to resolve to DAS source nicknames.
1128 * @return sources that are present in source list.
1130 public Vector resolveSourceNicknames(Vector sources)
1132 return dassourceBrowser.resolveSourceNicknames(sources);
1136 * get currently selected das sources. ensure you have called initDasSources
1137 * before calling this.
1139 * @return vector of selected das source nicknames
1141 public Vector getSelectedSources()
1143 return dassourceBrowser.getSelectedSources();
1147 * properly initialise DAS fetcher and then initiate a new thread to fetch
1148 * features from the named sources (rather than any turned on by default)
1152 * if true then runs in same thread, otherwise passes to the Swing
1155 public void fetchDasFeatures(Vector sources, boolean block)
1158 Vector resolved = resolveSourceNicknames(sources);
1159 if (resolved.size() == 0)
1161 resolved = dassourceBrowser.getSelectedSources();
1163 if (resolved.size() > 0)
1165 final Vector dassources = resolved;
1166 fetchDAS.setEnabled(false);
1167 // cancelDAS.setEnabled(true); doDasFetch does this.
1168 Runnable fetcher = new Runnable()
1173 doDasFeatureFetch(dassources, true, false);
1183 SwingUtilities.invokeLater(fetcher);
1188 public void saveDAS_actionPerformed(ActionEvent e)
1191 .saveProperties(jalview.bin.Cache.applicationProperties);
1194 public void complete()
1196 fetchDAS.setEnabled(true);
1197 cancelDAS.setEnabled(false);
1200 public void cancelDAS_actionPerformed(ActionEvent e)
1202 if (dasFeatureFetcher != null)
1204 dasFeatureFetcher.cancel();
1206 fetchDAS.setEnabled(true);
1207 cancelDAS.setEnabled(false);
1210 public void noDasSourceActive()
1213 JOptionPane.showInternalConfirmDialog(Desktop.desktop,
1214 "No das sources were selected.\n"
1215 + "Please select some sources and\n" + " try again.",
1216 "No Sources Selected", JOptionPane.DEFAULT_OPTION,
1217 JOptionPane.INFORMATION_MESSAGE);
1220 // ///////////////////////////////////////////////////////////////////////
1221 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
1222 // ///////////////////////////////////////////////////////////////////////
1223 class FeatureTableModel extends AbstractTableModel
1225 FeatureTableModel(Object[][] data)
1230 private String[] columnNames =
1231 { "Feature Type", "Colour", "Display" };
1233 private Object[][] data;
1235 public Object[][] getData()
1240 public void setData(Object[][] data)
1245 public int getColumnCount()
1247 return columnNames.length;
1250 public Object[] getRow(int row)
1255 public int getRowCount()
1260 public String getColumnName(int col)
1262 return columnNames[col];
1265 public Object getValueAt(int row, int col)
1267 return data[row][col];
1270 public Class getColumnClass(int c)
1272 return getValueAt(0, c).getClass();
1275 public boolean isCellEditable(int row, int col)
1277 return col == 0 ? false : true;
1280 public void setValueAt(Object value, int row, int col)
1282 data[row][col] = value;
1283 fireTableCellUpdated(row, col);
1284 updateFeatureRenderer(data);
1289 class ColorRenderer extends JLabel implements TableCellRenderer
1291 javax.swing.border.Border unselectedBorder = null;
1293 javax.swing.border.Border selectedBorder = null;
1295 final String baseTT = "Click to edit, right/apple click for menu.";
1297 public ColorRenderer()
1299 setOpaque(true); // MUST do this for background to show up.
1302 public Component getTableCellRendererComponent(JTable table,
1303 Object color, boolean isSelected, boolean hasFocus, int row,
1306 // JLabel comp = new JLabel();
1310 // setBounds(getBounds());
1312 setToolTipText(baseTT);
1313 setBackground(table.getBackground());
1314 if (color instanceof GraduatedColor)
1316 Rectangle cr = table.getCellRect(row, column, false);
1317 FeatureSettings.renderGraduatedColor(this, (GraduatedColor) color,
1318 (int) cr.getWidth(), (int) cr.getHeight());
1325 newColor = (Color) color;
1327 setBackground(newColor);
1328 // comp.setToolTipText("RGB value: " + newColor.getRed() + ", "
1329 // + newColor.getGreen() + ", " + newColor.getBlue());
1333 if (selectedBorder == null)
1335 selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1336 table.getSelectionBackground());
1339 setBorder(selectedBorder);
1343 if (unselectedBorder == null)
1345 unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1346 table.getBackground());
1349 setBorder(unselectedBorder);
1357 * update comp using rendering settings from gcol
1362 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol)
1364 int w = comp.getWidth(), h = comp.getHeight();
1367 w = (int) comp.getPreferredSize().getWidth();
1368 h = (int) comp.getPreferredSize().getHeight();
1375 renderGraduatedColor(comp, gcol, w, h);
1378 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol,
1384 if (gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD)
1387 tt += "Thresholded (Above " + gcol.getThresh() + ") ";
1389 if (gcol.getThreshType() == AnnotationColourGradient.BELOW_THRESHOLD)
1392 tt += "Thresholded (Below " + gcol.getThresh() + ") ";
1394 if (gcol.isColourByLabel())
1396 tt = "Coloured by label text. " + tt;
1402 Color newColor = gcol.getMaxColor();
1403 comp.setBackground(newColor);
1404 System.err.println("Width is " + w / 2);
1405 Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w / 2, h);
1406 comp.setIcon(ficon);
1407 // tt+="RGB value: Max (" + newColor.getRed() + ", "
1408 // + newColor.getGreen() + ", " + newColor.getBlue()
1409 // + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen()
1410 // + ", " + minCol.getBlue() + ")");
1413 if (tt.length() > 0)
1415 if (comp.getToolTipText() == null)
1417 comp.setToolTipText(tt);
1421 comp.setToolTipText(tt + " " + comp.getToolTipText());
1427 class FeatureIcon implements Icon
1429 GraduatedColor gcol;
1433 int width = 50, height = 20;
1435 FeatureIcon(GraduatedColor gfc, Color bg, int w, int h)
1443 public int getIconWidth()
1448 public int getIconHeight()
1453 public void paintIcon(Component c, Graphics g, int x, int y)
1456 if (gcol.isColourByLabel())
1459 g.fillRect(0, 0, width, height);
1460 // need an icon here.
1461 g.setColor(gcol.getMaxColor());
1463 g.setFont(new Font("Verdana", Font.PLAIN, 9));
1465 // g.setFont(g.getFont().deriveFont(
1466 // AffineTransform.getScaleInstance(
1467 // width/g.getFontMetrics().stringWidth("Label"),
1468 // height/g.getFontMetrics().getHeight())));
1470 g.drawString("Label", 0, 0);
1475 Color minCol = gcol.getMinColor();
1477 g.fillRect(0, 0, width, height);
1482 class ColorEditor extends AbstractCellEditor implements TableCellEditor,
1487 GraduatedColor currentGColor;
1489 FeatureColourChooser chooser;
1497 JColorChooser colorChooser;
1501 protected static final String EDIT = "edit";
1503 int selectedRow = 0;
1505 public ColorEditor(FeatureSettings me)
1508 // Set up the editor (from the table's point of view),
1509 // which is a button.
1510 // This button brings up the color chooser dialog,
1511 // which is the editor from the user's point of view.
1512 button = new JButton();
1513 button.setActionCommand(EDIT);
1514 button.addActionListener(this);
1515 button.setBorderPainted(false);
1516 // Set up the dialog that the button brings up.
1517 colorChooser = new JColorChooser();
1518 dialog = JColorChooser.createDialog(button, "Select new Colour", true, // modal
1519 colorChooser, this, // OK button handler
1520 null); // no CANCEL button handler
1524 * Handles events from the editor button and from the dialog's OK button.
1526 public void actionPerformed(ActionEvent e)
1529 if (EDIT.equals(e.getActionCommand()))
1531 // The user has clicked the cell, so
1532 // bring up the dialog.
1533 if (currentColor != null)
1535 // bring up simple color chooser
1536 button.setBackground(currentColor);
1537 colorChooser.setColor(currentColor);
1538 dialog.setVisible(true);
1542 // bring up graduated chooser.
1543 chooser = new FeatureColourChooser(me.fr, type);
1544 chooser.setRequestFocusEnabled(true);
1545 chooser.requestFocus();
1546 chooser.addActionListener(this);
1548 // Make the renderer reappear.
1549 fireEditingStopped();
1553 { // User pressed dialog's "OK" button.
1554 if (currentColor != null)
1556 currentColor = colorChooser.getColor();
1560 // class cast exceptions may be raised if the chooser created on a
1561 // non-graduated color
1562 currentGColor = (GraduatedColor) chooser.getLastColour();
1564 me.table.setValueAt(getCellEditorValue(), selectedRow, 1);
1565 fireEditingStopped();
1566 me.table.validate();
1570 // Implement the one CellEditor method that AbstractCellEditor doesn't.
1571 public Object getCellEditorValue()
1573 if (currentColor == null)
1575 return currentGColor;
1577 return currentColor;
1580 // Implement the one method defined by TableCellEditor.
1581 public Component getTableCellEditorComponent(JTable table, Object value,
1582 boolean isSelected, int row, int column)
1584 currentGColor = null;
1585 currentColor = null;
1586 this.selectedRow = row;
1587 type = me.table.getValueAt(row, 0).toString();
1588 button.setOpaque(true);
1589 button.setBackground(me.getBackground());
1590 if (value instanceof GraduatedColor)
1592 currentGColor = (GraduatedColor) value;
1593 JLabel btn = new JLabel();
1594 btn.setSize(button.getSize());
1595 FeatureSettings.renderGraduatedColor(btn, currentGColor);
1596 button.setBackground(btn.getBackground());
1597 button.setIcon(btn.getIcon());
1598 button.setText(btn.getText());
1603 button.setIcon(null);
1604 currentColor = (Color) value;
1605 button.setBackground(currentColor);