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