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
51 boolean alignmentHasFeatures = false;
\r
53 public FeatureSettings(AlignFrame af)
\r
56 fr = af.getFeatureRenderer();
\r
58 transparency.setMaximum( 100 - (int)(fr.transparency*100) ) ;
\r
64 catch (Exception ex)
\r
66 ex.printStackTrace();
\r
69 dassourceBrowser = new DasSourceBrowser();
\r
70 dasSettingsPane.add(dassourceBrowser, BorderLayout.CENTER);
\r
74 if (af.getViewport().featuresDisplayed == null || fr.renderOrder==null)
\r
75 fr.findAllFeatures();
\r
79 frame = new JInternalFrame();
\r
80 frame.setContentPane(this);
\r
81 Desktop.addInternalFrame(frame, "Sequence Feature Settings", 400, 450);
\r
82 frame.setLayer(JLayeredPane.PALETTE_LAYER);
\r
85 synchronized public void setTableData()
\r
87 alignmentHasFeatures = false;
\r
89 if (fr.featureGroups == null)
\r
90 fr.featureGroups = new Hashtable();
\r
92 Vector allFeatures = new Vector();
\r
93 Vector allGroups = new Vector();
\r
94 SequenceFeature[] tmpfeatures;
\r
97 for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)
\r
99 if (af.getViewport().alignment.getSequenceAt(i).getDatasetSequence().getSequenceFeatures() == null)
\r
102 alignmentHasFeatures = true;
\r
104 tmpfeatures = af.getViewport().alignment.getSequenceAt(i).getDatasetSequence().getSequenceFeatures();
\r
107 while (index < tmpfeatures.length)
\r
109 if(tmpfeatures[index].begin == 0 && tmpfeatures[index].end ==0)
\r
115 if(tmpfeatures[index].getFeatureGroup()!=null)
\r
117 group = tmpfeatures[index].featureGroup;
\r
118 if(!allGroups.contains(group))
\r
120 allGroups.addElement(group);
\r
122 boolean visible = true;
\r
123 if (fr.featureGroups.containsKey(group))
\r
125 visible = ( (Boolean) fr.featureGroups.get(group)).booleanValue();
\r
128 if (groupPanel == null)
\r
130 groupPanel = new JPanel();
\r
133 boolean alreadyAdded = false;
\r
134 for(int g=0; g<groupPanel.getComponentCount(); g++)
\r
136 if(((JCheckBox)groupPanel.getComponent(g))
\r
137 .getText().equals(group))
\r
139 alreadyAdded = true;
\r
147 fr.featureGroups.put(group, new Boolean(visible));
\r
149 final JCheckBox check = new JCheckBox(group, visible);
\r
150 check.setFont(new Font("Serif", Font.BOLD, 12));
\r
151 check.addItemListener(new ItemListener()
\r
153 public void itemStateChanged(ItemEvent evt)
\r
155 fr.featureGroups.put(check.getText(),
\r
156 new Boolean(check.isSelected()));
\r
157 af.alignPanel.seqPanel.seqCanvas.repaint();
\r
158 if (af.alignPanel.overviewPanel != null)
\r
159 af.alignPanel.overviewPanel.updateOverviewImage();
\r
164 groupPanel.add(check);
\r
168 if (!allFeatures.contains(tmpfeatures[index].getType()))
\r
170 allFeatures.addElement(tmpfeatures[index].getType());
\r
177 if(!alignmentHasFeatures)
\r
180 // { frame.setClosed(true); }
\r
181 // catch (Exception ex){}
\r
183 // JOptionPane.showInternalMessageDialog(
\r
184 /// Desktop.desktop, "No features have been added to this alignment!",
\r
193 void resetTable(boolean groupsChanged)
\r
195 SequenceFeature [] tmpfeatures;
\r
196 String group=null, type;
\r
197 Vector visibleChecks = new Vector();
\r
199 //Find out which features should be visible depending on which groups
\r
200 //are selected / deselected
\r
201 for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)
\r
204 tmpfeatures = af.getViewport().alignment.getSequenceAt(i).getDatasetSequence().getSequenceFeatures();
\r
205 if (tmpfeatures == null)
\r
209 while (index < tmpfeatures.length)
\r
211 group = tmpfeatures[index].featureGroup;
\r
213 if(tmpfeatures[index].begin==0 && tmpfeatures[index].end==0)
\r
219 if (group==null || fr.featureGroups.get(group)==null ||
\r
220 ((Boolean) fr.featureGroups.get(group)).booleanValue())
\r
222 type = tmpfeatures[index].getType();
\r
223 if(!visibleChecks.contains(type) )
\r
225 visibleChecks.addElement(type);
\r
232 int fSize = visibleChecks.size();
\r
233 Object [][] data = new Object[fSize][3];
\r
236 if(fr.renderOrder!=null)
\r
238 //First add the checks in the previous render order,
\r
239 //in case the window has been closed and reopened
\r
240 for(int ro=fr.renderOrder.length-1; ro>-1; ro--)
\r
242 type = fr.renderOrder[ro];
\r
244 if(!visibleChecks.contains(type))
\r
247 data[dataIndex][0] = type;
\r
248 data[dataIndex][1] = fr.getColour(type);
\r
249 data[dataIndex][2] = new Boolean(af.getViewport().featuresDisplayed.containsKey(type));
\r
251 visibleChecks.removeElement(type);
\r
255 fSize = visibleChecks.size();
\r
256 for(int i=0; i<fSize; i++)
\r
258 //These must be extra features belonging to the group
\r
259 //which was just selected
\r
260 type = visibleChecks.elementAt(i).toString();
\r
261 data[dataIndex][0] = type;
\r
263 data[dataIndex][1] = fr.getColour(type);
\r
264 data[dataIndex][2] = new Boolean(true);
\r
268 if(originalData==null)
\r
270 originalData = new Object[data.length][3];
\r
271 System.arraycopy(data,0,originalData,0,data.length);
\r
274 table = new JTable(new FeatureTableModel(data));
\r
275 scrollPane.setViewportView(table);
\r
276 table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));
\r
277 table.setFont(new Font("Verdana", Font.PLAIN, 12));
\r
278 table.setDefaultRenderer(Color.class,
\r
279 new ColorRenderer());
\r
281 table.setDefaultEditor(Color.class,
\r
282 new ColorEditor());
\r
284 table.getColumnModel().getColumn(0).setPreferredWidth(200);
\r
286 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
\r
288 table.addMouseListener(new MouseAdapter()
\r
290 public void mousePressed(MouseEvent evt)
\r
292 selectedRow = table.rowAtPoint(evt.getPoint());
\r
296 table.addMouseMotionListener(new MouseMotionAdapter()
\r
298 public void mouseDragged(MouseEvent evt)
\r
300 int newRow = table.rowAtPoint(evt.getPoint());
\r
301 if(newRow!=selectedRow
\r
305 Object[] temp = new Object[3];
\r
306 temp[0] = table.getValueAt(selectedRow, 0);
\r
307 temp[1] = table.getValueAt(selectedRow, 1);
\r
308 temp[2] = table.getValueAt(selectedRow, 2);
\r
310 table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0);
\r
311 table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1);
\r
312 table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2);
\r
314 table.setValueAt(temp[0], newRow, 0);
\r
315 table.setValueAt(temp[1], newRow, 1);
\r
316 table.setValueAt(temp[2], newRow, 2);
\r
318 selectedRow = newRow;
\r
323 if (groupPanel != null)
\r
325 groupPanel.setLayout(
\r
326 new GridLayout(fr.featureGroups.size() / 4 + 1, 4));
\r
328 groupPanel.validate();
\r
329 bigPanel.add(groupPanel, BorderLayout.NORTH);
\r
332 updateFeatureRenderer(data);
\r
338 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(
\r
339 "LAST_DIRECTORY"), new String[] { "fc" },
\r
340 new String[] { "Sequence Feature Colours" }, "Sequence Feature Colours");
\r
341 chooser.setFileView(new jalview.io.JalviewFileView());
\r
342 chooser.setDialogTitle("Load Feature Colours");
\r
343 chooser.setToolTipText("Load");
\r
345 int value = chooser.showOpenDialog(this);
\r
347 if (value == JalviewFileChooser.APPROVE_OPTION)
\r
349 File file = chooser.getSelectedFile();
\r
353 InputStreamReader in = new InputStreamReader(new FileInputStream(
\r
356 jalview.binding.JalviewUserColours jucs = new jalview.binding.
\r
357 JalviewUserColours();
\r
358 jucs = (jalview.binding.JalviewUserColours) jucs.unmarshal(in);
\r
361 for (int i = 0; i < jucs.getColourCount(); i++)
\r
363 fr.setColour( jucs.getColour(i).getName(),
\r
364 new Color(Integer.parseInt( jucs.getColour(i).getRGB(), 16)));
\r
368 af.alignPanel.repaint();
\r
370 catch (Exception ex)
\r
372 System.out.println("Error loading User Colour File\n" + ex);
\r
379 JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(
\r
380 "LAST_DIRECTORY"), new String[] { "fc" },
\r
381 new String[] { "Sequence Feature Colours" }, "Sequence Feature Colours");
\r
382 chooser.setFileView(new jalview.io.JalviewFileView());
\r
383 chooser.setDialogTitle("Save Feature Colour Scheme");
\r
384 chooser.setToolTipText("Save");
\r
386 int value = chooser.showSaveDialog(this);
\r
388 if (value == JalviewFileChooser.APPROVE_OPTION)
\r
390 String choice = chooser.getSelectedFile().getPath();
\r
391 jalview.binding.JalviewUserColours ucs = new jalview.binding.JalviewUserColours();
\r
392 ucs.setSchemeName("Sequence Features");
\r
395 PrintWriter out = new PrintWriter(new OutputStreamWriter(
\r
396 new FileOutputStream(choice), "UTF-8"));
\r
398 Enumeration e = fr.featureColours.keys();
\r
399 while(e.hasMoreElements())
\r
401 jalview.binding.Colour col = new jalview.binding.Colour();
\r
402 col.setName(e.nextElement().toString());
\r
403 col.setRGB(jalview.util.Format.getHexString(
\r
404 fr.getColour(col.getName())));
\r
405 ucs.addColour(col);
\r
411 catch (Exception ex)
\r
413 ex.printStackTrace();
\r
418 public void invertSelection()
\r
420 for(int i=0; i<table.getRowCount(); i++)
\r
422 Boolean value = (Boolean)table.getValueAt(i,2);
\r
425 new Boolean(!value.booleanValue()),
\r
430 public void close()
\r
434 frame.setClosed(true);
\r
436 catch (Exception exe)
\r
441 public void updateFeatureRenderer(Object [][] data)
\r
443 fr.setFeaturePriority( data );
\r
444 af.alignPanel.repaint();
\r
446 if(af.alignPanel.overviewPanel!=null)
\r
447 af.alignPanel.overviewPanel.updateOverviewImage();
\r
450 int selectedRow =-1;
\r
451 JTabbedPane tabbedPane = new JTabbedPane();
\r
452 BorderLayout borderLayout1 = new BorderLayout();
\r
453 BorderLayout borderLayout2 = new BorderLayout();
\r
454 BorderLayout borderLayout3 = new BorderLayout();
\r
455 JPanel bigPanel = new JPanel();
\r
456 BorderLayout borderLayout4 = new BorderLayout();
\r
457 JButton invert = new JButton();
\r
458 JPanel buttonPanel = new JPanel();
\r
459 JButton cancel = new JButton();
\r
460 JButton ok = new JButton();
\r
461 JButton loadColours = new JButton();
\r
462 JButton saveColours = new JButton();
\r
463 JPanel dasButtonPanel = new JPanel();
\r
464 JButton fetchDAS = new JButton();
\r
465 JButton saveDAS = new JButton();
\r
466 private void jbInit()
\r
469 this.setLayout(borderLayout1);
\r
470 settingsPane.setLayout(borderLayout2);
\r
471 dasSettingsPane.setLayout(borderLayout3);
\r
472 bigPanel.setLayout(borderLayout4);
\r
473 invert.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
474 invert.setText("Invert Selection");
\r
475 invert.addActionListener(new ActionListener()
\r
477 public void actionPerformed(ActionEvent e)
\r
482 cancel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
483 cancel.setText("Cancel");
\r
484 cancel.addActionListener(new ActionListener()
\r
486 public void actionPerformed(ActionEvent e)
\r
488 updateFeatureRenderer(originalData);
\r
492 ok.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
494 ok.addActionListener(new ActionListener()
\r
496 public void actionPerformed(ActionEvent e)
\r
501 loadColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
502 loadColours.setText("Load Colours");
\r
503 loadColours.addActionListener(new ActionListener()
\r
505 public void actionPerformed(ActionEvent e)
\r
510 saveColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
\r
511 saveColours.setText("Save Colours");
\r
512 saveColours.addActionListener(new ActionListener()
\r
514 public void actionPerformed(ActionEvent e)
\r
519 transparency.addChangeListener(new ChangeListener()
\r
521 public void stateChanged(ChangeEvent evt)
\r
523 fr.setTransparency( (float) (100 - transparency.getValue()) / 100f);
\r
524 af.alignPanel.repaint();
\r
529 transparency.setMaximum(70);
\r
530 fetchDAS.setText("Fetch DAS Features");
\r
531 fetchDAS.addActionListener(new ActionListener()
\r
533 public void actionPerformed(ActionEvent e)
\r
535 fetchDAS_actionPerformed(e);
\r
538 saveDAS.setText("Save as default");
\r
539 saveDAS.addActionListener(new ActionListener()
\r
541 public void actionPerformed(ActionEvent e)
\r
543 saveDAS_actionPerformed(e);
\r
546 dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
\r
547 dasSettingsPane.setBorder(null);
\r
548 this.add(tabbedPane, java.awt.BorderLayout.CENTER);
\r
549 tabbedPane.addTab("Display Settings", settingsPane );
\r
550 tabbedPane.addTab("DAS Settings", dasSettingsPane);
\r
551 bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
\r
552 transPanel.add(transparency);
\r
553 transPanel.add(invert);
\r
554 buttonPanel.add(ok);
\r
555 buttonPanel.add(cancel);
\r
556 buttonPanel.add(loadColours);
\r
557 buttonPanel.add(saveColours);
\r
558 bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
\r
559 dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
\r
560 dasButtonPanel.add(fetchDAS);
\r
561 dasButtonPanel.add(saveDAS);
\r
562 settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);
\r
563 settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
\r
566 public void fetchDAS_actionPerformed(ActionEvent e)
\r
568 Vector selectedSources = dassourceBrowser.getSelectedSources();
\r
570 SequenceI [] dataset, seqs ;
\r
573 if(af.getViewport().getSelectionGroup()!=null
\r
574 && af.getViewport().getSelectionGroup().getSize(false)>0)
\r
576 iSize = af.getViewport().getSelectionGroup().getSize(false);
\r
577 dataset = new SequenceI[iSize];
\r
578 seqs = af.getViewport().getSelectionGroup().
\r
579 getSequencesInOrder(
\r
580 af.getViewport().getAlignment());
\r
584 iSize = af.getViewport().getAlignment().getHeight();
\r
585 seqs = af.getViewport().getAlignment().getSequencesArray();
\r
588 dataset = new SequenceI[iSize];
\r
589 for (int i = 0; i < iSize; i++)
\r
591 dataset[i] = seqs[i].getDatasetSequence();
\r
594 new jalview.io.DasSequenceFeatureFetcher(
\r
599 af.getViewport().setShowSequenceFeatures(true);
\r
600 af.showSeqFeatures.setSelected(true);
\r
603 public void saveDAS_actionPerformed(ActionEvent e)
\r
605 dassourceBrowser.saveProperties(jalview.bin.Cache.applicationProperties);
\r
608 /////////////////////////////////////////////////////////////////////////
\r
609 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
\r
610 /////////////////////////////////////////////////////////////////////////
\r
611 class FeatureTableModel
\r
612 extends AbstractTableModel
\r
614 FeatureTableModel(Object[][] data)
\r
619 private String[] columnNames = {"Feature Type", "Colour","Display"};
\r
620 private Object[][] data;
\r
622 public Object[][] getData()
\r
627 public void setData(Object[][] data)
\r
632 public int getColumnCount() {
\r
633 return columnNames.length;
\r
636 public Object[] getRow(int row)
\r
641 public int getRowCount() {
\r
642 return data.length;
\r
645 public String getColumnName(int col) {
\r
646 return columnNames[col];
\r
649 public Object getValueAt(int row, int col) {
\r
650 return data[row][col];
\r
653 public Class getColumnClass(int c) {
\r
654 return getValueAt(0, c).getClass();
\r
657 public boolean isCellEditable(int row, int col) {
\r
658 return col==0 ? false:true;
\r
661 public void setValueAt(Object value, int row, int col) {
\r
662 data[row][col] = value;
\r
663 fireTableCellUpdated(row, col);
\r
664 updateFeatureRenderer(data);
\r
668 class ColorRenderer extends JLabel
\r
669 implements TableCellRenderer {
\r
670 javax.swing.border.Border unselectedBorder = null;
\r
671 javax.swing.border.Border selectedBorder = null;
\r
673 public ColorRenderer() {
\r
674 setOpaque(true); //MUST do this for background to show up.
\r
677 public Component getTableCellRendererComponent(
\r
678 JTable table, Object color,
\r
679 boolean isSelected, boolean hasFocus,
\r
680 int row, int column) {
\r
681 Color newColor = (Color)color;
\r
682 setBackground(newColor);
\r
684 if (selectedBorder == null) {
\r
685 selectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
\r
686 table.getSelectionBackground());
\r
688 setBorder(selectedBorder);
\r
690 if (unselectedBorder == null) {
\r
691 unselectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
\r
692 table.getBackground());
\r
694 setBorder(unselectedBorder);
\r
697 setToolTipText("RGB value: " + newColor.getRed() + ", "
\r
698 + newColor.getGreen() + ", "
\r
699 + newColor.getBlue());
\r
705 class ColorEditor extends AbstractCellEditor
\r
706 implements TableCellEditor,
\r
708 Color currentColor;
\r
710 JColorChooser colorChooser;
\r
712 protected static final String EDIT = "edit";
\r
714 public ColorEditor() {
\r
715 //Set up the editor (from the table's point of view),
\r
716 //which is a button.
\r
717 //This button brings up the color chooser dialog,
\r
718 //which is the editor from the user's point of view.
\r
719 button = new JButton();
\r
720 button.setActionCommand(EDIT);
\r
721 button.addActionListener(this);
\r
722 button.setBorderPainted(false);
\r
723 //Set up the dialog that the button brings up.
\r
724 colorChooser = new JColorChooser();
\r
725 dialog = JColorChooser.createDialog(button,
\r
726 "Select new Colour",
\r
729 this, //OK button handler
\r
730 null); //no CANCEL button handler
\r
734 * Handles events from the editor button and from
\r
735 * the dialog's OK button.
\r
737 public void actionPerformed(ActionEvent e) {
\r
739 if (EDIT.equals(e.getActionCommand())) {
\r
740 //The user has clicked the cell, so
\r
741 //bring up the dialog.
\r
742 button.setBackground(currentColor);
\r
743 colorChooser.setColor(currentColor);
\r
744 dialog.setVisible(true);
\r
746 //Make the renderer reappear.
\r
747 fireEditingStopped();
\r
749 } else { //User pressed dialog's "OK" button.
\r
750 currentColor = colorChooser.getColor();
\r
754 //Implement the one CellEditor method that AbstractCellEditor doesn't.
\r
755 public Object getCellEditorValue() {
\r
756 return currentColor;
\r
759 //Implement the one method defined by TableCellEditor.
\r
760 public Component getTableCellEditorComponent(JTable table,
\r
762 boolean isSelected,
\r
765 currentColor = (Color)value;
\r