2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
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
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
25 import java.util.List;
27 import java.awt.event.*;
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.api.FeaturesDisplayedI;
37 import jalview.bin.Cache;
38 import jalview.commands.OrderCommand;
39 import jalview.datamodel.*;
41 import jalview.schemes.AnnotationColourGradient;
42 import jalview.schemes.GraduatedColor;
43 import jalview.util.MessageManager;
44 import jalview.ws.dbsources.das.api.jalviewSourceI;
46 public class FeatureSettings extends JPanel
48 DasSourceBrowser dassourceBrowser;
50 jalview.ws.DasSequenceFeatureFetcher dasFeatureFetcher;
52 JPanel settingsPane = new JPanel();
54 JPanel dasSettingsPane = new JPanel();
56 final FeatureRenderer fr;
58 public final AlignFrame af;
60 Object[][] originalData;
62 private float originalTransparency;
64 final JInternalFrame frame;
66 JScrollPane scrollPane = new JScrollPane();
72 JSlider transparency = new JSlider();
74 JPanel transPanel = new JPanel(new GridLayout(1, 2));
76 public FeatureSettings(AlignFrame af)
79 fr = af.getFeatureRenderer();
80 // allow transparency to be recovered
81 transparency.setMaximum(100 - (int) ((originalTransparency=fr.getTransparency()) * 100));
86 } catch (Exception ex)
92 table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));
93 table.setFont(new Font("Verdana", Font.PLAIN, 12));
94 table.setDefaultRenderer(Color.class, new ColorRenderer());
96 table.setDefaultEditor(Color.class, new ColorEditor(this));
98 table.setDefaultEditor(GraduatedColor.class, new ColorEditor(this));
99 table.setDefaultRenderer(GraduatedColor.class, new ColorRenderer());
100 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
102 table.addMouseListener(new MouseAdapter()
104 public void mousePressed(MouseEvent evt)
106 selectedRow = table.rowAtPoint(evt.getPoint());
107 if (evt.isPopupTrigger())
109 popupSort(selectedRow, (String) table.getValueAt(selectedRow, 0),
110 table.getValueAt(selectedRow, 1), fr.getMinMax(),
111 evt.getX(), evt.getY());
113 else if (evt.getClickCount() == 2)
115 fr.ap.alignFrame.avc.markColumnsContainingFeatures(
116 evt.isAltDown(), evt.isShiftDown() || evt.isMetaDown(),
118 (String) table.getValueAt(selectedRow, 0));
123 table.addMouseMotionListener(new MouseMotionAdapter()
125 public void mouseDragged(MouseEvent evt)
127 int newRow = table.rowAtPoint(evt.getPoint());
128 if (newRow != selectedRow && selectedRow != -1 && newRow != -1)
130 Object[] temp = new Object[3];
131 temp[0] = table.getValueAt(selectedRow, 0);
132 temp[1] = table.getValueAt(selectedRow, 1);
133 temp[2] = table.getValueAt(selectedRow, 2);
135 table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0);
136 table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1);
137 table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2);
139 table.setValueAt(temp[0], newRow, 0);
140 table.setValueAt(temp[1], newRow, 1);
141 table.setValueAt(temp[2], newRow, 2);
143 selectedRow = newRow;
147 table.setToolTipText("<html>"
149 .wrapTooltip("Click/drag feature types up or down to change render order.<br/>Double click to select columns containing feature in alignment/current selection<br/>Pressing Alt will select columns outside features rather than inside<br/>Pressing Shift to modify current selection (rather than clear current selection)<br/>Press CTRL or Command/Meta to toggle columns in/outside features<br/>")
151 scrollPane.setViewportView(table);
153 dassourceBrowser = new DasSourceBrowser(this);
154 dasSettingsPane.add(dassourceBrowser, BorderLayout.CENTER);
156 if (af.getViewport().isShowSequenceFeatures() || !fr.hasRenderOrder())
158 fr.findAllFeatures(true); // display everything!
162 final PropertyChangeListener change;
163 final FeatureSettings fs = this;
164 fr.addPropertyChangeListener(change = new PropertyChangeListener()
166 public void propertyChange(PropertyChangeEvent evt)
168 if (!fs.resettingTable && !fs.handlingUpdate)
170 fs.handlingUpdate = true;
171 fs.resetTable(null); // new groups may be added with new seuqence
172 // feature types only
173 fs.handlingUpdate = false;
179 frame = new JInternalFrame();
180 frame.setContentPane(this);
181 if (new jalview.util.Platform().isAMac())
183 Desktop.addInternalFrame(frame,
184 MessageManager.getString("label.sequence_feature_settings"),
189 Desktop.addInternalFrame(frame,
190 MessageManager.getString("label.sequence_feature_settings"),
194 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
196 public void internalFrameClosed(
197 javax.swing.event.InternalFrameEvent evt)
199 fr.removePropertyChangeListener(change);
200 dassourceBrowser.fs = null;
203 frame.setLayer(JLayeredPane.PALETTE_LAYER);
206 protected void popupSort(final int selectedRow, final String type,
207 final Object typeCol, final Hashtable minmax, int x, int y)
209 JPopupMenu men = new JPopupMenu(MessageManager.formatMessage(
210 "label.settings_for_param", new String[]
212 JMenuItem scr = new JMenuItem(
213 MessageManager.getString("label.sort_by_score"));
215 final FeatureSettings me = this;
216 scr.addActionListener(new ActionListener()
219 public void actionPerformed(ActionEvent e)
221 me.af.avc.sortAlignmentByFeatureScore(new String[]
226 JMenuItem dens = new JMenuItem(
227 MessageManager.getString("label.sort_by_density"));
228 dens.addActionListener(new ActionListener()
231 public void actionPerformed(ActionEvent e)
233 me.af.avc.sortAlignmentByFeatureDensity(new String[]
241 final Object typeMinMax = minmax.get(type);
243 * final JCheckBoxMenuItem chb = new JCheckBoxMenuItem("Vary Height"); //
244 * this is broken at the moment and isn't that useful anyway!
245 * chb.setSelected(minmax.get(type) != null); chb.addActionListener(new
248 * public void actionPerformed(ActionEvent e) {
249 * chb.setState(chb.getState()); if (chb.getState()) { minmax.put(type,
250 * null); } else { minmax.put(type, typeMinMax); } }
256 if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null)
258 // if (table.getValueAt(row, column));
259 // graduated colourschemes for those where minmax exists for the
260 // positional features
261 final JCheckBoxMenuItem mxcol = new JCheckBoxMenuItem(
263 mxcol.setSelected(!(typeCol instanceof Color));
265 mxcol.addActionListener(new ActionListener()
267 JColorChooser colorChooser;
269 public void actionPerformed(ActionEvent e)
271 if (e.getSource() == mxcol)
273 if (typeCol instanceof Color)
275 FeatureColourChooser fc = new FeatureColourChooser(me.fr,
277 fc.addActionListener(this);
281 // bring up simple color chooser
282 colorChooser = new JColorChooser();
283 JDialog dialog = JColorChooser.createDialog(me,
284 "Select new Colour", true, // modal
285 colorChooser, this, // OK button handler
286 null); // no CANCEL button handler
287 colorChooser.setColor(((GraduatedColor) typeCol)
289 dialog.setVisible(true);
294 if (e.getSource() instanceof FeatureColourChooser)
296 FeatureColourChooser fc = (FeatureColourChooser) e
298 table.setValueAt(fc.getLastColour(), selectedRow, 1);
303 // probably the color chooser!
304 table.setValueAt(colorChooser.getColor(), selectedRow, 1);
306 me.updateFeatureRenderer(
307 ((FeatureTableModel) table.getModel()).getData(),
316 JMenuItem selCols = new JMenuItem(
317 MessageManager.getString("label.select_columns_containing"));
318 selCols.addActionListener(new ActionListener()
322 public void actionPerformed(ActionEvent arg0)
324 fr.ap.alignFrame.avc.markColumnsContainingFeatures(false, false,
328 JMenuItem clearCols = new JMenuItem(
329 MessageManager.getString("label.select_columns_not_containing"));
330 clearCols.addActionListener(new ActionListener()
334 public void actionPerformed(ActionEvent arg0)
336 fr.ap.alignFrame.avc.markColumnsContainingFeatures(true, false,
342 men.show(table, x, y);
346 * true when Feature Settings are updating from feature renderer
348 private boolean handlingUpdate = false;
351 * contains a float[3] for each feature type string. created by setTableData
353 Hashtable typeWidth = null;
355 synchronized public void setTableData()
357 Vector allFeatures = new Vector();
358 Vector allGroups = new Vector();
359 SequenceFeature[] tmpfeatures;
361 for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
363 if (af.getViewport().getAlignment().getSequenceAt(i)
364 .getDatasetSequence().getSequenceFeatures() == null)
369 tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
370 .getDatasetSequence().getSequenceFeatures();
373 while (index < tmpfeatures.length)
375 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
381 if (tmpfeatures[index].getFeatureGroup() != null)
383 group = tmpfeatures[index].featureGroup;
384 if (!allGroups.contains(group))
386 allGroups.addElement(group);
387 checkGroupState(group);
391 if (!allFeatures.contains(tmpfeatures[index].getType()))
393 allFeatures.addElement(tmpfeatures[index].getType());
405 * Synchronise gui group list and check visibility of group
408 * @return true if group is visible
410 private boolean checkGroupState(String group)
412 boolean visible = fr.checkGroupVisibility(group, true);
414 if (groupPanel == null)
416 groupPanel = new JPanel();
419 boolean alreadyAdded = false;
420 for (int g = 0; g < groupPanel.getComponentCount(); g++)
422 if (((JCheckBox) groupPanel.getComponent(g)).getText().equals(group))
425 ((JCheckBox) groupPanel.getComponent(g)).setSelected(visible);
435 final String grp = group;
436 final JCheckBox check = new JCheckBox(group, visible);
437 check.setFont(new Font("Serif", Font.BOLD, 12));
438 check.addItemListener(new ItemListener()
440 public void itemStateChanged(ItemEvent evt)
442 fr.setGroupVisibility(check.getText(), check.isSelected());
443 af.alignPanel.seqPanel.seqCanvas.repaint();
444 if (af.alignPanel.overviewPanel != null)
446 af.alignPanel.overviewPanel.updateOverviewImage();
449 resetTable(new String[]
453 groupPanel.add(check);
457 boolean resettingTable = false;
459 synchronized void resetTable(String[] groupChanged)
461 if (resettingTable == true)
465 resettingTable = true;
466 typeWidth = new Hashtable();
467 // TODO: change avWidth calculation to 'per-sequence' average and use long
469 float[] avWidth = null;
470 SequenceFeature[] tmpfeatures;
471 String group = null, type;
472 Vector visibleChecks = new Vector();
474 // Find out which features should be visible depending on which groups
475 // are selected / deselected
476 // and recompute average width ordering
477 for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
480 tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
481 .getDatasetSequence().getSequenceFeatures();
482 if (tmpfeatures == null)
488 while (index < tmpfeatures.length)
490 group = tmpfeatures[index].featureGroup;
492 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
498 if (group == null || checkGroupState(group))
500 type = tmpfeatures[index].getType();
501 if (!visibleChecks.contains(type))
503 visibleChecks.addElement(type);
506 if (!typeWidth.containsKey(tmpfeatures[index].getType()))
508 typeWidth.put(tmpfeatures[index].getType(),
509 avWidth = new float[3]);
513 avWidth = (float[]) typeWidth.get(tmpfeatures[index].getType());
516 if (tmpfeatures[index].getBegin() > tmpfeatures[index].getEnd())
518 avWidth[1] += 1 + tmpfeatures[index].getBegin()
519 - tmpfeatures[index].getEnd();
523 avWidth[1] += 1 + tmpfeatures[index].getEnd()
524 - tmpfeatures[index].getBegin();
530 int fSize = visibleChecks.size();
531 Object[][] data = new Object[fSize][3];
534 if (fr.hasRenderOrder())
538 fr.findAllFeatures(groupChanged != null); // prod to update
539 // colourschemes. but don't
541 // First add the checks in the previous render order,
542 // in case the window has been closed and reopened
544 List<String> frl = fr.getRenderOrder();
545 for (int ro = frl.size() - 1; ro > -1; ro--)
549 if (!visibleChecks.contains(type))
554 data[dataIndex][0] = type;
555 data[dataIndex][1] = fr.getFeatureStyle(type);
556 data[dataIndex][2] = new Boolean(af.getViewport()
557 .getFeaturesDisplayed().isVisible(type));
559 visibleChecks.removeElement(type);
563 fSize = visibleChecks.size();
564 for (int i = 0; i < fSize; i++)
566 // These must be extra features belonging to the group
567 // which was just selected
568 type = visibleChecks.elementAt(i).toString();
569 data[dataIndex][0] = type;
571 data[dataIndex][1] = fr.getFeatureStyle(type);
572 if (data[dataIndex][1] == null)
574 // "Colour has been updated in another view!!"
575 fr.clearRenderOrder();
579 data[dataIndex][2] = new Boolean(true);
583 if (originalData == null)
585 originalData = new Object[data.length][3];
586 for (int i = 0; i < data.length; i++)
588 System.arraycopy(data[i], 0, originalData[i], 0, 3);
592 table.setModel(new FeatureTableModel(data));
593 table.getColumnModel().getColumn(0).setPreferredWidth(200);
595 if (groupPanel != null)
597 groupPanel.setLayout(new GridLayout(
598 fr.getFeatureGroupsSize() / 4 + 1, 4));
600 groupPanel.validate();
601 bigPanel.add(groupPanel, BorderLayout.NORTH);
604 updateFeatureRenderer(data, groupChanged != null);
605 resettingTable = false;
609 * reorder data based on the featureRenderers global priority list.
613 private void ensureOrder(Object[][] data)
615 boolean sort = false;
616 float[] order = new float[data.length];
617 for (int i = 0; i < order.length; i++)
619 order[i] = fr.getOrder(data[i][0].toString());
621 order[i] = fr.setOrder(data[i][0].toString(), i / order.length);
623 sort = sort || order[i - 1] > order[i];
626 jalview.util.QuickSort.sort(order, data);
631 JalviewFileChooser chooser = new JalviewFileChooser(
632 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
633 { "fc" }, new String[]
634 { "Sequence Feature Colours" }, "Sequence Feature Colours");
635 chooser.setFileView(new jalview.io.JalviewFileView());
636 chooser.setDialogTitle("Load Feature Colours");
637 chooser.setToolTipText(MessageManager.getString("action.load"));
639 int value = chooser.showOpenDialog(this);
641 if (value == JalviewFileChooser.APPROVE_OPTION)
643 File file = chooser.getSelectedFile();
647 InputStreamReader in = new InputStreamReader(new FileInputStream(
650 jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
651 jucs = (jalview.schemabinding.version2.JalviewUserColours) jucs
654 for (int i = jucs.getColourCount() - 1; i >= 0; i--)
657 jalview.schemabinding.version2.Colour newcol = jucs.getColour(i);
660 Color mincol = null, maxcol = null;
663 mincol = new Color(Integer.parseInt(newcol.getMinRGB(), 16));
664 maxcol = new Color(Integer.parseInt(newcol.getRGB(), 16));
666 } catch (Exception e)
668 Cache.log.warn("Couldn't parse out graduated feature color.",
671 GraduatedColor gcol = new GraduatedColor(mincol, maxcol,
672 newcol.getMin(), newcol.getMax());
673 if (newcol.hasAutoScale())
675 gcol.setAutoScaled(newcol.getAutoScale());
677 if (newcol.hasColourByLabel())
679 gcol.setColourByLabel(newcol.getColourByLabel());
681 if (newcol.hasThreshold())
683 gcol.setThresh(newcol.getThreshold());
684 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD); // default
686 if (newcol.getThreshType().length() > 0)
688 String ttyp = newcol.getThreshType();
689 if (ttyp.equalsIgnoreCase("NONE"))
691 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD);
693 if (ttyp.equalsIgnoreCase("ABOVE"))
695 gcol.setThreshType(AnnotationColourGradient.ABOVE_THRESHOLD);
697 if (ttyp.equalsIgnoreCase("BELOW"))
699 gcol.setThreshType(AnnotationColourGradient.BELOW_THRESHOLD);
702 fr.setColour(name = newcol.getName(), gcol);
706 fr.setColour(name = jucs.getColour(i).getName(), new Color(
707 Integer.parseInt(jucs.getColour(i).getRGB(), 16)));
709 fr.setOrder(name, (i == 0) ? 0 : i / jucs.getColourCount());
714 Object[][] data = ((FeatureTableModel) table.getModel())
717 updateFeatureRenderer(data, false);
720 } catch (Exception ex)
722 System.out.println("Error loading User Colour File\n" + ex);
729 JalviewFileChooser chooser = new JalviewFileChooser(
730 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
731 { "fc" }, new String[]
732 { "Sequence Feature Colours" }, "Sequence Feature Colours");
733 chooser.setFileView(new jalview.io.JalviewFileView());
734 chooser.setDialogTitle("Save Feature Colour Scheme");
735 chooser.setToolTipText(MessageManager.getString("action.save"));
737 int value = chooser.showSaveDialog(this);
739 if (value == JalviewFileChooser.APPROVE_OPTION)
741 String choice = chooser.getSelectedFile().getPath();
742 jalview.schemabinding.version2.JalviewUserColours ucs = new jalview.schemabinding.version2.JalviewUserColours();
743 ucs.setSchemeName("Sequence Features");
746 PrintWriter out = new PrintWriter(new OutputStreamWriter(
747 new FileOutputStream(choice), "UTF-8"));
749 Set fr_colours = fr.getAllFeatureColours();
750 Iterator e = fr_colours.iterator();
751 float[] sortOrder = new float[fr_colours.size()];
752 String[] sortTypes = new String[fr_colours.size()];
756 sortTypes[i] = e.next().toString();
757 sortOrder[i] = fr.getOrder(sortTypes[i]);
760 jalview.util.QuickSort.sort(sortOrder, sortTypes);
764 for (i = 0; i < sortTypes.length; i++)
766 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
767 col.setName(sortTypes[i]);
768 col.setRGB(jalview.util.Format.getHexString(fr.getColour(col
770 fcol = fr.getFeatureStyle(sortTypes[i]);
771 if (fcol instanceof GraduatedColor)
773 gcol = (GraduatedColor) fcol;
774 col.setMin(gcol.getMin());
775 col.setMax(gcol.getMax());
776 col.setMinRGB(jalview.util.Format.getHexString(gcol
778 col.setAutoScale(gcol.isAutoScale());
779 col.setThreshold(gcol.getThresh());
780 col.setColourByLabel(gcol.isColourByLabel());
781 switch (gcol.getThreshType())
783 case AnnotationColourGradient.NO_THRESHOLD:
784 col.setThreshType("NONE");
786 case AnnotationColourGradient.ABOVE_THRESHOLD:
787 col.setThreshType("ABOVE");
789 case AnnotationColourGradient.BELOW_THRESHOLD:
790 col.setThreshType("BELOW");
798 } catch (Exception ex)
800 ex.printStackTrace();
805 public void invertSelection()
807 for (int i = 0; i < table.getRowCount(); i++)
809 Boolean value = (Boolean) table.getValueAt(i, 2);
811 table.setValueAt(new Boolean(!value.booleanValue()), i, 2);
815 public void orderByAvWidth()
817 if (table == null || table.getModel() == null)
819 Object[][] data = ((FeatureTableModel) table.getModel()).getData();
820 float[] width = new float[data.length];
824 for (int i = 0; i < data.length; i++)
826 awidth = (float[]) typeWidth.get(data[i][0]);
829 width[i] = awidth[1] / awidth[0];// *awidth[0]*awidth[2]; - better
830 // weight - but have to make per
831 // sequence, too (awidth[2])
832 // if (width[i]==1) // hack to distinguish single width sequences.
842 boolean sort = false;
843 for (int i = 0; i < width.length; i++)
845 // awidth = (float[]) typeWidth.get(data[i][0]);
848 width[i] = fr.getOrder(data[i][0].toString());
851 width[i] = fr.setOrder(data[i][0].toString(), i / data.length);
856 width[i] /= max; // normalize
857 fr.setOrder(data[i][0].toString(), width[i]); // store for later
860 sort = sort || width[i - 1] > width[i];
863 jalview.util.QuickSort.sort(width, data);
864 // update global priority order
866 updateFeatureRenderer(data, false);
874 frame.setClosed(true);
875 } catch (Exception exe)
881 public void updateFeatureRenderer(Object[][] data)
883 updateFeatureRenderer(data, true);
886 private void updateFeatureRenderer(Object[][] data, boolean visibleNew)
888 fr.setFeaturePriority(data, visibleNew);
889 af.alignPanel.paintAlignment(true);
892 int selectedRow = -1;
894 JTabbedPane tabbedPane = new JTabbedPane();
896 BorderLayout borderLayout1 = new BorderLayout();
898 BorderLayout borderLayout2 = new BorderLayout();
900 BorderLayout borderLayout3 = new BorderLayout();
902 JPanel bigPanel = new JPanel();
904 BorderLayout borderLayout4 = new BorderLayout();
906 JButton invert = new JButton();
908 JPanel buttonPanel = new JPanel();
910 JButton cancel = new JButton();
912 JButton ok = new JButton();
914 JButton loadColours = new JButton();
916 JButton saveColours = new JButton();
918 JPanel dasButtonPanel = new JPanel();
920 JButton fetchDAS = new JButton();
922 JButton saveDAS = new JButton();
924 JButton cancelDAS = new JButton();
926 JButton optimizeOrder = new JButton();
928 JButton sortByScore = new JButton();
930 JButton sortByDens = new JButton();
932 JPanel transbuttons = new JPanel(new GridLayout(4, 1));
934 private void jbInit() throws Exception
936 this.setLayout(borderLayout1);
937 settingsPane.setLayout(borderLayout2);
938 dasSettingsPane.setLayout(borderLayout3);
939 bigPanel.setLayout(borderLayout4);
940 invert.setFont(JvSwingUtils.getLabelFont());
941 invert.setText(MessageManager.getString("label.invert_selection"));
942 invert.addActionListener(new ActionListener()
944 public void actionPerformed(ActionEvent e)
949 optimizeOrder.setFont(JvSwingUtils.getLabelFont());
950 optimizeOrder.setText(MessageManager.getString("label.optimise_order"));
951 optimizeOrder.addActionListener(new ActionListener()
953 public void actionPerformed(ActionEvent e)
958 sortByScore.setFont(JvSwingUtils.getLabelFont());
960 .setText(MessageManager.getString("label.seq_sort_by_score"));
961 sortByScore.addActionListener(new ActionListener()
963 public void actionPerformed(ActionEvent e)
965 af.avc.sortAlignmentByFeatureScore(null);
968 sortByDens.setFont(JvSwingUtils.getLabelFont());
969 sortByDens.setText(MessageManager
970 .getString("label.sequence_sort_by_density"));
971 sortByDens.addActionListener(new ActionListener()
973 public void actionPerformed(ActionEvent e)
975 af.avc.sortAlignmentByFeatureDensity(null);
978 cancel.setFont(JvSwingUtils.getLabelFont());
979 cancel.setText(MessageManager.getString("action.cancel"));
980 cancel.addActionListener(new ActionListener()
982 public void actionPerformed(ActionEvent e)
984 fr.setTransparency(originalTransparency);
985 updateFeatureRenderer(originalData);
989 ok.setFont(JvSwingUtils.getLabelFont());
990 ok.setText(MessageManager.getString("action.ok"));
991 ok.addActionListener(new ActionListener()
993 public void actionPerformed(ActionEvent e)
998 loadColours.setFont(JvSwingUtils.getLabelFont());
999 loadColours.setText(MessageManager.getString("label.load_colours"));
1000 loadColours.addActionListener(new ActionListener()
1002 public void actionPerformed(ActionEvent e)
1007 saveColours.setFont(JvSwingUtils.getLabelFont());
1008 saveColours.setText(MessageManager.getString("label.save_colours"));
1009 saveColours.addActionListener(new ActionListener()
1011 public void actionPerformed(ActionEvent e)
1016 transparency.addChangeListener(new ChangeListener()
1018 public void stateChanged(ChangeEvent evt)
1020 fr.setTransparency((float) (100 - transparency.getValue()) / 100f);
1021 af.alignPanel.paintAlignment(true);
1025 transparency.setMaximum(70);
1026 fetchDAS.setText(MessageManager.getString("label.fetch_das_features"));
1027 fetchDAS.addActionListener(new ActionListener()
1029 public void actionPerformed(ActionEvent e)
1031 fetchDAS_actionPerformed(e);
1034 saveDAS.setText(MessageManager.getString("action.save_as_default"));
1035 saveDAS.addActionListener(new ActionListener()
1037 public void actionPerformed(ActionEvent e)
1039 saveDAS_actionPerformed(e);
1042 dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
1043 dasSettingsPane.setBorder(null);
1044 cancelDAS.setEnabled(false);
1045 cancelDAS.setText(MessageManager.getString("action.cancel_fetch"));
1046 cancelDAS.addActionListener(new ActionListener()
1048 public void actionPerformed(ActionEvent e)
1050 cancelDAS_actionPerformed(e);
1053 this.add(tabbedPane, java.awt.BorderLayout.CENTER);
1054 tabbedPane.addTab("Feature Settings", settingsPane);
1055 tabbedPane.addTab("DAS Settings", dasSettingsPane);
1056 bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
1057 transbuttons.add(optimizeOrder);
1058 transbuttons.add(invert);
1059 transbuttons.add(sortByScore);
1060 transbuttons.add(sortByDens);
1061 transPanel.add(transparency);
1062 transPanel.add(transbuttons);
1063 buttonPanel.add(ok);
1064 buttonPanel.add(cancel);
1065 buttonPanel.add(loadColours);
1066 buttonPanel.add(saveColours);
1067 bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
1068 dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
1069 dasButtonPanel.add(fetchDAS);
1070 dasButtonPanel.add(cancelDAS);
1071 dasButtonPanel.add(saveDAS);
1072 settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);
1073 settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
1076 public void fetchDAS_actionPerformed(ActionEvent e)
1078 fetchDAS.setEnabled(false);
1079 cancelDAS.setEnabled(true);
1080 dassourceBrowser.setGuiEnabled(false);
1081 Vector selectedSources = dassourceBrowser.getSelectedSources();
1082 doDasFeatureFetch(selectedSources, true, true);
1086 * get the features from selectedSources for all or the current selection
1088 * @param selectedSources
1089 * @param checkDbRefs
1090 * @param promptFetchDbRefs
1092 private void doDasFeatureFetch(List<jalviewSourceI> selectedSources,
1093 boolean checkDbRefs, boolean promptFetchDbRefs)
1095 SequenceI[] dataset, seqs;
1097 AlignViewport vp = af.getViewport();
1098 if (vp.getSelectionGroup() != null
1099 && vp.getSelectionGroup().getSize() > 0)
1101 iSize = vp.getSelectionGroup().getSize();
1102 dataset = new SequenceI[iSize];
1103 seqs = vp.getSelectionGroup().getSequencesInOrder(vp.getAlignment());
1107 iSize = vp.getAlignment().getHeight();
1108 seqs = vp.getAlignment().getSequencesArray();
1111 dataset = new SequenceI[iSize];
1112 for (int i = 0; i < iSize; i++)
1114 dataset[i] = seqs[i].getDatasetSequence();
1117 cancelDAS.setEnabled(true);
1118 dasFeatureFetcher = new jalview.ws.DasSequenceFeatureFetcher(dataset,
1119 this, selectedSources, checkDbRefs, promptFetchDbRefs);
1120 af.getViewport().setShowSequenceFeatures(true);
1121 af.showSeqFeatures.setSelected(true);
1125 * blocking call to initialise the das source browser
1127 public void initDasSources()
1129 dassourceBrowser.initDasSources();
1133 * examine the current list of das sources and return any matching the given
1134 * nicknames in sources
1137 * Vector of Strings to resolve to DAS source nicknames.
1138 * @return sources that are present in source list.
1140 public List<jalviewSourceI> resolveSourceNicknames(Vector sources)
1142 return dassourceBrowser.sourceRegistry.resolveSourceNicknames(sources);
1146 * get currently selected das sources. ensure you have called initDasSources
1147 * before calling this.
1149 * @return vector of selected das source nicknames
1151 public Vector getSelectedSources()
1153 return dassourceBrowser.getSelectedSources();
1157 * properly initialise DAS fetcher and then initiate a new thread to fetch
1158 * features from the named sources (rather than any turned on by default)
1162 * if true then runs in same thread, otherwise passes to the Swing
1165 public void fetchDasFeatures(Vector sources, boolean block)
1168 List<jalviewSourceI> resolved = dassourceBrowser.sourceRegistry
1169 .resolveSourceNicknames(sources);
1170 if (resolved.size() == 0)
1172 resolved = dassourceBrowser.getSelectedSources();
1174 if (resolved.size() > 0)
1176 final List<jalviewSourceI> dassources = resolved;
1177 fetchDAS.setEnabled(false);
1178 // cancelDAS.setEnabled(true); doDasFetch does this.
1179 Runnable fetcher = new Runnable()
1184 doDasFeatureFetch(dassources, true, false);
1194 SwingUtilities.invokeLater(fetcher);
1199 public void saveDAS_actionPerformed(ActionEvent e)
1202 .saveProperties(jalview.bin.Cache.applicationProperties);
1205 public void complete()
1207 fetchDAS.setEnabled(true);
1208 cancelDAS.setEnabled(false);
1209 dassourceBrowser.setGuiEnabled(true);
1213 public void cancelDAS_actionPerformed(ActionEvent e)
1215 if (dasFeatureFetcher != null)
1217 dasFeatureFetcher.cancel();
1222 public void noDasSourceActive()
1226 .showInternalConfirmDialog(
1229 .getString("label.no_das_sources_selected_warn"),
1231 .getString("label.no_das_sources_selected_title"),
1232 JOptionPane.DEFAULT_OPTION,
1233 JOptionPane.INFORMATION_MESSAGE);
1236 // ///////////////////////////////////////////////////////////////////////
1237 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
1238 // ///////////////////////////////////////////////////////////////////////
1239 class FeatureTableModel extends AbstractTableModel
1241 FeatureTableModel(Object[][] data)
1246 private String[] columnNames =
1247 { "Feature Type", "Colour", "Display" };
1249 private Object[][] data;
1251 public Object[][] getData()
1256 public void setData(Object[][] data)
1261 public int getColumnCount()
1263 return columnNames.length;
1266 public Object[] getRow(int row)
1271 public int getRowCount()
1276 public String getColumnName(int col)
1278 return columnNames[col];
1281 public Object getValueAt(int row, int col)
1283 return data[row][col];
1286 public Class getColumnClass(int c)
1288 return getValueAt(0, c).getClass();
1291 public boolean isCellEditable(int row, int col)
1293 return col == 0 ? false : true;
1296 public void setValueAt(Object value, int row, int col)
1298 data[row][col] = value;
1299 fireTableCellUpdated(row, col);
1300 updateFeatureRenderer(data);
1305 class ColorRenderer extends JLabel implements TableCellRenderer
1307 javax.swing.border.Border unselectedBorder = null;
1309 javax.swing.border.Border selectedBorder = null;
1311 final String baseTT = "Click to edit, right/apple click for menu.";
1313 public ColorRenderer()
1315 setOpaque(true); // MUST do this for background to show up.
1316 setHorizontalTextPosition(SwingConstants.CENTER);
1317 setVerticalTextPosition(SwingConstants.CENTER);
1320 public Component getTableCellRendererComponent(JTable table,
1321 Object color, boolean isSelected, boolean hasFocus, int row,
1324 // JLabel comp = new JLabel();
1328 // setBounds(getBounds());
1330 setToolTipText(baseTT);
1331 setBackground(table.getBackground());
1332 if (color instanceof GraduatedColor)
1334 Rectangle cr = table.getCellRect(row, column, false);
1335 FeatureSettings.renderGraduatedColor(this, (GraduatedColor) color,
1336 (int) cr.getWidth(), (int) cr.getHeight());
1343 newColor = (Color) color;
1345 setBackground(newColor);
1346 // comp.setToolTipText("RGB value: " + newColor.getRed() + ", "
1347 // + newColor.getGreen() + ", " + newColor.getBlue());
1351 if (selectedBorder == null)
1353 selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1354 table.getSelectionBackground());
1357 setBorder(selectedBorder);
1361 if (unselectedBorder == null)
1363 unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1364 table.getBackground());
1367 setBorder(unselectedBorder);
1375 * update comp using rendering settings from gcol
1380 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol)
1382 int w = comp.getWidth(), h = comp.getHeight();
1385 w = (int) comp.getPreferredSize().getWidth();
1386 h = (int) comp.getPreferredSize().getHeight();
1393 renderGraduatedColor(comp, gcol, w, h);
1396 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol,
1399 boolean thr = false;
1402 if (gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD)
1406 tt += "Thresholded (Above " + gcol.getThresh() + ") ";
1408 if (gcol.getThreshType() == AnnotationColourGradient.BELOW_THRESHOLD)
1412 tt += "Thresholded (Below " + gcol.getThresh() + ") ";
1414 if (gcol.isColourByLabel())
1416 tt = "Coloured by label text. " + tt;
1426 Color newColor = gcol.getMaxColor();
1427 comp.setBackground(newColor);
1428 // System.err.println("Width is " + w / 2);
1429 Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w, h, thr);
1430 comp.setIcon(ficon);
1431 // tt+="RGB value: Max (" + newColor.getRed() + ", "
1432 // + newColor.getGreen() + ", " + newColor.getBlue()
1433 // + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen()
1434 // + ", " + minCol.getBlue() + ")");
1436 comp.setHorizontalAlignment(SwingConstants.CENTER);
1438 if (tt.length() > 0)
1440 if (comp.getToolTipText() == null)
1442 comp.setToolTipText(tt);
1446 comp.setToolTipText(tt + " " + comp.getToolTipText());
1452 class FeatureIcon implements Icon
1454 GraduatedColor gcol;
1458 boolean midspace = false;
1460 int width = 50, height = 20;
1462 int s1, e1; // start and end of midpoint band for thresholded symbol
1464 Color mpcolour = Color.white;
1466 FeatureIcon(GraduatedColor gfc, Color bg, int w, int h, boolean mspace)
1485 public int getIconWidth()
1490 public int getIconHeight()
1495 public void paintIcon(Component c, Graphics g, int x, int y)
1498 if (gcol.isColourByLabel())
1501 g.fillRect(0, 0, width, height);
1502 // need an icon here.
1503 g.setColor(gcol.getMaxColor());
1505 g.setFont(new Font("Verdana", Font.PLAIN, 9));
1507 // g.setFont(g.getFont().deriveFont(
1508 // AffineTransform.getScaleInstance(
1509 // width/g.getFontMetrics().stringWidth("Label"),
1510 // height/g.getFontMetrics().getHeight())));
1512 g.drawString(MessageManager.getString("label.label"), 0, 0);
1517 Color minCol = gcol.getMinColor();
1519 g.fillRect(0, 0, s1, height);
1522 g.setColor(Color.white);
1523 g.fillRect(s1, 0, e1 - s1, height);
1525 g.setColor(gcol.getMaxColor());
1526 g.fillRect(0, e1, width - e1, height);
1531 class ColorEditor extends AbstractCellEditor implements TableCellEditor,
1536 GraduatedColor currentGColor;
1538 FeatureColourChooser chooser;
1546 JColorChooser colorChooser;
1550 protected static final String EDIT = "edit";
1552 int selectedRow = 0;
1554 public ColorEditor(FeatureSettings me)
1557 // Set up the editor (from the table's point of view),
1558 // which is a button.
1559 // This button brings up the color chooser dialog,
1560 // which is the editor from the user's point of view.
1561 button = new JButton();
1562 button.setActionCommand(EDIT);
1563 button.addActionListener(this);
1564 button.setBorderPainted(false);
1565 // Set up the dialog that the button brings up.
1566 colorChooser = new JColorChooser();
1567 dialog = JColorChooser.createDialog(button, "Select new Colour", true, // modal
1568 colorChooser, this, // OK button handler
1569 null); // no CANCEL button handler
1573 * Handles events from the editor button and from the dialog's OK button.
1575 public void actionPerformed(ActionEvent e)
1578 if (EDIT.equals(e.getActionCommand()))
1580 // The user has clicked the cell, so
1581 // bring up the dialog.
1582 if (currentColor != null)
1584 // bring up simple color chooser
1585 button.setBackground(currentColor);
1586 colorChooser.setColor(currentColor);
1587 dialog.setVisible(true);
1591 // bring up graduated chooser.
1592 chooser = new FeatureColourChooser(me.fr, type);
1593 chooser.setRequestFocusEnabled(true);
1594 chooser.requestFocus();
1595 chooser.addActionListener(this);
1597 // Make the renderer reappear.
1598 fireEditingStopped();
1602 { // User pressed dialog's "OK" button.
1603 if (currentColor != null)
1605 currentColor = colorChooser.getColor();
1609 // class cast exceptions may be raised if the chooser created on a
1610 // non-graduated color
1611 currentGColor = (GraduatedColor) chooser.getLastColour();
1613 me.table.setValueAt(getCellEditorValue(), selectedRow, 1);
1614 fireEditingStopped();
1615 me.table.validate();
1619 // Implement the one CellEditor method that AbstractCellEditor doesn't.
1620 public Object getCellEditorValue()
1622 if (currentColor == null)
1624 return currentGColor;
1626 return currentColor;
1629 // Implement the one method defined by TableCellEditor.
1630 public Component getTableCellEditorComponent(JTable table, Object value,
1631 boolean isSelected, int row, int column)
1633 currentGColor = null;
1634 currentColor = null;
1635 this.selectedRow = row;
1636 type = me.table.getValueAt(row, 0).toString();
1637 button.setOpaque(true);
1638 button.setBackground(me.getBackground());
1639 if (value instanceof GraduatedColor)
1641 currentGColor = (GraduatedColor) value;
1642 JLabel btn = new JLabel();
1643 btn.setSize(button.getSize());
1644 FeatureSettings.renderGraduatedColor(btn, currentGColor);
1645 button.setBackground(btn.getBackground());
1646 button.setIcon(btn.getIcon());
1647 button.setText(btn.getText());
1652 button.setIcon(null);
1653 currentColor = (Color) value;
1654 button.setBackground(currentColor);