2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ 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.
23 import jalview.api.FeatureSettingsControllerI;
24 import jalview.bin.Cache;
25 import jalview.datamodel.SequenceFeature;
26 import jalview.datamodel.SequenceI;
27 import jalview.gui.Help.HelpId;
28 import jalview.io.JalviewFileChooser;
29 import jalview.schemes.AnnotationColourGradient;
30 import jalview.schemes.GraduatedColor;
31 import jalview.util.MessageManager;
32 import jalview.viewmodel.AlignmentViewport;
33 import jalview.ws.dbsources.das.api.jalviewSourceI;
35 import java.awt.BorderLayout;
36 import java.awt.Color;
37 import java.awt.Component;
39 import java.awt.Graphics;
40 import java.awt.GridLayout;
41 import java.awt.Rectangle;
42 import java.awt.event.ActionEvent;
43 import java.awt.event.ActionListener;
44 import java.awt.event.ItemEvent;
45 import java.awt.event.ItemListener;
46 import java.awt.event.MouseAdapter;
47 import java.awt.event.MouseEvent;
48 import java.awt.event.MouseMotionAdapter;
49 import java.beans.PropertyChangeEvent;
50 import java.beans.PropertyChangeListener;
52 import java.io.FileInputStream;
53 import java.io.FileOutputStream;
54 import java.io.InputStreamReader;
55 import java.io.OutputStreamWriter;
56 import java.io.PrintWriter;
57 import java.util.Hashtable;
58 import java.util.Iterator;
59 import java.util.List;
61 import java.util.Vector;
63 import javax.help.HelpSetException;
64 import javax.swing.AbstractCellEditor;
65 import javax.swing.BorderFactory;
66 import javax.swing.Icon;
67 import javax.swing.JButton;
68 import javax.swing.JCheckBox;
69 import javax.swing.JCheckBoxMenuItem;
70 import javax.swing.JColorChooser;
71 import javax.swing.JDialog;
72 import javax.swing.JInternalFrame;
73 import javax.swing.JLabel;
74 import javax.swing.JLayeredPane;
75 import javax.swing.JMenuItem;
76 import javax.swing.JOptionPane;
77 import javax.swing.JPanel;
78 import javax.swing.JPopupMenu;
79 import javax.swing.JScrollPane;
80 import javax.swing.JSlider;
81 import javax.swing.JTabbedPane;
82 import javax.swing.JTable;
83 import javax.swing.ListSelectionModel;
84 import javax.swing.SwingConstants;
85 import javax.swing.SwingUtilities;
86 import javax.swing.event.ChangeEvent;
87 import javax.swing.event.ChangeListener;
88 import javax.swing.table.AbstractTableModel;
89 import javax.swing.table.TableCellEditor;
90 import javax.swing.table.TableCellRenderer;
92 public class FeatureSettings extends JPanel implements
93 FeatureSettingsControllerI
95 DasSourceBrowser dassourceBrowser;
97 jalview.ws.DasSequenceFeatureFetcher dasFeatureFetcher;
99 JPanel settingsPane = new JPanel();
101 JPanel dasSettingsPane = new JPanel();
103 final FeatureRenderer fr;
105 public final AlignFrame af;
107 Object[][] originalData;
109 private float originalTransparency;
111 final JInternalFrame frame;
113 JScrollPane scrollPane = new JScrollPane();
119 JSlider transparency = new JSlider();
121 JPanel transPanel = new JPanel(new GridLayout(1, 2));
123 public FeatureSettings(AlignFrame af)
126 fr = af.getFeatureRenderer();
127 // allow transparency to be recovered
128 transparency.setMaximum(100 - (int) ((originalTransparency = fr
129 .getTransparency()) * 100));
134 } catch (Exception ex)
136 ex.printStackTrace();
142 public String getToolTipText(MouseEvent e)
144 if (table.columnAtPoint(e.getPoint()) == 0)
147 * Tooltip for feature name only
149 return JvSwingUtils.wrapTooltip(true, MessageManager
150 .getString("label.feature_settings_click_drag"));
155 table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));
156 table.setFont(new Font("Verdana", Font.PLAIN, 12));
157 table.setDefaultRenderer(Color.class, new ColorRenderer());
159 table.setDefaultEditor(Color.class, new ColorEditor(this));
161 table.setDefaultEditor(GraduatedColor.class, new ColorEditor(this));
162 table.setDefaultRenderer(GraduatedColor.class, new ColorRenderer());
163 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
165 table.addMouseListener(new MouseAdapter()
167 public void mousePressed(MouseEvent evt)
169 selectedRow = table.rowAtPoint(evt.getPoint());
170 if (SwingUtilities.isRightMouseButton(evt))
172 popupSort(selectedRow, (String) table.getValueAt(selectedRow, 0),
173 table.getValueAt(selectedRow, 1), fr.getMinMax(),
174 evt.getX(), evt.getY());
176 else if (evt.getClickCount() == 2)
178 fr.ap.alignFrame.avc.markColumnsContainingFeatures(
179 evt.isAltDown(), evt.isShiftDown() || evt.isMetaDown(),
181 (String) table.getValueAt(selectedRow, 0));
185 // isPopupTrigger fires on mouseReleased on Mac
187 public void mouseReleased(MouseEvent evt)
189 selectedRow = table.rowAtPoint(evt.getPoint());
190 if (evt.isPopupTrigger())
192 popupSort(selectedRow, (String) table.getValueAt(selectedRow, 0),
193 table.getValueAt(selectedRow, 1), fr.getMinMax(),
194 evt.getX(), evt.getY());
199 table.addMouseMotionListener(new MouseMotionAdapter()
201 public void mouseDragged(MouseEvent evt)
203 int newRow = table.rowAtPoint(evt.getPoint());
204 if (newRow != selectedRow && selectedRow != -1 && newRow != -1)
206 Object[] temp = new Object[3];
207 temp[0] = table.getValueAt(selectedRow, 0);
208 temp[1] = table.getValueAt(selectedRow, 1);
209 temp[2] = table.getValueAt(selectedRow, 2);
211 table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0);
212 table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1);
213 table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2);
215 table.setValueAt(temp[0], newRow, 0);
216 table.setValueAt(temp[1], newRow, 1);
217 table.setValueAt(temp[2], newRow, 2);
219 selectedRow = newRow;
223 // table.setToolTipText(JvSwingUtils.wrapTooltip(true,
224 // MessageManager.getString("label.feature_settings_click_drag")));
225 scrollPane.setViewportView(table);
227 dassourceBrowser = new DasSourceBrowser(this);
228 dasSettingsPane.add(dassourceBrowser, BorderLayout.CENTER);
230 if (af.getViewport().isShowSequenceFeatures() || !fr.hasRenderOrder())
232 fr.findAllFeatures(true); // display everything!
235 discoverAllFeatureData();
236 final PropertyChangeListener change;
237 final FeatureSettings fs = this;
238 fr.addPropertyChangeListener(change = new PropertyChangeListener()
240 public void propertyChange(PropertyChangeEvent evt)
242 if (!fs.resettingTable && !fs.handlingUpdate)
244 fs.handlingUpdate = true;
245 fs.resetTable(null); // new groups may be added with new seuqence
246 // feature types only
247 fs.handlingUpdate = false;
253 frame = new JInternalFrame();
254 frame.setContentPane(this);
255 if (new jalview.util.Platform().isAMac())
257 Desktop.addInternalFrame(frame,
258 MessageManager.getString("label.sequence_feature_settings"),
263 Desktop.addInternalFrame(frame,
264 MessageManager.getString("label.sequence_feature_settings"),
268 frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
270 public void internalFrameClosed(
271 javax.swing.event.InternalFrameEvent evt)
273 fr.removePropertyChangeListener(change);
274 dassourceBrowser.fs = null;
277 frame.setLayer(JLayeredPane.PALETTE_LAYER);
280 protected void popupSort(final int selectedRow, final String type,
281 final Object typeCol, final Hashtable minmax, int x, int y)
283 JPopupMenu men = new JPopupMenu(MessageManager.formatMessage(
284 "label.settings_for_param", new String[] { type }));
285 JMenuItem scr = new JMenuItem(
286 MessageManager.getString("label.sort_by_score"));
288 final FeatureSettings me = this;
289 scr.addActionListener(new ActionListener()
292 public void actionPerformed(ActionEvent e)
294 me.af.avc.sortAlignmentByFeatureScore(new String[] { type });
298 JMenuItem dens = new JMenuItem(
299 MessageManager.getString("label.sort_by_density"));
300 dens.addActionListener(new ActionListener()
303 public void actionPerformed(ActionEvent e)
305 me.af.avc.sortAlignmentByFeatureDensity(new String[] { type });
312 final Object typeMinMax = minmax.get(type);
314 * final JCheckBoxMenuItem chb = new JCheckBoxMenuItem("Vary Height"); //
315 * this is broken at the moment and isn't that useful anyway!
316 * chb.setSelected(minmax.get(type) != null); chb.addActionListener(new
319 * public void actionPerformed(ActionEvent e) {
320 * chb.setState(chb.getState()); if (chb.getState()) { minmax.put(type,
321 * null); } else { minmax.put(type, typeMinMax); } }
327 if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null)
329 // if (table.getValueAt(row, column));
330 // graduated colourschemes for those where minmax exists for the
331 // positional features
332 final JCheckBoxMenuItem mxcol = new JCheckBoxMenuItem(
334 mxcol.setSelected(!(typeCol instanceof Color));
336 mxcol.addActionListener(new ActionListener()
338 JColorChooser colorChooser;
340 public void actionPerformed(ActionEvent e)
342 if (e.getSource() == mxcol)
344 if (typeCol instanceof Color)
346 FeatureColourChooser fc = new FeatureColourChooser(me.fr,
348 fc.addActionListener(this);
352 // bring up simple color chooser
353 colorChooser = new JColorChooser();
354 JDialog dialog = JColorChooser.createDialog(me,
355 "Select new Colour", true, // modal
356 colorChooser, this, // OK button handler
357 null); // no CANCEL button handler
358 colorChooser.setColor(((GraduatedColor) typeCol)
360 dialog.setVisible(true);
365 if (e.getSource() instanceof FeatureColourChooser)
367 FeatureColourChooser fc = (FeatureColourChooser) e
369 table.setValueAt(fc.getLastColour(), selectedRow, 1);
374 // probably the color chooser!
375 table.setValueAt(colorChooser.getColor(), selectedRow, 1);
377 me.updateFeatureRenderer(
378 ((FeatureTableModel) table.getModel()).getData(),
387 JMenuItem selCols = new JMenuItem(
388 MessageManager.getString("label.select_columns_containing"));
389 selCols.addActionListener(new ActionListener()
393 public void actionPerformed(ActionEvent arg0)
395 fr.ap.alignFrame.avc.markColumnsContainingFeatures(false, false,
399 JMenuItem clearCols = new JMenuItem(
400 MessageManager.getString("label.select_columns_not_containing"));
401 clearCols.addActionListener(new ActionListener()
405 public void actionPerformed(ActionEvent arg0)
407 fr.ap.alignFrame.avc.markColumnsContainingFeatures(true, false,
413 men.show(table, x, y);
417 * true when Feature Settings are updating from feature renderer
419 private boolean handlingUpdate = false;
422 * contains a float[3] for each feature type string. created by setTableData
424 Hashtable typeWidth = null;
427 synchronized public void discoverAllFeatureData()
429 Vector allFeatures = new Vector();
430 Vector allGroups = new Vector();
431 SequenceFeature[] tmpfeatures;
433 for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
435 tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
436 .getSequenceFeatures();
437 if (tmpfeatures == null)
443 while (index < tmpfeatures.length)
445 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
451 if (tmpfeatures[index].getFeatureGroup() != null)
453 group = tmpfeatures[index].featureGroup;
454 if (!allGroups.contains(group))
456 allGroups.addElement(group);
457 checkGroupState(group);
461 if (!allFeatures.contains(tmpfeatures[index].getType()))
463 allFeatures.addElement(tmpfeatures[index].getType());
475 * Synchronise gui group list and check visibility of group
478 * @return true if group is visible
480 private boolean checkGroupState(String group)
482 boolean visible = fr.checkGroupVisibility(group, true);
484 if (groupPanel == null)
486 groupPanel = new JPanel();
489 boolean alreadyAdded = false;
490 for (int g = 0; g < groupPanel.getComponentCount(); g++)
492 if (((JCheckBox) groupPanel.getComponent(g)).getText().equals(group))
495 ((JCheckBox) groupPanel.getComponent(g)).setSelected(visible);
505 final String grp = group;
506 final JCheckBox check = new JCheckBox(group, visible);
507 check.setFont(new Font("Serif", Font.BOLD, 12));
508 check.addItemListener(new ItemListener()
510 public void itemStateChanged(ItemEvent evt)
512 fr.setGroupVisibility(check.getText(), check.isSelected());
513 af.alignPanel.getSeqPanel().seqCanvas.repaint();
514 if (af.alignPanel.overviewPanel != null)
516 af.alignPanel.overviewPanel.updateOverviewImage();
519 resetTable(new String[] { grp });
522 groupPanel.add(check);
526 boolean resettingTable = false;
528 synchronized void resetTable(String[] groupChanged)
530 if (resettingTable == true)
534 resettingTable = true;
535 typeWidth = new Hashtable();
536 // TODO: change avWidth calculation to 'per-sequence' average and use long
538 float[] avWidth = null;
539 SequenceFeature[] tmpfeatures;
540 String group = null, type;
541 Vector visibleChecks = new Vector();
543 // Find out which features should be visible depending on which groups
544 // are selected / deselected
545 // and recompute average width ordering
546 for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
549 tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
550 .getSequenceFeatures();
551 if (tmpfeatures == null)
557 while (index < tmpfeatures.length)
559 group = tmpfeatures[index].featureGroup;
561 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
567 if (group == null || checkGroupState(group))
569 type = tmpfeatures[index].getType();
570 if (!visibleChecks.contains(type))
572 visibleChecks.addElement(type);
575 if (!typeWidth.containsKey(tmpfeatures[index].getType()))
577 typeWidth.put(tmpfeatures[index].getType(),
578 avWidth = new float[3]);
582 avWidth = (float[]) typeWidth.get(tmpfeatures[index].getType());
585 if (tmpfeatures[index].getBegin() > tmpfeatures[index].getEnd())
587 avWidth[1] += 1 + tmpfeatures[index].getBegin()
588 - tmpfeatures[index].getEnd();
592 avWidth[1] += 1 + tmpfeatures[index].getEnd()
593 - tmpfeatures[index].getBegin();
599 int fSize = visibleChecks.size();
600 Object[][] data = new Object[fSize][3];
603 if (fr.hasRenderOrder())
607 fr.findAllFeatures(groupChanged != null); // prod to update
608 // colourschemes. but don't
610 // First add the checks in the previous render order,
611 // in case the window has been closed and reopened
613 List<String> frl = fr.getRenderOrder();
614 for (int ro = frl.size() - 1; ro > -1; ro--)
618 if (!visibleChecks.contains(type))
623 data[dataIndex][0] = type;
624 data[dataIndex][1] = fr.getFeatureStyle(type);
625 data[dataIndex][2] = new Boolean(af.getViewport()
626 .getFeaturesDisplayed().isVisible(type));
628 visibleChecks.removeElement(type);
632 fSize = visibleChecks.size();
633 for (int i = 0; i < fSize; i++)
635 // These must be extra features belonging to the group
636 // which was just selected
637 type = visibleChecks.elementAt(i).toString();
638 data[dataIndex][0] = type;
640 data[dataIndex][1] = fr.getFeatureStyle(type);
641 if (data[dataIndex][1] == null)
643 // "Colour has been updated in another view!!"
644 fr.clearRenderOrder();
648 data[dataIndex][2] = new Boolean(true);
652 if (originalData == null)
654 originalData = new Object[data.length][3];
655 for (int i = 0; i < data.length; i++)
657 System.arraycopy(data[i], 0, originalData[i], 0, 3);
661 table.setModel(new FeatureTableModel(data));
662 table.getColumnModel().getColumn(0).setPreferredWidth(200);
664 if (groupPanel != null)
666 groupPanel.setLayout(new GridLayout(
667 fr.getFeatureGroupsSize() / 4 + 1, 4));
669 groupPanel.validate();
670 bigPanel.add(groupPanel, BorderLayout.NORTH);
673 updateFeatureRenderer(data, groupChanged != null);
674 resettingTable = false;
678 * reorder data based on the featureRenderers global priority list.
682 private void ensureOrder(Object[][] data)
684 boolean sort = false;
685 float[] order = new float[data.length];
686 for (int i = 0; i < order.length; i++)
688 order[i] = fr.getOrder(data[i][0].toString());
691 order[i] = fr.setOrder(data[i][0].toString(), i / order.length);
695 sort = sort || order[i - 1] > order[i];
700 jalview.util.QuickSort.sort(order, data);
706 JalviewFileChooser chooser = new JalviewFileChooser(
707 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
708 new String[] { "fc" },
709 new String[] { "Sequence Feature Colours" },
710 "Sequence Feature Colours");
711 chooser.setFileView(new jalview.io.JalviewFileView());
712 chooser.setDialogTitle(MessageManager
713 .getString("label.load_feature_colours"));
714 chooser.setToolTipText(MessageManager.getString("action.load"));
716 int value = chooser.showOpenDialog(this);
718 if (value == JalviewFileChooser.APPROVE_OPTION)
720 File file = chooser.getSelectedFile();
724 InputStreamReader in = new InputStreamReader(new FileInputStream(
727 jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
728 jucs = jucs.unmarshal(in);
730 for (int i = jucs.getColourCount() - 1; i >= 0; i--)
733 jalview.schemabinding.version2.Colour newcol = jucs.getColour(i);
736 Color mincol = null, maxcol = null;
739 mincol = new Color(Integer.parseInt(newcol.getMinRGB(), 16));
740 maxcol = new Color(Integer.parseInt(newcol.getRGB(), 16));
742 } catch (Exception e)
744 Cache.log.warn("Couldn't parse out graduated feature color.",
747 GraduatedColor gcol = new GraduatedColor(mincol, maxcol,
748 newcol.getMin(), newcol.getMax());
749 if (newcol.hasAutoScale())
751 gcol.setAutoScaled(newcol.getAutoScale());
753 if (newcol.hasColourByLabel())
755 gcol.setColourByLabel(newcol.getColourByLabel());
757 if (newcol.hasThreshold())
759 gcol.setThresh(newcol.getThreshold());
760 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD); // default
762 if (newcol.getThreshType().length() > 0)
764 String ttyp = newcol.getThreshType();
765 if (ttyp.equalsIgnoreCase("NONE"))
767 gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD);
769 if (ttyp.equalsIgnoreCase("ABOVE"))
771 gcol.setThreshType(AnnotationColourGradient.ABOVE_THRESHOLD);
773 if (ttyp.equalsIgnoreCase("BELOW"))
775 gcol.setThreshType(AnnotationColourGradient.BELOW_THRESHOLD);
778 fr.setColour(name = newcol.getName(), gcol);
782 fr.setColour(name = jucs.getColour(i).getName(), new Color(
783 Integer.parseInt(jucs.getColour(i).getRGB(), 16)));
785 fr.setOrder(name, (i == 0) ? 0 : i / jucs.getColourCount());
790 Object[][] data = ((FeatureTableModel) table.getModel())
793 updateFeatureRenderer(data, false);
796 } catch (Exception ex)
798 System.out.println("Error loading User Colour File\n" + ex);
805 JalviewFileChooser chooser = new JalviewFileChooser(
806 jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
807 new String[] { "fc" },
808 new String[] { "Sequence Feature Colours" },
809 "Sequence Feature Colours");
810 chooser.setFileView(new jalview.io.JalviewFileView());
811 chooser.setDialogTitle(MessageManager
812 .getString("label.save_feature_colours"));
813 chooser.setToolTipText(MessageManager.getString("action.save"));
815 int value = chooser.showSaveDialog(this);
817 if (value == JalviewFileChooser.APPROVE_OPTION)
819 String choice = chooser.getSelectedFile().getPath();
820 jalview.schemabinding.version2.JalviewUserColours ucs = new jalview.schemabinding.version2.JalviewUserColours();
821 ucs.setSchemeName("Sequence Features");
824 PrintWriter out = new PrintWriter(new OutputStreamWriter(
825 new FileOutputStream(choice), "UTF-8"));
827 Set fr_colours = fr.getAllFeatureColours();
828 Iterator e = fr_colours.iterator();
829 float[] sortOrder = new float[fr_colours.size()];
830 String[] sortTypes = new String[fr_colours.size()];
834 sortTypes[i] = e.next().toString();
835 sortOrder[i] = fr.getOrder(sortTypes[i]);
838 jalview.util.QuickSort.sort(sortOrder, sortTypes);
842 for (i = 0; i < sortTypes.length; i++)
844 jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
845 col.setName(sortTypes[i]);
846 col.setRGB(jalview.util.Format.getHexString(fr.getColour(col
848 fcol = fr.getFeatureStyle(sortTypes[i]);
849 if (fcol instanceof GraduatedColor)
851 gcol = (GraduatedColor) fcol;
852 col.setMin(gcol.getMin());
853 col.setMax(gcol.getMax());
854 col.setMinRGB(jalview.util.Format.getHexString(gcol
856 col.setAutoScale(gcol.isAutoScale());
857 col.setThreshold(gcol.getThresh());
858 col.setColourByLabel(gcol.isColourByLabel());
859 switch (gcol.getThreshType())
861 case AnnotationColourGradient.NO_THRESHOLD:
862 col.setThreshType("NONE");
864 case AnnotationColourGradient.ABOVE_THRESHOLD:
865 col.setThreshType("ABOVE");
867 case AnnotationColourGradient.BELOW_THRESHOLD:
868 col.setThreshType("BELOW");
876 } catch (Exception ex)
878 ex.printStackTrace();
883 public void invertSelection()
885 for (int i = 0; i < table.getRowCount(); i++)
887 Boolean value = (Boolean) table.getValueAt(i, 2);
889 table.setValueAt(new Boolean(!value.booleanValue()), i, 2);
893 public void orderByAvWidth()
895 if (table == null || table.getModel() == null)
899 Object[][] data = ((FeatureTableModel) table.getModel()).getData();
900 float[] width = new float[data.length];
904 for (int i = 0; i < data.length; i++)
906 awidth = (float[]) typeWidth.get(data[i][0]);
909 width[i] = awidth[1] / awidth[0];// *awidth[0]*awidth[2]; - better
910 // weight - but have to make per
911 // sequence, too (awidth[2])
912 // if (width[i]==1) // hack to distinguish single width sequences.
924 boolean sort = false;
925 for (int i = 0; i < width.length; i++)
927 // awidth = (float[]) typeWidth.get(data[i][0]);
930 width[i] = fr.getOrder(data[i][0].toString());
933 width[i] = fr.setOrder(data[i][0].toString(), i / data.length);
938 width[i] /= max; // normalize
939 fr.setOrder(data[i][0].toString(), width[i]); // store for later
943 sort = sort || width[i - 1] > width[i];
948 jalview.util.QuickSort.sort(width, data);
949 // update global priority order
952 updateFeatureRenderer(data, false);
960 frame.setClosed(true);
961 } catch (Exception exe)
967 public void updateFeatureRenderer(Object[][] data)
969 updateFeatureRenderer(data, true);
972 private void updateFeatureRenderer(Object[][] data, boolean visibleNew)
974 fr.setFeaturePriority(data, visibleNew);
975 af.alignPanel.paintAlignment(true);
978 int selectedRow = -1;
980 JTabbedPane tabbedPane = new JTabbedPane();
982 BorderLayout borderLayout1 = new BorderLayout();
984 BorderLayout borderLayout2 = new BorderLayout();
986 BorderLayout borderLayout3 = new BorderLayout();
988 JPanel bigPanel = new JPanel();
990 BorderLayout borderLayout4 = new BorderLayout();
992 JButton invert = new JButton();
994 JPanel buttonPanel = new JPanel();
996 JButton cancel = new JButton();
998 JButton ok = new JButton();
1000 JButton loadColours = new JButton();
1002 JButton saveColours = new JButton();
1004 JPanel dasButtonPanel = new JPanel();
1006 JButton fetchDAS = new JButton();
1008 JButton saveDAS = new JButton();
1010 JButton cancelDAS = new JButton();
1012 JButton optimizeOrder = new JButton();
1014 JButton sortByScore = new JButton();
1016 JButton sortByDens = new JButton();
1018 JButton help = new JButton();
1020 JPanel transbuttons = new JPanel(new GridLayout(5, 1));
1022 private void jbInit() throws Exception
1024 this.setLayout(borderLayout1);
1025 settingsPane.setLayout(borderLayout2);
1026 dasSettingsPane.setLayout(borderLayout3);
1027 bigPanel.setLayout(borderLayout4);
1028 invert.setFont(JvSwingUtils.getLabelFont());
1029 invert.setText(MessageManager.getString("label.invert_selection"));
1030 invert.addActionListener(new ActionListener()
1032 public void actionPerformed(ActionEvent e)
1037 optimizeOrder.setFont(JvSwingUtils.getLabelFont());
1038 optimizeOrder.setText(MessageManager.getString("label.optimise_order"));
1039 optimizeOrder.addActionListener(new ActionListener()
1041 public void actionPerformed(ActionEvent e)
1046 sortByScore.setFont(JvSwingUtils.getLabelFont());
1048 .setText(MessageManager.getString("label.seq_sort_by_score"));
1049 sortByScore.addActionListener(new ActionListener()
1051 public void actionPerformed(ActionEvent e)
1053 af.avc.sortAlignmentByFeatureScore(null);
1056 sortByDens.setFont(JvSwingUtils.getLabelFont());
1057 sortByDens.setText(MessageManager
1058 .getString("label.sequence_sort_by_density"));
1059 sortByDens.addActionListener(new ActionListener()
1061 public void actionPerformed(ActionEvent e)
1063 af.avc.sortAlignmentByFeatureDensity(null);
1066 help.setFont(JvSwingUtils.getLabelFont());
1067 help.setText(MessageManager.getString("action.help"));
1068 help.addActionListener(new ActionListener()
1070 public void actionPerformed(ActionEvent e)
1074 Help.showHelpWindow(HelpId.SequenceFeatureSettings);
1075 } catch (HelpSetException e1)
1077 e1.printStackTrace();
1081 help.setFont(JvSwingUtils.getLabelFont());
1082 help.setText(MessageManager.getString("action.help"));
1083 help.addActionListener(new ActionListener()
1085 public void actionPerformed(ActionEvent e)
1089 Help.showHelpWindow(HelpId.SequenceFeatureSettings);
1090 } catch (HelpSetException e1)
1092 e1.printStackTrace();
1096 cancel.setFont(JvSwingUtils.getLabelFont());
1097 cancel.setText(MessageManager.getString("action.cancel"));
1098 cancel.addActionListener(new ActionListener()
1100 public void actionPerformed(ActionEvent e)
1102 fr.setTransparency(originalTransparency);
1103 updateFeatureRenderer(originalData);
1107 ok.setFont(JvSwingUtils.getLabelFont());
1108 ok.setText(MessageManager.getString("action.ok"));
1109 ok.addActionListener(new ActionListener()
1111 public void actionPerformed(ActionEvent e)
1116 loadColours.setFont(JvSwingUtils.getLabelFont());
1117 loadColours.setText(MessageManager.getString("label.load_colours"));
1118 loadColours.addActionListener(new ActionListener()
1120 public void actionPerformed(ActionEvent e)
1125 saveColours.setFont(JvSwingUtils.getLabelFont());
1126 saveColours.setText(MessageManager.getString("label.save_colours"));
1127 saveColours.addActionListener(new ActionListener()
1129 public void actionPerformed(ActionEvent e)
1134 transparency.addChangeListener(new ChangeListener()
1136 public void stateChanged(ChangeEvent evt)
1138 fr.setTransparency((100 - transparency.getValue()) / 100f);
1139 af.alignPanel.paintAlignment(true);
1143 transparency.setMaximum(70);
1144 transparency.setToolTipText(MessageManager
1145 .getString("label.transparency_tip"));
1146 fetchDAS.setText(MessageManager.getString("label.fetch_das_features"));
1147 fetchDAS.addActionListener(new ActionListener()
1149 public void actionPerformed(ActionEvent e)
1151 fetchDAS_actionPerformed(e);
1154 saveDAS.setText(MessageManager.getString("action.save_as_default"));
1155 saveDAS.addActionListener(new ActionListener()
1157 public void actionPerformed(ActionEvent e)
1159 saveDAS_actionPerformed(e);
1162 dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
1163 dasSettingsPane.setBorder(null);
1164 cancelDAS.setEnabled(false);
1165 cancelDAS.setText(MessageManager.getString("action.cancel_fetch"));
1166 cancelDAS.addActionListener(new ActionListener()
1168 public void actionPerformed(ActionEvent e)
1170 cancelDAS_actionPerformed(e);
1173 this.add(tabbedPane, java.awt.BorderLayout.CENTER);
1174 tabbedPane.addTab(MessageManager.getString("label.feature_settings"),
1176 tabbedPane.addTab(MessageManager.getString("label.das_settings"),
1178 bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
1179 transbuttons.add(optimizeOrder);
1180 transbuttons.add(invert);
1181 transbuttons.add(sortByScore);
1182 transbuttons.add(sortByDens);
1183 transbuttons.add(help);
1184 JPanel sliderPanel = new JPanel();
1185 sliderPanel.add(transparency);
1186 transPanel.add(transparency);
1187 transPanel.add(transbuttons);
1188 buttonPanel.add(ok);
1189 buttonPanel.add(cancel);
1190 buttonPanel.add(loadColours);
1191 buttonPanel.add(saveColours);
1192 bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
1193 dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
1194 dasButtonPanel.add(fetchDAS);
1195 dasButtonPanel.add(cancelDAS);
1196 dasButtonPanel.add(saveDAS);
1197 settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);
1198 settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
1201 public void fetchDAS_actionPerformed(ActionEvent e)
1203 fetchDAS.setEnabled(false);
1204 cancelDAS.setEnabled(true);
1205 dassourceBrowser.setGuiEnabled(false);
1206 Vector selectedSources = dassourceBrowser.getSelectedSources();
1207 doDasFeatureFetch(selectedSources, true, true);
1211 * get the features from selectedSources for all or the current selection
1213 * @param selectedSources
1214 * @param checkDbRefs
1215 * @param promptFetchDbRefs
1217 private void doDasFeatureFetch(List<jalviewSourceI> selectedSources,
1218 boolean checkDbRefs, boolean promptFetchDbRefs)
1220 SequenceI[] dataset, seqs;
1222 AlignmentViewport vp = af.getViewport();
1223 if (vp.getSelectionGroup() != null
1224 && vp.getSelectionGroup().getSize() > 0)
1226 iSize = vp.getSelectionGroup().getSize();
1227 dataset = new SequenceI[iSize];
1228 seqs = vp.getSelectionGroup().getSequencesInOrder(vp.getAlignment());
1232 iSize = vp.getAlignment().getHeight();
1233 seqs = vp.getAlignment().getSequencesArray();
1236 dataset = new SequenceI[iSize];
1237 for (int i = 0; i < iSize; i++)
1239 dataset[i] = seqs[i].getDatasetSequence();
1242 cancelDAS.setEnabled(true);
1243 dasFeatureFetcher = new jalview.ws.DasSequenceFeatureFetcher(dataset,
1244 this, selectedSources, checkDbRefs, promptFetchDbRefs);
1245 af.getViewport().setShowSequenceFeatures(true);
1246 af.showSeqFeatures.setSelected(true);
1250 * blocking call to initialise the das source browser
1252 public void initDasSources()
1254 dassourceBrowser.initDasSources();
1258 * examine the current list of das sources and return any matching the given
1259 * nicknames in sources
1262 * Vector of Strings to resolve to DAS source nicknames.
1263 * @return sources that are present in source list.
1265 public List<jalviewSourceI> resolveSourceNicknames(Vector sources)
1267 return dassourceBrowser.sourceRegistry.resolveSourceNicknames(sources);
1271 * get currently selected das sources. ensure you have called initDasSources
1272 * before calling this.
1274 * @return vector of selected das source nicknames
1276 public Vector getSelectedSources()
1278 return dassourceBrowser.getSelectedSources();
1282 * properly initialise DAS fetcher and then initiate a new thread to fetch
1283 * features from the named sources (rather than any turned on by default)
1287 * if true then runs in same thread, otherwise passes to the Swing
1290 public void fetchDasFeatures(Vector sources, boolean block)
1293 List<jalviewSourceI> resolved = dassourceBrowser.sourceRegistry
1294 .resolveSourceNicknames(sources);
1295 if (resolved.size() == 0)
1297 resolved = dassourceBrowser.getSelectedSources();
1299 if (resolved.size() > 0)
1301 final List<jalviewSourceI> dassources = resolved;
1302 fetchDAS.setEnabled(false);
1303 // cancelDAS.setEnabled(true); doDasFetch does this.
1304 Runnable fetcher = new Runnable()
1309 doDasFeatureFetch(dassources, true, false);
1319 SwingUtilities.invokeLater(fetcher);
1324 public void saveDAS_actionPerformed(ActionEvent e)
1327 .saveProperties(jalview.bin.Cache.applicationProperties);
1330 public void complete()
1332 fetchDAS.setEnabled(true);
1333 cancelDAS.setEnabled(false);
1334 dassourceBrowser.setGuiEnabled(true);
1338 public void cancelDAS_actionPerformed(ActionEvent e)
1340 if (dasFeatureFetcher != null)
1342 dasFeatureFetcher.cancel();
1347 public void noDasSourceActive()
1351 .showInternalConfirmDialog(
1354 .getString("label.no_das_sources_selected_warn"),
1356 .getString("label.no_das_sources_selected_title"),
1357 JOptionPane.DEFAULT_OPTION,
1358 JOptionPane.INFORMATION_MESSAGE);
1361 // ///////////////////////////////////////////////////////////////////////
1362 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
1363 // ///////////////////////////////////////////////////////////////////////
1364 class FeatureTableModel extends AbstractTableModel
1366 FeatureTableModel(Object[][] data)
1371 private String[] columnNames = {
1372 MessageManager.getString("label.feature_type"),
1373 MessageManager.getString("action.colour"),
1374 MessageManager.getString("label.display") };
1376 private Object[][] data;
1378 public Object[][] getData()
1383 public void setData(Object[][] data)
1388 public int getColumnCount()
1390 return columnNames.length;
1393 public Object[] getRow(int row)
1398 public int getRowCount()
1403 public String getColumnName(int col)
1405 return columnNames[col];
1408 public Object getValueAt(int row, int col)
1410 return data[row][col];
1413 public Class getColumnClass(int c)
1415 return getValueAt(0, c).getClass();
1418 public boolean isCellEditable(int row, int col)
1420 return col == 0 ? false : true;
1423 public void setValueAt(Object value, int row, int col)
1425 data[row][col] = value;
1426 fireTableCellUpdated(row, col);
1427 updateFeatureRenderer(data);
1432 class ColorRenderer extends JLabel implements TableCellRenderer
1434 javax.swing.border.Border unselectedBorder = null;
1436 javax.swing.border.Border selectedBorder = null;
1438 final String baseTT = "Click to edit, right/apple click for menu.";
1440 public ColorRenderer()
1442 setOpaque(true); // MUST do this for background to show up.
1443 setHorizontalTextPosition(SwingConstants.CENTER);
1444 setVerticalTextPosition(SwingConstants.CENTER);
1447 public Component getTableCellRendererComponent(JTable table,
1448 Object color, boolean isSelected, boolean hasFocus, int row,
1451 // JLabel comp = new JLabel();
1455 // setBounds(getBounds());
1457 setToolTipText(baseTT);
1458 setBackground(table.getBackground());
1459 if (color instanceof GraduatedColor)
1461 Rectangle cr = table.getCellRect(row, column, false);
1462 FeatureSettings.renderGraduatedColor(this, (GraduatedColor) color,
1463 (int) cr.getWidth(), (int) cr.getHeight());
1470 newColor = (Color) color;
1472 setBackground(newColor);
1473 // comp.setToolTipText("RGB value: " + newColor.getRed() + ", "
1474 // + newColor.getGreen() + ", " + newColor.getBlue());
1478 if (selectedBorder == null)
1480 selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1481 table.getSelectionBackground());
1484 setBorder(selectedBorder);
1488 if (unselectedBorder == null)
1490 unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1491 table.getBackground());
1494 setBorder(unselectedBorder);
1502 * update comp using rendering settings from gcol
1507 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol)
1509 int w = comp.getWidth(), h = comp.getHeight();
1512 w = (int) comp.getPreferredSize().getWidth();
1513 h = (int) comp.getPreferredSize().getHeight();
1520 renderGraduatedColor(comp, gcol, w, h);
1523 public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol,
1526 boolean thr = false;
1529 if (gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD)
1533 tt += "Thresholded (Above " + gcol.getThresh() + ") ";
1535 if (gcol.getThreshType() == AnnotationColourGradient.BELOW_THRESHOLD)
1539 tt += "Thresholded (Below " + gcol.getThresh() + ") ";
1541 if (gcol.isColourByLabel())
1543 tt = "Coloured by label text. " + tt;
1553 Color newColor = gcol.getMaxColor();
1554 comp.setBackground(newColor);
1555 // System.err.println("Width is " + w / 2);
1556 Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w, h, thr);
1557 comp.setIcon(ficon);
1558 // tt+="RGB value: Max (" + newColor.getRed() + ", "
1559 // + newColor.getGreen() + ", " + newColor.getBlue()
1560 // + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen()
1561 // + ", " + minCol.getBlue() + ")");
1563 comp.setHorizontalAlignment(SwingConstants.CENTER);
1565 if (tt.length() > 0)
1567 if (comp.getToolTipText() == null)
1569 comp.setToolTipText(tt);
1573 comp.setToolTipText(tt + " " + comp.getToolTipText());
1579 class FeatureIcon implements Icon
1581 GraduatedColor gcol;
1585 boolean midspace = false;
1587 int width = 50, height = 20;
1589 int s1, e1; // start and end of midpoint band for thresholded symbol
1591 Color mpcolour = Color.white;
1593 FeatureIcon(GraduatedColor gfc, Color bg, int w, int h, boolean mspace)
1612 public int getIconWidth()
1617 public int getIconHeight()
1622 public void paintIcon(Component c, Graphics g, int x, int y)
1625 if (gcol.isColourByLabel())
1628 g.fillRect(0, 0, width, height);
1629 // need an icon here.
1630 g.setColor(gcol.getMaxColor());
1632 g.setFont(new Font("Verdana", Font.PLAIN, 9));
1634 // g.setFont(g.getFont().deriveFont(
1635 // AffineTransform.getScaleInstance(
1636 // width/g.getFontMetrics().stringWidth("Label"),
1637 // height/g.getFontMetrics().getHeight())));
1639 g.drawString(MessageManager.getString("label.label"), 0, 0);
1644 Color minCol = gcol.getMinColor();
1646 g.fillRect(0, 0, s1, height);
1649 g.setColor(Color.white);
1650 g.fillRect(s1, 0, e1 - s1, height);
1652 g.setColor(gcol.getMaxColor());
1653 g.fillRect(0, e1, width - e1, height);
1658 class ColorEditor extends AbstractCellEditor implements TableCellEditor,
1663 GraduatedColor currentGColor;
1665 FeatureColourChooser chooser;
1673 JColorChooser colorChooser;
1677 protected static final String EDIT = "edit";
1679 int selectedRow = 0;
1681 public ColorEditor(FeatureSettings me)
1684 // Set up the editor (from the table's point of view),
1685 // which is a button.
1686 // This button brings up the color chooser dialog,
1687 // which is the editor from the user's point of view.
1688 button = new JButton();
1689 button.setActionCommand(EDIT);
1690 button.addActionListener(this);
1691 button.setBorderPainted(false);
1692 // Set up the dialog that the button brings up.
1693 colorChooser = new JColorChooser();
1694 dialog = JColorChooser.createDialog(button, "Select new Colour", true, // modal
1695 colorChooser, this, // OK button handler
1696 null); // no CANCEL button handler
1700 * Handles events from the editor button and from the dialog's OK button.
1702 public void actionPerformed(ActionEvent e)
1705 if (EDIT.equals(e.getActionCommand()))
1707 // The user has clicked the cell, so
1708 // bring up the dialog.
1709 if (currentColor != null)
1711 // bring up simple color chooser
1712 button.setBackground(currentColor);
1713 colorChooser.setColor(currentColor);
1714 dialog.setVisible(true);
1718 // bring up graduated chooser.
1719 chooser = new FeatureColourChooser(me.fr, type);
1720 chooser.setRequestFocusEnabled(true);
1721 chooser.requestFocus();
1722 chooser.addActionListener(this);
1724 // Make the renderer reappear.
1725 fireEditingStopped();
1729 { // User pressed dialog's "OK" button.
1730 if (currentColor != null)
1732 currentColor = colorChooser.getColor();
1736 // class cast exceptions may be raised if the chooser created on a
1737 // non-graduated color
1738 currentGColor = (GraduatedColor) chooser.getLastColour();
1740 me.table.setValueAt(getCellEditorValue(), selectedRow, 1);
1741 fireEditingStopped();
1742 me.table.validate();
1746 // Implement the one CellEditor method that AbstractCellEditor doesn't.
1747 public Object getCellEditorValue()
1749 if (currentColor == null)
1751 return currentGColor;
1753 return currentColor;
1756 // Implement the one method defined by TableCellEditor.
1757 public Component getTableCellEditorComponent(JTable table, Object value,
1758 boolean isSelected, int row, int column)
1760 currentGColor = null;
1761 currentColor = null;
1762 this.selectedRow = row;
1763 type = me.table.getValueAt(row, 0).toString();
1764 button.setOpaque(true);
1765 button.setBackground(me.getBackground());
1766 if (value instanceof GraduatedColor)
1768 currentGColor = (GraduatedColor) value;
1769 JLabel btn = new JLabel();
1770 btn.setSize(button.getSize());
1771 FeatureSettings.renderGraduatedColor(btn, currentGColor);
1772 button.setBackground(btn.getBackground());
1773 button.setIcon(btn.getIcon());
1774 button.setText(btn.getText());
1779 button.setIcon(null);
1780 currentColor = (Color) value;
1781 button.setBackground(currentColor);