2 * Jalview - A Sequence Alignment Editor and Viewer
\r
3 * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
\r
5 * This program is free software; you can redistribute it and/or
\r
6 * modify it under the terms of the GNU General Public License
\r
7 * as published by the Free Software Foundation; either version 2
\r
8 * of the License, or (at your option) any later version.
\r
10 * This program is distributed in the hope that it will be useful,
\r
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
13 * GNU General Public License for more details.
\r
15 * You should have received a copy of the GNU General Public License
\r
16 * along with this program; if not, write to the Free Software
\r
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
\r
19 package jalview.gui;
\r
25 import java.awt.event.*;
\r
26 import javax.swing.*;
\r
27 import javax.swing.event.*;
\r
28 import javax.swing.table.*;
\r
30 import jalview.datamodel.*;
\r
31 import jalview.io.*;
\r
33 public class FeatureSettings
\r
36 DasSourceBrowser dassourceBrowser;
\r
37 jalview.io.DasSequenceFeatureFetcher dasFeatureFetcher;
\r
38 JPanel settingsPane = new JPanel();
\r
39 JPanel dasSettingsPane = new JPanel();
\r
41 final FeatureRenderer fr;
\r
42 public final AlignFrame af;
\r
43 Object[][] originalData;
\r
44 final JInternalFrame frame;
\r
45 JScrollPane scrollPane = new JScrollPane();
\r
48 JSlider transparency = new JSlider();
\r
50 JPanel transPanel = new JPanel(new FlowLayout());
\r
52 public FeatureSettings(AlignFrame af)
\r
55 fr = af.getFeatureRenderer();
\r
57 transparency.setMaximum(100 - (int) (fr.transparency * 100));
\r
63 catch (Exception ex)
\r
65 ex.printStackTrace();
\r
68 table = new JTable();
\r
69 table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));
\r
70 table.setFont(new Font("Verdana", Font.PLAIN, 12));
\r
71 table.setDefaultRenderer(Color.class,
\r
72 new ColorRenderer());
\r
74 table.setDefaultEditor(Color.class,
\r
77 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
\r
79 table.addMouseListener(new MouseAdapter()
\r
81 public void mousePressed(MouseEvent evt)
\r
83 selectedRow = table.rowAtPoint(evt.getPoint());
\r
87 table.addMouseMotionListener(new MouseMotionAdapter()
\r
89 public void mouseDragged(MouseEvent evt)
\r
91 int newRow = table.rowAtPoint(evt.getPoint());
\r
92 if (newRow != selectedRow
\r
93 && selectedRow != -1
\r
96 Object[] temp = new Object[3];
\r
97 temp[0] = table.getValueAt(selectedRow, 0);
\r
98 temp[1] = table.getValueAt(selectedRow, 1);
\r
99 temp[2] = table.getValueAt(selectedRow, 2);
\r
101 table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0);
\r
102 table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1);
\r
103 table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2);
\r
105 table.setValueAt(temp[0], newRow, 0);
\r
106 table.setValueAt(temp[1], newRow, 1);
\r
107 table.setValueAt(temp[2], newRow, 2);
\r
109 selectedRow = newRow;
\r
114 scrollPane.setViewportView(table);
\r
116 dassourceBrowser = new DasSourceBrowser();
\r
117 dasSettingsPane.add(dassourceBrowser, BorderLayout.CENTER);
\r
119 if (af.getViewport().featuresDisplayed == null || fr.renderOrder == null)
\r
121 fr.findAllFeatures();
\r
126 frame = new JInternalFrame();
\r
127 frame.setContentPane(this);
\r
128 Desktop.addInternalFrame(frame, "Sequence Feature Settings", 400, 450);
\r
129 frame.setLayer(JLayeredPane.PALETTE_LAYER);
\r
132 synchronized public void setTableData()
\r
134 if (fr.featureGroups == null)
\r
136 fr.featureGroups = new Hashtable();
\r
139 Vector allFeatures = new Vector();
\r
140 Vector allGroups = new Vector();
\r
141 SequenceFeature[] tmpfeatures;
\r
144 for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)
\r
146 if (af.getViewport().alignment.getSequenceAt(i).getDatasetSequence().
\r
147 getSequenceFeatures() == null)
\r
152 tmpfeatures = af.getViewport().alignment.getSequenceAt(i).
\r
153 getDatasetSequence().getSequenceFeatures();
\r
156 while (index < tmpfeatures.length)
\r
158 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
\r
164 if (tmpfeatures[index].getFeatureGroup() != null)
\r
166 group = tmpfeatures[index].featureGroup;
\r
167 if (!allGroups.contains(group))
\r
169 allGroups.addElement(group);
\r
171 boolean visible = true;
\r
172 if (fr.featureGroups.containsKey(group))
\r
174 visible = ( (Boolean) fr.featureGroups.get(group)).booleanValue();
\r
177 if (groupPanel == null)
\r
179 groupPanel = new JPanel();
\r
182 boolean alreadyAdded = false;
\r
183 for (int g = 0; g < groupPanel.getComponentCount(); g++)
\r
185 if ( ( (JCheckBox) groupPanel.getComponent(g))
\r
186 .getText().equals(group))
\r
188 alreadyAdded = true;
\r
198 fr.featureGroups.put(group, new Boolean(visible));
\r
200 final JCheckBox check = new JCheckBox(group, visible);
\r
201 check.setFont(new Font("Serif", Font.BOLD, 12));
\r
202 check.addItemListener(new ItemListener()
\r
204 public void itemStateChanged(ItemEvent evt)
\r
206 fr.featureGroups.put(check.getText(),
\r
207 new Boolean(check.isSelected()));
\r
208 af.alignPanel.seqPanel.seqCanvas.repaint();
\r
209 if (af.alignPanel.overviewPanel != null)
\r
211 af.alignPanel.overviewPanel.updateOverviewImage();
\r
217 groupPanel.add(check);
\r
221 if (!allFeatures.contains(tmpfeatures[index].getType()))
\r
223 allFeatures.addElement(tmpfeatures[index].getType());
\r
234 void resetTable(boolean groupsChanged)
\r
236 SequenceFeature[] tmpfeatures;
\r
237 String group = null, type;
\r
238 Vector visibleChecks = new Vector();
\r
240 //Find out which features should be visible depending on which groups
\r
241 //are selected / deselected
\r
242 for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)
\r
245 tmpfeatures = af.getViewport().alignment.getSequenceAt(i).
\r
246 getDatasetSequence().getSequenceFeatures();
\r
247 if (tmpfeatures == null)
\r
253 while (index < tmpfeatures.length)
\r
255 group = tmpfeatures[index].featureGroup;
\r
257 if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
\r
263 if (group == null || fr.featureGroups.get(group) == null ||
\r
264 ( (Boolean) fr.featureGroups.get(group)).booleanValue())
\r
266 type = tmpfeatures[index].getType();
\r
267 if (!visibleChecks.contains(type))
\r
269 visibleChecks.addElement(type);
\r
276 int fSize = visibleChecks.size();
\r
277 Object[][] data = new Object[fSize][3];
\r
280 if (fr.renderOrder != null)
\r
282 //First add the checks in the previous render order,
\r
283 //in case the window has been closed and reopened
\r
284 for (int ro = fr.renderOrder.length - 1; ro > -1; ro--)
\r
286 type = fr.renderOrder[ro];
\r
288 if (!visibleChecks.contains(type))
\r
293 data[dataIndex][0] = type;
\r
294 data[dataIndex][1] = fr.getColour(type);
\r
295 data[dataIndex][2] = new Boolean(af.getViewport().featuresDisplayed.
\r
296 containsKey(type));
\r
298 visibleChecks.removeElement(type);
\r
302 fSize = visibleChecks.size();
\r
303 for (int i = 0; i < fSize; i++)
\r
305 //These must be extra features belonging to the group
\r
306 //which was just selected
\r
307 type = visibleChecks.elementAt(i).toString();
\r
308 data[dataIndex][0] = type;
\r
310 data[dataIndex][1] = fr.getColour(type);
\r
311 if (data[dataIndex][1] == null)
\r
313 //"Colour has been updated in another view!!"
\r
314 fr.renderOrder = null;
\r
318 data[dataIndex][2] = new Boolean(true);
\r
322 if (originalData == null)
\r
324 originalData = new Object[data.length][3];
\r
325 System.arraycopy(data, 0, originalData, 0, data.length);
\r
328 table.setModel(new FeatureTableModel(data));
\r
329 table.getColumnModel().getColumn(0).setPreferredWidth(200);
\r
331 if (groupPanel != null)
\r
333 groupPanel.setLayout(
\r
334 new GridLayout(fr.featureGroups.size() / 4 + 1, 4));
\r
336 groupPanel.validate();
\r
337 bigPanel.add(groupPanel, BorderLayout.NORTH);
\r
340 updateFeatureRenderer(data);
\r
346 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
\r
348 "LAST_DIRECTORY"), new String[]
\r
351 {"Sequence Feature Colours"}, "Sequence Feature Colours");
\r
352 chooser.setFileView(new jalview.io.JalviewFileView());
\r
353 chooser.setDialogTitle("Load Feature Colours");
\r
354 chooser.setToolTipText("Load");
\r
356 int value = chooser.showOpenDialog(this);
\r
358 if (value == JalviewFileChooser.APPROVE_OPTION)
\r
360 File file = chooser.getSelectedFile();
\r
364 InputStreamReader in = new InputStreamReader(new FileInputStream(
\r
367 jalview.binding.JalviewUserColours jucs = new jalview.binding.
\r
368 JalviewUserColours();
\r
369 jucs = (jalview.binding.JalviewUserColours) jucs.unmarshal(in);
\r
371 for (int i = 0; i < jucs.getColourCount(); i++)
\r
373 fr.setColour(jucs.getColour(i).getName(),
\r
374 new Color(Integer.parseInt(jucs.getColour(i).getRGB(),
\r
379 af.alignPanel.paintAlignment(true);
\r
381 catch (Exception ex)
\r
383 System.out.println("Error loading User Colour File\n" + ex);
\r
390 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
\r
392 "LAST_DIRECTORY"), new String[]
\r
395 {"Sequence Feature Colours"}, "Sequence Feature Colours");
\r
396 chooser.setFileView(new jalview.io.JalviewFileView());
\r
397 chooser.setDialogTitle("Save Feature Colour Scheme");
\r
398 chooser.setToolTipText("Save");
\r
400 int value = chooser.showSaveDialog(this);
\r
402 if (value == JalviewFileChooser.APPROVE_OPTION)
\r
404 String choice = chooser.getSelectedFile().getPath();
\r
405 jalview.binding.JalviewUserColours ucs = new jalview.binding.
\r
406 JalviewUserColours();
\r
407 ucs.setSchemeName("Sequence Features");
\r
410 PrintWriter out = new PrintWriter(new OutputStreamWriter(
\r
411 new FileOutputStream(choice), "UTF-8"));
\r
413 Enumeration e = fr.featureColours.keys();
\r
414 while (e.hasMoreElements())
\r
416 jalview.binding.Colour col = new jalview.binding.Colour();
\r
417 col.setName(e.nextElement().toString());
\r
418 col.setRGB(jalview.util.Format.getHexString(
\r
419 fr.getColour(col.getName())));
\r
420 ucs.addColour(col);
\r
426 catch (Exception ex)
\r
428 ex.printStackTrace();
\r
433 public void invertSelection()
\r
435 for (int i = 0; i < table.getRowCount(); i++)
\r
437 Boolean value = (Boolean) table.getValueAt(i, 2);
\r
440 new Boolean(!value.booleanValue()),
\r
445 public void close()
\r
449 frame.setClosed(true);
\r
451 catch (Exception exe)
\r
456 public void updateFeatureRenderer(Object[][] data)
\r
458 fr.setFeaturePriority(data);
\r
459 af.alignPanel.paintAlignment(true);
\r
461 if (af.alignPanel.overviewPanel != null)
\r
463 af.alignPanel.overviewPanel.updateOverviewImage();
\r
467 int selectedRow = -1;
\r
468 JTabbedPane tabbedPane = new JTabbedPane();
\r
469 BorderLayout borderLayout1 = new BorderLayout();
\r
470 BorderLayout borderLayout2 = new BorderLayout();
\r
471 BorderLayout borderLayout3 = new BorderLayout();
\r
472 JPanel bigPanel = new JPanel();
\r
473 BorderLayout borderLayout4 = new BorderLayout();
\r
474 JButton invert = new JButton();
\r
475 JPanel buttonPanel = new JPanel();
\r
476 JButton cancel = new JButton();
\r
477 JButton ok = new JButton();
\r
478 JButton loadColours = new JButton();
\r
479 JButton saveColours = new JButton();
\r
480 JPanel dasButtonPanel = new JPanel();
\r
481 JButton fetchDAS = new JButton();
\r
482 JButton saveDAS = new JButton();
\r
483 JButton cancelDAS = new JButton();
\r
484 private void jbInit()
\r
487 this.setLayout(borderLayout1);
\r
488 settingsPane.setLayout(borderLayout2);
\r
489 dasSettingsPane.setLayout(borderLayout3);
\r
490 bigPanel.setLayout(borderLayout4);
\r
491 invert.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
492 invert.setText("Invert Selection");
\r
493 invert.addActionListener(new ActionListener()
\r
495 public void actionPerformed(ActionEvent e)
\r
500 cancel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
501 cancel.setText("Cancel");
\r
502 cancel.addActionListener(new ActionListener()
\r
504 public void actionPerformed(ActionEvent e)
\r
506 updateFeatureRenderer(originalData);
\r
510 ok.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
512 ok.addActionListener(new ActionListener()
\r
514 public void actionPerformed(ActionEvent e)
\r
519 loadColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
520 loadColours.setText("Load Colours");
\r
521 loadColours.addActionListener(new ActionListener()
\r
523 public void actionPerformed(ActionEvent e)
\r
528 saveColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
529 saveColours.setText("Save Colours");
\r
530 saveColours.addActionListener(new ActionListener()
\r
532 public void actionPerformed(ActionEvent e)
\r
537 transparency.addChangeListener(new ChangeListener()
\r
539 public void stateChanged(ChangeEvent evt)
\r
541 fr.setTransparency( (float) (100 - transparency.getValue()) / 100f);
\r
542 af.alignPanel.paintAlignment(true);
\r
546 transparency.setMaximum(70);
\r
547 fetchDAS.setText("Fetch DAS Features");
\r
548 fetchDAS.addActionListener(new ActionListener()
\r
550 public void actionPerformed(ActionEvent e)
\r
552 fetchDAS_actionPerformed(e);
\r
555 saveDAS.setText("Save as default");
\r
556 saveDAS.addActionListener(new ActionListener()
\r
558 public void actionPerformed(ActionEvent e)
\r
560 saveDAS_actionPerformed(e);
\r
563 dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
\r
564 dasSettingsPane.setBorder(null);
\r
565 cancelDAS.setEnabled(false);
\r
566 cancelDAS.setText("Cancel Fetch");
\r
567 cancelDAS.addActionListener(new ActionListener()
\r
569 public void actionPerformed(ActionEvent e)
\r
571 cancelDAS_actionPerformed(e);
\r
574 this.add(tabbedPane, java.awt.BorderLayout.CENTER);
\r
575 tabbedPane.addTab("Feature Settings", settingsPane);
\r
576 tabbedPane.addTab("DAS Settings", dasSettingsPane);
\r
577 bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
\r
578 transPanel.add(transparency);
\r
579 transPanel.add(invert);
\r
580 buttonPanel.add(ok);
\r
581 buttonPanel.add(cancel);
\r
582 buttonPanel.add(loadColours);
\r
583 buttonPanel.add(saveColours);
\r
584 bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
\r
585 dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
\r
586 dasButtonPanel.add(fetchDAS);
\r
587 dasButtonPanel.add(cancelDAS);
\r
588 dasButtonPanel.add(saveDAS);
\r
589 settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);
\r
590 settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
\r
593 public void fetchDAS_actionPerformed(ActionEvent e)
\r
595 fetchDAS.setEnabled(false);
\r
596 cancelDAS.setEnabled(true);
\r
597 Vector selectedSources = dassourceBrowser.getSelectedSources();
\r
599 SequenceI[] dataset, seqs;
\r
602 if (af.getViewport().getSelectionGroup() != null
\r
603 && af.getViewport().getSelectionGroup().getSize() > 0)
\r
605 iSize = af.getViewport().getSelectionGroup().getSize();
\r
606 dataset = new SequenceI[iSize];
\r
607 seqs = af.getViewport().getSelectionGroup().
\r
608 getSequencesInOrder(
\r
609 af.getViewport().getAlignment());
\r
613 iSize = af.getViewport().getAlignment().getHeight();
\r
614 seqs = af.getViewport().getAlignment().getSequencesArray();
\r
617 dataset = new SequenceI[iSize];
\r
618 for (int i = 0; i < iSize; i++)
\r
620 dataset[i] = seqs[i].getDatasetSequence();
\r
623 dasFeatureFetcher =
\r
624 new jalview.io.DasSequenceFeatureFetcher(
\r
629 af.getViewport().setShowSequenceFeatures(true);
\r
630 af.showSeqFeatures.setSelected(true);
\r
633 public void saveDAS_actionPerformed(ActionEvent e)
\r
635 dassourceBrowser.saveProperties(jalview.bin.Cache.applicationProperties);
\r
638 public void complete()
\r
640 fetchDAS.setEnabled(true);
\r
641 cancelDAS.setEnabled(false);
\r
644 public void cancelDAS_actionPerformed(ActionEvent e)
\r
646 dasFeatureFetcher.cancel();
\r
647 fetchDAS.setEnabled(true);
\r
648 cancelDAS.setEnabled(false);
\r
651 /////////////////////////////////////////////////////////////////////////
\r
652 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
\r
653 /////////////////////////////////////////////////////////////////////////
\r
654 class FeatureTableModel
\r
655 extends AbstractTableModel
\r
657 FeatureTableModel(Object[][] data)
\r
662 private String[] columnNames =
\r
664 "Feature Type", "Colour", "Display"};
\r
665 private Object[][] data;
\r
667 public Object[][] getData()
\r
672 public void setData(Object[][] data)
\r
677 public int getColumnCount()
\r
679 return columnNames.length;
\r
682 public Object[] getRow(int row)
\r
687 public int getRowCount()
\r
689 return data.length;
\r
692 public String getColumnName(int col)
\r
694 return columnNames[col];
\r
697 public Object getValueAt(int row, int col)
\r
699 return data[row][col];
\r
702 public Class getColumnClass(int c)
\r
704 return getValueAt(0, c).getClass();
\r
707 public boolean isCellEditable(int row, int col)
\r
709 return col == 0 ? false : true;
\r
712 public void setValueAt(Object value, int row, int col)
\r
714 data[row][col] = value;
\r
715 fireTableCellUpdated(row, col);
\r
716 updateFeatureRenderer(data);
\r
721 class ColorRenderer
\r
722 extends JLabel implements TableCellRenderer
\r
724 javax.swing.border.Border unselectedBorder = null;
\r
725 javax.swing.border.Border selectedBorder = null;
\r
727 public ColorRenderer()
\r
729 setOpaque(true); //MUST do this for background to show up.
\r
732 public Component getTableCellRendererComponent(
\r
733 JTable table, Object color,
\r
734 boolean isSelected, boolean hasFocus,
\r
735 int row, int column)
\r
737 Color newColor = (Color) color;
\r
738 setBackground(newColor);
\r
741 if (selectedBorder == null)
\r
743 selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
\r
744 table.getSelectionBackground());
\r
746 setBorder(selectedBorder);
\r
750 if (unselectedBorder == null)
\r
752 unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
\r
753 table.getBackground());
\r
755 setBorder(unselectedBorder);
\r
758 setToolTipText("RGB value: " + newColor.getRed() + ", "
\r
759 + newColor.getGreen() + ", "
\r
760 + newColor.getBlue());
\r
767 extends AbstractCellEditor implements TableCellEditor,
\r
770 Color currentColor;
\r
772 JColorChooser colorChooser;
\r
774 protected static final String EDIT = "edit";
\r
776 public ColorEditor()
\r
778 //Set up the editor (from the table's point of view),
\r
779 //which is a button.
\r
780 //This button brings up the color chooser dialog,
\r
781 //which is the editor from the user's point of view.
\r
782 button = new JButton();
\r
783 button.setActionCommand(EDIT);
\r
784 button.addActionListener(this);
\r
785 button.setBorderPainted(false);
\r
786 //Set up the dialog that the button brings up.
\r
787 colorChooser = new JColorChooser();
\r
788 dialog = JColorChooser.createDialog(button,
\r
789 "Select new Colour",
\r
792 this, //OK button handler
\r
793 null); //no CANCEL button handler
\r
797 * Handles events from the editor button and from
\r
798 * the dialog's OK button.
\r
800 public void actionPerformed(ActionEvent e)
\r
803 if (EDIT.equals(e.getActionCommand()))
\r
805 //The user has clicked the cell, so
\r
806 //bring up the dialog.
\r
807 button.setBackground(currentColor);
\r
808 colorChooser.setColor(currentColor);
\r
809 dialog.setVisible(true);
\r
811 //Make the renderer reappear.
\r
812 fireEditingStopped();
\r
816 { //User pressed dialog's "OK" button.
\r
817 currentColor = colorChooser.getColor();
\r
821 //Implement the one CellEditor method that AbstractCellEditor doesn't.
\r
822 public Object getCellEditorValue()
\r
824 return currentColor;
\r
827 //Implement the one method defined by TableCellEditor.
\r
828 public Component getTableCellEditorComponent(JTable table,
\r
830 boolean isSelected,
\r
834 currentColor = (Color) value;
\r