2 * Jalview - A Sequence Alignment Editor and Viewer
3 * Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
21 import jalview.datamodel.*;
23 import javax.swing.event.*;
26 import javax.swing.BorderFactory;
27 import java.awt.event.*;
28 import javax.swing.table.*;
30 import jalview.io.JalviewFileChooser;
31 import java.awt.BorderLayout;
33 import java.awt.Color;
35 public class FeatureSettings extends JPanel
37 DasSourceBrowser dassourceBrowser;
38 JPanel settingsPane = new JPanel();
39 JPanel dasSettingsPane = new JPanel();
41 final FeatureRenderer fr;
43 Object [][] originalData;
44 final JInternalFrame frame;
45 JScrollPane scrollPane = new JScrollPane();
48 JSlider transparency = new JSlider();
50 JPanel transPanel = new JPanel(new FlowLayout());
52 public FeatureSettings(AlignFrame af)
55 fr = af.getFeatureRenderer();
57 transparency.setMaximum( 100 - (int)(fr.transparency*100) ) ;
69 table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));
70 table.setFont(new Font("Verdana", Font.PLAIN, 12));
71 table.setDefaultRenderer(Color.class,
74 table.setDefaultEditor(Color.class,
77 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
79 table.addMouseListener(new MouseAdapter()
81 public void mousePressed(MouseEvent evt)
83 selectedRow = table.rowAtPoint(evt.getPoint());
87 table.addMouseMotionListener(new MouseMotionAdapter()
89 public void mouseDragged(MouseEvent evt)
91 int newRow = table.rowAtPoint(evt.getPoint());
92 if (newRow != selectedRow
96 Object[] temp = new Object[3];
97 temp[0] = table.getValueAt(selectedRow, 0);
98 temp[1] = table.getValueAt(selectedRow, 1);
99 temp[2] = table.getValueAt(selectedRow, 2);
101 table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0);
102 table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1);
103 table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2);
105 table.setValueAt(temp[0], newRow, 0);
106 table.setValueAt(temp[1], newRow, 1);
107 table.setValueAt(temp[2], newRow, 2);
109 selectedRow = newRow;
114 scrollPane.setViewportView(table);
116 dassourceBrowser = new DasSourceBrowser();
117 dasSettingsPane.add(dassourceBrowser, BorderLayout.CENTER);
121 if (af.getViewport().featuresDisplayed == null || fr.renderOrder==null)
122 fr.findAllFeatures();
126 frame = new JInternalFrame();
127 frame.setContentPane(this);
128 Desktop.addInternalFrame(frame, "Sequence Feature Settings", 400, 450);
129 frame.setLayer(JLayeredPane.PALETTE_LAYER);
132 synchronized public void setTableData()
134 if (fr.featureGroups == null)
135 fr.featureGroups = new Hashtable();
137 Vector allFeatures = new Vector();
138 Vector allGroups = new Vector();
139 SequenceFeature[] tmpfeatures;
142 for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)
144 if (af.getViewport().alignment.getSequenceAt(i).getDatasetSequence().getSequenceFeatures() == null)
147 tmpfeatures = af.getViewport().alignment.getSequenceAt(i).getDatasetSequence().getSequenceFeatures();
150 while (index < tmpfeatures.length)
152 if(tmpfeatures[index].begin == 0 && tmpfeatures[index].end ==0)
158 if(tmpfeatures[index].getFeatureGroup()!=null)
160 group = tmpfeatures[index].featureGroup;
161 if(!allGroups.contains(group))
163 allGroups.addElement(group);
165 boolean visible = true;
166 if (fr.featureGroups.containsKey(group))
168 visible = ( (Boolean) fr.featureGroups.get(group)).booleanValue();
171 if (groupPanel == null)
173 groupPanel = new JPanel();
176 boolean alreadyAdded = false;
177 for(int g=0; g<groupPanel.getComponentCount(); g++)
179 if(((JCheckBox)groupPanel.getComponent(g))
180 .getText().equals(group))
190 fr.featureGroups.put(group, new Boolean(visible));
192 final JCheckBox check = new JCheckBox(group, visible);
193 check.setFont(new Font("Serif", Font.BOLD, 12));
194 check.addItemListener(new ItemListener()
196 public void itemStateChanged(ItemEvent evt)
198 fr.featureGroups.put(check.getText(),
199 new Boolean(check.isSelected()));
200 af.alignPanel.seqPanel.seqCanvas.repaint();
201 if (af.alignPanel.overviewPanel != null)
202 af.alignPanel.overviewPanel.updateOverviewImage();
207 groupPanel.add(check);
211 if (!allFeatures.contains(tmpfeatures[index].getType()))
213 allFeatures.addElement(tmpfeatures[index].getType());
225 void resetTable(boolean groupsChanged)
227 SequenceFeature [] tmpfeatures;
228 String group=null, type;
229 Vector visibleChecks = new Vector();
231 //Find out which features should be visible depending on which groups
232 //are selected / deselected
233 for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)
236 tmpfeatures = af.getViewport().alignment.getSequenceAt(i).getDatasetSequence().getSequenceFeatures();
237 if (tmpfeatures == null)
241 while (index < tmpfeatures.length)
243 group = tmpfeatures[index].featureGroup;
245 if(tmpfeatures[index].begin==0 && tmpfeatures[index].end==0)
251 if (group==null || fr.featureGroups.get(group)==null ||
252 ((Boolean) fr.featureGroups.get(group)).booleanValue())
254 type = tmpfeatures[index].getType();
255 if(!visibleChecks.contains(type) )
257 visibleChecks.addElement(type);
264 int fSize = visibleChecks.size();
265 Object [][] data = new Object[fSize][3];
268 if(fr.renderOrder!=null)
270 //First add the checks in the previous render order,
271 //in case the window has been closed and reopened
272 for(int ro=fr.renderOrder.length-1; ro>-1; ro--)
274 type = fr.renderOrder[ro];
276 if(!visibleChecks.contains(type))
279 data[dataIndex][0] = type;
280 data[dataIndex][1] = fr.getColour(type);
281 data[dataIndex][2] = new Boolean(af.getViewport().featuresDisplayed.containsKey(type));
283 visibleChecks.removeElement(type);
287 fSize = visibleChecks.size();
288 for(int i=0; i<fSize; i++)
290 //These must be extra features belonging to the group
291 //which was just selected
292 type = visibleChecks.elementAt(i).toString();
293 data[dataIndex][0] = type;
295 data[dataIndex][1] = fr.getColour(type);
296 data[dataIndex][2] = new Boolean(true);
300 if(originalData==null)
302 originalData = new Object[data.length][3];
303 System.arraycopy(data,0,originalData,0,data.length);
306 table.setModel(new FeatureTableModel(data));
307 table.getColumnModel().getColumn(0).setPreferredWidth(200);
310 if (groupPanel != null)
312 groupPanel.setLayout(
313 new GridLayout(fr.featureGroups.size() / 4 + 1, 4));
315 groupPanel.validate();
316 bigPanel.add(groupPanel, BorderLayout.NORTH);
319 updateFeatureRenderer(data);
325 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(
326 "LAST_DIRECTORY"), new String[] { "fc" },
327 new String[] { "Sequence Feature Colours" }, "Sequence Feature Colours");
328 chooser.setFileView(new jalview.io.JalviewFileView());
329 chooser.setDialogTitle("Load Feature Colours");
330 chooser.setToolTipText("Load");
332 int value = chooser.showOpenDialog(this);
334 if (value == JalviewFileChooser.APPROVE_OPTION)
336 File file = chooser.getSelectedFile();
340 InputStreamReader in = new InputStreamReader(new FileInputStream(
343 jalview.binding.JalviewUserColours jucs = new jalview.binding.
344 JalviewUserColours();
345 jucs = (jalview.binding.JalviewUserColours) jucs.unmarshal(in);
348 for (int i = 0; i < jucs.getColourCount(); i++)
350 fr.setColour( jucs.getColour(i).getName(),
351 new Color(Integer.parseInt( jucs.getColour(i).getRGB(), 16)));
355 af.alignPanel.repaint();
359 System.out.println("Error loading User Colour File\n" + ex);
366 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(
367 "LAST_DIRECTORY"), new String[] { "fc" },
368 new String[] { "Sequence Feature Colours" }, "Sequence Feature Colours");
369 chooser.setFileView(new jalview.io.JalviewFileView());
370 chooser.setDialogTitle("Save Feature Colour Scheme");
371 chooser.setToolTipText("Save");
373 int value = chooser.showSaveDialog(this);
375 if (value == JalviewFileChooser.APPROVE_OPTION)
377 String choice = chooser.getSelectedFile().getPath();
378 jalview.binding.JalviewUserColours ucs = new jalview.binding.JalviewUserColours();
379 ucs.setSchemeName("Sequence Features");
382 PrintWriter out = new PrintWriter(new OutputStreamWriter(
383 new FileOutputStream(choice), "UTF-8"));
385 Enumeration e = fr.featureColours.keys();
386 while(e.hasMoreElements())
388 jalview.binding.Colour col = new jalview.binding.Colour();
389 col.setName(e.nextElement().toString());
390 col.setRGB(jalview.util.Format.getHexString(
391 fr.getColour(col.getName())));
400 ex.printStackTrace();
405 public void invertSelection()
407 for(int i=0; i<table.getRowCount(); i++)
409 Boolean value = (Boolean)table.getValueAt(i,2);
412 new Boolean(!value.booleanValue()),
421 frame.setClosed(true);
423 catch (Exception exe)
428 public void updateFeatureRenderer(Object [][] data)
430 fr.setFeaturePriority( data );
431 af.alignPanel.repaint();
433 if(af.alignPanel.overviewPanel!=null)
434 af.alignPanel.overviewPanel.updateOverviewImage();
438 JTabbedPane tabbedPane = new JTabbedPane();
439 BorderLayout borderLayout1 = new BorderLayout();
440 BorderLayout borderLayout2 = new BorderLayout();
441 BorderLayout borderLayout3 = new BorderLayout();
442 JPanel bigPanel = new JPanel();
443 BorderLayout borderLayout4 = new BorderLayout();
444 JButton invert = new JButton();
445 JPanel buttonPanel = new JPanel();
446 JButton cancel = new JButton();
447 JButton ok = new JButton();
448 JButton loadColours = new JButton();
449 JButton saveColours = new JButton();
450 JPanel dasButtonPanel = new JPanel();
451 JButton fetchDAS = new JButton();
452 JButton saveDAS = new JButton();
453 private void jbInit()
456 this.setLayout(borderLayout1);
457 settingsPane.setLayout(borderLayout2);
458 dasSettingsPane.setLayout(borderLayout3);
459 bigPanel.setLayout(borderLayout4);
460 invert.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
461 invert.setText("Invert Selection");
462 invert.addActionListener(new ActionListener()
464 public void actionPerformed(ActionEvent e)
469 cancel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
470 cancel.setText("Cancel");
471 cancel.addActionListener(new ActionListener()
473 public void actionPerformed(ActionEvent e)
475 updateFeatureRenderer(originalData);
479 ok.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
481 ok.addActionListener(new ActionListener()
483 public void actionPerformed(ActionEvent e)
488 loadColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
489 loadColours.setText("Load Colours");
490 loadColours.addActionListener(new ActionListener()
492 public void actionPerformed(ActionEvent e)
497 saveColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
498 saveColours.setText("Save Colours");
499 saveColours.addActionListener(new ActionListener()
501 public void actionPerformed(ActionEvent e)
506 transparency.addChangeListener(new ChangeListener()
508 public void stateChanged(ChangeEvent evt)
510 fr.setTransparency( (float) (100 - transparency.getValue()) / 100f);
511 af.alignPanel.repaint();
516 transparency.setMaximum(70);
517 fetchDAS.setText("Fetch DAS Features");
518 fetchDAS.addActionListener(new ActionListener()
520 public void actionPerformed(ActionEvent e)
522 fetchDAS_actionPerformed(e);
525 saveDAS.setText("Save as default");
526 saveDAS.addActionListener(new ActionListener()
528 public void actionPerformed(ActionEvent e)
530 saveDAS_actionPerformed(e);
533 dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
534 dasSettingsPane.setBorder(null);
535 this.add(tabbedPane, java.awt.BorderLayout.CENTER);
536 tabbedPane.addTab("Feature Settings", settingsPane );
537 tabbedPane.addTab("DAS Settings", dasSettingsPane);
538 bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
539 transPanel.add(transparency);
540 transPanel.add(invert);
542 buttonPanel.add(cancel);
543 buttonPanel.add(loadColours);
544 buttonPanel.add(saveColours);
545 bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
546 dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
547 dasButtonPanel.add(fetchDAS);
548 dasButtonPanel.add(saveDAS);
549 settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);
550 settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
553 public void fetchDAS_actionPerformed(ActionEvent e)
555 Vector selectedSources = dassourceBrowser.getSelectedSources();
557 SequenceI [] dataset, seqs ;
560 if(af.getViewport().getSelectionGroup()!=null
561 && af.getViewport().getSelectionGroup().getSize(false)>0)
563 iSize = af.getViewport().getSelectionGroup().getSize(false);
564 dataset = new SequenceI[iSize];
565 seqs = af.getViewport().getSelectionGroup().
567 af.getViewport().getAlignment());
571 iSize = af.getViewport().getAlignment().getHeight();
572 seqs = af.getViewport().getAlignment().getSequencesArray();
575 dataset = new SequenceI[iSize];
576 for (int i = 0; i < iSize; i++)
578 dataset[i] = seqs[i].getDatasetSequence();
581 new jalview.io.DasSequenceFeatureFetcher(
586 af.getViewport().setShowSequenceFeatures(true);
587 af.showSeqFeatures.setSelected(true);
590 public void saveDAS_actionPerformed(ActionEvent e)
592 dassourceBrowser.saveProperties(jalview.bin.Cache.applicationProperties);
595 /////////////////////////////////////////////////////////////////////////
596 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
597 /////////////////////////////////////////////////////////////////////////
598 class FeatureTableModel
599 extends AbstractTableModel
601 FeatureTableModel(Object[][] data)
606 private String[] columnNames = {"Feature Type", "Colour","Display"};
607 private Object[][] data;
609 public Object[][] getData()
614 public void setData(Object[][] data)
619 public int getColumnCount() {
620 return columnNames.length;
623 public Object[] getRow(int row)
628 public int getRowCount() {
632 public String getColumnName(int col) {
633 return columnNames[col];
636 public Object getValueAt(int row, int col) {
637 return data[row][col];
640 public Class getColumnClass(int c) {
641 return getValueAt(0, c).getClass();
644 public boolean isCellEditable(int row, int col) {
645 return col==0 ? false:true;
648 public void setValueAt(Object value, int row, int col) {
649 data[row][col] = value;
650 fireTableCellUpdated(row, col);
651 updateFeatureRenderer(data);
655 class ColorRenderer extends JLabel
656 implements TableCellRenderer {
657 javax.swing.border.Border unselectedBorder = null;
658 javax.swing.border.Border selectedBorder = null;
660 public ColorRenderer() {
661 setOpaque(true); //MUST do this for background to show up.
664 public Component getTableCellRendererComponent(
665 JTable table, Object color,
666 boolean isSelected, boolean hasFocus,
667 int row, int column) {
668 Color newColor = (Color)color;
669 setBackground(newColor);
671 if (selectedBorder == null) {
672 selectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
673 table.getSelectionBackground());
675 setBorder(selectedBorder);
677 if (unselectedBorder == null) {
678 unselectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
679 table.getBackground());
681 setBorder(unselectedBorder);
684 setToolTipText("RGB value: " + newColor.getRed() + ", "
685 + newColor.getGreen() + ", "
686 + newColor.getBlue());
692 class ColorEditor extends AbstractCellEditor
693 implements TableCellEditor,
697 JColorChooser colorChooser;
699 protected static final String EDIT = "edit";
701 public ColorEditor() {
702 //Set up the editor (from the table's point of view),
704 //This button brings up the color chooser dialog,
705 //which is the editor from the user's point of view.
706 button = new JButton();
707 button.setActionCommand(EDIT);
708 button.addActionListener(this);
709 button.setBorderPainted(false);
710 //Set up the dialog that the button brings up.
711 colorChooser = new JColorChooser();
712 dialog = JColorChooser.createDialog(button,
716 this, //OK button handler
717 null); //no CANCEL button handler
721 * Handles events from the editor button and from
722 * the dialog's OK button.
724 public void actionPerformed(ActionEvent e) {
726 if (EDIT.equals(e.getActionCommand())) {
727 //The user has clicked the cell, so
728 //bring up the dialog.
729 button.setBackground(currentColor);
730 colorChooser.setColor(currentColor);
731 dialog.setVisible(true);
733 //Make the renderer reappear.
734 fireEditingStopped();
736 } else { //User pressed dialog's "OK" button.
737 currentColor = colorChooser.getColor();
741 //Implement the one CellEditor method that AbstractCellEditor doesn't.
742 public Object getCellEditorValue() {
746 //Implement the one method defined by TableCellEditor.
747 public Component getTableCellEditorComponent(JTable table,
752 currentColor = (Color)value;