2 * Jalview - A Sequence Alignment Editor and Viewer
\r
3 * Copyright (C) 2005 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
223 void resetTable(boolean groupsChanged)
\r
225 SequenceFeature [] tmpfeatures;
\r
226 String group=null, type;
\r
227 Vector visibleChecks = new Vector();
\r
229 //Find out which features should be visible depending on which groups
\r
230 //are selected / deselected
\r
231 for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)
\r
234 tmpfeatures = af.getViewport().alignment.getSequenceAt(i).getDatasetSequence().getSequenceFeatures();
\r
235 if (tmpfeatures == null)
\r
239 while (index < tmpfeatures.length)
\r
241 group = tmpfeatures[index].featureGroup;
\r
243 if(tmpfeatures[index].begin==0 && tmpfeatures[index].end==0)
\r
249 if (group==null || fr.featureGroups.get(group)==null ||
\r
250 ((Boolean) fr.featureGroups.get(group)).booleanValue())
\r
252 type = tmpfeatures[index].getType();
\r
253 if(!visibleChecks.contains(type) )
\r
255 visibleChecks.addElement(type);
\r
262 int fSize = visibleChecks.size();
\r
263 Object [][] data = new Object[fSize][3];
\r
266 if(fr.renderOrder!=null)
\r
268 //First add the checks in the previous render order,
\r
269 //in case the window has been closed and reopened
\r
270 for(int ro=fr.renderOrder.length-1; ro>-1; ro--)
\r
272 type = fr.renderOrder[ro];
\r
274 if(!visibleChecks.contains(type))
\r
277 data[dataIndex][0] = type;
\r
278 data[dataIndex][1] = fr.getColour(type);
\r
279 data[dataIndex][2] = new Boolean(af.getViewport().featuresDisplayed.containsKey(type));
\r
281 visibleChecks.removeElement(type);
\r
285 fSize = visibleChecks.size();
\r
286 for(int i=0; i<fSize; i++)
\r
288 //These must be extra features belonging to the group
\r
289 //which was just selected
\r
290 type = visibleChecks.elementAt(i).toString();
\r
291 data[dataIndex][0] = type;
\r
293 data[dataIndex][1] = fr.getColour(type);
\r
294 data[dataIndex][2] = new Boolean(true);
\r
298 if(originalData==null)
\r
300 originalData = new Object[data.length][3];
\r
301 System.arraycopy(data,0,originalData,0,data.length);
\r
304 table.setModel(new FeatureTableModel(data));
\r
305 table.getColumnModel().getColumn(0).setPreferredWidth(200);
\r
308 if (groupPanel != null)
\r
310 groupPanel.setLayout(
\r
311 new GridLayout(fr.featureGroups.size() / 4 + 1, 4));
\r
313 groupPanel.validate();
\r
314 bigPanel.add(groupPanel, BorderLayout.NORTH);
\r
317 updateFeatureRenderer(data);
\r
323 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(
\r
324 "LAST_DIRECTORY"), new String[] { "fc" },
\r
325 new String[] { "Sequence Feature Colours" }, "Sequence Feature Colours");
\r
326 chooser.setFileView(new jalview.io.JalviewFileView());
\r
327 chooser.setDialogTitle("Load Feature Colours");
\r
328 chooser.setToolTipText("Load");
\r
330 int value = chooser.showOpenDialog(this);
\r
332 if (value == JalviewFileChooser.APPROVE_OPTION)
\r
334 File file = chooser.getSelectedFile();
\r
338 InputStreamReader in = new InputStreamReader(new FileInputStream(
\r
341 jalview.binding.JalviewUserColours jucs = new jalview.binding.
\r
342 JalviewUserColours();
\r
343 jucs = (jalview.binding.JalviewUserColours) jucs.unmarshal(in);
\r
346 for (int i = 0; i < jucs.getColourCount(); i++)
\r
348 fr.setColour( jucs.getColour(i).getName(),
\r
349 new Color(Integer.parseInt( jucs.getColour(i).getRGB(), 16)));
\r
353 af.alignPanel.repaint();
\r
355 catch (Exception ex)
\r
357 System.out.println("Error loading User Colour File\n" + ex);
\r
364 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(
\r
365 "LAST_DIRECTORY"), new String[] { "fc" },
\r
366 new String[] { "Sequence Feature Colours" }, "Sequence Feature Colours");
\r
367 chooser.setFileView(new jalview.io.JalviewFileView());
\r
368 chooser.setDialogTitle("Save Feature Colour Scheme");
\r
369 chooser.setToolTipText("Save");
\r
371 int value = chooser.showSaveDialog(this);
\r
373 if (value == JalviewFileChooser.APPROVE_OPTION)
\r
375 String choice = chooser.getSelectedFile().getPath();
\r
376 jalview.binding.JalviewUserColours ucs = new jalview.binding.JalviewUserColours();
\r
377 ucs.setSchemeName("Sequence Features");
\r
380 PrintWriter out = new PrintWriter(new OutputStreamWriter(
\r
381 new FileOutputStream(choice), "UTF-8"));
\r
383 Enumeration e = fr.featureColours.keys();
\r
384 while(e.hasMoreElements())
\r
386 jalview.binding.Colour col = new jalview.binding.Colour();
\r
387 col.setName(e.nextElement().toString());
\r
388 col.setRGB(jalview.util.Format.getHexString(
\r
389 fr.getColour(col.getName())));
\r
390 ucs.addColour(col);
\r
396 catch (Exception ex)
\r
398 ex.printStackTrace();
\r
403 public void invertSelection()
\r
405 for(int i=0; i<table.getRowCount(); i++)
\r
407 Boolean value = (Boolean)table.getValueAt(i,2);
\r
410 new Boolean(!value.booleanValue()),
\r
415 public void close()
\r
419 frame.setClosed(true);
\r
421 catch (Exception exe)
\r
426 public void updateFeatureRenderer(Object [][] data)
\r
428 fr.setFeaturePriority( data );
\r
429 af.alignPanel.repaint();
\r
431 if(af.alignPanel.overviewPanel!=null)
\r
432 af.alignPanel.overviewPanel.updateOverviewImage();
\r
435 int selectedRow =-1;
\r
436 JTabbedPane tabbedPane = new JTabbedPane();
\r
437 BorderLayout borderLayout1 = new BorderLayout();
\r
438 BorderLayout borderLayout2 = new BorderLayout();
\r
439 BorderLayout borderLayout3 = new BorderLayout();
\r
440 JPanel bigPanel = new JPanel();
\r
441 BorderLayout borderLayout4 = new BorderLayout();
\r
442 JButton invert = new JButton();
\r
443 JPanel buttonPanel = new JPanel();
\r
444 JButton cancel = new JButton();
\r
445 JButton ok = new JButton();
\r
446 JButton loadColours = new JButton();
\r
447 JButton saveColours = new JButton();
\r
448 JPanel dasButtonPanel = new JPanel();
\r
449 JButton fetchDAS = new JButton();
\r
450 JButton saveDAS = new JButton();
\r
451 private void jbInit()
\r
454 this.setLayout(borderLayout1);
\r
455 settingsPane.setLayout(borderLayout2);
\r
456 dasSettingsPane.setLayout(borderLayout3);
\r
457 bigPanel.setLayout(borderLayout4);
\r
458 invert.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
459 invert.setText("Invert Selection");
\r
460 invert.addActionListener(new ActionListener()
\r
462 public void actionPerformed(ActionEvent e)
\r
467 cancel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
468 cancel.setText("Cancel");
\r
469 cancel.addActionListener(new ActionListener()
\r
471 public void actionPerformed(ActionEvent e)
\r
473 updateFeatureRenderer(originalData);
\r
477 ok.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
479 ok.addActionListener(new ActionListener()
\r
481 public void actionPerformed(ActionEvent e)
\r
486 loadColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
487 loadColours.setText("Load Colours");
\r
488 loadColours.addActionListener(new ActionListener()
\r
490 public void actionPerformed(ActionEvent e)
\r
495 saveColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
496 saveColours.setText("Save Colours");
\r
497 saveColours.addActionListener(new ActionListener()
\r
499 public void actionPerformed(ActionEvent e)
\r
504 transparency.addChangeListener(new ChangeListener()
\r
506 public void stateChanged(ChangeEvent evt)
\r
508 fr.setTransparency( (float) (100 - transparency.getValue()) / 100f);
\r
509 af.alignPanel.repaint();
\r
514 transparency.setMaximum(70);
\r
515 fetchDAS.setText("Fetch DAS Features");
\r
516 fetchDAS.addActionListener(new ActionListener()
\r
518 public void actionPerformed(ActionEvent e)
\r
520 fetchDAS_actionPerformed(e);
\r
523 saveDAS.setText("Save as default");
\r
524 saveDAS.addActionListener(new ActionListener()
\r
526 public void actionPerformed(ActionEvent e)
\r
528 saveDAS_actionPerformed(e);
\r
531 dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
\r
532 dasSettingsPane.setBorder(null);
\r
533 this.add(tabbedPane, java.awt.BorderLayout.CENTER);
\r
534 tabbedPane.addTab("Display Settings", settingsPane );
\r
535 tabbedPane.addTab("DAS Settings", dasSettingsPane);
\r
536 bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
\r
537 transPanel.add(transparency);
\r
538 transPanel.add(invert);
\r
539 buttonPanel.add(ok);
\r
540 buttonPanel.add(cancel);
\r
541 buttonPanel.add(loadColours);
\r
542 buttonPanel.add(saveColours);
\r
543 bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
\r
544 dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
\r
545 dasButtonPanel.add(fetchDAS);
\r
546 dasButtonPanel.add(saveDAS);
\r
547 settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);
\r
548 settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
\r
551 public void fetchDAS_actionPerformed(ActionEvent e)
\r
553 Vector selectedSources = dassourceBrowser.getSelectedSources();
\r
555 SequenceI [] dataset, seqs ;
\r
558 if(af.getViewport().getSelectionGroup()!=null
\r
559 && af.getViewport().getSelectionGroup().getSize(false)>0)
\r
561 iSize = af.getViewport().getSelectionGroup().getSize(false);
\r
562 dataset = new SequenceI[iSize];
\r
563 seqs = af.getViewport().getSelectionGroup().
\r
564 getSequencesInOrder(
\r
565 af.getViewport().getAlignment());
\r
569 iSize = af.getViewport().getAlignment().getHeight();
\r
570 seqs = af.getViewport().getAlignment().getSequencesArray();
\r
573 dataset = new SequenceI[iSize];
\r
574 for (int i = 0; i < iSize; i++)
\r
576 dataset[i] = seqs[i].getDatasetSequence();
\r
579 new jalview.io.DasSequenceFeatureFetcher(
\r
584 af.getViewport().setShowSequenceFeatures(true);
\r
585 af.showSeqFeatures.setSelected(true);
\r
588 public void saveDAS_actionPerformed(ActionEvent e)
\r
590 dassourceBrowser.saveProperties(jalview.bin.Cache.applicationProperties);
\r
593 /////////////////////////////////////////////////////////////////////////
\r
594 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
\r
595 /////////////////////////////////////////////////////////////////////////
\r
596 class FeatureTableModel
\r
597 extends AbstractTableModel
\r
599 FeatureTableModel(Object[][] data)
\r
604 private String[] columnNames = {"Feature Type", "Colour","Display"};
\r
605 private Object[][] data;
\r
607 public Object[][] getData()
\r
612 public void setData(Object[][] data)
\r
617 public int getColumnCount() {
\r
618 return columnNames.length;
\r
621 public Object[] getRow(int row)
\r
626 public int getRowCount() {
\r
627 return data.length;
\r
630 public String getColumnName(int col) {
\r
631 return columnNames[col];
\r
634 public Object getValueAt(int row, int col) {
\r
635 return data[row][col];
\r
638 public Class getColumnClass(int c) {
\r
639 return getValueAt(0, c).getClass();
\r
642 public boolean isCellEditable(int row, int col) {
\r
643 return col==0 ? false:true;
\r
646 public void setValueAt(Object value, int row, int col) {
\r
647 data[row][col] = value;
\r
648 fireTableCellUpdated(row, col);
\r
649 updateFeatureRenderer(data);
\r
653 class ColorRenderer extends JLabel
\r
654 implements TableCellRenderer {
\r
655 javax.swing.border.Border unselectedBorder = null;
\r
656 javax.swing.border.Border selectedBorder = null;
\r
658 public ColorRenderer() {
\r
659 setOpaque(true); //MUST do this for background to show up.
\r
662 public Component getTableCellRendererComponent(
\r
663 JTable table, Object color,
\r
664 boolean isSelected, boolean hasFocus,
\r
665 int row, int column) {
\r
666 Color newColor = (Color)color;
\r
667 setBackground(newColor);
\r
669 if (selectedBorder == null) {
\r
670 selectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
\r
671 table.getSelectionBackground());
\r
673 setBorder(selectedBorder);
\r
675 if (unselectedBorder == null) {
\r
676 unselectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
\r
677 table.getBackground());
\r
679 setBorder(unselectedBorder);
\r
682 setToolTipText("RGB value: " + newColor.getRed() + ", "
\r
683 + newColor.getGreen() + ", "
\r
684 + newColor.getBlue());
\r
690 class ColorEditor extends AbstractCellEditor
\r
691 implements TableCellEditor,
\r
693 Color currentColor;
\r
695 JColorChooser colorChooser;
\r
697 protected static final String EDIT = "edit";
\r
699 public ColorEditor() {
\r
700 //Set up the editor (from the table's point of view),
\r
701 //which is a button.
\r
702 //This button brings up the color chooser dialog,
\r
703 //which is the editor from the user's point of view.
\r
704 button = new JButton();
\r
705 button.setActionCommand(EDIT);
\r
706 button.addActionListener(this);
\r
707 button.setBorderPainted(false);
\r
708 //Set up the dialog that the button brings up.
\r
709 colorChooser = new JColorChooser();
\r
710 dialog = JColorChooser.createDialog(button,
\r
711 "Select new Colour",
\r
714 this, //OK button handler
\r
715 null); //no CANCEL button handler
\r
719 * Handles events from the editor button and from
\r
720 * the dialog's OK button.
\r
722 public void actionPerformed(ActionEvent e) {
\r
724 if (EDIT.equals(e.getActionCommand())) {
\r
725 //The user has clicked the cell, so
\r
726 //bring up the dialog.
\r
727 button.setBackground(currentColor);
\r
728 colorChooser.setColor(currentColor);
\r
729 dialog.setVisible(true);
\r
731 //Make the renderer reappear.
\r
732 fireEditingStopped();
\r
734 } else { //User pressed dialog's "OK" button.
\r
735 currentColor = colorChooser.getColor();
\r
739 //Implement the one CellEditor method that AbstractCellEditor doesn't.
\r
740 public Object getCellEditorValue() {
\r
741 return currentColor;
\r
744 //Implement the one method defined by TableCellEditor.
\r
745 public Component getTableCellEditorComponent(JTable table,
\r
747 boolean isSelected,
\r
750 currentColor = (Color)value;
\r